From c0acc8b15d1b90e8ed1f345e275e7c278b24dc8c Mon Sep 17 00:00:00 2001 From: Matt Fleming Date: Apr 16 2020 13:29:59 +0000 Subject: Merge branch 'SLE12-SP5' into SLE12-SP5-RT - Refresh -rt patches: patches.rt/0243-md-raid5-Make-raid5_percpu-handling-RT-aware.patch patches.rt/efi-Disable-runtime-services-on-RT.patch patches.rt/pci-switchtec-Don-t-use-completion-s-wait-queue.patch - Update config files. --- diff --git a/blacklist.conf b/blacklist.conf index 7f831ac..0a07a55 100644 --- a/blacklist.conf +++ b/blacklist.conf @@ -514,7 +514,6 @@ b60706644282af04e4aa57da5af57470d453cd1f # vsprintf: cosmetic 741a76b350897604c48fb12beff1c9b77724dc96 # kthread: fixes rather rare races in CPU hotplug; there are several followup fixes on top of it to get it actually right; does not worth the risk 4950276672fce5c241857540f8561c440663673d # kmemcheck removal; not for released products d8be75663cec0069b85f80191abd2682ce4a512f # related to kmemcheck removal; not for released products -1f2cac107c591c24b60b115d6050adc213d10fc0 # blktrace: racy init/start-stop/teardown for ages; not worth it a6da0024ffc19e0d47712bb5ca4fd083f76b07df # blktrace: fix unlocked registration of tracepoints; racy for ages; found by syzcaller; not worth it 6b7e633fe9c24682df550e5311f47fb524701586 # ring_buffer: just an optimization 23721a755f98ac846897a013c92cccb281c1bcc8 # trace/xdp: compilation warning; we do not have the affected code @@ -643,7 +642,6 @@ df5d45aa08f848b79caf395211b222790534ccc7 # compiler-gcc.h: inapplicable 6066998cbd2b1012a8d5bc9a2957cfd0ad53150e # cpufreq: not supported on SLE 70f6bf2a3b7e40c3f802b0ea837762a8bc6c1430 # cpufreq: not supported on SLE 0373ca74831b0f93cd4cdbf7ad3aec3c33a479a5 # cpufreq: not supported on SLE -887207ed9e5812ed9239b6d07185a2d35dda91db # crypto: inapplicable b24b6478e65f140610ab1ffaadc7bc6bf0be8aad # cpufreq: not supported on SLE 1eb7b40386c97f6c4d1c62931bf306f4535a4bd6 # crypto: inapplicable 0a02dcca126280595950f3ea809f77c9cb0a235c # crypto: inapplicable @@ -833,13 +831,11 @@ ac7c2bb59870b8fd41c09502e73e72fcb63b85c3 # ipv6: nf_defrag: reverting 0b508bc926bdced678febee2a2b8cdba0a19e481 # Fixes a build issue only 24ecc3585348b616993a3c4d6dc2c6b8007e358c # Requires blkcg changes from 4.19 b57e99b4b8b0ebdf9707424e7ddc0c392bdc5fe6 # Requires block-layer changes from 4.19 -ad608fbcf166fec809e402d548761768f602702c # media: v4l: breaks kABI bbb68468641547d56c83012670bcaf77f3dacd64 # Duplicate of 24868367cdcac447232ebcb2aa06e1bf91291586 edb39592a5877bd91b2e6ee15194268f35b04892 # Duplicate of 7eb709f29593aced51901cb53565477762800722 0d4876f4e977798238db594321db9184704fcf5d # rtl8188eu: reverted in below c7346797f5fb7be8e139fbeb1324669e7cb2ef9a # rtl8188eu: reverting a54e43f993f8ec2f063b616a0e4d2b09e08d78a5 # Duplicate of 014562071c96 -92539d3eda2c090b382699bbb896d4b54e9bdece # media: v4l: fixes the above commit d52888aa2753e3063a9d3a0c9f72f94aa9809c15 # we don't support CONFIG_X86_5LEVEL 2c1f4f125159f10521944cea23e33a00fcf85ede # cleanup c2bc66082e1048c7573d72e62f597bdc5ce13fea # we're not removing lockless_dereference() @@ -1013,7 +1009,6 @@ b14c06ec024947eaa35212f2380e90233d5092e0 # drm/i915: already cherry-picked d4df171418262d2e0291dcff14e40bcebe73af3c # drm/msm: already cherry-picked a3c5e2cd79753121f49a8662c1e0a60ddb5486ca # drm/msm: A6XX isn't supported yet d179b88deb3bf6fed4991a31fd6f0f2cad21fab5 # drm/i915: causes a regression, leading to a black screen (bsc#1129027) -d179b88deb3bf6fed4991a31fd6f0f2cad21fab5 # drm/i915: causes a regression, leading to a black screen (bsc#1129027) 25dc194b34dd5919dd07b8873ee338182e15df9d # drm: already cherry-picked 02917e9f8676207a4c577d4d94eae12bf348e9d7 # EXPORT_SYMBOL_GPL change a3238924a820c1d7c977b632b769f3b5690cba09 # file not present: arch/arm/boot/dts/exynos5422-odroid-core.dtsi (git-fixes) @@ -1268,7 +1263,6 @@ f9927000cb35f250051f0f1878db12ee2626eea1 # ASoC: sun4i: not applicable 83ee240aad9147ed5dac5a7c7b4c559d134072e7 # ASoC: cx2072x: superfluous fd14f4436fd47d5418023c90e933e66d3645552e # ASoC: davinci: not applicable 12209993e98c5fa1855c467f22a24e3d5b8be205 # kABI breaks -1b7aebf0487613033aff26420e32fa2076d52846 # warning fix af31b04b67f4fd7f639fd465a507c154c46fc9fb # NV-DIMM unit test code only 6ae865615fc43d014da2fd1f1bba7e81ee622d1b # UBSAN bug which we don't use 81c7ed296dcd02bc0b4488246d040e03e633737a # We don't support CONFIG_X86_5LEVEL @@ -1276,7 +1270,6 @@ c1887159eb48ba40e775584cfb2a443962cf1a05 # Clang fix 684fb246578b9e81fc7b4ca5c71eae22edb650b2 # clang fix 5564597d51c8ff5b88d95c76255e18b13b760879 # no support for powermacs fe60522ec60082a1dd735691b82c64f65d4ad15e # not needed (bsc#1088804) -73aca179d78eaa11604ba0783a6d8b2125fbc332 # do not want to alter vermagic on released product 8adddf349fda0d3de2f6bb41ddf838cbf36a8ad2 # config-only fix 3e3ebed3fef4878e6f1680ff98088db1a9688831 # config-only fix d065ee93aab6ef4c2a5af5c455b5044bd5136547 # config-only fix @@ -1304,7 +1297,6 @@ d8f945bf8096375f458683b5718722a2d5dda2f0 # context missing eebcc19646489b68399ce7b35d9c38eb9f4ec40f # context missing f9dfed1c785734b95b08d67600e05d2092508ab0 # context missing 8beb90aaf334a6efa3e924339926b5f93a234dbb # breaks kabi on fip_mode -6a162836997c10bbefb7c7ca772201cc45c0e4a6 # cosmetic change eb085574a7526c4375965c5fbf7e5b0c19cdd336 # too risky, bsc#1148540 aeb309b81c6bada783c3695528a3e10748e97285 # too risky, bsc#1148540 bfba8e5cf28f413aa05571af493871d74438979f # not applicable, bsc#1149207 @@ -1439,7 +1431,6 @@ dc39c1d68f256990d4bb0033a219e8ca15ba4d7f # ppc sstep emu 71eb40fc53371bc247c8066ae76ad9e22ae1e18d # booke not supported afb89cd5f2ba2d5d04b85b2692a9a3d86b6fabd7 # drm/i915: stable fix, already applied 573e1fe003c1e2016bc40cc4f2b231e3b8c990f8 # drm/i915: stable fix, already applied -2d691aeca4aecbb8d0414a777a46981a8e142b05 # drm/i915: known to break things 0f0727d971f6fdf8f1077180d495ddb9928f0c8b # drm/amd: only for clang builds 71e5e886806ee3f8e0c44ed945eb2e4d6659c6e3 # wireless: only relevant for built-in kenrel 1e390478cfb527e34c9ab89ba57212cb05c33c51 # gpu/host1x: breaks kABI @@ -1465,3 +1456,30 @@ fd933c00ebe220060e66fb136a7050a242456566 # Documentation only 39323c64b8a95d10ddc66dc815dd14efdddf6777 # Documentation only 84029fd04c201a4c7e0b07ba262664900f47c6f5 # changes limit semantics, fixes noncritical case, see bsc#1164094 6df19872d881641e6394f93ef2938cffcbdae5bb # arm 32bit only +b8d17e7d93d2beb89e4f34c59996376b8b544792 # not applicable, upstream error +cf0ee7c60c89641f6e4d1d3c7867fe32b9e30300 # kABI +4f510aa10468954b1da4e94689c38ac6ea8d3627 # patched code does not exist: phy/rockchip: inno-hdmi: round clock rate down to closest 1000 Hz +0d4bbe3d407f79438dc4f87943db21f7134cfc65 # Duplicate of 2d691aeca4aecbb8d0414a777a46981a8e142b05: drm/i915/userptr: Try to acquire the page lock around set_page_dirty() +a542ad9e5de132cbb3e75b89008d44327a0d44d7 # Duplicate of 62d91dd2851e8ae2ca552f1b090a3575a4edf759: drm/radeon: fix bad DMA from INTERRUPT_CNTL2 +b992691d453c1cb16390d21c9f557196d3ab3141 # Duplicate of 3d0e3ce52ce3eb4b9de3caf9c38dbb5a4d3e13c3: drm/amdgpu: fix bad DMA from INTERRUPT_CNTL2 +ba16a48af797db124ac100417f9229b1650ce1fb # Duplicate of f0f3a6cecf3b98990985cd42f7bf5a0313894822: drm/i915: Fix pid leak with banned clients +775d78319f1ceb32be8eb3b1202ccdc60e9cb7f1 # breaks KABI +a1bd079fca6219e18bb0892f0a7228a76dd6292c # in fact fixes a864e29d94abac7f9756e07180c167f50fb00042 +8fc7036ee652207ca992fbb9abb64090c355a9e0 # in fact fixes 7f0bf1c09f3c8763a9807f66dcf4c7adad0ce7ff +1b710b1b10eff9d46666064ea25f079f70bc67a8 # DEBUG_RANDOM_BOOT is 0 +ca4b43c14cd88d28cfc6467d2fa075aad6818f1d # kABI +13380a1471aadc517994b7230371a227d1f9f152 # kABI, cosmetic patch +708e0ada1916be765b7faa58854062f2bc620bbf # not needed, we don't have info->name in load_info struct +2d691aeca4aecbb8d0414a777a46981a8e142b05 # drm/i915: known to break things (bsc#1145051) +fa882fc80dc8bf6ed24c0a85e73c17d62d2b1754 # platform/x86: already applied +fd4d9c7d0c71866ec0c2825189ebd2ce35bd95b8 # we use SLAB not SLUB in this kernel +5076190daded2197f62fe92cf69674488be44175 # we use SLAB not SLUB in this kernel +c657b936ea98630ef5ba4f130ab1ad5c534d0165 # AMD Raven Ridge not supported: drm/amdgpu/soc15: fix xclk for raven +870b4333a62e45b0b2000d14b301b7b8b8cad9da # we do not build x86 with CONFIG_EFI=n +3ff9c075cc767b3060bdac12da72fc94dd7da1b8 # not worth fixing a fuzzing bug which needs root to cause KABI breakage +a1fdbfbb1da2063ba98a12eb6f1bdd07451c7145 # requires an impossible kABI change +b34087157dd76e8d96e5e52808134a791ac61e57 # DIRECT_MAPPING_ERROR does not exist in this code-base +a9ae8731e6e52829a935d81a65d7f925cb95dbac # Not applicable: drm/amdgpu: Call find_vma under mmap_sem +1208f9e1d758c991b0a46a1bd60c616b906bbe27 # only for unsupported hardware +57d7713196ccd83010fcaa82b9f02d740c9e6bb2 # docu change for an unsupported feature +5439fa9263cb293e41168bc03711ec18c4f11cba # uncompiled SOC driver diff --git a/config/x86_64/rt b/config/x86_64/rt index be7d4bf..f2940e5 100644 --- a/config/x86_64/rt +++ b/config/x86_64/rt @@ -6616,6 +6616,7 @@ CONFIG_EFI_BOOTLOADER_CONTROL=m CONFIG_EFI_CAPSULE_LOADER=m # CONFIG_EFI_TEST is not set CONFIG_APPLE_PROPERTIES=y +CONFIG_EFI_RCI2_TABLE=y CONFIG_EFI_SECRET_KEY=y CONFIG_UEFI_CPER=y CONFIG_EFI_DEV_PATH_PARSER=y @@ -7525,6 +7526,7 @@ CONFIG_BINARY_PRINTF=y # Library routines # CONFIG_RAID6_PQ=m +CONFIG_RAID6_PQ_BENCHMARK=y CONFIG_BITREVERSE=y # CONFIG_HAVE_ARCH_BITREVERSE is not set CONFIG_RATIONAL=y diff --git a/config/x86_64/rt_debug b/config/x86_64/rt_debug index 6f75137..aeb1768 100644 --- a/config/x86_64/rt_debug +++ b/config/x86_64/rt_debug @@ -1,6 +1,6 @@ # # Automatically generated file; DO NOT EDIT. -# Linux/x86_64 4.12.14 Kernel Configuration +# Linux/x86 4.12.14 Kernel Configuration # CONFIG_64BIT=y CONFIG_X86_64=y @@ -6633,6 +6633,7 @@ CONFIG_EFI_BOOTLOADER_CONTROL=m CONFIG_EFI_CAPSULE_LOADER=m # CONFIG_EFI_TEST is not set CONFIG_APPLE_PROPERTIES=y +CONFIG_EFI_RCI2_TABLE=y CONFIG_EFI_SECRET_KEY=y CONFIG_UEFI_CPER=y CONFIG_EFI_DEV_PATH_PARSER=y @@ -7543,6 +7544,7 @@ CONFIG_BINARY_PRINTF=y # Library routines # CONFIG_RAID6_PQ=m +CONFIG_RAID6_PQ_BENCHMARK=y CONFIG_BITREVERSE=y # CONFIG_HAVE_ARCH_BITREVERSE is not set CONFIG_RATIONAL=y diff --git a/patches.kabi/debugfs-kabi-restore-debugfs_remove_recursive.patch b/patches.kabi/debugfs-kabi-restore-debugfs_remove_recursive.patch new file mode 100644 index 0000000..7ca8b9f --- /dev/null +++ b/patches.kabi/debugfs-kabi-restore-debugfs_remove_recursive.patch @@ -0,0 +1,48 @@ +From: Nicolai Stange +Patch-mainline: Never, kABI +Subject: kABI: restore debugfs_remove_recursive() +References: bsc#1159198 + +Upstream commit a3d1e7eb5abe ("simple_recursive_removal(): kernel-side +rm -rf for ramfs-style filesystems"), imported as +patches.suse/simple_recursive_removal-kernel-side-rm-rf-for-ramfs.patch, +removed the definition of debugfs_remove_recursive() and made it a #define +to debugfs_remove() instead. However, debugfs_remove_recursive() had been +EXPORTed and thus, needs to be retained in order to not break kABI. +Drop the debugfs_remove_recursive() #define again and implement +debugfs_remove_recursive() as a forwarding wrapper around debugfs_remove(). + +Signed-off-by: Nicolai Stange + +--- + fs/debugfs/inode.c | 7 +++++++ + include/linux/debugfs.h | 2 +- + 2 files changed, 8 insertions(+), 1 deletion(-) + +--- a/fs/debugfs/inode.c ++++ b/fs/debugfs/inode.c +@@ -727,6 +727,13 @@ void debugfs_remove(struct dentry *dentr + } + EXPORT_SYMBOL_GPL(debugfs_remove); + ++/* kABI compatibility wrapper */ ++void debugfs_remove_recursive(struct dentry *dentry) ++{ ++ debugfs_remove(dentry); ++} ++EXPORT_SYMBOL_GPL(debugfs_remove_recursive); ++ + /** + * debugfs_rename - rename a file/directory in the debugfs filesystem + * @old_dir: a pointer to the parent dentry for the renamed object. This +--- a/include/linux/debugfs.h ++++ b/include/linux/debugfs.h +@@ -85,7 +85,7 @@ struct dentry *debugfs_create_automount( + void *data); + + void debugfs_remove(struct dentry *dentry); +-#define debugfs_remove_recursive debugfs_remove ++void debugfs_remove_recursive(struct dentry *dentry); + + const struct file_operations *debugfs_real_fops(const struct file *filp); + diff --git a/patches.kabi/kabi-nvme-multipath-fix-iopolicy.patch b/patches.kabi/kabi-nvme-multipath-fix-iopolicy.patch new file mode 100644 index 0000000..c904d69 --- /dev/null +++ b/patches.kabi/kabi-nvme-multipath-fix-iopolicy.patch @@ -0,0 +1,46 @@ +From: Daniel Wagner +Date: Thu, 02 Apr 2020 09:41:09 +0200 +Subject: [PATCH] kabi: nvme: Add NVME_IOPOLICY_UNKNOWN back +Patch-mainline: Never, kABI workaround +References: bsc#1158983 + +The initial version of the nvme-multipath-round-robin-I-O-policy.patch +defined NVME_IOPOLICY_UNKNOWN, which was removed for the mainline +version. Add the definition back to avoid changes in struct +nvme_subsystem. + +Signed-off-by: Daniel Wagner +--- + drivers/nvme/host/multipath.c | 3 ++- + drivers/nvme/host/nvme.h | 1 + + 2 files changed, 3 insertions(+), 1 deletion(-) + +--- a/drivers/nvme/host/multipath.c ++++ b/drivers/nvme/host/multipath.c +@@ -545,6 +545,7 @@ void nvme_mpath_stop(struct nvme_ctrl *c + __ATTR(_name, _mode, _show, _store) + + static const char *nvme_iopolicy_names[] = { ++ [NVME_IOPOLICY_UNKNOWN] = "unknown", + [NVME_IOPOLICY_NUMA] = "numa", + [NVME_IOPOLICY_RR] = "round-robin", + }; +@@ -566,7 +567,7 @@ static ssize_t nvme_subsys_iopolicy_stor + container_of(dev, struct nvme_subsystem, dev); + int i; + +- for (i = 0; i < ARRAY_SIZE(nvme_iopolicy_names); i++) { ++ for (i = 1; i < ARRAY_SIZE(nvme_iopolicy_names); i++) { + if (sysfs_streq(buf, nvme_iopolicy_names[i])) { + WRITE_ONCE(subsys->iopolicy, i); + return count; +--- a/drivers/nvme/host/nvme.h ++++ b/drivers/nvme/host/nvme.h +@@ -250,6 +250,7 @@ struct nvme_ctrl { + }; + + enum nvme_iopolicy { ++ NVME_IOPOLICY_UNKNOWN, + NVME_IOPOLICY_NUMA, + NVME_IOPOLICY_RR, + }; diff --git a/patches.kabi/md-backport-kabi.patch b/patches.kabi/md-backport-kabi.patch new file mode 100644 index 0000000..686fd00 --- /dev/null +++ b/patches.kabi/md-backport-kabi.patch @@ -0,0 +1,110 @@ +From: NeilBrown +Subject: Fix kabi after "md: batch flush requests." +Patch-mainline: Never, kabi +References: bsc#1119680 + +The new fields are private to md, so they can be hidden from the kabi. + +Acked-by: NeilBrown +Signed-off-by: Neil Brown +Acked-by: Coly Li +--- + drivers/md/md-cluster.h | 7 +++++-- + drivers/md/md.h | 40 ++++++++++++++++++++++++++-------------- + 2 files changed, 31 insertions(+), 16 deletions(-) + +--- a/drivers/md/md-cluster.h ++++ b/drivers/md/md-cluster.h +@@ -13,7 +13,6 @@ struct md_cluster_operations { + int (*leave)(struct mddev *mddev); + int (*slot_number)(struct mddev *mddev); + int (*resync_info_update)(struct mddev *mddev, sector_t lo, sector_t hi); +- void (*resync_info_get)(struct mddev *mddev, sector_t *lo, sector_t *hi); + int (*metadata_update_start)(struct mddev *mddev); + int (*metadata_update_finish)(struct mddev *mddev); + void (*metadata_update_cancel)(struct mddev *mddev); +@@ -26,10 +25,14 @@ struct md_cluster_operations { + int (*remove_disk)(struct mddev *mddev, struct md_rdev *rdev); + void (*load_bitmaps)(struct mddev *mddev, int total_slots); + int (*gather_bitmaps)(struct md_rdev *rdev); +- int (*resize_bitmaps)(struct mddev *mddev, sector_t newsize, sector_t oldsize); + int (*lock_all_bitmaps)(struct mddev *mddev); + void (*unlock_all_bitmaps)(struct mddev *mddev); + void (*update_size)(struct mddev *mddev, sector_t old_dev_sectors); ++ ++#ifndef __GENKSYMS__ ++ void (*resync_info_get)(struct mddev *mddev, sector_t *lo, sector_t *hi); ++ int (*resize_bitmaps)(struct mddev *mddev, sector_t newsize, sector_t oldsize); ++#endif + }; + + #endif /* _MD_CLUSTER_H */ +--- a/drivers/md/md.h ++++ b/drivers/md/md.h +@@ -118,13 +118,6 @@ struct md_rdev { + * in superblock. + */ + +- /* +- * The members for check collision of write IOs. +- */ +- struct list_head serial_list; +- spinlock_t serial_list_lock; +- wait_queue_head_t serial_io_wait; +- + struct work_struct del_work; /* used for delayed sysfs removal */ + + struct kernfs_node *sysfs_state; /* handle for 'state' +@@ -138,6 +131,15 @@ struct md_rdev { + unsigned int size; /* Size in sectors of the PPL space */ + sector_t sector; /* First sector of the PPL space */ + } ppl; ++ ++#ifndef __GENKSYMS__ ++ /* ++ * The members for check collision of write IOs. ++ */ ++ struct list_head serial_list; ++ spinlock_t serial_list_lock; ++ wait_queue_head_t serial_io_wait; ++#endif + }; + enum flag_bits { + Faulty, /* device is known to have a fault */ +@@ -486,13 +488,16 @@ struct mddev { + */ + struct work_struct flush_work; + struct work_struct event_work; /* used by dm to report failure event */ +- mempool_t *serial_info_pool; + void (*sync_super)(struct mddev *mddev, struct md_rdev *rdev); + struct md_cluster_info *cluster_info; + unsigned int good_device_nr; /* good device num within cluster raid */ + + bool has_superblocks:1; ++ ++#ifndef __GENKSYMS__ ++ mempool_t *serial_info_pool; + bool fail_last_dev:1; ++#endif + }; + + enum recovery_flags { +@@ -584,7 +593,6 @@ struct md_personality + int (*check_reshape) (struct mddev *mddev); + int (*start_reshape) (struct mddev *mddev); + void (*finish_reshape) (struct mddev *mddev); +- void (*update_reshape_pos) (struct mddev *mddev); + /* quiesce suspends or resumes internal processing. + * 1 - stop new actions and wait for action io to complete + * 0 - return to normal behaviour +@@ -605,6 +613,10 @@ struct md_personality + int (*congested)(struct mddev *mddev, int bits); + /* Changes the consistency policy of an active array. */ + int (*change_consistency_policy)(struct mddev *mddev, const char *buf); ++ ++#ifndef __GENKSYMS__ ++ void (*update_reshape_pos) (struct mddev *mddev); ++#endif + }; + + struct md_sysfs_entry { diff --git a/patches.kabi/pcie_port_bus_type-kabi-compat.patch b/patches.kabi/pcie_port_bus_type-kabi-compat.patch new file mode 100644 index 0000000..6e93254 --- /dev/null +++ b/patches.kabi/pcie_port_bus_type-kabi-compat.patch @@ -0,0 +1,70 @@ +From: Takashi Iwai +Subject: kABI workaround for pcie_port_bus_type change +Patch-mainline: Never, kABI workaround +References: bsc#1161561 + +patches.suse/PCI-portdrv-Remove-pcie_port_bus_type-link-order-dep.patch +moved pcie_port_bus_type definition into pci-driver.c, and this broke +kABI. Take it back to generate the compatible kABI again. + +Signed-off-by: Takashi Iwai + +--- + drivers/pci/pci-driver.c | 8 +------- + drivers/pci/pcie/Makefile | 2 +- + drivers/pci/pcie/portdrv_bus.c | 15 +++++++++++++++ + 3 files changed, 17 insertions(+), 8 deletions(-) + +--- a/drivers/pci/pci-driver.c ++++ b/drivers/pci/pci-driver.c +@@ -1639,7 +1639,7 @@ struct bus_type pci_bus_type = { + EXPORT_SYMBOL(pci_bus_type); + + #ifdef CONFIG_PCIEPORTBUS +-static int pcie_port_bus_match(struct device *dev, struct device_driver *drv) ++int pcie_port_bus_match(struct device *dev, struct device_driver *drv) + { + struct pcie_device *pciedev; + struct pcie_port_service_driver *driver; +@@ -1659,12 +1659,6 @@ static int pcie_port_bus_match(struct de + + return 1; + } +- +-struct bus_type pcie_port_bus_type = { +- .name = "pci_express", +- .match = pcie_port_bus_match, +-}; +-EXPORT_SYMBOL_GPL(pcie_port_bus_type); + #endif + + static int __init pci_driver_init(void) +--- a/drivers/pci/pcie/Makefile ++++ b/drivers/pci/pcie/Makefile +@@ -5,7 +5,7 @@ + # Build PCI Express ASPM if needed + obj-$(CONFIG_PCIEASPM) += aspm.o + +-pcieportdrv-y := portdrv_core.o portdrv_pci.o err.o ++pcieportdrv-y := portdrv_core.o portdrv_pci.o err.o portdrv_bus.o + + obj-$(CONFIG_PCIEPORTBUS) += pcieportdrv.o + +--- /dev/null ++++ b/drivers/pci/pcie/portdrv_bus.c +@@ -0,0 +1,15 @@ ++#include ++#include ++#include ++#include ++#include ++ ++#include "portdrv.h" ++ ++extern int pcie_port_bus_match(struct device *dev, struct device_driver *drv); ++ ++struct bus_type pcie_port_bus_type = { ++ .name = "pci_express", ++ .match = pcie_port_bus_match, ++}; ++EXPORT_SYMBOL_GPL(pcie_port_bus_type); diff --git a/patches.kabi/qla2xxx-kABI-fixes-for-v10.01.00.18-k.patch b/patches.kabi/qla2xxx-kABI-fixes-for-v10.01.00.18-k.patch index 003839e..9168026 100644 --- a/patches.kabi/qla2xxx-kABI-fixes-for-v10.01.00.18-k.patch +++ b/patches.kabi/qla2xxx-kABI-fixes-for-v10.01.00.18-k.patch @@ -23,135 +23,3 @@ Signed-off-by: Daniel Wagner /* *************************** Data Structures/Defines ****************** */ ---- a/drivers/scsi/qla2xxx/qla_def.h -+++ b/drivers/scsi/qla2xxx/qla_def.h -@@ -591,12 +591,9 @@ typedef struct srb { - */ - uint8_t cmd_type; - uint8_t pad[3]; -- struct kref cmd_kref; /* need to migrate ref_count over to this */ -- void *priv; - wait_queue_head_t nvme_ls_waitq; - struct fc_port *fcport; - struct scsi_qla_host *vha; -- unsigned int start_timer:1; - unsigned int abort:1; - unsigned int aborted:1; - unsigned int completed:1; -@@ -548,7 +545,11 @@ typedef struct srb { - u32 gen2; /* scratch */ - int rc; - int retry_count; -+#ifdef __GENKSYMS__ -+ struct completion comp; -+#else - struct completion *comp; -+#endif - union { - struct srb_iocb iocb_cmd; - struct bsg_job *bsg_job; -@@ -556,7 +557,12 @@ typedef struct srb { - * Call nvme_private->fd->done() and free @sp. Only used by the NVMe - * code. - */ -+#ifndef __GENKSYMS__ -+ struct kref cmd_kref; /* need to migrate ref_count over to this */ -+ void *priv; -+ unsigned int start_timer:1; - void (*put_fn)(struct kref *kref); -+#endif - } srb_t; - - #define GET_CMD_SP(sp) (sp->u.scmd.cmd) -@@ -2267,10 +2273,14 @@ typedef enum { - FCT_BROADCAST, - FCT_INITIATOR, - FCT_TARGET, -+#ifdef __GENKSYMS__ -+ FCT_NVME -+#else - FCT_NVME_INITIATOR = 0x10, - FCT_NVME_TARGET = 0x20, - FCT_NVME_DISCOVERY = 0x40, - FCT_NVME = 0xf0, -+#endif - } fc_port_type_t; - - enum qla_sess_deletion { -@@ -2398,6 +2398,9 @@ typedef struct fc_port { - unsigned int explicit_logout:1; - unsigned int prli_pend_timer:1; - -+#ifdef __GENKSYMS__ -+ struct work_struct nvme_del_work; -+#endif - struct completion nvme_del_done; - uint32_t nvme_prli_service_param; - #define NVME_PRLI_SP_CONF BIT_7 -@@ -4411,6 +4424,9 @@ typedef struct scsi_qla_host { - - struct nvme_fc_local_port *nvme_local_port; - struct completion nvme_del_done; -+#ifdef __GENKSYMS__ -+ struct list_head nvme_rport_list; -+#endif - - uint16_t fcoe_vlan_id; - uint16_t fcoe_fcf_idx; ---- a/drivers/scsi/qla2xxx/qla_nvme.h -+++ b/drivers/scsi/qla2xxx/qla_nvme.h -@@ -33,10 +33,15 @@ struct nvme_private { - struct work_struct ls_work; - struct work_struct abort_work; - int comp_status; -+#ifndef __GENKSYMS__ - spinlock_t cmd_lock; -+#endif - }; - - struct qla_nvme_rport { -+#ifdef __GENKSYMS__ -+ struct list_head list; -+#endif - struct fc_port *fcport; - }; - ---- a/drivers/scsi/qla2xxx/qla_target.h -+++ b/drivers/scsi/qla2xxx/qla_target.h -@@ -889,14 +889,12 @@ struct qla_tgt_cmd { - unsigned int term_exchg:1; - unsigned int cmd_sent_to_fw:1; - unsigned int cmd_in_wq:1; -- -- /* -- * This variable may be set from outside the LIO and I/O completion -- * callback functions. Do not declare this member variable as a -- * bitfield to avoid a read-modify-write operation when this variable -- * is set. -- */ -- unsigned int aborted; -+#ifdef __GENKSYMS__ -+ unsigned int aborted:1; -+ unsigned int data_work:1; -+ unsigned int data_work_free:1; -+ unsigned int released:1; -+#endif - - struct scatterlist *sg; /* cmd data buffer SG vector */ - int sg_cnt; /* SG segments count */ -@@ -939,6 +937,15 @@ struct qla_tgt_cmd { - uint64_t jiffies_at_free; - - enum trace_flags trc_flags; -+#ifndef __GENKSYMS__ -+ /* -+ * This variable may be set from outside the LIO and I/O completion -+ * callback functions. Do not declare this member variable as a -+ * bitfield to avoid a read-modify-write operation when this variable -+ * is set. -+ */ -+ unsigned int aborted; -+#endif - }; - - struct qla_tgt_sess_work_param { diff --git a/patches.kabi/scsi-fc-kABI-fixes-for-new-ELS_FPIN-definition.patch b/patches.kabi/scsi-fc-kABI-fixes-for-new-ELS_FPIN-definition.patch new file mode 100644 index 0000000..097d83e --- /dev/null +++ b/patches.kabi/scsi-fc-kABI-fixes-for-new-ELS_FPIN-definition.patch @@ -0,0 +1,22 @@ +From: Hannes Reinecke +Date: Wed, 17 Jul 2019 13:24:09 +0200 +Subject: [PATCH] scsi/fc: kABI fixes for new ELS_FPIN definition +Patch-Mainline: never, kABI fix for SLE15-SP1 +References: bsc#1136217,jsc#SLE-4722 + +Signed-off-by: Hannes Reinecke +[dwagner: Added ELS_RDF definitions] +Signed-off-by: Daniel Wagner +--- +--- a/include/uapi/scsi/fc/fc_els.h ++++ b/include/uapi/scsi/fc/fc_els.h +@@ -53,7 +53,9 @@ enum fc_els_cmd { + ELS_REC = 0x13, /* read exchange concise */ + ELS_SRR = 0x14, /* sequence retransmission request */ + ELS_FPIN = 0x16, /* Fabric Performance Impact Notification */ ++#ifndef __GENKSYMS__ + ELS_RDF = 0x19, /* Register Diagnostic Functions */ ++#endif + ELS_PRLI = 0x20, /* process login */ + ELS_PRLO = 0x21, /* process logout */ + ELS_SCN = 0x22, /* state change notification */ diff --git a/patches.kabi/scsi-qla2xxx-kabi-fix-for-double-scsi_done-for-abort-path.patch b/patches.kabi/scsi-qla2xxx-kabi-fix-for-double-scsi_done-for-abort-path.patch deleted file mode 100644 index 71dc7e7..0000000 --- a/patches.kabi/scsi-qla2xxx-kabi-fix-for-double-scsi_done-for-abort-path.patch +++ /dev/null @@ -1,45 +0,0 @@ -From: Denis Kirjanov -Subject: kABI workaround for new struct srb bitfields -References: bsc#1143706 bsc#1082635 bsc#1154526 bsc#1048942 -Patch-mainline: Never, kABI fixup - -Signed-off-by: Denis Kirjanov - ---- - ---- a/drivers/scsi/qla2xxx/qla_def.h -+++ b/drivers/scsi/qla2xxx/qla_def.h -@@ -591,20 +591,16 @@ typedef struct srb { - */ - uint8_t cmd_type; - uint8_t pad[3]; -+ atomic_t ref_count; - wait_queue_head_t nvme_ls_waitq; - struct fc_port *fcport; - struct scsi_qla_host *vha; -- unsigned int abort:1; -- unsigned int aborted:1; -- unsigned int completed:1; -- - uint32_t handle; - uint16_t flags; - uint16_t type; - const char *name; - int iocbs; - struct qla_qpair *qpair; -- struct srb *cmd_sp; - struct list_head elem; - u32 gen1; /* scratch */ - u32 gen2; /* scratch */ -@@ -636,7 +632,11 @@ typedef struct srb { - struct kref cmd_kref; /* need to migrate ref_count over to this */ - void *priv; - unsigned int start_timer:1; -+ unsigned int abort:1; -+ unsigned int aborted:1; -+ unsigned int completed:1; - void (*put_fn)(struct kref *kref); -+ struct srb *cmd_sp; - #endif - } srb_t; - diff --git a/patches.kabi/v4l2_fh-kabi-workaround.patch b/patches.kabi/v4l2_fh-kabi-workaround.patch new file mode 100644 index 0000000..e121d4a --- /dev/null +++ b/patches.kabi/v4l2_fh-kabi-workaround.patch @@ -0,0 +1,125 @@ +From: Takashi Iwai +Subject: kABI workaround for v4l2_fh +Patch-mainline: Never, kABI workaround +References: CVE-2019-9458 bsc#1168295 + +The patch + patches.suse/media-v4l-event-Prevent-freeing-event-subscriptions-.patch +introduced a new field subscribe_lock into v4l2_fh object, and this +breaks kABI. Unfortunately we cannot use a standard technique due to the +embedded nature of this object. + +Convert to a global lock for avoiding the kABI breakage, as a cost of a +slight performance degration (which should be negligible). + +Signed-off-by: Takashi Iwai + +--- + drivers/media/v4l2-core/v4l2-event.c | 10 +++++----- + drivers/media/v4l2-core/v4l2-fh.c | 5 +++-- + include/media/v4l2-fh.h | 5 ++--- + 3 files changed, 10 insertions(+), 10 deletions(-) + +--- a/drivers/media/v4l2-core/v4l2-event.c ++++ b/drivers/media/v4l2-core/v4l2-event.c +@@ -197,7 +197,7 @@ static void __v4l2_event_unsubscribe(str + struct v4l2_fh *fh = sev->fh; + unsigned int i; + +- lockdep_assert_held(&fh->subscribe_lock); ++ lockdep_assert_held(&v4l2_fh_subscribe_lock); + assert_spin_locked(&fh->vdev->fh_lock); + + /* Remove any pending events for this subscription */ +@@ -235,7 +235,7 @@ int v4l2_event_subscribe(struct v4l2_fh + sev->ops = ops; + sev->elems = elems; + +- mutex_lock(&fh->subscribe_lock); ++ mutex_lock(&v4l2_fh_subscribe_lock); + + spin_lock_irqsave(&fh->vdev->fh_lock, flags); + found_ev = v4l2_event_subscribed(fh, sub->type, sub->id); +@@ -255,7 +255,7 @@ int v4l2_event_subscribe(struct v4l2_fh + } + } + +- mutex_unlock(&fh->subscribe_lock); ++ mutex_unlock(&v4l2_fh_subscribe_lock); + + return ret; + } +@@ -295,7 +295,7 @@ int v4l2_event_unsubscribe(struct v4l2_f + return 0; + } + +- mutex_lock(&fh->subscribe_lock); ++ mutex_lock(&v4l2_fh_subscribe_lock); + + spin_lock_irqsave(&fh->vdev->fh_lock, flags); + +@@ -308,7 +308,7 @@ int v4l2_event_unsubscribe(struct v4l2_f + if (sev && sev->ops && sev->ops->del) + sev->ops->del(sev); + +- mutex_unlock(&fh->subscribe_lock); ++ mutex_unlock(&v4l2_fh_subscribe_lock); + + kfree(sev); + +--- a/drivers/media/v4l2-core/v4l2-fh.c ++++ b/drivers/media/v4l2-core/v4l2-fh.c +@@ -26,6 +26,9 @@ + #include + #include + ++/* FIXME: converted to a global lock due to kABI compatibility */ ++DEFINE_MUTEX(v4l2_fh_subscribe_lock); ++ + void v4l2_fh_init(struct v4l2_fh *fh, struct video_device *vdev) + { + fh->vdev = vdev; +@@ -45,7 +48,6 @@ void v4l2_fh_init(struct v4l2_fh *fh, st + INIT_LIST_HEAD(&fh->available); + INIT_LIST_HEAD(&fh->subscribed); + fh->sequence = -1; +- mutex_init(&fh->subscribe_lock); + } + EXPORT_SYMBOL_GPL(v4l2_fh_init); + +@@ -91,7 +93,6 @@ void v4l2_fh_exit(struct v4l2_fh *fh) + return; + v4l_disable_media_source(fh->vdev); + v4l2_event_unsubscribe_all(fh); +- mutex_destroy(&fh->subscribe_lock); + fh->vdev = NULL; + } + EXPORT_SYMBOL_GPL(v4l2_fh_exit); +--- a/include/media/v4l2-fh.h ++++ b/include/media/v4l2-fh.h +@@ -37,8 +37,6 @@ struct v4l2_ctrl_handler; + * @prio: priority of the file handler, as defined by &enum v4l2_priority + * + * @wait: event' s wait queue +- * @subscribe_lock: serialise changes to the subscribed list; guarantee that +- * the add and del event callbacks are orderly called + * @subscribed: list of subscribed events + * @available: list of events waiting to be dequeued + * @navailable: number of available events at @available list +@@ -54,7 +52,6 @@ struct v4l2_fh { + + /* Events */ + wait_queue_head_t wait; +- struct mutex subscribe_lock; + struct list_head subscribed; + struct list_head available; + unsigned int navailable; +@@ -65,6 +62,8 @@ struct v4l2_fh { + #endif + }; + ++extern struct mutex v4l2_fh_subscribe_lock; ++ + /** + * v4l2_fh_init - Initialise the file handle. + * diff --git a/patches.rt/0243-md-raid5-Make-raid5_percpu-handling-RT-aware.patch b/patches.rt/0243-md-raid5-Make-raid5_percpu-handling-RT-aware.patch index 1f842a5..ebb85a7 100644 --- a/patches.rt/0243-md-raid5-Make-raid5_percpu-handling-RT-aware.patch +++ b/patches.rt/0243-md-raid5-Make-raid5_percpu-handling-RT-aware.patch @@ -24,7 +24,7 @@ Signed-off-by: Mike Galbraith --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c -@@ -2065,8 +2065,9 @@ static void raid_run_ops(struct stripe_h +@@ -2067,8 +2067,9 @@ static void raid_run_ops(struct stripe_h struct raid5_percpu *percpu; unsigned long cpu; @@ -35,7 +35,7 @@ Signed-off-by: Mike Galbraith if (test_bit(STRIPE_OP_BIOFILL, &ops_request)) { ops_run_biofill(sh); overlap_clear++; -@@ -2125,7 +2126,8 @@ static void raid_run_ops(struct stripe_h +@@ -2127,7 +2128,8 @@ static void raid_run_ops(struct stripe_h if (test_and_clear_bit(R5_Overlap, &dev->flags)) wake_up(&sh->raid_conf->wait_for_overlap); } @@ -45,7 +45,7 @@ Signed-off-by: Mike Galbraith } static void free_stripe(struct kmem_cache *sc, struct stripe_head *sh) -@@ -6796,6 +6798,7 @@ static int raid456_cpu_up_prepare(unsign +@@ -6824,6 +6826,7 @@ static int raid456_cpu_up_prepare(unsign __func__, cpu); return -ENOMEM; } @@ -53,7 +53,7 @@ Signed-off-by: Mike Galbraith return 0; } -@@ -6806,7 +6809,6 @@ static int raid5_alloc_percpu(struct r5c +@@ -6834,7 +6837,6 @@ static int raid5_alloc_percpu(struct r5c conf->percpu = alloc_percpu(struct raid5_percpu); if (!conf->percpu) return -ENOMEM; @@ -63,11 +63,11 @@ Signed-off-by: Mike Galbraith conf->scribble_disks = max(conf->raid_disks, --- a/drivers/md/raid5.h +++ b/drivers/md/raid5.h -@@ -623,6 +623,7 @@ struct r5conf { +@@ -633,6 +633,7 @@ struct r5conf { int recovery_disabled; /* per cpu variables */ struct raid5_percpu { + spinlock_t lock; /* Protection for -RT */ struct page *spare_page; /* Used when checking P/Q in raid6 */ - struct flex_array *scribble; /* space for constructing buffer - * lists and performing address + void *scribble; /* space for constructing buffer + * lists and performing address diff --git a/patches.rt/efi-Disable-runtime-services-on-RT.patch b/patches.rt/efi-Disable-runtime-services-on-RT.patch index 1f561c1..38dc6e5 100644 --- a/patches.rt/efi-Disable-runtime-services-on-RT.patch +++ b/patches.rt/efi-Disable-runtime-services-on-RT.patch @@ -35,9 +35,9 @@ Signed-off-by: Mike Galbraith --- a/drivers/firmware/efi/efi.c +++ b/drivers/firmware/efi/efi.c -@@ -74,7 +74,7 @@ static unsigned long *efi_tables[] = { - &efi.mem_attr_table, +@@ -56,7 +56,7 @@ struct efi __read_mostly efi = { }; + EXPORT_SYMBOL(efi); -static bool disable_runtime; +static bool disable_runtime = IS_ENABLED(CONFIG_PREEMPT_RT_BASE); diff --git a/patches.rt/pci-switchtec-Don-t-use-completion-s-wait-queue.patch b/patches.rt/pci-switchtec-Don-t-use-completion-s-wait-queue.patch index 5da56b4..a38bf75 100644 --- a/patches.rt/pci-switchtec-Don-t-use-completion-s-wait-queue.patch +++ b/patches.rt/pci-switchtec-Don-t-use-completion-s-wait-queue.patch @@ -28,7 +28,7 @@ Signed-off-by: Mike Galbraith --- a/drivers/pci/switch/switchtec.c +++ b/drivers/pci/switch/switchtec.c -@@ -297,10 +297,11 @@ struct switchtec_user { +@@ -299,10 +299,11 @@ struct switchtec_user { enum mrpc_state state; @@ -41,7 +41,7 @@ Signed-off-by: Mike Galbraith u32 cmd; u32 status; u32 return_code; -@@ -322,7 +323,7 @@ static struct switchtec_user *stuser_cre +@@ -324,7 +325,7 @@ static struct switchtec_user *stuser_cre stuser->stdev = stdev; kref_init(&stuser->kref); INIT_LIST_HEAD(&stuser->list); @@ -50,16 +50,16 @@ Signed-off-by: Mike Galbraith stuser->event_cnt = atomic_read(&stdev->event_cnt); dev_dbg(&stdev->dev, "%s: %p\n", __func__, stuser); -@@ -405,7 +406,7 @@ static int mrpc_queue_cmd(struct switcht +@@ -403,7 +404,7 @@ static int mrpc_queue_cmd(struct switcht kref_get(&stuser->kref); stuser->read_len = sizeof(stuser->data); stuser_set_state(stuser, MRPC_QUEUED); -- init_completion(&stuser->comp); +- reinit_completion(&stuser->comp); + stuser->cmd_done = false; list_add_tail(&stuser->list, &stdev->mrpc_queue); mrpc_cmd_submit(stdev); -@@ -442,7 +443,7 @@ static void mrpc_complete_cmd(struct swi +@@ -440,7 +441,7 @@ static void mrpc_complete_cmd(struct swi stuser->read_len); out: @@ -68,7 +68,7 @@ Signed-off-by: Mike Galbraith list_del_init(&stuser->list); stuser_put(stuser); stdev->mrpc_busy = 0; -@@ -712,10 +713,11 @@ static ssize_t switchtec_dev_read(struct +@@ -710,10 +711,11 @@ static ssize_t switchtec_dev_read(struct mutex_unlock(&stdev->mrpc_mutex); if (filp->f_flags & O_NONBLOCK) { @@ -82,7 +82,7 @@ Signed-off-by: Mike Galbraith if (rc < 0) return rc; } -@@ -763,7 +765,7 @@ static unsigned int switchtec_dev_poll(s +@@ -761,7 +763,7 @@ static unsigned int switchtec_dev_poll(s struct switchtec_dev *stdev = stuser->stdev; int ret = 0; @@ -91,7 +91,7 @@ Signed-off-by: Mike Galbraith poll_wait(filp, &stdev->event_wq, wait); if (lock_mutex_and_test_alive(stdev)) -@@ -771,7 +773,7 @@ static unsigned int switchtec_dev_poll(s +@@ -769,7 +771,7 @@ static unsigned int switchtec_dev_poll(s mutex_unlock(&stdev->mrpc_mutex); @@ -100,7 +100,7 @@ Signed-off-by: Mike Galbraith ret |= POLLIN | POLLRDNORM; if (stuser->event_cnt != atomic_read(&stdev->event_cnt)) -@@ -1237,7 +1239,8 @@ static void stdev_kill(struct switchtec_ +@@ -1240,7 +1242,8 @@ static void stdev_kill(struct switchtec_ /* Wake up and kill any users waiting on an MRPC request */ list_for_each_entry_safe(stuser, tmpuser, &stdev->mrpc_queue, list) { diff --git a/patches.suse/0001-ALSA-usb-audio-Apply-sample-rate-quirk-for-Audioengi.patch b/patches.suse/0001-ALSA-usb-audio-Apply-sample-rate-quirk-for-Audioengi.patch index 1e0cef5..df3318e 100644 --- a/patches.suse/0001-ALSA-usb-audio-Apply-sample-rate-quirk-for-Audioengi.patch +++ b/patches.suse/0001-ALSA-usb-audio-Apply-sample-rate-quirk-for-Audioengi.patch @@ -35,10 +35,10 @@ Signed-off-by: Oliver Neukum --- a/sound/usb/quirks.c +++ b/sound/usb/quirks.c -@@ -1281,6 +1281,7 @@ bool snd_usb_get_sample_rate_quirk(struc +@@ -1404,6 +1404,7 @@ bool snd_usb_get_sample_rate_quirk(struc case USB_ID(0x1395, 0x740a): /* Sennheiser DECT */ case USB_ID(0x1901, 0x0191): /* GE B850V3 CP2114 audio interface */ - case USB_ID(0x21B4, 0x0081): /* AudioQuest DragonFly */ + case USB_ID(0x21b4, 0x0081): /* AudioQuest DragonFly */ + case USB_ID(0x2912, 0x30c8): /* Audioengine D1 */ return true; } diff --git a/patches.suse/0001-Btrfs-fix-fsync-of-files-with-multiple-hard-links-in.patch b/patches.suse/0001-Btrfs-fix-fsync-of-files-with-multiple-hard-links-in.patch index 81a35a0..becb012 100644 --- a/patches.suse/0001-Btrfs-fix-fsync-of-files-with-multiple-hard-links-in.patch +++ b/patches.suse/0001-Btrfs-fix-fsync-of-files-with-multiple-hard-links-in.patch @@ -60,33 +60,29 @@ Reported-by: Jayashree Mohan Signed-off-by: Filipe Manana Signed-off-by: David Sterba --- - fs/btrfs/btrfs_inode.h | 6 ++++++ - fs/btrfs/inode.c | 17 +++++++++++++++++ - fs/btrfs/tree-log.c | 16 ++++++++++++++++ + fs/btrfs/btrfs_inode.h | 6 ++++++ + fs/btrfs/inode.c | 17 +++++++++++++++++ + fs/btrfs/tree-log.c | 16 ++++++++++++++++ 3 files changed, 39 insertions(+) -diff --git a/fs/btrfs/btrfs_inode.h b/fs/btrfs/btrfs_inode.h -index cbea7456f797..1d8c7560022d 100644 --- a/fs/btrfs/btrfs_inode.h +++ b/fs/btrfs/btrfs_inode.h -@@ -159,6 +159,12 @@ struct btrfs_inode { - */ +@@ -160,6 +160,12 @@ struct btrfs_inode { u64 last_unlink_trans; -+ /* + /* + * Track the transaction id of the last transaction used to create a + * hard link for the inode. This is used by the log tree (fsync). + */ + u64 last_link_trans; + - /* ++ /* * Number of bytes outstanding that are going to need csums. This is * used in ENOSPC accounting. -diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c -index 357fe75589a9..a248d8d5c41f 100644 + */ --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c -@@ -3831,6 +3831,21 @@ static int btrfs_read_locked_inode(struct inode *inode, +@@ -3672,6 +3672,21 @@ cache_index: * inode is not a directory, logging its parent unnecessarily. */ BTRFS_I(inode)->last_unlink_trans = BTRFS_I(inode)->last_trans; @@ -108,7 +104,7 @@ index 357fe75589a9..a248d8d5c41f 100644 path->slots[0]++; if (inode->i_nlink != 1 || -@@ -6753,6 +6768,7 @@ static int btrfs_link(struct dentry *old_dentry, struct inode *dir, +@@ -6454,6 +6469,7 @@ static int btrfs_link(struct dentry *old if (err) goto fail; } @@ -116,19 +112,17 @@ index 357fe75589a9..a248d8d5c41f 100644 d_instantiate(dentry, inode); ret = btrfs_log_new_name(trans, BTRFS_I(inode), NULL, parent, true, NULL); -@@ -9453,6 +9469,7 @@ struct inode *btrfs_alloc_inode(struct super_block *sb) +@@ -9156,6 +9172,7 @@ struct inode *btrfs_alloc_inode(struct s ei->index_cnt = (u64)-1; ei->dir_index = 0; ei->last_unlink_trans = 0; + ei->last_link_trans = 0; ei->last_log_commit = 0; - ei->delayed_iput_count = 0; -diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c -index 61ded3c9cc1a..8cd571f6747b 100644 + spin_lock_init(&ei->lock); --- a/fs/btrfs/tree-log.c +++ b/fs/btrfs/tree-log.c -@@ -5947,6 +5947,22 @@ static int btrfs_log_inode_parent(struct btrfs_trans_handle *trans, +@@ -5946,6 +5946,22 @@ static int btrfs_log_inode_parent(struct goto end_trans; } @@ -151,6 +145,3 @@ index 61ded3c9cc1a..8cd571f6747b 100644 while (1) { if (!parent || d_really_is_negative(parent) || sb != parent->d_sb) break; --- -2.19.0 - diff --git a/patches.suse/0001-Btrfs-make-plug-in-writing-meta-blocks-really-work.patch b/patches.suse/0001-Btrfs-make-plug-in-writing-meta-blocks-really-work.patch new file mode 100644 index 0000000..d916218 --- /dev/null +++ b/patches.suse/0001-Btrfs-make-plug-in-writing-meta-blocks-really-work.patch @@ -0,0 +1,66 @@ +From 6300463b14c1c2665674eb8f15843e5bb7a7ff84 Mon Sep 17 00:00:00 2001 +From: Liu Bo +Date: Mon, 21 Aug 2017 15:49:59 -0600 +Patch-mainline: v4.15 +Git-commit: 6300463b14c1c2665674eb8f15843e5bb7a7ff84 +References: bsc#1168273 +Subject: [PATCH 1/2] Btrfs: make plug in writing meta blocks really work + +We have started plug in btrfs_write_and_wait_marked_extents() but the +generated IOs actually go to device's schedule IO list where the work +is doing in another task, thus the started plug doesn't make any +sense. + +And since we wait for IOs immediately after writing meta blocks, it's +the same case as writing log tree, doing sync submit can merge more +IOs. + +Signed-off-by: Liu Bo +Reviewed-by: David Sterba +Signed-off-by: David Sterba +--- + fs/btrfs/disk-io.c | 6 ++++-- + fs/btrfs/transaction.c | 2 ++ + 2 files changed, 6 insertions(+), 2 deletions(-) + +--- a/fs/btrfs/disk-io.c ++++ b/fs/btrfs/disk-io.c +@@ -1003,8 +1003,10 @@ static blk_status_t __btree_submit_bio_d + return ret; + } + +-static int check_async_write(unsigned long bio_flags) ++static int check_async_write(struct btrfs_inode *bi, unsigned long bio_flags) + { ++ if (atomic_read(&bi->sync_writers)) ++ return 0; + if (bio_flags & EXTENT_BIO_TREE_LOG) + return 0; + #ifdef CONFIG_X86 +@@ -1019,7 +1021,7 @@ static blk_status_t btree_submit_bio_hoo + u64 bio_offset) + { + struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb); +- int async = check_async_write(bio_flags); ++ int async = check_async_write(BTRFS_I(inode), bio_flags); + blk_status_t ret; + + if (bio_op(bio) != REQ_OP_WRITE) { +--- a/fs/btrfs/transaction.c ++++ b/fs/btrfs/transaction.c +@@ -950,6 +950,7 @@ int btrfs_write_marked_extents(struct bt + u64 start = 0; + u64 end; + ++ atomic_inc(&BTRFS_I(fs_info->btree_inode)->sync_writers); + while (!find_first_extent_bit(dirty_pages, start, &start, &end, + mark, &cached_state)) { + bool wait_writeback = false; +@@ -985,6 +986,7 @@ int btrfs_write_marked_extents(struct bt + cond_resched(); + start = end + 1; + } ++ atomic_dec(&BTRFS_I(fs_info->btree_inode)->sync_writers); + return werr; + } + diff --git a/patches.suse/0001-HID-Add-quirk-for-Microsoft-PIXART-OEM-mouse.patch b/patches.suse/0001-HID-Add-quirk-for-Microsoft-PIXART-OEM-mouse.patch index 5f7a5b3..541bfdf 100644 --- a/patches.suse/0001-HID-Add-quirk-for-Microsoft-PIXART-OEM-mouse.patch +++ b/patches.suse/0001-HID-Add-quirk-for-Microsoft-PIXART-OEM-mouse.patch @@ -24,7 +24,7 @@ Signed-off-by: Oliver Neukum --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h -@@ -767,6 +767,7 @@ +@@ -768,6 +768,7 @@ #define USB_DEVICE_ID_MS_TOUCH_COVER_2 0x07a7 #define USB_DEVICE_ID_MS_TYPE_COVER_2 0x07a9 #define USB_DEVICE_ID_MS_POWER_COVER 0x07da @@ -34,10 +34,10 @@ Signed-off-by: Oliver Neukum #define USB_DEVICE_ID_RETRO_ADAPTER 0x3201 --- a/drivers/hid/usbhid/hid-quirks.c +++ b/drivers/hid/usbhid/hid-quirks.c -@@ -106,6 +106,7 @@ static const struct hid_blacklist { +@@ -105,6 +105,7 @@ static const struct hid_blacklist { + { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_MOUSE_C01A, HID_QUIRK_ALWAYS_POLL }, { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_MOUSE_C05A, HID_QUIRK_ALWAYS_POLL }, { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_MOUSE_C06A, HID_QUIRK_ALWAYS_POLL }, - { USB_VENDOR_ID_MGE, USB_DEVICE_ID_MGE_UPS, HID_QUIRK_NOGET }, + { USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_PIXART_MOUSE, HID_QUIRK_ALWAYS_POLL }, { USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_SURFACE_PRO_2, HID_QUIRK_NO_INIT_REPORTS }, { USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_2, HID_QUIRK_NO_INIT_REPORTS }, diff --git a/patches.suse/0001-HID-hiddev-Fix-race-in-in-hiddev_disconnect.patch b/patches.suse/0001-HID-hiddev-Fix-race-in-in-hiddev_disconnect.patch new file mode 100644 index 0000000..db9ac8e --- /dev/null +++ b/patches.suse/0001-HID-hiddev-Fix-race-in-in-hiddev_disconnect.patch @@ -0,0 +1,37 @@ +From 5c02c447eaeda29d3da121a2e17b97ccaf579b51 Mon Sep 17 00:00:00 2001 +From: "dan.carpenter@oracle.com" +Date: Wed, 15 Jan 2020 20:46:28 +0300 +Subject: [PATCH] HID: hiddev: Fix race in in hiddev_disconnect() +Git-commit: 5c02c447eaeda29d3da121a2e17b97ccaf579b51 +References: git-fixes +Patch-mainline: v5.6-rc4 + +Syzbot reports that "hiddev" is used after it's free in hiddev_disconnect(). +The hiddev_disconnect() function sets "hiddev->exist = 0;" so +hiddev_release() can free it as soon as we drop the "existancelock" +lock. This patch moves the mutex_unlock(&hiddev->existancelock) until +after we have finished using it. + +Reported-by: syzbot+784ccb935f9900cc7c9e@syzkaller.appspotmail.com +Fixes: 7f77897ef2b6 ("HID: hiddev: fix potential use-after-free") +Suggested-by: Alan Stern +Signed-off-by: Dan Carpenter +Signed-off-by: Jiri Kosina +Signed-off-by: Oliver Neukum +--- + drivers/hid/usbhid/hiddev.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/hid/usbhid/hiddev.c ++++ b/drivers/hid/usbhid/hiddev.c +@@ -967,9 +967,9 @@ void hiddev_disconnect(struct hid_device + hiddev->exist = 0; + + if (hiddev->open) { +- mutex_unlock(&hiddev->existancelock); + usbhid_close(hiddev->hid); + wake_up_interruptible(&hiddev->wait); ++ mutex_unlock(&hiddev->existancelock); + } else { + mutex_unlock(&hiddev->existancelock); + kfree(hiddev); diff --git a/patches.suse/0001-Input-add-safety-guards-to-input_set_keycode.patch b/patches.suse/0001-Input-add-safety-guards-to-input_set_keycode.patch new file mode 100644 index 0000000..b33e0ce --- /dev/null +++ b/patches.suse/0001-Input-add-safety-guards-to-input_set_keycode.patch @@ -0,0 +1,72 @@ +From cb222aed03d798fc074be55e59d9a112338ee784 Mon Sep 17 00:00:00 2001 +From: Dmitry Torokhov +Date: Fri, 13 Dec 2019 14:56:16 -0800 +Subject: [PATCH] Input: add safety guards to input_set_keycode() +Git-commit: cb222aed03d798fc074be55e59d9a112338ee784 +References: bsc#1168075 +Patch-mainline: v5.5-rc6 + +If we happen to have a garbage in input device's keycode table with values +too big we'll end up doing clear_bit() with offset way outside of our +bitmaps, damaging other objects within an input device or even outside of +it. Let's add sanity checks to the returned old keycodes. + +Reported-by: syzbot+c769968809f9359b07aa@syzkaller.appspotmail.com +Reported-by: syzbot+76f3a30e88d256644c78@syzkaller.appspotmail.com +Link: https://lore.kernel.org/r/20191207212757.GA245964@dtor-ws +Signed-off-by: Dmitry Torokhov +Signed-off-by: Oliver Neukum +--- + drivers/input/input.c | 26 ++++++++++++++++---------- + 1 file changed, 16 insertions(+), 10 deletions(-) + +diff --git a/drivers/input/input.c b/drivers/input/input.c +index 55086279d044..ee6c3234df36 100644 +--- a/drivers/input/input.c ++++ b/drivers/input/input.c +@@ -878,16 +878,18 @@ static int input_default_setkeycode(struct input_dev *dev, + } + } + +- __clear_bit(*old_keycode, dev->keybit); +- __set_bit(ke->keycode, dev->keybit); +- +- for (i = 0; i < dev->keycodemax; i++) { +- if (input_fetch_keycode(dev, i) == *old_keycode) { +- __set_bit(*old_keycode, dev->keybit); +- break; /* Setting the bit twice is useless, so break */ ++ if (*old_keycode <= KEY_MAX) { ++ __clear_bit(*old_keycode, dev->keybit); ++ for (i = 0; i < dev->keycodemax; i++) { ++ if (input_fetch_keycode(dev, i) == *old_keycode) { ++ __set_bit(*old_keycode, dev->keybit); ++ /* Setting the bit twice is useless, so break */ ++ break; ++ } + } + } + ++ __set_bit(ke->keycode, dev->keybit); + return 0; + } + +@@ -943,9 +945,13 @@ int input_set_keycode(struct input_dev *dev, + * Simulate keyup event if keycode is not present + * in the keymap anymore + */ +- if (test_bit(EV_KEY, dev->evbit) && +- !is_event_supported(old_keycode, dev->keybit, KEY_MAX) && +- __test_and_clear_bit(old_keycode, dev->key)) { ++ if (old_keycode > KEY_MAX) { ++ dev_warn(dev->dev.parent ?: &dev->dev, ++ "%s: got too big old keycode %#x\n", ++ __func__, old_keycode); ++ } else if (test_bit(EV_KEY, dev->evbit) && ++ !is_event_supported(old_keycode, dev->keybit, KEY_MAX) && ++ __test_and_clear_bit(old_keycode, dev->key)) { + struct input_value vals[] = { + { EV_KEY, old_keycode, 0 }, + input_value_sync +-- +2.16.4 + diff --git a/patches.suse/0001-KVM-arm64-Store-vcpu-on-the-stack-during-__guest_ent.patch b/patches.suse/0001-KVM-arm64-Store-vcpu-on-the-stack-during-__guest_ent.patch deleted file mode 100644 index d766e0a..0000000 --- a/patches.suse/0001-KVM-arm64-Store-vcpu-on-the-stack-during-__guest_ent.patch +++ /dev/null @@ -1,100 +0,0 @@ -From: James Morse -Date: Mon, 8 Jan 2018 15:38:03 +0000 -Subject: KVM: arm64: Store vcpu on the stack during __guest_enter() -Git-commit: 32b03d1059667a39e089c45ee38ec9c16332430f -Patch-mainline: v4.16-rc1 -References: fate#326420 fate#325360 - -KVM uses tpidr_el2 as its private vcpu register, which makes sense for -non-vhe world switch as only KVM can access this register. This means -vhe Linux has to use tpidr_el1, which KVM has to save/restore as part -of the host context. - -If the SDEI handler code runs behind KVMs back, it mustn't access any -per-cpu variables. To allow this on systems with vhe we need to make -the host use tpidr_el2, saving KVM from save/restoring it. - -__guest_enter() stores the host_ctxt on the stack, do the same with -the vcpu. - -Signed-off-by: James Morse -Reviewed-by: Christoffer Dall -Signed-off-by: Catalin Marinas -Signed-off-by: Matthias Brugger ---- - arch/arm64/kvm/hyp/entry.S | 10 +++++++--- - arch/arm64/kvm/hyp/hyp-entry.S | 6 +++--- - 2 files changed, 10 insertions(+), 6 deletions(-) - -diff --git a/arch/arm64/kvm/hyp/entry.S b/arch/arm64/kvm/hyp/entry.S -index 9c45c6af1f58..fe4678f20a85 100644 ---- a/arch/arm64/kvm/hyp/entry.S -+++ b/arch/arm64/kvm/hyp/entry.S -@@ -62,8 +62,8 @@ ENTRY(__guest_enter) - // Store the host regs - save_callee_saved_regs x1 - -- // Store the host_ctxt for use at exit time -- str x1, [sp, #-16]! -+ // Store host_ctxt and vcpu for use at exit time -+ stp x1, x0, [sp, #-16]! - - add x18, x0, #VCPU_CONTEXT - -@@ -159,6 +159,10 @@ abort_guest_exit_end: - ENDPROC(__guest_exit) - - ENTRY(__fpsimd_guest_restore) -+ // x0: esr -+ // x1: vcpu -+ // x2-x29,lr: vcpu regs -+ // vcpu x0-x1 on the stack - stp x2, x3, [sp, #-16]! - stp x4, lr, [sp, #-16]! - -@@ -173,7 +177,7 @@ alternative_else - alternative_endif - isb - -- mrs x3, tpidr_el2 -+ mov x3, x1 - - ldr x0, [x3, #VCPU_HOST_CONTEXT] - kern_hyp_va x0 -diff --git a/arch/arm64/kvm/hyp/hyp-entry.S b/arch/arm64/kvm/hyp/hyp-entry.S -index 5170ce1021da..fce7cc507e0a 100644 ---- a/arch/arm64/kvm/hyp/hyp-entry.S -+++ b/arch/arm64/kvm/hyp/hyp-entry.S -@@ -104,6 +104,7 @@ el1_trap: - /* - * x0: ESR_EC - */ -+ ldr x1, [sp, #16 + 8] // vcpu stored by __guest_enter - - /* - * We trap the first access to the FP/SIMD to save the host context -@@ -116,19 +117,18 @@ alternative_if_not ARM64_HAS_NO_FPSIMD - b.eq __fpsimd_guest_restore - alternative_else_nop_endif - -- mrs x1, tpidr_el2 - mov x0, #ARM_EXCEPTION_TRAP - b __guest_exit - - el1_irq: - stp x0, x1, [sp, #-16]! -- mrs x1, tpidr_el2 -+ ldr x1, [sp, #16 + 8] - mov x0, #ARM_EXCEPTION_IRQ - b __guest_exit - - el1_error: - stp x0, x1, [sp, #-16]! -- mrs x1, tpidr_el2 -+ ldr x1, [sp, #16 + 8] - mov x0, #ARM_EXCEPTION_EL1_SERROR - b __guest_exit - --- -2.19.0 - diff --git a/patches.suse/0001-PCI-pciehp-Differentiate-between-surprise-and-safe-r.patch b/patches.suse/0001-PCI-pciehp-Differentiate-between-surprise-and-safe-r.patch index 476011b..554c254 100644 --- a/patches.suse/0001-PCI-pciehp-Differentiate-between-surprise-and-safe-r.patch +++ b/patches.suse/0001-PCI-pciehp-Differentiate-between-surprise-and-safe-r.patch @@ -49,7 +49,7 @@ Signed-off-by: Oliver Neukum --- a/drivers/pci/hotplug/pciehp.h +++ b/drivers/pci/hotplug/pciehp.h -@@ -146,13 +146,13 @@ void pciehp_handle_button_press(struct s +@@ -191,13 +191,13 @@ void pciehp_handle_button_press(struct s void pciehp_handle_disable_request(struct slot *slot); void pciehp_handle_presence_or_link_change(struct slot *slot, u32 events); int pciehp_configure_device(struct slot *p_slot); @@ -130,7 +130,7 @@ Signed-off-by: Oliver Neukum { u8 getstatus = 0; struct controller *ctrl = p_slot->ctrl; -@@ -364,19 +368,19 @@ static int __pciehp_disable_slot(struct +@@ -361,19 +365,19 @@ static int __pciehp_disable_slot(struct } } @@ -200,5 +200,5 @@ Signed-off-by: Oliver Neukum __func__, pci_domain_nr(parent), parent->number); - pciehp_get_adapter_status(p_slot, &presence); - pci_lock_rescan_remove(); - + if (!presence) + pci_walk_bus(parent, pci_dev_set_disconnected, NULL); diff --git a/patches.suse/0001-PCI-pciehp-Make-pciehp_is_native-stricter.patch b/patches.suse/0001-PCI-pciehp-Make-pciehp_is_native-stricter.patch index 525cac9..4b6383e 100644 --- a/patches.suse/0001-PCI-pciehp-Make-pciehp_is_native-stricter.patch +++ b/patches.suse/0001-PCI-pciehp-Make-pciehp_is_native-stricter.patch @@ -23,9 +23,10 @@ Reviewed-by: Rafael J. Wysocki Signed-off-by: Oliver Neukum --- drivers/pci/pci-acpi.c | 26 ++++++++++++++------------ + drivers/pci/pcie/portdrv.h | 2 -- include/linux/pci.h | 2 ++ include/linux/pci_hotplug.h | 4 ++-- - 3 files changed, 18 insertions(+), 14 deletions(-) + 4 files changed, 18 insertions(+), 16 deletions(-) --- a/drivers/pci/pci-acpi.c +++ b/drivers/pci/pci-acpi.c @@ -72,7 +73,7 @@ Signed-off-by: Oliver Neukum /** --- a/include/linux/pci.h +++ b/include/linux/pci.h -@@ -1410,9 +1410,11 @@ pci_alloc_irq_vectors(struct pci_dev *de +@@ -1465,9 +1465,11 @@ static inline int pci_irqd_intx_xlate(st #ifdef CONFIG_PCIEPORTBUS extern bool pcie_ports_disabled; @@ -103,3 +104,14 @@ Signed-off-by: Oliver Neukum +static inline bool pciehp_is_native(struct pci_dev *bridge) { return true; } #endif #endif +--- a/drivers/pci/pcie/portdrv.h ++++ b/drivers/pci/pcie/portdrv.h +@@ -11,8 +11,6 @@ + + #include + +-extern bool pcie_ports_native; +- + /* Service Type */ + #define PCIE_PORT_SERVICE_PME_SHIFT 0 /* Power Management Event */ + #define PCIE_PORT_SERVICE_PME (1 << PCIE_PORT_SERVICE_PME_SHIFT) diff --git a/patches.suse/0001-PCI-portdrv-Simplify-PCIe-feature-permission-checkin.patch b/patches.suse/0001-PCI-portdrv-Simplify-PCIe-feature-permission-checkin.patch index 5fe0d13..691445b 100644 --- a/patches.suse/0001-PCI-portdrv-Simplify-PCIe-feature-permission-checkin.patch +++ b/patches.suse/0001-PCI-portdrv-Simplify-PCIe-feature-permission-checkin.patch @@ -74,7 +74,7 @@ Signed-off-by: Oliver Neukum @@ -6,7 +6,6 @@ obj-$(CONFIG_PCIEASPM) += aspm.o - pcieportdrv-y := portdrv_core.o portdrv_pci.o portdrv_bus.o + pcieportdrv-y := portdrv_core.o portdrv_pci.o -pcieportdrv-$(CONFIG_ACPI) += portdrv_acpi.o obj-$(CONFIG_PCIEPORTBUS) += pcieportdrv.o diff --git a/patches.suse/0001-PM-core-Fix-handling-of-devices-deleted-during-syste.patch b/patches.suse/0001-PM-core-Fix-handling-of-devices-deleted-during-syste.patch new file mode 100644 index 0000000..8b60f71 --- /dev/null +++ b/patches.suse/0001-PM-core-Fix-handling-of-devices-deleted-during-syste.patch @@ -0,0 +1,112 @@ +From 0552e05fdfea191a2cf3a0abd33574b5ef9ca818 Mon Sep 17 00:00:00 2001 +From: "Rafael J. Wysocki" +Date: Thu, 23 Jan 2020 00:11:24 +0100 +Subject: [PATCH] PM: core: Fix handling of devices deleted during system-wide + resume +Git-commit: 0552e05fdfea191a2cf3a0abd33574b5ef9ca818 +References: git-fixes +Patch-mainline: v5.6-rc1 + +If a device is deleted by one of its system-wide resume callbacks +(for example, because it does not appear to be present or accessible +any more) along with its children, the resume of the children may +continue leading to use-after-free errors and other issues +(potentially). + +Namely, if the device's children are resumed asynchronously, their +resume may have been scheduled already before the device's callback +runs and so the device may be deleted while dpm_wait_for_superior() +is being executed for them. The memory taken up by the parent device +object may be freed then while dpm_wait() is waiting for the parent's +resume callback to complete, which leads to a use-after-free. +Moreover, the resume of the children is really not expected to +continue after they have been unregistered, so it must be terminated +right away in that case. + +To address this problem, modify dpm_wait_for_superior() to check +if the target device is still there in the system-wide PM list of +devices and if so, to increment its parent's reference counter, both +under dpm_list_mtx which prevents device_del() running for the child +from dropping the parent's reference counter prematurely. + +If the device is not present in the system-wide PM list of devices +any more, the resume of it cannot continue, so check that again after +dpm_wait() returns, which means that the parent's callback has been +completed, and pass the result of that check to the caller of +dpm_wait_for_superior() to allow it to abort the device's resume +if it is not there any more. + +Link: https://lore.kernel.org/linux-pm/1579568452-27253-1-git-send-email-chanho.min@lge.com +Reported-by: Chanho Min +Cc: All applicable +Signed-off-by: Rafael J. Wysocki +Acked-by: Greg Kroah-Hartman +Signed-off-by: Oliver Neukum +--- + drivers/base/power/main.c | 39 +++++++++++++++++++++++++++++++++++---- + 1 file changed, 35 insertions(+), 4 deletions(-) + +--- a/drivers/base/power/main.c ++++ b/drivers/base/power/main.c +@@ -268,10 +268,38 @@ static void dpm_wait_for_suppliers(struc + device_links_read_unlock(idx); + } + +-static void dpm_wait_for_superior(struct device *dev, bool async) ++static bool dpm_wait_for_superior(struct device *dev, bool async) + { +- dpm_wait(dev->parent, async); ++ struct device *parent; ++ ++ /* ++ * If the device is resumed asynchronously and the parent's callback ++ * deletes both the device and the parent itself, the parent object may ++ * be freed while this function is running, so avoid that by reference ++ * counting the parent once more unless the device has been deleted ++ * already (in which case return right away). ++ */ ++ mutex_lock(&dpm_list_mtx); ++ ++ if (!device_pm_initialized(dev)) { ++ mutex_unlock(&dpm_list_mtx); ++ return false; ++ } ++ ++ parent = get_device(dev->parent); ++ ++ mutex_unlock(&dpm_list_mtx); ++ ++ dpm_wait(parent, async); ++ put_device(parent); ++ + dpm_wait_for_suppliers(dev, async); ++ ++ /* ++ * If the parent's callback has deleted the device, attempting to resume ++ * it would be invalid, so avoid doing that then. ++ */ ++ return device_pm_initialized(dev); + } + + static void dpm_wait_for_consumers(struct device *dev, bool async) +@@ -677,7 +705,8 @@ static int device_resume_early(struct de + if (!dev->power.is_late_suspended) + goto Out; + +- dpm_wait_for_superior(dev, async); ++ if (!dpm_wait_for_superior(dev, async)) ++ goto Out; + + if (dev->pm_domain) { + info = "early power domain "; +@@ -809,7 +838,9 @@ static int device_resume(struct device * + goto Complete; + } + +- dpm_wait_for_superior(dev, async); ++ if (!dpm_wait_for_superior(dev, async)) ++ goto Complete; ++ + dpm_watchdog_set(&wd, dev); + device_lock(dev); + diff --git a/patches.suse/0001-Revert-HID-add-NOGET-quirk-for-Eaton-Ellipse-MAX-UPS.patch b/patches.suse/0001-Revert-HID-add-NOGET-quirk-for-Eaton-Ellipse-MAX-UPS.patch new file mode 100644 index 0000000..e38db98 --- /dev/null +++ b/patches.suse/0001-Revert-HID-add-NOGET-quirk-for-Eaton-Ellipse-MAX-UPS.patch @@ -0,0 +1,39 @@ +From 6298944d8f57f40ee2a3e6dcea1253e78d7a9969 Mon Sep 17 00:00:00 2001 +From: Benjamin Tissoires +Date: Wed, 17 Oct 2018 09:01:53 +0200 +Subject: [PATCH] Revert "HID: add NOGET quirk for Eaton Ellipse MAX UPS" +Git-commit: 6298944d8f57f40ee2a3e6dcea1253e78d7a9969 +References: git-fixes +Patch-mainline: v4.20 + +This reverts commit 67ddbb3e6568fb1820b2cc45b00c50702b114801. + +67ddbb3e656 ("HID: add NOGET quirk for Eaton Ellipse MAX UPS") was reported +by Laurent Bigonville. It turns out that a later model Laurent got +doesn't need the quirk after all. + +My take is that Eaton upgraded their firmwares, so we don't need it +anymore. + +The old model was from 2012, so better make sure the new line works +properly by removing the quirk. This allows upower to actually fetch +the current data. + +Reported-by: Laurent Bigonville +Signed-off-by: Benjamin Tissoires +Signed-off-by: Jiri Kosina +Signed-off-by: Oliver Neukum +--- + drivers/hid/usbhid/hid-quirks.c | 1 - + 1 file changed, 1 deletion(-) + +--- a/drivers/hid/usbhid/hid-quirks.c ++++ b/drivers/hid/usbhid/hid-quirks.c +@@ -105,7 +105,6 @@ static const struct hid_blacklist { + { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_MOUSE_C01A, HID_QUIRK_ALWAYS_POLL }, + { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_MOUSE_C05A, HID_QUIRK_ALWAYS_POLL }, + { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_MOUSE_C06A, HID_QUIRK_ALWAYS_POLL }, +- { USB_VENDOR_ID_MGE, USB_DEVICE_ID_MGE_UPS, HID_QUIRK_NOGET }, + { USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_SURFACE_PRO_2, HID_QUIRK_NO_INIT_REPORTS }, + { USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_2, HID_QUIRK_NO_INIT_REPORTS }, + { USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TOUCH_COVER_2, HID_QUIRK_NO_INIT_REPORTS }, diff --git a/patches.suse/0001-USB-Disable-LPM-on-WD19-s-Realtek-Hub.patch b/patches.suse/0001-USB-Disable-LPM-on-WD19-s-Realtek-Hub.patch new file mode 100644 index 0000000..f80fbc4 --- /dev/null +++ b/patches.suse/0001-USB-Disable-LPM-on-WD19-s-Realtek-Hub.patch @@ -0,0 +1,41 @@ +From b63e48fb50e1ca71db301ca9082befa6f16c55c4 Mon Sep 17 00:00:00 2001 +From: Kai-Heng Feng +Date: Wed, 5 Feb 2020 19:26:33 +0800 +Subject: [PATCH] USB: Disable LPM on WD19's Realtek Hub +Git-commit: b63e48fb50e1ca71db301ca9082befa6f16c55c4 +References: git-fixes +Patch-mainline: v5.6-rc7 + +Realtek Hub (0bda:0x0487) used in Dell Dock WD19 sometimes drops off the +bus when bringing underlying ports from U3 to U0. + +Disabling LPM on the hub during setting link state is not enough, so +let's disable LPM completely for this hub. + +Acked-by: Alan Stern +Signed-off-by: Kai-Heng Feng +Cc: stable +Link: https://lore.kernel.org/r/20200205112633.25995-3-kai.heng.feng@canonical.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Oliver Neukum +--- + drivers/usb/core/quirks.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c +index 2dac3e7cdd97..df6e6156e1d4 100644 +--- a/drivers/usb/core/quirks.c ++++ b/drivers/usb/core/quirks.c +@@ -378,6 +378,9 @@ static const struct usb_device_id usb_quirk_list[] = { + { USB_DEVICE(0x0b05, 0x17e0), .driver_info = + USB_QUIRK_IGNORE_REMOTE_WAKEUP }, + ++ /* Realtek hub in Dell WD19 (Type-C) */ ++ { USB_DEVICE(0x0bda, 0x0487), .driver_info = USB_QUIRK_NO_LPM }, ++ + /* Action Semiconductor flash disk */ + { USB_DEVICE(0x10d6, 0x2200), .driver_info = + USB_QUIRK_STRING_FETCH_255 }, +-- +2.16.4 + diff --git a/patches.suse/0001-USB-Fix-novation-SourceControl-XL-after-suspend.patch b/patches.suse/0001-USB-Fix-novation-SourceControl-XL-after-suspend.patch new file mode 100644 index 0000000..11a6ccf --- /dev/null +++ b/patches.suse/0001-USB-Fix-novation-SourceControl-XL-after-suspend.patch @@ -0,0 +1,37 @@ +From b692056db8ecc7f452b934f016c17348282b7699 Mon Sep 17 00:00:00 2001 +From: Richard Dodd +Date: Wed, 12 Feb 2020 14:22:18 +0000 +Subject: [PATCH] USB: Fix novation SourceControl XL after suspend +Git-commit: b692056db8ecc7f452b934f016c17348282b7699 +References: git-fixes +Patch-mainline: v5.6-rc3 + +Currently, the SourceControl will stay in power-down mode after resuming +from suspend. This patch resets the device after suspend to power it up. + +Signed-off-by: Richard Dodd +Cc: stable +Link: https://lore.kernel.org/r/20200212142220.36892-1-richard.o.dodd@gmail.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Oliver Neukum +--- + drivers/usb/core/quirks.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c +index f27468966a3d..2b24336a72e5 100644 +--- a/drivers/usb/core/quirks.c ++++ b/drivers/usb/core/quirks.c +@@ -449,6 +449,9 @@ static const struct usb_device_id usb_quirk_list[] = { + /* INTEL VALUE SSD */ + { USB_DEVICE(0x8086, 0xf1a5), .driver_info = USB_QUIRK_RESET_RESUME }, + ++ /* novation SoundControl XL */ ++ { USB_DEVICE(0x1235, 0x0061), .driver_info = USB_QUIRK_RESET_RESUME }, ++ + { } /* terminating entry must be last */ + }; + +-- +2.16.4 + diff --git a/patches.suse/0001-USB-cdc-acm-fix-rounding-error-in-TIOCSSERIAL.patch b/patches.suse/0001-USB-cdc-acm-fix-rounding-error-in-TIOCSSERIAL.patch new file mode 100644 index 0000000..bb7aeed --- /dev/null +++ b/patches.suse/0001-USB-cdc-acm-fix-rounding-error-in-TIOCSSERIAL.patch @@ -0,0 +1,78 @@ +From b401f8c4f492cbf74f3f59c9141e5be3071071bb Mon Sep 17 00:00:00 2001 +From: Anthony Mallet +Date: Thu, 12 Mar 2020 14:31:01 +0100 +Subject: [PATCH] USB: cdc-acm: fix rounding error in TIOCSSERIAL +Git-commit: b401f8c4f492cbf74f3f59c9141e5be3071071bb +References: git-fixes +Patch-mainline: v5.6-rc7 + +By default, tty_port_init() initializes those parameters to a multiple +of HZ. For instance in line 69 of tty_port.c: + port->close_delay = (50 * HZ) / 100; +https://github.com/torvalds/linux/blob/master/drivers/tty/tty_port.c#L69 + +With e.g. CONFIG_HZ = 250 (as this is the case for Ubuntu 18.04 +linux-image-4.15.0-37-generic), the default setting for close_delay is +thus 125. + +When ioctl(fd, TIOCGSERIAL, &s) is executed, the setting returned in +user space is '12' (125/10). When ioctl(fd, TIOCSSERIAL, &s) is then +executed with the same setting '12', the value is interpreted as '120' +which is different from the current setting and a EPERM error may be +raised by set_serial_info() if !CAP_SYS_ADMIN. +https://github.com/torvalds/linux/blob/master/drivers/usb/class/cdc-acm.c#L919 + +Fixes: ba2d8ce9db0a6 ("cdc-acm: implement TIOCSSERIAL to avoid blocking close(2)") +Signed-off-by: Anthony Mallet +Cc: stable +Link: https://lore.kernel.org/r/20200312133101.7096-2-anthony.mallet@laas.fr +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Oliver Neukum +--- + drivers/usb/class/cdc-acm.c | 25 ++++++++++++++++--------- + 1 file changed, 16 insertions(+), 9 deletions(-) + +--- a/drivers/usb/class/cdc-acm.c ++++ b/drivers/usb/class/cdc-acm.c +@@ -942,6 +942,7 @@ static int set_serial_info(struct acm *a + { + struct serial_struct new_serial; + unsigned int closing_wait, close_delay; ++ unsigned int old_closing_wait, old_close_delay; + int retval = 0; + + if (copy_from_user(&new_serial, newinfo, sizeof(new_serial))) +@@ -951,18 +952,24 @@ static int set_serial_info(struct acm *a + closing_wait = new_serial.closing_wait == ASYNC_CLOSING_WAIT_NONE ? + ASYNC_CLOSING_WAIT_NONE : new_serial.closing_wait * 10; + ++ /* we must redo the rounding here, so that the values match */ ++ old_close_delay = jiffies_to_msecs(acm->port.close_delay) / 10; ++ old_closing_wait = acm->port.closing_wait == ASYNC_CLOSING_WAIT_NONE ? ++ ASYNC_CLOSING_WAIT_NONE : ++ jiffies_to_msecs(acm->port.closing_wait) / 10; ++ + mutex_lock(&acm->port.mutex); + +- if (!capable(CAP_SYS_ADMIN)) { +- if ((close_delay != acm->port.close_delay) || +- (closing_wait != acm->port.closing_wait)) ++ if ((new_serial.close_delay != old_close_delay) || ++ (new_serial.closing_wait != old_closing_wait)) { ++ if (!capable(CAP_SYS_ADMIN)) + retval = -EPERM; +- else +- retval = -EOPNOTSUPP; +- } else { +- acm->port.close_delay = close_delay; +- acm->port.closing_wait = closing_wait; +- } ++ else { ++ acm->port.close_delay = close_delay; ++ acm->port.closing_wait = closing_wait; ++ } ++ } else ++ retval = -EOPNOTSUPP; + + mutex_unlock(&acm->port.mutex); + return retval; diff --git a/patches.suse/0001-USB-core-add-endpoint-blacklist-quirk.patch b/patches.suse/0001-USB-core-add-endpoint-blacklist-quirk.patch new file mode 100644 index 0000000..4034e0e --- /dev/null +++ b/patches.suse/0001-USB-core-add-endpoint-blacklist-quirk.patch @@ -0,0 +1,121 @@ +From 73f8bda9b5dc1c69df2bc55c0cbb24461a6391a9 Mon Sep 17 00:00:00 2001 +From: Johan Hovold +Date: Mon, 3 Feb 2020 16:38:28 +0100 +Subject: [PATCH] USB: core: add endpoint-blacklist quirk +Git-commit: 73f8bda9b5dc1c69df2bc55c0cbb24461a6391a9 +References: git-fixes +Patch-mainline: v5.6-rc3 + +Add a new device quirk that can be used to blacklist endpoints. + +Since commit 3e4f8e21c4f2 ("USB: core: fix check for duplicate +endpoints") USB core ignores any duplicate endpoints found during +descriptor parsing. + +In order to handle devices where the first interfaces with duplicate +endpoints are the ones that should have their endpoints ignored, we need +to add a blacklist. + +Tested-by: edes +Cc: stable +Signed-off-by: Johan Hovold +Link: https://lore.kernel.org/r/20200203153830.26394-2-johan@kernel.org +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Oliver Neukum +--- + drivers/usb/core/config.c | 11 +++++++++++ + drivers/usb/core/quirks.c | 32 ++++++++++++++++++++++++++++++++ + drivers/usb/core/usb.h | 3 +++ + include/linux/usb/quirks.h | 3 +++ + 4 files changed, 49 insertions(+) + +--- a/drivers/usb/core/config.c ++++ b/drivers/usb/core/config.c +@@ -256,6 +256,7 @@ static int usb_parse_endpoint(struct dev + struct usb_host_interface *ifp, int num_ep, + unsigned char *buffer, int size) + { ++ struct usb_device *udev = to_usb_device(ddev); + unsigned char *buffer0 = buffer; + struct usb_endpoint_descriptor *d; + struct usb_host_endpoint *endpoint; +@@ -297,6 +298,16 @@ static int usb_parse_endpoint(struct dev + goto skip_to_next_endpoint_or_interface_descriptor; + } + ++ /* Ignore blacklisted endpoints */ ++ if (udev->quirks & USB_QUIRK_ENDPOINT_BLACKLIST) { ++ if (usb_endpoint_is_blacklisted(udev, ifp, d)) { ++ dev_warn(ddev, "config %d interface %d altsetting %d has a blacklisted endpoint with address 0x%X, skipping\n", ++ cfgno, inum, asnum, ++ d->bEndpointAddress); ++ goto skip_to_next_endpoint_or_interface_descriptor; ++ } ++ } ++ + endpoint = &ifp->endpoint[ifp->desc.bNumEndpoints]; + ++ifp->desc.bNumEndpoints; + +--- a/drivers/usb/core/quirks.c ++++ b/drivers/usb/core/quirks.c +@@ -318,6 +318,38 @@ static const struct usb_device_id usb_am + { } /* terminating entry must be last */ + }; + ++/* ++ * Entries for blacklisted endpoints that should be ignored when parsing ++ * configuration descriptors. ++ * ++ * Matched for devices with USB_QUIRK_ENDPOINT_BLACKLIST. ++ */ ++static const struct usb_device_id usb_endpoint_blacklist[] = { ++ { } ++}; ++ ++bool usb_endpoint_is_blacklisted(struct usb_device *udev, ++ struct usb_host_interface *intf, ++ struct usb_endpoint_descriptor *epd) ++{ ++ const struct usb_device_id *id; ++ unsigned int address; ++ ++ for (id = usb_endpoint_blacklist; id->match_flags; ++id) { ++ if (!usb_match_device(udev, id)) ++ continue; ++ ++ if (!usb_match_one_id_intf(udev, intf, id)) ++ continue; ++ ++ address = id->driver_info; ++ if (address == epd->bEndpointAddress) ++ return true; ++ } ++ ++ return false; ++} ++ + static bool usb_match_any_interface(struct usb_device *udev, + const struct usb_device_id *id) + { +--- a/drivers/usb/core/usb.h ++++ b/drivers/usb/core/usb.h +@@ -36,6 +36,9 @@ extern void usb_deauthorize_interface(st + extern void usb_authorize_interface(struct usb_interface *); + extern void usb_detect_quirks(struct usb_device *udev); + extern void usb_detect_interface_quirks(struct usb_device *udev); ++extern bool usb_endpoint_is_blacklisted(struct usb_device *udev, ++ struct usb_host_interface *intf, ++ struct usb_endpoint_descriptor *epd); + extern int usb_remove_device(struct usb_device *udev); + + extern int usb_get_device_descriptor(struct usb_device *dev, +--- a/include/linux/usb/quirks.h ++++ b/include/linux/usb/quirks.h +@@ -59,4 +59,7 @@ + /* Device needs a pause after every control message. */ + #define USB_QUIRK_DELAY_CTRL_MSG BIT(13) + ++/* device has blacklisted endpoints */ ++#define USB_QUIRK_ENDPOINT_BLACKLIST BIT(15) ++ + #endif /* __LINUX_USB_QUIRKS_H */ diff --git a/patches.suse/0001-USB-hub-Don-t-record-a-connect-change-event-during-r.patch b/patches.suse/0001-USB-hub-Don-t-record-a-connect-change-event-during-r.patch new file mode 100644 index 0000000..5d39e55 --- /dev/null +++ b/patches.suse/0001-USB-hub-Don-t-record-a-connect-change-event-during-r.patch @@ -0,0 +1,89 @@ +From 8099f58f1ecddf4f374f4828a3dff8397c7cbd74 Mon Sep 17 00:00:00 2001 +From: Alan Stern +Date: Fri, 31 Jan 2020 10:39:26 -0500 +Subject: [PATCH] USB: hub: Don't record a connect-change event during + reset-resume +Git-commit: 8099f58f1ecddf4f374f4828a3dff8397c7cbd74 +References: git-fixes +Patch-mainline: v5.6-rc3 + +Paul Zimmerman reports that his USB Bluetooth adapter sometimes +crashes following system resume, when it receives a +Get-Device-Descriptor request while it is busy doing something else. + +Such a request was added by commit a4f55d8b8c14 ("usb: hub: Check +device descriptor before resusciation"). It gets sent when the hub +driver's work thread checks whether a connect-change event on an +enabled port really indicates a new device has been connected, as +opposed to an old device momentarily disconnecting and then +reconnecting (which can happen with xHCI host controllers, since they +automatically enable connected ports). + +The same kind of thing occurs when a port's power session is lost +during system suspend. When the system wakes up it sees a +connect-change event on the port, and if the child device's +persist_enabled flag was set then hub_activate() sets the device's +reset_resume flag as well as the port's bit in hub->change_bits. The +reset-resume code then takes responsibility for checking that the same +device is still attached to the port, and it does this as part of the +device's resume pathway. By the time the hub driver's work thread +starts up again, the device has already been fully reinitialized and +is busy doing its own thing. There's no need for the work thread to +do the same check a second time, and in fact this unnecessary check is +what caused the problem that Paul observed. + +Note that performing the unnecessary check is not actually a bug. +Devices are supposed to be able to send descriptors back to the host +even when they are busy doing something else. The underlying cause of +Paul's problem lies in his Bluetooth adapter. Nevertheless, we +shouldn't perform the same check twice in a row -- and as a nice side +benefit, removing the extra check allows the Bluetooth adapter to work +more reliably. + +The work thread performs its check when it sees that the port's bit is +set in hub->change_bits. In this situation that bit is interpreted as +though a connect-change event had occurred on the port _after_ the +reset-resume, which is not what actually happened. + +One possible fix would be to make the reset-resume code clear the +port's bit in hub->change_bits. But it seems simpler to just avoid +setting the bit during hub_activate() in the first place. That's what +this patch does. + +(Proving that the patch is correct when CONFIG_PM is disabled requires +a little thought. In that setting hub_activate() will be called only +for initialization and resets, since there won't be any resumes or +reset-resumes. During initialization and hub resets the hub doesn't +have any child devices, and so this code path never gets executed.) + +Reported-and-tested-by: Paul Zimmerman +Signed-off-by: Alan Stern +Link: https://marc.info/?t=157949360700001&r=1&w=2 +CC: David Heinzelmann +CC: +Link: https://lore.kernel.org/r/Pine.LNX.4.44L0.2001311037460.1577-100000@iolanthe.rowland.org +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Oliver Neukum +--- + drivers/usb/core/hub.c | 5 ----- + 1 file changed, 5 deletions(-) + +diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c +index de94fa4a4ca7..1d212f82c69b 100644 +--- a/drivers/usb/core/hub.c ++++ b/drivers/usb/core/hub.c +@@ -1219,11 +1219,6 @@ static void hub_activate(struct usb_hub *hub, enum hub_activation_type type) + #ifdef CONFIG_PM + udev->reset_resume = 1; + #endif +- /* Don't set the change_bits when the device +- * was powered off. +- */ +- if (test_bit(port1, hub->power_bits)) +- set_bit(port1, hub->change_bits); + + } else { + /* The power session is gone; tell hub_wq */ +-- +2.16.4 + diff --git a/patches.suse/0001-USB-misc-iowarrior-add-support-for-2-OEMed-devices.patch b/patches.suse/0001-USB-misc-iowarrior-add-support-for-2-OEMed-devices.patch new file mode 100644 index 0000000..ddc2554 --- /dev/null +++ b/patches.suse/0001-USB-misc-iowarrior-add-support-for-2-OEMed-devices.patch @@ -0,0 +1,91 @@ +From 461d8deb26a7d70254bc0391feb4fd8a95e674e8 Mon Sep 17 00:00:00 2001 +From: Greg Kroah-Hartman +Date: Tue, 11 Feb 2020 20:04:21 -0800 +Subject: [PATCH] USB: misc: iowarrior: add support for 2 OEMed devices +Git-commit: 461d8deb26a7d70254bc0391feb4fd8a95e674e8 +References: git-fixes +Patch-mainline: v5.6-rc3 + +Add support for two OEM devices that are identical to existing +IO-Warrior devices, except for the USB device id. + +Cc: Christoph Jung +Cc: stable +Link: https://lore.kernel.org/r/20200212040422.2991-1-gregkh@linuxfoundation.org +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Oliver Neukum +--- + drivers/usb/misc/iowarrior.c | 15 +++++++++++++-- + 1 file changed, 13 insertions(+), 2 deletions(-) + +diff --git a/drivers/usb/misc/iowarrior.c b/drivers/usb/misc/iowarrior.c +index dce44fbf031f..990acbe14852 100644 +--- a/drivers/usb/misc/iowarrior.c ++++ b/drivers/usb/misc/iowarrior.c +@@ -34,6 +34,10 @@ + /* full speed iowarrior */ + #define USB_DEVICE_ID_CODEMERCS_IOW56 0x1503 + ++/* OEMed devices */ ++#define USB_DEVICE_ID_CODEMERCS_IOW24SAG 0x158a ++#define USB_DEVICE_ID_CODEMERCS_IOW56AM 0x158b ++ + /* Get a minor range for your devices from the usb maintainer */ + #ifdef CONFIG_USB_DYNAMIC_MINORS + #define IOWARRIOR_MINOR_BASE 0 +@@ -133,6 +137,8 @@ static const struct usb_device_id iowarrior_ids[] = { + {USB_DEVICE(USB_VENDOR_ID_CODEMERCS, USB_DEVICE_ID_CODEMERCS_IOWPV1)}, + {USB_DEVICE(USB_VENDOR_ID_CODEMERCS, USB_DEVICE_ID_CODEMERCS_IOWPV2)}, + {USB_DEVICE(USB_VENDOR_ID_CODEMERCS, USB_DEVICE_ID_CODEMERCS_IOW56)}, ++ {USB_DEVICE(USB_VENDOR_ID_CODEMERCS, USB_DEVICE_ID_CODEMERCS_IOW24SAG)}, ++ {USB_DEVICE(USB_VENDOR_ID_CODEMERCS, USB_DEVICE_ID_CODEMERCS_IOW56AM)}, + {} /* Terminating entry */ + }; + MODULE_DEVICE_TABLE(usb, iowarrior_ids); +@@ -357,6 +363,7 @@ static ssize_t iowarrior_write(struct file *file, + } + switch (dev->product_id) { + case USB_DEVICE_ID_CODEMERCS_IOW24: ++ case USB_DEVICE_ID_CODEMERCS_IOW24SAG: + case USB_DEVICE_ID_CODEMERCS_IOWPV1: + case USB_DEVICE_ID_CODEMERCS_IOWPV2: + case USB_DEVICE_ID_CODEMERCS_IOW40: +@@ -371,6 +378,7 @@ static ssize_t iowarrior_write(struct file *file, + goto exit; + break; + case USB_DEVICE_ID_CODEMERCS_IOW56: ++ case USB_DEVICE_ID_CODEMERCS_IOW56AM: + /* The IOW56 uses asynchronous IO and more urbs */ + if (atomic_read(&dev->write_busy) == MAX_WRITES_IN_FLIGHT) { + /* Wait until we are below the limit for submitted urbs */ +@@ -493,6 +501,7 @@ static long iowarrior_ioctl(struct file *file, unsigned int cmd, + switch (cmd) { + case IOW_WRITE: + if (dev->product_id == USB_DEVICE_ID_CODEMERCS_IOW24 || ++ dev->product_id == USB_DEVICE_ID_CODEMERCS_IOW24SAG || + dev->product_id == USB_DEVICE_ID_CODEMERCS_IOWPV1 || + dev->product_id == USB_DEVICE_ID_CODEMERCS_IOWPV2 || + dev->product_id == USB_DEVICE_ID_CODEMERCS_IOW40) { +@@ -767,7 +776,8 @@ static int iowarrior_probe(struct usb_interface *interface, + goto error; + } + +- if (dev->product_id == USB_DEVICE_ID_CODEMERCS_IOW56) { ++ if ((dev->product_id == USB_DEVICE_ID_CODEMERCS_IOW56) || ++ (dev->product_id == USB_DEVICE_ID_CODEMERCS_IOW56AM)) { + res = usb_find_last_int_out_endpoint(iface_desc, + &dev->int_out_endpoint); + if (res) { +@@ -780,7 +790,8 @@ static int iowarrior_probe(struct usb_interface *interface, + /* we have to check the report_size often, so remember it in the endianness suitable for our machine */ + dev->report_size = usb_endpoint_maxp(dev->int_in_endpoint); + if ((dev->interface->cur_altsetting->desc.bInterfaceNumber == 0) && +- (dev->product_id == USB_DEVICE_ID_CODEMERCS_IOW56)) ++ ((dev->product_id == USB_DEVICE_ID_CODEMERCS_IOW56) || ++ (dev->product_id == USB_DEVICE_ID_CODEMERCS_IOW56AM))) + /* IOWarrior56 has wMaxPacketSize different from report size */ + dev->report_size = 7; + +-- +2.16.4 + diff --git a/patches.suse/0001-USB-misc-iowarrior-add-support-for-the-100-device.patch b/patches.suse/0001-USB-misc-iowarrior-add-support-for-the-100-device.patch new file mode 100644 index 0000000..20801a0 --- /dev/null +++ b/patches.suse/0001-USB-misc-iowarrior-add-support-for-the-100-device.patch @@ -0,0 +1,72 @@ +From bab5417f5f0118ce914bc5b2f8381e959e891155 Mon Sep 17 00:00:00 2001 +From: Greg Kroah-Hartman +Date: Fri, 14 Feb 2020 08:11:48 -0800 +Subject: [PATCH] USB: misc: iowarrior: add support for the 100 device +Git-commit: bab5417f5f0118ce914bc5b2f8381e959e891155 +References: git-fixes +Patch-mainline: v5.6-rc3 + +Add a new device id for the 100 devie. It has 4 interfaces like the 28 +and 28L devices but a larger endpoint so more I/O pins. + +Cc: Christoph Jung +Cc: stable +Signed-off-by: Greg Kroah-Hartman +Link: https://lore.kernel.org/r/20200214161148.GA3963518@kroah.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Oliver Neukum +--- + drivers/usb/misc/iowarrior.c | 9 +++++++-- + 1 file changed, 7 insertions(+), 2 deletions(-) + +diff --git a/drivers/usb/misc/iowarrior.c b/drivers/usb/misc/iowarrior.c +index d20b60acfe8a..dce20301e367 100644 +--- a/drivers/usb/misc/iowarrior.c ++++ b/drivers/usb/misc/iowarrior.c +@@ -36,6 +36,7 @@ + /* fuller speed iowarrior */ + #define USB_DEVICE_ID_CODEMERCS_IOW28 0x1504 + #define USB_DEVICE_ID_CODEMERCS_IOW28L 0x1505 ++#define USB_DEVICE_ID_CODEMERCS_IOW100 0x1506 + + /* OEMed devices */ + #define USB_DEVICE_ID_CODEMERCS_IOW24SAG 0x158a +@@ -144,6 +145,7 @@ static const struct usb_device_id iowarrior_ids[] = { + {USB_DEVICE(USB_VENDOR_ID_CODEMERCS, USB_DEVICE_ID_CODEMERCS_IOW56AM)}, + {USB_DEVICE(USB_VENDOR_ID_CODEMERCS, USB_DEVICE_ID_CODEMERCS_IOW28)}, + {USB_DEVICE(USB_VENDOR_ID_CODEMERCS, USB_DEVICE_ID_CODEMERCS_IOW28L)}, ++ {USB_DEVICE(USB_VENDOR_ID_CODEMERCS, USB_DEVICE_ID_CODEMERCS_IOW100)}, + {} /* Terminating entry */ + }; + MODULE_DEVICE_TABLE(usb, iowarrior_ids); +@@ -386,6 +388,7 @@ static ssize_t iowarrior_write(struct file *file, + case USB_DEVICE_ID_CODEMERCS_IOW56AM: + case USB_DEVICE_ID_CODEMERCS_IOW28: + case USB_DEVICE_ID_CODEMERCS_IOW28L: ++ case USB_DEVICE_ID_CODEMERCS_IOW100: + /* The IOW56 uses asynchronous IO and more urbs */ + if (atomic_read(&dev->write_busy) == MAX_WRITES_IN_FLIGHT) { + /* Wait until we are below the limit for submitted urbs */ +@@ -786,7 +789,8 @@ static int iowarrior_probe(struct usb_interface *interface, + if ((dev->product_id == USB_DEVICE_ID_CODEMERCS_IOW56) || + (dev->product_id == USB_DEVICE_ID_CODEMERCS_IOW56AM) || + (dev->product_id == USB_DEVICE_ID_CODEMERCS_IOW28) || +- (dev->product_id == USB_DEVICE_ID_CODEMERCS_IOW28L)) { ++ (dev->product_id == USB_DEVICE_ID_CODEMERCS_IOW28L) || ++ (dev->product_id == USB_DEVICE_ID_CODEMERCS_IOW100)) { + res = usb_find_last_int_out_endpoint(iface_desc, + &dev->int_out_endpoint); + if (res) { +@@ -802,7 +806,8 @@ static int iowarrior_probe(struct usb_interface *interface, + ((dev->product_id == USB_DEVICE_ID_CODEMERCS_IOW56) || + (dev->product_id == USB_DEVICE_ID_CODEMERCS_IOW56AM) || + (dev->product_id == USB_DEVICE_ID_CODEMERCS_IOW28) || +- (dev->product_id == USB_DEVICE_ID_CODEMERCS_IOW28L))) ++ (dev->product_id == USB_DEVICE_ID_CODEMERCS_IOW28L) || ++ (dev->product_id == USB_DEVICE_ID_CODEMERCS_IOW100))) + /* IOWarrior56 has wMaxPacketSize different from report size */ + dev->report_size = 7; + +-- +2.16.4 + diff --git a/patches.suse/0001-USB-misc-iowarrior-add-support-for-the-28-and-28L-de.patch b/patches.suse/0001-USB-misc-iowarrior-add-support-for-the-28-and-28L-de.patch new file mode 100644 index 0000000..62e4589 --- /dev/null +++ b/patches.suse/0001-USB-misc-iowarrior-add-support-for-the-28-and-28L-de.patch @@ -0,0 +1,78 @@ +From 5f6f8da2d7b5a431d3f391d0d73ace8edfb42af7 Mon Sep 17 00:00:00 2001 +From: Greg Kroah-Hartman +Date: Tue, 11 Feb 2020 20:04:22 -0800 +Subject: [PATCH] USB: misc: iowarrior: add support for the 28 and 28L devices +Git-commit: 5f6f8da2d7b5a431d3f391d0d73ace8edfb42af7 +References: git-fixes +Patch-mainline: v5.6-rc3 + +Add new device ids for the 28 and 28L devices. These have 4 interfaces +instead of 2, but the driver binds the same, so the driver changes are +minimal. + +Cc: Christoph Jung +Cc: stable +Link: https://lore.kernel.org/r/20200212040422.2991-2-gregkh@linuxfoundation.org +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Oliver Neukum +--- + drivers/usb/misc/iowarrior.c | 15 +++++++++++++-- + 1 file changed, 13 insertions(+), 2 deletions(-) + +diff --git a/drivers/usb/misc/iowarrior.c b/drivers/usb/misc/iowarrior.c +index 990acbe14852..d20b60acfe8a 100644 +--- a/drivers/usb/misc/iowarrior.c ++++ b/drivers/usb/misc/iowarrior.c +@@ -33,6 +33,9 @@ + #define USB_DEVICE_ID_CODEMERCS_IOWPV2 0x1512 + /* full speed iowarrior */ + #define USB_DEVICE_ID_CODEMERCS_IOW56 0x1503 ++/* fuller speed iowarrior */ ++#define USB_DEVICE_ID_CODEMERCS_IOW28 0x1504 ++#define USB_DEVICE_ID_CODEMERCS_IOW28L 0x1505 + + /* OEMed devices */ + #define USB_DEVICE_ID_CODEMERCS_IOW24SAG 0x158a +@@ -139,6 +142,8 @@ static const struct usb_device_id iowarrior_ids[] = { + {USB_DEVICE(USB_VENDOR_ID_CODEMERCS, USB_DEVICE_ID_CODEMERCS_IOW56)}, + {USB_DEVICE(USB_VENDOR_ID_CODEMERCS, USB_DEVICE_ID_CODEMERCS_IOW24SAG)}, + {USB_DEVICE(USB_VENDOR_ID_CODEMERCS, USB_DEVICE_ID_CODEMERCS_IOW56AM)}, ++ {USB_DEVICE(USB_VENDOR_ID_CODEMERCS, USB_DEVICE_ID_CODEMERCS_IOW28)}, ++ {USB_DEVICE(USB_VENDOR_ID_CODEMERCS, USB_DEVICE_ID_CODEMERCS_IOW28L)}, + {} /* Terminating entry */ + }; + MODULE_DEVICE_TABLE(usb, iowarrior_ids); +@@ -379,6 +384,8 @@ static ssize_t iowarrior_write(struct file *file, + break; + case USB_DEVICE_ID_CODEMERCS_IOW56: + case USB_DEVICE_ID_CODEMERCS_IOW56AM: ++ case USB_DEVICE_ID_CODEMERCS_IOW28: ++ case USB_DEVICE_ID_CODEMERCS_IOW28L: + /* The IOW56 uses asynchronous IO and more urbs */ + if (atomic_read(&dev->write_busy) == MAX_WRITES_IN_FLIGHT) { + /* Wait until we are below the limit for submitted urbs */ +@@ -777,7 +784,9 @@ static int iowarrior_probe(struct usb_interface *interface, + } + + if ((dev->product_id == USB_DEVICE_ID_CODEMERCS_IOW56) || +- (dev->product_id == USB_DEVICE_ID_CODEMERCS_IOW56AM)) { ++ (dev->product_id == USB_DEVICE_ID_CODEMERCS_IOW56AM) || ++ (dev->product_id == USB_DEVICE_ID_CODEMERCS_IOW28) || ++ (dev->product_id == USB_DEVICE_ID_CODEMERCS_IOW28L)) { + res = usb_find_last_int_out_endpoint(iface_desc, + &dev->int_out_endpoint); + if (res) { +@@ -791,7 +800,9 @@ static int iowarrior_probe(struct usb_interface *interface, + dev->report_size = usb_endpoint_maxp(dev->int_in_endpoint); + if ((dev->interface->cur_altsetting->desc.bInterfaceNumber == 0) && + ((dev->product_id == USB_DEVICE_ID_CODEMERCS_IOW56) || +- (dev->product_id == USB_DEVICE_ID_CODEMERCS_IOW56AM))) ++ (dev->product_id == USB_DEVICE_ID_CODEMERCS_IOW56AM) || ++ (dev->product_id == USB_DEVICE_ID_CODEMERCS_IOW28) || ++ (dev->product_id == USB_DEVICE_ID_CODEMERCS_IOW28L))) + /* IOWarrior56 has wMaxPacketSize different from report size */ + dev->report_size = 7; + +-- +2.16.4 + diff --git a/patches.suse/0001-USB-quirks-blacklist-duplicate-ep-on-Sound-Devices-U.patch b/patches.suse/0001-USB-quirks-blacklist-duplicate-ep-on-Sound-Devices-U.patch new file mode 100644 index 0000000..092f3c8 --- /dev/null +++ b/patches.suse/0001-USB-quirks-blacklist-duplicate-ep-on-Sound-Devices-U.patch @@ -0,0 +1,150 @@ +From bdd1b147b8026df0e4260b387026b251d888ed01 Mon Sep 17 00:00:00 2001 +From: Johan Hovold +Date: Mon, 3 Feb 2020 16:38:29 +0100 +Subject: [PATCH] USB: quirks: blacklist duplicate ep on Sound Devices USBPre2 +Git-commit: bdd1b147b8026df0e4260b387026b251d888ed01 +Patch-mainline: v5.6-rc3 +References: git-fixes + +This device has a broken vendor-specific altsetting for interface 1, +where endpoint 0x85 is declared as an isochronous endpoint despite being +used by interface 2 for audio capture. + +Device Descriptor: + bLength 18 + bDescriptorType 1 + bcdUSB 2.00 + bDeviceClass 239 Miscellaneous Device + bDeviceSubClass 2 + bDeviceProtocol 1 Interface Association + bMaxPacketSize0 64 + idVendor 0x0926 + idProduct 0x0202 + bcdDevice 1.00 + iManufacturer 1 Sound Devices + iProduct 2 USBPre2 + iSerial 3 [...] + bNumConfigurations 1 + +[...] + + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 1 + bAlternateSetting 3 + bNumEndpoints 2 + bInterfaceClass 255 Vendor Specific Class + bInterfaceSubClass 0 + bInterfaceProtocol 0 + iInterface 0 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x85 EP 5 IN + bmAttributes 5 + Transfer Type Isochronous + Synch Type Asynchronous + Usage Type Data + wMaxPacketSize 0x0126 1x 294 bytes + bInterval 1 + +[...] + + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 2 + bAlternateSetting 1 + bNumEndpoints 1 + bInterfaceClass 1 Audio + bInterfaceSubClass 2 Streaming + bInterfaceProtocol 0 + iInterface 0 + AudioStreaming Interface Descriptor: + bLength 7 + bDescriptorType 36 + bDescriptorSubtype 1 (AS_GENERAL) + bTerminalLink 4 + bDelay 1 frames + wFormatTag 0x0001 PCM + AudioStreaming Interface Descriptor: + bLength 26 + bDescriptorType 36 + bDescriptorSubtype 2 (FORMAT_TYPE) + bFormatType 1 (FORMAT_TYPE_I) + bNrChannels 2 + bSubframeSize 2 + bBitResolution 16 + bSamFreqType 6 Discrete + tSamFreq[ 0] 8000 + tSamFreq[ 1] 16000 + tSamFreq[ 2] 24000 + tSamFreq[ 3] 32000 + tSamFreq[ 4] 44100 + tSamFreq[ 5] 48000 + Endpoint Descriptor: + bLength 9 + bDescriptorType 5 + bEndpointAddress 0x85 EP 5 IN + bmAttributes 5 + Transfer Type Isochronous + Synch Type Asynchronous + Usage Type Data + wMaxPacketSize 0x0126 1x 294 bytes + bInterval 4 + bRefresh 0 + bSynchAddress 0 + AudioStreaming Endpoint Descriptor: + bLength 7 + bDescriptorType 37 + bDescriptorSubtype 1 (EP_GENERAL) + bmAttributes 0x01 + Sampling Frequency + bLockDelayUnits 2 Decoded PCM samples + wLockDelay 0x0000 + +Since commit 3e4f8e21c4f2 ("USB: core: fix check for duplicate +endpoints") USB core ignores any duplicate endpoints found during +descriptor parsing, but in this case we need to ignore the first +instance in order to avoid breaking the audio capture interface. + +Fixes: 3e4f8e21c4f2 ("USB: core: fix check for duplicate endpoints") +Cc: stable +Reported-by: edes +Tested-by: edes +Link: https://lore.kernel.org/r/20200201105829.5682c887@acme7.acmenet +Signed-off-by: Johan Hovold +Link: https://lore.kernel.org/r/20200203153830.26394-3-johan@kernel.org +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Oliver Neukum +--- + drivers/usb/core/quirks.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c +index 56c8dffaf5f5..f27468966a3d 100644 +--- a/drivers/usb/core/quirks.c ++++ b/drivers/usb/core/quirks.c +@@ -354,6 +354,10 @@ static const struct usb_device_id usb_quirk_list[] = { + { USB_DEVICE(0x0904, 0x6103), .driver_info = + USB_QUIRK_LINEAR_FRAME_INTR_BINTERVAL }, + ++ /* Sound Devices USBPre2 */ ++ { USB_DEVICE(0x0926, 0x0202), .driver_info = ++ USB_QUIRK_ENDPOINT_BLACKLIST }, ++ + /* Keytouch QWERTY Panel keyboard */ + { USB_DEVICE(0x0926, 0x3333), .driver_info = + USB_QUIRK_CONFIG_INTF_STRINGS }, +@@ -479,6 +483,7 @@ static const struct usb_device_id usb_amd_resume_quirk_list[] = { + * Matched for devices with USB_QUIRK_ENDPOINT_BLACKLIST. + */ + static const struct usb_device_id usb_endpoint_blacklist[] = { ++ { USB_DEVICE_INTERFACE_NUMBER(0x0926, 0x0202, 1), .driver_info = 0x85 }, + { } + }; + +-- +2.16.4 + diff --git a/patches.suse/0001-USB-serial-option-add-ME910G1-ECM-composition-0x110b.patch b/patches.suse/0001-USB-serial-option-add-ME910G1-ECM-composition-0x110b.patch new file mode 100644 index 0000000..6b6d49e --- /dev/null +++ b/patches.suse/0001-USB-serial-option-add-ME910G1-ECM-composition-0x110b.patch @@ -0,0 +1,35 @@ +From 8e852a7953be2a6ee371449f7257fe15ace6a1fc Mon Sep 17 00:00:00 2001 +From: Daniele Palmas +Date: Wed, 4 Mar 2020 11:43:10 +0100 +Subject: [PATCH] USB: serial: option: add ME910G1 ECM composition 0x110b +Git-commit: 8e852a7953be2a6ee371449f7257fe15ace6a1fc +References: git-fixes +Patch-mainline: v5.6-rc7 + +Add ME910G1 ECM composition 0x110b: tty, tty, tty, ecm + +Signed-off-by: Daniele Palmas +Link: https://lore.kernel.org/r/20200304104310.2938-1-dnlplm@gmail.com +Cc: stable +Signed-off-by: Johan Hovold +Signed-off-by: Oliver Neukum +--- + drivers/usb/serial/option.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c +index 084cc2fff3ae..0b5dcf973d94 100644 +--- a/drivers/usb/serial/option.c ++++ b/drivers/usb/serial/option.c +@@ -1183,6 +1183,8 @@ static const struct usb_device_id option_ids[] = { + .driver_info = NCTRL(0) }, + { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x110a, 0xff), /* Telit ME910G1 */ + .driver_info = NCTRL(0) | RSVD(3) }, ++ { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x110b, 0xff), /* Telit ME910G1 (ECM) */ ++ .driver_info = NCTRL(0) }, + { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_LE910), + .driver_info = NCTRL(0) | RSVD(1) | RSVD(2) }, + { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_LE910_USBCFG4), +-- +2.16.4 + diff --git a/patches.suse/0001-USB-serial-pl2303-add-device-id-for-HP-LD381.patch b/patches.suse/0001-USB-serial-pl2303-add-device-id-for-HP-LD381.patch new file mode 100644 index 0000000..e896058 --- /dev/null +++ b/patches.suse/0001-USB-serial-pl2303-add-device-id-for-HP-LD381.patch @@ -0,0 +1,47 @@ +From cecc113c1af0dd41ccf265c1fdb84dbd05e63423 Mon Sep 17 00:00:00 2001 +From: Scott Chen +Date: Wed, 11 Mar 2020 14:14:23 +0800 +Subject: [PATCH] USB: serial: pl2303: add device-id for HP LD381 +Git-commit: cecc113c1af0dd41ccf265c1fdb84dbd05e63423 +References: git-fixes +Patch-mainline: v5.6-rc7 + +Add a device id for HP LD381 Display +LD381: 03f0:0f7f + +Signed-off-by: Scott Chen +Cc: stable +Signed-off-by: Johan Hovold +Signed-off-by: Oliver Neukum +--- + drivers/usb/serial/pl2303.c | 1 + + drivers/usb/serial/pl2303.h | 1 + + 2 files changed, 2 insertions(+) + +diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c +index aab737e1e7b6..c5a2995dfa2e 100644 +--- a/drivers/usb/serial/pl2303.c ++++ b/drivers/usb/serial/pl2303.c +@@ -99,6 +99,7 @@ static const struct usb_device_id id_table[] = { + { USB_DEVICE(SUPERIAL_VENDOR_ID, SUPERIAL_PRODUCT_ID) }, + { USB_DEVICE(HP_VENDOR_ID, HP_LD220_PRODUCT_ID) }, + { USB_DEVICE(HP_VENDOR_ID, HP_LD220TA_PRODUCT_ID) }, ++ { USB_DEVICE(HP_VENDOR_ID, HP_LD381_PRODUCT_ID) }, + { USB_DEVICE(HP_VENDOR_ID, HP_LD960_PRODUCT_ID) }, + { USB_DEVICE(HP_VENDOR_ID, HP_LD960TA_PRODUCT_ID) }, + { USB_DEVICE(HP_VENDOR_ID, HP_LCM220_PRODUCT_ID) }, +diff --git a/drivers/usb/serial/pl2303.h b/drivers/usb/serial/pl2303.h +index a019ea7e6e0e..52db5519aaf0 100644 +--- a/drivers/usb/serial/pl2303.h ++++ b/drivers/usb/serial/pl2303.h +@@ -130,6 +130,7 @@ + #define HP_LM920_PRODUCT_ID 0x026b + #define HP_TD620_PRODUCT_ID 0x0956 + #define HP_LD960_PRODUCT_ID 0x0b39 ++#define HP_LD381_PRODUCT_ID 0x0f7f + #define HP_LCM220_PRODUCT_ID 0x3139 + #define HP_LCM960_PRODUCT_ID 0x3239 + #define HP_LD220_PRODUCT_ID 0x3524 +-- +2.16.4 + diff --git a/patches.suse/0001-amdgpu-gmc_v9-save-restore-sdpif-regs-during-S3.patch b/patches.suse/0001-amdgpu-gmc_v9-save-restore-sdpif-regs-during-S3.patch new file mode 100644 index 0000000..e69881d --- /dev/null +++ b/patches.suse/0001-amdgpu-gmc_v9-save-restore-sdpif-regs-during-S3.patch @@ -0,0 +1,121 @@ +From a3ed353cf8015ba84a0407a5dc3ffee038166ab0 Mon Sep 17 00:00:00 2001 +From: Shirish S +Date: Mon, 27 Jan 2020 16:35:24 +0530 +Subject: amdgpu/gmc_v9: save/restore sdpif regs during S3 +Git-commit: a3ed353cf8015ba84a0407a5dc3ffee038166ab0 +Patch-mainline: v5.6-rc4 +References: bsc#1113956 + +fixes S3 issue with IOMMU + S/G enabled @ 64M VRAM. + +Suggested-by: Alex Deucher +Signed-off-by: Shirish S +Reviewed-by: Alex Deucher +Signed-off-by: Alex Deucher +Cc: stable@vger.kernel.org +Acked-by: Thomas Zimmermann +--- + drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h | 1 + + drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c | 37 ++++++++++++++++++- + .../include/asic_reg/dce/dce_12_0_offset.h | 2 + + 3 files changed, 39 insertions(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h +index d3c27a3c43f6..7546da0cc70c 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h +@@ -195,6 +195,7 @@ struct amdgpu_gmc { + uint32_t srbm_soft_reset; + bool prt_warning; + uint64_t stolen_size; ++ uint32_t sdpif_register; + /* apertures */ + u64 shared_aperture_start; + u64 shared_aperture_end; +diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c +index 90216abf14a4..cc0c273a86f9 100644 +--- a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c ++++ b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c +@@ -1271,6 +1271,19 @@ static void gmc_v9_0_init_golden_registers(struct amdgpu_device *adev) + } + } + ++/** ++ * gmc_v9_0_restore_registers - restores regs ++ * ++ * @adev: amdgpu_device pointer ++ * ++ * This restores register values, saved at suspend. ++ */ ++static void gmc_v9_0_restore_registers(struct amdgpu_device *adev) ++{ ++ if (adev->asic_type == CHIP_RAVEN) ++ WREG32(mmDCHUBBUB_SDPIF_MMIO_CNTRL_0, adev->gmc.sdpif_register); ++} ++ + /** + * gmc_v9_0_gart_enable - gart enable + * +@@ -1376,6 +1389,20 @@ static int gmc_v9_0_hw_init(void *handle) + return r; + } + ++/** ++ * gmc_v9_0_save_registers - saves regs ++ * ++ * @adev: amdgpu_device pointer ++ * ++ * This saves potential register values that should be ++ * restored upon resume ++ */ ++static void gmc_v9_0_save_registers(struct amdgpu_device *adev) ++{ ++ if (adev->asic_type == CHIP_RAVEN) ++ adev->gmc.sdpif_register = RREG32(mmDCHUBBUB_SDPIF_MMIO_CNTRL_0); ++} ++ + /** + * gmc_v9_0_gart_disable - gart disable + * +@@ -1412,9 +1439,16 @@ static int gmc_v9_0_hw_fini(void *handle) + + static int gmc_v9_0_suspend(void *handle) + { ++ int r; + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + +- return gmc_v9_0_hw_fini(adev); ++ r = gmc_v9_0_hw_fini(adev); ++ if (r) ++ return r; ++ ++ gmc_v9_0_save_registers(adev); ++ ++ return 0; + } + + static int gmc_v9_0_resume(void *handle) +@@ -1422,6 +1456,7 @@ static int gmc_v9_0_resume(void *handle) + int r; + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + ++ gmc_v9_0_restore_registers(adev); + r = gmc_v9_0_hw_init(adev); + if (r) + return r; +diff --git a/drivers/gpu/drm/amd/include/asic_reg/dce/dce_12_0_offset.h b/drivers/gpu/drm/amd/include/asic_reg/dce/dce_12_0_offset.h +index b6f74bf4af02..27bb8c1ab858 100644 +--- a/drivers/gpu/drm/amd/include/asic_reg/dce/dce_12_0_offset.h ++++ b/drivers/gpu/drm/amd/include/asic_reg/dce/dce_12_0_offset.h +@@ -7376,6 +7376,8 @@ + #define mmCRTC4_CRTC_DRR_CONTROL 0x0f3e + #define mmCRTC4_CRTC_DRR_CONTROL_BASE_IDX 2 + ++#define mmDCHUBBUB_SDPIF_MMIO_CNTRL_0 0x395d ++#define mmDCHUBBUB_SDPIF_MMIO_CNTRL_0_BASE_IDX 2 + + // addressBlock: dce_dc_fmt4_dispdec + // base address: 0x2000 +-- +2.25.1 + diff --git a/patches.suse/0001-btrfs-Introduce-support-for-FSID-change-without-meta.patch b/patches.suse/0001-btrfs-Introduce-support-for-FSID-change-without-meta.patch index b8ed4ee..a7a6520 100644 --- a/patches.suse/0001-btrfs-Introduce-support-for-FSID-change-without-meta.patch +++ b/patches.suse/0001-btrfs-Introduce-support-for-FSID-change-without-meta.patch @@ -35,20 +35,18 @@ and switches all users of the fsid to the new logic. Signed-off-by: Nikolay Borisov --- - fs/btrfs/ctree.c | 10 ++--- - fs/btrfs/ctree.h | 11 ++++-- - fs/btrfs/disk-io.c | 31 ++++++++++++--- - fs/btrfs/volumes.c | 70 ++++++++++++++++++++++++++------- - fs/btrfs/volumes.h | 1 + - include/uapi/linux/btrfs.h | 1 + - include/uapi/linux/btrfs_tree.h | 1 + + fs/btrfs/ctree.c | 10 ++--- + fs/btrfs/ctree.h | 11 ++++-- + fs/btrfs/disk-io.c | 31 ++++++++++++++--- + fs/btrfs/volumes.c | 70 +++++++++++++++++++++++++++++++--------- + fs/btrfs/volumes.h | 1 + include/uapi/linux/btrfs.h | 1 + include/uapi/linux/btrfs_tree.h | 1 7 files changed, 96 insertions(+), 29 deletions(-) -diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c -index f70741084f2d..c4a39eef23a0 100644 --- a/fs/btrfs/ctree.c +++ b/fs/btrfs/ctree.c -@@ -275,7 +275,7 @@ int btrfs_copy_root(struct btrfs_trans_handle *trans, +@@ -240,7 +240,7 @@ int btrfs_copy_root(struct btrfs_trans_h else btrfs_set_header_owner(cow, new_root_objectid); @@ -57,7 +55,7 @@ index f70741084f2d..c4a39eef23a0 100644 WARN_ON(btrfs_header_generation(buf) > trans->transid); if (new_root_objectid == BTRFS_TREE_RELOC_OBJECTID) -@@ -1150,7 +1150,7 @@ static noinline int __btrfs_cow_block(struct btrfs_trans_handle *trans, +@@ -1152,7 +1152,7 @@ static noinline int __btrfs_cow_block(st else btrfs_set_header_owner(cow, root->root_key.objectid); @@ -66,7 +64,7 @@ index f70741084f2d..c4a39eef23a0 100644 ret = update_ref_for_cow(trans, root, buf, cow, &last_ref); if (ret) { -@@ -3392,7 +3392,7 @@ static noinline int insert_new_root(struct btrfs_trans_handle *trans, +@@ -3444,7 +3444,7 @@ static noinline int insert_new_root(stru btrfs_set_header_backref_rev(c, BTRFS_MIXED_BACKREF_REV); btrfs_set_header_owner(c, root->root_key.objectid); @@ -75,7 +73,7 @@ index f70741084f2d..c4a39eef23a0 100644 write_extent_buffer_chunk_tree_uuid(c, fs_info->chunk_tree_uuid); btrfs_set_node_key(c, &lower_key, 0); -@@ -3527,7 +3527,7 @@ static noinline int split_node(struct btrfs_trans_handle *trans, +@@ -3579,7 +3579,7 @@ static noinline int split_node(struct bt btrfs_set_header_generation(split, trans->transid); btrfs_set_header_backref_rev(split, BTRFS_MIXED_BACKREF_REV); btrfs_set_header_owner(split, root->root_key.objectid); @@ -84,7 +82,7 @@ index f70741084f2d..c4a39eef23a0 100644 write_extent_buffer_chunk_tree_uuid(split, fs_info->chunk_tree_uuid); ret = tree_mod_log_eb_copy(fs_info, split, c, 0, mid, c_nritems - mid); -@@ -4320,7 +4320,7 @@ static noinline int split_leaf(struct btrfs_trans_handle *trans, +@@ -4372,7 +4372,7 @@ again: btrfs_set_header_backref_rev(right, BTRFS_MIXED_BACKREF_REV); btrfs_set_header_owner(right, root->root_key.objectid); btrfs_set_header_level(right, 0); @@ -93,11 +91,9 @@ index f70741084f2d..c4a39eef23a0 100644 write_extent_buffer_chunk_tree_uuid(right, fs_info->chunk_tree_uuid); if (split == 0) { -diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h -index da67736c382d..0076d2ecb2a0 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h -@@ -208,7 +208,7 @@ struct btrfs_root_backup { +@@ -209,7 +209,7 @@ struct btrfs_root_backup { struct btrfs_super_block { u8 csum[BTRFS_CSUM_SIZE]; /* the first 4 fields must match struct btrfs_header */ @@ -106,7 +102,7 @@ index da67736c382d..0076d2ecb2a0 100644 __le64 bytenr; /* this block number */ __le64 flags; -@@ -245,8 +245,11 @@ struct btrfs_super_block { +@@ -246,8 +246,11 @@ struct btrfs_super_block { __le64 cache_generation; __le64 uuid_tree_generation; @@ -119,7 +115,7 @@ index da67736c382d..0076d2ecb2a0 100644 u8 sys_chunk_array[BTRFS_SYSTEM_CHUNK_ARRAY_SIZE]; struct btrfs_root_backup super_roots[BTRFS_NUM_BACKUP_ROOTS]; } __attribute__ ((__packed__)); -@@ -275,7 +278,8 @@ struct btrfs_super_block { +@@ -277,7 +280,8 @@ struct btrfs_super_block { BTRFS_FEATURE_INCOMPAT_RAID56 | \ BTRFS_FEATURE_INCOMPAT_EXTENDED_IREF | \ BTRFS_FEATURE_INCOMPAT_SKINNY_METADATA | \ @@ -129,7 +125,7 @@ index da67736c382d..0076d2ecb2a0 100644 #define BTRFS_FEATURE_INCOMPAT_SAFE_SET \ (BTRFS_FEATURE_INCOMPAT_EXTENDED_IREF) -@@ -751,6 +755,7 @@ struct btrfs_delayed_root; +@@ -760,6 +764,7 @@ struct btrfs_delayed_root; struct btrfs_fs_info { u8 fsid[BTRFS_FSID_SIZE]; @@ -137,11 +133,9 @@ index da67736c382d..0076d2ecb2a0 100644 u8 chunk_tree_uuid[BTRFS_UUID_SIZE]; unsigned long flags; struct btrfs_root *extent_root; -diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c -index c33decceb3e6..05ee2399fb20 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c -@@ -579,7 +579,7 @@ static int csum_dirty_buffer(struct btrfs_fs_info *fs_info, struct page *page) +@@ -542,7 +542,7 @@ static int csum_dirty_buffer(struct btrf if (WARN_ON(!PageUptodate(page))) return -EUCLEAN; @@ -149,8 +143,8 @@ index c33decceb3e6..05ee2399fb20 100644 + ASSERT(memcmp_extent_buffer(eb, fs_info->metadata_fsid, btrfs_header_fsid(), BTRFS_FSID_SIZE) == 0); - return csum_tree_block(fs_info, eb, 0); -@@ -594,7 +594,19 @@ static int check_tree_block_fsid(struct btrfs_fs_info *fs_info, + if (csum_tree_block(eb, result)) +@@ -561,7 +561,19 @@ static int check_tree_block_fsid(struct read_extent_buffer(eb, fsid, btrfs_header_fsid(), BTRFS_FSID_SIZE); while (fs_devices) { @@ -171,7 +165,7 @@ index c33decceb3e6..05ee2399fb20 100644 ret = 0; break; } -@@ -1355,7 +1367,7 @@ struct btrfs_root *btrfs_create_tree(struct btrfs_trans_handle *trans, +@@ -1338,7 +1350,7 @@ struct btrfs_root *btrfs_create_tree(str btrfs_set_header_owner(leaf, objectid); root->node = leaf; @@ -180,7 +174,7 @@ index c33decceb3e6..05ee2399fb20 100644 write_extent_buffer_chunk_tree_uuid(leaf, fs_info->chunk_tree_uuid); btrfs_mark_buffer_dirty(leaf); -@@ -1436,7 +1448,7 @@ static struct btrfs_root *alloc_log_tree(struct btrfs_trans_handle *trans, +@@ -1419,7 +1431,7 @@ static struct btrfs_root *alloc_log_tree btrfs_set_header_owner(leaf, BTRFS_TREE_LOG_OBJECTID); root->node = leaf; @@ -189,7 +183,7 @@ index c33decceb3e6..05ee2399fb20 100644 btrfs_mark_buffer_dirty(root->node); btrfs_tree_unlock(root->node); return root; -@@ -2717,6 +2729,12 @@ int open_ctree(struct super_block *sb, +@@ -2699,6 +2711,12 @@ int open_ctree(struct super_block *sb, brelse(bh); memcpy(fs_info->fsid, fs_info->super_copy->fsid, BTRFS_FSID_SIZE); @@ -202,7 +196,7 @@ index c33decceb3e6..05ee2399fb20 100644 ret = btrfs_check_super_valid(fs_info); if (ret) { -@@ -3693,7 +3711,8 @@ int write_all_supers(struct btrfs_fs_info *fs_info, int max_mirrors) +@@ -3662,7 +3680,8 @@ int write_all_supers(struct btrfs_fs_inf btrfs_set_stack_device_io_width(dev_item, dev->io_width); btrfs_set_stack_device_sector_size(dev_item, dev->sector_size); memcpy(dev_item->uuid, dev->uuid, BTRFS_UUID_SIZE); @@ -212,7 +206,7 @@ index c33decceb3e6..05ee2399fb20 100644 flags = btrfs_super_flags(sb); btrfs_set_super_flags(sb, flags | BTRFS_HEADER_FLAG_WRITTEN); -@@ -4141,7 +4160,7 @@ static int btrfs_check_super_valid(struct btrfs_fs_info *fs_info) +@@ -4106,7 +4125,7 @@ static int btrfs_check_super_valid(struc ret = -EINVAL; } @@ -221,11 +215,9 @@ index c33decceb3e6..05ee2399fb20 100644 btrfs_err(fs_info, "dev_item UUID does not match fsid: %pU != %pU", fs_info->fsid, sb->dev_item.fsid); -diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c -index 94326471bae6..52e4a63dc01a 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c -@@ -172,14 +172,15 @@ static struct btrfs_fs_devices *__alloc_fs_devices(void) +@@ -173,14 +173,15 @@ static struct btrfs_fs_devices *__alloc_ /** * alloc_fs_devices - allocate struct btrfs_fs_devices @@ -244,7 +236,7 @@ index 94326471bae6..52e4a63dc01a 100644 { struct btrfs_fs_devices *fs_devs; -@@ -192,6 +193,11 @@ static struct btrfs_fs_devices *alloc_fs_devices(const u8 *fsid) +@@ -193,6 +194,11 @@ static struct btrfs_fs_devices *alloc_fs else generate_random_uuid(fs_devs->fsid); @@ -256,7 +248,7 @@ index 94326471bae6..52e4a63dc01a 100644 return fs_devs; } -@@ -272,13 +278,24 @@ static noinline struct btrfs_device *__find_device(struct list_head *head, +@@ -273,13 +279,24 @@ static noinline struct btrfs_device *__f return NULL; } @@ -284,7 +276,7 @@ index 94326471bae6..52e4a63dc01a 100644 } return NULL; } -@@ -615,10 +632,21 @@ static noinline int device_list_add(const char *path, +@@ -616,10 +633,21 @@ static noinline int device_list_add(cons struct rcu_string *name; int ret = 0; u64 found_transid = btrfs_super_generation(disk_super); @@ -308,7 +300,7 @@ index 94326471bae6..52e4a63dc01a 100644 if (IS_ERR(fs_devices)) return PTR_ERR(fs_devices); -@@ -731,7 +759,7 @@ static struct btrfs_fs_devices *clone_fs_devices(struct btrfs_fs_devices *orig) +@@ -761,7 +789,7 @@ static struct btrfs_fs_devices *clone_fs struct btrfs_device *device; struct btrfs_device *orig_dev; @@ -317,7 +309,7 @@ index 94326471bae6..52e4a63dc01a 100644 if (IS_ERR(fs_devices)) return fs_devices; -@@ -1006,6 +1034,11 @@ static int __btrfs_open_devices(struct btrfs_fs_devices *fs_devices, +@@ -1036,6 +1064,11 @@ static int __btrfs_open_devices(struct b if (btrfs_super_flags(disk_super) & BTRFS_SUPER_FLAG_SEEDING) { device->writeable = 0; @@ -329,7 +321,7 @@ index 94326471bae6..52e4a63dc01a 100644 } else { device->writeable = !bdev_read_only(bdev); seeding = 0; -@@ -1717,7 +1750,7 @@ static int btrfs_add_device(struct btrfs_trans_handle *trans, +@@ -1747,7 +1780,7 @@ static int btrfs_add_device(struct btrfs ptr = btrfs_device_uuid(dev_item); write_extent_buffer(leaf, device->uuid, ptr, BTRFS_UUID_SIZE); ptr = btrfs_device_fsid(dev_item); @@ -338,7 +330,7 @@ index 94326471bae6..52e4a63dc01a 100644 btrfs_mark_buffer_dirty(leaf); ret = 0; -@@ -2115,7 +2148,12 @@ static int btrfs_find_device_by_path(struct btrfs_fs_info *fs_info, +@@ -2145,7 +2178,12 @@ static int btrfs_find_device_by_path(str disk_super = (struct btrfs_super_block *)bh->b_data; devid = btrfs_stack_device_id(&disk_super->dev_item); dev_uuid = disk_super->dev_item.uuid; @@ -352,7 +344,7 @@ index 94326471bae6..52e4a63dc01a 100644 brelse(bh); if (!*device) ret = -ENOENT; -@@ -2230,6 +2268,8 @@ static int btrfs_prepare_sprout(struct btrfs_fs_info *fs_info) +@@ -2256,6 +2294,8 @@ static int btrfs_prepare_sprout(struct b generate_random_uuid(fs_devices->fsid); memcpy(fs_info->fsid, fs_devices->fsid, BTRFS_FSID_SIZE); @@ -361,7 +353,7 @@ index 94326471bae6..52e4a63dc01a 100644 memcpy(disk_super->fsid, fs_devices->fsid, BTRFS_FSID_SIZE); mutex_unlock(&fs_info->fs_devices->device_list_mutex); -@@ -6356,7 +6396,7 @@ struct btrfs_device *btrfs_find_device(struct btrfs_fs_info *fs_info, u64 devid, +@@ -6386,7 +6426,7 @@ struct btrfs_device *btrfs_find_device(s cur_devices = fs_info->fs_devices; while (cur_devices) { if (!fsid || @@ -370,7 +362,7 @@ index 94326471bae6..52e4a63dc01a 100644 device = __find_device(&cur_devices->devices, devid, uuid); if (device) -@@ -6640,12 +6680,12 @@ static struct btrfs_fs_devices *open_seed_devices(struct btrfs_fs_info *fs_info, +@@ -6611,12 +6651,12 @@ static struct btrfs_fs_devices *open_see fs_devices = fs_devices->seed; } @@ -385,7 +377,7 @@ index 94326471bae6..52e4a63dc01a 100644 if (IS_ERR(fs_devices)) return fs_devices; -@@ -6696,7 +6736,7 @@ static int read_one_dev(struct btrfs_fs_info *fs_info, +@@ -6667,7 +6707,7 @@ static int read_one_dev(struct btrfs_fs_ read_extent_buffer(leaf, fs_uuid, btrfs_device_fsid(dev_item), BTRFS_UUID_SIZE); @@ -394,11 +386,9 @@ index 94326471bae6..52e4a63dc01a 100644 fs_devices = open_seed_devices(fs_info, fs_uuid); if (IS_ERR(fs_devices)) return PTR_ERR(fs_devices); -diff --git a/fs/btrfs/volumes.h b/fs/btrfs/volumes.h -index 6d1b48929104..8777517317cf 100644 --- a/fs/btrfs/volumes.h +++ b/fs/btrfs/volumes.h -@@ -221,6 +221,7 @@ BTRFS_DEVICE_GETSET_FUNCS(bytes_used); +@@ -228,6 +228,7 @@ BTRFS_DEVICE_GETSET_FUNCS(bytes_used); struct btrfs_fs_devices { u8 fsid[BTRFS_FSID_SIZE]; /* FS specific uuid */ @@ -406,11 +396,9 @@ index 6d1b48929104..8777517317cf 100644 u64 num_devices; u64 open_devices; -diff --git a/include/uapi/linux/btrfs.h b/include/uapi/linux/btrfs.h -index a456e5309238..d53aa5a5d806 100644 --- a/include/uapi/linux/btrfs.h +++ b/include/uapi/linux/btrfs.h -@@ -273,6 +273,7 @@ struct btrfs_ioctl_fs_info_args { +@@ -267,6 +267,7 @@ struct btrfs_ioctl_fs_info_args { #define BTRFS_FEATURE_INCOMPAT_RAID56 (1ULL << 7) #define BTRFS_FEATURE_INCOMPAT_SKINNY_METADATA (1ULL << 8) #define BTRFS_FEATURE_INCOMPAT_NO_HOLES (1ULL << 9) @@ -418,8 +406,6 @@ index a456e5309238..d53aa5a5d806 100644 struct btrfs_ioctl_feature_flags { __u64 compat_flags; -diff --git a/include/uapi/linux/btrfs_tree.h b/include/uapi/linux/btrfs_tree.h -index 3142645a27f5..8afb27552130 100644 --- a/include/uapi/linux/btrfs_tree.h +++ b/include/uapi/linux/btrfs_tree.h @@ -455,6 +455,7 @@ struct btrfs_free_space_header { @@ -430,6 +416,3 @@ index 3142645a27f5..8afb27552130 100644 /* --- -2.17.1 - diff --git a/patches.suse/0001-btrfs-add-a-flush-step-for-delayed-iputs.patch b/patches.suse/0001-btrfs-add-a-flush-step-for-delayed-iputs.patch new file mode 100644 index 0000000..db04d80 --- /dev/null +++ b/patches.suse/0001-btrfs-add-a-flush-step-for-delayed-iputs.patch @@ -0,0 +1,64 @@ +From: Josef Bacik +Date: Thu, 1 Aug 2019 18:19:33 -0400 +Subject: btrfs: add a flush step for delayed iputs +Git-commit: 844245b4548499efad26e33e408a459b1fe3a346 +Patch-mainline: v5.4-rc1 +References: bsc#1165949 + +Delayed iputs could very well free up enough space without needing to +commit the transaction, so make this step it's own step. This will +allow us to skip the step for evictions in a later patch. + +Signed-off-by: Josef Bacik +Reviewed-by: David Sterba +Signed-off-by: David Sterba +Acked-by: Nikolay Borisov +--- + fs/btrfs/ctree.h | 3 ++- + fs/btrfs/space-info.c | 5 +++-- + include/trace/events/btrfs.h | 1 + + 3 files changed, 6 insertions(+), 3 deletions(-) + +--- a/fs/btrfs/ctree.h ++++ b/fs/btrfs/ctree.h +@@ -2549,7 +2549,8 @@ enum btrfs_flush_state { + FLUSH_DELALLOC_WAIT = 6, + ALLOC_CHUNK = 7, + ALLOC_CHUNK_FORCE = 8, +- COMMIT_TRANS = 9, ++ RUN_DELAYED_IPUTS = 9, ++ COMMIT_TRANS = 10, + }; + + void btrfs_trans_release_metadata(struct btrfs_trans_handle *trans, +--- a/fs/btrfs/space-info.c ++++ b/fs/btrfs/space-info.c +@@ -677,7 +677,7 @@ static int flush_space(struct btrfs_fs_i + if (ret > 0 || ret == -ENOSPC) + ret = 0; + break; +- case COMMIT_TRANS: ++ case RUN_DELAYED_IPUTS: + /* + * If we have pending delayed iputs then we could free up a + * bunch of pinned space, so make sure we run the iputs before +@@ -685,7 +685,8 @@ static int flush_space(struct btrfs_fs_i + */ + btrfs_run_delayed_iputs(fs_info); + btrfs_wait_on_delayed_iputs(fs_info); +- ++ break; ++ case COMMIT_TRANS: + ret = may_commit_transaction(fs_info, space_info); + break; + default: +--- a/include/trace/events/btrfs.h ++++ b/include/trace/events/btrfs.h +@@ -1013,6 +1013,7 @@ TRACE_EVENT(btrfs_trigger_flush, + { FLUSH_DELAYED_REFS, "FLUSH_ELAYED_REFS"}, \ + { ALLOC_CHUNK, "ALLOC_CHUNK"}, \ + { ALLOC_CHUNK_FORCE, "ALLOC_CHUNK_FORCE"}, \ ++ { RUN_DELAYED_IPUTS, "RUN_DELAYED_IPUTS"}, \ + { COMMIT_TRANS, "COMMIT_TRANS"}) + + TRACE_EVENT(btrfs_flush_space, diff --git a/patches.suse/0001-btrfs-add-btrfs_delete_ref_head-helper.patch b/patches.suse/0001-btrfs-add-btrfs_delete_ref_head-helper.patch new file mode 100644 index 0000000..aaed36f --- /dev/null +++ b/patches.suse/0001-btrfs-add-btrfs_delete_ref_head-helper.patch @@ -0,0 +1,96 @@ +From: Josef Bacik +Date: Mon, 3 Dec 2018 10:20:29 -0500 +Subject: btrfs: add btrfs_delete_ref_head helper +Git-commit: d7baffdaf9f9df8c9715aa507e3be2f409347c74 +Patch-mainline: v5.0-rc1 +References: bsc#1165949 + +We do this dance in cleanup_ref_head and check_ref_cleanup, unify it +into a helper and cleanup the calling functions. + +Reviewed-by: Omar Sandoval +Reviewed-by: Nikolay Borisov +Signed-off-by: Josef Bacik +Reviewed-by: David Sterba +Signed-off-by: David Sterba +Acked-by: Nikolay Borisov +--- + fs/btrfs/delayed-ref.c | 14 ++++++++++++++ + fs/btrfs/delayed-ref.h | 3 ++- + fs/btrfs/extent-tree.c | 21 ++------------------- + 3 files changed, 18 insertions(+), 20 deletions(-) + +--- a/fs/btrfs/delayed-ref.c ++++ b/fs/btrfs/delayed-ref.c +@@ -409,6 +409,20 @@ again: + return head; + } + ++void btrfs_delete_ref_head(struct btrfs_delayed_ref_root *delayed_refs, ++ struct btrfs_delayed_ref_head *head) ++{ ++ lockdep_assert_held(&delayed_refs->lock); ++ lockdep_assert_held(&head->lock); ++ ++ rb_erase(&head->href_node, &delayed_refs->href_root); ++ RB_CLEAR_NODE(&head->href_node); ++ atomic_dec(&delayed_refs->num_entries); ++ delayed_refs->num_heads--; ++ if (head->processing == 0) ++ delayed_refs->num_heads_ready--; ++} ++ + /* + * Helper to insert the ref_node to the tail or merge with tail. + * +--- a/fs/btrfs/delayed-ref.h ++++ b/fs/btrfs/delayed-ref.h +@@ -276,7 +276,8 @@ static inline void btrfs_delayed_ref_unl + { + mutex_unlock(&head->mutex); + } +- ++void btrfs_delete_ref_head(struct btrfs_delayed_ref_root *delayed_refs, ++ struct btrfs_delayed_ref_head *head); + + struct btrfs_delayed_ref_head * + btrfs_select_ref_head(struct btrfs_trans_handle *trans); +--- a/fs/btrfs/extent-tree.c ++++ b/fs/btrfs/extent-tree.c +@@ -2608,12 +2608,9 @@ static int cleanup_ref_head(struct btrfs + spin_unlock(&delayed_refs->lock); + return 1; + } +- delayed_refs->num_heads--; +- rb_erase(&head->href_node, &delayed_refs->href_root); +- RB_CLEAR_NODE(&head->href_node); ++ btrfs_delete_ref_head(delayed_refs, head); + spin_unlock(&delayed_refs->lock); + spin_unlock(&head->lock); +- atomic_dec(&delayed_refs->num_entries); + + trace_run_delayed_ref_head(fs_info, head, 0); + +@@ -7174,21 +7171,7 @@ static noinline int check_ref_cleanup(st + if (!mutex_trylock(&head->mutex)) + goto out; + +- /* +- * at this point we have a head with no other entries. Go +- * ahead and process it. +- */ +- rb_erase(&head->href_node, &delayed_refs->href_root); +- RB_CLEAR_NODE(&head->href_node); +- atomic_dec(&delayed_refs->num_entries); +- +- /* +- * we don't take a ref on the node because we're removing it from the +- * tree, so we just steal the ref the tree was holding. +- */ +- delayed_refs->num_heads--; +- if (head->processing == 0) +- delayed_refs->num_heads_ready--; ++ btrfs_delete_ref_head(delayed_refs, head); + head->processing = 0; + spin_unlock(&head->lock); + spin_unlock(&delayed_refs->lock); diff --git a/patches.suse/0001-btrfs-block-group-Fix-a-memory-leak-due-to-missing-b.patch b/patches.suse/0001-btrfs-block-group-Fix-a-memory-leak-due-to-missing-b.patch index 0c8280c..a996b4d 100644 --- a/patches.suse/0001-btrfs-block-group-Fix-a-memory-leak-due-to-missing-b.patch +++ b/patches.suse/0001-btrfs-block-group-Fix-a-memory-leak-due-to-missing-b.patch @@ -25,14 +25,12 @@ Signed-off-by: Qu Wenruo Reviewed-by: David Sterba Signed-off-by: David Sterba --- - fs/btrfs/block-group.c | 1 + + fs/btrfs/block-group.c | 1 + 1 file changed, 1 insertion(+) -diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c -index bf7e3f23bba7..670700cb1110 100644 ---- a/fs/btrfs/extent-tree.c -+++ b/fs/btrfs/extent-tree.c -@@ -1761,6 +1761,7 @@ int btrfs_read_block_groups(struct btrfs_fs_info *info) +--- a/fs/btrfs/block-group.c ++++ b/fs/btrfs/block-group.c +@@ -1589,6 +1589,7 @@ int btrfs_read_block_groups(struct btrfs btrfs_err(info, "bg %llu is a mixed block group but filesystem hasn't enabled mixed block groups", cache->key.objectid); @@ -40,6 +38,3 @@ index bf7e3f23bba7..670700cb1110 100644 ret = -EINVAL; goto error; } --- -2.23.0 - diff --git a/patches.suse/0001-btrfs-check-for-refs-on-snapshot-delete-resume.patch b/patches.suse/0001-btrfs-check-for-refs-on-snapshot-delete-resume.patch index 5fd92d9..df3a9c4 100644 --- a/patches.suse/0001-btrfs-check-for-refs-on-snapshot-delete-resume.patch +++ b/patches.suse/0001-btrfs-check-for-refs-on-snapshot-delete-resume.patch @@ -63,29 +63,25 @@ Signed-off-by: Josef Bacik Signed-off-by: David Sterba Signed-off-by: Filipe Manana --- - fs/btrfs/ctree.h | 2 ++ - fs/btrfs/extent-tree.c | 48 +++++++++++++++++++++++++++++++++++++++++- - fs/btrfs/root-tree.c | 8 +++++-- + fs/btrfs/ctree.h | 2 ++ + fs/btrfs/extent-tree.c | 48 +++++++++++++++++++++++++++++++++++++++++++++++- + fs/btrfs/root-tree.c | 8 ++++++-- 3 files changed, 55 insertions(+), 3 deletions(-) -diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h -index ee9e98d6958c..0f8bafd5c19d 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h -@@ -1176,6 +1176,8 @@ struct btrfs_subvolume_writers { - #define BTRFS_ROOT_MULTI_LOG_TASKS 7 +@@ -1182,6 +1182,8 @@ struct btrfs_subvolume_writers { #define BTRFS_ROOT_DIRTY 8 + #define BTRFS_ROOT_DELETING 9 #define BTRFS_ROOT_DEAD_RELOC_TREE 10 +/* Mark dead root stored on device whose cleanup needs to be resumed */ +#define BTRFS_ROOT_DEAD_TREE 11 /* * Record swapped tree blocks of a subvolume tree for delayed subtree trace -diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c -index 5ba32572a8a9..ef15a19765c1 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c -@@ -8450,6 +8450,7 @@ struct walk_control { +@@ -8689,6 +8689,7 @@ struct walk_control { int reada_slot; int reada_count; int for_reloc; @@ -93,11 +89,10 @@ index 5ba32572a8a9..ef15a19765c1 100644 }; #define DROP_REFERENCE 1 -@@ -8612,6 +8613,33 @@ static noinline int walk_down_proc(struct btrfs_trans_handle *trans, - return 0; +@@ -8852,6 +8853,33 @@ static noinline int walk_down_proc(struc } -+/* + /* + * This is used to verify a ref exists for this root to deal with a bug where we + * would have a drop_progress key that hadn't been updated properly. + */ @@ -124,14 +119,14 @@ index 5ba32572a8a9..ef15a19765c1 100644 + return 1; +} + - /* ++/* * helper to process tree block pointer. * -@@ -8768,6 +8796,23 @@ static noinline int do_walk_down(struct btrfs_trans_handle *trans, - parent = 0; + * when wc->stage == DROP_REFERENCE, this function checks +@@ -9008,6 +9036,23 @@ skip: } -+ /* + /* + * If we had a drop_progress we need to verify the refs are set + * as expected. If we find our ref then we know that from here + * on out everything should be correct, and we can clear the @@ -148,10 +143,11 @@ index 5ba32572a8a9..ef15a19765c1 100644 + wc->restarted = 0; + } + - /* ++ /* * Reloc tree doesn't contribute to qgroup numbers, and we have * already accounted them at merge time (replace_path), -@@ -8789,7 +8834,7 @@ static noinline int do_walk_down(struct btrfs_trans_handle *trans, + * thus we could skip expensive subtree trace here. +@@ -9028,7 +9073,7 @@ skip: if (ret) goto out_unlock; } @@ -160,7 +156,7 @@ index 5ba32572a8a9..ef15a19765c1 100644 *lookup_info = 1; ret = 1; -@@ -9091,6 +9136,7 @@ int btrfs_drop_snapshot(struct btrfs_root *root, +@@ -9339,6 +9384,7 @@ int btrfs_drop_snapshot(struct btrfs_roo } } @@ -168,11 +164,9 @@ index 5ba32572a8a9..ef15a19765c1 100644 wc->level = level; wc->shared_level = -1; wc->stage = DROP_REFERENCE; -diff --git a/fs/btrfs/root-tree.c b/fs/btrfs/root-tree.c -index 7d6bc308bf43..1ae9869123f4 100644 --- a/fs/btrfs/root-tree.c +++ b/fs/btrfs/root-tree.c -@@ -280,8 +280,10 @@ int btrfs_find_orphan_roots(struct btrfs_fs_info *fs_info) +@@ -280,8 +280,10 @@ int btrfs_find_orphan_roots(struct btrfs if (root) { WARN_ON(!test_bit(BTRFS_ROOT_ORPHAN_ITEM_INSERTED, &root->state)); @@ -184,7 +178,7 @@ index 7d6bc308bf43..1ae9869123f4 100644 continue; } -@@ -327,8 +329,10 @@ int btrfs_find_orphan_roots(struct btrfs_fs_info *fs_info) +@@ -327,8 +329,10 @@ int btrfs_find_orphan_roots(struct btrfs break; } @@ -196,6 +190,3 @@ index 7d6bc308bf43..1ae9869123f4 100644 } btrfs_free_path(path); --- -2.19.0 - diff --git a/patches.suse/0001-btrfs-extent_io-Move-the-BUG_ON-in-flush_write_bio-o.patch b/patches.suse/0001-btrfs-extent_io-Move-the-BUG_ON-in-flush_write_bio-o.patch new file mode 100644 index 0000000..0a51237 --- /dev/null +++ b/patches.suse/0001-btrfs-extent_io-Move-the-BUG_ON-in-flush_write_bio-o.patch @@ -0,0 +1,186 @@ +From f4340622e02261fae599e3da936ff4808b418173 Mon Sep 17 00:00:00 2001 +From: Qu Wenruo +Date: Wed, 20 Mar 2019 14:27:41 +0800 +Patch-mainline: v5.2 +Git-commit: f4340622e02261fae599e3da936ff4808b418173 +References: bsc#1168273 +Subject: [PATCH 1/7] btrfs: extent_io: Move the BUG_ON() in flush_write_bio() + one level up + +We have a BUG_ON() in flush_write_bio() to handle the return value of +submit_one_bio(). + +Move the BUG_ON() one level up to all its callers. + +This patch will introduce temporary variable, @flush_ret to keep code +change minimal in this patch. That variable will be cleaned up when +enhancing the error handling later. + +Reviewed-by: Johannes Thumshirn +Signed-off-by: Qu Wenruo +Reviewed-by: David Sterba +Signed-off-by: David Sterba +--- + fs/btrfs/extent_io.c | 55 ++++++++++++++++++++++++++++++++++++++------------- + 1 file changed, 41 insertions(+), 14 deletions(-) + +--- a/fs/btrfs/extent_io.c ++++ b/fs/btrfs/extent_io.c +@@ -170,15 +170,28 @@ static int __must_check submit_one_bio(s + return blk_status_to_errno(ret); + } + +-static void flush_write_bio(struct extent_page_data *epd) ++/* ++ * Submit bio from extent page data via submit_one_bio ++ * ++ * Return 0 if everything is OK. ++ * Return <0 for error. ++ */ ++static int __must_check flush_write_bio(struct extent_page_data *epd) + { +- if (epd->bio) { +- int ret; ++ int ret = 0; + ++ if (epd->bio) { + ret = submit_one_bio(epd->bio, 0, 0); +- BUG_ON(ret < 0); /* -ENOMEM */ ++ /* ++ * Clean up of epd->bio is handled by its endio function. ++ * And endio is either triggered by successful bio execution ++ * or the error handler of submit bio hook. ++ * So at this point, no matter what happened, we don't need ++ * to clean up epd->bio. ++ */ + epd->bio = NULL; + } ++ return ret; + } + + static inline struct btrfs_fs_info * +@@ -3595,7 +3608,8 @@ lock_extent_buffer_for_io(struct extent_ + + if (!btrfs_try_tree_write_lock(eb)) { + flush = 1; +- flush_write_bio(epd); ++ ret = flush_write_bio(epd); ++ BUG_ON(ret < 0); + btrfs_tree_lock(eb); + } + +@@ -3604,7 +3618,8 @@ lock_extent_buffer_for_io(struct extent_ + if (!epd->sync_io) + return 0; + if (!flush) { +- flush_write_bio(epd); ++ ret = flush_write_bio(epd); ++ BUG_ON(ret < 0); + flush = 1; + } + while (1) { +@@ -3645,7 +3660,8 @@ lock_extent_buffer_for_io(struct extent_ + + if (!trylock_page(p)) { + if (!flush) { +- flush_write_bio(epd); ++ ret = flush_write_bio(epd); ++ BUG_ON(ret < 0); + flush = 1; + } + lock_page(p); +@@ -3835,6 +3851,7 @@ int btree_write_cache_pages(struct addre + .sync_io = wbc->sync_mode == WB_SYNC_ALL, + }; + int ret = 0; ++ int flush_ret; + int done = 0; + int nr_to_write_done = 0; + struct pagevec pvec; +@@ -3939,7 +3956,8 @@ retry: + index = 0; + goto retry; + } +- flush_write_bio(&epd); ++ flush_ret = flush_write_bio(&epd); ++ BUG_ON(flush_ret < 0); + return ret; + } + +@@ -4023,7 +4041,8 @@ retry: + * mapping + */ + if (!trylock_page(page)) { +- flush_write_bio(epd); ++ ret = flush_write_bio(epd); ++ BUG_ON(ret < 0); + lock_page(page); + } + +@@ -4039,8 +4058,10 @@ retry: + } + + if (wbc->sync_mode != WB_SYNC_NONE) { +- if (PageWriteback(page)) +- flush_write_bio(epd); ++ if (PageWriteback(page)) { ++ ret = flush_write_bio(epd); ++ BUG_ON(ret < 0); ++ } + wait_on_page_writeback(page); + } + +@@ -4101,6 +4122,7 @@ retry: + int extent_write_full_page(struct page *page, struct writeback_control *wbc) + { + int ret; ++ int flush_ret; + struct extent_page_data epd = { + .bio = NULL, + .tree = &BTRFS_I(page->mapping->host)->io_tree, +@@ -4110,7 +4132,8 @@ int extent_write_full_page(struct page * + + ret = __extent_writepage(page, wbc, &epd); + +- flush_write_bio(&epd); ++ flush_ret = flush_write_bio(&epd); ++ BUG_ON(flush_ret < 0); + return ret; + } + +@@ -4118,6 +4141,7 @@ int extent_write_locked_range(struct ino + int mode) + { + int ret = 0; ++ int flush_ret; + struct address_space *mapping = inode->i_mapping; + struct extent_io_tree *tree = &BTRFS_I(inode)->io_tree; + struct page *page; +@@ -4152,7 +4176,8 @@ int extent_write_locked_range(struct ino + start += PAGE_SIZE; + } + +- flush_write_bio(&epd); ++ flush_ret = flush_write_bio(&epd); ++ BUG_ON(flush_ret < 0); + return ret; + } + +@@ -4161,6 +4186,7 @@ int extent_writepages(struct extent_io_t + struct writeback_control *wbc) + { + int ret = 0; ++ int flush_ret; + struct extent_page_data epd = { + .bio = NULL, + .tree = tree, +@@ -4169,7 +4195,8 @@ int extent_writepages(struct extent_io_t + }; + + ret = extent_write_cache_pages(mapping, wbc, &epd); +- flush_write_bio(&epd); ++ flush_ret = flush_write_bio(&epd); ++ BUG_ON(flush_ret < 0); + return ret; + } + diff --git a/patches.suse/0001-btrfs-fix-panic-during-relocation-after-ENOSPC-befor.patch b/patches.suse/0001-btrfs-fix-panic-during-relocation-after-ENOSPC-befor.patch new file mode 100644 index 0000000..139a0b2 --- /dev/null +++ b/patches.suse/0001-btrfs-fix-panic-during-relocation-after-ENOSPC-befor.patch @@ -0,0 +1,122 @@ +From e87ffb563f6cba2f6c333b2e1d7add91ea126339 Mon Sep 17 00:00:00 2001 +From: Josef Bacik +Date: Mon, 25 Feb 2019 11:14:45 -0500 +Patch-mainline: v5.2-rc1 +Git-commit: ff612ba7849964b1898fd3ccd1f56941129c6aab +References: bsc#1163508 +Subject: [PATCH 1/2] btrfs: fix panic during relocation after ENOSPC before + writeback happens + +We've been seeing the following sporadically throughout our fleet + +panic: kernel BUG at fs/btrfs/relocation.c:4584! +netversion: 5.0-0 +Backtrace: + #0 [ffffc90003adb880] machine_kexec at ffffffff81041da8 + #1 [ffffc90003adb8c8] __crash_kexec at ffffffff8110396c + #2 [ffffc90003adb988] crash_kexec at ffffffff811048ad + #3 [ffffc90003adb9a0] oops_end at ffffffff8101c19a + #4 [ffffc90003adb9c0] do_trap at ffffffff81019114 + #5 [ffffc90003adba00] do_error_trap at ffffffff810195d0 + #6 [ffffc90003adbab0] invalid_op at ffffffff81a00a9b + [exception RIP: btrfs_reloc_cow_block+692] + RIP: ffffffff8143b614 RSP: ffffc90003adbb68 RFLAGS: 00010246 + RAX: fffffffffffffff7 RBX: ffff8806b9c32000 RCX: ffff8806aad00690 + RDX: ffff880850b295e0 RSI: ffff8806b9c32000 RDI: ffff88084f205bd0 + RBP: ffff880849415000 R8: ffffc90003adbbe0 R9: ffff88085ac90000 + R10: ffff8805f7369140 R11: 0000000000000000 R12: ffff880850b295e0 + R13: ffff88084f205bd0 R14: 0000000000000000 R15: 0000000000000000 + ORIG_RAX: ffffffffffffffff CS: 0010 SS: 0018 + #7 [ffffc90003adbbb0] __btrfs_cow_block at ffffffff813bf1cd + #8 [ffffc90003adbc28] btrfs_cow_block at ffffffff813bf4b3 + #9 [ffffc90003adbc78] btrfs_search_slot at ffffffff813c2e6c + +The way relocation moves data extents is by creating a reloc inode and +preallocating extents in this inode and then copying the data into these +preallocated extents. Once we've done this for all of our extents, +we'll write out these dirty pages, which marks the extent written, and +goes into btrfs_reloc_cow_block(). From here we get our current +reloc_control, which _should_ match the reloc_control for the current +block group we're relocating. + +However if we get an ENOSPC in this path at some point we'll bail out, +never initiating writeback on this inode. Not a huge deal, unless we +happen to be doing relocation on a different block group, and this block +group is now rc->stage == UPDATE_DATA_PTRS. This trips the BUG_ON() in +btrfs_reloc_cow_block(), because we expect to be done modifying the data +inode. We are in fact done modifying the metadata for the data inode +we're currently using, but not the one from the failed block group, and +thus we BUG_ON(). + +(This happens when writeback finishes for extents from the previous +group, when we are at btrfs_finish_ordered_io() which updates the data +reloc tree (inode item, drops/adds extent items, etc).) + +Fix this by writing out the reloc data inode always, and then breaking +out of the loop after that point to keep from tripping this BUG_ON() +later. + +Signed-off-by: Josef Bacik +Reviewed-by: Filipe Manana +[ add note from Filipe ] +Signed-off-by: David Sterba +(cherry picked from commit ff612ba7849964b1898fd3ccd1f56941129c6aab) +--- + fs/btrfs/relocation.c | 31 ++++++++++++++++++++----------- + 1 file changed, 20 insertions(+), 11 deletions(-) + +diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c +index 570536b330e4..72c880a24536 100644 +--- a/fs/btrfs/relocation.c ++++ b/fs/btrfs/relocation.c +@@ -4556,27 +4556,36 @@ int btrfs_relocate_block_group(struct btrfs_fs_info *fs_info, u64 group_start) + mutex_lock(&fs_info->cleaner_mutex); + ret = relocate_block_group(rc); + mutex_unlock(&fs_info->cleaner_mutex); +- if (ret < 0) { ++ if (ret < 0) + err = ret; +- goto out; +- } +- +- if (rc->extents_found == 0) +- break; +- +- btrfs_info(fs_info, "found %llu extents", rc->extents_found); + ++ /* ++ * We may have gotten ENOSPC after we already dirtied some ++ * extents. If writeout happens while we're relocating a ++ * different block group we could end up hitting the ++ * BUG_ON(rc->stage == UPDATE_DATA_PTRS) in ++ * btrfs_reloc_cow_block. Make sure we write everything out ++ * properly so we don't trip over this problem, and then break ++ * out of the loop if we hit an error. ++ */ + if (rc->stage == MOVE_DATA_EXTENTS && rc->found_file_extent) { + ret = btrfs_wait_ordered_range(rc->data_inode, 0, + (u64)-1); +- if (ret) { ++ if (ret) + err = ret; +- goto out; +- } + invalidate_mapping_pages(rc->data_inode->i_mapping, + 0, -1); + rc->stage = UPDATE_DATA_PTRS; + } ++ ++ if (err < 0) ++ goto out; ++ ++ if (rc->extents_found == 0) ++ break; ++ ++ btrfs_info(fs_info, "found %llu extents", rc->extents_found); ++ + } + + WARN_ON(rc->block_group->pinned > 0); +-- +2.16.4 + diff --git a/patches.suse/0001-btrfs-make-btrfs_destroy_delayed_refs-use-btrfs_delayed_ref_lock.patch b/patches.suse/0001-btrfs-make-btrfs_destroy_delayed_refs-use-btrfs_delayed_ref_lock.patch new file mode 100644 index 0000000..297c5fb --- /dev/null +++ b/patches.suse/0001-btrfs-make-btrfs_destroy_delayed_refs-use-btrfs_delayed_ref_lock.patch @@ -0,0 +1,40 @@ +From: Josef Bacik +Date: Wed, 21 Nov 2018 14:05:39 -0500 +Subject: btrfs: make btrfs_destroy_delayed_refs use btrfs_delayed_ref_lock +Git-commit: 3069bd26690a01f1e8280dff9cb019fdf216a4f5 +Patch-mainline: v5.1-rc1 +References: bsc#1165949 + +We have this open coded in btrfs_destroy_delayed_refs, use the helper +instead. + +Reviewed-by: Nikolay Borisov +Signed-off-by: Josef Bacik +Reviewed-by: David Sterba +Signed-off-by: David Sterba +Acked-by: Nikolay Borisov +--- + fs/btrfs/disk-io.c | 11 ++--------- + 1 file changed, 2 insertions(+), 9 deletions(-) + +--- a/fs/btrfs/disk-io.c ++++ b/fs/btrfs/disk-io.c +@@ -4250,16 +4250,9 @@ static int btrfs_destroy_delayed_refs(st + + head = rb_entry(node, struct btrfs_delayed_ref_head, + href_node); +- if (!mutex_trylock(&head->mutex)) { +- refcount_inc(&head->refs); +- spin_unlock(&delayed_refs->lock); +- +- mutex_lock(&head->mutex); +- mutex_unlock(&head->mutex); +- btrfs_put_delayed_ref_head(head); +- spin_lock(&delayed_refs->lock); ++ if (btrfs_delayed_ref_lock(delayed_refs, head)) + continue; +- } ++ + spin_lock(&head->lock); + while ((n = rb_first(&head->ref_tree)) != NULL) { + ref = rb_entry(n, struct btrfs_delayed_ref_node, diff --git a/patches.suse/0001-btrfs-move-btrfs_add_free_space-out-of-a-header-file.patch b/patches.suse/0001-btrfs-move-btrfs_add_free_space-out-of-a-header-file.patch new file mode 100644 index 0000000..1fd81fc --- /dev/null +++ b/patches.suse/0001-btrfs-move-btrfs_add_free_space-out-of-a-header-file.patch @@ -0,0 +1,62 @@ +From: Josef Bacik +Date: Thu, 20 Jun 2019 15:37:43 -0400 +Subject: btrfs: move btrfs_add_free_space out of a header file +Git-commit: 478b4d9f0105e33cae34445d5ad2eb9798628231 +Patch-mainline: v5.4-rc1 +References: bsc#1165949 + +This is prep work for moving block_group_cache around. Having this in +the header file makes the header file include need to be in a certain +order, which is awkward, so just move it into free-space-cache.c and +then we can re-arrange later. + +Signed-off-by: Josef Bacik +Reviewed-by: David Sterba +Signed-off-by: David Sterba +Acked-by: Nikolay Borisov +--- + fs/btrfs/free-space-cache.c | 8 ++++++++ + fs/btrfs/free-space-cache.h | 10 ++-------- + 2 files changed, 10 insertions(+), 8 deletions(-) + +diff --git a/fs/btrfs/free-space-cache.c b/fs/btrfs/free-space-cache.c +index 062be9dde4c6..92cb06dd94d3 100644 +--- a/fs/btrfs/free-space-cache.c ++++ b/fs/btrfs/free-space-cache.c +@@ -2376,6 +2376,14 @@ int __btrfs_add_free_space(struct btrfs_fs_info *fs_info, + return ret; + } + ++int btrfs_add_free_space(struct btrfs_block_group_cache *block_group, ++ u64 bytenr, u64 size) ++{ ++ return __btrfs_add_free_space(block_group->fs_info, ++ block_group->free_space_ctl, ++ bytenr, size); ++} ++ + int btrfs_remove_free_space(struct btrfs_block_group_cache *block_group, + u64 offset, u64 bytes) + { +diff --git a/fs/btrfs/free-space-cache.h b/fs/btrfs/free-space-cache.h +index 8760acb55ffd..2205a4113ef3 100644 +--- a/fs/btrfs/free-space-cache.h ++++ b/fs/btrfs/free-space-cache.h +@@ -73,14 +73,8 @@ void btrfs_init_free_space_ctl(struct btrfs_block_group_cache *block_group); + int __btrfs_add_free_space(struct btrfs_fs_info *fs_info, + struct btrfs_free_space_ctl *ctl, + u64 bytenr, u64 size); +-static inline int +-btrfs_add_free_space(struct btrfs_block_group_cache *block_group, +- u64 bytenr, u64 size) +-{ +- return __btrfs_add_free_space(block_group->fs_info, +- block_group->free_space_ctl, +- bytenr, size); +-} ++int btrfs_add_free_space(struct btrfs_block_group_cache *block_group, ++ u64 bytenr, u64 size); + int btrfs_remove_free_space(struct btrfs_block_group_cache *block_group, + u64 bytenr, u64 size); + void __btrfs_remove_free_space_cache(struct btrfs_free_space_ctl *ctl); + diff --git a/patches.suse/0001-btrfs-qgroup-Always-free-PREALLOC-META-reserve-in-bt.patch b/patches.suse/0001-btrfs-qgroup-Always-free-PREALLOC-META-reserve-in-bt.patch index 653ed01..f121423 100644 --- a/patches.suse/0001-btrfs-qgroup-Always-free-PREALLOC-META-reserve-in-bt.patch +++ b/patches.suse/0001-btrfs-qgroup-Always-free-PREALLOC-META-reserve-in-bt.patch @@ -96,21 +96,19 @@ Signed-off-by: Qu Wenruo Signed-off-by: David Sterba Signed-off-by: Filipe Manana --- - fs/btrfs/ctree.h | 3 +-- - fs/btrfs/extent-tree.c | 6 ++---- - fs/btrfs/file.c | 7 +++---- - fs/btrfs/inode-map.c | 4 ++-- - fs/btrfs/inode.c | 12 ++++++------ - fs/btrfs/ioctl.c | 6 ++---- - fs/btrfs/relocation.c | 7 +++---- - 7 files changed, 19 insertions(+), 26 deletions(-) + fs/btrfs/ctree.h | 3 +-- + fs/btrfs/delalloc-space.c | 7 +++---- + fs/btrfs/file.c | 7 +++---- + fs/btrfs/inode-map.c | 4 ++-- + fs/btrfs/inode.c | 12 ++++++------ + fs/btrfs/ioctl.c | 6 ++---- + fs/btrfs/relocation.c | 7 +++---- + 7 files changed, 20 insertions(+), 26 deletions(-) -diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h -index 98e5d815a92c..d835442d67ff 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h -@@ -2834,8 +2834,7 @@ int btrfs_subvolume_reserve_metadata(struct btrfs_root *root, - u64 *qgroup_reserved, bool use_global_rsv); +@@ -2561,8 +2561,7 @@ int btrfs_subvolume_reserve_metadata(str + bool use_global_rsv); void btrfs_subvolume_release_metadata(struct btrfs_fs_info *fs_info, struct btrfs_block_rsv *rsv); -void btrfs_delalloc_release_extents(struct btrfs_inode *inode, u64 num_bytes, @@ -118,12 +116,10 @@ index 98e5d815a92c..d835442d67ff 100644 +void btrfs_delalloc_release_extents(struct btrfs_inode *inode, u64 num_bytes); int btrfs_delalloc_reserve_metadata(struct btrfs_inode *inode, u64 num_bytes); - void btrfs_delalloc_release_metadata(struct btrfs_inode *inode, u64 num_bytes, -diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c -index 0e122631e99b..cbd86ffaa2fb 100644 ---- a/fs/btrfs/extent-tree.c -+++ b/fs/btrfs/extent-tree.c -@@ -6168,7 +6168,6 @@ void btrfs_delalloc_release_metadata(struct btrfs_inode *inode, u64 num_bytes, + u64 btrfs_account_ro_block_groups_free_space(struct btrfs_space_info *sinfo); +--- a/fs/btrfs/delalloc-space.c ++++ b/fs/btrfs/delalloc-space.c +@@ -408,7 +408,6 @@ 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 @@ -131,17 +127,18 @@ index 0e122631e99b..cbd86ffaa2fb 100644 * * 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 -@@ -6176,8 +6175,7 @@ void btrfs_delalloc_release_metadata(struct btrfs_inode *inode, u64 num_bytes, +@@ -416,8 +415,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, - bool qgroup_free) +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); + struct btrfs_fs_info *fs_info = inode->root->fs_info; unsigned num_extents; -@@ -6191,7 +6189,7 @@ void btrfs_delalloc_release_extents(struct btrfs_inode *inode, u64 num_bytes, +@@ -431,7 +430,7 @@ void btrfs_delalloc_release_extents(stru if (btrfs_is_testing(fs_info)) return; @@ -150,11 +147,9 @@ index 0e122631e99b..cbd86ffaa2fb 100644 } /** -diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c -index 0d2f7528947e..0cbc3e9cbdfb 100644 --- a/fs/btrfs/file.c +++ b/fs/btrfs/file.c -@@ -1702,7 +1702,7 @@ static noinline ssize_t __btrfs_buffered_write(struct file *file, +@@ -1701,7 +1701,7 @@ again: force_page_uptodate); if (ret) { btrfs_delalloc_release_extents(BTRFS_I(inode), @@ -163,7 +158,7 @@ index 0d2f7528947e..0cbc3e9cbdfb 100644 break; } -@@ -1714,7 +1714,7 @@ static noinline ssize_t __btrfs_buffered_write(struct file *file, +@@ -1713,7 +1713,7 @@ again: if (extents_locked == -EAGAIN) goto again; btrfs_delalloc_release_extents(BTRFS_I(inode), @@ -172,7 +167,7 @@ index 0d2f7528947e..0cbc3e9cbdfb 100644 ret = extents_locked; break; } -@@ -1772,8 +1772,7 @@ static noinline ssize_t __btrfs_buffered_write(struct file *file, +@@ -1771,8 +1771,7 @@ again: unlock_extent_cached(&BTRFS_I(inode)->io_tree, lockstart, lockend, &cached_state, GFP_NOFS); @@ -182,11 +177,9 @@ index 0d2f7528947e..0cbc3e9cbdfb 100644 if (ret) { btrfs_drop_pages(pages, num_pages); break; -diff --git a/fs/btrfs/inode-map.c b/fs/btrfs/inode-map.c -index 9409dcc7020d..022b19336fee 100644 --- a/fs/btrfs/inode-map.c +++ b/fs/btrfs/inode-map.c -@@ -500,12 +500,12 @@ int btrfs_save_ino_cache(struct btrfs_root *root, +@@ -501,12 +501,12 @@ again: ret = btrfs_prealloc_file_range_trans(inode, trans, 0, 0, prealloc, prealloc, prealloc, &alloc_hint); if (ret) { @@ -201,11 +194,9 @@ index 9409dcc7020d..022b19336fee 100644 out_put: iput(inode); out_release: -diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c -index e18bd0ef846f..8dda701f2dea 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c -@@ -2118,7 +2118,7 @@ static void btrfs_writepage_fixup_worker(struct btrfs_work *work) +@@ -2120,7 +2120,7 @@ again: 0); ClearPageChecked(page); set_page_dirty(page); @@ -214,7 +205,7 @@ index e18bd0ef846f..8dda701f2dea 100644 out: unlock_extent_cached(&BTRFS_I(inode)->io_tree, page_start, page_end, &cached_state, GFP_NOFS); -@@ -4621,7 +4621,7 @@ int btrfs_truncate_block(struct inode *inode, loff_t from, loff_t len, +@@ -4634,7 +4634,7 @@ again: if (!page) { btrfs_delalloc_release_space(inode, data_reserved, block_start, blocksize, true); @@ -223,7 +214,7 @@ index e18bd0ef846f..8dda701f2dea 100644 ret = -ENOMEM; goto out; } -@@ -4690,7 +4690,7 @@ int btrfs_truncate_block(struct inode *inode, loff_t from, loff_t len, +@@ -4703,7 +4703,7 @@ out_unlock: if (ret) btrfs_delalloc_release_space(inode, data_reserved, block_start, blocksize, true); @@ -232,7 +223,7 @@ index e18bd0ef846f..8dda701f2dea 100644 unlock_page(page); put_page(page); out: -@@ -8614,7 +8614,7 @@ static ssize_t btrfs_direct_IO(struct kiocb *iocb, struct iov_iter *iter) +@@ -8643,7 +8643,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, true); @@ -241,7 +232,7 @@ index e18bd0ef846f..8dda701f2dea 100644 } out: if (wakeup) -@@ -8984,14 +8984,14 @@ int btrfs_page_mkwrite(struct vm_fault *vmf) +@@ -9013,14 +9013,14 @@ again: out_unlock: if (!ret) { @@ -258,11 +249,9 @@ index e18bd0ef846f..8dda701f2dea 100644 btrfs_delalloc_release_space(inode, data_reserved, page_start, reserved_space, (ret != 0)); out_noreserve: -diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c -index 1a2ea0d188f1..5ae2eb94b9ad 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c -@@ -1262,8 +1262,7 @@ static int cluster_pages_for_defrag(struct inode *inode, +@@ -1262,8 +1262,7 @@ again: unlock_page(pages[i]); put_page(pages[i]); } @@ -272,7 +261,7 @@ index 1a2ea0d188f1..5ae2eb94b9ad 100644 extent_changeset_free(data_reserved); return i_done; out: -@@ -1274,8 +1273,7 @@ static int cluster_pages_for_defrag(struct inode *inode, +@@ -1274,8 +1273,7 @@ out: btrfs_delalloc_release_space(inode, data_reserved, start_index << PAGE_SHIFT, page_cnt << PAGE_SHIFT, true); @@ -282,11 +271,9 @@ index 1a2ea0d188f1..5ae2eb94b9ad 100644 extent_changeset_free(data_reserved); return ret; -diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c -index 3d51064e3619..ba1d259f7394 100644 --- a/fs/btrfs/relocation.c +++ b/fs/btrfs/relocation.c -@@ -3321,7 +3321,7 @@ static int relocate_file_extent_cluster(struct inode *inode, +@@ -3322,7 +3322,7 @@ static int relocate_file_extent_cluster( btrfs_delalloc_release_metadata(BTRFS_I(inode), PAGE_SIZE, true); btrfs_delalloc_release_extents(BTRFS_I(inode), @@ -295,7 +282,7 @@ index 3d51064e3619..ba1d259f7394 100644 ret = -ENOMEM; goto out; } -@@ -3342,7 +3342,7 @@ static int relocate_file_extent_cluster(struct inode *inode, +@@ -3343,7 +3343,7 @@ static int relocate_file_extent_cluster( btrfs_delalloc_release_metadata(BTRFS_I(inode), PAGE_SIZE, true); btrfs_delalloc_release_extents(BTRFS_I(inode), @@ -304,7 +291,7 @@ index 3d51064e3619..ba1d259f7394 100644 ret = -EIO; goto out; } -@@ -3373,8 +3373,7 @@ static int relocate_file_extent_cluster(struct inode *inode, +@@ -3374,8 +3374,7 @@ static int relocate_file_extent_cluster( put_page(page); index++; @@ -314,6 +301,3 @@ index 3d51064e3619..ba1d259f7394 100644 balance_dirty_pages_ratelimited(inode->i_mapping); btrfs_throttle(fs_info); } --- -2.16.4 - diff --git a/patches.suse/0001-btrfs-qgroup-Move-reserved-data-accounting-from-btrf.patch b/patches.suse/0001-btrfs-qgroup-Move-reserved-data-accounting-from-btrf.patch index ceb0183..73f9fcb 100644 --- a/patches.suse/0001-btrfs-qgroup-Move-reserved-data-accounting-from-btrf.patch +++ b/patches.suse/0001-btrfs-qgroup-Move-reserved-data-accounting-from-btrf.patch @@ -104,15 +104,15 @@ Signed-off-by: David Sterba --- fs/btrfs/delayed-ref.c | 14 ++++---------- fs/btrfs/delayed-ref.h | 11 ----------- - fs/btrfs/extent-tree.c | 4 ---- + fs/btrfs/extent-tree.c | 3 --- fs/btrfs/qgroup.c | 19 +++++++++++++++---- fs/btrfs/qgroup.h | 18 +++++++++++------- include/trace/events/btrfs.h | 29 ----------------------------- - 6 files changed, 30 insertions(+), 65 deletions(-) + 6 files changed, 30 insertions(+), 64 deletions(-) --- a/fs/btrfs/delayed-ref.c +++ b/fs/btrfs/delayed-ref.c -@@ -590,15 +590,13 @@ static void init_delayed_ref_head(struct +@@ -611,15 +611,13 @@ static void init_delayed_ref_head(struct RB_CLEAR_NODE(&head_ref->href_node); head_ref->processing = 0; head_ref->total_ref_mod = count_mod; @@ -130,7 +130,7 @@ Signed-off-by: David Sterba } qrecord->bytenr = bytenr; -@@ -641,10 +639,6 @@ add_delayed_ref_head(struct btrfs_fs_inf +@@ -662,10 +660,6 @@ add_delayed_ref_head(struct btrfs_fs_inf existing = htree_insert(&delayed_refs->href_root, &head_ref->href_node); if (existing) { @@ -138,10 +138,10 @@ Signed-off-by: David Sterba - && head_ref->qgroup_reserved - && existing->qgroup_ref_root - && existing->qgroup_reserved); - update_existing_head_ref(delayed_refs, existing, head_ref, + update_existing_head_ref(trans, existing, head_ref, old_ref_mod); /* -@@ -764,7 +758,7 @@ int btrfs_add_delayed_tree_ref(struct bt +@@ -789,7 +783,7 @@ int btrfs_add_delayed_tree_ref(struct bt if (test_bit(BTRFS_FS_QUOTA_ENABLED, &fs_info->flags) && is_fstree(ref_root)) { @@ -150,7 +150,7 @@ Signed-off-by: David Sterba if (!record) goto free_head_ref; } -@@ -848,7 +842,7 @@ int btrfs_add_delayed_data_ref(struct bt +@@ -879,7 +873,7 @@ int btrfs_add_delayed_data_ref(struct bt if (test_bit(BTRFS_FS_QUOTA_ENABLED, &fs_info->flags) && is_fstree(ref_root)) { @@ -181,17 +181,16 @@ Signed-off-by: David Sterba * until the delayed ref is processed. must_insert_reserved is --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c -@@ -2519,10 +2519,6 @@ void btrfs_cleanup_ref_head_accounting(s - spin_unlock(&delayed_refs->lock); +@@ -2624,9 +2624,6 @@ void btrfs_cleanup_ref_head_accounting(s } } -- + - /* Also free its reserved qgroup space */ - btrfs_qgroup_free_delayed_ref(fs_info, head->qgroup_ref_root, - head->qgroup_reserved); + btrfs_delayed_refs_rsv_release(fs_info, nr_items); } - static int cleanup_ref_head(struct btrfs_trans_handle *trans, --- a/fs/btrfs/qgroup.c +++ b/fs/btrfs/qgroup.c @@ -1488,12 +1488,18 @@ int btrfs_qgroup_trace_extent_nolock(str diff --git a/patches.suse/0001-btrfs-relocation-Delay-reloc-tree-deletion-after-mer.patch b/patches.suse/0001-btrfs-relocation-Delay-reloc-tree-deletion-after-mer.patch index deeb8d3..f56ba98 100644 --- a/patches.suse/0001-btrfs-relocation-Delay-reloc-tree-deletion-after-mer.patch +++ b/patches.suse/0001-btrfs-relocation-Delay-reloc-tree-deletion-after-mer.patch @@ -59,15 +59,15 @@ Signed-off-by: David Sterba --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h -@@ -1171,6 +1171,7 @@ struct btrfs_subvolume_writers { - #define BTRFS_ROOT_FORCE_COW 6 +@@ -1181,6 +1181,7 @@ struct btrfs_subvolume_writers { #define BTRFS_ROOT_MULTI_LOG_TASKS 7 #define BTRFS_ROOT_DIRTY 8 + #define BTRFS_ROOT_DELETING 9 +#define BTRFS_ROOT_DEAD_RELOC_TREE 10 /* * in ram representation of the tree. extent_root is used for all allocations -@@ -1290,6 +1291,14 @@ struct btrfs_root { +@@ -1300,6 +1301,14 @@ struct btrfs_root { u64 nr_ordered_extents; /* @@ -94,7 +94,7 @@ Signed-off-by: David Sterba spin_lock_init(&root->inode_lock); --- a/fs/btrfs/relocation.c +++ b/fs/btrfs/relocation.c -@@ -174,6 +174,8 @@ struct reloc_control { +@@ -175,6 +175,8 @@ struct reloc_control { struct mapping_tree reloc_root_tree; /* list of reloc trees */ struct list_head reloc_roots; @@ -103,7 +103,7 @@ Signed-off-by: David Sterba /* size of metadata reservation for merging reloc trees */ u64 merging_rsv_size; /* size of relocated tree nodes */ -@@ -1503,15 +1505,17 @@ int btrfs_update_reloc_root(struct btrfs +@@ -1512,15 +1514,17 @@ int btrfs_update_reloc_root(struct btrfs struct btrfs_root_item *root_item; int ret; @@ -123,7 +123,7 @@ Signed-off-by: David Sterba __del_reloc_root(reloc_root); } -@@ -2157,6 +2161,58 @@ static int find_next_key(struct btrfs_pa +@@ -2166,6 +2170,58 @@ static int find_next_key(struct btrfs_pa } /* @@ -182,7 +182,7 @@ Signed-off-by: David Sterba * merge the relocated tree blocks in reloc tree with corresponding * fs tree. */ -@@ -2295,13 +2351,8 @@ static noinline_for_stack int merge_relo +@@ -2304,13 +2360,8 @@ static noinline_for_stack int merge_relo out: btrfs_free_path(path); @@ -198,7 +198,7 @@ Signed-off-by: David Sterba if (trans) btrfs_end_transaction_throttle(trans); -@@ -2446,14 +2497,6 @@ again: +@@ -2455,14 +2506,6 @@ again: } else { list_del_init(&reloc_root->root_list); } @@ -213,7 +213,7 @@ Signed-off-by: David Sterba } if (found) { -@@ -4187,6 +4230,9 @@ restart: +@@ -4209,6 +4252,9 @@ restart: goto out_free; } btrfs_commit_transaction(trans); @@ -223,7 +223,7 @@ Signed-off-by: David Sterba out_free: btrfs_free_block_rsv(fs_info, rc->block_rsv); btrfs_free_path(path); -@@ -4281,6 +4327,7 @@ static struct reloc_control *alloc_reloc +@@ -4303,6 +4349,7 @@ static struct reloc_control *alloc_reloc return NULL; INIT_LIST_HEAD(&rc->reloc_roots); @@ -231,7 +231,7 @@ Signed-off-by: David Sterba backref_cache_init(&rc->backref_cache); mapping_tree_init(&rc->reloc_root_tree); extent_io_tree_init(&rc->processed_blocks, -@@ -4591,6 +4638,10 @@ int btrfs_recover_relocation(struct btrf +@@ -4613,6 +4660,10 @@ int btrfs_recover_relocation(struct btrf goto out_free; } err = btrfs_commit_transaction(trans); diff --git a/patches.suse/0001-btrfs-run-delayed-iput-at-unlink-time.patch b/patches.suse/0001-btrfs-run-delayed-iput-at-unlink-time.patch new file mode 100644 index 0000000..f9e5a27 --- /dev/null +++ b/patches.suse/0001-btrfs-run-delayed-iput-at-unlink-time.patch @@ -0,0 +1,90 @@ +From: Josef Bacik +Date: Tue, 18 Jun 2019 10:59:18 -0400 +Subject: btrfs: run delayed iput at unlink time +Git-commit: 63611e738a62bfb186a61e4b16b9fb72657144e5 +Patch-mainline: v5.3-rc1 +References: bsc#1165949 + +We have been seeing issues in production where a cleaner script will end +up unlinking a bunch of files that have pending iputs. This means they +will get their final iput's run at btrfs-cleaner time and thus are not +throttled, which impacts the workload. + +Since we are unlinking these files we can just drop the delayed iput at +unlink time. We are already holding a reference to the inode so this +will not be the final iput and thus is completely safe to do at this +point. Doing this means we are more likely to be doing the final iput +at unlink time, and thus will get the IO charged to the caller and get +throttled appropriately without affecting the main workload. + +Reviewed-by: Nikolay Borisov +Signed-off-by: Josef Bacik +Signed-off-by: David Sterba +Acked-by: Nikolay Borisov +--- + fs/btrfs/inode.c | 40 ++++++++++++++++++++++++++++++++++------ + 1 file changed, 34 insertions(+), 6 deletions(-) + +--- a/fs/btrfs/inode.c ++++ b/fs/btrfs/inode.c +@@ -3264,6 +3264,28 @@ void btrfs_add_delayed_iput(struct inode + spin_unlock(&fs_info->delayed_iput_lock); + } + ++static void run_delayed_iput_locked(struct btrfs_fs_info *fs_info, ++ struct btrfs_inode *inode) ++{ ++ list_del_init(&inode->delayed_iput); ++ spin_unlock(&fs_info->delayed_iput_lock); ++ iput(&inode->vfs_inode); ++ if (atomic_dec_and_test(&fs_info->nr_delayed_iputs)) ++ wake_up(&fs_info->delayed_iputs_wait); ++ spin_lock(&fs_info->delayed_iput_lock); ++} ++ ++static void btrfs_run_delayed_iput(struct btrfs_fs_info *fs_info, ++ struct btrfs_inode *inode) ++{ ++ if (!list_empty(&inode->delayed_iput)) { ++ spin_lock(&fs_info->delayed_iput_lock); ++ if (!list_empty(&inode->delayed_iput)) ++ run_delayed_iput_locked(fs_info, inode); ++ spin_unlock(&fs_info->delayed_iput_lock); ++ } ++} ++ + void btrfs_run_delayed_iputs(struct btrfs_fs_info *fs_info) + { + spin_lock(&fs_info->delayed_iput_lock); +@@ -3272,12 +3294,7 @@ void btrfs_run_delayed_iputs(struct btrf + + inode = list_first_entry(&fs_info->delayed_iputs, + struct btrfs_inode, delayed_iput); +- list_del_init(&inode->delayed_iput); +- spin_unlock(&fs_info->delayed_iput_lock); +- iput(&inode->vfs_inode); +- if (atomic_dec_and_test(&fs_info->nr_delayed_iputs)) +- wake_up(&fs_info->delayed_iputs_wait); +- spin_lock(&fs_info->delayed_iput_lock); ++ run_delayed_iput_locked(fs_info, inode); + } + spin_unlock(&fs_info->delayed_iput_lock); + if (!test_bit(BTRFS_FS_CLEANER_RUNNING, &fs_info->flags)) +@@ -4006,6 +4023,17 @@ skip_backref: + ret = 0; + else if (ret) + btrfs_abort_transaction(trans, ret); ++ ++ /* ++ * If we have a pending delayed iput we could end up with the final iput ++ * being run in btrfs-cleaner context. If we have enough of these built ++ * up we can end up burning a lot of time in btrfs-cleaner without any ++ * way to throttle the unlinks. Since we're currently holding a ref on ++ * the inode we can run the delayed iput here without any issues as the ++ * final iput won't be done until after we drop the ref we're currently ++ * holding. ++ */ ++ btrfs_run_delayed_iput(fs_info, inode); + err: + btrfs_free_path(path); + if (ret) diff --git a/patches.suse/0001-btrfs-scrub-Require-mandatory-block-group-RO-for-dev.patch b/patches.suse/0001-btrfs-scrub-Require-mandatory-block-group-RO-for-dev.patch index 009a24d..b0089c7 100644 --- a/patches.suse/0001-btrfs-scrub-Require-mandatory-block-group-RO-for-dev.patch +++ b/patches.suse/0001-btrfs-scrub-Require-mandatory-block-group-RO-for-dev.patch @@ -93,10 +93,10 @@ Signed-off-by: David Sterba --- a/fs/btrfs/scrub.c +++ b/fs/btrfs/scrub.c -@@ -3848,15 +3848,14 @@ int scrub_enumerate_chunks(struct scrub_ +@@ -3849,15 +3849,14 @@ int scrub_enumerate_chunks(struct scrub_ */ scrub_pause_on(fs_info); - ret = btrfs_inc_block_group_ro(fs_info, cache); + ret = btrfs_inc_block_group_ro(cache); - scrub_pause_off(fs_info); if (ret == 0) { @@ -111,7 +111,7 @@ Signed-off-by: David Sterba * metadata are always cowed, and our scrub paused * commit_transactions. */ -@@ -3866,9 +3865,21 @@ int scrub_enumerate_chunks(struct scrub_ +@@ -3867,9 +3866,21 @@ int scrub_enumerate_chunks(struct scrub_ "failed setting block group ro, ret=%d\n", ret); btrfs_put_block_group(cache); diff --git a/patches.suse/0001-btrfs-sink-extent_write_locked_range-tree-parameter.patch b/patches.suse/0001-btrfs-sink-extent_write_locked_range-tree-parameter.patch new file mode 100644 index 0000000..016e51e --- /dev/null +++ b/patches.suse/0001-btrfs-sink-extent_write_locked_range-tree-parameter.patch @@ -0,0 +1,74 @@ +From 5e3ee23648a20dfaf72eeb88f884aae25ea7d8fb Mon Sep 17 00:00:00 2001 +From: Nikolay Borisov +Date: Fri, 8 Dec 2017 15:55:58 +0200 +Patch-mainline: v4.16 +Git-commit: 5e3ee23648a20dfaf72eeb88f884aae25ea7d8fb +References: bsc#1168273 +Subject: [PATCH 1/7] btrfs: sink extent_write_locked_range tree parameter + +This function is called only from submit_compressed_extents and the +io tree being passed is always that of the inode. But we are also +passing the inode, so just move getting the io tree pointer in +extent_write_locked_range to simplify the signature. + +Signed-off-by: Nikolay Borisov +Reviewed-by: David Sterba +Signed-off-by: David Sterba +--- + fs/btrfs/extent_io.c | 5 +++-- + fs/btrfs/extent_io.h | 4 ++-- + fs/btrfs/inode.c | 4 ++-- + 3 files changed, 7 insertions(+), 6 deletions(-) + +diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c +index 16ae832bdb5d..c0b2bf65d6b0 100644 +--- a/fs/btrfs/extent_io.c ++++ b/fs/btrfs/extent_io.c +@@ -4073,11 +4073,12 @@ int extent_write_full_page(struct extent_io_tree *tree, struct page *page, + return ret; + } + +-int extent_write_locked_range(struct extent_io_tree *tree, struct inode *inode, +- u64 start, u64 end, int mode) ++int extent_write_locked_range(struct inode *inode, u64 start, u64 end, ++ int mode) + { + int ret = 0; + struct address_space *mapping = inode->i_mapping; ++ struct extent_io_tree *tree = &BTRFS_I(inode)->io_tree; + struct page *page; + unsigned long nr_pages = (end - start + PAGE_SIZE) >> + PAGE_SHIFT; +diff --git a/fs/btrfs/extent_io.h b/fs/btrfs/extent_io.h +index c28f5ef88f42..f2cbabb2306a 100644 +--- a/fs/btrfs/extent_io.h ++++ b/fs/btrfs/extent_io.h +@@ -405,8 +405,8 @@ int extent_invalidatepage(struct extent_io_tree *tree, + struct page *page, unsigned long offset); + int extent_write_full_page(struct extent_io_tree *tree, struct page *page, + struct writeback_control *wbc); +-int extent_write_locked_range(struct extent_io_tree *tree, struct inode *inode, +- u64 start, u64 end, int mode); ++int extent_write_locked_range(struct inode *inode, u64 start, u64 end, ++ int mode); + int extent_writepages(struct extent_io_tree *tree, + struct address_space *mapping, + struct writeback_control *wbc); +diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c +index 9ad8c9321c8f..8a7da59292b7 100644 +--- a/fs/btrfs/inode.c ++++ b/fs/btrfs/inode.c +@@ -770,8 +770,8 @@ static noinline void submit_compressed_extents(struct inode *inode, + * all those pages down to the drive. + */ + if (!page_started && !ret) +- extent_write_locked_range(io_tree, +- inode, async_extent->start, ++ extent_write_locked_range(inode, ++ async_extent->start, + async_extent->start + + async_extent->ram_size - 1, + WB_SYNC_ALL); +-- +2.26.0 + diff --git a/patches.suse/0001-btrfs-sink-get_extent-parameter-to-extent_writepages.patch b/patches.suse/0001-btrfs-sink-get_extent-parameter-to-extent_writepages.patch new file mode 100644 index 0000000..2b829f7 --- /dev/null +++ b/patches.suse/0001-btrfs-sink-get_extent-parameter-to-extent_writepages.patch @@ -0,0 +1,65 @@ +From 433175992c1775db6cbc7c92294345408a333bee Mon Sep 17 00:00:00 2001 +From: David Sterba +Date: Fri, 23 Jun 2017 03:46:07 +0200 +Patch-mainline: v4.16 +Git-commit: 433175992c1775db6cbc7c92294345408a333bee +References: bsc#1168273 +Subject: [PATCH 1/7] btrfs: sink get_extent parameter to extent_writepages + +There's only one caller. + +Signed-off-by: David Sterba +--- + fs/btrfs/extent_io.c | 3 +-- + fs/btrfs/extent_io.h | 1 - + fs/btrfs/inode.c | 2 +- + 3 files changed, 2 insertions(+), 4 deletions(-) + +diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c +index 88131863d827..1d7aebd020ad 100644 +--- a/fs/btrfs/extent_io.c ++++ b/fs/btrfs/extent_io.c +@@ -4121,14 +4121,13 @@ int extent_write_locked_range(struct extent_io_tree *tree, struct inode *inode, + + int extent_writepages(struct extent_io_tree *tree, + struct address_space *mapping, +- get_extent_t *get_extent, + struct writeback_control *wbc) + { + int ret = 0; + struct extent_page_data epd = { + .bio = NULL, + .tree = tree, +- .get_extent = get_extent, ++ .get_extent = btrfs_get_extent, + .extent_locked = 0, + .sync_io = wbc->sync_mode == WB_SYNC_ALL, + }; +diff --git a/fs/btrfs/extent_io.h b/fs/btrfs/extent_io.h +index 9f6a5133ce8a..e07f9e1c34e8 100644 +--- a/fs/btrfs/extent_io.h ++++ b/fs/btrfs/extent_io.h +@@ -411,7 +411,6 @@ int extent_write_locked_range(struct extent_io_tree *tree, struct inode *inode, + int mode); + int extent_writepages(struct extent_io_tree *tree, + struct address_space *mapping, +- get_extent_t *get_extent, + struct writeback_control *wbc); + int btree_write_cache_pages(struct address_space *mapping, + struct writeback_control *wbc); +diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c +index ff91b2e3979a..a49dd803fb03 100644 +--- a/fs/btrfs/inode.c ++++ b/fs/btrfs/inode.c +@@ -8903,7 +8903,7 @@ static int btrfs_writepages(struct address_space *mapping, + struct extent_io_tree *tree; + + tree = &BTRFS_I(mapping->host)->io_tree; +- return extent_writepages(tree, mapping, btrfs_get_extent, wbc); ++ return extent_writepages(tree, mapping, wbc); + } + + static int +-- +2.26.0 + diff --git a/patches.suse/0001-btrfs-tree-checker-Remove-comprehensive-root-owner-c.patch b/patches.suse/0001-btrfs-tree-checker-Remove-comprehensive-root-owner-c.patch new file mode 100644 index 0000000..e37f83a --- /dev/null +++ b/patches.suse/0001-btrfs-tree-checker-Remove-comprehensive-root-owner-c.patch @@ -0,0 +1,74 @@ +From ff2ac107fae2440b6877c615c0ac788d2a106ed7 Mon Sep 17 00:00:00 2001 +From: Qu Wenruo +Date: Thu, 4 Apr 2019 11:47:07 +0800 +Patch-mainline: v5.2 +Git-commit: ff2ac107fae2440b6877c615c0ac788d2a106ed7 +References: bsc#1168273 +Subject: [PATCH 1/2] btrfs: tree-checker: Remove comprehensive root owner + check + +Commit 1ba98d086fe3 ("Btrfs: detect corruption when non-root leaf has +zero item") introduced comprehensive root owner checker. + +However it's pretty expensive tree search to locate the owner root, +especially when it get reused by mandatory read and write time +tree-checker. + +This patch will remove that check, and completely rely on owner based +empty leaf check, which is much faster and still works fine for most +case. + +And since we skip the old root owner check, now write time tree check +can be merged with btrfs_check_leaf_full(). + +Signed-off-by: Qu Wenruo +Signed-off-by: David Sterba +--- + fs/btrfs/tree-checker.c | 24 ------------------------ + 1 file changed, 24 deletions(-) + +diff --git a/fs/btrfs/tree-checker.c b/fs/btrfs/tree-checker.c +index 5c988b57b90e..b9dd2a6e133f 100644 +--- a/fs/btrfs/tree-checker.c ++++ b/fs/btrfs/tree-checker.c +@@ -831,7 +831,6 @@ static int check_leaf(struct extent_buffer *leaf, bool check_item_data) + */ + if (nritems == 0 && !btrfs_header_flag(leaf, BTRFS_HEADER_FLAG_RELOC)) { + u64 owner = btrfs_header_owner(leaf); +- struct btrfs_root *check_root; + + /* These trees must never be empty */ + if (owner == BTRFS_ROOT_TREE_OBJECTID || +@@ -845,29 +844,6 @@ static int check_leaf(struct extent_buffer *leaf, bool check_item_data) + owner); + return -EUCLEAN; + } +- key.objectid = owner; +- key.type = BTRFS_ROOT_ITEM_KEY; +- key.offset = (u64)-1; +- +- check_root = btrfs_get_fs_root(fs_info, &key, false); +- /* +- * The only reason we also check NULL here is that during +- * open_ctree() some roots has not yet been set up. +- */ +- if (!IS_ERR_OR_NULL(check_root)) { +- struct extent_buffer *eb; +- +- eb = btrfs_root_node(check_root); +- /* if leaf is the root, then it's fine */ +- if (leaf != eb) { +- generic_err(leaf, 0, +- "invalid nritems, have %u should not be 0 for non-root leaf", +- nritems); +- free_extent_buffer(eb); +- return -EUCLEAN; +- } +- free_extent_buffer(eb); +- } + return 0; + } + +-- +2.26.0 + diff --git a/patches.suse/0001-btrfs-wait-on-caching-when-putting-the-bg-cache.patch b/patches.suse/0001-btrfs-wait-on-caching-when-putting-the-bg-cache.patch new file mode 100644 index 0000000..49b0372 --- /dev/null +++ b/patches.suse/0001-btrfs-wait-on-caching-when-putting-the-bg-cache.patch @@ -0,0 +1,85 @@ +From: Josef Bacik +Date: Wed, 12 Sep 2018 10:45:45 -0400 +Subject: btrfs: wait on caching when putting the bg cache +Git-commit: 3aa7c7a31c26321696b92841d5103461c6f3f517 +Patch-mainline: v4.20-rc1 +References: bsc##1165949 + +While testing my backport I noticed there was a panic if I ran +generic/416 generic/417 generic/418 all in a row. This just happened to +uncover a race where we had outstanding IO after we destroy all of our +workqueues, and then we'd go to queue the endio work on those free'd +workqueues. + +This is because we aren't waiting for the caching threads to be done +before freeing everything up, so to fix this make sure we wait on any +outstanding caching that's being done before we free up the block group, +so we're sure to be done with all IO by the time we get to +btrfs_stop_all_workers(). This fixes the panic I was seeing +consistently in testing. + +------------[ cut here ]------------ +kernel BUG at fs/btrfs/volumes.c:6112! +SMP PTI +Modules linked in: +CPU: 1 PID: 27165 Comm: kworker/u4:7 Not tainted 4.16.0-02155-g3553e54a578d-dirty #875 +Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.11.0-2.el7 04/01/2014 +Workqueue: btrfs-cache btrfs_cache_helper +RIP: 0010:btrfs_map_bio+0x346/0x370 +RSP: 0000:ffffc900061e79d0 EFLAGS: 00010202 +RAX: 0000000000000000 RBX: ffff880071542e00 RCX: 0000000000533000 +RDX: ffff88006bb74380 RSI: 0000000000000008 RDI: ffff880078160000 +RBP: 0000000000000001 R08: ffff8800781cd200 R09: 0000000000503000 +R10: ffff88006cd21200 R11: 0000000000000000 R12: 0000000000000000 +R13: 0000000000000000 R14: ffff8800781cd200 R15: ffff880071542e00 +FS: 0000000000000000(0000) GS:ffff88007fd00000(0000) knlGS:0000000000000000 +CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 +CR2: 000000000817ffc4 CR3: 0000000078314000 CR4: 00000000000006e0 +DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 +DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 +Call Trace: + btree_submit_bio_hook+0x8a/0xd0 + submit_one_bio+0x5d/0x80 + read_extent_buffer_pages+0x18a/0x320 + btree_read_extent_buffer_pages+0xbc/0x200 + ? alloc_extent_buffer+0x359/0x3e0 + read_tree_block+0x3d/0x60 + read_block_for_search.isra.30+0x1a5/0x360 + btrfs_search_slot+0x41b/0xa10 + btrfs_next_old_leaf+0x212/0x470 + caching_thread+0x323/0x490 + normal_work_helper+0xc5/0x310 + process_one_work+0x141/0x340 + worker_thread+0x44/0x3c0 + kthread+0xf8/0x130 + ? process_one_work+0x340/0x340 + ? kthread_bind+0x10/0x10 + ret_from_fork+0x35/0x40 +RIP: btrfs_map_bio+0x346/0x370 RSP: ffffc900061e79d0 +---[ end trace 827eb13e50846033 ]--- +Kernel panic - not syncing: Fatal exception +Kernel Offset: disabled +---[ end Kernel panic - not syncing: Fatal exception + +CC: stable@vger.kernel.org # 4.4+ +Signed-off-by: Josef Bacik +Reviewed-by: Omar Sandoval +Signed-off-by: David Sterba +Acked-by: Nikolay Borisov +--- + fs/btrfs/extent-tree.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c +index f0524bdf49b3..686542318215 100644 +--- a/fs/btrfs/extent-tree.c ++++ b/fs/btrfs/extent-tree.c +@@ -9615,6 +9615,7 @@ void btrfs_put_block_group_cache(struct btrfs_fs_info *info) + + block_group = btrfs_lookup_first_block_group(info, last); + while (block_group) { ++ wait_block_group_cache_done(block_group); + spin_lock(&block_group->lock); + if (block_group->iref) + break; + diff --git a/patches.suse/0001-ceph-check-pool_flag_full-nearfull-in-addition-to-osdmap_full-nearfull.patch b/patches.suse/0001-ceph-check-pool_flag_full-nearfull-in-addition-to-osdmap_full-nearfull.patch new file mode 100644 index 0000000..f33f137 --- /dev/null +++ b/patches.suse/0001-ceph-check-pool_flag_full-nearfull-in-addition-to-osdmap_full-nearfull.patch @@ -0,0 +1,133 @@ +From: Ilya Dryomov +Date: Mon, 9 Mar 2020 12:03:14 +0100 +Subject: ceph: check POOL_FLAG_FULL/NEARFULL in addition to + OSDMAP_FULL/NEARFULL +Git-commit: 7614209736fbc4927584d4387faade4f31444fce +Patch-mainline: v5.6 +References: bsc#1169307 + + +CEPH_OSDMAP_FULL/NEARFULL aren't set since mimic, so we need to consult +per-pool flags as well. Unfortunately the backwards compatibility here +is lacking: + +- the change that deprecated OSDMAP_FULL/NEARFULL went into mimic, but + was guarded by require_osd_release >= RELEASE_LUMINOUS +- it was subsequently backported to luminous in v12.2.2, but that makes + no difference to clients that only check OSDMAP_FULL/NEARFULL because + require_osd_release is not client-facing -- it is for OSDs + +Since all kernels are affected, the best we can do here is just start +checking both map flags and pool flags and send that to stable. + +These checks are best effort, so take osdc->lock and look up pool flags +just once. Remove the FIXME, since filesystem quotas are checked above +and RADOS quotas are reflected in POOL_FLAG_FULL: when the pool reaches +its quota, both POOL_FLAG_FULL and POOL_FLAG_FULL_QUOTA are set. + +Cc: stable@vger.kernel.org +Reported-by: Yanhu Cao +Signed-off-by: Ilya Dryomov +Reviewed-by: Jeff Layton +Acked-by: Sage Weil +Acked-by: Luis Henriques +--- + fs/ceph/file.c | 14 +++++++++++--- + include/linux/ceph/osdmap.h | 4 ++++ + include/linux/ceph/rados.h | 6 ++++-- + net/ceph/osdmap.c | 9 +++++++++ + 4 files changed, 28 insertions(+), 5 deletions(-) + +--- a/fs/ceph/file.c ++++ b/fs/ceph/file.c +@@ -1381,9 +1381,12 @@ static ssize_t ceph_write_iter(struct ki + struct inode *inode = file_inode(file); + struct ceph_inode_info *ci = ceph_inode(inode); + struct ceph_fs_client *fsc = ceph_inode_to_client(inode); ++ struct ceph_osd_client *osdc = &fsc->client->osdc; + struct ceph_cap_flush *prealloc_cf; + ssize_t count, written = 0; + int err, want, got; ++ u32 map_flags; ++ u64 pool_flags; + loff_t pos; + loff_t limit = max(i_size_read(inode), fsc->max_file_size); + +@@ -1440,8 +1443,12 @@ retry_snap: + goto out; + } + +- /* FIXME: not complete since it doesn't account for being at quota */ +- if (ceph_osdmap_flag(&fsc->client->osdc, CEPH_OSDMAP_FULL)) { ++ down_read(&osdc->lock); ++ map_flags = osdc->osdmap->flags; ++ pool_flags = ceph_pg_pool_flags(osdc->osdmap, ci->i_layout.pool_id); ++ up_read(&osdc->lock); ++ if ((map_flags & CEPH_OSDMAP_FULL) || ++ (pool_flags & CEPH_POOL_FLAG_FULL)) { + err = -ENOSPC; + goto out; + } +@@ -1531,7 +1538,8 @@ retry_snap: + } + + if (written >= 0) { +- if (ceph_osdmap_flag(&fsc->client->osdc, CEPH_OSDMAP_NEARFULL)) ++ if ((map_flags & CEPH_OSDMAP_NEARFULL) || ++ (pool_flags & CEPH_POOL_FLAG_NEARFULL)) + iocb->ki_flags |= IOCB_DSYNC; + written = generic_write_sync(iocb, written); + } +--- a/include/linux/ceph/osdmap.h ++++ b/include/linux/ceph/osdmap.h +@@ -37,6 +37,9 @@ int ceph_spg_compare(const struct ceph_s + #define CEPH_POOL_FLAG_HASHPSPOOL (1ULL << 0) /* hash pg seed and pool id + together */ + #define CEPH_POOL_FLAG_FULL (1ULL << 1) /* pool is full */ ++#define CEPH_POOL_FLAG_FULL_QUOTA (1ULL << 10) /* pool ran out of quota, ++ will set FULL too */ ++#define CEPH_POOL_FLAG_NEARFULL (1ULL << 11) /* pool is nearfull */ + + struct ceph_pg_pool_info { + struct rb_node node; +@@ -309,5 +312,6 @@ extern struct ceph_pg_pool_info *ceph_pg + + extern const char *ceph_pg_pool_name_by_id(struct ceph_osdmap *map, u64 id); + extern int ceph_pg_poolid_by_name(struct ceph_osdmap *map, const char *name); ++u64 ceph_pg_pool_flags(struct ceph_osdmap *map, u64 id); + + #endif +--- a/include/linux/ceph/rados.h ++++ b/include/linux/ceph/rados.h +@@ -142,8 +142,10 @@ extern const char *ceph_osd_state_name(i + /* + * osd map flag bits + */ +-#define CEPH_OSDMAP_NEARFULL (1<<0) /* sync writes (near ENOSPC) */ +-#define CEPH_OSDMAP_FULL (1<<1) /* no data writes (ENOSPC) */ ++#define CEPH_OSDMAP_NEARFULL (1<<0) /* sync writes (near ENOSPC), ++ not set since ~luminous */ ++#define CEPH_OSDMAP_FULL (1<<1) /* no data writes (ENOSPC), ++ not set since ~luminous */ + #define CEPH_OSDMAP_PAUSERD (1<<2) /* pause all reads */ + #define CEPH_OSDMAP_PAUSEWR (1<<3) /* pause all writes */ + #define CEPH_OSDMAP_PAUSEREC (1<<4) /* pause recovery */ +--- a/net/ceph/osdmap.c ++++ b/net/ceph/osdmap.c +@@ -711,6 +711,15 @@ int ceph_pg_poolid_by_name(struct ceph_o + } + EXPORT_SYMBOL(ceph_pg_poolid_by_name); + ++u64 ceph_pg_pool_flags(struct ceph_osdmap *map, u64 id) ++{ ++ struct ceph_pg_pool_info *pi; ++ ++ pi = __lookup_pg_pool(&map->pg_pools, id); ++ return pi ? pi->flags : 0; ++} ++EXPORT_SYMBOL(ceph_pg_pool_flags); ++ + static void __remove_pg_pool(struct rb_root *root, struct ceph_pg_pool_info *pi) + { + rb_erase(&pi->node, root); + diff --git a/patches.suse/0001-crypto-pcrypt-Fix-user-after-free-on-module-unload.patch b/patches.suse/0001-crypto-pcrypt-Fix-user-after-free-on-module-unload.patch new file mode 100644 index 0000000..8ad7f8c --- /dev/null +++ b/patches.suse/0001-crypto-pcrypt-Fix-user-after-free-on-module-unload.patch @@ -0,0 +1,37 @@ +From 07bfd9bdf568a38d9440c607b72342036011f727 Mon Sep 17 00:00:00 2001 +From: Herbert Xu +Date: Tue, 19 Nov 2019 17:41:31 +0800 +Subject: [PATCH] crypto: pcrypt - Fix user-after-free on module unload +Git-commit: 07bfd9bdf568a38d9440c607b72342036011f727 +References: git-fixes +Patch-mainline: v5.6-rc1 + +On module unload of pcrypt we must unregister the crypto algorithms +first and then tear down the padata structure. As otherwise the +crypto algorithms are still alive and can be used while the padata +structure is being freed. + +Fixes: 5068c7a883d1 ("crypto: pcrypt - Add pcrypt crypto...") +Cc: +Signed-off-by: Herbert Xu +Signed-off-by: Oliver Neukum +--- + crypto/pcrypt.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/crypto/pcrypt.c ++++ b/crypto/pcrypt.c +@@ -505,11 +505,12 @@ err: + + static void __exit pcrypt_exit(void) + { ++ crypto_unregister_template(&pcrypt_tmpl); ++ + pcrypt_fini_padata(&pencrypt); + pcrypt_fini_padata(&pdecrypt); + + kset_unregister(pcrypt_kset); +- crypto_unregister_template(&pcrypt_tmpl); + } + + module_init(pcrypt_init); diff --git a/patches.suse/0001-device-Use-overflow-helpers-for-devm_kmalloc.patch b/patches.suse/0001-device-Use-overflow-helpers-for-devm_kmalloc.patch deleted file mode 100644 index acab343..0000000 --- a/patches.suse/0001-device-Use-overflow-helpers-for-devm_kmalloc.patch +++ /dev/null @@ -1,68 +0,0 @@ -From 2509b561f7c6599907c08cb364c86b8c45466e4f Mon Sep 17 00:00:00 2001 -From: Kees Cook -Date: Tue, 8 May 2018 22:29:52 -0700 -Subject: device: Use overflow helpers for devm_kmalloc() -Git-commit: 2509b561f7c6599907c08cb364c86b8c45466e4f -Patch-mainline: v4.18-rc1 -References: FATE#326289 - -Use the overflow helpers both in existing multiplication-using inlines as -well as the addition-overflow case in the core allocation routine. - -Signed-off-by: Kees Cook -Acked-by: Thomas Zimmermann ---- - drivers/base/devres.c | 7 ++++++- - include/linux/device.h | 8 ++++++-- - 2 files changed, 12 insertions(+), 3 deletions(-) - -diff --git a/drivers/base/devres.c b/drivers/base/devres.c -index 95b67281cd2a..f98a097e73f2 100644 ---- a/drivers/base/devres.c -+++ b/drivers/base/devres.c -@@ -84,9 +84,14 @@ static struct devres_group * node_to_group(struct devres_node *node) - static __always_inline struct devres * alloc_dr(dr_release_t release, - size_t size, gfp_t gfp, int nid) - { -- size_t tot_size = sizeof(struct devres) + size; -+ size_t tot_size; - struct devres *dr; - -+ /* We must catch any near-SIZE_MAX cases that could overflow. */ -+ if (unlikely(check_add_overflow(sizeof(struct devres), size, -+ &tot_size))) -+ return NULL; -+ - dr = kmalloc_node_track_caller(tot_size, gfp, nid); - if (unlikely(!dr)) - return NULL; -diff --git a/include/linux/device.h b/include/linux/device.h -index 477956990f5e..897efa647203 100644 ---- a/include/linux/device.h -+++ b/include/linux/device.h -@@ -25,6 +25,7 @@ - #include - #include - #include -+#include - #include - - struct device; -@@ -668,9 +669,12 @@ static inline void *devm_kzalloc(struct device *dev, size_t size, gfp_t gfp) - static inline void *devm_kmalloc_array(struct device *dev, - size_t n, size_t size, gfp_t flags) - { -- if (size != 0 && n > SIZE_MAX / size) -+ size_t bytes; -+ -+ if (unlikely(check_mul_overflow(n, size, &bytes))) - return NULL; -- return devm_kmalloc(dev, n * size, flags); -+ -+ return devm_kmalloc(dev, bytes, flags); - } - static inline void *devm_kcalloc(struct device *dev, - size_t n, size_t size, gfp_t flags) --- -2.19.1 - diff --git a/patches.suse/0001-drm-amd-amdgpu-Fix-GPR-read-from-debugfs-v2.patch b/patches.suse/0001-drm-amd-amdgpu-Fix-GPR-read-from-debugfs-v2.patch new file mode 100644 index 0000000..2a9fbaa --- /dev/null +++ b/patches.suse/0001-drm-amd-amdgpu-Fix-GPR-read-from-debugfs-v2.patch @@ -0,0 +1,57 @@ +From 5bbc6604a62814511c32f2e39bc9ffb2c1b92cbe Mon Sep 17 00:00:00 2001 +From: Tom St Denis +Date: Tue, 10 Mar 2020 08:40:41 -0400 +Subject: drm/amd/amdgpu: Fix GPR read from debugfs (v2) +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit +Git-commit: 5bbc6604a62814511c32f2e39bc9ffb2c1b92cbe +Patch-mainline: v5.6-rc7 +References: bsc#1113956 + +The offset into the array was specified in bytes but should +be in terms of 32-bit words. Also prevent large reads that +would also cause a buffer overread. + +v2: Read from correct offset from internal storage buffer. + +Signed-off-by: Tom St Denis +Acked-by: Christian König +Reviewed-by: Alex Deucher +Signed-off-by: Alex Deucher +Cc: stable@vger.kernel.org +Acked-by: Thomas Zimmermann +--- + drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c +index f24ed9a1a3e56..337d7cdce8e9c 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c +@@ -781,11 +781,11 @@ static ssize_t amdgpu_debugfs_gpr_read(struct file *f, char __user *buf, + ssize_t result = 0; + uint32_t offset, se, sh, cu, wave, simd, thread, bank, *data; + +- if (size & 3 || *pos & 3) ++ if (size > 4096 || size & 3 || *pos & 3) + return -EINVAL; + + /* decode offset */ +- offset = *pos & GENMASK_ULL(11, 0); ++ offset = (*pos & GENMASK_ULL(11, 0)) >> 2; + se = (*pos & GENMASK_ULL(19, 12)) >> 12; + sh = (*pos & GENMASK_ULL(27, 20)) >> 20; + cu = (*pos & GENMASK_ULL(35, 28)) >> 28; +@@ -823,7 +823,7 @@ static ssize_t amdgpu_debugfs_gpr_read(struct file *f, char __user *buf, + while (size) { + uint32_t value; + +- value = data[offset++]; ++ value = data[result >> 2]; + r = put_user(value, (uint32_t *)buf); + if (r) { + result = r; +-- +2.26.0 + diff --git a/patches.suse/0001-drm-amd-dm-mst-Ignore-payload-update-failures.patch b/patches.suse/0001-drm-amd-dm-mst-Ignore-payload-update-failures.patch new file mode 100644 index 0000000..e1f03c2 --- /dev/null +++ b/patches.suse/0001-drm-amd-dm-mst-Ignore-payload-update-failures.patch @@ -0,0 +1,165 @@ +From 58fe03d6dec908a1bec07eea7e94907af5c07eec Mon Sep 17 00:00:00 2001 +From: Lyude Paul +Date: Fri, 24 Jan 2020 14:10:46 -0500 +Subject: drm/amd/dm/mst: Ignore payload update failures +Git-commit: 58fe03d6dec908a1bec07eea7e94907af5c07eec +Patch-mainline: v5.6-rc1 +References: bsc#1112178 + +Disabling a display on MST can potentially happen after the entire MST +topology has been removed, which means that we can't communicate with +the topology at all in this scenario. Likewise, this also means that we +can't properly update payloads on the topology and as such, it's a good +idea to ignore payload update failures when disabling displays. +Currently, amdgpu makes the mistake of halting the payload update +process when any payload update failures occur, resulting in leaving +DC's local copies of the payload tables out of date. + +This ends up causing problems with hotplugging MST topologies, and +causes modesets on the second hotplug to fail like so: + +[drm] Failed to updateMST allocation table forpipe idx:1 +------------[ cut here ]------------ +WARNING: CPU: 5 PID: 1511 at +drivers/gpu/drm/amd/amdgpu/../display/dc/core/dc_link.c:2677 +update_mst_stream_alloc_table+0x11e/0x130 [amdgpu] +Modules linked in: cdc_ether usbnet fuse xt_conntrack nf_conntrack +nf_defrag_ipv6 libcrc32c nf_defrag_ipv4 ipt_REJECT nf_reject_ipv4 +nft_counter nft_compat nf_tables nfnetlink tun bridge stp llc sunrpc +vfat fat wmi_bmof uvcvideo snd_hda_codec_realtek snd_hda_codec_generic +snd_hda_codec_hdmi videobuf2_vmalloc snd_hda_intel videobuf2_memops +videobuf2_v4l2 snd_intel_dspcfg videobuf2_common crct10dif_pclmul +snd_hda_codec videodev crc32_pclmul snd_hwdep snd_hda_core +ghash_clmulni_intel snd_seq mc joydev pcspkr snd_seq_device snd_pcm +sp5100_tco k10temp i2c_piix4 snd_timer thinkpad_acpi ledtrig_audio snd +wmi soundcore video i2c_scmi acpi_cpufreq ip_tables amdgpu(O) +rtsx_pci_sdmmc amd_iommu_v2 gpu_sched mmc_core i2c_algo_bit ttm +drm_kms_helper syscopyarea sysfillrect sysimgblt fb_sys_fops cec drm +crc32c_intel serio_raw hid_multitouch r8152 mii nvme r8169 nvme_core +rtsx_pci pinctrl_amd +CPU: 5 PID: 1511 Comm: gnome-shell Tainted: G O 5.5.0-rc7Lyude-Test+ #4 +Hardware name: LENOVO FA495SIT26/FA495SIT26, BIOS R12ET22W(0.22 ) 01/31/2019 +RIP: 0010:update_mst_stream_alloc_table+0x11e/0x130 [amdgpu] +Code: 28 00 00 00 75 2b 48 8d 65 e0 5b 41 5c 41 5d 41 5e 5d c3 0f b6 06 +49 89 1c 24 41 88 44 24 08 0f b6 46 01 41 88 44 24 09 eb 93 <0f> 0b e9 +2f ff ff ff e8 a6 82 a3 c2 66 0f 1f 44 00 00 0f 1f 44 00 +RSP: 0018:ffffac428127f5b0 EFLAGS: 00010202 +RAX: 0000000000000002 RBX: ffff8d1e166eee80 RCX: 0000000000000000 +RDX: ffffac428127f668 RSI: ffff8d1e166eee80 RDI: ffffac428127f610 +RBP: ffffac428127f640 R08: ffffffffc03d94a8 R09: 0000000000000000 +R10: ffff8d1e24b02000 R11: ffffac428127f5b0 R12: ffff8d1e1b83d000 +R13: ffff8d1e1bea0b08 R14: 0000000000000002 R15: 0000000000000002 +FS: 00007fab23ffcd80(0000) GS:ffff8d1e28b40000(0000) knlGS:0000000000000000 +CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 +CR2: 00007f151f1711e8 CR3: 00000005997c0000 CR4: 00000000003406e0 +Call Trace: + ? mutex_lock+0xe/0x30 + dc_link_allocate_mst_payload+0x9a/0x210 [amdgpu] + ? dm_read_reg_func+0x39/0xb0 [amdgpu] + ? core_link_enable_stream+0x656/0x730 [amdgpu] + core_link_enable_stream+0x656/0x730 [amdgpu] + dce110_apply_ctx_to_hw+0x58e/0x5d0 [amdgpu] + ? dcn10_verify_allow_pstate_change_high+0x1d/0x280 [amdgpu] + ? dcn10_wait_for_mpcc_disconnect+0x3c/0x130 [amdgpu] + dc_commit_state+0x292/0x770 [amdgpu] + ? add_timer+0x101/0x1f0 + ? ttm_bo_put+0x1a1/0x2f0 [ttm] + amdgpu_dm_atomic_commit_tail+0xb59/0x1ff0 [amdgpu] + ? amdgpu_move_blit.constprop.0+0xb8/0x1f0 [amdgpu] + ? amdgpu_bo_move+0x16d/0x2b0 [amdgpu] + ? ttm_bo_handle_move_mem+0x118/0x570 [ttm] + ? ttm_bo_validate+0x134/0x150 [ttm] + ? dm_plane_helper_prepare_fb+0x1b9/0x2a0 [amdgpu] + ? _cond_resched+0x15/0x30 + ? wait_for_completion_timeout+0x38/0x160 + ? _cond_resched+0x15/0x30 + ? wait_for_completion_interruptible+0x33/0x190 + commit_tail+0x94/0x130 [drm_kms_helper] + drm_atomic_helper_commit+0x113/0x140 [drm_kms_helper] + drm_atomic_helper_set_config+0x70/0xb0 [drm_kms_helper] + drm_mode_setcrtc+0x194/0x6a0 [drm] + ? _cond_resched+0x15/0x30 + ? mutex_lock+0xe/0x30 + ? drm_mode_getcrtc+0x180/0x180 [drm] + drm_ioctl_kernel+0xaa/0xf0 [drm] + drm_ioctl+0x208/0x390 [drm] + ? drm_mode_getcrtc+0x180/0x180 [drm] + amdgpu_drm_ioctl+0x49/0x80 [amdgpu] + do_vfs_ioctl+0x458/0x6d0 + ksys_ioctl+0x5e/0x90 + __x64_sys_ioctl+0x16/0x20 + do_syscall_64+0x55/0x1b0 + entry_SYSCALL_64_after_hwframe+0x44/0xa9 +RIP: 0033:0x7fab2121f87b +Code: 0f 1e fa 48 8b 05 0d 96 2c 00 64 c7 00 26 00 00 00 48 c7 c0 ff ff +ff ff c3 66 0f 1f 44 00 00 f3 0f 1e fa b8 10 00 00 00 0f 05 <48> 3d 01 +f0 ff ff 73 01 c3 48 8b 0d dd 95 2c 00 f7 d8 64 89 01 48 +RSP: 002b:00007ffd045f9068 EFLAGS: 00000246 ORIG_RAX: 0000000000000010 +RAX: ffffffffffffffda RBX: 00007ffd045f90a0 RCX: 00007fab2121f87b +RDX: 00007ffd045f90a0 RSI: 00000000c06864a2 RDI: 000000000000000b +RBP: 00007ffd045f90a0 R08: 0000000000000000 R09: 000055dbd2985d10 +R10: 000055dbd2196280 R11: 0000000000000246 R12: 00000000c06864a2 +R13: 000000000000000b R14: 0000000000000000 R15: 000055dbd2196280 +---[ end trace 6ea888c24d2059cd ]--- + +Note as well, I have only been able to reproduce this on setups with 2 +MST displays. + +Changes since v1: +* Don't return false when part 1 or part 2 of updating the payloads + fails, we don't want to abort at any step of the process even if + things fail + +Reviewed-by: Mikita Lipski +Signed-off-by: Lyude Paul +Acked-by: Harry Wentland +Cc: stable@vger.kernel.org +Signed-off-by: Alex Deucher +Acked-by: Thomas Zimmermann +--- + drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c | 13 ++++--------- + 1 file changed, 4 insertions(+), 9 deletions(-) + +--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c ++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c +@@ -248,7 +248,8 @@ bool dm_helpers_dp_mst_write_payload_all + drm_dp_mst_reset_vcpi_slots(mst_mgr, mst_port); + } + +- ret = drm_dp_update_payload_part1(mst_mgr); ++ /* It's OK for this to fail */ ++ drm_dp_update_payload_part1(mst_mgr); + + /* mst_mgr->->payloads are VC payload notify MST branch using DPCD or + * AUX message. The sequence is slot 1-63 allocated sequence for each +@@ -257,9 +258,6 @@ bool dm_helpers_dp_mst_write_payload_all + + get_payload_table(aconnector, proposed_table); + +- if (ret) +- return false; +- + return true; + } + +@@ -310,7 +308,6 @@ bool dm_helpers_dp_mst_send_payload_allo + struct amdgpu_dm_connector *aconnector; + struct drm_dp_mst_topology_mgr *mst_mgr; + struct drm_dp_mst_port *mst_port; +- int ret; + + aconnector = stream->sink->priv; + +@@ -324,10 +321,8 @@ bool dm_helpers_dp_mst_send_payload_allo + if (!mst_mgr->mst_state) + return false; + +- ret = drm_dp_update_payload_part2(mst_mgr); +- +- if (ret) +- return false; ++ /* It's OK for this to fail */ ++ drm_dp_update_payload_part2(mst_mgr); + + if (!enable) + drm_dp_mst_deallocate_vcpi(mst_mgr, mst_port); diff --git a/patches.suse/0001-drm-amdkfd-fix-a-use-after-free-race-with-mmu_notife.patch b/patches.suse/0001-drm-amdkfd-fix-a-use-after-free-race-with-mmu_notife.patch new file mode 100644 index 0000000..08bf088 --- /dev/null +++ b/patches.suse/0001-drm-amdkfd-fix-a-use-after-free-race-with-mmu_notife.patch @@ -0,0 +1,200 @@ +From 0029cab3146a53b820e73c9cd70809b831c590d7 Mon Sep 17 00:00:00 2001 +From: Jason Gunthorpe +Date: Tue, 6 Aug 2019 20:15:46 -0300 +Subject: drm/amdkfd: fix a use after free race with mmu_notifer unregister +Git-commit: 0029cab3146a53b820e73c9cd70809b831c590d7 +Patch-mainline: v5.4-rc1 +References: bsc#1114279 bsc#1154048 + +When using mmu_notifer_unregister_no_release() the caller must ensure +there is a SRCU synchronize before the mn memory is freed, otherwise use +after free races are possible, for instance: + + CPU0 CPU1 + invalidate_range_start + hlist_for_each_entry_rcu(..) + mmu_notifier_unregister_no_release(&p->mn) + kfree(mn) + if (mn->ops->invalidate_range_end) + +The error unwind in amdkfd misses the SRCU synchronization. + +amdkfd keeps the kfd_process around until the mm is released, so split the +flow to fully initialize the kfd_process and register it for find_process, +and with the notifier. Past this point the kfd_process does not need to be +cleaned up as it is fully ready. + +The final failable step does a vm_mmap() and does not seem to impact the +kfd_process global state. Since it also cannot be undone (and already has +problems with undo if it internally fails), it has to be last. + +This way we don't have to try to unwind the mmu_notifier_register() and +avoid the problem with the SRCU. + +Along the way this also fixes various other error unwind bugs in the flow. + +Fixes: 45102048f77e ("amdkfd: Add process queue manager module") +Link: https://lore.kernel.org/r/20190806231548.25242-10-jgg@ziepe.ca +Reviewed-by: Felix Kuehling +Signed-off-by: Jason Gunthorpe +Acked-by: Thomas Zimmermann +[ pt: kfd_create_process() error path added from upstream commit + de9f26bbd3842a7e8fca4f88b448636cc56319ff. ] +Signed-off-by: Petr Tesarik +--- + drivers/gpu/drm/amd/amdkfd/kfd_process.c | 81 ++++++++++++++----------------- + 1 file changed, 39 insertions(+), 42 deletions(-) + +--- a/drivers/gpu/drm/amd/amdkfd/kfd_process.c ++++ b/drivers/gpu/drm/amd/amdkfd/kfd_process.c +@@ -62,8 +62,8 @@ static struct workqueue_struct *kfd_restore_wq; + + static struct kfd_process *find_process(const struct task_struct *thread); + static void kfd_process_ref_release(struct kref *ref); +-static struct kfd_process *create_process(const struct task_struct *thread, +- struct file *filep); ++static struct kfd_process *create_process(const struct task_struct *thread); ++static int kfd_process_init_cwsr_apu(struct kfd_process *p, struct file *filep); + + static void evict_process_worker(struct work_struct *work); + static void restore_process_worker(struct work_struct *work); +@@ -206,6 +268,7 @@ struct kfd_process *kfd_create_process(struct file *filep) + { + struct kfd_process *process; + struct task_struct *thread = current; ++ int ret; + + if (!thread->mm) + return ERR_PTR(-EINVAL); +@@ -287,11 +287,20 @@ struct kfd_process *kfd_create_process(struct file *filep) + + /* A prior open of /dev/kfd could have already created the process. */ + process = find_process(thread); +- if (process) ++ if (process) { + pr_debug("Process already found\n"); +- else +- process = create_process(thread, filep); ++ } else { ++ process = create_process(thread); ++ if (IS_ERR(process)) ++ goto out; + ++ ret = kfd_process_init_cwsr_apu(process, filep); ++ if (ret) { ++ process = ERR_PTR(ret); ++ goto out; ++ } ++ } ++out: + mutex_unlock(&kfd_processes_mutex); + + return process; +@@ -609,81 +617,69 @@ static int kfd_process_device_init_cwsr_dgpu(struct kfd_process_device *pdd) + return 0; + } + +-static struct kfd_process *create_process(const struct task_struct *thread, +- struct file *filep) ++/* ++ * On return the kfd_process is fully operational and will be freed when the ++ * mm is released ++ */ ++static struct kfd_process *create_process(const struct task_struct *thread) + { + struct kfd_process *process; + int err = -ENOMEM; + + process = kzalloc(sizeof(*process), GFP_KERNEL); +- + if (!process) + goto err_alloc_process; + +- process->pasid = kfd_pasid_alloc(); +- if (process->pasid == 0) +- goto err_alloc_pasid; +- +- if (kfd_alloc_process_doorbells(process) < 0) +- goto err_alloc_doorbells; +- + kref_init(&process->ref); +- + mutex_init(&process->mutex); +- + process->mm = thread->mm; +- +- /* register notifier */ +- process->mmu_notifier.ops = &kfd_process_mmu_notifier_ops; +- err = mmu_notifier_register(&process->mmu_notifier, process->mm); +- if (err) +- goto err_mmu_notifier; +- +- hash_add_rcu(kfd_processes_table, &process->kfd_processes, +- (uintptr_t)process->mm); +- + process->lead_thread = thread->group_leader; +- get_task_struct(process->lead_thread); +- + INIT_LIST_HEAD(&process->per_device_data); +- ++ INIT_DELAYED_WORK(&process->eviction_work, evict_process_worker); ++ INIT_DELAYED_WORK(&process->restore_work, restore_process_worker); ++ process->last_restore_timestamp = get_jiffies_64(); + kfd_event_init_process(process); ++ process->is_32bit_user_mode = in_compat_syscall(); ++ ++ process->pasid = kfd_pasid_alloc(); ++ if (process->pasid == 0) ++ goto err_alloc_pasid; ++ ++ if (kfd_alloc_process_doorbells(process) < 0) ++ goto err_alloc_doorbells; + + err = pqm_init(&process->pqm, process); + if (err != 0) + goto err_process_pqm_init; + + /* init process apertures*/ +- process->is_32bit_user_mode = in_compat_syscall(); + err = kfd_init_apertures(process); + if (err != 0) + goto err_init_apertures; + +- INIT_DELAYED_WORK(&process->eviction_work, evict_process_worker); +- INIT_DELAYED_WORK(&process->restore_work, restore_process_worker); +- process->last_restore_timestamp = get_jiffies_64(); +- +- err = kfd_process_init_cwsr_apu(process, filep); ++ /* Must be last, have to use release destruction after this */ ++ process->mmu_notifier.ops = &kfd_process_mmu_notifier_ops; ++ err = mmu_notifier_register(&process->mmu_notifier, process->mm); + if (err) +- goto err_init_cwsr; ++ goto err_register_notifier; ++ ++ get_task_struct(process->lead_thread); ++ hash_add_rcu(kfd_processes_table, &process->kfd_processes, ++ (uintptr_t)process->mm); + + return process; + +-err_init_cwsr: ++err_register_notifier: + kfd_process_free_outstanding_kfd_bos(process); + kfd_process_destroy_pdds(process); + err_init_apertures: + pqm_uninit(&process->pqm); + err_process_pqm_init: +- hash_del_rcu(&process->kfd_processes); +- synchronize_rcu(); +- mmu_notifier_unregister_no_release(&process->mmu_notifier, process->mm); +-err_mmu_notifier: +- mutex_destroy(&process->mutex); + kfd_free_process_doorbells(process); + err_alloc_doorbells: + kfd_pasid_free(process->pasid); + err_alloc_pasid: ++ mutex_destroy(&process->mutex); + kfree(process); + err_alloc_process: + return ERR_PTR(err); diff --git a/patches.suse/0001-drm-atmel-hlcdc-enable-clock-before-configuring-timi.patch b/patches.suse/0001-drm-atmel-hlcdc-enable-clock-before-configuring-timi.patch new file mode 100644 index 0000000..9260d16 --- /dev/null +++ b/patches.suse/0001-drm-atmel-hlcdc-enable-clock-before-configuring-timi.patch @@ -0,0 +1,51 @@ +From 2c1fb9d86f6820abbfaa38a6836157c76ccb4e7b Mon Sep 17 00:00:00 2001 +From: Claudiu Beznea +Date: Wed, 18 Dec 2019 14:28:25 +0200 +Subject: drm: atmel-hlcdc: enable clock before configuring timing engine +Git-commit: 2c1fb9d86f6820abbfaa38a6836157c76ccb4e7b +Patch-mainline: v5.6-rc1 +References: bsc#1114279 + +Changing pixel clock source without having this clock source enabled +will block the timing engine and the next operations after (in this case +setting ATMEL_HLCDC_CFG(5) settings in atmel_hlcdc_crtc_mode_set_nofb() +will fail). It is recomended (although in datasheet this is not present) +to actually enabled pixel clock source before doing any changes on timing +enginge (only SAM9X60 datasheet specifies that the peripheral clock and +pixel clock must be enabled before using LCD controller). + +Fixes: 1a396789f65a ("drm: add Atmel HLCDC Display Controller support") +Signed-off-by: Claudiu Beznea +Signed-off-by: Sam Ravnborg +Cc: Boris Brezillon +Cc: # v4.0+ +Link: https://patchwork.freedesktop.org/patch/msgid/1576672109-22707-3-git-send-email-claudiu.beznea@microchip.com +Acked-by: Thomas Zimmermann +--- + drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c | 8 +++++++- + 1 file changed, 7 insertions(+), 1 deletion(-) + +--- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c ++++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c +@@ -79,7 +79,11 @@ static void atmel_hlcdc_crtc_mode_set_no + struct videomode vm; + unsigned long prate; + unsigned int cfg; +- int div; ++ int div, ret; ++ ++ ret = clk_prepare_enable(crtc->dc->hlcdc->sys_clk); ++ if (ret) ++ return; + + vm.vfront_porch = adj->crtc_vsync_start - adj->crtc_vdisplay; + vm.vback_porch = adj->crtc_vtotal - adj->crtc_vsync_end; +@@ -138,6 +142,8 @@ static void atmel_hlcdc_crtc_mode_set_no + ATMEL_HLCDC_VSPSU | ATMEL_HLCDC_VSPHO | + ATMEL_HLCDC_GUARDTIME_MASK | ATMEL_HLCDC_MODE_MASK, + cfg); ++ ++ clk_disable_unprepare(crtc->dc->hlcdc->sys_clk); + } + + static enum drm_mode_status diff --git a/patches.suse/0001-drm-etnaviv-fix-dumping-of-iommuv2.patch b/patches.suse/0001-drm-etnaviv-fix-dumping-of-iommuv2.patch new file mode 100644 index 0000000..116f759 --- /dev/null +++ b/patches.suse/0001-drm-etnaviv-fix-dumping-of-iommuv2.patch @@ -0,0 +1,38 @@ +From a2f10d4a3069fee666dab20fab5458757ba1f22d Mon Sep 17 00:00:00 2001 +From: Christian Gmeiner +Date: Fri, 25 Oct 2019 12:39:10 +0200 +Subject: drm/etnaviv: fix dumping of iommuv2 +Git-commit: a2f10d4a3069fee666dab20fab5458757ba1f22d +Patch-mainline: v5.4-rc6 +References: bsc#1114279 + +etnaviv_iommuv2_dump_size(..) returns the number of PTE * SZ_4K but +etnaviv_iommuv2_dump(..) increments buf pointer even if there is no PTE. +This results in a bad buf pointer which gets used for memcpy(..), when +copying the MMU state in the coredump buffer. + +Fixes: afb7b3b1deb4 ("drm/etnaviv: implement IOMMUv2 translation") +Cc: stable@vger.kernel.org +Signed-off-by: Christian Gmeiner +Signed-off-by: Lucas Stach +Acked-by: Thomas Zimmermann +--- + drivers/gpu/drm/etnaviv/etnaviv_iommu_v2.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +--- a/drivers/gpu/drm/etnaviv/etnaviv_iommu_v2.c ++++ b/drivers/gpu/drm/etnaviv/etnaviv_iommu_v2.c +@@ -225,9 +225,11 @@ static void etnaviv_iommuv2_dump(struct + + memcpy(buf, etnaviv_domain->mtlb_cpu, SZ_4K); + buf += SZ_4K; +- for (i = 0; i < MMUv2_MAX_STLB_ENTRIES; i++, buf += SZ_4K) +- if (etnaviv_domain->mtlb_cpu[i] & MMUv2_PTE_PRESENT) ++ for (i = 0; i < MMUv2_MAX_STLB_ENTRIES; i++) ++ if (etnaviv_domain->mtlb_cpu[i] & MMUv2_PTE_PRESENT) { + memcpy(buf, etnaviv_domain->stlb_cpu[i], SZ_4K); ++ buf += SZ_4K; ++ } + } + + static void etnaviv_iommuv2_restore_nonsec(struct etnaviv_gpu *gpu) diff --git a/patches.suse/0001-drm-i915-Wean-off-drm_pci_alloc-drm_pci_free.patch b/patches.suse/0001-drm-i915-Wean-off-drm_pci_alloc-drm_pci_free.patch new file mode 100644 index 0000000..a8a71f7 --- /dev/null +++ b/patches.suse/0001-drm-i915-Wean-off-drm_pci_alloc-drm_pci_free.patch @@ -0,0 +1,253 @@ +From aa3146193ae25d0fe4b96d815169a135db2e8f01 Mon Sep 17 00:00:00 2001 +From: Chris Wilson +Date: Sun, 2 Feb 2020 15:39:34 +0000 +Subject: drm/i915: Wean off drm_pci_alloc/drm_pci_free +Git-commit: aa3146193ae25d0fe4b96d815169a135db2e8f01 +Patch-mainline: v5.6-rc3 +References: bsc#1114279 + +drm_pci_alloc and drm_pci_free are just very thin wrappers around +dma_alloc_coherent, with a note that we should be removing them. +Furthermore since + +commit de09d31dd38a50fdce106c15abd68432eebbd014 +Author: Kirill A. Shutemov +Date: Fri Jan 15 16:51:42 2016 -0800 + + page-flags: define PG_reserved behavior on compound pages + + As far as I can see there's no users of PG_reserved on compound pages. + Let's use PF_NO_COMPOUND here. + +drm_pci_alloc has been declared broken since it mixes GFP_COMP and +SetPageReserved. Avoid this conflict by weaning ourselves off using the +abstraction and using the dma functions directly. + +Reported-by: Taketo Kabe +Closes: https://gitlab.freedesktop.org/drm/intel/issues/1027 +Fixes: de09d31dd38a ("page-flags: define PG_reserved behavior on compound pages") +Signed-off-by: Chris Wilson +Cc: # v4.5+ +Reviewed-by: Daniel Vetter +Link: https://patchwork.freedesktop.org/patch/msgid/20200202153934.3899472-1-chris@chris-wilson.co.uk +(cherry picked from commit c6790dc22312f592c1434577258b31c48c72d52a) +Signed-off-by: Jani Nikula +Acked-by: Thomas Zimmermann +--- + drivers/gpu/drm/i915/i915_gem.c | 105 ++++++++++++++++----------------- + drivers/gpu/drm/i915/i915_gem_object.h | 3 + drivers/gpu/drm/i915/intel_display.c | 2 + 3 files changed, 55 insertions(+), 55 deletions(-) + +--- a/drivers/gpu/drm/i915/i915_gem.c ++++ b/drivers/gpu/drm/i915/i915_gem.c +@@ -165,77 +165,74 @@ static struct sg_table * + static int i915_gem_object_get_pages_phys(struct drm_i915_gem_object *obj) + { + struct address_space *mapping = obj->base.filp->f_mapping; +- drm_dma_handle_t *phys; +- struct sg_table *st; + struct scatterlist *sg; +- char *vaddr; + int i; +- int err; ++ struct sg_table *st; ++ dma_addr_t dma; ++ void *vaddr; ++ void *dst; + + if (WARN_ON(i915_gem_object_needs_bit17_swizzle(obj))) + return -EINVAL; + +- /* Always aligning to the object size, allows a single allocation ++ /* ++ * Always aligning to the object size, allows a single allocation + * to handle all possible callers, and given typical object sizes, + * the alignment of the buddy allocation will naturally match. + */ +- phys = drm_pci_alloc(obj->base.dev, +- roundup_pow_of_two(obj->base.size), +- roundup_pow_of_two(obj->base.size)); +- if (!phys) ++ vaddr = dma_alloc_coherent(&obj->base.dev->pdev->dev, ++ roundup_pow_of_two(obj->base.size), ++ &dma, GFP_KERNEL); ++ if (!vaddr) + return -ENOMEM; + +- vaddr = phys->vaddr; ++ st = kmalloc(sizeof(*st), GFP_KERNEL); ++ if (!st) ++ goto err_pci; ++ ++ if (sg_alloc_table(st, 1, GFP_KERNEL)) ++ goto err_st; ++ ++ sg = st->sgl; ++ sg->offset = 0; ++ sg->length = obj->base.size; ++ ++ sg_assign_page(sg, (struct page *)vaddr); ++ sg_dma_address(sg) = dma; ++ sg_dma_len(sg) = obj->base.size; ++ ++ dst = vaddr; + for (i = 0; i < obj->base.size / PAGE_SIZE; i++) { + struct page *page; +- char *src; ++ void *src; + + page = shmem_read_mapping_page(mapping, i); +- if (IS_ERR(page)) { +- err = PTR_ERR(page); +- goto err_phys; +- } ++ if (IS_ERR(page)) ++ goto err_st; + + src = kmap_atomic(page); +- memcpy(vaddr, src, PAGE_SIZE); +- drm_clflush_virt_range(vaddr, PAGE_SIZE); ++ memcpy(dst, src, PAGE_SIZE); ++ drm_clflush_virt_range(dst, PAGE_SIZE); + kunmap_atomic(src); + + put_page(page); +- vaddr += PAGE_SIZE; ++ dst += PAGE_SIZE; + } + + i915_gem_chipset_flush(to_i915(obj->base.dev)); + +- st = kmalloc(sizeof(*st), GFP_KERNEL); +- if (!st) { +- err = -ENOMEM; +- goto err_phys; +- } +- +- if (sg_alloc_table(st, 1, GFP_KERNEL)) { +- kfree(st); +- err = -ENOMEM; +- goto err_phys; +- } +- +- sg = st->sgl; +- sg->offset = 0; +- sg->length = obj->base.size; +- +- sg_dma_address(sg) = phys->busaddr; +- sg_dma_len(sg) = obj->base.size; +- +- obj->phys_handle = phys; + + __i915_gem_object_set_pages(obj, st, sg->length); + + return 0; + +-err_phys: +- drm_pci_free(obj->base.dev, phys); +- +- return err; ++err_st: ++ kfree(st); ++err_pci: ++ dma_free_coherent(&obj->base.dev->pdev->dev, ++ roundup_pow_of_two(obj->base.size), ++ vaddr, dma); ++ return -ENOMEM; + } + + static void __start_cpu_write(struct drm_i915_gem_object *obj) +@@ -263,11 +262,14 @@ static void + i915_gem_object_put_pages_phys(struct drm_i915_gem_object *obj, + struct sg_table *pages) + { ++ dma_addr_t dma = sg_dma_address(pages->sgl); ++ void *vaddr = sg_page(pages->sgl); ++ + __i915_gem_object_release_shmem(obj, pages, false); + + if (obj->mm.dirty) { + struct address_space *mapping = obj->base.filp->f_mapping; +- char *vaddr = obj->phys_handle->vaddr; ++ void *src = vaddr; + int i; + + for (i = 0; i < obj->base.size / PAGE_SIZE; i++) { +@@ -279,15 +281,16 @@ i915_gem_object_put_pages_phys(struct dr + continue; + + dst = kmap_atomic(page); +- drm_clflush_virt_range(vaddr, PAGE_SIZE); +- memcpy(dst, vaddr, PAGE_SIZE); ++ drm_clflush_virt_range(src, PAGE_SIZE); ++ memcpy(dst, src, PAGE_SIZE); + kunmap_atomic(dst); + + set_page_dirty(page); + if (obj->mm.madv == I915_MADV_WILLNEED) + mark_page_accessed(page); + put_page(page); +- vaddr += PAGE_SIZE; ++ ++ src += PAGE_SIZE; + } + obj->mm.dirty = false; + } +@@ -295,7 +298,9 @@ i915_gem_object_put_pages_phys(struct dr + sg_free_table(pages); + kfree(pages); + +- drm_pci_free(obj->base.dev, obj->phys_handle); ++ dma_free_coherent(&obj->base.dev->pdev->dev, ++ roundup_pow_of_two(obj->base.size), ++ vaddr, dma); + } + + static void +@@ -569,7 +574,7 @@ i915_gem_phys_pwrite(struct drm_i915_gem + struct drm_i915_gem_pwrite *args, + struct drm_file *file) + { +- void *vaddr = obj->phys_handle->vaddr + args->offset; ++ void *vaddr = sg_page(obj->mm.pages->sgl) + args->offset; + char __user *user_data = u64_to_user_ptr(args->data_ptr); + + /* We manually control the domain here and pretend that it +@@ -1542,10 +1547,10 @@ i915_gem_pwrite_ioctl(struct drm_device + ret = i915_gem_gtt_pwrite_fast(obj, args); + + if (ret == -EFAULT || ret == -ENOSPC) { +- if (obj->phys_handle) +- ret = i915_gem_phys_pwrite(obj, args, file); +- else ++ if (i915_gem_object_has_struct_page(obj)) + ret = i915_gem_shmem_pwrite(obj, args); ++ else ++ ret = i915_gem_phys_pwrite(obj, args, file); + } + + i915_gem_object_unpin_pages(obj); +--- a/drivers/gpu/drm/i915/i915_gem_object.h ++++ b/drivers/gpu/drm/i915/i915_gem_object.h +@@ -233,9 +233,6 @@ struct drm_i915_gem_object { + void *gvt_info; + }; + +- /** for phys allocated objects */ +- struct drm_dma_handle *phys_handle; +- + struct reservation_object __builtin_resv; + }; + +--- a/drivers/gpu/drm/i915/intel_display.c ++++ b/drivers/gpu/drm/i915/intel_display.c +@@ -9280,7 +9280,7 @@ static u32 intel_cursor_base(const struc + u32 base; + + if (INTEL_INFO(dev_priv)->cursor_needs_physical) +- base = obj->phys_handle->busaddr; ++ base = sg_dma_address(obj->mm.pages->sgl); + else + base = intel_plane_ggtt_offset(plane_state); + diff --git a/patches.suse/0001-drm-i915-gvt-Separate-display-reset-from-ALL_ENGINES.patch b/patches.suse/0001-drm-i915-gvt-Separate-display-reset-from-ALL_ENGINES.patch new file mode 100644 index 0000000..adad495 --- /dev/null +++ b/patches.suse/0001-drm-i915-gvt-Separate-display-reset-from-ALL_ENGINES.patch @@ -0,0 +1,96 @@ +From 3eb55e6f753a379e293395de8d5f3be28351a7f8 Mon Sep 17 00:00:00 2001 +From: Tina Zhang +Date: Fri, 21 Feb 2020 10:32:34 +0800 +Subject: drm/i915/gvt: Separate display reset from ALL_ENGINES reset +Git-commit: 3eb55e6f753a379e293395de8d5f3be28351a7f8 +Patch-mainline: v5.6-rc4 +References: bsc#1114279 + +ALL_ENGINES reset doesn't clobber display with the current gvt-g +supported platforms. Thus ALL_ENGINES reset shouldn't reset the +display engine registers emulated by gvt-g. + +This fixes guest warning like + +[ 14.622026] [drm] Initialized i915 1.6.0 20200114 for 0000:00:03.0 on minor 0 +[ 14.967917] fbcon: i915drmfb (fb0) is primary device +[ 25.100188] [drm:drm_atomic_helper_wait_for_dependencies [drm_kms_helper]] E RROR [CRTC:51:pipe A] flip_done timed out +[ 25.100860] -----------[ cut here ]----------- +[ 25.100861] pll on state mismatch (expected 0, found 1) +[ 25.101024] WARNING: CPU: 1 PID: 30 at drivers/gpu/drm/i915/display/intel_dis play.c:14382 verify_single_dpll_state.isra.115+0x28f/0x320 [i915] +[ 25.101025] Modules linked in: intel_rapl_msr intel_rapl_common kvm_intel kvm irqbypass crct10dif_pclmul crc32_pclmul ghash_clmulni_intel i915 aesni_intel cr ypto_simd cryptd glue_helper cec rc_core video drm_kms_helper joydev drm input_l eds i2c_algo_bit serio_raw fb_sys_fops syscopyarea sysfillrect sysimgblt mac_hid qemu_fw_cfg sch_fq_codel parport_pc ppdev lp parport ip_tables x_tables autofs4 e1000 psmouse i2c_piix4 pata_acpi floppy +[ 25.101052] CPU: 1 PID: 30 Comm: kworker/u4:1 Not tainted 5.5.0+ #1 +[ 25.101053] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1 .12.1-0-ga5cab58 04/01/2014 +[ 25.101055] Workqueue: events_unbound async_run_entry_fn +[ 25.101092] RIP: 0010:verify_single_dpll_state.isra.115+0x28f/0x320 [i915] +[ 25.101093] Code: e0 d9 ff e9 a3 fe ff ff 80 3d e9 c2 11 00 00 44 89 f6 48 c7 c7 c0 9d 88 c0 75 3b e8 eb df d9 ff e9 c7 fe ff ff e8 d1 e0 ae c4 <0f> 0b e9 7a fe ff ff 80 3d c0 c2 11 00 00 8d 71 41 89 c2 48 c7 c7 +[ 25.101093] RSP: 0018:ffffb1de80107878 EFLAGS: 00010286 +[ 25.101094] RAX: 0000000000000000 RBX: ffffb1de80107884 RCX: 0000000000000007 +[ 25.101095] RDX: 0000000000000000 RSI: 0000000000000002 RDI: ffff94fdfdd19740 +[ 25.101095] RBP: ffffb1de80107938 R08: 0000000d6bfdc7b4 R09: 000000000000002b +[ 25.101096] R10: ffff94fdf82dc000 R11: 0000000000000225 R12: 00000000000001f8 +[ 25.101096] R13: ffff94fdb3ca6a90 R14: ffff94fdb3ca0000 R15: 0000000000000000 +[ 25.101097] FS: 0000000000000000(0000) GS:ffff94fdfdd00000(0000) knlGS:00000 00000000000 +[ 25.101098] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 +[ 25.101098] CR2: 00007fbc3e2be9c8 CR3: 000000003339a003 CR4: 0000000000360ee0 +[ 25.101101] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 +[ 25.101101] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 +[ 25.101102] Call Trace: +[ 25.101139] intel_atomic_commit_tail+0xde4/0x1520 [i915] +[ 25.101141] ? flush_workqueue_prep_pwqs+0xfa/0x130 +[ 25.101142] ? flush_workqueue+0x198/0x3c0 +[ 25.101174] intel_atomic_commit+0x2ad/0x320 [i915] +[ 25.101209] drm_atomic_commit+0x4a/0x50 [drm] +[ 25.101220] drm_client_modeset_commit_atomic+0x1c4/0x200 [drm] +[ 25.101231] drm_client_modeset_commit_force+0x47/0x170 [drm] +[ 25.101250] drm_fb_helper_restore_fbdev_mode_unlocked+0x4e/0xa0 [drm_kms_hel per] +[ 25.101255] drm_fb_helper_set_par+0x2d/0x60 [drm_kms_helper] +[ 25.101287] intel_fbdev_set_par+0x1a/0x40 [i915] +[ 25.101289] ? con_is_visible+0x2e/0x60 +[ 25.101290] fbcon_init+0x378/0x600 +[ 25.101292] visual_init+0xd5/0x130 +[ 25.101296] do_bind_con_driver+0x217/0x430 +[ 25.101297] do_take_over_console+0x7d/0x1b0 +[ 25.101298] do_fbcon_takeover+0x5c/0xb0 +[ 25.101299] fbcon_fb_registered+0x199/0x1a0 +[ 25.101301] register_framebuffer+0x22c/0x330 +[ 25.101306] __drm_fb_helper_initial_config_and_unlock+0x31a/0x520 [drm_kms_h elper] +[ 25.101311] drm_fb_helper_initial_config+0x35/0x40 [drm_kms_helper] +[ 25.101341] intel_fbdev_initial_config+0x18/0x30 [i915] +[ 25.101342] async_run_entry_fn+0x3c/0x150 +[ 25.101343] process_one_work+0x1fd/0x3f0 +[ 25.101344] worker_thread+0x34/0x410 +[ 25.101346] kthread+0x121/0x140 +[ 25.101346] ? process_one_work+0x3f0/0x3f0 +[ 25.101347] ? kthread_park+0x90/0x90 +[ 25.101350] ret_from_fork+0x35/0x40 +[ 25.101351] --[ end trace b5b47d44cd998ba1 ]-- + +Fixes: 6294b61ba769 ("drm/i915/gvt: add missing display part reset for vGPU reset") +Signed-off-by: Tina Zhang +Reviewed-by: Zhenyu Wang +Signed-off-by: Zhenyu Wang +Link: http://patchwork.freedesktop.org/patch/msgid/20200221023234.28635-1-tina.zhang@intel.com +Acked-by: Thomas Zimmermann +--- + drivers/gpu/drm/i915/gvt/vgpu.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/i915/gvt/vgpu.c b/drivers/gpu/drm/i915/gvt/vgpu.c +index 85bd9bf4f6ee..487af6ea9972 100644 +--- a/drivers/gpu/drm/i915/gvt/vgpu.c ++++ b/drivers/gpu/drm/i915/gvt/vgpu.c +@@ -560,9 +560,9 @@ void intel_gvt_reset_vgpu_locked(struct intel_vgpu *vgpu, bool dmlr, + + intel_vgpu_reset_mmio(vgpu, dmlr); + populate_pvinfo_page(vgpu); +- intel_vgpu_reset_display(vgpu); + + if (dmlr) { ++ intel_vgpu_reset_display(vgpu); + intel_vgpu_reset_cfg_space(vgpu); + /* only reset the failsafe mode when dmlr reset */ + vgpu->failsafe = false; +-- +2.25.1 + diff --git a/patches.suse/0001-drm-i915-selftests-Fix-return-in-assert_mmap_offset.patch b/patches.suse/0001-drm-i915-selftests-Fix-return-in-assert_mmap_offset.patch new file mode 100644 index 0000000..aad47e4 --- /dev/null +++ b/patches.suse/0001-drm-i915-selftests-Fix-return-in-assert_mmap_offset.patch @@ -0,0 +1,35 @@ +From f4aaa44e8b20f7e0d4ea68d3bca4968b6ae5aaff Mon Sep 17 00:00:00 2001 +From: Dan Carpenter +Date: Fri, 28 Feb 2020 17:14:13 +0300 +Subject: drm/i915/selftests: Fix return in assert_mmap_offset() +Git-commit: f4aaa44e8b20f7e0d4ea68d3bca4968b6ae5aaff +Patch-mainline: v5.6-rc5 +References: bsc#1114279 + +The assert_mmap_offset() returns type bool so if we return an error +pointer that is "return true;" or success. If we have an error, then +we should return false. + +Fixes: 3d81d589d6e3 ("drm/i915: Test exhaustion of the mmap space") +Signed-off-by: Dan Carpenter +Reviewed-by: Chris Wilson +Signed-off-by: Chris Wilson +Link: https://patchwork.freedesktop.org/patch/msgid/20200228141413.qfjf4abr323drlo4@kili.mountain +(cherry picked from commit efbf928824820f2738f41271934f6ec2c6ebd587) +Signed-off-by: Jani Nikula +Acked-by: Thomas Zimmermann +--- + drivers/gpu/drm/i915/selftests/i915_gem_object.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/gpu/drm/i915/selftests/i915_gem_object.c ++++ b/drivers/gpu/drm/i915/selftests/i915_gem_object.c +@@ -465,7 +465,7 @@ static bool assert_mmap_offset(struct dr + + obj = i915_gem_object_create_internal(i915, size); + if (IS_ERR(obj)) +- return PTR_ERR(obj); ++ return false; + + err = i915_gem_object_create_mmap_offset(obj); + i915_gem_object_put(obj); diff --git a/patches.suse/0001-drm-lease-fix-WARNING-in-idr_destroy.patch b/patches.suse/0001-drm-lease-fix-WARNING-in-idr_destroy.patch new file mode 100644 index 0000000..decefcb --- /dev/null +++ b/patches.suse/0001-drm-lease-fix-WARNING-in-idr_destroy.patch @@ -0,0 +1,55 @@ +From b216a8e7908cd750550c0480cf7d2b3a37f06954 Mon Sep 17 00:00:00 2001 +From: Qiujun Huang +Date: Wed, 18 Mar 2020 15:53:50 +0800 +Subject: drm/lease: fix WARNING in idr_destroy +Git-commit: b216a8e7908cd750550c0480cf7d2b3a37f06954 +Patch-mainline: v5.6-rc7 +References: bsc#1113956 + +drm_lease_create takes ownership of leases. And leases will be released +by drm_master_put. + +drm_master_put + ->drm_master_destroy + ->idr_destroy + +So we needn't call idr_destroy again. + +Reported-and-tested-by: syzbot+05835159fe322770fe3d@syzkaller.appspotmail.com +Signed-off-by: Qiujun Huang +Cc: stable@vger.kernel.org +Signed-off-by: Daniel Vetter +Link: https://patchwork.freedesktop.org/patch/msgid/1584518030-4173-1-git-send-email-hqjagain@gmail.com +Acked-by: Thomas Zimmermann +--- + drivers/gpu/drm/drm_lease.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/drm_lease.c b/drivers/gpu/drm/drm_lease.c +index b481cafdde280..825abe38201ac 100644 +--- a/drivers/gpu/drm/drm_lease.c ++++ b/drivers/gpu/drm/drm_lease.c +@@ -542,10 +542,12 @@ int drm_mode_create_lease_ioctl(struct drm_device *dev, + } + + DRM_DEBUG_LEASE("Creating lease\n"); ++ /* lessee will take the ownership of leases */ + lessee = drm_lease_create(lessor, &leases); + + if (IS_ERR(lessee)) { + ret = PTR_ERR(lessee); ++ idr_destroy(&leases); + goto out_leases; + } + +@@ -580,7 +582,6 @@ int drm_mode_create_lease_ioctl(struct drm_device *dev, + + out_leases: + put_unused_fd(fd); +- idr_destroy(&leases); + + DRM_DEBUG_LEASE("drm_mode_create_lease_ioctl failed: %d\n", ret); + return ret; +-- +2.26.0 + diff --git a/patches.suse/0001-drm-mediatek-Add-gamma-property-according-to-hardwar.patch b/patches.suse/0001-drm-mediatek-Add-gamma-property-according-to-hardwar.patch new file mode 100644 index 0000000..fc594f8 --- /dev/null +++ b/patches.suse/0001-drm-mediatek-Add-gamma-property-according-to-hardwar.patch @@ -0,0 +1,54 @@ +From 4cebc1de506fa753301266a5a23bb21bca52ad3a Mon Sep 17 00:00:00 2001 +From: Yongqiang Niu +Date: Fri, 13 Dec 2019 15:28:51 +0800 +Subject: drm/mediatek: Add gamma property according to hardware capability +Git-commit: 4cebc1de506fa753301266a5a23bb21bca52ad3a +Patch-mainline: v5.6-rc1 +References: bsc#1114279 + +If there is no gamma function in the crtc +display path, don't add gamma property +for crtc + +Fixes: 2f3f4dda747c ("drm/mediatek: Add gamma correction.") +Signed-off-by: Yongqiang Niu +Signed-off-by: Hsin-Yi Wang +Signed-off-by: CK Hu +Acked-by: Thomas Zimmermann +--- + drivers/gpu/drm/mediatek/mtk_drm_crtc.c | 10 ++++++++-- + 1 file changed, 8 insertions(+), 2 deletions(-) + +--- a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c ++++ b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c +@@ -534,6 +534,7 @@ int mtk_drm_crtc_create(struct drm_devic + int pipe = priv->num_pipes; + int ret; + int i; ++ uint gamma_lut_size = 0; + + if (!path) + return 0; +@@ -588,6 +589,9 @@ int mtk_drm_crtc_create(struct drm_devic + } + + mtk_crtc->ddp_comp[i] = comp; ++ ++ if (comp->funcs && comp->funcs->gamma_set) ++ gamma_lut_size = MTK_LUT_SIZE; + } + + mtk_crtc->layer_nr = mtk_ddp_comp_layer_nr(mtk_crtc->ddp_comp[0]); +@@ -604,8 +608,10 @@ int mtk_drm_crtc_create(struct drm_devic + NULL, pipe); + if (ret < 0) + goto unprepare; +- drm_mode_crtc_set_gamma_size(&mtk_crtc->base, MTK_LUT_SIZE); +- drm_crtc_enable_color_mgmt(&mtk_crtc->base, 0, false, MTK_LUT_SIZE); ++ ++ if (gamma_lut_size) ++ drm_mode_crtc_set_gamma_size(&mtk_crtc->base, gamma_lut_size); ++ drm_crtc_enable_color_mgmt(&mtk_crtc->base, 0, false, gamma_lut_size); + priv->num_pipes++; + + return 0; diff --git a/patches.suse/0001-drm-mediatek-disable-all-the-planes-in-atomic_disabl.patch b/patches.suse/0001-drm-mediatek-disable-all-the-planes-in-atomic_disabl.patch new file mode 100644 index 0000000..78ec177 --- /dev/null +++ b/patches.suse/0001-drm-mediatek-disable-all-the-planes-in-atomic_disabl.patch @@ -0,0 +1,42 @@ +From 9b59b8c6f8462cd330fc7fb735c4d864357b3689 Mon Sep 17 00:00:00 2001 +From: Bibby Hsieh +Date: Tue, 10 Dec 2019 13:05:23 +0800 +Subject: drm/mediatek: disable all the planes in atomic_disable +Git-commit: 9b59b8c6f8462cd330fc7fb735c4d864357b3689 +Patch-mainline: v5.6-rc1 +References: bsc#1114279 + +Under shadow register case, we do not disable all the plane before +disable all the hardwares. Fix it. + +Fixes: 9dc84e98a31f ("drm/mediatek: add shadow register support") + +Signed-off-by: Bibby Hsieh +Signed-off-by: CK Hu +Acked-by: Thomas Zimmermann +--- + drivers/gpu/drm/mediatek/mtk_drm_crtc.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +--- a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c ++++ b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c +@@ -391,6 +391,7 @@ static void mtk_drm_crtc_disable(struct + { + struct mtk_drm_crtc *mtk_crtc = to_mtk_crtc(crtc); + struct mtk_ddp_comp *comp = mtk_crtc->ddp_comp[0]; ++ struct mtk_drm_private *priv = crtc->dev->dev_private; + int i; + + DRM_DEBUG_DRIVER("%s %d\n", __func__, crtc->base.id); +@@ -408,6 +409,11 @@ static void mtk_drm_crtc_disable(struct + } + mtk_crtc->pending_planes = true; + ++ if (priv->data->shadow_register) { ++ mtk_disp_mutex_acquire(mtk_crtc->mutex); ++ mtk_crtc_ddp_config(crtc); ++ mtk_disp_mutex_release(mtk_crtc->mutex); ++ } + /* Wait for planes to be disabled */ + drm_crtc_wait_one_vblank(crtc); + diff --git a/patches.suse/0001-drm-mipi_dbi-Fix-off-by-one-bugs-in-mipi_dbi_blank.patch b/patches.suse/0001-drm-mipi_dbi-Fix-off-by-one-bugs-in-mipi_dbi_blank.patch new file mode 100644 index 0000000..d74668f --- /dev/null +++ b/patches.suse/0001-drm-mipi_dbi-Fix-off-by-one-bugs-in-mipi_dbi_blank.patch @@ -0,0 +1,45 @@ +From 2ce18249af5a28031b3f909cfafccc88ea966c9d Mon Sep 17 00:00:00 2001 +From: Geert Uytterhoeven +Date: Mon, 30 Dec 2019 14:06:04 +0100 +Subject: drm/mipi_dbi: Fix off-by-one bugs in mipi_dbi_blank() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit +Git-commit: 2ce18249af5a28031b3f909cfafccc88ea966c9d +Patch-mainline: v5.6-rc1 +References: bsc#1114279 + +When configuring the frame memory window, the last column and row +numbers are written to the column resp. page address registers. These +numbers are thus one less than the actual window width resp. height. + +While this is handled correctly in mipi_dbi_fb_dirty() since commit +03ceb1c8dfd1e293 ("drm/tinydrm: Fix setting of the column/page end +addresses."), it is not in mipi_dbi_blank(). The latter still forgets +to subtract one when calculating the most significant bytes of the +column and row numbers, thus programming wrong values when the display +width or height is a multiple of 256. + +Fixes: 02dd95fe31693626 ("drm/tinydrm: Add MIPI DBI support") +Signed-off-by: Geert Uytterhoeven +Signed-off-by: Noralf Trønnes +Link: https://patchwork.freedesktop.org/patch/msgid/20191230130604.31006-1-geert+renesas@glider.be +Acked-by: Thomas Zimmermann +--- + drivers/gpu/drm/tinydrm/mipi-dbi.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/gpu/drm/tinydrm/mipi-dbi.c ++++ b/drivers/gpu/drm/tinydrm/mipi-dbi.c +@@ -293,9 +293,9 @@ static void mipi_dbi_blank(struct mipi_d + memset(mipi->tx_buf, 0, len); + + mipi_dbi_command(mipi, MIPI_DCS_SET_COLUMN_ADDRESS, 0, 0, +- (width >> 8) & 0xFF, (width - 1) & 0xFF); ++ ((width - 1) >> 8) & 0xFF, (width - 1) & 0xFF); + mipi_dbi_command(mipi, MIPI_DCS_SET_PAGE_ADDRESS, 0, 0, +- (height >> 8) & 0xFF, (height - 1) & 0xFF); ++ ((height - 1) >> 8) & 0xFF, (height - 1) & 0xFF); + mipi_dbi_command_buf(mipi, MIPI_DCS_WRITE_MEMORY_START, + (u8 *)mipi->tx_buf, len); + } diff --git a/patches.suse/0001-drm-msm-mdp4-Adjust-indentation-in-mdp4_dsi_encoder_.patch b/patches.suse/0001-drm-msm-mdp4-Adjust-indentation-in-mdp4_dsi_encoder_.patch new file mode 100644 index 0000000..fa01a78 --- /dev/null +++ b/patches.suse/0001-drm-msm-mdp4-Adjust-indentation-in-mdp4_dsi_encoder_.patch @@ -0,0 +1,50 @@ +From 251e3cb1418ff3f5061ee31335e346e852b16573 Mon Sep 17 00:00:00 2001 +From: Nathan Chancellor +Date: Mon, 9 Dec 2019 13:32:30 -0700 +Subject: drm: msm: mdp4: Adjust indentation in mdp4_dsi_encoder_enable +Git-commit: 251e3cb1418ff3f5061ee31335e346e852b16573 +Patch-mainline: v5.6-rc1 +References: bsc#1111666 bsc#1114279 + +Clang warns: + +../drivers/gpu/drm/msm/disp/mdp4/mdp4_dsi_encoder.c:124:3: warning: +misleading indentation; statement is not part of the previous 'if' +[-Wmisleading-indentation] + mdp4_crtc_set_config(encoder->crtc, + ^ +../drivers/gpu/drm/msm/disp/mdp4/mdp4_dsi_encoder.c:121:2: note: +previous statement is here + if (mdp4_dsi_encoder->enabled) + ^ + +This warning occurs because there is a space after the tab on this line. +Remove it so that the indentation is consistent with the Linux kernel +coding style and clang no longer warns. + +Fixes: 776638e73a19 ("drm/msm/dsi: Add a mdp4 encoder for DSI") +Link: https://github.com/ClangBuiltLinux/linux/issues/792 +Signed-off-by: Nathan Chancellor +Reviewed-by: Nick Desaulniers +Signed-off-by: Rob Clark +Acked-by: Thomas Zimmermann +--- + drivers/gpu/drm/msm/disp/mdp4/mdp4_dsi_encoder.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/msm/disp/mdp4/mdp4_dsi_encoder.c b/drivers/gpu/drm/msm/disp/mdp4/mdp4_dsi_encoder.c +index 772f0753ed38..aaf2f26f8505 100644 +--- a/drivers/gpu/drm/msm/disp/mdp4/mdp4_dsi_encoder.c ++++ b/drivers/gpu/drm/msm/disp/mdp4/mdp4_dsi_encoder.c +@@ -121,7 +121,7 @@ static void mdp4_dsi_encoder_enable(struct drm_encoder *encoder) + if (mdp4_dsi_encoder->enabled) + return; + +- mdp4_crtc_set_config(encoder->crtc, ++ mdp4_crtc_set_config(encoder->crtc, + MDP4_DMA_CONFIG_PACK_ALIGN_MSB | + MDP4_DMA_CONFIG_DEFLKR_EN | + MDP4_DMA_CONFIG_DITHER_EN | +-- +2.25.1 + diff --git a/patches.suse/0001-drm-rcar-du-Recognize-renesas-vsps-in-addition-to-vs.patch b/patches.suse/0001-drm-rcar-du-Recognize-renesas-vsps-in-addition-to-vs.patch new file mode 100644 index 0000000..b905391 --- /dev/null +++ b/patches.suse/0001-drm-rcar-du-Recognize-renesas-vsps-in-addition-to-vs.patch @@ -0,0 +1,58 @@ +From 7b627ce80fbd05885b27f711a5f9820f2b40749a Mon Sep 17 00:00:00 2001 +From: Geert Uytterhoeven +Date: Tue, 5 Nov 2019 19:35:03 +0100 +Subject: drm: rcar-du: Recognize "renesas,vsps" in addition to "vsps" +Git-commit: 7b627ce80fbd05885b27f711a5f9820f2b40749a +Patch-mainline: v5.6-rc1 +References: bsc#1114279 + +The Renesas-specific "vsps" property lacks a vendor prefix. +Add a "renesas," prefix to comply with DT best practises. +Retain backward compatibility with old DTBs by falling back to "vsps" +when needed. + +Fixes: 6d62ef3ac30be756 ("drm: rcar-du: Expose the VSP1 compositor through KMS planes") +Signed-off-by: Geert Uytterhoeven +Reviewed-by: Laurent Pinchart +Signed-off-by: Laurent Pinchart +Acked-by: Thomas Zimmermann +--- + drivers/gpu/drm/rcar-du/rcar_du_kms.c | 13 ++++++++++--- + 1 file changed, 10 insertions(+), 3 deletions(-) + +--- a/drivers/gpu/drm/rcar-du/rcar_du_kms.c ++++ b/drivers/gpu/drm/rcar-du/rcar_du_kms.c +@@ -544,6 +544,7 @@ static int rcar_du_properties_init(struct rcar_du_device *rcdu) + static int rcar_du_vsps_init(struct rcar_du_device *rcdu) + { + const struct device_node *np = rcdu->dev->of_node; ++ const char *vsps_prop_name = "renesas,vsps"; + struct of_phandle_args args; + struct { + struct device_node *np; +@@ -559,15 +560,21 @@ static int rcar_du_vsps_init(struct rcar_du_device *rcdu) + * entry contains a pointer to the VSP DT node and a bitmask of the + * connected DU CRTCs. + */ +- cells = of_property_count_u32_elems(np, "vsps") / rcdu->num_crtcs - 1; ++ ret = of_property_count_u32_elems(np, vsps_prop_name); ++ if (ret < 0) { ++ /* Backward compatibility with old DTBs. */ ++ vsps_prop_name = "vsps"; ++ ret = of_property_count_u32_elems(np, vsps_prop_name); ++ } ++ cells = ret / rcdu->num_crtcs - 1; + if (cells > 1) + return -EINVAL; + + for (i = 0; i < rcdu->num_crtcs; ++i) { + unsigned int j; + +- ret = of_parse_phandle_with_fixed_args(np, "vsps", cells, i, +- &args); ++ ret = of_parse_phandle_with_fixed_args(np, vsps_prop_name, ++ cells, i, &args); + if (ret < 0) + goto error; + + diff --git a/patches.suse/0001-md-raid0-avoid-RAID0-data-corruption-due-to-layout-c.patch b/patches.suse/0001-md-raid0-avoid-RAID0-data-corruption-due-to-layout-c.patch index acb20e4..8195879 100644 --- a/patches.suse/0001-md-raid0-avoid-RAID0-data-corruption-due-to-layout-c.patch +++ b/patches.suse/0001-md-raid0-avoid-RAID0-data-corruption-due-to-layout-c.patch @@ -25,20 +25,20 @@ specified, and refused to assemble an affected array if that parameter is not set. Fixes: 20d0189b1012 ("block: Introduce new bio_split()") -Cc: stable@vger.kernel.org (3.14+) +cc: stable@vger.kernel.org (3.14+) Acked-by: Guoqing Jiang Signed-off-by: NeilBrown Signed-off-by: Song Liu -Signed-off-by: Coly Li - --- - drivers/md/raid0.c | 34 +++++++++++++++++++++++++++++++++- - drivers/md/raid0.h | 14 ++++++++++++++ - 2 files changed, 47 insertions(+), 1 deletion(-) + drivers/md/raid0.c | 32 +++++++++++++++++++++++++++++++- + drivers/md/raid0.h | 14 ++++++++++++++ + 2 files changed, 45 insertions(+), 1 deletion(-) +diff --git a/drivers/md/raid0.c b/drivers/md/raid0.c +index bc422eae2c95..ec611abda835 100644 --- a/drivers/md/raid0.c +++ b/drivers/md/raid0.c -@@ -26,6 +26,9 @@ +@@ -19,6 +19,9 @@ #include "raid0.h" #include "raid5.h" @@ -48,7 +48,7 @@ Signed-off-by: Coly Li #define UNSUPPORTED_MDDEV_FLAGS \ ((1L << MD_HAS_JOURNAL) | \ (1L << MD_JOURNAL_CLEAN) | \ -@@ -146,6 +149,19 @@ static int create_strip_zones(struct mdd +@@ -139,6 +142,19 @@ static int create_strip_zones(struct mddev *mddev, struct r0conf **private_conf) } pr_debug("md/raid0:%s: FINAL %d zones\n", mdname(mddev), conf->nr_strip_zones); @@ -68,7 +68,7 @@ Signed-off-by: Coly Li /* * now since we have the hard sector sizes, we can make sure * chunk size is a multiple of that sector size -@@ -552,10 +568,12 @@ static void raid0_handle_discard(struct +@@ -547,10 +563,12 @@ static void raid0_handle_discard(struct mddev *mddev, struct bio *bio) static bool raid0_make_request(struct mddev *mddev, struct bio *bio) { @@ -81,14 +81,13 @@ Signed-off-by: Coly Li unsigned chunk_sects; unsigned sectors; -@@ -588,8 +606,22 @@ static bool raid0_make_request(struct md +@@ -584,8 +602,20 @@ static bool raid0_make_request(struct mddev *mddev, struct bio *bio) bio = split; } + orig_sector = sector; zone = find_zone(mddev->private, §or); - tmp_dev = map_sector(mddev, zone, sector, §or); -+ + switch (conf->layout) { + case RAID0_ORIG_LAYOUT: + tmp_dev = map_sector(mddev, zone, orig_sector, §or); @@ -101,13 +100,14 @@ Signed-off-by: Coly Li + bio_io_error(bio); + return true; + } -+ - bio_set_dev(bio, tmp_dev->bdev); - bio->bi_iter.bi_sector = sector + zone->dev_start + - tmp_dev->data_offset; + + if (unlikely(is_mddev_broken(tmp_dev, "raid0"))) { + bio_io_error(bio); +diff --git a/drivers/md/raid0.h b/drivers/md/raid0.h +index 540e65d92642..3816e5477db1 100644 --- a/drivers/md/raid0.h +++ b/drivers/md/raid0.h -@@ -7,11 +7,25 @@ struct strip_zone { +@@ -8,11 +8,25 @@ struct strip_zone { int nb_dev; /* # of devices attached to the zone */ }; @@ -133,3 +133,6 @@ Signed-off-by: Coly Li }; #endif +-- +2.25.0 + diff --git a/patches.suse/0001-media-ov519-add-missing-endpoint-sanity-checks.patch b/patches.suse/0001-media-ov519-add-missing-endpoint-sanity-checks.patch new file mode 100644 index 0000000..b3c622c --- /dev/null +++ b/patches.suse/0001-media-ov519-add-missing-endpoint-sanity-checks.patch @@ -0,0 +1,58 @@ +From 998912346c0da53a6dbb71fab3a138586b596b30 Mon Sep 17 00:00:00 2001 +From: Johan Hovold +Date: Fri, 3 Jan 2020 17:35:09 +0100 +Subject: [PATCH] media: ov519: add missing endpoint sanity checks +Git-commit: 998912346c0da53a6dbb71fab3a138586b596b30 +References: bsc#1168829 +Patch-mainline: v5.7-rc1 + +Make sure to check that we have at least one endpoint before accessing +the endpoint array to avoid dereferencing a NULL-pointer on stream +start. + +Note that these sanity checks are not redundant as the driver is mixing +looking up altsettings by index and by number, which need not coincide. + +Fixes: 1876bb923c98 ("V4L/DVB (12079): gspca_ov519: add support for the ov511 bridge") +Fixes: b282d87332f5 ("V4L/DVB (12080): gspca_ov519: Fix ov518+ with OV7620AE (Trust spacecam 320)") +Cc: stable # 2.6.31 +Cc: Hans de Goede +Signed-off-by: Johan Hovold +Signed-off-by: Hans Verkuil +Signed-off-by: Mauro Carvalho Chehab +Signed-off-by: Oliver Neukum +--- + drivers/media/usb/gspca/ov519.c | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +diff --git a/drivers/media/usb/gspca/ov519.c b/drivers/media/usb/gspca/ov519.c +index f417dfc0b872..0afe70a3f9a2 100644 +--- a/drivers/media/usb/gspca/ov519.c ++++ b/drivers/media/usb/gspca/ov519.c +@@ -3477,6 +3477,11 @@ static void ov511_mode_init_regs(struct sd *sd) + return; + } + ++ if (alt->desc.bNumEndpoints < 1) { ++ sd->gspca_dev.usb_err = -ENODEV; ++ return; ++ } ++ + packet_size = le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize); + reg_w(sd, R51x_FIFO_PSIZE, packet_size >> 5); + +@@ -3603,6 +3608,11 @@ static void ov518_mode_init_regs(struct sd *sd) + return; + } + ++ if (alt->desc.bNumEndpoints < 1) { ++ sd->gspca_dev.usb_err = -ENODEV; ++ return; ++ } ++ + packet_size = le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize); + ov518_reg_w32(sd, R51x_FIFO_PSIZE, packet_size & ~7, 2); + +-- +2.16.4 + diff --git a/patches.suse/0001-media-stv06xx-add-missing-descriptor-sanity-checks.patch b/patches.suse/0001-media-stv06xx-add-missing-descriptor-sanity-checks.patch new file mode 100644 index 0000000..0b503b9 --- /dev/null +++ b/patches.suse/0001-media-stv06xx-add-missing-descriptor-sanity-checks.patch @@ -0,0 +1,98 @@ +From 485b06aadb933190f4bc44e006076bc27a23f205 Mon Sep 17 00:00:00 2001 +From: Johan Hovold +Date: Fri, 3 Jan 2020 17:35:10 +0100 +Subject: [PATCH] media: stv06xx: add missing descriptor sanity checks +Git-commit: 485b06aadb933190f4bc44e006076bc27a23f205 +References: bsc#1168854 +Patch-mainline: v5.7-rc1 + +Make sure to check that we have two alternate settings and at least one +endpoint before accessing the second altsetting structure and +dereferencing the endpoint arrays. + +This specifically avoids dereferencing NULL-pointers or corrupting +memory when a device does not have the expected descriptors. + +Note that the sanity checks in stv06xx_start() and pb0100_start() are +not redundant as the driver is mixing looking up altsettings by index +and by number, which may not coincide. + +Fixes: 8668d504d72c ("V4L/DVB (12082): gspca_stv06xx: Add support for st6422 bridge and sensor") +Fixes: c0b33bdc5b8d ("[media] gspca-stv06xx: support bandwidth changing") +Cc: stable # 2.6.31 +Cc: Hans de Goede +Signed-off-by: Johan Hovold +Signed-off-by: Hans Verkuil +Signed-off-by: Mauro Carvalho Chehab +Signed-off-by: Oliver Neukum +--- + drivers/media/usb/gspca/stv06xx/stv06xx.c | 19 ++++++++++++++++++- + drivers/media/usb/gspca/stv06xx/stv06xx_pb0100.c | 4 ++++ + 2 files changed, 22 insertions(+), 1 deletion(-) + +diff --git a/drivers/media/usb/gspca/stv06xx/stv06xx.c b/drivers/media/usb/gspca/stv06xx/stv06xx.c +index 79653d409951..95673fc0a99c 100644 +--- a/drivers/media/usb/gspca/stv06xx/stv06xx.c ++++ b/drivers/media/usb/gspca/stv06xx/stv06xx.c +@@ -282,6 +282,9 @@ static int stv06xx_start(struct gspca_dev *gspca_dev) + return -EIO; + } + ++ if (alt->desc.bNumEndpoints < 1) ++ return -ENODEV; ++ + packet_size = le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize); + err = stv06xx_write_bridge(sd, STV_ISO_SIZE_L, packet_size); + if (err < 0) +@@ -306,11 +309,21 @@ static int stv06xx_start(struct gspca_dev *gspca_dev) + + static int stv06xx_isoc_init(struct gspca_dev *gspca_dev) + { ++ struct usb_interface_cache *intfc; + struct usb_host_interface *alt; + struct sd *sd = (struct sd *) gspca_dev; + ++ intfc = gspca_dev->dev->actconfig->intf_cache[0]; ++ ++ if (intfc->num_altsetting < 2) ++ return -ENODEV; ++ ++ alt = &intfc->altsetting[1]; ++ ++ if (alt->desc.bNumEndpoints < 1) ++ return -ENODEV; ++ + /* Start isoc bandwidth "negotiation" at max isoc bandwidth */ +- alt = &gspca_dev->dev->actconfig->intf_cache[0]->altsetting[1]; + alt->endpoint[0].desc.wMaxPacketSize = + cpu_to_le16(sd->sensor->max_packet_size[gspca_dev->curr_mode]); + +@@ -323,6 +336,10 @@ static int stv06xx_isoc_nego(struct gspca_dev *gspca_dev) + struct usb_host_interface *alt; + struct sd *sd = (struct sd *) gspca_dev; + ++ /* ++ * Existence of altsetting and endpoint was verified in ++ * stv06xx_isoc_init() ++ */ + alt = &gspca_dev->dev->actconfig->intf_cache[0]->altsetting[1]; + packet_size = le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize); + min_packet_size = sd->sensor->min_packet_size[gspca_dev->curr_mode]; +diff --git a/drivers/media/usb/gspca/stv06xx/stv06xx_pb0100.c b/drivers/media/usb/gspca/stv06xx/stv06xx_pb0100.c +index 6d1007715ff7..ae382b3b5f7f 100644 +--- a/drivers/media/usb/gspca/stv06xx/stv06xx_pb0100.c ++++ b/drivers/media/usb/gspca/stv06xx/stv06xx_pb0100.c +@@ -185,6 +185,10 @@ static int pb0100_start(struct sd *sd) + alt = usb_altnum_to_altsetting(intf, sd->gspca_dev.alt); + if (!alt) + return -ENODEV; ++ ++ if (alt->desc.bNumEndpoints < 1) ++ return -ENODEV; ++ + packet_size = le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize); + + /* If we don't have enough bandwidth use a lower framerate */ +-- +2.16.4 + diff --git a/patches.suse/0001-mm-Introduce-kvcalloc.patch b/patches.suse/0001-mm-Introduce-kvcalloc.patch index e204c42..26d653a 100644 --- a/patches.suse/0001-mm-Introduce-kvcalloc.patch +++ b/patches.suse/0001-mm-Introduce-kvcalloc.patch @@ -19,7 +19,7 @@ Acked-by: Thomas Zimmermann --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -555,6 +555,11 @@ static inline void *kvmalloc_array(size_ - return kvmalloc(n * size, flags); + return kvmalloc(bytes, flags); } +static inline void *kvcalloc(size_t n, size_t size, gfp_t flags) diff --git a/patches.suse/0001-padata-always-acquire-cpu_hotplug_lock-before-pinst-.patch b/patches.suse/0001-padata-always-acquire-cpu_hotplug_lock-before-pinst-.patch new file mode 100644 index 0000000..d8f7f80 --- /dev/null +++ b/patches.suse/0001-padata-always-acquire-cpu_hotplug_lock-before-pinst-.patch @@ -0,0 +1,70 @@ +From 38228e8848cd7dd86ccb90406af32de0cad24be3 Mon Sep 17 00:00:00 2001 +From: Daniel Jordan +Date: Tue, 3 Dec 2019 14:31:11 -0500 +Subject: [PATCH] padata: always acquire cpu_hotplug_lock before pinst->lock +Git-commit: 38228e8848cd7dd86ccb90406af32de0cad24be3 +References: git-fixes +Patch-mainline: v5.6-rc1 + +lockdep complains when padata's paths to update cpumasks via CPU hotplug +and sysfs are both taken: + + # echo 0 > /sys/devices/system/cpu/cpu1/online + # echo ff > /sys/kernel/pcrypt/pencrypt/parallel_cpumask + + ====================================================== + WARNING: possible circular locking dependency detected + 5.4.0-rc8-padata-cpuhp-v3+ #1 Not tainted + ------------------------------------------------------ + bash/205 is trying to acquire lock: + ffffffff8286bcd0 (cpu_hotplug_lock.rw_sem){++++}, at: padata_set_cpumask+0x2b/0x120 + + but task is already holding lock: + ffff8880001abfa0 (&pinst->lock){+.+.}, at: padata_set_cpumask+0x26/0x120 + + which lock already depends on the new lock. + +padata doesn't take cpu_hotplug_lock and pinst->lock in a consistent +order. Which should be first? CPU hotplug calls into padata with +cpu_hotplug_lock already held, so it should have priority. + +Fixes: 6751fb3c0e0c ("padata: Use get_online_cpus/put_online_cpus") +Signed-off-by: Daniel Jordan +Cc: Eric Biggers +Cc: Herbert Xu +Cc: Steffen Klassert +Cc: linux-crypto@vger.kernel.org +Cc: linux-kernel@vger.kernel.org +Signed-off-by: Herbert Xu +Signed-off-by: Oliver Neukum +--- + kernel/padata.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/kernel/padata.c b/kernel/padata.c +index 1e6500d64846..f5964f015139 100644 +--- a/kernel/padata.c ++++ b/kernel/padata.c +@@ -643,8 +643,8 @@ int padata_set_cpumask(struct padata_instance *pinst, int cpumask_type, + struct cpumask *serial_mask, *parallel_mask; + int err = -EINVAL; + +- mutex_lock(&pinst->lock); + get_online_cpus(); ++ mutex_lock(&pinst->lock); + + switch (cpumask_type) { + case PADATA_CPU_PARALLEL: +@@ -662,8 +662,8 @@ int padata_set_cpumask(struct padata_instance *pinst, int cpumask_type, + err = __padata_set_cpumasks(pinst, parallel_mask, serial_mask); + + out: +- put_online_cpus(); + mutex_unlock(&pinst->lock); ++ put_online_cpus(); + + return err; + } +-- +2.16.4 + diff --git a/patches.suse/0001-perf-qcom_l2-fix-column-exclusion-check.patch b/patches.suse/0001-perf-qcom_l2-fix-column-exclusion-check.patch new file mode 100644 index 0000000..1a0fc40 --- /dev/null +++ b/patches.suse/0001-perf-qcom_l2-fix-column-exclusion-check.patch @@ -0,0 +1,49 @@ +From 6c17c1c3099d7367e67d51290884846dfeecf7bf Mon Sep 17 00:00:00 2001 +From: Neil Leeder +Date: Mon, 24 Jul 2017 17:17:02 -0400 +Subject: [PATCH] perf: qcom_l2: fix column exclusion check +Git-commit: 6c17c1c3099d7367e67d51290884846dfeecf7bf +References: fate#325865,fate#325861,git-fixes +Patch-mainline: v4.13 + +The check for column exclusion did not verify that the event being +checked was an L2 event, and not a software event. +Software events should not be checked for column exclusion. +This resulted in a group with both software and L2 events sometimes +incorrectly rejecting the L2 event for column exclusion and +not counting it. + +Add a check for PMU type before applying column exclusion logic. + +Fixes: 21bdbb7102edeaeb ("perf: add qcom l2 cache perf events driver") +Acked-by: Mark Rutland +Signed-off-by: Neil Leeder +Signed-off-by: Will Deacon +Signed-off-by: Oliver Neukum +--- + drivers/perf/qcom_l2_pmu.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/perf/qcom_l2_pmu.c b/drivers/perf/qcom_l2_pmu.c +index c259848228b4..b242cce10468 100644 +--- a/drivers/perf/qcom_l2_pmu.c ++++ b/drivers/perf/qcom_l2_pmu.c +@@ -546,6 +546,7 @@ static int l2_cache_event_init(struct perf_event *event) + } + + if ((event != event->group_leader) && ++ !is_software_event(event->group_leader) && + (L2_EVT_GROUP(event->group_leader->attr.config) == + L2_EVT_GROUP(event->attr.config))) { + dev_dbg_ratelimited(&l2cache_pmu->pdev->dev, +@@ -558,6 +559,7 @@ static int l2_cache_event_init(struct perf_event *event) + list_for_each_entry(sibling, &event->group_leader->sibling_list, + group_entry) { + if ((sibling != event) && ++ !is_software_event(sibling) && + (L2_EVT_GROUP(sibling->attr.config) == + L2_EVT_GROUP(event->attr.config))) { + dev_dbg_ratelimited(&l2cache_pmu->pdev->dev, +-- +2.16.4 + diff --git a/patches.suse/0001-rtlwifi-rtl8192de-Fix-missing-callback-that-tests-fo.patch b/patches.suse/0001-rtlwifi-rtl8192de-Fix-missing-callback-that-tests-fo.patch new file mode 100644 index 0000000..71b742b --- /dev/null +++ b/patches.suse/0001-rtlwifi-rtl8192de-Fix-missing-callback-that-tests-fo.patch @@ -0,0 +1,72 @@ +From 3155db7613edea8fb943624062baf1e4f9cfbfd6 Mon Sep 17 00:00:00 2001 +From: Larry Finger +Date: Mon, 11 Nov 2019 13:40:45 -0600 +Subject: [PATCH] rtlwifi: rtl8192de: Fix missing callback that tests for hw + release of buffer +Git-commit: 3155db7613edea8fb943624062baf1e4f9cfbfd6 +Patch-mainline: v5.5-rc1 +References: bsc#1111666 git-fixes + +In commit 38506ecefab9 ("rtlwifi: rtl_pci: Start modification for +new drivers"), a callback needed to check if the hardware has released +a buffer indicating that a DMA operation is completed was not added. + +Fixes: 38506ecefab9 ("rtlwifi: rtl_pci: Start modification for new drivers") +Cc: Stable # v3.18+ +Signed-off-by: Larry Finger +Signed-off-by: Kalle Valo +Acked-by: Takashi Iwai + +--- + drivers/net/wireless/realtek/rtlwifi/rtl8192de/sw.c | 1 + + drivers/net/wireless/realtek/rtlwifi/rtl8192de/trx.c | 17 +++++++++++++++++ + drivers/net/wireless/realtek/rtlwifi/rtl8192de/trx.h | 2 ++ + 3 files changed, 20 insertions(+) + +--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/sw.c ++++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/sw.c +@@ -237,6 +237,7 @@ static struct rtl_hal_ops rtl8192de_hal_ + .led_control = rtl92de_led_control, + .set_desc = rtl92de_set_desc, + .get_desc = rtl92de_get_desc, ++ .is_tx_desc_closed = rtl92de_is_tx_desc_closed, + .tx_polling = rtl92de_tx_polling, + .enable_hw_sec = rtl92de_enable_hw_security_config, + .set_key = rtl92de_set_key, +--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/trx.c ++++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/trx.c +@@ -858,6 +858,23 @@ u32 rtl92de_get_desc(u8 *p_desc, bool is + return ret; + } + ++bool rtl92de_is_tx_desc_closed(struct ieee80211_hw *hw, ++ u8 hw_queue, u16 index) ++{ ++ struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); ++ struct rtl8192_tx_ring *ring = &rtlpci->tx_ring[hw_queue]; ++ u8 *entry = (u8 *)(&ring->desc[ring->idx]); ++ u8 own = (u8)rtl92de_get_desc(hw, entry, true, HW_DESC_OWN); ++ ++ /* a beacon packet will only use the first ++ * descriptor by defaut, and the own bit may not ++ * be cleared by the hardware ++ */ ++ if (own) ++ return false; ++ return true; ++} ++ + void rtl92de_tx_polling(struct ieee80211_hw *hw, u8 hw_queue) + { + struct rtl_priv *rtlpriv = rtl_priv(hw); +--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/trx.h ++++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/trx.h +@@ -736,6 +736,8 @@ bool rtl92de_rx_query_desc(struct ieee80 + u8 desc_name, u8 *val); + u64 rtl92de_get_desc(struct ieee80211_hw *hw, + u8 *p_desc, bool istx, u8 desc_name); ++bool rtl92de_is_tx_desc_closed(struct ieee80211_hw *hw, ++ u8 hw_queue, u16 index); + void rtl92de_tx_polling(struct ieee80211_hw *hw, u8 hw_queue); + void rtl92de_tx_fill_cmddesc(struct ieee80211_hw *hw, u8 *pdesc, + bool b_firstseg, bool b_lastseg, diff --git a/patches.suse/0001-staging-ccree-use-signal-safe-completion-wait.patch b/patches.suse/0001-staging-ccree-use-signal-safe-completion-wait.patch new file mode 100644 index 0000000..5dcf653 --- /dev/null +++ b/patches.suse/0001-staging-ccree-use-signal-safe-completion-wait.patch @@ -0,0 +1,36 @@ +From 0f2f02d1b57220951b9ae69abbcaa403163ee41b Mon Sep 17 00:00:00 2001 +From: Gilad Ben-Yossef +Date: Sun, 25 Jun 2017 10:47:24 +0300 +Subject: [PATCH] staging: ccree: use signal safe completion wait +Git-commit: 0f2f02d1b57220951b9ae69abbcaa403163ee41b +References: git-fixes +Patch-mainline: v4.13 + +We were waiting for a completion notification of HW DMA +operation using an interruptible wait which can result +in data corruption if a signal interrupted us while +DMA was not yet completed. + +Fix this by moving to uninterrupted wait. + +Fixes: abefd6741d ("staging: ccree: introduce CryptoCell HW driver"). + +Signed-off-by: Gilad Ben-Yossef +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Oliver Neukum +--- + drivers/staging/ccree/ssi_request_mgr.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/drivers/staging/ccree/ssi_request_mgr.c ++++ b/drivers/staging/ccree/ssi_request_mgr.c +@@ -482,7 +482,8 @@ int send_request( + if (!is_dout) { + /* Wait upon sequence completion. + * Return "0" -Operation done successfully. */ +- return wait_for_completion_interruptible(&ssi_req->seq_compl); ++ wait_for_completion(&ssi_req->seq_compl); ++ return 0; + } else { + /* Operation still in process */ + return -EINPROGRESS; diff --git a/patches.suse/0001-thunderbolt-Prevent-crash-if-non-active-NVMem-file-i.patch b/patches.suse/0001-thunderbolt-Prevent-crash-if-non-active-NVMem-file-i.patch new file mode 100644 index 0000000..617ce50 --- /dev/null +++ b/patches.suse/0001-thunderbolt-Prevent-crash-if-non-active-NVMem-file-i.patch @@ -0,0 +1,61 @@ +From 03cd45d2e219301880cabc357e3cf478a500080f Mon Sep 17 00:00:00 2001 +From: Mika Westerberg +Date: Thu, 13 Feb 2020 12:56:04 +0300 +Subject: [PATCH] thunderbolt: Prevent crash if non-active NVMem file is read +Git-commit: 03cd45d2e219301880cabc357e3cf478a500080f +References: git-fixes +Patch-mainline: v5.6-rc3 + +The driver does not populate .reg_read callback for the non-active NVMem +because the file is supposed to be write-only. However, it turns out +NVMem subsystem does not yet support this and expects that the .reg_read +callback is provided. If user reads the binary attribute it triggers +NULL pointer dereference like this one: + + BUG: kernel NULL pointer dereference, address: 0000000000000000 + ... + Call Trace: + bin_attr_nvmem_read+0x64/0x80 + kernfs_fop_read+0xa7/0x180 + vfs_read+0xbd/0x170 + ksys_read+0x5a/0xd0 + do_syscall_64+0x43/0x150 + entry_SYSCALL_64_after_hwframe+0x44/0xa9 + +Fix this in the driver by providing .reg_read callback that always +returns an error. + +Reported-by: Nicholas Johnson +Fixes: e6b245ccd524 ("thunderbolt: Add support for host and device NVM firmware upgrade") +Signed-off-by: Mika Westerberg +Cc: stable@vger.kernel.org +Link: https://lore.kernel.org/r/20200213095604.1074-1-mika.westerberg@linux.intel.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Oliver Neukum +--- + drivers/thunderbolt/switch.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +--- a/drivers/thunderbolt/switch.c ++++ b/drivers/thunderbolt/switch.c +@@ -239,6 +239,12 @@ static int tb_switch_nvm_read(void *priv + return ret; + } + ++static int tb_switch_nvm_no_read(void *priv, unsigned int offset, void *val, ++ size_t bytes) ++{ ++ return -EPERM; ++} ++ + static int tb_switch_nvm_write(void *priv, unsigned int offset, void *val, + size_t bytes) + { +@@ -284,6 +290,7 @@ static struct nvmem_device *register_nvm + config.read_only = true; + } else { + config.name = "nvm_non_active"; ++ config.reg_read = tb_switch_nvm_no_read; + config.reg_write = tb_switch_nvm_write; + config.root_only = true; + } diff --git a/patches.suse/0001-tools-Update-include-uapi-linux-fcntl.h-copy-from-th.patch b/patches.suse/0001-tools-Update-include-uapi-linux-fcntl.h-copy-from-th.patch new file mode 100644 index 0000000..7a2656b --- /dev/null +++ b/patches.suse/0001-tools-Update-include-uapi-linux-fcntl.h-copy-from-th.patch @@ -0,0 +1,71 @@ +From ca3cf049d2430ac83eff5c32af7b86bb2d1285bf Mon Sep 17 00:00:00 2001 +From: Arnaldo Carvalho de Melo +Date: Thu, 13 Jul 2017 17:15:24 -0300 +Subject: [PATCH] tools: Update include/uapi/linux/fcntl.h copy from the kernel +Git-commit: ca3cf049d2430ac83eff5c32af7b86bb2d1285bf +Patch-mainline: v4.14-rc1 +References: bsc#1166003 + +To get the changes in the commit c75b1d9421f8 ("fs: add fcntl() +interface for setting/getting write life time hints"). + +Silencing this perf build warning: + + Warning: include/uapi/linux/fcntl.h differs from kernel + +We already beautify the fcntl cmd argument, so an upcoming cset will +update the 'cmd' strarray to cover these new commands. + +The hints are in the 3rd arg, a pointer, so not yet supported in 'perf +trace', for that we need to copy it somehow, probably using eBPF, a new +attempt at doing that is planned. + +Cc: Adrian Hunter +Cc: David Ahern +Cc: Jens Axboe +Cc: Jiri Olsa +Cc: Martin K. Petersen +Cc: Namhyung Kim +Cc: Wang Nan +Link: http://lkml.kernel.org/n/tip-al471wzs3x48alql0tm3mnfa@git.kernel.org +Signed-off-by: Arnaldo Carvalho de Melo +Acked-by: Coly Li +--- + tools/include/uapi/linux/fcntl.h | 21 +++++++++++++++++++++ + 1 file changed, 21 insertions(+) + +diff --git a/tools/include/uapi/linux/fcntl.h b/tools/include/uapi/linux/fcntl.h +index 813afd6eee71..ec69d55bcec7 100644 +--- a/tools/include/uapi/linux/fcntl.h ++++ b/tools/include/uapi/linux/fcntl.h +@@ -42,6 +42,27 @@ + #define F_SEAL_WRITE 0x0008 /* prevent writes */ + /* (1U << 31) is reserved for signed error codes */ + ++/* ++ * Set/Get write life time hints. {GET,SET}_RW_HINT operate on the ++ * underlying inode, while {GET,SET}_FILE_RW_HINT operate only on ++ * the specific file. ++ */ ++#define F_GET_RW_HINT (F_LINUX_SPECIFIC_BASE + 11) ++#define F_SET_RW_HINT (F_LINUX_SPECIFIC_BASE + 12) ++#define F_GET_FILE_RW_HINT (F_LINUX_SPECIFIC_BASE + 13) ++#define F_SET_FILE_RW_HINT (F_LINUX_SPECIFIC_BASE + 14) ++ ++/* ++ * Valid hint values for F_{GET,SET}_RW_HINT. 0 is "not set", or can be ++ * used to clear any hints previously set. ++ */ ++#define RWF_WRITE_LIFE_NOT_SET 0 ++#define RWH_WRITE_LIFE_NONE 1 ++#define RWH_WRITE_LIFE_SHORT 2 ++#define RWH_WRITE_LIFE_MEDIUM 3 ++#define RWH_WRITE_LIFE_LONG 4 ++#define RWH_WRITE_LIFE_EXTREME 5 ++ + /* + * Types of directory notifications that may be requested. + */ +-- +2.25.0 + diff --git a/patches.suse/0001-tools-lib-traceevent-Do-not-free-tep-cmdlines-in-add.patch b/patches.suse/0001-tools-lib-traceevent-Do-not-free-tep-cmdlines-in-add.patch new file mode 100644 index 0000000..08790b4 --- /dev/null +++ b/patches.suse/0001-tools-lib-traceevent-Do-not-free-tep-cmdlines-in-add.patch @@ -0,0 +1,51 @@ +From b0215e2d6a18d8331b2d4a8b38ccf3eff783edb1 Mon Sep 17 00:00:00 2001 +From: "Steven Rostedt (VMware)" +Date: Wed, 28 Aug 2019 15:05:28 -0400 +Subject: [PATCH] tools lib traceevent: Do not free tep->cmdlines in + add_new_comm() on failure +Git-commit: b0215e2d6a18d8331b2d4a8b38ccf3eff783edb1 +Patch-mainline: v5.4 +References: git-fixes + +If the re-allocation of tep->cmdlines succeeds, then the previous +allocation of tep->cmdlines will be freed. If we later fail in +add_new_comm(), we must not free cmdlines, and also should assign +tep->cmdlines to the new allocation. Otherwise when freeing tep, the +tep->cmdlines will be pointing to garbage. + +Fixes: a6d2a61ac653a ("tools lib traceevent: Remove some die() calls") +Signed-off-by: Steven Rostedt (VMware) +Cc: Andrew Morton +Cc: Jiri Olsa +Cc: Namhyung Kim +Cc: linux-trace-devel@vger.kernel.org +Cc: stable@vger.kernel.org +Link: http://lkml.kernel.org/r/20190828191819.970121417@goodmis.org +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: Oliver Neukum +--- + tools/lib/traceevent/event-parse.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +--- a/tools/lib/traceevent/event-parse.c ++++ b/tools/lib/traceevent/event-parse.c +@@ -268,10 +268,10 @@ static int add_new_comm(struct pevent *p + errno = ENOMEM; + return -1; + } ++ pevent->cmdlines = cmdlines; + + cmdlines[pevent->cmdline_count].comm = strdup(comm); + if (!cmdlines[pevent->cmdline_count].comm) { +- free(cmdlines); + errno = ENOMEM; + return -1; + } +@@ -282,7 +282,6 @@ static int add_new_comm(struct pevent *p + pevent->cmdline_count++; + + qsort(cmdlines, pevent->cmdline_count, sizeof(*cmdlines), cmdline_cmp); +- pevent->cmdlines = cmdlines; + + return 0; + } diff --git a/patches.suse/0001-usb-core-hub-do-error-out-if-usb_autopm_get_interfac.patch b/patches.suse/0001-usb-core-hub-do-error-out-if-usb_autopm_get_interfac.patch new file mode 100644 index 0000000..17f5804 --- /dev/null +++ b/patches.suse/0001-usb-core-hub-do-error-out-if-usb_autopm_get_interfac.patch @@ -0,0 +1,62 @@ +From 60e3f6e4ac5b0fda43dad01c32e09409ec710045 Mon Sep 17 00:00:00 2001 +From: Eugeniu Rosca +Date: Wed, 26 Feb 2020 18:50:35 +0100 +Subject: [PATCH] usb: core: hub: do error out if usb_autopm_get_interface() + fails +Git-commit: 60e3f6e4ac5b0fda43dad01c32e09409ec710045 +References: git-fixes +Patch-mainline: v5.6-rc5 + +Reviewing a fresh portion of coverity defects in USB core +(specifically CID 1458999), Alan Stern noted below in [1]: + +On Tue, Feb 25, 2020 at 02:39:23PM -0500, Alan Stern wrote: + > A revised search finds line 997 in drivers/usb/core/hub.c and lines + > 216, 269 in drivers/usb/core/port.c. (I didn't try looking in any + > other directories.) AFAICT all three of these should check the + > return value, although a error message in the kernel log probably + > isn't needed. + +Factor out the usb_remove_device() change into a standalone patch to +allow conflict-free integration on top of the earliest stable branches. + +[1] https://lore.kernel.org/lkml/Pine.LNX.4.44L0.2002251419120.1485-100000@iolanthe.rowland.org + +Fixes: 253e05724f9230 ("USB: add a "remove hardware" sysfs attribute") +Cc: stable@vger.kernel.org # v2.6.33+ +Suggested-by: Alan Stern +Signed-off-by: Eugeniu Rosca +Acked-by: Alan Stern +Link: https://lore.kernel.org/r/20200226175036.14946-2-erosca@de.adit-jv.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Oliver Neukum +--- + drivers/usb/core/hub.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c +index 1105983b5c1c..54cd8ef795ec 100644 +--- a/drivers/usb/core/hub.c ++++ b/drivers/usb/core/hub.c +@@ -988,13 +988,17 @@ int usb_remove_device(struct usb_device *udev) + { + struct usb_hub *hub; + struct usb_interface *intf; ++ int ret; + + if (!udev->parent) /* Can't remove a root hub */ + return -EINVAL; + hub = usb_hub_to_struct_hub(udev->parent); + intf = to_usb_interface(hub->intfdev); + +- usb_autopm_get_interface(intf); ++ ret = usb_autopm_get_interface(intf); ++ if (ret < 0) ++ return ret; ++ + set_bit(udev->portnum, hub->removed_bits); + hub_port_logical_disconnect(hub, udev->portnum); + usb_autopm_put_interface(intf); +-- +2.16.4 + diff --git a/patches.suse/0001-usb-core-port-do-error-out-if-usb_autopm_get_interfa.patch b/patches.suse/0001-usb-core-port-do-error-out-if-usb_autopm_get_interfa.patch new file mode 100644 index 0000000..819d8bd --- /dev/null +++ b/patches.suse/0001-usb-core-port-do-error-out-if-usb_autopm_get_interfa.patch @@ -0,0 +1,67 @@ +From 1f8b39bc99a31759e97a0428a5c3f64802c1e61d Mon Sep 17 00:00:00 2001 +From: Eugeniu Rosca +Date: Wed, 26 Feb 2020 18:50:36 +0100 +Subject: [PATCH] usb: core: port: do error out if usb_autopm_get_interface() + fails +Git-commit: 1f8b39bc99a31759e97a0428a5c3f64802c1e61d +References: git-fixes +Patch-mainline: v5.6-rc5 + +Reviewing a fresh portion of coverity defects in USB core +(specifically CID 1458999), Alan Stern noted below in [1]: + +On Tue, Feb 25, 2020 at 02:39:23PM -0500, Alan Stern wrote: + > A revised search finds line 997 in drivers/usb/core/hub.c and lines + > 216, 269 in drivers/usb/core/port.c. (I didn't try looking in any + > other directories.) AFAICT all three of these should check the + > return value, although a error message in the kernel log probably + > isn't needed. + +Factor out the usb_port_runtime_{resume,suspend}() changes into a +standalone patch to allow conflict-free porting on top of stable v3.9+. + +[1] https://lore.kernel.org/lkml/Pine.LNX.4.44L0.2002251419120.1485-100000@iolanthe.rowland.org + +Fixes: 971fcd492cebf5 ("usb: add runtime pm support for usb port device") +Cc: stable@vger.kernel.org # v3.9+ +Suggested-by: Alan Stern +Signed-off-by: Eugeniu Rosca +Acked-by: Alan Stern +Link: https://lore.kernel.org/r/20200226175036.14946-3-erosca@de.adit-jv.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Oliver Neukum +--- + drivers/usb/core/port.c | 10 ++++++++-- + 1 file changed, 8 insertions(+), 2 deletions(-) + +diff --git a/drivers/usb/core/port.c b/drivers/usb/core/port.c +index bbbb35fa639f..235a7c645503 100644 +--- a/drivers/usb/core/port.c ++++ b/drivers/usb/core/port.c +@@ -213,7 +213,10 @@ static int usb_port_runtime_resume(struct device *dev) + if (!port_dev->is_superspeed && peer) + pm_runtime_get_sync(&peer->dev); + +- usb_autopm_get_interface(intf); ++ retval = usb_autopm_get_interface(intf); ++ if (retval < 0) ++ return retval; ++ + retval = usb_hub_set_port_power(hdev, hub, port1, true); + msleep(hub_power_on_good_delay(hub)); + if (udev && !retval) { +@@ -266,7 +269,10 @@ static int usb_port_runtime_suspend(struct device *dev) + if (usb_port_block_power_off) + return -EBUSY; + +- usb_autopm_get_interface(intf); ++ retval = usb_autopm_get_interface(intf); ++ if (retval < 0) ++ return retval; ++ + retval = usb_hub_set_port_power(hdev, hub, port1, false); + usb_clear_port_feature(hdev, port1, USB_PORT_FEAT_C_CONNECTION); + if (!port_dev->is_superspeed) +-- +2.16.4 + diff --git a/patches.suse/0001-usb-dwc2-Fix-in-ISOC-request-length-checking.patch b/patches.suse/0001-usb-dwc2-Fix-in-ISOC-request-length-checking.patch new file mode 100644 index 0000000..d2d1db1 --- /dev/null +++ b/patches.suse/0001-usb-dwc2-Fix-in-ISOC-request-length-checking.patch @@ -0,0 +1,47 @@ +From 860ef6cd3f90b84a1832f8a6485c90c34d3b588b Mon Sep 17 00:00:00 2001 +From: Minas Harutyunyan +Date: Tue, 21 Jan 2020 14:24:04 +0400 +Subject: [PATCH] usb: dwc2: Fix in ISOC request length checking +Git-commit: 860ef6cd3f90b84a1832f8a6485c90c34d3b588b +References: git-fixes +Patch-mainline: v5.6-rc3 + +Moved ISOC request length checking from dwc2_hsotg_start_req() function to +dwc2_hsotg_ep_queue(). + +Fixes: 4fca54aa58293 ("usb: gadget: s3c-hsotg: add multi count support") +Signed-off-by: Minas Harutyunyan +Signed-off-by: Felipe Balbi +Signed-off-by: Oliver Neukum +--- + drivers/usb/dwc2/gadget.c | 12 +++++++----- + 1 file changed, 7 insertions(+), 5 deletions(-) + +--- a/drivers/usb/dwc2/gadget.c ++++ b/drivers/usb/dwc2/gadget.c +@@ -1049,11 +1049,6 @@ static void dwc2_hsotg_start_req(struct + else + packets = 1; /* send one packet if length is zero. */ + +- if (hs_ep->isochronous && length > (hs_ep->mc * hs_ep->ep.maxpacket)) { +- dev_err(hsotg->dev, "req length > maxpacket*mc\n"); +- return; +- } +- + if (dir_in && index != 0) + if (hs_ep->isochronous) + epsize = DXEPTSIZ_MC(packets); +@@ -1354,6 +1349,13 @@ static int dwc2_hsotg_ep_queue(struct us + req->actual = 0; + req->status = -EINPROGRESS; + ++ /* Don't queue ISOC request if length greater than mps*mc */ ++ if (hs_ep->isochronous && ++ req->length > (hs_ep->mc * hs_ep->ep.maxpacket)) { ++ dev_err(hs->dev, "req length > maxpacket*mc\n"); ++ return -EINVAL; ++ } ++ + ret = dwc2_hsotg_handle_unaligned_buf_start(hs, hs_ep, hs_req); + if (ret) + return ret; diff --git a/patches.suse/0001-usb-gadget-composite-Fix-bMaxPower-for-SuperSpeedPlu.patch b/patches.suse/0001-usb-gadget-composite-Fix-bMaxPower-for-SuperSpeedPlu.patch new file mode 100644 index 0000000..08980c1 --- /dev/null +++ b/patches.suse/0001-usb-gadget-composite-Fix-bMaxPower-for-SuperSpeedPlu.patch @@ -0,0 +1,46 @@ +From c724417baf162bd3e035659e22cdf990cfb0d917 Mon Sep 17 00:00:00 2001 +From: Jack Pham +Date: Thu, 30 Jan 2020 19:10:35 -0800 +Subject: [PATCH] usb: gadget: composite: Fix bMaxPower for SuperSpeedPlus +Git-commit: c724417baf162bd3e035659e22cdf990cfb0d917 +References: git-fixes +Patch-mainline: v5.6-rc3 + +SuperSpeedPlus peripherals must report their bMaxPower of the +configuration descriptor in units of 8mA as per the USB 3.2 +specification. The current switch statement in encode_bMaxPower() +only checks for USB_SPEED_SUPER but not USB_SPEED_SUPER_PLUS so +the latter falls back to USB 2.0 encoding which uses 2mA units. +Replace the switch with a simple if/else. + +Fixes: eae5820b852f ("usb: gadget: composite: Write SuperSpeedPlus config descriptors") +Signed-off-by: Jack Pham +Signed-off-by: Felipe Balbi +Signed-off-by: Oliver Neukum +--- + drivers/usb/gadget/composite.c | 8 +++----- + 1 file changed, 3 insertions(+), 5 deletions(-) + +diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c +index 3b4f67000315..cd303a3ea680 100644 +--- a/drivers/usb/gadget/composite.c ++++ b/drivers/usb/gadget/composite.c +@@ -437,12 +437,10 @@ static u8 encode_bMaxPower(enum usb_device_speed speed, + val = CONFIG_USB_GADGET_VBUS_DRAW; + if (!val) + return 0; +- switch (speed) { +- case USB_SPEED_SUPER: +- return DIV_ROUND_UP(val, 8); +- default: ++ if (speed < USB_SPEED_SUPER) + return DIV_ROUND_UP(val, 2); +- } ++ else ++ return DIV_ROUND_UP(val, 8); + } + + static int config_buf(struct usb_configuration *config, +-- +2.16.4 + diff --git a/patches.suse/0001-usb-host-xhci-plat-add-a-shutdown.patch b/patches.suse/0001-usb-host-xhci-plat-add-a-shutdown.patch new file mode 100644 index 0000000..4135e2d --- /dev/null +++ b/patches.suse/0001-usb-host-xhci-plat-add-a-shutdown.patch @@ -0,0 +1,37 @@ +From b433e340e7565110b0ce9ca4b3e26f4b97a1decf Mon Sep 17 00:00:00 2001 +From: Ran Wang +Date: Fri, 6 Mar 2020 17:23:28 +0800 +Subject: [PATCH] usb: host: xhci-plat: add a shutdown +Git-commit: b433e340e7565110b0ce9ca4b3e26f4b97a1decf +References: git-fixes +Patch-mainline: v5.6-rc7 + +When loading new kernel via kexec, we need to shutdown host controller to +avoid any un-expected memory accessing during new kernel boot. + +Signed-off-by: Ran Wang +Cc: stable +Tested-by: Stephen Boyd +Reviewed-by: Peter Chen +Link: https://lore.kernel.org/r/20200306092328.41253-1-ran.wang_1@nxp.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Oliver Neukum +--- + drivers/usb/host/xhci-plat.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/usb/host/xhci-plat.c b/drivers/usb/host/xhci-plat.c +index d90cd5ec09cf..315b4552693c 100644 +--- a/drivers/usb/host/xhci-plat.c ++++ b/drivers/usb/host/xhci-plat.c +@@ -445,6 +445,7 @@ MODULE_DEVICE_TABLE(acpi, usb_xhci_acpi_match); + static struct platform_driver usb_xhci_driver = { + .probe = xhci_plat_probe, + .remove = xhci_plat_remove, ++ .shutdown = usb_hcd_platform_shutdown, + .driver = { + .name = "xhci-hcd", + .pm = &xhci_plat_pm_ops, +-- +2.16.4 + diff --git a/patches.suse/0001-usb-host-xhci-update-event-ring-dequeue-pointer-on-p.patch b/patches.suse/0001-usb-host-xhci-update-event-ring-dequeue-pointer-on-p.patch new file mode 100644 index 0000000..1e78c4c --- /dev/null +++ b/patches.suse/0001-usb-host-xhci-update-event-ring-dequeue-pointer-on-p.patch @@ -0,0 +1,119 @@ +From dc0ffbea5729a3abafa577ebfce87f18b79e294b Mon Sep 17 00:00:00 2001 +From: Peter Chen +Date: Fri, 15 Nov 2019 18:50:00 +0200 +Subject: [PATCH] usb: host: xhci: update event ring dequeue pointer on purpose +Git-commit: dc0ffbea5729a3abafa577ebfce87f18b79e294b +References: git-fixes +Patch-mainline: v5.5 + +On some situations, the software handles TRB events slower +than adding TRBs, then xhci_handle_event can't return zero +long time, the xHC will consider the event ring is full, +and trigger "Event Ring Full" error, but in fact, the software +has already finished lots of events, just no chance to +update ERDP (event ring dequeue pointer). + +In this commit, we force update ERDP if half of TRBS_PER_SEGMENT +events have handled to avoid "Event Ring Full" error. + +Signed-off-by: Peter Chen +Signed-off-by: Mathias Nyman +Link: https://lore.kernel.org/r/1573836603-10871-2-git-send-email-mathias.nyman@linux.intel.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Oliver Neukum +--- + drivers/usb/host/xhci-ring.c | 60 +++++++++++++++++++++++++++++++------------- + 1 file changed, 43 insertions(+), 17 deletions(-) + +diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c +index e7aab31fd9a5..55084adf1faf 100644 +--- a/drivers/usb/host/xhci-ring.c ++++ b/drivers/usb/host/xhci-ring.c +@@ -2740,6 +2740,42 @@ static int xhci_handle_event(struct xhci_hcd *xhci) + return 1; + } + ++/* ++ * Update Event Ring Dequeue Pointer: ++ * - When all events have finished ++ * - To avoid "Event Ring Full Error" condition ++ */ ++static void xhci_update_erst_dequeue(struct xhci_hcd *xhci, ++ union xhci_trb *event_ring_deq) ++{ ++ u64 temp_64; ++ dma_addr_t deq; ++ ++ temp_64 = xhci_read_64(xhci, &xhci->ir_set->erst_dequeue); ++ /* If necessary, update the HW's version of the event ring deq ptr. */ ++ if (event_ring_deq != xhci->event_ring->dequeue) { ++ deq = xhci_trb_virt_to_dma(xhci->event_ring->deq_seg, ++ xhci->event_ring->dequeue); ++ if (deq == 0) ++ xhci_warn(xhci, "WARN something wrong with SW event ring dequeue ptr\n"); ++ /* ++ * Per 4.9.4, Software writes to the ERDP register shall ++ * always advance the Event Ring Dequeue Pointer value. ++ */ ++ if ((temp_64 & (u64) ~ERST_PTR_MASK) == ++ ((u64) deq & (u64) ~ERST_PTR_MASK)) ++ return; ++ ++ /* Update HC event ring dequeue pointer */ ++ temp_64 &= ERST_PTR_MASK; ++ temp_64 |= ((u64) deq & (u64) ~ERST_PTR_MASK); ++ } ++ ++ /* Clear the event handler busy flag (RW1C) */ ++ temp_64 |= ERST_EHB; ++ xhci_write_64(xhci, temp_64, &xhci->ir_set->erst_dequeue); ++} ++ + /* + * xHCI spec says we can get an interrupt, and if the HC has an error condition, + * we might get bad data out of the event ring. Section 4.10.2.7 has a list of +@@ -2751,9 +2787,9 @@ irqreturn_t xhci_irq(struct usb_hcd *hcd) + union xhci_trb *event_ring_deq; + irqreturn_t ret = IRQ_NONE; + unsigned long flags; +- dma_addr_t deq; + u64 temp_64; + u32 status; ++ int event_loop = 0; + + spin_lock_irqsave(&xhci->lock, flags); + /* Check if the xHC generated the interrupt, or the irq is shared */ +@@ -2807,24 +2843,14 @@ irqreturn_t xhci_irq(struct usb_hcd *hcd) + /* FIXME this should be a delayed service routine + * that clears the EHB. + */ +- while (xhci_handle_event(xhci) > 0) {} +- +- temp_64 = xhci_read_64(xhci, &xhci->ir_set->erst_dequeue); +- /* If necessary, update the HW's version of the event ring deq ptr. */ +- if (event_ring_deq != xhci->event_ring->dequeue) { +- deq = xhci_trb_virt_to_dma(xhci->event_ring->deq_seg, +- xhci->event_ring->dequeue); +- if (deq == 0) +- xhci_warn(xhci, "WARN something wrong with SW event " +- "ring dequeue ptr.\n"); +- /* Update HC event ring dequeue pointer */ +- temp_64 &= ERST_PTR_MASK; +- temp_64 |= ((u64) deq & (u64) ~ERST_PTR_MASK); ++ while (xhci_handle_event(xhci) > 0) { ++ if (event_loop++ < TRBS_PER_SEGMENT / 2) ++ continue; ++ xhci_update_erst_dequeue(xhci, event_ring_deq); ++ event_loop = 0; + } + +- /* Clear the event handler busy flag (RW1C); event ring is empty. */ +- temp_64 |= ERST_EHB; +- xhci_write_64(xhci, temp_64, &xhci->ir_set->erst_dequeue); ++ xhci_update_erst_dequeue(xhci, event_ring_deq); + ret = IRQ_HANDLED; + + out: +-- +2.16.4 + diff --git a/patches.suse/0001-usb-musb-Disable-pullup-at-init.patch b/patches.suse/0001-usb-musb-Disable-pullup-at-init.patch new file mode 100644 index 0000000..c38d203 --- /dev/null +++ b/patches.suse/0001-usb-musb-Disable-pullup-at-init.patch @@ -0,0 +1,42 @@ +From 96a0c12843109e5c4d5eb1e09d915fdd0ce31d25 Mon Sep 17 00:00:00 2001 +From: Paul Cercueil +Date: Tue, 7 Jan 2020 09:26:25 -0600 +Subject: [PATCH] usb: musb: Disable pullup at init +Git-commit: 96a0c12843109e5c4d5eb1e09d915fdd0ce31d25 +References: git-fixes +Patch-mainline: v5.5 + +The pullup may be already enabled before the driver is initialized. This +happens for instance on JZ4740. + +It has to be disabled at init time, as we cannot guarantee that a gadget +driver will be bound to the UDC. + +Signed-off-by: Paul Cercueil +Suggested-by: Bin Liu +Cc: stable@vger.kernel.org +Signed-off-by: Bin Liu +Link: https://lore.kernel.org/r/20200107152625.857-3-b-liu@ti.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Oliver Neukum +--- + drivers/usb/musb/musb_core.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c +index 0096fc303cd4..5ebf30bd61bd 100644 +--- a/drivers/usb/musb/musb_core.c ++++ b/drivers/usb/musb/musb_core.c +@@ -2318,6 +2318,9 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl) + musb_disable_interrupts(musb); + musb_writeb(musb->mregs, MUSB_DEVCTL, 0); + ++ /* MUSB_POWER_SOFTCONN might be already set, JZ4740 does this. */ ++ musb_writeb(musb->mregs, MUSB_POWER, 0); ++ + /* Init IRQ workqueue before request_irq */ + INIT_DELAYED_WORK(&musb->irq_work, musb_irq_work); + INIT_DELAYED_WORK(&musb->deassert_reset_work, musb_deassert_reset); +-- +2.16.4 + diff --git a/patches.suse/0001-usb-quirks-add-NO_LPM-quirk-for-Logitech-Screen-Shar.patch b/patches.suse/0001-usb-quirks-add-NO_LPM-quirk-for-Logitech-Screen-Shar.patch new file mode 100644 index 0000000..ac69ad5 --- /dev/null +++ b/patches.suse/0001-usb-quirks-add-NO_LPM-quirk-for-Logitech-Screen-Shar.patch @@ -0,0 +1,38 @@ +From b96ed52d781a2026d0c0daa5787c6f3d45415862 Mon Sep 17 00:00:00 2001 +From: Dan Lazewatsky +Date: Wed, 26 Feb 2020 14:34:38 +0000 +Subject: [PATCH] usb: quirks: add NO_LPM quirk for Logitech Screen Share +Git-commit: b96ed52d781a2026d0c0daa5787c6f3d45415862 +References: git-fixes +Patch-mainline: v5.6-rc5 + +LPM on the device appears to cause xHCI host controllers to claim +that there isn't enough bandwidth to support additional devices. + +Signed-off-by: Dan Lazewatsky +Cc: stable +Signed-off-by: Gustavo Padovan +Link: https://lore.kernel.org/r/20200226143438.1445-1-gustavo.padovan@collabora.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Oliver Neukum +--- + drivers/usb/core/quirks.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c +index 2b24336a72e5..2dac3e7cdd97 100644 +--- a/drivers/usb/core/quirks.c ++++ b/drivers/usb/core/quirks.c +@@ -231,6 +231,9 @@ static const struct usb_device_id usb_quirk_list[] = { + /* Logitech PTZ Pro Camera */ + { USB_DEVICE(0x046d, 0x0853), .driver_info = USB_QUIRK_DELAY_INIT }, + ++ /* Logitech Screen Share */ ++ { USB_DEVICE(0x046d, 0x086c), .driver_info = USB_QUIRK_NO_LPM }, ++ + /* Logitech Quickcam Fusion */ + { USB_DEVICE(0x046d, 0x08c1), .driver_info = USB_QUIRK_RESET_RESUME }, + +-- +2.16.4 + diff --git a/patches.suse/0001-usb-quirks-add-NO_LPM-quirk-for-RTL8153-based-ethern.patch b/patches.suse/0001-usb-quirks-add-NO_LPM-quirk-for-RTL8153-based-ethern.patch new file mode 100644 index 0000000..e3e20fb --- /dev/null +++ b/patches.suse/0001-usb-quirks-add-NO_LPM-quirk-for-RTL8153-based-ethern.patch @@ -0,0 +1,57 @@ +From 75d7676ead19b1fbb5e0ee934c9ccddcb666b68c Mon Sep 17 00:00:00 2001 +From: Hans de Goede +Date: Fri, 13 Mar 2020 13:07:08 +0100 +Subject: [PATCH] usb: quirks: add NO_LPM quirk for RTL8153 based ethernet + adapters +Git-commit: 75d7676ead19b1fbb5e0ee934c9ccddcb666b68c +References: git-fixes +Patch-mainline: v5.6-rc7 + +We have been receiving bug reports that ethernet connections over +RTL8153 based ethernet adapters stops working after a while with +errors like these showing up in dmesg when the ethernet stops working: + +[12696.189484] r8152 6-1:1.0 enp10s0u1: Tx timeout +[12702.333456] r8152 6-1:1.0 enp10s0u1: Tx timeout +[12707.965422] r8152 6-1:1.0 enp10s0u1: Tx timeout + +This has been reported on Dell WD15 docks, Belkin USB-C Express Dock 3.1 +docks and with generic USB to ethernet dongles using the RTL8153 +chipsets. Some users have tried adding usbcore.quirks=0bda:8153:k to +the kernel commandline and all users who have tried this report that +this fixes this. + +Also note that we already have an existing NO_LPM quirk for the RTL8153 +used in the Microsoft Surface Dock (where it uses a different usb-id). + +This commit adds a NO_LPM quirk for the generic Realtek RTL8153 +0bda:8153 usb-id, fixing the Tx timeout errors on these devices. + +BugLink: https://bugzilla.kernel.org/show_bug.cgi?id=198931 +Cc: stable@vger.kernel.org +Cc: russianneuromancer@ya.ru +Signed-off-by: Hans de Goede +Link: https://lore.kernel.org/r/20200313120708.100339-1-hdegoede@redhat.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Oliver Neukum +--- + drivers/usb/core/quirks.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c +index df6e6156e1d4..da30b5664ff3 100644 +--- a/drivers/usb/core/quirks.c ++++ b/drivers/usb/core/quirks.c +@@ -381,6 +381,9 @@ static const struct usb_device_id usb_quirk_list[] = { + /* Realtek hub in Dell WD19 (Type-C) */ + { USB_DEVICE(0x0bda, 0x0487), .driver_info = USB_QUIRK_NO_LPM }, + ++ /* Generic RTL8153 based ethernet adapters */ ++ { USB_DEVICE(0x0bda, 0x8153), .driver_info = USB_QUIRK_NO_LPM }, ++ + /* Action Semiconductor flash disk */ + { USB_DEVICE(0x10d6, 0x2200), .driver_info = + USB_QUIRK_STRING_FETCH_255 }, +-- +2.16.4 + diff --git a/patches.suse/0001-usb-storage-Add-quirk-for-Samsung-Fit-flash.patch b/patches.suse/0001-usb-storage-Add-quirk-for-Samsung-Fit-flash.patch new file mode 100644 index 0000000..8112224 --- /dev/null +++ b/patches.suse/0001-usb-storage-Add-quirk-for-Samsung-Fit-flash.patch @@ -0,0 +1,49 @@ +From 86d92f5465958752481269348d474414dccb1552 Mon Sep 17 00:00:00 2001 +From: Jim Lin +Date: Mon, 2 Mar 2020 22:21:35 +0800 +Subject: [PATCH] usb: storage: Add quirk for Samsung Fit flash +Git-commit: 86d92f5465958752481269348d474414dccb1552 +References: git-fixes +Patch-mainline: v5.6-rc5 + +Current driver has 240 (USB2.0) and 2048 (USB3.0) as max_sectors, +e.g., /sys/bus/scsi/devices/0:0:0:0/max_sectors + +If data access times out, driver error handling will issue a port +reset. +Sometimes Samsung Fit (090C:1000) flash disk will not respond to +later Set Address or Get Descriptor command. + +Adding this quirk to limit max_sectors to 64 sectors to avoid issue +occurring. + +Signed-off-by: Jim Lin +Acked-by: Alan Stern +Cc: stable +Link: https://lore.kernel.org/r/1583158895-31342-1-git-send-email-jilin@nvidia.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Oliver Neukum +--- + drivers/usb/storage/unusual_devs.h | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h +index 1cd9b6305b06..1880f3e13f57 100644 +--- a/drivers/usb/storage/unusual_devs.h ++++ b/drivers/usb/storage/unusual_devs.h +@@ -1258,6 +1258,12 @@ UNUSUAL_DEV( 0x090a, 0x1200, 0x0000, 0x9999, + USB_SC_RBC, USB_PR_BULK, NULL, + 0 ), + ++UNUSUAL_DEV(0x090c, 0x1000, 0x1100, 0x1100, ++ "Samsung", ++ "Flash Drive FIT", ++ USB_SC_DEVICE, USB_PR_DEVICE, NULL, ++ US_FL_MAX_SECTORS_64), ++ + /* aeb */ + UNUSUAL_DEV( 0x090c, 0x1132, 0x0000, 0xffff, + "Feiya", +-- +2.16.4 + diff --git a/patches.suse/0001-usb-uas-fix-a-plug-unplug-racing.patch b/patches.suse/0001-usb-uas-fix-a-plug-unplug-racing.patch new file mode 100644 index 0000000..084197d --- /dev/null +++ b/patches.suse/0001-usb-uas-fix-a-plug-unplug-racing.patch @@ -0,0 +1,104 @@ +From 3e99862c05a9caa5a27969f41566b428696f5a9a Mon Sep 17 00:00:00 2001 +From: EJ Hsu +Date: Thu, 30 Jan 2020 01:25:06 -0800 +Subject: [PATCH] usb: uas: fix a plug & unplug racing +Git-commit: 3e99862c05a9caa5a27969f41566b428696f5a9a +References: git-fixes +Patch-mainline: v5.6-rc3 + +When a uas disk is plugged into an external hub, uas_probe() +will be called by the hub thread to do the probe. It will +first create a SCSI host and then do the scan for this host. +During the scan, it will probe the LUN using SCSI INQUERY command +which will be packed in the URB and submitted to uas disk. + +There might be a chance that this external hub with uas disk +attached is unplugged during the scan. In this case, uas driver +will fail to submit the URB (due to the NOTATTACHED state of uas +device) and try to put this SCSI command back to request queue +waiting for next chance to run. + +In normal case, this cycle will terminate when hub thread gets +disconnection event and calls into uas_disconnect() accordingly. +But in this case, uas_disconnect() will not be called because +hub thread of external hub gets stuck waiting for the completion +of this SCSI command. A deadlock happened. + +In this fix, uas will call scsi_scan_host() asynchronously to +avoid the blocking of hub thread. + +Signed-off-by: EJ Hsu +Acked-by: Oliver Neukum +Cc: stable +Link: https://lore.kernel.org/r/20200130092506.102760-1-ejh@nvidia.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Oliver Neukum +--- + drivers/usb/storage/uas.c | 23 ++++++++++++++++++++++- + 1 file changed, 22 insertions(+), 1 deletion(-) + +diff --git a/drivers/usb/storage/uas.c b/drivers/usb/storage/uas.c +index 95bba3ba6ac6..3670fda02c34 100644 +--- a/drivers/usb/storage/uas.c ++++ b/drivers/usb/storage/uas.c +@@ -45,6 +45,7 @@ struct uas_dev_info { + struct scsi_cmnd *cmnd[MAX_CMNDS]; + spinlock_t lock; + struct work_struct work; ++ struct work_struct scan_work; /* for async scanning */ + }; + + enum { +@@ -114,6 +115,17 @@ static void uas_do_work(struct work_struct *work) + spin_unlock_irqrestore(&devinfo->lock, flags); + } + ++static void uas_scan_work(struct work_struct *work) ++{ ++ struct uas_dev_info *devinfo = ++ container_of(work, struct uas_dev_info, scan_work); ++ struct Scsi_Host *shost = usb_get_intfdata(devinfo->intf); ++ ++ dev_dbg(&devinfo->intf->dev, "starting scan\n"); ++ scsi_scan_host(shost); ++ dev_dbg(&devinfo->intf->dev, "scan complete\n"); ++} ++ + static void uas_add_work(struct uas_cmd_info *cmdinfo) + { + struct scsi_pointer *scp = (void *)cmdinfo; +@@ -982,6 +994,7 @@ static int uas_probe(struct usb_interface *intf, const struct usb_device_id *id) + init_usb_anchor(&devinfo->data_urbs); + spin_lock_init(&devinfo->lock); + INIT_WORK(&devinfo->work, uas_do_work); ++ INIT_WORK(&devinfo->scan_work, uas_scan_work); + + result = uas_configure_endpoints(devinfo); + if (result) +@@ -998,7 +1011,9 @@ static int uas_probe(struct usb_interface *intf, const struct usb_device_id *id) + if (result) + goto free_streams; + +- scsi_scan_host(shost); ++ /* Submit the delayed_work for SCSI-device scanning */ ++ schedule_work(&devinfo->scan_work); ++ + return result; + + free_streams: +@@ -1166,6 +1181,12 @@ static void uas_disconnect(struct usb_interface *intf) + usb_kill_anchored_urbs(&devinfo->data_urbs); + uas_zap_pending(devinfo, DID_NO_CONNECT); + ++ /* ++ * Prevent SCSI scanning (if it hasn't started yet) ++ * or wait for the SCSI-scanning routine to stop. ++ */ ++ cancel_work_sync(&devinfo->scan_work); ++ + scsi_remove_host(shost); + uas_free_streams(devinfo); + scsi_host_put(shost); +-- +2.16.4 + diff --git a/patches.suse/0001-usb-xhci-apply-XHCI_SUSPEND_DELAY-to-AMD-XHCI-contro.patch b/patches.suse/0001-usb-xhci-apply-XHCI_SUSPEND_DELAY-to-AMD-XHCI-contro.patch new file mode 100644 index 0000000..7bd3661 --- /dev/null +++ b/patches.suse/0001-usb-xhci-apply-XHCI_SUSPEND_DELAY-to-AMD-XHCI-contro.patch @@ -0,0 +1,44 @@ +From 16263abc12d09871156a1c8650fb651f0e552f5e Mon Sep 17 00:00:00 2001 +From: Alberto Mattea +Date: Fri, 6 Mar 2020 17:08:58 +0200 +Subject: [PATCH] usb: xhci: apply XHCI_SUSPEND_DELAY to AMD XHCI controller + 1022:145c +Git-commit: 16263abc12d09871156a1c8650fb651f0e552f5e +References: git-fixes +Patch-mainline: v5.6-rc7 + +This controller timeouts during suspend (S3) with +[ 240.521724] xhci_hcd 0000:30:00.3: WARN: xHC save state timeout +[ 240.521729] xhci_hcd 0000:30:00.3: ERROR mismatched command completion event +thus preventing the system from entering S3. +Moreover it remains in an undefined state where some connected devices stop +working until a reboot. +Apply the XHCI_SUSPEND_DELAY quirk to make it suspend properly. + +CC: stable@vger.kernel.org +Signed-off-by: Alberto Mattea +Signed-off-by: Mathias Nyman +Link: https://lore.kernel.org/r/20200306150858.21904-3-mathias.nyman@linux.intel.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Oliver Neukum +--- + drivers/usb/host/xhci-pci.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c +index 5e9b537df631..1fddc41fa1f3 100644 +--- a/drivers/usb/host/xhci-pci.c ++++ b/drivers/usb/host/xhci-pci.c +@@ -136,7 +136,8 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci) + xhci->quirks |= XHCI_AMD_PLL_FIX; + + if (pdev->vendor == PCI_VENDOR_ID_AMD && +- (pdev->device == 0x15e0 || ++ (pdev->device == 0x145c || ++ pdev->device == 0x15e0 || + pdev->device == 0x15e1 || + pdev->device == 0x43bb)) + xhci->quirks |= XHCI_SUSPEND_DELAY; +-- +2.16.4 + diff --git a/patches.suse/0001-usbip-Fix-uninitialized-symbol-nents-in-stub_recv_cm.patch b/patches.suse/0001-usbip-Fix-uninitialized-symbol-nents-in-stub_recv_cm.patch new file mode 100644 index 0000000..2a11cdb --- /dev/null +++ b/patches.suse/0001-usbip-Fix-uninitialized-symbol-nents-in-stub_recv_cm.patch @@ -0,0 +1,120 @@ +From 2a9125317b247f2cf35c196f968906dcf062ae2d Mon Sep 17 00:00:00 2001 +From: Suwan Kim +Date: Mon, 11 Nov 2019 23:10:35 +0900 +Subject: [PATCH] usbip: Fix uninitialized symbol 'nents' in + stub_recv_cmd_submit() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit +Git-commit: 2a9125317b247f2cf35c196f968906dcf062ae2d +References: git-fixes +Patch-mainline: v5.5 + +Smatch reported that nents is not initialized and used in +stub_recv_cmd_submit(). nents is currently initialized by sgl_alloc() +and used to allocate multiple URBs when host controller doesn't +support scatter-gather DMA. The use of uninitialized nents means that +buf_len is zero and use_sg is true. But buffer length should not be +zero when an URB uses scatter-gather DMA. + +To prevent this situation, add the conditional that checks buf_len +and use_sg. And move the use of nents right after the sgl_alloc() to +avoid the use of uninitialized nents. + +If the error occurs, it adds SDEV_EVENT_ERROR_MALLOC and stub_priv +will be released by stub event handler and connection will be shut +down. + +Fixes: ea44d190764b ("usbip: Implement SG support to vhci-hcd and stub driver") +Reported-by: kbuild test robot +Reported-by: Dan Carpenter +Signed-off-by: Suwan Kim +Acked-by: Shuah Khan +Cc: stable +Link: https://lore.kernel.org/r/20191111141035.27788-1-suwan.kim027@gmail.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Oliver Neukum +--- + drivers/usb/usbip/stub_rx.c | 53 ++++++++++++++++++++++++++++---------------- + 1 file changed, 34 insertions(+), 19 deletions(-) + +--- a/drivers/usb/usbip/stub_rx.c ++++ b/drivers/usb/usbip/stub_rx.c +@@ -495,18 +495,51 @@ static void stub_recv_cmd_submit(struct + if (pipe == -1) + return; + ++ /* ++ * Smatch reported the error case where use_sg is true and buf_len is 0. ++ * In this case, It adds SDEV_EVENT_ERROR_MALLOC and stub_priv will be ++ * released by stub event handler and connection will be shut down. ++ */ ++ + priv = stub_priv_alloc(sdev, pdu); + if (!priv) + return; + + buf_len = (unsigned long long)pdu->u.cmd_submit.transfer_buffer_length; ++ ++ if (use_sg && !buf_len) { ++ dev_err(&udev->dev, "sg buffer with zero length\n"); ++ goto err_malloc; ++ } + +- /* allocate urb transfer buffer, if needed */ ++ /* allocate urb transfer buffer, if needed */ + if (buf_len) { + if (use_sg) { + sgl = sgl_alloc(buf_len, GFP_KERNEL, &nents); + if (!sgl) + goto err_malloc; ++ ++ /* Check if the server's HCD supports SG */ ++ if (!udev->bus->sg_tablesize) { ++ /* ++ * If the server's HCD doesn't support SG, break ++ * a single SG request into several URBs and map ++ * each SG list entry to corresponding URB ++ * buffer. The previously allocated SG list is ++ * stored in priv->sgl (If the server's HCD ++ * support SG, SG list is stored only in ++ * urb->sg) and it is used as an indicator that ++ * the server split single SG request into ++ * several URBs. Later, priv->sgl is used by ++ * stub_complete() and stub_send_ret_submit() to ++ * reassemble the divied URBs. ++ */ ++ support_sg = 0; ++ num_urbs = nents; ++ priv->completed_urbs = 0; ++ pdu->u.cmd_submit.transfer_flags &= ++ ~URB_DMA_MAP_SG; ++ } + } else { + buffer = kzalloc(buf_len, GFP_KERNEL); + if (!buffer) +@@ -514,24 +547,6 @@ static void stub_recv_cmd_submit(struct + } + } + +- /* Check if the server's HCD supports SG */ +- if (use_sg && !udev->bus->sg_tablesize) { +- /* +- * If the server's HCD doesn't support SG, break a single SG +- * request into several URBs and map each SG list entry to +- * corresponding URB buffer. The previously allocated SG +- * list is stored in priv->sgl (If the server's HCD support SG, +- * SG list is stored only in urb->sg) and it is used as an +- * indicator that the server split single SG request into +- * several URBs. Later, priv->sgl is used by stub_complete() and +- * stub_send_ret_submit() to reassemble the divied URBs. +- */ +- support_sg = 0; +- num_urbs = nents; +- priv->completed_urbs = 0; +- pdu->u.cmd_submit.transfer_flags &= ~URB_DMA_MAP_SG; +- } +- + /* allocate urb array */ + priv->num_urbs = num_urbs; + priv->urbs = kmalloc_array(num_urbs, sizeof(*priv->urbs), GFP_KERNEL); diff --git a/patches.suse/0001-vgacon-Fix-a-UAF-in-vgacon_invert_region.patch b/patches.suse/0001-vgacon-Fix-a-UAF-in-vgacon_invert_region.patch new file mode 100644 index 0000000..70497aa --- /dev/null +++ b/patches.suse/0001-vgacon-Fix-a-UAF-in-vgacon_invert_region.patch @@ -0,0 +1,133 @@ +From 513dc792d6060d5ef572e43852683097a8420f56 Mon Sep 17 00:00:00 2001 +From: Zhang Xiaoxu +Date: Wed, 4 Mar 2020 10:24:29 +0800 +Subject: vgacon: Fix a UAF in vgacon_invert_region +Git-commit: 513dc792d6060d5ef572e43852683097a8420f56 +Patch-mainline: v5.6-rc5 +References: CVE-2020-8647 bsc#1162929 CVE-2020-8649 bsc#1162931 bsc#1114279 + +When syzkaller tests, there is a UAF: + BUG: KASan: use after free in vgacon_invert_region+0x9d/0x110 at addr + ffff880000100000 + Read of size 2 by task syz-executor.1/16489 + page:ffffea0000004000 count:0 mapcount:-127 mapping: (null) + index:0x0 + page flags: 0xfffff00000000() + page dumped because: kasan: bad access detected + CPU: 1 PID: 16489 Comm: syz-executor.1 Not tainted + Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS + rel-1.9.3-0-ge2fc41e-prebuilt.qemu-project.org 04/01/2014 + Call Trace: + [] dump_stack+0x1e/0x20 + [] kasan_report+0x577/0x950 + [] __asan_load2+0x62/0x80 + [] vgacon_invert_region+0x9d/0x110 + [] invert_screen+0xe5/0x470 + [] set_selection+0x44b/0x12f0 + [] tioclinux+0xee/0x490 + [] vt_ioctl+0xff4/0x2670 + [] tty_ioctl+0x46a/0x1a10 + [] do_vfs_ioctl+0x5bd/0xc40 + [] SyS_ioctl+0x132/0x170 + [] system_call_fastpath+0x22/0x27 + Memory state around the buggy address: + ffff8800000fff00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 + ffff8800000fff80: 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 + >ffff880000100000: ff ff ff ff ff ff ff ff ff ff ff ff ff + ff ff ff + +It can be reproduce in the linux mainline by the program: + #include + #include + #include + #include + #include + #include + #include + #include + + struct tiocl_selection { + unsigned short xs; /* X start */ + unsigned short ys; /* Y start */ + unsigned short xe; /* X end */ + unsigned short ye; /* Y end */ + unsigned short sel_mode; /* selection mode */ + }; + + #define TIOCL_SETSEL 2 + struct tiocl { + unsigned char type; + unsigned char pad; + struct tiocl_selection sel; + }; + + int main() + { + int fd = 0; + const char *dev = "/dev/char/4:1"; + + struct vt_consize v = {0}; + struct tiocl tioc = {0}; + + fd = open(dev, O_RDWR, 0); + + v.v_rows = 3346; + ioctl(fd, VT_RESIZEX, &v); + + tioc.type = TIOCL_SETSEL; + ioctl(fd, TIOCLINUX, &tioc); + + return 0; + } + +When resize the screen, update the 'vc->vc_size_row' to the new_row_size, +but when 'set_origin' in 'vgacon_set_origin', vgacon use 'vga_vram_base' +for 'vc_origin' and 'vc_visible_origin', not 'vc_screenbuf'. It maybe +smaller than 'vc_screenbuf'. When TIOCLINUX, use the new_row_size to calc +the offset, it maybe larger than the vga_vram_size in vgacon driver, then +bad access. +Also, if set an larger screenbuf firstly, then set an more larger +screenbuf, when copy old_origin to new_origin, a bad access may happen. + +So, If the screen size larger than vga_vram, resize screen should be +failed. This alse fix CVE-2020-8649 and CVE-2020-8647. + +Linus pointed out that overflow checking seems absent. We're saved by +the existing bounds checks in vc_do_resize() with rather strict +limits: + + if (cols > VC_RESIZE_MAXCOL || lines > VC_RESIZE_MAXROW) + return -EINVAL; + +Fixes: 0aec4867dca14 ("[PATCH] SVGATextMode fix") +Reference: CVE-2020-8647 and CVE-2020-8649 +Reported-by: Hulk Robot +Signed-off-by: Zhang Xiaoxu +[danvet: augment commit message to point out overflow safety] +Cc: stable@vger.kernel.org +Signed-off-by: Daniel Vetter +Link: https://patchwork.freedesktop.org/patch/msgid/20200304022429.37738-1-zhangxiaoxu5@huawei.com +Acked-by: Thomas Zimmermann +--- + drivers/video/console/vgacon.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c +index de7b8382aba9..998b0de1812f 100644 +--- a/drivers/video/console/vgacon.c ++++ b/drivers/video/console/vgacon.c +@@ -1316,6 +1316,9 @@ static int vgacon_font_get(struct vc_data *c, struct console_font *font) + static int vgacon_resize(struct vc_data *c, unsigned int width, + unsigned int height, unsigned int user) + { ++ if ((width << 1) * height > vga_vram_size) ++ return -EINVAL; ++ + if (width % 2 || width > screen_info.orig_video_cols || + height > (screen_info.orig_video_lines * vga_default_font_height)/ + c->vc_font.height) +-- +2.25.1 + diff --git a/patches.suse/0001-virtio-blk-fix-hw_queue-stopped-on-arbitrary-error.patch b/patches.suse/0001-virtio-blk-fix-hw_queue-stopped-on-arbitrary-error.patch new file mode 100644 index 0000000..15505df --- /dev/null +++ b/patches.suse/0001-virtio-blk-fix-hw_queue-stopped-on-arbitrary-error.patch @@ -0,0 +1,49 @@ +From f5f6b95c72f7f8bb46eace8c5306c752d0133daa Mon Sep 17 00:00:00 2001 +From: Halil Pasic +Date: Thu, 13 Feb 2020 13:37:27 +0100 +Subject: [PATCH] virtio-blk: fix hw_queue stopped on arbitrary error +Git-commit: f5f6b95c72f7f8bb46eace8c5306c752d0133daa +Patch-mainline: v5.6.0 +References: git-fixes + +Since nobody else is going to restart our hw_queue for us, the +blk_mq_start_stopped_hw_queues() is in virtblk_done() is not sufficient +necessarily sufficient to ensure that the queue will get started again. +In case of global resource outage (-ENOMEM because mapping failure, +because of swiotlb full) our virtqueue may be empty and we can get +stuck with a stopped hw_queue. + +Let us not stop the queue on arbitrary errors, but only on -EONSPC which +indicates a full virtqueue, where the hw_queue is guaranteed to get +started by virtblk_done() before when it makes sense to carry on +submitting requests. Let us also remove a stale comment. + +Signed-off-by: Halil Pasic +Cc: Jens Axboe +Fixes: f7728002c1c7 ("virtio_ring: fix return code on DMA mapping fails") +Link: https://lore.kernel.org/r/20200213123728.61216-2-pasic@linux.ibm.com +Signed-off-by: Michael S. Tsirkin +Reviewed-by: Stefan Hajnoczi +Signed-off-by: Oliver Neukum +--- + drivers/block/virtio_blk.c | 8 +++++--- + 1 file changed, 5 insertions(+), 3 deletions(-) + +--- a/drivers/block/virtio_blk.c ++++ b/drivers/block/virtio_blk.c +@@ -271,10 +271,12 @@ static blk_status_t virtio_queue_rq(stru + err = virtblk_add_req(vblk->vqs[qid].vq, vbr, vbr->sg, num); + if (err) { + virtqueue_kick(vblk->vqs[qid].vq); +- blk_mq_stop_hw_queue(hctx); ++ /* Don't stop the queue if -ENOMEM: we may have failed to ++ * bounce the buffer due to global resource outage. ++ */ ++ if (err == -ENOSPC) ++ blk_mq_stop_hw_queue(hctx); + spin_unlock_irqrestore(&vblk->vqs[qid].lock, flags); +- /* Out of mem doesn't actually happen, since we fall back +- * to direct descriptors */ + if (err == -ENOMEM || err == -ENOSPC) + return BLK_STS_DEV_RESOURCE; + return BLK_STS_IOERR; diff --git a/patches.suse/0001-xhci-Do-not-open-code-__print_symbolic-in-xhci-trace.patch b/patches.suse/0001-xhci-Do-not-open-code-__print_symbolic-in-xhci-trace.patch new file mode 100644 index 0000000..4a49a07 --- /dev/null +++ b/patches.suse/0001-xhci-Do-not-open-code-__print_symbolic-in-xhci-trace.patch @@ -0,0 +1,73 @@ +From 045706bff837ee89c13f1ace173db71922c1c40b Mon Sep 17 00:00:00 2001 +From: "Steven Rostedt (VMware)" +Date: Fri, 6 Mar 2020 17:08:57 +0200 +Subject: [PATCH] xhci: Do not open code __print_symbolic() in xhci trace + events +Git-commit: 045706bff837ee89c13f1ace173db71922c1c40b +References: git-fixes +Patch-mainline: v5.6-rc7 + +libtraceevent (used by perf and trace-cmd) failed to parse the +xhci_urb_dequeue trace event. This is because the user space trace +event format parsing is not a full C compiler. It can handle some basic +logic, but is not meant to be able to handle everything C can do. + +In cases where a trace event field needs to be converted from a number +to a string, there's the __print_symbolic() macro that should be used: + + See samples/trace_events/trace-events-sample.h + +Some xhci trace events open coded the __print_symbolic() causing the +user spaces tools to fail to parse it. This has to be replaced with +__print_symbolic() instead. + +CC: stable@vger.kernel.org +Reported-by: Tzvetomir Stoyanov +Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=206531 +Fixes: 5abdc2e6e12ff ("usb: host: xhci: add urb_enqueue/dequeue/giveback tracers") +Signed-off-by: Steven Rostedt (VMware) +Signed-off-by: Mathias Nyman +Link: https://lore.kernel.org/r/20200306150858.21904-2-mathias.nyman@linux.intel.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Oliver Neukum +--- + drivers/usb/host/xhci-trace.h | 23 ++++++----------------- + 1 file changed, 6 insertions(+), 17 deletions(-) + +diff --git a/drivers/usb/host/xhci-trace.h b/drivers/usb/host/xhci-trace.h +index 56eb867803a6..b19582b2a72c 100644 +--- a/drivers/usb/host/xhci-trace.h ++++ b/drivers/usb/host/xhci-trace.h +@@ -289,23 +289,12 @@ DECLARE_EVENT_CLASS(xhci_log_urb, + ), + TP_printk("ep%d%s-%s: urb %p pipe %u slot %d length %d/%d sgs %d/%d stream %d flags %08x", + __entry->epnum, __entry->dir_in ? "in" : "out", +- ({ char *s; +- switch (__entry->type) { +- case USB_ENDPOINT_XFER_INT: +- s = "intr"; +- break; +- case USB_ENDPOINT_XFER_CONTROL: +- s = "control"; +- break; +- case USB_ENDPOINT_XFER_BULK: +- s = "bulk"; +- break; +- case USB_ENDPOINT_XFER_ISOC: +- s = "isoc"; +- break; +- default: +- s = "UNKNOWN"; +- } s; }), __entry->urb, __entry->pipe, __entry->slot_id, ++ __print_symbolic(__entry->type, ++ { USB_ENDPOINT_XFER_INT, "intr" }, ++ { USB_ENDPOINT_XFER_CONTROL, "control" }, ++ { USB_ENDPOINT_XFER_BULK, "bulk" }, ++ { USB_ENDPOINT_XFER_ISOC, "isoc" }), ++ __entry->urb, __entry->pipe, __entry->slot_id, + __entry->actual, __entry->length, __entry->num_mapped_sgs, + __entry->num_sgs, __entry->stream, __entry->flags + ) +-- +2.16.4 + diff --git a/patches.suse/0001-xhci-apply-XHCI_PME_STUCK_QUIRK-to-Intel-Comet-Lake-.patch b/patches.suse/0001-xhci-apply-XHCI_PME_STUCK_QUIRK-to-Intel-Comet-Lake-.patch new file mode 100644 index 0000000..36ddc7c --- /dev/null +++ b/patches.suse/0001-xhci-apply-XHCI_PME_STUCK_QUIRK-to-Intel-Comet-Lake-.patch @@ -0,0 +1,41 @@ +From a3ae87dce3a5abe0b57c811bab02b2564b574106 Mon Sep 17 00:00:00 2001 +From: Mathias Nyman +Date: Mon, 10 Feb 2020 15:45:53 +0200 +Subject: [PATCH] xhci: apply XHCI_PME_STUCK_QUIRK to Intel Comet Lake + platforms +Git-commit: a3ae87dce3a5abe0b57c811bab02b2564b574106 +References: git-fixes +Patch-mainline: v5.6-rc3 + +Intel Comet Lake based platform require the XHCI_PME_STUCK_QUIRK +quirk as well. Without this xHC can not enter D3 in runtime suspend. + +Cc: stable@vger.kernel.org +Signed-off-by: Mathias Nyman +Link: https://lore.kernel.org/r/20200210134553.9144-5-mathias.nyman@linux.intel.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Oliver Neukum +--- + drivers/usb/host/xhci-pci.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +--- a/drivers/usb/host/xhci-pci.c ++++ b/drivers/usb/host/xhci-pci.c +@@ -53,6 +53,7 @@ + #define PCI_DEVICE_ID_INTEL_BROXTON_B_XHCI 0x1aa8 + #define PCI_DEVICE_ID_INTEL_APL_XHCI 0x5aa8 + #define PCI_DEVICE_ID_INTEL_DNV_XHCI 0x19d0 ++#define PCI_DEVICE_ID_INTEL_CML_XHCI 0xa3af + + #define PCI_DEVICE_ID_AMD_PROMONTORYA_4 0x43b9 + #define PCI_DEVICE_ID_AMD_PROMONTORYA_3 0x43ba +@@ -191,7 +192,8 @@ static void xhci_pci_quirks(struct devic + pdev->device == PCI_DEVICE_ID_INTEL_BROXTON_M_XHCI || + pdev->device == PCI_DEVICE_ID_INTEL_BROXTON_B_XHCI || + pdev->device == PCI_DEVICE_ID_INTEL_APL_XHCI || +- pdev->device == PCI_DEVICE_ID_INTEL_DNV_XHCI)) { ++ pdev->device == PCI_DEVICE_ID_INTEL_DNV_XHCI || ++ pdev->device == PCI_DEVICE_ID_INTEL_CML_XHCI)) { + xhci->quirks |= XHCI_PME_STUCK_QUIRK; + } + if (pdev->vendor == PCI_VENDOR_ID_INTEL && diff --git a/patches.suse/0002-Btrfs-fix-btrfs_wait_ordered_range-so-that-it-waits-.patch b/patches.suse/0002-Btrfs-fix-btrfs_wait_ordered_range-so-that-it-waits-.patch new file mode 100644 index 0000000..3491aef --- /dev/null +++ b/patches.suse/0002-Btrfs-fix-btrfs_wait_ordered_range-so-that-it-waits-.patch @@ -0,0 +1,63 @@ +From b9cd174dedd6b9573ec0e21b9c949cd26af92e0c Mon Sep 17 00:00:00 2001 +From: Filipe Manana +Date: Thu, 13 Feb 2020 12:29:50 +0000 +Patch-mainline: v5.6-rc3 +Git-commit: e75fd33b3f744f644061a4f9662bd63f5434f806 +References: bsc#1163508 +Subject: [PATCH 2/2] Btrfs: fix btrfs_wait_ordered_range() so that it waits + for all ordered extents + +In btrfs_wait_ordered_range() once we find an ordered extent that has +finished with an error we exit the loop and don't wait for any other +ordered extents that might be still in progress. + +All the users of btrfs_wait_ordered_range() expect that there are no more +ordered extents in progress after that function returns. So past fixes +such like the ones from the two following commits: + + ff612ba7849964 ("btrfs: fix panic during relocation after ENOSPC before + writeback happens") + + 28aeeac1dd3080 ("Btrfs: fix panic when starting bg cache writeout after + IO error") + +don't work when there are multiple ordered extents in the range. + +Fix that by making btrfs_wait_ordered_range() wait for all ordered extents +even after it finds one that had an error. + +Link: https://github.com/kdave/btrfs-progs/issues/228#issuecomment-569777554 +CC: stable@vger.kernel.org # 4.4+ +Reviewed-by: Qu Wenruo +Reviewed-by: Josef Bacik +Signed-off-by: Filipe Manana +Signed-off-by: David Sterba +(cherry picked from commit e75fd33b3f744f644061a4f9662bd63f5434f806) +--- + fs/btrfs/ordered-data.c | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +diff --git a/fs/btrfs/ordered-data.c b/fs/btrfs/ordered-data.c +index 4f51e634f22d..4038fa4e2a87 100644 +--- a/fs/btrfs/ordered-data.c ++++ b/fs/btrfs/ordered-data.c +@@ -859,10 +859,15 @@ int btrfs_wait_ordered_range(struct inode *inode, u64 start, u64 len) + } + btrfs_start_ordered_extent(inode, ordered, 1); + end = ordered->file_offset; ++ /* ++ * If the ordered extent had an error save the error but don't ++ * exit without waiting first for all other ordered extents in ++ * the range to complete. ++ */ + if (test_bit(BTRFS_ORDERED_IOERR, &ordered->flags)) + ret = -EIO; + btrfs_put_ordered_extent(ordered); +- if (ret || end == 0 || end == start) ++ if (end == 0 || end == start) + break; + end--; + } +-- +2.16.4 + diff --git a/patches.suse/0002-Btrfs-remove-bio_flags-which-indicates-a-meta-block-.patch b/patches.suse/0002-Btrfs-remove-bio_flags-which-indicates-a-meta-block-.patch new file mode 100644 index 0000000..72bf73e --- /dev/null +++ b/patches.suse/0002-Btrfs-remove-bio_flags-which-indicates-a-meta-block-.patch @@ -0,0 +1,157 @@ +From 18fdc67900c5bfd1eeb41cfa50ea6f2eb7266f73 Mon Sep 17 00:00:00 2001 +From: Liu Bo +Date: Wed, 13 Sep 2017 12:18:22 -0600 +Patch-mainline: v4.15 +Git-commit: 18fdc67900c5bfd1eeb41cfa50ea6f2eb7266f73 +References: bsc#1168273 +Subject: [PATCH 2/2] Btrfs: remove bio_flags which indicates a meta block of + log-tree + +Since both committing transaction and writing log-tree are doing +plugging on metadata IO, we can unify to use %sync_writers to benefit +both cases, instead of checking bio_flags while writing meta blocks of +log-tree. + +We can remove this bio_flags because in order to write dirty blocks, +log tree also uses btrfs_write_marked_extents(), inside which we +have enabled %sync_writers, therefore, every write goes in a +synchronous way, so does checksuming. + +Please also note that, bio_flags is applied per-context while +%sync_writers is applied per-inode, so this might incur some overhead, ie. + +1) while log tree is flushing its dirty blocks via + btrfs_write_marked_extents(), in which %sync_writers is increased + by one. + +2) in the meantime, some writeback operations may happen upon btrfs's + metadata inode, so these writes go synchronously, too. + +However, AFAICS, the overhead is not a big one while the win is that +we unify the two places that needs synchronous way and remove a +special hack/flag. + +This removes the bio_flags related stuff for writing log-tree. + +Signed-off-by: Liu Bo +Reviewed-by: David Sterba +Signed-off-by: David Sterba +--- + fs/btrfs/disk-io.c | 6 ++---- + fs/btrfs/extent_io.c | 13 ++----------- + fs/btrfs/extent_io.h | 1 - + 3 files changed, 4 insertions(+), 16 deletions(-) + +--- a/fs/btrfs/disk-io.c ++++ b/fs/btrfs/disk-io.c +@@ -1003,12 +1003,10 @@ static blk_status_t __btree_submit_bio_d + return ret; + } + +-static int check_async_write(struct btrfs_inode *bi, unsigned long bio_flags) ++static int check_async_write(struct btrfs_inode *bi) + { + if (atomic_read(&bi->sync_writers)) + return 0; +- if (bio_flags & EXTENT_BIO_TREE_LOG) +- return 0; + #ifdef CONFIG_X86 + if (static_cpu_has(X86_FEATURE_XMM4_2)) + return 0; +@@ -1021,7 +1019,7 @@ static blk_status_t btree_submit_bio_hoo + u64 bio_offset) + { + struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb); +- int async = check_async_write(BTRFS_I(inode), bio_flags); ++ int async = check_async_write(BTRFS_I(inode)); + blk_status_t ret; + + if (bio_op(bio) != REQ_OP_WRITE) { +--- a/fs/btrfs/extent_io.c ++++ b/fs/btrfs/extent_io.c +@@ -119,7 +119,6 @@ struct extent_page_data { + struct bio *bio; + struct extent_io_tree *tree; + get_extent_t *get_extent; +- unsigned long bio_flags; + + /* tells writepage not to lock the state bits for this range + * it still does the unlocking +@@ -3758,7 +3757,6 @@ static noinline_for_stack int write_one_ + u64 offset = eb->start; + u32 nritems; + unsigned long i, num_pages; +- unsigned long bio_flags = 0; + unsigned long start, end; + int write_flags = (epd->sync_io ? REQ_SYNC : 0) | REQ_META; + int ret = 0; +@@ -3766,8 +3764,6 @@ static noinline_for_stack int write_one_ + clear_bit(EXTENT_BUFFER_WRITE_ERR, &eb->bflags); + num_pages = num_extent_pages(eb->start, eb->len); + atomic_set(&eb->io_pages, num_pages); +- if (btrfs_header_owner(eb) == BTRFS_TREE_LOG_OBJECTID) +- bio_flags = EXTENT_BIO_TREE_LOG; + + /* set btree blocks beyond nritems with 0 to avoid stale content. */ + nritems = btrfs_header_nritems(eb); +@@ -3794,8 +3790,7 @@ static noinline_for_stack int write_one_ + p, offset >> 9, PAGE_SIZE, 0, bdev, + &epd->bio, + end_bio_extent_buffer_writepage, +- 0, epd->bio_flags, bio_flags, false); +- epd->bio_flags = bio_flags; ++ 0, 0, 0, false); + if (ret) { + set_btree_ioerr(p); + if (PageWriteback(p)) +@@ -3832,7 +3827,6 @@ int btree_write_cache_pages(struct addre + .tree = tree, + .extent_locked = 0, + .sync_io = wbc->sync_mode == WB_SYNC_ALL, +- .bio_flags = 0, + }; + int ret = 0; + int done = 0; +@@ -4105,7 +4099,7 @@ static void flush_epd_write_bio(struct e + if (epd->bio) { + int ret; + +- ret = submit_one_bio(epd->bio, 0, epd->bio_flags); ++ ret = submit_one_bio(epd->bio, 0, 0); + BUG_ON(ret < 0); /* -ENOMEM */ + epd->bio = NULL; + } +@@ -4128,7 +4122,6 @@ int extent_write_full_page(struct extent + .get_extent = get_extent, + .extent_locked = 0, + .sync_io = wbc->sync_mode == WB_SYNC_ALL, +- .bio_flags = 0, + }; + + ret = __extent_writepage(page, wbc, &epd); +@@ -4153,7 +4146,6 @@ int extent_write_locked_range(struct ext + .get_extent = get_extent, + .extent_locked = 1, + .sync_io = mode == WB_SYNC_ALL, +- .bio_flags = 0, + }; + struct writeback_control wbc_writepages = { + .sync_mode = mode, +@@ -4193,7 +4185,6 @@ int extent_writepages(struct extent_io_t + .get_extent = get_extent, + .extent_locked = 0, + .sync_io = wbc->sync_mode == WB_SYNC_ALL, +- .bio_flags = 0, + }; + + ret = extent_write_cache_pages(mapping, wbc, __extent_writepage, &epd, +--- a/fs/btrfs/extent_io.h ++++ b/fs/btrfs/extent_io.h +@@ -33,7 +33,6 @@ + * type for this bio + */ + #define EXTENT_BIO_COMPRESSED 1 +-#define EXTENT_BIO_TREE_LOG 2 + #define EXTENT_BIO_FLAG_SHIFT 16 + + /* these are bit numbers for test/set bit */ diff --git a/patches.suse/0002-btrfs-Do-mandatory-tree-block-check-before-submittin.patch b/patches.suse/0002-btrfs-Do-mandatory-tree-block-check-before-submittin.patch new file mode 100644 index 0000000..c5a5144 --- /dev/null +++ b/patches.suse/0002-btrfs-Do-mandatory-tree-block-check-before-submittin.patch @@ -0,0 +1,95 @@ +From 8d47a0d8f7947422dd359ac8e462687f81a7a137 Mon Sep 17 00:00:00 2001 +From: Qu Wenruo +Date: Thu, 4 Apr 2019 11:47:08 +0800 +Patch-mainline: v5.2 +Git-commit: 8d47a0d8f7947422dd359ac8e462687f81a7a137 +References: bsc#1168273 +Subject: [PATCH 2/2] btrfs: Do mandatory tree block check before submitting + bio + +There are at least 2 reports about a memory bit flip sneaking into +on-disk data. + +Currently we only have a relaxed check triggered at +btrfs_mark_buffer_dirty() time, as it's not mandatory and only for +CONFIG_BTRFS_FS_CHECK_INTEGRITY enabled build, it doesn't help users to +detect such problem. + +This patch will address the hole by triggering comprehensive check on +tree blocks before writing it back to disk. + +The design points are: + +- Timing of the check: Tree block write hook + This timing is chosen to reduce the overhead. + The comprehensive check should be as expensive as a checksum + calculation. + Doing full check at btrfs_mark_buffer_dirty() is too expensive for end + user. + +- Loose empty leaf check + Originally for an empty leaf, tree-checker will report error if it's + not a tree root. + + The problem for such check at write time is: + * False alert for tree root created in current transaction + In that case, the commit root still needs to be written to disk. + And since current root can differ from commit root, then it will + cause false alert. + This happens for log tree. + + * False alert for relocated tree block + Relocated tree block can be written to disk due to memory pressure, + in that case an empty csum tree root can be written to disk and + cause false alert, since csum root node hasn't been updated. + + Previous patch of removing comprehensive empty leaf owner check has + paved the way for this patch. + +The example error output will be something like: + + BTRFS critical (device dm-3): corrupt leaf: root=2 block=1350630375424 slot=68, bad key order, prev (10510212874240 169 0) current (1714119868416 169 0) + BTRFS error (device dm-3): block=1350630375424 write time tree block corruption detected + BTRFS: error (device dm-3) in btrfs_commit_transaction:2220: errno=-5 IO failure (Error while writing out transaction) + BTRFS info (device dm-3): forced readonly + BTRFS warning (device dm-3): Skipping commit of aborted transaction. + BTRFS: error (device dm-3) in cleanup_transaction:1839: errno=-5 IO failure + BTRFS info (device dm-3): delayed_refs has NO entry + +Reported-by: Leonard Lausen +Signed-off-by: Qu Wenruo +Signed-off-by: David Sterba +--- + fs/btrfs/disk-io.c | 13 +++++++++++++ + 1 file changed, 13 insertions(+) + +--- a/fs/btrfs/disk-io.c ++++ b/fs/btrfs/disk-io.c +@@ -527,6 +527,7 @@ static int csum_dirty_buffer(struct btrf + u8 result[BTRFS_CSUM_SIZE]; + u16 csum_size = btrfs_super_csum_size(fs_info->super_copy); + struct extent_buffer *eb; ++ int ret; + + eb = (struct extent_buffer *)page->private; + if (page != eb->pages[0]) +@@ -548,7 +549,19 @@ static int csum_dirty_buffer(struct btrf + if (csum_tree_block(eb, result)) + return -EINVAL; + ++ if (btrfs_header_level(eb)) ++ ret = btrfs_check_node(fs_info, eb); ++ else ++ ret = btrfs_check_leaf_full(fs_info, eb); ++ ++ if (ret < 0) { ++ btrfs_err(fs_info, ++ "block=%llu write time tree block corruption detected", ++ eb->start); ++ return ret; ++ } + write_extent_buffer(eb, result, 0, csum_size); ++ + return 0; + } + diff --git a/patches.suse/0002-btrfs-Remove-fsid-metadata_fsid-fields-from-btrfs_in.patch b/patches.suse/0002-btrfs-Remove-fsid-metadata_fsid-fields-from-btrfs_in.patch index f820543..d4e492b 100644 --- a/patches.suse/0002-btrfs-Remove-fsid-metadata_fsid-fields-from-btrfs_in.patch +++ b/patches.suse/0002-btrfs-Remove-fsid-metadata_fsid-fields-from-btrfs_in.patch @@ -25,7 +25,7 @@ Signed-off-by: Nikolay Borisov --- a/fs/btrfs/check-integrity.c +++ b/fs/btrfs/check-integrity.c -@@ -1739,7 +1739,7 @@ static int btrfsic_test_for_metadata(str +@@ -1743,7 +1743,7 @@ static int btrfsic_test_for_metadata(str num_pages = state->metablock_size >> PAGE_SHIFT; h = (struct btrfs_header *)datav[0]; @@ -36,7 +36,7 @@ Signed-off-by: Nikolay Borisov for (i = 0; i < num_pages; i++) { --- a/fs/btrfs/ctree.c +++ b/fs/btrfs/ctree.c -@@ -25,6 +25,7 @@ +@@ -26,6 +26,7 @@ #include "print-tree.h" #include "locking.h" #include "qgroup.h" @@ -44,7 +44,7 @@ Signed-off-by: Nikolay Borisov static int split_node(struct btrfs_trans_handle *trans, struct btrfs_root *root, struct btrfs_path *path, int level); -@@ -275,7 +276,7 @@ int btrfs_copy_root(struct btrfs_trans_h +@@ -240,7 +241,7 @@ int btrfs_copy_root(struct btrfs_trans_h else btrfs_set_header_owner(cow, new_root_objectid); @@ -53,7 +53,7 @@ Signed-off-by: Nikolay Borisov WARN_ON(btrfs_header_generation(buf) > trans->transid); if (new_root_objectid == BTRFS_TREE_RELOC_OBJECTID) -@@ -1150,7 +1151,7 @@ static noinline int __btrfs_cow_block(st +@@ -1152,7 +1153,7 @@ static noinline int __btrfs_cow_block(st else btrfs_set_header_owner(cow, root->root_key.objectid); @@ -62,7 +62,7 @@ Signed-off-by: Nikolay Borisov ret = update_ref_for_cow(trans, root, buf, cow, &last_ref); if (ret) { -@@ -3392,7 +3393,7 @@ static noinline int insert_new_root(stru +@@ -3444,7 +3445,7 @@ static noinline int insert_new_root(stru btrfs_set_header_backref_rev(c, BTRFS_MIXED_BACKREF_REV); btrfs_set_header_owner(c, root->root_key.objectid); @@ -71,7 +71,7 @@ Signed-off-by: Nikolay Borisov write_extent_buffer_chunk_tree_uuid(c, fs_info->chunk_tree_uuid); btrfs_set_node_key(c, &lower_key, 0); -@@ -3527,7 +3528,7 @@ static noinline int split_node(struct bt +@@ -3579,7 +3580,7 @@ static noinline int split_node(struct bt btrfs_set_header_generation(split, trans->transid); btrfs_set_header_backref_rev(split, BTRFS_MIXED_BACKREF_REV); btrfs_set_header_owner(split, root->root_key.objectid); @@ -80,7 +80,7 @@ Signed-off-by: Nikolay Borisov write_extent_buffer_chunk_tree_uuid(split, fs_info->chunk_tree_uuid); ret = tree_mod_log_eb_copy(fs_info, split, c, 0, mid, c_nritems - mid); -@@ -4320,7 +4321,7 @@ again: +@@ -4372,7 +4373,7 @@ again: btrfs_set_header_backref_rev(right, BTRFS_MIXED_BACKREF_REV); btrfs_set_header_owner(right, root->root_key.objectid); btrfs_set_header_level(right, 0); @@ -91,8 +91,8 @@ Signed-off-by: Nikolay Borisov if (split == 0) { --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h -@@ -728,8 +728,6 @@ struct btrfs_delayed_root; - #define BTRFS_FS_BALANCE_RUNNING 18 +@@ -763,8 +763,6 @@ struct btrfs_delayed_root; + #define BTRFS_FS_CLEANER_RUNNING 19 struct btrfs_fs_info { - u8 fsid[BTRFS_FSID_SIZE]; @@ -102,7 +102,7 @@ Signed-off-by: Nikolay Borisov struct btrfs_root *extent_root; --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c -@@ -578,7 +578,7 @@ static int csum_dirty_buffer(struct btrf +@@ -542,7 +542,7 @@ static int csum_dirty_buffer(struct btrf if (WARN_ON(!PageUptodate(page))) return -EUCLEAN; @@ -110,8 +110,8 @@ Signed-off-by: Nikolay Borisov + ASSERT(memcmp_extent_buffer(eb, fs_info->fs_devices->metadata_uuid, btrfs_header_fsid(), BTRFS_FSID_SIZE) == 0); - return csum_tree_block(fs_info, eb, 0); -@@ -1506,7 +1506,7 @@ struct btrfs_root *btrfs_create_tree(str + if (csum_tree_block(eb, result)) +@@ -1350,7 +1350,7 @@ struct btrfs_root *btrfs_create_tree(str btrfs_set_header_owner(leaf, objectid); root->node = leaf; @@ -120,7 +120,7 @@ Signed-off-by: Nikolay Borisov write_extent_buffer_chunk_tree_uuid(leaf, fs_info->chunk_tree_uuid); btrfs_mark_buffer_dirty(leaf); -@@ -1587,7 +1587,7 @@ static struct btrfs_root *alloc_log_tree +@@ -1431,7 +1431,7 @@ static struct btrfs_root *alloc_log_tree btrfs_set_header_owner(leaf, BTRFS_TREE_LOG_OBJECTID); root->node = leaf; @@ -129,7 +129,7 @@ Signed-off-by: Nikolay Borisov btrfs_mark_buffer_dirty(root->node); btrfs_tree_unlock(root->node); return root; -@@ -2867,12 +2867,12 @@ int open_ctree(struct super_block *sb, +@@ -2710,12 +2710,12 @@ int open_ctree(struct super_block *sb, sizeof(*fs_info->super_for_commit)); brelse(bh); @@ -147,7 +147,7 @@ Signed-off-by: Nikolay Borisov } ret = btrfs_check_super_valid(fs_info); -@@ -2994,7 +2994,7 @@ int open_ctree(struct super_block *sb, +@@ -2839,7 +2839,7 @@ int open_ctree(struct super_block *sb, sb->s_blocksize = sectorsize; sb->s_blocksize_bits = blksize_bits(sectorsize); @@ -156,7 +156,7 @@ Signed-off-by: Nikolay Borisov mutex_lock(&fs_info->chunk_mutex); ret = btrfs_read_sys_array(fs_info); -@@ -4272,10 +4272,11 @@ static int btrfs_check_super_valid(struc +@@ -4125,10 +4125,11 @@ static int btrfs_check_super_valid(struc ret = -EINVAL; } @@ -172,7 +172,7 @@ Signed-off-by: Nikolay Borisov --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c -@@ -510,7 +510,7 @@ static noinline int create_subvol(struct +@@ -525,7 +525,7 @@ static noinline int create_subvol(struct btrfs_set_header_backref_rev(leaf, BTRFS_MIXED_BACKREF_REV); btrfs_set_header_owner(leaf, objectid); @@ -181,7 +181,7 @@ Signed-off-by: Nikolay Borisov write_extent_buffer_chunk_tree_uuid(leaf, fs_info->chunk_tree_uuid); btrfs_mark_buffer_dirty(leaf); -@@ -2794,7 +2794,8 @@ static long btrfs_ioctl_fs_info(struct b +@@ -2822,7 +2822,8 @@ static long btrfs_ioctl_fs_info(struct b mutex_lock(&fs_devices->device_list_mutex); fi_args->num_devices = fs_devices->num_devices; @@ -193,7 +193,7 @@ Signed-off-by: Nikolay Borisov if (device->devid > fi_args->max_id) --- a/fs/btrfs/super.c +++ b/fs/btrfs/super.c -@@ -2078,7 +2078,7 @@ static int btrfs_statfs(struct dentry *d +@@ -2088,7 +2088,7 @@ static int btrfs_statfs(struct dentry *d u64 total_free_data = 0; u64 total_free_meta = 0; int bits = dentry->d_sb->s_blocksize_bits; @@ -204,7 +204,7 @@ Signed-off-by: Nikolay Borisov int ret; --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c -@@ -173,14 +173,14 @@ static struct btrfs_fs_devices *__alloc_ +@@ -174,14 +174,14 @@ static struct btrfs_fs_devices *__alloc_ /** * alloc_fs_devices - allocate struct btrfs_fs_devices * @fsid: if not NULL, copy the uuid to fs_devices::fsid @@ -221,7 +221,7 @@ Signed-off-by: Nikolay Borisov { struct btrfs_fs_devices *fs_devs; -@@ -193,8 +193,8 @@ static struct btrfs_fs_devices *alloc_fs +@@ -194,8 +194,8 @@ static struct btrfs_fs_devices *alloc_fs else generate_random_uuid(fs_devs->fsid); @@ -232,7 +232,7 @@ Signed-off-by: Nikolay Borisov else memcpy(fs_devs->metadata_uuid, fs_devs->fsid, BTRFS_FSID_SIZE); -@@ -279,16 +279,16 @@ static noinline struct btrfs_device *__f +@@ -280,16 +280,16 @@ static noinline struct btrfs_device *__f } static noinline struct btrfs_fs_devices *find_fsid(u8 *fsid, @@ -252,7 +252,7 @@ Signed-off-by: Nikolay Borisov BTRFS_FSID_SIZE) == 0) return fs_devices; } else { -@@ -1750,7 +1750,8 @@ static int btrfs_add_device(struct btrfs +@@ -1780,7 +1780,8 @@ static int btrfs_add_device(struct btrfs ptr = btrfs_device_uuid(dev_item); write_extent_buffer(leaf, device->uuid, ptr, BTRFS_UUID_SIZE); ptr = btrfs_device_fsid(dev_item); @@ -262,7 +262,7 @@ Signed-off-by: Nikolay Borisov btrfs_mark_buffer_dirty(leaf); ret = 0; -@@ -2267,9 +2268,7 @@ static int btrfs_prepare_sprout(struct b +@@ -2293,9 +2294,7 @@ static int btrfs_prepare_sprout(struct b fs_devices->seed = seed_devices; generate_random_uuid(fs_devices->fsid); @@ -272,7 +272,7 @@ Signed-off-by: Nikolay Borisov memcpy(disk_super->fsid, fs_devices->fsid, BTRFS_FSID_SIZE); mutex_unlock(&fs_info->fs_devices->device_list_mutex); -@@ -2514,7 +2513,7 @@ int btrfs_init_new_device(struct btrfs_f +@@ -2540,7 +2539,7 @@ int btrfs_init_new_device(struct btrfs_f * so rename the fsid on the sysfs */ snprintf(fsid_buf, BTRFS_UUID_UNPARSED_SIZE, "%pU", @@ -281,7 +281,7 @@ Signed-off-by: Nikolay Borisov if (kobject_rename(&fs_info->fs_devices->fsid_kobj, fsid_buf)) btrfs_warn(fs_info, "sysfs: failed to create fsid for sprout"); -@@ -6735,7 +6734,8 @@ static int read_one_dev(struct btrfs_fs_ +@@ -6707,7 +6706,8 @@ static int read_one_dev(struct btrfs_fs_ read_extent_buffer(leaf, fs_uuid, btrfs_device_fsid(dev_item), BTRFS_UUID_SIZE); @@ -293,7 +293,7 @@ Signed-off-by: Nikolay Borisov return PTR_ERR(fs_devices); --- a/include/trace/events/btrfs.h +++ b/include/trace/events/btrfs.h -@@ -78,7 +78,7 @@ struct prelim_ref; +@@ -84,7 +84,7 @@ struct prelim_ref; #define TP_STRUCT__entry_fsid __array(u8, fsid, BTRFS_UUID_SIZE) #define TP_fast_assign_fsid(fs_info) \ @@ -302,7 +302,7 @@ Signed-off-by: Nikolay Borisov #define TP_STRUCT__entry_btrfs(args...) \ TP_STRUCT__entry( \ -@@ -628,7 +628,7 @@ TRACE_EVENT(btrfs_add_block_group, +@@ -634,7 +634,7 @@ TRACE_EVENT(btrfs_add_block_group, ), TP_fast_assign( @@ -311,7 +311,7 @@ Signed-off-by: Nikolay Borisov __entry->offset = block_group->key.objectid; __entry->size = block_group->key.offset; __entry->flags = block_group->flags; -@@ -983,7 +983,7 @@ TRACE_EVENT(btrfs_trigger_flush, +@@ -986,7 +986,7 @@ TRACE_EVENT(btrfs_trigger_flush, ), TP_fast_assign( @@ -320,7 +320,7 @@ Signed-off-by: Nikolay Borisov __entry->flags = flags; __entry->bytes = bytes; __entry->flush = flush; -@@ -1025,7 +1025,7 @@ TRACE_EVENT(btrfs_flush_space, +@@ -1028,7 +1028,7 @@ TRACE_EVENT(btrfs_flush_space, ), TP_fast_assign( @@ -328,4 +328,4 @@ Signed-off-by: Nikolay Borisov + memcpy(__entry->fsid, fs_info->fs_devices->fsid, BTRFS_UUID_SIZE); __entry->flags = flags; __entry->num_bytes = num_bytes; - __entry->orig_bytes = orig_bytes; + __entry->state = state; diff --git a/patches.suse/0002-btrfs-extent-tree-Open-code-process_func-in-__btrfs_.patch b/patches.suse/0002-btrfs-extent-tree-Open-code-process_func-in-__btrfs_.patch index b57a910..e4c0a27 100644 --- a/patches.suse/0002-btrfs-extent-tree-Open-code-process_func-in-__btrfs_.patch +++ b/patches.suse/0002-btrfs-extent-tree-Open-code-process_func-in-__btrfs_.patch @@ -20,23 +20,23 @@ Signed-off-by: Qu Wenruo Reviewed-by: David Sterba Signed-off-by: David Sterba --- - fs/btrfs/extent-tree.c | 30 ++++++++++++++++-------------- - 1 file changed, 16 insertions(+), 14 deletions(-) + fs/btrfs/extent-tree.c | 22 +++++++++++----------- + 1 file changed, 11 insertions(+), 11 deletions(-) --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c -@@ -3275,10 +3275,6 @@ static int __btrfs_mod_ref(struct btrfs_ +@@ -3346,10 +3346,6 @@ static int __btrfs_mod_ref(struct btrfs_ int i; int level; int ret = 0; - int (*process_func)(struct btrfs_trans_handle *, -- struct btrfs_fs_info *, +- struct btrfs_root *, - u64, u64, u64, u64, u64, u64); - if (btrfs_is_testing(fs_info)) return 0; -@@ -3290,11 +3286,6 @@ static int __btrfs_mod_ref(struct btrfs_ +@@ -3361,11 +3357,6 @@ static int __btrfs_mod_ref(struct btrfs_ if (!test_bit(BTRFS_ROOT_REF_COWS, &root->state) && level == 0) return 0; @@ -48,36 +48,30 @@ Signed-off-by: David Sterba if (full_backref) parent = buf->start; else -@@ -3316,16 +3307,27 @@ static int __btrfs_mod_ref(struct btrfs_ +@@ -3387,7 +3378,12 @@ static int __btrfs_mod_ref(struct btrfs_ num_bytes = btrfs_file_extent_disk_num_bytes(buf, fi); key.offset -= btrfs_file_extent_offset(buf, fi); -- ret = process_func(trans, fs_info, bytenr, num_bytes, -- parent, ref_root, key.objectid, -- key.offset); +- ret = process_func(trans, root, bytenr, num_bytes, + if (inc) -+ ret = btrfs_inc_extent_ref(trans, fs_info, bytenr, -+ num_bytes, parent, ref_root, -+ key.objectid, key.offset); ++ ret = btrfs_inc_extent_ref(trans, root, bytenr, num_bytes, ++ parent, ref_root, key.objectid, ++ key.offset); + else -+ ret = btrfs_free_extent(trans, fs_info, bytenr, -+ num_bytes, parent, ref_root, -+ key.objectid, key.offset); ++ ret = btrfs_free_extent(trans, root, bytenr, num_bytes, + parent, ref_root, key.objectid, + key.offset); if (ret) - goto fail; +@@ -3395,7 +3391,11 @@ static int __btrfs_mod_ref(struct btrfs_ } else { bytenr = btrfs_node_blockptr(buf, i); num_bytes = fs_info->nodesize; -- ret = process_func(trans, fs_info, bytenr, num_bytes, -- parent, ref_root, level - 1, 0); +- ret = process_func(trans, root, bytenr, num_bytes, + if (inc) -+ ret = btrfs_inc_extent_ref(trans, fs_info, bytenr, -+ num_bytes, parent, ref_root, -+ level - 1, 0); ++ ret = btrfs_inc_extent_ref(trans, root, bytenr, num_bytes, ++ parent, ref_root, level - 1, 0); + else -+ ret = btrfs_free_extent(trans, fs_info, bytenr, -+ num_bytes, parent, ref_root, -+ level - 1, 0); ++ ret = btrfs_free_extent(trans, root, bytenr, num_bytes, + parent, ref_root, level - 1, 0); if (ret) goto fail; - } diff --git a/patches.suse/0002-btrfs-extent_io-Handle-errors-better-in-extent_write.patch b/patches.suse/0002-btrfs-extent_io-Handle-errors-better-in-extent_write.patch new file mode 100644 index 0000000..9b43e40 --- /dev/null +++ b/patches.suse/0002-btrfs-extent_io-Handle-errors-better-in-extent_write.patch @@ -0,0 +1,93 @@ +From 3065976b045f77a910809fa7699f99a1e7c0dbbb Mon Sep 17 00:00:00 2001 +From: Qu Wenruo +Date: Wed, 20 Mar 2019 14:27:42 +0800 +Patch-mainline: v5.2 +Git-commit: 3065976b045f77a910809fa7699f99a1e7c0dbbb +References: bsc#1168273 +Subject: [PATCH 2/7] btrfs: extent_io: Handle errors better in + extent_write_full_page() + +Since now flush_write_bio() could return error, kill the BUG_ON() first. +Then don't call flush_write_bio() unconditionally, instead we check the +return value from __extent_writepage() first. + +If __extent_writepage() fails, we do cleanup, and return error without +submitting the possible corrupted or half-baked bio. + +If __extent_writepage() successes, then we call flush_write_bio() and +return the result. + +Signed-off-by: Qu Wenruo +Reviewed-by: David Sterba +Signed-off-by: David Sterba +--- + fs/btrfs/extent_io.c | 24 +++++++++++++++++++++--- + 1 file changed, 21 insertions(+), 3 deletions(-) + +diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c +index 43091b29b8d7..9d52f3b78732 100644 +--- a/fs/btrfs/extent_io.c ++++ b/fs/btrfs/extent_io.c +@@ -170,6 +170,16 @@ static int __must_check submit_one_bio(struct bio *bio, int mirror_num, + return blk_status_to_errno(ret); + } + ++/* Cleanup unsubmitted bios */ ++static void end_write_bio(struct extent_page_data *epd, int ret) ++{ ++ if (epd->bio) { ++ epd->bio->bi_status = errno_to_blk_status(ret); ++ bio_endio(epd->bio); ++ epd->bio = NULL; ++ } ++} ++ + /* + * Submit bio from extent page data via submit_one_bio + * +@@ -3397,6 +3407,9 @@ static noinline_for_stack int __extent_writepage_io(struct inode *inode, + * records are inserted to lock ranges in the tree, and as dirty areas + * are found, they are marked writeback. Then the lock bits are removed + * and the end_io handler clears the writeback ranges ++ * ++ * Return 0 if everything goes well. ++ * Return <0 for error. + */ + static int __extent_writepage(struct page *page, struct writeback_control *wbc, + struct extent_page_data *epd) +@@ -3466,6 +3479,7 @@ static int __extent_writepage(struct page *page, struct writeback_control *wbc, + end_extent_writepage(page, ret, start, page_end); + } + unlock_page(page); ++ ASSERT(ret <= 0); + return ret; + + done_unlocked: +@@ -4007,7 +4021,6 @@ static int extent_write_cache_pages(struct address_space *mapping, + int extent_write_full_page(struct page *page, struct writeback_control *wbc) + { + int ret; +- int flush_ret; + struct extent_page_data epd = { + .bio = NULL, + .tree = &BTRFS_I(page->mapping->host)->io_tree, +@@ -4016,9 +4029,14 @@ int extent_write_full_page(struct page *page, struct writeback_control *wbc) + }; + + ret = __extent_writepage(page, wbc, &epd); ++ ASSERT(ret <= 0); ++ if (ret < 0) { ++ end_write_bio(&epd, ret); ++ return ret; ++ } + +- flush_ret = flush_write_bio(&epd); +- BUG_ON(flush_ret < 0); ++ ret = flush_write_bio(&epd); ++ ASSERT(ret <= 0); + return ret; + } + +-- +2.26.0 + diff --git a/patches.suse/0002-btrfs-make-btrfs_destroy_delayed_refs-use-btrfs_delete_ref_head.patch b/patches.suse/0002-btrfs-make-btrfs_destroy_delayed_refs-use-btrfs_delete_ref_head.patch new file mode 100644 index 0000000..5267d23 --- /dev/null +++ b/patches.suse/0002-btrfs-make-btrfs_destroy_delayed_refs-use-btrfs_delete_ref_head.patch @@ -0,0 +1,34 @@ +From: Josef Bacik +Date: Wed, 21 Nov 2018 14:05:40 -0500 +Subject: btrfs: make btrfs_destroy_delayed_refs use btrfs_delete_ref_head +Git-commit: fa781cea3d6a2bd5f6c044cb06c608d7eeb6d787 +Patch-mainline: v5.1-rc1 +References: bsc#1165949 + +Instead of open coding this stuff use the helper instead. + +Reviewed-by: Nikolay Borisov +Signed-off-by: Josef Bacik +Reviewed-by: David Sterba +Signed-off-by: David Sterba +Acked-by: Nikolay Borisov +--- + fs/btrfs/disk-io.c | 7 +------ + 1 file changed, 1 insertion(+), 6 deletions(-) + +--- a/fs/btrfs/disk-io.c ++++ b/fs/btrfs/disk-io.c +@@ -4268,12 +4268,7 @@ static int btrfs_destroy_delayed_refs(st + if (head->must_insert_reserved) + pin_bytes = true; + btrfs_free_delayed_extent_op(head->extent_op); +- delayed_refs->num_heads--; +- if (head->processing == 0) +- delayed_refs->num_heads_ready--; +- atomic_dec(&delayed_refs->num_entries); +- rb_erase(&head->href_node, &delayed_refs->href_root); +- RB_CLEAR_NODE(&head->href_node); ++ btrfs_delete_ref_head(delayed_refs, head); + spin_unlock(&head->lock); + spin_unlock(&delayed_refs->lock); + mutex_unlock(&head->mutex); diff --git a/patches.suse/0002-btrfs-move-basic-block_group-definitions-to-their-own-header.patch b/patches.suse/0002-btrfs-move-basic-block_group-definitions-to-their-own-header.patch new file mode 100644 index 0000000..17d45ce --- /dev/null +++ b/patches.suse/0002-btrfs-move-basic-block_group-definitions-to-their-own-header.patch @@ -0,0 +1,592 @@ +From: Josef Bacik +Date: Thu, 20 Jun 2019 15:37:44 -0400 +Subject: btrfs: move basic block_group definitions to their own header +Git-commit: aac0023c2106952538414254960c51dcf0dc39e9 +Patch-mainline: v5.4-rc1 +References: bsc#1165949 + +This is prep work for moving all of the block group cache code into its +own file. + +Signed-off-by: Josef Bacik +Reviewed-by: David Sterba +[ minor comment updates ] +Signed-off-by: David Sterba +Acked-by: Nikolay Borisov +--- + fs/btrfs/block-group.h | 154 +++++++++++++++++++++++++++++++++ + fs/btrfs/ctree.h | 149 ------------------------------- + fs/btrfs/disk-io.c | 1 + fs/btrfs/extent-tree.c | 2 + fs/btrfs/free-space-cache.c | 1 + fs/btrfs/free-space-tree.c | 1 + fs/btrfs/free-space-tree.h | 2 + fs/btrfs/inode.c | 1 + fs/btrfs/ioctl.c | 1 + fs/btrfs/qgroup.c | 2 + fs/btrfs/reada.c | 1 + fs/btrfs/relocation.c | 1 + fs/btrfs/scrub.c | 1 + fs/btrfs/space-info.c | 1 + fs/btrfs/super.c | 1 + fs/btrfs/sysfs.c | 1 + fs/btrfs/tests/btrfs-tests.c | 2 + fs/btrfs/tests/free-space-tests.c | 1 + fs/btrfs/tests/free-space-tree-tests.c | 3 + fs/btrfs/transaction.c | 1 + fs/btrfs/volumes.c | 1 + 21 files changed, 176 insertions(+), 152 deletions(-) + +--- /dev/null ++++ b/fs/btrfs/block-group.h +@@ -0,0 +1,154 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++ ++#ifndef BTRFS_BLOCK_GROUP_H ++#define BTRFS_BLOCK_GROUP_H ++ ++enum btrfs_disk_cache_state { ++ BTRFS_DC_WRITTEN, ++ BTRFS_DC_ERROR, ++ BTRFS_DC_CLEAR, ++ BTRFS_DC_SETUP, ++}; ++ ++struct btrfs_caching_control { ++ struct list_head list; ++ struct mutex mutex; ++ wait_queue_head_t wait; ++ struct btrfs_work work; ++ struct btrfs_block_group_cache *block_group; ++ u64 progress; ++ refcount_t count; ++}; ++ ++/* Once caching_thread() finds this much free space, it will wake up waiters. */ ++#define CACHING_CTL_WAKE_UP SZ_2M ++ ++struct btrfs_block_group_cache { ++ struct btrfs_key key; ++ struct btrfs_block_group_item item; ++ struct btrfs_fs_info *fs_info; ++ struct inode *inode; ++ spinlock_t lock; ++ u64 pinned; ++ u64 reserved; ++ u64 delalloc_bytes; ++ u64 bytes_super; ++ u64 flags; ++ u64 cache_generation; ++ ++ /* ++ * If the free space extent count exceeds this number, convert the block ++ * group to bitmaps. ++ */ ++ u32 bitmap_high_thresh; ++ ++ /* ++ * If the free space extent count drops below this number, convert the ++ * block group back to extents. ++ */ ++ u32 bitmap_low_thresh; ++ ++ /* ++ * It is just used for the delayed data space allocation because ++ * only the data space allocation and the relative metadata update ++ * can be done cross the transaction. ++ */ ++ struct rw_semaphore data_rwsem; ++ ++ /* For raid56, this is a full stripe, without parity */ ++ unsigned long full_stripe_len; ++ ++ unsigned int ro; ++ unsigned int iref:1; ++ unsigned int has_caching_ctl:1; ++ unsigned int removed:1; ++ ++ int disk_cache_state; ++ ++ /* Cache tracking stuff */ ++ int cached; ++ struct btrfs_caching_control *caching_ctl; ++ u64 last_byte_to_unpin; ++ ++ struct btrfs_space_info *space_info; ++ ++ /* Free space cache stuff */ ++ struct btrfs_free_space_ctl *free_space_ctl; ++ ++ /* Block group cache stuff */ ++ struct rb_node cache_node; ++ ++ /* For block groups in the same raid type */ ++ struct list_head list; ++ ++ /* Usage count */ ++ atomic_t count; ++ ++ /* ++ * List of struct btrfs_free_clusters for this block group. ++ * Today it will only have one thing on it, but that may change ++ */ ++ struct list_head cluster_list; ++ ++ /* For delayed block group creation or deletion of empty block groups */ ++ struct list_head bg_list; ++ ++ /* For read-only block groups */ ++ struct list_head ro_list; ++ ++ atomic_t trimming; ++ ++ /* For dirty block groups */ ++ struct list_head dirty_list; ++ struct list_head io_list; ++ ++ struct btrfs_io_ctl io_ctl; ++ ++ /* ++ * Incremented when doing extent allocations and holding a read lock ++ * on the space_info's groups_sem semaphore. ++ * Decremented when an ordered extent that represents an IO against this ++ * block group's range is created (after it's added to its inode's ++ * root's list of ordered extents) or immediately after the allocation ++ * if it's a metadata extent or fallocate extent (for these cases we ++ * don't create ordered extents). ++ */ ++ atomic_t reservations; ++ ++ /* ++ * Incremented while holding the spinlock *lock* by a task checking if ++ * it can perform a nocow write (incremented if the value for the *ro* ++ * field is 0). Decremented by such tasks once they create an ordered ++ * extent or before that if some error happens before reaching that step. ++ * This is to prevent races between block group relocation and nocow ++ * writes through direct IO. ++ */ ++ atomic_t nocow_writers; ++ ++ /* Lock for free space tree operations. */ ++ struct mutex free_space_lock; ++ ++ /* ++ * Does the block group need to be added to the free space tree? ++ * Protected by free_space_lock. ++ */ ++ int needs_free_space; ++ ++ /* Record locked full stripes for RAID5/6 block group */ ++ struct btrfs_full_stripe_locks_tree full_stripe_locks_root; ++}; ++ ++#ifdef CONFIG_BTRFS_DEBUG ++static inline int btrfs_should_fragment_free_space( ++ struct btrfs_block_group_cache *block_group) ++{ ++ struct btrfs_fs_info *fs_info = block_group->fs_info; ++ ++ return (btrfs_test_opt(fs_info, FRAGMENT_METADATA) && ++ block_group->flags & BTRFS_BLOCK_GROUP_METADATA) || ++ (btrfs_test_opt(fs_info, FRAGMENT_DATA) && ++ block_group->flags & BTRFS_BLOCK_GROUP_DATA); ++} ++#endif ++ ++#endif /* BTRFS_BLOCK_GROUP_H */ +--- a/fs/btrfs/ctree.h ++++ b/fs/btrfs/ctree.h +@@ -50,6 +50,7 @@ struct btrfs_transaction; + struct btrfs_pending_snapshot; + struct btrfs_delayed_ref_root; + struct btrfs_space_info; ++struct btrfs_block_group_cache; + extern struct kmem_cache *btrfs_trans_handle_cachep; + extern struct kmem_cache *btrfs_transaction_cachep; + extern struct kmem_cache *btrfs_bit_radix_cachep; +@@ -426,26 +427,6 @@ enum btrfs_caching_type { + BTRFS_CACHE_ERROR = 4, + }; + +-enum btrfs_disk_cache_state { +- BTRFS_DC_WRITTEN = 0, +- BTRFS_DC_ERROR = 1, +- BTRFS_DC_CLEAR = 2, +- BTRFS_DC_SETUP = 3, +-}; +- +-struct btrfs_caching_control { +- struct list_head list; +- struct mutex mutex; +- wait_queue_head_t wait; +- struct btrfs_work work; +- struct btrfs_block_group_cache *block_group; +- u64 progress; +- refcount_t count; +-}; +- +-/* Once caching_thread() finds this much free space, it will wake up waiters. */ +-#define CACHING_CTL_WAKE_UP (1024 * 1024 * 2) +- + struct btrfs_io_ctl { + void *cur, *orig; + struct page *page; +@@ -468,121 +449,6 @@ struct btrfs_full_stripe_locks_tree { + struct mutex lock; + }; + +-struct btrfs_block_group_cache { +- struct btrfs_key key; +- struct btrfs_block_group_item item; +- struct btrfs_fs_info *fs_info; +- struct inode *inode; +- spinlock_t lock; +- u64 pinned; +- u64 reserved; +- u64 delalloc_bytes; +- u64 bytes_super; +- u64 flags; +- u64 cache_generation; +- u32 sectorsize; +- +- /* +- * If the free space extent count exceeds this number, convert the block +- * group to bitmaps. +- */ +- u32 bitmap_high_thresh; +- +- /* +- * If the free space extent count drops below this number, convert the +- * block group back to extents. +- */ +- u32 bitmap_low_thresh; +- +- /* +- * It is just used for the delayed data space allocation because +- * only the data space allocation and the relative metadata update +- * can be done cross the transaction. +- */ +- struct rw_semaphore data_rwsem; +- +- /* for raid56, this is a full stripe, without parity */ +- unsigned long full_stripe_len; +- +- unsigned int ro; +- unsigned int iref:1; +- unsigned int has_caching_ctl:1; +- unsigned int removed:1; +- +- int disk_cache_state; +- +- /* cache tracking stuff */ +- int cached; +- struct btrfs_caching_control *caching_ctl; +- u64 last_byte_to_unpin; +- +- struct btrfs_space_info *space_info; +- +- /* free space cache stuff */ +- struct btrfs_free_space_ctl *free_space_ctl; +- +- /* block group cache stuff */ +- struct rb_node cache_node; +- +- /* for block groups in the same raid type */ +- struct list_head list; +- +- /* usage count */ +- atomic_t count; +- +- /* List of struct btrfs_free_clusters for this block group. +- * Today it will only have one thing on it, but that may change +- */ +- struct list_head cluster_list; +- +- /* For delayed block group creation or deletion of empty block groups */ +- struct list_head bg_list; +- +- /* For read-only block groups */ +- struct list_head ro_list; +- +- atomic_t trimming; +- +- /* For dirty block groups */ +- struct list_head dirty_list; +- struct list_head io_list; +- +- struct btrfs_io_ctl io_ctl; +- +- /* +- * Incremented when doing extent allocations and holding a read lock +- * on the space_info's groups_sem semaphore. +- * Decremented when an ordered extent that represents an IO against this +- * block group's range is created (after it's added to its inode's +- * root's list of ordered extents) or immediately after the allocation +- * if it's a metadata extent or fallocate extent (for these cases we +- * don't create ordered extents). +- */ +- atomic_t reservations; +- +- /* +- * Incremented while holding the spinlock *lock* by a task checking if +- * it can perform a nocow write (incremented if the value for the *ro* +- * field is 0). Decremented by such tasks once they create an ordered +- * extent or before that if some error happens before reaching that step. +- * This is to prevent races between block group relocation and nocow +- * writes through direct IO. +- */ +- atomic_t nocow_writers; +- +- /* Lock for free space tree operations. */ +- struct mutex free_space_lock; +- +- /* +- * Does the block group need to be added to the free space tree? +- * Protected by free_space_lock. +- */ +- int needs_free_space; +- +- /* Record locked full stripes for RAID5/6 block group */ +- struct btrfs_full_stripe_locks_tree full_stripe_locks_root; +-}; +- + /* delayed seq elem */ + struct seq_list { + struct list_head list; +@@ -1356,19 +1222,6 @@ static inline u32 BTRFS_MAX_XATTR_SIZE(c + btrfs_clear_opt(fs_info->mount_opt, opt); \ + } + +-#ifdef CONFIG_BTRFS_DEBUG +-static inline int +-btrfs_should_fragment_free_space(struct btrfs_block_group_cache *block_group) +-{ +- struct btrfs_fs_info *fs_info = block_group->fs_info; +- +- return (btrfs_test_opt(fs_info, FRAGMENT_METADATA) && +- block_group->flags & BTRFS_BLOCK_GROUP_METADATA) || +- (btrfs_test_opt(fs_info, FRAGMENT_DATA) && +- block_group->flags & BTRFS_BLOCK_GROUP_DATA); +-} +-#endif +- + /* + * Requests for changes that need to be done during transaction commit. + * +--- a/fs/btrfs/disk-io.c ++++ b/fs/btrfs/disk-io.c +@@ -52,6 +52,7 @@ + #include "compression.h" + #include "tree-checker.h" + #include "space-info.h" ++#include "block-group.h" + + #ifdef CONFIG_X86 + #include +--- a/fs/btrfs/extent-tree.c ++++ b/fs/btrfs/extent-tree.c +@@ -42,6 +42,7 @@ + #include "space-info.h" + #include "block-rsv.h" + #include "delalloc-space.h" ++#include "block-group.h" + + #undef SCRAMBLE_DELAYED_REFS + +@@ -8084,7 +8085,6 @@ btrfs_create_block_group_cache(struct bt + cache->key.offset = size; + cache->key.type = BTRFS_BLOCK_GROUP_ITEM_KEY; + +- cache->sectorsize = fs_info->sectorsize; + cache->fs_info = fs_info; + cache->full_stripe_len = btrfs_full_stripe_len(fs_info, + &fs_info->mapping_tree, +--- a/fs/btrfs/free-space-cache.c ++++ b/fs/btrfs/free-space-cache.c +@@ -32,6 +32,7 @@ + #include "volumes.h" + #include "space-info.h" + #include "delalloc-space.h" ++#include "block-group.h" + + #define BITS_PER_BITMAP (PAGE_SIZE * 8UL) + #define MAX_CACHE_BYTES_PER_GIG SZ_32K +--- a/fs/btrfs/free-space-tree.c ++++ b/fs/btrfs/free-space-tree.c +@@ -23,6 +23,7 @@ + #include "locking.h" + #include "free-space-tree.h" + #include "transaction.h" ++#include "block-group.h" + + static int __add_block_group_free_space(struct btrfs_trans_handle *trans, + struct btrfs_fs_info *fs_info, +--- a/fs/btrfs/free-space-tree.h ++++ b/fs/btrfs/free-space-tree.h +@@ -19,6 +19,8 @@ + #ifndef __BTRFS_FREE_SPACE_TREE + #define __BTRFS_FREE_SPACE_TREE + ++struct btrfs_caching_control; ++ + /* + * The default size for new free space bitmap items. The last bitmap in a block + * group may be truncated, and none of the free space tree code assumes that +--- a/fs/btrfs/inode.c ++++ b/fs/btrfs/inode.c +@@ -63,6 +63,7 @@ + #include "qgroup.h" + #include "dedupe.h" + #include "delalloc-space.h" ++#include "block-group.h" + + struct btrfs_iget_args { + struct btrfs_key *location; +--- a/fs/btrfs/ioctl.c ++++ b/fs/btrfs/ioctl.c +@@ -63,6 +63,7 @@ + #include "compression.h" + #include "space-info.h" + #include "delalloc-space.h" ++#include "block-group.h" + + #ifdef CONFIG_64BIT + /* If we have a 32-bit userspace and 64-bit kernel, then the UAPI +--- a/fs/btrfs/qgroup.c ++++ b/fs/btrfs/qgroup.c +@@ -34,7 +34,7 @@ + #include "backref.h" + #include "extent_io.h" + #include "qgroup.h" +- ++#include "block-group.h" + + /* TODO XXX FIXME + * - subvol delete -> delete when ref goes to 0? delete limits also? +--- a/fs/btrfs/reada.c ++++ b/fs/btrfs/reada.c +@@ -28,6 +28,7 @@ + #include "disk-io.h" + #include "transaction.h" + #include "dev-replace.h" ++#include "block-group.h" + + #undef DEBUG + +--- a/fs/btrfs/relocation.c ++++ b/fs/btrfs/relocation.c +@@ -34,6 +34,7 @@ + #include "qgroup.h" + #include "print-tree.h" + #include "delalloc-space.h" ++#include "block-group.h" + + /* + * backref_node, mapping_node and tree_block start with this +--- a/fs/btrfs/scrub.c ++++ b/fs/btrfs/scrub.c +@@ -30,6 +30,7 @@ + #include "check-integrity.h" + #include "rcu-string.h" + #include "raid56.h" ++#include "block-group.h" + + /* + * This is only the first step towards a full-features scrub. It reads all +--- a/fs/btrfs/space-info.c ++++ b/fs/btrfs/space-info.c +@@ -8,6 +8,7 @@ + #include "ordered-data.h" + #include "transaction.h" + #include "math.h" ++#include "block-group.h" + + u64 btrfs_space_info_used(struct btrfs_space_info *s_info, + bool may_use_included) +--- a/fs/btrfs/super.c ++++ b/fs/btrfs/super.c +@@ -60,6 +60,7 @@ + #include "backref.h" + #include "space-info.h" + #include "tests/btrfs-tests.h" ++#include "block-group.h" + + #include "qgroup.h" + #include "backref.h" +--- a/fs/btrfs/sysfs.c ++++ b/fs/btrfs/sysfs.c +@@ -32,6 +32,7 @@ + #include "sysfs.h" + #include "volumes.h" + #include "space-info.h" ++#include "block-group.h" + + static inline struct btrfs_fs_info *to_fs_info(struct kobject *kobj); + static inline struct btrfs_fs_devices *to_fs_devs(struct kobject *kobj); +--- a/fs/btrfs/tests/btrfs-tests.c ++++ b/fs/btrfs/tests/btrfs-tests.c +@@ -27,6 +27,7 @@ + #include "../volumes.h" + #include "../disk-io.h" + #include "../qgroup.h" ++#include "../block-group.h" + + static struct vfsmount *test_mnt = NULL; + +@@ -211,7 +212,6 @@ btrfs_alloc_dummy_block_group(struct btr + cache->key.objectid = 0; + cache->key.offset = length; + cache->key.type = BTRFS_BLOCK_GROUP_ITEM_KEY; +- cache->sectorsize = fs_info->sectorsize; + cache->full_stripe_len = fs_info->sectorsize; + cache->fs_info = fs_info; + +--- a/fs/btrfs/tests/free-space-tests.c ++++ b/fs/btrfs/tests/free-space-tests.c +@@ -21,6 +21,7 @@ + #include "../ctree.h" + #include "../disk-io.h" + #include "../free-space-cache.h" ++#include "../block-group.h" + + #define BITS_PER_BITMAP (PAGE_SIZE * 8UL) + +--- a/fs/btrfs/tests/free-space-tree-tests.c ++++ b/fs/btrfs/tests/free-space-tree-tests.c +@@ -22,6 +22,7 @@ + #include "../disk-io.h" + #include "../free-space-tree.h" + #include "../transaction.h" ++#include "../block-group.h" + + struct free_space_extent { + u64 start; +@@ -81,7 +82,7 @@ static int __check_free_space_extents(st + i++; + } + prev_bit = bit; +- offset += cache->sectorsize; ++ offset += fs_info->sectorsize; + } + } + if (prev_bit == 1) { +--- a/fs/btrfs/transaction.c ++++ b/fs/btrfs/transaction.c +@@ -32,6 +32,7 @@ + #include "volumes.h" + #include "dev-replace.h" + #include "qgroup.h" ++#include "block-group.h" + + #define BTRFS_ROOT_TRANS_TAG 0 + +--- a/fs/btrfs/volumes.c ++++ b/fs/btrfs/volumes.c +@@ -43,6 +43,7 @@ + #include "sysfs.h" + #include "tree-checker.h" + #include "space-info.h" ++#include "block-group.h" + + const struct btrfs_raid_attr btrfs_raid_array[BTRFS_NR_RAID_TYPES] = { + [BTRFS_RAID_RAID10] = { diff --git a/patches.suse/0002-btrfs-move-space_info-to-space-info-h.patch b/patches.suse/0002-btrfs-move-space_info-to-space-info-h.patch new file mode 100644 index 0000000..e9bf6d1 --- /dev/null +++ b/patches.suse/0002-btrfs-move-space_info-to-space-info-h.patch @@ -0,0 +1,272 @@ +From: Josef Bacik +Date: Tue, 18 Jun 2019 16:09:16 -0400 +Subject: btrfs: move space_info to space-info.h +Git-commit: 8719aaae8d696bf0c73f74e6d6cc75451b50d5df +Patch-mainline: v5.3-rc1 +References: bsc#1165949 + +Migrate the struct definition and the one helper that's in ctree.h into +space-info.h + +Reviewed-by: Nikolay Borisov +Signed-off-by: Josef Bacik +Signed-off-by: David Sterba +Acked-by: Nikolay Borisov +--- + fs/btrfs/ctree.h | 73 ----------------------------------------- + fs/btrfs/disk-io.c | 1 + fs/btrfs/extent-tree.c | 1 + fs/btrfs/free-space-cache.c | 1 + fs/btrfs/ioctl.c | 1 + fs/btrfs/space-info.h | 77 ++++++++++++++++++++++++++++++++++++++++++++ + fs/btrfs/super.c | 1 + fs/btrfs/sysfs.c | 1 + fs/btrfs/volumes.c | 1 + 9 files changed, 85 insertions(+), 72 deletions(-) + +--- a/fs/btrfs/ctree.h ++++ b/fs/btrfs/ctree.h +@@ -48,6 +48,7 @@ struct btrfs_trans_handle; + struct btrfs_transaction; + struct btrfs_pending_snapshot; + struct btrfs_delayed_ref_root; ++struct btrfs_space_info; + extern struct kmem_cache *btrfs_trans_handle_cachep; + extern struct kmem_cache *btrfs_transaction_cachep; + extern struct kmem_cache *btrfs_bit_radix_cachep; +@@ -388,72 +389,6 @@ struct raid_kobject { + struct list_head list; + }; + +-struct btrfs_space_info { +- spinlock_t lock; +- +- u64 total_bytes; /* total bytes in the space, +- this doesn't take mirrors into account */ +- u64 bytes_used; /* total bytes used, +- this doesn't take mirrors into account */ +- u64 bytes_pinned; /* total bytes pinned, will be freed when the +- transaction finishes */ +- u64 bytes_reserved; /* total bytes the allocator has reserved for +- current allocations */ +- u64 bytes_may_use; /* number of bytes that may be used for +- delalloc/allocations */ +- u64 bytes_readonly; /* total bytes that are read only */ +- +- u64 max_extent_size; /* This will hold the maximum extent size of +- the space info if we had an ENOSPC in the +- allocator. */ +- +- unsigned int full:1; /* indicates that we cannot allocate any more +- chunks for this space */ +- unsigned int chunk_alloc:1; /* set if we are allocating a chunk */ +- +- unsigned int flush:1; /* set if we are trying to make space */ +- +- unsigned int force_alloc; /* set if we need to force a chunk +- alloc for this space */ +- +- u64 disk_used; /* total bytes used on disk */ +- u64 disk_total; /* total bytes on disk, takes mirrors into +- account */ +- +- u64 flags; +- +- /* +- * bytes_pinned is kept in line with what is actually pinned, as in +- * we've called update_block_group and dropped the bytes_used counter +- * and increased the bytes_pinned counter. However this means that +- * bytes_pinned does not reflect the bytes that will be pinned once the +- * delayed refs are flushed, so this counter is inc'ed every time we +- * call btrfs_free_extent so it is a realtime count of what will be +- * freed once the transaction is committed. It will be zeroed every +- * time the transaction commits. +- */ +- struct percpu_counter total_bytes_pinned; +- +- struct list_head list; +- /* Protected by the spinlock 'lock'. */ +- struct list_head ro_bgs; +- struct list_head priority_tickets; +- struct list_head tickets; +- /* +- * tickets_id just indicates the next ticket will be handled, so note +- * it's not stored per ticket. +- */ +- u64 tickets_id; +- +- struct rw_semaphore groups_sem; +- /* for block groups in our same type */ +- struct list_head block_groups[BTRFS_NR_RAID_TYPES]; +- wait_queue_head_t wait; +- +- struct kobject kobj; +- struct kobject *block_group_kobjs[BTRFS_NR_RAID_TYPES]; +-}; +- + #define BTRFS_BLOCK_RSV_GLOBAL 1 + #define BTRFS_BLOCK_RSV_DELALLOC 2 + #define BTRFS_BLOCK_RSV_TRANS 3 +@@ -2668,12 +2603,6 @@ BTRFS_SETGET_STACK_FUNCS(stack_dev_repla + ((unsigned long)(btrfs_leaf_data(leaf) + \ + btrfs_item_offset_nr(leaf, slot))) + +-static inline bool btrfs_mixed_space_info(struct btrfs_space_info *space_info) +-{ +- return ((space_info->flags & BTRFS_BLOCK_GROUP_METADATA) && +- (space_info->flags & BTRFS_BLOCK_GROUP_DATA)); +-} +- + static inline gfp_t btrfs_alloc_write_mask(struct address_space *mapping) + { + return mapping_gfp_constraint(mapping, ~__GFP_FS); +--- a/fs/btrfs/disk-io.c ++++ b/fs/btrfs/disk-io.c +@@ -51,6 +51,7 @@ + #include "qgroup.h" + #include "compression.h" + #include "tree-checker.h" ++#include "space-info.h" + + #ifdef CONFIG_X86 + #include +--- a/fs/btrfs/extent-tree.c ++++ b/fs/btrfs/extent-tree.c +@@ -39,6 +39,7 @@ + #include "math.h" + #include "sysfs.h" + #include "qgroup.h" ++#include "space-info.h" + + #undef SCRAMBLE_DELAYED_REFS + +--- a/fs/btrfs/free-space-cache.c ++++ b/fs/btrfs/free-space-cache.c +@@ -30,6 +30,7 @@ + #include "extent_io.h" + #include "inode-map.h" + #include "volumes.h" ++#include "space-info.h" + + #define BITS_PER_BITMAP (PAGE_SIZE * 8UL) + #define MAX_CACHE_BYTES_PER_GIG SZ_32K +--- a/fs/btrfs/ioctl.c ++++ b/fs/btrfs/ioctl.c +@@ -61,6 +61,7 @@ + #include "qgroup.h" + #include "tree-log.h" + #include "compression.h" ++#include "space-info.h" + + #ifdef CONFIG_64BIT + /* If we have a 32-bit userspace and 64-bit kernel, then the UAPI +--- /dev/null ++++ b/fs/btrfs/space-info.h +@@ -0,0 +1,77 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++ ++#ifndef BTRFS_SPACE_INFO_H ++#define BTRFS_SPACE_INFO_H ++ ++struct btrfs_space_info { ++ spinlock_t lock; ++ ++ u64 total_bytes; /* total bytes in the space, ++ this doesn't take mirrors into account */ ++ u64 bytes_used; /* total bytes used, ++ this doesn't take mirrors into account */ ++ u64 bytes_pinned; /* total bytes pinned, will be freed when the ++ transaction finishes */ ++ u64 bytes_reserved; /* total bytes the allocator has reserved for ++ current allocations */ ++ u64 bytes_may_use; /* number of bytes that may be used for ++ delalloc/allocations */ ++ u64 bytes_readonly; /* total bytes that are read only */ ++ ++ u64 max_extent_size; /* This will hold the maximum extent size of ++ the space info if we had an ENOSPC in the ++ allocator. */ ++ ++ unsigned int full:1; /* indicates that we cannot allocate any more ++ chunks for this space */ ++ unsigned int chunk_alloc:1; /* set if we are allocating a chunk */ ++ ++ unsigned int flush:1; /* set if we are trying to make space */ ++ ++ unsigned int force_alloc; /* set if we need to force a chunk ++ alloc for this space */ ++ ++ u64 disk_used; /* total bytes used on disk */ ++ u64 disk_total; /* total bytes on disk, takes mirrors into ++ account */ ++ ++ u64 flags; ++ ++ /* ++ * bytes_pinned is kept in line with what is actually pinned, as in ++ * we've called update_block_group and dropped the bytes_used counter ++ * and increased the bytes_pinned counter. However this means that ++ * bytes_pinned does not reflect the bytes that will be pinned once the ++ * delayed refs are flushed, so this counter is inc'ed every time we ++ * call btrfs_free_extent so it is a realtime count of what will be ++ * freed once the transaction is committed. It will be zeroed every ++ * time the transaction commits. ++ */ ++ struct percpu_counter total_bytes_pinned; ++ ++ struct list_head list; ++ /* Protected by the spinlock 'lock'. */ ++ struct list_head ro_bgs; ++ struct list_head priority_tickets; ++ struct list_head tickets; ++ /* ++ * tickets_id just indicates the next ticket will be handled, so note ++ * it's not stored per ticket. ++ */ ++ u64 tickets_id; ++ ++ struct rw_semaphore groups_sem; ++ /* for block groups in our same type */ ++ struct list_head block_groups[BTRFS_NR_RAID_TYPES]; ++ wait_queue_head_t wait; ++ ++ struct kobject kobj; ++ struct kobject *block_group_kobjs[BTRFS_NR_RAID_TYPES]; ++}; ++static inline bool btrfs_mixed_space_info(struct btrfs_space_info *space_info) ++{ ++ return ((space_info->flags & BTRFS_BLOCK_GROUP_METADATA) && ++ (space_info->flags & BTRFS_BLOCK_GROUP_DATA)); ++} ++ ++#endif /* BTRFS_SPACE_INFO_H */ +--- a/fs/btrfs/super.c ++++ b/fs/btrfs/super.c +@@ -58,6 +58,7 @@ + #include "dev-replace.h" + #include "free-space-cache.h" + #include "backref.h" ++#include "space-info.h" + #include "tests/btrfs-tests.h" + + #include "qgroup.h" +--- a/fs/btrfs/sysfs.c ++++ b/fs/btrfs/sysfs.c +@@ -31,6 +31,7 @@ + #include "transaction.h" + #include "sysfs.h" + #include "volumes.h" ++#include "space-info.h" + + static inline struct btrfs_fs_info *to_fs_info(struct kobject *kobj); + static inline struct btrfs_fs_devices *to_fs_devs(struct kobject *kobj); +--- a/fs/btrfs/volumes.c ++++ b/fs/btrfs/volumes.c +@@ -42,6 +42,7 @@ + #include "dev-replace.h" + #include "sysfs.h" + #include "tree-checker.h" ++#include "space-info.h" + + const struct btrfs_raid_attr btrfs_raid_array[BTRFS_NR_RAID_TYPES] = { + [BTRFS_RAID_RAID10] = { diff --git a/patches.suse/0002-btrfs-release-metadata-before-running-delayed-refs.patch b/patches.suse/0002-btrfs-release-metadata-before-running-delayed-refs.patch new file mode 100644 index 0000000..278f47a --- /dev/null +++ b/patches.suse/0002-btrfs-release-metadata-before-running-delayed-refs.patch @@ -0,0 +1,44 @@ +From: Josef Bacik +Date: Fri, 28 Sep 2018 07:17:48 -0400 +Subject: btrfs: release metadata before running delayed refs +Git-commit: f45c752b65af46bf42963295c332865d95f97fff +Patch-mainline: v4.20-rc1 +References: bsc##1165949 + +We want to release the unused reservation we have since it refills the +delayed refs reserve, which will make everything go smoother when +running the delayed refs if we're short on our reservation. + +CC: stable@vger.kernel.org # 4.4+ +Reviewed-by: Omar Sandoval +Reviewed-by: Liu Bo +Reviewed-by: Nikolay Borisov +Signed-off-by: Josef Bacik +Signed-off-by: David Sterba +Acked-by: Nikolay Borisov +--- + fs/btrfs/transaction.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +--- a/fs/btrfs/transaction.c ++++ b/fs/btrfs/transaction.c +@@ -1962,6 +1962,9 @@ int btrfs_commit_transaction(struct btrf + return ret; + } + ++ btrfs_trans_release_metadata(trans, fs_info); ++ trans->block_rsv = NULL; ++ + /* make a pass through all the delayed refs we have so far + * any runnings procs may add more while we are here + */ +@@ -1971,9 +1974,6 @@ int btrfs_commit_transaction(struct btrf + return ret; + } + +- btrfs_trans_release_metadata(trans, fs_info); +- trans->block_rsv = NULL; +- + cur_trans = trans->transaction; + + /* diff --git a/patches.suse/0002-btrfs-save-drop_progress-if-we-drop-refs-at-all.patch b/patches.suse/0002-btrfs-save-drop_progress-if-we-drop-refs-at-all.patch index 325a473..a2c5d91 100644 --- a/patches.suse/0002-btrfs-save-drop_progress-if-we-drop-refs-at-all.patch +++ b/patches.suse/0002-btrfs-save-drop_progress-if-we-drop-refs-at-all.patch @@ -94,14 +94,12 @@ Signed-off-by: Josef Bacik Signed-off-by: David Sterba Signed-off-by: Filipe Manana --- - fs/btrfs/extent-tree.c | 26 ++++++++++++++++++++------ - 1 file changed, 20 insertions(+), 6 deletions(-) + fs/btrfs/extent-tree.c | 25 +++++++++++++++++++------ + 1 file changed, 19 insertions(+), 6 deletions(-) -diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c -index ef15a19765c1..25e423b0aa9f 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c -@@ -8442,6 +8442,8 @@ struct walk_control { +@@ -8503,6 +8503,8 @@ struct walk_control { u64 refs[BTRFS_MAX_LEVEL]; u64 flags[BTRFS_MAX_LEVEL]; struct btrfs_key update_progress; @@ -110,7 +108,7 @@ index ef15a19765c1..25e423b0aa9f 100644 int stage; int level; int shared_level; -@@ -8828,6 +8830,16 @@ static noinline int do_walk_down(struct btrfs_trans_handle *trans, +@@ -8889,6 +8891,15 @@ skip: ret); } } @@ -123,11 +121,10 @@ index ef15a19765c1..25e423b0aa9f 100644 + */ + wc->drop_level = level; + find_next_key(path, level, &wc->drop_progress); -+ - ret = btrfs_free_extent(trans, fs_info, bytenr, blocksize, + ret = btrfs_free_extent(trans, root, bytenr, blocksize, parent, root->root_key.objectid, level - 1, 0); -@@ -9165,12 +9177,14 @@ int btrfs_drop_snapshot(struct btrfs_root *root, +@@ -9226,12 +9237,14 @@ int btrfs_drop_snapshot(struct btrfs_roo } if (wc->stage == DROP_REFERENCE) { @@ -148,6 +145,3 @@ index ef15a19765c1..25e423b0aa9f 100644 BUG_ON(wc->level == 0); if (btrfs_should_end_transaction(trans) || --- -2.19.0 - diff --git a/patches.suse/0002-btrfs-sink-extent_write_full_page-tree-argument.patch b/patches.suse/0002-btrfs-sink-extent_write_full_page-tree-argument.patch new file mode 100644 index 0000000..195565a --- /dev/null +++ b/patches.suse/0002-btrfs-sink-extent_write_full_page-tree-argument.patch @@ -0,0 +1,80 @@ +From 0a9b0e5351818d43ac013c00a1474cc3601fc5bb Mon Sep 17 00:00:00 2001 +From: Nikolay Borisov +Date: Fri, 8 Dec 2017 15:55:59 +0200 +Patch-mainline: v4.16 +Git-commit: 0a9b0e5351818d43ac013c00a1474cc3601fc5bb +References: bsc#1168273 +Subject: [PATCH 2/7] btrfs: sink extent_write_full_page tree argument + +The tree argument passed to extent_write_full_page is referenced from +the page being passed to the same function. Since we already have +enough information to get the reference, remove the function parameter. + +Signed-off-by: Nikolay Borisov +Reviewed-by: David Sterba +Signed-off-by: David Sterba +--- + fs/btrfs/extent_io.c | 5 ++--- + fs/btrfs/extent_io.h | 3 +-- + fs/btrfs/inode.c | 4 +--- + 3 files changed, 4 insertions(+), 8 deletions(-) + +diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c +index c0b2bf65d6b0..6cd3da16f114 100644 +--- a/fs/btrfs/extent_io.c ++++ b/fs/btrfs/extent_io.c +@@ -4056,13 +4056,12 @@ static noinline void flush_write_bio(void *data) + flush_epd_write_bio(epd); + } + +-int extent_write_full_page(struct extent_io_tree *tree, struct page *page, +- struct writeback_control *wbc) ++int extent_write_full_page(struct page *page, struct writeback_control *wbc) + { + int ret; + struct extent_page_data epd = { + .bio = NULL, +- .tree = tree, ++ .tree = &BTRFS_I(page->mapping->host)->io_tree, + .extent_locked = 0, + .sync_io = wbc->sync_mode == WB_SYNC_ALL, + }; +diff --git a/fs/btrfs/extent_io.h b/fs/btrfs/extent_io.h +index f2cbabb2306a..db2558b0cad4 100644 +--- a/fs/btrfs/extent_io.h ++++ b/fs/btrfs/extent_io.h +@@ -403,8 +403,7 @@ int find_first_extent_bit(struct extent_io_tree *tree, u64 start, + struct extent_state **cached_state); + int extent_invalidatepage(struct extent_io_tree *tree, + struct page *page, unsigned long offset); +-int extent_write_full_page(struct extent_io_tree *tree, struct page *page, +- struct writeback_control *wbc); ++int extent_write_full_page(struct page *page, struct writeback_control *wbc); + int extent_write_locked_range(struct inode *inode, u64 start, u64 end, + int mode); + int extent_writepages(struct extent_io_tree *tree, +diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c +index 8a7da59292b7..46df5e2a64e7 100644 +--- a/fs/btrfs/inode.c ++++ b/fs/btrfs/inode.c +@@ -8855,7 +8855,6 @@ int btrfs_readpage(struct file *file, struct page *page) + + static int btrfs_writepage(struct page *page, struct writeback_control *wbc) + { +- struct extent_io_tree *tree; + struct inode *inode = page->mapping->host; + int ret; + +@@ -8874,8 +8873,7 @@ static int btrfs_writepage(struct page *page, struct writeback_control *wbc) + redirty_page_for_writepage(wbc, page); + return AOP_WRITEPAGE_ACTIVATE; + } +- tree = &BTRFS_I(page->mapping->host)->io_tree; +- ret = extent_write_full_page(tree, page, wbc); ++ ret = extent_write_full_page(page, wbc); + btrfs_add_delayed_iput(inode); + return ret; + } +-- +2.26.0 + diff --git a/patches.suse/0002-btrfs-sink-get_extent-parameter-to-extent_write_lock.patch b/patches.suse/0002-btrfs-sink-get_extent-parameter-to-extent_write_lock.patch new file mode 100644 index 0000000..c7a6624 --- /dev/null +++ b/patches.suse/0002-btrfs-sink-get_extent-parameter-to-extent_write_lock.patch @@ -0,0 +1,70 @@ +From 916b929831a92a2a432274cd264311893f22a46d Mon Sep 17 00:00:00 2001 +From: David Sterba +Date: Fri, 23 Jun 2017 03:47:28 +0200 +Patch-mainline: v4.16 +Git-commit: 916b929831a92a2a432274cd264311893f22a46d +References: bsc#1168273 +Subject: [PATCH 2/7] btrfs: sink get_extent parameter to + extent_write_locked_range + +There's only one caller. + +Signed-off-by: David Sterba +--- + fs/btrfs/extent_io.c | 5 ++--- + fs/btrfs/extent_io.h | 3 +-- + fs/btrfs/inode.c | 1 - + 3 files changed, 3 insertions(+), 6 deletions(-) + +diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c +index 1d7aebd020ad..d9a76e33ac3c 100644 +--- a/fs/btrfs/extent_io.c ++++ b/fs/btrfs/extent_io.c +@@ -4077,8 +4077,7 @@ int extent_write_full_page(struct extent_io_tree *tree, struct page *page, + } + + int extent_write_locked_range(struct extent_io_tree *tree, struct inode *inode, +- u64 start, u64 end, get_extent_t *get_extent, +- int mode) ++ u64 start, u64 end, int mode) + { + int ret = 0; + struct address_space *mapping = inode->i_mapping; +@@ -4089,7 +4088,7 @@ int extent_write_locked_range(struct extent_io_tree *tree, struct inode *inode, + struct extent_page_data epd = { + .bio = NULL, + .tree = tree, +- .get_extent = get_extent, ++ .get_extent = btrfs_get_extent, + .extent_locked = 1, + .sync_io = mode == WB_SYNC_ALL, + }; +diff --git a/fs/btrfs/extent_io.h b/fs/btrfs/extent_io.h +index e07f9e1c34e8..b67fc0153b73 100644 +--- a/fs/btrfs/extent_io.h ++++ b/fs/btrfs/extent_io.h +@@ -407,8 +407,7 @@ int extent_write_full_page(struct extent_io_tree *tree, struct page *page, + get_extent_t *get_extent, + struct writeback_control *wbc); + int extent_write_locked_range(struct extent_io_tree *tree, struct inode *inode, +- u64 start, u64 end, get_extent_t *get_extent, +- int mode); ++ u64 start, u64 end, int mode); + int extent_writepages(struct extent_io_tree *tree, + struct address_space *mapping, + struct writeback_control *wbc); +diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c +index a49dd803fb03..ae62d59edd4b 100644 +--- a/fs/btrfs/inode.c ++++ b/fs/btrfs/inode.c +@@ -769,7 +769,6 @@ static noinline void submit_compressed_extents(struct inode *inode, + inode, async_extent->start, + async_extent->start + + async_extent->ram_size - 1, +- btrfs_get_extent, + WB_SYNC_ALL); + else if (ret) + unlock_page(async_cow->locked_page); +-- +2.26.0 + diff --git a/patches.suse/0002-btrfs-unify-error-handling-for-ticket-flushing.patch b/patches.suse/0002-btrfs-unify-error-handling-for-ticket-flushing.patch new file mode 100644 index 0000000..40c8a3a --- /dev/null +++ b/patches.suse/0002-btrfs-unify-error-handling-for-ticket-flushing.patch @@ -0,0 +1,92 @@ +From: Josef Bacik +Date: Thu, 1 Aug 2019 18:19:34 -0400 +Subject: btrfs: unify error handling for ticket flushing +Git-commit: 374bf9c5cd7d0b5c270cb954aaf18d794d4b088c +Patch-mainline: v5.4-rc1 +References: bsc#1165949 + +Currently we handle the cleanup of errored out tickets in both the +priority flush path and the normal flushing path. This is the same code +in both places, so just refactor so we don't duplicate the cleanup work. + +Signed-off-by: Josef Bacik +Reviewed-by: David Sterba +Signed-off-by: David Sterba +Acked-by: Nikolay Borisov +--- + fs/btrfs/space-info.c | 32 +++++++++++--------------------- + 1 file changed, 11 insertions(+), 21 deletions(-) + +diff --git a/fs/btrfs/space-info.c b/fs/btrfs/space-info.c +index 1f4e97070f33..bf2fde3fe782 100644 +--- a/fs/btrfs/space-info.c ++++ b/fs/btrfs/space-info.c +@@ -878,20 +878,19 @@ static void priority_reclaim_metadata_space(struct btrfs_fs_info *fs_info, + } while (flush_state < ARRAY_SIZE(priority_flush_states)); + } + +-static int wait_reserve_ticket(struct btrfs_fs_info *fs_info, +- struct btrfs_space_info *space_info, +- struct reserve_ticket *ticket) ++static void wait_reserve_ticket(struct btrfs_fs_info *fs_info, ++ struct btrfs_space_info *space_info, ++ struct reserve_ticket *ticket) + + { + DEFINE_WAIT(wait); +- u64 reclaim_bytes = 0; + int ret = 0; + + spin_lock(&space_info->lock); + while (ticket->bytes > 0 && ticket->error == 0) { + ret = prepare_to_wait_event(&ticket->wait, &wait, TASK_KILLABLE); + if (ret) { +- ret = -EINTR; ++ ticket->error = -EINTR; + break; + } + spin_unlock(&space_info->lock); +@@ -901,18 +900,7 @@ static int wait_reserve_ticket(struct btrfs_fs_info *fs_info, + finish_wait(&ticket->wait, &wait); + spin_lock(&space_info->lock); + } +- if (!ret) +- ret = ticket->error; +- if (!list_empty(&ticket->list)) +- list_del_init(&ticket->list); +- if (ticket->bytes && ticket->bytes < ticket->orig_bytes) +- reclaim_bytes = ticket->orig_bytes - ticket->bytes; + spin_unlock(&space_info->lock); +- +- if (reclaim_bytes) +- btrfs_space_info_add_old_bytes(fs_info, space_info, +- reclaim_bytes); +- return ret; + } + + /** +@@ -1010,16 +998,18 @@ static int __reserve_metadata_bytes(struct btrfs_fs_info *fs_info, + return ret; + + if (flush == BTRFS_RESERVE_FLUSH_ALL) +- return wait_reserve_ticket(fs_info, space_info, &ticket); ++ wait_reserve_ticket(fs_info, space_info, &ticket); ++ else ++ priority_reclaim_metadata_space(fs_info, space_info, &ticket); + +- ret = 0; +- priority_reclaim_metadata_space(fs_info, space_info, &ticket); + spin_lock(&space_info->lock); +- if (ticket.bytes) { ++ ret = ticket.error; ++ if (ticket.bytes || ticket.error) { + if (ticket.bytes < orig_bytes) + reclaim_bytes = orig_bytes - ticket.bytes; + list_del_init(&ticket.list); +- ret = -ENOSPC; ++ if (!ret) ++ ret = -ENOSPC; + } + spin_unlock(&space_info->lock); + + diff --git a/patches.suse/0002-dma-mapping-move-dma-configuration-to-bus-infrastruc.patch b/patches.suse/0002-dma-mapping-move-dma-configuration-to-bus-infrastruc.patch index a3c97d2..ec0a2a7 100644 --- a/patches.suse/0002-dma-mapping-move-dma-configuration-to-bus-infrastruc.patch +++ b/patches.suse/0002-dma-mapping-move-dma-configuration-to-bus-infrastruc.patch @@ -166,9 +166,9 @@ Signed-off-by: Mian Yousaf Kaukab +#include +#include #include "pci.h" + #include "pcie/portdrv.h" - struct pci_dynid { -@@ -1529,6 +1531,35 @@ static int pci_bus_num_vf(struct device +@@ -1544,6 +1546,35 @@ static int pci_bus_num_vf(struct device return pci_num_vf(to_pci_dev(dev)); } @@ -204,7 +204,7 @@ Signed-off-by: Mian Yousaf Kaukab struct bus_type pci_bus_type = { .name = "pci", .match = pci_bus_match, -@@ -1541,6 +1572,7 @@ struct bus_type pci_bus_type = { +@@ -1556,6 +1587,7 @@ struct bus_type pci_bus_type = { .drv_groups = pci_drv_groups, .pm = PCI_PM_OPS_PTR, .num_vf = pci_bus_num_vf, diff --git a/patches.suse/0002-drm-amdkfd-fix-a-use-after-free-race-with-mmu_notife.patch b/patches.suse/0002-drm-amdkfd-fix-a-use-after-free-race-with-mmu_notife.patch deleted file mode 100644 index 55db6ab..0000000 --- a/patches.suse/0002-drm-amdkfd-fix-a-use-after-free-race-with-mmu_notife.patch +++ /dev/null @@ -1,195 +0,0 @@ -From 0029cab3146a53b820e73c9cd70809b831c590d7 Mon Sep 17 00:00:00 2001 -From: Jason Gunthorpe -Date: Tue, 6 Aug 2019 20:15:46 -0300 -Subject: drm/amdkfd: fix a use after free race with mmu_notifer unregister -Git-commit: 0029cab3146a53b820e73c9cd70809b831c590d7 -Patch-mainline: v5.4-rc1 -References: bsc#1154048 - -When using mmu_notifer_unregister_no_release() the caller must ensure -there is a SRCU synchronize before the mn memory is freed, otherwise use -after free races are possible, for instance: - - CPU0 CPU1 - invalidate_range_start - hlist_for_each_entry_rcu(..) - mmu_notifier_unregister_no_release(&p->mn) - kfree(mn) - if (mn->ops->invalidate_range_end) - -The error unwind in amdkfd misses the SRCU synchronization. - -amdkfd keeps the kfd_process around until the mm is released, so split the -flow to fully initialize the kfd_process and register it for find_process, -and with the notifier. Past this point the kfd_process does not need to be -cleaned up as it is fully ready. - -The final failable step does a vm_mmap() and does not seem to impact the -kfd_process global state. Since it also cannot be undone (and already has -problems with undo if it internally fails), it has to be last. - -This way we don't have to try to unwind the mmu_notifier_register() and -avoid the problem with the SRCU. - -Along the way this also fixes various other error unwind bugs in the flow. - -Fixes: 45102048f77e ("amdkfd: Add process queue manager module") -Link: https://lore.kernel.org/r/20190806231548.25242-10-jgg@ziepe.ca -Reviewed-by: Felix Kuehling -Signed-off-by: Jason Gunthorpe -Acked-by: Thomas Zimmermann ---- - drivers/gpu/drm/amd/amdkfd/kfd_process.c | 83 +++++++++++++++---------------- - 1 file changed, 41 insertions(+), 42 deletions(-) - ---- a/drivers/gpu/drm/amd/amdkfd/kfd_process.c -+++ b/drivers/gpu/drm/amd/amdkfd/kfd_process.c -@@ -61,8 +61,8 @@ static struct workqueue_struct *kfd_rest - - static struct kfd_process *find_process(const struct task_struct *thread); - static void kfd_process_ref_release(struct kref *ref); --static struct kfd_process *create_process(const struct task_struct *thread, -- struct file *filep); -+static struct kfd_process *create_process(const struct task_struct *thread); -+static int kfd_process_init_cwsr_apu(struct kfd_process *p, struct file *filep); - - static void evict_process_worker(struct work_struct *work); - static void restore_process_worker(struct work_struct *work); -@@ -205,6 +205,7 @@ struct kfd_process *kfd_create_process(s - { - struct kfd_process *process; - struct task_struct *thread = current; -+ int ret; - - if (!thread->mm) - return ERR_PTR(-EINVAL); -@@ -224,9 +225,19 @@ struct kfd_process *kfd_create_process(s - process = find_process(thread); - if (process) - pr_debug("Process already found\n"); -- else -- process = create_process(thread, filep); -+ else { -+ process = create_process(thread); -+ if (IS_ERR(process)) -+ goto out; -+ -+ ret = kfd_process_init_cwsr_apu(process, filep); -+ if (ret) { -+ process = ERR_PTR(ret); -+ goto out; -+ } -+ } - -+out: - mutex_unlock(&kfd_processes_mutex); - - return process; -@@ -509,81 +520,69 @@ static int kfd_process_device_init_cwsr_ - return 0; - } - --static struct kfd_process *create_process(const struct task_struct *thread, -- struct file *filep) -+/* -+ * On return the kfd_process is fully operational and will be freed when the -+ * mm is released -+ */ -+static struct kfd_process *create_process(const struct task_struct *thread) - { - struct kfd_process *process; - int err = -ENOMEM; - - process = kzalloc(sizeof(*process), GFP_KERNEL); -- - if (!process) - goto err_alloc_process; - -- process->pasid = kfd_pasid_alloc(); -- if (process->pasid == 0) -- goto err_alloc_pasid; -- -- if (kfd_alloc_process_doorbells(process) < 0) -- goto err_alloc_doorbells; -- - kref_init(&process->ref); -- - mutex_init(&process->mutex); -- - process->mm = thread->mm; -- -- /* register notifier */ -- process->mmu_notifier.ops = &kfd_process_mmu_notifier_ops; -- err = mmu_notifier_register(&process->mmu_notifier, process->mm); -- if (err) -- goto err_mmu_notifier; -- -- hash_add_rcu(kfd_processes_table, &process->kfd_processes, -- (uintptr_t)process->mm); -- - process->lead_thread = thread->group_leader; -- get_task_struct(process->lead_thread); -- - INIT_LIST_HEAD(&process->per_device_data); -- -+ INIT_DELAYED_WORK(&process->eviction_work, evict_process_worker); -+ INIT_DELAYED_WORK(&process->restore_work, restore_process_worker); -+ process->last_restore_timestamp = get_jiffies_64(); - kfd_event_init_process(process); -+ process->is_32bit_user_mode = in_compat_syscall(); -+ -+ process->pasid = kfd_pasid_alloc(); -+ if (process->pasid == 0) -+ goto err_alloc_pasid; -+ -+ if (kfd_alloc_process_doorbells(process) < 0) -+ goto err_alloc_doorbells; - - err = pqm_init(&process->pqm, process); - if (err != 0) - goto err_process_pqm_init; - - /* init process apertures*/ -- process->is_32bit_user_mode = in_compat_syscall(); - err = kfd_init_apertures(process); - if (err != 0) - goto err_init_apertures; - -- INIT_DELAYED_WORK(&process->eviction_work, evict_process_worker); -- INIT_DELAYED_WORK(&process->restore_work, restore_process_worker); -- process->last_restore_timestamp = get_jiffies_64(); -- -- err = kfd_process_init_cwsr_apu(process, filep); -+ /* Must be last, have to use release destruction after this */ -+ process->mmu_notifier.ops = &kfd_process_mmu_notifier_ops; -+ err = mmu_notifier_register(&process->mmu_notifier, process->mm); - if (err) -- goto err_init_cwsr; -+ goto err_register_notifier; -+ -+ get_task_struct(process->lead_thread); -+ hash_add_rcu(kfd_processes_table, &process->kfd_processes, -+ (uintptr_t)process->mm); - - return process; - --err_init_cwsr: -+err_register_notifier: - kfd_process_free_outstanding_kfd_bos(process); - kfd_process_destroy_pdds(process); - err_init_apertures: - pqm_uninit(&process->pqm); - err_process_pqm_init: -- hash_del_rcu(&process->kfd_processes); -- synchronize_rcu(); -- mmu_notifier_unregister_no_release(&process->mmu_notifier, process->mm); --err_mmu_notifier: -- mutex_destroy(&process->mutex); - kfd_free_process_doorbells(process); - err_alloc_doorbells: - kfd_pasid_free(process->pasid); - err_alloc_pasid: -+ mutex_destroy(&process->mutex); - kfree(process); - err_alloc_process: - return ERR_PTR(err); diff --git a/patches.suse/0002-libceph-fix-alloc_msg_with_page_vector-memory-leaks.patch b/patches.suse/0002-libceph-fix-alloc_msg_with_page_vector-memory-leaks.patch new file mode 100644 index 0000000..28e1593 --- /dev/null +++ b/patches.suse/0002-libceph-fix-alloc_msg_with_page_vector-memory-leaks.patch @@ -0,0 +1,143 @@ +From: Ilya Dryomov +Date: Tue, 10 Mar 2020 16:19:01 +0100 +Subject: libceph: fix alloc_msg_with_page_vector() memory leaks +Git-commit: e886274031200bb60965c1b9c49b7acda56a93bd +Patch-mainline: v5.6 +References: bsc#1169308 + + +Make it so that CEPH_MSG_DATA_PAGES data item can own pages, +fixing a bunch of memory leaks for a page vector allocated in +alloc_msg_with_page_vector(). Currently, only watch-notify +messages trigger this allocation, and normally the page vector +is freed either in handle_watch_notify() or by the caller of +ceph_osdc_notify(). But if the message is freed before that +(e.g. if the session faults while reading in the message or +if the notify is stale), we leak the page vector. + +This was supposed to be fixed by switching to a message-owned +pagelist, but that never happened. + +Fixes: 1907920324f1 ("libceph: support for sending notifies") +Reported-by: Roman Penyaev +Signed-off-by: Ilya Dryomov +Reviewed-by: Roman Penyaev +Acked-by: Luis Henriques +--- + include/linux/ceph/messenger.h | 7 ++++--- + net/ceph/messenger.c | 9 +++++++-- + net/ceph/osd_client.c | 14 +++----------- + 3 files changed, 14 insertions(+), 16 deletions(-) + +diff --git a/include/linux/ceph/messenger.h b/include/linux/ceph/messenger.h +index c4458dc6a757..76371aaae2d1 100644 +--- a/include/linux/ceph/messenger.h ++++ b/include/linux/ceph/messenger.h +@@ -175,9 +175,10 @@ struct ceph_msg_data { + #endif /* CONFIG_BLOCK */ + struct ceph_bvec_iter bvec_pos; + struct { +- struct page **pages; /* NOT OWNER. */ ++ struct page **pages; + size_t length; /* total # bytes */ + unsigned int alignment; /* first page */ ++ bool own_pages; + }; + struct ceph_pagelist *pagelist; + }; +@@ -356,8 +357,8 @@ extern void ceph_con_keepalive(struct ceph_connection *con); + extern bool ceph_con_keepalive_expired(struct ceph_connection *con, + unsigned long interval); + +-extern void ceph_msg_data_add_pages(struct ceph_msg *msg, struct page **pages, +- size_t length, size_t alignment); ++void ceph_msg_data_add_pages(struct ceph_msg *msg, struct page **pages, ++ size_t length, size_t alignment, bool own_pages); + extern void ceph_msg_data_add_pagelist(struct ceph_msg *msg, + struct ceph_pagelist *pagelist); + #ifdef CONFIG_BLOCK +diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c +index 5b4bd8261002..f8ca5edc5f2c 100644 +--- a/net/ceph/messenger.c ++++ b/net/ceph/messenger.c +@@ -3248,12 +3248,16 @@ static struct ceph_msg_data *ceph_msg_data_add(struct ceph_msg *msg) + + static void ceph_msg_data_destroy(struct ceph_msg_data *data) + { +- if (data->type == CEPH_MSG_DATA_PAGELIST) ++ if (data->type == CEPH_MSG_DATA_PAGES && data->own_pages) { ++ int num_pages = calc_pages_for(data->alignment, data->length); ++ ceph_release_page_vector(data->pages, num_pages); ++ } else if (data->type == CEPH_MSG_DATA_PAGELIST) { + ceph_pagelist_release(data->pagelist); ++ } + } + + void ceph_msg_data_add_pages(struct ceph_msg *msg, struct page **pages, +- size_t length, size_t alignment) ++ size_t length, size_t alignment, bool own_pages) + { + struct ceph_msg_data *data; + +@@ -3265,6 +3269,7 @@ void ceph_msg_data_add_pages(struct ceph_msg *msg, struct page **pages, + data->pages = pages; + data->length = length; + data->alignment = alignment & ~PAGE_MASK; ++ data->own_pages = own_pages; + + msg->data_length += length; + } +diff --git a/net/ceph/osd_client.c b/net/ceph/osd_client.c +index b68b376d8c2f..af868d3923b9 100644 +--- a/net/ceph/osd_client.c ++++ b/net/ceph/osd_client.c +@@ -962,7 +962,7 @@ static void ceph_osdc_msg_data_add(struct ceph_msg *msg, + BUG_ON(length > (u64) SIZE_MAX); + if (length) + ceph_msg_data_add_pages(msg, osd_data->pages, +- length, osd_data->alignment); ++ length, osd_data->alignment, false); + } else if (osd_data->type == CEPH_OSD_DATA_TYPE_PAGELIST) { + BUG_ON(!length); + ceph_msg_data_add_pagelist(msg, osd_data->pagelist); +@@ -4436,9 +4436,7 @@ static void handle_watch_notify(struct ceph_osd_client *osdc, + CEPH_MSG_DATA_PAGES); + *lreq->preply_pages = data->pages; + *lreq->preply_len = data->length; +- } else { +- ceph_release_page_vector(data->pages, +- calc_pages_for(0, data->length)); ++ data->own_pages = false; + } + } + lreq->notify_finish_error = return_code; +@@ -5506,9 +5504,6 @@ static struct ceph_msg *get_reply(struct ceph_connection *con, + return m; + } + +-/* +- * TODO: switch to a msg-owned pagelist +- */ + static struct ceph_msg *alloc_msg_with_page_vector(struct ceph_msg_header *hdr) + { + struct ceph_msg *m; +@@ -5522,7 +5517,6 @@ static struct ceph_msg *alloc_msg_with_page_vector(struct ceph_msg_header *hdr) + + if (data_len) { + struct page **pages; +- struct ceph_osd_data osd_data; + + pages = ceph_alloc_page_vector(calc_pages_for(0, data_len), + GFP_NOIO); +@@ -5531,9 +5525,7 @@ static struct ceph_msg *alloc_msg_with_page_vector(struct ceph_msg_header *hdr) + return NULL; + } + +- ceph_osd_data_pages_init(&osd_data, pages, data_len, 0, false, +- false); +- ceph_osdc_msg_data_add(m, &osd_data); ++ ceph_msg_data_add_pages(m, pages, data_len, 0, true); + } + + return m; + diff --git a/patches.suse/0002-md-raid6-implement-recovery-using-ARM-NEON-intrinsic.patch b/patches.suse/0002-md-raid6-implement-recovery-using-ARM-NEON-intrinsic.patch index b354a02..16a988b 100644 --- a/patches.suse/0002-md-raid6-implement-recovery-using-ARM-NEON-intrinsic.patch +++ b/patches.suse/0002-md-raid6-implement-recovery-using-ARM-NEON-intrinsic.patch @@ -3,7 +3,7 @@ From: Ard Biesheuvel Date: Thu, 13 Jul 2017 18:16:01 +0100 Subject: [PATCH] md/raid6: implement recovery using ARM NEON intrinsics Git-commit: 6ec4e2514decd6fb4782a9364fa71d6244d05af4 -References: bsc#1111974 +References: bsc#1111974 bsc#1166003 Patch-mainline: v4.14-rc1 Provide a NEON accelerated implementation of the recovery algorithm, diff --git a/patches.suse/0003-btrfs-Rename-bin_search-btrfs_bin_search.patch b/patches.suse/0003-btrfs-Rename-bin_search-btrfs_bin_search.patch new file mode 100644 index 0000000..dc42741 --- /dev/null +++ b/patches.suse/0003-btrfs-Rename-bin_search-btrfs_bin_search.patch @@ -0,0 +1,69 @@ +From a74b35ec876df1c2d11b980bb5e4f697ea4fba94 Mon Sep 17 00:00:00 2001 +From: Nikolay Borisov +Date: Fri, 8 Dec 2017 16:27:43 +0200 +Patch-mainline: v4.16 +Git-commit: a74b35ec876df1c2d11b980bb5e4f697ea4fba94 +References: bsc#1168273 +Subject: [PATCH 3/7] btrfs: Rename bin_search -> btrfs_bin_search + +Currently there are 2 function doing binary search on btrfs nodes: +bin_search and btrfs_bin_search. The latter being a simple wrapper for +the former. So eliminate the wrapper and just rename bin_search to +btrfs_bin_search. No functional changes + +Signed-off-by: Nikolay Borisov +Reviewed-by: David Sterba +Signed-off-by: David Sterba +--- + fs/btrfs/ctree.c | 14 ++++---------- + 1 file changed, 4 insertions(+), 10 deletions(-) + +diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c +index 5361f69433a3..2a09577580b8 100644 +--- a/fs/btrfs/ctree.c ++++ b/fs/btrfs/ctree.c +@@ -1807,8 +1807,8 @@ static noinline int generic_bin_search(struct extent_buffer *eb, + * simple bin_search frontend that does the right thing for + * leaves vs nodes + */ +-static int bin_search(struct extent_buffer *eb, const struct btrfs_key *key, +- int level, int *slot) ++int btrfs_bin_search(struct extent_buffer *eb, const struct btrfs_key *key, ++ int level, int *slot) + { + if (level == 0) + return generic_bin_search(eb, +@@ -1824,12 +1824,6 @@ static int bin_search(struct extent_buffer *eb, const struct btrfs_key *key, + slot); + } + +-int btrfs_bin_search(struct extent_buffer *eb, const struct btrfs_key *key, +- int level, int *slot) +-{ +- return bin_search(eb, key, level, slot); +-} +- + static void root_add_used(struct btrfs_root *root, u32 size) + { + spin_lock(&root->accounting_lock); +@@ -2614,7 +2608,7 @@ static int key_search(struct extent_buffer *b, const struct btrfs_key *key, + int level, int *prev_cmp, int *slot) + { + if (*prev_cmp != 0) { +- *prev_cmp = bin_search(b, key, level, slot); ++ *prev_cmp = btrfs_bin_search(b, key, level, slot); + return *prev_cmp; + } + +@@ -5181,7 +5175,7 @@ int btrfs_search_forward(struct btrfs_root *root, struct btrfs_key *min_key, + while (1) { + nritems = btrfs_header_nritems(cur); + level = btrfs_header_level(cur); +- sret = bin_search(cur, min_key, level, &slot); ++ sret = btrfs_bin_search(cur, min_key, level, &slot); + + /* at the lowest level, we're done, setup the path and exit */ + if (level == path->lowest_level) { +-- +2.26.0 + diff --git a/patches.suse/0003-btrfs-add-cleanup_ref_head_accounting-helper.patch b/patches.suse/0003-btrfs-add-cleanup_ref_head_accounting-helper.patch index 7e1d5f0..f2e9502 100644 --- a/patches.suse/0003-btrfs-add-cleanup_ref_head_accounting-helper.patch +++ b/patches.suse/0003-btrfs-add-cleanup_ref_head_accounting-helper.patch @@ -23,7 +23,7 @@ Acked-by: Nikolay Borisov --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c -@@ -2494,6 +2494,40 @@ static int cleanup_extent_op(struct btrf +@@ -2578,6 +2578,40 @@ static int cleanup_extent_op(struct btrf return ret ? ret : 1; } @@ -64,9 +64,9 @@ Acked-by: Nikolay Borisov static int cleanup_ref_head(struct btrfs_trans_handle *trans, struct btrfs_fs_info *fs_info, struct btrfs_delayed_ref_head *head) -@@ -2531,29 +2565,6 @@ static int cleanup_ref_head(struct btrfs +@@ -2612,29 +2646,6 @@ static int cleanup_ref_head(struct btrfs + spin_unlock(&delayed_refs->lock); spin_unlock(&head->lock); - atomic_dec(&delayed_refs->num_entries); - trace_run_delayed_ref_head(fs_info, head, 0); - @@ -94,7 +94,7 @@ Acked-by: Nikolay Borisov if (head->must_insert_reserved) { btrfs_pin_extent(fs_info, head->bytenr, head->num_bytes, 1); -@@ -2563,9 +2574,9 @@ static int cleanup_ref_head(struct btrfs +@@ -2644,9 +2655,9 @@ static int cleanup_ref_head(struct btrfs } } @@ -107,7 +107,7 @@ Acked-by: Nikolay Borisov btrfs_delayed_ref_unlock(head); btrfs_put_delayed_ref_head(head); return 0; -@@ -7105,6 +7116,7 @@ static noinline int check_ref_cleanup(st +@@ -7180,6 +7191,7 @@ static noinline int check_ref_cleanup(st if (head->must_insert_reserved) ret = 1; diff --git a/patches.suse/0003-btrfs-call-btrfs_create_pending_block_groups-unconditionally.patch b/patches.suse/0003-btrfs-call-btrfs_create_pending_block_groups-unconditionally.patch new file mode 100644 index 0000000..1ed70dc --- /dev/null +++ b/patches.suse/0003-btrfs-call-btrfs_create_pending_block_groups-unconditionally.patch @@ -0,0 +1,57 @@ +From: Josef Bacik +Date: Wed, 21 Nov 2018 14:05:42 -0500 +Subject: btrfs: call btrfs_create_pending_block_groups unconditionally +Git-commit: 119e80df7d49e3794ca6d18afecd0cce948cad94 +Patch-mainline: v5.1-rc1 +References: bsc#1165949 + +The first thing we do is loop through the list, this + +if (!list_empty()) + btrfs_create_pending_block_groups(); + +thing is just wasted space. + +Reviewed-by: Nikolay Borisov +Signed-off-by: Josef Bacik +Signed-off-by: David Sterba +Acked-by: Nikolay Borisov +--- + fs/btrfs/extent-tree.c | 3 +-- + fs/btrfs/transaction.c | 6 ++---- + 2 files changed, 3 insertions(+), 6 deletions(-) + +--- a/fs/btrfs/extent-tree.c ++++ b/fs/btrfs/extent-tree.c +@@ -3104,8 +3104,7 @@ again: + } + + if (run_all) { +- if (!list_empty(&trans->new_bgs)) +- btrfs_create_pending_block_groups(trans, fs_info); ++ btrfs_create_pending_block_groups(trans, fs_info); + + spin_lock(&delayed_refs->lock); + node = rb_first(&delayed_refs->href_root); +--- a/fs/btrfs/transaction.c ++++ b/fs/btrfs/transaction.c +@@ -863,8 +863,7 @@ static int __btrfs_end_transaction(struc + btrfs_trans_release_metadata(trans, info); + trans->block_rsv = NULL; + +- if (!list_empty(&trans->new_bgs)) +- btrfs_create_pending_block_groups(trans, info); ++ btrfs_create_pending_block_groups(trans, info); + + btrfs_trans_release_chunk_metadata(trans); + +@@ -1978,8 +1977,7 @@ int btrfs_commit_transaction(struct btrf + cur_trans->delayed_refs.flushing = 1; + smp_wmb(); + +- if (!list_empty(&trans->new_bgs)) +- btrfs_create_pending_block_groups(trans, fs_info); ++ btrfs_create_pending_block_groups(trans, fs_info); + + ret = btrfs_run_delayed_refs(trans, fs_info, 0); + if (ret) { diff --git a/patches.suse/0003-btrfs-cleanup-extent_op-handling.patch b/patches.suse/0003-btrfs-cleanup-extent_op-handling.patch new file mode 100644 index 0000000..bccfd77 --- /dev/null +++ b/patches.suse/0003-btrfs-cleanup-extent_op-handling.patch @@ -0,0 +1,89 @@ +From: Josef Bacik +Date: Mon, 3 Dec 2018 10:20:31 -0500 +Subject: btrfs: cleanup extent_op handling +Git-commit: bedc661760a9837d592070669b296ab58e8f40c9 +Patch-mainline: v5.0-rc1 +References: bsc#1165949 + +The cleanup_extent_op function actually would run the extent_op if it +needed running, which made the name sort of a misnomer. Change it to +run_and_cleanup_extent_op, and move the actual cleanup work to +cleanup_extent_op so it can be used by check_ref_cleanup() in order to +unify the extent op handling. + +Reviewed-by: Lu Fengqi +Signed-off-by: Josef Bacik +Signed-off-by: David Sterba +Acked-by: Nikolay Borisov +--- + fs/btrfs/extent-tree.c | 37 ++++++++++++++++++++++--------------- + 1 file changed, 22 insertions(+), 15 deletions(-) + +--- a/fs/btrfs/extent-tree.c ++++ b/fs/btrfs/extent-tree.c +@@ -2558,22 +2558,33 @@ static void unselect_delayed_ref_head(st + btrfs_delayed_ref_unlock(head); + } + +-static int cleanup_extent_op(struct btrfs_trans_handle *trans, +- struct btrfs_fs_info *fs_info, +- struct btrfs_delayed_ref_head *head) ++static struct btrfs_delayed_extent_op *cleanup_extent_op( ++ struct btrfs_delayed_ref_head *head) + { + struct btrfs_delayed_extent_op *extent_op = head->extent_op; +- int ret; + + if (!extent_op) +- return 0; +- head->extent_op = NULL; ++ return NULL; + if (head->must_insert_reserved) { ++ head->extent_op = NULL; + btrfs_free_delayed_extent_op(extent_op); +- return 0; ++ return NULL; + } ++ return extent_op; ++} ++ ++static int run_and_cleanup_extent_op(struct btrfs_trans_handle *trans, ++ struct btrfs_delayed_ref_head *head) ++{ ++ struct btrfs_delayed_extent_op *extent_op; ++ int ret; ++ ++ extent_op = cleanup_extent_op(head); ++ if (!extent_op) ++ return 0; ++ head->extent_op = NULL; + spin_unlock(&head->lock); +- ret = run_delayed_extent_op(trans, fs_info, head, extent_op); ++ ret = run_delayed_extent_op(trans, trans->fs_info, head, extent_op); + btrfs_free_delayed_extent_op(extent_op); + return ret ? ret : 1; + } +@@ -2621,7 +2632,7 @@ static int cleanup_ref_head(struct btrfs + + delayed_refs = &trans->transaction->delayed_refs; + +- ret = cleanup_extent_op(trans, fs_info, head); ++ ret = run_and_cleanup_extent_op(trans, head); + if (ret < 0) { + unselect_delayed_ref_head(delayed_refs, head); + btrfs_debug(fs_info, "run_delayed_extent_op returned %d", ret); +@@ -7168,12 +7179,8 @@ static noinline int check_ref_cleanup(st + if (!RB_EMPTY_ROOT(&head->ref_tree)) + goto out; + +- if (head->extent_op) { +- if (!head->must_insert_reserved) +- goto out; +- btrfs_free_delayed_extent_op(head->extent_op); +- head->extent_op = NULL; +- } ++ if (cleanup_extent_op(head) != NULL) ++ goto out; + + /* + * waiting for the lock here would deadlock. If someone else has it diff --git a/patches.suse/0003-btrfs-delayed-ref-Use-btrfs_ref-to-refactor-btrfs_ad.patch b/patches.suse/0003-btrfs-delayed-ref-Use-btrfs_ref-to-refactor-btrfs_ad.patch index 7b7a900..46a6704 100644 --- a/patches.suse/0003-btrfs-delayed-ref-Use-btrfs_ref-to-refactor-btrfs_ad.patch +++ b/patches.suse/0003-btrfs-delayed-ref-Use-btrfs_ref-to-refactor-btrfs_ad.patch @@ -101,14 +101,15 @@ Signed-off-by: David Sterba int btrfs_add_delayed_data_ref(struct btrfs_fs_info *fs_info, --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c -@@ -2113,18 +2113,20 @@ int btrfs_inc_extent_ref(struct btrfs_tr +@@ -2193,6 +2193,7 @@ int btrfs_inc_extent_ref(struct btrfs_tr u64 bytenr, u64 num_bytes, u64 parent, u64 root_objectid, u64 owner, u64 offset) { + struct btrfs_ref generic_ref = { 0 }; + struct btrfs_fs_info *fs_info = root->fs_info; int old_ref_mod, new_ref_mod; int ret; - +@@ -2200,12 +2201,13 @@ int btrfs_inc_extent_ref(struct btrfs_tr BUG_ON(owner < BTRFS_FIRST_FREE_OBJECTID && root_objectid == BTRFS_TREE_LOG_OBJECTID); @@ -127,7 +128,7 @@ Signed-off-by: David Sterba } else { ret = btrfs_add_delayed_data_ref(fs_info, trans, bytenr, num_bytes, parent, -@@ -7121,18 +7123,20 @@ void btrfs_free_tree_block(struct btrfs_ +@@ -7215,18 +7217,20 @@ void btrfs_free_tree_block(struct btrfs_ u64 parent, int last_ref) { struct btrfs_fs_info *fs_info = root->fs_info; @@ -154,25 +155,24 @@ Signed-off-by: David Sterba BUG_ON(ret); /* -ENOMEM */ pin = old_ref_mod >= 0 && new_ref_mod < 0; } -@@ -7183,6 +7187,7 @@ int btrfs_free_extent(struct btrfs_trans - u64 bytenr, u64 num_bytes, u64 parent, u64 root_objectid, +@@ -7278,12 +7282,16 @@ int btrfs_free_extent(struct btrfs_trans u64 owner, u64 offset) { + struct btrfs_fs_info *fs_info = root->fs_info; + struct btrfs_ref generic_ref = { 0 }; int old_ref_mod, new_ref_mod; int ret; -@@ -7190,6 +7195,9 @@ int btrfs_free_extent(struct btrfs_trans + if (btrfs_is_testing(fs_info)) return 0; - + btrfs_init_generic_ref(&generic_ref, BTRFS_DROP_DELAYED_REF, bytenr, + num_bytes, parent); + generic_ref.real_root = root_objectid; /* * tree log blocks never actually go into the extent allocation * tree, just update pinning info and exit early. -@@ -7201,11 +7209,9 @@ int btrfs_free_extent(struct btrfs_trans +@@ -7295,11 +7303,9 @@ int btrfs_free_extent(struct btrfs_trans old_ref_mod = new_ref_mod = 0; ret = 0; } else if (owner < BTRFS_FIRST_FREE_OBJECTID) { @@ -187,7 +187,7 @@ Signed-off-by: David Sterba } else { ret = btrfs_add_delayed_data_ref(fs_info, trans, bytenr, num_bytes, parent, -@@ -8335,6 +8341,7 @@ struct extent_buffer *btrfs_alloc_tree_b +@@ -8430,6 +8436,7 @@ struct extent_buffer *btrfs_alloc_tree_b struct btrfs_block_rsv *block_rsv; struct extent_buffer *buf; struct btrfs_delayed_extent_op *extent_op; @@ -195,7 +195,7 @@ Signed-off-by: David Sterba u64 flags = 0; int ret; u32 blocksize = fs_info->nodesize; -@@ -8388,10 +8395,11 @@ struct extent_buffer *btrfs_alloc_tree_b +@@ -8483,10 +8490,11 @@ struct extent_buffer *btrfs_alloc_tree_b extent_op->is_data = false; extent_op->level = level; diff --git a/patches.suse/0003-btrfs-extent_io-Handle-errors-better-in-btree_write_.patch b/patches.suse/0003-btrfs-extent_io-Handle-errors-better-in-btree_write_.patch new file mode 100644 index 0000000..14f0bb9 --- /dev/null +++ b/patches.suse/0003-btrfs-extent_io-Handle-errors-better-in-btree_write_.patch @@ -0,0 +1,57 @@ +From 2b952eea813b1f7e7d4b9782271acd91625b9bb9 Mon Sep 17 00:00:00 2001 +From: Qu Wenruo +Date: Wed, 20 Mar 2019 14:27:43 +0800 +Patch-mainline: v5.2 +Git-commit: 2b952eea813b1f7e7d4b9782271acd91625b9bb9 +References: bsc#1168273 +Subject: [PATCH 3/7] btrfs: extent_io: Handle errors better in + btree_write_cache_pages() + +In btree_write_cache_pages(), we can only get @ret <= 0. +Add an ASSERT() for it just in case. + +Then instead of submitting the write bio even we got some error, check +the return value first. +If we have already hit some error, just clean up the corrupted or +half-baked bio, and return error. + +If there is no error so far, then call flush_write_bio() and return the +result. + +Signed-off-by: Qu Wenruo +Reviewed-by: David Sterba +Signed-off-by: David Sterba +--- + fs/btrfs/extent_io.c | 9 ++++++--- + 1 file changed, 6 insertions(+), 3 deletions(-) + +diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c +index 9d52f3b78732..8399fc4b27ae 100644 +--- a/fs/btrfs/extent_io.c ++++ b/fs/btrfs/extent_io.c +@@ -3748,7 +3748,6 @@ int btree_write_cache_pages(struct address_space *mapping, + .sync_io = wbc->sync_mode == WB_SYNC_ALL, + }; + int ret = 0; +- int flush_ret; + int done = 0; + int nr_to_write_done = 0; + struct pagevec pvec; +@@ -3848,8 +3847,12 @@ int btree_write_cache_pages(struct address_space *mapping, + index = 0; + goto retry; + } +- flush_ret = flush_write_bio(&epd); +- BUG_ON(flush_ret < 0); ++ ASSERT(ret <= 0); ++ if (ret < 0) { ++ end_write_bio(&epd, ret); ++ return ret; ++ } ++ ret = flush_write_bio(&epd); + return ret; + } + +-- +2.26.0 + diff --git a/patches.suse/0003-btrfs-factor-out-the-ticket-flush-handling.patch b/patches.suse/0003-btrfs-factor-out-the-ticket-flush-handling.patch new file mode 100644 index 0000000..4fbcbe0 --- /dev/null +++ b/patches.suse/0003-btrfs-factor-out-the-ticket-flush-handling.patch @@ -0,0 +1,106 @@ +From: Josef Bacik +Date: Thu, 1 Aug 2019 18:19:35 -0400 +Subject: btrfs: factor out the ticket flush handling +Git-commit: 03235279b4defc85e0e593824b27b5cf814b2fa0 +Patch-mainline: v5.4-rc1 +References: bsc#1165949 + +We're going to make this logic a little more complicated for evict, so +factor the ticket flushing/waiting code out of __reserve_metadata_bytes. +This has no functional change. + +Signed-off-by: Josef Bacik +Reviewed-by: David Sterba +Signed-off-by: David Sterba +Acked-by: Nikolay Borisov +--- + fs/btrfs/space-info.c | 64 ++++++++++++++++++++++++++++++++------------------ + 1 file changed, 42 insertions(+), 22 deletions(-) + +--- a/fs/btrfs/space-info.c ++++ b/fs/btrfs/space-info.c +@@ -919,6 +919,47 @@ static void wait_reserve_ticket(struct b + } + + /** ++ * handle_reserve_ticket - do the appropriate flushing and waiting for a ticket ++ * @fs_info - the fs ++ * @space_info - the space_info for the reservation ++ * @ticket - the ticket for the reservation ++ * @flush - how much we can flush ++ * ++ * This does the work of figuring out how to flush for the ticket, waiting for ++ * the reservation, and returning the appropriate error if there is one. ++ */ ++static int handle_reserve_ticket(struct btrfs_fs_info *fs_info, ++ struct btrfs_space_info *space_info, ++ struct reserve_ticket *ticket, ++ enum btrfs_reserve_flush_enum flush) ++{ ++ u64 reclaim_bytes = 0; ++ int ret; ++ ++ if (flush == BTRFS_RESERVE_FLUSH_ALL) ++ wait_reserve_ticket(fs_info, space_info, ticket); ++ else ++ priority_reclaim_metadata_space(fs_info, space_info, ticket); ++ ++ spin_lock(&space_info->lock); ++ ret = ticket->error; ++ if (ticket->bytes || ticket->error) { ++ if (ticket->bytes < ticket->orig_bytes) ++ reclaim_bytes = ticket->orig_bytes - ticket->bytes; ++ list_del_init(&ticket->list); ++ if (!ret) ++ ret = -ENOSPC; ++ } ++ spin_unlock(&space_info->lock); ++ ++ if (reclaim_bytes) ++ btrfs_space_info_add_old_bytes(fs_info, space_info, ++ reclaim_bytes); ++ ASSERT(list_empty(&ticket->list)); ++ return ret; ++} ++ ++/** + * reserve_metadata_bytes - try to reserve bytes from the block_rsv's space + * @root - the root we're allocating for + * @space_info - the space info we want to allocate from +@@ -940,7 +981,6 @@ static int __reserve_metadata_bytes(stru + struct btrfs_fs_info *fs_info = root->fs_info; + struct reserve_ticket ticket; + u64 used; +- u64 reclaim_bytes = 0; + int ret = 0; + + ASSERT(orig_bytes); +@@ -1016,27 +1056,7 @@ static int __reserve_metadata_bytes(stru + if (!ret || flush == BTRFS_RESERVE_NO_FLUSH) + return ret; + +- if (flush == BTRFS_RESERVE_FLUSH_ALL) +- wait_reserve_ticket(fs_info, space_info, &ticket); +- else +- priority_reclaim_metadata_space(fs_info, space_info, &ticket); +- +- spin_lock(&space_info->lock); +- ret = ticket.error; +- if (ticket.bytes || ticket.error) { +- if (ticket.bytes < orig_bytes) +- reclaim_bytes = orig_bytes - ticket.bytes; +- list_del_init(&ticket.list); +- if (!ret) +- ret = -ENOSPC; +- } +- spin_unlock(&space_info->lock); +- +- if (reclaim_bytes) +- btrfs_space_info_add_old_bytes(fs_info, space_info, +- reclaim_bytes); +- ASSERT(list_empty(&ticket.list)); +- return ret; ++ return handle_reserve_ticket(fs_info, space_info, &ticket, flush); + } + + /** diff --git a/patches.suse/0003-btrfs-migrate-the-block-group-lookup-code.patch b/patches.suse/0003-btrfs-migrate-the-block-group-lookup-code.patch new file mode 100644 index 0000000..9a8fdf9 --- /dev/null +++ b/patches.suse/0003-btrfs-migrate-the-block-group-lookup-code.patch @@ -0,0 +1,291 @@ +From: Josef Bacik +Date: Thu, 20 Jun 2019 15:37:45 -0400 +Subject: btrfs: migrate the block group lookup code +Git-commit: 2e405ad842546a1a37aaa586d5140d071cb1f802 +Patch-mainline: v5.4-rc1 +References: bsc#1165949 + +Move these bits first as they are the easiest to move. Export two of +the helpers so they can be moved all at once. + +Signed-off-by: Josef Bacik +Reviewed-by: David Sterba +[ minor style updates ] +Signed-off-by: David Sterba +Acked-by: Nikolay Borisov +--- + fs/btrfs/Makefile | 2 - + fs/btrfs/block-group.c | 95 ++++++++++++++++++++++++++++++++++++++++++++++++ + fs/btrfs/block-group.h | 7 +++ + fs/btrfs/ctree.h | 3 - + fs/btrfs/extent-tree.c | 96 +------------------------------------------------ + 5 files changed, 105 insertions(+), 98 deletions(-) + +--- a/fs/btrfs/Makefile ++++ b/fs/btrfs/Makefile +@@ -10,7 +10,7 @@ btrfs-y += super.o ctree.o extent-tree.o + compression.o delayed-ref.o relocation.o delayed-inode.o scrub.o \ + reada.o backref.o ulist.o qgroup.o send.o dev-replace.o raid56.o \ + uuid-tree.o props.o hash.o free-space-tree.o tree-checker.o space-info.o \ +- block-rsv.o delalloc-space.o ++ block-rsv.o delalloc-space.o block-group.o + + btrfs-$(CONFIG_BTRFS_FS_POSIX_ACL) += acl.o + btrfs-$(CONFIG_BTRFS_FS_CHECK_INTEGRITY) += check-integrity.o +--- /dev/null ++++ b/fs/btrfs/block-group.c +@@ -0,0 +1,95 @@ ++// SPDX-License-Identifier: GPL-2.0 ++ ++#include "ctree.h" ++#include "block-group.h" ++ ++/* ++ * This will return the block group at or after bytenr if contains is 0, else ++ * it will return the block group that contains the bytenr ++ */ ++static struct btrfs_block_group_cache *block_group_cache_tree_search( ++ struct btrfs_fs_info *info, u64 bytenr, int contains) ++{ ++ struct btrfs_block_group_cache *cache, *ret = NULL; ++ struct rb_node *n; ++ u64 end, start; ++ ++ spin_lock(&info->block_group_cache_lock); ++ n = info->block_group_cache_tree.rb_node; ++ ++ while (n) { ++ cache = rb_entry(n, struct btrfs_block_group_cache, ++ cache_node); ++ end = cache->key.objectid + cache->key.offset - 1; ++ start = cache->key.objectid; ++ ++ if (bytenr < start) { ++ if (!contains && (!ret || start < ret->key.objectid)) ++ ret = cache; ++ n = n->rb_left; ++ } else if (bytenr > start) { ++ if (contains && bytenr <= end) { ++ ret = cache; ++ break; ++ } ++ n = n->rb_right; ++ } else { ++ ret = cache; ++ break; ++ } ++ } ++ if (ret) { ++ btrfs_get_block_group(ret); ++ if (bytenr == 0 && info->first_logical_byte > ret->key.objectid) ++ info->first_logical_byte = ret->key.objectid; ++ } ++ spin_unlock(&info->block_group_cache_lock); ++ ++ return ret; ++} ++ ++/* ++ * Return the block group that starts at or after bytenr ++ */ ++struct btrfs_block_group_cache *btrfs_lookup_first_block_group( ++ struct btrfs_fs_info *info, u64 bytenr) ++{ ++ return block_group_cache_tree_search(info, bytenr, 0); ++} ++ ++/* ++ * Return the block group that contains the given bytenr ++ */ ++struct btrfs_block_group_cache *btrfs_lookup_block_group( ++ struct btrfs_fs_info *info, u64 bytenr) ++{ ++ return block_group_cache_tree_search(info, bytenr, 1); ++} ++ ++struct btrfs_block_group_cache *btrfs_next_block_group( ++ struct btrfs_block_group_cache *cache) ++{ ++ struct btrfs_fs_info *fs_info = cache->fs_info; ++ struct rb_node *node; ++ ++ spin_lock(&fs_info->block_group_cache_lock); ++ ++ /* If our block group was removed, we need a full search. */ ++ if (RB_EMPTY_NODE(&cache->cache_node)) { ++ const u64 next_bytenr = cache->key.objectid + cache->key.offset; ++ ++ spin_unlock(&fs_info->block_group_cache_lock); ++ btrfs_put_block_group(cache); ++ cache = btrfs_lookup_first_block_group(fs_info, next_bytenr); return cache; ++ } ++ node = rb_next(&cache->cache_node); ++ btrfs_put_block_group(cache); ++ if (node) { ++ cache = rb_entry(node, struct btrfs_block_group_cache, ++ cache_node); ++ btrfs_get_block_group(cache); ++ } else ++ cache = NULL; ++ spin_unlock(&fs_info->block_group_cache_lock); ++ return cache; ++} +--- a/fs/btrfs/block-group.h ++++ b/fs/btrfs/block-group.h +@@ -151,4 +151,11 @@ static inline int btrfs_should_fragment_ + } + #endif + ++struct btrfs_block_group_cache *btrfs_lookup_first_block_group( ++ struct btrfs_fs_info *info, u64 bytenr); ++struct btrfs_block_group_cache *btrfs_lookup_block_group( ++ struct btrfs_fs_info *info, u64 bytenr); ++struct btrfs_block_group_cache *btrfs_next_block_group( ++ struct btrfs_block_group_cache *cache); ++ + #endif /* BTRFS_BLOCK_GROUP_H */ +--- a/fs/btrfs/ctree.h ++++ b/fs/btrfs/ctree.h +@@ -2481,9 +2481,6 @@ int btrfs_exclude_logged_extents(struct + struct extent_buffer *eb); + 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, +- u64 bytenr); + void btrfs_get_block_group(struct btrfs_block_group_cache *cache); + void btrfs_put_block_group(struct btrfs_block_group_cache *cache); + int get_block_group_index(struct btrfs_block_group_cache *cache); +--- a/fs/btrfs/extent-tree.c ++++ b/fs/btrfs/extent-tree.c +@@ -154,52 +154,6 @@ static int btrfs_add_block_group_cache(s + return 0; + } + +-/* +- * This will return the block group at or after bytenr if contains is 0, else +- * it will return the block group that contains the bytenr +- */ +-static struct btrfs_block_group_cache * +-block_group_cache_tree_search(struct btrfs_fs_info *info, u64 bytenr, +- int contains) +-{ +- struct btrfs_block_group_cache *cache, *ret = NULL; +- struct rb_node *n; +- u64 end, start; +- +- spin_lock(&info->block_group_cache_lock); +- n = info->block_group_cache_tree.rb_node; +- +- while (n) { +- cache = rb_entry(n, struct btrfs_block_group_cache, +- cache_node); +- end = cache->key.objectid + cache->key.offset - 1; +- start = cache->key.objectid; +- +- if (bytenr < start) { +- if (!contains && (!ret || start < ret->key.objectid)) +- ret = cache; +- n = n->rb_left; +- } else if (bytenr > start) { +- if (contains && bytenr <= end) { +- ret = cache; +- break; +- } +- n = n->rb_right; +- } else { +- ret = cache; +- break; +- } +- } +- if (ret) { +- btrfs_get_block_group(ret); +- if (bytenr == 0 && info->first_logical_byte > ret->key.objectid) +- info->first_logical_byte = ret->key.objectid; +- } +- spin_unlock(&info->block_group_cache_lock); +- +- return ret; +-} +- + static int add_excluded_extent(struct btrfs_fs_info *fs_info, + u64 start, u64 num_bytes) + { +@@ -696,24 +650,6 @@ static int cache_block_group(struct btrf + return ret; + } + +-/* +- * return the block group that starts at or after bytenr +- */ +-static struct btrfs_block_group_cache * +-btrfs_lookup_first_block_group(struct btrfs_fs_info *info, u64 bytenr) +-{ +- return block_group_cache_tree_search(info, bytenr, 0); +-} +- +-/* +- * return the block group that contains the given bytenr +- */ +-struct btrfs_block_group_cache *btrfs_lookup_block_group( +- struct btrfs_fs_info *info, +- u64 bytenr) +-{ +- return block_group_cache_tree_search(info, bytenr, 1); +-} + + static void add_pinned_bytes(struct btrfs_fs_info *fs_info, + struct btrfs_ref *ref, int sign) +@@ -3352,34 +3288,6 @@ fail: + + } + +-static struct btrfs_block_group_cache * +-next_block_group(struct btrfs_fs_info *fs_info, +- struct btrfs_block_group_cache *cache) +-{ +- struct rb_node *node; +- +- spin_lock(&fs_info->block_group_cache_lock); +- +- /* If our block group was removed, we need a full search. */ +- if (RB_EMPTY_NODE(&cache->cache_node)) { +- const u64 next_bytenr = cache->key.objectid + cache->key.offset; +- +- spin_unlock(&fs_info->block_group_cache_lock); +- btrfs_put_block_group(cache); +- cache = btrfs_lookup_first_block_group(fs_info, next_bytenr); return cache; +- } +- node = rb_next(&cache->cache_node); +- btrfs_put_block_group(cache); +- if (node) { +- cache = rb_entry(node, struct btrfs_block_group_cache, +- cache_node); +- btrfs_get_block_group(cache); +- } else +- cache = NULL; +- spin_unlock(&fs_info->block_group_cache_lock); +- return cache; +-} +- + static int cache_save_setup(struct btrfs_block_group_cache *block_group, + struct btrfs_trans_handle *trans, + struct btrfs_path *path) +@@ -7881,7 +7789,7 @@ void btrfs_put_block_group_cache(struct + if (block_group->iref) + break; + spin_unlock(&block_group->lock); +- block_group = next_block_group(info, block_group); ++ block_group = btrfs_next_block_group(block_group); + } + if (!block_group) { + if (last == 0) +@@ -9103,7 +9011,7 @@ int btrfs_trim_fs(struct btrfs_fs_info * + int ret = 0; + + cache = btrfs_lookup_first_block_group(fs_info, range->start); +- for (; cache; cache = next_block_group(fs_info, cache)) { ++ for (; cache; cache = btrfs_next_block_group(cache)) { + if (cache->key.objectid >= (range->start + range->len)) { + btrfs_put_block_group(cache); + break; diff --git a/patches.suse/0003-btrfs-pass-root-to-various-extent-ref-mod-functions.patch b/patches.suse/0003-btrfs-pass-root-to-various-extent-ref-mod-functions.patch new file mode 100644 index 0000000..f977c64 --- /dev/null +++ b/patches.suse/0003-btrfs-pass-root-to-various-extent-ref-mod-functions.patch @@ -0,0 +1,340 @@ +From: Josef Bacik +Date: Fri, 29 Sep 2017 15:43:49 -0400 +Subject: btrfs: pass root to various extent ref mod functions +Git-commit: 84f7d8e6242ceb377c7af10a7133c653cc7fea5f +Patch-mainline: v4.15-rc1 +References: bsc#1165949 + +We need the actual root for the ref verifier tool to work, so change +these functions to pass the root around instead. This will be used in +a subsequent patch. + +Signed-off-by: Josef Bacik +Signed-off-by: David Sterba +Acked-by: Nikolay Borisov +--- + fs/btrfs/ctree.c | 2 +- + fs/btrfs/ctree.h | 7 ++++--- + fs/btrfs/extent-tree.c | 24 +++++++++++++----------- + fs/btrfs/file.c | 10 +++++----- + fs/btrfs/inode.c | 9 +++++---- + fs/btrfs/ioctl.c | 2 +- + fs/btrfs/relocation.c | 14 +++++++------- + fs/btrfs/tree-log.c | 2 +- + 8 files changed, 37 insertions(+), 33 deletions(-) + +diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c +index 19b9c5131745..531e0a8645b0 100644 +--- a/fs/btrfs/ctree.c ++++ b/fs/btrfs/ctree.c +@@ -192,7 +192,7 @@ struct extent_buffer *btrfs_lock_root_node(struct btrfs_root *root) + * tree until you end up with a lock on the root. A locked buffer + * is returned, with a reference held. + */ +-static struct extent_buffer *btrfs_read_lock_root_node(struct btrfs_root *root) ++struct extent_buffer *btrfs_read_lock_root_node(struct btrfs_root *root) + { + struct extent_buffer *eb; + +diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h +index 75947c6c04c3..2fcc3c30d471 100644 +--- a/fs/btrfs/ctree.h ++++ b/fs/btrfs/ctree.h +@@ -2637,7 +2637,7 @@ void btrfs_free_tree_block(struct btrfs_trans_handle *trans, + struct extent_buffer *buf, + u64 parent, int last_ref); + int btrfs_alloc_reserved_file_extent(struct btrfs_trans_handle *trans, +- u64 root_objectid, u64 owner, ++ struct btrfs_root *root, u64 owner, + u64 offset, u64 ram_bytes, + struct btrfs_key *ins); + int btrfs_alloc_logged_file_extent(struct btrfs_trans_handle *trans, +@@ -2656,7 +2656,7 @@ int btrfs_set_disk_extent_flags(struct btrfs_trans_handle *trans, + u64 bytenr, u64 num_bytes, u64 flags, + int level, int is_data); + int btrfs_free_extent(struct btrfs_trans_handle *trans, +- struct btrfs_fs_info *fs_info, ++ struct btrfs_root *root, + u64 bytenr, u64 num_bytes, u64 parent, u64 root_objectid, + u64 owner, u64 offset); + +@@ -2668,7 +2668,7 @@ void btrfs_prepare_extent_commit(struct btrfs_fs_info *fs_info); + int btrfs_finish_extent_commit(struct btrfs_trans_handle *trans, + struct btrfs_fs_info *fs_info); + int btrfs_inc_extent_ref(struct btrfs_trans_handle *trans, +- struct btrfs_fs_info *fs_info, ++ struct btrfs_root *root, + u64 bytenr, u64 num_bytes, u64 parent, + u64 root_objectid, u64 owner, u64 offset); + +@@ -2807,6 +2807,7 @@ void btrfs_set_item_key_safe(struct btrfs_fs_info *fs_info, + const struct btrfs_key *new_key); + struct extent_buffer *btrfs_root_node(struct btrfs_root *root); + struct extent_buffer *btrfs_lock_root_node(struct btrfs_root *root); ++struct extent_buffer *btrfs_read_lock_root_node(struct btrfs_root *root); + int btrfs_find_next_key(struct btrfs_root *root, struct btrfs_path *path, + struct btrfs_key *key, int lowest_level, + u64 min_trans); +diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c +index 624aa6841bf2..a9787c3c0f7e 100644 +--- a/fs/btrfs/extent-tree.c ++++ b/fs/btrfs/extent-tree.c +@@ -2177,10 +2177,11 @@ int btrfs_discard_extent(struct btrfs_fs_info *fs_info, u64 bytenr, + + /* Can return -ENOMEM */ + int btrfs_inc_extent_ref(struct btrfs_trans_handle *trans, +- struct btrfs_fs_info *fs_info, ++ struct btrfs_root *root, + u64 bytenr, u64 num_bytes, u64 parent, + u64 root_objectid, u64 owner, u64 offset) + { ++ struct btrfs_fs_info *fs_info = root->fs_info; + int old_ref_mod, new_ref_mod; + int ret; + +@@ -3339,7 +3340,7 @@ static int __btrfs_mod_ref(struct btrfs_trans_handle *trans, + int level; + int ret = 0; + int (*process_func)(struct btrfs_trans_handle *, +- struct btrfs_fs_info *, ++ struct btrfs_root *, + u64, u64, u64, u64, u64, u64); + + +@@ -3379,7 +3380,7 @@ static int __btrfs_mod_ref(struct btrfs_trans_handle *trans, + + num_bytes = btrfs_file_extent_disk_num_bytes(buf, fi); + key.offset -= btrfs_file_extent_offset(buf, fi); +- ret = process_func(trans, fs_info, bytenr, num_bytes, ++ ret = process_func(trans, root, bytenr, num_bytes, + parent, ref_root, key.objectid, + key.offset); + if (ret) +@@ -3387,7 +3388,7 @@ static int __btrfs_mod_ref(struct btrfs_trans_handle *trans, + } else { + bytenr = btrfs_node_blockptr(buf, i); + num_bytes = fs_info->nodesize; +- ret = process_func(trans, fs_info, bytenr, num_bytes, ++ ret = process_func(trans, root, bytenr, num_bytes, + parent, ref_root, level - 1, 0); + if (ret) + goto fail; +@@ -7331,17 +7332,17 @@ void btrfs_free_tree_block(struct btrfs_trans_handle *trans, + + /* Can return -ENOMEM */ + int btrfs_free_extent(struct btrfs_trans_handle *trans, +- struct btrfs_fs_info *fs_info, ++ struct btrfs_root *root, + u64 bytenr, u64 num_bytes, u64 parent, u64 root_objectid, + u64 owner, u64 offset) + { ++ struct btrfs_fs_info *fs_info = root->fs_info; + int old_ref_mod, new_ref_mod; + int ret; + + if (btrfs_is_testing(fs_info)) + return 0; + +- + /* + * tree log blocks never actually go into the extent allocation + * tree, just update pinning info and exit early. +@@ -8308,17 +8309,18 @@ static int alloc_reserved_tree_block(struct btrfs_trans_handle *trans, + } + + int btrfs_alloc_reserved_file_extent(struct btrfs_trans_handle *trans, +- u64 root_objectid, u64 owner, ++ struct btrfs_root *root, u64 owner, + u64 offset, u64 ram_bytes, + struct btrfs_key *ins) + { +- struct btrfs_fs_info *fs_info = trans->fs_info; ++ struct btrfs_fs_info *fs_info = root->fs_info; + int ret; + +- BUG_ON(root_objectid == BTRFS_TREE_LOG_OBJECTID); ++ BUG_ON(root->root_key.objectid == BTRFS_TREE_LOG_OBJECTID); + + ret = btrfs_add_delayed_data_ref(fs_info, trans, ins->objectid, +- ins->offset, 0, root_objectid, owner, ++ ins->offset, 0, ++ root->root_key.objectid, owner, + offset, ram_bytes, + BTRFS_ADD_DELAYED_EXTENT, NULL, NULL); + return ret; +@@ -8896,7 +8898,7 @@ static noinline int do_walk_down(struct btrfs_trans_handle *trans, + ret); + } + } +- ret = btrfs_free_extent(trans, fs_info, bytenr, blocksize, ++ ret = btrfs_free_extent(trans, root, bytenr, blocksize, + parent, root->root_key.objectid, + level - 1, 0); + if (ret) +diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c +index 79945053c7e7..d3c1725f03e4 100644 +--- a/fs/btrfs/file.c ++++ b/fs/btrfs/file.c +@@ -856,7 +856,7 @@ int __btrfs_drop_extents(struct btrfs_trans_handle *trans, + btrfs_mark_buffer_dirty(leaf); + + if (update_refs && disk_bytenr > 0) { +- ret = btrfs_inc_extent_ref(trans, fs_info, ++ ret = btrfs_inc_extent_ref(trans, root, + disk_bytenr, num_bytes, 0, + root->root_key.objectid, + new_key.objectid, +@@ -940,7 +940,7 @@ int __btrfs_drop_extents(struct btrfs_trans_handle *trans, + extent_end = ALIGN(extent_end, + fs_info->sectorsize); + } else if (update_refs && disk_bytenr > 0) { +- ret = btrfs_free_extent(trans, fs_info, ++ ret = btrfs_free_extent(trans, root, + disk_bytenr, num_bytes, 0, + root->root_key.objectid, + key.objectid, key.offset - +@@ -1234,7 +1234,7 @@ int btrfs_mark_extent_written(struct btrfs_trans_handle *trans, + extent_end - split); + btrfs_mark_buffer_dirty(leaf); + +- ret = btrfs_inc_extent_ref(trans, fs_info, bytenr, num_bytes, ++ ret = btrfs_inc_extent_ref(trans, root, bytenr, num_bytes, + 0, root->root_key.objectid, + ino, orig_offset); + if (ret) { +@@ -1268,7 +1268,7 @@ int btrfs_mark_extent_written(struct btrfs_trans_handle *trans, + extent_end = other_end; + del_slot = path->slots[0] + 1; + del_nr++; +- ret = btrfs_free_extent(trans, fs_info, bytenr, num_bytes, ++ ret = btrfs_free_extent(trans, root, bytenr, num_bytes, + 0, root->root_key.objectid, + ino, orig_offset); + if (ret) { +@@ -1288,7 +1288,7 @@ int btrfs_mark_extent_written(struct btrfs_trans_handle *trans, + key.offset = other_start; + del_slot = path->slots[0]; + del_nr++; +- ret = btrfs_free_extent(trans, fs_info, bytenr, num_bytes, ++ ret = btrfs_free_extent(trans, root, bytenr, num_bytes, + 0, root->root_key.objectid, + ino, orig_offset); + if (ret) { +diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c +index 4ddb299af472..a11f87fa79d0 100644 +--- a/fs/btrfs/inode.c ++++ b/fs/btrfs/inode.c +@@ -2218,8 +2218,9 @@ static int insert_reserved_file_extent(struct btrfs_trans_handle *trans, + if (ret < 0) + goto out; + qg_released = ret; +- ret = btrfs_alloc_reserved_file_extent(trans, root->root_key.objectid, +- btrfs_ino(BTRFS_I(inode)), file_pos, qg_released, &ins); ++ ret = btrfs_alloc_reserved_file_extent(trans, root, ++ btrfs_ino(BTRFS_I(inode)), ++ file_pos, qg_released, &ins); + out: + btrfs_free_path(path); + +@@ -2671,7 +2672,7 @@ static noinline int relink_extent_backref(struct btrfs_path *path, + inode_add_bytes(inode, len); + btrfs_release_path(path); + +- ret = btrfs_inc_extent_ref(trans, fs_info, new->bytenr, ++ ret = btrfs_inc_extent_ref(trans, root, new->bytenr, + new->disk_len, 0, + backref->root_id, backref->inum, + new->file_pos); /* start - extent_offset */ +@@ -4665,7 +4666,7 @@ int btrfs_truncate_inode_items(struct btrfs_trans_handle *trans, + root == fs_info->tree_root)) { + btrfs_set_path_blocking(path); + bytes_deleted += extent_num_bytes; +- ret = btrfs_free_extent(trans, fs_info, extent_start, ++ ret = btrfs_free_extent(trans, root, extent_start, + extent_num_bytes, 0, + btrfs_header_owner(leaf), + ino, extent_offset); +diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c +index f969c034d7b3..847d318756d4 100644 +--- a/fs/btrfs/ioctl.c ++++ b/fs/btrfs/ioctl.c +@@ -3694,7 +3694,7 @@ static int btrfs_clone(struct inode *src, struct inode *inode, + if (disko) { + inode_add_bytes(inode, datal); + ret = btrfs_inc_extent_ref(trans, +- fs_info, ++ root, + disko, diskl, 0, + root->root_key.objectid, + btrfs_ino(BTRFS_I(inode)), +diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c +index 9841faef08ea..7d506a3e46dd 100644 +--- a/fs/btrfs/relocation.c ++++ b/fs/btrfs/relocation.c +@@ -1742,7 +1742,7 @@ int replace_file_extents(struct btrfs_trans_handle *trans, + dirty = 1; + + key.offset -= btrfs_file_extent_offset(leaf, fi); +- ret = btrfs_inc_extent_ref(trans, fs_info, new_bytenr, ++ ret = btrfs_inc_extent_ref(trans, root, new_bytenr, + num_bytes, parent, + btrfs_header_owner(leaf), + key.objectid, key.offset); +@@ -1751,7 +1751,7 @@ int replace_file_extents(struct btrfs_trans_handle *trans, + break; + } + +- ret = btrfs_free_extent(trans, fs_info, bytenr, num_bytes, ++ ret = btrfs_free_extent(trans, root, bytenr, num_bytes, + parent, btrfs_header_owner(leaf), + key.objectid, key.offset); + if (ret) { +@@ -1952,21 +1952,21 @@ int replace_path(struct btrfs_trans_handle *trans, + path->slots[level], old_ptr_gen); + btrfs_mark_buffer_dirty(path->nodes[level]); + +- ret = btrfs_inc_extent_ref(trans, fs_info, old_bytenr, ++ ret = btrfs_inc_extent_ref(trans, src, old_bytenr, + blocksize, path->nodes[level]->start, + src->root_key.objectid, level - 1, 0); + BUG_ON(ret); +- ret = btrfs_inc_extent_ref(trans, fs_info, new_bytenr, ++ ret = btrfs_inc_extent_ref(trans, dest, new_bytenr, + blocksize, 0, dest->root_key.objectid, + level - 1, 0); + BUG_ON(ret); + +- ret = btrfs_free_extent(trans, fs_info, new_bytenr, blocksize, ++ ret = btrfs_free_extent(trans, src, new_bytenr, blocksize, + path->nodes[level]->start, + src->root_key.objectid, level - 1, 0); + BUG_ON(ret); + +- ret = btrfs_free_extent(trans, fs_info, old_bytenr, blocksize, ++ ret = btrfs_free_extent(trans, dest, old_bytenr, blocksize, + 0, dest->root_key.objectid, level - 1, + 0); + BUG_ON(ret); +@@ -2808,7 +2808,7 @@ static int do_relocation(struct btrfs_trans_handle *trans, + trans->transid); + btrfs_mark_buffer_dirty(upper->eb); + +- ret = btrfs_inc_extent_ref(trans, root->fs_info, ++ ret = btrfs_inc_extent_ref(trans, root, + node->eb->start, blocksize, + upper->eb->start, + btrfs_header_owner(upper->eb), +diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c +index 1036ac7313a7..aa7c71cff575 100644 +--- a/fs/btrfs/tree-log.c ++++ b/fs/btrfs/tree-log.c +@@ -717,7 +717,7 @@ static noinline int replay_one_extent(struct btrfs_trans_handle *trans, + ret = btrfs_lookup_data_extent(fs_info, ins.objectid, + ins.offset); + if (ret == 0) { +- ret = btrfs_inc_extent_ref(trans, fs_info, ++ ret = btrfs_inc_extent_ref(trans, root, + ins.objectid, ins.offset, + 0, root->root_key.objectid, + key->objectid, offset); + diff --git a/patches.suse/0003-btrfs-rename-do_chunk_alloc-to-btrfs_chunk_alloc.patch b/patches.suse/0003-btrfs-rename-do_chunk_alloc-to-btrfs_chunk_alloc.patch new file mode 100644 index 0000000..a0b620c --- /dev/null +++ b/patches.suse/0003-btrfs-rename-do_chunk_alloc-to-btrfs_chunk_alloc.patch @@ -0,0 +1,153 @@ +From: Josef Bacik +Date: Tue, 18 Jun 2019 16:09:17 -0400 +Subject: btrfs: rename do_chunk_alloc to btrfs_chunk_alloc +Git-commit: fc471cb0c8f0016ac7ec5cc3e329c5e23d83d593 +Patch-mainline: v5.3-rc1 +References: bsc#1165949 + +Really we just need the enum, but as we break more things up it'll help +to have this external to extent-tree.c. + +Reviewed-by: Nikolay Borisov +Signed-off-by: Josef Bacik +Signed-off-by: David Sterba +Acked-by: Nikolay Borisov +--- + fs/btrfs/ctree.h | 22 ++++++++++++++++++++++ + fs/btrfs/extent-tree.c | 38 ++++++++------------------------------ + 2 files changed, 30 insertions(+), 30 deletions(-) + +--- a/fs/btrfs/ctree.h ++++ b/fs/btrfs/ctree.h +@@ -2772,6 +2772,28 @@ enum btrfs_flush_state { + COMMIT_TRANS = 9, + }; + ++/* ++ * control flags for do_chunk_alloc's force field ++ * CHUNK_ALLOC_NO_FORCE means to only allocate a chunk ++ * if we really need one. ++ * ++ * CHUNK_ALLOC_LIMITED means to only try and allocate one ++ * if we have very few chunks already allocated. This is ++ * used as part of the clustering code to help make sure ++ * we have a good pool of storage to cluster in, without ++ * filling the FS with empty chunks ++ * ++ * CHUNK_ALLOC_FORCE means it must try to allocate one ++ * ++ */ ++enum btrfs_chunk_alloc_enum { ++ CHUNK_ALLOC_NO_FORCE, ++ CHUNK_ALLOC_LIMITED, ++ CHUNK_ALLOC_FORCE, ++}; ++ ++int btrfs_chunk_alloc(struct btrfs_trans_handle *trans, u64 flags, ++ enum btrfs_chunk_alloc_enum force); + int btrfs_alloc_data_chunk_ondemand(struct btrfs_inode *inode, u64 bytes); + int btrfs_check_data_free_space(struct inode *inode, + struct extent_changeset **reserved, u64 start, u64 len); +--- a/fs/btrfs/extent-tree.c ++++ b/fs/btrfs/extent-tree.c +@@ -44,26 +44,6 @@ + #undef SCRAMBLE_DELAYED_REFS + + /* +- * control flags for do_chunk_alloc's force field +- * CHUNK_ALLOC_NO_FORCE means to only allocate a chunk +- * if we really need one. +- * +- * CHUNK_ALLOC_LIMITED means to only try and allocate one +- * if we have very few chunks already allocated. This is +- * used as part of the clustering code to help make sure +- * we have a good pool of storage to cluster in, without +- * filling the FS with empty chunks +- * +- * CHUNK_ALLOC_FORCE means it must try to allocate one +- * +- */ +-enum { +- CHUNK_ALLOC_NO_FORCE = 0, +- CHUNK_ALLOC_LIMITED = 1, +- CHUNK_ALLOC_FORCE = 2, +-}; +- +-/* + * Declare a helper function to detect underflow of various space info members + */ + #define DECLARE_SPACE_INFO_UPDATE(name) \ +@@ -106,8 +86,6 @@ static int alloc_reserved_tree_block(str + u64 parent, u64 root_objectid, + u64 flags, struct btrfs_disk_key *key, + int level, struct btrfs_key *ins); +-static int do_chunk_alloc(struct btrfs_trans_handle *trans, u64 flags, +- int force); + static int find_next_key(struct btrfs_path *path, int level, + struct btrfs_key *key); + static void dump_space_info(struct btrfs_fs_info *fs_info, +@@ -4368,7 +4346,7 @@ alloc: + if (IS_ERR(trans)) + return PTR_ERR(trans); + +- ret = do_chunk_alloc(trans, alloc_target, ++ ret = btrfs_chunk_alloc(trans, alloc_target, + CHUNK_ALLOC_NO_FORCE); + btrfs_end_transaction(trans); + if (ret < 0) { +@@ -4649,8 +4627,8 @@ void check_system_chunk(struct btrfs_tra + * - return 1 if it successfully allocates a chunk, + * - return errors including -ENOSPC otherwise. + */ +-static int do_chunk_alloc(struct btrfs_trans_handle *trans, u64 flags, +- int force) ++int btrfs_chunk_alloc(struct btrfs_trans_handle *trans, u64 flags, ++ enum btrfs_chunk_alloc_enum force) + { + struct btrfs_fs_info *fs_info = trans->fs_info; + struct btrfs_space_info *space_info; +@@ -5097,7 +5075,7 @@ static int flush_space(struct btrfs_fs_i + ret = PTR_ERR(trans); + break; + } +- ret = do_chunk_alloc(trans, ++ ret = btrfs_chunk_alloc(trans, + btrfs_metadata_alloc_profile(fs_info), + (state == ALLOC_CHUNK) ? + CHUNK_ALLOC_NO_FORCE : CHUNK_ALLOC_FORCE); +@@ -8143,7 +8121,7 @@ loop: + goto out; + } + +- ret = do_chunk_alloc(trans, flags, CHUNK_ALLOC_FORCE); ++ ret = btrfs_chunk_alloc(trans, flags, CHUNK_ALLOC_FORCE); + + /* + * If we can't allocate a new chunk we've already looped +@@ -9819,7 +9797,7 @@ again: + */ + alloc_flags = update_block_group_flags(fs_info, cache->flags); + if (alloc_flags != cache->flags) { +- ret = do_chunk_alloc(trans, alloc_flags, ++ ret = btrfs_chunk_alloc(trans, alloc_flags, + CHUNK_ALLOC_FORCE); + /* + * ENOSPC is allowed here, we may have enough space +@@ -9836,7 +9814,7 @@ again: + if (!ret) + goto out; + alloc_flags = get_alloc_profile(fs_info, cache->space_info->flags); +- ret = do_chunk_alloc(trans, alloc_flags, CHUNK_ALLOC_FORCE); ++ ret = btrfs_chunk_alloc(trans, alloc_flags, CHUNK_ALLOC_FORCE); + if (ret < 0) + goto out; + ret = inc_block_group_ro(cache, 0); +@@ -9858,7 +9836,7 @@ int btrfs_force_chunk_alloc(struct btrfs + { + u64 alloc_flags = get_alloc_profile(fs_info, type); + +- return do_chunk_alloc(trans, alloc_flags, CHUNK_ALLOC_FORCE); ++ return btrfs_chunk_alloc(trans, alloc_flags, CHUNK_ALLOC_FORCE); + } + + /* diff --git a/patches.suse/0003-btrfs-sink-get_extent-parameter-to-extent_write_full.patch b/patches.suse/0003-btrfs-sink-get_extent-parameter-to-extent_write_full.patch new file mode 100644 index 0000000..cfa4398 --- /dev/null +++ b/patches.suse/0003-btrfs-sink-get_extent-parameter-to-extent_write_full.patch @@ -0,0 +1,66 @@ +From deac642d7e0fd83efd3372c4093fe60ac7436db6 Mon Sep 17 00:00:00 2001 +From: David Sterba +Date: Fri, 23 Jun 2017 03:47:28 +0200 +Patch-mainline: v4.16 +Git-commit: deac642d7e0fd83efd3372c4093fe60ac7436db6 +References: bsc#1168273 +Subject: [PATCH 3/7] btrfs: sink get_extent parameter to + extent_write_full_page + +There's only one caller. + +Signed-off-by: David Sterba +--- + fs/btrfs/extent_io.c | 3 +-- + fs/btrfs/extent_io.h | 1 - + fs/btrfs/inode.c | 2 +- + 3 files changed, 2 insertions(+), 4 deletions(-) + +diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c +index d9a76e33ac3c..7754124b07b8 100644 +--- a/fs/btrfs/extent_io.c ++++ b/fs/btrfs/extent_io.c +@@ -4058,14 +4058,13 @@ static noinline void flush_write_bio(void *data) + } + + int extent_write_full_page(struct extent_io_tree *tree, struct page *page, +- get_extent_t *get_extent, + struct writeback_control *wbc) + { + int ret; + struct extent_page_data epd = { + .bio = NULL, + .tree = tree, +- .get_extent = get_extent, ++ .get_extent = btrfs_get_extent, + .extent_locked = 0, + .sync_io = wbc->sync_mode == WB_SYNC_ALL, + }; +diff --git a/fs/btrfs/extent_io.h b/fs/btrfs/extent_io.h +index b67fc0153b73..abe4feea1539 100644 +--- a/fs/btrfs/extent_io.h ++++ b/fs/btrfs/extent_io.h +@@ -404,7 +404,6 @@ int find_first_extent_bit(struct extent_io_tree *tree, u64 start, + int extent_invalidatepage(struct extent_io_tree *tree, + struct page *page, unsigned long offset); + int extent_write_full_page(struct extent_io_tree *tree, struct page *page, +- get_extent_t *get_extent, + struct writeback_control *wbc); + int extent_write_locked_range(struct extent_io_tree *tree, struct inode *inode, + u64 start, u64 end, int mode); +diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c +index ae62d59edd4b..7403ef8856bd 100644 +--- a/fs/btrfs/inode.c ++++ b/fs/btrfs/inode.c +@@ -8891,7 +8891,7 @@ static int btrfs_writepage(struct page *page, struct writeback_control *wbc) + return AOP_WRITEPAGE_ACTIVATE; + } + tree = &BTRFS_I(page->mapping->host)->io_tree; +- ret = extent_write_full_page(tree, page, btrfs_get_extent, wbc); ++ ret = extent_write_full_page(tree, page, wbc); + btrfs_add_delayed_iput(inode); + return ret; + } +-- +2.26.0 + diff --git a/patches.suse/0003-drm-i915-userptr-fix-size-calculation.patch b/patches.suse/0003-drm-i915-userptr-fix-size-calculation.patch new file mode 100644 index 0000000..f1ce5c5 --- /dev/null +++ b/patches.suse/0003-drm-i915-userptr-fix-size-calculation.patch @@ -0,0 +1,84 @@ +From ecc4d2a52df65479de5e333a9065ed02202a400f Mon Sep 17 00:00:00 2001 +From: Matthew Auld +Date: Fri, 17 Jan 2020 13:24:13 +0000 +Subject: drm/i915/userptr: fix size calculation +Git-commit: ecc4d2a52df65479de5e333a9065ed02202a400f +Patch-mainline: v5.5 +References: bsc#1114279 + +If we create a rather large userptr object(e.g 1ULL << 32) we might +shift past the type-width of num_pages: (int)num_pages << PAGE_SHIFT, +resulting in a totally bogus sg_table, which fortunately will eventually +manifest as: + +gen8_ppgtt_insert_huge:463 GEM_BUG_ON(iter->sg->length < page_size) +kernel BUG at drivers/gpu/drm/i915/gt/gen8_ppgtt.c:463! + +v2: more unsigned long + prefer I915_GTT_PAGE_SIZE + +Fixes: 5cc9ed4b9a7a ("drm/i915: Introduce mapping of user pages into video memory (userptr) ioctl") +Signed-off-by: Matthew Auld +Cc: Chris Wilson +Reviewed-by: Chris Wilson +Signed-off-by: Chris Wilson +Link: https://patchwork.freedesktop.org/patch/msgid/20200117132413.1170563-2-matthew.auld@intel.com +(cherry picked from commit 8e78871bc1e5efec22c950d3fd24ddb63d4ff28a) +Signed-off-by: Joonas Lahtinen +Acked-by: Thomas Zimmermann +--- + drivers/gpu/drm/i915/i915_gem_gtt.c | 2 ++ + drivers/gpu/drm/i915/i915_gem_userptr.c | 4 ++-- + 2 files changed, 4 insertions(+), 2 deletions(-) + +--- a/drivers/gpu/drm/i915/i915_gem_gtt.c ++++ b/drivers/gpu/drm/i915/i915_gem_gtt.c +@@ -969,6 +969,7 @@ gen8_ppgtt_insert_pte_entries(struct i91 + pd = pdp->page_directory[idx->pdpe]; + vaddr = kmap_atomic_px(pd->page_table[idx->pde]); + do { ++ GEM_BUG_ON(iter->sg->length < I915_GTT_PAGE_SIZE); + vaddr[idx->pte] = pte_encode | iter->dma; + + iter->dma += I915_GTT_PAGE_SIZE; +@@ -1744,6 +1745,7 @@ static void gen6_ppgtt_insert_entries(st + + vaddr = kmap_atomic_px(ppgtt->pd.page_table[act_pt]); + do { ++ GEM_BUG_ON(iter.sg->length < I915_GTT_PAGE_SIZE); + vaddr[act_pte] = pte_encode | GEN6_PTE_ADDR_ENCODE(iter.dma); + + iter.dma += I915_GTT_PAGE_SIZE; +--- a/drivers/gpu/drm/i915/i915_gem_userptr.c ++++ b/drivers/gpu/drm/i915/i915_gem_userptr.c +@@ -452,7 +452,7 @@ err: + + static struct sg_table * + __i915_gem_userptr_alloc_pages(struct drm_i915_gem_object *obj, +- struct page **pvec, int num_pages) ++ struct page **pvec, unsigned long num_pages) + { + unsigned int max_segment = i915_sg_segment_size(); + struct sg_table *st; +@@ -512,9 +512,10 @@ __i915_gem_userptr_get_pages_worker(stru + { + struct get_pages_work *work = container_of(_work, typeof(*work), work); + struct drm_i915_gem_object *obj = work->obj; +- const int npages = obj->base.size >> PAGE_SHIFT; ++ const unsigned long npages = obj->base.size >> PAGE_SHIFT; ++ unsigned long pinned; + struct page **pvec; +- int pinned, ret; ++ int ret; + + ret = -ENOMEM; + pinned = 0; +@@ -618,7 +619,7 @@ __i915_gem_userptr_get_pages_schedule(st + + static int i915_gem_userptr_get_pages(struct drm_i915_gem_object *obj) + { +- const int num_pages = obj->base.size >> PAGE_SHIFT; ++ const unsigned long num_pages = obj->base.size >> PAGE_SHIFT; + struct mm_struct *mm = obj->userptr.mm->mm; + struct page **pvec; + struct sg_table *pages; diff --git a/patches.suse/0003-md-introduce-new-personality-funciton-start.patch b/patches.suse/0003-md-introduce-new-personality-funciton-start.patch new file mode 100644 index 0000000..cddea85 --- /dev/null +++ b/patches.suse/0003-md-introduce-new-personality-funciton-start.patch @@ -0,0 +1,261 @@ +From d5d885fd514fcebc9da5503c88aa0112df7514ef Mon Sep 17 00:00:00 2001 +From: Song Liu +Date: Sun, 19 Nov 2017 22:17:01 -0800 +Subject: [PATCH] md: introduce new personality funciton start() +Git-commit: d5d885fd514fcebc9da5503c88aa0112df7514ef +Patch-mainline: v4.16-rc1 +References: bsc#1166003 + +In do_md_run(), md threads should not wake up until the array is fully +initialized in md_run(). However, in raid5_run(), raid5-cache may wake +up mddev->thread to flush stripes that need to be written back. This +design doesn't break badly right now. But it could lead to bad bug in +the future. + +This patch tries to resolve this problem by splitting start up work +into two personality functions, run() and start(). Tasks that do not +require the md threads should go into run(), while task that require +the md threads go into start(). + +r5l_load_log() is moved to raid5_start(), so it is not called until +the md threads are started in do_md_run(). + +Signed-off-by: Song Liu +Signed-off-by: Shaohua Li +Signed-off-by: Coly Li + +--- + drivers/md/dm-raid.c | 9 +++++++++ + drivers/md/md.c | 26 ++++++++++++++++++++------ + drivers/md/md.h | 8 ++++++++ + drivers/md/raid5-cache.c | 22 +++++++++++++++++----- + drivers/md/raid5-log.h | 1 + + drivers/md/raid5.c | 10 ++++++++++ + 6 files changed, 65 insertions(+), 11 deletions(-) + +diff --git a/drivers/md/dm-raid.c b/drivers/md/dm-raid.c +index 6319d846e0ad..e5ef0757fe23 100644 +--- a/drivers/md/dm-raid.c ++++ b/drivers/md/dm-raid.c +@@ -3151,6 +3151,14 @@ static int raid_ctr(struct dm_target *ti, unsigned int argc, char **argv) + goto bad; + } + ++ r = md_start(&rs->md); ++ ++ if (r) { ++ ti->error = "Failed to start raid array"; ++ mddev_unlock(&rs->md); ++ goto bad_md_start; ++ } ++ + rs->callbacks.congested_fn = raid_is_congested; + dm_table_add_target_callbacks(ti->table, &rs->callbacks); + +@@ -3198,6 +3206,7 @@ static int raid_ctr(struct dm_target *ti, unsigned int argc, char **argv) + mddev_unlock(&rs->md); + return 0; + ++bad_md_start: + bad_journal_mode_set: + bad_stripe_cache: + bad_check_reshape: +diff --git a/drivers/md/md.c b/drivers/md/md.c +index 4e4dee0ec2de..a71adb3c34b9 100644 +--- a/drivers/md/md.c ++++ b/drivers/md/md.c +@@ -5560,11 +5560,6 @@ int md_run(struct mddev *mddev) + if (start_readonly && mddev->ro == 0) + mddev->ro = 2; /* read-only, but switch on first write */ + +- /* +- * NOTE: some pers->run(), for example r5l_recovery_log(), wakes +- * up mddev->thread. It is important to initialize critical +- * resources for mddev->thread BEFORE calling pers->run(). +- */ + err = pers->run(mddev); + if (err) + pr_warn("md: pers->run() failed ...\n"); +@@ -5678,6 +5673,9 @@ static int do_md_run(struct mddev *mddev) + if (mddev_is_clustered(mddev)) + md_allow_write(mddev); + ++ /* run start up tasks that require md_thread */ ++ md_start(mddev); ++ + md_wakeup_thread(mddev->thread); + md_wakeup_thread(mddev->sync_thread); /* possibly kick off a reshape */ + +@@ -5689,6 +5687,21 @@ static int do_md_run(struct mddev *mddev) + return err; + } + ++int md_start(struct mddev *mddev) ++{ ++ int ret = 0; ++ ++ if (mddev->pers->start) { ++ set_bit(MD_RECOVERY_WAIT, &mddev->recovery); ++ md_wakeup_thread(mddev->thread); ++ ret = mddev->pers->start(mddev); ++ clear_bit(MD_RECOVERY_WAIT, &mddev->recovery); ++ md_wakeup_thread(mddev->sync_thread); ++ } ++ return ret; ++} ++EXPORT_SYMBOL_GPL(md_start); ++ + static int restart_array(struct mddev *mddev) + { + struct gendisk *disk = mddev->gendisk; +@@ -8169,7 +8182,8 @@ void md_do_sync(struct md_thread *thread) + int ret; + + /* just incase thread restarts... */ +- if (test_bit(MD_RECOVERY_DONE, &mddev->recovery)) ++ if (test_bit(MD_RECOVERY_DONE, &mddev->recovery) || ++ test_bit(MD_RECOVERY_WAIT, &mddev->recovery)) + return; + if (mddev->ro) {/* never try to sync a read-only array */ + set_bit(MD_RECOVERY_INTR, &mddev->recovery); +diff --git a/drivers/md/md.h b/drivers/md/md.h +index 7d6bcf0eba0c..be8f72a9e30b 100644 +--- a/drivers/md/md.h ++++ b/drivers/md/md.h +@@ -485,6 +485,7 @@ enum recovery_flags { + MD_RECOVERY_RESHAPE, /* A reshape is happening */ + MD_RECOVERY_FROZEN, /* User request to abort, and not restart, any action */ + MD_RECOVERY_ERROR, /* sync-action interrupted because io-error */ ++ MD_RECOVERY_WAIT, /* waiting for pers->start() to finish */ + }; + + static inline int __must_check mddev_lock(struct mddev *mddev) +@@ -523,7 +524,13 @@ struct md_personality + struct list_head list; + struct module *owner; + bool (*make_request)(struct mddev *mddev, struct bio *bio); ++ /* ++ * start up works that do NOT require md_thread. tasks that ++ * requires md_thread should go into start() ++ */ + int (*run)(struct mddev *mddev); ++ /* start up works that require md threads */ ++ int (*start)(struct mddev *mddev); + void (*free)(struct mddev *mddev, void *priv); + void (*status)(struct seq_file *seq, struct mddev *mddev); + /* error_handler must set ->faulty and clear ->in_sync +@@ -687,6 +694,7 @@ extern int strict_strtoul_scaled(const char *cp, unsigned long *res, int scale); + + extern void mddev_init(struct mddev *mddev); + extern int md_run(struct mddev *mddev); ++extern int md_start(struct mddev *mddev); + extern void md_stop(struct mddev *mddev); + extern void md_stop_writes(struct mddev *mddev); + extern int md_rdev_init(struct md_rdev *rdev); +diff --git a/drivers/md/raid5-cache.c b/drivers/md/raid5-cache.c +index 39f31f07ffe9..f259a5fd3fbd 100644 +--- a/drivers/md/raid5-cache.c ++++ b/drivers/md/raid5-cache.c +@@ -2448,7 +2448,6 @@ static void r5c_recovery_flush_data_only_stripes(struct r5l_log *log, + raid5_release_stripe(sh); + } + +- md_wakeup_thread(conf->mddev->thread); + /* reuse conf->wait_for_quiescent in recovery */ + wait_event(conf->wait_for_quiescent, + atomic_read(&conf->active_stripes) == 0); +@@ -3036,6 +3035,23 @@ static int r5l_load_log(struct r5l_log *log) + return ret; + } + ++int r5l_start(struct r5l_log *log) ++{ ++ int ret; ++ ++ if (!log) ++ return 0; ++ ++ ret = r5l_load_log(log); ++ if (ret) { ++ struct mddev *mddev = log->rdev->mddev; ++ struct r5conf *conf = mddev->private; ++ ++ r5l_exit_log(conf); ++ } ++ return ret; ++} ++ + void r5c_update_on_rdev_error(struct mddev *mddev, struct md_rdev *rdev) + { + struct r5conf *conf = mddev->private; +@@ -3138,13 +3154,9 @@ int r5l_init_log(struct r5conf *conf, struct md_rdev *rdev) + + rcu_assign_pointer(conf->log, log); + +- if (r5l_load_log(log)) +- goto error; +- + set_bit(MD_HAS_JOURNAL, &conf->mddev->flags); + return 0; + +-error: + rcu_assign_pointer(conf->log, NULL); + md_unregister_thread(&log->reclaim_thread); + reclaim_thread: +diff --git a/drivers/md/raid5-log.h b/drivers/md/raid5-log.h +index 284578b0a349..3860041e8b74 100644 +--- a/drivers/md/raid5-log.h ++++ b/drivers/md/raid5-log.h +@@ -32,6 +32,7 @@ extern struct md_sysfs_entry r5c_journal_mode; + extern void r5c_update_on_rdev_error(struct mddev *mddev, + struct md_rdev *rdev); + extern bool r5c_big_stripe_cached(struct r5conf *conf, sector_t sect); ++extern int r5l_start(struct r5l_log *log); + + extern struct dma_async_tx_descriptor * + ops_run_partial_parity(struct stripe_head *sh, struct raid5_percpu *percpu, +diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c +index 98ce4272ace9..5a2a29bd02dd 100644 +--- a/drivers/md/raid5.c ++++ b/drivers/md/raid5.c +@@ -8364,6 +8364,13 @@ static int raid5_change_consistency_policy(struct mddev *mddev, const char *buf) + return err; + } + ++static int raid5_start(struct mddev *mddev) ++{ ++ struct r5conf *conf = mddev->private; ++ ++ return r5l_start(conf->log); ++} ++ + static struct md_personality raid6_personality = + { + .name = "raid6", +@@ -8371,6 +8378,7 @@ static struct md_personality raid6_personality = + .owner = THIS_MODULE, + .make_request = raid5_make_request, + .run = raid5_run, ++ .start = raid5_start, + .free = raid5_free, + .status = raid5_status, + .error_handler = raid5_error, +@@ -8395,6 +8403,7 @@ static struct md_personality raid5_personality = + .owner = THIS_MODULE, + .make_request = raid5_make_request, + .run = raid5_run, ++ .start = raid5_start, + .free = raid5_free, + .status = raid5_status, + .error_handler = raid5_error, +@@ -8420,6 +8429,7 @@ static struct md_personality raid4_personality = + .owner = THIS_MODULE, + .make_request = raid5_make_request, + .run = raid5_run, ++ .start = raid5_start, + .free = raid5_free, + .status = raid5_status, + .error_handler = raid5_error, +-- +2.25.0 + diff --git a/patches.suse/0004-btrfs-delayed-ref-Use-btrfs_ref-to-refactor-btrfs_ad.patch b/patches.suse/0004-btrfs-delayed-ref-Use-btrfs_ref-to-refactor-btrfs_ad.patch index cefdb23..e6c2a2a 100644 --- a/patches.suse/0004-btrfs-delayed-ref-Use-btrfs_ref-to-refactor-btrfs_ad.patch +++ b/patches.suse/0004-btrfs-delayed-ref-Use-btrfs_ref-to-refactor-btrfs_ad.patch @@ -15,8 +15,8 @@ Signed-off-by: David Sterba --- fs/btrfs/delayed-ref.c | 16 ++++++++++++---- fs/btrfs/delayed-ref.h | 4 +--- - fs/btrfs/extent-tree.c | 22 ++++++++++------------ - 3 files changed, 23 insertions(+), 19 deletions(-) + fs/btrfs/extent-tree.c | 23 ++++++++++------------- + 3 files changed, 23 insertions(+), 20 deletions(-) --- a/fs/btrfs/delayed-ref.c +++ b/fs/btrfs/delayed-ref.c @@ -75,7 +75,7 @@ Signed-off-by: David Sterba struct btrfs_trans_handle *trans, --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c -@@ -2128,10 +2128,8 @@ int btrfs_inc_extent_ref(struct btrfs_tr +@@ -2209,10 +2209,8 @@ int btrfs_inc_extent_ref(struct btrfs_tr ret = btrfs_add_delayed_tree_ref(fs_info, trans, &generic_ref, NULL, &old_ref_mod, &new_ref_mod); } else { @@ -88,7 +88,7 @@ Signed-off-by: David Sterba &old_ref_mod, &new_ref_mod); } -@@ -7213,10 +7211,8 @@ int btrfs_free_extent(struct btrfs_trans +@@ -7307,10 +7305,8 @@ int btrfs_free_extent(struct btrfs_trans ret = btrfs_add_delayed_tree_ref(fs_info, trans, &generic_ref, NULL, &old_ref_mod, &new_ref_mod); } else { @@ -101,22 +101,23 @@ Signed-off-by: David Sterba &old_ref_mod, &new_ref_mod); } -@@ -8167,14 +8163,16 @@ int btrfs_alloc_reserved_file_extent(str +@@ -8261,15 +8257,16 @@ int btrfs_alloc_reserved_file_extent(str struct btrfs_key *ins) { - struct btrfs_fs_info *fs_info = trans->fs_info; + struct btrfs_fs_info *fs_info = root->fs_info; + struct btrfs_ref generic_ref = { 0 }; int ret; - BUG_ON(root_objectid == BTRFS_TREE_LOG_OBJECTID); + BUG_ON(root->root_key.objectid == BTRFS_TREE_LOG_OBJECTID); - ret = btrfs_add_delayed_data_ref(fs_info, trans, ins->objectid, -- ins->offset, 0, root_objectid, owner, +- ins->offset, 0, +- root->root_key.objectid, owner, - offset, ram_bytes, - BTRFS_ADD_DELAYED_EXTENT, NULL, NULL); + btrfs_init_generic_ref(&generic_ref, BTRFS_ADD_DELAYED_EXTENT, + ins->objectid, ins->offset, 0); -+ btrfs_init_data_ref(&generic_ref, root_objectid, owner, offset); ++ btrfs_init_data_ref(&generic_ref, root->root_key.objectid, owner, offset); + ret = btrfs_add_delayed_data_ref(fs_info, trans, &generic_ref, + ram_bytes, NULL, NULL); return ret; diff --git a/patches.suse/0004-btrfs-drop-get_extent-from-extent_page_data.patch b/patches.suse/0004-btrfs-drop-get_extent-from-extent_page_data.patch new file mode 100644 index 0000000..9cf6c0e --- /dev/null +++ b/patches.suse/0004-btrfs-drop-get_extent-from-extent_page_data.patch @@ -0,0 +1,69 @@ +From 3c98c62f7a761ab132950cf36795c8001be72b47 Mon Sep 17 00:00:00 2001 +From: David Sterba +Date: Fri, 23 Jun 2017 04:01:08 +0200 +Patch-mainline: v4.16 +Git-commit: 3c98c62f7a761ab132950cf36795c8001be72b47 +References: bsc#1168273 +Subject: [PATCH 4/7] btrfs: drop get_extent from extent_page_data + +Previous patches cleaned up all places where +extent_page_data::get_extent was set and it was btrfs_get_extent all the +time, so we can simply call that instead. + +This also reduces size of extent_page_data by 8 bytes which has positive +effect on stack consumption on various functions on the write out path. + +Signed-off-by: David Sterba +--- + fs/btrfs/extent_io.c | 7 +------ + 1 file changed, 1 insertion(+), 6 deletions(-) + +diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c +index 7754124b07b8..3ecd3ab73981 100644 +--- a/fs/btrfs/extent_io.c ++++ b/fs/btrfs/extent_io.c +@@ -109,8 +109,6 @@ struct tree_entry { + struct extent_page_data { + struct bio *bio; + struct extent_io_tree *tree; +- get_extent_t *get_extent; +- + /* tells writepage not to lock the state bits for this range + * it still does the unlocking + */ +@@ -3373,7 +3371,7 @@ static noinline_for_stack int __extent_writepage_io(struct inode *inode, + page_end, NULL, 1); + break; + } +- em = epd->get_extent(BTRFS_I(inode), page, pg_offset, cur, ++ em = btrfs_get_extent(BTRFS_I(inode), page, pg_offset, cur, + end - cur + 1, 1); + if (IS_ERR_OR_NULL(em)) { + SetPageError(page); +@@ -4064,7 +4062,6 @@ int extent_write_full_page(struct extent_io_tree *tree, struct page *page, + struct extent_page_data epd = { + .bio = NULL, + .tree = tree, +- .get_extent = btrfs_get_extent, + .extent_locked = 0, + .sync_io = wbc->sync_mode == WB_SYNC_ALL, + }; +@@ -4087,7 +4084,6 @@ int extent_write_locked_range(struct extent_io_tree *tree, struct inode *inode, + struct extent_page_data epd = { + .bio = NULL, + .tree = tree, +- .get_extent = btrfs_get_extent, + .extent_locked = 1, + .sync_io = mode == WB_SYNC_ALL, + }; +@@ -4125,7 +4121,6 @@ int extent_writepages(struct extent_io_tree *tree, + struct extent_page_data epd = { + .bio = NULL, + .tree = tree, +- .get_extent = btrfs_get_extent, + .extent_locked = 0, + .sync_io = wbc->sync_mode == WB_SYNC_ALL, + }; +-- +2.26.0 + diff --git a/patches.suse/0004-btrfs-export-space_info_add_-bytes.patch b/patches.suse/0004-btrfs-export-space_info_add_-bytes.patch new file mode 100644 index 0000000..ef25b82 --- /dev/null +++ b/patches.suse/0004-btrfs-export-space_info_add_-bytes.patch @@ -0,0 +1,138 @@ +From: Josef Bacik +Date: Tue, 18 Jun 2019 16:09:18 -0400 +Subject: btrfs: export space_info_add_*_bytes +Git-commit: d44b72aa12d0a74b67ffabdcab2f64653282dccd +Patch-mainline: v5.3-rc1 +References: bsc#1165949 + +Prep work for consolidating all of the space_info code into one file. +We need to export these so multiple files can use them. + +Reviewed-by: Nikolay Borisov +Signed-off-by: Josef Bacik +Signed-off-by: David Sterba +Acked-by: Nikolay Borisov +--- + fs/btrfs/extent-tree.c | 40 ++++++++++++++++++---------------------- + fs/btrfs/space-info.h | 7 +++++++ + 2 files changed, 25 insertions(+), 22 deletions(-) + +--- a/fs/btrfs/extent-tree.c ++++ b/fs/btrfs/extent-tree.c +@@ -97,12 +97,6 @@ static int __reserve_metadata_bytes(stru + struct btrfs_space_info *space_info, + u64 orig_bytes, + enum btrfs_reserve_flush_enum flush); +-static void space_info_add_new_bytes(struct btrfs_fs_info *fs_info, +- struct btrfs_space_info *space_info, +- u64 num_bytes); +-static void space_info_add_old_bytes(struct btrfs_fs_info *fs_info, +- struct btrfs_space_info *space_info, +- u64 num_bytes); + + static noinline int + block_group_cache_done(struct btrfs_block_group_cache *cache) +@@ -4131,8 +4125,8 @@ static void update_space_info(struct btr + found->bytes_readonly += bytes_readonly; + if (total_bytes > 0) + found->full = 0; +- space_info_add_new_bytes(info, found, total_bytes - +- bytes_used - bytes_readonly); ++ btrfs_space_info_add_new_bytes(info, found, total_bytes - ++ bytes_used - bytes_readonly); + spin_unlock(&found->lock); + *space_info = found; + } +@@ -5319,7 +5313,8 @@ static int wait_reserve_ticket(struct bt + spin_unlock(&space_info->lock); + + if (reclaim_bytes) +- space_info_add_old_bytes(fs_info, space_info, reclaim_bytes); ++ btrfs_space_info_add_old_bytes(fs_info, space_info, ++ reclaim_bytes); + return ret; + } + +@@ -5434,7 +5429,8 @@ static int __reserve_metadata_bytes(stru + spin_unlock(&space_info->lock); + + if (reclaim_bytes) +- space_info_add_old_bytes(fs_info, space_info, reclaim_bytes); ++ btrfs_space_info_add_old_bytes(fs_info, space_info, ++ reclaim_bytes); + ASSERT(list_empty(&ticket.list)); + return ret; + } +@@ -5594,8 +5590,8 @@ void btrfs_migrate_to_delayed_refs_rsv(s + trace_btrfs_space_reservation(fs_info, "delayed_refs_rsv", + 0, num_bytes, 1); + if (to_free) +- space_info_add_old_bytes(fs_info, delayed_refs_rsv->space_info, +- to_free); ++ btrfs_space_info_add_old_bytes(fs_info, ++ delayed_refs_rsv->space_info, to_free); + } + + /** +@@ -5638,9 +5634,9 @@ int btrfs_delayed_refs_rsv_refill(struct + * This is for space we already have accounted in space_info->bytes_may_use, so + * basically when we're returning space from block_rsv's. + */ +-static void space_info_add_old_bytes(struct btrfs_fs_info *fs_info, +- struct btrfs_space_info *space_info, +- u64 num_bytes) ++void btrfs_space_info_add_old_bytes(struct btrfs_fs_info *fs_info, ++ struct btrfs_space_info *space_info, ++ u64 num_bytes) + { + struct reserve_ticket *ticket; + struct list_head *head; +@@ -5701,9 +5697,9 @@ again: + * space_info->bytes_may_use yet. So if we allocate a chunk or unpin an extent + * we use this helper. + */ +-static void space_info_add_new_bytes(struct btrfs_fs_info *fs_info, +- struct btrfs_space_info *space_info, +- u64 num_bytes) ++void btrfs_space_info_add_new_bytes(struct btrfs_fs_info *fs_info, ++ struct btrfs_space_info *space_info, ++ u64 num_bytes) + { + struct reserve_ticket *ticket; + struct list_head *head = &space_info->priority_tickets; +@@ -5786,8 +5782,8 @@ static u64 block_rsv_release_bytes(struc + spin_unlock(&dest->lock); + } + if (num_bytes) +- space_info_add_old_bytes(fs_info, space_info, +- num_bytes); ++ btrfs_space_info_add_old_bytes(fs_info, space_info, ++ num_bytes); + } + if (qgroup_to_release_ret) + *qgroup_to_release_ret = qgroup_to_release; +@@ -7011,8 +7007,8 @@ static int unpin_extent_range(struct btr + spin_unlock(&global_rsv->lock); + /* Add to any tickets we may have */ + if (len) +- space_info_add_new_bytes(fs_info, space_info, +- len); ++ btrfs_space_info_add_new_bytes(fs_info, ++ space_info, len); + } + spin_unlock(&space_info->lock); + } +--- a/fs/btrfs/space-info.h ++++ b/fs/btrfs/space-info.h +@@ -74,4 +74,11 @@ static inline bool btrfs_mixed_space_inf + (space_info->flags & BTRFS_BLOCK_GROUP_DATA)); + } + ++void btrfs_space_info_add_new_bytes(struct btrfs_fs_info *fs_info, ++ struct btrfs_space_info *space_info, ++ u64 num_bytes); ++void btrfs_space_info_add_old_bytes(struct btrfs_fs_info *fs_info, ++ struct btrfs_space_info *space_info, ++ u64 num_bytes); ++ + #endif /* BTRFS_SPACE_INFO_H */ diff --git a/patches.suse/0004-btrfs-extent_io-Kill-dead-condition-in-extent_write_.patch b/patches.suse/0004-btrfs-extent_io-Kill-dead-condition-in-extent_write_.patch new file mode 100644 index 0000000..9cac914 --- /dev/null +++ b/patches.suse/0004-btrfs-extent_io-Kill-dead-condition-in-extent_write_.patch @@ -0,0 +1,41 @@ +From e06808be8a5296c09be84b3aaf63087b5737ba16 Mon Sep 17 00:00:00 2001 +From: Qu Wenruo +Date: Wed, 20 Mar 2019 14:27:44 +0800 +Patch-mainline: v5.2 +Git-commit: e06808be8a5296c09be84b3aaf63087b5737ba16 +References: bsc#1168273 +Subject: [PATCH 4/7] btrfs: extent_io: Kill dead condition in + extent_write_cache_pages() + +Since __extent_writepage() will no longer return >0 value, +(ret == AOP_WRITEPAGE_ACTIVATE) will never be true. + +Kill that dead branch. + +Reviewed-by: Johannes Thumshirn +Signed-off-by: Qu Wenruo +Reviewed-by: David Sterba +Signed-off-by: David Sterba +--- + fs/btrfs/extent_io.c | 5 ----- + 1 file changed, 5 deletions(-) + +diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c +index 8399fc4b27ae..cd76be7013d8 100644 +--- a/fs/btrfs/extent_io.c ++++ b/fs/btrfs/extent_io.c +@@ -3974,11 +3974,6 @@ static int extent_write_cache_pages(struct address_space *mapping, + } + + ret = __extent_writepage(page, wbc, epd); +- +- if (unlikely(ret == AOP_WRITEPAGE_ACTIVATE)) { +- unlock_page(page); +- ret = 0; +- } + if (ret < 0) { + /* + * done_index is set past this page, +-- +2.26.0 + diff --git a/patches.suse/0004-btrfs-handle-delayed-ref-head-accounting-cleanup-in-.patch b/patches.suse/0004-btrfs-handle-delayed-ref-head-accounting-cleanup-in-.patch index e1be6f2..ffd0b21 100644 --- a/patches.suse/0004-btrfs-handle-delayed-ref-head-accounting-cleanup-in-.patch +++ b/patches.suse/0004-btrfs-handle-delayed-ref-head-accounting-cleanup-in-.patch @@ -52,9 +52,8 @@ Acked-by: Nikolay Borisov --- fs/btrfs/ctree.h | 4 ++++ fs/btrfs/disk-io.c | 1 + - fs/btrfs/extent-tree.c | 13 +++++-------- - fs/btrfs/transaction.c | 2 +- - 4 files changed, 11 insertions(+), 9 deletions(-) + fs/btrfs/extent-tree.c | 12 +++++------- + 3 files changed, 10 insertions(+), 7 deletions(-) --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h @@ -66,7 +65,7 @@ Acked-by: Nikolay Borisov extern struct kmem_cache *btrfs_trans_handle_cachep; extern struct kmem_cache *btrfs_transaction_cachep; extern struct kmem_cache *btrfs_bit_radix_cachep; -@@ -2645,6 +2646,9 @@ int btrfs_run_delayed_refs(struct btrfs_ +@@ -2663,6 +2664,9 @@ int btrfs_run_delayed_refs(struct btrfs_ struct btrfs_fs_info *fs_info, unsigned long count); int btrfs_async_run_delayed_refs(struct btrfs_fs_info *fs_info, unsigned long count, u64 transid, int wait); @@ -78,7 +77,7 @@ Acked-by: Nikolay Borisov struct btrfs_fs_info *fs_info, u64 bytenr, --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c -@@ -4296,6 +4296,7 @@ static int btrfs_destroy_delayed_refs(st +@@ -4298,6 +4298,7 @@ static int btrfs_destroy_delayed_refs(st if (pin_bytes) btrfs_pin_extent(fs_info, head->bytenr, head->num_bytes, 1); @@ -88,7 +87,7 @@ Acked-by: Nikolay Borisov spin_lock(&delayed_refs->lock); --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c -@@ -2494,13 +2494,10 @@ static int cleanup_extent_op(struct btrf +@@ -2589,12 +2589,10 @@ static int run_and_cleanup_extent_op(str return ret ? ret : 1; } @@ -101,11 +100,10 @@ Acked-by: Nikolay Borisov - struct btrfs_fs_info *fs_info = trans->fs_info; - struct btrfs_delayed_ref_root *delayed_refs = - &trans->transaction->delayed_refs; -- + int nr_items = 1; /* Dropping this ref head update. */ + if (head->total_ref_mod < 0) { - struct btrfs_space_info *space_info; - u64 flags; -@@ -2574,7 +2571,7 @@ static int cleanup_ref_head(struct btrfs +@@ -2675,7 +2673,7 @@ static int cleanup_ref_head(struct btrfs } } @@ -114,7 +112,7 @@ Acked-by: Nikolay Borisov trace_run_delayed_ref_head(fs_info, head, 0); btrfs_delayed_ref_unlock(head); -@@ -7116,7 +7113,7 @@ static noinline int check_ref_cleanup(st +@@ -7366,7 +7364,7 @@ static noinline int check_ref_cleanup(st if (head->must_insert_reserved) ret = 1; @@ -123,14 +121,3 @@ Acked-by: Nikolay Borisov mutex_unlock(&head->mutex); btrfs_put_delayed_ref_head(head); return ret; ---- a/fs/btrfs/transaction.c -+++ b/fs/btrfs/transaction.c -@@ -542,7 +542,7 @@ again: - * and then we deadlock with somebody doing a freeze. - * - * If we are ATTACH, it means we just want to catch the current -- * transaction and commit it, so we needn't do sb_start_intwrite(). -+ * transaction and commit it, so we needn't do sb_start_intwrite(). - */ - if (type & __TRANS_FREEZABLE) - sb_start_intwrite(fs_info->sb); diff --git a/patches.suse/0004-btrfs-merge-two-flush_write_bio-helpers.patch b/patches.suse/0004-btrfs-merge-two-flush_write_bio-helpers.patch new file mode 100644 index 0000000..4fd4f17 --- /dev/null +++ b/patches.suse/0004-btrfs-merge-two-flush_write_bio-helpers.patch @@ -0,0 +1,86 @@ +From e2932ee08e46629b0d39eda920e1d795e6d83946 Mon Sep 17 00:00:00 2001 +From: David Sterba +Date: Fri, 23 Jun 2017 04:16:17 +0200 +Patch-mainline: v4.16 +Git-commit: e2932ee08e46629b0d39eda920e1d795e6d83946 +References: bsc#1168273 +Subject: [PATCH 4/7] btrfs: merge two flush_write_bio helpers + +flush_epd_write_bio is same as flush_write_bio, no point having two such +functions. Merge them to flush_write_bio. The 'noinline' attribute is +removed as it does not have any meaning. + +Signed-off-by: David Sterba +--- + fs/btrfs/extent_io.c | 19 ++++++++----------- + 1 file changed, 8 insertions(+), 11 deletions(-) + +diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c +index 6cd3da16f114..f1842d59fffe 100644 +--- a/fs/btrfs/extent_io.c ++++ b/fs/btrfs/extent_io.c +@@ -138,7 +138,8 @@ static void add_extent_changeset(struct extent_state *state, unsigned bits, + BUG_ON(ret < 0); + } + +-static noinline void flush_write_bio(void *data); ++static void flush_write_bio(void *data); ++ + static inline struct btrfs_fs_info * + tree_fs_info(struct extent_io_tree *tree) + { +@@ -4039,8 +4040,10 @@ static int extent_write_cache_pages(struct address_space *mapping, + return ret; + } + +-static void flush_epd_write_bio(struct extent_page_data *epd) ++static void flush_write_bio(void *data) + { ++ struct extent_page_data *epd = data; ++ + if (epd->bio) { + int ret; + +@@ -4050,12 +4053,6 @@ static void flush_epd_write_bio(struct extent_page_data *epd) + } + } + +-static noinline void flush_write_bio(void *data) +-{ +- struct extent_page_data *epd = data; +- flush_epd_write_bio(epd); +-} +- + int extent_write_full_page(struct page *page, struct writeback_control *wbc) + { + int ret; +@@ -4068,7 +4065,7 @@ int extent_write_full_page(struct page *page, struct writeback_control *wbc) + + ret = __extent_writepage(page, wbc, &epd); + +- flush_epd_write_bio(&epd); ++ flush_write_bio(&epd); + return ret; + } + +@@ -4110,7 +4107,7 @@ int extent_write_locked_range(struct inode *inode, u64 start, u64 end, + start += PAGE_SIZE; + } + +- flush_epd_write_bio(&epd); ++ flush_write_bio(&epd); + return ret; + } + +@@ -4128,7 +4125,7 @@ int extent_writepages(struct extent_io_tree *tree, + + ret = extent_write_cache_pages(mapping, wbc, __extent_writepage, &epd, + flush_write_bio); +- flush_epd_write_bio(&epd); ++ flush_write_bio(&epd); + return ret; + } + +-- +2.26.0 + diff --git a/patches.suse/0004-btrfs-migrate-the-block-group-ref-counting-stuff.patch b/patches.suse/0004-btrfs-migrate-the-block-group-ref-counting-stuff.patch new file mode 100644 index 0000000..a192b52 --- /dev/null +++ b/patches.suse/0004-btrfs-migrate-the-block-group-ref-counting-stuff.patch @@ -0,0 +1,117 @@ +From: Josef Bacik +Date: Thu, 20 Jun 2019 15:37:46 -0400 +Subject: btrfs: migrate the block group ref counting stuff +Git-commit: 3cad128400c2445d9140c0f5720018e075ef66c6 +Patch-mainline: v5.4-rc1 +References: bsc#1165949 + +Another easy set to move over to block-group.c. + +Signed-off-by: Josef Bacik +Reviewed-by: David Sterba +Signed-off-by: David Sterba +Acked-by: Nikolay Borisov +--- + fs/btrfs/block-group.c | 25 +++++++++++++++++++++++++ + fs/btrfs/block-group.h | 2 ++ + fs/btrfs/ctree.h | 3 --- + fs/btrfs/extent-tree.c | 25 ------------------------- + 4 files changed, 27 insertions(+), 28 deletions(-) + +--- a/fs/btrfs/block-group.c ++++ b/fs/btrfs/block-group.c +@@ -3,6 +3,31 @@ + #include "ctree.h" + #include "block-group.h" + ++void btrfs_get_block_group(struct btrfs_block_group_cache *cache) ++{ ++ atomic_inc(&cache->count); ++} ++ ++void btrfs_put_block_group(struct btrfs_block_group_cache *cache) ++{ ++ if (atomic_dec_and_test(&cache->count)) { ++ WARN_ON(cache->pinned > 0); ++ WARN_ON(cache->reserved > 0); ++ ++ /* ++ * If not empty, someone is still holding mutex of ++ * full_stripe_lock, which can only be released by caller. ++ * And it will definitely cause use-after-free when caller ++ * tries to release full stripe lock. ++ * ++ * No better way to resolve, but only to warn. ++ */ ++ WARN_ON(!RB_EMPTY_ROOT(&cache->full_stripe_locks_root.root)); ++ kfree(cache->free_space_ctl); ++ kfree(cache); ++ } ++} ++ + /* + * This will return the block group at or after bytenr if contains is 0, else + * it will return the block group that contains the bytenr +--- a/fs/btrfs/block-group.h ++++ b/fs/btrfs/block-group.h +@@ -157,5 +157,7 @@ struct btrfs_block_group_cache *btrfs_lo + struct btrfs_fs_info *info, u64 bytenr); + struct btrfs_block_group_cache *btrfs_next_block_group( + struct btrfs_block_group_cache *cache); ++void btrfs_get_block_group(struct btrfs_block_group_cache *cache); ++void btrfs_put_block_group(struct btrfs_block_group_cache *cache); + + #endif /* BTRFS_BLOCK_GROUP_H */ +--- a/fs/btrfs/ctree.h ++++ b/fs/btrfs/ctree.h +@@ -2461,7 +2461,6 @@ void btrfs_wait_block_group_reservations + bool btrfs_inc_nocow_writers(struct btrfs_fs_info *fs_info, u64 bytenr); + void btrfs_dec_nocow_writers(struct btrfs_fs_info *fs_info, u64 bytenr); + void btrfs_wait_nocow_writers(struct btrfs_block_group_cache *bg); +-void btrfs_put_block_group(struct btrfs_block_group_cache *cache); + int btrfs_run_delayed_refs(struct btrfs_trans_handle *trans, + struct btrfs_fs_info *fs_info, unsigned long count); + int btrfs_async_run_delayed_refs(struct btrfs_fs_info *fs_info, +@@ -2481,8 +2480,6 @@ int btrfs_exclude_logged_extents(struct + struct extent_buffer *eb); + int btrfs_cross_ref_exist(struct btrfs_root *root, + u64 objectid, u64 offset, u64 bytenr); +-void btrfs_get_block_group(struct btrfs_block_group_cache *cache); +-void btrfs_put_block_group(struct btrfs_block_group_cache *cache); + int get_block_group_index(struct btrfs_block_group_cache *cache); + struct extent_buffer *btrfs_alloc_tree_block(struct btrfs_trans_handle *trans, + struct btrfs_root *root, +--- a/fs/btrfs/extent-tree.c ++++ b/fs/btrfs/extent-tree.c +@@ -89,31 +89,6 @@ static int block_group_bits(struct btrfs + return (cache->flags & bits) == bits; + } + +-void btrfs_get_block_group(struct btrfs_block_group_cache *cache) +-{ +- atomic_inc(&cache->count); +-} +- +-void btrfs_put_block_group(struct btrfs_block_group_cache *cache) +-{ +- if (atomic_dec_and_test(&cache->count)) { +- WARN_ON(cache->pinned > 0); +- WARN_ON(cache->reserved > 0); +- +- /* +- * If not empty, someone is still holding mutex of +- * full_stripe_lock, which can only be released by caller. +- * And it will definitely cause use-after-free when caller +- * tries to release full stripe lock. +- * +- * No better way to resolve, but only to warn. +- */ +- WARN_ON(!RB_EMPTY_ROOT(&cache->full_stripe_locks_root.root)); +- kfree(cache->free_space_ctl); +- kfree(cache); +- } +-} +- + /* + * this adds the block group to the fs_info rb tree for the block group + * cache diff --git a/patches.suse/0004-btrfs-only-track-ref_heads-in-delayed_ref_updates.patch b/patches.suse/0004-btrfs-only-track-ref_heads-in-delayed_ref_updates.patch new file mode 100644 index 0000000..d51590d --- /dev/null +++ b/patches.suse/0004-btrfs-only-track-ref_heads-in-delayed_ref_updates.patch @@ -0,0 +1,47 @@ +From: Josef Bacik +Date: Mon, 3 Dec 2018 10:20:32 -0500 +Subject: btrfs: only track ref_heads in delayed_ref_updates +Git-commit: 158ffa364bf723fa1ef128060646d23dc3942994 +Patch-mainline: v5.0-rc1 +References: bsc#1165949 + +We use this number to figure out how many delayed refs to run, but +__btrfs_run_delayed_refs really only checks every time we need a new +delayed ref head, so we always run at least one ref head completely no +matter what the number of items on it. Fix the accounting to only be +adjusted when we add/remove a ref head. + +In addition to using this number to limit the number of delayed refs +run, a future patch is also going to use it to calculate the amount of +space required for delayed refs space reservation. + +Reviewed-by: Nikolay Borisov +Signed-off-by: Josef Bacik +Signed-off-by: David Sterba +Acked-by: Nikolay Borisov +--- + fs/btrfs/delayed-ref.c | 3 --- + 1 file changed, 3 deletions(-) + +diff --git a/fs/btrfs/delayed-ref.c b/fs/btrfs/delayed-ref.c +index b3e4c9fcb664..48725fa757a3 100644 +--- a/fs/btrfs/delayed-ref.c ++++ b/fs/btrfs/delayed-ref.c +@@ -251,8 +251,6 @@ static inline void drop_delayed_ref(struct btrfs_trans_handle *trans, + ref->in_tree = 0; + btrfs_put_delayed_ref(ref); + atomic_dec(&delayed_refs->num_entries); +- if (trans->delayed_ref_updates) +- trans->delayed_ref_updates--; + } + + static bool merge_ref(struct btrfs_trans_handle *trans, +@@ -467,7 +465,6 @@ static int insert_delayed_ref(struct btrfs_trans_handle *trans, + if (ref->action == BTRFS_ADD_DELAYED_REF) + list_add_tail(&ref->add_list, &href->ref_add_list); + atomic_inc(&root->num_entries); +- trans->delayed_ref_updates++; + spin_unlock(&href->lock); + return ret; + } + diff --git a/patches.suse/0004-btrfs-refactor-priority_reclaim_metadata_space.patch b/patches.suse/0004-btrfs-refactor-priority_reclaim_metadata_space.patch new file mode 100644 index 0000000..30e5dcf --- /dev/null +++ b/patches.suse/0004-btrfs-refactor-priority_reclaim_metadata_space.patch @@ -0,0 +1,69 @@ +From: Josef Bacik +Date: Thu, 1 Aug 2019 18:19:36 -0400 +Subject: btrfs: refactor priority_reclaim_metadata_space +Git-commit: 9ce2f423b9463f975720782b3838640da313ecb4 +Patch-mainline: v5.4-rc1 +References: bsc#1165949 + +With the eviction flushing stuff we'll want to allow for different +states, but still work basically the same way that +priority_reclaim_metadata_space works currently. Refactor this to take +the flushing states and size as an argument so we can use the same logic +for limit flushing and eviction flushing. + +Signed-off-by: Josef Bacik +Reviewed-by: David Sterba +Signed-off-by: David Sterba +Acked-by: Nikolay Borisov +--- + fs/btrfs/space-info.c | 15 +++++++++------ + 1 file changed, 9 insertions(+), 6 deletions(-) + +diff --git a/fs/btrfs/space-info.c b/fs/btrfs/space-info.c +index 8e00f53601ff..37ec31199675 100644 +--- a/fs/btrfs/space-info.c ++++ b/fs/btrfs/space-info.c +@@ -849,8 +849,10 @@ static const enum btrfs_flush_state priority_flush_states[] = { + }; + + static void priority_reclaim_metadata_space(struct btrfs_fs_info *fs_info, +- struct btrfs_space_info *space_info, +- struct reserve_ticket *ticket) ++ struct btrfs_space_info *space_info, ++ struct reserve_ticket *ticket, ++ const enum btrfs_flush_state *states, ++ int states_nr) + { + u64 to_reclaim; + int flush_state; +@@ -866,8 +868,7 @@ static void priority_reclaim_metadata_space(struct btrfs_fs_info *fs_info, + + flush_state = 0; + do { +- flush_space(fs_info, space_info, to_reclaim, +- priority_flush_states[flush_state]); ++ flush_space(fs_info, space_info, to_reclaim, states[flush_state]); + flush_state++; + spin_lock(&space_info->lock); + if (ticket->bytes == 0) { +@@ -875,7 +876,7 @@ static void priority_reclaim_metadata_space(struct btrfs_fs_info *fs_info, + return; + } + spin_unlock(&space_info->lock); +- } while (flush_state < ARRAY_SIZE(priority_flush_states)); ++ } while (flush_state < states_nr); + } + + static void wait_reserve_ticket(struct btrfs_fs_info *fs_info, +@@ -924,7 +925,9 @@ static int handle_reserve_ticket(struct btrfs_fs_info *fs_info, + if (flush == BTRFS_RESERVE_FLUSH_ALL) + wait_reserve_ticket(fs_info, space_info, ticket); + else +- priority_reclaim_metadata_space(fs_info, space_info, ticket); ++ priority_reclaim_metadata_space(fs_info, space_info, ticket, ++ priority_flush_states, ++ ARRAY_SIZE(priority_flush_states)); + + spin_lock(&space_info->lock); + ret = ticket->error; + diff --git a/patches.suse/0004-btrfs-replace-cleaner_delayed_iput_mutex-with-a-waitqueue.patch b/patches.suse/0004-btrfs-replace-cleaner_delayed_iput_mutex-with-a-waitqueue.patch new file mode 100644 index 0000000..894d9f8 --- /dev/null +++ b/patches.suse/0004-btrfs-replace-cleaner_delayed_iput_mutex-with-a-waitqueue.patch @@ -0,0 +1,172 @@ +From: Josef Bacik +Date: Mon, 3 Dec 2018 11:06:52 -0500 +Subject: btrfs: replace cleaner_delayed_iput_mutex with a waitqueue +Git-commit: 034f784d7cab9af731ccd41b34e5e9625ef47db7 +Patch-mainline: v5.1-rc1 +References: bsc#1165949 + +The throttle path doesn't take cleaner_delayed_iput_mutex, which means +we could think we're done flushing iputs in the data space reservation +path when we could have a throttler doing an iput. There's no real +reason to serialize the delayed iput flushing, so instead of taking the +cleaner_delayed_iput_mutex whenever we flush the delayed iputs just +replace it with an atomic counter and a waitqueue. This removes the +short (or long depending on how big the inode is) window where we think +there are no more pending iputs when there really are some. + +The waiting is killable as it could be indirectly called from user +operations like fallocate or zero-range. Such call sites should handle +the error but otherwise it's not necessary. Eg. flush_space just needs +to attempt to make space by waiting on iputs. + +Signed-off-by: Josef Bacik +[ add killable comment and changelog parts ] +Signed-off-by: David Sterba +Acked-by: Nikolay Borisov +--- + fs/btrfs/ctree.h | 4 +++- + fs/btrfs/disk-io.c | 5 ++--- + fs/btrfs/extent-tree.c | 13 ++++++++----- + fs/btrfs/inode.c | 23 ++++++++++++++++++++++- + 4 files changed, 35 insertions(+), 10 deletions(-) + +--- a/fs/btrfs/ctree.h ++++ b/fs/btrfs/ctree.h +@@ -914,7 +914,8 @@ struct btrfs_fs_info { + + spinlock_t delayed_iput_lock; + struct list_head delayed_iputs; +- struct mutex cleaner_delayed_iput_mutex; ++ atomic_t nr_delayed_iputs; ++ wait_queue_head_t delayed_iputs_wait; + + /* this protects tree_mod_seq_list */ + spinlock_t tree_mod_seq_lock; +@@ -3328,6 +3329,7 @@ int btrfs_cont_expand(struct inode *inod + void btrfs_invalidate_inodes(struct btrfs_root *root); + void btrfs_add_delayed_iput(struct inode *inode); + void btrfs_run_delayed_iputs(struct btrfs_fs_info *fs_info); ++int btrfs_wait_on_delayed_iputs(struct btrfs_fs_info *fs_info); + int btrfs_prealloc_file_range(struct inode *inode, int mode, + u64 start, u64 num_bytes, u64 min_size, + loff_t actual_len, u64 *alloc_hint); +--- a/fs/btrfs/disk-io.c ++++ b/fs/btrfs/disk-io.c +@@ -1781,9 +1781,7 @@ static int cleaner_kthread(void *arg) + goto sleep; + } + +- mutex_lock(&fs_info->cleaner_delayed_iput_mutex); + btrfs_run_delayed_iputs(fs_info); +- mutex_unlock(&fs_info->cleaner_delayed_iput_mutex); + + again = btrfs_clean_one_deleted_snapshot(root); + mutex_unlock(&fs_info->cleaner_mutex); +@@ -2530,7 +2528,6 @@ int open_ctree(struct super_block *sb, + mutex_init(&fs_info->delete_unused_bgs_mutex); + mutex_init(&fs_info->reloc_mutex); + mutex_init(&fs_info->delalloc_root_mutex); +- mutex_init(&fs_info->cleaner_delayed_iput_mutex); + seqlock_init(&fs_info->profiles_lock); + + INIT_LIST_HEAD(&fs_info->dirty_cowonly_roots); +@@ -2554,6 +2551,7 @@ int open_ctree(struct super_block *sb, + atomic_set(&fs_info->defrag_running, 0); + atomic_set(&fs_info->qgroup_op_seq, 0); + atomic_set(&fs_info->reada_works_cnt, 0); ++ atomic_set(&fs_info->nr_delayed_iputs, 0); + atomic64_set(&fs_info->tree_mod_seq, 0); + fs_info->fs_frozen = 0; + fs_info->sb = sb; +@@ -2634,6 +2632,7 @@ int open_ctree(struct super_block *sb, + init_waitqueue_head(&fs_info->transaction_wait); + init_waitqueue_head(&fs_info->transaction_blocked_wait); + init_waitqueue_head(&fs_info->async_submit_wait); ++ init_waitqueue_head(&fs_info->delayed_iputs_wait); + + INIT_LIST_HEAD(&fs_info->pinned_chunks); + +--- a/fs/btrfs/extent-tree.c ++++ b/fs/btrfs/extent-tree.c +@@ -4402,10 +4402,14 @@ commit_trans: + /* + * The cleaner kthread might still be doing iput + * operations. Wait for it to finish so that +- * more space is released. ++ * more space is released. We don't need to ++ * explicitly run the delayed iputs here because ++ * the commit_transaction would have woken up ++ * the cleaner. + */ +- mutex_lock(&fs_info->cleaner_delayed_iput_mutex); +- mutex_unlock(&fs_info->cleaner_delayed_iput_mutex); ++ ret = btrfs_wait_on_delayed_iputs(fs_info); ++ if (ret) ++ return ret; + goto again; + } else { + btrfs_end_transaction(trans); +@@ -5076,9 +5080,8 @@ static int flush_space(struct btrfs_fs_i + * bunch of pinned space, so make sure we run the iputs before + * we do our pinned bytes check below. + */ +- mutex_lock(&fs_info->cleaner_delayed_iput_mutex); + btrfs_run_delayed_iputs(fs_info); +- mutex_unlock(&fs_info->cleaner_delayed_iput_mutex); ++ btrfs_wait_on_delayed_iputs(fs_info); + + ret = may_commit_transaction(fs_info, space_info); + break; +--- a/fs/btrfs/inode.c ++++ b/fs/btrfs/inode.c +@@ -3255,6 +3255,7 @@ void btrfs_add_delayed_iput(struct inode + if (atomic_add_unless(&inode->i_count, -1, 1)) + return; + ++ atomic_inc(&fs_info->nr_delayed_iputs); + spin_lock(&fs_info->delayed_iput_lock); + ASSERT(list_empty(&binode->delayed_iput)); + list_add_tail(&binode->delayed_iput, &fs_info->delayed_iputs); +@@ -3263,7 +3264,6 @@ void btrfs_add_delayed_iput(struct inode + + void btrfs_run_delayed_iputs(struct btrfs_fs_info *fs_info) + { +- + spin_lock(&fs_info->delayed_iput_lock); + while (!list_empty(&fs_info->delayed_iputs)) { + struct btrfs_inode *inode; +@@ -3273,6 +3273,8 @@ void btrfs_run_delayed_iputs(struct btrf + list_del_init(&inode->delayed_iput); + spin_unlock(&fs_info->delayed_iput_lock); + iput(&inode->vfs_inode); ++ if (atomic_dec_and_test(&fs_info->nr_delayed_iputs)) ++ wake_up(&fs_info->delayed_iputs_wait); + spin_lock(&fs_info->delayed_iput_lock); + } + spin_unlock(&fs_info->delayed_iput_lock); +@@ -3280,6 +3282,25 @@ void btrfs_run_delayed_iputs(struct btrf + wake_up_process(fs_info->cleaner_kthread); + } + ++/** ++ * btrfs_wait_on_delayed_iputs - wait on the delayed iputs to be done running ++ * @fs_info - the fs_info for this fs ++ * @return - EINTR if we were killed, 0 if nothing's pending ++ * ++ * This will wait on any delayed iputs that are currently running with KILLABLE ++ * set. Once they are all done running we will return, unless we are killed in ++ * which case we return EINTR. This helps in user operations like fallocate etc ++ * that might get blocked on the iputs. ++ */ ++int btrfs_wait_on_delayed_iputs(struct btrfs_fs_info *fs_info) ++{ ++ int ret = wait_event_killable(fs_info->delayed_iputs_wait, ++ atomic_read(&fs_info->nr_delayed_iputs) == 0); ++ if (ret) ++ return -EINTR; ++ return 0; ++} ++ + /* + * This creates an orphan entry for the given inode in case something goes wrong + * in the middle of an unlink. diff --git a/patches.suse/0004-btrfs-reset-max_extent_size-on-clear-in-a-bitmap.patch b/patches.suse/0004-btrfs-reset-max_extent_size-on-clear-in-a-bitmap.patch new file mode 100644 index 0000000..703da21 --- /dev/null +++ b/patches.suse/0004-btrfs-reset-max_extent_size-on-clear-in-a-bitmap.patch @@ -0,0 +1,34 @@ +From: Josef Bacik +Date: Fri, 28 Sep 2018 07:18:00 -0400 +Subject: btrfs: reset max_extent_size on clear in a bitmap +Git-commit: 553cceb49681d60975d00892877d4c871bf220f9 +Patch-mainline: v4.20-rc1 +References: bsc##1165949 + +We need to clear the max_extent_size when we clear bits from a bitmap +since it could have been from the range that contains the +max_extent_size. + +CC: stable@vger.kernel.org # 4.4+ +Reviewed-by: Liu Bo +Signed-off-by: Josef Bacik +Signed-off-by: David Sterba +Acked-by: Nikolay Borisov +--- + fs/btrfs/free-space-cache.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/fs/btrfs/free-space-cache.c b/fs/btrfs/free-space-cache.c +index a1f379e8ad13..67441219d6c9 100644 +--- a/fs/btrfs/free-space-cache.c ++++ b/fs/btrfs/free-space-cache.c +@@ -1687,6 +1687,8 @@ static inline void __bitmap_clear_bits(struct btrfs_free_space_ctl *ctl, + bitmap_clear(info->bitmap, start, count); + + info->bytes -= bytes; ++ if (info->max_extent_size > ctl->unit) ++ info->max_extent_size = 0; + } + + static void bitmap_clear_bits(struct btrfs_free_space_ctl *ctl, + diff --git a/patches.suse/0004-lib-raid6-altivec-Add-vpermxor-implementation-for-ra.patch b/patches.suse/0004-lib-raid6-altivec-Add-vpermxor-implementation-for-ra.patch new file mode 100644 index 0000000..b3cd322 --- /dev/null +++ b/patches.suse/0004-lib-raid6-altivec-Add-vpermxor-implementation-for-ra.patch @@ -0,0 +1,292 @@ +From 751ba79cc552c146595cd439b21c4ff8998c3b69 Mon Sep 17 00:00:00 2001 +From: Matt Brown +Date: Fri, 4 Aug 2017 13:42:32 +1000 +Subject: [PATCH] lib/raid6/altivec: Add vpermxor implementation for raid6 Q + syndrome +Git-commit: 751ba79cc552c146595cd439b21c4ff8998c3b69 +Patch-mainline: v4.17-rc1 +References: bsc#1111974 bsc#1166003 + +This patch uses the vpermxor instruction to optimise the raid6 Q +syndrome. This instruction was made available with POWER8, ISA version +2.07. It allows for both vperm and vxor instructions to be done in a +single instruction. This has been tested for correctness on a ppc64le +vm with a basic RAID6 setup containing 5 drives. + +The performance benchmarks are from the raid6test in the +/lib/raid6/test directory. These results are from an IBM Firestone +machine with ppc64le architecture. The benchmark results show a 35% +speed increase over the best existing algorithm for powerpc (altivec). +The raid6test has also been run on a big-endian ppc64 vm to ensure it +also works for big-endian architectures. + +Performance benchmarks: + raid6: altivecx4 gen() 18773 MB/s + raid6: altivecx8 gen() 19438 MB/s + + raid6: vpermxor4 gen() 25112 MB/s + raid6: vpermxor8 gen() 26279 MB/s + +Signed-off-by: Matt Brown +Reviewed-by: Daniel Axtens +[mpe: Add VPERMXOR macro so we can build with old binutils] +Signed-off-by: Michael Ellerman +Signed-off-by: Coly Li + +--- + arch/powerpc/include/asm/ppc-opcode.h | 6 + + include/linux/raid/pq.h | 4 + + lib/raid6/.gitignore | 1 + lib/raid6/Makefile | 27 ++++++++ + lib/raid6/algos.c | 4 + + lib/raid6/test/Makefile | 17 ++++- + lib/raid6/vpermxor.uc | 105 ++++++++++++++++++++++++++++++++++ + 7 files changed, 161 insertions(+), 3 deletions(-) + create mode 100644 lib/raid6/vpermxor.uc + +--- a/arch/powerpc/include/asm/ppc-opcode.h ++++ b/arch/powerpc/include/asm/ppc-opcode.h +@@ -267,6 +267,7 @@ + #define PPC_INST_TLBSRX_DOT 0x7c0006a5 + #define PPC_INST_VPMSUMW 0x10000488 + #define PPC_INST_VPMSUMD 0x100004c8 ++#define PPC_INST_VPERMXOR 0x1000002d + #define PPC_INST_XXLOR 0xf0000490 + #define PPC_INST_XXSWAPD 0xf0000250 + #define PPC_INST_XVCPSGNDP 0xf0000780 +@@ -501,6 +502,11 @@ + #define XVCPSGNDP(t, a, b) stringify_in_c(.long (PPC_INST_XVCPSGNDP | \ + VSX_XX3((t), (a), (b)))) + ++#define VPERMXOR(vrt, vra, vrb, vrc) \ ++ stringify_in_c(.long (PPC_INST_VPERMXOR | \ ++ ___PPC_RT(vrt) | ___PPC_RA(vra) | \ ++ ___PPC_RB(vrb) | (((vrc) & 0x1f) << 6))) ++ + #define PPC_NAP stringify_in_c(.long PPC_INST_NAP) + #define PPC_SLEEP stringify_in_c(.long PPC_INST_SLEEP) + #define PPC_WINKLE stringify_in_c(.long PPC_INST_WINKLE) +--- a/include/linux/raid/pq.h ++++ b/include/linux/raid/pq.h +@@ -106,6 +106,10 @@ extern const struct raid6_calls raid6_av + extern const struct raid6_calls raid6_avx512x2; + extern const struct raid6_calls raid6_avx512x4; + extern const struct raid6_calls raid6_s390vx8; ++extern const struct raid6_calls raid6_vpermxor1; ++extern const struct raid6_calls raid6_vpermxor2; ++extern const struct raid6_calls raid6_vpermxor4; ++extern const struct raid6_calls raid6_vpermxor8; + + struct raid6_recov_calls { + void (*data2)(int, size_t, int, int, void **); +--- a/lib/raid6/.gitignore ++++ b/lib/raid6/.gitignore +@@ -4,3 +4,4 @@ int*.c + tables.c + neon?.c + s390vx?.c ++vpermxor*.c +--- a/lib/raid6/Makefile ++++ b/lib/raid6/Makefile +@@ -4,7 +4,8 @@ raid6_pq-y += algos.o recov.o tables.o i + int8.o int16.o int32.o + + raid6_pq-$(CONFIG_X86) += recov_ssse3.o recov_avx2.o mmx.o sse1.o sse2.o avx2.o avx512.o recov_avx512.o +-raid6_pq-$(CONFIG_ALTIVEC) += altivec1.o altivec2.o altivec4.o altivec8.o ++raid6_pq-$(CONFIG_ALTIVEC) += altivec1.o altivec2.o altivec4.o altivec8.o \ ++ vpermxor1.o vpermxor2.o vpermxor4.o vpermxor8.o + raid6_pq-$(CONFIG_KERNEL_MODE_NEON) += neon.o neon1.o neon2.o neon4.o neon8.o recov_neon.o recov_neon_inner.o + raid6_pq-$(CONFIG_S390) += s390vx8.o recov_s390xc.o + +@@ -89,6 +90,30 @@ $(obj)/altivec8.c: UNROLL := 8 + $(obj)/altivec8.c: $(src)/altivec.uc $(src)/unroll.awk FORCE + $(call if_changed,unroll) + ++CFLAGS_vpermxor1.o += $(altivec_flags) ++targets += vpermxor1.c ++$(obj)/vpermxor1.c: UNROLL := 1 ++$(obj)/vpermxor1.c: $(src)/vpermxor.uc $(src)/unroll.awk FORCE ++ $(call if_changed,unroll) ++ ++CFLAGS_vpermxor2.o += $(altivec_flags) ++targets += vpermxor2.c ++$(obj)/vpermxor2.c: UNROLL := 2 ++$(obj)/vpermxor2.c: $(src)/vpermxor.uc $(src)/unroll.awk FORCE ++ $(call if_changed,unroll) ++ ++CFLAGS_vpermxor4.o += $(altivec_flags) ++targets += vpermxor4.c ++$(obj)/vpermxor4.c: UNROLL := 4 ++$(obj)/vpermxor4.c: $(src)/vpermxor.uc $(src)/unroll.awk FORCE ++ $(call if_changed,unroll) ++ ++CFLAGS_vpermxor8.o += $(altivec_flags) ++targets += vpermxor8.c ++$(obj)/vpermxor8.c: UNROLL := 8 ++$(obj)/vpermxor8.c: $(src)/vpermxor.uc $(src)/unroll.awk FORCE ++ $(call if_changed,unroll) ++ + CFLAGS_neon1.o += $(NEON_FLAGS) + targets += neon1.c + $(obj)/neon1.c: UNROLL := 1 +--- a/lib/raid6/algos.c ++++ b/lib/raid6/algos.c +@@ -74,6 +74,10 @@ const struct raid6_calls * const raid6_a + &raid6_altivec2, + &raid6_altivec4, + &raid6_altivec8, ++ &raid6_vpermxor1, ++ &raid6_vpermxor2, ++ &raid6_vpermxor4, ++ &raid6_vpermxor8, + #endif + #if defined(CONFIG_S390) + &raid6_s390vx8, +--- a/lib/raid6/test/Makefile ++++ b/lib/raid6/test/Makefile +@@ -47,7 +47,8 @@ else + gcc -c -x c - >&/dev/null && \ + rm ./-.o && echo yes) + ifeq ($(HAS_ALTIVEC),yes) +- OBJS += altivec1.o altivec2.o altivec4.o altivec8.o ++ OBJS += altivec1.o altivec2.o altivec4.o altivec8.o \ ++ vpermxor1.o vpermxor2.o vpermxor4.o vpermxor8.o + endif + endif + +@@ -94,6 +95,18 @@ altivec4.c: altivec.uc ../unroll.awk + altivec8.c: altivec.uc ../unroll.awk + $(AWK) ../unroll.awk -vN=8 < altivec.uc > $@ + ++vpermxor1.c: vpermxor.uc ../unroll.awk ++ $(AWK) ../unroll.awk -vN=1 < vpermxor.uc > $@ ++ ++vpermxor2.c: vpermxor.uc ../unroll.awk ++ $(AWK) ../unroll.awk -vN=2 < vpermxor.uc > $@ ++ ++vpermxor4.c: vpermxor.uc ../unroll.awk ++ $(AWK) ../unroll.awk -vN=4 < vpermxor.uc > $@ ++ ++vpermxor8.c: vpermxor.uc ../unroll.awk ++ $(AWK) ../unroll.awk -vN=8 < vpermxor.uc > $@ ++ + int1.c: int.uc ../unroll.awk + $(AWK) ../unroll.awk -vN=1 < int.uc > $@ + +@@ -116,7 +129,7 @@ tables.c: mktables + ./mktables > tables.c + + clean: +- rm -f *.o *.a mktables mktables.c *.uc int*.c altivec*.c neon*.c tables.c raid6test ++ rm -f *.o *.a mktables mktables.c *.uc int*.c altivec*.c vpermxor*.c neon*.c tables.c raid6test + + spotless: clean + rm -f *~ +--- /dev/null ++++ b/lib/raid6/vpermxor.uc +@@ -0,0 +1,105 @@ ++/* ++ * Copyright 2017, Matt Brown, IBM Corp. ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License ++ * as published by the Free Software Foundation; either version ++ * 2 of the License, or (at your option) any later version. ++ * ++ * vpermxor$#.c ++ * ++ * Based on H. Peter Anvin's paper - The mathematics of RAID-6 ++ * ++ * $#-way unrolled portable integer math RAID-6 instruction set ++ * This file is postprocessed using unroll.awk ++ * ++ * vpermxor$#.c makes use of the vpermxor instruction to optimise the RAID6 Q ++ * syndrome calculations. ++ * This can be run on systems which have both Altivec and vpermxor instruction. ++ * ++ * This instruction was introduced in POWER8 - ISA v2.07. ++ */ ++ ++#include ++#ifdef CONFIG_ALTIVEC ++ ++#include ++#ifdef __KERNEL__ ++#include ++#include ++#include ++#endif ++ ++typedef vector unsigned char unative_t; ++#define NSIZE sizeof(unative_t) ++ ++static const vector unsigned char gf_low = {0x1e, 0x1c, 0x1a, 0x18, 0x16, 0x14, ++ 0x12, 0x10, 0x0e, 0x0c, 0x0a, 0x08, ++ 0x06, 0x04, 0x02,0x00}; ++static const vector unsigned char gf_high = {0xfd, 0xdd, 0xbd, 0x9d, 0x7d, 0x5d, ++ 0x3d, 0x1d, 0xe0, 0xc0, 0xa0, 0x80, ++ 0x60, 0x40, 0x20, 0x00}; ++ ++static void noinline raid6_vpermxor$#_gen_syndrome_real(int disks, size_t bytes, ++ void **ptrs) ++{ ++ u8 **dptr = (u8 **)ptrs; ++ u8 *p, *q; ++ int d, z, z0; ++ unative_t wp$$, wq$$, wd$$; ++ ++ z0 = disks - 3; /* Highest data disk */ ++ p = dptr[z0+1]; /* XOR parity */ ++ q = dptr[z0+2]; /* RS syndrome */ ++ ++ for (d = 0; d < bytes; d += NSIZE*$#) { ++ wp$$ = wq$$ = *(unative_t *)&dptr[z0][d+$$*NSIZE]; ++ ++ for (z = z0-1; z>=0; z--) { ++ wd$$ = *(unative_t *)&dptr[z][d+$$*NSIZE]; ++ /* P syndrome */ ++ wp$$ = vec_xor(wp$$, wd$$); ++ ++ /* Q syndrome */ ++ asm(VPERMXOR(%0,%1,%2,%3):"=v"(wq$$):"v"(gf_high), "v"(gf_low), "v"(wq$$)); ++ wq$$ = vec_xor(wq$$, wd$$); ++ } ++ *(unative_t *)&p[d+NSIZE*$$] = wp$$; ++ *(unative_t *)&q[d+NSIZE*$$] = wq$$; ++ } ++} ++ ++static void raid6_vpermxor$#_gen_syndrome(int disks, size_t bytes, void **ptrs) ++{ ++ preempt_disable(); ++ enable_kernel_altivec(); ++ ++ raid6_vpermxor$#_gen_syndrome_real(disks, bytes, ptrs); ++ ++ disable_kernel_altivec(); ++ preempt_enable(); ++} ++ ++int raid6_have_altivec_vpermxor(void); ++#if $# == 1 ++int raid6_have_altivec_vpermxor(void) ++{ ++ /* Check if arch has both altivec and the vpermxor instructions */ ++# ifdef __KERNEL__ ++ return (cpu_has_feature(CPU_FTR_ALTIVEC_COMP) && ++ cpu_has_feature(CPU_FTR_ARCH_207S)); ++# else ++ return 1; ++#endif ++ ++} ++#endif ++ ++const struct raid6_calls raid6_vpermxor$# = { ++ raid6_vpermxor$#_gen_syndrome, ++ NULL, ++ raid6_have_altivec_vpermxor, ++ "vpermxor$#", ++ 0 ++}; ++#endif diff --git a/patches.suse/0005-btrfs-check-if-there-are-free-block-groups-for-commit.patch b/patches.suse/0005-btrfs-check-if-there-are-free-block-groups-for-commit.patch new file mode 100644 index 0000000..8644c01 --- /dev/null +++ b/patches.suse/0005-btrfs-check-if-there-are-free-block-groups-for-commit.patch @@ -0,0 +1,75 @@ +From: Josef Bacik +Date: Wed, 21 Nov 2018 14:03:06 -0500 +Subject: btrfs: check if there are free block groups for commit +Git-commit: d89dbefb8c5f7289ad404676869135501437c04e +Patch-mainline: v5.1-rc1 +References: bsc#1165949 + +may_commit_transaction will skip committing the transaction if we don't +have enough pinned space or if we're trying to find space for a SYSTEM +chunk. However, if we have pending free block groups in this transaction +we still want to commit as we may be able to allocate a chunk to make +our reservation. So instead of just returning ENOSPC, check if we have +free block groups pending, and if so commit the transaction to allow us +to use that free space. + +Reviewed-by: Omar Sandoval +Reviewed-by: Nikolay Borisov +Signed-off-by: Josef Bacik +Signed-off-by: David Sterba +Acked-by: Nikolay Borisov +--- + fs/btrfs/extent-tree.c | 24 ++++++++++++++++-------- + 1 file changed, 16 insertions(+), 8 deletions(-) + +--- a/fs/btrfs/extent-tree.c ++++ b/fs/btrfs/extent-tree.c +@@ -4967,8 +4967,17 @@ static int may_commit_transaction(struct + + if (!bytes_needed) + return 0; +- /* See if there is enough pinned space to make this reservation */ +- if (percpu_counter_compare(&space_info->total_bytes_pinned, ++ trans = btrfs_join_transaction(fs_info->extent_root); ++ if (IS_ERR(trans)) ++ return PTR_ERR(trans); ++ ++ /* ++ * See if there is enough pinned space to make this reservation, or if ++ * we have block groups that are going to be freed, allowing us to ++ * possibly do a chunk allocation the next loop through. ++ */ ++ if (test_bit(BTRFS_TRANS_HAVE_FREE_BGS, &trans->transaction->flags) || ++ percpu_counter_compare(&space_info->total_bytes_pinned, + bytes_needed) >= 0) + goto commit; + +@@ -4977,7 +4986,7 @@ static int may_commit_transaction(struct + * this reservation. + */ + if (space_info != delayed_rsv->space_info) +- return -ENOSPC; ++ goto enospc; + + spin_lock(&delayed_rsv->lock); + reclaim_bytes += delayed_rsv->reserved; +@@ -4992,15 +5001,14 @@ static int may_commit_transaction(struct + + if (percpu_counter_compare(&space_info->total_bytes_pinned, + bytes_needed) < 0) { +- return -ENOSPC; ++ goto enospc; + } + + commit: +- trans = btrfs_join_transaction(fs_info->extent_root); +- if (IS_ERR(trans)) +- return -ENOSPC; +- + return btrfs_commit_transaction(trans); ++enospc: ++ btrfs_end_transaction(trans); ++ return -ENOSPC; + } + + static int flush_space(struct btrfs_fs_info *fs_info, diff --git a/patches.suse/0005-btrfs-clean-up-pending-block-groups-when-transaction.patch b/patches.suse/0005-btrfs-clean-up-pending-block-groups-when-transaction.patch index 50b131b..ad34363 100644 --- a/patches.suse/0005-btrfs-clean-up-pending-block-groups-when-transaction.patch +++ b/patches.suse/0005-btrfs-clean-up-pending-block-groups-when-transaction.patch @@ -80,14 +80,12 @@ Reviewed-by: Nikolay Borisov Signed-off-by: David Sterba Acked-by: Nikolay Borisov --- - fs/btrfs/transaction.c | 13 +++++++++++++ + fs/btrfs/transaction.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) -diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c -index 8351b40af552..5ce9180030e6 100644 --- a/fs/btrfs/transaction.c +++ b/fs/btrfs/transaction.c -@@ -1921,6 +1921,18 @@ static void cleanup_transaction(struct btrfs_trans_handle *trans, +@@ -1919,6 +1919,18 @@ static void cleanup_transaction(struct b kmem_cache_free(btrfs_trans_handle_cachep, trans); } @@ -105,8 +103,8 @@ index 8351b40af552..5ce9180030e6 100644 + static inline int btrfs_start_delalloc_flush(struct btrfs_fs_info *fs_info) { - if (btrfs_test_opt(fs_info, FLUSHONCOMMIT)) -@@ -2322,6 +2334,7 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans) + /* +@@ -2329,6 +2341,7 @@ scrub_continue: btrfs_scrub_continue(fs_info); cleanup_transaction: btrfs_trans_release_metadata(trans, fs_info); @@ -114,6 +112,3 @@ index 8351b40af552..5ce9180030e6 100644 btrfs_trans_release_chunk_metadata(trans); trans->block_rsv = NULL; btrfs_warn(fs_info, "Skipping commit of aborted transaction."); --- -2.17.1 - diff --git a/patches.suse/0005-btrfs-extent_io-Handle-errors-better-in-extent_write.patch b/patches.suse/0005-btrfs-extent_io-Handle-errors-better-in-extent_write.patch new file mode 100644 index 0000000..d144615 --- /dev/null +++ b/patches.suse/0005-btrfs-extent_io-Handle-errors-better-in-extent_write.patch @@ -0,0 +1,57 @@ +From 02c6db4f7308e4f5adf4df2ef623160bfdb18636 Mon Sep 17 00:00:00 2001 +From: Qu Wenruo +Date: Wed, 20 Mar 2019 14:27:45 +0800 +Patch-mainline: v5.2 +Git-commit: 02c6db4f7308e4f5adf4df2ef623160bfdb18636 +References: bsc#1168273 +Subject: [PATCH 5/7] btrfs: extent_io: Handle errors better in + extent_write_locked_range() + +We can only get @ret <= 0. Add an ASSERT() for it just in case. + +Then, instead of submitting the write bio even we got some error, check +the return value first. + +If we have already hit some error, just clean up the corrupted or +half-baked bio, and return error. + +If there is no error so far, then call flush_write_bio() and return the +result. + +Signed-off-by: Qu Wenruo +Reviewed-by: David Sterba +Signed-off-by: David Sterba +--- + fs/btrfs/extent_io.c | 9 ++++++--- + 1 file changed, 6 insertions(+), 3 deletions(-) + +diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c +index cd76be7013d8..b43a0a0f41e4 100644 +--- a/fs/btrfs/extent_io.c ++++ b/fs/btrfs/extent_io.c +@@ -4042,7 +4042,6 @@ int extent_write_locked_range(struct inode *inode, u64 start, u64 end, + int mode) + { + int ret = 0; +- int flush_ret; + struct address_space *mapping = inode->i_mapping; + struct extent_io_tree *tree = &BTRFS_I(inode)->io_tree; + struct page *page; +@@ -4075,8 +4074,12 @@ int extent_write_locked_range(struct inode *inode, u64 start, u64 end, + start += PAGE_SIZE; + } + +- flush_ret = flush_write_bio(&epd); +- BUG_ON(flush_ret < 0); ++ ASSERT(ret <= 0); ++ if (ret < 0) { ++ end_write_bio(&epd, ret); ++ return ret; ++ } ++ ret = flush_write_bio(&epd); + return ret; + } + +-- +2.26.0 + diff --git a/patches.suse/0005-btrfs-introduce-an-evict-flushing-state.patch b/patches.suse/0005-btrfs-introduce-an-evict-flushing-state.patch new file mode 100644 index 0000000..a658c7d --- /dev/null +++ b/patches.suse/0005-btrfs-introduce-an-evict-flushing-state.patch @@ -0,0 +1,194 @@ +From: Josef Bacik +Date: Thu, 1 Aug 2019 18:19:37 -0400 +Subject: btrfs: introduce an evict flushing state +Git-commit: d3984c90414a36af581b3b7c0daa87f9de3c0533 +Patch-mainline: v5.4-rc1 +References: bsc#1165949 + +We have this weird space flushing loop inside inode.c for evict where +we'll do the normal LIMIT flush, and then commit the transaction and +hope we get our space. This is super janky, and in fact there's really +nothing stopping us from using FLUSH_ALL except that we run delayed +iputs, which means we could deadlock. So introduce a new flush state +for eviction that does the normal priority flushing with all of the +states that are safe for eviction. + +The nice side-effect of this is that we'll try harder for evictions. +Previously if (for example generic/269) you had a bunch of other +operations happening on the fs you could race with those reservations +when committing the transaction, and eventually miss getting a +reservation for the evict. With this code we'll have our ticket in +place through the transaction commit, so any pinned bytes will go to our +pending evictions first. + +Signed-off-by: Josef Bacik +Signed-off-by: David Sterba +Acked-by: Nikolay Borisov +--- + fs/btrfs/ctree.h | 1 + + fs/btrfs/inode.c | 81 +++++++++++++++++++++++---------------------------- + fs/btrfs/space-info.c | 27 +++++++++++++++-- + 3 files changed, 62 insertions(+), 47 deletions(-) + +diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h +index 4ad4715a7941..b161224b5a0b 100644 +--- a/fs/btrfs/ctree.h ++++ b/fs/btrfs/ctree.h +@@ -2536,6 +2536,7 @@ enum btrfs_reserve_flush_enum { + * case, use FLUSH LIMIT + */ + BTRFS_RESERVE_FLUSH_LIMIT, ++ BTRFS_RESERVE_FLUSH_EVICT, + BTRFS_RESERVE_FLUSH_ALL, + }; + +diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c +index 612c25aac15c..c4116bc58827 100644 +--- a/fs/btrfs/inode.c ++++ b/fs/btrfs/inode.c +@@ -5336,59 +5336,50 @@ static struct btrfs_trans_handle *evict_refill_and_join(struct btrfs_root *root, + { + struct btrfs_fs_info *fs_info = root->fs_info; + struct btrfs_block_rsv *global_rsv = &fs_info->global_block_rsv; ++ struct btrfs_trans_handle *trans; + u64 delayed_refs_extra = btrfs_calc_trans_metadata_size(fs_info, 1); +- int failures = 0; +- +- for (;;) { +- struct btrfs_trans_handle *trans; +- int ret; +- +- ret = btrfs_block_rsv_refill(root, rsv, +- rsv->size + delayed_refs_extra, +- BTRFS_RESERVE_FLUSH_LIMIT); +- +- if (ret && ++failures > 2) { +- btrfs_warn(fs_info, +- "could not allocate space for a delete; will truncate on mount"); +- return ERR_PTR(-ENOSPC); +- } +- +- /* +- * Evict can generate a large amount of delayed refs without +- * having a way to add space back since we exhaust our temporary +- * block rsv. We aren't allowed to do FLUSH_ALL in this case +- * because we could deadlock with so many things in the flushing +- * code, so we have to try and hold some extra space to +- * compensate for our delayed ref generation. If we can't get +- * that space then we need see if we can steal our minimum from +- * the global reserve. We will be ratelimited by the amount of +- * space we have for the delayed refs rsv, so we'll end up +- * committing and trying again. +- */ +- trans = btrfs_join_transaction(root); +- if (IS_ERR(trans) || !ret) { +- if (!IS_ERR(trans)) { +- trans->block_rsv = &fs_info->trans_block_rsv; +- trans->bytes_reserved = delayed_refs_extra; +- btrfs_block_rsv_migrate(rsv, trans->block_rsv, +- delayed_refs_extra, 1); +- } +- return trans; +- } ++ int ret; + ++ /* ++ * Eviction should be taking place at some place safe because of our ++ * delayed iputs. However the normal flushing code will run delayed ++ * iputs, so we cannot use FLUSH_ALL otherwise we'll deadlock. ++ * ++ * We reserve the delayed_refs_extra here again because we can't use ++ * btrfs_start_transaction(root, 0) for the same deadlocky reason as ++ * above. We reserve our extra bit here because we generate a ton of ++ * delayed refs activity by truncating. ++ * ++ * If we cannot make our reservation we'll attempt to steal from the ++ * global reserve, because we really want to be able to free up space. ++ */ ++ ret = btrfs_block_rsv_refill(root, rsv, rsv->size + delayed_refs_extra, ++ BTRFS_RESERVE_FLUSH_EVICT); ++ if (ret) { + /* + * Try to steal from the global reserve if there is space for + * it. + */ +- if (!btrfs_check_space_for_delayed_refs(fs_info) && +- !btrfs_block_rsv_migrate(global_rsv, rsv, rsv->size, 0)) +- return trans; ++ if (btrfs_check_space_for_delayed_refs(fs_info) || ++ btrfs_block_rsv_migrate(global_rsv, rsv, rsv->size, 0)) { ++ btrfs_warn(fs_info, ++ "could not allocate space for delete; will truncate on mount"); ++ return ERR_PTR(-ENOSPC); ++ } ++ delayed_refs_extra = 0; ++ } + +- /* If not, commit and try again. */ +- ret = btrfs_commit_transaction(trans); +- if (ret) +- return ERR_PTR(ret); ++ trans = btrfs_join_transaction(root); ++ if (IS_ERR(trans)) ++ return trans; ++ ++ if (delayed_refs_extra) { ++ trans->block_rsv = &fs_info->trans_block_rsv; ++ trans->bytes_reserved = delayed_refs_extra; ++ btrfs_block_rsv_migrate(rsv, trans->block_rsv, ++ delayed_refs_extra, 1); + } ++ return trans; + } + + void btrfs_evict_inode(struct inode *inode) +diff --git a/fs/btrfs/space-info.c b/fs/btrfs/space-info.c +index 37ec31199675..5f8f65599de1 100644 +--- a/fs/btrfs/space-info.c ++++ b/fs/btrfs/space-info.c +@@ -848,6 +848,17 @@ static const enum btrfs_flush_state priority_flush_states[] = { + ALLOC_CHUNK, + }; + ++static const enum btrfs_flush_state evict_flush_states[] = { ++ FLUSH_DELAYED_ITEMS_NR, ++ FLUSH_DELAYED_ITEMS, ++ FLUSH_DELAYED_REFS_NR, ++ FLUSH_DELAYED_REFS, ++ FLUSH_DELALLOC, ++ FLUSH_DELALLOC_WAIT, ++ ALLOC_CHUNK, ++ COMMIT_TRANS, ++}; ++ + static void priority_reclaim_metadata_space(struct btrfs_fs_info *fs_info, + struct btrfs_space_info *space_info, + struct reserve_ticket *ticket, +@@ -922,12 +933,24 @@ static int handle_reserve_ticket(struct btrfs_fs_info *fs_info, + u64 reclaim_bytes = 0; + int ret; + +- if (flush == BTRFS_RESERVE_FLUSH_ALL) ++ switch (flush) { ++ case BTRFS_RESERVE_FLUSH_ALL: + wait_reserve_ticket(fs_info, space_info, ticket); +- else ++ break; ++ case BTRFS_RESERVE_FLUSH_LIMIT: + priority_reclaim_metadata_space(fs_info, space_info, ticket, + priority_flush_states, + ARRAY_SIZE(priority_flush_states)); ++ break; ++ case BTRFS_RESERVE_FLUSH_EVICT: ++ priority_reclaim_metadata_space(fs_info, space_info, ticket, ++ evict_flush_states, ++ ARRAY_SIZE(evict_flush_states)); ++ break; ++ default: ++ ASSERT(0); ++ break; ++ } + + spin_lock(&space_info->lock); + ret = ticket->error; + diff --git a/patches.suse/0005-btrfs-introduce-delayed_refs_rsv.patch b/patches.suse/0005-btrfs-introduce-delayed_refs_rsv.patch new file mode 100644 index 0000000..441ff9b --- /dev/null +++ b/patches.suse/0005-btrfs-introduce-delayed_refs_rsv.patch @@ -0,0 +1,675 @@ +From: Josef Bacik +Date: Mon, 3 Dec 2018 10:20:33 -0500 +Subject: btrfs: introduce delayed_refs_rsv +Git-commit: ba2c4d4e3bda7d6de2bc616ae6715e0a0725b294 +Patch-mainline: v5.0-rc1 +References: bsc#1165949 + +Traditionally we've had voodoo in btrfs to account for the space that +delayed refs may take up by having a global_block_rsv. This works most +of the time, except when it doesn't. We've had issues reported and seen +in production where sometimes the global reserve is exhausted during +transaction commit before we can run all of our delayed refs, resulting +in an aborted transaction. Because of this voodoo we have equally +dubious flushing semantics around throttling delayed refs which we often +get wrong. + +So instead give them their own block_rsv. This way we can always know +exactly how much outstanding space we need for delayed refs. This +allows us to make sure we are constantly filling that reservation up +with space, and allows us to put more precise pressure on the enospc +system. Instead of doing math to see if its a good time to throttle, +the normal enospc code will be invoked if we have a lot of delayed refs +pending, and they will be run via the normal flushing mechanism. + +For now the delayed_refs_rsv will hold the reservations for the delayed +refs, the block group updates, and deleting csums. We could have a +separate rsv for the block group updates, but the csum deletion stuff is +still handled via the delayed_refs so that will stay there. + +Historical background: + +The global reserve has grown to cover everything we don't reserve space +explicitly for, and we've grown a lot of weird ad-hoc heuristics to know +if we're running short on space and when it's time to force a commit. A +failure rate of 20-40 file systems when we run hundreds of thousands of +them isn't super high, but cleaning up this code will make things less +ugly and more predictible. + +Thus the delayed refs rsv. We always know how many delayed refs we have +outstanding, and although running them generates more we can use the +global reserve for that spill over, which fits better into it's desired +use than a full blown reservation. This first approach is to simply +take how many times we're reserving space for and multiply that by 2 in +order to save enough space for the delayed refs that could be generated. +This is a niave approach and will probably evolve, but for now it works. + +Signed-off-by: Josef Bacik +Reviewed-by: David Sterba # high-level review +[ added background notes from the cover letter ] +Signed-off-by: David Sterba +Acked-by: Nikolay Borisov +--- + fs/btrfs/ctree.h | 14 ++- + fs/btrfs/delayed-ref.c | 44 ++++++++-- + fs/btrfs/disk-io.c | 3 + fs/btrfs/extent-tree.c | 214 +++++++++++++++++++++++++++++++++++++++++++++---- + fs/btrfs/transaction.c | 37 +++++++- + 5 files changed, 284 insertions(+), 28 deletions(-) + +--- a/fs/btrfs/ctree.h ++++ b/fs/btrfs/ctree.h +@@ -457,8 +457,9 @@ struct btrfs_space_info { + #define BTRFS_BLOCK_RSV_TRANS 3 + #define BTRFS_BLOCK_RSV_CHUNK 4 + #define BTRFS_BLOCK_RSV_DELOPS 5 +-#define BTRFS_BLOCK_RSV_EMPTY 6 +-#define BTRFS_BLOCK_RSV_TEMP 7 ++#define BTRFS_BLOCK_RSV_DELREFS 6 ++#define BTRFS_BLOCK_RSV_EMPTY 7 ++#define BTRFS_BLOCK_RSV_TEMP 8 + + struct btrfs_block_rsv { + u64 size; +@@ -800,6 +801,8 @@ struct btrfs_fs_info { + struct btrfs_block_rsv chunk_block_rsv; + /* block reservation for delayed operations */ + struct btrfs_block_rsv delayed_block_rsv; ++ /* block reservation for delayed refs */ ++ struct btrfs_block_rsv delayed_refs_rsv; + + struct btrfs_block_rsv empty_block_rsv; + +@@ -2825,6 +2828,13 @@ int btrfs_cond_migrate_bytes(struct btrf + void btrfs_block_rsv_release(struct btrfs_fs_info *fs_info, + struct btrfs_block_rsv *block_rsv, + u64 num_bytes); ++void btrfs_delayed_refs_rsv_release(struct btrfs_fs_info *fs_info, int nr); ++void btrfs_update_delayed_refs_rsv(struct btrfs_trans_handle *trans); ++int btrfs_delayed_refs_rsv_refill(struct btrfs_fs_info *fs_info, ++ enum btrfs_reserve_flush_enum flush); ++void btrfs_migrate_to_delayed_refs_rsv(struct btrfs_fs_info *fs_info, ++ struct btrfs_block_rsv *src, ++ u64 num_bytes); + int btrfs_inc_block_group_ro(struct btrfs_fs_info *fs_info, + struct btrfs_block_group_cache *cache); + void btrfs_dec_block_group_ro(struct btrfs_block_group_cache *cache); +--- a/fs/btrfs/delayed-ref.c ++++ b/fs/btrfs/delayed-ref.c +@@ -479,12 +479,14 @@ inserted: + * helper function to update the accounting in the head ref + * existing and update must have the same bytenr + */ +-static noinline void +-update_existing_head_ref(struct btrfs_delayed_ref_root *delayed_refs, ++static noinline void update_existing_head_ref(struct btrfs_trans_handle *trans, + struct btrfs_delayed_ref_head *existing, + struct btrfs_delayed_ref_head *update, + int *old_ref_mod_ret) + { ++ struct btrfs_delayed_ref_root *delayed_refs = ++ &trans->transaction->delayed_refs; ++ struct btrfs_fs_info *fs_info = trans->fs_info; + int old_ref_mod; + + BUG_ON(existing->is_data != update->is_data); +@@ -542,10 +544,18 @@ update_existing_head_ref(struct btrfs_de + * versa we need to make sure to adjust pending_csums accordingly. + */ + if (existing->is_data) { +- if (existing->total_ref_mod >= 0 && old_ref_mod < 0) ++ u64 csum_leaves = ++ btrfs_csum_bytes_to_leaves(fs_info, ++ existing->num_bytes); ++ ++ if (existing->total_ref_mod >= 0 && old_ref_mod < 0) { + delayed_refs->pending_csums -= existing->num_bytes; +- if (existing->total_ref_mod < 0 && old_ref_mod >= 0) ++ btrfs_delayed_refs_rsv_release(fs_info, csum_leaves); ++ } ++ if (existing->total_ref_mod < 0 && old_ref_mod >= 0) { + delayed_refs->pending_csums += existing->num_bytes; ++ trans->delayed_ref_updates += csum_leaves; ++ } + } + spin_unlock(&existing->lock); + } +@@ -653,7 +663,7 @@ add_delayed_ref_head(struct btrfs_fs_inf + && head_ref->qgroup_reserved + && existing->qgroup_ref_root + && existing->qgroup_reserved); +- update_existing_head_ref(delayed_refs, existing, head_ref, ++ update_existing_head_ref(trans, existing, head_ref, + old_ref_mod); + /* + * we've updated the existing ref, free the newly +@@ -664,8 +674,12 @@ add_delayed_ref_head(struct btrfs_fs_inf + } else { + if (old_ref_mod) + *old_ref_mod = 0; +- if (head_ref->is_data && head_ref->ref_mod < 0) ++ if (head_ref->is_data && head_ref->ref_mod < 0) { + delayed_refs->pending_csums += head_ref->num_bytes; ++ trans->delayed_ref_updates += ++ btrfs_csum_bytes_to_leaves(trans->fs_info, ++ head_ref->num_bytes); ++ } + delayed_refs->num_heads++; + delayed_refs->num_heads_ready++; + atomic_inc(&delayed_refs->num_entries); +@@ -796,6 +810,12 @@ int btrfs_add_delayed_tree_ref(struct bt + ret = insert_delayed_ref(trans, delayed_refs, head_ref, &ref->node); + spin_unlock(&delayed_refs->lock); + ++ /* ++ * Need to update the delayed_refs_rsv with any changes we may have ++ * made. ++ */ ++ btrfs_update_delayed_refs_rsv(trans); ++ + trace_add_delayed_tree_ref(fs_info, &ref->node, ref, + action == BTRFS_ADD_DELAYED_EXTENT ? + BTRFS_ADD_DELAYED_REF : action); +@@ -883,6 +903,12 @@ int btrfs_add_delayed_data_ref(struct bt + ret = insert_delayed_ref(trans, delayed_refs, head_ref, &ref->node); + spin_unlock(&delayed_refs->lock); + ++ /* ++ * Need to update the delayed_refs_rsv with any changes we may have ++ * made. ++ */ ++ btrfs_update_delayed_refs_rsv(trans); ++ + trace_add_delayed_data_ref(trans->fs_info, &ref->node, ref, + action == BTRFS_ADD_DELAYED_EXTENT ? + BTRFS_ADD_DELAYED_REF : action); +@@ -919,6 +945,12 @@ int btrfs_add_delayed_extent_op(struct b + NULL, NULL, NULL); + + spin_unlock(&delayed_refs->lock); ++ ++ /* ++ * Need to update the delayed_refs_rsv with any changes we may have ++ * made. ++ */ ++ btrfs_update_delayed_refs_rsv(trans); + return 0; + } + +--- a/fs/btrfs/disk-io.c ++++ b/fs/btrfs/disk-io.c +@@ -2540,6 +2540,8 @@ int open_ctree(struct super_block *sb, + btrfs_init_block_rsv(&fs_info->empty_block_rsv, BTRFS_BLOCK_RSV_EMPTY); + btrfs_init_block_rsv(&fs_info->delayed_block_rsv, + BTRFS_BLOCK_RSV_DELOPS); ++ btrfs_init_block_rsv(&fs_info->delayed_refs_rsv, ++ BTRFS_BLOCK_RSV_DELREFS); + atomic_set(&fs_info->nr_async_submits, 0); + atomic_set(&fs_info->async_delalloc_pages, 0); + atomic_set(&fs_info->async_submit_draining, 0); +@@ -4461,6 +4463,7 @@ void btrfs_cleanup_dirty_bgs(struct btrf + + spin_unlock(&cur_trans->dirty_bgs_lock); + btrfs_put_block_group(cache); ++ btrfs_delayed_refs_rsv_release(fs_info, 1); + spin_lock(&cur_trans->dirty_bgs_lock); + } + spin_unlock(&cur_trans->dirty_bgs_lock); +--- a/fs/btrfs/extent-tree.c ++++ b/fs/btrfs/extent-tree.c +@@ -2611,6 +2611,7 @@ static void cleanup_ref_head_accounting( + struct btrfs_fs_info *fs_info = trans->fs_info; + struct btrfs_delayed_ref_root *delayed_refs = + &trans->transaction->delayed_refs; ++ int nr_items = 1; /* Dropping this ref head update. */ + + if (head->total_ref_mod < 0) { + struct btrfs_space_info *space_info; +@@ -2627,16 +2628,24 @@ static void cleanup_ref_head_accounting( + percpu_counter_add(&space_info->total_bytes_pinned, + -head->num_bytes); + ++ /* ++ * We had csum deletions accounted for in our delayed refs rsv, ++ * we need to drop the csum leaves for this update from our ++ * delayed_refs_rsv. ++ */ + if (head->is_data) { + spin_lock(&delayed_refs->lock); + delayed_refs->pending_csums -= head->num_bytes; + spin_unlock(&delayed_refs->lock); ++ nr_items += btrfs_csum_bytes_to_leaves(fs_info, ++ head->num_bytes); + } + } + + /* Also free its reserved qgroup space */ + btrfs_qgroup_free_delayed_ref(fs_info, head->qgroup_ref_root, + head->qgroup_reserved); ++ btrfs_delayed_refs_rsv_release(fs_info, nr_items); + } + + static int cleanup_ref_head(struct btrfs_trans_handle *trans, +@@ -3748,6 +3757,8 @@ again: + */ + mutex_lock(&trans->transaction->cache_write_mutex); + while (!list_empty(&dirty)) { ++ bool drop_reserve = true; ++ + cache = list_first_entry(&dirty, + struct btrfs_block_group_cache, + dirty_list); +@@ -3819,6 +3830,7 @@ again: + list_add_tail(&cache->dirty_list, + &cur_trans->dirty_bgs); + btrfs_get_block_group(cache); ++ drop_reserve = false; + } + spin_unlock(&cur_trans->dirty_bgs_lock); + } else if (ret) { +@@ -3829,6 +3841,8 @@ again: + /* if its not on the io list, we need to put the block group */ + if (should_put) + btrfs_put_block_group(cache); ++ if (drop_reserve) ++ btrfs_delayed_refs_rsv_release(fs_info, 1); + + if (ret) + break; +@@ -3977,6 +3991,7 @@ int btrfs_write_dirty_block_groups(struc + /* if its not on the io list, we need to put the block group */ + if (should_put) + btrfs_put_block_group(cache); ++ btrfs_delayed_refs_rsv_release(fs_info, 1); + spin_lock(&cur_trans->dirty_bgs_lock); + } + spin_unlock(&cur_trans->dirty_bgs_lock); +@@ -5499,6 +5514,90 @@ int btrfs_cond_migrate_bytes(struct btrf + return 0; + } + ++/** ++ * btrfs_migrate_to_delayed_refs_rsv - transfer bytes to our delayed refs rsv. ++ * @fs_info - the fs info for our fs. ++ * @src - the source block rsv to transfer from. ++ * @num_bytes - the number of bytes to transfer. ++ * ++ * This transfers up to the num_bytes amount from the src rsv to the ++ * delayed_refs_rsv. Any extra bytes are returned to the space info. ++ */ ++void btrfs_migrate_to_delayed_refs_rsv(struct btrfs_fs_info *fs_info, ++ struct btrfs_block_rsv *src, ++ u64 num_bytes) ++{ ++ struct btrfs_block_rsv *delayed_refs_rsv = &fs_info->delayed_refs_rsv; ++ u64 to_free = 0; ++ ++ spin_lock(&src->lock); ++ src->reserved -= num_bytes; ++ src->size -= num_bytes; ++ spin_unlock(&src->lock); ++ ++ spin_lock(&delayed_refs_rsv->lock); ++ if (delayed_refs_rsv->size > delayed_refs_rsv->reserved) { ++ u64 delta = delayed_refs_rsv->size - ++ delayed_refs_rsv->reserved; ++ if (num_bytes > delta) { ++ to_free = num_bytes - delta; ++ num_bytes = delta; ++ } ++ } else { ++ to_free = num_bytes; ++ num_bytes = 0; ++ } ++ ++ if (num_bytes) ++ delayed_refs_rsv->reserved += num_bytes; ++ if (delayed_refs_rsv->reserved >= delayed_refs_rsv->size) ++ delayed_refs_rsv->full = 1; ++ spin_unlock(&delayed_refs_rsv->lock); ++ ++ if (num_bytes) ++ trace_btrfs_space_reservation(fs_info, "delayed_refs_rsv", ++ 0, num_bytes, 1); ++ if (to_free) ++ space_info_add_old_bytes(fs_info, delayed_refs_rsv->space_info, ++ to_free); ++} ++ ++/** ++ * btrfs_delayed_refs_rsv_refill - refill based on our delayed refs usage. ++ * @fs_info - the fs_info for our fs. ++ * @flush - control how we can flush for this reservation. ++ * ++ * This will refill the delayed block_rsv up to 1 items size worth of space and ++ * will return -ENOSPC if we can't make the reservation. ++ */ ++int btrfs_delayed_refs_rsv_refill(struct btrfs_fs_info *fs_info, ++ enum btrfs_reserve_flush_enum flush) ++{ ++ struct btrfs_block_rsv *block_rsv = &fs_info->delayed_refs_rsv; ++ u64 limit = btrfs_calc_trans_metadata_size(fs_info, 1); ++ 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; ++ num_bytes = min(num_bytes, limit); ++ } ++ spin_unlock(&block_rsv->lock); ++ ++ if (!num_bytes) ++ return 0; ++ ++ ret = reserve_metadata_bytes(fs_info->extent_root, block_rsv, ++ num_bytes, flush); ++ if (ret) ++ return ret; ++ block_rsv_add_bytes(block_rsv, num_bytes, 0); ++ trace_btrfs_space_reservation(fs_info, "delayed_refs_rsv", ++ 0, num_bytes, 1); ++ return 0; ++} ++ + /* + * This is for space we already have accounted in space_info->bytes_may_use, so + * basically when we're returning space from block_rsv's. +@@ -5829,6 +5928,31 @@ int btrfs_inode_rsv_refill(struct btrfs_ + return ret; + } + ++static u64 __btrfs_block_rsv_release(struct btrfs_fs_info *fs_info, ++ struct btrfs_block_rsv *block_rsv, ++ u64 num_bytes, u64 *qgroup_to_release) ++{ ++ struct btrfs_block_rsv *global_rsv = &fs_info->global_block_rsv; ++ struct btrfs_block_rsv *delayed_rsv = &fs_info->delayed_refs_rsv; ++ struct btrfs_block_rsv *target = delayed_rsv; ++ ++ if (target->full || target == block_rsv) ++ target = global_rsv; ++ ++ if (block_rsv->space_info != target->space_info) ++ target = NULL; ++ ++ return block_rsv_release_bytes(fs_info, block_rsv, target, num_bytes, ++ qgroup_to_release); ++} ++ ++void btrfs_block_rsv_release(struct btrfs_fs_info *fs_info, ++ struct btrfs_block_rsv *block_rsv, ++ u64 num_bytes) ++{ ++ __btrfs_block_rsv_release(fs_info, block_rsv, num_bytes, NULL); ++} ++ + /** + * btrfs_inode_rsv_release - release any excessive reservation. + * @inode - the inode we need to release from. +@@ -5843,7 +5967,6 @@ int btrfs_inode_rsv_refill(struct btrfs_ + 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; + struct btrfs_block_rsv *block_rsv = &inode->block_rsv; + u64 released = 0; + u64 qgroup_to_release = 0; +@@ -5853,8 +5976,8 @@ void btrfs_inode_rsv_release(struct btrf + * 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, +- &qgroup_to_release); ++ released = __btrfs_block_rsv_release(fs_info, block_rsv, 0, ++ &qgroup_to_release); + if (released > 0) + trace_btrfs_space_reservation(fs_info, "delalloc", + btrfs_ino(inode), released, 0); +@@ -5865,16 +5988,26 @@ void btrfs_inode_rsv_release(struct btrf + qgroup_to_release); + } + +-void btrfs_block_rsv_release(struct btrfs_fs_info *fs_info, +- struct btrfs_block_rsv *block_rsv, +- u64 num_bytes) ++/** ++ * btrfs_delayed_refs_rsv_release - release a ref head's reservation. ++ * @fs_info - the fs_info for our fs. ++ * @nr - the number of items to drop. ++ * ++ * This drops the delayed ref head's count from the delayed refs rsv and frees ++ * any excess reservation we had. ++ */ ++void btrfs_delayed_refs_rsv_release(struct btrfs_fs_info *fs_info, int nr) + { ++ struct btrfs_block_rsv *block_rsv = &fs_info->delayed_refs_rsv; + struct btrfs_block_rsv *global_rsv = &fs_info->global_block_rsv; ++ u64 num_bytes = btrfs_calc_trans_metadata_size(fs_info, nr); ++ u64 released = 0; + +- if (global_rsv == block_rsv || +- block_rsv->space_info != global_rsv->space_info) +- global_rsv = NULL; +- block_rsv_release_bytes(fs_info, block_rsv, global_rsv, num_bytes, NULL); ++ released = block_rsv_release_bytes(fs_info, block_rsv, global_rsv, ++ num_bytes, NULL); ++ if (released) ++ trace_btrfs_space_reservation(fs_info, "delayed_refs_rsv", ++ 0, released, 0); + } + + static void update_global_block_rsv(struct btrfs_fs_info *fs_info) +@@ -5939,9 +6072,10 @@ static void init_global_block_rsv(struct + 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; ++ fs_info->delayed_refs_rsv.space_info = space_info; + +- fs_info->extent_root->block_rsv = &fs_info->global_block_rsv; +- fs_info->csum_root->block_rsv = &fs_info->global_block_rsv; ++ fs_info->extent_root->block_rsv = &fs_info->delayed_refs_rsv; ++ fs_info->csum_root->block_rsv = &fs_info->delayed_refs_rsv; + fs_info->dev_root->block_rsv = &fs_info->global_block_rsv; + fs_info->tree_root->block_rsv = &fs_info->global_block_rsv; + if (fs_info->quota_root) +@@ -5961,6 +6095,33 @@ static void release_global_block_rsv(str + WARN_ON(fs_info->chunk_block_rsv.reserved > 0); + WARN_ON(fs_info->delayed_block_rsv.size > 0); + WARN_ON(fs_info->delayed_block_rsv.reserved > 0); ++ WARN_ON(fs_info->delayed_refs_rsv.reserved > 0); ++ WARN_ON(fs_info->delayed_refs_rsv.size > 0); ++} ++ ++/* ++ * btrfs_update_delayed_refs_rsv - adjust the size of the delayed refs rsv ++ * @trans - the trans that may have generated delayed refs ++ * ++ * This is to be called anytime we may have adjusted trans->delayed_ref_updates, ++ * it'll calculate the additional size and add it to the delayed_refs_rsv. ++ */ ++void btrfs_update_delayed_refs_rsv(struct btrfs_trans_handle *trans) ++{ ++ struct btrfs_fs_info *fs_info = trans->fs_info; ++ struct btrfs_block_rsv *delayed_rsv = &fs_info->delayed_refs_rsv; ++ u64 num_bytes; ++ ++ if (!trans->delayed_ref_updates) ++ return; ++ ++ num_bytes = btrfs_calc_trans_metadata_size(fs_info, ++ trans->delayed_ref_updates); ++ spin_lock(&delayed_rsv->lock); ++ delayed_rsv->size += num_bytes; ++ delayed_rsv->full = 0; ++ spin_unlock(&delayed_rsv->lock); ++ trans->delayed_ref_updates = 0; + } + + void btrfs_trans_release_metadata(struct btrfs_trans_handle *trans, +@@ -6277,6 +6438,7 @@ static int update_block_group(struct btr + u64 old_val; + u64 byte_in_group; + int factor; ++ int ret = 0; + + /* block accounting for super block */ + spin_lock(&info->delalloc_root_lock); +@@ -6290,8 +6452,10 @@ static int update_block_group(struct btr + + while (total) { + cache = btrfs_lookup_block_group(info, bytenr); +- if (!cache) +- return -ENOENT; ++ if (!cache) { ++ ret = -ENOENT; ++ break; ++ } + factor = btrfs_bg_type_to_factor(cache->flags); + + /* +@@ -6348,7 +6512,8 @@ static int update_block_group(struct btr + if (list_empty(&cache->dirty_list)) { + list_add_tail(&cache->dirty_list, + &trans->transaction->dirty_bgs); +- trans->transaction->num_dirty_bgs++; ++ trans->transaction->num_dirty_bgs++; ++ trans->delayed_ref_updates++; + btrfs_get_block_group(cache); + } + spin_unlock(&trans->transaction->dirty_bgs_lock); +@@ -6373,7 +6538,10 @@ static int update_block_group(struct btr + total -= num_bytes; + bytenr += num_bytes; + } +- return 0; ++ ++ /* Modified block groups are accounted for in the delayed_refs_rsv. */ ++ btrfs_update_delayed_refs_rsv(trans); ++ return ret; + } + + static u64 first_logical_byte(struct btrfs_fs_info *fs_info, u64 search_start) +@@ -8380,7 +8548,12 @@ again: + goto again; + } + +- if (btrfs_test_opt(fs_info, ENOSPC_DEBUG)) { ++ /* ++ * The global reserve still exists to save us from ourselves, so don't ++ * warn_on if we are short on our delayed refs reserve. ++ */ ++ if (block_rsv->type != BTRFS_BLOCK_RSV_DELREFS && ++ btrfs_test_opt(fs_info, ENOSPC_DEBUG)) { + static DEFINE_RATELIMIT_STATE(_rs, + DEFAULT_RATELIMIT_INTERVAL * 10, + /*DEFAULT_RATELIMIT_BURST*/ 1); +@@ -10317,6 +10490,7 @@ void btrfs_create_pending_block_groups(s + add_block_group_free_space(trans, fs_info, block_group); + /* already aborted the transaction if it failed. */ + next: ++ btrfs_delayed_refs_rsv_release(fs_info, 1); + list_del_init(&block_group->bg_list); + } + btrfs_trans_release_chunk_metadata(trans); +@@ -10394,6 +10568,8 @@ int btrfs_make_block_group(struct btrfs_ + link_block_group(cache); + + list_add_tail(&cache->bg_list, &trans->new_bgs); ++ trans->delayed_ref_updates++; ++ btrfs_update_delayed_refs_rsv(trans); + + set_avail_alloc_bits(fs_info, type); + return 0; +@@ -10431,6 +10607,7 @@ int btrfs_remove_block_group(struct btrf + int factor; + struct btrfs_caching_control *caching_ctl = NULL; + bool remove_em; ++ bool remove_rsv = false; + + block_group = btrfs_lookup_block_group(fs_info, group_start); + BUG_ON(!block_group); +@@ -10492,6 +10669,7 @@ int btrfs_remove_block_group(struct btrf + + if (!list_empty(&block_group->dirty_list)) { + list_del_init(&block_group->dirty_list); ++ remove_rsv = true; + btrfs_put_block_group(block_group); + } + spin_unlock(&trans->transaction->dirty_bgs_lock); +@@ -10701,6 +10879,8 @@ int btrfs_remove_block_group(struct btrf + + ret = btrfs_del_item(trans, root, path); + out: ++ if (remove_rsv) ++ btrfs_delayed_refs_rsv_release(fs_info, 1); + btrfs_free_path(path); + return ret; + } +--- a/fs/btrfs/transaction.c ++++ b/fs/btrfs/transaction.c +@@ -478,7 +478,7 @@ start_transaction(struct btrfs_root *roo + bool enforce_qgroups) + { + struct btrfs_fs_info *fs_info = root->fs_info; +- ++ struct btrfs_block_rsv *delayed_refs_rsv = &fs_info->delayed_refs_rsv; + struct btrfs_trans_handle *h; + struct btrfs_transaction *cur_trans; + u64 num_bytes = 0; +@@ -507,13 +507,28 @@ start_transaction(struct btrfs_root *roo + * the appropriate flushing if need be. + */ + if (num_items && root != fs_info->chunk_root) { ++ struct btrfs_block_rsv *rsv = &fs_info->trans_block_rsv; ++ u64 delayed_refs_bytes = 0; ++ + qgroup_reserved = num_items * fs_info->nodesize; + ret = btrfs_qgroup_reserve_meta_pertrans(root, qgroup_reserved, + enforce_qgroups); + if (ret) + return ERR_PTR(ret); + ++ /* ++ * We want to reserve all the bytes we may need all at once, so ++ * we only do 1 enospc flushing cycle per transaction start. We ++ * accomplish this by simply assuming we'll do 2 x num_items ++ * worth of delayed refs updates in this trans handle, and ++ * refill that amount for whatever is missing in the reserve. ++ */ + num_bytes = btrfs_calc_trans_metadata_size(fs_info, num_items); ++ if (delayed_refs_rsv->full == 0) { ++ delayed_refs_bytes = num_bytes; ++ num_bytes <<= 1; ++ } ++ + /* + * Do the reservation for the relocation root creation + */ +@@ -522,8 +537,24 @@ start_transaction(struct btrfs_root *roo + reloc_reserved = true; + } + +- ret = btrfs_block_rsv_add(root, &fs_info->trans_block_rsv, +- num_bytes, flush); ++ ret = btrfs_block_rsv_add(root, rsv, num_bytes, flush); ++ if (ret) ++ goto reserve_fail; ++ if (delayed_refs_bytes) { ++ btrfs_migrate_to_delayed_refs_rsv(fs_info, rsv, ++ delayed_refs_bytes); ++ num_bytes -= delayed_refs_bytes; ++ } ++ } else if (num_items == 0 && flush == BTRFS_RESERVE_FLUSH_ALL && ++ !delayed_refs_rsv->full) { ++ /* ++ * Some people call with btrfs_start_transaction(root, 0) ++ * because they can be throttled, but have some other mechanism ++ * for reserving space. We still want these guys to refill the ++ * delayed block_rsv so just add 1 items worth of reservation ++ * here. ++ */ ++ ret = btrfs_delayed_refs_rsv_refill(fs_info, flush); + if (ret) + goto reserve_fail; + } diff --git a/patches.suse/0005-btrfs-migrate-nocow-and-reservation-helpers.patch b/patches.suse/0005-btrfs-migrate-nocow-and-reservation-helpers.patch new file mode 100644 index 0000000..1ba6162 --- /dev/null +++ b/patches.suse/0005-btrfs-migrate-nocow-and-reservation-helpers.patch @@ -0,0 +1,246 @@ +From: Josef Bacik +Date: Thu, 20 Jun 2019 15:37:47 -0400 +Subject: btrfs: migrate nocow and reservation helpers +Git-commit: 3eeb3226a8891544ea4a9baf27ba3d73e8a42991 +Patch-mainline: v5.4-rc1 +References: bsc#1165949 + +These are relatively straightforward as well. + +Signed-off-by: Josef Bacik +Reviewed-by: David Sterba +Signed-off-by: David Sterba +Acked-by: Nikolay Borisov +--- + fs/btrfs/block-group.c | 98 +++++++++++++++++++++++++++++++++++++++++++++++++ + fs/btrfs/block-group.h | 6 +++ + fs/btrfs/ctree.h | 6 --- + fs/btrfs/extent-tree.c | 98 ------------------------------------------------- + 4 files changed, 104 insertions(+), 104 deletions(-) + +--- a/fs/btrfs/block-group.c ++++ b/fs/btrfs/block-group.c +@@ -2,6 +2,7 @@ + + #include "ctree.h" + #include "block-group.h" ++#include "space-info.h" + + void btrfs_get_block_group(struct btrfs_block_group_cache *cache) + { +@@ -118,3 +119,86 @@ struct btrfs_block_group_cache *btrfs_ne + spin_unlock(&fs_info->block_group_cache_lock); + return cache; + } ++ ++bool btrfs_inc_nocow_writers(struct btrfs_fs_info *fs_info, u64 bytenr) ++{ ++ struct btrfs_block_group_cache *bg; ++ bool ret = true; ++ ++ bg = btrfs_lookup_block_group(fs_info, bytenr); ++ if (!bg) ++ return false; ++ ++ spin_lock(&bg->lock); ++ if (bg->ro) ++ ret = false; ++ else ++ atomic_inc(&bg->nocow_writers); ++ spin_unlock(&bg->lock); ++ ++ /* No put on block group, done by btrfs_dec_nocow_writers */ ++ if (!ret) ++ btrfs_put_block_group(bg); ++ ++ return ret; ++} ++ ++void btrfs_dec_nocow_writers(struct btrfs_fs_info *fs_info, u64 bytenr) ++{ ++ struct btrfs_block_group_cache *bg; ++ ++ bg = btrfs_lookup_block_group(fs_info, bytenr); ++ ASSERT(bg); ++ if (atomic_dec_and_test(&bg->nocow_writers)) ++ wake_up_atomic_t(&bg->nocow_writers); ++ /* ++ * Once for our lookup and once for the lookup done by a previous call ++ * to btrfs_inc_nocow_writers() ++ */ ++ btrfs_put_block_group(bg); ++ btrfs_put_block_group(bg); ++} ++ ++void btrfs_wait_nocow_writers(struct btrfs_block_group_cache *bg) ++{ ++ wait_on_atomic_t(&bg->nocow_writers, atomic_t_wait, ++ TASK_UNINTERRUPTIBLE); ++} ++ ++void btrfs_dec_block_group_reservations(struct btrfs_fs_info *fs_info, ++ const u64 start) ++{ ++ struct btrfs_block_group_cache *bg; ++ ++ bg = btrfs_lookup_block_group(fs_info, start); ++ ASSERT(bg); ++ if (atomic_dec_and_test(&bg->reservations)) ++ wake_up_atomic_t(&bg->reservations); ++ btrfs_put_block_group(bg); ++} ++ ++void btrfs_wait_block_group_reservations(struct btrfs_block_group_cache *bg) ++{ ++ struct btrfs_space_info *space_info = bg->space_info; ++ ++ ASSERT(bg->ro); ++ ++ if (!(bg->flags & BTRFS_BLOCK_GROUP_DATA)) ++ return; ++ ++ /* ++ * Our block group is read only but before we set it to read only, ++ * some task might have had allocated an extent from it already, but it ++ * has not yet created a respective ordered extent (and added it to a ++ * root's list of ordered extents). ++ * Therefore wait for any task currently allocating extents, since the ++ * block group's reservations counter is incremented while a read lock ++ * on the groups' semaphore is held and decremented after releasing ++ * the read access on that semaphore and creating the ordered extent. ++ */ ++ down_write(&space_info->groups_sem); ++ up_write(&space_info->groups_sem); ++ ++ wait_on_atomic_t(&bg->reservations, atomic_t_wait, ++ TASK_UNINTERRUPTIBLE); ++} +--- a/fs/btrfs/block-group.h ++++ b/fs/btrfs/block-group.h +@@ -159,5 +159,11 @@ struct btrfs_block_group_cache *btrfs_ne + struct btrfs_block_group_cache *cache); + void btrfs_get_block_group(struct btrfs_block_group_cache *cache); + void btrfs_put_block_group(struct btrfs_block_group_cache *cache); ++void btrfs_dec_block_group_reservations(struct btrfs_fs_info *fs_info, ++ const u64 start); ++void btrfs_wait_block_group_reservations(struct btrfs_block_group_cache *bg); ++bool btrfs_inc_nocow_writers(struct btrfs_fs_info *fs_info, u64 bytenr); ++void btrfs_dec_nocow_writers(struct btrfs_fs_info *fs_info, u64 bytenr); ++void btrfs_wait_nocow_writers(struct btrfs_block_group_cache *bg); + + #endif /* BTRFS_BLOCK_GROUP_H */ +--- a/fs/btrfs/ctree.h ++++ b/fs/btrfs/ctree.h +@@ -2455,12 +2455,6 @@ static inline u64 btrfs_calc_trunc_metad + return (u64)fs_info->nodesize * BTRFS_MAX_LEVEL * num_items; + } + +-void btrfs_dec_block_group_reservations(struct btrfs_fs_info *fs_info, +- const u64 start); +-void btrfs_wait_block_group_reservations(struct btrfs_block_group_cache *bg); +-bool btrfs_inc_nocow_writers(struct btrfs_fs_info *fs_info, u64 bytenr); +-void btrfs_dec_nocow_writers(struct btrfs_fs_info *fs_info, u64 bytenr); +-void btrfs_wait_nocow_writers(struct btrfs_block_group_cache *bg); + int btrfs_run_delayed_refs(struct btrfs_trans_handle *trans, + struct btrfs_fs_info *fs_info, unsigned long count); + int btrfs_async_run_delayed_refs(struct btrfs_fs_info *fs_info, +--- a/fs/btrfs/extent-tree.c ++++ b/fs/btrfs/extent-tree.c +@@ -3768,52 +3768,6 @@ int btrfs_extent_readonly(struct btrfs_f + return readonly; + } + +-bool btrfs_inc_nocow_writers(struct btrfs_fs_info *fs_info, u64 bytenr) +-{ +- struct btrfs_block_group_cache *bg; +- bool ret = true; +- +- bg = btrfs_lookup_block_group(fs_info, bytenr); +- if (!bg) +- return false; +- +- spin_lock(&bg->lock); +- if (bg->ro) +- ret = false; +- else +- atomic_inc(&bg->nocow_writers); +- spin_unlock(&bg->lock); +- +- /* no put on block group, done by btrfs_dec_nocow_writers */ +- if (!ret) +- btrfs_put_block_group(bg); +- +- return ret; +- +-} +- +-void btrfs_dec_nocow_writers(struct btrfs_fs_info *fs_info, u64 bytenr) +-{ +- struct btrfs_block_group_cache *bg; +- +- bg = btrfs_lookup_block_group(fs_info, bytenr); +- ASSERT(bg); +- if (atomic_dec_and_test(&bg->nocow_writers)) +- wake_up_atomic_t(&bg->nocow_writers); +- /* +- * Once for our lookup and once for the lookup done by a previous call +- * to btrfs_inc_nocow_writers() +- */ +- btrfs_put_block_group(bg); +- btrfs_put_block_group(bg); +-} +- +-void btrfs_wait_nocow_writers(struct btrfs_block_group_cache *bg) +-{ +- wait_on_atomic_t(&bg->nocow_writers, atomic_t_wait, +- TASK_UNINTERRUPTIBLE); +-} +- + static void set_avail_alloc_bits(struct btrfs_fs_info *fs_info, u64 flags) + { + u64 extra_flags = chunk_to_extended(flags) & +@@ -4504,44 +4451,6 @@ btrfs_inc_block_group_reservations(struc + atomic_inc(&bg->reservations); + } + +-void btrfs_dec_block_group_reservations(struct btrfs_fs_info *fs_info, +- const u64 start) +-{ +- struct btrfs_block_group_cache *bg; +- +- bg = btrfs_lookup_block_group(fs_info, start); +- ASSERT(bg); +- if (atomic_dec_and_test(&bg->reservations)) +- wake_up_atomic_t(&bg->reservations); +- btrfs_put_block_group(bg); +-} +- +-void btrfs_wait_block_group_reservations(struct btrfs_block_group_cache *bg) +-{ +- struct btrfs_space_info *space_info = bg->space_info; +- +- ASSERT(bg->ro); +- +- if (!(bg->flags & BTRFS_BLOCK_GROUP_DATA)) +- return; +- +- /* +- * Our block group is read only but before we set it to read only, +- * some task might have had allocated an extent from it already, but it +- * has not yet created a respective ordered extent (and added it to a +- * root's list of ordered extents). +- * Therefore wait for any task currently allocating extents, since the +- * block group's reservations counter is incremented while a read lock +- * on the groups' semaphore is held and decremented after releasing +- * the read access on that semaphore and creating the ordered extent. +- */ +- down_write(&space_info->groups_sem); +- up_write(&space_info->groups_sem); +- +- wait_on_atomic_t(&bg->reservations, atomic_t_wait, +- TASK_UNINTERRUPTIBLE); +-} +- + /** + * btrfs_add_reserved_bytes - update the block_group and space info counters + * @cache: The cache we are manipulating diff --git a/patches.suse/0005-btrfs-move-the-space_info-handling-code-to-space-info-c.patch b/patches.suse/0005-btrfs-move-the-space_info-handling-code-to-space-info-c.patch new file mode 100644 index 0000000..c2fc861 --- /dev/null +++ b/patches.suse/0005-btrfs-move-the-space_info-handling-code-to-space-info-c.patch @@ -0,0 +1,573 @@ +From: Josef Bacik +Date: Tue, 18 Jun 2019 16:09:19 -0400 +Subject: btrfs: move the space_info handling code to space-info.c +Git-commit: 280c290881bc048bd5dbe02796173f55ca86e697 +Patch-mainline: v5.3-rc1 +References: bsc#1165949 + +These are the basic init and lookup functions and some helper functions, +fairly straightforward before the bad stuff starts. + +Reviewed-by: Nikolay Borisov +Signed-off-by: Josef Bacik +Signed-off-by: David Sterba +Acked-by: Nikolay Borisov +--- + fs/btrfs/Makefile | 2 + fs/btrfs/extent-tree.c | 204 ++++--------------------------------------------- + fs/btrfs/space-info.c | 175 ++++++++++++++++++++++++++++++++++++++++++ + fs/btrfs/space-info.h | 10 ++ + 4 files changed, 204 insertions(+), 187 deletions(-) + +--- a/fs/btrfs/Makefile ++++ b/fs/btrfs/Makefile +@@ -9,7 +9,7 @@ btrfs-y += super.o ctree.o extent-tree.o + export.o tree-log.o free-space-cache.o zlib.o lzo.o zstd.o \ + compression.o delayed-ref.o relocation.o delayed-inode.o scrub.o \ + reada.o backref.o ulist.o qgroup.o send.o dev-replace.o raid56.o \ +- uuid-tree.o props.o hash.o free-space-tree.o tree-checker.o ++ uuid-tree.o props.o hash.o free-space-tree.o tree-checker.o space-info.o + + btrfs-$(CONFIG_BTRFS_FS_POSIX_ACL) += acl.o + btrfs-$(CONFIG_BTRFS_FS_CHECK_INTEGRITY) += check-integrity.o +--- a/fs/btrfs/extent-tree.c ++++ b/fs/btrfs/extent-tree.c +@@ -741,25 +741,6 @@ struct btrfs_block_group_cache *btrfs_lo + return block_group_cache_tree_search(info, bytenr, 1); + } + +-static struct btrfs_space_info *__find_space_info(struct btrfs_fs_info *info, +- u64 flags) +-{ +- struct list_head *head = &info->space_info; +- struct btrfs_space_info *found; +- +- flags &= BTRFS_BLOCK_GROUP_TYPE_MASK; +- +- rcu_read_lock(); +- list_for_each_entry_rcu(found, head, list) { +- if (found->flags & flags) { +- rcu_read_unlock(); +- return found; +- } +- } +- rcu_read_unlock(); +- return NULL; +-} +- + static void add_pinned_bytes(struct btrfs_fs_info *fs_info, + struct btrfs_ref *ref, int sign) + { +@@ -778,26 +759,11 @@ static void add_pinned_bytes(struct btrf + flags = BTRFS_BLOCK_GROUP_DATA; + } + +- space_info = __find_space_info(fs_info, flags); ++ space_info = btrfs_find_space_info(fs_info, flags); + ASSERT(space_info); + percpu_counter_add(&space_info->total_bytes_pinned, num_bytes); + } + +-/* +- * after adding space to the filesystem, we need to clear the full flags +- * on all the space infos. +- */ +-void btrfs_clear_space_info_full(struct btrfs_fs_info *info) +-{ +- struct list_head *head = &info->space_info; +- struct btrfs_space_info *found; +- +- rcu_read_lock(); +- list_for_each_entry_rcu(found, head, list) +- found->full = 0; +- rcu_read_unlock(); +-} +- + /* simple helper to search for an existing data extent at a given offset */ + int btrfs_lookup_data_extent(struct btrfs_fs_info *fs_info, u64 start, u64 len) + { +@@ -2595,7 +2561,7 @@ void btrfs_cleanup_ref_head_accounting(s + flags = BTRFS_BLOCK_GROUP_SYSTEM; + else + flags = BTRFS_BLOCK_GROUP_METADATA; +- space_info = __find_space_info(fs_info, flags); ++ space_info = btrfs_find_space_info(fs_info, flags); + ASSERT(space_info); + percpu_counter_add(&space_info->total_bytes_pinned, + -head->num_bytes); +@@ -4041,94 +4007,6 @@ void btrfs_wait_nocow_writers(struct btr + TASK_UNINTERRUPTIBLE); + } + +-static const char *alloc_name(u64 flags) +-{ +- switch (flags) { +- case BTRFS_BLOCK_GROUP_METADATA|BTRFS_BLOCK_GROUP_DATA: +- return "mixed"; +- case BTRFS_BLOCK_GROUP_METADATA: +- return "metadata"; +- case BTRFS_BLOCK_GROUP_DATA: +- return "data"; +- case BTRFS_BLOCK_GROUP_SYSTEM: +- return "system"; +- default: +- WARN_ON(1); +- return "invalid-combination"; +- }; +-} +- +-static int create_space_info(struct btrfs_fs_info *info, u64 flags) +-{ +- +- struct btrfs_space_info *space_info; +- int i; +- int ret; +- +- space_info = kzalloc(sizeof(*space_info), GFP_NOFS); +- if (!space_info) +- return -ENOMEM; +- +- ret = percpu_counter_init(&space_info->total_bytes_pinned, 0, +- GFP_KERNEL); +- if (ret) { +- kfree(space_info); +- return ret; +- } +- +- for (i = 0; i < BTRFS_NR_RAID_TYPES; i++) +- INIT_LIST_HEAD(&space_info->block_groups[i]); +- init_rwsem(&space_info->groups_sem); +- spin_lock_init(&space_info->lock); +- space_info->flags = flags & BTRFS_BLOCK_GROUP_TYPE_MASK; +- space_info->force_alloc = CHUNK_ALLOC_NO_FORCE; +- init_waitqueue_head(&space_info->wait); +- INIT_LIST_HEAD(&space_info->ro_bgs); +- INIT_LIST_HEAD(&space_info->tickets); +- INIT_LIST_HEAD(&space_info->priority_tickets); +- +- ret = kobject_init_and_add(&space_info->kobj, &space_info_ktype, +- info->space_info_kobj, "%s", +- alloc_name(space_info->flags)); +- if (ret) { +- percpu_counter_destroy(&space_info->total_bytes_pinned); +- kfree(space_info); +- return ret; +- } +- +- list_add_rcu(&space_info->list, &info->space_info); +- if (flags & BTRFS_BLOCK_GROUP_DATA) +- info->data_sinfo = space_info; +- +- return ret; +-} +- +-static void update_space_info(struct btrfs_fs_info *info, u64 flags, +- u64 total_bytes, u64 bytes_used, +- u64 bytes_readonly, +- struct btrfs_space_info **space_info) +-{ +- struct btrfs_space_info *found; +- int factor; +- +- factor = btrfs_bg_type_to_factor(flags); +- +- found = __find_space_info(info, flags); +- ASSERT(found); +- spin_lock(&found->lock); +- found->total_bytes += total_bytes; +- found->disk_total += total_bytes * factor; +- found->bytes_used += bytes_used; +- found->disk_used += bytes_used * factor; +- found->bytes_readonly += bytes_readonly; +- if (total_bytes > 0) +- found->full = 0; +- btrfs_space_info_add_new_bytes(info, found, total_bytes - +- bytes_used - bytes_readonly); +- spin_unlock(&found->lock); +- *space_info = found; +-} +- + static void set_avail_alloc_bits(struct btrfs_fs_info *fs_info, u64 flags) + { + u64 extra_flags = chunk_to_extended(flags) & +@@ -4276,15 +4154,6 @@ u64 btrfs_system_alloc_profile(struct bt + return get_alloc_profile(fs_info, BTRFS_BLOCK_GROUP_SYSTEM); + } + +-static u64 btrfs_space_info_used(struct btrfs_space_info *s_info, +- bool may_use_included) +-{ +- ASSERT(s_info); +- return s_info->bytes_used + s_info->bytes_reserved + +- s_info->bytes_pinned + s_info->bytes_readonly + +- (may_use_included ? s_info->bytes_may_use : 0); +-} +- + int btrfs_alloc_data_chunk_ondemand(struct btrfs_inode *inode, u64 bytes) + { + struct btrfs_space_info *data_sinfo; +@@ -4574,7 +4443,7 @@ void check_system_chunk(struct btrfs_tra + */ + ASSERT(mutex_is_locked(&fs_info->chunk_mutex)); + +- info = __find_space_info(fs_info, BTRFS_BLOCK_GROUP_SYSTEM); ++ info = btrfs_find_space_info(fs_info, BTRFS_BLOCK_GROUP_SYSTEM); + spin_lock(&info->lock); + left = info->total_bytes - btrfs_space_info_used(info, true); + spin_unlock(&info->lock); +@@ -4633,7 +4502,7 @@ int btrfs_chunk_alloc(struct btrfs_trans + if (trans->allocating_chunk) + return -ENOSPC; + +- space_info = __find_space_info(fs_info, flags); ++ space_info = btrfs_find_space_info(fs_info, flags); + ASSERT(space_info); + + again: +@@ -4860,7 +4729,7 @@ static void shrink_delalloc(struct btrfs + to_reclaim = items * EXTENT_SIZE_PER_ITEM; + + trans = (struct btrfs_trans_handle *)current->journal_info; +- space_info = __find_space_info(fs_info, BTRFS_BLOCK_GROUP_METADATA); ++ space_info = btrfs_find_space_info(fs_info, BTRFS_BLOCK_GROUP_METADATA); + + delalloc_bytes = percpu_counter_sum_positive( + &fs_info->delalloc_bytes); +@@ -5183,7 +5052,7 @@ static void btrfs_async_reclaim_metadata + u64 last_tickets_id; + + fs_info = container_of(work, struct btrfs_fs_info, async_reclaim_work); +- space_info = __find_space_info(fs_info, BTRFS_BLOCK_GROUP_METADATA); ++ space_info = btrfs_find_space_info(fs_info, BTRFS_BLOCK_GROUP_METADATA); + + spin_lock(&space_info->lock); + to_reclaim = btrfs_calc_reclaim_metadata_size(fs_info->fs_root, +@@ -5833,7 +5702,7 @@ void btrfs_init_metadata_block_rsv(struc + unsigned short type) + { + btrfs_init_block_rsv(rsv, type); +- rsv->space_info = __find_space_info(fs_info, ++ rsv->space_info = btrfs_find_space_info(fs_info, + BTRFS_BLOCK_GROUP_METADATA); + } + +@@ -6065,10 +5934,10 @@ static void init_global_block_rsv(struct + { + struct btrfs_space_info *space_info; + +- space_info = __find_space_info(fs_info, BTRFS_BLOCK_GROUP_SYSTEM); ++ space_info = btrfs_find_space_info(fs_info, BTRFS_BLOCK_GROUP_SYSTEM); + fs_info->chunk_block_rsv.space_info = space_info; + +- space_info = __find_space_info(fs_info, BTRFS_BLOCK_GROUP_METADATA); ++ space_info = btrfs_find_space_info(fs_info, BTRFS_BLOCK_GROUP_METADATA); + fs_info->global_block_rsv.space_info = space_info; + fs_info->trans_block_rsv.space_info = space_info; + fs_info->empty_block_rsv.space_info = space_info; +@@ -6200,7 +6069,7 @@ int btrfs_subvolume_reserve_metadata(str + *qgroup_reserved = num_bytes; + + num_bytes = btrfs_calc_trans_metadata_size(fs_info, items); +- rsv->space_info = __find_space_info(fs_info, ++ rsv->space_info = btrfs_find_space_info(fs_info, + BTRFS_BLOCK_GROUP_METADATA); + ret = btrfs_block_rsv_add(root, rsv, num_bytes, + BTRFS_RESERVE_FLUSH_ALL); +@@ -7723,7 +7592,7 @@ static noinline int find_free_extent(str + + trace_find_free_extent(fs_info, num_bytes, empty_size, flags); + +- space_info = __find_space_info(fs_info, flags); ++ space_info = btrfs_find_space_info(fs_info, flags); + if (!space_info) { + btrfs_err(fs_info, "No space info for %llu", flags); + return -ENOSPC; +@@ -8262,7 +8131,7 @@ again: + } else if (btrfs_test_opt(fs_info, ENOSPC_DEBUG)) { + struct btrfs_space_info *sinfo; + +- sinfo = __find_space_info(fs_info, flags); ++ sinfo = btrfs_find_space_info(fs_info, flags); + btrfs_err(fs_info, + "allocation failed flags %llu, wanted %llu", + flags, num_bytes); +@@ -10275,7 +10144,7 @@ void btrfs_add_raid_kobjects(struct btrf + spin_unlock(&fs_info->pending_raid_kobjs_lock); + + list_for_each_entry(rkobj, &list, list) { +- space_info = __find_space_info(fs_info, rkobj->flags); ++ space_info = btrfs_find_space_info(fs_info, rkobj->flags); + index = __get_raid_index(rkobj->flags); + + ret = kobject_add(&rkobj->kobj, &space_info->kobj, +@@ -10546,9 +10415,9 @@ int btrfs_read_block_groups(struct btrfs + } + + trace_btrfs_add_block_group(info, cache, 0); +- update_space_info(info, cache->flags, found_key.offset, +- btrfs_block_group_used(&cache->item), +- cache->bytes_super, &space_info); ++ btrfs_update_space_info(info, cache->flags, found_key.offset, ++ btrfs_block_group_used(&cache->item), ++ cache->bytes_super, &space_info); + + cache->space_info = space_info; + +@@ -10690,7 +10559,7 @@ int btrfs_make_block_group(struct btrfs_ + * assigned to our block group. We want our bg to be added to the rbtree + * with its ->space_info set. + */ +- cache->space_info = __find_space_info(fs_info, cache->flags); ++ cache->space_info = btrfs_find_space_info(fs_info, cache->flags); + ASSERT(cache->space_info); + + ret = btrfs_add_block_group_cache(fs_info, cache); +@@ -10705,7 +10574,7 @@ int btrfs_make_block_group(struct btrfs_ + * the rbtree, update the space info's counters. + */ + trace_btrfs_add_block_group(fs_info, cache, 1); +- update_space_info(fs_info, cache->flags, size, bytes_used, ++ btrfs_update_space_info(fs_info, cache->flags, size, bytes_used, + cache->bytes_super, &cache->space_info); + update_global_block_rsv(fs_info); + +@@ -11240,43 +11109,6 @@ next: + spin_unlock(&fs_info->unused_bgs_lock); + } + +-int btrfs_init_space_info(struct btrfs_fs_info *fs_info) +-{ +- struct btrfs_super_block *disk_super; +- u64 features; +- u64 flags; +- int mixed = 0; +- int ret; +- +- disk_super = fs_info->super_copy; +- if (!btrfs_super_root(disk_super)) +- return -EINVAL; +- +- features = btrfs_super_incompat_flags(disk_super); +- if (features & BTRFS_FEATURE_INCOMPAT_MIXED_GROUPS) +- mixed = 1; +- +- flags = BTRFS_BLOCK_GROUP_SYSTEM; +- ret = create_space_info(fs_info, flags); +- if (ret) +- goto out; +- +- if (mixed) { +- flags = BTRFS_BLOCK_GROUP_METADATA | BTRFS_BLOCK_GROUP_DATA; +- ret = create_space_info(fs_info, flags); +- } else { +- flags = BTRFS_BLOCK_GROUP_METADATA; +- ret = create_space_info(fs_info, flags); +- if (ret) +- goto out; +- +- flags = BTRFS_BLOCK_GROUP_DATA; +- ret = create_space_info(fs_info, flags); +- } +-out: +- return ret; +-} +- + int btrfs_error_unpin_extent_range(struct btrfs_fs_info *fs_info, + u64 start, u64 end) + { +--- /dev/null ++++ b/fs/btrfs/space-info.c +@@ -0,0 +1,175 @@ ++// SPDX-License-Identifier: GPL-2.0 ++ ++#include "ctree.h" ++#include "space-info.h" ++#include "sysfs.h" ++#include "volumes.h" ++ ++u64 btrfs_space_info_used(struct btrfs_space_info *s_info, ++ bool may_use_included) ++{ ++ ASSERT(s_info); ++ return s_info->bytes_used + s_info->bytes_reserved + ++ s_info->bytes_pinned + s_info->bytes_readonly + ++ (may_use_included ? s_info->bytes_may_use : 0); ++} ++ ++/* ++ * after adding space to the filesystem, we need to clear the full flags ++ * on all the space infos. ++ */ ++void btrfs_clear_space_info_full(struct btrfs_fs_info *info) ++{ ++ struct list_head *head = &info->space_info; ++ struct btrfs_space_info *found; ++ ++ rcu_read_lock(); ++ list_for_each_entry_rcu(found, head, list) ++ found->full = 0; ++ rcu_read_unlock(); ++} ++ ++static const char *alloc_name(u64 flags) ++{ ++ switch (flags) { ++ case BTRFS_BLOCK_GROUP_METADATA|BTRFS_BLOCK_GROUP_DATA: ++ return "mixed"; ++ case BTRFS_BLOCK_GROUP_METADATA: ++ return "metadata"; ++ case BTRFS_BLOCK_GROUP_DATA: ++ return "data"; ++ case BTRFS_BLOCK_GROUP_SYSTEM: ++ return "system"; ++ default: ++ WARN_ON(1); ++ return "invalid-combination"; ++ }; ++} ++ ++static int create_space_info(struct btrfs_fs_info *info, u64 flags) ++{ ++ ++ struct btrfs_space_info *space_info; ++ int i; ++ int ret; ++ ++ space_info = kzalloc(sizeof(*space_info), GFP_NOFS); ++ if (!space_info) ++ return -ENOMEM; ++ ++ ret = percpu_counter_init(&space_info->total_bytes_pinned, 0, ++ GFP_KERNEL); ++ if (ret) { ++ kfree(space_info); ++ return ret; ++ } ++ ++ for (i = 0; i < BTRFS_NR_RAID_TYPES; i++) ++ INIT_LIST_HEAD(&space_info->block_groups[i]); ++ init_rwsem(&space_info->groups_sem); ++ spin_lock_init(&space_info->lock); ++ space_info->flags = flags & BTRFS_BLOCK_GROUP_TYPE_MASK; ++ space_info->force_alloc = CHUNK_ALLOC_NO_FORCE; ++ init_waitqueue_head(&space_info->wait); ++ INIT_LIST_HEAD(&space_info->ro_bgs); ++ INIT_LIST_HEAD(&space_info->tickets); ++ INIT_LIST_HEAD(&space_info->priority_tickets); ++ ++ ret = kobject_init_and_add(&space_info->kobj, &space_info_ktype, ++ info->space_info_kobj, "%s", ++ alloc_name(space_info->flags)); ++ if (ret) { ++ percpu_counter_destroy(&space_info->total_bytes_pinned); ++ kobject_put(&space_info->kobj); ++ return ret; ++ } ++ ++ list_add_rcu(&space_info->list, &info->space_info); ++ if (flags & BTRFS_BLOCK_GROUP_DATA) ++ info->data_sinfo = space_info; ++ ++ return ret; ++} ++ ++int btrfs_init_space_info(struct btrfs_fs_info *fs_info) ++{ ++ struct btrfs_super_block *disk_super; ++ u64 features; ++ u64 flags; ++ int mixed = 0; ++ int ret; ++ ++ disk_super = fs_info->super_copy; ++ if (!btrfs_super_root(disk_super)) ++ return -EINVAL; ++ ++ features = btrfs_super_incompat_flags(disk_super); ++ if (features & BTRFS_FEATURE_INCOMPAT_MIXED_GROUPS) ++ mixed = 1; ++ ++ flags = BTRFS_BLOCK_GROUP_SYSTEM; ++ ret = create_space_info(fs_info, flags); ++ if (ret) ++ goto out; ++ ++ if (mixed) { ++ flags = BTRFS_BLOCK_GROUP_METADATA | BTRFS_BLOCK_GROUP_DATA; ++ ret = create_space_info(fs_info, flags); ++ } else { ++ flags = BTRFS_BLOCK_GROUP_METADATA; ++ ret = create_space_info(fs_info, flags); ++ if (ret) ++ goto out; ++ ++ flags = BTRFS_BLOCK_GROUP_DATA; ++ ret = create_space_info(fs_info, flags); ++ } ++out: ++ return ret; ++} ++ ++void btrfs_update_space_info(struct btrfs_fs_info *info, u64 flags, ++ u64 total_bytes, u64 bytes_used, ++ u64 bytes_readonly, ++ struct btrfs_space_info **space_info) ++{ ++ struct btrfs_space_info *found; ++ int factor; ++ ++ factor = btrfs_bg_type_to_factor(flags); ++ ++ found = btrfs_find_space_info(info, flags); ++ ASSERT(found); ++ spin_lock(&found->lock); ++ found->total_bytes += total_bytes; ++ found->disk_total += total_bytes * factor; ++ found->bytes_used += bytes_used; ++ found->disk_used += bytes_used * factor; ++ found->bytes_readonly += bytes_readonly; ++ if (total_bytes > 0) ++ found->full = 0; ++ btrfs_space_info_add_new_bytes(info, found, ++ total_bytes - bytes_used - ++ bytes_readonly); ++ spin_unlock(&found->lock); ++ *space_info = found; ++} ++ ++struct btrfs_space_info *btrfs_find_space_info(struct btrfs_fs_info *info, ++ u64 flags) ++{ ++ struct list_head *head = &info->space_info; ++ struct btrfs_space_info *found; ++ ++ flags &= BTRFS_BLOCK_GROUP_TYPE_MASK; ++ ++ rcu_read_lock(); ++ list_for_each_entry_rcu(found, head, list) { ++ if (found->flags & flags) { ++ rcu_read_unlock(); ++ return found; ++ } ++ } ++ rcu_read_unlock(); ++ return NULL; ++} +--- a/fs/btrfs/space-info.h ++++ b/fs/btrfs/space-info.h +@@ -80,5 +80,15 @@ void btrfs_space_info_add_new_bytes(stru + void btrfs_space_info_add_old_bytes(struct btrfs_fs_info *fs_info, + struct btrfs_space_info *space_info, + u64 num_bytes); ++int btrfs_init_space_info(struct btrfs_fs_info *fs_info); ++void btrfs_update_space_info(struct btrfs_fs_info *info, u64 flags, ++ u64 total_bytes, u64 bytes_used, ++ u64 bytes_readonly, ++ struct btrfs_space_info **space_info); ++struct btrfs_space_info *btrfs_find_space_info(struct btrfs_fs_info *info, ++ u64 flags); ++u64 btrfs_space_info_used(struct btrfs_space_info *s_info, ++ bool may_use_included); ++void btrfs_clear_space_info_full(struct btrfs_fs_info *info); + + #endif /* BTRFS_SPACE_INFO_H */ diff --git a/patches.suse/0005-btrfs-only-check-delayed-ref-usage-in-should_end_transaction.patch b/patches.suse/0005-btrfs-only-check-delayed-ref-usage-in-should_end_transaction.patch new file mode 100644 index 0000000..f6b073e --- /dev/null +++ b/patches.suse/0005-btrfs-only-check-delayed-ref-usage-in-should_end_transaction.patch @@ -0,0 +1,39 @@ +From: Josef Bacik +Date: Fri, 29 Sep 2017 15:43:51 -0400 +Subject: Btrfs: only check delayed ref usage in should_end_transaction +Git-commit: 7c777430e855898461d54efd14b3942c763ee8de +Patch-mainline: v4.15-rc1 +References: bsc#1165949 + +We were only doing btrfs_check_space_for_delayed_refs() if the metadata +space was full, ie we couldn't allocate chunks. This assumes we'll be +able to allocate chunks during transaction commit, but since nothing +does a LIMIT flush during the transaction commit this won't actually +happen unless we happen to run shy of actual space. We already take +into account a full fs in btrfs_check_space_for_delayed_refs() so just +kill this extra check to make sure we're ending the transaction when we +need to. + +Signed-off-by: Josef Bacik +Reviewed-by: David Sterba +Signed-off-by: David Sterba +Acked-by: Nikolay Borisov +--- + fs/btrfs/transaction.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c +index 9c5f126064bd..68c3e1c04bca 100644 +--- a/fs/btrfs/transaction.c ++++ b/fs/btrfs/transaction.c +@@ -797,8 +797,7 @@ static int should_end_transaction(struct btrfs_trans_handle *trans) + { + struct btrfs_fs_info *fs_info = trans->fs_info; + +- if (fs_info->global_block_rsv.space_info->full && +- btrfs_check_space_for_delayed_refs(trans, fs_info)) ++ if (btrfs_check_space_for_delayed_refs(trans, fs_info)) + return 1; + + return !!btrfs_block_rsv_check(&fs_info->global_block_rsv, 5); + diff --git a/patches.suse/0005-btrfs-sink-flush_fn-to-extent_write_cache_pages.patch b/patches.suse/0005-btrfs-sink-flush_fn-to-extent_write_cache_pages.patch new file mode 100644 index 0000000..7c403d3 --- /dev/null +++ b/patches.suse/0005-btrfs-sink-flush_fn-to-extent_write_cache_pages.patch @@ -0,0 +1,60 @@ +From 25b860e038915ffb6c3d8d3fe8c46272a8d471fe Mon Sep 17 00:00:00 2001 +From: David Sterba +Date: Fri, 23 Jun 2017 04:30:28 +0200 +Patch-mainline: v4.16 +Git-commit: 25b860e038915ffb6c3d8d3fe8c46272a8d471fe +References: bsc#1168273 +Subject: [PATCH 5/7] btrfs: sink flush_fn to extent_write_cache_pages + +All callers pass the same value flush_write_bio. + +Signed-off-by: David Sterba +--- + fs/btrfs/extent_io.c | 10 ++++------ + 1 file changed, 4 insertions(+), 6 deletions(-) + +diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c +index f1842d59fffe..cf106d46a2fd 100644 +--- a/fs/btrfs/extent_io.c ++++ b/fs/btrfs/extent_io.c +@@ -3906,8 +3906,7 @@ int btree_write_cache_pages(struct address_space *mapping, + */ + static int extent_write_cache_pages(struct address_space *mapping, + struct writeback_control *wbc, +- writepage_t writepage, void *data, +- void (*flush_fn)(void *)) ++ writepage_t writepage, void *data) + { + struct inode *inode = mapping->host; + int ret = 0; +@@ -3971,7 +3970,7 @@ static int extent_write_cache_pages(struct address_space *mapping, + * mapping + */ + if (!trylock_page(page)) { +- flush_fn(data); ++ flush_write_bio(data); + lock_page(page); + } + +@@ -3982,7 +3981,7 @@ static int extent_write_cache_pages(struct address_space *mapping, + + if (wbc->sync_mode != WB_SYNC_NONE) { + if (PageWriteback(page)) +- flush_fn(data); ++ flush_write_bio(data); + wait_on_page_writeback(page); + } + +@@ -4123,8 +4122,7 @@ int extent_writepages(struct extent_io_tree *tree, + .sync_io = wbc->sync_mode == WB_SYNC_ALL, + }; + +- ret = extent_write_cache_pages(mapping, wbc, __extent_writepage, &epd, +- flush_write_bio); ++ ret = extent_write_cache_pages(mapping, wbc, __extent_writepage, &epd); + flush_write_bio(&epd); + return ret; + } +-- +2.26.0 + diff --git a/patches.suse/0005-btrfs-sink-get_extent-parameter-to-extent_fiemap.patch b/patches.suse/0005-btrfs-sink-get_extent-parameter-to-extent_fiemap.patch new file mode 100644 index 0000000..baa77f2 --- /dev/null +++ b/patches.suse/0005-btrfs-sink-get_extent-parameter-to-extent_fiemap.patch @@ -0,0 +1,78 @@ +From 2135fb9bb4b8d05d288d994c4f9f8077ce90d890 Mon Sep 17 00:00:00 2001 +From: David Sterba +Date: Fri, 23 Jun 2017 04:09:57 +0200 +Patch-mainline: v4.16 +Git-commit: 2135fb9bb4b8d05d288d994c4f9f8077ce90d890 +References: bsc#1168273 +Subject: [PATCH 5/7] btrfs: sink get_extent parameter to extent_fiemap + +All callers pass btrfs_get_extent_fiemap and we don't expect anything +else in the context of extent_fiemap. + +Signed-off-by: David Sterba +--- + fs/btrfs/extent_io.c | 6 +++--- + fs/btrfs/extent_io.h | 2 +- + fs/btrfs/inode.c | 2 +- + 3 files changed, 5 insertions(+), 5 deletions(-) + +diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c +index 3ecd3ab73981..d62e0194fc3b 100644 +--- a/fs/btrfs/extent_io.c ++++ b/fs/btrfs/extent_io.c +@@ -4441,7 +4441,7 @@ static int emit_last_fiemap_cache(struct btrfs_fs_info *fs_info, + } + + int extent_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, +- __u64 start, __u64 len, get_extent_t *get_extent) ++ __u64 start, __u64 len) + { + int ret = 0; + u64 off = start; +@@ -4524,7 +4524,7 @@ int extent_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, + &cached_state); + + em = get_extent_skip_holes(inode, start, last_for_get_extent, +- get_extent); ++ btrfs_get_extent_fiemap); + if (!em) + goto out; + if (IS_ERR(em)) { +@@ -4613,7 +4613,7 @@ int extent_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, + + /* now scan forward to see if this is really the last extent. */ + em = get_extent_skip_holes(inode, off, last_for_get_extent, +- get_extent); ++ btrfs_get_extent_fiemap); + if (IS_ERR(em)) { + ret = PTR_ERR(em); + goto out; +diff --git a/fs/btrfs/extent_io.h b/fs/btrfs/extent_io.h +index abe4feea1539..afc169d04b22 100644 +--- a/fs/btrfs/extent_io.h ++++ b/fs/btrfs/extent_io.h +@@ -417,7 +417,7 @@ int extent_readpages(struct extent_io_tree *tree, + struct list_head *pages, unsigned nr_pages, + get_extent_t get_extent); + int extent_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, +- __u64 start, __u64 len, get_extent_t *get_extent); ++ __u64 start, __u64 len); + void set_page_extent_mapped(struct page *page); + + struct extent_buffer *alloc_extent_buffer(struct btrfs_fs_info *fs_info, +diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c +index 7403ef8856bd..63cf6cd174d1 100644 +--- a/fs/btrfs/inode.c ++++ b/fs/btrfs/inode.c +@@ -8859,7 +8859,7 @@ static int btrfs_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, + if (ret) + return ret; + +- return extent_fiemap(inode, fieinfo, start, len, btrfs_get_extent_fiemap); ++ return extent_fiemap(inode, fieinfo, start, len); + } + + int btrfs_readpage(struct file *file, struct page *page) +-- +2.26.0 + diff --git a/patches.suse/0005-efi-generate-secret-key-in-EFI-boot-environment.patch b/patches.suse/0005-efi-generate-secret-key-in-EFI-boot-environment.patch index 4279dd0..7b11c40 100644 --- a/patches.suse/0005-efi-generate-secret-key-in-EFI-boot-environment.patch +++ b/patches.suse/0005-efi-generate-secret-key-in-EFI-boot-environment.patch @@ -57,7 +57,7 @@ Signed-off-by: Lee, Chun-Yi --- a/arch/x86/boot/compressed/eboot.c +++ b/arch/x86/boot/compressed/eboot.c -@@ -1001,6 +1001,9 @@ struct boot_params *efi_main(struct efi_ +@@ -1021,6 +1021,9 @@ struct boot_params *efi_main(struct efi_ setup_efi_pci(boot_params); @@ -282,7 +282,7 @@ Signed-off-by: Lee, Chun-Yi +} --- a/arch/x86/boot/compressed/misc.c +++ b/arch/x86/boot/compressed/misc.c -@@ -412,7 +412,7 @@ asmlinkage __visible void *extract_kerne +@@ -445,7 +445,7 @@ asmlinkage __visible void *extract_kerne return output; } @@ -328,7 +328,7 @@ Signed-off-by: Lee, Chun-Yi unsigned long input_size, --- a/arch/x86/include/asm/efi.h +++ b/arch/x86/include/asm/efi.h -@@ -162,6 +162,16 @@ static inline bool efi_runtime_supported +@@ -175,6 +175,16 @@ static inline bool efi_runtime_supported extern struct console early_efi_console; extern void parse_efi_setup(u64 phys_addr, u32 data_len); @@ -345,7 +345,7 @@ Signed-off-by: Lee, Chun-Yi extern void efifb_setup_from_dmi(struct screen_info *si, const char *opt); #ifdef CONFIG_EFI_MIXED -@@ -235,6 +245,9 @@ extern bool efi_reboot_required(void); +@@ -249,6 +259,9 @@ extern bool efi_is_table_address(unsigne #else static inline void parse_efi_setup(u64 phys_addr, u32 data_len) {} @@ -367,7 +367,7 @@ Signed-off-by: Lee, Chun-Yi #define RAMDISK_IMAGE_START_MASK 0x07FF --- a/arch/x86/kernel/setup.c +++ b/arch/x86/kernel/setup.c -@@ -419,10 +419,22 @@ static void __init reserve_initrd(void) +@@ -411,10 +411,22 @@ static void __init reserve_initrd(void) } #endif /* CONFIG_BLK_DEV_INITRD */ @@ -391,7 +391,7 @@ Signed-off-by: Lee, Chun-Yi pa_data = boot_params.hdr.setup_data; while (pa_data) { -@@ -444,9 +456,14 @@ static void __init parse_setup_data(void +@@ -436,9 +448,14 @@ static void __init parse_setup_data(void case SETUP_EFI: parse_efi_setup(pa_data, data_len); break; @@ -408,9 +408,9 @@ Signed-off-by: Lee, Chun-Yi } --- a/drivers/firmware/efi/Kconfig +++ b/drivers/firmware/efi/Kconfig -@@ -142,6 +142,22 @@ config APPLE_PROPERTIES +@@ -155,6 +155,22 @@ config EFI_RCI2_TABLE - If unsure, say Y if you have a Mac. Otherwise N. + Say Y here for Dell EMC PowerEdge systems. +config EFI_SECRET_KEY + bool "EFI secret key" @@ -433,7 +433,7 @@ Signed-off-by: Lee, Chun-Yi config UEFI_CPER --- a/drivers/firmware/efi/Makefile +++ b/drivers/firmware/efi/Makefile -@@ -29,3 +29,4 @@ arm-obj-$(CONFIG_EFI) := arm-init.o ar +@@ -30,3 +30,4 @@ arm-obj-$(CONFIG_EFI) := arm-init.o ar obj-$(CONFIG_ARM) += $(arm-obj-y) obj-$(CONFIG_ARM64) += $(arm-obj-y) obj-$(CONFIG_EFI_CAPSULE_LOADER) += capsule-loader.o @@ -527,7 +527,7 @@ Signed-off-by: Lee, Chun-Yi +late_initcall(init_efi_secret_key); --- a/include/linux/efi.h +++ b/include/linux/efi.h -@@ -1617,4 +1617,23 @@ efi_status_to_str(efi_status_t status) +@@ -1656,4 +1656,23 @@ efi_status_to_str(efi_status_t status) return ""; } diff --git a/patches.suse/0005-mm-Use-overflow-helpers-in-kvmalloc.patch b/patches.suse/0005-mm-Use-overflow-helpers-in-kvmalloc.patch new file mode 100644 index 0000000..92023a5 --- /dev/null +++ b/patches.suse/0005-mm-Use-overflow-helpers-in-kvmalloc.patch @@ -0,0 +1,62 @@ +From 3b3b1a29eb89ba93f91213cbebb332a2ac31fa8b Mon Sep 17 00:00:00 2001 +From: Kees Cook +Date: Tue, 8 May 2018 12:55:26 -0700 +Subject: [PATCH] mm: Use overflow helpers in kvmalloc() +Git-commit: 3b3b1a29eb89ba93f91213cbebb332a2ac31fa8b +Patch-mainline: v4.18-rc1 +References: bsc#1166003 + +Instead of open-coded multiplication and bounds checking, use the new +overflow helper. Additionally prepare for vmalloc() users to add +array_size()-family helpers in the future. + +Signed-off-by: Kees Cook +Signed-off-by: Coly Li + +--- + include/linux/mm.h | 7 +++++-- + include/linux/vmalloc.h | 1 + + 2 files changed, 6 insertions(+), 2 deletions(-) + +diff --git a/include/linux/mm.h b/include/linux/mm.h +index 1ac1f06a4be6..7cb1c6a6bf82 100644 +--- a/include/linux/mm.h ++++ b/include/linux/mm.h +@@ -25,6 +25,7 @@ + #include + #include + #include ++#include + + struct mempolicy; + struct anon_vma; +@@ -560,10 +561,12 @@ static inline void *kvzalloc(size_t size, gfp_t flags) + + static inline void *kvmalloc_array(size_t n, size_t size, gfp_t flags) + { +- if (size != 0 && n > SIZE_MAX / size) ++ size_t bytes; ++ ++ if (unlikely(check_mul_overflow(n, size, &bytes))) + return NULL; + +- return kvmalloc(n * size, flags); ++ return kvmalloc(bytes, flags); + } + + extern void kvfree(const void *addr); +diff --git a/include/linux/vmalloc.h b/include/linux/vmalloc.h +index 1e5d8c392f15..398e9c95cd61 100644 +--- a/include/linux/vmalloc.h ++++ b/include/linux/vmalloc.h +@@ -8,6 +8,7 @@ + #include + #include /* pgprot_t */ + #include ++#include + + struct vm_area_struct; /* vma defining user mapping in mm_types.h */ + struct notifier_block; /* in notifier.h */ +-- +2.25.0 + diff --git a/patches.suse/0006-btrfs-assert-on-non-empty-delayed-iputs.patch b/patches.suse/0006-btrfs-assert-on-non-empty-delayed-iputs.patch new file mode 100644 index 0000000..20da38d --- /dev/null +++ b/patches.suse/0006-btrfs-assert-on-non-empty-delayed-iputs.patch @@ -0,0 +1,33 @@ +From: Josef Bacik +Date: Fri, 28 Sep 2018 07:18:03 -0400 +Subject: btrfs: assert on non-empty delayed iputs +Git-commit: e187831e1875b2754a3ba3c683bd277d4a5f7be8 +Patch-mainline: v4.20-rc1 +References: bsc##1165949 + +I ran into an issue where there was some reference being held on an +inode that I couldn't track. This assert wasn't triggered, but it at +least rules out we're doing something stupid. + +Reviewed-by: Omar Sandoval +Signed-off-by: Josef Bacik +Reviewed-by: David Sterba +Signed-off-by: David Sterba +Acked-by: Nikolay Borisov +--- + fs/btrfs/disk-io.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c +index 27f6a3348f94..b0ab41da91d1 100644 +--- a/fs/btrfs/disk-io.c ++++ b/fs/btrfs/disk-io.c +@@ -3976,6 +3976,7 @@ void close_ctree(struct btrfs_fs_info *fs_info) + kthread_stop(fs_info->transaction_kthread); + kthread_stop(fs_info->cleaner_kthread); + ++ ASSERT(list_empty(&fs_info->delayed_iputs)); + set_bit(BTRFS_FS_CLOSING_DONE, &fs_info->flags); + + btrfs_free_qgroup_config(fs_info); + diff --git a/patches.suse/0006-btrfs-dump-block_rsv-details-when-dumping-space-info.patch b/patches.suse/0006-btrfs-dump-block_rsv-details-when-dumping-space-info.patch new file mode 100644 index 0000000..1bf006d --- /dev/null +++ b/patches.suse/0006-btrfs-dump-block_rsv-details-when-dumping-space-info.patch @@ -0,0 +1,53 @@ +From: Josef Bacik +Date: Wed, 21 Nov 2018 14:03:07 -0500 +Subject: btrfs: dump block_rsv details when dumping space info +Git-commit: b78e5616afef09bcee3d365bf42547e2c1e8d87a +Patch-mainline: v5.1-rc1 +References: bsc#1165949 + +For enospc_debug having the block rsvs is super helpful to see if we've +done something wrong. + +Reviewed-by: Omar Sandoval +Signed-off-by: Josef Bacik +Reviewed-by: David Sterba +Signed-off-by: David Sterba +Acked-by: Nikolay Borisov +--- + fs/btrfs/extent-tree.c | 15 +++++++++++++++ + 1 file changed, 15 insertions(+) + +diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c +index b85cd66ac583..9e74ce2d4cf2 100644 +--- a/fs/btrfs/extent-tree.c ++++ b/fs/btrfs/extent-tree.c +@@ -8086,6 +8086,15 @@ static noinline int find_free_extent(struct btrfs_fs_info *fs_info, + return ret; + } + ++#define DUMP_BLOCK_RSV(fs_info, rsv_name) \ ++do { \ ++ struct btrfs_block_rsv *__rsv = &(fs_info)->rsv_name; \ ++ spin_lock(&__rsv->lock); \ ++ btrfs_info(fs_info, #rsv_name ": size %llu reserved %llu", \ ++ __rsv->size, __rsv->reserved); \ ++ spin_unlock(&__rsv->lock); \ ++} while (0) ++ + static void dump_space_info(struct btrfs_fs_info *fs_info, + struct btrfs_space_info *info, u64 bytes, + int dump_block_groups) +@@ -8105,6 +8114,12 @@ static void dump_space_info(struct btrfs_fs_info *fs_info, + info->bytes_readonly); + spin_unlock(&info->lock); + ++ DUMP_BLOCK_RSV(fs_info, global_block_rsv); ++ DUMP_BLOCK_RSV(fs_info, trans_block_rsv); ++ DUMP_BLOCK_RSV(fs_info, chunk_block_rsv); ++ DUMP_BLOCK_RSV(fs_info, delayed_block_rsv); ++ DUMP_BLOCK_RSV(fs_info, delayed_refs_rsv); ++ + if (!dump_block_groups) + return; + + diff --git a/patches.suse/0006-btrfs-export-the-block-group-caching-helpers.patch b/patches.suse/0006-btrfs-export-the-block-group-caching-helpers.patch new file mode 100644 index 0000000..fac32b3 --- /dev/null +++ b/patches.suse/0006-btrfs-export-the-block-group-caching-helpers.patch @@ -0,0 +1,229 @@ +From: Josef Bacik +Date: Thu, 20 Jun 2019 15:37:48 -0400 +Subject: btrfs: export the block group caching helpers +Git-commit: 676f1f759fa3f65f8987295c99615c1090e074ea +Patch-mainline: v5.4-rc1 +References: bsc#1165949 + +This will make it so we can move them easily. + +Signed-off-by: Josef Bacik +Reviewed-by: David Sterba +[ coding style updates ] +Signed-off-by: David Sterba +Acked-by: Nikolay Borisov +--- + fs/btrfs/block-group.h | 13 ++++++++++ + fs/btrfs/extent-tree.c | 59 ++++++++++++++++++++----------------------------- + 2 files changed, 38 insertions(+), 34 deletions(-) + +--- a/fs/btrfs/block-group.h ++++ b/fs/btrfs/block-group.h +@@ -165,5 +165,18 @@ void btrfs_wait_block_group_reservations + bool btrfs_inc_nocow_writers(struct btrfs_fs_info *fs_info, u64 bytenr); + void btrfs_dec_nocow_writers(struct btrfs_fs_info *fs_info, u64 bytenr); + void btrfs_wait_nocow_writers(struct btrfs_block_group_cache *bg); ++void btrfs_wait_block_group_cache_progress(struct btrfs_block_group_cache *cache, ++ u64 num_bytes); ++int btrfs_wait_block_group_cache_done(struct btrfs_block_group_cache *cache); ++int btrfs_cache_block_group(struct btrfs_block_group_cache *cache, ++ int load_cache_only); ++ ++static inline int btrfs_block_group_cache_done( ++ struct btrfs_block_group_cache *cache) ++{ ++ smp_mb(); ++ return cache->cached == BTRFS_CACHE_FINISHED || ++ cache->cached == BTRFS_CACHE_ERROR; ++} + + #endif /* BTRFS_BLOCK_GROUP_H */ +--- a/fs/btrfs/extent-tree.c ++++ b/fs/btrfs/extent-tree.c +@@ -76,14 +76,6 @@ static int btrfs_add_reserved_bytes(stru + static int btrfs_free_reserved_bytes(struct btrfs_block_group_cache *cache, + u64 num_bytes, int delalloc); + +-static noinline int +-block_group_cache_done(struct btrfs_block_group_cache *cache) +-{ +- smp_mb(); +- return cache->cached == BTRFS_CACHE_FINISHED || +- cache->cached == BTRFS_CACHE_ERROR; +-} +- + static int block_group_bits(struct btrfs_block_group_cache *cache, u64 bits) + { + return (cache->flags & bits) == bits; +@@ -256,9 +248,10 @@ static void fragment_free_space(struct b + #endif + + /* +- * this is only called by cache_block_group, since we could have freed extents +- * we need to check the pinned_extents for any extents that can't be used yet +- * since their free space will be released as soon as the transaction commits. ++ * This is only called by btrfs_cache_block_group, since we could have freed ++ * extents we need to check the pinned_extents for any extents that can't be ++ * used yet since their free space will be released as soon as the transaction ++ * commits. + */ + u64 add_new_free_space(struct btrfs_block_group_cache *block_group, + struct btrfs_fs_info *info, u64 start, u64 end) +@@ -489,8 +482,8 @@ static noinline void caching_thread(stru + btrfs_put_block_group(block_group); + } + +-static int cache_block_group(struct btrfs_block_group_cache *cache, +- int load_cache_only) ++int btrfs_cache_block_group(struct btrfs_block_group_cache *cache, ++ int load_cache_only) + { + DEFINE_WAIT(wait); + struct btrfs_fs_info *fs_info = cache->fs_info; +@@ -4198,7 +4191,7 @@ static int update_block_group(struct btr + * space back to the block group, otherwise we will leak space. + */ + if (!alloc && cache->cached == BTRFS_CACHE_NO) +- cache_block_group(cache, 1); ++ btrfs_cache_block_group(cache, 1); + + byte_in_group = bytenr - cache->key.objectid; + WARN_ON(byte_in_group > cache->key.offset); +@@ -4360,7 +4353,7 @@ int btrfs_pin_extent_for_log_replay(stru + * to one because the slow code to read in the free extents does check + * the pinned extents. + */ +- cache_block_group(cache, 1); ++ btrfs_cache_block_group(cache, 1); + + pin_down_extent(fs_info, cache, bytenr, num_bytes, 0); + +@@ -4381,12 +4374,12 @@ static int __exclude_logged_extent(struc + if (!block_group) + return -EINVAL; + +- cache_block_group(block_group, 0); ++ btrfs_cache_block_group(block_group, 0); + caching_ctl = get_caching_control(block_group); + + if (!caching_ctl) { + /* Logic error */ +- BUG_ON(!block_group_cache_done(block_group)); ++ BUG_ON(!btrfs_block_group_cache_done(block_group)); + ret = btrfs_remove_free_space(block_group, start, num_bytes); + } else { + mutex_lock(&caching_ctl->mutex); +@@ -4533,7 +4526,7 @@ void btrfs_prepare_extent_commit(struct + list_for_each_entry_safe(caching_ctl, next, + &fs_info->caching_block_groups, list) { + cache = caching_ctl->block_group; +- if (block_group_cache_done(cache)) { ++ if (btrfs_block_group_cache_done(cache)) { + cache->last_byte_to_unpin = (u64)-1; + list_del_init(&caching_ctl->list); + put_caching_control(caching_ctl); +@@ -5187,9 +5180,8 @@ int btrfs_free_extent(struct btrfs_trans + * Callers of this must check if cache->cached == BTRFS_CACHE_ERROR before using + * any of the information in this block group. + */ +-static noinline void +-wait_block_group_cache_progress(struct btrfs_block_group_cache *cache, +- u64 num_bytes) ++void btrfs_wait_block_group_cache_progress(struct btrfs_block_group_cache *cache, ++ u64 num_bytes) + { + struct btrfs_caching_control *caching_ctl; + +@@ -5197,14 +5189,13 @@ wait_block_group_cache_progress(struct b + if (!caching_ctl) + return; + +- wait_event(caching_ctl->wait, block_group_cache_done(cache) || ++ wait_event(caching_ctl->wait, btrfs_block_group_cache_done(cache) || + (cache->free_space_ctl->free_space >= num_bytes)); + + put_caching_control(caching_ctl); + } + +-static noinline int +-wait_block_group_cache_done(struct btrfs_block_group_cache *cache) ++int btrfs_wait_block_group_cache_done(struct btrfs_block_group_cache *cache) + { + struct btrfs_caching_control *caching_ctl; + int ret = 0; +@@ -5213,7 +5204,7 @@ wait_block_group_cache_done(struct btrfs + if (!caching_ctl) + return (cache->cached == BTRFS_CACHE_ERROR) ? -EIO : 0; + +- wait_event(caching_ctl->wait, block_group_cache_done(cache)); ++ wait_event(caching_ctl->wait, btrfs_block_group_cache_done(cache)); + if (cache->cached == BTRFS_CACHE_ERROR) + ret = -EIO; + put_caching_control(caching_ctl); +@@ -5491,10 +5482,10 @@ search: + } + + have_block_group: +- cached = block_group_cache_done(block_group); ++ cached = btrfs_block_group_cache_done(block_group); + if (unlikely(!cached)) { + have_caching_bg = true; +- ret = cache_block_group(block_group, 0); ++ ret = btrfs_cache_block_group(block_group, 0); + BUG_ON(ret < 0); + ret = 0; + } +@@ -5615,7 +5606,7 @@ refill_cluster: + spin_unlock(&last_ptr->refill_lock); + + failed_cluster_refill = true; +- wait_block_group_cache_progress(block_group, ++ btrfs_wait_block_group_cache_progress(block_group, + num_bytes + empty_cluster + empty_size); + goto have_block_group; + } +@@ -5671,7 +5662,7 @@ unclustered_alloc: + */ + if (!offset && !failed_alloc && !cached && + loop > LOOP_CACHING_NOWAIT) { +- wait_block_group_cache_progress(block_group, ++ btrfs_wait_block_group_cache_progress(block_group, + num_bytes + empty_size); + failed_alloc = true; + goto have_block_group; +@@ -7661,7 +7652,7 @@ void btrfs_put_block_group_cache(struct + + block_group = btrfs_lookup_first_block_group(info, last); + while (block_group) { +- wait_block_group_cache_done(block_group); ++ btrfs_wait_block_group_cache_done(block_group); + spin_lock(&block_group->lock); + if (block_group->iref) + break; +@@ -8414,7 +8405,7 @@ int btrfs_remove_block_group(struct btrf + if (block_group->has_caching_ctl) + caching_ctl = get_caching_control(block_group); + if (block_group->cached == BTRFS_CACHE_STARTED) +- wait_block_group_cache_done(block_group); ++ btrfs_wait_block_group_cache_done(block_group); + if (block_group->has_caching_ctl) { + down_write(&fs_info->commit_root_sem); + if (!caching_ctl) { +@@ -8899,14 +8890,14 @@ int btrfs_trim_fs(struct btrfs_fs_info * + cache->key.objectid + cache->key.offset); + + if (end - start >= range->minlen) { +- if (!block_group_cache_done(cache)) { +- ret = cache_block_group(cache, 0); ++ if (!btrfs_block_group_cache_done(cache)) { ++ ret = btrfs_cache_block_group(cache, 0); + if (ret) { + bg_failed++; + bg_ret = ret; + continue; + } +- ret = wait_block_group_cache_done(cache); ++ ret = btrfs_wait_block_group_cache_done(cache); + if (ret) { + bg_failed++; + bg_ret = ret; diff --git a/patches.suse/0006-btrfs-extent_io-add-proper-error-handling-to-lock_ex.patch b/patches.suse/0006-btrfs-extent_io-add-proper-error-handling-to-lock_ex.patch new file mode 100644 index 0000000..a72761e --- /dev/null +++ b/patches.suse/0006-btrfs-extent_io-add-proper-error-handling-to-lock_ex.patch @@ -0,0 +1,93 @@ +From 2e3c25136adfb293d517e17f761d3b8a43a8fc22 Mon Sep 17 00:00:00 2001 +From: Qu Wenruo +Date: Wed, 20 Mar 2019 14:27:46 +0800 +Patch-mainline: v5.2 +Git-commit: 2e3c25136adfb293d517e17f761d3b8a43a8fc22 +References: bsc#1168273 +Subject: [PATCH 6/7] btrfs: extent_io: add proper error handling to + lock_extent_buffer_for_io() + +This function needs some extra checks on locked pages and eb. For error +handling we need to unlock locked pages and the eb. + +There is a rare >0 return value branch, where all pages get locked +while write bio is not flushed. + +Thankfully it's handled by the only caller, btree_write_cache_pages(), +as later write_one_eb() call will trigger submit_one_bio(). So there +shouldn't be any problem. + +Signed-off-by: Qu Wenruo +Reviewed-by: David Sterba +Signed-off-by: David Sterba +--- + fs/btrfs/extent_io.c | 27 ++++++++++++++++++++++----- + 1 file changed, 22 insertions(+), 5 deletions(-) + +--- a/fs/btrfs/extent_io.c ++++ b/fs/btrfs/extent_io.c +@@ -3611,19 +3611,27 @@ void wait_on_extent_buffer_writeback(str + TASK_UNINTERRUPTIBLE); + } + ++/* ++ * Lock eb pages and flush the bio if we can't the locks ++ * ++ * Return 0 if nothing went wrong ++ * Return >0 is same as 0, except bio is not submitted ++ * Return <0 if something went wrong, no page is locked ++ */ + static noinline_for_stack int + lock_extent_buffer_for_io(struct extent_buffer *eb, + struct btrfs_fs_info *fs_info, + struct extent_page_data *epd) + { +- unsigned long i, num_pages; ++ unsigned long i, num_pages, failed_page_nr; + int flush = 0; + int ret = 0; + + if (!btrfs_try_tree_write_lock(eb)) { +- flush = 1; + ret = flush_write_bio(epd); +- BUG_ON(ret < 0); ++ if (ret < 0) ++ return ret; ++ flush = 1; + btrfs_tree_lock(eb); + } + +@@ -3633,7 +3641,8 @@ lock_extent_buffer_for_io(struct extent_ + return 0; + if (!flush) { + ret = flush_write_bio(epd); +- BUG_ON(ret < 0); ++ if (ret < 0) ++ return ret; + flush = 1; + } + while (1) { +@@ -3675,7 +3684,10 @@ lock_extent_buffer_for_io(struct extent_ + if (!trylock_page(p)) { + if (!flush) { + ret = flush_write_bio(epd); +- BUG_ON(ret < 0); ++ if (ret < 0) { ++ failed_page_nr = i; ++ goto err_unlock; ++ } + flush = 1; + } + lock_page(p); +@@ -3683,6 +3695,11 @@ lock_extent_buffer_for_io(struct extent_ + } + + return ret; ++err_unlock: ++ /* Unlock already locked pages */ ++ for (i = 0; i < failed_page_nr; i++) ++ unlock_page(eb->pages[i]); ++ return ret; + } + + static void end_extent_buffer_writeback(struct extent_buffer *eb) diff --git a/patches.suse/0006-btrfs-move-and-export-can_overcommit.patch b/patches.suse/0006-btrfs-move-and-export-can_overcommit.patch new file mode 100644 index 0000000..68746c8 --- /dev/null +++ b/patches.suse/0006-btrfs-move-and-export-can_overcommit.patch @@ -0,0 +1,224 @@ +From: Josef Bacik +Date: Tue, 18 Jun 2019 16:09:20 -0400 +Subject: btrfs: move and export can_overcommit +Git-commit: 41783ef24d56ce45452db7c413df9a3bdcc8d651 +Patch-mainline: v5.3-rc1 +References: bsc#1165949 + +This is the first piece of moving the space reservation code to +space-info.c + +Reviewed-by: Nikolay Borisov +Signed-off-by: Josef Bacik +Signed-off-by: David Sterba +Acked-by: Nikolay Borisov +--- + fs/btrfs/extent-tree.c | 74 ++----------------------------------------------- + fs/btrfs/space-info.c | 70 ++++++++++++++++++++++++++++++++++++++++++++++ + fs/btrfs/space-info.h | 3 + + 3 files changed, 77 insertions(+), 70 deletions(-) + +--- a/fs/btrfs/extent-tree.c ++++ b/fs/btrfs/extent-tree.c +@@ -4374,11 +4374,6 @@ static void force_metadata_allocation(st + rcu_read_unlock(); + } + +-static inline u64 calc_global_rsv_need_space(struct btrfs_block_rsv *global) +-{ +- return (global->size << 1); +-} +- + static int should_alloc_chunk(struct btrfs_fs_info *fs_info, + struct btrfs_space_info *sinfo, int force) + { +@@ -4608,67 +4603,6 @@ out: + return ret; + } + +-static int can_overcommit(struct btrfs_root *root, +- struct btrfs_space_info *space_info, u64 bytes, +- enum btrfs_reserve_flush_enum flush) +-{ +- struct btrfs_fs_info *fs_info = root->fs_info; +- struct btrfs_block_rsv *global_rsv = &fs_info->global_block_rsv; +- u64 profile; +- u64 space_size; +- u64 avail; +- u64 used; +- int factor; +- +- /* Don't overcommit when in mixed mode. */ +- if (space_info->flags & BTRFS_BLOCK_GROUP_DATA) +- return 0; +- +- profile = get_alloc_profile_by_root(root, 0); +- used = btrfs_space_info_used(space_info, false); +- +- /* +- * We only want to allow over committing if we have lots of actual space +- * free, but if we don't have enough space to handle the global reserve +- * space then we could end up having a real enospc problem when trying +- * to allocate a chunk or some other such important allocation. +- */ +- spin_lock(&global_rsv->lock); +- space_size = calc_global_rsv_need_space(global_rsv); +- spin_unlock(&global_rsv->lock); +- if (used + space_size >= space_info->total_bytes) +- return 0; +- +- used += space_info->bytes_may_use; +- +- spin_lock(&fs_info->free_chunk_lock); +- avail = fs_info->free_chunk_space; +- spin_unlock(&fs_info->free_chunk_lock); +- +- /* +- * If we have dup, raid1 or raid10 then only half of the free +- * space is actually useable. For raid56, the space info used +- * doesn't include the parity drive, so we don't have to +- * change the math +- */ +- factor = btrfs_bg_type_to_factor(profile); +- avail = div_u64(avail, factor); +- +- /* +- * If we aren't flushing all things, let us overcommit up to +- * 1/2th of the space. If we can flush, don't let us overcommit +- * too much, let it overcommit up to 1/8 of the space. +- */ +- if (flush == BTRFS_RESERVE_FLUSH_ALL) +- avail >>= 3; +- else +- avail >>= 1; +- +- if (used + bytes < space_info->total_bytes + avail) +- return 1; +- return 0; +-} +- + static void btrfs_writeback_inodes_sb_nr(struct btrfs_fs_info *fs_info, + unsigned long nr_pages, int nr_items) + { +@@ -4984,14 +4918,14 @@ btrfs_calc_reclaim_metadata_size(struct + return to_reclaim; + + to_reclaim = min_t(u64, num_online_cpus() * SZ_1M, SZ_16M); +- if (can_overcommit(root, space_info, to_reclaim, ++ if (btrfs_can_overcommit(root, space_info, to_reclaim, + BTRFS_RESERVE_FLUSH_ALL)) + return 0; + + used = space_info->bytes_used + space_info->bytes_reserved + + space_info->bytes_pinned + space_info->bytes_readonly + + space_info->bytes_may_use; +- if (can_overcommit(root, space_info, SZ_1M, BTRFS_RESERVE_FLUSH_ALL)) ++ if (btrfs_can_overcommit(root, space_info, SZ_1M, BTRFS_RESERVE_FLUSH_ALL)) + expected = div_factor_fine(space_info->total_bytes, 95); + else + expected = div_factor_fine(space_info->total_bytes, 90); +@@ -5240,7 +5174,7 @@ static int __reserve_metadata_bytes(stru + trace_btrfs_space_reservation(fs_info, "space_info", + space_info->flags, orig_bytes, 1); + ret = 0; +- } else if (can_overcommit(root, space_info, orig_bytes, flush)) { ++ } else if (btrfs_can_overcommit(root, space_info, orig_bytes, flush)) { + update_bytes_may_use(fs_info, space_info, orig_bytes); + trace_btrfs_space_reservation(fs_info, "space_info", + space_info->flags, orig_bytes, 1); +@@ -5551,7 +5485,7 @@ again: + * adding the ticket space would be a double count. + */ + if (check_overcommit && +- !can_overcommit(fs_info->extent_root, space_info, 0, ++ !btrfs_can_overcommit(fs_info->extent_root, space_info, 0, + flush)) + break; + if (num_bytes >= ticket->bytes) { +--- a/fs/btrfs/space-info.c ++++ b/fs/btrfs/space-info.c +@@ -173,3 +173,73 @@ struct btrfs_space_info *btrfs_find_spac + rcu_read_unlock(); + return NULL; + } ++ ++static inline u64 calc_global_rsv_need_space(struct btrfs_block_rsv *global) ++{ ++ return (global->size << 1); ++} ++ ++int btrfs_can_overcommit(struct btrfs_root *root, ++ struct btrfs_space_info *space_info, u64 bytes, ++ enum btrfs_reserve_flush_enum flush) ++{ ++ struct btrfs_fs_info *fs_info = root->fs_info; ++ struct btrfs_block_rsv *global_rsv = &fs_info->global_block_rsv; ++ u64 profile; ++ u64 space_size; ++ u64 avail; ++ u64 used; ++ int factor; ++ ++ /* Don't overcommit when in mixed mode. */ ++ if (space_info->flags & BTRFS_BLOCK_GROUP_DATA) ++ return 0; ++ ++ if (space_info->flags & BTRFS_BLOCK_GROUP_METADATA) ++ profile = btrfs_metadata_alloc_profile(fs_info); ++ else ++ profile = btrfs_system_alloc_profile(fs_info); ++ ++ used = btrfs_space_info_used(space_info, false); ++ ++ /* ++ * We only want to allow over committing if we have lots of actual space ++ * free, but if we don't have enough space to handle the global reserve ++ * space then we could end up having a real enospc problem when trying ++ * to allocate a chunk or some other such important allocation. ++ */ ++ spin_lock(&global_rsv->lock); ++ space_size = calc_global_rsv_need_space(global_rsv); ++ spin_unlock(&global_rsv->lock); ++ if (used + space_size >= space_info->total_bytes) ++ return 0; ++ ++ used += space_info->bytes_may_use; ++ ++ spin_lock(&fs_info->free_chunk_lock); ++ avail = fs_info->free_chunk_space; ++ spin_unlock(&fs_info->free_chunk_lock); ++ ++ /* ++ * If we have dup, raid1 or raid10 then only half of the free ++ * space is actually useable. For raid56, the space info used ++ * doesn't include the parity drive, so we don't have to ++ * change the math ++ */ ++ factor = btrfs_bg_type_to_factor(profile); ++ avail = div_u64(avail, factor); ++ ++ /* ++ * If we aren't flushing all things, let us overcommit up to ++ * 1/2th of the space. If we can flush, don't let us overcommit ++ * too much, let it overcommit up to 1/8 of the space. ++ */ ++ if (flush == BTRFS_RESERVE_FLUSH_ALL) ++ avail >>= 3; ++ else ++ avail >>= 1; ++ ++ if (used + bytes < space_info->total_bytes + avail) ++ return 1; ++ return 0; ++} +--- a/fs/btrfs/space-info.h ++++ b/fs/btrfs/space-info.h +@@ -90,5 +90,8 @@ struct btrfs_space_info *btrfs_find_spac + u64 btrfs_space_info_used(struct btrfs_space_info *s_info, + bool may_use_included); + void btrfs_clear_space_info_full(struct btrfs_fs_info *info); ++int btrfs_can_overcommit(struct btrfs_root *root, ++ struct btrfs_space_info *space_info, u64 bytes, ++ enum btrfs_reserve_flush_enum flush); + + #endif /* BTRFS_SPACE_INFO_H */ diff --git a/patches.suse/0006-btrfs-rename-the-btrfs_calc_-metadata_size-helpers.patch b/patches.suse/0006-btrfs-rename-the-btrfs_calc_-metadata_size-helpers.patch new file mode 100644 index 0000000..25267fe --- /dev/null +++ b/patches.suse/0006-btrfs-rename-the-btrfs_calc_-metadata_size-helpers.patch @@ -0,0 +1,283 @@ +From: Josef Bacik +Date: Thu, 22 Aug 2019 15:14:33 -0400 +Subject: btrfs: rename the btrfs_calc_*_metadata_size helpers +Git-commit: 2bd36e7b4fd60d4ff5f9ba6a0ad84557ae4803c4 +Patch-mainline: v5.4-rc1 +References: bsc#1165949 + +btrfs_calc_trunc_metadata_size differs from trans_metadata_size in that +it doesn't take into account any splitting at the levels, because +truncate will never split nodes. However truncate _and_ changing will +never split nodes, so rename btrfs_calc_trunc_metadata_size to +btrfs_calc_metadata_size. Also btrfs_calc_trans_metadata_size is purely +for inserting items, so rename this to btrfs_calc_insert_metadata_size. +Making these clearer will help when I start using them differently in +upcoming patches. + +Reviewed-by: Nikolay Borisov +Signed-off-by: Josef Bacik +Reviewed-by: David Sterba +Signed-off-by: David Sterba +Acked-by: Nikolay Borisov +--- + fs/btrfs/block-group.c | 4 ++-- + fs/btrfs/ctree.h | 14 +++++++++----- + fs/btrfs/delalloc-space.c | 8 ++++---- + fs/btrfs/delayed-inode.c | 4 ++-- + fs/btrfs/delayed-ref.c | 8 ++++---- + fs/btrfs/file.c | 4 ++-- + fs/btrfs/free-space-cache.c | 4 ++-- + fs/btrfs/inode-map.c | 2 +- + fs/btrfs/inode.c | 6 +++--- + fs/btrfs/props.c | 2 +- + fs/btrfs/root-tree.c | 2 +- + fs/btrfs/space-info.c | 2 +- + fs/btrfs/transaction.c | 4 ++-- + 13 files changed, 34 insertions(+), 30 deletions(-) + +--- a/fs/btrfs/block-group.c ++++ b/fs/btrfs/block-group.c +@@ -3045,8 +3045,8 @@ void check_system_chunk(struct btrfs_tra + num_devs = get_profile_num_devs(fs_info, type); + + /* num_devs device items to update and 1 chunk item to add or remove */ +- thresh = btrfs_calc_trunc_metadata_size(fs_info, num_devs) + +- btrfs_calc_trans_metadata_size(fs_info, 1); ++ thresh = btrfs_calc_metadata_size(fs_info, num_devs) + ++ btrfs_calc_insert_metadata_size(fs_info, 1); + + if (left < thresh && btrfs_test_opt(fs_info, ENOSPC_DEBUG)) { + btrfs_info(fs_info, "left=%llu, need=%llu, flags=%llu", +--- a/fs/btrfs/ctree.h ++++ b/fs/btrfs/ctree.h +@@ -2440,17 +2440,21 @@ u64 hash_extent_data_ref(u64 root_object + + u64 btrfs_csum_bytes_to_leaves(struct btrfs_fs_info *fs_info, u64 csum_bytes); + +-static inline u64 btrfs_calc_trans_metadata_size(struct btrfs_fs_info *fs_info, +- unsigned num_items) ++/* ++ * Use this if we would be adding new items, as we could split nodes as we cow ++ * down the tree. ++ */ ++static inline u64 btrfs_calc_insert_metadata_size(struct btrfs_fs_info *fs_info, ++ unsigned num_items) + { + return (u64)fs_info->nodesize * BTRFS_MAX_LEVEL * 2 * num_items; + } + + /* +- * Doing a truncate won't result in new nodes or leaves, just what we need for +- * COW. ++ * Doing a truncate or a modification won't result in new nodes or leaves, just ++ * what we need for COW. + */ +-static inline u64 btrfs_calc_trunc_metadata_size(struct btrfs_fs_info *fs_info, ++static inline u64 btrfs_calc_metadata_size(struct btrfs_fs_info *fs_info, + unsigned num_items) + { + return (u64)fs_info->nodesize * BTRFS_MAX_LEVEL * num_items; +--- a/fs/btrfs/delalloc-space.c ++++ b/fs/btrfs/delalloc-space.c +@@ -255,12 +255,12 @@ static void btrfs_calculate_inode_block_ + lockdep_assert_held(&inode->lock); + outstanding_extents = inode->outstanding_extents; + if (outstanding_extents) +- reserve_size = btrfs_calc_trans_metadata_size(fs_info, ++ reserve_size = btrfs_calc_insert_metadata_size(fs_info, + outstanding_extents + 1); + csum_leaves = btrfs_csum_bytes_to_leaves(fs_info, + inode->csum_bytes); +- reserve_size += btrfs_calc_trans_metadata_size(fs_info, +- csum_leaves); ++ reserve_size += btrfs_calc_insert_metadata_size(fs_info, ++ csum_leaves); + /* + * For qgroup rsv, the calculation is very simple: + * account one nodesize for each outstanding extent +@@ -283,7 +283,7 @@ static void calc_inode_reservations(stru + u64 csum_leaves = btrfs_csum_bytes_to_leaves(fs_info, num_bytes); + + /* We add one for the inode update at finish ordered time */ +- *meta_reserve = btrfs_calc_trans_metadata_size(fs_info, ++ *meta_reserve = btrfs_calc_insert_metadata_size(fs_info, + nr_extents + csum_leaves + 1); + *qgroup_reserve = nr_extents * fs_info->nodesize; + } +--- a/fs/btrfs/delayed-inode.c ++++ b/fs/btrfs/delayed-inode.c +@@ -545,7 +545,7 @@ static int btrfs_delayed_item_reserve_me + src_rsv = trans->block_rsv; + dst_rsv = &fs_info->delayed_block_rsv; + +- num_bytes = btrfs_calc_trans_metadata_size(fs_info, 1); ++ num_bytes = btrfs_calc_insert_metadata_size(fs_info, 1); + + /* + * Here we migrate space rsv from transaction rsv, since have already +@@ -599,7 +599,7 @@ static int btrfs_delayed_inode_reserve_m + src_rsv = trans->block_rsv; + dst_rsv = &fs_info->delayed_block_rsv; + +- num_bytes = btrfs_calc_trans_metadata_size(fs_info, 1); ++ num_bytes = btrfs_calc_insert_metadata_size(fs_info, 1); + + /* + * btrfs_dirty_inode will update the inode under btrfs_join_transaction +--- a/fs/btrfs/delayed-ref.c ++++ b/fs/btrfs/delayed-ref.c +@@ -92,7 +92,7 @@ int btrfs_should_throttle_delayed_refs(s + void btrfs_delayed_refs_rsv_release(struct btrfs_fs_info *fs_info, int nr) + { + struct btrfs_block_rsv *block_rsv = &fs_info->delayed_refs_rsv; +- u64 num_bytes = btrfs_calc_trans_metadata_size(fs_info, nr); ++ u64 num_bytes = btrfs_calc_insert_metadata_size(fs_info, nr); + u64 released = 0; + + released = __btrfs_block_rsv_release(fs_info, block_rsv, num_bytes, +@@ -118,8 +118,8 @@ void btrfs_update_delayed_refs_rsv(struc + if (!trans->delayed_ref_updates) + return; + +- num_bytes = btrfs_calc_trans_metadata_size(fs_info, +- trans->delayed_ref_updates); ++ num_bytes = btrfs_calc_insert_metadata_size(fs_info, ++ trans->delayed_ref_updates); + spin_lock(&delayed_rsv->lock); + delayed_rsv->size += num_bytes; + delayed_rsv->full = 0; +@@ -187,7 +187,7 @@ int btrfs_delayed_refs_rsv_refill(struct + enum btrfs_reserve_flush_enum flush) + { + struct btrfs_block_rsv *block_rsv = &fs_info->delayed_refs_rsv; +- u64 limit = btrfs_calc_trans_metadata_size(fs_info, 1); ++ u64 limit = btrfs_calc_insert_metadata_size(fs_info, 1); + u64 num_bytes = 0; + int ret = -ENOSPC; + +--- a/fs/btrfs/file.c ++++ b/fs/btrfs/file.c +@@ -2523,7 +2523,7 @@ static int btrfs_punch_hole(struct inode + u64 tail_len; + u64 orig_start = offset; + u64 cur_offset; +- u64 min_size = btrfs_calc_trans_metadata_size(fs_info, 1); ++ u64 min_size = btrfs_calc_insert_metadata_size(fs_info, 1); + u64 drop_end; + int ret = 0; + int err = 0; +@@ -2641,7 +2641,7 @@ static int btrfs_punch_hole(struct inode + ret = -ENOMEM; + goto out_free; + } +- rsv->size = btrfs_calc_trans_metadata_size(fs_info, 1); ++ rsv->size = btrfs_calc_insert_metadata_size(fs_info, 1); + rsv->failfast = 1; + + /* +--- a/fs/btrfs/free-space-cache.c ++++ b/fs/btrfs/free-space-cache.c +@@ -227,8 +227,8 @@ int btrfs_check_trunc_cache_free_space(s + int ret; + + /* 1 for slack space, 1 for updating the inode */ +- needed_bytes = btrfs_calc_trunc_metadata_size(fs_info, 1) + +- btrfs_calc_trans_metadata_size(fs_info, 1); ++ needed_bytes = btrfs_calc_insert_metadata_size(fs_info, 1) + ++ btrfs_calc_metadata_size(fs_info, 1); + + spin_lock(&rsv->lock); + if (rsv->reserved < needed_bytes) +--- a/fs/btrfs/inode-map.c ++++ b/fs/btrfs/inode-map.c +@@ -436,7 +436,7 @@ int btrfs_save_ino_cache(struct btrfs_ro + * 1 item for free space object + * 3 items for pre-allocation + */ +- trans->bytes_reserved = btrfs_calc_trans_metadata_size(fs_info, 10); ++ trans->bytes_reserved = btrfs_calc_insert_metadata_size(fs_info, 10); + ret = btrfs_block_rsv_add(root, trans->block_rsv, + trans->bytes_reserved, + BTRFS_RESERVE_NO_FLUSH); +--- a/fs/btrfs/inode.c ++++ b/fs/btrfs/inode.c +@@ -5087,7 +5087,7 @@ static struct btrfs_trans_handle *evict_ + struct btrfs_fs_info *fs_info = root->fs_info; + struct btrfs_block_rsv *global_rsv = &fs_info->global_block_rsv; + struct btrfs_trans_handle *trans; +- u64 delayed_refs_extra = btrfs_calc_trans_metadata_size(fs_info, 1); ++ u64 delayed_refs_extra = btrfs_calc_insert_metadata_size(fs_info, 1); + int ret; + + /* +@@ -5179,7 +5179,7 @@ void btrfs_evict_inode(struct inode *ino + rsv = btrfs_alloc_block_rsv(fs_info, BTRFS_BLOCK_RSV_TEMP); + if (!rsv) + goto no_delete; +- rsv->size = btrfs_calc_trunc_metadata_size(fs_info, 1); ++ rsv->size = btrfs_calc_metadata_size(fs_info, 1); + rsv->failfast = 1; + + btrfs_i_size_write(BTRFS_I(inode), 0); +@@ -9028,7 +9028,7 @@ static int btrfs_truncate(struct inode * + int ret; + struct btrfs_trans_handle *trans; + u64 mask = fs_info->sectorsize - 1; +- u64 min_size = btrfs_calc_trunc_metadata_size(fs_info, 1); ++ u64 min_size = btrfs_calc_metadata_size(fs_info, 1); + + ret = btrfs_wait_ordered_range(inode, inode->i_size & (~mask), + (u64)-1); +--- a/fs/btrfs/props.c ++++ b/fs/btrfs/props.c +@@ -321,7 +321,7 @@ static int inherit_props(struct btrfs_tr + if (!value) + continue; + +- num_bytes = btrfs_calc_trans_metadata_size(fs_info, 1); ++ num_bytes = btrfs_calc_insert_metadata_size(fs_info, 1); + ret = btrfs_block_rsv_add(root, trans->block_rsv, + num_bytes, BTRFS_RESERVE_NO_FLUSH); + if (ret) +--- a/fs/btrfs/root-tree.c ++++ b/fs/btrfs/root-tree.c +@@ -549,7 +549,7 @@ int btrfs_subvolume_reserve_metadata(str + return ret; + } + +- num_bytes = btrfs_calc_trans_metadata_size(fs_info, items); ++ num_bytes = btrfs_calc_insert_metadata_size(fs_info, items); + rsv->space_info = btrfs_find_space_info(fs_info, + BTRFS_BLOCK_GROUP_METADATA); + ret = btrfs_block_rsv_add(root, rsv, num_bytes, +--- a/fs/btrfs/space-info.c ++++ b/fs/btrfs/space-info.c +@@ -437,7 +437,7 @@ static inline u64 calc_reclaim_items_nr( + u64 bytes; + u64 nr; + +- bytes = btrfs_calc_trans_metadata_size(fs_info, 1); ++ bytes = btrfs_calc_insert_metadata_size(fs_info, 1); + nr = div64_u64(to_reclaim, bytes); + if (!nr) + nr = 1; +--- a/fs/btrfs/transaction.c ++++ b/fs/btrfs/transaction.c +@@ -543,7 +543,7 @@ start_transaction(struct btrfs_root *roo + * worth of delayed refs updates in this trans handle, and + * refill that amount for whatever is missing in the reserve. + */ +- num_bytes = btrfs_calc_trans_metadata_size(fs_info, num_items); ++ num_bytes = btrfs_calc_insert_metadata_size(fs_info, num_items); + if (delayed_refs_rsv->full == 0) { + delayed_refs_bytes = num_bytes; + num_bytes <<= 1; +@@ -693,7 +693,7 @@ struct btrfs_trans_handle *btrfs_start_t + if (IS_ERR(trans)) + return trans; + +- num_bytes = btrfs_calc_trans_metadata_size(fs_info, num_items); ++ num_bytes = btrfs_calc_insert_metadata_size(fs_info, num_items); + ret = btrfs_cond_migrate_bytes(fs_info, &fs_info->trans_block_rsv, + num_bytes, min_factor); + if (ret) { diff --git a/patches.suse/0006-btrfs-sink-get_extent-parameter-to-get_extent_skip_h.patch b/patches.suse/0006-btrfs-sink-get_extent-parameter-to-get_extent_skip_h.patch new file mode 100644 index 0000000..e707346 --- /dev/null +++ b/patches.suse/0006-btrfs-sink-get_extent-parameter-to-get_extent_skip_h.patch @@ -0,0 +1,64 @@ +From e3350e16eaa61422d37e541e1468ce7476b44a4e Mon Sep 17 00:00:00 2001 +From: David Sterba +Date: Fri, 23 Jun 2017 04:09:57 +0200 +Patch-mainline: v4.16 +Git-commit: e3350e16eaa61422d37e541e1468ce7476b44a4e +References: bsc#1168273 +Subject: [PATCH 6/7] btrfs: sink get_extent parameter to get_extent_skip_holes + +All callers pass btrfs_get_extent_fiemap and get_extent_skip_holes +itself is used only as a fiemap helper. + +Signed-off-by: David Sterba +--- + fs/btrfs/extent_io.c | 13 +++++-------- + 1 file changed, 5 insertions(+), 8 deletions(-) + +diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c +index d62e0194fc3b..3f5debc5e56f 100644 +--- a/fs/btrfs/extent_io.c ++++ b/fs/btrfs/extent_io.c +@@ -4292,9 +4292,7 @@ int try_release_extent_mapping(struct extent_map_tree *map, + * This maps until we find something past 'last' + */ + static struct extent_map *get_extent_skip_holes(struct inode *inode, +- u64 offset, +- u64 last, +- get_extent_t *get_extent) ++ u64 offset, u64 last) + { + u64 sectorsize = btrfs_inode_sectorsize(inode); + struct extent_map *em; +@@ -4308,7 +4306,8 @@ static struct extent_map *get_extent_skip_holes(struct inode *inode, + if (len == 0) + break; + len = ALIGN(len, sectorsize); +- em = get_extent(BTRFS_I(inode), NULL, 0, offset, len, 0); ++ em = btrfs_get_extent_fiemap(BTRFS_I(inode), NULL, 0, offset, ++ len, 0); + if (IS_ERR_OR_NULL(em)) + return em; + +@@ -4523,8 +4522,7 @@ int extent_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, + lock_extent_bits(&BTRFS_I(inode)->io_tree, start, start + len - 1, + &cached_state); + +- em = get_extent_skip_holes(inode, start, last_for_get_extent, +- btrfs_get_extent_fiemap); ++ em = get_extent_skip_holes(inode, start, last_for_get_extent); + if (!em) + goto out; + if (IS_ERR(em)) { +@@ -4612,8 +4610,7 @@ int extent_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, + } + + /* now scan forward to see if this is really the last extent. */ +- em = get_extent_skip_holes(inode, off, last_for_get_extent, +- btrfs_get_extent_fiemap); ++ em = get_extent_skip_holes(inode, off, last_for_get_extent); + if (IS_ERR(em)) { + ret = PTR_ERR(em); + goto out; +-- +2.26.0 + diff --git a/patches.suse/0006-btrfs-sink-writepage-parameter-to-extent_write_cache.patch b/patches.suse/0006-btrfs-sink-writepage-parameter-to-extent_write_cache.patch new file mode 100644 index 0000000..17397e3 --- /dev/null +++ b/patches.suse/0006-btrfs-sink-writepage-parameter-to-extent_write_cache.patch @@ -0,0 +1,63 @@ +From 935db8531fa4d6cc951729a2b5063b6406b71432 Mon Sep 17 00:00:00 2001 +From: David Sterba +Date: Fri, 23 Jun 2017 04:30:28 +0200 +Patch-mainline: v4.16 +Git-commit: 935db8531fa4d6cc951729a2b5063b6406b71432 +References: bsc#1168273 +Subject: [PATCH 6/7] btrfs: sink writepage parameter to + extent_write_cache_pages + +The function extent_write_cache_pages is modelled after +write_cache_pages which is a generic interface and the writepage +parameter makes sense there. In btrfs we know exactly which callback +we're going to use, so we can pass it directly. + +Signed-off-by: David Sterba +--- + fs/btrfs/extent_io.c | 9 ++++----- + 1 file changed, 4 insertions(+), 5 deletions(-) + +diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c +index cf106d46a2fd..0ceb427a8e63 100644 +--- a/fs/btrfs/extent_io.c ++++ b/fs/btrfs/extent_io.c +@@ -3893,8 +3893,7 @@ int btree_write_cache_pages(struct address_space *mapping, + * write_cache_pages - walk the list of dirty pages of the given address space and write all of them. + * @mapping: address space structure to write + * @wbc: subtract the number of written pages from *@wbc->nr_to_write +- * @writepage: function called for each page +- * @data: data passed to writepage function ++ * @data: data passed to __extent_writepage function + * + * If a page is already under I/O, write_cache_pages() skips it, even + * if it's dirty. This is desirable behaviour for memory-cleaning writeback, +@@ -3906,7 +3905,7 @@ int btree_write_cache_pages(struct address_space *mapping, + */ + static int extent_write_cache_pages(struct address_space *mapping, + struct writeback_control *wbc, +- writepage_t writepage, void *data) ++ void *data) + { + struct inode *inode = mapping->host; + int ret = 0; +@@ -3991,7 +3990,7 @@ static int extent_write_cache_pages(struct address_space *mapping, + continue; + } + +- ret = (*writepage)(page, wbc, data); ++ ret = __extent_writepage(page, wbc, data); + + if (unlikely(ret == AOP_WRITEPAGE_ACTIVATE)) { + unlock_page(page); +@@ -4122,7 +4121,7 @@ int extent_writepages(struct extent_io_tree *tree, + .sync_io = wbc->sync_mode == WB_SYNC_ALL, + }; + +- ret = extent_write_cache_pages(mapping, wbc, __extent_writepage, &epd); ++ ret = extent_write_cache_pages(mapping, wbc, &epd); + flush_write_bio(&epd); + return ret; + } +-- +2.26.0 + diff --git a/patches.suse/0006-btrfs-update-may_commit_transaction-to-use-the-delayed-refs-rsv.patch b/patches.suse/0006-btrfs-update-may_commit_transaction-to-use-the-delayed-refs-rsv.patch new file mode 100644 index 0000000..f3d1bbb --- /dev/null +++ b/patches.suse/0006-btrfs-update-may_commit_transaction-to-use-the-delayed-refs-rsv.patch @@ -0,0 +1,84 @@ +From: Josef Bacik +Date: Mon, 3 Dec 2018 10:20:34 -0500 +Subject: btrfs: update may_commit_transaction to use the delayed refs rsv +Git-commit: 4c8edbc75cb9ff846066cd9781ede4f27caf3cf4 +Patch-mainline: v5.0-rc1 +References: bsc#1165949 + +Any space used in the delayed_refs_rsv will be freed up by a transaction +commit, so instead of just counting the pinned space we also need to +account for any space in the delayed_refs_rsv when deciding if it will +make a different to commit the transaction to satisfy our space +reservation. If we have enough bytes to satisfy our reservation ticket +then we are good to go, otherwise subtract out what space we would gain +back by committing the transaction and compare that against the pinned +space to make our decision. + +Reviewed-by: Nikolay Borisov +Signed-off-by: Josef Bacik +Signed-off-by: David Sterba +Acked-by: Nikolay Borisov +--- + fs/btrfs/extent-tree.c | 27 ++++++++++++++++----------- + 1 file changed, 16 insertions(+), 11 deletions(-) + +--- a/fs/btrfs/extent-tree.c ++++ b/fs/btrfs/extent-tree.c +@@ -4958,8 +4958,10 @@ static int may_commit_transaction(struct + { + struct reserve_ticket *ticket = NULL; + struct btrfs_block_rsv *delayed_rsv = &fs_info->delayed_block_rsv; ++ struct btrfs_block_rsv *delayed_refs_rsv = &fs_info->delayed_refs_rsv; + struct btrfs_trans_handle *trans; +- u64 bytes; ++ u64 bytes_needed; ++ u64 reclaim_bytes = 0; + + trans = (struct btrfs_trans_handle *)current->journal_info; + if (trans) +@@ -4972,14 +4974,14 @@ static int may_commit_transaction(struct + else if (!list_empty(&space_info->tickets)) + ticket = list_first_entry(&space_info->tickets, + struct reserve_ticket, list); +- bytes = ticket ? ticket->bytes : 0; ++ bytes_needed = (ticket) ? ticket->bytes : 0; + spin_unlock(&space_info->lock); + +- if (!bytes) ++ if (!bytes_needed) + return 0; + /* See if there is enough pinned space to make this reservation */ + if (percpu_counter_compare(&space_info->total_bytes_pinned, +- bytes) >= 0) ++ bytes_needed) >= 0) + goto commit; + + /* +@@ -4990,17 +4992,20 @@ static int may_commit_transaction(struct + return -ENOSPC; + + spin_lock(&delayed_rsv->lock); +- if (delayed_rsv->size > bytes) +- bytes = 0; +- else +- bytes -= delayed_rsv->size; ++ reclaim_bytes += delayed_rsv->reserved; ++ spin_unlock(&delayed_rsv->lock); ++ ++ spin_lock(&delayed_refs_rsv->lock); ++ reclaim_bytes += delayed_refs_rsv->reserved; ++ spin_unlock(&delayed_refs_rsv->lock); ++ if (reclaim_bytes >= bytes_needed) ++ goto commit; ++ bytes_needed -= reclaim_bytes; + + if (percpu_counter_compare(&space_info->total_bytes_pinned, +- bytes) < 0) { +- spin_unlock(&delayed_rsv->lock); ++ bytes_needed) < 0) { + return -ENOSPC; + } +- spin_unlock(&delayed_rsv->lock); + + commit: + trans = btrfs_join_transaction(fs_info->extent_root); diff --git a/patches.suse/0006-device-Use-overflow-helpers-for-devm_kmalloc.patch b/patches.suse/0006-device-Use-overflow-helpers-for-devm_kmalloc.patch new file mode 100644 index 0000000..77d0e01 --- /dev/null +++ b/patches.suse/0006-device-Use-overflow-helpers-for-devm_kmalloc.patch @@ -0,0 +1,68 @@ +From 2509b561f7c6599907c08cb364c86b8c45466e4f Mon Sep 17 00:00:00 2001 +From: Kees Cook +Date: Tue, 8 May 2018 22:29:52 -0700 +Subject: device: Use overflow helpers for devm_kmalloc() +Git-commit: 2509b561f7c6599907c08cb364c86b8c45466e4f +Patch-mainline: v4.18-rc1 +References: bsc#1166003 FATE#326289 + +Use the overflow helpers both in existing multiplication-using inlines as +well as the addition-overflow case in the core allocation routine. + +Signed-off-by: Kees Cook +Acked-by: Thomas Zimmermann +--- + drivers/base/devres.c | 7 ++++++- + include/linux/device.h | 8 ++++++-- + 2 files changed, 12 insertions(+), 3 deletions(-) + +diff --git a/drivers/base/devres.c b/drivers/base/devres.c +index 95b67281cd2a..f98a097e73f2 100644 +--- a/drivers/base/devres.c ++++ b/drivers/base/devres.c +@@ -84,9 +84,14 @@ static struct devres_group * node_to_group(struct devres_node *node) + static __always_inline struct devres * alloc_dr(dr_release_t release, + size_t size, gfp_t gfp, int nid) + { +- size_t tot_size = sizeof(struct devres) + size; ++ size_t tot_size; + struct devres *dr; + ++ /* We must catch any near-SIZE_MAX cases that could overflow. */ ++ if (unlikely(check_add_overflow(sizeof(struct devres), size, ++ &tot_size))) ++ return NULL; ++ + dr = kmalloc_node_track_caller(tot_size, gfp, nid); + if (unlikely(!dr)) + return NULL; +diff --git a/include/linux/device.h b/include/linux/device.h +index 477956990f5e..897efa647203 100644 +--- a/include/linux/device.h ++++ b/include/linux/device.h +@@ -25,6 +25,7 @@ + #include + #include + #include ++#include + #include + + struct device; +@@ -668,9 +669,12 @@ static inline void *devm_kzalloc(struct device *dev, size_t size, gfp_t gfp) + static inline void *devm_kmalloc_array(struct device *dev, + size_t n, size_t size, gfp_t flags) + { +- if (size != 0 && n > SIZE_MAX / size) ++ size_t bytes; ++ ++ if (unlikely(check_mul_overflow(n, size, &bytes))) + return NULL; +- return devm_kmalloc(dev, n * size, flags); ++ ++ return devm_kmalloc(dev, bytes, flags); + } + static inline void *devm_kcalloc(struct device *dev, + size_t n, size_t size, gfp_t flags) +-- +2.19.1 + diff --git a/patches.suse/0007-btrfs-add-new-flushing-states-for-the-delayed-refs-rsv.patch b/patches.suse/0007-btrfs-add-new-flushing-states-for-the-delayed-refs-rsv.patch new file mode 100644 index 0000000..36aa56d --- /dev/null +++ b/patches.suse/0007-btrfs-add-new-flushing-states-for-the-delayed-refs-rsv.patch @@ -0,0 +1,75 @@ +From: Josef Bacik +Date: Mon, 3 Dec 2018 10:20:35 -0500 +Subject: btrfs: add new flushing states for the delayed refs rsv +Git-commit: 413df7252d5256df406a23d7efb679f46d19a23d +Patch-mainline: v5.0-rc1 +References: bsc#1165949 + +A nice thing we gain with the delayed refs rsv is the ability to flush +the delayed refs on demand to deal with enospc pressure. Add states to +flush delayed refs on demand, and this will allow us to remove a lot of +ad-hoc work around checking to see if we should commit the transaction +to run our delayed refs. + +Signed-off-by: Josef Bacik +Signed-off-by: David Sterba +Acked-by: Nikolay Borisov +--- + fs/btrfs/ctree.h | 10 ++++++---- + fs/btrfs/extent-tree.c | 14 ++++++++++++++ + include/trace/events/btrfs.h | 2 ++ + 3 files changed, 22 insertions(+), 4 deletions(-) + +--- a/fs/btrfs/ctree.h ++++ b/fs/btrfs/ctree.h +@@ -2770,10 +2770,12 @@ enum btrfs_reserve_flush_enum { + enum btrfs_flush_state { + FLUSH_DELAYED_ITEMS_NR = 1, + FLUSH_DELAYED_ITEMS = 2, +- FLUSH_DELALLOC = 3, +- FLUSH_DELALLOC_WAIT = 4, +- ALLOC_CHUNK = 5, +- COMMIT_TRANS = 6, ++ FLUSH_DELAYED_REFS_NR = 3, ++ FLUSH_DELAYED_REFS = 4, ++ FLUSH_DELALLOC = 5, ++ FLUSH_DELALLOC_WAIT = 6, ++ ALLOC_CHUNK = 7, ++ COMMIT_TRANS = 8, + }; + + int btrfs_alloc_data_chunk_ondemand(struct btrfs_inode *inode, u64 bytes); +--- a/fs/btrfs/extent-tree.c ++++ b/fs/btrfs/extent-tree.c +@@ -5053,6 +5053,20 @@ static int flush_space(struct btrfs_fs_i + shrink_delalloc(root, num_bytes * 2, num_bytes, + state == FLUSH_DELALLOC_WAIT); + break; ++ case FLUSH_DELAYED_REFS_NR: ++ case FLUSH_DELAYED_REFS: ++ trans = btrfs_join_transaction(root); ++ if (IS_ERR(trans)) { ++ ret = PTR_ERR(trans); ++ break; ++ } ++ if (state == FLUSH_DELAYED_REFS_NR) ++ nr = calc_reclaim_items_nr(fs_info, num_bytes); ++ else ++ nr = 0; ++ btrfs_run_delayed_refs(trans, trans->fs_info, nr); ++ btrfs_end_transaction(trans); ++ break; + case ALLOC_CHUNK: + trans = btrfs_join_transaction(root); + if (IS_ERR(trans)) { +--- a/include/trace/events/btrfs.h ++++ b/include/trace/events/btrfs.h +@@ -1008,6 +1008,8 @@ TRACE_EVENT(btrfs_trigger_flush, + { FLUSH_DELAYED_ITEMS, "FLUSH_DELAYED_ITEMS"}, \ + { FLUSH_DELALLOC, "FLUSH_DELALLOC"}, \ + { FLUSH_DELALLOC_WAIT, "FLUSH_DELALLOC_WAIT"}, \ ++ { FLUSH_DELAYED_REFS_NR, "FLUSH_DELAYED_REFS_NR"}, \ ++ { FLUSH_DELAYED_REFS, "FLUSH_ELAYED_REFS"}, \ + { ALLOC_CHUNK, "ALLOC_CHUNK"}, \ + { COMMIT_TRANS, "COMMIT_TRANS"}) + diff --git a/patches.suse/0007-btrfs-don-t-use-global-reserve-for-chunk-allocation.patch b/patches.suse/0007-btrfs-don-t-use-global-reserve-for-chunk-allocation.patch new file mode 100644 index 0000000..be6ad41 --- /dev/null +++ b/patches.suse/0007-btrfs-don-t-use-global-reserve-for-chunk-allocation.patch @@ -0,0 +1,120 @@ +From: Josef Bacik +Date: Wed, 21 Nov 2018 14:03:08 -0500 +Subject: btrfs: don't use global reserve for chunk allocation +Git-commit: 450114fc0db0cd5c2e7324b917e5de52cff991d7 +Patch-mainline: v5.1-rc1 +References: bsc#1165949 + +We've done this forever because of the voodoo around knowing how much +space we have. However, we have better ways of doing this now, and on +normal file systems we'll easily have a global reserve of 512MiB, and +since metadata chunks are usually 1GiB that means we'll allocate +metadata chunks more readily. Instead use the actual used amount when +determining if we need to allocate a chunk or not. + +This has a side effect for mixed block group fs'es where we are no +longer allocating enough chunks for the data/metadata requirements. To +deal with this add a ALLOC_CHUNK_FORCE step to the flushing state +machine. This will only get used if we've already made a full loop +through the flushing machinery and tried committing the transaction. + +If we have then we can try and force a chunk allocation since we likely +need it to make progress. This resolves issues I was seeing with +the mixed bg tests in xfstests without the new flushing state. + +Reviewed-by: Nikolay Borisov +Signed-off-by: Josef Bacik +[ merged with patch "add ALLOC_CHUNK_FORCE to the flushing code" ] +Signed-off-by: David Sterba +Acked-by: Nikolay Borisov +--- + fs/btrfs/ctree.h | 3 ++- + fs/btrfs/extent-tree.c | 26 ++++++++++++++++---------- + include/trace/events/btrfs.h | 1 + + 3 files changed, 19 insertions(+), 11 deletions(-) + +--- a/fs/btrfs/ctree.h ++++ b/fs/btrfs/ctree.h +@@ -2809,7 +2809,8 @@ enum btrfs_flush_state { + FLUSH_DELALLOC = 5, + FLUSH_DELALLOC_WAIT = 6, + ALLOC_CHUNK = 7, +- COMMIT_TRANS = 8, ++ ALLOC_CHUNK_FORCE = 8, ++ COMMIT_TRANS = 9, + }; + + int btrfs_alloc_data_chunk_ondemand(struct btrfs_inode *inode, u64 bytes); +--- a/fs/btrfs/extent-tree.c ++++ b/fs/btrfs/extent-tree.c +@@ -4531,7 +4531,6 @@ static inline u64 calc_global_rsv_need_s + static int should_alloc_chunk(struct btrfs_fs_info *fs_info, + struct btrfs_space_info *sinfo, int force) + { +- struct btrfs_block_rsv *global_rsv = &fs_info->global_block_rsv; + u64 num_bytes = sinfo->total_bytes - sinfo->bytes_readonly; + u64 num_allocated = sinfo->bytes_used + sinfo->bytes_reserved + sinfo->bytes_pinned; + u64 thresh; +@@ -4540,14 +4539,6 @@ static int should_alloc_chunk(struct btr + return 1; + + /* +- * We need to take into account the global rsv because for all intents +- * and purposes it's used space. Don't worry about locking the +- * global_rsv, it doesn't change except when the transaction commits. +- */ +- if (sinfo->flags & BTRFS_BLOCK_GROUP_METADATA) +- num_allocated += calc_global_rsv_need_space(global_rsv); +- +- /* + * in limited mode, we want to have some free space up to + * about 1% of the FS size. + */ +@@ -5078,6 +5069,7 @@ static int flush_space(struct btrfs_fs_i + btrfs_end_transaction(trans); + break; + case ALLOC_CHUNK: ++ case ALLOC_CHUNK_FORCE: + trans = btrfs_join_transaction(root); + if (IS_ERR(trans)) { + ret = PTR_ERR(trans); +@@ -5085,7 +5077,8 @@ static int flush_space(struct btrfs_fs_i + } + ret = do_chunk_alloc(trans, + btrfs_metadata_alloc_profile(fs_info), +- CHUNK_ALLOC_NO_FORCE); ++ (state == ALLOC_CHUNK) ? ++ CHUNK_ALLOC_NO_FORCE : CHUNK_ALLOC_FORCE); + btrfs_end_transaction(trans); + if (ret > 0 || ret == -ENOSPC) + ret = 0; +@@ -5231,6 +5224,19 @@ static void btrfs_async_reclaim_metadata + commit_cycles--; + } + ++ /* ++ * We don't want to force a chunk allocation until we've tried ++ * pretty hard to reclaim space. Think of the case where we ++ * freed up a bunch of space and so have a lot of pinned space ++ * to reclaim. We would rather use that than possibly create a ++ * underutilized metadata chunk. So if this is our first run ++ * through the flushing state machine skip ALLOC_CHUNK_FORCE and ++ * commit the transaction. If nothing has changed the next go ++ * around then we can force a chunk allocation. ++ */ ++ if (flush_state == ALLOC_CHUNK_FORCE && !commit_cycles) ++ flush_state++; ++ + if (flush_state > COMMIT_TRANS) { + commit_cycles++; + if (commit_cycles > 2) { +--- a/include/trace/events/btrfs.h ++++ b/include/trace/events/btrfs.h +@@ -1011,6 +1011,7 @@ TRACE_EVENT(btrfs_trigger_flush, + { FLUSH_DELAYED_REFS_NR, "FLUSH_DELAYED_REFS_NR"}, \ + { FLUSH_DELAYED_REFS, "FLUSH_ELAYED_REFS"}, \ + { ALLOC_CHUNK, "ALLOC_CHUNK"}, \ ++ { ALLOC_CHUNK_FORCE, "ALLOC_CHUNK_FORCE"}, \ + { COMMIT_TRANS, "COMMIT_TRANS"}) + + TRACE_EVENT(btrfs_flush_space, diff --git a/patches.suse/0007-btrfs-drop-min_size-from-evict_refill_and_join.patch b/patches.suse/0007-btrfs-drop-min_size-from-evict_refill_and_join.patch new file mode 100644 index 0000000..3b05ab4 --- /dev/null +++ b/patches.suse/0007-btrfs-drop-min_size-from-evict_refill_and_join.patch @@ -0,0 +1,90 @@ +From: Josef Bacik +Date: Fri, 28 Sep 2018 07:18:19 -0400 +Subject: btrfs: drop min_size from evict_refill_and_join +Git-commit: ad80cf50c3f09a88eed918feeb95edaaf8d72b0a +Patch-mainline: v4.20-rc1 +References: bsc##1165949 + +We don't need it, rsv->size is set once and never changes throughout +its lifetime, so just use that for the reserve size. + +Signed-off-by: Josef Bacik +Reviewed-by: David Sterba +Signed-off-by: David Sterba +Acked-by: Nikolay Borisov +--- + fs/btrfs/inode.c | 16 ++++++---------- + 1 file changed, 6 insertions(+), 10 deletions(-) + +--- a/fs/btrfs/inode.c ++++ b/fs/btrfs/inode.c +@@ -5046,8 +5046,7 @@ static void evict_inode_truncate_pages(s + } + + static struct btrfs_trans_handle *evict_refill_and_join(struct btrfs_root *root, +- struct btrfs_block_rsv *rsv, +- u64 min_size) ++ struct btrfs_block_rsv *rsv) + { + struct btrfs_fs_info *fs_info = root->fs_info; + struct btrfs_block_rsv *global_rsv = &fs_info->global_block_rsv; +@@ -5057,7 +5056,7 @@ static struct btrfs_trans_handle *evict_ + struct btrfs_trans_handle *trans; + int ret; + +- ret = btrfs_block_rsv_refill(root, rsv, min_size, ++ ret = btrfs_block_rsv_refill(root, rsv, rsv->size, + BTRFS_RESERVE_FLUSH_LIMIT); + + if (ret && ++failures > 2) { +@@ -5075,7 +5074,7 @@ static struct btrfs_trans_handle *evict_ + * it. + */ + if (!btrfs_check_space_for_delayed_refs(trans, fs_info) && +- !btrfs_block_rsv_migrate(global_rsv, rsv, min_size, 0)) ++ !btrfs_block_rsv_migrate(global_rsv, rsv, rsv->size, 0)) + return trans; + + /* If not, commit and try again. */ +@@ -5091,7 +5090,6 @@ void btrfs_evict_inode(struct inode *ino + struct btrfs_trans_handle *trans; + struct btrfs_root *root = BTRFS_I(inode)->root; + struct btrfs_block_rsv *rsv; +- u64 min_size; + int ret; + + trace_btrfs_inode_evict(inode); +@@ -5101,8 +5099,6 @@ void btrfs_evict_inode(struct inode *ino + return; + } + +- min_size = btrfs_calc_trunc_metadata_size(fs_info, 1); +- + evict_inode_truncate_pages(inode); + + if (inode->i_nlink && +@@ -5135,13 +5131,13 @@ void btrfs_evict_inode(struct inode *ino + rsv = btrfs_alloc_block_rsv(fs_info, BTRFS_BLOCK_RSV_TEMP); + if (!rsv) + goto no_delete; +- rsv->size = min_size; ++ rsv->size = btrfs_calc_trunc_metadata_size(fs_info, 1); + rsv->failfast = 1; + + btrfs_i_size_write(BTRFS_I(inode), 0); + + while (1) { +- trans = evict_refill_and_join(root, rsv, min_size); ++ trans = evict_refill_and_join(root, rsv); + if (IS_ERR(trans)) + goto free_rsv; + +@@ -5166,7 +5162,7 @@ void btrfs_evict_inode(struct inode *ino + * If it turns out that we are dropping too many of these, we might want + * to add a mechanism for retrying these after a commit. + */ +- trans = evict_refill_and_join(root, rsv, min_size); ++ trans = evict_refill_and_join(root, rsv); + if (!IS_ERR(trans)) { + trans->block_rsv = rsv; + btrfs_orphan_del(trans, BTRFS_I(inode)); diff --git a/patches.suse/0007-btrfs-export-the-excluded-extents-helpers.patch b/patches.suse/0007-btrfs-export-the-excluded-extents-helpers.patch new file mode 100644 index 0000000..8b302f2 --- /dev/null +++ b/patches.suse/0007-btrfs-export-the-excluded-extents-helpers.patch @@ -0,0 +1,175 @@ +From: Josef Bacik +Date: Thu, 20 Jun 2019 15:37:49 -0400 +Subject: btrfs: export the excluded extents helpers +Git-commit: 6f410d1b3dbf9213ee89c569e8213511319bbd90 +Patch-mainline: v5.4-rc1 +References: bsc#1165949 + +We'll need this to move the caching stuff around. + +Signed-off-by: Josef Bacik +Reviewed-by: David Sterba +Signed-off-by: David Sterba +Acked-by: Nikolay Borisov +--- + fs/btrfs/ctree.h | 3 +++ + fs/btrfs/extent-tree.c | 38 ++++++++++++++++++++------------------ + 2 files changed, 23 insertions(+), 18 deletions(-) + +--- a/fs/btrfs/ctree.h ++++ b/fs/btrfs/ctree.h +@@ -2455,6 +2455,9 @@ static inline u64 btrfs_calc_trunc_metad + return (u64)fs_info->nodesize * BTRFS_MAX_LEVEL * num_items; + } + ++int btrfs_add_excluded_extent(struct btrfs_fs_info *fs_info, ++ u64 start, u64 num_bytes); ++void btrfs_free_excluded_extents(struct btrfs_block_group_cache *cache); + int btrfs_run_delayed_refs(struct btrfs_trans_handle *trans, + struct btrfs_fs_info *fs_info, unsigned long count); + int btrfs_async_run_delayed_refs(struct btrfs_fs_info *fs_info, +--- a/fs/btrfs/extent-tree.c ++++ b/fs/btrfs/extent-tree.c +@@ -121,8 +121,8 @@ static int btrfs_add_block_group_cache(s + return 0; + } + +-static int add_excluded_extent(struct btrfs_fs_info *fs_info, +- u64 start, u64 num_bytes) ++int btrfs_add_excluded_extent(struct btrfs_fs_info *fs_info, ++ u64 start, u64 num_bytes) + { + u64 end = start + num_bytes - 1; + set_extent_bits(&fs_info->freed_extents[0], +@@ -132,9 +132,9 @@ static int add_excluded_extent(struct bt + return 0; + } + +-static void free_excluded_extents(struct btrfs_fs_info *fs_info, +- struct btrfs_block_group_cache *cache) ++void btrfs_free_excluded_extents(struct btrfs_block_group_cache *cache) + { ++ struct btrfs_fs_info *fs_info = cache->fs_info; + u64 start, end; + + start = cache->key.objectid; +@@ -157,8 +157,8 @@ static int exclude_super_stripes(struct + if (cache->key.objectid < BTRFS_SUPER_INFO_OFFSET) { + stripe_len = BTRFS_SUPER_INFO_OFFSET - cache->key.objectid; + cache->bytes_super += stripe_len; +- ret = add_excluded_extent(fs_info, cache->key.objectid, +- stripe_len); ++ ret = btrfs_add_excluded_extent(fs_info, cache->key.objectid, ++ stripe_len); + if (ret) + return ret; + } +@@ -191,7 +191,7 @@ static int exclude_super_stripes(struct + } + + cache->bytes_super += len; +- ret = add_excluded_extent(fs_info, start, len); ++ ret = btrfs_add_excluded_extent(fs_info, start, len); + if (ret) { + kfree(logical); + return ret; +@@ -473,7 +473,7 @@ static noinline void caching_thread(stru + caching_ctl->progress = (u64)-1; + + up_read(&fs_info->commit_root_sem); +- free_excluded_extents(fs_info, block_group); ++ btrfs_free_excluded_extents(block_group); + mutex_unlock(&caching_ctl->mutex); + + wake_up(&caching_ctl->wait); +@@ -581,7 +581,7 @@ int btrfs_cache_block_group(struct btrfs + wake_up(&caching_ctl->wait); + if (ret == 1) { + put_caching_control(caching_ctl); +- free_excluded_extents(fs_info, cache); ++ btrfs_free_excluded_extents(cache); + return 0; + } + } else { +@@ -4385,7 +4385,8 @@ static int __exclude_logged_extent(struc + mutex_lock(&caching_ctl->mutex); + + if (start >= caching_ctl->progress) { +- ret = add_excluded_extent(fs_info, start, num_bytes); ++ ret = btrfs_add_excluded_extent(fs_info, start, ++ num_bytes); + } else if (start + num_bytes <= caching_ctl->progress) { + ret = btrfs_remove_free_space(block_group, + start, num_bytes); +@@ -4399,7 +4400,8 @@ static int __exclude_logged_extent(struc + num_bytes = (start + num_bytes) - + caching_ctl->progress; + start = caching_ctl->progress; +- ret = add_excluded_extent(fs_info, start, num_bytes); ++ ret = btrfs_add_excluded_extent(fs_info, start, ++ num_bytes); + } + out_lock: + mutex_unlock(&caching_ctl->mutex); +@@ -7727,7 +7729,7 @@ int btrfs_free_block_groups(struct btrfs + */ + if (block_group->cached == BTRFS_CACHE_NO || + block_group->cached == BTRFS_CACHE_ERROR) +- free_excluded_extents(info, block_group); ++ btrfs_free_excluded_extents(block_group); + + btrfs_remove_free_space_cache(block_group); + ASSERT(block_group->cached != BTRFS_CACHE_STARTED); +@@ -8032,7 +8034,7 @@ int btrfs_read_block_groups(struct btrfs + * We may have excluded something, so call this just in + * case. + */ +- free_excluded_extents(info, cache); ++ btrfs_free_excluded_extents(cache); + btrfs_put_block_group(cache); + goto error; + } +@@ -8047,7 +8049,7 @@ int btrfs_read_block_groups(struct btrfs + if (found_key.offset == btrfs_block_group_used(&cache->item)) { + cache->last_byte_to_unpin = (u64)-1; + cache->cached = BTRFS_CACHE_FINISHED; +- free_excluded_extents(info, cache); ++ btrfs_free_excluded_extents(cache); + } else if (btrfs_block_group_used(&cache->item) == 0) { + cache->last_byte_to_unpin = (u64)-1; + cache->cached = BTRFS_CACHE_FINISHED; +@@ -8055,7 +8057,7 @@ int btrfs_read_block_groups(struct btrfs + found_key.objectid, + found_key.objectid + + found_key.offset); +- free_excluded_extents(info, cache); ++ btrfs_free_excluded_extents(cache); + } + + ret = btrfs_add_block_group_cache(info, cache); +@@ -8188,14 +8190,14 @@ int btrfs_make_block_group(struct btrfs_ + * We may have excluded something, so call this just in + * case. + */ +- free_excluded_extents(fs_info, cache); ++ btrfs_free_excluded_extents(cache); + btrfs_put_block_group(cache); + return ret; + } + + add_new_free_space(cache, fs_info, chunk_offset, chunk_offset + size); + +- free_excluded_extents(fs_info, cache); ++ btrfs_free_excluded_extents(cache); + + #ifdef CONFIG_BTRFS_DEBUG + if (btrfs_should_fragment_free_space(cache)) { +@@ -8281,7 +8283,7 @@ int btrfs_remove_block_group(struct btrf + * Free the reserved super bytes from this block group before + * remove it. + */ +- free_excluded_extents(fs_info, block_group); ++ btrfs_free_excluded_extents(block_group); + + memcpy(&key, &block_group->key, sizeof(key)); + index = get_block_group_index(block_group); diff --git a/patches.suse/0007-btrfs-extent-tree-Use-btrfs_ref-to-refactor-btrfs_in.patch b/patches.suse/0007-btrfs-extent-tree-Use-btrfs_ref-to-refactor-btrfs_in.patch index 4920713..fc3bd8c 100644 --- a/patches.suse/0007-btrfs-extent-tree-Use-btrfs_ref-to-refactor-btrfs_in.patch +++ b/patches.suse/0007-btrfs-extent-tree-Use-btrfs_ref-to-refactor-btrfs_in.patch @@ -15,17 +15,17 @@ Reviewed-by: David Sterba Signed-off-by: David Sterba --- fs/btrfs/ctree.h | 4 +-- - fs/btrfs/extent-tree.c | 54 +++++++++++++++++++++++++++++-------------------- - fs/btrfs/file.c | 18 +++++++++++----- + fs/btrfs/extent-tree.c | 51 ++++++++++++++++++++++++++++--------------------- + fs/btrfs/file.c | 17 +++++++++++----- fs/btrfs/inode.c | 10 +++++---- - fs/btrfs/ioctl.c | 15 +++++++++---- - fs/btrfs/relocation.c | 41 ++++++++++++++++++++++++------------- - fs/btrfs/tree-log.c | 12 ++++++++-- - 7 files changed, 99 insertions(+), 55 deletions(-) + fs/btrfs/ioctl.c | 15 +++++++++----- + fs/btrfs/relocation.c | 42 +++++++++++++++++++++++++--------------- + fs/btrfs/tree-log.c | 13 ++++++++---- + 7 files changed, 96 insertions(+), 56 deletions(-) --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h -@@ -53,6 +53,7 @@ extern struct kmem_cache *btrfs_bit_radi +@@ -54,6 +54,7 @@ extern struct kmem_cache *btrfs_bit_radi extern struct kmem_cache *btrfs_path_cachep; extern struct kmem_cache *btrfs_free_space_cachep; struct btrfs_ordered_sum; @@ -33,10 +33,10 @@ Signed-off-by: David Sterba #ifdef CONFIG_BTRFS_FS_RUN_SANITY_TESTS #define STATIC noinline -@@ -2731,8 +2732,7 @@ int btrfs_finish_extent_commit(struct bt +@@ -2765,8 +2766,7 @@ int btrfs_finish_extent_commit(struct bt struct btrfs_fs_info *fs_info); int btrfs_inc_extent_ref(struct btrfs_trans_handle *trans, - struct btrfs_fs_info *fs_info, + struct btrfs_root *root, - u64 bytenr, u64 num_bytes, u64 parent, - u64 root_objectid, u64 owner, u64 offset); + struct btrfs_ref *generic_ref); @@ -45,15 +45,16 @@ Signed-off-by: David Sterba struct btrfs_fs_info *fs_info); --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c -@@ -2111,31 +2111,25 @@ int btrfs_discard_extent(struct btrfs_fs +@@ -2191,32 +2191,26 @@ int btrfs_discard_extent(struct btrfs_fs /* Can return -ENOMEM */ int btrfs_inc_extent_ref(struct btrfs_trans_handle *trans, - struct btrfs_fs_info *fs_info, + struct btrfs_root *root, - u64 bytenr, u64 num_bytes, u64 parent, - u64 root_objectid, u64 owner, u64 offset) + struct btrfs_ref *generic_ref) { - struct btrfs_ref generic_ref = { 0 }; + struct btrfs_fs_info *fs_info = root->fs_info; int old_ref_mod, new_ref_mod; int ret; @@ -87,7 +88,7 @@ Signed-off-by: David Sterba return ret; } -@@ -3254,7 +3248,10 @@ static int __btrfs_mod_ref(struct btrfs_ +@@ -3344,7 +3338,10 @@ static int __btrfs_mod_ref(struct btrfs_ u32 nritems; struct btrfs_key key; struct btrfs_file_extent_item *fi; @@ -98,18 +99,18 @@ Signed-off-by: David Sterba int level; int ret = 0; -@@ -3272,6 +3269,10 @@ static int __btrfs_mod_ref(struct btrfs_ - parent = buf->start; +@@ -3363,6 +3360,10 @@ static int __btrfs_mod_ref(struct btrfs_ else parent = 0; + + if (inc) + action = BTRFS_ADD_DELAYED_REF; + else + action = BTRFS_DROP_DELAYED_REF; - for (i = 0; i < nritems; i++) { if (level == 0) { -@@ -3289,10 +3290,15 @@ static int __btrfs_mod_ref(struct btrfs_ + btrfs_item_key_to_cpu(buf, &key, i); +@@ -3379,10 +3380,14 @@ static int __btrfs_mod_ref(struct btrfs_ num_bytes = btrfs_file_extent_disk_num_bytes(buf, fi); key.offset -= btrfs_file_extent_offset(buf, fi); @@ -120,15 +121,14 @@ Signed-off-by: David Sterba + generic_ref.real_root = root->root_key.objectid; + generic_ref.skip_qgroup = for_reloc; if (inc) -- ret = btrfs_inc_extent_ref(trans, fs_info, bytenr, -- num_bytes, parent, ref_root, -- key.objectid, key.offset); -+ ret = btrfs_inc_extent_ref(trans, fs_info, -+ &generic_ref); +- ret = btrfs_inc_extent_ref(trans, root, bytenr, num_bytes, +- parent, ref_root, key.objectid, +- key.offset); ++ ret = btrfs_inc_extent_ref(trans, root, &generic_ref); else - ret = btrfs_free_extent(trans, fs_info, bytenr, - num_bytes, parent, ref_root, -@@ -3302,10 +3308,14 @@ static int __btrfs_mod_ref(struct btrfs_ + ret = btrfs_free_extent(trans, root, bytenr, num_bytes, + parent, ref_root, key.objectid, +@@ -3392,9 +3397,13 @@ static int __btrfs_mod_ref(struct btrfs_ } else { bytenr = btrfs_node_blockptr(buf, i); num_bytes = fs_info->nodesize; @@ -138,14 +138,12 @@ Signed-off-by: David Sterba + btrfs_init_tree_ref(&generic_ref, level - 1, ref_root); + generic_ref.skip_qgroup = for_reloc; if (inc) -- ret = btrfs_inc_extent_ref(trans, fs_info, bytenr, -- num_bytes, parent, ref_root, -- level - 1, 0); -+ ret = btrfs_inc_extent_ref(trans, fs_info, -+ &generic_ref); +- ret = btrfs_inc_extent_ref(trans, root, bytenr, num_bytes, +- parent, ref_root, level - 1, 0); ++ ret = btrfs_inc_extent_ref(trans, root, &generic_ref); else - ret = btrfs_free_extent(trans, fs_info, bytenr, - num_bytes, parent, ref_root, + ret = btrfs_free_extent(trans, root, bytenr, num_bytes, + parent, ref_root, level - 1, 0); --- a/fs/btrfs/file.c +++ b/fs/btrfs/file.c @@ -762,6 +762,7 @@ int __btrfs_drop_extents(struct btrfs_tr @@ -156,11 +154,11 @@ Signed-off-by: David Sterba struct btrfs_key key; struct btrfs_key new_key; u64 ino = btrfs_ino(BTRFS_I(inode)); -@@ -918,11 +919,15 @@ next_slot: +@@ -918,11 +919,14 @@ next_slot: btrfs_mark_buffer_dirty(leaf); if (update_refs && disk_bytenr > 0) { -- ret = btrfs_inc_extent_ref(trans, fs_info, +- ret = btrfs_inc_extent_ref(trans, root, - disk_bytenr, num_bytes, 0, + btrfs_init_generic_ref(&ref, + BTRFS_ADD_DELAYED_REF, @@ -169,12 +167,11 @@ Signed-off-by: David Sterba root->root_key.objectid, new_key.objectid, start - extent_offset); -+ ret = btrfs_inc_extent_ref(trans, fs_info, -+ &ref); ++ ret = btrfs_inc_extent_ref(trans, root, &ref); BUG_ON(ret); /* -ENOMEM */ } key.offset = start; -@@ -1151,6 +1156,7 @@ int btrfs_mark_extent_written(struct btr +@@ -1151,6 +1155,7 @@ int btrfs_mark_extent_written(struct btr struct extent_buffer *leaf; struct btrfs_path *path; struct btrfs_file_extent_item *fi; @@ -182,24 +179,24 @@ Signed-off-by: David Sterba struct btrfs_key key; struct btrfs_key new_key; u64 bytenr; -@@ -1296,9 +1302,11 @@ again: +@@ -1296,9 +1301,11 @@ again: extent_end - split); btrfs_mark_buffer_dirty(leaf); -- ret = btrfs_inc_extent_ref(trans, fs_info, bytenr, num_bytes, +- ret = btrfs_inc_extent_ref(trans, root, bytenr, num_bytes, - 0, root->root_key.objectid, - ino, orig_offset); + btrfs_init_generic_ref(&ref, BTRFS_ADD_DELAYED_REF, bytenr, + num_bytes, 0); + btrfs_init_data_ref(&ref, root->root_key.objectid, ino, + orig_offset); -+ ret = btrfs_inc_extent_ref(trans, fs_info, &ref); ++ ret = btrfs_inc_extent_ref(trans, root, &ref); if (ret) { btrfs_abort_transaction(trans, ret); goto out; --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c -@@ -2519,6 +2519,7 @@ static noinline int relink_extent_backre +@@ -2527,6 +2527,7 @@ static noinline int relink_extent_backre struct btrfs_file_extent_item *item; struct btrfs_ordered_extent *ordered; struct btrfs_trans_handle *trans; @@ -207,11 +204,11 @@ Signed-off-by: David Sterba struct btrfs_root *root; struct btrfs_key key; struct extent_buffer *leaf; -@@ -2689,10 +2690,11 @@ again: +@@ -2697,10 +2698,11 @@ again: inode_add_bytes(inode, len); btrfs_release_path(path); -- ret = btrfs_inc_extent_ref(trans, fs_info, new->bytenr, +- ret = btrfs_inc_extent_ref(trans, root, new->bytenr, - new->disk_len, 0, - backref->root_id, backref->inum, - new->file_pos); /* start - extent_offset */ @@ -219,18 +216,17 @@ Signed-off-by: David Sterba + new->disk_len, 0); + btrfs_init_data_ref(&ref, backref->root_id, backref->inum, + new->file_pos); /* start - extent_offset */ -+ ret = btrfs_inc_extent_ref(trans, fs_info, &ref); ++ ret = btrfs_inc_extent_ref(trans, root, &ref); if (ret) { btrfs_abort_transaction(trans, ret); goto out_free_path; --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c -@@ -3774,13 +3774,18 @@ process_slot: +@@ -3784,13 +3784,18 @@ process_slot: datal); if (disko) { + struct btrfs_ref ref = { 0 }; -+ inode_add_bytes(inode, datal); + btrfs_init_generic_ref(&ref, + BTRFS_ADD_DELAYED_REF, disko, @@ -240,18 +236,19 @@ Signed-off-by: David Sterba + btrfs_ino(BTRFS_I(inode)), + new_key.offset - datao); ret = btrfs_inc_extent_ref(trans, -- fs_info, +- root, - disko, diskl, 0, - root->root_key.objectid, - btrfs_ino(BTRFS_I(inode)), - new_key.offset - datao); -+ fs_info, &ref); ++ root, &ref); ++ if (ret) { btrfs_abort_transaction(trans, ret); --- a/fs/btrfs/relocation.c +++ b/fs/btrfs/relocation.c -@@ -1679,6 +1679,8 @@ int replace_file_extents(struct btrfs_tr +@@ -1688,6 +1688,8 @@ int replace_file_extents(struct btrfs_tr nritems = btrfs_header_nritems(leaf); for (i = 0; i < nritems; i++) { @@ -260,11 +257,11 @@ Signed-off-by: David Sterba cond_resched(); btrfs_item_key_to_cpu(leaf, &key, i); if (key.type != BTRFS_EXTENT_DATA_KEY) -@@ -1739,10 +1741,12 @@ int replace_file_extents(struct btrfs_tr +@@ -1748,10 +1750,12 @@ int replace_file_extents(struct btrfs_tr dirty = 1; key.offset -= btrfs_file_extent_offset(leaf, fi); -- ret = btrfs_inc_extent_ref(trans, fs_info, new_bytenr, +- ret = btrfs_inc_extent_ref(trans, root, new_bytenr, - num_bytes, parent, - btrfs_header_owner(leaf), - key.objectid, key.offset); @@ -273,11 +270,11 @@ Signed-off-by: David Sterba + ref.real_root = root->root_key.objectid; + btrfs_init_data_ref(&ref, btrfs_header_owner(leaf), + key.objectid, key.offset); -+ ret = btrfs_inc_extent_ref(trans, fs_info, &ref); ++ ret = btrfs_inc_extent_ref(trans, root, &ref); if (ret) { btrfs_abort_transaction(trans, ret); break; -@@ -1792,6 +1796,7 @@ int replace_path(struct btrfs_trans_hand +@@ -1801,6 +1805,7 @@ int replace_path(struct btrfs_trans_hand struct btrfs_fs_info *fs_info = dest->fs_info; struct extent_buffer *eb; struct extent_buffer *parent; @@ -285,31 +282,31 @@ Signed-off-by: David Sterba struct btrfs_key key; u64 old_bytenr; u64 new_bytenr; -@@ -1950,13 +1955,17 @@ again: +@@ -1959,13 +1964,17 @@ again: path->slots[level], old_ptr_gen); btrfs_mark_buffer_dirty(path->nodes[level]); -- ret = btrfs_inc_extent_ref(trans, fs_info, old_bytenr, +- ret = btrfs_inc_extent_ref(trans, src, old_bytenr, - blocksize, path->nodes[level]->start, - src->root_key.objectid, level - 1, 0); + btrfs_init_generic_ref(&ref, BTRFS_ADD_DELAYED_REF, old_bytenr, + blocksize, path->nodes[level]->start); + ref.skip_qgroup = true; + btrfs_init_tree_ref(&ref, level - 1, src->root_key.objectid); -+ ret = btrfs_inc_extent_ref(trans, fs_info, &ref); ++ ret = btrfs_inc_extent_ref(trans, src, &ref); BUG_ON(ret); -- ret = btrfs_inc_extent_ref(trans, fs_info, new_bytenr, +- ret = btrfs_inc_extent_ref(trans, dest, new_bytenr, - blocksize, 0, dest->root_key.objectid, - level - 1, 0); + btrfs_init_generic_ref(&ref, BTRFS_ADD_DELAYED_REF, new_bytenr, + blocksize, 0); + ref.skip_qgroup = true; + btrfs_init_tree_ref(&ref, level - 1, dest->root_key.objectid); -+ ret = btrfs_inc_extent_ref(trans, fs_info, &ref); ++ ret = btrfs_inc_extent_ref(trans, dest, &ref); BUG_ON(ret); - ret = btrfs_free_extent(trans, fs_info, new_bytenr, blocksize, -@@ -2756,6 +2765,7 @@ static int do_relocation(struct btrfs_tr + ret = btrfs_free_extent(trans, src, new_bytenr, blocksize, +@@ -2765,6 +2774,7 @@ static int do_relocation(struct btrfs_tr rc->backref_cache.path[node->level] = node; list_for_each_entry(edge, &node->upper, list[LOWER]) { struct btrfs_key first_key; @@ -317,22 +314,22 @@ Signed-off-by: David Sterba cond_resched(); -@@ -2853,11 +2863,14 @@ static int do_relocation(struct btrfs_tr +@@ -2862,11 +2872,13 @@ static int do_relocation(struct btrfs_tr trans->transid); btrfs_mark_buffer_dirty(upper->eb); +- ret = btrfs_inc_extent_ref(trans, root, +- node->eb->start, blocksize, +- upper->eb->start, +- btrfs_header_owner(upper->eb), +- node->level, 0); + btrfs_init_generic_ref(&ref, BTRFS_ADD_DELAYED_REF, + node->eb->start, blocksize, + upper->eb->start); + ref.real_root = root->root_key.objectid; + btrfs_init_tree_ref(&ref, node->level, + btrfs_header_owner(upper->eb)); - ret = btrfs_inc_extent_ref(trans, root->fs_info, -- node->eb->start, blocksize, -- upper->eb->start, -- btrfs_header_owner(upper->eb), -- node->level, 0); -+ &ref); ++ ret = btrfs_inc_extent_ref(trans, root, &ref); BUG_ON(ret); ret = btrfs_drop_subtree(trans, root, eb, upper->eb); @@ -350,11 +347,11 @@ Signed-off-by: David Sterba /* * is this extent already allocated in the extent * allocation tree? If so, just add a reference -@@ -727,10 +729,14 @@ static noinline int replay_one_extent(st +@@ -727,10 +729,13 @@ static noinline int replay_one_extent(st ret = btrfs_lookup_data_extent(fs_info, ins.objectid, ins.offset); if (ret == 0) { -- ret = btrfs_inc_extent_ref(trans, fs_info, +- ret = btrfs_inc_extent_ref(trans, root, - ins.objectid, ins.offset, - 0, root->root_key.objectid, + btrfs_init_generic_ref(&ref, @@ -363,8 +360,16 @@ Signed-off-by: David Sterba + btrfs_init_data_ref(&ref, + root->root_key.objectid, key->objectid, offset); -+ ret = btrfs_inc_extent_ref(trans, fs_info, -+ &ref); ++ ret = btrfs_inc_extent_ref(trans, root, &ref); if (ret) goto out; } else { +@@ -3021,7 +3026,7 @@ static inline void btrfs_remove_log_ctx( + mutex_unlock(&root->log_mutex); + } + +-/* ++/* + * Invoked in log mutex context, or be sure there is no other task which + * can access the list. + */ diff --git a/patches.suse/0007-btrfs-extent_io-Handle-errors-better-in-extent_write.patch b/patches.suse/0007-btrfs-extent_io-Handle-errors-better-in-extent_write.patch new file mode 100644 index 0000000..655a136 --- /dev/null +++ b/patches.suse/0007-btrfs-extent_io-Handle-errors-better-in-extent_write.patch @@ -0,0 +1,52 @@ +From a2a72fbd1110323b2008dcb3ed14494957341dfe Mon Sep 17 00:00:00 2001 +From: Qu Wenruo +Date: Wed, 20 Mar 2019 14:27:48 +0800 +Patch-mainline: v5.2 +Git-commit: a2a72fbd1110323b2008dcb3ed14494957341dfe +References: bsc#1168273 +Subject: [PATCH 7/7] btrfs: extent_io: Handle errors better in + extent_writepages() + +We can only get <=0 from extent_write_cache_pages, add an ASSERT() for +it just in case. + +Then instead of submitting the write bio even if we got some error, +check the return value first. +If we have already hit some error, just clean up the corrupted or +half-baked bio, and return error. + +If there is no error so far, then call flush_write_bio() and return the +result. + +Signed-off-by: Qu Wenruo +Reviewed-by: David Sterba +Signed-off-by: David Sterba +--- + fs/btrfs/extent_io.c | 9 ++++++--- + 1 file changed, 6 insertions(+), 3 deletions(-) + +--- a/fs/btrfs/extent_io.c ++++ b/fs/btrfs/extent_io.c +@@ -4222,7 +4222,6 @@ int extent_writepages(struct extent_io_t + struct writeback_control *wbc) + { + int ret = 0; +- int flush_ret; + struct extent_page_data epd = { + .bio = NULL, + .tree = tree, +@@ -4231,8 +4230,12 @@ int extent_writepages(struct extent_io_t + }; + + ret = extent_write_cache_pages(mapping, wbc, &epd); +- flush_ret = flush_write_bio(&epd); +- BUG_ON(flush_ret < 0); ++ ASSERT(ret <= 0); ++ if (ret < 0) { ++ end_write_bio(&epd, ret); ++ return ret; ++ } ++ ret = flush_write_bio(&epd); + return ret; + } + diff --git a/patches.suse/0007-btrfs-move-the-space-info-update-macro-to-space-info-h.patch b/patches.suse/0007-btrfs-move-the-space-info-update-macro-to-space-info-h.patch new file mode 100644 index 0000000..5cf09eb --- /dev/null +++ b/patches.suse/0007-btrfs-move-the-space-info-update-macro-to-space-info-h.patch @@ -0,0 +1,224 @@ +From: Josef Bacik +Date: Tue, 18 Jun 2019 16:09:21 -0400 +Subject: btrfs: move the space info update macro to space-info.h +Git-commit: bb96c4e5742022b79b5bda5f52218b3d2785accd +Patch-mainline: v5.3-rc1 +References: bsc#1165949 + +Also rename it to btrfs_space_info_update_* so it's clear what we're +updating. + +Reviewed-by: Nikolay Borisov +Signed-off-by: Josef Bacik +Signed-off-by: David Sterba +Acked-by: Nikolay Borisov +--- + fs/btrfs/extent-tree.c | 63 ++++++++++++++++++++----------------------------- + fs/btrfs/space-info.h | 23 +++++++++++++++++ + 2 files changed, 49 insertions(+), 37 deletions(-) + +--- a/fs/btrfs/extent-tree.c ++++ b/fs/btrfs/extent-tree.c +@@ -43,26 +43,6 @@ + + #undef SCRAMBLE_DELAYED_REFS + +-/* +- * Declare a helper function to detect underflow of various space info members +- */ +-#define DECLARE_SPACE_INFO_UPDATE(name) \ +-static inline void update_##name(struct btrfs_fs_info *fs_info, \ +- struct btrfs_space_info *sinfo, \ +- s64 bytes) \ +-{ \ +- lockdep_assert_held(&sinfo->lock); \ +- trace_update_##name(fs_info, sinfo, sinfo->name, bytes); \ +- if (bytes < 0 && sinfo->name < -bytes) { \ +- WARN_ON(1); \ +- sinfo->name = 0; \ +- return; \ +- } \ +- sinfo->name += bytes; \ +-} +- +-DECLARE_SPACE_INFO_UPDATE(bytes_may_use); +-DECLARE_SPACE_INFO_UPDATE(bytes_pinned); + + static int update_block_group(struct btrfs_trans_handle *trans, + struct btrfs_fs_info *fs_info, u64 bytenr, +@@ -4266,7 +4246,7 @@ commit_trans: + data_sinfo->flags, bytes, 1); + return -ENOSPC; + } +- update_bytes_may_use(fs_info, data_sinfo, bytes); ++ btrfs_space_info_update_bytes_may_use(fs_info, data_sinfo, bytes); + trace_btrfs_space_reservation(fs_info, "space_info", + data_sinfo->flags, bytes, 1); + spin_unlock(&data_sinfo->lock); +@@ -4319,7 +4299,7 @@ void btrfs_free_reserved_data_space_noqu + + data_sinfo = fs_info->data_sinfo; + spin_lock(&data_sinfo->lock); +- update_bytes_may_use(fs_info, data_sinfo, -len); ++ btrfs_space_info_update_bytes_may_use(fs_info, data_sinfo, -len); + trace_btrfs_space_reservation(fs_info, "space_info", + data_sinfo->flags, len, 0); + spin_unlock(&data_sinfo->lock); +@@ -5156,12 +5136,14 @@ static int __reserve_metadata_bytes(stru + * If not things get more complicated. + */ + if (used + orig_bytes <= space_info->total_bytes) { +- update_bytes_may_use(fs_info, space_info, orig_bytes); ++ btrfs_space_info_update_bytes_may_use(fs_info, space_info, ++ orig_bytes); + trace_btrfs_space_reservation(fs_info, "space_info", + space_info->flags, orig_bytes, 1); + ret = 0; + } else if (btrfs_can_overcommit(root, space_info, orig_bytes, flush)) { +- update_bytes_may_use(fs_info, space_info, orig_bytes); ++ btrfs_space_info_update_bytes_may_use(fs_info, space_info, ++ orig_bytes); + trace_btrfs_space_reservation(fs_info, "space_info", + space_info->flags, orig_bytes, 1); + ret = 0; +@@ -5486,7 +5468,7 @@ again: + flush = BTRFS_RESERVE_FLUSH_ALL; + goto again; + } +- update_bytes_may_use(fs_info, space_info, -num_bytes); ++ btrfs_space_info_update_bytes_may_use(fs_info, space_info, -num_bytes); + trace_btrfs_space_reservation(fs_info, "space_info", + space_info->flags, num_bytes, 0); + spin_unlock(&space_info->lock); +@@ -5514,8 +5496,8 @@ again: + ticket->bytes, 1); + list_del_init(&ticket->list); + num_bytes -= ticket->bytes; +- update_bytes_may_use(fs_info, space_info, +- ticket->bytes); ++ btrfs_space_info_update_bytes_may_use(fs_info, ++ space_info, ticket->bytes); + ticket->bytes = 0; + space_info->tickets_id++; + wake_up(&ticket->wait); +@@ -5523,7 +5505,8 @@ again: + trace_btrfs_space_reservation(fs_info, "space_info", + space_info->flags, + num_bytes, 1); +- update_bytes_may_use(fs_info, space_info, num_bytes); ++ btrfs_space_info_update_bytes_may_use(fs_info, ++ space_info, num_bytes); + ticket->bytes -= num_bytes; + num_bytes = 0; + } +@@ -5823,14 +5806,16 @@ static void update_global_block_rsv(stru + num_bytes = min(num_bytes, + block_rsv->size - block_rsv->reserved); + block_rsv->reserved += num_bytes; +- update_bytes_may_use(fs_info, sinfo, num_bytes); ++ btrfs_space_info_update_bytes_may_use(fs_info, sinfo, ++ num_bytes); + trace_btrfs_space_reservation(fs_info, "space_info", + sinfo->flags, num_bytes, + 1); + } + } else if (block_rsv->reserved > block_rsv->size) { + num_bytes = block_rsv->reserved - block_rsv->size; +- update_bytes_may_use(fs_info, sinfo, -num_bytes); ++ btrfs_space_info_update_bytes_may_use(fs_info, sinfo, ++ -num_bytes); + trace_btrfs_space_reservation(fs_info, "space_info", + sinfo->flags, num_bytes, 0); + block_rsv->reserved = block_rsv->size; +@@ -6317,7 +6302,8 @@ static int update_block_group(struct btr + old_val -= num_bytes; + btrfs_set_block_group_used(&cache->item, old_val); + cache->pinned += num_bytes; +- update_bytes_pinned(info, cache->space_info, num_bytes); ++ btrfs_space_info_update_bytes_pinned(info, ++ cache->space_info, num_bytes); + cache->space_info->bytes_used -= num_bytes; + cache->space_info->disk_used -= num_bytes * factor; + spin_unlock(&cache->lock); +@@ -6398,7 +6384,8 @@ static int pin_down_extent(struct btrfs_ + spin_lock(&cache->space_info->lock); + spin_lock(&cache->lock); + cache->pinned += num_bytes; +- update_bytes_pinned(fs_info, cache->space_info, num_bytes); ++ btrfs_space_info_update_bytes_pinned(fs_info, cache->space_info, ++ num_bytes); + if (reserved) { + cache->reserved -= num_bytes; + cache->space_info->bytes_reserved -= num_bytes; +@@ -6615,7 +6602,8 @@ static int btrfs_add_reserved_bytes(stru + trace_btrfs_space_reservation(cache->fs_info, + "space_info", space_info->flags, + ram_bytes, 0); +- update_bytes_may_use(cache->fs_info, space_info, -ram_bytes); ++ btrfs_space_info_update_bytes_may_use(cache->fs_info, ++ space_info, -ram_bytes); + if (delalloc) + cache->delalloc_bytes += num_bytes; + } +@@ -6772,7 +6760,7 @@ static int unpin_extent_range(struct btr + spin_lock(&space_info->lock); + spin_lock(&cache->lock); + cache->pinned -= len; +- update_bytes_pinned(fs_info, space_info, -len); ++ btrfs_space_info_update_bytes_pinned(fs_info, space_info, -len); + + trace_btrfs_space_reservation(fs_info, "pinned", + space_info->flags, len, 0); +@@ -6792,8 +6780,8 @@ static int unpin_extent_range(struct btr + to_add = min(len, global_rsv->size - + global_rsv->reserved); + global_rsv->reserved += to_add; +- update_bytes_may_use(fs_info, space_info, +- to_add); ++ btrfs_space_info_update_bytes_may_use(fs_info, ++ space_info, to_add); + if (global_rsv->reserved >= global_rsv->size) + global_rsv->full = 1; + trace_btrfs_space_reservation(fs_info, +@@ -10957,7 +10945,8 @@ void btrfs_delete_unused_bgs(struct btrf + spin_lock(&space_info->lock); + spin_lock(&block_group->lock); + +- update_bytes_pinned(fs_info, space_info, -block_group->pinned); ++ btrfs_space_info_update_bytes_pinned(fs_info, space_info, ++ -block_group->pinned); + space_info->bytes_readonly += block_group->pinned; + percpu_counter_add(&space_info->total_bytes_pinned, + -block_group->pinned); +--- a/fs/btrfs/space-info.h ++++ b/fs/btrfs/space-info.h +@@ -74,6 +74,29 @@ static inline bool btrfs_mixed_space_inf + (space_info->flags & BTRFS_BLOCK_GROUP_DATA)); + } + ++/* ++ * ++ * Declare a helper function to detect underflow of various space info members ++ */ ++#define DECLARE_SPACE_INFO_UPDATE(name) \ ++static inline void \ ++btrfs_space_info_update_##name(struct btrfs_fs_info *fs_info, \ ++ struct btrfs_space_info *sinfo, \ ++ s64 bytes) \ ++{ \ ++ lockdep_assert_held(&sinfo->lock); \ ++ trace_update_##name(fs_info, sinfo, sinfo->name, bytes); \ ++ if (bytes < 0 && sinfo->name < -bytes) { \ ++ WARN_ON(1); \ ++ sinfo->name = 0; \ ++ return; \ ++ } \ ++ sinfo->name += bytes; \ ++} ++ ++DECLARE_SPACE_INFO_UPDATE(bytes_may_use); ++DECLARE_SPACE_INFO_UPDATE(bytes_pinned); ++ + void btrfs_space_info_add_new_bytes(struct btrfs_fs_info *fs_info, + struct btrfs_space_info *space_info, + u64 num_bytes); diff --git a/patches.suse/0007-btrfs-only-reserve-metadata_size-for-inodes.patch b/patches.suse/0007-btrfs-only-reserve-metadata_size-for-inodes.patch new file mode 100644 index 0000000..3c44a24 --- /dev/null +++ b/patches.suse/0007-btrfs-only-reserve-metadata_size-for-inodes.patch @@ -0,0 +1,80 @@ +From: Josef Bacik +Date: Thu, 22 Aug 2019 15:14:34 -0400 +Subject: btrfs: only reserve metadata_size for inodes +Git-commit: bcacf5f3f92b886431b3a739038cc74b5e7e9403 +Patch-mainline: v5.4-rc1 +References: bsc#1165949 + +Historically we reserved worst case for every btree operation, and +generally speaking we want to do that in cases where it could be the +worst case. However for updating inodes we know the inode items are +already in the tree, so it will only be an update operation and never an +insert operation. This allows us to always reserve only the +metadata_size amount for inode updates rather than the +insert_metadata_size amount. + +Reviewed-by: Nikolay Borisov +Signed-off-by: Josef Bacik +Signed-off-by: David Sterba +Acked-by: Nikolay Borisov +--- + fs/btrfs/delalloc-space.c | 21 +++++++++++++++++---- + fs/btrfs/delayed-inode.c | 2 +- + 2 files changed, 18 insertions(+), 5 deletions(-) + +diff --git a/fs/btrfs/delalloc-space.c b/fs/btrfs/delalloc-space.c +index 62aa18b38a08..391dcb217098 100644 +--- a/fs/btrfs/delalloc-space.c ++++ b/fs/btrfs/delalloc-space.c +@@ -255,9 +255,16 @@ static void btrfs_calculate_inode_block_rsv_size(struct btrfs_fs_info *fs_info, + + lockdep_assert_held(&inode->lock); + outstanding_extents = inode->outstanding_extents; +- if (outstanding_extents) ++ ++ /* ++ * Insert size for the number of outstanding extents, 1 normal size for ++ * updating the inode. ++ */ ++ if (outstanding_extents) { + reserve_size = btrfs_calc_insert_metadata_size(fs_info, +- outstanding_extents + 1); ++ outstanding_extents); ++ reserve_size += btrfs_calc_metadata_size(fs_info, 1); ++ } + csum_leaves = btrfs_csum_bytes_to_leaves(fs_info, + inode->csum_bytes); + reserve_size += btrfs_calc_insert_metadata_size(fs_info, +@@ -282,10 +289,16 @@ static void calc_inode_reservations(struct btrfs_fs_info *fs_info, + { + u64 nr_extents = count_max_extents(num_bytes); + u64 csum_leaves = btrfs_csum_bytes_to_leaves(fs_info, num_bytes); ++ u64 inode_update = btrfs_calc_metadata_size(fs_info, 1); + +- /* We add one for the inode update at finish ordered time */ + *meta_reserve = btrfs_calc_insert_metadata_size(fs_info, +- nr_extents + csum_leaves + 1); ++ nr_extents + csum_leaves); ++ ++ /* ++ * finish_ordered_io has to update the inode, so add the space required ++ * for an inode update. ++ */ ++ *meta_reserve += inode_update; + *qgroup_reserve = nr_extents * fs_info->nodesize; + } + +diff --git a/fs/btrfs/delayed-inode.c b/fs/btrfs/delayed-inode.c +index de87ea7ce84d..9318cf761a07 100644 +--- a/fs/btrfs/delayed-inode.c ++++ b/fs/btrfs/delayed-inode.c +@@ -612,7 +612,7 @@ static int btrfs_delayed_inode_reserve_metadata( + src_rsv = trans->block_rsv; + dst_rsv = &fs_info->delayed_block_rsv; + +- num_bytes = btrfs_calc_insert_metadata_size(fs_info, 1); ++ num_bytes = btrfs_calc_metadata_size(fs_info, 1); + + /* + * btrfs_dirty_inode will update the inode under btrfs_join_transaction + diff --git a/patches.suse/0007-btrfs-sink-get_extent-parameter-to-extent_readpages.patch b/patches.suse/0007-btrfs-sink-get_extent-parameter-to-extent_readpages.patch new file mode 100644 index 0000000..6cc9326 --- /dev/null +++ b/patches.suse/0007-btrfs-sink-get_extent-parameter-to-extent_readpages.patch @@ -0,0 +1,80 @@ +From 0932584b66e97aea91eb8c0b610e1d1083951b32 Mon Sep 17 00:00:00 2001 +From: David Sterba +Date: Fri, 23 Jun 2017 04:09:57 +0200 +Patch-mainline: v4.16 +Git-commit: 0932584b66e97aea91eb8c0b610e1d1083951b32 +References: bsc#1168273 +Subject: [PATCH 7/7] btrfs: sink get_extent parameter to extent_readpages + +There's only one caller that passes btrfs_get_extent. + +Signed-off-by: David Sterba +--- + fs/btrfs/extent_io.c | 11 +++++------ + fs/btrfs/extent_io.h | 3 +-- + fs/btrfs/inode.c | 3 +-- + 3 files changed, 7 insertions(+), 10 deletions(-) + +diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c +index 3f5debc5e56f..f86a6aae545a 100644 +--- a/fs/btrfs/extent_io.c ++++ b/fs/btrfs/extent_io.c +@@ -4133,8 +4133,7 @@ int extent_writepages(struct extent_io_tree *tree, + + int extent_readpages(struct extent_io_tree *tree, + struct address_space *mapping, +- struct list_head *pages, unsigned nr_pages, +- get_extent_t get_extent) ++ struct list_head *pages, unsigned nr_pages) + { + struct bio *bio = NULL; + unsigned page_idx; +@@ -4160,13 +4159,13 @@ int extent_readpages(struct extent_io_tree *tree, + pagepool[nr++] = page; + if (nr < ARRAY_SIZE(pagepool)) + continue; +- __extent_readpages(tree, pagepool, nr, get_extent, &em_cached, +- &bio, &bio_flags, &prev_em_start); ++ __extent_readpages(tree, pagepool, nr, btrfs_get_extent, ++ &em_cached, &bio, &bio_flags, &prev_em_start); + nr = 0; + } + if (nr) +- __extent_readpages(tree, pagepool, nr, get_extent, &em_cached, +- &bio, &bio_flags, &prev_em_start); ++ __extent_readpages(tree, pagepool, nr, btrfs_get_extent, ++ &em_cached, &bio, &bio_flags, &prev_em_start); + + if (em_cached) + free_extent_map(em_cached); +diff --git a/fs/btrfs/extent_io.h b/fs/btrfs/extent_io.h +index afc169d04b22..6cf4a0e5b0ea 100644 +--- a/fs/btrfs/extent_io.h ++++ b/fs/btrfs/extent_io.h +@@ -414,8 +414,7 @@ int btree_write_cache_pages(struct address_space *mapping, + struct writeback_control *wbc); + int extent_readpages(struct extent_io_tree *tree, + struct address_space *mapping, +- struct list_head *pages, unsigned nr_pages, +- get_extent_t get_extent); ++ struct list_head *pages, unsigned nr_pages); + int extent_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, + __u64 start, __u64 len); + void set_page_extent_mapped(struct page *page); +diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c +index 63cf6cd174d1..72c7b38fb17e 100644 +--- a/fs/btrfs/inode.c ++++ b/fs/btrfs/inode.c +@@ -8911,8 +8911,7 @@ btrfs_readpages(struct file *file, struct address_space *mapping, + { + struct extent_io_tree *tree; + tree = &BTRFS_I(mapping->host)->io_tree; +- return extent_readpages(tree, mapping, pages, nr_pages, +- btrfs_get_extent); ++ return extent_readpages(tree, mapping, pages, nr_pages); + } + static int __btrfs_releasepage(struct page *page, gfp_t gfp_flags) + { +-- +2.26.0 + diff --git a/patches.suse/0007-btrfs-unify-extent_page_data-type-passed-as-void.patch b/patches.suse/0007-btrfs-unify-extent_page_data-type-passed-as-void.patch new file mode 100644 index 0000000..7f8aeb0 --- /dev/null +++ b/patches.suse/0007-btrfs-unify-extent_page_data-type-passed-as-void.patch @@ -0,0 +1,93 @@ +From aab6e9edf07f2f4747fbc4aa04e14683fbe0c8ac Mon Sep 17 00:00:00 2001 +From: David Sterba +Date: Thu, 30 Nov 2017 18:00:02 +0100 +Patch-mainline: v4.16 +Git-commit: aab6e9edf07f2f4747fbc4aa04e14683fbe0c8ac +References: bsc#1168273 +Subject: [PATCH 7/7] btrfs: unify extent_page_data type passed as void + +Functions called from extent_write_cache_pages used void* as generic +callback data, but all of them convert it to extent_page_data, or use it +directly. + +Signed-off-by: David Sterba +--- + fs/btrfs/extent_io.c | 17 +++++++---------- + 1 file changed, 7 insertions(+), 10 deletions(-) + +diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c +index 0ceb427a8e63..eee9cc5db9ff 100644 +--- a/fs/btrfs/extent_io.c ++++ b/fs/btrfs/extent_io.c +@@ -138,7 +138,7 @@ static void add_extent_changeset(struct extent_state *state, unsigned bits, + BUG_ON(ret < 0); + } + +-static void flush_write_bio(void *data); ++static void flush_write_bio(struct extent_page_data *epd); + + static inline struct btrfs_fs_info * + tree_fs_info(struct extent_io_tree *tree) +@@ -3456,10 +3456,9 @@ static noinline_for_stack int __extent_writepage_io(struct inode *inode, + * and the end_io handler clears the writeback ranges + */ + static int __extent_writepage(struct page *page, struct writeback_control *wbc, +- void *data) ++ struct extent_page_data *epd) + { + struct inode *inode = page->mapping->host; +- struct extent_page_data *epd = data; + u64 start = page_offset(page); + u64 page_end = start + PAGE_SIZE - 1; + int ret; +@@ -3905,7 +3904,7 @@ int btree_write_cache_pages(struct address_space *mapping, + */ + static int extent_write_cache_pages(struct address_space *mapping, + struct writeback_control *wbc, +- void *data) ++ struct extent_page_data *epd) + { + struct inode *inode = mapping->host; + int ret = 0; +@@ -3969,7 +3968,7 @@ static int extent_write_cache_pages(struct address_space *mapping, + * mapping + */ + if (!trylock_page(page)) { +- flush_write_bio(data); ++ flush_write_bio(epd); + lock_page(page); + } + +@@ -3980,7 +3979,7 @@ static int extent_write_cache_pages(struct address_space *mapping, + + if (wbc->sync_mode != WB_SYNC_NONE) { + if (PageWriteback(page)) +- flush_write_bio(data); ++ flush_write_bio(epd); + wait_on_page_writeback(page); + } + +@@ -3990,7 +3989,7 @@ static int extent_write_cache_pages(struct address_space *mapping, + continue; + } + +- ret = __extent_writepage(page, wbc, data); ++ ret = __extent_writepage(page, wbc, epd); + + if (unlikely(ret == AOP_WRITEPAGE_ACTIVATE)) { + unlock_page(page); +@@ -4038,10 +4037,8 @@ static int extent_write_cache_pages(struct address_space *mapping, + return ret; + } + +-static void flush_write_bio(void *data) ++static void flush_write_bio(struct extent_page_data *epd) + { +- struct extent_page_data *epd = data; +- + if (epd->bio) { + int ret; + +-- +2.26.0 + diff --git a/patches.suse/0007-md-fix-an-error-code-format-and-remove-unsed-bio_sec.patch b/patches.suse/0007-md-fix-an-error-code-format-and-remove-unsed-bio_sec.patch new file mode 100644 index 0000000..b02055d --- /dev/null +++ b/patches.suse/0007-md-fix-an-error-code-format-and-remove-unsed-bio_sec.patch @@ -0,0 +1,53 @@ +From 13db16d74c02c0e9b2d0dc9b9773c8e58ad41064 Mon Sep 17 00:00:00 2001 +From: Yufen Yu +Date: Mon, 23 Apr 2018 17:37:30 +0800 +Subject: [PATCH] md: fix an error code format and remove unsed bio_sector +Git-commit: 13db16d74c02c0e9b2d0dc9b9773c8e58ad41064 +Patch-mainline: v4.18-rc1 +References: bsc#1111974 bsc#1166003 + +Signed-off-by: Yufen Yu +Signed-off-by: Shaohua Li +Signed-off-by: Coly Li + +--- + drivers/md/raid1.c | 2 -- + drivers/md/raid10.c | 2 +- + 2 files changed, 1 insertion(+), 3 deletions(-) + +diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c +index e9e3308cb0a7..397b3d80c48b 100644 +--- a/drivers/md/raid1.c ++++ b/drivers/md/raid1.c +@@ -2450,7 +2450,6 @@ static void handle_read_error(struct r1conf *conf, struct r1bio *r1_bio) + struct mddev *mddev = conf->mddev; + struct bio *bio; + struct md_rdev *rdev; +- sector_t bio_sector; + + clear_bit(R1BIO_ReadError, &r1_bio->state); + /* we got a read error. Maybe the drive is bad. Maybe just +@@ -2463,7 +2462,6 @@ static void handle_read_error(struct r1conf *conf, struct r1bio *r1_bio) + */ + + bio = r1_bio->bios[r1_bio->read_disk]; +- bio_sector = conf->mirrors[r1_bio->read_disk].rdev->data_offset + r1_bio->sector; + bio_put(bio); + r1_bio->bios[r1_bio->read_disk] = NULL; + +diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c +index 3c60774c8430..64300542ab20 100644 +--- a/drivers/md/raid10.c ++++ b/drivers/md/raid10.c +@@ -2363,7 +2363,7 @@ static void fix_read_error(struct r10conf *conf, struct mddev *mddev, struct r10 + { + int sect = 0; /* Offset from r10_bio->sector */ + int sectors = r10_bio->sectors; +- struct md_rdev*rdev; ++ struct md_rdev *rdev; + int max_read_errors = atomic_read(&mddev->max_corr_read_errors); + int d = r10_bio->devs[r10_bio->read_slot].devnum; + +-- +2.19.0 + diff --git a/patches.suse/0008-btrfs-do-not-allow-reservations-if-we-have-pending-tickets.patch b/patches.suse/0008-btrfs-do-not-allow-reservations-if-we-have-pending-tickets.patch new file mode 100644 index 0000000..56e2c67 --- /dev/null +++ b/patches.suse/0008-btrfs-do-not-allow-reservations-if-we-have-pending-tickets.patch @@ -0,0 +1,70 @@ +From: Josef Bacik +Date: Thu, 22 Aug 2019 15:10:54 -0400 +Subject: btrfs: do not allow reservations if we have pending tickets +Git-commit: ef1317a1b9a347cdc3967a2048046e8fb4db94ba +Patch-mainline: v5.4-rc1 +References: bsc#1165949 + +If we already have tickets on the list we don't want to steal their +reservations. This is a preparation patch for upcoming changes, +technically this shouldn't happen today because of the way we add bytes +to tickets before adding them to the space_info in most cases. + +This does not change the FIFO nature of reserve tickets, it simply +allows us to enforce it in a different way. Previously it was enforced +because any new space would be added to the first ticket on the list, +which would result in new reservations getting a reserve ticket. This +replaces that mechanism by simply checking to see if we have outstanding +reserve tickets and skipping straight to adding a ticket for our +reservation. + +Reviewed-by: Nikolay Borisov +Signed-off-by: Josef Bacik +Signed-off-by: David Sterba +Acked-by: Nikolay Borisov +--- + fs/btrfs/space-info.c | 14 ++++++-------- + 1 file changed, 6 insertions(+), 8 deletions(-) + +--- a/fs/btrfs/space-info.c ++++ b/fs/btrfs/space-info.c +@@ -1008,6 +1008,7 @@ static int __reserve_metadata_bytes(stru + struct reserve_ticket ticket; + u64 used; + int ret = 0; ++ bool pending_tickets; + + ASSERT(orig_bytes); + ASSERT(!current->journal_info || flush != BTRFS_RESERVE_FLUSH_ALL); +@@ -1015,26 +1016,23 @@ static int __reserve_metadata_bytes(stru + spin_lock(&space_info->lock); + ret = -ENOSPC; + used = btrfs_space_info_used(space_info, true); ++ pending_tickets = !list_empty(&space_info->tickets) || ++ !list_empty(&space_info->priority_tickets); + + /* + * If we have enough space then hooray, make our reservation and carry + * on. If not see if we can overcommit, and if we can, hooray carry on. + * If not things get more complicated. + */ +- if (used + orig_bytes <= space_info->total_bytes) { +- btrfs_space_info_update_bytes_may_use(fs_info, space_info, +- orig_bytes); +- trace_btrfs_space_reservation(fs_info, "space_info", +- space_info->flags, orig_bytes, 1); +- ret = 0; +- } else if (can_overcommit(root, space_info, orig_bytes, flush)) { ++ if (!pending_tickets && ++ ((used + orig_bytes <= space_info->total_bytes) || ++ can_overcommit(root, space_info, orig_bytes, flush))) { + btrfs_space_info_update_bytes_may_use(fs_info, space_info, + orig_bytes); + trace_btrfs_space_reservation(fs_info, "space_info", + space_info->flags, orig_bytes, 1); + ret = 0; + } +- + /* + * If we couldn't make a reservation then setup our reservation ticket + * and kick the async worker if it's not already running. diff --git a/patches.suse/0008-btrfs-don-t-enospc-all-tickets-on-flush-failure.patch b/patches.suse/0008-btrfs-don-t-enospc-all-tickets-on-flush-failure.patch new file mode 100644 index 0000000..ef2344e --- /dev/null +++ b/patches.suse/0008-btrfs-don-t-enospc-all-tickets-on-flush-failure.patch @@ -0,0 +1,154 @@ +From: Josef Bacik +Date: Wed, 21 Nov 2018 14:03:10 -0500 +Subject: btrfs: don't enospc all tickets on flush failure +Git-commit: f91587e4151e84f798f37839dddd3e4152fb4c76 +Patch-mainline: v5.1-rc1 +References: bsc#1165949 + +With the introduction of the per-inode block_rsv it became possible to +have really really large reservation requests made because of data +fragmentation. Since the ticket stuff assumed that we'd always have +relatively small reservation requests it just killed all tickets if we +were unable to satisfy the current request. + +However, this is generally not the case anymore. So fix this logic to +instead see if we had a ticket that we were able to give some +reservation to, and if we were continue the flushing loop again. + +Likewise we make the tickets use the space_info_add_old_bytes() method +of returning what reservation they did receive in hopes that it could +satisfy reservations down the line. + +Reviewed-by: Nikolay Borisov +Signed-off-by: Josef Bacik +Signed-off-by: David Sterba +Acked-by: Nikolay Borisov +--- + fs/btrfs/extent-tree.c | 45 +++++++++++++++++++++++++-------------------- + 1 file changed, 25 insertions(+), 20 deletions(-) + +--- a/fs/btrfs/extent-tree.c ++++ b/fs/btrfs/extent-tree.c +@@ -4929,6 +4929,7 @@ skip_async: + } + + struct reserve_ticket { ++ u64 orig_bytes; + u64 bytes; + int error; + struct list_head list; +@@ -5151,7 +5152,7 @@ static inline int need_do_async_reclaim( + !test_bit(BTRFS_FS_STATE_REMOUNTING, &fs_info->fs_state)); + } + +-static void wake_all_tickets(struct list_head *head) ++static bool wake_all_tickets(struct list_head *head) + { + struct reserve_ticket *ticket; + +@@ -5160,7 +5161,10 @@ static void wake_all_tickets(struct list + list_del_init(&ticket->list); + ticket->error = -ENOSPC; + wake_up(&ticket->wait); ++ if (ticket->bytes != ticket->orig_bytes) ++ return true; + } ++ return false; + } + + /* +@@ -5233,8 +5237,12 @@ static void btrfs_async_reclaim_metadata + if (flush_state > COMMIT_TRANS) { + commit_cycles++; + if (commit_cycles > 2) { +- wake_all_tickets(&space_info->tickets); +- space_info->flush = 0; ++ if (wake_all_tickets(&space_info->tickets)) { ++ flush_state = FLUSH_DELAYED_ITEMS_NR; ++ commit_cycles--; ++ } else { ++ space_info->flush = 0; ++ } + } else { + flush_state = FLUSH_DELAYED_ITEMS_NR; + } +@@ -5287,10 +5295,11 @@ static void priority_reclaim_metadata_sp + + static int wait_reserve_ticket(struct btrfs_fs_info *fs_info, + struct btrfs_space_info *space_info, +- struct reserve_ticket *ticket, u64 orig_bytes) ++ struct reserve_ticket *ticket) + + { + DEFINE_WAIT(wait); ++ u64 reclaim_bytes = 0; + int ret = 0; + + spin_lock(&space_info->lock); +@@ -5311,14 +5320,12 @@ static int wait_reserve_ticket(struct bt + ret = ticket->error; + if (!list_empty(&ticket->list)) + list_del_init(&ticket->list); +- if (ticket->bytes && ticket->bytes < orig_bytes) { +- u64 num_bytes = orig_bytes - ticket->bytes; +- update_bytes_may_use(space_info, -num_bytes); +- trace_btrfs_space_reservation(fs_info, "space_info", +- space_info->flags, num_bytes, 0); +- } ++ if (ticket->bytes && ticket->bytes < ticket->orig_bytes) ++ reclaim_bytes = ticket->orig_bytes - ticket->bytes; + spin_unlock(&space_info->lock); + ++ if (reclaim_bytes) ++ space_info_add_old_bytes(fs_info, space_info, reclaim_bytes); + return ret; + } + +@@ -5344,6 +5351,7 @@ static int __reserve_metadata_bytes(stru + struct btrfs_fs_info *fs_info = root->fs_info; + struct reserve_ticket ticket; + u64 used; ++ u64 reclaim_bytes = 0; + int ret = 0; + + ASSERT(orig_bytes); +@@ -5378,6 +5386,7 @@ static int __reserve_metadata_bytes(stru + * the list and we will do our own flushing further down. + */ + if (ret && flush != BTRFS_RESERVE_NO_FLUSH) { ++ ticket.orig_bytes = orig_bytes; + ticket.bytes = orig_bytes; + ticket.error = 0; + init_waitqueue_head(&ticket.wait); +@@ -5417,25 +5426,21 @@ static int __reserve_metadata_bytes(stru + return ret; + + if (flush == BTRFS_RESERVE_FLUSH_ALL) +- return wait_reserve_ticket(fs_info, space_info, &ticket, +- orig_bytes); ++ return wait_reserve_ticket(fs_info, space_info, &ticket); + + ret = 0; + priority_reclaim_metadata_space(fs_info, space_info, &ticket); + spin_lock(&space_info->lock); + if (ticket.bytes) { +- if (ticket.bytes < orig_bytes) { +- u64 num_bytes = orig_bytes - ticket.bytes; +- update_bytes_may_use(space_info, -num_bytes); +- trace_btrfs_space_reservation(fs_info, "space_info", +- space_info->flags, +- num_bytes, 0); +- +- } ++ if (ticket.bytes < orig_bytes) ++ reclaim_bytes = orig_bytes - ticket.bytes; + list_del_init(&ticket.list); + ret = -ENOSPC; + } + spin_unlock(&space_info->lock); ++ ++ if (reclaim_bytes) ++ space_info_add_old_bytes(fs_info, space_info, reclaim_bytes); + ASSERT(list_empty(&ticket.list)); + return ret; + } diff --git a/patches.suse/0008-btrfs-export-the-caching-control-helpers.patch b/patches.suse/0008-btrfs-export-the-caching-control-helpers.patch new file mode 100644 index 0000000..e3c3822 --- /dev/null +++ b/patches.suse/0008-btrfs-export-the-caching-control-helpers.patch @@ -0,0 +1,183 @@ +From: Josef Bacik +Date: Thu, 20 Jun 2019 15:37:50 -0400 +Subject: btrfs: export the caching control helpers +Git-commit: e3cb339fa5ca57cfa5429bf3da548331dce93038 +Patch-mainline: v5.4-rc1 +References: bsc#1165949 + +Man a lot of people use this stuff. + +Signed-off-by: Josef Bacik +Reviewed-by: David Sterba +Signed-off-by: David Sterba +Acked-by: Nikolay Borisov +--- + fs/btrfs/block-group.h | 3 +++ + fs/btrfs/extent-tree.c | 36 ++++++++++++++++++------------------ + 2 files changed, 21 insertions(+), 18 deletions(-) + +diff --git a/fs/btrfs/block-group.h b/fs/btrfs/block-group.h +index 7069bcfc5e8f..3f8b6ffefb8a 100644 +--- a/fs/btrfs/block-group.h ++++ b/fs/btrfs/block-group.h +@@ -170,6 +170,9 @@ void btrfs_wait_block_group_cache_progress(struct btrfs_block_group_cache *cache + int btrfs_wait_block_group_cache_done(struct btrfs_block_group_cache *cache); + int btrfs_cache_block_group(struct btrfs_block_group_cache *cache, + int load_cache_only); ++void btrfs_put_caching_control(struct btrfs_caching_control *ctl); ++struct btrfs_caching_control *btrfs_get_caching_control( ++ struct btrfs_block_group_cache *cache); + + static inline int btrfs_block_group_cache_done( + struct btrfs_block_group_cache *cache) +diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c +index 2d92f103fa2b..dab8e90237cd 100644 +--- a/fs/btrfs/extent-tree.c ++++ b/fs/btrfs/extent-tree.c +@@ -182,8 +182,8 @@ static int exclude_super_stripes(struct btrfs_block_group_cache *cache) + return 0; + } + +-static struct btrfs_caching_control * +-get_caching_control(struct btrfs_block_group_cache *cache) ++struct btrfs_caching_control *btrfs_get_caching_control( ++ struct btrfs_block_group_cache *cache) + { + struct btrfs_caching_control *ctl; + +@@ -199,7 +199,7 @@ get_caching_control(struct btrfs_block_group_cache *cache) + return ctl; + } + +-static void put_caching_control(struct btrfs_caching_control *ctl) ++void btrfs_put_caching_control(struct btrfs_caching_control *ctl) + { + if (refcount_dec_and_test(&ctl->count)) + kfree(ctl); +@@ -455,7 +455,7 @@ static noinline void caching_thread(struct btrfs_work *work) + + wake_up(&caching_ctl->wait); + +- put_caching_control(caching_ctl); ++ btrfs_put_caching_control(caching_ctl); + btrfs_put_block_group(block_group); + } + +@@ -504,7 +504,7 @@ int btrfs_cache_block_group(struct btrfs_block_group_cache *cache, + schedule(); + + finish_wait(&ctl->wait, &wait); +- put_caching_control(ctl); ++ btrfs_put_caching_control(ctl); + spin_lock(&cache->lock); + } + +@@ -557,7 +557,7 @@ int btrfs_cache_block_group(struct btrfs_block_group_cache *cache, + + wake_up(&caching_ctl->wait); + if (ret == 1) { +- put_caching_control(caching_ctl); ++ btrfs_put_caching_control(caching_ctl); + btrfs_free_excluded_extents(cache); + return 0; + } +@@ -579,7 +579,7 @@ int btrfs_cache_block_group(struct btrfs_block_group_cache *cache, + } + + if (load_cache_only) { +- put_caching_control(caching_ctl); ++ btrfs_put_caching_control(caching_ctl); + return 0; + } + +@@ -4153,7 +4153,7 @@ static int __exclude_logged_extent(struct btrfs_fs_info *fs_info, + return -EINVAL; + + btrfs_cache_block_group(block_group, 0); +- caching_ctl = get_caching_control(block_group); ++ caching_ctl = btrfs_get_caching_control(block_group); + + if (!caching_ctl) { + /* Logic error */ +@@ -4183,7 +4183,7 @@ static int __exclude_logged_extent(struct btrfs_fs_info *fs_info, + } + out_lock: + mutex_unlock(&caching_ctl->mutex); +- put_caching_control(caching_ctl); ++ btrfs_put_caching_control(caching_ctl); + } + btrfs_put_block_group(block_group); + return ret; +@@ -4306,7 +4306,7 @@ void btrfs_prepare_extent_commit(struct btrfs_fs_info *fs_info) + if (btrfs_block_group_cache_done(cache)) { + cache->last_byte_to_unpin = (u64)-1; + list_del_init(&caching_ctl->list); +- put_caching_control(caching_ctl); ++ btrfs_put_caching_control(caching_ctl); + } else { + cache->last_byte_to_unpin = caching_ctl->progress; + } +@@ -4937,14 +4937,14 @@ void btrfs_wait_block_group_cache_progress(struct btrfs_block_group_cache *cache + { + struct btrfs_caching_control *caching_ctl; + +- caching_ctl = get_caching_control(cache); ++ caching_ctl = btrfs_get_caching_control(cache); + if (!caching_ctl) + return; + + wait_event(caching_ctl->wait, btrfs_block_group_cache_done(cache) || + (cache->free_space_ctl->free_space >= num_bytes)); + +- put_caching_control(caching_ctl); ++ btrfs_put_caching_control(caching_ctl); + } + + int btrfs_wait_block_group_cache_done(struct btrfs_block_group_cache *cache) +@@ -4952,14 +4952,14 @@ int btrfs_wait_block_group_cache_done(struct btrfs_block_group_cache *cache) + struct btrfs_caching_control *caching_ctl; + int ret = 0; + +- caching_ctl = get_caching_control(cache); ++ caching_ctl = btrfs_get_caching_control(cache); + if (!caching_ctl) + return (cache->cached == BTRFS_CACHE_ERROR) ? -EIO : 0; + + wait_event(caching_ctl->wait, btrfs_block_group_cache_done(cache)); + if (cache->cached == BTRFS_CACHE_ERROR) + ret = -EIO; +- put_caching_control(caching_ctl); ++ btrfs_put_caching_control(caching_ctl); + return ret; + } + +@@ -7482,7 +7482,7 @@ int btrfs_free_block_groups(struct btrfs_fs_info *info) + caching_ctl = list_entry(info->caching_block_groups.next, + struct btrfs_caching_control, list); + list_del(&caching_ctl->list); +- put_caching_control(caching_ctl); ++ btrfs_put_caching_control(caching_ctl); + } + up_write(&info->commit_root_sem); + +@@ -8202,7 +8202,7 @@ int btrfs_remove_block_group(struct btrfs_trans_handle *trans, + } + + if (block_group->has_caching_ctl) +- caching_ctl = get_caching_control(block_group); ++ caching_ctl = btrfs_get_caching_control(block_group); + if (block_group->cached == BTRFS_CACHE_STARTED) + btrfs_wait_block_group_cache_done(block_group); + if (block_group->has_caching_ctl) { +@@ -8223,8 +8223,8 @@ int btrfs_remove_block_group(struct btrfs_trans_handle *trans, + up_write(&fs_info->commit_root_sem); + if (caching_ctl) { + /* Once for the caching bgs list and once for us. */ +- put_caching_control(caching_ctl); +- put_caching_control(caching_ctl); ++ btrfs_put_caching_control(caching_ctl); ++ btrfs_put_caching_control(caching_ctl); + } + } + + diff --git a/patches.suse/0008-btrfs-extent-tree-Use-btrfs_ref-to-refactor-btrfs_fr.patch b/patches.suse/0008-btrfs-extent-tree-Use-btrfs_ref-to-refactor-btrfs_fr.patch index 26e00ce..37a8dfe 100644 --- a/patches.suse/0008-btrfs-extent-tree-Use-btrfs_ref-to-refactor-btrfs_fr.patch +++ b/patches.suse/0008-btrfs-extent-tree-Use-btrfs_ref-to-refactor-btrfs_fr.patch @@ -15,18 +15,18 @@ Reviewed-by: David Sterba Signed-off-by: David Sterba --- fs/btrfs/ctree.h | 3 +-- - fs/btrfs/extent-tree.c | 44 +++++++++++++++++++------------------------- - fs/btrfs/file.c | 23 +++++++++++++---------- - fs/btrfs/inode.c | 13 +++++++++---- + fs/btrfs/extent-tree.c | 40 +++++++++++++++++----------------------- + fs/btrfs/file.c | 24 +++++++++++++----------- + fs/btrfs/inode.c | 12 ++++++++---- fs/btrfs/relocation.c | 25 ++++++++++++++++--------- - 5 files changed, 58 insertions(+), 50 deletions(-) + 5 files changed, 55 insertions(+), 49 deletions(-) --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h -@@ -2720,8 +2720,7 @@ int btrfs_set_disk_extent_flags(struct b +@@ -2754,8 +2754,7 @@ int btrfs_set_disk_extent_flags(struct b int level, int is_data); int btrfs_free_extent(struct btrfs_trans_handle *trans, - struct btrfs_fs_info *fs_info, + struct btrfs_root *root, - u64 bytenr, u64 num_bytes, u64 parent, u64 root_objectid, - u64 owner, u64 offset); + struct btrfs_ref *ref); @@ -35,38 +35,36 @@ Signed-off-by: David Sterba u64 start, u64 len, int delalloc); --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c -@@ -3298,9 +3298,8 @@ static int __btrfs_mod_ref(struct btrfs_ - ret = btrfs_inc_extent_ref(trans, fs_info, - &generic_ref); +@@ -3389,9 +3389,7 @@ static int __btrfs_mod_ref(struct btrfs_ + if (inc) + ret = btrfs_inc_extent_ref(trans, root, &generic_ref); else -- ret = btrfs_free_extent(trans, fs_info, bytenr, -- num_bytes, parent, ref_root, -- key.objectid, key.offset); -+ ret = btrfs_free_extent(trans, fs_info, -+ &generic_ref); +- ret = btrfs_free_extent(trans, root, bytenr, num_bytes, +- parent, ref_root, key.objectid, +- key.offset); ++ ret = btrfs_free_extent(trans, root, &generic_ref); if (ret) goto fail; } else { -@@ -3315,9 +3314,8 @@ static int __btrfs_mod_ref(struct btrfs_ - ret = btrfs_inc_extent_ref(trans, fs_info, - &generic_ref); +@@ -3400,8 +3398,7 @@ static int __btrfs_mod_ref(struct btrfs_ + if (inc) + ret = btrfs_inc_extent_ref(trans, root, &generic_ref); else -- ret = btrfs_free_extent(trans, fs_info, bytenr, -- num_bytes, parent, ref_root, -- level - 1, 0); -+ ret = btrfs_free_extent(trans, fs_info, -+ &generic_ref); +- ret = btrfs_free_extent(trans, root, bytenr, num_bytes, +- parent, ref_root, level - 1, 0); ++ ret = btrfs_free_extent(trans, root, &generic_ref); if (ret) goto fail; } -@@ -7190,42 +7188,36 @@ out: +@@ -7275,42 +7272,37 @@ out: /* Can return -ENOMEM */ int btrfs_free_extent(struct btrfs_trans_handle *trans, - struct btrfs_fs_info *fs_info, + struct btrfs_root *root, - u64 bytenr, u64 num_bytes, u64 parent, u64 root_objectid, - u64 owner, u64 offset) + struct btrfs_ref *ref) { + struct btrfs_fs_info *fs_info = root->fs_info; - struct btrfs_ref generic_ref = { 0 }; int old_ref_mod, new_ref_mod; int ret; @@ -74,7 +72,6 @@ Signed-off-by: David Sterba if (btrfs_is_testing(fs_info)) return 0; -- - btrfs_init_generic_ref(&generic_ref, BTRFS_DROP_DELAYED_REF, bytenr, - num_bytes, parent); - generic_ref.real_root = root_objectid; @@ -112,7 +109,7 @@ Signed-off-by: David Sterba return ret; } -@@ -8652,6 +8644,7 @@ static noinline int do_walk_down(struct +@@ -8737,6 +8729,7 @@ static noinline int do_walk_down(struct u32 blocksize; struct btrfs_key key; struct btrfs_key first_key; @@ -120,43 +117,43 @@ Signed-off-by: David Sterba struct extent_buffer *next; int level = wc->level; int reada = 0; -@@ -8825,9 +8818,10 @@ skip: +@@ -8909,9 +8902,10 @@ skip: + */ wc->drop_level = level; find_next_key(path, level, &wc->drop_progress); - -- ret = btrfs_free_extent(trans, fs_info, bytenr, blocksize, +- ret = btrfs_free_extent(trans, root, bytenr, blocksize, - parent, root->root_key.objectid, - level - 1, 0); + btrfs_init_generic_ref(&ref, BTRFS_DROP_DELAYED_REF, bytenr, + fs_info->nodesize, parent); + btrfs_init_tree_ref(&ref, level - 1, root->root_key.objectid); -+ ret = btrfs_free_extent(trans, fs_info, &ref); ++ ret = btrfs_free_extent(trans, root, &ref); if (ret) goto out_unlock; } --- a/fs/btrfs/file.c +++ b/fs/btrfs/file.c -@@ -1007,11 +1007,15 @@ delete_extent_item: +@@ -1006,11 +1006,14 @@ delete_extent_item: extent_end = ALIGN(extent_end, fs_info->sectorsize); } else if (update_refs && disk_bytenr > 0) { -- ret = btrfs_free_extent(trans, fs_info, +- ret = btrfs_free_extent(trans, root, - disk_bytenr, num_bytes, 0, +- root->root_key.objectid, +- key.objectid, key.offset - +- extent_offset); + btrfs_init_generic_ref(&ref, + BTRFS_DROP_DELAYED_REF, + disk_bytenr, num_bytes, 0); + btrfs_init_data_ref(&ref, - root->root_key.objectid, -- key.objectid, key.offset - -- extent_offset); ++ root->root_key.objectid, + key.objectid, + key.offset - extent_offset); -+ ret = btrfs_free_extent(trans, fs_info, -+ &ref); ++ ret = btrfs_free_extent(trans, root, &ref); BUG_ON(ret); /* -ENOMEM */ inode_sub_bytes(inode, extent_end - key.offset); -@@ -1328,6 +1332,9 @@ again: +@@ -1327,6 +1330,9 @@ again: other_start = end; other_end = 0; @@ -166,31 +163,31 @@ Signed-off-by: David Sterba if (extent_mergeable(leaf, path->slots[0] + 1, ino, bytenr, orig_offset, &other_start, &other_end)) { -@@ -1338,9 +1345,7 @@ again: +@@ -1337,9 +1343,7 @@ again: extent_end = other_end; del_slot = path->slots[0] + 1; del_nr++; -- ret = btrfs_free_extent(trans, fs_info, bytenr, num_bytes, +- ret = btrfs_free_extent(trans, root, bytenr, num_bytes, - 0, root->root_key.objectid, - ino, orig_offset); -+ ret = btrfs_free_extent(trans, fs_info, &ref); ++ ret = btrfs_free_extent(trans, root, &ref); if (ret) { btrfs_abort_transaction(trans, ret); goto out; -@@ -1358,9 +1363,7 @@ again: +@@ -1357,9 +1361,7 @@ again: key.offset = other_start; del_slot = path->slots[0]; del_nr++; -- ret = btrfs_free_extent(trans, fs_info, bytenr, num_bytes, +- ret = btrfs_free_extent(trans, root, bytenr, num_bytes, - 0, root->root_key.objectid, - ino, orig_offset); -+ ret = btrfs_free_extent(trans, fs_info, &ref); ++ ret = btrfs_free_extent(trans, root, &ref); if (ret) { btrfs_abort_transaction(trans, ret); goto out; --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c -@@ -4476,12 +4476,17 @@ delete: +@@ -4484,12 +4484,16 @@ delete: if (found_extent && (test_bit(BTRFS_ROOT_REF_COWS, &root->state) || root == fs_info->tree_root)) { @@ -198,27 +195,26 @@ Signed-off-by: David Sterba + btrfs_set_path_blocking(path); bytes_deleted += extent_num_bytes; -- ret = btrfs_free_extent(trans, fs_info, extent_start, +- ret = btrfs_free_extent(trans, root, extent_start, - extent_num_bytes, 0, - btrfs_header_owner(leaf), - ino, extent_offset); -+ + btrfs_init_generic_ref(&ref, BTRFS_DROP_DELAYED_REF, + extent_start, extent_num_bytes, 0); + ref.real_root = root->root_key.objectid; + btrfs_init_data_ref(&ref, btrfs_header_owner(leaf), + ino, extent_offset); -+ ret = btrfs_free_extent(trans, fs_info, &ref); ++ ret = btrfs_free_extent(trans, root, &ref); if (ret) { btrfs_abort_transaction(trans, ret); break; --- a/fs/btrfs/relocation.c +++ b/fs/btrfs/relocation.c -@@ -1752,9 +1752,12 @@ int replace_file_extents(struct btrfs_tr +@@ -1761,9 +1761,12 @@ int replace_file_extents(struct btrfs_tr break; } -- ret = btrfs_free_extent(trans, fs_info, bytenr, num_bytes, +- ret = btrfs_free_extent(trans, root, bytenr, num_bytes, - parent, btrfs_header_owner(leaf), - key.objectid, key.offset); + btrfs_init_generic_ref(&ref, BTRFS_DROP_DELAYED_REF, bytenr, @@ -226,32 +222,32 @@ Signed-off-by: David Sterba + ref.real_root = root->root_key.objectid; + btrfs_init_data_ref(&ref, btrfs_header_owner(leaf), + key.objectid, key.offset); -+ ret = btrfs_free_extent(trans, fs_info, &ref); ++ ret = btrfs_free_extent(trans, root, &ref); if (ret) { btrfs_abort_transaction(trans, ret); break; -@@ -1968,14 +1971,18 @@ again: - ret = btrfs_inc_extent_ref(trans, fs_info, &ref); +@@ -1977,14 +1980,18 @@ again: + ret = btrfs_inc_extent_ref(trans, dest, &ref); BUG_ON(ret); -- ret = btrfs_free_extent(trans, fs_info, new_bytenr, blocksize, +- ret = btrfs_free_extent(trans, src, new_bytenr, blocksize, - path->nodes[level]->start, - src->root_key.objectid, level - 1, 0); + btrfs_init_generic_ref(&ref, BTRFS_DROP_DELAYED_REF, new_bytenr, + blocksize, path->nodes[level]->start); + btrfs_init_tree_ref(&ref, level - 1, src->root_key.objectid); + ref.skip_qgroup = true; -+ ret = btrfs_free_extent(trans, fs_info, &ref); ++ ret = btrfs_free_extent(trans, src, &ref); BUG_ON(ret); -- ret = btrfs_free_extent(trans, fs_info, old_bytenr, blocksize, +- ret = btrfs_free_extent(trans, dest, old_bytenr, blocksize, - 0, dest->root_key.objectid, level - 1, - 0); + btrfs_init_generic_ref(&ref, BTRFS_DROP_DELAYED_REF, old_bytenr, + blocksize, 0); + btrfs_init_tree_ref(&ref, level - 1, dest->root_key.objectid); + ref.skip_qgroup = true; -+ ret = btrfs_free_extent(trans, fs_info, &ref); ++ ret = btrfs_free_extent(trans, dest, &ref); BUG_ON(ret); btrfs_unlock_up_safe(path, 0); diff --git a/patches.suse/0008-btrfs-move-btrfs_space_info_add_-bytes-to-space-info-c.patch b/patches.suse/0008-btrfs-move-btrfs_space_info_add_-bytes-to-space-info-c.patch new file mode 100644 index 0000000..188e1de --- /dev/null +++ b/patches.suse/0008-btrfs-move-btrfs_space_info_add_-bytes-to-space-info-c.patch @@ -0,0 +1,280 @@ +From: Josef Bacik +Date: Tue, 18 Jun 2019 16:09:22 -0400 +Subject: btrfs: move btrfs_space_info_add_*_bytes to space-info.c +Git-commit: b338b013e18a28341aaf9e665ac1edc9fae518d1 +Patch-mainline: v5.3-rc1 +References: bsc#1165949 + +Now that we've moved all the pre-requisite stuff, move these two +functions. + +Reviewed-by: Nikolay Borisov +Signed-off-by: Josef Bacik +Signed-off-by: David Sterba +Acked-by: Nikolay Borisov +--- + fs/btrfs/extent-tree.c | 115 ------------------------------------------------- + fs/btrfs/space-info.c | 105 ++++++++++++++++++++++++++++++++++++++++++++ + fs/btrfs/space-info.h | 9 +++ + 3 files changed, 114 insertions(+), 115 deletions(-) + +--- a/fs/btrfs/extent-tree.c ++++ b/fs/btrfs/extent-tree.c +@@ -4698,15 +4698,6 @@ skip_async: + } + } + +-struct reserve_ticket { +- u64 orig_bytes; +- u64 bytes; +- int error; +- struct list_head list; +- wait_queue_head_t wait; +-}; +- +- + /** + * maybe_commit_transaction - possibly commit the transaction if its ok to + * @root - the root we're allocating for +@@ -5412,112 +5403,6 @@ int btrfs_delayed_refs_rsv_refill(struct + return 0; + } + +-/* +- * This is for space we already have accounted in space_info->bytes_may_use, so +- * basically when we're returning space from block_rsv's. +- */ +-void btrfs_space_info_add_old_bytes(struct btrfs_fs_info *fs_info, +- struct btrfs_space_info *space_info, +- u64 num_bytes) +-{ +- struct reserve_ticket *ticket; +- struct list_head *head; +- u64 used; +- enum btrfs_reserve_flush_enum flush = BTRFS_RESERVE_NO_FLUSH; +- bool check_overcommit = false; +- +- spin_lock(&space_info->lock); +- head = &space_info->priority_tickets; +- +- /* +- * If we are over our limit then we need to check and see if we can +- * overcommit, and if we can't then we just need to free up our space +- * and not satisfy any requests. +- */ +- used = space_info->bytes_used + space_info->bytes_reserved + +- space_info->bytes_pinned + space_info->bytes_readonly + +- space_info->bytes_may_use; +- if (used - num_bytes >= space_info->total_bytes) +- check_overcommit = true; +-again: +- while (!list_empty(head) && num_bytes) { +- ticket = list_first_entry(head, struct reserve_ticket, +- list); +- /* +- * We use 0 bytes because this space is already reserved, so +- * adding the ticket space would be a double count. +- */ +- if (check_overcommit && +- !btrfs_can_overcommit(fs_info->extent_root, space_info, 0, +- flush)) +- break; +- if (num_bytes >= ticket->bytes) { +- list_del_init(&ticket->list); +- num_bytes -= ticket->bytes; +- ticket->bytes = 0; +- space_info->tickets_id++; +- wake_up(&ticket->wait); +- } else { +- ticket->bytes -= num_bytes; +- num_bytes = 0; +- } +- } +- +- if (num_bytes && head == &space_info->priority_tickets) { +- head = &space_info->tickets; +- flush = BTRFS_RESERVE_FLUSH_ALL; +- goto again; +- } +- btrfs_space_info_update_bytes_may_use(fs_info, space_info, -num_bytes); +- trace_btrfs_space_reservation(fs_info, "space_info", +- space_info->flags, num_bytes, 0); +- spin_unlock(&space_info->lock); +-} +- +-/* +- * This is for newly allocated space that isn't accounted in +- * space_info->bytes_may_use yet. So if we allocate a chunk or unpin an extent +- * we use this helper. +- */ +-void btrfs_space_info_add_new_bytes(struct btrfs_fs_info *fs_info, +- struct btrfs_space_info *space_info, +- u64 num_bytes) +-{ +- struct reserve_ticket *ticket; +- struct list_head *head = &space_info->priority_tickets; +- +-again: +- while (!list_empty(head) && num_bytes) { +- ticket = list_first_entry(head, struct reserve_ticket, +- list); +- if (num_bytes >= ticket->bytes) { +- trace_btrfs_space_reservation(fs_info, "space_info", +- space_info->flags, +- ticket->bytes, 1); +- list_del_init(&ticket->list); +- num_bytes -= ticket->bytes; +- btrfs_space_info_update_bytes_may_use(fs_info, +- space_info, ticket->bytes); +- ticket->bytes = 0; +- space_info->tickets_id++; +- wake_up(&ticket->wait); +- } else { +- trace_btrfs_space_reservation(fs_info, "space_info", +- space_info->flags, +- num_bytes, 1); +- btrfs_space_info_update_bytes_may_use(fs_info, +- space_info, num_bytes); +- ticket->bytes -= num_bytes; +- num_bytes = 0; +- } +- } +- +- if (num_bytes && head == &space_info->priority_tickets) { +- head = &space_info->tickets; +- goto 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, +--- a/fs/btrfs/space-info.c ++++ b/fs/btrfs/space-info.c +@@ -239,3 +239,108 @@ int btrfs_can_overcommit(struct btrfs_ro + return 1; + return 0; + } ++ ++/* ++ * This is for space we already have accounted in space_info->bytes_may_use, so ++ * basically when we're returning space from block_rsv's. ++ */ ++void btrfs_space_info_add_old_bytes(struct btrfs_fs_info *fs_info, ++ struct btrfs_space_info *space_info, ++ u64 num_bytes) ++{ ++ struct reserve_ticket *ticket; ++ struct list_head *head; ++ u64 used; ++ enum btrfs_reserve_flush_enum flush = BTRFS_RESERVE_NO_FLUSH; ++ bool check_overcommit = false; ++ ++ spin_lock(&space_info->lock); ++ head = &space_info->priority_tickets; ++ ++ /* ++ * If we are over our limit then we need to check and see if we can ++ * overcommit, and if we can't then we just need to free up our space ++ * and not satisfy any requests. ++ */ ++ used = space_info->bytes_used + space_info->bytes_reserved + ++ space_info->bytes_pinned + space_info->bytes_readonly + ++ space_info->bytes_may_use; ++ if (used - num_bytes >= space_info->total_bytes) ++ check_overcommit = true; ++again: ++ while (!list_empty(head) && num_bytes) { ++ ticket = list_first_entry(head, struct reserve_ticket, ++ list); ++ /* ++ * We use 0 bytes because this space is already reserved, so ++ * adding the ticket space would be a double count. ++ */ ++ if (check_overcommit && ++ !btrfs_can_overcommit(fs_info->extent_root, space_info, 0, ++ flush)) ++ break; ++ if (num_bytes >= ticket->bytes) { ++ list_del_init(&ticket->list); ++ num_bytes -= ticket->bytes; ++ ticket->bytes = 0; ++ space_info->tickets_id++; ++ wake_up(&ticket->wait); ++ } else { ++ ticket->bytes -= num_bytes; ++ num_bytes = 0; ++ } ++ } ++ ++ if (num_bytes && head == &space_info->priority_tickets) { ++ head = &space_info->tickets; ++ flush = BTRFS_RESERVE_FLUSH_ALL; ++ goto again; ++ } ++ btrfs_space_info_update_bytes_may_use(fs_info, space_info, -num_bytes); ++ trace_btrfs_space_reservation(fs_info, "space_info", ++ space_info->flags, num_bytes, 0); ++ spin_unlock(&space_info->lock); ++} ++/* ++ * This is for newly allocated space that isn't accounted in ++ * space_info->bytes_may_use yet. So if we allocate a chunk or unpin an extent ++ * we use this helper. ++ */ ++void btrfs_space_info_add_new_bytes(struct btrfs_fs_info *fs_info, ++ struct btrfs_space_info *space_info, ++ u64 num_bytes) ++{ ++ struct reserve_ticket *ticket; ++ struct list_head *head = &space_info->priority_tickets; ++ ++again: ++ while (!list_empty(head) && num_bytes) { ++ ticket = list_first_entry(head, struct reserve_ticket, ++ list); ++ if (num_bytes >= ticket->bytes) { ++ trace_btrfs_space_reservation(fs_info, "space_info", ++ space_info->flags, ++ ticket->bytes, 1); ++ list_del_init(&ticket->list); ++ num_bytes -= ticket->bytes; ++ btrfs_space_info_update_bytes_may_use(fs_info, ++ space_info, ticket->bytes); ++ ticket->bytes = 0; ++ space_info->tickets_id++; ++ wake_up(&ticket->wait); ++ } else { ++ trace_btrfs_space_reservation(fs_info, "space_info", ++ space_info->flags, ++ num_bytes, 1); ++ btrfs_space_info_update_bytes_may_use(fs_info, ++ space_info, num_bytes); ++ ticket->bytes -= num_bytes; ++ num_bytes = 0; ++ } ++ } ++ ++ if (num_bytes && head == &space_info->priority_tickets) { ++ head = &space_info->tickets; ++ goto again; ++ } ++} +--- a/fs/btrfs/space-info.h ++++ b/fs/btrfs/space-info.h +@@ -68,6 +68,15 @@ struct btrfs_space_info { + struct kobject kobj; + struct kobject *block_group_kobjs[BTRFS_NR_RAID_TYPES]; + }; ++ ++struct reserve_ticket { ++ u64 orig_bytes; ++ u64 bytes; ++ int error; ++ struct list_head list; ++ wait_queue_head_t wait; ++}; ++ + static inline bool btrfs_mixed_space_info(struct btrfs_space_info *space_info) + { + return ((space_info->flags & BTRFS_BLOCK_GROUP_METADATA) && diff --git a/patches.suse/0008-btrfs-reset-max_extent_size-properly.patch b/patches.suse/0008-btrfs-reset-max_extent_size-properly.patch new file mode 100644 index 0000000..9f5dcdc --- /dev/null +++ b/patches.suse/0008-btrfs-reset-max_extent_size-properly.patch @@ -0,0 +1,43 @@ +From: Josef Bacik +Date: Thu, 11 Oct 2018 15:54:03 -0400 +Subject: btrfs: reset max_extent_size properly +Git-commit: 21a94f7acf0f748599ea552af5d9ee7d7e41c72f +Patch-mainline: v4.20-rc1 +References: bsc##1165949 + +If we use up our block group before allocating a new one we'll easily +get a max_extent_size that's set really really low, which will result in +a lot of fragmentation. We need to make sure we're resetting the +max_extent_size when we add a new chunk or add new space. + +CC: stable@vger.kernel.org # 4.4+ +Reviewed-by: Filipe Manana +Signed-off-by: Josef Bacik +Signed-off-by: David Sterba +Acked-by: Nikolay Borisov +--- + fs/btrfs/extent-tree.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +--- a/fs/btrfs/extent-tree.c ++++ b/fs/btrfs/extent-tree.c +@@ -4688,8 +4688,10 @@ again: + goto out; + if (ret) + space_info->full = 1; +- else ++ else { + ret = 1; ++ space_info->max_extent_size = 0; ++ } + + space_info->force_alloc = CHUNK_ALLOC_NO_FORCE; + out: +@@ -6629,6 +6631,7 @@ static int btrfs_free_reserved_bytes(str + space_info->bytes_readonly += num_bytes; + cache->reserved -= num_bytes; + space_info->bytes_reserved -= num_bytes; ++ space_info->max_extent_size = 0; + + if (delalloc) + cache->delalloc_bytes -= num_bytes; diff --git a/patches.suse/0008-btrfs-rework-btrfs_check_space_for_delayed_refs.patch b/patches.suse/0008-btrfs-rework-btrfs_check_space_for_delayed_refs.patch new file mode 100644 index 0000000..8e78bd8 --- /dev/null +++ b/patches.suse/0008-btrfs-rework-btrfs_check_space_for_delayed_refs.patch @@ -0,0 +1,133 @@ +From: Josef Bacik +Date: Mon, 3 Dec 2018 10:20:36 -0500 +Subject: btrfs: rework btrfs_check_space_for_delayed_refs +Git-commit: 64403612b73a94bc7b02cf8ca126e3b8ced6e921 +Patch-mainline: v5.0-rc1 +References: bsc#1165949 + +Now with the delayed_refs_rsv we can now know exactly how much pending +delayed refs space we need. This means we can drastically simplify +btrfs_check_space_for_delayed_refs by simply checking how much space we +have reserved for the global rsv (which acts as a spill over buffer) and +the delayed refs rsv. If our total size is beyond that amount then we +know it's time to commit the transaction and stop any more delayed refs +from being generated. + +With the introduction of dealyed_refs_rsv infrastructure, namely +btrfs_update_delayed_refs_rsv we now know exactly how much pending +delayed refs space is required. + +Reviewed-by: Nikolay Borisov +Signed-off-by: Josef Bacik +Signed-off-by: David Sterba +Acked-by: Nikolay Borisov +--- + fs/btrfs/ctree.h | 3 +-- + fs/btrfs/extent-tree.c | 49 ++++++++++++++++++------------------------------- + fs/btrfs/inode.c | 2 +- + fs/btrfs/transaction.c | 2 +- + 4 files changed, 21 insertions(+), 35 deletions(-) + +--- a/fs/btrfs/ctree.h ++++ b/fs/btrfs/ctree.h +@@ -2650,8 +2650,7 @@ static inline u64 btrfs_calc_trunc_metad + + int btrfs_should_throttle_delayed_refs(struct btrfs_trans_handle *trans, + struct btrfs_fs_info *fs_info); +-int btrfs_check_space_for_delayed_refs(struct btrfs_trans_handle *trans, +- struct btrfs_fs_info *fs_info); ++bool btrfs_check_space_for_delayed_refs(struct btrfs_fs_info *fs_info); + void btrfs_dec_block_group_reservations(struct btrfs_fs_info *fs_info, + const u64 start); + void btrfs_wait_block_group_reservations(struct btrfs_block_group_cache *bg); +--- a/fs/btrfs/extent-tree.c ++++ b/fs/btrfs/extent-tree.c +@@ -2931,40 +2931,27 @@ u64 btrfs_csum_bytes_to_leaves(struct bt + return num_csums; + } + +-int btrfs_check_space_for_delayed_refs(struct btrfs_trans_handle *trans, +- struct btrfs_fs_info *fs_info) ++bool btrfs_check_space_for_delayed_refs(struct btrfs_fs_info *fs_info) + { +- struct btrfs_block_rsv *global_rsv; +- u64 num_heads = trans->transaction->delayed_refs.num_heads_ready; +- u64 csum_bytes = trans->transaction->delayed_refs.pending_csums; +- u64 num_dirty_bgs = trans->transaction->num_dirty_bgs; +- u64 num_bytes, num_dirty_bgs_bytes; +- int ret = 0; +- +- num_bytes = btrfs_calc_trans_metadata_size(fs_info, 1); +- num_heads = heads_to_leaves(fs_info, num_heads); +- if (num_heads > 1) +- num_bytes += (num_heads - 1) * fs_info->nodesize; +- num_bytes <<= 1; +- num_bytes += btrfs_csum_bytes_to_leaves(fs_info, csum_bytes) * +- fs_info->nodesize; +- num_dirty_bgs_bytes = btrfs_calc_trans_metadata_size(fs_info, +- num_dirty_bgs); +- global_rsv = &fs_info->global_block_rsv; +- +- /* +- * If we can't allocate any more chunks lets make sure we have _lots_ of +- * wiggle room since running delayed refs can create more delayed refs. +- */ +- if (global_rsv->space_info->full) { +- num_dirty_bgs_bytes <<= 1; +- num_bytes <<= 1; +- } ++ struct btrfs_block_rsv *delayed_refs_rsv = &fs_info->delayed_refs_rsv; ++ struct btrfs_block_rsv *global_rsv = &fs_info->global_block_rsv; ++ bool ret = false; ++ u64 reserved; + + spin_lock(&global_rsv->lock); +- if (global_rsv->reserved <= num_bytes + num_dirty_bgs_bytes) +- ret = 1; ++ reserved = global_rsv->reserved; + spin_unlock(&global_rsv->lock); ++ /* ++ * Since the global reserve is just kind of magic we don't really want ++ * to rely on it to save our bacon, so if our size is more than the ++ * delayed_refs_rsv and the global rsv then it's time to think about ++ * bailing. ++ */ ++ spin_lock(&delayed_refs_rsv->lock); ++ reserved += delayed_refs_rsv->reserved; ++ if (delayed_refs_rsv->size >= reserved) ++ ret = true; ++ spin_unlock(&delayed_refs_rsv->lock); + return ret; + } + +@@ -2984,7 +2971,7 @@ int btrfs_should_throttle_delayed_refs(s + if (val >= NSEC_PER_SEC / 2) + return 2; + +- return btrfs_check_space_for_delayed_refs(trans, fs_info); ++ return btrfs_check_space_for_delayed_refs(fs_info); + } + + struct async_delayed_refs { +--- a/fs/btrfs/inode.c ++++ b/fs/btrfs/inode.c +@@ -5113,7 +5113,7 @@ static struct btrfs_trans_handle *evict_ + * Try to steal from the global reserve if there is space for + * it. + */ +- if (!btrfs_check_space_for_delayed_refs(trans, fs_info) && ++ if (!btrfs_check_space_for_delayed_refs(fs_info) && + !btrfs_block_rsv_migrate(global_rsv, rsv, rsv->size, 0)) + return trans; + +--- a/fs/btrfs/transaction.c ++++ b/fs/btrfs/transaction.c +@@ -828,7 +828,7 @@ static int should_end_transaction(struct + { + struct btrfs_fs_info *fs_info = trans->fs_info; + +- if (btrfs_check_space_for_delayed_refs(trans, fs_info)) ++ if (btrfs_check_space_for_delayed_refs(fs_info)) + return 1; + + return !!btrfs_block_rsv_check(&fs_info->global_block_rsv, 5); diff --git a/patches.suse/0008-raid5-copy-write-hint-from-origin-bio-to-stripe.patch b/patches.suse/0008-raid5-copy-write-hint-from-origin-bio-to-stripe.patch new file mode 100644 index 0000000..09e06a2 --- /dev/null +++ b/patches.suse/0008-raid5-copy-write-hint-from-origin-bio-to-stripe.patch @@ -0,0 +1,68 @@ +From 2cd259a77de561d49c1ff939a239095749e65ee7 Mon Sep 17 00:00:00 2001 +From: Mariusz Dabrowski +Date: Thu, 19 Apr 2018 19:28:10 +0200 +Subject: [PATCH] raid5: copy write hint from origin bio to stripe +Git-commit: 2cd259a77de561d49c1ff939a239095749e65ee7 +Patch-mainline: v4.18-rc1 +References: bsc#1111974 bsc#1166003 + +Store write hint from original bio in stripe head so it can be assigned +to bio sent to each RAID device. + +Signed-off-by: Mariusz Dabrowski +Reviewed-by: Artur Paszkiewicz +Reviewed-by: Pawel Baldysiak +Signed-off-by: Shaohua Li +Signed-off-by: Coly Li + +--- + drivers/md/raid5.c | 6 ++++++ + drivers/md/raid5.h | 1 + + 2 files changed, 7 insertions(+) + +diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c +index be117d0a65a8..1e1515c817ff 100644 +--- a/drivers/md/raid5.c ++++ b/drivers/md/raid5.c +@@ -1139,6 +1139,9 @@ static void ops_run_io(struct stripe_head *sh, struct stripe_head_state *s) + bi->bi_io_vec[0].bv_len = STRIPE_SIZE; + bi->bi_io_vec[0].bv_offset = 0; + bi->bi_iter.bi_size = STRIPE_SIZE; ++ bi->bi_write_hint = sh->dev[i].write_hint; ++ if (!rrdev) ++ sh->dev[i].write_hint = RWF_WRITE_LIFE_NOT_SET; + /* + * If this is discard request, set bi_vcnt 0. We don't + * want to confuse SCSI because SCSI will replace payload +@@ -1190,6 +1193,8 @@ static void ops_run_io(struct stripe_head *sh, struct stripe_head_state *s) + rbi->bi_io_vec[0].bv_len = STRIPE_SIZE; + rbi->bi_io_vec[0].bv_offset = 0; + rbi->bi_iter.bi_size = STRIPE_SIZE; ++ rbi->bi_write_hint = sh->dev[i].write_hint; ++ sh->dev[i].write_hint = RWF_WRITE_LIFE_NOT_SET; + /* + * If this is discard request, set bi_vcnt 0. We don't + * want to confuse SCSI because SCSI will replace payload +@@ -3204,6 +3209,7 @@ static int add_stripe_bio(struct stripe_head *sh, struct bio *bi, int dd_idx, + (unsigned long long)sh->sector); + + spin_lock_irq(&sh->stripe_lock); ++ sh->dev[dd_idx].write_hint = bi->bi_write_hint; + /* Don't allow new IO added to stripes in batch list */ + if (sh->batch_head) + goto overlap; +diff --git a/drivers/md/raid5.h b/drivers/md/raid5.h +index 3f8da26032ac..aea2447b0ea7 100644 +--- a/drivers/md/raid5.h ++++ b/drivers/md/raid5.h +@@ -257,6 +257,7 @@ struct stripe_head { + sector_t sector; /* sector of this page */ + unsigned long flags; + u32 log_checksum; ++ unsigned short write_hint; + } dev[1]; /* allocated with extra space depending of RAID geometry */ + }; + +-- +2.25.0 + diff --git a/patches.suse/0009-btrfs-don-t-run-delayed-refs-in-the-end-transaction-logic.patch b/patches.suse/0009-btrfs-don-t-run-delayed-refs-in-the-end-transaction-logic.patch new file mode 100644 index 0000000..531d38a --- /dev/null +++ b/patches.suse/0009-btrfs-don-t-run-delayed-refs-in-the-end-transaction-logic.patch @@ -0,0 +1,101 @@ +From: Josef Bacik +Date: Mon, 3 Dec 2018 10:20:37 -0500 +Subject: btrfs: don't run delayed refs in the end transaction logic +Git-commit: db2462a6ad3dc490ac33250042e728226ef3ba00 +Patch-mainline: v5.0-rc1 +References: bsc#1165949 + +Over the years we have built up a lot of infrastructure to keep delayed +refs in check, mostly by running them at btrfs_end_transaction() time. +We have a lot of different maths we do to figure out how much, if we +should do it inline or async, etc. This existed because we had no +feedback mechanism to force the flushing of delayed refs when they +became a problem. However with the enospc flushing infrastructure in +place for flushing delayed refs when they put too much pressure on the +enospc system we have this problem solved. Rip out all of this code as +it is no longer needed. + +Signed-off-by: Josef Bacik +Signed-off-by: David Sterba +Acked-by: Nikolay Borisov +--- + fs/btrfs/transaction.c | 39 --------------------------------------- + 1 file changed, 39 deletions(-) + +--- a/fs/btrfs/transaction.c ++++ b/fs/btrfs/transaction.c +@@ -837,23 +837,12 @@ static int should_end_transaction(struct + int btrfs_should_end_transaction(struct btrfs_trans_handle *trans) + { + struct btrfs_transaction *cur_trans = trans->transaction; +- struct btrfs_fs_info *fs_info = trans->fs_info; +- int updates; +- int err; + + smp_mb(); + if (cur_trans->state >= TRANS_STATE_BLOCKED || + cur_trans->delayed_refs.flushing) + return 1; + +- updates = trans->delayed_ref_updates; +- trans->delayed_ref_updates = 0; +- if (updates) { +- err = btrfs_run_delayed_refs(trans, fs_info, updates * 2); +- if (err) /* Error code will also eval true */ +- return err; +- } +- + return should_end_transaction(trans); + } + +@@ -862,11 +851,8 @@ static int __btrfs_end_transaction(struc + { + struct btrfs_fs_info *info = trans->fs_info; + struct btrfs_transaction *cur_trans = trans->transaction; +- u64 transid = trans->transid; +- unsigned long cur = trans->delayed_ref_updates; + int lock = (trans->type != TRANS_JOIN_NOLOCK); + int err = 0; +- int must_run_delayed_refs = 0; + + if (trans->use_count > 1) { + trans->use_count--; +@@ -880,27 +866,6 @@ static int __btrfs_end_transaction(struc + if (!list_empty(&trans->new_bgs)) + btrfs_create_pending_block_groups(trans, info); + +- trans->delayed_ref_updates = 0; +- if (!trans->sync) { +- must_run_delayed_refs = +- btrfs_should_throttle_delayed_refs(trans, info); +- cur = max_t(unsigned long, cur, 32); +- +- /* +- * don't make the caller wait if they are from a NOLOCK +- * or ATTACH transaction, it will deadlock with commit +- */ +- if (must_run_delayed_refs == 1 && +- (trans->type & (__TRANS_JOIN_NOLOCK | __TRANS_ATTACH))) +- must_run_delayed_refs = 2; +- } +- +- btrfs_trans_release_metadata(trans, info); +- trans->block_rsv = NULL; +- +- if (!list_empty(&trans->new_bgs)) +- btrfs_create_pending_block_groups(trans, info); +- + btrfs_trans_release_chunk_metadata(trans); + + if (lock && !atomic_read(&info->open_ioctl_trans) && +@@ -948,10 +913,6 @@ static int __btrfs_end_transaction(struc + } + + kmem_cache_free(btrfs_trans_handle_cachep, trans); +- if (must_run_delayed_refs) { +- btrfs_async_run_delayed_refs(info, cur, transid, +- must_run_delayed_refs == 1); +- } + return err; + } + diff --git a/patches.suse/0009-btrfs-export-block_rsv_use_bytes.patch b/patches.suse/0009-btrfs-export-block_rsv_use_bytes.patch new file mode 100644 index 0000000..8c06a99 --- /dev/null +++ b/patches.suse/0009-btrfs-export-block_rsv_use_bytes.patch @@ -0,0 +1,86 @@ +From: Josef Bacik +Date: Tue, 18 Jun 2019 16:09:23 -0400 +Subject: btrfs: export block_rsv_use_bytes +Git-commit: c2a67a76ec87579a46a16c49fc9997737b7fa844 +Patch-mainline: v5.3-rc1 +References: bsc#1165949 + +We are going to need this to move the metadata reservation stuff to +space_info.c. + +Reviewed-by: Nikolay Borisov +Signed-off-by: Josef Bacik +Signed-off-by: David Sterba +Acked-by: Nikolay Borisov +--- + fs/btrfs/ctree.h | 1 + + fs/btrfs/extent-tree.c | 13 +++++-------- + 2 files changed, 6 insertions(+), 8 deletions(-) + +--- a/fs/btrfs/ctree.h ++++ b/fs/btrfs/ctree.h +@@ -2838,6 +2838,7 @@ int btrfs_block_rsv_refill(struct btrfs_ + int btrfs_block_rsv_migrate(struct btrfs_block_rsv *src_rsv, + struct btrfs_block_rsv *dst_rsv, u64 num_bytes, + int update_size); ++int btrfs_block_rsv_use_bytes(struct btrfs_block_rsv *block_rsv, u64 num_bytes); + int btrfs_cond_migrate_bytes(struct btrfs_fs_info *fs_info, + struct btrfs_block_rsv *dest, u64 num_bytes, + int min_factor); +--- a/fs/btrfs/extent-tree.c ++++ b/fs/btrfs/extent-tree.c +@@ -75,8 +75,6 @@ static int btrfs_add_reserved_bytes(stru + u64 ram_bytes, u64 num_bytes, int delalloc); + static int btrfs_free_reserved_bytes(struct btrfs_block_group_cache *cache, + u64 num_bytes, int delalloc); +-static int block_rsv_use_bytes(struct btrfs_block_rsv *block_rsv, +- u64 num_bytes); + static int __reserve_metadata_bytes(struct btrfs_root *root, + struct btrfs_space_info *space_info, + u64 orig_bytes, +@@ -5236,7 +5234,7 @@ static int reserve_metadata_bytes(struct + if (ret == -ENOSPC && + unlikely(root->orphan_cleanup_state == ORPHAN_CLEANUP_STARTED)) { + if (block_rsv != global_rsv && +- !block_rsv_use_bytes(global_rsv, orig_bytes)) ++ !btrfs_block_rsv_use_bytes(global_rsv, orig_bytes)) + ret = 0; + } + if (ret == -ENOSPC) { +@@ -5272,8 +5270,7 @@ static struct btrfs_block_rsv *get_block + return block_rsv; + } + +-static int block_rsv_use_bytes(struct btrfs_block_rsv *block_rsv, +- u64 num_bytes) ++int btrfs_block_rsv_use_bytes(struct btrfs_block_rsv *block_rsv, u64 num_bytes) + { + int ret = -ENOSPC; + spin_lock(&block_rsv->lock); +@@ -5470,7 +5467,7 @@ int btrfs_block_rsv_migrate(struct btrfs + { + int ret; + +- ret = block_rsv_use_bytes(src, num_bytes); ++ ret = btrfs_block_rsv_use_bytes(src, num_bytes); + if (ret) + return ret; + +@@ -8251,7 +8248,7 @@ use_block_rsv(struct btrfs_trans_handle + if (unlikely(block_rsv->size == 0)) + goto try_reserve; + again: +- ret = block_rsv_use_bytes(block_rsv, blocksize); ++ ret = btrfs_block_rsv_use_bytes(block_rsv, blocksize); + if (!ret) + return block_rsv; + +@@ -8289,7 +8286,7 @@ try_reserve: + */ + if (block_rsv->type != BTRFS_BLOCK_RSV_GLOBAL && + block_rsv->space_info == global_rsv->space_info) { +- ret = block_rsv_use_bytes(global_rsv, blocksize); ++ ret = btrfs_block_rsv_use_bytes(global_rsv, blocksize); + if (!ret) + return global_rsv; + } diff --git a/patches.suse/0009-btrfs-loop-in-inode_rsv_refill.patch b/patches.suse/0009-btrfs-loop-in-inode_rsv_refill.patch new file mode 100644 index 0000000..4964afd --- /dev/null +++ b/patches.suse/0009-btrfs-loop-in-inode_rsv_refill.patch @@ -0,0 +1,119 @@ +From: Josef Bacik +Date: Wed, 21 Nov 2018 14:03:11 -0500 +Subject: btrfs: loop in inode_rsv_refill +Git-commit: 5df1136363cabc4d3f92fc91e3f92bd6a5eebd27 +Patch-mainline: v5.1-rc1 +References: bsc#1165949 + +With severe fragmentation we can end up with our inode rsv size being +huge during writeout, which would cause us to need to make very large +metadata reservations. + +However we may not actually need that much once writeout is complete, +because of the over-reservation for the worst case. + +So instead try to make our reservation, and if we couldn't make it +re-calculate our new reservation size and try again. If our reservation +size doesn't change between tries then we know we are actually out of +space and can error. Flushing that could have been running in parallel +did not make any space. + +Signed-off-by: Josef Bacik +[ rename to calc_refill_bytes, update comment and changelog ] +Signed-off-by: David Sterba +Acked-by: Nikolay Borisov +--- + fs/btrfs/extent-tree.c | 63 ++++++++++++++++++++++++++++++++++++------------- + 1 file changed, 47 insertions(+), 16 deletions(-) + +--- a/fs/btrfs/extent-tree.c ++++ b/fs/btrfs/extent-tree.c +@@ -5922,6 +5922,21 @@ int btrfs_block_rsv_refill(struct btrfs_ + return ret; + } + ++static void calc_refill_bytes(struct btrfs_block_rsv *block_rsv, ++ u64 *metadata_bytes, u64 *qgroup_bytes) ++{ ++ *metadata_bytes = 0; ++ *qgroup_bytes = 0; ++ ++ spin_lock(&block_rsv->lock); ++ if (block_rsv->reserved < block_rsv->size) ++ *metadata_bytes = block_rsv->size - block_rsv->reserved; ++ if (block_rsv->qgroup_rsv_reserved < block_rsv->qgroup_rsv_size) ++ *qgroup_bytes = block_rsv->qgroup_rsv_size - ++ block_rsv->qgroup_rsv_reserved; ++ spin_unlock(&block_rsv->lock); ++} ++ + /** + * btrfs_inode_rsv_refill - refill the inode block rsv. + * @inode - the inode we are refilling. +@@ -5937,25 +5952,42 @@ 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; ++ u64 num_bytes, last = 0; ++ u64 qgroup_num_bytes; + 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); +- ++ calc_refill_bytes(block_rsv, &num_bytes, &qgroup_num_bytes); + if (num_bytes == 0) + return 0; + +- 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); ++ do { ++ 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); ++ if (ret) { ++ btrfs_qgroup_free_meta_prealloc(root, qgroup_num_bytes); ++ last = num_bytes; ++ /* ++ * If we are fragmented we can end up with a lot of ++ * outstanding extents which will make our size be much ++ * larger than our reserved amount. ++ * ++ * If the reservation happens here, it might be very ++ * big though not needed in the end, if the delalloc ++ * flushing happens. ++ * ++ * If this is the case try and do the reserve again. ++ */ ++ if (flush == BTRFS_RESERVE_FLUSH_ALL) ++ calc_refill_bytes(block_rsv, &num_bytes, ++ &qgroup_num_bytes); ++ if (num_bytes == 0) ++ return 0; ++ } ++ } while (ret && last != num_bytes); ++ + if (!ret) { + block_rsv_add_bytes(block_rsv, num_bytes, 0); + trace_btrfs_space_reservation(root->fs_info, "delalloc", +@@ -5965,8 +5997,7 @@ int btrfs_inode_rsv_refill(struct btrfs_ + 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; + } + diff --git a/patches.suse/0009-btrfs-roll-tracepoint-into-btrfs_space_info_update-helper.patch b/patches.suse/0009-btrfs-roll-tracepoint-into-btrfs_space_info_update-helper.patch new file mode 100644 index 0000000..8dacb82 --- /dev/null +++ b/patches.suse/0009-btrfs-roll-tracepoint-into-btrfs_space_info_update-helper.patch @@ -0,0 +1,170 @@ +From: Josef Bacik +Date: Thu, 22 Aug 2019 15:10:55 -0400 +Subject: btrfs: roll tracepoint into btrfs_space_info_update helper +Git-commit: f3e75e3805e1da4f7812f731b5396430fa3f2a08 +Patch-mainline: v5.4-rc1 +References: bsc#1165949 + +We duplicate this tracepoint everywhere we call these helpers, so update +the helper to have the tracepoint as well. + +Signed-off-by: Josef Bacik +Reviewed-by: David Sterba +Signed-off-by: David Sterba +Acked-by: Nikolay Borisov +--- + fs/btrfs/block-group.c | 3 --- + fs/btrfs/block-rsv.c | 5 ----- + fs/btrfs/delalloc-space.c | 4 ---- + fs/btrfs/extent-tree.c | 7 ------- + fs/btrfs/space-info.c | 10 ---------- + fs/btrfs/space-info.h | 10 +++++++--- + 6 files changed, 7 insertions(+), 32 deletions(-) + +--- a/fs/btrfs/block-group.c ++++ b/fs/btrfs/block-group.c +@@ -2712,9 +2712,6 @@ int btrfs_update_block_group(struct btrf + spin_unlock(&cache->lock); + spin_unlock(&cache->space_info->lock); + +- trace_btrfs_space_reservation(info, "pinned", +- cache->space_info->flags, +- num_bytes, 1); + percpu_counter_add(&cache->space_info->total_bytes_pinned, + num_bytes); + set_extent_dirty(info->pinned_extents, +--- a/fs/btrfs/block-rsv.c ++++ b/fs/btrfs/block-rsv.c +@@ -283,16 +283,11 @@ void btrfs_update_global_block_rsv(struc + block_rsv->reserved += num_bytes; + btrfs_space_info_update_bytes_may_use(fs_info, sinfo, + num_bytes); +- trace_btrfs_space_reservation(fs_info, "space_info", +- sinfo->flags, num_bytes, +- 1); + } + } else if (block_rsv->reserved > block_rsv->size) { + num_bytes = block_rsv->reserved - block_rsv->size; + btrfs_space_info_update_bytes_may_use(fs_info, sinfo, + -num_bytes); +- trace_btrfs_space_reservation(fs_info, "space_info", +- sinfo->flags, num_bytes, 0); + block_rsv->reserved = block_rsv->size; + } + +--- a/fs/btrfs/delalloc-space.c ++++ b/fs/btrfs/delalloc-space.c +@@ -129,8 +129,6 @@ commit_trans: + return -ENOSPC; + } + btrfs_space_info_update_bytes_may_use(fs_info, data_sinfo, bytes); +- trace_btrfs_space_reservation(fs_info, "space_info", +- data_sinfo->flags, bytes, 1); + spin_unlock(&data_sinfo->lock); + + return ret; +@@ -182,8 +180,6 @@ void btrfs_free_reserved_data_space_noqu + data_sinfo = fs_info->data_sinfo; + spin_lock(&data_sinfo->lock); + btrfs_space_info_update_bytes_may_use(fs_info, data_sinfo, -len); +- trace_btrfs_space_reservation(fs_info, "space_info", +- data_sinfo->flags, len, 0); + spin_unlock(&data_sinfo->lock); + } + +--- a/fs/btrfs/extent-tree.c ++++ b/fs/btrfs/extent-tree.c +@@ -3051,9 +3051,6 @@ static int unpin_extent_range(struct btr + spin_lock(&cache->lock); + cache->pinned -= len; + btrfs_space_info_update_bytes_pinned(fs_info, space_info, -len); +- +- trace_btrfs_space_reservation(fs_info, "pinned", +- space_info->flags, len, 0); + space_info->max_extent_size = 0; + percpu_counter_add(&space_info->total_bytes_pinned, -len); + if (cache->ro) { +@@ -3074,10 +3071,6 @@ static int unpin_extent_range(struct btr + space_info, to_add); + if (global_rsv->reserved >= global_rsv->size) + global_rsv->full = 1; +- trace_btrfs_space_reservation(fs_info, +- "space_info", +- space_info->flags, +- to_add, 1); + len -= to_add; + } + spin_unlock(&global_rsv->lock); +--- a/fs/btrfs/space-info.c ++++ b/fs/btrfs/space-info.c +@@ -306,8 +306,6 @@ again: + goto again; + } + btrfs_space_info_update_bytes_may_use(fs_info, space_info, -num_bytes); +- trace_btrfs_space_reservation(fs_info, "space_info", +- space_info->flags, num_bytes, 0); + spin_unlock(&space_info->lock); + } + /* +@@ -327,9 +325,6 @@ again: + ticket = list_first_entry(head, struct reserve_ticket, + list); + if (num_bytes >= ticket->bytes) { +- trace_btrfs_space_reservation(fs_info, "space_info", +- space_info->flags, +- ticket->bytes, 1); + list_del_init(&ticket->list); + num_bytes -= ticket->bytes; + btrfs_space_info_update_bytes_may_use(fs_info, +@@ -338,9 +333,6 @@ again: + space_info->tickets_id++; + wake_up(&ticket->wait); + } else { +- trace_btrfs_space_reservation(fs_info, "space_info", +- space_info->flags, +- num_bytes, 1); + btrfs_space_info_update_bytes_may_use(fs_info, + space_info, num_bytes); + ticket->bytes -= num_bytes; +@@ -1029,8 +1021,6 @@ static int __reserve_metadata_bytes(stru + can_overcommit(root, space_info, orig_bytes, flush))) { + btrfs_space_info_update_bytes_may_use(fs_info, space_info, + orig_bytes); +- trace_btrfs_space_reservation(fs_info, "space_info", +- space_info->flags, orig_bytes, 1); + ret = 0; + } + /* +--- a/fs/btrfs/space-info.h ++++ b/fs/btrfs/space-info.h +@@ -87,14 +87,18 @@ static inline bool btrfs_mixed_space_inf + * + * Declare a helper function to detect underflow of various space info members + */ +-#define DECLARE_SPACE_INFO_UPDATE(name) \ ++#define DECLARE_SPACE_INFO_UPDATE(name, trace_name) \ + static inline void \ + btrfs_space_info_update_##name(struct btrfs_fs_info *fs_info, \ + struct btrfs_space_info *sinfo, \ + s64 bytes) \ + { \ ++ const u64 abs_bytes = (bytes < 0) ? -bytes : bytes; \ + lockdep_assert_held(&sinfo->lock); \ + trace_update_##name(fs_info, sinfo, sinfo->name, bytes); \ ++ trace_btrfs_space_reservation(fs_info, trace_name, \ ++ sinfo->flags, abs_bytes, \ ++ bytes > 0); \ + if (bytes < 0 && sinfo->name < -bytes) { \ + WARN_ON(1); \ + sinfo->name = 0; \ +@@ -103,8 +107,8 @@ btrfs_space_info_update_##name(struct bt + sinfo->name += bytes; \ + } + +-DECLARE_SPACE_INFO_UPDATE(bytes_may_use); +-DECLARE_SPACE_INFO_UPDATE(bytes_pinned); ++DECLARE_SPACE_INFO_UPDATE(bytes_may_use, "space_info"); ++DECLARE_SPACE_INFO_UPDATE(bytes_pinned, "pinned"); + + void btrfs_space_info_add_new_bytes(struct btrfs_fs_info *fs_info, + struct btrfs_space_info *space_info, diff --git a/patches.suse/0009-btrfs-set-max_extent_size-properly.patch b/patches.suse/0009-btrfs-set-max_extent_size-properly.patch new file mode 100644 index 0000000..0aaf9e8 --- /dev/null +++ b/patches.suse/0009-btrfs-set-max_extent_size-properly.patch @@ -0,0 +1,97 @@ +From: Josef Bacik +Date: Fri, 12 Oct 2018 15:32:33 -0400 +Subject: btrfs: set max_extent_size properly +Git-commit: ad22cf6ea47fa20fbe11ac324a0a15c0a9a4a2a9 +Patch-mainline: v4.20-rc1 +References: bsc##1165949 + +We can't use entry->bytes if our entry is a bitmap entry, we need to use +entry->max_extent_size in that case. Fix up all the logic to make this +consistent. + +CC: stable@vger.kernel.org # 4.4+ +Signed-off-by: Josef Bacik +Reviewed-by: David Sterba +Signed-off-by: David Sterba +Acked-by: Nikolay Borisov +--- + fs/btrfs/free-space-cache.c | 30 ++++++++++++++++++++---------- + 1 file changed, 20 insertions(+), 10 deletions(-) + +diff --git a/fs/btrfs/free-space-cache.c b/fs/btrfs/free-space-cache.c +index 67441219d6c9..7f90c2bf9d5f 100644 +--- a/fs/btrfs/free-space-cache.c ++++ b/fs/btrfs/free-space-cache.c +@@ -1772,6 +1772,13 @@ static int search_bitmap(struct btrfs_free_space_ctl *ctl, + return -1; + } + ++static inline u64 get_max_extent_size(struct btrfs_free_space *entry) ++{ ++ if (entry->bitmap) ++ return entry->max_extent_size; ++ return entry->bytes; ++} ++ + /* Cache the size of the max extent in bytes */ + static struct btrfs_free_space * + find_free_space(struct btrfs_free_space_ctl *ctl, u64 *offset, u64 *bytes, +@@ -1793,8 +1800,8 @@ find_free_space(struct btrfs_free_space_ctl *ctl, u64 *offset, u64 *bytes, + for (node = &entry->offset_index; node; node = rb_next(node)) { + entry = rb_entry(node, struct btrfs_free_space, offset_index); + if (entry->bytes < *bytes) { +- if (entry->bytes > *max_extent_size) +- *max_extent_size = entry->bytes; ++ *max_extent_size = max(get_max_extent_size(entry), ++ *max_extent_size); + continue; + } + +@@ -1812,8 +1819,8 @@ find_free_space(struct btrfs_free_space_ctl *ctl, u64 *offset, u64 *bytes, + } + + if (entry->bytes < *bytes + align_off) { +- if (entry->bytes > *max_extent_size) +- *max_extent_size = entry->bytes; ++ *max_extent_size = max(get_max_extent_size(entry), ++ *max_extent_size); + continue; + } + +@@ -1825,8 +1832,10 @@ find_free_space(struct btrfs_free_space_ctl *ctl, u64 *offset, u64 *bytes, + *offset = tmp; + *bytes = size; + return entry; +- } else if (size > *max_extent_size) { +- *max_extent_size = size; ++ } else { ++ *max_extent_size = ++ max(get_max_extent_size(entry), ++ *max_extent_size); + } + continue; + } +@@ -2685,8 +2694,8 @@ static u64 btrfs_alloc_from_bitmap(struct btrfs_block_group_cache *block_group, + + err = search_bitmap(ctl, entry, &search_start, &search_bytes, true); + if (err) { +- if (search_bytes > *max_extent_size) +- *max_extent_size = search_bytes; ++ *max_extent_size = max(get_max_extent_size(entry), ++ *max_extent_size); + return 0; + } + +@@ -2723,8 +2732,9 @@ u64 btrfs_alloc_from_cluster(struct btrfs_block_group_cache *block_group, + + entry = rb_entry(node, struct btrfs_free_space, offset_index); + while (1) { +- if (entry->bytes < bytes && entry->bytes > *max_extent_size) +- *max_extent_size = entry->bytes; ++ if (entry->bytes < bytes) ++ *max_extent_size = max(get_max_extent_size(entry), ++ *max_extent_size); + + if (entry->bytes < bytes || + (!entry->bitmap && entry->offset < min_start)) { + diff --git a/patches.suse/0009-btrfs-temporarily-export-fragment_free_space.patch b/patches.suse/0009-btrfs-temporarily-export-fragment_free_space.patch new file mode 100644 index 0000000..cf7784e --- /dev/null +++ b/patches.suse/0009-btrfs-temporarily-export-fragment_free_space.patch @@ -0,0 +1,72 @@ +From: Josef Bacik +Date: Thu, 20 Jun 2019 15:37:51 -0400 +Subject: btrfs: temporarily export fragment_free_space +Git-commit: caa4efafcf037d3881436f2b7ad818cdacebb8a1 +Patch-mainline: v5.4-rc1 +References: bsc#1165949 + +This is used in caching and reading block groups, so export it while we +move these chunks independently. + +Signed-off-by: Josef Bacik +Reviewed-by: David Sterba +Signed-off-by: David Sterba +Acked-by: Nikolay Borisov +--- + fs/btrfs/block-group.h | 1 + + fs/btrfs/extent-tree.c | 8 ++++---- + 2 files changed, 5 insertions(+), 4 deletions(-) + +diff --git a/fs/btrfs/block-group.h b/fs/btrfs/block-group.h +index 3f8b6ffefb8a..ef101fd52158 100644 +--- a/fs/btrfs/block-group.h ++++ b/fs/btrfs/block-group.h +@@ -149,6 +149,7 @@ static inline int btrfs_should_fragment_free_space( + (btrfs_test_opt(fs_info, FRAGMENT_DATA) && + block_group->flags & BTRFS_BLOCK_GROUP_DATA); + } ++void btrfs_fragment_free_space(struct btrfs_block_group_cache *block_group); + #endif + + struct btrfs_block_group_cache *btrfs_lookup_first_block_group( +diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c +index dab8e90237cd..6cae152a4812 100644 +--- a/fs/btrfs/extent-tree.c ++++ b/fs/btrfs/extent-tree.c +@@ -206,7 +206,7 @@ void btrfs_put_caching_control(struct btrfs_caching_control *ctl) + } + + #ifdef CONFIG_BTRFS_DEBUG +-static void fragment_free_space(struct btrfs_block_group_cache *block_group) ++void btrfs_fragment_free_space(struct btrfs_block_group_cache *block_group) + { + struct btrfs_fs_info *fs_info = block_group->fs_info; + u64 start = block_group->key.objectid; +@@ -443,7 +443,7 @@ static noinline void caching_thread(struct btrfs_work *work) + block_group->space_info->bytes_used += bytes_used >> 1; + spin_unlock(&block_group->lock); + spin_unlock(&block_group->space_info->lock); +- fragment_free_space(block_group); ++ btrfs_fragment_free_space(block_group); + } + #endif + +@@ -550,7 +550,7 @@ int btrfs_cache_block_group(struct btrfs_block_group_cache *cache, + cache->space_info->bytes_used += bytes_used >> 1; + spin_unlock(&cache->lock); + spin_unlock(&cache->space_info->lock); +- fragment_free_space(cache); ++ btrfs_fragment_free_space(cache); + } + #endif + mutex_unlock(&caching_ctl->mutex); +@@ -7968,7 +7968,7 @@ int btrfs_make_block_group(struct btrfs_trans_handle *trans, u64 bytes_used, + u64 new_bytes_used = size - bytes_used; + + bytes_used += new_bytes_used >> 1; +- fragment_free_space(cache); ++ btrfs_fragment_free_space(cache); + } + #endif + /* + diff --git a/patches.suse/0009-md-raid5-Assigning-NULL-to-sh-batch_head-before-test.patch b/patches.suse/0009-md-raid5-Assigning-NULL-to-sh-batch_head-before-test.patch new file mode 100644 index 0000000..07703d1 --- /dev/null +++ b/patches.suse/0009-md-raid5-Assigning-NULL-to-sh-batch_head-before-test.patch @@ -0,0 +1,54 @@ +From 448ec638c6bcf36923db695b6188373b933e7ddc Mon Sep 17 00:00:00 2001 +From: Amy Chiang +Date: Wed, 16 May 2018 18:59:35 +0800 +Subject: [PATCH] md/raid5: Assigning NULL to sh->batch_head before testing bit + R5_Overlap of a stripe +Git-commit: 448ec638c6bcf36923db695b6188373b933e7ddc +Patch-mainline: v4.18-rc1 +References: bsc#1111974 bsc#1166003 + +In add_stripe_bio(), if the stripe_head is in batch list, the incoming +bio is regarded as overlapping, and the bit R5_Overlap on this stripe_head +is set. break_stripe_batch_list() checks bit R5_Overlap on each stripe_head +first then assigns NULL to sh->batch_head. + +If break_stripe_batch_list() checks bit R5_Overlap on stripe_head A +after add_stripe_bio() finds stripe_head A is in batch list and before +add_stripe_bio() sets bit R5_Overlapt of stripe_head A, +break_stripe_batch_list() would not know there's a process in +wait_for_overlap and needs to call wake_up(). There's a huge chance a +process never returns from schedule() if add_stripe_bio() is called +from raid5_make_request(). + +In break_stripe_batch_list(), assigning NULL to sh->batch_head should +be done before it checks bit R5_Overlap of a stripe_head. + +Signed-off-by: Amy Chiang +Signed-off-by: Shaohua Li +Signed-off-by: Coly Li + +--- + drivers/md/raid5.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +--- a/drivers/md/raid5.c ++++ b/drivers/md/raid5.c +@@ -4620,15 +4620,15 @@ static void break_stripe_batch_list(struct stripe_head *head_sh, + + sh->check_state = head_sh->check_state; + sh->reconstruct_state = head_sh->reconstruct_state; ++ spin_lock_irq(&sh->stripe_lock); ++ sh->batch_head = NULL; ++ spin_unlock_irq(&sh->stripe_lock); + for (i = 0; i < sh->disks; i++) { + if (test_and_clear_bit(R5_Overlap, &sh->dev[i].flags)) + do_wakeup = 1; + sh->dev[i].flags = head_sh->dev[i].flags & + (~((1 << R5_WriteError) | (1 << R5_Overlap))); + } +- spin_lock_irq(&sh->stripe_lock); +- sh->batch_head = NULL; +- spin_unlock_irq(&sh->stripe_lock); + if (handle_flags == 0 || + sh->state & handle_flags) + set_bit(STRIPE_HANDLE, &sh->state); diff --git a/patches.suse/0010-atomic-Add-irqsave-variant-of-atomic_dec_and_lock.patch b/patches.suse/0010-atomic-Add-irqsave-variant-of-atomic_dec_and_lock.patch new file mode 100644 index 0000000..eecede1 --- /dev/null +++ b/patches.suse/0010-atomic-Add-irqsave-variant-of-atomic_dec_and_lock.patch @@ -0,0 +1,63 @@ +From ccfbb5bed407053b27492a9adc06064d949a9aa6 Mon Sep 17 00:00:00 2001 +From: Anna-Maria Gleixner +Date: Tue, 12 Jun 2018 18:16:20 +0200 +Subject: [PATCH] atomic: Add irqsave variant of atomic_dec_and_lock() +Git-commit: ccfbb5bed407053b27492a9adc06064d949a9aa6 +Patch-mainline: v4.18-rc2 +References: bsc#1111974 bsc#1166003 + +There are in-tree users of atomic_dec_and_lock() which must acquire the +spin lock with interrupts disabled. To workaround the lack of an irqsave +variant of atomic_dec_and_lock() they use local_irq_save() at the call +site. This causes extra code and creates in some places unneeded long +interrupt disabled times. These places need also extra treatment for +PREEMPT_RT due to the disconnect of the irq disabling and the lock +function. + +Implement the missing irqsave variant of the function. + +Signed-off-by: Anna-Maria Gleixner +Signed-off-by: Sebastian Andrzej Siewior +Signed-off-by: Thomas Gleixner +Acked-by: Peter Zijlstra (Intel) +Link: https://lkml.kernel.org/r20180612161621.22645-3-bigeasy@linutronix.de +Acked-by: Coly Li +--- + include/linux/spinlock.h | 5 +++++ + lib/dec_and_lock.c | 16 ++++++++++++++++ + 2 files changed, 21 insertions(+) + +--- a/include/linux/spinlock.h ++++ b/include/linux/spinlock.h +@@ -408,4 +408,9 @@ extern int _atomic_dec_and_lock(atomic_t + #define atomic_dec_and_lock(atomic, lock) \ + __cond_lock(lock, _atomic_dec_and_lock(atomic, lock)) + ++extern int _atomic_dec_and_lock_irqsave(atomic_t *atomic, spinlock_t *lock, ++ unsigned long *flags); ++#define atomic_dec_and_lock_irqsave(atomic, lock, flags) \ ++ __cond_lock(lock, _atomic_dec_and_lock_irqsave(atomic, lock, &(flags))) ++ + #endif /* __LINUX_SPINLOCK_H */ +--- a/lib/dec_and_lock.c ++++ b/lib/dec_and_lock.c +@@ -32,3 +32,19 @@ int _atomic_dec_and_lock(atomic_t *atomi + } + + EXPORT_SYMBOL(_atomic_dec_and_lock); ++ ++int _atomic_dec_and_lock_irqsave(atomic_t *atomic, spinlock_t *lock, ++ unsigned long *flags) ++{ ++ /* Subtract 1 from counter unless that drops it to 0 (ie. it was 1) */ ++ if (atomic_add_unless(atomic, -1, 1)) ++ return 0; ++ ++ /* Otherwise do it the slow way */ ++ spin_lock_irqsave(lock, *flags); ++ if (atomic_dec_and_test(atomic)) ++ return 1; ++ spin_unlock_irqrestore(lock, *flags); ++ return 0; ++} ++EXPORT_SYMBOL(_atomic_dec_and_lock_irqsave); diff --git a/patches.suse/0010-btrfs-add-space-reservation-tracepoint-for-reserved-bytes.patch b/patches.suse/0010-btrfs-add-space-reservation-tracepoint-for-reserved-bytes.patch new file mode 100644 index 0000000..47f6b5c --- /dev/null +++ b/patches.suse/0010-btrfs-add-space-reservation-tracepoint-for-reserved-bytes.patch @@ -0,0 +1,35 @@ +From: Josef Bacik +Date: Thu, 22 Aug 2019 15:10:56 -0400 +Subject: btrfs: add space reservation tracepoint for reserved bytes +Git-commit: a43c383574d80503f3ba9cd08de16dad2590ca1b +Patch-mainline: v5.4-rc1 +References: bsc#1165949 + +I noticed when folding the trace_btrfs_space_reservation() tracepoint +into the btrfs_space_info_update_* helpers that we didn't emit a +tracepoint when doing btrfs_add_reserved_bytes(). I know this is +because we were swapping bytes_may_use for bytes_reserved, so in my mind +there was no reason to have the tracepoint there. But now there is +because we always emit the unreserve for the bytes_may_use side, and +this would have broken if compression was on anyway. Add a tracepoint +to cover the bytes_reserved counter so the math still comes out right. + +Signed-off-by: Josef Bacik +Reviewed-by: David Sterba +Signed-off-by: David Sterba +Acked-by: Nikolay Borisov +--- + fs/btrfs/block-group.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/fs/btrfs/block-group.c ++++ b/fs/btrfs/block-group.c +@@ -2782,7 +2782,7 @@ int btrfs_add_reserved_bytes(struct btrf + space_info->bytes_reserved += num_bytes; + trace_btrfs_space_reservation(cache->fs_info, + "space_info", space_info->flags, +- ram_bytes, 0); ++ ram_bytes, 1); + btrfs_space_info_update_bytes_may_use(cache->fs_info, + space_info, -ram_bytes); + if (delalloc) diff --git a/patches.suse/0010-btrfs-be-more-explicit-about-allowed-flush-states.patch b/patches.suse/0010-btrfs-be-more-explicit-about-allowed-flush-states.patch new file mode 100644 index 0000000..4272f3b --- /dev/null +++ b/patches.suse/0010-btrfs-be-more-explicit-about-allowed-flush-states.patch @@ -0,0 +1,75 @@ +From: Josef Bacik +Date: Wed, 21 Nov 2018 14:03:12 -0500 +Subject: btrfs: be more explicit about allowed flush states +Git-commit: 8a1bbe1d5cba415c771fe5ff68b83b93701c1d7f +Patch-mainline: v5.1-rc1 +References: bsc#1165949 + +For FLUSH_LIMIT flushers we really can only allocate chunks and flush +delayed inode items, everything else is problematic. I added a bunch of +new states and it lead to weirdness in the FLUSH_LIMIT case because I +forgot about how it worked. So instead explicitly declare the states +that are ok for flushing with FLUSH_LIMIT and use that for our state +machine. Then as we add new things that are safe we can just add them +to this list. + +Reviewed-by: Nikolay Borisov +Signed-off-by: Josef Bacik +Reviewed-by: David Sterba +Signed-off-by: David Sterba +Acked-by: Nikolay Borisov +--- + fs/btrfs/extent-tree.c | 22 +++++++++++----------- + 1 file changed, 11 insertions(+), 11 deletions(-) + +--- a/fs/btrfs/extent-tree.c ++++ b/fs/btrfs/extent-tree.c +@@ -5248,12 +5248,18 @@ void btrfs_init_async_reclaim_work(struc + INIT_WORK(work, btrfs_async_reclaim_metadata_space); + } + ++static const enum btrfs_flush_state priority_flush_states[] = { ++ FLUSH_DELAYED_ITEMS_NR, ++ FLUSH_DELAYED_ITEMS, ++ ALLOC_CHUNK, ++}; ++ + static void priority_reclaim_metadata_space(struct btrfs_fs_info *fs_info, + struct btrfs_space_info *space_info, + struct reserve_ticket *ticket) + { + u64 to_reclaim; +- int flush_state = FLUSH_DELAYED_ITEMS_NR; ++ int flush_state; + + spin_lock(&space_info->lock); + to_reclaim = btrfs_calc_reclaim_metadata_size(fs_info->extent_root, +@@ -5264,8 +5270,10 @@ static void priority_reclaim_metadata_sp + } + spin_unlock(&space_info->lock); + ++ flush_state = 0; + do { +- flush_space(fs_info, space_info, to_reclaim, flush_state); ++ flush_space(fs_info, space_info, to_reclaim, ++ priority_flush_states[flush_state]); + flush_state++; + spin_lock(&space_info->lock); + if (ticket->bytes == 0) { +@@ -5273,15 +5281,7 @@ static void priority_reclaim_metadata_sp + return; + } + spin_unlock(&space_info->lock); +- +- /* +- * Priority flushers can't wait on delalloc without +- * deadlocking. +- */ +- if (flush_state == FLUSH_DELALLOC || +- flush_state == FLUSH_DELALLOC_WAIT) +- flush_state = ALLOC_CHUNK; +- } while (flush_state < COMMIT_TRANS); ++ } while (flush_state < ARRAY_SIZE(priority_flush_states)); + } + + static int wait_reserve_ticket(struct btrfs_fs_info *fs_info, diff --git a/patches.suse/0010-btrfs-don-t-use-ctl-free_space-for-max_extent_size.patch b/patches.suse/0010-btrfs-don-t-use-ctl-free_space-for-max_extent_size.patch new file mode 100644 index 0000000..4b2b5c4 --- /dev/null +++ b/patches.suse/0010-btrfs-don-t-use-ctl-free_space-for-max_extent_size.patch @@ -0,0 +1,56 @@ +From: Josef Bacik +Date: Thu, 11 Oct 2018 15:54:09 -0400 +Subject: btrfs: don't use ctl->free_space for max_extent_size +Git-commit: fb5c39d7a887108087de6ff93d3f326b01b4ef41 +Patch-mainline: v4.20-rc1 +References: bsc##1165949 + +max_extent_size is supposed to be the largest contiguous range for the +space info, and ctl->free_space is the total free space in the block +group. We need to keep track of these separately and _only_ use the +max_free_space if we don't have a max_extent_size, as that means our +original request was too large to search any of the block groups for and +therefore wouldn't have a max_extent_size set. + +CC: stable@vger.kernel.org # 4.14+ +Reviewed-by: Filipe Manana +Signed-off-by: Josef Bacik +Signed-off-by: David Sterba +Acked-by: Nikolay Borisov +--- + fs/btrfs/extent-tree.c | 7 +++++-- + 1 file changed, 5 insertions(+), 2 deletions(-) + +diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c +index 87d6666cd8e3..85d1ceb90273 100644 +--- a/fs/btrfs/extent-tree.c ++++ b/fs/btrfs/extent-tree.c +@@ -7257,6 +7257,7 @@ static noinline int find_free_extent(struct btrfs_fs_info *fs_info, + struct btrfs_block_group_cache *block_group = NULL; + u64 search_start = 0; + u64 max_extent_size = 0; ++ u64 max_free_space = 0; + u64 empty_cluster = 0; + struct btrfs_space_info *space_info; + int loop = 0; +@@ -7552,8 +7553,8 @@ static noinline int find_free_extent(struct btrfs_fs_info *fs_info, + spin_lock(&ctl->tree_lock); + if (ctl->free_space < + num_bytes + empty_cluster + empty_size) { +- if (ctl->free_space > max_extent_size) +- max_extent_size = ctl->free_space; ++ max_free_space = max(max_free_space, ++ ctl->free_space); + spin_unlock(&ctl->tree_lock); + goto loop; + } +@@ -7720,6 +7721,8 @@ static noinline int find_free_extent(struct btrfs_fs_info *fs_info, + } + out: + if (ret == -ENOSPC) { ++ if (!max_extent_size) ++ max_extent_size = max_free_space; + spin_lock(&space_info->lock); + space_info->max_extent_size = max_extent_size; + spin_unlock(&space_info->lock); + diff --git a/patches.suse/0010-btrfs-fix-truncate-throttling.patch b/patches.suse/0010-btrfs-fix-truncate-throttling.patch new file mode 100644 index 0000000..4b21574 --- /dev/null +++ b/patches.suse/0010-btrfs-fix-truncate-throttling.patch @@ -0,0 +1,145 @@ +From: Josef Bacik +Date: Mon, 3 Dec 2018 10:20:38 -0500 +Subject: btrfs: fix truncate throttling +Git-commit: 28bad2125767c51a2974c234470981b39d3623ab +Patch-mainline: v5.0-rc1 +References: bsc#1165949 + +We have a bunch of magic to make sure we're throttling delayed refs when +truncating a file. Now that we have a delayed refs rsv and a mechanism +for refilling that reserve simply use that instead of all of this magic. + +Reviewed-by: Nikolay Borisov +Signed-off-by: Josef Bacik +Signed-off-by: David Sterba +Acked-by: Nikolay Borisov +--- + fs/btrfs/inode.c | 79 +++++++++++-------------------------------------------- + 1 file changed, 16 insertions(+), 63 deletions(-) + +--- a/fs/btrfs/inode.c ++++ b/fs/btrfs/inode.c +@@ -4218,31 +4218,6 @@ out: + return err; + } + +-static int truncate_space_check(struct btrfs_trans_handle *trans, +- struct btrfs_root *root, +- u64 bytes_deleted) +-{ +- struct btrfs_fs_info *fs_info = root->fs_info; +- int ret; +- +- /* +- * This is only used to apply pressure to the enospc system, we don't +- * intend to use this reservation at all. +- */ +- bytes_deleted = btrfs_csum_bytes_to_leaves(fs_info, bytes_deleted); +- bytes_deleted *= fs_info->nodesize; +- ret = btrfs_block_rsv_add(root, &fs_info->trans_block_rsv, +- bytes_deleted, BTRFS_RESERVE_NO_FLUSH); +- if (!ret) { +- trace_btrfs_space_reservation(fs_info, "transaction", +- trans->transid, +- bytes_deleted, 1); +- trans->bytes_reserved += bytes_deleted; +- } +- return ret; +- +-} +- + /* + * Return this if we need to call truncate_block for the last bit of the + * truncate. +@@ -4287,7 +4262,6 @@ int btrfs_truncate_inode_items(struct bt + u64 bytes_deleted = 0; + bool be_nice = 0; + bool should_throttle = 0; +- bool should_end = 0; + + BUG_ON(new_size > 0 && min_type != BTRFS_EXTENT_DATA_KEY); + +@@ -4500,15 +4474,7 @@ delete: + btrfs_abort_transaction(trans, ret); + break; + } +- if (btrfs_should_throttle_delayed_refs(trans, fs_info)) +- btrfs_async_run_delayed_refs(fs_info, +- trans->delayed_ref_updates * 2, +- trans->transid, 0); + if (be_nice) { +- if (truncate_space_check(trans, root, +- extent_num_bytes)) { +- should_end = 1; +- } + if (btrfs_should_throttle_delayed_refs(trans, + fs_info)) + should_throttle = 1; +@@ -4520,7 +4486,7 @@ delete: + + if (path->slots[0] == 0 || + path->slots[0] != pending_del_slot || +- should_throttle || should_end) { ++ should_throttle) { + if (pending_del_nr) { + ret = btrfs_del_items(trans, root, path, + pending_del_slot, +@@ -4532,24 +4498,23 @@ delete: + pending_del_nr = 0; + } + btrfs_release_path(path); +- if (should_throttle) { +- unsigned long updates = trans->delayed_ref_updates; +- if (updates) { +- trans->delayed_ref_updates = 0; +- ret = btrfs_run_delayed_refs(trans, +- fs_info, +- updates * 2); +- if (ret) +- break; +- } +- } + /* +- * if we failed to refill our space rsv, bail out +- * and let the transaction restart ++ * We can generate a lot of delayed refs, so we need to ++ * throttle every once and a while and make sure we're ++ * adding enough space to keep up with the work we are ++ * generating. Since we hold a transaction here we ++ * can't flush, and we don't want to FLUSH_LIMIT because ++ * we could have generated too many delayed refs to ++ * actually allocate, so just bail if we're short and ++ * let the normal reservation dance happen higher up. + */ +- if (should_end) { +- ret = -EAGAIN; +- break; ++ if (should_throttle) { ++ ret = btrfs_delayed_refs_rsv_refill(fs_info, ++ BTRFS_RESERVE_NO_FLUSH); ++ if (ret) { ++ ret = -EAGAIN; ++ break; ++ } + } + goto search_again; + } else { +@@ -4576,18 +4541,6 @@ out: + + btrfs_free_path(path); + +- if (be_nice && bytes_deleted > SZ_32M && (ret >= 0 || ret == -EAGAIN)) { +- unsigned long updates = trans->delayed_ref_updates; +- int err; +- +- if (updates) { +- trans->delayed_ref_updates = 0; +- err = btrfs_run_delayed_refs(trans, fs_info, +- updates * 2); +- if (err) +- ret = err; +- } +- } + return ret; + } + diff --git a/patches.suse/0010-btrfs-make-caching_thread-use-btrfs_find_next_key.patch b/patches.suse/0010-btrfs-make-caching_thread-use-btrfs_find_next_key.patch new file mode 100644 index 0000000..651b938 --- /dev/null +++ b/patches.suse/0010-btrfs-make-caching_thread-use-btrfs_find_next_key.patch @@ -0,0 +1,58 @@ +From: Josef Bacik +Date: Thu, 20 Jun 2019 15:37:52 -0400 +Subject: btrfs: make caching_thread use btrfs_find_next_key +Git-commit: 6a9fb468f1152d6254f49fee6ac28c3cfa3367e5 +Patch-mainline: v5.4-rc1 +References: bsc#1165949 + +extent-tree.c has a find_next_key that just walks up the path to find +the next key, but it is used for both the caching stuff and the snapshot +delete stuff. The snapshot deletion stuff is special so it can't really +use btrfs_find_next_key, but the caching thread stuff can. We just need +to fix btrfs_find_next_key to deal with ->skip_locking and then it works +exactly the same as the private find_next_key helper. + +Signed-off-by: Josef Bacik +Signed-off-by: David Sterba +Acked-by: Nikolay Borisov +--- + fs/btrfs/ctree.c | 4 ++-- + fs/btrfs/extent-tree.c | 2 +- + 2 files changed, 3 insertions(+), 3 deletions(-) + +diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c +index 9d1d0a926cb0..f8dc582db690 100644 +--- a/fs/btrfs/ctree.c ++++ b/fs/btrfs/ctree.c +@@ -5623,7 +5623,7 @@ int btrfs_find_next_key(struct btrfs_root *root, struct btrfs_path *path, + int slot; + struct extent_buffer *c; + +- WARN_ON(!path->keep_locks); ++ WARN_ON(!path->keep_locks && !path->skip_locking); + while (level < BTRFS_MAX_LEVEL) { + if (!path->nodes[level]) + return 1; +@@ -5639,7 +5639,7 @@ int btrfs_find_next_key(struct btrfs_root *root, struct btrfs_path *path, + !path->nodes[level + 1]) + return 1; + +- if (path->locks[level + 1]) { ++ if (path->locks[level + 1] || path->skip_locking) { + level++; + continue; + } +diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c +index 6cae152a4812..3348f9a4e15c 100644 +--- a/fs/btrfs/extent-tree.c ++++ b/fs/btrfs/extent-tree.c +@@ -331,7 +331,7 @@ static int load_extent_tree_free(struct btrfs_caching_control *caching_ctl) + if (path->slots[0] < nritems) { + btrfs_item_key_to_cpu(leaf, &key, path->slots[0]); + } else { +- ret = find_next_key(path, 0, &key); ++ ret = btrfs_find_next_key(extent_root, path, &key, 0, 0); + if (ret) + break; + + diff --git a/patches.suse/0010-btrfs-move-dump_space_info-to-space-info-c.patch b/patches.suse/0010-btrfs-move-dump_space_info-to-space-info-c.patch new file mode 100644 index 0000000..6be690b --- /dev/null +++ b/patches.suse/0010-btrfs-move-dump_space_info-to-space-info-c.patch @@ -0,0 +1,220 @@ +From: Josef Bacik +Date: Tue, 18 Jun 2019 16:09:24 -0400 +Subject: btrfs: move dump_space_info to space-info.c +Git-commit: 5da6afeb32e97f956aa3d599b7f94ceb36fcf854 +Patch-mainline: v5.3-rc1 +References: bsc#1165949 + +We'll need this exported so we can use it in all the various was we need +to use it. This is prep work to move reserve_metadata_bytes. + +Reviewed-by: Nikolay Borisov +Signed-off-by: Josef Bacik +Signed-off-by: David Sterba +Acked-by: Nikolay Borisov +--- + fs/btrfs/extent-tree.c | 70 ++++--------------------------------------------- + fs/btrfs/space-info.c | 55 ++++++++++++++++++++++++++++++++++++++ + fs/btrfs/space-info.h | 3 ++ + 3 files changed, 65 insertions(+), 63 deletions(-) + +--- a/fs/btrfs/extent-tree.c ++++ b/fs/btrfs/extent-tree.c +@@ -68,9 +68,6 @@ static int alloc_reserved_tree_block(str + int level, struct btrfs_key *ins); + static int find_next_key(struct btrfs_path *path, int level, + struct btrfs_key *key); +-static void dump_space_info(struct btrfs_fs_info *fs_info, +- struct btrfs_space_info *info, u64 bytes, +- int dump_block_groups); + static int btrfs_add_reserved_bytes(struct btrfs_block_group_cache *cache, + u64 ram_bytes, u64 num_bytes, int delalloc); + static int btrfs_free_reserved_bytes(struct btrfs_block_group_cache *cache, +@@ -4415,7 +4412,7 @@ void check_system_chunk(struct btrfs_tra + if (left < thresh && btrfs_test_opt(fs_info, ENOSPC_DEBUG)) { + btrfs_info(fs_info, "left=%llu, need=%llu, flags=%llu", + left, thresh, type); +- dump_space_info(fs_info, info, 0, 0); ++ btrfs_dump_space_info(fs_info, info, 0, 0); + } + + if (left < thresh) { +@@ -5243,8 +5240,8 @@ static int reserve_metadata_bytes(struct + orig_bytes, 1); + + if (btrfs_test_opt(fs_info, ENOSPC_DEBUG)) +- dump_space_info(fs_info, block_rsv->space_info, +- orig_bytes, 0); ++ btrfs_dump_space_info(fs_info, block_rsv->space_info, ++ orig_bytes, 0); + } + return ret; + } +@@ -7837,60 +7834,6 @@ out: + return ret; + } + +-#define DUMP_BLOCK_RSV(fs_info, rsv_name) \ +-do { \ +- struct btrfs_block_rsv *__rsv = &(fs_info)->rsv_name; \ +- spin_lock(&__rsv->lock); \ +- btrfs_info(fs_info, #rsv_name ": size %llu reserved %llu", \ +- __rsv->size, __rsv->reserved); \ +- spin_unlock(&__rsv->lock); \ +-} while (0) +- +-static void dump_space_info(struct btrfs_fs_info *fs_info, +- struct btrfs_space_info *info, u64 bytes, +- int dump_block_groups) +-{ +- struct btrfs_block_group_cache *cache; +- int index = 0; +- +- spin_lock(&info->lock); +- btrfs_info(fs_info, "space_info %llu has %llu free, is %sfull", +- info->flags, +- info->total_bytes - btrfs_space_info_used(info, true), +- info->full ? "" : "not "); +- btrfs_info(fs_info, +- "space_info total=%llu, used=%llu, pinned=%llu, reserved=%llu, may_use=%llu, readonly=%llu", +- info->total_bytes, info->bytes_used, info->bytes_pinned, +- info->bytes_reserved, info->bytes_may_use, +- info->bytes_readonly); +- spin_unlock(&info->lock); +- +- DUMP_BLOCK_RSV(fs_info, global_block_rsv); +- DUMP_BLOCK_RSV(fs_info, trans_block_rsv); +- DUMP_BLOCK_RSV(fs_info, chunk_block_rsv); +- DUMP_BLOCK_RSV(fs_info, delayed_block_rsv); +- DUMP_BLOCK_RSV(fs_info, delayed_refs_rsv); +- +- if (!dump_block_groups) +- return; +- +- down_read(&info->groups_sem); +-again: +- list_for_each_entry(cache, &info->block_groups[index], list) { +- spin_lock(&cache->lock); +- btrfs_info(fs_info, +- "block group %llu has %llu bytes, %llu used %llu pinned %llu reserved %s", +- cache->key.objectid, cache->key.offset, +- btrfs_block_group_used(&cache->item), cache->pinned, +- cache->reserved, cache->ro ? "[readonly]" : ""); +- btrfs_dump_free_space(cache, bytes); +- spin_unlock(&cache->lock); +- } +- if (++index < BTRFS_NR_RAID_TYPES) +- goto again; +- up_read(&info->groups_sem); +-} +- + int btrfs_reserve_extent(struct btrfs_root *root, u64 ram_bytes, + u64 num_bytes, u64 min_alloc_size, + u64 empty_size, u64 hint_byte, +@@ -7926,7 +7869,8 @@ again: + "allocation failed flags %llu, wanted %llu", + flags, num_bytes); + if (sinfo) +- dump_space_info(fs_info, sinfo, num_bytes, 1); ++ btrfs_dump_space_info(fs_info, sinfo, ++ num_bytes, 1); + } + } + +@@ -9410,7 +9354,7 @@ out: + btrfs_info(cache->fs_info, + "sinfo_used=%llu bg_num_bytes=%llu min_allocable=%llu", + sinfo_used, num_bytes, min_allocable_bytes); +- dump_space_info(cache->fs_info, cache->space_info, 0, 0); ++ btrfs_dump_space_info(cache->fs_info, cache->space_info, 0, 0); + } + return ret; + } +@@ -9903,7 +9847,7 @@ int btrfs_free_block_groups(struct btrfs + if (WARN_ON(space_info->bytes_pinned > 0 || + space_info->bytes_reserved > 0 || + space_info->bytes_may_use > 0)) +- dump_space_info(info, space_info, 0, 0); ++ btrfs_dump_space_info(info, space_info, 0, 0); + list_del(&space_info->list); + for (i = 0; i < BTRFS_NR_RAID_TYPES; i++) { + struct kobject *kobj; +--- a/fs/btrfs/space-info.c ++++ b/fs/btrfs/space-info.c +@@ -4,6 +4,7 @@ + #include "space-info.h" + #include "sysfs.h" + #include "volumes.h" ++#include "free-space-cache.h" + + u64 btrfs_space_info_used(struct btrfs_space_info *s_info, + bool may_use_included) +@@ -344,3 +345,57 @@ again: + goto again; + } + } ++ ++#define DUMP_BLOCK_RSV(fs_info, rsv_name) \ ++do { \ ++ struct btrfs_block_rsv *__rsv = &(fs_info)->rsv_name; \ ++ spin_lock(&__rsv->lock); \ ++ btrfs_info(fs_info, #rsv_name ": size %llu reserved %llu", \ ++ __rsv->size, __rsv->reserved); \ ++ spin_unlock(&__rsv->lock); \ ++} while (0) ++ ++void btrfs_dump_space_info(struct btrfs_fs_info *fs_info, ++ struct btrfs_space_info *info, u64 bytes, ++ int dump_block_groups) ++{ ++ struct btrfs_block_group_cache *cache; ++ int index = 0; ++ ++ spin_lock(&info->lock); ++ btrfs_info(fs_info, "space_info %llu has %llu free, is %sfull", ++ info->flags, ++ info->total_bytes - btrfs_space_info_used(info, true), ++ info->full ? "" : "not "); ++ btrfs_info(fs_info, ++ "space_info total=%llu, used=%llu, pinned=%llu, reserved=%llu, may_use=%llu, readonly=%llu", ++ info->total_bytes, info->bytes_used, info->bytes_pinned, ++ info->bytes_reserved, info->bytes_may_use, ++ info->bytes_readonly); ++ spin_unlock(&info->lock); ++ ++ DUMP_BLOCK_RSV(fs_info, global_block_rsv); ++ DUMP_BLOCK_RSV(fs_info, trans_block_rsv); ++ DUMP_BLOCK_RSV(fs_info, chunk_block_rsv); ++ DUMP_BLOCK_RSV(fs_info, delayed_block_rsv); ++ DUMP_BLOCK_RSV(fs_info, delayed_refs_rsv); ++ ++ if (!dump_block_groups) ++ return; ++ ++ down_read(&info->groups_sem); ++again: ++ list_for_each_entry(cache, &info->block_groups[index], list) { ++ spin_lock(&cache->lock); ++ btrfs_info(fs_info, ++ "block group %llu has %llu bytes, %llu used %llu pinned %llu reserved %s", ++ cache->key.objectid, cache->key.offset, ++ btrfs_block_group_used(&cache->item), cache->pinned, ++ cache->reserved, cache->ro ? "[readonly]" : ""); ++ btrfs_dump_free_space(cache, bytes); ++ spin_unlock(&cache->lock); ++ } ++ if (++index < BTRFS_NR_RAID_TYPES) ++ goto again; ++ up_read(&info->groups_sem); ++} +--- a/fs/btrfs/space-info.h ++++ b/fs/btrfs/space-info.h +@@ -125,5 +125,8 @@ void btrfs_clear_space_info_full(struct + int btrfs_can_overcommit(struct btrfs_root *root, + struct btrfs_space_info *space_info, u64 bytes, + enum btrfs_reserve_flush_enum flush); ++void btrfs_dump_space_info(struct btrfs_fs_info *fs_info, ++ struct btrfs_space_info *info, u64 bytes, ++ int dump_block_groups); + + #endif /* BTRFS_SPACE_INFO_H */ diff --git a/patches.suse/0010-md-introduce-new-personality-funciton-start.patch b/patches.suse/0010-md-introduce-new-personality-funciton-start.patch deleted file mode 100644 index e8bac97..0000000 --- a/patches.suse/0010-md-introduce-new-personality-funciton-start.patch +++ /dev/null @@ -1,261 +0,0 @@ -From d5d885fd514fcebc9da5503c88aa0112df7514ef Mon Sep 17 00:00:00 2001 -From: Song Liu -Date: Sun, 19 Nov 2017 22:17:01 -0800 -Subject: [PATCH] md: introduce new personality funciton start() -Git-commit: d5d885fd514fcebc9da5503c88aa0112df7514ef -References: bsc#1111974 -Patch-mainline: v4.16-rc1 - -In do_md_run(), md threads should not wake up until the array is fully -initialized in md_run(). However, in raid5_run(), raid5-cache may wake -up mddev->thread to flush stripes that need to be written back. This -design doesn't break badly right now. But it could lead to bad bug in -the future. - -This patch tries to resolve this problem by splitting start up work -into two personality functions, run() and start(). Tasks that do not -require the md threads should go into run(), while task that require -the md threads go into start(). - -r5l_load_log() is moved to raid5_start(), so it is not called until -the md threads are started in do_md_run(). - -Signed-off-by: Song Liu -Signed-off-by: Shaohua Li -Signed-off-by: Coly Li - ---- - drivers/md/dm-raid.c | 9 +++++++++ - drivers/md/md.c | 26 ++++++++++++++++++++------ - drivers/md/md.h | 8 ++++++++ - drivers/md/raid5-cache.c | 22 +++++++++++++++++----- - drivers/md/raid5-log.h | 1 + - drivers/md/raid5.c | 10 ++++++++++ - 6 files changed, 65 insertions(+), 11 deletions(-) - -diff --git a/drivers/md/dm-raid.c b/drivers/md/dm-raid.c -index 6319d846e0ad..e5ef0757fe23 100644 ---- a/drivers/md/dm-raid.c -+++ b/drivers/md/dm-raid.c -@@ -3151,6 +3151,14 @@ static int raid_ctr(struct dm_target *ti, unsigned int argc, char **argv) - goto bad; - } - -+ r = md_start(&rs->md); -+ -+ if (r) { -+ ti->error = "Failed to start raid array"; -+ mddev_unlock(&rs->md); -+ goto bad_md_start; -+ } -+ - rs->callbacks.congested_fn = raid_is_congested; - dm_table_add_target_callbacks(ti->table, &rs->callbacks); - -@@ -3198,6 +3206,7 @@ static int raid_ctr(struct dm_target *ti, unsigned int argc, char **argv) - mddev_unlock(&rs->md); - return 0; - -+bad_md_start: - bad_journal_mode_set: - bad_stripe_cache: - bad_check_reshape: -diff --git a/drivers/md/md.c b/drivers/md/md.c -index 4e4dee0ec2de..a71adb3c34b9 100644 ---- a/drivers/md/md.c -+++ b/drivers/md/md.c -@@ -5560,11 +5560,6 @@ int md_run(struct mddev *mddev) - if (start_readonly && mddev->ro == 0) - mddev->ro = 2; /* read-only, but switch on first write */ - -- /* -- * NOTE: some pers->run(), for example r5l_recovery_log(), wakes -- * up mddev->thread. It is important to initialize critical -- * resources for mddev->thread BEFORE calling pers->run(). -- */ - err = pers->run(mddev); - if (err) - pr_warn("md: pers->run() failed ...\n"); -@@ -5678,6 +5673,9 @@ static int do_md_run(struct mddev *mddev) - if (mddev_is_clustered(mddev)) - md_allow_write(mddev); - -+ /* run start up tasks that require md_thread */ -+ md_start(mddev); -+ - md_wakeup_thread(mddev->thread); - md_wakeup_thread(mddev->sync_thread); /* possibly kick off a reshape */ - -@@ -5689,6 +5687,21 @@ static int do_md_run(struct mddev *mddev) - return err; - } - -+int md_start(struct mddev *mddev) -+{ -+ int ret = 0; -+ -+ if (mddev->pers->start) { -+ set_bit(MD_RECOVERY_WAIT, &mddev->recovery); -+ md_wakeup_thread(mddev->thread); -+ ret = mddev->pers->start(mddev); -+ clear_bit(MD_RECOVERY_WAIT, &mddev->recovery); -+ md_wakeup_thread(mddev->sync_thread); -+ } -+ return ret; -+} -+EXPORT_SYMBOL_GPL(md_start); -+ - static int restart_array(struct mddev *mddev) - { - struct gendisk *disk = mddev->gendisk; -@@ -8169,7 +8182,8 @@ void md_do_sync(struct md_thread *thread) - int ret; - - /* just incase thread restarts... */ -- if (test_bit(MD_RECOVERY_DONE, &mddev->recovery)) -+ if (test_bit(MD_RECOVERY_DONE, &mddev->recovery) || -+ test_bit(MD_RECOVERY_WAIT, &mddev->recovery)) - return; - if (mddev->ro) {/* never try to sync a read-only array */ - set_bit(MD_RECOVERY_INTR, &mddev->recovery); -diff --git a/drivers/md/md.h b/drivers/md/md.h -index 7d6bcf0eba0c..be8f72a9e30b 100644 ---- a/drivers/md/md.h -+++ b/drivers/md/md.h -@@ -485,6 +485,7 @@ enum recovery_flags { - MD_RECOVERY_RESHAPE, /* A reshape is happening */ - MD_RECOVERY_FROZEN, /* User request to abort, and not restart, any action */ - MD_RECOVERY_ERROR, /* sync-action interrupted because io-error */ -+ MD_RECOVERY_WAIT, /* waiting for pers->start() to finish */ - }; - - static inline int __must_check mddev_lock(struct mddev *mddev) -@@ -523,7 +524,13 @@ struct md_personality - struct list_head list; - struct module *owner; - bool (*make_request)(struct mddev *mddev, struct bio *bio); -+ /* -+ * start up works that do NOT require md_thread. tasks that -+ * requires md_thread should go into start() -+ */ - int (*run)(struct mddev *mddev); -+ /* start up works that require md threads */ -+ int (*start)(struct mddev *mddev); - void (*free)(struct mddev *mddev, void *priv); - void (*status)(struct seq_file *seq, struct mddev *mddev); - /* error_handler must set ->faulty and clear ->in_sync -@@ -687,6 +694,7 @@ extern int strict_strtoul_scaled(const char *cp, unsigned long *res, int scale); - - extern void mddev_init(struct mddev *mddev); - extern int md_run(struct mddev *mddev); -+extern int md_start(struct mddev *mddev); - extern void md_stop(struct mddev *mddev); - extern void md_stop_writes(struct mddev *mddev); - extern int md_rdev_init(struct md_rdev *rdev); -diff --git a/drivers/md/raid5-cache.c b/drivers/md/raid5-cache.c -index 39f31f07ffe9..f259a5fd3fbd 100644 ---- a/drivers/md/raid5-cache.c -+++ b/drivers/md/raid5-cache.c -@@ -2448,7 +2448,6 @@ static void r5c_recovery_flush_data_only_stripes(struct r5l_log *log, - raid5_release_stripe(sh); - } - -- md_wakeup_thread(conf->mddev->thread); - /* reuse conf->wait_for_quiescent in recovery */ - wait_event(conf->wait_for_quiescent, - atomic_read(&conf->active_stripes) == 0); -@@ -3036,6 +3035,23 @@ static int r5l_load_log(struct r5l_log *log) - return ret; - } - -+int r5l_start(struct r5l_log *log) -+{ -+ int ret; -+ -+ if (!log) -+ return 0; -+ -+ ret = r5l_load_log(log); -+ if (ret) { -+ struct mddev *mddev = log->rdev->mddev; -+ struct r5conf *conf = mddev->private; -+ -+ r5l_exit_log(conf); -+ } -+ return ret; -+} -+ - void r5c_update_on_rdev_error(struct mddev *mddev, struct md_rdev *rdev) - { - struct r5conf *conf = mddev->private; -@@ -3138,13 +3154,9 @@ int r5l_init_log(struct r5conf *conf, struct md_rdev *rdev) - - rcu_assign_pointer(conf->log, log); - -- if (r5l_load_log(log)) -- goto error; -- - set_bit(MD_HAS_JOURNAL, &conf->mddev->flags); - return 0; - --error: - rcu_assign_pointer(conf->log, NULL); - md_unregister_thread(&log->reclaim_thread); - reclaim_thread: -diff --git a/drivers/md/raid5-log.h b/drivers/md/raid5-log.h -index 284578b0a349..3860041e8b74 100644 ---- a/drivers/md/raid5-log.h -+++ b/drivers/md/raid5-log.h -@@ -32,6 +32,7 @@ extern struct md_sysfs_entry r5c_journal_mode; - extern void r5c_update_on_rdev_error(struct mddev *mddev, - struct md_rdev *rdev); - extern bool r5c_big_stripe_cached(struct r5conf *conf, sector_t sect); -+extern int r5l_start(struct r5l_log *log); - - extern struct dma_async_tx_descriptor * - ops_run_partial_parity(struct stripe_head *sh, struct raid5_percpu *percpu, -diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c -index 98ce4272ace9..5a2a29bd02dd 100644 ---- a/drivers/md/raid5.c -+++ b/drivers/md/raid5.c -@@ -8364,6 +8364,13 @@ static int raid5_change_consistency_policy(struct mddev *mddev, const char *buf) - return err; - } - -+static int raid5_start(struct mddev *mddev) -+{ -+ struct r5conf *conf = mddev->private; -+ -+ return r5l_start(conf->log); -+} -+ - static struct md_personality raid6_personality = - { - .name = "raid6", -@@ -8371,6 +8378,7 @@ static struct md_personality raid6_personality = - .owner = THIS_MODULE, - .make_request = raid5_make_request, - .run = raid5_run, -+ .start = raid5_start, - .free = raid5_free, - .status = raid5_status, - .error_handler = raid5_error, -@@ -8395,6 +8403,7 @@ static struct md_personality raid5_personality = - .owner = THIS_MODULE, - .make_request = raid5_make_request, - .run = raid5_run, -+ .start = raid5_start, - .free = raid5_free, - .status = raid5_status, - .error_handler = raid5_error, -@@ -8420,6 +8429,7 @@ static struct md_personality raid4_personality = - .owner = THIS_MODULE, - .make_request = raid5_make_request, - .run = raid5_run, -+ .start = raid5_start, - .free = raid5_free, - .status = raid5_status, - .error_handler = raid5_error, --- -2.19.0 - diff --git a/patches.suse/0011-btrfs-catch-cow-on-deleting-snapshots.patch b/patches.suse/0011-btrfs-catch-cow-on-deleting-snapshots.patch new file mode 100644 index 0000000..0c96429 --- /dev/null +++ b/patches.suse/0011-btrfs-catch-cow-on-deleting-snapshots.patch @@ -0,0 +1,65 @@ +From: Josef Bacik +Date: Fri, 30 Nov 2018 11:52:13 -0500 +Subject: btrfs: catch cow on deleting snapshots +Git-commit: 83354f0772cd07828b0fcdf1ef2872fd2032acb8 +Patch-mainline: v5.0-rc1 +References: bsc#1165949 + +When debugging some weird extent reference bug I suspected that we were +changing a snapshot while we were deleting it, which could explain my +bug. This was indeed what was happening, and this patch helped me +verify my theory. It is never correct to modify the snapshot once it's +being deleted, so mark the root when we are deleting it and make sure we +complain about it when it happens. + +Reviewed-by: Filipe Manana +Signed-off-by: Josef Bacik +Signed-off-by: David Sterba +Acked-by: Nikolay Borisov +--- + fs/btrfs/ctree.c | 4 ++++ + fs/btrfs/ctree.h | 1 + + fs/btrfs/extent-tree.c | 9 +++++++++ + 3 files changed, 14 insertions(+) + +--- a/fs/btrfs/ctree.c ++++ b/fs/btrfs/ctree.c +@@ -1522,6 +1522,10 @@ noinline int btrfs_cow_block(struct btrf + u64 search_start; + int ret; + ++ if (test_bit(BTRFS_ROOT_DELETING, &root->state)) ++ btrfs_err(fs_info, ++ "COW'ing blocks on a fs root that's being dropped"); ++ + if (trans->transaction != fs_info->running_transaction) + WARN(1, KERN_CRIT "trans %llu running %llu\n", + trans->transid, +--- a/fs/btrfs/ctree.h ++++ b/fs/btrfs/ctree.h +@@ -1179,6 +1179,7 @@ struct btrfs_subvolume_writers { + #define BTRFS_ROOT_FORCE_COW 6 + #define BTRFS_ROOT_MULTI_LOG_TASKS 7 + #define BTRFS_ROOT_DIRTY 8 ++#define BTRFS_ROOT_DELETING 9 + + /* + * in ram representation of the tree. extent_root is used for all allocations +--- a/fs/btrfs/extent-tree.c ++++ b/fs/btrfs/extent-tree.c +@@ -9275,6 +9275,15 @@ int btrfs_drop_snapshot(struct btrfs_roo + if (block_rsv) + trans->block_rsv = block_rsv; + ++ /* ++ * This will help us catch people modifying the fs tree while we're ++ * dropping it. It is unsafe to mess with the fs tree while it's being ++ * dropped as we unlock the root node and parent nodes as we walk down ++ * the tree, assuming nothing will change. If something does change ++ * then we'll have stale information and drop references to blocks we've ++ * already dropped. ++ */ ++ set_bit(BTRFS_ROOT_DELETING, &root->state); + if (btrfs_disk_key_objectid(&root_item->drop_progress) == 0) { + level = btrfs_header_level(root->node); + path->nodes[level] = btrfs_lock_root_node(root); diff --git a/patches.suse/0011-btrfs-migrate-the-block-group-caching-code.patch b/patches.suse/0011-btrfs-migrate-the-block-group-caching-code.patch new file mode 100644 index 0000000..78d5190 --- /dev/null +++ b/patches.suse/0011-btrfs-migrate-the-block-group-caching-code.patch @@ -0,0 +1,1071 @@ +From: Josef Bacik +Date: Tue, 6 Aug 2019 16:43:19 +0200 +Subject: btrfs: migrate the block group caching code +Git-commit: 9f21246d8c7efb940b96098cb556bfe86205fbed +Patch-mainline: v5.4-rc1 +References: bsc#1165949 + +We can now just copy it over to block-group.c. + +Signed-off-by: Josef Bacik +Reviewed-by: David Sterba +Signed-off-by: David Sterba +Acked-by: Nikolay Borisov +--- + fs/btrfs/block-group.c | 460 +++++++++++++++++++++++++++++++++++++++++++ + fs/btrfs/block-group.h | 2 + fs/btrfs/ctree.h | 3 + fs/btrfs/extent-tree.c | 466 -------------------------------------------- + fs/btrfs/free-space-cache.c | 4 + fs/btrfs/free-space-cache.h | 3 + fs/btrfs/free-space-tree.c | 7 + 7 files changed, 470 insertions(+), 475 deletions(-) + +--- a/fs/btrfs/block-group.c ++++ b/fs/btrfs/block-group.c +@@ -3,6 +3,9 @@ + #include "ctree.h" + #include "block-group.h" + #include "space-info.h" ++#include "disk-io.h" ++#include "free-space-cache.h" ++#include "free-space-tree.h" + + void btrfs_get_block_group(struct btrfs_block_group_cache *cache) + { +@@ -216,3 +219,460 @@ void btrfs_wait_block_group_reservations + wait_on_atomic_t(&bg->reservations, atomic_t_wait, + TASK_UNINTERRUPTIBLE); + } ++ ++struct btrfs_caching_control *btrfs_get_caching_control( ++ struct btrfs_block_group_cache *cache) ++{ ++ struct btrfs_caching_control *ctl; ++ ++ spin_lock(&cache->lock); ++ if (!cache->caching_ctl) { ++ spin_unlock(&cache->lock); ++ return NULL; ++ } ++ ++ ctl = cache->caching_ctl; ++ refcount_inc(&ctl->count); ++ spin_unlock(&cache->lock); ++ return ctl; ++} ++ ++void btrfs_put_caching_control(struct btrfs_caching_control *ctl) ++{ ++ if (refcount_dec_and_test(&ctl->count)) ++ kfree(ctl); ++} ++ ++/* ++ * When we wait for progress in the block group caching, its because our ++ * allocation attempt failed at least once. So, we must sleep and let some ++ * progress happen before we try again. ++ * ++ * This function will sleep at least once waiting for new free space to show ++ * up, and then it will check the block group free space numbers for our min ++ * num_bytes. Another option is to have it go ahead and look in the rbtree for ++ * a free extent of a given size, but this is a good start. ++ * ++ * Callers of this must check if cache->cached == BTRFS_CACHE_ERROR before using ++ * any of the information in this block group. ++ */ ++void btrfs_wait_block_group_cache_progress(struct btrfs_block_group_cache *cache, ++ u64 num_bytes) ++{ ++ struct btrfs_caching_control *caching_ctl; ++ ++ caching_ctl = btrfs_get_caching_control(cache); ++ if (!caching_ctl) ++ return; ++ ++ wait_event(caching_ctl->wait, btrfs_block_group_cache_done(cache) || ++ (cache->free_space_ctl->free_space >= num_bytes)); ++ ++ btrfs_put_caching_control(caching_ctl); ++} ++ ++int btrfs_wait_block_group_cache_done(struct btrfs_block_group_cache *cache) ++{ ++ struct btrfs_caching_control *caching_ctl; ++ int ret = 0; ++ ++ caching_ctl = btrfs_get_caching_control(cache); ++ if (!caching_ctl) ++ return (cache->cached == BTRFS_CACHE_ERROR) ? -EIO : 0; ++ ++ wait_event(caching_ctl->wait, btrfs_block_group_cache_done(cache)); ++ if (cache->cached == BTRFS_CACHE_ERROR) ++ ret = -EIO; ++ btrfs_put_caching_control(caching_ctl); ++ return ret; ++} ++ ++#ifdef CONFIG_BTRFS_DEBUG ++void btrfs_fragment_free_space(struct btrfs_block_group_cache *block_group) ++{ ++ struct btrfs_fs_info *fs_info = block_group->fs_info; ++ u64 start = block_group->key.objectid; ++ u64 len = block_group->key.offset; ++ u64 chunk = block_group->flags & BTRFS_BLOCK_GROUP_METADATA ? ++ fs_info->nodesize : fs_info->sectorsize; ++ u64 step = chunk << 1; ++ ++ while (len > chunk) { ++ btrfs_remove_free_space(block_group, start, chunk); ++ start += step; ++ if (len < step) ++ len = 0; ++ else ++ len -= step; ++ } ++} ++#endif ++ ++/* ++ * This is only called by btrfs_cache_block_group, since we could have freed ++ * extents we need to check the pinned_extents for any extents that can't be ++ * used yet since their free space will be released as soon as the transaction ++ * commits. ++ */ ++u64 add_new_free_space(struct btrfs_block_group_cache *block_group, ++ u64 start, u64 end) ++{ ++ struct btrfs_fs_info *info = block_group->fs_info; ++ u64 extent_start, extent_end, size, total_added = 0; ++ int ret; ++ ++ while (start < end) { ++ ret = find_first_extent_bit(info->pinned_extents, start, ++ &extent_start, &extent_end, ++ EXTENT_DIRTY | EXTENT_UPTODATE, ++ NULL); ++ if (ret) ++ break; ++ ++ if (extent_start <= start) { ++ start = extent_end + 1; ++ } else if (extent_start > start && extent_start < end) { ++ size = extent_start - start; ++ total_added += size; ++ ret = btrfs_add_free_space(block_group, start, ++ size); ++ BUG_ON(ret); /* -ENOMEM or logic error */ ++ start = extent_end + 1; ++ } else { ++ break; ++ } ++ } ++ ++ if (start < end) { ++ size = end - start; ++ total_added += size; ++ ret = btrfs_add_free_space(block_group, start, size); ++ BUG_ON(ret); /* -ENOMEM or logic error */ ++ } ++ ++ return total_added; ++} ++ ++static int load_extent_tree_free(struct btrfs_caching_control *caching_ctl) ++{ ++ struct btrfs_block_group_cache *block_group = caching_ctl->block_group; ++ struct btrfs_fs_info *fs_info = block_group->fs_info; ++ struct btrfs_root *extent_root = fs_info->extent_root; ++ struct btrfs_path *path; ++ struct extent_buffer *leaf; ++ struct btrfs_key key; ++ u64 total_found = 0; ++ u64 last = 0; ++ u32 nritems; ++ int ret; ++ bool wakeup = true; ++ ++ path = btrfs_alloc_path(); ++ if (!path) ++ return -ENOMEM; ++ ++ last = max_t(u64, block_group->key.objectid, BTRFS_SUPER_INFO_OFFSET); ++ ++#ifdef CONFIG_BTRFS_DEBUG ++ /* ++ * If we're fragmenting we don't want to make anybody think we can ++ * allocate from this block group until we've had a chance to fragment ++ * the free space. ++ */ ++ if (btrfs_should_fragment_free_space(block_group)) ++ wakeup = false; ++#endif ++ /* ++ * We don't want to deadlock with somebody trying to allocate a new ++ * extent for the extent root while also trying to search the extent ++ * root to add free space. So we skip locking and search the commit ++ * root, since its read-only ++ */ ++ path->skip_locking = 1; ++ path->search_commit_root = 1; ++ path->reada = READA_FORWARD; ++ ++ key.objectid = last; ++ key.offset = 0; ++ key.type = BTRFS_EXTENT_ITEM_KEY; ++ ++next: ++ ret = btrfs_search_slot(NULL, extent_root, &key, path, 0, 0); ++ if (ret < 0) ++ goto out; ++ ++ leaf = path->nodes[0]; ++ nritems = btrfs_header_nritems(leaf); ++ ++ while (1) { ++ if (btrfs_fs_closing(fs_info) > 1) { ++ last = (u64)-1; ++ break; ++ } ++ ++ if (path->slots[0] < nritems) { ++ btrfs_item_key_to_cpu(leaf, &key, path->slots[0]); ++ } else { ++ ret = btrfs_find_next_key(extent_root, path, &key, 0, 0); ++ if (ret) ++ break; ++ ++ if (need_resched() || ++ rwsem_is_contended(&fs_info->commit_root_sem)) { ++ if (wakeup) ++ caching_ctl->progress = last; ++ btrfs_release_path(path); ++ up_read(&fs_info->commit_root_sem); ++ mutex_unlock(&caching_ctl->mutex); ++ cond_resched(); ++ mutex_lock(&caching_ctl->mutex); ++ down_read(&fs_info->commit_root_sem); ++ goto next; ++ } ++ ++ ret = btrfs_next_leaf(extent_root, path); ++ if (ret < 0) ++ goto out; ++ if (ret) ++ break; ++ leaf = path->nodes[0]; ++ nritems = btrfs_header_nritems(leaf); ++ continue; ++ } ++ ++ if (key.objectid < last) { ++ key.objectid = last; ++ key.offset = 0; ++ key.type = BTRFS_EXTENT_ITEM_KEY; ++ ++ if (wakeup) ++ caching_ctl->progress = last; ++ btrfs_release_path(path); ++ goto next; ++ } ++ ++ if (key.objectid < block_group->key.objectid) { ++ path->slots[0]++; ++ continue; ++ } ++ ++ if (key.objectid >= block_group->key.objectid + ++ block_group->key.offset) ++ break; ++ ++ if (key.type == BTRFS_EXTENT_ITEM_KEY || ++ key.type == BTRFS_METADATA_ITEM_KEY) { ++ total_found += add_new_free_space(block_group, last, ++ key.objectid); ++ if (key.type == BTRFS_METADATA_ITEM_KEY) ++ last = key.objectid + ++ fs_info->nodesize; ++ else ++ last = key.objectid + key.offset; ++ ++ if (total_found > CACHING_CTL_WAKE_UP) { ++ total_found = 0; ++ if (wakeup) ++ wake_up(&caching_ctl->wait); ++ } ++ } ++ path->slots[0]++; ++ } ++ ret = 0; ++ ++ total_found += add_new_free_space(block_group, last, ++ block_group->key.objectid + ++ block_group->key.offset); ++ caching_ctl->progress = (u64)-1; ++ ++out: ++ btrfs_free_path(path); ++ return ret; ++} ++ ++static noinline void caching_thread(struct btrfs_work *work) ++{ ++ struct btrfs_block_group_cache *block_group; ++ struct btrfs_fs_info *fs_info; ++ struct btrfs_caching_control *caching_ctl; ++ int ret; ++ ++ caching_ctl = container_of(work, struct btrfs_caching_control, work); ++ block_group = caching_ctl->block_group; ++ fs_info = block_group->fs_info; ++ ++ mutex_lock(&caching_ctl->mutex); ++ down_read(&fs_info->commit_root_sem); ++ ++ if (btrfs_fs_compat_ro(fs_info, FREE_SPACE_TREE)) ++ ret = load_free_space_tree(caching_ctl); ++ else ++ ret = load_extent_tree_free(caching_ctl); ++ ++ spin_lock(&block_group->lock); ++ block_group->caching_ctl = NULL; ++ block_group->cached = ret ? BTRFS_CACHE_ERROR : BTRFS_CACHE_FINISHED; ++ spin_unlock(&block_group->lock); ++ ++#ifdef CONFIG_BTRFS_DEBUG ++ if (btrfs_should_fragment_free_space(block_group)) { ++ u64 bytes_used; ++ ++ spin_lock(&block_group->space_info->lock); ++ spin_lock(&block_group->lock); ++ bytes_used = block_group->key.offset - ++ btrfs_block_group_used(&block_group->item); ++ block_group->space_info->bytes_used += bytes_used >> 1; ++ spin_unlock(&block_group->lock); ++ spin_unlock(&block_group->space_info->lock); ++ btrfs_fragment_free_space(block_group); ++ } ++#endif ++ ++ caching_ctl->progress = (u64)-1; ++ ++ up_read(&fs_info->commit_root_sem); ++ btrfs_free_excluded_extents(block_group); ++ mutex_unlock(&caching_ctl->mutex); ++ ++ wake_up(&caching_ctl->wait); ++ ++ btrfs_put_caching_control(caching_ctl); ++ btrfs_put_block_group(block_group); ++} ++ ++int btrfs_cache_block_group(struct btrfs_block_group_cache *cache, ++ int load_cache_only) ++{ ++ DEFINE_WAIT(wait); ++ struct btrfs_fs_info *fs_info = cache->fs_info; ++ struct btrfs_caching_control *caching_ctl; ++ int ret = 0; ++ ++ caching_ctl = kzalloc(sizeof(*caching_ctl), GFP_NOFS); ++ if (!caching_ctl) ++ return -ENOMEM; ++ ++ INIT_LIST_HEAD(&caching_ctl->list); ++ mutex_init(&caching_ctl->mutex); ++ init_waitqueue_head(&caching_ctl->wait); ++ caching_ctl->block_group = cache; ++ caching_ctl->progress = cache->key.objectid; ++ refcount_set(&caching_ctl->count, 1); ++ btrfs_init_work(&caching_ctl->work, btrfs_cache_helper, ++ caching_thread, NULL, NULL); ++ ++ spin_lock(&cache->lock); ++ /* ++ * This should be a rare occasion, but this could happen I think in the ++ * case where one thread starts to load the space cache info, and then ++ * some other thread starts a transaction commit which tries to do an ++ * allocation while the other thread is still loading the space cache ++ * info. The previous loop should have kept us from choosing this block ++ * group, but if we've moved to the state where we will wait on caching ++ * block groups we need to first check if we're doing a fast load here, ++ * so we can wait for it to finish, otherwise we could end up allocating ++ * from a block group who's cache gets evicted for one reason or ++ * another. ++ */ ++ while (cache->cached == BTRFS_CACHE_FAST) { ++ struct btrfs_caching_control *ctl; ++ ++ ctl = cache->caching_ctl; ++ refcount_inc(&ctl->count); ++ prepare_to_wait(&ctl->wait, &wait, TASK_UNINTERRUPTIBLE); ++ spin_unlock(&cache->lock); ++ ++ schedule(); ++ ++ finish_wait(&ctl->wait, &wait); ++ btrfs_put_caching_control(ctl); ++ spin_lock(&cache->lock); ++ } ++ ++ if (cache->cached != BTRFS_CACHE_NO) { ++ spin_unlock(&cache->lock); ++ kfree(caching_ctl); ++ return 0; ++ } ++ WARN_ON(cache->caching_ctl); ++ cache->caching_ctl = caching_ctl; ++ cache->cached = BTRFS_CACHE_FAST; ++ spin_unlock(&cache->lock); ++ ++ if (fs_info->mount_opt & BTRFS_MOUNT_SPACE_CACHE) { ++ mutex_lock(&caching_ctl->mutex); ++ ret = load_free_space_cache(cache); ++ ++ spin_lock(&cache->lock); ++ if (ret == 1) { ++ cache->caching_ctl = NULL; ++ cache->cached = BTRFS_CACHE_FINISHED; ++ cache->last_byte_to_unpin = (u64)-1; ++ caching_ctl->progress = (u64)-1; ++ } else { ++ if (load_cache_only) { ++ cache->caching_ctl = NULL; ++ cache->cached = BTRFS_CACHE_NO; ++ } else { ++ cache->cached = BTRFS_CACHE_STARTED; ++ cache->has_caching_ctl = 1; ++ } ++ } ++ spin_unlock(&cache->lock); ++#ifdef CONFIG_BTRFS_DEBUG ++ if (ret == 1 && ++ btrfs_should_fragment_free_space(cache)) { ++ u64 bytes_used; ++ ++ spin_lock(&cache->space_info->lock); ++ spin_lock(&cache->lock); ++ bytes_used = cache->key.offset - ++ btrfs_block_group_used(&cache->item); ++ cache->space_info->bytes_used += bytes_used >> 1; ++ spin_unlock(&cache->lock); ++ spin_unlock(&cache->space_info->lock); ++ btrfs_fragment_free_space(cache); ++ } ++#endif ++ mutex_unlock(&caching_ctl->mutex); ++ ++ wake_up(&caching_ctl->wait); ++ if (ret == 1) { ++ btrfs_put_caching_control(caching_ctl); ++ btrfs_free_excluded_extents(cache); ++ return 0; ++ } ++ } else { ++ /* ++ * We're either using the free space tree or no caching at all. ++ * Set cached to the appropriate value and wakeup any waiters. ++ */ ++ spin_lock(&cache->lock); ++ if (load_cache_only) { ++ cache->caching_ctl = NULL; ++ cache->cached = BTRFS_CACHE_NO; ++ } else { ++ cache->cached = BTRFS_CACHE_STARTED; ++ cache->has_caching_ctl = 1; ++ } ++ spin_unlock(&cache->lock); ++ wake_up(&caching_ctl->wait); ++ } ++ ++ if (load_cache_only) { ++ btrfs_put_caching_control(caching_ctl); ++ return 0; ++ } ++ ++ down_write(&fs_info->commit_root_sem); ++ refcount_inc(&caching_ctl->count); ++ list_add_tail(&caching_ctl->list, &fs_info->caching_block_groups); ++ up_write(&fs_info->commit_root_sem); ++ ++ btrfs_get_block_group(cache); ++ ++ btrfs_queue_work(fs_info->caching_workers, &caching_ctl->work); ++ ++ return ret; ++} +--- a/fs/btrfs/block-group.h ++++ b/fs/btrfs/block-group.h +@@ -174,6 +174,8 @@ int btrfs_cache_block_group(struct btrfs + void btrfs_put_caching_control(struct btrfs_caching_control *ctl); + struct btrfs_caching_control *btrfs_get_caching_control( + struct btrfs_block_group_cache *cache); ++u64 add_new_free_space(struct btrfs_block_group_cache *block_group, ++ u64 start, u64 end); + + static inline int btrfs_block_group_cache_done( + struct btrfs_block_group_cache *cache) +--- a/fs/btrfs/ctree.h ++++ b/fs/btrfs/ctree.h +@@ -2630,9 +2630,6 @@ void btrfs_end_write_no_snapshoting(stru + void btrfs_wait_for_snapshot_creation(struct btrfs_root *root); + void check_system_chunk(struct btrfs_trans_handle *trans, + struct btrfs_fs_info *fs_info, const u64 type); +-u64 add_new_free_space(struct btrfs_block_group_cache *block_group, +- struct btrfs_fs_info *info, u64 start, u64 end); +- + /* ctree.c */ + int btrfs_bin_search(struct extent_buffer *eb, const struct btrfs_key *key, + int level, int *slot); +--- a/fs/btrfs/extent-tree.c ++++ b/fs/btrfs/extent-tree.c +@@ -203,422 +203,6 @@ static int exclude_super_stripes(struct + return 0; + } + +-struct btrfs_caching_control *btrfs_get_caching_control( +- struct btrfs_block_group_cache *cache) +-{ +- struct btrfs_caching_control *ctl; +- +- spin_lock(&cache->lock); +- if (!cache->caching_ctl) { +- spin_unlock(&cache->lock); +- return NULL; +- } +- +- ctl = cache->caching_ctl; +- refcount_inc(&ctl->count); +- spin_unlock(&cache->lock); +- return ctl; +-} +- +-void btrfs_put_caching_control(struct btrfs_caching_control *ctl) +-{ +- if (refcount_dec_and_test(&ctl->count)) +- kfree(ctl); +-} +- +-#ifdef CONFIG_BTRFS_DEBUG +-void btrfs_fragment_free_space(struct btrfs_block_group_cache *block_group) +-{ +- struct btrfs_fs_info *fs_info = block_group->fs_info; +- u64 start = block_group->key.objectid; +- u64 len = block_group->key.offset; +- u64 chunk = block_group->flags & BTRFS_BLOCK_GROUP_METADATA ? +- fs_info->nodesize : fs_info->sectorsize; +- u64 step = chunk << 1; +- +- while (len > chunk) { +- btrfs_remove_free_space(block_group, start, chunk); +- start += step; +- if (len < step) +- len = 0; +- else +- len -= step; +- } +-} +-#endif +- +-/* +- * This is only called by btrfs_cache_block_group, since we could have freed +- * extents we need to check the pinned_extents for any extents that can't be +- * used yet since their free space will be released as soon as the transaction +- * commits. +- */ +-u64 add_new_free_space(struct btrfs_block_group_cache *block_group, +- struct btrfs_fs_info *info, u64 start, u64 end) +-{ +- u64 extent_start, extent_end, size, total_added = 0; +- int ret; +- +- while (start < end) { +- ret = find_first_extent_bit(info->pinned_extents, start, +- &extent_start, &extent_end, +- EXTENT_DIRTY | EXTENT_UPTODATE, +- NULL); +- if (ret) +- break; +- +- if (extent_start <= start) { +- start = extent_end + 1; +- } else if (extent_start > start && extent_start < end) { +- size = extent_start - start; +- total_added += size; +- ret = btrfs_add_free_space(block_group, start, +- size); +- BUG_ON(ret); /* -ENOMEM or logic error */ +- start = extent_end + 1; +- } else { +- break; +- } +- } +- +- if (start < end) { +- size = end - start; +- total_added += size; +- ret = btrfs_add_free_space(block_group, start, size); +- BUG_ON(ret); /* -ENOMEM or logic error */ +- } +- +- return total_added; +-} +- +-static int load_extent_tree_free(struct btrfs_caching_control *caching_ctl) +-{ +- struct btrfs_block_group_cache *block_group = caching_ctl->block_group; +- struct btrfs_fs_info *fs_info = block_group->fs_info; +- struct btrfs_root *extent_root = fs_info->extent_root; +- struct btrfs_path *path; +- struct extent_buffer *leaf; +- struct btrfs_key key; +- u64 total_found = 0; +- u64 last = 0; +- u32 nritems; +- int ret; +- bool wakeup = true; +- +- path = btrfs_alloc_path(); +- if (!path) +- return -ENOMEM; +- +- last = max_t(u64, block_group->key.objectid, BTRFS_SUPER_INFO_OFFSET); +- +-#ifdef CONFIG_BTRFS_DEBUG +- /* +- * If we're fragmenting we don't want to make anybody think we can +- * allocate from this block group until we've had a chance to fragment +- * the free space. +- */ +- if (btrfs_should_fragment_free_space(block_group)) +- wakeup = false; +-#endif +- /* +- * We don't want to deadlock with somebody trying to allocate a new +- * extent for the extent root while also trying to search the extent +- * root to add free space. So we skip locking and search the commit +- * root, since its read-only +- */ +- path->skip_locking = 1; +- path->search_commit_root = 1; +- path->reada = READA_FORWARD; +- +- key.objectid = last; +- key.offset = 0; +- key.type = BTRFS_EXTENT_ITEM_KEY; +- +-next: +- ret = btrfs_search_slot(NULL, extent_root, &key, path, 0, 0); +- if (ret < 0) +- goto out; +- +- leaf = path->nodes[0]; +- nritems = btrfs_header_nritems(leaf); +- +- while (1) { +- if (btrfs_fs_closing(fs_info) > 1) { +- last = (u64)-1; +- break; +- } +- +- if (path->slots[0] < nritems) { +- btrfs_item_key_to_cpu(leaf, &key, path->slots[0]); +- } else { +- ret = btrfs_find_next_key(extent_root, path, &key, 0, 0); +- if (ret) +- break; +- +- if (need_resched() || +- rwsem_is_contended(&fs_info->commit_root_sem)) { +- if (wakeup) +- caching_ctl->progress = last; +- btrfs_release_path(path); +- up_read(&fs_info->commit_root_sem); +- mutex_unlock(&caching_ctl->mutex); +- cond_resched(); +- mutex_lock(&caching_ctl->mutex); +- down_read(&fs_info->commit_root_sem); +- goto next; +- } +- +- ret = btrfs_next_leaf(extent_root, path); +- if (ret < 0) +- goto out; +- if (ret) +- break; +- leaf = path->nodes[0]; +- nritems = btrfs_header_nritems(leaf); +- continue; +- } +- +- if (key.objectid < last) { +- key.objectid = last; +- key.offset = 0; +- key.type = BTRFS_EXTENT_ITEM_KEY; +- +- if (wakeup) +- caching_ctl->progress = last; +- btrfs_release_path(path); +- goto next; +- } +- +- if (key.objectid < block_group->key.objectid) { +- path->slots[0]++; +- continue; +- } +- +- if (key.objectid >= block_group->key.objectid + +- block_group->key.offset) +- break; +- +- if (key.type == BTRFS_EXTENT_ITEM_KEY || +- key.type == BTRFS_METADATA_ITEM_KEY) { +- total_found += add_new_free_space(block_group, +- fs_info, last, +- key.objectid); +- if (key.type == BTRFS_METADATA_ITEM_KEY) +- last = key.objectid + +- fs_info->nodesize; +- else +- last = key.objectid + key.offset; +- +- if (total_found > CACHING_CTL_WAKE_UP) { +- total_found = 0; +- if (wakeup) +- wake_up(&caching_ctl->wait); +- } +- } +- path->slots[0]++; +- } +- ret = 0; +- +- total_found += add_new_free_space(block_group, fs_info, last, +- block_group->key.objectid + +- block_group->key.offset); +- caching_ctl->progress = (u64)-1; +- +-out: +- btrfs_free_path(path); +- return ret; +-} +- +-static noinline void caching_thread(struct btrfs_work *work) +-{ +- struct btrfs_block_group_cache *block_group; +- struct btrfs_fs_info *fs_info; +- struct btrfs_caching_control *caching_ctl; +- struct btrfs_root *extent_root; +- int ret; +- +- caching_ctl = container_of(work, struct btrfs_caching_control, work); +- block_group = caching_ctl->block_group; +- fs_info = block_group->fs_info; +- extent_root = fs_info->extent_root; +- +- mutex_lock(&caching_ctl->mutex); +- down_read(&fs_info->commit_root_sem); +- +- if (btrfs_fs_compat_ro(fs_info, FREE_SPACE_TREE)) +- ret = load_free_space_tree(caching_ctl); +- else +- ret = load_extent_tree_free(caching_ctl); +- +- spin_lock(&block_group->lock); +- block_group->caching_ctl = NULL; +- block_group->cached = ret ? BTRFS_CACHE_ERROR : BTRFS_CACHE_FINISHED; +- spin_unlock(&block_group->lock); +- +-#ifdef CONFIG_BTRFS_DEBUG +- if (btrfs_should_fragment_free_space(block_group)) { +- u64 bytes_used; +- +- spin_lock(&block_group->space_info->lock); +- spin_lock(&block_group->lock); +- bytes_used = block_group->key.offset - +- btrfs_block_group_used(&block_group->item); +- block_group->space_info->bytes_used += bytes_used >> 1; +- spin_unlock(&block_group->lock); +- spin_unlock(&block_group->space_info->lock); +- btrfs_fragment_free_space(block_group); +- } +-#endif +- +- caching_ctl->progress = (u64)-1; +- +- up_read(&fs_info->commit_root_sem); +- btrfs_free_excluded_extents(block_group); +- mutex_unlock(&caching_ctl->mutex); +- +- wake_up(&caching_ctl->wait); +- +- btrfs_put_caching_control(caching_ctl); +- btrfs_put_block_group(block_group); +-} +- +-int btrfs_cache_block_group(struct btrfs_block_group_cache *cache, +- int load_cache_only) +-{ +- DEFINE_WAIT(wait); +- struct btrfs_fs_info *fs_info = cache->fs_info; +- struct btrfs_caching_control *caching_ctl; +- int ret = 0; +- +- caching_ctl = kzalloc(sizeof(*caching_ctl), GFP_NOFS); +- if (!caching_ctl) +- return -ENOMEM; +- +- INIT_LIST_HEAD(&caching_ctl->list); +- mutex_init(&caching_ctl->mutex); +- init_waitqueue_head(&caching_ctl->wait); +- caching_ctl->block_group = cache; +- caching_ctl->progress = cache->key.objectid; +- refcount_set(&caching_ctl->count, 1); +- btrfs_init_work(&caching_ctl->work, btrfs_cache_helper, +- caching_thread, NULL, NULL); +- +- spin_lock(&cache->lock); +- /* +- * This should be a rare occasion, but this could happen I think in the +- * case where one thread starts to load the space cache info, and then +- * some other thread starts a transaction commit which tries to do an +- * allocation while the other thread is still loading the space cache +- * info. The previous loop should have kept us from choosing this block +- * group, but if we've moved to the state where we will wait on caching +- * block groups we need to first check if we're doing a fast load here, +- * so we can wait for it to finish, otherwise we could end up allocating +- * from a block group who's cache gets evicted for one reason or +- * another. +- */ +- while (cache->cached == BTRFS_CACHE_FAST) { +- struct btrfs_caching_control *ctl; +- +- ctl = cache->caching_ctl; +- refcount_inc(&ctl->count); +- prepare_to_wait(&ctl->wait, &wait, TASK_UNINTERRUPTIBLE); +- spin_unlock(&cache->lock); +- +- schedule(); +- +- finish_wait(&ctl->wait, &wait); +- btrfs_put_caching_control(ctl); +- spin_lock(&cache->lock); +- } +- +- if (cache->cached != BTRFS_CACHE_NO) { +- spin_unlock(&cache->lock); +- kfree(caching_ctl); +- return 0; +- } +- WARN_ON(cache->caching_ctl); +- cache->caching_ctl = caching_ctl; +- cache->cached = BTRFS_CACHE_FAST; +- spin_unlock(&cache->lock); +- +- if (fs_info->mount_opt & BTRFS_MOUNT_SPACE_CACHE) { +- mutex_lock(&caching_ctl->mutex); +- ret = load_free_space_cache(fs_info, cache); +- +- spin_lock(&cache->lock); +- if (ret == 1) { +- cache->caching_ctl = NULL; +- cache->cached = BTRFS_CACHE_FINISHED; +- cache->last_byte_to_unpin = (u64)-1; +- caching_ctl->progress = (u64)-1; +- } else { +- if (load_cache_only) { +- cache->caching_ctl = NULL; +- cache->cached = BTRFS_CACHE_NO; +- } else { +- cache->cached = BTRFS_CACHE_STARTED; +- cache->has_caching_ctl = 1; +- } +- } +- spin_unlock(&cache->lock); +-#ifdef CONFIG_BTRFS_DEBUG +- if (ret == 1 && +- btrfs_should_fragment_free_space(cache)) { +- u64 bytes_used; +- +- spin_lock(&cache->space_info->lock); +- spin_lock(&cache->lock); +- bytes_used = cache->key.offset - +- btrfs_block_group_used(&cache->item); +- cache->space_info->bytes_used += bytes_used >> 1; +- spin_unlock(&cache->lock); +- spin_unlock(&cache->space_info->lock); +- btrfs_fragment_free_space(cache); +- } +-#endif +- mutex_unlock(&caching_ctl->mutex); +- +- wake_up(&caching_ctl->wait); +- if (ret == 1) { +- btrfs_put_caching_control(caching_ctl); +- btrfs_free_excluded_extents(cache); +- return 0; +- } +- } else { +- /* +- * We're either using the free space tree or no caching at all. +- * Set cached to the appropriate value and wakeup any waiters. +- */ +- spin_lock(&cache->lock); +- if (load_cache_only) { +- cache->caching_ctl = NULL; +- cache->cached = BTRFS_CACHE_NO; +- } else { +- cache->cached = BTRFS_CACHE_STARTED; +- cache->has_caching_ctl = 1; +- } +- spin_unlock(&cache->lock); +- wake_up(&caching_ctl->wait); +- } +- +- if (load_cache_only) { +- btrfs_put_caching_control(caching_ctl); +- return 0; +- } +- +- down_write(&fs_info->commit_root_sem); +- refcount_inc(&caching_ctl->count); +- list_add_tail(&caching_ctl->list, &fs_info->caching_block_groups); +- up_write(&fs_info->commit_root_sem); +- +- btrfs_get_block_group(cache); +- +- btrfs_queue_work(fs_info->caching_workers, &caching_ctl->work); +- +- return ret; +-} +- +- + static void add_pinned_bytes(struct btrfs_fs_info *fs_info, + struct btrfs_ref *ref, int sign) + { +@@ -5168,51 +4752,6 @@ int btrfs_free_extent(struct btrfs_trans + return ret; + } + +-/* +- * when we wait for progress in the block group caching, its because +- * our allocation attempt failed at least once. So, we must sleep +- * and let some progress happen before we try again. +- * +- * This function will sleep at least once waiting for new free space to +- * show up, and then it will check the block group free space numbers +- * for our min num_bytes. Another option is to have it go ahead +- * and look in the rbtree for a free extent of a given size, but this +- * is a good start. +- * +- * Callers of this must check if cache->cached == BTRFS_CACHE_ERROR before using +- * any of the information in this block group. +- */ +-void btrfs_wait_block_group_cache_progress(struct btrfs_block_group_cache *cache, +- u64 num_bytes) +-{ +- struct btrfs_caching_control *caching_ctl; +- +- caching_ctl = btrfs_get_caching_control(cache); +- if (!caching_ctl) +- return; +- +- wait_event(caching_ctl->wait, btrfs_block_group_cache_done(cache) || +- (cache->free_space_ctl->free_space >= num_bytes)); +- +- btrfs_put_caching_control(caching_ctl); +-} +- +-int btrfs_wait_block_group_cache_done(struct btrfs_block_group_cache *cache) +-{ +- struct btrfs_caching_control *caching_ctl; +- int ret = 0; +- +- caching_ctl = btrfs_get_caching_control(cache); +- if (!caching_ctl) +- return (cache->cached == BTRFS_CACHE_ERROR) ? -EIO : 0; +- +- wait_event(caching_ctl->wait, btrfs_block_group_cache_done(cache)); +- if (cache->cached == BTRFS_CACHE_ERROR) +- ret = -EIO; +- btrfs_put_caching_control(caching_ctl); +- return ret; +-} +- + int __get_raid_index(u64 flags) + { + if (flags & BTRFS_BLOCK_GROUP_RAID10) +@@ -8053,8 +7592,7 @@ int btrfs_read_block_groups(struct btrfs + } else if (btrfs_block_group_used(&cache->item) == 0) { + cache->last_byte_to_unpin = (u64)-1; + cache->cached = BTRFS_CACHE_FINISHED; +- add_new_free_space(cache, info, +- found_key.objectid, ++ add_new_free_space(cache, found_key.objectid, + found_key.objectid + + found_key.offset); + btrfs_free_excluded_extents(cache); +@@ -8195,7 +7733,7 @@ int btrfs_make_block_group(struct btrfs_ + return ret; + } + +- add_new_free_space(cache, fs_info, chunk_offset, chunk_offset + size); ++ add_new_free_space(cache, chunk_offset, chunk_offset + size); + + btrfs_free_excluded_extents(cache); + +--- a/fs/btrfs/free-space-cache.c ++++ b/fs/btrfs/free-space-cache.c +@@ -830,9 +830,9 @@ free_cache: + goto out; + } + +-int load_free_space_cache(struct btrfs_fs_info *fs_info, +- struct btrfs_block_group_cache *block_group) ++int load_free_space_cache(struct btrfs_block_group_cache *block_group) + { ++ struct btrfs_fs_info *fs_info = block_group->fs_info; + struct btrfs_free_space_ctl *ctl = block_group->free_space_ctl; + struct inode *inode; + struct btrfs_path *path; +--- a/fs/btrfs/free-space-cache.h ++++ b/fs/btrfs/free-space-cache.h +@@ -64,8 +64,7 @@ int btrfs_check_trunc_cache_free_space(s + int btrfs_truncate_free_space_cache(struct btrfs_trans_handle *trans, + struct btrfs_block_group_cache *block_group, + struct inode *inode); +-int load_free_space_cache(struct btrfs_fs_info *fs_info, +- struct btrfs_block_group_cache *block_group); ++int load_free_space_cache(struct btrfs_block_group_cache *block_group); + int btrfs_wait_cache_io(struct btrfs_trans_handle *trans, + struct btrfs_block_group_cache *block_group, + struct btrfs_path *path); +--- a/fs/btrfs/free-space-tree.c ++++ b/fs/btrfs/free-space-tree.c +@@ -1465,7 +1465,6 @@ static int load_free_space_bitmaps(struc + extent_start = offset; + } else if (prev_bit == 1 && bit == 0) { + total_found += add_new_free_space(block_group, +- fs_info, + extent_start, + offset); + if (total_found > CACHING_CTL_WAKE_UP) { +@@ -1479,8 +1478,8 @@ static int load_free_space_bitmaps(struc + } + } + if (prev_bit == 1) { +- total_found += add_new_free_space(block_group, fs_info, +- extent_start, end); ++ total_found += add_new_free_space(block_group, extent_start, ++ end); + extent_count++; + } + +@@ -1537,7 +1536,7 @@ static int load_free_space_extents(struc + + caching_ctl->progress = key.objectid; + +- total_found += add_new_free_space(block_group, fs_info, ++ total_found += add_new_free_space(block_group, + key.objectid, + key.objectid + key.offset); + if (total_found > CACHING_CTL_WAKE_UP) { diff --git a/patches.suse/0011-btrfs-move-reserve_metadata_bytes-and-supporting-code-to-space-info-c.patch b/patches.suse/0011-btrfs-move-reserve_metadata_bytes-and-supporting-code-to-space-info-c.patch new file mode 100644 index 0000000..288cf2e --- /dev/null +++ b/patches.suse/0011-btrfs-move-reserve_metadata_bytes-and-supporting-code-to-space-info-c.patch @@ -0,0 +1,1478 @@ +From: Josef Bacik +Date: Tue, 18 Jun 2019 16:09:25 -0400 +Subject: btrfs: move reserve_metadata_bytes and supporting code to space-info.c +Git-commit: 0d9764f6d0fb9dd4d4b773b481f259c0567870c2 +Patch-mainline: v5.3-rc1 +References: bsc#1165949 + +This moves all of the metadata reservation code into space-info.c. + +Reviewed-by: Nikolay Borisov +Signed-off-by: Josef Bacik +Signed-off-by: David Sterba +Acked-by: Nikolay Borisov +--- + fs/btrfs/extent-tree.c | 696 ------------------------------------------------- + fs/btrfs/space-info.c | 687 ++++++++++++++++++++++++++++++++++++++++++++++++ + fs/btrfs/space-info.h | 4 + 3 files changed, 696 insertions(+), 691 deletions(-) + +--- a/fs/btrfs/extent-tree.c ++++ b/fs/btrfs/extent-tree.c +@@ -72,10 +72,6 @@ static int btrfs_add_reserved_bytes(stru + u64 ram_bytes, u64 num_bytes, int delalloc); + static int btrfs_free_reserved_bytes(struct btrfs_block_group_cache *cache, + u64 num_bytes, int delalloc); +-static int __reserve_metadata_bytes(struct btrfs_root *root, +- struct btrfs_space_info *space_info, +- u64 orig_bytes, +- enum btrfs_reserve_flush_enum flush); + + static noinline int + block_group_cache_done(struct btrfs_block_group_cache *cache) +@@ -4578,688 +4574,6 @@ out: + return ret; + } + +-static void btrfs_writeback_inodes_sb_nr(struct btrfs_fs_info *fs_info, +- unsigned long nr_pages, int nr_items) +-{ +- struct super_block *sb = fs_info->sb; +- +- if (down_read_trylock(&sb->s_umount)) { +- writeback_inodes_sb_nr(sb, nr_pages, WB_REASON_FS_FREE_SPACE); +- up_read(&sb->s_umount); +- } else { +- /* +- * We needn't worry the filesystem going from r/w to r/o though +- * we don't acquire ->s_umount mutex, because the filesystem +- * should guarantee the delalloc inodes list be empty after +- * the filesystem is readonly(all dirty pages are written to +- * the disk). +- */ +- btrfs_start_delalloc_roots(fs_info, 0, nr_items); +- if (!current->journal_info) +- btrfs_wait_ordered_roots(fs_info, nr_items, 0, (u64)-1); +- } +-} +- +-static inline u64 calc_reclaim_items_nr(struct btrfs_fs_info *fs_info, +- u64 to_reclaim) +-{ +- u64 bytes; +- u64 nr; +- +- bytes = btrfs_calc_trans_metadata_size(fs_info, 1); +- nr = div64_u64(to_reclaim, bytes); +- if (!nr) +- nr = 1; +- return nr; +-} +- +-#define EXTENT_SIZE_PER_ITEM SZ_256K +- +-/* +- * shrink metadata reservation for delalloc +- */ +-static void shrink_delalloc(struct btrfs_root *root, u64 to_reclaim, u64 orig, +- bool wait_ordered) +-{ +- struct btrfs_fs_info *fs_info = root->fs_info; +- struct btrfs_space_info *space_info; +- struct btrfs_trans_handle *trans; +- u64 delalloc_bytes; +- u64 dio_bytes; +- u64 max_reclaim; +- u64 items; +- long time_left; +- unsigned long nr_pages; +- int loops; +- enum btrfs_reserve_flush_enum flush; +- +- /* Calc the number of the pages we need flush for space reservation */ +- items = calc_reclaim_items_nr(fs_info, to_reclaim); +- to_reclaim = items * EXTENT_SIZE_PER_ITEM; +- +- trans = (struct btrfs_trans_handle *)current->journal_info; +- space_info = btrfs_find_space_info(fs_info, BTRFS_BLOCK_GROUP_METADATA); +- +- delalloc_bytes = percpu_counter_sum_positive( +- &fs_info->delalloc_bytes); +- dio_bytes = percpu_counter_sum_positive(&fs_info->dio_bytes); +- if (delalloc_bytes == 0 && dio_bytes == 0) { +- if (trans) +- return; +- if (wait_ordered) +- btrfs_wait_ordered_roots(fs_info, items, 0, (u64)-1); +- return; +- } +- +- /* +- * If we are doing more ordered than delalloc we need to just wait on +- * ordered extents, otherwise we'll waste time trying to flush delalloc +- * that likely won't give us the space back we need. +- */ +- if (dio_bytes > delalloc_bytes) +- wait_ordered = true; +- +- loops = 0; +- while ((delalloc_bytes || dio_bytes) && loops < 3) { +- max_reclaim = min(delalloc_bytes, to_reclaim); +- nr_pages = max_reclaim >> PAGE_SHIFT; +- btrfs_writeback_inodes_sb_nr(fs_info, nr_pages, items); +- /* +- * We need to wait for the async pages to actually start before +- * we do anything. +- */ +- max_reclaim = atomic_read(&fs_info->async_delalloc_pages); +- if (!max_reclaim) +- goto skip_async; +- +- if (max_reclaim <= nr_pages) +- max_reclaim = 0; +- else +- max_reclaim -= nr_pages; +- +- wait_event(fs_info->async_submit_wait, +- atomic_read(&fs_info->async_delalloc_pages) <= +- (int)max_reclaim); +-skip_async: +- if (!trans) +- flush = BTRFS_RESERVE_FLUSH_ALL; +- else +- flush = BTRFS_RESERVE_NO_FLUSH; +- spin_lock(&space_info->lock); +- if (list_empty(&space_info->tickets) && +- list_empty(&space_info->priority_tickets)) { +- spin_unlock(&space_info->lock); +- break; +- } +- spin_unlock(&space_info->lock); +- +- loops++; +- if (wait_ordered && !trans) { +- btrfs_wait_ordered_roots(fs_info, items, 0, (u64)-1); +- } else { +- time_left = schedule_timeout_killable(1); +- if (time_left) +- break; +- } +- delalloc_bytes = percpu_counter_sum_positive( +- &fs_info->delalloc_bytes); +- dio_bytes = percpu_counter_sum_positive(&fs_info->dio_bytes); +- } +-} +- +-/** +- * maybe_commit_transaction - possibly commit the transaction if its ok to +- * @root - the root we're allocating for +- * @bytes - the number of bytes we want to reserve +- * @force - force the commit +- * +- * This will check to make sure that committing the transaction will actually +- * get us somewhere and then commit the transaction if it does. Otherwise it +- * will return -ENOSPC. +- */ +-static int may_commit_transaction(struct btrfs_fs_info *fs_info, +- struct btrfs_space_info *space_info) +-{ +- struct reserve_ticket *ticket = NULL; +- struct btrfs_block_rsv *delayed_rsv = &fs_info->delayed_block_rsv; +- struct btrfs_block_rsv *delayed_refs_rsv = &fs_info->delayed_refs_rsv; +- struct btrfs_trans_handle *trans; +- u64 bytes_needed; +- u64 reclaim_bytes = 0; +- +- trans = (struct btrfs_trans_handle *)current->journal_info; +- if (trans) +- return -EAGAIN; +- +- spin_lock(&space_info->lock); +- if (!list_empty(&space_info->priority_tickets)) +- ticket = list_first_entry(&space_info->priority_tickets, +- struct reserve_ticket, list); +- else if (!list_empty(&space_info->tickets)) +- ticket = list_first_entry(&space_info->tickets, +- struct reserve_ticket, list); +- bytes_needed = (ticket) ? ticket->bytes : 0; +- spin_unlock(&space_info->lock); +- +- if (!bytes_needed) +- return 0; +- trans = btrfs_join_transaction(fs_info->extent_root); +- if (IS_ERR(trans)) +- return PTR_ERR(trans); +- +- /* +- * See if there is enough pinned space to make this reservation, or if +- * we have block groups that are going to be freed, allowing us to +- * possibly do a chunk allocation the next loop through. +- */ +- if (test_bit(BTRFS_TRANS_HAVE_FREE_BGS, &trans->transaction->flags) || +- percpu_counter_compare(&space_info->total_bytes_pinned, +- bytes_needed) >= 0) +- goto commit; +- +- /* +- * See if there is some space in the delayed insertion reservation for +- * this reservation. +- */ +- if (space_info != delayed_rsv->space_info) +- goto enospc; +- +- spin_lock(&delayed_rsv->lock); +- reclaim_bytes += delayed_rsv->reserved; +- spin_unlock(&delayed_rsv->lock); +- +- spin_lock(&delayed_refs_rsv->lock); +- reclaim_bytes += delayed_refs_rsv->reserved; +- spin_unlock(&delayed_refs_rsv->lock); +- if (reclaim_bytes >= bytes_needed) +- goto commit; +- bytes_needed -= reclaim_bytes; +- +- if (percpu_counter_compare(&space_info->total_bytes_pinned, +- bytes_needed) < 0) { +- goto enospc; +- } +- +-commit: +- return btrfs_commit_transaction(trans); +-enospc: +- btrfs_end_transaction(trans); +- return -ENOSPC; +-} +- +-static int flush_space(struct btrfs_fs_info *fs_info, +- struct btrfs_space_info *space_info, u64 num_bytes, +- int state) +-{ +- struct btrfs_root *root = fs_info->extent_root; +- struct btrfs_trans_handle *trans; +- int nr; +- int ret = 0; +- +- switch (state) { +- case FLUSH_DELAYED_ITEMS_NR: +- case FLUSH_DELAYED_ITEMS: +- if (state == FLUSH_DELAYED_ITEMS_NR) +- nr = calc_reclaim_items_nr(fs_info, num_bytes) * 2; +- else +- nr = -1; +- +- trans = btrfs_join_transaction(root); +- if (IS_ERR(trans)) { +- ret = PTR_ERR(trans); +- break; +- } +- ret = btrfs_run_delayed_items_nr(trans, fs_info, nr); +- btrfs_end_transaction(trans); +- break; +- case FLUSH_DELALLOC: +- case FLUSH_DELALLOC_WAIT: +- shrink_delalloc(root, num_bytes * 2, num_bytes, +- state == FLUSH_DELALLOC_WAIT); +- break; +- case FLUSH_DELAYED_REFS_NR: +- case FLUSH_DELAYED_REFS: +- trans = btrfs_join_transaction(root); +- if (IS_ERR(trans)) { +- ret = PTR_ERR(trans); +- break; +- } +- if (state == FLUSH_DELAYED_REFS_NR) +- nr = calc_reclaim_items_nr(fs_info, num_bytes); +- else +- nr = 0; +- btrfs_run_delayed_refs(trans, trans->fs_info, nr); +- btrfs_end_transaction(trans); +- break; +- case ALLOC_CHUNK: +- case ALLOC_CHUNK_FORCE: +- trans = btrfs_join_transaction(root); +- if (IS_ERR(trans)) { +- ret = PTR_ERR(trans); +- break; +- } +- ret = btrfs_chunk_alloc(trans, +- btrfs_metadata_alloc_profile(fs_info), +- (state == ALLOC_CHUNK) ? +- CHUNK_ALLOC_NO_FORCE : CHUNK_ALLOC_FORCE); +- btrfs_end_transaction(trans); +- if (ret > 0 || ret == -ENOSPC) +- ret = 0; +- break; +- case COMMIT_TRANS: +- /* +- * If we have pending delayed iputs then we could free up a +- * bunch of pinned space, so make sure we run the iputs before +- * we do our pinned bytes check below. +- */ +- btrfs_run_delayed_iputs(fs_info); +- btrfs_wait_on_delayed_iputs(fs_info); +- +- ret = may_commit_transaction(fs_info, space_info); +- break; +- default: +- ret = -ENOSPC; +- break; +- } +- +- trace_btrfs_flush_space(fs_info, space_info->flags, num_bytes, state, +- ret); +- return ret; +-} +- +-static inline u64 +-btrfs_calc_reclaim_metadata_size(struct btrfs_root *root, +- struct btrfs_space_info *space_info) +-{ +- struct reserve_ticket *ticket; +- u64 used; +- u64 expected; +- u64 to_reclaim = 0; +- +- list_for_each_entry(ticket, &space_info->tickets, list) +- to_reclaim += ticket->bytes; +- list_for_each_entry(ticket, &space_info->priority_tickets, list) +- to_reclaim += ticket->bytes; +- if (to_reclaim) +- return to_reclaim; +- +- to_reclaim = min_t(u64, num_online_cpus() * SZ_1M, SZ_16M); +- if (btrfs_can_overcommit(root, space_info, to_reclaim, +- BTRFS_RESERVE_FLUSH_ALL)) +- return 0; +- +- used = space_info->bytes_used + space_info->bytes_reserved + +- space_info->bytes_pinned + space_info->bytes_readonly + +- space_info->bytes_may_use; +- if (btrfs_can_overcommit(root, space_info, SZ_1M, BTRFS_RESERVE_FLUSH_ALL)) +- expected = div_factor_fine(space_info->total_bytes, 95); +- else +- expected = div_factor_fine(space_info->total_bytes, 90); +- +- if (used > expected) +- to_reclaim = used - expected; +- else +- to_reclaim = 0; +- to_reclaim = min(to_reclaim, space_info->bytes_may_use + +- space_info->bytes_reserved); +- return to_reclaim; +-} +- +-static inline int need_do_async_reclaim(struct btrfs_space_info *space_info, +- struct btrfs_root *root, u64 used) +-{ +- struct btrfs_fs_info *fs_info = root->fs_info; +- u64 thresh = div_factor_fine(space_info->total_bytes, 98); +- +- /* If we're just plain full then async reclaim just slows us down. */ +- if ((space_info->bytes_used + space_info->bytes_reserved) >= thresh) +- return 0; +- +- if (!btrfs_calc_reclaim_metadata_size(root, space_info)) +- return 0; +- +- return (used >= thresh && !btrfs_fs_closing(fs_info) && +- !test_bit(BTRFS_FS_STATE_REMOUNTING, &fs_info->fs_state)); +-} +- +-static bool wake_all_tickets(struct list_head *head) +-{ +- struct reserve_ticket *ticket; +- +- while (!list_empty(head)) { +- ticket = list_first_entry(head, struct reserve_ticket, list); +- list_del_init(&ticket->list); +- ticket->error = -ENOSPC; +- wake_up(&ticket->wait); +- if (ticket->bytes != ticket->orig_bytes) +- return true; +- } +- return false; +-} +- +-/* +- * This is for normal flushers, we can wait all goddamned day if we want to. We +- * will loop and continuously try to flush as long as we are making progress. +- * We count progress as clearing off tickets each time we have to loop. +- */ +-static void btrfs_async_reclaim_metadata_space(struct work_struct *work) +-{ +- struct btrfs_fs_info *fs_info; +- struct btrfs_space_info *space_info; +- u64 to_reclaim; +- int flush_state; +- int commit_cycles = 0; +- u64 last_tickets_id; +- +- fs_info = container_of(work, struct btrfs_fs_info, async_reclaim_work); +- space_info = btrfs_find_space_info(fs_info, BTRFS_BLOCK_GROUP_METADATA); +- +- spin_lock(&space_info->lock); +- to_reclaim = btrfs_calc_reclaim_metadata_size(fs_info->fs_root, +- space_info); +- if (!to_reclaim) { +- space_info->flush = 0; +- spin_unlock(&space_info->lock); +- return; +- } +- last_tickets_id = space_info->tickets_id; +- spin_unlock(&space_info->lock); +- +- flush_state = FLUSH_DELAYED_ITEMS_NR; +- do { +- struct reserve_ticket *ticket; +- int ret; +- +- ret = flush_space(fs_info, space_info, to_reclaim, flush_state); +- spin_lock(&space_info->lock); +- if (list_empty(&space_info->tickets)) { +- space_info->flush = 0; +- spin_unlock(&space_info->lock); +- return; +- } +- to_reclaim = btrfs_calc_reclaim_metadata_size(fs_info->fs_root, +- space_info); +- ticket = list_first_entry(&space_info->tickets, +- struct reserve_ticket, list); +- if (last_tickets_id == space_info->tickets_id) { +- flush_state++; +- } else { +- last_tickets_id = space_info->tickets_id; +- flush_state = FLUSH_DELAYED_ITEMS_NR; +- if (commit_cycles) +- commit_cycles--; +- } +- +- /* +- * We don't want to force a chunk allocation until we've tried +- * pretty hard to reclaim space. Think of the case where we +- * freed up a bunch of space and so have a lot of pinned space +- * to reclaim. We would rather use that than possibly create a +- * underutilized metadata chunk. So if this is our first run +- * through the flushing state machine skip ALLOC_CHUNK_FORCE and +- * commit the transaction. If nothing has changed the next go +- * around then we can force a chunk allocation. +- */ +- if (flush_state == ALLOC_CHUNK_FORCE && !commit_cycles) +- flush_state++; +- +- if (flush_state > COMMIT_TRANS) { +- commit_cycles++; +- if (commit_cycles > 2) { +- if (wake_all_tickets(&space_info->tickets)) { +- flush_state = FLUSH_DELAYED_ITEMS_NR; +- commit_cycles--; +- } else { +- space_info->flush = 0; +- } +- } else { +- flush_state = FLUSH_DELAYED_ITEMS_NR; +- } +- } +- spin_unlock(&space_info->lock); +- } while (flush_state <= COMMIT_TRANS); +-} +- +-void btrfs_init_async_reclaim_work(struct work_struct *work) +-{ +- INIT_WORK(work, btrfs_async_reclaim_metadata_space); +-} +- +-static const enum btrfs_flush_state priority_flush_states[] = { +- FLUSH_DELAYED_ITEMS_NR, +- FLUSH_DELAYED_ITEMS, +- ALLOC_CHUNK, +-}; +- +-static void priority_reclaim_metadata_space(struct btrfs_fs_info *fs_info, +- struct btrfs_space_info *space_info, +- struct reserve_ticket *ticket) +-{ +- u64 to_reclaim; +- int flush_state; +- +- spin_lock(&space_info->lock); +- to_reclaim = btrfs_calc_reclaim_metadata_size(fs_info->extent_root, +- space_info); +- if (!to_reclaim) { +- spin_unlock(&space_info->lock); +- return; +- } +- spin_unlock(&space_info->lock); +- +- flush_state = 0; +- do { +- flush_space(fs_info, space_info, to_reclaim, +- priority_flush_states[flush_state]); +- flush_state++; +- spin_lock(&space_info->lock); +- if (ticket->bytes == 0) { +- spin_unlock(&space_info->lock); +- return; +- } +- spin_unlock(&space_info->lock); +- } while (flush_state < ARRAY_SIZE(priority_flush_states)); +-} +- +-static int wait_reserve_ticket(struct btrfs_fs_info *fs_info, +- struct btrfs_space_info *space_info, +- struct reserve_ticket *ticket) +- +-{ +- DEFINE_WAIT(wait); +- u64 reclaim_bytes = 0; +- int ret = 0; +- +- spin_lock(&space_info->lock); +- while (ticket->bytes > 0 && ticket->error == 0) { +- ret = prepare_to_wait_event(&ticket->wait, &wait, TASK_KILLABLE); +- if (ret) { +- ret = -EINTR; +- break; +- } +- spin_unlock(&space_info->lock); +- +- schedule(); +- +- finish_wait(&ticket->wait, &wait); +- spin_lock(&space_info->lock); +- } +- if (!ret) +- ret = ticket->error; +- if (!list_empty(&ticket->list)) +- list_del_init(&ticket->list); +- if (ticket->bytes && ticket->bytes < ticket->orig_bytes) +- reclaim_bytes = ticket->orig_bytes - ticket->bytes; +- spin_unlock(&space_info->lock); +- +- if (reclaim_bytes) +- btrfs_space_info_add_old_bytes(fs_info, space_info, +- reclaim_bytes); +- return ret; +-} +- +-/** +- * reserve_metadata_bytes - try to reserve bytes from the block_rsv's space +- * @root - the root we're allocating for +- * @space_info - the space info we want to allocate from +- * @orig_bytes - the number of bytes we want +- * @flush - whether or not we can flush to make our reservation +- * +- * This will reserve orig_bytes number of bytes from the space info associated +- * with the block_rsv. If there is not enough space it will make an attempt to +- * flush out space to make room. It will do this by flushing delalloc if +- * possible or committing the transaction. If flush is 0 then no attempts to +- * regain reservations will be made and this will fail if there is not enough +- * space already. +- */ +-static int __reserve_metadata_bytes(struct btrfs_root *root, +- struct btrfs_space_info *space_info, +- u64 orig_bytes, +- enum btrfs_reserve_flush_enum flush) +-{ +- struct btrfs_fs_info *fs_info = root->fs_info; +- struct reserve_ticket ticket; +- u64 used; +- u64 reclaim_bytes = 0; +- int ret = 0; +- +- ASSERT(orig_bytes); +- ASSERT(!current->journal_info || flush != BTRFS_RESERVE_FLUSH_ALL); +- +- spin_lock(&space_info->lock); +- ret = -ENOSPC; +- used = btrfs_space_info_used(space_info, true); +- +- /* +- * If we have enough space then hooray, make our reservation and carry +- * on. If not see if we can overcommit, and if we can, hooray carry on. +- * If not things get more complicated. +- */ +- if (used + orig_bytes <= space_info->total_bytes) { +- btrfs_space_info_update_bytes_may_use(fs_info, space_info, +- orig_bytes); +- trace_btrfs_space_reservation(fs_info, "space_info", +- space_info->flags, orig_bytes, 1); +- ret = 0; +- } else if (btrfs_can_overcommit(root, space_info, orig_bytes, flush)) { +- btrfs_space_info_update_bytes_may_use(fs_info, space_info, +- orig_bytes); +- trace_btrfs_space_reservation(fs_info, "space_info", +- space_info->flags, orig_bytes, 1); +- ret = 0; +- } +- +- /* +- * If we couldn't make a reservation then setup our reservation ticket +- * and kick the async worker if it's not already running. +- * +- * If we are a priority flusher then we just need to add our ticket to +- * the list and we will do our own flushing further down. +- */ +- if (ret && flush != BTRFS_RESERVE_NO_FLUSH) { +- ticket.orig_bytes = orig_bytes; +- ticket.bytes = orig_bytes; +- ticket.error = 0; +- init_waitqueue_head(&ticket.wait); +- if (flush == BTRFS_RESERVE_FLUSH_ALL) { +- list_add_tail(&ticket.list, &space_info->tickets); +- if (!space_info->flush) { +- space_info->flush = 1; +- trace_btrfs_trigger_flush(fs_info, +- space_info->flags, +- orig_bytes, flush, +- "enospc"); +- queue_work(system_unbound_wq, +- &root->fs_info->async_reclaim_work); +- } +- } else { +- list_add_tail(&ticket.list, +- &space_info->priority_tickets); +- } +- } else if (!ret && space_info->flags & BTRFS_BLOCK_GROUP_METADATA) { +- used += orig_bytes; +- /* +- * We will do the space reservation dance during log replay, +- * which means we won't have fs_info->fs_root set, so don't do +- * the async reclaim as we will panic. +- */ +- if (!test_bit(BTRFS_FS_LOG_RECOVERING, &fs_info->flags) && +- need_do_async_reclaim(space_info, root, used) && +- !work_busy(&fs_info->async_reclaim_work)) { +- trace_btrfs_trigger_flush(fs_info, space_info->flags, +- orig_bytes, flush, "preempt"); +- queue_work(system_unbound_wq, +- &fs_info->async_reclaim_work); +- } +- } +- spin_unlock(&space_info->lock); +- if (!ret || flush == BTRFS_RESERVE_NO_FLUSH) +- return ret; +- +- if (flush == BTRFS_RESERVE_FLUSH_ALL) +- return wait_reserve_ticket(fs_info, space_info, &ticket); +- +- ret = 0; +- priority_reclaim_metadata_space(fs_info, space_info, &ticket); +- spin_lock(&space_info->lock); +- if (ticket.bytes) { +- if (ticket.bytes < orig_bytes) +- reclaim_bytes = orig_bytes - ticket.bytes; +- list_del_init(&ticket.list); +- ret = -ENOSPC; +- } +- spin_unlock(&space_info->lock); +- +- if (reclaim_bytes) +- btrfs_space_info_add_old_bytes(fs_info, space_info, +- reclaim_bytes); +- ASSERT(list_empty(&ticket.list)); +- return ret; +-} +- +-/** +- * reserve_metadata_bytes - try to reserve bytes from the block_rsv's space +- * @root - the root we're allocating for +- * @block_rsv - the block_rsv we're allocating for +- * @orig_bytes - the number of bytes we want +- * @flush - whether or not we can flush to make our reservation +- * +- * This will reserve orgi_bytes number of bytes from the space info associated +- * with the block_rsv. If there is not enough space it will make an attempt to +- * flush out space to make room. It will do this by flushing delalloc if +- * possible or committing the transaction. If flush is 0 then no attempts to +- * regain reservations will be made and this will fail if there is not enough +- * space already. +- */ +-static int reserve_metadata_bytes(struct btrfs_root *root, +- struct btrfs_block_rsv *block_rsv, +- u64 orig_bytes, +- enum btrfs_reserve_flush_enum flush) +-{ +- struct btrfs_fs_info *fs_info = root->fs_info; +- struct btrfs_block_rsv *global_rsv = &fs_info->global_block_rsv; +- int ret; +- +- ret = __reserve_metadata_bytes(root, block_rsv->space_info, orig_bytes, +- flush); +- if (ret == -ENOSPC && +- unlikely(root->orphan_cleanup_state == ORPHAN_CLEANUP_STARTED)) { +- if (block_rsv != global_rsv && +- !btrfs_block_rsv_use_bytes(global_rsv, orig_bytes)) +- ret = 0; +- } +- if (ret == -ENOSPC) { +- trace_btrfs_space_reservation(fs_info, "space_info:enospc", +- block_rsv->space_info->flags, +- orig_bytes, 1); +- +- if (btrfs_test_opt(fs_info, ENOSPC_DEBUG)) +- btrfs_dump_space_info(fs_info, block_rsv->space_info, +- orig_bytes, 0); +- } +- return ret; +-} +- + static struct btrfs_block_rsv *get_block_rsv( + const struct btrfs_trans_handle *trans, + const struct btrfs_root *root) +@@ -5406,7 +4720,7 @@ int btrfs_delayed_refs_rsv_refill(struct + if (!num_bytes) + return 0; + +- ret = reserve_metadata_bytes(fs_info->extent_root, block_rsv, ++ ret = btrfs_reserve_metadata_bytes(fs_info->extent_root, block_rsv, + num_bytes, flush); + if (ret) + return ret; +@@ -5538,7 +4852,7 @@ int btrfs_block_rsv_add(struct btrfs_roo + if (num_bytes == 0) + return 0; + +- ret = reserve_metadata_bytes(root, block_rsv, num_bytes, flush); ++ ret = btrfs_reserve_metadata_bytes(root, block_rsv, num_bytes, flush); + if (!ret) { + block_rsv_add_bytes(block_rsv, num_bytes, 1); + return 0; +@@ -5585,7 +4899,7 @@ int btrfs_block_rsv_refill(struct btrfs_ + if (!ret) + return 0; + +- ret = reserve_metadata_bytes(root, block_rsv, num_bytes, flush); ++ ret = btrfs_reserve_metadata_bytes(root, block_rsv, num_bytes, flush); + if (!ret) { + block_rsv_add_bytes(block_rsv, num_bytes, 0); + return 0; +@@ -5982,7 +5296,7 @@ int btrfs_delalloc_reserve_metadata(stru + ret = btrfs_qgroup_reserve_meta_prealloc(root, qgroup_reserve, true); + if (ret) + goto out_fail; +- ret = reserve_metadata_bytes(root, block_rsv, meta_reserve, flush); ++ ret = btrfs_reserve_metadata_bytes(root, block_rsv, meta_reserve, flush); + if (ret) + goto out_qgroup; + +@@ -8233,7 +7547,7 @@ again: + "BTRFS: block rsv returned %d\n", ret); + } + try_reserve: +- ret = reserve_metadata_bytes(root, block_rsv, blocksize, ++ ret = btrfs_reserve_metadata_bytes(root, block_rsv, blocksize, + BTRFS_RESERVE_NO_FLUSH); + if (!ret) + return block_rsv; +--- a/fs/btrfs/space-info.c ++++ b/fs/btrfs/space-info.c +@@ -5,6 +5,9 @@ + #include "sysfs.h" + #include "volumes.h" + #include "free-space-cache.h" ++#include "ordered-data.h" ++#include "transaction.h" ++#include "math.h" + + u64 btrfs_space_info_used(struct btrfs_space_info *s_info, + bool may_use_included) +@@ -403,3 +406,687 @@ again: + goto again; + up_read(&info->groups_sem); + } ++ ++static void btrfs_writeback_inodes_sb_nr(struct btrfs_fs_info *fs_info, ++ unsigned long nr_pages, int nr_items) ++{ ++ struct super_block *sb = fs_info->sb; ++ ++ if (down_read_trylock(&sb->s_umount)) { ++ writeback_inodes_sb_nr(sb, nr_pages, WB_REASON_FS_FREE_SPACE); ++ up_read(&sb->s_umount); ++ } else { ++ /* ++ * We needn't worry the filesystem going from r/w to r/o though ++ * we don't acquire ->s_umount mutex, because the filesystem ++ * should guarantee the delalloc inodes list be empty after ++ * the filesystem is readonly(all dirty pages are written to ++ * the disk). ++ */ ++ btrfs_start_delalloc_roots(fs_info, 0, nr_items); ++ if (!current->journal_info) ++ btrfs_wait_ordered_roots(fs_info, nr_items, 0, (u64)-1); ++ } ++} ++ ++ ++static inline u64 calc_reclaim_items_nr(struct btrfs_fs_info *fs_info, ++ u64 to_reclaim) ++{ ++ u64 bytes; ++ u64 nr; ++ ++ bytes = btrfs_calc_trans_metadata_size(fs_info, 1); ++ nr = div64_u64(to_reclaim, bytes); ++ if (!nr) ++ nr = 1; ++ return nr; ++} ++ ++#define EXTENT_SIZE_PER_ITEM SZ_256K ++ ++/* ++ * shrink metadata reservation for delalloc ++ */ ++static void shrink_delalloc(struct btrfs_root *root, u64 to_reclaim, u64 orig, ++ bool wait_ordered) ++{ ++ struct btrfs_fs_info *fs_info = root->fs_info; ++ struct btrfs_space_info *space_info; ++ struct btrfs_trans_handle *trans; ++ u64 delalloc_bytes; ++ u64 dio_bytes; ++ u64 max_reclaim; ++ u64 items; ++ long time_left; ++ unsigned long nr_pages; ++ int loops; ++ enum btrfs_reserve_flush_enum flush; ++ ++ /* Calc the number of the pages we need flush for space reservation */ ++ items = calc_reclaim_items_nr(fs_info, to_reclaim); ++ to_reclaim = items * EXTENT_SIZE_PER_ITEM; ++ ++ trans = (struct btrfs_trans_handle *)current->journal_info; ++ space_info = btrfs_find_space_info(fs_info, BTRFS_BLOCK_GROUP_METADATA); ++ ++ delalloc_bytes = percpu_counter_sum_positive( ++ &fs_info->delalloc_bytes); ++ dio_bytes = percpu_counter_sum_positive(&fs_info->dio_bytes); ++ if (delalloc_bytes == 0 && dio_bytes == 0) { ++ if (trans) ++ return; ++ if (wait_ordered) ++ btrfs_wait_ordered_roots(fs_info, items, 0, (u64)-1); ++ return; ++ } ++ ++ /* ++ * If we are doing more ordered than delalloc we need to just wait on ++ * ordered extents, otherwise we'll waste time trying to flush delalloc ++ * that likely won't give us the space back we need. ++ */ ++ if (dio_bytes > delalloc_bytes) ++ wait_ordered = true; ++ ++ loops = 0; ++ while ((delalloc_bytes || dio_bytes) && loops < 3) { ++ max_reclaim = min(delalloc_bytes, to_reclaim); ++ nr_pages = max_reclaim >> PAGE_SHIFT; ++ btrfs_writeback_inodes_sb_nr(fs_info, nr_pages, items); ++ /* ++ * We need to wait for the async pages to actually start before ++ * we do anything. ++ */ ++ max_reclaim = atomic_read(&fs_info->async_delalloc_pages); ++ if (!max_reclaim) ++ goto skip_async; ++ ++ if (max_reclaim <= nr_pages) ++ max_reclaim = 0; ++ else ++ max_reclaim -= nr_pages; ++ ++ wait_event(fs_info->async_submit_wait, ++ atomic_read(&fs_info->async_delalloc_pages) <= ++ (int)max_reclaim); ++skip_async: ++ if (!trans) ++ flush = BTRFS_RESERVE_FLUSH_ALL; ++ else ++ flush = BTRFS_RESERVE_NO_FLUSH; ++ spin_lock(&space_info->lock); ++ if (list_empty(&space_info->tickets) && ++ list_empty(&space_info->priority_tickets)) { ++ spin_unlock(&space_info->lock); ++ break; ++ } ++ spin_unlock(&space_info->lock); ++ ++ loops++; ++ if (wait_ordered && !trans) { ++ btrfs_wait_ordered_roots(fs_info, items, 0, (u64)-1); ++ } else { ++ time_left = schedule_timeout_killable(1); ++ if (time_left) ++ break; ++ } ++ delalloc_bytes = percpu_counter_sum_positive( ++ &fs_info->delalloc_bytes); ++ dio_bytes = percpu_counter_sum_positive(&fs_info->dio_bytes); ++ } ++} ++ ++/** ++ * maybe_commit_transaction - possibly commit the transaction if its ok to ++ * @root - the root we're allocating for ++ * @bytes - the number of bytes we want to reserve ++ * @force - force the commit ++ * ++ * This will check to make sure that committing the transaction will actually ++ * get us somewhere and then commit the transaction if it does. Otherwise it ++ * will return -ENOSPC. ++ */ ++static int may_commit_transaction(struct btrfs_fs_info *fs_info, ++ struct btrfs_space_info *space_info) ++{ ++ struct reserve_ticket *ticket = NULL; ++ struct btrfs_block_rsv *delayed_rsv = &fs_info->delayed_block_rsv; ++ struct btrfs_block_rsv *delayed_refs_rsv = &fs_info->delayed_refs_rsv; ++ struct btrfs_trans_handle *trans; ++ u64 bytes_needed; ++ u64 reclaim_bytes = 0; ++ ++ trans = (struct btrfs_trans_handle *)current->journal_info; ++ if (trans) ++ return -EAGAIN; ++ ++ spin_lock(&space_info->lock); ++ if (!list_empty(&space_info->priority_tickets)) ++ ticket = list_first_entry(&space_info->priority_tickets, ++ struct reserve_ticket, list); ++ else if (!list_empty(&space_info->tickets)) ++ ticket = list_first_entry(&space_info->tickets, ++ struct reserve_ticket, list); ++ bytes_needed = (ticket) ? ticket->bytes : 0; ++ spin_unlock(&space_info->lock); ++ ++ if (!bytes_needed) ++ return 0; ++ trans = btrfs_join_transaction(fs_info->extent_root); ++ if (IS_ERR(trans)) ++ return PTR_ERR(trans); ++ ++ /* ++ * See if there is enough pinned space to make this reservation, or if ++ * we have block groups that are going to be freed, allowing us to ++ * possibly do a chunk allocation the next loop through. ++ */ ++ if (test_bit(BTRFS_TRANS_HAVE_FREE_BGS, &trans->transaction->flags) || ++ percpu_counter_compare(&space_info->total_bytes_pinned, ++ bytes_needed) >= 0) ++ goto commit; ++ ++ /* ++ * See if there is some space in the delayed insertion reservation for ++ * this reservation. ++ */ ++ if (space_info != delayed_rsv->space_info) ++ goto enospc; ++ ++ spin_lock(&delayed_rsv->lock); ++ reclaim_bytes += delayed_rsv->reserved; ++ spin_unlock(&delayed_rsv->lock); ++ ++ spin_lock(&delayed_refs_rsv->lock); ++ reclaim_bytes += delayed_refs_rsv->reserved; ++ spin_unlock(&delayed_refs_rsv->lock); ++ if (reclaim_bytes >= bytes_needed) ++ goto commit; ++ bytes_needed -= reclaim_bytes; ++ ++ if (percpu_counter_compare(&space_info->total_bytes_pinned, ++ bytes_needed) < 0) { ++ goto enospc; ++ } ++ ++commit: ++ return btrfs_commit_transaction(trans); ++enospc: ++ btrfs_end_transaction(trans); ++ return -ENOSPC; ++} ++ ++static int flush_space(struct btrfs_fs_info *fs_info, ++ struct btrfs_space_info *space_info, u64 num_bytes, ++ int state) ++{ ++ struct btrfs_root *root = fs_info->extent_root; ++ struct btrfs_trans_handle *trans; ++ int nr; ++ int ret = 0; ++ ++ switch (state) { ++ case FLUSH_DELAYED_ITEMS_NR: ++ case FLUSH_DELAYED_ITEMS: ++ if (state == FLUSH_DELAYED_ITEMS_NR) ++ nr = calc_reclaim_items_nr(fs_info, num_bytes) * 2; ++ else ++ nr = -1; ++ ++ trans = btrfs_join_transaction(root); ++ if (IS_ERR(trans)) { ++ ret = PTR_ERR(trans); ++ break; ++ } ++ ret = btrfs_run_delayed_items_nr(trans, fs_info, nr); ++ btrfs_end_transaction(trans); ++ break; ++ case FLUSH_DELALLOC: ++ case FLUSH_DELALLOC_WAIT: ++ shrink_delalloc(root, num_bytes * 2, num_bytes, ++ state == FLUSH_DELALLOC_WAIT); ++ break; ++ case FLUSH_DELAYED_REFS_NR: ++ case FLUSH_DELAYED_REFS: ++ trans = btrfs_join_transaction(root); ++ if (IS_ERR(trans)) { ++ ret = PTR_ERR(trans); ++ break; ++ } ++ if (state == FLUSH_DELAYED_REFS_NR) ++ nr = calc_reclaim_items_nr(fs_info, num_bytes); ++ else ++ nr = 0; ++ btrfs_run_delayed_refs(trans, trans->fs_info, nr); ++ btrfs_end_transaction(trans); ++ break; ++ case ALLOC_CHUNK: ++ case ALLOC_CHUNK_FORCE: ++ trans = btrfs_join_transaction(root); ++ if (IS_ERR(trans)) { ++ ret = PTR_ERR(trans); ++ break; ++ } ++ ret = btrfs_chunk_alloc(trans, ++ btrfs_metadata_alloc_profile(fs_info), ++ (state == ALLOC_CHUNK) ? ++ CHUNK_ALLOC_NO_FORCE : CHUNK_ALLOC_FORCE); ++ btrfs_end_transaction(trans); ++ if (ret > 0 || ret == -ENOSPC) ++ ret = 0; ++ break; ++ case COMMIT_TRANS: ++ /* ++ * If we have pending delayed iputs then we could free up a ++ * bunch of pinned space, so make sure we run the iputs before ++ * we do our pinned bytes check below. ++ */ ++ btrfs_run_delayed_iputs(fs_info); ++ btrfs_wait_on_delayed_iputs(fs_info); ++ ++ ret = may_commit_transaction(fs_info, space_info); ++ break; ++ default: ++ ret = -ENOSPC; ++ break; ++ } ++ ++ trace_btrfs_flush_space(fs_info, space_info->flags, num_bytes, state, ++ ret); ++ return ret; ++} ++ ++static inline u64 ++btrfs_calc_reclaim_metadata_size(struct btrfs_root *root, ++ struct btrfs_space_info *space_info) ++{ ++ struct reserve_ticket *ticket; ++ u64 used; ++ u64 expected; ++ u64 to_reclaim = 0; ++ ++ list_for_each_entry(ticket, &space_info->tickets, list) ++ to_reclaim += ticket->bytes; ++ list_for_each_entry(ticket, &space_info->priority_tickets, list) ++ to_reclaim += ticket->bytes; ++ if (to_reclaim) ++ return to_reclaim; ++ ++ to_reclaim = min_t(u64, num_online_cpus() * SZ_1M, SZ_16M); ++ if (btrfs_can_overcommit(root, space_info, to_reclaim, ++ BTRFS_RESERVE_FLUSH_ALL)) ++ return 0; ++ ++ used = space_info->bytes_used + space_info->bytes_reserved + ++ space_info->bytes_pinned + space_info->bytes_readonly + ++ space_info->bytes_may_use; ++ if (btrfs_can_overcommit(root, space_info, SZ_1M, BTRFS_RESERVE_FLUSH_ALL)) ++ expected = div_factor_fine(space_info->total_bytes, 95); ++ else ++ expected = div_factor_fine(space_info->total_bytes, 90); ++ ++ if (used > expected) ++ to_reclaim = used - expected; ++ else ++ to_reclaim = 0; ++ to_reclaim = min(to_reclaim, space_info->bytes_may_use + ++ space_info->bytes_reserved); ++ return to_reclaim; ++} ++ ++static inline int need_do_async_reclaim(struct btrfs_space_info *space_info, ++ struct btrfs_root *root, u64 used) ++{ ++ struct btrfs_fs_info *fs_info = root->fs_info; ++ u64 thresh = div_factor_fine(space_info->total_bytes, 98); ++ ++ /* If we're just plain full then async reclaim just slows us down. */ ++ if ((space_info->bytes_used + space_info->bytes_reserved) >= thresh) ++ return 0; ++ ++ if (!btrfs_calc_reclaim_metadata_size(root, space_info)) ++ return 0; ++ ++ return (used >= thresh && !btrfs_fs_closing(fs_info) && ++ !test_bit(BTRFS_FS_STATE_REMOUNTING, &fs_info->fs_state)); ++} ++ ++static bool wake_all_tickets(struct list_head *head) ++{ ++ struct reserve_ticket *ticket; ++ ++ while (!list_empty(head)) { ++ ticket = list_first_entry(head, struct reserve_ticket, list); ++ list_del_init(&ticket->list); ++ ticket->error = -ENOSPC; ++ wake_up(&ticket->wait); ++ if (ticket->bytes != ticket->orig_bytes) ++ return true; ++ } ++ return false; ++} ++ ++/* ++ * This is for normal flushers, we can wait all goddamned day if we want to. We ++ * will loop and continuously try to flush as long as we are making progress. ++ * We count progress as clearing off tickets each time we have to loop. ++ */ ++static void btrfs_async_reclaim_metadata_space(struct work_struct *work) ++{ ++ struct btrfs_fs_info *fs_info; ++ struct btrfs_space_info *space_info; ++ u64 to_reclaim; ++ int flush_state; ++ int commit_cycles = 0; ++ u64 last_tickets_id; ++ ++ fs_info = container_of(work, struct btrfs_fs_info, async_reclaim_work); ++ space_info = btrfs_find_space_info(fs_info, BTRFS_BLOCK_GROUP_METADATA); ++ ++ spin_lock(&space_info->lock); ++ to_reclaim = btrfs_calc_reclaim_metadata_size(fs_info->fs_root, ++ space_info); ++ if (!to_reclaim) { ++ space_info->flush = 0; ++ spin_unlock(&space_info->lock); ++ return; ++ } ++ last_tickets_id = space_info->tickets_id; ++ spin_unlock(&space_info->lock); ++ ++ flush_state = FLUSH_DELAYED_ITEMS_NR; ++ do { ++ struct reserve_ticket *ticket; ++ int ret; ++ ++ ret = flush_space(fs_info, space_info, to_reclaim, flush_state); ++ spin_lock(&space_info->lock); ++ if (list_empty(&space_info->tickets)) { ++ space_info->flush = 0; ++ spin_unlock(&space_info->lock); ++ return; ++ } ++ to_reclaim = btrfs_calc_reclaim_metadata_size(fs_info->fs_root, ++ space_info); ++ ticket = list_first_entry(&space_info->tickets, ++ struct reserve_ticket, list); ++ if (last_tickets_id == space_info->tickets_id) { ++ flush_state++; ++ } else { ++ last_tickets_id = space_info->tickets_id; ++ flush_state = FLUSH_DELAYED_ITEMS_NR; ++ if (commit_cycles) ++ commit_cycles--; ++ } ++ ++ /* ++ * We don't want to force a chunk allocation until we've tried ++ * pretty hard to reclaim space. Think of the case where we ++ * freed up a bunch of space and so have a lot of pinned space ++ * to reclaim. We would rather use that than possibly create a ++ * underutilized metadata chunk. So if this is our first run ++ * through the flushing state machine skip ALLOC_CHUNK_FORCE and ++ * commit the transaction. If nothing has changed the next go ++ * around then we can force a chunk allocation. ++ */ ++ if (flush_state == ALLOC_CHUNK_FORCE && !commit_cycles) ++ flush_state++; ++ ++ if (flush_state > COMMIT_TRANS) { ++ commit_cycles++; ++ if (commit_cycles > 2) { ++ if (wake_all_tickets(&space_info->tickets)) { ++ flush_state = FLUSH_DELAYED_ITEMS_NR; ++ commit_cycles--; ++ } else { ++ space_info->flush = 0; ++ } ++ } else { ++ flush_state = FLUSH_DELAYED_ITEMS_NR; ++ } ++ } ++ spin_unlock(&space_info->lock); ++ } while (flush_state <= COMMIT_TRANS); ++} ++ ++void btrfs_init_async_reclaim_work(struct work_struct *work) ++{ ++ INIT_WORK(work, btrfs_async_reclaim_metadata_space); ++} ++ ++static const enum btrfs_flush_state priority_flush_states[] = { ++ FLUSH_DELAYED_ITEMS_NR, ++ FLUSH_DELAYED_ITEMS, ++ ALLOC_CHUNK, ++}; ++ ++static void priority_reclaim_metadata_space(struct btrfs_fs_info *fs_info, ++ struct btrfs_space_info *space_info, ++ struct reserve_ticket *ticket) ++{ ++ u64 to_reclaim; ++ int flush_state; ++ ++ spin_lock(&space_info->lock); ++ to_reclaim = btrfs_calc_reclaim_metadata_size(fs_info->extent_root, ++ space_info); ++ if (!to_reclaim) { ++ spin_unlock(&space_info->lock); ++ return; ++ } ++ spin_unlock(&space_info->lock); ++ ++ flush_state = 0; ++ do { ++ flush_space(fs_info, space_info, to_reclaim, ++ priority_flush_states[flush_state]); ++ flush_state++; ++ spin_lock(&space_info->lock); ++ if (ticket->bytes == 0) { ++ spin_unlock(&space_info->lock); ++ return; ++ } ++ spin_unlock(&space_info->lock); ++ } while (flush_state < ARRAY_SIZE(priority_flush_states)); ++} ++ ++static int wait_reserve_ticket(struct btrfs_fs_info *fs_info, ++ struct btrfs_space_info *space_info, ++ struct reserve_ticket *ticket) ++ ++{ ++ DEFINE_WAIT(wait); ++ u64 reclaim_bytes = 0; ++ int ret = 0; ++ ++ spin_lock(&space_info->lock); ++ while (ticket->bytes > 0 && ticket->error == 0) { ++ ret = prepare_to_wait_event(&ticket->wait, &wait, TASK_KILLABLE); ++ if (ret) { ++ ret = -EINTR; ++ break; ++ } ++ spin_unlock(&space_info->lock); ++ ++ schedule(); ++ ++ finish_wait(&ticket->wait, &wait); ++ spin_lock(&space_info->lock); ++ } ++ if (!ret) ++ ret = ticket->error; ++ if (!list_empty(&ticket->list)) ++ list_del_init(&ticket->list); ++ if (ticket->bytes && ticket->bytes < ticket->orig_bytes) ++ reclaim_bytes = ticket->orig_bytes - ticket->bytes; ++ spin_unlock(&space_info->lock); ++ ++ if (reclaim_bytes) ++ btrfs_space_info_add_old_bytes(fs_info, space_info, ++ reclaim_bytes); ++ return ret; ++} ++ ++/** ++ * reserve_metadata_bytes - try to reserve bytes from the block_rsv's space ++ * @root - the root we're allocating for ++ * @space_info - the space info we want to allocate from ++ * @orig_bytes - the number of bytes we want ++ * @flush - whether or not we can flush to make our reservation ++ * ++ * This will reserve orig_bytes number of bytes from the space info associated ++ * with the block_rsv. If there is not enough space it will make an attempt to ++ * flush out space to make room. It will do this by flushing delalloc if ++ * possible or committing the transaction. If flush is 0 then no attempts to ++ * regain reservations will be made and this will fail if there is not enough ++ * space already. ++ */ ++static int __reserve_metadata_bytes(struct btrfs_root *root, ++ struct btrfs_space_info *space_info, ++ u64 orig_bytes, ++ enum btrfs_reserve_flush_enum flush) ++{ ++ struct btrfs_fs_info *fs_info = root->fs_info; ++ struct reserve_ticket ticket; ++ u64 used; ++ u64 reclaim_bytes = 0; ++ int ret = 0; ++ ++ ASSERT(orig_bytes); ++ ASSERT(!current->journal_info || flush != BTRFS_RESERVE_FLUSH_ALL); ++ ++ spin_lock(&space_info->lock); ++ ret = -ENOSPC; ++ used = btrfs_space_info_used(space_info, true); ++ ++ /* ++ * If we have enough space then hooray, make our reservation and carry ++ * on. If not see if we can overcommit, and if we can, hooray carry on. ++ * If not things get more complicated. ++ */ ++ if (used + orig_bytes <= space_info->total_bytes) { ++ btrfs_space_info_update_bytes_may_use(fs_info, space_info, ++ orig_bytes); ++ trace_btrfs_space_reservation(fs_info, "space_info", ++ space_info->flags, orig_bytes, 1); ++ ret = 0; ++ } else if (btrfs_can_overcommit(root, space_info, orig_bytes, flush)) { ++ btrfs_space_info_update_bytes_may_use(fs_info, space_info, ++ orig_bytes); ++ trace_btrfs_space_reservation(fs_info, "space_info", ++ space_info->flags, orig_bytes, 1); ++ ret = 0; ++ } ++ ++ /* ++ * If we couldn't make a reservation then setup our reservation ticket ++ * and kick the async worker if it's not already running. ++ * ++ * If we are a priority flusher then we just need to add our ticket to ++ * the list and we will do our own flushing further down. ++ */ ++ if (ret && flush != BTRFS_RESERVE_NO_FLUSH) { ++ ticket.orig_bytes = orig_bytes; ++ ticket.bytes = orig_bytes; ++ ticket.error = 0; ++ init_waitqueue_head(&ticket.wait); ++ if (flush == BTRFS_RESERVE_FLUSH_ALL) { ++ list_add_tail(&ticket.list, &space_info->tickets); ++ if (!space_info->flush) { ++ space_info->flush = 1; ++ trace_btrfs_trigger_flush(fs_info, ++ space_info->flags, ++ orig_bytes, flush, ++ "enospc"); ++ queue_work(system_unbound_wq, ++ &root->fs_info->async_reclaim_work); ++ } ++ } else { ++ list_add_tail(&ticket.list, ++ &space_info->priority_tickets); ++ } ++ } else if (!ret && space_info->flags & BTRFS_BLOCK_GROUP_METADATA) { ++ used += orig_bytes; ++ /* ++ * We will do the space reservation dance during log replay, ++ * which means we won't have fs_info->fs_root set, so don't do ++ * the async reclaim as we will panic. ++ */ ++ if (!test_bit(BTRFS_FS_LOG_RECOVERING, &fs_info->flags) && ++ need_do_async_reclaim(space_info, root, used) && ++ !work_busy(&fs_info->async_reclaim_work)) { ++ trace_btrfs_trigger_flush(fs_info, space_info->flags, ++ orig_bytes, flush, "preempt"); ++ queue_work(system_unbound_wq, ++ &fs_info->async_reclaim_work); ++ } ++ } ++ spin_unlock(&space_info->lock); ++ if (!ret || flush == BTRFS_RESERVE_NO_FLUSH) ++ return ret; ++ ++ if (flush == BTRFS_RESERVE_FLUSH_ALL) ++ return wait_reserve_ticket(fs_info, space_info, &ticket); ++ ++ ret = 0; ++ priority_reclaim_metadata_space(fs_info, space_info, &ticket); ++ spin_lock(&space_info->lock); ++ if (ticket.bytes) { ++ if (ticket.bytes < orig_bytes) ++ reclaim_bytes = orig_bytes - ticket.bytes; ++ list_del_init(&ticket.list); ++ ret = -ENOSPC; ++ } ++ spin_unlock(&space_info->lock); ++ ++ if (reclaim_bytes) ++ btrfs_space_info_add_old_bytes(fs_info, space_info, ++ reclaim_bytes); ++ ASSERT(list_empty(&ticket.list)); ++ return ret; ++} ++ ++/** ++ * reserve_metadata_bytes - try to reserve bytes from the block_rsv's space ++ * @root - the root we're allocating for ++ * @block_rsv - the block_rsv we're allocating for ++ * @orig_bytes - the number of bytes we want ++ * @flush - whether or not we can flush to make our reservation ++ * ++ * This will reserve orgi_bytes number of bytes from the space info associated ++ * with the block_rsv. If there is not enough space it will make an attempt to ++ * flush out space to make room. It will do this by flushing delalloc if ++ * possible or committing the transaction. If flush is 0 then no attempts to ++ * regain reservations will be made and this will fail if there is not enough ++ * space already. ++ */ ++int btrfs_reserve_metadata_bytes(struct btrfs_root *root, ++ struct btrfs_block_rsv *block_rsv, ++ u64 orig_bytes, ++ enum btrfs_reserve_flush_enum flush) ++{ ++ struct btrfs_fs_info *fs_info = root->fs_info; ++ struct btrfs_block_rsv *global_rsv = &fs_info->global_block_rsv; ++ int ret; ++ ++ ret = __reserve_metadata_bytes(root, block_rsv->space_info, orig_bytes, ++ flush); ++ if (ret == -ENOSPC && ++ unlikely(root->orphan_cleanup_state == ORPHAN_CLEANUP_STARTED)) { ++ if (block_rsv != global_rsv && ++ !btrfs_block_rsv_use_bytes(global_rsv, orig_bytes)) ++ ret = 0; ++ } ++ if (ret == -ENOSPC) { ++ trace_btrfs_space_reservation(fs_info, "space_info:enospc", ++ block_rsv->space_info->flags, ++ orig_bytes, 1); ++ ++ if (btrfs_test_opt(fs_info, ENOSPC_DEBUG)) ++ btrfs_dump_space_info(fs_info, block_rsv->space_info, ++ orig_bytes, 0); ++ } ++ return ret; ++} ++ +--- a/fs/btrfs/space-info.h ++++ b/fs/btrfs/space-info.h +@@ -128,5 +128,9 @@ int btrfs_can_overcommit(struct btrfs_ro + void btrfs_dump_space_info(struct btrfs_fs_info *fs_info, + struct btrfs_space_info *info, u64 bytes, + int dump_block_groups); ++int btrfs_reserve_metadata_bytes(struct btrfs_root *root, ++ struct btrfs_block_rsv *block_rsv, ++ u64 orig_bytes, ++ enum btrfs_reserve_flush_enum flush); + + #endif /* BTRFS_SPACE_INFO_H */ diff --git a/patches.suse/0011-btrfs-only-free-reserved-extent-if-we-didn-t-insert-it.patch b/patches.suse/0011-btrfs-only-free-reserved-extent-if-we-didn-t-insert-it.patch new file mode 100644 index 0000000..ec1721e --- /dev/null +++ b/patches.suse/0011-btrfs-only-free-reserved-extent-if-we-didn-t-insert-it.patch @@ -0,0 +1,66 @@ +From: Josef Bacik +Date: Thu, 11 Oct 2018 15:54:21 -0400 +Subject: btrfs: only free reserved extent if we didn't insert it +Git-commit: 49940bdd57779c78462da7aa5a8650b2fea8c2ff +Patch-mainline: v4.20-rc1 +References: bsc##1165949 + +When we insert the file extent once the ordered extent completes we free +the reserved extent reservation as it'll have been migrated to the +bytes_used counter. However if we error out after this step we'll still +clear the reserved extent reservation, resulting in a negative +accounting of the reserved bytes for the block group and space info. +Fix this by only doing the free if we didn't successfully insert a file +extent for this extent. + +CC: stable@vger.kernel.org # 4.14+ +Reviewed-by: Omar Sandoval +Reviewed-by: Filipe Manana +Signed-off-by: Josef Bacik +Signed-off-by: David Sterba +Acked-by: Nikolay Borisov +--- + fs/btrfs/inode.c | 10 +++++++++- + 1 file changed, 9 insertions(+), 1 deletion(-) + +diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c +index f98ddd886036..28625f344952 100644 +--- a/fs/btrfs/inode.c ++++ b/fs/btrfs/inode.c +@@ -2941,6 +2941,7 @@ static int btrfs_finish_ordered_io(struct btrfs_ordered_extent *ordered_extent) + bool truncated = false; + bool range_locked = false; + bool clear_new_delalloc_bytes = false; ++ bool clear_reserved_extent = true; + + if (!test_bit(BTRFS_ORDERED_NOCOW, &ordered_extent->flags) && + !test_bit(BTRFS_ORDERED_PREALLOC, &ordered_extent->flags) && +@@ -3044,10 +3045,12 @@ static int btrfs_finish_ordered_io(struct btrfs_ordered_extent *ordered_extent) + logical_len, logical_len, + compress_type, 0, 0, + BTRFS_FILE_EXTENT_REG); +- if (!ret) ++ if (!ret) { ++ clear_reserved_extent = false; + btrfs_release_delalloc_bytes(fs_info, + ordered_extent->start, + ordered_extent->disk_len); ++ } + } + unpin_extent_cache(&BTRFS_I(inode)->extent_tree, + ordered_extent->file_offset, ordered_extent->len, +@@ -3108,8 +3111,13 @@ static int btrfs_finish_ordered_io(struct btrfs_ordered_extent *ordered_extent) + * wrong we need to return the space for this ordered extent + * back to the allocator. We only free the extent in the + * truncated case if we didn't write out the extent at all. ++ * ++ * If we made it past insert_reserved_file_extent before we ++ * errored out then we don't need to do this as the accounting ++ * has already been done. + */ + if ((ret || !logical_len) && ++ clear_reserved_extent && + !test_bit(BTRFS_ORDERED_NOCOW, &ordered_extent->flags) && + !test_bit(BTRFS_ORDERED_PREALLOC, &ordered_extent->flags)) + btrfs_free_reserved_extent(fs_info, + diff --git a/patches.suse/0011-btrfs-reserve-extra-space-during-evict.patch b/patches.suse/0011-btrfs-reserve-extra-space-during-evict.patch new file mode 100644 index 0000000..7ea3bc9 --- /dev/null +++ b/patches.suse/0011-btrfs-reserve-extra-space-during-evict.patch @@ -0,0 +1,71 @@ +From: Josef Bacik +Date: Wed, 21 Nov 2018 14:03:13 -0500 +Subject: btrfs: reserve extra space during evict +Git-commit: 260e77025ffa8779a7dc4bc21f3890273c93f9d4 +Patch-mainline: v5.1-rc1 +References: bsc#1165949 + +We could generate a lot of delayed refs in evict but never have any left +over space from our block rsv to make up for that fact. So reserve some +extra space and give it to the transaction so it can be used to refill +the delayed refs rsv every loop through the truncate path. + +Signed-off-by: Josef Bacik +Signed-off-by: David Sterba +Acked-by: Nikolay Borisov +--- + fs/btrfs/inode.c | 25 +++++++++++++++++++++++-- + 1 file changed, 23 insertions(+), 2 deletions(-) + +diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c +index a443645cf815..3f180b857e20 100644 +--- a/fs/btrfs/inode.c ++++ b/fs/btrfs/inode.c +@@ -5293,13 +5293,15 @@ static struct btrfs_trans_handle *evict_refill_and_join(struct btrfs_root *root, + { + struct btrfs_fs_info *fs_info = root->fs_info; + struct btrfs_block_rsv *global_rsv = &fs_info->global_block_rsv; ++ u64 delayed_refs_extra = btrfs_calc_trans_metadata_size(fs_info, 1); + int failures = 0; + + for (;;) { + struct btrfs_trans_handle *trans; + int ret; + +- ret = btrfs_block_rsv_refill(root, rsv, rsv->size, ++ ret = btrfs_block_rsv_refill(root, rsv, ++ rsv->size + delayed_refs_extra, + BTRFS_RESERVE_FLUSH_LIMIT); + + if (ret && ++failures > 2) { +@@ -5308,9 +5310,28 @@ static struct btrfs_trans_handle *evict_refill_and_join(struct btrfs_root *root, + return ERR_PTR(-ENOSPC); + } + ++ /* ++ * Evict can generate a large amount of delayed refs without ++ * having a way to add space back since we exhaust our temporary ++ * block rsv. We aren't allowed to do FLUSH_ALL in this case ++ * because we could deadlock with so many things in the flushing ++ * code, so we have to try and hold some extra space to ++ * compensate for our delayed ref generation. If we can't get ++ * that space then we need see if we can steal our minimum from ++ * the global reserve. We will be ratelimited by the amount of ++ * space we have for the delayed refs rsv, so we'll end up ++ * committing and trying again. ++ */ + trans = btrfs_join_transaction(root); +- if (IS_ERR(trans) || !ret) ++ if (IS_ERR(trans) || !ret) { ++ if (!IS_ERR(trans)) { ++ trans->block_rsv = &fs_info->trans_block_rsv; ++ trans->bytes_reserved = delayed_refs_extra; ++ btrfs_block_rsv_migrate(rsv, trans->block_rsv, ++ delayed_refs_extra, 1); ++ } + return trans; ++ } + + /* + * Try to steal from the global reserve if there is space for + diff --git a/patches.suse/0011-btrfs-stop-partially-refilling-tickets-when-releasing-space.patch b/patches.suse/0011-btrfs-stop-partially-refilling-tickets-when-releasing-space.patch new file mode 100644 index 0000000..46fd54f --- /dev/null +++ b/patches.suse/0011-btrfs-stop-partially-refilling-tickets-when-releasing-space.patch @@ -0,0 +1,120 @@ +From: Josef Bacik +Date: Wed, 28 Aug 2019 11:15:24 -0400 +Subject: btrfs: stop partially refilling tickets when releasing space +Git-commit: 91182645075f9a41953bea703a7d10e9f661cd13 +Patch-mainline: v5.4-rc1 +References: bsc#1165949 + +btrfs_space_info_add_old_bytes is used when adding the extra space from +an existing reservation back into the space_info to be used by any +waiting tickets. In order to keep us from overcommitting we check to +make sure that we can still use this space for our reserve ticket, and +if we cannot we'll simply subtract it from space_info->bytes_may_use. + +However this is problematic, because it assumes that only changes to +bytes_may_use would affect our ability to make reservations. Any +changes to bytes_reserved would be missed. If we were unable to make a +reservation prior because of reserved space, but that reserved space was +free'd due to unlink or truncate and we were allowed to immediately +reclaim that metadata space we would still ENOSPC. + +Consider the example where we create a file with a bunch of extents, +using up 2MiB of actual space for the new tree blocks. Then we try to +make a reservation of 2MiB but we do not have enough space to make this +reservation. The iput() occurs in another thread and we remove this +space, and since we did not write the blocks we simply do +space_info->bytes_reserved -= 2MiB. We would never see this because we +do not check our space info used, we just try to re-use the freed +reservations. + +To fix this problem, and to greatly simplify the wakeup code, do away +with this partial refilling nonsense. Use +btrfs_space_info_add_old_bytes to subtract the reservation from +space_info->bytes_may_use, and then check the ticket against the total +used of the space_info the same way we do with the initial reservation +attempt. + +This keeps the reservation logic consistent and solves the problem of +early ENOSPC in the case that we free up space in places other than +bytes_may_use and bytes_pinned. Thanks, + +Signed-off-by: Josef Bacik +Signed-off-by: David Sterba +Acked-by: Nikolay Borisov +--- + fs/btrfs/space-info.c | 43 +++++++++++++++---------------------------- + 1 file changed, 15 insertions(+), 28 deletions(-) + +--- a/fs/btrfs/space-info.c ++++ b/fs/btrfs/space-info.c +@@ -257,55 +257,42 @@ void btrfs_space_info_add_old_bytes(stru + struct btrfs_space_info *space_info, + u64 num_bytes) + { +- struct reserve_ticket *ticket; + struct list_head *head; +- u64 used; + enum btrfs_reserve_flush_enum flush = BTRFS_RESERVE_NO_FLUSH; +- bool check_overcommit = false; + + spin_lock(&space_info->lock); + head = &space_info->priority_tickets; ++ btrfs_space_info_update_bytes_may_use(fs_info, space_info, -num_bytes); + +- /* +- * If we are over our limit then we need to check and see if we can +- * overcommit, and if we can't then we just need to free up our space +- * and not satisfy any requests. +- */ +- used = space_info->bytes_used + space_info->bytes_reserved + +- space_info->bytes_pinned + space_info->bytes_readonly + +- space_info->bytes_may_use; +- if (used - num_bytes >= space_info->total_bytes) +- check_overcommit = true; + again: +- while (!list_empty(head) && num_bytes) { ++ while (!list_empty(head)) { ++ struct reserve_ticket *ticket; ++ u64 used = btrfs_space_info_used(space_info, true); ++ + ticket = list_first_entry(head, struct reserve_ticket, + list); +- /* +- * We use 0 bytes because this space is already reserved, so +- * adding the ticket space would be a double count. +- */ +- if (check_overcommit && +- !can_overcommit(fs_info->extent_root, space_info, 0, +- flush)) +- break; +- if (num_bytes >= ticket->bytes) { ++ /* Check and see if our ticket can be satisified now. */ ++ if ((used + ticket->bytes <= space_info->total_bytes) || ++ can_overcommit(fs_info->extent_root, space_info, ++ ticket->bytes, flush)) { ++ btrfs_space_info_update_bytes_may_use(fs_info, ++ space_info, ++ ticket->bytes); + list_del_init(&ticket->list); +- num_bytes -= ticket->bytes; + ticket->bytes = 0; + space_info->tickets_id++; + wake_up(&ticket->wait); ++ + } else { +- ticket->bytes -= num_bytes; +- num_bytes = 0; ++ break; + } + } + +- if (num_bytes && head == &space_info->priority_tickets) { ++ if (head == &space_info->priority_tickets) { + head = &space_info->tickets; + flush = BTRFS_RESERVE_FLUSH_ALL; + goto again; + } +- btrfs_space_info_update_bytes_may_use(fs_info, space_info, -num_bytes); + spin_unlock(&space_info->lock); + } + /* diff --git a/patches.suse/0011-md-remove-a-bogus-comment.patch b/patches.suse/0011-md-remove-a-bogus-comment.patch new file mode 100644 index 0000000..9930278 --- /dev/null +++ b/patches.suse/0011-md-remove-a-bogus-comment.patch @@ -0,0 +1,38 @@ +From 3ed122e68bb2dcab36b48109431341736e37ce85 Mon Sep 17 00:00:00 2001 +From: Christoph Hellwig +Date: Tue, 24 Jul 2018 09:52:33 +0200 +Subject: [PATCH] md: remove a bogus comment +Git-commit: 3ed122e68bb2dcab36b48109431341736e37ce85 +Patch-mainline: v4.19-rc1 +References: bsc#1111974 bsc#1166003 + +The function name mentioned doesn't exist, and the code next to it +doesn't match the description either. + +Signed-off-by: Christoph Hellwig +Reviewed-by: Ming Lei +Signed-off-by: Jens Axboe +Signed-off-by: Coly Li + +--- + drivers/md/md.c | 4 ---- + 1 file changed, 4 deletions(-) + +diff --git a/drivers/md/md.c b/drivers/md/md.c +index f6e58dbca0d4..cb4eb5faa519 100644 +--- a/drivers/md/md.c ++++ b/drivers/md/md.c +@@ -204,10 +204,6 @@ static int start_readonly; + */ + static bool create_on_open = true; + +-/* bio_clone_mddev +- * like bio_clone_bioset, but with a local bio set +- */ +- + struct bio *bio_alloc_mddev(gfp_t gfp_mask, int nr_iovecs, + struct mddev *mddev) + { +-- +2.19.0 + diff --git a/patches.suse/0012-btrfs-fix-insert_reserved-error-handling.patch b/patches.suse/0012-btrfs-fix-insert_reserved-error-handling.patch new file mode 100644 index 0000000..b5a6d93 --- /dev/null +++ b/patches.suse/0012-btrfs-fix-insert_reserved-error-handling.patch @@ -0,0 +1,57 @@ +From: Josef Bacik +Date: Thu, 11 Oct 2018 15:54:22 -0400 +Subject: btrfs: fix insert_reserved error handling +Git-commit: 80ee54bfe8a3850015585ebc84e8d207fcae6831 +Patch-mainline: v4.20-rc1 +References: bsc##1165949 + +We were not handling the reserved byte accounting properly for data +references. Metadata was fine, if it errored out the error paths would +free the bytes_reserved count and pin the extent, but it even missed one +of the error cases. So instead move this handling up into +run_one_delayed_ref so we are sure that both cases are properly cleaned +up in case of a transaction abort. + +CC: stable@vger.kernel.org # 4.18+ +Reviewed-by: Nikolay Borisov +Signed-off-by: Josef Bacik +Reviewed-by: David Sterba +Signed-off-by: David Sterba +Acked-by: Nikolay Borisov +--- + fs/btrfs/extent-tree.c | 10 ++++------ + 1 file changed, 4 insertions(+), 6 deletions(-) + +--- a/fs/btrfs/extent-tree.c ++++ b/fs/btrfs/extent-tree.c +@@ -2518,6 +2518,9 @@ static int run_one_delayed_ref(struct bt + insert_reserved); + else + BUG(); ++ if (ret && insert_reserved) ++ btrfs_pin_extent(trans->fs_info, node->bytenr, ++ node->num_bytes, 1); + return ret; + } + +@@ -8182,19 +8185,14 @@ static int alloc_reserved_tree_block(str + size += sizeof(*block_info); + + path = btrfs_alloc_path(); +- if (!path) { +- btrfs_free_and_pin_reserved_extent(fs_info, ins->objectid, +- fs_info->nodesize); ++ if (!path) + return -ENOMEM; +- } + + path->leave_spinning = 1; + ret = btrfs_insert_empty_item(trans, fs_info->extent_root, path, + ins, size); + if (ret) { + btrfs_free_path(path); +- btrfs_free_and_pin_reserved_extent(fs_info, ins->objectid, +- fs_info->nodesize); + return ret; + } + diff --git a/patches.suse/0012-btrfs-refactor-the-ticket-wakeup-code.patch b/patches.suse/0012-btrfs-refactor-the-ticket-wakeup-code.patch new file mode 100644 index 0000000..61e84d6 --- /dev/null +++ b/patches.suse/0012-btrfs-refactor-the-ticket-wakeup-code.patch @@ -0,0 +1,153 @@ +From: Josef Bacik +Date: Thu, 22 Aug 2019 15:10:58 -0400 +Subject: btrfs: refactor the ticket wakeup code +Git-commit: 18fa2284aac3f1071f51a897dc5585178cae458f +Patch-mainline: v5.4-rc1 +References: bsc#1165949 + +Now that btrfs_space_info_add_old_bytes simply checks if we can make the +reservation and updates bytes_may_use, there's no reason to have both +helpers in place. + +Factor out the ticket wakeup logic into it's own helper, make +btrfs_space_info_add_old_bytes() update bytes_may_use and then call the +wakeup helper, and replace all calls to btrfs_space_info_add_new_bytes() +with the wakeup helper. + +Reviewed-by: Nikolay Borisov +Signed-off-by: Josef Bacik +Signed-off-by: David Sterba +Acked-by: Nikolay Borisov +--- + fs/btrfs/extent-tree.c | 4 +-- + fs/btrfs/space-info.c | 52 ++++--------------------------------------------- + fs/btrfs/space-info.h | 19 ++++++++++++----- + 3 files changed, 20 insertions(+), 55 deletions(-) + +--- a/fs/btrfs/extent-tree.c ++++ b/fs/btrfs/extent-tree.c +@@ -3076,8 +3076,8 @@ static int unpin_extent_range(struct btr + spin_unlock(&global_rsv->lock); + /* Add to any tickets we may have */ + if (len) +- btrfs_space_info_add_new_bytes(fs_info, +- space_info, len); ++ btrfs_try_granting_tickets(fs_info, ++ space_info); + } + spin_unlock(&space_info->lock); + } +--- a/fs/btrfs/space-info.c ++++ b/fs/btrfs/space-info.c +@@ -153,9 +153,7 @@ void btrfs_update_space_info(struct btrf + found->bytes_readonly += bytes_readonly; + if (total_bytes > 0) + found->full = 0; +- btrfs_space_info_add_new_bytes(info, found, +- total_bytes - bytes_used - +- bytes_readonly); ++ btrfs_try_granting_tickets(info, found); + spin_unlock(&found->lock); + *space_info = found; + } +@@ -253,17 +251,15 @@ static int can_overcommit(struct btrfs_r + * This is for space we already have accounted in space_info->bytes_may_use, so + * basically when we're returning space from block_rsv's. + */ +-void btrfs_space_info_add_old_bytes(struct btrfs_fs_info *fs_info, +- struct btrfs_space_info *space_info, +- u64 num_bytes) ++void btrfs_try_granting_tickets(struct btrfs_fs_info *fs_info, ++ struct btrfs_space_info *space_info) + { + struct list_head *head; + enum btrfs_reserve_flush_enum flush = BTRFS_RESERVE_NO_FLUSH; + +- spin_lock(&space_info->lock); +- head = &space_info->priority_tickets; +- btrfs_space_info_update_bytes_may_use(fs_info, space_info, -num_bytes); ++ lockdep_assert_held(&space_info->lock); + ++ head = &space_info->priority_tickets; + again: + while (!list_empty(head)) { + struct reserve_ticket *ticket; +@@ -293,44 +289,6 @@ again: + flush = BTRFS_RESERVE_FLUSH_ALL; + goto again; + } +- spin_unlock(&space_info->lock); +-} +-/* +- * This is for newly allocated space that isn't accounted in +- * space_info->bytes_may_use yet. So if we allocate a chunk or unpin an extent +- * we use this helper. +- */ +-void btrfs_space_info_add_new_bytes(struct btrfs_fs_info *fs_info, +- struct btrfs_space_info *space_info, +- u64 num_bytes) +-{ +- struct reserve_ticket *ticket; +- struct list_head *head = &space_info->priority_tickets; +- +-again: +- while (!list_empty(head) && num_bytes) { +- ticket = list_first_entry(head, struct reserve_ticket, +- list); +- if (num_bytes >= ticket->bytes) { +- list_del_init(&ticket->list); +- num_bytes -= ticket->bytes; +- btrfs_space_info_update_bytes_may_use(fs_info, +- space_info, ticket->bytes); +- ticket->bytes = 0; +- space_info->tickets_id++; +- wake_up(&ticket->wait); +- } else { +- btrfs_space_info_update_bytes_may_use(fs_info, +- space_info, num_bytes); +- ticket->bytes -= num_bytes; +- num_bytes = 0; +- } +- } +- +- if (num_bytes && head == &space_info->priority_tickets) { +- head = &space_info->tickets; +- goto again; +- } + } + + #define DUMP_BLOCK_RSV(fs_info, rsv_name) \ +--- a/fs/btrfs/space-info.h ++++ b/fs/btrfs/space-info.h +@@ -110,12 +110,6 @@ btrfs_space_info_update_##name(struct bt + DECLARE_SPACE_INFO_UPDATE(bytes_may_use, "space_info"); + DECLARE_SPACE_INFO_UPDATE(bytes_pinned, "pinned"); + +-void btrfs_space_info_add_new_bytes(struct btrfs_fs_info *fs_info, +- struct btrfs_space_info *space_info, +- u64 num_bytes); +-void btrfs_space_info_add_old_bytes(struct btrfs_fs_info *fs_info, +- struct btrfs_space_info *space_info, +- u64 num_bytes); + int btrfs_init_space_info(struct btrfs_fs_info *fs_info); + void btrfs_update_space_info(struct btrfs_fs_info *info, u64 flags, + u64 total_bytes, u64 bytes_used, +@@ -133,5 +127,18 @@ int btrfs_reserve_metadata_bytes(struct + struct btrfs_block_rsv *block_rsv, + u64 orig_bytes, + enum btrfs_reserve_flush_enum flush); ++void btrfs_try_granting_tickets(struct btrfs_fs_info *fs_info, ++ struct btrfs_space_info *space_info); ++ ++static inline void btrfs_space_info_add_old_bytes( ++ struct btrfs_fs_info *fs_info, ++ struct btrfs_space_info *space_info, ++ u64 num_bytes) ++{ ++ spin_lock(&space_info->lock); ++ btrfs_space_info_update_bytes_may_use(fs_info, space_info, -num_bytes); ++ btrfs_try_granting_tickets(fs_info, space_info); ++ spin_unlock(&space_info->lock); ++} + + #endif /* BTRFS_SPACE_INFO_H */ diff --git a/patches.suse/0012-btrfs-temporarily-export-inc_block_group_ro.patch b/patches.suse/0012-btrfs-temporarily-export-inc_block_group_ro.patch new file mode 100644 index 0000000..4cfbb2a --- /dev/null +++ b/patches.suse/0012-btrfs-temporarily-export-inc_block_group_ro.patch @@ -0,0 +1,88 @@ +From: Josef Bacik +Date: Thu, 20 Jun 2019 15:37:54 -0400 +Subject: btrfs: temporarily export inc_block_group_ro +Git-commit: 3b2a78f21d5c53ff34b8e03cba4f904c91d4b3a2 +Patch-mainline: v5.4-rc1 +References: bsc#1165949 + +This is used in a few logical parts of the block group code, temporarily +export it so we can move things in pieces. + +Signed-off-by: Josef Bacik +Reviewed-by: David Sterba +Signed-off-by: David Sterba +Acked-by: Nikolay Borisov +--- + fs/btrfs/block-group.h | 2 ++ + fs/btrfs/extent-tree.c | 14 +++++++------- + 2 files changed, 9 insertions(+), 7 deletions(-) + +--- a/fs/btrfs/block-group.h ++++ b/fs/btrfs/block-group.h +@@ -185,4 +185,6 @@ static inline int btrfs_block_group_cach + cache->cached == BTRFS_CACHE_ERROR; + } + ++int __btrfs_inc_block_group_ro(struct btrfs_block_group_cache *cache, int force); ++ + #endif /* BTRFS_BLOCK_GROUP_H */ +--- a/fs/btrfs/extent-tree.c ++++ b/fs/btrfs/extent-tree.c +@@ -6763,7 +6763,7 @@ static u64 update_block_group_flags(stru + return flags; + } + +-static int inc_block_group_ro(struct btrfs_block_group_cache *cache, int force) ++int __inc_block_group_ro(struct btrfs_block_group_cache *cache, int force) + { + struct btrfs_space_info *sinfo = cache->space_info; + u64 num_bytes; +@@ -6868,14 +6868,14 @@ again: + goto out; + } + +- ret = inc_block_group_ro(cache, 0); ++ ret = __btrfs_inc_block_group_ro(cache, 0); + if (!ret) + goto out; + alloc_flags = get_alloc_profile(fs_info, cache->space_info->flags); + ret = btrfs_chunk_alloc(trans, alloc_flags, CHUNK_ALLOC_FORCE); + if (ret < 0) + goto out; +- ret = inc_block_group_ro(cache, 0); ++ ret = __btrfs_inc_block_group_ro(cache, 0); + out: + if (cache->flags & BTRFS_BLOCK_GROUP_SYSTEM) { + alloc_flags = update_block_group_flags(fs_info, cache->flags); +@@ -7616,7 +7616,7 @@ int btrfs_read_block_groups(struct btrfs + + set_avail_alloc_bits(info, cache->flags); + if (btrfs_chunk_readonly(info, cache->key.objectid)) { +- inc_block_group_ro(cache, 1); ++ __btrfs_inc_block_group_ro(cache, 1); + } else if (btrfs_block_group_used(&cache->item) == 0) { + spin_lock(&info->unused_bgs_lock); + /* Should always be true but just in case. */ +@@ -7644,11 +7644,11 @@ int btrfs_read_block_groups(struct btrfs + list_for_each_entry(cache, + &space_info->block_groups[BTRFS_RAID_RAID0], + list) +- inc_block_group_ro(cache, 1); ++ __btrfs_inc_block_group_ro(cache, 1); + list_for_each_entry(cache, + &space_info->block_groups[BTRFS_RAID_SINGLE], + list) +- inc_block_group_ro(cache, 1); ++ __btrfs_inc_block_group_ro(cache, 1); + } + + btrfs_add_raid_kobjects(info); +@@ -8187,7 +8187,7 @@ void btrfs_delete_unused_bgs(struct btrf + spin_unlock(&block_group->lock); + + /* We don't want to force the issue, only flip if it's ok. */ +- ret = inc_block_group_ro(block_group, 0); ++ ret = __btrfs_inc_block_group_ro(block_group, 0); + up_write(&space_info->groups_sem); + if (ret < 0) { + ret = 0; diff --git a/patches.suse/0012-btrfs-unexport-can_overcommit.patch b/patches.suse/0012-btrfs-unexport-can_overcommit.patch new file mode 100644 index 0000000..cccc99b --- /dev/null +++ b/patches.suse/0012-btrfs-unexport-can_overcommit.patch @@ -0,0 +1,81 @@ +From: Josef Bacik +Date: Tue, 18 Jun 2019 16:09:26 -0400 +Subject: btrfs: unexport can_overcommit +Git-commit: 83d731a5b228454d7c29ec64fdd93426698f97f6 +Patch-mainline: v5.3-rc1 +References: bsc#1165949 + +Now that we've moved all of the users to space-info.c, unexport it and +name it back to can_overcommit. + +Reviewed-by: Nikolay Borisov +Signed-off-by: Josef Bacik +Signed-off-by: David Sterba +Acked-by: Nikolay Borisov +--- + fs/btrfs/space-info.c | 14 +++++++------- + fs/btrfs/space-info.h | 3 --- + 2 files changed, 7 insertions(+), 10 deletions(-) + +--- a/fs/btrfs/space-info.c ++++ b/fs/btrfs/space-info.c +@@ -183,9 +183,9 @@ static inline u64 calc_global_rsv_need_s + return (global->size << 1); + } + +-int btrfs_can_overcommit(struct btrfs_root *root, +- struct btrfs_space_info *space_info, u64 bytes, +- enum btrfs_reserve_flush_enum flush) ++static int can_overcommit(struct btrfs_root *root, ++ struct btrfs_space_info *space_info, u64 bytes, ++ enum btrfs_reserve_flush_enum flush) + { + struct btrfs_fs_info *fs_info = root->fs_info; + struct btrfs_block_rsv *global_rsv = &fs_info->global_block_rsv; +@@ -280,7 +280,7 @@ again: + * adding the ticket space would be a double count. + */ + if (check_overcommit && +- !btrfs_can_overcommit(fs_info->extent_root, space_info, 0, ++ !can_overcommit(fs_info->extent_root, space_info, 0, + flush)) + break; + if (num_bytes >= ticket->bytes) { +@@ -708,14 +708,14 @@ btrfs_calc_reclaim_metadata_size(struct + return to_reclaim; + + to_reclaim = min_t(u64, num_online_cpus() * SZ_1M, SZ_16M); +- if (btrfs_can_overcommit(root, space_info, to_reclaim, ++ if (can_overcommit(root, space_info, to_reclaim, + BTRFS_RESERVE_FLUSH_ALL)) + return 0; + + used = space_info->bytes_used + space_info->bytes_reserved + + space_info->bytes_pinned + space_info->bytes_readonly + + space_info->bytes_may_use; +- if (btrfs_can_overcommit(root, space_info, SZ_1M, BTRFS_RESERVE_FLUSH_ALL)) ++ if (can_overcommit(root, space_info, SZ_1M, BTRFS_RESERVE_FLUSH_ALL)) + expected = div_factor_fine(space_info->total_bytes, 95); + else + expected = div_factor_fine(space_info->total_bytes, 90); +@@ -966,7 +966,7 @@ static int __reserve_metadata_bytes(stru + trace_btrfs_space_reservation(fs_info, "space_info", + space_info->flags, orig_bytes, 1); + ret = 0; +- } else if (btrfs_can_overcommit(root, space_info, orig_bytes, flush)) { ++ } else if (can_overcommit(root, space_info, orig_bytes, flush)) { + btrfs_space_info_update_bytes_may_use(fs_info, space_info, + orig_bytes); + trace_btrfs_space_reservation(fs_info, "space_info", +--- a/fs/btrfs/space-info.h ++++ b/fs/btrfs/space-info.h +@@ -122,9 +122,6 @@ struct btrfs_space_info *btrfs_find_spac + u64 btrfs_space_info_used(struct btrfs_space_info *s_info, + bool may_use_included); + void btrfs_clear_space_info_full(struct btrfs_fs_info *info); +-int btrfs_can_overcommit(struct btrfs_root *root, +- struct btrfs_space_info *space_info, u64 bytes, +- enum btrfs_reserve_flush_enum flush); + void btrfs_dump_space_info(struct btrfs_fs_info *fs_info, + struct btrfs_space_info *info, u64 bytes, + int dump_block_groups); diff --git a/patches.suse/0012-md-r5cache-remove-redundant-pointer-bio.patch b/patches.suse/0012-md-r5cache-remove-redundant-pointer-bio.patch new file mode 100644 index 0000000..1eb3062 --- /dev/null +++ b/patches.suse/0012-md-r5cache-remove-redundant-pointer-bio.patch @@ -0,0 +1,45 @@ +From ebc7709f65001911f275e13dd5f29b02803c0688 Mon Sep 17 00:00:00 2001 +From: Colin Ian King +Date: Tue, 3 Jul 2018 07:51:09 +0100 +Subject: [PATCH] md/r5cache: remove redundant pointer bio +Git-commit: ebc7709f65001911f275e13dd5f29b02803c0688 +Patch-mainline: v4.19-rc1 +References: bsc#1111974 bsc#1166003 + +Pointer bio is being assigned but is never used hence it is redundant +and can be removed. + +Cleans up clang warning: +Warning: variable 'bio' set but not used [-Wunused-but-set-variable] + +Signed-off-by: Colin Ian King +Signed-off-by: Shaohua Li +Signed-off-by: Coly Li + +--- + drivers/md/raid5-cache.c | 2 -- + 1 file changed, 2 deletions(-) + +diff --git a/drivers/md/raid5-cache.c b/drivers/md/raid5-cache.c +index 2b775abf377b..7416db70c6cc 100644 +--- a/drivers/md/raid5-cache.c ++++ b/drivers/md/raid5-cache.c +@@ -717,7 +717,6 @@ static void r5c_disable_writeback_async(struct work_struct *work) + static void r5l_submit_current_io(struct r5l_log *log) + { + struct r5l_io_unit *io = log->current_io; +- struct bio *bio; + struct r5l_meta_block *block; + unsigned long flags; + u32 crc; +@@ -730,7 +729,6 @@ static void r5l_submit_current_io(struct r5l_log *log) + block->meta_size = cpu_to_le32(io->meta_offset); + crc = crc32c_le(log->uuid_checksum, block, PAGE_SIZE); + block->checksum = cpu_to_le32(crc); +- bio = io->current_bio; + + log->current_io = NULL; + spin_lock_irqsave(&log->io_list_lock, flags); +-- +2.19.0 + diff --git a/patches.suse/0013-btrfs-add-assertions-for-releasing-trans-handle-reservations.patch b/patches.suse/0013-btrfs-add-assertions-for-releasing-trans-handle-reservations.patch new file mode 100644 index 0000000..111b03c --- /dev/null +++ b/patches.suse/0013-btrfs-add-assertions-for-releasing-trans-handle-reservations.patch @@ -0,0 +1,40 @@ +From: Josef Bacik +Date: Fri, 29 Sep 2017 15:44:05 -0400 +Subject: btrfs: add assertions for releasing trans handle reservations +Git-commit: bf2681cb94d13d91326fc098ca98620b595a9d6b +Patch-mainline: v4.15-rc1 +References: bsc#1165949 + +These are useful for debugging problems where we mess with +trans->block_rsv to make sure we're not screwing something up. + +Signed-off-by: Josef Bacik +Reviewed-by: David Sterba +Signed-off-by: David Sterba +Acked-by: Nikolay Borisov +--- + fs/btrfs/extent-tree.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c +index 423d89145bac..4f874d02f310 100644 +--- a/fs/btrfs/extent-tree.c ++++ b/fs/btrfs/extent-tree.c +@@ -5823,12 +5823,15 @@ static void release_global_block_rsv(struct btrfs_fs_info *fs_info) + void btrfs_trans_release_metadata(struct btrfs_trans_handle *trans, + struct btrfs_fs_info *fs_info) + { +- if (!trans->block_rsv) ++ if (!trans->block_rsv) { ++ ASSERT(!trans->bytes_reserved); + return; ++ } + + if (!trans->bytes_reserved) + return; + ++ ASSERT(trans->block_rsv == &fs_info->trans_block_rsv); + trace_btrfs_space_reservation(fs_info, "transaction", + trans->transid, trans->bytes_reserved, 0); + btrfs_block_rsv_release(fs_info, trans->block_rsv, + diff --git a/patches.suse/0013-btrfs-don-t-run-delayed_iputs-in-commit.patch b/patches.suse/0013-btrfs-don-t-run-delayed_iputs-in-commit.patch new file mode 100644 index 0000000..d99862f --- /dev/null +++ b/patches.suse/0013-btrfs-don-t-run-delayed_iputs-in-commit.patch @@ -0,0 +1,57 @@ +From: Josef Bacik +Date: Thu, 11 Oct 2018 15:54:31 -0400 +Subject: btrfs: don't run delayed_iputs in commit +Git-commit: 30928e9baac238a7330085a1c5747f0b5df444b4 +Patch-mainline: v4.20-rc1 +References: bsc##1165949 + +This could result in a really bad case where we do something like + +evict + evict_refill_and_join + btrfs_commit_transaction + btrfs_run_delayed_iputs + evict + evict_refill_and_join + btrfs_commit_transaction +... forever + +We have plenty of other places where we run delayed iputs that are much +safer, let those do the work. + +CC: stable@vger.kernel.org # 4.4+ +Reviewed-by: Filipe Manana +Signed-off-by: Josef Bacik +Reviewed-by: David Sterba +Signed-off-by: David Sterba +Acked-by: Nikolay Borisov +--- + fs/btrfs/transaction.c | 10 +--------- + 1 file changed, 1 insertion(+), 9 deletions(-) + +--- a/fs/btrfs/transaction.c ++++ b/fs/btrfs/transaction.c +@@ -542,7 +542,7 @@ again: + * and then we deadlock with somebody doing a freeze. + * + * If we are ATTACH, it means we just want to catch the current +- * transaction and commit it, so we needn't do sb_start_intwrite(). ++ * transaction and commit it, so we needn't do sb_start_intwrite(). + */ + if (type & __TRANS_FREEZABLE) + sb_start_intwrite(fs_info->sb); +@@ -2315,14 +2315,6 @@ int btrfs_commit_transaction(struct btrf + + kmem_cache_free(btrfs_trans_handle_cachep, trans); + +- /* +- * If fs has been frozen, we can not handle delayed iputs, otherwise +- * it'll result in deadlock about SB_FREEZE_FS. +- */ +- if (current != fs_info->transaction_kthread && +- current != fs_info->cleaner_kthread && !fs_info->fs_frozen) +- btrfs_run_delayed_iputs(fs_info); +- + return ret; + + scrub_continue: diff --git a/patches.suse/0013-btrfs-migrate-the-block-group-removal-code.patch b/patches.suse/0013-btrfs-migrate-the-block-group-removal-code.patch new file mode 100644 index 0000000..6111e2e --- /dev/null +++ b/patches.suse/0013-btrfs-migrate-the-block-group-removal-code.patch @@ -0,0 +1,1125 @@ +From: Josef Bacik +Date: Thu, 20 Jun 2019 15:37:55 -0400 +Subject: btrfs: migrate the block group removal code +Git-commit: e3e0520b32bc3dbc64110536d171bfb334ac7a2a +Patch-mainline: v5.4-rc1 +References: bsc#1165949 + +This is the removal code and the unused bgs code. + +Signed-off-by: Josef Bacik +Reviewed-by: David Sterba +[ refresh, move clear_incompat_bg_bits ] +Signed-off-by: David Sterba +Acked-by: Nikolay Borisov +--- + fs/btrfs/block-group.c | 516 ++++++++++++++++++++++++++++++++++++++++++++++++ + fs/btrfs/block-group.h | 7 + fs/btrfs/ctree.h | 7 + fs/btrfs/extent-tree.c | 522 ------------------------------------------------- + fs/btrfs/volumes.c | 2 + 5 files changed, 524 insertions(+), 530 deletions(-) + +--- a/fs/btrfs/block-group.c ++++ b/fs/btrfs/block-group.c +@@ -6,6 +6,9 @@ + #include "disk-io.h" + #include "free-space-cache.h" + #include "free-space-tree.h" ++#include "disk-io.h" ++#include "volumes.h" ++#include "transaction.h" + + void btrfs_get_block_group(struct btrfs_block_group_cache *cache) + { +@@ -676,3 +679,516 @@ int btrfs_cache_block_group(struct btrfs + + return ret; + } ++ ++static void clear_avail_alloc_bits(struct btrfs_fs_info *fs_info, u64 flags) ++{ ++ u64 extra_flags = chunk_to_extended(flags) & ++ BTRFS_EXTENDED_PROFILE_MASK; ++ ++ write_seqlock(&fs_info->profiles_lock); ++ if (flags & BTRFS_BLOCK_GROUP_DATA) ++ fs_info->avail_data_alloc_bits &= ~extra_flags; ++ if (flags & BTRFS_BLOCK_GROUP_METADATA) ++ fs_info->avail_metadata_alloc_bits &= ~extra_flags; ++ if (flags & BTRFS_BLOCK_GROUP_SYSTEM) ++ fs_info->avail_system_alloc_bits &= ~extra_flags; ++ write_sequnlock(&fs_info->profiles_lock); ++} ++ ++int btrfs_remove_block_group(struct btrfs_trans_handle *trans, ++ u64 group_start, struct extent_map *em) ++{ ++ struct btrfs_fs_info *fs_info = trans->fs_info; ++ struct btrfs_root *root = fs_info->extent_root; ++ struct btrfs_path *path; ++ struct btrfs_block_group_cache *block_group; ++ struct btrfs_free_cluster *cluster; ++ struct btrfs_root *tree_root = fs_info->tree_root; ++ struct btrfs_key key; ++ struct inode *inode; ++ struct kobject *kobj = NULL; ++ int ret; ++ int index; ++ int factor; ++ struct btrfs_caching_control *caching_ctl = NULL; ++ bool remove_em; ++ bool remove_rsv = false; ++ ++ block_group = btrfs_lookup_block_group(fs_info, group_start); ++ BUG_ON(!block_group); ++ BUG_ON(!block_group->ro); ++ ++ /* ++ * Free the reserved super bytes from this block group before ++ * remove it. ++ */ ++ btrfs_free_excluded_extents(block_group); ++ ++ memcpy(&key, &block_group->key, sizeof(key)); ++ index = get_block_group_index(block_group); ++ factor = btrfs_bg_type_to_factor(block_group->flags); ++ ++ /* make sure this block group isn't part of an allocation cluster */ ++ cluster = &fs_info->data_alloc_cluster; ++ spin_lock(&cluster->refill_lock); ++ btrfs_return_cluster_to_free_space(block_group, cluster); ++ spin_unlock(&cluster->refill_lock); ++ ++ /* ++ * make sure this block group isn't part of a metadata ++ * allocation cluster ++ */ ++ cluster = &fs_info->meta_alloc_cluster; ++ spin_lock(&cluster->refill_lock); ++ btrfs_return_cluster_to_free_space(block_group, cluster); ++ spin_unlock(&cluster->refill_lock); ++ ++ path = btrfs_alloc_path(); ++ if (!path) { ++ ret = -ENOMEM; ++ goto out; ++ } ++ ++ /* ++ * get the inode first so any iput calls done for the io_list ++ * aren't the final iput (no unlinks allowed now) ++ */ ++ inode = lookup_free_space_inode(fs_info, block_group, path); ++ ++ mutex_lock(&trans->transaction->cache_write_mutex); ++ /* ++ * Make sure our free space cache IO is done before removing the ++ * free space inode ++ */ ++ spin_lock(&trans->transaction->dirty_bgs_lock); ++ if (!list_empty(&block_group->io_list)) { ++ list_del_init(&block_group->io_list); ++ ++ WARN_ON(!IS_ERR(inode) && inode != block_group->io_ctl.inode); ++ ++ spin_unlock(&trans->transaction->dirty_bgs_lock); ++ btrfs_wait_cache_io(trans, block_group, path); ++ btrfs_put_block_group(block_group); ++ spin_lock(&trans->transaction->dirty_bgs_lock); ++ } ++ ++ if (!list_empty(&block_group->dirty_list)) { ++ list_del_init(&block_group->dirty_list); ++ remove_rsv = true; ++ btrfs_put_block_group(block_group); ++ } ++ spin_unlock(&trans->transaction->dirty_bgs_lock); ++ mutex_unlock(&trans->transaction->cache_write_mutex); ++ ++ if (!IS_ERR(inode)) { ++ ret = btrfs_orphan_add(trans, BTRFS_I(inode)); ++ if (ret) { ++ btrfs_add_delayed_iput(inode); ++ goto out; ++ } ++ clear_nlink(inode); ++ /* One for the block groups ref */ ++ spin_lock(&block_group->lock); ++ if (block_group->iref) { ++ block_group->iref = 0; ++ block_group->inode = NULL; ++ spin_unlock(&block_group->lock); ++ iput(inode); ++ } else { ++ spin_unlock(&block_group->lock); ++ } ++ /* One for our lookup ref */ ++ btrfs_add_delayed_iput(inode); ++ } ++ ++ key.objectid = BTRFS_FREE_SPACE_OBJECTID; ++ key.offset = block_group->key.objectid; ++ key.type = 0; ++ ++ ret = btrfs_search_slot(trans, tree_root, &key, path, -1, 1); ++ if (ret < 0) ++ goto out; ++ if (ret > 0) ++ btrfs_release_path(path); ++ if (ret == 0) { ++ ret = btrfs_del_item(trans, tree_root, path); ++ if (ret) ++ goto out; ++ btrfs_release_path(path); ++ } ++ ++ spin_lock(&fs_info->block_group_cache_lock); ++ rb_erase(&block_group->cache_node, ++ &fs_info->block_group_cache_tree); ++ RB_CLEAR_NODE(&block_group->cache_node); ++ ++ if (fs_info->first_logical_byte == block_group->key.objectid) ++ fs_info->first_logical_byte = (u64)-1; ++ spin_unlock(&fs_info->block_group_cache_lock); ++ ++ down_write(&block_group->space_info->groups_sem); ++ /* ++ * we must use list_del_init so people can check to see if they ++ * are still on the list after taking the semaphore ++ */ ++ list_del_init(&block_group->list); ++ if (list_empty(&block_group->space_info->block_groups[index])) { ++ kobj = block_group->space_info->block_group_kobjs[index]; ++ block_group->space_info->block_group_kobjs[index] = NULL; ++ clear_avail_alloc_bits(fs_info, block_group->flags); ++ } ++ up_write(&block_group->space_info->groups_sem); ++ if (kobj) { ++ kobject_del(kobj); ++ kobject_put(kobj); ++ } ++ ++ if (block_group->has_caching_ctl) ++ caching_ctl = btrfs_get_caching_control(block_group); ++ if (block_group->cached == BTRFS_CACHE_STARTED) ++ btrfs_wait_block_group_cache_done(block_group); ++ if (block_group->has_caching_ctl) { ++ down_write(&fs_info->commit_root_sem); ++ if (!caching_ctl) { ++ struct btrfs_caching_control *ctl; ++ ++ list_for_each_entry(ctl, ++ &fs_info->caching_block_groups, list) ++ if (ctl->block_group == block_group) { ++ caching_ctl = ctl; ++ refcount_inc(&caching_ctl->count); ++ break; ++ } ++ } ++ if (caching_ctl) ++ list_del_init(&caching_ctl->list); ++ up_write(&fs_info->commit_root_sem); ++ if (caching_ctl) { ++ /* Once for the caching bgs list and once for us. */ ++ btrfs_put_caching_control(caching_ctl); ++ btrfs_put_caching_control(caching_ctl); ++ } ++ } ++ ++ spin_lock(&trans->transaction->dirty_bgs_lock); ++ WARN_ON(!list_empty(&block_group->dirty_list)); ++ WARN_ON(!list_empty(&block_group->io_list)); ++ spin_unlock(&trans->transaction->dirty_bgs_lock); ++ ++ btrfs_remove_free_space_cache(block_group); ++ ++ spin_lock(&block_group->space_info->lock); ++ list_del_init(&block_group->ro_list); ++ ++ if (btrfs_test_opt(fs_info, ENOSPC_DEBUG)) { ++ WARN_ON(block_group->space_info->total_bytes ++ < block_group->key.offset); ++ WARN_ON(block_group->space_info->bytes_readonly ++ < block_group->key.offset); ++ WARN_ON(block_group->space_info->disk_total ++ < block_group->key.offset * factor); ++ } ++ block_group->space_info->total_bytes -= block_group->key.offset; ++ block_group->space_info->bytes_readonly -= block_group->key.offset; ++ block_group->space_info->disk_total -= block_group->key.offset * factor; ++ ++ spin_unlock(&block_group->space_info->lock); ++ ++ memcpy(&key, &block_group->key, sizeof(key)); ++ ++ mutex_lock(&fs_info->chunk_mutex); ++ if (!list_empty(&em->list)) { ++ /* We're in the transaction->pending_chunks list. */ ++ free_extent_map(em); ++ } ++ spin_lock(&block_group->lock); ++ block_group->removed = 1; ++ /* ++ * At this point trimming can't start on this block group, because we ++ * removed the block group from the tree fs_info->block_group_cache_tree ++ * so no one can't find it anymore and even if someone already got this ++ * block group before we removed it from the rbtree, they have already ++ * incremented block_group->trimming - if they didn't, they won't find ++ * any free space entries because we already removed them all when we ++ * called btrfs_remove_free_space_cache(). ++ * ++ * And we must not remove the extent map from the fs_info->mapping_tree ++ * to prevent the same logical address range and physical device space ++ * ranges from being reused for a new block group. This is because our ++ * fs trim operation (btrfs_trim_fs() / btrfs_ioctl_fitrim()) is ++ * completely transactionless, so while it is trimming a range the ++ * currently running transaction might finish and a new one start, ++ * allowing for new block groups to be created that can reuse the same ++ * physical device locations unless we take this special care. ++ * ++ * There may also be an implicit trim operation if the file system ++ * is mounted with -odiscard. The same protections must remain ++ * in place until the extents have been discarded completely when ++ * the transaction commit has completed. ++ */ ++ remove_em = (atomic_read(&block_group->trimming) == 0); ++ if (!remove_em) { ++ /* ++ * Our em might be in trans->transaction->pending_chunks which ++ * is protected by fs_info->chunk_mutex ([lock|unlock]_chunks), ++ * and so is the fs_info->pinned_chunks list. ++ * ++ * So at this point we must be holding the chunk_mutex to avoid ++ * any races with chunk allocation (more specifically at ++ * volumes.c:contains_pending_extent()), to ensure it always ++ * sees the em, either in the pending_chunks list or in the ++ * pinned_chunks list. ++ */ ++ list_move_tail(&em->list, &fs_info->pinned_chunks); ++ } ++ spin_unlock(&block_group->lock); ++ ++ mutex_unlock(&fs_info->chunk_mutex); ++ ++ ret = remove_block_group_free_space(trans, fs_info, block_group); ++ if (ret) ++ goto out; ++ ++ btrfs_put_block_group(block_group); ++ btrfs_put_block_group(block_group); ++ ++ ret = btrfs_search_slot(trans, root, &key, path, -1, 1); ++ if (ret > 0) ++ ret = -EIO; ++ if (ret < 0) ++ goto out; ++ ++ ret = btrfs_del_item(trans, root, path); ++ if (ret) ++ goto out; ++ ++ if (remove_em) { ++ struct extent_map_tree *em_tree; ++ ++ em_tree = &fs_info->mapping_tree.map_tree; ++ mutex_lock(&fs_info->chunk_mutex); ++ write_lock(&em_tree->lock); ++ /* ++ * The em might be in the pending_chunks list, so make sure the ++ * chunk mutex is locked, since remove_extent_mapping() will ++ * delete us from that list. ++ */ ++ remove_extent_mapping(em_tree, em); ++ write_unlock(&em_tree->lock); ++ mutex_unlock(&fs_info->chunk_mutex); ++ /* once for the tree */ ++ free_extent_map(em); ++ } ++out: ++ if (remove_rsv) ++ btrfs_delayed_refs_rsv_release(fs_info, 1); ++ btrfs_free_path(path); ++ return ret; ++} ++ ++struct btrfs_trans_handle *btrfs_start_trans_remove_block_group( ++ struct btrfs_fs_info *fs_info, const u64 chunk_offset) ++{ ++ struct extent_map_tree *em_tree = &fs_info->mapping_tree.map_tree; ++ struct extent_map *em; ++ struct map_lookup *map; ++ unsigned int num_items; ++ ++ read_lock(&em_tree->lock); ++ em = lookup_extent_mapping(em_tree, chunk_offset, 1); ++ read_unlock(&em_tree->lock); ++ ASSERT(em && em->start == chunk_offset); ++ ++ /* ++ * We need to reserve 3 + N units from the metadata space info in order ++ * to remove a block group (done at btrfs_remove_chunk() and at ++ * btrfs_remove_block_group()), which are used for: ++ * ++ * 1 unit for adding the free space inode's orphan (located in the tree ++ * of tree roots). ++ * 1 unit for deleting the block group item (located in the extent ++ * tree). ++ * 1 unit for deleting the free space item (located in tree of tree ++ * roots). ++ * N units for deleting N device extent items corresponding to each ++ * stripe (located in the device tree). ++ * ++ * In order to remove a block group we also need to reserve units in the ++ * system space info in order to update the chunk tree (update one or ++ * more device items and remove one chunk item), but this is done at ++ * btrfs_remove_chunk() through a call to check_system_chunk(). ++ */ ++ map = em->map_lookup; ++ num_items = 3 + map->num_stripes; ++ free_extent_map(em); ++ ++ return btrfs_start_transaction_fallback_global_rsv(fs_info->extent_root, ++ num_items, 1); ++} ++ ++/* ++ * Process the unused_bgs list and remove any that don't have any allocated ++ * space inside of them. ++ */ ++void btrfs_delete_unused_bgs(struct btrfs_fs_info *fs_info) ++{ ++ struct btrfs_block_group_cache *block_group; ++ struct btrfs_space_info *space_info; ++ struct btrfs_trans_handle *trans; ++ int ret = 0; ++ ++ if (!test_bit(BTRFS_FS_OPEN, &fs_info->flags)) ++ return; ++ ++ spin_lock(&fs_info->unused_bgs_lock); ++ while (!list_empty(&fs_info->unused_bgs)) { ++ u64 start, end; ++ int trimming; ++ ++ block_group = list_first_entry(&fs_info->unused_bgs, ++ struct btrfs_block_group_cache, ++ bg_list); ++ list_del_init(&block_group->bg_list); ++ ++ space_info = block_group->space_info; ++ ++ if (ret || btrfs_mixed_space_info(space_info)) { ++ btrfs_put_block_group(block_group); ++ continue; ++ } ++ spin_unlock(&fs_info->unused_bgs_lock); ++ ++ mutex_lock(&fs_info->delete_unused_bgs_mutex); ++ ++ /* Don't want to race with allocators so take the groups_sem */ ++ down_write(&space_info->groups_sem); ++ spin_lock(&block_group->lock); ++ if (block_group->reserved || block_group->pinned || ++ btrfs_block_group_used(&block_group->item) || ++ block_group->ro || ++ list_is_singular(&block_group->list)) { ++ /* ++ * We want to bail if we made new allocations or have ++ * outstanding allocations in this block group. We do ++ * the ro check in case balance is currently acting on ++ * this block group. ++ */ ++ spin_unlock(&block_group->lock); ++ up_write(&space_info->groups_sem); ++ goto next; ++ } ++ spin_unlock(&block_group->lock); ++ ++ /* We don't want to force the issue, only flip if it's ok. */ ++ ret = __btrfs_inc_block_group_ro(block_group, 0); ++ up_write(&space_info->groups_sem); ++ if (ret < 0) { ++ ret = 0; ++ goto next; ++ } ++ ++ /* ++ * Want to do this before we do anything else so we can recover ++ * properly if we fail to join the transaction. ++ */ ++ trans = btrfs_start_trans_remove_block_group(fs_info, ++ block_group->key.objectid); ++ if (IS_ERR(trans)) { ++ btrfs_dec_block_group_ro(block_group); ++ ret = PTR_ERR(trans); ++ goto next; ++ } ++ ++ /* ++ * We could have pending pinned extents for this block group, ++ * just delete them, we don't care about them anymore. ++ */ ++ start = block_group->key.objectid; ++ end = start + block_group->key.offset - 1; ++ /* ++ * Hold the unused_bg_unpin_mutex lock to avoid racing with ++ * btrfs_finish_extent_commit(). If we are at transaction N, ++ * another task might be running finish_extent_commit() for the ++ * previous transaction N - 1, and have seen a range belonging ++ * to the block group in freed_extents[] before we were able to ++ * clear the whole block group range from freed_extents[]. This ++ * means that task can lookup for the block group after we ++ * unpinned it from freed_extents[] and removed it, leading to ++ * a BUG_ON() at btrfs_unpin_extent_range(). ++ */ ++ mutex_lock(&fs_info->unused_bg_unpin_mutex); ++ ret = clear_extent_bits(&fs_info->freed_extents[0], start, end, ++ EXTENT_DIRTY); ++ if (ret) { ++ mutex_unlock(&fs_info->unused_bg_unpin_mutex); ++ btrfs_dec_block_group_ro(block_group); ++ goto end_trans; ++ } ++ ret = clear_extent_bits(&fs_info->freed_extents[1], start, end, ++ EXTENT_DIRTY); ++ if (ret) { ++ mutex_unlock(&fs_info->unused_bg_unpin_mutex); ++ btrfs_dec_block_group_ro(block_group); ++ goto end_trans; ++ } ++ mutex_unlock(&fs_info->unused_bg_unpin_mutex); ++ ++ /* Reset pinned so btrfs_put_block_group doesn't complain */ ++ spin_lock(&space_info->lock); ++ spin_lock(&block_group->lock); ++ ++ btrfs_space_info_update_bytes_pinned(fs_info, space_info, ++ -block_group->pinned); ++ space_info->bytes_readonly += block_group->pinned; ++ percpu_counter_add(&space_info->total_bytes_pinned, ++ -block_group->pinned); ++ block_group->pinned = 0; ++ ++ spin_unlock(&block_group->lock); ++ spin_unlock(&space_info->lock); ++ ++ /* DISCARD can flip during remount */ ++ trimming = btrfs_test_opt(fs_info, DISCARD); ++ ++ /* Implicit trim during transaction commit. */ ++ if (trimming) ++ btrfs_get_block_group_trimming(block_group); ++ ++ /* ++ * Btrfs_remove_chunk will abort the transaction if things go ++ * horribly wrong. ++ */ ++ ret = btrfs_remove_chunk(trans, fs_info, block_group->key.objectid); ++ ++ if (ret) { ++ if (trimming) ++ btrfs_put_block_group_trimming(block_group); ++ goto end_trans; ++ } ++ ++ /* ++ * If we're not mounted with -odiscard, we can just forget ++ * about this block group. Otherwise we'll need to wait ++ * until transaction commit to do the actual discard. ++ */ ++ if (trimming) { ++ spin_lock(&fs_info->unused_bgs_lock); ++ /* ++ * A concurrent scrub might have added us to the list ++ * fs_info->unused_bgs, so use a list_move operation ++ * to add the block group to the deleted_bgs list. ++ */ ++ list_move(&block_group->bg_list, ++ &trans->transaction->deleted_bgs); ++ spin_unlock(&fs_info->unused_bgs_lock); ++ btrfs_get_block_group(block_group); ++ } ++end_trans: ++ btrfs_end_transaction(trans); ++next: ++ mutex_unlock(&fs_info->delete_unused_bgs_mutex); ++ btrfs_put_block_group(block_group); ++ spin_lock(&fs_info->unused_bgs_lock); ++ } ++ spin_unlock(&fs_info->unused_bgs_lock); ++} +--- a/fs/btrfs/block-group.h ++++ b/fs/btrfs/block-group.h +@@ -176,6 +176,13 @@ struct btrfs_caching_control *btrfs_get_ + struct btrfs_block_group_cache *cache); + u64 add_new_free_space(struct btrfs_block_group_cache *block_group, + u64 start, u64 end); ++struct btrfs_trans_handle *btrfs_start_trans_remove_block_group( ++ struct btrfs_fs_info *fs_info, ++ const u64 chunk_offset); ++int btrfs_remove_block_group(struct btrfs_trans_handle *trans, ++ u64 group_start, struct extent_map *em); ++void btrfs_delete_unused_bgs(struct btrfs_fs_info *fs_info); ++void btrfs_mark_bg_unused(struct btrfs_block_group_cache *bg); + + static inline int btrfs_block_group_cache_done( + struct btrfs_block_group_cache *cache) +--- a/fs/btrfs/ctree.h ++++ b/fs/btrfs/ctree.h +@@ -2537,13 +2537,6 @@ int btrfs_make_block_group(struct btrfs_ + u64 type, u64 chunk_objectid, u64 chunk_offset, + u64 size); + void btrfs_add_raid_kobjects(struct btrfs_fs_info *fs_info); +-struct btrfs_trans_handle *btrfs_start_trans_remove_block_group( +- struct btrfs_fs_info *fs_info, +- const u64 chunk_offset); +-int btrfs_remove_block_group(struct btrfs_trans_handle *trans, +- struct btrfs_fs_info *fs_info, u64 group_start, +- struct extent_map *em); +-void btrfs_delete_unused_bgs(struct btrfs_fs_info *fs_info); + void btrfs_get_block_group_trimming(struct btrfs_block_group_cache *cache); + void btrfs_put_block_group_trimming(struct btrfs_block_group_cache *cache); + void btrfs_create_pending_block_groups(struct btrfs_trans_handle *trans, +--- a/fs/btrfs/extent-tree.c ++++ b/fs/btrfs/extent-tree.c +@@ -7779,528 +7779,6 @@ int btrfs_make_block_group(struct btrfs_ + return 0; + } + +-static void clear_avail_alloc_bits(struct btrfs_fs_info *fs_info, u64 flags) +-{ +- u64 extra_flags = chunk_to_extended(flags) & +- BTRFS_EXTENDED_PROFILE_MASK; +- +- write_seqlock(&fs_info->profiles_lock); +- if (flags & BTRFS_BLOCK_GROUP_DATA) +- fs_info->avail_data_alloc_bits &= ~extra_flags; +- if (flags & BTRFS_BLOCK_GROUP_METADATA) +- fs_info->avail_metadata_alloc_bits &= ~extra_flags; +- if (flags & BTRFS_BLOCK_GROUP_SYSTEM) +- fs_info->avail_system_alloc_bits &= ~extra_flags; +- write_sequnlock(&fs_info->profiles_lock); +-} +- +-int btrfs_remove_block_group(struct btrfs_trans_handle *trans, +- struct btrfs_fs_info *fs_info, u64 group_start, +- struct extent_map *em) +-{ +- struct btrfs_root *root = fs_info->extent_root; +- struct btrfs_path *path; +- struct btrfs_block_group_cache *block_group; +- struct btrfs_free_cluster *cluster; +- struct btrfs_root *tree_root = fs_info->tree_root; +- struct btrfs_key key; +- struct inode *inode; +- struct kobject *kobj = NULL; +- int ret; +- int index; +- int factor; +- struct btrfs_caching_control *caching_ctl = NULL; +- bool remove_em; +- bool remove_rsv = false; +- +- block_group = btrfs_lookup_block_group(fs_info, group_start); +- BUG_ON(!block_group); +- BUG_ON(!block_group->ro); +- +- /* +- * Free the reserved super bytes from this block group before +- * remove it. +- */ +- btrfs_free_excluded_extents(block_group); +- +- memcpy(&key, &block_group->key, sizeof(key)); +- index = get_block_group_index(block_group); +- factor = btrfs_bg_type_to_factor(block_group->flags); +- +- /* make sure this block group isn't part of an allocation cluster */ +- cluster = &fs_info->data_alloc_cluster; +- spin_lock(&cluster->refill_lock); +- btrfs_return_cluster_to_free_space(block_group, cluster); +- spin_unlock(&cluster->refill_lock); +- +- /* +- * make sure this block group isn't part of a metadata +- * allocation cluster +- */ +- cluster = &fs_info->meta_alloc_cluster; +- spin_lock(&cluster->refill_lock); +- btrfs_return_cluster_to_free_space(block_group, cluster); +- spin_unlock(&cluster->refill_lock); +- +- path = btrfs_alloc_path(); +- if (!path) { +- ret = -ENOMEM; +- goto out; +- } +- +- /* +- * get the inode first so any iput calls done for the io_list +- * aren't the final iput (no unlinks allowed now) +- */ +- inode = lookup_free_space_inode(fs_info, block_group, path); +- +- mutex_lock(&trans->transaction->cache_write_mutex); +- /* +- * make sure our free spache cache IO is done before remove the +- * free space inode +- */ +- spin_lock(&trans->transaction->dirty_bgs_lock); +- if (!list_empty(&block_group->io_list)) { +- list_del_init(&block_group->io_list); +- +- WARN_ON(!IS_ERR(inode) && inode != block_group->io_ctl.inode); +- +- spin_unlock(&trans->transaction->dirty_bgs_lock); +- btrfs_wait_cache_io(trans, block_group, path); +- btrfs_put_block_group(block_group); +- spin_lock(&trans->transaction->dirty_bgs_lock); +- } +- +- if (!list_empty(&block_group->dirty_list)) { +- list_del_init(&block_group->dirty_list); +- remove_rsv = true; +- btrfs_put_block_group(block_group); +- } +- spin_unlock(&trans->transaction->dirty_bgs_lock); +- mutex_unlock(&trans->transaction->cache_write_mutex); +- +- if (!IS_ERR(inode)) { +- ret = btrfs_orphan_add(trans, BTRFS_I(inode)); +- if (ret) { +- btrfs_add_delayed_iput(inode); +- goto out; +- } +- clear_nlink(inode); +- /* One for the block groups ref */ +- spin_lock(&block_group->lock); +- if (block_group->iref) { +- block_group->iref = 0; +- block_group->inode = NULL; +- spin_unlock(&block_group->lock); +- iput(inode); +- } else { +- spin_unlock(&block_group->lock); +- } +- /* One for our lookup ref */ +- btrfs_add_delayed_iput(inode); +- } +- +- key.objectid = BTRFS_FREE_SPACE_OBJECTID; +- key.offset = block_group->key.objectid; +- key.type = 0; +- +- ret = btrfs_search_slot(trans, tree_root, &key, path, -1, 1); +- if (ret < 0) +- goto out; +- if (ret > 0) +- btrfs_release_path(path); +- if (ret == 0) { +- ret = btrfs_del_item(trans, tree_root, path); +- if (ret) +- goto out; +- btrfs_release_path(path); +- } +- +- spin_lock(&fs_info->block_group_cache_lock); +- rb_erase(&block_group->cache_node, +- &fs_info->block_group_cache_tree); +- RB_CLEAR_NODE(&block_group->cache_node); +- +- if (fs_info->first_logical_byte == block_group->key.objectid) +- fs_info->first_logical_byte = (u64)-1; +- spin_unlock(&fs_info->block_group_cache_lock); +- +- down_write(&block_group->space_info->groups_sem); +- /* +- * we must use list_del_init so people can check to see if they +- * are still on the list after taking the semaphore +- */ +- list_del_init(&block_group->list); +- if (list_empty(&block_group->space_info->block_groups[index])) { +- kobj = block_group->space_info->block_group_kobjs[index]; +- block_group->space_info->block_group_kobjs[index] = NULL; +- clear_avail_alloc_bits(fs_info, block_group->flags); +- } +- up_write(&block_group->space_info->groups_sem); +- if (kobj) { +- kobject_del(kobj); +- kobject_put(kobj); +- } +- +- if (block_group->has_caching_ctl) +- caching_ctl = btrfs_get_caching_control(block_group); +- if (block_group->cached == BTRFS_CACHE_STARTED) +- btrfs_wait_block_group_cache_done(block_group); +- if (block_group->has_caching_ctl) { +- down_write(&fs_info->commit_root_sem); +- if (!caching_ctl) { +- struct btrfs_caching_control *ctl; +- +- list_for_each_entry(ctl, +- &fs_info->caching_block_groups, list) +- if (ctl->block_group == block_group) { +- caching_ctl = ctl; +- refcount_inc(&caching_ctl->count); +- break; +- } +- } +- if (caching_ctl) +- list_del_init(&caching_ctl->list); +- up_write(&fs_info->commit_root_sem); +- if (caching_ctl) { +- /* Once for the caching bgs list and once for us. */ +- btrfs_put_caching_control(caching_ctl); +- btrfs_put_caching_control(caching_ctl); +- } +- } +- +- spin_lock(&trans->transaction->dirty_bgs_lock); +- if (!list_empty(&block_group->dirty_list)) { +- WARN_ON(1); +- } +- if (!list_empty(&block_group->io_list)) { +- WARN_ON(1); +- } +- spin_unlock(&trans->transaction->dirty_bgs_lock); +- btrfs_remove_free_space_cache(block_group); +- +- spin_lock(&block_group->space_info->lock); +- list_del_init(&block_group->ro_list); +- +- if (btrfs_test_opt(fs_info, ENOSPC_DEBUG)) { +- WARN_ON(block_group->space_info->total_bytes +- < block_group->key.offset); +- WARN_ON(block_group->space_info->bytes_readonly +- < block_group->key.offset); +- WARN_ON(block_group->space_info->disk_total +- < block_group->key.offset * factor); +- } +- block_group->space_info->total_bytes -= block_group->key.offset; +- block_group->space_info->bytes_readonly -= block_group->key.offset; +- block_group->space_info->disk_total -= block_group->key.offset * factor; +- +- spin_unlock(&block_group->space_info->lock); +- +- memcpy(&key, &block_group->key, sizeof(key)); +- +- mutex_lock(&fs_info->chunk_mutex); +- if (!list_empty(&em->list)) { +- /* We're in the transaction->pending_chunks list. */ +- free_extent_map(em); +- } +- spin_lock(&block_group->lock); +- block_group->removed = 1; +- /* +- * At this point trimming can't start on this block group, because we +- * removed the block group from the tree fs_info->block_group_cache_tree +- * so no one can't find it anymore and even if someone already got this +- * block group before we removed it from the rbtree, they have already +- * incremented block_group->trimming - if they didn't, they won't find +- * any free space entries because we already removed them all when we +- * called btrfs_remove_free_space_cache(). +- * +- * And we must not remove the extent map from the fs_info->mapping_tree +- * to prevent the same logical address range and physical device space +- * ranges from being reused for a new block group. This is because our +- * fs trim operation (btrfs_trim_fs() / btrfs_ioctl_fitrim()) is +- * completely transactionless, so while it is trimming a range the +- * currently running transaction might finish and a new one start, +- * allowing for new block groups to be created that can reuse the same +- * physical device locations unless we take this special care. +- * +- * There may also be an implicit trim operation if the file system +- * is mounted with -odiscard. The same protections must remain +- * in place until the extents have been discarded completely when +- * the transaction commit has completed. +- */ +- remove_em = (atomic_read(&block_group->trimming) == 0); +- /* +- * Make sure a trimmer task always sees the em in the pinned_chunks list +- * if it sees block_group->removed == 1 (needs to lock block_group->lock +- * before checking block_group->removed). +- */ +- if (!remove_em) { +- /* +- * Our em might be in trans->transaction->pending_chunks which +- * is protected by fs_info->chunk_mutex ([lock|unlock]_chunks), +- * and so is the fs_info->pinned_chunks list. +- * +- * So at this point we must be holding the chunk_mutex to avoid +- * any races with chunk allocation (more specifically at +- * volumes.c:contains_pending_extent()), to ensure it always +- * sees the em, either in the pending_chunks list or in the +- * pinned_chunks list. +- */ +- list_move_tail(&em->list, &fs_info->pinned_chunks); +- } +- spin_unlock(&block_group->lock); +- mutex_unlock(&fs_info->chunk_mutex); +- +- ret = remove_block_group_free_space(trans, fs_info, block_group); +- if (ret) +- goto out; +- +- btrfs_put_block_group(block_group); +- btrfs_put_block_group(block_group); +- +- ret = btrfs_search_slot(trans, root, &key, path, -1, 1); +- if (ret > 0) +- ret = -EIO; +- if (ret < 0) +- goto out; +- +- ret = btrfs_del_item(trans, root, path); +- if (ret) +- goto out; +- +- if (remove_em) { +- struct extent_map_tree *em_tree; +- +- em_tree = &fs_info->mapping_tree.map_tree; +- mutex_lock(&fs_info->chunk_mutex); +- write_lock(&em_tree->lock); +- /* +- * The em might be in the pending_chunks list, so make sure the +- * chunk mutex is locked, since remove_extent_mapping() will +- * delete us from that list. +- */ +- remove_extent_mapping(em_tree, em); +- write_unlock(&em_tree->lock); +- mutex_unlock(&fs_info->chunk_mutex); +- /* once for the tree */ +- free_extent_map(em); +- } +-out: +- if (remove_rsv) +- btrfs_delayed_refs_rsv_release(fs_info, 1); +- btrfs_free_path(path); +- return ret; +-} +- +-struct btrfs_trans_handle * +-btrfs_start_trans_remove_block_group(struct btrfs_fs_info *fs_info, +- const u64 chunk_offset) +-{ +- struct extent_map_tree *em_tree = &fs_info->mapping_tree.map_tree; +- struct extent_map *em; +- struct map_lookup *map; +- unsigned int num_items; +- +- read_lock(&em_tree->lock); +- em = lookup_extent_mapping(em_tree, chunk_offset, 1); +- read_unlock(&em_tree->lock); +- ASSERT(em && em->start == chunk_offset); +- +- /* +- * We need to reserve 3 + N units from the metadata space info in order +- * to remove a block group (done at btrfs_remove_chunk() and at +- * btrfs_remove_block_group()), which are used for: +- * +- * 1 unit for adding the free space inode's orphan (located in the tree +- * of tree roots). +- * 1 unit for deleting the block group item (located in the extent +- * tree). +- * 1 unit for deleting the free space item (located in tree of tree +- * roots). +- * N units for deleting N device extent items corresponding to each +- * stripe (located in the device tree). +- * +- * In order to remove a block group we also need to reserve units in the +- * system space info in order to update the chunk tree (update one or +- * more device items and remove one chunk item), but this is done at +- * btrfs_remove_chunk() through a call to check_system_chunk(). +- */ +- map = em->map_lookup; +- num_items = 3 + map->num_stripes; +- free_extent_map(em); +- +- return btrfs_start_transaction_fallback_global_rsv(fs_info->extent_root, +- num_items, 1); +-} +- +-/* +- * Process the unused_bgs list and remove any that don't have any allocated +- * space inside of them. +- */ +-void btrfs_delete_unused_bgs(struct btrfs_fs_info *fs_info) +-{ +- struct btrfs_block_group_cache *block_group; +- struct btrfs_space_info *space_info; +- struct btrfs_trans_handle *trans; +- int ret = 0; +- +- if (!test_bit(BTRFS_FS_OPEN, &fs_info->flags)) +- return; +- +- spin_lock(&fs_info->unused_bgs_lock); +- while (!list_empty(&fs_info->unused_bgs)) { +- u64 start, end; +- int trimming; +- +- block_group = list_first_entry(&fs_info->unused_bgs, +- struct btrfs_block_group_cache, +- bg_list); +- list_del_init(&block_group->bg_list); +- +- space_info = block_group->space_info; +- +- if (ret || btrfs_mixed_space_info(space_info)) { +- btrfs_put_block_group(block_group); +- continue; +- } +- spin_unlock(&fs_info->unused_bgs_lock); +- +- mutex_lock(&fs_info->delete_unused_bgs_mutex); +- +- /* Don't want to race with allocators so take the groups_sem */ +- down_write(&space_info->groups_sem); +- spin_lock(&block_group->lock); +- if (block_group->reserved || block_group->pinned || +- btrfs_block_group_used(&block_group->item) || +- block_group->ro || +- list_is_singular(&block_group->list)) { +- /* +- * We want to bail if we made new allocations or have +- * outstanding allocations in this block group. We do +- * the ro check in case balance is currently acting on +- * this block group. +- */ +- spin_unlock(&block_group->lock); +- up_write(&space_info->groups_sem); +- goto next; +- } +- spin_unlock(&block_group->lock); +- +- /* We don't want to force the issue, only flip if it's ok. */ +- ret = __btrfs_inc_block_group_ro(block_group, 0); +- up_write(&space_info->groups_sem); +- if (ret < 0) { +- ret = 0; +- goto next; +- } +- +- /* +- * Want to do this before we do anything else so we can recover +- * properly if we fail to join the transaction. +- */ +- trans = btrfs_start_trans_remove_block_group(fs_info, +- block_group->key.objectid); +- if (IS_ERR(trans)) { +- btrfs_dec_block_group_ro(block_group); +- ret = PTR_ERR(trans); +- goto next; +- } +- +- /* +- * We could have pending pinned extents for this block group, +- * just delete them, we don't care about them anymore. +- */ +- start = block_group->key.objectid; +- end = start + block_group->key.offset - 1; +- /* +- * Hold the unused_bg_unpin_mutex lock to avoid racing with +- * btrfs_finish_extent_commit(). If we are at transaction N, +- * another task might be running finish_extent_commit() for the +- * previous transaction N - 1, and have seen a range belonging +- * to the block group in freed_extents[] before we were able to +- * clear the whole block group range from freed_extents[]. This +- * means that task can lookup for the block group after we +- * unpinned it from freed_extents[] and removed it, leading to +- * a BUG_ON() at btrfs_unpin_extent_range(). +- */ +- mutex_lock(&fs_info->unused_bg_unpin_mutex); +- ret = clear_extent_bits(&fs_info->freed_extents[0], start, end, +- EXTENT_DIRTY); +- if (ret) { +- mutex_unlock(&fs_info->unused_bg_unpin_mutex); +- btrfs_dec_block_group_ro(block_group); +- goto end_trans; +- } +- ret = clear_extent_bits(&fs_info->freed_extents[1], start, end, +- EXTENT_DIRTY); +- if (ret) { +- mutex_unlock(&fs_info->unused_bg_unpin_mutex); +- btrfs_dec_block_group_ro(block_group); +- goto end_trans; +- } +- mutex_unlock(&fs_info->unused_bg_unpin_mutex); +- +- /* Reset pinned so btrfs_put_block_group doesn't complain */ +- spin_lock(&space_info->lock); +- spin_lock(&block_group->lock); +- +- btrfs_space_info_update_bytes_pinned(fs_info, space_info, +- -block_group->pinned); +- space_info->bytes_readonly += block_group->pinned; +- percpu_counter_add(&space_info->total_bytes_pinned, +- -block_group->pinned); +- block_group->pinned = 0; +- +- spin_unlock(&block_group->lock); +- spin_unlock(&space_info->lock); +- +- /* DISCARD can flip during remount */ +- trimming = btrfs_test_opt(fs_info, DISCARD); +- +- /* Implicit trim during transaction commit. */ +- if (trimming) +- btrfs_get_block_group_trimming(block_group); +- +- /* +- * Btrfs_remove_chunk will abort the transaction if things go +- * horribly wrong. +- */ +- ret = btrfs_remove_chunk(trans, fs_info, +- block_group->key.objectid); +- +- if (ret) { +- if (trimming) +- btrfs_put_block_group_trimming(block_group); +- goto end_trans; +- } +- +- /* +- * If we're not mounted with -odiscard, we can just forget +- * about this block group. Otherwise we'll need to wait +- * until transaction commit to do the actual discard. +- */ +- if (trimming) { +- spin_lock(&fs_info->unused_bgs_lock); +- /* +- * A concurrent scrub might have added us to the list +- * fs_info->unused_bgs, so use a list_move operation +- * to add the block group to the deleted_bgs list. +- */ +- list_move(&block_group->bg_list, +- &trans->transaction->deleted_bgs); +- spin_unlock(&fs_info->unused_bgs_lock); +- btrfs_get_block_group(block_group); +- } +-end_trans: +- btrfs_end_transaction(trans); +-next: +- mutex_unlock(&fs_info->delete_unused_bgs_mutex); +- btrfs_put_block_group(block_group); +- spin_lock(&fs_info->unused_bgs_lock); +- } +- spin_unlock(&fs_info->unused_bgs_lock); +-} +- + int btrfs_error_unpin_extent_range(struct btrfs_fs_info *fs_info, + u64 start, u64 end) + { +--- a/fs/btrfs/volumes.c ++++ b/fs/btrfs/volumes.c +@@ -2939,7 +2939,7 @@ int btrfs_remove_chunk(struct btrfs_tran + } + } + +- ret = btrfs_remove_block_group(trans, fs_info, chunk_offset, em); ++ ret = btrfs_remove_block_group(trans, chunk_offset, em); + if (ret) { + btrfs_abort_transaction(trans, ret); + goto out; diff --git a/patches.suse/0013-btrfs-move-btrfs_block_rsv-definitions-into-it-s-own-header.patch b/patches.suse/0013-btrfs-move-btrfs_block_rsv-definitions-into-it-s-own-header.patch new file mode 100644 index 0000000..5198485 --- /dev/null +++ b/patches.suse/0013-btrfs-move-btrfs_block_rsv-definitions-into-it-s-own-header.patch @@ -0,0 +1,218 @@ +From: Josef Bacik +Date: Wed, 19 Jun 2019 13:47:17 -0400 +Subject: btrfs: move btrfs_block_rsv definitions into it's own header +Git-commit: d12ffdd1aa4c165774748265c67af3aa1edab1a0 +Patch-mainline: v5.3-rc1 +References: bsc#1165949 + +Prep work for separating out all of the block_rsv related code into its +own file. + +Signed-off-by: Josef Bacik +Signed-off-by: David Sterba +Acked-by: Nikolay Borisov +--- + fs/btrfs/block-rsv.h | 77 +++++++++++++++++++++++++++++++++++++++++++++++++ + fs/btrfs/ctree.h | 65 ----------------------------------------- + fs/btrfs/extent-tree.c | 8 +---- + 3 files changed, 80 insertions(+), 70 deletions(-) + +--- /dev/null ++++ b/fs/btrfs/block-rsv.h +@@ -0,0 +1,77 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++ ++#ifndef BTRFS_BLOCK_RSV_H ++#define BTRFS_BLOCK_RSV_H ++ ++enum btrfs_reserve_flush_enum; ++ ++/* ++ * Types of block reserves ++ */ ++enum { ++ BTRFS_BLOCK_RSV_GLOBAL, ++ BTRFS_BLOCK_RSV_DELALLOC, ++ BTRFS_BLOCK_RSV_TRANS, ++ BTRFS_BLOCK_RSV_CHUNK, ++ BTRFS_BLOCK_RSV_DELOPS, ++ BTRFS_BLOCK_RSV_DELREFS, ++ BTRFS_BLOCK_RSV_EMPTY, ++ BTRFS_BLOCK_RSV_TEMP, ++}; ++ ++struct btrfs_block_rsv { ++ u64 size; ++ u64 reserved; ++ struct btrfs_space_info *space_info; ++ spinlock_t lock; ++ 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; ++}; ++ ++void btrfs_init_block_rsv(struct btrfs_block_rsv *rsv, unsigned short type); ++struct btrfs_block_rsv *btrfs_alloc_block_rsv(struct btrfs_fs_info *fs_info, ++ 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_fs_info *fs_info, ++ struct btrfs_block_rsv *rsv); ++int btrfs_block_rsv_add(struct btrfs_root *root, ++ struct btrfs_block_rsv *block_rsv, u64 num_bytes, ++ enum btrfs_reserve_flush_enum flush); ++int btrfs_block_rsv_check(struct btrfs_block_rsv *block_rsv, int min_factor); ++int btrfs_block_rsv_refill(struct btrfs_root *root, ++ struct btrfs_block_rsv *block_rsv, u64 min_reserved, ++ enum btrfs_reserve_flush_enum flush); ++int btrfs_block_rsv_migrate(struct btrfs_block_rsv *src_rsv, ++ struct btrfs_block_rsv *dst_rsv, u64 num_bytes, ++ bool update_size); ++int btrfs_block_rsv_use_bytes(struct btrfs_block_rsv *block_rsv, u64 num_bytes); ++int btrfs_cond_migrate_bytes(struct btrfs_fs_info *fs_info, ++ struct btrfs_block_rsv *dest, u64 num_bytes, ++ int min_factor); ++void btrfs_block_rsv_release(struct btrfs_fs_info *fs_info, ++ struct btrfs_block_rsv *block_rsv, ++ u64 num_bytes); ++ ++#endif /* BTRFS_BLOCK_RSV_H */ +--- a/fs/btrfs/ctree.h ++++ b/fs/btrfs/ctree.h +@@ -43,6 +43,7 @@ + #include "extent_io.h" + #include "extent_map.h" + #include "async-thread.h" ++#include "block-rsv.h" + + struct btrfs_trans_handle; + struct btrfs_transaction; +@@ -389,44 +390,6 @@ struct raid_kobject { + struct list_head list; + }; + +-#define BTRFS_BLOCK_RSV_GLOBAL 1 +-#define BTRFS_BLOCK_RSV_DELALLOC 2 +-#define BTRFS_BLOCK_RSV_TRANS 3 +-#define BTRFS_BLOCK_RSV_CHUNK 4 +-#define BTRFS_BLOCK_RSV_DELOPS 5 +-#define BTRFS_BLOCK_RSV_DELREFS 6 +-#define BTRFS_BLOCK_RSV_EMPTY 7 +-#define BTRFS_BLOCK_RSV_TEMP 8 +- +-struct btrfs_block_rsv { +- u64 size; +- u64 reserved; +- struct btrfs_space_info *space_info; +- spinlock_t lock; +- 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; +-}; +- + /* + * free clusters are used to claim free space in relatively large chunks, + * allowing us to do less seeky writes. They are used for all metadata +@@ -2819,32 +2782,6 @@ void btrfs_delalloc_release_metadata(str + 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); +-struct btrfs_block_rsv *btrfs_alloc_block_rsv(struct btrfs_fs_info *fs_info, +- 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_fs_info *fs_info, +- struct btrfs_block_rsv *rsv); +-void __btrfs_free_block_rsv(struct btrfs_block_rsv *rsv); +-int btrfs_block_rsv_add(struct btrfs_root *root, +- struct btrfs_block_rsv *block_rsv, u64 num_bytes, +- enum btrfs_reserve_flush_enum flush); +-int btrfs_block_rsv_check(struct btrfs_block_rsv *block_rsv, int min_factor); +-int btrfs_block_rsv_refill(struct btrfs_root *root, +- struct btrfs_block_rsv *block_rsv, u64 min_reserved, +- enum btrfs_reserve_flush_enum flush); +-int btrfs_block_rsv_migrate(struct btrfs_block_rsv *src_rsv, +- struct btrfs_block_rsv *dst_rsv, u64 num_bytes, +- int update_size); +-int btrfs_block_rsv_use_bytes(struct btrfs_block_rsv *block_rsv, u64 num_bytes); +-int btrfs_cond_migrate_bytes(struct btrfs_fs_info *fs_info, +- struct btrfs_block_rsv *dest, u64 num_bytes, +- int min_factor); +-void btrfs_block_rsv_release(struct btrfs_fs_info *fs_info, +- struct btrfs_block_rsv *block_rsv, +- u64 num_bytes); + void btrfs_delayed_refs_rsv_release(struct btrfs_fs_info *fs_info, int nr); + void btrfs_update_delayed_refs_rsv(struct btrfs_trans_handle *trans); + int btrfs_delayed_refs_rsv_refill(struct btrfs_fs_info *fs_info, +--- a/fs/btrfs/extent-tree.c ++++ b/fs/btrfs/extent-tree.c +@@ -40,6 +40,7 @@ + #include "sysfs.h" + #include "qgroup.h" + #include "space-info.h" ++#include "block-rsv.h" + + #undef SCRAMBLE_DELAYED_REFS + +@@ -4774,7 +4775,7 @@ static u64 block_rsv_release_bytes(struc + + int btrfs_block_rsv_migrate(struct btrfs_block_rsv *src, + struct btrfs_block_rsv *dst, u64 num_bytes, +- int update_size) ++ bool update_size) + { + int ret; + +@@ -4824,11 +4825,6 @@ void btrfs_free_block_rsv(struct btrfs_f + kfree(rsv); + } + +-void __btrfs_free_block_rsv(struct btrfs_block_rsv *rsv) +-{ +- kfree(rsv); +-} +- + int btrfs_block_rsv_add(struct btrfs_root *root, + struct btrfs_block_rsv *block_rsv, u64 num_bytes, + enum btrfs_reserve_flush_enum flush) diff --git a/patches.suse/0013-btrfs-rework-wake_all_tickets.patch b/patches.suse/0013-btrfs-rework-wake_all_tickets.patch new file mode 100644 index 0000000..a379a8b --- /dev/null +++ b/patches.suse/0013-btrfs-rework-wake_all_tickets.patch @@ -0,0 +1,109 @@ +From: Josef Bacik +Date: Wed, 28 Aug 2019 11:12:47 -0400 +Subject: btrfs: rework wake_all_tickets +Git-commit: 2341ccd1bf05b3d844c10ad224cd38b06fd53219 +Patch-mainline: v5.4-rc1 +References: bsc#1165949 + +Now that we no longer partially fill tickets we need to rework +wake_all_tickets to call btrfs_try_to_wakeup_tickets() in order to see +if any subsequent tickets are able to be satisfied. If our tickets_id +changes we know something happened and we can keep flushing. + +Also if we find a ticket that is smaller than the first ticket in our +queue then we want to retry the flushing loop again in case +may_commit_transaction() decides we could satisfy the ticket by +committing the transaction. + +Rename this to maybe_fail_all_tickets() while we're at it, to better +reflect what the function is actually doing. + +Signed-off-by: Josef Bacik +Signed-off-by: David Sterba +Acked-by: Nikolay Borisov +--- + fs/btrfs/space-info.c | 56 ++++++++++++++++++++++++++++++++++++++++++++------- + 1 file changed, 49 insertions(+), 7 deletions(-) + +diff --git a/fs/btrfs/space-info.c b/fs/btrfs/space-info.c +index fe3d7e30bfca..eb4a926ea7b9 100644 +--- a/fs/btrfs/space-info.c ++++ b/fs/btrfs/space-info.c +@@ -679,19 +679,61 @@ static inline int need_do_async_reclaim(struct btrfs_fs_info *fs_info, + !test_bit(BTRFS_FS_STATE_REMOUNTING, &fs_info->fs_state)); + } + +-static bool wake_all_tickets(struct list_head *head) ++/* ++ * maybe_fail_all_tickets - we've exhausted our flushing, start failing tickets ++ * @fs_info - fs_info for this fs ++ * @space_info - the space info we were flushing ++ * ++ * We call this when we've exhausted our flushing ability and haven't made ++ * progress in satisfying tickets. The reservation code handles tickets in ++ * order, so if there is a large ticket first and then smaller ones we could ++ * very well satisfy the smaller tickets. This will attempt to wake up any ++ * tickets in the list to catch this case. ++ * ++ * This function returns true if it was able to make progress by clearing out ++ * other tickets, or if it stumbles across a ticket that was smaller than the ++ * first ticket. ++ */ ++static bool maybe_fail_all_tickets(struct btrfs_fs_info *fs_info, ++ struct btrfs_space_info *space_info) + { + struct reserve_ticket *ticket; ++ u64 tickets_id = space_info->tickets_id; ++ u64 first_ticket_bytes = 0; ++ ++ while (!list_empty(&space_info->tickets) && ++ tickets_id == space_info->tickets_id) { ++ ticket = list_first_entry(&space_info->tickets, ++ struct reserve_ticket, list); ++ ++ /* ++ * may_commit_transaction will avoid committing the transaction ++ * if it doesn't feel like the space reclaimed by the commit ++ * would result in the ticket succeeding. However if we have a ++ * smaller ticket in the queue it may be small enough to be ++ * satisified by committing the transaction, so if any ++ * subsequent ticket is smaller than the first ticket go ahead ++ * and send us back for another loop through the enospc flushing ++ * code. ++ */ ++ if (first_ticket_bytes == 0) ++ first_ticket_bytes = ticket->bytes; ++ else if (first_ticket_bytes > ticket->bytes) ++ return true; + +- while (!list_empty(head)) { +- ticket = list_first_entry(head, struct reserve_ticket, list); + list_del_init(&ticket->list); + ticket->error = -ENOSPC; + wake_up(&ticket->wait); +- if (ticket->bytes != ticket->orig_bytes) +- return true; ++ ++ /* ++ * We're just throwing tickets away, so more flushing may not ++ * trip over btrfs_try_granting_tickets, so we need to call it ++ * here to see if we can make progress with the next ticket in ++ * the list. ++ */ ++ btrfs_try_granting_tickets(fs_info, space_info); + } +- return false; ++ return (tickets_id != space_info->tickets_id); + } + + /* +@@ -759,7 +801,7 @@ static void btrfs_async_reclaim_metadata_space(struct work_struct *work) + if (flush_state > COMMIT_TRANS) { + commit_cycles++; + if (commit_cycles > 2) { +- if (wake_all_tickets(&space_info->tickets)) { ++ if (maybe_fail_all_tickets(fs_info, space_info)) { + flush_state = FLUSH_DELAYED_ITEMS_NR; + commit_cycles--; + } else { + diff --git a/patches.suse/0013-drivers-md-raid5-Use-irqsave-variant-of-atomic_dec_a.patch b/patches.suse/0013-drivers-md-raid5-Use-irqsave-variant-of-atomic_dec_a.patch new file mode 100644 index 0000000..fde98a4 --- /dev/null +++ b/patches.suse/0013-drivers-md-raid5-Use-irqsave-variant-of-atomic_dec_a.patch @@ -0,0 +1,51 @@ +From 685dbcaa25becfba864b72ec3f03470833b7f692 Mon Sep 17 00:00:00 2001 +From: Anna-Maria Gleixner +Date: Tue, 3 Jul 2018 22:01:36 +0200 +Subject: [PATCH] drivers/md/raid5: Use irqsave variant of + atomic_dec_and_lock() +Git-commit: 685dbcaa25becfba864b72ec3f03470833b7f692 +Patch-mainline: v4.19-rc1 +References: bsc#1111974 bsc#1166003 + +The irqsave variant of atomic_dec_and_lock handles irqsave/restore when +taking/releasing the spin lock. With this variant the call of +local_irq_save is no longer required. + +Cc: Shaohua Li +Cc: linux-raid@vger.kernel.org +Acked-by: Peter Zijlstra (Intel) +Signed-off-by: Anna-Maria Gleixner +Signed-off-by: Sebastian Andrzej Siewior +Signed-off-by: Shaohua Li +Signed-off-by: Coly Li + +--- + drivers/md/raid5.c | 5 ++--- + 1 file changed, 2 insertions(+), 3 deletions(-) + +diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c +index 2031506a0ecd..e933bff9459e 100644 +--- a/drivers/md/raid5.c ++++ b/drivers/md/raid5.c +@@ -409,16 +409,15 @@ void raid5_release_stripe(struct stripe_head *sh) + md_wakeup_thread(conf->mddev->thread); + return; + slow_path: +- local_irq_save(flags); + /* we are ok here if STRIPE_ON_RELEASE_LIST is set or not */ +- if (atomic_dec_and_lock(&sh->count, &conf->device_lock)) { ++ if (atomic_dec_and_lock_irqsave(&sh->count, &conf->device_lock, flags)) { + INIT_LIST_HEAD(&list); + hash = sh->hash_lock_index; + do_release_stripe(conf, sh, &list); + spin_unlock(&conf->device_lock); + release_inactive_stripe_list(conf, &list, hash); ++ local_irq_restore(flags); + } +- local_irq_restore(flags); + } + + static inline void remove_hash(struct stripe_head *sh) +-- +2.19.0 + diff --git a/patches.suse/0013-perf-qcom_l2-fix-column-exclusion-check.patch b/patches.suse/0013-perf-qcom_l2-fix-column-exclusion-check.patch deleted file mode 100644 index 509d981..0000000 --- a/patches.suse/0013-perf-qcom_l2-fix-column-exclusion-check.patch +++ /dev/null @@ -1,50 +0,0 @@ -From adbeaf6495d5677a09f547d72f940d909f1f46ee Mon Sep 17 00:00:00 2001 -From: Neil Leeder -Date: Mon, 24 Jul 2017 17:17:02 -0400 -Subject: [PATCH 013/105] perf: qcom_l2: fix column exclusion check - -Git-commit: 6c17c1c3099d7367e67d51290884846dfeecf7bf -Patch-mainline: v4.13-rc3 -References: fate#325865,fate#325861 - -The check for column exclusion did not verify that the event being -checked was an L2 event, and not a software event. -Software events should not be checked for column exclusion. -This resulted in a group with both software and L2 events sometimes -incorrectly rejecting the L2 event for column exclusion and -not counting it. - -Add a check for PMU type before applying column exclusion logic. - -Fixes: 21bdbb7102edeaeb ("perf: add qcom l2 cache perf events driver") -Acked-by: Mark Rutland -Signed-off-by: Neil Leeder -Signed-off-by: Will Deacon -Signed-off-by: Mian Yousaf Kaukab ---- - drivers/perf/qcom_l2_pmu.c | 2 ++ - 1 file changed, 2 insertions(+) - -diff --git a/drivers/perf/qcom_l2_pmu.c b/drivers/perf/qcom_l2_pmu.c -index c259848228b4..b242cce10468 100644 ---- a/drivers/perf/qcom_l2_pmu.c -+++ b/drivers/perf/qcom_l2_pmu.c -@@ -546,6 +546,7 @@ static int l2_cache_event_init(struct perf_event *event) - } - - if ((event != event->group_leader) && -+ !is_software_event(event->group_leader) && - (L2_EVT_GROUP(event->group_leader->attr.config) == - L2_EVT_GROUP(event->attr.config))) { - dev_dbg_ratelimited(&l2cache_pmu->pdev->dev, -@@ -558,6 +559,7 @@ static int l2_cache_event_init(struct perf_event *event) - list_for_each_entry(sibling, &event->group_leader->sibling_list, - group_entry) { - if ((sibling != event) && -+ !is_software_event(sibling) && - (L2_EVT_GROUP(sibling->attr.config) == - L2_EVT_GROUP(event->attr.config))) { - dev_dbg_ratelimited(&l2cache_pmu->pdev->dev, --- -2.11.0 - diff --git a/patches.suse/0014-btrfs-export-btrfs_block_rsv_add_bytes.patch b/patches.suse/0014-btrfs-export-btrfs_block_rsv_add_bytes.patch new file mode 100644 index 0000000..ef4862f --- /dev/null +++ b/patches.suse/0014-btrfs-export-btrfs_block_rsv_add_bytes.patch @@ -0,0 +1,104 @@ +From: Josef Bacik +Date: Wed, 19 Jun 2019 13:47:18 -0400 +Subject: btrfs: export btrfs_block_rsv_add_bytes +Git-commit: 0b50174ad5e9fb32abcfdb10b1a14e76a72b20e6 +Patch-mainline: v5.3-rc1 +References: bsc#1165949 + +This is used in a few places, we need to make sure it's exported so we +can move it around. + +Signed-off-by: Josef Bacik +Signed-off-by: David Sterba +Acked-by: Nikolay Borisov +--- + fs/btrfs/block-rsv.h | 2 ++ + fs/btrfs/extent-tree.c | 18 +++++++++--------- + 2 files changed, 11 insertions(+), 9 deletions(-) + +--- a/fs/btrfs/block-rsv.h ++++ b/fs/btrfs/block-rsv.h +@@ -73,5 +73,7 @@ int btrfs_cond_migrate_bytes(struct btrf + void btrfs_block_rsv_release(struct btrfs_fs_info *fs_info, + struct btrfs_block_rsv *block_rsv, + u64 num_bytes); ++void btrfs_block_rsv_add_bytes(struct btrfs_block_rsv *block_rsv, ++ u64 num_bytes, bool update_size); + + #endif /* BTRFS_BLOCK_RSV_H */ +--- a/fs/btrfs/extent-tree.c ++++ b/fs/btrfs/extent-tree.c +@@ -4596,8 +4596,8 @@ int btrfs_block_rsv_use_bytes(struct btr + return ret; + } + +-static void block_rsv_add_bytes(struct btrfs_block_rsv *block_rsv, +- u64 num_bytes, int update_size) ++void btrfs_block_rsv_add_bytes(struct btrfs_block_rsv *block_rsv, u64 num_bytes, ++ bool update_size) + { + spin_lock(&block_rsv->lock); + block_rsv->reserved += num_bytes; +@@ -4629,7 +4629,7 @@ int btrfs_cond_migrate_bytes(struct btrf + global_rsv->full = 0; + spin_unlock(&global_rsv->lock); + +- block_rsv_add_bytes(dest, num_bytes, 1); ++ btrfs_block_rsv_add_bytes(dest, num_bytes, 1); + return 0; + } + +@@ -4711,7 +4711,7 @@ int btrfs_delayed_refs_rsv_refill(struct + num_bytes, flush); + if (ret) + return ret; +- block_rsv_add_bytes(block_rsv, num_bytes, 0); ++ btrfs_block_rsv_add_bytes(block_rsv, num_bytes, 0); + trace_btrfs_space_reservation(fs_info, "delayed_refs_rsv", + 0, num_bytes, 1); + return 0; +@@ -4783,7 +4783,7 @@ int btrfs_block_rsv_migrate(struct btrfs + if (ret) + return ret; + +- block_rsv_add_bytes(dst, num_bytes, update_size); ++ btrfs_block_rsv_add_bytes(dst, num_bytes, update_size); + return 0; + } + +@@ -4836,7 +4836,7 @@ int btrfs_block_rsv_add(struct btrfs_roo + + ret = btrfs_reserve_metadata_bytes(root, block_rsv, num_bytes, flush); + if (!ret) { +- block_rsv_add_bytes(block_rsv, num_bytes, 1); ++ btrfs_block_rsv_add_bytes(block_rsv, num_bytes, 1); + return 0; + } + +@@ -4883,7 +4883,7 @@ int btrfs_block_rsv_refill(struct btrfs_ + + ret = btrfs_reserve_metadata_bytes(root, block_rsv, num_bytes, flush); + if (!ret) { +- block_rsv_add_bytes(block_rsv, num_bytes, 0); ++ btrfs_block_rsv_add_bytes(block_rsv, num_bytes, 0); + return 0; + } + +@@ -5296,7 +5296,7 @@ int btrfs_delalloc_reserve_metadata(stru + spin_unlock(&inode->lock); + + /* Now we can safely add our space to our block rsv */ +- block_rsv_add_bytes(block_rsv, meta_reserve, false); ++ btrfs_block_rsv_add_bytes(block_rsv, meta_reserve, false); + trace_btrfs_space_reservation(root->fs_info, "delalloc", + btrfs_ino(inode), meta_reserve, 1); + +@@ -7550,7 +7550,7 @@ try_reserve: + static void unuse_block_rsv(struct btrfs_fs_info *fs_info, + struct btrfs_block_rsv *block_rsv, u32 blocksize) + { +- block_rsv_add_bytes(block_rsv, blocksize, 0); ++ btrfs_block_rsv_add_bytes(block_rsv, blocksize, 0); + block_rsv_release_bytes(fs_info, block_rsv, NULL, 0, NULL); + } + diff --git a/patches.suse/0014-btrfs-fix-may_commit_transaction-to-deal-with-no-partial-filling.patch b/patches.suse/0014-btrfs-fix-may_commit_transaction-to-deal-with-no-partial-filling.patch new file mode 100644 index 0000000..ce7e5e1 --- /dev/null +++ b/patches.suse/0014-btrfs-fix-may_commit_transaction-to-deal-with-no-partial-filling.patch @@ -0,0 +1,62 @@ +From: Josef Bacik +Date: Thu, 22 Aug 2019 15:11:00 -0400 +Subject: btrfs: fix may_commit_transaction to deal with no partial filling +Git-commit: 00c0135eb8b8172de48e1accbb09ebfa3aa8bf25 +Patch-mainline: v5.4-rc1 +References: bsc#1165949 + +Now that we aren't partially filling tickets we may have some slack +space left in the space_info. We need to account for this in +may_commit_transaction, otherwise we may choose to not commit the +transaction despite it actually having enough space to satisfy our +ticket. + +Calculate the free space we have in the space_info, if any, and subtract +this from the ticket we have and use that amount to determine if we will +need to commit to reclaim enough space. + +Reviewed-by: Nikolay Borisov +Signed-off-by: Josef Bacik +Signed-off-by: David Sterba +Acked-by: Nikolay Borisov +--- + fs/btrfs/space-info.c | 12 ++++++++++++ + 1 file changed, 12 insertions(+) + +diff --git a/fs/btrfs/space-info.c b/fs/btrfs/space-info.c +index eb4a926ea7b9..3ab7a4810bef 100644 +--- a/fs/btrfs/space-info.c ++++ b/fs/btrfs/space-info.c +@@ -473,12 +473,19 @@ static int may_commit_transaction(struct btrfs_fs_info *fs_info, + struct btrfs_trans_handle *trans; + u64 bytes_needed; + u64 reclaim_bytes = 0; ++ u64 cur_free_bytes = 0; + + trans = (struct btrfs_trans_handle *)current->journal_info; + if (trans) + return -EAGAIN; + + spin_lock(&space_info->lock); ++ cur_free_bytes = btrfs_space_info_used(space_info, true); ++ if (cur_free_bytes < space_info->total_bytes) ++ cur_free_bytes = space_info->total_bytes - cur_free_bytes; ++ else ++ cur_free_bytes = 0; ++ + if (!list_empty(&space_info->priority_tickets)) + ticket = list_first_entry(&space_info->priority_tickets, + struct reserve_ticket, list); +@@ -486,6 +493,11 @@ static int may_commit_transaction(struct btrfs_fs_info *fs_info, + ticket = list_first_entry(&space_info->tickets, + struct reserve_ticket, list); + bytes_needed = (ticket) ? ticket->bytes : 0; ++ ++ if (bytes_needed > cur_free_bytes) ++ bytes_needed -= cur_free_bytes; ++ else ++ bytes_needed = 0; + spin_unlock(&space_info->lock); + + if (!bytes_needed) + diff --git a/patches.suse/0014-btrfs-migrate-the-block-group-read-creation-code.patch b/patches.suse/0014-btrfs-migrate-the-block-group-read-creation-code.patch new file mode 100644 index 0000000..cf13ef3 --- /dev/null +++ b/patches.suse/0014-btrfs-migrate-the-block-group-read-creation-code.patch @@ -0,0 +1,1411 @@ +From: Josef Bacik +Date: Thu, 20 Jun 2019 15:37:57 -0400 +Subject: btrfs: migrate the block group read/creation code +Git-commit: 4358d9635a16a7bc92fecf095fd76d5a3d776188 +Patch-mainline: v5.4-rc1 +References: bsc#1165949 + +All of the prep work has been done so we can now cleanly move this chunk +over. + +Signed-off-by: Josef Bacik +Reviewed-by: David Sterba +[ refresh, add btrfs_get_alloc_profile export, comment updates ] +Signed-off-by: David Sterba +Acked-by: Nikolay Borisov +--- + fs/btrfs/block-group.c | 618 +++++++++++++++++++++++++++++++++++++++++++++++ + fs/btrfs/block-group.h | 7 + fs/btrfs/ctree.h | 8 + fs/btrfs/extent-tree.c | 633 ------------------------------------------------- + 4 files changed, 633 insertions(+), 633 deletions(-) + +--- a/fs/btrfs/block-group.c ++++ b/fs/btrfs/block-group.c +@@ -9,6 +9,8 @@ + #include "disk-io.h" + #include "volumes.h" + #include "transaction.h" ++#include "sysfs.h" ++#include "tree-log.h" + + void btrfs_get_block_group(struct btrfs_block_group_cache *cache) + { +@@ -36,6 +38,45 @@ void btrfs_put_block_group(struct btrfs_ + } + + /* ++ * This adds the block group to the fs_info rb tree for the block group cache ++ */ ++static int btrfs_add_block_group_cache(struct btrfs_fs_info *info, ++ struct btrfs_block_group_cache *block_group) ++{ ++ struct rb_node **p; ++ struct rb_node *parent = NULL; ++ struct btrfs_block_group_cache *cache; ++ ++ spin_lock(&info->block_group_cache_lock); ++ p = &info->block_group_cache_tree.rb_node; ++ ++ while (*p) { ++ parent = *p; ++ cache = rb_entry(parent, struct btrfs_block_group_cache, ++ cache_node); ++ if (block_group->key.objectid < cache->key.objectid) { ++ p = &(*p)->rb_left; ++ } else if (block_group->key.objectid > cache->key.objectid) { ++ p = &(*p)->rb_right; ++ } else { ++ spin_unlock(&info->block_group_cache_lock); ++ return -EEXIST; ++ } ++ } ++ ++ rb_link_node(&block_group->cache_node, parent, p); ++ rb_insert_color(&block_group->cache_node, ++ &info->block_group_cache_tree); ++ ++ if (info->first_logical_byte > block_group->key.objectid) ++ info->first_logical_byte = block_group->key.objectid; ++ ++ spin_unlock(&info->block_group_cache_lock); ++ ++ return 0; ++} ++ ++/* + * This will return the block group at or after bytenr if contains is 0, else + * it will return the block group that contains the bytenr + */ +@@ -1192,3 +1233,580 @@ next: + } + spin_unlock(&fs_info->unused_bgs_lock); + } ++ ++static int find_first_block_group(struct btrfs_fs_info *fs_info, ++ struct btrfs_path *path, ++ struct btrfs_key *key) ++{ ++ struct btrfs_root *root = fs_info->extent_root; ++ int ret = 0; ++ struct btrfs_key found_key; ++ struct extent_buffer *leaf; ++ struct btrfs_block_group_item bg; ++ u64 flags; ++ int slot; ++ ++ ret = btrfs_search_slot(NULL, root, key, path, 0, 0); ++ if (ret < 0) ++ goto out; ++ ++ while (1) { ++ slot = path->slots[0]; ++ leaf = path->nodes[0]; ++ if (slot >= btrfs_header_nritems(leaf)) { ++ ret = btrfs_next_leaf(root, path); ++ if (ret == 0) ++ continue; ++ if (ret < 0) ++ goto out; ++ break; ++ } ++ btrfs_item_key_to_cpu(leaf, &found_key, slot); ++ ++ if (found_key.objectid >= key->objectid && ++ found_key.type == BTRFS_BLOCK_GROUP_ITEM_KEY) { ++ struct extent_map_tree *em_tree; ++ struct extent_map *em; ++ ++ em_tree = &root->fs_info->mapping_tree.map_tree; ++ read_lock(&em_tree->lock); ++ em = lookup_extent_mapping(em_tree, found_key.objectid, ++ found_key.offset); ++ read_unlock(&em_tree->lock); ++ if (!em) { ++ btrfs_err(fs_info, ++ "logical %llu len %llu found bg but no related chunk", ++ found_key.objectid, found_key.offset); ++ ret = -ENOENT; ++ } else if (em->start != found_key.objectid || ++ em->len != found_key.offset) { ++ btrfs_err(fs_info, ++ "block group %llu len %llu mismatch with chunk %llu len %llu", ++ found_key.objectid, found_key.offset, ++ em->start, em->len); ++ ret = -EUCLEAN; ++ } else { ++ read_extent_buffer(leaf, &bg, ++ btrfs_item_ptr_offset(leaf, slot), ++ sizeof(bg)); ++ flags = btrfs_block_group_flags(&bg) & ++ BTRFS_BLOCK_GROUP_TYPE_MASK; ++ ++ if (flags != (em->map_lookup->type & ++ BTRFS_BLOCK_GROUP_TYPE_MASK)) { ++ btrfs_err(fs_info, ++"block group %llu len %llu type flags 0x%llx mismatch with chunk type flags 0x%llx", ++ found_key.objectid, ++ found_key.offset, flags, ++ (BTRFS_BLOCK_GROUP_TYPE_MASK & ++ em->map_lookup->type)); ++ ret = -EUCLEAN; ++ } else { ++ ret = 0; ++ } ++ } ++ free_extent_map(em); ++ goto out; ++ } ++ path->slots[0]++; ++ } ++out: ++ return ret; ++} ++ ++static void set_avail_alloc_bits(struct btrfs_fs_info *fs_info, u64 flags) ++{ ++ u64 extra_flags = chunk_to_extended(flags) & ++ BTRFS_EXTENDED_PROFILE_MASK; ++ ++ write_seqlock(&fs_info->profiles_lock); ++ if (flags & BTRFS_BLOCK_GROUP_DATA) ++ fs_info->avail_data_alloc_bits |= extra_flags; ++ if (flags & BTRFS_BLOCK_GROUP_METADATA) ++ fs_info->avail_metadata_alloc_bits |= extra_flags; ++ if (flags & BTRFS_BLOCK_GROUP_SYSTEM) ++ fs_info->avail_system_alloc_bits |= extra_flags; ++ write_sequnlock(&fs_info->profiles_lock); ++} ++ ++static int exclude_super_stripes(struct btrfs_block_group_cache *cache) ++{ ++ struct btrfs_fs_info *fs_info = cache->fs_info; ++ u64 bytenr; ++ u64 *logical; ++ int stripe_len; ++ int i, nr, ret; ++ ++ if (cache->key.objectid < BTRFS_SUPER_INFO_OFFSET) { ++ stripe_len = BTRFS_SUPER_INFO_OFFSET - cache->key.objectid; ++ cache->bytes_super += stripe_len; ++ ret = btrfs_add_excluded_extent(fs_info, cache->key.objectid, ++ stripe_len); ++ if (ret) ++ return ret; ++ } ++ ++ for (i = 0; i < BTRFS_SUPER_MIRROR_MAX; i++) { ++ bytenr = btrfs_sb_offset(i); ++ ret = btrfs_rmap_block(fs_info, cache->key.objectid, ++ bytenr, 0, &logical, &nr, &stripe_len); ++ if (ret) ++ return ret; ++ ++ while (nr--) { ++ u64 start, len; ++ ++ if (logical[nr] > cache->key.objectid + ++ cache->key.offset) ++ continue; ++ ++ if (logical[nr] + stripe_len <= cache->key.objectid) ++ continue; ++ ++ start = logical[nr]; ++ if (start < cache->key.objectid) { ++ start = cache->key.objectid; ++ len = (logical[nr] + stripe_len) - start; ++ } else { ++ len = min_t(u64, stripe_len, ++ cache->key.objectid + ++ cache->key.offset - start); ++ } ++ ++ cache->bytes_super += len; ++ ret = btrfs_add_excluded_extent(fs_info, start, len); ++ if (ret) { ++ kfree(logical); ++ return ret; ++ } ++ } ++ ++ kfree(logical); ++ } ++ return 0; ++} ++ ++static void link_block_group(struct btrfs_block_group_cache *cache) ++{ ++ struct btrfs_space_info *space_info = cache->space_info; ++ struct btrfs_fs_info *fs_info = cache->fs_info; ++ int index = get_block_group_index(cache); ++ bool first = false; ++ ++ down_write(&space_info->groups_sem); ++ if (list_empty(&space_info->block_groups[index])) ++ first = true; ++ list_add_tail(&cache->list, &space_info->block_groups[index]); ++ up_write(&space_info->groups_sem); ++ ++ if (first) { ++ struct raid_kobject *rkobj = kzalloc(sizeof(*rkobj), GFP_NOFS); ++ if (!rkobj) { ++ btrfs_warn(cache->fs_info, "couldn't alloc memory for raid level kobject"); ++ return; ++ } ++ rkobj->flags = cache->flags; ++ kobject_init(&rkobj->kobj, &btrfs_raid_ktype); ++ ++ spin_lock(&fs_info->pending_raid_kobjs_lock); ++ list_add_tail(&rkobj->list, &fs_info->pending_raid_kobjs); ++ spin_unlock(&fs_info->pending_raid_kobjs_lock); ++ space_info->block_group_kobjs[index] = &rkobj->kobj; ++ } ++} ++ ++static struct btrfs_block_group_cache *btrfs_create_block_group_cache( ++ struct btrfs_fs_info *fs_info, u64 start, u64 size) ++{ ++ struct btrfs_block_group_cache *cache; ++ ++ cache = kzalloc(sizeof(*cache), GFP_NOFS); ++ if (!cache) ++ return NULL; ++ ++ cache->free_space_ctl = kzalloc(sizeof(*cache->free_space_ctl), ++ GFP_NOFS); ++ if (!cache->free_space_ctl) { ++ kfree(cache); ++ return NULL; ++ } ++ ++ cache->key.objectid = start; ++ cache->key.offset = size; ++ cache->key.type = BTRFS_BLOCK_GROUP_ITEM_KEY; ++ ++ cache->fs_info = fs_info; ++ cache->full_stripe_len = btrfs_full_stripe_len(fs_info, ++ &fs_info->mapping_tree, ++ start); ++ set_free_space_tree_thresholds(cache); ++ ++ atomic_set(&cache->count, 1); ++ spin_lock_init(&cache->lock); ++ init_rwsem(&cache->data_rwsem); ++ INIT_LIST_HEAD(&cache->list); ++ INIT_LIST_HEAD(&cache->cluster_list); ++ INIT_LIST_HEAD(&cache->bg_list); ++ INIT_LIST_HEAD(&cache->ro_list); ++ INIT_LIST_HEAD(&cache->dirty_list); ++ INIT_LIST_HEAD(&cache->io_list); ++ btrfs_init_free_space_ctl(cache); ++ atomic_set(&cache->trimming, 0); ++ mutex_init(&cache->free_space_lock); ++ btrfs_init_full_stripe_locks_tree(&cache->full_stripe_locks_root); ++ ++ return cache; ++} ++ ++/* ++ * Iterate all chunks and verify that each of them has the corresponding block ++ * group ++ */ ++static int check_chunk_block_group_mappings(struct btrfs_fs_info *fs_info) ++{ ++ struct btrfs_mapping_tree *map_tree = &fs_info->mapping_tree; ++ struct extent_map *em; ++ struct btrfs_block_group_cache *bg; ++ u64 start = 0; ++ int ret = 0; ++ ++ while (1) { ++ read_lock(&map_tree->map_tree.lock); ++ /* ++ * lookup_extent_mapping will return the first extent map ++ * intersecting the range, so setting @len to 1 is enough to ++ * get the first chunk. ++ */ ++ em = lookup_extent_mapping(&map_tree->map_tree, start, 1); ++ read_unlock(&map_tree->map_tree.lock); ++ if (!em) ++ break; ++ ++ bg = btrfs_lookup_block_group(fs_info, em->start); ++ if (!bg) { ++ btrfs_err(fs_info, ++ "chunk start=%llu len=%llu doesn't have corresponding block group", ++ em->start, em->len); ++ ret = -EUCLEAN; ++ free_extent_map(em); ++ break; ++ } ++ if (bg->key.objectid != em->start || ++ bg->key.offset != em->len || ++ (bg->flags & BTRFS_BLOCK_GROUP_TYPE_MASK) != ++ (em->map_lookup->type & BTRFS_BLOCK_GROUP_TYPE_MASK)) { ++ btrfs_err(fs_info, ++"chunk start=%llu len=%llu flags=0x%llx doesn't match block group start=%llu len=%llu flags=0x%llx", ++ em->start, em->len, ++ em->map_lookup->type & BTRFS_BLOCK_GROUP_TYPE_MASK, ++ bg->key.objectid, bg->key.offset, ++ bg->flags & BTRFS_BLOCK_GROUP_TYPE_MASK); ++ ret = -EUCLEAN; ++ free_extent_map(em); ++ btrfs_put_block_group(bg); ++ break; ++ } ++ start = em->start + em->len; ++ free_extent_map(em); ++ btrfs_put_block_group(bg); ++ } ++ return ret; ++} ++ ++int btrfs_read_block_groups(struct btrfs_fs_info *info) ++{ ++ struct btrfs_path *path; ++ int ret; ++ struct btrfs_block_group_cache *cache; ++ struct btrfs_space_info *space_info; ++ struct btrfs_key key; ++ struct btrfs_key found_key; ++ struct extent_buffer *leaf; ++ int need_clear = 0; ++ u64 cache_gen; ++ u64 feature; ++ int mixed; ++ ++ feature = btrfs_super_incompat_flags(info->super_copy); ++ mixed = !!(feature & BTRFS_FEATURE_INCOMPAT_MIXED_GROUPS); ++ ++ key.objectid = 0; ++ key.offset = 0; ++ key.type = BTRFS_BLOCK_GROUP_ITEM_KEY; ++ path = btrfs_alloc_path(); ++ if (!path) ++ return -ENOMEM; ++ path->reada = READA_FORWARD; ++ ++ cache_gen = btrfs_super_cache_generation(info->super_copy); ++ if (btrfs_test_opt(info, SPACE_CACHE) && ++ btrfs_super_generation(info->super_copy) != cache_gen) ++ need_clear = 1; ++ if (btrfs_test_opt(info, CLEAR_CACHE)) ++ need_clear = 1; ++ ++ while (1) { ++ ret = find_first_block_group(info, path, &key); ++ if (ret > 0) ++ break; ++ if (ret != 0) ++ goto error; ++ ++ leaf = path->nodes[0]; ++ btrfs_item_key_to_cpu(leaf, &found_key, path->slots[0]); ++ ++ cache = btrfs_create_block_group_cache(info, found_key.objectid, ++ found_key.offset); ++ if (!cache) { ++ ret = -ENOMEM; ++ goto error; ++ } ++ ++ if (need_clear) { ++ /* ++ * When we mount with old space cache, we need to ++ * set BTRFS_DC_CLEAR and set dirty flag. ++ * ++ * a) Setting 'BTRFS_DC_CLEAR' makes sure that we ++ * truncate the old free space cache inode and ++ * setup a new one. ++ * b) Setting 'dirty flag' makes sure that we flush ++ * the new space cache info onto disk. ++ */ ++ if (btrfs_test_opt(info, SPACE_CACHE)) ++ cache->disk_cache_state = BTRFS_DC_CLEAR; ++ } ++ ++ read_extent_buffer(leaf, &cache->item, ++ btrfs_item_ptr_offset(leaf, path->slots[0]), ++ sizeof(cache->item)); ++ cache->flags = btrfs_block_group_flags(&cache->item); ++ if (!mixed && ++ ((cache->flags & BTRFS_BLOCK_GROUP_METADATA) && ++ (cache->flags & BTRFS_BLOCK_GROUP_DATA))) { ++ btrfs_err(info, ++"bg %llu is a mixed block group but filesystem hasn't enabled mixed block groups", ++ cache->key.objectid); ++ ret = -EINVAL; ++ goto error; ++ } ++ ++ key.objectid = found_key.objectid + found_key.offset; ++ btrfs_release_path(path); ++ ++ /* ++ * We need to exclude the super stripes now so that the space ++ * info has super bytes accounted for, otherwise we'll think ++ * we have more space than we actually do. ++ */ ++ ret = exclude_super_stripes(cache); ++ if (ret) { ++ /* ++ * We may have excluded something, so call this just in ++ * case. ++ */ ++ btrfs_free_excluded_extents(cache); ++ btrfs_put_block_group(cache); ++ goto error; ++ } ++ ++ /* ++ * check for two cases, either we are full, and therefore ++ * don't need to bother with the caching work since we won't ++ * find any space, or we are empty, and we can just add all ++ * the space in and be done with it. This saves us _alot_ of ++ * time, particularly in the full case. ++ */ ++ if (found_key.offset == btrfs_block_group_used(&cache->item)) { ++ cache->last_byte_to_unpin = (u64)-1; ++ cache->cached = BTRFS_CACHE_FINISHED; ++ btrfs_free_excluded_extents(cache); ++ } else if (btrfs_block_group_used(&cache->item) == 0) { ++ cache->last_byte_to_unpin = (u64)-1; ++ cache->cached = BTRFS_CACHE_FINISHED; ++ add_new_free_space(cache, found_key.objectid, ++ found_key.objectid + ++ found_key.offset); ++ btrfs_free_excluded_extents(cache); ++ } ++ ++ ret = btrfs_add_block_group_cache(info, cache); ++ if (ret) { ++ btrfs_remove_free_space_cache(cache); ++ btrfs_put_block_group(cache); ++ goto error; ++ } ++ ++ trace_btrfs_add_block_group(info, cache, 0); ++ btrfs_update_space_info(info, cache->flags, found_key.offset, ++ btrfs_block_group_used(&cache->item), ++ cache->bytes_super, &space_info); ++ ++ cache->space_info = space_info; ++ ++ link_block_group(cache); ++ ++ set_avail_alloc_bits(info, cache->flags); ++ if (btrfs_chunk_readonly(info, cache->key.objectid)) { ++ __btrfs_inc_block_group_ro(cache, 1); ++ } else if (btrfs_block_group_used(&cache->item) == 0) { ++ spin_lock(&info->unused_bgs_lock); ++ /* Should always be true but just in case. */ ++ if (list_empty(&cache->bg_list)) { ++ btrfs_get_block_group(cache); ++ list_add_tail(&cache->bg_list, ++ &info->unused_bgs); ++ } ++ spin_unlock(&info->unused_bgs_lock); ++ } ++ } ++ ++ list_for_each_entry_rcu(space_info, &info->space_info, list) { ++ if (!(btrfs_get_alloc_profile(info, space_info->flags) & ++ (BTRFS_BLOCK_GROUP_RAID10 | ++ BTRFS_BLOCK_GROUP_RAID1 | ++ BTRFS_BLOCK_GROUP_RAID5 | ++ BTRFS_BLOCK_GROUP_RAID6 | ++ BTRFS_BLOCK_GROUP_DUP))) ++ continue; ++ /* ++ * avoid allocating from un-mirrored block group if there are ++ * mirrored block groups. ++ */ ++ list_for_each_entry(cache, ++ &space_info->block_groups[BTRFS_RAID_RAID0], ++ list) ++ __btrfs_inc_block_group_ro(cache, 1); ++ list_for_each_entry(cache, ++ &space_info->block_groups[BTRFS_RAID_SINGLE], ++ list) ++ __btrfs_inc_block_group_ro(cache, 1); ++ } ++ ++ btrfs_add_raid_kobjects(info); ++ btrfs_init_global_block_rsv(info); ++ ret = check_chunk_block_group_mappings(info); ++error: ++ btrfs_free_path(path); ++ return ret; ++} ++ ++void btrfs_create_pending_block_groups(struct btrfs_trans_handle *trans, ++ struct btrfs_fs_info *fs_info) ++{ ++ struct btrfs_block_group_cache *block_group; ++ struct btrfs_root *extent_root = fs_info->extent_root; ++ struct btrfs_block_group_item item; ++ struct btrfs_key key; ++ int ret = 0; ++ ++ if (!trans->can_flush_pending_bgs) ++ return; ++ ++ while (!list_empty(&trans->new_bgs)) { ++ block_group = list_first_entry(&trans->new_bgs, ++ struct btrfs_block_group_cache, ++ bg_list); ++ if (ret) ++ goto next; ++ ++ spin_lock(&block_group->lock); ++ memcpy(&item, &block_group->item, sizeof(item)); ++ memcpy(&key, &block_group->key, sizeof(key)); ++ spin_unlock(&block_group->lock); ++ ++ ret = btrfs_insert_item(trans, extent_root, &key, &item, ++ sizeof(item)); ++ if (ret) ++ btrfs_abort_transaction(trans, ret); ++ ret = btrfs_finish_chunk_alloc(trans, fs_info, key.objectid, ++ key.offset); ++ if (ret) ++ btrfs_abort_transaction(trans, ret); ++ add_block_group_free_space(trans, fs_info, block_group); ++ /* already aborted the transaction if it failed. */ ++next: ++ btrfs_delayed_refs_rsv_release(fs_info, 1); ++ list_del_init(&block_group->bg_list); ++ } ++ btrfs_trans_release_chunk_metadata(trans); ++} ++ ++int btrfs_make_block_group(struct btrfs_trans_handle *trans, ++ struct btrfs_fs_info *fs_info, u64 bytes_used, ++ u64 type, u64 chunk_objectid, u64 chunk_offset, ++ u64 size) ++{ ++ struct btrfs_block_group_cache *cache; ++ int ret; ++ ++ btrfs_set_log_full_commit(fs_info, trans); ++ ++ cache = btrfs_create_block_group_cache(fs_info, chunk_offset, size); ++ if (!cache) ++ return -ENOMEM; ++ ++ btrfs_set_block_group_used(&cache->item, bytes_used); ++ btrfs_set_block_group_chunk_objectid(&cache->item, chunk_objectid); ++ btrfs_set_block_group_flags(&cache->item, type); ++ ++ cache->flags = type; ++ cache->last_byte_to_unpin = (u64)-1; ++ cache->cached = BTRFS_CACHE_FINISHED; ++ cache->needs_free_space = 1; ++ ret = exclude_super_stripes(cache); ++ if (ret) { ++ /* ++ * We may have excluded something, so call this just in ++ * case. ++ */ ++ btrfs_free_excluded_extents(cache); ++ btrfs_put_block_group(cache); ++ return ret; ++ } ++ ++ add_new_free_space(cache, chunk_offset, chunk_offset + size); ++ ++ btrfs_free_excluded_extents(cache); ++ ++#ifdef CONFIG_BTRFS_DEBUG ++ if (btrfs_should_fragment_free_space(cache)) { ++ u64 new_bytes_used = size - bytes_used; ++ ++ bytes_used += new_bytes_used >> 1; ++ btrfs_fragment_free_space(cache); ++ } ++#endif ++ /* ++ * Ensure the corresponding space_info object is created and ++ * assigned to our block group. We want our bg to be added to the rbtree ++ * with its ->space_info set. ++ */ ++ cache->space_info = btrfs_find_space_info(fs_info, cache->flags); ++ ASSERT(cache->space_info); ++ ++ ret = btrfs_add_block_group_cache(fs_info, cache); ++ if (ret) { ++ btrfs_remove_free_space_cache(cache); ++ btrfs_put_block_group(cache); ++ return ret; ++ } ++ ++ /* ++ * Now that our block group has its ->space_info set and is inserted in ++ * the rbtree, update the space info's counters. ++ */ ++ trace_btrfs_add_block_group(fs_info, cache, 1); ++ btrfs_update_space_info(fs_info, cache->flags, size, bytes_used, ++ cache->bytes_super, &cache->space_info); ++ btrfs_update_global_block_rsv(fs_info); ++ ++ link_block_group(cache); ++ ++ list_add_tail(&cache->bg_list, &trans->new_bgs); ++ trans->delayed_ref_updates++; ++ btrfs_update_delayed_refs_rsv(trans); ++ ++ set_avail_alloc_bits(fs_info, type); ++ return 0; ++} +--- a/fs/btrfs/block-group.h ++++ b/fs/btrfs/block-group.h +@@ -183,6 +183,13 @@ int btrfs_remove_block_group(struct btrf + u64 group_start, struct extent_map *em); + void btrfs_delete_unused_bgs(struct btrfs_fs_info *fs_info); + void btrfs_mark_bg_unused(struct btrfs_block_group_cache *bg); ++int btrfs_read_block_groups(struct btrfs_fs_info *info); ++int btrfs_make_block_group(struct btrfs_trans_handle *trans, ++ struct btrfs_fs_info *fs_info, u64 bytes_used, ++ u64 type, u64 chunk_objectid, u64 chunk_offset, ++ u64 size); ++void btrfs_create_pending_block_groups(struct btrfs_trans_handle *trans, ++ struct btrfs_fs_info *fs_info); + + static inline int btrfs_block_group_cache_done( + struct btrfs_block_group_cache *cache) +--- a/fs/btrfs/ctree.h ++++ b/fs/btrfs/ctree.h +@@ -2530,20 +2530,14 @@ int btrfs_setup_space_cache(struct btrfs + struct btrfs_fs_info *fs_info); + int btrfs_extent_readonly(struct btrfs_fs_info *fs_info, u64 bytenr); + int btrfs_free_block_groups(struct btrfs_fs_info *info); +-int btrfs_read_block_groups(struct btrfs_fs_info *info); + int btrfs_can_relocate(struct btrfs_fs_info *fs_info, u64 bytenr); +-int btrfs_make_block_group(struct btrfs_trans_handle *trans, +- struct btrfs_fs_info *fs_info, u64 bytes_used, +- u64 type, u64 chunk_objectid, u64 chunk_offset, +- u64 size); + void btrfs_add_raid_kobjects(struct btrfs_fs_info *fs_info); + void btrfs_get_block_group_trimming(struct btrfs_block_group_cache *cache); + void btrfs_put_block_group_trimming(struct btrfs_block_group_cache *cache); +-void btrfs_create_pending_block_groups(struct btrfs_trans_handle *trans, +- struct btrfs_fs_info *fs_info); + u64 btrfs_data_alloc_profile(struct btrfs_fs_info *fs_info); + u64 btrfs_metadata_alloc_profile(struct btrfs_fs_info *fs_info); + u64 btrfs_system_alloc_profile(struct btrfs_fs_info *fs_info); ++u64 btrfs_get_alloc_profile(struct btrfs_fs_info *fs_info, u64 orig_flags); + void btrfs_clear_space_info_full(struct btrfs_fs_info *info); + + enum btrfs_reserve_flush_enum { +--- a/fs/btrfs/extent-tree.c ++++ b/fs/btrfs/extent-tree.c +@@ -81,46 +81,6 @@ static int block_group_bits(struct btrfs + return (cache->flags & bits) == bits; + } + +-/* +- * this adds the block group to the fs_info rb tree for the block group +- * cache +- */ +-static int btrfs_add_block_group_cache(struct btrfs_fs_info *info, +- struct btrfs_block_group_cache *block_group) +-{ +- struct rb_node **p; +- struct rb_node *parent = NULL; +- struct btrfs_block_group_cache *cache; +- +- spin_lock(&info->block_group_cache_lock); +- p = &info->block_group_cache_tree.rb_node; +- +- while (*p) { +- parent = *p; +- cache = rb_entry(parent, struct btrfs_block_group_cache, +- cache_node); +- if (block_group->key.objectid < cache->key.objectid) { +- p = &(*p)->rb_left; +- } else if (block_group->key.objectid > cache->key.objectid) { +- p = &(*p)->rb_right; +- } else { +- spin_unlock(&info->block_group_cache_lock); +- return -EEXIST; +- } +- } +- +- rb_link_node(&block_group->cache_node, parent, p); +- rb_insert_color(&block_group->cache_node, +- &info->block_group_cache_tree); +- +- if (info->first_logical_byte > block_group->key.objectid) +- info->first_logical_byte = block_group->key.objectid; +- +- spin_unlock(&info->block_group_cache_lock); +- +- return 0; +-} +- + int btrfs_add_excluded_extent(struct btrfs_fs_info *fs_info, + u64 start, u64 num_bytes) + { +@@ -146,63 +106,6 @@ void btrfs_free_excluded_extents(struct + start, end, EXTENT_UPTODATE); + } + +-static int exclude_super_stripes(struct btrfs_fs_info *fs_info, +- struct btrfs_block_group_cache *cache) +-{ +- u64 bytenr; +- u64 *logical; +- int stripe_len; +- int i, nr, ret; +- +- if (cache->key.objectid < BTRFS_SUPER_INFO_OFFSET) { +- stripe_len = BTRFS_SUPER_INFO_OFFSET - cache->key.objectid; +- cache->bytes_super += stripe_len; +- ret = btrfs_add_excluded_extent(fs_info, cache->key.objectid, +- stripe_len); +- if (ret) +- return ret; +- } +- +- for (i = 0; i < BTRFS_SUPER_MIRROR_MAX; i++) { +- bytenr = btrfs_sb_offset(i); +- ret = btrfs_rmap_block(fs_info, cache->key.objectid, +- bytenr, 0, &logical, &nr, &stripe_len); +- if (ret) +- return ret; +- +- while (nr--) { +- u64 start, len; +- +- if (logical[nr] > cache->key.objectid + +- cache->key.offset) +- continue; +- +- if (logical[nr] + stripe_len <= cache->key.objectid) +- continue; +- +- start = logical[nr]; +- if (start < cache->key.objectid) { +- start = cache->key.objectid; +- len = (logical[nr] + stripe_len) - start; +- } else { +- len = min_t(u64, stripe_len, +- cache->key.objectid + +- cache->key.offset - start); +- } +- +- cache->bytes_super += len; +- ret = btrfs_add_excluded_extent(fs_info, start, len); +- if (ret) { +- kfree(logical); +- return ret; +- } +- } +- +- kfree(logical); +- } +- return 0; +-} +- + static void add_pinned_bytes(struct btrfs_fs_info *fs_info, + struct btrfs_ref *ref, int sign) + { +@@ -3345,21 +3248,6 @@ int btrfs_extent_readonly(struct btrfs_f + return readonly; + } + +-static void set_avail_alloc_bits(struct btrfs_fs_info *fs_info, u64 flags) +-{ +- u64 extra_flags = chunk_to_extended(flags) & +- BTRFS_EXTENDED_PROFILE_MASK; +- +- write_seqlock(&fs_info->profiles_lock); +- if (flags & BTRFS_BLOCK_GROUP_DATA) +- fs_info->avail_data_alloc_bits |= extra_flags; +- if (flags & BTRFS_BLOCK_GROUP_METADATA) +- fs_info->avail_metadata_alloc_bits |= extra_flags; +- if (flags & BTRFS_BLOCK_GROUP_SYSTEM) +- fs_info->avail_system_alloc_bits |= extra_flags; +- write_sequnlock(&fs_info->profiles_lock); +-} +- + /* + * returns target flags in extended format or 0 if restripe for this + * chunk_type is not in progress +@@ -3440,7 +3328,7 @@ static u64 btrfs_reduce_alloc_profile(st + return extended_to_chunk(flags | allowed); + } + +-static u64 get_alloc_profile(struct btrfs_fs_info *fs_info, u64 orig_flags) ++u64 btrfs_get_alloc_profile(struct btrfs_fs_info *fs_info, u64 orig_flags) + { + unsigned seq; + u64 flags; +@@ -3473,23 +3361,23 @@ static u64 get_alloc_profile_by_root(str + else + flags = BTRFS_BLOCK_GROUP_METADATA; + +- ret = get_alloc_profile(fs_info, flags); ++ ret = btrfs_get_alloc_profile(fs_info, flags); + return ret; + } + + u64 btrfs_data_alloc_profile(struct btrfs_fs_info *fs_info) + { +- return get_alloc_profile(fs_info, BTRFS_BLOCK_GROUP_DATA); ++ return btrfs_get_alloc_profile(fs_info, BTRFS_BLOCK_GROUP_DATA); + } + + u64 btrfs_metadata_alloc_profile(struct btrfs_fs_info *fs_info) + { +- return get_alloc_profile(fs_info, BTRFS_BLOCK_GROUP_METADATA); ++ return btrfs_get_alloc_profile(fs_info, BTRFS_BLOCK_GROUP_METADATA); + } + + u64 btrfs_system_alloc_profile(struct btrfs_fs_info *fs_info) + { +- return get_alloc_profile(fs_info, BTRFS_BLOCK_GROUP_SYSTEM); ++ return btrfs_get_alloc_profile(fs_info, BTRFS_BLOCK_GROUP_SYSTEM); + } + + static void force_metadata_allocation(struct btrfs_fs_info *info) +@@ -6885,7 +6773,7 @@ again: + ret = __btrfs_inc_block_group_ro(cache, 0); + if (!ret) + goto out; +- alloc_flags = get_alloc_profile(fs_info, cache->space_info->flags); ++ alloc_flags = btrfs_get_alloc_profile(fs_info, cache->space_info->flags); + ret = btrfs_chunk_alloc(trans, alloc_flags, CHUNK_ALLOC_FORCE); + if (ret < 0) + goto out; +@@ -6906,7 +6794,7 @@ out: + int btrfs_force_chunk_alloc(struct btrfs_trans_handle *trans, + struct btrfs_fs_info *fs_info, u64 type) + { +- u64 alloc_flags = get_alloc_profile(fs_info, type); ++ u64 alloc_flags = btrfs_get_alloc_profile(fs_info, type); + + return btrfs_chunk_alloc(trans, alloc_flags, CHUNK_ALLOC_FORCE); + } +@@ -7117,86 +7005,6 @@ out: + return ret; + } + +-static int find_first_block_group(struct btrfs_fs_info *fs_info, +- struct btrfs_path *path, +- struct btrfs_key *key) +-{ +- struct btrfs_root *root = fs_info->extent_root; +- int ret = 0; +- struct btrfs_key found_key; +- struct extent_buffer *leaf; +- struct btrfs_block_group_item bg; +- u64 flags; +- int slot; +- +- ret = btrfs_search_slot(NULL, root, key, path, 0, 0); +- if (ret < 0) +- goto out; +- +- while (1) { +- slot = path->slots[0]; +- leaf = path->nodes[0]; +- if (slot >= btrfs_header_nritems(leaf)) { +- ret = btrfs_next_leaf(root, path); +- if (ret == 0) +- continue; +- if (ret < 0) +- goto out; +- break; +- } +- btrfs_item_key_to_cpu(leaf, &found_key, slot); +- +- if (found_key.objectid >= key->objectid && +- found_key.type == BTRFS_BLOCK_GROUP_ITEM_KEY) { +- struct extent_map_tree *em_tree; +- struct extent_map *em; +- +- em_tree = &root->fs_info->mapping_tree.map_tree; +- read_lock(&em_tree->lock); +- em = lookup_extent_mapping(em_tree, found_key.objectid, +- found_key.offset); +- read_unlock(&em_tree->lock); +- if (!em) { +- btrfs_err(fs_info, +- "logical %llu len %llu found bg but no related chunk", +- found_key.objectid, found_key.offset); +- ret = -ENOENT; +- } else if (em->start != found_key.objectid || +- em->len != found_key.offset) { +- btrfs_err(fs_info, +- "block group %llu len %llu mismatch with chunk %llu len %llu", +- found_key.objectid, found_key.offset, +- em->start, em->len); +- ret = -EUCLEAN; +- } else { +- read_extent_buffer(leaf, &bg, +- btrfs_item_ptr_offset(leaf, slot), +- sizeof(bg)); +- flags = btrfs_block_group_flags(&bg) & +- BTRFS_BLOCK_GROUP_TYPE_MASK; +- +- if (flags != (em->map_lookup->type & +- BTRFS_BLOCK_GROUP_TYPE_MASK)) { +- btrfs_err(fs_info, +-"block group %llu len %llu type flags 0x%llx mismatch with chunk type flags 0x%llx", +- found_key.objectid, +- found_key.offset, flags, +- (BTRFS_BLOCK_GROUP_TYPE_MASK & +- em->map_lookup->type)); +- ret = -EUCLEAN; +- } else { +- ret = 0; +- } +- } +- free_extent_map(em); +- goto out; +- } +- path->slots[0]++; +- } +-out: +- return ret; +-} +- + void btrfs_put_block_group_cache(struct btrfs_fs_info *info) + { + struct btrfs_block_group_cache *block_group; +@@ -7366,433 +7174,6 @@ void btrfs_add_raid_kobjects(struct btrf + "failed to add kobject for block cache, ignoring"); + } + +-static void link_block_group(struct btrfs_block_group_cache *cache) +-{ +- struct btrfs_space_info *space_info = cache->space_info; +- struct btrfs_fs_info *fs_info = cache->fs_info; +- int index = get_block_group_index(cache); +- bool first = false; +- +- down_write(&space_info->groups_sem); +- if (list_empty(&space_info->block_groups[index])) +- first = true; +- list_add_tail(&cache->list, &space_info->block_groups[index]); +- up_write(&space_info->groups_sem); +- +- if (first) { +- struct raid_kobject *rkobj = kzalloc(sizeof(*rkobj), GFP_NOFS); +- if (!rkobj) { +- btrfs_warn(cache->fs_info, "couldn't alloc memory for raid level kobject"); +- return; +- } +- rkobj->flags = cache->flags; +- kobject_init(&rkobj->kobj, &btrfs_raid_ktype); +- +- spin_lock(&fs_info->pending_raid_kobjs_lock); +- list_add_tail(&rkobj->list, &fs_info->pending_raid_kobjs); +- spin_unlock(&fs_info->pending_raid_kobjs_lock); +- space_info->block_group_kobjs[index] = &rkobj->kobj; +- } +-} +- +-static struct btrfs_block_group_cache * +-btrfs_create_block_group_cache(struct btrfs_fs_info *fs_info, +- u64 start, u64 size) +-{ +- struct btrfs_block_group_cache *cache; +- +- cache = kzalloc(sizeof(*cache), GFP_NOFS); +- if (!cache) +- return NULL; +- +- cache->free_space_ctl = kzalloc(sizeof(*cache->free_space_ctl), +- GFP_NOFS); +- if (!cache->free_space_ctl) { +- kfree(cache); +- return NULL; +- } +- +- cache->key.objectid = start; +- cache->key.offset = size; +- cache->key.type = BTRFS_BLOCK_GROUP_ITEM_KEY; +- +- cache->fs_info = fs_info; +- cache->full_stripe_len = btrfs_full_stripe_len(fs_info, +- &fs_info->mapping_tree, +- start); +- set_free_space_tree_thresholds(cache); +- +- atomic_set(&cache->count, 1); +- spin_lock_init(&cache->lock); +- init_rwsem(&cache->data_rwsem); +- INIT_LIST_HEAD(&cache->list); +- INIT_LIST_HEAD(&cache->cluster_list); +- INIT_LIST_HEAD(&cache->bg_list); +- INIT_LIST_HEAD(&cache->ro_list); +- INIT_LIST_HEAD(&cache->dirty_list); +- INIT_LIST_HEAD(&cache->io_list); +- btrfs_init_free_space_ctl(cache); +- atomic_set(&cache->trimming, 0); +- mutex_init(&cache->free_space_lock); +- btrfs_init_full_stripe_locks_tree(&cache->full_stripe_locks_root); +- +- return cache; +-} +- +- +-/* +- * Iterate all chunks and verify that each of them has the corresponding block +- * group +- */ +-static int check_chunk_block_group_mappings(struct btrfs_fs_info *fs_info) +-{ +- struct btrfs_mapping_tree *map_tree = &fs_info->mapping_tree; +- struct extent_map *em; +- struct btrfs_block_group_cache *bg; +- u64 start = 0; +- int ret = 0; +- +- while (1) { +- read_lock(&map_tree->map_tree.lock); +- /* +- * lookup_extent_mapping will return the first extent map +- * intersecting the range, so setting @len to 1 is enough to +- * get the first chunk. +- */ +- em = lookup_extent_mapping(&map_tree->map_tree, start, 1); +- read_unlock(&map_tree->map_tree.lock); +- if (!em) +- break; +- +- bg = btrfs_lookup_block_group(fs_info, em->start); +- if (!bg) { +- btrfs_err(fs_info, +- "chunk start=%llu len=%llu doesn't have corresponding block group", +- em->start, em->len); +- ret = -EUCLEAN; +- free_extent_map(em); +- break; +- } +- if (bg->key.objectid != em->start || +- bg->key.offset != em->len || +- (bg->flags & BTRFS_BLOCK_GROUP_TYPE_MASK) != +- (em->map_lookup->type & BTRFS_BLOCK_GROUP_TYPE_MASK)) { +- btrfs_err(fs_info, +-"chunk start=%llu len=%llu flags=0x%llx doesn't match block group start=%llu len=%llu flags=0x%llx", +- em->start, em->len, +- em->map_lookup->type & BTRFS_BLOCK_GROUP_TYPE_MASK, +- bg->key.objectid, bg->key.offset, +- bg->flags & BTRFS_BLOCK_GROUP_TYPE_MASK); +- ret = -EUCLEAN; +- free_extent_map(em); +- btrfs_put_block_group(bg); +- break; +- } +- start = em->start + em->len; +- free_extent_map(em); +- btrfs_put_block_group(bg); +- } +- return ret; +-} +- +-int btrfs_read_block_groups(struct btrfs_fs_info *info) +-{ +- struct btrfs_path *path; +- int ret; +- struct btrfs_block_group_cache *cache; +- struct btrfs_space_info *space_info; +- struct btrfs_key key; +- struct btrfs_key found_key; +- struct extent_buffer *leaf; +- int need_clear = 0; +- u64 cache_gen; +- u64 feature; +- int mixed; +- +- feature = btrfs_super_incompat_flags(info->super_copy); +- mixed = !!(feature & BTRFS_FEATURE_INCOMPAT_MIXED_GROUPS); +- +- key.objectid = 0; +- key.offset = 0; +- key.type = BTRFS_BLOCK_GROUP_ITEM_KEY; +- path = btrfs_alloc_path(); +- if (!path) +- return -ENOMEM; +- path->reada = READA_FORWARD; +- +- cache_gen = btrfs_super_cache_generation(info->super_copy); +- if (btrfs_test_opt(info, SPACE_CACHE) && +- btrfs_super_generation(info->super_copy) != cache_gen) +- need_clear = 1; +- if (btrfs_test_opt(info, CLEAR_CACHE)) +- need_clear = 1; +- +- while (1) { +- ret = find_first_block_group(info, path, &key); +- if (ret > 0) +- break; +- if (ret != 0) +- goto error; +- +- leaf = path->nodes[0]; +- btrfs_item_key_to_cpu(leaf, &found_key, path->slots[0]); +- +- cache = btrfs_create_block_group_cache(info, found_key.objectid, +- found_key.offset); +- if (!cache) { +- ret = -ENOMEM; +- goto error; +- } +- +- if (need_clear) { +- /* +- * When we mount with old space cache, we need to +- * set BTRFS_DC_CLEAR and set dirty flag. +- * +- * a) Setting 'BTRFS_DC_CLEAR' makes sure that we +- * truncate the old free space cache inode and +- * setup a new one. +- * b) Setting 'dirty flag' makes sure that we flush +- * the new space cache info onto disk. +- */ +- if (btrfs_test_opt(info, SPACE_CACHE)) +- cache->disk_cache_state = BTRFS_DC_CLEAR; +- } +- +- read_extent_buffer(leaf, &cache->item, +- btrfs_item_ptr_offset(leaf, path->slots[0]), +- sizeof(cache->item)); +- cache->flags = btrfs_block_group_flags(&cache->item); +- if (!mixed && +- ((cache->flags & BTRFS_BLOCK_GROUP_METADATA) && +- (cache->flags & BTRFS_BLOCK_GROUP_DATA))) { +- btrfs_err(info, +-"bg %llu is a mixed block group but filesystem hasn't enabled mixed block groups", +- cache->key.objectid); +- ret = -EINVAL; +- goto error; +- } +- +- key.objectid = found_key.objectid + found_key.offset; +- btrfs_release_path(path); +- +- /* +- * We need to exclude the super stripes now so that the space +- * info has super bytes accounted for, otherwise we'll think +- * we have more space than we actually do. +- */ +- ret = exclude_super_stripes(info, cache); +- if (ret) { +- /* +- * We may have excluded something, so call this just in +- * case. +- */ +- btrfs_free_excluded_extents(cache); +- btrfs_put_block_group(cache); +- goto error; +- } +- +- /* +- * check for two cases, either we are full, and therefore +- * don't need to bother with the caching work since we won't +- * find any space, or we are empty, and we can just add all +- * the space in and be done with it. This saves us _alot_ of +- * time, particularly in the full case. +- */ +- if (found_key.offset == btrfs_block_group_used(&cache->item)) { +- cache->last_byte_to_unpin = (u64)-1; +- cache->cached = BTRFS_CACHE_FINISHED; +- btrfs_free_excluded_extents(cache); +- } else if (btrfs_block_group_used(&cache->item) == 0) { +- cache->last_byte_to_unpin = (u64)-1; +- cache->cached = BTRFS_CACHE_FINISHED; +- add_new_free_space(cache, found_key.objectid, +- found_key.objectid + +- found_key.offset); +- btrfs_free_excluded_extents(cache); +- } +- +- ret = btrfs_add_block_group_cache(info, cache); +- if (ret) { +- btrfs_remove_free_space_cache(cache); +- btrfs_put_block_group(cache); +- goto error; +- } +- +- trace_btrfs_add_block_group(info, cache, 0); +- btrfs_update_space_info(info, cache->flags, found_key.offset, +- btrfs_block_group_used(&cache->item), +- cache->bytes_super, &space_info); +- +- cache->space_info = space_info; +- +- link_block_group(cache); +- +- set_avail_alloc_bits(info, cache->flags); +- if (btrfs_chunk_readonly(info, cache->key.objectid)) { +- __btrfs_inc_block_group_ro(cache, 1); +- } else if (btrfs_block_group_used(&cache->item) == 0) { +- spin_lock(&info->unused_bgs_lock); +- /* Should always be true but just in case. */ +- if (list_empty(&cache->bg_list)) { +- btrfs_get_block_group(cache); +- list_add_tail(&cache->bg_list, +- &info->unused_bgs); +- } +- spin_unlock(&info->unused_bgs_lock); +- } +- } +- +- list_for_each_entry_rcu(space_info, &info->space_info, list) { +- if (!(get_alloc_profile(info, space_info->flags) & +- (BTRFS_BLOCK_GROUP_RAID10 | +- BTRFS_BLOCK_GROUP_RAID1 | +- BTRFS_BLOCK_GROUP_RAID5 | +- BTRFS_BLOCK_GROUP_RAID6 | +- BTRFS_BLOCK_GROUP_DUP))) +- continue; +- /* +- * avoid allocating from un-mirrored block group if there are +- * mirrored block groups. +- */ +- list_for_each_entry(cache, +- &space_info->block_groups[BTRFS_RAID_RAID0], +- list) +- __btrfs_inc_block_group_ro(cache, 1); +- list_for_each_entry(cache, +- &space_info->block_groups[BTRFS_RAID_SINGLE], +- list) +- __btrfs_inc_block_group_ro(cache, 1); +- } +- +- btrfs_add_raid_kobjects(info); +- btrfs_init_global_block_rsv(info); +- ret = check_chunk_block_group_mappings(info); +-error: +- btrfs_free_path(path); +- return ret; +-} +- +-void btrfs_create_pending_block_groups(struct btrfs_trans_handle *trans, +- struct btrfs_fs_info *fs_info) +-{ +- struct btrfs_block_group_cache *block_group; +- struct btrfs_root *extent_root = fs_info->extent_root; +- struct btrfs_block_group_item item; +- struct btrfs_key key; +- int ret = 0; +- +- if (!trans->can_flush_pending_bgs) +- return; +- +- while (!list_empty(&trans->new_bgs)) { +- block_group = list_first_entry(&trans->new_bgs, +- struct btrfs_block_group_cache, +- bg_list); +- if (ret) +- goto next; +- +- spin_lock(&block_group->lock); +- memcpy(&item, &block_group->item, sizeof(item)); +- memcpy(&key, &block_group->key, sizeof(key)); +- spin_unlock(&block_group->lock); +- +- ret = btrfs_insert_item(trans, extent_root, &key, &item, +- sizeof(item)); +- if (ret) +- btrfs_abort_transaction(trans, ret); +- ret = btrfs_finish_chunk_alloc(trans, fs_info, key.objectid, +- key.offset); +- if (ret) +- btrfs_abort_transaction(trans, ret); +- add_block_group_free_space(trans, fs_info, block_group); +- /* already aborted the transaction if it failed. */ +-next: +- btrfs_delayed_refs_rsv_release(fs_info, 1); +- list_del_init(&block_group->bg_list); +- } +- btrfs_trans_release_chunk_metadata(trans); +-} +- +-int btrfs_make_block_group(struct btrfs_trans_handle *trans, +- struct btrfs_fs_info *fs_info, u64 bytes_used, +- u64 type, u64 chunk_objectid, u64 chunk_offset, +- u64 size) +-{ +- struct btrfs_block_group_cache *cache; +- int ret; +- +- btrfs_set_log_full_commit(fs_info, trans); +- +- cache = btrfs_create_block_group_cache(fs_info, chunk_offset, size); +- if (!cache) +- return -ENOMEM; +- +- btrfs_set_block_group_used(&cache->item, bytes_used); +- btrfs_set_block_group_chunk_objectid(&cache->item, chunk_objectid); +- btrfs_set_block_group_flags(&cache->item, type); +- +- cache->flags = type; +- cache->last_byte_to_unpin = (u64)-1; +- cache->cached = BTRFS_CACHE_FINISHED; +- cache->needs_free_space = 1; +- ret = exclude_super_stripes(fs_info, cache); +- if (ret) { +- /* +- * We may have excluded something, so call this just in +- * case. +- */ +- btrfs_free_excluded_extents(cache); +- btrfs_put_block_group(cache); +- return ret; +- } +- +- add_new_free_space(cache, chunk_offset, chunk_offset + size); +- +- btrfs_free_excluded_extents(cache); +- +-#ifdef CONFIG_BTRFS_DEBUG +- if (btrfs_should_fragment_free_space(cache)) { +- u64 new_bytes_used = size - bytes_used; +- +- bytes_used += new_bytes_used >> 1; +- btrfs_fragment_free_space(cache); +- } +-#endif +- /* +- * Ensure the corresponding space_info object is created and +- * assigned to our block group. We want our bg to be added to the rbtree +- * with its ->space_info set. +- */ +- cache->space_info = btrfs_find_space_info(fs_info, cache->flags); +- ASSERT(cache->space_info); +- +- ret = btrfs_add_block_group_cache(fs_info, cache); +- if (ret) { +- btrfs_remove_free_space_cache(cache); +- btrfs_put_block_group(cache); +- return ret; +- } +- +- /* +- * Now that our block group has its ->space_info set and is inserted in +- * the rbtree, update the space info's counters. +- */ +- trace_btrfs_add_block_group(fs_info, cache, 1); +- btrfs_update_space_info(fs_info, cache->flags, size, bytes_used, +- cache->bytes_super, &cache->space_info); +- btrfs_update_global_block_rsv(fs_info); +- +- link_block_group(cache); +- +- list_add_tail(&cache->bg_list, &trans->new_bgs); +- trans->delayed_ref_updates++; +- btrfs_update_delayed_refs_rsv(trans); +- +- set_avail_alloc_bits(fs_info, type); +- return 0; +-} +- + int btrfs_error_unpin_extent_range(struct btrfs_fs_info *fs_info, + u64 start, u64 end) + { diff --git a/patches.suse/0014-btrfs-wait-on-ordered-extents-on-abort-cleanup.patch b/patches.suse/0014-btrfs-wait-on-ordered-extents-on-abort-cleanup.patch new file mode 100644 index 0000000..43e6021 --- /dev/null +++ b/patches.suse/0014-btrfs-wait-on-ordered-extents-on-abort-cleanup.patch @@ -0,0 +1,86 @@ +From: Josef Bacik +Date: Wed, 21 Nov 2018 14:05:45 -0500 +Subject: btrfs: wait on ordered extents on abort cleanup +Git-commit: 74d5d229b1bf60f93bff244b2dfc0eb21ec32a07 +Patch-mainline: v5.0-rc3 +References: bsc#1165949 + +If we flip read-only before we initiate writeback on all dirty pages for +ordered extents we've created then we'll have ordered extents left over +on umount, which results in all sorts of bad things happening. Fix this +by making sure we wait on ordered extents if we have to do the aborted +transaction cleanup stuff. + +generic/475 can produce this warning: + + [ 8531.177332] WARNING: CPU: 2 PID: 11997 at fs/btrfs/disk-io.c:3856 btrfs_free_fs_root+0x95/0xa0 [btrfs] + [ 8531.183282] CPU: 2 PID: 11997 Comm: umount Tainted: G W 5.0.0-rc1-default+ #394 + [ 8531.185164] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996),BIOS rel-1.11.2-0-gf9626cc-prebuilt.qemu-project.org 04/01/2014 + [ 8531.187851] RIP: 0010:btrfs_free_fs_root+0x95/0xa0 [btrfs] + [ 8531.193082] RSP: 0018:ffffb1ab86163d98 EFLAGS: 00010286 + [ 8531.194198] RAX: ffff9f3449494d18 RBX: ffff9f34a2695000 RCX:0000000000000000 + [ 8531.195629] RDX: 0000000000000002 RSI: 0000000000000001 RDI:0000000000000000 + [ 8531.197315] RBP: ffff9f344e930000 R08: 0000000000000001 R09:0000000000000000 + [ 8531.199095] R10: 0000000000000000 R11: ffff9f34494d4ff8 R12:ffffb1ab86163dc0 + [ 8531.200870] R13: ffff9f344e9300b0 R14: ffffb1ab86163db8 R15:0000000000000000 + [ 8531.202707] FS: 00007fc68e949fc0(0000) GS:ffff9f34bd800000(0000)knlGS:0000000000000000 + [ 8531.204851] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 + [ 8531.205942] CR2: 00007ffde8114dd8 CR3: 000000002dfbd000 CR4:00000000000006e0 + [ 8531.207516] Call Trace: + [ 8531.208175] btrfs_free_fs_roots+0xdb/0x170 [btrfs] + [ 8531.210209] ? wait_for_completion+0x5b/0x190 + [ 8531.211303] close_ctree+0x157/0x350 [btrfs] + [ 8531.212412] generic_shutdown_super+0x64/0x100 + [ 8531.213485] kill_anon_super+0x14/0x30 + [ 8531.214430] btrfs_kill_super+0x12/0xa0 [btrfs] + [ 8531.215539] deactivate_locked_super+0x29/0x60 + [ 8531.216633] cleanup_mnt+0x3b/0x70 + [ 8531.217497] task_work_run+0x98/0xc0 + [ 8531.218397] exit_to_usermode_loop+0x83/0x90 + [ 8531.219324] do_syscall_64+0x15b/0x180 + [ 8531.220192] entry_SYSCALL_64_after_hwframe+0x49/0xbe + [ 8531.221286] RIP: 0033:0x7fc68e5e4d07 + [ 8531.225621] RSP: 002b:00007ffde8116608 EFLAGS: 00000246 ORIG_RAX:00000000000000a6 + [ 8531.227512] RAX: 0000000000000000 RBX: 00005580c2175970 RCX:00007fc68e5e4d07 + [ 8531.229098] RDX: 0000000000000001 RSI: 0000000000000000 RDI:00005580c2175b80 + [ 8531.230730] RBP: 0000000000000000 R08: 00005580c2175ba0 R09:00007ffde8114e80 + [ 8531.232269] R10: 0000000000000000 R11: 0000000000000246 R12:00005580c2175b80 + [ 8531.233839] R13: 00007fc68eac61c4 R14: 00005580c2175a68 R15:0000000000000000 + +Leaving a tree in the rb-tree: + +3853 void btrfs_free_fs_root(struct btrfs_root *root) +3854 { +3855 iput(root->ino_cache_inode); +3856 WARN_ON(!RB_EMPTY_ROOT(&root->inode_tree)); + +CC: stable@vger.kernel.org +Reviewed-by: Nikolay Borisov +Signed-off-by: Josef Bacik +[ add stacktrace ] +Signed-off-by: David Sterba +Acked-by: Nikolay Borisov +--- + fs/btrfs/disk-io.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c +index 469a51b4b273..18eefc5b2532 100644 +--- a/fs/btrfs/disk-io.c ++++ b/fs/btrfs/disk-io.c +@@ -4201,6 +4201,14 @@ static void btrfs_destroy_all_ordered_extents(struct btrfs_fs_info *fs_info) + spin_lock(&fs_info->ordered_root_lock); + } + spin_unlock(&fs_info->ordered_root_lock); ++ ++ /* ++ * We need this here because if we've been flipped read-only we won't ++ * get sync() from the umount, so we need to make sure any ordered ++ * extents that haven't had their dirty pages IO start writeout yet ++ * actually get run and error out properly. ++ */ ++ btrfs_wait_ordered_roots(fs_info, U64_MAX, 0, (u64)-1); + } + + static int btrfs_destroy_delayed_refs(struct btrfs_transaction *trans, + diff --git a/patches.suse/0014-drivers-md-raid5-Do-not-disable-irq-on-release_inact.patch b/patches.suse/0014-drivers-md-raid5-Do-not-disable-irq-on-release_inact.patch new file mode 100644 index 0000000..862508c --- /dev/null +++ b/patches.suse/0014-drivers-md-raid5-Do-not-disable-irq-on-release_inact.patch @@ -0,0 +1,45 @@ +From 08edaaa6d6fa5f6ac9be2adcc71f80b4083b6494 Mon Sep 17 00:00:00 2001 +From: Anna-Maria Gleixner +Date: Tue, 3 Jul 2018 22:01:37 +0200 +Subject: [PATCH] drivers/md/raid5: Do not disable irq on + release_inactive_stripe_list() call +Git-commit: 08edaaa6d6fa5f6ac9be2adcc71f80b4083b6494 +Patch-mainline: v4.19-rc1 +References: bsc#1111974 bsc#1166003 + +There is no need to invoke release_inactive_stripe_list() with interrupts +disabled. All call sites, except raid5_release_stripe(), unlock +->device_lock and enable interrupts before invoking the function. + +Make it consistent. + +Cc: Shaohua Li +Cc: linux-raid@vger.kernel.org +Acked-by: Peter Zijlstra (Intel) +Signed-off-by: Anna-Maria Gleixner +Signed-off-by: Sebastian Andrzej Siewior +Signed-off-by: Shaohua Li +Signed-off-by: Coly Li + +--- + drivers/md/raid5.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c +index e933bff9459e..ca1dd0cb04c5 100644 +--- a/drivers/md/raid5.c ++++ b/drivers/md/raid5.c +@@ -414,9 +414,8 @@ void raid5_release_stripe(struct stripe_head *sh) + INIT_LIST_HEAD(&list); + hash = sh->hash_lock_index; + do_release_stripe(conf, sh, &list); +- spin_unlock(&conf->device_lock); ++ spin_unlock_irqrestore(&conf->device_lock, flags); + release_inactive_stripe_list(conf, &list, hash); +- local_irq_restore(flags); + } + } + +-- +2.19.0 + diff --git a/patches.suse/0015-btrfs-export-_btrfs_block_rsv_release.patch b/patches.suse/0015-btrfs-export-_btrfs_block_rsv_release.patch new file mode 100644 index 0000000..4648f94 --- /dev/null +++ b/patches.suse/0015-btrfs-export-_btrfs_block_rsv_release.patch @@ -0,0 +1,77 @@ +From: Josef Bacik +Date: Wed, 19 Jun 2019 13:47:19 -0400 +Subject: btrfs: export __btrfs_block_rsv_release +Git-commit: fed14b323db868c3ac0071925763964a6ca58883 +Patch-mainline: v5.3-rc1 +References: bsc#1165949 + +The delalloc reserve stuff calls this directly because it cares about +the qgroup accounting stuff, so export it so we can move it around. Fix +btrfs_block_rsv_release() to just be a static inline since it just calls +__btrfs_block_rsv_release() with NULL for the qgroup stuff. + +Signed-off-by: Josef Bacik +Signed-off-by: David Sterba +Acked-by: Nikolay Borisov +--- + fs/btrfs/block-rsv.h | 13 ++++++++++--- + fs/btrfs/extent-tree.c | 13 +++---------- + 2 files changed, 13 insertions(+), 13 deletions(-) + +diff --git a/fs/btrfs/block-rsv.h b/fs/btrfs/block-rsv.h +index f4af1c0766a7..feb0a4d4b1c9 100644 +--- a/fs/btrfs/block-rsv.h ++++ b/fs/btrfs/block-rsv.h +@@ -70,10 +70,17 @@ int btrfs_block_rsv_use_bytes(struct btrfs_block_rsv *block_rsv, u64 num_bytes); + int btrfs_cond_migrate_bytes(struct btrfs_fs_info *fs_info, + struct btrfs_block_rsv *dest, u64 num_bytes, + int min_factor); +-void btrfs_block_rsv_release(struct btrfs_fs_info *fs_info, +- struct btrfs_block_rsv *block_rsv, +- u64 num_bytes); + void btrfs_block_rsv_add_bytes(struct btrfs_block_rsv *block_rsv, + u64 num_bytes, bool update_size); ++u64 __btrfs_block_rsv_release(struct btrfs_fs_info *fs_info, ++ struct btrfs_block_rsv *block_rsv, ++ u64 num_bytes, u64 *qgroup_to_release); ++ ++static inline void btrfs_block_rsv_release(struct btrfs_fs_info *fs_info, ++ struct btrfs_block_rsv *block_rsv, ++ u64 num_bytes) ++{ ++ __btrfs_block_rsv_release(fs_info, block_rsv, num_bytes, NULL); ++} + + #endif /* BTRFS_BLOCK_RSV_H */ +diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c +index 2f6e74803c9f..486ddc4c436d 100644 +--- a/fs/btrfs/extent-tree.c ++++ b/fs/btrfs/extent-tree.c +@@ -4674,9 +4674,9 @@ int btrfs_block_rsv_refill(struct btrfs_root *root, + return ret; + } + +-static u64 __btrfs_block_rsv_release(struct btrfs_fs_info *fs_info, +- struct btrfs_block_rsv *block_rsv, +- u64 num_bytes, u64 *qgroup_to_release) ++u64 __btrfs_block_rsv_release(struct btrfs_fs_info *fs_info, ++ struct btrfs_block_rsv *block_rsv, ++ u64 num_bytes, u64 *qgroup_to_release) + { + struct btrfs_block_rsv *global_rsv = &fs_info->global_block_rsv; + struct btrfs_block_rsv *delayed_rsv = &fs_info->delayed_refs_rsv; +@@ -4692,13 +4692,6 @@ static u64 __btrfs_block_rsv_release(struct btrfs_fs_info *fs_info, + qgroup_to_release); + } + +-void btrfs_block_rsv_release(struct btrfs_fs_info *fs_info, +- struct btrfs_block_rsv *block_rsv, +- u64 num_bytes) +-{ +- __btrfs_block_rsv_release(fs_info, block_rsv, num_bytes, NULL); +-} +- + /** + * btrfs_inode_rsv_release - release any excessive reservation. + * @inode - the inode we need to release from. + diff --git a/patches.suse/0015-btrfs-remove-orig_bytes-from-reserve_ticket.patch b/patches.suse/0015-btrfs-remove-orig_bytes-from-reserve_ticket.patch new file mode 100644 index 0000000..51dc31e --- /dev/null +++ b/patches.suse/0015-btrfs-remove-orig_bytes-from-reserve_ticket.patch @@ -0,0 +1,70 @@ +From: Josef Bacik +Date: Thu, 22 Aug 2019 15:11:01 -0400 +Subject: btrfs: remove orig_bytes from reserve_ticket +Git-commit: def936e53530321bc5454883fa5c7ffdaa635837 +Patch-mainline: v5.4-rc1 +References: bsc#1165949 + +Now that we do not do partial filling of tickets simply remove +orig_bytes, it is no longer needed. + +Reviewed-by: Nikolay Borisov +Signed-off-by: Josef Bacik +Signed-off-by: David Sterba +Acked-by: Nikolay Borisov +--- + fs/btrfs/space-info.c | 8 -------- + fs/btrfs/space-info.h | 1 - + 2 files changed, 9 deletions(-) + +diff --git a/fs/btrfs/space-info.c b/fs/btrfs/space-info.c +index 3ab7a4810bef..af53c3344598 100644 +--- a/fs/btrfs/space-info.c ++++ b/fs/btrfs/space-info.c +@@ -920,7 +920,6 @@ static int handle_reserve_ticket(struct btrfs_fs_info *fs_info, + struct reserve_ticket *ticket, + enum btrfs_reserve_flush_enum flush) + { +- u64 reclaim_bytes = 0; + int ret; + + switch (flush) { +@@ -945,17 +944,11 @@ static int handle_reserve_ticket(struct btrfs_fs_info *fs_info, + spin_lock(&space_info->lock); + ret = ticket->error; + if (ticket->bytes || ticket->error) { +- if (ticket->bytes < ticket->orig_bytes) +- reclaim_bytes = ticket->orig_bytes - ticket->bytes; + list_del_init(&ticket->list); + if (!ret) + ret = -ENOSPC; + } + spin_unlock(&space_info->lock); +- +- if (reclaim_bytes) +- btrfs_space_info_add_old_bytes(fs_info, space_info, +- reclaim_bytes); + ASSERT(list_empty(&ticket->list)); + return ret; + } +@@ -1015,7 +1008,6 @@ static int __reserve_metadata_bytes(struct btrfs_fs_info *fs_info, + * the list and we will do our own flushing further down. + */ + if (ret && flush != BTRFS_RESERVE_NO_FLUSH) { +- ticket.orig_bytes = orig_bytes; + ticket.bytes = orig_bytes; + ticket.error = 0; + init_waitqueue_head(&ticket.wait); +diff --git a/fs/btrfs/space-info.h b/fs/btrfs/space-info.h +index b844e50a6a49..dc6ee66ed600 100644 +--- a/fs/btrfs/space-info.h ++++ b/fs/btrfs/space-info.h +@@ -70,7 +70,6 @@ struct btrfs_space_info { + }; + + struct reserve_ticket { +- u64 orig_bytes; + u64 bytes; + int error; + struct list_head list; + diff --git a/patches.suse/0015-btrfs-run-delayed-iputs-before-committing.patch b/patches.suse/0015-btrfs-run-delayed-iputs-before-committing.patch new file mode 100644 index 0000000..32330a2 --- /dev/null +++ b/patches.suse/0015-btrfs-run-delayed-iputs-before-committing.patch @@ -0,0 +1,43 @@ +From: Josef Bacik +Date: Fri, 11 Jan 2019 10:21:01 -0500 +Subject: btrfs: run delayed iputs before committing +Git-commit: 3ec9a4c81c8cc2a8d9673588dd84d9cc7c31019b +Patch-mainline: v5.0-rc3 +References: bsc#1165949 + +Delayed iputs means we can have final iputs of deleted inodes in the +queue, which could potentially generate a lot of pinned space that could +be free'd. So before we decide to commit the transaction for ENOPSC +reasons, run the delayed iputs so that any potential space is free'd up. +If there is and we freed enough we can then commit the transaction and +potentially be able to make our reservation. + +Reviewed-by: Omar Sandoval +Signed-off-by: Josef Bacik +Signed-off-by: David Sterba +Acked-by: Nikolay Borisov +--- + fs/btrfs/extent-tree.c | 9 +++++++++ + 1 file changed, 9 insertions(+) + +diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c +index 6f6fae410fc1..d81035b7ea7d 100644 +--- a/fs/btrfs/extent-tree.c ++++ b/fs/btrfs/extent-tree.c +@@ -4952,6 +4952,15 @@ static void flush_space(struct btrfs_fs_info *fs_info, + ret = 0; + break; + case COMMIT_TRANS: ++ /* ++ * If we have pending delayed iputs then we could free up a ++ * bunch of pinned space, so make sure we run the iputs before ++ * we do our pinned bytes check below. ++ */ ++ mutex_lock(&fs_info->cleaner_delayed_iput_mutex); ++ btrfs_run_delayed_iputs(fs_info); ++ mutex_unlock(&fs_info->cleaner_delayed_iput_mutex); ++ + ret = may_commit_transaction(fs_info, space_info); + break; + default: + diff --git a/patches.suse/0015-btrfs-temporarily-export-btrfs_get_restripe_target.patch b/patches.suse/0015-btrfs-temporarily-export-btrfs_get_restripe_target.patch new file mode 100644 index 0000000..62dfa12 --- /dev/null +++ b/patches.suse/0015-btrfs-temporarily-export-btrfs_get_restripe_target.patch @@ -0,0 +1,66 @@ +From: Josef Bacik +Date: Thu, 20 Jun 2019 15:37:58 -0400 +Subject: btrfs: temporarily export btrfs_get_restripe_target +Git-commit: 8484764e8587dc3defa9579b795e3f7bbf9789c5 +Patch-mainline: v5.4-rc1 +References: bsc#1165949 + +This gets used by a few different logical chunks of the block group +code, export it while we move things around. + +Signed-off-by: Josef Bacik +Reviewed-by: David Sterba +Signed-off-by: David Sterba +Acked-by: Nikolay Borisov +--- + fs/btrfs/block-group.h | 1 + + fs/btrfs/extent-tree.c | 8 ++++---- + 2 files changed, 5 insertions(+), 4 deletions(-) + +--- a/fs/btrfs/block-group.h ++++ b/fs/btrfs/block-group.h +@@ -200,5 +200,6 @@ static inline int btrfs_block_group_cach + } + + int __btrfs_inc_block_group_ro(struct btrfs_block_group_cache *cache, int force); ++u64 btrfs_get_restripe_target(struct btrfs_fs_info *fs_info, u64 flags); + + #endif /* BTRFS_BLOCK_GROUP_H */ +--- a/fs/btrfs/extent-tree.c ++++ b/fs/btrfs/extent-tree.c +@@ -3254,7 +3254,7 @@ int btrfs_extent_readonly(struct btrfs_f + * + * should be called with either volume_mutex or balance_lock held + */ +-static u64 get_restripe_target(struct btrfs_fs_info *fs_info, u64 flags) ++u64 btrfs_get_restripe_target(struct btrfs_fs_info *fs_info, u64 flags) + { + struct btrfs_balance_control *bctl = fs_info->balance_ctl; + u64 target = 0; +@@ -3295,7 +3295,7 @@ static u64 btrfs_reduce_alloc_profile(st + * try to reduce to the target profile + */ + spin_lock(&fs_info->balance_lock); +- target = get_restripe_target(fs_info, flags); ++ target = btrfs_get_restripe_target(fs_info, flags); + if (target) { + /* pick target profile only if it's already available */ + if ((flags & target) & BTRFS_EXTENDED_PROFILE_MASK) { +@@ -6625,7 +6625,7 @@ static u64 update_block_group_flags(stru + * if restripe for this chunk_type is on pick target profile and + * return, otherwise do the usual balance + */ +- stripped = get_restripe_target(fs_info, flags); ++ stripped = btrfs_get_restripe_target(fs_info, flags); + if (stripped) + return extended_to_chunk(stripped); + +@@ -6933,7 +6933,7 @@ int btrfs_can_relocate(struct btrfs_fs_i + * 3: raid0 + * 4: single + */ +- target = get_restripe_target(fs_info, block_group->flags); ++ target = btrfs_get_restripe_target(fs_info, block_group->flags); + if (target) { + index = __get_raid_index(extended_to_chunk(target)); + } else { diff --git a/patches.suse/0016-btrfs-cleanup-the-target-logic-in-_btrfs_block_rsv_release.patch b/patches.suse/0016-btrfs-cleanup-the-target-logic-in-_btrfs_block_rsv_release.patch new file mode 100644 index 0000000..256b2e7 --- /dev/null +++ b/patches.suse/0016-btrfs-cleanup-the-target-logic-in-_btrfs_block_rsv_release.patch @@ -0,0 +1,46 @@ +From: Josef Bacik +Date: Wed, 19 Jun 2019 13:47:20 -0400 +Subject: btrfs: cleanup the target logic in __btrfs_block_rsv_release +Git-commit: fcec36224fc674953eadfca05c69225e6595641b +Patch-mainline: v5.3-rc1 +References: bsc#1165949 + +This works for all callers already, but if we wanted to use the helper +for the global_block_rsv it would end up trying to refill itself. Fix +the logic to be able to be used no matter which block rsv is passed in +to this helper. + +Signed-off-by: Josef Bacik +Signed-off-by: David Sterba +Acked-by: Nikolay Borisov +--- + fs/btrfs/extent-tree.c | 12 +++++++++--- + 1 file changed, 9 insertions(+), 3 deletions(-) + +diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c +index 486ddc4c436d..a457776c3e41 100644 +--- a/fs/btrfs/extent-tree.c ++++ b/fs/btrfs/extent-tree.c +@@ -4680,12 +4680,18 @@ u64 __btrfs_block_rsv_release(struct btrfs_fs_info *fs_info, + { + struct btrfs_block_rsv *global_rsv = &fs_info->global_block_rsv; + struct btrfs_block_rsv *delayed_rsv = &fs_info->delayed_refs_rsv; +- struct btrfs_block_rsv *target = delayed_rsv; ++ struct btrfs_block_rsv *target = NULL; + +- if (target->full || target == block_rsv) ++ /* ++ * If we are the delayed_rsv then push to the global rsv, otherwise dump ++ * into the delayed rsv if it is not full. ++ */ ++ if (block_rsv == delayed_rsv) + target = global_rsv; ++ else if (block_rsv != global_rsv && !delayed_rsv->full) ++ target = delayed_rsv; + +- if (block_rsv->space_info != target->space_info) ++ if (target && block_rsv->space_info != target->space_info) + target = NULL; + + return block_rsv_release_bytes(fs_info, block_rsv, target, num_bytes, + diff --git a/patches.suse/0016-btrfs-migrate-inc-dec_block_group_ro-code.patch b/patches.suse/0016-btrfs-migrate-inc-dec_block_group_ro-code.patch new file mode 100644 index 0000000..93f0035 --- /dev/null +++ b/patches.suse/0016-btrfs-migrate-inc-dec_block_group_ro-code.patch @@ -0,0 +1,505 @@ +From: Josef Bacik +Date: Thu, 20 Jun 2019 15:37:59 -0400 +Subject: btrfs: migrate inc/dec_block_group_ro code +Git-commit: 26ce2095e03c248759951d81fdff37e2bf32601c +Patch-mainline: v5.4-rc1 +References: bsc#1165949 + +This can easily be moved now. + +Signed-off-by: Josef Bacik +Reviewed-by: David Sterba +[ refresh ] +Signed-off-by: David Sterba +Acked-by: Nikolay Borisov +--- + fs/btrfs/block-group.c | 213 +++++++++++++++++++++++++++++++++++++++++++++++++ + fs/btrfs/block-group.h | 2 + fs/btrfs/ctree.h | 3 + fs/btrfs/extent-tree.c | 195 -------------------------------------------- + fs/btrfs/relocation.c | 2 + fs/btrfs/scrub.c | 2 + 6 files changed, 217 insertions(+), 200 deletions(-) + +--- a/fs/btrfs/block-group.c ++++ b/fs/btrfs/block-group.c +@@ -1068,6 +1068,80 @@ struct btrfs_trans_handle *btrfs_start_t + } + + /* ++ * Mark block group @cache read-only, so later write won't happen to block ++ * group @cache. ++ * ++ * If @force is not set, this function will only mark the block group readonly ++ * if we have enough free space (1M) in other metadata/system block groups. ++ * If @force is not set, this function will mark the block group readonly ++ * without checking free space. ++ * ++ * NOTE: This function doesn't care if other block groups can contain all the ++ * data in this block group. That check should be done by relocation routine, ++ * not this function. ++ */ ++int __btrfs_inc_block_group_ro(struct btrfs_block_group_cache *cache, int force) ++{ ++ struct btrfs_space_info *sinfo = cache->space_info; ++ u64 num_bytes; ++ u64 sinfo_used; ++ u64 min_allocable_bytes; ++ int ret = -ENOSPC; ++ ++ /* ++ * We need some metadata space and system metadata space for ++ * allocating chunks in some corner cases until we force to set ++ * it to be readonly. ++ */ ++ if ((sinfo->flags & ++ (BTRFS_BLOCK_GROUP_SYSTEM | BTRFS_BLOCK_GROUP_METADATA)) && ++ !force) ++ min_allocable_bytes = SZ_1M; ++ else ++ min_allocable_bytes = 0; ++ ++ spin_lock(&sinfo->lock); ++ spin_lock(&cache->lock); ++ ++ if (cache->ro) { ++ cache->ro++; ++ ret = 0; ++ goto out; ++ } ++ ++ num_bytes = cache->key.offset - cache->reserved - cache->pinned - ++ cache->bytes_super - btrfs_block_group_used(&cache->item); ++ sinfo_used = btrfs_space_info_used(sinfo, true); ++ ++ /* ++ * sinfo_used + num_bytes should always <= sinfo->total_bytes. ++ * ++ * Here we make sure if we mark this bg RO, we still have enough ++ * free space as buffer (if min_allocable_bytes is not 0). ++ */ ++ if (sinfo_used + num_bytes + min_allocable_bytes <= ++ sinfo->total_bytes) { ++ sinfo->bytes_readonly += num_bytes; ++ cache->ro++; ++ list_add_tail(&cache->ro_list, &sinfo->ro_bgs); ++ ret = 0; ++ } ++out: ++ spin_unlock(&cache->lock); ++ spin_unlock(&sinfo->lock); ++ if (ret == -ENOSPC && btrfs_test_opt(cache->fs_info, ENOSPC_DEBUG)) { ++ btrfs_info(cache->fs_info, ++ "unable to make block group %llu ro", ++ cache->key.objectid); ++ btrfs_info(cache->fs_info, ++ "sinfo_used=%llu bg_num_bytes=%llu min_allocable=%llu", ++ sinfo_used, num_bytes, min_allocable_bytes); ++ btrfs_dump_space_info(cache->fs_info, cache->space_info, 0, 0); ++ } ++ return ret; ++} ++ ++/* + * Process the unused_bgs list and remove any that don't have any allocated + * space inside of them. + */ +@@ -1810,3 +1884,142 @@ int btrfs_make_block_group(struct btrfs_ + set_avail_alloc_bits(fs_info, type); + return 0; + } ++ ++static u64 update_block_group_flags(struct btrfs_fs_info *fs_info, u64 flags) ++{ ++ u64 num_devices; ++ u64 stripped; ++ ++ /* ++ * if restripe for this chunk_type is on pick target profile and ++ * return, otherwise do the usual balance ++ */ ++ stripped = btrfs_get_restripe_target(fs_info, flags); ++ if (stripped) ++ return extended_to_chunk(stripped); ++ ++ num_devices = fs_info->fs_devices->rw_devices; ++ ++ stripped = BTRFS_BLOCK_GROUP_RAID0 | ++ BTRFS_BLOCK_GROUP_RAID5 | BTRFS_BLOCK_GROUP_RAID6 | ++ BTRFS_BLOCK_GROUP_RAID1 | BTRFS_BLOCK_GROUP_RAID10; ++ ++ if (num_devices == 1) { ++ stripped |= BTRFS_BLOCK_GROUP_DUP; ++ stripped = flags & ~stripped; ++ ++ /* turn raid0 into single device chunks */ ++ if (flags & BTRFS_BLOCK_GROUP_RAID0) ++ return stripped; ++ ++ /* turn mirroring into duplication */ ++ if (flags & (BTRFS_BLOCK_GROUP_RAID1 | ++ BTRFS_BLOCK_GROUP_RAID10)) ++ return stripped | BTRFS_BLOCK_GROUP_DUP; ++ } else { ++ /* they already had raid on here, just return */ ++ if (flags & stripped) ++ return flags; ++ ++ stripped |= BTRFS_BLOCK_GROUP_DUP; ++ stripped = flags & ~stripped; ++ ++ /* switch duplicated blocks with raid1 */ ++ if (flags & BTRFS_BLOCK_GROUP_DUP) ++ return stripped | BTRFS_BLOCK_GROUP_RAID1; ++ ++ /* this is drive concat, leave it alone */ ++ } ++ ++ return flags; ++} ++ ++int btrfs_inc_block_group_ro(struct btrfs_block_group_cache *cache) ++ ++{ ++ struct btrfs_fs_info *fs_info = cache->fs_info; ++ struct btrfs_trans_handle *trans; ++ u64 alloc_flags; ++ int ret; ++ ++again: ++ trans = btrfs_join_transaction(fs_info->extent_root); ++ if (IS_ERR(trans)) ++ return PTR_ERR(trans); ++ ++ /* ++ * we're not allowed to set block groups readonly after the dirty ++ * block groups cache has started writing. If it already started, ++ * back off and let this transaction commit ++ */ ++ mutex_lock(&fs_info->ro_block_group_mutex); ++ if (test_bit(BTRFS_TRANS_DIRTY_BG_RUN, &trans->transaction->flags)) { ++ u64 transid = trans->transid; ++ ++ mutex_unlock(&fs_info->ro_block_group_mutex); ++ btrfs_end_transaction(trans); ++ ++ ret = btrfs_wait_for_commit(fs_info, transid); ++ if (ret) ++ return ret; ++ goto again; ++ } ++ ++ /* ++ * if we are changing raid levels, try to allocate a corresponding ++ * block group with the new raid level. ++ */ ++ alloc_flags = update_block_group_flags(fs_info, cache->flags); ++ if (alloc_flags != cache->flags) { ++ ret = btrfs_chunk_alloc(trans, alloc_flags, CHUNK_ALLOC_FORCE); ++ /* ++ * ENOSPC is allowed here, we may have enough space ++ * already allocated at the new raid level to ++ * carry on ++ */ ++ if (ret == -ENOSPC) ++ ret = 0; ++ if (ret < 0) ++ goto out; ++ } ++ ++ ret = __btrfs_inc_block_group_ro(cache, 0); ++ if (!ret) ++ goto out; ++ alloc_flags = btrfs_get_alloc_profile(fs_info, cache->space_info->flags); ++ ret = btrfs_chunk_alloc(trans, alloc_flags, CHUNK_ALLOC_FORCE); ++ if (ret < 0) ++ goto out; ++ ret = __btrfs_inc_block_group_ro(cache, 0); ++out: ++ if (cache->flags & BTRFS_BLOCK_GROUP_SYSTEM) { ++ alloc_flags = update_block_group_flags(fs_info, cache->flags); ++ mutex_lock(&fs_info->chunk_mutex); ++ check_system_chunk(trans, fs_info, alloc_flags); ++ mutex_unlock(&fs_info->chunk_mutex); ++ } ++ mutex_unlock(&fs_info->ro_block_group_mutex); ++ ++ btrfs_end_transaction(trans); ++ return ret; ++} ++ ++void btrfs_dec_block_group_ro(struct btrfs_block_group_cache *cache) ++{ ++ struct btrfs_space_info *sinfo = cache->space_info; ++ u64 num_bytes; ++ ++ BUG_ON(!cache->ro); ++ ++ spin_lock(&sinfo->lock); ++ spin_lock(&cache->lock); ++ if (!--cache->ro) { ++ num_bytes = cache->key.offset - cache->reserved - ++ cache->pinned - cache->bytes_super - ++ btrfs_block_group_used(&cache->item); ++ sinfo->bytes_readonly -= num_bytes; ++ list_del_init(&cache->ro_list); ++ } ++ spin_unlock(&cache->lock); ++ spin_unlock(&sinfo->lock); ++} +--- a/fs/btrfs/block-group.h ++++ b/fs/btrfs/block-group.h +@@ -190,6 +190,8 @@ int btrfs_make_block_group(struct btrfs_ + u64 size); + void btrfs_create_pending_block_groups(struct btrfs_trans_handle *trans, + struct btrfs_fs_info *fs_info); ++int btrfs_inc_block_group_ro(struct btrfs_block_group_cache *cache); ++void btrfs_dec_block_group_ro(struct btrfs_block_group_cache *cache); + + static inline int btrfs_block_group_cache_done( + struct btrfs_block_group_cache *cache) +--- a/fs/btrfs/ctree.h ++++ b/fs/btrfs/ctree.h +@@ -2597,9 +2597,6 @@ void btrfs_delalloc_release_extents(stru + bool qgroup_free); + + int btrfs_delalloc_reserve_metadata(struct btrfs_inode *inode, u64 num_bytes); +-int btrfs_inc_block_group_ro(struct btrfs_fs_info *fs_info, +- struct btrfs_block_group_cache *cache); +-void btrfs_dec_block_group_ro(struct btrfs_block_group_cache *cache); + void btrfs_put_block_group_cache(struct btrfs_fs_info *info); + u64 btrfs_account_ro_block_groups_free_space(struct btrfs_space_info *sinfo); + int btrfs_error_unpin_extent_range(struct btrfs_fs_info *fs_info, +--- a/fs/btrfs/extent-tree.c ++++ b/fs/btrfs/extent-tree.c +@@ -6616,181 +6616,6 @@ int btrfs_drop_subtree(struct btrfs_tran + return ret; + } + +-static u64 update_block_group_flags(struct btrfs_fs_info *fs_info, u64 flags) +-{ +- u64 num_devices; +- u64 stripped; +- +- /* +- * if restripe for this chunk_type is on pick target profile and +- * return, otherwise do the usual balance +- */ +- stripped = btrfs_get_restripe_target(fs_info, flags); +- if (stripped) +- return extended_to_chunk(stripped); +- +- num_devices = fs_info->fs_devices->rw_devices; +- +- stripped = BTRFS_BLOCK_GROUP_RAID0 | +- BTRFS_BLOCK_GROUP_RAID5 | BTRFS_BLOCK_GROUP_RAID6 | +- BTRFS_BLOCK_GROUP_RAID1 | BTRFS_BLOCK_GROUP_RAID10; +- +- if (num_devices == 1) { +- stripped |= BTRFS_BLOCK_GROUP_DUP; +- stripped = flags & ~stripped; +- +- /* turn raid0 into single device chunks */ +- if (flags & BTRFS_BLOCK_GROUP_RAID0) +- return stripped; +- +- /* turn mirroring into duplication */ +- if (flags & (BTRFS_BLOCK_GROUP_RAID1 | +- BTRFS_BLOCK_GROUP_RAID10)) +- return stripped | BTRFS_BLOCK_GROUP_DUP; +- } else { +- /* they already had raid on here, just return */ +- if (flags & stripped) +- return flags; +- +- stripped |= BTRFS_BLOCK_GROUP_DUP; +- stripped = flags & ~stripped; +- +- /* switch duplicated blocks with raid1 */ +- if (flags & BTRFS_BLOCK_GROUP_DUP) +- return stripped | BTRFS_BLOCK_GROUP_RAID1; +- +- /* this is drive concat, leave it alone */ +- } +- +- return flags; +-} +- +-int __inc_block_group_ro(struct btrfs_block_group_cache *cache, int force) +-{ +- struct btrfs_space_info *sinfo = cache->space_info; +- u64 num_bytes; +- u64 sinfo_used; +- u64 min_allocable_bytes; +- int ret = -ENOSPC; +- +- /* +- * We need some metadata space and system metadata space for +- * allocating chunks in some corner cases until we force to set +- * it to be readonly. +- */ +- if ((sinfo->flags & +- (BTRFS_BLOCK_GROUP_SYSTEM | BTRFS_BLOCK_GROUP_METADATA)) && +- !force) +- min_allocable_bytes = SZ_1M; +- else +- min_allocable_bytes = 0; +- +- spin_lock(&sinfo->lock); +- spin_lock(&cache->lock); +- +- if (cache->ro) { +- cache->ro++; +- ret = 0; +- goto out; +- } +- +- num_bytes = cache->key.offset - cache->reserved - cache->pinned - +- cache->bytes_super - btrfs_block_group_used(&cache->item); +- sinfo_used = btrfs_space_info_used(sinfo, true); +- +- if (sinfo_used + num_bytes + min_allocable_bytes <= +- sinfo->total_bytes) { +- sinfo->bytes_readonly += num_bytes; +- cache->ro++; +- list_add_tail(&cache->ro_list, &sinfo->ro_bgs); +- ret = 0; +- } +-out: +- spin_unlock(&cache->lock); +- spin_unlock(&sinfo->lock); +- if (ret == -ENOSPC && btrfs_test_opt(cache->fs_info, ENOSPC_DEBUG)) { +- btrfs_info(cache->fs_info, +- "unable to make block group %llu ro", +- cache->key.objectid); +- btrfs_info(cache->fs_info, +- "sinfo_used=%llu bg_num_bytes=%llu min_allocable=%llu", +- sinfo_used, num_bytes, min_allocable_bytes); +- btrfs_dump_space_info(cache->fs_info, cache->space_info, 0, 0); +- } +- return ret; +-} +- +-int btrfs_inc_block_group_ro(struct btrfs_fs_info *fs_info, +- struct btrfs_block_group_cache *cache) +- +-{ +- struct btrfs_trans_handle *trans; +- u64 alloc_flags; +- int ret; +- +-again: +- trans = btrfs_join_transaction(fs_info->extent_root); +- if (IS_ERR(trans)) +- return PTR_ERR(trans); +- +- /* +- * we're not allowed to set block groups readonly after the dirty +- * block groups cache has started writing. If it already started, +- * back off and let this transaction commit +- */ +- mutex_lock(&fs_info->ro_block_group_mutex); +- if (test_bit(BTRFS_TRANS_DIRTY_BG_RUN, &trans->transaction->flags)) { +- u64 transid = trans->transid; +- +- mutex_unlock(&fs_info->ro_block_group_mutex); +- btrfs_end_transaction(trans); +- +- ret = btrfs_wait_for_commit(fs_info, transid); +- if (ret) +- return ret; +- goto again; +- } +- +- /* +- * if we are changing raid levels, try to allocate a corresponding +- * block group with the new raid level. +- */ +- alloc_flags = update_block_group_flags(fs_info, cache->flags); +- if (alloc_flags != cache->flags) { +- ret = btrfs_chunk_alloc(trans, alloc_flags, +- CHUNK_ALLOC_FORCE); +- /* +- * ENOSPC is allowed here, we may have enough space +- * already allocated at the new raid level to +- * carry on +- */ +- if (ret == -ENOSPC) +- ret = 0; +- if (ret < 0) +- goto out; +- } +- +- ret = __btrfs_inc_block_group_ro(cache, 0); +- if (!ret) +- goto out; +- alloc_flags = btrfs_get_alloc_profile(fs_info, cache->space_info->flags); +- ret = btrfs_chunk_alloc(trans, alloc_flags, CHUNK_ALLOC_FORCE); +- if (ret < 0) +- goto out; +- ret = __btrfs_inc_block_group_ro(cache, 0); +-out: +- if (cache->flags & BTRFS_BLOCK_GROUP_SYSTEM) { +- alloc_flags = update_block_group_flags(fs_info, cache->flags); +- mutex_lock(&fs_info->chunk_mutex); +- check_system_chunk(trans, fs_info, alloc_flags); +- mutex_unlock(&fs_info->chunk_mutex); +- } +- mutex_unlock(&fs_info->ro_block_group_mutex); +- +- btrfs_end_transaction(trans); +- return ret; +-} +- + int btrfs_force_chunk_alloc(struct btrfs_trans_handle *trans, + struct btrfs_fs_info *fs_info, u64 type) + { +@@ -6834,26 +6659,6 @@ u64 btrfs_account_ro_block_groups_free_s + return free_bytes; + } + +-void btrfs_dec_block_group_ro(struct btrfs_block_group_cache *cache) +-{ +- struct btrfs_space_info *sinfo = cache->space_info; +- u64 num_bytes; +- +- BUG_ON(!cache->ro); +- +- spin_lock(&sinfo->lock); +- spin_lock(&cache->lock); +- if (!--cache->ro) { +- num_bytes = cache->key.offset - cache->reserved - +- cache->pinned - cache->bytes_super - +- btrfs_block_group_used(&cache->item); +- sinfo->bytes_readonly -= num_bytes; +- list_del_init(&cache->ro_list); +- } +- spin_unlock(&cache->lock); +- spin_unlock(&sinfo->lock); +-} +- + /* + * checks to see if its even possible to relocate this block group. + * +--- a/fs/btrfs/relocation.c ++++ b/fs/btrfs/relocation.c +@@ -4453,7 +4453,7 @@ int btrfs_relocate_block_group(struct bt + rc->block_group = btrfs_lookup_block_group(fs_info, group_start); + BUG_ON(!rc->block_group); + +- ret = btrfs_inc_block_group_ro(fs_info, rc->block_group); ++ ret = btrfs_inc_block_group_ro(rc->block_group); + if (ret) { + err = ret; + goto out; +--- a/fs/btrfs/scrub.c ++++ b/fs/btrfs/scrub.c +@@ -3848,7 +3848,7 @@ int scrub_enumerate_chunks(struct scrub_ + * -> btrfs_scrub_pause() + */ + scrub_pause_on(fs_info); +- ret = btrfs_inc_block_group_ro(fs_info, cache); ++ ret = btrfs_inc_block_group_ro(cache); + if (!ret && is_dev_replace) { + /* + * If we are doing a device replace wait for any tasks diff --git a/patches.suse/0016-btrfs-rename-btrfs_space_info_add_old_bytes.patch b/patches.suse/0016-btrfs-rename-btrfs_space_info_add_old_bytes.patch new file mode 100644 index 0000000..abaa4b9 --- /dev/null +++ b/patches.suse/0016-btrfs-rename-btrfs_space_info_add_old_bytes.patch @@ -0,0 +1,65 @@ +From: Josef Bacik +Date: Thu, 22 Aug 2019 15:11:02 -0400 +Subject: btrfs: rename btrfs_space_info_add_old_bytes +Git-commit: d05e46497f86175f85a4f0b9346cae2260e97c8d +Patch-mainline: v5.4-rc1 +References: bsc#1165949 + +This name doesn't really fit with how the space reservation stuff works +now, rename it to btrfs_space_info_free_bytes_may_use so it's clear what +the function is doing. + +Reviewed-by: Nikolay Borisov +Signed-off-by: Josef Bacik +Reviewed-by: David Sterba +Signed-off-by: David Sterba +Acked-by: Nikolay Borisov +--- + fs/btrfs/block-rsv.c | 5 +++-- + fs/btrfs/delayed-ref.c | 2 +- + fs/btrfs/space-info.h | 2 +- + 3 files changed, 5 insertions(+), 4 deletions(-) + +diff --git a/fs/btrfs/block-rsv.c b/fs/btrfs/block-rsv.c +index c808f93b743a..01b1ce2240bc 100644 +--- a/fs/btrfs/block-rsv.c ++++ b/fs/btrfs/block-rsv.c +@@ -54,8 +54,9 @@ static u64 block_rsv_release_bytes(struct btrfs_fs_info *fs_info, + spin_unlock(&dest->lock); + } + if (num_bytes) +- btrfs_space_info_add_old_bytes(fs_info, space_info, +- num_bytes); ++ btrfs_space_info_free_bytes_may_use(fs_info, ++ space_info, ++ num_bytes); + } + if (qgroup_to_release_ret) + *qgroup_to_release_ret = qgroup_to_release; +diff --git a/fs/btrfs/delayed-ref.c b/fs/btrfs/delayed-ref.c +index 951a60c740e7..df3bd880061d 100644 +--- a/fs/btrfs/delayed-ref.c ++++ b/fs/btrfs/delayed-ref.c +@@ -158,7 +158,7 @@ void btrfs_migrate_to_delayed_refs_rsv(struct btrfs_fs_info *fs_info, + trace_btrfs_space_reservation(fs_info, "delayed_refs_rsv", + 0, num_bytes, 1); + if (to_free) +- btrfs_space_info_add_old_bytes(fs_info, ++ btrfs_space_info_free_bytes_may_use(fs_info, + delayed_refs_rsv->space_info, to_free); + } + +diff --git a/fs/btrfs/space-info.h b/fs/btrfs/space-info.h +index dc6ee66ed600..8867e84aa33d 100644 +--- a/fs/btrfs/space-info.h ++++ b/fs/btrfs/space-info.h +@@ -129,7 +129,7 @@ int btrfs_reserve_metadata_bytes(struct btrfs_root *root, + void btrfs_try_granting_tickets(struct btrfs_fs_info *fs_info, + struct btrfs_space_info *space_info); + +-static inline void btrfs_space_info_add_old_bytes( ++static inline void btrfs_space_info_free_bytes_may_use( + struct btrfs_fs_info *fs_info, + struct btrfs_space_info *space_info, + u64 num_bytes) + diff --git a/patches.suse/0016-btrfs-wakeup-cleaner-thread-when-adding-delayed-iput.patch b/patches.suse/0016-btrfs-wakeup-cleaner-thread-when-adding-delayed-iput.patch new file mode 100644 index 0000000..c79b801 --- /dev/null +++ b/patches.suse/0016-btrfs-wakeup-cleaner-thread-when-adding-delayed-iput.patch @@ -0,0 +1,73 @@ +From: Josef Bacik +Date: Fri, 11 Jan 2019 10:21:02 -0500 +Subject: btrfs: wakeup cleaner thread when adding delayed iput +Git-commit: fd340d0f68cc87badfc9efcb226f23a5428826a0 +Patch-mainline: v5.0-rc3 +References: bsc#1165949 + +The cleaner thread usually takes care of delayed iputs, with the +exception of the btrfs_end_transaction_throttle path. Delaying iputs +means we are potentially delaying the eviction of an inode and it's +respective space. The cleaner thread only gets woken up every 30 +seconds, or when we require space. If there are a lot of inodes that +need to be deleted we could induce a serious amount of latency while we +wait for these inodes to be evicted. So instead wakeup the cleaner if +it's not already awake to process any new delayed iputs we add to the +list. If we suddenly need space we will less likely be backed up +behind a bunch of inodes that are waiting to be deleted, and we could +possibly free space before we need to get into the flushing logic which +will save us some latency. + +Reviewed-by: Filipe Manana +Signed-off-by: Josef Bacik +Signed-off-by: David Sterba +Acked-by: Nikolay Borisov +--- + fs/btrfs/ctree.h | 4 ++++ + fs/btrfs/disk-io.c | 3 +++ + fs/btrfs/inode.c | 2 ++ + 3 files changed, 9 insertions(+) + +--- a/fs/btrfs/ctree.h ++++ b/fs/btrfs/ctree.h +@@ -756,6 +756,10 @@ struct btrfs_delayed_root; + */ + #define BTRFS_FS_BALANCE_RUNNING 18 + ++ ++/* Indicate that the cleaner thread is awake and doing something. */ ++#define BTRFS_FS_CLEANER_RUNNING 19 ++ + 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 +@@ -1754,6 +1754,8 @@ static int cleaner_kthread(void *arg) + while (1) { + again = 0; + ++ set_bit(BTRFS_FS_CLEANER_RUNNING, &fs_info->flags); ++ + /* Make the cleaner go to sleep early. */ + if (btrfs_need_cleaner_sleep(fs_info)) + goto sleep; +@@ -1800,6 +1802,7 @@ static int cleaner_kthread(void *arg) + */ + btrfs_delete_unused_bgs(fs_info); + sleep: ++ clear_bit(BTRFS_FS_CLEANER_RUNNING, &fs_info->flags); + if (kthread_should_park()) + kthread_parkme(); + if (kthread_should_stop()) +--- a/fs/btrfs/inode.c ++++ b/fs/btrfs/inode.c +@@ -3276,6 +3276,8 @@ void btrfs_run_delayed_iputs(struct btrf + spin_lock(&fs_info->delayed_iput_lock); + } + spin_unlock(&fs_info->delayed_iput_lock); ++ if (!test_bit(BTRFS_FS_CLEANER_RUNNING, &fs_info->flags)) ++ wake_up_process(fs_info->cleaner_kthread); + } + + /* diff --git a/patches.suse/0016-raid5-block-failing-device-if-raid-will-be-failed.patch b/patches.suse/0016-raid5-block-failing-device-if-raid-will-be-failed.patch new file mode 100644 index 0000000..148a7da --- /dev/null +++ b/patches.suse/0016-raid5-block-failing-device-if-raid-will-be-failed.patch @@ -0,0 +1,55 @@ +From fb73b357fb985cc652a72a41541d25915c7f9635 Mon Sep 17 00:00:00 2001 +From: Mariusz Tkaczyk +Date: Tue, 4 Sep 2018 15:08:30 +0200 +Subject: [PATCH] raid5: block failing device if raid will be failed +Git-commit: fb73b357fb985cc652a72a41541d25915c7f9635 +Patch-mainline: v4.20-rc1 +References: bsc#1166003 + +Currently there is an inconsistency for failing the member drives +for arrays with different RAID levels. For RAID456 - there is a possibility +to fail all of the devices. However - for other RAID levels - kernel blocks +removing the member drive, if the operation results in array's FAIL state +(EBUSY is returned). For example - removing last drive from RAID1 is not +possible. +This kind of blocker was never implemented for raid456 and we cannot see +the reason why. + +We had tested following patch and did not observe any regression, so do you +have any comments/reasons for current approach, or we can send the proper +patch for this? + +Signed-off-by: Mariusz Tkaczyk +Signed-off-by: Shaohua Li +Signed-off-by: Coly Li + +--- + drivers/md/raid5.c | 12 ++++++++++++ + 1 file changed, 12 insertions(+) + +diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c +index e4e98f47865d..4990f0319f6c 100644 +--- a/drivers/md/raid5.c ++++ b/drivers/md/raid5.c +@@ -2681,6 +2681,18 @@ static void raid5_error(struct mddev *mddev, struct md_rdev *rdev) + pr_debug("raid456: error called\n"); + + spin_lock_irqsave(&conf->device_lock, flags); ++ ++ if (test_bit(In_sync, &rdev->flags) && ++ mddev->degraded == conf->max_degraded) { ++ /* ++ * Don't allow to achieve failed state ++ * Don't try to recover this device ++ */ ++ conf->recovery_disabled = mddev->recovery_disabled; ++ spin_unlock_irqrestore(&conf->device_lock, flags); ++ return; ++ } ++ + set_bit(Faulty, &rdev->flags); + clear_bit(In_sync, &rdev->flags); + mddev->degraded = raid5_calc_degraded(conf); +-- +2.25.0 + diff --git a/patches.suse/0017-btrfs-change-the-minimum-global-reserve-size.patch b/patches.suse/0017-btrfs-change-the-minimum-global-reserve-size.patch new file mode 100644 index 0000000..1abff04 --- /dev/null +++ b/patches.suse/0017-btrfs-change-the-minimum-global-reserve-size.patch @@ -0,0 +1,65 @@ +From: Josef Bacik +Date: Thu, 22 Aug 2019 15:19:00 -0400 +Subject: btrfs: change the minimum global reserve size +Git-commit: 3593ce30b5b4a8fbe84dd1c275e9be01af28511a +Patch-mainline: v5.4-rc1 +References: bsc#1165949 + +It made sense to have the global reserve set at 16M in the past, but +since it is used less nowadays set the minimum size to the number of +items we'll need to update the main trees we update during a transaction +commit, plus some slop area so we can do unlinks if we need to. + +In practice this doesn't affect normal file systems, but for xfstests +where we do things like fill up a fs and then rm * it can fall over in +weird ways. This enables us for more sane behavior at extremely small +file system sizes. + +Signed-off-by: Josef Bacik +Signed-off-by: David Sterba +Acked-by: Nikolay Borisov +--- + fs/btrfs/block-rsv.c | 22 +++++++++++++++++++++- + 1 file changed, 21 insertions(+), 1 deletion(-) + +diff --git a/fs/btrfs/block-rsv.c b/fs/btrfs/block-rsv.c +index 01b1ce2240bc..c8b7995c33ee 100644 +--- a/fs/btrfs/block-rsv.c ++++ b/fs/btrfs/block-rsv.c +@@ -259,6 +259,7 @@ void btrfs_update_global_block_rsv(struct btrfs_fs_info *fs_info) + struct btrfs_block_rsv *block_rsv = &fs_info->global_block_rsv; + struct btrfs_space_info *sinfo = block_rsv->space_info; + u64 num_bytes; ++ unsigned min_items; + + /* + * The global block rsv is based on the size of the extent tree, the +@@ -268,7 +269,26 @@ void btrfs_update_global_block_rsv(struct btrfs_fs_info *fs_info) + num_bytes = btrfs_root_used(&fs_info->extent_root->root_item) + + btrfs_root_used(&fs_info->csum_root->root_item) + + btrfs_root_used(&fs_info->tree_root->root_item); +- num_bytes = max_t(u64, num_bytes, SZ_16M); ++ ++ /* ++ * We at a minimum are going to modify the csum root, the tree root, and ++ * the extent root. ++ */ ++ min_items = 3; ++ ++ /* ++ * But we also want to reserve enough space so we can do the fallback ++ * global reserve for an unlink, which is an additional 5 items (see the ++ * comment in __unlink_start_trans for what we're modifying.) ++ * ++ * But we also need space for the delayed ref updates from the unlink, ++ * so its 10, 5 for the actual operation, and 5 for the delayed ref ++ * updates. ++ */ ++ min_items += 10; ++ ++ num_bytes = max_t(u64, num_bytes, ++ btrfs_calc_insert_metadata_size(fs_info, min_items)); + + spin_lock(&sinfo->lock); + spin_lock(&block_rsv->lock); + diff --git a/patches.suse/0017-btrfs-don-t-end-the-transaction-for-delayed-refs-in-throttle.patch b/patches.suse/0017-btrfs-don-t-end-the-transaction-for-delayed-refs-in-throttle.patch new file mode 100644 index 0000000..83341e1 --- /dev/null +++ b/patches.suse/0017-btrfs-don-t-end-the-transaction-for-delayed-refs-in-throttle.patch @@ -0,0 +1,56 @@ +From: Josef Bacik +Date: Thu, 24 Jan 2019 09:31:43 -0500 +Subject: btrfs: don't end the transaction for delayed refs in throttle +Git-commit: 302167c50b32e7fccc98994a91d40ddbbab04e52 +Patch-mainline: v5.0-rc5 +References: bsc#1165949 + +Previously callers to btrfs_end_transaction_throttle() would commit the +transaction if there wasn't enough delayed refs space. This happens in +relocation, and if the fs is relatively empty we'll run out of delayed +refs space basically immediately, so we'll just be stuck in this loop of +committing the transaction over and over again. + +This code existed because we didn't have a good feedback mechanism for +running delayed refs, but with the delayed refs rsv we do now. Delete +this throttling code and let the btrfs_start_transaction() in relocation +deal with putting pressure on the delayed refs infrastructure. With +this patch we no longer take 5 minutes to balance a metadata only fs. + +Qu has submitted a fstest to catch slow balance or excessive transaction +commits. Steps to reproduce: + +* create subvolume +* create many (eg. 16000) inlined files, of size 2KiB +* iteratively snapshot and touch several files to trigger metadata + updates +* start balance -m + +Reported-by: Qu Wenruo +Fixes: 64403612b73a ("btrfs: rework btrfs_check_space_for_delayed_refs") +Signed-off-by: Josef Bacik +[ add tags and steps to reproduce ] +Signed-off-by: David Sterba +Acked-by: Nikolay Borisov +--- + fs/btrfs/transaction.c | 9 --------- + 1 file changed, 9 deletions(-) + +--- a/fs/btrfs/transaction.c ++++ b/fs/btrfs/transaction.c +@@ -868,15 +868,6 @@ static int __btrfs_end_transaction(struc + + btrfs_trans_release_chunk_metadata(trans); + +- if (lock && !atomic_read(&info->open_ioctl_trans) && +- should_end_transaction(trans) && +- READ_ONCE(cur_trans->state) == TRANS_STATE_RUNNING) { +- spin_lock(&info->trans_lock); +- if (cur_trans->state == TRANS_STATE_RUNNING) +- cur_trans->state = TRANS_STATE_BLOCKED; +- spin_unlock(&info->trans_lock); +- } +- + if (lock && READ_ONCE(cur_trans->state) == TRANS_STATE_BLOCKED) { + if (throttle) + return btrfs_commit_transaction(trans); diff --git a/patches.suse/0017-btrfs-migrate-the-dirty-bg-writeout-code.patch b/patches.suse/0017-btrfs-migrate-the-dirty-bg-writeout-code.patch new file mode 100644 index 0000000..cb7aa7b --- /dev/null +++ b/patches.suse/0017-btrfs-migrate-the-dirty-bg-writeout-code.patch @@ -0,0 +1,1136 @@ +From: Josef Bacik +Date: Thu, 20 Jun 2019 15:38:00 -0400 +Subject: btrfs: migrate the dirty bg writeout code +Git-commit: 77745c05115fcf3c2b7deb599799a6b51d1c5155 +Patch-mainline: v5.4-rc1 +References: bsc#1165949 + +This can be easily migrated over now. + +Signed-off-by: Josef Bacik +Reviewed-by: David Sterba +[ update comments ] +Signed-off-by: David Sterba +Acked-by: Nikolay Borisov +--- + fs/btrfs/block-group.c | 517 ++++++++++++++++++++++++++++++++++++++++++++++++ + fs/btrfs/block-group.h | 3 + fs/btrfs/ctree.h | 6 + fs/btrfs/extent-tree.c | 519 ------------------------------------------------- + fs/btrfs/transaction.c | 6 + 5 files changed, 523 insertions(+), 528 deletions(-) + +--- a/fs/btrfs/block-group.c ++++ b/fs/btrfs/block-group.c +@@ -11,6 +11,7 @@ + #include "transaction.h" + #include "sysfs.h" + #include "tree-log.h" ++#include "delalloc-space.h" + + void btrfs_get_block_group(struct btrfs_block_group_cache *cache) + { +@@ -2023,3 +2024,519 @@ void btrfs_dec_block_group_ro(struct btr + spin_unlock(&cache->lock); + spin_unlock(&sinfo->lock); + } ++ ++static int write_one_cache_group(struct btrfs_trans_handle *trans, ++ struct btrfs_path *path, ++ struct btrfs_block_group_cache *cache) ++{ ++ struct btrfs_fs_info *fs_info = trans->fs_info; ++ int ret; ++ struct btrfs_root *extent_root = fs_info->extent_root; ++ unsigned long bi; ++ struct extent_buffer *leaf; ++ ++ ret = btrfs_search_slot(trans, extent_root, &cache->key, path, 0, 1); ++ if (ret) { ++ if (ret > 0) ++ ret = -ENOENT; ++ goto fail; ++ } ++ ++ leaf = path->nodes[0]; ++ bi = btrfs_item_ptr_offset(leaf, path->slots[0]); ++ write_extent_buffer(leaf, &cache->item, bi, sizeof(cache->item)); ++ btrfs_mark_buffer_dirty(leaf); ++fail: ++ btrfs_release_path(path); ++ return ret; ++ ++} ++ ++static int cache_save_setup(struct btrfs_block_group_cache *block_group, ++ struct btrfs_trans_handle *trans, ++ struct btrfs_path *path) ++{ ++ struct btrfs_fs_info *fs_info = block_group->fs_info; ++ struct btrfs_root *root = fs_info->tree_root; ++ struct inode *inode = NULL; ++ struct extent_changeset *data_reserved = NULL; ++ u64 alloc_hint = 0; ++ int dcs = BTRFS_DC_ERROR; ++ u64 num_pages = 0; ++ int retries = 0; ++ int ret = 0; ++ ++ /* ++ * If this block group is smaller than 100 megs don't bother caching the ++ * block group. ++ */ ++ if (block_group->key.offset < (100 * SZ_1M)) { ++ spin_lock(&block_group->lock); ++ block_group->disk_cache_state = BTRFS_DC_WRITTEN; ++ spin_unlock(&block_group->lock); ++ return 0; ++ } ++ ++ if (trans->aborted) ++ return 0; ++again: ++ inode = lookup_free_space_inode(fs_info, block_group, path); ++ if (IS_ERR(inode) && PTR_ERR(inode) != -ENOENT) { ++ ret = PTR_ERR(inode); ++ btrfs_release_path(path); ++ goto out; ++ } ++ ++ if (IS_ERR(inode)) { ++ BUG_ON(retries); ++ retries++; ++ ++ if (block_group->ro) ++ goto out_free; ++ ++ ret = create_free_space_inode(fs_info, trans, block_group, ++ path); ++ if (ret) ++ goto out_free; ++ goto again; ++ } ++ ++ /* ++ * We want to set the generation to 0, that way if anything goes wrong ++ * from here on out we know not to trust this cache when we load up next ++ * time. ++ */ ++ BTRFS_I(inode)->generation = 0; ++ ret = btrfs_update_inode(trans, root, inode); ++ if (ret) { ++ /* ++ * So theoretically we could recover from this, simply set the ++ * super cache generation to 0 so we know to invalidate the ++ * cache, but then we'd have to keep track of the block groups ++ * that fail this way so we know we _have_ to reset this cache ++ * before the next commit or risk reading stale cache. So to ++ * limit our exposure to horrible edge cases lets just abort the ++ * transaction, this only happens in really bad situations ++ * anyway. ++ */ ++ btrfs_abort_transaction(trans, ret); ++ goto out_put; ++ } ++ WARN_ON(ret); ++ ++ /* We've already setup this transaction, go ahead and exit */ ++ if (block_group->cache_generation == trans->transid && ++ i_size_read(inode)) { ++ dcs = BTRFS_DC_SETUP; ++ goto out_put; ++ } ++ ++ if (i_size_read(inode) > 0) { ++ ret = btrfs_check_trunc_cache_free_space(fs_info, ++ &fs_info->global_block_rsv); ++ if (ret) ++ goto out_put; ++ ++ ret = btrfs_truncate_free_space_cache(trans, NULL, inode); ++ if (ret) ++ goto out_put; ++ } ++ ++ spin_lock(&block_group->lock); ++ if (block_group->cached != BTRFS_CACHE_FINISHED || ++ !btrfs_test_opt(fs_info, SPACE_CACHE)) { ++ /* ++ * don't bother trying to write stuff out _if_ ++ * a) we're not cached, ++ * b) we're with nospace_cache mount option, ++ * c) we're with v2 space_cache (FREE_SPACE_TREE). ++ */ ++ dcs = BTRFS_DC_WRITTEN; ++ spin_unlock(&block_group->lock); ++ goto out_put; ++ } ++ spin_unlock(&block_group->lock); ++ ++ /* ++ * We hit an ENOSPC when setting up the cache in this transaction, just ++ * skip doing the setup, we've already cleared the cache so we're safe. ++ */ ++ if (test_bit(BTRFS_TRANS_CACHE_ENOSPC, &trans->transaction->flags)) { ++ ret = -ENOSPC; ++ goto out_put; ++ } ++ ++ /* ++ * Try to preallocate enough space based on how big the block group is. ++ * Keep in mind this has to include any pinned space which could end up ++ * taking up quite a bit since it's not folded into the other space ++ * cache. ++ */ ++ num_pages = div_u64(block_group->key.offset, SZ_256M); ++ if (!num_pages) ++ num_pages = 1; ++ ++ num_pages *= 16; ++ num_pages *= PAGE_SIZE; ++ ++ ret = btrfs_check_data_free_space(inode, &data_reserved, 0, num_pages); ++ if (ret) ++ goto out_put; ++ ++ ret = btrfs_prealloc_file_range_trans(inode, trans, 0, 0, num_pages, ++ num_pages, num_pages, ++ &alloc_hint); ++ /* ++ * Our cache requires contiguous chunks so that we don't modify a bunch ++ * of metadata or split extents when writing the cache out, which means ++ * we can enospc if we are heavily fragmented in addition to just normal ++ * out of space conditions. So if we hit this just skip setting up any ++ * other block groups for this transaction, maybe we'll unpin enough ++ * space the next time around. ++ */ ++ if (!ret) ++ dcs = BTRFS_DC_SETUP; ++ else if (ret == -ENOSPC) ++ set_bit(BTRFS_TRANS_CACHE_ENOSPC, &trans->transaction->flags); ++ ++out_put: ++ iput(inode); ++out_free: ++ btrfs_release_path(path); ++out: ++ spin_lock(&block_group->lock); ++ if (!ret && dcs == BTRFS_DC_SETUP) ++ block_group->cache_generation = trans->transid; ++ block_group->disk_cache_state = dcs; ++ spin_unlock(&block_group->lock); ++ ++ extent_changeset_free(data_reserved); ++ return ret; ++} ++ ++int btrfs_setup_space_cache(struct btrfs_trans_handle *trans) ++{ ++ struct btrfs_fs_info *fs_info = trans->fs_info; ++ struct btrfs_block_group_cache *cache, *tmp; ++ struct btrfs_transaction *cur_trans = trans->transaction; ++ struct btrfs_path *path; ++ ++ if (list_empty(&cur_trans->dirty_bgs) || ++ !btrfs_test_opt(fs_info, SPACE_CACHE)) ++ return 0; ++ ++ path = btrfs_alloc_path(); ++ if (!path) ++ return -ENOMEM; ++ ++ /* Could add new block groups, use _safe just in case */ ++ list_for_each_entry_safe(cache, tmp, &cur_trans->dirty_bgs, ++ dirty_list) { ++ if (cache->disk_cache_state == BTRFS_DC_CLEAR) ++ cache_save_setup(cache, trans, path); ++ } ++ ++ btrfs_free_path(path); ++ return 0; ++} ++ ++/* ++ * Transaction commit does final block group cache writeback during a critical ++ * section where nothing is allowed to change the FS. This is required in ++ * order for the cache to actually match the block group, but can introduce a ++ * lot of latency into the commit. ++ * ++ * So, btrfs_start_dirty_block_groups is here to kick off block group cache IO. ++ * There's a chance we'll have to redo some of it if the block group changes ++ * again during the commit, but it greatly reduces the commit latency by ++ * getting rid of the easy block groups while we're still allowing others to ++ * join the commit. ++ */ ++int btrfs_start_dirty_block_groups(struct btrfs_trans_handle *trans) ++{ ++ struct btrfs_fs_info *fs_info = trans->fs_info; ++ struct btrfs_block_group_cache *cache; ++ struct btrfs_transaction *cur_trans = trans->transaction; ++ int ret = 0; ++ int should_put; ++ struct btrfs_path *path = NULL; ++ LIST_HEAD(dirty); ++ struct list_head *io = &cur_trans->io_bgs; ++ int num_started = 0; ++ int loops = 0; ++ ++ spin_lock(&cur_trans->dirty_bgs_lock); ++ if (list_empty(&cur_trans->dirty_bgs)) { ++ spin_unlock(&cur_trans->dirty_bgs_lock); ++ return 0; ++ } ++ list_splice_init(&cur_trans->dirty_bgs, &dirty); ++ spin_unlock(&cur_trans->dirty_bgs_lock); ++ ++again: ++ /* Make sure all the block groups on our dirty list actually exist */ ++ btrfs_create_pending_block_groups(trans, fs_info); ++ ++ if (!path) { ++ path = btrfs_alloc_path(); ++ if (!path) ++ return -ENOMEM; ++ } ++ ++ /* ++ * cache_write_mutex is here only to save us from balance or automatic ++ * removal of empty block groups deleting this block group while we are ++ * writing out the cache ++ */ ++ mutex_lock(&trans->transaction->cache_write_mutex); ++ while (!list_empty(&dirty)) { ++ bool drop_reserve = true; ++ ++ cache = list_first_entry(&dirty, ++ struct btrfs_block_group_cache, ++ dirty_list); ++ /* ++ * This can happen if something re-dirties a block group that ++ * is already under IO. Just wait for it to finish and then do ++ * it all again ++ */ ++ if (!list_empty(&cache->io_list)) { ++ list_del_init(&cache->io_list); ++ btrfs_wait_cache_io(trans, cache, path); ++ btrfs_put_block_group(cache); ++ } ++ ++ ++ /* ++ * btrfs_wait_cache_io uses the cache->dirty_list to decide if ++ * it should update the cache_state. Don't delete until after ++ * we wait. ++ * ++ * Since we're not running in the commit critical section ++ * we need the dirty_bgs_lock to protect from update_block_group ++ */ ++ spin_lock(&cur_trans->dirty_bgs_lock); ++ list_del_init(&cache->dirty_list); ++ spin_unlock(&cur_trans->dirty_bgs_lock); ++ ++ should_put = 1; ++ ++ cache_save_setup(cache, trans, path); ++ ++ if (cache->disk_cache_state == BTRFS_DC_SETUP) { ++ cache->io_ctl.inode = NULL; ++ ret = btrfs_write_out_cache(fs_info, trans, cache, path); ++ if (ret == 0 && cache->io_ctl.inode) { ++ num_started++; ++ should_put = 0; ++ ++ /* ++ * The cache_write_mutex is protecting the ++ * io_list, also refer to the definition of ++ * btrfs_transaction::io_bgs for more details ++ */ ++ list_add_tail(&cache->io_list, io); ++ } else { ++ /* ++ * If we failed to write the cache, the ++ * generation will be bad and life goes on ++ */ ++ ret = 0; ++ } ++ } ++ if (!ret) { ++ ret = write_one_cache_group(trans, path, cache); ++ /* ++ * Our block group might still be attached to the list ++ * of new block groups in the transaction handle of some ++ * other task (struct btrfs_trans_handle->new_bgs). This ++ * means its block group item isn't yet in the extent ++ * tree. If this happens ignore the error, as we will ++ * try again later in the critical section of the ++ * transaction commit. ++ */ ++ if (ret == -ENOENT) { ++ ret = 0; ++ spin_lock(&cur_trans->dirty_bgs_lock); ++ if (list_empty(&cache->dirty_list)) { ++ list_add_tail(&cache->dirty_list, ++ &cur_trans->dirty_bgs); ++ btrfs_get_block_group(cache); ++ drop_reserve = false; ++ } ++ spin_unlock(&cur_trans->dirty_bgs_lock); ++ } else if (ret) { ++ btrfs_abort_transaction(trans, ret); ++ } ++ } ++ ++ /* If it's not on the io list, we need to put the block group */ ++ if (should_put) ++ btrfs_put_block_group(cache); ++ if (drop_reserve) ++ btrfs_delayed_refs_rsv_release(fs_info, 1); ++ ++ if (ret) ++ break; ++ ++ /* ++ * Avoid blocking other tasks for too long. It might even save ++ * us from writing caches for block groups that are going to be ++ * removed. ++ */ ++ mutex_unlock(&trans->transaction->cache_write_mutex); ++ mutex_lock(&trans->transaction->cache_write_mutex); ++ } ++ mutex_unlock(&trans->transaction->cache_write_mutex); ++ ++ /* ++ * Go through delayed refs for all the stuff we've just kicked off ++ * and then loop back (just once) ++ */ ++ ret = btrfs_run_delayed_refs(trans, fs_info, 0); ++ if (!ret && loops == 0) { ++ loops++; ++ spin_lock(&cur_trans->dirty_bgs_lock); ++ list_splice_init(&cur_trans->dirty_bgs, &dirty); ++ /* ++ * dirty_bgs_lock protects us from concurrent block group ++ * deletes too (not just cache_write_mutex). ++ */ ++ if (!list_empty(&dirty)) { ++ spin_unlock(&cur_trans->dirty_bgs_lock); ++ goto again; ++ } ++ spin_unlock(&cur_trans->dirty_bgs_lock); ++ } else if (ret < 0) { ++ btrfs_cleanup_dirty_bgs(cur_trans, fs_info); ++ } ++ ++ btrfs_free_path(path); ++ return ret; ++} ++ ++int btrfs_write_dirty_block_groups(struct btrfs_trans_handle *trans) ++{ ++ struct btrfs_fs_info *fs_info = trans->fs_info; ++ struct btrfs_block_group_cache *cache; ++ struct btrfs_transaction *cur_trans = trans->transaction; ++ int ret = 0; ++ int should_put; ++ struct btrfs_path *path; ++ struct list_head *io = &cur_trans->io_bgs; ++ int num_started = 0; ++ ++ path = btrfs_alloc_path(); ++ if (!path) ++ return -ENOMEM; ++ ++ /* ++ * Even though we are in the critical section of the transaction commit, ++ * we can still have concurrent tasks adding elements to this ++ * transaction's list of dirty block groups. These tasks correspond to ++ * endio free space workers started when writeback finishes for a ++ * space cache, which run inode.c:btrfs_finish_ordered_io(), and can ++ * allocate new block groups as a result of COWing nodes of the root ++ * tree when updating the free space inode. The writeback for the space ++ * caches is triggered by an earlier call to ++ * btrfs_start_dirty_block_groups() and iterations of the following ++ * loop. ++ * Also we want to do the cache_save_setup first and then run the ++ * delayed refs to make sure we have the best chance at doing this all ++ * in one shot. ++ */ ++ spin_lock(&cur_trans->dirty_bgs_lock); ++ while (!list_empty(&cur_trans->dirty_bgs)) { ++ cache = list_first_entry(&cur_trans->dirty_bgs, ++ struct btrfs_block_group_cache, ++ dirty_list); ++ ++ /* ++ * This can happen if cache_save_setup re-dirties a block group ++ * that is already under IO. Just wait for it to finish and ++ * then do it all again ++ */ ++ if (!list_empty(&cache->io_list)) { ++ spin_unlock(&cur_trans->dirty_bgs_lock); ++ list_del_init(&cache->io_list); ++ btrfs_wait_cache_io(trans, cache, path); ++ btrfs_put_block_group(cache); ++ spin_lock(&cur_trans->dirty_bgs_lock); ++ } ++ ++ /* ++ * Don't remove from the dirty list until after we've waited on ++ * any pending IO ++ */ ++ list_del_init(&cache->dirty_list); ++ spin_unlock(&cur_trans->dirty_bgs_lock); ++ should_put = 1; ++ ++ cache_save_setup(cache, trans, path); ++ ++ if (!ret) ++ ret = btrfs_run_delayed_refs(trans, fs_info, ++ (unsigned long) -1); ++ ++ if (!ret && cache->disk_cache_state == BTRFS_DC_SETUP) { ++ cache->io_ctl.inode = NULL; ++ ret = btrfs_write_out_cache(fs_info, trans, cache, path); ++ if (ret == 0 && cache->io_ctl.inode) { ++ num_started++; ++ should_put = 0; ++ list_add_tail(&cache->io_list, io); ++ } else { ++ /* ++ * If we failed to write the cache, the ++ * generation will be bad and life goes on ++ */ ++ ret = 0; ++ } ++ } ++ if (!ret) { ++ ret = write_one_cache_group(trans, path, cache); ++ /* ++ * One of the free space endio workers might have ++ * created a new block group while updating a free space ++ * cache's inode (at inode.c:btrfs_finish_ordered_io()) ++ * and hasn't released its transaction handle yet, in ++ * which case the new block group is still attached to ++ * its transaction handle and its creation has not ++ * finished yet (no block group item in the extent tree ++ * yet, etc). If this is the case, wait for all free ++ * space endio workers to finish and retry. This is a ++ * a very rare case so no need for a more efficient and ++ * complex approach. ++ */ ++ if (ret == -ENOENT) { ++ wait_event(cur_trans->writer_wait, ++ atomic_read(&cur_trans->num_writers) == 1); ++ ret = write_one_cache_group(trans, path, cache); ++ } ++ if (ret) ++ btrfs_abort_transaction(trans, ret); ++ } ++ ++ /* If its not on the io list, we need to put the block group */ ++ if (should_put) ++ btrfs_put_block_group(cache); ++ btrfs_delayed_refs_rsv_release(fs_info, 1); ++ spin_lock(&cur_trans->dirty_bgs_lock); ++ } ++ spin_unlock(&cur_trans->dirty_bgs_lock); ++ ++ /* ++ * Refer to the definition of io_bgs member for details why it's safe ++ * to use it without any locking ++ */ ++ while (!list_empty(io)) { ++ cache = list_first_entry(io, struct btrfs_block_group_cache, ++ io_list); ++ list_del_init(&cache->io_list); ++ btrfs_wait_cache_io(trans, cache, path); ++ btrfs_put_block_group(cache); ++ } ++ ++ btrfs_free_path(path); ++ return ret; ++} +--- a/fs/btrfs/block-group.h ++++ b/fs/btrfs/block-group.h +@@ -192,6 +192,9 @@ void btrfs_create_pending_block_groups(s + struct btrfs_fs_info *fs_info); + int btrfs_inc_block_group_ro(struct btrfs_block_group_cache *cache); + void btrfs_dec_block_group_ro(struct btrfs_block_group_cache *cache); ++int btrfs_start_dirty_block_groups(struct btrfs_trans_handle *trans); ++int btrfs_write_dirty_block_groups(struct btrfs_trans_handle *trans); ++int btrfs_setup_space_cache(struct btrfs_trans_handle *trans); + + static inline int btrfs_block_group_cache_done( + struct btrfs_block_group_cache *cache) +--- a/fs/btrfs/ctree.h ++++ b/fs/btrfs/ctree.h +@@ -2522,12 +2522,6 @@ int btrfs_inc_extent_ref(struct btrfs_tr + struct btrfs_root *root, + struct btrfs_ref *generic_ref); + +-int btrfs_start_dirty_block_groups(struct btrfs_trans_handle *trans, +- struct btrfs_fs_info *fs_info); +-int btrfs_write_dirty_block_groups(struct btrfs_trans_handle *trans, +- struct btrfs_fs_info *fs_info); +-int btrfs_setup_space_cache(struct btrfs_trans_handle *trans, +- struct btrfs_fs_info *fs_info); + int btrfs_extent_readonly(struct btrfs_fs_info *fs_info, u64 bytenr); + int btrfs_free_block_groups(struct btrfs_fs_info *info); + int btrfs_can_relocate(struct btrfs_fs_info *fs_info, u64 bytenr); +--- a/fs/btrfs/extent-tree.c ++++ b/fs/btrfs/extent-tree.c +@@ -2716,525 +2716,6 @@ int btrfs_dec_ref(struct btrfs_trans_han + return __btrfs_mod_ref(trans, root, buf, full_backref, 0); + } + +-static int write_one_cache_group(struct btrfs_trans_handle *trans, +- struct btrfs_fs_info *fs_info, +- struct btrfs_path *path, +- struct btrfs_block_group_cache *cache) +-{ +- int ret; +- struct btrfs_root *extent_root = fs_info->extent_root; +- unsigned long bi; +- struct extent_buffer *leaf; +- +- ret = btrfs_search_slot(trans, extent_root, &cache->key, path, 0, 1); +- if (ret) { +- if (ret > 0) +- ret = -ENOENT; +- goto fail; +- } +- +- leaf = path->nodes[0]; +- bi = btrfs_item_ptr_offset(leaf, path->slots[0]); +- write_extent_buffer(leaf, &cache->item, bi, sizeof(cache->item)); +- btrfs_mark_buffer_dirty(leaf); +-fail: +- btrfs_release_path(path); +- return ret; +- +-} +- +-static int cache_save_setup(struct btrfs_block_group_cache *block_group, +- struct btrfs_trans_handle *trans, +- struct btrfs_path *path) +-{ +- struct btrfs_fs_info *fs_info = block_group->fs_info; +- struct btrfs_root *root = fs_info->tree_root; +- struct inode *inode = NULL; +- struct extent_changeset *data_reserved = NULL; +- u64 alloc_hint = 0; +- int dcs = BTRFS_DC_ERROR; +- u64 num_pages = 0; +- int retries = 0; +- int ret = 0; +- +- /* +- * If this block group is smaller than 100 megs don't bother caching the +- * block group. +- */ +- if (block_group->key.offset < (100 * SZ_1M)) { +- spin_lock(&block_group->lock); +- block_group->disk_cache_state = BTRFS_DC_WRITTEN; +- spin_unlock(&block_group->lock); +- return 0; +- } +- +- if (trans->aborted) +- return 0; +-again: +- inode = lookup_free_space_inode(fs_info, block_group, path); +- if (IS_ERR(inode) && PTR_ERR(inode) != -ENOENT) { +- ret = PTR_ERR(inode); +- btrfs_release_path(path); +- goto out; +- } +- +- if (IS_ERR(inode)) { +- BUG_ON(retries); +- retries++; +- +- if (block_group->ro) +- goto out_free; +- +- ret = create_free_space_inode(fs_info, trans, block_group, +- path); +- if (ret) +- goto out_free; +- goto again; +- } +- +- /* +- * We want to set the generation to 0, that way if anything goes wrong +- * from here on out we know not to trust this cache when we load up next +- * time. +- */ +- BTRFS_I(inode)->generation = 0; +- ret = btrfs_update_inode(trans, root, inode); +- if (ret) { +- /* +- * So theoretically we could recover from this, simply set the +- * super cache generation to 0 so we know to invalidate the +- * cache, but then we'd have to keep track of the block groups +- * that fail this way so we know we _have_ to reset this cache +- * before the next commit or risk reading stale cache. So to +- * limit our exposure to horrible edge cases lets just abort the +- * transaction, this only happens in really bad situations +- * anyway. +- */ +- btrfs_abort_transaction(trans, ret); +- goto out_put; +- } +- WARN_ON(ret); +- +- /* We've already setup this transaction, go ahead and exit */ +- if (block_group->cache_generation == trans->transid && +- i_size_read(inode)) { +- dcs = BTRFS_DC_SETUP; +- goto out_put; +- } +- +- if (i_size_read(inode) > 0) { +- ret = btrfs_check_trunc_cache_free_space(fs_info, +- &fs_info->global_block_rsv); +- if (ret) +- goto out_put; +- +- ret = btrfs_truncate_free_space_cache(trans, NULL, inode); +- if (ret) +- goto out_put; +- } +- +- spin_lock(&block_group->lock); +- if (block_group->cached != BTRFS_CACHE_FINISHED || +- !btrfs_test_opt(fs_info, SPACE_CACHE)) { +- /* +- * don't bother trying to write stuff out _if_ +- * a) we're not cached, +- * b) we're with nospace_cache mount option, +- * c) we're with v2 space_cache (FREE_SPACE_TREE). +- */ +- dcs = BTRFS_DC_WRITTEN; +- spin_unlock(&block_group->lock); +- goto out_put; +- } +- spin_unlock(&block_group->lock); +- +- /* +- * We hit an ENOSPC when setting up the cache in this transaction, just +- * skip doing the setup, we've already cleared the cache so we're safe. +- */ +- if (test_bit(BTRFS_TRANS_CACHE_ENOSPC, &trans->transaction->flags)) { +- ret = -ENOSPC; +- goto out_put; +- } +- +- /* +- * Try to preallocate enough space based on how big the block group is. +- * Keep in mind this has to include any pinned space which could end up +- * taking up quite a bit since it's not folded into the other space +- * cache. +- */ +- num_pages = div_u64(block_group->key.offset, SZ_256M); +- if (!num_pages) +- num_pages = 1; +- +- num_pages *= 16; +- num_pages *= PAGE_SIZE; +- +- ret = btrfs_check_data_free_space(inode, &data_reserved, 0, num_pages); +- if (ret) +- goto out_put; +- +- ret = btrfs_prealloc_file_range_trans(inode, trans, 0, 0, num_pages, +- num_pages, num_pages, +- &alloc_hint); +- /* +- * Our cache requires contiguous chunks so that we don't modify a bunch +- * of metadata or split extents when writing the cache out, which means +- * we can enospc if we are heavily fragmented in addition to just normal +- * out of space conditions. So if we hit this just skip setting up any +- * other block groups for this transaction, maybe we'll unpin enough +- * space the next time around. +- */ +- if (!ret) +- dcs = BTRFS_DC_SETUP; +- else if (ret == -ENOSPC) +- set_bit(BTRFS_TRANS_CACHE_ENOSPC, &trans->transaction->flags); +- +-out_put: +- iput(inode); +-out_free: +- btrfs_release_path(path); +-out: +- spin_lock(&block_group->lock); +- if (!ret && dcs == BTRFS_DC_SETUP) +- block_group->cache_generation = trans->transid; +- block_group->disk_cache_state = dcs; +- spin_unlock(&block_group->lock); +- +- extent_changeset_free(data_reserved); +- return ret; +-} +- +-int btrfs_setup_space_cache(struct btrfs_trans_handle *trans, +- struct btrfs_fs_info *fs_info) +-{ +- struct btrfs_block_group_cache *cache, *tmp; +- struct btrfs_transaction *cur_trans = trans->transaction; +- struct btrfs_path *path; +- +- if (list_empty(&cur_trans->dirty_bgs) || +- !btrfs_test_opt(fs_info, SPACE_CACHE)) +- return 0; +- +- path = btrfs_alloc_path(); +- if (!path) +- return -ENOMEM; +- +- /* Could add new block groups, use _safe just in case */ +- list_for_each_entry_safe(cache, tmp, &cur_trans->dirty_bgs, +- dirty_list) { +- if (cache->disk_cache_state == BTRFS_DC_CLEAR) +- cache_save_setup(cache, trans, path); +- } +- +- btrfs_free_path(path); +- return 0; +-} +- +-/* +- * transaction commit does final block group cache writeback during a +- * critical section where nothing is allowed to change the FS. This is +- * required in order for the cache to actually match the block group, +- * but can introduce a lot of latency into the commit. +- * +- * So, btrfs_start_dirty_block_groups is here to kick off block group +- * cache IO. There's a chance we'll have to redo some of it if the +- * block group changes again during the commit, but it greatly reduces +- * the commit latency by getting rid of the easy block groups while +- * we're still allowing others to join the commit. +- */ +-int btrfs_start_dirty_block_groups(struct btrfs_trans_handle *trans, +- struct btrfs_fs_info *fs_info) +-{ +- struct btrfs_block_group_cache *cache; +- struct btrfs_transaction *cur_trans = trans->transaction; +- int ret = 0; +- int should_put; +- struct btrfs_path *path = NULL; +- LIST_HEAD(dirty); +- struct list_head *io = &cur_trans->io_bgs; +- int num_started = 0; +- int loops = 0; +- +- spin_lock(&cur_trans->dirty_bgs_lock); +- if (list_empty(&cur_trans->dirty_bgs)) { +- spin_unlock(&cur_trans->dirty_bgs_lock); +- return 0; +- } +- list_splice_init(&cur_trans->dirty_bgs, &dirty); +- spin_unlock(&cur_trans->dirty_bgs_lock); +- +-again: +- /* +- * make sure all the block groups on our dirty list actually +- * exist +- */ +- btrfs_create_pending_block_groups(trans, fs_info); +- +- if (!path) { +- path = btrfs_alloc_path(); +- if (!path) +- return -ENOMEM; +- } +- +- /* +- * cache_write_mutex is here only to save us from balance or automatic +- * removal of empty block groups deleting this block group while we are +- * writing out the cache +- */ +- mutex_lock(&trans->transaction->cache_write_mutex); +- while (!list_empty(&dirty)) { +- bool drop_reserve = true; +- +- cache = list_first_entry(&dirty, +- struct btrfs_block_group_cache, +- dirty_list); +- /* +- * this can happen if something re-dirties a block +- * group that is already under IO. Just wait for it to +- * finish and then do it all again +- */ +- if (!list_empty(&cache->io_list)) { +- list_del_init(&cache->io_list); +- btrfs_wait_cache_io(trans, cache, path); +- btrfs_put_block_group(cache); +- } +- +- +- /* +- * btrfs_wait_cache_io uses the cache->dirty_list to decide +- * if it should update the cache_state. Don't delete +- * until after we wait. +- * +- * Since we're not running in the commit critical section +- * we need the dirty_bgs_lock to protect from update_block_group +- */ +- spin_lock(&cur_trans->dirty_bgs_lock); +- list_del_init(&cache->dirty_list); +- spin_unlock(&cur_trans->dirty_bgs_lock); +- +- should_put = 1; +- +- cache_save_setup(cache, trans, path); +- +- if (cache->disk_cache_state == BTRFS_DC_SETUP) { +- cache->io_ctl.inode = NULL; +- ret = btrfs_write_out_cache(fs_info, trans, +- cache, path); +- if (ret == 0 && cache->io_ctl.inode) { +- num_started++; +- should_put = 0; +- +- /* +- * the cache_write_mutex is protecting +- * the io_list +- */ +- list_add_tail(&cache->io_list, io); +- } else { +- /* +- * if we failed to write the cache, the +- * generation will be bad and life goes on +- */ +- ret = 0; +- } +- } +- if (!ret) { +- ret = write_one_cache_group(trans, fs_info, +- path, cache); +- /* +- * Our block group might still be attached to the list +- * of new block groups in the transaction handle of some +- * other task (struct btrfs_trans_handle->new_bgs). This +- * means its block group item isn't yet in the extent +- * tree. If this happens ignore the error, as we will +- * try again later in the critical section of the +- * transaction commit. +- */ +- if (ret == -ENOENT) { +- ret = 0; +- spin_lock(&cur_trans->dirty_bgs_lock); +- if (list_empty(&cache->dirty_list)) { +- list_add_tail(&cache->dirty_list, +- &cur_trans->dirty_bgs); +- btrfs_get_block_group(cache); +- drop_reserve = false; +- } +- spin_unlock(&cur_trans->dirty_bgs_lock); +- } else if (ret) { +- btrfs_abort_transaction(trans, ret); +- } +- } +- +- /* if its not on the io list, we need to put the block group */ +- if (should_put) +- btrfs_put_block_group(cache); +- if (drop_reserve) +- btrfs_delayed_refs_rsv_release(fs_info, 1); +- +- if (ret) +- break; +- +- /* +- * Avoid blocking other tasks for too long. It might even save +- * us from writing caches for block groups that are going to be +- * removed. +- */ +- mutex_unlock(&trans->transaction->cache_write_mutex); +- mutex_lock(&trans->transaction->cache_write_mutex); +- } +- mutex_unlock(&trans->transaction->cache_write_mutex); +- +- /* +- * go through delayed refs for all the stuff we've just kicked off +- * and then loop back (just once) +- */ +- ret = btrfs_run_delayed_refs(trans, fs_info, 0); +- if (!ret && loops == 0) { +- loops++; +- spin_lock(&cur_trans->dirty_bgs_lock); +- list_splice_init(&cur_trans->dirty_bgs, &dirty); +- /* +- * dirty_bgs_lock protects us from concurrent block group +- * deletes too (not just cache_write_mutex). +- */ +- if (!list_empty(&dirty)) { +- spin_unlock(&cur_trans->dirty_bgs_lock); +- goto again; +- } +- spin_unlock(&cur_trans->dirty_bgs_lock); +- } else if (ret < 0) { +- btrfs_cleanup_dirty_bgs(cur_trans, fs_info); +- } +- +- btrfs_free_path(path); +- return ret; +-} +- +-int btrfs_write_dirty_block_groups(struct btrfs_trans_handle *trans, +- struct btrfs_fs_info *fs_info) +-{ +- struct btrfs_block_group_cache *cache; +- struct btrfs_transaction *cur_trans = trans->transaction; +- int ret = 0; +- int should_put; +- struct btrfs_path *path; +- struct list_head *io = &cur_trans->io_bgs; +- int num_started = 0; +- +- path = btrfs_alloc_path(); +- if (!path) +- return -ENOMEM; +- +- /* +- * Even though we are in the critical section of the transaction commit, +- * we can still have concurrent tasks adding elements to this +- * transaction's list of dirty block groups. These tasks correspond to +- * endio free space workers started when writeback finishes for a +- * space cache, which run inode.c:btrfs_finish_ordered_io(), and can +- * allocate new block groups as a result of COWing nodes of the root +- * tree when updating the free space inode. The writeback for the space +- * caches is triggered by an earlier call to +- * btrfs_start_dirty_block_groups() and iterations of the following +- * loop. +- * Also we want to do the cache_save_setup first and then run the +- * delayed refs to make sure we have the best chance at doing this all +- * in one shot. +- */ +- spin_lock(&cur_trans->dirty_bgs_lock); +- while (!list_empty(&cur_trans->dirty_bgs)) { +- cache = list_first_entry(&cur_trans->dirty_bgs, +- struct btrfs_block_group_cache, +- dirty_list); +- +- /* +- * this can happen if cache_save_setup re-dirties a block +- * group that is already under IO. Just wait for it to +- * finish and then do it all again +- */ +- if (!list_empty(&cache->io_list)) { +- spin_unlock(&cur_trans->dirty_bgs_lock); +- list_del_init(&cache->io_list); +- btrfs_wait_cache_io(trans, cache, path); +- btrfs_put_block_group(cache); +- spin_lock(&cur_trans->dirty_bgs_lock); +- } +- +- /* +- * don't remove from the dirty list until after we've waited +- * on any pending IO +- */ +- list_del_init(&cache->dirty_list); +- spin_unlock(&cur_trans->dirty_bgs_lock); +- should_put = 1; +- +- cache_save_setup(cache, trans, path); +- +- if (!ret) +- ret = btrfs_run_delayed_refs(trans, fs_info, +- (unsigned long) -1); +- +- if (!ret && cache->disk_cache_state == BTRFS_DC_SETUP) { +- cache->io_ctl.inode = NULL; +- ret = btrfs_write_out_cache(fs_info, trans, +- cache, path); +- if (ret == 0 && cache->io_ctl.inode) { +- num_started++; +- should_put = 0; +- list_add_tail(&cache->io_list, io); +- } else { +- /* +- * if we failed to write the cache, the +- * generation will be bad and life goes on +- */ +- ret = 0; +- } +- } +- if (!ret) { +- ret = write_one_cache_group(trans, fs_info, +- path, cache); +- /* +- * One of the free space endio workers might have +- * created a new block group while updating a free space +- * cache's inode (at inode.c:btrfs_finish_ordered_io()) +- * and hasn't released its transaction handle yet, in +- * which case the new block group is still attached to +- * its transaction handle and its creation has not +- * finished yet (no block group item in the extent tree +- * yet, etc). If this is the case, wait for all free +- * space endio workers to finish and retry. This is a +- * a very rare case so no need for a more efficient and +- * complex approach. +- */ +- if (ret == -ENOENT) { +- wait_event(cur_trans->writer_wait, +- atomic_read(&cur_trans->num_writers) == 1); +- ret = write_one_cache_group(trans, fs_info, +- path, cache); +- } +- if (ret) +- btrfs_abort_transaction(trans, ret); +- } +- +- /* if its not on the io list, we need to put the block group */ +- if (should_put) +- btrfs_put_block_group(cache); +- btrfs_delayed_refs_rsv_release(fs_info, 1); +- spin_lock(&cur_trans->dirty_bgs_lock); +- } +- spin_unlock(&cur_trans->dirty_bgs_lock); +- +- while (!list_empty(io)) { +- cache = list_first_entry(io, struct btrfs_block_group_cache, +- io_list); +- list_del_init(&cache->io_list); +- btrfs_wait_cache_io(trans, cache, path); +- btrfs_put_block_group(cache); +- } +- +- btrfs_free_path(path); +- return ret; +-} +- + int btrfs_extent_readonly(struct btrfs_fs_info *fs_info, u64 bytenr) + { + struct btrfs_block_group_cache *block_group; +--- a/fs/btrfs/transaction.c ++++ b/fs/btrfs/transaction.c +@@ -1188,7 +1188,7 @@ static noinline int commit_cowonly_roots + if (ret) + return ret; + +- ret = btrfs_setup_space_cache(trans, fs_info); ++ ret = btrfs_setup_space_cache(trans); + if (ret) + return ret; + +@@ -1216,7 +1216,7 @@ again: + } + + while (!list_empty(dirty_bgs) || !list_empty(io_bgs)) { +- ret = btrfs_write_dirty_block_groups(trans, fs_info); ++ ret = btrfs_write_dirty_block_groups(trans); + if (ret) + return ret; + ret = btrfs_run_delayed_refs(trans, fs_info, (unsigned long)-1); +@@ -2028,7 +2028,7 @@ int btrfs_commit_transaction(struct btrf + mutex_unlock(&fs_info->ro_block_group_mutex); + + if (run_it) +- ret = btrfs_start_dirty_block_groups(trans, fs_info); ++ ret = btrfs_start_dirty_block_groups(trans); + } + if (ret) { + btrfs_end_transaction(trans); diff --git a/patches.suse/0017-btrfs-stop-using-block_rsv_release_bytes-everywhere.patch b/patches.suse/0017-btrfs-stop-using-block_rsv_release_bytes-everywhere.patch new file mode 100644 index 0000000..28c88bb --- /dev/null +++ b/patches.suse/0017-btrfs-stop-using-block_rsv_release_bytes-everywhere.patch @@ -0,0 +1,65 @@ +From: Josef Bacik +Date: Wed, 19 Jun 2019 13:47:21 -0400 +Subject: btrfs: stop using block_rsv_release_bytes everywhere +Git-commit: 424a47805a819ff59ada9549c4a21fe0ba95c446 +Patch-mainline: v5.3-rc1 +References: bsc#1165949 + +block_rsv_release_bytes() is the internal to the block_rsv code, and +shouldn't be called directly by anything else. Switch all users to the +exported helpers. + +Signed-off-by: Josef Bacik +Signed-off-by: David Sterba +Acked-by: Nikolay Borisov +--- + fs/btrfs/extent-tree.c | 14 ++++++-------- + 1 file changed, 6 insertions(+), 8 deletions(-) + +--- a/fs/btrfs/extent-tree.c ++++ b/fs/btrfs/extent-tree.c +@@ -4960,12 +4960,11 @@ void btrfs_inode_rsv_release(struct btrf + void btrfs_delayed_refs_rsv_release(struct btrfs_fs_info *fs_info, int nr) + { + struct btrfs_block_rsv *block_rsv = &fs_info->delayed_refs_rsv; +- struct btrfs_block_rsv *global_rsv = &fs_info->global_block_rsv; + u64 num_bytes = btrfs_calc_trans_metadata_size(fs_info, nr); + u64 released = 0; + +- released = block_rsv_release_bytes(fs_info, block_rsv, global_rsv, +- num_bytes, NULL); ++ released = __btrfs_block_rsv_release(fs_info, block_rsv, num_bytes, ++ NULL); + if (released) + trace_btrfs_space_reservation(fs_info, "delayed_refs_rsv", + 0, released, 0); +@@ -5050,8 +5049,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, NULL); ++ btrfs_block_rsv_release(fs_info, &fs_info->global_block_rsv, (u64)-1); + 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); +@@ -5119,8 +5117,8 @@ 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, NULL); ++ btrfs_block_rsv_release(fs_info, &fs_info->chunk_block_rsv, ++ trans->chunk_bytes_reserved); + trans->chunk_bytes_reserved = 0; + } + +@@ -7550,7 +7548,7 @@ static void unuse_block_rsv(struct btrfs + struct btrfs_block_rsv *block_rsv, u32 blocksize) + { + btrfs_block_rsv_add_bytes(block_rsv, blocksize, 0); +- block_rsv_release_bytes(fs_info, block_rsv, NULL, 0, NULL); ++ btrfs_block_rsv_release(fs_info, block_rsv, 0); + } + + /* diff --git a/patches.suse/0017-md-raid10-Fix-raid10-replace-hang-when-new-added-dis.patch b/patches.suse/0017-md-raid10-Fix-raid10-replace-hang-when-new-added-dis.patch new file mode 100644 index 0000000..ee0e261 --- /dev/null +++ b/patches.suse/0017-md-raid10-Fix-raid10-replace-hang-when-new-added-dis.patch @@ -0,0 +1,129 @@ +From ee37d7314a32ab6809eacc3389bad0406c69a81f Mon Sep 17 00:00:00 2001 +From: Alex Wu +Date: Fri, 21 Sep 2018 16:05:03 +0800 +Subject: [PATCH] md/raid10: Fix raid10 replace hang when new added disk faulty +Git-commit: ee37d7314a32ab6809eacc3389bad0406c69a81f +Patch-mainline: v4.20-rc1 +References: bsc#1166003 + +[Symptom] + +Resync thread hang when new added disk faulty during replacing. + +[Root Cause] + +In raid10_sync_request(), we expect to issue a bio with callback +end_sync_read(), and a bio with callback end_sync_write(). + +In normal situation, we will add resyncing sectors into +mddev->recovery_active when raid10_sync_request() returned, and sub +resynced sectors from mddev->recovery_active when end_sync_write() +calls end_sync_request(). + +If new added disk, which are replacing the old disk, is set faulty, +there is a race condition: + 1. In the first rcu protected section, resync thread did not detect + that mreplace is set faulty and pass the condition. + 2. In the second rcu protected section, mreplace is set faulty. + 3. But, resync thread will prepare the read object first, and then + check the write condition. + 4. It will find that mreplace is set faulty and do not have to + prepare write object. +This cause we add resync sectors but never sub it. + +[How to Reproduce] + +This issue can be easily reproduced by the following steps: + mdadm -C /dev/md0 --assume-clean -l 10 -n 4 /dev/sd[abcd] + mdadm /dev/md0 -a /dev/sde + mdadm /dev/md0 --replace /dev/sdd + sleep 1 + mdadm /dev/md0 -f /dev/sde + +[How to Fix] + +This issue can be fixed by using local variables to record the result +of test conditions. Once the conditions are satisfied, we can make sure +that we need to issue a bio for read and a bio for write. + +Previous 'commit 24afd80d99f8 ("md/raid10: handle recovery of +replacement devices.")' will also check whether bio is NULL, but leave +the comment saying that it is a pointless test. So we remove this dummy +check. + +Reported-by: Alex Chen +Reviewed-by: Allen Peng +Reviewed-by: BingJing Chang +Signed-off-by: Alex Wu +Signed-off-by: Shaohua Li +Signed-off-by: Coly Li + +--- + drivers/md/raid10.c | 27 ++++++++++++++------------- + 1 file changed, 14 insertions(+), 13 deletions(-) + +diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c +index d6f7978b4449..749848b2c477 100644 +--- a/drivers/md/raid10.c ++++ b/drivers/md/raid10.c +@@ -3079,6 +3079,8 @@ static sector_t raid10_sync_request(struct mddev *mddev, sector_t sector_nr, + sector_t sect; + int must_sync; + int any_working; ++ int need_recover = 0; ++ int need_replace = 0; + struct raid10_info *mirror = &conf->mirrors[i]; + struct md_rdev *mrdev, *mreplace; + +@@ -3086,11 +3088,15 @@ static sector_t raid10_sync_request(struct mddev *mddev, sector_t sector_nr, + mrdev = rcu_dereference(mirror->rdev); + mreplace = rcu_dereference(mirror->replacement); + +- if ((mrdev == NULL || +- test_bit(Faulty, &mrdev->flags) || +- test_bit(In_sync, &mrdev->flags)) && +- (mreplace == NULL || +- test_bit(Faulty, &mreplace->flags))) { ++ if (mrdev != NULL && ++ !test_bit(Faulty, &mrdev->flags) && ++ !test_bit(In_sync, &mrdev->flags)) ++ need_recover = 1; ++ if (mreplace != NULL && ++ !test_bit(Faulty, &mreplace->flags)) ++ need_replace = 1; ++ ++ if (!need_recover && !need_replace) { + rcu_read_unlock(); + continue; + } +@@ -3213,7 +3219,7 @@ static sector_t raid10_sync_request(struct mddev *mddev, sector_t sector_nr, + r10_bio->devs[1].devnum = i; + r10_bio->devs[1].addr = to_addr; + +- if (!test_bit(In_sync, &mrdev->flags)) { ++ if (need_recover) { + bio = r10_bio->devs[1].bio; + bio->bi_next = biolist; + biolist = bio; +@@ -3230,16 +3236,11 @@ static sector_t raid10_sync_request(struct mddev *mddev, sector_t sector_nr, + bio = r10_bio->devs[1].repl_bio; + if (bio) + bio->bi_end_io = NULL; +- /* Note: if mreplace != NULL, then bio ++ /* Note: if need_replace, then bio + * cannot be NULL as r10buf_pool_alloc will + * have allocated it. +- * So the second test here is pointless. +- * But it keeps semantic-checkers happy, and +- * this comment keeps human reviewers +- * happy. + */ +- if (mreplace == NULL || bio == NULL || +- test_bit(Faulty, &mreplace->flags)) ++ if (!need_replace) + break; + bio->bi_next = biolist; + biolist = bio; +-- +2.25.0 + diff --git a/patches.suse/0018-btrfs-always-reserve-our-entire-size-for-the-global-reserve.patch b/patches.suse/0018-btrfs-always-reserve-our-entire-size-for-the-global-reserve.patch new file mode 100644 index 0000000..ed6ef23 --- /dev/null +++ b/patches.suse/0018-btrfs-always-reserve-our-entire-size-for-the-global-reserve.patch @@ -0,0 +1,50 @@ +From: Josef Bacik +Date: Thu, 22 Aug 2019 15:19:01 -0400 +Subject: btrfs: always reserve our entire size for the global reserve +Git-commit: d792b0f197116b7093c119df29cb174ccfde94b9 +Patch-mainline: v5.4-rc1 +References: bsc#1165949 + +While messing with the overcommit logic I noticed that sometimes we'd +ENOSPC out when really we should have run out of space much earlier. It +turns out it's because we'll only reserve up to the free amount left in +the space info for the global reserve, but that doesn't make sense with +overcommit because we could be well above our actual size. This results +in the global reserve not carving out it's entire reservation, and thus +not putting enough pressure on the rest of the infrastructure to do the +right thing and ENOSPC out at a convenient time. Fix this by always +taking our full reservation amount for the global reserve. + +Reviewed-by: Nikolay Borisov +Signed-off-by: Josef Bacik +Signed-off-by: David Sterba +Acked-by: Nikolay Borisov +--- + fs/btrfs/block-rsv.c | 13 ++++--------- + 1 file changed, 4 insertions(+), 9 deletions(-) + +diff --git a/fs/btrfs/block-rsv.c b/fs/btrfs/block-rsv.c +index c8b7995c33ee..bea66b499e6f 100644 +--- a/fs/btrfs/block-rsv.c ++++ b/fs/btrfs/block-rsv.c +@@ -296,15 +296,10 @@ void btrfs_update_global_block_rsv(struct btrfs_fs_info *fs_info) + block_rsv->size = min_t(u64, num_bytes, SZ_512M); + + if (block_rsv->reserved < block_rsv->size) { +- num_bytes = btrfs_space_info_used(sinfo, true); +- if (sinfo->total_bytes > num_bytes) { +- num_bytes = sinfo->total_bytes - num_bytes; +- num_bytes = min(num_bytes, +- block_rsv->size - block_rsv->reserved); +- block_rsv->reserved += num_bytes; +- btrfs_space_info_update_bytes_may_use(fs_info, sinfo, +- num_bytes); +- } ++ num_bytes = block_rsv->size - block_rsv->reserved; ++ block_rsv->reserved += num_bytes; ++ btrfs_space_info_update_bytes_may_use(fs_info, sinfo, ++ num_bytes); + } else if (block_rsv->reserved > block_rsv->size) { + num_bytes = block_rsv->reserved - block_rsv->size; + btrfs_space_info_update_bytes_may_use(fs_info, sinfo, + diff --git a/patches.suse/0018-btrfs-export-block-group-accounting-helpers.patch b/patches.suse/0018-btrfs-export-block-group-accounting-helpers.patch new file mode 100644 index 0000000..f95356d --- /dev/null +++ b/patches.suse/0018-btrfs-export-block-group-accounting-helpers.patch @@ -0,0 +1,130 @@ +From: Josef Bacik +Date: Thu, 20 Jun 2019 15:38:01 -0400 +Subject: btrfs: export block group accounting helpers +Git-commit: ade4b5169f3f161e50412ad6279dc76219e05461 +Patch-mainline: v5.4-rc1 +References: bsc#1165949 + +Want to move these functions into block-group.c, so export them. + +Signed-off-by: Josef Bacik +Reviewed-by: David Sterba +Signed-off-by: David Sterba +Acked-by: Nikolay Borisov +--- + fs/btrfs/block-group.h | 7 +++++++ + fs/btrfs/extent-tree.c | 29 ++++++++++------------------- + 2 files changed, 17 insertions(+), 19 deletions(-) + +--- a/fs/btrfs/block-group.h ++++ b/fs/btrfs/block-group.h +@@ -195,6 +195,13 @@ void btrfs_dec_block_group_ro(struct btr + int btrfs_start_dirty_block_groups(struct btrfs_trans_handle *trans); + int btrfs_write_dirty_block_groups(struct btrfs_trans_handle *trans); + int btrfs_setup_space_cache(struct btrfs_trans_handle *trans); ++int btrfs_update_block_group(struct btrfs_trans_handle *trans, ++ struct btrfs_fs_info *info, ++ u64 bytenr, u64 num_bytes, int alloc); ++int btrfs_add_reserved_bytes(struct btrfs_block_group_cache *cache, ++ u64 ram_bytes, u64 num_bytes, int delalloc); ++void btrfs_free_reserved_bytes(struct btrfs_block_group_cache *cache, ++ u64 num_bytes, int delalloc); + + static inline int btrfs_block_group_cache_done( + struct btrfs_block_group_cache *cache) +--- a/fs/btrfs/extent-tree.c ++++ b/fs/btrfs/extent-tree.c +@@ -47,9 +47,6 @@ + #undef SCRAMBLE_DELAYED_REFS + + +-static int update_block_group(struct btrfs_trans_handle *trans, +- struct btrfs_fs_info *fs_info, u64 bytenr, +- u64 num_bytes, int alloc); + static int __btrfs_free_extent(struct btrfs_trans_handle *trans, + struct btrfs_fs_info *fs_info, + struct btrfs_delayed_ref_node *node, u64 parent, +@@ -71,10 +68,6 @@ static int alloc_reserved_tree_block(str + int level, struct btrfs_key *ins); + static int find_next_key(struct btrfs_path *path, int level, + struct btrfs_key *key); +-static int btrfs_add_reserved_bytes(struct btrfs_block_group_cache *cache, +- u64 ram_bytes, u64 num_bytes, int delalloc); +-static int btrfs_free_reserved_bytes(struct btrfs_block_group_cache *cache, +- u64 num_bytes, int delalloc); + + static int block_group_bits(struct btrfs_block_group_cache *cache, u64 bits) + { +@@ -3122,9 +3115,9 @@ void btrfs_trans_release_metadata(struct + trans->bytes_reserved = 0; + } + +-static int update_block_group(struct btrfs_trans_handle *trans, +- struct btrfs_fs_info *info, u64 bytenr, +- u64 num_bytes, int alloc) ++int btrfs_update_block_group(struct btrfs_trans_handle *trans, ++ struct btrfs_fs_info *info, u64 bytenr, ++ u64 num_bytes, int alloc) + { + struct btrfs_block_group_cache *cache = NULL; + u64 total = num_bytes; +@@ -3425,8 +3418,8 @@ btrfs_inc_block_group_reservations(struc + * reservation and the block group has become read only we cannot make the + * reservation and return -EAGAIN, otherwise this function always succeeds. + */ +-static int btrfs_add_reserved_bytes(struct btrfs_block_group_cache *cache, +- u64 ram_bytes, u64 num_bytes, int delalloc) ++int btrfs_add_reserved_bytes(struct btrfs_block_group_cache *cache, ++ u64 ram_bytes, u64 num_bytes, int delalloc) + { + struct btrfs_space_info *space_info = cache->space_info; + int ret = 0; +@@ -3464,11 +3457,10 @@ static int btrfs_add_reserved_bytes(stru + * reserve set to 0 in order to clear the reservation. + */ + +-static int btrfs_free_reserved_bytes(struct btrfs_block_group_cache *cache, +- u64 num_bytes, int delalloc) ++void btrfs_free_reserved_bytes(struct btrfs_block_group_cache *cache, ++ u64 num_bytes, int delalloc) + { + struct btrfs_space_info *space_info = cache->space_info; +- int ret = 0; + + spin_lock(&space_info->lock); + spin_lock(&cache->lock); +@@ -3482,7 +3474,6 @@ static int btrfs_free_reserved_bytes(str + cache->delalloc_bytes -= num_bytes; + spin_unlock(&cache->lock); + spin_unlock(&space_info->lock); +- return ret; + } + void btrfs_prepare_extent_commit(struct btrfs_fs_info *fs_info) + { +@@ -3967,7 +3958,7 @@ static int __btrfs_free_extent(struct bt + goto out; + } + +- ret = update_block_group(trans, info, bytenr, num_bytes, 0); ++ ret = btrfs_update_block_group(trans, info, bytenr, num_bytes, 0); + if (ret) { + btrfs_abort_transaction(trans, ret); + goto out; +@@ -4891,7 +4882,7 @@ static int alloc_reserved_file_extent(st + if (ret) + return ret; + +- ret = update_block_group(trans, fs_info, ins->objectid, ins->offset, 1); ++ ret = btrfs_update_block_group(trans, fs_info, ins->objectid, ins->offset, 1); + if (ret) { /* -ENOENT, logic error */ + btrfs_err(fs_info, "update block group failed for %llu %llu", + ins->objectid, ins->offset); +@@ -4969,7 +4960,7 @@ static int alloc_reserved_tree_block(str + if (ret) + return ret; + +- ret = update_block_group(trans, fs_info, ins->objectid, ++ ret = btrfs_update_block_group(trans, fs_info, ins->objectid, + fs_info->nodesize, 1); + if (ret) { /* -ENOENT, logic error */ + btrfs_err(fs_info, "update block group failed for %llu %llu", diff --git a/patches.suse/0018-btrfs-migrate-the-block-rsv-code-to-block-rsv-c.patch b/patches.suse/0018-btrfs-migrate-the-block-rsv-code-to-block-rsv-c.patch new file mode 100644 index 0000000..5aecf32 --- /dev/null +++ b/patches.suse/0018-btrfs-migrate-the-block-rsv-code-to-block-rsv-c.patch @@ -0,0 +1,550 @@ +From: Josef Bacik +Date: Wed, 19 Jun 2019 13:47:22 -0400 +Subject: btrfs: migrate the block-rsv code to block-rsv.c +Git-commit: 550fa228ee7ebea3c3499897a7aef6536de73fff +Patch-mainline: v5.3-rc1 +References: bsc#1165949 + +This moves everything out of extent-tree.c to block-rsv.c. + +Signed-off-by: Josef Bacik +Signed-off-by: David Sterba +Acked-by: Nikolay Borisov +--- + fs/btrfs/Makefile | 3 + fs/btrfs/block-rsv.c | 253 +++++++++++++++++++++++++++++++++++++++++++++++++ + fs/btrfs/extent-tree.c | 248 ------------------------------------------------ + 3 files changed, 255 insertions(+), 249 deletions(-) + +--- a/fs/btrfs/Makefile ++++ b/fs/btrfs/Makefile +@@ -9,7 +9,8 @@ btrfs-y += super.o ctree.o extent-tree.o + export.o tree-log.o free-space-cache.o zlib.o lzo.o zstd.o \ + compression.o delayed-ref.o relocation.o delayed-inode.o scrub.o \ + reada.o backref.o ulist.o qgroup.o send.o dev-replace.o raid56.o \ +- uuid-tree.o props.o hash.o free-space-tree.o tree-checker.o space-info.o ++ uuid-tree.o props.o hash.o free-space-tree.o tree-checker.o space-info.o \ ++ block-rsv.o + + btrfs-$(CONFIG_BTRFS_FS_POSIX_ACL) += acl.o + btrfs-$(CONFIG_BTRFS_FS_CHECK_INTEGRITY) += check-integrity.o +--- /dev/null ++++ b/fs/btrfs/block-rsv.c +@@ -0,0 +1,253 @@ ++// SPDX-License-Identifier: GPL-2.0 ++ ++#include "ctree.h" ++#include "block-rsv.h" ++#include "space-info.h" ++#include "math.h" ++ ++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, ++ 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) { ++ 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; ++ block_rsv->reserved = block_rsv->size; ++ block_rsv->full = 1; ++ } 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; ++ if (num_bytes > 0) { ++ if (dest) { ++ spin_lock(&dest->lock); ++ if (!dest->full) { ++ u64 bytes_to_add; ++ ++ bytes_to_add = dest->size - dest->reserved; ++ bytes_to_add = min(num_bytes, bytes_to_add); ++ dest->reserved += bytes_to_add; ++ if (dest->reserved >= dest->size) ++ dest->full = 1; ++ num_bytes -= bytes_to_add; ++ } ++ spin_unlock(&dest->lock); ++ } ++ if (num_bytes) ++ btrfs_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; ++} ++ ++int btrfs_block_rsv_migrate(struct btrfs_block_rsv *src, ++ struct btrfs_block_rsv *dst, u64 num_bytes, ++ bool update_size) ++{ ++ int ret; ++ ++ ret = btrfs_block_rsv_use_bytes(src, num_bytes); ++ if (ret) ++ return ret; ++ ++ btrfs_block_rsv_add_bytes(dst, num_bytes, update_size); ++ return 0; ++} ++ ++void btrfs_init_block_rsv(struct btrfs_block_rsv *rsv, unsigned short type) ++{ ++ memset(rsv, 0, sizeof(*rsv)); ++ spin_lock_init(&rsv->lock); ++ 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 = btrfs_find_space_info(fs_info, ++ BTRFS_BLOCK_GROUP_METADATA); ++} ++ ++struct btrfs_block_rsv *btrfs_alloc_block_rsv(struct btrfs_fs_info *fs_info, ++ unsigned short type) ++{ ++ struct btrfs_block_rsv *block_rsv; ++ ++ block_rsv = kmalloc(sizeof(*block_rsv), GFP_NOFS); ++ if (!block_rsv) ++ return NULL; ++ ++ btrfs_init_metadata_block_rsv(fs_info, block_rsv, type); ++ return block_rsv; ++} ++ ++void btrfs_free_block_rsv(struct btrfs_fs_info *fs_info, ++ struct btrfs_block_rsv *rsv) ++{ ++ if (!rsv) ++ return; ++ btrfs_block_rsv_release(fs_info, rsv, (u64)-1); ++ kfree(rsv); ++} ++ ++int btrfs_block_rsv_add(struct btrfs_root *root, ++ struct btrfs_block_rsv *block_rsv, u64 num_bytes, ++ enum btrfs_reserve_flush_enum flush) ++{ ++ int ret; ++ ++ if (num_bytes == 0) ++ return 0; ++ ++ ret = btrfs_reserve_metadata_bytes(root, block_rsv, num_bytes, flush); ++ if (!ret) ++ btrfs_block_rsv_add_bytes(block_rsv, num_bytes, true); ++ ++ return ret; ++} ++ ++int btrfs_block_rsv_check(struct btrfs_block_rsv *block_rsv, int min_factor) ++{ ++ u64 num_bytes = 0; ++ int ret = -ENOSPC; ++ ++ if (!block_rsv) ++ return 0; ++ ++ spin_lock(&block_rsv->lock); ++ num_bytes = div_factor(block_rsv->size, min_factor); ++ if (block_rsv->reserved >= num_bytes) ++ ret = 0; ++ spin_unlock(&block_rsv->lock); ++ ++ return ret; ++} ++ ++int btrfs_block_rsv_refill(struct btrfs_root *root, ++ struct btrfs_block_rsv *block_rsv, u64 min_reserved, ++ enum btrfs_reserve_flush_enum flush) ++{ ++ u64 num_bytes = 0; ++ int ret = -ENOSPC; ++ ++ if (!block_rsv) ++ return 0; ++ ++ spin_lock(&block_rsv->lock); ++ num_bytes = min_reserved; ++ if (block_rsv->reserved >= num_bytes) ++ ret = 0; ++ else ++ num_bytes -= block_rsv->reserved; ++ spin_unlock(&block_rsv->lock); ++ ++ if (!ret) ++ return 0; ++ ++ ret = btrfs_reserve_metadata_bytes(root, block_rsv, num_bytes, flush); ++ if (!ret) { ++ btrfs_block_rsv_add_bytes(block_rsv, num_bytes, false); ++ return 0; ++ } ++ ++ return ret; ++} ++ ++u64 __btrfs_block_rsv_release(struct btrfs_fs_info *fs_info, ++ struct btrfs_block_rsv *block_rsv, ++ u64 num_bytes, u64 *qgroup_to_release) ++{ ++ struct btrfs_block_rsv *global_rsv = &fs_info->global_block_rsv; ++ struct btrfs_block_rsv *delayed_rsv = &fs_info->delayed_refs_rsv; ++ struct btrfs_block_rsv *target = NULL; ++ ++ /* ++ * If we are the delayed_rsv then push to the global rsv, otherwise dump ++ * into the delayed rsv if it is not full. ++ */ ++ if (block_rsv == delayed_rsv) ++ target = global_rsv; ++ else if (block_rsv != global_rsv && !delayed_rsv->full) ++ target = delayed_rsv; ++ ++ if (target && block_rsv->space_info != target->space_info) ++ target = NULL; ++ ++ return block_rsv_release_bytes(fs_info, block_rsv, target, num_bytes, ++ qgroup_to_release); ++} ++ ++int btrfs_block_rsv_use_bytes(struct btrfs_block_rsv *block_rsv, u64 num_bytes) ++{ ++ int ret = -ENOSPC; ++ ++ spin_lock(&block_rsv->lock); ++ if (block_rsv->reserved >= num_bytes) { ++ block_rsv->reserved -= num_bytes; ++ if (block_rsv->reserved < block_rsv->size) ++ block_rsv->full = 0; ++ ret = 0; ++ } ++ spin_unlock(&block_rsv->lock); ++ return ret; ++} ++ ++void btrfs_block_rsv_add_bytes(struct btrfs_block_rsv *block_rsv, ++ u64 num_bytes, bool update_size) ++{ ++ spin_lock(&block_rsv->lock); ++ block_rsv->reserved += num_bytes; ++ if (update_size) ++ block_rsv->size += num_bytes; ++ else if (block_rsv->reserved >= block_rsv->size) ++ block_rsv->full = 1; ++ spin_unlock(&block_rsv->lock); ++} ++ ++int btrfs_cond_migrate_bytes(struct btrfs_fs_info *fs_info, ++ struct btrfs_block_rsv *dest, u64 num_bytes, ++ int min_factor) ++{ ++ struct btrfs_block_rsv *global_rsv = &fs_info->global_block_rsv; ++ u64 min_bytes; ++ ++ if (global_rsv->space_info != dest->space_info) ++ return -ENOSPC; ++ ++ spin_lock(&global_rsv->lock); ++ min_bytes = div_factor(global_rsv->size, min_factor); ++ if (global_rsv->reserved < min_bytes + num_bytes) { ++ spin_unlock(&global_rsv->lock); ++ return -ENOSPC; ++ } ++ global_rsv->reserved -= num_bytes; ++ if (global_rsv->reserved < global_rsv->size) ++ global_rsv->full = 0; ++ spin_unlock(&global_rsv->lock); ++ ++ btrfs_block_rsv_add_bytes(dest, num_bytes, true); ++ return 0; ++} +--- a/fs/btrfs/extent-tree.c ++++ b/fs/btrfs/extent-tree.c +@@ -4582,57 +4582,6 @@ static struct btrfs_block_rsv *get_block + return block_rsv; + } + +-int btrfs_block_rsv_use_bytes(struct btrfs_block_rsv *block_rsv, u64 num_bytes) +-{ +- int ret = -ENOSPC; +- spin_lock(&block_rsv->lock); +- if (block_rsv->reserved >= num_bytes) { +- block_rsv->reserved -= num_bytes; +- if (block_rsv->reserved < block_rsv->size) +- block_rsv->full = 0; +- ret = 0; +- } +- spin_unlock(&block_rsv->lock); +- return ret; +-} +- +-void btrfs_block_rsv_add_bytes(struct btrfs_block_rsv *block_rsv, u64 num_bytes, +- bool update_size) +-{ +- spin_lock(&block_rsv->lock); +- block_rsv->reserved += num_bytes; +- if (update_size) +- block_rsv->size += num_bytes; +- else if (block_rsv->reserved >= block_rsv->size) +- block_rsv->full = 1; +- spin_unlock(&block_rsv->lock); +-} +- +-int btrfs_cond_migrate_bytes(struct btrfs_fs_info *fs_info, +- struct btrfs_block_rsv *dest, u64 num_bytes, +- int min_factor) +-{ +- struct btrfs_block_rsv *global_rsv = &fs_info->global_block_rsv; +- u64 min_bytes; +- +- if (global_rsv->space_info != dest->space_info) +- return -ENOSPC; +- +- spin_lock(&global_rsv->lock); +- min_bytes = div_factor(global_rsv->size, min_factor); +- if (global_rsv->reserved < min_bytes + num_bytes) { +- spin_unlock(&global_rsv->lock); +- return -ENOSPC; +- } +- global_rsv->reserved -= num_bytes; +- if (global_rsv->reserved < global_rsv->size) +- global_rsv->full = 0; +- spin_unlock(&global_rsv->lock); +- +- btrfs_block_rsv_add_bytes(dest, num_bytes, 1); +- return 0; +-} +- + /** + * btrfs_migrate_to_delayed_refs_rsv - transfer bytes to our delayed refs rsv. + * @fs_info - the fs info for our fs. +@@ -4717,203 +4666,6 @@ int btrfs_delayed_refs_rsv_refill(struct + return 0; + } + +-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, +- 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) { +- 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; +- block_rsv->reserved = block_rsv->size; +- block_rsv->full = 1; +- } 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; +- if (num_bytes > 0) { +- if (dest) { +- spin_lock(&dest->lock); +- if (!dest->full) { +- u64 bytes_to_add; +- +- bytes_to_add = dest->size - dest->reserved; +- bytes_to_add = min(num_bytes, bytes_to_add); +- dest->reserved += bytes_to_add; +- if (dest->reserved >= dest->size) +- dest->full = 1; +- num_bytes -= bytes_to_add; +- } +- spin_unlock(&dest->lock); +- } +- if (num_bytes) +- btrfs_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; +-} +- +-int btrfs_block_rsv_migrate(struct btrfs_block_rsv *src, +- struct btrfs_block_rsv *dst, u64 num_bytes, +- bool update_size) +-{ +- int ret; +- +- ret = btrfs_block_rsv_use_bytes(src, num_bytes); +- if (ret) +- return ret; +- +- btrfs_block_rsv_add_bytes(dst, num_bytes, update_size); +- return 0; +-} +- +-void btrfs_init_block_rsv(struct btrfs_block_rsv *rsv, unsigned short type) +-{ +- memset(rsv, 0, sizeof(*rsv)); +- spin_lock_init(&rsv->lock); +- 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 = btrfs_find_space_info(fs_info, +- BTRFS_BLOCK_GROUP_METADATA); +-} +- +-struct btrfs_block_rsv *btrfs_alloc_block_rsv(struct btrfs_fs_info *fs_info, +- unsigned short type) +-{ +- struct btrfs_block_rsv *block_rsv; +- +- block_rsv = kmalloc(sizeof(*block_rsv), GFP_NOFS); +- if (!block_rsv) +- return NULL; +- +- btrfs_init_metadata_block_rsv(fs_info, block_rsv, type); +- return block_rsv; +-} +- +-void btrfs_free_block_rsv(struct btrfs_fs_info *fs_info, +- struct btrfs_block_rsv *rsv) +-{ +- if (!rsv) +- return; +- btrfs_block_rsv_release(fs_info, rsv, (u64)-1); +- kfree(rsv); +-} +- +-int btrfs_block_rsv_add(struct btrfs_root *root, +- struct btrfs_block_rsv *block_rsv, u64 num_bytes, +- enum btrfs_reserve_flush_enum flush) +-{ +- int ret; +- +- if (num_bytes == 0) +- return 0; +- +- ret = btrfs_reserve_metadata_bytes(root, block_rsv, num_bytes, flush); +- if (!ret) { +- btrfs_block_rsv_add_bytes(block_rsv, num_bytes, 1); +- return 0; +- } +- +- return ret; +-} +- +-int btrfs_block_rsv_check(struct btrfs_block_rsv *block_rsv, int min_factor) +-{ +- u64 num_bytes = 0; +- int ret = -ENOSPC; +- +- if (!block_rsv) +- return 0; +- +- spin_lock(&block_rsv->lock); +- num_bytes = div_factor(block_rsv->size, min_factor); +- if (block_rsv->reserved >= num_bytes) +- ret = 0; +- spin_unlock(&block_rsv->lock); +- +- return ret; +-} +- +-int btrfs_block_rsv_refill(struct btrfs_root *root, +- struct btrfs_block_rsv *block_rsv, u64 min_reserved, +- enum btrfs_reserve_flush_enum flush) +-{ +- u64 num_bytes = 0; +- int ret = -ENOSPC; +- +- if (!block_rsv) +- return 0; +- +- spin_lock(&block_rsv->lock); +- num_bytes = min_reserved; +- if (block_rsv->reserved >= num_bytes) +- ret = 0; +- else +- num_bytes -= block_rsv->reserved; +- spin_unlock(&block_rsv->lock); +- +- if (!ret) +- return 0; +- +- ret = btrfs_reserve_metadata_bytes(root, block_rsv, num_bytes, flush); +- if (!ret) { +- btrfs_block_rsv_add_bytes(block_rsv, num_bytes, 0); +- return 0; +- } +- +- return ret; +-} +- +-u64 __btrfs_block_rsv_release(struct btrfs_fs_info *fs_info, +- struct btrfs_block_rsv *block_rsv, +- u64 num_bytes, u64 *qgroup_to_release) +-{ +- struct btrfs_block_rsv *global_rsv = &fs_info->global_block_rsv; +- struct btrfs_block_rsv *delayed_rsv = &fs_info->delayed_refs_rsv; +- struct btrfs_block_rsv *target = NULL; +- +- /* +- * If we are the delayed_rsv then push to the global rsv, otherwise dump +- * into the delayed rsv if it is not full. +- */ +- if (block_rsv == delayed_rsv) +- target = global_rsv; +- else if (block_rsv != global_rsv && !delayed_rsv->full) +- target = delayed_rsv; +- +- if (target && block_rsv->space_info != target->space_info) +- target = NULL; +- +- return block_rsv_release_bytes(fs_info, block_rsv, target, num_bytes, +- qgroup_to_release); +-} +- + /** + * btrfs_inode_rsv_release - release any excessive reservation. + * @inode - the inode we need to release from. diff --git a/patches.suse/0018-md-remove-redundant-code-that-is-no-longer-reachable.patch b/patches.suse/0018-md-remove-redundant-code-that-is-no-longer-reachable.patch new file mode 100644 index 0000000..6fc8041 --- /dev/null +++ b/patches.suse/0018-md-remove-redundant-code-that-is-no-longer-reachable.patch @@ -0,0 +1,32 @@ +From 116d99adf59314924adae0cb691e4d289b5f2407 Mon Sep 17 00:00:00 2001 +From: Colin Ian King +Date: Mon, 8 Oct 2018 22:16:09 +0100 +Subject: [PATCH] md: remove redundant code that is no longer reachable +Git-commit: 116d99adf59314924adae0cb691e4d289b5f2407 +Patch-mainline: v4.20-rc1 +References: bsc#1111974 bsc#1166003 + +And earlier commit removed the error label to two statements that +are now never reachable. Since this code is now dead code, remove it. + +Detected by CoverityScan, CID#1462409 ("Structurally dead code") + +Fixes: d5d885fd514f ("md: introduce new personality funciton start()") +Signed-off-by: Colin Ian King +Signed-off-by: Shaohua Li +Signed-off-by: Coly Li +--- + drivers/md/raid5-cache.c | 2 -- + 1 file changed, 2 deletions(-) + +--- a/drivers/md/raid5-cache.c ++++ b/drivers/md/raid5-cache.c +@@ -3150,8 +3150,6 @@ int r5l_init_log(struct r5conf *conf, st + set_bit(MD_HAS_JOURNAL, &conf->mddev->flags); + return 0; + +- rcu_assign_pointer(conf->log, NULL); +- md_unregister_thread(&log->reclaim_thread); + reclaim_thread: + mempool_destroy(log->meta_pool); + out_mempool: diff --git a/patches.suse/0019-btrfs-Introduce-mount-time-chunk-dev-extent-mapping-.patch b/patches.suse/0019-btrfs-Introduce-mount-time-chunk-dev-extent-mapping-.patch index 62f9db6..94ad324 100644 --- a/patches.suse/0019-btrfs-Introduce-mount-time-chunk-dev-extent-mapping-.patch +++ b/patches.suse/0019-btrfs-Introduce-mount-time-chunk-dev-extent-mapping-.patch @@ -29,7 +29,7 @@ Signed-off-by: David Sterba --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c -@@ -2972,6 +2972,13 @@ retry_root_backup: +@@ -2920,6 +2920,13 @@ retry_root_backup: fs_info->generation = generation; fs_info->last_trans_committed = generation; @@ -45,7 +45,7 @@ Signed-off-by: David Sterba btrfs_err(fs_info, "failed to recover balance: %d", ret); --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c -@@ -6741,6 +6741,7 @@ static int read_one_chunk(struct btrfs_f +@@ -6558,6 +6558,7 @@ static int read_one_chunk(struct btrfs_f map->stripe_len = btrfs_chunk_stripe_len(leaf, chunk); map->type = btrfs_chunk_type(leaf, chunk); map->sub_stripes = btrfs_chunk_sub_stripes(leaf, chunk); @@ -53,9 +53,9 @@ Signed-off-by: David Sterba for (i = 0; i < num_stripes; i++) { map->stripes[i].physical = btrfs_stripe_offset_nr(leaf, chunk, i); -@@ -7316,3 +7317,186 @@ bool btrfs_pinned_by_swapfile(struct btr - fs_devices = fs_devices->seed; - } +@@ -7336,3 +7337,186 @@ int btrfs_bg_type_to_factor(u64 flags) + return 2; + return 1; } + + @@ -250,9 +250,9 @@ Signed-off-by: David Sterba struct btrfs_bio_stripe stripes[]; }; -@@ -544,4 +545,5 @@ struct list_head *btrfs_get_fs_uuids(voi - void btrfs_set_fs_info_ptr(struct btrfs_fs_info *fs_info); - void btrfs_reset_fs_info_ptr(struct btrfs_fs_info *fs_info); +@@ -553,4 +554,5 @@ void btrfs_reset_fs_info_ptr(struct btrf + + int btrfs_bg_type_to_factor(u64 flags); +int btrfs_verify_dev_extents(struct btrfs_fs_info *fs_info); #endif diff --git a/patches.suse/0019-btrfs-migrate-the-block-group-space-accounting-helpers.patch b/patches.suse/0019-btrfs-migrate-the-block-group-space-accounting-helpers.patch new file mode 100644 index 0000000..3cf07d1 --- /dev/null +++ b/patches.suse/0019-btrfs-migrate-the-block-group-space-accounting-helpers.patch @@ -0,0 +1,449 @@ +From: Josef Bacik +Date: Thu, 20 Jun 2019 15:38:02 -0400 +Subject: btrfs: migrate the block group space accounting helpers +Git-commit: 606d1bf10d7ebafdee26e8896b467b885c5233ec +Patch-mainline: v5.4-rc1 +References: bsc#1165949 + +We can now easily migrate this code as well. + +Signed-off-by: Josef Bacik +Reviewed-by: David Sterba +Signed-off-by: David Sterba +Acked-by: Nikolay Borisov +--- + fs/btrfs/block-group.c | 184 ++++++++++++++++++++++++++++++++++++++++++++++ + fs/btrfs/block-group.h | 1 + fs/btrfs/extent-tree.c | 193 +------------------------------------------------ + 3 files changed, 188 insertions(+), 190 deletions(-) + +--- a/fs/btrfs/block-group.c ++++ b/fs/btrfs/block-group.c +@@ -2540,3 +2540,187 @@ int btrfs_write_dirty_block_groups(struc + btrfs_free_path(path); + return ret; + } ++ ++int btrfs_update_block_group(struct btrfs_trans_handle *trans, ++ u64 bytenr, u64 num_bytes, int alloc) ++{ ++ struct btrfs_fs_info *info = trans->fs_info; ++ struct btrfs_block_group_cache *cache = NULL; ++ u64 total = num_bytes; ++ u64 old_val; ++ u64 byte_in_group; ++ int factor; ++ int ret = 0; ++ ++ /* Block accounting for super block */ ++ spin_lock(&info->delalloc_root_lock); ++ old_val = btrfs_super_bytes_used(info->super_copy); ++ if (alloc) ++ old_val += num_bytes; ++ else ++ old_val -= num_bytes; ++ btrfs_set_super_bytes_used(info->super_copy, old_val); ++ spin_unlock(&info->delalloc_root_lock); ++ ++ while (total) { ++ cache = btrfs_lookup_block_group(info, bytenr); ++ if (!cache) { ++ ret = -ENOENT; ++ break; ++ } ++ factor = btrfs_bg_type_to_factor(cache->flags); ++ ++ /* ++ * If this block group has free space cache written out, we ++ * need to make sure to load it if we are removing space. This ++ * is because we need the unpinning stage to actually add the ++ * space back to the block group, otherwise we will leak space. ++ */ ++ if (!alloc && cache->cached == BTRFS_CACHE_NO) ++ btrfs_cache_block_group(cache, 1); ++ ++ byte_in_group = bytenr - cache->key.objectid; ++ WARN_ON(byte_in_group > cache->key.offset); ++ ++ spin_lock(&cache->space_info->lock); ++ spin_lock(&cache->lock); ++ ++ if (btrfs_test_opt(info, SPACE_CACHE) && ++ cache->disk_cache_state < BTRFS_DC_CLEAR) ++ cache->disk_cache_state = BTRFS_DC_CLEAR; ++ ++ old_val = btrfs_block_group_used(&cache->item); ++ num_bytes = min(total, cache->key.offset - byte_in_group); ++ if (alloc) { ++ old_val += num_bytes; ++ btrfs_set_block_group_used(&cache->item, old_val); ++ cache->reserved -= num_bytes; ++ cache->space_info->bytes_reserved -= num_bytes; ++ cache->space_info->bytes_used += num_bytes; ++ cache->space_info->disk_used += num_bytes * factor; ++ spin_unlock(&cache->lock); ++ spin_unlock(&cache->space_info->lock); ++ } else { ++ old_val -= num_bytes; ++ btrfs_set_block_group_used(&cache->item, old_val); ++ cache->pinned += num_bytes; ++ btrfs_space_info_update_bytes_pinned(info, ++ cache->space_info, num_bytes); ++ cache->space_info->bytes_used -= num_bytes; ++ cache->space_info->disk_used -= num_bytes * factor; ++ spin_unlock(&cache->lock); ++ spin_unlock(&cache->space_info->lock); ++ ++ trace_btrfs_space_reservation(info, "pinned", ++ cache->space_info->flags, ++ num_bytes, 1); ++ percpu_counter_add(&cache->space_info->total_bytes_pinned, ++ num_bytes); ++ set_extent_dirty(info->pinned_extents, ++ bytenr, bytenr + num_bytes - 1, ++ GFP_NOFS | __GFP_NOFAIL); ++ } ++ ++ spin_lock(&trans->transaction->dirty_bgs_lock); ++ if (list_empty(&cache->dirty_list)) { ++ list_add_tail(&cache->dirty_list, ++ &trans->transaction->dirty_bgs); ++ trans->transaction->num_dirty_bgs++; ++ trans->delayed_ref_updates++; ++ btrfs_get_block_group(cache); ++ } ++ spin_unlock(&trans->transaction->dirty_bgs_lock); ++ ++ /* ++ * No longer have used bytes in this block group, queue it for ++ * deletion. We do this after adding the block group to the ++ * dirty list to avoid races between cleaner kthread and space ++ * cache writeout. ++ */ ++ if (!alloc && old_val == 0) { ++ spin_lock(&info->unused_bgs_lock); ++ if (list_empty(&cache->bg_list)) { ++ btrfs_get_block_group(cache); ++ list_add_tail(&cache->bg_list, ++ &info->unused_bgs); ++ } ++ spin_unlock(&info->unused_bgs_lock); ++ } ++ ++ btrfs_put_block_group(cache); ++ total -= num_bytes; ++ bytenr += num_bytes; ++ } ++ ++ /* Modified block groups are accounted for in the delayed_refs_rsv. */ ++ btrfs_update_delayed_refs_rsv(trans); ++ return ret; ++} ++ ++/** ++ * btrfs_add_reserved_bytes - update the block_group and space info counters ++ * @cache: The cache we are manipulating ++ * @ram_bytes: The number of bytes of file content, and will be same to ++ * @num_bytes except for the compress path. ++ * @num_bytes: The number of bytes in question ++ * @delalloc: The blocks are allocated for the delalloc write ++ * ++ * This is called by the allocator when it reserves space. If this is a ++ * reservation and the block group has become read only we cannot make the ++ * reservation and return -EAGAIN, otherwise this function always succeeds. ++ */ ++int btrfs_add_reserved_bytes(struct btrfs_block_group_cache *cache, ++ u64 ram_bytes, u64 num_bytes, int delalloc) ++{ ++ struct btrfs_space_info *space_info = cache->space_info; ++ int ret = 0; ++ ++ spin_lock(&space_info->lock); ++ spin_lock(&cache->lock); ++ if (cache->ro) { ++ ret = -EAGAIN; ++ } else { ++ cache->reserved += num_bytes; ++ space_info->bytes_reserved += num_bytes; ++ trace_btrfs_space_reservation(cache->fs_info, ++ "space_info", space_info->flags, ++ ram_bytes, 0); ++ btrfs_space_info_update_bytes_may_use(cache->fs_info, ++ space_info, -ram_bytes); ++ if (delalloc) ++ cache->delalloc_bytes += num_bytes; ++ } ++ spin_unlock(&cache->lock); ++ spin_unlock(&space_info->lock); ++ return ret; ++} ++ ++/** ++ * btrfs_free_reserved_bytes - update the block_group and space info counters ++ * @cache: The cache we are manipulating ++ * @num_bytes: The number of bytes in question ++ * @delalloc: The blocks are allocated for the delalloc write ++ * ++ * This is called by somebody who is freeing space that was never actually used ++ * on disk. For example if you reserve some space for a new leaf in transaction ++ * A and before transaction A commits you free that leaf, you call this with ++ * reserve set to 0 in order to clear the reservation. ++ */ ++void btrfs_free_reserved_bytes(struct btrfs_block_group_cache *cache, ++ u64 num_bytes, int delalloc) ++{ ++ struct btrfs_space_info *space_info = cache->space_info; ++ ++ spin_lock(&space_info->lock); ++ spin_lock(&cache->lock); ++ if (cache->ro) ++ space_info->bytes_readonly += num_bytes; ++ cache->reserved -= num_bytes; ++ space_info->bytes_reserved -= num_bytes; ++ space_info->max_extent_size = 0; ++ ++ if (delalloc) ++ cache->delalloc_bytes -= num_bytes; ++ spin_unlock(&cache->lock); ++ spin_unlock(&space_info->lock); ++} +--- a/fs/btrfs/block-group.h ++++ b/fs/btrfs/block-group.h +@@ -196,7 +196,6 @@ int btrfs_start_dirty_block_groups(struc + int btrfs_write_dirty_block_groups(struct btrfs_trans_handle *trans); + int btrfs_setup_space_cache(struct btrfs_trans_handle *trans); + int btrfs_update_block_group(struct btrfs_trans_handle *trans, +- struct btrfs_fs_info *info, + u64 bytenr, u64 num_bytes, int alloc); + int btrfs_add_reserved_bytes(struct btrfs_block_group_cache *cache, + u64 ram_bytes, u64 num_bytes, int delalloc); +--- a/fs/btrfs/extent-tree.c ++++ b/fs/btrfs/extent-tree.c +@@ -3115,122 +3115,6 @@ void btrfs_trans_release_metadata(struct + trans->bytes_reserved = 0; + } + +-int btrfs_update_block_group(struct btrfs_trans_handle *trans, +- struct btrfs_fs_info *info, u64 bytenr, +- u64 num_bytes, int alloc) +-{ +- struct btrfs_block_group_cache *cache = NULL; +- u64 total = num_bytes; +- u64 old_val; +- u64 byte_in_group; +- int factor; +- int ret = 0; +- +- /* block accounting for super block */ +- spin_lock(&info->delalloc_root_lock); +- old_val = btrfs_super_bytes_used(info->super_copy); +- if (alloc) +- old_val += num_bytes; +- else +- old_val -= num_bytes; +- btrfs_set_super_bytes_used(info->super_copy, old_val); +- spin_unlock(&info->delalloc_root_lock); +- +- while (total) { +- cache = btrfs_lookup_block_group(info, bytenr); +- if (!cache) { +- ret = -ENOENT; +- break; +- } +- factor = btrfs_bg_type_to_factor(cache->flags); +- +- /* +- * If this block group has free space cache written out, we +- * need to make sure to load it if we are removing space. This +- * is because we need the unpinning stage to actually add the +- * space back to the block group, otherwise we will leak space. +- */ +- if (!alloc && cache->cached == BTRFS_CACHE_NO) +- btrfs_cache_block_group(cache, 1); +- +- byte_in_group = bytenr - cache->key.objectid; +- WARN_ON(byte_in_group > cache->key.offset); +- +- spin_lock(&cache->space_info->lock); +- spin_lock(&cache->lock); +- +- if (btrfs_test_opt(info, SPACE_CACHE) && +- cache->disk_cache_state < BTRFS_DC_CLEAR) +- cache->disk_cache_state = BTRFS_DC_CLEAR; +- +- old_val = btrfs_block_group_used(&cache->item); +- num_bytes = min(total, cache->key.offset - byte_in_group); +- if (alloc) { +- old_val += num_bytes; +- btrfs_set_block_group_used(&cache->item, old_val); +- cache->reserved -= num_bytes; +- cache->space_info->bytes_reserved -= num_bytes; +- cache->space_info->bytes_used += num_bytes; +- cache->space_info->disk_used += num_bytes * factor; +- spin_unlock(&cache->lock); +- spin_unlock(&cache->space_info->lock); +- } else { +- old_val -= num_bytes; +- btrfs_set_block_group_used(&cache->item, old_val); +- cache->pinned += num_bytes; +- btrfs_space_info_update_bytes_pinned(info, +- cache->space_info, num_bytes); +- cache->space_info->bytes_used -= num_bytes; +- cache->space_info->disk_used -= num_bytes * factor; +- spin_unlock(&cache->lock); +- spin_unlock(&cache->space_info->lock); +- +- trace_btrfs_space_reservation(info, "pinned", +- cache->space_info->flags, +- num_bytes, 1); +- percpu_counter_add(&cache->space_info->total_bytes_pinned, +- num_bytes); +- set_extent_dirty(info->pinned_extents, +- bytenr, bytenr + num_bytes - 1, +- GFP_NOFS | __GFP_NOFAIL); +- } +- +- spin_lock(&trans->transaction->dirty_bgs_lock); +- if (list_empty(&cache->dirty_list)) { +- list_add_tail(&cache->dirty_list, +- &trans->transaction->dirty_bgs); +- trans->transaction->num_dirty_bgs++; +- trans->delayed_ref_updates++; +- btrfs_get_block_group(cache); +- } +- spin_unlock(&trans->transaction->dirty_bgs_lock); +- +- /* +- * No longer have used bytes in this block group, queue it for +- * deletion. We do this after adding the block group to the +- * dirty list to avoid races between cleaner kthread and space +- * cache writeout. +- */ +- if (!alloc && old_val == 0) { +- spin_lock(&info->unused_bgs_lock); +- if (list_empty(&cache->bg_list)) { +- btrfs_get_block_group(cache); +- list_add_tail(&cache->bg_list, +- &info->unused_bgs); +- } +- spin_unlock(&info->unused_bgs_lock); +- } +- +- btrfs_put_block_group(cache); +- total -= num_bytes; +- bytenr += num_bytes; +- } +- +- /* Modified block groups are accounted for in the delayed_refs_rsv. */ +- btrfs_update_delayed_refs_rsv(trans); +- return ret; +-} +- + static u64 first_logical_byte(struct btrfs_fs_info *fs_info, u64 search_start) + { + struct btrfs_block_group_cache *cache; +@@ -3406,75 +3290,6 @@ btrfs_inc_block_group_reservations(struc + atomic_inc(&bg->reservations); + } + +-/** +- * btrfs_add_reserved_bytes - update the block_group and space info counters +- * @cache: The cache we are manipulating +- * @ram_bytes: The number of bytes of file content, and will be same to +- * @num_bytes except for the compress path. +- * @num_bytes: The number of bytes in question +- * @delalloc: The blocks are allocated for the delalloc write +- * +- * This is called by the allocator when it reserves space. If this is a +- * reservation and the block group has become read only we cannot make the +- * reservation and return -EAGAIN, otherwise this function always succeeds. +- */ +-int btrfs_add_reserved_bytes(struct btrfs_block_group_cache *cache, +- u64 ram_bytes, u64 num_bytes, int delalloc) +-{ +- struct btrfs_space_info *space_info = cache->space_info; +- int ret = 0; +- +- spin_lock(&space_info->lock); +- spin_lock(&cache->lock); +- if (cache->ro) { +- ret = -EAGAIN; +- } else { +- cache->reserved += num_bytes; +- space_info->bytes_reserved += num_bytes; +- +- trace_btrfs_space_reservation(cache->fs_info, +- "space_info", space_info->flags, +- ram_bytes, 0); +- btrfs_space_info_update_bytes_may_use(cache->fs_info, +- space_info, -ram_bytes); +- if (delalloc) +- cache->delalloc_bytes += num_bytes; +- } +- spin_unlock(&cache->lock); +- spin_unlock(&space_info->lock); +- return ret; +-} +- +-/** +- * btrfs_free_reserved_bytes - update the block_group and space info counters +- * @cache: The cache we are manipulating +- * @num_bytes: The number of bytes in question +- * @delalloc: The blocks are allocated for the delalloc write +- * +- * This is called by somebody who is freeing space that was never actually used +- * on disk. For example if you reserve some space for a new leaf in transaction +- * A and before transaction A commits you free that leaf, you call this with +- * reserve set to 0 in order to clear the reservation. +- */ +- +-void btrfs_free_reserved_bytes(struct btrfs_block_group_cache *cache, +- u64 num_bytes, int delalloc) +-{ +- struct btrfs_space_info *space_info = cache->space_info; +- +- spin_lock(&space_info->lock); +- spin_lock(&cache->lock); +- if (cache->ro) +- space_info->bytes_readonly += num_bytes; +- cache->reserved -= num_bytes; +- space_info->bytes_reserved -= num_bytes; +- space_info->max_extent_size = 0; +- +- if (delalloc) +- cache->delalloc_bytes -= num_bytes; +- spin_unlock(&cache->lock); +- spin_unlock(&space_info->lock); +-} + void btrfs_prepare_extent_commit(struct btrfs_fs_info *fs_info) + { + struct btrfs_caching_control *next; +@@ -3958,7 +3773,7 @@ static int __btrfs_free_extent(struct bt + goto out; + } + +- ret = btrfs_update_block_group(trans, info, bytenr, num_bytes, 0); ++ ret = btrfs_update_block_group(trans, bytenr, num_bytes, 0); + if (ret) { + btrfs_abort_transaction(trans, ret); + goto out; +@@ -4882,7 +4697,7 @@ static int alloc_reserved_file_extent(st + if (ret) + return ret; + +- ret = btrfs_update_block_group(trans, fs_info, ins->objectid, ins->offset, 1); ++ ret = btrfs_update_block_group(trans, ins->objectid, ins->offset, 1); + if (ret) { /* -ENOENT, logic error */ + btrfs_err(fs_info, "update block group failed for %llu %llu", + ins->objectid, ins->offset); +@@ -4960,8 +4775,8 @@ static int alloc_reserved_tree_block(str + if (ret) + return ret; + +- ret = btrfs_update_block_group(trans, fs_info, ins->objectid, +- fs_info->nodesize, 1); ++ ret = btrfs_update_block_group(trans, ins->objectid, fs_info->nodesize, ++ 1); + if (ret) { /* -ENOENT, logic error */ + btrfs_err(fs_info, "update block group failed for %llu %llu", + ins->objectid, ins->offset); diff --git a/patches.suse/0019-btrfs-migrate-the-global_block_rsv-helpers-to-block-rsv-c.patch b/patches.suse/0019-btrfs-migrate-the-global_block_rsv-helpers-to-block-rsv-c.patch new file mode 100644 index 0000000..728b127 --- /dev/null +++ b/patches.suse/0019-btrfs-migrate-the-global_block_rsv-helpers-to-block-rsv-c.patch @@ -0,0 +1,493 @@ +From: Josef Bacik +Date: Wed, 19 Jun 2019 13:47:23 -0400 +Subject: btrfs: migrate the global_block_rsv helpers to block-rsv.c +Git-commit: 67f9c2209e885c8f97215655739155c94ca9cb9c +Patch-mainline: v5.3-rc1 +References: bsc#1165949 + +These helpers belong in block-rsv.c + +Signed-off-by: Josef Bacik +Signed-off-by: David Sterba +Acked-by: Nikolay Borisov +--- + fs/btrfs/block-rsv.c | 172 ++++++++++++++++++++++++++++++++++++++++++++ + fs/btrfs/block-rsv.h | 15 +++ + fs/btrfs/extent-tree.c | 189 +------------------------------------------------ + 3 files changed, 193 insertions(+), 183 deletions(-) + +--- a/fs/btrfs/block-rsv.c ++++ b/fs/btrfs/block-rsv.c +@@ -4,6 +4,7 @@ + #include "block-rsv.h" + #include "space-info.h" + #include "math.h" ++#include "transaction.h" + + static u64 block_rsv_release_bytes(struct btrfs_fs_info *fs_info, + struct btrfs_block_rsv *block_rsv, +@@ -251,3 +252,174 @@ int btrfs_cond_migrate_bytes(struct btrf + btrfs_block_rsv_add_bytes(dest, num_bytes, true); + return 0; + } ++ ++void btrfs_update_global_block_rsv(struct btrfs_fs_info *fs_info) ++{ ++ struct btrfs_block_rsv *block_rsv = &fs_info->global_block_rsv; ++ struct btrfs_space_info *sinfo = block_rsv->space_info; ++ u64 num_bytes; ++ ++ /* ++ * The global block rsv is based on the size of the extent tree, the ++ * checksum tree and the root tree. If the fs is empty we want to set ++ * it to a minimal amount for safety. ++ */ ++ num_bytes = btrfs_root_used(&fs_info->extent_root->root_item) + ++ btrfs_root_used(&fs_info->csum_root->root_item) + ++ btrfs_root_used(&fs_info->tree_root->root_item); ++ num_bytes = max_t(u64, num_bytes, SZ_16M); ++ ++ spin_lock(&sinfo->lock); ++ spin_lock(&block_rsv->lock); ++ ++ block_rsv->size = min_t(u64, num_bytes, SZ_512M); ++ ++ if (block_rsv->reserved < block_rsv->size) { ++ num_bytes = btrfs_space_info_used(sinfo, true); ++ if (sinfo->total_bytes > num_bytes) { ++ num_bytes = sinfo->total_bytes - num_bytes; ++ num_bytes = min(num_bytes, ++ block_rsv->size - block_rsv->reserved); ++ block_rsv->reserved += num_bytes; ++ btrfs_space_info_update_bytes_may_use(fs_info, sinfo, ++ num_bytes); ++ trace_btrfs_space_reservation(fs_info, "space_info", ++ sinfo->flags, num_bytes, ++ 1); ++ } ++ } else if (block_rsv->reserved > block_rsv->size) { ++ num_bytes = block_rsv->reserved - block_rsv->size; ++ btrfs_space_info_update_bytes_may_use(fs_info, sinfo, ++ -num_bytes); ++ trace_btrfs_space_reservation(fs_info, "space_info", ++ sinfo->flags, num_bytes, 0); ++ block_rsv->reserved = block_rsv->size; ++ } ++ ++ if (block_rsv->reserved == block_rsv->size) ++ block_rsv->full = 1; ++ else ++ block_rsv->full = 0; ++ ++ spin_unlock(&block_rsv->lock); ++ spin_unlock(&sinfo->lock); ++} ++ ++void btrfs_init_global_block_rsv(struct btrfs_fs_info *fs_info) ++{ ++ struct btrfs_space_info *space_info; ++ ++ space_info = btrfs_find_space_info(fs_info, BTRFS_BLOCK_GROUP_SYSTEM); ++ fs_info->chunk_block_rsv.space_info = space_info; ++ ++ space_info = btrfs_find_space_info(fs_info, BTRFS_BLOCK_GROUP_METADATA); ++ fs_info->global_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; ++ fs_info->delayed_refs_rsv.space_info = space_info; ++ ++ fs_info->extent_root->block_rsv = &fs_info->delayed_refs_rsv; ++ fs_info->csum_root->block_rsv = &fs_info->delayed_refs_rsv; ++ fs_info->dev_root->block_rsv = &fs_info->global_block_rsv; ++ fs_info->tree_root->block_rsv = &fs_info->global_block_rsv; ++ if (fs_info->quota_root) ++ fs_info->quota_root->block_rsv = &fs_info->global_block_rsv; ++ fs_info->chunk_root->block_rsv = &fs_info->chunk_block_rsv; ++ ++ btrfs_update_global_block_rsv(fs_info); ++} ++ ++void btrfs_release_global_block_rsv(struct btrfs_fs_info *fs_info) ++{ ++ btrfs_block_rsv_release(fs_info, &fs_info->global_block_rsv, (u64)-1); ++ 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); ++ WARN_ON(fs_info->chunk_block_rsv.reserved > 0); ++ WARN_ON(fs_info->delayed_block_rsv.size > 0); ++ WARN_ON(fs_info->delayed_block_rsv.reserved > 0); ++ WARN_ON(fs_info->delayed_refs_rsv.reserved > 0); ++ WARN_ON(fs_info->delayed_refs_rsv.size > 0); ++} ++ ++static struct btrfs_block_rsv *get_block_rsv( ++ const struct btrfs_trans_handle *trans, ++ const struct btrfs_root *root) ++{ ++ struct btrfs_fs_info *fs_info = root->fs_info; ++ struct btrfs_block_rsv *block_rsv = NULL; ++ ++ if (test_bit(BTRFS_ROOT_REF_COWS, &root->state) || ++ (root == fs_info->csum_root && trans->adding_csums) || ++ (root == fs_info->uuid_root)) ++ block_rsv = trans->block_rsv; ++ ++ if (!block_rsv) ++ block_rsv = root->block_rsv; ++ ++ if (!block_rsv) ++ block_rsv = &fs_info->empty_block_rsv; ++ ++ return block_rsv; ++} ++ ++struct btrfs_block_rsv *btrfs_use_block_rsv(struct btrfs_trans_handle *trans, ++ struct btrfs_root *root, ++ u32 blocksize) ++{ ++ struct btrfs_fs_info *fs_info = root->fs_info; ++ struct btrfs_block_rsv *block_rsv; ++ struct btrfs_block_rsv *global_rsv = &fs_info->global_block_rsv; ++ int ret; ++ bool global_updated = false; ++ ++ block_rsv = get_block_rsv(trans, root); ++ ++ if (unlikely(block_rsv->size == 0)) ++ goto try_reserve; ++again: ++ ret = btrfs_block_rsv_use_bytes(block_rsv, blocksize); ++ if (!ret) ++ return block_rsv; ++ ++ if (block_rsv->failfast) ++ return ERR_PTR(ret); ++ ++ if (block_rsv->type == BTRFS_BLOCK_RSV_GLOBAL && !global_updated) { ++ global_updated = true; ++ btrfs_update_global_block_rsv(fs_info); ++ goto again; ++ } ++ ++ /* ++ * The global reserve still exists to save us from ourselves, so don't ++ * warn_on if we are short on our delayed refs reserve. ++ */ ++ if (block_rsv->type != BTRFS_BLOCK_RSV_DELREFS && ++ btrfs_test_opt(fs_info, ENOSPC_DEBUG)) { ++ static DEFINE_RATELIMIT_STATE(_rs, ++ DEFAULT_RATELIMIT_INTERVAL * 10, ++ /*DEFAULT_RATELIMIT_BURST*/ 1); ++ if (__ratelimit(&_rs)) ++ WARN(1, KERN_DEBUG ++ "BTRFS: block rsv returned %d\n", ret); ++ } ++try_reserve: ++ ret = btrfs_reserve_metadata_bytes(root, block_rsv, blocksize, ++ BTRFS_RESERVE_NO_FLUSH); ++ if (!ret) ++ return block_rsv; ++ /* ++ * If we couldn't reserve metadata bytes try and use some from ++ * the global reserve if its space type is the same as the global ++ * reservation. ++ */ ++ if (block_rsv->type != BTRFS_BLOCK_RSV_GLOBAL && ++ block_rsv->space_info == global_rsv->space_info) { ++ ret = btrfs_block_rsv_use_bytes(global_rsv, blocksize); ++ if (!ret) ++ return global_rsv; ++ } ++ return ERR_PTR(ret); ++} +--- a/fs/btrfs/block-rsv.h ++++ b/fs/btrfs/block-rsv.h +@@ -3,6 +3,7 @@ + #ifndef BTRFS_BLOCK_RSV_H + #define BTRFS_BLOCK_RSV_H + ++struct btrfs_trans_handle; + enum btrfs_reserve_flush_enum; + + /* +@@ -75,6 +76,12 @@ void btrfs_block_rsv_add_bytes(struct bt + u64 __btrfs_block_rsv_release(struct btrfs_fs_info *fs_info, + struct btrfs_block_rsv *block_rsv, + u64 num_bytes, u64 *qgroup_to_release); ++void btrfs_update_global_block_rsv(struct btrfs_fs_info *fs_info); ++void btrfs_init_global_block_rsv(struct btrfs_fs_info *fs_info); ++void btrfs_release_global_block_rsv(struct btrfs_fs_info *fs_info); ++struct btrfs_block_rsv *btrfs_use_block_rsv(struct btrfs_trans_handle *trans, ++ struct btrfs_root *root, ++ u32 blocksize); + + static inline void btrfs_block_rsv_release(struct btrfs_fs_info *fs_info, + struct btrfs_block_rsv *block_rsv, +@@ -83,4 +90,12 @@ static inline void btrfs_block_rsv_relea + __btrfs_block_rsv_release(fs_info, block_rsv, num_bytes, NULL); + } + ++static inline void btrfs_unuse_block_rsv(struct btrfs_fs_info *fs_info, ++ struct btrfs_block_rsv *block_rsv, ++ u32 blocksize) ++{ ++ btrfs_block_rsv_add_bytes(block_rsv, blocksize, false); ++ btrfs_block_rsv_release(fs_info, block_rsv, 0); ++} ++ + #endif /* BTRFS_BLOCK_RSV_H */ +--- a/fs/btrfs/extent-tree.c ++++ b/fs/btrfs/extent-tree.c +@@ -4561,27 +4561,6 @@ out: + return ret; + } + +-static struct btrfs_block_rsv *get_block_rsv( +- const struct btrfs_trans_handle *trans, +- const struct btrfs_root *root) +-{ +- struct btrfs_fs_info *fs_info = root->fs_info; +- struct btrfs_block_rsv *block_rsv = NULL; +- +- if (test_bit(BTRFS_ROOT_REF_COWS, &root->state) || +- (root == fs_info->csum_root && trans->adding_csums) || +- (root == fs_info->uuid_root)) +- block_rsv = trans->block_rsv; +- +- if (!block_rsv) +- block_rsv = root->block_rsv; +- +- if (!block_rsv) +- block_rsv = &fs_info->empty_block_rsv; +- +- return block_rsv; +-} +- + /** + * btrfs_migrate_to_delayed_refs_rsv - transfer bytes to our delayed refs rsv. + * @fs_info - the fs info for our fs. +@@ -4722,95 +4701,6 @@ void btrfs_delayed_refs_rsv_release(stru + 0, released, 0); + } + +-static void update_global_block_rsv(struct btrfs_fs_info *fs_info) +-{ +- struct btrfs_block_rsv *block_rsv = &fs_info->global_block_rsv; +- struct btrfs_space_info *sinfo = block_rsv->space_info; +- u64 num_bytes; +- +- /* +- * The global block rsv is based on the size of the extent tree, the +- * checksum tree and the root tree. If the fs is empty we want to set +- * it to a minimal amount for safety. +- */ +- num_bytes = btrfs_root_used(&fs_info->extent_root->root_item) + +- btrfs_root_used(&fs_info->csum_root->root_item) + +- btrfs_root_used(&fs_info->tree_root->root_item); +- num_bytes = max_t(u64, num_bytes, SZ_16M); +- +- spin_lock(&sinfo->lock); +- spin_lock(&block_rsv->lock); +- +- block_rsv->size = min_t(u64, num_bytes, SZ_512M); +- +- if (block_rsv->reserved < block_rsv->size) { +- num_bytes = btrfs_space_info_used(sinfo, true); +- if (sinfo->total_bytes > num_bytes) { +- num_bytes = sinfo->total_bytes - num_bytes; +- num_bytes = min(num_bytes, +- block_rsv->size - block_rsv->reserved); +- block_rsv->reserved += num_bytes; +- btrfs_space_info_update_bytes_may_use(fs_info, sinfo, +- num_bytes); +- trace_btrfs_space_reservation(fs_info, "space_info", +- sinfo->flags, num_bytes, +- 1); +- } +- } else if (block_rsv->reserved > block_rsv->size) { +- num_bytes = block_rsv->reserved - block_rsv->size; +- btrfs_space_info_update_bytes_may_use(fs_info, sinfo, +- -num_bytes); +- trace_btrfs_space_reservation(fs_info, "space_info", +- sinfo->flags, num_bytes, 0); +- block_rsv->reserved = block_rsv->size; +- } +- +- if (block_rsv->reserved == block_rsv->size) +- block_rsv->full = 1; +- else +- block_rsv->full = 0; +- +- spin_unlock(&block_rsv->lock); +- spin_unlock(&sinfo->lock); +-} +- +-static void init_global_block_rsv(struct btrfs_fs_info *fs_info) +-{ +- struct btrfs_space_info *space_info; +- +- space_info = btrfs_find_space_info(fs_info, BTRFS_BLOCK_GROUP_SYSTEM); +- fs_info->chunk_block_rsv.space_info = space_info; +- +- space_info = btrfs_find_space_info(fs_info, BTRFS_BLOCK_GROUP_METADATA); +- fs_info->global_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; +- fs_info->delayed_refs_rsv.space_info = space_info; +- +- fs_info->extent_root->block_rsv = &fs_info->delayed_refs_rsv; +- fs_info->csum_root->block_rsv = &fs_info->delayed_refs_rsv; +- fs_info->dev_root->block_rsv = &fs_info->global_block_rsv; +- fs_info->tree_root->block_rsv = &fs_info->global_block_rsv; +- if (fs_info->quota_root) +- fs_info->quota_root->block_rsv = &fs_info->global_block_rsv; +- fs_info->chunk_root->block_rsv = &fs_info->chunk_block_rsv; +- +- update_global_block_rsv(fs_info); +-} +- +-static void release_global_block_rsv(struct btrfs_fs_info *fs_info) +-{ +- btrfs_block_rsv_release(fs_info, &fs_info->global_block_rsv, (u64)-1); +- 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); +- WARN_ON(fs_info->chunk_block_rsv.reserved > 0); +- WARN_ON(fs_info->delayed_block_rsv.size > 0); +- WARN_ON(fs_info->delayed_block_rsv.reserved > 0); +- WARN_ON(fs_info->delayed_refs_rsv.reserved > 0); +- WARN_ON(fs_info->delayed_refs_rsv.size > 0); +-} + + /* + * btrfs_update_delayed_refs_rsv - adjust the size of the delayed refs rsv +@@ -5614,7 +5504,7 @@ void btrfs_prepare_extent_commit(struct + + up_write(&fs_info->commit_root_sem); + +- update_global_block_rsv(fs_info); ++ btrfs_update_global_block_rsv(fs_info); + } + + /* +@@ -7236,73 +7126,6 @@ btrfs_init_new_buffer(struct btrfs_trans + return buf; + } + +-static struct btrfs_block_rsv * +-use_block_rsv(struct btrfs_trans_handle *trans, +- struct btrfs_root *root, u32 blocksize) +-{ +- struct btrfs_fs_info *fs_info = root->fs_info; +- struct btrfs_block_rsv *block_rsv; +- struct btrfs_block_rsv *global_rsv = &fs_info->global_block_rsv; +- int ret; +- bool global_updated = false; +- +- block_rsv = get_block_rsv(trans, root); +- +- if (unlikely(block_rsv->size == 0)) +- goto try_reserve; +-again: +- ret = btrfs_block_rsv_use_bytes(block_rsv, blocksize); +- if (!ret) +- return block_rsv; +- +- if (block_rsv->failfast) +- return ERR_PTR(ret); +- +- if (block_rsv->type == BTRFS_BLOCK_RSV_GLOBAL && !global_updated) { +- global_updated = true; +- update_global_block_rsv(fs_info); +- goto again; +- } +- +- /* +- * The global reserve still exists to save us from ourselves, so don't +- * warn_on if we are short on our delayed refs reserve. +- */ +- if (block_rsv->type != BTRFS_BLOCK_RSV_DELREFS && +- btrfs_test_opt(fs_info, ENOSPC_DEBUG)) { +- static DEFINE_RATELIMIT_STATE(_rs, +- DEFAULT_RATELIMIT_INTERVAL * 10, +- /*DEFAULT_RATELIMIT_BURST*/ 1); +- if (__ratelimit(&_rs)) +- WARN(1, KERN_DEBUG +- "BTRFS: block rsv returned %d\n", ret); +- } +-try_reserve: +- ret = btrfs_reserve_metadata_bytes(root, block_rsv, blocksize, +- BTRFS_RESERVE_NO_FLUSH); +- if (!ret) +- return block_rsv; +- /* +- * If we couldn't reserve metadata bytes try and use some from +- * the global reserve if its space type is the same as the global +- * reservation. +- */ +- if (block_rsv->type != BTRFS_BLOCK_RSV_GLOBAL && +- block_rsv->space_info == global_rsv->space_info) { +- ret = btrfs_block_rsv_use_bytes(global_rsv, blocksize); +- if (!ret) +- return global_rsv; +- } +- return ERR_PTR(ret); +-} +- +-static void unuse_block_rsv(struct btrfs_fs_info *fs_info, +- struct btrfs_block_rsv *block_rsv, u32 blocksize) +-{ +- btrfs_block_rsv_add_bytes(block_rsv, blocksize, 0); +- btrfs_block_rsv_release(fs_info, block_rsv, 0); +-} +- + /* + * finds a free extent and does all the dirty work required for allocation + * returns the tree buffer or an ERR_PTR on error. +@@ -7335,7 +7158,7 @@ struct extent_buffer *btrfs_alloc_tree_b + } + #endif + +- block_rsv = use_block_rsv(trans, root, blocksize); ++ block_rsv = btrfs_use_block_rsv(trans, root, blocksize); + if (IS_ERR(block_rsv)) + return ERR_CAST(block_rsv); + +@@ -7391,7 +7214,7 @@ out_free_buf: + out_free_reserved: + btrfs_free_reserved_extent(fs_info, ins.objectid, ins.offset, 0); + out_unuse: +- unuse_block_rsv(fs_info, block_rsv, blocksize); ++ btrfs_unuse_block_rsv(fs_info, block_rsv, blocksize); + return ERR_PTR(ret); + } + +@@ -8890,7 +8713,7 @@ int btrfs_free_block_groups(struct btrfs + */ + synchronize_rcu(); + +- release_global_block_rsv(info); ++ btrfs_release_global_block_rsv(info); + + while (!list_empty(&info->space_info)) { + int i; +@@ -9254,7 +9077,7 @@ int btrfs_read_block_groups(struct btrfs + } + + btrfs_add_raid_kobjects(info); +- init_global_block_rsv(info); ++ btrfs_init_global_block_rsv(info); + ret = check_chunk_block_group_mappings(info); + error: + btrfs_free_path(path); +@@ -9369,7 +9192,7 @@ int btrfs_make_block_group(struct btrfs_ + trace_btrfs_add_block_group(fs_info, cache, 1); + btrfs_update_space_info(fs_info, cache->flags, size, bytes_used, + cache->bytes_super, &cache->space_info); +- update_global_block_rsv(fs_info); ++ btrfs_update_global_block_rsv(fs_info); + + link_block_group(cache); + diff --git a/patches.suse/0019-btrfs-use-btrfs_try_granting_tickets-in-update_global_rsv.patch b/patches.suse/0019-btrfs-use-btrfs_try_granting_tickets-in-update_global_rsv.patch new file mode 100644 index 0000000..5124895 --- /dev/null +++ b/patches.suse/0019-btrfs-use-btrfs_try_granting_tickets-in-update_global_rsv.patch @@ -0,0 +1,38 @@ +From: Josef Bacik +Date: Thu, 22 Aug 2019 15:19:02 -0400 +Subject: btrfs: use btrfs_try_granting_tickets in update_global_rsv +Git-commit: 426551f6866a369c045c77a16725f41a097fac99 +Patch-mainline: v5.4-rc1 +References: bsc#1165949 + +We have some annoying xfstests tests that will create a very small fs, +fill it up, delete it, and repeat to make sure everything works right. +This trips btrfs up sometimes because we may commit a transaction to +free space, but most of the free metadata space was being reserved by +the global reserve. So we commit and update the global reserve, but the +space is simply added to bytes_may_use directly, instead of trying to +add it to existing tickets. This results in ENOSPC when we really did +have space. Fix this by calling btrfs_try_granting_tickets once we add +back our excess space to wake any pending tickets. + +Reviewed-by: Nikolay Borisov +Signed-off-by: Josef Bacik +Signed-off-by: David Sterba +Acked-by: Nikolay Borisov +--- + fs/btrfs/block-rsv.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/fs/btrfs/block-rsv.c b/fs/btrfs/block-rsv.c +index bea66b499e6f..d07bd41a7c1e 100644 +--- a/fs/btrfs/block-rsv.c ++++ b/fs/btrfs/block-rsv.c +@@ -305,6 +305,7 @@ void btrfs_update_global_block_rsv(struct btrfs_fs_info *fs_info) + btrfs_space_info_update_bytes_may_use(fs_info, sinfo, + -num_bytes); + block_rsv->reserved = block_rsv->size; ++ btrfs_try_granting_tickets(fs_info, sinfo); + } + + if (block_rsv->reserved == block_rsv->size) + diff --git a/patches.suse/0019-md-bitmap-use-mddev_suspend-resume-instead-of-quiesc.patch b/patches.suse/0019-md-bitmap-use-mddev_suspend-resume-instead-of-quiesc.patch new file mode 100644 index 0000000..6349c92 --- /dev/null +++ b/patches.suse/0019-md-bitmap-use-mddev_suspend-resume-instead-of-quiesc.patch @@ -0,0 +1,67 @@ +From f8f83d8ffeb47041ff0937ecac6d10bcb388cd9f Mon Sep 17 00:00:00 2001 +From: Jack Wang +Date: Mon, 8 Oct 2018 17:24:03 +0200 +Subject: [PATCH] md/bitmap: use mddev_suspend/resume instead of ->quiesce() +Git-commit: f8f83d8ffeb47041ff0937ecac6d10bcb388cd9f +Patch-mainline: v4.20-rc1 +References: bsc#1166003 + +After 9e1cc0a54556 ("md: use mddev_suspend/resume instead of ->quiesce()") +We still have similar left in bitmap functions. + +Replace quiesce() with mddev_suspend/resume. + +Also move md_bitmap_create out of mddev_suspend. and move mddev_resume +after md_bitmap_destroy. as we did in set_bitmap_file. + +Signed-off-by: Jack Wang +Reviewed-by: Gioh Kim +Signed-off-by: Shaohua Li +Signed-off-by: Coly Li +--- + drivers/md/md-bitmap.c | 9 +++++---- + 1 file changed, 5 insertions(+), 4 deletions(-) + +diff --git a/drivers/md/md-bitmap.c b/drivers/md/md-bitmap.c +index 2fc8c113977f..1cd4f991792c 100644 +--- a/drivers/md/md-bitmap.c ++++ b/drivers/md/md-bitmap.c +@@ -2288,9 +2288,9 @@ location_store(struct mddev *mddev, const char *buf, size_t len) + goto out; + } + if (mddev->pers) { +- mddev->pers->quiesce(mddev, 1); ++ mddev_suspend(mddev); + md_bitmap_destroy(mddev); +- mddev->pers->quiesce(mddev, 0); ++ mddev_resume(mddev); + } + mddev->bitmap_info.offset = 0; + if (mddev->bitmap_info.file) { +@@ -2327,8 +2327,8 @@ location_store(struct mddev *mddev, const char *buf, size_t len) + mddev->bitmap_info.offset = offset; + if (mddev->pers) { + struct bitmap *bitmap; +- mddev->pers->quiesce(mddev, 1); + bitmap = md_bitmap_create(mddev, -1); ++ mddev_suspend(mddev); + if (IS_ERR(bitmap)) + rv = PTR_ERR(bitmap); + else { +@@ -2337,11 +2337,12 @@ location_store(struct mddev *mddev, const char *buf, size_t len) + if (rv) + mddev->bitmap_info.offset = 0; + } +- mddev->pers->quiesce(mddev, 0); + if (rv) { + md_bitmap_destroy(mddev); ++ mddev_resume(mddev); + goto out; + } ++ mddev_resume(mddev); + } + } + } +-- +2.25.0 + diff --git a/patches.suse/0020-btrfs-do-not-account-global-reserve-in-can_overcommit.patch b/patches.suse/0020-btrfs-do-not-account-global-reserve-in-can_overcommit.patch new file mode 100644 index 0000000..4e0b6e0 --- /dev/null +++ b/patches.suse/0020-btrfs-do-not-account-global-reserve-in-can_overcommit.patch @@ -0,0 +1,82 @@ +From: Josef Bacik +Date: Thu, 22 Aug 2019 15:19:03 -0400 +Subject: btrfs: do not account global reserve in can_overcommit +Git-commit: 0096420adb036b143d6c42ad7c02a945b3e1119c +Patch-mainline: v5.4-rc1 +References: bsc#1165949 + +We ran into a problem in production where a box with plenty of space was +getting wedged doing ENOSPC flushing. These boxes only had 20% of the +disk allocated, but their metadata space + global reserve was right at +the size of their metadata chunk. + +In this case can_overcommit should be allowing allocations without +problem, but there's logic in can_overcommit that doesn't allow us to +overcommit if there's not enough real space to satisfy the global +reserve. + +This is for historical reasons. Before there were only certain places +we could allocate chunks. We could go to commit the transaction and not +have enough space for our pending delayed refs and such and be unable to +allocate a new chunk. This would result in a abort because of ENOSPC. +This code was added to solve this problem. + +However since then we've gained the ability to always be able to +allocate a chunk. So we can easily overcommit in these cases without +risking a transaction abort because of ENOSPC. + +Also prior to now the global reserve really would be used because that's +the space we relied on for delayed refs. With delayed refs being +tracked separately we no longer have to worry about running out of +delayed refs space while committing. We are much less likely to +exhaust our global reserve space during transaction commit. + +Fix the can_overcommit code to simply see if our current usage + what we +want is less than our current free space plus whatever slack space we +have in the disk is. This solves the problem we were seeing in +production and keeps us from flushing as aggressively as we approach our +actual metadata size usage. + +Reviewed-by: Nikolay Borisov +Signed-off-by: Josef Bacik +Signed-off-by: David Sterba +Acked-by: Nikolay Borisov +--- + fs/btrfs/space-info.c | 18 +----------------- + 1 file changed, 1 insertion(+), 17 deletions(-) + +--- a/fs/btrfs/space-info.c ++++ b/fs/btrfs/space-info.c +@@ -187,9 +187,7 @@ static int can_overcommit(struct btrfs_r + enum btrfs_reserve_flush_enum flush) + { + struct btrfs_fs_info *fs_info = root->fs_info; +- struct btrfs_block_rsv *global_rsv = &fs_info->global_block_rsv; + u64 profile; +- u64 space_size; + u64 avail; + u64 used; + int factor; +@@ -203,21 +201,7 @@ static int can_overcommit(struct btrfs_r + else + profile = btrfs_system_alloc_profile(fs_info); + +- used = btrfs_space_info_used(space_info, false); +- +- /* +- * We only want to allow over committing if we have lots of actual space +- * free, but if we don't have enough space to handle the global reserve +- * space then we could end up having a real enospc problem when trying +- * to allocate a chunk or some other such important allocation. +- */ +- spin_lock(&global_rsv->lock); +- space_size = calc_global_rsv_need_space(global_rsv); +- spin_unlock(&global_rsv->lock); +- if (used + space_size >= space_info->total_bytes) +- return 0; +- +- used += space_info->bytes_may_use; ++ used = btrfs_space_info_used(space_info, true); + + spin_lock(&fs_info->free_chunk_lock); + avail = fs_info->free_chunk_space; diff --git a/patches.suse/0020-btrfs-don-t-call-btrfs_start_delalloc_roots-in-flushoncommit.patch b/patches.suse/0020-btrfs-don-t-call-btrfs_start_delalloc_roots-in-flushoncommit.patch new file mode 100644 index 0000000..e229de7 --- /dev/null +++ b/patches.suse/0020-btrfs-don-t-call-btrfs_start_delalloc_roots-in-flushoncommit.patch @@ -0,0 +1,46 @@ +From: Josef Bacik +Date: Thu, 19 Oct 2017 14:16:01 -0400 +Subject: btrfs: don't call btrfs_start_delalloc_roots in flushoncommit +Git-commit: ce8ea7cc6eb3139f4c730d647325e69354159b0f +Patch-mainline: v4.15-rc1 +References: bsc#1165949 + +We're holding the sb_start_intwrite lock at this point, and doing async +filemap_flush of the inodes will result in a deadlock if we freeze the +fs during this operation. This is because we could do a +btrfs_join_transaction() in the thread we are waiting on which would +block at sb_start_intwrite, and thus deadlock. Using +writeback_inodes_sb() side steps the problem by not introducing all of +these extra locking dependencies. + +Signed-off-by: Josef Bacik +Signed-off-by: David Sterba +Acked-by: Nikolay Borisov +--- + fs/btrfs/transaction.c | 11 ++++++++++- + 1 file changed, 10 insertions(+), 1 deletion(-) + +diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c +index 68c3e1c04bca..5a8c2649af2f 100644 +--- a/fs/btrfs/transaction.c ++++ b/fs/btrfs/transaction.c +@@ -1916,8 +1916,17 @@ static void cleanup_transaction(struct btrfs_trans_handle *trans, + + static inline int btrfs_start_delalloc_flush(struct btrfs_fs_info *fs_info) + { ++ /* ++ * We use writeback_inodes_sb here because if we used ++ * btrfs_start_delalloc_roots we would deadlock with fs freeze. ++ * Currently are holding the fs freeze lock, if we do an async flush ++ * we'll do btrfs_join_transaction() and deadlock because we need to ++ * wait for the fs freeze lock. Using the direct flushing we benefit ++ * from already being in a transaction and our join_transaction doesn't ++ * have to re-take the fs freeze lock. ++ */ + if (btrfs_test_opt(fs_info, FLUSHONCOMMIT)) +- return btrfs_start_delalloc_roots(fs_info, 1, -1); ++ writeback_inodes_sb(fs_info->sb, WB_REASON_SYNC); + return 0; + } + + diff --git a/patches.suse/0020-btrfs-migrate-the-chunk-allocation-code.patch b/patches.suse/0020-btrfs-migrate-the-chunk-allocation-code.patch new file mode 100644 index 0000000..4bf5265 --- /dev/null +++ b/patches.suse/0020-btrfs-migrate-the-chunk-allocation-code.patch @@ -0,0 +1,691 @@ +From: Josef Bacik +Date: Thu, 20 Jun 2019 15:38:04 -0400 +Subject: btrfs: migrate the chunk allocation code +Git-commit: 07730d87ac7872b54efa02da5d20b42fd6bb165a +Patch-mainline: v5.4-rc1 +References: bsc#1165949 + +This feels more at home in block-group.c than in extent-tree.c. + +Signed-off-by: Josef Bacik +Reviewed-by: David Sterba i +[ refresh ] +Signed-off-by: David Sterba +Acked-by: Nikolay Borisov +--- + fs/btrfs/block-group.c | 253 +++++++++++++++++++++++++++++++++++++++++++++- + fs/btrfs/block-group.h | 21 +++ + fs/btrfs/ctree.h | 26 ---- + fs/btrfs/delalloc-space.c | 1 + fs/btrfs/extent-tree.c | 250 --------------------------------------------- + fs/btrfs/relocation.c | 3 + fs/btrfs/volumes.c | 4 + 7 files changed, 277 insertions(+), 281 deletions(-) + +--- a/fs/btrfs/block-group.c ++++ b/fs/btrfs/block-group.c +@@ -12,6 +12,7 @@ + #include "sysfs.h" + #include "tree-log.h" + #include "delalloc-space.h" ++#include "math.h" + + void btrfs_get_block_group(struct btrfs_block_group_cache *cache) + { +@@ -1996,7 +1997,7 @@ out: + if (cache->flags & BTRFS_BLOCK_GROUP_SYSTEM) { + alloc_flags = update_block_group_flags(fs_info, cache->flags); + mutex_lock(&fs_info->chunk_mutex); +- check_system_chunk(trans, fs_info, alloc_flags); ++ check_system_chunk(trans, alloc_flags); + mutex_unlock(&fs_info->chunk_mutex); + } + mutex_unlock(&fs_info->ro_block_group_mutex); +@@ -2724,3 +2725,253 @@ void btrfs_free_reserved_bytes(struct bt + spin_unlock(&cache->lock); + spin_unlock(&space_info->lock); + } ++ ++static void force_metadata_allocation(struct btrfs_fs_info *info) ++{ ++ struct list_head *head = &info->space_info; ++ struct btrfs_space_info *found; ++ ++ rcu_read_lock(); ++ list_for_each_entry_rcu(found, head, list) { ++ if (found->flags & BTRFS_BLOCK_GROUP_METADATA) ++ found->force_alloc = CHUNK_ALLOC_FORCE; ++ } ++ rcu_read_unlock(); ++} ++ ++static int should_alloc_chunk(struct btrfs_fs_info *fs_info, ++ struct btrfs_space_info *sinfo, int force) ++{ ++ u64 num_bytes = sinfo->total_bytes - sinfo->bytes_readonly; ++ u64 num_allocated = sinfo->bytes_used + sinfo->bytes_reserved + sinfo->bytes_pinned; ++ u64 thresh; ++ ++ if (force == CHUNK_ALLOC_FORCE) ++ return 1; ++ ++ /* ++ * in limited mode, we want to have some free space up to ++ * about 1% of the FS size. ++ */ ++ if (force == CHUNK_ALLOC_LIMITED) { ++ thresh = btrfs_super_total_bytes(fs_info->super_copy); ++ thresh = max_t(u64, SZ_64M, div_factor_fine(thresh, 1)); ++ ++ if (num_bytes - num_allocated < thresh) ++ return 1; ++ } ++ ++ if (num_allocated + SZ_2M < div_factor(num_bytes, 8)) ++ return 0; ++ return 1; ++} ++ ++int btrfs_force_chunk_alloc(struct btrfs_trans_handle *trans, u64 type) ++{ ++ u64 alloc_flags = btrfs_get_alloc_profile(trans->fs_info, type); ++ ++ return btrfs_chunk_alloc(trans, alloc_flags, CHUNK_ALLOC_FORCE); ++} ++ ++/* ++ * If force is CHUNK_ALLOC_FORCE: ++ * - return 1 if it successfully allocates a chunk, ++ * - return errors including -ENOSPC otherwise. ++ * If force is NOT CHUNK_ALLOC_FORCE: ++ * - return 0 if it doesn't need to allocate a new chunk, ++ * - return 1 if it successfully allocates a chunk, ++ * - return errors including -ENOSPC otherwise. ++ */ ++int btrfs_chunk_alloc(struct btrfs_trans_handle *trans, u64 flags, ++ enum btrfs_chunk_alloc_enum force) ++{ ++ struct btrfs_fs_info *fs_info = trans->fs_info; ++ struct btrfs_space_info *space_info; ++ int wait_for_alloc = 0; ++ int ret = 0; ++ ++ /* Don't re-enter if we're already allocating a chunk */ ++ if (trans->allocating_chunk) ++ return -ENOSPC; ++ ++ space_info = btrfs_find_space_info(fs_info, flags); ++ ASSERT(space_info); ++ ++again: ++ spin_lock(&space_info->lock); ++ if (force < space_info->force_alloc) ++ force = space_info->force_alloc; ++ if (space_info->full) { ++ if (should_alloc_chunk(fs_info, space_info, force)) ++ ret = -ENOSPC; ++ else ++ ret = 0; ++ spin_unlock(&space_info->lock); ++ return ret; ++ } ++ ++ if (!should_alloc_chunk(fs_info, space_info, force)) { ++ spin_unlock(&space_info->lock); ++ return 0; ++ } else if (space_info->chunk_alloc) { ++ wait_for_alloc = 1; ++ } else { ++ space_info->chunk_alloc = 1; ++ } ++ ++ spin_unlock(&space_info->lock); ++ ++ mutex_lock(&fs_info->chunk_mutex); ++ ++ /* ++ * The chunk_mutex is held throughout the entirety of a chunk ++ * allocation, so once we've acquired the chunk_mutex we know that the ++ * other guy is done and we need to recheck and see if we should ++ * allocate. ++ */ ++ if (wait_for_alloc) { ++ mutex_unlock(&fs_info->chunk_mutex); ++ wait_for_alloc = 0; ++ goto again; ++ } ++ ++ trans->allocating_chunk = true; ++ ++ /* ++ * If we have mixed data/metadata chunks we want to make sure we keep ++ * allocating mixed chunks instead of individual chunks. ++ */ ++ if (btrfs_mixed_space_info(space_info)) ++ flags |= (BTRFS_BLOCK_GROUP_DATA | BTRFS_BLOCK_GROUP_METADATA); ++ ++ /* ++ * if we're doing a data chunk, go ahead and make sure that ++ * we keep a reasonable number of metadata chunks allocated in the ++ * FS as well. ++ */ ++ if (flags & BTRFS_BLOCK_GROUP_DATA && fs_info->metadata_ratio) { ++ fs_info->data_chunk_allocations++; ++ if (!(fs_info->data_chunk_allocations % ++ fs_info->metadata_ratio)) ++ force_metadata_allocation(fs_info); ++ } ++ ++ /* ++ * Check if we have enough space in SYSTEM chunk because we may need ++ * to update devices. ++ */ ++ check_system_chunk(trans, flags); ++ ++ ret = btrfs_alloc_chunk(trans, fs_info, flags); ++ trans->allocating_chunk = false; ++ ++ spin_lock(&space_info->lock); ++ if (ret < 0 && ret != -ENOSPC) ++ goto out; ++ if (ret) ++ space_info->full = 1; ++ else { ++ ret = 1; ++ space_info->max_extent_size = 0; ++ } ++ ++ space_info->force_alloc = CHUNK_ALLOC_NO_FORCE; ++out: ++ space_info->chunk_alloc = 0; ++ spin_unlock(&space_info->lock); ++ mutex_unlock(&fs_info->chunk_mutex); ++ /* ++ * When we allocate a new chunk we reserve space in the chunk block ++ * reserve to make sure we can COW nodes/leafs in the chunk tree or ++ * add new nodes/leafs to it if we end up needing to do it when ++ * inserting the chunk item and updating device items as part of the ++ * second phase of chunk allocation, performed by ++ * btrfs_finish_chunk_alloc(). So make sure we don't accumulate a ++ * large number of new block groups to create in our transaction ++ * handle's new_bgs list to avoid exhausting the chunk block reserve ++ * in extreme cases - like having a single transaction create many new ++ * block groups when starting to write out the free space caches of all ++ * the block groups that were made dirty during the lifetime of the ++ * transaction. ++ */ ++ if (trans->chunk_bytes_reserved >= (u64)SZ_2M) ++ btrfs_create_pending_block_groups(trans, fs_info); ++ ++ return ret; ++} ++ ++static u64 get_profile_num_devs(struct btrfs_fs_info *fs_info, u64 type) ++{ ++ u64 num_dev; ++ ++ if (type & (BTRFS_BLOCK_GROUP_RAID10 | ++ BTRFS_BLOCK_GROUP_RAID0 | ++ BTRFS_BLOCK_GROUP_RAID5 | ++ BTRFS_BLOCK_GROUP_RAID6)) ++ num_dev = fs_info->fs_devices->rw_devices; ++ else if (type & BTRFS_BLOCK_GROUP_RAID1) ++ num_dev = 2; ++ else ++ num_dev = 1; /* DUP or single */ ++ ++ return num_dev; ++} ++ ++/* ++ * If @is_allocation is true, reserve space in the system space info necessary ++ * for allocating a chunk, otherwise if it's false, reserve space necessary for ++ * removing a chunk. ++ */ ++void check_system_chunk(struct btrfs_trans_handle *trans, u64 type) ++{ ++ struct btrfs_fs_info *fs_info = trans->fs_info; ++ struct btrfs_space_info *info; ++ u64 left; ++ u64 thresh; ++ int ret = 0; ++ u64 num_devs; ++ ++ /* ++ * Needed because we can end up allocating a system chunk and for an ++ * atomic and race free space reservation in the chunk block reserve. ++ */ ++ lockdep_assert_held(&fs_info->chunk_mutex); ++ ++ info = btrfs_find_space_info(fs_info, BTRFS_BLOCK_GROUP_SYSTEM); ++ spin_lock(&info->lock); ++ left = info->total_bytes - btrfs_space_info_used(info, true); ++ spin_unlock(&info->lock); ++ ++ num_devs = get_profile_num_devs(fs_info, type); ++ ++ /* num_devs device items to update and 1 chunk item to add or remove */ ++ thresh = btrfs_calc_trunc_metadata_size(fs_info, num_devs) + ++ btrfs_calc_trans_metadata_size(fs_info, 1); ++ ++ if (left < thresh && btrfs_test_opt(fs_info, ENOSPC_DEBUG)) { ++ btrfs_info(fs_info, "left=%llu, need=%llu, flags=%llu", ++ left, thresh, type); ++ btrfs_dump_space_info(fs_info, info, 0, 0); ++ } ++ ++ if (left < thresh) { ++ u64 flags = btrfs_system_alloc_profile(fs_info); ++ ++ /* ++ * Ignore failure to create system chunk. We might end up not ++ * needing it, as we might not need to COW all nodes/leafs from ++ * the paths we visit in the chunk tree (they were already COWed ++ * or created in the current transaction for example). ++ */ ++ ret = btrfs_alloc_chunk(trans, fs_info, flags); ++ } ++ ++ if (!ret) { ++ ret = btrfs_block_rsv_add(fs_info->chunk_root, ++ &fs_info->chunk_block_rsv, ++ thresh, BTRFS_RESERVE_NO_FLUSH); ++ if (!ret) ++ trans->chunk_bytes_reserved += thresh; ++ } ++} ++ +--- a/fs/btrfs/block-group.h ++++ b/fs/btrfs/block-group.h +@@ -10,6 +10,23 @@ enum btrfs_disk_cache_state { + BTRFS_DC_SETUP, + }; + ++/* ++ * Control flags for do_chunk_alloc's force field CHUNK_ALLOC_NO_FORCE means to ++ * only allocate a chunk if we really need one. ++ * ++ * CHUNK_ALLOC_LIMITED means to only try and allocate one if we have very few ++ * chunks already allocated. This is used as part of the clustering code to ++ * help make sure we have a good pool of storage to cluster in, without filling ++ * the FS with empty chunks ++ * ++ * CHUNK_ALLOC_FORCE means it must try to allocate one ++ */ ++enum btrfs_chunk_alloc_enum { ++ CHUNK_ALLOC_NO_FORCE, ++ CHUNK_ALLOC_LIMITED, ++ CHUNK_ALLOC_FORCE, ++}; ++ + struct btrfs_caching_control { + struct list_head list; + struct mutex mutex; +@@ -201,6 +218,10 @@ int btrfs_add_reserved_bytes(struct btrf + u64 ram_bytes, u64 num_bytes, int delalloc); + void btrfs_free_reserved_bytes(struct btrfs_block_group_cache *cache, + u64 num_bytes, int delalloc); ++int btrfs_chunk_alloc(struct btrfs_trans_handle *trans, u64 flags, ++ enum btrfs_chunk_alloc_enum force); ++int btrfs_force_chunk_alloc(struct btrfs_trans_handle *trans, u64 type); ++void check_system_chunk(struct btrfs_trans_handle *trans, const u64 type); + + static inline int btrfs_block_group_cache_done( + struct btrfs_block_group_cache *cache) +--- a/fs/btrfs/ctree.h ++++ b/fs/btrfs/ctree.h +@@ -2557,28 +2557,6 @@ enum btrfs_flush_state { + COMMIT_TRANS = 9, + }; + +-/* +- * control flags for do_chunk_alloc's force field +- * CHUNK_ALLOC_NO_FORCE means to only allocate a chunk +- * if we really need one. +- * +- * CHUNK_ALLOC_LIMITED means to only try and allocate one +- * if we have very few chunks already allocated. This is +- * used as part of the clustering code to help make sure +- * we have a good pool of storage to cluster in, without +- * filling the FS with empty chunks +- * +- * CHUNK_ALLOC_FORCE means it must try to allocate one +- * +- */ +-enum btrfs_chunk_alloc_enum { +- CHUNK_ALLOC_NO_FORCE, +- CHUNK_ALLOC_LIMITED, +- CHUNK_ALLOC_FORCE, +-}; +- +-int btrfs_chunk_alloc(struct btrfs_trans_handle *trans, u64 flags, +- enum btrfs_chunk_alloc_enum force); + void btrfs_trans_release_metadata(struct btrfs_trans_handle *trans, + struct btrfs_fs_info *fs_info); + int btrfs_subvolume_reserve_metadata(struct btrfs_root *root, +@@ -2597,8 +2575,6 @@ int btrfs_error_unpin_extent_range(struc + u64 start, u64 end); + int btrfs_discard_extent(struct btrfs_fs_info *fs_info, u64 bytenr, + u64 num_bytes, u64 *actual_bytes); +-int btrfs_force_chunk_alloc(struct btrfs_trans_handle *trans, +- struct btrfs_fs_info *fs_info, u64 type); + int btrfs_trim_fs(struct btrfs_fs_info *fs_info, struct fstrim_range *range); + + int btrfs_init_space_info(struct btrfs_fs_info *fs_info); +@@ -2608,8 +2584,6 @@ int __get_raid_index(u64 flags); + int btrfs_start_write_no_snapshoting(struct btrfs_root *root); + void btrfs_end_write_no_snapshoting(struct btrfs_root *root); + void btrfs_wait_for_snapshot_creation(struct btrfs_root *root); +-void check_system_chunk(struct btrfs_trans_handle *trans, +- struct btrfs_fs_info *fs_info, const u64 type); + /* ctree.c */ + int btrfs_bin_search(struct extent_buffer *eb, const struct btrfs_key *key, + int level, int *slot); +--- a/fs/btrfs/delalloc-space.c ++++ b/fs/btrfs/delalloc-space.c +@@ -7,6 +7,7 @@ + #include "space-info.h" + #include "transaction.h" + #include "qgroup.h" ++#include "block-group.h" + + int btrfs_alloc_data_chunk_ondemand(struct btrfs_inode *inode, u64 bytes) + { +--- a/fs/btrfs/extent-tree.c ++++ b/fs/btrfs/extent-tree.c +@@ -2854,248 +2854,6 @@ u64 btrfs_system_alloc_profile(struct bt + return btrfs_get_alloc_profile(fs_info, BTRFS_BLOCK_GROUP_SYSTEM); + } + +-static void force_metadata_allocation(struct btrfs_fs_info *info) +-{ +- struct list_head *head = &info->space_info; +- struct btrfs_space_info *found; +- +- rcu_read_lock(); +- list_for_each_entry_rcu(found, head, list) { +- if (found->flags & BTRFS_BLOCK_GROUP_METADATA) +- found->force_alloc = CHUNK_ALLOC_FORCE; +- } +- rcu_read_unlock(); +-} +- +-static int should_alloc_chunk(struct btrfs_fs_info *fs_info, +- struct btrfs_space_info *sinfo, int force) +-{ +- u64 num_bytes = sinfo->total_bytes - sinfo->bytes_readonly; +- u64 num_allocated = sinfo->bytes_used + sinfo->bytes_reserved + sinfo->bytes_pinned; +- u64 thresh; +- +- if (force == CHUNK_ALLOC_FORCE) +- return 1; +- +- /* +- * in limited mode, we want to have some free space up to +- * about 1% of the FS size. +- */ +- if (force == CHUNK_ALLOC_LIMITED) { +- thresh = btrfs_super_total_bytes(fs_info->super_copy); +- thresh = max_t(u64, SZ_64M, div_factor_fine(thresh, 1)); +- +- if (num_bytes - num_allocated < thresh) +- return 1; +- } +- +- if (num_allocated + SZ_2M < div_factor(num_bytes, 8)) +- return 0; +- return 1; +-} +- +-static u64 get_profile_num_devs(struct btrfs_fs_info *fs_info, u64 type) +-{ +- u64 num_dev; +- +- if (type & (BTRFS_BLOCK_GROUP_RAID10 | +- BTRFS_BLOCK_GROUP_RAID0 | +- BTRFS_BLOCK_GROUP_RAID5 | +- BTRFS_BLOCK_GROUP_RAID6)) +- num_dev = fs_info->fs_devices->rw_devices; +- else if (type & BTRFS_BLOCK_GROUP_RAID1) +- num_dev = 2; +- else +- num_dev = 1; /* DUP or single */ +- +- return num_dev; +-} +- +-/* +- * If @is_allocation is true, reserve space in the system space info necessary +- * for allocating a chunk, otherwise if it's false, reserve space necessary for +- * removing a chunk. +- */ +-void check_system_chunk(struct btrfs_trans_handle *trans, +- struct btrfs_fs_info *fs_info, u64 type) +-{ +- struct btrfs_space_info *info; +- u64 left; +- u64 thresh; +- int ret = 0; +- u64 num_devs; +- +- /* +- * Needed because we can end up allocating a system chunk and for an +- * atomic and race free space reservation in the chunk block reserve. +- */ +- ASSERT(mutex_is_locked(&fs_info->chunk_mutex)); +- +- info = btrfs_find_space_info(fs_info, BTRFS_BLOCK_GROUP_SYSTEM); +- spin_lock(&info->lock); +- left = info->total_bytes - btrfs_space_info_used(info, true); +- spin_unlock(&info->lock); +- +- num_devs = get_profile_num_devs(fs_info, type); +- +- /* num_devs device items to update and 1 chunk item to add or remove */ +- thresh = btrfs_calc_trunc_metadata_size(fs_info, num_devs) + +- btrfs_calc_trans_metadata_size(fs_info, 1); +- +- if (left < thresh && btrfs_test_opt(fs_info, ENOSPC_DEBUG)) { +- btrfs_info(fs_info, "left=%llu, need=%llu, flags=%llu", +- left, thresh, type); +- btrfs_dump_space_info(fs_info, info, 0, 0); +- } +- +- if (left < thresh) { +- u64 flags = btrfs_system_alloc_profile(fs_info); +- +- /* +- * Ignore failure to create system chunk. We might end up not +- * needing it, as we might not need to COW all nodes/leafs from +- * the paths we visit in the chunk tree (they were already COWed +- * or created in the current transaction for example). +- */ +- ret = btrfs_alloc_chunk(trans, fs_info, flags); +- } +- +- if (!ret) { +- ret = btrfs_block_rsv_add(fs_info->chunk_root, +- &fs_info->chunk_block_rsv, +- thresh, BTRFS_RESERVE_NO_FLUSH); +- if (!ret) +- trans->chunk_bytes_reserved += thresh; +- } +-} +- +-/* +- * If force is CHUNK_ALLOC_FORCE: +- * - return 1 if it successfully allocates a chunk, +- * - return errors including -ENOSPC otherwise. +- * If force is NOT CHUNK_ALLOC_FORCE: +- * - return 0 if it doesn't need to allocate a new chunk, +- * - return 1 if it successfully allocates a chunk, +- * - return errors including -ENOSPC otherwise. +- */ +-int btrfs_chunk_alloc(struct btrfs_trans_handle *trans, u64 flags, +- enum btrfs_chunk_alloc_enum force) +-{ +- struct btrfs_fs_info *fs_info = trans->fs_info; +- struct btrfs_space_info *space_info; +- int wait_for_alloc = 0; +- int ret = 0; +- +- /* Don't re-enter if we're already allocating a chunk */ +- if (trans->allocating_chunk) +- return -ENOSPC; +- +- space_info = btrfs_find_space_info(fs_info, flags); +- ASSERT(space_info); +- +-again: +- spin_lock(&space_info->lock); +- if (force < space_info->force_alloc) +- force = space_info->force_alloc; +- if (space_info->full) { +- if (should_alloc_chunk(fs_info, space_info, force)) +- ret = -ENOSPC; +- else +- ret = 0; +- spin_unlock(&space_info->lock); +- return ret; +- } +- +- if (!should_alloc_chunk(fs_info, space_info, force)) { +- spin_unlock(&space_info->lock); +- return 0; +- } else if (space_info->chunk_alloc) { +- wait_for_alloc = 1; +- } else { +- space_info->chunk_alloc = 1; +- } +- +- spin_unlock(&space_info->lock); +- +- mutex_lock(&fs_info->chunk_mutex); +- +- /* +- * The chunk_mutex is held throughout the entirety of a chunk +- * allocation, so once we've acquired the chunk_mutex we know that the +- * other guy is done and we need to recheck and see if we should +- * allocate. +- */ +- if (wait_for_alloc) { +- mutex_unlock(&fs_info->chunk_mutex); +- wait_for_alloc = 0; +- goto again; +- } +- +- trans->allocating_chunk = true; +- +- /* +- * If we have mixed data/metadata chunks we want to make sure we keep +- * allocating mixed chunks instead of individual chunks. +- */ +- if (btrfs_mixed_space_info(space_info)) +- flags |= (BTRFS_BLOCK_GROUP_DATA | BTRFS_BLOCK_GROUP_METADATA); +- +- /* +- * if we're doing a data chunk, go ahead and make sure that +- * we keep a reasonable number of metadata chunks allocated in the +- * FS as well. +- */ +- if (flags & BTRFS_BLOCK_GROUP_DATA && fs_info->metadata_ratio) { +- fs_info->data_chunk_allocations++; +- if (!(fs_info->data_chunk_allocations % +- fs_info->metadata_ratio)) +- force_metadata_allocation(fs_info); +- } +- +- /* +- * Check if we have enough space in SYSTEM chunk because we may need +- * to update devices. +- */ +- check_system_chunk(trans, fs_info, flags); +- +- ret = btrfs_alloc_chunk(trans, fs_info, flags); +- trans->allocating_chunk = false; +- +- spin_lock(&space_info->lock); +- if (ret < 0 && ret != -ENOSPC) +- goto out; +- if (ret) +- space_info->full = 1; +- else { +- ret = 1; +- space_info->max_extent_size = 0; +- } +- +- space_info->force_alloc = CHUNK_ALLOC_NO_FORCE; +-out: +- space_info->chunk_alloc = 0; +- spin_unlock(&space_info->lock); +- mutex_unlock(&fs_info->chunk_mutex); +- /* +- * When we allocate a new chunk we reserve space in the chunk block +- * reserve to make sure we can COW nodes/leafs in the chunk tree or +- * add new nodes/leafs to it if we end up needing to do it when +- * inserting the chunk item and updating device items as part of the +- * second phase of chunk allocation, performed by +- * btrfs_finish_chunk_alloc(). So make sure we don't accumulate a +- * large number of new block groups to create in our transaction +- * handle's new_bgs list to avoid exhausting the chunk block reserve +- * in extreme cases - like having a single transaction create many new +- * block groups when starting to write out the free space caches of all +- * the block groups that were made dirty during the lifetime of the +- * transaction. +- */ +- if (trans->chunk_bytes_reserved >= (u64)SZ_2M) +- btrfs_create_pending_block_groups(trans, fs_info); +- +- return ret; +-} +- + void btrfs_trans_release_metadata(struct btrfs_trans_handle *trans, + struct btrfs_fs_info *fs_info) + { +@@ -5903,14 +5661,6 @@ int btrfs_drop_subtree(struct btrfs_tran + return ret; + } + +-int btrfs_force_chunk_alloc(struct btrfs_trans_handle *trans, +- struct btrfs_fs_info *fs_info, u64 type) +-{ +- u64 alloc_flags = btrfs_get_alloc_profile(fs_info, type); +- +- return btrfs_chunk_alloc(trans, alloc_flags, CHUNK_ALLOC_FORCE); +-} +- + /* + * helper to account the unused space of all the readonly block group in the + * space_info. takes mirrors into account. +--- a/fs/btrfs/relocation.c ++++ b/fs/btrfs/relocation.c +@@ -4242,8 +4242,7 @@ restart: + } + } + if (trans && progress && err == -ENOSPC) { +- ret = btrfs_force_chunk_alloc(trans, fs_info, +- rc->block_group->flags); ++ ret = btrfs_force_chunk_alloc(trans, rc->block_group->flags); + if (ret == 1) { + err = 0; + progress = 0; +--- a/fs/btrfs/volumes.c ++++ b/fs/btrfs/volumes.c +@@ -2880,7 +2880,7 @@ int btrfs_remove_chunk(struct btrfs_tran + } + map = em->map_lookup; + mutex_lock(&fs_info->chunk_mutex); +- check_system_chunk(trans, fs_info, map->type); ++ check_system_chunk(trans, map->type); + mutex_unlock(&fs_info->chunk_mutex); + + /* +@@ -3113,7 +3113,7 @@ static int btrfs_may_alloc_data_chunk(st + if (IS_ERR(trans)) + return PTR_ERR(trans); + +- ret = btrfs_force_chunk_alloc(trans, fs_info, ++ ret = btrfs_force_chunk_alloc(trans, + BTRFS_BLOCK_GROUP_DATA); + btrfs_end_transaction(trans); + if (ret < 0) diff --git a/patches.suse/0020-btrfs-migrate-the-delayed-refs-rsv-code.patch b/patches.suse/0020-btrfs-migrate-the-delayed-refs-rsv-code.patch new file mode 100644 index 0000000..15b5d37 --- /dev/null +++ b/patches.suse/0020-btrfs-migrate-the-delayed-refs-rsv-code.patch @@ -0,0 +1,473 @@ +From: Josef Bacik +Date: Wed, 19 Jun 2019 15:11:58 -0400 +Subject: btrfs: migrate the delayed refs rsv code +Git-commit: 6ef03debdb3d82d7deec65f96e143b9adcfb2cd4 +Patch-mainline: v5.3-rc1 +References: bsc#1165949 + +These belong with the delayed refs related code, not in extent-tree.c. + +Signed-off-by: Josef Bacik +Signed-off-by: David Sterba +Acked-by: Nikolay Borisov +--- + fs/btrfs/ctree.h | 14 --- + fs/btrfs/delayed-ref.c | 174 +++++++++++++++++++++++++++++++++++++++++++++++++ + fs/btrfs/delayed-ref.h | 10 ++ + fs/btrfs/extent-tree.c | 174 ------------------------------------------------- + fs/btrfs/inode.c | 3 + 5 files changed, 187 insertions(+), 188 deletions(-) + +--- a/fs/btrfs/ctree.h ++++ b/fs/btrfs/ctree.h +@@ -2602,9 +2602,6 @@ static inline u64 btrfs_calc_trunc_metad + return (u64)fs_info->nodesize * BTRFS_MAX_LEVEL * num_items; + } + +-int btrfs_should_throttle_delayed_refs(struct btrfs_trans_handle *trans, +- struct btrfs_fs_info *fs_info); +-bool btrfs_check_space_for_delayed_refs(struct btrfs_fs_info *fs_info); + void btrfs_dec_block_group_reservations(struct btrfs_fs_info *fs_info, + const u64 start); + void btrfs_wait_block_group_reservations(struct btrfs_block_group_cache *bg); +@@ -2782,20 +2779,13 @@ void btrfs_delalloc_release_metadata(str + bool qgroup_free); + int btrfs_delalloc_reserve_space(struct inode *inode, + struct extent_changeset **reserved, u64 start, u64 len); +-void btrfs_delayed_refs_rsv_release(struct btrfs_fs_info *fs_info, int nr); +-void btrfs_update_delayed_refs_rsv(struct btrfs_trans_handle *trans); +-int btrfs_delayed_refs_rsv_refill(struct btrfs_fs_info *fs_info, +- enum btrfs_reserve_flush_enum flush); +-void btrfs_migrate_to_delayed_refs_rsv(struct btrfs_fs_info *fs_info, +- struct btrfs_block_rsv *src, +- u64 num_bytes); + int btrfs_inc_block_group_ro(struct btrfs_fs_info *fs_info, +- struct btrfs_block_group_cache *cache); ++ struct btrfs_block_group_cache *cache); + void btrfs_dec_block_group_ro(struct btrfs_block_group_cache *cache); + void btrfs_put_block_group_cache(struct btrfs_fs_info *info); + u64 btrfs_account_ro_block_groups_free_space(struct btrfs_space_info *sinfo); + int btrfs_error_unpin_extent_range(struct btrfs_fs_info *fs_info, +- u64 start, u64 end); ++ u64 start, u64 end); + int btrfs_discard_extent(struct btrfs_fs_info *fs_info, u64 bytenr, + u64 num_bytes, u64 *actual_bytes); + int btrfs_force_chunk_alloc(struct btrfs_trans_handle *trans, +--- a/fs/btrfs/delayed-ref.c ++++ b/fs/btrfs/delayed-ref.c +@@ -23,6 +23,7 @@ + #include "delayed-ref.h" + #include "transaction.h" + #include "qgroup.h" ++#include "space-info.h" + + struct kmem_cache *btrfs_delayed_ref_head_cachep; + struct kmem_cache *btrfs_delayed_tree_ref_cachep; +@@ -37,6 +38,179 @@ struct kmem_cache *btrfs_delayed_extent_ + * of hammering updates on the extent allocation tree. + */ + ++bool btrfs_check_space_for_delayed_refs(struct btrfs_fs_info *fs_info) ++{ ++ struct btrfs_block_rsv *delayed_refs_rsv = &fs_info->delayed_refs_rsv; ++ struct btrfs_block_rsv *global_rsv = &fs_info->global_block_rsv; ++ bool ret = false; ++ u64 reserved; ++ ++ spin_lock(&global_rsv->lock); ++ reserved = global_rsv->reserved; ++ spin_unlock(&global_rsv->lock); ++ ++ /* ++ * Since the global reserve is just kind of magic we don't really want ++ * to rely on it to save our bacon, so if our size is more than the ++ * delayed_refs_rsv and the global rsv then it's time to think about ++ * bailing. ++ */ ++ spin_lock(&delayed_refs_rsv->lock); ++ reserved += delayed_refs_rsv->reserved; ++ if (delayed_refs_rsv->size >= reserved) ++ ret = true; ++ spin_unlock(&delayed_refs_rsv->lock); ++ return ret; ++} ++ ++int btrfs_should_throttle_delayed_refs(struct btrfs_trans_handle *trans) ++{ ++ u64 num_entries = ++ atomic_read(&trans->transaction->delayed_refs.num_entries); ++ u64 avg_runtime; ++ u64 val; ++ ++ smp_mb(); ++ avg_runtime = trans->fs_info->avg_delayed_ref_runtime; ++ val = num_entries * avg_runtime; ++ if (val >= NSEC_PER_SEC) ++ return 1; ++ if (val >= NSEC_PER_SEC / 2) ++ return 2; ++ ++ return btrfs_check_space_for_delayed_refs(trans->fs_info); ++} ++ ++/** ++ * btrfs_delayed_refs_rsv_release - release a ref head's reservation. ++ * @fs_info - the fs_info for our fs. ++ * @nr - the number of items to drop. ++ * ++ * This drops the delayed ref head's count from the delayed refs rsv and frees ++ * any excess reservation we had. ++ */ ++void btrfs_delayed_refs_rsv_release(struct btrfs_fs_info *fs_info, int nr) ++{ ++ struct btrfs_block_rsv *block_rsv = &fs_info->delayed_refs_rsv; ++ u64 num_bytes = btrfs_calc_trans_metadata_size(fs_info, nr); ++ u64 released = 0; ++ ++ released = __btrfs_block_rsv_release(fs_info, block_rsv, num_bytes, ++ NULL); ++ if (released) ++ trace_btrfs_space_reservation(fs_info, "delayed_refs_rsv", ++ 0, released, 0); ++} ++ ++/* ++ * btrfs_update_delayed_refs_rsv - adjust the size of the delayed refs rsv ++ * @trans - the trans that may have generated delayed refs ++ * ++ * This is to be called anytime we may have adjusted trans->delayed_ref_updates, ++ * it'll calculate the additional size and add it to the delayed_refs_rsv. ++ */ ++void btrfs_update_delayed_refs_rsv(struct btrfs_trans_handle *trans) ++{ ++ struct btrfs_fs_info *fs_info = trans->fs_info; ++ struct btrfs_block_rsv *delayed_rsv = &fs_info->delayed_refs_rsv; ++ u64 num_bytes; ++ ++ if (!trans->delayed_ref_updates) ++ return; ++ ++ num_bytes = btrfs_calc_trans_metadata_size(fs_info, ++ trans->delayed_ref_updates); ++ spin_lock(&delayed_rsv->lock); ++ delayed_rsv->size += num_bytes; ++ delayed_rsv->full = 0; ++ spin_unlock(&delayed_rsv->lock); ++ trans->delayed_ref_updates = 0; ++} ++ ++/** ++ * btrfs_migrate_to_delayed_refs_rsv - transfer bytes to our delayed refs rsv. ++ * @fs_info - the fs info for our fs. ++ * @src - the source block rsv to transfer from. ++ * @num_bytes - the number of bytes to transfer. ++ * ++ * This transfers up to the num_bytes amount from the src rsv to the ++ * delayed_refs_rsv. Any extra bytes are returned to the space info. ++ */ ++void btrfs_migrate_to_delayed_refs_rsv(struct btrfs_fs_info *fs_info, ++ struct btrfs_block_rsv *src, ++ u64 num_bytes) ++{ ++ struct btrfs_block_rsv *delayed_refs_rsv = &fs_info->delayed_refs_rsv; ++ u64 to_free = 0; ++ ++ spin_lock(&src->lock); ++ src->reserved -= num_bytes; ++ src->size -= num_bytes; ++ spin_unlock(&src->lock); ++ ++ spin_lock(&delayed_refs_rsv->lock); ++ if (delayed_refs_rsv->size > delayed_refs_rsv->reserved) { ++ u64 delta = delayed_refs_rsv->size - ++ delayed_refs_rsv->reserved; ++ if (num_bytes > delta) { ++ to_free = num_bytes - delta; ++ num_bytes = delta; ++ } ++ } else { ++ to_free = num_bytes; ++ num_bytes = 0; ++ } ++ ++ if (num_bytes) ++ delayed_refs_rsv->reserved += num_bytes; ++ if (delayed_refs_rsv->reserved >= delayed_refs_rsv->size) ++ delayed_refs_rsv->full = 1; ++ spin_unlock(&delayed_refs_rsv->lock); ++ ++ if (num_bytes) ++ trace_btrfs_space_reservation(fs_info, "delayed_refs_rsv", ++ 0, num_bytes, 1); ++ if (to_free) ++ btrfs_space_info_add_old_bytes(fs_info, ++ delayed_refs_rsv->space_info, to_free); ++} ++ ++/** ++ * btrfs_delayed_refs_rsv_refill - refill based on our delayed refs usage. ++ * @fs_info - the fs_info for our fs. ++ * @flush - control how we can flush for this reservation. ++ * ++ * This will refill the delayed block_rsv up to 1 items size worth of space and ++ * will return -ENOSPC if we can't make the reservation. ++ */ ++int btrfs_delayed_refs_rsv_refill(struct btrfs_fs_info *fs_info, ++ enum btrfs_reserve_flush_enum flush) ++{ ++ struct btrfs_block_rsv *block_rsv = &fs_info->delayed_refs_rsv; ++ u64 limit = btrfs_calc_trans_metadata_size(fs_info, 1); ++ 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; ++ num_bytes = min(num_bytes, limit); ++ } ++ spin_unlock(&block_rsv->lock); ++ ++ if (!num_bytes) ++ return 0; ++ ++ ret = btrfs_reserve_metadata_bytes(fs_info->extent_root, block_rsv, ++ num_bytes, flush); ++ if (ret) ++ return ret; ++ btrfs_block_rsv_add_bytes(block_rsv, num_bytes, 0); ++ trace_btrfs_space_reservation(fs_info, "delayed_refs_rsv", ++ 0, num_bytes, 1); ++ return 0; ++} ++ + /* + * compare two delayed tree backrefs with same bytenr and type + */ +--- a/fs/btrfs/delayed-ref.h ++++ b/fs/btrfs/delayed-ref.h +@@ -381,6 +381,16 @@ int btrfs_check_delayed_seq(struct btrfs + struct btrfs_delayed_ref_root *delayed_refs, + u64 seq); + ++void btrfs_delayed_refs_rsv_release(struct btrfs_fs_info *fs_info, int nr); ++void btrfs_update_delayed_refs_rsv(struct btrfs_trans_handle *trans); ++int btrfs_delayed_refs_rsv_refill(struct btrfs_fs_info *fs_info, ++ enum btrfs_reserve_flush_enum flush); ++void btrfs_migrate_to_delayed_refs_rsv(struct btrfs_fs_info *fs_info, ++ struct btrfs_block_rsv *src, ++ u64 num_bytes); ++int btrfs_should_throttle_delayed_refs(struct btrfs_trans_handle *trans); ++bool btrfs_check_space_for_delayed_refs(struct btrfs_fs_info *fs_info); ++ + /* + * helper functions to cast a node into its container + */ +--- a/fs/btrfs/extent-tree.c ++++ b/fs/btrfs/extent-tree.c +@@ -2854,49 +2854,6 @@ u64 btrfs_csum_bytes_to_leaves(struct bt + return num_csums; + } + +-bool btrfs_check_space_for_delayed_refs(struct btrfs_fs_info *fs_info) +-{ +- struct btrfs_block_rsv *delayed_refs_rsv = &fs_info->delayed_refs_rsv; +- struct btrfs_block_rsv *global_rsv = &fs_info->global_block_rsv; +- bool ret = false; +- u64 reserved; +- +- spin_lock(&global_rsv->lock); +- reserved = global_rsv->reserved; +- spin_unlock(&global_rsv->lock); +- /* +- * Since the global reserve is just kind of magic we don't really want +- * to rely on it to save our bacon, so if our size is more than the +- * delayed_refs_rsv and the global rsv then it's time to think about +- * bailing. +- */ +- spin_lock(&delayed_refs_rsv->lock); +- reserved += delayed_refs_rsv->reserved; +- if (delayed_refs_rsv->size >= reserved) +- ret = true; +- spin_unlock(&delayed_refs_rsv->lock); +- return ret; +-} +- +-int btrfs_should_throttle_delayed_refs(struct btrfs_trans_handle *trans, +- struct btrfs_fs_info *fs_info) +-{ +- u64 num_entries = +- atomic_read(&trans->transaction->delayed_refs.num_entries); +- u64 avg_runtime; +- u64 val; +- +- smp_mb(); +- avg_runtime = fs_info->avg_delayed_ref_runtime; +- val = num_entries * avg_runtime; +- if (val >= NSEC_PER_SEC) +- return 1; +- if (val >= NSEC_PER_SEC / 2) +- return 2; +- +- return btrfs_check_space_for_delayed_refs(fs_info); +-} +- + struct async_delayed_refs { + struct btrfs_root *root; + u64 transid; +@@ -4562,90 +4519,6 @@ out: + } + + /** +- * btrfs_migrate_to_delayed_refs_rsv - transfer bytes to our delayed refs rsv. +- * @fs_info - the fs info for our fs. +- * @src - the source block rsv to transfer from. +- * @num_bytes - the number of bytes to transfer. +- * +- * This transfers up to the num_bytes amount from the src rsv to the +- * delayed_refs_rsv. Any extra bytes are returned to the space info. +- */ +-void btrfs_migrate_to_delayed_refs_rsv(struct btrfs_fs_info *fs_info, +- struct btrfs_block_rsv *src, +- u64 num_bytes) +-{ +- struct btrfs_block_rsv *delayed_refs_rsv = &fs_info->delayed_refs_rsv; +- u64 to_free = 0; +- +- spin_lock(&src->lock); +- src->reserved -= num_bytes; +- src->size -= num_bytes; +- spin_unlock(&src->lock); +- +- spin_lock(&delayed_refs_rsv->lock); +- if (delayed_refs_rsv->size > delayed_refs_rsv->reserved) { +- u64 delta = delayed_refs_rsv->size - +- delayed_refs_rsv->reserved; +- if (num_bytes > delta) { +- to_free = num_bytes - delta; +- num_bytes = delta; +- } +- } else { +- to_free = num_bytes; +- num_bytes = 0; +- } +- +- if (num_bytes) +- delayed_refs_rsv->reserved += num_bytes; +- if (delayed_refs_rsv->reserved >= delayed_refs_rsv->size) +- delayed_refs_rsv->full = 1; +- spin_unlock(&delayed_refs_rsv->lock); +- +- if (num_bytes) +- trace_btrfs_space_reservation(fs_info, "delayed_refs_rsv", +- 0, num_bytes, 1); +- if (to_free) +- btrfs_space_info_add_old_bytes(fs_info, +- delayed_refs_rsv->space_info, to_free); +-} +- +-/** +- * btrfs_delayed_refs_rsv_refill - refill based on our delayed refs usage. +- * @fs_info - the fs_info for our fs. +- * @flush - control how we can flush for this reservation. +- * +- * This will refill the delayed block_rsv up to 1 items size worth of space and +- * will return -ENOSPC if we can't make the reservation. +- */ +-int btrfs_delayed_refs_rsv_refill(struct btrfs_fs_info *fs_info, +- enum btrfs_reserve_flush_enum flush) +-{ +- struct btrfs_block_rsv *block_rsv = &fs_info->delayed_refs_rsv; +- u64 limit = btrfs_calc_trans_metadata_size(fs_info, 1); +- 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; +- num_bytes = min(num_bytes, limit); +- } +- spin_unlock(&block_rsv->lock); +- +- if (!num_bytes) +- return 0; +- +- ret = btrfs_reserve_metadata_bytes(fs_info->extent_root, block_rsv, +- num_bytes, flush); +- if (ret) +- return ret; +- btrfs_block_rsv_add_bytes(block_rsv, num_bytes, 0); +- trace_btrfs_space_reservation(fs_info, "delayed_refs_rsv", +- 0, num_bytes, 1); +- return 0; +-} +- +-/** + * btrfs_inode_rsv_release - release any excessive reservation. + * @inode - the inode we need to release from. + * @qgroup_free - free or convert qgroup meta. +@@ -4680,53 +4553,6 @@ void btrfs_inode_rsv_release(struct btrf + qgroup_to_release); + } + +-/** +- * btrfs_delayed_refs_rsv_release - release a ref head's reservation. +- * @fs_info - the fs_info for our fs. +- * @nr - the number of items to drop. +- * +- * This drops the delayed ref head's count from the delayed refs rsv and frees +- * any excess reservation we had. +- */ +-void btrfs_delayed_refs_rsv_release(struct btrfs_fs_info *fs_info, int nr) +-{ +- struct btrfs_block_rsv *block_rsv = &fs_info->delayed_refs_rsv; +- u64 num_bytes = btrfs_calc_trans_metadata_size(fs_info, nr); +- u64 released = 0; +- +- released = __btrfs_block_rsv_release(fs_info, block_rsv, num_bytes, +- NULL); +- if (released) +- trace_btrfs_space_reservation(fs_info, "delayed_refs_rsv", +- 0, released, 0); +-} +- +- +-/* +- * btrfs_update_delayed_refs_rsv - adjust the size of the delayed refs rsv +- * @trans - the trans that may have generated delayed refs +- * +- * This is to be called anytime we may have adjusted trans->delayed_ref_updates, +- * it'll calculate the additional size and add it to the delayed_refs_rsv. +- */ +-void btrfs_update_delayed_refs_rsv(struct btrfs_trans_handle *trans) +-{ +- struct btrfs_fs_info *fs_info = trans->fs_info; +- struct btrfs_block_rsv *delayed_rsv = &fs_info->delayed_refs_rsv; +- u64 num_bytes; +- +- if (!trans->delayed_ref_updates) +- return; +- +- num_bytes = btrfs_calc_trans_metadata_size(fs_info, +- trans->delayed_ref_updates); +- spin_lock(&delayed_rsv->lock); +- delayed_rsv->size += num_bytes; +- delayed_rsv->full = 0; +- spin_unlock(&delayed_rsv->lock); +- trans->delayed_ref_updates = 0; +-} +- + void btrfs_trans_release_metadata(struct btrfs_trans_handle *trans, + struct btrfs_fs_info *fs_info) + { +--- a/fs/btrfs/inode.c ++++ b/fs/btrfs/inode.c +@@ -4517,8 +4517,7 @@ delete: + break; + } + if (be_nice) { +- if (btrfs_should_throttle_delayed_refs(trans, +- fs_info)) ++ if (btrfs_should_throttle_delayed_refs(trans)) + should_throttle = 1; + } + } diff --git a/patches.suse/0020-md-cluster-raid10-resize-all-the-bitmaps-before-star.patch b/patches.suse/0020-md-cluster-raid10-resize-all-the-bitmaps-before-star.patch new file mode 100644 index 0000000..33527ed --- /dev/null +++ b/patches.suse/0020-md-cluster-raid10-resize-all-the-bitmaps-before-star.patch @@ -0,0 +1,224 @@ +From afd75628608337cf427a1f9ca0e46698a74f25d8 Mon Sep 17 00:00:00 2001 +From: Guoqing Jiang +Date: Thu, 18 Oct 2018 16:37:41 +0800 +Subject: [PATCH] md-cluster/raid10: resize all the bitmaps before start + reshape +Git-commit: afd75628608337cf427a1f9ca0e46698a74f25d8 +Patch-mainline: v4.20-rc1 +References: bsc#1166003 + +To support add disk under grow mode, we need to resize +all the bitmaps of each node before reshape, so that we +can ensure all nodes have the same view of the bitmap of +the clustered raid. + +So after the master node resized the bitmap, it broadcast +a message to other slave nodes, and it checks the size of +each bitmap are same or not by compare pages. We can only +continue the reshaping after all nodes update the bitmap +to the same size (by checking the pages), otherwise revert +bitmap size to previous value. + +The resize_bitmaps interface and BITMAP_RESIZE message are +introduced in md-cluster.c for the purpose. + +Reviewed-by: NeilBrown +Signed-off-by: Guoqing Jiang +Signed-off-by: Shaohua Li +Signed-off-by: Coly Li +--- + drivers/md/md-cluster.c | 81 +++++++++++++++++++++++++++++++++++++++++ + drivers/md/md-cluster.h | 1 + + drivers/md/raid10.c | 41 +++++++++++++++++++-- + 3 files changed, 120 insertions(+), 3 deletions(-) + +diff --git a/drivers/md/md-cluster.c b/drivers/md/md-cluster.c +index 0b2af6e74fc3..e223fae80da3 100644 +--- a/drivers/md/md-cluster.c ++++ b/drivers/md/md-cluster.c +@@ -105,6 +105,7 @@ enum msg_type { + RE_ADD, + BITMAP_NEEDS_SYNC, + CHANGE_CAPACITY, ++ BITMAP_RESIZE, + }; + + struct cluster_msg { +@@ -612,6 +613,11 @@ static int process_recvd_msg(struct mddev *mddev, struct cluster_msg *msg) + case BITMAP_NEEDS_SYNC: + __recover_slot(mddev, le32_to_cpu(msg->slot)); + break; ++ case BITMAP_RESIZE: ++ if (le64_to_cpu(msg->high) != mddev->pers->size(mddev, 0, 0)) ++ ret = md_bitmap_resize(mddev->bitmap, ++ le64_to_cpu(msg->high), 0, 0); ++ break; + default: + ret = -1; + pr_warn("%s:%d Received unknown message from %d\n", +@@ -1102,6 +1108,80 @@ static void metadata_update_cancel(struct mddev *mddev) + unlock_comm(cinfo); + } + ++static int update_bitmap_size(struct mddev *mddev, sector_t size) ++{ ++ struct md_cluster_info *cinfo = mddev->cluster_info; ++ struct cluster_msg cmsg = {0}; ++ int ret; ++ ++ cmsg.type = cpu_to_le32(BITMAP_RESIZE); ++ cmsg.high = cpu_to_le64(size); ++ ret = sendmsg(cinfo, &cmsg, 0); ++ if (ret) ++ pr_err("%s:%d: failed to send BITMAP_RESIZE message (%d)\n", ++ __func__, __LINE__, ret); ++ return ret; ++} ++ ++static int resize_bitmaps(struct mddev *mddev, sector_t newsize, sector_t oldsize) ++{ ++ struct bitmap_counts *counts; ++ char str[64]; ++ struct dlm_lock_resource *bm_lockres; ++ struct bitmap *bitmap = mddev->bitmap; ++ unsigned long my_pages = bitmap->counts.pages; ++ int i, rv; ++ ++ /* ++ * We need to ensure all the nodes can grow to a larger ++ * bitmap size before make the reshaping. ++ */ ++ rv = update_bitmap_size(mddev, newsize); ++ if (rv) ++ return rv; ++ ++ for (i = 0; i < mddev->bitmap_info.nodes; i++) { ++ if (i == md_cluster_ops->slot_number(mddev)) ++ continue; ++ ++ bitmap = get_bitmap_from_slot(mddev, i); ++ if (IS_ERR(bitmap)) { ++ pr_err("can't get bitmap from slot %d\n", i); ++ goto out; ++ } ++ counts = &bitmap->counts; ++ ++ /* ++ * If we can hold the bitmap lock of one node then ++ * the slot is not occupied, update the pages. ++ */ ++ snprintf(str, 64, "bitmap%04d", i); ++ bm_lockres = lockres_init(mddev, str, NULL, 1); ++ if (!bm_lockres) { ++ pr_err("Cannot initialize %s lock\n", str); ++ goto out; ++ } ++ bm_lockres->flags |= DLM_LKF_NOQUEUE; ++ rv = dlm_lock_sync(bm_lockres, DLM_LOCK_PW); ++ if (!rv) ++ counts->pages = my_pages; ++ lockres_free(bm_lockres); ++ ++ if (my_pages != counts->pages) ++ /* ++ * Let's revert the bitmap size if one node ++ * can't resize bitmap ++ */ ++ goto out; ++ } ++ ++ return 0; ++out: ++ md_bitmap_free(bitmap); ++ update_bitmap_size(mddev, oldsize); ++ return -1; ++} ++ + /* + * return 0 if all the bitmaps have the same sync_size + */ +@@ -1492,6 +1572,7 @@ static struct md_cluster_operations cluster_ops = { + .remove_disk = remove_disk, + .load_bitmaps = load_bitmaps, + .gather_bitmaps = gather_bitmaps, ++ .resize_bitmaps = resize_bitmaps, + .lock_all_bitmaps = lock_all_bitmaps, + .unlock_all_bitmaps = unlock_all_bitmaps, + .update_size = update_size, +diff --git a/drivers/md/md-cluster.h b/drivers/md/md-cluster.h +index c0240708f443..9bd753a6a94e 100644 +--- a/drivers/md/md-cluster.h ++++ b/drivers/md/md-cluster.h +@@ -26,6 +26,7 @@ struct md_cluster_operations { + int (*remove_disk)(struct mddev *mddev, struct md_rdev *rdev); + void (*load_bitmaps)(struct mddev *mddev, int total_slots); + int (*gather_bitmaps)(struct md_rdev *rdev); ++ int (*resize_bitmaps)(struct mddev *mddev, sector_t newsize, sector_t oldsize); + int (*lock_all_bitmaps)(struct mddev *mddev); + void (*unlock_all_bitmaps)(struct mddev *mddev); + void (*update_size)(struct mddev *mddev, sector_t old_dev_sectors); +diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c +index a52f43b151b5..72e52921c545 100644 +--- a/drivers/md/raid10.c ++++ b/drivers/md/raid10.c +@@ -25,6 +25,7 @@ + #include + #include + #include ++#include + #include + #include "md.h" + #include "raid10.h" +@@ -4288,12 +4289,46 @@ static int raid10_start_reshape(struct mddev *mddev) + spin_unlock_irq(&conf->device_lock); + + if (mddev->delta_disks && mddev->bitmap) { +- ret = md_bitmap_resize(mddev->bitmap, +- raid10_size(mddev, 0, conf->geo.raid_disks), +- 0, 0); ++ struct mdp_superblock_1 *sb = NULL; ++ sector_t oldsize, newsize; ++ ++ oldsize = raid10_size(mddev, 0, 0); ++ newsize = raid10_size(mddev, 0, conf->geo.raid_disks); ++ ++ if (!mddev_is_clustered(mddev)) { ++ ret = md_bitmap_resize(mddev->bitmap, newsize, 0, 0); ++ if (ret) ++ goto abort; ++ else ++ goto out; ++ } ++ ++ rdev_for_each(rdev, mddev) { ++ if (rdev->raid_disk > -1 && ++ !test_bit(Faulty, &rdev->flags)) ++ sb = page_address(rdev->sb_page); ++ } ++ ++ /* ++ * some node is already performing reshape, and no need to ++ * call md_bitmap_resize again since it should be called when ++ * receiving BITMAP_RESIZE msg ++ */ ++ if ((sb && (le32_to_cpu(sb->feature_map) & ++ MD_FEATURE_RESHAPE_ACTIVE)) || (oldsize == newsize)) ++ goto out; ++ ++ ret = md_bitmap_resize(mddev->bitmap, newsize, 0, 0); + if (ret) + goto abort; ++ ++ ret = md_cluster_ops->resize_bitmaps(mddev, newsize, oldsize); ++ if (ret) { ++ md_bitmap_resize(mddev->bitmap, oldsize, 0, 0); ++ goto abort; ++ } + } ++out: + if (mddev->delta_disks > 0) { + rdev_for_each(rdev, mddev) + if (rdev->raid_disk < 0 && +-- +2.25.0 + diff --git a/patches.suse/0021-btrfs-add-enospc-debug-messages-for-ticket-failure.patch b/patches.suse/0021-btrfs-add-enospc-debug-messages-for-ticket-failure.patch new file mode 100644 index 0000000..84aca14 --- /dev/null +++ b/patches.suse/0021-btrfs-add-enospc-debug-messages-for-ticket-failure.patch @@ -0,0 +1,94 @@ +From: Josef Bacik +Date: Thu, 22 Aug 2019 15:19:04 -0400 +Subject: btrfs: add enospc debug messages for ticket failure +Git-commit: 84fe47a4be931d506670a1f126c477f5c17d3a76 +Patch-mainline: v5.4-rc1 +References: bsc#1165949 + +When debugging weird enospc problems it's handy to be able to dump the +space info when we wake up all tickets, and see what the ticket values +are. This helped me figure out cases where we were enospc'ing when we +shouldn't have been. + +Reviewed-by: Nikolay Borisov +Signed-off-by: Josef Bacik +Signed-off-by: David Sterba +Acked-by: Nikolay Borisov +--- + fs/btrfs/space-info.c | 32 +++++++++++++++++++++++++------- + 1 file changed, 25 insertions(+), 7 deletions(-) + +diff --git a/fs/btrfs/space-info.c b/fs/btrfs/space-info.c +index 55f0c288b631..98dc092a905e 100644 +--- a/fs/btrfs/space-info.c ++++ b/fs/btrfs/space-info.c +@@ -258,14 +258,11 @@ do { \ + spin_unlock(&__rsv->lock); \ + } while (0) + +-void btrfs_dump_space_info(struct btrfs_fs_info *fs_info, +- struct btrfs_space_info *info, u64 bytes, +- int dump_block_groups) ++static void __btrfs_dump_space_info(struct btrfs_fs_info *fs_info, ++ struct btrfs_space_info *info) + { +- struct btrfs_block_group_cache *cache; +- int index = 0; ++ lockdep_assert_held(&info->lock); + +- spin_lock(&info->lock); + btrfs_info(fs_info, "space_info %llu has %llu free, is %sfull", + info->flags, + info->total_bytes - btrfs_space_info_used(info, true), +@@ -275,7 +272,6 @@ void btrfs_dump_space_info(struct btrfs_fs_info *fs_info, + info->total_bytes, info->bytes_used, info->bytes_pinned, + info->bytes_reserved, info->bytes_may_use, + info->bytes_readonly); +- spin_unlock(&info->lock); + + DUMP_BLOCK_RSV(fs_info, global_block_rsv); + DUMP_BLOCK_RSV(fs_info, trans_block_rsv); +@@ -283,6 +279,19 @@ void btrfs_dump_space_info(struct btrfs_fs_info *fs_info, + DUMP_BLOCK_RSV(fs_info, delayed_block_rsv); + DUMP_BLOCK_RSV(fs_info, delayed_refs_rsv); + ++} ++ ++void btrfs_dump_space_info(struct btrfs_fs_info *fs_info, ++ struct btrfs_space_info *info, u64 bytes, ++ int dump_block_groups) ++{ ++ struct btrfs_block_group_cache *cache; ++ int index = 0; ++ ++ spin_lock(&info->lock); ++ __btrfs_dump_space_info(fs_info, info); ++ spin_unlock(&info->lock); ++ + if (!dump_block_groups) + return; + +@@ -696,6 +705,11 @@ static bool maybe_fail_all_tickets(struct btrfs_fs_info *fs_info, + u64 tickets_id = space_info->tickets_id; + u64 first_ticket_bytes = 0; + ++ if (btrfs_test_opt(fs_info, ENOSPC_DEBUG)) { ++ btrfs_info(fs_info, "cannot satisfy tickets, dumping space info"); ++ __btrfs_dump_space_info(fs_info, space_info); ++ } ++ + while (!list_empty(&space_info->tickets) && + tickets_id == space_info->tickets_id) { + ticket = list_first_entry(&space_info->tickets, +@@ -716,6 +730,10 @@ static bool maybe_fail_all_tickets(struct btrfs_fs_info *fs_info, + else if (first_ticket_bytes > ticket->bytes) + return true; + ++ if (btrfs_test_opt(fs_info, ENOSPC_DEBUG)) ++ btrfs_info(fs_info, "failing ticket with %llu bytes", ++ ticket->bytes); ++ + list_del_init(&ticket->list); + ticket->error = -ENOSPC; + wake_up(&ticket->wait); + diff --git a/patches.suse/0021-btrfs-migrate-btrfs_trans_release_chunk_metadata.patch b/patches.suse/0021-btrfs-migrate-btrfs_trans_release_chunk_metadata.patch new file mode 100644 index 0000000..a937cb0 --- /dev/null +++ b/patches.suse/0021-btrfs-migrate-btrfs_trans_release_chunk_metadata.patch @@ -0,0 +1,92 @@ +From: Josef Bacik +Date: Wed, 19 Jun 2019 15:11:59 -0400 +Subject: btrfs: migrate btrfs_trans_release_chunk_metadata +Git-commit: fb6dea26601b60e41d70c310537dd1e2617b25b6 +Patch-mainline: v5.3-rc1 +References: bsc#1165949 + +Move this into transaction.c with the rest of the transaction related +code. + +Signed-off-by: Josef Bacik +Signed-off-by: David Sterba +Acked-by: Nikolay Borisov +--- + fs/btrfs/ctree.h | 1 - + fs/btrfs/extent-tree.c | 18 ------------------ + fs/btrfs/transaction.c | 18 ++++++++++++++++++ + fs/btrfs/transaction.h | 1 + + 4 files changed, 19 insertions(+), 19 deletions(-) + +--- a/fs/btrfs/ctree.h ++++ b/fs/btrfs/ctree.h +@@ -2764,7 +2764,6 @@ void btrfs_free_reserved_data_space_noqu + u64 len); + void btrfs_trans_release_metadata(struct btrfs_trans_handle *trans, + struct btrfs_fs_info *fs_info); +-void btrfs_trans_release_chunk_metadata(struct btrfs_trans_handle *trans); + int btrfs_subvolume_reserve_metadata(struct btrfs_root *root, + struct btrfs_block_rsv *rsv, + int nitems, +--- a/fs/btrfs/extent-tree.c ++++ b/fs/btrfs/extent-tree.c +@@ -4573,24 +4573,6 @@ void btrfs_trans_release_metadata(struct + } + + /* +- * To be called after all the new block groups attached to the transaction +- * handle have been created (btrfs_create_pending_block_groups()). +- */ +-void btrfs_trans_release_chunk_metadata(struct btrfs_trans_handle *trans) +-{ +- struct btrfs_fs_info *fs_info = trans->fs_info; +- +- if (!trans->chunk_bytes_reserved) +- return; +- +- WARN_ON_ONCE(!list_empty(&trans->new_bgs)); +- +- btrfs_block_rsv_release(fs_info, &fs_info->chunk_block_rsv, +- trans->chunk_bytes_reserved); +- trans->chunk_bytes_reserved = 0; +-} +- +-/* + * btrfs_subvolume_reserve_metadata() - reserve space for subvolume operation + * root: the root of the parent directory + * rsv: block reservation +--- a/fs/btrfs/transaction.c ++++ b/fs/btrfs/transaction.c +@@ -183,6 +183,24 @@ static inline int extwriter_counter_read + } + + /* ++ * To be called after all the new block groups attached to the transaction ++ * handle have been created (btrfs_create_pending_block_groups()). ++ */ ++void btrfs_trans_release_chunk_metadata(struct btrfs_trans_handle *trans) ++{ ++ struct btrfs_fs_info *fs_info = trans->fs_info; ++ ++ if (!trans->chunk_bytes_reserved) ++ return; ++ ++ WARN_ON_ONCE(!list_empty(&trans->new_bgs)); ++ ++ btrfs_block_rsv_release(fs_info, &fs_info->chunk_block_rsv, ++ trans->chunk_bytes_reserved); ++ trans->chunk_bytes_reserved = 0; ++} ++ ++/* + * either allocate a new transaction or hop into the existing one + */ + static noinline int join_transaction(struct btrfs_fs_info *fs_info, +--- a/fs/btrfs/transaction.h ++++ b/fs/btrfs/transaction.h +@@ -234,4 +234,5 @@ void btrfs_put_transaction(struct btrfs_ + void btrfs_apply_pending_changes(struct btrfs_fs_info *fs_info); + void btrfs_add_dropped_root(struct btrfs_trans_handle *trans, + struct btrfs_root *root); ++void btrfs_trans_release_chunk_metadata(struct btrfs_trans_handle *trans); + #endif diff --git a/patches.suse/0021-btrfs-migrate-the-alloc_profile-helpers.patch b/patches.suse/0021-btrfs-migrate-the-alloc_profile-helpers.patch new file mode 100644 index 0000000..8c7758e --- /dev/null +++ b/patches.suse/0021-btrfs-migrate-the-alloc_profile-helpers.patch @@ -0,0 +1,298 @@ +From: Josef Bacik +Date: Thu, 20 Jun 2019 15:38:05 -0400 +Subject: btrfs: migrate the alloc_profile helpers +Git-commit: 878d7b679491665997122d6599001538c639cca9 +Patch-mainline: v5.4-rc1 +References: bsc#1165949 + +These feel more at home in block-group.c. + +Signed-off-by: Josef Bacik +Reviewed-by: David Sterba +[ refresh, adjust btrfs_get_alloc_profile exports ] +Signed-off-by: David Sterba +Acked-by: Nikolay Borisov +--- + fs/btrfs/block-group.c | 100 ++++++++++++++++++++++++++++++++++++++++++ + fs/btrfs/block-group.h | 16 ++++++ + fs/btrfs/ctree.h | 4 - + fs/btrfs/extent-tree.c | 114 ------------------------------------------------- + 4 files changed, 116 insertions(+), 118 deletions(-) + +--- a/fs/btrfs/block-group.c ++++ b/fs/btrfs/block-group.c +@@ -14,6 +14,106 @@ + #include "delalloc-space.h" + #include "math.h" + ++/* ++ * Return target flags in extended format or 0 if restripe for this chunk_type ++ * is not in progress ++ * ++ * Should be called with balance_lock held ++ */ ++u64 btrfs_get_restripe_target(struct btrfs_fs_info *fs_info, u64 flags) ++{ ++ struct btrfs_balance_control *bctl = fs_info->balance_ctl; ++ u64 target = 0; ++ ++ if (!bctl) ++ return 0; ++ ++ if (flags & BTRFS_BLOCK_GROUP_DATA && ++ bctl->data.flags & BTRFS_BALANCE_ARGS_CONVERT) { ++ target = BTRFS_BLOCK_GROUP_DATA | bctl->data.target; ++ } else if (flags & BTRFS_BLOCK_GROUP_SYSTEM && ++ bctl->sys.flags & BTRFS_BALANCE_ARGS_CONVERT) { ++ target = BTRFS_BLOCK_GROUP_SYSTEM | bctl->sys.target; ++ } else if (flags & BTRFS_BLOCK_GROUP_METADATA && ++ bctl->meta.flags & BTRFS_BALANCE_ARGS_CONVERT) { ++ target = BTRFS_BLOCK_GROUP_METADATA | bctl->meta.target; ++ } ++ ++ return target; ++} ++ ++/* ++ * @flags: available profiles in extended format (see ctree.h) ++ * ++ * Returns reduced profile in chunk format. If profile changing is in ++ * progress (either running or paused) picks the target profile (if it's ++ * already available), otherwise falls back to plain reducing. ++ */ ++static u64 btrfs_reduce_alloc_profile(struct btrfs_fs_info *fs_info, u64 flags) ++{ ++ u64 num_devices = fs_info->fs_devices->rw_devices; ++ u64 target; ++ u64 raid_type; ++ u64 allowed = 0; ++ ++ /* ++ * see if restripe for this chunk_type is in progress, if so ++ * try to reduce to the target profile ++ */ ++ spin_lock(&fs_info->balance_lock); ++ target = btrfs_get_restripe_target(fs_info, flags); ++ if (target) { ++ /* pick target profile only if it's already available */ ++ if ((flags & target) & BTRFS_EXTENDED_PROFILE_MASK) { ++ spin_unlock(&fs_info->balance_lock); ++ return extended_to_chunk(target); ++ } ++ } ++ spin_unlock(&fs_info->balance_lock); ++ ++ /* First, mask out the RAID levels which aren't possible */ ++ for (raid_type = 0; raid_type < BTRFS_NR_RAID_TYPES; raid_type++) { ++ if (num_devices >= btrfs_raid_array[raid_type].devs_min) ++ allowed |= btrfs_raid_array[raid_type].bg_flag; ++ } ++ allowed &= flags; ++ ++ if (allowed & BTRFS_BLOCK_GROUP_RAID6) ++ allowed = BTRFS_BLOCK_GROUP_RAID6; ++ else if (allowed & BTRFS_BLOCK_GROUP_RAID5) ++ allowed = BTRFS_BLOCK_GROUP_RAID5; ++ else if (allowed & BTRFS_BLOCK_GROUP_RAID10) ++ allowed = BTRFS_BLOCK_GROUP_RAID10; ++ else if (allowed & BTRFS_BLOCK_GROUP_RAID1) ++ allowed = BTRFS_BLOCK_GROUP_RAID1; ++ else if (allowed & BTRFS_BLOCK_GROUP_RAID0) ++ allowed = BTRFS_BLOCK_GROUP_RAID0; ++ ++ flags &= ~BTRFS_BLOCK_GROUP_PROFILE_MASK; ++ ++ return extended_to_chunk(flags | allowed); ++} ++ ++u64 btrfs_get_alloc_profile(struct btrfs_fs_info *fs_info, u64 orig_flags) ++{ ++ unsigned seq; ++ u64 flags; ++ ++ do { ++ flags = orig_flags; ++ seq = read_seqbegin(&fs_info->profiles_lock); ++ ++ if (flags & BTRFS_BLOCK_GROUP_DATA) ++ flags |= fs_info->avail_data_alloc_bits; ++ else if (flags & BTRFS_BLOCK_GROUP_SYSTEM) ++ flags |= fs_info->avail_system_alloc_bits; ++ else if (flags & BTRFS_BLOCK_GROUP_METADATA) ++ flags |= fs_info->avail_metadata_alloc_bits; ++ } while (read_seqretry(&fs_info->profiles_lock, seq)); ++ ++ return btrfs_reduce_alloc_profile(fs_info, flags); ++} ++ + void btrfs_get_block_group(struct btrfs_block_group_cache *cache) + { + atomic_inc(&cache->count); +--- a/fs/btrfs/block-group.h ++++ b/fs/btrfs/block-group.h +@@ -222,6 +222,22 @@ int btrfs_chunk_alloc(struct btrfs_trans + enum btrfs_chunk_alloc_enum force); + int btrfs_force_chunk_alloc(struct btrfs_trans_handle *trans, u64 type); + void check_system_chunk(struct btrfs_trans_handle *trans, const u64 type); ++u64 btrfs_get_alloc_profile(struct btrfs_fs_info *fs_info, u64 orig_flags); ++ ++static inline u64 btrfs_data_alloc_profile(struct btrfs_fs_info *fs_info) ++{ ++ return btrfs_get_alloc_profile(fs_info, BTRFS_BLOCK_GROUP_DATA); ++} ++ ++static inline u64 btrfs_metadata_alloc_profile(struct btrfs_fs_info *fs_info) ++{ ++ return btrfs_get_alloc_profile(fs_info, BTRFS_BLOCK_GROUP_METADATA); ++} ++ ++static inline u64 btrfs_system_alloc_profile(struct btrfs_fs_info *fs_info) ++{ ++ return btrfs_get_alloc_profile(fs_info, BTRFS_BLOCK_GROUP_SYSTEM); ++} + + static inline int btrfs_block_group_cache_done( + struct btrfs_block_group_cache *cache) +--- a/fs/btrfs/ctree.h ++++ b/fs/btrfs/ctree.h +@@ -2528,10 +2528,6 @@ int btrfs_can_relocate(struct btrfs_fs_i + void btrfs_add_raid_kobjects(struct btrfs_fs_info *fs_info); + void btrfs_get_block_group_trimming(struct btrfs_block_group_cache *cache); + void btrfs_put_block_group_trimming(struct btrfs_block_group_cache *cache); +-u64 btrfs_data_alloc_profile(struct btrfs_fs_info *fs_info); +-u64 btrfs_metadata_alloc_profile(struct btrfs_fs_info *fs_info); +-u64 btrfs_system_alloc_profile(struct btrfs_fs_info *fs_info); +-u64 btrfs_get_alloc_profile(struct btrfs_fs_info *fs_info, u64 orig_flags); + void btrfs_clear_space_info_full(struct btrfs_fs_info *info); + + enum btrfs_reserve_flush_enum { +--- a/fs/btrfs/extent-tree.c ++++ b/fs/btrfs/extent-tree.c +@@ -2722,105 +2722,6 @@ int btrfs_extent_readonly(struct btrfs_f + return readonly; + } + +-/* +- * returns target flags in extended format or 0 if restripe for this +- * chunk_type is not in progress +- * +- * should be called with either volume_mutex or balance_lock held +- */ +-u64 btrfs_get_restripe_target(struct btrfs_fs_info *fs_info, u64 flags) +-{ +- struct btrfs_balance_control *bctl = fs_info->balance_ctl; +- u64 target = 0; +- +- if (!bctl) +- return 0; +- +- if (flags & BTRFS_BLOCK_GROUP_DATA && +- bctl->data.flags & BTRFS_BALANCE_ARGS_CONVERT) { +- target = BTRFS_BLOCK_GROUP_DATA | bctl->data.target; +- } else if (flags & BTRFS_BLOCK_GROUP_SYSTEM && +- bctl->sys.flags & BTRFS_BALANCE_ARGS_CONVERT) { +- target = BTRFS_BLOCK_GROUP_SYSTEM | bctl->sys.target; +- } else if (flags & BTRFS_BLOCK_GROUP_METADATA && +- bctl->meta.flags & BTRFS_BALANCE_ARGS_CONVERT) { +- target = BTRFS_BLOCK_GROUP_METADATA | bctl->meta.target; +- } +- +- return target; +-} +- +-/* +- * @flags: available profiles in extended format (see ctree.h) +- * +- * Returns reduced profile in chunk format. If profile changing is in +- * progress (either running or paused) picks the target profile (if it's +- * already available), otherwise falls back to plain reducing. +- */ +-static u64 btrfs_reduce_alloc_profile(struct btrfs_fs_info *fs_info, u64 flags) +-{ +- u64 num_devices = fs_info->fs_devices->rw_devices; +- u64 target; +- u64 raid_type; +- u64 allowed = 0; +- +- /* +- * see if restripe for this chunk_type is in progress, if so +- * try to reduce to the target profile +- */ +- spin_lock(&fs_info->balance_lock); +- target = btrfs_get_restripe_target(fs_info, flags); +- if (target) { +- /* pick target profile only if it's already available */ +- if ((flags & target) & BTRFS_EXTENDED_PROFILE_MASK) { +- spin_unlock(&fs_info->balance_lock); +- return extended_to_chunk(target); +- } +- } +- spin_unlock(&fs_info->balance_lock); +- +- /* First, mask out the RAID levels which aren't possible */ +- for (raid_type = 0; raid_type < BTRFS_NR_RAID_TYPES; raid_type++) { +- if (num_devices >= btrfs_raid_array[raid_type].devs_min) +- allowed |= btrfs_raid_array[raid_type].bg_flag; +- } +- allowed &= flags; +- +- if (allowed & BTRFS_BLOCK_GROUP_RAID6) +- allowed = BTRFS_BLOCK_GROUP_RAID6; +- else if (allowed & BTRFS_BLOCK_GROUP_RAID5) +- allowed = BTRFS_BLOCK_GROUP_RAID5; +- else if (allowed & BTRFS_BLOCK_GROUP_RAID10) +- allowed = BTRFS_BLOCK_GROUP_RAID10; +- else if (allowed & BTRFS_BLOCK_GROUP_RAID1) +- allowed = BTRFS_BLOCK_GROUP_RAID1; +- else if (allowed & BTRFS_BLOCK_GROUP_RAID0) +- allowed = BTRFS_BLOCK_GROUP_RAID0; +- +- flags &= ~BTRFS_BLOCK_GROUP_PROFILE_MASK; +- +- return extended_to_chunk(flags | allowed); +-} +- +-u64 btrfs_get_alloc_profile(struct btrfs_fs_info *fs_info, u64 orig_flags) +-{ +- unsigned seq; +- u64 flags; +- +- do { +- flags = orig_flags; +- seq = read_seqbegin(&fs_info->profiles_lock); +- +- if (flags & BTRFS_BLOCK_GROUP_DATA) +- flags |= fs_info->avail_data_alloc_bits; +- else if (flags & BTRFS_BLOCK_GROUP_SYSTEM) +- flags |= fs_info->avail_system_alloc_bits; +- else if (flags & BTRFS_BLOCK_GROUP_METADATA) +- flags |= fs_info->avail_metadata_alloc_bits; +- } while (read_seqretry(&fs_info->profiles_lock, seq)); +- +- return btrfs_reduce_alloc_profile(fs_info, flags); +-} + + static u64 get_alloc_profile_by_root(struct btrfs_root *root, int data) + { +@@ -2839,21 +2740,6 @@ static u64 get_alloc_profile_by_root(str + return ret; + } + +-u64 btrfs_data_alloc_profile(struct btrfs_fs_info *fs_info) +-{ +- return btrfs_get_alloc_profile(fs_info, BTRFS_BLOCK_GROUP_DATA); +-} +- +-u64 btrfs_metadata_alloc_profile(struct btrfs_fs_info *fs_info) +-{ +- return btrfs_get_alloc_profile(fs_info, BTRFS_BLOCK_GROUP_METADATA); +-} +- +-u64 btrfs_system_alloc_profile(struct btrfs_fs_info *fs_info) +-{ +- return btrfs_get_alloc_profile(fs_info, BTRFS_BLOCK_GROUP_SYSTEM); +-} +- + void btrfs_trans_release_metadata(struct btrfs_trans_handle *trans, + struct btrfs_fs_info *fs_info) + { diff --git a/patches.suse/0021-md-cluster-raid10-support-add-disk-under-grow-mode.patch b/patches.suse/0021-md-cluster-raid10-support-add-disk-under-grow-mode.patch new file mode 100644 index 0000000..985ff9b --- /dev/null +++ b/patches.suse/0021-md-cluster-raid10-support-add-disk-under-grow-mode.patch @@ -0,0 +1,157 @@ +From 7564beda19b3646d781934d04fc382b738053e6f Mon Sep 17 00:00:00 2001 +From: Guoqing Jiang +Date: Thu, 18 Oct 2018 16:37:42 +0800 +Subject: [PATCH] md-cluster/raid10: support add disk under grow mode +Git-commit: 7564beda19b3646d781934d04fc382b738053e6f +Patch-mainline: v4.20-rc1 +References: bsc#1166003 + +For clustered raid10 scenario, we need to let all the nodes +know about that a new disk is added to the array, and the +reshape caused by add new member just need to be happened in +one node, but other nodes should know about the change. + +Since reshape means read data from somewhere (which is already +used by array) and write data to unused region. Obviously, it +is awful if one node is reading data from address while another +node is writing to the same address. Considering we have +implemented suspend writes in the resyncing area, so we can +just broadcast the reading address to other nodes to avoid the +trouble. + +For master node, it would call reshape_request then update sb +during the reshape period. To avoid above trouble, we call +resync_info_update to send RESYNC message in reshape_request. + +Then from slave node's view, it receives two type messages: +1. RESYNCING message +Slave node add the address (where master node reading data from) +to suspend list. + +2. METADATA_UPDATED message +Once slave nodes know the reshaping is started in master node, +it is time to update reshape position and call start_reshape to +follow master node's step. After reshape is done, only reshape +position is need to be updated, so the majority task of reshaping +is happened on the master node. + +Reviewed-by: NeilBrown +Signed-off-by: Guoqing Jiang +Signed-off-by: Shaohua Li +Signed-off-by: Coly Li + +--- + drivers/md/md.c | 24 ++++++++++++++++++++++++ + drivers/md/md.h | 1 + + drivers/md/raid10.c | 34 ++++++++++++++++++++++++++++++++++ + 3 files changed, 59 insertions(+) + +diff --git a/drivers/md/md.c b/drivers/md/md.c +index 4c0f3e0331d5..e07096c4ff20 100644 +--- a/drivers/md/md.c ++++ b/drivers/md/md.c +@@ -9230,6 +9230,30 @@ static void check_sb_changes(struct mddev *mddev, struct md_rdev *rdev) + if (mddev->raid_disks != le32_to_cpu(sb->raid_disks)) + update_raid_disks(mddev, le32_to_cpu(sb->raid_disks)); + ++ /* ++ * Since mddev->delta_disks has already updated in update_raid_disks, ++ * so it is time to check reshape. ++ */ ++ if (test_bit(MD_RESYNCING_REMOTE, &mddev->recovery) && ++ (le32_to_cpu(sb->feature_map) & MD_FEATURE_RESHAPE_ACTIVE)) { ++ /* ++ * reshape is happening in the remote node, we need to ++ * update reshape_position and call start_reshape. ++ */ ++ mddev->reshape_position = sb->reshape_position; ++ if (mddev->pers->update_reshape_pos) ++ mddev->pers->update_reshape_pos(mddev); ++ if (mddev->pers->start_reshape) ++ mddev->pers->start_reshape(mddev); ++ } else if (test_bit(MD_RESYNCING_REMOTE, &mddev->recovery) && ++ mddev->reshape_position != MaxSector && ++ !(le32_to_cpu(sb->feature_map) & MD_FEATURE_RESHAPE_ACTIVE)) { ++ /* reshape is just done in another node. */ ++ mddev->reshape_position = MaxSector; ++ if (mddev->pers->update_reshape_pos) ++ mddev->pers->update_reshape_pos(mddev); ++ } ++ + /* Finally set the event to be up to date */ + mddev->events = le64_to_cpu(sb->events); + } +diff --git a/drivers/md/md.h b/drivers/md/md.h +index 8afd6bfdbfb9..c52afb52c776 100644 +--- a/drivers/md/md.h ++++ b/drivers/md/md.h +@@ -557,6 +557,7 @@ struct md_personality + int (*check_reshape) (struct mddev *mddev); + int (*start_reshape) (struct mddev *mddev); + void (*finish_reshape) (struct mddev *mddev); ++ void (*update_reshape_pos) (struct mddev *mddev); + /* quiesce suspends or resumes internal processing. + * 1 - stop new actions and wait for action io to complete + * 0 - return to normal behaviour +diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c +index 72e52921c545..1edd58a3098b 100644 +--- a/drivers/md/raid10.c ++++ b/drivers/md/raid10.c +@@ -4605,6 +4605,32 @@ static sector_t reshape_request(struct mddev *mddev, sector_t sector_nr, + r10_bio->master_bio = read_bio; + r10_bio->read_slot = r10_bio->devs[r10_bio->read_slot].devnum; + ++ /* ++ * Broadcast RESYNC message to other nodes, so all nodes would not ++ * write to the region to avoid conflict. ++ */ ++ if (mddev_is_clustered(mddev) && conf->cluster_sync_high <= sector_nr) { ++ struct mdp_superblock_1 *sb = NULL; ++ int sb_reshape_pos = 0; ++ ++ conf->cluster_sync_low = sector_nr; ++ conf->cluster_sync_high = sector_nr + CLUSTER_RESYNC_WINDOW_SECTORS; ++ sb = page_address(rdev->sb_page); ++ if (sb) { ++ sb_reshape_pos = le64_to_cpu(sb->reshape_position); ++ /* ++ * Set cluster_sync_low again if next address for array ++ * reshape is less than cluster_sync_low. Since we can't ++ * update cluster_sync_low until it has finished reshape. ++ */ ++ if (sb_reshape_pos < conf->cluster_sync_low) ++ conf->cluster_sync_low = sb_reshape_pos; ++ } ++ ++ md_cluster_ops->resync_info_update(mddev, conf->cluster_sync_low, ++ conf->cluster_sync_high); ++ } ++ + /* Now find the locations in the new layout */ + __raid10_find_phys(&conf->geo, r10_bio); + +@@ -4756,6 +4782,13 @@ static void end_reshape(struct r10conf *conf) + conf->fullsync = 0; + } + ++static void raid10_update_reshape_pos(struct mddev *mddev) ++{ ++ struct r10conf *conf = mddev->private; ++ ++ conf->reshape_progress = mddev->reshape_position; ++} ++ + static int handle_reshape_read_error(struct mddev *mddev, + struct r10bio *r10_bio) + { +@@ -4924,6 +4957,7 @@ static struct md_personality raid10_personality = + .check_reshape = raid10_check_reshape, + .start_reshape = raid10_start_reshape, + .finish_reshape = raid10_finish_reshape, ++ .update_reshape_pos = raid10_update_reshape_pos, + .congested = raid10_congested, + }; + +-- +2.25.0 + diff --git a/patches.suse/0022-btrfs-clear-space-cache-inode-generation-always.patch b/patches.suse/0022-btrfs-clear-space-cache-inode-generation-always.patch new file mode 100644 index 0000000..7ef8c46 --- /dev/null +++ b/patches.suse/0022-btrfs-clear-space-cache-inode-generation-always.patch @@ -0,0 +1,60 @@ +From: Josef Bacik +Date: Fri, 17 Nov 2017 14:50:46 -0500 +Subject: btrfs: clear space cache inode generation always +Git-commit: 8e138e0d92c6c9d3d481674fb14e3439b495be37 +Patch-mainline: v4.15-rc2 +References: bsc#1165949 + +We discovered a box that had double allocations, and suspected the space +cache may be to blame. While auditing the write out path I noticed that +if we've already setup the space cache we will just carry on. This +means that any error we hit after cache_save_setup before we go to +actually write the cache out we won't reset the inode generation, so +whatever was already written will be considered correct, except it'll be +stale. Fix this by _always_ resetting the generation on the block group +inode, this way we only ever have valid or invalid cache. + +With this patch I was no longer able to reproduce cache corruption with +dm-log-writes and my bpf error injection tool. + +Cc: stable@vger.kernel.org +Signed-off-by: Josef Bacik +Signed-off-by: David Sterba +Acked-by: Nikolay Borisov +--- + fs/btrfs/extent-tree.c | 14 +++++++------- + 1 file changed, 7 insertions(+), 7 deletions(-) + +diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c +index 673ac4e01dd0..784d41e95ed9 100644 +--- a/fs/btrfs/extent-tree.c ++++ b/fs/btrfs/extent-tree.c +@@ -3502,13 +3502,6 @@ static int cache_save_setup(struct btrfs_block_group_cache *block_group, + goto again; + } + +- /* We've already setup this transaction, go ahead and exit */ +- if (block_group->cache_generation == trans->transid && +- i_size_read(inode)) { +- dcs = BTRFS_DC_SETUP; +- goto out_put; +- } +- + /* + * We want to set the generation to 0, that way if anything goes wrong + * from here on out we know not to trust this cache when we load up next +@@ -3532,6 +3525,13 @@ static int cache_save_setup(struct btrfs_block_group_cache *block_group, + } + WARN_ON(ret); + ++ /* We've already setup this transaction, go ahead and exit */ ++ if (block_group->cache_generation == trans->transid && ++ i_size_read(inode)) { ++ dcs = BTRFS_DC_SETUP; ++ goto out_put; ++ } ++ + if (i_size_read(inode) > 0) { + ret = btrfs_check_trunc_cache_free_space(fs_info, + &fs_info->global_block_rsv); + diff --git a/patches.suse/0022-btrfs-migrate-the-block-group-cleanup-code.patch b/patches.suse/0022-btrfs-migrate-the-block-group-cleanup-code.patch new file mode 100644 index 0000000..7aa44a1 --- /dev/null +++ b/patches.suse/0022-btrfs-migrate-the-block-group-cleanup-code.patch @@ -0,0 +1,344 @@ +From: Josef Bacik +Date: Thu, 20 Jun 2019 15:38:06 -0400 +Subject: btrfs: migrate the block group cleanup code +Git-commit: 3e43c279e824889dacd5321505a88506e8c772e3 +Patch-mainline: v5.4-rc1 +References: bsc#1165949 + +This can now be easily migrated as well. + +Signed-off-by: Josef Bacik +Reviewed-by: David Sterba +[ refresh on top of sysfs cleanups ] +Signed-off-by: David Sterba +Acked-by: Nikolay Borisov +--- + fs/btrfs/block-group.c | 139 ++++++++++++++++++++++++++++++++++++++++++++++++ + fs/btrfs/block-group.h | 2 + fs/btrfs/ctree.h | 2 + fs/btrfs/extent-tree.c | 140 ------------------------------------------------- + 4 files changed, 141 insertions(+), 142 deletions(-) + +--- a/fs/btrfs/block-group.c ++++ b/fs/btrfs/block-group.c +@@ -3075,3 +3075,142 @@ void check_system_chunk(struct btrfs_tra + } + } + ++void btrfs_put_block_group_cache(struct btrfs_fs_info *info) ++{ ++ struct btrfs_block_group_cache *block_group; ++ u64 last = 0; ++ ++ while (1) { ++ struct inode *inode; ++ ++ block_group = btrfs_lookup_first_block_group(info, last); ++ while (block_group) { ++ btrfs_wait_block_group_cache_done(block_group); ++ spin_lock(&block_group->lock); ++ if (block_group->iref) ++ break; ++ spin_unlock(&block_group->lock); ++ block_group = btrfs_next_block_group(block_group); ++ } ++ if (!block_group) { ++ if (last == 0) ++ break; ++ last = 0; ++ continue; ++ } ++ ++ inode = block_group->inode; ++ block_group->iref = 0; ++ block_group->inode = NULL; ++ spin_unlock(&block_group->lock); ++ ASSERT(block_group->io_ctl.inode == NULL); ++ iput(inode); ++ last = block_group->key.objectid + block_group->key.offset; ++ btrfs_put_block_group(block_group); ++ } ++} ++ ++/* ++ * Must be called only after stopping all workers, since we could have block ++ * group caching kthreads running, and therefore they could race with us if we ++ * freed the block groups before stopping them. ++ */ ++int btrfs_free_block_groups(struct btrfs_fs_info *info) ++{ ++ struct btrfs_block_group_cache *block_group; ++ struct btrfs_space_info *space_info; ++ struct btrfs_caching_control *caching_ctl; ++ struct rb_node *n; ++ ++ down_write(&info->commit_root_sem); ++ while (!list_empty(&info->caching_block_groups)) { ++ caching_ctl = list_entry(info->caching_block_groups.next, ++ struct btrfs_caching_control, list); ++ list_del(&caching_ctl->list); ++ btrfs_put_caching_control(caching_ctl); ++ } ++ up_write(&info->commit_root_sem); ++ ++ spin_lock(&info->unused_bgs_lock); ++ while (!list_empty(&info->unused_bgs)) { ++ block_group = list_first_entry(&info->unused_bgs, ++ struct btrfs_block_group_cache, ++ bg_list); ++ list_del_init(&block_group->bg_list); ++ btrfs_put_block_group(block_group); ++ } ++ spin_unlock(&info->unused_bgs_lock); ++ ++ spin_lock(&info->block_group_cache_lock); ++ while ((n = rb_last(&info->block_group_cache_tree)) != NULL) { ++ block_group = rb_entry(n, struct btrfs_block_group_cache, ++ cache_node); ++ rb_erase(&block_group->cache_node, ++ &info->block_group_cache_tree); ++ RB_CLEAR_NODE(&block_group->cache_node); ++ spin_unlock(&info->block_group_cache_lock); ++ ++ down_write(&block_group->space_info->groups_sem); ++ list_del(&block_group->list); ++ up_write(&block_group->space_info->groups_sem); ++ ++ /* ++ * We haven't cached this block group, which means we could ++ * possibly have excluded extents on this block group. ++ */ ++ if (block_group->cached == BTRFS_CACHE_NO || ++ block_group->cached == BTRFS_CACHE_ERROR) ++ btrfs_free_excluded_extents(block_group); ++ ++ btrfs_remove_free_space_cache(block_group); ++ ASSERT(block_group->cached != BTRFS_CACHE_STARTED); ++ ASSERT(list_empty(&block_group->dirty_list)); ++ ASSERT(list_empty(&block_group->io_list)); ++ ASSERT(list_empty(&block_group->bg_list)); ++ ASSERT(atomic_read(&block_group->count) == 1); ++ btrfs_put_block_group(block_group); ++ ++ spin_lock(&info->block_group_cache_lock); ++ } ++ spin_unlock(&info->block_group_cache_lock); ++ ++ /* ++ * Now that all the block groups are freed, go through and free all the ++ * space_info structs. This is only called during the final stages of ++ * unmount, and so we know nobody is using them. We call ++ * synchronize_rcu() once before we start, just to be on the safe side. ++ */ ++ synchronize_rcu(); ++ ++ btrfs_release_global_block_rsv(info); ++ ++ while (!list_empty(&info->space_info)) { ++ int i; ++ ++ space_info = list_entry(info->space_info.next, ++ struct btrfs_space_info, ++ list); ++ ++ /* ++ * Do not hide this behind enospc_debug, this is actually ++ * important and indicates a real bug if this happens. ++ */ ++ if (WARN_ON(space_info->bytes_pinned > 0 || ++ space_info->bytes_reserved > 0 || ++ space_info->bytes_may_use > 0)) ++ btrfs_dump_space_info(info, space_info, 0, 0); ++ list_del(&space_info->list); ++ for (i = 0; i < BTRFS_NR_RAID_TYPES; i++) { ++ struct kobject *kobj; ++ kobj = space_info->block_group_kobjs[i]; ++ space_info->block_group_kobjs[i] = NULL; ++ if (kobj) { ++ kobject_del(kobj); ++ kobject_put(kobj); ++ } ++ } ++ kobject_del(&space_info->kobj); ++ kobject_put(&space_info->kobj); ++ } ++ return 0; ++} +--- a/fs/btrfs/block-group.h ++++ b/fs/btrfs/block-group.h +@@ -223,6 +223,8 @@ int btrfs_chunk_alloc(struct btrfs_trans + int btrfs_force_chunk_alloc(struct btrfs_trans_handle *trans, u64 type); + void check_system_chunk(struct btrfs_trans_handle *trans, const u64 type); + u64 btrfs_get_alloc_profile(struct btrfs_fs_info *fs_info, u64 orig_flags); ++void btrfs_put_block_group_cache(struct btrfs_fs_info *info); ++int btrfs_free_block_groups(struct btrfs_fs_info *info); + + static inline u64 btrfs_data_alloc_profile(struct btrfs_fs_info *fs_info) + { +--- a/fs/btrfs/ctree.h ++++ b/fs/btrfs/ctree.h +@@ -2523,7 +2523,6 @@ int btrfs_inc_extent_ref(struct btrfs_tr + struct btrfs_ref *generic_ref); + + int btrfs_extent_readonly(struct btrfs_fs_info *fs_info, u64 bytenr); +-int btrfs_free_block_groups(struct btrfs_fs_info *info); + int btrfs_can_relocate(struct btrfs_fs_info *fs_info, u64 bytenr); + void btrfs_add_raid_kobjects(struct btrfs_fs_info *fs_info); + void btrfs_get_block_group_trimming(struct btrfs_block_group_cache *cache); +@@ -2565,7 +2564,6 @@ void btrfs_delalloc_release_extents(stru + bool qgroup_free); + + int btrfs_delalloc_reserve_metadata(struct btrfs_inode *inode, u64 num_bytes); +-void btrfs_put_block_group_cache(struct btrfs_fs_info *info); + u64 btrfs_account_ro_block_groups_free_space(struct btrfs_space_info *sinfo); + int btrfs_error_unpin_extent_range(struct btrfs_fs_info *fs_info, + u64 start, u64 end); +--- a/fs/btrfs/extent-tree.c ++++ b/fs/btrfs/extent-tree.c +@@ -5733,146 +5733,6 @@ out: + return ret; + } + +-void btrfs_put_block_group_cache(struct btrfs_fs_info *info) +-{ +- struct btrfs_block_group_cache *block_group; +- u64 last = 0; +- +- while (1) { +- struct inode *inode; +- +- block_group = btrfs_lookup_first_block_group(info, last); +- while (block_group) { +- btrfs_wait_block_group_cache_done(block_group); +- spin_lock(&block_group->lock); +- if (block_group->iref) +- break; +- spin_unlock(&block_group->lock); +- block_group = btrfs_next_block_group(block_group); +- } +- if (!block_group) { +- if (last == 0) +- break; +- last = 0; +- continue; +- } +- +- inode = block_group->inode; +- block_group->iref = 0; +- block_group->inode = NULL; +- spin_unlock(&block_group->lock); +- ASSERT(block_group->io_ctl.inode == NULL); +- iput(inode); +- last = block_group->key.objectid + block_group->key.offset; +- btrfs_put_block_group(block_group); +- } +-} +- +-/* +- * Must be called only after stopping all workers, since we could have block +- * group caching kthreads running, and therefore they could race with us if we +- * freed the block groups before stopping them. +- */ +-int btrfs_free_block_groups(struct btrfs_fs_info *info) +-{ +- struct btrfs_block_group_cache *block_group; +- struct btrfs_space_info *space_info; +- struct btrfs_caching_control *caching_ctl; +- struct rb_node *n; +- +- down_write(&info->commit_root_sem); +- while (!list_empty(&info->caching_block_groups)) { +- caching_ctl = list_entry(info->caching_block_groups.next, +- struct btrfs_caching_control, list); +- list_del(&caching_ctl->list); +- btrfs_put_caching_control(caching_ctl); +- } +- up_write(&info->commit_root_sem); +- +- spin_lock(&info->unused_bgs_lock); +- while (!list_empty(&info->unused_bgs)) { +- block_group = list_first_entry(&info->unused_bgs, +- struct btrfs_block_group_cache, +- bg_list); +- list_del_init(&block_group->bg_list); +- btrfs_put_block_group(block_group); +- } +- spin_unlock(&info->unused_bgs_lock); +- +- spin_lock(&info->block_group_cache_lock); +- while ((n = rb_last(&info->block_group_cache_tree)) != NULL) { +- block_group = rb_entry(n, struct btrfs_block_group_cache, +- cache_node); +- rb_erase(&block_group->cache_node, +- &info->block_group_cache_tree); +- RB_CLEAR_NODE(&block_group->cache_node); +- spin_unlock(&info->block_group_cache_lock); +- +- down_write(&block_group->space_info->groups_sem); +- list_del(&block_group->list); +- up_write(&block_group->space_info->groups_sem); +- +- /* +- * We haven't cached this block group, which means we could +- * possibly have excluded extents on this block group. +- */ +- if (block_group->cached == BTRFS_CACHE_NO || +- block_group->cached == BTRFS_CACHE_ERROR) +- btrfs_free_excluded_extents(block_group); +- +- btrfs_remove_free_space_cache(block_group); +- ASSERT(block_group->cached != BTRFS_CACHE_STARTED); +- ASSERT(list_empty(&block_group->dirty_list)); +- ASSERT(list_empty(&block_group->io_list)); +- ASSERT(list_empty(&block_group->bg_list)); +- ASSERT(atomic_read(&block_group->count) == 1); +- btrfs_put_block_group(block_group); +- +- spin_lock(&info->block_group_cache_lock); +- } +- spin_unlock(&info->block_group_cache_lock); +- +- /* now that all the block groups are freed, go through and +- * free all the space_info structs. This is only called during +- * the final stages of unmount, and so we know nobody is +- * using them. We call synchronize_rcu() once before we start, +- * just to be on the safe side. +- */ +- synchronize_rcu(); +- +- btrfs_release_global_block_rsv(info); +- +- while (!list_empty(&info->space_info)) { +- int i; +- +- space_info = list_entry(info->space_info.next, +- struct btrfs_space_info, +- list); +- +- /* +- * Do not hide this behind enospc_debug, this is actually +- * important and indicates a real bug if this happens. +- */ +- if (WARN_ON(space_info->bytes_pinned > 0 || +- space_info->bytes_reserved > 0 || +- space_info->bytes_may_use > 0)) +- btrfs_dump_space_info(info, space_info, 0, 0); +- list_del(&space_info->list); +- for (i = 0; i < BTRFS_NR_RAID_TYPES; i++) { +- struct kobject *kobj; +- kobj = space_info->block_group_kobjs[i]; +- space_info->block_group_kobjs[i] = NULL; +- if (kobj) { +- kobject_del(kobj); +- kobject_put(kobj); +- } +- } +- kobject_del(&space_info->kobj); +- kobject_put(&space_info->kobj); +- } +- return 0; +-} +- + /* link_block_group will queue up kobjects to add when we're reclaim-safe */ + void btrfs_add_raid_kobjects(struct btrfs_fs_info *fs_info) + { diff --git a/patches.suse/0022-btrfs-migrate-the-delalloc-space-stuff-to-it-s-own-home.patch b/patches.suse/0022-btrfs-migrate-the-delalloc-space-stuff-to-it-s-own-home.patch new file mode 100644 index 0000000..32140e9 --- /dev/null +++ b/patches.suse/0022-btrfs-migrate-the-delalloc-space-stuff-to-it-s-own-home.patch @@ -0,0 +1,1187 @@ +From: Josef Bacik +Date: Wed, 19 Jun 2019 15:12:00 -0400 +Subject: btrfs: migrate the delalloc space stuff to it's own home +Git-commit: 867363429d706984915cb4b1f299ce05f8413e23 +Patch-mainline: v5.3-rc1 +References: bsc#1165949 + +We have code for data and metadata reservations for delalloc. There's +quite a bit of code here, and it's used in a lot of places so I've +separated it out to it's own file. inode.c and file.c are already +pretty large, and this code is complicated enough to live in its own +space. + +Signed-off-by: Josef Bacik +Signed-off-by: David Sterba +Acked-by: Nikolay Borisov +--- + fs/btrfs/Makefile | 2 + fs/btrfs/ctree.h | 14 - + fs/btrfs/delalloc-space.c | 493 ++++++++++++++++++++++++++++++++++++++++++++ + fs/btrfs/delalloc-space.h | 23 ++ + fs/btrfs/extent-tree.c | 493 -------------------------------------------- + fs/btrfs/file.c | 1 + fs/btrfs/free-space-cache.c | 1 + fs/btrfs/inode-map.c | 1 + fs/btrfs/inode.c | 1 + fs/btrfs/ioctl.c | 1 + fs/btrfs/ordered-data.c | 1 + fs/btrfs/relocation.c | 1 + 12 files changed, 525 insertions(+), 507 deletions(-) + +--- a/fs/btrfs/Makefile ++++ b/fs/btrfs/Makefile +@@ -10,7 +10,7 @@ btrfs-y += super.o ctree.o extent-tree.o + compression.o delayed-ref.o relocation.o delayed-inode.o scrub.o \ + reada.o backref.o ulist.o qgroup.o send.o dev-replace.o raid56.o \ + uuid-tree.o props.o hash.o free-space-tree.o tree-checker.o space-info.o \ +- block-rsv.o ++ block-rsv.o delalloc-space.o + + btrfs-$(CONFIG_BTRFS_FS_POSIX_ACL) += acl.o + btrfs-$(CONFIG_BTRFS_FS_CHECK_INTEGRITY) += check-integrity.o +--- a/fs/btrfs/ctree.h ++++ b/fs/btrfs/ctree.h +@@ -2754,16 +2754,6 @@ enum btrfs_chunk_alloc_enum { + + int btrfs_chunk_alloc(struct btrfs_trans_handle *trans, u64 flags, + enum btrfs_chunk_alloc_enum force); +-int btrfs_alloc_data_chunk_ondemand(struct btrfs_inode *inode, u64 bytes); +-int btrfs_check_data_free_space(struct inode *inode, +- struct extent_changeset **reserved, u64 start, u64 len); +-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, 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, + struct btrfs_fs_info *fs_info); + int btrfs_subvolume_reserve_metadata(struct btrfs_root *root, +@@ -2776,10 +2766,6 @@ void btrfs_delalloc_release_extents(stru + bool qgroup_free); + + int btrfs_delalloc_reserve_metadata(struct btrfs_inode *inode, u64 num_bytes); +-void btrfs_delalloc_release_metadata(struct btrfs_inode *inode, u64 num_bytes, +- bool qgroup_free); +-int btrfs_delalloc_reserve_space(struct inode *inode, +- struct extent_changeset **reserved, u64 start, u64 len); + int btrfs_inc_block_group_ro(struct btrfs_fs_info *fs_info, + struct btrfs_block_group_cache *cache); + void btrfs_dec_block_group_ro(struct btrfs_block_group_cache *cache); +--- /dev/null ++++ b/fs/btrfs/delalloc-space.c +@@ -0,0 +1,493 @@ ++// SPDX-License-Identifier: GPL-2.0 ++ ++#include "ctree.h" ++#include "delalloc-space.h" ++#include "block-rsv.h" ++#include "btrfs_inode.h" ++#include "space-info.h" ++#include "transaction.h" ++#include "qgroup.h" ++ ++int btrfs_alloc_data_chunk_ondemand(struct btrfs_inode *inode, u64 bytes) ++{ ++ struct btrfs_root *root = inode->root; ++ struct btrfs_fs_info *fs_info = root->fs_info; ++ struct btrfs_space_info *data_sinfo = fs_info->data_sinfo; ++ u64 used; ++ int ret = 0; ++ int need_commit = 2; ++ int have_pinned_space; ++ ++ /* Make sure bytes are sectorsize aligned */ ++ bytes = ALIGN(bytes, fs_info->sectorsize); ++ ++ if (btrfs_is_free_space_inode(inode)) { ++ need_commit = 0; ++ ASSERT(current->journal_info); ++ } ++ ++again: ++ /* Make sure we have enough space to handle the data first */ ++ spin_lock(&data_sinfo->lock); ++ used = btrfs_space_info_used(data_sinfo, true); ++ ++ if (used + bytes > data_sinfo->total_bytes) { ++ struct btrfs_trans_handle *trans; ++ ++ /* ++ * If we don't have enough free bytes in this space then we need ++ * to alloc a new chunk. ++ */ ++ if (!data_sinfo->full) { ++ u64 alloc_target; ++ ++ data_sinfo->force_alloc = CHUNK_ALLOC_FORCE; ++ spin_unlock(&data_sinfo->lock); ++ ++ alloc_target = btrfs_data_alloc_profile(fs_info); ++ /* ++ * It is ugly that we don't call nolock join ++ * transaction for the free space inode case here. ++ * But it is safe because we only do the data space ++ * reservation for the free space cache in the ++ * transaction context, the common join transaction ++ * just increase the counter of the current transaction ++ * handler, doesn't try to acquire the trans_lock of ++ * the fs. ++ */ ++ trans = btrfs_join_transaction(root); ++ if (IS_ERR(trans)) ++ return PTR_ERR(trans); ++ ++ ret = btrfs_chunk_alloc(trans, alloc_target, ++ CHUNK_ALLOC_NO_FORCE); ++ btrfs_end_transaction(trans); ++ if (ret < 0) { ++ if (ret != -ENOSPC) ++ return ret; ++ else { ++ have_pinned_space = 1; ++ goto commit_trans; ++ } ++ } ++ ++ goto again; ++ } ++ ++ /* ++ * If we don't have enough pinned space to deal with this ++ * allocation, and no removed chunk in current transaction, ++ * don't bother committing the transaction. ++ */ ++ have_pinned_space = percpu_counter_compare( ++ &data_sinfo->total_bytes_pinned, ++ used + bytes - data_sinfo->total_bytes); ++ spin_unlock(&data_sinfo->lock); ++ ++ /* Commit the current transaction and try again */ ++commit_trans: ++ if (need_commit && !atomic_read(&fs_info->open_ioctl_trans)) { ++ need_commit--; ++ ++ if (need_commit > 0) { ++ btrfs_start_delalloc_roots(fs_info, 0, -1); ++ btrfs_wait_ordered_roots(fs_info, U64_MAX, 0, ++ (u64)-1); ++ } ++ ++ trans = btrfs_join_transaction(root); ++ if (IS_ERR(trans)) ++ return PTR_ERR(trans); ++ if (have_pinned_space >= 0 || ++ test_bit(BTRFS_TRANS_HAVE_FREE_BGS, ++ &trans->transaction->flags) || ++ need_commit > 0) { ++ ret = btrfs_commit_transaction(trans); ++ if (ret) ++ return ret; ++ /* ++ * The cleaner kthread might still be doing iput ++ * operations. Wait for it to finish so that ++ * more space is released. We don't need to ++ * explicitly run the delayed iputs here because ++ * the commit_transaction would have woken up ++ * the cleaner. ++ */ ++ ret = btrfs_wait_on_delayed_iputs(fs_info); ++ if (ret) ++ return ret; ++ goto again; ++ } else { ++ btrfs_end_transaction(trans); ++ } ++ } ++ ++ trace_btrfs_space_reservation(fs_info, ++ "space_info:enospc", ++ data_sinfo->flags, bytes, 1); ++ return -ENOSPC; ++ } ++ btrfs_space_info_update_bytes_may_use(fs_info, data_sinfo, bytes); ++ trace_btrfs_space_reservation(fs_info, "space_info", ++ data_sinfo->flags, bytes, 1); ++ spin_unlock(&data_sinfo->lock); ++ ++ return ret; ++} ++ ++int btrfs_check_data_free_space(struct inode *inode, ++ struct extent_changeset **reserved, u64 start, u64 len) ++{ ++ struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb); ++ int ret; ++ ++ /* align the range */ ++ len = round_up(start + len, fs_info->sectorsize) - ++ round_down(start, fs_info->sectorsize); ++ start = round_down(start, fs_info->sectorsize); ++ ++ ret = btrfs_alloc_data_chunk_ondemand(BTRFS_I(inode), len); ++ if (ret < 0) ++ return ret; ++ ++ /* Use new btrfs_qgroup_reserve_data to reserve precious data space. */ ++ ret = btrfs_qgroup_reserve_data(inode, reserved, start, len); ++ if (ret < 0) ++ btrfs_free_reserved_data_space_noquota(inode, start, len); ++ else ++ ret = 0; ++ return ret; ++} ++ ++/* ++ * Called if we need to clear a data reservation for this inode ++ * Normally in a error case. ++ * ++ * This one will *NOT* use accurate qgroup reserved space API, just for case ++ * which we can't sleep and is sure it won't affect qgroup reserved space. ++ * Like clear_bit_hook(). ++ */ ++void btrfs_free_reserved_data_space_noquota(struct inode *inode, u64 start, ++ u64 len) ++{ ++ struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb); ++ struct btrfs_space_info *data_sinfo; ++ ++ /* Make sure the range is aligned to sectorsize */ ++ len = round_up(start + len, fs_info->sectorsize) - ++ round_down(start, fs_info->sectorsize); ++ start = round_down(start, fs_info->sectorsize); ++ ++ data_sinfo = fs_info->data_sinfo; ++ spin_lock(&data_sinfo->lock); ++ btrfs_space_info_update_bytes_may_use(fs_info, data_sinfo, -len); ++ trace_btrfs_space_reservation(fs_info, "space_info", ++ data_sinfo->flags, len, 0); ++ spin_unlock(&data_sinfo->lock); ++} ++ ++/* ++ * Called if we need to clear a data reservation for this inode ++ * Normally in a error case. ++ * ++ * This one will handle the per-inode data rsv map for accurate reserved ++ * space framework. ++ */ ++void btrfs_free_reserved_data_space(struct inode *inode, ++ struct extent_changeset *reserved, u64 start, u64 len) ++{ ++ struct btrfs_root *root = BTRFS_I(inode)->root; ++ ++ /* Make sure the range is aligned to sectorsize */ ++ len = round_up(start + len, root->fs_info->sectorsize) - ++ round_down(start, root->fs_info->sectorsize); ++ start = round_down(start, root->fs_info->sectorsize); ++ ++ btrfs_free_reserved_data_space_noquota(inode, start, len); ++ btrfs_qgroup_free_data(inode, reserved, start, len); ++} ++ ++/** ++ * 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. ++ */ ++static 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 *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 = __btrfs_block_rsv_release(fs_info, block_rsv, 0, ++ &qgroup_to_release); ++ if (released > 0) ++ trace_btrfs_space_reservation(fs_info, "delalloc", ++ btrfs_ino(inode), released, 0); ++ if (qgroup_free) ++ btrfs_qgroup_free_meta_prealloc(inode->root, qgroup_to_release); ++ else ++ btrfs_qgroup_convert_reserved_meta(inode->root, ++ qgroup_to_release); ++} ++ ++static void btrfs_calculate_inode_block_rsv_size(struct btrfs_fs_info *fs_info, ++ struct btrfs_inode *inode) ++{ ++ struct btrfs_block_rsv *block_rsv = &inode->block_rsv; ++ u64 reserve_size = 0; ++ u64 qgroup_rsv_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(fs_info, ++ outstanding_extents + 1); ++ csum_leaves = btrfs_csum_bytes_to_leaves(fs_info, ++ inode->csum_bytes); ++ reserve_size += btrfs_calc_trans_metadata_size(fs_info, ++ 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 = (u64)outstanding_extents * fs_info->nodesize; ++ ++ spin_lock(&block_rsv->lock); ++ block_rsv->size = reserve_size; ++ block_rsv->qgroup_rsv_size = qgroup_rsv_size; ++ spin_unlock(&block_rsv->lock); ++} ++ ++static void calc_inode_reservations(struct btrfs_fs_info *fs_info, ++ u64 num_bytes, u64 *meta_reserve, ++ u64 *qgroup_reserve) ++{ ++ u64 nr_extents = count_max_extents(num_bytes); ++ u64 csum_leaves = btrfs_csum_bytes_to_leaves(fs_info, num_bytes); ++ ++ /* We add one for the inode update at finish ordered time */ ++ *meta_reserve = btrfs_calc_trans_metadata_size(fs_info, ++ nr_extents + csum_leaves + 1); ++ *qgroup_reserve = nr_extents * fs_info->nodesize; ++} ++ ++int btrfs_delalloc_reserve_metadata(struct btrfs_inode *inode, u64 num_bytes) ++{ ++ struct btrfs_root *root = inode->root; ++ struct btrfs_fs_info *fs_info = root->fs_info; ++ struct btrfs_block_rsv *block_rsv = &inode->block_rsv; ++ u64 meta_reserve, qgroup_reserve; ++ unsigned nr_extents; ++ enum btrfs_reserve_flush_enum flush = BTRFS_RESERVE_FLUSH_ALL; ++ int ret = 0; ++ bool delalloc_lock = true; ++ ++ /* ++ * 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 ++ * mutex since we won't race with anybody. We need this mostly to make ++ * lockdep shut its filthy mouth. ++ * ++ * If we have a transaction open (can happen if we call truncate_block ++ * from truncate), then we need FLUSH_LIMIT so we don't deadlock. ++ */ ++ if (btrfs_is_free_space_inode(inode)) { ++ flush = BTRFS_RESERVE_NO_FLUSH; ++ delalloc_lock = false; ++ } else { ++ if (current->journal_info) ++ flush = BTRFS_RESERVE_FLUSH_LIMIT; ++ ++ if (btrfs_transaction_in_commit(fs_info)) ++ schedule_timeout(1); ++ } ++ ++ if (delalloc_lock) ++ mutex_lock(&inode->delalloc_mutex); ++ ++ num_bytes = ALIGN(num_bytes, fs_info->sectorsize); ++ ++ /* ++ * We always want to do it this way, every other way is wrong and ends ++ * in tears. Pre-reserving the amount we are going to add will always ++ * be the right way, because otherwise if we have enough parallelism we ++ * could end up with thousands of inodes all holding little bits of ++ * reservations they were able to make previously and the only way to ++ * reclaim that space is to ENOSPC out the operations and clear ++ * everything out and try again, which is bad. This way we just ++ * over-reserve slightly, and clean up the mess when we are done. ++ */ ++ calc_inode_reservations(fs_info, num_bytes, &meta_reserve, ++ &qgroup_reserve); ++ ret = btrfs_qgroup_reserve_meta_prealloc(root, qgroup_reserve, true); ++ if (ret) ++ goto out_fail; ++ ret = btrfs_reserve_metadata_bytes(root, block_rsv, meta_reserve, flush); ++ if (ret) ++ goto out_qgroup; ++ ++ /* ++ * Now we need to update our outstanding extents and csum bytes _first_ ++ * and then add the reservation to the block_rsv. This keeps us from ++ * racing with an ordered completion or some such that would think it ++ * needs to free the reservation we just made. ++ */ ++ spin_lock(&inode->lock); ++ nr_extents = count_max_extents(num_bytes); ++ btrfs_mod_outstanding_extents(inode, nr_extents); ++ inode->csum_bytes += num_bytes; ++ btrfs_calculate_inode_block_rsv_size(fs_info, inode); ++ spin_unlock(&inode->lock); ++ ++ /* Now we can safely add our space to our block rsv */ ++ btrfs_block_rsv_add_bytes(block_rsv, meta_reserve, false); ++ trace_btrfs_space_reservation(root->fs_info, "delalloc", ++ btrfs_ino(inode), meta_reserve, 1); ++ ++ spin_lock(&block_rsv->lock); ++ block_rsv->qgroup_rsv_reserved += qgroup_reserve; ++ spin_unlock(&block_rsv->lock); ++ ++ if (delalloc_lock) ++ mutex_unlock(&inode->delalloc_mutex); ++ return 0; ++out_qgroup: ++ btrfs_qgroup_free_meta_prealloc(root, qgroup_reserve); ++out_fail: ++ btrfs_inode_rsv_release(inode, true); ++ if (delalloc_lock) ++ mutex_unlock(&inode->delalloc_mutex); ++ return ret; ++} ++ ++/** ++ * 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 btrfs_inode *inode, u64 num_bytes, ++ bool qgroup_free) ++{ ++ struct btrfs_fs_info *fs_info = inode->root->fs_info; ++ ++ num_bytes = ALIGN(num_bytes, fs_info->sectorsize); ++ spin_lock(&inode->lock); ++ inode->csum_bytes -= num_bytes; ++ btrfs_calculate_inode_block_rsv_size(fs_info, inode); ++ spin_unlock(&inode->lock); ++ ++ if (btrfs_is_testing(fs_info)) ++ return; ++ ++ btrfs_inode_rsv_release(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 ++ * 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, ++ bool qgroup_free) ++{ ++ struct btrfs_fs_info *fs_info = inode->root->fs_info; ++ unsigned num_extents; ++ ++ spin_lock(&inode->lock); ++ num_extents = count_max_extents(num_bytes); ++ btrfs_mod_outstanding_extents(inode, -num_extents); ++ btrfs_calculate_inode_block_rsv_size(fs_info, inode); ++ spin_unlock(&inode->lock); ++ ++ if (btrfs_is_testing(fs_info)) ++ return; ++ ++ btrfs_inode_rsv_release(inode, qgroup_free); ++} ++ ++/** ++ * btrfs_delalloc_reserve_space - reserve data and metadata space for ++ * delalloc ++ * @inode: inode we're writing to ++ * @start: start range we are writing to ++ * @len: how long the range we are writing to ++ * @reserved: mandatory parameter, record actually reserved qgroup ranges of ++ * current reservation. ++ * ++ * This will do the following things ++ * ++ * - reserve space in data space info for num bytes ++ * and reserve precious corresponding qgroup space ++ * (Done in check_data_free_space) ++ * ++ * - reserve space for metadata space, based on the number of outstanding ++ * extents and how much csums will be needed ++ * also reserve metadata space in a per root over-reserve method. ++ * - add to the inodes->delalloc_bytes ++ * - add it to the fs_info's delalloc inodes list. ++ * (Above 3 all done in delalloc_reserve_metadata) ++ * ++ * Return 0 for success ++ * Return <0 for error(-ENOSPC or -EQUOT) ++ */ ++int btrfs_delalloc_reserve_space(struct inode *inode, ++ struct extent_changeset **reserved, u64 start, u64 len) ++{ ++ int ret; ++ ++ ret = btrfs_check_data_free_space(inode, reserved, start, len); ++ if (ret < 0) ++ return ret; ++ ret = btrfs_delalloc_reserve_metadata(BTRFS_I(inode), len); ++ if (ret < 0) ++ btrfs_free_reserved_data_space(inode, *reserved, start, len); ++ return ret; ++} ++ ++/** ++ * btrfs_delalloc_release_space - release data and metadata space for delalloc ++ * @inode: inode we're releasing space for ++ * @start: start position of the space already reserved ++ * @len: the len of the space already reserved ++ * @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 ++ * list if there are no delalloc bytes left. ++ * Also it will handle the qgroup reserved space. ++ */ ++void btrfs_delalloc_release_space(struct inode *inode, ++ struct extent_changeset *reserved, ++ u64 start, u64 len, bool qgroup_free) ++{ ++ btrfs_delalloc_release_metadata(BTRFS_I(inode), len, qgroup_free); ++ btrfs_free_reserved_data_space(inode, reserved, start, len); ++} +--- /dev/null ++++ b/fs/btrfs/delalloc-space.h +@@ -0,0 +1,23 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++ ++#ifndef BTRFS_DELALLOC_SPACE_H ++#define BTRFS_DELALLOC_SPACE_H ++ ++struct extent_changeset; ++ ++int btrfs_alloc_data_chunk_ondemand(struct btrfs_inode *inode, u64 bytes); ++int btrfs_check_data_free_space(struct inode *inode, ++ struct extent_changeset **reserved, u64 start, u64 len); ++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, bool qgroup_free); ++void btrfs_free_reserved_data_space_noquota(struct inode *inode, u64 start, ++ u64 len); ++void btrfs_delalloc_release_metadata(struct btrfs_inode *inode, u64 num_bytes, ++ bool qgroup_free); ++int btrfs_delalloc_reserve_space(struct inode *inode, ++ struct extent_changeset **reserved, u64 start, u64 len); ++ ++#endif /* BTRFS_DELALLOC_SPACE_H */ +--- a/fs/btrfs/extent-tree.c ++++ b/fs/btrfs/extent-tree.c +@@ -41,6 +41,7 @@ + #include "qgroup.h" + #include "space-info.h" + #include "block-rsv.h" ++#include "delalloc-space.h" + + #undef SCRAMBLE_DELAYED_REFS + +@@ -4083,213 +4084,6 @@ u64 btrfs_system_alloc_profile(struct bt + return get_alloc_profile(fs_info, BTRFS_BLOCK_GROUP_SYSTEM); + } + +-int btrfs_alloc_data_chunk_ondemand(struct btrfs_inode *inode, u64 bytes) +-{ +- struct btrfs_space_info *data_sinfo; +- struct btrfs_root *root = inode->root; +- struct btrfs_fs_info *fs_info = root->fs_info; +- u64 used; +- int ret = 0; +- int need_commit = 2; +- int have_pinned_space; +- +- /* make sure bytes are sectorsize aligned */ +- bytes = ALIGN(bytes, fs_info->sectorsize); +- +- if (btrfs_is_free_space_inode(inode)) { +- need_commit = 0; +- ASSERT(current->journal_info); +- } +- +- data_sinfo = fs_info->data_sinfo; +- if (!data_sinfo) +- goto alloc; +- +-again: +- /* make sure we have enough space to handle the data first */ +- spin_lock(&data_sinfo->lock); +- used = btrfs_space_info_used(data_sinfo, true); +- +- if (used + bytes > data_sinfo->total_bytes) { +- struct btrfs_trans_handle *trans; +- +- /* +- * if we don't have enough free bytes in this space then we need +- * to alloc a new chunk. +- */ +- if (!data_sinfo->full) { +- u64 alloc_target; +- +- data_sinfo->force_alloc = CHUNK_ALLOC_FORCE; +- spin_unlock(&data_sinfo->lock); +-alloc: +- alloc_target = btrfs_data_alloc_profile(fs_info); +- /* +- * It is ugly that we don't call nolock join +- * transaction for the free space inode case here. +- * But it is safe because we only do the data space +- * reservation for the free space cache in the +- * transaction context, the common join transaction +- * just increase the counter of the current transaction +- * handler, doesn't try to acquire the trans_lock of +- * the fs. +- */ +- trans = btrfs_join_transaction(root); +- if (IS_ERR(trans)) +- return PTR_ERR(trans); +- +- ret = btrfs_chunk_alloc(trans, alloc_target, +- CHUNK_ALLOC_NO_FORCE); +- btrfs_end_transaction(trans); +- if (ret < 0) { +- if (ret != -ENOSPC) +- return ret; +- else { +- have_pinned_space = 1; +- goto commit_trans; +- } +- } +- +- if (!data_sinfo) +- data_sinfo = fs_info->data_sinfo; +- +- goto again; +- } +- +- /* +- * If we don't have enough pinned space to deal with this +- * allocation, and no removed chunk in current transaction, +- * don't bother committing the transaction. +- */ +- have_pinned_space = percpu_counter_compare( +- &data_sinfo->total_bytes_pinned, +- used + bytes - data_sinfo->total_bytes); +- spin_unlock(&data_sinfo->lock); +- +- /* commit the current transaction and try again */ +-commit_trans: +- if (need_commit && +- !atomic_read(&fs_info->open_ioctl_trans)) { +- need_commit--; +- +- if (need_commit > 0) { +- btrfs_start_delalloc_roots(fs_info, 0, -1); +- btrfs_wait_ordered_roots(fs_info, U64_MAX, 0, +- (u64)-1); +- } +- +- trans = btrfs_join_transaction(root); +- if (IS_ERR(trans)) +- return PTR_ERR(trans); +- if (have_pinned_space >= 0 || +- test_bit(BTRFS_TRANS_HAVE_FREE_BGS, +- &trans->transaction->flags) || +- need_commit > 0) { +- ret = btrfs_commit_transaction(trans); +- if (ret) +- return ret; +- /* +- * The cleaner kthread might still be doing iput +- * operations. Wait for it to finish so that +- * more space is released. We don't need to +- * explicitly run the delayed iputs here because +- * the commit_transaction would have woken up +- * the cleaner. +- */ +- ret = btrfs_wait_on_delayed_iputs(fs_info); +- if (ret) +- return ret; +- goto again; +- } else { +- btrfs_end_transaction(trans); +- } +- } +- +- trace_btrfs_space_reservation(fs_info, +- "space_info:enospc", +- data_sinfo->flags, bytes, 1); +- return -ENOSPC; +- } +- btrfs_space_info_update_bytes_may_use(fs_info, data_sinfo, bytes); +- trace_btrfs_space_reservation(fs_info, "space_info", +- data_sinfo->flags, bytes, 1); +- spin_unlock(&data_sinfo->lock); +- +- return ret; +-} +- +-int btrfs_check_data_free_space(struct inode *inode, +- struct extent_changeset **reserved, u64 start, u64 len) +-{ +- struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb); +- int ret; +- +- /* align the range */ +- len = round_up(start + len, fs_info->sectorsize) - +- round_down(start, fs_info->sectorsize); +- start = round_down(start, fs_info->sectorsize); +- +- ret = btrfs_alloc_data_chunk_ondemand(BTRFS_I(inode), len); +- if (ret < 0) +- return ret; +- +- /* Use new btrfs_qgroup_reserve_data to reserve precious data space. */ +- ret = btrfs_qgroup_reserve_data(inode, reserved, start, len); +- if (ret < 0) +- btrfs_free_reserved_data_space_noquota(inode, start, len); +- else +- ret = 0; +- return ret; +-} +- +-/* +- * Called if we need to clear a data reservation for this inode +- * Normally in a error case. +- * +- * This one will *NOT* use accurate qgroup reserved space API, just for case +- * which we can't sleep and is sure it won't affect qgroup reserved space. +- * Like clear_bit_hook(). +- */ +-void btrfs_free_reserved_data_space_noquota(struct inode *inode, u64 start, +- u64 len) +-{ +- struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb); +- struct btrfs_space_info *data_sinfo; +- +- /* Make sure the range is aligned to sectorsize */ +- len = round_up(start + len, fs_info->sectorsize) - +- round_down(start, fs_info->sectorsize); +- start = round_down(start, fs_info->sectorsize); +- +- data_sinfo = fs_info->data_sinfo; +- spin_lock(&data_sinfo->lock); +- btrfs_space_info_update_bytes_may_use(fs_info, data_sinfo, -len); +- trace_btrfs_space_reservation(fs_info, "space_info", +- data_sinfo->flags, len, 0); +- spin_unlock(&data_sinfo->lock); +-} +- +-/* +- * Called if we need to clear a data reservation for this inode +- * Normally in a error case. +- * +- * This one will handle the per-inode data rsv map for accurate reserved +- * space framework. +- */ +-void btrfs_free_reserved_data_space(struct inode *inode, +- struct extent_changeset *reserved, u64 start, u64 len) +-{ +- struct btrfs_root *root = BTRFS_I(inode)->root; +- +- /* Make sure the range is aligned to sectorsize */ +- len = round_up(start + len, root->fs_info->sectorsize) - +- round_down(start, root->fs_info->sectorsize); +- start = round_down(start, root->fs_info->sectorsize); +- +- btrfs_free_reserved_data_space_noquota(inode, start, len); +- btrfs_qgroup_free_data(inode, reserved, start, len); +-} +- + static void force_metadata_allocation(struct btrfs_fs_info *info) + { + struct list_head *head = &info->space_info; +@@ -4532,41 +4326,6 @@ out: + return ret; + } + +-/** +- * 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, bool qgroup_free) +-{ +- struct btrfs_fs_info *fs_info = inode->root->fs_info; +- 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 = __btrfs_block_rsv_release(fs_info, block_rsv, 0, +- &qgroup_to_release); +- if (released > 0) +- trace_btrfs_space_reservation(fs_info, "delalloc", +- btrfs_ino(inode), released, 0); +- if (qgroup_free) +- btrfs_qgroup_free_meta_prealloc(inode->root, qgroup_to_release); +- else +- btrfs_qgroup_convert_reserved_meta(inode->root, +- qgroup_to_release); +-} +- + void btrfs_trans_release_metadata(struct btrfs_trans_handle *trans, + struct btrfs_fs_info *fs_info) + { +@@ -4644,256 +4403,6 @@ void btrfs_subvolume_release_metadata(st + btrfs_block_rsv_release(fs_info, rsv, (u64)-1); + } + +-static void btrfs_calculate_inode_block_rsv_size(struct btrfs_fs_info *fs_info, +- struct btrfs_inode *inode) +-{ +- struct btrfs_block_rsv *block_rsv = &inode->block_rsv; +- u64 reserve_size = 0; +- u64 qgroup_rsv_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(fs_info, +- outstanding_extents + 1); +- csum_leaves = btrfs_csum_bytes_to_leaves(fs_info, +- inode->csum_bytes); +- reserve_size += btrfs_calc_trans_metadata_size(fs_info, +- 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 = (u64)outstanding_extents * fs_info->nodesize; +- +- spin_lock(&block_rsv->lock); +- block_rsv->size = reserve_size; +- block_rsv->qgroup_rsv_size = qgroup_rsv_size; +- spin_unlock(&block_rsv->lock); +-} +- +-static void calc_inode_reservations(struct btrfs_fs_info *fs_info, +- u64 num_bytes, u64 *meta_reserve, +- u64 *qgroup_reserve) +-{ +- u64 nr_extents = count_max_extents(num_bytes); +- u64 csum_leaves = btrfs_csum_bytes_to_leaves(fs_info, num_bytes); +- +- /* We add one for the inode update at finish ordered time */ +- *meta_reserve = btrfs_calc_trans_metadata_size(fs_info, +- nr_extents + csum_leaves + 1); +- *qgroup_reserve = nr_extents * fs_info->nodesize; +-} +- +-int btrfs_delalloc_reserve_metadata(struct btrfs_inode *inode, u64 num_bytes) +-{ +- struct btrfs_root *root = inode->root; +- struct btrfs_fs_info *fs_info = root->fs_info; +- struct btrfs_block_rsv *block_rsv = &inode->block_rsv; +- u64 meta_reserve, qgroup_reserve; +- unsigned nr_extents; +- enum btrfs_reserve_flush_enum flush = BTRFS_RESERVE_FLUSH_ALL; +- int ret = 0; +- bool delalloc_lock = true; +- +- /* 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 +- * mutex since we won't race with anybody. We need this mostly to make +- * lockdep shut its filthy mouth. +- * +- * If we have a transaction open (can happen if we call truncate_block +- * from truncate), then we need FLUSH_LIMIT so we don't deadlock. +- */ +- if (btrfs_is_free_space_inode(inode)) { +- flush = BTRFS_RESERVE_NO_FLUSH; +- delalloc_lock = false; +- } else if (current->journal_info) { +- flush = BTRFS_RESERVE_FLUSH_LIMIT; +- } +- +- if (flush != BTRFS_RESERVE_NO_FLUSH && +- btrfs_transaction_in_commit(fs_info)) +- schedule_timeout(1); +- +- if (delalloc_lock) +- mutex_lock(&inode->delalloc_mutex); +- +- num_bytes = ALIGN(num_bytes, fs_info->sectorsize); +- +- /* +- * We always want to do it this way, every other way is wrong and ends +- * in tears. Pre-reserving the amount we are going to add will always +- * be the right way, because otherwise if we have enough parallelism we +- * could end up with thousands of inodes all holding little bits of +- * reservations they were able to make previously and the only way to +- * reclaim that space is to ENOSPC out the operations and clear +- * everything out and try again, which is bad. This way we just +- * over-reserve slightly, and clean up the mess when we are done. +- */ +- calc_inode_reservations(fs_info, num_bytes, &meta_reserve, +- &qgroup_reserve); +- ret = btrfs_qgroup_reserve_meta_prealloc(root, qgroup_reserve, true); +- if (ret) +- goto out_fail; +- ret = btrfs_reserve_metadata_bytes(root, block_rsv, meta_reserve, flush); +- if (ret) +- goto out_qgroup; +- +- /* +- * Now we need to update our outstanding extents and csum bytes _first_ +- * and then add the reservation to the block_rsv. This keeps us from +- * racing with an ordered completion or some such that would think it +- * needs to free the reservation we just made. +- */ +- spin_lock(&inode->lock); +- nr_extents = count_max_extents(num_bytes); +- btrfs_mod_outstanding_extents(inode, nr_extents); +- inode->csum_bytes += num_bytes; +- btrfs_calculate_inode_block_rsv_size(fs_info, inode); +- spin_unlock(&inode->lock); +- +- /* Now we can safely add our space to our block rsv */ +- btrfs_block_rsv_add_bytes(block_rsv, meta_reserve, false); +- trace_btrfs_space_reservation(root->fs_info, "delalloc", +- btrfs_ino(inode), meta_reserve, 1); +- +- spin_lock(&block_rsv->lock); +- block_rsv->qgroup_rsv_reserved += qgroup_reserve; +- spin_unlock(&block_rsv->lock); +- +- if (delalloc_lock) +- mutex_unlock(&inode->delalloc_mutex); +- return 0; +- +-out_qgroup: +- btrfs_qgroup_free_meta_prealloc(root, qgroup_reserve); +-out_fail: +- btrfs_inode_rsv_release(inode, true); +- if (delalloc_lock) +- mutex_unlock(&inode->delalloc_mutex); +- return ret; +-} +- +-/** +- * 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 btrfs_inode *inode, u64 num_bytes, +- bool qgroup_free) +-{ +- struct btrfs_fs_info *fs_info = btrfs_sb(inode->vfs_inode.i_sb); +- +- num_bytes = ALIGN(num_bytes, fs_info->sectorsize); +- spin_lock(&inode->lock); +- inode->csum_bytes -= num_bytes; +- btrfs_calculate_inode_block_rsv_size(fs_info, inode); +- spin_unlock(&inode->lock); +- +- if (btrfs_is_testing(fs_info)) +- return; +- +- btrfs_inode_rsv_release(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 +- * 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, +- bool qgroup_free) +-{ +- struct btrfs_fs_info *fs_info = btrfs_sb(inode->vfs_inode.i_sb); +- unsigned num_extents; +- +- spin_lock(&inode->lock); +- num_extents = count_max_extents(num_bytes); +- btrfs_mod_outstanding_extents(inode, -num_extents); +- btrfs_calculate_inode_block_rsv_size(fs_info, inode); +- spin_unlock(&inode->lock); +- +- if (btrfs_is_testing(fs_info)) +- return; +- +- btrfs_inode_rsv_release(inode, qgroup_free); +-} +- +-/** +- * btrfs_delalloc_reserve_space - reserve data and metadata space for +- * delalloc +- * @inode: inode we're writing to +- * @start: start range we are writing to +- * @len: how long the range we are writing to +- * @reserved: mandatory parameter, record actually reserved qgroup ranges of +- * current reservation. +- * +- * This will do the following things +- * +- * o reserve space in data space info for num bytes +- * and reserve precious corresponding qgroup space +- * (Done in check_data_free_space) +- * +- * o reserve space for metadata space, based on the number of outstanding +- * extents and how much csums will be needed +- * also reserve metadata space in a per root over-reserve method. +- * o add to the inodes->delalloc_bytes +- * o add it to the fs_info's delalloc inodes list. +- * (Above 3 all done in delalloc_reserve_metadata) +- * +- * Return 0 for success +- * Return <0 for error(-ENOSPC or -EQUOT) +- */ +-int btrfs_delalloc_reserve_space(struct inode *inode, +- struct extent_changeset **reserved, u64 start, u64 len) +-{ +- int ret; +- +- ret = btrfs_check_data_free_space(inode, reserved, start, len); +- if (ret < 0) +- return ret; +- ret = btrfs_delalloc_reserve_metadata(BTRFS_I(inode), len); +- if (ret < 0) +- btrfs_free_reserved_data_space(inode, *reserved, start, len); +- return ret; +-} +- +-/** +- * btrfs_delalloc_release_space - release data and metadata space for delalloc +- * @inode: inode we're releasing space for +- * @start: start position of the space already reserved +- * @len: the len of the space already reserved +- * @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 +- * list if there are no delalloc bytes left. +- * Also it will handle the qgroup reserved space. +- */ +-void btrfs_delalloc_release_space(struct inode *inode, +- struct extent_changeset *reserved, +- u64 start, u64 len, bool qgroup_free) +-{ +- btrfs_delalloc_release_metadata(BTRFS_I(inode), len, qgroup_free); +- btrfs_free_reserved_data_space(inode, reserved, start, len); +-} +- + static int update_block_group(struct btrfs_trans_handle *trans, + struct btrfs_fs_info *info, u64 bytenr, + u64 num_bytes, int alloc) +--- a/fs/btrfs/file.c ++++ b/fs/btrfs/file.c +@@ -42,6 +42,7 @@ + #include "volumes.h" + #include "qgroup.h" + #include "compression.h" ++#include "delalloc-space.h" + + static struct kmem_cache *btrfs_inode_defrag_cachep; + /* +--- a/fs/btrfs/free-space-cache.c ++++ b/fs/btrfs/free-space-cache.c +@@ -31,6 +31,7 @@ + #include "inode-map.h" + #include "volumes.h" + #include "space-info.h" ++#include "delalloc-space.h" + + #define BITS_PER_BITMAP (PAGE_SIZE * 8UL) + #define MAX_CACHE_BYTES_PER_GIG SZ_32K +--- a/fs/btrfs/inode-map.c ++++ b/fs/btrfs/inode-map.c +@@ -25,6 +25,7 @@ + #include "free-space-cache.h" + #include "inode-map.h" + #include "transaction.h" ++#include "delalloc-space.h" + + static int caching_kthread(void *data) + { +--- a/fs/btrfs/inode.c ++++ b/fs/btrfs/inode.c +@@ -62,6 +62,7 @@ + #include "props.h" + #include "qgroup.h" + #include "dedupe.h" ++#include "delalloc-space.h" + + struct btrfs_iget_args { + struct btrfs_key *location; +--- a/fs/btrfs/ioctl.c ++++ b/fs/btrfs/ioctl.c +@@ -62,6 +62,7 @@ + #include "tree-log.h" + #include "compression.h" + #include "space-info.h" ++#include "delalloc-space.h" + + #ifdef CONFIG_64BIT + /* If we have a 32-bit userspace and 64-bit kernel, then the UAPI +--- a/fs/btrfs/ordered-data.c ++++ b/fs/btrfs/ordered-data.c +@@ -26,6 +26,7 @@ + #include "extent_io.h" + #include "disk-io.h" + #include "compression.h" ++#include "delalloc-space.h" + + static struct kmem_cache *btrfs_ordered_extent_cache; + +--- a/fs/btrfs/relocation.c ++++ b/fs/btrfs/relocation.c +@@ -33,6 +33,7 @@ + #include "inode-map.h" + #include "qgroup.h" + #include "print-tree.h" ++#include "delalloc-space.h" + + /* + * backref_node, mapping_node and tree_block start with this diff --git a/patches.suse/0022-md-cluster-introduce-resync_info_get-interface-for-s.patch b/patches.suse/0022-md-cluster-introduce-resync_info_get-interface-for-s.patch new file mode 100644 index 0000000..5e86912 --- /dev/null +++ b/patches.suse/0022-md-cluster-introduce-resync_info_get-interface-for-s.patch @@ -0,0 +1,91 @@ +From 5ebaf80bc8d5826edcc2d1cea26a7d5a4b8f01dd Mon Sep 17 00:00:00 2001 +From: Guoqing Jiang +Date: Thu, 18 Oct 2018 16:37:43 +0800 +Subject: [PATCH] md-cluster: introduce resync_info_get interface for sanity + check +Git-commit: 5ebaf80bc8d5826edcc2d1cea26a7d5a4b8f01dd +Patch-mainline: v4.20-rc1 +References: bsc#1166003 + +Since the resync region from suspend_info means one node +is reshaping this area, so the position of reshape_progress +should be included in the area. + +Reviewed-by: NeilBrown +Signed-off-by: Guoqing Jiang +Signed-off-by: Shaohua Li +Signed-off-by: Coly Li + +--- + drivers/md/md-cluster.c | 14 ++++++++++++++ + drivers/md/md-cluster.h | 1 + + drivers/md/raid10.c | 8 +++++++- + 3 files changed, 22 insertions(+), 1 deletion(-) + +diff --git a/drivers/md/md-cluster.c b/drivers/md/md-cluster.c +index e223fae80da3..ca4a35f8bad8 100644 +--- a/drivers/md/md-cluster.c ++++ b/drivers/md/md-cluster.c +@@ -1323,6 +1323,19 @@ static int resync_start(struct mddev *mddev) + return dlm_lock_sync_interruptible(cinfo->resync_lockres, DLM_LOCK_EX, mddev); + } + ++static void resync_info_get(struct mddev *mddev, sector_t *lo, sector_t *hi) ++{ ++ struct md_cluster_info *cinfo = mddev->cluster_info; ++ struct suspend_info *s; ++ ++ spin_lock_irq(&cinfo->suspend_lock); ++ list_for_each_entry(s, &cinfo->suspend_list, list) { ++ *lo = s->lo; ++ *hi = s->hi; ++ } ++ spin_unlock_irq(&cinfo->suspend_lock); ++} ++ + static int resync_info_update(struct mddev *mddev, sector_t lo, sector_t hi) + { + struct md_cluster_info *cinfo = mddev->cluster_info; +@@ -1562,6 +1575,7 @@ static struct md_cluster_operations cluster_ops = { + .resync_start = resync_start, + .resync_finish = resync_finish, + .resync_info_update = resync_info_update, ++ .resync_info_get = resync_info_get, + .metadata_update_start = metadata_update_start, + .metadata_update_finish = metadata_update_finish, + .metadata_update_cancel = metadata_update_cancel, +diff --git a/drivers/md/md-cluster.h b/drivers/md/md-cluster.h +index 9bd753a6a94e..a78e3021775d 100644 +--- a/drivers/md/md-cluster.h ++++ b/drivers/md/md-cluster.h +@@ -14,6 +14,7 @@ struct md_cluster_operations { + int (*leave)(struct mddev *mddev); + int (*slot_number)(struct mddev *mddev); + int (*resync_info_update)(struct mddev *mddev, sector_t lo, sector_t hi); ++ void (*resync_info_get)(struct mddev *mddev, sector_t *lo, sector_t *hi); + int (*metadata_update_start)(struct mddev *mddev); + int (*metadata_update_finish)(struct mddev *mddev); + void (*metadata_update_cancel)(struct mddev *mddev); +diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c +index 1edd58a3098b..b98e746e7fc4 100644 +--- a/drivers/md/raid10.c ++++ b/drivers/md/raid10.c +@@ -4785,8 +4785,14 @@ static void end_reshape(struct r10conf *conf) + static void raid10_update_reshape_pos(struct mddev *mddev) + { + struct r10conf *conf = mddev->private; ++ sector_t lo, hi; + +- conf->reshape_progress = mddev->reshape_position; ++ md_cluster_ops->resync_info_get(mddev, &lo, &hi); ++ if (((mddev->reshape_position <= hi) && (mddev->reshape_position >= lo)) ++ || mddev->reshape_position == MaxSector) ++ conf->reshape_progress = mddev->reshape_position; ++ else ++ WARN_ON_ONCE(1); + } + + static int handle_reshape_read_error(struct mddev *mddev, +-- +2.25.0 + diff --git a/patches.suse/0023-btrfs-move-the-subvolume-reservation-stuff-out-of-extent-tree-c.patch b/patches.suse/0023-btrfs-move-the-subvolume-reservation-stuff-out-of-extent-tree-c.patch new file mode 100644 index 0000000..bbb886a --- /dev/null +++ b/patches.suse/0023-btrfs-move-the-subvolume-reservation-stuff-out-of-extent-tree-c.patch @@ -0,0 +1,211 @@ +From: Josef Bacik +Date: Wed, 19 Jun 2019 15:12:01 -0400 +Subject: btrfs: move the subvolume reservation stuff out of extent-tree.c +Git-commit: 28a32d2b1a6d7860e0b364c34a6b4205dce85537 +Patch-mainline: v5.3-rc1 +References: bsc#1165949 + +This is just two functions, put it in root-tree.c since it involves root +items. + +Signed-off-by: Josef Bacik +Signed-off-by: David Sterba +Acked-by: Nikolay Borisov +--- + fs/btrfs/ctree.h | 2 - + fs/btrfs/extent-tree.c | 58 ------------------------------------------------- + fs/btrfs/ioctl.c | 9 +------ + fs/btrfs/root-tree.c | 54 +++++++++++++++++++++++++++++++++++++++++++++ + 4 files changed, 57 insertions(+), 66 deletions(-) + +--- a/fs/btrfs/ctree.h ++++ b/fs/btrfs/ctree.h +@@ -2757,7 +2757,7 @@ void btrfs_trans_release_metadata(struct + int btrfs_subvolume_reserve_metadata(struct btrfs_root *root, + struct btrfs_block_rsv *rsv, + int nitems, +- u64 *qgroup_reserved, bool use_global_rsv); ++ bool use_global_rsv); + void btrfs_subvolume_release_metadata(struct btrfs_fs_info *fs_info, + struct btrfs_block_rsv *rsv); + void btrfs_delalloc_release_extents(struct btrfs_inode *inode, u64 num_bytes, +--- a/fs/btrfs/extent-tree.c ++++ b/fs/btrfs/extent-tree.c +@@ -4331,64 +4331,6 @@ void btrfs_trans_release_metadata(struct + trans->bytes_reserved = 0; + } + +-/* +- * btrfs_subvolume_reserve_metadata() - reserve space for subvolume operation +- * root: the root of the parent directory +- * rsv: block reservation +- * items: the number of items that we need do reservation +- * qgroup_reserved: used to return the reserved size in qgroup +- * +- * This function is used to reserve the space for snapshot/subvolume +- * creation and deletion. Those operations are different with the +- * common file/directory operations, they change two fs/file trees +- * and root tree, the number of items that the qgroup reserves is +- * different with the free space reservation. So we can not use +- * the space reservation mechanism in start_transaction(). +- */ +-int btrfs_subvolume_reserve_metadata(struct btrfs_root *root, +- struct btrfs_block_rsv *rsv, +- int items, +- u64 *qgroup_reserved, +- bool use_global_rsv) +-{ +- u64 num_bytes; +- int ret; +- struct btrfs_fs_info *fs_info = root->fs_info; +- struct btrfs_block_rsv *global_rsv = &fs_info->global_block_rsv; +- +- if (test_bit(BTRFS_FS_QUOTA_ENABLED, &fs_info->flags)) { +- /* One for parent inode, two for dir entries */ +- num_bytes = 3 * fs_info->nodesize; +- ret = btrfs_qgroup_reserve_meta_prealloc(root, num_bytes, true); +- if (ret) +- return ret; +- } else { +- num_bytes = 0; +- } +- +- *qgroup_reserved = num_bytes; +- +- num_bytes = btrfs_calc_trans_metadata_size(fs_info, items); +- rsv->space_info = btrfs_find_space_info(fs_info, +- BTRFS_BLOCK_GROUP_METADATA); +- ret = btrfs_block_rsv_add(root, rsv, num_bytes, +- BTRFS_RESERVE_FLUSH_ALL); +- +- if (ret == -ENOSPC && use_global_rsv) +- ret = btrfs_block_rsv_migrate(global_rsv, rsv, num_bytes, 1); +- +- if (ret && *qgroup_reserved) +- btrfs_qgroup_free_meta_prealloc(root, *qgroup_reserved); +- +- return ret; +-} +- +-void btrfs_subvolume_release_metadata(struct btrfs_fs_info *fs_info, +- struct btrfs_block_rsv *rsv) +-{ +- btrfs_block_rsv_release(fs_info, rsv, (u64)-1); +-} +- + static int update_block_group(struct btrfs_trans_handle *trans, + struct btrfs_fs_info *info, u64 bytenr, + u64 num_bytes, int alloc) +--- a/fs/btrfs/ioctl.c ++++ b/fs/btrfs/ioctl.c +@@ -470,7 +470,6 @@ static noinline int create_subvol(struct + u64 objectid; + u64 new_dirid = BTRFS_FIRST_FREE_OBJECTID; + u64 index = 0; +- u64 qgroup_reserved; + uuid_le new_uuid; + + root_item = kzalloc(sizeof(*root_item), GFP_KERNEL); +@@ -495,8 +494,7 @@ static noinline int create_subvol(struct + * The same as the snapshot creation, please see the comment + * of create_snapshot(). + */ +- ret = btrfs_subvolume_reserve_metadata(root, &block_rsv, +- 8, &qgroup_reserved, false); ++ ret = btrfs_subvolume_reserve_metadata(root, &block_rsv, 8, false); + if (ret) + goto fail_free; + +@@ -719,7 +717,6 @@ static int create_snapshot(struct btrfs_ + */ + ret = btrfs_subvolume_reserve_metadata(BTRFS_I(dir)->root, + &pending_snapshot->block_rsv, 8, +- &pending_snapshot->qgroup_reserved, + false); + if (ret) + goto dec_and_free; +@@ -2386,7 +2383,6 @@ static noinline int btrfs_ioctl_snap_des + struct btrfs_trans_handle *trans; + struct btrfs_block_rsv block_rsv; + u64 root_flags; +- u64 qgroup_reserved; + int namelen; + int ret; + int err = 0; +@@ -2504,8 +2500,7 @@ static noinline int btrfs_ioctl_snap_des + * One for dir inode, two for dir entries, two for root + * ref/backref. + */ +- err = btrfs_subvolume_reserve_metadata(root, &block_rsv, +- 5, &qgroup_reserved, true); ++ err = btrfs_subvolume_reserve_metadata(root, &block_rsv, 5, true); + if (err) + goto out_up_write; + +--- a/fs/btrfs/root-tree.c ++++ b/fs/btrfs/root-tree.c +@@ -22,6 +22,8 @@ + #include "transaction.h" + #include "disk-io.h" + #include "print-tree.h" ++#include "qgroup.h" ++#include "space-info.h" + + /* + * Read a root item from the tree. In case we detect a root item smaller then +@@ -515,3 +517,55 @@ void btrfs_update_root_times(struct btrf + btrfs_set_stack_timespec_nsec(&item->ctime, ct.tv_nsec); + spin_unlock(&root->root_item_lock); + } ++ ++/* ++ * btrfs_subvolume_reserve_metadata() - reserve space for subvolume operation ++ * root: the root of the parent directory ++ * rsv: block reservation ++ * items: the number of items that we need do reservation ++ * use_global_rsv: allow fallback to the global block reservation ++ * ++ * This function is used to reserve the space for snapshot/subvolume ++ * creation and deletion. Those operations are different with the ++ * common file/directory operations, they change two fs/file trees ++ * and root tree, the number of items that the qgroup reserves is ++ * different with the free space reservation. So we can not use ++ * the space reservation mechanism in start_transaction(). ++ */ ++int btrfs_subvolume_reserve_metadata(struct btrfs_root *root, ++ struct btrfs_block_rsv *rsv, int items, ++ bool use_global_rsv) ++{ ++ u64 num_bytes; ++ int ret; ++ struct btrfs_fs_info *fs_info = root->fs_info; ++ struct btrfs_block_rsv *global_rsv = &fs_info->global_block_rsv; ++ ++ if (test_bit(BTRFS_FS_QUOTA_ENABLED, &fs_info->flags)) { ++ /* One for parent inode, two for dir entries */ ++ num_bytes = 3 * fs_info->nodesize; ++ ret = btrfs_qgroup_reserve_meta_prealloc(root, num_bytes, true); ++ if (ret) ++ return ret; ++ } ++ ++ num_bytes = btrfs_calc_trans_metadata_size(fs_info, items); ++ rsv->space_info = btrfs_find_space_info(fs_info, ++ BTRFS_BLOCK_GROUP_METADATA); ++ ret = btrfs_block_rsv_add(root, rsv, num_bytes, ++ BTRFS_RESERVE_FLUSH_ALL); ++ ++ if (ret == -ENOSPC && use_global_rsv) ++ ret = btrfs_block_rsv_migrate(global_rsv, rsv, num_bytes, true); ++ ++ if (ret && num_bytes) ++ btrfs_qgroup_free_meta_prealloc(root, num_bytes); ++ ++ return ret; ++} ++ ++void btrfs_subvolume_release_metadata(struct btrfs_fs_info *fs_info, ++ struct btrfs_block_rsv *rsv) ++{ ++ btrfs_block_rsv_release(fs_info, rsv, (u64)-1); ++} diff --git a/patches.suse/0023-btrfs-unexport-the-temporary-exported-functions.patch b/patches.suse/0023-btrfs-unexport-the-temporary-exported-functions.patch new file mode 100644 index 0000000..51b5d8e --- /dev/null +++ b/patches.suse/0023-btrfs-unexport-the-temporary-exported-functions.patch @@ -0,0 +1,135 @@ +From: Josef Bacik +Date: Thu, 20 Jun 2019 15:38:07 -0400 +Subject: btrfs: unexport the temporary exported functions +Git-commit: e11c0406ad1bb602e1e880fa4ff37dadb716639d +Patch-mainline: v5.4-rc1 +References: bsc#1165949 + +These were renamed and exported to facilitate logical migration of +different code chunks into block-group.c. Now that all the users are in +one file go ahead and rename them back, move the code around, and make +them static. + +Signed-off-by: Josef Bacik +Reviewed-by: David Sterba +Signed-off-by: David Sterba +Acked-by: Nikolay Borisov +--- + fs/btrfs/block-group.c | 22 +++++++++++----------- + fs/btrfs/block-group.h | 3 --- + 2 files changed, 11 insertions(+), 14 deletions(-) + +--- a/fs/btrfs/block-group.c ++++ b/fs/btrfs/block-group.c +@@ -434,7 +434,7 @@ int btrfs_wait_block_group_cache_done(st + } + + #ifdef CONFIG_BTRFS_DEBUG +-void btrfs_fragment_free_space(struct btrfs_block_group_cache *block_group) ++static void fragment_free_space(struct btrfs_block_group_cache *block_group) + { + struct btrfs_fs_info *fs_info = block_group->fs_info; + u64 start = block_group->key.objectid; +@@ -671,7 +671,7 @@ static noinline void caching_thread(stru + block_group->space_info->bytes_used += bytes_used >> 1; + spin_unlock(&block_group->lock); + spin_unlock(&block_group->space_info->lock); +- btrfs_fragment_free_space(block_group); ++ fragment_free_space(block_group); + } + #endif + +@@ -778,7 +778,7 @@ int btrfs_cache_block_group(struct btrfs + cache->space_info->bytes_used += bytes_used >> 1; + spin_unlock(&cache->lock); + spin_unlock(&cache->space_info->lock); +- btrfs_fragment_free_space(cache); ++ fragment_free_space(cache); + } + #endif + mutex_unlock(&caching_ctl->mutex); +@@ -1182,7 +1182,7 @@ struct btrfs_trans_handle *btrfs_start_t + * data in this block group. That check should be done by relocation routine, + * not this function. + */ +-int __btrfs_inc_block_group_ro(struct btrfs_block_group_cache *cache, int force) ++static int inc_block_group_ro(struct btrfs_block_group_cache *cache, int force) + { + struct btrfs_space_info *sinfo = cache->space_info; + u64 num_bytes; +@@ -1297,7 +1297,7 @@ void btrfs_delete_unused_bgs(struct btrf + spin_unlock(&block_group->lock); + + /* We don't want to force the issue, only flip if it's ok. */ +- ret = __btrfs_inc_block_group_ro(block_group, 0); ++ ret = inc_block_group_ro(block_group, 0); + up_write(&space_info->groups_sem); + if (ret < 0) { + ret = 0; +@@ -1824,7 +1824,7 @@ int btrfs_read_block_groups(struct btrfs + + set_avail_alloc_bits(info, cache->flags); + if (btrfs_chunk_readonly(info, cache->key.objectid)) { +- __btrfs_inc_block_group_ro(cache, 1); ++ inc_block_group_ro(cache, 1); + } else if (btrfs_block_group_used(&cache->item) == 0) { + spin_lock(&info->unused_bgs_lock); + /* Should always be true but just in case. */ +@@ -1852,11 +1852,11 @@ int btrfs_read_block_groups(struct btrfs + list_for_each_entry(cache, + &space_info->block_groups[BTRFS_RAID_RAID0], + list) +- __btrfs_inc_block_group_ro(cache, 1); ++ inc_block_group_ro(cache, 1); + list_for_each_entry(cache, + &space_info->block_groups[BTRFS_RAID_SINGLE], + list) +- __btrfs_inc_block_group_ro(cache, 1); ++ inc_block_group_ro(cache, 1); + } + + btrfs_add_raid_kobjects(info); +@@ -1950,7 +1950,7 @@ int btrfs_make_block_group(struct btrfs_ + u64 new_bytes_used = size - bytes_used; + + bytes_used += new_bytes_used >> 1; +- btrfs_fragment_free_space(cache); ++ fragment_free_space(cache); + } + #endif + /* +@@ -2085,14 +2085,14 @@ again: + goto out; + } + +- ret = __btrfs_inc_block_group_ro(cache, 0); ++ ret = inc_block_group_ro(cache, 0); + if (!ret) + goto out; + alloc_flags = btrfs_get_alloc_profile(fs_info, cache->space_info->flags); + ret = btrfs_chunk_alloc(trans, alloc_flags, CHUNK_ALLOC_FORCE); + if (ret < 0) + goto out; +- ret = __btrfs_inc_block_group_ro(cache, 0); ++ ret = inc_block_group_ro(cache, 0); + out: + if (cache->flags & BTRFS_BLOCK_GROUP_SYSTEM) { + alloc_flags = update_block_group_flags(fs_info, cache->flags); +--- a/fs/btrfs/block-group.h ++++ b/fs/btrfs/block-group.h +@@ -166,7 +166,6 @@ static inline int btrfs_should_fragment_ + (btrfs_test_opt(fs_info, FRAGMENT_DATA) && + block_group->flags & BTRFS_BLOCK_GROUP_DATA); + } +-void btrfs_fragment_free_space(struct btrfs_block_group_cache *block_group); + #endif + + struct btrfs_block_group_cache *btrfs_lookup_first_block_group( +@@ -249,7 +248,5 @@ static inline int btrfs_block_group_cach + cache->cached == BTRFS_CACHE_ERROR; + } + +-int __btrfs_inc_block_group_ro(struct btrfs_block_group_cache *cache, int force); + u64 btrfs_get_restripe_target(struct btrfs_fs_info *fs_info, u64 flags); +- + #endif /* BTRFS_BLOCK_GROUP_H */ diff --git a/patches.suse/0023-md-cluster-raid10-call-update_size-in-md_reap_sync_t.patch b/patches.suse/0023-md-cluster-raid10-call-update_size-in-md_reap_sync_t.patch new file mode 100644 index 0000000..55bc9b7 --- /dev/null +++ b/patches.suse/0023-md-cluster-raid10-call-update_size-in-md_reap_sync_t.patch @@ -0,0 +1,84 @@ +From aefb2e5fc2be590e6bef8985f3d175c3d38b0b77 Mon Sep 17 00:00:00 2001 +From: Guoqing Jiang +Date: Thu, 18 Oct 2018 16:37:44 +0800 +Subject: [PATCH] md-cluster/raid10: call update_size in md_reap_sync_thread +Git-commit: aefb2e5fc2be590e6bef8985f3d175c3d38b0b77 +Patch-mainline: v4.20-rc1 +References: bsc#1166003 + +We need to change the capacity in all nodes after one node +finishs reshape. And as we did before, we can't change the +capacity directly in md_do_sync, instead, the capacity should +be only changed in update_size or received CHANGE_CAPACITY +msg. + +So master node calls update_size after completes reshape in +md_reap_sync_thread, but we need to skip ops->update_size if +MD_CLOSING is set since reshaping could not be finish. + +Reviewed-by: NeilBrown +Signed-off-by: Guoqing Jiang +Signed-off-by: Shaohua Li +Signed-off-by: Coly Li + +--- + drivers/md/md.c | 21 ++++++++++++++++++--- + 1 file changed, 18 insertions(+), 3 deletions(-) + +diff --git a/drivers/md/md.c b/drivers/md/md.c +index e07096c4ff20..e28f5db0a882 100644 +--- a/drivers/md/md.c ++++ b/drivers/md/md.c +@@ -8623,8 +8623,10 @@ void md_do_sync(struct md_thread *thread) + mddev_lock_nointr(mddev); + md_set_array_sectors(mddev, mddev->pers->size(mddev, 0, 0)); + mddev_unlock(mddev); +- set_capacity(mddev->gendisk, mddev->array_sectors); +- revalidate_disk(mddev->gendisk); ++ if (!mddev_is_clustered(mddev)) { ++ set_capacity(mddev->gendisk, mddev->array_sectors); ++ revalidate_disk(mddev->gendisk); ++ } + } + + spin_lock(&mddev->lock); +@@ -8968,6 +8970,8 @@ EXPORT_SYMBOL(md_check_recovery); + void md_reap_sync_thread(struct mddev *mddev) + { + struct md_rdev *rdev; ++ sector_t old_dev_sectors = mddev->dev_sectors; ++ bool is_reshaped = false; + + /* resync has finished, collect result */ + md_unregister_thread(&mddev->sync_thread); +@@ -8982,8 +8986,11 @@ void md_reap_sync_thread(struct mddev *mddev) + } + } + if (test_bit(MD_RECOVERY_RESHAPE, &mddev->recovery) && +- mddev->pers->finish_reshape) ++ mddev->pers->finish_reshape) { + mddev->pers->finish_reshape(mddev); ++ if (mddev_is_clustered(mddev)) ++ is_reshaped = true; ++ } + + /* If array is no-longer degraded, then any saved_raid_disk + * information must be scrapped. +@@ -9004,6 +9011,14 @@ void md_reap_sync_thread(struct mddev *mddev) + clear_bit(MD_RECOVERY_RESHAPE, &mddev->recovery); + clear_bit(MD_RECOVERY_REQUESTED, &mddev->recovery); + clear_bit(MD_RECOVERY_CHECK, &mddev->recovery); ++ /* ++ * We call md_cluster_ops->update_size here because sync_size could ++ * be changed by md_update_sb, and MD_RECOVERY_RESHAPE is cleared, ++ * so it is time to update size across cluster. ++ */ ++ if (mddev_is_clustered(mddev) && is_reshaped ++ && !test_bit(MD_CLOSING, &mddev->flags)) ++ md_cluster_ops->update_size(mddev, old_dev_sectors); + wake_up(&resync_wait); + /* flag recovery needed just to double check */ + set_bit(MD_RECOVERY_NEEDED, &mddev->recovery); +-- +2.25.0 + diff --git a/patches.suse/0024-md-cluster-raid10-don-t-call-remove_and_add_spares-d.patch b/patches.suse/0024-md-cluster-raid10-don-t-call-remove_and_add_spares-d.patch new file mode 100644 index 0000000..0dec038 --- /dev/null +++ b/patches.suse/0024-md-cluster-raid10-don-t-call-remove_and_add_spares-d.patch @@ -0,0 +1,46 @@ +From ca1e98e04a8d6cefbe8ad138df806434de6de7f3 Mon Sep 17 00:00:00 2001 +From: Guoqing Jiang +Date: Thu, 18 Oct 2018 16:37:45 +0800 +Subject: [PATCH] md-cluster/raid10: don't call remove_and_add_spares during + reshaping stage +Git-commit: ca1e98e04a8d6cefbe8ad138df806434de6de7f3 +Patch-mainline: v4.20-rc1 +References: bsc#1166003 + +remove_and_add_spares is not needed if reshape is +happening in another node, because raid10_add_disk +called inside raid10_start_reshape would handle the +role changes of disk. Plus, remove_and_add_spares +can't deal with the role change due to reshape. + +Reviewed-by: NeilBrown +Signed-off-by: Guoqing Jiang +Signed-off-by: Shaohua Li +Signed-off-by: Coly Li + +--- + drivers/md/md.c | 8 ++++++-- + 1 file changed, 6 insertions(+), 2 deletions(-) + +diff --git a/drivers/md/md.c b/drivers/md/md.c +index e28f5db0a882..fa2bbdec9955 100644 +--- a/drivers/md/md.c ++++ b/drivers/md/md.c +@@ -9218,8 +9218,12 @@ static void check_sb_changes(struct mddev *mddev, struct md_rdev *rdev) + } + + if (role != rdev2->raid_disk) { +- /* got activated */ +- if (rdev2->raid_disk == -1 && role != 0xffff) { ++ /* ++ * got activated except reshape is happening. ++ */ ++ if (rdev2->raid_disk == -1 && role != 0xffff && ++ !(le32_to_cpu(sb->feature_map) & ++ MD_FEATURE_RESHAPE_ACTIVE)) { + rdev2->saved_raid_disk = role; + ret = remove_and_add_spares(mddev, rdev2); + pr_info("Activated spare: %s\n", +-- +2.25.0 + diff --git a/patches.suse/0025-md-cluster-bitmap-don-t-call-md_bitmap_sync_with_clu.patch b/patches.suse/0025-md-cluster-bitmap-don-t-call-md_bitmap_sync_with_clu.patch new file mode 100644 index 0000000..749e045 --- /dev/null +++ b/patches.suse/0025-md-cluster-bitmap-don-t-call-md_bitmap_sync_with_clu.patch @@ -0,0 +1,84 @@ +From cbce6863b6d04f6eac6b144bcfaaf11a189d6533 Mon Sep 17 00:00:00 2001 +From: Guoqing Jiang +Date: Thu, 18 Oct 2018 16:37:46 +0800 +Subject: [PATCH] md-cluster/bitmap: don't call md_bitmap_sync_with_cluster + during reshaping stage +Git-commit: cbce6863b6d04f6eac6b144bcfaaf11a189d6533 +Patch-mainline: v4.20-rc1 +References: bsc#1166003 + +When reshape is happening in one node, other nodes could receive +lots of RESYNCING messages, so md_bitmap_sync_with_cluster is called. + +Since the resyncing window is typically small in these RESYNCING +messages, so WARN is always triggered, so we should not call the +func when reshape is happening. + +Reviewed-by: NeilBrown +Signed-off-by: Guoqing Jiang +Signed-off-by: Shaohua Li +Signed-off-by: Coly Li +--- + drivers/md/md-cluster.c | 27 ++++++++++++++++++++------- + 1 file changed, 20 insertions(+), 7 deletions(-) + +diff --git a/drivers/md/md-cluster.c b/drivers/md/md-cluster.c +index ca4a35f8bad8..792e0218a42f 100644 +--- a/drivers/md/md-cluster.c ++++ b/drivers/md/md-cluster.c +@@ -457,12 +457,13 @@ static void remove_suspend_info(struct mddev *mddev, int slot) + mddev->pers->quiesce(mddev, 0); + } + +- + static void process_suspend_info(struct mddev *mddev, + int slot, sector_t lo, sector_t hi) + { + struct md_cluster_info *cinfo = mddev->cluster_info; + struct suspend_info *s; ++ struct mdp_superblock_1 *sb = NULL; ++ struct md_rdev *rdev; + + if (!hi) { + /* +@@ -476,6 +477,12 @@ static void process_suspend_info(struct mddev *mddev, + return; + } + ++ rdev_for_each(rdev, mddev) ++ if (rdev->raid_disk > -1 && !test_bit(Faulty, &rdev->flags)) { ++ sb = page_address(rdev->sb_page); ++ break; ++ } ++ + /* + * The bitmaps are not same for different nodes + * if RESYNCING is happening in one node, then +@@ -488,12 +495,18 @@ static void process_suspend_info(struct mddev *mddev, + * sync_low/hi is used to record the region which + * arrived in the previous RESYNCING message, + * +- * Call bitmap_sync_with_cluster to clear +- * NEEDED_MASK and set RESYNC_MASK since +- * resync thread is running in another node, +- * so we don't need to do the resync again +- * with the same section */ +- md_bitmap_sync_with_cluster(mddev, cinfo->sync_low, cinfo->sync_hi, lo, hi); ++ * Call md_bitmap_sync_with_cluster to clear NEEDED_MASK ++ * and set RESYNC_MASK since resync thread is running ++ * in another node, so we don't need to do the resync ++ * again with the same section. ++ * ++ * Skip md_bitmap_sync_with_cluster in case reshape ++ * happening, because reshaping region is small and ++ * we don't want to trigger lots of WARN. ++ */ ++ if (sb && !(le32_to_cpu(sb->feature_map) & MD_FEATURE_RESHAPE_ACTIVE)) ++ md_bitmap_sync_with_cluster(mddev, cinfo->sync_low, ++ cinfo->sync_hi, lo, hi); + cinfo->sync_low = lo; + cinfo->sync_hi = hi; + +-- +2.25.0 + diff --git a/patches.suse/0026-md-cluster-send-BITMAP_NEEDS_SYNC-message-if-reshapi.patch b/patches.suse/0026-md-cluster-send-BITMAP_NEEDS_SYNC-message-if-reshapi.patch new file mode 100644 index 0000000..4163789 --- /dev/null +++ b/patches.suse/0026-md-cluster-send-BITMAP_NEEDS_SYNC-message-if-reshapi.patch @@ -0,0 +1,92 @@ +From cb9ee154317b084a96a7c2b771d1688f39fc714c Mon Sep 17 00:00:00 2001 +From: Guoqing Jiang +Date: Thu, 18 Oct 2018 16:37:47 +0800 +Subject: [PATCH] md-cluster: send BITMAP_NEEDS_SYNC message if reshaping is + interrupted +Git-commit: cb9ee154317b084a96a7c2b771d1688f39fc714c +Patch-mainline: v4.20-rc1 +References: bsc#1166003 + +We need to continue the reshaping if it was interrupted in +original node. So original node should call resync_bitmap +in case reshaping is aborted. + +Then BITMAP_NEEDS_SYNC message is broadcasted to other nodes, +node which continues the reshaping should restart reshape from +mddev->reshape_position instead of from the first beginning. + +Reviewed-by: NeilBrown +Signed-off-by: Guoqing Jiang +Signed-off-by: Shaohua Li +Signed-off-by: Coly Li + +--- + drivers/md/md-cluster.c | 19 ++++++++++++++++--- + drivers/md/md.c | 12 ++++++++++-- + 2 files changed, 26 insertions(+), 5 deletions(-) + +diff --git a/drivers/md/md-cluster.c b/drivers/md/md-cluster.c +index 792e0218a42f..f1b870766deb 100644 +--- a/drivers/md/md-cluster.c ++++ b/drivers/md/md-cluster.c +@@ -333,6 +333,12 @@ static void recover_bitmaps(struct md_thread *thread) + } + spin_unlock_irq(&cinfo->suspend_lock); + ++ /* Kick off a reshape if needed */ ++ if (test_bit(MD_RESYNCING_REMOTE, &mddev->recovery) && ++ test_bit(MD_RECOVERY_RESHAPE, &mddev->recovery) && ++ mddev->reshape_position != MaxSector) ++ md_wakeup_thread(mddev->sync_thread); ++ + if (hi > 0) { + if (lo < mddev->recovery_cp) + mddev->recovery_cp = lo; +@@ -1020,10 +1026,17 @@ static int leave(struct mddev *mddev) + if (!cinfo) + return 0; + +- /* BITMAP_NEEDS_SYNC message should be sent when node ++ /* ++ * BITMAP_NEEDS_SYNC message should be sent when node + * is leaving the cluster with dirty bitmap, also we +- * can only deliver it when dlm connection is available */ +- if (cinfo->slot_number > 0 && mddev->recovery_cp != MaxSector) ++ * can only deliver it when dlm connection is available. ++ * ++ * Also, we should send BITMAP_NEEDS_SYNC message in ++ * case reshaping is interrupted. ++ */ ++ if ((cinfo->slot_number > 0 && mddev->recovery_cp != MaxSector) || ++ (mddev->reshape_position != MaxSector && ++ test_bit(MD_CLOSING, &mddev->flags))) + resync_bitmap(mddev); + + set_bit(MD_CLUSTER_HOLDING_MUTEX_FOR_RECVD, &cinfo->state); +diff --git a/drivers/md/md.c b/drivers/md/md.c +index fa2bbdec9955..390f410e51dd 100644 +--- a/drivers/md/md.c ++++ b/drivers/md/md.c +@@ -8370,9 +8370,17 @@ void md_do_sync(struct md_thread *thread) + else if (!mddev->bitmap) + j = mddev->recovery_cp; + +- } else if (test_bit(MD_RECOVERY_RESHAPE, &mddev->recovery)) ++ } else if (test_bit(MD_RECOVERY_RESHAPE, &mddev->recovery)) { + max_sectors = mddev->resync_max_sectors; +- else { ++ /* ++ * If the original node aborts reshaping then we continue the ++ * reshaping, so set j again to avoid restart reshape from the ++ * first beginning ++ */ ++ if (mddev_is_clustered(mddev) && ++ mddev->reshape_position != MaxSector) ++ j = mddev->reshape_position; ++ } else { + /* recovery follows the physical size of devices */ + max_sectors = mddev->dev_sectors; + j = MaxSector; +-- +2.25.0 + diff --git a/patches.suse/0027-md-cluster-remove-suspend_info.patch b/patches.suse/0027-md-cluster-remove-suspend_info.patch new file mode 100644 index 0000000..58f1c33 --- /dev/null +++ b/patches.suse/0027-md-cluster-remove-suspend_info.patch @@ -0,0 +1,243 @@ +From ea89238c0a7b346bc90552e0244e87edf3311920 Mon Sep 17 00:00:00 2001 +From: Guoqing Jiang +Date: Thu, 18 Oct 2018 16:37:48 +0800 +Subject: [PATCH] md-cluster: remove suspend_info +Git-commit: ea89238c0a7b346bc90552e0244e87edf3311920 +Patch-mainline: v4.20-rc1 +References: bsc#1166003 + +Previously, we allow multiple nodes can resync device, but we +had changed it to only support one node can do resync at one +time, but suspend_info is still used. + +Now, let's remove the structure and use suspend_lo/hi to record +the range. + +Reviewed-by: NeilBrown +Signed-off-by: Guoqing Jiang +Signed-off-by: Shaohua Li +Signed-off-by: Coly Li + +--- + drivers/md/md-cluster.c | 103 +++++++++++++--------------------------- + 1 file changed, 32 insertions(+), 71 deletions(-) + +diff --git a/drivers/md/md-cluster.c b/drivers/md/md-cluster.c +index f1b870766deb..8dff19d5502e 100644 +--- a/drivers/md/md-cluster.c ++++ b/drivers/md/md-cluster.c +@@ -33,13 +33,6 @@ struct dlm_lock_resource { + int mode; + }; + +-struct suspend_info { +- int slot; +- sector_t lo; +- sector_t hi; +- struct list_head list; +-}; +- + struct resync_info { + __le64 lo; + __le64 hi; +@@ -80,7 +73,13 @@ struct md_cluster_info { + struct dlm_lock_resource **other_bitmap_lockres; + struct dlm_lock_resource *resync_lockres; + struct list_head suspend_list; ++ + spinlock_t suspend_lock; ++ /* record the region which write should be suspended */ ++ sector_t suspend_lo; ++ sector_t suspend_hi; ++ int suspend_from; /* the slot which broadcast suspend_lo/hi */ ++ + struct md_thread *recovery_thread; + unsigned long recovery_map; + /* communication loc resources */ +@@ -271,25 +270,22 @@ static void add_resync_info(struct dlm_lock_resource *lockres, + ri->hi = cpu_to_le64(hi); + } + +-static struct suspend_info *read_resync_info(struct mddev *mddev, struct dlm_lock_resource *lockres) ++static int read_resync_info(struct mddev *mddev, ++ struct dlm_lock_resource *lockres) + { + struct resync_info ri; +- struct suspend_info *s = NULL; +- sector_t hi = 0; ++ struct md_cluster_info *cinfo = mddev->cluster_info; ++ int ret = 0; + + dlm_lock_sync(lockres, DLM_LOCK_CR); + memcpy(&ri, lockres->lksb.sb_lvbptr, sizeof(struct resync_info)); +- hi = le64_to_cpu(ri.hi); +- if (hi > 0) { +- s = kzalloc(sizeof(struct suspend_info), GFP_KERNEL); +- if (!s) +- goto out; +- s->hi = hi; +- s->lo = le64_to_cpu(ri.lo); ++ if (le64_to_cpu(ri.hi) > 0) { ++ cinfo->suspend_hi = le64_to_cpu(ri.hi); ++ cinfo->suspend_lo = le64_to_cpu(ri.lo); ++ ret = 1; + } + dlm_unlock_sync(lockres); +-out: +- return s; ++ return ret; + } + + static void recover_bitmaps(struct md_thread *thread) +@@ -299,7 +295,6 @@ static void recover_bitmaps(struct md_thread *thread) + struct dlm_lock_resource *bm_lockres; + char str[64]; + int slot, ret; +- struct suspend_info *s, *tmp; + sector_t lo, hi; + + while (cinfo->recovery_map) { +@@ -326,11 +321,9 @@ static void recover_bitmaps(struct md_thread *thread) + + /* Clear suspend_area associated with the bitmap */ + spin_lock_irq(&cinfo->suspend_lock); +- list_for_each_entry_safe(s, tmp, &cinfo->suspend_list, list) +- if (slot == s->slot) { +- list_del(&s->list); +- kfree(s); +- } ++ cinfo->suspend_hi = 0; ++ cinfo->suspend_lo = 0; ++ cinfo->suspend_from = -1; + spin_unlock_irq(&cinfo->suspend_lock); + + /* Kick off a reshape if needed */ +@@ -441,24 +434,13 @@ static void ack_bast(void *arg, int mode) + } + } + +-static void __remove_suspend_info(struct md_cluster_info *cinfo, int slot) +-{ +- struct suspend_info *s, *tmp; +- +- list_for_each_entry_safe(s, tmp, &cinfo->suspend_list, list) +- if (slot == s->slot) { +- list_del(&s->list); +- kfree(s); +- break; +- } +-} +- + static void remove_suspend_info(struct mddev *mddev, int slot) + { + struct md_cluster_info *cinfo = mddev->cluster_info; + mddev->pers->quiesce(mddev, 1); + spin_lock_irq(&cinfo->suspend_lock); +- __remove_suspend_info(cinfo, slot); ++ cinfo->suspend_hi = 0; ++ cinfo->suspend_lo = 0; + spin_unlock_irq(&cinfo->suspend_lock); + mddev->pers->quiesce(mddev, 0); + } +@@ -467,7 +449,6 @@ static void process_suspend_info(struct mddev *mddev, + int slot, sector_t lo, sector_t hi) + { + struct md_cluster_info *cinfo = mddev->cluster_info; +- struct suspend_info *s; + struct mdp_superblock_1 *sb = NULL; + struct md_rdev *rdev; + +@@ -516,17 +497,11 @@ static void process_suspend_info(struct mddev *mddev, + cinfo->sync_low = lo; + cinfo->sync_hi = hi; + +- s = kzalloc(sizeof(struct suspend_info), GFP_KERNEL); +- if (!s) +- return; +- s->slot = slot; +- s->lo = lo; +- s->hi = hi; + mddev->pers->quiesce(mddev, 1); + spin_lock_irq(&cinfo->suspend_lock); +- /* Remove existing entry (if exists) before adding */ +- __remove_suspend_info(cinfo, slot); +- list_add(&s->list, &cinfo->suspend_list); ++ cinfo->suspend_from = slot; ++ cinfo->suspend_lo = lo; ++ cinfo->suspend_hi = hi; + spin_unlock_irq(&cinfo->suspend_lock); + mddev->pers->quiesce(mddev, 0); + } +@@ -825,7 +800,6 @@ static int gather_all_resync_info(struct mddev *mddev, int total_slots) + struct md_cluster_info *cinfo = mddev->cluster_info; + int i, ret = 0; + struct dlm_lock_resource *bm_lockres; +- struct suspend_info *s; + char str[64]; + sector_t lo, hi; + +@@ -844,16 +818,13 @@ static int gather_all_resync_info(struct mddev *mddev, int total_slots) + bm_lockres->flags |= DLM_LKF_NOQUEUE; + ret = dlm_lock_sync(bm_lockres, DLM_LOCK_PW); + if (ret == -EAGAIN) { +- s = read_resync_info(mddev, bm_lockres); +- if (s) { ++ if (read_resync_info(mddev, bm_lockres)) { + pr_info("%s:%d Resync[%llu..%llu] in progress on %d\n", + __func__, __LINE__, +- (unsigned long long) s->lo, +- (unsigned long long) s->hi, i); +- spin_lock_irq(&cinfo->suspend_lock); +- s->slot = i; +- list_add(&s->list, &cinfo->suspend_list); +- spin_unlock_irq(&cinfo->suspend_lock); ++ (unsigned long long) cinfo->suspend_lo, ++ (unsigned long long) cinfo->suspend_hi, ++ i); ++ cinfo->suspend_from = i; + } + ret = 0; + lockres_free(bm_lockres); +@@ -1352,13 +1323,10 @@ static int resync_start(struct mddev *mddev) + static void resync_info_get(struct mddev *mddev, sector_t *lo, sector_t *hi) + { + struct md_cluster_info *cinfo = mddev->cluster_info; +- struct suspend_info *s; + + spin_lock_irq(&cinfo->suspend_lock); +- list_for_each_entry(s, &cinfo->suspend_list, list) { +- *lo = s->lo; +- *hi = s->hi; +- } ++ *lo = cinfo->suspend_lo; ++ *hi = cinfo->suspend_hi; + spin_unlock_irq(&cinfo->suspend_lock); + } + +@@ -1414,21 +1382,14 @@ static int area_resyncing(struct mddev *mddev, int direction, + { + struct md_cluster_info *cinfo = mddev->cluster_info; + int ret = 0; +- struct suspend_info *s; + + if ((direction == READ) && + test_bit(MD_CLUSTER_SUSPEND_READ_BALANCING, &cinfo->state)) + return 1; + + spin_lock_irq(&cinfo->suspend_lock); +- if (list_empty(&cinfo->suspend_list)) +- goto out; +- list_for_each_entry(s, &cinfo->suspend_list, list) +- if (hi > s->lo && lo < s->hi) { +- ret = 1; +- break; +- } +-out: ++ if (hi > cinfo->suspend_lo && lo < cinfo->suspend_hi) ++ ret = 1; + spin_unlock_irq(&cinfo->suspend_lock); + return ret; + } +-- +2.25.0 + diff --git a/patches.suse/0028-md-remove-set-but-not-used-variable-bi_rdev.patch b/patches.suse/0028-md-remove-set-but-not-used-variable-bi_rdev.patch new file mode 100644 index 0000000..e9f0e7c --- /dev/null +++ b/patches.suse/0028-md-remove-set-but-not-used-variable-bi_rdev.patch @@ -0,0 +1,46 @@ +From f91389c8d2867d10a206273b8eb3b7955b65591e Mon Sep 17 00:00:00 2001 +From: Yue Haibing +Date: Thu, 8 Nov 2018 12:11:06 +0000 +Subject: [PATCH] md: remove set but not used variable 'bi_rdev' +Git-commit: f91389c8d2867d10a206273b8eb3b7955b65591e +Patch-mainline: v5.0-rc1 +References: bsc#1166003 + +Fixes gcc '-Wunused-but-set-variable' warning: + +drivers/md/md.c: In function 'md_integrity_add_rdev': +drivers/md/md.c:2149:24: warning: + variable 'bi_rdev' set but not used [-Wunused-but-set-variable] + +It not used any more after commit + 1501efadc524 ("md/raid: only permit hot-add of compatible integrity profiles") + +Signed-off-by: Yue Haibing +Signed-off-by: Shaohua Li +Signed-off-by: Coly Li +--- + drivers/md/md.c | 2 -- + 1 file changed, 2 deletions(-) + +diff --git a/drivers/md/md.c b/drivers/md/md.c +index fc488cb30a94..69778419aa20 100644 +--- a/drivers/md/md.c ++++ b/drivers/md/md.c +@@ -2148,14 +2148,12 @@ EXPORT_SYMBOL(md_integrity_register); + */ + int md_integrity_add_rdev(struct md_rdev *rdev, struct mddev *mddev) + { +- struct blk_integrity *bi_rdev; + struct blk_integrity *bi_mddev; + char name[BDEVNAME_SIZE]; + + if (!mddev->gendisk) + return 0; + +- bi_rdev = bdev_get_integrity(rdev->bdev); + bi_mddev = blk_get_integrity(mddev->gendisk); + + if (!bi_mddev) /* nothing to do */ +-- +2.25.0 + diff --git a/patches.suse/0029-lib-raid6-add-missing-include-for-raid6test.patch b/patches.suse/0029-lib-raid6-add-missing-include-for-raid6test.patch new file mode 100644 index 0000000..80324b1 --- /dev/null +++ b/patches.suse/0029-lib-raid6-add-missing-include-for-raid6test.patch @@ -0,0 +1,33 @@ +From e731f3e28b7e7d1c745b03084e01036ee00018eb Mon Sep 17 00:00:00 2001 +From: Daniel Verkamp +Date: Mon, 12 Nov 2018 15:22:16 -0800 +Subject: [PATCH] lib/raid6: add missing include for raid6test +Git-commit: e731f3e28b7e7d1c745b03084e01036ee00018eb +Patch-mainline: v5.0-rc1 +References: bsc#1166003 + +Add #include for gettimeofday() to fix the compiler warning +about an implicitly defined functions. + +Signed-off-by: Daniel Verkamp +Signed-off-by: Shaohua Li +Signed-off-by: Coly Li +--- + include/linux/raid/pq.h | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/include/linux/raid/pq.h b/include/linux/raid/pq.h +index ea8505204fdf..0c245dcb8b48 100644 +--- a/include/linux/raid/pq.h ++++ b/include/linux/raid/pq.h +@@ -35,6 +35,7 @@ extern const char raid6_empty_zero_page[PAGE_SIZE]; + #include + #include + #include ++#include + #include + + /* Not standard, but glibc defines it */ +-- +2.25.0 + diff --git a/patches.suse/0030-lib-raid6-avoid-__attribute_const__-redefinition.patch b/patches.suse/0030-lib-raid6-avoid-__attribute_const__-redefinition.patch new file mode 100644 index 0000000..9bf5197 --- /dev/null +++ b/patches.suse/0030-lib-raid6-avoid-__attribute_const__-redefinition.patch @@ -0,0 +1,38 @@ +From 58af3110a7c5d161f72f94a98c6f2b9b75bf5cf9 Mon Sep 17 00:00:00 2001 +From: Daniel Verkamp +Date: Mon, 12 Nov 2018 15:22:17 -0800 +Subject: [PATCH] lib/raid6: avoid __attribute_const__ redefinition +Git-commit: 58af3110a7c5d161f72f94a98c6f2b9b75bf5cf9 +Patch-mainline: v5.0-rc1 +References: bsc#1166003 + +This is defined in glibc's sys/cdefs.h on my system with the same +definition as the raid6test fallback definition. Add a #ifndef check to +avoid a compiler warning about redefining it. + +Signed-off-by: Daniel Verkamp +Signed-off-by: Shaohua Li +Signed-off-by: Coly Li + +--- + include/linux/raid/pq.h | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/include/linux/raid/pq.h b/include/linux/raid/pq.h +index 0c245dcb8b48..d7c99161bba2 100644 +--- a/include/linux/raid/pq.h ++++ b/include/linux/raid/pq.h +@@ -53,7 +53,9 @@ extern const char raid6_empty_zero_page[PAGE_SIZE]; + + #define __init + #define __exit +-#define __attribute_const__ __attribute__((const)) ++#ifndef __attribute_const__ ++# define __attribute_const__ __attribute__((const)) ++#endif + #define noinline __attribute__((noinline)) + + #define preempt_enable() +-- +2.25.0 + diff --git a/patches.suse/0031-lib-raid6-add-option-to-skip-algo-benchmarking.patch b/patches.suse/0031-lib-raid6-add-option-to-skip-algo-benchmarking.patch new file mode 100644 index 0000000..c3b7d89 --- /dev/null +++ b/patches.suse/0031-lib-raid6-add-option-to-skip-algo-benchmarking.patch @@ -0,0 +1,81 @@ +From be85f93ae2df32dea0b20908316f1d894c3e0f64 Mon Sep 17 00:00:00 2001 +From: Daniel Verkamp +Date: Mon, 12 Nov 2018 15:26:52 -0800 +Subject: [PATCH] lib/raid6: add option to skip algo benchmarking +Git-commit: be85f93ae2df32dea0b20908316f1d894c3e0f64 +Patch-mainline: v5.0-rc1 +References: bsc#1166003 + +This is helpful for systems where fast startup time is important. +It is especially nice to avoid benchmarking RAID functions that are +never used (for example, BTRFS selects RAID6_PQ even if the parity RAID +mode is not in use). + +This saves 250+ milliseconds of boot time on modern x86 and ARM systems +with a dozen or more available implementations. + +The new option is defaulted to 'y' to match the previous behavior of +always benchmarking on init. + +Signed-off-by: Daniel Verkamp +Signed-off-by: Shaohua Li +Signed-off-by: Coly Li + +--- + include/linux/raid/pq.h | 3 +++ + lib/Kconfig | 8 ++++++++ + lib/raid6/algos.c | 5 +++++ + 3 files changed, 16 insertions(+) + +diff --git a/include/linux/raid/pq.h b/include/linux/raid/pq.h +index d7c99161bba2..605cf46c17bd 100644 +--- a/include/linux/raid/pq.h ++++ b/include/linux/raid/pq.h +@@ -70,6 +70,9 @@ extern const char raid6_empty_zero_page[PAGE_SIZE]; + #define MODULE_DESCRIPTION(desc) + #define subsys_initcall(x) + #define module_exit(x) ++ ++#define IS_ENABLED(x) (x) ++#define CONFIG_RAID6_PQ_BENCHMARK 1 + #endif /* __KERNEL__ */ + + /* Routine choices */ +diff --git a/lib/Kconfig b/lib/Kconfig +index a9965f4af4dd..fcb05305a5a2 100644 +--- a/lib/Kconfig ++++ b/lib/Kconfig +@@ -10,6 +10,14 @@ menu "Library routines" + config RAID6_PQ + tristate + ++config RAID6_PQ_BENCHMARK ++ bool "Automatically choose fastest RAID6 PQ functions" ++ depends on RAID6_PQ ++ default y ++ help ++ Benchmark all available RAID6 PQ functions on init and choose the ++ fastest one. ++ + config BITREVERSE + tristate + +diff --git a/lib/raid6/algos.c b/lib/raid6/algos.c +index a753ff56670f..7e4f7a8ffa8e 100644 +--- a/lib/raid6/algos.c ++++ b/lib/raid6/algos.c +@@ -163,6 +163,11 @@ static inline const struct raid6_calls *raid6_choose_gen( + if ((*algo)->valid && !(*algo)->valid()) + continue; + ++ if (!IS_ENABLED(CONFIG_RAID6_PQ_BENCHMARK)) { ++ best = *algo; ++ break; ++ } ++ + perf = 0; + + preempt_disable(); +-- +2.25.0 + diff --git a/patches.suse/0032-raid10-refactor-common-wait-code-from-regular-read-w.patch b/patches.suse/0032-raid10-refactor-common-wait-code-from-regular-read-w.patch new file mode 100644 index 0000000..192f943 --- /dev/null +++ b/patches.suse/0032-raid10-refactor-common-wait-code-from-regular-read-w.patch @@ -0,0 +1,131 @@ +From caea3c47ad515210129f06b6bbe53f82f69efebe Mon Sep 17 00:00:00 2001 +From: Guoqing Jiang +Date: Fri, 7 Dec 2018 18:24:21 +0800 +Subject: [PATCH] raid10: refactor common wait code from regular read/write + request +Git-commit: caea3c47ad515210129f06b6bbe53f82f69efebe +Patch-mainline: v5.0-rc1 +References: bsc#1166003 + +Both raid10_read_request and raid10_write_request share +the same code at the beginning of them, so introduce +regular_request_wait to clean up code, and call it in +both request functions. + +Signed-off-by: Guoqing Jiang +Signed-off-by: Shaohua Li +Signed-off-by: Coly Li + +--- + drivers/md/raid10.c | 72 ++++++++++++++++----------------------------- + 1 file changed, 25 insertions(+), 47 deletions(-) + +diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c +index b98e746e7fc4..76c92e31afc0 100644 +--- a/drivers/md/raid10.c ++++ b/drivers/md/raid10.c +@@ -1124,6 +1124,29 @@ static void raid10_unplug(struct blk_plug_cb *cb, bool from_schedule) + kfree(plug); + } + ++/* ++ * 1. Register the new request and wait if the reconstruction thread has put ++ * up a bar for new requests. Continue immediately if no resync is active ++ * currently. ++ * 2. If IO spans the reshape position. Need to wait for reshape to pass. ++ */ ++static void regular_request_wait(struct mddev *mddev, struct r10conf *conf, ++ struct bio *bio, sector_t sectors) ++{ ++ wait_barrier(conf); ++ while (test_bit(MD_RECOVERY_RESHAPE, &mddev->recovery) && ++ bio->bi_iter.bi_sector < conf->reshape_progress && ++ bio->bi_iter.bi_sector + sectors > conf->reshape_progress) { ++ raid10_log(conf->mddev, "wait reshape"); ++ allow_barrier(conf); ++ wait_event(conf->wait_barrier, ++ conf->reshape_progress <= bio->bi_iter.bi_sector || ++ conf->reshape_progress >= bio->bi_iter.bi_sector + ++ sectors); ++ wait_barrier(conf); ++ } ++} ++ + static void raid10_read_request(struct mddev *mddev, struct bio *bio, + struct r10bio *r10_bio) + { +@@ -1132,7 +1155,6 @@ static void raid10_read_request(struct mddev *mddev, struct bio *bio, + const int op = bio_op(bio); + const unsigned long do_sync = (bio->bi_opf & REQ_SYNC); + int max_sectors; +- sector_t sectors; + struct md_rdev *rdev; + char b[BDEVNAME_SIZE]; + int slot = r10_bio->read_slot; +@@ -1166,30 +1188,8 @@ static void raid10_read_request(struct mddev *mddev, struct bio *bio, + } + rcu_read_unlock(); + } +- /* +- * Register the new request and wait if the reconstruction +- * thread has put up a bar for new requests. +- * Continue immediately if no resync is active currently. +- */ +- wait_barrier(conf); +- +- sectors = r10_bio->sectors; +- while (test_bit(MD_RECOVERY_RESHAPE, &mddev->recovery) && +- bio->bi_iter.bi_sector < conf->reshape_progress && +- bio->bi_iter.bi_sector + sectors > conf->reshape_progress) { +- /* +- * IO spans the reshape position. Need to wait for reshape to +- * pass +- */ +- raid10_log(conf->mddev, "wait reshape"); +- allow_barrier(conf); +- wait_event(conf->wait_barrier, +- conf->reshape_progress <= bio->bi_iter.bi_sector || +- conf->reshape_progress >= bio->bi_iter.bi_sector + +- sectors); +- wait_barrier(conf); +- } + ++ regular_request_wait(mddev, conf, bio, r10_bio->sectors); + rdev = read_balance(conf, r10_bio, &max_sectors); + if (!rdev) { + if (err_rdev) { +@@ -1332,30 +1332,8 @@ static void raid10_write_request(struct mddev *mddev, struct bio *bio, + finish_wait(&conf->wait_barrier, &w); + } + +- /* +- * Register the new request and wait if the reconstruction +- * thread has put up a bar for new requests. +- * Continue immediately if no resync is active currently. +- */ +- wait_barrier(conf); +- + sectors = r10_bio->sectors; +- while (test_bit(MD_RECOVERY_RESHAPE, &mddev->recovery) && +- bio->bi_iter.bi_sector < conf->reshape_progress && +- bio->bi_iter.bi_sector + sectors > conf->reshape_progress) { +- /* +- * IO spans the reshape position. Need to wait for reshape to +- * pass +- */ +- raid10_log(conf->mddev, "wait reshape"); +- allow_barrier(conf); +- wait_event(conf->wait_barrier, +- conf->reshape_progress <= bio->bi_iter.bi_sector || +- conf->reshape_progress >= bio->bi_iter.bi_sector + +- sectors); +- wait_barrier(conf); +- } +- ++ regular_request_wait(mddev, conf, bio, sectors); + if (test_bit(MD_RECOVERY_RESHAPE, &mddev->recovery) && + (mddev->reshape_backwards + ? (bio->bi_iter.bi_sector < conf->reshape_safe && +-- +2.25.0 + diff --git a/patches.suse/0033-md-Make-bio_alloc_mddev-use-bio_alloc_bioset.patch b/patches.suse/0033-md-Make-bio_alloc_mddev-use-bio_alloc_bioset.patch new file mode 100644 index 0000000..346ed44 --- /dev/null +++ b/patches.suse/0033-md-Make-bio_alloc_mddev-use-bio_alloc_bioset.patch @@ -0,0 +1,42 @@ +From 6251691a92170d3a781aaf7b5f2c31b50d669809 Mon Sep 17 00:00:00 2001 +From: Marcos Paulo de Souza +Date: Mon, 14 Jan 2019 06:31:56 -0700 +Subject: [PATCH] md: Make bio_alloc_mddev use bio_alloc_bioset +Git-commit: 6251691a92170d3a781aaf7b5f2c31b50d669809 +Patch-mainline: v5.0-rc3 +References: bsc#1166003 + +bio_alloc_bioset returns a bio pointer or NULL, so we can avoid storing +the returned data into a new variable. + +(Coly Li: rebase for Linux v4.12 based SUSE kernel) + +Acked-by: Guoqing Jiang +Acked-by: Artur Paszkiewicz +Signed-off-by: Marcos Paulo de Souza +Signed-off-by: Jens Axboe +Signed-off-by: Coly Li + +--- + drivers/md/md.c | 7 +------ + 1 file changed, 1 insertion(+), 6 deletions(-) + +--- a/drivers/md/md.c ++++ b/drivers/md/md.c +@@ -189,15 +189,10 @@ static bool create_on_open = true; + struct bio *bio_alloc_mddev(gfp_t gfp_mask, int nr_iovecs, + struct mddev *mddev) + { +- struct bio *b; +- + if (!mddev || !mddev->bio_set) + return bio_alloc(gfp_mask, nr_iovecs); + +- b = bio_alloc_bioset(gfp_mask, nr_iovecs, mddev->bio_set); +- if (!b) +- return NULL; +- return b; ++ return bio_alloc_bioset(gfp_mask, nr_iovecs, mddev->bio_set); + } + EXPORT_SYMBOL_GPL(bio_alloc_mddev); + diff --git a/patches.suse/0034-md-linear-use-struct_size-in-kzalloc.patch b/patches.suse/0034-md-linear-use-struct_size-in-kzalloc.patch new file mode 100644 index 0000000..c7556cb --- /dev/null +++ b/patches.suse/0034-md-linear-use-struct_size-in-kzalloc.patch @@ -0,0 +1,51 @@ +From f1e5b6239bdd46aa3f4e631611800ea7d10826c4 Mon Sep 17 00:00:00 2001 +From: "Gustavo A. R. Silva" +Date: Mon, 7 Jan 2019 11:45:38 -0600 +Subject: [PATCH] md-linear: use struct_size() in kzalloc() +Git-commit: f1e5b6239bdd46aa3f4e631611800ea7d10826c4 +Patch-mainline: v5.1-rc1 +References: bsc#1166003 + +One of the more common cases of allocation size calculations is finding the +size of a structure that has a zero-sized array at the end, along with memory +for some number of elements for that array. For example: + +struct foo { + int stuff; + void *entry[]; +}; + +instance = kzalloc(sizeof(struct foo) + sizeof(void *) * count, GFP_KERNEL); + +Instead of leaving these open-coded and prone to type mistakes, we can now +use the new struct_size() helper: + +instance = kzalloc(struct_size(instance, entry, count), GFP_KERNEL); + +This code was detected with the help of Coccinelle. + +Signed-off-by: Gustavo A. R. Silva +Signed-off-by: Song Liu +Signed-off-by: Coly Li + +--- + drivers/md/md-linear.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/drivers/md/md-linear.c b/drivers/md/md-linear.c +index d45c697c0ebe..5998d78aa189 100644 +--- a/drivers/md/md-linear.c ++++ b/drivers/md/md-linear.c +@@ -96,8 +96,7 @@ static struct linear_conf *linear_conf(struct mddev *mddev, int raid_disks) + int i, cnt; + bool discard_supported = false; + +- conf = kzalloc (sizeof (*conf) + raid_disks*sizeof(struct dev_info), +- GFP_KERNEL); ++ conf = kzalloc(struct_size(conf, disks, raid_disks), GFP_KERNEL); + if (!conf) + return NULL; + +-- +2.25.0 + diff --git a/patches.suse/0035-raid1-simplify-raid1_error-function.patch b/patches.suse/0035-raid1-simplify-raid1_error-function.patch new file mode 100644 index 0000000..8d16bdf --- /dev/null +++ b/patches.suse/0035-raid1-simplify-raid1_error-function.patch @@ -0,0 +1,39 @@ +From ebda52fa1be73952ec603b1fad685ce86ccb5ee6 Mon Sep 17 00:00:00 2001 +From: Yufen Yu +Date: Fri, 1 Feb 2019 10:45:01 +0800 +Subject: [PATCH] raid1: simplify raid1_error function +Git-commit: ebda52fa1be73952ec603b1fad685ce86ccb5ee6 +Patch-mainline: v5.1-rc1 +References: bsc#1166003 + +Remove redundance set_bit and let code simplify. + +Signed-off-by: Yufen Yu +Signed-off-by: Song Liu +Signed-off-by: Coly Li + +--- + drivers/md/raid1.c | 6 ++---- + 1 file changed, 2 insertions(+), 4 deletions(-) + +diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c +index 1d54109071cc..7e63ccc4ae7b 100644 +--- a/drivers/md/raid1.c ++++ b/drivers/md/raid1.c +@@ -1603,11 +1603,9 @@ static void raid1_error(struct mddev *mddev, struct md_rdev *rdev) + return; + } + set_bit(Blocked, &rdev->flags); +- if (test_and_clear_bit(In_sync, &rdev->flags)) { ++ if (test_and_clear_bit(In_sync, &rdev->flags)) + mddev->degraded++; +- set_bit(Faulty, &rdev->flags); +- } else +- set_bit(Faulty, &rdev->flags); ++ set_bit(Faulty, &rdev->flags); + spin_unlock_irqrestore(&conf->device_lock, flags); + /* + * if recovery is running, make sure it aborts. +-- +2.25.0 + diff --git a/patches.suse/0036-md-convert-to-kvmalloc.patch b/patches.suse/0036-md-convert-to-kvmalloc.patch new file mode 100644 index 0000000..93628a4 --- /dev/null +++ b/patches.suse/0036-md-convert-to-kvmalloc.patch @@ -0,0 +1,224 @@ +From b330e6a49dc3e9145de5c986b29bbbb884351e92 Mon Sep 17 00:00:00 2001 +From: Kent Overstreet +Date: Mon, 11 Mar 2019 23:31:06 -0700 +Subject: [PATCH] md: convert to kvmalloc +Git-commit: b330e6a49dc3e9145de5c986b29bbbb884351e92 +Patch-mainline: v5.1-rc1 +References: bsc#1166003 + +The code really just wants a big flat buffer, so just do that. + +Link: http://lkml.kernel.org/r/20181217131929.11727-3-kent.overstreet@gmail.com +Signed-off-by: Kent Overstreet +Reviewed-by: Matthew Wilcox +Cc: Shaohua Li +Cc: Alexey Dobriyan +Cc: Al Viro +Cc: Dave Hansen +Cc: Eric Paris +Cc: Marcelo Ricardo Leitner +Cc: Neil Horman +Cc: Paul Moore +Cc: Pravin B Shelar +Cc: Stephen Smalley +Cc: Vlad Yasevich +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +Signed-off-by: Coly Li + +--- + drivers/md/raid5-ppl.c | 6 +-- + drivers/md/raid5.c | 85 +++++++++++++++++++++---------------------------- + drivers/md/raid5.h | 9 ++--- + 3 files changed, 45 insertions(+), 55 deletions(-) + +--- a/drivers/md/raid5-ppl.c ++++ b/drivers/md/raid5-ppl.c +@@ -16,7 +16,6 @@ + #include + #include + #include +-#include + #include + #include + #include "md.h" +@@ -165,7 +164,7 @@ ops_run_partial_parity(struct stripe_hea + struct dma_async_tx_descriptor *tx) + { + int disks = sh->disks; +- struct page **srcs = flex_array_get(percpu->scribble, 0); ++ struct page **srcs = percpu->scribble; + int count = 0, pd_idx = sh->pd_idx, i; + struct async_submit_ctl submit; + +@@ -196,8 +195,7 @@ ops_run_partial_parity(struct stripe_hea + } + + init_async_submit(&submit, ASYNC_TX_FENCE|ASYNC_TX_XOR_ZERO_DST, tx, +- NULL, sh, flex_array_get(percpu->scribble, 0) +- + sizeof(struct page *) * (sh->disks + 2)); ++ NULL, sh, (void *) (srcs + sh->disks + 2)); + + if (count == 1) + tx = async_memcpy(sh->ppl_page, srcs[0], 0, 0, PAGE_SIZE, +--- a/drivers/md/raid5.c ++++ b/drivers/md/raid5.c +@@ -54,7 +54,6 @@ + #include + #include + #include +-#include + #include + + #include +@@ -1395,22 +1394,16 @@ static void ops_complete_compute(void *s + } + + /* return a pointer to the address conversion region of the scribble buffer */ +-static addr_conv_t *to_addr_conv(struct stripe_head *sh, +- struct raid5_percpu *percpu, int i) ++static struct page **to_addr_page(struct raid5_percpu *percpu, int i) + { +- void *addr; +- +- addr = flex_array_get(percpu->scribble, i); +- return addr + sizeof(struct page *) * (sh->disks + 2); ++ return percpu->scribble + i * percpu->scribble_obj_size; + } + + /* return a pointer to the address conversion region of the scribble buffer */ +-static struct page **to_addr_page(struct raid5_percpu *percpu, int i) ++static addr_conv_t *to_addr_conv(struct stripe_head *sh, ++ struct raid5_percpu *percpu, int i) + { +- void *addr; +- +- addr = flex_array_get(percpu->scribble, i); +- return addr; ++ return (void *) (to_addr_page(percpu, i) + sh->disks + 2); + } + + static struct dma_async_tx_descriptor * +@@ -2239,21 +2232,23 @@ static int grow_stripes(struct r5conf *c + * calculate over all devices (not just the data blocks), using zeros in place + * of the P and Q blocks. + */ +-static struct flex_array *scribble_alloc(int num, int cnt, gfp_t flags) ++static int scribble_alloc(struct raid5_percpu *percpu, ++ int num, int cnt, gfp_t flags) + { +- struct flex_array *ret; +- size_t len; ++ size_t obj_size = ++ sizeof(struct page *) * (num+2) + ++ sizeof(addr_conv_t) * (num+2); ++ void *scribble; + +- len = sizeof(struct page *) * (num+2) + sizeof(addr_conv_t) * (num+2); +- ret = flex_array_alloc(len, cnt, flags); +- if (!ret) +- return NULL; +- /* always prealloc all elements, so no locking is required */ +- if (flex_array_prealloc(ret, 0, cnt, flags)) { +- flex_array_free(ret); +- return NULL; +- } +- return ret; ++ scribble = kvmalloc_array(cnt, obj_size, flags); ++ if (!scribble) ++ return -ENOMEM; ++ ++ kvfree(percpu->scribble); ++ ++ percpu->scribble = scribble; ++ percpu->scribble_obj_size = obj_size; ++ return 0; + } + + static int resize_chunks(struct r5conf *conf, int new_disks, int new_sectors) +@@ -2271,23 +2266,18 @@ static int resize_chunks(struct r5conf * + return 0; + mddev_suspend(conf->mddev); + get_online_cpus(); ++ + for_each_present_cpu(cpu) { + struct raid5_percpu *percpu; +- struct flex_array *scribble; + + percpu = per_cpu_ptr(conf->percpu, cpu); +- scribble = scribble_alloc(new_disks, +- new_sectors / STRIPE_SECTORS, +- GFP_NOIO); +- +- if (scribble) { +- flex_array_free(percpu->scribble); +- percpu->scribble = scribble; +- } else { +- err = -ENOMEM; ++ err = scribble_alloc(percpu, new_disks, ++ new_sectors / STRIPE_SECTORS, ++ GFP_NOIO); ++ if (err) + break; +- } + } ++ + put_online_cpus(); + mddev_resume(conf->mddev); + if (!err) { +@@ -6741,25 +6731,26 @@ raid5_size(struct mddev *mddev, sector_t + static void free_scratch_buffer(struct r5conf *conf, struct raid5_percpu *percpu) + { + safe_put_page(percpu->spare_page); +- if (percpu->scribble) +- flex_array_free(percpu->scribble); + percpu->spare_page = NULL; ++ kvfree(percpu->scribble); + percpu->scribble = NULL; + } + + static int alloc_scratch_buffer(struct r5conf *conf, struct raid5_percpu *percpu) + { +- if (conf->level == 6 && !percpu->spare_page) ++ if (conf->level == 6 && !percpu->spare_page) { + percpu->spare_page = alloc_page(GFP_KERNEL); +- if (!percpu->scribble) +- percpu->scribble = scribble_alloc(max(conf->raid_disks, +- conf->previous_raid_disks), +- max(conf->chunk_sectors, +- conf->prev_chunk_sectors) +- / STRIPE_SECTORS, +- GFP_KERNEL); ++ if (!percpu->spare_page) ++ return -ENOMEM; ++ } + +- if (!percpu->scribble || (conf->level == 6 && !percpu->spare_page)) { ++ if (scribble_alloc(percpu, ++ max(conf->raid_disks, ++ conf->previous_raid_disks), ++ max(conf->chunk_sectors, ++ conf->prev_chunk_sectors) ++ / STRIPE_SECTORS, ++ GFP_KERNEL)) { + free_scratch_buffer(conf, percpu); + return -ENOMEM; + } +--- a/drivers/md/raid5.h ++++ b/drivers/md/raid5.h +@@ -637,10 +637,11 @@ struct r5conf { + /* per cpu variables */ + struct raid5_percpu { + struct page *spare_page; /* Used when checking P/Q in raid6 */ +- struct flex_array *scribble; /* space for constructing buffer +- * lists and performing address +- * conversions +- */ ++ void *scribble; /* space for constructing buffer ++ * lists and performing address ++ * conversions ++ */ ++ int scribble_obj_size; + } __percpu *percpu; + int scribble_disks; + int scribble_sectors; diff --git a/patches.suse/0037-raid5-set-write-hint-for-PPL.patch b/patches.suse/0037-raid5-set-write-hint-for-PPL.patch new file mode 100644 index 0000000..f09239a --- /dev/null +++ b/patches.suse/0037-raid5-set-write-hint-for-PPL.patch @@ -0,0 +1,170 @@ +From a596d08677320925b69e70c0fdc4c0f59384a65e Mon Sep 17 00:00:00 2001 +From: Mariusz Dabrowski +Date: Mon, 18 Feb 2019 15:04:09 +0100 +Subject: [PATCH] raid5: set write hint for PPL +Git-commit: a596d08677320925b69e70c0fdc4c0f59384a65e +Patch-mainline: v5.1-rc1 +References: bsc#1166003 + +When the Partial Parity Log is enabled, circular buffer is used to store +PPL data. Each write to RAID device causes overwrite of data in this buffer +so some write_hint can be set to those request to help drives handle +garbage collection. This patch adds new sysfs attribute which can be used +to specify which write_hint should be assigned to PPL. + +Acked-by: Guoqing Jiang +Signed-off-by: Mariusz Dabrowski +Signed-off-by: Song Liu +Signed-off-by: Coly Li + +--- + Documentation/admin-guide/md.rst | 3 + + drivers/md/md.h | 1 + drivers/md/raid5-log.h | 1 + drivers/md/raid5-ppl.c | 63 +++++++++++++++++++++++++++++++++++++++ + drivers/md/raid5.c | 1 + 5 files changed, 69 insertions(+) + +--- a/Documentation/admin-guide/md.rst ++++ b/Documentation/admin-guide/md.rst +@@ -756,3 +756,6 @@ These currently include: + The cache mode for raid5. raid5 could include an extra disk for + caching. The mode can be "write-throuth" and "write-back". The + default is "write-through". ++ ++ ppl_write_hint ++ NVMe stream ID to be set for each PPL write request. +--- a/drivers/md/md.h ++++ b/drivers/md/md.h +@@ -25,6 +25,7 @@ + #include + #include + #include ++#include + #include "md-cluster.h" + + #define MaxSector (~(sector_t)0) +--- a/drivers/md/raid5-log.h ++++ b/drivers/md/raid5-log.h +@@ -44,6 +44,7 @@ extern void ppl_stripe_write_finished(st + extern int ppl_modify_log(struct r5conf *conf, struct md_rdev *rdev, bool add); + extern void ppl_quiesce(struct r5conf *conf, int quiesce); + extern int ppl_handle_flush_request(struct r5l_log *log, struct bio *bio); ++extern struct md_sysfs_entry ppl_write_hint; + + static inline bool raid5_has_log(struct r5conf *conf) + { +--- a/drivers/md/raid5-ppl.c ++++ b/drivers/md/raid5-ppl.c +@@ -20,6 +20,7 @@ + #include + #include "md.h" + #include "raid5.h" ++#include "raid5-log.h" + + /* + * PPL consists of a 4KB header (struct ppl_header) and at least 128KB for +@@ -115,6 +116,8 @@ struct ppl_conf { + /* stripes to retry if failed to allocate io_unit */ + struct list_head no_mem_stripes; + spinlock_t no_mem_stripes_lock; ++ ++ unsigned short write_hint; + }; + + struct ppl_log { +@@ -474,6 +477,7 @@ static void ppl_submit_iounit(struct ppl + bio_set_dev(bio, log->rdev->bdev); + bio->bi_iter.bi_sector = log->next_io_sector; + bio_add_page(bio, io->header_page, PAGE_SIZE, 0); ++ bio->bi_write_hint = ppl_conf->write_hint; + + pr_debug("%s: log->current_io_sector: %llu\n", __func__, + (unsigned long long)log->next_io_sector); +@@ -503,6 +507,7 @@ static void ppl_submit_iounit(struct ppl + bio = bio_alloc_bioset(GFP_NOIO, BIO_MAX_PAGES, + ppl_conf->bs); + bio->bi_opf = prev->bi_opf; ++ bio->bi_write_hint = prev->bi_write_hint; + bio_copy_dev(bio, prev); + bio->bi_iter.bi_sector = bio_end_sector(prev); + bio_add_page(bio, sh->ppl_page, PAGE_SIZE, 0); +@@ -1415,6 +1420,7 @@ int ppl_init_log(struct r5conf *conf) + atomic64_set(&ppl_conf->seq, 0); + INIT_LIST_HEAD(&ppl_conf->no_mem_stripes); + spin_lock_init(&ppl_conf->no_mem_stripes_lock); ++ ppl_conf->write_hint = RWF_WRITE_LIFE_NOT_SET; + + if (!mddev->external) { + ppl_conf->signature = ~crc32c_le(~0, mddev->uuid, sizeof(mddev->uuid)); +@@ -1509,3 +1515,60 @@ int ppl_modify_log(struct r5conf *conf, + + return ret; + } ++ ++static ssize_t ++ppl_write_hint_show(struct mddev *mddev, char *buf) ++{ ++ size_t ret = 0; ++ struct r5conf *conf; ++ struct ppl_conf *ppl_conf = NULL; ++ ++ spin_lock(&mddev->lock); ++ conf = mddev->private; ++ if (conf && raid5_has_ppl(conf)) ++ ppl_conf = conf->log_private; ++ ret = sprintf(buf, "%d\n", ppl_conf ? ppl_conf->write_hint : 0); ++ spin_unlock(&mddev->lock); ++ ++ return ret; ++} ++ ++static ssize_t ++ppl_write_hint_store(struct mddev *mddev, const char *page, size_t len) ++{ ++ struct r5conf *conf; ++ struct ppl_conf *ppl_conf; ++ int err = 0; ++ unsigned short new; ++ ++ if (len >= PAGE_SIZE) ++ return -EINVAL; ++ if (kstrtou16(page, 10, &new)) ++ return -EINVAL; ++ ++ err = mddev_lock(mddev); ++ if (err) ++ return err; ++ ++ conf = mddev->private; ++ if (!conf) { ++ err = -ENODEV; ++ } else if (raid5_has_ppl(conf)) { ++ ppl_conf = conf->log_private; ++ if (!ppl_conf) ++ err = -EINVAL; ++ else ++ ppl_conf->write_hint = new; ++ } else { ++ err = -EINVAL; ++ } ++ ++ mddev_unlock(mddev); ++ ++ return err ?: len; ++} ++ ++struct md_sysfs_entry ++ppl_write_hint = __ATTR(ppl_write_hint, S_IRUGO | S_IWUSR, ++ ppl_write_hint_show, ++ ppl_write_hint_store); +--- a/drivers/md/raid5.c ++++ b/drivers/md/raid5.c +@@ -6649,6 +6649,7 @@ static struct attribute *raid5_attrs[] = + &raid5_skip_copy.attr, + &raid5_rmw_level.attr, + &r5c_journal_mode.attr, ++ &ppl_write_hint.attr, + NULL, + }; + static struct attribute_group raid5_attrs_group = { diff --git a/patches.suse/0038-md-add-a-missing-endianness-conversion-in-check_sb_c.patch b/patches.suse/0038-md-add-a-missing-endianness-conversion-in-check_sb_c.patch new file mode 100644 index 0000000..e713f4b --- /dev/null +++ b/patches.suse/0038-md-add-a-missing-endianness-conversion-in-check_sb_c.patch @@ -0,0 +1,38 @@ +From ed4d0a4ea11e19863952ac6a7cea3bbb27ccd452 Mon Sep 17 00:00:00 2001 +From: Christoph Hellwig +Date: Thu, 4 Apr 2019 18:56:10 +0200 +Subject: [PATCH] md: add a missing endianness conversion in check_sb_changes +Git-commit: ed4d0a4ea11e19863952ac6a7cea3bbb27ccd452 +Patch-mainline: v5.2-rc1 +References: bsc#1166003 + +The on-disk value is little endian and we need to convert it to +native endian before storing the value in the in-core structure. + +Fixes: 7564beda19b36 ("md-cluster/raid10: support add disk under grow mode") +Cc: # 4.20+ +Acked-by: Guoqing Jiang +Signed-off-by: Christoph Hellwig +Signed-off-by: Song Liu +Signed-off-by: Coly Li + +--- + drivers/md/md.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/md/md.c b/drivers/md/md.c +index 664b77ceaf2d..a15eb7e37c6d 100644 +--- a/drivers/md/md.c ++++ b/drivers/md/md.c +@@ -9227,7 +9227,7 @@ static void check_sb_changes(struct mddev *mddev, struct md_rdev *rdev) + * reshape is happening in the remote node, we need to + * update reshape_position and call start_reshape. + */ +- mddev->reshape_position = sb->reshape_position; ++ mddev->reshape_position = le64_to_cpu(sb->reshape_position); + if (mddev->pers->update_reshape_pos) + mddev->pers->update_reshape_pos(mddev); + if (mddev->pers->start_reshape) +-- +2.25.0 + diff --git a/patches.suse/0039-lib-raid6-altivec-Add-vpermxor-implementation-for-ra.patch b/patches.suse/0039-lib-raid6-altivec-Add-vpermxor-implementation-for-ra.patch deleted file mode 100644 index 4c0632e..0000000 --- a/patches.suse/0039-lib-raid6-altivec-Add-vpermxor-implementation-for-ra.patch +++ /dev/null @@ -1,292 +0,0 @@ -From 751ba79cc552c146595cd439b21c4ff8998c3b69 Mon Sep 17 00:00:00 2001 -From: Matt Brown -Date: Fri, 4 Aug 2017 13:42:32 +1000 -Subject: [PATCH] lib/raid6/altivec: Add vpermxor implementation for raid6 Q - syndrome -Git-commit: 751ba79cc552c146595cd439b21c4ff8998c3b69 -References: bsc#1111974 -Patch-mainline: v4.17-rc1 - -This patch uses the vpermxor instruction to optimise the raid6 Q -syndrome. This instruction was made available with POWER8, ISA version -2.07. It allows for both vperm and vxor instructions to be done in a -single instruction. This has been tested for correctness on a ppc64le -vm with a basic RAID6 setup containing 5 drives. - -The performance benchmarks are from the raid6test in the -/lib/raid6/test directory. These results are from an IBM Firestone -machine with ppc64le architecture. The benchmark results show a 35% -speed increase over the best existing algorithm for powerpc (altivec). -The raid6test has also been run on a big-endian ppc64 vm to ensure it -also works for big-endian architectures. - -Performance benchmarks: - raid6: altivecx4 gen() 18773 MB/s - raid6: altivecx8 gen() 19438 MB/s - - raid6: vpermxor4 gen() 25112 MB/s - raid6: vpermxor8 gen() 26279 MB/s - -Signed-off-by: Matt Brown -Reviewed-by: Daniel Axtens -[mpe: Add VPERMXOR macro so we can build with old binutils] -Signed-off-by: Michael Ellerman -Signed-off-by: Coly Li - ---- - arch/powerpc/include/asm/ppc-opcode.h | 6 + - include/linux/raid/pq.h | 4 + - lib/raid6/.gitignore | 1 - lib/raid6/Makefile | 27 ++++++++ - lib/raid6/algos.c | 4 + - lib/raid6/test/Makefile | 17 ++++- - lib/raid6/vpermxor.uc | 105 ++++++++++++++++++++++++++++++++++ - 7 files changed, 161 insertions(+), 3 deletions(-) - create mode 100644 lib/raid6/vpermxor.uc - ---- a/arch/powerpc/include/asm/ppc-opcode.h -+++ b/arch/powerpc/include/asm/ppc-opcode.h -@@ -261,6 +261,7 @@ - #define PPC_INST_TLBSRX_DOT 0x7c0006a5 - #define PPC_INST_VPMSUMW 0x10000488 - #define PPC_INST_VPMSUMD 0x100004c8 -+#define PPC_INST_VPERMXOR 0x1000002d - #define PPC_INST_XXLOR 0xf0000490 - #define PPC_INST_XXSWAPD 0xf0000250 - #define PPC_INST_XVCPSGNDP 0xf0000780 -@@ -495,6 +496,11 @@ - #define XVCPSGNDP(t, a, b) stringify_in_c(.long (PPC_INST_XVCPSGNDP | \ - VSX_XX3((t), (a), (b)))) - -+#define VPERMXOR(vrt, vra, vrb, vrc) \ -+ stringify_in_c(.long (PPC_INST_VPERMXOR | \ -+ ___PPC_RT(vrt) | ___PPC_RA(vra) | \ -+ ___PPC_RB(vrb) | (((vrc) & 0x1f) << 6))) -+ - #define PPC_NAP stringify_in_c(.long PPC_INST_NAP) - #define PPC_SLEEP stringify_in_c(.long PPC_INST_SLEEP) - #define PPC_WINKLE stringify_in_c(.long PPC_INST_WINKLE) ---- a/include/linux/raid/pq.h -+++ b/include/linux/raid/pq.h -@@ -106,6 +106,10 @@ extern const struct raid6_calls raid6_av - extern const struct raid6_calls raid6_avx512x2; - extern const struct raid6_calls raid6_avx512x4; - extern const struct raid6_calls raid6_s390vx8; -+extern const struct raid6_calls raid6_vpermxor1; -+extern const struct raid6_calls raid6_vpermxor2; -+extern const struct raid6_calls raid6_vpermxor4; -+extern const struct raid6_calls raid6_vpermxor8; - - struct raid6_recov_calls { - void (*data2)(int, size_t, int, int, void **); ---- a/lib/raid6/.gitignore -+++ b/lib/raid6/.gitignore -@@ -4,3 +4,4 @@ int*.c - tables.c - neon?.c - s390vx?.c -+vpermxor*.c ---- a/lib/raid6/Makefile -+++ b/lib/raid6/Makefile -@@ -4,7 +4,8 @@ raid6_pq-y += algos.o recov.o tables.o i - int8.o int16.o int32.o - - raid6_pq-$(CONFIG_X86) += recov_ssse3.o recov_avx2.o mmx.o sse1.o sse2.o avx2.o avx512.o recov_avx512.o --raid6_pq-$(CONFIG_ALTIVEC) += altivec1.o altivec2.o altivec4.o altivec8.o -+raid6_pq-$(CONFIG_ALTIVEC) += altivec1.o altivec2.o altivec4.o altivec8.o \ -+ vpermxor1.o vpermxor2.o vpermxor4.o vpermxor8.o - raid6_pq-$(CONFIG_KERNEL_MODE_NEON) += neon.o neon1.o neon2.o neon4.o neon8.o recov_neon.o recov_neon_inner.o - raid6_pq-$(CONFIG_S390) += s390vx8.o recov_s390xc.o - -@@ -89,6 +90,30 @@ $(obj)/altivec8.c: UNROLL := 8 - $(obj)/altivec8.c: $(src)/altivec.uc $(src)/unroll.awk FORCE - $(call if_changed,unroll) - -+CFLAGS_vpermxor1.o += $(altivec_flags) -+targets += vpermxor1.c -+$(obj)/vpermxor1.c: UNROLL := 1 -+$(obj)/vpermxor1.c: $(src)/vpermxor.uc $(src)/unroll.awk FORCE -+ $(call if_changed,unroll) -+ -+CFLAGS_vpermxor2.o += $(altivec_flags) -+targets += vpermxor2.c -+$(obj)/vpermxor2.c: UNROLL := 2 -+$(obj)/vpermxor2.c: $(src)/vpermxor.uc $(src)/unroll.awk FORCE -+ $(call if_changed,unroll) -+ -+CFLAGS_vpermxor4.o += $(altivec_flags) -+targets += vpermxor4.c -+$(obj)/vpermxor4.c: UNROLL := 4 -+$(obj)/vpermxor4.c: $(src)/vpermxor.uc $(src)/unroll.awk FORCE -+ $(call if_changed,unroll) -+ -+CFLAGS_vpermxor8.o += $(altivec_flags) -+targets += vpermxor8.c -+$(obj)/vpermxor8.c: UNROLL := 8 -+$(obj)/vpermxor8.c: $(src)/vpermxor.uc $(src)/unroll.awk FORCE -+ $(call if_changed,unroll) -+ - CFLAGS_neon1.o += $(NEON_FLAGS) - targets += neon1.c - $(obj)/neon1.c: UNROLL := 1 ---- a/lib/raid6/algos.c -+++ b/lib/raid6/algos.c -@@ -74,6 +74,10 @@ const struct raid6_calls * const raid6_a - &raid6_altivec2, - &raid6_altivec4, - &raid6_altivec8, -+ &raid6_vpermxor1, -+ &raid6_vpermxor2, -+ &raid6_vpermxor4, -+ &raid6_vpermxor8, - #endif - #if defined(CONFIG_S390) - &raid6_s390vx8, ---- a/lib/raid6/test/Makefile -+++ b/lib/raid6/test/Makefile -@@ -47,7 +47,8 @@ else - gcc -c -x c - >&/dev/null && \ - rm ./-.o && echo yes) - ifeq ($(HAS_ALTIVEC),yes) -- OBJS += altivec1.o altivec2.o altivec4.o altivec8.o -+ OBJS += altivec1.o altivec2.o altivec4.o altivec8.o \ -+ vpermxor1.o vpermxor2.o vpermxor4.o vpermxor8.o - endif - endif - -@@ -94,6 +95,18 @@ altivec4.c: altivec.uc ../unroll.awk - altivec8.c: altivec.uc ../unroll.awk - $(AWK) ../unroll.awk -vN=8 < altivec.uc > $@ - -+vpermxor1.c: vpermxor.uc ../unroll.awk -+ $(AWK) ../unroll.awk -vN=1 < vpermxor.uc > $@ -+ -+vpermxor2.c: vpermxor.uc ../unroll.awk -+ $(AWK) ../unroll.awk -vN=2 < vpermxor.uc > $@ -+ -+vpermxor4.c: vpermxor.uc ../unroll.awk -+ $(AWK) ../unroll.awk -vN=4 < vpermxor.uc > $@ -+ -+vpermxor8.c: vpermxor.uc ../unroll.awk -+ $(AWK) ../unroll.awk -vN=8 < vpermxor.uc > $@ -+ - int1.c: int.uc ../unroll.awk - $(AWK) ../unroll.awk -vN=1 < int.uc > $@ - -@@ -116,7 +129,7 @@ tables.c: mktables - ./mktables > tables.c - - clean: -- rm -f *.o *.a mktables mktables.c *.uc int*.c altivec*.c neon*.c tables.c raid6test -+ rm -f *.o *.a mktables mktables.c *.uc int*.c altivec*.c vpermxor*.c neon*.c tables.c raid6test - - spotless: clean - rm -f *~ ---- /dev/null -+++ b/lib/raid6/vpermxor.uc -@@ -0,0 +1,105 @@ -+/* -+ * Copyright 2017, Matt Brown, IBM Corp. -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License -+ * as published by the Free Software Foundation; either version -+ * 2 of the License, or (at your option) any later version. -+ * -+ * vpermxor$#.c -+ * -+ * Based on H. Peter Anvin's paper - The mathematics of RAID-6 -+ * -+ * $#-way unrolled portable integer math RAID-6 instruction set -+ * This file is postprocessed using unroll.awk -+ * -+ * vpermxor$#.c makes use of the vpermxor instruction to optimise the RAID6 Q -+ * syndrome calculations. -+ * This can be run on systems which have both Altivec and vpermxor instruction. -+ * -+ * This instruction was introduced in POWER8 - ISA v2.07. -+ */ -+ -+#include -+#ifdef CONFIG_ALTIVEC -+ -+#include -+#ifdef __KERNEL__ -+#include -+#include -+#include -+#endif -+ -+typedef vector unsigned char unative_t; -+#define NSIZE sizeof(unative_t) -+ -+static const vector unsigned char gf_low = {0x1e, 0x1c, 0x1a, 0x18, 0x16, 0x14, -+ 0x12, 0x10, 0x0e, 0x0c, 0x0a, 0x08, -+ 0x06, 0x04, 0x02,0x00}; -+static const vector unsigned char gf_high = {0xfd, 0xdd, 0xbd, 0x9d, 0x7d, 0x5d, -+ 0x3d, 0x1d, 0xe0, 0xc0, 0xa0, 0x80, -+ 0x60, 0x40, 0x20, 0x00}; -+ -+static void noinline raid6_vpermxor$#_gen_syndrome_real(int disks, size_t bytes, -+ void **ptrs) -+{ -+ u8 **dptr = (u8 **)ptrs; -+ u8 *p, *q; -+ int d, z, z0; -+ unative_t wp$$, wq$$, wd$$; -+ -+ z0 = disks - 3; /* Highest data disk */ -+ p = dptr[z0+1]; /* XOR parity */ -+ q = dptr[z0+2]; /* RS syndrome */ -+ -+ for (d = 0; d < bytes; d += NSIZE*$#) { -+ wp$$ = wq$$ = *(unative_t *)&dptr[z0][d+$$*NSIZE]; -+ -+ for (z = z0-1; z>=0; z--) { -+ wd$$ = *(unative_t *)&dptr[z][d+$$*NSIZE]; -+ /* P syndrome */ -+ wp$$ = vec_xor(wp$$, wd$$); -+ -+ /* Q syndrome */ -+ asm(VPERMXOR(%0,%1,%2,%3):"=v"(wq$$):"v"(gf_high), "v"(gf_low), "v"(wq$$)); -+ wq$$ = vec_xor(wq$$, wd$$); -+ } -+ *(unative_t *)&p[d+NSIZE*$$] = wp$$; -+ *(unative_t *)&q[d+NSIZE*$$] = wq$$; -+ } -+} -+ -+static void raid6_vpermxor$#_gen_syndrome(int disks, size_t bytes, void **ptrs) -+{ -+ preempt_disable(); -+ enable_kernel_altivec(); -+ -+ raid6_vpermxor$#_gen_syndrome_real(disks, bytes, ptrs); -+ -+ disable_kernel_altivec(); -+ preempt_enable(); -+} -+ -+int raid6_have_altivec_vpermxor(void); -+#if $# == 1 -+int raid6_have_altivec_vpermxor(void) -+{ -+ /* Check if arch has both altivec and the vpermxor instructions */ -+# ifdef __KERNEL__ -+ return (cpu_has_feature(CPU_FTR_ALTIVEC_COMP) && -+ cpu_has_feature(CPU_FTR_ARCH_207S)); -+# else -+ return 1; -+#endif -+ -+} -+#endif -+ -+const struct raid6_calls raid6_vpermxor$# = { -+ raid6_vpermxor$#_gen_syndrome, -+ NULL, -+ raid6_have_altivec_vpermxor, -+ "vpermxor$#", -+ 0 -+}; -+#endif diff --git a/patches.suse/0039-md-use-correct-types-in-md_bitmap_print_sb.patch b/patches.suse/0039-md-use-correct-types-in-md_bitmap_print_sb.patch new file mode 100644 index 0000000..1545b73 --- /dev/null +++ b/patches.suse/0039-md-use-correct-types-in-md_bitmap_print_sb.patch @@ -0,0 +1,41 @@ +From c35403f82ced283807f31eeafc2a7aebf1b20331 Mon Sep 17 00:00:00 2001 +From: Christoph Hellwig +Date: Thu, 4 Apr 2019 18:56:11 +0200 +Subject: [PATCH] md: use correct types in md_bitmap_print_sb +Git-commit: c35403f82ced283807f31eeafc2a7aebf1b20331 +Patch-mainline: v5.2-rc1 +References: bsc#1166003 + +If we want to convert from a little endian format we need to cast +to a little endian type, otherwise sparse will be unhappy. + +Signed-off-by: Christoph Hellwig +Signed-off-by: Song Liu +Signed-off-by: Coly Li + +--- + drivers/md/md-bitmap.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/drivers/md/md-bitmap.c b/drivers/md/md-bitmap.c +index 1cd4f991792c..3a62a46b75c7 100644 +--- a/drivers/md/md-bitmap.c ++++ b/drivers/md/md-bitmap.c +@@ -490,10 +490,10 @@ void md_bitmap_print_sb(struct bitmap *bitmap) + pr_debug(" magic: %08x\n", le32_to_cpu(sb->magic)); + pr_debug(" version: %d\n", le32_to_cpu(sb->version)); + pr_debug(" uuid: %08x.%08x.%08x.%08x\n", +- le32_to_cpu(*(__u32 *)(sb->uuid+0)), +- le32_to_cpu(*(__u32 *)(sb->uuid+4)), +- le32_to_cpu(*(__u32 *)(sb->uuid+8)), +- le32_to_cpu(*(__u32 *)(sb->uuid+12))); ++ le32_to_cpu(*(__le32 *)(sb->uuid+0)), ++ le32_to_cpu(*(__le32 *)(sb->uuid+4)), ++ le32_to_cpu(*(__le32 *)(sb->uuid+8)), ++ le32_to_cpu(*(__le32 *)(sb->uuid+12))); + pr_debug(" events: %llu\n", + (unsigned long long) le64_to_cpu(sb->events)); + pr_debug("events cleared: %llu\n", +-- +2.25.0 + diff --git a/patches.suse/0040-md-use-correct-type-in-super_1_load.patch b/patches.suse/0040-md-use-correct-type-in-super_1_load.patch new file mode 100644 index 0000000..e502495 --- /dev/null +++ b/patches.suse/0040-md-use-correct-type-in-super_1_load.patch @@ -0,0 +1,44 @@ +From 00485d094244db47ae2bf4f738e8d0f8d9f5890f Mon Sep 17 00:00:00 2001 +From: Christoph Hellwig +Date: Thu, 4 Apr 2019 18:56:12 +0200 +Subject: [PATCH] md: use correct type in super_1_load +Git-commit: 00485d094244db47ae2bf4f738e8d0f8d9f5890f +Patch-mainline: v5.2-rc1 +References: bsc#1166003 + +If we want to convert from a little endian format we need to cast +to a little endian type, otherwise sparse will be unhappy. + +Signed-off-by: Christoph Hellwig +Signed-off-by: Song Liu +Signed-off-by: Coly Li + +--- + drivers/md/md.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/md/md.c b/drivers/md/md.c +index a15eb7e37c6d..7a74e2de40b5 100644 +--- a/drivers/md/md.c ++++ b/drivers/md/md.c +@@ -1548,7 +1548,7 @@ static int super_1_load(struct md_rdev *rdev, struct md_rdev *refdev, int minor_ + */ + s32 offset; + sector_t bb_sector; +- u64 *bbp; ++ __le64 *bbp; + int i; + int sectors = le16_to_cpu(sb->bblog_size); + if (sectors > (PAGE_SIZE / 512)) +@@ -1560,7 +1560,7 @@ static int super_1_load(struct md_rdev *rdev, struct md_rdev *refdev, int minor_ + if (!sync_page_io(rdev, bb_sector, sectors << 9, + rdev->bb_page, REQ_OP_READ, 0, true)) + return -EIO; +- bbp = (u64 *)page_address(rdev->bb_page); ++ bbp = (__le64 *)page_address(rdev->bb_page); + rdev->badblocks.shift = sb->bblog_shift; + for (i = 0 ; i < (sectors << (9-3)) ; i++, bbp++) { + u64 bb = le64_to_cpu(*bbp); +-- +2.25.0 + diff --git a/patches.suse/0041-md-use-correct-type-in-super_1_sync.patch b/patches.suse/0041-md-use-correct-type-in-super_1_sync.patch new file mode 100644 index 0000000..82ba374 --- /dev/null +++ b/patches.suse/0041-md-use-correct-type-in-super_1_sync.patch @@ -0,0 +1,35 @@ +From ae50640bebc48f1fc0092f16ea004c7c4d12c985 Mon Sep 17 00:00:00 2001 +From: Christoph Hellwig +Date: Thu, 4 Apr 2019 18:56:13 +0200 +Subject: [PATCH] md: use correct type in super_1_sync +Git-commit: ae50640bebc48f1fc0092f16ea004c7c4d12c985 +Patch-mainline: v5.2-rc1 +References: bsc#1166003 + +If we want to convert from a little endian format we need to cast +to a little endian type, otherwise sparse will be unhappy. + +Signed-off-by: Christoph Hellwig +Signed-off-by: Song Liu +Signed-off-by: Coly Li + +--- + drivers/md/md.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/md/md.c b/drivers/md/md.c +index 7a74e2de40b5..4a31380b0eff 100644 +--- a/drivers/md/md.c ++++ b/drivers/md/md.c +@@ -1872,7 +1872,7 @@ static void super_1_sync(struct mddev *mddev, struct md_rdev *rdev) + md_error(mddev, rdev); + else { + struct badblocks *bb = &rdev->badblocks; +- u64 *bbp = (u64 *)page_address(rdev->bb_page); ++ __le64 *bbp = (__le64 *)page_address(rdev->bb_page); + u64 *p = bb->page; + sb->feature_map |= cpu_to_le32(MD_FEATURE_BAD_BLOCKS); + if (bb->changed) { +-- +2.25.0 + diff --git a/patches.suse/0043-md-add-__acquires-__releases-annotations-to-un-lock_.patch b/patches.suse/0043-md-add-__acquires-__releases-annotations-to-un-lock_.patch new file mode 100644 index 0000000..92118a2 --- /dev/null +++ b/patches.suse/0043-md-add-__acquires-__releases-annotations-to-un-lock_.patch @@ -0,0 +1,45 @@ +From 368ecade0532982c8916a49e66b8105413d8db59 Mon Sep 17 00:00:00 2001 +From: Christoph Hellwig +Date: Thu, 4 Apr 2019 18:56:15 +0200 +Subject: [PATCH] md: add __acquires/__releases annotations to + (un)lock_two_stripes +Git-commit: 368ecade0532982c8916a49e66b8105413d8db59 +Patch-mainline: v5.2-rc1 +References: bsc#1166003 + +This tells sparse that we acquire/release the two stripe locks and +avoids a warning. + +Signed-off-by: Christoph Hellwig +Signed-off-by: Song Liu +Signed-off-by: Coly Li + +--- + drivers/md/raid5.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c +index 364dd2f6fa1b..d794d8745144 100644 +--- a/drivers/md/raid5.c ++++ b/drivers/md/raid5.c +@@ -711,6 +711,8 @@ static bool is_full_stripe_write(struct stripe_head *sh) + } + + static void lock_two_stripes(struct stripe_head *sh1, struct stripe_head *sh2) ++ __acquires(&sh1->stripe_lock) ++ __acquires(&sh2->stripe_lock) + { + if (sh1 > sh2) { + spin_lock_irq(&sh2->stripe_lock); +@@ -722,6 +724,8 @@ static void lock_two_stripes(struct stripe_head *sh1, struct stripe_head *sh2) + } + + static void unlock_two_stripes(struct stripe_head *sh1, struct stripe_head *sh2) ++ __releases(&sh1->stripe_lock) ++ __releases(&sh2->stripe_lock) + { + spin_unlock(&sh1->stripe_lock); + spin_unlock_irq(&sh2->stripe_lock); +-- +2.25.0 + diff --git a/patches.suse/0044-md-add-__acquires-__releases-annotations-to-handle_a.patch b/patches.suse/0044-md-add-__acquires-__releases-annotations-to-handle_a.patch new file mode 100644 index 0000000..6d4fb70 --- /dev/null +++ b/patches.suse/0044-md-add-__acquires-__releases-annotations-to-handle_a.patch @@ -0,0 +1,36 @@ +From efcd487c69b9d968552a6bf80e7839c4f28b419d Mon Sep 17 00:00:00 2001 +From: Christoph Hellwig +Date: Thu, 4 Apr 2019 18:56:16 +0200 +Subject: [PATCH] md: add __acquires/__releases annotations to + handle_active_stripes +Git-commit: efcd487c69b9d968552a6bf80e7839c4f28b419d +Patch-mainline: v5.2-rc1 +References: bsc#1166003 + +This tells sparse that we release and reacquire the device_lock and +avoids a warning. + +Signed-off-by: Christoph Hellwig +Signed-off-by: Song Liu +Signed-off-by: Coly Li + +--- + drivers/md/raid5.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c +index d794d8745144..2b0a715e70c9 100644 +--- a/drivers/md/raid5.c ++++ b/drivers/md/raid5.c +@@ -6159,6 +6159,8 @@ static int retry_aligned_read(struct r5conf *conf, struct bio *raid_bio, + static int handle_active_stripes(struct r5conf *conf, int group, + struct r5worker *worker, + struct list_head *temp_inactive_list) ++ __releases(&conf->device_lock) ++ __acquires(&conf->device_lock) + { + struct stripe_head *batch[MAX_STRIPE_BATCH], *sh; + int i, batch_size = 0, hash; +-- +2.25.0 + diff --git a/patches.suse/0045-md-return-ENODEV-if-rdev-has-no-mddev-assigned.patch b/patches.suse/0045-md-return-ENODEV-if-rdev-has-no-mddev-assigned.patch new file mode 100644 index 0000000..ea9029a --- /dev/null +++ b/patches.suse/0045-md-return-ENODEV-if-rdev-has-no-mddev-assigned.patch @@ -0,0 +1,46 @@ +From c42d3240990814eec1e4b2b93fa0487fc4873aed Mon Sep 17 00:00:00 2001 +From: Pawel Baldysiak +Date: Wed, 27 Mar 2019 13:48:21 +0100 +Subject: [PATCH] md: return -ENODEV if rdev has no mddev assigned +Git-commit: c42d3240990814eec1e4b2b93fa0487fc4873aed +Patch-mainline: v5.2-rc1 +References: bsc#1166003 + +Mdadm expects that setting drive as faulty will fail with -EBUSY only if +this operation will cause RAID to be failed. If this happens, it will +try to stop the array. Currently -EBUSY might also be returned if rdev +is in the middle of the removal process - for example there is a race +with mdmon that already requested the drive to be failed/removed. + +If rdev does not contain mddev, return -ENODEV instead, so the caller +can distinguish between those two cases and behave accordingly. + +Reviewed-by: NeilBrown +Signed-off-by: Pawel Baldysiak +Signed-off-by: Song Liu +Signed-off-by: Coly Li + +--- + drivers/md/md.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/md/md.c b/drivers/md/md.c +index 541015373f6a..45ffa23fa85d 100644 +--- a/drivers/md/md.c ++++ b/drivers/md/md.c +@@ -3380,10 +3380,10 @@ rdev_attr_store(struct kobject *kobj, struct attribute *attr, + return -EIO; + if (!capable(CAP_SYS_ADMIN)) + return -EACCES; +- rv = mddev ? mddev_lock(mddev): -EBUSY; ++ rv = mddev ? mddev_lock(mddev) : -ENODEV; + if (!rv) { + if (rdev->mddev == NULL) +- rv = -EBUSY; ++ rv = -ENODEV; + else + rv = entry->store(rdev, page, length); + mddev_unlock(mddev); +-- +2.25.0 + diff --git a/patches.suse/0046-md-fix-for-divide-error-in-status_resync.patch b/patches.suse/0046-md-fix-for-divide-error-in-status_resync.patch new file mode 100644 index 0000000..8ddb895 --- /dev/null +++ b/patches.suse/0046-md-fix-for-divide-error-in-status_resync.patch @@ -0,0 +1,93 @@ +From 9642fa73d073527b0cbc337cc17a47d545d82cd2 Mon Sep 17 00:00:00 2001 +From: Mariusz Tkaczyk +Date: Thu, 13 Jun 2019 16:11:41 +0200 +Subject: [PATCH] md: fix for divide error in status_resync +Git-commit: 9642fa73d073527b0cbc337cc17a47d545d82cd2 +Patch-mainline: v5.2-rc6 +References: bsc#1166003 + +Stopping external metadata arrays during resync/recovery causes +retries, loop of interrupting and starting reconstruction, until it +hit at good moment to stop completely. While these retries +curr_mark_cnt can be small- especially on HDD drives, so subtraction +result can be smaller than 0. However it is casted to uint without +checking. As a result of it the status bar in /proc/mdstat while stopping +is strange (it jumps between 0% and 99%). + +The real problem occurs here after commit 72deb455b5ec ("block: remove +CONFIG_LBDAF"). Sector_div() macro has been changed, now the +divisor is casted to uint32. For db = -8 the divisior(db/32-1) becomes 0. + +Check if db value can be really counted and replace these macro by +div64_u64() inline. + +Signed-off-by: Mariusz Tkaczyk +Signed-off-by: Song Liu +Signed-off-by: Coly Li + +--- + drivers/md/md.c | 36 ++++++++++++++++++++++-------------- + 1 file changed, 22 insertions(+), 14 deletions(-) + +diff --git a/drivers/md/md.c b/drivers/md/md.c +index 04f4f131f9d6..9801d540fea1 100644 +--- a/drivers/md/md.c ++++ b/drivers/md/md.c +@@ -7607,9 +7607,9 @@ static void status_unused(struct seq_file *seq) + static int status_resync(struct seq_file *seq, struct mddev *mddev) + { + sector_t max_sectors, resync, res; +- unsigned long dt, db; +- sector_t rt; +- int scale; ++ unsigned long dt, db = 0; ++ sector_t rt, curr_mark_cnt, resync_mark_cnt; ++ int scale, recovery_active; + unsigned int per_milli; + + if (test_bit(MD_RECOVERY_SYNC, &mddev->recovery) || +@@ -7698,22 +7698,30 @@ static int status_resync(struct seq_file *seq, struct mddev *mddev) + * db: blocks written from mark until now + * rt: remaining time + * +- * rt is a sector_t, so could be 32bit or 64bit. +- * So we divide before multiply in case it is 32bit and close +- * to the limit. +- * We scale the divisor (db) by 32 to avoid losing precision +- * near the end of resync when the number of remaining sectors +- * is close to 'db'. +- * We then divide rt by 32 after multiplying by db to compensate. +- * The '+1' avoids division by zero if db is very small. ++ * rt is a sector_t, which is always 64bit now. We are keeping ++ * the original algorithm, but it is not really necessary. ++ * ++ * Original algorithm: ++ * So we divide before multiply in case it is 32bit and close ++ * to the limit. ++ * We scale the divisor (db) by 32 to avoid losing precision ++ * near the end of resync when the number of remaining sectors ++ * is close to 'db'. ++ * We then divide rt by 32 after multiplying by db to compensate. ++ * The '+1' avoids division by zero if db is very small. + */ + dt = ((jiffies - mddev->resync_mark) / HZ); + if (!dt) dt++; +- db = (mddev->curr_mark_cnt - atomic_read(&mddev->recovery_active)) +- - mddev->resync_mark_cnt; ++ ++ curr_mark_cnt = mddev->curr_mark_cnt; ++ recovery_active = atomic_read(&mddev->recovery_active); ++ resync_mark_cnt = mddev->resync_mark_cnt; ++ ++ if (curr_mark_cnt >= (recovery_active + resync_mark_cnt)) ++ db = curr_mark_cnt - (recovery_active + resync_mark_cnt); + + rt = max_sectors - resync; /* number of remaining sectors */ +- sector_div(rt, db/32+1); ++ rt = div64_u64(rt, db/32+1); + rt *= dt; + rt >>= 5; + +-- +2.25.0 + diff --git a/patches.suse/0047-raid5-cache-Need-to-do-start-part-job-after-adding-j.patch b/patches.suse/0047-raid5-cache-Need-to-do-start-part-job-after-adding-j.patch new file mode 100644 index 0000000..648395d --- /dev/null +++ b/patches.suse/0047-raid5-cache-Need-to-do-start-part-job-after-adding-j.patch @@ -0,0 +1,60 @@ +From d9771f5ec46c282d518b453c793635dbdc3a2a94 Mon Sep 17 00:00:00 2001 +From: Xiao Ni +Date: Fri, 14 Jun 2019 15:41:05 -0700 +Subject: [PATCH] raid5-cache: Need to do start() part job after adding journal + device +Git-commit: d9771f5ec46c282d518b453c793635dbdc3a2a94 +Patch-mainline: v5.3-rc1 +References: bsc#1166003 git-fixes + +commit d5d885fd514f ("md: introduce new personality funciton start()") +splits the init job to two parts. The first part run() does the jobs that +do not require the md threads. The second part start() does the jobs that +require the md threads. + +Now it just does run() in adding new journal device. It needs to do the +second part start() too. + +Fixes: d5d885fd514f ("md: introduce new personality funciton start()") +Cc: stable@vger.kernel.org #v4.9+ +Reported-by: Michal Soltys +Signed-off-by: Xiao Ni +Signed-off-by: Song Liu +Signed-off-by: Jens Axboe +Signed-off-by: Coly Li +--- + drivers/md/raid5.c | 11 +++++++++-- + 1 file changed, 9 insertions(+), 2 deletions(-) + +diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c +index b83bce2beb66..da94cbaa1a9e 100644 +--- a/drivers/md/raid5.c ++++ b/drivers/md/raid5.c +@@ -7672,7 +7672,7 @@ static int raid5_remove_disk(struct mddev *mddev, struct md_rdev *rdev) + static int raid5_add_disk(struct mddev *mddev, struct md_rdev *rdev) + { + struct r5conf *conf = mddev->private; +- int err = -EEXIST; ++ int ret, err = -EEXIST; + int disk; + struct disk_info *p; + int first = 0; +@@ -7687,7 +7687,14 @@ static int raid5_add_disk(struct mddev *mddev, struct md_rdev *rdev) + * The array is in readonly mode if journal is missing, so no + * write requests running. We should be safe + */ +- log_init(conf, rdev, false); ++ ret = log_init(conf, rdev, false); ++ if (ret) ++ return ret; ++ ++ ret = r5l_start(conf->log); ++ if (ret) ++ return ret; ++ + return 0; + } + if (mddev->recovery_disabled == conf->recovery_disabled) +-- +2.16.4 + diff --git a/patches.suse/0048-md-md.c-Return-ENODEV-when-mddev-is-NULL-in-rdev_att.patch b/patches.suse/0048-md-md.c-Return-ENODEV-when-mddev-is-NULL-in-rdev_att.patch new file mode 100644 index 0000000..0b74fb6 --- /dev/null +++ b/patches.suse/0048-md-md.c-Return-ENODEV-when-mddev-is-NULL-in-rdev_att.patch @@ -0,0 +1,38 @@ +From 168b305b0cfb7467a6691993f922ecbdcfc00c98 Mon Sep 17 00:00:00 2001 +From: Marcos Paulo de Souza +Date: Fri, 14 Jun 2019 15:41:06 -0700 +Subject: [PATCH] md: md.c: Return -ENODEV when mddev is NULL in rdev_attr_show +Git-commit: 168b305b0cfb7467a6691993f922ecbdcfc00c98 +Patch-mainline: v5.3-rc1 +References: bsc#1166003 + +Commit c42d3240990814eec1e4b2b93fa0487fc4873aed +("md: return -ENODEV if rdev has no mddev assigned") changed +rdev_attr_store to return -ENODEV when rdev->mddev is NULL, now do the +same to rdev_attr_show. + +Signed-off-by: Marcos Paulo de Souza +Signed-off-by: Song Liu +Signed-off-by: Jens Axboe +Signed-off-by: Coly Li + +--- + drivers/md/md.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/md/md.c b/drivers/md/md.c +index 04f4f131f9d6..86f4f2b5a724 100644 +--- a/drivers/md/md.c ++++ b/drivers/md/md.c +@@ -3356,7 +3356,7 @@ rdev_attr_show(struct kobject *kobj, struct attribute *attr, char *page) + if (!entry->show) + return -EIO; + if (!rdev->mddev) +- return -EBUSY; ++ return -ENODEV; + return entry->show(rdev, page); + } + +-- +2.25.0 + diff --git a/patches.suse/0049-md-fix-spelling-typo-and-add-necessary-space.patch b/patches.suse/0049-md-fix-spelling-typo-and-add-necessary-space.patch new file mode 100644 index 0000000..c8ca6bb --- /dev/null +++ b/patches.suse/0049-md-fix-spelling-typo-and-add-necessary-space.patch @@ -0,0 +1,73 @@ +From e5b521ee9b58c8954ad4d75ccaed9428f4b1a0ca Mon Sep 17 00:00:00 2001 +From: Yufen Yu +Date: Fri, 14 Jun 2019 15:41:07 -0700 +Subject: [PATCH] md: fix spelling typo and add necessary space +Git-commit: e5b521ee9b58c8954ad4d75ccaed9428f4b1a0ca +Patch-mainline: v5.3-rc1 +References: bsc#1166003 + +This patch fix a spelling typo and add necessary space for code. +In addition, the patch get rid of the unnecessary 'if'. + +Signed-off-by: Yufen Yu +Signed-off-by: Song Liu +Signed-off-by: Jens Axboe +Signed-off-by: Coly Li + +--- + drivers/md/md.c | 11 ++++------- + 1 file changed, 4 insertions(+), 7 deletions(-) + +diff --git a/drivers/md/md.c b/drivers/md/md.c +index 86f4f2b5a724..1f37a1adc926 100644 +--- a/drivers/md/md.c ++++ b/drivers/md/md.c +@@ -5639,8 +5639,7 @@ int md_run(struct mddev *mddev) + spin_unlock(&mddev->lock); + rdev_for_each(rdev, mddev) + if (rdev->raid_disk >= 0) +- if (sysfs_link_rdev(mddev, rdev)) +- /* failure here is OK */; ++ sysfs_link_rdev(mddev, rdev); /* failure here is OK */ + + if (mddev->degraded && !mddev->ro) + /* This ensures that recovering status is reported immediately +@@ -8190,8 +8189,7 @@ void md_do_sync(struct md_thread *thread) + { + struct mddev *mddev = thread->mddev; + struct mddev *mddev2; +- unsigned int currspeed = 0, +- window; ++ unsigned int currspeed = 0, window; + sector_t max_sectors,j, io_sectors, recovery_done; + unsigned long mark[SYNC_MARKS]; + unsigned long update_time; +@@ -8248,7 +8246,7 @@ void md_do_sync(struct md_thread *thread) + * 0 == not engaged in resync at all + * 2 == checking that there is no conflict with another sync + * 1 == like 2, but have yielded to allow conflicting resync to +- * commense ++ * commence + * other == active in resync - this many blocks + * + * Before starting a resync we must have set curr_resync to +@@ -8379,7 +8377,7 @@ void md_do_sync(struct md_thread *thread) + /* + * Tune reconstruction: + */ +- window = 32*(PAGE_SIZE/512); ++ window = 32 * (PAGE_SIZE / 512); + pr_debug("md: using %dk window, over a total of %lluk.\n", + window/2, (unsigned long long)max_sectors/2); + +@@ -9192,7 +9190,6 @@ static void check_sb_changes(struct mddev *mddev, struct md_rdev *rdev) + * perform resync with the new activated disk */ + set_bit(MD_RECOVERY_NEEDED, &mddev->recovery); + md_wakeup_thread(mddev->thread); +- + } + /* device faulty + * We just want to do the minimum to mark the disk +-- +2.25.0 + diff --git a/patches.suse/0050-md-raid1-get-rid-of-extra-blank-line-and-space.patch b/patches.suse/0050-md-raid1-get-rid-of-extra-blank-line-and-space.patch new file mode 100644 index 0000000..39e2e54 --- /dev/null +++ b/patches.suse/0050-md-raid1-get-rid-of-extra-blank-line-and-space.patch @@ -0,0 +1,72 @@ +From ebfeb444fa6fd9bc7be62694fff838bc57e19a7d Mon Sep 17 00:00:00 2001 +From: Yufen Yu +Date: Fri, 14 Jun 2019 15:41:08 -0700 +Subject: [PATCH] md/raid1: get rid of extra blank line and space +Git-commit: ebfeb444fa6fd9bc7be62694fff838bc57e19a7d +Patch-mainline: v5.3-rc1 +References: bsc#1166003 + +This patch get rid of extra blank line and space, and +add necessary space for code. + +Signed-off-by: Yufen Yu +Signed-off-by: Song Liu +Signed-off-by: Jens Axboe +Signed-off-by: Coly Li + +--- + drivers/md/raid1.c | 9 +++------ + 1 file changed, 3 insertions(+), 6 deletions(-) + +diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c +index e331b433d00c..869c32fea1b8 100644 +--- a/drivers/md/raid1.c ++++ b/drivers/md/raid1.c +@@ -1424,7 +1424,6 @@ static void raid1_write_request(struct mddev *mddev, struct bio *bio, + if (!r1_bio->bios[i]) + continue; + +- + if (first_clone) { + /* do behind I/O ? + * Not if there are too many, or cannot +@@ -1704,9 +1703,8 @@ static int raid1_add_disk(struct mddev *mddev, struct md_rdev *rdev) + first = last = rdev->saved_raid_disk; + + for (mirror = first; mirror <= last; mirror++) { +- p = conf->mirrors+mirror; ++ p = conf->mirrors + mirror; + if (!p->rdev) { +- + if (mddev->gendisk) + disk_stack_limits(mddev->gendisk, rdev->bdev, + rdev->data_offset << 9); +@@ -2863,7 +2861,6 @@ static sector_t raid1_sync_request(struct mddev *mddev, sector_t sector_nr, + if (read_targets == 1) + bio->bi_opf &= ~MD_FAILFAST; + generic_make_request(bio); +- + } + return nr_sectors; + } +@@ -3064,7 +3061,7 @@ static int raid1_run(struct mddev *mddev) + } + + mddev->degraded = 0; +- for (i=0; i < conf->raid_disks; i++) ++ for (i = 0; i < conf->raid_disks; i++) + if (conf->mirrors[i].rdev == NULL || + !test_bit(In_sync, &conf->mirrors[i].rdev->flags) || + test_bit(Faulty, &conf->mirrors[i].rdev->flags)) +@@ -3099,7 +3096,7 @@ static int raid1_run(struct mddev *mddev) + mddev->queue); + } + +- ret = md_integrity_register(mddev); ++ ret = md_integrity_register(mddev); + if (ret) { + md_unregister_thread(&mddev->thread); + raid1_free(mddev, conf); +-- +2.25.0 + diff --git a/patches.suse/0051-md-raid10-Use-struct_size-in-kmalloc.patch b/patches.suse/0051-md-raid10-Use-struct_size-in-kmalloc.patch new file mode 100644 index 0000000..74c6eda --- /dev/null +++ b/patches.suse/0051-md-raid10-Use-struct_size-in-kmalloc.patch @@ -0,0 +1,52 @@ +From 8cf05a7841e1cfd894741d6bab43067b0ca85eb8 Mon Sep 17 00:00:00 2001 +From: "Gustavo A. R. Silva" +Date: Fri, 14 Jun 2019 15:41:09 -0700 +Subject: [PATCH] md: raid10: Use struct_size() in kmalloc() +Git-commit: 8cf05a7841e1cfd894741d6bab43067b0ca85eb8 +Patch-mainline: v5.3-rc1 +References: bsc#1166003 + +One of the more common cases of allocation size calculations is finding +the size of a structure that has a zero-sized array at the end, along +with memory for some number of elements for that array. For example: + +struct foo { + int stuff; + struct boo entry[]; +}; + +instance = kmalloc(size, GFP_KERNEL); + +Instead of leaving these open-coded and prone to type mistakes, we can +now use the new struct_size() helper: + +instance = kmalloc(struct_size(instance, entry, count), GFP_KERNEL); + +This code was detected with the help of Coccinelle. + +Signed-off-by: Gustavo A. R. Silva +Signed-off-by: Song Liu +Signed-off-by: Jens Axboe +Signed-off-by: Coly Li + +--- + drivers/md/raid10.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c +index 1facd0153399..f35e076ee47d 100644 +--- a/drivers/md/raid10.c ++++ b/drivers/md/raid10.c +@@ -4755,8 +4755,7 @@ static int handle_reshape_read_error(struct mddev *mddev, + int idx = 0; + struct page **pages; + +- r10b = kmalloc(sizeof(*r10b) + +- sizeof(struct r10dev) * conf->copies, GFP_NOIO); ++ r10b = kmalloc(struct_size(r10b, devs, conf->copies), GFP_NOIO); + if (!r10b) { + set_bit(MD_RECOVERY_INTR, &mddev->recovery); + return -ENOMEM; +-- +2.25.0 + diff --git a/patches.suse/0052-md-raid10-read-balance-chooses-idlest-disk-for-SSD.patch b/patches.suse/0052-md-raid10-read-balance-chooses-idlest-disk-for-SSD.patch new file mode 100644 index 0000000..dad78ec --- /dev/null +++ b/patches.suse/0052-md-raid10-read-balance-chooses-idlest-disk-for-SSD.patch @@ -0,0 +1,141 @@ +From e9eeba28a1e01a55b49cdcf9c7a346d2aaa0aa7d Mon Sep 17 00:00:00 2001 +From: Guoqing Jiang +Date: Fri, 14 Jun 2019 15:41:11 -0700 +Subject: [PATCH] md/raid10: read balance chooses idlest disk for SSD +Git-commit: e9eeba28a1e01a55b49cdcf9c7a346d2aaa0aa7d +Patch-mainline: v5.3-rc1 +References: bsc#1166003 + +Andy reported that raid10 array with SSD disks has poor +read performance. Compared with raid1, RAID-1 can be 3x +faster than RAID-10 sometimes [1]. + +The thing is that raid10 chooses the low distance disk +for read request, however, the approach doesn't work +well for SSD device since it doesn't have spindle like +HDD, we should just read from the SSD which has less +pending IO like commit 9dedf60313fa4 ("md/raid1: read +balance chooses idlest disk for SSD"). + +So this commit selects the idlest SSD disk for read if +array has none rotational disk, otherwise, read_balance +uses the previous distance priority algorithm. With the +change, the performance of raid10 gets increased largely +per Andy's test [2]. + +[1]. https://marc.info/?l=linux-raid&m=155915890004761&w=2 +[2]. https://marc.info/?l=linux-raid&m=155990654223786&w=2 + +Tested-by: Andy Smith +Signed-off-by: Guoqing Jiang +Signed-off-by: Song Liu +Signed-off-by: Jens Axboe +Signed-off-by: Coly Li + +--- + drivers/md/raid10.c | 45 +++++++++++++++++++++++++++++++++------------ + 1 file changed, 33 insertions(+), 12 deletions(-) + +diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c +index c9a149b2ec86..8a1354a08a1a 100644 +--- a/drivers/md/raid10.c ++++ b/drivers/md/raid10.c +@@ -707,15 +707,19 @@ static struct md_rdev *read_balance(struct r10conf *conf, + int sectors = r10_bio->sectors; + int best_good_sectors; + sector_t new_distance, best_dist; +- struct md_rdev *best_rdev, *rdev = NULL; ++ struct md_rdev *best_dist_rdev, *best_pending_rdev, *rdev = NULL; + int do_balance; +- int best_slot; ++ int best_dist_slot, best_pending_slot; ++ bool has_nonrot_disk = false; ++ unsigned int min_pending; + struct geom *geo = &conf->geo; + + raid10_find_phys(conf, r10_bio); + rcu_read_lock(); +- best_slot = -1; +- best_rdev = NULL; ++ best_dist_slot = -1; ++ min_pending = UINT_MAX; ++ best_dist_rdev = NULL; ++ best_pending_rdev = NULL; + best_dist = MaxSector; + best_good_sectors = 0; + do_balance = 1; +@@ -737,6 +741,8 @@ static struct md_rdev *read_balance(struct r10conf *conf, + sector_t first_bad; + int bad_sectors; + sector_t dev_sector; ++ unsigned int pending; ++ bool nonrot; + + if (r10_bio->devs[slot].bio == IO_BLOCKED) + continue; +@@ -773,8 +779,8 @@ static struct md_rdev *read_balance(struct r10conf *conf, + first_bad - dev_sector; + if (good_sectors > best_good_sectors) { + best_good_sectors = good_sectors; +- best_slot = slot; +- best_rdev = rdev; ++ best_dist_slot = slot; ++ best_dist_rdev = rdev; + } + if (!do_balance) + /* Must read from here */ +@@ -787,14 +793,23 @@ static struct md_rdev *read_balance(struct r10conf *conf, + if (!do_balance) + break; + +- if (best_slot >= 0) ++ nonrot = blk_queue_nonrot(bdev_get_queue(rdev->bdev)); ++ has_nonrot_disk |= nonrot; ++ pending = atomic_read(&rdev->nr_pending); ++ if (min_pending > pending && nonrot) { ++ min_pending = pending; ++ best_pending_slot = slot; ++ best_pending_rdev = rdev; ++ } ++ ++ if (best_dist_slot >= 0) + /* At least 2 disks to choose from so failfast is OK */ + set_bit(R10BIO_FailFast, &r10_bio->state); + /* This optimisation is debatable, and completely destroys + * sequential read speed for 'far copies' arrays. So only + * keep it for 'near' arrays, and review those later. + */ +- if (geo->near_copies > 1 && !atomic_read(&rdev->nr_pending)) ++ if (geo->near_copies > 1 && !pending) + new_distance = 0; + + /* for far > 1 always use the lowest address */ +@@ -803,15 +818,21 @@ static struct md_rdev *read_balance(struct r10conf *conf, + else + new_distance = abs(r10_bio->devs[slot].addr - + conf->mirrors[disk].head_position); ++ + if (new_distance < best_dist) { + best_dist = new_distance; +- best_slot = slot; +- best_rdev = rdev; ++ best_dist_slot = slot; ++ best_dist_rdev = rdev; + } + } + if (slot >= conf->copies) { +- slot = best_slot; +- rdev = best_rdev; ++ if (has_nonrot_disk) { ++ slot = best_pending_slot; ++ rdev = best_pending_rdev; ++ } else { ++ slot = best_dist_slot; ++ rdev = best_dist_rdev; ++ } + } + + if (slot >= 0) { +-- +2.25.0 + diff --git a/patches.suse/0053-md-raid1-fix-potential-data-inconsistency-issue-with.patch b/patches.suse/0053-md-raid1-fix-potential-data-inconsistency-issue-with.patch new file mode 100644 index 0000000..942ad7c --- /dev/null +++ b/patches.suse/0053-md-raid1-fix-potential-data-inconsistency-issue-with.patch @@ -0,0 +1,250 @@ +From 3e148a3209792e04f63ec99701235c960765fc9a Mon Sep 17 00:00:00 2001 +From: Guoqing Jiang +Date: Wed, 19 Jun 2019 17:30:46 +0800 +Subject: [PATCH] md/raid1: fix potential data inconsistency issue with write + behind device +Git-commit: 3e148a3209792e04f63ec99701235c960765fc9a +Patch-mainline: v5.3-rc1 +References: bsc#1166003 + +For write-behind mode, we think write IO is complete once it has +reached all the non-writemostly devices. It works fine for single +queue devices. + +But for multiqueue device, if there are lots of IOs come from upper +layer, then the write-behind device could issue those IOs to different +queues, depends on the each queue's delay, so there is no guarantee +that those IOs can arrive in order. + +To address the issue, we need to check the collision among write +behind IOs, we can only continue without collision, otherwise wait +for the completion of previous collisioned IO. + +And WBCollision is introduced for multiqueue device which is worked +under write-behind mode. + +But this patch doesn't handle below cases which could have the data +inconsistency issue as well, these cases will be handled in later +patches. + +1. modify max_write_behind by write backlog node. +2. add or remove array's bitmap dynamically. +3. the change of member disk. + +Reviewed-by: NeilBrown +Signed-off-by: Guoqing Jiang +Signed-off-by: Song Liu +Signed-off-by: Coly Li + +--- + drivers/md/md.c | 41 +++++++++++++++++++++++++++++++ + drivers/md/md.h | 21 ++++++++++++++++ + drivers/md/raid1.c | 68 ++++++++++++++++++++++++++++++++++++++++++++++++++++- + 3 files changed, 129 insertions(+), 1 deletion(-) + +--- a/drivers/md/md.c ++++ b/drivers/md/md.c +@@ -130,6 +130,19 @@ static inline int speed_max(struct mddev + mddev->sync_speed_max : sysctl_speed_limit_max; + } + ++static int rdev_init_wb(struct md_rdev *rdev) ++{ ++ if (rdev->bdev->bd_queue->nr_hw_queues == 1) ++ return 0; ++ ++ spin_lock_init(&rdev->wb_list_lock); ++ INIT_LIST_HEAD(&rdev->wb_list); ++ init_waitqueue_head(&rdev->wb_io_wait); ++ set_bit(WBCollisionCheck, &rdev->flags); ++ ++ return 1; ++} ++ + static struct ctl_table_header *raid_table_header; + + static struct ctl_table raid_table[] = { +@@ -5618,6 +5631,32 @@ int md_run(struct mddev *mddev) + md_bitmap_destroy(mddev); + goto abort; + } ++ ++ if (mddev->bitmap_info.max_write_behind > 0) { ++ bool creat_pool = false; ++ ++ rdev_for_each(rdev, mddev) { ++ if (test_bit(WriteMostly, &rdev->flags) && ++ rdev_init_wb(rdev)) ++ creat_pool = true; ++ } ++ if (creat_pool && mddev->wb_info_pool == NULL) { ++ mddev->wb_info_pool = ++ mempool_create_kmalloc_pool(NR_WB_INFOS, ++ sizeof(struct wb_info)); ++ if (!mddev->wb_info_pool) { ++ err = -ENOMEM; ++ mddev_detach(mddev); ++ if (mddev->private) ++ pers->free(mddev, mddev->private); ++ mddev->private = NULL; ++ module_put(pers->owner); ++ md_bitmap_destroy(mddev); ++ goto abort; ++ } ++ } ++ } ++ + if (mddev->queue) { + bool nonrot = true; + +@@ -5853,6 +5892,8 @@ static void __md_stop_writes(struct mdde + mddev->in_sync = 1; + md_update_sb(mddev, 1); + } ++ mempool_destroy(mddev->wb_info_pool); ++ mddev->wb_info_pool = NULL; + } + + void md_stop_writes(struct mddev *mddev) +--- a/drivers/md/md.h ++++ b/drivers/md/md.h +@@ -117,6 +117,14 @@ struct md_rdev { + * for reporting to userspace and storing + * in superblock. + */ ++ ++ /* ++ * The members for check collision of write behind IOs. ++ */ ++ struct list_head wb_list; ++ spinlock_t wb_list_lock; ++ wait_queue_head_t wb_io_wait; ++ + struct work_struct del_work; /* used for delayed sysfs removal */ + + struct kernfs_node *sysfs_state; /* handle for 'state' +@@ -201,6 +209,10 @@ enum flag_bits { + * it didn't fail, so don't use FailFast + * any more for metadata + */ ++ WBCollisionCheck, /* ++ * multiqueue device should check if there ++ * is collision between write behind bios. ++ */ + }; + + static inline int is_badblock(struct md_rdev *rdev, sector_t s, int sectors, +@@ -253,6 +265,14 @@ enum mddev_sb_flags { + MD_SB_NEED_REWRITE, /* metadata write needs to be repeated */ + }; + ++#define NR_WB_INFOS 8 ++/* record current range of write behind IOs */ ++struct wb_info { ++ sector_t lo; ++ sector_t hi; ++ struct list_head list; ++}; ++ + struct mddev { + void *private; + struct md_personality *pers; +@@ -469,6 +489,7 @@ struct mddev { + */ + struct work_struct flush_work; + struct work_struct event_work; /* used by dm to report failure event */ ++ mempool_t *wb_info_pool; + void (*sync_super)(struct mddev *mddev, struct md_rdev *rdev); + struct md_cluster_info *cluster_info; + unsigned int good_device_nr; /* good device num within cluster raid */ +--- a/drivers/md/raid1.c ++++ b/drivers/md/raid1.c +@@ -84,6 +84,57 @@ static void lower_barrier(struct r1conf + + #include "raid1-10.c" + ++static int check_and_add_wb(struct md_rdev *rdev, sector_t lo, sector_t hi) ++{ ++ struct wb_info *wi, *temp_wi; ++ unsigned long flags; ++ int ret = 0; ++ struct mddev *mddev = rdev->mddev; ++ ++ wi = mempool_alloc(mddev->wb_info_pool, GFP_NOIO); ++ ++ spin_lock_irqsave(&rdev->wb_list_lock, flags); ++ list_for_each_entry(temp_wi, &rdev->wb_list, list) { ++ /* collision happened */ ++ if (hi > temp_wi->lo && lo < temp_wi->hi) { ++ ret = -EBUSY; ++ break; ++ } ++ } ++ ++ if (!ret) { ++ wi->lo = lo; ++ wi->hi = hi; ++ list_add(&wi->list, &rdev->wb_list); ++ } else ++ mempool_free(wi, mddev->wb_info_pool); ++ spin_unlock_irqrestore(&rdev->wb_list_lock, flags); ++ ++ return ret; ++} ++ ++static void remove_wb(struct md_rdev *rdev, sector_t lo, sector_t hi) ++{ ++ struct wb_info *wi; ++ unsigned long flags; ++ int found = 0; ++ struct mddev *mddev = rdev->mddev; ++ ++ spin_lock_irqsave(&rdev->wb_list_lock, flags); ++ list_for_each_entry(wi, &rdev->wb_list, list) ++ if (hi == wi->hi && lo == wi->lo) { ++ list_del(&wi->list); ++ mempool_free(wi, mddev->wb_info_pool); ++ found = 1; ++ break; ++ } ++ ++ if (!found) ++ WARN_ON("The write behind IO is not recorded\n"); ++ spin_unlock_irqrestore(&rdev->wb_list_lock, flags); ++ wake_up(&rdev->wb_io_wait); ++} ++ + /* + * for resync bio, r1bio pointer can be retrieved from the per-bio + * 'struct resync_pages'. +@@ -485,6 +536,12 @@ static void raid1_end_write_request(stru + } + + if (behind) { ++ if (test_bit(WBCollisionCheck, &rdev->flags)) { ++ sector_t lo = r1_bio->sector; ++ sector_t hi = r1_bio->sector + r1_bio->sectors; ++ ++ remove_wb(rdev, lo, hi); ++ } + if (test_bit(WriteMostly, &rdev->flags)) + atomic_dec(&r1_bio->behind_remaining); + +@@ -1482,7 +1539,16 @@ static void raid1_write_request(struct m + mbio = bio_clone_fast(bio, GFP_NOIO, mddev->bio_set); + + if (r1_bio->behind_master_bio) { +- if (test_bit(WriteMostly, &conf->mirrors[i].rdev->flags)) ++ struct md_rdev *rdev = conf->mirrors[i].rdev; ++ ++ if (test_bit(WBCollisionCheck, &rdev->flags)) { ++ sector_t lo = r1_bio->sector; ++ sector_t hi = r1_bio->sector + r1_bio->sectors; ++ ++ wait_event(rdev->wb_io_wait, ++ check_and_add_wb(rdev, lo, hi) == 0); ++ } ++ if (test_bit(WriteMostly, &rdev->flags)) + atomic_inc(&r1_bio->behind_remaining); + } + diff --git a/patches.suse/0054-md-introduce-mddev_create-destroy_wb_pool-for-the-ch.patch b/patches.suse/0054-md-introduce-mddev_create-destroy_wb_pool-for-the-ch.patch new file mode 100644 index 0000000..33655be --- /dev/null +++ b/patches.suse/0054-md-introduce-mddev_create-destroy_wb_pool-for-the-ch.patch @@ -0,0 +1,154 @@ +From 963c555e75b033202dd76cf6325a7b7c83d08d5f Mon Sep 17 00:00:00 2001 +From: Guoqing Jiang +Date: Fri, 14 Jun 2019 17:10:36 +0800 +Subject: [PATCH] md: introduce mddev_create/destroy_wb_pool for the change of + member device +Git-commit: 963c555e75b033202dd76cf6325a7b7c83d08d5f +Patch-mainline: v5.3-rc1 +References: bsc#1166003 + +Previously, we called rdev_init_wb to avoid potential data +inconsistency when array is created. + +Now, we need to call the function and create mempool if a +device is added or just be flaged as "writemostly". So +mddev_create_wb_pool is introduced and called accordingly. +And for safety reason, we mark implicit GFP_NOIO allocation +scope for create mempool during mddev_suspend/mddev_resume. + +And mempool should be removed conversely after remove a +member device or its's "writemostly" flag, which is done +by call mddev_destroy_wb_pool. + +Reviewed-by: NeilBrown +Signed-off-by: Guoqing Jiang +Signed-off-by: Song Liu +Signed-off-by: Coly Li + +--- + drivers/md/md.c | 65 +++++++++++++++++++++++++++++++++++++++++++++++++ + drivers/md/md.h | 2 ++ + 2 files changed, 67 insertions(+) + +diff --git a/drivers/md/md.c b/drivers/md/md.c +index 9a9762c83cc8..b43207ab00b2 100644 +--- a/drivers/md/md.c ++++ b/drivers/md/md.c +@@ -37,6 +37,7 @@ + + */ + ++#include + #include + #include + #include +@@ -137,6 +138,64 @@ static int rdev_init_wb(struct md_rdev *rdev) + return 1; + } + ++/* ++ * Create wb_info_pool if rdev is the first multi-queue device flaged ++ * with writemostly, also write-behind mode is enabled. ++ */ ++void mddev_create_wb_pool(struct mddev *mddev, struct md_rdev *rdev, ++ bool is_suspend) ++{ ++ if (mddev->bitmap_info.max_write_behind == 0) ++ return; ++ ++ if (!test_bit(WriteMostly, &rdev->flags) || !rdev_init_wb(rdev)) ++ return; ++ ++ if (mddev->wb_info_pool == NULL) { ++ unsigned int noio_flag; ++ ++ if (!is_suspend) ++ mddev_suspend(mddev); ++ noio_flag = memalloc_noio_save(); ++ mddev->wb_info_pool = mempool_create_kmalloc_pool(NR_WB_INFOS, ++ sizeof(struct wb_info)); ++ memalloc_noio_restore(noio_flag); ++ if (!mddev->wb_info_pool) ++ pr_err("can't alloc memory pool for writemostly\n"); ++ if (!is_suspend) ++ mddev_resume(mddev); ++ } ++} ++EXPORT_SYMBOL_GPL(mddev_create_wb_pool); ++ ++/* ++ * destroy wb_info_pool if rdev is the last device flaged with WBCollisionCheck. ++ */ ++static void mddev_destroy_wb_pool(struct mddev *mddev, struct md_rdev *rdev) ++{ ++ if (!test_and_clear_bit(WBCollisionCheck, &rdev->flags)) ++ return; ++ ++ if (mddev->wb_info_pool) { ++ struct md_rdev *temp; ++ int num = 0; ++ ++ /* ++ * Check if other rdevs need wb_info_pool. ++ */ ++ rdev_for_each(temp, mddev) ++ if (temp != rdev && ++ test_bit(WBCollisionCheck, &temp->flags)) ++ num++; ++ if (!num) { ++ mddev_suspend(rdev->mddev); ++ mempool_destroy(mddev->wb_info_pool); ++ mddev->wb_info_pool = NULL; ++ mddev_resume(rdev->mddev); ++ } ++ } ++} ++ + static struct ctl_table_header *raid_table_header; + + static struct ctl_table raid_table[] = { +@@ -2223,6 +2282,9 @@ static int bind_rdev_to_array(struct md_rdev *rdev, struct mddev *mddev) + rdev->mddev = mddev; + pr_debug("md: bind<%s>\n", b); + ++ if (mddev->raid_disks) ++ mddev_create_wb_pool(mddev, rdev, false); ++ + if ((err = kobject_add(&rdev->kobj, &mddev->kobj, "dev-%s", b))) + goto fail; + +@@ -2259,6 +2321,7 @@ static void unbind_rdev_from_array(struct md_rdev *rdev) + bd_unlink_disk_holder(rdev->bdev, rdev->mddev->gendisk); + list_del_rcu(&rdev->same_set); + pr_debug("md: unbind<%s>\n", bdevname(rdev->bdev,b)); ++ mddev_destroy_wb_pool(rdev->mddev, rdev); + rdev->mddev = NULL; + sysfs_remove_link(&rdev->kobj, "block"); + sysfs_put(rdev->sysfs_state); +@@ -2771,8 +2834,10 @@ state_store(struct md_rdev *rdev, const char *buf, size_t len) + } + } else if (cmd_match(buf, "writemostly")) { + set_bit(WriteMostly, &rdev->flags); ++ mddev_create_wb_pool(rdev->mddev, rdev, false); + err = 0; + } else if (cmd_match(buf, "-writemostly")) { ++ mddev_destroy_wb_pool(rdev->mddev, rdev); + clear_bit(WriteMostly, &rdev->flags); + err = 0; + } else if (cmd_match(buf, "blocked")) { +diff --git a/drivers/md/md.h b/drivers/md/md.h +index d449d514cff9..10f98200e2f8 100644 +--- a/drivers/md/md.h ++++ b/drivers/md/md.h +@@ -730,6 +730,8 @@ extern struct bio *bio_alloc_mddev(gfp_t gfp_mask, int nr_iovecs, + extern void md_reload_sb(struct mddev *mddev, int raid_disk); + extern void md_update_sb(struct mddev *mddev, int force); + extern void md_kick_rdev_from_array(struct md_rdev * rdev); ++extern void mddev_create_wb_pool(struct mddev *mddev, struct md_rdev *rdev, ++ bool is_suspend); + struct md_rdev *md_find_rdev_nr_rcu(struct mddev *mddev, int nr); + struct md_rdev *md_find_rdev_rcu(struct mddev *mddev, dev_t dev); + +-- +2.25.0 + diff --git a/patches.suse/0055-md-bitmap-create-and-destroy-wb_info_pool-with-the-c.patch b/patches.suse/0055-md-bitmap-create-and-destroy-wb_info_pool-with-the-c.patch new file mode 100644 index 0000000..d568eb7 --- /dev/null +++ b/patches.suse/0055-md-bitmap-create-and-destroy-wb_info_pool-with-the-c.patch @@ -0,0 +1,61 @@ +From 10c92fca636e40dcb15d85ffe06b1b6843cd28fc Mon Sep 17 00:00:00 2001 +From: Guoqing Jiang +Date: Fri, 14 Jun 2019 17:10:37 +0800 +Subject: [PATCH] md-bitmap: create and destroy wb_info_pool with the change of + backlog +Git-commit: 10c92fca636e40dcb15d85ffe06b1b6843cd28fc +Patch-mainline: v5.3-rc1 +References: bsc#1166003 + +Since we can enable write-behind mode by write backlog node, +so create wb_info_pool if the mode is just enabled, also call +call md_bitmap_update_sb to make user aware the write-behind +mode is enabled. Conversely, wb_info_pool should be destroyed +when write-behind mode is disabled. + +Beside above, it is better to update bitmap sb if we change +the number of max_write_behind. + +Reviewed-by: NeilBrown +Signed-off-by: Guoqing Jiang +Signed-off-by: Song Liu +Signed-off-by: Coly Li + +--- + drivers/md/md-bitmap.c | 14 ++++++++++++++ + 1 file changed, 14 insertions(+) + +diff --git a/drivers/md/md-bitmap.c b/drivers/md/md-bitmap.c +index c01d41198f5e..15dd817fe83b 100644 +--- a/drivers/md/md-bitmap.c ++++ b/drivers/md/md-bitmap.c +@@ -2462,12 +2462,26 @@ static ssize_t + backlog_store(struct mddev *mddev, const char *buf, size_t len) + { + unsigned long backlog; ++ unsigned long old_mwb = mddev->bitmap_info.max_write_behind; + int rv = kstrtoul(buf, 10, &backlog); + if (rv) + return rv; + if (backlog > COUNTER_MAX) + return -EINVAL; + mddev->bitmap_info.max_write_behind = backlog; ++ if (!backlog && mddev->wb_info_pool) { ++ /* wb_info_pool is not needed if backlog is zero */ ++ mempool_destroy(mddev->wb_info_pool); ++ mddev->wb_info_pool = NULL; ++ } else if (backlog && !mddev->wb_info_pool) { ++ /* wb_info_pool is needed since backlog is not zero */ ++ struct md_rdev *rdev; ++ ++ rdev_for_each(rdev, mddev) ++ mddev_create_wb_pool(mddev, rdev, false); ++ } ++ if (old_mwb != backlog) ++ md_bitmap_update_sb(mddev->bitmap); + return len; + } + +-- +2.25.0 + diff --git a/patches.suse/0056-md-bitmap-create-and-destroy-wb_info_pool-with-the-c.patch b/patches.suse/0056-md-bitmap-create-and-destroy-wb_info_pool-with-the-c.patch new file mode 100644 index 0000000..1928e8f --- /dev/null +++ b/patches.suse/0056-md-bitmap-create-and-destroy-wb_info_pool-with-the-c.patch @@ -0,0 +1,58 @@ +From 617b194a13c0f3b0a6d14fc6227c222877c23b4e Mon Sep 17 00:00:00 2001 +From: Guoqing Jiang +Date: Fri, 14 Jun 2019 17:10:38 +0800 +Subject: [PATCH] md-bitmap: create and destroy wb_info_pool with the change of + bitmap +Git-commit: 617b194a13c0f3b0a6d14fc6227c222877c23b4e +Patch-mainline: v5.3-rc1 +References: bsc#1166003 + +The write-behind attribute is part of bitmap, since bitmap +can be added/removed dynamically with the following. + +1. mdadm --grow /dev/md0 --bitmap=none +2. mdadm --grow /dev/md0 --bitmap=internal --write-behind + +So we need to destroy wb_info_pool in md_bitmap_destroy, +and create the pool before load bitmap. + +Reviewed-by: NeilBrown +Signed-off-by: Guoqing Jiang +Signed-off-by: Song Liu +Signed-off-by: Coly Li + +--- + drivers/md/md-bitmap.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/drivers/md/md-bitmap.c b/drivers/md/md-bitmap.c +index 15dd817fe83b..b092c7b5282f 100644 +--- a/drivers/md/md-bitmap.c ++++ b/drivers/md/md-bitmap.c +@@ -1790,6 +1790,8 @@ void md_bitmap_destroy(struct mddev *mddev) + return; + + md_bitmap_wait_behind_writes(mddev); ++ mempool_destroy(mddev->wb_info_pool); ++ mddev->wb_info_pool = NULL; + + mutex_lock(&mddev->bitmap_info.mutex); + spin_lock(&mddev->lock); +@@ -1900,10 +1902,14 @@ int md_bitmap_load(struct mddev *mddev) + sector_t start = 0; + sector_t sector = 0; + struct bitmap *bitmap = mddev->bitmap; ++ struct md_rdev *rdev; + + if (!bitmap) + goto out; + ++ rdev_for_each(rdev, mddev) ++ mddev_create_wb_pool(mddev, rdev, true); ++ + if (mddev_is_clustered(mddev)) + md_cluster_ops->load_bitmaps(mddev, mddev->bitmap_info.nodes); + +-- +2.25.0 + diff --git a/patches.suse/0057-md-add-bitmap_abort-label-in-md_run.patch b/patches.suse/0057-md-add-bitmap_abort-label-in-md_run.patch new file mode 100644 index 0000000..d5601e3 --- /dev/null +++ b/patches.suse/0057-md-add-bitmap_abort-label-in-md_run.patch @@ -0,0 +1,70 @@ +From d494549ac8852ec42854d1491dd17bb9350a0abc Mon Sep 17 00:00:00 2001 +From: Guoqing Jiang +Date: Fri, 14 Jun 2019 17:10:39 +0800 +Subject: [PATCH] md: add bitmap_abort label in md_run +Git-commit: d494549ac8852ec42854d1491dd17bb9350a0abc +Patch-mainline: v5.3-rc1 +References: bsc#1166003 + +Now, there are two places need to consider about +the failure of destroy bitmap, so move the common +part between bitmap_abort and abort label. + +Reviewed-by: NeilBrown +Signed-off-by: Guoqing Jiang +Signed-off-by: Song Liu +Signed-off-by: Coly Li + +--- + drivers/md/md.c | 26 ++++++++++---------------- + 1 file changed, 10 insertions(+), 16 deletions(-) + +--- a/drivers/md/md.c ++++ b/drivers/md/md.c +@@ -5687,15 +5687,8 @@ int md_run(struct mddev *mddev) + mddev->bitmap = bitmap; + + } +- if (err) { +- mddev_detach(mddev); +- if (mddev->private) +- pers->free(mddev, mddev->private); +- mddev->private = NULL; +- module_put(pers->owner); +- md_bitmap_destroy(mddev); +- goto abort; +- } ++ if (err) ++ goto bitmap_abort; + + if (mddev->bitmap_info.max_write_behind > 0) { + bool creat_pool = false; +@@ -5711,13 +5704,7 @@ int md_run(struct mddev *mddev) + sizeof(struct wb_info)); + if (!mddev->wb_info_pool) { + err = -ENOMEM; +- mddev_detach(mddev); +- if (mddev->private) +- pers->free(mddev, mddev->private); +- mddev->private = NULL; +- module_put(pers->owner); +- md_bitmap_destroy(mddev); +- goto abort; ++ goto bitmap_abort; + } + } + } +@@ -5782,6 +5769,13 @@ int md_run(struct mddev *mddev) + sysfs_notify(&mddev->kobj, NULL, "degraded"); + return 0; + ++bitmap_abort: ++ mddev_detach(mddev); ++ if (mddev->private) ++ pers->free(mddev, mddev->private); ++ mddev->private = NULL; ++ module_put(pers->owner); ++ md_bitmap_destroy(mddev); + abort: + if (mddev->bio_set) { + bioset_free(mddev->bio_set); diff --git a/patches.suse/0058-md-raid1-Fix-a-warning-message-in-remove_wb.patch b/patches.suse/0058-md-raid1-Fix-a-warning-message-in-remove_wb.patch new file mode 100644 index 0000000..22abd6b --- /dev/null +++ b/patches.suse/0058-md-raid1-Fix-a-warning-message-in-remove_wb.patch @@ -0,0 +1,36 @@ +From 16d4b74654ff7c3c5d0b6446278ef51b1de41484 Mon Sep 17 00:00:00 2001 +From: Dan Carpenter +Date: Wed, 26 Jun 2019 12:42:51 +0300 +Subject: [PATCH] md/raid1: Fix a warning message in remove_wb() +Git-commit: 16d4b74654ff7c3c5d0b6446278ef51b1de41484 +Patch-mainline: v5.3-rc1 +References: bsc#1166003 + +The WARN_ON() macro doesn't take an error message, it just takes a +condition. I've changed this to use WARN(1, "...") instead. + +Fixes: 3e148a320979 ("md/raid1: fix potential data inconsistency issue with write behind device") +Signed-off-by: Dan Carpenter +Signed-off-by: Song Liu +Signed-off-by: Coly Li + +--- + drivers/md/raid1.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c +index 3d44da663797..34e26834ad28 100644 +--- a/drivers/md/raid1.c ++++ b/drivers/md/raid1.c +@@ -96,7 +96,7 @@ static void remove_wb(struct md_rdev *rdev, sector_t lo, sector_t hi) + } + + if (!found) +- WARN_ON("The write behind IO is not recorded\n"); ++ WARN(1, "The write behind IO is not recorded\n"); + spin_unlock_irqrestore(&rdev->wb_list_lock, flags); + wake_up(&rdev->wb_io_wait); + } +-- +2.25.0 + diff --git a/patches.suse/0059-raid1-use-an-int-as-the-return-value-of-raise_barrie.patch b/patches.suse/0059-raid1-use-an-int-as-the-return-value-of-raise_barrie.patch new file mode 100644 index 0000000..84dc7a5 --- /dev/null +++ b/patches.suse/0059-raid1-use-an-int-as-the-return-value-of-raise_barrie.patch @@ -0,0 +1,41 @@ +From 4675719d0f47d18bc13db62bd21cffd4e4ec8001 Mon Sep 17 00:00:00 2001 +From: Hou Tao +Date: Tue, 2 Jul 2019 22:35:48 +0800 +Subject: [PATCH] raid1: use an int as the return value of raise_barrier() +Git-commit: 4675719d0f47d18bc13db62bd21cffd4e4ec8001 +Patch-mainline: v5.4-rc1 +References: bsc#1166003 + +Using a sector_t as the return value is misleading, because +raise_barrier() only return 0 or -EINTR. + +Also add comments for the return values of raise_barrier(). + +Signed-off-by: Hou Tao +Signed-off-by: Song Liu +Signed-off-by: Coly Li + +--- + drivers/md/raid1.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c +index 34e26834ad28..108c75006cef 100644 +--- a/drivers/md/raid1.c ++++ b/drivers/md/raid1.c +@@ -872,8 +872,11 @@ static void flush_pending_writes(struct r1conf *conf) + * backgroup IO calls must call raise_barrier. Once that returns + * there is no normal IO happeing. It must arrange to call + * lower_barrier when the particular background IO completes. ++ * ++ * If resync/recovery is interrupted, returns -EINTR; ++ * Otherwise, returns 0. + */ +-static sector_t raise_barrier(struct r1conf *conf, sector_t sector_nr) ++static int raise_barrier(struct r1conf *conf, sector_t sector_nr) + { + int idx = sector_to_idx(sector_nr); + +-- +2.25.0 + diff --git a/patches.suse/0060-md-raid1-end-bio-when-the-device-faulty.patch b/patches.suse/0060-md-raid1-end-bio-when-the-device-faulty.patch new file mode 100644 index 0000000..0f7f10d --- /dev/null +++ b/patches.suse/0060-md-raid1-end-bio-when-the-device-faulty.patch @@ -0,0 +1,75 @@ +From eeba6809d8d58908b5ed1b5ceb5fcb09a98a7cad Mon Sep 17 00:00:00 2001 +From: Yufen Yu +Date: Fri, 19 Jul 2019 13:48:46 +0800 +Subject: [PATCH] md/raid1: end bio when the device faulty +Git-commit: eeba6809d8d58908b5ed1b5ceb5fcb09a98a7cad +Patch-mainline: v5.4-rc1 +References: bsc#1166003 + +When write bio return error, it would be added to conf->retry_list +and wait for raid1d thread to retry write and acknowledge badblocks. + +In narrow_write_error(), the error bio will be split in the unit of +badblock shift (such as one sector) and raid1d thread issues them +one by one. Until all of the splited bio has finished, raid1d thread +can go on processing other things, which is time consuming. + +But, there is a scene for error handling that is not necessary. +When the device has been set faulty, flush_bio_list() may end +bios in pending_bio_list with error status. Since these bios +has not been issued to the device actually, error handlding to +retry write and acknowledge badblocks make no sense. + +Even without that scene, when the device is faulty, badblocks info +can not be written out to the device. Thus, we also no need to +handle the error IO. + +Signed-off-by: Yufen Yu +Signed-off-by: Song Liu +Signed-off-by: Coly Li + +--- + drivers/md/raid1.c | 26 ++++++++++++++------------ + 1 file changed, 14 insertions(+), 12 deletions(-) + +diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c +index 108c75006cef..7ffbd8112400 100644 +--- a/drivers/md/raid1.c ++++ b/drivers/md/raid1.c +@@ -447,19 +447,21 @@ static void raid1_end_write_request(struct bio *bio) + /* We never try FailFast to WriteMostly devices */ + !test_bit(WriteMostly, &rdev->flags)) { + md_error(r1_bio->mddev, rdev); +- if (!test_bit(Faulty, &rdev->flags)) +- /* This is the only remaining device, +- * We need to retry the write without +- * FailFast +- */ +- set_bit(R1BIO_WriteError, &r1_bio->state); +- else { +- /* Finished with this branch */ +- r1_bio->bios[mirror] = NULL; +- to_put = bio; +- } +- } else ++ } ++ ++ /* ++ * When the device is faulty, it is not necessary to ++ * handle write error. ++ * For failfast, this is the only remaining device, ++ * We need to retry the write without FailFast. ++ */ ++ if (!test_bit(Faulty, &rdev->flags)) + set_bit(R1BIO_WriteError, &r1_bio->state); ++ else { ++ /* Finished with this branch */ ++ r1_bio->bios[mirror] = NULL; ++ to_put = bio; ++ } + } else { + /* + * Set R1BIO_Uptodate in our master bio, so that we +-- +2.25.0 + diff --git a/patches.suse/0061-md-raid10-end-bio-when-the-device-faulty.patch b/patches.suse/0061-md-raid10-end-bio-when-the-device-faulty.patch new file mode 100644 index 0000000..b1f6e1a --- /dev/null +++ b/patches.suse/0061-md-raid10-end-bio-when-the-device-faulty.patch @@ -0,0 +1,60 @@ +From 7cee6d4e6035603d42acd56d591e624921aa1b14 Mon Sep 17 00:00:00 2001 +From: Yufen Yu +Date: Fri, 19 Jul 2019 13:48:47 +0800 +Subject: [PATCH] md/raid10: end bio when the device faulty +Git-commit: 7cee6d4e6035603d42acd56d591e624921aa1b14 +Patch-mainline: v5.4-rc1 +References: bsc#1166003 + +Just like raid1, we do not queue write error bio to retry write +and acknowlege badblocks, when the device is faulty. + +Signed-off-by: Yufen Yu +Signed-off-by: Song Liu +Signed-off-by: Coly Li + +--- + drivers/md/raid10.c | 26 ++++++++++++++------------ + 1 file changed, 14 insertions(+), 12 deletions(-) + +diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c +index 8a1354a08a1a..a982e040b609 100644 +--- a/drivers/md/raid10.c ++++ b/drivers/md/raid10.c +@@ -465,19 +465,21 @@ static void raid10_end_write_request(struct bio *bio) + if (test_bit(FailFast, &rdev->flags) && + (bio->bi_opf & MD_FAILFAST)) { + md_error(rdev->mddev, rdev); +- if (!test_bit(Faulty, &rdev->flags)) +- /* This is the only remaining device, +- * We need to retry the write without +- * FailFast +- */ +- set_bit(R10BIO_WriteError, &r10_bio->state); +- else { +- r10_bio->devs[slot].bio = NULL; +- to_put = bio; +- dec_rdev = 1; +- } +- } else ++ } ++ ++ /* ++ * When the device is faulty, it is not necessary to ++ * handle write error. ++ * For failfast, this is the only remaining device, ++ * We need to retry the write without FailFast. ++ */ ++ if (!test_bit(Faulty, &rdev->flags)) + set_bit(R10BIO_WriteError, &r10_bio->state); ++ else { ++ r10_bio->devs[slot].bio = NULL; ++ to_put = bio; ++ dec_rdev = 1; ++ } + } + } else { + /* +-- +2.25.0 + diff --git a/patches.suse/0062-md-allow-last-device-to-be-forcibly-removed-from-RAI.patch b/patches.suse/0062-md-allow-last-device-to-be-forcibly-removed-from-RAI.patch new file mode 100644 index 0000000..268cbf8 --- /dev/null +++ b/patches.suse/0062-md-allow-last-device-to-be-forcibly-removed-from-RAI.patch @@ -0,0 +1,145 @@ +From 9a567843f7ce0037bfd4d5fdc58a09d0a527b28b Mon Sep 17 00:00:00 2001 +From: Guoqing Jiang +Date: Wed, 24 Jul 2019 11:09:19 +0200 +Subject: [PATCH] md: allow last device to be forcibly removed from + RAID1/RAID10. +Git-commit: 9a567843f7ce0037bfd4d5fdc58a09d0a527b28b +Patch-mainline: v5.4-rc1 +References: bsc#1166003 + +When the 'last' device in a RAID1 or RAID10 reports an error, +we do not mark it as failed. This would serve little purpose +as there is no risk of losing data beyond that which is obviously +lost (as there is with RAID5), and there could be other sectors +on the device which are readable, and only readable from this device. +This in general this maximises access to data. + +However the current implementation also stops an admin from removing +the last device by direct action. This is rarely useful, but in many +case is not harmful and can make automation easier by removing special +cases. + +Also, if an attempt to write metadata fails the device must be marked +as faulty, else an infinite loop will result, attempting to update +the metadata on all non-faulty devices. + +So add 'fail_last_dev' member to 'struct mddev', then we can bypasses +the 'last disk' checks for RAID1 and RAID10, and control the behavior +per array by change sysfs node. + +Signed-off-by: NeilBrown +[add sysfs node for fail_last_dev by Guoqing] + +Signed-off-by: Guoqing Jiang +Signed-off-by: Song Liu +Signed-off-by: Coly Li + +--- + drivers/md/md.c | 29 +++++++++++++++++++++++++++++ + drivers/md/md.h | 1 + + drivers/md/raid1.c | 6 +++--- + drivers/md/raid10.c | 6 +++--- + 4 files changed, 36 insertions(+), 6 deletions(-) + +diff --git a/drivers/md/md.c b/drivers/md/md.c +index 3f1252440ad0..67b90d547f8b 100644 +--- a/drivers/md/md.c ++++ b/drivers/md/md.c +@@ -5178,6 +5178,34 @@ static struct md_sysfs_entry md_consistency_policy = + __ATTR(consistency_policy, S_IRUGO | S_IWUSR, consistency_policy_show, + consistency_policy_store); + ++static ssize_t fail_last_dev_show(struct mddev *mddev, char *page) ++{ ++ return sprintf(page, "%d\n", mddev->fail_last_dev); ++} ++ ++/* ++ * Setting fail_last_dev to true to allow last device to be forcibly removed ++ * from RAID1/RAID10. ++ */ ++static ssize_t ++fail_last_dev_store(struct mddev *mddev, const char *buf, size_t len) ++{ ++ int ret; ++ bool value; ++ ++ ret = kstrtobool(buf, &value); ++ if (ret) ++ return ret; ++ ++ if (value != mddev->fail_last_dev) ++ mddev->fail_last_dev = value; ++ ++ return len; ++} ++static struct md_sysfs_entry md_fail_last_dev = ++__ATTR(fail_last_dev, S_IRUGO | S_IWUSR, fail_last_dev_show, ++ fail_last_dev_store); ++ + static struct attribute *md_default_attrs[] = { + &md_level.attr, + &md_layout.attr, +@@ -5194,6 +5222,7 @@ static struct attribute *md_default_attrs[] = { + &md_array_size.attr, + &max_corr_read_errors.attr, + &md_consistency_policy.attr, ++ &md_fail_last_dev.attr, + NULL, + }; + +diff --git a/drivers/md/md.h b/drivers/md/md.h +index 10f98200e2f8..b742659150a2 100644 +--- a/drivers/md/md.h ++++ b/drivers/md/md.h +@@ -487,6 +487,7 @@ struct mddev { + unsigned int good_device_nr; /* good device num within cluster raid */ + + bool has_superblocks:1; ++ bool fail_last_dev:1; + }; + + enum recovery_flags { +diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c +index 7ffbd8112400..cd80f281b95d 100644 +--- a/drivers/md/raid1.c ++++ b/drivers/md/raid1.c +@@ -1617,12 +1617,12 @@ static void raid1_error(struct mddev *mddev, struct md_rdev *rdev) + + /* + * If it is not operational, then we have already marked it as dead +- * else if it is the last working disks, ignore the error, let the +- * next level up know. ++ * else if it is the last working disks with "fail_last_dev == false", ++ * ignore the error, let the next level up know. + * else mark the drive as failed + */ + spin_lock_irqsave(&conf->device_lock, flags); +- if (test_bit(In_sync, &rdev->flags) ++ if (test_bit(In_sync, &rdev->flags) && !mddev->fail_last_dev + && (conf->raid_disks - mddev->degraded) == 1) { + /* + * Don't fail the drive, act as though we were just a +diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c +index a982e040b609..299c7b1c9718 100644 +--- a/drivers/md/raid10.c ++++ b/drivers/md/raid10.c +@@ -1640,12 +1640,12 @@ static void raid10_error(struct mddev *mddev, struct md_rdev *rdev) + + /* + * If it is not operational, then we have already marked it as dead +- * else if it is the last working disks, ignore the error, let the +- * next level up know. ++ * else if it is the last working disks with "fail_last_dev == false", ++ * ignore the error, let the next level up know. + * else mark the drive as failed + */ + spin_lock_irqsave(&conf->device_lock, flags); +- if (test_bit(In_sync, &rdev->flags) ++ if (test_bit(In_sync, &rdev->flags) && !mddev->fail_last_dev + && !enough(conf, rdev->raid_disk)) { + /* + * Don't fail the drive, just return an IO error. +-- +2.25.0 + diff --git a/patches.suse/0063-md-don-t-set-In_sync-if-array-is-frozen.patch b/patches.suse/0063-md-don-t-set-In_sync-if-array-is-frozen.patch new file mode 100644 index 0000000..9cacaf4 --- /dev/null +++ b/patches.suse/0063-md-don-t-set-In_sync-if-array-is-frozen.patch @@ -0,0 +1,55 @@ +From 062f5b2ae12a153644c765e7ba3b0f825427be1d Mon Sep 17 00:00:00 2001 +From: Guoqing Jiang +Date: Wed, 24 Jul 2019 11:09:20 +0200 +Subject: [PATCH] md: don't set In_sync if array is frozen +Git-commit: 062f5b2ae12a153644c765e7ba3b0f825427be1d +Patch-mainline: v5.4-rc1 +References: bsc#1166003 + +When a disk is added to array, the following path is called in mdadm. + +Manage_subdevs -> sysfs_freeze_array + -> Manage_add + -> sysfs_set_str(&info, NULL, "sync_action","idle") + +Then from kernel side, Manage_add invokes the path (add_new_disk -> +validate_super = super_1_validate) to set In_sync flag. + +Since In_sync means "device is in_sync with rest of array", and the new +added disk need to resync thread to help the synchronization of data. +And md_reap_sync_thread would call spare_active to set In_sync for the +new added disk finally. So don't set In_sync if array is in frozen. + +Signed-off-by: Guoqing Jiang +Signed-off-by: Song Liu +Signed-off-by: Coly Li + +--- + drivers/md/md.c | 11 +++++++++-- + 1 file changed, 9 insertions(+), 2 deletions(-) + +diff --git a/drivers/md/md.c b/drivers/md/md.c +index 67b90d547f8b..1cdaa6ff9bd7 100644 +--- a/drivers/md/md.c ++++ b/drivers/md/md.c +@@ -1826,8 +1826,15 @@ static int super_1_validate(struct mddev *mddev, struct md_rdev *rdev) + if (!(le32_to_cpu(sb->feature_map) & + MD_FEATURE_RECOVERY_BITMAP)) + rdev->saved_raid_disk = -1; +- } else +- set_bit(In_sync, &rdev->flags); ++ } else { ++ /* ++ * If the array is FROZEN, then the device can't ++ * be in_sync with rest of array. ++ */ ++ if (!test_bit(MD_RECOVERY_FROZEN, ++ &mddev->recovery)) ++ set_bit(In_sync, &rdev->flags); ++ } + rdev->raid_disk = role; + break; + } +-- +2.25.0 + diff --git a/patches.suse/0064-md-don-t-call-spare_active-in-md_reap_sync_thread-if.patch b/patches.suse/0064-md-don-t-call-spare_active-in-md_reap_sync_thread-if.patch new file mode 100644 index 0000000..b40b3ab --- /dev/null +++ b/patches.suse/0064-md-don-t-call-spare_active-in-md_reap_sync_thread-if.patch @@ -0,0 +1,46 @@ +From 0d8ed0e9bf9643f27f4816dca61081784dedb38d Mon Sep 17 00:00:00 2001 +From: Guoqing Jiang +Date: Wed, 24 Jul 2019 11:09:21 +0200 +Subject: [PATCH] md: don't call spare_active in md_reap_sync_thread if all + member devices can't work +Git-commit: 0d8ed0e9bf9643f27f4816dca61081784dedb38d +Patch-mainline: v5.4-rc1 +References: bsc#1166003 + +When add one disk to array, the md_reap_sync_thread is responsible +to activate the spare and set In_sync flag for the new member in +spare_active(). + +But if raid1 has one member disk A, and disk B is added to the array. +Then we offline A before all the datas are synchronized from A to B, +obviously B doesn't have the latest data as A, but B is still marked +with In_sync flag. + +So let's not call spare_active under the condition, otherwise B is +still showed with 'U' state which is not correct. + +Signed-off-by: Guoqing Jiang +Signed-off-by: Song Liu +Signed-off-by: Coly Li + +--- + drivers/md/md.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/md/md.c b/drivers/md/md.c +index 1cdaa6ff9bd7..daa885ee4d60 100644 +--- a/drivers/md/md.c ++++ b/drivers/md/md.c +@@ -9075,7 +9075,8 @@ void md_reap_sync_thread(struct mddev *mddev) + /* resync has finished, collect result */ + md_unregister_thread(&mddev->sync_thread); + if (!test_bit(MD_RECOVERY_INTR, &mddev->recovery) && +- !test_bit(MD_RECOVERY_REQUESTED, &mddev->recovery)) { ++ !test_bit(MD_RECOVERY_REQUESTED, &mddev->recovery) && ++ mddev->degraded != mddev->raid_disks) { + /* success...*/ + /* activate any spares */ + if (mddev->pers->spare_active(mddev)) { +-- +2.25.0 + diff --git a/patches.suse/0065-raid1-factor-out-a-common-routine-to-handle-the-comp.patch b/patches.suse/0065-raid1-factor-out-a-common-routine-to-handle-the-comp.patch new file mode 100644 index 0000000..48ed73a --- /dev/null +++ b/patches.suse/0065-raid1-factor-out-a-common-routine-to-handle-the-comp.patch @@ -0,0 +1,86 @@ +From 449808a254fd567d3dbeb11595a0af238c687c82 Mon Sep 17 00:00:00 2001 +From: Hou Tao +Date: Sat, 27 Jul 2019 14:02:58 +0800 +Subject: [PATCH] raid1: factor out a common routine to handle the completion + of sync write +Git-commit: 449808a254fd567d3dbeb11595a0af238c687c82 +Patch-mainline: v5.4-rc1 +References: bsc#1166003 + +It's just code clean-up. + +Signed-off-by: Hou Tao +Signed-off-by: Song Liu +Signed-off-by: Coly Li + +--- + drivers/md/raid1.c | 39 ++++++++++++++++++--------------------- + 1 file changed, 18 insertions(+), 21 deletions(-) + +diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c +index cd80f281b95d..6ea4f2679b78 100644 +--- a/drivers/md/raid1.c ++++ b/drivers/md/raid1.c +@@ -1906,6 +1906,22 @@ static void abort_sync_write(struct mddev *mddev, struct r1bio *r1_bio) + } while (sectors_to_go > 0); + } + ++static void put_sync_write_buf(struct r1bio *r1_bio, int uptodate) ++{ ++ if (atomic_dec_and_test(&r1_bio->remaining)) { ++ struct mddev *mddev = r1_bio->mddev; ++ int s = r1_bio->sectors; ++ ++ if (test_bit(R1BIO_MadeGood, &r1_bio->state) || ++ test_bit(R1BIO_WriteError, &r1_bio->state)) ++ reschedule_retry(r1_bio); ++ else { ++ put_buf(r1_bio); ++ md_done_sync(mddev, s, uptodate); ++ } ++ } ++} ++ + static void end_sync_write(struct bio *bio) + { + int uptodate = !bio->bi_status; +@@ -1932,16 +1948,7 @@ static void end_sync_write(struct bio *bio) + ) + set_bit(R1BIO_MadeGood, &r1_bio->state); + +- if (atomic_dec_and_test(&r1_bio->remaining)) { +- int s = r1_bio->sectors; +- if (test_bit(R1BIO_MadeGood, &r1_bio->state) || +- test_bit(R1BIO_WriteError, &r1_bio->state)) +- reschedule_retry(r1_bio); +- else { +- put_buf(r1_bio); +- md_done_sync(mddev, s, uptodate); +- } +- } ++ put_sync_write_buf(r1_bio, uptodate); + } + + static int r1_sync_page_io(struct md_rdev *rdev, sector_t sector, +@@ -2224,17 +2231,7 @@ static void sync_request_write(struct mddev *mddev, struct r1bio *r1_bio) + generic_make_request(wbio); + } + +- if (atomic_dec_and_test(&r1_bio->remaining)) { +- /* if we're here, all write(s) have completed, so clean up */ +- int s = r1_bio->sectors; +- if (test_bit(R1BIO_MadeGood, &r1_bio->state) || +- test_bit(R1BIO_WriteError, &r1_bio->state)) +- reschedule_retry(r1_bio); +- else { +- put_buf(r1_bio); +- md_done_sync(mddev, s, 1); +- } +- } ++ put_sync_write_buf(r1_bio, 1); + } + + /* +-- +2.25.0 + diff --git a/patches.suse/0066-raid5-improve-too-many-read-errors-msg-by-adding-lim.patch b/patches.suse/0066-raid5-improve-too-many-read-errors-msg-by-adding-lim.patch new file mode 100644 index 0000000..a834e4b --- /dev/null +++ b/patches.suse/0066-raid5-improve-too-many-read-errors-msg-by-adding-lim.patch @@ -0,0 +1,52 @@ +From 0009fad033370802de75e4cedab54f4d86450e22 Mon Sep 17 00:00:00 2001 +From: Nigel Croxon +Date: Wed, 21 Aug 2019 09:27:08 -0400 +Subject: [PATCH] raid5 improve too many read errors msg by adding limits +Git-commit: 0009fad033370802de75e4cedab54f4d86450e22 +Patch-mainline: v5.4-rc1 +References: bsc#1166003 + +Often limits can be changed by admin. When discussing such things +it helps if you can provide "self-sustained" facts. Also +sometimes the admin thinks he changed a limit, but it did not +take effect for some reason or he changed the wrong thing. + +V3: Only pr_warn when Faulty is 0. +V2: Add read_errors value to pr_warn. + +Signed-off-by: Nigel Croxon +Signed-off-by: Song Liu +Signed-off-by: Coly Li + +--- + drivers/md/raid5.c | 14 ++++++++++---- + 1 file changed, 10 insertions(+), 4 deletions(-) + +diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c +index 59cafafd5a5d..88e56ee98976 100644 +--- a/drivers/md/raid5.c ++++ b/drivers/md/raid5.c +@@ -2549,10 +2549,16 @@ static void raid5_end_read_request(struct bio * bi) + (unsigned long long)s, + bdn); + } else if (atomic_read(&rdev->read_errors) +- > conf->max_nr_stripes) +- pr_warn("md/raid:%s: Too many read errors, failing device %s.\n", +- mdname(conf->mddev), bdn); +- else ++ > conf->max_nr_stripes) { ++ if (!test_bit(Faulty, &rdev->flags)) { ++ pr_warn("md/raid:%s: %d read_errors > %d stripes\n", ++ mdname(conf->mddev), ++ atomic_read(&rdev->read_errors), ++ conf->max_nr_stripes); ++ pr_warn("md/raid:%s: Too many read errors, failing device %s.\n", ++ mdname(conf->mddev), bdn); ++ } ++ } else + retry = 1; + if (set_bad && test_bit(In_sync, &rdev->flags) + && !test_bit(R5_ReadNoMerge, &sh->dev[i].flags)) +-- +2.25.0 + diff --git a/patches.suse/0067-md-raid0-linear-Mark-array-as-broken-and-fail-BIOs-i.patch b/patches.suse/0067-md-raid0-linear-Mark-array-as-broken-and-fail-BIOs-i.patch new file mode 100644 index 0000000..4d5278c --- /dev/null +++ b/patches.suse/0067-md-raid0-linear-Mark-array-as-broken-and-fail-BIOs-i.patch @@ -0,0 +1,186 @@ +From 62f7b1989c02feed9274131b2fd5e990de4aba6f Mon Sep 17 00:00:00 2001 +From: "Guilherme G. Piccoli" +Date: Tue, 3 Sep 2019 16:49:00 -0300 +Subject: [PATCH] md raid0/linear: Mark array as 'broken' and fail BIOs if a + member is gone +Git-commit: 62f7b1989c02feed9274131b2fd5e990de4aba6f +Patch-mainline: v5.4-rc1 +References: bsc#1166003 + +Currently md raid0/linear are not provided with any mechanism to validate +if an array member got removed or failed. The driver keeps sending BIOs +regardless of the state of array members, and kernel shows state 'clean' +in the 'array_state' sysfs attribute. This leads to the following +Situation: if a raid0/linear array member is removed and the array is +mounted, some user writing to this array won't realize that errors are +happening unless they check dmesg or perform one fsync per written file. +Despite udev signaling the member device is gone, 'mdadm' cannot issue the +STOP_ARRAY ioctl successfully, given the array is mounted. + +In other words, no -EIO is returned and writes (except direct ones) appear +normal. Meaning the user might think the wrote data is correctly stored in +the array, but instead garbage was written given that raid0 does stripping +(and so, it requires all its members to be working in order to not corrupt +data). For md/linear, writes to the available members will work fine, but +if the writes go to the missing member(s), it'll cause a file corruption +situation, whereas the portion of the writes to the missing devices aren't +written effectively. + +This patch changes this behavior: we check if the block device's gendisk +is UP when submitting the BIO to the array member, and if it isn't, we flag +the md device as MD_BROKEN and fail subsequent I/Os to that device; a read +request to the array requiring data from a valid member is still completed. +While flagging the device as MD_BROKEN, we also show a rate-limited warning +in the kernel log. + +A new array state 'broken' was added too: it mimics the state 'clean' in +every aspect, being useful only to distinguish if the array has some member +missing. We rely on the MD_BROKEN flag to put the array in the 'broken' +state. This state cannot be written in 'array_state' as it just shows +one or more members of the array are missing but acts like 'clean', it +wouldn't make sense to write it. + +With this patch, the filesystem reacts much faster to the event of missing +array member: after some I/O errors, ext4 for instance aborts the journal +and prevents corruption. Without this change, we're able to keep writing +in the disk and after a machine reboot, e2fsck shows some severe fs errors +that demand fixing. This patch was tested in ext4 and xfs filesystems, and +requires a 'mdadm' counterpart to handle the 'broken' state. + +Cc: Song Liu +Reviewed-by: NeilBrown +Signed-off-by: Guilherme G. Piccoli +Signed-off-by: Song Liu +Signed-off-by: Coly Li + +--- + drivers/md/md-linear.c | 5 +++++ + drivers/md/md.c | 22 ++++++++++++++++++---- + drivers/md/md.h | 16 ++++++++++++++++ + drivers/md/raid0.c | 6 ++++++ + 4 files changed, 45 insertions(+), 4 deletions(-) + +--- a/drivers/md/md-linear.c ++++ b/drivers/md/md-linear.c +@@ -265,6 +265,11 @@ static bool linear_make_request(struct m + bio_sector < start_sector)) + goto out_of_bounds; + ++ if (unlikely(is_mddev_broken(tmp_dev->rdev, "linear"))) { ++ bio_io_error(bio); ++ return true; ++ } ++ + if (unlikely(bio_end_sector(bio) > end_sector)) { + /* This bio crosses a device boundary, so we have to split it */ + struct bio *split = bio_split(bio, end_sector - bio_sector, +--- a/drivers/md/md.c ++++ b/drivers/md/md.c +@@ -382,6 +382,11 @@ static blk_qc_t md_make_request(struct r + unsigned int sectors; + int cpu; + ++ if (unlikely(test_bit(MD_BROKEN, &mddev->flags)) && (rw == WRITE)) { ++ bio_io_error(bio); ++ return BLK_QC_T_NONE; ++ } ++ + blk_queue_split(q, &bio); + + if (mddev == NULL || mddev->pers == NULL) { +@@ -4182,12 +4187,17 @@ __ATTR_PREALLOC(resync_start, S_IRUGO|S_ + * active-idle + * like active, but no writes have been seen for a while (100msec). + * ++ * broken ++ * RAID0/LINEAR-only: same as clean, but array is missing a member. ++ * It's useful because RAID0/LINEAR mounted-arrays aren't stopped ++ * when a member is gone, so this state will at least alert the ++ * user that something is wrong. + */ + enum array_state { clear, inactive, suspended, readonly, read_auto, clean, active, +- write_pending, active_idle, bad_word}; ++ write_pending, active_idle, broken, bad_word}; + static char *array_states[] = { + "clear", "inactive", "suspended", "readonly", "read-auto", "clean", "active", +- "write-pending", "active-idle", NULL }; ++ "write-pending", "active-idle", "broken", NULL }; + + static int match_word(const char *word, char **list) + { +@@ -4203,7 +4213,7 @@ array_state_show(struct mddev *mddev, ch + { + enum array_state st = inactive; + +- if (mddev->pers && !test_bit(MD_NOT_READY, &mddev->flags)) ++ if (mddev->pers && !test_bit(MD_NOT_READY, &mddev->flags)) { + switch(mddev->ro) { + case 1: + st = readonly; +@@ -4223,7 +4233,10 @@ array_state_show(struct mddev *mddev, ch + st = active; + spin_unlock(&mddev->lock); + } +- else { ++ ++ if (test_bit(MD_BROKEN, &mddev->flags) && st == clean) ++ st = broken; ++ } else { + if (list_empty(&mddev->disks) && + mddev->raid_disks == 0 && + mddev->dev_sectors == 0) +@@ -4337,6 +4350,7 @@ array_state_store(struct mddev *mddev, c + break; + case write_pending: + case active_idle: ++ case broken: + /* these cannot be set */ + break; + } +--- a/drivers/md/md.h ++++ b/drivers/md/md.h +@@ -259,6 +259,9 @@ enum mddev_flags { + MD_NOT_READY, /* do_md_run() is active, so 'array_state' + * must not report that array is ready yet + */ ++ MD_BROKEN, /* This is used in RAID-0/LINEAR only, to stop ++ * I/O in case an array member is gone/failed. ++ */ + }; + + enum mddev_sb_flags { +@@ -747,6 +750,19 @@ extern void mddev_create_wb_pool(struct + struct md_rdev *md_find_rdev_nr_rcu(struct mddev *mddev, int nr); + struct md_rdev *md_find_rdev_rcu(struct mddev *mddev, dev_t dev); + ++static inline bool is_mddev_broken(struct md_rdev *rdev, const char *md_type) ++{ ++ int flags = rdev->bdev->bd_disk->flags; ++ ++ if (!(flags & GENHD_FL_UP)) { ++ if (!test_and_set_bit(MD_BROKEN, &rdev->mddev->flags)) ++ pr_warn("md: %s: %s array has a missing/failed member\n", ++ mdname(rdev->mddev), md_type); ++ return true; ++ } ++ return false; ++} ++ + static inline void rdev_dec_pending(struct md_rdev *rdev, struct mddev *mddev) + { + int faulty = test_bit(Faulty, &rdev->flags); +--- a/drivers/md/raid0.c ++++ b/drivers/md/raid0.c +@@ -590,6 +590,12 @@ static bool raid0_make_request(struct md + + zone = find_zone(mddev->private, §or); + tmp_dev = map_sector(mddev, zone, sector, §or); ++ ++ if (unlikely(is_mddev_broken(tmp_dev, "raid0"))) { ++ bio_io_error(bio); ++ return true; ++ } ++ + bio_set_dev(bio, tmp_dev->bdev); + bio->bi_iter.bi_sector = sector + zone->dev_start + + tmp_dev->data_offset; diff --git a/patches.suse/0068-md-raid1-fail-run-raid1-array-when-active-disk-less-.patch b/patches.suse/0068-md-raid1-fail-run-raid1-array-when-active-disk-less-.patch new file mode 100644 index 0000000..bff87f5 --- /dev/null +++ b/patches.suse/0068-md-raid1-fail-run-raid1-array-when-active-disk-less-.patch @@ -0,0 +1,78 @@ +From 07f1a6850c5d5a65c917c3165692b5179ac4cb6b Mon Sep 17 00:00:00 2001 +From: Yufen Yu +Date: Tue, 3 Sep 2019 21:12:41 +0800 +Subject: [PATCH] md/raid1: fail run raid1 array when active disk less than one +Git-commit: 07f1a6850c5d5a65c917c3165692b5179ac4cb6b +Patch-mainline: v5.4-rc1 +References: bsc#1166003 + +When run test case: + mdadm -CR /dev/md1 -l 1 -n 4 /dev/sd[a-d] --assume-clean --bitmap=internal + mdadm -S /dev/md1 + mdadm -A /dev/md1 /dev/sd[b-c] --run --force + + mdadm --zero /dev/sda + mdadm /dev/md1 -a /dev/sda + + echo offline > /sys/block/sdc/device/state + echo offline > /sys/block/sdb/device/state + sleep 5 + mdadm -S /dev/md1 + + echo running > /sys/block/sdb/device/state + echo running > /sys/block/sdc/device/state + mdadm -A /dev/md1 /dev/sd[a-c] --run --force + +mdadm run fail with kernel message as follow: +[ 172.986064] md: kicking non-fresh sdb from array! +[ 173.004210] md: kicking non-fresh sdc from array! +[ 173.022383] md/raid1:md1: active with 0 out of 4 mirrors +[ 173.022406] md1: failed to create bitmap (-5) + +In fact, when active disk in raid1 array less than one, we +need to return fail in raid1_run(). + +Reviewed-by: NeilBrown +Signed-off-by: Yufen Yu +Signed-off-by: Song Liu +Signed-off-by: Coly Li + +--- + drivers/md/raid1.c | 13 ++++++++++++- + 1 file changed, 12 insertions(+), 1 deletion(-) + +diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c +index 6ea4f2679b78..0466ee2453b4 100644 +--- a/drivers/md/raid1.c ++++ b/drivers/md/raid1.c +@@ -3129,6 +3129,13 @@ static int raid1_run(struct mddev *mddev) + !test_bit(In_sync, &conf->mirrors[i].rdev->flags) || + test_bit(Faulty, &conf->mirrors[i].rdev->flags)) + mddev->degraded++; ++ /* ++ * RAID1 needs at least one disk in active ++ */ ++ if (conf->raid_disks - mddev->degraded < 1) { ++ ret = -EINVAL; ++ goto abort; ++ } + + if (conf->raid_disks - mddev->degraded == 1) + mddev->recovery_cp = MaxSector; +@@ -3162,8 +3169,12 @@ static int raid1_run(struct mddev *mddev) + ret = md_integrity_register(mddev); + if (ret) { + md_unregister_thread(&mddev->thread); +- raid1_free(mddev, conf); ++ goto abort; + } ++ return 0; ++ ++abort: ++ raid1_free(mddev, conf); + return ret; + } + +-- +2.25.0 + diff --git a/patches.suse/0069-md-raid5-use-bio_end_sector-to-calculate-last_sector.patch b/patches.suse/0069-md-raid5-use-bio_end_sector-to-calculate-last_sector.patch new file mode 100644 index 0000000..954b02f --- /dev/null +++ b/patches.suse/0069-md-raid5-use-bio_end_sector-to-calculate-last_sector.patch @@ -0,0 +1,34 @@ +From b0f01ecf293c49d841abbf8b55c4b717936ab11e Mon Sep 17 00:00:00 2001 +From: Guoqing Jiang +Date: Tue, 3 Sep 2019 11:41:03 +0200 +Subject: [PATCH] md/raid5: use bio_end_sector to calculate last_sector +Git-commit: b0f01ecf293c49d841abbf8b55c4b717936ab11e +Patch-mainline: v5.4-rc1 +References: bsc#1166003 + +Use the common way to get last_sector. + +Signed-off-by: Guoqing Jiang +Signed-off-by: Song Liu +Signed-off-by: Coly Li + +--- + drivers/md/raid5.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c +index 88e56ee98976..da6a86e28318 100644 +--- a/drivers/md/raid5.c ++++ b/drivers/md/raid5.c +@@ -5499,7 +5499,7 @@ static void make_discard_request(struct mddev *mddev, struct bio *bi) + return; + + logical_sector = bi->bi_iter.bi_sector & ~((sector_t)STRIPE_SECTORS-1); +- last_sector = bi->bi_iter.bi_sector + (bi->bi_iter.bi_size>>9); ++ last_sector = bio_end_sector(bi); + + bi->bi_next = NULL; + +-- +2.25.0 + diff --git a/patches.suse/0070-raid5-don-t-increment-read_errors-on-EILSEQ-return.patch b/patches.suse/0070-raid5-don-t-increment-read_errors-on-EILSEQ-return.patch new file mode 100644 index 0000000..5e6dd54 --- /dev/null +++ b/patches.suse/0070-raid5-don-t-increment-read_errors-on-EILSEQ-return.patch @@ -0,0 +1,46 @@ +From b76b4715eba0d0ed574f58918b29c1b2f0fa37a8 Mon Sep 17 00:00:00 2001 +From: Nigel Croxon +Date: Fri, 6 Sep 2019 09:21:33 -0400 +Subject: [PATCH] raid5: don't increment read_errors on EILSEQ return +Git-commit: b76b4715eba0d0ed574f58918b29c1b2f0fa37a8 +Patch-mainline: v5.4-rc1 +References: bsc#1166003 + +While MD continues to count read errors returned by the lower layer. +If those errors are -EILSEQ, instead of -EIO, it should NOT increase +the read_errors count. + +When RAID6 is set up on dm-integrity target that detects massive +corruption, the leg will be ejected from the array. Even if the +issue is correctable with a sector re-write and the array has +necessary redundancy to correct it. + +The leg is ejected because it runs up the rdev->read_errors beyond +conf->max_nr_stripes. The return status in dm-drypt when there is +a data integrity error is -EILSEQ (BLK_STS_PROTECTION). + +Signed-off-by: Nigel Croxon +Signed-off-by: Song Liu +Signed-off-by: Coly Li + +--- + drivers/md/raid5.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c +index da6a86e28318..8ea8443e09d5 100644 +--- a/drivers/md/raid5.c ++++ b/drivers/md/raid5.c +@@ -2526,7 +2526,8 @@ static void raid5_end_read_request(struct bio * bi) + int set_bad = 0; + + clear_bit(R5_UPTODATE, &sh->dev[i].flags); +- atomic_inc(&rdev->read_errors); ++ if (!(bi->bi_status == BLK_STS_PROTECTION)) ++ atomic_inc(&rdev->read_errors); + if (test_bit(R5_ReadRepl, &sh->dev[i].flags)) + pr_warn_ratelimited( + "md/raid:%s: read error on replacement device (sector %llu on %s).\n", +-- +2.25.0 + diff --git a/patches.suse/0071-raid5-don-t-set-STRIPE_HANDLE-to-stripe-which-is-in-.patch b/patches.suse/0071-raid5-don-t-set-STRIPE_HANDLE-to-stripe-which-is-in-.patch new file mode 100644 index 0000000..2317ee2 --- /dev/null +++ b/patches.suse/0071-raid5-don-t-set-STRIPE_HANDLE-to-stripe-which-is-in-.patch @@ -0,0 +1,76 @@ +From 6ce220dd2f8ea71d6afc29b9a7524c12e39f374a Mon Sep 17 00:00:00 2001 +From: Guoqing Jiang +Date: Wed, 11 Sep 2019 10:06:29 +0200 +Subject: [PATCH] raid5: don't set STRIPE_HANDLE to stripe which is in batch + list +Git-commit: 6ce220dd2f8ea71d6afc29b9a7524c12e39f374a +Patch-mainline: v5.4-rc1 +References: bsc#1166003 + +If stripe in batch list is set with STRIPE_HANDLE flag, then the stripe +could be set with STRIPE_ACTIVE by the handle_stripe function. And if +error happens to the batch_head at the same time, break_stripe_batch_list +is called, then below warning could happen (the same report in [1]), it +means a member of batch list was set with STRIPE_ACTIVE. + +[7028915.431770] stripe state: 2001 +[7028915.431815] ------------[ cut here ]------------ +[7028915.431828] WARNING: CPU: 18 PID: 29089 at drivers/md/raid5.c:4614 break_stripe_batch_list+0x203/0x240 [raid456] +[...] +[7028915.431879] CPU: 18 PID: 29089 Comm: kworker/u82:5 Tainted: G O 4.14.86-1-storage #4.14.86-1.2~deb9 +[7028915.431881] Hardware name: Supermicro SSG-2028R-ACR24L/X10DRH-iT, BIOS 3.1 06/18/2018 +[7028915.431888] Workqueue: raid5wq raid5_do_work [raid456] +[7028915.431890] task: ffff9ab0ef36d7c0 task.stack: ffffb72926f84000 +[7028915.431896] RIP: 0010:break_stripe_batch_list+0x203/0x240 [raid456] +[7028915.431898] RSP: 0018:ffffb72926f87ba8 EFLAGS: 00010286 +[7028915.431900] RAX: 0000000000000012 RBX: ffff9aaa84a98000 RCX: 0000000000000000 +[7028915.431901] RDX: 0000000000000000 RSI: ffff9ab2bfa15458 RDI: ffff9ab2bfa15458 +[7028915.431902] RBP: ffff9aaa8fb4e900 R08: 0000000000000001 R09: 0000000000002eb4 +[7028915.431903] R10: 00000000ffffffff R11: 0000000000000000 R12: ffff9ab1736f1b00 +[7028915.431904] R13: 0000000000000000 R14: ffff9aaa8fb4e900 R15: 0000000000000001 +[7028915.431906] FS: 0000000000000000(0000) GS:ffff9ab2bfa00000(0000) knlGS:0000000000000000 +[7028915.431907] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 +[7028915.431908] CR2: 00007ff953b9f5d8 CR3: 0000000bf4009002 CR4: 00000000003606e0 +[7028915.431909] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 +[7028915.431910] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 +[7028915.431910] Call Trace: +[7028915.431923] handle_stripe+0x8e7/0x2020 [raid456] +[7028915.431930] ? __wake_up_common_lock+0x89/0xc0 +[7028915.431935] handle_active_stripes.isra.58+0x35f/0x560 [raid456] +[7028915.431939] raid5_do_work+0xc6/0x1f0 [raid456] + +Also commit 59fc630b8b5f9f ("RAID5: batch adjacent full stripe write") +said "If a stripe is added to batch list, then only the first stripe +of the list should be put to handle_list and run handle_stripe." + +So don't set STRIPE_HANDLE to stripe which is already in batch list, +otherwise the stripe could be put to handle_list and run handle_stripe, +then the above warning could be triggered. + +[1]. https://www.spinics.net/lists/raid/msg62552.html + +Signed-off-by: Guoqing Jiang +Signed-off-by: Song Liu +Signed-off-by: Coly Li + +--- + drivers/md/raid5.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c +index 8ea8443e09d5..9fc6737e9713 100644 +--- a/drivers/md/raid5.c ++++ b/drivers/md/raid5.c +@@ -5727,7 +5727,8 @@ static bool raid5_make_request(struct mddev *mddev, struct bio * bi) + do_flush = false; + } + +- set_bit(STRIPE_HANDLE, &sh->state); ++ if (!sh->batch_head) ++ set_bit(STRIPE_HANDLE, &sh->state); + clear_bit(STRIPE_DELAYED, &sh->state); + if ((!sh->batch_head || sh == sh->batch_head) && + (bi->bi_opf & REQ_SYNC) && +-- +2.25.0 + diff --git a/patches.suse/0072-md-add-feature-flag-MD_FEATURE_RAID0_LAYOUT.patch b/patches.suse/0072-md-add-feature-flag-MD_FEATURE_RAID0_LAYOUT.patch new file mode 100644 index 0000000..640a73c --- /dev/null +++ b/patches.suse/0072-md-add-feature-flag-MD_FEATURE_RAID0_LAYOUT.patch @@ -0,0 +1,115 @@ +From 33f2c35a54dfd75ad0e7e86918dcbe4de799a56c Mon Sep 17 00:00:00 2001 +From: NeilBrown +Date: Mon, 9 Sep 2019 16:52:29 +1000 +Subject: [PATCH] md: add feature flag MD_FEATURE_RAID0_LAYOUT +Git-commit: 33f2c35a54dfd75ad0e7e86918dcbe4de799a56c +Patch-mainline: v5.4-rc1 +References: bsc#1166003 + +Due to a bug introduced in Linux 3.14 we cannot determine the +correctly layout for a multi-zone RAID0 array - there are two +possibilities. + +It is possible to tell the kernel which to chose using a module +parameter, but this can be clumsy to use. It would be best if +the choice were recorded in the metadata. +So add a feature flag for this purpose. +If it is set, then the 'layout' field of the superblock is used +to determine which layout to use. + +If this flag is not set, then mddev->layout gets set to -1, +which causes the module parameter to be required. + +Acked-by: Guoqing Jiang +Signed-off-by: NeilBrown +Signed-off-by: Song Liu +Signed-off-by: Coly Li + +--- + drivers/md/md.c | 13 +++++++++++++ + drivers/md/raid0.c | 3 +++ + include/uapi/linux/raid/md_p.h | 2 ++ + 3 files changed, 18 insertions(+) + +diff --git a/drivers/md/md.c b/drivers/md/md.c +index 73d5a1b04022..1be7abeb24fd 100644 +--- a/drivers/md/md.c ++++ b/drivers/md/md.c +@@ -1237,6 +1237,8 @@ static int super_90_validate(struct mddev *mddev, struct md_rdev *rdev) + mddev->new_layout = mddev->layout; + mddev->new_chunk_sectors = mddev->chunk_sectors; + } ++ if (mddev->level == 0) ++ mddev->layout = -1; + + if (sb->state & (1<recovery_cp = MaxSector; +@@ -1652,6 +1654,10 @@ static int super_1_load(struct md_rdev *rdev, struct md_rdev *refdev, int minor_ + rdev->ppl.sector = rdev->sb_start + rdev->ppl.offset; + } + ++ if ((le32_to_cpu(sb->feature_map) & MD_FEATURE_RAID0_LAYOUT) && ++ sb->level != 0) ++ return -EINVAL; ++ + if (!refdev) { + ret = 1; + } else { +@@ -1762,6 +1768,10 @@ static int super_1_validate(struct mddev *mddev, struct md_rdev *rdev) + mddev->new_chunk_sectors = mddev->chunk_sectors; + } + ++ if (mddev->level == 0 && ++ !(le32_to_cpu(sb->feature_map) & MD_FEATURE_RAID0_LAYOUT)) ++ mddev->layout = -1; ++ + if (le32_to_cpu(sb->feature_map) & MD_FEATURE_JOURNAL) + set_bit(MD_HAS_JOURNAL, &mddev->flags); + +@@ -6898,6 +6908,9 @@ static int set_array_info(struct mddev *mddev, mdu_array_info_t *info) + mddev->external = 0; + + mddev->layout = info->layout; ++ if (mddev->level == 0) ++ /* Cannot trust RAID0 layout info here */ ++ mddev->layout = -1; + mddev->chunk_sectors = info->chunk_size >> 9; + + if (mddev->persistent) { +diff --git a/drivers/md/raid0.c b/drivers/md/raid0.c +index ec611abda835..f61693e59684 100644 +--- a/drivers/md/raid0.c ++++ b/drivers/md/raid0.c +@@ -145,6 +145,9 @@ static int create_strip_zones(struct mddev *mddev, struct r0conf **private_conf) + + if (conf->nr_strip_zones == 1) { + conf->layout = RAID0_ORIG_LAYOUT; ++ } else if (mddev->layout == RAID0_ORIG_LAYOUT || ++ mddev->layout == RAID0_ALT_MULTIZONE_LAYOUT) { ++ conf->layout = mddev->layout; + } else if (default_layout == RAID0_ORIG_LAYOUT || + default_layout == RAID0_ALT_MULTIZONE_LAYOUT) { + conf->layout = default_layout; +diff --git a/include/uapi/linux/raid/md_p.h b/include/uapi/linux/raid/md_p.h +index b0d15c73f6d7..1f2d8c81f0e0 100644 +--- a/include/uapi/linux/raid/md_p.h ++++ b/include/uapi/linux/raid/md_p.h +@@ -329,6 +329,7 @@ struct mdp_superblock_1 { + #define MD_FEATURE_JOURNAL 512 /* support write cache */ + #define MD_FEATURE_PPL 1024 /* support PPL */ + #define MD_FEATURE_MULTIPLE_PPLS 2048 /* support for multiple PPLs */ ++#define MD_FEATURE_RAID0_LAYOUT 4096 /* layout is meaningful for RAID0 */ + #define MD_FEATURE_ALL (MD_FEATURE_BITMAP_OFFSET \ + |MD_FEATURE_RECOVERY_OFFSET \ + |MD_FEATURE_RESHAPE_ACTIVE \ +@@ -341,6 +342,7 @@ struct mdp_superblock_1 { + |MD_FEATURE_JOURNAL \ + |MD_FEATURE_PPL \ + |MD_FEATURE_MULTIPLE_PPLS \ ++ |MD_FEATURE_RAID0_LAYOUT \ + ) + + struct r5l_payload_header { +-- +2.25.0 + diff --git a/patches.suse/0073-raid5-remove-STRIPE_OPS_REQ_PENDING.patch b/patches.suse/0073-raid5-remove-STRIPE_OPS_REQ_PENDING.patch new file mode 100644 index 0000000..77d0f66 --- /dev/null +++ b/patches.suse/0073-raid5-remove-STRIPE_OPS_REQ_PENDING.patch @@ -0,0 +1,52 @@ +From feb9bf9849e2aa0dd2833285af7c25aee07df7bb Mon Sep 17 00:00:00 2001 +From: Guoqing Jiang +Date: Thu, 12 Sep 2019 12:10:15 +0200 +Subject: [PATCH] raid5: remove STRIPE_OPS_REQ_PENDING +Git-commit: feb9bf9849e2aa0dd2833285af7c25aee07df7bb +Patch-mainline: v5.4-rc1 +References: bsc#1166003 + +This stripe state is not used anymore after commit 51acbcec6c42b24 +("md: remove CONFIG_MULTICORE_RAID456"), so remove the obsoleted +state. + +gjiang@nb01257:~/md$ grep STRIPE_OPS_REQ_PENDING drivers/md/ -r +Drivers/md/raid5.c: (1 << STRIPE_OPS_REQ_PENDING) | +Drivers/md/raid5.h: STRIPE_OPS_REQ_PENDING, + +Signed-off-by: Guoqing Jiang +Signed-off-by: Song Liu +Signed-off-by: Coly Li + +--- + drivers/md/raid5.c | 1 - + drivers/md/raid5.h | 1 - + 2 files changed, 2 deletions(-) + +diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c +index 9fc6737e9713..223e97ab27e6 100644 +--- a/drivers/md/raid5.c ++++ b/drivers/md/raid5.c +@@ -4621,7 +4621,6 @@ static void break_stripe_batch_list(struct stripe_head *head_sh, + (1 << STRIPE_FULL_WRITE) | + (1 << STRIPE_BIOFILL_RUN) | + (1 << STRIPE_COMPUTE_RUN) | +- (1 << STRIPE_OPS_REQ_PENDING) | + (1 << STRIPE_DISCARD) | + (1 << STRIPE_BATCH_READY) | + (1 << STRIPE_BATCH_ERR) | +diff --git a/drivers/md/raid5.h b/drivers/md/raid5.h +index cf991f13403e..877e7d3f4bd1 100644 +--- a/drivers/md/raid5.h ++++ b/drivers/md/raid5.h +@@ -357,7 +357,6 @@ enum { + STRIPE_FULL_WRITE, /* all blocks are set to be overwritten */ + STRIPE_BIOFILL_RUN, + STRIPE_COMPUTE_RUN, +- STRIPE_OPS_REQ_PENDING, + STRIPE_ON_UNPLUG_LIST, + STRIPE_DISCARD, + STRIPE_ON_RELEASE_LIST, +-- +2.25.0 + diff --git a/patches.suse/0074-md-fix-an-error-code-format-and-remove-unsed-bio_sec.patch b/patches.suse/0074-md-fix-an-error-code-format-and-remove-unsed-bio_sec.patch deleted file mode 100644 index face2cf..0000000 --- a/patches.suse/0074-md-fix-an-error-code-format-and-remove-unsed-bio_sec.patch +++ /dev/null @@ -1,53 +0,0 @@ -From 13db16d74c02c0e9b2d0dc9b9773c8e58ad41064 Mon Sep 17 00:00:00 2001 -From: Yufen Yu -Date: Mon, 23 Apr 2018 17:37:30 +0800 -Subject: [PATCH] md: fix an error code format and remove unsed bio_sector -Git-commit: 13db16d74c02c0e9b2d0dc9b9773c8e58ad41064 -References: bsc#1111974 -Patch-mainline: v4.18-rc1 - -Signed-off-by: Yufen Yu -Signed-off-by: Shaohua Li -Signed-off-by: Coly Li - ---- - drivers/md/raid1.c | 2 -- - drivers/md/raid10.c | 2 +- - 2 files changed, 1 insertion(+), 3 deletions(-) - -diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c -index e9e3308cb0a7..397b3d80c48b 100644 ---- a/drivers/md/raid1.c -+++ b/drivers/md/raid1.c -@@ -2450,7 +2450,6 @@ static void handle_read_error(struct r1conf *conf, struct r1bio *r1_bio) - struct mddev *mddev = conf->mddev; - struct bio *bio; - struct md_rdev *rdev; -- sector_t bio_sector; - - clear_bit(R1BIO_ReadError, &r1_bio->state); - /* we got a read error. Maybe the drive is bad. Maybe just -@@ -2463,7 +2462,6 @@ static void handle_read_error(struct r1conf *conf, struct r1bio *r1_bio) - */ - - bio = r1_bio->bios[r1_bio->read_disk]; -- bio_sector = conf->mirrors[r1_bio->read_disk].rdev->data_offset + r1_bio->sector; - bio_put(bio); - r1_bio->bios[r1_bio->read_disk] = NULL; - -diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c -index 3c60774c8430..64300542ab20 100644 ---- a/drivers/md/raid10.c -+++ b/drivers/md/raid10.c -@@ -2363,7 +2363,7 @@ static void fix_read_error(struct r10conf *conf, struct mddev *mddev, struct r10 - { - int sect = 0; /* Offset from r10_bio->sector */ - int sectors = r10_bio->sectors; -- struct md_rdev*rdev; -+ struct md_rdev *rdev; - int max_read_errors = atomic_read(&mddev->max_corr_read_errors); - int d = r10_bio->devs[r10_bio->read_slot].devnum; - --- -2.19.0 - diff --git a/patches.suse/0074-raid5-use-bio_end_sector-in-r5_next_bio.patch b/patches.suse/0074-raid5-use-bio_end_sector-in-r5_next_bio.patch new file mode 100644 index 0000000..bb41d7f --- /dev/null +++ b/patches.suse/0074-raid5-use-bio_end_sector-in-r5_next_bio.patch @@ -0,0 +1,37 @@ +From 067df25c83902e2950ef24fed713f0fa38282f34 Mon Sep 17 00:00:00 2001 +From: Guoqing Jiang +Date: Thu, 12 Sep 2019 12:10:16 +0200 +Subject: [PATCH] raid5: use bio_end_sector in r5_next_bio +Git-commit: 067df25c83902e2950ef24fed713f0fa38282f34 +Patch-mainline: v5.4-rc1 +References: bsc#1166003 + +Actually, we calculate bio's end sector here, so use the common +way for the purpose. + +Signed-off-by: Guoqing Jiang +Signed-off-by: Song Liu +Signed-off-by: Coly Li + +--- + drivers/md/raid5.h | 4 +--- + 1 file changed, 1 insertion(+), 3 deletions(-) + +diff --git a/drivers/md/raid5.h b/drivers/md/raid5.h +index 877e7d3f4bd1..f90e0704bed9 100644 +--- a/drivers/md/raid5.h ++++ b/drivers/md/raid5.h +@@ -492,9 +492,7 @@ struct disk_info { + */ + static inline struct bio *r5_next_bio(struct bio *bio, sector_t sector) + { +- int sectors = bio_sectors(bio); +- +- if (bio->bi_iter.bi_sector + sectors < sector + STRIPE_SECTORS) ++ if (bio_end_sector(bio) < sector + STRIPE_SECTORS) + return bio->bi_next; + else + return NULL; +-- +2.25.0 + diff --git a/patches.suse/0075-fcntl-fix-typo-in-RWH_WRITE_LIFE_NOT_SET-r-w-hint-na.patch b/patches.suse/0075-fcntl-fix-typo-in-RWH_WRITE_LIFE_NOT_SET-r-w-hint-na.patch new file mode 100644 index 0000000..3709eb6 --- /dev/null +++ b/patches.suse/0075-fcntl-fix-typo-in-RWH_WRITE_LIFE_NOT_SET-r-w-hint-na.patch @@ -0,0 +1,100 @@ +From 9a7f12edf8848a9b355a86fc0183d7be932ef11e Mon Sep 17 00:00:00 2001 +From: Eugene Syromiatnikov +Date: Fri, 20 Sep 2019 17:58:21 +0200 +Subject: [PATCH] fcntl: fix typo in RWH_WRITE_LIFE_NOT_SET r/w hint name +Git-commit: 9a7f12edf8848a9b355a86fc0183d7be932ef11e +Patch-mainline: v5.5-rc1 +References: bsc#1166003 + +According to commit message in the original commit c75b1d9421f8 ("fs: +add fcntl() interface for setting/getting write life time hints"), +as well as userspace library[1] and man page update[2], R/W hint constants +are intended to have RWH_* prefix. However, RWF_WRITE_LIFE_NOT_SET retained +"RWF_*" prefix used in the early versions of the proposed patch set[3]. +Rename it and provide the old name as a synonym for the new one +for backward compatibility. + +[1] https://github.com/axboe/fio/commit/bd553af6c849 +[2] https://github.com/mkerrisk/man-pages/commit/580082a186fd +[3] https://www.mail-archive.com/linux-block@vger.kernel.org/msg09638.html + +Fixes: c75b1d9421f8 ("fs: add fcntl() interface for setting/getting write life time hints") +Acked-by: Song Liu +Signed-off-by: Eugene Syromiatnikov +Signed-off-by: Jens Axboe +Signed-off-by: Coly Li + +--- + fs/fcntl.c | 2 +- + include/uapi/linux/fcntl.h | 9 ++++++++- + tools/include/uapi/linux/fcntl.h | 9 ++++++++- + 3 files changed, 17 insertions(+), 3 deletions(-) + +diff --git a/fs/fcntl.c b/fs/fcntl.c +index 3d40771e8e7c..41b6438bd2d9 100644 +--- a/fs/fcntl.c ++++ b/fs/fcntl.c +@@ -261,7 +261,7 @@ static int f_getowner_uids(struct file *filp, unsigned long arg) + static bool rw_hint_valid(enum rw_hint hint) + { + switch (hint) { +- case RWF_WRITE_LIFE_NOT_SET: ++ case RWH_WRITE_LIFE_NOT_SET: + case RWH_WRITE_LIFE_NONE: + case RWH_WRITE_LIFE_SHORT: + case RWH_WRITE_LIFE_MEDIUM: +diff --git a/include/uapi/linux/fcntl.h b/include/uapi/linux/fcntl.h +index 1d338357df8a..1f97b33c840e 100644 +--- a/include/uapi/linux/fcntl.h ++++ b/include/uapi/linux/fcntl.h +@@ -58,13 +58,20 @@ + * Valid hint values for F_{GET,SET}_RW_HINT. 0 is "not set", or can be + * used to clear any hints previously set. + */ +-#define RWF_WRITE_LIFE_NOT_SET 0 ++#define RWH_WRITE_LIFE_NOT_SET 0 + #define RWH_WRITE_LIFE_NONE 1 + #define RWH_WRITE_LIFE_SHORT 2 + #define RWH_WRITE_LIFE_MEDIUM 3 + #define RWH_WRITE_LIFE_LONG 4 + #define RWH_WRITE_LIFE_EXTREME 5 + ++/* ++ * The originally introduced spelling is remained from the first ++ * versions of the patch set that introduced the feature, see commit ++ * v4.13-rc1~212^2~51. ++ */ ++#define RWF_WRITE_LIFE_NOT_SET RWH_WRITE_LIFE_NOT_SET ++ + /* + * Types of directory notifications that may be requested. + */ +diff --git a/tools/include/uapi/linux/fcntl.h b/tools/include/uapi/linux/fcntl.h +index 1d338357df8a..1f97b33c840e 100644 +--- a/tools/include/uapi/linux/fcntl.h ++++ b/tools/include/uapi/linux/fcntl.h +@@ -58,13 +58,20 @@ + * Valid hint values for F_{GET,SET}_RW_HINT. 0 is "not set", or can be + * used to clear any hints previously set. + */ +-#define RWF_WRITE_LIFE_NOT_SET 0 ++#define RWH_WRITE_LIFE_NOT_SET 0 + #define RWH_WRITE_LIFE_NONE 1 + #define RWH_WRITE_LIFE_SHORT 2 + #define RWH_WRITE_LIFE_MEDIUM 3 + #define RWH_WRITE_LIFE_LONG 4 + #define RWH_WRITE_LIFE_EXTREME 5 + ++/* ++ * The originally introduced spelling is remained from the first ++ * versions of the patch set that introduced the feature, see commit ++ * v4.13-rc1~212^2~51. ++ */ ++#define RWF_WRITE_LIFE_NOT_SET RWH_WRITE_LIFE_NOT_SET ++ + /* + * Types of directory notifications that may be requested. + */ +-- +2.25.0 + diff --git a/patches.suse/0075-raid5-copy-write-hint-from-origin-bio-to-stripe.patch b/patches.suse/0075-raid5-copy-write-hint-from-origin-bio-to-stripe.patch deleted file mode 100644 index 6b5aae4..0000000 --- a/patches.suse/0075-raid5-copy-write-hint-from-origin-bio-to-stripe.patch +++ /dev/null @@ -1,68 +0,0 @@ -From 2cd259a77de561d49c1ff939a239095749e65ee7 Mon Sep 17 00:00:00 2001 -From: Mariusz Dabrowski -Date: Thu, 19 Apr 2018 19:28:10 +0200 -Subject: [PATCH] raid5: copy write hint from origin bio to stripe -Git-commit: 2cd259a77de561d49c1ff939a239095749e65ee7 -References: bsc#1111974 -Patch-mainline: v4.18-rc1 - -Store write hint from original bio in stripe head so it can be assigned -to bio sent to each RAID device. - -Signed-off-by: Mariusz Dabrowski -Reviewed-by: Artur Paszkiewicz -Reviewed-by: Pawel Baldysiak -Signed-off-by: Shaohua Li -Signed-off-by: Coly Li - ---- - drivers/md/raid5.c | 6 ++++++ - drivers/md/raid5.h | 1 + - 2 files changed, 7 insertions(+) - -diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c -index be117d0a65a8..1e1515c817ff 100644 ---- a/drivers/md/raid5.c -+++ b/drivers/md/raid5.c -@@ -1139,6 +1139,9 @@ static void ops_run_io(struct stripe_head *sh, struct stripe_head_state *s) - bi->bi_io_vec[0].bv_len = STRIPE_SIZE; - bi->bi_io_vec[0].bv_offset = 0; - bi->bi_iter.bi_size = STRIPE_SIZE; -+ bi->bi_write_hint = sh->dev[i].write_hint; -+ if (!rrdev) -+ sh->dev[i].write_hint = RWF_WRITE_LIFE_NOT_SET; - /* - * If this is discard request, set bi_vcnt 0. We don't - * want to confuse SCSI because SCSI will replace payload -@@ -1190,6 +1193,8 @@ static void ops_run_io(struct stripe_head *sh, struct stripe_head_state *s) - rbi->bi_io_vec[0].bv_len = STRIPE_SIZE; - rbi->bi_io_vec[0].bv_offset = 0; - rbi->bi_iter.bi_size = STRIPE_SIZE; -+ rbi->bi_write_hint = sh->dev[i].write_hint; -+ sh->dev[i].write_hint = RWF_WRITE_LIFE_NOT_SET; - /* - * If this is discard request, set bi_vcnt 0. We don't - * want to confuse SCSI because SCSI will replace payload -@@ -3204,6 +3209,7 @@ static int add_stripe_bio(struct stripe_head *sh, struct bio *bi, int dd_idx, - (unsigned long long)sh->sector); - - spin_lock_irq(&sh->stripe_lock); -+ sh->dev[dd_idx].write_hint = bi->bi_write_hint; - /* Don't allow new IO added to stripes in batch list */ - if (sh->batch_head) - goto overlap; -diff --git a/drivers/md/raid5.h b/drivers/md/raid5.h -index 3f8da26032ac..aea2447b0ea7 100644 ---- a/drivers/md/raid5.h -+++ b/drivers/md/raid5.h -@@ -257,6 +257,7 @@ struct stripe_head { - sector_t sector; /* sector of this page */ - unsigned long flags; - u32 log_checksum; -+ unsigned short write_hint; - } dev[1]; /* allocated with extra space depending of RAID geometry */ - }; - --- -2.19.0 - diff --git a/patches.suse/0076-md-raid0-Fix-an-error-message-in-raid0_make_request.patch b/patches.suse/0076-md-raid0-Fix-an-error-message-in-raid0_make_request.patch new file mode 100644 index 0000000..97848d4 --- /dev/null +++ b/patches.suse/0076-md-raid0-Fix-an-error-message-in-raid0_make_request.patch @@ -0,0 +1,37 @@ +From e3fc3f3d0943b126f76b8533960e4168412d9e5a Mon Sep 17 00:00:00 2001 +From: Dan Carpenter +Date: Sat, 21 Sep 2019 09:00:31 +0300 +Subject: [PATCH] md/raid0: Fix an error message in raid0_make_request() +Git-commit: e3fc3f3d0943b126f76b8533960e4168412d9e5a +Patch-mainline: v5.5-rc1 +References: bsc#1166003 + +The first argument to WARN() is supposed to be a condition. The +original code will just print the mdname() instead of the full warning +message. + +Fixes: c84a1372df92 ("md/raid0: avoid RAID0 data corruption due to layout confusion.") +Signed-off-by: Dan Carpenter +Signed-off-by: Song Liu +Signed-off-by: Coly Li + +--- + drivers/md/raid0.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/md/raid0.c b/drivers/md/raid0.c +index f61693e59684..3956ea502f97 100644 +--- a/drivers/md/raid0.c ++++ b/drivers/md/raid0.c +@@ -615,7 +615,7 @@ static bool raid0_make_request(struct mddev *mddev, struct bio *bio) + tmp_dev = map_sector(mddev, zone, sector, §or); + break; + default: +- WARN("md/raid0:%s: Invalid layout\n", mdname(mddev)); ++ WARN(1, "md/raid0:%s: Invalid layout\n", mdname(mddev)); + bio_io_error(bio); + return true; + } +-- +2.25.0 + diff --git a/patches.suse/0076-md-raid5-Assigning-NULL-to-sh-batch_head-before-test.patch b/patches.suse/0076-md-raid5-Assigning-NULL-to-sh-batch_head-before-test.patch deleted file mode 100644 index de6fe6c..0000000 --- a/patches.suse/0076-md-raid5-Assigning-NULL-to-sh-batch_head-before-test.patch +++ /dev/null @@ -1,54 +0,0 @@ -From 448ec638c6bcf36923db695b6188373b933e7ddc Mon Sep 17 00:00:00 2001 -From: Amy Chiang -Date: Wed, 16 May 2018 18:59:35 +0800 -Subject: [PATCH] md/raid5: Assigning NULL to sh->batch_head before testing bit - R5_Overlap of a stripe -Git-commit: 448ec638c6bcf36923db695b6188373b933e7ddc -References: bsc#1111974 -Patch-mainline: v4.18-rc1 - -In add_stripe_bio(), if the stripe_head is in batch list, the incoming -bio is regarded as overlapping, and the bit R5_Overlap on this stripe_head -is set. break_stripe_batch_list() checks bit R5_Overlap on each stripe_head -first then assigns NULL to sh->batch_head. - -If break_stripe_batch_list() checks bit R5_Overlap on stripe_head A -after add_stripe_bio() finds stripe_head A is in batch list and before -add_stripe_bio() sets bit R5_Overlapt of stripe_head A, -break_stripe_batch_list() would not know there's a process in -wait_for_overlap and needs to call wake_up(). There's a huge chance a -process never returns from schedule() if add_stripe_bio() is called -from raid5_make_request(). - -In break_stripe_batch_list(), assigning NULL to sh->batch_head should -be done before it checks bit R5_Overlap of a stripe_head. - -Signed-off-by: Amy Chiang -Signed-off-by: Shaohua Li -Signed-off-by: Coly Li - ---- - drivers/md/raid5.c | 6 +++--- - 1 file changed, 3 insertions(+), 3 deletions(-) - ---- a/drivers/md/raid5.c -+++ b/drivers/md/raid5.c -@@ -4621,15 +4621,15 @@ static void break_stripe_batch_list(stru - - sh->check_state = head_sh->check_state; - sh->reconstruct_state = head_sh->reconstruct_state; -+ spin_lock_irq(&sh->stripe_lock); -+ sh->batch_head = NULL; -+ spin_unlock_irq(&sh->stripe_lock); - for (i = 0; i < sh->disks; i++) { - if (test_and_clear_bit(R5_Overlap, &sh->dev[i].flags)) - do_wakeup = 1; - sh->dev[i].flags = head_sh->dev[i].flags & - (~((1 << R5_WriteError) | (1 << R5_Overlap))); - } -- spin_lock_irq(&sh->stripe_lock); -- sh->batch_head = NULL; -- spin_unlock_irq(&sh->stripe_lock); - if (handle_flags == 0 || - sh->state & handle_flags) - set_bit(STRIPE_HANDLE, &sh->state); diff --git a/patches.suse/0077-MD-fix-lock-contention-for-flush-bios.patch b/patches.suse/0077-MD-fix-lock-contention-for-flush-bios.patch deleted file mode 100644 index 54e407a..0000000 --- a/patches.suse/0077-MD-fix-lock-contention-for-flush-bios.patch +++ /dev/null @@ -1,373 +0,0 @@ -From 5a409b4f56d50b212334f338cb8465d65550cd85 Mon Sep 17 00:00:00 2001 -From: Xiao Ni -Date: Mon, 21 May 2018 11:49:54 +0800 -Subject: [PATCH] MD: fix lock contention for flush bios -Git-commit: 5a409b4f56d50b212334f338cb8465d65550cd85 -References: bsc#1111974 -Patch-mainline: v4.18-rc1 - -There is a lock contention when there are many processes which send flush bios -to md device. eg. Create many lvs on one raid device and mkfs.xfs on each lv. - -Now it just can handle flush request sequentially. It needs to wait mddev->flush_bio -to be NULL, otherwise get mddev->lock. - -This patch remove mddev->flush_bio and handle flush bio asynchronously. -I did a test with command dbench -s 128 -t 300. This is the test result: - -=================Without the patch============================ - Operation Count AvgLat MaxLat - -------------------------------------------------- - Flush 11165 167.595 5879.560 - Close 107469 1.391 2231.094 - LockX 384 0.003 0.019 - Rename 5944 2.141 1856.001 - ReadX 208121 0.003 0.074 - WriteX 98259 1925.402 15204.895 - Unlink 25198 13.264 3457.268 - UnlockX 384 0.001 0.009 - FIND_FIRST 47111 0.012 0.076 - SET_FILE_INFORMATION 12966 0.007 0.065 - QUERY_FILE_INFORMATION 27921 0.004 0.085 - QUERY_PATH_INFORMATION 124650 0.005 5.766 - QUERY_FS_INFORMATION 22519 0.003 0.053 - NTCreateX 141086 4.291 2502.812 - -Throughput 3.7181 MB/sec (sync open) 128 clients 128 procs max_latency=15204.905 ms - -=================With the patch============================ - Operation Count AvgLat MaxLat - -------------------------------------------------- - Flush 4500 174.134 406.398 - Close 48195 0.060 467.062 - LockX 256 0.003 0.029 - Rename 2324 0.026 0.360 - ReadX 78846 0.004 0.504 - WriteX 66832 562.775 1467.037 - Unlink 5516 3.665 1141.740 - UnlockX 256 0.002 0.019 - FIND_FIRST 16428 0.015 0.313 - SET_FILE_INFORMATION 6400 0.009 0.520 - QUERY_FILE_INFORMATION 17865 0.003 0.089 - QUERY_PATH_INFORMATION 47060 0.078 416.299 - QUERY_FS_INFORMATION 7024 0.004 0.032 - NTCreateX 55921 0.854 1141.452 - -Throughput 11.744 MB/sec (sync open) 128 clients 128 procs max_latency=1467.041 ms - -The test is done on raid1 disk with two rotational disks - -V5: V4 is more complicated than the version with memory pool. So revert to the memory pool -version - -V4: use address of fbio to do hash to choose free flush info. -V3: -Shaohua suggests mempool is overkill. In v3 it allocs memory during creating raid device -and uses a simple bitmap to record which resource is free. - -Fix a bug from v2. It should set flush_pending to 1 at first. - -V2: -Neil pointed out two problems. One is counting error problem and another is return value -when allocat memory fails. -1. counting error problem -This isn't safe. It is only safe to call rdev_dec_pending() on rdevs -that you previously called - atomic_inc(&rdev->nr_pending); -If an rdev was added to the list between the start and end of the flush, -this will do something bad. - -Now it doesn't use bio_chain. It uses specified call back function for each -flush bio. -2. Returned on IO error when kmalloc fails is wrong. -I use mempool suggested by Neil in V2 -3. Fixed some places pointed by Guoqing - -Suggested-by: Ming Lei -Signed-off-by: Xiao Ni -Signed-off-by: Shaohua Li -Signed-off-by: Coly Li ---- - drivers/md/md.c | 158 +++++++++++++++++++++++++++++++++++++------------------- - drivers/md/md.h | 22 +++++--- - 2 files changed, 120 insertions(+), 60 deletions(-) - -diff --git a/drivers/md/md.c b/drivers/md/md.c -index df9eb1a04f26..6b4e2f29fe4e 100644 ---- a/drivers/md/md.c -+++ b/drivers/md/md.c -@@ -130,6 +130,24 @@ static inline int speed_max(struct mddev *mddev) - mddev->sync_speed_max : sysctl_speed_limit_max; - } - -+static void * flush_info_alloc(gfp_t gfp_flags, void *data) -+{ -+ return kzalloc(sizeof(struct flush_info), gfp_flags); -+} -+static void flush_info_free(void *flush_info, void *data) -+{ -+ kfree(flush_info); -+} -+ -+static void * flush_bio_alloc(gfp_t gfp_flags, void *data) -+{ -+ return kzalloc(sizeof(struct flush_bio), gfp_flags); -+} -+static void flush_bio_free(void *flush_bio, void *data) -+{ -+ kfree(flush_bio); -+} -+ - static struct ctl_table_header *raid_table_header; - - static struct ctl_table raid_table[] = { -@@ -412,30 +430,53 @@ static int md_congested(void *data, int bits) - /* - * Generic flush handling for md - */ -+static void submit_flushes(struct work_struct *ws) -+{ -+ struct flush_info *fi = container_of(ws, struct flush_info, flush_work); -+ struct mddev *mddev = fi->mddev; -+ struct bio *bio = fi->bio; -+ -+ bio->bi_opf &= ~REQ_PREFLUSH; -+ md_handle_request(mddev, bio); -+ -+ mempool_free(fi, mddev->flush_pool); -+} - --static void md_end_flush(struct bio *bio) -+static void md_end_flush(struct bio *fbio) - { -- struct md_rdev *rdev = bio->bi_private; -- struct mddev *mddev = rdev->mddev; -+ struct flush_bio *fb = fbio->bi_private; -+ struct md_rdev *rdev = fb->rdev; -+ struct flush_info *fi = fb->fi; -+ struct bio *bio = fi->bio; -+ struct mddev *mddev = fi->mddev; - - rdev_dec_pending(rdev, mddev); - -- if (atomic_dec_and_test(&mddev->flush_pending)) { -- /* The pre-request flush has finished */ -- queue_work(md_wq, &mddev->flush_work); -+ if (atomic_dec_and_test(&fi->flush_pending)) { -+ if (bio->bi_iter.bi_size == 0) -+ /* an empty barrier - all done */ -+ bio_endio(bio); -+ else { -+ INIT_WORK(&fi->flush_work, submit_flushes); -+ queue_work(md_wq, &fi->flush_work); -+ } - } -- bio_put(bio); --} - --static void md_submit_flush_data(struct work_struct *ws); -+ mempool_free(fb, mddev->flush_bio_pool); -+ bio_put(fbio); -+} - --static void submit_flushes(struct work_struct *ws) -+void md_flush_request(struct mddev *mddev, struct bio *bio) - { -- struct mddev *mddev = container_of(ws, struct mddev, flush_work); - struct md_rdev *rdev; -+ struct flush_info *fi; -+ -+ fi = mempool_alloc(mddev->flush_pool, GFP_NOIO); -+ -+ fi->bio = bio; -+ fi->mddev = mddev; -+ atomic_set(&fi->flush_pending, 1); - -- INIT_WORK(&mddev->flush_work, md_submit_flush_data); -- atomic_set(&mddev->flush_pending, 1); - rcu_read_lock(); - rdev_for_each_rcu(rdev, mddev) - if (rdev->raid_disk >= 0 && -@@ -445,59 +486,39 @@ static void submit_flushes(struct work_struct *ws) - * we reclaim rcu_read_lock - */ - struct bio *bi; -+ struct flush_bio *fb; - atomic_inc(&rdev->nr_pending); - atomic_inc(&rdev->nr_pending); - rcu_read_unlock(); -+ -+ fb = mempool_alloc(mddev->flush_bio_pool, GFP_NOIO); -+ fb->fi = fi; -+ fb->rdev = rdev; -+ - bi = bio_alloc_mddev(GFP_NOIO, 0, mddev); -- bi->bi_end_io = md_end_flush; -- bi->bi_private = rdev; - bio_set_dev(bi, rdev->bdev); -+ bi->bi_end_io = md_end_flush; -+ bi->bi_private = fb; - bi->bi_opf = REQ_OP_WRITE | REQ_PREFLUSH; -- atomic_inc(&mddev->flush_pending); -+ -+ atomic_inc(&fi->flush_pending); - submit_bio(bi); -+ - rcu_read_lock(); - rdev_dec_pending(rdev, mddev); - } - rcu_read_unlock(); -- if (atomic_dec_and_test(&mddev->flush_pending)) -- queue_work(md_wq, &mddev->flush_work); --} -- --static void md_submit_flush_data(struct work_struct *ws) --{ -- struct mddev *mddev = container_of(ws, struct mddev, flush_work); -- struct bio *bio = mddev->flush_bio; - -- /* -- * must reset flush_bio before calling into md_handle_request to avoid a -- * deadlock, because other bios passed md_handle_request suspend check -- * could wait for this and below md_handle_request could wait for those -- * bios because of suspend check -- */ -- mddev->flush_bio = NULL; -- wake_up(&mddev->sb_wait); -- -- if (bio->bi_iter.bi_size == 0) -- /* an empty barrier - all done */ -- bio_endio(bio); -- else { -- bio->bi_opf &= ~REQ_PREFLUSH; -- md_handle_request(mddev, bio); -+ if (atomic_dec_and_test(&fi->flush_pending)) { -+ if (bio->bi_iter.bi_size == 0) -+ /* an empty barrier - all done */ -+ bio_endio(bio); -+ else { -+ INIT_WORK(&fi->flush_work, submit_flushes); -+ queue_work(md_wq, &fi->flush_work); -+ } - } - } -- --void md_flush_request(struct mddev *mddev, struct bio *bio) --{ -- spin_lock_irq(&mddev->lock); -- wait_event_lock_irq(mddev->sb_wait, -- !mddev->flush_bio, -- mddev->lock); -- mddev->flush_bio = bio; -- spin_unlock_irq(&mddev->lock); -- -- INIT_WORK(&mddev->flush_work, submit_flushes); -- queue_work(md_wq, &mddev->flush_work); --} - EXPORT_SYMBOL(md_flush_request); - - static inline struct mddev *mddev_get(struct mddev *mddev) -@@ -555,7 +576,6 @@ void mddev_init(struct mddev *mddev) - atomic_set(&mddev->openers, 0); - atomic_set(&mddev->active_io, 0); - spin_lock_init(&mddev->lock); -- atomic_set(&mddev->flush_pending, 0); - init_waitqueue_head(&mddev->sb_wait); - init_waitqueue_head(&mddev->recovery_wait); - mddev->reshape_position = MaxSector; -@@ -5510,6 +5530,22 @@ int md_run(struct mddev *mddev) - goto abort; - } - } -+ if (mddev->flush_pool == NULL) { -+ mddev->flush_pool = mempool_create(NR_FLUSH_INFOS, flush_info_alloc, -+ flush_info_free, mddev); -+ if (!mddev->flush_pool) { -+ err = -ENOMEM; -+ goto abort; -+ } -+ } -+ if (mddev->flush_bio_pool == NULL) { -+ mddev->flush_bio_pool = mempool_create(NR_FLUSH_BIOS, flush_bio_alloc, -+ flush_bio_free, mddev); -+ if (!mddev->flush_bio_pool) { -+ err = -ENOMEM; -+ goto abort; -+ } -+ } - - spin_lock(&pers_lock); - pers = find_pers(mddev->level, mddev->clevel); -@@ -5669,6 +5705,14 @@ int md_run(struct mddev *mddev) - return 0; - - abort: -+ if (mddev->flush_bio_pool) { -+ mempool_destroy(mddev->flush_bio_pool); -+ mddev->flush_bio_pool = NULL; -+ } -+ if (mddev->flush_pool){ -+ mempool_destroy(mddev->flush_pool); -+ mddev->flush_pool = NULL; -+ } - if (mddev->bio_set) { - bioset_free(mddev->bio_set); - mddev->bio_set = NULL; -@@ -5889,6 +5933,14 @@ void md_stop(struct mddev *mddev) - * This is called from dm-raid - */ - __md_stop(mddev); -+ if (mddev->flush_bio_pool) { -+ mempool_destroy(mddev->flush_bio_pool); -+ mddev->flush_bio_pool = NULL; -+ } -+ if (mddev->flush_pool) { -+ mempool_destroy(mddev->flush_pool); -+ mddev->flush_pool = NULL; -+ } - if (mddev->bio_set) { - bioset_free(mddev->bio_set); - mddev->bio_set = NULL; -diff --git a/drivers/md/md.h b/drivers/md/md.h -index fbc925cce810..ffcb1ae217fe 100644 ---- a/drivers/md/md.h -+++ b/drivers/md/md.h -@@ -252,6 +252,19 @@ enum mddev_sb_flags { - MD_SB_NEED_REWRITE, /* metadata write needs to be repeated */ - }; - -+#define NR_FLUSH_INFOS 8 -+#define NR_FLUSH_BIOS 64 -+struct flush_info { -+ struct bio *bio; -+ struct mddev *mddev; -+ struct work_struct flush_work; -+ atomic_t flush_pending; -+}; -+struct flush_bio { -+ struct flush_info *fi; -+ struct md_rdev *rdev; -+}; -+ - struct mddev { - void *private; - struct md_personality *pers; -@@ -457,13 +470,8 @@ struct mddev { - * metadata and bitmap writes - */ - -- /* Generic flush handling. -- * The last to finish preflush schedules a worker to submit -- * the rest of the request (without the REQ_PREFLUSH flag). -- */ -- struct bio *flush_bio; -- atomic_t flush_pending; -- struct work_struct flush_work; -+ mempool_t *flush_pool; -+ mempool_t *flush_bio_pool; - struct work_struct event_work; /* used by dm to report failure event */ - void (*sync_super)(struct mddev *mddev, struct md_rdev *rdev); - struct md_cluster_info *cluster_info; --- -2.16.3 - diff --git a/patches.suse/0077-md-bitmap-avoid-race-window-between-md_bitmap_resize.patch b/patches.suse/0077-md-bitmap-avoid-race-window-between-md_bitmap_resize.patch new file mode 100644 index 0000000..a2370e4 --- /dev/null +++ b/patches.suse/0077-md-bitmap-avoid-race-window-between-md_bitmap_resize.patch @@ -0,0 +1,101 @@ +From fadcbd2901a0f7c8721f3bdb69eac95c272dc8ed Mon Sep 17 00:00:00 2001 +From: Guoqing Jiang +Date: Thu, 26 Sep 2019 13:53:50 +0200 +Subject: [PATCH] md/bitmap: avoid race window between md_bitmap_resize and + bitmap_file_clear_bit +Git-commit: fadcbd2901a0f7c8721f3bdb69eac95c272dc8ed +Patch-mainline: v5.5-rc1 +References: bsc#1166003 + +We need to move "spin_lock_irq(&bitmap->counts.lock)" before unmap previous +storage, otherwise panic like belows could happen as follows. + +[ 902.353802] sdl: detected capacity change from 1077936128 to 3221225472 +[ 902.616948] general protection fault: 0000 [#1] SMP +[snip] +[ 902.618588] CPU: 12 PID: 33698 Comm: md0_raid1 Tainted: G O 4.14.144-1-pserver #4.14.144-1.1~deb10 +[ 902.618870] Hardware name: Supermicro SBA-7142G-T4/BHQGE, BIOS 3.00 10/24/2012 +[ 902.619120] task: ffff9ae1860fc600 task.stack: ffffb52e4c704000 +[ 902.619301] RIP: 0010:bitmap_file_clear_bit+0x90/0xd0 [md_mod] +[ 902.619464] RSP: 0018:ffffb52e4c707d28 EFLAGS: 00010087 +[ 902.619626] RAX: ffe8008b0d061000 RBX: ffff9ad078c87300 RCX: 0000000000000000 +[ 902.619792] RDX: ffff9ad986341868 RSI: 0000000000000803 RDI: ffff9ad078c87300 +[ 902.619986] RBP: ffff9ad0ed7a8000 R08: 0000000000000000 R09: 0000000000000000 +[ 902.620154] R10: ffffb52e4c707ec0 R11: ffff9ad987d1ed44 R12: ffff9ad0ed7a8360 +[ 902.620320] R13: 0000000000000003 R14: 0000000000060000 R15: 0000000000000800 +[ 902.620487] FS: 0000000000000000(0000) GS:ffff9ad987d00000(0000) knlGS:0000000000000000 +[ 902.620738] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 +[ 902.620901] CR2: 000055ff12aecec0 CR3: 0000001005207000 CR4: 00000000000406e0 +[ 902.621068] Call Trace: +[ 902.621256] bitmap_daemon_work+0x2dd/0x360 [md_mod] +[ 902.621429] ? find_pers+0x70/0x70 [md_mod] +[ 902.621597] md_check_recovery+0x51/0x540 [md_mod] +[ 902.621762] raid1d+0x5c/0xeb0 [raid1] +[ 902.621939] ? try_to_del_timer_sync+0x4d/0x80 +[ 902.622102] ? del_timer_sync+0x35/0x40 +[ 902.622265] ? schedule_timeout+0x177/0x360 +[ 902.622453] ? call_timer_fn+0x130/0x130 +[ 902.622623] ? find_pers+0x70/0x70 [md_mod] +[ 902.622794] ? md_thread+0x94/0x150 [md_mod] +[ 902.622959] md_thread+0x94/0x150 [md_mod] +[ 902.623121] ? wait_woken+0x80/0x80 +[ 902.623280] kthread+0x119/0x130 +[ 902.623437] ? kthread_create_on_node+0x60/0x60 +[ 902.623600] ret_from_fork+0x22/0x40 +[ 902.624225] RIP: bitmap_file_clear_bit+0x90/0xd0 [md_mod] RSP: ffffb52e4c707d28 + +Because mdadm was running on another cpu to do resize, so bitmap_resize was +called to replace bitmap as below shows. + +Pid: 38801 TASK: ffff9ad074a90e00 CPU: 0 COMMAND: "mdadm" + [exception RIP: queued_spin_lock_slowpath+56] + [snip] +-- -- + #5 [ffffb52e60f17c58] queued_spin_lock_slowpath at ffffffff9c0b27b8 + #6 [ffffb52e60f17c58] bitmap_resize at ffffffffc0399877 [md_mod] + #7 [ffffb52e60f17d30] raid1_resize at ffffffffc0285bf9 [raid1] + #8 [ffffb52e60f17d50] update_size at ffffffffc038a31a [md_mod] + #9 [ffffb52e60f17d70] md_ioctl at ffffffffc0395ca4 [md_mod] + +And the procedure to keep resize bitmap safe is allocate new storage +space, then quiesce, copy bits, replace bitmap, and re-start. + +However the daemon (bitmap_daemon_work) could happen even the array is +quiesced, which means when bitmap_file_clear_bit is triggered by raid1d, +then it thinks it should be fine to access store->filemap since +counts->lock is held, but resize could change the storage without the +protection of the lock. + +Cc: Jack Wang +Cc: NeilBrown +Signed-off-by: Guoqing Jiang +Signed-off-by: Song Liu +Signed-off-by: Coly Li + +--- + drivers/md/md-bitmap.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/md/md-bitmap.c b/drivers/md/md-bitmap.c +index b092c7b5282f..3ad18246fcb3 100644 +--- a/drivers/md/md-bitmap.c ++++ b/drivers/md/md-bitmap.c +@@ -2139,6 +2139,7 @@ int md_bitmap_resize(struct bitmap *bitmap, sector_t blocks, + memcpy(page_address(store.sb_page), + page_address(bitmap->storage.sb_page), + sizeof(bitmap_super_t)); ++ spin_lock_irq(&bitmap->counts.lock); + md_bitmap_file_unmap(&bitmap->storage); + bitmap->storage = store; + +@@ -2154,7 +2155,6 @@ int md_bitmap_resize(struct bitmap *bitmap, sector_t blocks, + blocks = min(old_counts.chunks << old_counts.chunkshift, + chunks << chunkshift); + +- spin_lock_irq(&bitmap->counts.lock); + /* For cluster raid, need to pre-allocate bitmap */ + if (mddev_is_clustered(bitmap->mddev)) { + unsigned long page; +-- +2.25.0 + diff --git a/patches.suse/0078-md-no-longer-compare-spare-disk-superblock-events-in.patch b/patches.suse/0078-md-no-longer-compare-spare-disk-superblock-events-in.patch new file mode 100644 index 0000000..007c113 --- /dev/null +++ b/patches.suse/0078-md-no-longer-compare-spare-disk-superblock-events-in.patch @@ -0,0 +1,192 @@ +From 6a5cb53aaa4ef515ddeffa04ce18b771121127b4 Mon Sep 17 00:00:00 2001 +From: Yufen Yu +Date: Wed, 16 Oct 2019 16:00:03 +0800 +Subject: [PATCH] md: no longer compare spare disk superblock events in + super_load +Git-commit: 6a5cb53aaa4ef515ddeffa04ce18b771121127b4 +Patch-mainline: v5.5-rc1 +References: bsc#1166003 + +We have a test case as follow: + + mdadm -CR /dev/md1 -l 1 -n 4 /dev/sd[a-d] \ + --assume-clean --bitmap=internal + mdadm -S /dev/md1 + mdadm -A /dev/md1 /dev/sd[b-c] --run --force + + mdadm --zero /dev/sda + mdadm /dev/md1 -a /dev/sda + + echo offline > /sys/block/sdc/device/state + echo offline > /sys/block/sdb/device/state + sleep 5 + mdadm -S /dev/md1 + + echo running > /sys/block/sdb/device/state + echo running > /sys/block/sdc/device/state + mdadm -A /dev/md1 /dev/sd[a-c] --run --force + +When we readd /dev/sda to the array, it started to do recovery. +After offline the other two disks in md1, the recovery have +been interrupted and superblock update info cannot be written +to the offline disks. While the spare disk (/dev/sda) can continue +to update superblock info. + +After stopping the array and assemble it, we found the array +run fail, with the follow kernel message: + +[ 172.986064] md: kicking non-fresh sdb from array! +[ 173.004210] md: kicking non-fresh sdc from array! +[ 173.022383] md/raid1:md1: active with 0 out of 4 mirrors +[ 173.022406] md1: failed to create bitmap (-5) +[ 173.023466] md: md1 stopped. + +Since both sdb and sdc have the value of 'sb->events' smaller than +that in sda, they have been kicked from the array. However, the only +remained disk sda is in 'spare' state before stop and it cannot be +added to conf->mirrors[] array. In the end, raid array assemble +and run fail. + +In fact, we can use the older disk sdb or sdc to assemble the array. +That means we should not choose the 'spare' disk as the fresh disk in +analyze_sbs(). + +To fix the problem, we do not compare superblock events when it is +a spare disk, as same as validate_super. + +Signed-off-by: Yufen Yu +Signed-off-by: Song Liu +Signed-off-by: Coly Li + +--- + drivers/md/md.c | 57 +++++++++++++++++++++++++++++++++++++++++++------ + 1 file changed, 51 insertions(+), 6 deletions(-) + +diff --git a/drivers/md/md.c b/drivers/md/md.c +index b8dd56b746da..6f0ecfe8eab2 100644 +--- a/drivers/md/md.c ++++ b/drivers/md/md.c +@@ -1156,7 +1156,15 @@ static int super_90_load(struct md_rdev *rdev, struct md_rdev *refdev, int minor + rdev->desc_nr = sb->this_disk.number; + + if (!refdev) { +- ret = 1; ++ /* ++ * Insist on good event counter while assembling, except ++ * for spares (which don't need an event count) ++ */ ++ if (sb->disks[rdev->desc_nr].state & ( ++ (1<sb_page); +@@ -1172,7 +1180,14 @@ static int super_90_load(struct md_rdev *rdev, struct md_rdev *refdev, int minor + } + ev1 = md_event(sb); + ev2 = md_event(refsb); +- if (ev1 > ev2) ++ ++ /* ++ * Insist on good event counter while assembling, except ++ * for spares (which don't need an event count) ++ */ ++ if (sb->disks[rdev->desc_nr].state & ( ++ (1< ev2)) + ret = 1; + else + ret = 0; +@@ -1532,6 +1547,7 @@ static int super_1_load(struct md_rdev *rdev, struct md_rdev *refdev, int minor_ + sector_t sectors; + char b[BDEVNAME_SIZE], b2[BDEVNAME_SIZE]; + int bmask; ++ __u64 role; + + /* + * Calculate the position of the superblock in 512byte sectors. +@@ -1665,8 +1681,20 @@ static int super_1_load(struct md_rdev *rdev, struct md_rdev *refdev, int minor_ + sb->level != 0) + return -EINVAL; + ++ role = le16_to_cpu(sb->dev_roles[rdev->desc_nr]); ++ + if (!refdev) { +- ret = 1; ++ /* ++ * Insist of good event counter while assembling, except for ++ * spares (which don't need an event count) ++ */ ++ if (rdev->desc_nr >= 0 && ++ rdev->desc_nr < le32_to_cpu(sb->max_dev) && ++ (role < MD_DISK_ROLE_MAX || ++ role == MD_DISK_ROLE_JOURNAL)) ++ ret = 1; ++ else ++ ret = 0; + } else { + __u64 ev1, ev2; + struct mdp_superblock_1 *refsb = page_address(refdev->sb_page); +@@ -1683,7 +1711,14 @@ static int super_1_load(struct md_rdev *rdev, struct md_rdev *refdev, int minor_ + ev1 = le64_to_cpu(sb->events); + ev2 = le64_to_cpu(refsb->events); + +- if (ev1 > ev2) ++ /* ++ * Insist of good event counter while assembling, except for ++ * spares (which don't need an event count) ++ */ ++ if (rdev->desc_nr >= 0 && ++ rdev->desc_nr < le32_to_cpu(sb->max_dev) && ++ (role < MD_DISK_ROLE_MAX || ++ role == MD_DISK_ROLE_JOURNAL) && ev1 > ev2) + ret = 1; + else + ret = 0; +@@ -3604,7 +3639,7 @@ static struct md_rdev *md_import_device(dev_t newdev, int super_format, int supe + * Check a full RAID array for plausibility + */ + +-static void analyze_sbs(struct mddev *mddev) ++static int analyze_sbs(struct mddev *mddev) + { + int i; + struct md_rdev *rdev, *freshest, *tmp; +@@ -3625,6 +3660,12 @@ static void analyze_sbs(struct mddev *mddev) + md_kick_rdev_from_array(rdev); + } + ++ /* Cannot find a valid fresh disk */ ++ if (!freshest) { ++ pr_warn("md: cannot find a valid disk\n"); ++ return -EINVAL; ++ } ++ + super_types[mddev->major_version]. + validate_super(mddev, freshest); + +@@ -3659,6 +3700,8 @@ static void analyze_sbs(struct mddev *mddev) + clear_bit(In_sync, &rdev->flags); + } + } ++ ++ return 0; + } + + /* Read a fixed-point number. +@@ -5577,7 +5620,9 @@ int md_run(struct mddev *mddev) + if (!mddev->raid_disks) { + if (!mddev->persistent) + return -EINVAL; +- analyze_sbs(mddev); ++ err = analyze_sbs(mddev); ++ if (err) ++ return -EINVAL; + } + + if (mddev->level != LEVEL_NONE) +-- +2.25.0 + diff --git a/patches.suse/0079-atomic-Add-irqsave-variant-of-atomic_dec_and_lock.patch b/patches.suse/0079-atomic-Add-irqsave-variant-of-atomic_dec_and_lock.patch deleted file mode 100644 index e35229b..0000000 --- a/patches.suse/0079-atomic-Add-irqsave-variant-of-atomic_dec_and_lock.patch +++ /dev/null @@ -1,63 +0,0 @@ -From ccfbb5bed407053b27492a9adc06064d949a9aa6 Mon Sep 17 00:00:00 2001 -From: Anna-Maria Gleixner -Date: Tue, 12 Jun 2018 18:16:20 +0200 -Subject: [PATCH] atomic: Add irqsave variant of atomic_dec_and_lock() -Git-commit: ccfbb5bed407053b27492a9adc06064d949a9aa6 -Patch-mainline: v4.18-rc2 -References: bsc#1111974 - -There are in-tree users of atomic_dec_and_lock() which must acquire the -spin lock with interrupts disabled. To workaround the lack of an irqsave -variant of atomic_dec_and_lock() they use local_irq_save() at the call -site. This causes extra code and creates in some places unneeded long -interrupt disabled times. These places need also extra treatment for -PREEMPT_RT due to the disconnect of the irq disabling and the lock -function. - -Implement the missing irqsave variant of the function. - -Signed-off-by: Anna-Maria Gleixner -Signed-off-by: Sebastian Andrzej Siewior -Signed-off-by: Thomas Gleixner -Acked-by: Peter Zijlstra (Intel) -Link: https://lkml.kernel.org/r20180612161621.22645-3-bigeasy@linutronix.de -Acked-by: Coly Li ---- - include/linux/spinlock.h | 5 +++++ - lib/dec_and_lock.c | 16 ++++++++++++++++ - 2 files changed, 21 insertions(+) - ---- a/include/linux/spinlock.h -+++ b/include/linux/spinlock.h -@@ -408,4 +408,9 @@ extern int _atomic_dec_and_lock(atomic_t - #define atomic_dec_and_lock(atomic, lock) \ - __cond_lock(lock, _atomic_dec_and_lock(atomic, lock)) - -+extern int _atomic_dec_and_lock_irqsave(atomic_t *atomic, spinlock_t *lock, -+ unsigned long *flags); -+#define atomic_dec_and_lock_irqsave(atomic, lock, flags) \ -+ __cond_lock(lock, _atomic_dec_and_lock_irqsave(atomic, lock, &(flags))) -+ - #endif /* __LINUX_SPINLOCK_H */ ---- a/lib/dec_and_lock.c -+++ b/lib/dec_and_lock.c -@@ -32,3 +32,19 @@ int _atomic_dec_and_lock(atomic_t *atomi - } - - EXPORT_SYMBOL(_atomic_dec_and_lock); -+ -+int _atomic_dec_and_lock_irqsave(atomic_t *atomic, spinlock_t *lock, -+ unsigned long *flags) -+{ -+ /* Subtract 1 from counter unless that drops it to 0 (ie. it was 1) */ -+ if (atomic_add_unless(atomic, -1, 1)) -+ return 0; -+ -+ /* Otherwise do it the slow way */ -+ spin_lock_irqsave(lock, *flags); -+ if (atomic_dec_and_test(atomic)) -+ return 1; -+ spin_unlock_irqrestore(lock, *flags); -+ return 0; -+} -+EXPORT_SYMBOL(_atomic_dec_and_lock_irqsave); diff --git a/patches.suse/0079-md-raid1-avoid-soft-lockup-under-high-load.patch b/patches.suse/0079-md-raid1-avoid-soft-lockup-under-high-load.patch new file mode 100644 index 0000000..5b2e9cb --- /dev/null +++ b/patches.suse/0079-md-raid1-avoid-soft-lockup-under-high-load.patch @@ -0,0 +1,34 @@ +From 5fa4f8bac9516b988d2ccd3f05f4267f8da24269 Mon Sep 17 00:00:00 2001 +From: Hannes Reinecke +Date: Fri, 25 Oct 2019 09:08:56 +0200 +Subject: [PATCH] md/raid1: avoid soft lockup under high load +Git-commit: 5fa4f8bac9516b988d2ccd3f05f4267f8da24269 +Patch-mainline: v5.5-rc1 +References: bsc#1166003 + +As all I/O is being pushed through a kernel thread the softlockup +watchdog might be triggered under high load. + +Signed-off-by: Hannes Reinecke +Signed-off-by: Song Liu +Signed-off-by: Coly Li + +--- + drivers/md/raid1.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c +index bb29aeefcbd0..a409ab6f30bc 100644 +--- a/drivers/md/raid1.c ++++ b/drivers/md/raid1.c +@@ -819,6 +819,7 @@ static void flush_bio_list(struct r1conf *conf, struct bio *bio) + else + generic_make_request(bio); + bio = next; ++ cond_resched(); + } + } + +-- +2.25.0 + diff --git a/patches.suse/0080-md-avoid-invalid-memory-access-for-array-sb-dev_role.patch b/patches.suse/0080-md-avoid-invalid-memory-access-for-array-sb-dev_role.patch new file mode 100644 index 0000000..1fb1f50 --- /dev/null +++ b/patches.suse/0080-md-avoid-invalid-memory-access-for-array-sb-dev_role.patch @@ -0,0 +1,128 @@ +From 228fc7d76db68732677230a3c64337908fd298e3 Mon Sep 17 00:00:00 2001 +From: Yufen Yu +Date: Wed, 30 Oct 2019 18:47:02 +0800 +Subject: [PATCH] md: avoid invalid memory access for array sb->dev_roles +Git-commit: 228fc7d76db68732677230a3c64337908fd298e3 +Patch-mainline: v5.5-rc1 +References: bsc#1166003 + +we need to gurantee 'desc_nr' valid before access array +of sb->dev_roles. + +In addition, we should avoid .load_super always return '0' +when level is LEVEL_MULTIPATH, which is not expected. + +Reported-by: coverity-bot +Addresses-coverity-id: 1487373 ("Memory - illegal accesses") +Fixes: 6a5cb53aaa4e ("md: no longer compare spare disk superblock events in super_load") +Signed-off-by: Yufen Yu +Signed-off-by: Song Liu +Signed-off-by: Coly Li + +--- + drivers/md/md.c | 51 +++++++++++++++++++------------------------------ + 1 file changed, 20 insertions(+), 31 deletions(-) + +diff --git a/drivers/md/md.c b/drivers/md/md.c +index 6f0ecfe8eab2..805b33e27496 100644 +--- a/drivers/md/md.c ++++ b/drivers/md/md.c +@@ -1105,6 +1105,7 @@ static int super_90_load(struct md_rdev *rdev, struct md_rdev *refdev, int minor + char b[BDEVNAME_SIZE], b2[BDEVNAME_SIZE]; + mdp_super_t *sb; + int ret; ++ bool spare_disk = true; + + /* + * Calculate the position of the superblock (512byte sectors), +@@ -1155,13 +1156,15 @@ static int super_90_load(struct md_rdev *rdev, struct md_rdev *refdev, int minor + else + rdev->desc_nr = sb->this_disk.number; + ++ /* not spare disk, or LEVEL_MULTIPATH */ ++ if (sb->level == LEVEL_MULTIPATH || ++ (rdev->desc_nr >= 0 && ++ sb->disks[rdev->desc_nr].state & ++ ((1<disks[rdev->desc_nr].state & ( +- (1<disks[rdev->desc_nr].state & ( +- (1< ev2)) ++ if (!spare_disk && ev1 > ev2) + ret = 1; + else + ret = 0; +@@ -1547,7 +1544,7 @@ static int super_1_load(struct md_rdev *rdev, struct md_rdev *refdev, int minor_ + sector_t sectors; + char b[BDEVNAME_SIZE], b2[BDEVNAME_SIZE]; + int bmask; +- __u64 role; ++ bool spare_disk = true; + + /* + * Calculate the position of the superblock in 512byte sectors. +@@ -1681,17 +1678,16 @@ static int super_1_load(struct md_rdev *rdev, struct md_rdev *refdev, int minor_ + sb->level != 0) + return -EINVAL; + +- role = le16_to_cpu(sb->dev_roles[rdev->desc_nr]); ++ /* not spare disk, or LEVEL_MULTIPATH */ ++ if (sb->level == cpu_to_le32(LEVEL_MULTIPATH) || ++ (rdev->desc_nr >= 0 && ++ rdev->desc_nr < le32_to_cpu(sb->max_dev) && ++ (le16_to_cpu(sb->dev_roles[rdev->desc_nr]) < MD_DISK_ROLE_MAX || ++ le16_to_cpu(sb->dev_roles[rdev->desc_nr]) == MD_DISK_ROLE_JOURNAL))) ++ spare_disk = false; + + if (!refdev) { +- /* +- * Insist of good event counter while assembling, except for +- * spares (which don't need an event count) +- */ +- if (rdev->desc_nr >= 0 && +- rdev->desc_nr < le32_to_cpu(sb->max_dev) && +- (role < MD_DISK_ROLE_MAX || +- role == MD_DISK_ROLE_JOURNAL)) ++ if (!spare_disk) + ret = 1; + else + ret = 0; +@@ -1711,14 +1707,7 @@ static int super_1_load(struct md_rdev *rdev, struct md_rdev *refdev, int minor_ + ev1 = le64_to_cpu(sb->events); + ev2 = le64_to_cpu(refsb->events); + +- /* +- * Insist of good event counter while assembling, except for +- * spares (which don't need an event count) +- */ +- if (rdev->desc_nr >= 0 && +- rdev->desc_nr < le32_to_cpu(sb->max_dev) && +- (role < MD_DISK_ROLE_MAX || +- role == MD_DISK_ROLE_JOURNAL) && ev1 > ev2) ++ if (!spare_disk && ev1 > ev2) + ret = 1; + else + ret = 0; +-- +2.25.0 + diff --git a/patches.suse/0081-md-raid10-prevent-access-of-uninitialized-resync_pag.patch b/patches.suse/0081-md-raid10-prevent-access-of-uninitialized-resync_pag.patch new file mode 100644 index 0000000..e0a5ef7 --- /dev/null +++ b/patches.suse/0081-md-raid10-prevent-access-of-uninitialized-resync_pag.patch @@ -0,0 +1,45 @@ +From 45422b704db392a6d79d07ee3e3670b11048bd53 Mon Sep 17 00:00:00 2001 +From: John Pittman +Date: Mon, 11 Nov 2019 16:43:20 -0800 +Subject: [PATCH] md/raid10: prevent access of uninitialized resync_pages + offset +Git-commit: 45422b704db392a6d79d07ee3e3670b11048bd53 +Patch-mainline: v5.5-rc1 +References: bsc#1166003 + +Due to unneeded multiplication in the out_free_pages portion of +r10buf_pool_alloc(), when using a 3-copy raid10 layout, it is +possible to access a resync_pages offset that has not been +initialized. This access translates into a crash of the system +within resync_free_pages() while passing a bad pointer to +put_page(). Remove the multiplication, preventing access to the +uninitialized area. + +Fixes: f0250618361db ("md: raid10: don't use bio's vec table to manage resync pages") +Cc: stable@vger.kernel.org # 4.12+ +Signed-off-by: John Pittman +Suggested-by: David Jeffery +Reviewed-by: Laurence Oberman +Signed-off-by: Song Liu +Signed-off-by: Coly Li + +--- + drivers/md/raid10.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c +index 2eca0a81a8c9..ec136e44aef7 100644 +--- a/drivers/md/raid10.c ++++ b/drivers/md/raid10.c +@@ -191,7 +191,7 @@ static void * r10buf_pool_alloc(gfp_t gfp_flags, void *data) + + out_free_pages: + while (--j >= 0) +- resync_free_pages(&rps[j * 2]); ++ resync_free_pages(&rps[j]); + + j = 0; + out_free_bio: +-- +2.25.0 + diff --git a/patches.suse/0082-drivers-md-raid5.c-use-the-new-spelling-of-RWH_WRITE.patch b/patches.suse/0082-drivers-md-raid5.c-use-the-new-spelling-of-RWH_WRITE.patch new file mode 100644 index 0000000..a606265 --- /dev/null +++ b/patches.suse/0082-drivers-md-raid5.c-use-the-new-spelling-of-RWH_WRITE.patch @@ -0,0 +1,44 @@ +From f1934892bd76ec127af4dd1ed17b73bc29b944a8 Mon Sep 17 00:00:00 2001 +From: Eugene Syromiatnikov +Date: Fri, 20 Sep 2019 17:58:28 +0200 +Subject: [PATCH] drivers/md/raid5.c: use the new spelling of + RWH_WRITE_LIFE_NOT_SET +Git-commit: f1934892bd76ec127af4dd1ed17b73bc29b944a8 +Patch-mainline: v5.5-rc1 +References: bsc#1166003 + +As it is consistent with prefixes of other write life time hints. + +Signed-off-by: Eugene Syromiatnikov +Signed-off-by: Song Liu +Signed-off-by: Coly Li + +--- + drivers/md/raid5.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c +index 12a8ce83786e..f0fc538bfe59 100644 +--- a/drivers/md/raid5.c ++++ b/drivers/md/raid5.c +@@ -1134,7 +1134,7 @@ static void ops_run_io(struct stripe_head *sh, struct stripe_head_state *s) + bi->bi_iter.bi_size = STRIPE_SIZE; + bi->bi_write_hint = sh->dev[i].write_hint; + if (!rrdev) +- sh->dev[i].write_hint = RWF_WRITE_LIFE_NOT_SET; ++ sh->dev[i].write_hint = RWH_WRITE_LIFE_NOT_SET; + /* + * If this is discard request, set bi_vcnt 0. We don't + * want to confuse SCSI because SCSI will replace payload +@@ -1187,7 +1187,7 @@ static void ops_run_io(struct stripe_head *sh, struct stripe_head_state *s) + rbi->bi_io_vec[0].bv_offset = 0; + rbi->bi_iter.bi_size = STRIPE_SIZE; + rbi->bi_write_hint = sh->dev[i].write_hint; +- sh->dev[i].write_hint = RWF_WRITE_LIFE_NOT_SET; ++ sh->dev[i].write_hint = RWH_WRITE_LIFE_NOT_SET; + /* + * If this is discard request, set bi_vcnt 0. We don't + * want to confuse SCSI because SCSI will replace payload +-- +2.25.0 + diff --git a/patches.suse/0083-drivers-md-raid5-ppl.c-use-the-new-spelling-of-RWH_W.patch b/patches.suse/0083-drivers-md-raid5-ppl.c-use-the-new-spelling-of-RWH_W.patch new file mode 100644 index 0000000..b4f9271 --- /dev/null +++ b/patches.suse/0083-drivers-md-raid5-ppl.c-use-the-new-spelling-of-RWH_W.patch @@ -0,0 +1,35 @@ +From 0815ef3c019d280eb1b38e63ca7280f0f7db2bf8 Mon Sep 17 00:00:00 2001 +From: Eugene Syromiatnikov +Date: Fri, 20 Sep 2019 17:58:34 +0200 +Subject: [PATCH] drivers/md/raid5-ppl.c: use the new spelling of + RWH_WRITE_LIFE_NOT_SET +Git-commit: 0815ef3c019d280eb1b38e63ca7280f0f7db2bf8 +Patch-mainline: v5.5-rc1 +References: bsc#1166003 + +As it is consistent with prefixes of other write life time hints. + +Signed-off-by: Eugene Syromiatnikov +Signed-off-by: Song Liu +Signed-off-by: Coly Li + +--- + drivers/md/raid5-ppl.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/md/raid5-ppl.c b/drivers/md/raid5-ppl.c +index 18a4064a61a8..cab5b1352892 100644 +--- a/drivers/md/raid5-ppl.c ++++ b/drivers/md/raid5-ppl.c +@@ -1404,7 +1404,7 @@ int ppl_init_log(struct r5conf *conf) + atomic64_set(&ppl_conf->seq, 0); + INIT_LIST_HEAD(&ppl_conf->no_mem_stripes); + spin_lock_init(&ppl_conf->no_mem_stripes_lock); +- ppl_conf->write_hint = RWF_WRITE_LIFE_NOT_SET; ++ ppl_conf->write_hint = RWH_WRITE_LIFE_NOT_SET; + + if (!mddev->external) { + ppl_conf->signature = ~crc32c_le(~0, mddev->uuid, sizeof(mddev->uuid)); +-- +2.25.0 + diff --git a/patches.suse/0084-raid5-need-to-set-STRIPE_HANDLE-for-batch-head.patch b/patches.suse/0084-raid5-need-to-set-STRIPE_HANDLE-for-batch-head.patch new file mode 100644 index 0000000..269648b --- /dev/null +++ b/patches.suse/0084-raid5-need-to-set-STRIPE_HANDLE-for-batch-head.patch @@ -0,0 +1,45 @@ +From a7ede3d16808b8f3915c8572d783530a82b2f027 Mon Sep 17 00:00:00 2001 +From: Guoqing Jiang +Date: Wed, 27 Nov 2019 17:57:50 +0100 +Subject: [PATCH] raid5: need to set STRIPE_HANDLE for batch head +Git-commit: a7ede3d16808b8f3915c8572d783530a82b2f027 +Patch-mainline: v5.5-rc2 +References: bsc#1166003 + +With commit 6ce220dd2f8ea71d6afc29b9a7524c12e39f374a ("raid5: don't set +STRIPE_HANDLE to stripe which is in batch list"), we don't want to set +STRIPE_HANDLE flag for sh which is already in batch list. + +However, the stripe which is the head of batch list should set this flag, +otherwise panic could happen inside init_stripe at BUG_ON(sh->batch_head), +it is reproducible with raid5 on top of nvdimm devices per Xiao oberserved. + +Thanks for Xiao's effort to verify the change. + +Fixes: 6ce220dd2f8ea ("raid5: don't set STRIPE_HANDLE to stripe which is in batch list") +Reported-by: Xiao Ni +Tested-by: Xiao Ni +Signed-off-by: Guoqing Jiang +Signed-off-by: Song Liu +Signed-off-by: Coly Li + +--- + drivers/md/raid5.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c +index f0fc538bfe59..d4d3b67ffbba 100644 +--- a/drivers/md/raid5.c ++++ b/drivers/md/raid5.c +@@ -5726,7 +5726,7 @@ static bool raid5_make_request(struct mddev *mddev, struct bio * bi) + do_flush = false; + } + +- if (!sh->batch_head) ++ if (!sh->batch_head || sh == sh->batch_head) + set_bit(STRIPE_HANDLE, &sh->state); + clear_bit(STRIPE_DELAYED, &sh->state); + if ((!sh->batch_head || sh == sh->batch_head) && +-- +2.25.0 + diff --git a/patches.suse/0085-md-raid1-check-rdev-before-reference-in-raid1_sync_r.patch b/patches.suse/0085-md-raid1-check-rdev-before-reference-in-raid1_sync_r.patch new file mode 100644 index 0000000..62e8cdd --- /dev/null +++ b/patches.suse/0085-md-raid1-check-rdev-before-reference-in-raid1_sync_r.patch @@ -0,0 +1,35 @@ +From 028288df635f5a9addd48ac4677b720192747944 Mon Sep 17 00:00:00 2001 +From: Zhiqiang Liu +Date: Tue, 10 Dec 2019 10:42:25 +0800 +Subject: [PATCH] md: raid1: check rdev before reference in raid1_sync_request + func +Git-commit: 028288df635f5a9addd48ac4677b720192747944 +Patch-mainline: v5.5-rc2 +References: bsc#1166003 + +In raid1_sync_request func, rdev should be checked before reference. + +Signed-off-by: Zhiqiang Liu +Signed-off-by: Song Liu +Signed-off-by: Coly Li + +--- + drivers/md/raid1.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c +index a409ab6f30bc..201fd8aec59a 100644 +--- a/drivers/md/raid1.c ++++ b/drivers/md/raid1.c +@@ -2782,7 +2782,7 @@ static sector_t raid1_sync_request(struct mddev *mddev, sector_t sector_nr, + write_targets++; + } + } +- if (bio->bi_end_io) { ++ if (rdev && bio->bi_end_io) { + atomic_inc(&rdev->nr_pending); + bio->bi_iter.bi_sector = sector_nr + rdev->data_offset; + bio_set_dev(bio, rdev->bdev); +-- +2.25.0 + diff --git a/patches.suse/0086-md-make-sure-desc_nr-less-than-MD_SB_DISKS.patch b/patches.suse/0086-md-make-sure-desc_nr-less-than-MD_SB_DISKS.patch new file mode 100644 index 0000000..145366b --- /dev/null +++ b/patches.suse/0086-md-make-sure-desc_nr-less-than-MD_SB_DISKS.patch @@ -0,0 +1,35 @@ +From 3b7436cc9449d5ff7fa1c1fd5bc3edb6402ff5b8 Mon Sep 17 00:00:00 2001 +From: Yufen Yu +Date: Tue, 10 Dec 2019 15:01:29 +0800 +Subject: [PATCH] md: make sure desc_nr less than MD_SB_DISKS +Git-commit: 3b7436cc9449d5ff7fa1c1fd5bc3edb6402ff5b8 +Patch-mainline: v5.5-rc2 +References: bsc#1166003 + +For super_90_load, we need to make sure 'desc_nr' less +than MD_SB_DISKS, avoiding invalid memory access of 'sb->disks'. + +Fixes: 228fc7d76db6 ("md: avoid invalid memory access for array sb->dev_roles") +Signed-off-by: Yufen Yu +Signed-off-by: Song Liu +Signed-off-by: Coly Li + +--- + drivers/md/md.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/md/md.c b/drivers/md/md.c +index 805b33e27496..4e7c9f398bc6 100644 +--- a/drivers/md/md.c ++++ b/drivers/md/md.c +@@ -1159,6 +1159,7 @@ static int super_90_load(struct md_rdev *rdev, struct md_rdev *refdev, int minor + /* not spare disk, or LEVEL_MULTIPATH */ + if (sb->level == LEVEL_MULTIPATH || + (rdev->desc_nr >= 0 && ++ rdev->desc_nr < MD_SB_DISKS && + sb->disks[rdev->desc_nr].state & + ((1< +Date: Sat, 7 Dec 2019 11:00:08 +0800 +Subject: [PATCH] md-bitmap: small cleanups +Git-commit: 55180498dfd5f3c7e2d2c0e470f7cede1acee248 +Patch-mainline: v5.6-rc1 +References: bsc#1166003 + +In md_bitmap_unplug, bitmap->storage.filemap is double checked. + +In md_bitmap_daemon_work, bitmap->storage.filemap should be checked +before reference. + +Signed-off-by: Zhiqiang Liu +Signed-off-by: Song Liu +Signed-off-by: Coly Li + +--- + drivers/md/md-bitmap.c | 5 ++--- + 1 file changed, 2 insertions(+), 3 deletions(-) + +diff --git a/drivers/md/md-bitmap.c b/drivers/md/md-bitmap.c +index 3ad18246fcb3..9860062bdc1e 100644 +--- a/drivers/md/md-bitmap.c ++++ b/drivers/md/md-bitmap.c +@@ -1019,8 +1019,6 @@ void md_bitmap_unplug(struct bitmap *bitmap) + /* look at each page to see if there are any set bits that need to be + * flushed out to disk */ + for (i = 0; i < bitmap->storage.file_pages; i++) { +- if (!bitmap->storage.filemap) +- return; + dirty = test_and_clear_page_attr(bitmap, i, BITMAP_PAGE_DIRTY); + need_write = test_and_clear_page_attr(bitmap, i, + BITMAP_PAGE_NEEDWRITE); +@@ -1338,7 +1336,8 @@ void md_bitmap_daemon_work(struct mddev *mddev) + BITMAP_PAGE_DIRTY)) + /* bitmap_unplug will handle the rest */ + break; +- if (test_and_clear_page_attr(bitmap, j, ++ if (bitmap->storage.filemap && ++ test_and_clear_page_attr(bitmap, j, + BITMAP_PAGE_NEEDWRITE)) { + write_page(bitmap, bitmap->storage.filemap[j], 0); + } +-- +2.25.0 + diff --git a/patches.suse/0087-md-remove-a-bogus-comment.patch b/patches.suse/0087-md-remove-a-bogus-comment.patch deleted file mode 100644 index 97055c9..0000000 --- a/patches.suse/0087-md-remove-a-bogus-comment.patch +++ /dev/null @@ -1,38 +0,0 @@ -From 3ed122e68bb2dcab36b48109431341736e37ce85 Mon Sep 17 00:00:00 2001 -From: Christoph Hellwig -Date: Tue, 24 Jul 2018 09:52:33 +0200 -Subject: [PATCH] md: remove a bogus comment -Git-commit: 3ed122e68bb2dcab36b48109431341736e37ce85 -References: bsc#1111974 -Patch-mainline: v4.19-rc1 - -The function name mentioned doesn't exist, and the code next to it -doesn't match the description either. - -Signed-off-by: Christoph Hellwig -Reviewed-by: Ming Lei -Signed-off-by: Jens Axboe -Signed-off-by: Coly Li - ---- - drivers/md/md.c | 4 ---- - 1 file changed, 4 deletions(-) - -diff --git a/drivers/md/md.c b/drivers/md/md.c -index f6e58dbca0d4..cb4eb5faa519 100644 ---- a/drivers/md/md.c -+++ b/drivers/md/md.c -@@ -204,10 +204,6 @@ static int start_readonly; - */ - static bool create_on_open = true; - --/* bio_clone_mddev -- * like bio_clone_bioset, but with a local bio set -- */ -- - struct bio *bio_alloc_mddev(gfp_t gfp_mask, int nr_iovecs, - struct mddev *mddev) - { --- -2.19.0 - diff --git a/patches.suse/0088-raid6-test-fix-a-compilation-error.patch b/patches.suse/0088-raid6-test-fix-a-compilation-error.patch new file mode 100644 index 0000000..9ffc201 --- /dev/null +++ b/patches.suse/0088-raid6-test-fix-a-compilation-error.patch @@ -0,0 +1,55 @@ +From 6b8651aac1dca6140dd7fb4c9fec2736ed3f6223 Mon Sep 17 00:00:00 2001 +From: Zhengyuan Liu +Date: Fri, 20 Dec 2019 10:21:26 +0800 +Subject: [PATCH] raid6/test: fix a compilation error +Git-commit: 6b8651aac1dca6140dd7fb4c9fec2736ed3f6223 +Patch-mainline: v5.6-rc1 +References: bsc#1166003 + +The compilation error is redeclaration showed as following: + + In file included from ../../../include/linux/limits.h:6, + from /usr/include/x86_64-linux-gnu/bits/local_lim.h:38, + from /usr/include/x86_64-linux-gnu/bits/posix1_lim.h:161, + from /usr/include/limits.h:183, + from /usr/lib/gcc/x86_64-linux-gnu/8/include-fixed/limits.h:194, + from /usr/lib/gcc/x86_64-linux-gnu/8/include-fixed/syslimits.h:7, + from /usr/lib/gcc/x86_64-linux-gnu/8/include-fixed/limits.h:34, + from ../../../include/linux/raid/pq.h:30, + from algos.c:14: + ../../../include/linux/types.h:114:15: error: conflicting types for ‘int64_t’ + typedef s64 int64_t; + ^~~~~~~ + In file included from /usr/include/stdint.h:34, + from /usr/lib/gcc/x86_64-linux-gnu/8/include/stdint.h:9, + from /usr/include/inttypes.h:27, + from ../../../include/linux/raid/pq.h:29, + from algos.c:14: + /usr/include/x86_64-linux-gnu/bits/stdint-intn.h:27:19: note: previous \ + declaration of ‘int64_t’ was here + typedef __int64_t int64_t; + +Fixes: 54d50897d544 ("linux/kernel.h: split *_MAX and *_MIN macros into ") +Signed-off-by: Zhengyuan Liu +Signed-off-by: Song Liu +Signed-off-by: Coly Li + +--- + include/linux/raid/pq.h | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/include/linux/raid/pq.h b/include/linux/raid/pq.h +index 0832c9b66852..0b6e7ad9cd2a 100644 +--- a/include/linux/raid/pq.h ++++ b/include/linux/raid/pq.h +@@ -27,7 +27,6 @@ extern const char raid6_empty_zero_page[PAGE_SIZE]; + + #include + #include +-#include + #include + #include + #include +-- +2.25.0 + diff --git a/patches.suse/0089-raid6-test-fix-a-compilation-warning.patch b/patches.suse/0089-raid6-test-fix-a-compilation-warning.patch new file mode 100644 index 0000000..d7edfcd --- /dev/null +++ b/patches.suse/0089-raid6-test-fix-a-compilation-warning.patch @@ -0,0 +1,59 @@ +From 5e5ac01c2b8802921fee680518a986011cb59820 Mon Sep 17 00:00:00 2001 +From: Zhengyuan Liu +Date: Fri, 20 Dec 2019 10:21:27 +0800 +Subject: [PATCH] raid6/test: fix a compilation warning +Git-commit: 5e5ac01c2b8802921fee680518a986011cb59820 +Patch-mainline: v5.6-rc1 +References: bsc#1166003 + +The compilation warning is redefination showed as following: + + In file included from tables.c:2: + ../../../include/linux/export.h:180: warning: "EXPORT_SYMBOL" redefined + #define EXPORT_SYMBOL(sym) __EXPORT_SYMBOL(sym, "") + + In file included from tables.c:1: + ../../../include/linux/raid/pq.h:61: note: this is the location of the previous definition + #define EXPORT_SYMBOL(sym) + +Fixes: 69a94abb82ee ("export.h, genksyms: do not make genksyms calculate CRC of trimmed symbols") +Signed-off-by: Zhengyuan Liu +Signed-off-by: Song Liu +Signed-off-by: Coly Li + +--- + include/linux/raid/pq.h | 2 ++ + lib/raid6/mktables.c | 2 +- + 2 files changed, 3 insertions(+), 1 deletion(-) + +diff --git a/include/linux/raid/pq.h b/include/linux/raid/pq.h +index 0b6e7ad9cd2a..e0ddb47f4402 100644 +--- a/include/linux/raid/pq.h ++++ b/include/linux/raid/pq.h +@@ -58,7 +58,9 @@ extern const char raid6_empty_zero_page[PAGE_SIZE]; + #define enable_kernel_altivec() + #define disable_kernel_altivec() + ++#undef EXPORT_SYMBOL + #define EXPORT_SYMBOL(sym) ++#undef EXPORT_SYMBOL_GPL + #define EXPORT_SYMBOL_GPL(sym) + #define MODULE_LICENSE(licence) + #define MODULE_DESCRIPTION(desc) +diff --git a/lib/raid6/mktables.c b/lib/raid6/mktables.c +index 9c485df1308f..f02e10fa6238 100644 +--- a/lib/raid6/mktables.c ++++ b/lib/raid6/mktables.c +@@ -56,8 +56,8 @@ int main(int argc, char *argv[]) + uint8_t v; + uint8_t exptbl[256], invtbl[256]; + +- printf("#include \n"); + printf("#include \n"); ++ printf("#include \n"); + + /* Compute multiplication table */ + printf("\nconst u8 __attribute__((aligned(256)))\n" +-- +2.25.0 + diff --git a/patches.suse/0090-md-raid6-fix-algorithm-choice-under-larger-PAGE_SIZE.patch b/patches.suse/0090-md-raid6-fix-algorithm-choice-under-larger-PAGE_SIZE.patch new file mode 100644 index 0000000..67b921c --- /dev/null +++ b/patches.suse/0090-md-raid6-fix-algorithm-choice-under-larger-PAGE_SIZE.patch @@ -0,0 +1,180 @@ +From f591df3cc6d60cadf8ceff5d44af73ea6ba0a39a Mon Sep 17 00:00:00 2001 +From: Zhengyuan Liu +Date: Fri, 20 Dec 2019 10:21:28 +0800 +Subject: [PATCH] md/raid6: fix algorithm choice under larger PAGE_SIZE +Git-commit: f591df3cc6d60cadf8ceff5d44af73ea6ba0a39a +Patch-mainline: v5.6-rc1 +References: bsc#1166003 + +There are several algorithms available for raid6 to generate xor and syndrome +parity, including basic int1, int2 ... int32 and SIMD optimized implementation +like sse and neon. To test and choose the best algorithms at the initial +stage, we need provide enough disk data to feed the algorithms. However, the +disk number we provided depends on page size and gfmul table, seeing bellow: + + const int disks = (65536/PAGE_SIZE) + 2; + +So when come to 64K PAGE_SIZE, there is only one data disk plus 2 parity disk, +as a result the chosed algorithm is not reliable. For example, on my arm64 +machine with 64K page enabled, it will choose intx32 as the best one, although +the NEON implementation is better. + +This patch tries to fix the problem by defining a constant raid6 disk number to +supporting arbitrary page size. + +Suggested-by: H. Peter Anvin +Signed-off-by: Zhengyuan Liu +Signed-off-by: Song Liu +Signed-off-by: Coly Li + +--- + include/linux/raid/pq.h | 4 +++ + lib/raid6/algos.c | 63 ++++++++++++++++++++++++++--------------- + 2 files changed, 44 insertions(+), 23 deletions(-) + +diff --git a/include/linux/raid/pq.h b/include/linux/raid/pq.h +index e0ddb47f4402..154e954b711d 100644 +--- a/include/linux/raid/pq.h ++++ b/include/linux/raid/pq.h +@@ -28,6 +28,7 @@ extern const char raid6_empty_zero_page[PAGE_SIZE]; + #include + #include + #include ++#include + #include + #include + #include +@@ -43,6 +44,9 @@ typedef uint64_t u64; + #ifndef PAGE_SIZE + # define PAGE_SIZE 4096 + #endif ++#ifndef PAGE_SHIFT ++# define PAGE_SHIFT 12 ++#endif + extern const char raid6_empty_zero_page[PAGE_SIZE]; + + #define __init +diff --git a/lib/raid6/algos.c b/lib/raid6/algos.c +index 17417eee0866..bf1b4765c8f6 100644 +--- a/lib/raid6/algos.c ++++ b/lib/raid6/algos.c +@@ -124,6 +124,9 @@ const struct raid6_recov_calls *const raid6_recov_algos[] = { + #define time_before(x, y) ((x) < (y)) + #endif + ++#define RAID6_TEST_DISKS 8 ++#define RAID6_TEST_DISKS_ORDER 3 ++ + static inline const struct raid6_recov_calls *raid6_choose_recov(void) + { + const struct raid6_recov_calls *const *algo; +@@ -146,7 +149,7 @@ static inline const struct raid6_recov_calls *raid6_choose_recov(void) + } + + static inline const struct raid6_calls *raid6_choose_gen( +- void *(*const dptrs)[(65536/PAGE_SIZE)+2], const int disks) ++ void *(*const dptrs)[RAID6_TEST_DISKS], const int disks) + { + unsigned long perf, bestgenperf, bestxorperf, j0, j1; + int start = (disks>>1)-1, stop = disks-3; /* work on the second half of the disks */ +@@ -181,7 +184,8 @@ static inline const struct raid6_calls *raid6_choose_gen( + best = *algo; + } + pr_info("raid6: %-8s gen() %5ld MB/s\n", (*algo)->name, +- (perf*HZ) >> (20-16+RAID6_TIME_JIFFIES_LG2)); ++ (perf * HZ * (disks-2)) >> ++ (20 - PAGE_SHIFT + RAID6_TIME_JIFFIES_LG2)); + + if (!(*algo)->xor_syndrome) + continue; +@@ -204,17 +208,24 @@ static inline const struct raid6_calls *raid6_choose_gen( + bestxorperf = perf; + + pr_info("raid6: %-8s xor() %5ld MB/s\n", (*algo)->name, +- (perf*HZ) >> (20-16+RAID6_TIME_JIFFIES_LG2+1)); ++ (perf * HZ * (disks-2)) >> ++ (20 - PAGE_SHIFT + RAID6_TIME_JIFFIES_LG2 + 1)); + } + } + + if (best) { +- pr_info("raid6: using algorithm %s gen() %ld MB/s\n", +- best->name, +- (bestgenperf*HZ) >> (20-16+RAID6_TIME_JIFFIES_LG2)); +- if (best->xor_syndrome) +- pr_info("raid6: .... xor() %ld MB/s, rmw enabled\n", +- (bestxorperf*HZ) >> (20-16+RAID6_TIME_JIFFIES_LG2+1)); ++ if (IS_ENABLED(CONFIG_RAID6_PQ_BENCHMARK)) { ++ pr_info("raid6: using algorithm %s gen() %ld MB/s\n", ++ best->name, ++ (bestgenperf * HZ * (disks-2)) >> ++ (20 - PAGE_SHIFT+RAID6_TIME_JIFFIES_LG2)); ++ if (best->xor_syndrome) ++ pr_info("raid6: .... xor() %ld MB/s, rmw enabled\n", ++ (bestxorperf * HZ * (disks-2)) >> ++ (20 - PAGE_SHIFT + RAID6_TIME_JIFFIES_LG2 + 1)); ++ } else ++ pr_info("raid6: skip pq benchmark and using algorithm %s\n", ++ best->name); + raid6_call = *best; + } else + pr_err("raid6: Yikes! No algorithm found!\n"); +@@ -228,27 +239,33 @@ static inline const struct raid6_calls *raid6_choose_gen( + + int __init raid6_select_algo(void) + { +- const int disks = (65536/PAGE_SIZE)+2; ++ const int disks = RAID6_TEST_DISKS; + + const struct raid6_calls *gen_best; + const struct raid6_recov_calls *rec_best; +- char *syndromes; +- void *dptrs[(65536/PAGE_SIZE)+2]; +- int i; +- +- for (i = 0; i < disks-2; i++) +- dptrs[i] = ((char *)raid6_gfmul) + PAGE_SIZE*i; +- +- /* Normal code - use a 2-page allocation to avoid D$ conflict */ +- syndromes = (void *) __get_free_pages(GFP_KERNEL, 1); ++ char *disk_ptr, *p; ++ void *dptrs[RAID6_TEST_DISKS]; ++ int i, cycle; + +- if (!syndromes) { ++ /* prepare the buffer and fill it circularly with gfmul table */ ++ disk_ptr = (char *)__get_free_pages(GFP_KERNEL, RAID6_TEST_DISKS_ORDER); ++ if (!disk_ptr) { + pr_err("raid6: Yikes! No memory available.\n"); + return -ENOMEM; + } + +- dptrs[disks-2] = syndromes; +- dptrs[disks-1] = syndromes + PAGE_SIZE; ++ p = disk_ptr; ++ for (i = 0; i < disks; i++) ++ dptrs[i] = p + PAGE_SIZE * i; ++ ++ cycle = ((disks - 2) * PAGE_SIZE) / 65536; ++ for (i = 0; i < cycle; i++) { ++ memcpy(p, raid6_gfmul, 65536); ++ p += 65536; ++ } ++ ++ if ((disks - 2) * PAGE_SIZE % 65536) ++ memcpy(p, raid6_gfmul, (disks - 2) * PAGE_SIZE % 65536); + + /* select raid gen_syndrome function */ + gen_best = raid6_choose_gen(&dptrs, disks); +@@ -256,7 +273,7 @@ int __init raid6_select_algo(void) + /* select raid recover functions */ + rec_best = raid6_choose_recov(); + +- free_pages((unsigned long)syndromes, 1); ++ free_pages((unsigned long)disk_ptr, RAID6_TEST_DISKS_ORDER); + + return gen_best && rec_best ? 0 : -EINVAL; + } +-- +2.25.0 + diff --git a/patches.suse/0091-raid5-remove-worker_cnt_per_group-argument-from-allo.patch b/patches.suse/0091-raid5-remove-worker_cnt_per_group-argument-from-allo.patch new file mode 100644 index 0000000..aa0e54c --- /dev/null +++ b/patches.suse/0091-raid5-remove-worker_cnt_per_group-argument-from-allo.patch @@ -0,0 +1,95 @@ +From d2c9ad41249ac862d3a3a4d5d56e6b1cd79d8a17 Mon Sep 17 00:00:00 2001 +From: Guoqing Jiang +Date: Fri, 20 Dec 2019 15:46:29 +0100 +Subject: [PATCH] raid5: remove worker_cnt_per_group argument from + alloc_thread_groups +Git-commit: d2c9ad41249ac862d3a3a4d5d56e6b1cd79d8a17 +Patch-mainline: v5.6-rc1 +References: bsc#1166003 + +We can use "cnt" directly to update conf->worker_cnt_per_group +if alloc_thread_groups returns 0. + +Signed-off-by: Guoqing Jiang +Signed-off-by: Song Liu +Signed-off-by: Coly Li + +--- + drivers/md/raid5.c | 21 +++++++-------------- + 1 file changed, 7 insertions(+), 14 deletions(-) + +--- a/drivers/md/raid5.c ++++ b/drivers/md/raid5.c +@@ -6606,7 +6606,6 @@ raid5_show_group_thread_cnt(struct mddev + + static int alloc_thread_groups(struct r5conf *conf, int cnt, + int *group_cnt, +- int *worker_cnt_per_group, + struct r5worker_group **worker_groups); + static ssize_t + raid5_store_group_thread_cnt(struct mddev *mddev, const char *page, size_t len) +@@ -6615,7 +6614,7 @@ raid5_store_group_thread_cnt(struct mdde + unsigned int new; + int err; + struct r5worker_group *new_groups, *old_groups; +- int group_cnt, worker_cnt_per_group; ++ int group_cnt; + + if (len >= PAGE_SIZE) + return -EINVAL; +@@ -6638,13 +6637,11 @@ raid5_store_group_thread_cnt(struct mdde + if (old_groups) + flush_workqueue(raid5_wq); + +- err = alloc_thread_groups(conf, new, +- &group_cnt, &worker_cnt_per_group, +- &new_groups); ++ err = alloc_thread_groups(conf, new, &group_cnt, &new_groups); + if (!err) { + spin_lock_irq(&conf->device_lock); + conf->group_cnt = group_cnt; +- conf->worker_cnt_per_group = worker_cnt_per_group; ++ conf->worker_cnt_per_group = new; + conf->worker_groups = new_groups; + spin_unlock_irq(&conf->device_lock); + +@@ -6680,16 +6677,13 @@ static struct attribute_group raid5_attr + .attrs = raid5_attrs, + }; + +-static int alloc_thread_groups(struct r5conf *conf, int cnt, +- int *group_cnt, +- int *worker_cnt_per_group, ++static int alloc_thread_groups(struct r5conf *conf, int cnt, int *group_cnt, + struct r5worker_group **worker_groups) + { + int i, j, k; + ssize_t size; + struct r5worker *workers; + +- *worker_cnt_per_group = cnt; + if (cnt == 0) { + *group_cnt = 0; + *worker_groups = NULL; +@@ -6891,7 +6885,7 @@ static struct r5conf *setup_conf(struct + struct disk_info *disk; + char pers_name[6]; + int i; +- int group_cnt, worker_cnt_per_group; ++ int group_cnt; + struct r5worker_group *new_group; + + if (mddev->new_level != 5 +@@ -6935,10 +6929,9 @@ static struct r5conf *setup_conf(struct + for (i = 0; i < PENDING_IO_MAX; i++) + list_add(&conf->pending_data[i].sibling, &conf->free_list); + /* Don't enable multi-threading by default*/ +- if (!alloc_thread_groups(conf, 0, &group_cnt, &worker_cnt_per_group, +- &new_group)) { ++ if (!alloc_thread_groups(conf, 0, &group_cnt, &new_group)) { + conf->group_cnt = group_cnt; +- conf->worker_cnt_per_group = worker_cnt_per_group; ++ conf->worker_cnt_per_group = 0; + conf->worker_groups = new_group; + } else + goto abort; diff --git a/patches.suse/0092-md-rename-wb-stuffs.patch b/patches.suse/0092-md-rename-wb-stuffs.patch new file mode 100644 index 0000000..b787c00 --- /dev/null +++ b/patches.suse/0092-md-rename-wb-stuffs.patch @@ -0,0 +1,410 @@ +From 404659cf1e2570dad3cd117fa3bd71f06ecfd142 Mon Sep 17 00:00:00 2001 +From: Guoqing Jiang +Date: Mon, 23 Dec 2019 10:48:53 +0100 +Subject: [PATCH] md: rename wb stuffs +Git-commit: 404659cf1e2570dad3cd117fa3bd71f06ecfd142 +Patch-mainline: v5.6-rc1 +References: bsc#1166003 + +Previously, wb_info_pool and wb_list stuffs are introduced +to address potential data inconsistence issue for write +behind device. + +Now rename them to serial related name, since the same +mechanism will be used to address reorder overlap write +issue for raid1. + +Signed-off-by: Guoqing Jiang +Signed-off-by: Song Liu +Signed-off-by: Coly Li + +--- + drivers/md/md-bitmap.c | 20 ++++++------ + drivers/md/md.c | 70 ++++++++++++++++++++++-------------------- + drivers/md/md.h | 24 +++++++-------- + drivers/md/raid1.c | 43 +++++++++++++------------- + 4 files changed, 80 insertions(+), 77 deletions(-) + +diff --git a/drivers/md/md-bitmap.c b/drivers/md/md-bitmap.c +index 9860062bdc1e..212e75dfebb7 100644 +--- a/drivers/md/md-bitmap.c ++++ b/drivers/md/md-bitmap.c +@@ -1789,8 +1789,8 @@ void md_bitmap_destroy(struct mddev *mddev) + return; + + md_bitmap_wait_behind_writes(mddev); +- mempool_destroy(mddev->wb_info_pool); +- mddev->wb_info_pool = NULL; ++ mempool_destroy(mddev->serial_info_pool); ++ mddev->serial_info_pool = NULL; + + mutex_lock(&mddev->bitmap_info.mutex); + spin_lock(&mddev->lock); +@@ -1907,7 +1907,7 @@ int md_bitmap_load(struct mddev *mddev) + goto out; + + rdev_for_each(rdev, mddev) +- mddev_create_wb_pool(mddev, rdev, true); ++ mddev_create_serial_pool(mddev, rdev, true); + + if (mddev_is_clustered(mddev)) + md_cluster_ops->load_bitmaps(mddev, mddev->bitmap_info.nodes); +@@ -2474,16 +2474,16 @@ backlog_store(struct mddev *mddev, const char *buf, size_t len) + if (backlog > COUNTER_MAX) + return -EINVAL; + mddev->bitmap_info.max_write_behind = backlog; +- if (!backlog && mddev->wb_info_pool) { +- /* wb_info_pool is not needed if backlog is zero */ +- mempool_destroy(mddev->wb_info_pool); +- mddev->wb_info_pool = NULL; +- } else if (backlog && !mddev->wb_info_pool) { +- /* wb_info_pool is needed since backlog is not zero */ ++ if (!backlog && mddev->serial_info_pool) { ++ /* serial_info_pool is not needed if backlog is zero */ ++ mempool_destroy(mddev->serial_info_pool); ++ mddev->serial_info_pool = NULL; ++ } else if (backlog && !mddev->serial_info_pool) { ++ /* serial_info_pool is needed since backlog is not zero */ + struct md_rdev *rdev; + + rdev_for_each(rdev, mddev) +- mddev_create_wb_pool(mddev, rdev, false); ++ mddev_create_serial_pool(mddev, rdev, false); + } + if (old_mwb != backlog) + md_bitmap_update_sb(mddev->bitmap); +diff --git a/drivers/md/md.c b/drivers/md/md.c +index 4e7c9f398bc6..ea37bfacb6fb 100644 +--- a/drivers/md/md.c ++++ b/drivers/md/md.c +@@ -125,72 +125,74 @@ static inline int speed_max(struct mddev *mddev) + mddev->sync_speed_max : sysctl_speed_limit_max; + } + +-static int rdev_init_wb(struct md_rdev *rdev) ++static int rdev_init_serial(struct md_rdev *rdev) + { + if (rdev->bdev->bd_queue->nr_hw_queues == 1) + return 0; + +- spin_lock_init(&rdev->wb_list_lock); +- INIT_LIST_HEAD(&rdev->wb_list); +- init_waitqueue_head(&rdev->wb_io_wait); +- set_bit(WBCollisionCheck, &rdev->flags); ++ spin_lock_init(&rdev->serial_list_lock); ++ INIT_LIST_HEAD(&rdev->serial_list); ++ init_waitqueue_head(&rdev->serial_io_wait); ++ set_bit(CollisionCheck, &rdev->flags); + + return 1; + } + + /* +- * Create wb_info_pool if rdev is the first multi-queue device flaged ++ * Create serial_info_pool if rdev is the first multi-queue device flaged + * with writemostly, also write-behind mode is enabled. + */ +-void mddev_create_wb_pool(struct mddev *mddev, struct md_rdev *rdev, ++void mddev_create_serial_pool(struct mddev *mddev, struct md_rdev *rdev, + bool is_suspend) + { + if (mddev->bitmap_info.max_write_behind == 0) + return; + +- if (!test_bit(WriteMostly, &rdev->flags) || !rdev_init_wb(rdev)) ++ if (!test_bit(WriteMostly, &rdev->flags) || !rdev_init_serial(rdev)) + return; + +- if (mddev->wb_info_pool == NULL) { ++ if (mddev->serial_info_pool == NULL) { + unsigned int noio_flag; + + if (!is_suspend) + mddev_suspend(mddev); + noio_flag = memalloc_noio_save(); +- mddev->wb_info_pool = mempool_create_kmalloc_pool(NR_WB_INFOS, +- sizeof(struct wb_info)); ++ mddev->serial_info_pool = ++ mempool_create_kmalloc_pool(NR_SERIAL_INFOS, ++ sizeof(struct serial_info)); + memalloc_noio_restore(noio_flag); +- if (!mddev->wb_info_pool) +- pr_err("can't alloc memory pool for writemostly\n"); ++ if (!mddev->serial_info_pool) ++ pr_err("can't alloc memory pool for serialization\n"); + if (!is_suspend) + mddev_resume(mddev); + } + } +-EXPORT_SYMBOL_GPL(mddev_create_wb_pool); ++EXPORT_SYMBOL_GPL(mddev_create_serial_pool); + + /* +- * destroy wb_info_pool if rdev is the last device flaged with WBCollisionCheck. ++ * Destroy serial_info_pool if rdev is the last device flaged with ++ * CollisionCheck. + */ +-static void mddev_destroy_wb_pool(struct mddev *mddev, struct md_rdev *rdev) ++static void mddev_destroy_serial_pool(struct mddev *mddev, struct md_rdev *rdev) + { +- if (!test_and_clear_bit(WBCollisionCheck, &rdev->flags)) ++ if (!test_and_clear_bit(CollisionCheck, &rdev->flags)) + return; + +- if (mddev->wb_info_pool) { ++ if (mddev->serial_info_pool) { + struct md_rdev *temp; + int num = 0; + + /* +- * Check if other rdevs need wb_info_pool. ++ * Check if other rdevs need serial_info_pool. + */ + rdev_for_each(temp, mddev) + if (temp != rdev && +- test_bit(WBCollisionCheck, &temp->flags)) ++ test_bit(CollisionCheck, &temp->flags)) + num++; + if (!num) { + mddev_suspend(rdev->mddev); +- mempool_destroy(mddev->wb_info_pool); +- mddev->wb_info_pool = NULL; ++ mempool_destroy(mddev->serial_info_pool); ++ mddev->serial_info_pool = NULL; + mddev_resume(rdev->mddev); + } + } +@@ -2337,7 +2339,7 @@ static int bind_rdev_to_array(struct md_rdev *rdev, struct mddev *mddev) + pr_debug("md: bind<%s>\n", b); + + if (mddev->raid_disks) +- mddev_create_wb_pool(mddev, rdev, false); ++ mddev_create_serial_pool(mddev, rdev, false); + + if ((err = kobject_add(&rdev->kobj, &mddev->kobj, "dev-%s", b))) + goto fail; +@@ -2375,7 +2377,7 @@ static void unbind_rdev_from_array(struct md_rdev *rdev) + bd_unlink_disk_holder(rdev->bdev, rdev->mddev->gendisk); + list_del_rcu(&rdev->same_set); + pr_debug("md: unbind<%s>\n", bdevname(rdev->bdev,b)); +- mddev_destroy_wb_pool(rdev->mddev, rdev); ++ mddev_destroy_serial_pool(rdev->mddev, rdev); + rdev->mddev = NULL; + sysfs_remove_link(&rdev->kobj, "block"); + sysfs_put(rdev->sysfs_state); +@@ -2888,10 +2890,10 @@ state_store(struct md_rdev *rdev, const char *buf, size_t len) + } + } else if (cmd_match(buf, "writemostly")) { + set_bit(WriteMostly, &rdev->flags); +- mddev_create_wb_pool(rdev->mddev, rdev, false); ++ mddev_create_serial_pool(rdev->mddev, rdev, false); + err = 0; + } else if (cmd_match(buf, "-writemostly")) { +- mddev_destroy_wb_pool(rdev->mddev, rdev); ++ mddev_destroy_serial_pool(rdev->mddev, rdev); + clear_bit(WriteMostly, &rdev->flags); + err = 0; + } else if (cmd_match(buf, "blocked")) { +@@ -5773,14 +5775,14 @@ int md_run(struct mddev *mddev) + + rdev_for_each(rdev, mddev) { + if (test_bit(WriteMostly, &rdev->flags) && +- rdev_init_wb(rdev)) ++ rdev_init_serial(rdev)) + creat_pool = true; + } +- if (creat_pool && mddev->wb_info_pool == NULL) { +- mddev->wb_info_pool = +- mempool_create_kmalloc_pool(NR_WB_INFOS, +- sizeof(struct wb_info)); +- if (!mddev->wb_info_pool) { ++ if (creat_pool && mddev->serial_info_pool == NULL) { ++ mddev->serial_info_pool = ++ mempool_create_kmalloc_pool(NR_SERIAL_INFOS, ++ sizeof(struct serial_info)); ++ if (!mddev->serial_info_pool) { + err = -ENOMEM; + goto bitmap_abort; + } +@@ -6025,8 +6027,8 @@ static void __md_stop_writes(struct mddev *mddev) + mddev->in_sync = 1; + md_update_sb(mddev, 1); + } +- mempool_destroy(mddev->wb_info_pool); +- mddev->wb_info_pool = NULL; ++ mempool_destroy(mddev->serial_info_pool); ++ mddev->serial_info_pool = NULL; + } + + void md_stop_writes(struct mddev *mddev) +diff --git a/drivers/md/md.h b/drivers/md/md.h +index 5f86f8adb0a4..7b811645cec7 100644 +--- a/drivers/md/md.h ++++ b/drivers/md/md.h +@@ -111,11 +111,11 @@ struct md_rdev { + */ + + /* +- * The members for check collision of write behind IOs. ++ * The members for check collision of write IOs. + */ +- struct list_head wb_list; +- spinlock_t wb_list_lock; +- wait_queue_head_t wb_io_wait; ++ struct list_head serial_list; ++ spinlock_t serial_list_lock; ++ wait_queue_head_t serial_io_wait; + + struct work_struct del_work; /* used for delayed sysfs removal */ + +@@ -201,9 +201,9 @@ enum flag_bits { + * it didn't fail, so don't use FailFast + * any more for metadata + */ +- WBCollisionCheck, /* +- * multiqueue device should check if there +- * is collision between write behind bios. ++ CollisionCheck, /* ++ * check if there is collision between raid1 ++ * serial bios. + */ + }; + +@@ -263,9 +263,9 @@ enum mddev_sb_flags { + MD_SB_NEED_REWRITE, /* metadata write needs to be repeated */ + }; + +-#define NR_WB_INFOS 8 +-/* record current range of write behind IOs */ +-struct wb_info { ++#define NR_SERIAL_INFOS 8 ++/* record current range of serialize IOs */ ++struct serial_info { + sector_t lo; + sector_t hi; + struct list_head list; +@@ -487,7 +487,7 @@ struct mddev { + */ + struct work_struct flush_work; + struct work_struct event_work; /* used by dm to report failure event */ +- mempool_t *wb_info_pool; ++ mempool_t *serial_info_pool; + void (*sync_super)(struct mddev *mddev, struct md_rdev *rdev); + struct md_cluster_info *cluster_info; + unsigned int good_device_nr; /* good device num within cluster raid */ +@@ -737,7 +737,7 @@ extern struct bio *bio_alloc_mddev(gfp_t gfp_mask, int nr_iovecs, + extern void md_reload_sb(struct mddev *mddev, int raid_disk); + extern void md_update_sb(struct mddev *mddev, int force); + extern void md_kick_rdev_from_array(struct md_rdev * rdev); +-extern void mddev_create_wb_pool(struct mddev *mddev, struct md_rdev *rdev, ++extern void mddev_create_serial_pool(struct mddev *mddev, struct md_rdev *rdev, + bool is_suspend); + struct md_rdev *md_find_rdev_nr_rcu(struct mddev *mddev, int nr); + struct md_rdev *md_find_rdev_rcu(struct mddev *mddev, dev_t dev); +diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c +index 201fd8aec59a..0439f674ab14 100644 +--- a/drivers/md/raid1.c ++++ b/drivers/md/raid1.c +@@ -50,17 +50,17 @@ static void lower_barrier(struct r1conf *conf, sector_t sector_nr); + + #include "raid1-10.c" + +-static int check_and_add_wb(struct md_rdev *rdev, sector_t lo, sector_t hi) ++static int check_and_add_serial(struct md_rdev *rdev, sector_t lo, sector_t hi) + { +- struct wb_info *wi, *temp_wi; ++ struct serial_info *wi, *temp_wi; + unsigned long flags; + int ret = 0; + struct mddev *mddev = rdev->mddev; + +- wi = mempool_alloc(mddev->wb_info_pool, GFP_NOIO); ++ wi = mempool_alloc(mddev->serial_info_pool, GFP_NOIO); + +- spin_lock_irqsave(&rdev->wb_list_lock, flags); +- list_for_each_entry(temp_wi, &rdev->wb_list, list) { ++ spin_lock_irqsave(&rdev->serial_list_lock, flags); ++ list_for_each_entry(temp_wi, &rdev->serial_list, list) { + /* collision happened */ + if (hi > temp_wi->lo && lo < temp_wi->hi) { + ret = -EBUSY; +@@ -71,34 +71,34 @@ static int check_and_add_wb(struct md_rdev *rdev, sector_t lo, sector_t hi) + if (!ret) { + wi->lo = lo; + wi->hi = hi; +- list_add(&wi->list, &rdev->wb_list); ++ list_add(&wi->list, &rdev->serial_list); + } else +- mempool_free(wi, mddev->wb_info_pool); +- spin_unlock_irqrestore(&rdev->wb_list_lock, flags); ++ mempool_free(wi, mddev->serial_info_pool); ++ spin_unlock_irqrestore(&rdev->serial_list_lock, flags); + + return ret; + } + +-static void remove_wb(struct md_rdev *rdev, sector_t lo, sector_t hi) ++static void remove_serial(struct md_rdev *rdev, sector_t lo, sector_t hi) + { +- struct wb_info *wi; ++ struct serial_info *wi; + unsigned long flags; + int found = 0; + struct mddev *mddev = rdev->mddev; + +- spin_lock_irqsave(&rdev->wb_list_lock, flags); +- list_for_each_entry(wi, &rdev->wb_list, list) ++ spin_lock_irqsave(&rdev->serial_list_lock, flags); ++ list_for_each_entry(wi, &rdev->serial_list, list) + if (hi == wi->hi && lo == wi->lo) { + list_del(&wi->list); +- mempool_free(wi, mddev->wb_info_pool); ++ mempool_free(wi, mddev->serial_info_pool); + found = 1; + break; + } + + if (!found) +- WARN(1, "The write behind IO is not recorded\n"); +- spin_unlock_irqrestore(&rdev->wb_list_lock, flags); +- wake_up(&rdev->wb_io_wait); ++ WARN(1, "The write IO is not recorded for serialization\n"); ++ spin_unlock_irqrestore(&rdev->serial_list_lock, flags); ++ wake_up(&rdev->serial_io_wait); + } + + /* +@@ -499,11 +499,11 @@ static void raid1_end_write_request(struct bio *bio) + } + + if (behind) { +- if (test_bit(WBCollisionCheck, &rdev->flags)) { ++ if (test_bit(CollisionCheck, &rdev->flags)) { + sector_t lo = r1_bio->sector; + sector_t hi = r1_bio->sector + r1_bio->sectors; + +- remove_wb(rdev, lo, hi); ++ remove_serial(rdev, lo, hi); + } + if (test_bit(WriteMostly, &rdev->flags)) + atomic_dec(&r1_bio->behind_remaining); +@@ -1508,12 +1508,13 @@ static void raid1_write_request(struct mddev *mddev, struct bio *bio, + if (r1_bio->behind_master_bio) { + struct md_rdev *rdev = conf->mirrors[i].rdev; + +- if (test_bit(WBCollisionCheck, &rdev->flags)) { ++ if (test_bit(CollisionCheck, &rdev->flags)) { + sector_t lo = r1_bio->sector; + sector_t hi = r1_bio->sector + r1_bio->sectors; + +- wait_event(rdev->wb_io_wait, +- check_and_add_wb(rdev, lo, hi) == 0); ++ wait_event(rdev->serial_io_wait, ++ check_and_add_serial(rdev, lo, hi) ++ == 0); + } + if (test_bit(WriteMostly, &rdev->flags)) + atomic_inc(&r1_bio->behind_remaining); +-- +2.25.0 + diff --git a/patches.suse/0093-md-fix-a-typo-s-creat-create.patch b/patches.suse/0093-md-fix-a-typo-s-creat-create.patch new file mode 100644 index 0000000..ae8360e --- /dev/null +++ b/patches.suse/0093-md-fix-a-typo-s-creat-create.patch @@ -0,0 +1,44 @@ +From 3e173ab55b990d2b4ceb90bf55a88a96eb88598e Mon Sep 17 00:00:00 2001 +From: Guoqing Jiang +Date: Mon, 23 Dec 2019 10:48:54 +0100 +Subject: [PATCH] md: fix a typo s/creat/create +Git-commit: 3e173ab55b990d2b4ceb90bf55a88a96eb88598e +Patch-mainline: v5.6-rc1 +References: bsc#1166003 + +It actually means create here, so fix the typo. + +Reported-by: Song Liu +Signed-off-by: Guoqing Jiang +Signed-off-by: Song Liu +Signed-off-by: Coly Li + +--- + drivers/md/md.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/drivers/md/md.c b/drivers/md/md.c +index ea37bfacb6fb..8f5def0cb60a 100644 +--- a/drivers/md/md.c ++++ b/drivers/md/md.c +@@ -5771,14 +5771,14 @@ int md_run(struct mddev *mddev) + goto bitmap_abort; + + if (mddev->bitmap_info.max_write_behind > 0) { +- bool creat_pool = false; ++ bool create_pool = false; + + rdev_for_each(rdev, mddev) { + if (test_bit(WriteMostly, &rdev->flags) && + rdev_init_serial(rdev)) +- creat_pool = true; ++ create_pool = true; + } +- if (creat_pool && mddev->serial_info_pool == NULL) { ++ if (create_pool && mddev->serial_info_pool == NULL) { + mddev->serial_info_pool = + mempool_create_kmalloc_pool(NR_SERIAL_INFOS, + sizeof(struct serial_info)); +-- +2.25.0 + diff --git a/patches.suse/0098-md-r5cache-remove-redundant-pointer-bio.patch b/patches.suse/0098-md-r5cache-remove-redundant-pointer-bio.patch deleted file mode 100644 index 59380f5..0000000 --- a/patches.suse/0098-md-r5cache-remove-redundant-pointer-bio.patch +++ /dev/null @@ -1,45 +0,0 @@ -From ebc7709f65001911f275e13dd5f29b02803c0688 Mon Sep 17 00:00:00 2001 -From: Colin Ian King -Date: Tue, 3 Jul 2018 07:51:09 +0100 -Subject: [PATCH] md/r5cache: remove redundant pointer bio -Git-commit: ebc7709f65001911f275e13dd5f29b02803c0688 -References: bsc#1111974 -Patch-mainline: v4.19-rc1 - -Pointer bio is being assigned but is never used hence it is redundant -and can be removed. - -Cleans up clang warning: -Warning: variable 'bio' set but not used [-Wunused-but-set-variable] - -Signed-off-by: Colin Ian King -Signed-off-by: Shaohua Li -Signed-off-by: Coly Li - ---- - drivers/md/raid5-cache.c | 2 -- - 1 file changed, 2 deletions(-) - -diff --git a/drivers/md/raid5-cache.c b/drivers/md/raid5-cache.c -index 2b775abf377b..7416db70c6cc 100644 ---- a/drivers/md/raid5-cache.c -+++ b/drivers/md/raid5-cache.c -@@ -717,7 +717,6 @@ static void r5c_disable_writeback_async(struct work_struct *work) - static void r5l_submit_current_io(struct r5l_log *log) - { - struct r5l_io_unit *io = log->current_io; -- struct bio *bio; - struct r5l_meta_block *block; - unsigned long flags; - u32 crc; -@@ -730,7 +729,6 @@ static void r5l_submit_current_io(struct r5l_log *log) - block->meta_size = cpu_to_le32(io->meta_offset); - crc = crc32c_le(log->uuid_checksum, block, PAGE_SIZE); - block->checksum = cpu_to_le32(crc); -- bio = io->current_bio; - - log->current_io = NULL; - spin_lock_irqsave(&log->io_list_lock, flags); --- -2.19.0 - diff --git a/patches.suse/0099-drivers-md-raid5-Use-irqsave-variant-of-atomic_dec_a.patch b/patches.suse/0099-drivers-md-raid5-Use-irqsave-variant-of-atomic_dec_a.patch deleted file mode 100644 index 512b995..0000000 --- a/patches.suse/0099-drivers-md-raid5-Use-irqsave-variant-of-atomic_dec_a.patch +++ /dev/null @@ -1,51 +0,0 @@ -From 685dbcaa25becfba864b72ec3f03470833b7f692 Mon Sep 17 00:00:00 2001 -From: Anna-Maria Gleixner -Date: Tue, 3 Jul 2018 22:01:36 +0200 -Subject: [PATCH] drivers/md/raid5: Use irqsave variant of - atomic_dec_and_lock() -Git-commit: 685dbcaa25becfba864b72ec3f03470833b7f692 -References: bsc#1111974 -Patch-mainline: v4.19-rc1 - -The irqsave variant of atomic_dec_and_lock handles irqsave/restore when -taking/releasing the spin lock. With this variant the call of -local_irq_save is no longer required. - -Cc: Shaohua Li -Cc: linux-raid@vger.kernel.org -Acked-by: Peter Zijlstra (Intel) -Signed-off-by: Anna-Maria Gleixner -Signed-off-by: Sebastian Andrzej Siewior -Signed-off-by: Shaohua Li -Signed-off-by: Coly Li - ---- - drivers/md/raid5.c | 5 ++--- - 1 file changed, 2 insertions(+), 3 deletions(-) - -diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c -index 2031506a0ecd..e933bff9459e 100644 ---- a/drivers/md/raid5.c -+++ b/drivers/md/raid5.c -@@ -409,16 +409,15 @@ void raid5_release_stripe(struct stripe_head *sh) - md_wakeup_thread(conf->mddev->thread); - return; - slow_path: -- local_irq_save(flags); - /* we are ok here if STRIPE_ON_RELEASE_LIST is set or not */ -- if (atomic_dec_and_lock(&sh->count, &conf->device_lock)) { -+ if (atomic_dec_and_lock_irqsave(&sh->count, &conf->device_lock, flags)) { - INIT_LIST_HEAD(&list); - hash = sh->hash_lock_index; - do_release_stripe(conf, sh, &list); - spin_unlock(&conf->device_lock); - release_inactive_stripe_list(conf, &list, hash); -+ local_irq_restore(flags); - } -- local_irq_restore(flags); - } - - static inline void remove_hash(struct stripe_head *sh) --- -2.19.0 - diff --git a/patches.suse/0100-drivers-md-raid5-Do-not-disable-irq-on-release_inact.patch b/patches.suse/0100-drivers-md-raid5-Do-not-disable-irq-on-release_inact.patch deleted file mode 100644 index 5d44598..0000000 --- a/patches.suse/0100-drivers-md-raid5-Do-not-disable-irq-on-release_inact.patch +++ /dev/null @@ -1,45 +0,0 @@ -From 08edaaa6d6fa5f6ac9be2adcc71f80b4083b6494 Mon Sep 17 00:00:00 2001 -From: Anna-Maria Gleixner -Date: Tue, 3 Jul 2018 22:01:37 +0200 -Subject: [PATCH] drivers/md/raid5: Do not disable irq on - release_inactive_stripe_list() call -Git-commit: 08edaaa6d6fa5f6ac9be2adcc71f80b4083b6494 -References: bsc#1111974 -Patch-mainline: v4.19-rc1 - -There is no need to invoke release_inactive_stripe_list() with interrupts -disabled. All call sites, except raid5_release_stripe(), unlock -->device_lock and enable interrupts before invoking the function. - -Make it consistent. - -Cc: Shaohua Li -Cc: linux-raid@vger.kernel.org -Acked-by: Peter Zijlstra (Intel) -Signed-off-by: Anna-Maria Gleixner -Signed-off-by: Sebastian Andrzej Siewior -Signed-off-by: Shaohua Li -Signed-off-by: Coly Li - ---- - drivers/md/raid5.c | 3 +-- - 1 file changed, 1 insertion(+), 2 deletions(-) - -diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c -index e933bff9459e..ca1dd0cb04c5 100644 ---- a/drivers/md/raid5.c -+++ b/drivers/md/raid5.c -@@ -414,9 +414,8 @@ void raid5_release_stripe(struct stripe_head *sh) - INIT_LIST_HEAD(&list); - hash = sh->hash_lock_index; - do_release_stripe(conf, sh, &list); -- spin_unlock(&conf->device_lock); -+ spin_unlock_irqrestore(&conf->device_lock, flags); - release_inactive_stripe_list(conf, &list, hash); -- local_irq_restore(flags); - } - } - --- -2.19.0 - diff --git a/patches.suse/0166-md-remove-redundant-code-that-is-no-longer-reachable.patch b/patches.suse/0166-md-remove-redundant-code-that-is-no-longer-reachable.patch deleted file mode 100644 index 74990be..0000000 --- a/patches.suse/0166-md-remove-redundant-code-that-is-no-longer-reachable.patch +++ /dev/null @@ -1,32 +0,0 @@ -From 116d99adf59314924adae0cb691e4d289b5f2407 Mon Sep 17 00:00:00 2001 -From: Colin Ian King -Date: Mon, 8 Oct 2018 22:16:09 +0100 -Subject: [PATCH] md: remove redundant code that is no longer reachable -Git-commit: 116d99adf59314924adae0cb691e4d289b5f2407 -Patch-mainline: v4.20-rc1 -References: bsc#1111974 - -And earlier commit removed the error label to two statements that -are now never reachable. Since this code is now dead code, remove it. - -Detected by CoverityScan, CID#1462409 ("Structurally dead code") - -Fixes: d5d885fd514f ("md: introduce new personality funciton start()") -Signed-off-by: Colin Ian King -Signed-off-by: Shaohua Li -Signed-off-by: Coly Li ---- - drivers/md/raid5-cache.c | 2 -- - 1 file changed, 2 deletions(-) - ---- a/drivers/md/raid5-cache.c -+++ b/drivers/md/raid5-cache.c -@@ -3150,8 +3150,6 @@ int r5l_init_log(struct r5conf *conf, st - set_bit(MD_HAS_JOURNAL, &conf->mddev->flags); - return 0; - -- rcu_assign_pointer(conf->log, NULL); -- md_unregister_thread(&log->reclaim_thread); - reclaim_thread: - mempool_destroy(log->meta_pool); - out_mempool: diff --git a/patches.suse/0167-md-fix-memleak-for-mempool.patch b/patches.suse/0167-md-fix-memleak-for-mempool.patch deleted file mode 100644 index ab3fe59..0000000 --- a/patches.suse/0167-md-fix-memleak-for-mempool.patch +++ /dev/null @@ -1,67 +0,0 @@ -From 6aaa58c994277647f8b05ffef3b9b225a2d08f36 Mon Sep 17 00:00:00 2001 -From: Jack Wang -Date: Fri, 19 Oct 2018 16:21:31 +0200 -Subject: [PATCH] md: fix memleak for mempool -Git-commit: 6aaa58c994277647f8b05ffef3b9b225a2d08f36 -Patch-mainline: v4.20-rc1 -References: bsc#1111974 - -I noticed kmemleak report memory leak when run create/stop -md in a loop, backtrace: -[<000000001ca975e7>] mempool_create_node+0x86/0xd0 -[<0000000095576bcd>] md_run+0x1057/0x1410 [md_mod] -[<000000007b45c5fc>] do_md_run+0x15/0x130 [md_mod] -[<000000001ede9ec0>] md_ioctl+0x1f49/0x25d0 [md_mod] -[<000000004142cacf>] blkdev_ioctl+0x680/0xd00 - -The root cause is we alloc mddev->flush_pool and -mddev->flush_bio_pool in md_run, but from do_md_stop -will not call into md_stop but __md_stop, move the -mempool_destroy to __md_stop fixes the problem for me. - -The bug was introduced in 5a409b4f56d5, the fixes should go to -4.18+ - -(Coly Li: rebase for SLE15-SP1 kernel) - -Fixes: 5a409b4f56d5 ("MD: fix lock contention for flush bios") -Signed-off-by: Jack Wang -Reviewed-by: Xiao Ni -Signed-off-by: Shaohua Li -Signed-off-by: Coly Li ---- - drivers/md/md.c | 16 ++++++++-------- - 1 file changed, 8 insertions(+), 8 deletions(-) - ---- a/drivers/md/md.c -+++ b/drivers/md/md.c -@@ -5922,14 +5922,6 @@ static void __md_stop(struct mddev *mdde - mddev->to_remove = &md_redundancy_group; - module_put(pers->owner); - clear_bit(MD_RECOVERY_FROZEN, &mddev->recovery); --} -- --void md_stop(struct mddev *mddev) --{ -- /* stop the array and free an attached data structures. -- * This is called from dm-raid -- */ -- __md_stop(mddev); - if (mddev->flush_bio_pool) { - mempool_destroy(mddev->flush_bio_pool); - mddev->flush_bio_pool = NULL; -@@ -5938,6 +5930,14 @@ void md_stop(struct mddev *mddev) - mempool_destroy(mddev->flush_pool); - mddev->flush_pool = NULL; - } -+} -+ -+void md_stop(struct mddev *mddev) -+{ -+ /* stop the array and free an attached data structures. -+ * This is called from dm-raid -+ */ -+ __md_stop(mddev); - if (mddev->bio_set) { - bioset_free(mddev->bio_set); - mddev->bio_set = NULL; diff --git a/patches.suse/0168-MD-Memory-leak-when-flush-bio-size-is-zero.patch b/patches.suse/0168-MD-Memory-leak-when-flush-bio-size-is-zero.patch deleted file mode 100644 index ef982d8..0000000 --- a/patches.suse/0168-MD-Memory-leak-when-flush-bio-size-is-zero.patch +++ /dev/null @@ -1,54 +0,0 @@ -From af9b926de9c5986ab009e64917de87c9758bab10 Mon Sep 17 00:00:00 2001 -From: Xiao Ni -Date: Sat, 20 Oct 2018 08:09:25 +0800 -Subject: [PATCH] MD: Memory leak when flush bio size is zero -Git-commit: af9b926de9c5986ab009e64917de87c9758bab10 -Patch-mainline: v4.20-rc1 -References: bsc#1111974 - -flush_pool is leaked when flush bio size is zero - -Fixes: 5a409b4f56d5 ("MD: fix lock contention for flush bios") -Signed-off-by: David Jeffery -Signed-off-by: Xiao Ni -Signed-off-by: Shaohua Li -Signed-off-by: Coly Li ---- - drivers/md/md.c | 10 ++++++---- - 1 file changed, 6 insertions(+), 4 deletions(-) - -diff --git a/drivers/md/md.c b/drivers/md/md.c -index 1fa7f1b1d98a..fc488cb30a94 100644 ---- a/drivers/md/md.c -+++ b/drivers/md/md.c -@@ -452,10 +452,11 @@ static void md_end_flush(struct bio *fbio) - rdev_dec_pending(rdev, mddev); - - if (atomic_dec_and_test(&fi->flush_pending)) { -- if (bio->bi_iter.bi_size == 0) -+ if (bio->bi_iter.bi_size == 0) { - /* an empty barrier - all done */ - bio_endio(bio); -- else { -+ mempool_free(fi, mddev->flush_pool); -+ } else { - INIT_WORK(&fi->flush_work, submit_flushes); - queue_work(md_wq, &fi->flush_work); - } -@@ -509,10 +510,11 @@ void md_flush_request(struct mddev *mddev, struct bio *bio) - rcu_read_unlock(); - - if (atomic_dec_and_test(&fi->flush_pending)) { -- if (bio->bi_iter.bi_size == 0) -+ if (bio->bi_iter.bi_size == 0) { - /* an empty barrier - all done */ - bio_endio(bio); -- else { -+ mempool_free(fi, mddev->flush_pool); -+ } else { - INIT_WORK(&fi->flush_work, submit_flushes); - queue_work(md_wq, &fi->flush_work); - } --- -2.16.3 - diff --git a/patches.suse/0200-raid-remove-tile-specific-raid6-implementation.patch b/patches.suse/0200-raid-remove-tile-specific-raid6-implementation.patch index 201d876..8a795af 100644 --- a/patches.suse/0200-raid-remove-tile-specific-raid6-implementation.patch +++ b/patches.suse/0200-raid-remove-tile-specific-raid6-implementation.patch @@ -10,20 +10,21 @@ The Tile architecture is getting removed, so we no longer need this either. Acked-by: Ard Biesheuvel Signed-off-by: Arnd Bergmann -Signed-off-by: Coly Li - +Acked-by: Coly Li --- - include/linux/raid/pq.h | 1 - lib/raid6/Makefile | 6 --- - lib/raid6/algos.c | 3 - - lib/raid6/test/Makefile | 7 --- - lib/raid6/tilegx.uc | 87 ------------------------------------------------ + include/linux/raid/pq.h | 1 - + lib/raid6/Makefile | 6 --- + lib/raid6/algos.c | 3 -- + lib/raid6/test/Makefile | 7 ---- + lib/raid6/tilegx.uc | 87 ----------------------------------------- 5 files changed, 104 deletions(-) delete mode 100644 lib/raid6/tilegx.uc +diff --git a/include/linux/raid/pq.h b/include/linux/raid/pq.h +index 583cdd3d49ca..a366cc314479 100644 --- a/include/linux/raid/pq.h +++ b/include/linux/raid/pq.h -@@ -105,7 +105,6 @@ extern const struct raid6_calls raid6_av +@@ -105,7 +105,6 @@ extern const struct raid6_calls raid6_avx2x4; extern const struct raid6_calls raid6_avx512x1; extern const struct raid6_calls raid6_avx512x2; extern const struct raid6_calls raid6_avx512x4; @@ -31,9 +32,11 @@ Signed-off-by: Coly Li extern const struct raid6_calls raid6_s390vx8; struct raid6_recov_calls { +diff --git a/lib/raid6/Makefile b/lib/raid6/Makefile +index 4add700ddfe3..44d6b46df051 100644 --- a/lib/raid6/Makefile +++ b/lib/raid6/Makefile -@@ -6,7 +6,6 @@ raid6_pq-y += algos.o recov.o tables.o i +@@ -7,7 +7,6 @@ raid6_pq-y += algos.o recov.o tables.o int1.o int2.o int4.o \ raid6_pq-$(CONFIG_X86) += recov_ssse3.o recov_avx2.o mmx.o sse1.o sse2.o avx2.o avx512.o recov_avx512.o raid6_pq-$(CONFIG_ALTIVEC) += altivec1.o altivec2.o altivec4.o altivec8.o raid6_pq-$(CONFIG_KERNEL_MODE_NEON) += neon.o neon1.o neon2.o neon4.o neon8.o recov_neon.o recov_neon_inner.o @@ -53,9 +56,11 @@ Signed-off-by: Coly Li targets += s390vx8.c $(obj)/s390vx8.c: UNROLL := 8 $(obj)/s390vx8.c: $(src)/s390vx.uc $(src)/unroll.awk FORCE +diff --git a/lib/raid6/algos.c b/lib/raid6/algos.c +index 476994723258..c65aa80d67ed 100644 --- a/lib/raid6/algos.c +++ b/lib/raid6/algos.c -@@ -75,9 +75,6 @@ const struct raid6_calls * const raid6_a +@@ -75,9 +75,6 @@ const struct raid6_calls * const raid6_algos[] = { &raid6_altivec4, &raid6_altivec8, #endif @@ -65,9 +70,11 @@ Signed-off-by: Coly Li #if defined(CONFIG_S390) &raid6_s390vx8, #endif +diff --git a/lib/raid6/test/Makefile b/lib/raid6/test/Makefile +index be1010bdc435..fabc477b1417 100644 --- a/lib/raid6/test/Makefile +++ b/lib/raid6/test/Makefile -@@ -50,9 +50,6 @@ else +@@ -51,9 +51,6 @@ else OBJS += altivec1.o altivec2.o altivec4.o altivec8.o endif endif @@ -77,7 +84,7 @@ Signed-off-by: Coly Li .c.o: $(CC) $(CFLAGS) -c -o $@ $< -@@ -115,15 +112,11 @@ int16.c: int.uc ../unroll.awk +@@ -116,15 +113,11 @@ int16.c: int.uc ../unroll.awk int32.c: int.uc ../unroll.awk $(AWK) ../unroll.awk -vN=32 < int.uc > $@ @@ -93,6 +100,9 @@ Signed-off-by: Coly Li spotless: clean rm -f *~ +diff --git a/lib/raid6/tilegx.uc b/lib/raid6/tilegx.uc +deleted file mode 100644 +index 2dd291a11264..000000000000 --- a/lib/raid6/tilegx.uc +++ /dev/null @@ -1,87 +0,0 @@ @@ -183,3 +193,6 @@ Signed-off-by: Coly Li - "tilegx$#", - 0 -}; +-- +2.25.0 + diff --git a/patches.suse/ACPI-watchdog-Fix-gas-access_width-usage.patch b/patches.suse/ACPI-watchdog-Fix-gas-access_width-usage.patch new file mode 100644 index 0000000..b8a4532 --- /dev/null +++ b/patches.suse/ACPI-watchdog-Fix-gas-access_width-usage.patch @@ -0,0 +1,60 @@ +From 2ba33a4e9e22ac4dda928d3e9b5978a3a2ded4e0 Mon Sep 17 00:00:00 2001 +From: Mika Westerberg +Date: Wed, 12 Feb 2020 17:59:40 +0300 +Subject: [PATCH] ACPI: watchdog: Fix gas->access_width usage +Git-commit: 2ba33a4e9e22ac4dda928d3e9b5978a3a2ded4e0 +Patch-mainline: v5.6-rc4 +References: bsc#1051510 + +ACPI Generic Address Structure (GAS) access_width field is not in bytes +as the driver seems to expect in few places so fix this by using the +newly introduced macro ACPI_ACCESS_BYTE_WIDTH(). + +Fixes: b1abf6fc4982 ("ACPI / watchdog: Fix off-by-one error at resource assignment") +Fixes: 058dfc767008 ("ACPI / watchdog: Add support for WDAT hardware watchdog") +Reported-by: Jean Delvare +Signed-off-by: Mika Westerberg +Reviewed-by: Jean Delvare +Cc: 4.16+ # 4.16+ +Signed-off-by: Rafael J. Wysocki +Acked-by: Takashi Iwai + +--- + drivers/acpi/acpi_watchdog.c | 3 +-- + drivers/watchdog/wdat_wdt.c | 2 +- + 2 files changed, 2 insertions(+), 3 deletions(-) + +diff --git a/drivers/acpi/acpi_watchdog.c b/drivers/acpi/acpi_watchdog.c +index ab6e434b4cee..6e9ec6e3fe47 100644 +--- a/drivers/acpi/acpi_watchdog.c ++++ b/drivers/acpi/acpi_watchdog.c +@@ -136,12 +136,11 @@ void __init acpi_watchdog_init(void) + gas = &entries[i].register_region; + + res.start = gas->address; ++ res.end = res.start + ACPI_ACCESS_BYTE_WIDTH(gas->access_width) - 1; + if (gas->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) { + res.flags = IORESOURCE_MEM; +- res.end = res.start + ALIGN(gas->access_width, 4) - 1; + } else if (gas->space_id == ACPI_ADR_SPACE_SYSTEM_IO) { + res.flags = IORESOURCE_IO; +- res.end = res.start + gas->access_width - 1; + } else { + pr_warn("Unsupported address space: %u\n", + gas->space_id); +diff --git a/drivers/watchdog/wdat_wdt.c b/drivers/watchdog/wdat_wdt.c +index b069349b52f5..e1b1fcfc02af 100644 +--- a/drivers/watchdog/wdat_wdt.c ++++ b/drivers/watchdog/wdat_wdt.c +@@ -389,7 +389,7 @@ static int wdat_wdt_probe(struct platform_device *pdev) + + memset(&r, 0, sizeof(r)); + r.start = gas->address; +- r.end = r.start + gas->access_width - 1; ++ r.end = r.start + ACPI_ACCESS_BYTE_WIDTH(gas->access_width) - 1; + if (gas->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) { + r.flags = IORESOURCE_MEM; + } else if (gas->space_id == ACPI_ADR_SPACE_SYSTEM_IO) { +-- +2.16.4 + diff --git a/patches.suse/ACPICA-Introduce-ACPI_ACCESS_BYTE_WIDTH-macro.patch b/patches.suse/ACPICA-Introduce-ACPI_ACCESS_BYTE_WIDTH-macro.patch new file mode 100644 index 0000000..293b801 --- /dev/null +++ b/patches.suse/ACPICA-Introduce-ACPI_ACCESS_BYTE_WIDTH-macro.patch @@ -0,0 +1,38 @@ +From 1dade3a7048ccfc675650cd2cf13d578b095e5fb Mon Sep 17 00:00:00 2001 +From: Mika Westerberg +Date: Wed, 12 Feb 2020 17:59:39 +0300 +Subject: [PATCH] ACPICA: Introduce ACPI_ACCESS_BYTE_WIDTH() macro +Git-commit: 1dade3a7048ccfc675650cd2cf13d578b095e5fb +Patch-mainline: v5.6-rc4 +References: bsc#1051510 + +Sometimes it is useful to find the access_width field value in bytes and +not in bits so add a helper that can be used for this purpose. + +Suggested-by: Jean Delvare +Signed-off-by: Mika Westerberg +Reviewed-by: Jean Delvare +Cc: 4.16+ # 4.16+ +Signed-off-by: Rafael J. Wysocki +Acked-by: Takashi Iwai + +--- + include/acpi/actypes.h | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/include/acpi/actypes.h ++++ b/include/acpi/actypes.h +@@ -551,11 +551,12 @@ typedef u64 acpi_integer; + #define ACPI_MAKE_RSDP_SIG(dest) (memcpy (ACPI_CAST_PTR (char, (dest)), ACPI_SIG_RSDP, 8)) + + /* +- * Algorithm to obtain access bit width. ++ * Algorithm to obtain access bit or byte width. + * Can be used with access_width of struct acpi_generic_address and access_size of + * struct acpi_resource_generic_register. + */ + #define ACPI_ACCESS_BIT_WIDTH(size) (1 << ((size) + 2)) ++#define ACPI_ACCESS_BYTE_WIDTH(size) (1 << ((size) - 1)) + + /******************************************************************************* + * diff --git a/patches.suse/ALSA-ali5451-remove-redundant-variable-capture_flag.patch b/patches.suse/ALSA-ali5451-remove-redundant-variable-capture_flag.patch new file mode 100644 index 0000000..2399af9 --- /dev/null +++ b/patches.suse/ALSA-ali5451-remove-redundant-variable-capture_flag.patch @@ -0,0 +1,55 @@ +From f18b529a662c18a060e29404d64188398bbf35e4 Mon Sep 17 00:00:00 2001 +From: Colin Ian King +Date: Sat, 8 Feb 2020 22:34:43 +0000 +Subject: [PATCH] ALSA: ali5451: remove redundant variable capture_flag +Git-commit: f18b529a662c18a060e29404d64188398bbf35e4 +Patch-mainline: v5.7-rc1 +References: bsc#1051510 + +Variable capture_flag is only ever assigned values, it is never read +and hence it is redundant. Remove it. + +Addresses-Coverity ("Unused value") + +Signed-off-by: Colin Ian King +Link: https://lore.kernel.org/r/20200208223443.38047-1-colin.king@canonical.com +Signed-off-by: Takashi Iwai + +--- + sound/pci/ali5451/ali5451.c | 6 ++---- + 1 file changed, 2 insertions(+), 4 deletions(-) + +diff --git a/sound/pci/ali5451/ali5451.c b/sound/pci/ali5451/ali5451.c +index 4f524a9dbbca..4462375d2d82 100644 +--- a/sound/pci/ali5451/ali5451.c ++++ b/sound/pci/ali5451/ali5451.c +@@ -1070,7 +1070,7 @@ static int snd_ali_trigger(struct snd_pcm_substream *substream, + { + struct snd_ali *codec = snd_pcm_substream_chip(substream); + struct snd_pcm_substream *s; +- unsigned int what, whati, capture_flag; ++ unsigned int what, whati; + struct snd_ali_voice *pvoice, *evoice; + unsigned int val; + int do_start; +@@ -1088,7 +1088,7 @@ static int snd_ali_trigger(struct snd_pcm_substream *substream, + return -EINVAL; + } + +- what = whati = capture_flag = 0; ++ what = whati = 0; + snd_pcm_group_for_each_entry(s, substream) { + if ((struct snd_ali *) snd_pcm_substream_chip(s) == codec) { + pvoice = s->runtime->private_data; +@@ -1110,8 +1110,6 @@ static int snd_ali_trigger(struct snd_pcm_substream *substream, + evoice->running = 0; + } + snd_pcm_trigger_done(s, substream); +- if (pvoice->mode) +- capture_flag = 1; + } + } + spin_lock(&codec->reg_lock); +-- +2.16.4 + diff --git a/patches.suse/ALSA-core-Add-snd_device_get_state-helper.patch b/patches.suse/ALSA-core-Add-snd_device_get_state-helper.patch new file mode 100644 index 0000000..75fc5b5 --- /dev/null +++ b/patches.suse/ALSA-core-Add-snd_device_get_state-helper.patch @@ -0,0 +1,64 @@ +From c208a5335036a332c0248b0e16fca57332b3f1d1 Mon Sep 17 00:00:00 2001 +From: Takashi Iwai +Date: Mon, 23 Mar 2020 18:06:42 +0100 +Subject: [PATCH] ALSA: core: Add snd_device_get_state() helper +Git-commit: c208a5335036a332c0248b0e16fca57332b3f1d1 +Patch-mainline: v5.7-rc1 +References: bsc#1051510 + +A new small helper to get the current state of the device registration +for the given object. It'll be used for USB-audio driver to check the +delayed device registrations. + +Link: https://lore.kernel.org/r/20200323170643.19181-1-tiwai@suse.de +Signed-off-by: Takashi Iwai + +--- + include/sound/core.h | 1 + + sound/core/device.c | 21 +++++++++++++++++++++ + 2 files changed, 22 insertions(+) + +diff --git a/include/sound/core.h b/include/sound/core.h +index ac8b692b69b4..381a010a1bd4 100644 +--- a/include/sound/core.h ++++ b/include/sound/core.h +@@ -266,6 +266,7 @@ void snd_device_disconnect(struct snd_card *card, void *device_data); + void snd_device_disconnect_all(struct snd_card *card); + void snd_device_free(struct snd_card *card, void *device_data); + void snd_device_free_all(struct snd_card *card); ++int snd_device_get_state(struct snd_card *card, void *device_data); + + /* isadma.c */ + +diff --git a/sound/core/device.c b/sound/core/device.c +index cdc5af526739..bf0b04a7ee79 100644 +--- a/sound/core/device.c ++++ b/sound/core/device.c +@@ -237,3 +237,24 @@ void snd_device_free_all(struct snd_card *card) + list_for_each_entry_safe_reverse(dev, next, &card->devices, list) + __snd_device_free(dev); + } ++ ++/** ++ * snd_device_get_state - Get the current state of the given device ++ * @card: the card instance ++ * @device_data: the data pointer to release ++ * ++ * Returns the current state of the given device object. For the valid ++ * device, either @SNDRV_DEV_BUILD, @SNDRV_DEV_REGISTERED or ++ * @SNDRV_DEV_DISCONNECTED is returned. ++ * Or for a non-existing device, -1 is returned as an error. ++ */ ++int snd_device_get_state(struct snd_card *card, void *device_data) ++{ ++ struct snd_device *dev; ++ ++ dev = look_for_dev(card, device_data); ++ if (dev) ++ return dev->state; ++ return -1; ++} ++EXPORT_SYMBOL_GPL(snd_device_get_state); +-- +2.16.4 + diff --git a/patches.suse/ALSA-core-Replace-zero-length-array-with-flexible-ar.patch b/patches.suse/ALSA-core-Replace-zero-length-array-with-flexible-ar.patch new file mode 100644 index 0000000..679322a --- /dev/null +++ b/patches.suse/ALSA-core-Replace-zero-length-array-with-flexible-ar.patch @@ -0,0 +1,53 @@ +From 9478bd43a2eb5c72b599368513d10880b296d65f Mon Sep 17 00:00:00 2001 +From: "Gustavo A. R. Silva" +Date: Tue, 11 Feb 2020 13:39:10 -0600 +Subject: [PATCH] ALSA: core: Replace zero-length array with flexible-array member +Git-commit: 9478bd43a2eb5c72b599368513d10880b296d65f +Patch-mainline: v5.7-rc1 +References: bsc#1051510 + +The current codebase makes use of the zero-length array language +extension to the C90 standard, but the preferred mechanism to declare +variable-length types such as these ones is a flexible array member[1][2], +introduced in C99: + +struct foo { + int stuff; + struct boo array[]; +}; + +By making use of the mechanism above, we will get a compiler warning +in case the flexible array does not occur last in the structure, which +will help us prevent some kind of undefined behavior bugs from being +inadvertenly introduced[3] to the codebase from now on. + +This issue was found with the help of Coccinelle. + +[1] https://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html +[2] https://github.com/KSPP/linux/issues/21 +[3] commit 76497732932f ("cxgb3/l2t: Fix undefined behaviour") + +Signed-off-by: Gustavo A. R. Silva +Link: https://lore.kernel.org/r/20200211193910.GA4596@embeddedor +Signed-off-by: Takashi Iwai + +--- + sound/core/oss/rate.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/sound/core/oss/rate.c b/sound/core/oss/rate.c +index 7cd09cef6961..d381f4c967c9 100644 +--- a/sound/core/oss/rate.c ++++ b/sound/core/oss/rate.c +@@ -47,7 +47,7 @@ struct rate_priv { + unsigned int pos; + rate_f func; + snd_pcm_sframes_t old_src_frames, old_dst_frames; +- struct rate_channel channels[0]; ++ struct rate_channel channels[]; + }; + + static void rate_init(struct snd_pcm_plugin *plugin) +-- +2.16.4 + diff --git a/patches.suse/ALSA-emu10k1-Fix-endianness-annotations.patch b/patches.suse/ALSA-emu10k1-Fix-endianness-annotations.patch new file mode 100644 index 0000000..3b89ed7 --- /dev/null +++ b/patches.suse/ALSA-emu10k1-Fix-endianness-annotations.patch @@ -0,0 +1,44 @@ +From 6a7322df2c2825bb2f45d247432a3b7d3f3ed233 Mon Sep 17 00:00:00 2001 +From: Takashi Iwai +Date: Thu, 6 Feb 2020 17:31:51 +0100 +Subject: [PATCH] ALSA: emu10k1: Fix endianness annotations +Git-commit: 6a7322df2c2825bb2f45d247432a3b7d3f3ed233 +Patch-mainline: v5.7-rc1 +References: bsc#1051510 + +The internal page tables are little endian, hence they should be +__le32 type. This fixes the relevant sparse warning: + sound/pci/emu10k1/emu10k1_main.c:2013:51: warning: incorrect type in assignment (different base types) + sound/pci/emu10k1/emu10k1_main.c:2013:51: expected unsigned int [usertype] + sound/pci/emu10k1/emu10k1_main.c:2013:51: got restricted __le32 [usertype] + +No functional changes, just sparse warning fixes. + +Link: https://lore.kernel.org/r/20200206163152.6073-3-tiwai@suse.de +Signed-off-by: Takashi Iwai + +--- + sound/pci/emu10k1/emu10k1_main.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +--- a/sound/pci/emu10k1/emu10k1_main.c ++++ b/sound/pci/emu10k1/emu10k1_main.c +@@ -1804,6 +1804,7 @@ int snd_emu10k1_create(struct snd_card * + int idx, err; + int is_audigy; + size_t page_table_size; ++ __le32 *pgtbl; + unsigned int silent_page; + const struct snd_emu_chip_details *c; + static struct snd_device_ops ops = { +@@ -2022,8 +2023,9 @@ int snd_emu10k1_create(struct snd_card * + /* Clear silent pages and set up pointers */ + memset(emu->silent_page.area, 0, emu->silent_page.bytes); + silent_page = emu->silent_page.addr << emu->address_mode; ++ pgtbl = (__le32 *)emu->ptb_pages.area; + for (idx = 0; idx < (emu->address_mode ? MAXPAGES1 : MAXPAGES0); idx++) +- ((u32 *)emu->ptb_pages.area)[idx] = cpu_to_le32(silent_page | idx); ++ pgtbl[idx] = cpu_to_le32(silent_page | idx); + + /* set up voice indices */ + for (idx = 0; idx < NUM_G; idx++) { diff --git a/patches.suse/ALSA-hda-Use-scnprintf-for-string-truncation.patch b/patches.suse/ALSA-hda-Use-scnprintf-for-string-truncation.patch new file mode 100644 index 0000000..a4dbeb8 --- /dev/null +++ b/patches.suse/ALSA-hda-Use-scnprintf-for-string-truncation.patch @@ -0,0 +1,36 @@ +From 0a7efa14e61ae2132fd718887deb28479b33386b Mon Sep 17 00:00:00 2001 +From: Takashi Iwai +Date: Fri, 13 Mar 2020 14:02:41 +0100 +Subject: [PATCH] ALSA: hda: Use scnprintf() for string truncation +Git-commit: 0a7efa14e61ae2132fd718887deb28479b33386b +Patch-mainline: v5.7-rc1 +References: bsc#1051510 + +snd_hdac_codec_modalias() truncates the string to the given size and +returns its size, but it returned a wrong size from snprintf(). +snprintf() returns the would-be-output size, not the actual size. +Use scnprintf() instead to return the correct size. + +Link: https://lore.kernel.org/r/20200313130241.8970-1-tiwai@suse.de +Signed-off-by: Takashi Iwai + +--- + sound/hda/hdac_device.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/sound/hda/hdac_device.c b/sound/hda/hdac_device.c +index 9a526aeef8da..e3119f5cb0d5 100644 +--- a/sound/hda/hdac_device.c ++++ b/sound/hda/hdac_device.c +@@ -204,7 +204,7 @@ EXPORT_SYMBOL_GPL(snd_hdac_device_set_chip_name); + */ + int snd_hdac_codec_modalias(struct hdac_device *codec, char *buf, size_t size) + { +- return snprintf(buf, size, "hdaudio:v%08Xr%08Xa%02X\n", ++ return scnprintf(buf, size, "hdaudio:v%08Xr%08Xa%02X\n", + codec->vendor_id, codec->revision_id, codec->type); + } + EXPORT_SYMBOL_GPL(snd_hdac_codec_modalias); +-- +2.16.4 + diff --git a/patches.suse/ALSA-hda-ca0132-Add-Recon3Di-quirk-to-handle-integra.patch b/patches.suse/ALSA-hda-ca0132-Add-Recon3Di-quirk-to-handle-integra.patch new file mode 100644 index 0000000..e8edcea --- /dev/null +++ b/patches.suse/ALSA-hda-ca0132-Add-Recon3Di-quirk-to-handle-integra.patch @@ -0,0 +1,43 @@ +From e9097e47e349b747dee50f935216de0ffb662962 Mon Sep 17 00:00:00 2001 +From: Geoffrey Allott +Date: Thu, 19 Mar 2020 14:00:48 +0000 +Subject: [PATCH] ALSA: hda/ca0132 - Add Recon3Di quirk to handle integrated sound on EVGA X99 Classified motherboard +Git-commit: e9097e47e349b747dee50f935216de0ffb662962 +Patch-mainline: v5.7-rc1 +References: bsc#1051510 + +I have a system which has an EVGA X99 Classified motherboard. The pin +assignments for the HD Audio controller are not correct under Linux. +Windows 10 works fine and informs me that it's using the Recon3Di +driver, and on Linux, `cat +/sys/class/sound/card0/device/subsystem_{vendor,device}` yields + +0x3842 +0x1038 + +This patch adds a corresponding entry to the quirk list. + +Signed-off-by: Geoffrey Allott +Cc: +Link: https://lore.kernel.org/r/a6cd56b678c00ce2db3685e4278919f2584f8244.camel@allott.email +Signed-off-by: Takashi Iwai + +--- + sound/pci/hda/patch_ca0132.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/sound/pci/hda/patch_ca0132.c b/sound/pci/hda/patch_ca0132.c +index ded8bc07d755..10223e080d59 100644 +--- a/sound/pci/hda/patch_ca0132.c ++++ b/sound/pci/hda/patch_ca0132.c +@@ -1180,6 +1180,7 @@ static const struct snd_pci_quirk ca0132_quirks[] = { + SND_PCI_QUIRK(0x1458, 0xA016, "Recon3Di", QUIRK_R3DI), + SND_PCI_QUIRK(0x1458, 0xA026, "Gigabyte G1.Sniper Z97", QUIRK_R3DI), + SND_PCI_QUIRK(0x1458, 0xA036, "Gigabyte GA-Z170X-Gaming 7", QUIRK_R3DI), ++ SND_PCI_QUIRK(0x3842, 0x1038, "EVGA X99 Classified", QUIRK_R3DI), + SND_PCI_QUIRK(0x1102, 0x0013, "Recon3D", QUIRK_R3D), + SND_PCI_QUIRK(0x1102, 0x0051, "Sound Blaster AE-5", QUIRK_AE5), + {} +-- +2.16.4 + diff --git a/patches.suse/ALSA-hda-ca0132-Replace-zero-length-array-with-flexi.patch b/patches.suse/ALSA-hda-ca0132-Replace-zero-length-array-with-flexi.patch new file mode 100644 index 0000000..1b4e2f6 --- /dev/null +++ b/patches.suse/ALSA-hda-ca0132-Replace-zero-length-array-with-flexi.patch @@ -0,0 +1,53 @@ +From 76501954cb9ef5b3d614a075870cfce47fbbd6df Mon Sep 17 00:00:00 2001 +From: "Gustavo A. R. Silva" +Date: Tue, 11 Feb 2020 13:44:03 -0600 +Subject: [PATCH] ALSA: hda/ca0132 - Replace zero-length array with flexible-array member +Git-commit: 76501954cb9ef5b3d614a075870cfce47fbbd6df +Patch-mainline: v5.7-rc1 +References: bsc#1051510 + +The current codebase makes use of the zero-length array language +extension to the C90 standard, but the preferred mechanism to declare +variable-length types such as these ones is a flexible array member[1][2], +introduced in C99: + +struct foo { + int stuff; + struct boo array[]; +}; + +By making use of the mechanism above, we will get a compiler warning +in case the flexible array does not occur last in the structure, which +will help us prevent some kind of undefined behavior bugs from being +inadvertenly introduced[3] to the codebase from now on. + +This issue was found with the help of Coccinelle. + +[1] https://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html +[2] https://github.com/KSPP/linux/issues/21 +[3] commit 76497732932f ("cxgb3/l2t: Fix undefined behaviour") + +Signed-off-by: Gustavo A. R. Silva +Link: https://lore.kernel.org/r/20200211194403.GA10318@embeddedor +Signed-off-by: Takashi Iwai + +--- + sound/pci/hda/patch_ca0132.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/sound/pci/hda/patch_ca0132.c b/sound/pci/hda/patch_ca0132.c +index ded8bc07d755..a4a39f7d9ae1 100644 +--- a/sound/pci/hda/patch_ca0132.c ++++ b/sound/pci/hda/patch_ca0132.c +@@ -2698,7 +2698,7 @@ struct dsp_image_seg { + u32 magic; + u32 chip_addr; + u32 count; +- u32 data[0]; ++ u32 data[]; + }; + + static const u32 g_magic_value = 0x4c46584d; +-- +2.16.4 + diff --git a/patches.suse/ALSA-hda-default-enable-CA0132-DSP-support.patch b/patches.suse/ALSA-hda-default-enable-CA0132-DSP-support.patch new file mode 100644 index 0000000..5154b14 --- /dev/null +++ b/patches.suse/ALSA-hda-default-enable-CA0132-DSP-support.patch @@ -0,0 +1,37 @@ +From 652bb5d8df4b3a79ed350db35cda12637e63efa7 Mon Sep 17 00:00:00 2001 +From: Rouven Czerwinski +Date: Sun, 29 Mar 2020 07:30:15 +0200 +Subject: [PATCH] ALSA: hda: default enable CA0132 DSP support +Git-commit: 652bb5d8df4b3a79ed350db35cda12637e63efa7 +Patch-mainline: v5.7-rc1 +References: bsc#1051510 + +If SND_HDA_CODEC_CA0132 is enabled, the DSP support should be enabled as +well. Disabled DSP support leads to a hanging alsa system and no sound +output on the card otherwise. Tested on: + + 06:00.0 Audio device: Creative Labs Sound Core3D [Sound Blaster Recon3D / Z-Series] (rev 01) + +Signed-off-by: Rouven Czerwinski +Link: https://lore.kernel.org/r/20200329053710.4276-1-r.czerwinski@pengutronix.de +Signed-off-by: Takashi Iwai + +--- + sound/pci/hda/Kconfig | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/sound/pci/hda/Kconfig b/sound/pci/hda/Kconfig +index bd48335d09d7..e1d3082a4fe9 100644 +--- a/sound/pci/hda/Kconfig ++++ b/sound/pci/hda/Kconfig +@@ -184,6 +184,7 @@ comment "Set to Y if you want auto-loading the codec driver" + config SND_HDA_CODEC_CA0132_DSP + bool "Support new DSP code for CA0132 codec" + depends on SND_HDA_CODEC_CA0132 ++ default y + select SND_HDA_DSP_LOADER + select FW_LOADER + help +-- +2.16.4 + diff --git a/patches.suse/ALSA-hda-realtek-Add-Headset-Button-supported-for-Th.patch b/patches.suse/ALSA-hda-realtek-Add-Headset-Button-supported-for-Th.patch new file mode 100644 index 0000000..7cd45fa --- /dev/null +++ b/patches.suse/ALSA-hda-realtek-Add-Headset-Button-supported-for-Th.patch @@ -0,0 +1,61 @@ +From 76f7dec08fd64e9e3ad0810a1a8a60b0a846d348 Mon Sep 17 00:00:00 2001 +From: Kailang Yang +Date: Mon, 10 Feb 2020 16:30:26 +0800 +Subject: [PATCH] ALSA: hda/realtek - Add Headset Button supported for ThinkPad X1 +Git-commit: 76f7dec08fd64e9e3ad0810a1a8a60b0a846d348 +Patch-mainline: v5.6-rc5 +References: bsc#1111666 + +ThinkPad want to support Headset Button control. +This patch will enable it. + +Signed-off-by: Kailang Yang +Cc: +Link: https://lore.kernel.org/r/7f0b7128f40f41f6b5582ff610adc33d@realtek.com +Signed-off-by: Takashi Iwai + +--- + sound/pci/hda/patch_realtek.c | 13 +++++++++---- + 1 file changed, 9 insertions(+), 4 deletions(-) + +diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c +index 128c7e9df6de..a8d66c1e4991 100644 +--- a/sound/pci/hda/patch_realtek.c ++++ b/sound/pci/hda/patch_realtek.c +@@ -5920,7 +5920,7 @@ enum { + ALC289_FIXUP_DUAL_SPK, + ALC294_FIXUP_SPK2_TO_DAC1, + ALC294_FIXUP_ASUS_DUAL_SPK, +- ++ ALC285_FIXUP_THINKPAD_HEADSET_JACK, + }; + + static const struct hda_fixup alc269_fixups[] = { +@@ -7042,7 +7042,12 @@ static const struct hda_fixup alc269_fixups[] = { + .chained = true, + .chain_id = ALC294_FIXUP_SPK2_TO_DAC1 + }, +- ++ [ALC285_FIXUP_THINKPAD_HEADSET_JACK] = { ++ .type = HDA_FIXUP_FUNC, ++ .v.func = alc_fixup_headset_jack, ++ .chained = true, ++ .chain_id = ALC285_FIXUP_SPEAKER2_TO_DAC1 ++ }, + }; + + static const struct snd_pci_quirk alc269_fixup_tbl[] = { +@@ -7278,8 +7283,8 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { + SND_PCI_QUIRK(0x17aa, 0x224c, "Thinkpad", ALC298_FIXUP_TPT470_DOCK), + SND_PCI_QUIRK(0x17aa, 0x224d, "Thinkpad", ALC298_FIXUP_TPT470_DOCK), + SND_PCI_QUIRK(0x17aa, 0x225d, "Thinkpad T480", ALC269_FIXUP_LIMIT_INT_MIC_BOOST), +- SND_PCI_QUIRK(0x17aa, 0x2292, "Thinkpad X1 Yoga 7th", ALC285_FIXUP_SPEAKER2_TO_DAC1), +- SND_PCI_QUIRK(0x17aa, 0x2293, "Thinkpad X1 Carbon 7th", ALC285_FIXUP_SPEAKER2_TO_DAC1), ++ SND_PCI_QUIRK(0x17aa, 0x2292, "Thinkpad X1 Yoga 7th", ALC285_FIXUP_THINKPAD_HEADSET_JACK), ++ SND_PCI_QUIRK(0x17aa, 0x2293, "Thinkpad X1 Carbon 7th", ALC285_FIXUP_THINKPAD_HEADSET_JACK), + SND_PCI_QUIRK(0x17aa, 0x30bb, "ThinkCentre AIO", ALC233_FIXUP_LENOVO_LINE2_MIC_HOTKEY), + SND_PCI_QUIRK(0x17aa, 0x30e2, "ThinkCentre AIO", ALC233_FIXUP_LENOVO_LINE2_MIC_HOTKEY), + SND_PCI_QUIRK(0x17aa, 0x310c, "ThinkCentre Station", ALC294_FIXUP_LENOVO_MIC_LOCATION), +-- +2.16.4 + diff --git a/patches.suse/ALSA-hda-realtek-Add-Headset-Mic-supported.patch b/patches.suse/ALSA-hda-realtek-Add-Headset-Mic-supported.patch new file mode 100644 index 0000000..3edd7bd --- /dev/null +++ b/patches.suse/ALSA-hda-realtek-Add-Headset-Mic-supported.patch @@ -0,0 +1,37 @@ +From 78def224f59c05d00e815be946ec229719ccf377 Mon Sep 17 00:00:00 2001 +From: Kailang Yang +Date: Thu, 20 Feb 2020 15:21:54 +0800 +Subject: [PATCH] ALSA: hda/realtek - Add Headset Mic supported +Git-commit: 78def224f59c05d00e815be946ec229719ccf377 +Patch-mainline: v5.6-rc5 +References: bsc#1111666 + +Dell desktop platform supported headset Mic. +Add pin verb to enable headset Mic. +This platform only support fixed type headset for Iphone type. + +Signed-off-by: Kailang Yang +Cc: +Link: https://lore.kernel.org/r/b9da28d772ef43088791b0f3675929e7@realtek.com +Signed-off-by: Takashi Iwai + +--- + sound/pci/hda/patch_realtek.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c +index 31bee0512334..128c7e9df6de 100644 +--- a/sound/pci/hda/patch_realtek.c ++++ b/sound/pci/hda/patch_realtek.c +@@ -7117,6 +7117,8 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { + SND_PCI_QUIRK(0x1028, 0x0935, "Dell", ALC274_FIXUP_DELL_AIO_LINEOUT_VERB), + SND_PCI_QUIRK(0x1028, 0x097e, "Dell Precision", ALC289_FIXUP_DUAL_SPK), + SND_PCI_QUIRK(0x1028, 0x097d, "Dell Precision", ALC289_FIXUP_DUAL_SPK), ++ SND_PCI_QUIRK(0x1028, 0x098d, "Dell Precision", ALC233_FIXUP_ASUS_MIC_NO_PRESENCE), ++ SND_PCI_QUIRK(0x1028, 0x09bf, "Dell Precision", ALC233_FIXUP_ASUS_MIC_NO_PRESENCE), + SND_PCI_QUIRK(0x1028, 0x164a, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE), + SND_PCI_QUIRK(0x1028, 0x164b, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE), + SND_PCI_QUIRK(0x103c, 0x1586, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC2), +-- +2.16.4 + diff --git a/patches.suse/ALSA-hda-realtek-Add-more-codec-supported-Headset-Bu.patch b/patches.suse/ALSA-hda-realtek-Add-more-codec-supported-Headset-Bu.patch new file mode 100644 index 0000000..93f2c88 --- /dev/null +++ b/patches.suse/ALSA-hda-realtek-Add-more-codec-supported-Headset-Bu.patch @@ -0,0 +1,38 @@ +From 2b3b6497c38d123934de68ea82a247b557d95290 Mon Sep 17 00:00:00 2001 +From: Kailang Yang +Date: Mon, 10 Feb 2020 16:15:14 +0800 +Subject: [PATCH] ALSA: hda/realtek - Add more codec supported Headset Button +Git-commit: 2b3b6497c38d123934de68ea82a247b557d95290 +Patch-mainline: v5.6-rc2 +References: bsc#1111666 + +Add supported Headset Button for ALC215/ALC285/ALC289. + +Signed-off-by: Kailang Yang +Cc: +Link: https://lore.kernel.org/r/948f70b4488f4cc2b629a39ce4e4be33@realtek.com +Signed-off-by: Takashi Iwai + +--- + sound/pci/hda/patch_realtek.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c +index 4770fb3f51fb..3ee88adf57e7 100644 +--- a/sound/pci/hda/patch_realtek.c ++++ b/sound/pci/hda/patch_realtek.c +@@ -5701,8 +5701,11 @@ static void alc_fixup_headset_jack(struct hda_codec *codec, + break; + case HDA_FIXUP_ACT_INIT: + switch (codec->core.vendor_id) { ++ case 0x10ec0215: + case 0x10ec0225: ++ case 0x10ec0285: + case 0x10ec0295: ++ case 0x10ec0289: + case 0x10ec0299: + alc_write_coef_idx(codec, 0x48, 0xd011); + alc_update_coef_idx(codec, 0x49, 0x007f, 0x0045); +-- +2.16.4 + diff --git a/patches.suse/ALSA-hda-realtek-Apply-quirk-for-MSI-GP63-too.patch b/patches.suse/ALSA-hda-realtek-Apply-quirk-for-MSI-GP63-too.patch new file mode 100644 index 0000000..ea9d15c --- /dev/null +++ b/patches.suse/ALSA-hda-realtek-Apply-quirk-for-MSI-GP63-too.patch @@ -0,0 +1,35 @@ +From a655e2b107d463ce2745188ce050d07daed09a71 Mon Sep 17 00:00:00 2001 +From: Takashi Iwai +Date: Mon, 17 Feb 2020 16:19:47 +0100 +Subject: [PATCH] ALSA: hda/realtek - Apply quirk for MSI GP63, too +Git-commit: a655e2b107d463ce2745188ce050d07daed09a71 +Patch-mainline: v5.6-rc3 +References: bsc#1111666 + +The same quirk that was applied to MSI GL73 is needed for MSI GP63, +too. Adding the entry with the SSID 1462:1228. + +Buglink: https://bugzilla.kernel.org/show_bug.cgi?id=206503 +Cc: +Link: https://lore.kernel.org/r/20200217151947.17528-1-tiwai@suse.de +Signed-off-by: Takashi Iwai + +--- + sound/pci/hda/patch_realtek.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c +index 6c8cb4ce517e..82485e06dde1 100644 +--- a/sound/pci/hda/patch_realtek.c ++++ b/sound/pci/hda/patch_realtek.c +@@ -2447,6 +2447,7 @@ static const struct snd_pci_quirk alc882_fixup_tbl[] = { + SND_PCI_QUIRK(0x1071, 0x8258, "Evesham Voyaeger", ALC882_FIXUP_EAPD), + SND_PCI_QUIRK(0x1458, 0xa002, "Gigabyte EP45-DS3/Z87X-UD3H", ALC889_FIXUP_FRONT_HP_NO_PRESENCE), + SND_PCI_QUIRK(0x1458, 0xa0b8, "Gigabyte AZ370-Gaming", ALC1220_FIXUP_GB_DUAL_CODECS), ++ SND_PCI_QUIRK(0x1462, 0x1228, "MSI-GP63", ALC1220_FIXUP_CLEVO_P950), + SND_PCI_QUIRK(0x1462, 0x1276, "MSI-GL73", ALC1220_FIXUP_CLEVO_P950), + SND_PCI_QUIRK(0x1462, 0x7350, "MSI-7350", ALC889_FIXUP_CD), + SND_PCI_QUIRK(0x1462, 0xda57, "MSI Z270-Gaming", ALC1220_FIXUP_GB_DUAL_CODECS), +-- +2.16.4 + diff --git a/patches.suse/ALSA-hda-realtek-Apply-quirk-for-yet-another-MSI-lap.patch b/patches.suse/ALSA-hda-realtek-Apply-quirk-for-yet-another-MSI-lap.patch new file mode 100644 index 0000000..0d939ce --- /dev/null +++ b/patches.suse/ALSA-hda-realtek-Apply-quirk-for-yet-another-MSI-lap.patch @@ -0,0 +1,35 @@ +From cc5049ae4d457194796f854eb2e38b9727ad8c2d Mon Sep 17 00:00:00 2001 +From: Takashi Iwai +Date: Tue, 18 Feb 2020 09:09:15 +0100 +Subject: [PATCH] ALSA: hda/realtek - Apply quirk for yet another MSI laptop +Git-commit: cc5049ae4d457194796f854eb2e38b9727ad8c2d +Patch-mainline: v5.6-rc3 +References: bsc#1111666 + +MSI GP65 laptop with SSID 1462:1293 requires the same quirk as other +MSI models. + +Buglink: https://bugzilla.kernel.org/show_bug.cgi?id=204159 +Cc: +Link: https://lore.kernel.org/r/20200218080915.3433-1-tiwai@suse.de +Signed-off-by: Takashi Iwai + +--- + sound/pci/hda/patch_realtek.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c +index 82485e06dde1..477589e7ec1d 100644 +--- a/sound/pci/hda/patch_realtek.c ++++ b/sound/pci/hda/patch_realtek.c +@@ -2449,6 +2449,7 @@ static const struct snd_pci_quirk alc882_fixup_tbl[] = { + SND_PCI_QUIRK(0x1458, 0xa0b8, "Gigabyte AZ370-Gaming", ALC1220_FIXUP_GB_DUAL_CODECS), + SND_PCI_QUIRK(0x1462, 0x1228, "MSI-GP63", ALC1220_FIXUP_CLEVO_P950), + SND_PCI_QUIRK(0x1462, 0x1276, "MSI-GL73", ALC1220_FIXUP_CLEVO_P950), ++ SND_PCI_QUIRK(0x1462, 0x1293, "MSI-GP65", ALC1220_FIXUP_CLEVO_P950), + SND_PCI_QUIRK(0x1462, 0x7350, "MSI-7350", ALC889_FIXUP_CD), + SND_PCI_QUIRK(0x1462, 0xda57, "MSI Z270-Gaming", ALC1220_FIXUP_GB_DUAL_CODECS), + SND_PCI_QUIRK_VENDOR(0x1462, "MSI", ALC882_FIXUP_GPIO3), +-- +2.16.4 + diff --git a/patches.suse/ALSA-hda-realtek-Enable-headset-mic-of-Acer-X2660G-w.patch b/patches.suse/ALSA-hda-realtek-Enable-headset-mic-of-Acer-X2660G-w.patch new file mode 100644 index 0000000..0b274cb --- /dev/null +++ b/patches.suse/ALSA-hda-realtek-Enable-headset-mic-of-Acer-X2660G-w.patch @@ -0,0 +1,59 @@ +From d858c706bdca97698752bd26b60c21ec07ef04f2 Mon Sep 17 00:00:00 2001 +From: Jian-Hong Pan +Date: Tue, 17 Mar 2020 16:28:07 +0800 +Subject: [PATCH] ALSA: hda/realtek - Enable headset mic of Acer X2660G with ALC662 +Git-commit: d858c706bdca97698752bd26b60c21ec07ef04f2 +Patch-mainline: v5.6-rc7 +References: git-fixes + +The Acer desktop X2660G with ALC662 can't detect the headset microphone +until ALC662_FIXUP_ACER_X2660G_HEADSET_MODE quirk applied. + +Signed-off-by: Jian-Hong Pan +Cc: +Link: https://lore.kernel.org/r/20200317082806.73194-2-jian-hong@endlessm.com +Signed-off-by: Takashi Iwai + +--- + sound/pci/hda/patch_realtek.c | 11 +++++++++++ + 1 file changed, 11 insertions(+) + +diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c +index 7b83b020ac3c..a08481f358e9 100644 +--- a/sound/pci/hda/patch_realtek.c ++++ b/sound/pci/hda/patch_realtek.c +@@ -8612,6 +8612,7 @@ enum { + ALC669_FIXUP_ACER_ASPIRE_ETHOS, + ALC669_FIXUP_ACER_ASPIRE_ETHOS_HEADSET, + ALC671_FIXUP_HP_HEADSET_MIC2, ++ ALC662_FIXUP_ACER_X2660G_HEADSET_MODE, + }; + + static const struct hda_fixup alc662_fixups[] = { +@@ -8957,6 +8958,15 @@ static const struct hda_fixup alc662_fixups[] = { + .type = HDA_FIXUP_FUNC, + .v.func = alc671_fixup_hp_headset_mic2, + }, ++ [ALC662_FIXUP_ACER_X2660G_HEADSET_MODE] = { ++ .type = HDA_FIXUP_PINS, ++ .v.pins = (const struct hda_pintbl[]) { ++ { 0x1a, 0x02a1113c }, /* use as headset mic, without its own jack detect */ ++ { } ++ }, ++ .chained = true, ++ .chain_id = ALC662_FIXUP_USI_FUNC ++ }, + }; + + static const struct snd_pci_quirk alc662_fixup_tbl[] = { +@@ -8968,6 +8978,7 @@ static const struct snd_pci_quirk alc662_fixup_tbl[] = { + SND_PCI_QUIRK(0x1025, 0x0349, "eMachines eM250", ALC662_FIXUP_INV_DMIC), + SND_PCI_QUIRK(0x1025, 0x034a, "Gateway LT27", ALC662_FIXUP_INV_DMIC), + SND_PCI_QUIRK(0x1025, 0x038b, "Acer Aspire 8943G", ALC662_FIXUP_ASPIRE), ++ SND_PCI_QUIRK(0x1025, 0x124e, "Acer 2660G", ALC662_FIXUP_ACER_X2660G_HEADSET_MODE), + SND_PCI_QUIRK(0x1028, 0x05d8, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE), + SND_PCI_QUIRK(0x1028, 0x05db, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE), + SND_PCI_QUIRK(0x1028, 0x05fe, "Dell XPS 15", ALC668_FIXUP_DELL_XPS13), +-- +2.16.4 + diff --git a/patches.suse/ALSA-hda-realtek-Enable-mute-LED-on-an-HP-system.patch b/patches.suse/ALSA-hda-realtek-Enable-mute-LED-on-an-HP-system.patch new file mode 100644 index 0000000..054ff1a --- /dev/null +++ b/patches.suse/ALSA-hda-realtek-Enable-mute-LED-on-an-HP-system.patch @@ -0,0 +1,70 @@ +From f5a88b0accc24c4a9021247d7a3124f90aa4c586 Mon Sep 17 00:00:00 2001 +From: Kai-Heng Feng +Date: Fri, 27 Mar 2020 12:46:25 +0800 +Subject: [PATCH] ALSA: hda/realtek: Enable mute LED on an HP system +Git-commit: f5a88b0accc24c4a9021247d7a3124f90aa4c586 +Patch-mainline: v5.7-rc1 +References: bsc#1051510 + +The system in question uses ALC285, and it uses GPIO 0x04 to control its +mute LED. + +The mic mute LED can be controlled by GPIO 0x01, however the system uses +DMIC so we should use that to control mic mute LED. + +Signed-off-by: Kai-Heng Feng +Cc: +Link: https://lore.kernel.org/r/20200327044626.29582-1-kai.heng.feng@canonical.com +Signed-off-by: Takashi Iwai + +--- + sound/pci/hda/patch_realtek.c | 12 ++++++++++++ + 1 file changed, 12 insertions(+) + +diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c +index 63e1a56f705b..1ad8c2e2d1af 100644 +--- a/sound/pci/hda/patch_realtek.c ++++ b/sound/pci/hda/patch_realtek.c +@@ -4008,6 +4008,12 @@ static void alc269_fixup_hp_gpio_led(struct hda_codec *codec, + alc_fixup_hp_gpio_led(codec, action, 0x08, 0x10); + } + ++static void alc285_fixup_hp_gpio_led(struct hda_codec *codec, ++ const struct hda_fixup *fix, int action) ++{ ++ alc_fixup_hp_gpio_led(codec, action, 0x04, 0x00); ++} ++ + static void alc286_fixup_hp_gpio_led(struct hda_codec *codec, + const struct hda_fixup *fix, int action) + { +@@ -5923,6 +5929,7 @@ enum { + ALC294_FIXUP_ASUS_DUAL_SPK, + ALC285_FIXUP_THINKPAD_HEADSET_JACK, + ALC294_FIXUP_ASUS_HPE, ++ ALC285_FIXUP_HP_GPIO_LED, + }; + + static const struct hda_fixup alc269_fixups[] = { +@@ -7061,6 +7068,10 @@ static const struct hda_fixup alc269_fixups[] = { + .chained = true, + .chain_id = ALC294_FIXUP_ASUS_HEADSET_MIC + }, ++ [ALC285_FIXUP_HP_GPIO_LED] = { ++ .type = HDA_FIXUP_FUNC, ++ .v.func = alc285_fixup_hp_gpio_led, ++ }, + }; + + static const struct snd_pci_quirk alc269_fixup_tbl[] = { +@@ -7208,6 +7219,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { + SND_PCI_QUIRK(0x103c, 0x83b9, "HP Spectre x360", ALC269_FIXUP_HP_MUTE_LED_MIC3), + SND_PCI_QUIRK(0x103c, 0x8497, "HP Envy x360", ALC269_FIXUP_HP_MUTE_LED_MIC3), + SND_PCI_QUIRK(0x103c, 0x84e7, "HP Pavilion 15", ALC269_FIXUP_HP_MUTE_LED_MIC3), ++ SND_PCI_QUIRK(0x103c, 0x8736, "HP", ALC285_FIXUP_HP_GPIO_LED), + SND_PCI_QUIRK(0x1043, 0x103e, "ASUS X540SA", ALC256_FIXUP_ASUS_MIC), + SND_PCI_QUIRK(0x1043, 0x103f, "ASUS TX300", ALC282_FIXUP_ASUS_TX300), + SND_PCI_QUIRK(0x1043, 0x106d, "Asus K53BE", ALC269_FIXUP_LIMIT_INT_MIC_BOOST), +-- +2.16.4 + diff --git a/patches.suse/ALSA-hda-realtek-Enable-the-headset-of-ASUS-B9450FA-.patch b/patches.suse/ALSA-hda-realtek-Enable-the-headset-of-ASUS-B9450FA-.patch new file mode 100644 index 0000000..2a93999 --- /dev/null +++ b/patches.suse/ALSA-hda-realtek-Enable-the-headset-of-ASUS-B9450FA-.patch @@ -0,0 +1,62 @@ +From 8b33a134a9cc2a501f8fc731d91caef39237d495 Mon Sep 17 00:00:00 2001 +From: Jian-Hong Pan +Date: Tue, 25 Feb 2020 15:29:21 +0800 +Subject: [PATCH] ALSA: hda/realtek - Enable the headset of ASUS B9450FA with ALC294 +Git-commit: 8b33a134a9cc2a501f8fc731d91caef39237d495 +Patch-mainline: v5.6-rc5 +References: bsc#1111666 + +A headset on the laptop like ASUS B9450FA does not work, until quirk +ALC294_FIXUP_ASUS_HPE is applied. + +Signed-off-by: Jian-Hong Pan +Signed-off-by: Kailang Yang +Cc: +Link: https://lore.kernel.org/r/20200225072920.109199-1-jian-hong@endlessm.com +Signed-off-by: Takashi Iwai + +--- + sound/pci/hda/patch_realtek.c | 13 +++++++++++++ + 1 file changed, 13 insertions(+) + +diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c +index 508d2be3d43d..0ac06ff1a17c 100644 +--- a/sound/pci/hda/patch_realtek.c ++++ b/sound/pci/hda/patch_realtek.c +@@ -5922,6 +5922,7 @@ enum { + ALC294_FIXUP_SPK2_TO_DAC1, + ALC294_FIXUP_ASUS_DUAL_SPK, + ALC285_FIXUP_THINKPAD_HEADSET_JACK, ++ ALC294_FIXUP_ASUS_HPE, + }; + + static const struct hda_fixup alc269_fixups[] = { +@@ -7049,6 +7050,17 @@ static const struct hda_fixup alc269_fixups[] = { + .chained = true, + .chain_id = ALC285_FIXUP_SPEAKER2_TO_DAC1 + }, ++ [ALC294_FIXUP_ASUS_HPE] = { ++ .type = HDA_FIXUP_VERBS, ++ .v.verbs = (const struct hda_verb[]) { ++ /* Set EAPD high */ ++ { 0x20, AC_VERB_SET_COEF_INDEX, 0x0f }, ++ { 0x20, AC_VERB_SET_PROC_COEF, 0x7774 }, ++ { } ++ }, ++ .chained = true, ++ .chain_id = ALC294_FIXUP_ASUS_HEADSET_MIC ++ }, + }; + + static const struct snd_pci_quirk alc269_fixup_tbl[] = { +@@ -7214,6 +7226,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { + SND_PCI_QUIRK(0x1043, 0x16e3, "ASUS UX50", ALC269_FIXUP_STEREO_DMIC), + SND_PCI_QUIRK(0x1043, 0x17d1, "ASUS UX431FL", ALC294_FIXUP_ASUS_DUAL_SPK), + SND_PCI_QUIRK(0x1043, 0x18b1, "Asus MJ401TA", ALC256_FIXUP_ASUS_HEADSET_MIC), ++ SND_PCI_QUIRK(0x1043, 0x19ce, "ASUS B9450FA", ALC294_FIXUP_ASUS_HPE), + SND_PCI_QUIRK(0x1043, 0x1a13, "Asus G73Jw", ALC269_FIXUP_ASUS_G73JW), + SND_PCI_QUIRK(0x1043, 0x1a30, "ASUS X705UD", ALC256_FIXUP_ASUS_MIC), + SND_PCI_QUIRK(0x1043, 0x1b13, "Asus U41SV", ALC269_FIXUP_INV_DMIC), +-- +2.16.4 + diff --git a/patches.suse/ALSA-hda-realtek-Enable-the-headset-of-Acer-N50-600-.patch b/patches.suse/ALSA-hda-realtek-Enable-the-headset-of-Acer-N50-600-.patch new file mode 100644 index 0000000..273928f --- /dev/null +++ b/patches.suse/ALSA-hda-realtek-Enable-the-headset-of-Acer-N50-600-.patch @@ -0,0 +1,60 @@ +From a124458a127ccd7629e20cd7bae3e1f758ed32aa Mon Sep 17 00:00:00 2001 +From: Jian-Hong Pan +Date: Tue, 17 Mar 2020 16:28:09 +0800 +Subject: [PATCH] ALSA: hda/realtek - Enable the headset of Acer N50-600 with ALC662 +Git-commit: a124458a127ccd7629e20cd7bae3e1f758ed32aa +Patch-mainline: v5.6-rc7 +References: git-fixes + +A headset on the desktop like Acer N50-600 does not work, until quirk +ALC662_FIXUP_ACER_NITRO_HEADSET_MODE is applied. + +Signed-off-by: Jian-Hong Pan +Cc: +Link: https://lore.kernel.org/r/20200317082806.73194-3-jian-hong@endlessm.com +Signed-off-by: Takashi Iwai + +--- + sound/pci/hda/patch_realtek.c | 12 ++++++++++++ + 1 file changed, 12 insertions(+) + +diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c +index a08481f358e9..63e1a56f705b 100644 +--- a/sound/pci/hda/patch_realtek.c ++++ b/sound/pci/hda/patch_realtek.c +@@ -8613,6 +8613,7 @@ enum { + ALC669_FIXUP_ACER_ASPIRE_ETHOS_HEADSET, + ALC671_FIXUP_HP_HEADSET_MIC2, + ALC662_FIXUP_ACER_X2660G_HEADSET_MODE, ++ ALC662_FIXUP_ACER_NITRO_HEADSET_MODE, + }; + + static const struct hda_fixup alc662_fixups[] = { +@@ -8967,6 +8968,16 @@ static const struct hda_fixup alc662_fixups[] = { + .chained = true, + .chain_id = ALC662_FIXUP_USI_FUNC + }, ++ [ALC662_FIXUP_ACER_NITRO_HEADSET_MODE] = { ++ .type = HDA_FIXUP_PINS, ++ .v.pins = (const struct hda_pintbl[]) { ++ { 0x1a, 0x01a11140 }, /* use as headset mic, without its own jack detect */ ++ { 0x1b, 0x0221144f }, ++ { } ++ }, ++ .chained = true, ++ .chain_id = ALC662_FIXUP_USI_FUNC ++ }, + }; + + static const struct snd_pci_quirk alc662_fixup_tbl[] = { +@@ -8978,6 +8989,7 @@ static const struct snd_pci_quirk alc662_fixup_tbl[] = { + SND_PCI_QUIRK(0x1025, 0x0349, "eMachines eM250", ALC662_FIXUP_INV_DMIC), + SND_PCI_QUIRK(0x1025, 0x034a, "Gateway LT27", ALC662_FIXUP_INV_DMIC), + SND_PCI_QUIRK(0x1025, 0x038b, "Acer Aspire 8943G", ALC662_FIXUP_ASPIRE), ++ SND_PCI_QUIRK(0x1025, 0x123c, "Acer Nitro N50-600", ALC662_FIXUP_ACER_NITRO_HEADSET_MODE), + SND_PCI_QUIRK(0x1025, 0x124e, "Acer 2660G", ALC662_FIXUP_ACER_X2660G_HEADSET_MODE), + SND_PCI_QUIRK(0x1028, 0x05d8, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE), + SND_PCI_QUIRK(0x1028, 0x05db, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE), +-- +2.16.4 + diff --git a/patches.suse/ALSA-hda-realtek-Fix-a-regression-for-mute-led-on-Le.patch b/patches.suse/ALSA-hda-realtek-Fix-a-regression-for-mute-led-on-Le.patch new file mode 100644 index 0000000..d76e89a --- /dev/null +++ b/patches.suse/ALSA-hda-realtek-Fix-a-regression-for-mute-led-on-Le.patch @@ -0,0 +1,37 @@ +From c37c0ab029569a75fd180edb03d411e7a28a936f Mon Sep 17 00:00:00 2001 +From: Hui Wang +Date: Wed, 19 Feb 2020 13:23:06 +0800 +Subject: [PATCH] ALSA: hda/realtek - Fix a regression for mute led on Lenovo Carbon X1 +Git-commit: c37c0ab029569a75fd180edb03d411e7a28a936f +Patch-mainline: v5.6-rc5 +References: bsc#1111666 + +Need to chain the THINKPAD_ACPI, otherwise the mute led will not +work. + +Fixes: d2cd795c4ece ("ALSA: hda - fixup for the bass speaker on Lenovo Carbon X1 7th gen") +Cc: +Signed-off-by: Hui Wang +Link: https://lore.kernel.org/r/20200219052306.24935-1-hui.wang@canonical.com +Signed-off-by: Takashi Iwai + +--- + sound/pci/hda/patch_realtek.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c +index 477589e7ec1d..31bee0512334 100644 +--- a/sound/pci/hda/patch_realtek.c ++++ b/sound/pci/hda/patch_realtek.c +@@ -6684,6 +6684,8 @@ static const struct hda_fixup alc269_fixups[] = { + [ALC285_FIXUP_SPEAKER2_TO_DAC1] = { + .type = HDA_FIXUP_FUNC, + .v.func = alc285_fixup_speaker2_to_dac1, ++ .chained = true, ++ .chain_id = ALC269_FIXUP_THINKPAD_ACPI + }, + [ALC256_FIXUP_DELL_INSPIRON_7559_SUBWOOFER] = { + .type = HDA_FIXUP_PINS, +-- +2.16.4 + diff --git a/patches.suse/ALSA-hda-realtek-Fix-pop-noise-on-ALC225.patch b/patches.suse/ALSA-hda-realtek-Fix-pop-noise-on-ALC225.patch new file mode 100644 index 0000000..29f2c9c --- /dev/null +++ b/patches.suse/ALSA-hda-realtek-Fix-pop-noise-on-ALC225.patch @@ -0,0 +1,39 @@ +From 3b36b13d5e69d6f51ff1c55d1b404a74646c9757 Mon Sep 17 00:00:00 2001 +From: Kai-Heng Feng +Date: Wed, 11 Mar 2020 14:13:28 +0800 +Subject: [PATCH] ALSA: hda/realtek: Fix pop noise on ALC225 +Git-commit: 3b36b13d5e69d6f51ff1c55d1b404a74646c9757 +Patch-mainline: v5.6-rc7 +References: git-fixes + +Commit 317d9313925c ("ALSA: hda/realtek - Set default power save node to +0") makes the ALC225 have pop noise on S3 resume and cold boot. + +So partially revert this commit for ALC225 to fix the regression. + +Fixes: 317d9313925c ("ALSA: hda/realtek - Set default power save node to 0") +Buglink: https://bugs.launchpad.net/bugs/1866357 +Signed-off-by: Kai-Heng Feng +Link: https://lore.kernel.org/r/20200311061328.17614-1-kai.heng.feng@canonical.com +Signed-off-by: Takashi Iwai + +--- + sound/pci/hda/patch_realtek.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c +index 0ac06ff1a17c..7b83b020ac3c 100644 +--- a/sound/pci/hda/patch_realtek.c ++++ b/sound/pci/hda/patch_realtek.c +@@ -8051,6 +8051,8 @@ static int patch_alc269(struct hda_codec *codec) + spec->gen.mixer_nid = 0; + break; + case 0x10ec0225: ++ codec->power_save_node = 1; ++ /* fall through */ + case 0x10ec0295: + case 0x10ec0299: + spec->codec_variant = ALC269_TYPE_ALC225; +-- +2.16.4 + diff --git a/patches.suse/ALSA-hda-realtek-Fix-silent-output-on-Gigabyte-X570-.patch b/patches.suse/ALSA-hda-realtek-Fix-silent-output-on-Gigabyte-X570-.patch new file mode 100644 index 0000000..a8b2479 --- /dev/null +++ b/patches.suse/ALSA-hda-realtek-Fix-silent-output-on-Gigabyte-X570-.patch @@ -0,0 +1,37 @@ +From 0d45e86d2267d5bdf7bbb631499788da1c27ceb2 Mon Sep 17 00:00:00 2001 +From: Christian Lachner +Date: Sun, 23 Feb 2020 10:24:16 +0100 +Subject: [PATCH] ALSA: hda/realtek - Fix silent output on Gigabyte X570 Aorus Master +Git-commit: 0d45e86d2267d5bdf7bbb631499788da1c27ceb2 +Patch-mainline: v5.6-rc5 +References: bsc#1111666 + +The Gigabyte X570 Aorus Master motherboard with ALC1220 codec +requires a similar workaround for Clevo laptops to enforce the +DAC/mixer connection path. Set up a quirk entry for that. + +Buglink: https://bugzilla.kernel.org/show_bug.cgi?id=205275 +Signed-off-by: Christian Lachner +Cc: +Link: https://lore.kernel.org/r/20200223092416.15016-2-gladiac@gmail.com +Signed-off-by: Takashi Iwai + +--- + sound/pci/hda/patch_realtek.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c +index a8d66c1e4991..508d2be3d43d 100644 +--- a/sound/pci/hda/patch_realtek.c ++++ b/sound/pci/hda/patch_realtek.c +@@ -2447,6 +2447,7 @@ static const struct snd_pci_quirk alc882_fixup_tbl[] = { + SND_PCI_QUIRK(0x1071, 0x8258, "Evesham Voyaeger", ALC882_FIXUP_EAPD), + SND_PCI_QUIRK(0x1458, 0xa002, "Gigabyte EP45-DS3/Z87X-UD3H", ALC889_FIXUP_FRONT_HP_NO_PRESENCE), + SND_PCI_QUIRK(0x1458, 0xa0b8, "Gigabyte AZ370-Gaming", ALC1220_FIXUP_GB_DUAL_CODECS), ++ SND_PCI_QUIRK(0x1458, 0xa0cd, "Gigabyte X570 Aorus Master", ALC1220_FIXUP_CLEVO_P950), + SND_PCI_QUIRK(0x1462, 0x1228, "MSI-GP63", ALC1220_FIXUP_CLEVO_P950), + SND_PCI_QUIRK(0x1462, 0x1276, "MSI-GL73", ALC1220_FIXUP_CLEVO_P950), + SND_PCI_QUIRK(0x1462, 0x1293, "MSI-GP65", ALC1220_FIXUP_CLEVO_P950), +-- +2.16.4 + diff --git a/patches.suse/ALSA-hda-realtek-Remove-now-unnecessary-XPS-13-headp.patch b/patches.suse/ALSA-hda-realtek-Remove-now-unnecessary-XPS-13-headp.patch new file mode 100644 index 0000000..8b74c59 --- /dev/null +++ b/patches.suse/ALSA-hda-realtek-Remove-now-unnecessary-XPS-13-headp.patch @@ -0,0 +1,147 @@ +From f36938aa7440f46a0a365f1cfde5f5985af2bef3 Mon Sep 17 00:00:00 2001 +From: Thomas Hebb +Date: Mon, 30 Mar 2020 12:09:39 -0400 +Subject: [PATCH] ALSA: hda/realtek - Remove now-unnecessary XPS 13 headphone noise fixups +Git-commit: f36938aa7440f46a0a365f1cfde5f5985af2bef3 +Patch-mainline: v5.7-rc1 +References: bsc#1051510 + +patch_realtek.c has historically failed to properly configure the PC +Beep Hidden Register for the ALC256 codec (among others). Depending on +your kernel version, symptoms of this misconfiguration can range from +chassis noise, picked up by a poorly-shielded PCBEEP trace, getting +amplified and played on your internal speaker and/or headphones to loud +feedback, which responds to the "Headphone Mic Boost" ALSA control, +getting played through your headphones. For details of the problem, see +the patch in this series titled "ALSA: hda/realtek - Set principled PC +Beep configuration for ALC256", which fixes the configuration. + +These symptoms have been most noticed on the Dell XPS 13 9350 and 9360, +popular laptops that use the ALC256. As a result, several model-specific +fixups have been introduced to try and fix the problem, the most +egregious of which locks the "Headphone Mic Boost" control as a hack to +minimize noise from a feedback loop that shouldn't have been there in +the first place. + +Now that the underlying issue has been fixed, remove all these fixups. +Remaining fixups needed by the XPS 13 are all picked up by existing pin +quirks. + +This change should, for the XPS 13 9350/9360 + + - Significantly increase volume and audio quality on headphones + - Eliminate headphone popping on suspend/resume + - Allow "Headphone Mic Boost" to be set again, making the headphone + jack fully usable as a microphone jack too. + +Fixes: 8c69729b4439 ("ALSA: hda - Fix headphone noise after Dell XPS 13 resume back from S3") +Fixes: 423cd785619a ("ALSA: hda - Fix headphone noise on Dell XPS 13 9360") +Fixes: e4c9fd10eb21 ("ALSA: hda - Apply headphone noise quirk for another Dell XPS 13 variant") +Fixes: 1099f48457d0 ("ALSA: hda/realtek: Reduce the Headphone static noise on XPS 9350/9360") +Cc: stable@vger.kernel.org +Signed-off-by: Thomas Hebb +Link: https://lore.kernel.org/r/b649a00edfde150cf6eebbb4390e15e0c2deb39a.1585584498.git.tommyhebb@gmail.com +Signed-off-by: Takashi Iwai + +--- + Documentation/sound/hd-audio/models.rst | 2 -- + sound/pci/hda/patch_realtek.c | 34 --------------------------------- + 2 files changed, 36 deletions(-) + +diff --git a/Documentation/sound/hd-audio/models.rst b/Documentation/sound/hd-audio/models.rst +index 11298f0ce44d..0ea967d34583 100644 +--- a/Documentation/sound/hd-audio/models.rst ++++ b/Documentation/sound/hd-audio/models.rst +@@ -216,8 +216,6 @@ alc298-dell-aio + ALC298 fixups on Dell AIO machines + alc275-dell-xps + ALC275 fixups on Dell XPS models +-alc256-dell-xps13 +- ALC256 fixups on Dell XPS13 + lenovo-spk-noise + Workaround for speaker noise on Lenovo machines + lenovo-hotkey +diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c +index 425521d03dc3..f66a48154a57 100644 +--- a/sound/pci/hda/patch_realtek.c ++++ b/sound/pci/hda/patch_realtek.c +@@ -5491,17 +5491,6 @@ static void alc271_hp_gate_mic_jack(struct hda_codec *codec, + } + } + +-static void alc256_fixup_dell_xps_13_headphone_noise2(struct hda_codec *codec, +- const struct hda_fixup *fix, +- int action) +-{ +- if (action != HDA_FIXUP_ACT_PRE_PROBE) +- return; +- +- snd_hda_codec_amp_stereo(codec, 0x1a, HDA_INPUT, 0, HDA_AMP_VOLMASK, 1); +- snd_hda_override_wcaps(codec, 0x1a, get_wcaps(codec, 0x1a) & ~AC_WCAP_IN_AMP); +-} +- + static void alc269_fixup_limit_int_mic_boost(struct hda_codec *codec, + const struct hda_fixup *fix, + int action) +@@ -5916,8 +5905,6 @@ enum { + ALC298_FIXUP_DELL1_MIC_NO_PRESENCE, + ALC298_FIXUP_DELL_AIO_MIC_NO_PRESENCE, + ALC275_FIXUP_DELL_XPS, +- ALC256_FIXUP_DELL_XPS_13_HEADPHONE_NOISE, +- ALC256_FIXUP_DELL_XPS_13_HEADPHONE_NOISE2, + ALC293_FIXUP_LENOVO_SPK_NOISE, + ALC233_FIXUP_LENOVO_LINE2_MIC_HOTKEY, + ALC255_FIXUP_DELL_SPK_NOISE, +@@ -6658,23 +6645,6 @@ static const struct hda_fixup alc269_fixups[] = { + {} + } + }, +- [ALC256_FIXUP_DELL_XPS_13_HEADPHONE_NOISE] = { +- .type = HDA_FIXUP_VERBS, +- .v.verbs = (const struct hda_verb[]) { +- /* Disable pass-through path for FRONT 14h */ +- {0x20, AC_VERB_SET_COEF_INDEX, 0x36}, +- {0x20, AC_VERB_SET_PROC_COEF, 0x1737}, +- {} +- }, +- .chained = true, +- .chain_id = ALC255_FIXUP_DELL1_MIC_NO_PRESENCE +- }, +- [ALC256_FIXUP_DELL_XPS_13_HEADPHONE_NOISE2] = { +- .type = HDA_FIXUP_FUNC, +- .v.func = alc256_fixup_dell_xps_13_headphone_noise2, +- .chained = true, +- .chain_id = ALC256_FIXUP_DELL_XPS_13_HEADPHONE_NOISE +- }, + [ALC293_FIXUP_LENOVO_SPK_NOISE] = { + .type = HDA_FIXUP_FUNC, + .v.func = alc_fixup_disable_aamix, +@@ -7172,17 +7142,14 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { + SND_PCI_QUIRK(0x1028, 0x06de, "Dell", ALC293_FIXUP_DISABLE_AAMIX_MULTIJACK), + SND_PCI_QUIRK(0x1028, 0x06df, "Dell", ALC293_FIXUP_DISABLE_AAMIX_MULTIJACK), + SND_PCI_QUIRK(0x1028, 0x06e0, "Dell", ALC293_FIXUP_DISABLE_AAMIX_MULTIJACK), +- SND_PCI_QUIRK(0x1028, 0x0704, "Dell XPS 13 9350", ALC256_FIXUP_DELL_XPS_13_HEADPHONE_NOISE2), + SND_PCI_QUIRK(0x1028, 0x0706, "Dell Inspiron 7559", ALC256_FIXUP_DELL_INSPIRON_7559_SUBWOOFER), + SND_PCI_QUIRK(0x1028, 0x0725, "Dell Inspiron 3162", ALC255_FIXUP_DELL_SPK_NOISE), + SND_PCI_QUIRK(0x1028, 0x0738, "Dell Precision 5820", ALC269_FIXUP_NO_SHUTUP), +- SND_PCI_QUIRK(0x1028, 0x075b, "Dell XPS 13 9360", ALC256_FIXUP_DELL_XPS_13_HEADPHONE_NOISE2), + SND_PCI_QUIRK(0x1028, 0x075c, "Dell XPS 27 7760", ALC298_FIXUP_SPK_VOLUME), + SND_PCI_QUIRK(0x1028, 0x075d, "Dell AIO", ALC298_FIXUP_SPK_VOLUME), + SND_PCI_QUIRK(0x1028, 0x07b0, "Dell Precision 7520", ALC295_FIXUP_DISABLE_DAC3), + SND_PCI_QUIRK(0x1028, 0x0798, "Dell Inspiron 17 7000 Gaming", ALC256_FIXUP_DELL_INSPIRON_7559_SUBWOOFER), + SND_PCI_QUIRK(0x1028, 0x080c, "Dell WYSE", ALC225_FIXUP_DELL_WYSE_MIC_NO_PRESENCE), +- SND_PCI_QUIRK(0x1028, 0x082a, "Dell XPS 13 9360", ALC256_FIXUP_DELL_XPS_13_HEADPHONE_NOISE2), + SND_PCI_QUIRK(0x1028, 0x084b, "Dell", ALC274_FIXUP_DELL_AIO_LINEOUT_VERB), + SND_PCI_QUIRK(0x1028, 0x084e, "Dell", ALC274_FIXUP_DELL_AIO_LINEOUT_VERB), + SND_PCI_QUIRK(0x1028, 0x0871, "Dell Precision 3630", ALC255_FIXUP_DELL_HEADSET_MIC), +@@ -7536,7 +7503,6 @@ static const struct hda_model_fixup alc269_fixup_models[] = { + {.id = ALC298_FIXUP_DELL1_MIC_NO_PRESENCE, .name = "alc298-dell1"}, + {.id = ALC298_FIXUP_DELL_AIO_MIC_NO_PRESENCE, .name = "alc298-dell-aio"}, + {.id = ALC275_FIXUP_DELL_XPS, .name = "alc275-dell-xps"}, +- {.id = ALC256_FIXUP_DELL_XPS_13_HEADPHONE_NOISE, .name = "alc256-dell-xps13"}, + {.id = ALC293_FIXUP_LENOVO_SPK_NOISE, .name = "lenovo-spk-noise"}, + {.id = ALC233_FIXUP_LENOVO_LINE2_MIC_HOTKEY, .name = "lenovo-hotkey"}, + {.id = ALC255_FIXUP_DELL_SPK_NOISE, .name = "dell-spk-noise"}, +-- +2.16.4 + diff --git a/patches.suse/ALSA-hda-realtek-Set-principled-PC-Beep-configuratio.patch b/patches.suse/ALSA-hda-realtek-Set-principled-PC-Beep-configuratio.patch new file mode 100644 index 0000000..44e16f9 --- /dev/null +++ b/patches.suse/ALSA-hda-realtek-Set-principled-PC-Beep-configuratio.patch @@ -0,0 +1,96 @@ +From c44737449468a0bdc50e09ec75e530f208391561 Mon Sep 17 00:00:00 2001 +From: Thomas Hebb +Date: Mon, 30 Mar 2020 12:09:38 -0400 +Subject: [PATCH] ALSA: hda/realtek - Set principled PC Beep configuration for ALC256 +Git-commit: c44737449468a0bdc50e09ec75e530f208391561 +Patch-mainline: v5.7-rc1 +References: bsc#1051510 + +The Realtek PC Beep Hidden Register[1] is currently set by +patch_realtek.c in two different places: + +In alc_fill_eapd_coef(), it's set to the value 0x5757, corresponding to +non-beep input on 1Ah and no 1Ah loopback to either headphones or +speakers. (Although, curiously, the loopback amp is still enabled.) This +write was added fairly recently by commit e3743f431143 ("ALSA: +hda/realtek - Dell headphone has noise on unmute for ALC236") and is a +safe default. However, it happens in the wrong place: +alc_fill_eapd_coef() runs on module load and cold boot but not on S3 +resume, meaning the register loses its value after suspend. + +Conversely, in alc256_init(), the register is updated to unset bit 13 +(disable speaker loopback) and set bit 5 (set non-beep input on 1Ah). +Although this write does run on S3 resume, it's not quite enough to fix +up the register's default value of 0x3717. What's missing is a set of +bit 14 to disable headphone loopback. Without that, we end up with a +feedback loop where the headphone jack is being driven by amplified +samples of itself[2]. + +This change eliminates the update in alc256_init() and replaces it with +the 0x5757 write from alc_fill_eapd_coef(). Kailang says that 0x5757 is +supposed to be the codec's default value, so using it will make +debugging easier for Realtek. + +Affects the ALC255, ALC256, ALC257, ALC235, and ALC236 codecs. + +[1] Newly documented in Documentation/sound/hd-audio/realtek-pc-beep.rst + +[2] Setting the "Headphone Mic Boost" control from userspace changes +this feedback loop and has been a widely-shared workaround for headphone +noise on laptops like the Dell XPS 13 9350. This commit eliminates the +feedback loop and makes the workaround unnecessary. + +Fixes: e1e8c1fdce8b ("ALSA: hda/realtek - Dell headphone has noise on unmute for ALC236") +Cc: stable@vger.kernel.org +Signed-off-by: Thomas Hebb +Link: https://lore.kernel.org/r/bf22b417d1f2474b12011c2a39ed6cf8b06d3bf5.1585584498.git.tommyhebb@gmail.com +Signed-off-by: Takashi Iwai + +--- + sound/pci/hda/patch_realtek.c | 15 +++++++++------ + 1 file changed, 9 insertions(+), 6 deletions(-) + +diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c +index 0af33f00617a..425521d03dc3 100644 +--- a/sound/pci/hda/patch_realtek.c ++++ b/sound/pci/hda/patch_realtek.c +@@ -368,7 +368,9 @@ static void alc_fill_eapd_coef(struct hda_codec *codec) + case 0x10ec0215: + case 0x10ec0233: + case 0x10ec0235: ++ case 0x10ec0236: + case 0x10ec0255: ++ case 0x10ec0256: + case 0x10ec0257: + case 0x10ec0282: + case 0x10ec0283: +@@ -380,11 +382,6 @@ static void alc_fill_eapd_coef(struct hda_codec *codec) + case 0x10ec0300: + alc_update_coef_idx(codec, 0x10, 1<<9, 0); + break; +- case 0x10ec0236: +- case 0x10ec0256: +- alc_write_coef_idx(codec, 0x36, 0x5757); +- alc_update_coef_idx(codec, 0x10, 1<<9, 0); +- break; + case 0x10ec0275: + alc_update_coef_idx(codec, 0xe, 0, 1<<0); + break; +@@ -3371,7 +3368,13 @@ static void alc256_init(struct hda_codec *codec) + alc_update_coefex_idx(codec, 0x57, 0x04, 0x0007, 0x4); /* Hight power */ + alc_update_coefex_idx(codec, 0x53, 0x02, 0x8000, 1 << 15); /* Clear bit */ + alc_update_coefex_idx(codec, 0x53, 0x02, 0x8000, 0 << 15); +- alc_update_coef_idx(codec, 0x36, 1 << 13, 1 << 5); /* Switch pcbeep path to Line in path*/ ++ /* ++ * Expose headphone mic (or possibly Line In on some machines) instead ++ * of PC Beep on 1Ah, and disable 1Ah loopback for all outputs. See ++ * Documentation/sound/hd-audio/realtek-pc-beep.rst for details of ++ * this register. ++ */ ++ alc_write_coef_idx(codec, 0x36, 0x5757); + } + + static void alc256_shutup(struct hda_codec *codec) +-- +2.16.4 + diff --git a/patches.suse/ALSA-hda-realtek-a-fake-key-event-is-triggered-by-ru.patch b/patches.suse/ALSA-hda-realtek-a-fake-key-event-is-triggered-by-ru.patch new file mode 100644 index 0000000..799d031 --- /dev/null +++ b/patches.suse/ALSA-hda-realtek-a-fake-key-event-is-triggered-by-ru.patch @@ -0,0 +1,251 @@ +From 476c02e0b4fd9071d158f6a1a1dfea1d36ee0ffd Mon Sep 17 00:00:00 2001 +From: Hui Wang +Date: Sun, 29 Mar 2020 16:20:18 +0800 +Subject: [PATCH] ALSA: hda/realtek - a fake key event is triggered by running shutup +Git-commit: 476c02e0b4fd9071d158f6a1a1dfea1d36ee0ffd +Patch-mainline: v5.7-rc1 +References: bsc#1051510 + +On the Lenovo X1C7 machines, after we plug the headset, the rt_resume() +and rt_suspend() of the codec driver will be called periodically, the +driver can't stay in the rt_suspend state even users doen't use the +sound card. + +Through debugging, I found when running rt_suspend(), it will call +alc225_shutup(), in this function, it will change 3k pull down control +by alc_update_coef_idx(codec, 0x4a, 0, 3 << 10), this will trigger a +fake key event and that event will resume the codec, when codec +suspend agin, it will trigger the fake key event one more time, this +process will repeat. + +If disable the key event before changing the pull down control, it +will not trigger fake key event. It also needs to restore the pull +down control and re-enable the key event, otherwise the system can't +get key event when codec is in rt_suspend state. + +Also move some functions ahead of alc225_shutup(), this can save the +function declaration. + +Fixes: 76f7dec08fd6 (ALSA: hda/realtek - Add Headset Button supported for ThinkPad X1) +Cc: Kailang Yang +Cc: +Signed-off-by: Hui Wang +Link: https://lore.kernel.org/r/20200329082018.20486-1-hui.wang@canonical.com +Signed-off-by: Takashi Iwai + +--- + sound/pci/hda/patch_realtek.c | 170 ++++++++++++++++++++++++++---------------- + 1 file changed, 107 insertions(+), 63 deletions(-) + +diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c +index 1ad8c2e2d1af..0af33f00617a 100644 +--- a/sound/pci/hda/patch_realtek.c ++++ b/sound/pci/hda/patch_realtek.c +@@ -107,6 +107,7 @@ struct alc_spec { + unsigned int done_hp_init:1; + unsigned int no_shutup_pins:1; + unsigned int ultra_low_power:1; ++ unsigned int has_hs_key:1; + + /* for PLL fix */ + hda_nid_t pll_nid; +@@ -2982,6 +2983,107 @@ static int alc269_parse_auto_config(struct hda_codec *codec) + return alc_parse_auto_config(codec, alc269_ignore, ssids); + } + ++static const struct hda_jack_keymap alc_headset_btn_keymap[] = { ++ { SND_JACK_BTN_0, KEY_PLAYPAUSE }, ++ { SND_JACK_BTN_1, KEY_VOICECOMMAND }, ++ { SND_JACK_BTN_2, KEY_VOLUMEUP }, ++ { SND_JACK_BTN_3, KEY_VOLUMEDOWN }, ++ {} ++}; ++ ++static void alc_headset_btn_callback(struct hda_codec *codec, ++ struct hda_jack_callback *jack) ++{ ++ int report = 0; ++ ++ if (jack->unsol_res & (7 << 13)) ++ report |= SND_JACK_BTN_0; ++ ++ if (jack->unsol_res & (1 << 16 | 3 << 8)) ++ report |= SND_JACK_BTN_1; ++ ++ /* Volume up key */ ++ if (jack->unsol_res & (7 << 23)) ++ report |= SND_JACK_BTN_2; ++ ++ /* Volume down key */ ++ if (jack->unsol_res & (7 << 10)) ++ report |= SND_JACK_BTN_3; ++ ++ jack->jack->button_state = report; ++} ++ ++static void alc_disable_headset_jack_key(struct hda_codec *codec) ++{ ++ struct alc_spec *spec = codec->spec; ++ ++ if (!spec->has_hs_key) ++ return; ++ ++ switch (codec->core.vendor_id) { ++ case 0x10ec0215: ++ case 0x10ec0225: ++ case 0x10ec0285: ++ case 0x10ec0295: ++ case 0x10ec0289: ++ case 0x10ec0299: ++ alc_write_coef_idx(codec, 0x48, 0x0); ++ alc_update_coef_idx(codec, 0x49, 0x0045, 0x0); ++ alc_update_coef_idx(codec, 0x44, 0x0045 << 8, 0x0); ++ break; ++ case 0x10ec0236: ++ case 0x10ec0256: ++ alc_write_coef_idx(codec, 0x48, 0x0); ++ alc_update_coef_idx(codec, 0x49, 0x0045, 0x0); ++ break; ++ } ++} ++ ++static void alc_enable_headset_jack_key(struct hda_codec *codec) ++{ ++ struct alc_spec *spec = codec->spec; ++ ++ if (!spec->has_hs_key) ++ return; ++ ++ switch (codec->core.vendor_id) { ++ case 0x10ec0215: ++ case 0x10ec0225: ++ case 0x10ec0285: ++ case 0x10ec0295: ++ case 0x10ec0289: ++ case 0x10ec0299: ++ alc_write_coef_idx(codec, 0x48, 0xd011); ++ alc_update_coef_idx(codec, 0x49, 0x007f, 0x0045); ++ alc_update_coef_idx(codec, 0x44, 0x007f << 8, 0x0045 << 8); ++ break; ++ case 0x10ec0236: ++ case 0x10ec0256: ++ alc_write_coef_idx(codec, 0x48, 0xd011); ++ alc_update_coef_idx(codec, 0x49, 0x007f, 0x0045); ++ break; ++ } ++} ++ ++static void alc_fixup_headset_jack(struct hda_codec *codec, ++ const struct hda_fixup *fix, int action) ++{ ++ struct alc_spec *spec = codec->spec; ++ ++ switch (action) { ++ case HDA_FIXUP_ACT_PRE_PROBE: ++ spec->has_hs_key = 1; ++ snd_hda_jack_detect_enable_callback(codec, 0x55, ++ alc_headset_btn_callback); ++ snd_hda_jack_add_kctl(codec, 0x55, "Headset Jack", false, ++ SND_JACK_HEADSET, alc_headset_btn_keymap); ++ break; ++ case HDA_FIXUP_ACT_INIT: ++ alc_enable_headset_jack_key(codec); ++ break; ++ } ++} ++ + static void alc269vb_toggle_power_output(struct hda_codec *codec, int power_up) + { + alc_update_coef_idx(codec, 0x04, 1 << 11, power_up ? (1 << 11) : 0); +@@ -3372,6 +3474,8 @@ static void alc225_shutup(struct hda_codec *codec) + + if (!hp_pin) + hp_pin = 0x21; ++ ++ alc_disable_headset_jack_key(codec); + /* 3k pull low control for Headset jack. */ + alc_update_coef_idx(codec, 0x4a, 0, 3 << 10); + +@@ -3411,6 +3515,9 @@ static void alc225_shutup(struct hda_codec *codec) + alc_update_coef_idx(codec, 0x4a, 3<<4, 2<<4); + msleep(30); + } ++ ++ alc_update_coef_idx(codec, 0x4a, 3 << 10, 0); ++ alc_enable_headset_jack_key(codec); + } + + static void alc_default_init(struct hda_codec *codec) +@@ -5668,69 +5775,6 @@ static void alc285_fixup_invalidate_dacs(struct hda_codec *codec, + snd_hda_override_wcaps(codec, 0x03, 0); + } + +-static const struct hda_jack_keymap alc_headset_btn_keymap[] = { +- { SND_JACK_BTN_0, KEY_PLAYPAUSE }, +- { SND_JACK_BTN_1, KEY_VOICECOMMAND }, +- { SND_JACK_BTN_2, KEY_VOLUMEUP }, +- { SND_JACK_BTN_3, KEY_VOLUMEDOWN }, +- {} +-}; +- +-static void alc_headset_btn_callback(struct hda_codec *codec, +- struct hda_jack_callback *jack) +-{ +- int report = 0; +- +- if (jack->unsol_res & (7 << 13)) +- report |= SND_JACK_BTN_0; +- +- if (jack->unsol_res & (1 << 16 | 3 << 8)) +- report |= SND_JACK_BTN_1; +- +- /* Volume up key */ +- if (jack->unsol_res & (7 << 23)) +- report |= SND_JACK_BTN_2; +- +- /* Volume down key */ +- if (jack->unsol_res & (7 << 10)) +- report |= SND_JACK_BTN_3; +- +- jack->jack->button_state = report; +-} +- +-static void alc_fixup_headset_jack(struct hda_codec *codec, +- const struct hda_fixup *fix, int action) +-{ +- +- switch (action) { +- case HDA_FIXUP_ACT_PRE_PROBE: +- snd_hda_jack_detect_enable_callback(codec, 0x55, +- alc_headset_btn_callback); +- snd_hda_jack_add_kctl(codec, 0x55, "Headset Jack", false, +- SND_JACK_HEADSET, alc_headset_btn_keymap); +- break; +- case HDA_FIXUP_ACT_INIT: +- switch (codec->core.vendor_id) { +- case 0x10ec0215: +- case 0x10ec0225: +- case 0x10ec0285: +- case 0x10ec0295: +- case 0x10ec0289: +- case 0x10ec0299: +- alc_write_coef_idx(codec, 0x48, 0xd011); +- alc_update_coef_idx(codec, 0x49, 0x007f, 0x0045); +- alc_update_coef_idx(codec, 0x44, 0x007f << 8, 0x0045 << 8); +- break; +- case 0x10ec0236: +- case 0x10ec0256: +- alc_write_coef_idx(codec, 0x48, 0xd011); +- alc_update_coef_idx(codec, 0x49, 0x007f, 0x0045); +- break; +- } +- break; +- } +-} +- + static void alc295_fixup_chromebook(struct hda_codec *codec, + const struct hda_fixup *fix, int action) + { +-- +2.16.4 + diff --git a/patches.suse/ALSA-hda-remove-redundant-assignment-to-variable-tim.patch b/patches.suse/ALSA-hda-remove-redundant-assignment-to-variable-tim.patch new file mode 100644 index 0000000..628f509 --- /dev/null +++ b/patches.suse/ALSA-hda-remove-redundant-assignment-to-variable-tim.patch @@ -0,0 +1,37 @@ +From 4dca80b4df0a7aa4f8865b0bd6f48962c5994b1e Mon Sep 17 00:00:00 2001 +From: Colin Ian King +Date: Sat, 8 Feb 2020 22:27:56 +0000 +Subject: [PATCH] ALSA: hda: remove redundant assignment to variable timeout +Git-commit: 4dca80b4df0a7aa4f8865b0bd6f48962c5994b1e +Patch-mainline: v5.7-rc1 +References: bsc#1051510 + +Variable timeout is being assigned with the value 200 that is never +read, it is assigned a new value in a following do-loop. The assignment +is redundant and can be removed. + +Addresses-coverity: ("Unused value") +Signed-off-by: Colin Ian King +Link: https://lore.kernel.org/r/20200208222756.37707-1-colin.king@canonical.com +Signed-off-by: Takashi Iwai + +--- + sound/pci/hda/hda_controller.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/sound/pci/hda/hda_controller.c b/sound/pci/hda/hda_controller.c +index 2609e391ce54..9765652a73d7 100644 +--- a/sound/pci/hda/hda_controller.c ++++ b/sound/pci/hda/hda_controller.c +@@ -373,7 +373,7 @@ static int azx_get_sync_time(ktime_t *device, + u32 wallclk_ctr, wallclk_cycles; + bool direction; + u32 dma_select; +- u32 timeout = 200; ++ u32 timeout; + u32 retry_count = 0; + + runtime = substream->runtime; +-- +2.16.4 + diff --git a/patches.suse/ALSA-hda_codec-Replace-zero-length-array-with-flexib.patch b/patches.suse/ALSA-hda_codec-Replace-zero-length-array-with-flexib.patch new file mode 100644 index 0000000..3b4582e --- /dev/null +++ b/patches.suse/ALSA-hda_codec-Replace-zero-length-array-with-flexib.patch @@ -0,0 +1,53 @@ +From bb80b96422b443ddcb6dbb39261ea3e02a13661d Mon Sep 17 00:00:00 2001 +From: "Gustavo A. R. Silva" +Date: Tue, 11 Feb 2020 14:07:39 -0600 +Subject: [PATCH] ALSA: hda_codec: Replace zero-length array with flexible-array member +Git-commit: bb80b96422b443ddcb6dbb39261ea3e02a13661d +Patch-mainline: v5.7-rc1 +References: bsc#1051510 + +The current codebase makes use of the zero-length array language +extension to the C90 standard, but the preferred mechanism to declare +variable-length types such as these ones is a flexible array member[1][2], +introduced in C99: + +struct foo { + int stuff; + struct boo array[]; +}; + +By making use of the mechanism above, we will get a compiler warning +in case the flexible array does not occur last in the structure, which +will help us prevent some kind of undefined behavior bugs from being +inadvertenly introduced[3] to the codebase from now on. + +This issue was found with the help of Coccinelle. + +[1] https://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html +[2] https://github.com/KSPP/linux/issues/21 +[3] commit 76497732932f ("cxgb3/l2t: Fix undefined behaviour") + +Signed-off-by: Gustavo A. R. Silva +Link: https://lore.kernel.org/r/20200211200739.GA12948@embeddedor +Signed-off-by: Takashi Iwai + +--- + sound/pci/hda/hda_codec.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c +index 5dc42f932739..97a03685dd8b 100644 +--- a/sound/pci/hda/hda_codec.c ++++ b/sound/pci/hda/hda_codec.c +@@ -88,7 +88,7 @@ struct hda_conn_list { + struct list_head list; + int len; + hda_nid_t nid; +- hda_nid_t conns[0]; ++ hda_nid_t conns[]; + }; + + /* look up the cached results */ +-- +2.16.4 + diff --git a/patches.suse/ALSA-hdsp-remove-redundant-assignment-to-variable-er.patch b/patches.suse/ALSA-hdsp-remove-redundant-assignment-to-variable-er.patch new file mode 100644 index 0000000..88dfe21 --- /dev/null +++ b/patches.suse/ALSA-hdsp-remove-redundant-assignment-to-variable-er.patch @@ -0,0 +1,38 @@ +From 0cc629722221701a1b1030477c44dfbaca6c110d Mon Sep 17 00:00:00 2001 +From: Colin Ian King +Date: Sat, 8 Feb 2020 22:20:06 +0000 +Subject: [PATCH] ALSA: hdsp: remove redundant assignment to variable err +Git-commit: 0cc629722221701a1b1030477c44dfbaca6c110d +Patch-mainline: v5.7-rc1 +References: bsc#1051510 + +Variable err is being assigned with a value that is never read, it is +assigned a new value in the next statement. The assignment is redundant +and can be removed. + +Addresses-coverity: ("Unused value") +Signed-off-by: Colin Ian King +Link: https://lore.kernel.org/r/20200208222006.37376-1-colin.king@canonical.com +Signed-off-by: Takashi Iwai + +--- + sound/pci/rme9652/hdsp.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/sound/pci/rme9652/hdsp.c b/sound/pci/rme9652/hdsp.c +index cc06f0a1a7e4..227aece17e39 100644 +--- a/sound/pci/rme9652/hdsp.c ++++ b/sound/pci/rme9652/hdsp.c +@@ -3353,7 +3353,8 @@ snd_hdsp_proc_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer) + return; + } + } else { +- int err = -EINVAL; ++ int err; ++ + err = hdsp_request_fw_loader(hdsp); + if (err < 0) { + snd_iprintf(buffer, +-- +2.16.4 + diff --git a/patches.suse/ALSA-info-remove-redundant-assignment-to-variable-c.patch b/patches.suse/ALSA-info-remove-redundant-assignment-to-variable-c.patch new file mode 100644 index 0000000..2ef8aff --- /dev/null +++ b/patches.suse/ALSA-info-remove-redundant-assignment-to-variable-c.patch @@ -0,0 +1,37 @@ +From 0e023687ca552147a76540377be4c642b1313d53 Mon Sep 17 00:00:00 2001 +From: Colin Ian King +Date: Sat, 8 Feb 2020 22:42:06 +0000 +Subject: [PATCH] ALSA: info: remove redundant assignment to variable c +Git-commit: 0e023687ca552147a76540377be4c642b1313d53 +Patch-mainline: v5.7-rc1 +References: bsc#1051510 + +Variable c is being assigned with the value -1 that is never read, +it is assigned a new value in a following while-loop. The assignment +is redundant and can be removed. + +Addresses-coverity: ("Unused value") +Signed-off-by: Colin Ian King +Link: https://lore.kernel.org/r/20200208224206.38540-1-colin.king@canonical.com +Signed-off-by: Takashi Iwai + +--- + sound/core/info.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/sound/core/info.c b/sound/core/info.c +index ca87ae4c30ba..8c6bc5241df5 100644 +--- a/sound/core/info.c ++++ b/sound/core/info.c +@@ -604,7 +604,7 @@ int snd_info_card_free(struct snd_card *card) + */ + int snd_info_get_line(struct snd_info_buffer *buffer, char *line, int len) + { +- int c = -1; ++ int c; + + if (snd_BUG_ON(!buffer || !buffer->buffer)) + return 1; +-- +2.16.4 + diff --git a/patches.suse/ALSA-korg1212-fix-if-statement-empty-body-warnings.patch b/patches.suse/ALSA-korg1212-fix-if-statement-empty-body-warnings.patch new file mode 100644 index 0000000..717f100 --- /dev/null +++ b/patches.suse/ALSA-korg1212-fix-if-statement-empty-body-warnings.patch @@ -0,0 +1,51 @@ +From 66db29588dd6c55591b0f93dc8044a018d78d501 Mon Sep 17 00:00:00 2001 +From: Randy Dunlap +Date: Tue, 25 Feb 2020 21:32:49 -0800 +Subject: [PATCH] ALSA: korg1212: fix if-statement empty body warnings +Mime-version: 1.0 +Content-type: text/plain; charset=UTF-8 +Content-transfer-encoding: 8bit +Git-commit: 66db29588dd6c55591b0f93dc8044a018d78d501 +Patch-mainline: v5.7-rc1 +References: bsc#1051510 + +Fix gcc warnings when -Wextra is used by using an empty do-while +block instead of . Fixes these build warnings: + +../sound/pci/korg1212/korg1212.c:674:44: warning: suggest braces around empty body in an ‘if’ statement [-Wempty-body] +../sound/pci/korg1212/korg1212.c:708:43: warning: suggest braces around empty body in an ‘if’ statement [-Wempty-body] +../sound/pci/korg1212/korg1212.c:730:43: warning: suggest braces around empty body in an ‘if’ statement [-Wempty-body] +../sound/pci/korg1212/korg1212.c:853:43: warning: suggest braces around empty body in an ‘if’ statement [-Wempty-body] +../sound/pci/korg1212/korg1212.c:1013:44: warning: suggest braces around empty body in an ‘if’ statement [-Wempty-body] +../sound/pci/korg1212/korg1212.c:1035:43: warning: suggest braces around empty body in an ‘if’ statement [-Wempty-body] +../sound/pci/korg1212/korg1212.c:1052:43: warning: suggest braces around empty body in an ‘if’ statement [-Wempty-body] +../sound/pci/korg1212/korg1212.c:1066:43: warning: suggest braces around empty body in an ‘if’ statement [-Wempty-body] +../sound/pci/korg1212/korg1212.c:1087:43: warning: suggest braces around empty body in an ‘if’ statement [-Wempty-body] +../sound/pci/korg1212/korg1212.c:1094:43: warning: suggest braces around empty body in an ‘if’ statement [-Wempty-body] +../sound/pci/korg1212/korg1212.c:1208:43: warning: suggest braces around empty body in an ‘if’ statement [-Wempty-body] +../sound/pci/korg1212/korg1212.c:2360:102: warning: suggest braces around empty body in an ‘if’ statement [-Wempty-body] + +Signed-off-by: Randy Dunlap +Link: https://lore.kernel.org/r/91fb1e97-a773-5790-3f65-8198403341e1@infradead.org +Signed-off-by: Takashi Iwai + +--- + sound/pci/korg1212/korg1212.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/sound/pci/korg1212/korg1212.c b/sound/pci/korg1212/korg1212.c +index 21ab9cc50c71..65a887b217ee 100644 +--- a/sound/pci/korg1212/korg1212.c ++++ b/sound/pci/korg1212/korg1212.c +@@ -30,7 +30,7 @@ + #if K1212_DEBUG_LEVEL > 0 + #define K1212_DEBUG_PRINTK(fmt,args...) printk(KERN_DEBUG fmt,##args) + #else +-#define K1212_DEBUG_PRINTK(fmt,...) ++#define K1212_DEBUG_PRINTK(fmt,...) do { } while (0) + #endif + #if K1212_DEBUG_LEVEL > 1 + #define K1212_DEBUG_PRINTK_VERBOSE(fmt,args...) printk(KERN_DEBUG fmt,##args) +-- +2.16.4 + diff --git a/patches.suse/ALSA-line6-Fix-endless-MIDI-read-loop.patch b/patches.suse/ALSA-line6-Fix-endless-MIDI-read-loop.patch new file mode 100644 index 0000000..b2c646e --- /dev/null +++ b/patches.suse/ALSA-line6-Fix-endless-MIDI-read-loop.patch @@ -0,0 +1,60 @@ +From d683469b3c93d7e2afd39e6e1970f24700eb7a68 Mon Sep 17 00:00:00 2001 +From: Takashi Iwai +Date: Mon, 9 Mar 2020 10:59:22 +0100 +Subject: [PATCH] ALSA: line6: Fix endless MIDI read loop +Git-commit: d683469b3c93d7e2afd39e6e1970f24700eb7a68 +Patch-mainline: v5.6-rc7 +References: git-fixes + +The MIDI input event parser of the LINE6 driver may enter into an +endless loop when the unexpected data sequence is given, as it tries +to continue the secondary bytes without termination. Also, when the +input data is too short, the parser returns a negative error, while +the caller doesn't handle it properly. This would lead to the +unexpected behavior as well. + +This patch addresses those issues by checking the return value +correctly and handling the one-byte event in the parser properly. + +The bug was reported by syzkaller. + +Reported-by: syzbot+cce32521ee0a824c21f7@syzkaller.appspotmail.com +Cc: +Link: https://lore.kernel.org/r/000000000000033087059f8f8fa3@google.com +Link: https://lore.kernel.org/r/20200309095922.30269-1-tiwai@suse.de +Signed-off-by: Takashi Iwai + +--- + sound/usb/line6/driver.c | 2 +- + sound/usb/line6/midibuf.c | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/sound/usb/line6/driver.c b/sound/usb/line6/driver.c +index b5a3f754a4f1..4f096685ed65 100644 +--- a/sound/usb/line6/driver.c ++++ b/sound/usb/line6/driver.c +@@ -305,7 +305,7 @@ static void line6_data_received(struct urb *urb) + line6_midibuf_read(mb, line6->buffer_message, + LINE6_MIDI_MESSAGE_MAXLEN); + +- if (done == 0) ++ if (done <= 0) + break; + + line6->message_length = done; +diff --git a/sound/usb/line6/midibuf.c b/sound/usb/line6/midibuf.c +index 8d6eefa0d936..6a70463f82c4 100644 +--- a/sound/usb/line6/midibuf.c ++++ b/sound/usb/line6/midibuf.c +@@ -159,7 +159,7 @@ int line6_midibuf_read(struct midi_buffer *this, unsigned char *data, + int midi_length_prev = + midibuf_message_length(this->command_prev); + +- if (midi_length_prev > 0) { ++ if (midi_length_prev > 1) { + midi_length = midi_length_prev - 1; + repeat = 1; + } else +-- +2.16.4 + diff --git a/patches.suse/ALSA-pcm-Fix-superfluous-snprintf-usage.patch b/patches.suse/ALSA-pcm-Fix-superfluous-snprintf-usage.patch new file mode 100644 index 0000000..7b3625e --- /dev/null +++ b/patches.suse/ALSA-pcm-Fix-superfluous-snprintf-usage.patch @@ -0,0 +1,31 @@ +From 296a37fd029dd8a911396e3c28e0bbd5a2720a5d Mon Sep 17 00:00:00 2001 +From: Takashi Iwai +Date: Fri, 13 Mar 2020 14:02:23 +0100 +Subject: [PATCH] ALSA: pcm: Fix superfluous snprintf() usage +Git-commit: 296a37fd029dd8a911396e3c28e0bbd5a2720a5d +Patch-mainline: v5.7-rc1 +References: bsc#1051510 + +show_pcm_class() returns obviously a short string that can't overflow +PAGE_SIZE. And even if it were to overflow, using snprintf() there is +just wrong, as it doesn't return the correct size. +So simplify with sprintf() instead. + +Link: https://lore.kernel.org/r/20200313130223.8908-1-tiwai@suse.de +Signed-off-by: Takashi Iwai + +--- + sound/core/pcm.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/sound/core/pcm.c ++++ b/sound/core/pcm.c +@@ -1081,7 +1081,7 @@ static ssize_t show_pcm_class(struct dev + str = "none"; + else + str = strs[pcm->dev_class]; +- return snprintf(buf, PAGE_SIZE, "%s\n", str); ++ return sprintf(buf, "%s\n", str); + } + + static DEVICE_ATTR(pcm_class, S_IRUGO, show_pcm_class, NULL); diff --git a/patches.suse/ALSA-pcm-Use-a-macro-for-parameter-masks-to-reduce-t.patch b/patches.suse/ALSA-pcm-Use-a-macro-for-parameter-masks-to-reduce-t.patch new file mode 100644 index 0000000..cac45ae --- /dev/null +++ b/patches.suse/ALSA-pcm-Use-a-macro-for-parameter-masks-to-reduce-t.patch @@ -0,0 +1,139 @@ +From f9b0c053a29fdc0ad58e816554216523b29930f8 Mon Sep 17 00:00:00 2001 +From: Takashi Iwai +Date: Thu, 6 Feb 2020 17:39:43 +0100 +Subject: [PATCH] ALSA: pcm: Use a macro for parameter masks to reduce the needed cast +Git-commit: f9b0c053a29fdc0ad58e816554216523b29930f8 +Patch-mainline: v5.7-rc1 +References: bsc#1051510 + +The parameter bit mask needs often explicit cast with __force, +e.g. for the PCM subformat type. Instead of adding __force at each +place, which is error prone, this patch introduces a new macro and +replaces the all bit shift with it. This fixes the sparse warnings +like the following: + sound/core/pcm_native.c:2508:30: warning: restricted snd_pcm_access_t degrades to integer + +No functional changes, just sparse warning fixes. + +Link: https://lore.kernel.org/r/20200206163945.6797-7-tiwai@suse.de +Signed-off-by: Takashi Iwai + +--- + sound/core/pcm_native.c | 32 ++++++++++++++++++-------------- + 1 file changed, 18 insertions(+), 14 deletions(-) + +diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c +index 900f9cfd4646..559633d4702d 100644 +--- a/sound/core/pcm_native.c ++++ b/sound/core/pcm_native.c +@@ -228,6 +228,9 @@ int snd_pcm_info_user(struct snd_pcm_substream *substream, + return err; + } + ++/* macro for simplified cast */ ++#define PARAM_MASK_BIT(b) (1U << (__force int)(b)) ++ + static bool hw_support_mmap(struct snd_pcm_substream *substream) + { + if (!(substream->runtime->hw.info & SNDRV_PCM_INFO_MMAP)) +@@ -257,7 +260,7 @@ static int constrain_mask_params(struct snd_pcm_substream *substream, + return -EINVAL; + + /* This parameter is not requested to change by a caller. */ +- if (!(params->rmask & (1 << k))) ++ if (!(params->rmask & PARAM_MASK_BIT(k))) + continue; + + if (trace_hw_mask_param_enabled()) +@@ -271,7 +274,7 @@ static int constrain_mask_params(struct snd_pcm_substream *substream, + + /* Set corresponding flag so that the caller gets it. */ + trace_hw_mask_param(substream, k, 0, &old_mask, m); +- params->cmask |= 1 << k; ++ params->cmask |= PARAM_MASK_BIT(k); + } + + return 0; +@@ -293,7 +296,7 @@ static int constrain_interval_params(struct snd_pcm_substream *substream, + return -EINVAL; + + /* This parameter is not requested to change by a caller. */ +- if (!(params->rmask & (1 << k))) ++ if (!(params->rmask & PARAM_MASK_BIT(k))) + continue; + + if (trace_hw_interval_param_enabled()) +@@ -307,7 +310,7 @@ static int constrain_interval_params(struct snd_pcm_substream *substream, + + /* Set corresponding flag so that the caller gets it. */ + trace_hw_interval_param(substream, k, 0, &old_interval, i); +- params->cmask |= 1 << k; ++ params->cmask |= PARAM_MASK_BIT(k); + } + + return 0; +@@ -349,7 +352,7 @@ static int constrain_params_by_rules(struct snd_pcm_substream *substream, + * have 0 so that the parameters are never changed anymore. + */ + for (k = 0; k <= SNDRV_PCM_HW_PARAM_LAST_INTERVAL; k++) +- vstamps[k] = (params->rmask & (1 << k)) ? 1 : 0; ++ vstamps[k] = (params->rmask & PARAM_MASK_BIT(k)) ? 1 : 0; + + /* Due to the above design, actual sequence number starts at 2. */ + stamp = 2; +@@ -417,7 +420,7 @@ static int constrain_params_by_rules(struct snd_pcm_substream *substream, + hw_param_interval(params, r->var)); + } + +- params->cmask |= (1 << r->var); ++ params->cmask |= PARAM_MASK_BIT(r->var); + vstamps[r->var] = stamp; + again = true; + } +@@ -486,9 +489,9 @@ int snd_pcm_hw_refine(struct snd_pcm_substream *substream, + + params->info = 0; + params->fifo_size = 0; +- if (params->rmask & (1 << SNDRV_PCM_HW_PARAM_SAMPLE_BITS)) ++ if (params->rmask & PARAM_MASK_BIT(SNDRV_PCM_HW_PARAM_SAMPLE_BITS)) + params->msbits = 0; +- if (params->rmask & (1 << SNDRV_PCM_HW_PARAM_RATE)) { ++ if (params->rmask & PARAM_MASK_BIT(SNDRV_PCM_HW_PARAM_RATE)) { + params->rate_num = 0; + params->rate_den = 0; + } +@@ -2506,16 +2509,16 @@ static int snd_pcm_hw_constraints_complete(struct snd_pcm_substream *substream) + unsigned int mask = 0; + + if (hw->info & SNDRV_PCM_INFO_INTERLEAVED) +- mask |= 1 << SNDRV_PCM_ACCESS_RW_INTERLEAVED; ++ mask |= PARAM_MASK_BIT(SNDRV_PCM_ACCESS_RW_INTERLEAVED); + if (hw->info & SNDRV_PCM_INFO_NONINTERLEAVED) +- mask |= 1 << SNDRV_PCM_ACCESS_RW_NONINTERLEAVED; ++ mask |= PARAM_MASK_BIT(SNDRV_PCM_ACCESS_RW_NONINTERLEAVED); + if (hw_support_mmap(substream)) { + if (hw->info & SNDRV_PCM_INFO_INTERLEAVED) +- mask |= 1 << SNDRV_PCM_ACCESS_MMAP_INTERLEAVED; ++ mask |= PARAM_MASK_BIT(SNDRV_PCM_ACCESS_MMAP_INTERLEAVED); + if (hw->info & SNDRV_PCM_INFO_NONINTERLEAVED) +- mask |= 1 << SNDRV_PCM_ACCESS_MMAP_NONINTERLEAVED; ++ mask |= PARAM_MASK_BIT(SNDRV_PCM_ACCESS_MMAP_NONINTERLEAVED); + if (hw->info & SNDRV_PCM_INFO_COMPLEX) +- mask |= 1 << SNDRV_PCM_ACCESS_MMAP_COMPLEX; ++ mask |= PARAM_MASK_BIT(SNDRV_PCM_ACCESS_MMAP_COMPLEX); + } + err = snd_pcm_hw_constraint_mask(runtime, SNDRV_PCM_HW_PARAM_ACCESS, mask); + if (err < 0) +@@ -2525,7 +2528,8 @@ static int snd_pcm_hw_constraints_complete(struct snd_pcm_substream *substream) + if (err < 0) + return err; + +- err = snd_pcm_hw_constraint_mask(runtime, SNDRV_PCM_HW_PARAM_SUBFORMAT, 1 << SNDRV_PCM_SUBFORMAT_STD); ++ err = snd_pcm_hw_constraint_mask(runtime, SNDRV_PCM_HW_PARAM_SUBFORMAT, ++ PARAM_MASK_BIT(SNDRV_PCM_SUBFORMAT_STD)); + if (err < 0) + return err; + +-- +2.16.4 + diff --git a/patches.suse/ALSA-pcm-oss-Avoid-plugin-buffer-overflow.patch b/patches.suse/ALSA-pcm-oss-Avoid-plugin-buffer-overflow.patch new file mode 100644 index 0000000..e7359e4 --- /dev/null +++ b/patches.suse/ALSA-pcm-oss-Avoid-plugin-buffer-overflow.patch @@ -0,0 +1,73 @@ +From f2ecf903ef06eb1bbbfa969db9889643d487e73a Mon Sep 17 00:00:00 2001 +From: Takashi Iwai +Date: Mon, 9 Mar 2020 09:21:48 +0100 +Subject: [PATCH] ALSA: pcm: oss: Avoid plugin buffer overflow +Git-commit: f2ecf903ef06eb1bbbfa969db9889643d487e73a +Patch-mainline: v5.6-rc7 +References: git-fixes + +Each OSS PCM plugins allocate its internal buffer per pre-calculation +of the max buffer size through the chain of plugins (calling +src_frames and dst_frames callbacks). This works for most plugins, +but the rate plugin might behave incorrectly. The calculation in the +rate plugin involves with the fractional position, i.e. it may vary +depending on the input position. Since the buffer size +pre-calculation is always done with the offset zero, it may return a +shorter size than it might be; this may result in the out-of-bound +access as spotted by fuzzer. + +This patch addresses those possible buffer overflow accesses by simply +setting the upper limit per the given buffer size for each plugin +before src_frames() and after dst_frames() calls. + +Reported-by: syzbot+e1fe9f44fb8ecf4fb5dd@syzkaller.appspotmail.com +Cc: +Link: https://lore.kernel.org/r/000000000000b25ea005a02bcf21@google.com +Link: https://lore.kernel.org/r/20200309082148.19855-1-tiwai@suse.de +Signed-off-by: Takashi Iwai + +--- + sound/core/oss/pcm_plugin.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/sound/core/oss/pcm_plugin.c b/sound/core/oss/pcm_plugin.c +index 240e4702c098..c9401832967c 100644 +--- a/sound/core/oss/pcm_plugin.c ++++ b/sound/core/oss/pcm_plugin.c +@@ -209,6 +209,8 @@ snd_pcm_sframes_t snd_pcm_plug_client_size(struct snd_pcm_substream *plug, snd_p + if (stream == SNDRV_PCM_STREAM_PLAYBACK) { + plugin = snd_pcm_plug_last(plug); + while (plugin && drv_frames > 0) { ++ if (drv_frames > plugin->buf_frames) ++ drv_frames = plugin->buf_frames; + plugin_prev = plugin->prev; + if (plugin->src_frames) + drv_frames = plugin->src_frames(plugin, drv_frames); +@@ -220,6 +222,8 @@ snd_pcm_sframes_t snd_pcm_plug_client_size(struct snd_pcm_substream *plug, snd_p + plugin_next = plugin->next; + if (plugin->dst_frames) + drv_frames = plugin->dst_frames(plugin, drv_frames); ++ if (drv_frames > plugin->buf_frames) ++ drv_frames = plugin->buf_frames; + plugin = plugin_next; + } + } else +@@ -248,11 +252,15 @@ snd_pcm_sframes_t snd_pcm_plug_slave_size(struct snd_pcm_substream *plug, snd_pc + if (frames < 0) + return frames; + } ++ if (frames > plugin->buf_frames) ++ frames = plugin->buf_frames; + plugin = plugin_next; + } + } else if (stream == SNDRV_PCM_STREAM_CAPTURE) { + plugin = snd_pcm_plug_last(plug); + while (plugin) { ++ if (frames > plugin->buf_frames) ++ frames = plugin->buf_frames; + plugin_prev = plugin->prev; + if (plugin->src_frames) { + frames = plugin->src_frames(plugin, frames); +-- +2.16.4 + diff --git a/patches.suse/ALSA-pcm-oss-Remove-WARNING-from-snd_pcm_plug_alloc-.patch b/patches.suse/ALSA-pcm-oss-Remove-WARNING-from-snd_pcm_plug_alloc-.patch new file mode 100644 index 0000000..ad52cf1 --- /dev/null +++ b/patches.suse/ALSA-pcm-oss-Remove-WARNING-from-snd_pcm_plug_alloc-.patch @@ -0,0 +1,49 @@ +From 5461e0530c222129dfc941058be114b5cbc00837 Mon Sep 17 00:00:00 2001 +From: Takashi Iwai +Date: Thu, 12 Mar 2020 16:57:30 +0100 +Subject: [PATCH] ALSA: pcm: oss: Remove WARNING from snd_pcm_plug_alloc() checks +Git-commit: 5461e0530c222129dfc941058be114b5cbc00837 +Patch-mainline: v5.6-rc7 +References: git-fixes + +The return value checks in snd_pcm_plug_alloc() are covered with +snd_BUG_ON() macro that may trigger a kernel WARNING depending on the +kconfig. But since the error condition can be triggered by a weird +user space parameter passed to OSS layer, we shouldn't give the kernel +stack trace just for that. As it's a normal error condition, let's +remove snd_BUG_ON() macro usage there. + +Reported-by: syzbot+2a59ee7a9831b264f45e@syzkaller.appspotmail.com +Cc: +Link: https://lore.kernel.org/r/20200312155730.7520-1-tiwai@suse.de +Signed-off-by: Takashi Iwai + +--- + sound/core/oss/pcm_plugin.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/sound/core/oss/pcm_plugin.c b/sound/core/oss/pcm_plugin.c +index c9401832967c..752d078908e9 100644 +--- a/sound/core/oss/pcm_plugin.c ++++ b/sound/core/oss/pcm_plugin.c +@@ -111,7 +111,7 @@ int snd_pcm_plug_alloc(struct snd_pcm_substream *plug, snd_pcm_uframes_t frames) + while (plugin->next) { + if (plugin->dst_frames) + frames = plugin->dst_frames(plugin, frames); +- if (snd_BUG_ON((snd_pcm_sframes_t)frames <= 0)) ++ if ((snd_pcm_sframes_t)frames <= 0) + return -ENXIO; + plugin = plugin->next; + err = snd_pcm_plugin_alloc(plugin, frames); +@@ -123,7 +123,7 @@ int snd_pcm_plug_alloc(struct snd_pcm_substream *plug, snd_pcm_uframes_t frames) + while (plugin->prev) { + if (plugin->src_frames) + frames = plugin->src_frames(plugin, frames); +- if (snd_BUG_ON((snd_pcm_sframes_t)frames <= 0)) ++ if ((snd_pcm_sframes_t)frames <= 0) + return -ENXIO; + plugin = plugin->prev; + err = snd_pcm_plugin_alloc(plugin, frames); +-- +2.16.4 + diff --git a/patches.suse/ALSA-pcm-oss-Unlock-mutex-temporarily-for-sleeping-a.patch b/patches.suse/ALSA-pcm-oss-Unlock-mutex-temporarily-for-sleeping-a.patch new file mode 100644 index 0000000..96a05b1 --- /dev/null +++ b/patches.suse/ALSA-pcm-oss-Unlock-mutex-temporarily-for-sleeping-a.patch @@ -0,0 +1,60 @@ +From 146f66975bafbcfab349901c9f9c9f521ac96cbb Mon Sep 17 00:00:00 2001 +From: Takashi Iwai +Date: Fri, 14 Feb 2020 18:16:43 +0100 +Subject: [PATCH] ALSA: pcm: oss: Unlock mutex temporarily for sleeping at read/write +Git-commit: 146f66975bafbcfab349901c9f9c9f521ac96cbb +Patch-mainline: v5.7-rc1 +References: bsc#1051510 + +ALSA PCM OSS layer calls the generic __snd_pcm_lib_xfer() helper for +the actual transfer of the audio data. The xfer helper may sleep long +for waiting for the enough space becoming empty for read/write, and +it does unlock/relock for the substream lock. This works fine, so +far, but a slight problem specific to OSS layer is that OSS layer +wraps yet more mutex (runtime->oss.params_lock) over +__snd_pcm_lib_xfer() call; so this mutex is still locked during a +possible long sleep, and it prevents the whole ioctl and other actions +applied to the given stream. + +This patch adds the temporarily unlock and relock of the mutex around +__snd_pcm_lib_xfer() call in the OSS layer to be more friendly to the +concurrent accesses. The long mutex protection itself shouldn't be a +real issue for the normal systems, and its influence appears only on +strange things like fuzzers. + +Link: https://lore.kernel.org/r/20200214171643.26212-1-tiwai@suse.de +Signed-off-by: Takashi Iwai + +--- + sound/core/oss/pcm_oss.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c +index 707eb2a9d50c..930def8201f4 100644 +--- a/sound/core/oss/pcm_oss.c ++++ b/sound/core/oss/pcm_oss.c +@@ -1217,8 +1217,10 @@ snd_pcm_sframes_t snd_pcm_oss_write3(struct snd_pcm_substream *substream, const + if (ret < 0) + break; + } ++ mutex_unlock(&runtime->oss.params_lock); + ret = __snd_pcm_lib_xfer(substream, (void *)ptr, true, + frames, in_kernel); ++ mutex_lock(&runtime->oss.params_lock); + if (ret != -EPIPE && ret != -ESTRPIPE) + break; + /* test, if we can't store new data, because the stream */ +@@ -1254,8 +1256,10 @@ snd_pcm_sframes_t snd_pcm_oss_read3(struct snd_pcm_substream *substream, char *p + ret = snd_pcm_oss_capture_position_fixup(substream, &delay); + if (ret < 0) + break; ++ mutex_unlock(&runtime->oss.params_lock); + ret = __snd_pcm_lib_xfer(substream, (void *)ptr, true, + frames, in_kernel); ++ mutex_lock(&runtime->oss.params_lock); + if (ret == -EPIPE) { + if (runtime->status->state == SNDRV_PCM_STATE_DRAINING) { + ret = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DROP, NULL); +-- +2.16.4 + diff --git a/patches.suse/ALSA-pcm.h-add-for_each_pcm_streams.patch b/patches.suse/ALSA-pcm.h-add-for_each_pcm_streams.patch new file mode 100644 index 0000000..af77e96 --- /dev/null +++ b/patches.suse/ALSA-pcm.h-add-for_each_pcm_streams.patch @@ -0,0 +1,42 @@ +From 3193abd26b515ccac65e1c323533cb7f53d06176 Mon Sep 17 00:00:00 2001 +From: Kuninori Morimoto +Date: Mon, 17 Feb 2020 17:28:19 +0900 +Subject: [PATCH] ALSA: pcm.h: add for_each_pcm_streams() +Git-commit: 3193abd26b515ccac65e1c323533cb7f53d06176 +Patch-mainline: v5.7-rc1 +References: bsc#1051510 + +ALSA code has SNDRV_PCM_STREAM_PLAYBACK/CAPTURE everywhere. +Having for_each_xxxx macro is useful. +This patch adds for_each_pcm_streams() for it. + +Signed-off-by: Kuninori Morimoto +Reviewed-by: Ranjani Sridharan +Reviewed-by: Pierre-Louis Bossart +Acked-by: Takashi Iwai +Link: https://lore.kernel.org/r/874kvpbotq.wl-kuninori.morimoto.gx@renesas.com +Signed-off-by: Mark Brown + +--- + include/sound/pcm.h | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/include/sound/pcm.h b/include/sound/pcm.h +index f657ff08f317..2628246b76fa 100644 +--- a/include/sound/pcm.h ++++ b/include/sound/pcm.h +@@ -644,6 +644,11 @@ void snd_pcm_stream_unlock_irqrestore(struct snd_pcm_substream *substream, + #define snd_pcm_group_for_each_entry(s, substream) \ + list_for_each_entry(s, &substream->group->substreams, link_list) + ++#define for_each_pcm_streams(stream) \ ++ for (stream = SNDRV_PCM_STREAM_PLAYBACK; \ ++ stream <= SNDRV_PCM_STREAM_LAST; \ ++ stream++) ++ + /** + * snd_pcm_running - Check whether the substream is in a running state + * @substream: substream to check +-- +2.16.4 + diff --git a/patches.suse/ALSA-seq-oss-Fix-running-status-after-receiving-syse.patch b/patches.suse/ALSA-seq-oss-Fix-running-status-after-receiving-syse.patch new file mode 100644 index 0000000..a12d7d1 --- /dev/null +++ b/patches.suse/ALSA-seq-oss-Fix-running-status-after-receiving-syse.patch @@ -0,0 +1,37 @@ +From 6c3171ef76a0bad892050f6959a7eac02fb16df7 Mon Sep 17 00:00:00 2001 +From: Takashi Iwai +Date: Mon, 16 Mar 2020 10:05:06 +0100 +Subject: [PATCH] ALSA: seq: oss: Fix running status after receiving sysex +Git-commit: 6c3171ef76a0bad892050f6959a7eac02fb16df7 +Patch-mainline: v5.6-rc7 +References: git-fixes + +This is a similar bug like the previous case for virmidi: the invalid +running status is kept after receiving a sysex message. + +Again the fix is to clear the running status after handling the sysex. + +Cc: +Link: https://lore.kernel.org/r/3b4a4e0f232b7afbaf0a843f63d0e538e3029bfd.camel@domdv.de +Link: https://lore.kernel.org/r/20200316090506.23966-3-tiwai@suse.de +Signed-off-by: Takashi Iwai + +--- + sound/core/seq/oss/seq_oss_midi.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/sound/core/seq/oss/seq_oss_midi.c b/sound/core/seq/oss/seq_oss_midi.c +index a88c235b2ea3..2ddfe2226651 100644 +--- a/sound/core/seq/oss/seq_oss_midi.c ++++ b/sound/core/seq/oss/seq_oss_midi.c +@@ -602,6 +602,7 @@ send_midi_event(struct seq_oss_devinfo *dp, struct snd_seq_event *ev, struct seq + len = snd_seq_oss_timer_start(dp->timer); + if (ev->type == SNDRV_SEQ_EVENT_SYSEX) { + snd_seq_oss_readq_sysex(dp->readq, mdev->seq_device, ev); ++ snd_midi_event_reset_decode(mdev->coder); + } else { + len = snd_midi_event_decode(mdev->coder, msg, sizeof(msg), ev); + if (len > 0) +-- +2.16.4 + diff --git a/patches.suse/ALSA-seq-virmidi-Fix-running-status-after-receiving-.patch b/patches.suse/ALSA-seq-virmidi-Fix-running-status-after-receiving-.patch new file mode 100644 index 0000000..db1ce8f --- /dev/null +++ b/patches.suse/ALSA-seq-virmidi-Fix-running-status-after-receiving-.patch @@ -0,0 +1,42 @@ +From 4384f167ce5fa7241b61bb0984d651bc528ddebe Mon Sep 17 00:00:00 2001 +From: Takashi Iwai +Date: Mon, 16 Mar 2020 10:05:05 +0100 +Subject: [PATCH] ALSA: seq: virmidi: Fix running status after receiving sysex +Git-commit: 4384f167ce5fa7241b61bb0984d651bc528ddebe +Patch-mainline: v5.6-rc7 +References: git-fixes + +The virmidi driver handles sysex event exceptionally in a short-cut +snd_seq_dump_var_event() call, but this missed the reset of the +running status. As a result, it may lead to an incomplete command +right after the sysex when an event with the same running status was +queued. + +Fix it by clearing the running status properly via alling +snd_midi_event_reset_decode() for that code path. + +Reported-by: Andreas Steinmetz +Cc: +Link: https://lore.kernel.org/r/3b4a4e0f232b7afbaf0a843f63d0e538e3029bfd.camel@domdv.de +Link: https://lore.kernel.org/r/20200316090506.23966-2-tiwai@suse.de +Signed-off-by: Takashi Iwai + +--- + sound/core/seq/seq_virmidi.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/sound/core/seq/seq_virmidi.c b/sound/core/seq/seq_virmidi.c +index 626d87c1539b..77d7037d1476 100644 +--- a/sound/core/seq/seq_virmidi.c ++++ b/sound/core/seq/seq_virmidi.c +@@ -81,6 +81,7 @@ static int snd_virmidi_dev_receive_event(struct snd_virmidi_dev *rdev, + if ((ev->flags & SNDRV_SEQ_EVENT_LENGTH_MASK) != SNDRV_SEQ_EVENT_LENGTH_VARIABLE) + continue; + snd_seq_dump_var_event(ev, (snd_seq_dump_func_t)snd_rawmidi_receive, vmidi->substream); ++ snd_midi_event_reset_decode(vmidi->parser); + } else { + len = snd_midi_event_decode(vmidi->parser, msg, sizeof(msg), ev); + if (len > 0) +-- +2.16.4 + diff --git a/patches.suse/ALSA-usb-audio-Add-boot-quirk-for-MOTU-M-Series.patch b/patches.suse/ALSA-usb-audio-Add-boot-quirk-for-MOTU-M-Series.patch new file mode 100644 index 0000000..80bcddb --- /dev/null +++ b/patches.suse/ALSA-usb-audio-Add-boot-quirk-for-MOTU-M-Series.patch @@ -0,0 +1,118 @@ +From 73ac9f5e5b43a5dbadb61f27dae7a971f7ec0d22 Mon Sep 17 00:00:00 2001 +From: Alexander Tsoy +Date: Sun, 12 Jan 2020 13:23:58 +0300 +Subject: [PATCH] ALSA: usb-audio: Add boot quirk for MOTU M Series +Git-commit: 73ac9f5e5b43a5dbadb61f27dae7a971f7ec0d22 +Patch-mainline: v5.6-rc1 +References: bsc#1111666 + +Add delay to make sure that audio urbs are not sent too early. +Otherwise the device hangs. Windows driver makes ~2s delay, so use +about the same time delay value. + +snd_usb_apply_boot_quirk() is called 3 times for my MOTU M4, which +is an overkill. Thus a quirk that is called only once is implemented. + +Also send two vendor-specific control messages before and after +the delay. This behaviour is blindly copied from the Windows driver. + +Signed-off-by: Alexander Tsoy +Link: https://lore.kernel.org/r/20200112102358.18085-1-alexander@tsoy.me +Signed-off-by: Takashi Iwai + +--- + sound/usb/card.c | 4 ++++ + sound/usb/quirks.c | 38 ++++++++++++++++++++++++++++++++++++++ + sound/usb/quirks.h | 5 +++++ + 3 files changed, 47 insertions(+) + +diff --git a/sound/usb/card.c b/sound/usb/card.c +index 9f743ebae615..2f582ac7cf78 100644 +--- a/sound/usb/card.c ++++ b/sound/usb/card.c +@@ -600,6 +600,10 @@ static int usb_audio_probe(struct usb_interface *intf, + } + } + if (! chip) { ++ err = snd_usb_apply_boot_quirk_once(dev, intf, quirk, id); ++ if (err < 0) ++ return err; ++ + /* it's a fresh one. + * now look for an empty slot and create a new card instance + */ +diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c +index 11159fcfdcdf..3a5242e383b2 100644 +--- a/sound/usb/quirks.c ++++ b/sound/usb/quirks.c +@@ -1113,6 +1113,31 @@ static int snd_usb_motu_microbookii_boot_quirk(struct usb_device *dev) + return err; + } + ++static int snd_usb_motu_m_series_boot_quirk(struct usb_device *dev) ++{ ++ int ret; ++ ++ if (snd_usb_pipe_sanity_check(dev, usb_sndctrlpipe(dev, 0))) ++ return -EINVAL; ++ ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), ++ 1, USB_TYPE_VENDOR | USB_RECIP_DEVICE, ++ 0x0, 0, NULL, 0, 1000); ++ ++ if (ret < 0) ++ return ret; ++ ++ msleep(2000); ++ ++ ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), ++ 1, USB_TYPE_VENDOR | USB_RECIP_DEVICE, ++ 0x20, 0, NULL, 0, 1000); ++ ++ if (ret < 0) ++ return ret; ++ ++ return 0; ++} ++ + /* + * Setup quirks + */ +@@ -1297,6 +1322,19 @@ int snd_usb_apply_boot_quirk(struct usb_device *dev, + return 0; + } + ++int snd_usb_apply_boot_quirk_once(struct usb_device *dev, ++ struct usb_interface *intf, ++ const struct snd_usb_audio_quirk *quirk, ++ unsigned int id) ++{ ++ switch (id) { ++ case USB_ID(0x07fd, 0x0008): /* MOTU M Series */ ++ return snd_usb_motu_m_series_boot_quirk(dev); ++ } ++ ++ return 0; ++} ++ + /* + * check if the device uses big-endian samples + */ +diff --git a/sound/usb/quirks.h b/sound/usb/quirks.h +index a80e0ddd0736..df0355843a4c 100644 +--- a/sound/usb/quirks.h ++++ b/sound/usb/quirks.h +@@ -20,6 +20,11 @@ int snd_usb_apply_boot_quirk(struct usb_device *dev, + const struct snd_usb_audio_quirk *quirk, + unsigned int usb_id); + ++int snd_usb_apply_boot_quirk_once(struct usb_device *dev, ++ struct usb_interface *intf, ++ const struct snd_usb_audio_quirk *quirk, ++ unsigned int usb_id); ++ + void snd_usb_set_format_quirk(struct snd_usb_substream *subs, + struct audioformat *fmt); + +-- +2.16.4 + diff --git a/patches.suse/ALSA-usb-audio-Add-clock-validity-quirk-for-Denon-MC.patch b/patches.suse/ALSA-usb-audio-Add-clock-validity-quirk-for-Denon-MC.patch new file mode 100644 index 0000000..92a6134 --- /dev/null +++ b/patches.suse/ALSA-usb-audio-Add-clock-validity-quirk-for-Denon-MC.patch @@ -0,0 +1,274 @@ +From 9f35a31283775e6f6af73fb2c95c686a4c0acac7 Mon Sep 17 00:00:00 2001 +From: Alexander Tsoy +Date: Thu, 13 Feb 2020 02:54:50 +0300 +Subject: [PATCH] ALSA: usb-audio: Add clock validity quirk for Denon MC7000/MCX8000 +Git-commit: 9f35a31283775e6f6af73fb2c95c686a4c0acac7 +Patch-mainline: v5.6-rc2 +References: bsc#1111666 + +It should be safe to ignore clock validity check result if the following +conditions are met: + - only one single sample rate is supported; + - the terminal is directly connected to the clock source; + - the clock type is internal. + +This is to deal with some Denon DJ controllers that always reports that +clock is invalid. + +Tested-by: Tobias Oszlanyi +Signed-off-by: Alexander Tsoy +Cc: +Link: https://lore.kernel.org/r/20200212235450.697348-1-alexander@tsoy.me +Signed-off-by: Takashi Iwai + +--- + sound/usb/clock.c | 91 +++++++++++++++++++++++++++++++++++++----------------- + sound/usb/clock.h | 4 +-- + sound/usb/format.c | 3 +- + 3 files changed, 66 insertions(+), 32 deletions(-) + +diff --git a/sound/usb/clock.c b/sound/usb/clock.c +index 018b1ecb5404..a48313dfa967 100644 +--- a/sound/usb/clock.c ++++ b/sound/usb/clock.c +@@ -151,8 +151,34 @@ static int uac_clock_selector_set_val(struct snd_usb_audio *chip, int selector_i + return ret; + } + ++/* ++ * Assume the clock is valid if clock source supports only one single sample ++ * rate, the terminal is connected directly to it (there is no clock selector) ++ * and clock type is internal. This is to deal with some Denon DJ controllers ++ * that always reports that clock is invalid. ++ */ ++static bool uac_clock_source_is_valid_quirk(struct snd_usb_audio *chip, ++ struct audioformat *fmt, ++ int source_id) ++{ ++ if (fmt->protocol == UAC_VERSION_2) { ++ struct uac_clock_source_descriptor *cs_desc = ++ snd_usb_find_clock_source(chip->ctrl_intf, source_id); ++ ++ if (!cs_desc) ++ return false; ++ ++ return (fmt->nr_rates == 1 && ++ (fmt->clock & 0xff) == cs_desc->bClockID && ++ (cs_desc->bmAttributes & 0x3) != ++ UAC_CLOCK_SOURCE_TYPE_EXT); ++ } ++ ++ return false; ++} ++ + static bool uac_clock_source_is_valid(struct snd_usb_audio *chip, +- int protocol, ++ struct audioformat *fmt, + int source_id) + { + int err; +@@ -160,7 +186,7 @@ static bool uac_clock_source_is_valid(struct snd_usb_audio *chip, + struct usb_device *dev = chip->dev; + u32 bmControls; + +- if (protocol == UAC_VERSION_3) { ++ if (fmt->protocol == UAC_VERSION_3) { + struct uac3_clock_source_descriptor *cs_desc = + snd_usb_find_clock_source_v3(chip->ctrl_intf, source_id); + +@@ -194,10 +220,14 @@ static bool uac_clock_source_is_valid(struct snd_usb_audio *chip, + return false; + } + +- return data ? true : false; ++ if (data) ++ return true; ++ else ++ return uac_clock_source_is_valid_quirk(chip, fmt, source_id); + } + +-static int __uac_clock_find_source(struct snd_usb_audio *chip, int entity_id, ++static int __uac_clock_find_source(struct snd_usb_audio *chip, ++ struct audioformat *fmt, int entity_id, + unsigned long *visited, bool validate) + { + struct uac_clock_source_descriptor *source; +@@ -217,7 +247,7 @@ static int __uac_clock_find_source(struct snd_usb_audio *chip, int entity_id, + source = snd_usb_find_clock_source(chip->ctrl_intf, entity_id); + if (source) { + entity_id = source->bClockID; +- if (validate && !uac_clock_source_is_valid(chip, UAC_VERSION_2, ++ if (validate && !uac_clock_source_is_valid(chip, fmt, + entity_id)) { + usb_audio_err(chip, + "clock source %d is not valid, cannot use\n", +@@ -248,8 +278,9 @@ static int __uac_clock_find_source(struct snd_usb_audio *chip, int entity_id, + } + + cur = ret; +- ret = __uac_clock_find_source(chip, selector->baCSourceID[ret - 1], +- visited, validate); ++ ret = __uac_clock_find_source(chip, fmt, ++ selector->baCSourceID[ret - 1], ++ visited, validate); + if (!validate || ret > 0 || !chip->autoclock) + return ret; + +@@ -260,8 +291,9 @@ static int __uac_clock_find_source(struct snd_usb_audio *chip, int entity_id, + if (i == cur) + continue; + +- ret = __uac_clock_find_source(chip, selector->baCSourceID[i - 1], +- visited, true); ++ ret = __uac_clock_find_source(chip, fmt, ++ selector->baCSourceID[i - 1], ++ visited, true); + if (ret < 0) + continue; + +@@ -281,14 +313,16 @@ static int __uac_clock_find_source(struct snd_usb_audio *chip, int entity_id, + /* FIXME: multipliers only act as pass-thru element for now */ + multiplier = snd_usb_find_clock_multiplier(chip->ctrl_intf, entity_id); + if (multiplier) +- return __uac_clock_find_source(chip, multiplier->bCSourceID, +- visited, validate); ++ return __uac_clock_find_source(chip, fmt, ++ multiplier->bCSourceID, ++ visited, validate); + + return -EINVAL; + } + +-static int __uac3_clock_find_source(struct snd_usb_audio *chip, int entity_id, +- unsigned long *visited, bool validate) ++static int __uac3_clock_find_source(struct snd_usb_audio *chip, ++ struct audioformat *fmt, int entity_id, ++ unsigned long *visited, bool validate) + { + struct uac3_clock_source_descriptor *source; + struct uac3_clock_selector_descriptor *selector; +@@ -307,7 +341,7 @@ static int __uac3_clock_find_source(struct snd_usb_audio *chip, int entity_id, + source = snd_usb_find_clock_source_v3(chip->ctrl_intf, entity_id); + if (source) { + entity_id = source->bClockID; +- if (validate && !uac_clock_source_is_valid(chip, UAC_VERSION_3, ++ if (validate && !uac_clock_source_is_valid(chip, fmt, + entity_id)) { + usb_audio_err(chip, + "clock source %d is not valid, cannot use\n", +@@ -338,7 +372,8 @@ static int __uac3_clock_find_source(struct snd_usb_audio *chip, int entity_id, + } + + cur = ret; +- ret = __uac3_clock_find_source(chip, selector->baCSourceID[ret - 1], ++ ret = __uac3_clock_find_source(chip, fmt, ++ selector->baCSourceID[ret - 1], + visited, validate); + if (!validate || ret > 0 || !chip->autoclock) + return ret; +@@ -350,8 +385,9 @@ static int __uac3_clock_find_source(struct snd_usb_audio *chip, int entity_id, + if (i == cur) + continue; + +- ret = __uac3_clock_find_source(chip, selector->baCSourceID[i - 1], +- visited, true); ++ ret = __uac3_clock_find_source(chip, fmt, ++ selector->baCSourceID[i - 1], ++ visited, true); + if (ret < 0) + continue; + +@@ -372,7 +408,8 @@ static int __uac3_clock_find_source(struct snd_usb_audio *chip, int entity_id, + multiplier = snd_usb_find_clock_multiplier_v3(chip->ctrl_intf, + entity_id); + if (multiplier) +- return __uac3_clock_find_source(chip, multiplier->bCSourceID, ++ return __uac3_clock_find_source(chip, fmt, ++ multiplier->bCSourceID, + visited, validate); + + return -EINVAL; +@@ -389,18 +426,18 @@ static int __uac3_clock_find_source(struct snd_usb_audio *chip, int entity_id, + * + * Returns the clock source UnitID (>=0) on success, or an error. + */ +-int snd_usb_clock_find_source(struct snd_usb_audio *chip, int protocol, +- int entity_id, bool validate) ++int snd_usb_clock_find_source(struct snd_usb_audio *chip, ++ struct audioformat *fmt, bool validate) + { + DECLARE_BITMAP(visited, 256); + memset(visited, 0, sizeof(visited)); + +- switch (protocol) { ++ switch (fmt->protocol) { + case UAC_VERSION_2: +- return __uac_clock_find_source(chip, entity_id, visited, ++ return __uac_clock_find_source(chip, fmt, fmt->clock, visited, + validate); + case UAC_VERSION_3: +- return __uac3_clock_find_source(chip, entity_id, visited, ++ return __uac3_clock_find_source(chip, fmt, fmt->clock, visited, + validate); + default: + return -EINVAL; +@@ -501,8 +538,7 @@ static int set_sample_rate_v2v3(struct snd_usb_audio *chip, int iface, + * automatic clock selection if the current clock is not + * valid. + */ +- clock = snd_usb_clock_find_source(chip, fmt->protocol, +- fmt->clock, true); ++ clock = snd_usb_clock_find_source(chip, fmt, true); + if (clock < 0) { + /* We did not find a valid clock, but that might be + * because the current sample rate does not match an +@@ -510,8 +546,7 @@ static int set_sample_rate_v2v3(struct snd_usb_audio *chip, int iface, + * and we will do another validation after setting the + * rate. + */ +- clock = snd_usb_clock_find_source(chip, fmt->protocol, +- fmt->clock, false); ++ clock = snd_usb_clock_find_source(chip, fmt, false); + if (clock < 0) + return clock; + } +@@ -577,7 +612,7 @@ static int set_sample_rate_v2v3(struct snd_usb_audio *chip, int iface, + + validation: + /* validate clock after rate change */ +- if (!uac_clock_source_is_valid(chip, fmt->protocol, clock)) ++ if (!uac_clock_source_is_valid(chip, fmt, clock)) + return -ENXIO; + return 0; + } +diff --git a/sound/usb/clock.h b/sound/usb/clock.h +index 076e31b79ee0..68df0fbe09d0 100644 +--- a/sound/usb/clock.h ++++ b/sound/usb/clock.h +@@ -6,7 +6,7 @@ int snd_usb_init_sample_rate(struct snd_usb_audio *chip, int iface, + struct usb_host_interface *alts, + struct audioformat *fmt, int rate); + +-int snd_usb_clock_find_source(struct snd_usb_audio *chip, int protocol, +- int entity_id, bool validate); ++int snd_usb_clock_find_source(struct snd_usb_audio *chip, ++ struct audioformat *fmt, bool validate); + + #endif /* __USBAUDIO_CLOCK_H */ +diff --git a/sound/usb/format.c b/sound/usb/format.c +index 50cb183958bf..9f5cb4ed3a0c 100644 +--- a/sound/usb/format.c ++++ b/sound/usb/format.c +@@ -336,8 +336,7 @@ static int parse_audio_format_rates_v2v3(struct snd_usb_audio *chip, + struct usb_device *dev = chip->dev; + unsigned char tmp[2], *data; + int nr_triplets, data_size, ret = 0, ret_l6; +- int clock = snd_usb_clock_find_source(chip, fp->protocol, +- fp->clock, false); ++ int clock = snd_usb_clock_find_source(chip, fp, false); + + if (clock < 0) { + dev_err(&dev->dev, +-- +2.16.4 + diff --git a/patches.suse/ALSA-usb-audio-Add-delayed_register-option.patch b/patches.suse/ALSA-usb-audio-Add-delayed_register-option.patch new file mode 100644 index 0000000..3bab070 --- /dev/null +++ b/patches.suse/ALSA-usb-audio-Add-delayed_register-option.patch @@ -0,0 +1,82 @@ +From b70038ef4feae9c5c9d01de4cd799ae52ccafc08 Mon Sep 17 00:00:00 2001 +From: Takashi Iwai +Date: Wed, 25 Mar 2020 11:33:20 +0100 +Subject: [PATCH] ALSA: usb-audio: Add delayed_register option +Git-commit: b70038ef4feae9c5c9d01de4cd799ae52ccafc08 +Patch-mainline: v5.7-rc1 +References: bsc#1051510 + +Add a new option for specifying the quirk for delayed registration of +the certain device. A list of devices can be passed in a form + ID:IFACE,ID:IFACE,ID:IFACE,.... +where ID is the 32bit hex number combo of vendor and device IDs and +IFACE is the interface number to trigger the register. + +When a matching device is probed, the card registration is delayed +until the given interface is probed. It's needed for syncing the +registration until the last interface when multiple interfaces are +provided for the same card. + +Link: https://lore.kernel.org/r/20200325103322.2508-3-tiwai@suse.de +Signed-off-by: Takashi Iwai + +--- + sound/usb/card.c | 21 ++++++++++++++++++++- + 1 file changed, 20 insertions(+), 1 deletion(-) + +diff --git a/sound/usb/card.c b/sound/usb/card.c +index 55d563a8154d..951134238669 100644 +--- a/sound/usb/card.c ++++ b/sound/usb/card.c +@@ -72,6 +72,7 @@ static int device_setup[SNDRV_CARDS]; /* device parameter for this card */ + static bool ignore_ctl_error; + static bool autoclock = true; + static char *quirk_alias[SNDRV_CARDS]; ++static char *delayed_register[SNDRV_CARDS]; + + bool snd_usb_use_vmalloc = true; + bool snd_usb_skip_validation; +@@ -95,6 +96,8 @@ module_param(autoclock, bool, 0444); + MODULE_PARM_DESC(autoclock, "Enable auto-clock selection for UAC2 devices (default: yes)."); + module_param_array(quirk_alias, charp, NULL, 0444); + MODULE_PARM_DESC(quirk_alias, "Quirk aliases, e.g. 0123abcd:5678beef."); ++module_param_array(delayed_register, charp, NULL, 0444); ++MODULE_PARM_DESC(delayed_register, "Quirk for delayed registration, given by id:iface, e.g. 0123abcd:4."); + module_param_named(use_vmalloc, snd_usb_use_vmalloc, bool, 0444); + MODULE_PARM_DESC(use_vmalloc, "Use vmalloc for PCM intermediate buffers (default: yes)."); + module_param_named(skip_validation, snd_usb_skip_validation, bool, 0444); +@@ -525,6 +528,21 @@ static bool get_alias_id(struct usb_device *dev, unsigned int *id) + return false; + } + ++static bool check_delayed_register_option(struct snd_usb_audio *chip, int iface) ++{ ++ int i; ++ unsigned int id, inum; ++ ++ for (i = 0; i < ARRAY_SIZE(delayed_register); i++) { ++ if (delayed_register[i] && ++ sscanf(delayed_register[i], "%x:%x", &id, &inum) == 2 && ++ id == chip->usb_id) ++ return inum != iface; ++ } ++ ++ return false; ++} ++ + static const struct usb_device_id usb_audio_ids[]; /* defined below */ + + /* look for the corresponding quirk */ +@@ -665,7 +683,8 @@ static int usb_audio_probe(struct usb_interface *intf, + /* we are allowed to call snd_card_register() many times, but first + * check to see if a device needs to skip it or do anything special + */ +- if (!snd_usb_registration_quirk(chip, ifnum)) { ++ if (!snd_usb_registration_quirk(chip, ifnum) && ++ !check_delayed_register_option(chip, ifnum)) { + err = snd_card_register(chip->card); + if (err < 0) + goto __error; +-- +2.16.4 + diff --git a/patches.suse/ALSA-usb-audio-Add-support-for-MOTU-MicroBook-IIc.patch b/patches.suse/ALSA-usb-audio-Add-support-for-MOTU-MicroBook-IIc.patch new file mode 100644 index 0000000..e9f5917 --- /dev/null +++ b/patches.suse/ALSA-usb-audio-Add-support-for-MOTU-MicroBook-IIc.patch @@ -0,0 +1,184 @@ +From 2edb84e3047b93da2f2b234219cdc304df042d9e Mon Sep 17 00:00:00 2001 +From: Alexander Tsoy +Date: Sat, 29 Feb 2020 18:18:15 +0300 +Subject: [PATCH] ALSA: usb-audio: Add support for MOTU MicroBook IIc +Git-commit: 2edb84e3047b93da2f2b234219cdc304df042d9e +Patch-mainline: v5.7-rc1 +References: bsc#1051510 + +MicroBook IIc operates in UAC2 mode by default. This patch addresses +several issues with it: + +- MicroBook II and IIc shares the same USB ID. We can distinguish them + by interface class. +- MaxPacketsOnly attribute is erroneously set in endpoint descriptors. + As a result this card produces noise with all sample rates other than + 96 KHz. This also causes issues like IOMMU page faults and other + problems with host controller. +- Sample rate changes takes more than 2 seconds for this device. Clock + validity request returns false during that period, so the clock validity + quirk is required. + +Signed-off-by: Alexander Tsoy +Link: https://lore.kernel.org/r/20200229151815.14199-1-alexander@tsoy.me +Signed-off-by: Takashi Iwai + +--- + sound/usb/clock.c | 59 +++++++++++++++++++++++++++++++++++++++--------- + sound/usb/pcm.c | 7 +++++- + sound/usb/quirks-table.h | 2 +- + sound/usb/quirks.c | 18 ++++++++++++++- + 4 files changed, 72 insertions(+), 14 deletions(-) + +diff --git a/sound/usb/clock.c b/sound/usb/clock.c +index a48313dfa967..b118cf97607f 100644 +--- a/sound/usb/clock.c ++++ b/sound/usb/clock.c +@@ -151,16 +151,15 @@ static int uac_clock_selector_set_val(struct snd_usb_audio *chip, int selector_i + return ret; + } + +-/* +- * Assume the clock is valid if clock source supports only one single sample +- * rate, the terminal is connected directly to it (there is no clock selector) +- * and clock type is internal. This is to deal with some Denon DJ controllers +- * that always reports that clock is invalid. +- */ + static bool uac_clock_source_is_valid_quirk(struct snd_usb_audio *chip, + struct audioformat *fmt, + int source_id) + { ++ bool ret = false; ++ int count; ++ unsigned char data; ++ struct usb_device *dev = chip->dev; ++ + if (fmt->protocol == UAC_VERSION_2) { + struct uac_clock_source_descriptor *cs_desc = + snd_usb_find_clock_source(chip->ctrl_intf, source_id); +@@ -168,13 +167,51 @@ static bool uac_clock_source_is_valid_quirk(struct snd_usb_audio *chip, + if (!cs_desc) + return false; + +- return (fmt->nr_rates == 1 && +- (fmt->clock & 0xff) == cs_desc->bClockID && +- (cs_desc->bmAttributes & 0x3) != +- UAC_CLOCK_SOURCE_TYPE_EXT); ++ /* ++ * Assume the clock is valid if clock source supports only one ++ * single sample rate, the terminal is connected directly to it ++ * (there is no clock selector) and clock type is internal. ++ * This is to deal with some Denon DJ controllers that always ++ * reports that clock is invalid. ++ */ ++ if (fmt->nr_rates == 1 && ++ (fmt->clock & 0xff) == cs_desc->bClockID && ++ (cs_desc->bmAttributes & 0x3) != ++ UAC_CLOCK_SOURCE_TYPE_EXT) ++ return true; ++ } ++ ++ /* ++ * MOTU MicroBook IIc ++ * Sample rate changes takes more than 2 seconds for this device. Clock ++ * validity request returns false during that period. ++ */ ++ if (chip->usb_id == USB_ID(0x07fd, 0x0004)) { ++ count = 0; ++ ++ while ((!ret) && (count < 50)) { ++ int err; ++ ++ msleep(100); ++ ++ err = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), UAC2_CS_CUR, ++ USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN, ++ UAC2_CS_CONTROL_CLOCK_VALID << 8, ++ snd_usb_ctrl_intf(chip) | (source_id << 8), ++ &data, sizeof(data)); ++ if (err < 0) { ++ dev_warn(&dev->dev, ++ "%s(): cannot get clock validity for id %d\n", ++ __func__, source_id); ++ return false; ++ } ++ ++ ret = !!data; ++ count++; ++ } + } + +- return false; ++ return ret; + } + + static bool uac_clock_source_is_valid(struct snd_usb_audio *chip, +diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c +index bd258f1ec2dd..a4e4064f9aee 100644 +--- a/sound/usb/pcm.c ++++ b/sound/usb/pcm.c +@@ -357,7 +357,12 @@ static int set_sync_ep_implicit_fb_quirk(struct snd_usb_substream *subs, + ep = 0x81; + ifnum = 1; + goto add_sync_ep_from_ifnum; +- case USB_ID(0x07fd, 0x0004): /* MOTU MicroBook II */ ++ case USB_ID(0x07fd, 0x0004): /* MOTU MicroBook II/IIc */ ++ /* MicroBook IIc */ ++ if (altsd->bInterfaceClass == USB_CLASS_AUDIO) ++ return 0; ++ ++ /* MicroBook II */ + ep = 0x84; + ifnum = 0; + goto add_sync_ep_from_ifnum; +diff --git a/sound/usb/quirks-table.h b/sound/usb/quirks-table.h +index d187aa6d50db..1c8719292eee 100644 +--- a/sound/usb/quirks-table.h ++++ b/sound/usb/quirks-table.h +@@ -3472,7 +3472,7 @@ AU0828_DEVICE(0x2040, 0x7270, "Hauppauge", "HVR-950Q"), + }, + /* MOTU Microbook II */ + { +- USB_DEVICE(0x07fd, 0x0004), ++ USB_DEVICE_VENDOR_SPEC(0x07fd, 0x0004), + .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) { + .vendor_name = "MOTU", + .product_name = "MicroBookII", +diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c +index 915aea256f65..3cc745fe24d8 100644 +--- a/sound/usb/quirks.c ++++ b/sound/usb/quirks.c +@@ -1352,7 +1352,15 @@ int snd_usb_apply_boot_quirk(struct usb_device *dev, + case USB_ID(0x2466, 0x8010): /* Fractal Audio Axe-Fx 3 */ + return snd_usb_axefx3_boot_quirk(dev); + case USB_ID(0x07fd, 0x0004): /* MOTU MicroBook II */ +- return snd_usb_motu_microbookii_boot_quirk(dev); ++ /* ++ * For some reason interface 3 with vendor-spec class is ++ * detected on MicroBook IIc. ++ */ ++ if (get_iface_desc(intf->altsetting)->bInterfaceClass == ++ USB_CLASS_VENDOR_SPEC && ++ get_iface_desc(intf->altsetting)->bInterfaceNumber < 3) ++ return snd_usb_motu_microbookii_boot_quirk(dev); ++ break; + } + + return 0; +@@ -1790,5 +1798,13 @@ void snd_usb_audioformat_attributes_quirk(struct snd_usb_audio *chip, + else + fp->ep_attr |= USB_ENDPOINT_SYNC_SYNC; + break; ++ case USB_ID(0x07fd, 0x0004): /* MOTU MicroBook IIc */ ++ /* ++ * MaxPacketsOnly attribute is erroneously set in endpoint ++ * descriptors. As a result this card produces noise with ++ * all sample rates other than 96 KHz. ++ */ ++ fp->attributes &= ~UAC_EP_CS_ATTR_FILL_MAX; ++ break; + } + } +-- +2.16.4 + diff --git a/patches.suse/ALSA-usb-audio-Apply-48kHz-fixed-rate-playback-for-J.patch b/patches.suse/ALSA-usb-audio-Apply-48kHz-fixed-rate-playback-for-J.patch new file mode 100644 index 0000000..2a779fd --- /dev/null +++ b/patches.suse/ALSA-usb-audio-Apply-48kHz-fixed-rate-playback-for-J.patch @@ -0,0 +1,84 @@ +From 74f73476c3755664504b7d266b5e8f91050ffed9 Mon Sep 17 00:00:00 2001 +From: Takashi Iwai +Date: Tue, 11 Feb 2020 12:14:19 +0100 +Subject: [PATCH] ALSA: usb-audio: Apply 48kHz fixed rate playback for Jabra Evolve 65 headset +Git-commit: 74f73476c3755664504b7d266b5e8f91050ffed9 +Patch-mainline: v5.6-rc2 +References: bsc#1111666 + +Jabra Evolve 65 headset appears as if supporting lower rates than +48kHz, but it actually doesn't work but with 48kHz for playback. + +This patch applies a workaround to enforce the 48kHz like LINE6 +devices already did. The workaround is put in a unified helper +function, set_fixed_rate(), to be called from both places now. + +Buglink: https://bugzilla.kernel.org/show_bug.cgi?id=206149 +Link: https://lore.kernel.org/r/20200211111419.5895-1-tiwai@suse.de +Signed-off-by: Takashi Iwai + +--- + sound/usb/format.c | 33 ++++++++++++++++++++++----------- + 1 file changed, 22 insertions(+), 11 deletions(-) + +diff --git a/sound/usb/format.c b/sound/usb/format.c +index 9260136e4c9b..50cb183958bf 100644 +--- a/sound/usb/format.c ++++ b/sound/usb/format.c +@@ -151,6 +151,19 @@ static u64 parse_audio_format_i_type(struct snd_usb_audio *chip, + return pcm_formats; + } + ++static int set_fixed_rate(struct audioformat *fp, int rate, int rate_bits) ++{ ++ kfree(fp->rate_table); ++ fp->rate_table = kmalloc(sizeof(int), GFP_KERNEL); ++ if (!fp->rate_table) ++ return -ENOMEM; ++ fp->nr_rates = 1; ++ fp->rate_min = rate; ++ fp->rate_max = rate; ++ fp->rates = rate_bits; ++ fp->rate_table[0] = rate; ++ return 0; ++} + + /* + * parse the format descriptor and stores the possible sample rates +@@ -223,6 +236,14 @@ static int parse_audio_format_rates_v1(struct snd_usb_audio *chip, struct audiof + fp->rate_min = combine_triple(&fmt[offset + 1]); + fp->rate_max = combine_triple(&fmt[offset + 4]); + } ++ ++ /* Jabra Evolve 65 headset */ ++ if (chip->usb_id == USB_ID(0x0b0e, 0x030b)) { ++ /* only 48kHz for playback while keeping 16kHz for capture */ ++ if (fp->nr_rates != 1) ++ return set_fixed_rate(fp, 48000, SNDRV_PCM_RATE_48000); ++ } ++ + return 0; + } + +@@ -299,17 +320,7 @@ static int line6_parse_audio_format_rates_quirk(struct snd_usb_audio *chip, + case USB_ID(0x0e41, 0x4248): /* Line6 Helix >= fw 2.82 */ + case USB_ID(0x0e41, 0x4249): /* Line6 Helix Rack >= fw 2.82 */ + case USB_ID(0x0e41, 0x424a): /* Line6 Helix LT >= fw 2.82 */ +- /* supported rates: 48Khz */ +- kfree(fp->rate_table); +- fp->rate_table = kmalloc(sizeof(int), GFP_KERNEL); +- if (!fp->rate_table) +- return -ENOMEM; +- fp->nr_rates = 1; +- fp->rate_min = 48000; +- fp->rate_max = 48000; +- fp->rates = SNDRV_PCM_RATE_48000; +- fp->rate_table[0] = 48000; +- return 0; ++ return set_fixed_rate(fp, 48000, SNDRV_PCM_RATE_48000); + } + + return -ENODEV; +-- +2.16.4 + diff --git a/patches.suse/ALSA-usb-audio-Create-a-registration-quirk-for-Kings.patch b/patches.suse/ALSA-usb-audio-Create-a-registration-quirk-for-Kings.patch new file mode 100644 index 0000000..d5b50a4 --- /dev/null +++ b/patches.suse/ALSA-usb-audio-Create-a-registration-quirk-for-Kings.patch @@ -0,0 +1,76 @@ +From 55f7326170d9e83e2d828591938e1101982a679c Mon Sep 17 00:00:00 2001 +From: Chris Wulff +Date: Sat, 14 Mar 2020 12:54:49 -0400 +Subject: [PATCH] ALSA: usb-audio: Create a registration quirk for Kingston HyperX Amp (0951:16d8) +Git-commit: 55f7326170d9e83e2d828591938e1101982a679c +Patch-mainline: v5.7-rc1 +References: bsc#1051510 + +Create a quirk that allows special processing and/or +skipping the call to snd_card_register. + +For HyperX AMP, which uses two interfaces, but only has +a capture stream in the second, this allows the capture +stream to merge with the first PCM. + +Signed-off-by: Chris Wulff +Link: https://lore.kernel.org/r/20200314165449.4086-3-crwulff@gmail.com +Signed-off-by: Takashi Iwai + +--- + sound/usb/card.c | 12 ++++++++---- + sound/usb/quirks.c | 14 ++++++++++++++ + sound/usb/quirks.h | 3 +++ + 3 files changed, 25 insertions(+), 4 deletions(-) + +--- a/sound/usb/card.c ++++ b/sound/usb/card.c +@@ -675,10 +675,14 @@ static int usb_audio_probe(struct usb_in + goto __error; + } + +- /* we are allowed to call snd_card_register() many times */ +- err = snd_card_register(chip->card); +- if (err < 0) +- goto __error; ++ /* we are allowed to call snd_card_register() many times, but first ++ * check to see if a device needs to skip it or do anything special ++ */ ++ if (snd_usb_registration_quirk(chip, ifnum) == 0) { ++ err = snd_card_register(chip->card); ++ if (err < 0) ++ goto __error; ++ } + + usb_chip[chip->index] = chip; + chip->num_interfaces++; +--- a/sound/usb/quirks.c ++++ b/sound/usb/quirks.c +@@ -1774,3 +1774,17 @@ void snd_usb_audioformat_attributes_quir + break; + } + } ++ ++int snd_usb_registration_quirk(struct snd_usb_audio *chip, ++ int iface) ++{ ++ switch (chip->usb_id) { ++ case USB_ID(0x0951, 0x16d8): /* Kingston HyperX AMP */ ++ /* Register only when we reach interface 2 so that streams can ++ * merge correctly into PCMs from interface 0 ++ */ ++ return (iface != 2); ++ } ++ /* Register as normal */ ++ return 0; ++} +--- a/sound/usb/quirks.h ++++ b/sound/usb/quirks.h +@@ -50,4 +50,7 @@ void snd_usb_audioformat_attributes_quir + struct audioformat *fp, + int stream); + ++int snd_usb_registration_quirk(struct snd_usb_audio *chip, ++ int iface); ++ + #endif /* __USBAUDIO_QUIRKS_H */ diff --git a/patches.suse/ALSA-usb-audio-Don-t-create-a-mixer-element-with-bog.patch b/patches.suse/ALSA-usb-audio-Don-t-create-a-mixer-element-with-bog.patch new file mode 100644 index 0000000..ebfbfb9 --- /dev/null +++ b/patches.suse/ALSA-usb-audio-Don-t-create-a-mixer-element-with-bog.patch @@ -0,0 +1,44 @@ +From e9a0ef0b5ddcbc0d56c65aefc0f18d16e6f71207 Mon Sep 17 00:00:00 2001 +From: Takashi Iwai +Date: Fri, 14 Feb 2020 15:49:28 +0100 +Subject: [PATCH] ALSA: usb-audio: Don't create a mixer element with bogus volume range +Git-commit: e9a0ef0b5ddcbc0d56c65aefc0f18d16e6f71207 +Patch-mainline: v5.7-rc1 +References: bsc#1051510 + +Some USB-audio descriptors provide a bogus volume range (e.g. volume +min and max are identical), which confuses user-space. +This patch makes the driver skipping such a control element. + +Buglink: https://bugzilla.kernel.org/show_bug.cgi?id=206221 +Link: https://lore.kernel.org/r/20200214144928.23628-1-tiwai@suse.de +Signed-off-by: Takashi Iwai + +--- + sound/usb/mixer.c | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c +index d659fdb475e2..96e20488804d 100644 +--- a/sound/usb/mixer.c ++++ b/sound/usb/mixer.c +@@ -1666,6 +1666,16 @@ static void __build_feature_ctl(struct usb_mixer_interface *mixer, + /* get min/max values */ + get_min_max_with_quirks(cval, 0, kctl); + ++ /* skip a bogus volume range */ ++ if (cval->max <= cval->min) { ++ usb_audio_dbg(mixer->chip, ++ "[%d] FU [%s] skipped due to invalid volume\n", ++ cval->head.id, kctl->id.name); ++ snd_ctl_free_one(kctl); ++ return; ++ } ++ ++ + if (control == UAC_FU_VOLUME) { + check_mapped_dB(map, cval); + if (cval->dBmin < cval->dBmax || !cval->initialized) { +-- +2.16.4 + diff --git a/patches.suse/ALSA-usb-audio-Fix-UAC2-3-effect-unit-parsing.patch b/patches.suse/ALSA-usb-audio-Fix-UAC2-3-effect-unit-parsing.patch new file mode 100644 index 0000000..11a0511 --- /dev/null +++ b/patches.suse/ALSA-usb-audio-Fix-UAC2-3-effect-unit-parsing.patch @@ -0,0 +1,87 @@ +From d75a170fd848f037a1e28893ad10be7a4c51f8a6 Mon Sep 17 00:00:00 2001 +From: Takashi Iwai +Date: Tue, 11 Feb 2020 17:05:21 +0100 +Subject: [PATCH] ALSA: usb-audio: Fix UAC2/3 effect unit parsing +Git-commit: d75a170fd848f037a1e28893ad10be7a4c51f8a6 +Patch-mainline: v5.6-rc2 +References: bsc#1111666 + +We've got a regression report about M-Audio Fast Track C400 device, +and the git bisection resulted in the commit e0ccdef92653 ("ALSA: +Usb-audio: Clean up check_input_term()"). This commit was about the +rewrite of the input terminal parser, and it's not too obvious from +the change what really broke. The answer is: it's the interpretation +of UAC2/3 effect units. + +In the original code, UAC2 effect unit is as if through UAC1 +processing unit because both UAC1 PU and UAC2/3 EU share the same +number (0x07). The old code went through a complex switch-case +fallthrough, finally bailing out in the middle: + + if (protocol == UAC_VERSION_2 && + hdr[2] == UAC2_EFFECT_UNIT) { + /* UAC2/UAC1 unit IDs overlap here in an + * uncompatible way. Ignore this unit for now. + */ + return 0; + } + +... and this special handling was missing in the new code; the new +code treats UAC2/3 effect unit as if it were equivalent with the +processing unit. + +Actually, the old code was too confusing. The effect unit has an +incompatible unit description with the processing unit, so we +shouldn't have dealt with EU in the same way. + +This patch addresses the regression by changing the effect unit +handling to the own parser function. The own parser function makes +the clear distinct with PU, so it improves the readability, too. + +The EU parser just sets the type and the id like the old kernels. +Once when the proper effect unit support is added, we can revisit this +parser function, but for now, let's keep this simple setup as is. + +Fixes: e0ccdef92653 ("ALSA: usb-audio: Clean up check_input_term()") +Cc: +Buglink: https://bugzilla.kernel.org/show_bug.cgi?id=206147 +Link: https://lore.kernel.org/r/20200211160521.31990-1-tiwai@suse.de +Signed-off-by: Takashi Iwai + +--- + sound/usb/mixer.c | 12 ++++++++++-- + 1 file changed, 10 insertions(+), 2 deletions(-) + +diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c +index d659fdb475e2..81b2db0edd5f 100644 +--- a/sound/usb/mixer.c ++++ b/sound/usb/mixer.c +@@ -897,6 +897,15 @@ static int parse_term_proc_unit(struct mixer_build *state, + return 0; + } + ++static int parse_term_effect_unit(struct mixer_build *state, ++ struct usb_audio_term *term, ++ void *p1, int id) ++{ ++ term->type = UAC3_EFFECT_UNIT << 16; /* virtual type */ ++ term->id = id; ++ return 0; ++} ++ + static int parse_term_uac2_clock_source(struct mixer_build *state, + struct usb_audio_term *term, + void *p1, int id) +@@ -981,8 +990,7 @@ static int __check_input_term(struct mixer_build *state, int id, + UAC3_PROCESSING_UNIT); + case PTYPE(UAC_VERSION_2, UAC2_EFFECT_UNIT): + case PTYPE(UAC_VERSION_3, UAC3_EFFECT_UNIT): +- return parse_term_proc_unit(state, term, p1, id, +- UAC3_EFFECT_UNIT); ++ return parse_term_effect_unit(state, term, p1, id); + case PTYPE(UAC_VERSION_1, UAC1_EXTENSION_UNIT): + case PTYPE(UAC_VERSION_2, UAC2_EXTENSION_UNIT_V2): + case PTYPE(UAC_VERSION_3, UAC3_EXTENSION_UNIT): +-- +2.16.4 + diff --git a/patches.suse/ALSA-usb-audio-Fix-case-when-USB-MIDI-interface-has-.patch b/patches.suse/ALSA-usb-audio-Fix-case-when-USB-MIDI-interface-has-.patch new file mode 100644 index 0000000..5021703 --- /dev/null +++ b/patches.suse/ALSA-usb-audio-Fix-case-when-USB-MIDI-interface-has-.patch @@ -0,0 +1,79 @@ +From 5c6cd7021a05a02fcf37f360592d7c18d4d807fb Mon Sep 17 00:00:00 2001 +From: Andreas Steinmetz +Date: Tue, 31 Mar 2020 14:25:54 +0200 +Subject: [PATCH] ALSA: usb-audio: Fix case when USB MIDI interface has more than one extra endpoint descriptor +Git-commit: 5c6cd7021a05a02fcf37f360592d7c18d4d807fb +Patch-mainline: v5.7-rc1 +References: bsc#1051510 + +The Miditech MIDIFACE 16x16 (USB ID 1290:1749) has more than one extra +endpoint descriptor. + +The first extra descriptor is: 0x06 0x30 0x00 0x00 0x00 0x00 + +As the code in snd_usbmidi_get_ms_info() looks only at the +first extra descriptor to find USB_DT_CS_ENDPOINT the device +as such is recognized but there is neither input nor output +configured. + +The patch iterates through the extra descriptors to find the +proper one. With this patch the device is correctly configured. + +Signed-off-by: Andreas Steinmetz +Link: https://lore.kernel.org/r/1c3b431a86f69e1d60745b6110cdb93c299f120b.camel@domdv.de +Signed-off-by: Takashi Iwai + +--- + sound/usb/midi.c | 29 ++++++++++++++++++++++++----- + 1 file changed, 24 insertions(+), 5 deletions(-) + +diff --git a/sound/usb/midi.c b/sound/usb/midi.c +index be5c597ed40c..047b90595d65 100644 +--- a/sound/usb/midi.c ++++ b/sound/usb/midi.c +@@ -1826,6 +1826,28 @@ static int snd_usbmidi_create_endpoints(struct snd_usb_midi *umidi, + return 0; + } + ++static struct usb_ms_endpoint_descriptor *find_usb_ms_endpoint_descriptor( ++ struct usb_host_endpoint *hostep) ++{ ++ unsigned char *extra = hostep->extra; ++ int extralen = hostep->extralen; ++ ++ while (extralen > 3) { ++ struct usb_ms_endpoint_descriptor *ms_ep = ++ (struct usb_ms_endpoint_descriptor *)extra; ++ ++ if (ms_ep->bLength > 3 && ++ ms_ep->bDescriptorType == USB_DT_CS_ENDPOINT && ++ ms_ep->bDescriptorSubtype == UAC_MS_GENERAL) ++ return ms_ep; ++ if (!extra[0]) ++ break; ++ extralen -= extra[0]; ++ extra += extra[0]; ++ } ++ return NULL; ++} ++ + /* + * Returns MIDIStreaming device capabilities. + */ +@@ -1863,11 +1885,8 @@ static int snd_usbmidi_get_ms_info(struct snd_usb_midi *umidi, + ep = get_ep_desc(hostep); + if (!usb_endpoint_xfer_bulk(ep) && !usb_endpoint_xfer_int(ep)) + continue; +- ms_ep = (struct usb_ms_endpoint_descriptor *)hostep->extra; +- if (hostep->extralen < 4 || +- ms_ep->bLength < 4 || +- ms_ep->bDescriptorType != USB_DT_CS_ENDPOINT || +- ms_ep->bDescriptorSubtype != UAC_MS_GENERAL) ++ ms_ep = find_usb_ms_endpoint_descriptor(hostep); ++ if (!ms_ep) + continue; + if (usb_endpoint_dir_out(ep)) { + if (endpoints[epidx].out_ep) { +-- +2.16.4 + diff --git a/patches.suse/ALSA-usb-audio-Fix-mixer-controls-USB-interface-for-.patch b/patches.suse/ALSA-usb-audio-Fix-mixer-controls-USB-interface-for-.patch new file mode 100644 index 0000000..ae7fb6b --- /dev/null +++ b/patches.suse/ALSA-usb-audio-Fix-mixer-controls-USB-interface-for-.patch @@ -0,0 +1,90 @@ +From 0aef31b75272a9894f7205c2c888c7dbc248ce94 Mon Sep 17 00:00:00 2001 +From: Chris Wulff +Date: Sat, 14 Mar 2020 12:54:48 -0400 +Subject: [PATCH] ALSA: usb-audio: Fix mixer controls' USB interface for Kingston HyperX Amp (0951:16d8) +Git-commit: 0aef31b75272a9894f7205c2c888c7dbc248ce94 +Patch-mainline: v5.7-rc1 +References: bsc#1051510 + +Use the USB interface of the mixer that the control +was created on instead of the default control interface. + +This fixes the Kingston HyperX AMP (0951:16d8) which has +controls on two interfaces. + +Signed-off-by: Chris Wulff +Link: https://lore.kernel.org/r/20200314165449.4086-2-crwulff@gmail.com +Signed-off-by: Takashi Iwai + +--- + sound/usb/mixer.c | 17 +++++++++++------ + 1 file changed, 11 insertions(+), 6 deletions(-) + +--- a/sound/usb/mixer.c ++++ b/sound/usb/mixer.c +@@ -307,6 +307,11 @@ static int uac2_ctl_value_size(int val_t + * retrieve a mixer value + */ + ++static inline int mixer_ctrl_intf(struct usb_mixer_interface *mixer) ++{ ++ return get_iface_desc(mixer->hostif)->bInterfaceNumber; ++} ++ + static int get_ctl_value_v1(struct usb_mixer_elem_info *cval, int request, + int validx, int *value_ret) + { +@@ -321,7 +326,7 @@ static int get_ctl_value_v1(struct usb_m + return -EIO; + + while (timeout-- > 0) { +- idx = snd_usb_ctrl_intf(chip) | (cval->head.id << 8); ++ idx = mixer_ctrl_intf(cval->head.mixer) | (cval->head.id << 8); + if (snd_usb_ctl_msg(chip->dev, usb_rcvctrlpipe(chip->dev, 0), request, + USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN, + validx, idx, buf, val_len) >= val_len) { +@@ -366,7 +371,7 @@ static int get_ctl_value_v2(struct usb_m + if (ret) + goto error; + +- idx = snd_usb_ctrl_intf(chip) | (cval->head.id << 8); ++ idx = mixer_ctrl_intf(cval->head.mixer) | (cval->head.id << 8); + ret = snd_usb_ctl_msg(chip->dev, usb_rcvctrlpipe(chip->dev, 0), bRequest, + USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN, + validx, idx, buf, size); +@@ -491,7 +496,7 @@ int snd_usb_mixer_set_ctl_value(struct u + return -EIO; + + while (timeout-- > 0) { +- idx = snd_usb_ctrl_intf(chip) | (cval->head.id << 8); ++ idx = mixer_ctrl_intf(cval->head.mixer) | (cval->head.id << 8); + if (snd_usb_ctl_msg(chip->dev, + usb_sndctrlpipe(chip->dev, 0), request, + USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT, +@@ -1218,7 +1223,7 @@ static int get_min_max_with_quirks(struc + get_ctl_value(cval, UAC_GET_MIN, (cval->control << 8) | minchn, &cval->min) < 0) { + usb_audio_err(cval->head.mixer->chip, + "%d:%d: cannot get min/max values for control %d (id %d)\n", +- cval->head.id, snd_usb_ctrl_intf(cval->head.mixer->chip), ++ cval->head.id, mixer_ctrl_intf(cval->head.mixer), + cval->control, cval->head.id); + return -EINVAL; + } +@@ -1437,7 +1442,7 @@ static int mixer_ctl_connector_get(struc + if (ret) + goto error; + +- idx = snd_usb_ctrl_intf(chip) | (cval->head.id << 8); ++ idx = mixer_ctrl_intf(cval->head.mixer) | (cval->head.id << 8); + if (cval->head.mixer->protocol == UAC_VERSION_2) { + struct uac2_connectors_ctl_blk uac2_conn; + +@@ -3232,7 +3237,7 @@ static void snd_usb_mixer_proc_read(stru + list_for_each_entry(mixer, &chip->mixer_list, list) { + snd_iprintf(buffer, + "USB Mixer: usb_id=0x%08x, ctrlif=%i, ctlerr=%i\n", +- chip->usb_id, snd_usb_ctrl_intf(chip), ++ chip->usb_id, mixer_ctrl_intf(mixer), + mixer->ignore_ctl_error); + snd_iprintf(buffer, "Card: %s\n", chip->card->longname); + for (unitid = 0; unitid < MAX_ID_ELEMS; unitid++) { diff --git a/patches.suse/ALSA-usb-audio-Inform-devices-that-need-delayed-regi.patch b/patches.suse/ALSA-usb-audio-Inform-devices-that-need-delayed-regi.patch new file mode 100644 index 0000000..e13a8db --- /dev/null +++ b/patches.suse/ALSA-usb-audio-Inform-devices-that-need-delayed-regi.patch @@ -0,0 +1,82 @@ +From a4aad5636c7298eecfb60fc9d73933336cb0c4d8 Mon Sep 17 00:00:00 2001 +From: Takashi Iwai +Date: Wed, 25 Mar 2020 11:33:21 +0100 +Subject: [PATCH] ALSA: usb-audio: Inform devices that need delayed registration +Git-commit: a4aad5636c7298eecfb60fc9d73933336cb0c4d8 +Patch-mainline: v5.7-rc1 +References: bsc#1051510 + +The USB-audio driver may call snd_card_register() multiple times as +its probe function is per USB interface while some USB-audio devices +may provide multiple interfaces to assign different streams although +they belong to the same device. This works in most cases but the +registration is racy, hence it may miss the device recognition, +e.g. PA doesn't see certain devices when hotplugged. + +The recent addition of the delayed registration quirk allows to sync +the registration at the last known interface, and the previous commit +added a new module option to allow the dynamic setup for that +purpose. + +Now, this patch tries to find out and notifies for such devices that +require the delayed registration. It shows a message like: + + Found post-registration device assignment: 1234abcd:02 + +If you hit this message, you can pass delayed_register module option +Like: + + snd_usb_audio.delayed_register=1234abcd:02 + +by just copying the last shown entry. If this works, it can be added +statically in the quirk list, registration_quirks[] found at the end +of sound/usb/quirks.c. + +Link: https://lore.kernel.org/r/20200325103322.2508-4-tiwai@suse.de +Signed-off-by: Takashi Iwai + +--- + sound/usb/card.c | 7 +++++++ + sound/usb/stream.c | 3 +++ + sound/usb/usbaudio.h | 2 +- + 3 files changed, 11 insertions(+), 1 deletion(-) + +--- a/sound/usb/card.c ++++ b/sound/usb/card.c +@@ -693,6 +693,13 @@ static int usb_audio_probe(struct usb_in + goto __error; + } + ++ if (chip->need_delayed_register) { ++ dev_info(&dev->dev, ++ "Found post-registration device assignment: %08x:%02x\n", ++ chip->usb_id, ifnum); ++ chip->need_delayed_register = false; /* clear again */ ++ } ++ + /* we are allowed to call snd_card_register() many times, but first + * check to see if a device needs to skip it or do anything special + */ +--- a/sound/usb/stream.c ++++ b/sound/usb/stream.c +@@ -512,6 +512,9 @@ static int __snd_usb_add_audio_stream(st + subs = &as->substream[stream]; + if (subs->ep_num) + continue; ++ if (snd_device_get_state(chip->card, as->pcm) != ++ SNDRV_DEV_BUILD) ++ chip->need_delayed_register = true; + err = snd_pcm_new_stream(as->pcm, stream, 1); + if (err < 0) + return err; +--- a/sound/usb/usbaudio.h ++++ b/sound/usb/usbaudio.h +@@ -44,7 +44,7 @@ struct snd_usb_audio { + wait_queue_head_t shutdown_wait; + unsigned int txfr_quirk:1; /* Subframe boundaries on transfers */ + unsigned int tx_length_quirk:1; /* Put length specifier in transfers */ +- ++ unsigned int need_delayed_register:1; /* warn for delayed registration */ + int num_interfaces; + int num_suspended_intf; + int sample_rate_read_error; diff --git a/patches.suse/ALSA-usb-audio-Parse-source-ID-of-UAC2-effect-unit.patch b/patches.suse/ALSA-usb-audio-Parse-source-ID-of-UAC2-effect-unit.patch new file mode 100644 index 0000000..56863cf --- /dev/null +++ b/patches.suse/ALSA-usb-audio-Parse-source-ID-of-UAC2-effect-unit.patch @@ -0,0 +1,44 @@ +From 60081b35c68ba6a466dee08de581be06999c930a Mon Sep 17 00:00:00 2001 +From: Takashi Iwai +Date: Thu, 13 Feb 2020 12:20:59 +0100 +Subject: [PATCH] ALSA: usb-audio: Parse source ID of UAC2 effect unit +Git-commit: 60081b35c68ba6a466dee08de581be06999c930a +Patch-mainline: v5.7-rc1 +References: bsc#1051510 + +During parsing the input source, we currently cut off at the Effect +Unit node without parsing further its source id. It's no big problem, +so far, but it should be more consistent to parse it properly. + +This patch adds the recursive parsing in parse_term_effect_unit(). +It doesn't add anything in the audio unit parser itself, and the +effect unit itself is still skipped, though. + +Buglink: https://bugzilla.kernel.org/show_bug.cgi?id=206147 +Link: https://lore.kernel.org/r/20200213112059.18745-3-tiwai@suse.de +Signed-off-by: Takashi Iwai + +--- + sound/usb/mixer.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c +index 81b2db0edd5f..56d0878e4999 100644 +--- a/sound/usb/mixer.c ++++ b/sound/usb/mixer.c +@@ -901,6 +901,12 @@ static int parse_term_effect_unit(struct mixer_build *state, + struct usb_audio_term *term, + void *p1, int id) + { ++ struct uac2_effect_unit_descriptor *d = p1; ++ int err; ++ ++ err = __check_input_term(state, d->bSourceID, term); ++ if (err < 0) ++ return err; + term->type = UAC3_EFFECT_UNIT << 16; /* virtual type */ + term->id = id; + return 0; +-- +2.16.4 + diff --git a/patches.suse/ALSA-usb-audio-Rewrite-registration-quirk-handling.patch b/patches.suse/ALSA-usb-audio-Rewrite-registration-quirk-handling.patch new file mode 100644 index 0000000..943fada --- /dev/null +++ b/patches.suse/ALSA-usb-audio-Rewrite-registration-quirk-handling.patch @@ -0,0 +1,101 @@ +From d8695bc5b1fe88305396b1f788d3b5f218e28a30 Mon Sep 17 00:00:00 2001 +From: Takashi Iwai +Date: Wed, 25 Mar 2020 11:33:19 +0100 +Subject: [PATCH] ALSA: usb-audio: Rewrite registration quirk handling +Git-commit: d8695bc5b1fe88305396b1f788d3b5f218e28a30 +Patch-mainline: v5.7-rc1 +References: bsc#1051510 + +A slight refactoring of the registration quirk code. Now it uses the +table lookup for easy additions in future. Also the return type was +changed to bool, and got a few more comments. + +Link: https://lore.kernel.org/r/20200325103322.2508-2-tiwai@suse.de +Signed-off-by: Takashi Iwai + +--- + sound/usb/card.c | 2 +- + sound/usb/quirks.c | 40 ++++++++++++++++++++++++++++++---------- + sound/usb/quirks.h | 3 +-- + 3 files changed, 32 insertions(+), 13 deletions(-) + +diff --git a/sound/usb/card.c b/sound/usb/card.c +index 16bbe2a50fb7..55d563a8154d 100644 +--- a/sound/usb/card.c ++++ b/sound/usb/card.c +@@ -665,7 +665,7 @@ static int usb_audio_probe(struct usb_interface *intf, + /* we are allowed to call snd_card_register() many times, but first + * check to see if a device needs to skip it or do anything special + */ +- if (snd_usb_registration_quirk(chip, ifnum) == 0) { ++ if (!snd_usb_registration_quirk(chip, ifnum)) { + err = snd_card_register(chip->card); + if (err < 0) + goto __error; +diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c +index d605aff801b8..86f192a3043d 100644 +--- a/sound/usb/quirks.c ++++ b/sound/usb/quirks.c +@@ -1809,16 +1809,36 @@ void snd_usb_audioformat_attributes_quirk(struct snd_usb_audio *chip, + } + } + +-int snd_usb_registration_quirk(struct snd_usb_audio *chip, +- int iface) ++/* ++ * registration quirk: ++ * the registration is skipped if a device matches with the given ID, ++ * unless the interface reaches to the defined one. This is for delaying ++ * the registration until the last known interface, so that the card and ++ * devices appear at the same time. ++ */ ++ ++struct registration_quirk { ++ unsigned int usb_id; /* composed via USB_ID() */ ++ unsigned int interface; /* the interface to trigger register */ ++}; ++ ++#define REG_QUIRK_ENTRY(vendor, product, iface) \ ++ { .usb_id = USB_ID(vendor, product), .interface = (iface) } ++ ++static const struct registration_quirk registration_quirks[] = { ++ REG_QUIRK_ENTRY(0x0951, 0x16d8, 2), /* Kingston HyperX AMP */ ++ { 0 } /* terminator */ ++}; ++ ++/* return true if skipping registration */ ++bool snd_usb_registration_quirk(struct snd_usb_audio *chip, int iface) + { +- switch (chip->usb_id) { +- case USB_ID(0x0951, 0x16d8): /* Kingston HyperX AMP */ +- /* Register only when we reach interface 2 so that streams can +- * merge correctly into PCMs from interface 0 +- */ +- return (iface != 2); +- } ++ const struct registration_quirk *q; ++ ++ for (q = registration_quirks; q->usb_id; q++) ++ if (chip->usb_id == q->usb_id) ++ return iface != q->interface; ++ + /* Register as normal */ +- return 0; ++ return false; + } +diff --git a/sound/usb/quirks.h b/sound/usb/quirks.h +index 3afc01eabc7e..c76cf24a640a 100644 +--- a/sound/usb/quirks.h ++++ b/sound/usb/quirks.h +@@ -51,7 +51,6 @@ void snd_usb_audioformat_attributes_quirk(struct snd_usb_audio *chip, + struct audioformat *fp, + int stream); + +-int snd_usb_registration_quirk(struct snd_usb_audio *chip, +- int iface); ++bool snd_usb_registration_quirk(struct snd_usb_audio *chip, int iface); + + #endif /* __USBAUDIO_QUIRKS_H */ +-- +2.16.4 + diff --git a/patches.suse/ALSA-usb-audio-Use-lower-hex-numbers-for-IDs.patch b/patches.suse/ALSA-usb-audio-Use-lower-hex-numbers-for-IDs.patch new file mode 100644 index 0000000..d094b30 --- /dev/null +++ b/patches.suse/ALSA-usb-audio-Use-lower-hex-numbers-for-IDs.patch @@ -0,0 +1,83 @@ +From 8be03a7177c36bfc05bbe9f4949cdeba57f1c2ab Mon Sep 17 00:00:00 2001 +From: Takashi Iwai +Date: Sun, 5 Jan 2020 09:19:00 +0100 +Subject: [PATCH] ALSA: usb-audio: Use lower hex numbers for IDs +Git-commit: 8be03a7177c36bfc05bbe9f4949cdeba57f1c2ab +Patch-mainline: v5.6-rc1 +References: bsc#1111666 + +For consistency reason, make all hex numbers with lower alphabets for +USB ID entries. It improves grep-ability and reduces careless +mistakes. + +Link: https://lore.kernel.org/r/20200105081900.21870-1-tiwai@suse.de +Signed-off-by: Takashi Iwai + +--- + sound/usb/format.c | 8 ++++---- + sound/usb/midi.c | 4 ++-- + sound/usb/quirks.c | 14 +++++++------- + 3 files changed, 13 insertions(+), 13 deletions(-) + +--- a/sound/usb/format.c ++++ b/sound/usb/format.c +@@ -302,10 +302,10 @@ static int line6_parse_audio_format_rate + struct audioformat *fp) + { + switch (chip->usb_id) { +- case USB_ID(0x0E41, 0x4241): /* Line6 Helix */ +- case USB_ID(0x0E41, 0x4242): /* Line6 Helix Rack */ +- case USB_ID(0x0E41, 0x4244): /* Line6 Helix LT */ +- case USB_ID(0x0E41, 0x4246): /* Line6 HX-Stomp */ ++ case USB_ID(0x0e41, 0x4241): /* Line6 Helix */ ++ case USB_ID(0x0e41, 0x4242): /* Line6 Helix Rack */ ++ case USB_ID(0x0e41, 0x4244): /* Line6 Helix LT */ ++ case USB_ID(0x0e41, 0x4246): /* Line6 HX-Stomp */ + /* supported rates: 48Khz */ + kfree(fp->rate_table); + fp->rate_table = kmalloc(sizeof(int), GFP_KERNEL); +--- a/sound/usb/midi.c ++++ b/sound/usb/midi.c +@@ -1408,8 +1408,8 @@ static int snd_usbmidi_out_endpoint_crea + /* + * Some devices only work with 9 bytes packet size: + */ +- case USB_ID(0x0644, 0x800E): /* Tascam US-122L */ +- case USB_ID(0x0644, 0x800F): /* Tascam US-144 */ ++ case USB_ID(0x0644, 0x800e): /* Tascam US-122L */ ++ case USB_ID(0x0644, 0x800f): /* Tascam US-144 */ + ep->max_transfer = 9; + break; + } +--- a/sound/usb/quirks.c ++++ b/sound/usb/quirks.c +@@ -1395,22 +1395,22 @@ bool snd_usb_get_sample_rate_quirk(struc + { + /* devices which do not support reading the sample rate. */ + switch (chip->usb_id) { +- case USB_ID(0x041E, 0x4080): /* Creative Live Cam VF0610 */ +- case USB_ID(0x04D8, 0xFEEA): /* Benchmark DAC1 Pre */ ++ case USB_ID(0x041e, 0x4080): /* Creative Live Cam VF0610 */ ++ case USB_ID(0x04d8, 0xfeea): /* Benchmark DAC1 Pre */ + case USB_ID(0x0556, 0x0014): /* Phoenix Audio TMX320VC */ +- case USB_ID(0x05A3, 0x9420): /* ELP HD USB Camera */ ++ case USB_ID(0x05a3, 0x9420): /* ELP HD USB Camera */ + case USB_ID(0x05a7, 0x1020): /* Bose Companion 5 */ +- case USB_ID(0x074D, 0x3553): /* Outlaw RR2150 (Micronas UAC3553B) */ ++ case USB_ID(0x074d, 0x3553): /* Outlaw RR2150 (Micronas UAC3553B) */ + case USB_ID(0x1395, 0x740a): /* Sennheiser DECT */ + case USB_ID(0x1901, 0x0191): /* GE B850V3 CP2114 audio interface */ +- case USB_ID(0x21B4, 0x0081): /* AudioQuest DragonFly */ ++ case USB_ID(0x21b4, 0x0081): /* AudioQuest DragonFly */ + return true; + } + + /* devices of these vendors don't support reading rate, either */ + switch (USB_ID_VENDOR(chip->usb_id)) { +- case 0x045E: /* MS Lifecam */ +- case 0x047F: /* Plantronics */ ++ case 0x045e: /* MS Lifecam */ ++ case 0x047f: /* Plantronics */ + case 0x1de7: /* Phoenix Audio */ + return true; + } diff --git a/patches.suse/ALSA-usb-audio-add-implicit-fb-quirk-for-MOTU-M-Seri.patch b/patches.suse/ALSA-usb-audio-add-implicit-fb-quirk-for-MOTU-M-Seri.patch new file mode 100644 index 0000000..9f7bc43 --- /dev/null +++ b/patches.suse/ALSA-usb-audio-add-implicit-fb-quirk-for-MOTU-M-Seri.patch @@ -0,0 +1,42 @@ +From c249177944b650816069f6c49b769baaa94339dc Mon Sep 17 00:00:00 2001 +From: Alexander Tsoy +Date: Wed, 15 Jan 2020 18:13:58 +0300 +Subject: [PATCH] ALSA: usb-audio: add implicit fb quirk for MOTU M Series +Git-commit: c249177944b650816069f6c49b769baaa94339dc +Patch-mainline: v5.6-rc1 +References: bsc#1111666 + +This fixes crackling sound during playback. + +Further note: MOTU is known for reusing Product IDs for different +devices or different generations of the device (e.g. MicroBook +I/II/IIc shares a single Product ID). This patch was only tested with +M4 audio interface, but the same Product ID is also used by M2. Hope +it will work for M2 as well. + +Signed-off-by: Alexander Tsoy +Link: https://lore.kernel.org/r/20200115151358.56672-1-alexander@tsoy.me +Signed-off-by: Takashi Iwai + +--- + sound/usb/pcm.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c +index 2f6a80ca36fc..5844a0c9d0db 100644 +--- a/sound/usb/pcm.c ++++ b/sound/usb/pcm.c +@@ -361,6 +361,10 @@ static int set_sync_ep_implicit_fb_quirk(struct snd_usb_substream *subs, + ep = 0x84; + ifnum = 0; + goto add_sync_ep_from_ifnum; ++ case USB_ID(0x07fd, 0x0008): /* MOTU M Series */ ++ ep = 0x81; ++ ifnum = 2; ++ goto add_sync_ep_from_ifnum; + case USB_ID(0x0582, 0x01d8): /* BOSS Katana */ + /* BOSS Katana amplifiers do not need quirks */ + return 0; +-- +2.16.4 + diff --git a/patches.suse/ALSA-usb-audio-add-quirks-for-Line6-Helix-devices-fw.patch b/patches.suse/ALSA-usb-audio-add-quirks-for-Line6-Helix-devices-fw.patch new file mode 100644 index 0000000..f769480 --- /dev/null +++ b/patches.suse/ALSA-usb-audio-add-quirks-for-Line6-Helix-devices-fw.patch @@ -0,0 +1,35 @@ +From b81cbf7abfc94878a3c6f0789f2185ee55b1cc21 Mon Sep 17 00:00:00 2001 +From: Nicola Lunghi +Date: Sat, 25 Jan 2020 15:09:17 +0000 +Subject: [PATCH] ALSA: usb-audio: add quirks for Line6 Helix devices fw>=2.82 +Git-commit: b81cbf7abfc94878a3c6f0789f2185ee55b1cc21 +Patch-mainline: v5.6-rc1 +References: bsc#1111666 + +With firmware 2.82 Line6 changed the usb id of some of the Helix +devices but the quirks is still needed. + +Add it to the quirk list for line6 helix family of devices. + +Thanks to Jens for pointing out the missing ids. + +Signed-off-by: Nicola Lunghi +Link: https://lore.kernel.org/r/20200125150917.5040-1-nick83ola@gmail.com +Signed-off-by: Takashi Iwai + +--- + sound/usb/format.c | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/sound/usb/format.c ++++ b/sound/usb/format.c +@@ -306,6 +306,9 @@ static int line6_parse_audio_format_rate + case USB_ID(0x0e41, 0x4242): /* Line6 Helix Rack */ + case USB_ID(0x0e41, 0x4244): /* Line6 Helix LT */ + case USB_ID(0x0e41, 0x4246): /* Line6 HX-Stomp */ ++ case USB_ID(0x0e41, 0x4248): /* Line6 Helix >= fw 2.82 */ ++ case USB_ID(0x0e41, 0x4249): /* Line6 Helix Rack >= fw 2.82 */ ++ case USB_ID(0x0e41, 0x424a): /* Line6 Helix LT >= fw 2.82 */ + /* supported rates: 48Khz */ + kfree(fp->rate_table); + fp->rate_table = kmalloc(sizeof(int), GFP_KERNEL); diff --git a/patches.suse/ALSA-usb-audio-fix-Corsair-Virtuoso-mixer-label-coll.patch b/patches.suse/ALSA-usb-audio-fix-Corsair-Virtuoso-mixer-label-coll.patch new file mode 100644 index 0000000..198253d --- /dev/null +++ b/patches.suse/ALSA-usb-audio-fix-Corsair-Virtuoso-mixer-label-coll.patch @@ -0,0 +1,62 @@ +From 7d8d3c377cc9731c3924f807c7769177ca3f0865 Mon Sep 17 00:00:00 2001 +From: Chris Boyle +Date: Fri, 27 Dec 2019 10:40:53 +0100 +Subject: [PATCH] ALSA: usb-audio: fix Corsair Virtuoso mixer label collision +Git-commit: 7d8d3c377cc9731c3924f807c7769177ca3f0865 +Patch-mainline: v5.6-rc1 +References: bsc#1111666 + +The Corsair Virtuoso RGB Wireless is a USB headset with a mic and a +sidetone feature. Label its mixer appropriately instead of all +"Headset", so that applications such as Pulseaudio don't just move +the sidetone control when they intend the main Headset control. + +Signed-off-by: Chris Boyle +Link: https://lore.kernel.org/r/20191227094053.GA12167@nova.chris.boyle.name +Signed-off-by: Takashi Iwai + +--- + sound/usb/mixer_maps.c | 20 ++++++++++++++++++++ + 1 file changed, 20 insertions(+) + +diff --git a/sound/usb/mixer_maps.c b/sound/usb/mixer_maps.c +index 73baf398c84a..d094934ae6c5 100644 +--- a/sound/usb/mixer_maps.c ++++ b/sound/usb/mixer_maps.c +@@ -349,6 +349,16 @@ static const struct usbmix_name_map dell_alc4020_map[] = { + { 0 } + }; + ++/* ++ * Corsair Virtuoso calls everything "Headset" without this, leading to ++ * applications moving the sidetone control instead of the main one. ++ */ ++static const struct usbmix_name_map corsair_virtuoso_map[] = { ++ { 3, "Mic Capture" }, ++ { 6, "Sidetone Playback" }, ++ { 0 } ++}; ++ + /* + * Control map entries + */ +@@ -468,6 +478,16 @@ static struct usbmix_ctl_map usbmix_ctl_maps[] = { + .id = USB_ID(0x05a7, 0x1020), + .map = bose_companion5_map, + }, ++ { ++ /* Corsair Virtuoso (wired mode) */ ++ .id = USB_ID(0x1b1c, 0x0a41), ++ .map = corsair_virtuoso_map, ++ }, ++ { ++ /* Corsair Virtuoso (wireless mode) */ ++ .id = USB_ID(0x1b1c, 0x0a42), ++ .map = corsair_virtuoso_map, ++ }, + { 0 } /* terminator */ + }; + +-- +2.16.4 + diff --git a/patches.suse/ALSA-usb-audio-unlock-on-error-in-probe.patch b/patches.suse/ALSA-usb-audio-unlock-on-error-in-probe.patch new file mode 100644 index 0000000..142c798 --- /dev/null +++ b/patches.suse/ALSA-usb-audio-unlock-on-error-in-probe.patch @@ -0,0 +1,35 @@ +From a3afa29942b84b4e2548beacccc3a68b8d77e3dc Mon Sep 17 00:00:00 2001 +From: Dan Carpenter +Date: Wed, 15 Jan 2020 20:46:04 +0300 +Subject: [PATCH] ALSA: usb-audio: unlock on error in probe +Git-commit: a3afa29942b84b4e2548beacccc3a68b8d77e3dc +Patch-mainline: v5.6-rc1 +References: bsc#1111666 + +We need to unlock before we returning on this error path. + +Fixes: 73ac9f5e5b43 ("ALSA: usb-audio: Add boot quirk for MOTU M Series") +Signed-off-by: Dan Carpenter +Link: https://lore.kernel.org/r/20200115174604.rhanfgy4j3uc65cx@kili.mountain +Signed-off-by: Takashi Iwai + +--- + sound/usb/card.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/sound/usb/card.c b/sound/usb/card.c +index 2f582ac7cf78..827fb0bc8b56 100644 +--- a/sound/usb/card.c ++++ b/sound/usb/card.c +@@ -602,7 +602,7 @@ static int usb_audio_probe(struct usb_interface *intf, + if (! chip) { + err = snd_usb_apply_boot_quirk_once(dev, intf, quirk, id); + if (err < 0) +- return err; ++ goto __error; + + /* it's a fresh one. + * now look for an empty slot and create a new card instance +-- +2.16.4 + diff --git a/patches.suse/ALSA-usb-midi-Replace-zero-length-array-with-flexibl.patch b/patches.suse/ALSA-usb-midi-Replace-zero-length-array-with-flexibl.patch new file mode 100644 index 0000000..572d2fc --- /dev/null +++ b/patches.suse/ALSA-usb-midi-Replace-zero-length-array-with-flexibl.patch @@ -0,0 +1,53 @@ +From 6c8019d08e0e84ecad78f726c737dc6a49b58b57 Mon Sep 17 00:00:00 2001 +From: "Gustavo A. R. Silva" +Date: Tue, 11 Feb 2020 13:42:24 -0600 +Subject: [PATCH] ALSA: usb-midi: Replace zero-length array with flexible-array member +Git-commit: 6c8019d08e0e84ecad78f726c737dc6a49b58b57 +Patch-mainline: v5.7-rc1 +References: bsc#1051510 + +The current codebase makes use of the zero-length array language +extension to the C90 standard, but the preferred mechanism to declare +variable-length types such as these ones is a flexible array member[1][2], +introduced in C99: + +struct foo { + int stuff; + struct boo array[]; +}; + +By making use of the mechanism above, we will get a compiler warning +in case the flexible array does not occur last in the structure, which +will help us prevent some kind of undefined behavior bugs from being +inadvertenly introduced[3] to the codebase from now on. + +This issue was found with the help of Coccinelle. + +[1] https://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html +[2] https://github.com/KSPP/linux/issues/21 +[3] commit 76497732932f ("cxgb3/l2t: Fix undefined behaviour") + +Signed-off-by: Gustavo A. R. Silva +Link: https://lore.kernel.org/r/20200211194224.GA9383@embeddedor +Signed-off-by: Takashi Iwai + +--- + sound/usb/midi.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/sound/usb/midi.c b/sound/usb/midi.c +index 392e5fda680c..be5c597ed40c 100644 +--- a/sound/usb/midi.c ++++ b/sound/usb/midi.c +@@ -91,7 +91,7 @@ struct usb_ms_endpoint_descriptor { + __u8 bDescriptorType; + __u8 bDescriptorSubtype; + __u8 bNumEmbMIDIJack; +- __u8 baAssocJackID[0]; ++ __u8 baAssocJackID[]; + } __attribute__ ((packed)); + + struct snd_usb_midi_in_endpoint; +-- +2.16.4 + diff --git a/patches.suse/ALSA-usx2y-Adjust-indentation-in-snd_usX2Y_hwdep_dsp.patch b/patches.suse/ALSA-usx2y-Adjust-indentation-in-snd_usX2Y_hwdep_dsp.patch new file mode 100644 index 0000000..41111e1 --- /dev/null +++ b/patches.suse/ALSA-usx2y-Adjust-indentation-in-snd_usX2Y_hwdep_dsp.patch @@ -0,0 +1,50 @@ +From df4654bd6e42125d9b85ce3a26eaca2935290b98 Mon Sep 17 00:00:00 2001 +From: Nathan Chancellor +Date: Tue, 17 Dec 2019 20:42:57 -0700 +Subject: [PATCH] ALSA: usx2y: Adjust indentation in snd_usX2Y_hwdep_dsp_status +Git-commit: df4654bd6e42125d9b85ce3a26eaca2935290b98 +Patch-mainline: v5.6-rc1 +References: bsc#1051510 + +Clang warns: + +../sound/usb/usx2y/usX2Yhwdep.c:122:3: warning: misleading indentation; +statement is not part of the previous 'if' [-Wmisleading-indentation] + info->version = USX2Y_DRIVER_VERSION; + ^ +../sound/usb/usx2y/usX2Yhwdep.c:120:2: note: previous statement is here + if (us428->chip_status & USX2Y_STAT_CHIP_INIT) + ^ +1 warning generated. + +This warning occurs because there is a space before the tab on this +line. Remove it so that the indentation is consistent with the Linux +kernel coding style and clang no longer warns. + +This was introduced before the beginning of git history so no fixes tag. + +Link: https://github.com/ClangBuiltLinux/linux/issues/831 +Signed-off-by: Nathan Chancellor +Link: https://lore.kernel.org/r/20191218034257.54535-1-natechancellor@gmail.com +Signed-off-by: Takashi Iwai + +--- + sound/usb/usx2y/usX2Yhwdep.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/sound/usb/usx2y/usX2Yhwdep.c b/sound/usb/usx2y/usX2Yhwdep.c +index d1caa8ed9e68..9985fc139487 100644 +--- a/sound/usb/usx2y/usX2Yhwdep.c ++++ b/sound/usb/usx2y/usX2Yhwdep.c +@@ -119,7 +119,7 @@ static int snd_usX2Y_hwdep_dsp_status(struct snd_hwdep *hw, + info->num_dsps = 2; // 0: Prepad Data, 1: FPGA Code + if (us428->chip_status & USX2Y_STAT_CHIP_INIT) + info->chip_ready = 1; +- info->version = USX2Y_DRIVER_VERSION; ++ info->version = USX2Y_DRIVER_VERSION; + return 0; + } + +-- +2.16.4 + diff --git a/patches.suse/ALSA-usx2y-use-for_each_pcm_streams-macro.patch b/patches.suse/ALSA-usx2y-use-for_each_pcm_streams-macro.patch new file mode 100644 index 0000000..8b6a4bd --- /dev/null +++ b/patches.suse/ALSA-usx2y-use-for_each_pcm_streams-macro.patch @@ -0,0 +1,44 @@ +From ffd11d1e7ad4602d5d1c2b4517ad316f7587d4d9 Mon Sep 17 00:00:00 2001 +From: Kuninori Morimoto +Date: Mon, 17 Feb 2020 17:28:51 +0900 +Subject: [PATCH] ALSA: usx2y: use for_each_pcm_streams() macro +Git-commit: ffd11d1e7ad4602d5d1c2b4517ad316f7587d4d9 +Patch-mainline: v5.7-rc1 +References: bsc#1051510 + +Signed-off-by: Kuninori Morimoto +Reviewed-by: Takashi Iwai +Reviewed-by: Ranjani Sridharan +Reviewed-by: Pierre-Louis Bossart +Link: https://lore.kernel.org/r/87sgj9aa8e.wl-kuninori.morimoto.gx@renesas.com +Signed-off-by: Mark Brown +Acked-by: Takashi Iwai + +--- + sound/usb/usx2y/usbusx2yaudio.c | 9 +++++---- + 1 file changed, 5 insertions(+), 4 deletions(-) + +diff --git a/sound/usb/usx2y/usbusx2yaudio.c b/sound/usb/usx2y/usbusx2yaudio.c +index 772f6f3ccbb1..37d290fe9d43 100644 +--- a/sound/usb/usx2y/usbusx2yaudio.c ++++ b/sound/usb/usx2y/usbusx2yaudio.c +@@ -906,11 +906,12 @@ static const struct snd_pcm_ops snd_usX2Y_pcm_ops = + */ + static void usX2Y_audio_stream_free(struct snd_usX2Y_substream **usX2Y_substream) + { +- kfree(usX2Y_substream[SNDRV_PCM_STREAM_PLAYBACK]); +- usX2Y_substream[SNDRV_PCM_STREAM_PLAYBACK] = NULL; ++ int stream; + +- kfree(usX2Y_substream[SNDRV_PCM_STREAM_CAPTURE]); +- usX2Y_substream[SNDRV_PCM_STREAM_CAPTURE] = NULL; ++ for_each_pcm_streams(stream) { ++ kfree(usX2Y_substream[stream]); ++ usX2Y_substream[stream] = NULL; ++ } + } + + static void snd_usX2Y_pcm_private_free(struct snd_pcm *pcm) +-- +2.16.4 + diff --git a/patches.suse/ALSA-via82xx-Fix-endianness-annotations.patch b/patches.suse/ALSA-via82xx-Fix-endianness-annotations.patch new file mode 100644 index 0000000..4663151 --- /dev/null +++ b/patches.suse/ALSA-via82xx-Fix-endianness-annotations.patch @@ -0,0 +1,104 @@ +From c5bb086741c1f5cf05630dab7318433b71abb1f1 Mon Sep 17 00:00:00 2001 +From: Takashi Iwai +Date: Thu, 6 Feb 2020 17:31:50 +0100 +Subject: [PATCH] ALSA: via82xx: Fix endianness annotations +Git-commit: c5bb086741c1f5cf05630dab7318433b71abb1f1 +Patch-mainline: v5.7-rc1 +References: bsc#1051510 + +The internal page tables are in little endian, hence they should be +__le32 type. This fixes the relevant sparse warnings: + sound/pci/via82xx.c:454:60: warning: incorrect type in assignment (different base types) + sound/pci/via82xx.c:454:60: expected unsigned int [usertype] + sound/pci/via82xx.c:454:60: got restricted __le32 [usertype] + .... + +No functional changes, just sparse warning fixes. + +Link: https://lore.kernel.org/r/20200206163152.6073-2-tiwai@suse.de +Signed-off-by: Takashi Iwai + +--- + sound/pci/via82xx.c | 6 ++++-- + sound/pci/via82xx_modem.c | 6 ++++-- + 2 files changed, 8 insertions(+), 4 deletions(-) + +diff --git a/sound/pci/via82xx.c b/sound/pci/via82xx.c +index 799789c8eea9..8b03e2dc503f 100644 +--- a/sound/pci/via82xx.c ++++ b/sound/pci/via82xx.c +@@ -414,6 +414,7 @@ static int build_via_table(struct viadev *dev, struct snd_pcm_substream *substre + { + unsigned int i, idx, ofs, rest; + struct via82xx *chip = snd_pcm_substream_chip(substream); ++ __le32 *pgtbl; + + if (dev->table.area == NULL) { + /* the start of each lists must be aligned to 8 bytes, +@@ -435,6 +436,7 @@ static int build_via_table(struct viadev *dev, struct snd_pcm_substream *substre + /* fill the entries */ + idx = 0; + ofs = 0; ++ pgtbl = (__le32 *)dev->table.area; + for (i = 0; i < periods; i++) { + rest = fragsize; + /* fill descriptors for a period. +@@ -451,7 +453,7 @@ static int build_via_table(struct viadev *dev, struct snd_pcm_substream *substre + return -EINVAL; + } + addr = snd_pcm_sgbuf_get_addr(substream, ofs); +- ((u32 *)dev->table.area)[idx << 1] = cpu_to_le32(addr); ++ pgtbl[idx << 1] = cpu_to_le32(addr); + r = snd_pcm_sgbuf_get_chunk_size(substream, ofs, rest); + rest -= r; + if (! rest) { +@@ -466,7 +468,7 @@ static int build_via_table(struct viadev *dev, struct snd_pcm_substream *substre + "tbl %d: at %d size %d (rest %d)\n", + idx, ofs, r, rest); + */ +- ((u32 *)dev->table.area)[(idx<<1) + 1] = cpu_to_le32(r | flag); ++ pgtbl[(idx<<1) + 1] = cpu_to_le32(r | flag); + dev->idx_table[idx].offset = ofs; + dev->idx_table[idx].size = r; + ofs += r; +diff --git a/sound/pci/via82xx_modem.c b/sound/pci/via82xx_modem.c +index 84e589803e2e..607b7100db1c 100644 +--- a/sound/pci/via82xx_modem.c ++++ b/sound/pci/via82xx_modem.c +@@ -267,6 +267,7 @@ static int build_via_table(struct viadev *dev, struct snd_pcm_substream *substre + { + unsigned int i, idx, ofs, rest; + struct via82xx_modem *chip = snd_pcm_substream_chip(substream); ++ __le32 *pgtbl; + + if (dev->table.area == NULL) { + /* the start of each lists must be aligned to 8 bytes, +@@ -288,6 +289,7 @@ static int build_via_table(struct viadev *dev, struct snd_pcm_substream *substre + /* fill the entries */ + idx = 0; + ofs = 0; ++ pgtbl = (__le32 *)dev->table.area; + for (i = 0; i < periods; i++) { + rest = fragsize; + /* fill descriptors for a period. +@@ -304,7 +306,7 @@ static int build_via_table(struct viadev *dev, struct snd_pcm_substream *substre + return -EINVAL; + } + addr = snd_pcm_sgbuf_get_addr(substream, ofs); +- ((u32 *)dev->table.area)[idx << 1] = cpu_to_le32(addr); ++ pgtbl[idx << 1] = cpu_to_le32(addr); + r = PAGE_SIZE - (ofs % PAGE_SIZE); + if (rest < r) + r = rest; +@@ -321,7 +323,7 @@ static int build_via_table(struct viadev *dev, struct snd_pcm_substream *substre + "tbl %d: at %d size %d (rest %d)\n", + idx, ofs, r, rest); + */ +- ((u32 *)dev->table.area)[(idx<<1) + 1] = cpu_to_le32(r | flag); ++ pgtbl[(idx<<1) + 1] = cpu_to_le32(r | flag); + dev->idx_table[idx].offset = ofs; + dev->idx_table[idx].size = r; + ofs += r; +-- +2.16.4 + diff --git a/patches.suse/ASoC-Intel-mrfld-fix-incorrect-check-on-p-sink.patch b/patches.suse/ASoC-Intel-mrfld-fix-incorrect-check-on-p-sink.patch new file mode 100644 index 0000000..8e6758d --- /dev/null +++ b/patches.suse/ASoC-Intel-mrfld-fix-incorrect-check-on-p-sink.patch @@ -0,0 +1,39 @@ +From f5e056e1e46fcbb5f74ce560792aeb7d57ce79e6 Mon Sep 17 00:00:00 2001 +From: Colin Ian King +Date: Tue, 19 Nov 2019 11:36:40 +0000 +Subject: [PATCH] ASoC: Intel: mrfld: fix incorrect check on p->sink +Git-commit: f5e056e1e46fcbb5f74ce560792aeb7d57ce79e6 +Patch-mainline: v5.7-rc1 +References: bsc#1051510 + +The check on p->sink looks bogus, I believe it should be p->source +since the following code blocks are related to p->source. Fix +this by replacing p->sink with p->source. + +Fixes: 24c8d14192cc ("ASoC: Intel: mrfld: add DSP core controls") +Signed-off-by: Colin Ian King +Addresses-coverity: ("Copy-paste error") +Link: https://lore.kernel.org/r/20191119113640.166940-1-colin.king@canonical.com +Signed-off-by: Mark Brown +Acked-by: Takashi Iwai + +--- + sound/soc/intel/atom/sst-atom-controls.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/sound/soc/intel/atom/sst-atom-controls.c b/sound/soc/intel/atom/sst-atom-controls.c +index baef461a99f1..f883c9340eee 100644 +--- a/sound/soc/intel/atom/sst-atom-controls.c ++++ b/sound/soc/intel/atom/sst-atom-controls.c +@@ -1333,7 +1333,7 @@ int sst_send_pipe_gains(struct snd_soc_dai *dai, int stream, int mute) + dai->capture_widget->name); + w = dai->capture_widget; + snd_soc_dapm_widget_for_each_source_path(w, p) { +- if (p->connected && !p->connected(w, p->sink)) ++ if (p->connected && !p->connected(w, p->source)) + continue; + + if (p->connect && p->source->power && +-- +2.16.4 + diff --git a/patches.suse/ASoC-Intel-mrfld-return-error-codes-when-an-error-oc.patch b/patches.suse/ASoC-Intel-mrfld-return-error-codes-when-an-error-oc.patch new file mode 100644 index 0000000..795b51f --- /dev/null +++ b/patches.suse/ASoC-Intel-mrfld-return-error-codes-when-an-error-oc.patch @@ -0,0 +1,42 @@ +From 3025571edd9df653e1ad649f0638368a39d1bbb5 Mon Sep 17 00:00:00 2001 +From: Colin Ian King +Date: Sat, 8 Feb 2020 22:07:20 +0000 +Subject: [PATCH] ASoC: Intel: mrfld: return error codes when an error occurs +Git-commit: 3025571edd9df653e1ad649f0638368a39d1bbb5 +Patch-mainline: v5.7-rc1 +References: bsc#1051510 + +Currently function sst_platform_get_resources always returns zero and +error return codes set by the function are never returned. Fix this +by returning the error return code in variable ret rather than the +hard coded zero. + +Addresses-coverity: ("Unused value") +Fixes: f533a035e4da ("ASoC: Intel: mrfld - create separate module for pci part") +Signed-off-by: Colin Ian King +Acked-by: Cezary Rojewski +Acked-by: Pierre-Louis Bossart +Link: https://lore.kernel.org/r/20200208220720.36657-1-colin.king@canonical.com +Signed-off-by: Mark Brown +Acked-by: Takashi Iwai + +--- + sound/soc/intel/atom/sst/sst_pci.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/sound/soc/intel/atom/sst/sst_pci.c b/sound/soc/intel/atom/sst/sst_pci.c +index d952719bc098..5862fe968083 100644 +--- a/sound/soc/intel/atom/sst/sst_pci.c ++++ b/sound/soc/intel/atom/sst/sst_pci.c +@@ -99,7 +99,7 @@ static int sst_platform_get_resources(struct intel_sst_drv *ctx) + dev_dbg(ctx->dev, "DRAM Ptr %p\n", ctx->dram); + do_release_regions: + pci_release_regions(pci); +- return 0; ++ return ret; + } + + /* +-- +2.16.4 + diff --git a/patches.suse/ASoC-dapm-Correct-DAPM-handling-of-active-widgets-du.patch b/patches.suse/ASoC-dapm-Correct-DAPM-handling-of-active-widgets-du.patch new file mode 100644 index 0000000..66ae095 --- /dev/null +++ b/patches.suse/ASoC-dapm-Correct-DAPM-handling-of-active-widgets-du.patch @@ -0,0 +1,47 @@ +From 9b3193089e77d3b59b045146ff1c770dd899acb1 Mon Sep 17 00:00:00 2001 +From: Charles Keepax +Date: Fri, 28 Feb 2020 15:31:45 +0000 +Subject: [PATCH] ASoC: dapm: Correct DAPM handling of active widgets during shutdown +Git-commit: 9b3193089e77d3b59b045146ff1c770dd899acb1 +Patch-mainline: v5.6-rc5 +References: bsc#1051510 + +commit c2caa4da46a4 ("ASoC: Fix widget powerdown on shutdown") added a +set of the power state during snd_soc_dapm_shutdown to ensure the +widgets powered off. However, when commit 39eb5fd13dff +("asoc: dapm: Delay w->power update until the changes are written") +added the new_power member of the widget structure, to differentiate +between the current power state and the target power state, it did not +update the shutdown to use the new_power member. + +As new_power has not updated it will be left in the state set by the +last DAPM sequence, ie. 1 for active widgets. So as the DAPM sequence +for the shutdown proceeds it will turn the widgets on (despite them +already being on) rather than turning them off. + +Fixes: 39eb5fd13dff ("ASoC: dapm: Delay w->power update until the changes are written") +Signed-off-by: Charles Keepax +Link: https://lore.kernel.org/r/20200228153145.21013-1-ckeepax@opensource.cirrus.com +Signed-off-by: Mark Brown +Acked-by: Takashi Iwai + +--- + sound/soc/soc-dapm.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c +index 9b130561d562..9fb54e6fe254 100644 +--- a/sound/soc/soc-dapm.c ++++ b/sound/soc/soc-dapm.c +@@ -4772,7 +4772,7 @@ static void soc_dapm_shutdown_dapm(struct snd_soc_dapm_context *dapm) + continue; + if (w->power) { + dapm_seq_insert(w, &down_list, false); +- w->power = 0; ++ w->new_power = 0; + powerdown = 1; + } + } +-- +2.16.4 + diff --git a/patches.suse/ASoC-jz4740-i2s-Fix-divider-written-at-incorrect-off.patch b/patches.suse/ASoC-jz4740-i2s-Fix-divider-written-at-incorrect-off.patch new file mode 100644 index 0000000..72a5e1d --- /dev/null +++ b/patches.suse/ASoC-jz4740-i2s-Fix-divider-written-at-incorrect-off.patch @@ -0,0 +1,38 @@ +From 9401d5aa328e64617d87abd59af1c91cace4c3e4 Mon Sep 17 00:00:00 2001 +From: Paul Cercueil +Date: Fri, 6 Mar 2020 23:29:27 +0100 +Subject: [PATCH] ASoC: jz4740-i2s: Fix divider written at incorrect offset in register +Git-commit: 9401d5aa328e64617d87abd59af1c91cace4c3e4 +Patch-mainline: v5.7-rc1 +References: bsc#1051510 + +The 4-bit divider value was written at offset 8, while the jz4740 +programming manual locates it at offset 0. + +Fixes: 26b0aad80a86 ("ASoC: jz4740: Add dynamic sampling rate support to jz4740-i2s") +Signed-off-by: Paul Cercueil +Cc: stable@vger.kernel.org +Link: https://lore.kernel.org/r/20200306222931.39664-2-paul@crapouillou.net +Signed-off-by: Mark Brown +Acked-by: Takashi Iwai + +--- + sound/soc/jz4740/jz4740-i2s.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/sound/soc/jz4740/jz4740-i2s.c b/sound/soc/jz4740/jz4740-i2s.c +index 9d5405881209..434737b2b2b2 100644 +--- a/sound/soc/jz4740/jz4740-i2s.c ++++ b/sound/soc/jz4740/jz4740-i2s.c +@@ -83,7 +83,7 @@ + #define JZ_AIC_I2S_STATUS_BUSY BIT(2) + + #define JZ_AIC_CLK_DIV_MASK 0xf +-#define I2SDIV_DV_SHIFT 8 ++#define I2SDIV_DV_SHIFT 0 + #define I2SDIV_DV_MASK (0xf << I2SDIV_DV_SHIFT) + #define I2SDIV_IDV_SHIFT 8 + #define I2SDIV_IDV_MASK (0xf << I2SDIV_IDV_SHIFT) +-- +2.16.4 + diff --git a/patches.suse/ASoC-pcm-Fix-possible-buffer-overflow-in-dpcm-state-.patch b/patches.suse/ASoC-pcm-Fix-possible-buffer-overflow-in-dpcm-state-.patch new file mode 100644 index 0000000..6de3816 --- /dev/null +++ b/patches.suse/ASoC-pcm-Fix-possible-buffer-overflow-in-dpcm-state-.patch @@ -0,0 +1,82 @@ +From 6c89ffea60aa3b2a33ae7987de1e84bfb89e4c9e Mon Sep 17 00:00:00 2001 +From: Takashi Iwai +Date: Tue, 18 Feb 2020 12:17:37 +0100 +Subject: [PATCH] ASoC: pcm: Fix possible buffer overflow in dpcm state sysfs output +Git-commit: 6c89ffea60aa3b2a33ae7987de1e84bfb89e4c9e +Patch-mainline: v5.6-rc5 +References: bsc#1051510 + +dpcm_show_state() invokes multiple snprintf() calls to concatenate +formatted strings on the fixed size buffer. The usage of snprintf() +is supposed for avoiding the buffer overflow, but it doesn't work as +expected because snprintf() doesn't return the actual output size but +the size to be written. + +Fix this bug by replacing all snprintf() calls with scnprintf() +calls. + +Fixes: f86dcef87b77 ("ASoC: dpcm: Add debugFS support for DPCM") +Signed-off-by: Takashi Iwai +Acked-by: Cezary Rojewski +Link: https://lore.kernel.org/r/20200218111737.14193-4-tiwai@suse.de +Signed-off-by: Mark Brown + +--- + sound/soc/soc-pcm.c | 16 ++++++++-------- + 1 file changed, 8 insertions(+), 8 deletions(-) + +--- a/sound/soc/soc-pcm.c ++++ b/sound/soc/soc-pcm.c +@@ -2956,16 +2956,16 @@ static ssize_t dpcm_show_state(struct sn + ssize_t offset = 0; + + /* FE state */ +- offset += snprintf(buf + offset, size - offset, ++ offset += scnprintf(buf + offset, size - offset, + "[%s - %s]\n", fe->dai_link->name, + stream ? "Capture" : "Playback"); + +- offset += snprintf(buf + offset, size - offset, "State: %s\n", ++ offset += scnprintf(buf + offset, size - offset, "State: %s\n", + dpcm_state_string(fe->dpcm[stream].state)); + + if ((fe->dpcm[stream].state >= SND_SOC_DPCM_STATE_HW_PARAMS) && + (fe->dpcm[stream].state <= SND_SOC_DPCM_STATE_STOP)) +- offset += snprintf(buf + offset, size - offset, ++ offset += scnprintf(buf + offset, size - offset, + "Hardware Params: " + "Format = %s, Channels = %d, Rate = %d\n", + snd_pcm_format_name(params_format(params)), +@@ -2973,10 +2973,10 @@ static ssize_t dpcm_show_state(struct sn + params_rate(params)); + + /* BEs state */ +- offset += snprintf(buf + offset, size - offset, "Backends:\n"); ++ offset += scnprintf(buf + offset, size - offset, "Backends:\n"); + + if (list_empty(&fe->dpcm[stream].be_clients)) { +- offset += snprintf(buf + offset, size - offset, ++ offset += scnprintf(buf + offset, size - offset, + " No active DSP links\n"); + goto out; + } +@@ -2985,16 +2985,16 @@ static ssize_t dpcm_show_state(struct sn + struct snd_soc_pcm_runtime *be = dpcm->be; + params = &dpcm->hw_params; + +- offset += snprintf(buf + offset, size - offset, ++ offset += scnprintf(buf + offset, size - offset, + "- %s\n", be->dai_link->name); + +- offset += snprintf(buf + offset, size - offset, ++ offset += scnprintf(buf + offset, size - offset, + " State: %s\n", + dpcm_state_string(be->dpcm[stream].state)); + + if ((be->dpcm[stream].state >= SND_SOC_DPCM_STATE_HW_PARAMS) && + (be->dpcm[stream].state <= SND_SOC_DPCM_STATE_STOP)) +- offset += snprintf(buf + offset, size - offset, ++ offset += scnprintf(buf + offset, size - offset, + " Hardware Params: " + "Format = %s, Channels = %d, Rate = %d\n", + snd_pcm_format_name(params_format(params)), diff --git a/patches.suse/ASoC-pcm-update-FE-BE-trigger-order-based-on-the-com.patch b/patches.suse/ASoC-pcm-update-FE-BE-trigger-order-based-on-the-com.patch new file mode 100644 index 0000000..45de1a5 --- /dev/null +++ b/patches.suse/ASoC-pcm-update-FE-BE-trigger-order-based-on-the-com.patch @@ -0,0 +1,185 @@ +From acbf27746ecfa96b290b54cc7f05273482ea128a Mon Sep 17 00:00:00 2001 +From: Ranjani Sridharan +Date: Mon, 4 Nov 2019 14:48:11 -0800 +Subject: [PATCH] ASoC: pcm: update FE/BE trigger order based on the command +Git-commit: acbf27746ecfa96b290b54cc7f05273482ea128a +Patch-mainline: v5.5-rc1 +References: bsc#1051510 + +Currently, the trigger orders SND_SOC_DPCM_TRIGGER_PRE/POST +determine the order in which FE DAI and BE DAI are triggered. +In the case of SND_SOC_DPCM_TRIGGER_PRE, the FE DAI is +triggered before the BE DAI and in the case of +SND_SOC_DPCM_TRIGGER_POST, the BE DAI is triggered before +the FE DAI. And this order remains the same irrespective of the +trigger command. + +In the case of the SOF driver, during playback, the FW +expects the BE DAI to be triggered before the FE DAI during +the START trigger. The BE DAI trigger handles the starting of +Link DMA and so it must be started before the FE DAI is started +to prevent xruns during pause/release. This can be addressed +by setting the trigger order for the FE dai link to +SND_SOC_DPCM_TRIGGER_POST. But during the STOP trigger, +the FW expects the FE DAI to be triggered before the BE DAI. +Retaining the same order during the START and STOP commands, +results in FW error as the DAI component in the FW is still +active. + +The issue can be fixed by mirroring the trigger order of +FE and BE DAI's during the START and STOP trigger. So, with the +trigger order set to SND_SOC_DPCM_TRIGGER_PRE, the FE DAI will be +trigger first during SNDRV_PCM_TRIGGER_START/STOP/RESUME +and the BE DAI will be triggered first during the +STOP/SUSPEND/PAUSE commands. Conversely, with the trigger order +set to SND_SOC_DPCM_TRIGGER_POST, the BE DAI will be triggered +first during the SNDRV_PCM_TRIGGER_START/STOP/RESUME commands +and the FE DAI will be triggered first during the +SNDRV_PCM_TRIGGER_STOP/SUSPEND/PAUSE commands. + +Signed-off-by: Ranjani Sridharan +Signed-off-by: Pierre-Louis Bossart +Link: https://lore.kernel.org/r/20191104224812.3393-2-ranjani.sridharan@linux.intel.com +Signed-off-by: Mark Brown +Acked-by: Takashi Iwai + +--- + sound/soc/soc-pcm.c | 95 ++++++++++++++++++++++++++++++++++++++--------------- + 1 file changed, 68 insertions(+), 27 deletions(-) + +diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c +index 8655df6a6089..1c00119b72e3 100644 +--- a/sound/soc/soc-pcm.c ++++ b/sound/soc/soc-pcm.c +@@ -2322,42 +2322,81 @@ int dpcm_be_dai_trigger(struct snd_soc_pcm_runtime *fe, int stream, + } + EXPORT_SYMBOL_GPL(dpcm_be_dai_trigger); + ++static int dpcm_dai_trigger_fe_be(struct snd_pcm_substream *substream, ++ int cmd, bool fe_first) ++{ ++ struct snd_soc_pcm_runtime *fe = substream->private_data; ++ int ret; ++ ++ /* call trigger on the frontend before the backend. */ ++ if (fe_first) { ++ dev_dbg(fe->dev, "ASoC: pre trigger FE %s cmd %d\n", ++ fe->dai_link->name, cmd); ++ ++ ret = soc_pcm_trigger(substream, cmd); ++ if (ret < 0) ++ return ret; ++ ++ ret = dpcm_be_dai_trigger(fe, substream->stream, cmd); ++ return ret; ++ } ++ ++ /* call trigger on the frontend after the backend. */ ++ ret = dpcm_be_dai_trigger(fe, substream->stream, cmd); ++ if (ret < 0) ++ return ret; ++ ++ dev_dbg(fe->dev, "ASoC: post trigger FE %s cmd %d\n", ++ fe->dai_link->name, cmd); ++ ++ ret = soc_pcm_trigger(substream, cmd); ++ ++ return ret; ++} ++ + static int dpcm_fe_dai_do_trigger(struct snd_pcm_substream *substream, int cmd) + { + struct snd_soc_pcm_runtime *fe = substream->private_data; +- int stream = substream->stream, ret; ++ int stream = substream->stream; ++ int ret = 0; + enum snd_soc_dpcm_trigger trigger = fe->dai_link->trigger[stream]; + + fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE; + + switch (trigger) { + case SND_SOC_DPCM_TRIGGER_PRE: +- /* call trigger on the frontend before the backend. */ +- +- dev_dbg(fe->dev, "ASoC: pre trigger FE %s cmd %d\n", +- fe->dai_link->name, cmd); +- +- ret = soc_pcm_trigger(substream, cmd); +- if (ret < 0) { +- dev_err(fe->dev,"ASoC: trigger FE failed %d\n", ret); +- goto out; ++ switch (cmd) { ++ case SNDRV_PCM_TRIGGER_START: ++ case SNDRV_PCM_TRIGGER_RESUME: ++ case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: ++ ret = dpcm_dai_trigger_fe_be(substream, cmd, true); ++ break; ++ case SNDRV_PCM_TRIGGER_STOP: ++ case SNDRV_PCM_TRIGGER_SUSPEND: ++ case SNDRV_PCM_TRIGGER_PAUSE_PUSH: ++ ret = dpcm_dai_trigger_fe_be(substream, cmd, false); ++ break; ++ default: ++ ret = -EINVAL; ++ break; + } +- +- ret = dpcm_be_dai_trigger(fe, substream->stream, cmd); + break; + case SND_SOC_DPCM_TRIGGER_POST: +- /* call trigger on the frontend after the backend. */ +- +- ret = dpcm_be_dai_trigger(fe, substream->stream, cmd); +- if (ret < 0) { +- dev_err(fe->dev,"ASoC: trigger FE failed %d\n", ret); +- goto out; ++ switch (cmd) { ++ case SNDRV_PCM_TRIGGER_START: ++ case SNDRV_PCM_TRIGGER_RESUME: ++ case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: ++ ret = dpcm_dai_trigger_fe_be(substream, cmd, false); ++ break; ++ case SNDRV_PCM_TRIGGER_STOP: ++ case SNDRV_PCM_TRIGGER_SUSPEND: ++ case SNDRV_PCM_TRIGGER_PAUSE_PUSH: ++ ret = dpcm_dai_trigger_fe_be(substream, cmd, true); ++ break; ++ default: ++ ret = -EINVAL; ++ break; + } +- +- dev_dbg(fe->dev, "ASoC: post trigger FE %s cmd %d\n", +- fe->dai_link->name, cmd); +- +- ret = soc_pcm_trigger(substream, cmd); + break; + case SND_SOC_DPCM_TRIGGER_BESPOKE: + /* bespoke trigger() - handles both FE and BEs */ +@@ -2366,10 +2405,6 @@ static int dpcm_fe_dai_do_trigger(struct snd_pcm_substream *substream, int cmd) + fe->dai_link->name, cmd); + + ret = soc_pcm_bespoke_trigger(substream, cmd); +- if (ret < 0) { +- dev_err(fe->dev,"ASoC: trigger FE failed %d\n", ret); +- goto out; +- } + break; + default: + dev_err(fe->dev, "ASoC: invalid trigger cmd %d for %s\n", cmd, +@@ -2378,6 +2413,12 @@ static int dpcm_fe_dai_do_trigger(struct snd_pcm_substream *substream, int cmd) + goto out; + } + ++ if (ret < 0) { ++ dev_err(fe->dev, "ASoC: trigger FE cmd: %d failed: %d\n", ++ cmd, ret); ++ goto out; ++ } ++ + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: + case SNDRV_PCM_TRIGGER_RESUME: +-- +2.16.4 + diff --git a/patches.suse/ASoC-pcm512x-Fix-unbalanced-regulator-enable-call-in.patch b/patches.suse/ASoC-pcm512x-Fix-unbalanced-regulator-enable-call-in.patch new file mode 100644 index 0000000..b6579bd --- /dev/null +++ b/patches.suse/ASoC-pcm512x-Fix-unbalanced-regulator-enable-call-in.patch @@ -0,0 +1,51 @@ +From ac0a68997935c4acb92eaae5ad8982e0bb432d56 Mon Sep 17 00:00:00 2001 +From: Matthias Reichl +Date: Thu, 20 Feb 2020 21:29:56 +0100 +Subject: [PATCH] ASoC: pcm512x: Fix unbalanced regulator enable call in probe error path +Git-commit: ac0a68997935c4acb92eaae5ad8982e0bb432d56 +Patch-mainline: v5.6-rc5 +References: bsc#1051510 + +When we get a clock error during probe we have to call +regulator_bulk_disable before bailing out, otherwise we trigger +a warning in regulator_put. + +Fix this by using "goto err" like in the error cases above. + +Fixes: 5a3af1293194d ("ASoC: pcm512x: Add PCM512x driver") +Signed-off-by: Matthias Reichl +Reviewed-by: Pierre-Louis Bossart +Link: https://lore.kernel.org/r/20200220202956.29233-1-hias@horus.com +Signed-off-by: Mark Brown +Acked-by: Takashi Iwai + +--- + sound/soc/codecs/pcm512x.c | 8 +++++--- + 1 file changed, 5 insertions(+), 3 deletions(-) + +diff --git a/sound/soc/codecs/pcm512x.c b/sound/soc/codecs/pcm512x.c +index 861210f6bf4f..4cbef9affffd 100644 +--- a/sound/soc/codecs/pcm512x.c ++++ b/sound/soc/codecs/pcm512x.c +@@ -1564,13 +1564,15 @@ int pcm512x_probe(struct device *dev, struct regmap *regmap) + } + + pcm512x->sclk = devm_clk_get(dev, NULL); +- if (PTR_ERR(pcm512x->sclk) == -EPROBE_DEFER) +- return -EPROBE_DEFER; ++ if (PTR_ERR(pcm512x->sclk) == -EPROBE_DEFER) { ++ ret = -EPROBE_DEFER; ++ goto err; ++ } + if (!IS_ERR(pcm512x->sclk)) { + ret = clk_prepare_enable(pcm512x->sclk); + if (ret != 0) { + dev_err(dev, "Failed to enable SCLK: %d\n", ret); +- return ret; ++ goto err; + } + } + +-- +2.16.4 + diff --git a/patches.suse/ASoC-sun8i-codec-Remove-unused-dev-from-codec-struct.patch b/patches.suse/ASoC-sun8i-codec-Remove-unused-dev-from-codec-struct.patch new file mode 100644 index 0000000..a96b813 --- /dev/null +++ b/patches.suse/ASoC-sun8i-codec-Remove-unused-dev-from-codec-struct.patch @@ -0,0 +1,45 @@ +From 150cbf8e66ec86966c13fd7a0e3de8813bca03d8 Mon Sep 17 00:00:00 2001 +From: Samuel Holland +Date: Mon, 17 Feb 2020 00:42:20 -0600 +Subject: [PATCH] ASoC: sun8i-codec: Remove unused dev from codec struct +Git-commit: 150cbf8e66ec86966c13fd7a0e3de8813bca03d8 +Patch-mainline: v5.7-rc1 +References: bsc#1051510 + +This field is not used anywhere in the driver, so remove it. + +Fixes: 36c684936fae ("ASoC: Add sun8i digital audio codec") +Signed-off-by: Samuel Holland +Acked-by: Chen-Yu Tsai +Link: https://lore.kernel.org/r/20200217064250.15516-5-samuel@sholland.org +Signed-off-by: Mark Brown +Acked-by: Takashi Iwai + +--- + sound/soc/sunxi/sun8i-codec.c | 3 --- + 1 file changed, 3 deletions(-) + +diff --git a/sound/soc/sunxi/sun8i-codec.c b/sound/soc/sunxi/sun8i-codec.c +index 55798bc8eae2..41471bd01042 100644 +--- a/sound/soc/sunxi/sun8i-codec.c ++++ b/sound/soc/sunxi/sun8i-codec.c +@@ -85,7 +85,6 @@ + #define SUN8I_AIF1CLK_CTRL_AIF1_BCLK_DIV_MASK GENMASK(12, 9) + + struct sun8i_codec { +- struct device *dev; + struct regmap *regmap; + struct clk *clk_module; + struct clk *clk_bus; +@@ -541,8 +540,6 @@ static int sun8i_codec_probe(struct platform_device *pdev) + if (!scodec) + return -ENOMEM; + +- scodec->dev = &pdev->dev; +- + scodec->clk_module = devm_clk_get(&pdev->dev, "mod"); + if (IS_ERR(scodec->clk_module)) { + dev_err(&pdev->dev, "Failed to get the module clock\n"); +-- +2.16.4 + diff --git a/patches.suse/ASoC-topology-Fix-memleak-in-soc_tplg_link_elems_loa.patch b/patches.suse/ASoC-topology-Fix-memleak-in-soc_tplg_link_elems_loa.patch new file mode 100644 index 0000000..85d3045 --- /dev/null +++ b/patches.suse/ASoC-topology-Fix-memleak-in-soc_tplg_link_elems_loa.patch @@ -0,0 +1,43 @@ +From 2b2d5c4db732c027a14987cfccf767dac1b45170 Mon Sep 17 00:00:00 2001 +From: Dragos Tarcatu +Date: Fri, 7 Feb 2020 20:53:24 +0200 +Subject: [PATCH] ASoC: topology: Fix memleak in soc_tplg_link_elems_load() +Git-commit: 2b2d5c4db732c027a14987cfccf767dac1b45170 +Patch-mainline: v5.6-rc5 +References: bsc#1051510 + +If soc_tplg_link_config() fails, _link needs to be freed in case of +topology ABI version mismatch. However the current code is returning +directly and ends up leaking memory in this case. +This patch fixes that. + +Fixes: 593d9e52f9bb ("ASoC: topology: Add support to configure existing physical DAI links") +Signed-off-by: Dragos Tarcatu +Link: https://lore.kernel.org/r/20200207185325.22320-2-dragos_tarcatu@mentor.com +Signed-off-by: Mark Brown +Acked-by: Takashi Iwai + +--- + sound/soc/soc-topology.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/sound/soc/soc-topology.c b/sound/soc/soc-topology.c +index 107ba3ed5440..953517a73298 100644 +--- a/sound/soc/soc-topology.c ++++ b/sound/soc/soc-topology.c +@@ -2376,8 +2376,11 @@ static int soc_tplg_link_elems_load(struct soc_tplg *tplg, + } + + ret = soc_tplg_link_config(tplg, _link); +- if (ret < 0) ++ if (ret < 0) { ++ if (!abi_match) ++ kfree(_link); + return ret; ++ } + + /* offset by version-specific struct size and + * real priv data size +-- +2.16.4 + diff --git a/patches.suse/Btrfs-do-not-reset-bio-bi_ops-while-writing-bio.patch b/patches.suse/Btrfs-do-not-reset-bio-bi_ops-while-writing-bio.patch new file mode 100644 index 0000000..48c0bd6 --- /dev/null +++ b/patches.suse/Btrfs-do-not-reset-bio-bi_ops-while-writing-bio.patch @@ -0,0 +1,40 @@ +From 5f14efd3d437205143dcffcf776e0122eae1755a Mon Sep 17 00:00:00 2001 +From: Liu Bo +Date: Wed, 23 Aug 2017 12:15:09 -0600 +Patch-mainline: v4.14 +Git-commit: 5f14efd3d437205143dcffcf776e0122eae1755a +References: bsc#1168273 +Subject: [PATCH] Btrfs: do not reset bio->bi_ops while writing bio + +flush_epd_write_bio() sets bio->bi_opf by itself to honor REQ_SYNC, +but it's not needed at all since bio->bi_opf has set up properly in +both __extent_writepage() and write_one_eb(), and in the case of +write_one_eb(), it also sets REQ_META, which we will lose in +flush_epd_write_bio(). + +This remove this unnecessary bio->bi_opf setting. + +Signed-off-by: Liu Bo +Reviewed-by: David Sterba +Signed-off-by: David Sterba +--- + fs/btrfs/extent_io.c | 3 --- + 1 file changed, 3 deletions(-) + +diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c +index 4ead6da5a645..3738d245518c 100644 +--- a/fs/btrfs/extent_io.c ++++ b/fs/btrfs/extent_io.c +@@ -4062,9 +4062,6 @@ static void flush_epd_write_bio(struct extent_page_data *epd) + if (epd->bio) { + int ret; + +- bio_set_op_attrs(epd->bio, REQ_OP_WRITE, +- epd->sync_io ? REQ_SYNC : 0); +- + ret = submit_one_bio(epd->bio, 0, epd->bio_flags); + BUG_ON(ret < 0); /* -ENOMEM */ + epd->bio = NULL; +-- +2.26.0 + diff --git a/patches.suse/Btrfs-fix-block-group-remaining-RO-forever-after-err.patch b/patches.suse/Btrfs-fix-block-group-remaining-RO-forever-after-err.patch index 7e8aa64..38453c5 100644 --- a/patches.suse/Btrfs-fix-block-group-remaining-RO-forever-after-err.patch +++ b/patches.suse/Btrfs-fix-block-group-remaining-RO-forever-after-err.patch @@ -37,16 +37,14 @@ Fixes: f0e9b7d6401959 ("Btrfs: fix race setting block group readonly during devi Signed-off-by: Filipe Manana Signed-off-by: David Sterba --- - fs/btrfs/ordered-data.c | 6 +----- - fs/btrfs/ordered-data.h | 2 +- - fs/btrfs/scrub.c | 39 --------------------------------------- + fs/btrfs/ordered-data.c | 6 +----- + fs/btrfs/ordered-data.h | 2 +- + fs/btrfs/scrub.c | 39 --------------------------------------- 3 files changed, 2 insertions(+), 45 deletions(-) -diff --git a/fs/btrfs/ordered-data.c b/fs/btrfs/ordered-data.c -index c6f5f7e..a098632 100644 --- a/fs/btrfs/ordered-data.c +++ b/fs/btrfs/ordered-data.c -@@ -737,12 +737,11 @@ u64 btrfs_wait_ordered_extents(struct btrfs_root *root, u64 nr, +@@ -745,12 +745,11 @@ u64 btrfs_wait_ordered_extents(struct bt return count; } @@ -60,7 +58,7 @@ index c6f5f7e..a098632 100644 u64 done; INIT_LIST_HEAD(&splice); -@@ -762,7 +761,6 @@ u64 btrfs_wait_ordered_roots(struct btrfs_fs_info *fs_info, u64 nr, +@@ -770,7 +769,6 @@ u64 btrfs_wait_ordered_roots(struct btrf done = btrfs_wait_ordered_extents(root, nr, range_start, range_len); btrfs_put_fs_root(root); @@ -68,7 +66,7 @@ index c6f5f7e..a098632 100644 spin_lock(&fs_info->ordered_root_lock); if (nr != U64_MAX) { -@@ -772,8 +770,6 @@ u64 btrfs_wait_ordered_roots(struct btrfs_fs_info *fs_info, u64 nr, +@@ -780,8 +778,6 @@ u64 btrfs_wait_ordered_roots(struct btrf list_splice_tail(&splice, &fs_info->ordered_roots); spin_unlock(&fs_info->ordered_root_lock); mutex_unlock(&fs_info->ordered_operations_mutex); @@ -77,11 +75,9 @@ index c6f5f7e..a098632 100644 } /* -diff --git a/fs/btrfs/ordered-data.h b/fs/btrfs/ordered-data.h -index 56c4c0e..bc08fb1 100644 --- a/fs/btrfs/ordered-data.h +++ b/fs/btrfs/ordered-data.h -@@ -202,7 +202,7 @@ int btrfs_find_ordered_sum(struct inode *inode, u64 offset, u64 disk_bytenr, +@@ -202,7 +202,7 @@ int btrfs_find_ordered_sum(struct inode u32 *sum, int len); u64 btrfs_wait_ordered_extents(struct btrfs_root *root, u64 nr, const u64 range_start, const u64 range_len); @@ -90,14 +86,12 @@ index 56c4c0e..bc08fb1 100644 const u64 range_start, const u64 range_len); void btrfs_get_logged_extents(struct btrfs_inode *inode, struct list_head *logged_list, -diff --git a/fs/btrfs/scrub.c b/fs/btrfs/scrub.c -index c71d0d2..8ed36be 100644 --- a/fs/btrfs/scrub.c +++ b/fs/btrfs/scrub.c -@@ -3848,45 +3848,6 @@ int scrub_enumerate_chunks(struct scrub_ctx *sctx, +@@ -3849,45 +3849,6 @@ int scrub_enumerate_chunks(struct scrub_ */ scrub_pause_on(fs_info); - ret = btrfs_inc_block_group_ro(fs_info, cache); + ret = btrfs_inc_block_group_ro(cache); - if (!ret && is_dev_replace) { - /* - * If we are doing a device replace wait for any tasks @@ -140,6 +134,3 @@ index c71d0d2..8ed36be 100644 scrub_pause_off(fs_info); if (ret == 0) { --- -2.16.4 - diff --git a/patches.suse/Btrfs-fix-race-between-adding-and-putting-tree-mod-s.patch b/patches.suse/Btrfs-fix-race-between-adding-and-putting-tree-mod-s.patch index 67d80f4..b7f487d 100644 --- a/patches.suse/Btrfs-fix-race-between-adding-and-putting-tree-mod-s.patch +++ b/patches.suse/Btrfs-fix-race-between-adding-and-putting-tree-mod-s.patch @@ -103,18 +103,16 @@ Reviewed-by: Nikolay Borisov Signed-off-by: Filipe Manana Signed-off-by: David Sterba --- - fs/btrfs/ctree.c | 8 ++------ - fs/btrfs/ctree.h | 6 ++---- - fs/btrfs/delayed-ref.c | 8 ++++---- - fs/btrfs/disk-io.c | 1 - - fs/btrfs/tests/btrfs-tests.c | 1 - + fs/btrfs/ctree.c | 8 ++------ + fs/btrfs/ctree.h | 6 ++---- + fs/btrfs/delayed-ref.c | 8 ++++---- + fs/btrfs/disk-io.c | 1 - + fs/btrfs/tests/btrfs-tests.c | 1 - 5 files changed, 8 insertions(+), 16 deletions(-) -diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c -index efa913bc5625..356a1bba7645 100644 --- a/fs/btrfs/ctree.c +++ b/fs/btrfs/ctree.c -@@ -339,12 +339,10 @@ u64 btrfs_get_tree_mod_seq(struct btrfs_fs_info *fs_info, +@@ -339,12 +339,10 @@ u64 btrfs_get_tree_mod_seq(struct btrfs_ struct seq_list *elem) { tree_mod_log_write_lock(fs_info); @@ -127,7 +125,7 @@ index efa913bc5625..356a1bba7645 100644 tree_mod_log_write_unlock(fs_info); return elem->seq; -@@ -364,7 +362,7 @@ void btrfs_put_tree_mod_seq(struct btrfs_fs_info *fs_info, +@@ -364,7 +362,7 @@ void btrfs_put_tree_mod_seq(struct btrfs if (!seq_putting) return; @@ -136,7 +134,7 @@ index efa913bc5625..356a1bba7645 100644 list_del(&elem->list); elem->seq = 0; -@@ -375,19 +373,17 @@ void btrfs_put_tree_mod_seq(struct btrfs_fs_info *fs_info, +@@ -375,19 +373,17 @@ void btrfs_put_tree_mod_seq(struct btrfs * blocker with lower sequence number exists, we * cannot remove anything from the log */ @@ -157,13 +155,11 @@ index efa913bc5625..356a1bba7645 100644 tm_root = &fs_info->tree_mod_log; for (node = rb_first(tm_root); node; node = next) { next = rb_next(node); -diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h -index 79fdd23579c8..b3b45b24eadf 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h -@@ -913,14 +913,12 @@ struct btrfs_fs_info { - struct list_head delayed_iputs; - struct mutex cleaner_delayed_iput_mutex; +@@ -919,14 +919,12 @@ struct btrfs_fs_info { + atomic_t nr_delayed_iputs; + wait_queue_head_t delayed_iputs_wait; - /* this protects tree_mod_seq_list */ - spinlock_t tree_mod_seq_lock; @@ -178,11 +174,9 @@ index 79fdd23579c8..b3b45b24eadf 100644 atomic_t nr_async_submits; atomic_t async_submit_draining; -diff --git a/fs/btrfs/delayed-ref.c b/fs/btrfs/delayed-ref.c -index 869af3f28f9e..dbc7afbb3319 100644 --- a/fs/btrfs/delayed-ref.c +++ b/fs/btrfs/delayed-ref.c -@@ -316,7 +316,7 @@ void btrfs_merge_delayed_refs(struct btrfs_trans_handle *trans, +@@ -311,7 +311,7 @@ void btrfs_merge_delayed_refs(struct btr if (head->is_data) return; @@ -191,7 +185,7 @@ index 869af3f28f9e..dbc7afbb3319 100644 if (!list_empty(&fs_info->tree_mod_seq_list)) { struct seq_list *elem; -@@ -324,7 +324,7 @@ void btrfs_merge_delayed_refs(struct btrfs_trans_handle *trans, +@@ -319,7 +319,7 @@ void btrfs_merge_delayed_refs(struct btr struct seq_list, list); seq = elem->seq; } @@ -200,7 +194,7 @@ index 869af3f28f9e..dbc7afbb3319 100644 again: for (node = rb_first(&head->ref_tree); node; node = rb_next(node)) { -@@ -343,7 +343,7 @@ int btrfs_check_delayed_seq(struct btrfs_fs_info *fs_info, +@@ -338,7 +338,7 @@ int btrfs_check_delayed_seq(struct btrfs struct seq_list *elem; int ret = 0; @@ -209,7 +203,7 @@ index 869af3f28f9e..dbc7afbb3319 100644 if (!list_empty(&fs_info->tree_mod_seq_list)) { elem = list_first_entry(&fs_info->tree_mod_seq_list, struct seq_list, list); -@@ -357,7 +357,7 @@ int btrfs_check_delayed_seq(struct btrfs_fs_info *fs_info, +@@ -352,7 +352,7 @@ int btrfs_check_delayed_seq(struct btrfs } } @@ -218,11 +212,9 @@ index 869af3f28f9e..dbc7afbb3319 100644 return ret; } -diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c -index 9372435471cf..928ba1339a1e 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c -@@ -2544,7 +2544,6 @@ int open_ctree(struct super_block *sb, +@@ -2518,7 +2518,6 @@ int open_ctree(struct super_block *sb, spin_lock_init(&fs_info->delayed_iput_lock); spin_lock_init(&fs_info->defrag_inodes_lock); spin_lock_init(&fs_info->free_chunk_lock); @@ -230,11 +222,9 @@ index 9372435471cf..928ba1339a1e 100644 spin_lock_init(&fs_info->super_lock); spin_lock_init(&fs_info->qgroup_op_lock); spin_lock_init(&fs_info->buffer_lock); -diff --git a/fs/btrfs/tests/btrfs-tests.c b/fs/btrfs/tests/btrfs-tests.c -index c3492bc1cc60..c77432e9d397 100644 --- a/fs/btrfs/tests/btrfs-tests.c +++ b/fs/btrfs/tests/btrfs-tests.c -@@ -121,7 +121,6 @@ struct btrfs_fs_info *btrfs_alloc_dummy_fs_info(u32 nodesize, u32 sectorsize) +@@ -121,7 +121,6 @@ struct btrfs_fs_info *btrfs_alloc_dummy_ spin_lock_init(&fs_info->qgroup_op_lock); spin_lock_init(&fs_info->super_lock); spin_lock_init(&fs_info->fs_roots_radix_lock); @@ -242,6 +232,3 @@ index c3492bc1cc60..c77432e9d397 100644 mutex_init(&fs_info->qgroup_ioctl_lock); mutex_init(&fs_info->qgroup_rescan_lock); rwlock_init(&fs_info->tree_mod_log_lock); --- -2.16.4 - diff --git a/patches.suse/Btrfs-fix-unwritten-extent-buffers-and-hangs-on-futu.patch b/patches.suse/Btrfs-fix-unwritten-extent-buffers-and-hangs-on-futu.patch new file mode 100644 index 0000000..a067152 --- /dev/null +++ b/patches.suse/Btrfs-fix-unwritten-extent-buffers-and-hangs-on-futu.patch @@ -0,0 +1,149 @@ +From 18dfa7117a3f379862dcd3f67cadd678013bb9dd Mon Sep 17 00:00:00 2001 +From: Filipe Manana +Date: Wed, 11 Sep 2019 17:42:00 +0100 +Patch-mainline: v5.3 +Git-commit: 18dfa7117a3f379862dcd3f67cadd678013bb9dd +References: bsc#1168273 +Subject: [PATCH] Btrfs: fix unwritten extent buffers and hangs on future + writeback attempts + +The lock_extent_buffer_io() returns 1 to the caller to tell it everything +went fine and the callers needs to start writeback for the extent buffer +(submit a bio, etc), 0 to tell the caller everything went fine but it does +not need to start writeback for the extent buffer, and a negative value if +some error happened. + +When it's about to return 1 it tries to lock all pages, and if a try lock +on a page fails, and we didn't flush any existing bio in our "epd", it +calls flush_write_bio(epd) and overwrites the return value of 1 to 0 or +an error. The page might have been locked elsewhere, not with the goal +of starting writeback of the extent buffer, and even by some code other +than btrfs, like page migration for example, so it does not mean the +writeback of the extent buffer was already started by some other task, +so returning a 0 tells the caller (btree_write_cache_pages()) to not +start writeback for the extent buffer. Note that epd might currently have +either no bio, so flush_write_bio() returns 0 (success) or it might have +a bio for another extent buffer with a lower index (logical address). + +Since we return 0 with the EXTENT_BUFFER_WRITEBACK bit set on the +extent buffer and writeback is never started for the extent buffer, +future attempts to writeback the extent buffer will hang forever waiting +on that bit to be cleared, since it can only be cleared after writeback +completes. Such hang is reported with a trace like the following: + + [49887.347053] INFO: task btrfs-transacti:1752 blocked for more than 122 seconds. + [49887.347059] Not tainted 5.2.13-gentoo #2 + [49887.347060] "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message. + [49887.347062] btrfs-transacti D 0 1752 2 0x80004000 + [49887.347064] Call Trace: + [49887.347069] ? __schedule+0x265/0x830 + [49887.347071] ? bit_wait+0x50/0x50 + [49887.347072] ? bit_wait+0x50/0x50 + [49887.347074] schedule+0x24/0x90 + [49887.347075] io_schedule+0x3c/0x60 + [49887.347077] bit_wait_io+0x8/0x50 + [49887.347079] __wait_on_bit+0x6c/0x80 + [49887.347081] ? __lock_release.isra.29+0x155/0x2d0 + [49887.347083] out_of_line_wait_on_bit+0x7b/0x80 + [49887.347084] ? var_wake_function+0x20/0x20 + [49887.347087] lock_extent_buffer_for_io+0x28c/0x390 + [49887.347089] btree_write_cache_pages+0x18e/0x340 + [49887.347091] do_writepages+0x29/0xb0 + [49887.347093] ? kmem_cache_free+0x132/0x160 + [49887.347095] ? convert_extent_bit+0x544/0x680 + [49887.347097] filemap_fdatawrite_range+0x70/0x90 + [49887.347099] btrfs_write_marked_extents+0x53/0x120 + [49887.347100] btrfs_write_and_wait_transaction.isra.4+0x38/0xa0 + [49887.347102] btrfs_commit_transaction+0x6bb/0x990 + [49887.347103] ? start_transaction+0x33e/0x500 + [49887.347105] transaction_kthread+0x139/0x15c + +So fix this by not overwriting the return value (ret) with the result +from flush_write_bio(). We also need to clear the EXTENT_BUFFER_WRITEBACK +bit in case flush_write_bio() returns an error, otherwise it will hang +any future attempts to writeback the extent buffer, and undo all work +done before (set back EXTENT_BUFFER_DIRTY, etc). + +This is a regression introduced in the 5.2 kernel. + +Fixes: 2e3c25136adfb ("btrfs: extent_io: add proper error handling to lock_extent_buffer_for_io()") +Fixes: f4340622e0226 ("btrfs: extent_io: Move the BUG_ON() in flush_write_bio() one level up") +Reported-by: Zdenek Sojka +Link: https://lore.kernel.org/linux-btrfs/GpO.2yos.3WGDOLpx6t%7D.1TUDYM@seznam.cz/T/#u +Reported-by: Stefan Priebe - Profihost AG +Link: https://lore.kernel.org/linux-btrfs/5c4688ac-10a7-fb07-70e8-c5d31a3fbb38@profihost.ag/T/#t +Reported-by: Drazen Kacar +Link: https://lore.kernel.org/linux-btrfs/DB8PR03MB562876ECE2319B3E579590F799C80@DB8PR03MB5628.eurprd03.prod.outlook.com/ +Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=204377 +Signed-off-by: Filipe Manana +Signed-off-by: David Sterba +--- + fs/btrfs/extent_io.c | 35 ++++++++++++++++++++++++++--------- + 1 file changed, 26 insertions(+), 9 deletions(-) + +diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c +index aea990473392..9d1f42200af5 100644 +--- a/fs/btrfs/extent_io.c ++++ b/fs/btrfs/extent_io.c +@@ -3628,6 +3628,13 @@ void wait_on_extent_buffer_writeback(struct extent_buffer *eb) + TASK_UNINTERRUPTIBLE); + } + ++static void end_extent_buffer_writeback(struct extent_buffer *eb) ++{ ++ clear_bit(EXTENT_BUFFER_WRITEBACK, &eb->bflags); ++ smp_mb__after_atomic(); ++ wake_up_bit(&eb->bflags, EXTENT_BUFFER_WRITEBACK); ++} ++ + /* + * Lock eb pages and flush the bio if we can't the locks + * +@@ -3699,8 +3706,11 @@ static noinline_for_stack int lock_extent_buffer_for_io(struct extent_buffer *eb + + if (!trylock_page(p)) { + if (!flush) { +- ret = flush_write_bio(epd); +- if (ret < 0) { ++ int err; ++ ++ err = flush_write_bio(epd); ++ if (err < 0) { ++ ret = err; + failed_page_nr = i; + goto err_unlock; + } +@@ -3715,16 +3725,23 @@ static noinline_for_stack int lock_extent_buffer_for_io(struct extent_buffer *eb + /* Unlock already locked pages */ + for (i = 0; i < failed_page_nr; i++) + unlock_page(eb->pages[i]); ++ /* ++ * Clear EXTENT_BUFFER_WRITEBACK and wake up anyone waiting on it. ++ * Also set back EXTENT_BUFFER_DIRTY so future attempts to this eb can ++ * be made and undo everything done before. ++ */ ++ btrfs_tree_lock(eb); ++ spin_lock(&eb->refs_lock); ++ set_bit(EXTENT_BUFFER_DIRTY, &eb->bflags); ++ end_extent_buffer_writeback(eb); ++ spin_unlock(&eb->refs_lock); ++ percpu_counter_add_batch(&fs_info->dirty_metadata_bytes, eb->len, ++ fs_info->dirty_metadata_batch); ++ btrfs_clear_header_flag(eb, BTRFS_HEADER_FLAG_WRITTEN); ++ btrfs_tree_unlock(eb); + return ret; + } + +-static void end_extent_buffer_writeback(struct extent_buffer *eb) +-{ +- clear_bit(EXTENT_BUFFER_WRITEBACK, &eb->bflags); +- smp_mb__after_atomic(); +- wake_up_bit(&eb->bflags, EXTENT_BUFFER_WRITEBACK); +-} +- + static void set_btree_ioerr(struct page *page) + { + struct extent_buffer *eb = (struct extent_buffer *)page->private; +-- +2.26.0 + diff --git a/patches.suse/CIFS-Add-support-for-setting-owner-info-dos-attributes-and-create.patch b/patches.suse/CIFS-Add-support-for-setting-owner-info-dos-attributes-and-create.patch new file mode 100644 index 0000000..072db6e --- /dev/null +++ b/patches.suse/CIFS-Add-support-for-setting-owner-info-dos-attributes-and-create.patch @@ -0,0 +1,228 @@ +From: Boris Protopopov +Date: Thu, 19 Dec 2019 16:52:50 +0000 +Subject: [PATCH] CIFS: Add support for setting owner info, dos attributes, and + create time +Git-commit: 438471b67963b8267e94beab383b6d6fc41b3481 +References: bsc#1144333 +Patch-mainline: v5.6-rc1 + +This is needed for backup/restore scenarios among others. + +Add extended attribute "system.cifs_ntsd" (and alias "system.smb3_ntsd") +to allow for setting owner and DACL in the security descriptor. This is in +addition to the existing "system.cifs_acl" and "system.smb3_acl" attributes +that allow for setting DACL only. Add support for setting creation time and +dos attributes using set_file_info() calls to complement the existing +support for getting these attributes via query_path_info() calls. + +Signed-off-by: Boris Protopopov +Signed-off-by: Steve French +Acked-by: Paulo Alcantara +--- + fs/cifs/xattr.c | 128 +++++++++++++++++++++++++++++++++++++++++++----- + 1 file changed, 117 insertions(+), 11 deletions(-) + +diff --git a/fs/cifs/xattr.c b/fs/cifs/xattr.c +index db4ba8f6077e..b8299173ea7e 100644 +--- a/fs/cifs/xattr.c ++++ b/fs/cifs/xattr.c +@@ -32,7 +32,8 @@ + #include "cifs_unicode.h" + + #define MAX_EA_VALUE_SIZE CIFSMaxBufSize +-#define CIFS_XATTR_CIFS_ACL "system.cifs_acl" ++#define CIFS_XATTR_CIFS_ACL "system.cifs_acl" /* DACL only */ ++#define CIFS_XATTR_CIFS_NTSD "system.cifs_ntsd" /* owner plus DACL */ + #define CIFS_XATTR_ATTRIB "cifs.dosattrib" /* full name: user.cifs.dosattrib */ + #define CIFS_XATTR_CREATETIME "cifs.creationtime" /* user.cifs.creationtime */ + /* +@@ -40,12 +41,62 @@ + * confusing users and using the 20+ year old term 'cifs' when it is no longer + * secure, replaced by SMB2 (then even more highly secure SMB3) many years ago + */ +-#define SMB3_XATTR_CIFS_ACL "system.smb3_acl" ++#define SMB3_XATTR_CIFS_ACL "system.smb3_acl" /* DACL only */ ++#define SMB3_XATTR_CIFS_NTSD "system.smb3_ntsd" /* owner plus DACL */ + #define SMB3_XATTR_ATTRIB "smb3.dosattrib" /* full name: user.smb3.dosattrib */ + #define SMB3_XATTR_CREATETIME "smb3.creationtime" /* user.smb3.creationtime */ + /* BB need to add server (Samba e.g) support for security and trusted prefix */ + +-enum { XATTR_USER, XATTR_CIFS_ACL, XATTR_ACL_ACCESS, XATTR_ACL_DEFAULT }; ++enum { XATTR_USER, XATTR_CIFS_ACL, XATTR_ACL_ACCESS, XATTR_ACL_DEFAULT, ++ XATTR_CIFS_NTSD }; ++ ++static int cifs_attrib_set(unsigned int xid, struct cifs_tcon *pTcon, ++ struct inode *inode, char *full_path, ++ const void *value, size_t size) ++{ ++ ssize_t rc = -EOPNOTSUPP; ++ __u32 *pattrib = (__u32 *)value; ++ __u32 attrib; ++ FILE_BASIC_INFO info_buf; ++ ++ if ((value == NULL) || (size != sizeof(__u32))) ++ return -ERANGE; ++ ++ memset(&info_buf, 0, sizeof(info_buf)); ++ attrib = *pattrib; ++ info_buf.Attributes = cpu_to_le32(attrib); ++ if (pTcon->ses->server->ops->set_file_info) ++ rc = pTcon->ses->server->ops->set_file_info(inode, full_path, ++ &info_buf, xid); ++ if (rc == 0) ++ CIFS_I(inode)->cifsAttrs = attrib; ++ ++ return rc; ++} ++ ++static int cifs_creation_time_set(unsigned int xid, struct cifs_tcon *pTcon, ++ struct inode *inode, char *full_path, ++ const void *value, size_t size) ++{ ++ ssize_t rc = -EOPNOTSUPP; ++ __u64 *pcreation_time = (__u64 *)value; ++ __u64 creation_time; ++ FILE_BASIC_INFO info_buf; ++ ++ if ((value == NULL) || (size != sizeof(__u64))) ++ return -ERANGE; ++ ++ memset(&info_buf, 0, sizeof(info_buf)); ++ creation_time = *pcreation_time; ++ info_buf.CreationTime = cpu_to_le64(creation_time); ++ if (pTcon->ses->server->ops->set_file_info) ++ rc = pTcon->ses->server->ops->set_file_info(inode, full_path, ++ &info_buf, xid); ++ if (rc == 0) ++ CIFS_I(inode)->createtime = creation_time; ++ ++ return rc; ++} + + static int cifs_xattr_set(const struct xattr_handler *handler, + struct dentry *dentry, struct inode *inode, +@@ -86,6 +137,23 @@ static int cifs_xattr_set(const struct xattr_handler *handler, + + switch (handler->flags) { + case XATTR_USER: ++ cifs_dbg(FYI, "%s:setting user xattr %s\n", __func__, name); ++ if ((strcmp(name, CIFS_XATTR_ATTRIB) == 0) || ++ (strcmp(name, SMB3_XATTR_ATTRIB) == 0)) { ++ rc = cifs_attrib_set(xid, pTcon, inode, full_path, ++ value, size); ++ if (rc == 0) /* force revalidate of the inode */ ++ CIFS_I(inode)->time = 0; ++ break; ++ } else if ((strcmp(name, CIFS_XATTR_CREATETIME) == 0) || ++ (strcmp(name, SMB3_XATTR_CREATETIME) == 0)) { ++ rc = cifs_creation_time_set(xid, pTcon, inode, ++ full_path, value, size); ++ if (rc == 0) /* force revalidate of the inode */ ++ CIFS_I(inode)->time = 0; ++ break; ++ } ++ + if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR) + goto out; + +@@ -95,7 +163,8 @@ static int cifs_xattr_set(const struct xattr_handler *handler, + cifs_sb->local_nls, cifs_sb); + break; + +- case XATTR_CIFS_ACL: { ++ case XATTR_CIFS_ACL: ++ case XATTR_CIFS_NTSD: { + struct cifs_ntsd *pacl; + + if (!value) +@@ -106,12 +175,25 @@ static int cifs_xattr_set(const struct xattr_handler *handler, + } else { + memcpy(pacl, value, size); + if (value && +- pTcon->ses->server->ops->set_acl) +- rc = pTcon->ses->server->ops->set_acl(pacl, +- size, inode, +- full_path, CIFS_ACL_DACL); +- else ++ pTcon->ses->server->ops->set_acl) { ++ rc = 0; ++ if (handler->flags == XATTR_CIFS_NTSD) { ++ /* set owner and DACL */ ++ rc = pTcon->ses->server->ops->set_acl( ++ pacl, size, inode, ++ full_path, ++ CIFS_ACL_OWNER); ++ } ++ if (rc == 0) { ++ /* set DACL */ ++ rc = pTcon->ses->server->ops->set_acl( ++ pacl, size, inode, ++ full_path, ++ CIFS_ACL_DACL); ++ } ++ } else { + rc = -EOPNOTSUPP; ++ } + if (rc == 0) /* force revalidate of the inode */ + CIFS_I(inode)->time = 0; + kfree(pacl); +@@ -179,7 +261,7 @@ static int cifs_creation_time_get(struct dentry *dentry, struct inode *inode, + void *value, size_t size) + { + ssize_t rc; +- __u64 * pcreatetime; ++ __u64 *pcreatetime; + + rc = cifs_revalidate_dentry_attr(dentry); + if (rc) +@@ -244,7 +326,9 @@ static int cifs_xattr_get(const struct xattr_handler *handler, + full_path, name, value, size, cifs_sb); + break; + +- case XATTR_CIFS_ACL: { ++ case XATTR_CIFS_ACL: ++ case XATTR_CIFS_NTSD: { ++ /* the whole ntsd is fetched regardless */ + u32 acllen; + struct cifs_ntsd *pacl; + +@@ -382,6 +466,26 @@ static const struct xattr_handler smb3_acl_xattr_handler = { + .set = cifs_xattr_set, + }; + ++static const struct xattr_handler cifs_cifs_ntsd_xattr_handler = { ++ .name = CIFS_XATTR_CIFS_NTSD, ++ .flags = XATTR_CIFS_NTSD, ++ .get = cifs_xattr_get, ++ .set = cifs_xattr_set, ++}; ++ ++/* ++ * Although this is just an alias for the above, need to move away from ++ * confusing users and using the 20 year old term 'cifs' when it is no ++ * longer secure and was replaced by SMB2/SMB3 a long time ago, and ++ * SMB3 and later are highly secure. ++ */ ++static const struct xattr_handler smb3_ntsd_xattr_handler = { ++ .name = SMB3_XATTR_CIFS_NTSD, ++ .flags = XATTR_CIFS_NTSD, ++ .get = cifs_xattr_get, ++ .set = cifs_xattr_set, ++}; ++ + static const struct xattr_handler cifs_posix_acl_access_xattr_handler = { + .name = XATTR_NAME_POSIX_ACL_ACCESS, + .flags = XATTR_ACL_ACCESS, +@@ -401,6 +505,8 @@ const struct xattr_handler *cifs_xattr_handlers[] = { + &cifs_os2_xattr_handler, + &cifs_cifs_acl_xattr_handler, + &smb3_acl_xattr_handler, /* alias for above since avoiding "cifs" */ ++ &cifs_cifs_ntsd_xattr_handler, ++ &smb3_ntsd_xattr_handler, /* alias for above since avoiding "cifs" */ + &cifs_posix_acl_access_xattr_handler, + &cifs_posix_acl_default_xattr_handler, + NULL +-- +2.25.1 + + diff --git a/patches.suse/CIFS-Fix-retry-mid-list-corruption-on-reconnects.patch b/patches.suse/CIFS-Fix-retry-mid-list-corruption-on-reconnects.patch index 5664066..67ddd4f 100644 --- a/patches.suse/CIFS-Fix-retry-mid-list-corruption-on-reconnects.patch +++ b/patches.suse/CIFS-Fix-retry-mid-list-corruption-on-reconnects.patch @@ -178,6 +178,6 @@ Acked-by: Paulo Alcantara qhead); + mid->mid_flags |= MID_DELETED; + } - cifs_dbg(VFS, "%s: invalid mid state mid=%llu state=%d\n", + cifs_server_dbg(VFS, "%s: invalid mid state mid=%llu state=%d\n", __func__, mid->mid, mid->mid_state); rc = -EIO; diff --git a/patches.suse/CIFS-Fix-task-struct-use-after-free-on-reconnect.patch b/patches.suse/CIFS-Fix-task-struct-use-after-free-on-reconnect.patch new file mode 100644 index 0000000..839163b --- /dev/null +++ b/patches.suse/CIFS-Fix-task-struct-use-after-free-on-reconnect.patch @@ -0,0 +1,178 @@ +From: Vincent Whitchurch +Date: Thu, 23 Jan 2020 17:09:06 +0100 +Subject: CIFS: Fix task struct use-after-free on reconnect +Patch-mainline: v5.6-rc1 +Git-commit: f1f27ad74557e39f67a8331a808b860f89254f2d +References: bsc#1144333 + +The task which created the MID may be gone by the time cifsd attempts to +call the callbacks on MIDs from cifs_reconnect(). + +This leads to a use-after-free of the task struct in cifs_wake_up_task: + + ================================================================== + BUG: KASAN: use-after-free in __lock_acquire+0x31a0/0x3270 + Read of size 8 at addr ffff8880103e3a68 by task cifsd/630 + + CPU: 0 PID: 630 Comm: cifsd Not tainted 5.5.0-rc6+ #119 + Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.10.2-1 04/01/2014 + Call Trace: + dump_stack+0x8e/0xcb + print_address_description.constprop.5+0x1d3/0x3c0 + ? __lock_acquire+0x31a0/0x3270 + __kasan_report+0x152/0x1aa + ? __lock_acquire+0x31a0/0x3270 + ? __lock_acquire+0x31a0/0x3270 + kasan_report+0xe/0x20 + __lock_acquire+0x31a0/0x3270 + ? __wake_up_common+0x1dc/0x630 + ? _raw_spin_unlock_irqrestore+0x4c/0x60 + ? mark_held_locks+0xf0/0xf0 + ? _raw_spin_unlock_irqrestore+0x39/0x60 + ? __wake_up_common_lock+0xd5/0x130 + ? __wake_up_common+0x630/0x630 + lock_acquire+0x13f/0x330 + ? try_to_wake_up+0xa3/0x19e0 + _raw_spin_lock_irqsave+0x38/0x50 + ? try_to_wake_up+0xa3/0x19e0 + try_to_wake_up+0xa3/0x19e0 + ? cifs_compound_callback+0x178/0x210 + ? set_cpus_allowed_ptr+0x10/0x10 + cifs_reconnect+0xa1c/0x15d0 + ? generic_ip_connect+0x1860/0x1860 + ? rwlock_bug.part.0+0x90/0x90 + cifs_readv_from_socket+0x479/0x690 + cifs_read_from_socket+0x9d/0xe0 + ? cifs_readv_from_socket+0x690/0x690 + ? mempool_resize+0x690/0x690 + ? rwlock_bug.part.0+0x90/0x90 + ? memset+0x1f/0x40 + ? allocate_buffers+0xff/0x340 + cifs_demultiplex_thread+0x388/0x2a50 + ? cifs_handle_standard+0x610/0x610 + ? rcu_read_lock_held_common+0x120/0x120 + ? mark_lock+0x11b/0xc00 + ? __lock_acquire+0x14ed/0x3270 + ? __kthread_parkme+0x78/0x100 + ? lockdep_hardirqs_on+0x3e8/0x560 + ? lock_downgrade+0x6a0/0x6a0 + ? lockdep_hardirqs_on+0x3e8/0x560 + ? _raw_spin_unlock_irqrestore+0x39/0x60 + ? cifs_handle_standard+0x610/0x610 + kthread+0x2bb/0x3a0 + ? kthread_create_worker_on_cpu+0xc0/0xc0 + ret_from_fork+0x3a/0x50 + + Allocated by task 649: + save_stack+0x19/0x70 + __kasan_kmalloc.constprop.5+0xa6/0xf0 + kmem_cache_alloc+0x107/0x320 + copy_process+0x17bc/0x5370 + _do_fork+0x103/0xbf0 + __x64_sys_clone+0x168/0x1e0 + do_syscall_64+0x9b/0xec0 + entry_SYSCALL_64_after_hwframe+0x49/0xbe + + Freed by task 0: + save_stack+0x19/0x70 + __kasan_slab_free+0x11d/0x160 + kmem_cache_free+0xb5/0x3d0 + rcu_core+0x52f/0x1230 + __do_softirq+0x24d/0x962 + + The buggy address belongs to the object at ffff8880103e32c0 + which belongs to the cache task_struct of size 6016 + The buggy address is located 1960 bytes inside of + 6016-byte region [ffff8880103e32c0, ffff8880103e4a40) + The buggy address belongs to the page: + page:ffffea000040f800 refcount:1 mapcount:0 mapping:ffff8880108da5c0 + index:0xffff8880103e4c00 compound_mapcount: 0 + raw: 4000000000010200 ffffea00001f2208 ffffea00001e3408 ffff8880108da5c0 + raw: ffff8880103e4c00 0000000000050003 00000001ffffffff 0000000000000000 + page dumped because: kasan: bad access detected + + Memory state around the buggy address: + ffff8880103e3900: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb + ffff8880103e3980: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb + >ffff8880103e3a00: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb + ^ + ffff8880103e3a80: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb + ffff8880103e3b00: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb + ================================================================== + +This can be reliably reproduced by adding the below delay to +cifs_reconnect(), running find(1) on the mount, restarting the samba +server while find is running, and killing find during the delay: + + spin_unlock(&GlobalMid_Lock); + mutex_unlock(&server->srv_mutex); + + + msleep(10000); + + + cifs_dbg(FYI, "%s: issuing mid callbacks\n", __func__); + list_for_each_safe(tmp, tmp2, &retry_list) { + mid_entry = list_entry(tmp, struct mid_q_entry, qhead); + +Fix this by holding a reference to the task struct until the MID is +freed. + +Signed-off-by: Vincent Whitchurch +Signed-off-by: Steve French +CC: Stable +Reviewed-by: Paulo Alcantara (SUSE) +Reviewed-by: Pavel Shilovsky +Acked-by: Paulo Alcantara +--- + fs/cifs/cifsglob.h | 1 + + fs/cifs/smb2transport.c | 3 +++ + fs/cifs/transport.c | 3 +++ + 3 files changed, 7 insertions(+) + +--- a/fs/cifs/cifsglob.h ++++ b/fs/cifs/cifsglob.h +@@ -1542,6 +1542,7 @@ struct mid_q_entry { + mid_callback_t *callback; /* call completion callback */ + mid_handle_t *handle; /* call handle mid callback */ + void *callback_data; /* general purpose pointer for callback */ ++ struct task_struct *creator; + void *resp_buf; /* pointer to received SMB header */ + unsigned int resp_buf_size; + int mid_state; /* wish this were enum but can not pass to wait_event */ +--- a/fs/cifs/smb2transport.c ++++ b/fs/cifs/smb2transport.c +@@ -32,6 +32,7 @@ + #include + #include + #include ++#include + #include "smb2pdu.h" + #include "cifsglob.h" + #include "cifsproto.h" +@@ -599,6 +600,8 @@ smb2_mid_entry_alloc(const struct smb2_s + * The default is for the mid to be synchronous, so the + * default callback just wakes up the current task. + */ ++ get_task_struct(current); ++ temp->creator = current; + temp->callback = cifs_wake_up_task; + temp->callback_data = current; + +--- a/fs/cifs/transport.c ++++ b/fs/cifs/transport.c +@@ -76,6 +76,8 @@ AllocMidQEntry(const struct smb_hdr *smb + * The default is for the mid to be synchronous, so the + * default callback just wakes up the current task. + */ ++ get_task_struct(current); ++ temp->creator = current; + temp->callback = cifs_wake_up_task; + temp->callback_data = current; + +@@ -158,6 +160,7 @@ static void _cifs_mid_q_entry_release(st + } + } + #endif ++ put_task_struct(midEntry->creator); + + mempool_free(midEntry, cifs_mid_poolp); + } diff --git a/patches.suse/CIFS-Return-directly-after-a-failed-build_path_from_dentry-in-cif.patch b/patches.suse/CIFS-Return-directly-after-a-failed-build_path_from_dentry-in-cif.patch new file mode 100644 index 0000000..e612a03 --- /dev/null +++ b/patches.suse/CIFS-Return-directly-after-a-failed-build_path_from_dentry-in-cif.patch @@ -0,0 +1,39 @@ +From: Markus Elfring +Date: Sun, 20 Aug 2017 17:17:30 +0200 +Subject: [PATCH] CIFS: Return directly after a failed build_path_from_dentry() + in cifs_do_create() +Git-commit: 598b6c57f2ff29df948c846f4bf3046c33d6b37f +References: bsc#1144333 +Patch-mainline: v5.5-rc1 + +Return directly after a call of the function "build_path_from_dentry" +failed at the beginning. + +Signed-off-by: Markus Elfring +Signed-off-by: Steve French +Acked-by: Paulo Alcantara +--- + fs/cifs/dir.c | 6 ++---- + 1 file changed, 2 insertions(+), 4 deletions(-) + +diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c +index 7ce689d31aa2..f3b79012ff29 100644 +--- a/fs/cifs/dir.c ++++ b/fs/cifs/dir.c +@@ -244,10 +244,8 @@ cifs_do_create(struct inode *inode, struct dentry *direntry, unsigned int xid, + *oplock = REQ_OPLOCK; + + full_path = build_path_from_dentry(direntry); +- if (full_path == NULL) { +- rc = -ENOMEM; +- goto out; +- } ++ if (!full_path) ++ return -ENOMEM; + + if (tcon->unix_ext && cap_unix(tcon->ses) && !tcon->broken_posix_open && + (CIFS_UNIX_POSIX_PATH_OPS_CAP & +-- +2.25.1 + + diff --git a/patches.suse/CIFS-Use-common-error-handling-code-in-smb2_ioctl_query_info-.patch b/patches.suse/CIFS-Use-common-error-handling-code-in-smb2_ioctl_query_info-.patch new file mode 100644 index 0000000..a7c16ba --- /dev/null +++ b/patches.suse/CIFS-Use-common-error-handling-code-in-smb2_ioctl_query_info-.patch @@ -0,0 +1,94 @@ +From: Markus Elfring +Date: Tue, 5 Nov 2019 22:26:53 +0100 +Subject: [PATCH] CIFS: Use common error handling code in + smb2_ioctl_query_info() +Git-commit: 2b1116bbe898aefdf584838448c6869f69851e0f +References: bsc#1144333 +Patch-mainline: v5.5-rc1 + +Move the same error code assignments so that such exception handling +can be better reused at the end of this function. + +This issue was detected by using the Coccinelle software. + +Signed-off-by: Markus Elfring +Signed-off-by: Steve French +Acked-by: Paulo Alcantara +--- + fs/cifs/smb2ops.c | 45 +++++++++++++++++++++++---------------------- + 1 file changed, 23 insertions(+), 22 deletions(-) + +diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c +index e31cdd493e1b..f28d4207bbda 100644 +--- a/fs/cifs/smb2ops.c ++++ b/fs/cifs/smb2ops.c +@@ -1524,35 +1524,32 @@ smb2_ioctl_query_info(const unsigned int xid, + if (le32_to_cpu(io_rsp->OutputCount) < qi.input_buffer_length) + qi.input_buffer_length = le32_to_cpu(io_rsp->OutputCount); + if (qi.input_buffer_length > 0 && +- le32_to_cpu(io_rsp->OutputOffset) + qi.input_buffer_length > rsp_iov[1].iov_len) { +- rc = -EFAULT; +- goto iqinf_exit; +- } +- if (copy_to_user(&pqi->input_buffer_length, &qi.input_buffer_length, +- sizeof(qi.input_buffer_length))) { +- rc = -EFAULT; +- goto iqinf_exit; +- } ++ le32_to_cpu(io_rsp->OutputOffset) + qi.input_buffer_length ++ > rsp_iov[1].iov_len) ++ goto e_fault; ++ ++ if (copy_to_user(&pqi->input_buffer_length, ++ &qi.input_buffer_length, ++ sizeof(qi.input_buffer_length))) ++ goto e_fault; ++ + if (copy_to_user((void __user *)pqi + sizeof(struct smb_query_info), + (const void *)io_rsp + le32_to_cpu(io_rsp->OutputOffset), +- qi.input_buffer_length)) { +- rc = -EFAULT; +- goto iqinf_exit; +- } ++ qi.input_buffer_length)) ++ goto e_fault; + } else { + pqi = (struct smb_query_info __user *)arg; + qi_rsp = (struct smb2_query_info_rsp *)rsp_iov[1].iov_base; + if (le32_to_cpu(qi_rsp->OutputBufferLength) < qi.input_buffer_length) + qi.input_buffer_length = le32_to_cpu(qi_rsp->OutputBufferLength); +- if (copy_to_user(&pqi->input_buffer_length, &qi.input_buffer_length, +- sizeof(qi.input_buffer_length))) { +- rc = -EFAULT; +- goto iqinf_exit; +- } +- if (copy_to_user(pqi + 1, qi_rsp->Buffer, qi.input_buffer_length)) { +- rc = -EFAULT; +- goto iqinf_exit; +- } ++ if (copy_to_user(&pqi->input_buffer_length, ++ &qi.input_buffer_length, ++ sizeof(qi.input_buffer_length))) ++ goto e_fault; ++ ++ if (copy_to_user(pqi + 1, qi_rsp->Buffer, ++ qi.input_buffer_length)) ++ goto e_fault; + } + + iqinf_exit: +@@ -1568,6 +1565,10 @@ smb2_ioctl_query_info(const unsigned int xid, + free_rsp_buf(resp_buftype[1], rsp_iov[1].iov_base); + free_rsp_buf(resp_buftype[2], rsp_iov[2].iov_base); + return rc; ++ ++e_fault: ++ rc = -EFAULT; ++ goto iqinf_exit; + } + + static ssize_t +-- +2.25.1 + + diff --git a/patches.suse/CIFS-Use-memdup_user-rather-than-duplicating-its-implementation.patch b/patches.suse/CIFS-Use-memdup_user-rather-than-duplicating-its-implementation.patch new file mode 100644 index 0000000..dcd2d56 --- /dev/null +++ b/patches.suse/CIFS-Use-memdup_user-rather-than-duplicating-its-implementation.patch @@ -0,0 +1,49 @@ +From: Markus Elfring +Date: Tue, 5 Nov 2019 21:30:25 +0100 +Subject: [PATCH] CIFS: Use memdup_user() rather than duplicating its + implementation +Git-commit: cfaa1181097f6a1a6f4f6670ebc97848efda0883 +References: bsc#1144333 +Patch-mainline: v5.5-rc1 + +Reuse existing functionality from memdup_user() instead of keeping +duplicate source code. + +Generated by: scripts/coccinelle/api/memdup_user.cocci + +Fixes: f5b05d622a3e99e6a97a189fe500414be802a05c ("cifs: add IOCTL for QUERY_INFO passthrough to userspace") +Signed-off-by: Markus Elfring +Signed-off-by: Steve French +Acked-by: Paulo Alcantara +--- + fs/cifs/smb2ops.c | 13 ++++--------- + 1 file changed, 4 insertions(+), 9 deletions(-) + +diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c +index cd55af9b7cc5..e31cdd493e1b 100644 +--- a/fs/cifs/smb2ops.c ++++ b/fs/cifs/smb2ops.c +@@ -1402,15 +1402,10 @@ smb2_ioctl_query_info(const unsigned int xid, + if (smb3_encryption_required(tcon)) + flags |= CIFS_TRANSFORM_REQ; + +- buffer = kmalloc(qi.output_buffer_length, GFP_KERNEL); +- if (buffer == NULL) +- return -ENOMEM; +- +- if (copy_from_user(buffer, arg + sizeof(struct smb_query_info), +- qi.output_buffer_length)) { +- rc = -EFAULT; +- goto iqinf_exit; +- } ++ buffer = memdup_user(arg + sizeof(struct smb_query_info), ++ qi.output_buffer_length); ++ if (IS_ERR(buffer)) ++ return PTR_ERR(buffer); + + /* Open */ + memset(&open_iov, 0, sizeof(open_iov)); +-- +2.25.1 + + diff --git a/patches.suse/CIFS-fix-a-white-space-issue-in-cifs_get_inode_info-.patch b/patches.suse/CIFS-fix-a-white-space-issue-in-cifs_get_inode_info-.patch new file mode 100644 index 0000000..94cb5bf --- /dev/null +++ b/patches.suse/CIFS-fix-a-white-space-issue-in-cifs_get_inode_info-.patch @@ -0,0 +1,36 @@ +From: Dan Carpenter via samba-technical +Date: Tue, 26 Nov 2019 15:11:15 +0300 +Subject: [PATCH] CIFS: fix a white space issue in cifs_get_inode_info() +Git-commit: 68464b88cc0a735eaacd2c69beffb85d36f25292 +References: bsc#1144333 +Patch-mainline: v5.5-rc1 + +We accidentally messed up the indenting on this if statement. + +Fixes: 16c696a6c300 ("CIFS: refactor cifs_get_inode_info()") +Signed-off-by: Dan Carpenter +Reviewed-by: Aurelien Aptel +Signed-off-by: Steve French +Acked-by: Paulo Alcantara +--- + fs/cifs/inode.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c +index 1fec2e7d796a..8a76195e8a69 100644 +--- a/fs/cifs/inode.c ++++ b/fs/cifs/inode.c +@@ -967,7 +967,8 @@ cifs_get_inode_info(struct inode **inode, + } + } else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) { + rc = cifs_acl_to_fattr(cifs_sb, &fattr, *inode, false, +- full_path, fid); if (rc) { ++ full_path, fid); ++ if (rc) { + cifs_dbg(FYI, "%s: Getting ACL failed with error: %d\n", + __func__, rc); + goto out; +-- +2.25.1 + + diff --git a/patches.suse/CIFS-refactor-cifs_get_inode_info-.patch b/patches.suse/CIFS-refactor-cifs_get_inode_info-.patch new file mode 100644 index 0000000..f4f1ad4 --- /dev/null +++ b/patches.suse/CIFS-refactor-cifs_get_inode_info-.patch @@ -0,0 +1,483 @@ +From: Aurelien Aptel +Date: Mon, 18 Nov 2019 21:04:08 +0100 +Subject: [PATCH] CIFS: refactor cifs_get_inode_info() +Git-commit: b8f7442bc46e48fb6fe5d7bc3e1ac1500ce649a9 +References: bsc#1144333 +Patch-mainline: v5.5-rc1 + +Make logic of cifs_get_inode() much clearer by moving code to sub +functions and adding comments. + +Document the steps this function does. + +cifs_get_inode_info() gets and updates a file inode metadata from its +file path. + +* If caller already has raw info data from server they can pass it. +* If inode already exists (just need to update) caller can pass it. + +Step 1: get raw data from server if none was passed +Step 2: parse raw data into intermediate internal cifs_fattr struct +Step 3: set fattr uniqueid which is later used for inode number. This + can sometime be done from raw data +Step 4: tweak fattr according to mount options (file_mode, acl to mode + bits, uid, gid, etc) +Step 5: update or create inode from final fattr struct + +* add is_smb1_server() helper +* add is_inode_cache_good() helper +* move SMB1-backupcreds-getinfo-retry to separate func + cifs_backup_query_path_info(). +* move set-uniqueid code to separate func cifs_set_fattr_ino() +* don't clobber uniqueid from backup cred retry +* fix some probable corner cases memleaks + +Signed-off-by: Aurelien Aptel +Signed-off-by: Steve French +Acked-by: Paulo Alcantara +--- + fs/cifs/cifsglob.h | 6 + + fs/cifs/inode.c | 340 +++++++++++++++++++++++++++------------------ + 2 files changed, 207 insertions(+), 139 deletions(-) + +diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h +index 478b913f6f79..6bd917b4ee1d 100644 +--- a/fs/cifs/cifsglob.h ++++ b/fs/cifs/cifsglob.h +@@ -1967,4 +1967,10 @@ extern struct smb_version_values smb302_values; + #define ALT_SMB311_VERSION_STRING "3.11" + extern struct smb_version_operations smb311_operations; + extern struct smb_version_values smb311_values; ++ ++static inline bool is_smb1_server(struct TCP_Server_Info *server) ++{ ++ return strcmp(server->vals->version_string, SMB1_VERSION_STRING) == 0; ++} ++ + #endif /* _CIFS_GLOB_H */ +diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c +index df9377828e2f..1fec2e7d796a 100644 +--- a/fs/cifs/inode.c ++++ b/fs/cifs/inode.c +@@ -727,22 +727,138 @@ static __u64 simple_hashstr(const char *str) + return hash; + } + ++/** ++ * cifs_backup_query_path_info - SMB1 fallback code to get ino ++ * ++ * Fallback code to get file metadata when we don't have access to ++ * @full_path (EACCESS) and have backup creds. ++ * ++ * @data will be set to search info result buffer ++ * @resp_buf will be set to cifs resp buf and needs to be freed with ++ * cifs_buf_release() when done with @data. ++ */ ++static int ++cifs_backup_query_path_info(int xid, ++ struct cifs_tcon *tcon, ++ struct super_block *sb, ++ const char *full_path, ++ void **resp_buf, ++ FILE_ALL_INFO **data) ++{ ++ struct cifs_sb_info *cifs_sb = CIFS_SB(sb); ++ struct cifs_search_info info = {0}; ++ u16 flags; ++ int rc; ++ ++ *resp_buf = NULL; ++ info.endOfSearch = false; ++ if (tcon->unix_ext) ++ info.info_level = SMB_FIND_FILE_UNIX; ++ else if ((tcon->ses->capabilities & ++ tcon->ses->server->vals->cap_nt_find) == 0) ++ info.info_level = SMB_FIND_FILE_INFO_STANDARD; ++ else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) ++ info.info_level = SMB_FIND_FILE_ID_FULL_DIR_INFO; ++ else /* no srvino useful for fallback to some netapp */ ++ info.info_level = SMB_FIND_FILE_DIRECTORY_INFO; ++ ++ flags = CIFS_SEARCH_CLOSE_ALWAYS | ++ CIFS_SEARCH_CLOSE_AT_END | ++ CIFS_SEARCH_BACKUP_SEARCH; ++ ++ rc = CIFSFindFirst(xid, tcon, full_path, ++ cifs_sb, NULL, flags, &info, false); ++ if (rc) ++ return rc; ++ ++ *resp_buf = (void *)info.ntwrk_buf_start; ++ *data = (FILE_ALL_INFO *)info.srch_entries_start; ++ return 0; ++} ++ ++static void ++cifs_set_fattr_ino(int xid, ++ struct cifs_tcon *tcon, ++ struct super_block *sb, ++ struct inode **inode, ++ const char *full_path, ++ FILE_ALL_INFO *data, ++ struct cifs_fattr *fattr) ++{ ++ struct cifs_sb_info *cifs_sb = CIFS_SB(sb); ++ struct TCP_Server_Info *server = tcon->ses->server; ++ int rc; ++ ++ if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)) { ++ if (*inode) ++ fattr->cf_uniqueid = CIFS_I(*inode)->uniqueid; ++ else ++ fattr->cf_uniqueid = iunique(sb, ROOT_I); ++ return; ++ } ++ ++ /* ++ * If we have an inode pass a NULL tcon to ensure we don't ++ * make a round trip to the server. This only works for SMB2+. ++ */ ++ rc = server->ops->get_srv_inum(xid, ++ *inode ? NULL : tcon, ++ cifs_sb, full_path, ++ &fattr->cf_uniqueid, ++ data); ++ if (rc) { ++ /* ++ * If that fails reuse existing ino or generate one ++ * and disable server ones ++ */ ++ if (*inode) ++ fattr->cf_uniqueid = CIFS_I(*inode)->uniqueid; ++ else { ++ fattr->cf_uniqueid = iunique(sb, ROOT_I); ++ cifs_autodisable_serverino(cifs_sb); ++ } ++ return; ++ } ++ ++ /* If no errors, check for zero root inode (invalid) */ ++ if (fattr->cf_uniqueid == 0 && strlen(full_path) == 0) { ++ cifs_dbg(FYI, "Invalid (0) inodenum\n"); ++ if (*inode) { ++ /* reuse */ ++ fattr->cf_uniqueid = CIFS_I(*inode)->uniqueid; ++ } else { ++ /* make an ino by hashing the UNC */ ++ fattr->cf_flags |= CIFS_FATTR_FAKE_ROOT_INO; ++ fattr->cf_uniqueid = simple_hashstr(tcon->treeName); ++ } ++ } ++} ++ ++static inline bool is_inode_cache_good(struct inode *ino) ++{ ++ return ino && CIFS_CACHE_READ(CIFS_I(ino)) && CIFS_I(ino)->time != 0; ++} ++ + int +-cifs_get_inode_info(struct inode **inode, const char *full_path, +- FILE_ALL_INFO *data, struct super_block *sb, int xid, ++cifs_get_inode_info(struct inode **inode, ++ const char *full_path, ++ FILE_ALL_INFO *in_data, ++ struct super_block *sb, int xid, + const struct cifs_fid *fid) + { +- __u16 srchflgs; +- int rc = 0, tmprc = ENOSYS; ++ + struct cifs_tcon *tcon; + struct TCP_Server_Info *server; + struct tcon_link *tlink; + struct cifs_sb_info *cifs_sb = CIFS_SB(sb); +- char *buf = NULL; + bool adjust_tz = false; +- struct cifs_fattr fattr; +- struct cifs_search_info *srchinf = NULL; ++ struct cifs_fattr fattr = {0}; + bool symlink = false; ++ FILE_ALL_INFO *data = in_data; ++ FILE_ALL_INFO *tmp_data = NULL; ++ void *smb1_backup_rsp_buf = NULL; ++ int rc = 0; ++ int tmprc = 0; + + tlink = cifs_sb_tlink(cifs_sb); + if (IS_ERR(tlink)) +@@ -750,142 +866,88 @@ cifs_get_inode_info(struct inode **inode, const char *full_path, + tcon = tlink_tcon(tlink); + server = tcon->ses->server; + +- cifs_dbg(FYI, "Getting info on %s\n", full_path); ++ /* ++ * 1. Fetch file metadata if not provided (data) ++ */ + +- if ((data == NULL) && (*inode != NULL)) { +- if (CIFS_CACHE_READ(CIFS_I(*inode)) && +- CIFS_I(*inode)->time != 0) { ++ if (!data) { ++ if (is_inode_cache_good(*inode)) { + cifs_dbg(FYI, "No need to revalidate cached inode sizes\n"); +- goto cgii_exit; ++ goto out; + } +- } +- +- /* if inode info is not passed, get it from server */ +- if (data == NULL) { +- if (!server->ops->query_path_info) { +- rc = -ENOSYS; +- goto cgii_exit; +- } +- buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL); +- if (buf == NULL) { ++ tmp_data = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL); ++ if (!tmp_data) { + rc = -ENOMEM; +- goto cgii_exit; ++ goto out; + } +- data = (FILE_ALL_INFO *)buf; +- rc = server->ops->query_path_info(xid, tcon, cifs_sb, full_path, +- data, &adjust_tz, &symlink); ++ rc = server->ops->query_path_info(xid, tcon, cifs_sb, ++ full_path, tmp_data, ++ &adjust_tz, &symlink); ++ data = tmp_data; + } + +- if (!rc) { +- cifs_all_info_to_fattr(&fattr, data, sb, adjust_tz, +- symlink); +- } else if (rc == -EREMOTE) { ++ /* ++ * 2. Convert it to internal cifs metadata (fattr) ++ */ ++ ++ switch (rc) { ++ case 0: ++ cifs_all_info_to_fattr(&fattr, data, sb, adjust_tz, symlink); ++ break; ++ case -EREMOTE: ++ /* DFS link, no metadata available on this server */ + cifs_create_dfs_fattr(&fattr, sb); + rc = 0; +- } else if ((rc == -EACCES) && backup_cred(cifs_sb) && +- (strcmp(server->vals->version_string, SMB1_VERSION_STRING) +- == 0)) { ++ break; ++ case -EACCES: + /* +- * For SMB2 and later the backup intent flag is already +- * sent if needed on open and there is no path based +- * FindFirst operation to use to retry with ++ * perm errors, try again with backup flags if possible ++ * ++ * For SMB2 and later the backup intent flag ++ * is already sent if needed on open and there ++ * is no path based FindFirst operation to use ++ * to retry with + */ ++ if (backup_cred(cifs_sb) && is_smb1_server(server)) { ++ /* for easier reading */ ++ FILE_DIRECTORY_INFO *fdi; ++ SEARCH_ID_FULL_DIR_INFO *si; + +- srchinf = kzalloc(sizeof(struct cifs_search_info), +- GFP_KERNEL); +- if (srchinf == NULL) { +- rc = -ENOMEM; +- goto cgii_exit; +- } +- +- srchinf->endOfSearch = false; +- if (tcon->unix_ext) +- srchinf->info_level = SMB_FIND_FILE_UNIX; +- else if ((tcon->ses->capabilities & +- tcon->ses->server->vals->cap_nt_find) == 0) +- srchinf->info_level = SMB_FIND_FILE_INFO_STANDARD; +- else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) +- srchinf->info_level = SMB_FIND_FILE_ID_FULL_DIR_INFO; +- else /* no srvino useful for fallback to some netapp */ +- srchinf->info_level = SMB_FIND_FILE_DIRECTORY_INFO; +- +- srchflgs = CIFS_SEARCH_CLOSE_ALWAYS | +- CIFS_SEARCH_CLOSE_AT_END | +- CIFS_SEARCH_BACKUP_SEARCH; ++ rc = cifs_backup_query_path_info(xid, tcon, sb, ++ full_path, ++ &smb1_backup_rsp_buf, ++ &data); ++ if (rc) ++ goto out; + +- rc = CIFSFindFirst(xid, tcon, full_path, +- cifs_sb, NULL, srchflgs, srchinf, false); +- if (!rc) { +- data = (FILE_ALL_INFO *)srchinf->srch_entries_start; ++ fdi = (FILE_DIRECTORY_INFO *)data; ++ si = (SEARCH_ID_FULL_DIR_INFO *)data; + +- cifs_dir_info_to_fattr(&fattr, +- (FILE_DIRECTORY_INFO *)data, cifs_sb); +- fattr.cf_uniqueid = le64_to_cpu( +- ((SEARCH_ID_FULL_DIR_INFO *)data)->UniqueId); +- +- cifs_buf_release(srchinf->ntwrk_buf_start); ++ cifs_dir_info_to_fattr(&fattr, fdi, cifs_sb); ++ fattr.cf_uniqueid = le64_to_cpu(si->UniqueId); ++ /* uniqueid set, skip get inum step */ ++ goto handle_mnt_opt; ++ } else { ++ /* nothing we can do, bail out */ ++ goto out; + } +- kfree(srchinf); +- if (rc) +- goto cgii_exit; +- } else +- goto cgii_exit; +- +- /* +- * If an inode wasn't passed in, then get the inode number +- * +- * Is an i_ino of zero legal? Can we use that to check if the server +- * supports returning inode numbers? Are there other sanity checks we +- * can use to ensure that the server is really filling in that field? +- */ +- if (*inode == NULL) { +- if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) { +- if (server->ops->get_srv_inum) +- tmprc = server->ops->get_srv_inum(xid, +- tcon, cifs_sb, full_path, +- &fattr.cf_uniqueid, data); +- if (tmprc) { +- cifs_dbg(FYI, "GetSrvInodeNum rc %d\n", +- tmprc); +- fattr.cf_uniqueid = iunique(sb, ROOT_I); +- cifs_autodisable_serverino(cifs_sb); +- } else if ((fattr.cf_uniqueid == 0) && +- strlen(full_path) == 0) { +- /* some servers ret bad root ino ie 0 */ +- cifs_dbg(FYI, "Invalid (0) inodenum\n"); +- fattr.cf_flags |= +- CIFS_FATTR_FAKE_ROOT_INO; +- fattr.cf_uniqueid = +- simple_hashstr(tcon->treeName); +- } +- } else +- fattr.cf_uniqueid = iunique(sb, ROOT_I); +- } else { +- if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) +- && server->ops->get_srv_inum) { +- /* +- * Pass a NULL tcon to ensure we don't make a round +- * trip to the server. This only works for SMB2+. +- */ +- tmprc = server->ops->get_srv_inum(xid, +- NULL, cifs_sb, full_path, +- &fattr.cf_uniqueid, data); +- if (tmprc) +- fattr.cf_uniqueid = CIFS_I(*inode)->uniqueid; +- else if ((fattr.cf_uniqueid == 0) && +- strlen(full_path) == 0) { +- /* +- * Reuse existing root inode num since +- * inum zero for root causes ls of . and .. to +- * not be returned +- */ +- cifs_dbg(FYI, "Srv ret 0 inode num for root\n"); +- fattr.cf_uniqueid = CIFS_I(*inode)->uniqueid; +- } +- } else +- fattr.cf_uniqueid = CIFS_I(*inode)->uniqueid; ++ break; ++ default: ++ cifs_dbg(FYI, "%s: unhandled err rc %d\n", __func__, rc); ++ goto out; + } + ++ /* ++ * 3. Get or update inode number (fattr.cf_uniqueid) ++ */ ++ ++ cifs_set_fattr_ino(xid, tcon, sb, inode, full_path, data, &fattr); ++ ++ /* ++ * 4. Tweak fattr based on mount options ++ */ ++ ++handle_mnt_opt: + /* query for SFU type info if supported and needed */ + if (fattr.cf_cifsattrs & ATTR_SYSTEM && + cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) { +@@ -900,16 +962,15 @@ cifs_get_inode_info(struct inode **inode, const char *full_path, + full_path, fid); + if (rc) { + cifs_dbg(FYI, "%s: Get mode from SID failed. rc=%d\n", +- __func__, rc); +- goto cgii_exit; ++ __func__, rc); ++ goto out; + } + } else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) { + rc = cifs_acl_to_fattr(cifs_sb, &fattr, *inode, false, +- full_path, fid); +- if (rc) { ++ full_path, fid); if (rc) { + cifs_dbg(FYI, "%s: Getting ACL failed with error: %d\n", + __func__, rc); +- goto cgii_exit; ++ goto out; + } + } + +@@ -925,6 +986,10 @@ cifs_get_inode_info(struct inode **inode, const char *full_path, + cifs_dbg(FYI, "check_mf_symlink: %d\n", tmprc); + } + ++ /* ++ * 5. Update inode with final fattr data ++ */ ++ + if (!*inode) { + *inode = cifs_iget(sb, &fattr); + if (!*inode) +@@ -937,7 +1002,7 @@ cifs_get_inode_info(struct inode **inode, const char *full_path, + CIFS_I(*inode)->uniqueid != fattr.cf_uniqueid)) { + CIFS_I(*inode)->time = 0; /* force reval */ + rc = -ESTALE; +- goto cgii_exit; ++ goto out; + } + + /* if filetype is different, return error */ +@@ -945,18 +1010,15 @@ cifs_get_inode_info(struct inode **inode, const char *full_path, + (fattr.cf_mode & S_IFMT))) { + CIFS_I(*inode)->time = 0; /* force reval */ + rc = -ESTALE; +- goto cgii_exit; ++ goto out; + } + + cifs_fattr_to_inode(*inode, &fattr); + } +- +-cgii_exit: +- if ((*inode) && ((*inode)->i_ino == 0)) +- cifs_dbg(FYI, "inode number of zero returned\n"); +- +- kfree(buf); ++out: ++ cifs_buf_release(smb1_backup_rsp_buf); + cifs_put_tlink(tlink); ++ kfree(tmp_data); + return rc; + } + +-- +2.25.1 + + diff --git a/patches.suse/Crypto-chelsio-Fixes-a-deadlock-between-rtnl_lock-an.patch b/patches.suse/Crypto-chelsio-Fixes-a-deadlock-between-rtnl_lock-an.patch new file mode 100644 index 0000000..e14aac8 --- /dev/null +++ b/patches.suse/Crypto-chelsio-Fixes-a-deadlock-between-rtnl_lock-an.patch @@ -0,0 +1,102 @@ +From 876aa9f527cd0ddc857337aba3683298b3abe6ab Mon Sep 17 00:00:00 2001 +From: Ayush Sawal +Date: Mon, 30 Mar 2020 20:48:53 +0530 +Subject: [PATCH] Crypto: chelsio - Fixes a deadlock between rtnl_lock and uld_mutex +Git-commit: 876aa9f527cd0ddc857337aba3683298b3abe6ab +Patch-mainline: v5.7-rc1 +References: bsc#1111666 + +The locks are taken in this order during driver registration +(uld_mutex), at: cxgb4_register_uld.part.14+0x49/0xd60 [cxgb4] +(rtnl_mutex), at: rtnetlink_rcv_msg+0x2db/0x400 +(uld_mutex), at: cxgb_up+0x3a/0x7b0 [cxgb4] +(rtnl_mutex), at: chcr_add_xfrmops+0x83/0xa0 [chcr](stucked here) + +To avoid this now the netdev features are updated after the +cxgb4_register_uld function is completed. + +Fixes: 6dad4e8ab3ec6 ("chcr: Add support for Inline IPSec"). + +Signed-off-by: Ayush Sawal +Signed-off-by: David S. Miller +Acked-by: Takashi Iwai + +--- + drivers/crypto/chelsio/chcr_core.c | 32 ++++++++++++++++++++++++++++---- + drivers/crypto/chelsio/chcr_ipsec.c | 2 -- + 2 files changed, 28 insertions(+), 6 deletions(-) + +--- a/drivers/crypto/chelsio/chcr_core.c ++++ b/drivers/crypto/chelsio/chcr_core.c +@@ -33,6 +33,10 @@ static int cpl_fw6_pld_handler(struct ch + static void *chcr_uld_add(const struct cxgb4_lld_info *lld); + static int chcr_uld_state_change(void *handle, enum cxgb4_state state); + ++#ifdef CONFIG_CHELSIO_IPSEC_INLINE ++static void update_netdev_features(void); ++#endif /* CONFIG_CHELSIO_IPSEC_INLINE */ ++ + static chcr_handler_func work_handlers[NUM_CPL_CMDS] = { + [CPL_FW6_PLD] = cpl_fw6_pld_handler, + }; +@@ -203,10 +207,6 @@ static void *chcr_uld_add(const struct c + } + u_ctx->lldi = *lld; + chcr_dev_init(u_ctx); +-#ifdef CONFIG_CHELSIO_IPSEC_INLINE +- if (lld->crypto & ULP_CRYPTO_IPSEC_INLINE) +- chcr_add_xfrmops(lld); +-#endif /* CONFIG_CHELSIO_IPSEC_INLINE */ + out: + return u_ctx; + } +@@ -282,6 +282,24 @@ static int chcr_uld_state_change(void *h + return ret; + } + ++#ifdef CONFIG_CHELSIO_IPSEC_INLINE ++static void update_netdev_features(void) ++{ ++ struct uld_ctx *u_ctx, *tmp; ++ ++ mutex_lock(&drv_data.drv_mutex); ++ list_for_each_entry_safe(u_ctx, tmp, &drv_data.inact_dev, entry) { ++ if (u_ctx->lldi.crypto & ULP_CRYPTO_IPSEC_INLINE) ++ chcr_add_xfrmops(&u_ctx->lldi); ++ } ++ list_for_each_entry_safe(u_ctx, tmp, &drv_data.act_dev, entry) { ++ if (u_ctx->lldi.crypto & ULP_CRYPTO_IPSEC_INLINE) ++ chcr_add_xfrmops(&u_ctx->lldi); ++ } ++ mutex_unlock(&drv_data.drv_mutex); ++} ++#endif /* CONFIG_CHELSIO_IPSEC_INLINE */ ++ + static int __init chcr_crypto_init(void) + { + INIT_LIST_HEAD(&drv_data.act_dev); +@@ -291,6 +309,12 @@ static int __init chcr_crypto_init(void) + drv_data.last_dev = NULL; + cxgb4_register_uld(CXGB4_ULD_CRYPTO, &chcr_uld_info); + ++ #ifdef CONFIG_CHELSIO_IPSEC_INLINE ++ rtnl_lock(); ++ update_netdev_features(); ++ rtnl_unlock(); ++ #endif /* CONFIG_CHELSIO_IPSEC_INLINE */ ++ + return 0; + } + +--- a/drivers/crypto/chelsio/chcr_ipsec.c ++++ b/drivers/crypto/chelsio/chcr_ipsec.c +@@ -99,9 +99,7 @@ void chcr_add_xfrmops(const struct cxgb4 + netdev->xfrmdev_ops = &chcr_xfrmdev_ops; + netdev->hw_enc_features |= NETIF_F_HW_ESP; + netdev->features |= NETIF_F_HW_ESP; +- rtnl_lock(); + netdev_change_features(netdev); +- rtnl_unlock(); + } + } + diff --git a/patches.suse/Crypto-chelsio-Fixes-a-hang-issue-during-driver-regi.patch b/patches.suse/Crypto-chelsio-Fixes-a-hang-issue-during-driver-regi.patch new file mode 100644 index 0000000..148c3f6 --- /dev/null +++ b/patches.suse/Crypto-chelsio-Fixes-a-hang-issue-during-driver-regi.patch @@ -0,0 +1,46 @@ +From ad59ddd02de26271b89564962e74d689f1a30b49 Mon Sep 17 00:00:00 2001 +From: Ayush Sawal +Date: Mon, 30 Mar 2020 20:48:52 +0530 +Subject: [PATCH] Crypto: chelsio - Fixes a hang issue during driver registration +Git-commit: ad59ddd02de26271b89564962e74d689f1a30b49 +Patch-mainline: v5.7-rc1 +References: bsc#1111666 + +This issue occurs only when multiadapters are present. Hang +happens because assign_chcr_device returns u_ctx pointer of +adapter which is not yet initialized as for this adapter cxgb_up +is not been called yet. + +The last_dev pointer is used to determine u_ctx pointer and it +is initialized two times in chcr_uld_add in chcr_dev_add respectively. + +The fix here is don't initialize the last_dev pointer during +chcr_uld_add. Only assign to value to it when the adapter's +initialization is completed i.e in chcr_dev_add. + +Fixes: fef4912b66d62 ("crypto: chelsio - Handle PCI shutdown event"). + +Signed-off-by: Ayush Sawal +Signed-off-by: David S. Miller +Acked-by: Takashi Iwai + +--- + drivers/crypto/chelsio/chcr_core.c | 2 -- + 1 file changed, 2 deletions(-) + +diff --git a/drivers/crypto/chelsio/chcr_core.c b/drivers/crypto/chelsio/chcr_core.c +index 0015810214a9..f1499534a0fe 100644 +--- a/drivers/crypto/chelsio/chcr_core.c ++++ b/drivers/crypto/chelsio/chcr_core.c +@@ -129,8 +129,6 @@ static void chcr_dev_init(struct uld_ctx *u_ctx) + atomic_set(&dev->inflight, 0); + mutex_lock(&drv_data.drv_mutex); + list_add_tail(&u_ctx->entry, &drv_data.inact_dev); +- if (!drv_data.last_dev) +- drv_data.last_dev = u_ctx; + mutex_unlock(&drv_data.drv_mutex); + } + +-- +2.16.4 + diff --git a/patches.suse/EDAC-ghes-Make-platform-based-whitelisting-x86-only.patch b/patches.suse/EDAC-ghes-Make-platform-based-whitelisting-x86-only.patch new file mode 100644 index 0000000..bebabd3 --- /dev/null +++ b/patches.suse/EDAC-ghes-Make-platform-based-whitelisting-x86-only.patch @@ -0,0 +1,55 @@ +From: Borislav Petkov +Date: Fri, 18 May 2018 13:13:31 +0200 +Subject: EDAC, ghes: Make platform-based whitelisting x86-only + +Git-commit: eaa3a1d46cfdbf1af50311e7a22f5d38c0418b56 +Patch-mainline: v4.18-rc1 +References: bsc#1158187 + +ARM machines all have DMI tables so if they request hw error reporting +through GHES, then the driver should be able to detect DIMMs and report +errors successfully (famous last words :)). + +Make the platform-based list x86-specific so that ghes_edac can load on +ARM. + +Reported-by: Qiang Zheng +Signed-off-by: Borislav Petkov +Reviewed-by: James Morse +Tested-by: James Morse +Tested-by: Qiang Zheng +Link: https://lkml.kernel.org/r/1526039543-180996-1-git-send-email-zhengqiang10@huawei.com +Signed-off-by: Mian Yousaf Kaukab +--- + drivers/edac/ghes_edac.c | 14 +++++++++----- + 1 file changed, 9 insertions(+), 5 deletions(-) + +diff --git a/drivers/edac/ghes_edac.c b/drivers/edac/ghes_edac.c +index 863fbf3db29f..473aeec4b1da 100644 +--- a/drivers/edac/ghes_edac.c ++++ b/drivers/edac/ghes_edac.c +@@ -440,12 +440,16 @@ int ghes_edac_register(struct ghes *ghes, struct device *dev) + struct mem_ctl_info *mci; + struct edac_mc_layer layers[1]; + struct ghes_edac_dimm_fill dimm_fill; +- int idx; ++ int idx = -1; + +- /* Check if safe to enable on this system */ +- idx = acpi_match_platform_list(plat_list); +- if (!force_load && idx < 0) +- return -ENODEV; ++ if (IS_ENABLED(CONFIG_X86)) { ++ /* Check if safe to enable on this system */ ++ idx = acpi_match_platform_list(plat_list); ++ if (!force_load && idx < 0) ++ return -ENODEV; ++ } else { ++ idx = 0; ++ } + + /* + * We have only one logical memory controller to which all DIMMs belong. +-- +2.16.4 + diff --git a/patches.suse/EDAC-skx_common-downgrade-message-importance-on-miss.patch b/patches.suse/EDAC-skx_common-downgrade-message-importance-on-miss.patch new file mode 100644 index 0000000..dfb73ec --- /dev/null +++ b/patches.suse/EDAC-skx_common-downgrade-message-importance-on-miss.patch @@ -0,0 +1,42 @@ +From 854bb48018d5da261d438b2232fa683bdb553979 Mon Sep 17 00:00:00 2001 +From: Aristeu Rozanski +Date: Wed, 4 Dec 2019 16:23:25 -0500 +Subject: [PATCH] EDAC: skx_common: downgrade message importance on missing PCI + device +References: bsc#1165581 +Git-commit: 854bb48018d5da261d438b2232fa683bdb553979 +Patch-mainline: v5.6-rc1 + +Both skx_edac and i10nm_edac drivers are loaded based on the matching CPU being +available which leads the module to be automatically loaded in virtual machines +as well. That will fail due the missing PCI devices. In both drivers the first +function to make use of the PCI devices is skx_get_hi_lo() will simply print + + EDAC skx: Can't get tolm/tohm + +for each CPU core, which is noisy. This patch makes it a debug message. + +Signed-off-by: Aristeu Rozanski +Signed-off-by: Tony Luck +Link: https://lore.kernel.org/r/20191204212325.c4k47p5hrnn3vpb5@redhat.com +Signed-off-by: Thomas Abraham +--- + drivers/edac/skx_common.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/edac/skx_common.c b/drivers/edac/skx_common.c +index 95662a4ff4c4..99bbaf629b8d 100644 +--- a/drivers/edac/skx_common.c ++++ b/drivers/edac/skx_common.c +@@ -256,7 +256,7 @@ int skx_get_hi_lo(unsigned int did, int off[], u64 *tolm, u64 *tohm) + + pdev = pci_get_device(PCI_VENDOR_ID_INTEL, did, NULL); + if (!pdev) { +- skx_printk(KERN_ERR, "Can't get tolm/tohm\n"); ++ edac_dbg(2, "Can't get tolm/tohm\n"); + return -ENODEV; + } + +-- +2.16.4 + diff --git a/patches.suse/HID-apple-Add-support-for-recent-firmware-on-Magic-K.patch b/patches.suse/HID-apple-Add-support-for-recent-firmware-on-Magic-K.patch new file mode 100644 index 0000000..2facddc --- /dev/null +++ b/patches.suse/HID-apple-Add-support-for-recent-firmware-on-Magic-K.patch @@ -0,0 +1,37 @@ +From e433be929e63265b7412478eb7ff271467aee2d7 Mon Sep 17 00:00:00 2001 +From: Mansour Behabadi +Date: Wed, 29 Jan 2020 17:26:31 +1100 +Subject: [PATCH] HID: apple: Add support for recent firmware on Magic Keyboards +Git-commit: e433be929e63265b7412478eb7ff271467aee2d7 +Patch-mainline: v5.6-rc4 +References: bsc#1051510 + +Magic Keyboards with more recent firmware (0x0100) report Fn key differently. +Without this patch, Fn key may not behave as expected and may not be +configurable via hid_apple fnmode module parameter. + +Signed-off-by: Mansour Behabadi +Signed-off-by: Jiri Kosina +Acked-by: Takashi Iwai + +--- + drivers/hid/hid-apple.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/hid/hid-apple.c b/drivers/hid/hid-apple.c +index 6ac8becc2372..d732d1d10caf 100644 +--- a/drivers/hid/hid-apple.c ++++ b/drivers/hid/hid-apple.c +@@ -340,7 +340,8 @@ static int apple_input_mapping(struct hid_device *hdev, struct hid_input *hi, + unsigned long **bit, int *max) + { + if (usage->hid == (HID_UP_CUSTOM | 0x0003) || +- usage->hid == (HID_UP_MSVENDOR | 0x0003)) { ++ usage->hid == (HID_UP_MSVENDOR | 0x0003) || ++ usage->hid == (HID_UP_HPVENDOR2 | 0x0003)) { + /* The fn key on Apple USB keyboards */ + set_bit(EV_REP, hi->input->evbit); + hid_map_usage_clear(hi, usage, bit, max, EV_KEY, KEY_FN); +-- +2.16.4 + diff --git a/patches.suse/HID-core-fix-off-by-one-memset-in-hid_report_raw_eve.patch b/patches.suse/HID-core-fix-off-by-one-memset-in-hid_report_raw_eve.patch new file mode 100644 index 0000000..d9a4a21 --- /dev/null +++ b/patches.suse/HID-core-fix-off-by-one-memset-in-hid_report_raw_eve.patch @@ -0,0 +1,49 @@ +From 5ebdffd25098898aff1249ae2f7dbfddd76d8f8f Mon Sep 17 00:00:00 2001 +From: Johan Korsnes +Date: Fri, 17 Jan 2020 13:08:35 +0100 +Subject: [PATCH] HID: core: fix off-by-one memset in hid_report_raw_event() +Git-commit: 5ebdffd25098898aff1249ae2f7dbfddd76d8f8f +Patch-mainline: v5.6-rc4 +References: bsc#1051510 + +In case a report is greater than HID_MAX_BUFFER_SIZE, it is truncated, +but the report-number byte is not correctly handled. This results in a +off-by-one in the following memset, causing a kernel Oops and ensuing +system crash. + +Note: With commit 8ec321e96e05 ("HID: Fix slab-out-of-bounds read in +hid_field_extract") I no longer hit the kernel Oops as we instead fail +"controlled" at probe if there is a report too long in the HID +report-descriptor. hid_report_raw_event() is an exported symbol, so +presumabely we cannot always rely on this being the case. + +Fixes: 966922f26c7f ("HID: fix a crash in hid_report_raw_event() function.") +Signed-off-by: Johan Korsnes +Cc: Armando Visconti +Cc: Jiri Kosina +Cc: Alan Stern +Signed-off-by: Jiri Kosina +Acked-by: Takashi Iwai + +--- + drivers/hid/hid-core.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c +index 851fe54ea59e..359616e3efbb 100644 +--- a/drivers/hid/hid-core.c ++++ b/drivers/hid/hid-core.c +@@ -1741,7 +1741,9 @@ int hid_report_raw_event(struct hid_device *hid, int type, u8 *data, u32 size, + + rsize = ((report->size - 1) >> 3) + 1; + +- if (rsize > HID_MAX_BUFFER_SIZE) ++ if (report_enum->numbered && rsize >= HID_MAX_BUFFER_SIZE) ++ rsize = HID_MAX_BUFFER_SIZE - 1; ++ else if (rsize > HID_MAX_BUFFER_SIZE) + rsize = HID_MAX_BUFFER_SIZE; + + if (csize < rsize) { +-- +2.16.4 + diff --git a/patches.suse/IB-hfi1-Close-window-for-pq-and-request-coliding.patch b/patches.suse/IB-hfi1-Close-window-for-pq-and-request-coliding.patch new file mode 100644 index 0000000..3865e42 --- /dev/null +++ b/patches.suse/IB-hfi1-Close-window-for-pq-and-request-coliding.patch @@ -0,0 +1,267 @@ +From: Mike Marciniszyn +Date: Mon, 10 Feb 2020 08:10:33 -0500 +Subject: IB/hfi1: Close window for pq and request coliding +Patch-mainline: v5.6-rc2 +Git-commit: be8638344c70bf492963ace206a9896606b6922d +References: bsc#1060463 FATE#323043 + +Cleaning up a pq can result in the following warning and panic: + + WARNING: CPU: 52 PID: 77418 at lib/list_debug.c:53 __list_del_entry+0x63/0xd0 + list_del corruption, ffff88cb2c6ac068->next is LIST_POISON1 (dead000000000100) + Modules linked in: mmfs26(OE) mmfslinux(OE) tracedev(OE) 8021q garp mrp ib_isert iscsi_target_mod target_core_mod crc_t10dif crct10dif_generic opa_vnic rpcrdma ib_iser libiscsi scsi_transport_iscsi ib_ipoib(OE) bridge stp llc iTCO_wdt iTCO_vendor_support intel_powerclamp coretemp intel_rapl iosf_mbi kvm_intel kvm irqbypass crct10dif_pclmul crct10dif_common crc32_pclmul ghash_clmulni_intel ast aesni_intel ttm lrw gf128mul glue_helper ablk_helper drm_kms_helper cryptd syscopyarea sysfillrect sysimgblt fb_sys_fops drm pcspkr joydev lpc_ich mei_me drm_panel_orientation_quirks i2c_i801 mei wmi ipmi_si ipmi_devintf ipmi_msghandler nfit libnvdimm acpi_power_meter acpi_pad hfi1(OE) rdmavt(OE) rdma_ucm ib_ucm ib_uverbs ib_umad rdma_cm ib_cm iw_cm ib_core binfmt_misc numatools(OE) xpmem(OE) ip_tables + nfsv3 nfs_acl nfs lockd grace sunrpc fscache igb ahci i2c_algo_bit libahci dca ptp libata pps_core crc32c_intel [last unloaded: i2c_algo_bit] + CPU: 52 PID: 77418 Comm: pvbatch Kdump: loaded Tainted: G OE ------------ 3.10.0-957.38.3.el7.x86_64 #1 + Hardware name: HPE.COM HPE SGI 8600-XA730i Gen10/X11DPT-SB-SG007, BIOS SBED1229 01/22/2019 + Call Trace: + [] dump_stack+0x19/0x1b + [] __warn+0xd8/0x100 + [] warn_slowpath_fmt+0x5f/0x80 + [] __list_del_entry+0x63/0xd0 + [] list_del+0xd/0x30 + [] kmem_cache_destroy+0x50/0x110 + [] hfi1_user_sdma_free_queues+0xf0/0x200 [hfi1] + [] hfi1_file_close+0x70/0x1e0 [hfi1] + [] __fput+0xec/0x260 + [] ____fput+0xe/0x10 + [] task_work_run+0xbb/0xe0 + [] do_notify_resume+0xa5/0xc0 + [] int_signal+0x12/0x17 + BUG: unable to handle kernel NULL pointer dereference at 0000000000000010 + IP: [] kmem_cache_close+0x7e/0x300 + PGD 2cdab19067 PUD 2f7bfdb067 PMD 0 + Oops: 0000 [#1] SMP + Modules linked in: mmfs26(OE) mmfslinux(OE) tracedev(OE) 8021q garp mrp ib_isert iscsi_target_mod target_core_mod crc_t10dif crct10dif_generic opa_vnic rpcrdma ib_iser libiscsi scsi_transport_iscsi ib_ipoib(OE) bridge stp llc iTCO_wdt iTCO_vendor_support intel_powerclamp coretemp intel_rapl iosf_mbi kvm_intel kvm irqbypass crct10dif_pclmul crct10dif_common crc32_pclmul ghash_clmulni_intel ast aesni_intel ttm lrw gf128mul glue_helper ablk_helper drm_kms_helper cryptd syscopyarea sysfillrect sysimgblt fb_sys_fops drm pcspkr joydev lpc_ich mei_me drm_panel_orientation_quirks i2c_i801 mei wmi ipmi_si ipmi_devintf ipmi_msghandler nfit libnvdimm acpi_power_meter acpi_pad hfi1(OE) rdmavt(OE) rdma_ucm ib_ucm ib_uverbs ib_umad rdma_cm ib_cm iw_cm ib_core binfmt_misc numatools(OE) xpmem(OE) ip_tables + nfsv3 nfs_acl nfs lockd grace sunrpc fscache igb ahci i2c_algo_bit libahci dca ptp libata pps_core crc32c_intel [last unloaded: i2c_algo_bit] + CPU: 52 PID: 77418 Comm: pvbatch Kdump: loaded Tainted: G W OE ------------ 3.10.0-957.38.3.el7.x86_64 #1 + Hardware name: HPE.COM HPE SGI 8600-XA730i Gen10/X11DPT-SB-SG007, BIOS SBED1229 01/22/2019 + task: ffff88cc26db9040 ti: ffff88b5393a8000 task.ti: ffff88b5393a8000 + RIP: 0010:[] [] kmem_cache_close+0x7e/0x300 + RSP: 0018:ffff88b5393abd60 EFLAGS: 00010287 + RAX: 0000000000000000 RBX: ffff88cb2c6ac000 RCX: 0000000000000003 + RDX: 0000000000000400 RSI: 0000000000000400 RDI: ffffffff9095b800 + RBP: ffff88b5393abdb0 R08: ffffffff9095b808 R09: ffffffff8ff77c19 + R10: ffff88b73ce1f160 R11: ffffddecddde9800 R12: ffff88cb2c6ac000 + R13: 000000000000000c R14: ffff88cf3fdca780 R15: 0000000000000000 + FS: 00002aaaaab52500(0000) GS:ffff88b73ce00000(0000) knlGS:0000000000000000 + CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 + CR2: 0000000000000010 CR3: 0000002d27664000 CR4: 00000000007607e0 + DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 + DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 + PKRU: 55555554 + Call Trace: + [] __kmem_cache_shutdown+0x14/0x80 + [] kmem_cache_destroy+0x58/0x110 + [] hfi1_user_sdma_free_queues+0xf0/0x200 [hfi1] + [] hfi1_file_close+0x70/0x1e0 [hfi1] + [] __fput+0xec/0x260 + [] ____fput+0xe/0x10 + [] task_work_run+0xbb/0xe0 + [] do_notify_resume+0xa5/0xc0 + [] int_signal+0x12/0x17 + Code: 00 00 ba 00 04 00 00 0f 4f c2 3d 00 04 00 00 89 45 bc 0f 84 e7 01 00 00 48 63 45 bc 49 8d 04 c4 48 89 45 b0 48 8b 80 c8 00 00 00 <48> 8b 78 10 48 89 45 c0 48 83 c0 10 48 89 45 d0 48 8b 17 48 39 + RIP [] kmem_cache_close+0x7e/0x300 + RSP + CR2: 0000000000000010 + +The panic is the result of slab entries being freed during the destruction +of the pq slab. + +The code attempts to quiesce the pq, but looking for n_req == 0 doesn't +account for new requests. + +Fix the issue by using SRCU to get a pq pointer and adjust the pq free +logic to NULL the fd pq pointer prior to the quiesce. + +Fixes: e87473bc1b6c ("IB/hfi1: Only set fd pointer when base context is completely initialized") +Link: https://lore.kernel.org/r/20200210131033.87408.81174.stgit@awfm-01.aw.intel.com +Reviewed-by: Kaike Wan +Signed-off-by: Mike Marciniszyn +Signed-off-by: Dennis Dalessandro +Signed-off-by: Jason Gunthorpe +Acked-by: Thomas Bogendoerfer +--- + drivers/infiniband/hw/hfi1/file_ops.c | 52 ++++++++++++++++++------------ + drivers/infiniband/hw/hfi1/hfi.h | 5 ++ + drivers/infiniband/hw/hfi1/user_exp_rcv.c | 3 - + drivers/infiniband/hw/hfi1/user_sdma.c | 17 ++++++--- + 4 files changed, 48 insertions(+), 29 deletions(-) + +--- a/drivers/infiniband/hw/hfi1/file_ops.c ++++ b/drivers/infiniband/hw/hfi1/file_ops.c +@@ -199,23 +199,24 @@ static int hfi1_file_open(struct inode * + + fd = kzalloc(sizeof(*fd), GFP_KERNEL); + +- if (fd) { +- fd->rec_cpu_num = -1; /* no cpu affinity by default */ +- fd->mm = current->mm; +- mmgrab(fd->mm); +- fd->dd = dd; +- kobject_get(&fd->dd->kobj); +- fp->private_data = fd; +- } else { +- fp->private_data = NULL; +- +- if (atomic_dec_and_test(&dd->user_refcount)) +- complete(&dd->user_comp); +- +- return -ENOMEM; +- } +- ++ if (!fd || init_srcu_struct(&fd->pq_srcu)) ++ goto nomem; ++ spin_lock_init(&fd->pq_rcu_lock); ++ spin_lock_init(&fd->tid_lock); ++ spin_lock_init(&fd->invalid_lock); ++ fd->rec_cpu_num = -1; /* no cpu affinity by default */ ++ fd->mm = current->mm; ++ mmgrab(fd->mm); ++ fd->dd = dd; ++ kobject_get(&fd->dd->kobj); ++ fp->private_data = fd; + return 0; ++nomem: ++ kfree(fd); ++ fp->private_data = NULL; ++ if (atomic_dec_and_test(&dd->user_refcount)) ++ complete(&dd->user_comp); ++ return -ENOMEM; + } + + static long hfi1_file_ioctl(struct file *fp, unsigned int cmd, +@@ -354,21 +355,30 @@ static long hfi1_file_ioctl(struct file + static ssize_t hfi1_write_iter(struct kiocb *kiocb, struct iov_iter *from) + { + struct hfi1_filedata *fd = kiocb->ki_filp->private_data; +- struct hfi1_user_sdma_pkt_q *pq = fd->pq; ++ struct hfi1_user_sdma_pkt_q *pq; + struct hfi1_user_sdma_comp_q *cq = fd->cq; + int done = 0, reqs = 0; + unsigned long dim = from->nr_segs; ++ int idx; + +- if (!cq || !pq) ++ idx = srcu_read_lock(&fd->pq_srcu); ++ pq = srcu_dereference(fd->pq, &fd->pq_srcu); ++ if (!cq || !pq) { ++ srcu_read_unlock(&fd->pq_srcu, idx); + return -EIO; ++ } + +- if (!iter_is_iovec(from) || !dim) ++ if (!iter_is_iovec(from) || !dim) { ++ srcu_read_unlock(&fd->pq_srcu, idx); + return -EINVAL; ++ } + + trace_hfi1_sdma_request(fd->dd, fd->uctxt->ctxt, fd->subctxt, dim); + +- if (atomic_read(&pq->n_reqs) == pq->n_max_reqs) ++ if (atomic_read(&pq->n_reqs) == pq->n_max_reqs) { ++ srcu_read_unlock(&fd->pq_srcu, idx); + return -ENOSPC; ++ } + + while (dim) { + int ret; +@@ -386,6 +396,7 @@ static ssize_t hfi1_write_iter(struct ki + reqs++; + } + ++ srcu_read_unlock(&fd->pq_srcu, idx); + return reqs; + } + +@@ -759,6 +770,7 @@ done: + if (atomic_dec_and_test(&dd->user_refcount)) + complete(&dd->user_comp); + ++ cleanup_srcu_struct(&fdata->pq_srcu); + kfree(fdata); + return 0; + } +--- a/drivers/infiniband/hw/hfi1/hfi.h ++++ b/drivers/infiniband/hw/hfi1/hfi.h +@@ -1362,10 +1362,13 @@ struct mmu_rb_handler; + + /* Private data for file operations */ + struct hfi1_filedata { ++ struct srcu_struct pq_srcu; + struct hfi1_devdata *dd; + struct hfi1_ctxtdata *uctxt; + struct hfi1_user_sdma_comp_q *cq; +- struct hfi1_user_sdma_pkt_q *pq; ++ /* update side lock for SRCU */ ++ spinlock_t pq_rcu_lock; ++ struct hfi1_user_sdma_pkt_q __rcu *pq; + u16 subctxt; + /* for cpu affinity; -1 if none */ + int rec_cpu_num; +--- a/drivers/infiniband/hw/hfi1/user_exp_rcv.c ++++ b/drivers/infiniband/hw/hfi1/user_exp_rcv.c +@@ -90,9 +90,6 @@ int hfi1_user_exp_rcv_init(struct hfi1_f + struct hfi1_devdata *dd = uctxt->dd; + int ret = 0; + +- spin_lock_init(&fd->tid_lock); +- spin_lock_init(&fd->invalid_lock); +- + fd->entry_to_rb = kcalloc(uctxt->expected_count, + sizeof(struct rb_node *), + GFP_KERNEL); +--- a/drivers/infiniband/hw/hfi1/user_sdma.c ++++ b/drivers/infiniband/hw/hfi1/user_sdma.c +@@ -182,7 +182,6 @@ int hfi1_user_sdma_alloc_queues(struct h + pq = kzalloc(sizeof(*pq), GFP_KERNEL); + if (!pq) + return -ENOMEM; +- + pq->dd = dd; + pq->ctxt = uctxt->ctxt; + pq->subctxt = fd->subctxt; +@@ -240,7 +239,7 @@ int hfi1_user_sdma_alloc_queues(struct h + goto pq_mmu_fail; + } + +- fd->pq = pq; ++ rcu_assign_pointer(fd->pq, pq); + fd->cq = cq; + + return 0; +@@ -268,8 +267,14 @@ int hfi1_user_sdma_free_queues(struct hf + + trace_hfi1_sdma_user_free_queues(uctxt->dd, uctxt->ctxt, fd->subctxt); + +- pq = fd->pq; ++ spin_lock(&fd->pq_rcu_lock); ++ pq = srcu_dereference_check(fd->pq, &fd->pq_srcu, ++ lockdep_is_held(&fd->pq_rcu_lock)); + if (pq) { ++ rcu_assign_pointer(fd->pq, NULL); ++ spin_unlock(&fd->pq_rcu_lock); ++ synchronize_srcu(&fd->pq_srcu); ++ /* at this point there can be no more new requests */ + if (pq->handler) + hfi1_mmu_rb_unregister(pq->handler); + iowait_sdma_drain(&pq->busy); +@@ -281,7 +286,8 @@ int hfi1_user_sdma_free_queues(struct hf + kfree(pq->req_in_use); + kmem_cache_destroy(pq->txreq_cache); + kfree(pq); +- fd->pq = NULL; ++ } else { ++ spin_unlock(&fd->pq_rcu_lock); + } + if (fd->cq) { + vfree(fd->cq->comps); +@@ -318,7 +324,8 @@ int hfi1_user_sdma_process_request(struc + { + int ret = 0, i; + struct hfi1_ctxtdata *uctxt = fd->uctxt; +- struct hfi1_user_sdma_pkt_q *pq = fd->pq; ++ struct hfi1_user_sdma_pkt_q *pq = ++ srcu_dereference(fd->pq, &fd->pq_srcu); + struct hfi1_user_sdma_comp_q *cq = fd->cq; + struct hfi1_devdata *dd = pq->dd; + unsigned long idx = 0; diff --git a/patches.suse/Input-avoid-BIT-macro-usage-in-the-serio.h-UAPI-head.patch b/patches.suse/Input-avoid-BIT-macro-usage-in-the-serio.h-UAPI-head.patch new file mode 100644 index 0000000..ed4ae5d --- /dev/null +++ b/patches.suse/Input-avoid-BIT-macro-usage-in-the-serio.h-UAPI-head.patch @@ -0,0 +1,56 @@ +From 52afa505a03d914081f40cb869a3248567a57573 Mon Sep 17 00:00:00 2001 +From: Eugene Syromiatnikov +Date: Tue, 24 Mar 2020 15:53:50 -0700 +Subject: [PATCH] Input: avoid BIT() macro usage in the serio.h UAPI header +Git-commit: 52afa505a03d914081f40cb869a3248567a57573 +Patch-mainline: v5.6 +References: bsc#1051510 + +The commit 19ba1eb15a2a ("Input: psmouse - add a custom serio protocol +to send extra information") introduced usage of the BIT() macro +for SERIO_* flags; this macro is not provided in UAPI headers. +Replace if with similarly defined _BITUL() macro defined +in . + +Fixes: 19ba1eb15a2a ("Input: psmouse - add a custom serio protocol to send extra information") +Signed-off-by: Eugene Syromiatnikov +Cc: # v5.0+ +Link: https://lore.kernel.org/r/20200324041341.GA32335@asgard.redhat.com +Signed-off-by: Dmitry Torokhov +Acked-by: Takashi Iwai + +--- + include/uapi/linux/serio.h | 10 +++++----- + 1 file changed, 5 insertions(+), 5 deletions(-) + +diff --git a/include/uapi/linux/serio.h b/include/uapi/linux/serio.h +index 50e991952c97..ed2a96f43ce4 100644 +--- a/include/uapi/linux/serio.h ++++ b/include/uapi/linux/serio.h +@@ -9,7 +9,7 @@ + #ifndef _UAPI_SERIO_H + #define _UAPI_SERIO_H + +- ++#include + #include + + #define SPIOCSTYPE _IOW('q', 0x01, unsigned long) +@@ -18,10 +18,10 @@ + /* + * bit masks for use in "interrupt" flags (3rd argument) + */ +-#define SERIO_TIMEOUT BIT(0) +-#define SERIO_PARITY BIT(1) +-#define SERIO_FRAME BIT(2) +-#define SERIO_OOB_DATA BIT(3) ++#define SERIO_TIMEOUT _BITUL(0) ++#define SERIO_PARITY _BITUL(1) ++#define SERIO_FRAME _BITUL(2) ++#define SERIO_OOB_DATA _BITUL(3) + + /* + * Serio types +-- +2.16.4 + diff --git a/patches.suse/Input-edt-ft5x06-work-around-first-register-access-e.patch b/patches.suse/Input-edt-ft5x06-work-around-first-register-access-e.patch new file mode 100644 index 0000000..c318717 --- /dev/null +++ b/patches.suse/Input-edt-ft5x06-work-around-first-register-access-e.patch @@ -0,0 +1,55 @@ +From e112324cc0422c046f1cf54c56f333d34fa20885 Mon Sep 17 00:00:00 2001 +From: Philipp Zabel +Date: Thu, 9 Jan 2020 17:03:21 -0800 +Subject: [PATCH] Input: edt-ft5x06 - work around first register access error +Git-commit: e112324cc0422c046f1cf54c56f333d34fa20885 +Patch-mainline: v5.6-rc1 +References: bsc#1051510 + +The EP0700MLP1 returns bogus data on the first register read access +(reading the threshold parameter from register 0x00): + + edt_ft5x06 2-0038: crc error: 0xfc expected, got 0x40 + +It ignores writes until then. This patch adds a dummy read after which +the number of sensors and parameter read/writes work correctly. + +Signed-off-by: Philipp Zabel +Signed-off-by: Marco Felsch +Tested-by: Andy Shevchenko +Reviewed-by: Andy Shevchenko +Signed-off-by: Dmitry Torokhov +Acked-by: Takashi Iwai + +--- + drivers/input/touchscreen/edt-ft5x06.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/drivers/input/touchscreen/edt-ft5x06.c b/drivers/input/touchscreen/edt-ft5x06.c +index d61731c0037d..b87b1e074f62 100644 +--- a/drivers/input/touchscreen/edt-ft5x06.c ++++ b/drivers/input/touchscreen/edt-ft5x06.c +@@ -1050,6 +1050,7 @@ static int edt_ft5x06_ts_probe(struct i2c_client *client, + { + const struct edt_i2c_chip_data *chip_data; + struct edt_ft5x06_ts_data *tsdata; ++ u8 buf[2] = { 0xfc, 0x00 }; + struct input_dev *input; + unsigned long irq_flags; + int error; +@@ -1140,6 +1141,12 @@ static int edt_ft5x06_ts_probe(struct i2c_client *client, + return error; + } + ++ /* ++ * Dummy read access. EP0700MLP1 returns bogus data on the first ++ * register read access and ignores writes. ++ */ ++ edt_ft5x06_ts_readwrite(tsdata->client, 2, buf, 2, buf); ++ + edt_ft5x06_ts_set_regs(tsdata); + edt_ft5x06_ts_get_defaults(&client->dev, tsdata); + edt_ft5x06_ts_get_parameters(tsdata); +-- +2.16.4 + diff --git a/patches.suse/Input-raydium_i2c_ts-fix-error-codes-in-raydium_i2c_.patch b/patches.suse/Input-raydium_i2c_ts-fix-error-codes-in-raydium_i2c_.patch new file mode 100644 index 0000000..719ed84 --- /dev/null +++ b/patches.suse/Input-raydium_i2c_ts-fix-error-codes-in-raydium_i2c_.patch @@ -0,0 +1,43 @@ +From 32cf3a610c35cb21e3157f4bbf29d89960e30a36 Mon Sep 17 00:00:00 2001 +From: Dan Carpenter +Date: Fri, 6 Mar 2020 11:50:51 -0800 +Subject: [PATCH] Input: raydium_i2c_ts - fix error codes in raydium_i2c_boot_trigger() +Git-commit: 32cf3a610c35cb21e3157f4bbf29d89960e30a36 +Patch-mainline: v5.6 +References: bsc#1051510 + +These functions are supposed to return negative error codes but instead +it returns true on failure and false on success. The error codes are +eventually propagated back to user space. + +Fixes: 48a2b783483b ("Input: add Raydium I2C touchscreen driver") +Signed-off-by: Dan Carpenter +Link: https://lore.kernel.org/r/20200303101306.4potflz7na2nn3od@kili.mountain +Cc: stable@vger.kernel.org +Signed-off-by: Dmitry Torokhov +Acked-by: Takashi Iwai + +--- + drivers/input/touchscreen/raydium_i2c_ts.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/input/touchscreen/raydium_i2c_ts.c ++++ b/drivers/input/touchscreen/raydium_i2c_ts.c +@@ -441,7 +441,7 @@ static int raydium_i2c_write_object(stru + return 0; + } + +-static bool raydium_i2c_boot_trigger(struct i2c_client *client) ++static int raydium_i2c_boot_trigger(struct i2c_client *client) + { + static const u8 cmd[7][6] = { + { 0x08, 0x0C, 0x09, 0x00, 0x50, 0xD7 }, +@@ -469,7 +469,7 @@ static bool raydium_i2c_boot_trigger(str + return 0; + } + +-static bool raydium_i2c_fw_trigger(struct i2c_client *client) ++static int raydium_i2c_fw_trigger(struct i2c_client *client) + { + static const u8 cmd[5][11] = { + { 0, 0x09, 0x71, 0x0C, 0x09, 0x00, 0x50, 0xD7, 0, 0, 0 }, diff --git a/patches.suse/Input-synaptics-enable-RMI-on-HP-Envy-13-ad105ng.patch b/patches.suse/Input-synaptics-enable-RMI-on-HP-Envy-13-ad105ng.patch new file mode 100644 index 0000000..816ac62 --- /dev/null +++ b/patches.suse/Input-synaptics-enable-RMI-on-HP-Envy-13-ad105ng.patch @@ -0,0 +1,38 @@ +From 1369d0abe469fb4cdea8a5bce219d38cb857a658 Mon Sep 17 00:00:00 2001 +From: Yussuf Khalil +Date: Sat, 7 Mar 2020 14:16:31 -0800 +Subject: [PATCH] Input: synaptics - enable RMI on HP Envy 13-ad105ng +Git-commit: 1369d0abe469fb4cdea8a5bce219d38cb857a658 +Patch-mainline: v5.6 +References: bsc#1051510 + +This laptop (and perhaps other variants of the same model) reports an +SMBus-capable Synaptics touchpad. Everything (including suspend and +resume) works fine when RMI is enabled via the kernel command line, so +let's add it to the whitelist. + +Signed-off-by: Yussuf Khalil +Link: https://lore.kernel.org/r/20200307213508.267187-1-dev@pp3345.net +Cc: stable@vger.kernel.org +Signed-off-by: Dmitry Torokhov +Acked-by: Takashi Iwai + +--- + drivers/input/mouse/synaptics.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c +index 2c666fb34625..4d2036209b45 100644 +--- a/drivers/input/mouse/synaptics.c ++++ b/drivers/input/mouse/synaptics.c +@@ -186,6 +186,7 @@ static const char * const smbus_pnp_ids[] = { + "SYN3052", /* HP EliteBook 840 G4 */ + "SYN3221", /* HP 15-ay000 */ + "SYN323d", /* HP Spectre X360 13-w013dx */ ++ "SYN3257", /* HP Envy 13-ad105ng */ + NULL + }; + +-- +2.16.4 + diff --git a/patches.suse/Input-synaptics-enable-SMBus-on-ThinkPad-L470.patch b/patches.suse/Input-synaptics-enable-SMBus-on-ThinkPad-L470.patch new file mode 100644 index 0000000..d5ea948 --- /dev/null +++ b/patches.suse/Input-synaptics-enable-SMBus-on-ThinkPad-L470.patch @@ -0,0 +1,36 @@ +From b8a3d819f872e0a3a0a6db0dbbcd48071042fb98 Mon Sep 17 00:00:00 2001 +From: Gaurav Agrawal +Date: Thu, 13 Feb 2020 17:06:10 -0800 +Subject: [PATCH] Input: synaptics - enable SMBus on ThinkPad L470 +Git-commit: b8a3d819f872e0a3a0a6db0dbbcd48071042fb98 +Patch-mainline: v5.6-rc2 +References: bsc#1051510 + +Add touchpad LEN2044 to the list, as it is capable of working with +psmouse.synaptics_intertouch=1 + +Signed-off-by: Gaurav Agrawal +Cc: stable@vger.kernel.org +Link: https://lore.kernel.org/r/CADdtggVzVJq5gGNmFhKSz2MBwjTpdN5YVOdr4D3Hkkv=KZRc9g@mail.gmail.com +Signed-off-by: Dmitry Torokhov +Acked-by: Takashi Iwai + +--- + drivers/input/mouse/synaptics.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c +index 8cb8475657ca..36f410aa4bad 100644 +--- a/drivers/input/mouse/synaptics.c ++++ b/drivers/input/mouse/synaptics.c +@@ -180,6 +180,7 @@ static const char * const smbus_pnp_ids[] = { + "LEN0097", /* X280 -> ALPS trackpoint */ + "LEN009b", /* T580 */ + "LEN200f", /* T450s */ ++ "LEN2044", /* L470 */ + "LEN2054", /* E480 */ + "LEN2055", /* E580 */ + "SYN3052", /* HP EliteBook 840 G4 */ +-- +2.16.4 + diff --git a/patches.suse/Input-synaptics-remove-the-LEN0049-dmi-id-from-topbu.patch b/patches.suse/Input-synaptics-remove-the-LEN0049-dmi-id-from-topbu.patch new file mode 100644 index 0000000..66b5dcb --- /dev/null +++ b/patches.suse/Input-synaptics-remove-the-LEN0049-dmi-id-from-topbu.patch @@ -0,0 +1,48 @@ +From 5179a9dfa9440c1781816e2c9a183d1d2512dc61 Mon Sep 17 00:00:00 2001 +From: Benjamin Tissoires +Date: Thu, 13 Feb 2020 17:07:47 -0800 +Subject: [PATCH] Input: synaptics - remove the LEN0049 dmi id from topbuttonpad list +Git-commit: 5179a9dfa9440c1781816e2c9a183d1d2512dc61 +Patch-mainline: v5.6-rc2 +References: bsc#1051510 + +The Yoga 11e is using LEN0049, but it doesn't have a trackstick. + +Thus, there is no need to create a software top buttons row. + +However, it seems that the device works under SMBus, so keep it as part +of the smbus_pnp_ids. + +Signed-off-by: Benjamin Tissoires +Cc: stable@vger.kernel.org +Link: https://lore.kernel.org/r/20200115013023.9710-1-benjamin.tissoires@redhat.com +Signed-off-by: Dmitry Torokhov +Acked-by: Takashi Iwai + +--- + drivers/input/mouse/synaptics.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c +index 36f410aa4bad..2c666fb34625 100644 +--- a/drivers/input/mouse/synaptics.c ++++ b/drivers/input/mouse/synaptics.c +@@ -146,7 +146,6 @@ static const char * const topbuttonpad_pnp_ids[] = { + "LEN0042", /* Yoga */ + "LEN0045", + "LEN0047", +- "LEN0049", + "LEN2000", /* S540 */ + "LEN2001", /* Edge E431 */ + "LEN2002", /* Edge E531 */ +@@ -166,6 +165,7 @@ static const char * const smbus_pnp_ids[] = { + /* all of the topbuttonpad_pnp_ids are valid, we just add some extras */ + "LEN0048", /* X1 Carbon 3 */ + "LEN0046", /* X250 */ ++ "LEN0049", /* Yoga 11e */ + "LEN004a", /* W541 */ + "LEN005b", /* P50 */ + "LEN005e", /* T560 */ +-- +2.16.4 + diff --git a/patches.suse/Input-synaptics-switch-T470s-to-RMI4-by-default.patch b/patches.suse/Input-synaptics-switch-T470s-to-RMI4-by-default.patch new file mode 100644 index 0000000..c8865c0 --- /dev/null +++ b/patches.suse/Input-synaptics-switch-T470s-to-RMI4-by-default.patch @@ -0,0 +1,36 @@ +From bf502391353b928e63096127e5fd8482080203f5 Mon Sep 17 00:00:00 2001 +From: Lyude Paul +Date: Thu, 13 Feb 2020 16:59:15 -0800 +Subject: [PATCH] Input: synaptics - switch T470s to RMI4 by default +Git-commit: bf502391353b928e63096127e5fd8482080203f5 +Patch-mainline: v5.6-rc2 +References: bsc#1051510 + +This supports RMI4 and everything seems to work, including the touchpad +buttons. So, let's enable this by default. + +Signed-off-by: Lyude Paul +Cc: stable@vger.kernel.org +Link: https://lore.kernel.org/r/20200204194322.112638-1-lyude@redhat.com +Signed-off-by: Dmitry Torokhov +Acked-by: Takashi Iwai + +--- + drivers/input/mouse/synaptics.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c +index 1ae6f8bba9ae..8cb8475657ca 100644 +--- a/drivers/input/mouse/synaptics.c ++++ b/drivers/input/mouse/synaptics.c +@@ -169,6 +169,7 @@ static const char * const smbus_pnp_ids[] = { + "LEN004a", /* W541 */ + "LEN005b", /* P50 */ + "LEN005e", /* T560 */ ++ "LEN006c", /* T470s */ + "LEN0071", /* T480 */ + "LEN0072", /* X1 Carbon Gen 5 (2017) - Elan/ALPS trackpoint */ + "LEN0073", /* X1 Carbon G5 (Elantech) */ +-- +2.16.4 + diff --git a/patches.suse/KVM-PPC-Book3S-PR-Add-guest-MSR-parameter-for-kvmppc.patch b/patches.suse/KVM-PPC-Book3S-PR-Add-guest-MSR-parameter-for-kvmppc.patch index 96b8653..050c31f 100644 --- a/patches.suse/KVM-PPC-Book3S-PR-Add-guest-MSR-parameter-for-kvmppc.patch +++ b/patches.suse/KVM-PPC-Book3S-PR-Add-guest-MSR-parameter-for-kvmppc.patch @@ -4,7 +4,7 @@ Date: Wed, 23 May 2018 15:01:48 +0800 Subject: [PATCH] KVM: PPC: Book3S PR: Add guest MSR parameter for kvmppc_save_tm()/kvmppc_restore_tm() -References: bsc#1061840 +References: bsc#1061840 CVE-2020-8834 Patch-mainline: v4.18-rc1 Git-commit: 6f597c6b63b6f3675914b5ec8fcd008a58678650 diff --git a/patches.suse/KVM-arm64-Store-vcpu-on-the-stack-during-__guest_ent.patch b/patches.suse/KVM-arm64-Store-vcpu-on-the-stack-during-__guest_ent.patch new file mode 100644 index 0000000..1a1064a --- /dev/null +++ b/patches.suse/KVM-arm64-Store-vcpu-on-the-stack-during-__guest_ent.patch @@ -0,0 +1,93 @@ +From: James Morse +Date: Mon, 8 Jan 2018 15:38:03 +0000 +Subject: KVM: arm64: Store vcpu on the stack during __guest_enter() +Patch-mainline: v4.16-rc1 +Git-commit: 32b03d1059667a39e089c45ee38ec9c16332430f +References: bsc#1133021 fate#326420 fate#325360 + +KVM uses tpidr_el2 as its private vcpu register, which makes sense for +non-vhe world switch as only KVM can access this register. This means +vhe Linux has to use tpidr_el1, which KVM has to save/restore as part +of the host context. + +If the SDEI handler code runs behind KVMs back, it mustn't access any +per-cpu variables. To allow this on systems with vhe we need to make +the host use tpidr_el2, saving KVM from save/restoring it. + +__guest_enter() stores the host_ctxt on the stack, do the same with +the vcpu. + +Signed-off-by: James Morse +Reviewed-by: Christoffer Dall +Signed-off-by: Catalin Marinas +Acked-by: Liang Yan +--- + arch/arm64/kvm/hyp/entry.S | 10 +++++++--- + arch/arm64/kvm/hyp/hyp-entry.S | 6 +++--- + 2 files changed, 10 insertions(+), 6 deletions(-) + +--- a/arch/arm64/kvm/hyp/entry.S ++++ b/arch/arm64/kvm/hyp/entry.S +@@ -62,8 +62,8 @@ ENTRY(__guest_enter) + // Store the host regs + save_callee_saved_regs x1 + +- // Store the host_ctxt for use at exit time +- str x1, [sp, #-16]! ++ // Store host_ctxt and vcpu for use at exit time ++ stp x1, x0, [sp, #-16]! + + add x18, x0, #VCPU_CONTEXT + +@@ -159,6 +159,10 @@ abort_guest_exit_end: + ENDPROC(__guest_exit) + + ENTRY(__fpsimd_guest_restore) ++ // x0: esr ++ // x1: vcpu ++ // x2-x29,lr: vcpu regs ++ // vcpu x0-x1 on the stack + stp x2, x3, [sp, #-16]! + stp x4, lr, [sp, #-16]! + +@@ -173,7 +177,7 @@ alternative_else + alternative_endif + isb + +- mrs x3, tpidr_el2 ++ mov x3, x1 + + ldr x0, [x3, #VCPU_HOST_CONTEXT] + kern_hyp_va x0 +--- a/arch/arm64/kvm/hyp/hyp-entry.S ++++ b/arch/arm64/kvm/hyp/hyp-entry.S +@@ -104,6 +104,7 @@ el1_trap: + /* + * x0: ESR_EC + */ ++ ldr x1, [sp, #16 + 8] // vcpu stored by __guest_enter + + /* + * We trap the first access to the FP/SIMD to save the host context +@@ -116,19 +117,18 @@ alternative_if_not ARM64_HAS_NO_FPSIMD + b.eq __fpsimd_guest_restore + alternative_else_nop_endif + +- mrs x1, tpidr_el2 + mov x0, #ARM_EXCEPTION_TRAP + b __guest_exit + + el1_irq: + stp x0, x1, [sp, #-16]! +- mrs x1, tpidr_el2 ++ ldr x1, [sp, #16 + 8] + mov x0, #ARM_EXCEPTION_IRQ + b __guest_exit + + el1_error: + stp x0, x1, [sp, #-16]! +- mrs x1, tpidr_el2 ++ ldr x1, [sp, #16 + 8] + mov x0, #ARM_EXCEPTION_EL1_SERROR + b __guest_exit + diff --git a/patches.suse/KVM-s390-ENOTSUPP-EOPNOTSUPP-fixups.patch b/patches.suse/KVM-s390-ENOTSUPP-EOPNOTSUPP-fixups.patch new file mode 100644 index 0000000..0bbc904 --- /dev/null +++ b/patches.suse/KVM-s390-ENOTSUPP-EOPNOTSUPP-fixups.patch @@ -0,0 +1,49 @@ +From: Christian Borntraeger +Date: Thu, 5 Dec 2019 07:40:43 -0500 +Subject: KVM: s390: ENOTSUPP -> EOPNOTSUPP fixups +Patch-mainline: v5.6-rc1 +Git-commit: c611990844c28c61ca4b35ff69d3a2ae95ccd486 +References: bsc#1133021 + +There is no ENOTSUPP for userspace. + +Reported-by: Julian Wiedmann +Fixes: 519783935451 ("KVM: s390: introduce ais mode modify function") +Fixes: 2c1a48f2e5ed ("KVM: S390: add new group for flic") +Reviewed-by: Cornelia Huck +Reviewed-by: Thomas Huth +Signed-off-by: Christian Borntraeger +Acked-by: Liang Yan +--- + arch/s390/kvm/interrupt.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +--- a/arch/s390/kvm/interrupt.c ++++ b/arch/s390/kvm/interrupt.c +@@ -1926,7 +1926,7 @@ static int flic_ais_mode_get_all(struct + return -EINVAL; + + if (!test_kvm_facility(kvm, 72)) +- return -ENOTSUPP; ++ return -EOPNOTSUPP; + + mutex_lock(&fi->ais_lock); + ais.simm = fi->simm; +@@ -2229,7 +2229,7 @@ static int modify_ais_mode(struct kvm *k + int ret = 0; + + if (!test_kvm_facility(kvm, 72)) +- return -ENOTSUPP; ++ return -EOPNOTSUPP; + + if (copy_from_user(&req, (void __user *)attr->addr, sizeof(req))) + return -EFAULT; +@@ -2309,7 +2309,7 @@ static int flic_ais_mode_set_all(struct + struct kvm_s390_ais_all ais; + + if (!test_kvm_facility(kvm, 72)) +- return -ENOTSUPP; ++ return -EOPNOTSUPP; + + if (copy_from_user(&ais, (void __user *)attr->addr, sizeof(ais))) + return -EFAULT; diff --git a/patches.suse/KVM-s390-do-not-clobber-registers-during-guest-reset.patch b/patches.suse/KVM-s390-do-not-clobber-registers-during-guest-reset.patch new file mode 100644 index 0000000..28b00e0 --- /dev/null +++ b/patches.suse/KVM-s390-do-not-clobber-registers-during-guest-reset.patch @@ -0,0 +1,48 @@ +From: Christian Borntraeger +Date: Fri, 31 Jan 2020 05:02:00 -0500 +Subject: KVM: s390: do not clobber registers during guest reset/store status +Patch-mainline: v5.6-rc1 +Git-commit: 55680890ea78be0df5e1384989f1be835043c084 +References: bsc#1133021 + +The initial CPU reset clobbers the userspace fpc and the store status +ioctl clobbers the guest acrs + fpr. As these calls are only done via +ioctl (and not via vcpu_run), no CPU context is loaded, so we can (and +must) act directly on the sync regs, not on the thread context. + +Cc: stable@kernel.org +Fixes: e1788bb995be ("KVM: s390: handle floating point registers in the run ioctl not in vcpu_put/load") +Fixes: 31d8b8d41a7e ("KVM: s390: handle access registers in the run ioctl not in vcpu_put/load") +Signed-off-by: Christian Borntraeger +Reviewed-by: David Hildenbrand +Reviewed-by: Cornelia Huck +Signed-off-by: Janosch Frank +Link: https://lore.kernel.org/r/20200131100205.74720-2-frankja@linux.ibm.com +Signed-off-by: Christian Borntraeger +Acked-by: Liang Yan +--- + arch/s390/kvm/kvm-s390.c | 6 ++---- + 1 file changed, 2 insertions(+), 4 deletions(-) + +--- a/arch/s390/kvm/kvm-s390.c ++++ b/arch/s390/kvm/kvm-s390.c +@@ -2405,9 +2405,7 @@ static void kvm_s390_vcpu_initial_reset( + memset(vcpu->arch.sie_block->gcr, 0, 16 * sizeof(__u64)); + vcpu->arch.sie_block->gcr[0] = 0xE0UL; + vcpu->arch.sie_block->gcr[14] = 0xC2000000UL; +- /* make sure the new fpc will be lazily loaded */ +- save_fpu_regs(); +- current->thread.fpu.fpc = 0; ++ vcpu->run->s.regs.fpc = 0; + vcpu->arch.sie_block->gbea = 1; + vcpu->arch.sie_block->pp = 0; + vcpu->arch.sie_block->fpf &= ~FPF_BPBC; +@@ -3787,7 +3785,7 @@ long kvm_arch_vcpu_ioctl(struct file *fi + } + case KVM_S390_STORE_STATUS: + idx = srcu_read_lock(&vcpu->kvm->srcu); +- r = kvm_s390_vcpu_store_status(vcpu, arg); ++ r = kvm_s390_store_status_unloaded(vcpu, arg); + srcu_read_unlock(&vcpu->kvm->srcu, idx); + break; + case KVM_S390_SET_INITIAL_PSW: { diff --git a/patches.suse/NFC-fdp-Fix-a-signedness-bug-in-fdp_nci_send_patch.patch b/patches.suse/NFC-fdp-Fix-a-signedness-bug-in-fdp_nci_send_patch.patch new file mode 100644 index 0000000..59f75ec --- /dev/null +++ b/patches.suse/NFC-fdp-Fix-a-signedness-bug-in-fdp_nci_send_patch.patch @@ -0,0 +1,47 @@ +From 0dcdf9f64028ec3b75db6b691560f8286f3898bf Mon Sep 17 00:00:00 2001 +From: Dan Carpenter +Date: Fri, 20 Mar 2020 16:21:17 +0300 +Subject: [PATCH] NFC: fdp: Fix a signedness bug in fdp_nci_send_patch() +Git-commit: 0dcdf9f64028ec3b75db6b691560f8286f3898bf +Patch-mainline: v5.6 +References: bsc#1051510 + +The nci_conn_max_data_pkt_payload_size() function sometimes returns +-EPROTO so "max_size" needs to be signed for the error handling to +work. We can make "payload_size" an int as well. + +Fixes: a06347c04c13 ("NFC: Add Intel Fields Peak NFC solution driver") +Signed-off-by: Dan Carpenter +Signed-off-by: David S. Miller +Acked-by: Takashi Iwai + +--- + drivers/nfc/fdp/fdp.c | 5 ++--- + 1 file changed, 2 insertions(+), 3 deletions(-) + +diff --git a/drivers/nfc/fdp/fdp.c b/drivers/nfc/fdp/fdp.c +index 0cc9ac856fe2..ed2123129e0e 100644 +--- a/drivers/nfc/fdp/fdp.c ++++ b/drivers/nfc/fdp/fdp.c +@@ -184,7 +184,7 @@ static int fdp_nci_send_patch(struct nci_dev *ndev, u8 conn_id, u8 type) + const struct firmware *fw; + struct sk_buff *skb; + unsigned long len; +- u8 max_size, payload_size; ++ int max_size, payload_size; + int rc = 0; + + if ((type == NCI_PATCH_TYPE_OTP && !info->otp_patch) || +@@ -207,8 +207,7 @@ static int fdp_nci_send_patch(struct nci_dev *ndev, u8 conn_id, u8 type) + + while (len) { + +- payload_size = min_t(unsigned long, (unsigned long) max_size, +- len); ++ payload_size = min_t(unsigned long, max_size, len); + + skb = nci_skb_alloc(ndev, (NCI_CTRL_HDR_SIZE + payload_size), + GFP_KERNEL); +-- +2.16.4 + diff --git a/patches.suse/NFC-pn544-Fix-a-typo-in-a-debug-message.patch b/patches.suse/NFC-pn544-Fix-a-typo-in-a-debug-message.patch new file mode 100644 index 0000000..3dfa94b --- /dev/null +++ b/patches.suse/NFC-pn544-Fix-a-typo-in-a-debug-message.patch @@ -0,0 +1,35 @@ +From c4c10784293ec89746721b1a40cb730b0106deea Mon Sep 17 00:00:00 2001 +From: Christophe JAILLET +Date: Sat, 15 Feb 2020 08:17:28 +0100 +Subject: [PATCH] NFC: pn544: Fix a typo in a debug message +Git-commit: c4c10784293ec89746721b1a40cb730b0106deea +Patch-mainline: v5.6-rc3 +References: bsc#1051510 + +The ending character of the string shoulb be \n, not \b. + +Fixes: 17936b43f0fd ("NFC: Standardize logging style") +Signed-off-by: Christophe JAILLET +Signed-off-by: David S. Miller +Acked-by: Takashi Iwai + +--- + drivers/nfc/pn544/pn544.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/nfc/pn544/pn544.c b/drivers/nfc/pn544/pn544.c +index 2b83156efe3f..b788870473e8 100644 +--- a/drivers/nfc/pn544/pn544.c ++++ b/drivers/nfc/pn544/pn544.c +@@ -682,7 +682,7 @@ static int pn544_hci_tm_send(struct nfc_hci_dev *hdev, struct sk_buff *skb) + static int pn544_hci_check_presence(struct nfc_hci_dev *hdev, + struct nfc_target *target) + { +- pr_debug("supported protocol %d\b", target->supported_protocols); ++ pr_debug("supported protocol %d\n", target->supported_protocols); + if (target->supported_protocols & (NFC_PROTO_ISO14443_MASK | + NFC_PROTO_ISO14443_B_MASK)) { + return nfc_hci_send_cmd(hdev, target->hci_reader_gate, +-- +2.16.4 + diff --git a/patches.suse/NFC-port100-Convert-cpu_to_le16-le16_to_cpu-E1-E2-to.patch b/patches.suse/NFC-port100-Convert-cpu_to_le16-le16_to_cpu-E1-E2-to.patch new file mode 100644 index 0000000..e762176 --- /dev/null +++ b/patches.suse/NFC-port100-Convert-cpu_to_le16-le16_to_cpu-E1-E2-to.patch @@ -0,0 +1,36 @@ +From 718eae277e62a26e5862eb72a830b5e0fe37b04a Mon Sep 17 00:00:00 2001 +From: Mao Wenan +Date: Mon, 9 Dec 2019 21:08:45 +0800 +Subject: [PATCH] NFC: port100: Convert cpu_to_le16(le16_to_cpu(E1) + E2) to use le16_add_cpu(). +Git-commit: 718eae277e62a26e5862eb72a830b5e0fe37b04a +Patch-mainline: v5.6-rc1 +References: bsc#1051510 + +Convert cpu_to_le16(le16_to_cpu(frame->datalen) + len) to +use le16_add_cpu(), which is more concise and does the same thing. + +Reported-by: Hulk Robot +Signed-off-by: Mao Wenan +Signed-off-by: David S. Miller +Acked-by: Takashi Iwai + +--- + drivers/nfc/port100.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/nfc/port100.c b/drivers/nfc/port100.c +index 604dba4f18af..8e4d355dc3ae 100644 +--- a/drivers/nfc/port100.c ++++ b/drivers/nfc/port100.c +@@ -565,7 +565,7 @@ static void port100_tx_update_payload_len(void *_frame, int len) + { + struct port100_frame *frame = _frame; + +- frame->datalen = cpu_to_le16(le16_to_cpu(frame->datalen) + len); ++ le16_add_cpu(&frame->datalen, len); + } + + static bool port100_rx_frame_is_valid(void *_frame) +-- +2.16.4 + diff --git a/patches.suse/NFS-send-state-management-on-a-single-connection.patch b/patches.suse/NFS-send-state-management-on-a-single-connection.patch new file mode 100644 index 0000000..057794e --- /dev/null +++ b/patches.suse/NFS-send-state-management-on-a-single-connection.patch @@ -0,0 +1,156 @@ +From: NeilBrown +Date: Thu, 30 May 2019 10:41:28 +1000 +Subject: [PATCH] NFS: send state management on a single connection. +Git-commit: 5a0c257f8e0f4c4b3c33dff545317c21a921303e +Patch-mainline: v5.3 +References: bsc#1167005 + +With NFSv4.1, different network connections need to be explicitly +bound to a session. During session startup, this is not possible +so only a single connection must be used for session startup. + +So add a task flag to disable the default round-robin choice of +connections (when nconnect > 1) and force the use of a single +connection. +Then use that flag on all requests for session management - for +consistence, include NFSv4.0 management (SETCLIENTID) and session +destruction + +Reported-by: Chuck Lever +Signed-off-by: NeilBrown +Signed-off-by: Trond Myklebust +Acked-by: NeilBrown + +--- + fs/nfs/nfs4proc.c | 22 +++++++++++++--------- + include/linux/sunrpc/sched.h | 1 + + net/sunrpc/clnt.c | 18 +++++++++++++++++- + 3 files changed, 31 insertions(+), 10 deletions(-) + +--- a/fs/nfs/nfs4proc.c ++++ b/fs/nfs/nfs4proc.c +@@ -5636,7 +5636,7 @@ int nfs4_proc_setclientid(struct nfs_cli + .rpc_message = &msg, + .callback_ops = &nfs4_setclientid_ops, + .callback_data = &setclientid, +- .flags = RPC_TASK_TIMEOUT, ++ .flags = RPC_TASK_TIMEOUT | RPC_TASK_NO_ROUND_ROBIN, + }; + int status; + +@@ -5702,7 +5702,8 @@ int nfs4_proc_setclientid_confirm(struct + dprintk("NFS call setclientid_confirm auth=%s, (client ID %llx)\n", + clp->cl_rpcclient->cl_auth->au_ops->au_name, + clp->cl_clientid); +- status = rpc_call_sync(clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT); ++ status = rpc_call_sync(clp->cl_rpcclient, &msg, ++ RPC_TASK_TIMEOUT | RPC_TASK_NO_ROUND_ROBIN); + trace_nfs4_setclientid_confirm(clp, status); + dprintk("NFS reply setclientid_confirm: %d\n", status); + return status; +@@ -7238,7 +7239,7 @@ static int _nfs4_proc_secinfo(struct ino + NFS_SP4_MACH_CRED_SECINFO, &clnt, &msg); + + status = nfs4_call_sync(clnt, NFS_SERVER(dir), &msg, &args.seq_args, +- &res.seq_res, 0); ++ &res.seq_res, RPC_TASK_NO_ROUND_ROBIN); + dprintk("NFS reply secinfo: %d\n", status); + + if (cred) +@@ -7636,7 +7637,7 @@ static int _nfs4_proc_exchange_id(struct + .rpc_client = clp->cl_rpcclient, + .callback_ops = &nfs4_exchange_id_call_ops, + .rpc_message = &msg, +- .flags = RPC_TASK_TIMEOUT, ++ .flags = RPC_TASK_TIMEOUT | RPC_TASK_NO_ROUND_ROBIN, + }; + struct nfs41_exchange_id_data *calldata; + struct rpc_task *task; +@@ -7799,7 +7800,8 @@ static int _nfs4_proc_destroy_clientid(s + }; + int status; + +- status = rpc_call_sync(clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT); ++ status = rpc_call_sync(clp->cl_rpcclient, &msg, ++ RPC_TASK_TIMEOUT | RPC_TASK_NO_ROUND_ROBIN); + trace_nfs4_destroy_clientid(clp, status); + if (status) + dprintk("NFS: Got error %d from the server %s on " +@@ -8080,7 +8082,8 @@ static int _nfs4_proc_create_session(str + nfs4_init_channel_attrs(&args, clp->cl_rpcclient); + args.flags = (SESSION4_PERSIST | SESSION4_BACK_CHAN); + +- status = rpc_call_sync(session->clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT); ++ status = rpc_call_sync(session->clp->cl_rpcclient, &msg, ++ RPC_TASK_TIMEOUT | RPC_TASK_NO_ROUND_ROBIN); + trace_nfs4_create_session(clp, status); + + switch (status) { +@@ -8156,7 +8159,8 @@ int nfs4_proc_destroy_session(struct nfs + if (!test_and_clear_bit(NFS4_SESSION_ESTABLISHED, &session->session_state)) + return 0; + +- status = rpc_call_sync(session->clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT); ++ status = rpc_call_sync(session->clp->cl_rpcclient, &msg, ++ RPC_TASK_TIMEOUT | RPC_TASK_NO_ROUND_ROBIN); + trace_nfs4_destroy_session(session->clp, status); + + if (status) +@@ -8410,7 +8414,7 @@ static int nfs41_proc_reclaim_complete(s + .rpc_client = clp->cl_rpcclient, + .rpc_message = &msg, + .callback_ops = &nfs4_reclaim_complete_call_ops, +- .flags = RPC_TASK_ASYNC, ++ .flags = RPC_TASK_ASYNC | RPC_TASK_NO_ROUND_ROBIN, + }; + int status = -ENOMEM; + +@@ -8971,7 +8975,7 @@ _nfs41_proc_secinfo_no_name(struct nfs_s + + dprintk("--> %s\n", __func__); + status = nfs4_call_sync(clnt, server, &msg, &args.seq_args, +- &res.seq_res, 0); ++ &res.seq_res, RPC_TASK_NO_ROUND_ROBIN); + dprintk("<-- %s status=%d\n", __func__, status); + + if (cred) +--- a/include/linux/sunrpc/sched.h ++++ b/include/linux/sunrpc/sched.h +@@ -117,6 +117,7 @@ struct rpc_task_setup { + */ + #define RPC_TASK_ASYNC 0x0001 /* is an async task */ + #define RPC_TASK_SWAPPER 0x0002 /* is swapping in/out */ ++#define RPC_TASK_NO_ROUND_ROBIN 0x0040 /* send requests on "main" xprt */ + #define RPC_CALL_MAJORSEEN 0x0020 /* major timeout seen */ + #define RPC_TASK_ROOTCREDS 0x0040 /* force root creds */ + #define RPC_TASK_DYNAMIC 0x0080 /* task was kmalloc'ed */ +--- a/net/sunrpc/clnt.c ++++ b/net/sunrpc/clnt.c +@@ -1010,10 +1010,26 @@ void rpc_task_release_client(struct rpc_ + rpc_task_release_transport(task); + } + ++static struct rpc_xprt * ++rpc_task_get_first_xprt(struct rpc_clnt *clnt) ++{ ++ struct rpc_xprt *xprt; ++ ++ rcu_read_lock(); ++ xprt = xprt_get(rcu_dereference(clnt->cl_xprt)); ++ rcu_read_unlock(); ++ ++ return xprt; ++} ++ + static + void rpc_task_set_transport(struct rpc_task *task, struct rpc_clnt *clnt) + { +- if (!task->tk_xprt) ++ if (task->tk_xprt) ++ return; ++ if (task->tk_flags & RPC_TASK_NO_ROUND_ROBIN) ++ task->tk_xprt = rpc_task_get_first_xprt(clnt); ++ else + task->tk_xprt = xprt_iter_get_next(&clnt->cl_xpi); + } + diff --git a/patches.suse/PCI-AER-Clear-device-status-bits-during-ERR_COR-hand.patch b/patches.suse/PCI-AER-Clear-device-status-bits-during-ERR_COR-hand.patch new file mode 100644 index 0000000..1dbb6d4 --- /dev/null +++ b/patches.suse/PCI-AER-Clear-device-status-bits-during-ERR_COR-hand.patch @@ -0,0 +1,29 @@ +From 10d790d99d3b42ec07d54178b291708f14af886d Mon Sep 17 00:00:00 2001 +From: Oza Pawandeep +Date: Thu, 19 Jul 2018 17:58:09 -0500 +Subject: [PATCH] PCI/AER: Clear device status bits during ERR_COR handling +Git-commit: 10d790d99d3b42ec07d54178b291708f14af886d +Patch-mainline: v4.19-rc1 +References: bsc#1161561 + +In case of correctable error, the Correctable Error Detected bit in the +Device Status register is set. Clear it after handling the error. + +Signed-off-by: Oza Pawandeep +Signed-off-by: Bjorn Helgaas +Acked-by: Takashi Iwai + +--- + drivers/pci/pcie/aer/aerdrv_core.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/pci/pcie/aer/aerdrv_core.c ++++ b/drivers/pci/pcie/aer/aerdrv_core.c +@@ -294,6 +294,7 @@ static void handle_error_source(struct p + if (pos) + pci_write_config_dword(dev, pos + PCI_ERR_COR_STATUS, + info->status); ++ pci_aer_clear_device_status(dev); + } else if (info->severity == AER_NONFATAL) + pcie_do_nonfatal_recovery(dev); + else if (info->severity == AER_FATAL) diff --git a/patches.suse/PCI-AER-Clear-device-status-bits-during-ERR_FATAL-an.patch b/patches.suse/PCI-AER-Clear-device-status-bits-during-ERR_FATAL-an.patch new file mode 100644 index 0000000..12f9fb3 --- /dev/null +++ b/patches.suse/PCI-AER-Clear-device-status-bits-during-ERR_FATAL-an.patch @@ -0,0 +1,86 @@ +From ec752f5d54d723af3df03959637f963079643cd8 Mon Sep 17 00:00:00 2001 +From: Oza Pawandeep +Date: Thu, 19 Jul 2018 17:58:09 -0500 +Subject: [PATCH] PCI/AER: Clear device status bits during ERR_FATAL and ERR_NONFATAL +Git-commit: ec752f5d54d723af3df03959637f963079643cd8 +Patch-mainline: v4.19-rc1 +References: bsc#1161561 + +Clear the device status bits while handling both ERR_FATAL and ERR_NONFATAL +cases. + +Signed-off-by: Oza Pawandeep +[bhelgaas: rename to pci_aer_clear_device_status(), declare internal to PCI +core instead of exposing it everywhere] + +Signed-off-by: Bjorn Helgaas +Acked-by: Takashi Iwai + +--- + drivers/pci/pcie/aer/aerdrv.c | 7 +------ + drivers/pci/pcie/aer/aerdrv_core.c | 8 ++++++++ + drivers/pci/pcie/err.c | 1 + + include/linux/aer.h | 2 ++ + 4 files changed, 12 insertions(+), 6 deletions(-) + +--- a/drivers/pci/pcie/aer/aerdrv_core.c ++++ b/drivers/pci/pcie/aer/aerdrv_core.c +@@ -53,6 +53,14 @@ int pci_disable_pcie_error_reporting(str + } + EXPORT_SYMBOL_GPL(pci_disable_pcie_error_reporting); + ++void pci_aer_clear_device_status(struct pci_dev *dev) ++{ ++ u16 sta; ++ ++ pcie_capability_read_word(dev, PCI_EXP_DEVSTA, &sta); ++ pcie_capability_write_word(dev, PCI_EXP_DEVSTA, sta); ++} ++ + int pci_cleanup_aer_uncorrect_error_status(struct pci_dev *dev) + { + int pos; +--- a/drivers/pci/pcie/err.c ++++ b/drivers/pci/pcie/err.c +@@ -318,6 +318,7 @@ void pcie_do_fatal_recovery(struct pci_d + * of the bridge and clear the error status of the bridge. + */ + pci_aer_clear_fatal_status(dev); ++ pci_aer_clear_device_status(dev); + } + + if (result == PCI_ERS_RESULT_RECOVERED) { +--- a/include/linux/aer.h ++++ b/include/linux/aer.h +@@ -46,6 +46,7 @@ int pci_disable_pcie_error_reporting(str + int pci_cleanup_aer_uncorrect_error_status(struct pci_dev *dev); + int pci_cleanup_aer_error_status_regs(struct pci_dev *dev); + void pci_aer_clear_fatal_status(struct pci_dev *dev); ++void pci_aer_clear_device_status(struct pci_dev *dev); + #else + static inline int pci_enable_pcie_error_reporting(struct pci_dev *dev) + { +@@ -64,6 +65,7 @@ static inline int pci_cleanup_aer_error_ + return -EINVAL; + } + static inline void pci_aer_clear_fatal_status(struct pci_dev *dev) { } ++static inline void pci_aer_clear_device_status(struct pci_dev *dev) { } + #endif + + void cper_print_aer(struct pci_dev *dev, int aer_severity, +--- a/drivers/pci/pcie/aer/aerdrv.c ++++ b/drivers/pci/pcie/aer/aerdrv.c +@@ -347,12 +347,7 @@ static pci_ers_result_t aer_root_reset(s + */ + static void aer_error_resume(struct pci_dev *dev) + { +- u16 reg16; +- +- /* Clean up Root device status */ +- pcie_capability_read_word(dev, PCI_EXP_DEVSTA, ®16); +- pcie_capability_write_word(dev, PCI_EXP_DEVSTA, reg16); +- ++ pci_aer_clear_device_status(dev); + pci_cleanup_aer_uncorrect_error_status(dev); + } + diff --git a/patches.suse/PCI-AER-Clear-only-ERR_FATAL-status-bits-during-fata.patch b/patches.suse/PCI-AER-Clear-only-ERR_FATAL-status-bits-during-fata.patch new file mode 100644 index 0000000..97ecbe0 --- /dev/null +++ b/patches.suse/PCI-AER-Clear-only-ERR_FATAL-status-bits-during-fata.patch @@ -0,0 +1,80 @@ +From 7ab92e89bf8b0a93f0d53b6d83270e4cd0f7c563 Mon Sep 17 00:00:00 2001 +From: Bjorn Helgaas +Date: Thu, 19 Jul 2018 17:55:58 -0500 +Subject: [PATCH] PCI/AER: Clear only ERR_FATAL status bits during fatal recovery +Git-commit: 7ab92e89bf8b0a93f0d53b6d83270e4cd0f7c563 +Patch-mainline: v4.19-rc1 +References: bsc#1161561 + +During recovery from fatal errors, we previously called +pci_cleanup_aer_uncorrect_error_status(), which cleared *all* uncorrectable +error status bits (both ERR_FATAL and ERR_NONFATAL). + +Instead, call a new pci_aer_clear_fatal_status() that clears only the +ERR_FATAL bits (as indicated by the PCI_ERR_UNCOR_SEVER register). + +Based-on-patch-by: Oza Pawandeep +Signed-off-by: Bjorn Helgaas +Acked-by: Takashi Iwai + +--- + drivers/pci/pcie/aer/aerdrv_core.c | 17 +++++++++++++++++ + drivers/pci/pcie/err.c | 2 +- + include/linux/aer.h | 2 ++ + 3 files changed, 20 insertions(+), 1 deletion(-) + +--- a/drivers/pci/pcie/aer/aerdrv_core.c ++++ b/drivers/pci/pcie/aer/aerdrv_core.c +@@ -70,6 +70,23 @@ int pci_cleanup_aer_uncorrect_error_stat + } + EXPORT_SYMBOL_GPL(pci_cleanup_aer_uncorrect_error_status); + ++void pci_aer_clear_fatal_status(struct pci_dev *dev) ++{ ++ int pos; ++ u32 status, sev; ++ ++ pos = dev->aer_cap; ++ if (!pos) ++ return; ++ ++ /* Clear status bits for ERR_FATAL errors only */ ++ pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_STATUS, &status); ++ pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_SEVER, &sev); ++ status &= sev; ++ if (status) ++ pci_write_config_dword(dev, pos + PCI_ERR_UNCOR_STATUS, status); ++} ++ + int pci_cleanup_aer_error_status_regs(struct pci_dev *dev) + { + int pos; +--- a/drivers/pci/pcie/err.c ++++ b/drivers/pci/pcie/err.c +@@ -262,7 +262,7 @@ void pcie_do_fatal_recovery(struct pci_d + * do error recovery on all subordinates of the bridge instead + * of the bridge and clear the error status of the bridge. + */ +- pci_cleanup_aer_uncorrect_error_status(dev); ++ pci_aer_clear_fatal_status(dev); + } + + if (result == PCI_ERS_RESULT_RECOVERED) { +--- a/include/linux/aer.h ++++ b/include/linux/aer.h +@@ -45,6 +45,7 @@ int pci_enable_pcie_error_reporting(stru + int pci_disable_pcie_error_reporting(struct pci_dev *dev); + int pci_cleanup_aer_uncorrect_error_status(struct pci_dev *dev); + int pci_cleanup_aer_error_status_regs(struct pci_dev *dev); ++void pci_aer_clear_fatal_status(struct pci_dev *dev); + #else + static inline int pci_enable_pcie_error_reporting(struct pci_dev *dev) + { +@@ -62,6 +63,7 @@ static inline int pci_cleanup_aer_error_ + { + return -EINVAL; + } ++static inline void pci_aer_clear_fatal_status(struct pci_dev *dev) { } + #endif + + void cper_print_aer(struct pci_dev *dev, int aer_severity, diff --git a/patches.suse/PCI-AER-Clear-only-ERR_NONFATAL-bits-during-non-fata.patch b/patches.suse/PCI-AER-Clear-only-ERR_NONFATAL-bits-during-non-fata.patch new file mode 100644 index 0000000..dc8efda --- /dev/null +++ b/patches.suse/PCI-AER-Clear-only-ERR_NONFATAL-bits-during-non-fata.patch @@ -0,0 +1,44 @@ +From e7b0b847de6db161e3917732276e425bc92a2feb Mon Sep 17 00:00:00 2001 +From: Oza Pawandeep +Date: Thu, 19 Jul 2018 17:58:05 -0500 +Subject: [PATCH] PCI/AER: Clear only ERR_NONFATAL bits during non-fatal recovery +Git-commit: e7b0b847de6db161e3917732276e425bc92a2feb +Patch-mainline: v4.19-rc1 +References: bsc#1161561 + +pci_cleanup_aer_uncorrect_error_status() is called by driver .slot_reset() +methods when handling ERR_NONFATAL errors. Previously this cleared *all* +the bits, including ERR_FATAL bits. + +Since we're only handling ERR_NONFATAL errors, clear only the ERR_NONFATAL +error status bits. + +Signed-off-by: Oza Pawandeep +[bhelgaas: split to separate patch] +Signed-off-by: Bjorn Helgaas +Acked-by: Takashi Iwai + +--- + drivers/pci/pcie/aer/aerdrv_core.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +--- a/drivers/pci/pcie/aer/aerdrv_core.c ++++ b/drivers/pci/pcie/aer/aerdrv_core.c +@@ -56,13 +56,16 @@ EXPORT_SYMBOL_GPL(pci_disable_pcie_error + int pci_cleanup_aer_uncorrect_error_status(struct pci_dev *dev) + { + int pos; +- u32 status; ++ u32 status, sev; + + pos = dev->aer_cap; + if (!pos) + return -EIO; + ++ /* Clear status bits for ERR_NONFATAL errors only */ + pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_STATUS, &status); ++ pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_SEVER, &sev); ++ status &= ~sev; + if (status) + pci_write_config_dword(dev, pos + PCI_ERR_UNCOR_STATUS, status); + diff --git a/patches.suse/PCI-AER-Don-t-clear-AER-bits-if-error-handling-is-Fi.patch b/patches.suse/PCI-AER-Don-t-clear-AER-bits-if-error-handling-is-Fi.patch new file mode 100644 index 0000000..e29aeef --- /dev/null +++ b/patches.suse/PCI-AER-Don-t-clear-AER-bits-if-error-handling-is-Fi.patch @@ -0,0 +1,58 @@ +From 45687f96c112adda2f1d1f05b977661eb00d5a1c Mon Sep 17 00:00:00 2001 +From: Alexandru Gagniuc +Date: Tue, 17 Jul 2018 10:31:23 -0500 +Subject: [PATCH] PCI/AER: Don't clear AER bits if error handling is Firmware-First +Git-commit: 45687f96c112adda2f1d1f05b977661eb00d5a1c +Patch-mainline: v4.19-rc1 +References: bsc#1161561 + +If the platform requests Firmware-First error handling, firmware is +responsible for reading and clearing AER status bits. If OSPM also clears +them, we may miss errors. See ACPI v6.2, sec 18.3.2.5 and 18.4. + +This race is mostly of theoretical significance, as it is not easy to +reasonably demonstrate it in testing. + +Signed-off-by: Alexandru Gagniuc +[bhelgaas: add similar guards to pci_cleanup_aer_uncorrect_error_status() +and pci_aer_clear_fatal_status()] + +Signed-off-by: Bjorn Helgaas +Acked-by: Takashi Iwai + +--- + drivers/pci/pcie/aer/aerdrv_core.c | 9 +++++++++ + 1 file changed, 9 insertions(+) + +--- a/drivers/pci/pcie/aer/aerdrv_core.c ++++ b/drivers/pci/pcie/aer/aerdrv_core.c +@@ -70,6 +70,9 @@ int pci_cleanup_aer_uncorrect_error_stat + if (!pos) + return -EIO; + ++ if (pcie_aer_get_firmware_first(dev)) ++ return -EIO; ++ + /* Clear status bits for ERR_NONFATAL errors only */ + pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_STATUS, &status); + pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_SEVER, &sev); +@@ -90,6 +93,9 @@ void pci_aer_clear_fatal_status(struct p + if (!pos) + return; + ++ if (pcie_aer_get_firmware_first(dev)) ++ return; ++ + /* Clear status bits for ERR_FATAL errors only */ + pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_STATUS, &status); + pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_SEVER, &sev); +@@ -111,6 +117,9 @@ int pci_cleanup_aer_error_status_regs(st + if (!pos) + return -EIO; + ++ if (pcie_aer_get_firmware_first(dev)) ++ return -EIO; ++ + port_type = pci_pcie_type(dev); + if (port_type == PCI_EXP_TYPE_ROOT_PORT) { + pci_read_config_dword(dev, pos + PCI_ERR_ROOT_STATUS, &status); diff --git a/patches.suse/PCI-AER-Don-t-read-upstream-ports-below-fatal-errors.patch b/patches.suse/PCI-AER-Don-t-read-upstream-ports-below-fatal-errors.patch new file mode 100644 index 0000000..481121b --- /dev/null +++ b/patches.suse/PCI-AER-Don-t-read-upstream-ports-below-fatal-errors.patch @@ -0,0 +1,38 @@ +From 9d938ea53b265ed6df6cdd1715d971f0235fdbfc Mon Sep 17 00:00:00 2001 +From: Keith Busch +Date: Thu, 20 Sep 2018 10:27:10 -0600 +Subject: [PATCH] PCI/AER: Don't read upstream ports below fatal errors +Git-commit: 9d938ea53b265ed6df6cdd1715d971f0235fdbfc +Patch-mainline: v4.20-rc1 +References: bsc#1161561 + +The AER driver has never read the config space of an endpoint that reported +a fatal error because the link to that device is considered unreliable. + +An ERR_FATAL from an upstream port almost certainly indicates an error on +its upstream link, so we can't expect to reliably read its config space for +the same reason. + +Signed-off-by: Keith Busch +Signed-off-by: Bjorn Helgaas +Reviewed-by: Sinan Kaya +Acked-by: Takashi Iwai + +--- + drivers/pci/pcie/aer/aerdrv_core.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +--- a/drivers/pci/pcie/aer/aerdrv_core.c ++++ b/drivers/pci/pcie/aer/aerdrv_core.c +@@ -363,8 +363,9 @@ int aer_get_device_error_info(struct pci + &info->mask); + if (!(info->status & ~info->mask)) + return 0; +- } else if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE || +- info->severity == AER_NONFATAL) { ++ } else if (pci_pcie_type(dev) == PCI_EXP_TYPE_ROOT_PORT || ++ pci_pcie_type(dev) == PCI_EXP_TYPE_DOWNSTREAM || ++ info->severity == AER_NONFATAL) { + + /* Link is still healthy for IO reads */ + pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_STATUS, diff --git a/patches.suse/PCI-AER-Factor-message-prefixes-with-dev_fmt.patch b/patches.suse/PCI-AER-Factor-message-prefixes-with-dev_fmt.patch new file mode 100644 index 0000000..3fab473 --- /dev/null +++ b/patches.suse/PCI-AER-Factor-message-prefixes-with-dev_fmt.patch @@ -0,0 +1,59 @@ +From 8d077c3ce0109c406c265cafc334258caee47e6d Mon Sep 17 00:00:00 2001 +From: Bjorn Helgaas +Date: Fri, 13 Dec 2019 16:46:05 -0600 +Subject: [PATCH] PCI/AER: Factor message prefixes with dev_fmt() +Git-commit: 8d077c3ce0109c406c265cafc334258caee47e6d +Patch-mainline: v5.6-rc1 +References: bsc#1161561 + +Define dev_fmt() with the common prefix of log messages so we don't have to +repeat it in every printk. No functional change intended. + +Link: https://lore.kernel.org/r/20191213225709.GA213811@google.com +Signed-off-by: Bjorn Helgaas +Acked-by: Takashi Iwai + +--- + drivers/pci/pcie/err.c | 8 +++++--- + 1 file changed, 5 insertions(+), 3 deletions(-) + +diff --git a/drivers/pci/pcie/err.c b/drivers/pci/pcie/err.c +index 98acf944a27f..01dfc8bb7ca0 100644 +--- a/drivers/pci/pcie/err.c ++++ b/drivers/pci/pcie/err.c +@@ -10,6 +10,8 @@ + * Zhang Yanmin (yanmin.zhang@intel.com) + */ + ++#define dev_fmt(fmt) "AER: " fmt ++ + #include + #include + #include +@@ -63,7 +65,7 @@ static int report_error_detected(struct pci_dev *dev, + */ + if (dev->hdr_type != PCI_HEADER_TYPE_BRIDGE) { + vote = PCI_ERS_RESULT_NO_AER_DRIVER; +- pci_info(dev, "AER: Can't recover (no error_detected callback)\n"); ++ pci_info(dev, "can't recover (no error_detected callback)\n"); + } else { + vote = PCI_ERS_RESULT_NONE; + } +@@ -235,12 +237,12 @@ void pcie_do_recovery(struct pci_dev *dev, enum pci_channel_state state, + + pci_aer_clear_device_status(dev); + pci_cleanup_aer_uncorrect_error_status(dev); +- pci_info(dev, "AER: Device recovery successful\n"); ++ pci_info(dev, "device recovery successful\n"); + return; + + failed: + pci_uevent_ers(dev, PCI_ERS_RESULT_DISCONNECT); + + /* TODO: Should kernel panic here? */ +- pci_info(dev, "AER: Device recovery failed\n"); ++ pci_info(dev, "device recovery failed\n"); + } +-- +2.16.4 + diff --git a/patches.suse/PCI-AER-Factor-out-ERR_NONFATAL-status-bit-clearing.patch b/patches.suse/PCI-AER-Factor-out-ERR_NONFATAL-status-bit-clearing.patch new file mode 100644 index 0000000..5ffc7ba --- /dev/null +++ b/patches.suse/PCI-AER-Factor-out-ERR_NONFATAL-status-bit-clearing.patch @@ -0,0 +1,45 @@ +From 5b6c09660da8779dd545fa717c2b0cc79d477c9e Mon Sep 17 00:00:00 2001 +From: Oza Pawandeep +Date: Thu, 19 Jul 2018 17:58:06 -0500 +Subject: [PATCH] PCI/AER: Factor out ERR_NONFATAL status bit clearing +Git-commit: 5b6c09660da8779dd545fa717c2b0cc79d477c9e +Patch-mainline: v4.19-rc1 +References: bsc#1161561 + +aer_error_resume() clears all ERR_NONFATAL error status bits. This is +exactly what pci_cleanup_aer_uncorrect_error_status(), so use that instead +of duplicating the code. + +Signed-off-by: Oza Pawandeep +[bhelgaas: split to separate patch] +Signed-off-by: Bjorn Helgaas +Acked-by: Takashi Iwai + +--- + drivers/pci/pcie/aer/aerdrv.c | 9 +-------- + 1 file changed, 1 insertion(+), 8 deletions(-) + +--- a/drivers/pci/pcie/aer/aerdrv.c ++++ b/drivers/pci/pcie/aer/aerdrv.c +@@ -347,20 +347,13 @@ static pci_ers_result_t aer_root_reset(s + */ + static void aer_error_resume(struct pci_dev *dev) + { +- int pos; +- u32 status, mask; + u16 reg16; + + /* Clean up Root device status */ + pcie_capability_read_word(dev, PCI_EXP_DEVSTA, ®16); + pcie_capability_write_word(dev, PCI_EXP_DEVSTA, reg16); + +- /* Clean AER Root Error Status */ +- pos = dev->aer_cap; +- pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_STATUS, &status); +- pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_SEVER, &mask); +- status &= ~mask; /* Clear corresponding nonfatal bits */ +- pci_write_config_dword(dev, pos + PCI_ERR_UNCOR_STATUS, status); ++ pci_cleanup_aer_uncorrect_error_status(dev); + } + + /** diff --git a/patches.suse/PCI-AER-Factor-out-error-reporting-to-drivers-pci-pc.patch b/patches.suse/PCI-AER-Factor-out-error-reporting-to-drivers-pci-pc.patch index 2c3dc43..308f0a1 100644 --- a/patches.suse/PCI-AER-Factor-out-error-reporting-to-drivers-pci-pc.patch +++ b/patches.suse/PCI-AER-Factor-out-error-reporting-to-drivers-pci-pc.patch @@ -50,8 +50,8 @@ Acked-by: Takashi Iwai # Build PCI Express ASPM if needed obj-$(CONFIG_PCIEASPM) += aspm.o --pcieportdrv-y := portdrv_core.o portdrv_pci.o portdrv_bus.o -+pcieportdrv-y := portdrv_core.o portdrv_pci.o err.o portdrv_bus.o +-pcieportdrv-y := portdrv_core.o portdrv_pci.o ++pcieportdrv-y := portdrv_core.o portdrv_pci.o err.o obj-$(CONFIG_PCIEPORTBUS) += pcieportdrv.o diff --git a/patches.suse/PCI-AER-Log-which-device-prevents-error-recovery.patch b/patches.suse/PCI-AER-Log-which-device-prevents-error-recovery.patch new file mode 100644 index 0000000..74e8724 --- /dev/null +++ b/patches.suse/PCI-AER-Log-which-device-prevents-error-recovery.patch @@ -0,0 +1,46 @@ +From 01daacfb9035e5b86d43a01f11a0614648f306c1 Mon Sep 17 00:00:00 2001 +From: Yicong Yang +Date: Fri, 13 Dec 2019 19:44:34 +0800 +Subject: [PATCH] PCI/AER: Log which device prevents error recovery +Git-commit: 01daacfb9035e5b86d43a01f11a0614648f306c1 +Patch-mainline: v5.6-rc1 +References: bsc#1161561 + +PCI error recovery will fail if any device under the Root Port doesn't have +an error_detected callback. Currently only the failure result is printed, +which is not enough to identify the driver that lacks the callback. + +Log a message to identify the device with no error_detected callback. + +[bhelgaas: tweak log message] +Link: https://lore.kernel.org/r/1576237474-32021-1-git-send-email-yangyicong@hisilicon.com +Signed-off-by: Yicong Yang +Signed-off-by: Bjorn Helgaas +Acked-by: Takashi Iwai + +--- + drivers/pci/pcie/err.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/drivers/pci/pcie/err.c b/drivers/pci/pcie/err.c +index b0e6048a9208..98acf944a27f 100644 +--- a/drivers/pci/pcie/err.c ++++ b/drivers/pci/pcie/err.c +@@ -61,10 +61,12 @@ static int report_error_detected(struct pci_dev *dev, + * error callbacks of "any" device in the subtree, and will + * exit in the disconnected error state. + */ +- if (dev->hdr_type != PCI_HEADER_TYPE_BRIDGE) ++ if (dev->hdr_type != PCI_HEADER_TYPE_BRIDGE) { + vote = PCI_ERS_RESULT_NO_AER_DRIVER; +- else ++ pci_info(dev, "AER: Can't recover (no error_detected callback)\n"); ++ } else { + vote = PCI_ERS_RESULT_NONE; ++ } + } else { + err_handler = dev->driver->err_handler; + vote = err_handler->error_detected(dev, state); +-- +2.16.4 + diff --git a/patches.suse/PCI-AER-Remove-ERR_FATAL-code-from-ERR_NONFATAL-path.patch b/patches.suse/PCI-AER-Remove-ERR_FATAL-code-from-ERR_NONFATAL-path.patch new file mode 100644 index 0000000..d0ca182 --- /dev/null +++ b/patches.suse/PCI-AER-Remove-ERR_FATAL-code-from-ERR_NONFATAL-path.patch @@ -0,0 +1,46 @@ +From 43ec03a9e5f382ff70fdef35b4ea813263cd8270 Mon Sep 17 00:00:00 2001 +From: Oza Pawandeep +Date: Thu, 19 Jul 2018 17:58:07 -0500 +Subject: [PATCH] PCI/AER: Remove ERR_FATAL code from ERR_NONFATAL path +Git-commit: 43ec03a9e5f382ff70fdef35b4ea813263cd8270 +Patch-mainline: v4.19-rc1 +References: bsc#1161561 + +broadcast_error_message() is only used for ERR_NONFATAL events, when the +state is always pci_channel_io_normal, so remove the unused alternate path. + +Signed-off-by: Oza Pawandeep +[bhelgaas: changelog] +Signed-off-by: Bjorn Helgaas +Acked-by: Takashi Iwai + +--- + drivers/pci/pcie/err.c | 11 +++-------- + 1 file changed, 3 insertions(+), 8 deletions(-) + +diff --git a/drivers/pci/pcie/err.c b/drivers/pci/pcie/err.c +index 0539518f9861..638eda5c1d79 100644 +--- a/drivers/pci/pcie/err.c ++++ b/drivers/pci/pcie/err.c +@@ -259,15 +259,10 @@ static pci_ers_result_t broadcast_error_message(struct pci_dev *dev, + /* + * If the error is reported by an end point, we think this + * error is related to the upstream link of the end point. ++ * The error is non fatal so the bus is ok; just invoke ++ * the callback for the function that logged the error. + */ +- if (state == pci_channel_io_normal) +- /* +- * the error is non fatal so the bus is ok, just invoke +- * the callback for the function that logged the error. +- */ +- cb(dev, &result_data); +- else +- pci_walk_bus(dev->bus, cb, &result_data); ++ cb(dev, &result_data); + } + + return result_data.result; +-- +2.16.4 + diff --git a/patches.suse/PCI-AER-Take-reference-on-error-devices.patch b/patches.suse/PCI-AER-Take-reference-on-error-devices.patch new file mode 100644 index 0000000..57296ac --- /dev/null +++ b/patches.suse/PCI-AER-Take-reference-on-error-devices.patch @@ -0,0 +1,40 @@ +From 60271ab044a53edb9dcbe76bebea2221c4ff04d9 Mon Sep 17 00:00:00 2001 +From: Keith Busch +Date: Thu, 20 Sep 2018 10:27:09 -0600 +Subject: [PATCH] PCI/AER: Take reference on error devices +Git-commit: 60271ab044a53edb9dcbe76bebea2221c4ff04d9 +Patch-mainline: v4.20-rc1 +References: bsc#1161561 + +Error handling may be running in parallel with a hot removal. Reference +count the device during AER handling so the device can not be freed while +AER wants to reference it. + +Signed-off-by: Keith Busch +Signed-off-by: Bjorn Helgaas +Reviewed-by: Sinan Kaya +Acked-by: Takashi Iwai + +--- + drivers/pci/pcie/aer/aerdrv_core.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/drivers/pci/pcie/aer/aerdrv_core.c ++++ b/drivers/pci/pcie/aer/aerdrv_core.c +@@ -149,7 +149,7 @@ int pci_aer_init(struct pci_dev *dev) + static int add_error_device(struct aer_err_info *e_info, struct pci_dev *dev) + { + if (e_info->error_dev_num < AER_MAX_MULTI_ERR_DEVICES) { +- e_info->dev[e_info->error_dev_num] = dev; ++ e_info->dev[e_info->error_dev_num] = pci_dev_get(dev); + e_info->error_dev_num++; + return 0; + } +@@ -299,6 +299,7 @@ static void handle_error_source(struct p + pcie_do_nonfatal_recovery(dev); + else if (info->severity == AER_FATAL) + pcie_do_fatal_recovery(dev, PCIE_PORT_SERVICE_AER); ++ pci_dev_put(dev); + } + + #ifdef CONFIG_ACPI_APEI_PCIEAER diff --git a/patches.suse/PCI-ASPM-Clear-the-correct-bits-when-enabling-L1-sub.patch b/patches.suse/PCI-ASPM-Clear-the-correct-bits-when-enabling-L1-sub.patch new file mode 100644 index 0000000..ca58a53 --- /dev/null +++ b/patches.suse/PCI-ASPM-Clear-the-correct-bits-when-enabling-L1-sub.patch @@ -0,0 +1,46 @@ +From 58a3862a10a317a81097ab0c78aecebabb1704f5 Mon Sep 17 00:00:00 2001 +From: Yicong Yang +Date: Fri, 13 Mar 2020 17:53:47 +0800 +Subject: [PATCH] PCI/ASPM: Clear the correct bits when enabling L1 substates +Git-commit: 58a3862a10a317a81097ab0c78aecebabb1704f5 +Patch-mainline: v5.7-rc1 +References: bsc#1051510 + +In pcie_config_aspm_l1ss(), we cleared the wrong bits when enabling ASPM L1 +Substates. Instead of the L1.x enable bits (PCI_L1SS_CTL1_L1SS_MASK, 0xf), we +cleared the Link Activation Interrupt Enable bit (PCI_L1SS_CAP_L1_PM_SS, +0x10). + +Clear the L1.x enable bits before writing the new L1.x configuration. + +[bhelgaas: changelog] +Fixes: aeda9adebab8 ("PCI/ASPM: Configure L1 substate settings") +Link: https://lore.kernel.org/r/1584093227-1292-1-git-send-email-yangyicong@hisilicon.com +Signed-off-by: Yicong Yang +Signed-off-by: Bjorn Helgaas +Cc: stable@vger.kernel.org # v4.11+ +Acked-by: Takashi Iwai + +--- + drivers/pci/pcie/aspm.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/pci/pcie/aspm.c b/drivers/pci/pcie/aspm.c +index 0dcd44308228..c2596e79ec63 100644 +--- a/drivers/pci/pcie/aspm.c ++++ b/drivers/pci/pcie/aspm.c +@@ -747,9 +747,9 @@ static void pcie_config_aspm_l1ss(struct pcie_link_state *link, u32 state) + + /* Enable what we need to enable */ + pci_clear_and_set_dword(parent, up_cap_ptr + PCI_L1SS_CTL1, +- PCI_L1SS_CAP_L1_PM_SS, val); ++ PCI_L1SS_CTL1_L1SS_MASK, val); + pci_clear_and_set_dword(child, dw_cap_ptr + PCI_L1SS_CTL1, +- PCI_L1SS_CAP_L1_PM_SS, val); ++ PCI_L1SS_CTL1_L1SS_MASK, val); + } + + static void pcie_config_aspm_dev(struct pci_dev *pdev, u32 val) +-- +2.16.4 + diff --git a/patches.suse/PCI-ERR-Always-report-current-recovery-status-for-ud.patch b/patches.suse/PCI-ERR-Always-report-current-recovery-status-for-ud.patch new file mode 100644 index 0000000..fd1f0bf --- /dev/null +++ b/patches.suse/PCI-ERR-Always-report-current-recovery-status-for-ud.patch @@ -0,0 +1,50 @@ +From 7b42d97e99d3a2babffd1b3456ded08b54981538 Mon Sep 17 00:00:00 2001 +From: Keith Busch +Date: Thu, 20 Sep 2018 10:27:15 -0600 +Subject: [PATCH] PCI/ERR: Always report current recovery status for udev +Git-commit: 7b42d97e99d3a2babffd1b3456ded08b54981538 +Patch-mainline: v4.20-rc1 +References: bsc#1161561 + +A device still participates in error recovery even if it doesn't have +the error callbacks. + +Always provide the status for user event watchers. + +Signed-off-by: Keith Busch +Signed-off-by: Bjorn Helgaas +Reviewed-by: Sinan Kaya +Acked-by: Takashi Iwai + +--- + drivers/pci/pcie/err.c | 5 ++--- + 1 file changed, 2 insertions(+), 3 deletions(-) + +diff --git a/drivers/pci/pcie/err.c b/drivers/pci/pcie/err.c +index 362a717c831a..31e8a4314384 100644 +--- a/drivers/pci/pcie/err.c ++++ b/drivers/pci/pcie/err.c +@@ -70,9 +70,8 @@ static int report_error_detected(struct pci_dev *dev, + } else { + err_handler = dev->driver->err_handler; + vote = err_handler->error_detected(dev, state); +- pci_uevent_ers(dev, PCI_ERS_RESULT_NONE); + } +- ++ pci_uevent_ers(dev, vote); + *result = merge_result(*result, vote); + device_unlock(&dev->dev); + return 0; +@@ -140,8 +139,8 @@ static int report_resume(struct pci_dev *dev, void *data) + + err_handler = dev->driver->err_handler; + err_handler->resume(dev); +- pci_uevent_ers(dev, PCI_ERS_RESULT_RECOVERED); + out: ++ pci_uevent_ers(dev, PCI_ERS_RESULT_RECOVERED); + device_unlock(&dev->dev); + return 0; + } +-- +2.16.4 + diff --git a/patches.suse/PCI-ERR-Handle-fatal-error-recovery.patch b/patches.suse/PCI-ERR-Handle-fatal-error-recovery.patch new file mode 100644 index 0000000..ef3b4a4 --- /dev/null +++ b/patches.suse/PCI-ERR-Handle-fatal-error-recovery.patch @@ -0,0 +1,256 @@ +From bdb5ac85777de67c909c9ad4327f03f7648b543f Mon Sep 17 00:00:00 2001 +From: Keith Busch +Date: Thu, 20 Sep 2018 10:27:12 -0600 +Subject: [PATCH] PCI/ERR: Handle fatal error recovery +Git-commit: bdb5ac85777de67c909c9ad4327f03f7648b543f +Patch-mainline: v4.20-rc1 +References: bsc#1161561 + +We don't need to be paranoid about the topology changing while handling an +error. If the device has changed in a hotplug capable slot, we can rely on +the presence detection handling to react to a changing topology. + +Restore the fatal error handling behavior that existed before merging DPC +with AER with 7e9084b36740 ("PCI/AER: Handle ERR_FATAL with removal and +re-enumeration of devices"). + +Signed-off-by: Keith Busch +Signed-off-by: Bjorn Helgaas +Reviewed-by: Sinan Kaya +Acked-by: Takashi Iwai + +--- + Documentation/PCI/pci-error-recovery.txt | 35 ++++---------- + drivers/pci/pci.h | 4 - + drivers/pci/pcie/aer/aerdrv_core.c | 12 +++- + drivers/pci/pcie/dpc.c | 4 - + drivers/pci/pcie/err.c | 75 ++----------------------------- + 5 files changed, 28 insertions(+), 102 deletions(-) + +--- a/Documentation/PCI/pci-error-recovery.txt ++++ b/Documentation/PCI/pci-error-recovery.txt +@@ -110,7 +110,7 @@ The actual steps taken by a platform to + event will be platform-dependent, but will follow the general + sequence described below. + +-STEP 0: Error Event: ERR_NONFATAL ++STEP 0: Error Event + ------------------- + A PCI bus error is detected by the PCI hardware. On powerpc, the slot + is isolated, in that all I/O is blocked: all reads return 0xffffffff, +@@ -228,7 +228,13 @@ proceeds to either STEP3 (Link Reset) or + If any driver returned PCI_ERS_RESULT_NEED_RESET, then the platform + proceeds to STEP 4 (Slot Reset) + +-STEP 3: Slot Reset ++STEP 3: Link Reset ++------------------ ++The platform resets the link. This is a PCI-Express specific step ++and is done whenever a fatal error has been detected that can be ++"solved" by resetting the link. ++ ++STEP 4: Slot Reset + ------------------ + + In response to a return value of PCI_ERS_RESULT_NEED_RESET, the +@@ -314,7 +320,7 @@ Failure). + >>> However, it probably should. + + +-STEP 4: Resume Operations ++STEP 5: Resume Operations + ------------------------- + The platform will call the resume() callback on all affected device + drivers if all drivers on the segment have returned +@@ -326,7 +332,7 @@ a result code. + At this point, if a new error happens, the platform will restart + a new error recovery sequence. + +-STEP 5: Permanent Failure ++STEP 6: Permanent Failure + ------------------------- + A "permanent failure" has occurred, and the platform cannot recover + the device. The platform will call error_detected() with a +@@ -349,27 +355,6 @@ errors. See the discussion in powerpc/ee + for additional detail on real-life experience of the causes of + software errors. + +-STEP 0: Error Event: ERR_FATAL +-------------------- +-PCI bus error is detected by the PCI hardware. On powerpc, the slot is +-isolated, in that all I/O is blocked: all reads return 0xffffffff, all +-writes are ignored. +- +-STEP 1: Remove devices +--------------------- +-Platform removes the devices depending on the error agent, it could be +-this port for all subordinates or upstream component (likely downstream +-port) +- +-STEP 2: Reset link +--------------------- +-The platform resets the link. This is a PCI-Express specific step and is +-done whenever a fatal error has been detected that can be "solved" by +-resetting the link. +- +-STEP 3: Re-enumerate the devices +--------------------- +-Initiates the re-enumeration. + + Conclusion; General Remarks + --------------------------- +--- a/drivers/pci/pci.h ++++ b/drivers/pci/pci.h +@@ -404,8 +404,8 @@ static inline resource_size_t pci_resour + void pci_enable_acs(struct pci_dev *dev); + + /* PCI error reporting and recovery */ +-void pcie_do_fatal_recovery(struct pci_dev *dev, u32 service); +-void pcie_do_nonfatal_recovery(struct pci_dev *dev); ++void pcie_do_recovery(struct pci_dev *dev, enum pci_channel_state state, ++ u32 service); + + bool pcie_wait_for_link(struct pci_dev *pdev, bool active); + #ifdef CONFIG_PCIEASPM +--- a/drivers/pci/pcie/dpc.c ++++ b/drivers/pci/pcie/dpc.c +@@ -172,7 +172,7 @@ static irqreturn_t dpc_handler(int irq, + + reason = (status & PCI_EXP_DPC_STATUS_TRIGGER_RSN) >> 1; + ext_reason = (status & PCI_EXP_DPC_STATUS_TRIGGER_RSN_EXT) >> 5; +- dev_warn(dev, "DPC %s detected, remove downstream devices\n", ++ dev_warn(dev, "DPC %s detected\n", + (reason == 0) ? "unmasked uncorrectable error" : + (reason == 1) ? "ERR_NONFATAL" : + (reason == 2) ? "ERR_FATAL" : +@@ -189,7 +189,7 @@ static irqreturn_t dpc_handler(int irq, + } + + /* We configure DPC so it only triggers on ERR_FATAL */ +- pcie_do_fatal_recovery(pdev, PCIE_PORT_SERVICE_DPC); ++ pcie_do_recovery(pdev, pci_channel_io_frozen, PCIE_PORT_SERVICE_DPC); + + return IRQ_HANDLED; + } +--- a/drivers/pci/pcie/err.c ++++ b/drivers/pci/pcie/err.c +@@ -270,83 +270,20 @@ static pci_ers_result_t broadcast_error_ + return result_data.result; + } + +-/** +- * pcie_do_fatal_recovery - handle fatal error recovery process +- * @dev: pointer to a pci_dev data structure of agent detecting an error +- * +- * Invoked when an error is fatal. Once being invoked, removes the devices +- * beneath this AER agent, followed by reset link e.g. secondary bus reset +- * followed by re-enumeration of devices. +- */ +-void pcie_do_fatal_recovery(struct pci_dev *dev, u32 service) +-{ +- struct pci_dev *udev; +- struct pci_bus *parent; +- struct pci_dev *pdev, *temp; +- pci_ers_result_t result; +- +- if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) +- udev = dev; +- else +- udev = dev->bus->self; +- +- parent = udev->subordinate; +- pci_walk_bus(parent, pci_dev_set_disconnected, NULL); +- +- pci_lock_rescan_remove(); +- pci_dev_get(dev); +- list_for_each_entry_safe_reverse(pdev, temp, &parent->devices, +- bus_list) { +- pci_stop_and_remove_bus_device(pdev); +- } +- +- result = reset_link(udev, service); +- +- if ((service == PCIE_PORT_SERVICE_AER) && +- (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE)) { +- /* +- * If the error is reported by a bridge, we think this error +- * is related to the downstream link of the bridge, so we +- * do error recovery on all subordinates of the bridge instead +- * of the bridge and clear the error status of the bridge. +- */ +- pci_aer_clear_fatal_status(dev); +- pci_aer_clear_device_status(dev); +- } +- +- if (result == PCI_ERS_RESULT_RECOVERED) { +- if (pcie_wait_for_link(udev, true)) +- pci_rescan_bus(udev->bus); +- pci_info(dev, "Device recovery from fatal error successful\n"); +- } else { +- pci_uevent_ers(dev, PCI_ERS_RESULT_DISCONNECT); +- pci_info(dev, "Device recovery from fatal error failed\n"); +- } +- +- pci_dev_put(dev); +- pci_unlock_rescan_remove(); +-} +- +-/** +- * pcie_do_nonfatal_recovery - handle nonfatal error recovery process +- * @dev: pointer to a pci_dev data structure of agent detecting an error +- * +- * Invoked when an error is nonfatal/fatal. Once being invoked, broadcast +- * error detected message to all downstream drivers within a hierarchy in +- * question and return the returned code. +- */ +-void pcie_do_nonfatal_recovery(struct pci_dev *dev) ++void pcie_do_recovery(struct pci_dev *dev, enum pci_channel_state state, ++ u32 service) + { + pci_ers_result_t status; +- enum pci_channel_state state; +- +- state = pci_channel_io_normal; + + status = broadcast_error_message(dev, + state, + "error_detected", + report_error_detected); + ++ if (state == pci_channel_io_frozen && ++ reset_link(dev, service) != PCI_ERS_RESULT_RECOVERED) ++ goto failed; ++ + if (status == PCI_ERS_RESULT_CAN_RECOVER) + status = broadcast_error_message(dev, + state, +--- a/drivers/pci/pcie/aer/aerdrv_core.c ++++ b/drivers/pci/pcie/aer/aerdrv_core.c +@@ -296,9 +296,11 @@ static void handle_error_source(struct p + info->status); + pci_aer_clear_device_status(dev); + } else if (info->severity == AER_NONFATAL) +- pcie_do_nonfatal_recovery(dev); ++ pcie_do_recovery(dev, pci_channel_io_normal, ++ PCIE_PORT_SERVICE_AER); + else if (info->severity == AER_FATAL) +- pcie_do_fatal_recovery(dev, PCIE_PORT_SERVICE_AER); ++ pcie_do_recovery(dev, pci_channel_io_frozen, ++ PCIE_PORT_SERVICE_AER); + pci_dev_put(dev); + } + +@@ -364,9 +366,11 @@ static void aer_recover_work_func(struct + } + cper_print_aer(pdev, entry.severity, entry.regs); + if (entry.severity == AER_NONFATAL) +- pcie_do_nonfatal_recovery(pdev); ++ pcie_do_recovery(pdev, pci_channel_io_normal, ++ PCIE_PORT_SERVICE_AER); + else if (entry.severity == AER_FATAL) +- pcie_do_fatal_recovery(pdev, PCIE_PORT_SERVICE_AER); ++ pcie_do_recovery(pdev, pci_channel_io_frozen, ++ PCIE_PORT_SERVICE_AER); + pci_dev_put(pdev); + } + } diff --git a/patches.suse/PCI-ERR-Remove-duplicated-include-from-err.c.patch b/patches.suse/PCI-ERR-Remove-duplicated-include-from-err.c.patch new file mode 100644 index 0000000..a8b5d29 --- /dev/null +++ b/patches.suse/PCI-ERR-Remove-duplicated-include-from-err.c.patch @@ -0,0 +1,33 @@ +From 479e01a402f006746324a04a72bd949ceca5e73d Mon Sep 17 00:00:00 2001 +From: YueHaibing +Date: Wed, 26 Sep 2018 11:00:10 +0000 +Subject: [PATCH] PCI/ERR: Remove duplicated include from err.c +Git-commit: 479e01a402f006746324a04a72bd949ceca5e73d +Patch-mainline: v4.20-rc1 +References: bsc#1161561 + +Remove duplicated include. + +Signed-off-by: YueHaibing +Signed-off-by: Bjorn Helgaas +Acked-by: Takashi Iwai + +--- + drivers/pci/pcie/err.c | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/drivers/pci/pcie/err.c b/drivers/pci/pcie/err.c +index 4da2a62b4f77..773197a12568 100644 +--- a/drivers/pci/pcie/err.c ++++ b/drivers/pci/pcie/err.c +@@ -12,7 +12,6 @@ + + #include + #include +-#include + #include + #include + #include +-- +2.16.4 + diff --git a/patches.suse/PCI-ERR-Run-error-recovery-callbacks-for-all-affecte.patch b/patches.suse/PCI-ERR-Run-error-recovery-callbacks-for-all-affecte.patch new file mode 100644 index 0000000..6bbf156 --- /dev/null +++ b/patches.suse/PCI-ERR-Run-error-recovery-callbacks-for-all-affecte.patch @@ -0,0 +1,173 @@ +From bfcb79fca19d267712e425af1dd48812c40dec0c Mon Sep 17 00:00:00 2001 +From: Keith Busch +Date: Thu, 20 Sep 2018 10:27:13 -0600 +Subject: [PATCH] PCI/ERR: Run error recovery callbacks for all affected devices +Git-commit: bfcb79fca19d267712e425af1dd48812c40dec0c +Patch-mainline: v4.20-rc1 +References: bsc#1161561 + +If an Endpoint reported an error with ERR_FATAL, we previously ran driver +error recovery callbacks only for the Endpoint's driver. But if we reset a +Link to recover from the error, all downstream components are affected, +including the Endpoint, any multi-function peers, and children of those +peers. + +Initiate the Link reset from the deepest Downstream Port that is +reliable, and call the error recovery callbacks for all its children. + +If a Downstream Port (including a Root Port) reports an error, we assume +the Port itself is reliable and we need to reset its downstream Link. In +all other cases (Switch Upstream Ports, Endpoints, Bridges, etc), we assume +the Link leading to the component needs to be reset, so we initiate the +reset at the parent Downstream Port. + +This allows two other clean-ups. First, we currently only use a Link +reset, which can only be initiated using a Downstream Port, so we can +remove checks for Endpoints. Second, the Downstream Port where we initiate +the Link reset is reliable (unlike components downstream from it), so the +special cases for error detect and resume are no longer necessary. + +Signed-off-by: Keith Busch +[bhelgaas: changelog] +Signed-off-by: Bjorn Helgaas +Reviewed-by: Sinan Kaya +Acked-by: Takashi Iwai + +--- + drivers/pci/pcie/err.c | 84 ++++++++++++------------------------------------- + 1 file changed, 21 insertions(+), 63 deletions(-) + +--- a/drivers/pci/pcie/err.c ++++ b/drivers/pci/pcie/err.c +@@ -63,30 +63,12 @@ static int report_error_detected(struct + if (!dev->driver || + !dev->driver->err_handler || + !dev->driver->err_handler->error_detected) { +- if (result_data->state == pci_channel_io_frozen && +- dev->hdr_type != PCI_HEADER_TYPE_BRIDGE) { +- /* +- * In case of fatal recovery, if one of down- +- * stream device has no driver. We might be +- * unable to recover because a later insmod +- * of a driver for this device is unaware of +- * its hw state. +- */ +- pci_printk(KERN_DEBUG, dev, "device has %s\n", +- dev->driver ? +- "no AER-aware driver" : "no driver"); +- } +- + /* +- * If there's any device in the subtree that does not +- * have an error_detected callback, returning +- * PCI_ERS_RESULT_NO_AER_DRIVER prevents calling of +- * the subsequent mmio_enabled/slot_reset/resume +- * callbacks of "any" device in the subtree. All the +- * devices in the subtree are left in the error state +- * without recovery. ++ * If any device in the subtree does not have an error_detected ++ * callback, PCI_ERS_RESULT_NO_AER_DRIVER prevents subsequent ++ * error callbacks of "any" device in the subtree, and will ++ * exit in the disconnected error state. + */ +- + if (dev->hdr_type != PCI_HEADER_TYPE_BRIDGE) + vote = PCI_ERS_RESULT_NO_AER_DRIVER; + else +@@ -184,34 +166,23 @@ static pci_ers_result_t default_reset_li + + static pci_ers_result_t reset_link(struct pci_dev *dev, u32 service) + { +- struct pci_dev *udev; + pci_ers_result_t status; + struct pcie_port_service_driver *driver = NULL; + +- if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) { +- /* Reset this port for all subordinates */ +- udev = dev; +- } else { +- /* Reset the upstream component (likely downstream port) */ +- udev = dev->bus->self; +- } +- +- /* Use the aer driver of the component firstly */ +- driver = pcie_port_find_service(udev, service); +- ++ driver = pcie_port_find_service(dev, service); + if (driver && driver->reset_link) { +- status = driver->reset_link(udev); +- } else if (udev->has_secondary_link) { +- status = default_reset_link(udev); ++ status = driver->reset_link(dev); ++ } else if (dev->has_secondary_link) { ++ status = default_reset_link(dev); + } else { + pci_printk(KERN_DEBUG, dev, "no link-reset support at upstream device %s\n", +- pci_name(udev)); ++ pci_name(dev)); + return PCI_ERS_RESULT_DISCONNECT; + } + + if (status != PCI_ERS_RESULT_RECOVERED) { + pci_printk(KERN_DEBUG, dev, "link reset at upstream device %s failed\n", +- pci_name(udev)); ++ pci_name(dev)); + return PCI_ERS_RESULT_DISCONNECT; + } + +@@ -243,30 +214,7 @@ static pci_ers_result_t broadcast_error_ + else + result_data.result = PCI_ERS_RESULT_RECOVERED; + +- if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) { +- /* +- * If the error is reported by a bridge, we think this error +- * is related to the downstream link of the bridge, so we +- * do error recovery on all subordinates of the bridge instead +- * of the bridge and clear the error status of the bridge. +- */ +- if (cb == report_error_detected) +- dev->error_state = state; +- pci_walk_bus(dev->subordinate, cb, &result_data); +- if (cb == report_resume) { +- pci_cleanup_aer_uncorrect_error_status(dev); +- dev->error_state = pci_channel_io_normal; +- } +- } else { +- /* +- * If the error is reported by an end point, we think this +- * error is related to the upstream link of the end point. +- * The error is non fatal so the bus is ok; just invoke +- * the callback for the function that logged the error. +- */ +- cb(dev, &result_data); +- } +- ++ pci_walk_bus(dev->subordinate, cb, &result_data); + return result_data.result; + } + +@@ -275,6 +223,14 @@ void pcie_do_recovery(struct pci_dev *de + { + pci_ers_result_t status; + ++ /* ++ * Error recovery runs on all subordinates of the first downstream port. ++ * If the downstream port detected the error, it is cleared at the end. ++ */ ++ if (!(pci_pcie_type(dev) == PCI_EXP_TYPE_ROOT_PORT || ++ pci_pcie_type(dev) == PCI_EXP_TYPE_DOWNSTREAM)) ++ dev = dev->bus->self; ++ + status = broadcast_error_message(dev, + state, + "error_detected", +@@ -310,6 +266,8 @@ void pcie_do_recovery(struct pci_dev *de + "resume", + report_resume); + ++ pci_aer_clear_device_status(dev); ++ pci_cleanup_aer_uncorrect_error_status(dev); + pci_info(dev, "AER: Device recovery successful\n"); + return; + diff --git a/patches.suse/PCI-ERR-Simplify-broadcast-callouts.patch b/patches.suse/PCI-ERR-Simplify-broadcast-callouts.patch new file mode 100644 index 0000000..abf1c9e --- /dev/null +++ b/patches.suse/PCI-ERR-Simplify-broadcast-callouts.patch @@ -0,0 +1,230 @@ +From 542aeb9c8f930e4099432cb0bec17b92c0175e08 Mon Sep 17 00:00:00 2001 +From: Keith Busch +Date: Thu, 20 Sep 2018 10:27:14 -0600 +Subject: [PATCH] PCI/ERR: Simplify broadcast callouts +Git-commit: 542aeb9c8f930e4099432cb0bec17b92c0175e08 +Patch-mainline: v4.20-rc1 +References: bsc#1161561 + +There is no point in having a generic broadcast function if it needs to +have special cases for each callback it broadcasts. + +Abstract the error broadcast to only the necessary information and removes +the now unnecessary helper to walk the bus. + +Signed-off-by: Keith Busch +Signed-off-by: Bjorn Helgaas +Reviewed-by: Sinan Kaya +Acked-by: Takashi Iwai + +--- + drivers/pci/pcie/err.c | 107 ++++++++++++++++++------------------------------- + 1 file changed, 38 insertions(+), 69 deletions(-) + +diff --git a/drivers/pci/pcie/err.c b/drivers/pci/pcie/err.c +index 0fa5e1417a4a..362a717c831a 100644 +--- a/drivers/pci/pcie/err.c ++++ b/drivers/pci/pcie/err.c +@@ -19,11 +19,6 @@ + #include "portdrv.h" + #include "../pci.h" + +-struct aer_broadcast_data { +- enum pci_channel_state state; +- enum pci_ers_result result; +-}; +- + static pci_ers_result_t merge_result(enum pci_ers_result orig, + enum pci_ers_result new) + { +@@ -49,16 +44,15 @@ static pci_ers_result_t merge_result(enum pci_ers_result orig, + return orig; + } + +-static int report_error_detected(struct pci_dev *dev, void *data) ++static int report_error_detected(struct pci_dev *dev, ++ enum pci_channel_state state, ++ enum pci_ers_result *result) + { + pci_ers_result_t vote; + const struct pci_error_handlers *err_handler; +- struct aer_broadcast_data *result_data; +- +- result_data = (struct aer_broadcast_data *) data; + + device_lock(&dev->dev); +- dev->error_state = result_data->state; ++ dev->error_state = state; + + if (!dev->driver || + !dev->driver->err_handler || +@@ -75,22 +69,29 @@ static int report_error_detected(struct pci_dev *dev, void *data) + vote = PCI_ERS_RESULT_NONE; + } else { + err_handler = dev->driver->err_handler; +- vote = err_handler->error_detected(dev, result_data->state); ++ vote = err_handler->error_detected(dev, state); + pci_uevent_ers(dev, PCI_ERS_RESULT_NONE); + } + +- result_data->result = merge_result(result_data->result, vote); ++ *result = merge_result(*result, vote); + device_unlock(&dev->dev); + return 0; + } + ++static int report_frozen_detected(struct pci_dev *dev, void *data) ++{ ++ return report_error_detected(dev, pci_channel_io_frozen, data); ++} ++ ++static int report_normal_detected(struct pci_dev *dev, void *data) ++{ ++ return report_error_detected(dev, pci_channel_io_normal, data); ++} ++ + static int report_mmio_enabled(struct pci_dev *dev, void *data) + { +- pci_ers_result_t vote; ++ pci_ers_result_t vote, *result = data; + const struct pci_error_handlers *err_handler; +- struct aer_broadcast_data *result_data; +- +- result_data = (struct aer_broadcast_data *) data; + + device_lock(&dev->dev); + if (!dev->driver || +@@ -100,7 +101,7 @@ static int report_mmio_enabled(struct pci_dev *dev, void *data) + + err_handler = dev->driver->err_handler; + vote = err_handler->mmio_enabled(dev); +- result_data->result = merge_result(result_data->result, vote); ++ *result = merge_result(*result, vote); + out: + device_unlock(&dev->dev); + return 0; +@@ -108,11 +109,8 @@ static int report_mmio_enabled(struct pci_dev *dev, void *data) + + static int report_slot_reset(struct pci_dev *dev, void *data) + { +- pci_ers_result_t vote; ++ pci_ers_result_t vote, *result = data; + const struct pci_error_handlers *err_handler; +- struct aer_broadcast_data *result_data; +- +- result_data = (struct aer_broadcast_data *) data; + + device_lock(&dev->dev); + if (!dev->driver || +@@ -122,7 +120,7 @@ static int report_slot_reset(struct pci_dev *dev, void *data) + + err_handler = dev->driver->err_handler; + vote = err_handler->slot_reset(dev); +- result_data->result = merge_result(result_data->result, vote); ++ *result = merge_result(*result, vote); + out: + device_unlock(&dev->dev); + return 0; +@@ -189,39 +187,11 @@ static pci_ers_result_t reset_link(struct pci_dev *dev, u32 service) + return status; + } + +-/** +- * broadcast_error_message - handle message broadcast to downstream drivers +- * @dev: pointer to from where in a hierarchy message is broadcasted down +- * @state: error state +- * @error_mesg: message to print +- * @cb: callback to be broadcasted +- * +- * Invoked during error recovery process. Once being invoked, the content +- * of error severity will be broadcasted to all downstream drivers in a +- * hierarchy in question. +- */ +-static pci_ers_result_t broadcast_error_message(struct pci_dev *dev, +- enum pci_channel_state state, +- char *error_mesg, +- int (*cb)(struct pci_dev *, void *)) +-{ +- struct aer_broadcast_data result_data; +- +- pci_printk(KERN_DEBUG, dev, "broadcast %s message\n", error_mesg); +- result_data.state = state; +- if (cb == report_error_detected) +- result_data.result = PCI_ERS_RESULT_CAN_RECOVER; +- else +- result_data.result = PCI_ERS_RESULT_RECOVERED; +- +- pci_walk_bus(dev->subordinate, cb, &result_data); +- return result_data.result; +-} +- + void pcie_do_recovery(struct pci_dev *dev, enum pci_channel_state state, + u32 service) + { +- pci_ers_result_t status; ++ pci_ers_result_t status = PCI_ERS_RESULT_CAN_RECOVER; ++ struct pci_bus *bus; + + /* + * Error recovery runs on all subordinates of the first downstream port. +@@ -230,21 +200,23 @@ void pcie_do_recovery(struct pci_dev *dev, enum pci_channel_state state, + if (!(pci_pcie_type(dev) == PCI_EXP_TYPE_ROOT_PORT || + pci_pcie_type(dev) == PCI_EXP_TYPE_DOWNSTREAM)) + dev = dev->bus->self; ++ bus = dev->subordinate; + +- status = broadcast_error_message(dev, +- state, +- "error_detected", +- report_error_detected); ++ pci_dbg(dev, "broadcast error_detected message\n"); ++ if (state == pci_channel_io_frozen) ++ pci_walk_bus(bus, report_frozen_detected, &status); ++ else ++ pci_walk_bus(bus, report_normal_detected, &status); + + if (state == pci_channel_io_frozen && + reset_link(dev, service) != PCI_ERS_RESULT_RECOVERED) + goto failed; + +- if (status == PCI_ERS_RESULT_CAN_RECOVER) +- status = broadcast_error_message(dev, +- state, +- "mmio_enabled", +- report_mmio_enabled); ++ if (status == PCI_ERS_RESULT_CAN_RECOVER) { ++ status = PCI_ERS_RESULT_RECOVERED; ++ pci_dbg(dev, "broadcast mmio_enabled message\n"); ++ pci_walk_bus(bus, report_mmio_enabled, &status); ++ } + + if (status == PCI_ERS_RESULT_NEED_RESET) { + /* +@@ -252,19 +224,16 @@ void pcie_do_recovery(struct pci_dev *dev, enum pci_channel_state state, + * functions to reset slot before calling + * drivers' slot_reset callbacks? + */ +- status = broadcast_error_message(dev, +- state, +- "slot_reset", +- report_slot_reset); ++ status = PCI_ERS_RESULT_RECOVERED; ++ pci_dbg(dev, "broadcast slot_reset message\n"); ++ pci_walk_bus(bus, report_slot_reset, &status); + } + + if (status != PCI_ERS_RESULT_RECOVERED) + goto failed; + +- broadcast_error_message(dev, +- state, +- "resume", +- report_resume); ++ pci_dbg(dev, "broadcast resume message\n"); ++ pci_walk_bus(bus, report_resume, &status); + + pci_aer_clear_device_status(dev); + pci_cleanup_aer_uncorrect_error_status(dev); +-- +2.16.4 + diff --git a/patches.suse/PCI-ERR-Use-slot-reset-if-available.patch b/patches.suse/PCI-ERR-Use-slot-reset-if-available.patch new file mode 100644 index 0000000..3a79f5d --- /dev/null +++ b/patches.suse/PCI-ERR-Use-slot-reset-if-available.patch @@ -0,0 +1,133 @@ +From c4eed62a214330908eec11b0dc170d34fa50b412 Mon Sep 17 00:00:00 2001 +From: Keith Busch +Date: Thu, 20 Sep 2018 10:27:11 -0600 +Subject: [PATCH] PCI/ERR: Use slot reset if available +Git-commit: c4eed62a214330908eec11b0dc170d34fa50b412 +Patch-mainline: v4.20-rc1 +References: bsc#1161561 + +The secondary bus reset may have link side effects that a hotplug capable +port may incorrectly react to. Use the slot specific reset for hotplug +ports, fixing the undesirable link down-up handling during error +recovering. + +Signed-off-by: Keith Busch +[bhelgaas: fold in +https://lore.kernel.org/linux-pci/20180926152326.14821-1-keith.busch@intel.com +for issue reported by Stephen Rothwell ] + +Signed-off-by: Bjorn Helgaas +Reviewed-by: Sinan Kaya +Acked-by: Takashi Iwai + +--- + drivers/pci/pci.c | 37 +++++++++++++++++++++++++++++++++++++ + drivers/pci/pci.h | 2 ++ + drivers/pci/pcie/aer/aerdrv.c | 2 +- + drivers/pci/pcie/err.c | 2 +- + drivers/pci/slot.c | 1 - + 5 files changed, 41 insertions(+), 3 deletions(-) + +--- a/drivers/pci/pci.c ++++ b/drivers/pci/pci.c +@@ -35,6 +35,8 @@ + #include + #include "pci.h" + ++DEFINE_MUTEX(pci_slot_mutex); ++ + const char *pci_power_names[] = { + "error", "D0", "D1", "D2", "D3hot", "D3cold", "unknown", + }; +@@ -4920,6 +4922,41 @@ static int pci_bus_reset(struct pci_bus + } + + /** ++ * pci_bus_error_reset - reset the bridge's subordinate bus ++ * @bridge: The parent device that connects to the bus to reset ++ * ++ * This function will first try to reset the slots on this bus if the method is ++ * available. If slot reset fails or is not available, this will fall back to a ++ * secondary bus reset. ++ */ ++int pci_bus_error_reset(struct pci_dev *bridge) ++{ ++ struct pci_bus *bus = bridge->subordinate; ++ struct pci_slot *slot; ++ ++ if (!bus) ++ return -ENOTTY; ++ ++ mutex_lock(&pci_slot_mutex); ++ if (list_empty(&bus->slots)) ++ goto bus_reset; ++ ++ list_for_each_entry(slot, &bus->slots, list) ++ if (pci_probe_reset_slot(slot)) ++ goto bus_reset; ++ ++ list_for_each_entry(slot, &bus->slots, list) ++ if (pci_slot_reset(slot, 0)) ++ goto bus_reset; ++ ++ mutex_unlock(&pci_slot_mutex); ++ return 0; ++bus_reset: ++ mutex_unlock(&pci_slot_mutex); ++ return pci_bus_reset(bridge->subordinate, 0); ++} ++ ++/** + * pci_probe_reset_bus - probe whether a PCI bus can be reset + * @bus: PCI bus to probe + * +--- a/drivers/pci/pci.h ++++ b/drivers/pci/pci.h +@@ -32,6 +32,7 @@ int pci_mmap_fits(struct pci_dev *pdev, + enum pci_mmap_api mmap_api); + + int pci_probe_reset_function(struct pci_dev *dev); ++int pci_bus_error_reset(struct pci_dev *dev); + + /** + * struct pci_platform_pm_ops - Firmware PM callbacks +@@ -147,6 +148,7 @@ static inline void pci_remove_legacy_fil + + /* Lock for read/write access to pci device and bus lists */ + extern struct rw_semaphore pci_bus_sem; ++extern struct mutex pci_slot_mutex; + + extern raw_spinlock_t pci_lock; + +--- a/drivers/pci/pcie/aer/aerdrv.c ++++ b/drivers/pci/pcie/aer/aerdrv.c +@@ -325,7 +325,7 @@ static pci_ers_result_t aer_root_reset(s + reg32 &= ~ROOT_PORT_INTR_ON_MESG_MASK; + pci_write_config_dword(dev, pos + PCI_ERR_ROOT_COMMAND, reg32); + +- rc = pci_reset_bridge_secondary_bus(dev); ++ rc = pci_bus_error_reset(dev); + pci_printk(KERN_DEBUG, dev, "Root Port link has been reset\n"); + + /* Clear Root Error Status */ +--- a/drivers/pci/pcie/err.c ++++ b/drivers/pci/pcie/err.c +@@ -177,7 +177,7 @@ static pci_ers_result_t default_reset_li + { + int rc; + +- rc = pci_reset_bridge_secondary_bus(dev); ++ rc = pci_bus_error_reset(dev); + pci_printk(KERN_DEBUG, dev, "downstream link has been reset\n"); + return rc ? PCI_ERS_RESULT_DISCONNECT : PCI_ERS_RESULT_RECOVERED; + } +--- a/drivers/pci/slot.c ++++ b/drivers/pci/slot.c +@@ -14,7 +14,6 @@ + + struct kset *pci_slots_kset; + EXPORT_SYMBOL_GPL(pci_slots_kset); +-static DEFINE_MUTEX(pci_slot_mutex); + + static ssize_t pci_slot_attr_show(struct kobject *kobj, + struct attribute *attr, char *buf) diff --git a/patches.suse/PCI-Handle-error-return-from-pci_reset_bridge_second.patch b/patches.suse/PCI-Handle-error-return-from-pci_reset_bridge_second.patch index defba69..0068af7 100644 --- a/patches.suse/PCI-Handle-error-return-from-pci_reset_bridge_second.patch +++ b/patches.suse/PCI-Handle-error-return-from-pci_reset_bridge_second.patch @@ -19,8 +19,9 @@ Acked-by: Thomas Bogendoerfer --- drivers/pci/hotplug/pciehp_hpc.c | 5 +++-- drivers/pci/pci.c | 12 ++++++------ + drivers/pci/pcie/aer/aerdrv.c | 5 +++-- drivers/pci/pcie/err.c | 6 ++++-- - 3 files changed, 13 insertions(+), 10 deletions(-) + 4 files changed, 16 insertions(+), 12 deletions(-) --- a/drivers/pci/hotplug/pciehp_hpc.c +++ b/drivers/pci/hotplug/pciehp_hpc.c @@ -52,7 +53,7 @@ Acked-by: Thomas Bogendoerfer int pcie_init_notification(struct controller *ctrl) --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c -@@ -4256,9 +4256,7 @@ static int pci_parent_bus_reset(struct p +@@ -4257,9 +4257,7 @@ static int pci_parent_bus_reset(struct p if (probe) return 0; @@ -63,7 +64,7 @@ Acked-by: Thomas Bogendoerfer } static int pci_reset_hotplug_slot(struct hotplug_slot *hotplug, int probe) -@@ -4903,6 +4901,8 @@ EXPORT_SYMBOL_GPL(pci_try_reset_slot); +@@ -4904,6 +4902,8 @@ EXPORT_SYMBOL_GPL(pci_try_reset_slot); static int pci_bus_reset(struct pci_bus *bus, int probe) { @@ -72,7 +73,7 @@ Acked-by: Thomas Bogendoerfer if (!bus->self || !pci_bus_resetable(bus)) return -ENOTTY; -@@ -4913,11 +4913,11 @@ static int pci_bus_reset(struct pci_bus +@@ -4914,11 +4914,11 @@ static int pci_bus_reset(struct pci_bus might_sleep(); @@ -86,7 +87,7 @@ Acked-by: Thomas Bogendoerfer } /** -@@ -4977,7 +4977,7 @@ int pci_try_reset_bus(struct pci_bus *bu +@@ -4978,7 +4978,7 @@ int pci_try_reset_bus(struct pci_bus *bu if (pci_bus_trylock(bus)) { might_sleep(); @@ -111,3 +112,31 @@ Acked-by: Thomas Bogendoerfer } static pci_ers_result_t reset_link(struct pci_dev *dev, u32 service) +--- a/drivers/pci/pcie/aer/aerdrv.c ++++ b/drivers/pci/pcie/aer/aerdrv.c +@@ -316,6 +316,7 @@ static pci_ers_result_t aer_root_reset(s + { + u32 reg32; + int pos; ++ int rc; + + pos = dev->aer_cap; + +@@ -324,7 +325,7 @@ static pci_ers_result_t aer_root_reset(s + reg32 &= ~ROOT_PORT_INTR_ON_MESG_MASK; + pci_write_config_dword(dev, pos + PCI_ERR_ROOT_COMMAND, reg32); + +- pci_reset_bridge_secondary_bus(dev); ++ rc = pci_reset_bridge_secondary_bus(dev); + pci_printk(KERN_DEBUG, dev, "Root Port link has been reset\n"); + + /* Clear Root Error Status */ +@@ -336,7 +337,7 @@ static pci_ers_result_t aer_root_reset(s + reg32 |= ROOT_PORT_INTR_ON_MESG_MASK; + pci_write_config_dword(dev, pos + PCI_ERR_ROOT_COMMAND, reg32); + +- return PCI_ERS_RESULT_RECOVERED; ++ return rc ? PCI_ERS_RESULT_DISCONNECT : PCI_ERS_RESULT_RECOVERED; + } + + /** diff --git a/patches.suse/PCI-Simplify-disconnected-marking.patch b/patches.suse/PCI-Simplify-disconnected-marking.patch new file mode 100644 index 0000000..7e1cd32 --- /dev/null +++ b/patches.suse/PCI-Simplify-disconnected-marking.patch @@ -0,0 +1,82 @@ +From a50ac6bfd6042b16e0de4ac3264c407e678c9b10 Mon Sep 17 00:00:00 2001 +From: Lukas Wunner +Date: Sun, 19 Aug 2018 16:29:00 +0200 +Subject: [PATCH] PCI: Simplify disconnected marking +Git-commit: a50ac6bfd6042b16e0de4ac3264c407e678c9b10 +Patch-mainline: v4.20-rc1 +References: bsc#1161561 + +Commit 89ee9f768003 ("PCI: Add device disconnected state") iterates over +the devices on a parent bus, marks each as disconnected, then marks +each device's children as disconnected using pci_walk_bus(). + +The same can be achieved more succinctly by calling pci_walk_bus() on +the parent bus. Moreover, this does not need to wait until acquiring +pci_lock_rescan_remove(), so move it out of that critical section. + +The critical section in err.c contains a pci_dev_get() / pci_dev_put() +pair which was apparently copy-pasted from pciehp_pci.c. In the latter +it serves the purpose of holding the struct pci_dev in place until the +Command register is updated. err.c doesn't do anything like that, hence +the pair is unnecessary. Remove it. + +Signed-off-by: Lukas Wunner +Signed-off-by: Bjorn Helgaas +Cc: Keith Busch +Cc: Oza Pawandeep +Cc: Sinan Kaya +Cc: Benjamin Herrenschmidt +Acked-by: Takashi Iwai + +--- + drivers/pci/hotplug/pciehp_pci.c | 9 +++------ + drivers/pci/pcie/err.c | 8 ++------ + 2 files changed, 5 insertions(+), 12 deletions(-) + +--- a/drivers/pci/hotplug/pciehp_pci.c ++++ b/drivers/pci/hotplug/pciehp_pci.c +@@ -89,6 +89,9 @@ int pciehp_unconfigure_device(struct slo + __func__, pci_domain_nr(parent), parent->number); + pciehp_get_adapter_status(p_slot, &presence); + ++ if (!presence) ++ pci_walk_bus(parent, pci_dev_set_disconnected, NULL); ++ + pci_lock_rescan_remove(); + + /* +@@ -100,12 +103,6 @@ int pciehp_unconfigure_device(struct slo + list_for_each_entry_safe_reverse(dev, temp, &parent->devices, + bus_list) { + pci_dev_get(dev); +- if (!presence) { +- pci_dev_set_disconnected(dev, NULL); +- if (pci_has_subordinate(dev)) +- pci_walk_bus(dev->subordinate, +- pci_dev_set_disconnected, NULL); +- } + pci_stop_and_remove_bus_device(dev); + /* + * Ensure that no new Requests will be generated from +--- a/drivers/pci/pcie/err.c ++++ b/drivers/pci/pcie/err.c +@@ -296,17 +296,13 @@ void pcie_do_fatal_recovery(struct pci_d + udev = dev->bus->self; + + parent = udev->subordinate; ++ pci_walk_bus(parent, pci_dev_set_disconnected, NULL); ++ + pci_lock_rescan_remove(); + pci_dev_get(dev); + list_for_each_entry_safe_reverse(pdev, temp, &parent->devices, + bus_list) { +- pci_dev_get(pdev); +- pci_dev_set_disconnected(pdev, NULL); +- if (pci_has_subordinate(pdev)) +- pci_walk_bus(pdev->subordinate, +- pci_dev_set_disconnected, NULL); + pci_stop_and_remove_bus_device(pdev); +- pci_dev_put(pdev); + } + + result = reset_link(udev, service); diff --git a/patches.suse/PCI-Unify-device-inaccessible.patch b/patches.suse/PCI-Unify-device-inaccessible.patch new file mode 100644 index 0000000..8d6f313 --- /dev/null +++ b/patches.suse/PCI-Unify-device-inaccessible.patch @@ -0,0 +1,127 @@ +From a6bd101b8f84f9b98768e9ab1e418c239e2e669f Mon Sep 17 00:00:00 2001 +From: Keith Busch +Date: Thu, 20 Sep 2018 10:27:16 -0600 +Subject: [PATCH] PCI: Unify device inaccessible +Git-commit: a6bd101b8f84f9b98768e9ab1e418c239e2e669f +Patch-mainline: v4.20-rc1 +References: bsc#1161561 + +Bring surprise removals and permanent failures together so we no longer +need separate flags. The implementation enforces that error handling will +not be able to override a surprise removal's permanent channel failure. + +Signed-off-by: Keith Busch +Signed-off-by: Bjorn Helgaas +Reviewed-by: Sinan Kaya +Acked-by: Takashi Iwai + +--- + drivers/pci/pci.h | 60 ++++++++++++++++++++++++++++++++++++++++++++----- + drivers/pci/pcie/err.c | 10 +++----- + 2 files changed, 59 insertions(+), 11 deletions(-) + +--- a/drivers/pci/pci.h ++++ b/drivers/pci/pci.h +@@ -297,21 +297,71 @@ struct pci_sriov { + bool drivers_autoprobe; /* auto probing of VFs by driver */ + }; + +-/* pci_dev priv_flags */ +-#define PCI_DEV_DISCONNECTED 0 +-#define PCI_DEV_ADDED 1 ++/** ++ * pci_dev_set_io_state - Set the new error state if possible. ++ * ++ * @dev - pci device to set new error_state ++ * @new - the state we want dev to be in ++ * ++ * Must be called with device_lock held. ++ * ++ * Returns true if state has been changed to the requested state. ++ */ ++static inline bool pci_dev_set_io_state(struct pci_dev *dev, ++ pci_channel_state_t new) ++{ ++ bool changed = false; ++ ++ device_lock_assert(&dev->dev); ++ switch (new) { ++ case pci_channel_io_perm_failure: ++ switch (dev->error_state) { ++ case pci_channel_io_frozen: ++ case pci_channel_io_normal: ++ case pci_channel_io_perm_failure: ++ changed = true; ++ break; ++ } ++ break; ++ case pci_channel_io_frozen: ++ switch (dev->error_state) { ++ case pci_channel_io_frozen: ++ case pci_channel_io_normal: ++ changed = true; ++ break; ++ } ++ break; ++ case pci_channel_io_normal: ++ switch (dev->error_state) { ++ case pci_channel_io_frozen: ++ case pci_channel_io_normal: ++ changed = true; ++ break; ++ } ++ break; ++ } ++ if (changed) ++ dev->error_state = new; ++ return changed; ++} + + static inline int pci_dev_set_disconnected(struct pci_dev *dev, void *unused) + { +- set_bit(PCI_DEV_DISCONNECTED, &dev->priv_flags); ++ device_lock(&dev->dev); ++ pci_dev_set_io_state(dev, pci_channel_io_perm_failure); ++ device_unlock(&dev->dev); ++ + return 0; + } + + static inline bool pci_dev_is_disconnected(const struct pci_dev *dev) + { +- return test_bit(PCI_DEV_DISCONNECTED, &dev->priv_flags); ++ return dev->error_state == pci_channel_io_perm_failure; + } + ++/* pci_dev priv_flags */ ++#define PCI_DEV_ADDED 0 ++ + static inline void pci_dev_assign_added(struct pci_dev *dev, bool added) + { + assign_bit(PCI_DEV_ADDED, &dev->priv_flags, added); +--- a/drivers/pci/pcie/err.c ++++ b/drivers/pci/pcie/err.c +@@ -52,9 +52,8 @@ static int report_error_detected(struct + const struct pci_error_handlers *err_handler; + + device_lock(&dev->dev); +- dev->error_state = state; +- +- if (!dev->driver || ++ if (!pci_dev_set_io_state(dev, state) || ++ !dev->driver || + !dev->driver->err_handler || + !dev->driver->err_handler->error_detected) { + /* +@@ -130,9 +129,8 @@ static int report_resume(struct pci_dev + const struct pci_error_handlers *err_handler; + + device_lock(&dev->dev); +- dev->error_state = pci_channel_io_normal; +- +- if (!dev->driver || ++ if (!pci_dev_set_io_state(dev, pci_channel_io_normal) || ++ !dev->driver || + !dev->driver->err_handler || + !dev->driver->err_handler->resume) + goto out; diff --git a/patches.suse/PCI-endpoint-Fix-clearing-start-entry-in-configfs.patch b/patches.suse/PCI-endpoint-Fix-clearing-start-entry-in-configfs.patch new file mode 100644 index 0000000..8f84766 --- /dev/null +++ b/patches.suse/PCI-endpoint-Fix-clearing-start-entry-in-configfs.patch @@ -0,0 +1,45 @@ +From f58d5f53c89479c12ad719c1960176442add5aaa Mon Sep 17 00:00:00 2001 +From: Kunihiko Hayashi +Date: Wed, 26 Feb 2020 14:52:23 +0900 +Subject: [PATCH] PCI: endpoint: Fix clearing start entry in configfs +Git-commit: f58d5f53c89479c12ad719c1960176442add5aaa +Patch-mainline: v5.7-rc1 +References: bsc#1051510 + +After an endpoint is started through configfs, if 0 is written to the +configfs entry 'start', the controller stops but the epc_group->start +value remains 1. + +A subsequent unlinking of the function from the controller would trigger +a spurious WARN_ON_ONCE() in pci_epc_epf_unlink() despite right +behavior. + +Fix it by setting epc_group->start = 0 when a controller is stopped +using configfs. + +Fixes: d74679911610 ("PCI: endpoint: Introduce configfs entry for configuring EP functions") +Signed-off-by: Kunihiko Hayashi +Signed-off-by: Lorenzo Pieralisi +Acked-by: Kishon Vijay Abraham I +Cc: Kishon Vijay Abraham I +Acked-by: Takashi Iwai + +--- + drivers/pci/endpoint/pci-ep-cfs.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/pci/endpoint/pci-ep-cfs.c b/drivers/pci/endpoint/pci-ep-cfs.c +index e7e8367eead1..55edce50be96 100644 +--- a/drivers/pci/endpoint/pci-ep-cfs.c ++++ b/drivers/pci/endpoint/pci-ep-cfs.c +@@ -57,6 +57,7 @@ static ssize_t pci_epc_start_store(struct config_item *item, const char *page, + + if (!start) { + pci_epc_stop(epc); ++ epc_group->start = 0; + return len; + } + +-- +2.16.4 + diff --git a/patches.suse/PCI-portdrv-Initialize-service-drivers-directly.patch b/patches.suse/PCI-portdrv-Initialize-service-drivers-directly.patch new file mode 100644 index 0000000..c6346a9 --- /dev/null +++ b/patches.suse/PCI-portdrv-Initialize-service-drivers-directly.patch @@ -0,0 +1,145 @@ +From c29de84149aba5f74e87b6491c13ac7203c12f55 Mon Sep 17 00:00:00 2001 +From: Keith Busch +Date: Thu, 20 Sep 2018 10:27:06 -0600 +Subject: [PATCH] PCI: portdrv: Initialize service drivers directly +Git-commit: c29de84149aba5f74e87b6491c13ac7203c12f55 +Patch-mainline: v4.20-rc1 +References: bsc#1161561 + +The PCI port driver saves the PCI state after initializing the device with +the applicable service devices. This was, however, before the service +drivers were even registered because PCI probe happens before the +device_initcall initialized those service drivers. The config space state +that the services set up were not being saved. The end result would cause +PCI devices to not react to events that the drivers think they did if the +PCI state ever needed to be restored. + +Fix this by changing the service drivers from using the init calls to +having the portdrv driver calling the services directly. This will get the +state saved as desired, while making the relationship between the port +driver and the services under it more explicit in the code. + +Signed-off-by: Keith Busch +Signed-off-by: Bjorn Helgaas +Reviewed-by: Sinan Kaya +Acked-by: Takashi Iwai + +--- + drivers/pci/hotplug/pciehp_core.c | 3 +-- + drivers/pci/pcie/aer/aerdrv.c | 3 +-- + drivers/pci/pcie/dpc.c | 3 +-- + drivers/pci/pcie/pme.c | 3 +-- + drivers/pci/pcie/portdrv.h | 24 ++++++++++++++++++++++++ + drivers/pci/pcie/portdrv_pci.c | 9 +++++++++ + 6 files changed, 37 insertions(+), 8 deletions(-) + +--- a/drivers/pci/hotplug/pciehp_core.c ++++ b/drivers/pci/hotplug/pciehp_core.c +@@ -322,7 +322,7 @@ static struct pcie_port_service_driver h + #endif /* PM */ + }; + +-static int __init pcied_init(void) ++int __init pcie_hp_init(void) + { + int retval = 0; + +@@ -333,4 +333,3 @@ static int __init pcied_init(void) + + return retval; + } +-device_initcall(pcied_init); +--- a/drivers/pci/pcie/aer/aerdrv.c ++++ b/drivers/pci/pcie/aer/aerdrv.c +@@ -357,10 +357,9 @@ static void aer_error_resume(struct pci_ + * + * Invoked when AER root service driver is loaded. + */ +-static int __init aer_service_init(void) ++int __init pcie_aer_init(void) + { + if (!pci_aer_available() || aer_acpi_firmware_first()) + return -ENXIO; + return pcie_port_service_register(&aerdriver); + } +-device_initcall(aer_service_init); +--- a/drivers/pci/pcie/dpc.c ++++ b/drivers/pci/pcie/dpc.c +@@ -285,8 +285,7 @@ static struct pcie_port_service_driver d + .reset_link = dpc_reset_link, + }; + +-static int __init dpc_service_init(void) ++int __init pcie_dpc_init(void) + { + return pcie_port_service_register(&dpcdriver); + } +-device_initcall(dpc_service_init); +--- a/drivers/pci/pcie/pme.c ++++ b/drivers/pci/pcie/pme.c +@@ -449,8 +449,7 @@ static struct pcie_port_service_driver p + /** + * pcie_pme_service_init - Register the PCIe PME service driver. + */ +-static int __init pcie_pme_service_init(void) ++int __init pcie_pme_init(void) + { + return pcie_port_service_register(&pcie_pme_driver); + } +-device_initcall(pcie_pme_service_init); +--- a/drivers/pci/pcie/portdrv.h ++++ b/drivers/pci/pcie/portdrv.h +@@ -27,6 +27,30 @@ extern bool pcie_ports_native; + + #define PCIE_PORT_DEVICE_MAXSERVICES 5 + ++#ifdef CONFIG_PCIEAER ++int pcie_aer_init(void); ++#else ++static inline int pcie_aer_init(void) { return 0; } ++#endif ++ ++#ifdef CONFIG_HOTPLUG_PCI_PCIE ++int pcie_hp_init(void); ++#else ++static inline int pcie_hp_init(void) { return 0; } ++#endif ++ ++#ifdef CONFIG_PCIE_PME ++int pcie_pme_init(void); ++#else ++static inline int pcie_pme_init(void) { return 0; } ++#endif ++ ++#ifdef CONFIG_PCIE_DPC ++int pcie_dpc_init(void); ++#else ++static inline int pcie_dpc_init(void) { return 0; } ++#endif ++ + /* Port Type */ + #define PCIE_ANY_PORT (~0) + +--- a/drivers/pci/pcie/portdrv_pci.c ++++ b/drivers/pci/pcie/portdrv_pci.c +@@ -228,11 +228,20 @@ static struct dmi_system_id __initdata p + {} + }; + ++static void __init pcie_init_services(void) ++{ ++ pcie_aer_init(); ++ pcie_pme_init(); ++ pcie_dpc_init(); ++ pcie_hp_init(); ++} ++ + static int __init pcie_portdrv_init(void) + { + if (pcie_ports_disabled) + return -EACCES; + ++ pcie_init_services(); + dmi_check_system(pcie_portdrv_dmi_table); + + return pci_register_driver(&pcie_portdriver); diff --git a/patches.suse/PCI-portdrv-Remove-pcie_port_bus_type-link-order-dep.patch b/patches.suse/PCI-portdrv-Remove-pcie_port_bus_type-link-order-dep.patch new file mode 100644 index 0000000..ae90bab --- /dev/null +++ b/patches.suse/PCI-portdrv-Remove-pcie_port_bus_type-link-order-dep.patch @@ -0,0 +1,193 @@ +From c6c889d932bb49d95273711a790d16f814cb213b Mon Sep 17 00:00:00 2001 +From: Bjorn Helgaas +Date: Fri, 9 Mar 2018 11:06:56 -0600 +Subject: [PATCH] PCI/portdrv: Remove pcie_port_bus_type link order dependency +Git-commit: c6c889d932bb49d95273711a790d16f814cb213b +Patch-mainline: v4.17-rc1 +References: bsc#1161561 + +The pcie_port_bus_type must be registered before drivers that depend on it +can be registered. Those drivers include: + + pcied_init() # PCIe native hotplug driver + aer_service_init() # AER driver + dpc_service_init() # DPC driver + pcie_pme_service_init() # PME driver + +Previously we registered pcie_port_bus_type from pcie_portdrv_init(), a +device_initcall. The callers of pcie_port_service_register() (above) are +also device_initcalls. This is fragile because the device_initcall +ordering depends on link order, which is not explicit. + +Register pcie_port_bus_type from pci_driver_init() along with pci_bus_type. +This removes the link order dependency between portdrv and the pciehp, AER, +DPC, and PCIe PME drivers. + +Signed-off-by: Bjorn Helgaas +Reviewed-by: Rafael J. Wysocki +Reviewed-by: Christoph Hellwig +Acked-by: Takashi Iwai + +--- + drivers/pci/pci-driver.c | 44 ++++++++++++++++++++++++++++++++- + drivers/pci/pcie/Makefile | 2 - + drivers/pci/pcie/portdrv_bus.c | 54 ----------------------------------------- + drivers/pci/pcie/portdrv_pci.c | 13 --------- + 4 files changed, 45 insertions(+), 68 deletions(-) + delete mode 100644 drivers/pci/pcie/portdrv_bus.c + +--- a/drivers/pci/pci-driver.c ++++ b/drivers/pci/pci-driver.c +@@ -21,6 +21,7 @@ + #include + #include + #include "pci.h" ++#include "pcie/portdrv.h" + + struct pci_dynid { + struct list_head node; +@@ -1558,8 +1559,49 @@ struct bus_type pci_bus_type = { + }; + EXPORT_SYMBOL(pci_bus_type); + ++#ifdef CONFIG_PCIEPORTBUS ++static int pcie_port_bus_match(struct device *dev, struct device_driver *drv) ++{ ++ struct pcie_device *pciedev; ++ struct pcie_port_service_driver *driver; ++ ++ if (drv->bus != &pcie_port_bus_type || dev->bus != &pcie_port_bus_type) ++ return 0; ++ ++ pciedev = to_pcie_device(dev); ++ driver = to_service_driver(drv); ++ ++ if (driver->service != pciedev->service) ++ return 0; ++ ++ if (driver->port_type != PCIE_ANY_PORT && ++ driver->port_type != pci_pcie_type(pciedev->port)) ++ return 0; ++ ++ return 1; ++} ++ ++struct bus_type pcie_port_bus_type = { ++ .name = "pci_express", ++ .match = pcie_port_bus_match, ++}; ++EXPORT_SYMBOL_GPL(pcie_port_bus_type); ++#endif ++ + static int __init pci_driver_init(void) + { +- return bus_register(&pci_bus_type); ++ int ret; ++ ++ ret = bus_register(&pci_bus_type); ++ if (ret) ++ return ret; ++ ++#ifdef CONFIG_PCIEPORTBUS ++ ret = bus_register(&pcie_port_bus_type); ++ if (ret) ++ return ret; ++#endif ++ ++ return 0; + } + postcore_initcall(pci_driver_init); +--- a/drivers/pci/pcie/Makefile ++++ b/drivers/pci/pcie/Makefile +@@ -5,7 +5,7 @@ + # Build PCI Express ASPM if needed + obj-$(CONFIG_PCIEASPM) += aspm.o + +-pcieportdrv-y := portdrv_core.o portdrv_pci.o portdrv_bus.o ++pcieportdrv-y := portdrv_core.o portdrv_pci.o + pcieportdrv-$(CONFIG_ACPI) += portdrv_acpi.o + + obj-$(CONFIG_PCIEPORTBUS) += pcieportdrv.o +--- a/drivers/pci/pcie/portdrv_pci.c ++++ b/drivers/pci/pcie/portdrv_pci.c +@@ -256,22 +256,11 @@ static struct dmi_system_id __initdata p + + static int __init pcie_portdrv_init(void) + { +- int retval; +- + if (pcie_ports_disabled) + return -EACCES; + + dmi_check_system(pcie_portdrv_dmi_table); + +- retval = pcie_port_bus_register(); +- if (retval) { +- printk(KERN_WARNING "PCIE: bus_register error: %d\n", retval); +- goto out; +- } +- retval = pci_register_driver(&pcie_portdriver); +- if (retval) +- pcie_port_bus_unregister(); +- out: +- return retval; ++ return pci_register_driver(&pcie_portdriver); + } + device_initcall(pcie_portdrv_init); +--- a/drivers/pci/pcie/portdrv_bus.c ++++ /dev/null +@@ -1,54 +0,0 @@ +-/* +- * File: portdrv_bus.c +- * Purpose: PCI Express Port Bus Driver's Bus Overloading Functions +- * +- * Copyright (C) 2004 Intel +- * Copyright (C) Tom Long Nguyen (tom.l.nguyen@intel.com) +- */ +- +-#include +-#include +-#include +-#include +-#include +- +-#include "portdrv.h" +- +-static int pcie_port_bus_match(struct device *dev, struct device_driver *drv); +- +-struct bus_type pcie_port_bus_type = { +- .name = "pci_express", +- .match = pcie_port_bus_match, +-}; +-EXPORT_SYMBOL_GPL(pcie_port_bus_type); +- +-static int pcie_port_bus_match(struct device *dev, struct device_driver *drv) +-{ +- struct pcie_device *pciedev; +- struct pcie_port_service_driver *driver; +- +- if (drv->bus != &pcie_port_bus_type || dev->bus != &pcie_port_bus_type) +- return 0; +- +- pciedev = to_pcie_device(dev); +- driver = to_service_driver(drv); +- +- if (driver->service != pciedev->service) +- return 0; +- +- if ((driver->port_type != PCIE_ANY_PORT) && +- (driver->port_type != pci_pcie_type(pciedev->port))) +- return 0; +- +- return 1; +-} +- +-int pcie_port_bus_register(void) +-{ +- return bus_register(&pcie_port_bus_type); +-} +- +-void pcie_port_bus_unregister(void) +-{ +- bus_unregister(&pcie_port_bus_type); +-} diff --git a/patches.suse/PCI-switchtec-Fix-init_completion-race-condition-wit.patch b/patches.suse/PCI-switchtec-Fix-init_completion-race-condition-wit.patch new file mode 100644 index 0000000..2733a3b --- /dev/null +++ b/patches.suse/PCI-switchtec-Fix-init_completion-race-condition-wit.patch @@ -0,0 +1,52 @@ +From efbdc769601f4d50018bf7ca50fc9f7c67392ece Mon Sep 17 00:00:00 2001 +From: Logan Gunthorpe +Date: Sat, 21 Mar 2020 12:25:45 +0100 +Subject: [PATCH] PCI/switchtec: Fix init_completion race condition with poll_wait() +Git-commit: efbdc769601f4d50018bf7ca50fc9f7c67392ece +Patch-mainline: v5.7-rc1 +References: bsc#1051510 + +The call to init_completion() in mrpc_queue_cmd() can theoretically +race with the call to poll_wait() in switchtec_dev_poll(). + + poll() write() + switchtec_dev_poll() switchtec_dev_write() + poll_wait(&s->comp.wait); mrpc_queue_cmd() + init_completion(&s->comp) + init_waitqueue_head(&s->comp.wait) + +To my knowledge, no one has hit this bug. + +Fix this by using reinit_completion() instead of init_completion() in +mrpc_queue_cmd(). + +Fixes: 080b47def5e5 ("MicroSemi Switchtec management interface driver") + +Reported-by: Sebastian Andrzej Siewior +Signed-off-by: Logan Gunthorpe +Signed-off-by: Thomas Gleixner +Signed-off-by: Peter Zijlstra (Intel) +Acked-by: Bjorn Helgaas +Link: https://lkml.kernel.org/r/20200313183608.2646-1-logang@deltatee.com +Acked-by: Takashi Iwai + +--- + drivers/pci/switch/switchtec.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/pci/switch/switchtec.c b/drivers/pci/switch/switchtec.c +index a823b4b8ef8a..81dc7ac01381 100644 +--- a/drivers/pci/switch/switchtec.c ++++ b/drivers/pci/switch/switchtec.c +@@ -175,7 +175,7 @@ static int mrpc_queue_cmd(struct switchtec_user *stuser) + kref_get(&stuser->kref); + stuser->read_len = sizeof(stuser->data); + stuser_set_state(stuser, MRPC_QUEUED); +- init_completion(&stuser->comp); ++ reinit_completion(&stuser->comp); + list_add_tail(&stuser->list, &stdev->mrpc_queue); + + mrpc_cmd_submit(stdev); +-- +2.16.4 + diff --git a/patches.suse/RDMA-cma-Fix-unbalanced-cm_id-reference-count-during.patch b/patches.suse/RDMA-cma-Fix-unbalanced-cm_id-reference-count-during.patch new file mode 100644 index 0000000..ada8d89 --- /dev/null +++ b/patches.suse/RDMA-cma-Fix-unbalanced-cm_id-reference-count-during.patch @@ -0,0 +1,52 @@ +From: Parav Pandit +Date: Sun, 26 Jan 2020 16:26:46 +0200 +Subject: RDMA/cma: Fix unbalanced cm_id reference count during address resolve +Patch-mainline: v5.6-rc1 +Git-commit: b4fb4cc5ba83b20dae13cef116c33648e81d2f44 +References: bsc#1103992 FATE#326009 + +Below commit missed the AF_IB and loopback code flow in +rdma_resolve_addr(). This leads to an unbalanced cm_id refcount in +cma_work_handler() which puts the refcount which was not incremented prior +to queuing the work. + +A call trace is observed with such code flow: + + BUG: unable to handle kernel NULL pointer dereference at (null) + [] __mutex_lock_slowpath+0x166/0x1d0 + [] mutex_lock+0x1f/0x2f + [] cma_work_handler+0x25/0xa0 + [] process_one_work+0x17f/0x440 + [] worker_thread+0x126/0x3c0 + +Hence, hold the cm_id reference when scheduling the resolve work item. + +Fixes: 722c7b2bfead ("RDMA/{cma, core}: Avoid callback on rdma_addr_cancel()") +Link: https://lore.kernel.org/r/20200126142652.104803-2-leon@kernel.org +Signed-off-by: Parav Pandit +Signed-off-by: Leon Romanovsky +Reviewed-by: Jason Gunthorpe +Signed-off-by: Jason Gunthorpe +Acked-by: Thomas Bogendoerfer +--- + drivers/infiniband/core/cma.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/drivers/infiniband/core/cma.c ++++ b/drivers/infiniband/core/cma.c +@@ -3018,6 +3018,7 @@ static int cma_resolve_loopback(struct r + rdma_addr_get_sgid(&id_priv->id.route.addr.dev_addr, &gid); + rdma_addr_set_dgid(&id_priv->id.route.addr.dev_addr, &gid); + ++ atomic_inc(&id_priv->refcount); + cma_init_resolve_addr_work(work, id_priv); + queue_work(cma_wq, &work->work); + return 0; +@@ -3044,6 +3045,7 @@ static int cma_resolve_ib_addr(struct rd + rdma_addr_set_dgid(&id_priv->id.route.addr.dev_addr, (union ib_gid *) + &(((struct sockaddr_ib *) &id_priv->id.route.addr.dst_addr)->sib_addr)); + ++ atomic_inc(&id_priv->refcount); + cma_init_resolve_addr_work(work, id_priv); + queue_work(cma_wq, &work->work); + return 0; diff --git a/patches.suse/RDMA-hfi1-Fix-memory-leak-in-_dev_comp_vect_mappings.patch b/patches.suse/RDMA-hfi1-Fix-memory-leak-in-_dev_comp_vect_mappings.patch new file mode 100644 index 0000000..e0eb3ae --- /dev/null +++ b/patches.suse/RDMA-hfi1-Fix-memory-leak-in-_dev_comp_vect_mappings.patch @@ -0,0 +1,48 @@ +From: Kamal Heib +Date: Wed, 5 Feb 2020 13:05:30 +0200 +Subject: RDMA/hfi1: Fix memory leak in _dev_comp_vect_mappings_create +Patch-mainline: v5.6-rc2 +Git-commit: 8a4f300b978edbbaa73ef9eca660e45eb9f13873 +References: bsc#1114685 FATE#325854 + +Make sure to free the allocated cpumask_var_t's to avoid the following +reported memory leak by kmemleak: + +$ cat /sys/kernel/debug/kmemleak +unreferenced object 0xffff8897f812d6a8 (size 8): + comm "kworker/1:1", pid 347, jiffies 4294751400 (age 101.703s) + hex dump (first 8 bytes): + 00 00 00 00 00 00 00 00 ........ + backtrace: + [<00000000bff49664>] alloc_cpumask_var_node+0x4c/0xb0 + [<0000000075d3ca81>] hfi1_comp_vectors_set_up+0x20f/0x800 [hfi1] + [<0000000098d420df>] hfi1_init_dd+0x3311/0x4960 [hfi1] + [<0000000071be7e52>] init_one+0x25e/0xf10 [hfi1] + [<000000005483d4c2>] local_pci_probe+0xd4/0x180 + [<000000007c3cbc6e>] work_for_cpu_fn+0x51/0xa0 + [<000000001d626905>] process_one_work+0x8f0/0x17b0 + [<000000007e569e7e>] worker_thread+0x536/0xb50 + [<00000000fd39a4a5>] kthread+0x30c/0x3d0 + [<0000000056f2edb3>] ret_from_fork+0x3a/0x50 + +Fixes: 5d18ee67d4c1 ("IB/{hfi1, rdmavt, qib}: Implement CQ completion vector support") +Link: https://lore.kernel.org/r/20200205110530.12129-1-kamalheib1@gmail.com +Signed-off-by: Kamal Heib +Reviewed-by: Dennis Dalessandro +Signed-off-by: Jason Gunthorpe +Acked-by: Thomas Bogendoerfer +--- + drivers/infiniband/hw/hfi1/affinity.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/drivers/infiniband/hw/hfi1/affinity.c ++++ b/drivers/infiniband/hw/hfi1/affinity.c +@@ -478,6 +478,8 @@ static int _dev_comp_vect_mappings_creat + rvt_get_ibdev_name(&(dd)->verbs_dev.rdi), i, cpu); + } + ++ free_cpumask_var(available_cpus); ++ free_cpumask_var(non_intr_cpus); + return 0; + + fail: diff --git a/patches.suse/RDMA-uverbs-Verify-MR-access-flags.patch b/patches.suse/RDMA-uverbs-Verify-MR-access-flags.patch new file mode 100644 index 0000000..e8a45da --- /dev/null +++ b/patches.suse/RDMA-uverbs-Verify-MR-access-flags.patch @@ -0,0 +1,32 @@ +From: Michael Guralnik +Date: Wed, 8 Jan 2020 20:05:35 +0200 +Subject: RDMA/uverbs: Verify MR access flags +Patch-mainline: v5.6-rc1 +Git-commit: ca95c1411198c2d87217c19d44571052cdc94725 +References: bsc#1103992 FATE#326009 + +Verify that MR access flags that are passed from user are all supported +ones, otherwise an error is returned. + +Fixes: 4fca03778351 ("IB/uverbs: Move ib_access_flags and ib_read_counters_flags to uapi") +Link: https://lore.kernel.org/r/1578506740-22188-6-git-send-email-yishaih@mellanox.com +Signed-off-by: Michael Guralnik +Signed-off-by: Yishai Hadas +Signed-off-by: Jason Gunthorpe +Acked-by: Thomas Bogendoerfer +--- + include/rdma/ib_verbs.h | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/include/rdma/ib_verbs.h ++++ b/include/rdma/ib_verbs.h +@@ -3907,6 +3907,9 @@ static inline int ib_check_mr_access(int + !(flags & IB_ACCESS_LOCAL_WRITE)) + return -EINVAL; + ++ if (flags & ~IB_ACCESS_SUPPORTED) ++ return -EINVAL; ++ + return 0; + } + diff --git a/patches.suse/SMB3-Backup-intent-flag-missing-from-some-more-ops.patch b/patches.suse/SMB3-Backup-intent-flag-missing-from-some-more-ops.patch new file mode 100644 index 0000000..8c5b103 --- /dev/null +++ b/patches.suse/SMB3-Backup-intent-flag-missing-from-some-more-ops.patch @@ -0,0 +1,729 @@ +From: Amir Goldstein +Date: Mon, 3 Feb 2020 21:46:43 +0200 +Subject: [PATCH] SMB3: Backup intent flag missing from some more ops +Git-commit: 0f060936e490c6279dfe773d75d526d3d3d77111 +References: bsc#1144333 +Patch-mainline: v5.6-rc1 + +When "backup intent" is requested on the mount (e.g. backupuid or +backupgid mount options), the corresponding flag was missing from +some of the operations. + +Change all operations to use the macro cifs_create_options() to +set the backup intent flag if needed. + +Signed-off-by: Amir Goldstein +Signed-off-by: Steve French +Acked-by: Paulo Alcantara +--- + fs/cifs/cifsacl.c | 14 +++----- + fs/cifs/cifsfs.c | 2 +- + fs/cifs/cifsglob.h | 6 ++-- + fs/cifs/cifsproto.h | 8 +++++ + fs/cifs/connect.c | 2 +- + fs/cifs/dir.c | 5 +-- + fs/cifs/file.c | 10 ++---- + fs/cifs/inode.c | 8 ++--- + fs/cifs/ioctl.c | 2 +- + fs/cifs/link.c | 18 +++------- + fs/cifs/smb1ops.c | 19 +++++------ + fs/cifs/smb2inode.c | 9 ++--- + fs/cifs/smb2ops.c | 81 +++++++++++++++------------------------------ + fs/cifs/smb2proto.h | 2 +- + 14 files changed, 68 insertions(+), 118 deletions(-) + +diff --git a/fs/cifs/cifsacl.c b/fs/cifs/cifsacl.c +index fb41e51dd574..440828afcdde 100644 +--- a/fs/cifs/cifsacl.c ++++ b/fs/cifs/cifsacl.c +@@ -1084,7 +1084,7 @@ static struct cifs_ntsd *get_cifs_acl_by_path(struct cifs_sb_info *cifs_sb, + struct cifs_ntsd *pntsd = NULL; + int oplock = 0; + unsigned int xid; +- int rc, create_options = 0; ++ int rc; + struct cifs_tcon *tcon; + struct tcon_link *tlink = cifs_sb_tlink(cifs_sb); + struct cifs_fid fid; +@@ -1096,13 +1096,10 @@ static struct cifs_ntsd *get_cifs_acl_by_path(struct cifs_sb_info *cifs_sb, + tcon = tlink_tcon(tlink); + xid = get_xid(); + +- if (backup_cred(cifs_sb)) +- create_options |= CREATE_OPEN_BACKUP_INTENT; +- + oparms.tcon = tcon; + oparms.cifs_sb = cifs_sb; + oparms.desired_access = READ_CONTROL; +- oparms.create_options = create_options; ++ oparms.create_options = cifs_create_options(cifs_sb, 0); + oparms.disposition = FILE_OPEN; + oparms.path = path; + oparms.fid = &fid; +@@ -1147,7 +1144,7 @@ int set_cifs_acl(struct cifs_ntsd *pnntsd, __u32 acllen, + { + int oplock = 0; + unsigned int xid; +- int rc, access_flags, create_options = 0; ++ int rc, access_flags; + struct cifs_tcon *tcon; + struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); + struct tcon_link *tlink = cifs_sb_tlink(cifs_sb); +@@ -1160,9 +1157,6 @@ int set_cifs_acl(struct cifs_ntsd *pnntsd, __u32 acllen, + tcon = tlink_tcon(tlink); + xid = get_xid(); + +- if (backup_cred(cifs_sb)) +- create_options |= CREATE_OPEN_BACKUP_INTENT; +- + if (aclflag == CIFS_ACL_OWNER || aclflag == CIFS_ACL_GROUP) + access_flags = WRITE_OWNER; + else +@@ -1171,7 +1165,7 @@ int set_cifs_acl(struct cifs_ntsd *pnntsd, __u32 acllen, + oparms.tcon = tcon; + oparms.cifs_sb = cifs_sb; + oparms.desired_access = access_flags; +- oparms.create_options = create_options; ++ oparms.create_options = cifs_create_options(cifs_sb, 0); + oparms.disposition = FILE_OPEN; + oparms.path = path; + oparms.fid = &fid; +diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c +index 5492b9860baa..febab27cd838 100644 +--- a/fs/cifs/cifsfs.c ++++ b/fs/cifs/cifsfs.c +@@ -275,7 +275,7 @@ cifs_statfs(struct dentry *dentry, struct kstatfs *buf) + buf->f_ffree = 0; /* unlimited */ + + if (server->ops->queryfs) +- rc = server->ops->queryfs(xid, tcon, buf); ++ rc = server->ops->queryfs(xid, tcon, cifs_sb, buf); + + free_xid(xid); + return 0; +diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h +index 239338d57086..1205041fd966 100644 +--- a/fs/cifs/cifsglob.h ++++ b/fs/cifs/cifsglob.h +@@ -298,7 +298,8 @@ struct smb_version_operations { + const char *, struct dfs_info3_param **, + unsigned int *, const struct nls_table *, int); + /* informational QFS call */ +- void (*qfs_tcon)(const unsigned int, struct cifs_tcon *); ++ void (*qfs_tcon)(const unsigned int, struct cifs_tcon *, ++ struct cifs_sb_info *); + /* check if a path is accessible or not */ + int (*is_path_accessible)(const unsigned int, struct cifs_tcon *, + struct cifs_sb_info *, const char *); +@@ -409,7 +410,7 @@ struct smb_version_operations { + struct cifsInodeInfo *); + /* query remote filesystem */ + int (*queryfs)(const unsigned int, struct cifs_tcon *, +- struct kstatfs *); ++ struct cifs_sb_info *, struct kstatfs *); + /* send mandatory brlock to the server */ + int (*mand_lock)(const unsigned int, struct cifsFileInfo *, __u64, + __u64, __u32, int, int, bool); +@@ -490,6 +491,7 @@ struct smb_version_operations { + /* ioctl passthrough for query_info */ + int (*ioctl_query_info)(const unsigned int xid, + struct cifs_tcon *tcon, ++ struct cifs_sb_info *cifs_sb, + __le16 *path, int is_dir, + unsigned long p); + /* make unix special files (block, char, fifo, socket) */ +diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h +index 948bf3474db1..748bd00cb5f1 100644 +--- a/fs/cifs/cifsproto.h ++++ b/fs/cifs/cifsproto.h +@@ -612,4 +612,12 @@ static inline int get_dfs_path(const unsigned int xid, struct cifs_ses *ses, + } + #endif + ++static inline int cifs_create_options(struct cifs_sb_info *cifs_sb, int options) ++{ ++ if (backup_cred(cifs_sb)) ++ return options | CREATE_OPEN_BACKUP_INTENT; ++ else ++ return options; ++} ++ + #endif /* _CIFSPROTO_H */ +diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c +index 0aa3623ae0e1..a941ac7a659d 100644 +--- a/fs/cifs/connect.c ++++ b/fs/cifs/connect.c +@@ -4365,7 +4365,7 @@ static int mount_get_conns(struct smb_vol *vol, struct cifs_sb_info *cifs_sb, + + /* do not care if a following call succeed - informational */ + if (!tcon->pipe && server->ops->qfs_tcon) { +- server->ops->qfs_tcon(*xid, tcon); ++ server->ops->qfs_tcon(*xid, tcon, cifs_sb); + if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RO_CACHE) { + if (tcon->fsDevInfo.DeviceCharacteristics & + cpu_to_le32(FILE_READ_ONLY_DEVICE)) +diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c +index f3b79012ff29..0ef099442f20 100644 +--- a/fs/cifs/dir.c ++++ b/fs/cifs/dir.c +@@ -355,13 +355,10 @@ cifs_do_create(struct inode *inode, struct dentry *direntry, unsigned int xid, + if (!tcon->unix_ext && (mode & S_IWUGO) == 0) + create_options |= CREATE_OPTION_READONLY; + +- if (backup_cred(cifs_sb)) +- create_options |= CREATE_OPEN_BACKUP_INTENT; +- + oparms.tcon = tcon; + oparms.cifs_sb = cifs_sb; + oparms.desired_access = desired_access; +- oparms.create_options = create_options; ++ oparms.create_options = cifs_create_options(cifs_sb, create_options); + oparms.disposition = disposition; + oparms.path = full_path; + oparms.fid = fid; +diff --git a/fs/cifs/file.c b/fs/cifs/file.c +index a4e8f7d445ac..79e6f4f55b9b 100644 +--- a/fs/cifs/file.c ++++ b/fs/cifs/file.c +@@ -222,9 +222,6 @@ cifs_nt_open(char *full_path, struct inode *inode, struct cifs_sb_info *cifs_sb, + if (!buf) + return -ENOMEM; + +- if (backup_cred(cifs_sb)) +- create_options |= CREATE_OPEN_BACKUP_INTENT; +- + /* O_SYNC also has bit for O_DSYNC so following check picks up either */ + if (f_flags & O_SYNC) + create_options |= CREATE_WRITE_THROUGH; +@@ -235,7 +232,7 @@ cifs_nt_open(char *full_path, struct inode *inode, struct cifs_sb_info *cifs_sb, + oparms.tcon = tcon; + oparms.cifs_sb = cifs_sb; + oparms.desired_access = desired_access; +- oparms.create_options = create_options; ++ oparms.create_options = cifs_create_options(cifs_sb, create_options); + oparms.disposition = disposition; + oparms.path = full_path; + oparms.fid = fid; +@@ -752,9 +749,6 @@ cifs_reopen_file(struct cifsFileInfo *cfile, bool can_flush) + + desired_access = cifs_convert_flags(cfile->f_flags); + +- if (backup_cred(cifs_sb)) +- create_options |= CREATE_OPEN_BACKUP_INTENT; +- + /* O_SYNC also has bit for O_DSYNC so following check picks up either */ + if (cfile->f_flags & O_SYNC) + create_options |= CREATE_WRITE_THROUGH; +@@ -768,7 +762,7 @@ cifs_reopen_file(struct cifsFileInfo *cfile, bool can_flush) + oparms.tcon = tcon; + oparms.cifs_sb = cifs_sb; + oparms.desired_access = desired_access; +- oparms.create_options = create_options; ++ oparms.create_options = cifs_create_options(cifs_sb, create_options); + oparms.disposition = disposition; + oparms.path = full_path; + oparms.fid = &cfile->fid; +diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c +index 9b547f7f5f5d..b1383c524b98 100644 +--- a/fs/cifs/inode.c ++++ b/fs/cifs/inode.c +@@ -472,9 +472,7 @@ cifs_sfu_type(struct cifs_fattr *fattr, const char *path, + oparms.tcon = tcon; + oparms.cifs_sb = cifs_sb; + oparms.desired_access = GENERIC_READ; +- oparms.create_options = CREATE_NOT_DIR; +- if (backup_cred(cifs_sb)) +- oparms.create_options |= CREATE_OPEN_BACKUP_INTENT; ++ oparms.create_options = cifs_create_options(cifs_sb, CREATE_NOT_DIR); + oparms.disposition = FILE_OPEN; + oparms.path = path; + oparms.fid = &fid; +@@ -1284,7 +1282,7 @@ cifs_rename_pending_delete(const char *full_path, struct dentry *dentry, + oparms.tcon = tcon; + oparms.cifs_sb = cifs_sb; + oparms.desired_access = DELETE | FILE_WRITE_ATTRIBUTES; +- oparms.create_options = CREATE_NOT_DIR; ++ oparms.create_options = cifs_create_options(cifs_sb, CREATE_NOT_DIR); + oparms.disposition = FILE_OPEN; + oparms.path = full_path; + oparms.fid = &fid; +@@ -1822,7 +1820,7 @@ cifs_do_rename(const unsigned int xid, struct dentry *from_dentry, + oparms.cifs_sb = cifs_sb; + /* open the file to be renamed -- we need DELETE perms */ + oparms.desired_access = DELETE; +- oparms.create_options = CREATE_NOT_DIR; ++ oparms.create_options = cifs_create_options(cifs_sb, CREATE_NOT_DIR); + oparms.disposition = FILE_OPEN; + oparms.path = from_path; + oparms.fid = &fid; +diff --git a/fs/cifs/ioctl.c b/fs/cifs/ioctl.c +index 1a01e108d75e..e4c935026d5e 100644 +--- a/fs/cifs/ioctl.c ++++ b/fs/cifs/ioctl.c +@@ -65,7 +65,7 @@ static long cifs_ioctl_query_info(unsigned int xid, struct file *filep, + + if (tcon->ses->server->ops->ioctl_query_info) + rc = tcon->ses->server->ops->ioctl_query_info( +- xid, tcon, utf16_path, ++ xid, tcon, cifs_sb, utf16_path, + filep->private_data ? 0 : 1, p); + else + rc = -EOPNOTSUPP; +diff --git a/fs/cifs/link.c b/fs/cifs/link.c +index b736acd3917b..852aa00ec729 100644 +--- a/fs/cifs/link.c ++++ b/fs/cifs/link.c +@@ -315,7 +315,7 @@ cifs_query_mf_symlink(unsigned int xid, struct cifs_tcon *tcon, + oparms.tcon = tcon; + oparms.cifs_sb = cifs_sb; + oparms.desired_access = GENERIC_READ; +- oparms.create_options = CREATE_NOT_DIR; ++ oparms.create_options = cifs_create_options(cifs_sb, CREATE_NOT_DIR); + oparms.disposition = FILE_OPEN; + oparms.path = path; + oparms.fid = &fid; +@@ -353,15 +353,11 @@ cifs_create_mf_symlink(unsigned int xid, struct cifs_tcon *tcon, + struct cifs_fid fid; + struct cifs_open_parms oparms; + struct cifs_io_parms io_parms; +- int create_options = CREATE_NOT_DIR; +- +- if (backup_cred(cifs_sb)) +- create_options |= CREATE_OPEN_BACKUP_INTENT; + + oparms.tcon = tcon; + oparms.cifs_sb = cifs_sb; + oparms.desired_access = GENERIC_WRITE; +- oparms.create_options = create_options; ++ oparms.create_options = cifs_create_options(cifs_sb, CREATE_NOT_DIR); + oparms.disposition = FILE_CREATE; + oparms.path = path; + oparms.fid = &fid; +@@ -402,9 +398,7 @@ smb3_query_mf_symlink(unsigned int xid, struct cifs_tcon *tcon, + oparms.tcon = tcon; + oparms.cifs_sb = cifs_sb; + oparms.desired_access = GENERIC_READ; +- oparms.create_options = CREATE_NOT_DIR; +- if (backup_cred(cifs_sb)) +- oparms.create_options |= CREATE_OPEN_BACKUP_INTENT; ++ oparms.create_options = cifs_create_options(cifs_sb, CREATE_NOT_DIR); + oparms.disposition = FILE_OPEN; + oparms.fid = &fid; + oparms.reconnect = false; +@@ -457,14 +451,10 @@ smb3_create_mf_symlink(unsigned int xid, struct cifs_tcon *tcon, + struct cifs_fid fid; + struct cifs_open_parms oparms; + struct cifs_io_parms io_parms; +- int create_options = CREATE_NOT_DIR; + __le16 *utf16_path; + __u8 oplock = SMB2_OPLOCK_LEVEL_NONE; + struct kvec iov[2]; + +- if (backup_cred(cifs_sb)) +- create_options |= CREATE_OPEN_BACKUP_INTENT; +- + cifs_dbg(FYI, "%s: path: %s\n", __func__, path); + + utf16_path = cifs_convert_path_to_utf16(path, cifs_sb); +@@ -474,7 +464,7 @@ smb3_create_mf_symlink(unsigned int xid, struct cifs_tcon *tcon, + oparms.tcon = tcon; + oparms.cifs_sb = cifs_sb; + oparms.desired_access = GENERIC_WRITE; +- oparms.create_options = create_options; ++ oparms.create_options = cifs_create_options(cifs_sb, CREATE_NOT_DIR); + oparms.disposition = FILE_CREATE; + oparms.fid = &fid; + oparms.reconnect = false; +diff --git a/fs/cifs/smb1ops.c b/fs/cifs/smb1ops.c +index d70a2bb062df..eb994e313c6a 100644 +--- a/fs/cifs/smb1ops.c ++++ b/fs/cifs/smb1ops.c +@@ -504,7 +504,8 @@ cifs_negotiate_rsize(struct cifs_tcon *tcon, struct smb_vol *volume_info) + } + + static void +-cifs_qfs_tcon(const unsigned int xid, struct cifs_tcon *tcon) ++cifs_qfs_tcon(const unsigned int xid, struct cifs_tcon *tcon, ++ struct cifs_sb_info *cifs_sb) + { + CIFSSMBQFSDeviceInfo(xid, tcon); + CIFSSMBQFSAttributeInfo(xid, tcon); +@@ -565,7 +566,7 @@ cifs_query_path_info(const unsigned int xid, struct cifs_tcon *tcon, + oparms.tcon = tcon; + oparms.cifs_sb = cifs_sb; + oparms.desired_access = FILE_READ_ATTRIBUTES; +- oparms.create_options = 0; ++ oparms.create_options = cifs_create_options(cifs_sb, 0); + oparms.disposition = FILE_OPEN; + oparms.path = full_path; + oparms.fid = &fid; +@@ -793,7 +794,7 @@ smb_set_file_info(struct inode *inode, const char *full_path, + oparms.tcon = tcon; + oparms.cifs_sb = cifs_sb; + oparms.desired_access = SYNCHRONIZE | FILE_WRITE_ATTRIBUTES; +- oparms.create_options = CREATE_NOT_DIR; ++ oparms.create_options = cifs_create_options(cifs_sb, CREATE_NOT_DIR); + oparms.disposition = FILE_OPEN; + oparms.path = full_path; + oparms.fid = &fid; +@@ -872,7 +873,7 @@ cifs_oplock_response(struct cifs_tcon *tcon, struct cifs_fid *fid, + + static int + cifs_queryfs(const unsigned int xid, struct cifs_tcon *tcon, +- struct kstatfs *buf) ++ struct cifs_sb_info *cifs_sb, struct kstatfs *buf) + { + int rc = -EOPNOTSUPP; + +@@ -970,7 +971,8 @@ cifs_query_symlink(const unsigned int xid, struct cifs_tcon *tcon, + oparms.tcon = tcon; + oparms.cifs_sb = cifs_sb; + oparms.desired_access = FILE_READ_ATTRIBUTES; +- oparms.create_options = OPEN_REPARSE_POINT; ++ oparms.create_options = cifs_create_options(cifs_sb, ++ OPEN_REPARSE_POINT); + oparms.disposition = FILE_OPEN; + oparms.path = full_path; + oparms.fid = &fid; +@@ -1029,7 +1031,6 @@ cifs_make_node(unsigned int xid, struct inode *inode, + struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); + struct inode *newinode = NULL; + int rc = -EPERM; +- int create_options = CREATE_NOT_DIR | CREATE_OPTION_SPECIAL; + FILE_ALL_INFO *buf = NULL; + struct cifs_io_parms io_parms; + __u32 oplock = 0; +@@ -1090,13 +1091,11 @@ cifs_make_node(unsigned int xid, struct inode *inode, + goto out; + } + +- if (backup_cred(cifs_sb)) +- create_options |= CREATE_OPEN_BACKUP_INTENT; +- + oparms.tcon = tcon; + oparms.cifs_sb = cifs_sb; + oparms.desired_access = GENERIC_WRITE; +- oparms.create_options = create_options; ++ oparms.create_options = cifs_create_options(cifs_sb, CREATE_NOT_DIR | ++ CREATE_OPTION_SPECIAL); + oparms.disposition = FILE_CREATE; + oparms.path = full_path; + oparms.fid = &fid; +diff --git a/fs/cifs/smb2inode.c b/fs/cifs/smb2inode.c +index 5ef5e97a6d13..1cf207564ff9 100644 +--- a/fs/cifs/smb2inode.c ++++ b/fs/cifs/smb2inode.c +@@ -99,9 +99,7 @@ smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon, + oparms.tcon = tcon; + oparms.desired_access = desired_access; + oparms.disposition = create_disposition; +- oparms.create_options = create_options; +- if (backup_cred(cifs_sb)) +- oparms.create_options |= CREATE_OPEN_BACKUP_INTENT; ++ oparms.create_options = cifs_create_options(cifs_sb, create_options); + oparms.fid = &fid; + oparms.reconnect = false; + oparms.mode = mode; +@@ -457,7 +455,7 @@ smb2_query_path_info(const unsigned int xid, struct cifs_tcon *tcon, + + /* If it is a root and its handle is cached then use it */ + if (!strlen(full_path) && !no_cached_open) { +- rc = open_shroot(xid, tcon, &fid); ++ rc = open_shroot(xid, tcon, cifs_sb, &fid); + if (rc) + goto out; + +@@ -474,9 +472,6 @@ smb2_query_path_info(const unsigned int xid, struct cifs_tcon *tcon, + goto out; + } + +- if (backup_cred(cifs_sb)) +- create_options |= CREATE_OPEN_BACKUP_INTENT; +- + cifs_get_readable_path(tcon, full_path, &cfile); + rc = smb2_compound_op(xid, tcon, cifs_sb, full_path, + FILE_READ_ATTRIBUTES, FILE_OPEN, create_options, +diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c +index 6787fce26f20..33bb86cae369 100644 +--- a/fs/cifs/smb2ops.c ++++ b/fs/cifs/smb2ops.c +@@ -655,7 +655,8 @@ smb2_cached_lease_break(struct work_struct *work) + /* + * Open the directory at the root of a share + */ +-int open_shroot(unsigned int xid, struct cifs_tcon *tcon, struct cifs_fid *pfid) ++int open_shroot(unsigned int xid, struct cifs_tcon *tcon, ++ struct cifs_sb_info *cifs_sb, struct cifs_fid *pfid) + { + struct cifs_ses *ses = tcon->ses; + struct TCP_Server_Info *server = ses->server; +@@ -702,7 +703,7 @@ int open_shroot(unsigned int xid, struct cifs_tcon *tcon, struct cifs_fid *pfid) + rqst[0].rq_nvec = SMB2_CREATE_IOV_SIZE; + + oparms.tcon = tcon; +- oparms.create_options = 0; ++ oparms.create_options = cifs_create_options(cifs_sb, 0); + oparms.desired_access = FILE_READ_ATTRIBUTES; + oparms.disposition = FILE_OPEN; + oparms.fid = pfid; +@@ -818,7 +819,8 @@ int open_shroot(unsigned int xid, struct cifs_tcon *tcon, struct cifs_fid *pfid) + } + + static void +-smb3_qfs_tcon(const unsigned int xid, struct cifs_tcon *tcon) ++smb3_qfs_tcon(const unsigned int xid, struct cifs_tcon *tcon, ++ struct cifs_sb_info *cifs_sb) + { + int rc; + __le16 srch_path = 0; /* Null - open root of share */ +@@ -830,7 +832,7 @@ smb3_qfs_tcon(const unsigned int xid, struct cifs_tcon *tcon) + oparms.tcon = tcon; + oparms.desired_access = FILE_READ_ATTRIBUTES; + oparms.disposition = FILE_OPEN; +- oparms.create_options = 0; ++ oparms.create_options = cifs_create_options(cifs_sb, 0); + oparms.fid = &fid; + oparms.reconnect = false; + +@@ -838,7 +840,7 @@ smb3_qfs_tcon(const unsigned int xid, struct cifs_tcon *tcon) + rc = SMB2_open(xid, &oparms, &srch_path, &oplock, NULL, NULL, + NULL); + else +- rc = open_shroot(xid, tcon, &fid); ++ rc = open_shroot(xid, tcon, cifs_sb, &fid); + + if (rc) + return; +@@ -860,7 +862,8 @@ smb3_qfs_tcon(const unsigned int xid, struct cifs_tcon *tcon) + } + + static void +-smb2_qfs_tcon(const unsigned int xid, struct cifs_tcon *tcon) ++smb2_qfs_tcon(const unsigned int xid, struct cifs_tcon *tcon, ++ struct cifs_sb_info *cifs_sb) + { + int rc; + __le16 srch_path = 0; /* Null - open root of share */ +@@ -871,7 +874,7 @@ smb2_qfs_tcon(const unsigned int xid, struct cifs_tcon *tcon) + oparms.tcon = tcon; + oparms.desired_access = FILE_READ_ATTRIBUTES; + oparms.disposition = FILE_OPEN; +- oparms.create_options = 0; ++ oparms.create_options = cifs_create_options(cifs_sb, 0); + oparms.fid = &fid; + oparms.reconnect = false; + +@@ -906,10 +909,7 @@ smb2_is_path_accessible(const unsigned int xid, struct cifs_tcon *tcon, + oparms.tcon = tcon; + oparms.desired_access = FILE_READ_ATTRIBUTES; + oparms.disposition = FILE_OPEN; +- if (backup_cred(cifs_sb)) +- oparms.create_options = CREATE_OPEN_BACKUP_INTENT; +- else +- oparms.create_options = 0; ++ oparms.create_options = cifs_create_options(cifs_sb, 0); + oparms.fid = &fid; + oparms.reconnect = false; + +@@ -1151,10 +1151,7 @@ smb2_set_ea(const unsigned int xid, struct cifs_tcon *tcon, + oparms.tcon = tcon; + oparms.desired_access = FILE_WRITE_EA; + oparms.disposition = FILE_OPEN; +- if (backup_cred(cifs_sb)) +- oparms.create_options = CREATE_OPEN_BACKUP_INTENT; +- else +- oparms.create_options = 0; ++ oparms.create_options = cifs_create_options(cifs_sb, 0); + oparms.fid = &fid; + oparms.reconnect = false; + +@@ -1422,6 +1419,7 @@ SMB2_request_res_key(const unsigned int xid, struct cifs_tcon *tcon, + static int + smb2_ioctl_query_info(const unsigned int xid, + struct cifs_tcon *tcon, ++ struct cifs_sb_info *cifs_sb, + __le16 *path, int is_dir, + unsigned long p) + { +@@ -1447,6 +1445,7 @@ smb2_ioctl_query_info(const unsigned int xid, + struct kvec close_iov[1]; + unsigned int size[2]; + void *data[2]; ++ int create_options = is_dir ? CREATE_NOT_FILE : CREATE_NOT_DIR; + + memset(rqst, 0, sizeof(rqst)); + resp_buftype[0] = resp_buftype[1] = resp_buftype[2] = CIFS_NO_BUFFER; +@@ -1477,10 +1476,7 @@ smb2_ioctl_query_info(const unsigned int xid, + memset(&oparms, 0, sizeof(oparms)); + oparms.tcon = tcon; + oparms.disposition = FILE_OPEN; +- if (is_dir) +- oparms.create_options = CREATE_NOT_FILE; +- else +- oparms.create_options = CREATE_NOT_DIR; ++ oparms.create_options = cifs_create_options(cifs_sb, create_options); + oparms.fid = &fid; + oparms.reconnect = false; + +@@ -2086,10 +2082,7 @@ smb2_query_dir_first(const unsigned int xid, struct cifs_tcon *tcon, + oparms.tcon = tcon; + oparms.desired_access = FILE_READ_ATTRIBUTES | FILE_READ_DATA; + oparms.disposition = FILE_OPEN; +- if (backup_cred(cifs_sb)) +- oparms.create_options = CREATE_OPEN_BACKUP_INTENT; +- else +- oparms.create_options = 0; ++ oparms.create_options = cifs_create_options(cifs_sb, 0); + oparms.fid = fid; + oparms.reconnect = false; + +@@ -2343,10 +2336,7 @@ smb2_query_info_compound(const unsigned int xid, struct cifs_tcon *tcon, + oparms.tcon = tcon; + oparms.desired_access = desired_access; + oparms.disposition = FILE_OPEN; +- if (cifs_sb && backup_cred(cifs_sb)) +- oparms.create_options = CREATE_OPEN_BACKUP_INTENT; +- else +- oparms.create_options = 0; ++ oparms.create_options = cifs_create_options(cifs_sb, 0); + oparms.fid = &fid; + oparms.reconnect = false; + +@@ -2402,7 +2392,7 @@ smb2_query_info_compound(const unsigned int xid, struct cifs_tcon *tcon, + + static int + smb2_queryfs(const unsigned int xid, struct cifs_tcon *tcon, +- struct kstatfs *buf) ++ struct cifs_sb_info *cifs_sb, struct kstatfs *buf) + { + struct smb2_query_info_rsp *rsp; + struct smb2_fs_full_size_info *info = NULL; +@@ -2439,7 +2429,7 @@ smb2_queryfs(const unsigned int xid, struct cifs_tcon *tcon, + + static int + smb311_queryfs(const unsigned int xid, struct cifs_tcon *tcon, +- struct kstatfs *buf) ++ struct cifs_sb_info *cifs_sb, struct kstatfs *buf) + { + int rc; + __le16 srch_path = 0; /* Null - open root of share */ +@@ -2448,12 +2438,12 @@ smb311_queryfs(const unsigned int xid, struct cifs_tcon *tcon, + struct cifs_fid fid; + + if (!tcon->posix_extensions) +- return smb2_queryfs(xid, tcon, buf); ++ return smb2_queryfs(xid, tcon, cifs_sb, buf); + + oparms.tcon = tcon; + oparms.desired_access = FILE_READ_ATTRIBUTES; + oparms.disposition = FILE_OPEN; +- oparms.create_options = 0; ++ oparms.create_options = cifs_create_options(cifs_sb, 0); + oparms.fid = &fid; + oparms.reconnect = false; + +@@ -2722,6 +2712,7 @@ smb2_query_symlink(const unsigned int xid, struct cifs_tcon *tcon, + struct smb2_create_rsp *create_rsp; + struct smb2_ioctl_rsp *ioctl_rsp; + struct reparse_data_buffer *reparse_buf; ++ int create_options = is_reparse_point ? OPEN_REPARSE_POINT : 0; + u32 plen; + + cifs_dbg(FYI, "%s: path: %s\n", __func__, full_path); +@@ -2748,14 +2739,7 @@ smb2_query_symlink(const unsigned int xid, struct cifs_tcon *tcon, + oparms.tcon = tcon; + oparms.desired_access = FILE_READ_ATTRIBUTES; + oparms.disposition = FILE_OPEN; +- +- if (backup_cred(cifs_sb)) +- oparms.create_options = CREATE_OPEN_BACKUP_INTENT; +- else +- oparms.create_options = 0; +- if (is_reparse_point) +- oparms.create_options = OPEN_REPARSE_POINT; +- ++ oparms.create_options = cifs_create_options(cifs_sb, create_options); + oparms.fid = &fid; + oparms.reconnect = false; + +@@ -2934,11 +2918,6 @@ get_smb2_acl_by_path(struct cifs_sb_info *cifs_sb, + tcon = tlink_tcon(tlink); + xid = get_xid(); + +- if (backup_cred(cifs_sb)) +- oparms.create_options = CREATE_OPEN_BACKUP_INTENT; +- else +- oparms.create_options = 0; +- + utf16_path = cifs_convert_path_to_utf16(path, cifs_sb); + if (!utf16_path) { + rc = -ENOMEM; +@@ -2949,6 +2928,7 @@ get_smb2_acl_by_path(struct cifs_sb_info *cifs_sb, + oparms.tcon = tcon; + oparms.desired_access = READ_CONTROL; + oparms.disposition = FILE_OPEN; ++ oparms.create_options = cifs_create_options(cifs_sb, 0); + oparms.fid = &fid; + oparms.reconnect = false; + +@@ -2990,11 +2970,6 @@ set_smb2_acl(struct cifs_ntsd *pnntsd, __u32 acllen, + tcon = tlink_tcon(tlink); + xid = get_xid(); + +- if (backup_cred(cifs_sb)) +- oparms.create_options = CREATE_OPEN_BACKUP_INTENT; +- else +- oparms.create_options = 0; +- + if (aclflag == CIFS_ACL_OWNER || aclflag == CIFS_ACL_GROUP) + access_flags = WRITE_OWNER; + else +@@ -3009,6 +2984,7 @@ set_smb2_acl(struct cifs_ntsd *pnntsd, __u32 acllen, + + oparms.tcon = tcon; + oparms.desired_access = access_flags; ++ oparms.create_options = cifs_create_options(cifs_sb, 0); + oparms.disposition = FILE_OPEN; + oparms.path = path; + oparms.fid = &fid; +@@ -4491,7 +4467,6 @@ smb2_make_node(unsigned int xid, struct inode *inode, + { + struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); + int rc = -EPERM; +- int create_options = CREATE_NOT_DIR | CREATE_OPTION_SPECIAL; + FILE_ALL_INFO *buf = NULL; + struct cifs_io_parms io_parms; + __u32 oplock = 0; +@@ -4527,13 +4502,11 @@ smb2_make_node(unsigned int xid, struct inode *inode, + goto out; + } + +- if (backup_cred(cifs_sb)) +- create_options |= CREATE_OPEN_BACKUP_INTENT; +- + oparms.tcon = tcon; + oparms.cifs_sb = cifs_sb; + oparms.desired_access = GENERIC_WRITE; +- oparms.create_options = create_options; ++ oparms.create_options = cifs_create_options(cifs_sb, CREATE_NOT_DIR | ++ CREATE_OPTION_SPECIAL); + oparms.disposition = FILE_CREATE; + oparms.path = full_path; + oparms.fid = &fid; +diff --git a/fs/cifs/smb2proto.h b/fs/cifs/smb2proto.h +index 6c678e00046f..de6388ef344f 100644 +--- a/fs/cifs/smb2proto.h ++++ b/fs/cifs/smb2proto.h +@@ -68,7 +68,7 @@ extern int smb3_handle_read_data(struct TCP_Server_Info *server, + struct mid_q_entry *mid); + + extern int open_shroot(unsigned int xid, struct cifs_tcon *tcon, +- struct cifs_fid *pfid); ++ struct cifs_sb_info *cifs_sb, struct cifs_fid *pfid); + extern void close_shroot(struct cached_fid *cfid); + extern void close_shroot_lease(struct cached_fid *cfid); + extern void close_shroot_lease_locked(struct cached_fid *cfid); +-- +2.25.1 + + diff --git a/patches.suse/SUNRPC-Fix-svcauth_gss_proxy_init.patch b/patches.suse/SUNRPC-Fix-svcauth_gss_proxy_init.patch new file mode 100644 index 0000000..c8f05e9 --- /dev/null +++ b/patches.suse/SUNRPC-Fix-svcauth_gss_proxy_init.patch @@ -0,0 +1,164 @@ +From: Chuck Lever +Date: Thu, 24 Oct 2019 09:34:16 -0400 +Subject: SUNRPC: Fix svcauth_gss_proxy_init() +Patch-mainline: v5.5-rc1 +Git-commit: 5866efa8cbfbadf3905072798e96652faf02dbe8 +References: bsc#1103992 FATE#326009 + +gss_read_proxy_verf() assumes things about the XDR buffer containing +the RPC Call that are not true for buffers generated by +svc_rdma_recv(). + +RDMA's buffers look more like what the upper layer generates for +sending: head is a kmalloc'd buffer; it does not point to a page +whose contents are contiguous with the first page in the buffers' +page array. The result is that ACCEPT_SEC_CONTEXT via RPC/RDMA has +stopped working on Linux NFS servers that use gssproxy. + +This does not affect clients that use only TCP to send their +ACCEPT_SEC_CONTEXT operation (that's all Linux clients). Other +clients, like Solaris NFS clients, send ACCEPT_SEC_CONTEXT on the +same transport as they send all other NFS operations. Such clients +can send ACCEPT_SEC_CONTEXT via RPC/RDMA. + +I thought I had found every direct reference in the server RPC code +to the rqstp->rq_pages field. + +Bug found at the 2019 Westford NFS bake-a-thon. + +Fixes: 3316f0631139 ("svcrdma: Persistently allocate and DMA- ... ") +Signed-off-by: Chuck Lever +Tested-by: Bill Baker +Reviewed-by: Simo Sorce +Signed-off-by: J. Bruce Fields +Acked-by: Thomas Bogendoerfer +--- + net/sunrpc/auth_gss/svcauth_gss.c | 84 ++++++++++++++++++++++++++++---------- + 1 file changed, 63 insertions(+), 21 deletions(-) + +--- a/net/sunrpc/auth_gss/svcauth_gss.c ++++ b/net/sunrpc/auth_gss/svcauth_gss.c +@@ -1044,24 +1044,32 @@ gss_read_verf(struct rpc_gss_wire_cred * + return 0; + } + +-/* Ok this is really heavily depending on a set of semantics in +- * how rqstp is set up by svc_recv and pages laid down by the +- * server when reading a request. We are basically guaranteed that +- * the token lays all down linearly across a set of pages, starting +- * at iov_base in rq_arg.head[0] which happens to be the first of a +- * set of pages stored in rq_pages[]. +- * rq_arg.head[0].iov_base will provide us the page_base to pass +- * to the upcall. +- */ +-static inline int +-gss_read_proxy_verf(struct svc_rqst *rqstp, +- struct rpc_gss_wire_cred *gc, __be32 *authp, +- struct xdr_netobj *in_handle, +- struct gssp_in_token *in_token) ++static void gss_free_in_token_pages(struct gssp_in_token *in_token) + { +- struct kvec *argv = &rqstp->rq_arg.head[0]; + u32 inlen; +- int res; ++ int i; ++ ++ i = 0; ++ inlen = in_token->page_len; ++ while (inlen) { ++ if (in_token->pages[i]) ++ put_page(in_token->pages[i]); ++ inlen -= inlen > PAGE_SIZE ? PAGE_SIZE : inlen; ++ } ++ ++ kfree(in_token->pages); ++ in_token->pages = NULL; ++} ++ ++static int gss_read_proxy_verf(struct svc_rqst *rqstp, ++ struct rpc_gss_wire_cred *gc, __be32 *authp, ++ struct xdr_netobj *in_handle, ++ struct gssp_in_token *in_token) ++{ ++ struct kvec *argv = &rqstp->rq_arg.head[0]; ++ unsigned int page_base, length; ++ int pages, i, res; ++ size_t inlen; + + res = gss_read_common_verf(gc, argv, authp, in_handle); + if (res) +@@ -1071,10 +1079,36 @@ gss_read_proxy_verf(struct svc_rqst *rqs + if (inlen > (argv->iov_len + rqstp->rq_arg.page_len)) + return SVC_DENIED; + +- in_token->pages = rqstp->rq_pages; +- in_token->page_base = (ulong)argv->iov_base & ~PAGE_MASK; ++ pages = DIV_ROUND_UP(inlen, PAGE_SIZE); ++ in_token->pages = kcalloc(pages, sizeof(struct page *), GFP_KERNEL); ++ if (!in_token->pages) ++ return SVC_DENIED; ++ in_token->page_base = 0; + in_token->page_len = inlen; ++ for (i = 0; i < pages; i++) { ++ in_token->pages[i] = alloc_page(GFP_KERNEL); ++ if (!in_token->pages[i]) { ++ gss_free_in_token_pages(in_token); ++ return SVC_DENIED; ++ } ++ } + ++ length = min_t(unsigned int, inlen, argv->iov_len); ++ memcpy(page_address(in_token->pages[0]), argv->iov_base, length); ++ inlen -= length; ++ ++ i = 1; ++ page_base = rqstp->rq_arg.page_base; ++ while (inlen) { ++ length = min_t(unsigned int, inlen, PAGE_SIZE); ++ memcpy(page_address(in_token->pages[i]), ++ page_address(rqstp->rq_arg.pages[i]) + page_base, ++ length); ++ ++ inlen -= length; ++ page_base = 0; ++ i++; ++ } + return 0; + } + +@@ -1249,8 +1283,11 @@ static int svcauth_gss_proxy_init(struct + break; + case GSS_S_COMPLETE: + status = gss_proxy_save_rsc(sn->rsc_cache, &ud, &handle); +- if (status) ++ if (status) { ++ pr_info("%s: gss_proxy_save_rsc failed (%d)\n", ++ __func__, status); + goto out; ++ } + cli_handle.data = (u8 *)&handle; + cli_handle.len = sizeof(handle); + break; +@@ -1261,15 +1298,20 @@ static int svcauth_gss_proxy_init(struct + + /* Got an answer to the upcall; use it: */ + if (gss_write_init_verf(sn->rsc_cache, rqstp, +- &cli_handle, &ud.major_status)) ++ &cli_handle, &ud.major_status)) { ++ pr_info("%s: gss_write_init_verf failed\n", __func__); + goto out; ++ } + if (gss_write_resv(resv, PAGE_SIZE, + &cli_handle, &ud.out_token, +- ud.major_status, ud.minor_status)) ++ ud.major_status, ud.minor_status)) { ++ pr_info("%s: gss_write_resv failed\n", __func__); + goto out; ++ } + + ret = SVC_COMPLETE; + out: ++ gss_free_in_token_pages(&ud.in_token); + gssp_free_upcall_data(&ud); + return ret; + } diff --git a/patches.suse/USB-serial-io_edgeport-fix-slab-out-of-bounds-read-i.patch b/patches.suse/USB-serial-io_edgeport-fix-slab-out-of-bounds-read-i.patch new file mode 100644 index 0000000..9600108 --- /dev/null +++ b/patches.suse/USB-serial-io_edgeport-fix-slab-out-of-bounds-read-i.patch @@ -0,0 +1,40 @@ +From 57aa9f294b09463492f604feaa5cc719beaace32 Mon Sep 17 00:00:00 2001 +From: Qiujun Huang +Date: Wed, 25 Mar 2020 15:52:37 +0800 +Subject: [PATCH] USB: serial: io_edgeport: fix slab-out-of-bounds read in edge_interrupt_callback +Git-commit: 57aa9f294b09463492f604feaa5cc719beaace32 +Patch-mainline: v5.7-rc1 +References: bsc#1051510 + +Fix slab-out-of-bounds read in the interrupt-URB completion handler. + +The boundary condition should be (length - 1) as we access +data[position + 1]. + +Reported-and-tested-by: syzbot+37ba33391ad5f3935bbd@syzkaller.appspotmail.com +Signed-off-by: Qiujun Huang +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Cc: stable +Signed-off-by: Johan Hovold +Acked-by: Takashi Iwai + +--- + drivers/usb/serial/io_edgeport.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/usb/serial/io_edgeport.c b/drivers/usb/serial/io_edgeport.c +index 5737add6a2a4..4cca0b836f43 100644 +--- a/drivers/usb/serial/io_edgeport.c ++++ b/drivers/usb/serial/io_edgeport.c +@@ -710,7 +710,7 @@ static void edge_interrupt_callback(struct urb *urb) + /* grab the txcredits for the ports if available */ + position = 2; + portNumber = 0; +- while ((position < length) && ++ while ((position < length - 1) && + (portNumber < edge_serial->serial->num_ports)) { + txCredits = data[position] | (data[position+1] << 8); + if (txCredits) { +-- +2.16.4 + diff --git a/patches.suse/acpi-watchdog-allow-disabling-wdat-at-boot.patch b/patches.suse/acpi-watchdog-allow-disabling-wdat-at-boot.patch index 701204f..ca82226 100644 --- a/patches.suse/acpi-watchdog-allow-disabling-wdat-at-boot.patch +++ b/patches.suse/acpi-watchdog-allow-disabling-wdat-at-boot.patch @@ -1,9 +1,8 @@ From: Jean Delvare Date: Thu, 6 Feb 2020 16:58:45 +0100 Subject: ACPI: watchdog: Allow disabling WDAT at boot -Patch-mainline: Queued in subsystem maintainer repository +Patch-mainline: v5.6 Git-commit: 3f9e12e0df012c4a9a7fd7eb0d3ae69b459d6b2c -Git-repo: https://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm.git References: bsc#1162557 In case the WDAT interface is broken, give the user an option to diff --git a/patches.suse/acpi-watchdog-set-default-timeout-in-probe.patch b/patches.suse/acpi-watchdog-set-default-timeout-in-probe.patch index 5d253b5..de440a1 100644 --- a/patches.suse/acpi-watchdog-set-default-timeout-in-probe.patch +++ b/patches.suse/acpi-watchdog-set-default-timeout-in-probe.patch @@ -1,7 +1,8 @@ From: Mika Westerberg Subject: ACPI / watchdog: Set default timeout in probe Date: Wed, 12 Feb 2020 17:59:41 +0300 -Patch-mainline: Submitted by Mika Westerberg 2020-02-12 +Patch-mainline: v5.6 +Git-commit: cabe17d0173ab04bd3f87b8199ae75f43f1ea473 References: bsc#1162557 If the BIOS default timeout for the watchdog is too small userspace may diff --git a/patches.suse/apei-ghes-Do-not-delay-GHES-polling.patch b/patches.suse/apei-ghes-Do-not-delay-GHES-polling.patch new file mode 100644 index 0000000..ef40554 --- /dev/null +++ b/patches.suse/apei-ghes-Do-not-delay-GHES-polling.patch @@ -0,0 +1,47 @@ +From: Bhaskar Upadhaya +Date: Wed, 8 Jan 2020 09:17:38 -0800 +Subject: apei/ghes: Do not delay GHES polling + +Git-commit: cea79e7e2f24125b895bbfcdf98c8cfd1fb684d1 +Patch-mainline: v5.6-rc1 +References: bsc#1166982 + +Currently, the ghes_poll_func() timer callback is registered with the +TIMER_DEFERRABLE flag. Thus, it is run when the CPU eventually wakes +up together with a subsequent non-deferrable timer and not at the precisely +configured polling interval. + +For polling mode, the polling interval configured by firmware should not +be exceeded according to the ACPI spec 6.3, Table 18-394. The definition +of the polling interval is: + +"Indicates the poll interval in milliseconds OSPM should use to + periodically check the error source for the presence of an error + condition." + +If this interval is extended due to the timer callback deferring, error +records can get lost. Which we are observing on our ThunderX2 platforms. + +Therefore, remove the TIMER_DEFERRABLE flag so that the timer callback +executes at the precise interval. + +Signed-off-by: Bhaskar Upadhaya +[ bp: Subject & changelog ] +Acked-by: Borislav Petkov +Signed-off-by: Rafael J. Wysocki +Signed-off-by: Mian Yousaf Kaukab +--- + drivers/acpi/apei/ghes.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/acpi/apei/ghes.c ++++ b/drivers/acpi/apei/ghes.c +@@ -1076,7 +1076,7 @@ static int ghes_probe(struct platform_de + + switch (generic->notify.type) { + case ACPI_HEST_NOTIFY_POLLED: +- setup_deferrable_timer(&ghes->timer, ghes_poll_func, ++ setup_timer(&ghes->timer, ghes_poll_func, + (unsigned long)ghes); + ghes_add_timer(ghes); + break; diff --git a/patches.suse/arm64-PCI-Preserve-firmware-configuration-when-desir.patch b/patches.suse/arm64-PCI-Preserve-firmware-configuration-when-desir.patch index 5c8ac3f..333055c 100644 --- a/patches.suse/arm64-PCI-Preserve-firmware-configuration-when-desir.patch +++ b/patches.suse/arm64-PCI-Preserve-firmware-configuration-when-desir.patch @@ -20,15 +20,13 @@ Acked-by: Ard Biesheuvel [Yousaf]: Whole series is folded in here Signed-off-by: Mian Yousaf Kaukab --- - arch/arm64/kernel/pci.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++-- - include/linux/pci-acpi.h | 1 + - 2 files changed, 51 insertions(+), 2 deletions(-) + arch/arm64/kernel/pci.c | 50 +++++++++++++++++++++++++++++++++++++++++++++-- + include/linux/pci-acpi.h | 1 + 2 files changed, 49 insertions(+), 2 deletions(-) -diff --git a/arch/arm64/kernel/pci.c b/arch/arm64/kernel/pci.c -index e2b7e4f9cc31..ed5e5809bb43 100644 --- a/arch/arm64/kernel/pci.c +++ b/arch/arm64/kernel/pci.c -@@ -179,6 +179,27 @@ static void pci_acpi_generic_release_info(struct acpi_pci_root_info *ci) +@@ -179,6 +179,25 @@ static void pci_acpi_generic_release_inf kfree(ri); } @@ -44,9 +42,7 @@ index e2b7e4f9cc31..ed5e5809bb43 100644 + if (ACPI_FAILURE(status) || !madt) + return ret; + -+ ret = (!memcmp(madt->header.oem_id, "AMAZON", ACPI_OEM_ID_SIZE) && -+ !memcmp(madt->header.oem_table_id, "GRAVITON", -+ ACPI_OEM_TABLE_ID_SIZE)); ++ ret = !memcmp(madt->header.oem_id, "AMAZON", ACPI_OEM_ID_SIZE); + + acpi_put_table((struct acpi_table_header *)madt); + @@ -56,7 +52,7 @@ index e2b7e4f9cc31..ed5e5809bb43 100644 /* Interface called from ACPI code to setup PCI host controller */ struct pci_bus *pci_acpi_scan_root(struct acpi_pci_root *root) { -@@ -211,8 +232,35 @@ struct pci_bus *pci_acpi_scan_root(struct acpi_pci_root *root) +@@ -211,8 +230,35 @@ struct pci_bus *pci_acpi_scan_root(struc if (!bus) return NULL; @@ -94,11 +90,9 @@ index e2b7e4f9cc31..ed5e5809bb43 100644 list_for_each_entry(child, &bus->children, node) pcie_bus_configure_settings(child); -diff --git a/include/linux/pci-acpi.h b/include/linux/pci-acpi.h -index dd86c97f2454..dade015f8baf 100644 --- a/include/linux/pci-acpi.h +++ b/include/linux/pci-acpi.h -@@ -106,6 +106,7 @@ static inline void acpiphp_check_host_bridge(struct acpi_device *adev) { } +@@ -106,6 +106,7 @@ static inline void acpiphp_check_host_br #endif extern const guid_t pci_acpi_dsm_guid; @@ -106,6 +100,3 @@ index dd86c97f2454..dade015f8baf 100644 #define DEVICE_LABEL_DSM 0x07 #define RESET_DELAY_DSM 0x08 #define FUNCTION_DELAY_DSM 0x09 --- -2.11.0 - diff --git a/patches.suse/ath9k-Handle-txpower-changes-even-when-TPC-is-disabl.patch b/patches.suse/ath9k-Handle-txpower-changes-even-when-TPC-is-disabl.patch new file mode 100644 index 0000000..5b4bb38 --- /dev/null +++ b/patches.suse/ath9k-Handle-txpower-changes-even-when-TPC-is-disabl.patch @@ -0,0 +1,61 @@ +From 968ae2caad0782db5dbbabb560d3cdefd2945d38 Mon Sep 17 00:00:00 2001 +From: Remi Pommarel +Date: Sat, 29 Feb 2020 17:13:47 +0100 +Subject: [PATCH] ath9k: Handle txpower changes even when TPC is disabled +Git-commit: 968ae2caad0782db5dbbabb560d3cdefd2945d38 +Patch-mainline: v5.7-rc1 +References: bsc#1051510 + +When TPC is disabled IEEE80211_CONF_CHANGE_POWER event can be handled to +reconfigure HW's maximum txpower. + +This fixes 0dBm txpower setting when user attaches to an interface for +the first time with the following scenario: + +ieee80211_do_open() + ath9k_add_interface() + ath9k_set_txpower() /* Set TX power with not yet initialized + sc->hw->conf.power_level */ + + ieee80211_hw_config() /* Iniatilize sc->hw->conf.power_level and + raise IEEE80211_CONF_CHANGE_POWER */ + + ath9k_config() /* IEEE80211_CONF_CHANGE_POWER is ignored */ + +This issue can be reproduced with the following: + + $ modprobe -r ath9k + $ modprobe ath9k + $ wpa_supplicant -i wlan0 -c /tmp/wpa.conf & + $ iw dev /* Here TX power is either 0 or 3 depending on RF chain */ + $ killall wpa_supplicant + $ iw dev /* TX power goes back to calibrated value and subsequent + calls will be fine */ + +Fixes: 283dd11994cde ("ath9k: add per-vif TX power capability") +Cc: stable@vger.kernel.org +Signed-off-by: Remi Pommarel +Signed-off-by: Kalle Valo +Acked-by: Takashi Iwai + +--- + drivers/net/wireless/ath/ath9k/main.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c +index 0548aa3702e3..ef2b856670e1 100644 +--- a/drivers/net/wireless/ath/ath9k/main.c ++++ b/drivers/net/wireless/ath/ath9k/main.c +@@ -1457,6 +1457,9 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed) + ath_chanctx_set_channel(sc, ctx, &hw->conf.chandef); + } + ++ if (changed & IEEE80211_CONF_CHANGE_POWER) ++ ath9k_set_txpower(sc, NULL); ++ + mutex_unlock(&sc->mutex); + ath9k_ps_restore(sc); + +-- +2.16.4 + diff --git a/patches.suse/atm-zatm-Fix-empty-body-Clang-warnings.patch b/patches.suse/atm-zatm-Fix-empty-body-Clang-warnings.patch new file mode 100644 index 0000000..8a193d1 --- /dev/null +++ b/patches.suse/atm-zatm-Fix-empty-body-Clang-warnings.patch @@ -0,0 +1,175 @@ +From 64b9d16e2d02ca6e5dc8fcd30cfd52b0ecaaa8f4 Mon Sep 17 00:00:00 2001 +From: Nathan Chancellor +Date: Wed, 17 Oct 2018 11:04:19 -0700 +Subject: [PATCH] atm: zatm: Fix empty body Clang warnings +Git-commit: 64b9d16e2d02ca6e5dc8fcd30cfd52b0ecaaa8f4 +Patch-mainline: v4.20-rc1 +References: bsc#1051510 + +Clang warns: + +drivers/atm/zatm.c:513:7: error: while loop has empty body +[-Werror,-Wempty-body] + zwait; + ^ +drivers/atm/zatm.c:513:7: note: put the semicolon on a separate line to +silence this warning + +Get rid of this warning by using an empty do-while loop. While we're at +it, add parentheses to make it clear that this is a function-like macro. + +Link: https://github.com/ClangBuiltLinux/linux/issues/42 +Suggested-by: Masahiro Yamada +Signed-off-by: Nathan Chancellor +Signed-off-by: David S. Miller +Acked-by: Takashi Iwai + +--- + drivers/atm/zatm.c | 42 +++++++++++++++++++++--------------------- + 1 file changed, 21 insertions(+), 21 deletions(-) + +diff --git a/drivers/atm/zatm.c b/drivers/atm/zatm.c +index e89146ddede6..d5c76b50d357 100644 +--- a/drivers/atm/zatm.c ++++ b/drivers/atm/zatm.c +@@ -126,7 +126,7 @@ static unsigned long dummy[2] = {0,0}; + #define zin_n(r) inl(zatm_dev->base+r*4) + #define zin(r) inl(zatm_dev->base+uPD98401_##r*4) + #define zout(v,r) outl(v,zatm_dev->base+uPD98401_##r*4) +-#define zwait while (zin(CMR) & uPD98401_BUSY) ++#define zwait() do {} while (zin(CMR) & uPD98401_BUSY) + + /* RX0, RX1, TX0, TX1 */ + static const int mbx_entries[NR_MBX] = { 1024,1024,1024,1024 }; +@@ -140,7 +140,7 @@ static const int mbx_esize[NR_MBX] = { 16,16,4,4 }; /* entry size in bytes */ + + static void zpokel(struct zatm_dev *zatm_dev,u32 value,u32 addr) + { +- zwait; ++ zwait(); + zout(value,CER); + zout(uPD98401_IND_ACC | uPD98401_IA_BALL | + (uPD98401_IA_TGT_CM << uPD98401_IA_TGT_SHIFT) | addr,CMR); +@@ -149,10 +149,10 @@ static void zpokel(struct zatm_dev *zatm_dev,u32 value,u32 addr) + + static u32 zpeekl(struct zatm_dev *zatm_dev,u32 addr) + { +- zwait; ++ zwait(); + zout(uPD98401_IND_ACC | uPD98401_IA_BALL | uPD98401_IA_RW | + (uPD98401_IA_TGT_CM << uPD98401_IA_TGT_SHIFT) | addr,CMR); +- zwait; ++ zwait(); + return zin(CER); + } + +@@ -241,7 +241,7 @@ static void refill_pool(struct atm_dev *dev,int pool) + } + if (first) { + spin_lock_irqsave(&zatm_dev->lock, flags); +- zwait; ++ zwait(); + zout(virt_to_bus(first),CER); + zout(uPD98401_ADD_BAT | (pool << uPD98401_POOL_SHIFT) | count, + CMR); +@@ -508,9 +508,9 @@ static int open_rx_first(struct atm_vcc *vcc) + } + if (zatm_vcc->pool < 0) return -EMSGSIZE; + spin_lock_irqsave(&zatm_dev->lock, flags); +- zwait; ++ zwait(); + zout(uPD98401_OPEN_CHAN,CMR); +- zwait; ++ zwait(); + DPRINTK("0x%x 0x%x\n",zin(CMR),zin(CER)); + chan = (zin(CMR) & uPD98401_CHAN_ADDR) >> uPD98401_CHAN_ADDR_SHIFT; + spin_unlock_irqrestore(&zatm_dev->lock, flags); +@@ -571,21 +571,21 @@ static void close_rx(struct atm_vcc *vcc) + pos = vcc->vci >> 1; + shift = (1-(vcc->vci & 1)) << 4; + zpokel(zatm_dev,zpeekl(zatm_dev,pos) & ~(0xffff << shift),pos); +- zwait; ++ zwait(); + zout(uPD98401_NOP,CMR); +- zwait; ++ zwait(); + zout(uPD98401_NOP,CMR); + spin_unlock_irqrestore(&zatm_dev->lock, flags); + } + spin_lock_irqsave(&zatm_dev->lock, flags); +- zwait; ++ zwait(); + zout(uPD98401_DEACT_CHAN | uPD98401_CHAN_RT | (zatm_vcc->rx_chan << + uPD98401_CHAN_ADDR_SHIFT),CMR); +- zwait; ++ zwait(); + udelay(10); /* why oh why ... ? */ + zout(uPD98401_CLOSE_CHAN | uPD98401_CHAN_RT | (zatm_vcc->rx_chan << + uPD98401_CHAN_ADDR_SHIFT),CMR); +- zwait; ++ zwait(); + if (!(zin(CMR) & uPD98401_CHAN_ADDR)) + printk(KERN_CRIT DEV_LABEL "(itf %d): can't close RX channel " + "%d\n",vcc->dev->number,zatm_vcc->rx_chan); +@@ -699,7 +699,7 @@ printk("NONONONOO!!!!\n"); + skb_queue_tail(&zatm_vcc->tx_queue,skb); + DPRINTK("QRP=0x%08lx\n",zpeekl(zatm_dev,zatm_vcc->tx_chan*VC_SIZE/4+ + uPD98401_TXVC_QRP)); +- zwait; ++ zwait(); + zout(uPD98401_TX_READY | (zatm_vcc->tx_chan << + uPD98401_CHAN_ADDR_SHIFT),CMR); + spin_unlock_irqrestore(&zatm_dev->lock, flags); +@@ -891,12 +891,12 @@ static void close_tx(struct atm_vcc *vcc) + } + spin_lock_irqsave(&zatm_dev->lock, flags); + #if 0 +- zwait; ++ zwait(); + zout(uPD98401_DEACT_CHAN | (chan << uPD98401_CHAN_ADDR_SHIFT),CMR); + #endif +- zwait; ++ zwait(); + zout(uPD98401_CLOSE_CHAN | (chan << uPD98401_CHAN_ADDR_SHIFT),CMR); +- zwait; ++ zwait(); + if (!(zin(CMR) & uPD98401_CHAN_ADDR)) + printk(KERN_CRIT DEV_LABEL "(itf %d): can't close TX channel " + "%d\n",vcc->dev->number,chan); +@@ -926,9 +926,9 @@ static int open_tx_first(struct atm_vcc *vcc) + zatm_vcc->tx_chan = 0; + if (vcc->qos.txtp.traffic_class == ATM_NONE) return 0; + spin_lock_irqsave(&zatm_dev->lock, flags); +- zwait; ++ zwait(); + zout(uPD98401_OPEN_CHAN,CMR); +- zwait; ++ zwait(); + DPRINTK("0x%x 0x%x\n",zin(CMR),zin(CER)); + chan = (zin(CMR) & uPD98401_CHAN_ADDR) >> uPD98401_CHAN_ADDR_SHIFT; + spin_unlock_irqrestore(&zatm_dev->lock, flags); +@@ -1557,7 +1557,7 @@ static void zatm_phy_put(struct atm_dev *dev,unsigned char value, + struct zatm_dev *zatm_dev; + + zatm_dev = ZATM_DEV(dev); +- zwait; ++ zwait(); + zout(value,CER); + zout(uPD98401_IND_ACC | uPD98401_IA_B0 | + (uPD98401_IA_TGT_PHY << uPD98401_IA_TGT_SHIFT) | addr,CMR); +@@ -1569,10 +1569,10 @@ static unsigned char zatm_phy_get(struct atm_dev *dev,unsigned long addr) + struct zatm_dev *zatm_dev; + + zatm_dev = ZATM_DEV(dev); +- zwait; ++ zwait(); + zout(uPD98401_IND_ACC | uPD98401_IA_B0 | uPD98401_IA_RW | + (uPD98401_IA_TGT_PHY << uPD98401_IA_TGT_SHIFT) | addr,CMR); +- zwait; ++ zwait(); + return zin(CER) & 0xff; + } + +-- +2.16.4 + diff --git a/patches.suse/b43legacy-Fix-Wcast-function-type.patch b/patches.suse/b43legacy-Fix-Wcast-function-type.patch new file mode 100644 index 0000000..2cf90f5 --- /dev/null +++ b/patches.suse/b43legacy-Fix-Wcast-function-type.patch @@ -0,0 +1,48 @@ +From 475eec112e4267232d10f4afe2f939a241692b6c Mon Sep 17 00:00:00 2001 +From: Phong Tran +Date: Wed, 27 Nov 2019 00:55:26 +0700 +Subject: [PATCH] b43legacy: Fix -Wcast-function-type +Git-commit: 475eec112e4267232d10f4afe2f939a241692b6c +Patch-mainline: v5.6-rc1 +References: bsc#1051510 + +correct usage prototype of callback in tasklet_init(). +Report by https://github.com/KSPP/linux/issues/20 + +Tested-by: Larry Finger +Signed-off-by: Phong Tran +Reviewed-by: Kees Cook +Signed-off-by: Kalle Valo +Acked-by: Takashi Iwai + +--- + drivers/net/wireless/broadcom/b43legacy/main.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/wireless/broadcom/b43legacy/main.c b/drivers/net/wireless/broadcom/b43legacy/main.c +index 4325e91736eb..8b6b657c4b85 100644 +--- a/drivers/net/wireless/broadcom/b43legacy/main.c ++++ b/drivers/net/wireless/broadcom/b43legacy/main.c +@@ -1275,8 +1275,9 @@ static void handle_irq_ucode_debug(struct b43legacy_wldev *dev) + } + + /* Interrupt handler bottom-half */ +-static void b43legacy_interrupt_tasklet(struct b43legacy_wldev *dev) ++static void b43legacy_interrupt_tasklet(unsigned long data) + { ++ struct b43legacy_wldev *dev = (struct b43legacy_wldev *)data; + u32 reason; + u32 dma_reason[ARRAY_SIZE(dev->dma_reason)]; + u32 merged_dma_reason = 0; +@@ -3741,7 +3742,7 @@ static int b43legacy_one_core_attach(struct ssb_device *dev, + b43legacy_set_status(wldev, B43legacy_STAT_UNINIT); + wldev->bad_frames_preempt = modparam_bad_frames_preempt; + tasklet_init(&wldev->isr_tasklet, +- (void (*)(unsigned long))b43legacy_interrupt_tasklet, ++ b43legacy_interrupt_tasklet, + (unsigned long)wldev); + if (modparam_pio) + wldev->__using_pio = true; +-- +2.16.4 + diff --git a/patches.suse/batman-adv-Avoid-spurious-warnings-from-bat_v-neigh_.patch b/patches.suse/batman-adv-Avoid-spurious-warnings-from-bat_v-neigh_.patch new file mode 100644 index 0000000..e5581ca --- /dev/null +++ b/patches.suse/batman-adv-Avoid-spurious-warnings-from-bat_v-neigh_.patch @@ -0,0 +1,71 @@ +From 6a4bc44b012cbc29c9d824be2c7ab9eac8ee6b6f Mon Sep 17 00:00:00 2001 +From: Sven Eckelmann +Date: Mon, 16 Oct 2017 09:31:47 +0200 +Subject: [PATCH] batman-adv: Avoid spurious warnings from bat_v neigh_cmp implementation +Git-commit: 6a4bc44b012cbc29c9d824be2c7ab9eac8ee6b6f +Patch-mainline: v4.15-rc1 +References: bsc#1051510 + +The neighbor compare API implementation for B.A.T.M.A.N. V checks whether +the neigh_ifinfo for this neighbor on a specific interface exists. A +warning is printed when it isn't found. + +But it is not called inside a lock which would prevent that this +information is lost right before batadv_neigh_ifinfo_get. It must therefore +be expected that batadv_v_neigh_(cmp|is_sob) might not be able to get the +requested neigh_ifinfo. + +A WARN_ON for such a situation seems not to be appropriate because this +will only flood the kernel logs. The warnings must therefore be removed. + +Signed-off-by: Sven Eckelmann +Signed-off-by: Simon Wunderlich +Acked-by: Takashi Iwai + +--- + net/batman-adv/bat_v.c | 9 ++++----- + 1 file changed, 4 insertions(+), 5 deletions(-) + +diff --git a/net/batman-adv/bat_v.c b/net/batman-adv/bat_v.c +index 93ef1c06227e..341ceab8338d 100644 +--- a/net/batman-adv/bat_v.c ++++ b/net/batman-adv/bat_v.c +@@ -19,7 +19,6 @@ + #include "main.h" + + #include +-#include + #include + #include + #include +@@ -623,11 +622,11 @@ static int batadv_v_neigh_cmp(struct batadv_neigh_node *neigh1, + int ret = 0; + + ifinfo1 = batadv_neigh_ifinfo_get(neigh1, if_outgoing1); +- if (WARN_ON(!ifinfo1)) ++ if (!ifinfo1) + goto err_ifinfo1; + + ifinfo2 = batadv_neigh_ifinfo_get(neigh2, if_outgoing2); +- if (WARN_ON(!ifinfo2)) ++ if (!ifinfo2) + goto err_ifinfo2; + + ret = ifinfo1->bat_v.throughput - ifinfo2->bat_v.throughput; +@@ -649,11 +648,11 @@ static bool batadv_v_neigh_is_sob(struct batadv_neigh_node *neigh1, + bool ret = false; + + ifinfo1 = batadv_neigh_ifinfo_get(neigh1, if_outgoing1); +- if (WARN_ON(!ifinfo1)) ++ if (!ifinfo1) + goto err_ifinfo1; + + ifinfo2 = batadv_neigh_ifinfo_get(neigh2, if_outgoing2); +- if (WARN_ON(!ifinfo2)) ++ if (!ifinfo2) + goto err_ifinfo2; + + threshold = ifinfo1->bat_v.throughput / 4; +-- +2.16.4 + diff --git a/patches.suse/batman-adv-Don-t-schedule-OGM-for-disabled-interface.patch b/patches.suse/batman-adv-Don-t-schedule-OGM-for-disabled-interface.patch new file mode 100644 index 0000000..3c69859 --- /dev/null +++ b/patches.suse/batman-adv-Don-t-schedule-OGM-for-disabled-interface.patch @@ -0,0 +1,42 @@ +From 8e8ce08198de193e3d21d42e96945216e3d9ac7f Mon Sep 17 00:00:00 2001 +From: Sven Eckelmann +Date: Sun, 16 Feb 2020 13:02:06 +0100 +Subject: [PATCH] batman-adv: Don't schedule OGM for disabled interface +Git-commit: 8e8ce08198de193e3d21d42e96945216e3d9ac7f +Patch-mainline: v5.6-rc6 +References: bsc#1051510 + +A transmission scheduling for an interface which is currently dropped by +batadv_iv_ogm_iface_disable could still be in progress. The B.A.T.M.A.N. V +is simply cancelling the workqueue item in an synchronous way but this is +not possible with B.A.T.M.A.N. IV because the OGM submissions are +intertwined. + +Instead it has to stop submitting the OGM when it detect that the buffer +pointer is set to NULL. + +Reported-by: syzbot+a98f2016f40b9cd3818a@syzkaller.appspotmail.com +Reported-by: syzbot+ac36b6a33c28a491e929@syzkaller.appspotmail.com +Fixes: c6c8fea29769 ("net: Add batman-adv meshing protocol") +Signed-off-by: Sven Eckelmann +Cc: Hillf Danton +Signed-off-by: Simon Wunderlich +Acked-by: Takashi Iwai + +--- + net/batman-adv/bat_iv_ogm.c | 4 ++++ + 1 file changed, 4 insertions(+) + +--- a/net/batman-adv/bat_iv_ogm.c ++++ b/net/batman-adv/bat_iv_ogm.c +@@ -932,6 +932,10 @@ static void batadv_iv_ogm_schedule(struc + (hard_iface->if_status == BATADV_IF_TO_BE_REMOVED)) + return; + ++ /* interface already disabled by batadv_iv_ogm_iface_disable */ ++ if (!*ogm_buff) ++ return; ++ + /* the interface gets activated here to avoid race conditions between + * the moment of activating the interface in + * hardif_activate_interface() where the originator mac is set and diff --git a/patches.suse/batman-adv-prevent-TT-request-storms-by-not-sending-.patch b/patches.suse/batman-adv-prevent-TT-request-storms-by-not-sending-.patch new file mode 100644 index 0000000..b5815e4 --- /dev/null +++ b/patches.suse/batman-adv-prevent-TT-request-storms-by-not-sending-.patch @@ -0,0 +1,84 @@ +From 16116dac23396e73c01eeee97b102e4833a4b205 Mon Sep 17 00:00:00 2001 +From: Marek Lindner +Date: Sat, 12 May 2018 00:23:07 +0800 +Subject: [PATCH] batman-adv: prevent TT request storms by not sending inconsistent TT TLVLs +Git-commit: 16116dac23396e73c01eeee97b102e4833a4b205 +Patch-mainline: v4.17-rc7 +References: bsc#1051510 + +A translation table TVLV changset sent with an OGM consists +of a number of headers (one per VLAN) plus the changeset +itself (addition and/or deletion of entries). + +The per-VLAN headers are used by OGM recipients for consistency +checks. Said consistency check might determine that a full +translation table request is needed to restore consistency. If +the TT sender adds per-VLAN headers of empty VLANs into the OGM, +recipients are led to believe to have reached an inconsistent +state and thus request a full table update. The full table does +not contain empty VLANs (due to missing entries) the cycle +restarts when the next OGM is issued. + +Consequently, when the translation table TVLV headers are +composed, empty VLANs are to be excluded. + +Fixes: 21a57f6e7a3b ("batman-adv: make the TT CRC logic VLAN specific") +Signed-off-by: Marek Lindner +Signed-off-by: Sven Eckelmann +Signed-off-by: Simon Wunderlich +Acked-by: Takashi Iwai + +--- + net/batman-adv/translation-table.c | 15 ++++++++++++--- + 1 file changed, 12 insertions(+), 3 deletions(-) + +diff --git a/net/batman-adv/translation-table.c b/net/batman-adv/translation-table.c +index 23f9c212ab1e..3986551397ca 100644 +--- a/net/batman-adv/translation-table.c ++++ b/net/batman-adv/translation-table.c +@@ -931,15 +931,20 @@ batadv_tt_prepare_tvlv_local_data(struct batadv_priv *bat_priv, + struct batadv_tvlv_tt_vlan_data *tt_vlan; + struct batadv_softif_vlan *vlan; + u16 num_vlan = 0; +- u16 num_entries = 0; ++ u16 vlan_entries = 0; ++ u16 total_entries = 0; + u16 tvlv_len; + u8 *tt_change_ptr; + int change_offset; + + spin_lock_bh(&bat_priv->softif_vlan_list_lock); + hlist_for_each_entry_rcu(vlan, &bat_priv->softif_vlan_list, list) { ++ vlan_entries = atomic_read(&vlan->tt.num_entries); ++ if (vlan_entries < 1) ++ continue; ++ + num_vlan++; +- num_entries += atomic_read(&vlan->tt.num_entries); ++ total_entries += vlan_entries; + } + + change_offset = sizeof(**tt_data); +@@ -947,7 +952,7 @@ batadv_tt_prepare_tvlv_local_data(struct batadv_priv *bat_priv, + + /* if tt_len is negative, allocate the space needed by the full table */ + if (*tt_len < 0) +- *tt_len = batadv_tt_len(num_entries); ++ *tt_len = batadv_tt_len(total_entries); + + tvlv_len = *tt_len; + tvlv_len += change_offset; +@@ -964,6 +969,10 @@ batadv_tt_prepare_tvlv_local_data(struct batadv_priv *bat_priv, + + tt_vlan = (struct batadv_tvlv_tt_vlan_data *)(*tt_data + 1); + hlist_for_each_entry_rcu(vlan, &bat_priv->softif_vlan_list, list) { ++ vlan_entries = atomic_read(&vlan->tt.num_entries); ++ if (vlan_entries < 1) ++ continue; ++ + tt_vlan->vid = htons(vlan->vid); + tt_vlan->crc = htonl(vlan->tt.crc); + +-- +2.16.4 + diff --git a/patches.suse/binfmt_elf-Do-not-move-brk-for-INTERP-less-ET_EXEC.patch b/patches.suse/binfmt_elf-Do-not-move-brk-for-INTERP-less-ET_EXEC.patch new file mode 100644 index 0000000..e09a576 --- /dev/null +++ b/patches.suse/binfmt_elf-Do-not-move-brk-for-INTERP-less-ET_EXEC.patch @@ -0,0 +1,41 @@ +From: Kees Cook +Date: Thu, 26 Sep 2019 10:15:25 -0700 +Subject: binfmt_elf: Do not move brk for INTERP-less ET_EXEC + +Git-commit: 7be3cb019db1cbd5fd5ffe6d64a23fefa4b6f229 +Patch-mainline: v5.4-rc1 +References: bsc#1169013 + +When brk was moved for binaries without an interpreter, it should have +been limited to ET_DYN only. In other words, the special case was an +ET_DYN that lacks an INTERP, not just an executable that lacks INTERP. +The bug manifested for giant static executables, where the brk would end +up in the middle of the text area on 32-bit architectures. + +Reported-and-tested-by: Richard Kojedzinszky +Fixes: bbdc6076d2e5 ("binfmt_elf: move brk out of mmap when doing direct loader exec") +Cc: stable@vger.kernel.org +Signed-off-by: Kees Cook +Signed-off-by: Linus Torvalds +Signed-off-by: Mian Yousaf Kaukab +--- + fs/binfmt_elf.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c +index cec3b4146440..ad4c6b1d5074 100644 +--- a/fs/binfmt_elf.c ++++ b/fs/binfmt_elf.c +@@ -1121,7 +1121,8 @@ static int load_elf_binary(struct linux_binprm *bprm) + * (since it grows up, and may collide early with the stack + * growing down), and into the unused ELF_ET_DYN_BASE region. + */ +- if (IS_ENABLED(CONFIG_ARCH_HAS_ELF_RANDOMIZE) && !interpreter) ++ if (IS_ENABLED(CONFIG_ARCH_HAS_ELF_RANDOMIZE) && ++ loc->elf_ex.e_type == ET_DYN && !interpreter) + current->mm->brk = current->mm->start_brk = + ELF_ET_DYN_BASE; + +-- +2.16.4 + diff --git a/patches.suse/binfmt_elf-move-brk-out-of-mmap-when-doing-direct-lo.patch b/patches.suse/binfmt_elf-move-brk-out-of-mmap-when-doing-direct-lo.patch new file mode 100644 index 0000000..1661e9e --- /dev/null +++ b/patches.suse/binfmt_elf-move-brk-out-of-mmap-when-doing-direct-lo.patch @@ -0,0 +1,107 @@ +From: Kees Cook +Date: Tue, 14 May 2019 15:43:57 -0700 +Subject: binfmt_elf: move brk out of mmap when doing direct loader exec + +Git-commit: bbdc6076d2e5d07db44e74c11b01a3e27ab90b32 +Patch-mainline: v5.2-rc1 +References: bsc#1169013 + +Commmit eab09532d400 ("binfmt_elf: use ELF_ET_DYN_BASE only for PIE"), +made changes in the rare case when the ELF loader was directly invoked +(e.g to set a non-inheritable LD_LIBRARY_PATH, testing new versions of +the loader), by moving into the mmap region to avoid both ET_EXEC and +PIE binaries. This had the effect of also moving the brk region into +mmap, which could lead to the stack and brk being arbitrarily close to +each other. An unlucky process wouldn't get its requested stack size +and stack allocations could end up scribbling on the heap. + +This is illustrated here. In the case of using the loader directly, brk +(so helpfully identified as "[heap]") is allocated with the _loader_ not +the binary. For example, with ASLR entirely disabled, you can see this +more clearly: + +$ /bin/cat /proc/self/maps +555555554000-55555555c000 r-xp 00000000 ... /bin/cat +55555575b000-55555575c000 r--p 00007000 ... /bin/cat +55555575c000-55555575d000 rw-p 00008000 ... /bin/cat +55555575d000-55555577e000 rw-p 00000000 ... [heap] +... +7ffff7ff7000-7ffff7ffa000 r--p 00000000 ... [vvar] +7ffff7ffa000-7ffff7ffc000 r-xp 00000000 ... [vdso] +7ffff7ffc000-7ffff7ffd000 r--p 00027000 ... /lib/x86_64-linux-gnu/ld-2.27.so +7ffff7ffd000-7ffff7ffe000 rw-p 00028000 ... /lib/x86_64-linux-gnu/ld-2.27.so +7ffff7ffe000-7ffff7fff000 rw-p 00000000 ... +7ffffffde000-7ffffffff000 rw-p 00000000 ... [stack] + +$ /lib/x86_64-linux-gnu/ld-2.27.so /bin/cat /proc/self/maps +... +7ffff7bcc000-7ffff7bd4000 r-xp 00000000 ... /bin/cat +7ffff7bd4000-7ffff7dd3000 ---p 00008000 ... /bin/cat +7ffff7dd3000-7ffff7dd4000 r--p 00007000 ... /bin/cat +7ffff7dd4000-7ffff7dd5000 rw-p 00008000 ... /bin/cat +7ffff7dd5000-7ffff7dfc000 r-xp 00000000 ... /lib/x86_64-linux-gnu/ld-2.27.so +7ffff7fb2000-7ffff7fd6000 rw-p 00000000 ... +7ffff7ff7000-7ffff7ffa000 r--p 00000000 ... [vvar] +7ffff7ffa000-7ffff7ffc000 r-xp 00000000 ... [vdso] +7ffff7ffc000-7ffff7ffd000 r--p 00027000 ... /lib/x86_64-linux-gnu/ld-2.27.so +7ffff7ffd000-7ffff7ffe000 rw-p 00028000 ... /lib/x86_64-linux-gnu/ld-2.27.so +7ffff7ffe000-7ffff8020000 rw-p 00000000 ... [heap] +7ffffffde000-7ffffffff000 rw-p 00000000 ... [stack] + +The solution is to move brk out of mmap and into ELF_ET_DYN_BASE since +nothing is there in the direct loader case (and ET_EXEC is still far +away at 0x400000). Anything that ran before should still work (i.e. +the ultimately-launched binary already had the brk very far from its +text, so this should be no different from a COMPAT_BRK standpoint). The +only risk I see here is that if someone started to suddenly depend on +the entire memory space lower than the mmap region being available when +launching binaries via a direct loader execs which seems highly +unlikely, I'd hope: this would mean a binary would _not_ work when +exec()ed normally. + +(Note that this is only done under CONFIG_ARCH_HAS_ELF_RANDOMIZATION +when randomization is turned on.) + +Link: http://lkml.kernel.org/r/20190422225727.GA21011@beast +Link: https://lkml.kernel.org/r/CAGXu5jJ5sj3emOT2QPxQkNQk0qbU6zEfu9=Omfhx_p0nCKPSjA@mail.gmail.com +Fixes: eab09532d400 ("binfmt_elf: use ELF_ET_DYN_BASE only for PIE") +Signed-off-by: Kees Cook +Reported-by: Ali Saidi +Cc: Ali Saidi +Cc: Guenter Roeck +Cc: Michal Hocko +Cc: Matthew Wilcox +Cc: Thomas Gleixner +Cc: Jann Horn +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +Signed-off-by: Mian Yousaf Kaukab +--- + fs/binfmt_elf.c | 11 +++++++++++ + 1 file changed, 11 insertions(+) + +diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c +index 1a66b6215c80..fa9e99a962e0 100644 +--- a/fs/binfmt_elf.c ++++ b/fs/binfmt_elf.c +@@ -1134,6 +1134,17 @@ static int load_elf_binary(struct linux_binprm *bprm) + current->mm->start_stack = bprm->p; + + if ((current->flags & PF_RANDOMIZE) && (randomize_va_space > 1)) { ++ /* ++ * For architectures with ELF randomization, when executing ++ * a loader directly (i.e. no interpreter listed in ELF ++ * headers), move the brk area out of the mmap region ++ * (since it grows up, and may collide early with the stack ++ * growing down), and into the unused ELF_ET_DYN_BASE region. ++ */ ++ if (IS_ENABLED(CONFIG_ARCH_HAS_ELF_RANDOMIZE) && !interpreter) ++ current->mm->brk = current->mm->start_brk = ++ ELF_ET_DYN_BASE; ++ + current->mm->brk = current->mm->start_brk = + arch_randomize_brk(current->mm); + #ifdef compat_brk_randomized +-- +2.16.4 + diff --git a/patches.suse/blk-mq-Allow-blocking-queue-tag-iter-callbacks.patch b/patches.suse/blk-mq-Allow-blocking-queue-tag-iter-callbacks.patch index 39acb90..43fe8a7 100644 --- a/patches.suse/blk-mq-Allow-blocking-queue-tag-iter-callbacks.patch +++ b/patches.suse/blk-mq-Allow-blocking-queue-tag-iter-callbacks.patch @@ -1,9 +1,10 @@ +From 530ca2c9bd6949c72c9b5cfc330cb3dbccaa3f5b Mon Sep 17 00:00:00 2001 From: Keith Busch Date: Tue, 25 Sep 2018 10:36:20 -0600 Subject: [PATCH] blk-mq: Allow blocking queue tag iter callbacks Git-commit: 530ca2c9bd6949c72c9b5cfc330cb3dbccaa3f5b Patch-mainline: v4.19-rc6 -References: bsc#1104967,FATE#325924 +References: bsc#1167316 A recent commit runs tag iterator callbacks under the rcu read lock, but existing callbacks do not satisfy the non-blocking requirement. diff --git a/patches.suse/blktrace-Fix-potential-deadlock-between-delete-sysfs.patch b/patches.suse/blktrace-Fix-potential-deadlock-between-delete-sysfs.patch index 612e2a0..44df911 100644 --- a/patches.suse/blktrace-Fix-potential-deadlock-between-delete-sysfs.patch +++ b/patches.suse/blktrace-Fix-potential-deadlock-between-delete-sysfs.patch @@ -1,9 +1,10 @@ +From 5acb3cc2c2e9d3020a4fee43763c6463767f1572 Mon Sep 17 00:00:00 2001 From: Waiman Long Date: Wed, 20 Sep 2017 13:12:20 -0600 Subject: [PATCH] blktrace: Fix potential deadlock between delete & sysfs ops Git-commit: 5acb3cc2c2e9d3020a4fee43763c6463767f1572 Patch-mainline: v4.14-rc3 -References: bsc#1104967,FATE#325924 +References: bsc#1104967,bsc#1159285,FATE#325924 CVE-2019-19768 The lockdep code had reported the following unsafe locking scenario: @@ -43,7 +44,8 @@ Fix typo in patch subject line, and prune a comment detailing how the code used to work. Signed-off-by: Jens Axboe -Acked-by: Hannes Reinecke +Acked-by: Jan Kara + --- block/blk-core.c | 3 +++ include/linux/blkdev.h | 1 + diff --git a/patches.suse/blktrace-Protect-q-blk_trace-with-RCU.patch b/patches.suse/blktrace-Protect-q-blk_trace-with-RCU.patch new file mode 100644 index 0000000..10262e4 --- /dev/null +++ b/patches.suse/blktrace-Protect-q-blk_trace-with-RCU.patch @@ -0,0 +1,401 @@ +From c780e86dd48ef6467a1146cf7d0fe1e05a635039 Mon Sep 17 00:00:00 2001 +From: Jan Kara +Date: Thu, 6 Feb 2020 15:28:12 +0100 +Subject: [PATCH] blktrace: Protect q->blk_trace with RCU +Git-commit: c780e86dd48ef6467a1146cf7d0fe1e05a635039 +Patch-mainline: v5.6-rc4 +References: bsc#1159285 CVE-2019-19768 + +KASAN is reporting that __blk_add_trace() has a use-after-free issue +when accessing q->blk_trace. Indeed the switching of block tracing (and +thus eventual freeing of q->blk_trace) is completely unsynchronized with +the currently running tracing and thus it can happen that the blk_trace +structure is being freed just while __blk_add_trace() works on it. +Protect accesses to q->blk_trace by RCU during tracing and make sure we +wait for the end of RCU grace period when shutting down tracing. Luckily +that is rare enough event that we can afford that. Note that postponing +the freeing of blk_trace to an RCU callback should better be avoided as +it could have unexpected user visible side-effects as debugfs files +would be still existing for a short while block tracing has been shut +down. + +Link: https://bugzilla.kernel.org/show_bug.cgi?id=205711 +Cc: stable@vger.kernel.org +Reviewed-by: Chaitanya Kulkarni +Reviewed-by: Ming Lei +Tested-by: Ming Lei +Reviewed-by: Bart Van Assche +Reported-by: Tristan Madani +Signed-off-by: Jan Kara +Signed-off-by: Jens Axboe +Acked-by: Jan Kara + +--- + include/linux/blkdev.h | 2 + include/linux/blktrace_api.h | 17 ++++-- + kernel/trace/blktrace.c | 109 +++++++++++++++++++++++++++++++------------ + 3 files changed, 92 insertions(+), 36 deletions(-) + +--- a/include/linux/blkdev.h ++++ b/include/linux/blkdev.h +@@ -624,7 +624,7 @@ struct request_queue { + unsigned int sg_reserved_size; + int node; + #ifdef CONFIG_BLK_DEV_IO_TRACE +- struct blk_trace *blk_trace; ++ struct blk_trace __rcu *blk_trace; + struct mutex blk_trace_mutex; + #endif + /* +--- a/include/linux/blktrace_api.h ++++ b/include/linux/blktrace_api.h +@@ -50,9 +50,12 @@ void __trace_note_message(struct blk_tra + **/ + #define blk_add_cgroup_trace_msg(q, cg, fmt, ...) \ + do { \ +- struct blk_trace *bt = (q)->blk_trace; \ ++ struct blk_trace *bt; \ ++ rcu_read_lock(); \ ++ bt = rcu_dereference((q)->blk_trace); \ + if (unlikely(bt)) \ + __trace_note_message(bt, cg, fmt, ##__VA_ARGS__);\ ++ rcu_read_unlock(); \ + } while (0) + #define blk_add_trace_msg(q, fmt, ...) \ + blk_add_cgroup_trace_msg(q, NULL, fmt, ##__VA_ARGS__) +@@ -60,10 +63,14 @@ void __trace_note_message(struct blk_tra + + static inline bool blk_trace_note_message_enabled(struct request_queue *q) + { +- struct blk_trace *bt = q->blk_trace; +- if (likely(!bt)) +- return false; +- return bt->act_mask & BLK_TC_NOTIFY; ++ struct blk_trace *bt; ++ bool ret; ++ ++ rcu_read_lock(); ++ bt = rcu_dereference(q->blk_trace); ++ ret = bt && (bt->act_mask & BLK_TC_NOTIFY); ++ rcu_read_unlock(); ++ return ret; + } + + extern void blk_add_driver_data(struct request_queue *q, struct request *rq, +--- a/kernel/trace/blktrace.c ++++ b/kernel/trace/blktrace.c +@@ -331,6 +331,7 @@ static void blk_trace_free(struct blk_tr + + static void blk_trace_cleanup(struct blk_trace *bt) + { ++ synchronize_rcu(); + blk_trace_free(bt); + if (atomic_dec_and_test(&blk_probes_ref)) + blk_unregister_tracepoints(); +@@ -633,8 +634,10 @@ static int compat_blk_trace_setup(struct + static int __blk_trace_startstop(struct request_queue *q, int start) + { + int ret; +- struct blk_trace *bt = q->blk_trace; ++ struct blk_trace *bt; + ++ bt = rcu_dereference_protected(q->blk_trace, ++ lockdep_is_held(&q->blk_trace_mutex)); + if (bt == NULL) + return -EINVAL; + +@@ -743,8 +746,8 @@ int blk_trace_ioctl(struct block_device + void blk_trace_shutdown(struct request_queue *q) + { + mutex_lock(&q->blk_trace_mutex); +- +- if (q->blk_trace) { ++ if (rcu_dereference_protected(q->blk_trace, ++ lockdep_is_held(&q->blk_trace_mutex))) { + __blk_trace_startstop(q, 0); + __blk_trace_remove(q); + } +@@ -802,10 +805,14 @@ static void blk_add_trace_rq(struct requ + unsigned int nr_bytes, u32 what, + union kernfs_node_id *cgid) + { +- struct blk_trace *bt = rq->q->blk_trace; ++ struct blk_trace *bt; + +- if (likely(!bt)) ++ rcu_read_lock(); ++ bt = rcu_dereference(rq->q->blk_trace); ++ if (likely(!bt)) { ++ rcu_read_unlock(); + return; ++ } + + if (blk_rq_is_passthrough(rq)) + what |= BLK_TC_ACT(BLK_TC_PC); +@@ -814,6 +821,7 @@ static void blk_add_trace_rq(struct requ + + __blk_add_trace(bt, blk_rq_trace_sector(rq), nr_bytes, req_op(rq), + rq->cmd_flags, what, error, 0, NULL, cgid); ++ rcu_read_unlock(); + } + + static void blk_add_trace_rq_insert(void *ignore, +@@ -859,13 +867,18 @@ static void blk_add_trace_rq_complete(vo + static void blk_add_trace_bio(struct request_queue *q, struct bio *bio, + u32 what, int error, union kernfs_node_id *cgid) + { +- struct blk_trace *bt = q->blk_trace; ++ struct blk_trace *bt; + +- if (likely(!bt)) ++ rcu_read_lock(); ++ bt = rcu_dereference(q->blk_trace); ++ if (likely(!bt)) { ++ rcu_read_unlock(); + return; ++ } + + __blk_add_trace(bt, bio->bi_iter.bi_sector, bio->bi_iter.bi_size, + bio_op(bio), bio->bi_opf, what, error, 0, NULL, cgid); ++ rcu_read_unlock(); + } + + static void blk_add_trace_bio_bounce(void *ignore, +@@ -916,11 +929,14 @@ static void blk_add_trace_getrq(void *ig + blk_add_trace_bio(q, bio, BLK_TA_GETRQ, 0, + blk_trace_bio_get_cgid(q, bio)); + else { +- struct blk_trace *bt = q->blk_trace; ++ struct blk_trace *bt; + ++ rcu_read_lock(); ++ bt = rcu_dereference(q->blk_trace); + if (bt) + __blk_add_trace(bt, 0, 0, rw, 0, BLK_TA_GETRQ, 0, 0, + NULL, NULL); ++ rcu_read_unlock(); + } + } + +@@ -933,27 +949,35 @@ static void blk_add_trace_sleeprq(void * + blk_add_trace_bio(q, bio, BLK_TA_SLEEPRQ, 0, + blk_trace_bio_get_cgid(q, bio)); + else { +- struct blk_trace *bt = q->blk_trace; ++ struct blk_trace *bt; + ++ rcu_read_lock(); ++ bt = rcu_dereference(q->blk_trace); + if (bt) + __blk_add_trace(bt, 0, 0, rw, 0, BLK_TA_SLEEPRQ, + 0, 0, NULL, NULL); ++ rcu_read_unlock(); + } + } + + static void blk_add_trace_plug(void *ignore, struct request_queue *q) + { +- struct blk_trace *bt = q->blk_trace; ++ struct blk_trace *bt; + ++ rcu_read_lock(); ++ bt = rcu_dereference(q->blk_trace); + if (bt) + __blk_add_trace(bt, 0, 0, 0, 0, BLK_TA_PLUG, 0, 0, NULL, NULL); ++ rcu_read_unlock(); + } + + static void blk_add_trace_unplug(void *ignore, struct request_queue *q, + unsigned int depth, bool explicit) + { +- struct blk_trace *bt = q->blk_trace; ++ struct blk_trace *bt; + ++ rcu_read_lock(); ++ bt = rcu_dereference(q->blk_trace); + if (bt) { + __be64 rpdu = cpu_to_be64(depth); + u32 what; +@@ -965,14 +989,17 @@ static void blk_add_trace_unplug(void *i + + __blk_add_trace(bt, 0, 0, 0, 0, what, 0, sizeof(rpdu), &rpdu, NULL); + } ++ rcu_read_unlock(); + } + + static void blk_add_trace_split(void *ignore, + struct request_queue *q, struct bio *bio, + unsigned int pdu) + { +- struct blk_trace *bt = q->blk_trace; ++ struct blk_trace *bt; + ++ rcu_read_lock(); ++ bt = rcu_dereference(q->blk_trace); + if (bt) { + __be64 rpdu = cpu_to_be64(pdu); + +@@ -981,6 +1008,7 @@ static void blk_add_trace_split(void *ig + BLK_TA_SPLIT, bio->bi_status, sizeof(rpdu), + &rpdu, blk_trace_bio_get_cgid(q, bio)); + } ++ rcu_read_unlock(); + } + + /** +@@ -1000,11 +1028,15 @@ static void blk_add_trace_bio_remap(void + struct request_queue *q, struct bio *bio, + dev_t dev, sector_t from) + { +- struct blk_trace *bt = q->blk_trace; ++ struct blk_trace *bt; + struct blk_io_trace_remap r; + +- if (likely(!bt)) ++ rcu_read_lock(); ++ bt = rcu_dereference(q->blk_trace); ++ if (likely(!bt)) { ++ rcu_read_unlock(); + return; ++ } + + r.device_from = cpu_to_be32(dev); + r.device_to = cpu_to_be32(bio_dev(bio)); +@@ -1013,6 +1045,7 @@ static void blk_add_trace_bio_remap(void + __blk_add_trace(bt, bio->bi_iter.bi_sector, bio->bi_iter.bi_size, + bio_op(bio), bio->bi_opf, BLK_TA_REMAP, bio->bi_status, + sizeof(r), &r, blk_trace_bio_get_cgid(q, bio)); ++ rcu_read_unlock(); + } + + /** +@@ -1033,11 +1066,15 @@ static void blk_add_trace_rq_remap(void + struct request *rq, dev_t dev, + sector_t from) + { +- struct blk_trace *bt = q->blk_trace; ++ struct blk_trace *bt; + struct blk_io_trace_remap r; + +- if (likely(!bt)) ++ rcu_read_lock(); ++ bt = rcu_dereference(q->blk_trace); ++ if (likely(!bt)) { ++ rcu_read_unlock(); + return; ++ } + + r.device_from = cpu_to_be32(dev); + r.device_to = cpu_to_be32(disk_devt(rq->rq_disk)); +@@ -1046,6 +1083,7 @@ static void blk_add_trace_rq_remap(void + __blk_add_trace(bt, blk_rq_pos(rq), blk_rq_bytes(rq), + rq_data_dir(rq), 0, BLK_TA_REMAP, 0, + sizeof(r), &r, blk_trace_request_get_cgid(q, rq)); ++ rcu_read_unlock(); + } + + /** +@@ -1063,14 +1101,19 @@ void blk_add_driver_data(struct request_ + struct request *rq, + void *data, size_t len) + { +- struct blk_trace *bt = q->blk_trace; ++ struct blk_trace *bt; + +- if (likely(!bt)) ++ rcu_read_lock(); ++ bt = rcu_dereference(q->blk_trace); ++ if (likely(!bt)) { ++ rcu_read_unlock(); + return; ++ } + + __blk_add_trace(bt, blk_rq_trace_sector(rq), blk_rq_bytes(rq), 0, 0, + BLK_TA_DRV_DATA, 0, len, data, + blk_trace_request_get_cgid(q, rq)); ++ rcu_read_unlock(); + } + EXPORT_SYMBOL_GPL(blk_add_driver_data); + +@@ -1761,6 +1804,7 @@ static ssize_t sysfs_blk_trace_attr_show + struct hd_struct *p = dev_to_part(dev); + struct request_queue *q; + struct block_device *bdev; ++ struct blk_trace *bt; + ssize_t ret = -ENXIO; + + bdev = bdget(part_devt(p)); +@@ -1773,21 +1817,23 @@ static ssize_t sysfs_blk_trace_attr_show + + mutex_lock(&q->blk_trace_mutex); + ++ bt = rcu_dereference_protected(q->blk_trace, ++ lockdep_is_held(&q->blk_trace_mutex)); + if (attr == &dev_attr_enable) { +- ret = sprintf(buf, "%u\n", !!q->blk_trace); ++ ret = sprintf(buf, "%u\n", !!bt); + goto out_unlock_bdev; + } + +- if (q->blk_trace == NULL) ++ if (bt == NULL) + ret = sprintf(buf, "disabled\n"); + else if (attr == &dev_attr_act_mask) +- ret = blk_trace_mask2str(buf, q->blk_trace->act_mask); ++ ret = blk_trace_mask2str(buf, bt->act_mask); + else if (attr == &dev_attr_pid) +- ret = sprintf(buf, "%u\n", q->blk_trace->pid); ++ ret = sprintf(buf, "%u\n", bt->pid); + else if (attr == &dev_attr_start_lba) +- ret = sprintf(buf, "%llu\n", q->blk_trace->start_lba); ++ ret = sprintf(buf, "%llu\n", bt->start_lba); + else if (attr == &dev_attr_end_lba) +- ret = sprintf(buf, "%llu\n", q->blk_trace->end_lba); ++ ret = sprintf(buf, "%llu\n", bt->end_lba); + + out_unlock_bdev: + mutex_unlock(&q->blk_trace_mutex); +@@ -1804,6 +1850,7 @@ static ssize_t sysfs_blk_trace_attr_stor + struct block_device *bdev; + struct request_queue *q; + struct hd_struct *p; ++ struct blk_trace *bt; + u64 value; + ssize_t ret = -EINVAL; + +@@ -1834,8 +1881,10 @@ static ssize_t sysfs_blk_trace_attr_stor + + mutex_lock(&q->blk_trace_mutex); + ++ bt = rcu_dereference_protected(q->blk_trace, ++ lockdep_is_held(&q->blk_trace_mutex)); + if (attr == &dev_attr_enable) { +- if (!!value == !!q->blk_trace) { ++ if (!!value == !!bt) { + ret = 0; + goto out_unlock_bdev; + } +@@ -1847,18 +1896,18 @@ static ssize_t sysfs_blk_trace_attr_stor + } + + ret = 0; +- if (q->blk_trace == NULL) ++ if (bt == NULL) + ret = blk_trace_setup_queue(q, bdev); + + if (ret == 0) { + if (attr == &dev_attr_act_mask) +- q->blk_trace->act_mask = value; ++ bt->act_mask = value; + else if (attr == &dev_attr_pid) +- q->blk_trace->pid = value; ++ bt->pid = value; + else if (attr == &dev_attr_start_lba) +- q->blk_trace->start_lba = value; ++ bt->start_lba = value; + else if (attr == &dev_attr_end_lba) +- q->blk_trace->end_lba = value; ++ bt->end_lba = value; + } + + out_unlock_bdev: diff --git a/patches.suse/blktrace-fix-dereference-after-null-check.patch b/patches.suse/blktrace-fix-dereference-after-null-check.patch new file mode 100644 index 0000000..e61f77b --- /dev/null +++ b/patches.suse/blktrace-fix-dereference-after-null-check.patch @@ -0,0 +1,70 @@ +From 153031a301bb07194e9c37466cfce8eacb977621 Mon Sep 17 00:00:00 2001 +From: Cengiz Can +Date: Wed, 4 Mar 2020 13:58:19 +0300 +Subject: [PATCH] blktrace: fix dereference after null check +Git-commit: 153031a301bb07194e9c37466cfce8eacb977621 +Patch-mainline: v5.6-rc5 +References: bsc#1159285 + +There was a recent change in blktrace.c that added a RCU protection to +`q->blk_trace` in order to fix a use-after-free issue during access. + +However the change missed an edge case that can lead to dereferencing of +`bt` pointer even when it's NULL: + +Coverity static analyzer marked this as a FORWARD_NULL issue with CID +1460458. + +``` +/kernel/trace/blktrace.c: 1904 in sysfs_blk_trace_attr_store() +1898 ret = 0; +1899 if (bt == NULL) +1900 ret = blk_trace_setup_queue(q, bdev); +1901 +1902 if (ret == 0) { +1903 if (attr == &dev_attr_act_mask) +>>> CID 1460458: Null pointer dereferences (FORWARD_NULL) +>>> Dereferencing null pointer "bt". +1904 bt->act_mask = value; +1905 else if (attr == &dev_attr_pid) +1906 bt->pid = value; +1907 else if (attr == &dev_attr_start_lba) +1908 bt->start_lba = value; +1909 else if (attr == &dev_attr_end_lba) +``` + +Added a reassignment with RCU annotation to fix the issue. + +Fixes: c780e86dd48 ("blktrace: Protect q->blk_trace with RCU") +Cc: stable@vger.kernel.org +Reviewed-by: Ming Lei +Reviewed-by: Bob Liu +Reviewed-by: Steven Rostedt (VMware) +Signed-off-by: Cengiz Can +Signed-off-by: Jens Axboe +Acked-by: Jan Kara + +--- + kernel/trace/blktrace.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/kernel/trace/blktrace.c b/kernel/trace/blktrace.c +index 4560878f0bac..ca39dc3230cb 100644 +--- a/kernel/trace/blktrace.c ++++ b/kernel/trace/blktrace.c +@@ -1896,8 +1896,11 @@ static ssize_t sysfs_blk_trace_attr_store(struct device *dev, + } + + ret = 0; +- if (bt == NULL) ++ if (bt == NULL) { + ret = blk_trace_setup_queue(q, bdev); ++ bt = rcu_dereference_protected(q->blk_trace, ++ lockdep_is_held(&q->blk_trace_mutex)); ++ } + + if (ret == 0) { + if (attr == &dev_attr_act_mask) +-- +2.16.4 + diff --git a/patches.suse/blktrace-fix-trace-mutex-deadlock.patch b/patches.suse/blktrace-fix-trace-mutex-deadlock.patch new file mode 100644 index 0000000..4b9f9ac --- /dev/null +++ b/patches.suse/blktrace-fix-trace-mutex-deadlock.patch @@ -0,0 +1,46 @@ +From 2967acbb257a6a9bf912f4778b727e00972eac9b Mon Sep 17 00:00:00 2001 +From: Jens Axboe +Date: Sun, 19 Nov 2017 11:52:55 -0700 +Subject: [PATCH] blktrace: fix trace mutex deadlock +Git-commit: 2967acbb257a6a9bf912f4778b727e00972eac9b +Patch-mainline: v4.15-rc2 +References: bsc#1159285 + +A previous commit changed the locking around registration/cleanup, +but direct callers of blk_trace_remove() were missed. This means +that if we hit the error path in setup, we will deadlock on +attempting to re-acquire the queue trace mutex. + +Fixes: 1f2cac107c59 ("blktrace: fix unlocked access to init/start-stop/teardown") +Signed-off-by: Jens Axboe +Acked-by: Jan Kara + +--- + kernel/trace/blktrace.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/kernel/trace/blktrace.c b/kernel/trace/blktrace.c +index c5987d4c5f23..987d9a9ae283 100644 +--- a/kernel/trace/blktrace.c ++++ b/kernel/trace/blktrace.c +@@ -591,7 +591,7 @@ static int __blk_trace_setup(struct request_queue *q, char *name, dev_t dev, + return ret; + + if (copy_to_user(arg, &buts, sizeof(buts))) { +- blk_trace_remove(q); ++ __blk_trace_remove(q); + return -EFAULT; + } + return 0; +@@ -637,7 +637,7 @@ static int compat_blk_trace_setup(struct request_queue *q, char *name, + return ret; + + if (copy_to_user(arg, &buts.name, ARRAY_SIZE(buts.name))) { +- blk_trace_remove(q); ++ __blk_trace_remove(q); + return -EFAULT; + } + +-- +2.16.4 + diff --git a/patches.suse/blktrace-fix-unlocked-access-to-init-start-stop-tear.patch b/patches.suse/blktrace-fix-unlocked-access-to-init-start-stop-tear.patch new file mode 100644 index 0000000..bf8e8e6 --- /dev/null +++ b/patches.suse/blktrace-fix-unlocked-access-to-init-start-stop-tear.patch @@ -0,0 +1,150 @@ +From 1f2cac107c591c24b60b115d6050adc213d10fc0 Mon Sep 17 00:00:00 2001 +From: Jens Axboe +Date: Sun, 5 Nov 2017 09:13:48 -0700 +Subject: [PATCH] blktrace: fix unlocked access to init/start-stop/teardown +Git-commit: 1f2cac107c591c24b60b115d6050adc213d10fc0 +Patch-mainline: v4.15-rc1 +References: bsc#1159285 CVE-2019-19768 + +sg.c calls into the blktrace functions without holding the proper queue +mutex for doing setup, start/stop, or teardown. + +Add internal unlocked variants, and export the ones that do the proper +locking. + +Fixes: 6da127ad0918 ("blktrace: Add blktrace ioctls to SCSI generic devices") +Tested-by: Dmitry Vyukov +Signed-off-by: Jens Axboe +Acked-by: Jan Kara + +--- + kernel/trace/blktrace.c | 58 +++++++++++++++++++++++++++++++++++++++--------- + 1 file changed, 48 insertions(+), 10 deletions(-) + +--- a/kernel/trace/blktrace.c ++++ b/kernel/trace/blktrace.c +@@ -312,7 +312,7 @@ static void blk_trace_cleanup(struct blk + blk_unregister_tracepoints(); + } + +-int blk_trace_remove(struct request_queue *q) ++static int __blk_trace_remove(struct request_queue *q) + { + struct blk_trace *bt; + +@@ -325,6 +325,17 @@ int blk_trace_remove(struct request_queu + + return 0; + } ++ ++int blk_trace_remove(struct request_queue *q) ++{ ++ int ret; ++ ++ mutex_lock(&q->blk_trace_mutex); ++ ret = __blk_trace_remove(q); ++ mutex_unlock(&q->blk_trace_mutex); ++ ++ return ret; ++} + EXPORT_SYMBOL_GPL(blk_trace_remove); + + static ssize_t blk_dropped_read(struct file *filp, char __user *buffer, +@@ -526,9 +537,8 @@ err: + return ret; + } + +-int blk_trace_setup(struct request_queue *q, char *name, dev_t dev, +- struct block_device *bdev, +- char __user *arg) ++static int __blk_trace_setup(struct request_queue *q, char *name, dev_t dev, ++ struct block_device *bdev, char __user *arg) + { + struct blk_user_trace_setup buts; + int ret; +@@ -547,6 +557,19 @@ int blk_trace_setup(struct request_queue + } + return 0; + } ++ ++int blk_trace_setup(struct request_queue *q, char *name, dev_t dev, ++ struct block_device *bdev, ++ char __user *arg) ++{ ++ int ret; ++ ++ mutex_lock(&q->blk_trace_mutex); ++ ret = __blk_trace_setup(q, name, dev, bdev, arg); ++ mutex_unlock(&q->blk_trace_mutex); ++ ++ return ret; ++} + EXPORT_SYMBOL_GPL(blk_trace_setup); + + #if defined(CONFIG_COMPAT) && defined(CONFIG_X86_64) +@@ -583,7 +606,7 @@ static int compat_blk_trace_setup(struct + } + #endif + +-int blk_trace_startstop(struct request_queue *q, int start) ++static int __blk_trace_startstop(struct request_queue *q, int start) + { + int ret; + struct blk_trace *bt = q->blk_trace; +@@ -622,6 +645,17 @@ int blk_trace_startstop(struct request_q + + return ret; + } ++ ++int blk_trace_startstop(struct request_queue *q, int start) ++{ ++ int ret; ++ ++ mutex_lock(&q->blk_trace_mutex); ++ ret = __blk_trace_startstop(q, start); ++ mutex_unlock(&q->blk_trace_mutex); ++ ++ return ret; ++} + EXPORT_SYMBOL_GPL(blk_trace_startstop); + + /* +@@ -652,7 +686,7 @@ int blk_trace_ioctl(struct block_device + switch (cmd) { + case BLKTRACESETUP: + bdevname(bdev, b); +- ret = blk_trace_setup(q, b, bdev->bd_dev, bdev, arg); ++ ret = __blk_trace_setup(q, b, bdev->bd_dev, bdev, arg); + break; + #if defined(CONFIG_COMPAT) && defined(CONFIG_X86_64) + case BLKTRACESETUP32: +@@ -663,10 +697,10 @@ int blk_trace_ioctl(struct block_device + case BLKTRACESTART: + start = 1; + case BLKTRACESTOP: +- ret = blk_trace_startstop(q, start); ++ ret = __blk_trace_startstop(q, start); + break; + case BLKTRACETEARDOWN: +- ret = blk_trace_remove(q); ++ ret = __blk_trace_remove(q); + break; + default: + ret = -ENOTTY; +@@ -684,10 +718,14 @@ int blk_trace_ioctl(struct block_device + **/ + void blk_trace_shutdown(struct request_queue *q) + { ++ mutex_lock(&q->blk_trace_mutex); ++ + if (q->blk_trace) { +- blk_trace_startstop(q, 0); +- blk_trace_remove(q); ++ __blk_trace_startstop(q, 0); ++ __blk_trace_remove(q); + } ++ ++ mutex_unlock(&q->blk_trace_mutex); + } + + #ifdef CONFIG_BLK_CGROUP diff --git a/patches.suse/bnxt_en-Fix-NTUPLE-firmware-command-failures.patch b/patches.suse/bnxt_en-Fix-NTUPLE-firmware-command-failures.patch new file mode 100644 index 0000000..9867e27 --- /dev/null +++ b/patches.suse/bnxt_en-Fix-NTUPLE-firmware-command-failures.patch @@ -0,0 +1,32 @@ +From: Michael Chan +Date: Fri, 17 Jan 2020 00:32:45 -0500 +Subject: bnxt_en: Fix NTUPLE firmware command failures. +Patch-mainline: v5.5-rc7 +Git-commit: ceb3284c588eee5ea256c70e4d8d7cf399b8134e +References: bsc#1104745 FATE#325918 + +The NTUPLE related firmware commands are sent to the wrong firmware +channel, causing all these commands to fail on new firmware that +supports the new firmware channel. Fix it by excluding the 3 +NTUPLE firmware commands from the list for the new firmware channel. + +Fixes: 760b6d33410c ("bnxt_en: Add support for 2nd firmware message channel.") +Signed-off-by: Michael Chan +Signed-off-by: David S. Miller +Acked-by: Thomas Bogendoerfer +--- + drivers/net/ethernet/broadcom/bnxt/bnxt.h | 3 --- + 1 file changed, 3 deletions(-) + +--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.h ++++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.h +@@ -1702,9 +1702,6 @@ static inline bool bnxt_cfa_hwrm_message + case HWRM_CFA_ENCAP_RECORD_FREE: + case HWRM_CFA_DECAP_FILTER_ALLOC: + case HWRM_CFA_DECAP_FILTER_FREE: +- case HWRM_CFA_NTUPLE_FILTER_ALLOC: +- case HWRM_CFA_NTUPLE_FILTER_FREE: +- case HWRM_CFA_NTUPLE_FILTER_CFG: + case HWRM_CFA_EM_FLOW_ALLOC: + case HWRM_CFA_EM_FLOW_FREE: + case HWRM_CFA_EM_FLOW_CFG: diff --git a/patches.suse/bnxt_en-Fix-TC-queue-mapping.patch b/patches.suse/bnxt_en-Fix-TC-queue-mapping.patch new file mode 100644 index 0000000..c70bc01 --- /dev/null +++ b/patches.suse/bnxt_en-Fix-TC-queue-mapping.patch @@ -0,0 +1,32 @@ +From: Michael Chan +Date: Sun, 2 Feb 2020 02:41:38 -0500 +Subject: bnxt_en: Fix TC queue mapping. +Git-commit: 18e4960c18f484ac288f41b43d0e6c4c88e6ea78 +Patch-mainline: 5.6-rc1 +References: networking-stable-20_02_05 + +The driver currently only calls netdev_set_tc_queue when the number of +TCs is greater than 1. Instead, the comparison should be greater than +or equal to 1. Even with 1 TC, we need to set the queue mapping. + +This bug can cause warnings when the number of TCs is changed back to 1. + +Fixes: 7809592d3e2e ("bnxt_en: Enable MSIX early in bnxt_init_one().") +Signed-off-by: Michael Chan +Signed-off-by: Jakub Kicinski +Signed-off-by: Jiri Slaby +--- + drivers/net/ethernet/broadcom/bnxt/bnxt.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c ++++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c +@@ -5796,7 +5796,7 @@ static void bnxt_setup_msix(struct bnxt + int tcs, i; + + tcs = netdev_get_num_tc(dev); +- if (tcs > 1) { ++ if (tcs) { + int i, off, count; + + for (i = 0; i < tcs; i++) { diff --git a/patches.suse/bnxt_en-Improve-device-shutdown-method.patch b/patches.suse/bnxt_en-Improve-device-shutdown-method.patch new file mode 100644 index 0000000..294c934 --- /dev/null +++ b/patches.suse/bnxt_en-Improve-device-shutdown-method.patch @@ -0,0 +1,35 @@ +From: Vasundhara Volam +Date: Thu, 20 Feb 2020 17:26:34 -0500 +Subject: bnxt_en: Improve device shutdown method. +Patch-mainline: v5.6-rc3 +Git-commit: 5567ae4a8d569d996d0d88d0eceb76205e4c7ce5 +References: bsc#1104745 FATE#325918 + +Especially when bnxt_shutdown() is called during kexec, we need to +disable MSIX and disable Bus Master to completely quiesce the device. +Make these 2 calls unconditionally in the shutdown method. + +Fixes: c20dc142dd7b ("bnxt_en: Disable bus master during PCI shutdown and driver unload.") +Signed-off-by: Vasundhara Volam +Signed-off-by: Michael Chan +Signed-off-by: David S. Miller +Acked-by: Thomas Bogendoerfer +--- + drivers/net/ethernet/broadcom/bnxt/bnxt.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c ++++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c +@@ -10707,10 +10707,10 @@ static void bnxt_shutdown(struct pci_dev + dev_close(dev); + + bnxt_ulp_shutdown(bp); ++ bnxt_clear_int_mode(bp); ++ pci_disable_device(pdev); + + if (system_state == SYSTEM_POWER_OFF) { +- bnxt_clear_int_mode(bp); +- pci_disable_device(pdev); + pci_wake_from_d3(pdev, bp->wol); + pci_set_power_state(pdev, PCI_D3hot); + } diff --git a/patches.suse/bnxt_en-Issue-PCIe-FLR-in-kdump-kernel-to-cleanup-pe.patch b/patches.suse/bnxt_en-Issue-PCIe-FLR-in-kdump-kernel-to-cleanup-pe.patch new file mode 100644 index 0000000..54ec2dd --- /dev/null +++ b/patches.suse/bnxt_en-Issue-PCIe-FLR-in-kdump-kernel-to-cleanup-pe.patch @@ -0,0 +1,37 @@ +From: Vasundhara Volam +Date: Thu, 20 Feb 2020 17:26:35 -0500 +Subject: bnxt_en: Issue PCIe FLR in kdump kernel to cleanup pending DMAs. +Patch-mainline: v5.6-rc3 +Git-commit: 8743db4a9acfd51f805ac0c87bcaae92c42d1061 +References: bsc#1134090 jsc#SLE-5954 + +If crashed kernel does not shutdown the NIC properly, PCIe FLR +is required in the kdump kernel in order to initialize all the +functions properly. + +Fixes: d629522e1d66 ("bnxt_en: Reduce memory usage when running in kdump kernel.") +Signed-off-by: Vasundhara Volam +Signed-off-by: Michael Chan +Signed-off-by: David S. Miller +Acked-by: Thomas Bogendoerfer +--- + drivers/net/ethernet/broadcom/bnxt/bnxt.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c ++++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c +@@ -10454,6 +10454,14 @@ static int bnxt_init_one(struct pci_dev + if (version_printed++ == 0) + pr_info("%s", version); + ++ /* Clear any pending DMA transactions from crash kernel ++ * while loading driver in capture kernel. ++ */ ++ if (is_kdump_kernel()) { ++ pci_clear_master(pdev); ++ pcie_flr(pdev); ++ } ++ + max_irqs = bnxt_get_max_irq(pdev); + dev = alloc_etherdev_mq(sizeof(*bp), max_irqs); + if (!dev) diff --git a/patches.suse/bnxt_en-Support-all-variants-of-the-5750X-chip-famil.patch b/patches.suse/bnxt_en-Support-all-variants-of-the-5750X-chip-famil.patch new file mode 100644 index 0000000..06017fa --- /dev/null +++ b/patches.suse/bnxt_en-Support-all-variants-of-the-5750X-chip-famil.patch @@ -0,0 +1,41 @@ +From: Michael Chan +Date: Mon, 29 Jul 2019 06:10:32 -0400 +Subject: bnxt_en: Support all variants of the 5750X chip family. +Patch-mainline: v5.4-rc1 +Git-commit: 1dc88b97a020148c0eea6c595d511a19c2fab347 +References: bsc#1167216 + +Define the 57508, 57504, and 57502 chip IDs that are all part of the +BNXT_CHIP_P5 family of chips. + +Signed-off-by: Michael Chan +Signed-off-by: David S. Miller +Acked-by: Thomas Bogendoerfer +--- + drivers/net/ethernet/broadcom/bnxt/bnxt.h | 8 ++++++-- + 1 file changed, 6 insertions(+), 2 deletions(-) + +--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.h ++++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.h +@@ -1272,7 +1272,9 @@ struct bnxt { + + #define CHIP_NUM_5745X 0xd730 + +-#define CHIP_NUM_57500 0x1750 ++#define CHIP_NUM_57508 0x1750 ++#define CHIP_NUM_57504 0x1751 ++#define CHIP_NUM_57502 0x1752 + + #define CHIP_NUM_58802 0xd802 + #define CHIP_NUM_58804 0xd804 +@@ -1373,7 +1375,9 @@ struct bnxt { + + /* Chip class phase 5 */ + #define BNXT_CHIP_P5(bp) \ +- ((bp)->chip_num == CHIP_NUM_57500) ++ ((bp)->chip_num == CHIP_NUM_57508 || \ ++ (bp)->chip_num == CHIP_NUM_57504 || \ ++ (bp)->chip_num == CHIP_NUM_57502) + + /* Chip class phase 4.x */ + #define BNXT_CHIP_P4(bp) \ diff --git a/patches.suse/bonding-alb-properly-access-headers-in-bond_alb_xmit.patch b/patches.suse/bonding-alb-properly-access-headers-in-bond_alb_xmit.patch new file mode 100644 index 0000000..d21644a --- /dev/null +++ b/patches.suse/bonding-alb-properly-access-headers-in-bond_alb_xmit.patch @@ -0,0 +1,174 @@ +From: Eric Dumazet +Date: Tue, 4 Feb 2020 19:26:05 -0800 +Subject: bonding/alb: properly access headers in bond_alb_xmit() +Git-commit: 38f88c45404293bbc027b956def6c10cbd45c616 +Patch-mainline: 5.6-rc1 +References: networking-stable-20_02_09 + +syzbot managed to send an IPX packet through bond_alb_xmit() +and af_packet and triggered a use-after-free. + +First, bond_alb_xmit() was using ipx_hdr() helper to reach +the IPX header, but ipx_hdr() was using the transport offset +instead of the network offset. In the particular syzbot +report transport offset was 0xFFFF + +This patch removes ipx_hdr() since it was only (mis)used from bonding. + +Then we need to make sure IPv4/IPv6/IPX headers are pulled +in skb->head before dereferencing anything. + +BUG: KASAN: use-after-free in bond_alb_xmit+0x153a/0x1590 drivers/net/bonding/bond_alb.c:1452 +Read of size 2 at addr ffff8801ce56dfff by task syz-executor.2/18108 + (if (ipx_hdr(skb)->ipx_checksum != IPX_NO_CHECKSUM) ...) + +Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011 +Call Trace: + [] __dump_stack lib/dump_stack.c:17 [inline] + [] dump_stack+0x14d/0x20b lib/dump_stack.c:53 + [] print_address_description+0x6f/0x20b mm/kasan/report.c:282 + [] kasan_report_error mm/kasan/report.c:380 [inline] + [] kasan_report mm/kasan/report.c:438 [inline] + [] kasan_report.cold+0x8c/0x2a0 mm/kasan/report.c:422 + [] __asan_report_load_n_noabort+0xf/0x20 mm/kasan/report.c:469 + [] bond_alb_xmit+0x153a/0x1590 drivers/net/bonding/bond_alb.c:1452 + [] __bond_start_xmit drivers/net/bonding/bond_main.c:4199 [inline] + [] bond_start_xmit+0x4f4/0x1570 drivers/net/bonding/bond_main.c:4224 + [] __netdev_start_xmit include/linux/netdevice.h:4525 [inline] + [] netdev_start_xmit include/linux/netdevice.h:4539 [inline] + [] xmit_one net/core/dev.c:3611 [inline] + [] dev_hard_start_xmit+0x168/0x910 net/core/dev.c:3627 + [] __dev_queue_xmit+0x1f55/0x33b0 net/core/dev.c:4238 + [] dev_queue_xmit+0x18/0x20 net/core/dev.c:4278 + [] packet_snd net/packet/af_packet.c:3226 [inline] + [] packet_sendmsg+0x4919/0x70b0 net/packet/af_packet.c:3252 + [] sock_sendmsg_nosec net/socket.c:673 [inline] + [] sock_sendmsg+0x12c/0x160 net/socket.c:684 + [] __sys_sendto+0x262/0x380 net/socket.c:1996 + [] SYSC_sendto net/socket.c:2008 [inline] + [] SyS_sendto+0x40/0x60 net/socket.c:2004 + +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Signed-off-by: Eric Dumazet +Reported-by: syzbot +Cc: Jay Vosburgh +Cc: Veaceslav Falico +Cc: Andy Gospodarek +Signed-off-by: David S. Miller +Signed-off-by: Jiri Slaby +--- + drivers/net/bonding/bond_alb.c | 44 +++++++++++++++++++++++++++++------------ + include/net/ipx.h | 5 ---- + 2 files changed, 32 insertions(+), 17 deletions(-) + +--- a/drivers/net/bonding/bond_alb.c ++++ b/drivers/net/bonding/bond_alb.c +@@ -1404,26 +1404,31 @@ int bond_alb_xmit(struct sk_buff *skb, s + bool do_tx_balance = true; + u32 hash_index = 0; + const u8 *hash_start = NULL; +- struct ipv6hdr *ip6hdr; + + skb_reset_mac_header(skb); + eth_data = eth_hdr(skb); + + switch (ntohs(skb->protocol)) { + case ETH_P_IP: { +- const struct iphdr *iph = ip_hdr(skb); ++ const struct iphdr *iph; + + if (ether_addr_equal_64bits(eth_data->h_dest, mac_bcast) || +- (iph->daddr == ip_bcast) || +- (iph->protocol == IPPROTO_IGMP)) { ++ !pskb_network_may_pull(skb, sizeof(*iph))) { ++ do_tx_balance = false; ++ break; ++ } ++ iph = ip_hdr(skb); ++ if (iph->daddr == ip_bcast || iph->protocol == IPPROTO_IGMP) { + do_tx_balance = false; + break; + } + hash_start = (char *)&(iph->daddr); + hash_size = sizeof(iph->daddr); +- } + break; +- case ETH_P_IPV6: ++ } ++ case ETH_P_IPV6: { ++ const struct ipv6hdr *ip6hdr; ++ + /* IPv6 doesn't really use broadcast mac address, but leave + * that here just in case. + */ +@@ -1440,7 +1445,11 @@ int bond_alb_xmit(struct sk_buff *skb, s + break; + } + +- /* Additianally, DAD probes should not be tx-balanced as that ++ if (!pskb_network_may_pull(skb, sizeof(*ip6hdr))) { ++ do_tx_balance = false; ++ break; ++ } ++ /* Additionally, DAD probes should not be tx-balanced as that + * will lead to false positives for duplicate addresses and + * prevent address configuration from working. + */ +@@ -1450,17 +1459,26 @@ int bond_alb_xmit(struct sk_buff *skb, s + break; + } + +- hash_start = (char *)&(ipv6_hdr(skb)->daddr); +- hash_size = sizeof(ipv6_hdr(skb)->daddr); ++ hash_start = (char *)&ip6hdr->daddr; ++ hash_size = sizeof(ip6hdr->daddr); + break; +- case ETH_P_IPX: +- if (ipx_hdr(skb)->ipx_checksum != IPX_NO_CHECKSUM) { ++ } ++ case ETH_P_IPX: { ++ const struct ipxhdr *ipxhdr; ++ ++ if (pskb_network_may_pull(skb, sizeof(*ipxhdr))) { ++ do_tx_balance = false; ++ break; ++ } ++ ipxhdr = (struct ipxhdr *)skb_network_header(skb); ++ ++ if (ipxhdr->ipx_checksum != IPX_NO_CHECKSUM) { + /* something is wrong with this packet */ + do_tx_balance = false; + break; + } + +- if (ipx_hdr(skb)->ipx_type != IPX_TYPE_NCP) { ++ if (ipxhdr->ipx_type != IPX_TYPE_NCP) { + /* The only protocol worth balancing in + * this family since it has an "ARP" like + * mechanism +@@ -1469,9 +1487,11 @@ int bond_alb_xmit(struct sk_buff *skb, s + break; + } + ++ eth_data = eth_hdr(skb); + hash_start = (char *)eth_data->h_dest; + hash_size = ETH_ALEN; + break; ++ } + case ETH_P_ARP: + do_tx_balance = false; + if (bond_info->rlb_enabled) +--- a/include/net/ipx.h ++++ b/include/net/ipx.h +@@ -45,11 +45,6 @@ struct ipxhdr { + /* From af_ipx.c */ + extern int sysctl_ipx_pprop_broadcasting; + +-static __inline__ struct ipxhdr *ipx_hdr(struct sk_buff *skb) +-{ +- return (struct ipxhdr *)skb_transport_header(skb); +-} +- + struct ipx_interface { + /* IPX address */ + __be32 if_netnum; diff --git a/patches.suse/bpf-Explicitly-memset-some-bpf-info-structures-decla.patch b/patches.suse/bpf-Explicitly-memset-some-bpf-info-structures-decla.patch new file mode 100644 index 0000000..d4689f6 --- /dev/null +++ b/patches.suse/bpf-Explicitly-memset-some-bpf-info-structures-decla.patch @@ -0,0 +1,79 @@ +From: Greg Kroah-Hartman +Date: Fri, 20 Mar 2020 17:22:58 +0100 +Subject: bpf: Explicitly memset some bpf info structures declared on the stack +Patch-mainline: v5.6 +Git-commit: 5c6f25887963f15492b604dd25cb149c501bbabf +References: bsc#1083647 + +Trying to initialize a structure with "= {};" will not always clean out +all padding locations in a structure. So be explicit and call memset to +initialize everything for a number of bpf information structures that +are then copied from userspace, sometimes from smaller memory locations +than the size of the structure. + +Reported-by: Daniel Borkmann +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Daniel Borkmann +Acked-by: Yonghong Song +Link: https://lore.kernel.org/bpf/20200320162258.GA794295@kroah.com +Acked-by: Gary Lin +--- + kernel/bpf/btf.c | 3 ++- + kernel/bpf/syscall.c | 6 ++++-- + 2 files changed, 6 insertions(+), 3 deletions(-) + +--- a/kernel/bpf/btf.c ++++ b/kernel/bpf/btf.c +@@ -2627,7 +2627,7 @@ int btf_get_info_by_fd(const struct btf + union bpf_attr __user *uattr) + { + struct bpf_btf_info __user *uinfo; +- struct bpf_btf_info info = {}; ++ struct bpf_btf_info info; + u32 info_copy, btf_copy; + void __user *ubtf; + u32 uinfo_len; +@@ -2636,6 +2636,7 @@ int btf_get_info_by_fd(const struct btf + uinfo_len = attr->info.info_len; + + info_copy = min_t(u32, uinfo_len, sizeof(info)); ++ memset(&info, 0, sizeof(info)); + if (copy_from_user(&info, uinfo, info_copy)) + return -EFAULT; + +--- a/kernel/bpf/syscall.c ++++ b/kernel/bpf/syscall.c +@@ -1896,7 +1896,7 @@ static int bpf_prog_get_info_by_fd(struc + union bpf_attr __user *uattr) + { + struct bpf_prog_info __user *uinfo = u64_to_user_ptr(attr->info.info); +- struct bpf_prog_info info = {}; ++ struct bpf_prog_info info; + u32 info_len = attr->info.info_len; + char __user *uinsns; + u32 ulen; +@@ -1907,6 +1907,7 @@ static int bpf_prog_get_info_by_fd(struc + return err; + info_len = min_t(u32, sizeof(info), info_len); + ++ memset(&info, 0, sizeof(info)); + if (copy_from_user(&info, uinfo, info_len)) + return -EFAULT; + +@@ -2088,7 +2089,7 @@ static int bpf_map_get_info_by_fd(struct + union bpf_attr __user *uattr) + { + struct bpf_map_info __user *uinfo = u64_to_user_ptr(attr->info.info); +- struct bpf_map_info info = {}; ++ struct bpf_map_info info; + u32 info_len = attr->info.info_len; + int err; + +@@ -2097,6 +2098,7 @@ static int bpf_map_get_info_by_fd(struct + return err; + info_len = min_t(u32, sizeof(info), info_len); + ++ memset(&info, 0, sizeof(info)); + info.type = map->map_type; + info.id = map->id; + info.key_size = map->key_size; diff --git a/patches.suse/bpf-Explicitly-memset-the-bpf_attr-structure.patch b/patches.suse/bpf-Explicitly-memset-the-bpf_attr-structure.patch new file mode 100644 index 0000000..266bdbd --- /dev/null +++ b/patches.suse/bpf-Explicitly-memset-the-bpf_attr-structure.patch @@ -0,0 +1,51 @@ +From: Greg Kroah-Hartman +Date: Fri, 20 Mar 2020 10:48:13 +0100 +Subject: bpf: Explicitly memset the bpf_attr structure +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit +Patch-mainline: v5.6 +Git-commit: 8096f229421f7b22433775e928d506f0342e5907 +References: bsc#1083647 + +For the bpf syscall, we are relying on the compiler to properly zero out +the bpf_attr union that we copy userspace data into. Unfortunately that +doesn't always work properly, padding and other oddities might not be +correctly zeroed, and in some tests odd things have been found when the +stack is pre-initialized to other values. + +Fix this by explicitly memsetting the structure to 0 before using it. + +Reported-by: Maciej Żenczykowski +Reported-by: John Stultz +Reported-by: Alexander Potapenko +Reported-by: Alistair Delva +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Daniel Borkmann +Acked-by: Yonghong Song +Link: https://android-review.googlesource.com/c/kernel/common/+/1235490 +Link: https://lore.kernel.org/bpf/20200320094813.GA421650@kroah.com +Acked-by: Gary Lin +--- + kernel/bpf/syscall.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/kernel/bpf/syscall.c ++++ b/kernel/bpf/syscall.c +@@ -1427,7 +1427,7 @@ static int bpf_obj_get_info_by_fd(const + + SYSCALL_DEFINE3(bpf, int, cmd, union bpf_attr __user *, uattr, unsigned int, size) + { +- union bpf_attr attr = {}; ++ union bpf_attr attr; + int err; + + if (sysctl_unprivileged_bpf_disabled && !capable(CAP_SYS_ADMIN)) +@@ -1439,6 +1439,7 @@ SYSCALL_DEFINE3(bpf, int, cmd, union bpf + size = min_t(u32, size, sizeof(attr)); + + /* copy attributes from user space, may be less than sizeof(bpf_attr) */ ++ memset(&attr, 0, sizeof(attr)); + if (copy_from_user(&attr, uattr, size) != 0) + return -EFAULT; + diff --git a/patches.suse/bpf-offload-Replace-bitwise-AND-by-logical-AND-in-bp.patch b/patches.suse/bpf-offload-Replace-bitwise-AND-by-logical-AND-in-bp.patch new file mode 100644 index 0000000..c4e70d3 --- /dev/null +++ b/patches.suse/bpf-offload-Replace-bitwise-AND-by-logical-AND-in-bp.patch @@ -0,0 +1,35 @@ +From: Johannes Krude +Date: Wed, 12 Feb 2020 20:32:27 +0100 +Subject: bpf, offload: Replace bitwise AND by logical AND in + bpf_prog_offload_info_fill +Patch-mainline: v5.6-rc3 +Git-commit: e20d3a055a457a10a4c748ce5b7c2ed3173a1324 +References: bsc#1109837 + +This if guards whether user-space wants a copy of the offload-jited +bytecode and whether this bytecode exists. By erroneously doing a bitwise +AND instead of a logical AND on user- and kernel-space buffer-size can lead +to no data being copied to user-space especially when user-space size is a +power of two and bigger then the kernel-space buffer. + +Fixes: fcfb126defda ("bpf: add new jited info fields in bpf_dev_offload and bpf_prog_info") +Signed-off-by: Johannes Krude +Signed-off-by: Daniel Borkmann +Acked-by: Jakub Kicinski +Link: https://lore.kernel.org/bpf/20200212193227.GA3769@phlox.h.transitiv.net +Acked-by: Thomas Bogendoerfer +--- + kernel/bpf/offload.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/kernel/bpf/offload.c ++++ b/kernel/bpf/offload.c +@@ -307,7 +307,7 @@ int bpf_prog_offload_info_fill(struct bp + + ulen = info->jited_prog_len; + info->jited_prog_len = aux->offload->jited_len; +- if (info->jited_prog_len & ulen) { ++ if (info->jited_prog_len && ulen) { + uinsns = u64_to_user_ptr(info->jited_prog_insns); + ulen = min_t(u32, info->jited_prog_len, ulen); + if (copy_to_user(uinsns, aux->offload->jited_image, ulen)) { diff --git a/patches.suse/bpf-x64-fix-stack-layout-of-JITed-bpf-code.patch b/patches.suse/bpf-x64-fix-stack-layout-of-JITed-bpf-code.patch index 78f6d49..e31052c 100644 --- a/patches.suse/bpf-x64-fix-stack-layout-of-JITed-bpf-code.patch +++ b/patches.suse/bpf-x64-fix-stack-layout-of-JITed-bpf-code.patch @@ -16,25 +16,23 @@ Fixes: 177366bf7ceb ("bpf: change x86 JITed program stack layout") Signed-off-by: Alexei Starovoitov Acked-by: Gary Lin --- - arch/x86/net/bpf_jit_comp.c | 83 +++++++++++--------------------------------- - 1 file changed, 21 insertions(+), 62 deletions(-) + arch/x86/net/bpf_jit_comp.c | 70 +++++++++++++------------------------------- + 1 file changed, 21 insertions(+), 49 deletions(-) --- a/arch/x86/net/bpf_jit_comp.c +++ b/arch/x86/net/bpf_jit_comp.c -@@ -200,11 +200,7 @@ struct jit_context { +@@ -191,9 +191,7 @@ struct jit_context { #define BPF_MAX_INSN_SIZE 128 #define BPF_INSN_SAFETY 64 --#define AUX_STACK_SPACE \ -- (32 /* space for rbx, r13, r14, r15 */ + \ -- 8 /* space for skb_copy_bits() buffer */) +-#define AUX_STACK_SPACE 40 /* Space for RBX, R13, R14, R15, tailcnt */ - --#define PROLOGUE_SIZE 37 +-#define PROLOGUE_SIZE 37 +#define PROLOGUE_SIZE 20 /* emit x64 prologue code for BPF program and check it's size. * bpf_tail_call helper will skip it while jumping into another program -@@ -214,51 +210,19 @@ static void emit_prologue(u8 **pprog, u3 +@@ -203,40 +201,19 @@ static void emit_prologue(u8 **pprog, u3 u8 *prog = *pprog; int cnt = 0; @@ -48,19 +46,8 @@ Acked-by: Gary Lin - /* sub rbp, AUX_STACK_SPACE */ - EMIT4(0x48, 0x83, 0xED, AUX_STACK_SPACE); - -- /* all classic BPF filters use R6(rbx) save it */ -- - /* mov qword ptr [rbp+0],rbx */ - EMIT4(0x48, 0x89, 0x5D, 0); -- -- /* bpf_convert_filter() maps classic BPF register X to R7 and uses R8 -- * as temporary, so all tcpdump filters need to spill/fill R7(r13) and -- * R8(r14). R9(r15) spill could be made conditional, but there is only -- * one 'bpf_error' return path out of helper functions inside bpf_jit.S -- * The overhead of extra spill is negligible for any filter other -- * than synthetic ones. Therefore not worth adding complexity. -- */ -- - /* mov qword ptr [rbp+8],r13 */ - EMIT4(0x4C, 0x89, 0x6D, 8); - /* mov qword ptr [rbp+16],r14 */ @@ -96,7 +83,7 @@ Acked-by: Gary Lin *pprog = prog; } -@@ -298,13 +262,13 @@ static void emit_bpf_tail_call(u8 **ppro +@@ -276,13 +253,13 @@ static void emit_bpf_tail_call(u8 **ppro /* if (tail_call_cnt > MAX_TAIL_CALL_CNT) * goto out; */ @@ -112,7 +99,7 @@ Acked-by: Gary Lin /* prog = array->ptrs[index]; */ EMIT4_off32(0x48, 0x8B, 0x84, 0xD6, /* mov rax, [rsi + rdx * 8 + offsetof(...)] */ -@@ -1069,19 +1033,14 @@ common_load: +@@ -960,19 +937,14 @@ emit_jmp: seen_exit = true; /* update cleanup_addr */ ctx->cleanup_addr = proglen; diff --git a/patches.suse/bpf-x64-remove-ld_abs-ld_ind.patch b/patches.suse/bpf-x64-remove-ld_abs-ld_ind.patch new file mode 100644 index 0000000..1151837 --- /dev/null +++ b/patches.suse/bpf-x64-remove-ld_abs-ld_ind.patch @@ -0,0 +1,424 @@ +From: Daniel Borkmann +Date: Fri, 4 May 2018 01:08:16 +0200 +Subject: bpf, x64: remove ld_abs/ld_ind +Patch-mainline: v4.18-rc1 +Git-commit: e782bdcf58c5ace7b7d58b2436177de9785a18e8 +References: bsc#1154385 + +Since LD_ABS/LD_IND instructions are now removed from the core and +reimplemented through a combination of inlined BPF instructions and +a slow-path helper, we can get rid of the complexity from x64 JIT. + +Signed-off-by: Daniel Borkmann +Acked-by: Alexei Starovoitov +Signed-off-by: Alexei Starovoitov +Acked-by: Gary Lin +--- + arch/x86/net/Makefile | 2 + arch/x86/net/bpf_jit.S | 154 -------------------------------------------- + arch/x86/net/bpf_jit_comp.c | 140 +--------------------------------------- + 3 files changed, 5 insertions(+), 291 deletions(-) + delete mode 100644 arch/x86/net/bpf_jit.S + +--- a/arch/x86/net/Makefile ++++ b/arch/x86/net/Makefile +@@ -3,4 +3,4 @@ + # + OBJECT_FILES_NON_STANDARD_bpf_jit.o += y + +-obj-$(CONFIG_BPF_JIT) += bpf_jit.o bpf_jit_comp.o ++obj-$(CONFIG_BPF_JIT) += bpf_jit_comp.o +--- a/arch/x86/net/bpf_jit.S ++++ /dev/null +@@ -1,154 +0,0 @@ +-/* bpf_jit.S : BPF JIT helper functions +- * +- * Copyright (C) 2011 Eric Dumazet (eric.dumazet@gmail.com) +- * +- * This program is free software; you can redistribute it and/or +- * modify it under the terms of the GNU General Public License +- * as published by the Free Software Foundation; version 2 +- * of the License. +- */ +-#include +-#include +- +-/* +- * Calling convention : +- * rbx : skb pointer (callee saved) +- * esi : offset of byte(s) to fetch in skb (can be scratched) +- * r10 : copy of skb->data +- * r9d : hlen = skb->len - skb->data_len +- */ +-#define SKBDATA %r10 +-#define SKF_MAX_NEG_OFF $(-0x200000) /* SKF_LL_OFF from filter.h */ +- +-#define FUNC(name) \ +- .globl name; \ +- .type name, @function; \ +- name: +- +-FUNC(sk_load_word) +- test %esi,%esi +- js bpf_slow_path_word_neg +- +-FUNC(sk_load_word_positive_offset) +- mov %r9d,%eax # hlen +- sub %esi,%eax # hlen - offset +- cmp $3,%eax +- jle bpf_slow_path_word +- mov (SKBDATA,%rsi),%eax +- bswap %eax /* ntohl() */ +- ret +- +-FUNC(sk_load_half) +- test %esi,%esi +- js bpf_slow_path_half_neg +- +-FUNC(sk_load_half_positive_offset) +- mov %r9d,%eax +- sub %esi,%eax # hlen - offset +- cmp $1,%eax +- jle bpf_slow_path_half +- movzwl (SKBDATA,%rsi),%eax +- rol $8,%ax # ntohs() +- ret +- +-FUNC(sk_load_byte) +- test %esi,%esi +- js bpf_slow_path_byte_neg +- +-FUNC(sk_load_byte_positive_offset) +- cmp %esi,%r9d /* if (offset >= hlen) goto bpf_slow_path_byte */ +- jle bpf_slow_path_byte +- movzbl (SKBDATA,%rsi),%eax +- ret +- +-/* rsi contains offset and can be scratched */ +-#define bpf_slow_path_common(LEN) \ +- lea 32(%rbp), %rdx;\ +- FRAME_BEGIN; \ +- mov %rbx, %rdi; /* arg1 == skb */ \ +- push %r9; \ +- push SKBDATA; \ +-/* rsi already has offset */ \ +- mov $LEN,%ecx; /* len */ \ +- call skb_copy_bits; \ +- test %eax,%eax; \ +- pop SKBDATA; \ +- pop %r9; \ +- FRAME_END +- +- +-bpf_slow_path_word: +- bpf_slow_path_common(4) +- js bpf_error +- mov 32(%rbp),%eax +- bswap %eax +- ret +- +-bpf_slow_path_half: +- bpf_slow_path_common(2) +- js bpf_error +- mov 32(%rbp),%ax +- rol $8,%ax +- movzwl %ax,%eax +- ret +- +-bpf_slow_path_byte: +- bpf_slow_path_common(1) +- js bpf_error +- movzbl 32(%rbp),%eax +- ret +- +-#define sk_negative_common(SIZE) \ +- FRAME_BEGIN; \ +- mov %rbx, %rdi; /* arg1 == skb */ \ +- push %r9; \ +- push SKBDATA; \ +-/* rsi already has offset */ \ +- mov $SIZE,%edx; /* size */ \ +- call bpf_internal_load_pointer_neg_helper; \ +- test %rax,%rax; \ +- pop SKBDATA; \ +- pop %r9; \ +- FRAME_END; \ +- jz bpf_error +- +-bpf_slow_path_word_neg: +- cmp SKF_MAX_NEG_OFF, %esi /* test range */ +- jl bpf_error /* offset lower -> error */ +- +-FUNC(sk_load_word_negative_offset) +- sk_negative_common(4) +- mov (%rax), %eax +- bswap %eax +- ret +- +-bpf_slow_path_half_neg: +- cmp SKF_MAX_NEG_OFF, %esi +- jl bpf_error +- +-FUNC(sk_load_half_negative_offset) +- sk_negative_common(2) +- mov (%rax),%ax +- rol $8,%ax +- movzwl %ax,%eax +- ret +- +-bpf_slow_path_byte_neg: +- cmp SKF_MAX_NEG_OFF, %esi +- jl bpf_error +- +-FUNC(sk_load_byte_negative_offset) +- sk_negative_common(1) +- movzbl (%rax), %eax +- ret +- +-bpf_error: +-# force a return 0 from jit handler +- xor %eax,%eax +- mov (%rbp),%rbx +- mov 8(%rbp),%r13 +- mov 16(%rbp),%r14 +- mov 24(%rbp),%r15 +- add $40, %rbp +- leaveq +- ret +--- a/arch/x86/net/bpf_jit_comp.c ++++ b/arch/x86/net/bpf_jit_comp.c +@@ -16,15 +16,6 @@ + #include + #include + +-/* +- * assembly code in arch/x86/net/bpf_jit.S +- */ +-extern u8 sk_load_word[], sk_load_half[], sk_load_byte[]; +-extern u8 sk_load_word_positive_offset[], sk_load_half_positive_offset[]; +-extern u8 sk_load_byte_positive_offset[]; +-extern u8 sk_load_word_negative_offset[], sk_load_half_negative_offset[]; +-extern u8 sk_load_byte_negative_offset[]; +- + static u8 *emit_code(u8 *ptr, u32 bytes, unsigned int len) + { + if (len == 1) +@@ -115,9 +106,6 @@ static void bpf_flush_icache(void *start + set_fs(old_fs); + } + +-#define CHOOSE_LOAD_FUNC(K, func) \ +- ((int)K < 0 ? ((int)K >= SKF_LL_OFF ? func##_negative_offset : func) : func##_positive_offset) +- + /* pick a register outside of BPF range for JIT internal work */ + #define AUX_REG (MAX_BPF_JIT_REG + 1) + +@@ -127,8 +115,8 @@ static void bpf_flush_icache(void *start + * register in load/store instructions, it always needs an + * extra byte of encoding and is callee saved. + * +- * r9 caches skb->len - skb->data_len +- * r10 caches skb->data, and used for blinding (if enabled) ++ * Also x86-64 register R9 is unused. x86-64 register R10 is ++ * used for blinding (if enabled). + */ + static const int reg2hex[] = { + [BPF_REG_0] = 0, /* rax */ +@@ -197,19 +185,15 @@ static void jit_fill_hole(void *area, un + + struct jit_context { + int cleanup_addr; /* epilogue code offset */ +- bool seen_ld_abs; +- bool seen_ax_reg; + }; + + /* maximum number of bytes emitted while JITing one eBPF insn */ + #define BPF_MAX_INSN_SIZE 128 + #define BPF_INSN_SAFETY 64 + +-#define AUX_STACK_SPACE \ +- (32 /* space for rbx, r13, r14, r15 */ + \ +- 8 /* space for skb_copy_bits() buffer */) ++#define AUX_STACK_SPACE 40 /* Space for RBX, R13, R14, R15, tailcnt */ + +-#define PROLOGUE_SIZE 37 ++#define PROLOGUE_SIZE 37 + + /* emit x64 prologue code for BPF program and check it's size. + * bpf_tail_call helper will skip it while jumping into another program +@@ -229,19 +213,8 @@ static void emit_prologue(u8 **pprog, u3 + /* sub rbp, AUX_STACK_SPACE */ + EMIT4(0x48, 0x83, 0xED, AUX_STACK_SPACE); + +- /* all classic BPF filters use R6(rbx) save it */ +- + /* mov qword ptr [rbp+0],rbx */ + EMIT4(0x48, 0x89, 0x5D, 0); +- +- /* bpf_convert_filter() maps classic BPF register X to R7 and uses R8 +- * as temporary, so all tcpdump filters need to spill/fill R7(r13) and +- * R8(r14). R9(r15) spill could be made conditional, but there is only +- * one 'bpf_error' return path out of helper functions inside bpf_jit.S +- * The overhead of extra spill is negligible for any filter other +- * than synthetic ones. Therefore not worth adding complexity. +- */ +- + /* mov qword ptr [rbp+8],r13 */ + EMIT4(0x4C, 0x89, 0x6D, 8); + /* mov qword ptr [rbp+16],r14 */ +@@ -341,26 +314,6 @@ static void emit_bpf_tail_call(u8 **ppro + *pprog = prog; + } + +- +-static void emit_load_skb_data_hlen(u8 **pprog) +-{ +- u8 *prog = *pprog; +- int cnt = 0; +- +- /* r9d = skb->len - skb->data_len (headlen) +- * r10 = skb->data +- */ +- /* mov %r9d, off32(%rdi) */ +- EMIT3_off32(0x44, 0x8b, 0x8f, offsetof(struct sk_buff, len)); +- +- /* sub %r9d, off32(%rdi) */ +- EMIT3_off32(0x44, 0x2b, 0x8f, offsetof(struct sk_buff, data_len)); +- +- /* mov %r10, off32(%rdi) */ +- EMIT3_off32(0x4c, 0x8b, 0x97, offsetof(struct sk_buff, data)); +- *pprog = prog; +-} +- + static void emit_mov_imm32(u8 **pprog, bool sign_propagate, + u32 dst_reg, const u32 imm32) + { +@@ -428,8 +381,6 @@ static int do_jit(struct bpf_prog *bpf_p + { + struct bpf_insn *insn = bpf_prog->insnsi; + int insn_cnt = bpf_prog->len; +- bool seen_ld_abs = ctx->seen_ld_abs | (oldproglen == 0); +- bool seen_ax_reg = ctx->seen_ax_reg | (oldproglen == 0); + bool seen_exit = false; + u8 temp[BPF_MAX_INSN_SIZE + BPF_INSN_SAFETY]; + int i, cnt = 0; +@@ -439,9 +390,6 @@ static int do_jit(struct bpf_prog *bpf_p + emit_prologue(&prog, bpf_prog->aux->stack_depth, + bpf_prog_was_classic(bpf_prog)); + +- if (seen_ld_abs) +- emit_load_skb_data_hlen(&prog); +- + for (i = 0; i < insn_cnt; i++, insn++) { + const s32 imm32 = insn->imm; + u32 dst_reg = insn->dst_reg; +@@ -449,13 +397,9 @@ static int do_jit(struct bpf_prog *bpf_p + u8 b2 = 0, b3 = 0; + s64 jmp_offset; + u8 jmp_cond; +- bool reload_skb_data; + int ilen; + u8 *func; + +- if (dst_reg == BPF_REG_AX || src_reg == BPF_REG_AX) +- ctx->seen_ax_reg = seen_ax_reg = true; +- + switch (insn->code) { + /* ALU */ + case BPF_ALU | BPF_ADD | BPF_X: +@@ -878,35 +822,12 @@ xadd: if (is_imm8(insn->off)) + case BPF_JMP | BPF_CALL: + func = (u8 *) __bpf_call_base + imm32; + jmp_offset = func - (image + addrs[i]); +- if (seen_ld_abs) { +- reload_skb_data = bpf_helper_changes_pkt_data(func); +- if (reload_skb_data) { +- EMIT1(0x57); /* push %rdi */ +- jmp_offset += 22; /* pop, mov, sub, mov */ +- } else { +- EMIT2(0x41, 0x52); /* push %r10 */ +- EMIT2(0x41, 0x51); /* push %r9 */ +- /* need to adjust jmp offset, since +- * pop %r9, pop %r10 take 4 bytes after call insn +- */ +- jmp_offset += 4; +- } +- } + if (!imm32 || !is_simm32(jmp_offset)) { + pr_err("unsupported bpf func %d addr %p image %p\n", + imm32, func, image); + return -EINVAL; + } + EMIT1_off32(0xE8, jmp_offset); +- if (seen_ld_abs) { +- if (reload_skb_data) { +- EMIT1(0x5F); /* pop %rdi */ +- emit_load_skb_data_hlen(&prog); +- } else { +- EMIT2(0x41, 0x59); /* pop %r9 */ +- EMIT2(0x41, 0x5A); /* pop %r10 */ +- } +- } + break; + + case BPF_JMP | BPF_TAIL_CALL: +@@ -1031,59 +952,6 @@ emit_jmp: + } + break; + +- case BPF_LD | BPF_IND | BPF_W: +- func = sk_load_word; +- goto common_load; +- case BPF_LD | BPF_ABS | BPF_W: +- func = CHOOSE_LOAD_FUNC(imm32, sk_load_word); +-common_load: +- ctx->seen_ld_abs = seen_ld_abs = true; +- jmp_offset = func - (image + addrs[i]); +- if (!func || !is_simm32(jmp_offset)) { +- pr_err("unsupported bpf func %d addr %p image %p\n", +- imm32, func, image); +- return -EINVAL; +- } +- if (BPF_MODE(insn->code) == BPF_ABS) { +- /* mov %esi, imm32 */ +- EMIT1_off32(0xBE, imm32); +- } else { +- /* mov %rsi, src_reg */ +- EMIT_mov(BPF_REG_2, src_reg); +- if (imm32) { +- if (is_imm8(imm32)) +- /* add %esi, imm8 */ +- EMIT3(0x83, 0xC6, imm32); +- else +- /* add %esi, imm32 */ +- EMIT2_off32(0x81, 0xC6, imm32); +- } +- } +- /* skb pointer is in R6 (%rbx), it will be copied into +- * %rdi if skb_copy_bits() call is necessary. +- * sk_load_* helpers also use %r10 and %r9d. +- * See bpf_jit.S +- */ +- if (seen_ax_reg) +- /* r10 = skb->data, mov %r10, off32(%rbx) */ +- EMIT3_off32(0x4c, 0x8b, 0x93, +- offsetof(struct sk_buff, data)); +- EMIT1_off32(0xE8, jmp_offset); /* call */ +- break; +- +- case BPF_LD | BPF_IND | BPF_H: +- func = sk_load_half; +- goto common_load; +- case BPF_LD | BPF_ABS | BPF_H: +- func = CHOOSE_LOAD_FUNC(imm32, sk_load_half); +- goto common_load; +- case BPF_LD | BPF_IND | BPF_B: +- func = sk_load_byte; +- goto common_load; +- case BPF_LD | BPF_ABS | BPF_B: +- func = CHOOSE_LOAD_FUNC(imm32, sk_load_byte); +- goto common_load; +- + case BPF_JMP | BPF_EXIT: + if (seen_exit) { + jmp_offset = ctx->cleanup_addr - addrs[i]; diff --git a/patches.suse/bpf-x64-save-several-bytes-by-using-mov-over-movabsq.patch b/patches.suse/bpf-x64-save-several-bytes-by-using-mov-over-movabsq.patch new file mode 100644 index 0000000..f58a14d --- /dev/null +++ b/patches.suse/bpf-x64-save-several-bytes-by-using-mov-over-movabsq.patch @@ -0,0 +1,191 @@ +From: Daniel Borkmann +Date: Sat, 24 Feb 2018 01:07:59 +0100 +Subject: bpf, x64: save several bytes by using mov over movabsq when possible +Patch-mainline: v4.17-rc1 +Git-commit: 6fe8b9c1f41dfe3209dabc5bd0726e003a065288 +References: bsc#1154385 + +While analyzing some of the more complex BPF programs from Cilium, +I found that LLVM generally prefers to emit LD_IMM64 instead of MOV32 +BPF instructions for loading unsigned 32-bit immediates into a +register. Given we cannot change the current/stable LLVM versions +that are already out there, lets optimize this case such that the +JIT prefers to emit 'mov %eax, imm32' over 'movabsq %rax, imm64' +whenever suitable in order to reduce the image size by 4-5 bytes per +such load in the typical case, reducing image size on some of the +bigger programs by up to 4%. emit_mov_imm32() and emit_mov_imm64() +have been added as helpers. + +Signed-off-by: Daniel Borkmann +Signed-off-by: Alexei Starovoitov +Acked-by: Gary Lin +--- + arch/x86/net/bpf_jit_comp.c | 125 ++++++++++++++++++++++++++------------------ + 1 file changed, 74 insertions(+), 51 deletions(-) + +--- a/arch/x86/net/bpf_jit_comp.c ++++ b/arch/x86/net/bpf_jit_comp.c +@@ -63,7 +63,12 @@ static bool is_imm8(int value) + + static bool is_simm32(s64 value) + { +- return value == (s64) (s32) value; ++ return value == (s64)(s32)value; ++} ++ ++static bool is_uimm32(u64 value) ++{ ++ return value == (u64)(u32)value; + } + + /* mov dst, src */ +@@ -353,6 +358,68 @@ static void emit_load_skb_data_hlen(u8 * + *pprog = prog; + } + ++static void emit_mov_imm32(u8 **pprog, bool sign_propagate, ++ u32 dst_reg, const u32 imm32) ++{ ++ u8 *prog = *pprog; ++ u8 b1, b2, b3; ++ int cnt = 0; ++ ++ /* optimization: if imm32 is positive, use 'mov %eax, imm32' ++ * (which zero-extends imm32) to save 2 bytes. ++ */ ++ if (sign_propagate && (s32)imm32 < 0) { ++ /* 'mov %rax, imm32' sign extends imm32 */ ++ b1 = add_1mod(0x48, dst_reg); ++ b2 = 0xC7; ++ b3 = 0xC0; ++ EMIT3_off32(b1, b2, add_1reg(b3, dst_reg), imm32); ++ goto done; ++ } ++ ++ /* optimization: if imm32 is zero, use 'xor %eax, %eax' ++ * to save 3 bytes. ++ */ ++ if (imm32 == 0) { ++ if (is_ereg(dst_reg)) ++ EMIT1(add_2mod(0x40, dst_reg, dst_reg)); ++ b2 = 0x31; /* xor */ ++ b3 = 0xC0; ++ EMIT2(b2, add_2reg(b3, dst_reg, dst_reg)); ++ goto done; ++ } ++ ++ /* mov %eax, imm32 */ ++ if (is_ereg(dst_reg)) ++ EMIT1(add_1mod(0x40, dst_reg)); ++ EMIT1_off32(add_1reg(0xB8, dst_reg), imm32); ++done: ++ *pprog = prog; ++} ++ ++static void emit_mov_imm64(u8 **pprog, u32 dst_reg, ++ const u32 imm32_hi, const u32 imm32_lo) ++{ ++ u8 *prog = *pprog; ++ int cnt = 0; ++ ++ if (is_uimm32(((u64)imm32_hi << 32) | (u32)imm32_lo)) { ++ /* For emitting plain u32, where sign bit must not be ++ * propagated LLVM tends to load imm64 over mov32 ++ * directly, so save couple of bytes by just doing ++ * 'mov %eax, imm32' instead. ++ */ ++ emit_mov_imm32(&prog, false, dst_reg, imm32_lo); ++ } else { ++ /* movabsq %rax, imm64 */ ++ EMIT2(add_1mod(0x48, dst_reg), add_1reg(0xB8, dst_reg)); ++ EMIT(imm32_lo, 4); ++ EMIT(imm32_hi, 4); ++ } ++ ++ *pprog = prog; ++} ++ + static int do_jit(struct bpf_prog *bpf_prog, int *addrs, u8 *image, + int oldproglen, struct jit_context *ctx) + { +@@ -375,7 +442,7 @@ static int do_jit(struct bpf_prog *bpf_p + const s32 imm32 = insn->imm; + u32 dst_reg = insn->dst_reg; + u32 src_reg = insn->src_reg; +- u8 b1 = 0, b2 = 0, b3 = 0; ++ u8 b2 = 0, b3 = 0; + s64 jmp_offset; + u8 jmp_cond; + bool reload_skb_data; +@@ -463,58 +530,13 @@ static int do_jit(struct bpf_prog *bpf_p + break; + + case BPF_ALU64 | BPF_MOV | BPF_K: +- /* optimization: if imm32 is positive, +- * use 'mov eax, imm32' (which zero-extends imm32) +- * to save 2 bytes +- */ +- if (imm32 < 0) { +- /* 'mov rax, imm32' sign extends imm32 */ +- b1 = add_1mod(0x48, dst_reg); +- b2 = 0xC7; +- b3 = 0xC0; +- EMIT3_off32(b1, b2, add_1reg(b3, dst_reg), imm32); +- break; +- } +- + case BPF_ALU | BPF_MOV | BPF_K: +- /* optimization: if imm32 is zero, use 'xor ,' +- * to save 3 bytes. +- */ +- if (imm32 == 0) { +- if (is_ereg(dst_reg)) +- EMIT1(add_2mod(0x40, dst_reg, dst_reg)); +- b2 = 0x31; /* xor */ +- b3 = 0xC0; +- EMIT2(b2, add_2reg(b3, dst_reg, dst_reg)); +- break; +- } +- +- /* mov %eax, imm32 */ +- if (is_ereg(dst_reg)) +- EMIT1(add_1mod(0x40, dst_reg)); +- EMIT1_off32(add_1reg(0xB8, dst_reg), imm32); ++ emit_mov_imm32(&prog, BPF_CLASS(insn->code) == BPF_ALU64, ++ dst_reg, imm32); + break; + + case BPF_LD | BPF_IMM | BPF_DW: +- /* optimization: if imm64 is zero, use 'xor ,' +- * to save 7 bytes. +- */ +- if (insn[0].imm == 0 && insn[1].imm == 0) { +- b1 = add_2mod(0x48, dst_reg, dst_reg); +- b2 = 0x31; /* xor */ +- b3 = 0xC0; +- EMIT3(b1, b2, add_2reg(b3, dst_reg, dst_reg)); +- +- insn++; +- i++; +- break; +- } +- +- /* movabsq %rax, imm64 */ +- EMIT2(add_1mod(0x48, dst_reg), add_1reg(0xB8, dst_reg)); +- EMIT(insn[0].imm, 4); +- EMIT(insn[1].imm, 4); +- ++ emit_mov_imm64(&prog, dst_reg, insn[1].imm, insn[0].imm); + insn++; + i++; + break; +@@ -602,7 +624,8 @@ static int do_jit(struct bpf_prog *bpf_p + EMIT_mov(BPF_REG_0, src_reg); + else + /* mov rax, imm32 */ +- EMIT3_off32(0x48, 0xC7, 0xC0, imm32); ++ emit_mov_imm32(&prog, true, ++ BPF_REG_0, imm32); + + if (BPF_CLASS(insn->code) == BPF_ALU64) + EMIT1(add_1mod(0x48, AUX_REG)); diff --git a/patches.suse/brcmfmac-abort-and-release-host-after-error.patch b/patches.suse/brcmfmac-abort-and-release-host-after-error.patch new file mode 100644 index 0000000..0028ca1 --- /dev/null +++ b/patches.suse/brcmfmac-abort-and-release-host-after-error.patch @@ -0,0 +1,57 @@ +From 863844ee3bd38219c88e82966d1df36a77716f3e Mon Sep 17 00:00:00 2001 +From: Guenter Roeck +Date: Tue, 28 Jan 2020 14:14:57 -0800 +Subject: [PATCH] brcmfmac: abort and release host after error +Git-commit: 863844ee3bd38219c88e82966d1df36a77716f3e +Patch-mainline: v5.7-rc1 +References: bsc#1111666 + +With commit 216b44000ada ("brcmfmac: Fix use after free in +brcmf_sdio_readframes()") applied, we see locking timeouts in +brcmf_sdio_watchdog_thread(). + +Brcmfmac: brcmf_escan_timeout: timer expired +Info: task brcmf_wdog/mmc1:621 blocked for more than 120 seconds. +Not tainted 4.19.94-07984-g24ff99a0f713 #1 +"echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message. +brcmf_wdog/mmc1 D 0 621 2 0x00000000 last_sleep: 2440793077. last_runnable: 2440766827 +[] (__schedule) from [] (schedule+0x98/0xc4) +[] (schedule) from [] (__mmc_claim_host+0x154/0x274) +[] (__mmc_claim_host) from [] (brcmf_sdio_watchdog_thread+0x1b0/0x1f8 [brcmfmac]) +[] (brcmf_sdio_watchdog_thread [brcmfmac]) from [] (kthread+0x178/0x180) + +In addition to restarting or exiting the loop, it is also necessary to +abort the command and to release the host. + +Fixes: 216b44000ada ("brcmfmac: Fix use after free in brcmf_sdio_readframes()") +Cc: Dan Carpenter +Cc: Matthias Kaehlcke +Cc: Brian Norris +Cc: Douglas Anderson +Signed-off-by: Guenter Roeck +Reviewed-by: Douglas Anderson +Acked-by: franky.lin@broadcom.com +Acked-by: Dan Carpenter +Signed-off-by: Kalle Valo +Acked-by: Takashi Iwai + +--- + drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c +index f9047db6a11d..3a08252f1a53 100644 +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c +@@ -1938,6 +1938,8 @@ static uint brcmf_sdio_readframes(struct brcmf_sdio *bus, uint maxframes) + if (brcmf_sdio_hdparse(bus, bus->rxhdr, &rd_new, + BRCMF_SDIO_FT_NORMAL)) { + rd->len = 0; ++ brcmf_sdio_rxfail(bus, true, true); ++ sdio_release_host(bus->sdiodev->func1); + brcmu_pkt_buf_free_skb(pkt); + continue; + } +-- +2.16.4 + diff --git a/patches.suse/btrfs-Remove-redundant-mirror_num-arg.patch b/patches.suse/btrfs-Remove-redundant-mirror_num-arg.patch new file mode 100644 index 0000000..9c49aeb --- /dev/null +++ b/patches.suse/btrfs-Remove-redundant-mirror_num-arg.patch @@ -0,0 +1,93 @@ +From d3fac6ba7dccc54f52087bb9d7b9be27aa6fa622 Mon Sep 17 00:00:00 2001 +From: Nikolay Borisov +Date: Tue, 24 Oct 2017 11:50:39 +0300 +Patch-mainline: v4.16 +Git-commit: d3fac6ba7dccc54f52087bb9d7b9be27aa6fa622 +References: bsc#1168273 +Subject: [PATCH] btrfs: Remove redundant mirror_num arg + +The following callpath is always invoked with mirror_num set to 0, so +let's remove it as an argument and directly pass 0 to __do_redpage. No +functional change. + +extent_readpages + __extent_readpages + __do_contiguous_readpages + __do_readpage + +Signed-off-by: Nikolay Borisov +Reviewed-by: David Sterba +Signed-off-by: David Sterba +--- + fs/btrfs/extent_io.c | 16 +++++++--------- + 1 file changed, 7 insertions(+), 9 deletions(-) + +diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c +index 012d63870b99..c6e82a3e706d 100644 +--- a/fs/btrfs/extent_io.c ++++ b/fs/btrfs/extent_io.c +@@ -3094,7 +3094,7 @@ static inline void __do_contiguous_readpages(struct extent_io_tree *tree, + u64 start, u64 end, + get_extent_t *get_extent, + struct extent_map **em_cached, +- struct bio **bio, int mirror_num, ++ struct bio **bio, + unsigned long *bio_flags, + u64 *prev_em_start) + { +@@ -3116,7 +3116,7 @@ static inline void __do_contiguous_readpages(struct extent_io_tree *tree, + + for (index = 0; index < nr_pages; index++) { + __do_readpage(tree, pages[index], get_extent, em_cached, bio, +- mirror_num, bio_flags, 0, prev_em_start); ++ 0, bio_flags, 0, prev_em_start); + put_page(pages[index]); + } + } +@@ -3125,8 +3125,7 @@ static void __extent_readpages(struct extent_io_tree *tree, + struct page *pages[], + int nr_pages, get_extent_t *get_extent, + struct extent_map **em_cached, +- struct bio **bio, int mirror_num, +- unsigned long *bio_flags, ++ struct bio **bio, unsigned long *bio_flags, + u64 *prev_em_start) + { + u64 start = 0; +@@ -3147,7 +3146,7 @@ static void __extent_readpages(struct extent_io_tree *tree, + __do_contiguous_readpages(tree, &pages[first_index], + index - first_index, start, + end, get_extent, em_cached, +- bio, mirror_num, bio_flags, ++ bio, bio_flags, + prev_em_start); + start = page_start; + end = start + PAGE_SIZE - 1; +@@ -3159,8 +3158,7 @@ static void __extent_readpages(struct extent_io_tree *tree, + __do_contiguous_readpages(tree, &pages[first_index], + index - first_index, start, + end, get_extent, em_cached, bio, +- mirror_num, bio_flags, +- prev_em_start); ++ bio_flags, prev_em_start); + } + + static int __extent_read_full_page(struct extent_io_tree *tree, +@@ -4171,12 +4169,12 @@ int extent_readpages(struct extent_io_tree *tree, + if (nr < ARRAY_SIZE(pagepool)) + continue; + __extent_readpages(tree, pagepool, nr, get_extent, &em_cached, +- &bio, 0, &bio_flags, &prev_em_start); ++ &bio, &bio_flags, &prev_em_start); + nr = 0; + } + if (nr) + __extent_readpages(tree, pagepool, nr, get_extent, &em_cached, +- &bio, 0, &bio_flags, &prev_em_start); ++ &bio, &bio_flags, &prev_em_start); + + if (em_cached) + free_extent_map(em_cached); +-- +2.26.0 + diff --git a/patches.suse/btrfs-account-for-trans_block_rsv-in-may_commit_transaction.patch b/patches.suse/btrfs-account-for-trans_block_rsv-in-may_commit_transaction.patch new file mode 100644 index 0000000..0865e87 --- /dev/null +++ b/patches.suse/btrfs-account-for-trans_block_rsv-in-may_commit_transaction.patch @@ -0,0 +1,48 @@ +From: Josef Bacik +Date: Fri, 13 Mar 2020 15:58:07 -0400 +Subject: btrfs: Account for trans_block_rsv in may_commit_transaction +Patch-mainline: Submitted, https://lore.kernel.org/linux-btrfs/20200313195809.141753-1-josef@toxicpanda.com/ +References: bsc#1165949 + +On ppc64le with 64k page size (respectively 64k block size) generic/320 +was failing and debug output showed we were getting a premature ENOSPC +with a bunch of space in btrfs_fs_info::trans_block_rsv. + +This meant there were still open transaction handles holding space, yet +the flusher didn't commit the transaction because it deemed the freed +space won't be enough to satisfy the current reserve ticket. Fix this +by accounting for space in trans_block_rsv when deciding whether the +current transaction should be committed or not. + +Reviewed-by: Nikolay Borisov +Signed-off-by: Josef Bacik +Acked-by: Nikolay Borisov +--- + fs/btrfs/space-info.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/fs/btrfs/space-info.c b/fs/btrfs/space-info.c +index 177cb4054443..3c4881995b1d 100644 +--- a/fs/btrfs/space-info.c ++++ b/fs/btrfs/space-info.c +@@ -618,6 +618,7 @@ static int may_commit_transaction(struct btrfs_fs_info *fs_info, + struct reserve_ticket *ticket = NULL; + struct btrfs_block_rsv *delayed_rsv = &fs_info->delayed_block_rsv; + struct btrfs_block_rsv *delayed_refs_rsv = &fs_info->delayed_refs_rsv; ++ struct btrfs_block_rsv *trans_rsv = &fs_info->trans_block_rsv; + struct btrfs_trans_handle *trans; + u64 bytes_needed; + u64 reclaim_bytes = 0; +@@ -680,6 +681,11 @@ static int may_commit_transaction(struct btrfs_fs_info *fs_info, + spin_lock(&delayed_refs_rsv->lock); + reclaim_bytes += delayed_refs_rsv->reserved; + spin_unlock(&delayed_refs_rsv->lock); ++ ++ spin_lock(&trans_rsv->lock); ++ reclaim_bytes += trans_rsv->reserved; ++ spin_unlock(&trans_rsv->lock); ++ + if (reclaim_bytes >= bytes_needed) + goto commit; + bytes_needed -= reclaim_bytes; + diff --git a/patches.suse/btrfs-add-enospc_debug-printing-in-metadata_reserve_bytes.patch b/patches.suse/btrfs-add-enospc_debug-printing-in-metadata_reserve_bytes.patch new file mode 100644 index 0000000..a5fba33 --- /dev/null +++ b/patches.suse/btrfs-add-enospc_debug-printing-in-metadata_reserve_bytes.patch @@ -0,0 +1,40 @@ +From: Nikolay Borisov +Date: Fri, 15 Dec 2017 12:05:37 +0200 +Subject: btrfs: Add enospc_debug printing in metadata_reserve_bytes +Git-commit: 9a3daff320260723b9e64b5b3b9c6592a0cd006a +Patch-mainline: v4.17-rc1 +References: bsc#1165949 + +Currently when enospc_debug mount option is turned on we do not print +any debug info in case metadata reservation failures happen. Fix this +by adding the necessary hook in reserve_metadata_bytes. + +Signed-off-by: Nikolay Borisov +Reviewed-by: Qu Wenruo +Signed-off-by: David Sterba +--- + fs/btrfs/extent-tree.c | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c +index 9a677860f64d..85258e85a030 100644 +--- a/fs/btrfs/extent-tree.c ++++ b/fs/btrfs/extent-tree.c +@@ -5394,10 +5394,15 @@ static int reserve_metadata_bytes(struct btrfs_root *root, + !block_rsv_use_bytes(global_rsv, orig_bytes)) + ret = 0; + } +- if (ret == -ENOSPC) ++ if (ret == -ENOSPC) { + trace_btrfs_space_reservation(fs_info, "space_info:enospc", + block_rsv->space_info->flags, + orig_bytes, 1); ++ ++ if (btrfs_test_opt(fs_info, ENOSPC_DEBUG)) ++ dump_space_info(fs_info, block_rsv->space_info, ++ orig_bytes, 0); ++ } + return ret; + } + + diff --git a/patches.suse/btrfs-adjust-dirty_metadata_bytes-after-writeback-fa.patch b/patches.suse/btrfs-adjust-dirty_metadata_bytes-after-writeback-fa.patch new file mode 100644 index 0000000..2ed7d7b --- /dev/null +++ b/patches.suse/btrfs-adjust-dirty_metadata_bytes-after-writeback-fa.patch @@ -0,0 +1,52 @@ +From eb5b64f142504a597d67e2109d603055ff765e52 Mon Sep 17 00:00:00 2001 +From: Dennis Zhou +Patch-mainline: v5.4 +Git-commit: eb5b64f142504a597d67e2109d603055ff765e52 +References: bsc#1168273 +Date: Fri, 13 Sep 2019 14:54:07 +0100 +Subject: [PATCH] btrfs: adjust dirty_metadata_bytes after writeback failure of + extent buffer + +Before, if a eb failed to write out, we would end up triggering a +BUG_ON(). As of f4340622e0226 ("btrfs: extent_io: Move the BUG_ON() in +flush_write_bio() one level up"), we no longer BUG_ON(), so we should +make life consistent and add back the unwritten bytes to +dirty_metadata_bytes. + +Fixes: f4340622e022 ("btrfs: extent_io: Move the BUG_ON() in flush_write_bio() one level up") +CC: stable@vger.kernel.org # 5.2+ +Reviewed-by: Filipe Manana +Signed-off-by: Dennis Zhou +Signed-off-by: David Sterba +--- + fs/btrfs/extent_io.c | 9 +++++++++ + 1 file changed, 9 insertions(+) + +diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c +index 4dc5e6939856..67066ece4de3 100644 +--- a/fs/btrfs/extent_io.c ++++ b/fs/btrfs/extent_io.c +@@ -3728,11 +3728,20 @@ static void end_extent_buffer_writeback(struct extent_buffer *eb) + static void set_btree_ioerr(struct page *page) + { + struct extent_buffer *eb = (struct extent_buffer *)page->private; ++ struct btrfs_fs_info *fs_info; + + SetPageError(page); + if (test_and_set_bit(EXTENT_BUFFER_WRITE_ERR, &eb->bflags)) + return; + ++ /* ++ * If we error out, we should add back the dirty_metadata_bytes ++ * to make it consistent. ++ */ ++ fs_info = eb->fs_info; ++ percpu_counter_add_batch(&fs_info->dirty_metadata_bytes, ++ eb->len, fs_info->dirty_metadata_batch); ++ + /* + * If writeback for a btree extent that doesn't belong to a log tree + * failed, increment the counter transaction->eb_write_errors. +-- +2.26.0 + diff --git a/patches.suse/btrfs-allow-us-to-use-up-to-90-of-the-global-rsv-for-unlink.patch b/patches.suse/btrfs-allow-us-to-use-up-to-90-of-the-global-rsv-for-unlink.patch new file mode 100644 index 0000000..21305f6 --- /dev/null +++ b/patches.suse/btrfs-allow-us-to-use-up-to-90-of-the-global-rsv-for-unlink.patch @@ -0,0 +1,34 @@ +From: Josef Bacik +Date: Fri, 13 Mar 2020 15:58:06 -0400 +Subject: btrfs: allow us to use up to 90% of the global rsv for unlink +Patch-mainline: Submitted, https://lore.kernel.org/linux-btrfs/20200313195809.141753-1-josef@toxicpanda.com/ +References: bsc#1165949 + +We previously had a limit of stealing 50% of the global reserve for +unlink. This was from a time when the global reserve was used for the +delayed refs as well. However now those reservations are kept separate, +so the global reserve can be depleted much more to allow us to make +progress for space restoring operations like unlink. Change the minimum +amount of space required to be left in the global reserve to 10%. + +Signed-off-by: Josef Bacik +Reviewed-by: Nikolay Borisov +Acked-by: Nikolay Borisov +--- + fs/btrfs/space-info.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/fs/btrfs/space-info.c b/fs/btrfs/space-info.c +index 21482914dd13..177cb4054443 100644 +--- a/fs/btrfs/space-info.c ++++ b/fs/btrfs/space-info.c +@@ -859,7 +859,7 @@ static bool steal_from_global_rsv(struct btrfs_fs_info *fs_info, + return false; + + spin_lock(&global_rsv->lock); +- min_bytes = div_factor(global_rsv->size, 5); ++ min_bytes = div_factor(global_rsv->size, 1); + if (global_rsv->reserved < min_bytes + ticket->bytes) { + spin_unlock(&global_rsv->lock); + return false; + diff --git a/patches.suse/btrfs-change-how-we-decide-to-commit-transactions-du.patch b/patches.suse/btrfs-change-how-we-decide-to-commit-transactions-du.patch index 55789a5..cffa7ea 100644 --- a/patches.suse/btrfs-change-how-we-decide-to-commit-transactions-du.patch +++ b/patches.suse/btrfs-change-how-we-decide-to-commit-transactions-du.patch @@ -34,12 +34,12 @@ Tested-by: Nikolay Borisov Signed-off-by: David Sterba --- - fs/btrfs/extent-tree.c | 45 ++++++++++++++++++++++++++++++--------------- - 1 file changed, 30 insertions(+), 15 deletions(-) + fs/btrfs/extent-tree.c | 43 +++++++++++++++++++++++++++++-------------- + 1 file changed, 29 insertions(+), 14 deletions(-) --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c -@@ -4833,6 +4833,14 @@ skip_async: +@@ -4911,6 +4911,14 @@ skip_async: } } @@ -54,7 +54,7 @@ Signed-off-by: David Sterba /** * maybe_commit_transaction - possibly commit the transaction if its ok to * @root - the root we're allocating for -@@ -4844,19 +4852,29 @@ skip_async: +@@ -4922,19 +4930,29 @@ skip_async: * will return -ENOSPC. */ static int may_commit_transaction(struct btrfs_fs_info *fs_info, @@ -88,7 +88,7 @@ Signed-off-by: David Sterba /* See if there is enough pinned space to make this reservation */ if (percpu_counter_compare(&space_info->total_bytes_pinned, bytes) >= 0) -@@ -4870,8 +4888,13 @@ static int may_commit_transaction(struct +@@ -4948,8 +4966,13 @@ static int may_commit_transaction(struct return -ENOSPC; spin_lock(&delayed_rsv->lock); @@ -103,7 +103,7 @@ Signed-off-by: David Sterba spin_unlock(&delayed_rsv->lock); return -ENOSPC; } -@@ -4885,13 +4908,6 @@ commit: +@@ -4963,13 +4986,6 @@ commit: return btrfs_commit_transaction(trans); } @@ -116,26 +116,14 @@ Signed-off-by: David Sterba - static int flush_space(struct btrfs_fs_info *fs_info, struct btrfs_space_info *space_info, u64 num_bytes, - u64 orig_bytes, int state) -@@ -4936,8 +4952,7 @@ static int flush_space(struct btrfs_fs_i + int state) +@@ -5014,8 +5030,7 @@ static int flush_space(struct btrfs_fs_i ret = 0; break; case COMMIT_TRANS: - ret = may_commit_transaction(fs_info, space_info, -- orig_bytes, 0); +- num_bytes, 0); + ret = may_commit_transaction(fs_info, space_info); break; default: ret = -ENOSPC; -@@ -5807,7 +5822,7 @@ int btrfs_orphan_reserve_metadata(struct - */ - u64 num_bytes = btrfs_calc_trans_metadata_size(fs_info, 1); - -- trace_btrfs_space_reservation(fs_info, "orphan", btrfs_ino(inode), -+ trace_btrfs_space_reservation(fs_info, "orphan", btrfs_ino(inode), - num_bytes, 1); - return btrfs_block_rsv_migrate(src_rsv, dst_rsv, num_bytes, 1); - } - - - diff --git a/patches.suse/btrfs-clean-up-error-handling-in-btrfs_truncate.patch b/patches.suse/btrfs-clean-up-error-handling-in-btrfs_truncate.patch new file mode 100644 index 0000000..6240006 --- /dev/null +++ b/patches.suse/btrfs-clean-up-error-handling-in-btrfs_truncate.patch @@ -0,0 +1,106 @@ +From: Omar Sandoval +Date: Tue, 22 May 2018 09:59:50 -0700 +Subject: Btrfs: clean up error handling in btrfs_truncate() +Git-commit: ad7e1a740d940cf7da1beb332a1095bcda40c747 +Patch-mainline: v4.18-rc1 +References: bsc#1165949 + +btrfs_truncate() uses two variables for error handling, ret and err (if +this sounds familiar, it's because btrfs_truncate_inode_items() did +something similar). This is error prone, as was made evident by "Btrfs: +fix error handling in btrfs_truncate()". We only have err because we +don't want to mask an error if we call btrfs_update_inode() and +btrfs_end_transaction(), so let's make that its own scoped return +variable and use ret everywhere else. + +Reviewed-by: Nikolay Borisov +Signed-off-by: Omar Sandoval +Signed-off-by: David Sterba +Acked-by: Nikolay Borisov +--- + fs/btrfs/inode.c | 33 ++++++++++++++------------------- + 1 file changed, 14 insertions(+), 19 deletions(-) + +diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c +index 880431ae5e59..89b208201783 100644 +--- a/fs/btrfs/inode.c ++++ b/fs/btrfs/inode.c +@@ -9030,8 +9030,7 @@ static int btrfs_truncate(struct inode *inode, bool skip_writeback) + struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb); + struct btrfs_root *root = BTRFS_I(inode)->root; + struct btrfs_block_rsv *rsv; +- int ret = 0; +- int err = 0; ++ int ret; + struct btrfs_trans_handle *trans; + u64 mask = fs_info->sectorsize - 1; + u64 min_size = btrfs_calc_trunc_metadata_size(fs_info, 1); +@@ -9083,7 +9082,7 @@ static int btrfs_truncate(struct inode *inode, bool skip_writeback) + */ + trans = btrfs_start_transaction(root, 2); + if (IS_ERR(trans)) { +- err = PTR_ERR(trans); ++ ret = PTR_ERR(trans); + goto out; + } + +@@ -9107,24 +9106,19 @@ static int btrfs_truncate(struct inode *inode, bool skip_writeback) + inode->i_size, + BTRFS_EXTENT_DATA_KEY); + trans->block_rsv = &fs_info->trans_block_rsv; +- if (ret != -ENOSPC && ret != -EAGAIN) { +- if (ret < 0) +- err = ret; ++ if (ret != -ENOSPC && ret != -EAGAIN) + break; +- } + + ret = btrfs_update_inode(trans, root, inode); +- if (ret) { +- err = ret; ++ if (ret) + break; +- } + + btrfs_end_transaction(trans); + btrfs_btree_balance_dirty(fs_info); + + trans = btrfs_start_transaction(root, 2); + if (IS_ERR(trans)) { +- ret = err = PTR_ERR(trans); ++ ret = PTR_ERR(trans); + trans = NULL; + break; + } +@@ -9158,21 +9152,22 @@ static int btrfs_truncate(struct inode *inode, bool skip_writeback) + } + + if (trans) { ++ int ret2; ++ + trans->block_rsv = &fs_info->trans_block_rsv; +- ret = btrfs_update_inode(trans, root, inode); +- if (ret && !err) +- err = ret; ++ ret2 = btrfs_update_inode(trans, root, inode); ++ if (ret2 && !ret) ++ ret = ret2; + +- ret = btrfs_end_transaction(trans); ++ ret2 = btrfs_end_transaction(trans); ++ if (ret2 && !ret) ++ ret = ret2; + btrfs_btree_balance_dirty(fs_info); + } + out: + btrfs_free_block_rsv(fs_info, rsv); + +- if (ret && !err) +- err = ret; +- +- return err; ++ return ret; + } + + /* + diff --git a/patches.suse/btrfs-cleanup-root-usage-by-btrfs_get_alloc_profile.patch b/patches.suse/btrfs-cleanup-root-usage-by-btrfs_get_alloc_profile.patch new file mode 100644 index 0000000..62f8496 --- /dev/null +++ b/patches.suse/btrfs-cleanup-root-usage-by-btrfs_get_alloc_profile.patch @@ -0,0 +1,194 @@ +From: Jeff Mahoney +Date: Wed, 17 May 2017 11:38:35 -0400 +Subject: btrfs: cleanup root usage by btrfs_get_alloc_profile +Git-commit: 1b86826d12dc4acf9576cad9c43da74025dc8074 +Patch-mainline: v4.13-rc1 +References: bsc#1165949 + +There are two places where we don't already know what kind of alloc +profile we need before calling btrfs_get_alloc_profile, but we need +access to a root everywhere we call it. + +This patch adds helpers for btrfs_{data,metadata,system}_alloc_profile() +and relegates btrfs_system_alloc_profile to a static for use in those +two cases. The next patch will eliminate one of those. + +Signed-off-by: Jeff Mahoney +Reviewed-by: Liu Bo +Signed-off-by: David Sterba +Acked-by: Nikolay Borisov +--- + fs/btrfs/ctree.h | 4 +++- + fs/btrfs/extent-tree.c | 28 +++++++++++++++++++++------- + fs/btrfs/inode.c | 3 +-- + fs/btrfs/super.c | 3 +-- + fs/btrfs/volumes.c | 5 ++--- + 5 files changed, 28 insertions(+), 15 deletions(-) + +diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h +index c457cb177340..c13b4859df73 100644 +--- a/fs/btrfs/ctree.h ++++ b/fs/btrfs/ctree.h +@@ -2681,7 +2681,9 @@ void btrfs_get_block_group_trimming(struct btrfs_block_group_cache *cache); + void btrfs_put_block_group_trimming(struct btrfs_block_group_cache *cache); + void btrfs_create_pending_block_groups(struct btrfs_trans_handle *trans, + struct btrfs_fs_info *fs_info); +-u64 btrfs_get_alloc_profile(struct btrfs_root *root, int data); ++u64 btrfs_data_alloc_profile(struct btrfs_fs_info *fs_info); ++u64 btrfs_metadata_alloc_profile(struct btrfs_fs_info *fs_info); ++u64 btrfs_system_alloc_profile(struct btrfs_fs_info *fs_info); + void btrfs_clear_space_info_full(struct btrfs_fs_info *info); + + enum btrfs_reserve_flush_enum { +diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c +index 4c0d3980fe3f..47eb98ffdfc6 100644 +--- a/fs/btrfs/extent-tree.c ++++ b/fs/btrfs/extent-tree.c +@@ -4121,7 +4121,7 @@ static u64 get_alloc_profile(struct btrfs_fs_info *fs_info, u64 orig_flags) + return btrfs_reduce_alloc_profile(fs_info, flags); + } + +-u64 btrfs_get_alloc_profile(struct btrfs_root *root, int data) ++static u64 get_alloc_profile_by_root(struct btrfs_root *root, int data) + { + struct btrfs_fs_info *fs_info = root->fs_info; + u64 flags; +@@ -4138,6 +4138,21 @@ u64 btrfs_get_alloc_profile(struct btrfs_root *root, int data) + return ret; + } + ++u64 btrfs_data_alloc_profile(struct btrfs_fs_info *fs_info) ++{ ++ return get_alloc_profile(fs_info, BTRFS_BLOCK_GROUP_DATA); ++} ++ ++u64 btrfs_metadata_alloc_profile(struct btrfs_fs_info *fs_info) ++{ ++ return get_alloc_profile(fs_info, BTRFS_BLOCK_GROUP_METADATA); ++} ++ ++u64 btrfs_system_alloc_profile(struct btrfs_fs_info *fs_info) ++{ ++ return get_alloc_profile(fs_info, BTRFS_BLOCK_GROUP_SYSTEM); ++} ++ + static u64 btrfs_space_info_used(struct btrfs_space_info *s_info, + bool may_use_included) + { +@@ -4187,7 +4202,7 @@ int btrfs_alloc_data_chunk_ondemand(struct btrfs_inode *inode, u64 bytes) + data_sinfo->force_alloc = CHUNK_ALLOC_FORCE; + spin_unlock(&data_sinfo->lock); + alloc: +- alloc_target = btrfs_get_alloc_profile(root, 1); ++ alloc_target = btrfs_data_alloc_profile(fs_info); + /* + * It is ugly that we don't call nolock join + * transaction for the free space inode case here. +@@ -4463,9 +4478,8 @@ void check_system_chunk(struct btrfs_trans_handle *trans, + } + + if (left < thresh) { +- u64 flags; ++ u64 flags = btrfs_system_alloc_profile(fs_info); + +- flags = btrfs_get_alloc_profile(fs_info->chunk_root, 0); + /* + * Ignore failure to create system chunk. We might end up not + * needing it, as we might not need to COW all nodes/leafs from +@@ -4629,7 +4643,7 @@ static int can_overcommit(struct btrfs_root *root, + if (space_info->flags & BTRFS_BLOCK_GROUP_DATA) + return 0; + +- profile = btrfs_get_alloc_profile(root, 0); ++ profile = get_alloc_profile_by_root(root, 0); + used = btrfs_space_info_used(space_info, false); + + /* +@@ -4894,7 +4908,7 @@ static int flush_space(struct btrfs_fs_info *fs_info, + break; + } + ret = do_chunk_alloc(trans, fs_info, +- btrfs_get_alloc_profile(root, 0), ++ btrfs_metadata_alloc_profile(fs_info), + CHUNK_ALLOC_NO_FORCE); + btrfs_end_transaction(trans); + if (ret > 0 || ret == -ENOSPC) +@@ -7954,7 +7968,7 @@ int btrfs_reserve_extent(struct btrfs_root *root, u64 ram_bytes, + u64 flags; + int ret; + +- flags = btrfs_get_alloc_profile(root, is_data); ++ flags = get_alloc_profile_by_root(root, is_data); + again: + WARN_ON(num_bytes < fs_info->sectorsize); + ret = find_free_extent(fs_info, ram_bytes, num_bytes, empty_size, +diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c +index 683ee05798e5..222d33d78092 100644 +--- a/fs/btrfs/inode.c ++++ b/fs/btrfs/inode.c +@@ -8473,7 +8473,6 @@ static int btrfs_submit_direct_hook(struct btrfs_dio_private *dip, + { + struct inode *inode = dip->inode; + struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb); +- struct btrfs_root *root = BTRFS_I(inode)->root; + struct bio *bio; + struct bio *orig_bio = dip->orig_bio; + u64 start_sector = orig_bio->bi_iter.bi_sector; +@@ -8499,7 +8498,7 @@ static int btrfs_submit_direct_hook(struct btrfs_dio_private *dip, + } + + /* async crcs make it difficult to collect full stripe writes. */ +- if (btrfs_get_alloc_profile(root, 1) & BTRFS_BLOCK_GROUP_RAID56_MASK) ++ if (btrfs_data_alloc_profile(fs_info) & BTRFS_BLOCK_GROUP_RAID56_MASK) + async_submit = 0; + else + async_submit = 1; +diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c +index 4f1cdd5058f1..3371213924bd 100644 +--- a/fs/btrfs/super.c ++++ b/fs/btrfs/super.c +@@ -1898,7 +1898,6 @@ static inline void btrfs_descending_sort_devices( + static int btrfs_calc_avail_data_space(struct btrfs_fs_info *fs_info, + u64 *free_bytes) + { +- struct btrfs_root *root = fs_info->tree_root; + struct btrfs_device_info *devices_info; + struct btrfs_fs_devices *fs_devices = fs_info->fs_devices; + struct btrfs_device *device; +@@ -1932,7 +1931,7 @@ static int btrfs_calc_avail_data_space(struct btrfs_fs_info *fs_info, + return -ENOMEM; + + /* calc min stripe number for data space allocation */ +- type = btrfs_get_alloc_profile(root, 1); ++ type = btrfs_data_alloc_profile(fs_info); + if (type & BTRFS_BLOCK_GROUP_RAID0) { + min_stripes = 2; + num_stripes = nr_devices; +diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c +index e37f95976443..e28c113785bb 100644 +--- a/fs/btrfs/volumes.c ++++ b/fs/btrfs/volumes.c +@@ -5019,20 +5019,19 @@ int btrfs_alloc_chunk(struct btrfs_trans_handle *trans, + static noinline int init_first_rw_device(struct btrfs_trans_handle *trans, + struct btrfs_fs_info *fs_info) + { +- struct btrfs_root *extent_root = fs_info->extent_root; + u64 chunk_offset; + u64 sys_chunk_offset; + u64 alloc_profile; + int ret; + + chunk_offset = find_next_chunk(fs_info); +- alloc_profile = btrfs_get_alloc_profile(extent_root, 0); ++ alloc_profile = btrfs_metadata_alloc_profile(fs_info); + ret = __btrfs_alloc_chunk(trans, chunk_offset, alloc_profile); + if (ret) + return ret; + + sys_chunk_offset = find_next_chunk(fs_info); +- alloc_profile = btrfs_get_alloc_profile(fs_info->chunk_root, 0); ++ alloc_profile = btrfs_system_alloc_profile(fs_info); + ret = __btrfs_alloc_chunk(trans, sys_chunk_offset, alloc_profile); + return ret; + } + diff --git a/patches.suse/btrfs-delayed-ref-pass-delayed_refs-directly-to-btrfs_delayed_ref_lock.patch b/patches.suse/btrfs-delayed-ref-pass-delayed_refs-directly-to-btrfs_delayed_ref_lock.patch new file mode 100644 index 0000000..e48fb32 --- /dev/null +++ b/patches.suse/btrfs-delayed-ref-pass-delayed_refs-directly-to-btrfs_delayed_ref_lock.patch @@ -0,0 +1,62 @@ +From: Lu Fengqi +Date: Thu, 11 Oct 2018 13:40:34 +0800 +Subject: btrfs: delayed-ref: pass delayed_refs directly to + btrfs_delayed_ref_lock +Git-commit: 9e920a6f03e40b1eb712f38b29ad5880153754e2 +Patch-mainline: v4.20-rc1 +References: bsc#1165949 + +Since trans is only used for referring to delayed_refs, there is no need +to pass it instead of delayed_refs to btrfs_delayed_ref_lock(). + +No functional change. + +Reviewed-by: Nikolay Borisov +Signed-off-by: Lu Fengqi +Reviewed-by: David Sterba +Signed-off-by: David Sterba +Acked-by: Nikolay Borisov +--- + fs/btrfs/delayed-ref.c | 5 +---- + fs/btrfs/delayed-ref.h | 2 +- + fs/btrfs/extent-tree.c | 2 +- + 3 files changed, 3 insertions(+), 6 deletions(-) + +--- a/fs/btrfs/delayed-ref.c ++++ b/fs/btrfs/delayed-ref.c +@@ -210,12 +210,9 @@ find_ref_head(struct rb_root *root, u64 + return NULL; + } + +-int btrfs_delayed_ref_lock(struct btrfs_trans_handle *trans, ++int btrfs_delayed_ref_lock(struct btrfs_delayed_ref_root *delayed_refs, + struct btrfs_delayed_ref_head *head) + { +- struct btrfs_delayed_ref_root *delayed_refs; +- +- delayed_refs = &trans->transaction->delayed_refs; + assert_spin_locked(&delayed_refs->lock); + if (mutex_trylock(&head->mutex)) + return 0; +--- a/fs/btrfs/delayed-ref.h ++++ b/fs/btrfs/delayed-ref.h +@@ -270,7 +270,7 @@ void btrfs_merge_delayed_refs(struct btr + struct btrfs_delayed_ref_head * + btrfs_find_delayed_ref_head(struct btrfs_delayed_ref_root *delayed_refs, + u64 bytenr); +-int btrfs_delayed_ref_lock(struct btrfs_trans_handle *trans, ++int btrfs_delayed_ref_lock(struct btrfs_delayed_ref_root *delayed_refs, + struct btrfs_delayed_ref_head *head); + static inline void btrfs_delayed_ref_unlock(struct btrfs_delayed_ref_head *head) + { +--- a/fs/btrfs/extent-tree.c ++++ b/fs/btrfs/extent-tree.c +@@ -2685,7 +2685,7 @@ static noinline int __btrfs_run_delayed_ + + /* grab the lock that says we are going to process + * all the refs for this head */ +- ret = btrfs_delayed_ref_lock(trans, locked_ref); ++ ret = btrfs_delayed_ref_lock(delayed_refs, locked_ref); + spin_unlock(&delayed_refs->lock); + /* + * we may have dropped the spin lock to get the head diff --git a/patches.suse/btrfs-drop-unused-space_info-parameter-from-create_space_info.patch b/patches.suse/btrfs-drop-unused-space_info-parameter-from-create_space_info.patch new file mode 100644 index 0000000..6142637 --- /dev/null +++ b/patches.suse/btrfs-drop-unused-space_info-parameter-from-create_space_info.patch @@ -0,0 +1,76 @@ +From: Lu Fengqi +Date: Mon, 28 May 2018 14:30:27 +0800 +Subject: btrfs: drop unused space_info parameter from create_space_info +Git-commit: 4ca616832783ce6563b59b2d4764fdbb272e0362 +Patch-mainline: v4.18-rc1 +References: bsc#1165949 + +Since commit dc2d3005d27d ("btrfs: remove dead create_space_info +calls"), there is only one caller btrfs_init_space_info. However, it +doesn't need create_space_info to return space_info at all. + +Signed-off-by: Lu Fengqi +Reviewed-by: Nikolay Borisov +Signed-off-by: David Sterba +Acked-by: Nikolay Borisov +--- + fs/btrfs/extent-tree.c | 13 +++++-------- + 1 file changed, 5 insertions(+), 8 deletions(-) + +diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c +index 7273dcddcdf4..7ebb05fe2cd8 100644 +--- a/fs/btrfs/extent-tree.c ++++ b/fs/btrfs/extent-tree.c +@@ -4007,8 +4007,7 @@ static const char *alloc_name(u64 flags) + }; + } + +-static int create_space_info(struct btrfs_fs_info *info, u64 flags, +- struct btrfs_space_info **new) ++static int create_space_info(struct btrfs_fs_info *info, u64 flags) + { + + struct btrfs_space_info *space_info; +@@ -4046,7 +4045,6 @@ static int create_space_info(struct btrfs_fs_info *info, u64 flags, + return ret; + } + +- *new = space_info; + list_add_rcu(&space_info->list, &info->space_info); + if (flags & BTRFS_BLOCK_GROUP_DATA) + info->data_sinfo = space_info; +@@ -10825,7 +10823,6 @@ void btrfs_delete_unused_bgs(struct btrfs_fs_info *fs_info) + + int btrfs_init_space_info(struct btrfs_fs_info *fs_info) + { +- struct btrfs_space_info *space_info; + struct btrfs_super_block *disk_super; + u64 features; + u64 flags; +@@ -10841,21 +10838,21 @@ int btrfs_init_space_info(struct btrfs_fs_info *fs_info) + mixed = 1; + + flags = BTRFS_BLOCK_GROUP_SYSTEM; +- ret = create_space_info(fs_info, flags, &space_info); ++ ret = create_space_info(fs_info, flags); + if (ret) + goto out; + + if (mixed) { + flags = BTRFS_BLOCK_GROUP_METADATA | BTRFS_BLOCK_GROUP_DATA; +- ret = create_space_info(fs_info, flags, &space_info); ++ ret = create_space_info(fs_info, flags); + } else { + flags = BTRFS_BLOCK_GROUP_METADATA; +- ret = create_space_info(fs_info, flags, &space_info); ++ ret = create_space_info(fs_info, flags); + if (ret) + goto out; + + flags = BTRFS_BLOCK_GROUP_DATA; +- ret = create_space_info(fs_info, flags, &space_info); ++ ret = create_space_info(fs_info, flags); + } + out: + return ret; + diff --git a/patches.suse/btrfs-dump_space_info-when-encountering-total_bytes_pinned-0-at-umount.patch b/patches.suse/btrfs-dump_space_info-when-encountering-total_bytes_pinned-0-at-umount.patch index 7dda76c..f59c069 100644 --- a/patches.suse/btrfs-dump_space_info-when-encountering-total_bytes_pinned-0-at-umount.patch +++ b/patches.suse/btrfs-dump_space_info-when-encountering-total_bytes_pinned-0-at-umount.patch @@ -8,38 +8,17 @@ can track down likely causes. Signed-off-by: Jeff Mahoney --- - fs/btrfs/extent-tree.c | 9 +++++++-- - 1 file changed, 7 insertions(+), 2 deletions(-) + fs/btrfs/space-info.c | 2 ++ + 1 file changed, 2 insertions(+) ---- a/fs/btrfs/extent-tree.c -+++ b/fs/btrfs/extent-tree.c -@@ -7949,6 +7949,8 @@ static void dump_space_info(struct btrfs +--- a/fs/btrfs/space-info.c ++++ b/fs/btrfs/space-info.c +@@ -298,6 +298,8 @@ static void __btrfs_dump_space_info(stru info->total_bytes, info->bytes_used, info->bytes_pinned, info->bytes_reserved, info->bytes_may_use, info->bytes_readonly); + btrfs_info(fs_info, "total_bytes_pinned=%lld", + percpu_counter_sum(&info->total_bytes_pinned)); - spin_unlock(&info->lock); - if (!dump_block_groups) -@@ -9848,6 +9850,7 @@ int btrfs_free_block_groups(struct btrfs - - while (!list_empty(&info->space_info)) { - int i; -+ s64 pinned; - - space_info = list_entry(info->space_info.next, - struct btrfs_space_info, -@@ -9857,9 +9860,11 @@ int btrfs_free_block_groups(struct btrfs - * Do not hide this behind enospc_debug, this is actually - * important and indicates a real bug if this happens. - */ -+ pinned = percpu_counter_sum(&space_info->total_bytes_pinned); - if (WARN_ON(space_info->bytes_pinned > 0 || - space_info->bytes_reserved > 0 || -- space_info->bytes_may_use > 0)) -+ space_info->bytes_may_use > 0 || -+ pinned != 0)) - dump_space_info(info, space_info, 0, 0); - list_del(&space_info->list); - for (i = 0; i < BTRFS_NR_RAID_TYPES; i++) { + DUMP_BLOCK_RSV(fs_info, global_block_rsv); + DUMP_BLOCK_RSV(fs_info, trans_block_rsv); diff --git a/patches.suse/btrfs-extent-tree-add-lockdep-assert-when-updating-space-info.patch b/patches.suse/btrfs-extent-tree-add-lockdep-assert-when-updating-space-info.patch new file mode 100644 index 0000000..d487254 --- /dev/null +++ b/patches.suse/btrfs-extent-tree-add-lockdep-assert-when-updating-space-info.patch @@ -0,0 +1,30 @@ +From: Qu Wenruo +Date: Mon, 29 Apr 2019 14:03:32 +0800 +Subject: btrfs: extent-tree: Add lockdep assert when updating space info +Git-commit: 0185f364cb65855cdf5dfd0de11f8f9622940250 +Patch-mainline: v5.3-rc1 +References: bsc#1165949 + +Just add a safe net for btrfs_space_info member updating. + +Signed-off-by: Qu Wenruo +Reviewed-by: David Sterba +Signed-off-by: David Sterba +Acked-by: Nikolay Borisov +--- + fs/btrfs/extent-tree.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c +index af73264e33a5..f37daddbeabe 100644 +--- a/fs/btrfs/extent-tree.c ++++ b/fs/btrfs/extent-tree.c +@@ -58,6 +58,7 @@ enum { + static inline void update_##name(struct btrfs_space_info *sinfo, \ + s64 bytes) \ + { \ ++ lockdep_assert_held(&sinfo->lock); \ + if (bytes < 0 && sinfo->name < -bytes) { \ + WARN_ON(1); \ + sinfo->name = 0; \ + diff --git a/patches.suse/btrfs-extent-tree-add-trace-events-for-space-info-numbers-update.patch b/patches.suse/btrfs-extent-tree-add-trace-events-for-space-info-numbers-update.patch new file mode 100644 index 0000000..dbd8c41 --- /dev/null +++ b/patches.suse/btrfs-extent-tree-add-trace-events-for-space-info-numbers-update.patch @@ -0,0 +1,282 @@ +From: Qu Wenruo +Date: Mon, 29 Apr 2019 14:03:33 +0800 +Subject: btrfs: extent-tree: Add trace events for space info numbers update +Git-commit: 480b9b4d847fe18f4a559f5cac718d9b2cbcdcaf +Patch-mainline: v5.3-rc1 +References: bsc#1165949 + +Add trace event for update_bytes_pinned() and update_bytes_may_use() to +detect underflow better. + +The output would be something like (only showing data part): + + ## Buffered write start, 16K total ## + 2255.954 xfs_io/860 btrfs:update_bytes_may_use:(nil)U: type=DATA old=0 diff=4096 + 2257.169 sudo/860 btrfs:update_bytes_may_use:(nil)U: type=DATA old=4096 diff=4096 + 2257.346 sudo/860 btrfs:update_bytes_may_use:(nil)U: type=DATA old=8192 diff=4096 + 2257.542 sudo/860 btrfs:update_bytes_may_use:(nil)U: type=DATA old=12288 diff=4096 + + ## Delalloc start ## + 3727.853 kworker/u8:3-e/700 btrfs:update_bytes_may_use:(nil)U: type=DATA old=16384 diff=-16384 + + ## Space cache update ## + 3733.132 sudo/862 btrfs:update_bytes_may_use:(nil)U: type=DATA old=0 diff=65536 + 3733.169 sudo/862 btrfs:update_bytes_may_use:(nil)U: type=DATA old=65536 diff=-65536 + 3739.868 sudo/862 btrfs:update_bytes_may_use:(nil)U: type=DATA old=0 diff=65536 + 3739.891 sudo/862 btrfs:update_bytes_may_use:(nil)U: type=DATA old=65536 diff=-65536 + +These two trace events will allow bcc tool to probe btrfs_space_info +changes and detect underflow with more details (e.g. backtrace for each +update). + +Signed-off-by: Qu Wenruo +Reviewed-by: David Sterba +Signed-off-by: David Sterba +Acked-by: Nikolay Borisov +--- + fs/btrfs/extent-tree.c | 36 +++++++++++++++++-------------- + include/trace/events/btrfs.h | 49 +++++++++++++++++++++++++++++++++++++++---- + 2 files changed, 65 insertions(+), 20 deletions(-) + +--- a/fs/btrfs/extent-tree.c ++++ b/fs/btrfs/extent-tree.c +@@ -66,10 +66,12 @@ enum { + * Declare a helper function to detect underflow of various space info members + */ + #define DECLARE_SPACE_INFO_UPDATE(name) \ +-static inline void update_##name(struct btrfs_space_info *sinfo, \ ++static inline void update_##name(struct btrfs_fs_info *fs_info, \ ++ struct btrfs_space_info *sinfo, \ + s64 bytes) \ + { \ + lockdep_assert_held(&sinfo->lock); \ ++ trace_update_##name(fs_info, sinfo, sinfo->name, bytes); \ + if (bytes < 0 && sinfo->name < -bytes) { \ + WARN_ON(1); \ + sinfo->name = 0; \ +@@ -4422,7 +4424,7 @@ commit_trans: + data_sinfo->flags, bytes, 1); + return -ENOSPC; + } +- update_bytes_may_use(data_sinfo, bytes); ++ update_bytes_may_use(fs_info, data_sinfo, bytes); + trace_btrfs_space_reservation(fs_info, "space_info", + data_sinfo->flags, bytes, 1); + spin_unlock(&data_sinfo->lock); +@@ -4475,7 +4477,7 @@ void btrfs_free_reserved_data_space_noqu + + data_sinfo = fs_info->data_sinfo; + spin_lock(&data_sinfo->lock); +- update_bytes_may_use(data_sinfo, -len); ++ update_bytes_may_use(fs_info, data_sinfo, -len); + trace_btrfs_space_reservation(fs_info, "space_info", + data_sinfo->flags, len, 0); + spin_unlock(&data_sinfo->lock); +@@ -5377,12 +5379,12 @@ static int __reserve_metadata_bytes(stru + * If not things get more complicated. + */ + if (used + orig_bytes <= space_info->total_bytes) { +- update_bytes_may_use(space_info, orig_bytes); ++ update_bytes_may_use(fs_info, space_info, orig_bytes); + trace_btrfs_space_reservation(fs_info, "space_info", + space_info->flags, orig_bytes, 1); + ret = 0; + } else if (can_overcommit(root, space_info, orig_bytes, flush)) { +- update_bytes_may_use(space_info, orig_bytes); ++ update_bytes_may_use(fs_info, space_info, orig_bytes); + trace_btrfs_space_reservation(fs_info, "space_info", + space_info->flags, orig_bytes, 1); + ret = 0; +@@ -5706,7 +5708,7 @@ again: + flush = BTRFS_RESERVE_FLUSH_ALL; + goto again; + } +- update_bytes_may_use(space_info, -num_bytes); ++ update_bytes_may_use(fs_info, space_info, -num_bytes); + trace_btrfs_space_reservation(fs_info, "space_info", + space_info->flags, num_bytes, 0); + spin_unlock(&space_info->lock); +@@ -5734,7 +5736,8 @@ again: + ticket->bytes, 1); + list_del_init(&ticket->list); + num_bytes -= ticket->bytes; +- update_bytes_may_use(space_info, ticket->bytes); ++ update_bytes_may_use(fs_info, space_info, ++ ticket->bytes); + ticket->bytes = 0; + space_info->tickets_id++; + wake_up(&ticket->wait); +@@ -5742,7 +5745,7 @@ again: + trace_btrfs_space_reservation(fs_info, "space_info", + space_info->flags, + num_bytes, 1); +- update_bytes_may_use(space_info, num_bytes); ++ update_bytes_may_use(fs_info, space_info, num_bytes); + ticket->bytes -= num_bytes; + num_bytes = 0; + } +@@ -6042,14 +6045,14 @@ static void update_global_block_rsv(stru + num_bytes = min(num_bytes, + block_rsv->size - block_rsv->reserved); + block_rsv->reserved += num_bytes; +- update_bytes_may_use(sinfo, num_bytes); ++ update_bytes_may_use(fs_info, sinfo, num_bytes); + trace_btrfs_space_reservation(fs_info, "space_info", + sinfo->flags, num_bytes, + 1); + } + } else if (block_rsv->reserved > block_rsv->size) { + num_bytes = block_rsv->reserved - block_rsv->size; +- update_bytes_may_use(sinfo, -num_bytes); ++ update_bytes_may_use(fs_info, sinfo, -num_bytes); + trace_btrfs_space_reservation(fs_info, "space_info", + sinfo->flags, num_bytes, 0); + block_rsv->reserved = block_rsv->size; +@@ -6536,7 +6539,7 @@ static int update_block_group(struct btr + old_val -= num_bytes; + btrfs_set_block_group_used(&cache->item, old_val); + cache->pinned += num_bytes; +- update_bytes_pinned(cache->space_info, num_bytes); ++ update_bytes_pinned(info, cache->space_info, num_bytes); + cache->space_info->bytes_used -= num_bytes; + cache->space_info->disk_used -= num_bytes * factor; + spin_unlock(&cache->lock); +@@ -6617,7 +6620,7 @@ static int pin_down_extent(struct btrfs_ + spin_lock(&cache->space_info->lock); + spin_lock(&cache->lock); + cache->pinned += num_bytes; +- update_bytes_pinned(cache->space_info, num_bytes); ++ update_bytes_pinned(fs_info, cache->space_info, num_bytes); + if (reserved) { + cache->reserved -= num_bytes; + cache->space_info->bytes_reserved -= num_bytes; +@@ -6834,7 +6837,7 @@ static int btrfs_add_reserved_bytes(stru + trace_btrfs_space_reservation(cache->fs_info, + "space_info", space_info->flags, + ram_bytes, 0); +- update_bytes_may_use(space_info, -ram_bytes); ++ update_bytes_may_use(cache->fs_info, space_info, -ram_bytes); + if (delalloc) + cache->delalloc_bytes += num_bytes; + } +@@ -6991,7 +6994,7 @@ static int unpin_extent_range(struct btr + spin_lock(&space_info->lock); + spin_lock(&cache->lock); + cache->pinned -= len; +- update_bytes_pinned(space_info, -len); ++ update_bytes_pinned(fs_info, space_info, -len); + + trace_btrfs_space_reservation(fs_info, "pinned", + space_info->flags, len, 0); +@@ -7011,7 +7014,8 @@ static int unpin_extent_range(struct btr + to_add = min(len, global_rsv->size - + global_rsv->reserved); + global_rsv->reserved += to_add; +- update_bytes_may_use(space_info, to_add); ++ update_bytes_may_use(fs_info, space_info, ++ to_add); + if (global_rsv->reserved >= global_rsv->size) + global_rsv->full = 1; + trace_btrfs_space_reservation(fs_info, +@@ -11175,7 +11179,7 @@ void btrfs_delete_unused_bgs(struct btrf + spin_lock(&space_info->lock); + spin_lock(&block_group->lock); + +- update_bytes_pinned(space_info, -block_group->pinned); ++ update_bytes_pinned(fs_info, space_info, -block_group->pinned); + space_info->bytes_readonly += block_group->pinned; + percpu_counter_add(&space_info->total_bytes_pinned, + -block_group->pinned); +--- a/include/trace/events/btrfs.h ++++ b/include/trace/events/btrfs.h +@@ -27,6 +27,7 @@ struct __btrfs_workqueue; + struct btrfs_qgroup_extent_record; + struct btrfs_qgroup; + struct prelim_ref; ++struct btrfs_space_info; + + #define show_ref_type(type) \ + __print_symbolic(type, \ +@@ -662,7 +663,7 @@ TRACE_EVENT(btrfs_add_block_group, + { BTRFS_DROP_DELAYED_REF, "DROP_DELAYED_REF" }, \ + { BTRFS_ADD_DELAYED_EXTENT, "ADD_DELAYED_EXTENT" }, \ + { BTRFS_UPDATE_DELAYED_HEAD, "UPDATE_DELAYED_HEAD" }) +- ++ + + DECLARE_EVENT_CLASS(btrfs_delayed_tree_ref, + +@@ -676,7 +677,7 @@ DECLARE_EVENT_CLASS(btrfs_delayed_tree_r + TP_STRUCT__entry_btrfs( + __field( u64, bytenr ) + __field( u64, num_bytes ) +- __field( int, action ) ++ __field( int, action ) + __field( u64, parent ) + __field( u64, ref_root ) + __field( int, level ) +@@ -739,7 +740,7 @@ DECLARE_EVENT_CLASS(btrfs_delayed_data_r + TP_STRUCT__entry_btrfs( + __field( u64, bytenr ) + __field( u64, num_bytes ) +- __field( int, action ) ++ __field( int, action ) + __field( u64, parent ) + __field( u64, ref_root ) + __field( u64, owner ) +@@ -805,7 +806,7 @@ DECLARE_EVENT_CLASS(btrfs_delayed_ref_he + TP_STRUCT__entry_btrfs( + __field( u64, bytenr ) + __field( u64, num_bytes ) +- __field( int, action ) ++ __field( int, action ) + __field( int, is_data ) + ), + +@@ -1802,6 +1803,46 @@ TRACE_EVENT(btrfs_inode_mod_outstanding_ + show_root_type(__entry->root_objectid), + (unsigned long long)__entry->ino, __entry->mod) + ); ++ ++DECLARE_EVENT_CLASS(btrfs__space_info_update, ++ ++ TP_PROTO(struct btrfs_fs_info *fs_info, ++ struct btrfs_space_info *sinfo, u64 old, s64 diff), ++ ++ TP_ARGS(fs_info, sinfo, old, diff), ++ ++ TP_STRUCT__entry_btrfs( ++ __field( u64, type ) ++ __field( u64, old ) ++ __field( s64, diff ) ++ ), ++ ++ TP_fast_assign_btrfs(fs_info, ++ __entry->type = sinfo->flags; ++ __entry->old = old; ++ __entry->diff = diff; ++ ), ++ TP_printk_btrfs("type=%s old=%llu diff=%lld", ++ __print_flags(__entry->type, "|", BTRFS_GROUP_FLAGS), ++ __entry->old, __entry->diff) ++); ++ ++DEFINE_EVENT(btrfs__space_info_update, update_bytes_may_use, ++ ++ TP_PROTO(struct btrfs_fs_info *fs_info, ++ struct btrfs_space_info *sinfo, u64 old, s64 diff), ++ ++ TP_ARGS(fs_info, sinfo, old, diff) ++); ++ ++DEFINE_EVENT(btrfs__space_info_update, update_bytes_pinned, ++ ++ TP_PROTO(struct btrfs_fs_info *fs_info, ++ struct btrfs_space_info *sinfo, u64 old, s64 diff), ++ ++ TP_ARGS(fs_info, sinfo, old, diff) ++); ++ + #endif /* _TRACE_BTRFS_H */ + + /* This part must be outside protection */ diff --git a/patches.suse/btrfs-extent-tree-detect-bytes_may_use-underflow-earlier.patch b/patches.suse/btrfs-extent-tree-detect-bytes_may_use-underflow-earlier.patch new file mode 100644 index 0000000..8f10694 --- /dev/null +++ b/patches.suse/btrfs-extent-tree-detect-bytes_may_use-underflow-earlier.patch @@ -0,0 +1,169 @@ +From: Qu Wenruo +Date: Wed, 24 Oct 2018 20:24:01 +0800 +Subject: btrfs: extent-tree: Detect bytes_may_use underflow earlier +Git-commit: 9f9b8e8d0ebe1af42ddd3c86e12569c53914a89d +Patch-mainline: v5.0-rc1 +References: bsc#1165949 + +Although we have space_info::bytes_may_use underflow detection in +btrfs_free_reserved_data_space_noquota(), we have more callers who are +subtracting number from space_info::bytes_may_use. + +So instead of doing underflow detection for every caller, introduce a +new wrapper update_bytes_may_use() to replace open coded bytes_may_use +modifiers. + +This also introduce a macro to declare more wrappers, but currently +space_info::bytes_may_use is the mostly interesting one. + +Reviewed-by: Josef Bacik +Signed-off-by: Qu Wenruo +Signed-off-by: Lu Fengqi +Signed-off-by: David Sterba +Acked-by: Nikolay Borisov +--- + fs/btrfs/extent-tree.c | 46 ++++++++++++++++++++++++++++++---------------- + 1 file changed, 30 insertions(+), 16 deletions(-) + +--- a/fs/btrfs/extent-tree.c ++++ b/fs/btrfs/extent-tree.c +@@ -62,6 +62,23 @@ enum { + CHUNK_ALLOC_FORCE = 2, + }; + ++/* ++ * Declare a helper function to detect underflow of various space info members ++ */ ++#define DECLARE_SPACE_INFO_UPDATE(name) \ ++static inline void update_##name(struct btrfs_space_info *sinfo, \ ++ s64 bytes) \ ++{ \ ++ if (bytes < 0 && sinfo->name < -bytes) { \ ++ WARN_ON(1); \ ++ sinfo->name = 0; \ ++ return; \ ++ } \ ++ sinfo->name += bytes; \ ++} ++ ++DECLARE_SPACE_INFO_UPDATE(bytes_may_use); ++ + static int update_block_group(struct btrfs_trans_handle *trans, + struct btrfs_fs_info *fs_info, u64 bytenr, + u64 num_bytes, int alloc); +@@ -4382,7 +4399,7 @@ commit_trans: + data_sinfo->flags, bytes, 1); + return -ENOSPC; + } +- data_sinfo->bytes_may_use += bytes; ++ update_bytes_may_use(data_sinfo, bytes); + trace_btrfs_space_reservation(fs_info, "space_info", + data_sinfo->flags, bytes, 1); + spin_unlock(&data_sinfo->lock); +@@ -4435,10 +4452,7 @@ void btrfs_free_reserved_data_space_noqu + + data_sinfo = fs_info->data_sinfo; + spin_lock(&data_sinfo->lock); +- if (WARN_ON(data_sinfo->bytes_may_use < len)) +- data_sinfo->bytes_may_use = 0; +- else +- data_sinfo->bytes_may_use -= len; ++ update_bytes_may_use(data_sinfo, -len); + trace_btrfs_space_reservation(fs_info, "space_info", + data_sinfo->flags, len, 0); + spin_unlock(&data_sinfo->lock); +@@ -5236,7 +5250,7 @@ static int wait_reserve_ticket(struct bt + list_del_init(&ticket->list); + if (ticket->bytes && ticket->bytes < orig_bytes) { + u64 num_bytes = orig_bytes - ticket->bytes; +- space_info->bytes_may_use -= num_bytes; ++ update_bytes_may_use(space_info, -num_bytes); + trace_btrfs_space_reservation(fs_info, "space_info", + space_info->flags, num_bytes, 0); + } +@@ -5282,12 +5296,12 @@ static int __reserve_metadata_bytes(stru + * If not things get more complicated. + */ + if (used + orig_bytes <= space_info->total_bytes) { +- space_info->bytes_may_use += orig_bytes; ++ update_bytes_may_use(space_info, orig_bytes); + trace_btrfs_space_reservation(fs_info, "space_info", + space_info->flags, orig_bytes, 1); + ret = 0; + } else if (can_overcommit(root, space_info, orig_bytes, flush)) { +- space_info->bytes_may_use += orig_bytes; ++ update_bytes_may_use(space_info, orig_bytes); + trace_btrfs_space_reservation(fs_info, "space_info", + space_info->flags, orig_bytes, 1); + ret = 0; +@@ -5349,7 +5363,7 @@ static int __reserve_metadata_bytes(stru + if (ticket.bytes) { + if (ticket.bytes < orig_bytes) { + u64 num_bytes = orig_bytes - ticket.bytes; +- space_info->bytes_may_use -= num_bytes; ++ update_bytes_may_use(space_info, -num_bytes); + trace_btrfs_space_reservation(fs_info, "space_info", + space_info->flags, + num_bytes, 0); +@@ -5530,7 +5544,7 @@ again: + flush = BTRFS_RESERVE_FLUSH_ALL; + goto again; + } +- space_info->bytes_may_use -= num_bytes; ++ update_bytes_may_use(space_info, -num_bytes); + trace_btrfs_space_reservation(fs_info, "space_info", + space_info->flags, num_bytes, 0); + spin_unlock(&space_info->lock); +@@ -5558,7 +5572,7 @@ again: + ticket->bytes, 1); + list_del_init(&ticket->list); + num_bytes -= ticket->bytes; +- space_info->bytes_may_use += ticket->bytes; ++ update_bytes_may_use(space_info, ticket->bytes); + ticket->bytes = 0; + space_info->tickets_id++; + wake_up(&ticket->wait); +@@ -5566,7 +5580,7 @@ again: + trace_btrfs_space_reservation(fs_info, "space_info", + space_info->flags, + num_bytes, 1); +- space_info->bytes_may_use += num_bytes; ++ update_bytes_may_use(space_info, num_bytes); + ticket->bytes -= num_bytes; + num_bytes = 0; + } +@@ -5880,14 +5894,14 @@ static void update_global_block_rsv(stru + num_bytes = min(num_bytes, + block_rsv->size - block_rsv->reserved); + block_rsv->reserved += num_bytes; +- sinfo->bytes_may_use += num_bytes; ++ update_bytes_may_use(sinfo, num_bytes); + trace_btrfs_space_reservation(fs_info, "space_info", + sinfo->flags, num_bytes, + 1); + } + } else if (block_rsv->reserved > block_rsv->size) { + num_bytes = block_rsv->reserved - block_rsv->size; +- sinfo->bytes_may_use -= num_bytes; ++ update_bytes_may_use(sinfo, -num_bytes); + trace_btrfs_space_reservation(fs_info, "space_info", + sinfo->flags, num_bytes, 0); + block_rsv->reserved = block_rsv->size; +@@ -6601,7 +6615,7 @@ static int btrfs_add_reserved_bytes(stru + trace_btrfs_space_reservation(cache->fs_info, + "space_info", space_info->flags, + ram_bytes, 0); +- space_info->bytes_may_use -= ram_bytes; ++ update_bytes_may_use(space_info, -ram_bytes); + if (delalloc) + cache->delalloc_bytes += num_bytes; + } +@@ -6778,7 +6792,7 @@ static int unpin_extent_range(struct btr + to_add = min(len, global_rsv->size - + global_rsv->reserved); + global_rsv->reserved += to_add; +- space_info->bytes_may_use += to_add; ++ update_bytes_may_use(space_info, to_add); + if (global_rsv->reserved >= global_rsv->size) + global_rsv->full = 1; + trace_btrfs_space_reservation(fs_info, diff --git a/patches.suse/btrfs-extent-tree-detect-bytes_pinned-underflow-earlier.patch b/patches.suse/btrfs-extent-tree-detect-bytes_pinned-underflow-earlier.patch new file mode 100644 index 0000000..e22026f --- /dev/null +++ b/patches.suse/btrfs-extent-tree-detect-bytes_pinned-underflow-earlier.patch @@ -0,0 +1,65 @@ +From: Lu Fengqi +Date: Wed, 24 Oct 2018 20:24:02 +0800 +Subject: btrfs: extent-tree: Detect bytes_pinned underflow earlier +Git-commit: e2907c1a6ae1842f9c1d5393bbe966c1ccfbc335 +Patch-mainline: v5.0-rc1 +References: bsc#1165949 + +Introduce a new wrapper update_bytes_pinned to replace open coded +bytes_pinned modifiers. Now the underflows of space_info::bytes_pinned +get detected and reported. + +Reviewed-by: Josef Bacik +Signed-off-by: Lu Fengqi +Signed-off-by: David Sterba +Acked-by: Nikolay Borisov +--- + fs/btrfs/extent-tree.c | 9 +++++---- + 1 file changed, 5 insertions(+), 4 deletions(-) + +--- a/fs/btrfs/extent-tree.c ++++ b/fs/btrfs/extent-tree.c +@@ -78,6 +78,7 @@ static inline void update_##name(struct + } + + DECLARE_SPACE_INFO_UPDATE(bytes_may_use); ++DECLARE_SPACE_INFO_UPDATE(bytes_pinned); + + static int update_block_group(struct btrfs_trans_handle *trans, + struct btrfs_fs_info *fs_info, u64 bytenr, +@@ -6309,7 +6310,7 @@ static int update_block_group(struct btr + old_val -= num_bytes; + btrfs_set_block_group_used(&cache->item, old_val); + cache->pinned += num_bytes; +- cache->space_info->bytes_pinned += num_bytes; ++ update_bytes_pinned(cache->space_info, num_bytes); + cache->space_info->bytes_used -= num_bytes; + cache->space_info->disk_used -= num_bytes * factor; + spin_unlock(&cache->lock); +@@ -6386,7 +6387,7 @@ static int pin_down_extent(struct btrfs_ + spin_lock(&cache->space_info->lock); + spin_lock(&cache->lock); + cache->pinned += num_bytes; +- cache->space_info->bytes_pinned += num_bytes; ++ update_bytes_pinned(cache->space_info, num_bytes); + if (reserved) { + cache->reserved -= num_bytes; + cache->space_info->bytes_reserved -= num_bytes; +@@ -6760,7 +6761,7 @@ static int unpin_extent_range(struct btr + spin_lock(&space_info->lock); + spin_lock(&cache->lock); + cache->pinned -= len; +- space_info->bytes_pinned -= len; ++ update_bytes_pinned(space_info, -len); + + trace_btrfs_space_reservation(fs_info, "pinned", + space_info->flags, len, 0); +@@ -10855,7 +10856,7 @@ void btrfs_delete_unused_bgs(struct btrf + spin_lock(&space_info->lock); + spin_lock(&block_group->lock); + +- space_info->bytes_pinned -= block_group->pinned; ++ update_bytes_pinned(space_info, -block_group->pinned); + space_info->bytes_readonly += block_group->pinned; + percpu_counter_add(&space_info->total_bytes_pinned, + -block_group->pinned); diff --git a/patches.suse/btrfs-extent_io-Kill-the-forward-declaration-of-flus.patch b/patches.suse/btrfs-extent_io-Kill-the-forward-declaration-of-flus.patch new file mode 100644 index 0000000..d04880d --- /dev/null +++ b/patches.suse/btrfs-extent_io-Kill-the-forward-declaration-of-flus.patch @@ -0,0 +1,114 @@ +From bb58eb9e167d087cc518f7a71c3c00f1671958da Mon Sep 17 00:00:00 2001 +From: Qu Wenruo +Date: Fri, 25 Jan 2019 13:09:15 +0800 +Patch-mainline: v5.1 +Git-commit: bb58eb9e167d087cc518f7a71c3c00f1671958da +References: bsc#1168273 +Subject: [PATCH] btrfs: extent_io: Kill the forward declaration of + flush_write_bio + +There is no need to forward declare flush_write_bio(), as it only +depends on submit_one_bio(). Both of them are pretty small, just move +them to kill the forward declaration. + +Reviewed-by: Nikolay Borisov +Reviewed-by: Johannes Thumshirn +Signed-off-by: Qu Wenruo +Signed-off-by: David Sterba +--- + fs/btrfs/extent_io.c | 70 ++++++++++++++++++++++++--------------------------- + 1 file changed, 34 insertions(+), 36 deletions(-) + +--- a/fs/btrfs/extent_io.c ++++ b/fs/btrfs/extent_io.c +@@ -146,7 +146,40 @@ static void add_extent_changeset(struct + BUG_ON(ret < 0); + } + +-static void flush_write_bio(struct extent_page_data *epd); ++static int __must_check submit_one_bio(struct bio *bio, int mirror_num, ++ unsigned long bio_flags) ++{ ++ blk_status_t ret = 0; ++ struct bio_vec *bvec = bio_last_bvec_all(bio); ++ struct page *page = bvec->bv_page; ++ struct extent_io_tree *tree = bio->bi_private; ++ u64 start; ++ ++ start = page_offset(page) + bvec->bv_offset; ++ ++ bio->bi_private = NULL; ++ bio_get(bio); ++ ++ if (tree->ops) ++ ret = tree->ops->submit_bio_hook(page->mapping->host, bio, ++ mirror_num, bio_flags, start); ++ else ++ btrfsic_submit_bio(bio); ++ ++ bio_put(bio); ++ return blk_status_to_errno(ret); ++} ++ ++static void flush_write_bio(struct extent_page_data *epd) ++{ ++ if (epd->bio) { ++ int ret; ++ ++ ret = submit_one_bio(epd->bio, 0, 0); ++ BUG_ON(ret < 0); /* -ENOMEM */ ++ epd->bio = NULL; ++ } ++} + + static inline struct btrfs_fs_info * + tree_fs_info(struct extent_io_tree *tree) +@@ -2762,30 +2795,6 @@ struct bio *btrfs_bio_clone_partial(stru + return bio; + } + +-static int __must_check submit_one_bio(struct bio *bio, int mirror_num, +- unsigned long bio_flags) +-{ +- blk_status_t ret = 0; +- struct bio_vec *bvec = bio_last_bvec_all(bio); +- struct page *page = bvec->bv_page; +- struct extent_io_tree *tree = bio->bi_private; +- u64 start; +- +- start = page_offset(page) + bvec->bv_offset; +- +- bio->bi_private = NULL; +- bio_get(bio); +- +- if (tree->ops) +- ret = tree->ops->submit_bio_hook(page->mapping->host, bio, +- mirror_num, bio_flags, start); +- else +- btrfsic_submit_bio(bio); +- +- bio_put(bio); +- return blk_status_to_errno(ret); +-} +- + static int merge_bio(struct extent_io_tree *tree, struct page *page, + unsigned long offset, size_t size, struct bio *bio, + unsigned long bio_flags) +@@ -4089,17 +4098,6 @@ retry: + return ret; + } + +-static void flush_write_bio(struct extent_page_data *epd) +-{ +- if (epd->bio) { +- int ret; +- +- ret = submit_one_bio(epd->bio, 0, 0); +- BUG_ON(ret < 0); /* -ENOMEM */ +- epd->bio = NULL; +- } +-} +- + int extent_write_full_page(struct page *page, struct writeback_control *wbc) + { + int ret; diff --git a/patches.suse/btrfs-factor-our-read-write-stage-off-csum_tree_bloc.patch b/patches.suse/btrfs-factor-our-read-write-stage-off-csum_tree_bloc.patch new file mode 100644 index 0000000..82a22cc --- /dev/null +++ b/patches.suse/btrfs-factor-our-read-write-stage-off-csum_tree_bloc.patch @@ -0,0 +1,135 @@ +From 2996e1f8bcadf0436cc67b63af01523f6cf5d43f Mon Sep 17 00:00:00 2001 +From: Johannes Thumshirn +Date: Mon, 25 Feb 2019 14:24:15 +0100 +Patch-mainline: v5.1 +Git-commit: 2996e1f8bcadf0436cc67b63af01523f6cf5d43f +References: bsc#1168273 +Subject: [PATCH] btrfs: factor our read/write stage off csum_tree_block into + its callers + +Currently csum_tree_block() does two things, first it as it's name +suggests it calculates the checksum for a tree-block. But it also writes +this checksum to disk or reads an extent_buffer from disk and compares the +checksum with the calculated checksum, depending on the verify argument. + +Furthermore one of the two callers passes in '1' for the verify argument, +the other one passes in '0'. + +For clarity and less layering violations, factor out the second stage in +csum_tree_block()'s callers. + +Suggested-by: Nikolay Borisov +Reviewed-by: Qu Wenruo +Reviewed-by: Nikolay Borisov +Signed-off-by: Johannes Thumshirn +Reviewed-by: David Sterba +Signed-off-by: David Sterba +--- + fs/btrfs/disk-io.c | 55 +++++++++++++++++++++++++++-------------------------- + 1 file changed, 29 insertions(+), 26 deletions(-) + +--- a/fs/btrfs/disk-io.c ++++ b/fs/btrfs/disk-io.c +@@ -277,15 +277,12 @@ void btrfs_csum_final(u32 crc, u8 *resul + } + + /* +- * compute the csum for a btree block, and either verify it or write it +- * into the csum field of the block. ++ * Compute the csum of a btree block and store the result to provided buffer. ++ * ++ * Returns error if the extent buffer cannot be mapped. + */ +-static int csum_tree_block(struct btrfs_fs_info *fs_info, +- struct extent_buffer *buf, +- int verify) ++static int csum_tree_block(struct extent_buffer *buf, u8 *result) + { +- u16 csum_size = btrfs_super_csum_size(fs_info->super_copy); +- char result[BTRFS_CSUM_SIZE]; + unsigned long len; + unsigned long cur_len; + unsigned long offset = BTRFS_CSUM_SIZE; +@@ -311,23 +308,6 @@ static int csum_tree_block(struct btrfs_ + + btrfs_csum_final(crc, result); + +- if (verify) { +- if (memcmp_extent_buffer(buf, result, 0, csum_size)) { +- u32 val; +- u32 found = 0; +- memcpy(&found, result, csum_size); +- +- read_extent_buffer(buf, &val, 0, csum_size); +- btrfs_warn_rl(fs_info, +- "%s checksum verify failed on %llu wanted %X found %X level %d", +- fs_info->sb->s_id, buf->start, +- val, found, btrfs_header_level(buf)); +- return -EUCLEAN; +- } +- } else { +- write_extent_buffer(buf, result, 0, csum_size); +- } +- + return 0; + } + +@@ -544,6 +524,8 @@ static int csum_dirty_buffer(struct btrf + { + u64 start = page_offset(page); + u64 found_start; ++ u8 result[BTRFS_CSUM_SIZE]; ++ u16 csum_size = btrfs_super_csum_size(fs_info->super_copy); + struct extent_buffer *eb; + + eb = (struct extent_buffer *)page->private; +@@ -563,7 +545,11 @@ static int csum_dirty_buffer(struct btrf + ASSERT(memcmp_extent_buffer(eb, fs_info->fsid, + btrfs_header_fsid(), BTRFS_FSID_SIZE) == 0); + +- return csum_tree_block(fs_info, eb, 0); ++ if (csum_tree_block(eb, result)) ++ return -EINVAL; ++ ++ write_extent_buffer(eb, result, 0, csum_size); ++ return 0; + } + + static int check_tree_block_fsid(struct btrfs_fs_info *fs_info, +@@ -593,7 +579,9 @@ static int btree_readpage_end_io_hook(st + struct extent_buffer *eb; + struct btrfs_root *root = BTRFS_I(page->mapping->host)->root; + struct btrfs_fs_info *fs_info = root->fs_info; ++ u16 csum_size = btrfs_super_csum_size(fs_info->super_copy); + int ret = 0; ++ u8 result[BTRFS_CSUM_SIZE]; + int reads_done; + + if (!page->private) +@@ -640,10 +628,25 @@ static int btree_readpage_end_io_hook(st + btrfs_set_buffer_lockdep_class(btrfs_header_owner(eb), + eb, found_level); + +- ret = csum_tree_block(fs_info, eb, 1); ++ ret = csum_tree_block(eb, result); + if (ret) + goto err; + ++ if (memcmp_extent_buffer(eb, result, 0, csum_size)) { ++ u32 val; ++ u32 found = 0; ++ ++ memcpy(&found, result, csum_size); ++ ++ read_extent_buffer(eb, &val, 0, csum_size); ++ btrfs_warn_rl(fs_info, ++ "%s checksum verify failed on %llu wanted %x found %x level %d", ++ fs_info->sb->s_id, eb->start, ++ val, found, btrfs_header_level(eb)); ++ ret = -EUCLEAN; ++ goto err; ++ } ++ + /* + * If this is a leaf block and it is corrupt, set the corrupt bit so + * that we don't try and read the other copies of this block, just diff --git a/patches.suse/btrfs-fix-missing-delayed-iputs-on-unmount.patch b/patches.suse/btrfs-fix-missing-delayed-iputs-on-unmount.patch new file mode 100644 index 0000000..e5afa16 --- /dev/null +++ b/patches.suse/btrfs-fix-missing-delayed-iputs-on-unmount.patch @@ -0,0 +1,151 @@ +From: Omar Sandoval +Date: Wed, 31 Oct 2018 10:06:08 -0700 +Subject: Btrfs: fix missing delayed iputs on unmount +Git-commit: d6fd0ae25c6495674dc5a41a8d16bc8e0073276d +Patch-mainline: v4.20-rc2 +References: bsc#1165949 + +There's a race between close_ctree() and cleaner_kthread(). +close_ctree() sets btrfs_fs_closing(), and the cleaner stops when it +sees it set, but this is racy; the cleaner might have already checked +the bit and could be cleaning stuff. In particular, if it deletes unused +block groups, it will create delayed iputs for the free space cache +inodes. As of "btrfs: don't run delayed_iputs in commit", we're no +longer running delayed iputs after a commit. Therefore, if the cleaner +creates more delayed iputs after delayed iputs are run in +btrfs_commit_super(), we will leak inodes on unmount and get a busy +inode crash from the VFS. + +Fix it by parking the cleaner before we actually close anything. Then, +any remaining delayed iputs will always be handled in +btrfs_commit_super(). This also ensures that the commit in close_ctree() +is really the last commit, so we can get rid of the commit in +cleaner_kthread(). + +The fstest/generic/475 followed by 476 can trigger a crash that +manifests as a slab corruption caused by accessing the freed kthread +structure by a wake up function. Sample trace: + +[ 5657.077612] BUG: unable to handle kernel NULL pointer dereference at 00000000000000cc +[ 5657.079432] PGD 1c57a067 P4D 1c57a067 PUD da10067 PMD 0 +[ 5657.080661] Oops: 0000 [#1] PREEMPT SMP +[ 5657.081592] CPU: 1 PID: 5157 Comm: fsstress Tainted: G W 4.19.0-rc8-default+ #323 +[ 5657.083703] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.11.2-0-gf9626cc-prebuilt.qemu-project.org 04/01/2014 +[ 5657.086577] RIP: 0010:shrink_page_list+0x2f9/0xe90 +[ 5657.091937] RSP: 0018:ffffb5c745c8f728 EFLAGS: 00010287 +[ 5657.092953] RAX: 0000000000000074 RBX: ffffb5c745c8f830 RCX: 0000000000000000 +[ 5657.094590] RDX: 0000000000000000 RSI: 0000000000000001 RDI: ffff9a8747fdf3d0 +[ 5657.095987] RBP: ffffb5c745c8f9e0 R08: 0000000000000000 R09: 0000000000000000 +[ 5657.097159] R10: ffff9a8747fdf5e8 R11: 0000000000000000 R12: ffffb5c745c8f788 +[ 5657.098513] R13: ffff9a877f6ff2c0 R14: ffff9a877f6ff2c8 R15: dead000000000200 +[ 5657.099689] FS: 00007f948d853b80(0000) GS:ffff9a877d600000(0000) knlGS:0000000000000000 +[ 5657.101032] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 +[ 5657.101953] CR2: 00000000000000cc CR3: 00000000684bd000 CR4: 00000000000006e0 +[ 5657.103159] Call Trace: +[ 5657.103776] shrink_inactive_list+0x194/0x410 +[ 5657.104671] shrink_node_memcg.constprop.84+0x39a/0x6a0 +[ 5657.105750] shrink_node+0x62/0x1c0 +[ 5657.106529] try_to_free_pages+0x1a4/0x500 +[ 5657.107408] __alloc_pages_slowpath+0x2c9/0xb20 +[ 5657.108418] __alloc_pages_nodemask+0x268/0x2b0 +[ 5657.109348] kmalloc_large_node+0x37/0x90 +[ 5657.110205] __kmalloc_node+0x236/0x310 +[ 5657.111014] kvmalloc_node+0x3e/0x70 + +Fixes: 30928e9baac2 ("btrfs: don't run delayed_iputs in commit") +Signed-off-by: Omar Sandoval +Reviewed-by: David Sterba +[ add trace ] +Signed-off-by: David Sterba +Acked-by: Nikolay Borisov +--- + fs/btrfs/disk-io.c | 51 +++++++++++++++------------------------------------ + 1 file changed, 15 insertions(+), 36 deletions(-) + +--- a/fs/btrfs/disk-io.c ++++ b/fs/btrfs/disk-io.c +@@ -1759,9 +1759,8 @@ static int cleaner_kthread(void *arg) + struct btrfs_root *root = arg; + struct btrfs_fs_info *fs_info = root->fs_info; + int again; +- struct btrfs_trans_handle *trans; + +- do { ++ while (1) { + again = 0; + + /* Make the cleaner go to sleep early. */ +@@ -1810,42 +1809,16 @@ static int cleaner_kthread(void *arg) + */ + btrfs_delete_unused_bgs(fs_info); + sleep: ++ if (kthread_should_park()) ++ kthread_parkme(); ++ if (kthread_should_stop()) ++ return 0; + if (!again) { + set_current_state(TASK_INTERRUPTIBLE); +- if (!kthread_should_stop()) +- schedule(); ++ schedule(); + __set_current_state(TASK_RUNNING); + } +- } while (!kthread_should_stop()); +- +- /* +- * Transaction kthread is stopped before us and wakes us up. +- * However we might have started a new transaction and COWed some +- * tree blocks when deleting unused block groups for example. So +- * make sure we commit the transaction we started to have a clean +- * shutdown when evicting the btree inode - if it has dirty pages +- * when we do the final iput() on it, eviction will trigger a +- * writeback for it which will fail with null pointer dereferences +- * since work queues and other resources were already released and +- * destroyed by the time the iput/eviction/writeback is made. +- */ +- trans = btrfs_attach_transaction(root); +- if (IS_ERR(trans)) { +- if (PTR_ERR(trans) != -ENOENT) +- btrfs_err(fs_info, +- "cleaner transaction attach returned %ld", +- PTR_ERR(trans)); +- } else { +- int ret; +- +- ret = btrfs_commit_transaction(trans); +- if (ret) +- btrfs_err(fs_info, +- "cleaner open transaction commit returned %d", +- ret); + } +- +- return 0; + } + + static int transaction_kthread(void *arg) +@@ -3841,6 +3814,13 @@ void close_ctree(struct btrfs_fs_info *f + int ret; + + set_bit(BTRFS_FS_CLOSING_START, &fs_info->flags); ++ /* ++ * We don't want the cleaner to start new transactions, add more delayed ++ * iputs, etc. while we're closing. We can't use kthread_stop() yet ++ * because that frees the task_struct, and the transaction kthread might ++ * still try to wake up the cleaner. ++ */ ++ kthread_park(fs_info->cleaner_kthread); + + /* wait for the qgroup rescan worker to stop */ + btrfs_qgroup_wait_for_completion(fs_info, false); +@@ -3868,9 +3848,8 @@ void close_ctree(struct btrfs_fs_info *f + + if (!(fs_info->sb->s_flags & MS_RDONLY)) { + /* +- * If the cleaner thread is stopped and there are +- * block groups queued for removal, the deletion will be +- * skipped when we quit the cleaner thread. ++ * The cleaner kthread is stopped, so do one final pass over ++ * unused block groups. + */ + btrfs_delete_unused_bgs(fs_info); + diff --git a/patches.suse/btrfs-fix-qgroup-double-free-after-failure-to-reserve-metadata-for-delalloc.patch b/patches.suse/btrfs-fix-qgroup-double-free-after-failure-to-reserve-metadata-for-delalloc.patch new file mode 100644 index 0000000..f503f40 --- /dev/null +++ b/patches.suse/btrfs-fix-qgroup-double-free-after-failure-to-reserve-metadata-for-delalloc.patch @@ -0,0 +1,45 @@ +From: Filipe Manana +Date: Tue, 15 Oct 2019 10:54:39 +0100 +Subject: Btrfs: fix qgroup double free after failure to reserve metadata for + delalloc +Git-commit: c7967fc1499beb9b70bb9d33525fb0b384af8883 +Patch-mainline: v5.4-rc5 +References: bsc#1165949 + +If we fail to reserve metadata for delalloc operations we end up releasing +the previously reserved qgroup amount twice, once explicitly under the +'out_qgroup' label by calling btrfs_qgroup_free_meta_prealloc() and once +again, under label 'out_fail', by calling btrfs_inode_rsv_release() with a +value of 'true' for its 'qgroup_free' argument, which results in +btrfs_qgroup_free_meta_prealloc() being called again, so we end up having +a double free. + +Also if we fail to reserve the necessary qgroup amount, we jump to the +label 'out_fail', which calls btrfs_inode_rsv_release() and that in turns +calls btrfs_qgroup_free_meta_prealloc(), even though we weren't able to +reserve any qgroup amount. So we freed some amount we never reserved. + +So fix this by removing the call to btrfs_inode_rsv_release() in the +failure path, since it's not necessary at all as we haven't changed the +inode's block reserve in any way at this point. + +Fixes: c8eaeac7b73434 ("btrfs: reserve delalloc metadata differently") +CC: stable@vger.kernel.org # 5.2+ +Signed-off-by: Filipe Manana +Reviewed-by: David Sterba +Signed-off-by: David Sterba +Acked-by: Nikolay Borisov +--- + fs/btrfs/delalloc-space.c | 1 - + 1 file changed, 1 deletion(-) + +--- a/fs/btrfs/delalloc-space.c ++++ b/fs/btrfs/delalloc-space.c +@@ -370,7 +370,6 @@ int btrfs_delalloc_reserve_metadata(stru + out_qgroup: + btrfs_qgroup_free_meta_prealloc(root, qgroup_reserve); + out_fail: +- btrfs_inode_rsv_release(inode, true); + if (delalloc_lock) + mutex_unlock(&inode->delalloc_mutex); + return ret; diff --git a/patches.suse/btrfs-fix-race-between-block-group-removal-and-block.patch b/patches.suse/btrfs-fix-race-between-block-group-removal-and-block.patch index 3733c1d..2bb5c9e 100644 --- a/patches.suse/btrfs-fix-race-between-block-group-removal-and-block.patch +++ b/patches.suse/btrfs-fix-race-between-block-group-removal-and-block.patch @@ -119,14 +119,12 @@ CC: stable@vger.kernel.org # 4.4+ Signed-off-by: Filipe Manana Signed-off-by: David Sterba --- - fs/btrfs/extent-tree.c | 37 ++++++++++++++++++++----------------- + fs/btrfs/extent-tree.c | 37 ++++++++++++++++++++----------------- 1 file changed, 20 insertions(+), 17 deletions(-) -diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c -index d8a7c023aa21..2e13466b549e 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c -@@ -10677,23 +10677,6 @@ int btrfs_remove_block_group(struct btrfs_trans_handle *trans, +@@ -10930,23 +10930,6 @@ int btrfs_remove_block_group(struct btrf list_move_tail(&em->list, &fs_info->pinned_chunks); } spin_unlock(&block_group->lock); @@ -150,7 +148,7 @@ index d8a7c023aa21..2e13466b549e 100644 mutex_unlock(&fs_info->chunk_mutex); ret = remove_block_group_free_space(trans, fs_info, block_group); -@@ -10710,6 +10693,26 @@ int btrfs_remove_block_group(struct btrfs_trans_handle *trans, +@@ -10963,6 +10946,26 @@ int btrfs_remove_block_group(struct btrf goto out; ret = btrfs_del_item(trans, root, path); @@ -175,8 +173,5 @@ index d8a7c023aa21..2e13466b549e 100644 + free_extent_map(em); + } out: - btrfs_free_path(path); - return ret; --- -2.16.4 - + if (remove_rsv) + btrfs_delayed_refs_rsv_release(fs_info, 1); diff --git a/patches.suse/btrfs-fix-race-leading-to-metadata-space-leak-after-task-received-signal.patch b/patches.suse/btrfs-fix-race-leading-to-metadata-space-leak-after-task-received-signal.patch new file mode 100644 index 0000000..74cc32d --- /dev/null +++ b/patches.suse/btrfs-fix-race-leading-to-metadata-space-leak-after-task-received-signal.patch @@ -0,0 +1,177 @@ +From: Filipe Manana +Date: Fri, 25 Oct 2019 10:53:41 +0100 +Subject: Btrfs: fix race leading to metadata space leak after task received + signal +Git-commit: 0cab7acc4afc0a4b20fd01a9a28971774501db80 +Patch-mainline: v5.4-rc7 +References: bsc#1165949 + +When a task that is allocating metadata needs to wait for the async +reclaim job to process its ticket and gets a signal (because it was killed +for example) before doing the wait, the task ends up erroring out but +with space reserved for its ticket, which never gets released, resulting +in a metadata space leak (more specifically a leak in the bytes_may_use +counter of the metadata space_info object). + +Here's the sequence of steps leading to the space leak: + +1) A task tries to create a file for example, so it ends up trying to + start a transaction at btrfs_create(); + +2) The filesystem is currently in a state where there is not enough + metadata free space to satisfy the transaction's needs. So at + space-info.c:__reserve_metadata_bytes() we create a ticket and + add it to the list of tickets of the space info object. Also, + because the metadata async reclaim job is not running, we queue + a job ro run metadata reclaim; + +3) In the meanwhile the task receives a signal (like SIGTERM from + a kill command for example); + +4) After queing the async reclaim job, at __reserve_metadata_bytes(), + we unlock the metadata space info and call handle_reserve_ticket(); + +5) That last function calls wait_reserve_ticket(), which acquires the + lock from the metadata space info. Then in the first iteration of + its while loop, it calls prepare_to_wait_event(), which returns + -ERESTARTSYS because the task has a pending signal. As a result, + we set the error field of the ticket to -EINTR and exit the while + loop without deleting the ticket from the list of tickets (in the + space info object). After exiting the loop we unlock the space info; + +6) The async reclaim job is able to release enough metadata, acquires + the metadata space info's lock and then reserves space for the ticket, + since the ticket is still in the list of (non-priority) tickets. The + space reservation happens at btrfs_try_granting_tickets(), called from + maybe_fail_all_tickets(). This increments the bytes_may_use counter + from the metadata space info object, sets the ticket's bytes field to + zero (meaning success, that space was reserved) and removes it from + the list of tickets; + +7) wait_reserve_ticket() returns, with the error field of the ticket + set to -EINTR. Then handle_reserve_ticket() just propagates that error + to the caller. Because an error was returned, the caller does not + release the reserved space, since the expectation is that any error + means no space was reserved. + +Fix this by removing the ticket from the list, while holding the space +info lock, at wait_reserve_ticket() when prepare_to_wait_event() returns +an error. + +Also add some comments and an assertion to guarantee we never end up with +a ticket that has an error set and a bytes counter field set to zero, to +more easily detect regressions in the future. + +This issue could be triggered sporadically by some test cases from fstests +such as generic/269 for example, which tries to fill a filesystem and then +kills fsstress processes running in the background. + +When this issue happens, we get a warning in syslog/dmesg when unmounting +the filesystem, like the following: + + ------------[ cut here ]------------ + WARNING: CPU: 0 PID: 13240 at fs/btrfs/block-group.c:3186 btrfs_free_block_groups+0x314/0x470 [btrfs] + (...) + CPU: 0 PID: 13240 Comm: umount Tainted: G W L 5.3.0-rc8-btrfs-next-48+ #1 + Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.12.0-0-ga698c8995f-prebuilt.qemu.org 04/01/2014 + RIP: 0010:btrfs_free_block_groups+0x314/0x470 [btrfs] + (...) + RSP: 0018:ffff9910c14cfdb8 EFLAGS: 00010286 + RAX: 0000000000000024 RBX: ffff89cd8a4d55f0 RCX: 0000000000000000 + RDX: 0000000000000000 RSI: ffff89cdf6a178a8 RDI: ffff89cdf6a178a8 + RBP: ffff9910c14cfde8 R08: 0000000000000000 R09: 0000000000000001 + R10: ffff89cd4d618040 R11: 0000000000000000 R12: ffff89cd8a4d5508 + R13: ffff89cde7c4a600 R14: dead000000000122 R15: dead000000000100 + FS: 00007f42754432c0(0000) GS:ffff89cdf6a00000(0000) knlGS:0000000000000000 + CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 + CR2: 00007fd25a47f730 CR3: 000000021f8d6006 CR4: 00000000003606f0 + DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 + DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 + Call Trace: + close_ctree+0x1ad/0x390 [btrfs] + generic_shutdown_super+0x6c/0x110 + kill_anon_super+0xe/0x30 + btrfs_kill_super+0x12/0xa0 [btrfs] + deactivate_locked_super+0x3a/0x70 + cleanup_mnt+0xb4/0x160 + task_work_run+0x7e/0xc0 + exit_to_usermode_loop+0xfa/0x100 + do_syscall_64+0x1cb/0x220 + entry_SYSCALL_64_after_hwframe+0x49/0xbe + RIP: 0033:0x7f4274d2cb37 + (...) + RSP: 002b:00007ffcff701d38 EFLAGS: 00000246 ORIG_RAX: 00000000000000a6 + RAX: 0000000000000000 RBX: 0000557ebde2f060 RCX: 00007f4274d2cb37 + RDX: 0000000000000001 RSI: 0000000000000000 RDI: 0000557ebde2f240 + RBP: 0000557ebde2f240 R08: 0000557ebde2f270 R09: 0000000000000015 + R10: 00000000000006b4 R11: 0000000000000246 R12: 00007f427522ee64 + R13: 0000000000000000 R14: 0000000000000000 R15: 00007ffcff701fc0 + irq event stamp: 0 + hardirqs last enabled at (0): [<0000000000000000>] 0x0 + hardirqs last disabled at (0): [] copy_process+0x75e/0x1fd0 + softirqs last enabled at (0): [] copy_process+0x75e/0x1fd0 + softirqs last disabled at (0): [<0000000000000000>] 0x0 + ---[ end trace bcf4b235461b26f6 ]--- + BTRFS info (device sdb): space_info 4 has 19116032 free, is full + BTRFS info (device sdb): space_info total=33554432, used=14176256, pinned=0, reserved=0, may_use=196608, readonly=65536 + BTRFS info (device sdb): global_block_rsv: size 0 reserved 0 + BTRFS info (device sdb): trans_block_rsv: size 0 reserved 0 + BTRFS info (device sdb): chunk_block_rsv: size 0 reserved 0 + BTRFS info (device sdb): delayed_block_rsv: size 0 reserved 0 + BTRFS info (device sdb): delayed_refs_rsv: size 0 reserved 0 + +Fixes: 374bf9c5cd7d0b ("btrfs: unify error handling for ticket flushing") +Reviewed-by: Josef Bacik +Signed-off-by: Filipe Manana +Signed-off-by: David Sterba +Acked-by: Nikolay Borisov +--- + fs/btrfs/space-info.c | 21 +++++++++++++++++++++ + 1 file changed, 21 insertions(+) + +diff --git a/fs/btrfs/space-info.c b/fs/btrfs/space-info.c +index 98dc092a905e..e8a4b0ebe97f 100644 +--- a/fs/btrfs/space-info.c ++++ b/fs/btrfs/space-info.c +@@ -893,6 +893,15 @@ static void wait_reserve_ticket(struct btrfs_fs_info *fs_info, + while (ticket->bytes > 0 && ticket->error == 0) { + ret = prepare_to_wait_event(&ticket->wait, &wait, TASK_KILLABLE); + if (ret) { ++ /* ++ * Delete us from the list. After we unlock the space ++ * info, we don't want the async reclaim job to reserve ++ * space for this ticket. If that would happen, then the ++ * ticket's task would not known that space was reserved ++ * despite getting an error, resulting in a space leak ++ * (bytes_may_use counter of our space_info). ++ */ ++ list_del_init(&ticket->list); + ticket->error = -EINTR; + break; + } +@@ -945,12 +954,24 @@ static int handle_reserve_ticket(struct btrfs_fs_info *fs_info, + spin_lock(&space_info->lock); + ret = ticket->error; + if (ticket->bytes || ticket->error) { ++ /* ++ * Need to delete here for priority tickets. For regular tickets ++ * either the async reclaim job deletes the ticket from the list ++ * or we delete it ourselves at wait_reserve_ticket(). ++ */ + list_del_init(&ticket->list); + if (!ret) + ret = -ENOSPC; + } + spin_unlock(&space_info->lock); + ASSERT(list_empty(&ticket->list)); ++ /* ++ * Check that we can't have an error set if the reservation succeeded, ++ * as that would confuse tasks and lead them to error out without ++ * releasing reserved space (if an error happens the expectation is that ++ * space wasn't reserved at all). ++ */ ++ ASSERT(!(ticket->bytes == 0 && ticket->error)); + return ret; + } + + diff --git a/patches.suse/btrfs-force-chunk-allocation-if-our-global-rsv-is-larger-than-metadata.patch b/patches.suse/btrfs-force-chunk-allocation-if-our-global-rsv-is-larger-than-metadata.patch new file mode 100644 index 0000000..2d31c82 --- /dev/null +++ b/patches.suse/btrfs-force-chunk-allocation-if-our-global-rsv-is-larger-than-metadata.patch @@ -0,0 +1,112 @@ +From: Josef Bacik +Date: Fri, 13 Mar 2020 15:28:48 -0400 +Subject: btrfs: force chunk allocation if our global rsv is larger than + metadata +Patch-mainline: Submitted, https://lore.kernel.org/linux-btrfs/20200313192848.140759-1-josef@toxicpanda.com/ +References: bsc#1165949 + +Nikolay noticed a bunch of test failures with my global rsv steal +patches. At first he thought they were introduced by them, but they've +been failing for a while with 64k nodes. + +The problem is with 64k nodes we have a global reserve that calculates +out to 13mib on a freshly made file system, which only has 8mib of +metadata space. Because of changes I previously made we no longer +account for the global reserve in the overcommit logic, which means we +correctly allow overcommit to happen even though we are already +overcommitted. + +However in some corner cases, for example btrfs/170, we will allocate +the entire file system up with data chunks before we have enough space +pressure to allocate a metadata chunk. Then once the fs is full we +ENOSPC out because we cannot overcommit and the global reserve is taking +up all of the available space. + +The most ideal way to deal with this is to change our space reservation +stuff to take into account the height of the tree's that we're +modifying, so that our global reserve calculation does not end up so +obscenely large. + +However that is a huuuuuuge undertaking. Instead fix this by forcing a +chunk allocation if the global reserve is larger than the total metadata +space. This gives us essentially the same behavior that happened +before, we get a chunk allocated and these tests can pass. + +This is meant to be a stop-gap measure until we can tackle the "tree +height only" project. + +Fixes: 0096420adb03 ("btrfs: do not account global reserve in can_overcommit") +Signed-off-by: Josef Bacik +Acked-by: Nikolay Borisov +--- + fs/btrfs/block-rsv.c | 3 +++ + fs/btrfs/transaction.c | 18 ++++++++++++++++++ + 2 files changed, 21 insertions(+) + +--- a/fs/btrfs/block-rsv.c ++++ b/fs/btrfs/block-rsv.c +@@ -5,6 +5,7 @@ + #include "space-info.h" + #include "math.h" + #include "transaction.h" ++#include "block-group.h" + + static u64 block_rsv_release_bytes(struct btrfs_fs_info *fs_info, + struct btrfs_block_rsv *block_rsv, +@@ -313,6 +314,8 @@ void btrfs_update_global_block_rsv(struc + else + block_rsv->full = 0; + ++ if (block_rsv->size >= sinfo->total_bytes) ++ sinfo->force_alloc = CHUNK_ALLOC_FORCE; + spin_unlock(&block_rsv->lock); + spin_unlock(&sinfo->lock); + } +--- a/fs/btrfs/transaction.c ++++ b/fs/btrfs/transaction.c +@@ -33,6 +33,7 @@ + #include "dev-replace.h" + #include "qgroup.h" + #include "block-group.h" ++#include "space-info.h" + + #define BTRFS_ROOT_TRANS_TAG 0 + +@@ -504,6 +505,7 @@ start_transaction(struct btrfs_root *roo + u64 num_bytes = 0; + u64 qgroup_reserved = 0; + bool reloc_reserved = false; ++ bool do_chunk_alloc = false; + int ret; + + /* Send isn't supposed to start transactions. */ +@@ -566,6 +568,9 @@ start_transaction(struct btrfs_root *roo + delayed_refs_bytes); + num_bytes -= delayed_refs_bytes; + } ++ ++ if (rsv->space_info->force_alloc) ++ do_chunk_alloc = true; + } else if (num_items == 0 && flush == BTRFS_RESERVE_FLUSH_ALL && + !delayed_refs_rsv->full) { + /* +@@ -647,6 +652,19 @@ got_it: + + if (!current->journal_info && type != TRANS_USERSPACE) + current->journal_info = h; ++ ++ /* ++ * If the space_info is marked ALLOC_FORCE then we'll get upgraded to ++ * ALLOC_FORCE the first run through, and then we won't allocate for ++ * anybody else who races in later. We don't care about the return ++ * value here. ++ */ ++ if (do_chunk_alloc && num_bytes) { ++ u64 flags = h->block_rsv->space_info->flags; ++ btrfs_chunk_alloc(h, btrfs_get_alloc_profile(fs_info, flags), ++ CHUNK_ALLOC_NO_FORCE); ++ } ++ + return h; + + join_fail: diff --git a/patches.suse/btrfs-improve-global-reserve-stealing-logic.patch b/patches.suse/btrfs-improve-global-reserve-stealing-logic.patch new file mode 100644 index 0000000..821a93e --- /dev/null +++ b/patches.suse/btrfs-improve-global-reserve-stealing-logic.patch @@ -0,0 +1,218 @@ +From: Josef Bacik +Date: Fri, 13 Mar 2020 15:58:05 -0400 +Subject: btrfs: Improve global reserve stealing logic +Patch-mainline: Submitted, https://lore.kernel.org/linux-btrfs/20200313195809.141753-1-josef@toxicpanda.com/ +References: bsc#1165949 + +For unlink transactions and block group removal +btrfs_start_transaction_fallback_global_rsv will first try to start +an ordinary transaction and if it fails it will fall back to reserving +the required amount by stealing from the global reserve. This is +problematic because of all the same reasons we had with previous +iterations of the ENOSPC handling, thundering herd. We get a bunch of +failures all at once, everybody tries to allocate from the global +reserve, some win and some lose, we get an ENSOPC. + +Fix this behavior by introducing BTRFS_RESERVE_FLUSH_ALL_STEAL. It's +used to mark unlink reservation. To fix this we need to integrate this +logic into the normal ENOSPC infrastructure. We still go through all of +the normal flushing work, and at the moment we begin to fail all the +tickets we try to satisfy any tickets that are allowed to steal by +stealing from the global reserve. If this works we start the flushing +system over again just like we would with a normal ticket satisfaction. +This serializes our global reserve stealing, so we don't have the +thundering herd problem. + +Signed-off-by: Josef Bacik +Reviewed-by: Nikolay Borisov +Acked-by: Nikolay Borisov +--- + fs/btrfs/block-group.c | 2 +- + fs/btrfs/ctree.h | 1 + + fs/btrfs/inode.c | 2 +- + fs/btrfs/space-info.c | 36 +++++++++++++++++++++++++++++++++++- + fs/btrfs/space-info.h | 1 + + fs/btrfs/transaction.c | 43 ++++++------------------------------------- + fs/btrfs/transaction.h | 3 +-- + 7 files changed, 46 insertions(+), 42 deletions(-) + +--- a/fs/btrfs/block-group.c ++++ b/fs/btrfs/block-group.c +@@ -1152,7 +1152,7 @@ struct btrfs_trans_handle *btrfs_start_t + free_extent_map(em); + + return btrfs_start_transaction_fallback_global_rsv(fs_info->extent_root, +- num_items, 1); ++ num_items); + } + + /* +--- a/fs/btrfs/ctree.h ++++ b/fs/btrfs/ctree.h +@@ -2575,6 +2575,7 @@ enum btrfs_reserve_flush_enum { + BTRFS_RESERVE_FLUSH_LIMIT, + BTRFS_RESERVE_FLUSH_EVICT, + BTRFS_RESERVE_FLUSH_ALL, ++ BTRFS_RESERVE_FLUSH_ALL_STEAL, + }; + + enum btrfs_flush_state { +--- a/fs/btrfs/inode.c ++++ b/fs/btrfs/inode.c +@@ -4085,7 +4085,7 @@ static struct btrfs_trans_handle *__unli + * 1 for the inode ref + * 1 for the inode + */ +- return btrfs_start_transaction_fallback_global_rsv(root, 5, 5); ++ return btrfs_start_transaction_fallback_global_rsv(root, 5); + } + + static int btrfs_unlink(struct inode *dir, struct dentry *dentry) +--- a/fs/btrfs/space-info.c ++++ b/fs/btrfs/space-info.c +@@ -696,6 +696,34 @@ static inline int need_do_async_reclaim( + !test_bit(BTRFS_FS_STATE_REMOUNTING, &fs_info->fs_state)); + } + ++static bool steal_from_global_rsv(struct btrfs_fs_info *fs_info, ++ struct btrfs_space_info *space_info, ++ struct reserve_ticket *ticket) ++{ ++ struct btrfs_block_rsv *global_rsv = &fs_info->global_block_rsv; ++ u64 min_bytes; ++ ++ if (global_rsv->space_info != space_info) ++ return false; ++ ++ spin_lock(&global_rsv->lock); ++ min_bytes = div_factor(global_rsv->size, 5); ++ if (global_rsv->reserved < min_bytes + ticket->bytes) { ++ spin_unlock(&global_rsv->lock); ++ return false; ++ } ++ global_rsv->reserved -= ticket->bytes; ++ ticket->bytes = 0; ++ list_del_init(&ticket->list); ++ wake_up(&ticket->wait); ++ space_info->tickets_id++; ++ if (global_rsv->reserved < global_rsv->size) ++ global_rsv->full = 0; ++ spin_unlock(&global_rsv->lock); ++ ++ return true; ++} ++ + /* + * maybe_fail_all_tickets - we've exhausted our flushing, start failing tickets + * @fs_info - fs_info for this fs +@@ -728,6 +756,9 @@ static bool maybe_fail_all_tickets(struc + ticket = list_first_entry(&space_info->tickets, + struct reserve_ticket, list); + ++ if (ticket->steal && ++ steal_from_global_rsv(fs_info, space_info, ticket)) ++ return true; + /* + * may_commit_transaction will avoid committing the transaction + * if it doesn't feel like the space reclaimed by the commit +@@ -951,6 +982,7 @@ static int handle_reserve_ticket(struct + + switch (flush) { + case BTRFS_RESERVE_FLUSH_ALL: ++ case BTRFS_RESERVE_FLUSH_ALL_STEAL: + wait_reserve_ticket(fs_info, space_info, ticket); + break; + case BTRFS_RESERVE_FLUSH_LIMIT: +@@ -1049,7 +1081,9 @@ static int __reserve_metadata_bytes(stru + ticket.bytes = orig_bytes; + ticket.error = 0; + init_waitqueue_head(&ticket.wait); +- if (flush == BTRFS_RESERVE_FLUSH_ALL) { ++ ticket.steal = (flush == BTRFS_RESERVE_FLUSH_ALL_STEAL); ++ if (flush == BTRFS_RESERVE_FLUSH_ALL || ++ flush == BTRFS_RESERVE_FLUSH_ALL_STEAL) { + list_add_tail(&ticket.list, &space_info->tickets); + if (!space_info->flush) { + space_info->flush = 1; +--- a/fs/btrfs/space-info.h ++++ b/fs/btrfs/space-info.h +@@ -72,6 +72,7 @@ struct btrfs_space_info { + struct reserve_ticket { + u64 bytes; + int error; ++ bool steal; + struct list_head list; + wait_queue_head_t wait; + }; +--- a/fs/btrfs/transaction.c ++++ b/fs/btrfs/transaction.c +@@ -544,7 +544,8 @@ start_transaction(struct btrfs_root *roo + * refill that amount for whatever is missing in the reserve. + */ + num_bytes = btrfs_calc_insert_metadata_size(fs_info, num_items); +- if (delayed_refs_rsv->full == 0) { ++ if (flush == BTRFS_RESERVE_FLUSH_ALL && ++ delayed_refs_rsv->full == 0) { + delayed_refs_bytes = num_bytes; + num_bytes <<= 1; + } +@@ -670,43 +671,11 @@ struct btrfs_trans_handle *btrfs_start_t + + struct btrfs_trans_handle *btrfs_start_transaction_fallback_global_rsv( + struct btrfs_root *root, +- unsigned int num_items, +- int min_factor) +-{ +- struct btrfs_fs_info *fs_info = root->fs_info; +- struct btrfs_trans_handle *trans; +- u64 num_bytes; +- int ret; ++ unsigned int num_items) + +- /* +- * We have two callers: unlink and block group removal. The +- * former should succeed even if we will temporarily exceed +- * quota and the latter operates on the extent root so +- * qgroup enforcement is ignored anyway. +- */ +- trans = start_transaction(root, num_items, TRANS_START, +- BTRFS_RESERVE_FLUSH_ALL, false); +- if (!IS_ERR(trans) || PTR_ERR(trans) != -ENOSPC) +- return trans; +- +- trans = btrfs_start_transaction(root, 0); +- if (IS_ERR(trans)) +- return trans; +- +- num_bytes = btrfs_calc_insert_metadata_size(fs_info, num_items); +- ret = btrfs_cond_migrate_bytes(fs_info, &fs_info->trans_block_rsv, +- num_bytes, min_factor); +- if (ret) { +- btrfs_end_transaction(trans); +- return ERR_PTR(ret); +- } +- +- trans->block_rsv = &fs_info->trans_block_rsv; +- trans->bytes_reserved = num_bytes; +- trace_btrfs_space_reservation(fs_info, "transaction", +- trans->transid, num_bytes, 1); +- +- return trans; ++{ ++ return start_transaction(root, num_items, TRANS_START, ++ BTRFS_RESERVE_FLUSH_ALL_STEAL, false); + } + + struct btrfs_trans_handle *btrfs_start_transaction_lflush( +--- a/fs/btrfs/transaction.h ++++ b/fs/btrfs/transaction.h +@@ -185,8 +185,7 @@ struct btrfs_trans_handle *btrfs_start_t + unsigned int num_items); + struct btrfs_trans_handle *btrfs_start_transaction_fallback_global_rsv( + struct btrfs_root *root, +- unsigned int num_items, +- int min_factor); ++ unsigned int num_items); + struct btrfs_trans_handle *btrfs_start_transaction_lflush( + struct btrfs_root *root, + unsigned int num_items); diff --git a/patches.suse/btrfs-improve-performance-on-fsync-of-files-with-mul.patch b/patches.suse/btrfs-improve-performance-on-fsync-of-files-with-mul.patch index 9f8bac3..18420fd 100644 --- a/patches.suse/btrfs-improve-performance-on-fsync-of-files-with-mul.patch +++ b/patches.suse/btrfs-improve-performance-on-fsync-of-files-with-mul.patch @@ -27,33 +27,29 @@ Tested-by: James Wang Signed-off-by: Filipe Manana Signed-off-by: David Sterba --- - fs/btrfs/btrfs_inode.h | 6 -- - fs/btrfs/inode.c | 17 --- - fs/btrfs/tree-log.c | 228 +++++++++++++++++++++++++++++++++-------- + fs/btrfs/btrfs_inode.h | 6 - + fs/btrfs/inode.c | 17 --- + fs/btrfs/tree-log.c | 228 ++++++++++++++++++++++++++++++++++++++++--------- 3 files changed, 188 insertions(+), 63 deletions(-) -diff --git a/fs/btrfs/btrfs_inode.h b/fs/btrfs/btrfs_inode.h -index 7f895b673c4f..19e4eecd67ce 100644 --- a/fs/btrfs/btrfs_inode.h +++ b/fs/btrfs/btrfs_inode.h -@@ -159,12 +159,6 @@ struct btrfs_inode { - */ +@@ -160,12 +160,6 @@ struct btrfs_inode { u64 last_unlink_trans; -- /* + /* - * Track the transaction id of the last transaction used to create a - * hard link for the inode. This is used by the log tree (fsync). - */ - u64 last_link_trans; - - /* +- /* * Number of bytes outstanding that are going to need csums. This is * used in ENOSPC accounting. -diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c -index 0038dab54f40..b3e279e68eaa 100644 + */ --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c -@@ -3668,21 +3668,6 @@ static int btrfs_read_locked_inode(struct inode *inode, +@@ -3707,21 +3707,6 @@ cache_index: * inode is not a directory, logging its parent unnecessarily. */ BTRFS_I(inode)->last_unlink_trans = BTRFS_I(inode)->last_trans; @@ -75,7 +71,7 @@ index 0038dab54f40..b3e279e68eaa 100644 path->slots[0]++; if (inode->i_nlink != 1 || -@@ -6494,7 +6479,6 @@ static int btrfs_link(struct dentry *old_dentry, struct inode *dir, +@@ -6500,7 +6485,6 @@ static int btrfs_link(struct dentry *old if (err) goto fail; } @@ -83,19 +79,17 @@ index 0038dab54f40..b3e279e68eaa 100644 d_instantiate(dentry, inode); ret = btrfs_log_new_name(trans, BTRFS_I(inode), NULL, parent, true, NULL); -@@ -9202,7 +9186,6 @@ struct inode *btrfs_alloc_inode(struct super_block *sb) +@@ -9211,7 +9195,6 @@ struct inode *btrfs_alloc_inode(struct s ei->index_cnt = (u64)-1; ei->dir_index = 0; ei->last_unlink_trans = 0; - ei->last_link_trans = 0; ei->last_log_commit = 0; - ei->delayed_iput_count = 0; -diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c -index 27c47acde982..5c0fd8b848ec 100644 + spin_lock_init(&ei->lock); --- a/fs/btrfs/tree-log.c +++ b/fs/btrfs/tree-log.c -@@ -6008,6 +6008,190 @@ static int btrfs_log_all_parents(struct btrfs_trans_handle *trans, +@@ -6007,6 +6007,190 @@ out: return ret; } @@ -286,7 +280,7 @@ index 27c47acde982..5c0fd8b848ec 100644 /* * helper function around btrfs_log_inode to make sure newly created * parent directories also end up in the log. A minimal inode and backref -@@ -6026,11 +6210,9 @@ static int btrfs_log_inode_parent(struct btrfs_trans_handle *trans, +@@ -6025,11 +6209,9 @@ static int btrfs_log_inode_parent(struct struct btrfs_fs_info *fs_info = root->fs_info; int inode_only = exists_only ? LOG_INODE_EXISTS : LOG_INODE_ALL; struct super_block *sb; @@ -298,7 +292,7 @@ index 27c47acde982..5c0fd8b848ec 100644 sb = inode->vfs_inode.i_sb; -@@ -6136,54 +6318,20 @@ static int btrfs_log_inode_parent(struct btrfs_trans_handle *trans, +@@ -6135,54 +6317,20 @@ static int btrfs_log_inode_parent(struct * and has a link count of 2. */ if (inode->last_unlink_trans > last_committed) { @@ -333,7 +327,7 @@ index 27c47acde982..5c0fd8b848ec 100644 - inode = BTRFS_I(d_inode(parent)); - if (root != inode->root) - break; - +- - if (inode->generation > last_committed) { - ret = btrfs_log_inode(trans, root, inode, - LOG_INODE_EXISTS, 0, LLONG_MAX, ctx); @@ -342,7 +336,7 @@ index 27c47acde982..5c0fd8b848ec 100644 - } - if (IS_ROOT(parent)) - break; -- + - parent = dget_parent(parent); - dput(old_parent); - old_parent = parent; @@ -357,6 +351,3 @@ index 27c47acde982..5c0fd8b848ec 100644 if (ret < 0) { btrfs_set_log_full_commit(fs_info, trans); ret = 1; --- -2.19.0 - diff --git a/patches.suse/btrfs-move-btrfs_raid_group-values-to-btrfs_raid_attr-table.patch b/patches.suse/btrfs-move-btrfs_raid_group-values-to-btrfs_raid_attr-table.patch new file mode 100644 index 0000000..392e416 --- /dev/null +++ b/patches.suse/btrfs-move-btrfs_raid_group-values-to-btrfs_raid_attr-table.patch @@ -0,0 +1,139 @@ +From: Anand Jain +Date: Wed, 25 Apr 2018 19:01:43 +0800 +Subject: btrfs: move btrfs_raid_group values to btrfs_raid_attr table +Git-commit: 41a6e8913cdff6b30ac53a24641259d117c0b101 +Patch-mainline: v4.18-rc1 +References: bsc#1165949 + +Add a new member struct btrfs_raid_attr::bg_flag so that +btrfs_raid_array can maintain the bit map flag of the raid type, and +so we can drop btrfs_raid_group. + +Signed-off-by: Anand Jain +Reviewed-by: Nikolay Borisov +Signed-off-by: David Sterba +Acked-by: Nikolay Borisov +--- + fs/btrfs/disk-io.c | 2 +- + fs/btrfs/extent-tree.c | 2 +- + fs/btrfs/volumes.c | 19 ++++++++----------- + fs/btrfs/volumes.h | 2 +- + 4 files changed, 11 insertions(+), 14 deletions(-) + +--- a/fs/btrfs/disk-io.c ++++ b/fs/btrfs/disk-io.c +@@ -3548,7 +3548,7 @@ int btrfs_get_num_tolerated_disk_barrier + for (raid_type = 0; raid_type < BTRFS_NR_RAID_TYPES; raid_type++) { + if (raid_type == BTRFS_RAID_SINGLE) + continue; +- if (!(flags & btrfs_raid_group[raid_type])) ++ if (!(flags & btrfs_raid_array[raid_type].bg_flag)) + continue; + min_tolerated = min(min_tolerated, + btrfs_raid_array[raid_type]. +--- a/fs/btrfs/extent-tree.c ++++ b/fs/btrfs/extent-tree.c +@@ -4193,7 +4193,7 @@ static u64 btrfs_reduce_alloc_profile(st + /* First, mask out the RAID levels which aren't possible */ + for (raid_type = 0; raid_type < BTRFS_NR_RAID_TYPES; raid_type++) { + if (num_devices >= btrfs_raid_array[raid_type].devs_min) +- allowed |= btrfs_raid_group[raid_type]; ++ allowed |= btrfs_raid_array[raid_type].bg_flag; + } + allowed &= flags; + +--- a/fs/btrfs/volumes.c ++++ b/fs/btrfs/volumes.c +@@ -51,6 +51,7 @@ const struct btrfs_raid_attr btrfs_raid_ + .tolerated_failures = 1, + .devs_increment = 2, + .ncopies = 2, ++ .bg_flag = BTRFS_BLOCK_GROUP_RAID10, + }, + [BTRFS_RAID_RAID1] = { + .sub_stripes = 1, +@@ -60,6 +61,7 @@ const struct btrfs_raid_attr btrfs_raid_ + .tolerated_failures = 1, + .devs_increment = 2, + .ncopies = 2, ++ .bg_flag = BTRFS_BLOCK_GROUP_RAID1, + }, + [BTRFS_RAID_DUP] = { + .sub_stripes = 1, +@@ -69,6 +71,7 @@ const struct btrfs_raid_attr btrfs_raid_ + .tolerated_failures = 0, + .devs_increment = 1, + .ncopies = 2, ++ .bg_flag = BTRFS_BLOCK_GROUP_DUP, + }, + [BTRFS_RAID_RAID0] = { + .sub_stripes = 1, +@@ -78,6 +81,7 @@ const struct btrfs_raid_attr btrfs_raid_ + .tolerated_failures = 0, + .devs_increment = 1, + .ncopies = 1, ++ .bg_flag = BTRFS_BLOCK_GROUP_RAID0, + }, + [BTRFS_RAID_SINGLE] = { + .sub_stripes = 1, +@@ -87,6 +91,7 @@ const struct btrfs_raid_attr btrfs_raid_ + .tolerated_failures = 0, + .devs_increment = 1, + .ncopies = 1, ++ .bg_flag = 0, + }, + [BTRFS_RAID_RAID5] = { + .sub_stripes = 1, +@@ -96,6 +101,7 @@ const struct btrfs_raid_attr btrfs_raid_ + .tolerated_failures = 1, + .devs_increment = 1, + .ncopies = 2, ++ .bg_flag = BTRFS_BLOCK_GROUP_RAID5, + }, + [BTRFS_RAID_RAID6] = { + .sub_stripes = 1, +@@ -105,19 +111,10 @@ const struct btrfs_raid_attr btrfs_raid_ + .tolerated_failures = 2, + .devs_increment = 1, + .ncopies = 3, ++ .bg_flag = BTRFS_BLOCK_GROUP_RAID6, + }, + }; + +-const u64 btrfs_raid_group[BTRFS_NR_RAID_TYPES] = { +- [BTRFS_RAID_RAID10] = BTRFS_BLOCK_GROUP_RAID10, +- [BTRFS_RAID_RAID1] = BTRFS_BLOCK_GROUP_RAID1, +- [BTRFS_RAID_DUP] = BTRFS_BLOCK_GROUP_DUP, +- [BTRFS_RAID_RAID0] = BTRFS_BLOCK_GROUP_RAID0, +- [BTRFS_RAID_SINGLE] = 0, +- [BTRFS_RAID_RAID5] = BTRFS_BLOCK_GROUP_RAID5, +- [BTRFS_RAID_RAID6] = BTRFS_BLOCK_GROUP_RAID6, +-}; +- + /* + * Table to convert BTRFS_RAID_* to the error code if minimum number of devices + * condition is not met. Zero means there's no corresponding +@@ -1802,7 +1799,7 @@ static int btrfs_check_raid_min_devices( + } while (read_seqretry(&fs_info->profiles_lock, seq)); + + for (i = 0; i < BTRFS_NR_RAID_TYPES; i++) { +- if (!(all_avail & btrfs_raid_group[i])) ++ if (!(all_avail & btrfs_raid_array[i].bg_flag)) + continue; + + if (num_devices < btrfs_raid_array[i].devs_min) { +--- a/fs/btrfs/volumes.h ++++ b/fs/btrfs/volumes.h +@@ -336,11 +336,11 @@ struct btrfs_raid_attr { + int tolerated_failures; /* max tolerated fail devs */ + int devs_increment; /* ndevs has to be a multiple of this */ + int ncopies; /* how many copies to data has */ ++ u64 bg_flag; /* block group flag of the raid */ + }; + + extern const struct btrfs_raid_attr btrfs_raid_array[BTRFS_NR_RAID_TYPES]; + extern const int btrfs_raid_mindev_error[BTRFS_NR_RAID_TYPES]; +-extern const u64 btrfs_raid_group[BTRFS_NR_RAID_TYPES]; + + struct map_lookup { + u64 type; diff --git a/patches.suse/btrfs-only-check-priority-tickets-for-priority-flushing.patch b/patches.suse/btrfs-only-check-priority-tickets-for-priority-flushing.patch new file mode 100644 index 0000000..815eea9 --- /dev/null +++ b/patches.suse/btrfs-only-check-priority-tickets-for-priority-flushing.patch @@ -0,0 +1,100 @@ +From: Josef Bacik +Date: Fri, 13 Mar 2020 15:58:08 -0400 +Subject: btrfs: only check priority tickets for priority flushing +Patch-mainline: Submitted, https://lore.kernel.org/linux-btrfs/20200313195809.141753-1-josef@toxicpanda.com/ +References: bsc#1165949 + +In debugging a generic/320 failure on ppc64, Nikolay noticed that +sometimes we'd ENOSPC out with plenty of space to reclaim if we had +committed the transaction. He further discovered that this was because +there was a priority ticket that was small enough to fit in the free +space currently in the space_info. + +Consider the following scenario. There is no more space to reclaim in +the fs without committing the transaction. Assume there's 1mib of space +free in the space info, but there are pending normal tickets with 2mib +reservations. + +Now a priority ticket comes in with a .5mib reservation. Because we +have normal tickets pending we add ourselves to the priority list, +despite the fact that we could satisfy this reservation. + +The flushing machinery now gets to the point where it wants to commit +the transaction, but because there's a .5mib ticket on the priority list +and we have 1mib of free space we assume the ticket will be granted +soon, so we bail without committing the transaction. + +Meanwhile the priority flushing does not commit the transaction, and +eventually fails with an ENOSPC. Then all other tickets are failed with +ENOSPC because we were never able to actually commit the transaction. + +The fix for this is we should have simply granted the priority flusher +his reservation, because there was space to make the reservation. +Priority flushers by definition take priority, so they are allowed to +make their reservations before any previous normal tickets. By not +adding this priority ticket to the list the normal flushing mechanisms +will then commit the transaction and everything will continue normally. + +We still need to serialize ourselves with other priority tickets, so if +there are any tickets on the priority list then we need to add ourselves +to that list in order to maintain the serialization between priority +tickets. + +Signed-off-by: Josef Bacik +Reviewed-by: Nikolay Borisov +Acked-by: Nikolay Borisov +--- + fs/btrfs/space-info.c | 26 ++++++++++++++++++++++---- + 1 file changed, 22 insertions(+), 4 deletions(-) + +--- a/fs/btrfs/space-info.c ++++ b/fs/btrfs/space-info.c +@@ -1030,6 +1030,17 @@ static int handle_reserve_ticket(struct + return ret; + } + ++ ++/* ++ * This returns true if this flush state will go through the ordinary flushing ++ * code. ++ */ ++static inline bool is_normal_flushing(enum btrfs_reserve_flush_enum flush) ++{ ++ return (flush == BTRFS_RESERVE_FLUSH_ALL) || ++ (flush == BTRFS_RESERVE_FLUSH_ALL_STEAL); ++} ++ + /** + * reserve_metadata_bytes - try to reserve bytes from the block_rsv's space + * @root - the root we're allocating for +@@ -1061,10 +1072,18 @@ static int __reserve_metadata_bytes(stru + spin_lock(&space_info->lock); + ret = -ENOSPC; + used = btrfs_space_info_used(space_info, true); +- pending_tickets = !list_empty(&space_info->tickets) || +- !list_empty(&space_info->priority_tickets); + + /* ++ * We don't want NO_FLUSH allocations to jump everybody, they can ++ * generally handle ENOSPC in a different way, so treat them the same as ++ * normal flushers when it comes to skipping pending tickets. ++ */ ++ if (is_normal_flushing(flush) || (flush == BTRFS_RESERVE_NO_FLUSH)) ++ pending_tickets = !list_empty(&space_info->tickets) || ++ !list_empty(&space_info->priority_tickets); ++ else ++ pending_tickets = !list_empty(&space_info->priority_tickets); ++ /* + * If we have enough space then hooray, make our reservation and carry + * on. If not see if we can overcommit, and if we can, hooray carry on. + * If not things get more complicated. +@@ -1088,8 +1107,7 @@ static int __reserve_metadata_bytes(stru + ticket.error = 0; + init_waitqueue_head(&ticket.wait); + ticket.steal = (flush == BTRFS_RESERVE_FLUSH_ALL_STEAL); +- if (flush == BTRFS_RESERVE_FLUSH_ALL || +- flush == BTRFS_RESERVE_FLUSH_ALL_STEAL) { ++ if (is_normal_flushing(flush)) { + list_add_tail(&ticket.list, &space_info->tickets); + if (!space_info->flush) { + space_info->flush = 1; diff --git a/patches.suse/btrfs-output-enospc-debug-info-in-inc_block_group_ro.patch b/patches.suse/btrfs-output-enospc-debug-info-in-inc_block_group_ro.patch new file mode 100644 index 0000000..a50e7b2 --- /dev/null +++ b/patches.suse/btrfs-output-enospc-debug-info-in-inc_block_group_ro.patch @@ -0,0 +1,61 @@ +From: Qu Wenruo +Date: Wed, 30 Jan 2019 13:07:51 +0800 +Subject: btrfs: Output ENOSPC debug info in inc_block_group_ro +Git-commit: 3ece54e504dc18068dee722e3dcb69d90b360988 +Patch-mainline: v5.1-rc1 +References: bsc#1165949 + +Since inc_block_group_ro() would return -ENOSPC, outputting debug info +for enospc_debug mount option would be helpful to debug some balance +false ENOSPC report. + +Signed-off-by: Qu Wenruo +Reviewed-by: David Sterba +Signed-off-by: David Sterba +Acked-by: Nikolay Borisov +--- + fs/btrfs/extent-tree.c | 15 +++++++++++++-- + 1 file changed, 13 insertions(+), 2 deletions(-) + +diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c +index 2f683dad3c66..994c71c9eb70 100644 +--- a/fs/btrfs/extent-tree.c ++++ b/fs/btrfs/extent-tree.c +@@ -9605,6 +9605,7 @@ static int inc_block_group_ro(struct btrfs_block_group_cache *cache, int force) + { + struct btrfs_space_info *sinfo = cache->space_info; + u64 num_bytes; ++ u64 sinfo_used; + u64 min_allocable_bytes; + int ret = -ENOSPC; + +@@ -9631,9 +9632,10 @@ static int inc_block_group_ro(struct btrfs_block_group_cache *cache, int force) + + num_bytes = cache->key.offset - cache->reserved - cache->pinned - + cache->bytes_super - btrfs_block_group_used(&cache->item); ++ sinfo_used = btrfs_space_info_used(sinfo, true); + +- if (btrfs_space_info_used(sinfo, true) + num_bytes + +- min_allocable_bytes <= sinfo->total_bytes) { ++ if (sinfo_used + num_bytes + min_allocable_bytes <= ++ sinfo->total_bytes) { + sinfo->bytes_readonly += num_bytes; + cache->ro++; + list_add_tail(&cache->ro_list, &sinfo->ro_bgs); +@@ -9642,6 +9644,15 @@ static int inc_block_group_ro(struct btrfs_block_group_cache *cache, int force) + out: + spin_unlock(&cache->lock); + spin_unlock(&sinfo->lock); ++ if (ret == -ENOSPC && btrfs_test_opt(cache->fs_info, ENOSPC_DEBUG)) { ++ btrfs_info(cache->fs_info, ++ "unable to make block group %llu ro", ++ cache->key.objectid); ++ btrfs_info(cache->fs_info, ++ "sinfo_used=%llu bg_num_bytes=%llu min_allocable=%llu", ++ sinfo_used, num_bytes, min_allocable_bytes); ++ dump_space_info(cache->fs_info, cache->space_info, 0, 0); ++ } + return ret; + } + + diff --git a/patches.suse/btrfs-prevent-ioctls-from-interfering-with-a-swap-file.patch b/patches.suse/btrfs-prevent-ioctls-from-interfering-with-a-swap-file.patch index 9e5f7c5..35ebab7 100644 --- a/patches.suse/btrfs-prevent-ioctls-from-interfering-with-a-swap-file.patch +++ b/patches.suse/btrfs-prevent-ioctls-from-interfering-with-a-swap-file.patch @@ -243,7 +243,7 @@ Acked-by: Nikolay Borisov - BUG_ON(!rc->block_group); + rc->block_group = bg; - ret = btrfs_inc_block_group_ro(fs_info, rc->block_group); + ret = btrfs_inc_block_group_ro(rc->block_group); if (ret) { --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c diff --git a/patches.suse/btrfs-qgroup-Don-t-hold-qgroup_ioctl_lock-in-btrfs_q.patch b/patches.suse/btrfs-qgroup-Don-t-hold-qgroup_ioctl_lock-in-btrfs_q.patch new file mode 100644 index 0000000..8e4d124 --- /dev/null +++ b/patches.suse/btrfs-qgroup-Don-t-hold-qgroup_ioctl_lock-in-btrfs_q.patch @@ -0,0 +1,187 @@ +From e88439debd0a7f969b3ddba6f147152cd0732676 Mon Sep 17 00:00:00 2001 +From: Qu Wenruo +Patch-mainline: v5.3 +Git-commit: e88439debd0a7f969b3ddba6f147152cd0732676 +References: bsc#1165823 +Date: Thu, 13 Jun 2019 17:31:24 +0800 +Subject: [PATCH] btrfs: qgroup: Don't hold qgroup_ioctl_lock in + btrfs_qgroup_inherit() + +[BUG] +Lockdep will report the following circular locking dependency: + + WARNING: possible circular locking dependency detected + 5.2.0-rc2-custom #24 Tainted: G O + ------------------------------------------------------ + btrfs/8631 is trying to acquire lock: + 000000002536438c (&fs_info->qgroup_ioctl_lock#2){+.+.}, at: btrfs_qgroup_inherit+0x40/0x620 [btrfs] + + but task is already holding lock: + 000000003d52cc23 (&fs_info->tree_log_mutex){+.+.}, at: create_pending_snapshot+0x8b6/0xe60 [btrfs] + + which lock already depends on the new lock. + + the existing dependency chain (in reverse order) is: + + -> #2 (&fs_info->tree_log_mutex){+.+.}: + __mutex_lock+0x76/0x940 + mutex_lock_nested+0x1b/0x20 + btrfs_commit_transaction+0x475/0xa00 [btrfs] + btrfs_commit_super+0x71/0x80 [btrfs] + close_ctree+0x2bd/0x320 [btrfs] + btrfs_put_super+0x15/0x20 [btrfs] + generic_shutdown_super+0x72/0x110 + kill_anon_super+0x18/0x30 + btrfs_kill_super+0x16/0xa0 [btrfs] + deactivate_locked_super+0x3a/0x80 + deactivate_super+0x51/0x60 + cleanup_mnt+0x3f/0x80 + __cleanup_mnt+0x12/0x20 + task_work_run+0x94/0xb0 + exit_to_usermode_loop+0xd8/0xe0 + do_syscall_64+0x210/0x240 + entry_SYSCALL_64_after_hwframe+0x49/0xbe + + -> #1 (&fs_info->reloc_mutex){+.+.}: + __mutex_lock+0x76/0x940 + mutex_lock_nested+0x1b/0x20 + btrfs_commit_transaction+0x40d/0xa00 [btrfs] + btrfs_quota_enable+0x2da/0x730 [btrfs] + btrfs_ioctl+0x2691/0x2b40 [btrfs] + do_vfs_ioctl+0xa9/0x6d0 + ksys_ioctl+0x67/0x90 + __x64_sys_ioctl+0x1a/0x20 + do_syscall_64+0x65/0x240 + entry_SYSCALL_64_after_hwframe+0x49/0xbe + + -> #0 (&fs_info->qgroup_ioctl_lock#2){+.+.}: + lock_acquire+0xa7/0x190 + __mutex_lock+0x76/0x940 + mutex_lock_nested+0x1b/0x20 + btrfs_qgroup_inherit+0x40/0x620 [btrfs] + create_pending_snapshot+0x9d7/0xe60 [btrfs] + create_pending_snapshots+0x94/0xb0 [btrfs] + btrfs_commit_transaction+0x415/0xa00 [btrfs] + btrfs_mksubvol+0x496/0x4e0 [btrfs] + btrfs_ioctl_snap_create_transid+0x174/0x180 [btrfs] + btrfs_ioctl_snap_create_v2+0x11c/0x180 [btrfs] + btrfs_ioctl+0xa90/0x2b40 [btrfs] + do_vfs_ioctl+0xa9/0x6d0 + ksys_ioctl+0x67/0x90 + __x64_sys_ioctl+0x1a/0x20 + do_syscall_64+0x65/0x240 + entry_SYSCALL_64_after_hwframe+0x49/0xbe + + other info that might help us debug this: + + Chain exists of: + &fs_info->qgroup_ioctl_lock#2 --> &fs_info->reloc_mutex --> &fs_info->tree_log_mutex + + Possible unsafe locking scenario: + + CPU0 CPU1 + ---- ---- + lock(&fs_info->tree_log_mutex); + lock(&fs_info->reloc_mutex); + lock(&fs_info->tree_log_mutex); + lock(&fs_info->qgroup_ioctl_lock#2); + + *** DEADLOCK *** + + 6 locks held by btrfs/8631: + #0: 00000000ed8f23f6 (sb_writers#12){.+.+}, at: mnt_want_write_file+0x28/0x60 + #1: 000000009fb1597a (&type->i_mutex_dir_key#10/1){+.+.}, at: btrfs_mksubvol+0x70/0x4e0 [btrfs] + #2: 0000000088c5ad88 (&fs_info->subvol_sem){++++}, at: btrfs_mksubvol+0x128/0x4e0 [btrfs] + #3: 000000009606fc3e (sb_internal#2){.+.+}, at: start_transaction+0x37a/0x520 [btrfs] + #4: 00000000f82bbdf5 (&fs_info->reloc_mutex){+.+.}, at: btrfs_commit_transaction+0x40d/0xa00 [btrfs] + #5: 000000003d52cc23 (&fs_info->tree_log_mutex){+.+.}, at: create_pending_snapshot+0x8b6/0xe60 [btrfs] + +[CAUSE] +Due to the delayed subvolume creation, we need to call +btrfs_qgroup_inherit() inside commit transaction code, with a lot of +other mutex hold. +This hell of lock chain can lead to above problem. + +[FIX] +On the other hand, we don't really need to hold qgroup_ioctl_lock if +we're in the context of create_pending_snapshot(). +As in that context, we're the only one being able to modify qgroup. + +All other qgroup functions which needs qgroup_ioctl_lock are either +holding a transaction handle, or will start a new transaction: + Functions will start a new transaction(): + * btrfs_quota_enable() + * btrfs_quota_disable() + Functions hold a transaction handler: + * btrfs_add_qgroup_relation() + * btrfs_del_qgroup_relation() + * btrfs_create_qgroup() + * btrfs_remove_qgroup() + * btrfs_limit_qgroup() + * btrfs_qgroup_inherit() call inside create_subvol() + +So we have a higher level protection provided by transaction, thus we +don't need to always hold qgroup_ioctl_lock in btrfs_qgroup_inherit(). + +Only the btrfs_qgroup_inherit() call in create_subvol() needs to hold +qgroup_ioctl_lock, while the btrfs_qgroup_inherit() call in +create_pending_snapshot() is already protected by transaction. + +So the fix is to detect the context by checking +trans->transaction->state. +If we're at TRANS_STATE_COMMIT_DOING, then we're in commit transaction +context and no need to get the mutex. + +Reported-by: Nikolay Borisov +Signed-off-by: Qu Wenruo +Signed-off-by: David Sterba +--- + fs/btrfs/qgroup.c | 24 ++++++++++++++++++++++-- + 1 file changed, 22 insertions(+), 2 deletions(-) + +--- a/fs/btrfs/qgroup.c ++++ b/fs/btrfs/qgroup.c +@@ -2581,13 +2581,32 @@ int btrfs_qgroup_inherit(struct btrfs_tr + int ret = 0; + int i; + u64 *i_qgroups; ++ bool committing = false; + struct btrfs_root *quota_root = fs_info->quota_root; + struct btrfs_qgroup *srcgroup; + struct btrfs_qgroup *dstgroup; + u32 level_size = 0; + u64 nums; + +- mutex_lock(&fs_info->qgroup_ioctl_lock); ++ /* ++ * There are only two callers of this function. ++ * ++ * One in create_subvol() in the ioctl context, which needs to hold ++ * the qgroup_ioctl_lock. ++ * ++ * The other one in create_pending_snapshot() where no other qgroup ++ * code can modify the fs as they all need to either start a new trans ++ * or hold a trans handler, thus we don't need to hold ++ * qgroup_ioctl_lock. ++ * This would avoid long and complex lock chain and make lockdep happy. ++ */ ++ spin_lock(&fs_info->trans_lock); ++ if (trans->transaction->state == TRANS_STATE_COMMIT_DOING) ++ committing = true; ++ spin_unlock(&fs_info->trans_lock); ++ ++ if (!committing) ++ mutex_lock(&fs_info->qgroup_ioctl_lock); + if (!test_bit(BTRFS_FS_QUOTA_ENABLED, &fs_info->flags)) + goto out; + +@@ -2765,7 +2784,8 @@ int btrfs_qgroup_inherit(struct btrfs_tr + unlock: + spin_unlock(&fs_info->qgroup_lock); + out: +- mutex_unlock(&fs_info->qgroup_ioctl_lock); ++ if (!committing) ++ mutex_unlock(&fs_info->qgroup_ioctl_lock); + return ret; + } + diff --git a/patches.suse/btrfs-qgroup-Mark-qgroup-inconsistent-if-we-re-inher.patch b/patches.suse/btrfs-qgroup-Mark-qgroup-inconsistent-if-we-re-inher.patch new file mode 100644 index 0000000..0aaad07 --- /dev/null +++ b/patches.suse/btrfs-qgroup-Mark-qgroup-inconsistent-if-we-re-inher.patch @@ -0,0 +1,113 @@ +From af917575332599d3323a88b8d16d5b59ac5d753b Mon Sep 17 00:00:00 2001 +From: Qu Wenruo +Date: Thu, 2 Apr 2020 14:24:57 +0800 +Patch-mainline: Submitted, Thu, 2 Apr 2020 14:37:35 +0800 +References: bsc#1165823 +Subject: [PATCH] btrfs: qgroup: Mark qgroup inconsistent if we're inherting + snapshot to a new qgroup + +[BUG] +For the following operation, qgroup is guaranteed to be screwed up due +to snapshot adding to a new qgroup: + + # mkfs.btrfs -f $dev + # mount $dev $mnt + # btrfs qgroup en $mnt + # btrfs subv create $mnt/src + # xfs_io -f -c "pwrite 0 1m" $mnt/src/file + # sync + # btrfs qgroup create 1/0 $mnt/src + # btrfs subv snapshot -i 1/0 $mnt/src $mnt/snapshot + # btrfs qgroup show -prce $mnt/src + qgroupid rfer excl max_rfer max_excl parent child + -------- ---- ---- -------- -------- ------ ----- + 0/5 16.00KiB 16.00KiB none none --- --- + 0/257 1.02MiB 16.00KiB none none --- --- + 0/258 1.02MiB 16.00KiB none none 1/0 --- + 1/0 0.00B 0.00B none none --- 0/258 + ^^^^^^^^^^^^^^^^^^^^ + +[CAUSE] +The problem is in btrfs_qgroup_inherit(), we don't have good enough +check to determine if the new relation ship would break the existing +accounting. + +Unlike btrfs_add_qgroup_relation(), which has proper check to determine +if we can do quick update without a rescan, in btrfs_qgroup_inherit() we +can even assign a snapshot to multiple qgroups. + +[FIX] +Fix the problem by manually marking qgroup inconsistent for snapshot +inheritance. + +For subvolume creation, since all its extents are exclusively owned by +itself, we don't need to rescan. + +In theory, we should call relationship check like quick_update_accounting() +when doing qgroup inheritance and inform user about qgroup inconsistent. + +But we don't have good enough mechanism to inform user in the snapshot +creation context, thus we can only silently mark the qgroup +inconsistent. + +Anyway, user shouldn't use qgroup inheritance during snapshot creation, +and should add qgroup relationship after snapshot creation by 'btrfs +qgroup assign', which has a much better UI to inform user about qgroup +inconsistent and kick in rescan automatically. + +Signed-off-by: Qu Wenruo +--- + fs/btrfs/qgroup.c | 14 ++++++++++++++ + 1 file changed, 14 insertions(+) + +--- a/fs/btrfs/qgroup.c ++++ b/fs/btrfs/qgroup.c +@@ -2585,6 +2585,7 @@ int btrfs_qgroup_inherit(struct btrfs_tr + struct btrfs_root *quota_root = fs_info->quota_root; + struct btrfs_qgroup *srcgroup; + struct btrfs_qgroup *dstgroup; ++ bool need_rescan = false; + u32 level_size = 0; + u64 nums; + +@@ -2742,6 +2743,13 @@ int btrfs_qgroup_inherit(struct btrfs_tr + goto unlock; + } + ++i_qgroups; ++ ++ /* ++ * If we're doing a snapshot, and adding the snapshot to a new ++ * qgroup, the numbers are guaranteed to be incorrect. ++ */ ++ if (srcid) ++ need_rescan = true; + } + + for (i = 0; i < inherit->num_ref_copies; ++i, i_qgroups += 2) { +@@ -2761,6 +2769,9 @@ int btrfs_qgroup_inherit(struct btrfs_tr + + dst->rfer = src->rfer - level_size; + dst->rfer_cmpr = src->rfer_cmpr - level_size; ++ ++ /* Manually tweaking numbers? No way to keep qgroup sane */ ++ need_rescan = true; + } + for (i = 0; i < inherit->num_excl_copies; ++i, i_qgroups += 2) { + struct btrfs_qgroup *src; +@@ -2779,6 +2790,7 @@ int btrfs_qgroup_inherit(struct btrfs_tr + + dst->excl = src->excl + level_size; + dst->excl_cmpr = src->excl_cmpr + level_size; ++ need_rescan = true; + } + + unlock: +@@ -2786,6 +2798,8 @@ unlock: + out: + if (!committing) + mutex_unlock(&fs_info->qgroup_ioctl_lock); ++ if (need_rescan) ++ fs_info->qgroup_flags |= BTRFS_QGROUP_STATUS_FLAG_INCONSISTENT; + return ret; + } + diff --git a/patches.suse/btrfs-refactor-block-group-replication-factor-calculation-to-a-helper.patch b/patches.suse/btrfs-refactor-block-group-replication-factor-calculation-to-a-helper.patch new file mode 100644 index 0000000..fd51421 --- /dev/null +++ b/patches.suse/btrfs-refactor-block-group-replication-factor-calculation-to-a-helper.patch @@ -0,0 +1,146 @@ +From: David Sterba +Date: Fri, 13 Jul 2018 20:46:30 +0200 +Subject: btrfs: refactor block group replication factor calculation to a helper +Git-commit: 46df06b85e28eaf430aa5c8f8aa26120fa746b72 +Patch-mainline: v4.19-rc1 +References: bsc#1165949 + +There are many places that open code the duplicity factor of the block +group profiles, create a common helper. This can be easily extended for +more copies. + +Signed-off-by: David Sterba +Acked-by: Nikolay Borisov +--- + fs/btrfs/extent-tree.c | 36 ++++++++---------------------------- + fs/btrfs/super.c | 11 +++-------- + fs/btrfs/volumes.c | 11 +++++++++++ + fs/btrfs/volumes.h | 2 ++ + 4 files changed, 24 insertions(+), 36 deletions(-) + +--- a/fs/btrfs/extent-tree.c ++++ b/fs/btrfs/extent-tree.c +@@ -4093,11 +4093,7 @@ static void update_space_info(struct btr + struct btrfs_space_info *found; + int factor; + +- if (flags & (BTRFS_BLOCK_GROUP_DUP | BTRFS_BLOCK_GROUP_RAID1 | +- BTRFS_BLOCK_GROUP_RAID10)) +- factor = 2; +- else +- factor = 1; ++ factor = btrfs_bg_type_to_factor(flags); + + found = __find_space_info(info, flags); + ASSERT(found); +@@ -4729,6 +4725,7 @@ static int can_overcommit(struct btrfs_r + u64 space_size; + u64 avail; + u64 used; ++ int factor; + + /* Don't overcommit when in mixed mode. */ + if (space_info->flags & BTRFS_BLOCK_GROUP_DATA) +@@ -4761,10 +4758,8 @@ static int can_overcommit(struct btrfs_r + * doesn't include the parity drive, so we don't have to + * change the math + */ +- if (profile & (BTRFS_BLOCK_GROUP_DUP | +- BTRFS_BLOCK_GROUP_RAID1 | +- BTRFS_BLOCK_GROUP_RAID10)) +- avail >>= 1; ++ factor = btrfs_bg_type_to_factor(profile); ++ avail = div_u64(avail, factor); + + /* + * If we aren't flushing all things, let us overcommit up to +@@ -6264,12 +6259,8 @@ static int update_block_group(struct btr + cache = btrfs_lookup_block_group(info, bytenr); + if (!cache) + return -ENOENT; +- if (cache->flags & (BTRFS_BLOCK_GROUP_DUP | +- BTRFS_BLOCK_GROUP_RAID1 | +- BTRFS_BLOCK_GROUP_RAID10)) +- factor = 2; +- else +- factor = 1; ++ factor = btrfs_bg_type_to_factor(cache->flags); ++ + /* + * If this block group has free space cache written out, we + * need to make sure to load it if we are removing space. This +@@ -9529,13 +9520,7 @@ u64 btrfs_account_ro_block_groups_free_s + continue; + } + +- if (block_group->flags & (BTRFS_BLOCK_GROUP_RAID1 | +- BTRFS_BLOCK_GROUP_RAID10 | +- BTRFS_BLOCK_GROUP_DUP)) +- factor = 2; +- else +- factor = 1; +- ++ factor = btrfs_bg_type_to_factor(block_group->flags); + free_bytes += (block_group->key.offset - + btrfs_block_group_used(&block_group->item)) * + factor; +@@ -10351,12 +10336,7 @@ int btrfs_remove_block_group(struct btrf + + memcpy(&key, &block_group->key, sizeof(key)); + index = get_block_group_index(block_group); +- if (block_group->flags & (BTRFS_BLOCK_GROUP_DUP | +- BTRFS_BLOCK_GROUP_RAID1 | +- BTRFS_BLOCK_GROUP_RAID10)) +- factor = 2; +- else +- factor = 1; ++ factor = btrfs_bg_type_to_factor(block_group->flags); + + /* make sure this block group isn't part of an allocation cluster */ + cluster = &fs_info->data_alloc_cluster; +--- a/fs/btrfs/super.c ++++ b/fs/btrfs/super.c +@@ -2095,14 +2095,9 @@ static int btrfs_statfs(struct dentry *d + btrfs_account_ro_block_groups_free_space(found); + + for (i = 0; i < BTRFS_NR_RAID_TYPES; i++) { +- if (!list_empty(&found->block_groups[i])) { +- switch (i) { +- case BTRFS_RAID_DUP: +- case BTRFS_RAID_RAID1: +- case BTRFS_RAID_RAID10: +- factor = 2; +- } +- } ++ if (!list_empty(&found->block_groups[i])) ++ factor = btrfs_bg_type_to_factor( ++ btrfs_raid_array[i].bg_flag); + } + } + +--- a/fs/btrfs/volumes.c ++++ b/fs/btrfs/volumes.c +@@ -7325,3 +7325,14 @@ void btrfs_reset_fs_info_ptr(struct btrf + fs_devices = fs_devices->seed; + } + } ++ ++/* ++ * Multiplicity factor for simple profiles: DUP, RAID1-like and RAID10. ++ */ ++int btrfs_bg_type_to_factor(u64 flags) ++{ ++ if (flags & (BTRFS_BLOCK_GROUP_DUP | BTRFS_BLOCK_GROUP_RAID1 | ++ BTRFS_BLOCK_GROUP_RAID10)) ++ return 2; ++ return 1; ++} +--- a/fs/btrfs/volumes.h ++++ b/fs/btrfs/volumes.h +@@ -551,4 +551,6 @@ struct list_head *btrfs_get_fs_uuids(voi + void btrfs_set_fs_info_ptr(struct btrfs_fs_info *fs_info); + void btrfs_reset_fs_info_ptr(struct btrfs_fs_info *fs_info); + ++int btrfs_bg_type_to_factor(u64 flags); ++ + #endif diff --git a/patches.suse/btrfs-remove-btrfs_inode-delayed_iput_count.patch b/patches.suse/btrfs-remove-btrfs_inode-delayed_iput_count.patch new file mode 100644 index 0000000..a23a8b2 --- /dev/null +++ b/patches.suse/btrfs-remove-btrfs_inode-delayed_iput_count.patch @@ -0,0 +1,100 @@ +From: Nikolay Borisov +Date: Tue, 16 Jan 2018 09:31:58 +0200 +Subject: btrfs: Remove btrfs_inode::delayed_iput_count +Git-commit: c1c3fac2a95b14e36333528e408e76d90c93bbf7 +Patch-mainline: v4.17-rc1 +References: bsc#1165949 + +delayed_iput_count wa supposed to be used to implement, well, delayed +iput. The idea is that we keep accumulating the number of iputs we do +until eventually the inode is deleted. Turns out we never really +switched the delayed_iput_count from 0 to 1, hence all conditional +code relying on the value of that member being different than 0 was +never executed. This, as it turns out, didn't cause any problem due +to the simple fact that the generic inode's i_count member was always +used to count the number of iputs. So let's just remove the unused +member and all unused code. This patch essentially provides no +functional changes. While at it, also add proper documentation for +btrfs_add_delayed_iput + +Signed-off-by: Nikolay Borisov +Reviewed-by: David Sterba +[ reformat comment ] +Signed-off-by: David Sterba +--- + fs/btrfs/btrfs_inode.h | 1 - + fs/btrfs/inode.c | 27 +++++++++++++-------------- + 2 files changed, 13 insertions(+), 15 deletions(-) + +diff --git a/fs/btrfs/btrfs_inode.h b/fs/btrfs/btrfs_inode.h +index 63f0ccc92a71..f527e99c9f8d 100644 +--- a/fs/btrfs/btrfs_inode.h ++++ b/fs/btrfs/btrfs_inode.h +@@ -195,7 +195,6 @@ struct btrfs_inode { + + /* Hook into fs_info->delayed_iputs */ + struct list_head delayed_iput; +- long delayed_iput_count; + + /* + * To avoid races between lockless (i_mutex not held) direct IO writes +diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c +index 4d3a4d1507a1..b55b47f493e9 100644 +--- a/fs/btrfs/inode.c ++++ b/fs/btrfs/inode.c +@@ -3242,6 +3242,16 @@ static int btrfs_readpage_end_io_hook(struct btrfs_io_bio *io_bio, + start, (size_t)(end - start + 1)); + } + ++/* ++ * btrfs_add_delayed_iput - perform a delayed iput on @inode ++ * ++ * @inode: The inode we want to perform iput on ++ * ++ * This function uses the generic vfs_inode::i_count to track whether we should ++ * just decrement it (in case it's > 1) or if this is the last iput then link ++ * the inode to the delayed iput machinery. Delayed iputs are processed at ++ * transaction commit time/superblock commit/cleaner kthread. ++ */ + void btrfs_add_delayed_iput(struct inode *inode) + { + struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb); +@@ -3251,12 +3261,8 @@ void btrfs_add_delayed_iput(struct inode *inode) + return; + + spin_lock(&fs_info->delayed_iput_lock); +- if (binode->delayed_iput_count == 0) { +- ASSERT(list_empty(&binode->delayed_iput)); +- list_add_tail(&binode->delayed_iput, &fs_info->delayed_iputs); +- } else { +- binode->delayed_iput_count++; +- } ++ ASSERT(list_empty(&binode->delayed_iput)); ++ list_add_tail(&binode->delayed_iput, &fs_info->delayed_iputs); + spin_unlock(&fs_info->delayed_iput_lock); + } + +@@ -3269,13 +3275,7 @@ void btrfs_run_delayed_iputs(struct btrfs_fs_info *fs_info) + + inode = list_first_entry(&fs_info->delayed_iputs, + struct btrfs_inode, delayed_iput); +- if (inode->delayed_iput_count) { +- inode->delayed_iput_count--; +- list_move_tail(&inode->delayed_iput, +- &fs_info->delayed_iputs); +- } else { +- list_del_init(&inode->delayed_iput); +- } ++ list_del_init(&inode->delayed_iput); + spin_unlock(&fs_info->delayed_iput_lock); + iput(&inode->vfs_inode); + spin_lock(&fs_info->delayed_iput_lock); +@@ -9333,7 +9333,6 @@ struct inode *btrfs_alloc_inode(struct super_block *sb) + ei->dir_index = 0; + ei->last_unlink_trans = 0; + ei->last_log_commit = 0; +- ei->delayed_iput_count = 0; + + spin_lock_init(&ei->lock); + ei->outstanding_extents = 0; + diff --git a/patches.suse/btrfs-remove-fs_info-from-do_chunk_alloc.patch b/patches.suse/btrfs-remove-fs_info-from-do_chunk_alloc.patch new file mode 100644 index 0000000..8289598 --- /dev/null +++ b/patches.suse/btrfs-remove-fs_info-from-do_chunk_alloc.patch @@ -0,0 +1,98 @@ +From: Nikolay Borisov +Date: Wed, 20 Jun 2018 15:49:05 +0300 +Subject: btrfs: Remove fs_info from do_chunk_alloc +Git-commit: 01458828bb420d6a8f9aa09af2376caab71660b3 +Patch-mainline: v4.19-rc1 +References: bsc#1165949 + +This function is always called with a valid transaction handle from +where fs_info can be referenced. No functional changes. + +Signed-off-by: Nikolay Borisov +Reviewed-by: Qu Wenruo +Signed-off-by: David Sterba +--- + fs/btrfs/extent-tree.c | 22 ++++++++++------------ + 1 file changed, 10 insertions(+), 12 deletions(-) + +--- a/fs/btrfs/extent-tree.c ++++ b/fs/btrfs/extent-tree.c +@@ -84,8 +84,7 @@ static int alloc_reserved_tree_block(str + u64 parent, u64 root_objectid, + u64 flags, struct btrfs_disk_key *key, + int level, struct btrfs_key *ins); +-static int do_chunk_alloc(struct btrfs_trans_handle *trans, +- struct btrfs_fs_info *fs_info, u64 flags, ++static int do_chunk_alloc(struct btrfs_trans_handle *trans, u64 flags, + int force); + static int find_next_key(struct btrfs_path *path, int level, + struct btrfs_key *key); +@@ -4327,7 +4326,7 @@ alloc: + if (IS_ERR(trans)) + return PTR_ERR(trans); + +- ret = do_chunk_alloc(trans, fs_info, alloc_target, ++ ret = do_chunk_alloc(trans, alloc_target, + CHUNK_ALLOC_NO_FORCE); + btrfs_end_transaction(trans); + if (ret < 0) { +@@ -4616,9 +4615,10 @@ void check_system_chunk(struct btrfs_tra + * - return 1 if it successfully allocates a chunk, + * - return errors including -ENOSPC otherwise. + */ +-static int do_chunk_alloc(struct btrfs_trans_handle *trans, +- struct btrfs_fs_info *fs_info, u64 flags, int force) ++static int do_chunk_alloc(struct btrfs_trans_handle *trans, u64 flags, ++ int force) + { ++ struct btrfs_fs_info *fs_info = trans->fs_info; + struct btrfs_space_info *space_info; + int wait_for_alloc = 0; + int ret = 0; +@@ -5024,7 +5024,7 @@ static int flush_space(struct btrfs_fs_i + ret = PTR_ERR(trans); + break; + } +- ret = do_chunk_alloc(trans, fs_info, ++ ret = do_chunk_alloc(trans, + btrfs_metadata_alloc_profile(fs_info), + CHUNK_ALLOC_NO_FORCE); + btrfs_end_transaction(trans); +@@ -7920,8 +7920,7 @@ loop: + goto out; + } + +- ret = do_chunk_alloc(trans, fs_info, flags, +- CHUNK_ALLOC_FORCE); ++ ret = do_chunk_alloc(trans, flags, CHUNK_ALLOC_FORCE); + + /* + * If we can't allocate a new chunk we've already looped +@@ -9483,7 +9482,7 @@ again: + */ + alloc_flags = update_block_group_flags(fs_info, cache->flags); + if (alloc_flags != cache->flags) { +- ret = do_chunk_alloc(trans, fs_info, alloc_flags, ++ ret = do_chunk_alloc(trans, alloc_flags, + CHUNK_ALLOC_FORCE); + /* + * ENOSPC is allowed here, we may have enough space +@@ -9500,8 +9499,7 @@ again: + if (!ret) + goto out; + alloc_flags = get_alloc_profile(fs_info, cache->space_info->flags); +- ret = do_chunk_alloc(trans, fs_info, alloc_flags, +- CHUNK_ALLOC_FORCE); ++ ret = do_chunk_alloc(trans, alloc_flags, CHUNK_ALLOC_FORCE); + if (ret < 0) + goto out; + ret = inc_block_group_ro(cache, 0); +@@ -9523,7 +9521,7 @@ int btrfs_force_chunk_alloc(struct btrfs + { + u64 alloc_flags = get_alloc_profile(fs_info, type); + +- return do_chunk_alloc(trans, fs_info, alloc_flags, CHUNK_ALLOC_FORCE); ++ return do_chunk_alloc(trans, alloc_flags, CHUNK_ALLOC_FORCE); + } + + /* diff --git a/patches.suse/btrfs-remove-redundant-argument-of-flush_space.patch b/patches.suse/btrfs-remove-redundant-argument-of-flush_space.patch new file mode 100644 index 0000000..24b8131 --- /dev/null +++ b/patches.suse/btrfs-remove-redundant-argument-of-flush_space.patch @@ -0,0 +1,133 @@ +From: Nikolay Borisov +Date: Tue, 11 Jul 2017 13:25:13 +0300 +Subject: btrfs: Remove redundant argument of flush_space +Git-commit: 7bdd6277e0dc2beb4f5db5ea4ff7670ecf0b5879 +Patch-mainline: v4.14-rc1 +References: bsc#1165949 + +All callers of flush_space pass the same number for orig/num_bytes +arguments. Let's remove one of the numbers and also modify the trace +point to show only a single number - bytes requested. + +Seems that last point where the two parameters were treated differently +is before the ticketed enospc rework. + +Signed-off-by: Nikolay Borisov +Reviewed-by: David Sterba +Signed-off-by: David Sterba +--- + fs/btrfs/extent-tree.c | 18 ++++++++---------- + include/trace/events/btrfs.h | 13 +++++-------- + 2 files changed, 13 insertions(+), 18 deletions(-) + +--- a/fs/btrfs/extent-tree.c ++++ b/fs/btrfs/extent-tree.c +@@ -4890,7 +4890,7 @@ struct reserve_ticket { + + static int flush_space(struct btrfs_fs_info *fs_info, + struct btrfs_space_info *space_info, u64 num_bytes, +- u64 orig_bytes, int state) ++ int state) + { + struct btrfs_root *root = fs_info->extent_root; + struct btrfs_trans_handle *trans; +@@ -4915,7 +4915,7 @@ static int flush_space(struct btrfs_fs_i + break; + case FLUSH_DELALLOC: + case FLUSH_DELALLOC_WAIT: +- shrink_delalloc(root, num_bytes * 2, orig_bytes, ++ shrink_delalloc(root, num_bytes * 2, num_bytes, + state == FLUSH_DELALLOC_WAIT); + break; + case ALLOC_CHUNK: +@@ -4933,15 +4933,15 @@ static int flush_space(struct btrfs_fs_i + break; + case COMMIT_TRANS: + ret = may_commit_transaction(fs_info, space_info, +- orig_bytes, 0); ++ num_bytes, 0); + break; + default: + ret = -ENOSPC; + break; + } + +- trace_btrfs_flush_space(fs_info, space_info->flags, num_bytes, +- orig_bytes, state, ret); ++ trace_btrfs_flush_space(fs_info, space_info->flags, num_bytes, state, ++ ret); + return ret; + } + +@@ -5045,8 +5045,7 @@ static void btrfs_async_reclaim_metadata + struct reserve_ticket *ticket; + int ret; + +- ret = flush_space(fs_info, space_info, to_reclaim, to_reclaim, +- flush_state); ++ ret = flush_space(fs_info, space_info, to_reclaim, flush_state); + spin_lock(&space_info->lock); + if (list_empty(&space_info->tickets)) { + space_info->flush = 0; +@@ -5101,8 +5100,7 @@ static void priority_reclaim_metadata_sp + spin_unlock(&space_info->lock); + + do { +- flush_space(fs_info, space_info, to_reclaim, to_reclaim, +- flush_state); ++ flush_space(fs_info, space_info, to_reclaim, flush_state); + flush_state++; + spin_lock(&space_info->lock); + if (ticket->bytes == 0) { +@@ -5803,7 +5801,7 @@ int btrfs_orphan_reserve_metadata(struct + */ + u64 num_bytes = btrfs_calc_trans_metadata_size(fs_info, 1); + +- trace_btrfs_space_reservation(fs_info, "orphan", btrfs_ino(inode), ++ trace_btrfs_space_reservation(fs_info, "orphan", btrfs_ino(inode), + num_bytes, 1); + return btrfs_block_rsv_migrate(src_rsv, dst_rsv, num_bytes, 1); + } +--- a/include/trace/events/btrfs.h ++++ b/include/trace/events/btrfs.h +@@ -1011,15 +1011,14 @@ TRACE_EVENT(btrfs_trigger_flush, + TRACE_EVENT(btrfs_flush_space, + + TP_PROTO(const struct btrfs_fs_info *fs_info, u64 flags, u64 num_bytes, +- u64 orig_bytes, int state, int ret), ++ int state, int ret), + +- TP_ARGS(fs_info, flags, num_bytes, orig_bytes, state, ret), ++ TP_ARGS(fs_info, flags, num_bytes, state, ret), + + TP_STRUCT__entry( + __array( u8, fsid, BTRFS_UUID_SIZE ) + __field( u64, flags ) + __field( u64, num_bytes ) +- __field( u64, orig_bytes ) + __field( int, state ) + __field( int, ret ) + ), +@@ -1028,19 +1027,17 @@ TRACE_EVENT(btrfs_flush_space, + memcpy(__entry->fsid, fs_info->fsid, BTRFS_UUID_SIZE); + __entry->flags = flags; + __entry->num_bytes = num_bytes; +- __entry->orig_bytes = orig_bytes; + __entry->state = state; + __entry->ret = ret; + ), + +- TP_printk("%pU: state=%d(%s) flags=%llu(%s) num_bytes=%llu " +- "orig_bytes=%llu ret=%d", __entry->fsid, __entry->state, ++ TP_printk("%pU: state=%d(%s) flags=%llu(%s) num_bytes=%llu ret=%d", ++ __entry->fsid, __entry->state, + show_flush_state(__entry->state), + (unsigned long long)__entry->flags, + __print_flags((unsigned long)__entry->flags, "|", + BTRFS_GROUP_FLAGS), +- (unsigned long long)__entry->num_bytes, +- (unsigned long long)__entry->orig_bytes, __entry->ret) ++ (unsigned long long)__entry->num_bytes, __entry->ret) + ); + + DECLARE_EVENT_CLASS(btrfs__reserved_extent, diff --git a/patches.suse/btrfs-reserve-delalloc-metadata-differently.patch b/patches.suse/btrfs-reserve-delalloc-metadata-differently.patch new file mode 100644 index 0000000..f04f050 --- /dev/null +++ b/patches.suse/btrfs-reserve-delalloc-metadata-differently.patch @@ -0,0 +1,233 @@ +From: Josef Bacik +Date: Wed, 10 Apr 2019 15:56:10 -0400 +Subject: btrfs: reserve delalloc metadata differently +Git-commit: c8eaeac7b734347c3afba7008b7af62f37b9c140 +Patch-mainline: v5.2-rc1 +References: bsc#1165949 + +With the per-inode block reserves we started refilling the reserve based +on the calculated size of the outstanding csum bytes and extents for the +inode, including the amount we were adding with the new operation. + +However, generic/224 exposed a problem with this approach. With 1000 +files all writing at the same time we ended up with a bunch of bytes +being reserved but unusable. + +When you write to a file we reserve space for the csum leaves for those +bytes, the number of extent items required to cover those bytes, and a +single transaction item for updating the inode at ordered extent finish +for that range of bytes. This is held until the ordered extent finishes +and we release all of the reserved space. + +If a second write comes in at this point we would add a single +reservation for the new outstanding extent and however many reservations +for the csum leaves. At this point we find the delta of how much we +have reserved and how much outstanding size this is and attempt to +reserve this delta. If the first write finishes it will not release any +space, because the space it had reserved for the initial write is still +needed for the second write. However some space would have been used, +as we have added csums, extent items, and dirtied the inode. Our +reserved space would be > 0 but less than the total needed reserved +space. + +This is just for a single inode, now consider generic/224. This has +1000 inodes writing in parallel to a very small file system, 1GiB. In +my testing this usually means we get about a 120MiB metadata area to +work with, more than enough to allow the writes to continue, but not +enough if all of the inodes are stuck trying to reserve the slack space +while continuing to hold their leftovers from their initial writes. + +Fix this by pre-reserved _only_ for the space we are currently trying to +add. Then once that is successful modify our inodes csum count and +outstanding extents, and then add the newly reserved space to the inodes +block_rsv. This allows us to actually pass generic/224 without running +out of metadata space. + +Signed-off-by: Josef Bacik +Signed-off-by: David Sterba +Acked-by: Nikolay Borisov +--- + fs/btrfs/extent-tree.c | 143 +++++++++++++++++-------------------------------- + 1 file changed, 52 insertions(+), 91 deletions(-) + +--- a/fs/btrfs/extent-tree.c ++++ b/fs/btrfs/extent-tree.c +@@ -5936,85 +5936,6 @@ int btrfs_block_rsv_refill(struct btrfs_ + return ret; + } + +-static void calc_refill_bytes(struct btrfs_block_rsv *block_rsv, +- u64 *metadata_bytes, u64 *qgroup_bytes) +-{ +- *metadata_bytes = 0; +- *qgroup_bytes = 0; +- +- spin_lock(&block_rsv->lock); +- if (block_rsv->reserved < block_rsv->size) +- *metadata_bytes = block_rsv->size - block_rsv->reserved; +- if (block_rsv->qgroup_rsv_reserved < block_rsv->qgroup_rsv_size) +- *qgroup_bytes = block_rsv->qgroup_rsv_size - +- block_rsv->qgroup_rsv_reserved; +- spin_unlock(&block_rsv->lock); +-} +- +-/** +- * 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, last = 0; +- u64 qgroup_num_bytes; +- int ret = -ENOSPC; +- +- calc_refill_bytes(block_rsv, &num_bytes, &qgroup_num_bytes); +- if (num_bytes == 0) +- return 0; +- +- do { +- 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); +- if (ret) { +- btrfs_qgroup_free_meta_prealloc(root, qgroup_num_bytes); +- last = num_bytes; +- /* +- * If we are fragmented we can end up with a lot of +- * outstanding extents which will make our size be much +- * larger than our reserved amount. +- * +- * If the reservation happens here, it might be very +- * big though not needed in the end, if the delalloc +- * flushing happens. +- * +- * If this is the case try and do the reserve again. +- */ +- if (flush == BTRFS_RESERVE_FLUSH_ALL) +- calc_refill_bytes(block_rsv, &num_bytes, +- &qgroup_num_bytes); +- if (num_bytes == 0) +- return 0; +- } +- } while (ret && last != num_bytes); +- +- if (!ret) { +- block_rsv_add_bytes(block_rsv, num_bytes, 0); +- trace_btrfs_space_reservation(root->fs_info, "delalloc", +- btrfs_ino(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); +- } +- return ret; +-} +- + static u64 __btrfs_block_rsv_release(struct btrfs_fs_info *fs_info, + struct btrfs_block_rsv *block_rsv, + u64 num_bytes, u64 *qgroup_to_release) +@@ -6338,9 +6259,25 @@ static void btrfs_calculate_inode_block_ + spin_unlock(&block_rsv->lock); + } + ++static void calc_inode_reservations(struct btrfs_fs_info *fs_info, ++ u64 num_bytes, u64 *meta_reserve, ++ u64 *qgroup_reserve) ++{ ++ u64 nr_extents = count_max_extents(num_bytes); ++ u64 csum_leaves = btrfs_csum_bytes_to_leaves(fs_info, num_bytes); ++ ++ /* We add one for the inode update at finish ordered time */ ++ *meta_reserve = btrfs_calc_trans_metadata_size(fs_info, ++ nr_extents + csum_leaves + 1); ++ *qgroup_reserve = nr_extents * fs_info->nodesize; ++} ++ + int btrfs_delalloc_reserve_metadata(struct btrfs_inode *inode, u64 num_bytes) + { +- struct btrfs_fs_info *fs_info = btrfs_sb(inode->vfs_inode.i_sb); ++ struct btrfs_root *root = inode->root; ++ struct btrfs_fs_info *fs_info = root->fs_info; ++ struct btrfs_block_rsv *block_rsv = &inode->block_rsv; ++ u64 meta_reserve, qgroup_reserve; + unsigned nr_extents; + enum btrfs_reserve_flush_enum flush = BTRFS_RESERVE_FLUSH_ALL; + int ret = 0; +@@ -6370,7 +6307,31 @@ int btrfs_delalloc_reserve_metadata(stru + + num_bytes = ALIGN(num_bytes, fs_info->sectorsize); + +- /* Add our new extents and calculate the new rsv size. */ ++ /* ++ * We always want to do it this way, every other way is wrong and ends ++ * in tears. Pre-reserving the amount we are going to add will always ++ * be the right way, because otherwise if we have enough parallelism we ++ * could end up with thousands of inodes all holding little bits of ++ * reservations they were able to make previously and the only way to ++ * reclaim that space is to ENOSPC out the operations and clear ++ * everything out and try again, which is bad. This way we just ++ * over-reserve slightly, and clean up the mess when we are done. ++ */ ++ calc_inode_reservations(fs_info, num_bytes, &meta_reserve, ++ &qgroup_reserve); ++ ret = btrfs_qgroup_reserve_meta_prealloc(root, qgroup_reserve, true); ++ if (ret) ++ goto out_fail; ++ ret = reserve_metadata_bytes(root, block_rsv, meta_reserve, flush); ++ if (ret) ++ goto out_qgroup; ++ ++ /* ++ * Now we need to update our outstanding extents and csum bytes _first_ ++ * and then add the reservation to the block_rsv. This keeps us from ++ * racing with an ordered completion or some such that would think it ++ * needs to free the reservation we just made. ++ */ + spin_lock(&inode->lock); + nr_extents = count_max_extents(num_bytes); + btrfs_mod_outstanding_extents(inode, nr_extents); +@@ -6378,22 +6339,22 @@ int btrfs_delalloc_reserve_metadata(stru + btrfs_calculate_inode_block_rsv_size(fs_info, inode); + spin_unlock(&inode->lock); + +- ret = btrfs_inode_rsv_refill(inode, flush); +- if (unlikely(ret)) +- goto out_fail; ++ /* Now we can safely add our space to our block rsv */ ++ block_rsv_add_bytes(block_rsv, meta_reserve, false); ++ trace_btrfs_space_reservation(root->fs_info, "delalloc", ++ btrfs_ino(inode), meta_reserve, 1); ++ ++ spin_lock(&block_rsv->lock); ++ block_rsv->qgroup_rsv_reserved += qgroup_reserve; ++ spin_unlock(&block_rsv->lock); + + if (delalloc_lock) + mutex_unlock(&inode->delalloc_mutex); + return 0; + ++out_qgroup: ++ btrfs_qgroup_free_meta_prealloc(root, qgroup_reserve); + out_fail: +- spin_lock(&inode->lock); +- nr_extents = count_max_extents(num_bytes); +- btrfs_mod_outstanding_extents(inode, -nr_extents); +- inode->csum_bytes -= num_bytes; +- btrfs_calculate_inode_block_rsv_size(fs_info, inode); +- spin_unlock(&inode->lock); +- + btrfs_inode_rsv_release(inode, true); + if (delalloc_lock) + mutex_unlock(&inode->delalloc_mutex); diff --git a/patches.suse/btrfs-run-btrfs_try_granting_tickets-if-a-priority-ticket-fails.patch b/patches.suse/btrfs-run-btrfs_try_granting_tickets-if-a-priority-ticket-fails.patch new file mode 100644 index 0000000..4d56ddc --- /dev/null +++ b/patches.suse/btrfs-run-btrfs_try_granting_tickets-if-a-priority-ticket-fails.patch @@ -0,0 +1,60 @@ +From: Josef Bacik +Date: Fri, 13 Mar 2020 15:58:09 -0400 +Subject: btrfs: run btrfs_try_granting_tickets if a priority ticket fails +Patch-mainline: Submitted, https://lore.kernel.org/linux-btrfs/20200313195809.141753-1-josef@toxicpanda.com/ +References: bsc#1165949 + +With normal tickets we could have a large reservation at the front of +the list that is unable to be satisfied, but a smaller ticket later on +that can be satisfied. The way we handle this is to run +btrfs_try_granting_tickets() in maybe_fail_all_tickets(). + +However no such protection exists for priority tickets. Fix this by +handling it in handle_reserve_ticket(). If we've returned after +attempting to flush space in a priority related way, we'll still be on +the priority list and need to be removed. + +We rely on the flushing to free up space and wake the ticket, but if +there is not enough space to reclaim _but_ there's enough space in the +space_info to handle subsequent reservations then we would have gotten +an ENOSPC erroneously. + +Address this by catching where we are still on the list, meaning we were +a priority ticket, and removing ourselves and then running +btrfs_try_granting_tickets(). This will handle this particular corner +case. + +Signed-off-by: Josef Bacik +Reviewed-by: Nikolay Borisov +Acked-by: Nikolay Borisov +--- + fs/btrfs/space-info.c | 14 ++++++++++---- + 1 file changed, 10 insertions(+), 4 deletions(-) + +diff --git a/fs/btrfs/space-info.c b/fs/btrfs/space-info.c +index 7c3a13dfe89e..365f2d9da156 100644 +--- a/fs/btrfs/space-info.c ++++ b/fs/btrfs/space-info.c +@@ -1155,11 +1155,17 @@ static int handle_reserve_ticket(struct btrfs_fs_info *fs_info, + ret = ticket->error; + if (ticket->bytes || ticket->error) { + /* +- * Need to delete here for priority tickets. For regular tickets +- * either the async reclaim job deletes the ticket from the list +- * or we delete it ourselves at wait_reserve_ticket(). ++ * We were a priority ticket, so we need to delete ourselves ++ * from the list. Because we could have other priority tickets ++ * behind us that require less space, run ++ * btrfs_try_granting_tickets() to see if their reservations can ++ * now be made. + */ +- list_del_init(&ticket->list); ++ if (!list_empty(&ticket->list)) { ++ list_del_init(&ticket->list); ++ btrfs_try_granting_tickets(fs_info, space_info); ++ } ++ + if (!ret) + ret = -ENOSPC; + } + diff --git a/patches.suse/btrfs-switch-to-on-stack-csum-buffer-in-csum_tree_bl.patch b/patches.suse/btrfs-switch-to-on-stack-csum-buffer-in-csum_tree_bl.patch new file mode 100644 index 0000000..c28cdb8 --- /dev/null +++ b/patches.suse/btrfs-switch-to-on-stack-csum-buffer-in-csum_tree_bl.patch @@ -0,0 +1,73 @@ +From 71a635516ca521931be418827150f782b0a03ae7 Mon Sep 17 00:00:00 2001 +From: David Sterba +Date: Mon, 6 Nov 2017 19:23:00 +0100 +Patch-mainline: v4.16 +Git-commit: 71a635516ca521931be418827150f782b0a03ae7 +References: bsc#1168273 +Subject: [PATCH] btrfs: switch to on-stack csum buffer in csum_tree_block + +The maximum size of a checksum buffer is known, BTRFS_CSUM_SIZE, and we +don't have to allocate it dynamically. This code path is not used at all +as we have only the crc32c and use an on-stack buffer already. + +Signed-off-by: David Sterba +--- + fs/btrfs/disk-io.c | 16 +++------------- + 1 file changed, 3 insertions(+), 13 deletions(-) + +diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c +index cbf37df05a88..5f9430063c50 100644 +--- a/fs/btrfs/disk-io.c ++++ b/fs/btrfs/disk-io.c +@@ -285,7 +285,7 @@ static int csum_tree_block(struct btrfs_fs_info *fs_info, + int verify) + { + u16 csum_size = btrfs_super_csum_size(fs_info->super_copy); +- char *result = NULL; ++ char result[BTRFS_CSUM_SIZE]; + unsigned long len; + unsigned long cur_len; + unsigned long offset = BTRFS_CSUM_SIZE; +@@ -294,7 +294,6 @@ static int csum_tree_block(struct btrfs_fs_info *fs_info, + unsigned long map_len; + int err; + u32 crc = ~(u32)0; +- unsigned long inline_result; + + len = buf->len - offset; + while (len > 0) { +@@ -308,13 +307,7 @@ static int csum_tree_block(struct btrfs_fs_info *fs_info, + len -= cur_len; + offset += cur_len; + } +- if (csum_size > sizeof(inline_result)) { +- result = kzalloc(csum_size, GFP_NOFS); +- if (!result) +- return -ENOMEM; +- } else { +- result = (char *)&inline_result; +- } ++ memset(result, 0, BTRFS_CSUM_SIZE); + + btrfs_csum_final(crc, result); + +@@ -329,15 +322,12 @@ static int csum_tree_block(struct btrfs_fs_info *fs_info, + "%s checksum verify failed on %llu wanted %X found %X level %d", + fs_info->sb->s_id, buf->start, + val, found, btrfs_header_level(buf)); +- if (result != (char *)&inline_result) +- kfree(result); + return -EUCLEAN; + } + } else { + write_extent_buffer(buf, result, 0, csum_size); + } +- if (result != (char *)&inline_result) +- kfree(result); ++ + return 0; + } + +-- +2.26.0 + diff --git a/patches.suse/btrfs-track-dio-bytes-in-flight.patch b/patches.suse/btrfs-track-dio-bytes-in-flight.patch new file mode 100644 index 0000000..babef43 --- /dev/null +++ b/patches.suse/btrfs-track-dio-bytes-in-flight.patch @@ -0,0 +1,162 @@ +From: Josef Bacik +Date: Wed, 10 Apr 2019 15:56:09 -0400 +Subject: btrfs: track DIO bytes in flight +Git-commit: 4297ff84dc24d120753e0425702e8ad9b80ed10f +Patch-mainline: v5.2-rc1 +References: bsc#1165949 + +When diagnosing a slowdown of generic/224 I noticed we were not doing +anything when calling into shrink_delalloc(). This is because all +writes in 224 are O_DIRECT, not delalloc, and thus our delalloc_bytes +counter is 0, which short circuits most of the work inside of +shrink_delalloc(). However O_DIRECT writes still consume metadata +resources and generate ordered extents, which we can still wait on. + +Fix this by tracking outstanding DIO write bytes, and use this as well +as the delalloc bytes counter to decide if we need to lookup and wait on +any ordered extents. If we have more DIO writes than delalloc bytes +we'll go ahead and wait on any ordered extents regardless of our flush +state as flushing delalloc is likely to not gain us anything. + +Signed-off-by: Josef Bacik +[ use dio instead of odirect in identifiers ] +Signed-off-by: David Sterba +Acked-by: Nikolay Borisov +--- + fs/btrfs/ctree.h | 1 + + fs/btrfs/disk-io.c | 15 ++++++++++++++- + fs/btrfs/extent-tree.c | 15 +++++++++++++-- + fs/btrfs/ordered-data.c | 9 ++++++++- + 4 files changed, 36 insertions(+), 4 deletions(-) + +--- a/fs/btrfs/ctree.h ++++ b/fs/btrfs/ctree.h +@@ -1000,6 +1000,7 @@ struct btrfs_fs_info { + /* used to keep from writing metadata until there is a nice batch */ + struct percpu_counter dirty_metadata_bytes; + struct percpu_counter delalloc_bytes; ++ struct percpu_counter dio_bytes; + s32 dirty_metadata_batch; + s32 delalloc_batch; + +--- a/fs/btrfs/disk-io.c ++++ b/fs/btrfs/disk-io.c +@@ -2483,11 +2483,17 @@ int open_ctree(struct super_block *sb, + goto fail; + } + +- ret = percpu_counter_init(&fs_info->dirty_metadata_bytes, 0, GFP_KERNEL); ++ ret = percpu_counter_init(&fs_info->dio_bytes, 0, GFP_KERNEL); + if (ret) { + err = ret; + goto fail_srcu; + } ++ ++ ret = percpu_counter_init(&fs_info->dirty_metadata_bytes, 0, GFP_KERNEL); ++ if (ret) { ++ err = ret; ++ goto fail_dio_bytes; ++ } + fs_info->dirty_metadata_batch = PAGE_SIZE * + (1 + ilog2(nr_cpu_ids)); + +@@ -3176,6 +3182,8 @@ fail_delalloc_bytes: + percpu_counter_destroy(&fs_info->delalloc_bytes); + fail_dirty_metadata_bytes: + percpu_counter_destroy(&fs_info->dirty_metadata_bytes); ++fail_dio_bytes: ++ percpu_counter_destroy(&fs_info->dio_bytes); + fail_srcu: + cleanup_srcu_struct(&fs_info->subvol_srcu); + fail: +@@ -3872,6 +3880,10 @@ void close_ctree(struct btrfs_fs_info *f + percpu_counter_sum(&fs_info->delalloc_bytes)); + } + ++ if (percpu_counter_sum(&fs_info->dio_bytes)) ++ btrfs_info(fs_info, "at unmount dio bytes count %lld", ++ percpu_counter_sum(&fs_info->dio_bytes)); ++ + btrfs_sysfs_remove_mounted(fs_info); + btrfs_sysfs_remove_fsid(fs_info->fs_devices); + +@@ -3903,6 +3915,7 @@ void close_ctree(struct btrfs_fs_info *f + + percpu_counter_destroy(&fs_info->dirty_metadata_bytes); + percpu_counter_destroy(&fs_info->delalloc_bytes); ++ percpu_counter_destroy(&fs_info->dio_bytes); + percpu_counter_destroy(&fs_info->bio_counter); + cleanup_srcu_struct(&fs_info->subvol_srcu); + +--- a/fs/btrfs/extent-tree.c ++++ b/fs/btrfs/extent-tree.c +@@ -4861,6 +4861,7 @@ static void shrink_delalloc(struct btrfs + struct btrfs_space_info *space_info; + struct btrfs_trans_handle *trans; + u64 delalloc_bytes; ++ u64 dio_bytes; + u64 max_reclaim; + u64 items; + long time_left; +@@ -4877,7 +4878,8 @@ static void shrink_delalloc(struct btrfs + + delalloc_bytes = percpu_counter_sum_positive( + &fs_info->delalloc_bytes); +- if (delalloc_bytes == 0) { ++ dio_bytes = percpu_counter_sum_positive(&fs_info->dio_bytes); ++ if (delalloc_bytes == 0 && dio_bytes == 0) { + if (trans) + return; + if (wait_ordered) +@@ -4885,8 +4887,16 @@ static void shrink_delalloc(struct btrfs + return; + } + ++ /* ++ * If we are doing more ordered than delalloc we need to just wait on ++ * ordered extents, otherwise we'll waste time trying to flush delalloc ++ * that likely won't give us the space back we need. ++ */ ++ if (dio_bytes > delalloc_bytes) ++ wait_ordered = true; ++ + loops = 0; +- while (delalloc_bytes && loops < 3) { ++ while ((delalloc_bytes || dio_bytes) && loops < 3) { + max_reclaim = min(delalloc_bytes, to_reclaim); + nr_pages = max_reclaim >> PAGE_SHIFT; + btrfs_writeback_inodes_sb_nr(fs_info, nr_pages, items); +@@ -4929,6 +4939,7 @@ skip_async: + } + delalloc_bytes = percpu_counter_sum_positive( + &fs_info->delalloc_bytes); ++ dio_bytes = percpu_counter_sum_positive(&fs_info->dio_bytes); + } + } + +--- a/fs/btrfs/ordered-data.c ++++ b/fs/btrfs/ordered-data.c +@@ -208,8 +208,11 @@ static int __btrfs_add_ordered_extent(st + if (type != BTRFS_ORDERED_IO_DONE && type != BTRFS_ORDERED_COMPLETE) + set_bit(type, &entry->flags); + +- if (dio) ++ if (dio) { ++ percpu_counter_add_batch(&fs_info->dio_bytes, len, ++ fs_info->delalloc_batch); + set_bit(BTRFS_ORDERED_DIRECT, &entry->flags); ++ } + + /* one ref for the tree */ + refcount_set(&entry->refs, 1); +@@ -612,6 +615,10 @@ void btrfs_remove_ordered_extent(struct + if (root != fs_info->tree_root) + btrfs_delalloc_release_metadata(btrfs_inode, entry->len, false); + ++ if (test_bit(BTRFS_ORDERED_DIRECT, &entry->flags)) ++ percpu_counter_add_batch(&fs_info->dio_bytes, -entry->len, ++ fs_info->delalloc_batch); ++ + tree = &btrfs_inode->ordered_tree; + spin_lock_irq(&tree->lock); + node = &entry->rb_node; diff --git a/patches.suse/btrfs-use-spinlock-to-protect--caching_block_groups-list.patch b/patches.suse/btrfs-use-spinlock-to-protect--caching_block_groups-list.patch index 6e125e3..76e845a 100644 --- a/patches.suse/btrfs-use-spinlock-to-protect--caching_block_groups-list.patch +++ b/patches.suse/btrfs-use-spinlock-to-protect--caching_block_groups-list.patch @@ -15,14 +15,59 @@ post-release. Signed-off-by: Jeff Mahoney --- + fs/btrfs/block-group.c | 6 ++++++ fs/btrfs/ctree.h | 1 + fs/btrfs/disk-io.c | 1 + - fs/btrfs/extent-tree.c | 24 +++++++++++++++++------- - 3 files changed, 19 insertions(+), 7 deletions(-) + fs/btrfs/extent-tree.c | 6 +++++- + 4 files changed, 13 insertions(+), 1 deletion(-) +--- a/fs/btrfs/block-group.c ++++ b/fs/btrfs/block-group.c +@@ -812,8 +812,10 @@ int btrfs_cache_block_group(struct btrfs + } + + down_write(&fs_info->commit_root_sem); ++ spin_lock(&fs_info->caching_block_groups_lock); + refcount_inc(&caching_ctl->count); + list_add_tail(&caching_ctl->list, &fs_info->caching_block_groups); ++ spin_unlock(&fs_info->caching_block_groups_lock); + up_write(&fs_info->commit_root_sem); + + btrfs_get_block_group(cache); +@@ -992,6 +994,7 @@ int btrfs_remove_block_group(struct btrf + btrfs_wait_block_group_cache_done(block_group); + if (block_group->has_caching_ctl) { + down_write(&fs_info->commit_root_sem); ++ spin_lock(&fs_info->caching_block_groups_lock); + if (!caching_ctl) { + struct btrfs_caching_control *ctl; + +@@ -1005,6 +1008,7 @@ int btrfs_remove_block_group(struct btrf + } + if (caching_ctl) + list_del_init(&caching_ctl->list); ++ spin_unlock(&fs_info->caching_block_groups_lock); + up_write(&fs_info->commit_root_sem); + if (caching_ctl) { + /* Once for the caching bgs list and once for us. */ +@@ -3124,12 +3128,14 @@ int btrfs_free_block_groups(struct btrfs + struct rb_node *n; + + down_write(&info->commit_root_sem); ++ spin_lock(&info->caching_block_groups_lock); + while (!list_empty(&info->caching_block_groups)) { + caching_ctl = list_entry(info->caching_block_groups.next, + struct btrfs_caching_control, list); + list_del(&caching_ctl->list); + btrfs_put_caching_control(caching_ctl); + } ++ spin_unlock(&info->caching_block_groups_lock); + up_write(&info->commit_root_sem); + + spin_lock(&info->unused_bgs_lock); --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h -@@ -874,6 +874,7 @@ struct btrfs_fs_info { +@@ -677,6 +677,7 @@ struct btrfs_fs_info { struct list_head trans_list; struct list_head dead_roots; @@ -32,7 +77,7 @@ Signed-off-by: Jeff Mahoney spinlock_t delayed_iput_lock; --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c -@@ -2633,6 +2633,7 @@ int open_ctree(struct super_block *sb, +@@ -2530,6 +2530,7 @@ int open_ctree(struct super_block *sb, spin_lock_init(&fs_info->qgroup_op_lock); spin_lock_init(&fs_info->buffer_lock); spin_lock_init(&fs_info->unused_bgs_lock); @@ -42,22 +87,7 @@ Signed-off-by: Jeff Mahoney mutex_init(&fs_info->delete_unused_bgs_mutex); --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c -@@ -716,10 +716,12 @@ static int cache_block_group(struct btrf - return 0; - } - -- down_write(&fs_info->commit_root_sem); -+ down_read(&fs_info->commit_root_sem); -+ spin_lock(&fs_info->caching_block_groups_lock); - refcount_inc(&caching_ctl->count); - list_add_tail(&caching_ctl->list, &fs_info->caching_block_groups); -- up_write(&fs_info->commit_root_sem); -+ spin_unlock(&fs_info->caching_block_groups_lock); -+ up_read(&fs_info->commit_root_sem); - - btrfs_get_block_group(cache); - -@@ -6618,7 +6620,8 @@ void btrfs_prepare_extent_commit(struct +@@ -2961,7 +2961,8 @@ void btrfs_prepare_extent_commit(struct struct btrfs_caching_control *caching_ctl; struct btrfs_block_group_cache *cache; @@ -67,7 +97,7 @@ Signed-off-by: Jeff Mahoney list_for_each_entry_safe(caching_ctl, next, &fs_info->caching_block_groups, list) { -@@ -6631,7 +6634,10 @@ void btrfs_prepare_extent_commit(struct +@@ -2974,7 +2975,10 @@ void btrfs_prepare_extent_commit(struct cache->last_byte_to_unpin = caching_ctl->progress; } } @@ -78,42 +108,3 @@ Signed-off-by: Jeff Mahoney if (fs_info->pinned_extents == &fs_info->freed_extents[0]) fs_info->pinned_extents = &fs_info->freed_extents[1]; else -@@ -9791,14 +9797,16 @@ int btrfs_free_block_groups(struct btrfs - struct btrfs_caching_control *caching_ctl; - struct rb_node *n; - -- down_write(&info->commit_root_sem); -+ down_read(&info->commit_root_sem); -+ spin_lock(&info->caching_block_groups_lock); - while (!list_empty(&info->caching_block_groups)) { - caching_ctl = list_entry(info->caching_block_groups.next, - struct btrfs_caching_control, list); - list_del(&caching_ctl->list); - put_caching_control(caching_ctl); - } -- up_write(&info->commit_root_sem); -+ spin_unlock(&info->caching_block_groups_lock); -+ up_read(&info->commit_root_sem); - - spin_lock(&info->unused_bgs_lock); - while (!list_empty(&info->unused_bgs)) { -@@ -10453,7 +10461,8 @@ int btrfs_remove_block_group(struct btrf - if (block_group->cached == BTRFS_CACHE_STARTED) - wait_block_group_cache_done(block_group); - if (block_group->has_caching_ctl) { -- down_write(&fs_info->commit_root_sem); -+ down_read(&fs_info->commit_root_sem); -+ spin_lock(&fs_info->caching_block_groups_lock); - if (!caching_ctl) { - struct btrfs_caching_control *ctl; - -@@ -10467,7 +10476,8 @@ int btrfs_remove_block_group(struct btrf - } - if (caching_ctl) - list_del_init(&caching_ctl->list); -- up_write(&fs_info->commit_root_sem); -+ spin_unlock(&fs_info->caching_block_groups_lock); -+ up_read(&fs_info->commit_root_sem); - if (caching_ctl) { - /* Once for the caching bgs list and once for us. */ - put_caching_control(caching_ctl); diff --git a/patches.suse/can-gw-ensure-DLC-boundaries-after-CAN-frame-modific.patch b/patches.suse/can-gw-ensure-DLC-boundaries-after-CAN-frame-modific.patch index e7b6f30..54b23cd 100644 --- a/patches.suse/can-gw-ensure-DLC-boundaries-after-CAN-frame-modific.patch +++ b/patches.suse/can-gw-ensure-DLC-boundaries-after-CAN-frame-modific.patch @@ -4,7 +4,7 @@ Date: Fri, 4 Jan 2019 15:55:26 +0100 Subject: [PATCH] can: gw: ensure DLC boundaries after CAN frame modification Git-commit: 0aaa81377c5a01f686bcdb8c7a6929a7bf330c68 Patch-mainline: v5.0-rc3 -References: bsc#1051510 +References: CVE-2019-3701 bsc#1051510 bsc#1120386 Muyu Yu provided a POC where user root with CAP_NET_ADMIN can create a CAN frame modification rule that makes the data length code a higher value than diff --git a/patches.suse/ceph-canonicalize-server-path-in-place.patch b/patches.suse/ceph-canonicalize-server-path-in-place.patch new file mode 100644 index 0000000..2c98a02 --- /dev/null +++ b/patches.suse/ceph-canonicalize-server-path-in-place.patch @@ -0,0 +1,219 @@ +From: Ilya Dryomov +Date: Mon, 10 Feb 2020 22:51:08 +0100 +Subject: ceph: canonicalize server path in place +Git-commit: b27a939e8376a3f1ed09b9c33ef44d20f18ec3d0 +Patch-mainline: v5.6-rc2 +References: bsc#1168443 + +syzbot reported that 4fbc0c711b24 ("ceph: remove the extra slashes in +the server path") had caused a regression where an allocation could be +done under a spinlock -- compare_mount_options() is called by sget_fc() +with sb_lock held. + +We don't really need the supplied server path, so canonicalize it +in place and compare it directly. To make this work, the leading +slash is kept around and the logic in ceph_real_mount() to skip it +is restored. CEPH_MSG_CLIENT_SESSION now reports the same (i.e. +canonicalized) path, with the leading slash of course. + +Fixes: 4fbc0c711b24 ("ceph: remove the extra slashes in the server path") +Reported-by: syzbot+98704a51af8e3d9425a9@syzkaller.appspotmail.com +Signed-off-by: Ilya Dryomov +Reviewed-by: Jeff Layton +Acked-by: Luis Henriques +--- + fs/ceph/super.c | 118 ++++++++++++-------------------------------------------- + fs/ceph/super.h | 2 + 2 files changed, 28 insertions(+), 92 deletions(-) + +--- a/fs/ceph/super.c ++++ b/fs/ceph/super.c +@@ -124,6 +124,26 @@ static int ceph_sync_fs(struct super_blo + } + + /* ++ * Remove adjacent slashes and then the trailing slash, unless it is ++ * the only remaining character. ++ * ++ * E.g. "//dir1////dir2///" --> "/dir1/dir2", "///" --> "/". ++ */ ++static void canonicalize_path(char *path) ++{ ++ int i, j = 0; ++ ++ for (i = 0; path[i] != '\0'; i++) { ++ if (path[i] != '/' || j < 1 || path[j - 1] != '/') ++ path[j++] = path[i]; ++ } ++ ++ if (j > 1 && path[j - 1] == '/') ++ j--; ++ path[j] = '\0'; ++} ++ ++/* + * mount options + */ + enum { +@@ -389,73 +409,6 @@ static int strcmp_null(const char *s1, c + return strcmp(s1, s2); + } + +-/** +- * path_remove_extra_slash - Remove the extra slashes in the server path +- * @server_path: the server path and could be NULL +- * +- * Return NULL if the path is NULL or only consists of "/", or a string +- * without any extra slashes including the leading slash(es) and the +- * slash(es) at the end of the server path, such as: +- * "//dir1////dir2///" --> "dir1/dir2" +- */ +-static char *path_remove_extra_slash(const char *server_path) +-{ +- const char *path = server_path; +- const char *cur, *end; +- char *buf, *p; +- int len; +- +- /* if the server path is omitted */ +- if (!path) +- return NULL; +- +- /* remove all the leading slashes */ +- while (*path == '/') +- path++; +- +- /* if the server path only consists of slashes */ +- if (*path == '\0') +- return NULL; +- +- len = strlen(path); +- +- buf = kmalloc(len + 1, GFP_KERNEL); +- if (!buf) +- return ERR_PTR(-ENOMEM); +- +- end = path + len; +- p = buf; +- do { +- cur = strchr(path, '/'); +- if (!cur) +- cur = end; +- +- len = cur - path; +- +- /* including one '/' */ +- if (cur != end) +- len += 1; +- +- memcpy(p, path, len); +- p += len; +- +- while (cur <= end && *cur == '/') +- cur++; +- path = cur; +- } while (path < end); +- +- *p = '\0'; +- +- /* +- * remove the last slash if there has and just to make sure that +- * we will get something like "dir1/dir2" +- */ +- if (*(--p) == '/') +- *p = '\0'; +- +- return buf; +-} +- + static int compare_mount_options(struct ceph_mount_options *new_fsopt, + struct ceph_options *new_opt, + struct ceph_fs_client *fsc) +@@ -463,7 +416,6 @@ static int compare_mount_options(struct + struct ceph_mount_options *fsopt1 = new_fsopt; + struct ceph_mount_options *fsopt2 = fsc->mount_options; + int ofs = offsetof(struct ceph_mount_options, snapdir_name); +- char *p1, *p2; + int ret; + + ret = memcmp(fsopt1, fsopt2, ofs); +@@ -473,21 +425,12 @@ static int compare_mount_options(struct + ret = strcmp_null(fsopt1->snapdir_name, fsopt2->snapdir_name); + if (ret) + return ret; ++ + ret = strcmp_null(fsopt1->mds_namespace, fsopt2->mds_namespace); + if (ret) + return ret; + +- p1 = path_remove_extra_slash(fsopt1->server_path); +- if (IS_ERR(p1)) +- return PTR_ERR(p1); +- p2 = path_remove_extra_slash(fsopt2->server_path); +- if (IS_ERR(p2)) { +- kfree(p1); +- return PTR_ERR(p2); +- } +- ret = strcmp_null(p1, p2); +- kfree(p1); +- kfree(p2); ++ ret = strcmp_null(fsopt1->server_path, fsopt2->server_path); + if (ret) + return ret; + +@@ -555,6 +498,8 @@ static int parse_mount_options(struct ce + err = -ENOMEM; + goto out; + } ++ ++ canonicalize_path(fsopt->server_path); + } else { + dev_name_end = dev_name + strlen(dev_name); + } +@@ -981,7 +926,9 @@ static struct dentry *ceph_real_mount(st + mutex_lock(&fsc->client->mount_mutex); + + if (!fsc->sb->s_root) { +- const char *path, *p; ++ const char *path = fsc->mount_options->server_path ? ++ fsc->mount_options->server_path + 1 : ""; ++ + err = __ceph_open_session(fsc->client, started); + if (err < 0) + goto out; +@@ -993,16 +940,6 @@ static struct dentry *ceph_real_mount(st + goto out; + } + +- p = path_remove_extra_slash(fsc->mount_options->server_path); +- if (IS_ERR(p)) { +- err = PTR_ERR(p); +- goto out; +- } +- /* if the server path is omitted or just consists of '/' */ +- if (!p) +- path = ""; +- else +- path = p; + dout("mount opening path '%s'\n", path); + + err = ceph_fs_debugfs_init(fsc); +@@ -1010,7 +947,6 @@ static struct dentry *ceph_real_mount(st + goto out; + + root = open_root_dentry(fsc, path, started); +- kfree(p); + if (IS_ERR(root)) { + err = PTR_ERR(root); + goto out; +--- a/fs/ceph/super.h ++++ b/fs/ceph/super.h +@@ -85,7 +85,7 @@ struct ceph_mount_options { + + char *snapdir_name; /* default ".snap" */ + char *mds_namespace; /* default NULL */ +- char *server_path; /* default "/" */ ++ char *server_path; /* default NULL (means "/") */ + char *fscache_uniq; /* default NULL */ + }; + diff --git a/patches.suse/ceph-remove-the-extra-slashes-in-the-server-path.patch b/patches.suse/ceph-remove-the-extra-slashes-in-the-server-path.patch new file mode 100644 index 0000000..6ae5dd1 --- /dev/null +++ b/patches.suse/ceph-remove-the-extra-slashes-in-the-server-path.patch @@ -0,0 +1,242 @@ +From: Xiubo Li +Date: Fri, 20 Dec 2019 09:34:04 -0500 +Subject: ceph: remove the extra slashes in the server path +Git-commit: 4fbc0c711b2464ee1551850b85002faae0b775d5 +Patch-mainline: v5.6-rc1 +References: bsc#1168443 + +It's possible to pass the mount helper a server path that has more +than one contiguous slash character. For example: + + $ mount -t ceph 192.168.195.165:40176:/// /mnt/cephfs/ + +In the MDS server side the extra slashes of the server path will be +treated as snap dir, and then we can get the following debug logs: + + ceph: mount opening path // + ceph: open_root_inode opening '//' + ceph: fill_trace 0000000059b8a3bc is_dentry 0 is_target 1 + ceph: alloc_inode 00000000dc4ca00b + ceph: get_inode created new inode 00000000dc4ca00b 1.ffffffffffffffff ino 1 + ceph: get_inode on 1=1.ffffffffffffffff got 00000000dc4ca00b + +And then when creating any new file or directory under the mount +point, we can hit the following BUG_ON in ceph_fill_trace(): + + BUG_ON(ceph_snap(dir) != dvino.snap); + +Have the client ignore the extra slashes in the server path when +mounting. This will also canonicalize the path, so that identical mounts +can be consilidated. + +1) "//mydir1///mydir//" +2) "/mydir1/mydir" +3) "/mydir1/mydir/" + +Regardless of the internal treatment of these paths, the kernel still +stores the original string including the leading '/' for presentation +to userland. + +URL: https://tracker.ceph.com/issues/42771 +Signed-off-by: Xiubo Li +Reviewed-by: Jeff Layton +Signed-off-by: Ilya Dryomov +Acked-by: Luis Henriques +--- + fs/ceph/super.c | 120 +++++++++++++++++++++++++++++++++++++++++++++++--------- + 1 file changed, 101 insertions(+), 19 deletions(-) + +--- a/fs/ceph/super.c ++++ b/fs/ceph/super.c +@@ -105,7 +105,6 @@ static int ceph_statfs(struct dentry *de + return 0; + } + +- + static int ceph_sync_fs(struct super_block *sb, int wait) + { + struct ceph_fs_client *fsc = ceph_sb_to_client(sb); +@@ -390,6 +389,73 @@ static int strcmp_null(const char *s1, c + return strcmp(s1, s2); + } + ++/** ++ * path_remove_extra_slash - Remove the extra slashes in the server path ++ * @server_path: the server path and could be NULL ++ * ++ * Return NULL if the path is NULL or only consists of "/", or a string ++ * without any extra slashes including the leading slash(es) and the ++ * slash(es) at the end of the server path, such as: ++ * "//dir1////dir2///" --> "dir1/dir2" ++ */ ++static char *path_remove_extra_slash(const char *server_path) ++{ ++ const char *path = server_path; ++ const char *cur, *end; ++ char *buf, *p; ++ int len; ++ ++ /* if the server path is omitted */ ++ if (!path) ++ return NULL; ++ ++ /* remove all the leading slashes */ ++ while (*path == '/') ++ path++; ++ ++ /* if the server path only consists of slashes */ ++ if (*path == '\0') ++ return NULL; ++ ++ len = strlen(path); ++ ++ buf = kmalloc(len + 1, GFP_KERNEL); ++ if (!buf) ++ return ERR_PTR(-ENOMEM); ++ ++ end = path + len; ++ p = buf; ++ do { ++ cur = strchr(path, '/'); ++ if (!cur) ++ cur = end; ++ ++ len = cur - path; ++ ++ /* including one '/' */ ++ if (cur != end) ++ len += 1; ++ ++ memcpy(p, path, len); ++ p += len; ++ ++ while (cur <= end && *cur == '/') ++ cur++; ++ path = cur; ++ } while (path < end); ++ ++ *p = '\0'; ++ ++ /* ++ * remove the last slash if there has and just to make sure that ++ * we will get something like "dir1/dir2" ++ */ ++ if (*(--p) == '/') ++ *p = '\0'; ++ ++ return buf; ++} ++ + static int compare_mount_options(struct ceph_mount_options *new_fsopt, + struct ceph_options *new_opt, + struct ceph_fs_client *fsc) +@@ -397,6 +463,7 @@ static int compare_mount_options(struct + struct ceph_mount_options *fsopt1 = new_fsopt; + struct ceph_mount_options *fsopt2 = fsc->mount_options; + int ofs = offsetof(struct ceph_mount_options, snapdir_name); ++ char *p1, *p2; + int ret; + + ret = memcmp(fsopt1, fsopt2, ofs); +@@ -409,9 +476,21 @@ static int compare_mount_options(struct + ret = strcmp_null(fsopt1->mds_namespace, fsopt2->mds_namespace); + if (ret) + return ret; +- ret = strcmp_null(fsopt1->server_path, fsopt2->server_path); ++ ++ p1 = path_remove_extra_slash(fsopt1->server_path); ++ if (IS_ERR(p1)) ++ return PTR_ERR(p1); ++ p2 = path_remove_extra_slash(fsopt2->server_path); ++ if (IS_ERR(p2)) { ++ kfree(p1); ++ return PTR_ERR(p2); ++ } ++ ret = strcmp_null(p1, p2); ++ kfree(p1); ++ kfree(p2); + if (ret) + return ret; ++ + ret = strcmp_null(fsopt1->fscache_uniq, fsopt2->fscache_uniq); + if (ret) + return ret; +@@ -467,12 +546,14 @@ static int parse_mount_options(struct ce + */ + dev_name_end = strchr(dev_name, '/'); + if (dev_name_end) { +- if (strlen(dev_name_end) > 1) { +- fsopt->server_path = kstrdup(dev_name_end, GFP_KERNEL); +- if (!fsopt->server_path) { +- err = -ENOMEM; +- goto out; +- } ++ /* ++ * The server_path will include the whole chars from userland ++ * including the leading '/'. ++ */ ++ fsopt->server_path = kstrdup(dev_name_end, GFP_KERNEL); ++ if (!fsopt->server_path) { ++ err = -ENOMEM; ++ goto out; + } + } else { + dev_name_end = dev_name + strlen(dev_name); +@@ -801,7 +882,6 @@ static void destroy_caches(void) + ceph_fscache_unregister(); + } + +- + /* + * ceph_umount_begin - initiate forced umount. Tear down down the + * mount, skipping steps that may hang while waiting for server(s). +@@ -888,9 +968,6 @@ out: + return root; + } + +- +- +- + /* + * mount: join the ceph cluster, and open root directory. + */ +@@ -904,7 +981,7 @@ static struct dentry *ceph_real_mount(st + mutex_lock(&fsc->client->mount_mutex); + + if (!fsc->sb->s_root) { +- const char *path; ++ const char *path, *p; + err = __ceph_open_session(fsc->client, started); + if (err < 0) + goto out; +@@ -916,19 +993,24 @@ static struct dentry *ceph_real_mount(st + goto out; + } + +- if (!fsc->mount_options->server_path) { +- path = ""; +- dout("mount opening path \\t\n"); +- } else { +- path = fsc->mount_options->server_path + 1; +- dout("mount opening path %s\n", path); ++ p = path_remove_extra_slash(fsc->mount_options->server_path); ++ if (IS_ERR(p)) { ++ err = PTR_ERR(p); ++ goto out; + } ++ /* if the server path is omitted or just consists of '/' */ ++ if (!p) ++ path = ""; ++ else ++ path = p; ++ dout("mount opening path '%s'\n", path); + + err = ceph_fs_debugfs_init(fsc); + if (err < 0) + goto out; + + root = open_root_dentry(fsc, path, started); ++ kfree(p); + if (IS_ERR(root)) { + err = PTR_ERR(root); + goto out; diff --git a/patches.suse/cfg80211-check-reg_rule-for-NULL-in-handle_channel_c.patch b/patches.suse/cfg80211-check-reg_rule-for-NULL-in-handle_channel_c.patch new file mode 100644 index 0000000..6333857 --- /dev/null +++ b/patches.suse/cfg80211-check-reg_rule-for-NULL-in-handle_channel_c.patch @@ -0,0 +1,36 @@ +From a7ee7d44b57c9ae174088e53a668852b7f4f452d Mon Sep 17 00:00:00 2001 +From: Johannes Berg +Date: Fri, 21 Feb 2020 10:44:50 +0100 +Subject: [PATCH] cfg80211: check reg_rule for NULL in handle_channel_custom() +Git-commit: a7ee7d44b57c9ae174088e53a668852b7f4f452d +Patch-mainline: v5.6-rc4 +References: bsc#1051510 + +We may end up with a NULL reg_rule after the loop in +handle_channel_custom() if the bandwidth didn't fit, +check if this is the case and bail out if so. + +Signed-off-by: Johannes Berg +Link: https://lore.kernel.org/r/20200221104449.3b558a50201c.I4ad3725c4dacaefd2d18d3cc65ba6d18acd5dbfe@changeid +Acked-by: Takashi Iwai + +--- + net/wireless/reg.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/net/wireless/reg.c b/net/wireless/reg.c +index fff9a74891fc..1a8218f1bbe0 100644 +--- a/net/wireless/reg.c ++++ b/net/wireless/reg.c +@@ -2276,7 +2276,7 @@ static void handle_channel_custom(struct wiphy *wiphy, + break; + } + +- if (IS_ERR(reg_rule)) { ++ if (IS_ERR_OR_NULL(reg_rule)) { + pr_debug("Disabling freq %d MHz as custom regd has no rule that fits it\n", + chan->center_freq); + if (wiphy->regulatory_flags & REGULATORY_WIPHY_SELF_MANAGED) { +-- +2.16.4 + diff --git a/patches.suse/cfg80211-check-wiphy-driver-existence-for-drvinfo-re.patch b/patches.suse/cfg80211-check-wiphy-driver-existence-for-drvinfo-re.patch new file mode 100644 index 0000000..c018bec --- /dev/null +++ b/patches.suse/cfg80211-check-wiphy-driver-existence-for-drvinfo-re.patch @@ -0,0 +1,44 @@ +From bfb7bac3a8f47100ebe7961bd14e924c96e21ca7 Mon Sep 17 00:00:00 2001 +From: Sergey Matyukevich +Date: Mon, 3 Feb 2020 10:56:50 +0000 +Subject: [PATCH] cfg80211: check wiphy driver existence for drvinfo report +Git-commit: bfb7bac3a8f47100ebe7961bd14e924c96e21ca7 +Patch-mainline: v5.6-rc2 +References: bsc#1051510 + +When preparing ethtool drvinfo, check if wiphy driver is defined +before dereferencing it. Driver may not exist, e.g. if wiphy is +attached to a virtual platform device. + +Signed-off-by: Sergey Matyukevich +Link: https://lore.kernel.org/r/20200203105644.28875-1-sergey.matyukevich.os@quantenna.com +Signed-off-by: Johannes Berg +Acked-by: Takashi Iwai + +--- + net/wireless/ethtool.c | 8 ++++++-- + 1 file changed, 6 insertions(+), 2 deletions(-) + +diff --git a/net/wireless/ethtool.c b/net/wireless/ethtool.c +index a9c0f368db5d..24e18405cdb4 100644 +--- a/net/wireless/ethtool.c ++++ b/net/wireless/ethtool.c +@@ -7,9 +7,13 @@ + void cfg80211_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) + { + struct wireless_dev *wdev = dev->ieee80211_ptr; ++ struct device *pdev = wiphy_dev(wdev->wiphy); + +- strlcpy(info->driver, wiphy_dev(wdev->wiphy)->driver->name, +- sizeof(info->driver)); ++ if (pdev->driver) ++ strlcpy(info->driver, pdev->driver->name, ++ sizeof(info->driver)); ++ else ++ strlcpy(info->driver, "N/A", sizeof(info->driver)); + + strlcpy(info->version, init_utsname()->release, sizeof(info->version)); + +-- +2.16.4 + diff --git a/patches.suse/cgroup-memcg-net-do-not-associate-sock-with-unrelated-cgroup.patch b/patches.suse/cgroup-memcg-net-do-not-associate-sock-with-unrelated-cgroup.patch new file mode 100644 index 0000000..5922d2c --- /dev/null +++ b/patches.suse/cgroup-memcg-net-do-not-associate-sock-with-unrelated-cgroup.patch @@ -0,0 +1,127 @@ +From: Shakeel Butt +Date: Mon, 9 Mar 2020 22:16:05 -0700 +Subject: cgroup: memcg: net: do not associate sock with unrelated cgroup +Git-commit: e876ecc67db80dfdb8e237f71e5b43bb88ae549c +Patch-mainline: v5.6-rc6 +References: bsc#1167290 + +We are testing network memory accounting in our setup and noticed +inconsistent network memory usage and often unrelated cgroups network +usage correlates with testing workload. On further inspection, it +seems like mem_cgroup_sk_alloc() and cgroup_sk_alloc() are broken in +irq context specially for cgroup v1. + +mem_cgroup_sk_alloc() and cgroup_sk_alloc() can be called in irq context +and kind of assumes that this can only happen from sk_clone_lock() +and the source sock object has already associated cgroup. However in +cgroup v1, where network memory accounting is opt-in, the source sock +can be unassociated with any cgroup and the new cloned sock can get +associated with unrelated interrupted cgroup. + +Cgroup v2 can also suffer if the source sock object was created by +process in the root cgroup or if sk_alloc() is called in irq context. +The fix is to just do nothing in interrupt. + +WARNING: Please note that about half of the TCP sockets are allocated +from the IRQ context, so, memory used by such sockets will not be +accouted by the memcg. + +The stack trace of mem_cgroup_sk_alloc() from IRQ-context: + +CPU: 70 PID: 12720 Comm: ssh Tainted: 5.6.0-smp-DEV #1 +Hardware name: ... +Call Trace: + + dump_stack+0x57/0x75 + mem_cgroup_sk_alloc+0xe9/0xf0 + sk_clone_lock+0x2a7/0x420 + inet_csk_clone_lock+0x1b/0x110 + tcp_create_openreq_child+0x23/0x3b0 + tcp_v6_syn_recv_sock+0x88/0x730 + tcp_check_req+0x429/0x560 + tcp_v6_rcv+0x72d/0xa40 + ip6_protocol_deliver_rcu+0xc9/0x400 + ip6_input+0x44/0xd0 + ? ip6_protocol_deliver_rcu+0x400/0x400 + ip6_rcv_finish+0x71/0x80 + ipv6_rcv+0x5b/0xe0 + ? ip6_sublist_rcv+0x2e0/0x2e0 + process_backlog+0x108/0x1e0 + net_rx_action+0x26b/0x460 + __do_softirq+0x104/0x2a6 + do_softirq_own_stack+0x2a/0x40 + + do_softirq.part.19+0x40/0x50 + __local_bh_enable_ip+0x51/0x60 + ip6_finish_output2+0x23d/0x520 + ? ip6table_mangle_hook+0x55/0x160 + __ip6_finish_output+0xa1/0x100 + ip6_finish_output+0x30/0xd0 + ip6_output+0x73/0x120 + ? __ip6_finish_output+0x100/0x100 + ip6_xmit+0x2e3/0x600 + ? ipv6_anycast_cleanup+0x50/0x50 + ? inet6_csk_route_socket+0x136/0x1e0 + ? skb_free_head+0x1e/0x30 + inet6_csk_xmit+0x95/0xf0 + __tcp_transmit_skb+0x5b4/0xb20 + __tcp_send_ack.part.60+0xa3/0x110 + tcp_send_ack+0x1d/0x20 + tcp_rcv_state_process+0xe64/0xe80 + ? tcp_v6_connect+0x5d1/0x5f0 + tcp_v6_do_rcv+0x1b1/0x3f0 + ? tcp_v6_do_rcv+0x1b1/0x3f0 + __release_sock+0x7f/0xd0 + release_sock+0x30/0xa0 + __inet_stream_connect+0x1c3/0x3b0 + ? prepare_to_wait+0xb0/0xb0 + inet_stream_connect+0x3b/0x60 + __sys_connect+0x101/0x120 + ? __sys_getsockopt+0x11b/0x140 + __x64_sys_connect+0x1a/0x20 + do_syscall_64+0x51/0x200 + entry_SYSCALL_64_after_hwframe+0x44/0xa9 + +The stack trace of mem_cgroup_sk_alloc() from IRQ-context: +Fixes: 2d7580738345 ("mm: memcontrol: consolidate cgroup socket tracking") +Fixes: d979a39d7242 ("cgroup: duplicate cgroup reference when cloning sockets") +Signed-off-by: Shakeel Butt +Reviewed-by: Roman Gushchin +Signed-off-by: David S. Miller +Acked-by: Michal Koutný +--- + kernel/cgroup/cgroup.c | 4 ++++ + mm/memcontrol.c | 4 ++++ + 2 files changed, 8 insertions(+) + +diff --git a/kernel/cgroup/cgroup.c b/kernel/cgroup/cgroup.c +index 75f687301bbf..6b2fc56b2201 100644 +--- a/kernel/cgroup/cgroup.c ++++ b/kernel/cgroup/cgroup.c +@@ -6258,6 +6258,10 @@ void cgroup_sk_alloc(struct sock_cgroup_data *skcd) + return; + } + ++ /* Don't associate the sock with unrelated interrupted task's cgroup. */ ++ if (in_interrupt()) ++ return; ++ + rcu_read_lock(); + + while (true) { +diff --git a/mm/memcontrol.c b/mm/memcontrol.c +index d09776cd6e10..1cf41ee22258 100644 +--- a/mm/memcontrol.c ++++ b/mm/memcontrol.c +@@ -6696,6 +6696,10 @@ void mem_cgroup_sk_alloc(struct sock *sk) + return; + } + ++ /* Do not associate the sock with unrelated interrupted task's memcg. */ ++ if (in_interrupt()) ++ return; ++ + rcu_read_lock(); + memcg = mem_cgroup_from_task(current); + if (memcg == root_mem_cgroup) + diff --git a/patches.suse/cifs-Add-tracepoints-for-errors-on-flush-or-fsync.patch b/patches.suse/cifs-Add-tracepoints-for-errors-on-flush-or-fsync.patch new file mode 100644 index 0000000..467238d --- /dev/null +++ b/patches.suse/cifs-Add-tracepoints-for-errors-on-flush-or-fsync.patch @@ -0,0 +1,80 @@ +From: Steve French +Date: Wed, 5 Feb 2020 18:22:37 -0600 +Subject: [PATCH] cifs: Add tracepoints for errors on flush or fsync +Git-commit: f2bf09e97b47c7b13e8a918f560f6082e9bc8f8a +References: bsc#1144333 +Patch-mainline: v5.6-rc1 + +Makes it easier to debug errors on writeback that happen later, +and are being returned on flush or fsync + +For example: + writetest-17829 [002] .... 13583.407859: cifs_flush_err: ino=90 rc=-28 + +Signed-off-by: Steve French +Acked-by: Paulo Alcantara +--- + fs/cifs/file.c | 7 +++++-- + fs/cifs/trace.h | 27 +++++++++++++++++++++++++++ + 2 files changed, 32 insertions(+), 2 deletions(-) + +--- a/fs/cifs/file.c ++++ b/fs/cifs/file.c +@@ -2652,8 +2652,10 @@ int cifs_fsync(struct file *file, loff_t + struct inode *inode = file->f_mapping->host; + + rc = filemap_write_and_wait_range(inode->i_mapping, start, end); +- if (rc) ++ if (rc) { ++ trace_cifs_fsync_err(file_inode(file)->i_ino, rc); + return rc; ++ } + inode_lock(inode); + + xid = get_xid(); +@@ -2688,7 +2690,8 @@ int cifs_flush(struct file *file, fl_own + rc = filemap_write_and_wait(inode->i_mapping); + + cifs_dbg(FYI, "Flush inode %p file %p rc %d\n", inode, file, rc); +- ++ if (rc) ++ trace_cifs_flush_err(inode->i_ino, rc); + return rc; + } + +--- a/fs/cifs/trace.h ++++ b/fs/cifs/trace.h +@@ -547,6 +547,33 @@ DEFINE_EVENT(smb3_exit_err_class, smb3_# + + DEFINE_SMB3_EXIT_ERR_EVENT(exit_err); + ++ ++DECLARE_EVENT_CLASS(smb3_sync_err_class, ++ TP_PROTO(unsigned long ino, ++ int rc), ++ TP_ARGS(ino, rc), ++ TP_STRUCT__entry( ++ __field(unsigned long, ino) ++ __field(int, rc) ++ ), ++ TP_fast_assign( ++ __entry->ino = ino; ++ __entry->rc = rc; ++ ), ++ TP_printk("\tino=%lu rc=%d", ++ __entry->ino, __entry->rc) ++) ++ ++#define DEFINE_SMB3_SYNC_ERR_EVENT(name) \ ++DEFINE_EVENT(smb3_sync_err_class, cifs_##name, \ ++ TP_PROTO(unsigned long ino, \ ++ int rc), \ ++ TP_ARGS(ino, rc)) ++ ++DEFINE_SMB3_SYNC_ERR_EVENT(fsync_err); ++DEFINE_SMB3_SYNC_ERR_EVENT(flush_err); ++ ++ + DECLARE_EVENT_CLASS(smb3_enter_exit_class, + TP_PROTO(unsigned int xid, + const char *func_name), diff --git a/patches.suse/cifs-Adjust-indentation-in-smb2_open_file.patch b/patches.suse/cifs-Adjust-indentation-in-smb2_open_file.patch new file mode 100644 index 0000000..49dbe22 --- /dev/null +++ b/patches.suse/cifs-Adjust-indentation-in-smb2_open_file.patch @@ -0,0 +1,48 @@ +From: Nathan Chancellor +Date: Tue, 17 Dec 2019 20:04:51 -0700 +Subject: [PATCH] cifs: Adjust indentation in smb2_open_file +Git-commit: 7935799e041ae10d380d04ea23868240f082bd11 +References: bsc#1144333 +Patch-mainline: v5.5-rc4 + +Clang warns: + +../fs/cifs/smb2file.c:70:3: warning: misleading indentation; statement +is not part of the previous 'if' [-Wmisleading-indentation] + if (oparms->tcon->use_resilient) { + ^ +../fs/cifs/smb2file.c:66:2: note: previous statement is here + if (rc) + ^ +1 warning generated. + +This warning occurs because there is a space after the tab on this line. +Remove it so that the indentation is consistent with the Linux kernel +coding style and clang no longer warns. + +Fixes: 592fafe644bf ("Add resilienthandles mount parm") +Link: https://github.com/ClangBuiltLinux/linux/issues/826 +Signed-off-by: Nathan Chancellor +Signed-off-by: Steve French +Acked-by: Paulo Alcantara +--- + fs/cifs/smb2file.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/fs/cifs/smb2file.c b/fs/cifs/smb2file.c +index 8b0b512c5792..afe1f03aabe3 100644 +--- a/fs/cifs/smb2file.c ++++ b/fs/cifs/smb2file.c +@@ -67,7 +67,7 @@ smb2_open_file(const unsigned int xid, struct cifs_open_parms *oparms, + goto out; + + +- if (oparms->tcon->use_resilient) { ++ if (oparms->tcon->use_resilient) { + /* default timeout is 0, servers pick default (120 seconds) */ + nr_ioctl_req.Timeout = + cpu_to_le32(oparms->tcon->handle_timeout); +-- +2.25.1 + + diff --git a/patches.suse/cifs-Avoid-doing-network-I-O-while-holding-cache-lock.patch b/patches.suse/cifs-Avoid-doing-network-I-O-while-holding-cache-lock.patch new file mode 100644 index 0000000..b856081 --- /dev/null +++ b/patches.suse/cifs-Avoid-doing-network-I-O-while-holding-cache-lock.patch @@ -0,0 +1,1014 @@ +From: "Paulo Alcantara (SUSE)" +Date: Wed, 4 Dec 2019 17:38:03 -0300 +Subject: [PATCH] cifs: Avoid doing network I/O while holding cache lock +Git-commit: 742d8de0186e9f8ec469f8171ea25781a17421bf +References: bsc#1144333 +Patch-mainline: v5.6-rc1 + +When creating or updating a cache entry, we need to get an DFS +referral (get_dfs_referral), so avoid holding any locks during such +network operation. + +To prevent that, do the following: +* change cache hashtable sync method from RCU sync to a read/write + lock. +* use GFP_ATOMIC in memory allocations. + +Signed-off-by: Paulo Alcantara (SUSE) +Signed-off-by: Steve French +Acked-by: Paulo Alcantara +--- + fs/cifs/dfs_cache.c | 545 +++++++++++++++++++++++--------------------- + 1 file changed, 282 insertions(+), 263 deletions(-) + +diff --git a/fs/cifs/dfs_cache.c b/fs/cifs/dfs_cache.c +index 82c5d9a31f9e..76ffe12d64f5 100644 +--- a/fs/cifs/dfs_cache.c ++++ b/fs/cifs/dfs_cache.c +@@ -5,8 +5,6 @@ + * Copyright (c) 2018-2019 Paulo Alcantara + */ + +-#include +-#include + #include + #include + #include +@@ -44,7 +42,6 @@ struct cache_entry { + int numtgts; + struct list_head tlist; + struct cache_dfs_tgt *tgthint; +- struct rcu_head rcu; + }; + + struct vol_info { +@@ -68,10 +65,10 @@ static struct nls_table *cache_nlsc; + /* + * Number of entries in the cache + */ +-static size_t cache_count; ++static atomic_t cache_count; + + static struct hlist_head cache_htable[CACHE_HTABLE_SIZE]; +-static DEFINE_MUTEX(list_lock); ++static DECLARE_RWSEM(htable_rw_lock); + + static LIST_HEAD(vol_list); + static DEFINE_SPINLOCK(vol_list_lock); +@@ -121,38 +118,29 @@ static inline void free_tgts(struct cache_entry *ce) + } + } + +-static void free_cache_entry(struct rcu_head *rcu) +-{ +- struct cache_entry *ce = container_of(rcu, struct cache_entry, rcu); +- +- kmem_cache_free(cache_slab, ce); +-} +- + static inline void flush_cache_ent(struct cache_entry *ce) + { +- if (hlist_unhashed(&ce->hlist)) +- return; +- +- hlist_del_init_rcu(&ce->hlist); ++ hlist_del_init(&ce->hlist); + kfree(ce->path); + free_tgts(ce); +- cache_count--; +- call_rcu(&ce->rcu, free_cache_entry); ++ atomic_dec(&cache_count); ++ kmem_cache_free(cache_slab, ce); + } + + static void flush_cache_ents(void) + { + int i; + +- rcu_read_lock(); + for (i = 0; i < CACHE_HTABLE_SIZE; i++) { + struct hlist_head *l = &cache_htable[i]; ++ struct hlist_node *n; + struct cache_entry *ce; + +- hlist_for_each_entry_rcu(ce, l, hlist) +- flush_cache_ent(ce); ++ hlist_for_each_entry_safe(ce, n, l, hlist) { ++ if (!hlist_unhashed(&ce->hlist)) ++ flush_cache_ent(ce); ++ } + } +- rcu_read_unlock(); + } + + /* +@@ -160,36 +148,39 @@ static void flush_cache_ents(void) + */ + static int dfscache_proc_show(struct seq_file *m, void *v) + { +- int bucket; ++ int i; + struct cache_entry *ce; + struct cache_dfs_tgt *t; + + seq_puts(m, "DFS cache\n---------\n"); + +- mutex_lock(&list_lock); ++ down_read(&htable_rw_lock); ++ for (i = 0; i < CACHE_HTABLE_SIZE; i++) { ++ struct hlist_head *l = &cache_htable[i]; + +- rcu_read_lock(); +- hash_for_each_rcu(cache_htable, bucket, ce, hlist) { +- seq_printf(m, +- "cache entry: path=%s,type=%s,ttl=%d,etime=%ld," +- "interlink=%s,path_consumed=%d,expired=%s\n", +- ce->path, +- ce->srvtype == DFS_TYPE_ROOT ? "root" : "link", +- ce->ttl, ce->etime.tv_nsec, +- IS_INTERLINK_SET(ce->flags) ? "yes" : "no", +- ce->path_consumed, +- cache_entry_expired(ce) ? "yes" : "no"); ++ hlist_for_each_entry(ce, l, hlist) { ++ if (hlist_unhashed(&ce->hlist)) ++ continue; + +- list_for_each_entry(t, &ce->tlist, list) { +- seq_printf(m, " %s%s\n", +- t->name, +- ce->tgthint == t ? " (target hint)" : ""); ++ seq_printf(m, ++ "cache entry: path=%s,type=%s,ttl=%d,etime=%ld," ++ "interlink=%s,path_consumed=%d,expired=%s\n", ++ ce->path, ++ ce->srvtype == DFS_TYPE_ROOT ? "root" : "link", ++ ce->ttl, ce->etime.tv_nsec, ++ IS_INTERLINK_SET(ce->flags) ? "yes" : "no", ++ ce->path_consumed, ++ cache_entry_expired(ce) ? "yes" : "no"); ++ ++ list_for_each_entry(t, &ce->tlist, list) { ++ seq_printf(m, " %s%s\n", ++ t->name, ++ ce->tgthint == t ? " (target hint)" : ""); ++ } + } +- + } +- rcu_read_unlock(); ++ up_read(&htable_rw_lock); + +- mutex_unlock(&list_lock); + return 0; + } + +@@ -207,9 +198,10 @@ static ssize_t dfscache_proc_write(struct file *file, const char __user *buffer, + return -EINVAL; + + cifs_dbg(FYI, "clearing dfs cache"); +- mutex_lock(&list_lock); ++ ++ down_write(&htable_rw_lock); + flush_cache_ents(); +- mutex_unlock(&list_lock); ++ up_write(&htable_rw_lock); + + return count; + } +@@ -305,6 +297,7 @@ int dfs_cache_init(void) + for (i = 0; i < CACHE_HTABLE_SIZE; i++) + INIT_HLIST_HEAD(&cache_htable[i]); + ++ atomic_set(&cache_count, 0); + cache_nlsc = load_nls_default(); + + cifs_dbg(FYI, "%s: initialized DFS referral cache\n", __func__); +@@ -356,14 +349,14 @@ static inline struct timespec64 get_expire_time(int ttl) + } + + /* Allocate a new DFS target */ +-static inline struct cache_dfs_tgt *alloc_tgt(const char *name) ++static struct cache_dfs_tgt *alloc_target(const char *name) + { + struct cache_dfs_tgt *t; + +- t = kmalloc(sizeof(*t), GFP_KERNEL); ++ t = kmalloc(sizeof(*t), GFP_ATOMIC); + if (!t) + return ERR_PTR(-ENOMEM); +- t->name = kstrndup(name, strlen(name), GFP_KERNEL); ++ t->name = kstrndup(name, strlen(name), GFP_ATOMIC); + if (!t->name) { + kfree(t); + return ERR_PTR(-ENOMEM); +@@ -390,7 +383,7 @@ static int copy_ref_data(const struct dfs_info3_param *refs, int numrefs, + for (i = 0; i < numrefs; i++) { + struct cache_dfs_tgt *t; + +- t = alloc_tgt(refs[i].node_name); ++ t = alloc_target(refs[i].node_name); + if (IS_ERR(t)) { + free_tgts(ce); + return PTR_ERR(t); +@@ -439,41 +432,44 @@ static struct cache_entry *alloc_cache_entry(const char *path, + return ce; + } + ++/* Must be called with htable_rw_lock held */ + static void remove_oldest_entry(void) + { +- int bucket; ++ int i; + struct cache_entry *ce; + struct cache_entry *to_del = NULL; + +- rcu_read_lock(); +- hash_for_each_rcu(cache_htable, bucket, ce, hlist) { +- if (!to_del || timespec64_compare(&ce->etime, +- &to_del->etime) < 0) +- to_del = ce; ++ for (i = 0; i < CACHE_HTABLE_SIZE; i++) { ++ struct hlist_head *l = &cache_htable[i]; ++ ++ hlist_for_each_entry(ce, l, hlist) { ++ if (hlist_unhashed(&ce->hlist)) ++ continue; ++ if (!to_del || timespec64_compare(&ce->etime, ++ &to_del->etime) < 0) ++ to_del = ce; ++ } + } ++ + if (!to_del) { + cifs_dbg(FYI, "%s: no entry to remove", __func__); +- goto out; ++ return; + } ++ + cifs_dbg(FYI, "%s: removing entry", __func__); + dump_ce(to_del); + flush_cache_ent(to_del); +-out: +- rcu_read_unlock(); + } + + /* Add a new DFS cache entry */ +-static inline struct cache_entry * +-add_cache_entry(unsigned int hash, const char *path, +- const struct dfs_info3_param *refs, int numrefs) ++static int add_cache_entry(const char *path, unsigned int hash, ++ struct dfs_info3_param *refs, int numrefs) + { + struct cache_entry *ce; + + ce = alloc_cache_entry(path, refs, numrefs); + if (IS_ERR(ce)) +- return ce; +- +- hlist_add_head_rcu(&ce->hlist, &cache_htable[hash]); ++ return PTR_ERR(ce); + + spin_lock(&cache_ttl_lock); + if (!cache_ttl) { +@@ -485,13 +481,20 @@ add_cache_entry(unsigned int hash, const char *path, + } + spin_unlock(&cache_ttl_lock); + +- return ce; ++ down_write(&htable_rw_lock); ++ hlist_add_head(&ce->hlist, &cache_htable[hash]); ++ dump_ce(ce); ++ up_write(&htable_rw_lock); ++ ++ return 0; + } + + /* + * Find a DFS cache entry in hash table and optionally check prefix path against + * @path. + * Use whole path components in the match. ++ * Must be called with htable_rw_lock held. ++ * + * Return ERR_PTR(-ENOENT) if the entry is not found. + */ + static struct cache_entry *lookup_cache_entry(const char *path, +@@ -503,15 +506,13 @@ static struct cache_entry *lookup_cache_entry(const char *path, + + h = cache_entry_hash(path, strlen(path)); + +- rcu_read_lock(); +- hlist_for_each_entry_rcu(ce, &cache_htable[h], hlist) { ++ hlist_for_each_entry(ce, &cache_htable[h], hlist) { + if (!strcasecmp(path, ce->path)) { + found = true; + dump_ce(ce); + break; + } + } +- rcu_read_unlock(); + + if (!found) + ce = ERR_PTR(-ENOENT); +@@ -521,12 +522,6 @@ static struct cache_entry *lookup_cache_entry(const char *path, + return ce; + } + +-static inline void destroy_slab_cache(void) +-{ +- rcu_barrier(); +- kmem_cache_destroy(cache_slab); +-} +- + static void __vol_release(struct vol_info *vi) + { + kfree(vi->fullpath); +@@ -564,77 +559,74 @@ void dfs_cache_destroy(void) + unload_nls(cache_nlsc); + free_vol_list(); + flush_cache_ents(); +- destroy_slab_cache(); ++ kmem_cache_destroy(cache_slab); + destroy_workqueue(dfscache_wq); + + cifs_dbg(FYI, "%s: destroyed DFS referral cache\n", __func__); + } + +-static inline struct cache_entry * +-__update_cache_entry(const char *path, const struct dfs_info3_param *refs, +- int numrefs) ++/* Must be called with htable_rw_lock held */ ++static int __update_cache_entry(const char *path, ++ const struct dfs_info3_param *refs, ++ int numrefs) + { + int rc; +- unsigned int h; + struct cache_entry *ce; + char *s, *th = NULL; + +- ce = lookup_cache_entry(path, &h); ++ ce = lookup_cache_entry(path, NULL); + if (IS_ERR(ce)) +- return ce; ++ return PTR_ERR(ce); + + if (ce->tgthint) { + s = ce->tgthint->name; +- th = kstrndup(s, strlen(s), GFP_KERNEL); ++ th = kstrndup(s, strlen(s), GFP_ATOMIC); + if (!th) +- return ERR_PTR(-ENOMEM); ++ return -ENOMEM; + } + + free_tgts(ce); + ce->numtgts = 0; + + rc = copy_ref_data(refs, numrefs, ce, th); ++ + kfree(th); + +- if (rc) +- ce = ERR_PTR(rc); +- +- return ce; ++ return 0; + } + +-/* Update an expired cache entry by getting a new DFS referral from server */ +-static struct cache_entry * +-update_cache_entry(const unsigned int xid, struct cifs_ses *ses, +- const struct nls_table *nls_codepage, int remap, +- const char *path, struct cache_entry *ce) ++static int get_dfs_referral(const unsigned int xid, struct cifs_ses *ses, ++ const struct nls_table *nls_codepage, int remap, ++ const char *path, struct dfs_info3_param **refs, ++ int *numrefs) + { +- int rc; +- struct dfs_info3_param *refs = NULL; +- int numrefs = 0; ++ cifs_dbg(FYI, "%s: get an DFS referral for %s\n", __func__, path); + +- cifs_dbg(FYI, "%s: update expired cache entry\n", __func__); +- /* +- * Check if caller provided enough parameters to update an expired +- * entry. +- */ + if (!ses || !ses->server || !ses->server->ops->get_dfs_refer) +- return ERR_PTR(-ETIME); ++ return -EOPNOTSUPP; + if (unlikely(!nls_codepage)) +- return ERR_PTR(-ETIME); ++ return -EINVAL; + +- cifs_dbg(FYI, "%s: DFS referral request for %s\n", __func__, path); ++ *refs = NULL; ++ *numrefs = 0; + +- rc = ses->server->ops->get_dfs_refer(xid, ses, path, &refs, &numrefs, +- nls_codepage, remap); +- if (rc) +- ce = ERR_PTR(rc); +- else +- ce = __update_cache_entry(path, refs, numrefs); ++ return ses->server->ops->get_dfs_refer(xid, ses, path, refs, numrefs, ++ nls_codepage, remap); ++} + +- dump_refs(refs, numrefs); +- free_dfs_info_array(refs, numrefs); ++/* Update an expired cache entry by getting a new DFS referral from server */ ++static int update_cache_entry(const char *path, ++ const struct dfs_info3_param *refs, ++ int numrefs) ++{ + +- return ce; ++ int rc; ++ ++ down_write(&htable_rw_lock); ++ rc = __update_cache_entry(path, refs, numrefs); ++ up_write(&htable_rw_lock); ++ ++ return rc; + } + + /* +@@ -646,95 +638,86 @@ update_cache_entry(const unsigned int xid, struct cifs_ses *ses, + * For interlinks, __cifs_dfs_mount() and expand_dfs_referral() are supposed to + * handle them properly. + */ +-static struct cache_entry * +-do_dfs_cache_find(const unsigned int xid, struct cifs_ses *ses, +- const struct nls_table *nls_codepage, int remap, +- const char *path, bool noreq) ++static int __dfs_cache_find(const unsigned int xid, struct cifs_ses *ses, ++ const struct nls_table *nls_codepage, int remap, ++ const char *path, bool noreq) + { + int rc; +- unsigned int h; ++ unsigned int hash; + struct cache_entry *ce; +- struct dfs_info3_param *nrefs; +- int numnrefs; ++ struct dfs_info3_param *refs = NULL; ++ int numrefs = 0; ++ bool newent = false; + + cifs_dbg(FYI, "%s: search path: %s\n", __func__, path); + +- ce = lookup_cache_entry(path, &h); +- if (IS_ERR(ce)) { +- cifs_dbg(FYI, "%s: cache miss\n", __func__); +- /* +- * If @noreq is set, no requests will be sent to the server for +- * either updating or getting a new DFS referral. +- */ +- if (noreq) +- return ce; +- /* +- * No cache entry was found, so check for valid parameters that +- * will be required to get a new DFS referral and then create a +- * new cache entry. +- */ +- if (!ses || !ses->server || !ses->server->ops->get_dfs_refer) { +- ce = ERR_PTR(-EOPNOTSUPP); +- return ce; +- } +- if (unlikely(!nls_codepage)) { +- ce = ERR_PTR(-EINVAL); +- return ce; +- } ++ down_read(&htable_rw_lock); + +- nrefs = NULL; +- numnrefs = 0; ++ ce = lookup_cache_entry(path, &hash); + +- cifs_dbg(FYI, "%s: DFS referral request for %s\n", __func__, +- path); ++ /* ++ * If @noreq is set, no requests will be sent to the server. Just return ++ * the cache entry. ++ */ ++ if (noreq) { ++ up_read(&htable_rw_lock); ++ return IS_ERR(ce) ? PTR_ERR(ce) : 0; ++ } + +- rc = ses->server->ops->get_dfs_refer(xid, ses, path, &nrefs, +- &numnrefs, nls_codepage, +- remap); +- if (rc) { +- ce = ERR_PTR(rc); +- return ce; ++ if (!IS_ERR(ce)) { ++ if (!cache_entry_expired(ce)) { ++ dump_ce(ce); ++ up_read(&htable_rw_lock); ++ return 0; + } ++ } else { ++ newent = true; ++ } + +- dump_refs(nrefs, numnrefs); ++ up_read(&htable_rw_lock); + +- cifs_dbg(FYI, "%s: new cache entry\n", __func__); ++ /* ++ * No entry was found. ++ * ++ * Request a new DFS referral in order to create a new cache entry, or ++ * updating an existing one. ++ */ ++ rc = get_dfs_referral(xid, ses, nls_codepage, remap, path, ++ &refs, &numrefs); ++ if (rc) ++ return rc; + +- if (cache_count >= CACHE_MAX_ENTRIES) { +- cifs_dbg(FYI, "%s: reached max cache size (%d)", +- __func__, CACHE_MAX_ENTRIES); +- remove_oldest_entry(); +- } +- ce = add_cache_entry(h, path, nrefs, numnrefs); +- free_dfs_info_array(nrefs, numnrefs); ++ dump_refs(refs, numrefs); + +- if (IS_ERR(ce)) +- return ce; +- +- cache_count++; ++ if (!newent) { ++ rc = update_cache_entry(path, refs, numrefs); ++ goto out_free_refs; + } + +- dump_ce(ce); ++ if (atomic_read(&cache_count) >= CACHE_MAX_ENTRIES) { ++ cifs_dbg(FYI, "%s: reached max cache size (%d)", __func__, ++ CACHE_MAX_ENTRIES); ++ down_write(&htable_rw_lock); ++ remove_oldest_entry(); ++ up_write(&htable_rw_lock); ++ } + +- /* Just return the found cache entry in case @noreq is set */ +- if (noreq) +- return ce; ++ rc = add_cache_entry(path, hash, refs, numrefs); ++ if (!rc) ++ atomic_inc(&cache_count); + +- if (cache_entry_expired(ce)) { +- cifs_dbg(FYI, "%s: expired cache entry\n", __func__); +- ce = update_cache_entry(xid, ses, nls_codepage, remap, path, +- ce); +- if (IS_ERR(ce)) { +- cifs_dbg(FYI, "%s: failed to update expired entry\n", +- __func__); +- } +- } +- return ce; ++out_free_refs: ++ free_dfs_info_array(refs, numrefs); ++ return rc; + } + +-/* Set up a new DFS referral from a given cache entry */ +-static int setup_ref(const char *path, const struct cache_entry *ce, +- struct dfs_info3_param *ref, const char *tgt) ++/* ++ * Set up a DFS referral from a given cache entry. ++ * ++ * Must be called with htable_rw_lock held. ++ */ ++static int setup_referral(const char *path, struct cache_entry *ce, ++ struct dfs_info3_param *ref, const char *target) + { + int rc; + +@@ -742,18 +725,17 @@ static int setup_ref(const char *path, const struct cache_entry *ce, + + memset(ref, 0, sizeof(*ref)); + +- ref->path_name = kstrndup(path, strlen(path), GFP_KERNEL); ++ ref->path_name = kstrndup(path, strlen(path), GFP_ATOMIC); + if (!ref->path_name) + return -ENOMEM; + +- ref->path_consumed = ce->path_consumed; +- +- ref->node_name = kstrndup(tgt, strlen(tgt), GFP_KERNEL); ++ ref->node_name = kstrndup(target, strlen(target), GFP_ATOMIC); + if (!ref->node_name) { + rc = -ENOMEM; + goto err_free_path; + } + ++ ref->path_consumed = ce->path_consumed; + ref->ttl = ce->ttl; + ref->server_type = ce->srvtype; + ref->ref_flag = ce->flags; +@@ -767,8 +749,7 @@ static int setup_ref(const char *path, const struct cache_entry *ce, + } + + /* Return target list of a DFS cache entry */ +-static int get_tgt_list(const struct cache_entry *ce, +- struct dfs_cache_tgt_list *tl) ++static int get_targets(struct cache_entry *ce, struct dfs_cache_tgt_list *tl) + { + int rc; + struct list_head *head = &tl->tl_list; +@@ -779,14 +760,13 @@ static int get_tgt_list(const struct cache_entry *ce, + INIT_LIST_HEAD(head); + + list_for_each_entry(t, &ce->tlist, list) { +- it = kzalloc(sizeof(*it), GFP_KERNEL); ++ it = kzalloc(sizeof(*it), GFP_ATOMIC); + if (!it) { + rc = -ENOMEM; + goto err_free_it; + } + +- it->it_name = kstrndup(t->name, strlen(t->name), +- GFP_KERNEL); ++ it->it_name = kstrndup(t->name, strlen(t->name), GFP_ATOMIC); + if (!it->it_name) { + kfree(it); + rc = -ENOMEM; +@@ -798,6 +778,7 @@ static int get_tgt_list(const struct cache_entry *ce, + else + list_add_tail(&it->it_list, head); + } ++ + tl->tl_numtgts = ce->numtgts; + + return 0; +@@ -845,19 +826,29 @@ int dfs_cache_find(const unsigned int xid, struct cifs_ses *ses, + if (rc) + return rc; + +- mutex_lock(&list_lock); +- ce = do_dfs_cache_find(xid, ses, nls_codepage, remap, npath, false); +- if (!IS_ERR(ce)) { +- if (ref) +- rc = setup_ref(path, ce, ref, get_tgt_name(ce)); +- else +- rc = 0; +- if (!rc && tgt_list) +- rc = get_tgt_list(ce, tgt_list); +- } else { ++ rc = __dfs_cache_find(xid, ses, nls_codepage, remap, npath, false); ++ if (rc) ++ goto out_free_path; ++ ++ down_read(&htable_rw_lock); ++ ++ ce = lookup_cache_entry(npath, NULL); ++ if (IS_ERR(ce)) { ++ up_read(&htable_rw_lock); + rc = PTR_ERR(ce); ++ goto out_free_path; + } +- mutex_unlock(&list_lock); ++ ++ if (ref) ++ rc = setup_referral(path, ce, ref, get_tgt_name(ce)); ++ else ++ rc = 0; ++ if (!rc && tgt_list) ++ rc = get_targets(ce, tgt_list); ++ ++ up_read(&htable_rw_lock); ++ ++out_free_path: + free_normalized_path(path, npath); + return rc; + } +@@ -889,22 +880,27 @@ int dfs_cache_noreq_find(const char *path, struct dfs_info3_param *ref, + if (rc) + return rc; + +- mutex_lock(&list_lock); +- ce = do_dfs_cache_find(0, NULL, NULL, 0, npath, true); ++ cifs_dbg(FYI, "%s: path: %s\n", __func__, npath); ++ ++ down_read(&htable_rw_lock); ++ ++ ce = lookup_cache_entry(npath, NULL); + if (IS_ERR(ce)) { + rc = PTR_ERR(ce); +- goto out; ++ goto out_unlock; + } + + if (ref) +- rc = setup_ref(path, ce, ref, get_tgt_name(ce)); ++ rc = setup_referral(path, ce, ref, get_tgt_name(ce)); + else + rc = 0; + if (!rc && tgt_list) +- rc = get_tgt_list(ce, tgt_list); +-out: +- mutex_unlock(&list_lock); ++ rc = get_targets(ce, tgt_list); ++ ++out_unlock: ++ up_read(&htable_rw_lock); + free_normalized_path(path, npath); ++ + return rc; + } + +@@ -940,21 +936,24 @@ int dfs_cache_update_tgthint(const unsigned int xid, struct cifs_ses *ses, + if (rc) + return rc; + +- cifs_dbg(FYI, "%s: path: %s\n", __func__, npath); ++ cifs_dbg(FYI, "%s: update target hint - path: %s\n", __func__, npath); + +- mutex_lock(&list_lock); +- ce = do_dfs_cache_find(xid, ses, nls_codepage, remap, npath, false); ++ rc = __dfs_cache_find(xid, ses, nls_codepage, remap, npath, false); ++ if (rc) ++ goto out_free_path; ++ ++ down_write(&htable_rw_lock); ++ ++ ce = lookup_cache_entry(npath, NULL); + if (IS_ERR(ce)) { + rc = PTR_ERR(ce); +- goto out; ++ goto out_unlock; + } + +- rc = 0; +- + t = ce->tgthint; + + if (likely(!strcasecmp(it->it_name, t->name))) +- goto out; ++ goto out_unlock; + + list_for_each_entry(t, &ce->tlist, list) { + if (!strcasecmp(t->name, it->it_name)) { +@@ -965,9 +964,11 @@ int dfs_cache_update_tgthint(const unsigned int xid, struct cifs_ses *ses, + } + } + +-out: +- mutex_unlock(&list_lock); ++out_unlock: ++ up_write(&htable_rw_lock); ++out_free_path: + free_normalized_path(path, npath); ++ + return rc; + } + +@@ -1002,20 +1003,19 @@ int dfs_cache_noreq_update_tgthint(const char *path, + + cifs_dbg(FYI, "%s: path: %s\n", __func__, npath); + +- mutex_lock(&list_lock); ++ down_write(&htable_rw_lock); + +- ce = do_dfs_cache_find(0, NULL, NULL, 0, npath, true); ++ ce = lookup_cache_entry(npath, NULL); + if (IS_ERR(ce)) { + rc = PTR_ERR(ce); +- goto out; ++ goto out_unlock; + } + + rc = 0; +- + t = ce->tgthint; + + if (unlikely(!strcasecmp(it->it_name, t->name))) +- goto out; ++ goto out_unlock; + + list_for_each_entry(t, &ce->tlist, list) { + if (!strcasecmp(t->name, it->it_name)) { +@@ -1026,9 +1026,10 @@ int dfs_cache_noreq_update_tgthint(const char *path, + } + } + +-out: +- mutex_unlock(&list_lock); ++out_unlock: ++ up_write(&htable_rw_lock); + free_normalized_path(path, npath); ++ + return rc; + } + +@@ -1049,7 +1050,6 @@ int dfs_cache_get_tgt_referral(const char *path, + int rc; + char *npath; + struct cache_entry *ce; +- unsigned int h; + + if (!it || !ref) + return -EINVAL; +@@ -1060,21 +1060,22 @@ int dfs_cache_get_tgt_referral(const char *path, + + cifs_dbg(FYI, "%s: path: %s\n", __func__, npath); + +- mutex_lock(&list_lock); ++ down_read(&htable_rw_lock); + +- ce = lookup_cache_entry(npath, &h); ++ ce = lookup_cache_entry(npath, NULL); + if (IS_ERR(ce)) { + rc = PTR_ERR(ce); +- goto out; ++ goto out_unlock; + } + + cifs_dbg(FYI, "%s: target name: %s\n", __func__, it->it_name); + +- rc = setup_ref(path, ce, ref, it->it_name); ++ rc = setup_referral(path, ce, ref, it->it_name); + +-out: +- mutex_unlock(&list_lock); ++out_unlock: ++ up_read(&htable_rw_lock); + free_normalized_path(path, npath); ++ + return rc; + } + +@@ -1343,6 +1344,7 @@ static struct cifs_ses *find_root_ses(struct vol_info *vi, + { + char *rpath; + int rc; ++ struct cache_entry *ce; + struct dfs_info3_param ref = {0}; + char *mdata = NULL, *devname = NULL; + struct TCP_Server_Info *server; +@@ -1353,15 +1355,26 @@ static struct cifs_ses *find_root_ses(struct vol_info *vi, + if (IS_ERR(rpath)) + return ERR_CAST(rpath); + +- memset(&vol, 0, sizeof(vol)); ++ down_read(&htable_rw_lock); + +- rc = dfs_cache_noreq_find(rpath, &ref, NULL); ++ ce = lookup_cache_entry(rpath, NULL); ++ if (IS_ERR(ce)) { ++ up_read(&htable_rw_lock); ++ ses = ERR_CAST(ce); ++ goto out; ++ } ++ ++ rc = setup_referral(path, ce, &ref, get_tgt_name(ce)); + if (rc) { ++ up_read(&htable_rw_lock); + ses = ERR_PTR(rc); + goto out; + } + +- mdata = cifs_compose_mount_options(vi->mntdata, rpath, &ref, &devname); ++ up_read(&htable_rw_lock); ++ ++ mdata = cifs_compose_mount_options(vi->mntdata, rpath, &ref, ++ &devname); + free_dfs_info_param(&ref); + + if (IS_ERR(mdata)) { +@@ -1395,16 +1408,15 @@ static struct cifs_ses *find_root_ses(struct vol_info *vi, + } + + /* Refresh DFS cache entry from a given tcon */ +-static void refresh_tcon(struct vol_info *vi, struct cifs_tcon *tcon) ++static int refresh_tcon(struct vol_info *vi, struct cifs_tcon *tcon) + { + int rc = 0; + unsigned int xid; + char *path, *npath; +- unsigned int h; + struct cache_entry *ce; +- struct dfs_info3_param *refs = NULL; +- int numrefs = 0; + struct cifs_ses *root_ses = NULL, *ses; ++ struct dfs_info3_param *refs = NULL; ++ int numrefs = 0; + + xid = get_xid(); + +@@ -1412,19 +1424,23 @@ static void refresh_tcon(struct vol_info *vi, struct cifs_tcon *tcon) + + rc = get_normalized_path(path, &npath); + if (rc) +- goto out; ++ goto out_free_xid; + +- mutex_lock(&list_lock); +- ce = lookup_cache_entry(npath, &h); +- mutex_unlock(&list_lock); ++ down_read(&htable_rw_lock); + ++ ce = lookup_cache_entry(npath, NULL); + if (IS_ERR(ce)) { + rc = PTR_ERR(ce); +- goto out; ++ up_read(&htable_rw_lock); ++ goto out_free_path; + } + +- if (!cache_entry_expired(ce)) +- goto out; ++ if (!cache_entry_expired(ce)) { ++ up_read(&htable_rw_lock); ++ goto out_free_path; ++ } ++ ++ up_read(&htable_rw_lock); + + /* If it's a DFS Link, then use root SMB session for refreshing it */ + if (is_dfs_link(npath)) { +@@ -1432,35 +1448,29 @@ static void refresh_tcon(struct vol_info *vi, struct cifs_tcon *tcon) + if (IS_ERR(ses)) { + rc = PTR_ERR(ses); + root_ses = NULL; +- goto out; ++ goto out_free_path; + } + } else { + ses = tcon->ses; + } + +- if (unlikely(!ses->server->ops->get_dfs_refer)) { +- rc = -EOPNOTSUPP; +- } else { +- rc = ses->server->ops->get_dfs_refer(xid, ses, path, &refs, +- &numrefs, cache_nlsc, +- tcon->remap); +- if (!rc) { +- mutex_lock(&list_lock); +- ce = __update_cache_entry(npath, refs, numrefs); +- mutex_unlock(&list_lock); +- dump_refs(refs, numrefs); +- free_dfs_info_array(refs, numrefs); +- if (IS_ERR(ce)) +- rc = PTR_ERR(ce); +- } ++ rc = get_dfs_referral(xid, ses, cache_nlsc, tcon->remap, npath, &refs, ++ &numrefs); ++ if (!rc) { ++ dump_refs(refs, numrefs); ++ rc = update_cache_entry(npath, refs, numrefs); ++ free_dfs_info_array(refs, numrefs); + } + +-out: + if (root_ses) + cifs_put_smb_ses(root_ses); + ++out_free_path: ++ free_normalized_path(path, npath); ++ ++out_free_xid: + free_xid(xid); +- free_normalized_path(path, npath); ++ return rc; + } + + /* +@@ -1474,6 +1484,7 @@ static void refresh_cache_worker(struct work_struct *work) + LIST_HEAD(vols); + LIST_HEAD(tcons); + struct cifs_tcon *tcon, *ntcon; ++ int rc; + + /* + * Find SMB volumes that are eligible (server->tcpStatus == CifsGood) +@@ -1501,8 +1512,16 @@ static void refresh_cache_worker(struct work_struct *work) + goto next_vol; + + get_tcons(server, &tcons); ++ rc = 0; ++ + list_for_each_entry_safe(tcon, ntcon, &tcons, ulist) { +- refresh_tcon(vi, tcon); ++ /* ++ * Skip tcp server if any of its tcons failed to refresh ++ * (possibily due to reconnects). ++ */ ++ if (!rc) ++ rc = refresh_tcon(vi, tcon); ++ + list_del_init(&tcon->ulist); + cifs_put_tcon(tcon); + } +-- +2.25.1 + + diff --git a/patches.suse/cifs-Clean-up-DFS-referral-cache.patch b/patches.suse/cifs-Clean-up-DFS-referral-cache.patch new file mode 100644 index 0000000..59b9fd9 --- /dev/null +++ b/patches.suse/cifs-Clean-up-DFS-referral-cache.patch @@ -0,0 +1,1249 @@ +From: "Paulo Alcantara (SUSE)" +Date: Wed, 4 Dec 2019 17:37:58 -0300 +Subject: [PATCH] cifs: Clean up DFS referral cache +Git-commit: 185352ae6171c845951e21017b2925a6f2795904 +References: bsc#1144333 +Patch-mainline: v5.6-rc1 + +Do some renaming and code cleanup. + +No functional changes. + +Signed-off-by: Paulo Alcantara (SUSE) +Reviewed-by: Aurelien Aptel +Signed-off-by: Steve French +Acked-by: Paulo Alcantara +--- + fs/cifs/dfs_cache.c | 565 +++++++++++++++++++++++++--------------------------- + 1 file changed, 279 insertions(+), 286 deletions(-) + +--- a/fs/cifs/dfs_cache.c ++++ b/fs/cifs/dfs_cache.c +@@ -22,60 +22,59 @@ + + #include "dfs_cache.h" + +-#define DFS_CACHE_HTABLE_SIZE 32 +-#define DFS_CACHE_MAX_ENTRIES 64 ++#define CACHE_HTABLE_SIZE 32 ++#define CACHE_MAX_ENTRIES 64 + + #define IS_INTERLINK_SET(v) ((v) & (DFSREF_REFERRAL_SERVER | \ + DFSREF_STORAGE_SERVER)) + +-struct dfs_cache_tgt { +- char *t_name; +- struct list_head t_list; ++struct cache_dfs_tgt { ++ char *name; ++ struct list_head list; + }; + +-struct dfs_cache_entry { +- struct hlist_node ce_hlist; +- const char *ce_path; +- int ce_ttl; +- int ce_srvtype; +- int ce_flags; +- struct timespec64 ce_etime; +- int ce_path_consumed; +- int ce_numtgts; +- struct list_head ce_tlist; +- struct dfs_cache_tgt *ce_tgthint; +- struct rcu_head ce_rcu; ++struct cache_entry { ++ struct hlist_node hlist; ++ const char *path; ++ int ttl; ++ int srvtype; ++ int flags; ++ struct timespec64 etime; ++ int path_consumed; ++ int numtgts; ++ struct list_head tlist; ++ struct cache_dfs_tgt *tgthint; ++ struct rcu_head rcu; + }; + +-static struct kmem_cache *dfs_cache_slab __read_mostly; +- +-struct dfs_cache_vol_info { +- char *vi_fullpath; +- struct smb_vol vi_vol; +- char *vi_mntdata; +- struct list_head vi_list; ++struct vol_info { ++ char *fullpath; ++ struct smb_vol smb_vol; ++ char *mntdata; ++ struct list_head list; + }; + +-struct dfs_cache { +- struct mutex dc_lock; +- struct nls_table *dc_nlsc; +- struct list_head dc_vol_list; +- int dc_ttl; +- struct delayed_work dc_refresh; +-}; ++static struct kmem_cache *cache_slab __read_mostly; ++static struct workqueue_struct *dfscache_wq __read_mostly; + +-static struct dfs_cache dfs_cache; ++static int cache_ttl; ++static struct nls_table *cache_nlsc; + + /* + * Number of entries in the cache + */ +-static size_t dfs_cache_count; ++static size_t cache_count; ++ ++static struct hlist_head cache_htable[CACHE_HTABLE_SIZE]; ++static DEFINE_MUTEX(list_lock); + +-static DEFINE_MUTEX(dfs_cache_list_lock); +-static struct hlist_head dfs_cache_htable[DFS_CACHE_HTABLE_SIZE]; ++static LIST_HEAD(vol_list); ++static DEFINE_MUTEX(vol_lock); + + static void refresh_cache_worker(struct work_struct *work); + ++static DECLARE_DELAYED_WORK(refresh_task, refresh_cache_worker); ++ + static inline bool is_path_valid(const char *path) + { + return path && (strchr(path + 1, '\\') || strchr(path + 1, '/')); +@@ -100,42 +99,42 @@ static inline void free_normalized_path( + kfree(npath); + } + +-static inline bool cache_entry_expired(const struct dfs_cache_entry *ce) ++static inline bool cache_entry_expired(const struct cache_entry *ce) + { + struct timespec64 ts; + + ts = current_kernel_time64(); +- return timespec64_compare(&ts, &ce->ce_etime) >= 0; ++ return timespec64_compare(&ts, &ce->etime) >= 0; + } + +-static inline void free_tgts(struct dfs_cache_entry *ce) ++static inline void free_tgts(struct cache_entry *ce) + { +- struct dfs_cache_tgt *t, *n; ++ struct cache_dfs_tgt *t, *n; + +- list_for_each_entry_safe(t, n, &ce->ce_tlist, t_list) { +- list_del(&t->t_list); +- kfree(t->t_name); ++ list_for_each_entry_safe(t, n, &ce->tlist, list) { ++ list_del(&t->list); ++ kfree(t->name); + kfree(t); + } + } + + static void free_cache_entry(struct rcu_head *rcu) + { +- struct dfs_cache_entry *ce = container_of(rcu, struct dfs_cache_entry, +- ce_rcu); +- kmem_cache_free(dfs_cache_slab, ce); ++ struct cache_entry *ce = container_of(rcu, struct cache_entry, rcu); ++ ++ kmem_cache_free(cache_slab, ce); + } + +-static inline void flush_cache_ent(struct dfs_cache_entry *ce) ++static inline void flush_cache_ent(struct cache_entry *ce) + { +- if (hlist_unhashed(&ce->ce_hlist)) ++ if (hlist_unhashed(&ce->hlist)) + return; + +- hlist_del_init_rcu(&ce->ce_hlist); +- kfree_const(ce->ce_path); ++ hlist_del_init_rcu(&ce->hlist); ++ kfree_const(ce->path); + free_tgts(ce); +- dfs_cache_count--; +- call_rcu(&ce->ce_rcu, free_cache_entry); ++ cache_count--; ++ call_rcu(&ce->rcu, free_cache_entry); + } + + static void flush_cache_ents(void) +@@ -143,11 +142,11 @@ static void flush_cache_ents(void) + int i; + + rcu_read_lock(); +- for (i = 0; i < DFS_CACHE_HTABLE_SIZE; i++) { +- struct hlist_head *l = &dfs_cache_htable[i]; +- struct dfs_cache_entry *ce; ++ for (i = 0; i < CACHE_HTABLE_SIZE; i++) { ++ struct hlist_head *l = &cache_htable[i]; ++ struct cache_entry *ce; + +- hlist_for_each_entry_rcu(ce, l, ce_hlist) ++ hlist_for_each_entry_rcu(ce, l, hlist) + flush_cache_ent(ce); + } + rcu_read_unlock(); +@@ -159,35 +158,35 @@ static void flush_cache_ents(void) + static int dfscache_proc_show(struct seq_file *m, void *v) + { + int bucket; +- struct dfs_cache_entry *ce; +- struct dfs_cache_tgt *t; ++ struct cache_entry *ce; ++ struct cache_dfs_tgt *t; + + seq_puts(m, "DFS cache\n---------\n"); + +- mutex_lock(&dfs_cache_list_lock); ++ mutex_lock(&list_lock); + + rcu_read_lock(); +- hash_for_each_rcu(dfs_cache_htable, bucket, ce, ce_hlist) { ++ hash_for_each_rcu(cache_htable, bucket, ce, hlist) { + seq_printf(m, + "cache entry: path=%s,type=%s,ttl=%d,etime=%ld," + "interlink=%s,path_consumed=%d,expired=%s\n", +- ce->ce_path, +- ce->ce_srvtype == DFS_TYPE_ROOT ? "root" : "link", +- ce->ce_ttl, ce->ce_etime.tv_nsec, +- IS_INTERLINK_SET(ce->ce_flags) ? "yes" : "no", +- ce->ce_path_consumed, ++ ce->path, ++ ce->srvtype == DFS_TYPE_ROOT ? "root" : "link", ++ ce->ttl, ce->etime.tv_nsec, ++ IS_INTERLINK_SET(ce->flags) ? "yes" : "no", ++ ce->path_consumed, + cache_entry_expired(ce) ? "yes" : "no"); + +- list_for_each_entry(t, &ce->ce_tlist, t_list) { ++ list_for_each_entry(t, &ce->tlist, list) { + seq_printf(m, " %s%s\n", +- t->t_name, +- ce->ce_tgthint == t ? " (target hint)" : ""); ++ t->name, ++ ce->tgthint == t ? " (target hint)" : ""); + } + + } + rcu_read_unlock(); + +- mutex_unlock(&dfs_cache_list_lock); ++ mutex_unlock(&list_lock); + return 0; + } + +@@ -205,9 +204,9 @@ static ssize_t dfscache_proc_write(struc + return -EINVAL; + + cifs_dbg(FYI, "clearing dfs cache"); +- mutex_lock(&dfs_cache_list_lock); ++ mutex_lock(&list_lock); + flush_cache_ents(); +- mutex_unlock(&dfs_cache_list_lock); ++ mutex_unlock(&list_lock); + + return count; + } +@@ -226,25 +225,25 @@ const struct file_operations dfscache_pr + }; + + #ifdef CONFIG_CIFS_DEBUG2 +-static inline void dump_tgts(const struct dfs_cache_entry *ce) ++static inline void dump_tgts(const struct cache_entry *ce) + { +- struct dfs_cache_tgt *t; ++ struct cache_dfs_tgt *t; + + cifs_dbg(FYI, "target list:\n"); +- list_for_each_entry(t, &ce->ce_tlist, t_list) { +- cifs_dbg(FYI, " %s%s\n", t->t_name, +- ce->ce_tgthint == t ? " (target hint)" : ""); ++ list_for_each_entry(t, &ce->tlist, list) { ++ cifs_dbg(FYI, " %s%s\n", t->name, ++ ce->tgthint == t ? " (target hint)" : ""); + } + } + +-static inline void dump_ce(const struct dfs_cache_entry *ce) ++static inline void dump_ce(const struct cache_entry *ce) + { + cifs_dbg(FYI, "cache entry: path=%s,type=%s,ttl=%d,etime=%ld," +- "interlink=%s,path_consumed=%d,expired=%s\n", ce->ce_path, +- ce->ce_srvtype == DFS_TYPE_ROOT ? "root" : "link", ce->ce_ttl, +- ce->ce_etime.tv_nsec, +- IS_INTERLINK_SET(ce->ce_flags) ? "yes" : "no", +- ce->ce_path_consumed, ++ "interlink=%s,path_consumed=%d,expired=%s\n", ce->path, ++ ce->srvtype == DFS_TYPE_ROOT ? "root" : "link", ce->ttl, ++ ce->etime.tv_nsec, ++ IS_INTERLINK_SET(ce->flags) ? "yes" : "no", ++ ce->path_consumed, + cache_entry_expired(ce) ? "yes" : "no"); + dump_tgts(ce); + } +@@ -284,25 +283,34 @@ static inline void dump_refs(const struc + */ + int dfs_cache_init(void) + { ++ int rc; + int i; + +- dfs_cache_slab = kmem_cache_create("cifs_dfs_cache", +- sizeof(struct dfs_cache_entry), 0, +- SLAB_HWCACHE_ALIGN, NULL); +- if (!dfs_cache_slab) ++ dfscache_wq = alloc_workqueue("cifs-dfscache", ++ WQ_FREEZABLE | WQ_MEM_RECLAIM, 1); ++ if (!dfscache_wq) + return -ENOMEM; + +- for (i = 0; i < DFS_CACHE_HTABLE_SIZE; i++) +- INIT_HLIST_HEAD(&dfs_cache_htable[i]); ++ cache_slab = kmem_cache_create("cifs_dfs_cache", ++ sizeof(struct cache_entry), 0, ++ SLAB_HWCACHE_ALIGN, NULL); ++ if (!cache_slab) { ++ rc = -ENOMEM; ++ goto out_destroy_wq; ++ } ++ ++ for (i = 0; i < CACHE_HTABLE_SIZE; i++) ++ INIT_HLIST_HEAD(&cache_htable[i]); + +- INIT_LIST_HEAD(&dfs_cache.dc_vol_list); +- mutex_init(&dfs_cache.dc_lock); +- INIT_DELAYED_WORK(&dfs_cache.dc_refresh, refresh_cache_worker); +- dfs_cache.dc_ttl = -1; +- dfs_cache.dc_nlsc = load_nls_default(); ++ cache_ttl = -1; ++ cache_nlsc = load_nls_default(); + + cifs_dbg(FYI, "%s: initialized DFS referral cache\n", __func__); + return 0; ++ ++out_destroy_wq: ++ destroy_workqueue(dfscache_wq); ++ return rc; + } + + static inline unsigned int cache_entry_hash(const void *data, int size) +@@ -310,7 +318,7 @@ static inline unsigned int cache_entry_h + unsigned int h; + + h = jhash(data, size, 0); +- return h & (DFS_CACHE_HTABLE_SIZE - 1); ++ return h & (CACHE_HTABLE_SIZE - 1); + } + + /* Check whether second path component of @path is SYSVOL or NETLOGON */ +@@ -325,11 +333,11 @@ static inline bool is_sysvol_or_netlogon + } + + /* Return target hint of a DFS cache entry */ +-static inline char *get_tgt_name(const struct dfs_cache_entry *ce) ++static inline char *get_tgt_name(const struct cache_entry *ce) + { +- struct dfs_cache_tgt *t = ce->ce_tgthint; ++ struct cache_dfs_tgt *t = ce->tgthint; + +- return t ? t->t_name : ERR_PTR(-ENOENT); ++ return t ? t->name : ERR_PTR(-ENOENT); + } + + /* Return expire time out of a new entry's TTL */ +@@ -344,19 +352,19 @@ static inline struct timespec64 get_expi + } + + /* Allocate a new DFS target */ +-static inline struct dfs_cache_tgt *alloc_tgt(const char *name) ++static inline struct cache_dfs_tgt *alloc_tgt(const char *name) + { +- struct dfs_cache_tgt *t; ++ struct cache_dfs_tgt *t; + + t = kmalloc(sizeof(*t), GFP_KERNEL); + if (!t) + return ERR_PTR(-ENOMEM); +- t->t_name = kstrndup(name, strlen(name), GFP_KERNEL); +- if (!t->t_name) { ++ t->name = kstrndup(name, strlen(name), GFP_KERNEL); ++ if (!t->name) { + kfree(t); + return ERR_PTR(-ENOMEM); + } +- INIT_LIST_HEAD(&t->t_list); ++ INIT_LIST_HEAD(&t->list); + return t; + } + +@@ -365,63 +373,63 @@ static inline struct dfs_cache_tgt *allo + * target hint. + */ + static int copy_ref_data(const struct dfs_info3_param *refs, int numrefs, +- struct dfs_cache_entry *ce, const char *tgthint) ++ struct cache_entry *ce, const char *tgthint) + { + int i; + +- ce->ce_ttl = refs[0].ttl; +- ce->ce_etime = get_expire_time(ce->ce_ttl); +- ce->ce_srvtype = refs[0].server_type; +- ce->ce_flags = refs[0].ref_flag; +- ce->ce_path_consumed = refs[0].path_consumed; ++ ce->ttl = refs[0].ttl; ++ ce->etime = get_expire_time(ce->ttl); ++ ce->srvtype = refs[0].server_type; ++ ce->flags = refs[0].ref_flag; ++ ce->path_consumed = refs[0].path_consumed; + + for (i = 0; i < numrefs; i++) { +- struct dfs_cache_tgt *t; ++ struct cache_dfs_tgt *t; + + t = alloc_tgt(refs[i].node_name); + if (IS_ERR(t)) { + free_tgts(ce); + return PTR_ERR(t); + } +- if (tgthint && !strcasecmp(t->t_name, tgthint)) { +- list_add(&t->t_list, &ce->ce_tlist); ++ if (tgthint && !strcasecmp(t->name, tgthint)) { ++ list_add(&t->list, &ce->tlist); + tgthint = NULL; + } else { +- list_add_tail(&t->t_list, &ce->ce_tlist); ++ list_add_tail(&t->list, &ce->tlist); + } +- ce->ce_numtgts++; ++ ce->numtgts++; + } + +- ce->ce_tgthint = list_first_entry_or_null(&ce->ce_tlist, +- struct dfs_cache_tgt, t_list); ++ ce->tgthint = list_first_entry_or_null(&ce->tlist, ++ struct cache_dfs_tgt, list); + + return 0; + } + + /* Allocate a new cache entry */ +-static struct dfs_cache_entry * +-alloc_cache_entry(const char *path, const struct dfs_info3_param *refs, +- int numrefs) ++static struct cache_entry *alloc_cache_entry(const char *path, ++ const struct dfs_info3_param *refs, ++ int numrefs) + { +- struct dfs_cache_entry *ce; ++ struct cache_entry *ce; + int rc; + +- ce = kmem_cache_zalloc(dfs_cache_slab, GFP_KERNEL); ++ ce = kmem_cache_zalloc(cache_slab, GFP_KERNEL); + if (!ce) + return ERR_PTR(-ENOMEM); + +- ce->ce_path = kstrdup_const(path, GFP_KERNEL); +- if (!ce->ce_path) { +- kmem_cache_free(dfs_cache_slab, ce); ++ ce->path = kstrdup_const(path, GFP_KERNEL); ++ if (!ce->path) { ++ kmem_cache_free(cache_slab, ce); + return ERR_PTR(-ENOMEM); + } +- INIT_HLIST_NODE(&ce->ce_hlist); +- INIT_LIST_HEAD(&ce->ce_tlist); ++ INIT_HLIST_NODE(&ce->hlist); ++ INIT_LIST_HEAD(&ce->tlist); + + rc = copy_ref_data(refs, numrefs, ce, NULL); + if (rc) { +- kfree_const(ce->ce_path); +- kmem_cache_free(dfs_cache_slab, ce); ++ kfree_const(ce->path); ++ kmem_cache_free(cache_slab, ce); + ce = ERR_PTR(rc); + } + return ce; +@@ -430,13 +438,13 @@ alloc_cache_entry(const char *path, cons + static void remove_oldest_entry(void) + { + int bucket; +- struct dfs_cache_entry *ce; +- struct dfs_cache_entry *to_del = NULL; ++ struct cache_entry *ce; ++ struct cache_entry *to_del = NULL; + + rcu_read_lock(); +- hash_for_each_rcu(dfs_cache_htable, bucket, ce, ce_hlist) { +- if (!to_del || timespec64_compare(&ce->ce_etime, +- &to_del->ce_etime) < 0) ++ hash_for_each_rcu(cache_htable, bucket, ce, hlist) { ++ if (!to_del || timespec64_compare(&ce->etime, ++ &to_del->etime) < 0) + to_del = ce; + } + if (!to_del) { +@@ -451,93 +459,84 @@ out: + } + + /* Add a new DFS cache entry */ +-static inline struct dfs_cache_entry * ++static inline struct cache_entry * + add_cache_entry(unsigned int hash, const char *path, + const struct dfs_info3_param *refs, int numrefs) + { +- struct dfs_cache_entry *ce; ++ struct cache_entry *ce; + + ce = alloc_cache_entry(path, refs, numrefs); + if (IS_ERR(ce)) + return ce; + +- hlist_add_head_rcu(&ce->ce_hlist, &dfs_cache_htable[hash]); ++ hlist_add_head_rcu(&ce->hlist, &cache_htable[hash]); + +- mutex_lock(&dfs_cache.dc_lock); +- if (dfs_cache.dc_ttl < 0) { +- dfs_cache.dc_ttl = ce->ce_ttl; +- queue_delayed_work(cifsiod_wq, &dfs_cache.dc_refresh, +- dfs_cache.dc_ttl * HZ); ++ mutex_lock(&vol_lock); ++ if (cache_ttl < 0) { ++ cache_ttl = ce->ttl; ++ queue_delayed_work(dfscache_wq, &refresh_task, cache_ttl * HZ); + } else { +- dfs_cache.dc_ttl = min_t(int, dfs_cache.dc_ttl, ce->ce_ttl); +- mod_delayed_work(cifsiod_wq, &dfs_cache.dc_refresh, +- dfs_cache.dc_ttl * HZ); ++ cache_ttl = min_t(int, cache_ttl, ce->ttl); ++ mod_delayed_work(dfscache_wq, &refresh_task, cache_ttl * HZ); + } +- mutex_unlock(&dfs_cache.dc_lock); ++ mutex_unlock(&vol_lock); + + return ce; + } + +-static struct dfs_cache_entry *__find_cache_entry(unsigned int hash, +- const char *path) ++/* ++ * Find a DFS cache entry in hash table and optionally check prefix path against ++ * @path. ++ * Use whole path components in the match. ++ * Return ERR_PTR(-ENOENT) if the entry is not found. ++ */ ++static struct cache_entry *lookup_cache_entry(const char *path, ++ unsigned int *hash) + { +- struct dfs_cache_entry *ce; ++ struct cache_entry *ce; ++ unsigned int h; + bool found = false; + +- rcu_read_lock(); +- hlist_for_each_entry_rcu(ce, &dfs_cache_htable[hash], ce_hlist) { +- if (!strcasecmp(path, ce->ce_path)) { +-#ifdef CONFIG_CIFS_DEBUG2 +- char *name = get_tgt_name(ce); ++ h = cache_entry_hash(path, strlen(path)); + +- if (IS_ERR(name)) { +- rcu_read_unlock(); +- return ERR_CAST(name); +- } +- cifs_dbg(FYI, "%s: cache hit\n", __func__); +- cifs_dbg(FYI, "%s: target hint: %s\n", __func__, name); +-#endif ++ rcu_read_lock(); ++ hlist_for_each_entry_rcu(ce, &cache_htable[h], hlist) { ++ if (!strcasecmp(path, ce->path)) { + found = true; ++ dump_ce(ce); + break; + } + } + rcu_read_unlock(); +- return found ? ce : ERR_PTR(-ENOENT); +-} + +-/* +- * Find a DFS cache entry in hash table and optionally check prefix path against +- * @path. +- * Use whole path components in the match. +- * Return ERR_PTR(-ENOENT) if the entry is not found. +- */ +-static inline struct dfs_cache_entry *find_cache_entry(const char *path, +- unsigned int *hash) +-{ +- *hash = cache_entry_hash(path, strlen(path)); +- return __find_cache_entry(*hash, path); ++ if (!found) ++ ce = ERR_PTR(-ENOENT); ++ if (hash) ++ *hash = h; ++ ++ return ce; + } + + static inline void destroy_slab_cache(void) + { + rcu_barrier(); +- kmem_cache_destroy(dfs_cache_slab); ++ kmem_cache_destroy(cache_slab); + } + +-static inline void free_vol(struct dfs_cache_vol_info *vi) ++static inline void free_vol(struct vol_info *vi) + { +- list_del(&vi->vi_list); +- kfree(vi->vi_fullpath); +- kfree(vi->vi_mntdata); +- cifs_cleanup_volume_info_contents(&vi->vi_vol); ++ list_del(&vi->list); ++ kfree(vi->fullpath); ++ kfree(vi->mntdata); ++ cifs_cleanup_volume_info_contents(&vi->smb_vol); + kfree(vi); + } + + static inline void free_vol_list(void) + { +- struct dfs_cache_vol_info *vi, *nvi; ++ struct vol_info *vi, *nvi; + +- list_for_each_entry_safe(vi, nvi, &dfs_cache.dc_vol_list, vi_list) ++ list_for_each_entry_safe(vi, nvi, &vol_list, list) + free_vol(vi); + } + +@@ -546,40 +545,38 @@ static inline void free_vol_list(void) + */ + void dfs_cache_destroy(void) + { +- cancel_delayed_work_sync(&dfs_cache.dc_refresh); +- unload_nls(dfs_cache.dc_nlsc); ++ cancel_delayed_work_sync(&refresh_task); ++ unload_nls(cache_nlsc); + free_vol_list(); +- mutex_destroy(&dfs_cache.dc_lock); +- + flush_cache_ents(); + destroy_slab_cache(); +- mutex_destroy(&dfs_cache_list_lock); ++ destroy_workqueue(dfscache_wq); + + cifs_dbg(FYI, "%s: destroyed DFS referral cache\n", __func__); + } + +-static inline struct dfs_cache_entry * ++static inline struct cache_entry * + __update_cache_entry(const char *path, const struct dfs_info3_param *refs, + int numrefs) + { + int rc; + unsigned int h; +- struct dfs_cache_entry *ce; ++ struct cache_entry *ce; + char *s, *th = NULL; + +- ce = find_cache_entry(path, &h); ++ ce = lookup_cache_entry(path, &h); + if (IS_ERR(ce)) + return ce; + +- if (ce->ce_tgthint) { +- s = ce->ce_tgthint->t_name; ++ if (ce->tgthint) { ++ s = ce->tgthint->name; + th = kstrndup(s, strlen(s), GFP_KERNEL); + if (!th) + return ERR_PTR(-ENOMEM); + } + + free_tgts(ce); +- ce->ce_numtgts = 0; ++ ce->numtgts = 0; + + rc = copy_ref_data(refs, numrefs, ce, th); + kfree(th); +@@ -591,10 +588,10 @@ __update_cache_entry(const char *path, c + } + + /* Update an expired cache entry by getting a new DFS referral from server */ +-static struct dfs_cache_entry * ++static struct cache_entry * + update_cache_entry(const unsigned int xid, struct cifs_ses *ses, + const struct nls_table *nls_codepage, int remap, +- const char *path, struct dfs_cache_entry *ce) ++ const char *path, struct cache_entry *ce) + { + int rc; + struct dfs_info3_param *refs = NULL; +@@ -634,20 +631,20 @@ update_cache_entry(const unsigned int xi + * For interlinks, __cifs_dfs_mount() and expand_dfs_referral() are supposed to + * handle them properly. + */ +-static struct dfs_cache_entry * ++static struct cache_entry * + do_dfs_cache_find(const unsigned int xid, struct cifs_ses *ses, + const struct nls_table *nls_codepage, int remap, + const char *path, bool noreq) + { + int rc; + unsigned int h; +- struct dfs_cache_entry *ce; ++ struct cache_entry *ce; + struct dfs_info3_param *nrefs; + int numnrefs; + + cifs_dbg(FYI, "%s: search path: %s\n", __func__, path); + +- ce = find_cache_entry(path, &h); ++ ce = lookup_cache_entry(path, &h); + if (IS_ERR(ce)) { + cifs_dbg(FYI, "%s: cache miss\n", __func__); + /* +@@ -688,9 +685,9 @@ do_dfs_cache_find(const unsigned int xid + + cifs_dbg(FYI, "%s: new cache entry\n", __func__); + +- if (dfs_cache_count >= DFS_CACHE_MAX_ENTRIES) { ++ if (cache_count >= CACHE_MAX_ENTRIES) { + cifs_dbg(FYI, "%s: reached max cache size (%d)", +- __func__, DFS_CACHE_MAX_ENTRIES); ++ __func__, CACHE_MAX_ENTRIES); + remove_oldest_entry(); + } + ce = add_cache_entry(h, path, nrefs, numnrefs); +@@ -699,7 +696,7 @@ do_dfs_cache_find(const unsigned int xid + if (IS_ERR(ce)) + return ce; + +- dfs_cache_count++; ++ cache_count++; + } + + dump_ce(ce); +@@ -721,7 +718,7 @@ do_dfs_cache_find(const unsigned int xid + } + + /* Set up a new DFS referral from a given cache entry */ +-static int setup_ref(const char *path, const struct dfs_cache_entry *ce, ++static int setup_ref(const char *path, const struct cache_entry *ce, + struct dfs_info3_param *ref, const char *tgt) + { + int rc; +@@ -734,7 +731,7 @@ static int setup_ref(const char *path, c + if (!ref->path_name) + return -ENOMEM; + +- ref->path_consumed = ce->ce_path_consumed; ++ ref->path_consumed = ce->path_consumed; + + ref->node_name = kstrndup(tgt, strlen(tgt), GFP_KERNEL); + if (!ref->node_name) { +@@ -742,9 +739,9 @@ static int setup_ref(const char *path, c + goto err_free_path; + } + +- ref->ttl = ce->ce_ttl; +- ref->server_type = ce->ce_srvtype; +- ref->ref_flag = ce->ce_flags; ++ ref->ttl = ce->ttl; ++ ref->server_type = ce->srvtype; ++ ref->ref_flag = ce->flags; + + return 0; + +@@ -755,25 +752,25 @@ err_free_path: + } + + /* Return target list of a DFS cache entry */ +-static int get_tgt_list(const struct dfs_cache_entry *ce, ++static int get_tgt_list(const struct cache_entry *ce, + struct dfs_cache_tgt_list *tl) + { + int rc; + struct list_head *head = &tl->tl_list; +- struct dfs_cache_tgt *t; ++ struct cache_dfs_tgt *t; + struct dfs_cache_tgt_iterator *it, *nit; + + memset(tl, 0, sizeof(*tl)); + INIT_LIST_HEAD(head); + +- list_for_each_entry(t, &ce->ce_tlist, t_list) { ++ list_for_each_entry(t, &ce->tlist, list) { + it = kzalloc(sizeof(*it), GFP_KERNEL); + if (!it) { + rc = -ENOMEM; + goto err_free_it; + } + +- it->it_name = kstrndup(t->t_name, strlen(t->t_name), ++ it->it_name = kstrndup(t->name, strlen(t->name), + GFP_KERNEL); + if (!it->it_name) { + kfree(it); +@@ -781,12 +778,12 @@ static int get_tgt_list(const struct dfs + goto err_free_it; + } + +- if (ce->ce_tgthint == t) ++ if (ce->tgthint == t) + list_add(&it->it_list, head); + else + list_add_tail(&it->it_list, head); + } +- tl->tl_numtgts = ce->ce_numtgts; ++ tl->tl_numtgts = ce->numtgts; + + return 0; + +@@ -827,7 +824,7 @@ int dfs_cache_find(const unsigned int xi + { + int rc; + char *npath; +- struct dfs_cache_entry *ce; ++ struct cache_entry *ce; + + if (unlikely(!is_path_valid(path))) + return -EINVAL; +@@ -836,7 +833,7 @@ int dfs_cache_find(const unsigned int xi + if (rc) + return rc; + +- mutex_lock(&dfs_cache_list_lock); ++ mutex_lock(&list_lock); + ce = do_dfs_cache_find(xid, ses, nls_codepage, remap, npath, false); + if (!IS_ERR(ce)) { + if (ref) +@@ -848,7 +845,7 @@ int dfs_cache_find(const unsigned int xi + } else { + rc = PTR_ERR(ce); + } +- mutex_unlock(&dfs_cache_list_lock); ++ mutex_unlock(&list_lock); + free_normalized_path(path, npath); + return rc; + } +@@ -874,7 +871,7 @@ int dfs_cache_noreq_find(const char *pat + { + int rc; + char *npath; +- struct dfs_cache_entry *ce; ++ struct cache_entry *ce; + + if (unlikely(!is_path_valid(path))) + return -EINVAL; +@@ -883,7 +880,7 @@ int dfs_cache_noreq_find(const char *pat + if (rc) + return rc; + +- mutex_lock(&dfs_cache_list_lock); ++ mutex_lock(&list_lock); + ce = do_dfs_cache_find(0, NULL, NULL, 0, npath, true); + if (IS_ERR(ce)) { + rc = PTR_ERR(ce); +@@ -897,7 +894,7 @@ int dfs_cache_noreq_find(const char *pat + if (!rc && tgt_list) + rc = get_tgt_list(ce, tgt_list); + out: +- mutex_unlock(&dfs_cache_list_lock); ++ mutex_unlock(&list_lock); + free_normalized_path(path, npath); + return rc; + } +@@ -927,8 +924,8 @@ int dfs_cache_update_tgthint(const unsig + { + int rc; + char *npath; +- struct dfs_cache_entry *ce; +- struct dfs_cache_tgt *t; ++ struct cache_entry *ce; ++ struct cache_dfs_tgt *t; + + if (unlikely(!is_path_valid(path))) + return -EINVAL; +@@ -939,7 +936,7 @@ int dfs_cache_update_tgthint(const unsig + + cifs_dbg(FYI, "%s: path: %s\n", __func__, npath); + +- mutex_lock(&dfs_cache_list_lock); ++ mutex_lock(&list_lock); + ce = do_dfs_cache_find(xid, ses, nls_codepage, remap, npath, false); + if (IS_ERR(ce)) { + rc = PTR_ERR(ce); +@@ -948,14 +945,14 @@ int dfs_cache_update_tgthint(const unsig + + rc = 0; + +- t = ce->ce_tgthint; ++ t = ce->tgthint; + +- if (likely(!strcasecmp(it->it_name, t->t_name))) ++ if (likely(!strcasecmp(it->it_name, t->name))) + goto out; + +- list_for_each_entry(t, &ce->ce_tlist, t_list) { +- if (!strcasecmp(t->t_name, it->it_name)) { +- ce->ce_tgthint = t; ++ list_for_each_entry(t, &ce->tlist, list) { ++ if (!strcasecmp(t->name, it->it_name)) { ++ ce->tgthint = t; + cifs_dbg(FYI, "%s: new target hint: %s\n", __func__, + it->it_name); + break; +@@ -963,7 +960,7 @@ int dfs_cache_update_tgthint(const unsig + } + + out: +- mutex_unlock(&dfs_cache_list_lock); ++ mutex_unlock(&list_lock); + free_normalized_path(path, npath); + return rc; + } +@@ -987,8 +984,8 @@ int dfs_cache_noreq_update_tgthint(const + { + int rc; + char *npath; +- struct dfs_cache_entry *ce; +- struct dfs_cache_tgt *t; ++ struct cache_entry *ce; ++ struct cache_dfs_tgt *t; + + if (unlikely(!is_path_valid(path)) || !it) + return -EINVAL; +@@ -999,7 +996,7 @@ int dfs_cache_noreq_update_tgthint(const + + cifs_dbg(FYI, "%s: path: %s\n", __func__, npath); + +- mutex_lock(&dfs_cache_list_lock); ++ mutex_lock(&list_lock); + + ce = do_dfs_cache_find(0, NULL, NULL, 0, npath, true); + if (IS_ERR(ce)) { +@@ -1009,14 +1006,14 @@ int dfs_cache_noreq_update_tgthint(const + + rc = 0; + +- t = ce->ce_tgthint; ++ t = ce->tgthint; + +- if (unlikely(!strcasecmp(it->it_name, t->t_name))) ++ if (unlikely(!strcasecmp(it->it_name, t->name))) + goto out; + +- list_for_each_entry(t, &ce->ce_tlist, t_list) { +- if (!strcasecmp(t->t_name, it->it_name)) { +- ce->ce_tgthint = t; ++ list_for_each_entry(t, &ce->tlist, list) { ++ if (!strcasecmp(t->name, it->it_name)) { ++ ce->tgthint = t; + cifs_dbg(FYI, "%s: new target hint: %s\n", __func__, + it->it_name); + break; +@@ -1024,7 +1021,7 @@ int dfs_cache_noreq_update_tgthint(const + } + + out: +- mutex_unlock(&dfs_cache_list_lock); ++ mutex_unlock(&list_lock); + free_normalized_path(path, npath); + return rc; + } +@@ -1045,7 +1042,7 @@ int dfs_cache_get_tgt_referral(const cha + { + int rc; + char *npath; +- struct dfs_cache_entry *ce; ++ struct cache_entry *ce; + unsigned int h; + + if (!it || !ref) +@@ -1059,9 +1056,9 @@ int dfs_cache_get_tgt_referral(const cha + + cifs_dbg(FYI, "%s: path: %s\n", __func__, npath); + +- mutex_lock(&dfs_cache_list_lock); ++ mutex_lock(&list_lock); + +- ce = find_cache_entry(npath, &h); ++ ce = lookup_cache_entry(npath, &h); + if (IS_ERR(ce)) { + rc = PTR_ERR(ce); + goto out; +@@ -1072,7 +1069,7 @@ int dfs_cache_get_tgt_referral(const cha + rc = setup_ref(path, ce, ref, it->it_name); + + out: +- mutex_unlock(&dfs_cache_list_lock); ++ mutex_unlock(&list_lock); + free_normalized_path(path, npath); + return rc; + } +@@ -1083,7 +1080,7 @@ static int dup_vol(struct smb_vol *vol, + + if (vol->username) { + new->username = kstrndup(vol->username, strlen(vol->username), +- GFP_KERNEL); ++ GFP_KERNEL); + if (!new->username) + return -ENOMEM; + } +@@ -1101,7 +1098,7 @@ static int dup_vol(struct smb_vol *vol, + } + if (vol->domainname) { + new->domainname = kstrndup(vol->domainname, +- strlen(vol->domainname), GFP_KERNEL); ++ strlen(vol->domainname), GFP_KERNEL); + if (!new->domainname) + goto err_free_unc; + } +@@ -1148,7 +1145,7 @@ err_free_username: + int dfs_cache_add_vol(char *mntdata, struct smb_vol *vol, const char *fullpath) + { + int rc; +- struct dfs_cache_vol_info *vi; ++ struct vol_info *vi; + + if (!vol || !fullpath || !mntdata) + return -EINVAL; +@@ -1159,38 +1156,37 @@ int dfs_cache_add_vol(char *mntdata, str + if (!vi) + return -ENOMEM; + +- vi->vi_fullpath = kstrndup(fullpath, strlen(fullpath), GFP_KERNEL); +- if (!vi->vi_fullpath) { ++ vi->fullpath = kstrndup(fullpath, strlen(fullpath), GFP_KERNEL); ++ if (!vi->fullpath) { + rc = -ENOMEM; + goto err_free_vi; + } + +- rc = dup_vol(vol, &vi->vi_vol); ++ rc = dup_vol(vol, &vi->smb_vol); + if (rc) + goto err_free_fullpath; + +- vi->vi_mntdata = mntdata; ++ vi->mntdata = mntdata; + +- mutex_lock(&dfs_cache.dc_lock); +- list_add_tail(&vi->vi_list, &dfs_cache.dc_vol_list); +- mutex_unlock(&dfs_cache.dc_lock); ++ mutex_lock(&vol_lock); ++ list_add_tail(&vi->list, &vol_list); ++ mutex_unlock(&vol_lock); + return 0; + + err_free_fullpath: +- kfree(vi->vi_fullpath); ++ kfree(vi->fullpath); + err_free_vi: + kfree(vi); + return rc; + } + +-static inline struct dfs_cache_vol_info *find_vol(const char *fullpath) ++static inline struct vol_info *find_vol(const char *fullpath) + { +- struct dfs_cache_vol_info *vi; ++ struct vol_info *vi; + +- list_for_each_entry(vi, &dfs_cache.dc_vol_list, vi_list) { +- cifs_dbg(FYI, "%s: vi->vi_fullpath: %s\n", __func__, +- vi->vi_fullpath); +- if (!strcasecmp(vi->vi_fullpath, fullpath)) ++ list_for_each_entry(vi, &vol_list, list) { ++ cifs_dbg(FYI, "%s: vi->fullpath: %s\n", __func__, vi->fullpath); ++ if (!strcasecmp(vi->fullpath, fullpath)) + return vi; + } + return ERR_PTR(-ENOENT); +@@ -1207,14 +1203,14 @@ static inline struct dfs_cache_vol_info + int dfs_cache_update_vol(const char *fullpath, struct TCP_Server_Info *server) + { + int rc; +- struct dfs_cache_vol_info *vi; ++ struct vol_info *vi; + + if (!fullpath || !server) + return -EINVAL; + + cifs_dbg(FYI, "%s: fullpath: %s\n", __func__, fullpath); + +- mutex_lock(&dfs_cache.dc_lock); ++ mutex_lock(&vol_lock); + + vi = find_vol(fullpath); + if (IS_ERR(vi)) { +@@ -1223,12 +1219,12 @@ int dfs_cache_update_vol(const char *ful + } + + cifs_dbg(FYI, "%s: updating volume info\n", __func__); +- memcpy(&vi->vi_vol.dstaddr, &server->dstaddr, +- sizeof(vi->vi_vol.dstaddr)); ++ memcpy(&vi->smb_vol.dstaddr, &server->dstaddr, ++ sizeof(vi->smb_vol.dstaddr)); + rc = 0; + + out: +- mutex_unlock(&dfs_cache.dc_lock); ++ mutex_unlock(&vol_lock); + return rc; + } + +@@ -1239,18 +1235,18 @@ out: + */ + void dfs_cache_del_vol(const char *fullpath) + { +- struct dfs_cache_vol_info *vi; ++ struct vol_info *vi; + + if (!fullpath || !*fullpath) + return; + + cifs_dbg(FYI, "%s: fullpath: %s\n", __func__, fullpath); + +- mutex_lock(&dfs_cache.dc_lock); ++ mutex_lock(&vol_lock); + vi = find_vol(fullpath); + if (!IS_ERR(vi)) + free_vol(vi); +- mutex_unlock(&dfs_cache.dc_lock); ++ mutex_unlock(&vol_lock); + } + + /* Get all tcons that are within a DFS namespace and can be refreshed */ +@@ -1278,7 +1274,7 @@ static void get_tcons(struct TCP_Server_ + spin_unlock(&cifs_tcp_ses_lock); + } + +-static inline bool is_dfs_link(const char *path) ++static bool is_dfs_link(const char *path) + { + char *s; + +@@ -1288,7 +1284,7 @@ static inline bool is_dfs_link(const cha + return !!strchr(s + 1, '\\'); + } + +-static inline char *get_dfs_root(const char *path) ++static char *get_dfs_root(const char *path) + { + char *s, *npath; + +@@ -1308,8 +1304,9 @@ static inline char *get_dfs_root(const c + } + + /* Find root SMB session out of a DFS link path */ +-static struct cifs_ses *find_root_ses(struct dfs_cache_vol_info *vi, +- struct cifs_tcon *tcon, const char *path) ++static struct cifs_ses *find_root_ses(struct vol_info *vi, ++ struct cifs_tcon *tcon, ++ const char *path) + { + char *rpath; + int rc; +@@ -1331,8 +1328,7 @@ static struct cifs_ses *find_root_ses(st + goto out; + } + +- mdata = cifs_compose_mount_options(vi->vi_mntdata, rpath, &ref, +- &devname); ++ mdata = cifs_compose_mount_options(vi->mntdata, rpath, &ref, &devname); + free_dfs_info_param(&ref); + + if (IS_ERR(mdata)) { +@@ -1371,14 +1367,13 @@ out: + } + + /* Refresh DFS cache entry from a given tcon */ +-static void do_refresh_tcon(struct dfs_cache *dc, struct dfs_cache_vol_info *vi, +- struct cifs_tcon *tcon) ++static void refresh_tcon(struct vol_info *vi, struct cifs_tcon *tcon) + { + int rc = 0; + unsigned int xid; + char *path, *npath; + unsigned int h; +- struct dfs_cache_entry *ce; ++ struct cache_entry *ce; + struct dfs_info3_param *refs = NULL; + int numrefs = 0; + struct cifs_ses *root_ses = NULL, *ses; +@@ -1391,9 +1386,9 @@ static void do_refresh_tcon(struct dfs_c + if (rc) + goto out; + +- mutex_lock(&dfs_cache_list_lock); +- ce = find_cache_entry(npath, &h); +- mutex_unlock(&dfs_cache_list_lock); ++ mutex_lock(&list_lock); ++ ce = lookup_cache_entry(npath, &h); ++ mutex_unlock(&list_lock); + + if (IS_ERR(ce)) { + rc = PTR_ERR(ce); +@@ -1419,12 +1414,12 @@ static void do_refresh_tcon(struct dfs_c + rc = -EOPNOTSUPP; + } else { + rc = ses->server->ops->get_dfs_refer(xid, ses, path, &refs, +- &numrefs, dc->dc_nlsc, ++ &numrefs, cache_nlsc, + tcon->remap); + if (!rc) { +- mutex_lock(&dfs_cache_list_lock); ++ mutex_lock(&list_lock); + ce = __update_cache_entry(npath, refs, numrefs); +- mutex_unlock(&dfs_cache_list_lock); ++ mutex_unlock(&list_lock); + dump_refs(refs, numrefs); + free_dfs_info_array(refs, numrefs); + if (IS_ERR(ce)) +@@ -1446,30 +1441,28 @@ out: + */ + static void refresh_cache_worker(struct work_struct *work) + { +- struct dfs_cache *dc = container_of(work, struct dfs_cache, +- dc_refresh.work); +- struct dfs_cache_vol_info *vi; ++ struct vol_info *vi; + struct TCP_Server_Info *server; + LIST_HEAD(list); + struct cifs_tcon *tcon, *ntcon; + +- mutex_lock(&dc->dc_lock); ++ mutex_lock(&vol_lock); + +- list_for_each_entry(vi, &dc->dc_vol_list, vi_list) { +- server = cifs_find_tcp_session(&vi->vi_vol); ++ list_for_each_entry(vi, &vol_list, list) { ++ server = cifs_find_tcp_session(&vi->smb_vol); + if (IS_ERR_OR_NULL(server)) + continue; + if (server->tcpStatus != CifsGood) + goto next; + get_tcons(server, &list); + list_for_each_entry_safe(tcon, ntcon, &list, ulist) { +- do_refresh_tcon(dc, vi, tcon); ++ refresh_tcon(vi, tcon); + list_del_init(&tcon->ulist); + cifs_put_tcon(tcon); + } + next: + cifs_put_tcp_session(server, 0); + } +- queue_delayed_work(cifsiod_wq, &dc->dc_refresh, dc->dc_ttl * HZ); +- mutex_unlock(&dc->dc_lock); ++ queue_delayed_work(dfscache_wq, &refresh_task, cache_ttl * HZ); ++ mutex_unlock(&vol_lock); + } diff --git a/patches.suse/cifs-Don-t-display-RDMA-transport-on-reconnect.patch b/patches.suse/cifs-Don-t-display-RDMA-transport-on-reconnect.patch new file mode 100644 index 0000000..a42b093 --- /dev/null +++ b/patches.suse/cifs-Don-t-display-RDMA-transport-on-reconnect.patch @@ -0,0 +1,38 @@ +From: Long Li +Date: Wed, 16 Oct 2019 13:51:50 -0700 +Subject: [PATCH] cifs: Don't display RDMA transport on reconnect +Git-commit: 14cc639c17ab0b6671526a7459087352507609e4 +References: bsc#1144333 +Patch-mainline: v5.5-rc1 + +On reconnect, the transport data structure is NULL and its information is not +available. + +Signed-off-by: Long Li +Cc: stable@vger.kernel.org +Signed-off-by: Steve French +Acked-by: Paulo Alcantara +--- + fs/cifs/cifs_debug.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/fs/cifs/cifs_debug.c b/fs/cifs/cifs_debug.c +index 0b4eee3bed66..efb2928ff6c8 100644 +--- a/fs/cifs/cifs_debug.c ++++ b/fs/cifs/cifs_debug.c +@@ -256,6 +256,11 @@ static int cifs_debug_data_proc_show(struct seq_file *m, void *v) + if (!server->rdma) + goto skip_rdma; + ++ if (!server->smbd_conn) { ++ seq_printf(m, "\nSMBDirect transport not available"); ++ goto skip_rdma; ++ } ++ + seq_printf(m, "\nSMBDirect (in hex) protocol version: %x " + "transport status: %x", + server->smbd_conn->protocol, +-- +2.25.1 + + diff --git a/patches.suse/cifs-Fix-memory-allocation-in-__smb2_handle_cancelle.patch b/patches.suse/cifs-Fix-memory-allocation-in-__smb2_handle_cancelle.patch deleted file mode 100644 index 96e5958..0000000 --- a/patches.suse/cifs-Fix-memory-allocation-in-__smb2_handle_cancelle.patch +++ /dev/null @@ -1,61 +0,0 @@ -From 9dd247f296aebd6c38d1c7535872517dadf502d9 Mon Sep 17 00:00:00 2001 -From: "Paulo Alcantara (SUSE)" -Date: Mon, 13 Jan 2020 17:38:18 -0300 -Subject: [PATCH] cifs: Fix memory allocation in __smb2_handle_cancelled_cmd() -Patch-mainline: Not yet, submitted upstream -References: bsc#1144333 - -__smb2_handle_cancelled_cmd() is called under a spin lock held in -cifs_mid_q_entry_release(), so make its memory allocation GFP_ATOMIC. - -This issue was observed when running xfstests generic/028: - -[ 1722.589204] CIFS VFS: \\192.168.30.26 Cancelling wait for mid 72064 cmd: 5 -[ 1722.590687] CIFS VFS: \\192.168.30.26 Cancelling wait for mid 72065 cmd: 17 -[ 1722.593529] CIFS VFS: \\192.168.30.26 Cancelling wait for mid 72066 cmd: 6 -[ 1723.039014] BUG: sleeping function called from invalid context at mm/slab.h:565 -[ 1723.040710] in_atomic(): 1, irqs_disabled(): 0, non_block: 0, pid: 30877, name: cifsd -[ 1723.045098] CPU: 3 PID: 30877 Comm: cifsd Not tainted 5.5.0-rc4+ #313 -[ 1723.046256] Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS rel-1.12.0-59-gc9ba527-rebuilt.opensuse.org 04/01/2014 -[ 1723.048221] Call Trace: -[ 1723.048689] dump_stack+0x97/0xe0 -[ 1723.049268] ___might_sleep.cold+0xd1/0xe1 -[ 1723.050069] kmem_cache_alloc_trace+0x204/0x2b0 -[ 1723.051051] __smb2_handle_cancelled_cmd+0x40/0x140 [cifs] -[ 1723.052137] smb2_handle_cancelled_mid+0xf6/0x120 [cifs] -[ 1723.053247] cifs_mid_q_entry_release+0x44d/0x630 [cifs] -[ 1723.054351] ? cifs_reconnect+0x26a/0x1620 [cifs] -[ 1723.055325] cifs_demultiplex_thread+0xad4/0x14a0 [cifs] -[ 1723.056458] ? cifs_handle_standard+0x2c0/0x2c0 [cifs] -[ 1723.057365] ? kvm_sched_clock_read+0x14/0x30 -[ 1723.058197] ? sched_clock+0x5/0x10 -[ 1723.058838] ? sched_clock_cpu+0x18/0x110 -[ 1723.059629] ? lockdep_hardirqs_on+0x17d/0x250 -[ 1723.060456] kthread+0x1ab/0x200 -[ 1723.061149] ? cifs_handle_standard+0x2c0/0x2c0 [cifs] -[ 1723.062078] ? kthread_create_on_node+0xd0/0xd0 -[ 1723.062897] ret_from_fork+0x3a/0x50 - -Signed-off-by: Paulo Alcantara (SUSE) -Fixes: 9150c3adbf24 ("CIFS: Close open handle after interrupted close") -Acked-by: Paulo Alcantara ---- - fs/cifs/smb2misc.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/fs/cifs/smb2misc.c b/fs/cifs/smb2misc.c -index 0516fc482d43..0511aaf451d4 100644 ---- a/fs/cifs/smb2misc.c -+++ b/fs/cifs/smb2misc.c -@@ -743,7 +743,7 @@ __smb2_handle_cancelled_cmd(struct cifs_tcon *tcon, __u16 cmd, __u64 mid, - { - struct close_cancelled_open *cancelled; - -- cancelled = kzalloc(sizeof(*cancelled), GFP_KERNEL); -+ cancelled = kzalloc(sizeof(*cancelled), GFP_ATOMIC); - if (!cancelled) - return -ENOMEM; - --- -2.24.1 - diff --git a/patches.suse/cifs-Fix-memory-allocation-in-__smb2_handle_cancelled_cmd-.patch b/patches.suse/cifs-Fix-memory-allocation-in-__smb2_handle_cancelled_cmd-.patch new file mode 100644 index 0000000..85d7bc5 --- /dev/null +++ b/patches.suse/cifs-Fix-memory-allocation-in-__smb2_handle_cancelled_cmd-.patch @@ -0,0 +1,65 @@ +From: "Paulo Alcantara (SUSE)" +Date: Mon, 13 Jan 2020 17:46:59 -0300 +Subject: [PATCH] cifs: Fix memory allocation in __smb2_handle_cancelled_cmd() +Git-commit: 0a5a98863c9debc02387b3d23c46d187756f5e2b +References: bsc#1144333 +Patch-mainline: v5.6-rc1 + +__smb2_handle_cancelled_cmd() is called under a spin lock held in +cifs_mid_q_entry_release(), so make its memory allocation GFP_ATOMIC. + +This issue was observed when running xfstests generic/028: + +[ 1722.589204] CIFS VFS: \\192.168.30.26 Cancelling wait for mid 72064 cmd: 5 +[ 1722.590687] CIFS VFS: \\192.168.30.26 Cancelling wait for mid 72065 cmd: 17 +[ 1722.593529] CIFS VFS: \\192.168.30.26 Cancelling wait for mid 72066 cmd: 6 +[ 1723.039014] BUG: sleeping function called from invalid context at mm/slab.h:565 +[ 1723.040710] in_atomic(): 1, irqs_disabled(): 0, non_block: 0, pid: 30877, name: cifsd +[ 1723.045098] CPU: 3 PID: 30877 Comm: cifsd Not tainted 5.5.0-rc4+ #313 +[ 1723.046256] Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS rel-1.12.0-59-gc9ba527-rebuilt.opensuse.org 04/01/2014 +[ 1723.048221] Call Trace: +[ 1723.048689] dump_stack+0x97/0xe0 +[ 1723.049268] ___might_sleep.cold+0xd1/0xe1 +[ 1723.050069] kmem_cache_alloc_trace+0x204/0x2b0 +[ 1723.051051] __smb2_handle_cancelled_cmd+0x40/0x140 [cifs] +[ 1723.052137] smb2_handle_cancelled_mid+0xf6/0x120 [cifs] +[ 1723.053247] cifs_mid_q_entry_release+0x44d/0x630 [cifs] +[ 1723.054351] ? cifs_reconnect+0x26a/0x1620 [cifs] +[ 1723.055325] cifs_demultiplex_thread+0xad4/0x14a0 [cifs] +[ 1723.056458] ? cifs_handle_standard+0x2c0/0x2c0 [cifs] +[ 1723.057365] ? kvm_sched_clock_read+0x14/0x30 +[ 1723.058197] ? sched_clock+0x5/0x10 +[ 1723.058838] ? sched_clock_cpu+0x18/0x110 +[ 1723.059629] ? lockdep_hardirqs_on+0x17d/0x250 +[ 1723.060456] kthread+0x1ab/0x200 +[ 1723.061149] ? cifs_handle_standard+0x2c0/0x2c0 [cifs] +[ 1723.062078] ? kthread_create_on_node+0xd0/0xd0 +[ 1723.062897] ret_from_fork+0x3a/0x50 + +Signed-off-by: Paulo Alcantara (SUSE) +Fixes: 9150c3adbf24 ("CIFS: Close open handle after interrupted close") +Cc: Stable +Signed-off-by: Steve French +Reviewed-by: Pavel Shilovsky +Acked-by: Paulo Alcantara +--- + fs/cifs/smb2misc.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/fs/cifs/smb2misc.c b/fs/cifs/smb2misc.c +index 0516fc482d43..0511aaf451d4 100644 +--- a/fs/cifs/smb2misc.c ++++ b/fs/cifs/smb2misc.c +@@ -743,7 +743,7 @@ __smb2_handle_cancelled_cmd(struct cifs_tcon *tcon, __u16 cmd, __u64 mid, + { + struct close_cancelled_open *cancelled; + +- cancelled = kzalloc(sizeof(*cancelled), GFP_KERNEL); ++ cancelled = kzalloc(sizeof(*cancelled), GFP_ATOMIC); + if (!cancelled) + return -ENOMEM; + +-- +2.25.1 + + diff --git a/patches.suse/cifs-Fix-mode-output-in-debugging-statements.patch b/patches.suse/cifs-Fix-mode-output-in-debugging-statements.patch new file mode 100644 index 0000000..732d8c1 --- /dev/null +++ b/patches.suse/cifs-Fix-mode-output-in-debugging-statements.patch @@ -0,0 +1,71 @@ +From: Frank Sorenson +Date: Wed, 12 Feb 2020 15:31:48 -0600 +Subject: [PATCH] cifs: Fix mode output in debugging statements +Git-commit: f52aa79df43c4509146140de0241bc21a4a3b4c7 +References: bsc#1144333 +Patch-mainline: v5.6-rc2 + +A number of the debug statements output file or directory mode +in hex. Change these to print using octal. + +Signed-off-by: Frank Sorenson +Signed-off-by: Steve French +Acked-by: Paulo Alcantara +--- + fs/cifs/cifsacl.c | 4 ++-- + fs/cifs/connect.c | 2 +- + fs/cifs/inode.c | 2 +- + 3 files changed, 4 insertions(+), 4 deletions(-) + +diff --git a/fs/cifs/cifsacl.c b/fs/cifs/cifsacl.c +index 440828afcdde..716574aab3b6 100644 +--- a/fs/cifs/cifsacl.c ++++ b/fs/cifs/cifsacl.c +@@ -601,7 +601,7 @@ static void access_flags_to_mode(__le32 ace_flags, int type, umode_t *pmode, + ((flags & FILE_EXEC_RIGHTS) == FILE_EXEC_RIGHTS)) + *pmode |= (S_IXUGO & (*pbits_to_set)); + +- cifs_dbg(NOISY, "access flags 0x%x mode now 0x%x\n", flags, *pmode); ++ cifs_dbg(NOISY, "access flags 0x%x mode now %04o\n", flags, *pmode); + return; + } + +@@ -630,7 +630,7 @@ static void mode_to_access_flags(umode_t mode, umode_t bits_to_use, + if (mode & S_IXUGO) + *pace_flags |= SET_FILE_EXEC_RIGHTS; + +- cifs_dbg(NOISY, "mode: 0x%x, access flags now 0x%x\n", ++ cifs_dbg(NOISY, "mode: %04o, access flags now 0x%x\n", + mode, *pace_flags); + return; + } +diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c +index a941ac7a659d..4804d1df8c1c 100644 +--- a/fs/cifs/connect.c ++++ b/fs/cifs/connect.c +@@ -4151,7 +4151,7 @@ int cifs_setup_cifs_sb(struct smb_vol *pvolume_info, + cifs_sb->mnt_gid = pvolume_info->linux_gid; + cifs_sb->mnt_file_mode = pvolume_info->file_mode; + cifs_sb->mnt_dir_mode = pvolume_info->dir_mode; +- cifs_dbg(FYI, "file mode: 0x%hx dir mode: 0x%hx\n", ++ cifs_dbg(FYI, "file mode: %04ho dir mode: %04ho\n", + cifs_sb->mnt_file_mode, cifs_sb->mnt_dir_mode); + + cifs_sb->actimeo = pvolume_info->actimeo; +diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c +index 9ba623b601ec..b5e6635c578e 100644 +--- a/fs/cifs/inode.c ++++ b/fs/cifs/inode.c +@@ -1648,7 +1648,7 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, umode_t mode) + struct TCP_Server_Info *server; + char *full_path; + +- cifs_dbg(FYI, "In cifs_mkdir, mode = 0x%hx inode = 0x%p\n", ++ cifs_dbg(FYI, "In cifs_mkdir, mode = %04ho inode = 0x%p\n", + mode, inode); + + cifs_sb = CIFS_SB(inode->i_sb); +-- +2.25.1 + + diff --git a/patches.suse/cifs-Fix-mount-options-set-in-automount.patch b/patches.suse/cifs-Fix-mount-options-set-in-automount.patch index 1dcb904..b839247 100644 --- a/patches.suse/cifs-Fix-mount-options-set-in-automount.patch +++ b/patches.suse/cifs-Fix-mount-options-set-in-automount.patch @@ -1,9 +1,9 @@ -From d9a7498aef445922d915399666669d8bf7cee0d6 Mon Sep 17 00:00:00 2001 From: "Paulo Alcantara (SUSE)" -Date: Wed, 8 Jan 2020 12:46:01 -0300 +Date: Thu, 9 Jan 2020 10:03:19 -0300 Subject: [PATCH] cifs: Fix mount options set in automount -Patch-mainline: Not yet, submitted upstream +Git-commit: 5739375ee4230980166807d347cc21c305532bbc References: bsc#1144333 +Patch-mainline: v5.6-rc1 Starting from 4a367dc04435, we must set the mount options based on the DFS full path rather than the resolved target, that is, cifs_mount() @@ -15,6 +15,7 @@ Reported-by: Martijn de Gouw Fixes: 4a367dc04435 ("cifs: Add support for failover in cifs_mount()") Link: https://lore.kernel.org/linux-cifs/39643d7d-2abb-14d3-ced6-c394fab9a777@prodrive-technologies.com Tested-by: Martijn de Gouw +Signed-off-by: Steve French Acked-by: Paulo Alcantara --- fs/cifs/cifs_dfs_ref.c | 97 +++++++++++++++++++----------------------- @@ -208,5 +209,6 @@ index 41957b82d796..606f26d862dc 100644 kfree(root_path); free_full_path: -- -2.24.1 +2.25.1 + diff --git a/patches.suse/cifs-Fix-potential-deadlock-when-updating-vol-in-cifs_reconnect-.patch b/patches.suse/cifs-Fix-potential-deadlock-when-updating-vol-in-cifs_reconnect-.patch new file mode 100644 index 0000000..148afc8 --- /dev/null +++ b/patches.suse/cifs-Fix-potential-deadlock-when-updating-vol-in-cifs_reconnect-.patch @@ -0,0 +1,271 @@ +From: "Paulo Alcantara (SUSE)" +Date: Wed, 4 Dec 2019 17:38:02 -0300 +Subject: [PATCH] cifs: Fix potential deadlock when updating vol in + cifs_reconnect() +Git-commit: 06d57378bcc9b2c33640945174842115593795d1 +References: bsc#1144333 +Patch-mainline: v5.6-rc1 + +We can't acquire volume lock while refreshing the DFS cache because +cifs_reconnect() may call dfs_cache_update_vol() while we are walking +through the volume list. + +To prevent that, make vol_info refcounted, create a temp list with all +volumes eligible for refreshing, and then use it without any locks +held. + +Besides, replace vol_lock with a spinlock and protect cache_ttl from +concurrent accesses or changes. + +Signed-off-by: Paulo Alcantara (SUSE) +Signed-off-by: Steve French +Acked-by: Paulo Alcantara +--- + fs/cifs/dfs_cache.c | 109 +++++++++++++++++++++++++++++++------------- + 1 file changed, 77 insertions(+), 32 deletions(-) + +diff --git a/fs/cifs/dfs_cache.c b/fs/cifs/dfs_cache.c +index 1d1f7c03931b..82c5d9a31f9e 100644 +--- a/fs/cifs/dfs_cache.c ++++ b/fs/cifs/dfs_cache.c +@@ -49,15 +49,20 @@ struct cache_entry { + + struct vol_info { + char *fullpath; ++ spinlock_t smb_vol_lock; + struct smb_vol smb_vol; + char *mntdata; + struct list_head list; ++ struct list_head rlist; ++ struct kref refcnt; + }; + + static struct kmem_cache *cache_slab __read_mostly; + static struct workqueue_struct *dfscache_wq __read_mostly; + + static int cache_ttl; ++static DEFINE_SPINLOCK(cache_ttl_lock); ++ + static struct nls_table *cache_nlsc; + + /* +@@ -69,7 +74,7 @@ static struct hlist_head cache_htable[CACHE_HTABLE_SIZE]; + static DEFINE_MUTEX(list_lock); + + static LIST_HEAD(vol_list); +-static DEFINE_MUTEX(vol_lock); ++static DEFINE_SPINLOCK(vol_list_lock); + + static void refresh_cache_worker(struct work_struct *work); + +@@ -300,7 +305,6 @@ int dfs_cache_init(void) + for (i = 0; i < CACHE_HTABLE_SIZE; i++) + INIT_HLIST_HEAD(&cache_htable[i]); + +- cache_ttl = -1; + cache_nlsc = load_nls_default(); + + cifs_dbg(FYI, "%s: initialized DFS referral cache\n", __func__); +@@ -471,15 +475,15 @@ add_cache_entry(unsigned int hash, const char *path, + + hlist_add_head_rcu(&ce->hlist, &cache_htable[hash]); + +- mutex_lock(&vol_lock); +- if (cache_ttl < 0) { ++ spin_lock(&cache_ttl_lock); ++ if (!cache_ttl) { + cache_ttl = ce->ttl; + queue_delayed_work(dfscache_wq, &refresh_task, cache_ttl * HZ); + } else { + cache_ttl = min_t(int, cache_ttl, ce->ttl); + mod_delayed_work(dfscache_wq, &refresh_task, cache_ttl * HZ); + } +- mutex_unlock(&vol_lock); ++ spin_unlock(&cache_ttl_lock); + + return ce; + } +@@ -523,21 +527,32 @@ static inline void destroy_slab_cache(void) + kmem_cache_destroy(cache_slab); + } + +-static inline void free_vol(struct vol_info *vi) ++static void __vol_release(struct vol_info *vi) + { +- list_del(&vi->list); + kfree(vi->fullpath); + kfree(vi->mntdata); + cifs_cleanup_volume_info_contents(&vi->smb_vol); + kfree(vi); + } + ++static void vol_release(struct kref *kref) ++{ ++ struct vol_info *vi = container_of(kref, struct vol_info, refcnt); ++ ++ spin_lock(&vol_list_lock); ++ list_del(&vi->list); ++ spin_unlock(&vol_list_lock); ++ __vol_release(vi); ++} ++ + static inline void free_vol_list(void) + { + struct vol_info *vi, *nvi; + +- list_for_each_entry_safe(vi, nvi, &vol_list, list) +- free_vol(vi); ++ list_for_each_entry_safe(vi, nvi, &vol_list, list) { ++ list_del_init(&vi->list); ++ __vol_release(vi); ++ } + } + + /** +@@ -1156,10 +1171,13 @@ int dfs_cache_add_vol(char *mntdata, struct smb_vol *vol, const char *fullpath) + goto err_free_fullpath; + + vi->mntdata = mntdata; ++ spin_lock_init(&vi->smb_vol_lock); ++ kref_init(&vi->refcnt); + +- mutex_lock(&vol_lock); ++ spin_lock(&vol_list_lock); + list_add_tail(&vi->list, &vol_list); +- mutex_unlock(&vol_lock); ++ spin_unlock(&vol_list_lock); ++ + return 0; + + err_free_fullpath: +@@ -1169,7 +1187,8 @@ int dfs_cache_add_vol(char *mntdata, struct smb_vol *vol, const char *fullpath) + return rc; + } + +-static inline struct vol_info *find_vol(const char *fullpath) ++/* Must be called with vol_list_lock held */ ++static struct vol_info *find_vol(const char *fullpath) + { + struct vol_info *vi; + +@@ -1191,7 +1210,6 @@ static inline struct vol_info *find_vol(const char *fullpath) + */ + int dfs_cache_update_vol(const char *fullpath, struct TCP_Server_Info *server) + { +- int rc; + struct vol_info *vi; + + if (!fullpath || !server) +@@ -1199,22 +1217,24 @@ int dfs_cache_update_vol(const char *fullpath, struct TCP_Server_Info *server) + + cifs_dbg(FYI, "%s: fullpath: %s\n", __func__, fullpath); + +- mutex_lock(&vol_lock); +- ++ spin_lock(&vol_list_lock); + vi = find_vol(fullpath); + if (IS_ERR(vi)) { +- rc = PTR_ERR(vi); +- goto out; ++ spin_unlock(&vol_list_lock); ++ return PTR_ERR(vi); + } ++ kref_get(&vi->refcnt); ++ spin_unlock(&vol_list_lock); + + cifs_dbg(FYI, "%s: updating volume info\n", __func__); ++ spin_lock(&vi->smb_vol_lock); + memcpy(&vi->smb_vol.dstaddr, &server->dstaddr, + sizeof(vi->smb_vol.dstaddr)); +- rc = 0; ++ spin_unlock(&vi->smb_vol_lock); + +-out: +- mutex_unlock(&vol_lock); +- return rc; ++ kref_put(&vi->refcnt, vol_release); ++ ++ return 0; + } + + /** +@@ -1231,11 +1251,11 @@ void dfs_cache_del_vol(const char *fullpath) + + cifs_dbg(FYI, "%s: fullpath: %s\n", __func__, fullpath); + +- mutex_lock(&vol_lock); ++ spin_lock(&vol_list_lock); + vi = find_vol(fullpath); +- if (!IS_ERR(vi)) +- free_vol(vi); +- mutex_unlock(&vol_lock); ++ spin_unlock(&vol_list_lock); ++ ++ kref_put(&vi->refcnt, vol_release); + } + + /* Get all tcons that are within a DFS namespace and can be refreshed */ +@@ -1449,27 +1469,52 @@ static void refresh_tcon(struct vol_info *vi, struct cifs_tcon *tcon) + */ + static void refresh_cache_worker(struct work_struct *work) + { +- struct vol_info *vi; ++ struct vol_info *vi, *nvi; + struct TCP_Server_Info *server; +- LIST_HEAD(list); ++ LIST_HEAD(vols); ++ LIST_HEAD(tcons); + struct cifs_tcon *tcon, *ntcon; + +- mutex_lock(&vol_lock); +- ++ /* ++ * Find SMB volumes that are eligible (server->tcpStatus == CifsGood) ++ * for refreshing. ++ */ ++ spin_lock(&vol_list_lock); + list_for_each_entry(vi, &vol_list, list) { + server = get_tcp_server(&vi->smb_vol); + if (!server) + continue; + +- get_tcons(server, &list); +- list_for_each_entry_safe(tcon, ntcon, &list, ulist) { ++ kref_get(&vi->refcnt); ++ list_add_tail(&vi->rlist, &vols); ++ put_tcp_server(server); ++ } ++ spin_unlock(&vol_list_lock); ++ ++ /* Walk through all TCONs and refresh any expired cache entry */ ++ list_for_each_entry_safe(vi, nvi, &vols, rlist) { ++ spin_lock(&vi->smb_vol_lock); ++ server = get_tcp_server(&vi->smb_vol); ++ spin_unlock(&vi->smb_vol_lock); ++ ++ if (!server) ++ goto next_vol; ++ ++ get_tcons(server, &tcons); ++ list_for_each_entry_safe(tcon, ntcon, &tcons, ulist) { + refresh_tcon(vi, tcon); + list_del_init(&tcon->ulist); + cifs_put_tcon(tcon); + } + + put_tcp_server(server); ++ ++next_vol: ++ list_del_init(&vi->rlist); ++ kref_put(&vi->refcnt, vol_release); + } ++ ++ spin_lock(&cache_ttl_lock); + queue_delayed_work(dfscache_wq, &refresh_task, cache_ttl * HZ); +- mutex_unlock(&vol_lock); ++ spin_unlock(&cache_ttl_lock); + } +-- +2.25.1 + + diff --git a/patches.suse/cifs-Fix-return-value-in-__update_cache_entry.patch b/patches.suse/cifs-Fix-return-value-in-__update_cache_entry.patch new file mode 100644 index 0000000..50be95a --- /dev/null +++ b/patches.suse/cifs-Fix-return-value-in-__update_cache_entry.patch @@ -0,0 +1,35 @@ +From: YueHaibing +Date: Fri, 17 Jan 2020 10:21:56 +0800 +Subject: [PATCH] cifs: Fix return value in __update_cache_entry +Git-commit: eecfc57130b5faa11fa5fe556313254c7ecfabed +References: bsc#1144333 +Patch-mainline: v5.6-rc1 + +copy_ref_data() may return error, it should be +returned to upstream caller. + +Fixes: 03535b72873b ("cifs: Avoid doing network I/O while holding cache lock") +Signed-off-by: YueHaibing +Signed-off-by: Steve French +Acked-by: Paulo Alcantara +--- + fs/cifs/dfs_cache.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/fs/cifs/dfs_cache.c b/fs/cifs/dfs_cache.c +index 76ffe12d64f5..2bbfe283fb52 100644 +--- a/fs/cifs/dfs_cache.c ++++ b/fs/cifs/dfs_cache.c +@@ -592,7 +592,7 @@ static int __update_cache_entry(const char *path, + + kfree(th); + +- return 0; ++ return rc; + } + + static int get_dfs_referral(const unsigned int xid, struct cifs_ses *ses, +-- +2.25.1 + + diff --git a/patches.suse/cifs-Fix-use-after-free-bug-in-cifs_reconnect-.patch b/patches.suse/cifs-Fix-use-after-free-bug-in-cifs_reconnect-.patch index f537b07..2d4bc24 100644 --- a/patches.suse/cifs-Fix-use-after-free-bug-in-cifs_reconnect-.patch +++ b/patches.suse/cifs-Fix-use-after-free-bug-in-cifs_reconnect-.patch @@ -202,7 +202,7 @@ Acked-by: Paulo Alcantara + rc = reconn_setup_dfs_targets(cifs_sb, &tgt_list, &tgt_it); if (rc && (rc != -EOPNOTSUPP)) { - cifs_dbg(VFS, "%s: no target servers for DFS failover\n", + cifs_server_dbg(VFS, "%s: no target servers for DFS failover\n", @@ -503,6 +520,10 @@ cifs_reconnect(struct TCP_Server_Info *s /* the demux thread will exit normally next time through the loop */ diff --git a/patches.suse/cifs-Get-rid-of-kstrdup_const-d-paths.patch b/patches.suse/cifs-Get-rid-of-kstrdup_const-d-paths.patch new file mode 100644 index 0000000..499201a --- /dev/null +++ b/patches.suse/cifs-Get-rid-of-kstrdup_const-d-paths.patch @@ -0,0 +1,52 @@ +From: "Paulo Alcantara (SUSE)" +Date: Wed, 4 Dec 2019 17:37:59 -0300 +Subject: [PATCH] cifs: Get rid of kstrdup_const()'d paths +Git-commit: 199c6bdfb04b71d88a7765e08285885fbca60df4 +References: bsc#1144333 +Patch-mainline: v5.6-rc1 + +The DFS cache API is mostly used with heap allocated strings. + +Signed-off-by: Paulo Alcantara (SUSE) +Reviewed-by: Aurelien Aptel +Signed-off-by: Steve French +Acked-by: Paulo Alcantara +--- + fs/cifs/dfs_cache.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/fs/cifs/dfs_cache.c b/fs/cifs/dfs_cache.c +index aed4183840c5..49c5f045270f 100644 +--- a/fs/cifs/dfs_cache.c ++++ b/fs/cifs/dfs_cache.c +@@ -131,7 +131,7 @@ static inline void flush_cache_ent(struct cache_entry *ce) + return; + + hlist_del_init_rcu(&ce->hlist); +- kfree_const(ce->path); ++ kfree(ce->path); + free_tgts(ce); + cache_count--; + call_rcu(&ce->rcu, free_cache_entry); +@@ -420,7 +420,7 @@ static struct cache_entry *alloc_cache_entry(const char *path, + if (!ce) + return ERR_PTR(-ENOMEM); + +- ce->path = kstrdup_const(path, GFP_KERNEL); ++ ce->path = kstrndup(path, strlen(path), GFP_KERNEL); + if (!ce->path) { + kmem_cache_free(cache_slab, ce); + return ERR_PTR(-ENOMEM); +@@ -430,7 +430,7 @@ static struct cache_entry *alloc_cache_entry(const char *path, + + rc = copy_ref_data(refs, numrefs, ce, NULL); + if (rc) { +- kfree_const(ce->path); ++ kfree(ce->path); + kmem_cache_free(cache_slab, ce); + ce = ERR_PTR(rc); + } +-- +2.25.1 + + diff --git a/patches.suse/cifs-Introduce-helpers-for-finding-TCP-connection.patch b/patches.suse/cifs-Introduce-helpers-for-finding-TCP-connection.patch new file mode 100644 index 0000000..6c5978e --- /dev/null +++ b/patches.suse/cifs-Introduce-helpers-for-finding-TCP-connection.patch @@ -0,0 +1,98 @@ +From: "Paulo Alcantara (SUSE)" +Date: Wed, 4 Dec 2019 17:38:00 -0300 +Subject: [PATCH] cifs: Introduce helpers for finding TCP connection +Git-commit: 345c1a4a9e09dc5842b7bbb6728a77910db69c52 +References: bsc#1144333 +Patch-mainline: v5.6-rc1 + +Add helpers for finding TCP connections that are good candidates for +being used by DFS refresh worker. + +Signed-off-by: Paulo Alcantara (SUSE) +Reviewed-by: Aurelien Aptel +Signed-off-by: Steve French +Acked-by: Paulo Alcantara +--- + fs/cifs/dfs_cache.c | 44 +++++++++++++++++++++++++++++++------------- + 1 file changed, 31 insertions(+), 13 deletions(-) + +diff --git a/fs/cifs/dfs_cache.c b/fs/cifs/dfs_cache.c +index 49c5f045270f..e889608e5e13 100644 +--- a/fs/cifs/dfs_cache.c ++++ b/fs/cifs/dfs_cache.c +@@ -1305,6 +1305,30 @@ static char *get_dfs_root(const char *path) + return npath; + } + ++static inline void put_tcp_server(struct TCP_Server_Info *server) ++{ ++ cifs_put_tcp_session(server, 0); ++} ++ ++static struct TCP_Server_Info *get_tcp_server(struct smb_vol *vol) ++{ ++ struct TCP_Server_Info *server; ++ ++ server = cifs_find_tcp_session(vol); ++ if (IS_ERR_OR_NULL(server)) ++ return NULL; ++ ++ spin_lock(&GlobalMid_Lock); ++ if (server->tcpStatus != CifsGood) { ++ spin_unlock(&GlobalMid_Lock); ++ put_tcp_server(server); ++ return NULL; ++ } ++ spin_unlock(&GlobalMid_Lock); ++ ++ return server; ++} ++ + /* Find root SMB session out of a DFS link path */ + static struct cifs_ses *find_root_ses(struct vol_info *vi, + struct cifs_tcon *tcon, +@@ -1347,13 +1371,8 @@ static struct cifs_ses *find_root_ses(struct vol_info *vi, + goto out; + } + +- server = cifs_find_tcp_session(&vol); +- if (IS_ERR_OR_NULL(server)) { +- ses = ERR_PTR(-EHOSTDOWN); +- goto out; +- } +- if (server->tcpStatus != CifsGood) { +- cifs_put_tcp_session(server, 0); ++ server = get_tcp_server(&vol); ++ if (!server) { + ses = ERR_PTR(-EHOSTDOWN); + goto out; + } +@@ -1451,19 +1470,18 @@ static void refresh_cache_worker(struct work_struct *work) + mutex_lock(&vol_lock); + + list_for_each_entry(vi, &vol_list, list) { +- server = cifs_find_tcp_session(&vi->smb_vol); +- if (IS_ERR_OR_NULL(server)) ++ server = get_tcp_server(&vi->smb_vol); ++ if (!server) + continue; +- if (server->tcpStatus != CifsGood) +- goto next; ++ + get_tcons(server, &list); + list_for_each_entry_safe(tcon, ntcon, &list, ulist) { + refresh_tcon(vi, tcon); + list_del_init(&tcon->ulist); + cifs_put_tcon(tcon); + } +-next: +- cifs_put_tcp_session(server, 0); ++ ++ put_tcp_server(server); + } + queue_delayed_work(dfscache_wq, &refresh_task, cache_ttl * HZ); + mutex_unlock(&vol_lock); +-- +2.25.1 + + diff --git a/patches.suse/cifs-Merge-is_path_valid-into-get_normalized_path-.patch b/patches.suse/cifs-Merge-is_path_valid-into-get_normalized_path-.patch new file mode 100644 index 0000000..e57fabc --- /dev/null +++ b/patches.suse/cifs-Merge-is_path_valid-into-get_normalized_path-.patch @@ -0,0 +1,90 @@ +From: "Paulo Alcantara (SUSE)" +Date: Wed, 4 Dec 2019 17:38:01 -0300 +Subject: [PATCH] cifs: Merge is_path_valid() into get_normalized_path() +Git-commit: ff2f7fc08268f266372c30a815349749e8499eb5 +References: bsc#1144333 +Patch-mainline: v5.6-rc1 + +Just do the trivial path validation in get_normalized_path(). + +Signed-off-by: Paulo Alcantara (SUSE) +Reviewed-by: Aurelien Aptel +Signed-off-by: Steve French +Acked-by: Paulo Alcantara +--- + fs/cifs/dfs_cache.c | 21 ++++----------------- + 1 file changed, 4 insertions(+), 17 deletions(-) + +diff --git a/fs/cifs/dfs_cache.c b/fs/cifs/dfs_cache.c +index e889608e5e13..1d1f7c03931b 100644 +--- a/fs/cifs/dfs_cache.c ++++ b/fs/cifs/dfs_cache.c +@@ -75,13 +75,11 @@ static void refresh_cache_worker(struct work_struct *work); + + static DECLARE_DELAYED_WORK(refresh_task, refresh_cache_worker); + +-static inline bool is_path_valid(const char *path) ++static int get_normalized_path(const char *path, char **npath) + { +- return path && (strchr(path + 1, '\\') || strchr(path + 1, '/')); +-} ++ if (!path || strlen(path) < 3 || (*path != '\\' && *path != '/')) ++ return -EINVAL; + +-static inline int get_normalized_path(const char *path, char **npath) +-{ + if (*path == '\\') { + *npath = (char *)path; + } else { +@@ -828,9 +826,6 @@ int dfs_cache_find(const unsigned int xid, struct cifs_ses *ses, + char *npath; + struct cache_entry *ce; + +- if (unlikely(!is_path_valid(path))) +- return -EINVAL; +- + rc = get_normalized_path(path, &npath); + if (rc) + return rc; +@@ -875,9 +870,6 @@ int dfs_cache_noreq_find(const char *path, struct dfs_info3_param *ref, + char *npath; + struct cache_entry *ce; + +- if (unlikely(!is_path_valid(path))) +- return -EINVAL; +- + rc = get_normalized_path(path, &npath); + if (rc) + return rc; +@@ -929,9 +921,6 @@ int dfs_cache_update_tgthint(const unsigned int xid, struct cifs_ses *ses, + struct cache_entry *ce; + struct cache_dfs_tgt *t; + +- if (unlikely(!is_path_valid(path))) +- return -EINVAL; +- + rc = get_normalized_path(path, &npath); + if (rc) + return rc; +@@ -989,7 +978,7 @@ int dfs_cache_noreq_update_tgthint(const char *path, + struct cache_entry *ce; + struct cache_dfs_tgt *t; + +- if (unlikely(!is_path_valid(path)) || !it) ++ if (!it) + return -EINVAL; + + rc = get_normalized_path(path, &npath); +@@ -1049,8 +1038,6 @@ int dfs_cache_get_tgt_referral(const char *path, + + if (!it || !ref) + return -EINVAL; +- if (unlikely(!is_path_valid(path))) +- return -EINVAL; + + rc = get_normalized_path(path, &npath); + if (rc) +-- +2.25.1 + + diff --git a/patches.suse/cifs-Optimize-readdir-on-reparse-points.patch b/patches.suse/cifs-Optimize-readdir-on-reparse-points.patch new file mode 100644 index 0000000..8bb487b --- /dev/null +++ b/patches.suse/cifs-Optimize-readdir-on-reparse-points.patch @@ -0,0 +1,135 @@ +From: "Paulo Alcantara (SUSE)" +Date: Wed, 18 Dec 2019 18:11:37 -0300 +Subject: [PATCH] cifs: Optimize readdir on reparse points +Git-commit: 046aca3c25fd28da591f59a2dc1a01848e81e0b2 +References: bsc#1144333 +Patch-mainline: v5.5-rc4 + +When listing a directory with thounsands of files and most of them are +reparse points, we simply marked all those dentries for revalidation +and then sending additional (compounded) create/getinfo/close requests +for each of them. + +Instead, upon receiving a response from an SMB2_QUERY_DIRECTORY +(FileIdFullDirectoryInformation) command, the directory entries that +have a file attribute of FILE_ATTRIBUTE_REPARSE_POINT will contain an +EaSize field with a reparse tag in it, so we parse it and mark the +dentry for revalidation only if it is a DFS or a symlink. + +Signed-off-by: Paulo Alcantara (SUSE) +Reviewed-by: Pavel Shilovsky +Signed-off-by: Steve French +Acked-by: Paulo Alcantara +--- + fs/cifs/cifsglob.h | 1 + fs/cifs/readdir.c | 63 +++++++++++++++++++++++++++++++++++++++++++++-------- + 2 files changed, 55 insertions(+), 9 deletions(-) + +--- a/fs/cifs/cifsglob.h ++++ b/fs/cifs/cifsglob.h +@@ -1647,6 +1647,7 @@ struct cifs_fattr { + struct timespec cf_atime; + struct timespec cf_mtime; + struct timespec cf_ctime; ++ u32 cf_cifstag; + }; + + static inline void free_dfs_info_param(struct dfs_info3_param *param) +--- a/fs/cifs/readdir.c ++++ b/fs/cifs/readdir.c +@@ -139,6 +139,28 @@ retry: + dput(dentry); + } + ++static bool reparse_file_needs_reval(const struct cifs_fattr *fattr) ++{ ++ if (!(fattr->cf_cifsattrs & ATTR_REPARSE)) ++ return false; ++ /* ++ * The DFS tags should be only intepreted by server side as per ++ * MS-FSCC 2.1.2.1, but let's include them anyway. ++ * ++ * Besides, if cf_cifstag is unset (0), then we still need it to be ++ * revalidated to know exactly what reparse point it is. ++ */ ++ switch (fattr->cf_cifstag) { ++ case IO_REPARSE_TAG_DFS: ++ case IO_REPARSE_TAG_DFSR: ++ case IO_REPARSE_TAG_SYMLINK: ++ case IO_REPARSE_TAG_NFS: ++ case 0: ++ return true; ++ } ++ return false; ++} ++ + static void + cifs_fill_common_info(struct cifs_fattr *fattr, struct cifs_sb_info *cifs_sb) + { +@@ -158,7 +180,7 @@ cifs_fill_common_info(struct cifs_fattr + * is a symbolic link, DFS referral or a reparse point with a direct + * access like junctions, deduplicated files, NFS symlinks. + */ +- if (fattr->cf_cifsattrs & ATTR_REPARSE) ++ if (reparse_file_needs_reval(fattr)) + fattr->cf_flags |= CIFS_FATTR_NEED_REVAL; + + /* non-unix readdir doesn't provide nlink */ +@@ -194,19 +216,37 @@ cifs_fill_common_info(struct cifs_fattr + } + } + ++static void __dir_info_to_fattr(struct cifs_fattr *fattr, const void *info) ++{ ++ const FILE_DIRECTORY_INFO *fi = info; ++ ++ memset(fattr, 0, sizeof(*fattr)); ++ fattr->cf_cifsattrs = le32_to_cpu(fi->ExtFileAttributes); ++ fattr->cf_eof = le64_to_cpu(fi->EndOfFile); ++ fattr->cf_bytes = le64_to_cpu(fi->AllocationSize); ++ fattr->cf_createtime = le64_to_cpu(fi->CreationTime); ++ fattr->cf_atime = cifs_NTtimeToUnix(fi->LastAccessTime); ++ fattr->cf_ctime = cifs_NTtimeToUnix(fi->ChangeTime); ++ fattr->cf_mtime = cifs_NTtimeToUnix(fi->LastWriteTime); ++} ++ + void + cifs_dir_info_to_fattr(struct cifs_fattr *fattr, FILE_DIRECTORY_INFO *info, + struct cifs_sb_info *cifs_sb) + { +- memset(fattr, 0, sizeof(*fattr)); +- fattr->cf_cifsattrs = le32_to_cpu(info->ExtFileAttributes); +- fattr->cf_eof = le64_to_cpu(info->EndOfFile); +- fattr->cf_bytes = le64_to_cpu(info->AllocationSize); +- fattr->cf_createtime = le64_to_cpu(info->CreationTime); +- fattr->cf_atime = cifs_NTtimeToUnix(info->LastAccessTime); +- fattr->cf_ctime = cifs_NTtimeToUnix(info->ChangeTime); +- fattr->cf_mtime = cifs_NTtimeToUnix(info->LastWriteTime); ++ __dir_info_to_fattr(fattr, info); ++ cifs_fill_common_info(fattr, cifs_sb); ++} + ++static void cifs_fulldir_info_to_fattr(struct cifs_fattr *fattr, ++ SEARCH_ID_FULL_DIR_INFO *info, ++ struct cifs_sb_info *cifs_sb) ++{ ++ __dir_info_to_fattr(fattr, info); ++ ++ /* See MS-FSCC 2.4.18 FileIdFullDirectoryInformation */ ++ if (fattr->cf_cifsattrs & ATTR_REPARSE) ++ fattr->cf_cifstag = le32_to_cpu(info->EaSize); + cifs_fill_common_info(fattr, cifs_sb); + } + +@@ -755,6 +795,11 @@ static int cifs_filldir(char *find_entry + (FIND_FILE_STANDARD_INFO *)find_entry, + cifs_sb); + break; ++ case SMB_FIND_FILE_ID_FULL_DIR_INFO: ++ cifs_fulldir_info_to_fattr(&fattr, ++ (SEARCH_ID_FULL_DIR_INFO *)find_entry, ++ cifs_sb); ++ break; + default: + cifs_dir_info_to_fattr(&fattr, + (FILE_DIRECTORY_INFO *)find_entry, diff --git a/patches.suse/cifs-Use-define-in-cifs_dbg.patch b/patches.suse/cifs-Use-define-in-cifs_dbg.patch new file mode 100644 index 0000000..1ef1695 --- /dev/null +++ b/patches.suse/cifs-Use-define-in-cifs_dbg.patch @@ -0,0 +1,36 @@ +From: Joe Perches +Date: Fri, 21 Feb 2020 05:20:45 -0800 +Subject: [PATCH] cifs: Use #define in cifs_dbg +Git-commit: fb4b5f13464c468a9c10ae1ab8ba9aa352d0256a +References: bsc#1144333 +Patch-mainline: v5.6-rc4 + +All other uses of cifs_dbg use defines so change this one. + +Signed-off-by: Joe Perches +Reviewed-by: Aurelien Aptel +Signed-off-by: Steve French +Acked-by: Paulo Alcantara +--- + fs/cifs/inode.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c +index 49dbf11e2c3f..1e8a4b1579db 100644 +--- a/fs/cifs/inode.c ++++ b/fs/cifs/inode.c +@@ -653,8 +653,8 @@ cifs_all_info_to_fattr(struct cifs_fattr *fattr, FILE_ALL_INFO *info, + */ + if ((fattr->cf_nlink < 1) && !tcon->unix_ext && + !info->DeletePending) { +- cifs_dbg(1, "bogus file nlink value %u\n", +- fattr->cf_nlink); ++ cifs_dbg(VFS, "bogus file nlink value %u\n", ++ fattr->cf_nlink); + fattr->cf_flags |= CIFS_FATTR_UNKNOWN_NLINK; + } + } +-- +2.25.1 + + diff --git a/patches.suse/cifs-add-SMB2_open-arg-to-return-POSIX-data.patch b/patches.suse/cifs-add-SMB2_open-arg-to-return-POSIX-data.patch new file mode 100644 index 0000000..c939233 --- /dev/null +++ b/patches.suse/cifs-add-SMB2_open-arg-to-return-POSIX-data.patch @@ -0,0 +1,296 @@ +From 4d259af32c05b0ca54bbd54b16cd04726aa9cd49 Mon Sep 17 00:00:00 2001 +From: Aurelien Aptel +Date: Mon, 2 Mar 2020 17:53:22 +0100 +Subject: [PATCH] cifs: add SMB2_open() arg to return POSIX data +Patch-mainline: Not yet, in for-next branch +References: bsc#1144333 + +allows SMB2_open() callers to pass down a POSIX data buffer that will +trigger requesting POSIX create context and parsing the response into +the provided buffer. + +Signed-off-by: Aurelien Aptel +Signed-off-by: Steve French +Acked-by: Paulo Alcantara +--- + fs/cifs/link.c | 4 ++-- + fs/cifs/smb2file.c | 2 +- + fs/cifs/smb2ops.c | 23 ++++++++++++------- + fs/cifs/smb2pdu.c | 55 ++++++++++++++++++++++++++++++++------------- + fs/cifs/smb2pdu.h | 12 +++++----- + fs/cifs/smb2proto.h | 5 ++++- + 6 files changed, 66 insertions(+), 35 deletions(-) + +diff --git a/fs/cifs/link.c b/fs/cifs/link.c +index 852aa00ec729..a25ef35b023e 100644 +--- a/fs/cifs/link.c ++++ b/fs/cifs/link.c +@@ -416,7 +416,7 @@ smb3_query_mf_symlink(unsigned int xid, struct cifs_tcon *tcon, + } + + rc = SMB2_open(xid, &oparms, utf16_path, &oplock, pfile_info, NULL, +- NULL); ++ NULL, NULL); + if (rc) + goto qmf_out_open_fail; + +@@ -470,7 +470,7 @@ smb3_create_mf_symlink(unsigned int xid, struct cifs_tcon *tcon, + oparms.reconnect = false; + + rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, NULL, +- NULL); ++ NULL, NULL); + if (rc) { + kfree(utf16_path); + return rc; +diff --git a/fs/cifs/smb2file.c b/fs/cifs/smb2file.c +index afe1f03aabe3..0a19d6d8e1cc 100644 +--- a/fs/cifs/smb2file.c ++++ b/fs/cifs/smb2file.c +@@ -62,7 +62,7 @@ smb2_open_file(const unsigned int xid, struct cifs_open_parms *oparms, + smb2_oplock = SMB2_OPLOCK_LEVEL_BATCH; + + rc = SMB2_open(xid, oparms, smb2_path, &smb2_oplock, smb2_data, NULL, +- NULL); ++ NULL, NULL); + if (rc) + goto out; + +diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c +index 5fa34225a99b..076bedb261d5 100644 +--- a/fs/cifs/smb2ops.c ++++ b/fs/cifs/smb2ops.c +@@ -794,7 +794,8 @@ int open_shroot(unsigned int xid, struct cifs_tcon *tcon, + tcon->crfid.has_lease = true; + smb2_parse_contexts(server, o_rsp, + &oparms.fid->epoch, +- oparms.fid->lease_key, &oplock, NULL); ++ oparms.fid->lease_key, &oplock, ++ NULL, NULL); + } else + goto oshr_exit; + +@@ -838,7 +839,7 @@ smb3_qfs_tcon(const unsigned int xid, struct cifs_tcon *tcon, + + if (no_cached_open) + rc = SMB2_open(xid, &oparms, &srch_path, &oplock, NULL, NULL, +- NULL); ++ NULL, NULL); + else + rc = open_shroot(xid, tcon, cifs_sb, &fid); + +@@ -878,7 +879,8 @@ smb2_qfs_tcon(const unsigned int xid, struct cifs_tcon *tcon, + oparms.fid = &fid; + oparms.reconnect = false; + +- rc = SMB2_open(xid, &oparms, &srch_path, &oplock, NULL, NULL, NULL); ++ rc = SMB2_open(xid, &oparms, &srch_path, &oplock, NULL, NULL, ++ NULL, NULL); + if (rc) + return; + +@@ -913,7 +915,8 @@ smb2_is_path_accessible(const unsigned int xid, struct cifs_tcon *tcon, + oparms.fid = &fid; + oparms.reconnect = false; + +- rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, NULL, NULL); ++ rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, NULL, NULL, ++ NULL); + if (rc) { + kfree(utf16_path); + return rc; +@@ -2122,7 +2125,8 @@ smb3_notify(const unsigned int xid, struct file *pfile, + oparms.fid = &fid; + oparms.reconnect = false; + +- rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, NULL, NULL); ++ rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, NULL, NULL, ++ NULL); + if (rc) + goto notify_exit; + +@@ -2541,7 +2545,8 @@ smb311_queryfs(const unsigned int xid, struct cifs_tcon *tcon, + oparms.fid = &fid; + oparms.reconnect = false; + +- rc = SMB2_open(xid, &oparms, &srch_path, &oplock, NULL, NULL, NULL); ++ rc = SMB2_open(xid, &oparms, &srch_path, &oplock, NULL, NULL, ++ NULL, NULL); + if (rc) + return rc; + +@@ -3026,7 +3031,8 @@ get_smb2_acl_by_path(struct cifs_sb_info *cifs_sb, + oparms.fid = &fid; + oparms.reconnect = false; + +- rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, NULL, NULL); ++ rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL,NULL, NULL, ++ NULL); + kfree(utf16_path); + if (!rc) { + rc = SMB2_query_acl(xid, tlink_tcon(tlink), fid.persistent_fid, +@@ -3084,7 +3090,8 @@ set_smb2_acl(struct cifs_ntsd *pnntsd, __u32 acllen, + oparms.fid = &fid; + oparms.reconnect = false; + +- rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, NULL, NULL); ++ rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, NULL, ++ NULL, NULL); + kfree(utf16_path); + if (!rc) { + rc = SMB2_set_acl(xid, tlink_tcon(tlink), fid.persistent_fid, +diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c +index 7356017a0821..47d3e382ecaa 100644 +--- a/fs/cifs/smb2pdu.c ++++ b/fs/cifs/smb2pdu.c +@@ -1951,25 +1951,46 @@ parse_query_id_ctxt(struct create_context *cc, struct smb2_file_all_info *buf) + } + + static void +-parse_posix_ctxt(struct create_context *cc, struct smb2_file_all_info *info) ++parse_posix_ctxt(struct create_context *cc, struct smb2_file_all_info *info, ++ struct create_posix_rsp *posix) + { +- /* struct create_posix_rsp *posix = (struct create_posix_rsp *)cc; */ ++ int sid_len; ++ u8 *beg = (u8 *)cc + le16_to_cpu(cc->DataOffset); ++ u8 *end = beg + le32_to_cpu(cc->DataLength); ++ u8 *sid; + +- /* +- * TODO: Need to add parsing for the context and return. Can +- * smb2_file_all_info hold POSIX data? Need to change the +- * passed type from SMB2_open. +- */ +- printk_once(KERN_WARNING +- "SMB3 3.11 POSIX response context not completed yet\n"); ++ memset(posix, 0, sizeof(*posix)); + ++ posix->nlink = le32_to_cpu(*(__le32 *)(beg + 0)); ++ posix->reparse_tag = le32_to_cpu(*(__le32 *)(beg + 4)); ++ posix->mode = le32_to_cpu(*(__le32 *)(beg + 8)); ++ ++ sid = beg + 12; ++ sid_len = posix_info_sid_size(sid, end); ++ if (sid_len < 0) { ++ cifs_dbg(VFS, "bad owner sid in posix create response\n"); ++ return; ++ } ++ memcpy(&posix->owner, sid, sid_len); ++ ++ sid = sid + sid_len; ++ sid_len = posix_info_sid_size(sid, end); ++ if (sid_len < 0) { ++ cifs_dbg(VFS, "bad group sid in posix create response\n"); ++ return; ++ } ++ memcpy(&posix->group, sid, sid_len); ++ ++ cifs_dbg(FYI, "nlink=%d mode=%o reparse_tag=%x\n", ++ posix->nlink, posix->mode, posix->reparse_tag); + } + + void + smb2_parse_contexts(struct TCP_Server_Info *server, +- struct smb2_create_rsp *rsp, +- unsigned int *epoch, char *lease_key, __u8 *oplock, +- struct smb2_file_all_info *buf) ++ struct smb2_create_rsp *rsp, ++ unsigned int *epoch, char *lease_key, __u8 *oplock, ++ struct smb2_file_all_info *buf, ++ struct create_posix_rsp *posix) + { + char *data_offset; + struct create_context *cc; +@@ -1999,8 +2020,9 @@ smb2_parse_contexts(struct TCP_Server_Info *server, + strncmp(name, SMB2_CREATE_QUERY_ON_DISK_ID, 4) == 0) + parse_query_id_ctxt(cc, buf); + else if ((le16_to_cpu(cc->NameLength) == 16)) { +- if (memcmp(name, smb3_create_tag_posix, 16) == 0) +- parse_posix_ctxt(cc, buf); ++ if (posix && ++ memcmp(name, smb3_create_tag_posix, 16) == 0) ++ parse_posix_ctxt(cc, buf, posix); + } + /* else { + cifs_dbg(FYI, "Context not matched with len %d\n", +@@ -2725,6 +2747,7 @@ SMB2_open_free(struct smb_rqst *rqst) + int + SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms, __le16 *path, + __u8 *oplock, struct smb2_file_all_info *buf, ++ struct create_posix_rsp *posix, + struct kvec *err_iov, int *buftype) + { + struct smb_rqst rqst; +@@ -2803,7 +2826,7 @@ SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms, __le16 *path, + + + smb2_parse_contexts(server, rsp, &oparms->fid->epoch, +- oparms->fid->lease_key, oplock, buf); ++ oparms->fid->lease_key, oplock, buf, posix); + creat_exit: + SMB2_open_free(&rqst); + free_rsp_buf(resp_buftype, rsp); +@@ -4302,7 +4325,7 @@ SMB2_write(const unsigned int xid, struct cifs_io_parms *io_parms, + return rc; + } + +-static int posix_info_sid_size(const void *beg, const void *end) ++int posix_info_sid_size(const void *beg, const void *end) + { + size_t subauth; + int total; +diff --git a/fs/cifs/smb2pdu.h b/fs/cifs/smb2pdu.h +index 700311978523..ad14b8505b4d 100644 +--- a/fs/cifs/smb2pdu.h ++++ b/fs/cifs/smb2pdu.h +@@ -1605,13 +1605,11 @@ extern char smb2_padding[7]; + + /* equivalent of the contents of SMB3.1.1 POSIX open context response */ + struct create_posix_rsp { +- __le32 nlink; +- __le32 reparse_tag; +- __le32 mode; +- /* +- * var sized owner SID +- * var sized group SID +- */ ++ u32 nlink; ++ u32 reparse_tag; ++ u32 mode; ++ struct cifs_sid owner; /* var-sized on the wire */ ++ struct cifs_sid group; /* var-sized on the wire */ + } __packed; + + /* +diff --git a/fs/cifs/smb2proto.h b/fs/cifs/smb2proto.h +index c0f0801e7e8e..4d1ff7b66fdc 100644 +--- a/fs/cifs/smb2proto.h ++++ b/fs/cifs/smb2proto.h +@@ -139,6 +139,7 @@ extern int SMB2_tdis(const unsigned int xid, struct cifs_tcon *tcon); + extern int SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms, + __le16 *path, __u8 *oplock, + struct smb2_file_all_info *buf, ++ struct create_posix_rsp *posix, + struct kvec *err_iov, int *resp_buftype); + extern int SMB2_open_init(struct cifs_tcon *tcon, struct smb_rqst *rqst, + __u8 *oplock, struct cifs_open_parms *oparms, +@@ -252,7 +253,8 @@ extern enum securityEnum smb2_select_sectype(struct TCP_Server_Info *, + extern void smb2_parse_contexts(struct TCP_Server_Info *server, + struct smb2_create_rsp *rsp, + unsigned int *epoch, char *lease_key, +- __u8 *oplock, struct smb2_file_all_info *buf); ++ __u8 *oplock, struct smb2_file_all_info *buf, ++ struct create_posix_rsp *posix); + extern int smb3_encryption_required(const struct cifs_tcon *tcon); + extern int smb2_validate_iov(unsigned int offset, unsigned int buffer_length, + struct kvec *iov, unsigned int min_buf_size); +@@ -274,4 +276,5 @@ extern int smb2_query_info_compound(const unsigned int xid, + struct cifs_sb_info *cifs_sb); + int posix_info_parse(const void *beg, const void *end, + struct smb2_posix_info_parsed *out); ++int posix_info_sid_size(const void *beg, const void *end); + #endif /* _SMB2PROTO_H */ +-- +2.25.1 + diff --git a/patches.suse/cifs-add-SMB3-change-notification-support.patch b/patches.suse/cifs-add-SMB3-change-notification-support.patch new file mode 100644 index 0000000..761e5e1 --- /dev/null +++ b/patches.suse/cifs-add-SMB3-change-notification-support.patch @@ -0,0 +1,212 @@ +From: Steve French +Date: Thu, 6 Feb 2020 06:00:14 -0600 +Subject: [PATCH] cifs: add SMB3 change notification support +Git-commit: d26c2ddd33569667e3eeb577c4c1d966ca9192e2 +References: bsc#1144333 +Patch-mainline: v5.6-rc1 + +A commonly used SMB3 feature is change notification, allowing an +app to be notified about changes to a directory. The SMB3 +Notify request blocks until the server detects a change to that +directory or its contents that matches the completion flags +that were passed in and the "watch_tree" flag (which indicates +whether subdirectories under this directory should be also +included). See MS-SMB2 2.2.35 for additional detail. + +To use this simply pass in the following structure to ioctl: + + struct __attribute__((__packed__)) smb3_notify { + uint32_t completion_filter; + bool watch_tree; + } __packed; + + using CIFS_IOC_NOTIFY 0x4005cf09 + or equivalently _IOW(CIFS_IOCTL_MAGIC, 9, struct smb3_notify) + +SMB3 change notification is supported by all major servers. +The ioctl will block until the server detects a change to that +directory or its subdirectories (if watch_tree is set). + +Signed-off-by: Steve French +Reviewed-by: Aurelien Aptel +Acked-by: Paulo Alcantara (SUSE) +Acked-by: Paulo Alcantara +--- + fs/cifs/cifs_ioctl.h | 6 +++++ + fs/cifs/cifsglob.h | 2 ++ + fs/cifs/ioctl.c | 16 ++++++++++++ + fs/cifs/smb2ops.c | 62 ++++++++++++++++++++++++++++++++++++++++++++ + fs/cifs/smb2pdu.c | 1 + + 5 files changed, 87 insertions(+) + +diff --git a/fs/cifs/cifs_ioctl.h b/fs/cifs/cifs_ioctl.h +index 0f0dc1c1fe41..153d5c842a9b 100644 +--- a/fs/cifs/cifs_ioctl.h ++++ b/fs/cifs/cifs_ioctl.h +@@ -65,6 +65,11 @@ struct smb3_key_debug_info { + __u8 smb3decryptionkey[SMB3_SIGN_KEY_SIZE]; + } __packed; + ++struct smb3_notify { ++ __u32 completion_filter; ++ bool watch_tree; ++} __packed; ++ + #define CIFS_IOCTL_MAGIC 0xCF + #define CIFS_IOC_COPYCHUNK_FILE _IOW(CIFS_IOCTL_MAGIC, 3, int) + #define CIFS_IOC_SET_INTEGRITY _IO(CIFS_IOCTL_MAGIC, 4) +@@ -72,3 +77,4 @@ struct smb3_key_debug_info { + #define CIFS_ENUMERATE_SNAPSHOTS _IOR(CIFS_IOCTL_MAGIC, 6, struct smb_snapshot_array) + #define CIFS_QUERY_INFO _IOWR(CIFS_IOCTL_MAGIC, 7, struct smb_query_info) + #define CIFS_DUMP_KEY _IOWR(CIFS_IOCTL_MAGIC, 8, struct smb3_key_debug_info) ++#define CIFS_IOC_NOTIFY _IOW(CIFS_IOCTL_MAGIC, 9, struct smb3_notify) +diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h +index 1205041fd966..de82cfa44b1a 100644 +--- a/fs/cifs/cifsglob.h ++++ b/fs/cifs/cifsglob.h +@@ -431,6 +431,8 @@ struct smb_version_operations { + struct cifsFileInfo *src_file); + int (*enum_snapshots)(const unsigned int xid, struct cifs_tcon *tcon, + struct cifsFileInfo *src_file, void __user *); ++ int (*notify)(const unsigned int xid, struct file *pfile, ++ void __user *pbuf); + int (*query_mf_symlink)(unsigned int, struct cifs_tcon *, + struct cifs_sb_info *, const unsigned char *, + char *, unsigned int *); +diff --git a/fs/cifs/ioctl.c b/fs/cifs/ioctl.c +index e4c935026d5e..4a73e63c4d43 100644 +--- a/fs/cifs/ioctl.c ++++ b/fs/cifs/ioctl.c +@@ -169,6 +169,7 @@ long cifs_ioctl(struct file *filep, unsigned int command, unsigned long arg) + unsigned int xid; + struct cifsFileInfo *pSMBFile = filep->private_data; + struct cifs_tcon *tcon; ++ struct cifs_sb_info *cifs_sb; + __u64 ExtAttrBits = 0; + __u64 caps; + +@@ -299,6 +300,21 @@ long cifs_ioctl(struct file *filep, unsigned int command, unsigned long arg) + else + rc = 0; + break; ++ case CIFS_IOC_NOTIFY: ++ if (!S_ISDIR(inode->i_mode)) { ++ /* Notify can only be done on directories */ ++ rc = -EOPNOTSUPP; ++ break; ++ } ++ cifs_sb = CIFS_SB(inode->i_sb); ++ tcon = tlink_tcon(cifs_sb_tlink(cifs_sb)); ++ if (tcon && tcon->ses->server->ops->notify) { ++ rc = tcon->ses->server->ops->notify(xid, ++ filep, (void __user *)arg); ++ cifs_dbg(FYI, "ioctl notify rc %d\n", rc); ++ } else ++ rc = -EOPNOTSUPP; ++ break; + default: + cifs_dbg(FYI, "unsupported ioctl\n"); + break; +diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c +index ac6628e28b12..baa825f4cec0 100644 +--- a/fs/cifs/smb2ops.c ++++ b/fs/cifs/smb2ops.c +@@ -2045,6 +2045,66 @@ smb3_enum_snapshots(const unsigned int xid, struct cifs_tcon *tcon, + return rc; + } + ++ ++ ++static int ++smb3_notify(const unsigned int xid, struct file *pfile, ++ void __user *ioc_buf) ++{ ++ struct smb3_notify notify; ++ struct dentry *dentry = pfile->f_path.dentry; ++ struct inode *inode = file_inode(pfile); ++ struct cifs_sb_info *cifs_sb; ++ struct cifs_open_parms oparms; ++ struct cifs_fid fid; ++ struct cifs_tcon *tcon; ++ unsigned char *path = NULL; ++ __le16 *utf16_path = NULL; ++ u8 oplock = SMB2_OPLOCK_LEVEL_NONE; ++ int rc = 0; ++ ++ path = build_path_from_dentry(dentry); ++ if (path == NULL) ++ return -ENOMEM; ++ ++ cifs_sb = CIFS_SB(inode->i_sb); ++ ++ utf16_path = cifs_convert_path_to_utf16(path + 1, cifs_sb); ++ if (utf16_path == NULL) { ++ rc = -ENOMEM; ++ goto notify_exit; ++ } ++ ++ if (copy_from_user(¬ify, ioc_buf, sizeof(struct smb3_notify))) { ++ rc = -EFAULT; ++ goto notify_exit; ++ } ++ ++ tcon = cifs_sb_master_tcon(cifs_sb); ++ oparms.tcon = tcon; ++ oparms.desired_access = FILE_READ_ATTRIBUTES; ++ oparms.disposition = FILE_OPEN; ++ oparms.create_options = cifs_create_options(cifs_sb, 0); ++ oparms.fid = &fid; ++ oparms.reconnect = false; ++ ++ rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, NULL, NULL); ++ if (rc) ++ goto notify_exit; ++ ++ rc = SMB2_change_notify(xid, tcon, fid.persistent_fid, fid.volatile_fid, ++ notify.watch_tree, notify.completion_filter); ++ ++ SMB2_close(xid, tcon, fid.persistent_fid, fid.volatile_fid); ++ ++ cifs_dbg(FYI, "change notify for path %s rc %d\n", path, rc); ++ ++notify_exit: ++ kfree(path); ++ kfree(utf16_path); ++ return rc; ++} ++ + static int + smb2_query_dir_first(const unsigned int xid, struct cifs_tcon *tcon, + const char *path, struct cifs_sb_info *cifs_sb, +@@ -4841,6 +4901,7 @@ struct smb_version_operations smb30_operations = { + .dir_needs_close = smb2_dir_needs_close, + .fallocate = smb3_fallocate, + .enum_snapshots = smb3_enum_snapshots, ++ .notify = smb3_notify, + .init_transform_rq = smb3_init_transform_rq, + .is_transform_hdr = smb3_is_transform_hdr, + .receive_transform = smb3_receive_transform, +@@ -4951,6 +5012,7 @@ struct smb_version_operations smb311_operations = { + .dir_needs_close = smb2_dir_needs_close, + .fallocate = smb3_fallocate, + .enum_snapshots = smb3_enum_snapshots, ++ .notify = smb3_notify, + .init_transform_rq = smb3_init_transform_rq, + .is_transform_hdr = smb3_is_transform_hdr, + .receive_transform = smb3_receive_transform, +diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c +index 1a732ff71de4..47cce0bd1afe 100644 +--- a/fs/cifs/smb2pdu.c ++++ b/fs/cifs/smb2pdu.c +@@ -3363,6 +3363,7 @@ SMB2_notify_init(const unsigned int xid, struct smb_rqst *rqst, + + req->PersistentFileId = persistent_fid; + req->VolatileFileId = volatile_fid; ++ /* See note 354 of MS-SMB2, 64K max */ + req->OutputBufferLength = + cpu_to_le32(SMB2_MAX_BUFFER_SIZE - MAX_SMB2_HDR_SIZE); + req->CompletionFilter = cpu_to_le32(completion_filter); +-- +2.25.1 + + diff --git a/patches.suse/cifs-add-a-debug-macro-that-prints-server-share-for-errors.patch b/patches.suse/cifs-add-a-debug-macro-that-prints-server-share-for-errors.patch new file mode 100644 index 0000000..b760111 --- /dev/null +++ b/patches.suse/cifs-add-a-debug-macro-that-prints-server-share-for-errors.patch @@ -0,0 +1,472 @@ +From: Ronnie Sahlberg +Date: Wed, 4 Sep 2019 12:32:41 +1000 +Subject: [PATCH] cifs: add a debug macro that prints \\server\share for errors +Git-commit: 3175eb9b577e82b44a25ad2d515ec9418ae06c04 +References: bsc#1144333 +Patch-mainline: v5.4-rc1 + +Where we have a tcon available we can log \\server\share as part +of the message. Only do this for the VFS log level. + +Signed-off-by: Ronnie Sahlberg +Signed-off-by: Steve French +Acked-by: Paulo Alcantara +--- + fs/cifs/cifs_debug.h | 50 ++++++++++++++++++++++++++++++++++------ + fs/cifs/smb2ops.c | 54 ++++++++++++++++++++++---------------------- + fs/cifs/smb2pdu.c | 28 +++++++++++------------ + fs/cifs/transport.c | 4 ++-- + 4 files changed, 86 insertions(+), 50 deletions(-) + +diff --git a/fs/cifs/cifs_debug.h b/fs/cifs/cifs_debug.h +index 567af916f103..100b0056a369 100644 +--- a/fs/cifs/cifs_debug.h ++++ b/fs/cifs/cifs_debug.h +@@ -82,15 +82,18 @@ do { \ + + #define cifs_server_dbg_func(ratefunc, type, fmt, ...) \ + do { \ ++ const char *sn = ""; \ ++ if (server && server->hostname) \ ++ sn = server->hostname; \ + if ((type) & FYI && cifsFYI & CIFS_INFO) { \ +- pr_debug_ ## ratefunc("%s: Server:%s " fmt, \ +- __FILE__, server->hostname, ##__VA_ARGS__);\ ++ pr_debug_ ## ratefunc("%s: \\\\%s " fmt, \ ++ __FILE__, sn, ##__VA_ARGS__); \ + } else if ((type) & VFS) { \ +- pr_err_ ## ratefunc("CIFS VFS: Server:%s " fmt, \ +- server->hostname, ##__VA_ARGS__); \ ++ pr_err_ ## ratefunc("CIFS VFS: \\\\%s " fmt, \ ++ sn, ##__VA_ARGS__); \ + } else if ((type) & NOISY && (NOISY != 0)) { \ +- pr_debug_ ## ratefunc("Server:%s " fmt, \ +- server->hostname, ##__VA_ARGS__); \ ++ pr_debug_ ## ratefunc("\\\\%s " fmt, \ ++ sn, ##__VA_ARGS__); \ + } \ + } while (0) + +@@ -104,6 +107,33 @@ do { \ + type, fmt, ##__VA_ARGS__); \ + } while (0) + ++#define cifs_tcon_dbg_func(ratefunc, type, fmt, ...) \ ++do { \ ++ const char *tn = ""; \ ++ if (tcon && tcon->treeName) \ ++ tn = tcon->treeName; \ ++ if ((type) & FYI && cifsFYI & CIFS_INFO) { \ ++ pr_debug_ ## ratefunc("%s: %s " fmt, \ ++ __FILE__, tn, ##__VA_ARGS__); \ ++ } else if ((type) & VFS) { \ ++ pr_err_ ## ratefunc("CIFS VFS: %s " fmt, \ ++ tn, ##__VA_ARGS__); \ ++ } else if ((type) & NOISY && (NOISY != 0)) { \ ++ pr_debug_ ## ratefunc("%s " fmt, \ ++ tn, ##__VA_ARGS__); \ ++ } \ ++} while (0) ++ ++#define cifs_tcon_dbg(type, fmt, ...) \ ++do { \ ++ if ((type) & ONCE) \ ++ cifs_tcon_dbg_func(once, \ ++ type, fmt, ##__VA_ARGS__); \ ++ else \ ++ cifs_tcon_dbg_func(ratelimited, \ ++ type, fmt, ##__VA_ARGS__); \ ++} while (0) ++ + /* + * debug OFF + * --------- +@@ -118,10 +148,16 @@ do { \ + #define cifs_server_dbg(type, fmt, ...) \ + do { \ + if (0) \ +- pr_debug("Server:%s " fmt, \ ++ pr_debug("\\\\%s " fmt, \ + server->hostname, ##__VA_ARGS__); \ + } while (0) + ++#define cifs_tcon_dbg(type, fmt, ...) \ ++do { \ ++ if (0) \ ++ pr_debug("%s " fmt, tcon->treeName, ##__VA_ARGS__); \ ++} while (0) ++ + #define cifs_info(fmt, ...) \ + do { \ + pr_info("CIFS: "fmt, ##__VA_ARGS__); \ +diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c +index 070d0b7b21dc..83b02d74d48e 100644 +--- a/fs/cifs/smb2ops.c ++++ b/fs/cifs/smb2ops.c +@@ -109,10 +109,10 @@ smb2_add_credits(struct TCP_Server_Info *server, + /* change_conf hasn't been executed */ + break; + case 0: +- cifs_dbg(VFS, "Possible client or server bug - zero credits\n"); ++ cifs_server_dbg(VFS, "Possible client or server bug - zero credits\n"); + break; + case 1: +- cifs_dbg(VFS, "disabling echoes and oplocks\n"); ++ cifs_server_dbg(VFS, "disabling echoes and oplocks\n"); + break; + case 2: + cifs_dbg(FYI, "disabling oplocks\n"); +@@ -230,7 +230,7 @@ smb2_adjust_credits(struct TCP_Server_Info *server, + + if (server->reconnect_instance != credits->instance) { + spin_unlock(&server->req_lock); +- cifs_dbg(VFS, "trying to return %d credits to old session\n", ++ cifs_server_dbg(VFS, "trying to return %d credits to old session\n", + credits->value - new_val); + return -EAGAIN; + } +@@ -270,7 +270,7 @@ smb2_find_mid(struct TCP_Server_Info *server, char *buf) + __u64 wire_mid = le64_to_cpu(shdr->MessageId); + + if (shdr->ProtocolId == SMB2_TRANSFORM_PROTO_NUM) { +- cifs_dbg(VFS, "Encrypted frame parsing not supported yet\n"); ++ cifs_server_dbg(VFS, "Encrypted frame parsing not supported yet\n"); + return NULL; + } + +@@ -294,10 +294,10 @@ smb2_dump_detail(void *buf, struct TCP_Server_Info *server) + #ifdef CONFIG_CIFS_DEBUG2 + struct smb2_sync_hdr *shdr = (struct smb2_sync_hdr *)buf; + +- cifs_dbg(VFS, "Cmd: %d Err: 0x%x Flags: 0x%x Mid: %llu Pid: %d\n", ++ cifs_server_dbg(VFS, "Cmd: %d Err: 0x%x Flags: 0x%x Mid: %llu Pid: %d\n", + shdr->Command, shdr->Status, shdr->Flags, shdr->MessageId, + shdr->ProcessId); +- cifs_dbg(VFS, "smb buf %p len %u\n", buf, ++ cifs_server_dbg(VFS, "smb buf %p len %u\n", buf, + server->ops->calc_smb_size(buf, server)); + #endif + } +@@ -576,7 +576,7 @@ SMB3_request_interfaces(const unsigned int xid, struct cifs_tcon *tcon) + "server does not support query network interfaces\n"); + goto out; + } else if (rc != 0) { +- cifs_dbg(VFS, "error %d on ioctl to get interface list\n", rc); ++ cifs_tcon_dbg(VFS, "error %d on ioctl to get interface list\n", rc); + goto out; + } + +@@ -1330,11 +1330,11 @@ SMB2_request_res_key(const unsigned int xid, struct cifs_tcon *tcon, + (char **)&res_key, &ret_data_len); + + if (rc) { +- cifs_dbg(VFS, "refcpy ioctl error %d getting resume key\n", rc); ++ cifs_tcon_dbg(VFS, "refcpy ioctl error %d getting resume key\n", rc); + goto req_res_key_exit; + } + if (ret_data_len < sizeof(struct resume_key_req)) { +- cifs_dbg(VFS, "Invalid refcopy resume key length\n"); ++ cifs_tcon_dbg(VFS, "Invalid refcopy resume key length\n"); + rc = -EINVAL; + goto req_res_key_exit; + } +@@ -1486,7 +1486,7 @@ smb2_ioctl_query_info(const unsigned int xid, + qi.input_buffer_length, + qi.output_buffer_length, buffer); + } else { /* unknown flags */ +- cifs_dbg(VFS, "invalid passthru query flags: 0x%x\n", qi.flags); ++ cifs_tcon_dbg(VFS, "invalid passthru query flags: 0x%x\n", qi.flags); + rc = -EINVAL; + } + +@@ -1613,7 +1613,7 @@ smb2_copychunk_range(const unsigned int xid, + if (rc == 0) { + if (ret_data_len != + sizeof(struct copychunk_ioctl_rsp)) { +- cifs_dbg(VFS, "invalid cchunk response size\n"); ++ cifs_tcon_dbg(VFS, "invalid cchunk response size\n"); + rc = -EIO; + goto cchunk_out; + } +@@ -1627,12 +1627,12 @@ smb2_copychunk_range(const unsigned int xid, + */ + if (le32_to_cpu(retbuf->TotalBytesWritten) > + le32_to_cpu(pcchunk->Length)) { +- cifs_dbg(VFS, "invalid copy chunk response\n"); ++ cifs_tcon_dbg(VFS, "invalid copy chunk response\n"); + rc = -EIO; + goto cchunk_out; + } + if (le32_to_cpu(retbuf->ChunksWritten) != 1) { +- cifs_dbg(VFS, "invalid num chunks written\n"); ++ cifs_tcon_dbg(VFS, "invalid num chunks written\n"); + rc = -EIO; + goto cchunk_out; + } +@@ -2422,7 +2422,7 @@ smb2_get_dfs_refer(const unsigned int xid, struct cifs_ses *ses, + + if (rc) { + if ((rc != -ENOENT) && (rc != -EOPNOTSUPP)) +- cifs_dbg(VFS, "ioctl error in %s rc=%d\n", __func__, rc); ++ cifs_tcon_dbg(VFS, "ioctl error in %s rc=%d\n", __func__, rc); + goto out; + } + +@@ -2431,7 +2431,7 @@ smb2_get_dfs_refer(const unsigned int xid, struct cifs_ses *ses, + nls_codepage, remap, search_name, + true /* is_unicode */); + if (rc) { +- cifs_dbg(VFS, "parse error in %s rc=%d\n", __func__, rc); ++ cifs_tcon_dbg(VFS, "parse error in %s rc=%d\n", __func__, rc); + goto out; + } + +@@ -2661,7 +2661,7 @@ smb2_query_symlink(const unsigned int xid, struct cifs_tcon *tcon, + + if (plen + le32_to_cpu(ioctl_rsp->OutputOffset) > + rsp_iov[1].iov_len) { +- cifs_dbg(VFS, "srv returned invalid ioctl len: %d\n", ++ cifs_tcon_dbg(VFS, "srv returned invalid ioctl len: %d\n", + plen); + rc = -EIO; + goto querty_exit; +@@ -3614,14 +3614,14 @@ crypt_message(struct TCP_Server_Info *server, int num_rqst, + + rc = smb2_get_enc_key(server, tr_hdr->SessionId, enc, key); + if (rc) { +- cifs_dbg(VFS, "%s: Could not get %scryption key\n", __func__, ++ cifs_server_dbg(VFS, "%s: Could not get %scryption key\n", __func__, + enc ? "en" : "de"); + return 0; + } + + rc = smb3_crypto_aead_allocate(server); + if (rc) { +- cifs_dbg(VFS, "%s: crypto alloc failed\n", __func__); ++ cifs_server_dbg(VFS, "%s: crypto alloc failed\n", __func__); + return rc; + } + +@@ -3629,19 +3629,19 @@ crypt_message(struct TCP_Server_Info *server, int num_rqst, + server->secmech.ccmaesdecrypt; + rc = crypto_aead_setkey(tfm, key, SMB3_SIGN_KEY_SIZE); + if (rc) { +- cifs_dbg(VFS, "%s: Failed to set aead key %d\n", __func__, rc); ++ cifs_server_dbg(VFS, "%s: Failed to set aead key %d\n", __func__, rc); + return rc; + } + + rc = crypto_aead_setauthsize(tfm, SMB2_SIGNATURE_SIZE); + if (rc) { +- cifs_dbg(VFS, "%s: Failed to set authsize %d\n", __func__, rc); ++ cifs_server_dbg(VFS, "%s: Failed to set authsize %d\n", __func__, rc); + return rc; + } + + req = aead_request_alloc(tfm, GFP_KERNEL); + if (!req) { +- cifs_dbg(VFS, "%s: Failed to alloc aead request\n", __func__); ++ cifs_server_dbg(VFS, "%s: Failed to alloc aead request\n", __func__); + return -ENOMEM; + } + +@@ -3652,7 +3652,7 @@ crypt_message(struct TCP_Server_Info *server, int num_rqst, + + sg = init_sg(num_rqst, rqst, sign); + if (!sg) { +- cifs_dbg(VFS, "%s: Failed to init sg\n", __func__); ++ cifs_server_dbg(VFS, "%s: Failed to init sg\n", __func__); + rc = -ENOMEM; + goto free_req; + } +@@ -3660,7 +3660,7 @@ crypt_message(struct TCP_Server_Info *server, int num_rqst, + iv_len = crypto_aead_ivsize(tfm); + iv = kzalloc(iv_len, GFP_KERNEL); + if (!iv) { +- cifs_dbg(VFS, "%s: Failed to alloc iv\n", __func__); ++ cifs_server_dbg(VFS, "%s: Failed to alloc iv\n", __func__); + rc = -ENOMEM; + goto free_sg; + } +@@ -3902,7 +3902,7 @@ handle_read_data(struct TCP_Server_Info *server, struct mid_q_entry *mid, + bool use_rdma_mr = false; + + if (shdr->Command != SMB2_READ) { +- cifs_dbg(VFS, "only big read responses are supported\n"); ++ cifs_server_dbg(VFS, "only big read responses are supported\n"); + return -ENOTSUPP; + } + +@@ -4148,7 +4148,7 @@ receive_encrypted_standard(struct TCP_Server_Info *server, + } + + if (*num_mids >= MAX_COMPOUND) { +- cifs_dbg(VFS, "too many PDUs in compound\n"); ++ cifs_server_dbg(VFS, "too many PDUs in compound\n"); + return -1; + } + bufs[*num_mids] = buf; +@@ -4194,7 +4194,7 @@ smb3_receive_transform(struct TCP_Server_Info *server, + + if (pdu_length < sizeof(struct smb2_transform_hdr) + + sizeof(struct smb2_sync_hdr)) { +- cifs_dbg(VFS, "Transform message is too small (%u)\n", ++ cifs_server_dbg(VFS, "Transform message is too small (%u)\n", + pdu_length); + cifs_reconnect(server); + wake_up(&server->response_q); +@@ -4202,7 +4202,7 @@ smb3_receive_transform(struct TCP_Server_Info *server, + } + + if (pdu_length < orig_len + sizeof(struct smb2_transform_hdr)) { +- cifs_dbg(VFS, "Transform message is broken\n"); ++ cifs_server_dbg(VFS, "Transform message is broken\n"); + cifs_reconnect(server); + wake_up(&server->response_q); + return -ECONNABORTED; +diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c +index 9a65e517df30..cab696ac68ab 100644 +--- a/fs/cifs/smb2pdu.c ++++ b/fs/cifs/smb2pdu.c +@@ -1019,7 +1019,7 @@ int smb3_validate_negotiate(const unsigned int xid, struct cifs_tcon *tcon) + } + + if (tcon->ses->session_flags & SMB2_SESSION_FLAG_IS_NULL) +- cifs_server_dbg(VFS, "Unexpected null user (anonymous) auth flag sent by server\n"); ++ cifs_tcon_dbg(VFS, "Unexpected null user (anonymous) auth flag sent by server\n"); + + pneg_inbuf = kmalloc(sizeof(*pneg_inbuf), GFP_NOFS); + if (!pneg_inbuf) +@@ -1076,18 +1076,18 @@ int smb3_validate_negotiate(const unsigned int xid, struct cifs_tcon *tcon) + * Old Windows versions or Netapp SMB server can return + * not supported error. Client should accept it. + */ +- cifs_server_dbg(VFS, "Server does not support validate negotiate\n"); ++ cifs_tcon_dbg(VFS, "Server does not support validate negotiate\n"); + rc = 0; + goto out_free_inbuf; + } else if (rc != 0) { +- cifs_server_dbg(VFS, "validate protocol negotiate failed: %d\n", rc); ++ cifs_tcon_dbg(VFS, "validate protocol negotiate failed: %d\n", rc); + rc = -EIO; + goto out_free_inbuf; + } + + rc = -EIO; + if (rsplen != sizeof(*pneg_rsp)) { +- cifs_server_dbg(VFS, "invalid protocol negotiate response size: %d\n", ++ cifs_tcon_dbg(VFS, "invalid protocol negotiate response size: %d\n", + rsplen); + + /* relax check since Mac returns max bufsize allowed on ioctl */ +@@ -1114,7 +1114,7 @@ int smb3_validate_negotiate(const unsigned int xid, struct cifs_tcon *tcon) + goto out_free_rsp; + + vneg_out: +- cifs_server_dbg(VFS, "protocol revalidation - security settings mismatch\n"); ++ cifs_tcon_dbg(VFS, "protocol revalidation - security settings mismatch\n"); + out_free_rsp: + kfree(pneg_rsp); + out_free_inbuf: +@@ -1762,11 +1762,11 @@ SMB2_tcon(const unsigned int xid, struct cifs_ses *ses, const char *tree, + + if ((rsp->Capabilities & SMB2_SHARE_CAP_DFS) && + ((tcon->share_flags & SHI1005_FLAGS_DFS) == 0)) +- cifs_server_dbg(VFS, "DFS capability contradicts DFS flag\n"); ++ cifs_tcon_dbg(VFS, "DFS capability contradicts DFS flag\n"); + + if (tcon->seal && + !(server->capabilities & SMB2_GLOBAL_CAP_ENCRYPTION)) +- cifs_server_dbg(VFS, "Encryption is requested but not supported\n"); ++ cifs_tcon_dbg(VFS, "Encryption is requested but not supported\n"); + + init_copy_chunk_defaults(tcon); + if (server->ops->validate_negotiate) +@@ -1779,7 +1779,7 @@ SMB2_tcon(const unsigned int xid, struct cifs_ses *ses, const char *tree, + + tcon_error_exit: + if (rsp && rsp->sync_hdr.Status == STATUS_BAD_NETWORK_NAME) { +- cifs_server_dbg(VFS, "BAD_NETWORK_NAME: %s\n", tree); ++ cifs_tcon_dbg(VFS, "BAD_NETWORK_NAME: %s\n", tree); + } + goto tcon_exit; + } +@@ -2812,14 +2812,14 @@ SMB2_ioctl(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid, + if (*plen == 0) + goto ioctl_exit; /* server returned no data */ + else if (*plen > rsp_iov.iov_len || *plen > 0xFF00) { +- cifs_server_dbg(VFS, "srv returned invalid ioctl length: %d\n", *plen); ++ cifs_tcon_dbg(VFS, "srv returned invalid ioctl length: %d\n", *plen); + *plen = 0; + rc = -EIO; + goto ioctl_exit; + } + + if (rsp_iov.iov_len - *plen < le32_to_cpu(rsp->OutputOffset)) { +- cifs_server_dbg(VFS, "Malformed ioctl resp: len %d offset %d\n", *plen, ++ cifs_tcon_dbg(VFS, "Malformed ioctl resp: len %d offset %d\n", *plen, + le32_to_cpu(rsp->OutputOffset)); + *plen = 0; + rc = -EIO; +@@ -3110,7 +3110,7 @@ query_info(const unsigned int xid, struct cifs_tcon *tcon, + if (!*data) { + *data = kmalloc(*dlen, GFP_KERNEL); + if (!*data) { +- cifs_server_dbg(VFS, ++ cifs_tcon_dbg(VFS, + "Error %d allocating memory for acl\n", + rc); + *dlen = 0; +@@ -3505,7 +3505,7 @@ smb2_readv_callback(struct mid_q_entry *mid) + + rc = smb2_verify_signature(&rqst, server); + if (rc) +- cifs_server_dbg(VFS, "SMB signature verification returned error = %d\n", ++ cifs_tcon_dbg(VFS, "SMB signature verification returned error = %d\n", + rc); + } + /* FIXME: should this be counted toward the initiating task? */ +@@ -4095,7 +4095,7 @@ SMB2_query_directory(const unsigned int xid, struct cifs_tcon *tcon, + info_buf_size = sizeof(SEARCH_ID_FULL_DIR_INFO) - 1; + break; + default: +- cifs_server_dbg(VFS, "info level %u isn't supported\n", ++ cifs_tcon_dbg(VFS, "info level %u isn't supported\n", + srch_inf->info_level); + rc = -EINVAL; + goto qdir_exit; +@@ -4186,7 +4186,7 @@ SMB2_query_directory(const unsigned int xid, struct cifs_tcon *tcon, + else if (resp_buftype == CIFS_SMALL_BUFFER) + srch_inf->smallBuf = true; + else +- cifs_server_dbg(VFS, "illegal search buffer type\n"); ++ cifs_tcon_dbg(VFS, "illegal search buffer type\n"); + + trace_smb3_query_dir_done(xid, persistent_fid, tcon->tid, + tcon->ses->Suid, index, srch_inf->entries_in_buffer); +diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c +index a90bd4d75b4d..4fccb90492e9 100644 +--- a/fs/cifs/transport.c ++++ b/fs/cifs/transport.c +@@ -1403,7 +1403,7 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifs_tcon *tcon, + use ses->maxReq */ + + if (len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) { +- cifs_server_dbg(VFS, "Illegal length, greater than maximum frame, %d\n", ++ cifs_tcon_dbg(VFS, "Illegal length, greater than maximum frame, %d\n", + len); + return -EIO; + } +@@ -1505,7 +1505,7 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifs_tcon *tcon, + /* rcvd frame is ok */ + if (out_buf == NULL || midQ->mid_state != MID_RESPONSE_RECEIVED) { + rc = -EIO; +- cifs_server_dbg(VFS, "Bad MID state?\n"); ++ cifs_tcon_dbg(VFS, "Bad MID state?\n"); + goto out; + } + +-- +2.25.1 + + diff --git a/patches.suse/cifs-add-missing-mount-option-to-proc-mounts.patch b/patches.suse/cifs-add-missing-mount-option-to-proc-mounts.patch new file mode 100644 index 0000000..b4cf1ff --- /dev/null +++ b/patches.suse/cifs-add-missing-mount-option-to-proc-mounts.patch @@ -0,0 +1,34 @@ +From: Steve French +Date: Wed, 19 Feb 2020 23:59:32 -0600 +Subject: [PATCH] cifs: add missing mount option to /proc/mounts +Git-commit: ec57010acd03428a749d2600bf09bd537eaae993 +References: bsc#1144333 +Patch-mainline: v5.6-rc4 + +We were not displaying the mount option "signloosely" in /proc/mounts +for cifs mounts which some users found confusing recently + +Signed-off-by: Steve French +Reviewed-by: Aurelien Aptel +Acked-by: Paulo Alcantara +--- + fs/cifs/cifsfs.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c +index 46ebaf3f0824..fa77fe5258b0 100644 +--- a/fs/cifs/cifsfs.c ++++ b/fs/cifs/cifsfs.c +@@ -530,6 +530,8 @@ cifs_show_options(struct seq_file *s, struct dentry *root) + + if (tcon->seal) + seq_puts(s, ",seal"); ++ else if (tcon->ses->server->ignore_signature) ++ seq_puts(s, ",signloosely"); + if (tcon->nocase) + seq_puts(s, ",nocase"); + if (tcon->local_lease) +-- +2.25.1 + + diff --git a/patches.suse/cifs-add-new-debugging-macro-cifs_server_dbg.patch b/patches.suse/cifs-add-new-debugging-macro-cifs_server_dbg.patch new file mode 100644 index 0000000..8fd17da --- /dev/null +++ b/patches.suse/cifs-add-new-debugging-macro-cifs_server_dbg.patch @@ -0,0 +1,1235 @@ +From: Ronnie Sahlberg +Date: Wed, 28 Aug 2019 17:15:35 +1000 +Subject: [PATCH] cifs: add new debugging macro cifs_server_dbg +Git-commit: afe6f65353b644f55875d42d812ffe87f1887d68 +References: bsc#1144333 +Patch-mainline: v5.4-rc1 + +which can be used from contexts where we have a TCP_Server_Info *server. +This new macro will prepend the debugging string with "Server: " +which will help when debugging issues on hosts with many cifs connections +to several different servers. + +Convert a bunch of cifs_dbg(VFS) calls to cifs_server_dbg(VFS) + +Signed-off-by: Ronnie Sahlberg +Signed-off-by: Steve French +Acked-by: Paulo Alcantara +--- + fs/cifs/cifs_debug.h | 31 +++++++++++ + fs/cifs/connect.c | 47 ++++++++-------- + fs/cifs/smb2pdu.c | 113 ++++++++++++++++++++------------------- + fs/cifs/smb2transport.c | 61 ++++++++++----------- + fs/cifs/transport.c | 115 +++++++++++++++++++++------------------- + 5 files changed, 204 insertions(+), 163 deletions(-) + +diff --git a/fs/cifs/cifs_debug.h b/fs/cifs/cifs_debug.h +index 3d392620a2f4..567af916f103 100644 +--- a/fs/cifs/cifs_debug.h ++++ b/fs/cifs/cifs_debug.h +@@ -80,6 +80,30 @@ do { \ + type, fmt, ##__VA_ARGS__); \ + } while (0) + ++#define cifs_server_dbg_func(ratefunc, type, fmt, ...) \ ++do { \ ++ if ((type) & FYI && cifsFYI & CIFS_INFO) { \ ++ pr_debug_ ## ratefunc("%s: Server:%s " fmt, \ ++ __FILE__, server->hostname, ##__VA_ARGS__);\ ++ } else if ((type) & VFS) { \ ++ pr_err_ ## ratefunc("CIFS VFS: Server:%s " fmt, \ ++ server->hostname, ##__VA_ARGS__); \ ++ } else if ((type) & NOISY && (NOISY != 0)) { \ ++ pr_debug_ ## ratefunc("Server:%s " fmt, \ ++ server->hostname, ##__VA_ARGS__); \ ++ } \ ++} while (0) ++ ++#define cifs_server_dbg(type, fmt, ...) \ ++do { \ ++ if ((type) & ONCE) \ ++ cifs_server_dbg_func(once, \ ++ type, fmt, ##__VA_ARGS__); \ ++ else \ ++ cifs_server_dbg_func(ratelimited, \ ++ type, fmt, ##__VA_ARGS__); \ ++} while (0) ++ + /* + * debug OFF + * --------- +@@ -91,6 +115,13 @@ do { \ + pr_debug(fmt, ##__VA_ARGS__); \ + } while (0) + ++#define cifs_server_dbg(type, fmt, ...) \ ++do { \ ++ if (0) \ ++ pr_debug("Server:%s " fmt, \ ++ server->hostname, ##__VA_ARGS__); \ ++} while (0) ++ + #define cifs_info(fmt, ...) \ + do { \ + pr_info("CIFS: "fmt, ##__VA_ARGS__); \ +diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c +index 4fe559821aff..1efbbfffddba 100644 +--- a/fs/cifs/connect.c ++++ b/fs/cifs/connect.c +@@ -489,7 +489,7 @@ cifs_reconnect(struct TCP_Server_Info *server) + } else { + rc = reconn_setup_dfs_targets(cifs_sb, &tgt_list, &tgt_it); + if (rc && (rc != -EOPNOTSUPP)) { +- cifs_dbg(VFS, "%s: no target servers for DFS failover\n", ++ cifs_server_dbg(VFS, "%s: no target servers for DFS failover\n", + __func__); + } else { + server->nr_targets = dfs_cache_get_nr_tgts(&tgt_list); +@@ -617,12 +617,12 @@ cifs_reconnect(struct TCP_Server_Info *server) + rc = dfs_cache_noreq_update_tgthint(cifs_sb->origin_fullpath + 1, + tgt_it); + if (rc) { +- cifs_dbg(VFS, "%s: failed to update DFS target hint: rc = %d\n", ++ cifs_server_dbg(VFS, "%s: failed to update DFS target hint: rc = %d\n", + __func__, rc); + } + rc = dfs_cache_update_vol(cifs_sb->origin_fullpath, server); + if (rc) { +- cifs_dbg(VFS, "%s: failed to update vol info in DFS cache: rc = %d\n", ++ cifs_server_dbg(VFS, "%s: failed to update vol info in DFS cache: rc = %d\n", + __func__, rc); + } + dfs_cache_free_tgts(&tgt_list); +@@ -678,7 +678,7 @@ allocate_buffers(struct TCP_Server_Info *server) + if (!server->bigbuf) { + server->bigbuf = (char *)cifs_buf_get(); + if (!server->bigbuf) { +- cifs_dbg(VFS, "No memory for large SMB response\n"); ++ cifs_server_dbg(VFS, "No memory for large SMB response\n"); + msleep(3000); + /* retry will check if exiting */ + return false; +@@ -691,7 +691,7 @@ allocate_buffers(struct TCP_Server_Info *server) + if (!server->smallbuf) { + server->smallbuf = (char *)cifs_small_buf_get(); + if (!server->smallbuf) { +- cifs_dbg(VFS, "No memory for SMB response\n"); ++ cifs_server_dbg(VFS, "No memory for SMB response\n"); + msleep(1000); + /* retry will check if exiting */ + return false; +@@ -722,8 +722,8 @@ server_unresponsive(struct TCP_Server_Info *server) + if ((server->tcpStatus == CifsGood || + server->tcpStatus == CifsNeedNegotiate) && + time_after(jiffies, server->lstrp + 3 * server->echo_interval)) { +- cifs_dbg(VFS, "Server %s has not responded in %lu seconds. Reconnecting...\n", +- server->hostname, (3 * server->echo_interval) / HZ); ++ cifs_server_dbg(VFS, "has not responded in %lu seconds. Reconnecting...\n", ++ (3 * server->echo_interval) / HZ); + cifs_reconnect(server); + wake_up(&server->response_q); + return true; +@@ -861,7 +861,7 @@ is_smb_response(struct TCP_Server_Info *server, unsigned char type) + wake_up(&server->response_q); + break; + default: +- cifs_dbg(VFS, "RFC 1002 unknown response type 0x%x\n", type); ++ cifs_server_dbg(VFS, "RFC 1002 unknown response type 0x%x\n", type); + cifs_reconnect(server); + } + +@@ -1008,7 +1008,7 @@ standard_receive3(struct TCP_Server_Info *server, struct mid_q_entry *mid) + /* make sure this will fit in a large buffer */ + if (pdu_length > CIFSMaxBufSize + MAX_HEADER_SIZE(server) - + server->vals->header_preamble_size) { +- cifs_dbg(VFS, "SMB response too long (%u bytes)\n", pdu_length); ++ cifs_server_dbg(VFS, "SMB response too long (%u bytes)\n", pdu_length); + cifs_reconnect(server); + wake_up(&server->response_q); + return -ECONNABORTED; +@@ -1149,7 +1149,7 @@ cifs_demultiplex_thread(void *p) + /* make sure we have enough to get to the MID */ + if (server->pdu_size < HEADER_SIZE(server) - 1 - + server->vals->header_preamble_size) { +- cifs_dbg(VFS, "SMB response too short (%u bytes)\n", ++ cifs_server_dbg(VFS, "SMB response too short (%u bytes)\n", + server->pdu_size); + cifs_reconnect(server); + wake_up(&server->response_q); +@@ -1222,7 +1222,7 @@ cifs_demultiplex_thread(void *p) + smb2_add_credits_from_hdr(bufs[i], server); + cifs_dbg(FYI, "Received oplock break\n"); + } else { +- cifs_dbg(VFS, "No task to wake, unknown frame " ++ cifs_server_dbg(VFS, "No task to wake, unknown frame " + "received! NumMids %d\n", + atomic_read(&midCount)); + cifs_dump_mem("Received Data is: ", bufs[i], +@@ -2840,16 +2840,17 @@ cifs_setup_ipc(struct cifs_ses *ses, struct smb_vol *volume_info) + struct nls_table *nls_codepage; + char unc[SERVER_NAME_LENGTH + sizeof("//x/IPC$")] = {0}; + bool seal = false; ++ struct TCP_Server_Info *server = ses->server; + + /* + * If the mount request that resulted in the creation of the + * session requires encryption, force IPC to be encrypted too. + */ + if (volume_info->seal) { +- if (ses->server->capabilities & SMB2_GLOBAL_CAP_ENCRYPTION) ++ if (server->capabilities & SMB2_GLOBAL_CAP_ENCRYPTION) + seal = true; + else { +- cifs_dbg(VFS, ++ cifs_server_dbg(VFS, + "IPC: server doesn't support encryption\n"); + return -EOPNOTSUPP; + } +@@ -2859,7 +2860,7 @@ cifs_setup_ipc(struct cifs_ses *ses, struct smb_vol *volume_info) + if (tcon == NULL) + return -ENOMEM; + +- scnprintf(unc, sizeof(unc), "\\\\%s\\IPC$", ses->server->hostname); ++ scnprintf(unc, sizeof(unc), "\\\\%s\\IPC$", server->hostname); + + /* cannot fail */ + nls_codepage = load_nls_default(); +@@ -2868,11 +2869,11 @@ cifs_setup_ipc(struct cifs_ses *ses, struct smb_vol *volume_info) + tcon->ses = ses; + tcon->ipc = true; + tcon->seal = seal; +- rc = ses->server->ops->tree_connect(xid, ses, unc, tcon, nls_codepage); ++ rc = server->ops->tree_connect(xid, ses, unc, tcon, nls_codepage); + free_xid(xid); + + if (rc) { +- cifs_dbg(VFS, "failed to connect to IPC (rc=%d)\n", rc); ++ cifs_server_dbg(VFS, "failed to connect to IPC (rc=%d)\n", rc); + tconInfoFree(tcon); + goto out; + } +@@ -2958,7 +2959,7 @@ void cifs_put_smb_ses(struct cifs_ses *ses) + xid = get_xid(); + rc = server->ops->logoff(xid, ses); + if (rc) +- cifs_dbg(VFS, "%s: Session Logoff failure rc=%d\n", ++ cifs_server_dbg(VFS, "%s: Session Logoff failure rc=%d\n", + __func__, rc); + _free_xid(xid); + } +@@ -3659,10 +3660,10 @@ bind_socket(struct TCP_Server_Info *server) + saddr4 = (struct sockaddr_in *)&server->srcaddr; + saddr6 = (struct sockaddr_in6 *)&server->srcaddr; + if (saddr6->sin6_family == AF_INET6) +- cifs_dbg(VFS, "Failed to bind to: %pI6c, error: %d\n", ++ cifs_server_dbg(VFS, "Failed to bind to: %pI6c, error: %d\n", + &saddr6->sin6_addr, rc); + else +- cifs_dbg(VFS, "Failed to bind to: %pI4, error: %d\n", ++ cifs_server_dbg(VFS, "Failed to bind to: %pI4, error: %d\n", + &saddr4->sin_addr.s_addr, rc); + } + } +@@ -3766,7 +3767,7 @@ generic_ip_connect(struct TCP_Server_Info *server) + rc = __sock_create(cifs_net_ns(server), sfamily, SOCK_STREAM, + IPPROTO_TCP, &socket, 1); + if (rc < 0) { +- cifs_dbg(VFS, "Error %d creating socket\n", rc); ++ cifs_server_dbg(VFS, "Error %d creating socket\n", rc); + server->ssocket = NULL; + return rc; + } +@@ -4150,7 +4151,7 @@ static int mount_get_conns(struct smb_vol *vol, struct cifs_sb_info *cifs_sb, + + if ((vol->persistent == true) && (!(ses->server->capabilities & + SMB2_GLOBAL_CAP_PERSISTENT_HANDLES))) { +- cifs_dbg(VFS, "persistent handles not supported by server\n"); ++ cifs_server_dbg(VFS, "persistent handles not supported by server\n"); + return -EOPNOTSUPP; + } + +@@ -4588,7 +4589,7 @@ static int is_path_remote(struct cifs_sb_info *cifs_sb, struct smb_vol *vol, + rc = cifs_are_all_path_components_accessible(server, xid, tcon, + cifs_sb, full_path, tcon->Flags & SMB_SHARE_IS_IN_DFS); + if (rc != 0) { +- cifs_dbg(VFS, "cannot query dirs between root and final path, " ++ cifs_server_dbg(VFS, "cannot query dirs between root and final path, " + "enabling CIFS_MOUNT_USE_PREFIX_PATH\n"); + cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_USE_PREFIX_PATH; + rc = 0; +@@ -5090,7 +5091,7 @@ cifs_setup_session(const unsigned int xid, struct cifs_ses *ses, + rc = server->ops->sess_setup(xid, ses, nls_info); + + if (rc) +- cifs_dbg(VFS, "Send error in SessSetup = %d\n", rc); ++ cifs_server_dbg(VFS, "Send error in SessSetup = %d\n", rc); + + return rc; + } +diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c +index a33cb91b4963..dbc6ef50dd45 100644 +--- a/fs/cifs/smb2pdu.c ++++ b/fs/cifs/smb2pdu.c +@@ -542,7 +542,7 @@ assemble_neg_contexts(struct smb2_negotiate_req *req, + + if (*total_len > 200) { + /* In case length corrupted don't want to overrun smb buffer */ +- cifs_dbg(VFS, "Bad frame length assembling neg contexts\n"); ++ cifs_server_dbg(VFS, "Bad frame length assembling neg contexts\n"); + return; + } + +@@ -660,7 +660,7 @@ static int smb311_decode_neg_context(struct smb2_negotiate_rsp *rsp, + + cifs_dbg(FYI, "decoding %d negotiate contexts\n", ctxt_cnt); + if (len_of_smb <= offset) { +- cifs_dbg(VFS, "Invalid response: negotiate context offset\n"); ++ cifs_server_dbg(VFS, "Invalid response: negotiate context offset\n"); + return -EINVAL; + } + +@@ -692,7 +692,7 @@ static int smb311_decode_neg_context(struct smb2_negotiate_rsp *rsp, + else if (pctx->ContextType == SMB2_POSIX_EXTENSIONS_AVAILABLE) + server->posix_ext_supported = true; + else +- cifs_dbg(VFS, "unknown negcontext of type %d ignored\n", ++ cifs_server_dbg(VFS, "unknown negcontext of type %d ignored\n", + le16_to_cpu(pctx->ContextType)); + + if (rc) +@@ -817,7 +817,7 @@ SMB2_negotiate(const unsigned int xid, struct cifs_ses *ses) + req->Dialects[1] = cpu_to_le16(SMB302_PROT_ID); + req->DialectCount = cpu_to_le16(2); + total_len += 4; +- } else if (strcmp(ses->server->vals->version_string, ++ } else if (strcmp(server->vals->version_string, + SMBDEFAULT_VERSION_STRING) == 0) { + req->Dialects[0] = cpu_to_le16(SMB21_PROT_ID); + req->Dialects[1] = cpu_to_le16(SMB30_PROT_ID); +@@ -840,16 +840,16 @@ SMB2_negotiate(const unsigned int xid, struct cifs_ses *ses) + else + req->SecurityMode = 0; + +- req->Capabilities = cpu_to_le32(ses->server->vals->req_capabilities); ++ req->Capabilities = cpu_to_le32(server->vals->req_capabilities); + + /* ClientGUID must be zero for SMB2.02 dialect */ +- if (ses->server->vals->protocol_id == SMB20_PROT_ID) ++ if (server->vals->protocol_id == SMB20_PROT_ID) + memset(req->ClientGUID, 0, SMB2_CLIENT_GUID_SIZE); + else { + memcpy(req->ClientGUID, server->client_guid, + SMB2_CLIENT_GUID_SIZE); +- if ((ses->server->vals->protocol_id == SMB311_PROT_ID) || +- (strcmp(ses->server->vals->version_string, ++ if ((server->vals->protocol_id == SMB311_PROT_ID) || ++ (strcmp(server->vals->version_string, + SMBDEFAULT_VERSION_STRING) == 0)) + assemble_neg_contexts(req, server, &total_len); + } +@@ -868,42 +868,42 @@ SMB2_negotiate(const unsigned int xid, struct cifs_ses *ses) + * cifs_stats_inc(&tcon->stats.smb2_stats.smb2_com_fail[SMB2...]); + */ + if (rc == -EOPNOTSUPP) { +- cifs_dbg(VFS, "Dialect not supported by server. Consider " ++ cifs_server_dbg(VFS, "Dialect not supported by server. Consider " + "specifying vers=1.0 or vers=2.0 on mount for accessing" + " older servers\n"); + goto neg_exit; + } else if (rc != 0) + goto neg_exit; + +- if (strcmp(ses->server->vals->version_string, ++ if (strcmp(server->vals->version_string, + SMB3ANY_VERSION_STRING) == 0) { + if (rsp->DialectRevision == cpu_to_le16(SMB20_PROT_ID)) { +- cifs_dbg(VFS, ++ cifs_server_dbg(VFS, + "SMB2 dialect returned but not requested\n"); + return -EIO; + } else if (rsp->DialectRevision == cpu_to_le16(SMB21_PROT_ID)) { +- cifs_dbg(VFS, ++ cifs_server_dbg(VFS, + "SMB2.1 dialect returned but not requested\n"); + return -EIO; + } +- } else if (strcmp(ses->server->vals->version_string, ++ } else if (strcmp(server->vals->version_string, + SMBDEFAULT_VERSION_STRING) == 0) { + if (rsp->DialectRevision == cpu_to_le16(SMB20_PROT_ID)) { +- cifs_dbg(VFS, ++ cifs_server_dbg(VFS, + "SMB2 dialect returned but not requested\n"); + return -EIO; + } else if (rsp->DialectRevision == cpu_to_le16(SMB21_PROT_ID)) { + /* ops set to 3.0 by default for default so update */ +- ses->server->ops = &smb21_operations; +- ses->server->vals = &smb21_values; ++ server->ops = &smb21_operations; ++ server->vals = &smb21_values; + } else if (rsp->DialectRevision == cpu_to_le16(SMB311_PROT_ID)) { +- ses->server->ops = &smb311_operations; +- ses->server->vals = &smb311_values; ++ server->ops = &smb311_operations; ++ server->vals = &smb311_values; + } + } else if (le16_to_cpu(rsp->DialectRevision) != +- ses->server->vals->protocol_id) { ++ server->vals->protocol_id) { + /* if requested single dialect ensure returned dialect matched */ +- cifs_dbg(VFS, "Illegal 0x%x dialect returned: not requested\n", ++ cifs_server_dbg(VFS, "Illegal 0x%x dialect returned: not requested\n", + le16_to_cpu(rsp->DialectRevision)); + return -EIO; + } +@@ -921,7 +921,7 @@ SMB2_negotiate(const unsigned int xid, struct cifs_ses *ses) + else if (rsp->DialectRevision == cpu_to_le16(SMB311_PROT_ID)) + cifs_dbg(FYI, "negotiated smb3.1.1 dialect\n"); + else { +- cifs_dbg(VFS, "Illegal dialect returned by server 0x%x\n", ++ cifs_server_dbg(VFS, "Illegal dialect returned by server 0x%x\n", + le16_to_cpu(rsp->DialectRevision)); + rc = -EIO; + goto neg_exit; +@@ -981,7 +981,7 @@ SMB2_negotiate(const unsigned int xid, struct cifs_ses *ses) + rc = smb311_decode_neg_context(rsp, server, + rsp_iov.iov_len); + else +- cifs_dbg(VFS, "Missing expected negotiate contexts\n"); ++ cifs_server_dbg(VFS, "Missing expected negotiate contexts\n"); + } + neg_exit: + free_rsp_buf(resp_buftype, rsp); +@@ -995,11 +995,12 @@ int smb3_validate_negotiate(const unsigned int xid, struct cifs_tcon *tcon) + struct validate_negotiate_info_rsp *pneg_rsp = NULL; + u32 rsplen; + u32 inbuflen; /* max of 4 dialects */ ++ struct TCP_Server_Info *server = tcon->ses->server; + + cifs_dbg(FYI, "validate negotiate\n"); + + /* In SMB3.11 preauth integrity supersedes validate negotiate */ +- if (tcon->ses->server->dialect == SMB311_PROT_ID) ++ if (server->dialect == SMB311_PROT_ID) + return 0; + + /* +@@ -1018,15 +1019,15 @@ int smb3_validate_negotiate(const unsigned int xid, struct cifs_tcon *tcon) + } + + if (tcon->ses->session_flags & SMB2_SESSION_FLAG_IS_NULL) +- cifs_dbg(VFS, "Unexpected null user (anonymous) auth flag sent by server\n"); ++ cifs_server_dbg(VFS, "Unexpected null user (anonymous) auth flag sent by server\n"); + + pneg_inbuf = kmalloc(sizeof(*pneg_inbuf), GFP_NOFS); + if (!pneg_inbuf) + return -ENOMEM; + + pneg_inbuf->Capabilities = +- cpu_to_le32(tcon->ses->server->vals->req_capabilities); +- memcpy(pneg_inbuf->Guid, tcon->ses->server->client_guid, ++ cpu_to_le32(server->vals->req_capabilities); ++ memcpy(pneg_inbuf->Guid, server->client_guid, + SMB2_CLIENT_GUID_SIZE); + + if (tcon->ses->sign) +@@ -1039,7 +1040,7 @@ int smb3_validate_negotiate(const unsigned int xid, struct cifs_tcon *tcon) + pneg_inbuf->SecurityMode = 0; + + +- if (strcmp(tcon->ses->server->vals->version_string, ++ if (strcmp(server->vals->version_string, + SMB3ANY_VERSION_STRING) == 0) { + pneg_inbuf->Dialects[0] = cpu_to_le16(SMB30_PROT_ID); + pneg_inbuf->Dialects[1] = cpu_to_le16(SMB302_PROT_ID); +@@ -1047,7 +1048,7 @@ int smb3_validate_negotiate(const unsigned int xid, struct cifs_tcon *tcon) + /* structure is big enough for 3 dialects, sending only 2 */ + inbuflen = sizeof(*pneg_inbuf) - + (2 * sizeof(pneg_inbuf->Dialects[0])); +- } else if (strcmp(tcon->ses->server->vals->version_string, ++ } else if (strcmp(server->vals->version_string, + SMBDEFAULT_VERSION_STRING) == 0) { + pneg_inbuf->Dialects[0] = cpu_to_le16(SMB21_PROT_ID); + pneg_inbuf->Dialects[1] = cpu_to_le16(SMB30_PROT_ID); +@@ -1059,7 +1060,7 @@ int smb3_validate_negotiate(const unsigned int xid, struct cifs_tcon *tcon) + } else { + /* otherwise specific dialect was requested */ + pneg_inbuf->Dialects[0] = +- cpu_to_le16(tcon->ses->server->vals->protocol_id); ++ cpu_to_le16(server->vals->protocol_id); + pneg_inbuf->DialectCount = cpu_to_le16(1); + /* structure is big enough for 3 dialects, sending only 1 */ + inbuflen = sizeof(*pneg_inbuf) - +@@ -1075,18 +1076,18 @@ int smb3_validate_negotiate(const unsigned int xid, struct cifs_tcon *tcon) + * Old Windows versions or Netapp SMB server can return + * not supported error. Client should accept it. + */ +- cifs_dbg(VFS, "Server does not support validate negotiate\n"); ++ cifs_server_dbg(VFS, "Server does not support validate negotiate\n"); + rc = 0; + goto out_free_inbuf; + } else if (rc != 0) { +- cifs_dbg(VFS, "validate protocol negotiate failed: %d\n", rc); ++ cifs_server_dbg(VFS, "validate protocol negotiate failed: %d\n", rc); + rc = -EIO; + goto out_free_inbuf; + } + + rc = -EIO; + if (rsplen != sizeof(*pneg_rsp)) { +- cifs_dbg(VFS, "invalid protocol negotiate response size: %d\n", ++ cifs_server_dbg(VFS, "invalid protocol negotiate response size: %d\n", + rsplen); + + /* relax check since Mac returns max bufsize allowed on ioctl */ +@@ -1095,16 +1096,16 @@ int smb3_validate_negotiate(const unsigned int xid, struct cifs_tcon *tcon) + } + + /* check validate negotiate info response matches what we got earlier */ +- if (pneg_rsp->Dialect != cpu_to_le16(tcon->ses->server->dialect)) ++ if (pneg_rsp->Dialect != cpu_to_le16(server->dialect)) + goto vneg_out; + +- if (pneg_rsp->SecurityMode != cpu_to_le16(tcon->ses->server->sec_mode)) ++ if (pneg_rsp->SecurityMode != cpu_to_le16(server->sec_mode)) + goto vneg_out; + + /* do not validate server guid because not saved at negprot time yet */ + + if ((le32_to_cpu(pneg_rsp->Capabilities) | SMB2_NT_FIND | +- SMB2_LARGE_FILES) != tcon->ses->server->capabilities) ++ SMB2_LARGE_FILES) != server->capabilities) + goto vneg_out; + + /* validate negotiate successful */ +@@ -1113,7 +1114,7 @@ int smb3_validate_negotiate(const unsigned int xid, struct cifs_tcon *tcon) + goto out_free_rsp; + + vneg_out: +- cifs_dbg(VFS, "protocol revalidation - security settings mismatch\n"); ++ cifs_server_dbg(VFS, "protocol revalidation - security settings mismatch\n"); + out_free_rsp: + kfree(pneg_rsp); + out_free_inbuf: +@@ -1567,7 +1568,7 @@ SMB2_sess_setup(const unsigned int xid, struct cifs_ses *ses, + sess_data->func(sess_data); + + if ((ses->session_flags & SMB2_SESSION_FLAG_IS_GUEST) && (ses->sign)) +- cifs_dbg(VFS, "signing requested but authenticated as guest\n"); ++ cifs_server_dbg(VFS, "signing requested but authenticated as guest\n"); + rc = sess_data->result; + out: + kfree(sess_data); +@@ -1660,10 +1661,11 @@ SMB2_tcon(const unsigned int xid, struct cifs_ses *ses, const char *tree, + __le16 *unc_path = NULL; + int flags = 0; + unsigned int total_len; ++ struct TCP_Server_Info *server = ses->server; + + cifs_dbg(FYI, "TCON\n"); + +- if (!(ses->server) || !tree) ++ if (!server || !tree) + return -EIO; + + unc_path = kmalloc(MAX_SHARENAME_LENGTH * 2, GFP_KERNEL); +@@ -1706,7 +1708,7 @@ SMB2_tcon(const unsigned int xid, struct cifs_ses *ses, const char *tree, + * unless it is guest or anonymous user. See MS-SMB2 3.2.5.3.1 + * (Samba servers don't always set the flag so also check if null user) + */ +- if ((ses->server->dialect == SMB311_PROT_ID) && ++ if ((server->dialect == SMB311_PROT_ID) && + !smb3_encryption_required(tcon) && + !(ses->session_flags & + (SMB2_SESSION_FLAG_IS_GUEST|SMB2_SESSION_FLAG_IS_NULL)) && +@@ -1745,7 +1747,7 @@ SMB2_tcon(const unsigned int xid, struct cifs_ses *ses, const char *tree, + cifs_dbg(FYI, "connection to printer\n"); + break; + default: +- cifs_dbg(VFS, "unknown share type %d\n", rsp->ShareType); ++ cifs_server_dbg(VFS, "unknown share type %d\n", rsp->ShareType); + rc = -EOPNOTSUPP; + goto tcon_error_exit; + } +@@ -1760,15 +1762,15 @@ SMB2_tcon(const unsigned int xid, struct cifs_ses *ses, const char *tree, + + if ((rsp->Capabilities & SMB2_SHARE_CAP_DFS) && + ((tcon->share_flags & SHI1005_FLAGS_DFS) == 0)) +- cifs_dbg(VFS, "DFS capability contradicts DFS flag\n"); ++ cifs_server_dbg(VFS, "DFS capability contradicts DFS flag\n"); + + if (tcon->seal && +- !(tcon->ses->server->capabilities & SMB2_GLOBAL_CAP_ENCRYPTION)) +- cifs_dbg(VFS, "Encryption is requested but not supported\n"); ++ !(server->capabilities & SMB2_GLOBAL_CAP_ENCRYPTION)) ++ cifs_server_dbg(VFS, "Encryption is requested but not supported\n"); + + init_copy_chunk_defaults(tcon); +- if (tcon->ses->server->ops->validate_negotiate) +- rc = tcon->ses->server->ops->validate_negotiate(xid, tcon); ++ if (server->ops->validate_negotiate) ++ rc = server->ops->validate_negotiate(xid, tcon); + tcon_exit: + + free_rsp_buf(resp_buftype, rsp); +@@ -1777,7 +1779,7 @@ SMB2_tcon(const unsigned int xid, struct cifs_ses *ses, const char *tree, + + tcon_error_exit: + if (rsp && rsp->sync_hdr.Status == STATUS_BAD_NETWORK_NAME) { +- cifs_dbg(VFS, "BAD_NETWORK_NAME: %s\n", tree); ++ cifs_server_dbg(VFS, "BAD_NETWORK_NAME: %s\n", tree); + } + goto tcon_exit; + } +@@ -2741,6 +2743,7 @@ SMB2_ioctl(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid, + int resp_buftype = CIFS_NO_BUFFER; + int rc = 0; + int flags = 0; ++ struct TCP_Server_Info *server; + + cifs_dbg(FYI, "SMB2 IOCTL\n"); + +@@ -2756,7 +2759,8 @@ SMB2_ioctl(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid, + else + return -EIO; + +- if (!ses || !(ses->server)) ++ server = ses->server; ++ if (!ses || !(server)) + return -EIO; + + if (smb3_encryption_required(tcon)) +@@ -2806,14 +2810,14 @@ SMB2_ioctl(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid, + if (*plen == 0) + goto ioctl_exit; /* server returned no data */ + else if (*plen > rsp_iov.iov_len || *plen > 0xFF00) { +- cifs_dbg(VFS, "srv returned invalid ioctl length: %d\n", *plen); ++ cifs_server_dbg(VFS, "srv returned invalid ioctl length: %d\n", *plen); + *plen = 0; + rc = -EIO; + goto ioctl_exit; + } + + if (rsp_iov.iov_len - *plen < le32_to_cpu(rsp->OutputOffset)) { +- cifs_dbg(VFS, "Malformed ioctl resp: len %d offset %d\n", *plen, ++ cifs_server_dbg(VFS, "Malformed ioctl resp: len %d offset %d\n", *plen, + le32_to_cpu(rsp->OutputOffset)); + *plen = 0; + rc = -EIO; +@@ -3054,12 +3058,13 @@ query_info(const unsigned int xid, struct cifs_tcon *tcon, + int rc = 0; + int resp_buftype = CIFS_NO_BUFFER; + struct cifs_ses *ses = tcon->ses; ++ struct TCP_Server_Info *server = ses->server; + int flags = 0; + bool allocated = false; + + cifs_dbg(FYI, "Query Info\n"); + +- if (!ses || !(ses->server)) ++ if (!ses || !(server)) + return -EIO; + + if (smb3_encryption_required(tcon)) +@@ -3097,7 +3102,7 @@ query_info(const unsigned int xid, struct cifs_tcon *tcon, + if (!*data) { + *data = kmalloc(*dlen, GFP_KERNEL); + if (!*data) { +- cifs_dbg(VFS, ++ cifs_server_dbg(VFS, + "Error %d allocating memory for acl\n", + rc); + *dlen = 0; +@@ -3489,7 +3494,7 @@ smb2_readv_callback(struct mid_q_entry *mid) + + rc = smb2_verify_signature(&rqst, server); + if (rc) +- cifs_dbg(VFS, "SMB signature verification returned error = %d\n", ++ cifs_server_dbg(VFS, "SMB signature verification returned error = %d\n", + rc); + } + /* FIXME: should this be counted toward the initiating task? */ +@@ -4079,7 +4084,7 @@ SMB2_query_directory(const unsigned int xid, struct cifs_tcon *tcon, + info_buf_size = sizeof(SEARCH_ID_FULL_DIR_INFO) - 1; + break; + default: +- cifs_dbg(VFS, "info level %u isn't supported\n", ++ cifs_server_dbg(VFS, "info level %u isn't supported\n", + srch_inf->info_level); + rc = -EINVAL; + goto qdir_exit; +@@ -4170,7 +4175,7 @@ SMB2_query_directory(const unsigned int xid, struct cifs_tcon *tcon, + else if (resp_buftype == CIFS_SMALL_BUFFER) + srch_inf->smallBuf = true; + else +- cifs_dbg(VFS, "illegal search buffer type\n"); ++ cifs_server_dbg(VFS, "illegal search buffer type\n"); + + trace_smb3_query_dir_done(xid, persistent_fid, tcon->tid, + tcon->ses->Suid, index, srch_inf->entries_in_buffer); +diff --git a/fs/cifs/smb2transport.c b/fs/cifs/smb2transport.c +index 1ccbcf9c2c3b..b02242eacb55 100644 +--- a/fs/cifs/smb2transport.c ++++ b/fs/cifs/smb2transport.c +@@ -176,7 +176,7 @@ smb2_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server) + + ses = smb2_find_smb_ses(server, shdr->SessionId); + if (!ses) { +- cifs_dbg(VFS, "%s: Could not find session\n", __func__); ++ cifs_server_dbg(VFS, "%s: Could not find session\n", __func__); + return 0; + } + +@@ -185,21 +185,21 @@ smb2_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server) + + rc = smb2_crypto_shash_allocate(server); + if (rc) { +- cifs_dbg(VFS, "%s: sha256 alloc failed\n", __func__); ++ cifs_server_dbg(VFS, "%s: sha256 alloc failed\n", __func__); + return rc; + } + + rc = crypto_shash_setkey(server->secmech.hmacsha256, + ses->auth_key.response, SMB2_NTLMV2_SESSKEY_SIZE); + if (rc) { +- cifs_dbg(VFS, "%s: Could not update with response\n", __func__); ++ cifs_server_dbg(VFS, "%s: Could not update with response\n", __func__); + return rc; + } + + shash = &server->secmech.sdeschmacsha256->shash; + rc = crypto_shash_init(shash); + if (rc) { +- cifs_dbg(VFS, "%s: Could not init sha256", __func__); ++ cifs_server_dbg(VFS, "%s: Could not init sha256", __func__); + return rc; + } + +@@ -215,7 +215,7 @@ smb2_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server) + rc = crypto_shash_update(shash, iov[0].iov_base, + iov[0].iov_len); + if (rc) { +- cifs_dbg(VFS, "%s: Could not update with payload\n", ++ cifs_server_dbg(VFS, "%s: Could not update with payload\n", + __func__); + return rc; + } +@@ -239,68 +239,69 @@ static int generate_key(struct cifs_ses *ses, struct kvec label, + int rc = 0; + unsigned char prfhash[SMB2_HMACSHA256_SIZE]; + unsigned char *hashptr = prfhash; ++ struct TCP_Server_Info *server = ses->server; + + memset(prfhash, 0x0, SMB2_HMACSHA256_SIZE); + memset(key, 0x0, key_size); + +- rc = smb3_crypto_shash_allocate(ses->server); ++ rc = smb3_crypto_shash_allocate(server); + if (rc) { +- cifs_dbg(VFS, "%s: crypto alloc failed\n", __func__); ++ cifs_server_dbg(VFS, "%s: crypto alloc failed\n", __func__); + goto smb3signkey_ret; + } + +- rc = crypto_shash_setkey(ses->server->secmech.hmacsha256, ++ rc = crypto_shash_setkey(server->secmech.hmacsha256, + ses->auth_key.response, SMB2_NTLMV2_SESSKEY_SIZE); + if (rc) { +- cifs_dbg(VFS, "%s: Could not set with session key\n", __func__); ++ cifs_server_dbg(VFS, "%s: Could not set with session key\n", __func__); + goto smb3signkey_ret; + } + +- rc = crypto_shash_init(&ses->server->secmech.sdeschmacsha256->shash); ++ rc = crypto_shash_init(&server->secmech.sdeschmacsha256->shash); + if (rc) { +- cifs_dbg(VFS, "%s: Could not init sign hmac\n", __func__); ++ cifs_server_dbg(VFS, "%s: Could not init sign hmac\n", __func__); + goto smb3signkey_ret; + } + +- rc = crypto_shash_update(&ses->server->secmech.sdeschmacsha256->shash, ++ rc = crypto_shash_update(&server->secmech.sdeschmacsha256->shash, + i, 4); + if (rc) { +- cifs_dbg(VFS, "%s: Could not update with n\n", __func__); ++ cifs_server_dbg(VFS, "%s: Could not update with n\n", __func__); + goto smb3signkey_ret; + } + +- rc = crypto_shash_update(&ses->server->secmech.sdeschmacsha256->shash, ++ rc = crypto_shash_update(&server->secmech.sdeschmacsha256->shash, + label.iov_base, label.iov_len); + if (rc) { +- cifs_dbg(VFS, "%s: Could not update with label\n", __func__); ++ cifs_server_dbg(VFS, "%s: Could not update with label\n", __func__); + goto smb3signkey_ret; + } + +- rc = crypto_shash_update(&ses->server->secmech.sdeschmacsha256->shash, ++ rc = crypto_shash_update(&server->secmech.sdeschmacsha256->shash, + &zero, 1); + if (rc) { +- cifs_dbg(VFS, "%s: Could not update with zero\n", __func__); ++ cifs_server_dbg(VFS, "%s: Could not update with zero\n", __func__); + goto smb3signkey_ret; + } + +- rc = crypto_shash_update(&ses->server->secmech.sdeschmacsha256->shash, ++ rc = crypto_shash_update(&server->secmech.sdeschmacsha256->shash, + context.iov_base, context.iov_len); + if (rc) { +- cifs_dbg(VFS, "%s: Could not update with context\n", __func__); ++ cifs_server_dbg(VFS, "%s: Could not update with context\n", __func__); + goto smb3signkey_ret; + } + +- rc = crypto_shash_update(&ses->server->secmech.sdeschmacsha256->shash, ++ rc = crypto_shash_update(&server->secmech.sdeschmacsha256->shash, + L, 4); + if (rc) { +- cifs_dbg(VFS, "%s: Could not update with L\n", __func__); ++ cifs_server_dbg(VFS, "%s: Could not update with L\n", __func__); + goto smb3signkey_ret; + } + +- rc = crypto_shash_final(&ses->server->secmech.sdeschmacsha256->shash, ++ rc = crypto_shash_final(&server->secmech.sdeschmacsha256->shash, + hashptr); + if (rc) { +- cifs_dbg(VFS, "%s: Could not generate sha256 hash\n", __func__); ++ cifs_server_dbg(VFS, "%s: Could not generate sha256 hash\n", __func__); + goto smb3signkey_ret; + } + +@@ -436,7 +437,7 @@ smb3_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server) + + ses = smb2_find_smb_ses(server, shdr->SessionId); + if (!ses) { +- cifs_dbg(VFS, "%s: Could not find session\n", __func__); ++ cifs_server_dbg(VFS, "%s: Could not find session\n", __func__); + return 0; + } + +@@ -446,7 +447,7 @@ smb3_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server) + rc = crypto_shash_setkey(server->secmech.cmacaes, + ses->smb3signingkey, SMB2_CMACAES_SIZE); + if (rc) { +- cifs_dbg(VFS, "%s: Could not set key for cmac aes\n", __func__); ++ cifs_server_dbg(VFS, "%s: Could not set key for cmac aes\n", __func__); + return rc; + } + +@@ -457,7 +458,7 @@ smb3_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server) + */ + rc = crypto_shash_init(shash); + if (rc) { +- cifs_dbg(VFS, "%s: Could not init cmac aes\n", __func__); ++ cifs_server_dbg(VFS, "%s: Could not init cmac aes\n", __func__); + return rc; + } + +@@ -473,7 +474,7 @@ smb3_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server) + rc = crypto_shash_update(shash, iov[0].iov_base, + iov[0].iov_len); + if (rc) { +- cifs_dbg(VFS, "%s: Could not update with payload\n", ++ cifs_server_dbg(VFS, "%s: Could not update with payload\n", + __func__); + return rc; + } +@@ -665,7 +666,7 @@ smb2_check_receive(struct mid_q_entry *mid, struct TCP_Server_Info *server, + + rc = smb2_verify_signature(&rqst, server); + if (rc) +- cifs_dbg(VFS, "SMB signature verification returned error = %d\n", ++ cifs_server_dbg(VFS, "SMB signature verification returned error = %d\n", + rc); + } + +@@ -739,7 +740,7 @@ smb3_crypto_aead_allocate(struct TCP_Server_Info *server) + else + tfm = crypto_alloc_aead("ccm(aes)", 0, 0); + if (IS_ERR(tfm)) { +- cifs_dbg(VFS, "%s: Failed to alloc encrypt aead\n", ++ cifs_server_dbg(VFS, "%s: Failed to alloc encrypt aead\n", + __func__); + return PTR_ERR(tfm); + } +@@ -754,7 +755,7 @@ smb3_crypto_aead_allocate(struct TCP_Server_Info *server) + if (IS_ERR(tfm)) { + crypto_free_aead(server->secmech.ccmaesencrypt); + server->secmech.ccmaesencrypt = NULL; +- cifs_dbg(VFS, "%s: Failed to alloc decrypt aead\n", ++ cifs_server_dbg(VFS, "%s: Failed to alloc decrypt aead\n", + __func__); + return PTR_ERR(tfm); + } +diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c +index 5d6d44bfe10a..0d60bd2f4dca 100644 +--- a/fs/cifs/transport.c ++++ b/fs/cifs/transport.c +@@ -118,7 +118,7 @@ DeleteMidQEntry(struct mid_q_entry *midEntry) + #ifdef CONFIG_CIFS_STATS2 + now = jiffies; + if (now < midEntry->when_alloc) +- cifs_dbg(VFS, "invalid mid allocation time\n"); ++ cifs_server_dbg(VFS, "invalid mid allocation time\n"); + roundtrip_time = now - midEntry->when_alloc; + + if (smb_cmd < NUMBER_OF_SMB2_COMMANDS) { +@@ -232,7 +232,7 @@ smb_send_kvec(struct TCP_Server_Info *server, struct msghdr *smb_msg, + retries++; + if (retries >= 14 || + (!server->noblocksnd && (retries > 2))) { +- cifs_dbg(VFS, "sends on sock %p stuck for 15 seconds\n", ++ cifs_server_dbg(VFS, "sends on sock %p stuck for 15 seconds\n", + ssocket); + return -EAGAIN; + } +@@ -246,7 +246,7 @@ smb_send_kvec(struct TCP_Server_Info *server, struct msghdr *smb_msg, + if (rc == 0) { + /* should never happen, letting socket clear before + retrying is our only obvious option here */ +- cifs_dbg(VFS, "tcp sent no data\n"); ++ cifs_server_dbg(VFS, "tcp sent no data\n"); + msleep(500); + continue; + } +@@ -440,7 +440,7 @@ __smb_send_rqst(struct TCP_Server_Info *server, int num_rqst, + } + smbd_done: + if (rc < 0 && rc != -EINTR) +- cifs_dbg(VFS, "Error %d sending data on socket to server\n", ++ cifs_server_dbg(VFS, "Error %d sending data on socket to server\n", + rc); + else if (rc > 0) + rc = 0; +@@ -473,8 +473,8 @@ smb_send_rqst(struct TCP_Server_Info *server, int num_rqst, + cur_rqst[0].rq_nvec = 1; + + if (!server->ops->init_transform_rq) { +- cifs_dbg(VFS, "Encryption requested but transform callback " +- "is missing\n"); ++ cifs_server_dbg(VFS, "Encryption requested but transform " ++ "callback is missing\n"); + return -EIO; + } + +@@ -548,7 +548,7 @@ wait_for_free_credits(struct TCP_Server_Info *server, const int num_credits, + if (!rc) { + trace_smb3_credit_timeout(server->CurrentMid, + server->hostname, num_credits); +- cifs_dbg(VFS, "wait timed out after %d ms\n", ++ cifs_server_dbg(VFS, "wait timed out after %d ms\n", + timeout); + return -ENOTSUPP; + } +@@ -589,7 +589,7 @@ wait_for_free_credits(struct TCP_Server_Info *server, const int num_credits, + trace_smb3_credit_timeout( + server->CurrentMid, + server->hostname, num_credits); +- cifs_dbg(VFS, "wait timed out after %d ms\n", ++ cifs_server_dbg(VFS, "wait timed out after %d ms\n", + timeout); + return -ENOTSUPP; + } +@@ -869,7 +869,7 @@ cifs_sync_mid_result(struct mid_q_entry *mid, struct TCP_Server_Info *server) + break; + default: + list_del_init(&mid->qhead); +- cifs_dbg(VFS, "%s: invalid mid state mid=%llu state=%d\n", ++ cifs_server_dbg(VFS, "%s: invalid mid state mid=%llu state=%d\n", + __func__, mid->mid, mid->mid_state); + rc = -EIO; + } +@@ -910,7 +910,7 @@ cifs_check_receive(struct mid_q_entry *mid, struct TCP_Server_Info *server, + rc = cifs_verify_signature(&rqst, server, + mid->sequence_number); + if (rc) +- cifs_dbg(VFS, "SMB signature verification returned error = %d\n", ++ cifs_server_dbg(VFS, "SMB signature verification returned error = %d\n", + rc); + } + +@@ -1107,7 +1107,7 @@ compound_send_recv(const unsigned int xid, struct cifs_ses *ses, + } + if (rc != 0) { + for (; i < num_rqst; i++) { +- cifs_dbg(VFS, "Cancelling wait for mid %llu cmd: %d\n", ++ cifs_server_dbg(VFS, "Cancelling wait for mid %llu cmd: %d\n", + midQ[i]->mid, le16_to_cpu(midQ[i]->command)); + send_cancel(server, &rqst[i], midQ[i]); + spin_lock(&GlobalMid_Lock); +@@ -1242,17 +1242,18 @@ SendReceive(const unsigned int xid, struct cifs_ses *ses, + struct kvec iov = { .iov_base = in_buf, .iov_len = len }; + struct smb_rqst rqst = { .rq_iov = &iov, .rq_nvec = 1 }; + struct cifs_credits credits = { .value = 1, .instance = 0 }; ++ struct TCP_Server_Info *server = ses->server; + + if (ses == NULL) { + cifs_dbg(VFS, "Null smb session\n"); + return -EIO; + } +- if (ses->server == NULL) { ++ if (server == NULL) { + cifs_dbg(VFS, "Null tcp session\n"); + return -EIO; + } + +- if (ses->server->tcpStatus == CifsExiting) ++ if (server->tcpStatus == CifsExiting) + return -ENOENT; + + /* Ensure that we do not send more than 50 overlapping requests +@@ -1260,12 +1261,12 @@ SendReceive(const unsigned int xid, struct cifs_ses *ses, + use ses->maxReq */ + + if (len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) { +- cifs_dbg(VFS, "Illegal length, greater than maximum frame, %d\n", ++ cifs_server_dbg(VFS, "Illegal length, greater than maximum frame, %d\n", + len); + return -EIO; + } + +- rc = wait_for_free_request(ses->server, flags, &credits.instance); ++ rc = wait_for_free_request(server, flags, &credits.instance); + if (rc) + return rc; + +@@ -1273,70 +1274,70 @@ SendReceive(const unsigned int xid, struct cifs_ses *ses, + and avoid races inside tcp sendmsg code that could cause corruption + of smb data */ + +- mutex_lock(&ses->server->srv_mutex); ++ mutex_lock(&server->srv_mutex); + + rc = allocate_mid(ses, in_buf, &midQ); + if (rc) { + mutex_unlock(&ses->server->srv_mutex); + /* Update # of requests on wire to server */ +- add_credits(ses->server, &credits, 0); ++ add_credits(server, &credits, 0); + return rc; + } + +- rc = cifs_sign_smb(in_buf, ses->server, &midQ->sequence_number); ++ rc = cifs_sign_smb(in_buf, server, &midQ->sequence_number); + if (rc) { +- mutex_unlock(&ses->server->srv_mutex); ++ mutex_unlock(&server->srv_mutex); + goto out; + } + + midQ->mid_state = MID_REQUEST_SUBMITTED; + +- cifs_in_send_inc(ses->server); +- rc = smb_send(ses->server, in_buf, len); +- cifs_in_send_dec(ses->server); ++ cifs_in_send_inc(server); ++ rc = smb_send(server, in_buf, len); ++ cifs_in_send_dec(server); + cifs_save_when_sent(midQ); + + if (rc < 0) +- ses->server->sequence_number -= 2; ++ server->sequence_number -= 2; + +- mutex_unlock(&ses->server->srv_mutex); ++ mutex_unlock(&server->srv_mutex); + + if (rc < 0) + goto out; + +- rc = wait_for_response(ses->server, midQ); ++ rc = wait_for_response(server, midQ); + if (rc != 0) { +- send_cancel(ses->server, &rqst, midQ); ++ send_cancel(server, &rqst, midQ); + spin_lock(&GlobalMid_Lock); + if (midQ->mid_state == MID_REQUEST_SUBMITTED) { + /* no longer considered to be "in-flight" */ + midQ->callback = DeleteMidQEntry; + spin_unlock(&GlobalMid_Lock); +- add_credits(ses->server, &credits, 0); ++ add_credits(server, &credits, 0); + return rc; + } + spin_unlock(&GlobalMid_Lock); + } + +- rc = cifs_sync_mid_result(midQ, ses->server); ++ rc = cifs_sync_mid_result(midQ, server); + if (rc != 0) { +- add_credits(ses->server, &credits, 0); ++ add_credits(server, &credits, 0); + return rc; + } + + if (!midQ->resp_buf || !out_buf || + midQ->mid_state != MID_RESPONSE_RECEIVED) { + rc = -EIO; +- cifs_dbg(VFS, "Bad MID state?\n"); ++ cifs_server_dbg(VFS, "Bad MID state?\n"); + goto out; + } + + *pbytes_returned = get_rfc1002_length(midQ->resp_buf); + memcpy(out_buf, midQ->resp_buf, *pbytes_returned + 4); +- rc = cifs_check_receive(midQ, ses->server, 0); ++ rc = cifs_check_receive(midQ, server, 0); + out: + cifs_delete_mid(midQ); +- add_credits(ses->server, &credits, 0); ++ add_credits(server, &credits, 0); + + return rc; + } +@@ -1379,19 +1380,21 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifs_tcon *tcon, + struct kvec iov = { .iov_base = in_buf, .iov_len = len }; + struct smb_rqst rqst = { .rq_iov = &iov, .rq_nvec = 1 }; + unsigned int instance; ++ struct TCP_Server_Info *server; + + if (tcon == NULL || tcon->ses == NULL) { + cifs_dbg(VFS, "Null smb session\n"); + return -EIO; + } + ses = tcon->ses; ++ server = ses->server; + +- if (ses->server == NULL) { ++ if (server == NULL) { + cifs_dbg(VFS, "Null tcp session\n"); + return -EIO; + } + +- if (ses->server->tcpStatus == CifsExiting) ++ if (server->tcpStatus == CifsExiting) + return -ENOENT; + + /* Ensure that we do not send more than 50 overlapping requests +@@ -1399,12 +1402,12 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifs_tcon *tcon, + use ses->maxReq */ + + if (len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) { +- cifs_dbg(VFS, "Illegal length, greater than maximum frame, %d\n", ++ cifs_server_dbg(VFS, "Illegal length, greater than maximum frame, %d\n", + len); + return -EIO; + } + +- rc = wait_for_free_request(ses->server, CIFS_BLOCKING_OP, &instance); ++ rc = wait_for_free_request(server, CIFS_BLOCKING_OP, &instance); + if (rc) + return rc; + +@@ -1412,31 +1415,31 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifs_tcon *tcon, + and avoid races inside tcp sendmsg code that could cause corruption + of smb data */ + +- mutex_lock(&ses->server->srv_mutex); ++ mutex_lock(&server->srv_mutex); + + rc = allocate_mid(ses, in_buf, &midQ); + if (rc) { +- mutex_unlock(&ses->server->srv_mutex); ++ mutex_unlock(&server->srv_mutex); + return rc; + } + +- rc = cifs_sign_smb(in_buf, ses->server, &midQ->sequence_number); ++ rc = cifs_sign_smb(in_buf, server, &midQ->sequence_number); + if (rc) { + cifs_delete_mid(midQ); +- mutex_unlock(&ses->server->srv_mutex); ++ mutex_unlock(&server->srv_mutex); + return rc; + } + + midQ->mid_state = MID_REQUEST_SUBMITTED; +- cifs_in_send_inc(ses->server); +- rc = smb_send(ses->server, in_buf, len); +- cifs_in_send_dec(ses->server); ++ cifs_in_send_inc(server); ++ rc = smb_send(server, in_buf, len); ++ cifs_in_send_dec(server); + cifs_save_when_sent(midQ); + + if (rc < 0) +- ses->server->sequence_number -= 2; ++ server->sequence_number -= 2; + +- mutex_unlock(&ses->server->srv_mutex); ++ mutex_unlock(&server->srv_mutex); + + if (rc < 0) { + cifs_delete_mid(midQ); +@@ -1444,21 +1447,21 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifs_tcon *tcon, + } + + /* Wait for a reply - allow signals to interrupt. */ +- rc = wait_event_interruptible(ses->server->response_q, ++ rc = wait_event_interruptible(server->response_q, + (!(midQ->mid_state == MID_REQUEST_SUBMITTED)) || +- ((ses->server->tcpStatus != CifsGood) && +- (ses->server->tcpStatus != CifsNew))); ++ ((server->tcpStatus != CifsGood) && ++ (server->tcpStatus != CifsNew))); + + /* Were we interrupted by a signal ? */ + if ((rc == -ERESTARTSYS) && + (midQ->mid_state == MID_REQUEST_SUBMITTED) && +- ((ses->server->tcpStatus == CifsGood) || +- (ses->server->tcpStatus == CifsNew))) { ++ ((server->tcpStatus == CifsGood) || ++ (server->tcpStatus == CifsNew))) { + + if (in_buf->Command == SMB_COM_TRANSACTION2) { + /* POSIX lock. We send a NT_CANCEL SMB to cause the + blocking lock to return. */ +- rc = send_cancel(ses->server, &rqst, midQ); ++ rc = send_cancel(server, &rqst, midQ); + if (rc) { + cifs_delete_mid(midQ); + return rc; +@@ -1477,9 +1480,9 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifs_tcon *tcon, + } + } + +- rc = wait_for_response(ses->server, midQ); ++ rc = wait_for_response(server, midQ); + if (rc) { +- send_cancel(ses->server, &rqst, midQ); ++ send_cancel(server, &rqst, midQ); + spin_lock(&GlobalMid_Lock); + if (midQ->mid_state == MID_REQUEST_SUBMITTED) { + /* no longer considered to be "in-flight" */ +@@ -1494,20 +1497,20 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifs_tcon *tcon, + rstart = 1; + } + +- rc = cifs_sync_mid_result(midQ, ses->server); ++ rc = cifs_sync_mid_result(midQ, server); + if (rc != 0) + return rc; + + /* rcvd frame is ok */ + if (out_buf == NULL || midQ->mid_state != MID_RESPONSE_RECEIVED) { + rc = -EIO; +- cifs_dbg(VFS, "Bad MID state?\n"); ++ cifs_server_dbg(VFS, "Bad MID state?\n"); + goto out; + } + + *pbytes_returned = get_rfc1002_length(midQ->resp_buf); + memcpy(out_buf, midQ->resp_buf, *pbytes_returned + 4); +- rc = cifs_check_receive(midQ, ses->server, 0); ++ rc = cifs_check_receive(midQ, server, 0); + out: + cifs_delete_mid(midQ); + if (rstart && rc == -EACCES) +-- +2.25.1 + + diff --git a/patches.suse/cifs-add-passthrough-for-smb2-setinfo.patch b/patches.suse/cifs-add-passthrough-for-smb2-setinfo.patch new file mode 100644 index 0000000..7c45fe9 --- /dev/null +++ b/patches.suse/cifs-add-passthrough-for-smb2-setinfo.patch @@ -0,0 +1,103 @@ +From: Ronnie Sahlberg +Date: Thu, 25 Jul 2019 13:08:43 +1000 +Subject: [PATCH] cifs: add passthrough for smb2 setinfo +Git-commit: 0e90696dc2b33a2c390242c5b9f330a16ae2ac82 +References: bsc#1144333 +Patch-mainline: v5.4-rc1 + +Add support to send smb2 set-info commands from userspace. + +Signed-off-by: Ronnie Sahlberg +Signed-off-by: Steve French +Reviewed-by: Paulo Alcantara +Acked-by: Paulo Alcantara +--- + fs/cifs/cifs_ioctl.h | 1 + + fs/cifs/smb2ops.c | 29 +++++++++++++++++++++++++---- + 2 files changed, 26 insertions(+), 4 deletions(-) + +diff --git a/fs/cifs/cifs_ioctl.h b/fs/cifs/cifs_ioctl.h +index 086ddc5108af..6c3bd07868d7 100644 +--- a/fs/cifs/cifs_ioctl.h ++++ b/fs/cifs/cifs_ioctl.h +@@ -46,6 +46,7 @@ struct smb_snapshot_array { + /* query_info flags */ + #define PASSTHRU_QUERY_INFO 0x00000000 + #define PASSTHRU_FSCTL 0x00000001 ++#define PASSTHRU_SET_INFO 0x00000002 + struct smb_query_info { + __u32 info_type; + __u32 file_info_class; +diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c +index 64a5864127be..461a68fdff1f 100644 +--- a/fs/cifs/smb2ops.c ++++ b/fs/cifs/smb2ops.c +@@ -1369,7 +1369,10 @@ smb2_ioctl_query_info(const unsigned int xid, + struct cifs_fid fid; + struct kvec qi_iov[1]; + struct kvec io_iov[SMB2_IOCTL_IOV_SIZE]; ++ struct kvec si_iov[SMB2_SET_INFO_IOV_SIZE]; + struct kvec close_iov[1]; ++ unsigned int size[2]; ++ void *data[2]; + + memset(rqst, 0, sizeof(rqst)); + resp_buftype[0] = resp_buftype[1] = resp_buftype[2] = CIFS_NO_BUFFER; +@@ -1404,7 +1407,6 @@ smb2_ioctl_query_info(const unsigned int xid, + + memset(&oparms, 0, sizeof(oparms)); + oparms.tcon = tcon; +- oparms.desired_access = FILE_READ_ATTRIBUTES | READ_CONTROL; + oparms.disposition = FILE_OPEN; + if (is_dir) + oparms.create_options = CREATE_NOT_FILE; +@@ -1413,9 +1415,6 @@ smb2_ioctl_query_info(const unsigned int xid, + oparms.fid = &fid; + oparms.reconnect = false; + +- /* +- * FSCTL codes encode the special access they need in the fsctl code. +- */ + if (qi.flags & PASSTHRU_FSCTL) { + switch (qi.info_type & FSCTL_DEVICE_ACCESS_MASK) { + case FSCTL_DEVICE_ACCESS_FILE_READ_WRITE_ACCESS: +@@ -1431,6 +1430,10 @@ smb2_ioctl_query_info(const unsigned int xid, + oparms.desired_access = GENERIC_WRITE; + break; + } ++ } else if (qi.flags & PASSTHRU_SET_INFO) { ++ oparms.desired_access = GENERIC_WRITE; ++ } else { ++ oparms.desired_access = FILE_READ_ATTRIBUTES | READ_CONTROL; + } + + rc = SMB2_open_init(tcon, &rqst[0], &oplock, &oparms, path); +@@ -1454,6 +1457,24 @@ smb2_ioctl_query_info(const unsigned int xid, + qi.output_buffer_length, + CIFSMaxBufSize); + } ++ } else if (qi.flags == PASSTHRU_SET_INFO) { ++ /* Can eventually relax perm check since server enforces too */ ++ if (!capable(CAP_SYS_ADMIN)) ++ rc = -EPERM; ++ else { ++ memset(&si_iov, 0, sizeof(si_iov)); ++ rqst[1].rq_iov = si_iov; ++ rqst[1].rq_nvec = 1; ++ ++ size[0] = 8; ++ data[0] = buffer; ++ ++ rc = SMB2_set_info_init(tcon, &rqst[1], ++ COMPOUND_FID, COMPOUND_FID, ++ current->tgid, ++ FILE_END_OF_FILE_INFORMATION, ++ SMB2_O_INFO_FILE, 0, data, size); ++ } + } else if (qi.flags == PASSTHRU_QUERY_INFO) { + memset(&qi_iov, 0, sizeof(qi_iov)); + rqst[1].rq_iov = qi_iov; +-- +2.25.1 + + diff --git a/patches.suse/cifs-add-smb2-POSIX-info-level.patch b/patches.suse/cifs-add-smb2-POSIX-info-level.patch new file mode 100644 index 0000000..1fa79f2 --- /dev/null +++ b/patches.suse/cifs-add-smb2-POSIX-info-level.patch @@ -0,0 +1,195 @@ +From 75b29b314b37b22ac0711954c40b3bfbe64cc7a0 Mon Sep 17 00:00:00 2001 +From: Aurelien Aptel +Date: Sat, 8 Feb 2020 15:50:57 +0100 +Subject: [PATCH] cifs: add smb2 POSIX info level +Patch-mainline: Not yet, in for-next branch +References: bsc#1144333 + +* add new info level and structs for SMB2 posix extension +* add functions to parse and validate it + +Signed-off-by: Aurelien Aptel +Signed-off-by: Steve French +Acked-by: Paulo Alcantara +--- + fs/cifs/cifspdu.h | 1 + fs/cifs/smb2pdu.c | 95 ++++++++++++++++++++++++++++++++++++++++++++++++++++ + fs/cifs/smb2pdu.h | 45 ++++++++++++++++++++++++ + fs/cifs/smb2proto.h | 2 + + 4 files changed, 143 insertions(+) + +--- a/fs/cifs/cifspdu.h ++++ b/fs/cifs/cifspdu.h +@@ -1691,6 +1691,7 @@ struct smb_t2_rsp { + #define SMB_FIND_FILE_ID_FULL_DIR_INFO 0x105 + #define SMB_FIND_FILE_ID_BOTH_DIR_INFO 0x106 + #define SMB_FIND_FILE_UNIX 0x202 ++#define SMB_FIND_FILE_POSIX_INFO 0x064 + + typedef struct smb_com_transaction2_qpi_req { + struct smb_hdr hdr; /* wct = 14+ */ +--- a/fs/cifs/smb2pdu.c ++++ b/fs/cifs/smb2pdu.c +@@ -4279,6 +4279,101 @@ SMB2_write(const unsigned int xid, struc + return rc; + } + ++static int posix_info_sid_size(const void *beg, const void *end) ++{ ++ size_t subauth; ++ int total; ++ ++ if (beg + 1 > end) ++ return -1; ++ ++ subauth = *(u8 *)(beg+1); ++ if (subauth < 1 || subauth > 15) ++ return -1; ++ ++ total = 1 + 1 + 6 + 4*subauth; ++ if (beg + total > end) ++ return -1; ++ ++ return total; ++} ++ ++int posix_info_parse(const void *beg, const void *end, ++ struct smb2_posix_info_parsed *out) ++ ++{ ++ int total_len = 0; ++ int sid_len; ++ int name_len; ++ const void *owner_sid; ++ const void *group_sid; ++ const void *name; ++ ++ /* if no end bound given, assume payload to be correct */ ++ if (!end) { ++ const struct smb2_posix_info *p = beg; ++ ++ end = beg + le32_to_cpu(p->NextEntryOffset); ++ /* last element will have a 0 offset, pick a sensible bound */ ++ if (end == beg) ++ end += 0xFFFF; ++ } ++ ++ /* check base buf */ ++ if (beg + sizeof(struct smb2_posix_info) > end) ++ return -1; ++ total_len = sizeof(struct smb2_posix_info); ++ ++ /* check owner sid */ ++ owner_sid = beg + total_len; ++ sid_len = posix_info_sid_size(owner_sid, end); ++ if (sid_len < 0) ++ return -1; ++ total_len += sid_len; ++ ++ /* check group sid */ ++ group_sid = beg + total_len; ++ sid_len = posix_info_sid_size(group_sid, end); ++ if (sid_len < 0) ++ return -1; ++ total_len += sid_len; ++ ++ /* check name len */ ++ if (beg + total_len + 4 > end) ++ return -1; ++ name_len = le32_to_cpu(*(__le32 *)(beg + total_len)); ++ if (name_len < 1 || name_len > 0xFFFF) ++ return -1; ++ total_len += 4; ++ ++ /* check name */ ++ name = beg + total_len; ++ if (name + name_len > end) ++ return -1; ++ total_len += name_len; ++ ++ if (out) { ++ out->base = beg; ++ out->size = total_len; ++ out->name_len = name_len; ++ out->name = name; ++ memcpy(&out->owner, owner_sid, ++ posix_info_sid_size(owner_sid, end)); ++ memcpy(&out->group, group_sid, ++ posix_info_sid_size(group_sid, end)); ++ } ++ return total_len; ++} ++ ++static int posix_info_extra_size(const void *beg, const void *end) ++{ ++ int len = posix_info_parse(beg, end, NULL); ++ ++ if (len < 0) ++ return -1; ++ return len - sizeof(struct smb2_posix_info); ++} ++ + static unsigned int + num_entries(char *bufstart, char *end_of_buf, char **lastentry, size_t size) + { +--- a/fs/cifs/smb2pdu.h ++++ b/fs/cifs/smb2pdu.h +@@ -1613,4 +1613,49 @@ struct create_posix_rsp { + * var sized group SID + */ + } __packed; ++ ++/* ++ * SMB2-only POSIX info level ++ * ++ * See posix_info_sid_size(), posix_info_extra_size() and ++ * posix_info_parse() to help with the handling of this struct. ++ */ ++struct smb2_posix_info { ++ __le32 NextEntryOffset; ++ __u32 Ignored; ++ __le64 CreationTime; ++ __le64 LastAccessTime; ++ __le64 LastWriteTime; ++ __le64 ChangeTime; ++ __le64 EndOfFile; ++ __le64 AllocationSize; ++ __le32 DosAttributes; ++ __le64 Inode; ++ __le32 DeviceId; ++ __le32 Zero; ++ /* beginning of POSIX Create Context Response */ ++ __le32 HardLinks; ++ __le32 ReparseTag; ++ __le32 Mode; ++ /* ++ * var sized owner SID ++ * var sized group SID ++ * le32 filenamelength ++ * u8 filename[] ++ */ ++} __packed; ++ ++/* ++ * Parsed version of the above struct. Allows direct access to the ++ * variable length fields ++ */ ++struct smb2_posix_info_parsed { ++ const struct smb2_posix_info *base; ++ size_t size; ++ struct cifs_sid owner; ++ struct cifs_sid group; ++ int name_len; ++ const u8 *name; ++}; ++ + #endif /* _SMB2PDU_H */ +--- a/fs/cifs/smb2proto.h ++++ b/fs/cifs/smb2proto.h +@@ -271,4 +271,6 @@ extern int smb2_query_info_compound(cons + u32 class, u32 type, u32 output_len, + struct kvec *rsp, int *buftype, + struct cifs_sb_info *cifs_sb); ++int posix_info_parse(const void *beg, const void *end, ++ struct smb2_posix_info_parsed *out); + #endif /* _SMB2PROTO_H */ diff --git a/patches.suse/cifs-add-support-for-fallocate-mode-0-for-non-sparse-files.patch b/patches.suse/cifs-add-support-for-fallocate-mode-0-for-non-sparse-files.patch new file mode 100644 index 0000000..6336a78 --- /dev/null +++ b/patches.suse/cifs-add-support-for-fallocate-mode-0-for-non-sparse-files.patch @@ -0,0 +1,152 @@ +From: Ronnie Sahlberg +Date: Fri, 17 Jan 2020 11:45:02 +1000 +Subject: [PATCH] cifs: add support for fallocate mode 0 for non-sparse files +Git-commit: 8bd0d701445ef263a52968ced2854c3d35712695 +References: bsc#1144333 +Patch-mainline: v5.6-rc1 + +RHBZ 1336264 + +When we extend a file we must also force the size to be updated. + +This fixes an issue with holetest in xfs-tests which performs the following +sequence : +1, create a new file +2, use fallocate mode==0 to populate the file +3, mmap the file +4, touch each page by reading the mmapped region. + +Signed-off-by: Ronnie Sahlberg +Signed-off-by: Steve French +Acked-by: Paulo Alcantara +--- + fs/cifs/cifsfs.h | 3 ++ + fs/cifs/inode.c | 4 +-- + fs/cifs/smb2ops.c | 64 ++++++++++++++++++++++++------------------------------ + 3 files changed, 34 insertions(+), 37 deletions(-) + +--- a/fs/cifs/cifsfs.h ++++ b/fs/cifs/cifsfs.h +@@ -150,6 +150,9 @@ extern ssize_t cifs_file_copychunk_range + size_t len, unsigned int flags); + + extern long cifs_ioctl(struct file *filep, unsigned int cmd, unsigned long arg); ++extern void cifs_setsize(struct inode *inode, loff_t offset); ++extern int cifs_truncate_page(struct address_space *mapping, loff_t from); ++ + #ifdef CONFIG_CIFS_NFSD_EXPORT + extern const struct export_operations cifs_export_ops; + #endif /* CONFIG_CIFS_NFSD_EXPORT */ +--- a/fs/cifs/inode.c ++++ b/fs/cifs/inode.c +@@ -2228,7 +2228,7 @@ int cifs_fiemap(struct inode *inode, str + return -ENOTSUPP; + } + +-static int cifs_truncate_page(struct address_space *mapping, loff_t from) ++int cifs_truncate_page(struct address_space *mapping, loff_t from) + { + pgoff_t index = from >> PAGE_SHIFT; + unsigned offset = from & (PAGE_SIZE - 1); +@@ -2245,7 +2245,7 @@ static int cifs_truncate_page(struct add + return rc; + } + +-static void cifs_setsize(struct inode *inode, loff_t offset) ++void cifs_setsize(struct inode *inode, loff_t offset) + { + struct cifsInodeInfo *cifs_i = CIFS_I(inode); + +--- a/fs/cifs/smb2ops.c ++++ b/fs/cifs/smb2ops.c +@@ -11,6 +11,7 @@ + #include + #include + #include ++#include "cifsfs.h" + #include "cifsglob.h" + #include "smb2pdu.h" + #include "smb2proto.h" +@@ -3161,28 +3162,32 @@ static long smb3_simple_falloc(struct fi + } + + /* ++ * Extending the file ++ */ ++ if ((keep_size == false) && i_size_read(inode) < off + len) { ++ if ((cifsi->cifsAttrs & FILE_ATTRIBUTE_SPARSE_FILE) == 0) ++ smb2_set_sparse(xid, tcon, cfile, inode, false); ++ ++ eof = cpu_to_le64(off + len); ++ rc = SMB2_set_eof(xid, tcon, cfile->fid.persistent_fid, ++ cfile->fid.volatile_fid, cfile->pid, &eof); ++ if (rc == 0) { ++ cifsi->server_eof = off + len; ++ cifs_setsize(inode, off + len); ++ cifs_truncate_page(inode->i_mapping, inode->i_size); ++ truncate_setsize(inode, off + len); ++ } ++ goto out; ++ } ++ ++ /* + * Files are non-sparse by default so falloc may be a no-op +- * Must check if file sparse. If not sparse, and not extending +- * then no need to do anything since file already allocated ++ * Must check if file sparse. If not sparse, and since we are not ++ * extending then no need to do anything since file already allocated + */ + if ((cifsi->cifsAttrs & FILE_ATTRIBUTE_SPARSE_FILE) == 0) { +- if (keep_size == true) +- rc = 0; +- /* check if extending file */ +- else if (i_size_read(inode) >= off + len) +- /* not extending file and already not sparse */ +- rc = 0; +- /* BB: in future add else clause to extend file */ +- else +- rc = -EOPNOTSUPP; +- if (rc) +- trace_smb3_falloc_err(xid, cfile->fid.persistent_fid, +- tcon->tid, tcon->ses->Suid, off, len, rc); +- else +- trace_smb3_falloc_done(xid, cfile->fid.persistent_fid, +- tcon->tid, tcon->ses->Suid, off, len); +- free_xid(xid); +- return rc; ++ rc = 0; ++ goto out; + } + + if ((keep_size == true) || (i_size_read(inode) >= off + len)) { +@@ -3196,25 +3201,14 @@ static long smb3_simple_falloc(struct fi + */ + if ((off > 8192) || (off + len + 8192 < i_size_read(inode))) { + rc = -EOPNOTSUPP; +- trace_smb3_falloc_err(xid, cfile->fid.persistent_fid, +- tcon->tid, tcon->ses->Suid, off, len, rc); +- free_xid(xid); +- return rc; +- } +- +- smb2_set_sparse(xid, tcon, cfile, inode, false); +- rc = 0; +- } else { +- smb2_set_sparse(xid, tcon, cfile, inode, false); +- rc = 0; +- if (i_size_read(inode) < off + len) { +- eof = cpu_to_le64(off + len); +- rc = SMB2_set_eof(xid, tcon, cfile->fid.persistent_fid, +- cfile->fid.volatile_fid, cfile->pid, +- &eof); ++ goto out; + } + } + ++ smb2_set_sparse(xid, tcon, cfile, inode, false); ++ rc = 0; ++ ++out: + if (rc) + trace_smb3_falloc_err(xid, cfile->fid.persistent_fid, tcon->tid, + tcon->ses->Suid, off, len, rc); diff --git a/patches.suse/cifs-allow-chmod-to-set-mode-bits-using-special-sid.patch b/patches.suse/cifs-allow-chmod-to-set-mode-bits-using-special-sid.patch new file mode 100644 index 0000000..6bc9611 --- /dev/null +++ b/patches.suse/cifs-allow-chmod-to-set-mode-bits-using-special-sid.patch @@ -0,0 +1,140 @@ +From: Steve French +Date: Fri, 19 Jul 2019 08:15:55 +0000 +Subject: [PATCH] cifs: allow chmod to set mode bits using special sid +Git-commit: 22442179a5bb8c62c978cdb686cfb3a8f6d110d8 +References: bsc#1144333 +Patch-mainline: v5.4-rc1 + + When mounting with "modefromsid" set mode bits (chmod) by + adding ACE with special SID (S-1-5-88-3-) to the ACL. + Subsequent patch will fix setting default mode on file + create and mkdir. + + See See e.g. + https://docs.microsoft.com/en-us/previous-versions/windows/it-pro/windows-server-2008-R2-and-2008/hh509017(v=ws.10) + +Signed-off-by: Steve French +Acked-by: Paulo Alcantara +--- + fs/cifs/cifsacl.c | 42 +++++++++++++++++++++++++++++++++++++----- + fs/cifs/inode.c | 6 ++++-- + 2 files changed, 41 insertions(+), 7 deletions(-) + +diff --git a/fs/cifs/cifsacl.c b/fs/cifs/cifsacl.c +index 7fe4509e6c03..3e0c5ed9ca20 100644 +--- a/fs/cifs/cifsacl.c ++++ b/fs/cifs/cifsacl.c +@@ -806,7 +806,7 @@ static void parse_dacl(struct cifs_acl *pdacl, char *end_of_acl, + + + static int set_chmod_dacl(struct cifs_acl *pndacl, struct cifs_sid *pownersid, +- struct cifs_sid *pgrpsid, __u64 nmode) ++ struct cifs_sid *pgrpsid, __u64 nmode, bool modefromsid) + { + u16 size = 0; + struct cifs_acl *pnndacl; +@@ -820,8 +820,33 @@ static int set_chmod_dacl(struct cifs_acl *pndacl, struct cifs_sid *pownersid, + size += fill_ace_for_sid((struct cifs_ace *)((char *)pnndacl + size), + &sid_everyone, nmode, S_IRWXO); + ++ /* TBD: Move this ACE to the top of ACE list instead of bottom */ ++ if (modefromsid) { ++ struct cifs_ace *pntace = ++ (struct cifs_ace *)((char *)pnndacl + size); ++ int i; ++ ++ pntace->type = ACCESS_DENIED; ++ pntace->flags = 0x0; ++ pntace->sid.num_subauth = 3; ++ pntace->sid.revision = 1; ++ /* size = 1 + 1 + 2 + 4 + 1 + 1 + 6 + (psid->num_subauth * 4) */ ++ pntace->size = cpu_to_le16(28); ++ size += 28; ++ for (i = 0; i < NUM_AUTHS; i++) ++ pntace->sid.authority[i] = ++ sid_unix_NFS_mode.authority[i]; ++ pntace->sid.sub_auth[0] = sid_unix_NFS_mode.sub_auth[0]; ++ pntace->sid.sub_auth[1] = sid_unix_NFS_mode.sub_auth[1]; ++ pntace->sid.sub_auth[2] = cpu_to_le32(nmode & 07777); ++ ++ pndacl->num_aces = cpu_to_le32(4); ++ size += fill_ace_for_sid((struct cifs_ace *)((char *)pnndacl + size), ++ &sid_unix_NFS_mode, nmode, S_IRWXO); ++ } else ++ pndacl->num_aces = cpu_to_le32(3); ++ + pndacl->size = cpu_to_le16(size + sizeof(struct cifs_acl)); +- pndacl->num_aces = cpu_to_le32(3); + + return 0; + } +@@ -921,7 +946,8 @@ static int parse_sec_desc(struct cifs_sb_info *cifs_sb, + + /* Convert permission bits from mode to equivalent CIFS ACL */ + static int build_sec_desc(struct cifs_ntsd *pntsd, struct cifs_ntsd *pnntsd, +- __u32 secdesclen, __u64 nmode, kuid_t uid, kgid_t gid, int *aclflag) ++ __u32 secdesclen, __u64 nmode, kuid_t uid, kgid_t gid, ++ bool mode_from_sid, int *aclflag) + { + int rc = 0; + __u32 dacloffset; +@@ -946,7 +972,7 @@ static int build_sec_desc(struct cifs_ntsd *pntsd, struct cifs_ntsd *pnntsd, + ndacl_ptr->num_aces = 0; + + rc = set_chmod_dacl(ndacl_ptr, owner_sid_ptr, group_sid_ptr, +- nmode); ++ nmode, mode_from_sid); + sidsoffset = ndacloffset + le16_to_cpu(ndacl_ptr->size); + /* copy sec desc control portion & owner and group sids */ + copy_sec_desc(pntsd, pnntsd, sidsoffset); +@@ -1196,6 +1222,7 @@ id_mode_to_cifs_acl(struct inode *inode, const char *path, __u64 nmode, + struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); + struct tcon_link *tlink = cifs_sb_tlink(cifs_sb); + struct smb_version_operations *ops; ++ bool mode_from_sid; + + if (IS_ERR(tlink)) + return PTR_ERR(tlink); +@@ -1233,8 +1260,13 @@ id_mode_to_cifs_acl(struct inode *inode, const char *path, __u64 nmode, + return -ENOMEM; + } + ++ if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MODE_FROM_SID) ++ mode_from_sid = true; ++ else ++ mode_from_sid = false; ++ + rc = build_sec_desc(pntsd, pnntsd, secdesclen, nmode, uid, gid, +- &aclflag); ++ mode_from_sid, &aclflag); + + cifs_dbg(NOISY, "build_sec_desc rc: %d\n", rc); + +diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c +index c1e620ebcf7c..26cdfbf1e164 100644 +--- a/fs/cifs/inode.c ++++ b/fs/cifs/inode.c +@@ -2489,7 +2489,8 @@ cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs) + if (attrs->ia_valid & ATTR_GID) + gid = attrs->ia_gid; + +- if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) { ++ if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) || ++ (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MODE_FROM_SID)) { + if (uid_valid(uid) || gid_valid(gid)) { + rc = id_mode_to_cifs_acl(inode, full_path, NO_CHANGE_64, + uid, gid); +@@ -2510,7 +2511,8 @@ cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs) + if (attrs->ia_valid & ATTR_MODE) { + mode = attrs->ia_mode; + rc = 0; +- if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) { ++ if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) || ++ (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MODE_FROM_SID)) { + rc = id_mode_to_cifs_acl(inode, full_path, mode, + INVALID_UID, INVALID_GID); + if (rc) { +-- +2.25.1 + + diff --git a/patches.suse/cifs-call-wake_up-server-response_q-inside-of-cifs_r.patch b/patches.suse/cifs-call-wake_up-server-response_q-inside-of-cifs_r.patch new file mode 100644 index 0000000..5863075 --- /dev/null +++ b/patches.suse/cifs-call-wake_up-server-response_q-inside-of-cifs_r.patch @@ -0,0 +1,123 @@ +From 6970363a60b1b5db967f95fb986e0c7bdb83c84d Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Mon, 24 Feb 2020 14:31:02 -0600 +Subject: [PATCH] cifs: call wake_up(&server->response_q) inside of + cifs_reconnect() +Patch-mainline: Not yet, in for-next branch +References: bsc#1144333 + +This means it's consistently called and the callers don't need to +care about it. + +Signed-off-by: Stefan Metzmacher +Reviewed-by: Pavel Shilovsky +Signed-off-by: Steve French +Acked-by: Paulo Alcantara +--- + fs/cifs/cifssmb.c | 1 - + fs/cifs/connect.c | 7 ++----- + fs/cifs/smb2ops.c | 3 --- + 3 files changed, 2 insertions(+), 9 deletions(-) + +diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c +index 6e95ee69dd18..b173ff22560b 100644 +--- a/fs/cifs/cifssmb.c ++++ b/fs/cifs/cifssmb.c +@@ -1602,7 +1602,6 @@ cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid) + if (server->ops->is_session_expired && + server->ops->is_session_expired(buf)) { + cifs_reconnect(server); +- wake_up(&server->response_q); + return -1; + } + +diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c +index e2196b363765..f4d12b79ceed 100644 +--- a/fs/cifs/connect.c ++++ b/fs/cifs/connect.c +@@ -489,6 +489,7 @@ cifs_reconnect(struct TCP_Server_Info *server) + dfs_cache_free_tgts(&tgt_list); + cifs_put_tcp_super(sb); + #endif ++ wake_up(&server->response_q); + return rc; + } else + server->tcpStatus = CifsNeedReconnect; +@@ -623,6 +624,7 @@ cifs_reconnect(struct TCP_Server_Info *server) + if (server->tcpStatus == CifsNeedNegotiate) + mod_delayed_work(cifsiod_wq, &server->echo, 0); + ++ wake_up(&server->response_q); + return rc; + } + +@@ -717,7 +719,6 @@ server_unresponsive(struct TCP_Server_Info *server) + cifs_server_dbg(VFS, "has not responded in %lu seconds. Reconnecting...\n", + (3 * server->echo_interval) / HZ); + cifs_reconnect(server); +- wake_up(&server->response_q); + return true; + } + +@@ -850,7 +851,6 @@ is_smb_response(struct TCP_Server_Info *server, unsigned char type) + */ + cifs_set_port((struct sockaddr *)&server->dstaddr, CIFS_PORT); + cifs_reconnect(server); +- wake_up(&server->response_q); + break; + default: + cifs_server_dbg(VFS, "RFC 1002 unknown response type 0x%x\n", type); +@@ -1022,7 +1022,6 @@ standard_receive3(struct TCP_Server_Info *server, struct mid_q_entry *mid) + server->vals->header_preamble_size) { + cifs_server_dbg(VFS, "SMB response too long (%u bytes)\n", pdu_length); + cifs_reconnect(server); +- wake_up(&server->response_q); + return -ECONNABORTED; + } + +@@ -1070,7 +1069,6 @@ cifs_handle_standard(struct TCP_Server_Info *server, struct mid_q_entry *mid) + if (server->ops->is_session_expired && + server->ops->is_session_expired(buf)) { + cifs_reconnect(server); +- wake_up(&server->response_q); + return -1; + } + +@@ -1164,7 +1162,6 @@ cifs_demultiplex_thread(void *p) + cifs_server_dbg(VFS, "SMB response too short (%u bytes)\n", + server->pdu_size); + cifs_reconnect(server); +- wake_up(&server->response_q); + continue; + } + +diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c +index c31e84ee3c39..5fa34225a99b 100644 +--- a/fs/cifs/smb2ops.c ++++ b/fs/cifs/smb2ops.c +@@ -4149,7 +4149,6 @@ handle_read_data(struct TCP_Server_Info *server, struct mid_q_entry *mid, + if (server->ops->is_session_expired && + server->ops->is_session_expired(buf)) { + cifs_reconnect(server); +- wake_up(&server->response_q); + return -1; + } + +@@ -4513,14 +4512,12 @@ smb3_receive_transform(struct TCP_Server_Info *server, + cifs_server_dbg(VFS, "Transform message is too small (%u)\n", + pdu_length); + cifs_reconnect(server); +- wake_up(&server->response_q); + return -ECONNABORTED; + } + + if (pdu_length < orig_len + sizeof(struct smb2_transform_hdr)) { + cifs_server_dbg(VFS, "Transform message is broken\n"); + cifs_reconnect(server); +- wake_up(&server->response_q); + return -ECONNABORTED; + } + +-- +2.25.1 + diff --git a/patches.suse/cifs-create-a-helper-function-to-parse-the-query-directory-response.patch b/patches.suse/cifs-create-a-helper-function-to-parse-the-query-directory-response.patch new file mode 100644 index 0000000..8ff933c --- /dev/null +++ b/patches.suse/cifs-create-a-helper-function-to-parse-the-query-directory-response.patch @@ -0,0 +1,192 @@ +From: Ronnie Sahlberg +Date: Wed, 8 Jan 2020 13:08:05 +1000 +Subject: [PATCH] cifs: create a helper function to parse the query-directory + response buffer +Git-commit: af08f9e79c602835f975f0f8f6e90fc48848bffa +References: bsc#1144333 +Patch-mainline: v5.6-rc1 + +Signed-off-by: Ronnie Sahlberg +Signed-off-by: Steve French +Reviewed-by: Pavel Shilovsky +Acked-by: Paulo Alcantara +--- + fs/cifs/smb2pdu.c | 133 ++++++++++++++++++++++++++-------------------- + 1 file changed, 75 insertions(+), 58 deletions(-) + +diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c +index 50466062c1da..a23ca3d0dcd9 100644 +--- a/fs/cifs/smb2pdu.c ++++ b/fs/cifs/smb2pdu.c +@@ -4370,58 +4370,17 @@ void SMB2_query_directory_free(struct smb_rqst *rqst) + } + + int +-SMB2_query_directory(const unsigned int xid, struct cifs_tcon *tcon, +- u64 persistent_fid, u64 volatile_fid, int index, +- struct cifs_search_info *srch_inf) ++smb2_parse_query_directory(struct cifs_tcon *tcon, ++ struct kvec *rsp_iov, ++ int resp_buftype, ++ struct cifs_search_info *srch_inf) + { +- struct smb_rqst rqst; +- struct kvec iov[SMB2_QUERY_DIRECTORY_IOV_SIZE]; +- struct smb2_query_directory_rsp *rsp = NULL; +- int resp_buftype = CIFS_NO_BUFFER; +- struct kvec rsp_iov; +- int rc = 0; +- struct TCP_Server_Info *server; +- struct cifs_ses *ses = tcon->ses; +- char *end_of_smb; ++ struct smb2_query_directory_rsp *rsp; + size_t info_buf_size; +- int flags = 0; ++ char *end_of_smb; ++ int rc; + +- if (ses && (ses->server)) +- server = ses->server; +- else +- return -EIO; +- +- if (smb3_encryption_required(tcon)) +- flags |= CIFS_TRANSFORM_REQ; +- +- memset(&rqst, 0, sizeof(struct smb_rqst)); +- memset(&iov, 0, sizeof(iov)); +- rqst.rq_iov = iov; +- rqst.rq_nvec = SMB2_QUERY_DIRECTORY_IOV_SIZE; +- +- rc = SMB2_query_directory_init(xid, tcon, &rqst, persistent_fid, +- volatile_fid, index, +- srch_inf->info_level); +- if (rc) +- goto qdir_exit; +- +- rc = cifs_send_recv(xid, ses, &rqst, &resp_buftype, flags, &rsp_iov); +- rsp = (struct smb2_query_directory_rsp *)rsp_iov.iov_base; +- +- if (rc) { +- if (rc == -ENODATA && +- rsp->sync_hdr.Status == STATUS_NO_MORE_FILES) { +- trace_smb3_query_dir_done(xid, persistent_fid, +- tcon->tid, tcon->ses->Suid, index, 0); +- srch_inf->endOfSearch = true; +- rc = 0; +- } else { +- trace_smb3_query_dir_err(xid, persistent_fid, tcon->tid, +- tcon->ses->Suid, index, 0, rc); +- cifs_stats_fail_inc(tcon, SMB2_QUERY_DIRECTORY_HE); +- } +- goto qdir_exit; +- } ++ rsp = (struct smb2_query_directory_rsp *)rsp_iov->iov_base; + + switch (srch_inf->info_level) { + case SMB_FIND_FILE_DIRECTORY_INFO: +@@ -4433,18 +4392,14 @@ SMB2_query_directory(const unsigned int xid, struct cifs_tcon *tcon, + default: + cifs_tcon_dbg(VFS, "info level %u isn't supported\n", + srch_inf->info_level); +- rc = -EINVAL; +- goto qdir_exit; ++ return -EINVAL; + } + + rc = smb2_validate_iov(le16_to_cpu(rsp->OutputBufferOffset), +- le32_to_cpu(rsp->OutputBufferLength), &rsp_iov, ++ le32_to_cpu(rsp->OutputBufferLength), rsp_iov, + info_buf_size); +- if (rc) { +- trace_smb3_query_dir_err(xid, persistent_fid, tcon->tid, +- tcon->ses->Suid, index, 0, rc); +- goto qdir_exit; +- } ++ if (rc) ++ return rc; + + srch_inf->unicode = true; + +@@ -4457,7 +4412,7 @@ SMB2_query_directory(const unsigned int xid, struct cifs_tcon *tcon, + srch_inf->ntwrk_buf_start = (char *)rsp; + srch_inf->srch_entries_start = srch_inf->last_entry = + (char *)rsp + le16_to_cpu(rsp->OutputBufferOffset); +- end_of_smb = rsp_iov.iov_len + (char *)rsp; ++ end_of_smb = rsp_iov->iov_len + (char *)rsp; + srch_inf->entries_in_buffer = + num_entries(srch_inf->srch_entries_start, end_of_smb, + &srch_inf->last_entry, info_buf_size); +@@ -4472,6 +4427,68 @@ SMB2_query_directory(const unsigned int xid, struct cifs_tcon *tcon, + else + cifs_tcon_dbg(VFS, "illegal search buffer type\n"); + ++ return 0; ++} ++ ++int ++SMB2_query_directory(const unsigned int xid, struct cifs_tcon *tcon, ++ u64 persistent_fid, u64 volatile_fid, int index, ++ struct cifs_search_info *srch_inf) ++{ ++ struct smb_rqst rqst; ++ struct kvec iov[SMB2_QUERY_DIRECTORY_IOV_SIZE]; ++ struct smb2_query_directory_rsp *rsp = NULL; ++ int resp_buftype = CIFS_NO_BUFFER; ++ struct kvec rsp_iov; ++ int rc = 0; ++ struct TCP_Server_Info *server; ++ struct cifs_ses *ses = tcon->ses; ++ int flags = 0; ++ ++ if (ses && (ses->server)) ++ server = ses->server; ++ else ++ return -EIO; ++ ++ if (smb3_encryption_required(tcon)) ++ flags |= CIFS_TRANSFORM_REQ; ++ ++ memset(&rqst, 0, sizeof(struct smb_rqst)); ++ memset(&iov, 0, sizeof(iov)); ++ rqst.rq_iov = iov; ++ rqst.rq_nvec = SMB2_QUERY_DIRECTORY_IOV_SIZE; ++ ++ rc = SMB2_query_directory_init(xid, tcon, &rqst, persistent_fid, ++ volatile_fid, index, ++ srch_inf->info_level); ++ if (rc) ++ goto qdir_exit; ++ ++ rc = cifs_send_recv(xid, ses, &rqst, &resp_buftype, flags, &rsp_iov); ++ rsp = (struct smb2_query_directory_rsp *)rsp_iov.iov_base; ++ ++ if (rc) { ++ if (rc == -ENODATA && ++ rsp->sync_hdr.Status == STATUS_NO_MORE_FILES) { ++ trace_smb3_query_dir_done(xid, persistent_fid, ++ tcon->tid, tcon->ses->Suid, index, 0); ++ srch_inf->endOfSearch = true; ++ rc = 0; ++ } else { ++ trace_smb3_query_dir_err(xid, persistent_fid, tcon->tid, ++ tcon->ses->Suid, index, 0, rc); ++ cifs_stats_fail_inc(tcon, SMB2_QUERY_DIRECTORY_HE); ++ } ++ goto qdir_exit; ++ } ++ ++ rc = smb2_parse_query_directory(tcon, &rsp_iov, resp_buftype, ++ srch_inf); ++ if (rc) { ++ trace_smb3_query_dir_err(xid, persistent_fid, tcon->tid, ++ tcon->ses->Suid, index, 0, rc); ++ goto qdir_exit; ++ } + resp_buftype = CIFS_NO_BUFFER; + + trace_smb3_query_dir_done(xid, persistent_fid, tcon->tid, +-- +2.25.1 + + diff --git a/patches.suse/cifs-do-d_move-in-rename.patch b/patches.suse/cifs-do-d_move-in-rename.patch new file mode 100644 index 0000000..bdbe409 --- /dev/null +++ b/patches.suse/cifs-do-d_move-in-rename.patch @@ -0,0 +1,57 @@ +From 5f8de0432b1ee5312bbb586b57fddec8c6e8c91a Mon Sep 17 00:00:00 2001 +From: Steve French +Date: Tue, 25 Feb 2020 18:08:54 -0600 +Subject: [PATCH] cifs: do d_move in rename +Patch-mainline: Not yet, in for-next branch +References: bsc#1144333 + +See commit 349457ccf2592c14bdf13b6706170ae2e94931b1 +"Allow file systems to manually d_move() inside of ->rename()" + +Lessens possibility of race conditions in rename + +Signed-off-by: Steve French +Acked-by: Paulo Alcantara +--- + fs/cifs/cifsfs.c | 4 ++-- + fs/cifs/inode.c | 2 ++ + 2 files changed, 4 insertions(+), 2 deletions(-) + +diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c +index fa77fe5258b0..94e3ed4850b5 100644 +--- a/fs/cifs/cifsfs.c ++++ b/fs/cifs/cifsfs.c +@@ -1018,7 +1018,7 @@ struct file_system_type cifs_fs_type = { + .name = "cifs", + .mount = cifs_do_mount, + .kill_sb = cifs_kill_sb, +- /* .fs_flags */ ++ .fs_flags = FS_RENAME_DOES_D_MOVE, + }; + MODULE_ALIAS_FS("cifs"); + +@@ -1027,7 +1027,7 @@ static struct file_system_type smb3_fs_type = { + .name = "smb3", + .mount = smb3_do_mount, + .kill_sb = cifs_kill_sb, +- /* .fs_flags */ ++ .fs_flags = FS_RENAME_DOES_D_MOVE, + }; + MODULE_ALIAS_FS("smb3"); + MODULE_ALIAS("smb3"); +diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c +index e6d66977a81d..8d01ec2dca66 100644 +--- a/fs/cifs/inode.c ++++ b/fs/cifs/inode.c +@@ -1835,6 +1835,8 @@ cifs_do_rename(const unsigned int xid, struct dentry *from_dentry, + CIFSSMBClose(xid, tcon, fid.netfid); + } + do_rename_exit: ++ if (rc == 0) ++ d_move(from_dentry, to_dentry); + cifs_put_tlink(tlink); + return rc; + } +-- +2.25.1 + diff --git a/patches.suse/cifs-do-not-ignore-the-SYNC-flags-in-getattr.patch b/patches.suse/cifs-do-not-ignore-the-SYNC-flags-in-getattr.patch new file mode 100644 index 0000000..418c68f --- /dev/null +++ b/patches.suse/cifs-do-not-ignore-the-SYNC-flags-in-getattr.patch @@ -0,0 +1,66 @@ +From 14b894d59153d7ed4ffe72b52bcc831a3f9006dc Mon Sep 17 00:00:00 2001 +From: Steve French +Date: Tue, 18 Feb 2020 18:07:57 -0600 +Subject: [PATCH] cifs: do not ignore the SYNC flags in getattr +Patch-mainline: Not yet, in for-next branch +References: bsc#1144333 + +Check the AT_STATX_FORCE_SYNC flag and force an attribute +revalidation if requested by the caller, and if the caller +specificies AT_STATX_DONT_SYNC only revalidate cached attributes +if required. In addition do not flush writes in getattr (which +can be expensive) if size or timestamps not requested by the +caller. + +Signed-off-by: Steve French +Reviewed-by: Aurelien Aptel +Reviewed-by: Ronnie Sahlberg +Signed-off-by: Steve French +Acked-by: Paulo Alcantara +--- + fs/cifs/inode.c | 22 +++++++++++++++++----- + 1 file changed, 17 insertions(+), 5 deletions(-) + +diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c +index 1e8a4b1579db..84b8ebaa5932 100644 +--- a/fs/cifs/inode.c ++++ b/fs/cifs/inode.c +@@ -2148,8 +2148,9 @@ int cifs_getattr(const struct path *path, struct kstat *stat, + * We need to be sure that all dirty pages are written and the server + * has actual ctime, mtime and file length. + */ +- if (!CIFS_CACHE_READ(CIFS_I(inode)) && inode->i_mapping && +- inode->i_mapping->nrpages != 0) { ++ if ((request_mask & (STATX_CTIME | STATX_MTIME | STATX_SIZE)) && ++ !CIFS_CACHE_READ(CIFS_I(inode)) && ++ inode->i_mapping && inode->i_mapping->nrpages != 0) { + rc = filemap_fdatawait(inode->i_mapping); + if (rc) { + mapping_set_error(inode->i_mapping, rc); +@@ -2157,9 +2158,20 @@ int cifs_getattr(const struct path *path, struct kstat *stat, + } + } + +- rc = cifs_revalidate_dentry_attr(dentry); +- if (rc) +- return rc; ++ if ((flags & AT_STATX_SYNC_TYPE) == AT_STATX_FORCE_SYNC) ++ CIFS_I(inode)->time = 0; /* force revalidate */ ++ ++ /* ++ * If the caller doesn't require syncing, only sync if ++ * necessary (e.g. due to earlier truncate or setattr ++ * invalidating the cached metadata) ++ */ ++ if (((flags & AT_STATX_SYNC_TYPE) != AT_STATX_DONT_SYNC) || ++ (CIFS_I(inode)->time == 0)) { ++ rc = cifs_revalidate_dentry_attr(dentry); ++ if (rc) ++ return rc; ++ } + + generic_fillattr(inode, stat); + stat->blksize = cifs_sb->bsize; +-- +2.25.1 + diff --git a/patches.suse/cifs-don-t-leak-EAGAIN-for-stat-during-reconnect.patch b/patches.suse/cifs-don-t-leak-EAGAIN-for-stat-during-reconnect.patch new file mode 100644 index 0000000..e2aa89b --- /dev/null +++ b/patches.suse/cifs-don-t-leak-EAGAIN-for-stat-during-reconnect.patch @@ -0,0 +1,64 @@ +From: Ronnie Sahlberg +Date: Wed, 19 Feb 2020 06:01:03 +1000 +Subject: [PATCH] cifs: don't leak -EAGAIN for stat() during reconnect +Git-commit: fc513fac56e1b626ae48a74d7551d9c35c50129e +References: bsc#1144333 +Patch-mainline: v5.6-rc4 + +If from cifs_revalidate_dentry_attr() the SMB2/QUERY_INFO call fails with an +error, such as STATUS_SESSION_EXPIRED, causing the session to be reconnected +it is possible we will leak -EAGAIN back to the application even for +system calls such as stat() where this is not a valid error. + +Fix this by re-trying the operation from within cifs_revalidate_dentry_attr() +if cifs_get_inode_info*() returns -EAGAIN. + +This fixes stat() and possibly also other system calls that uses +cifs_revalidate_dentry*(). + +Signed-off-by: Ronnie Sahlberg +Signed-off-by: Steve French +Reviewed-by: Pavel Shilovsky +Reviewed-by: Aurelien Aptel +CC: Stable +Acked-by: Paulo Alcantara +--- + fs/cifs/inode.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c +index b5e6635c578e..1c6f659110d0 100644 +--- a/fs/cifs/inode.c ++++ b/fs/cifs/inode.c +@@ -2073,6 +2073,7 @@ int cifs_revalidate_dentry_attr(struct dentry *dentry) + struct inode *inode = d_inode(dentry); + struct super_block *sb = dentry->d_sb; + char *full_path = NULL; ++ int count = 0; + + if (inode == NULL) + return -ENOENT; +@@ -2094,15 +2095,18 @@ int cifs_revalidate_dentry_attr(struct dentry *dentry) + full_path, inode, inode->i_count.counter, + dentry, cifs_get_time(dentry), jiffies); + ++again: + if (cifs_sb_master_tcon(CIFS_SB(sb))->unix_ext) + rc = cifs_get_inode_info_unix(&inode, full_path, sb, xid); + else + rc = cifs_get_inode_info(&inode, full_path, NULL, sb, + xid, NULL); +- ++ if (rc == -EAGAIN && count++ < 10) ++ goto again; + out: + kfree(full_path); + free_xid(xid); ++ + return rc; + } + +-- +2.25.1 + + diff --git a/patches.suse/cifs-don-t-use-pre-for-MODULE_SOFTDEP.patch b/patches.suse/cifs-don-t-use-pre-for-MODULE_SOFTDEP.patch new file mode 100644 index 0000000..5b02b7a --- /dev/null +++ b/patches.suse/cifs-don-t-use-pre-for-MODULE_SOFTDEP.patch @@ -0,0 +1,56 @@ +From: Ronnie Sahlberg +Date: Thu, 31 Oct 2019 13:55:14 +1000 +Subject: [PATCH] cifs: don't use 'pre:' for MODULE_SOFTDEP +Git-commit: 3591bb83eee7731d3421621a3b04d2432f80bba0 +References: bsc#1144333 +Patch-mainline: v5.5-rc1 + +It can cause +to fail with +modprobe: FATAL: Module is builtin. + +RHBZ: 1767094 + +Signed-off-by: Ronnie Sahlberg +Signed-off-by: Steve French +Acked-by: Paulo Alcantara +--- + fs/cifs/cifsfs.c | 28 ++++++++++++++-------------- + 1 file changed, 14 insertions(+), 14 deletions(-) + +--- a/fs/cifs/cifsfs.c ++++ b/fs/cifs/cifsfs.c +@@ -1621,19 +1621,19 @@ MODULE_DESCRIPTION + ("VFS to access SMB3 servers e.g. Samba, Macs, Azure and Windows (and " + "also older servers complying with the SNIA CIFS Specification)"); + MODULE_VERSION(CIFS_VERSION); +-MODULE_SOFTDEP("pre: arc4"); +-MODULE_SOFTDEP("pre: des"); +-MODULE_SOFTDEP("pre: ecb"); +-MODULE_SOFTDEP("pre: hmac"); +-MODULE_SOFTDEP("pre: md4"); +-MODULE_SOFTDEP("pre: md5"); +-MODULE_SOFTDEP("pre: nls"); +-MODULE_SOFTDEP("pre: aes"); +-MODULE_SOFTDEP("pre: cmac"); +-MODULE_SOFTDEP("pre: sha256"); +-MODULE_SOFTDEP("pre: sha512"); +-MODULE_SOFTDEP("pre: aead2"); +-MODULE_SOFTDEP("pre: ccm"); +-MODULE_SOFTDEP("pre: gcm"); ++MODULE_SOFTDEP("arc4"); ++MODULE_SOFTDEP("des"); ++MODULE_SOFTDEP("ecb"); ++MODULE_SOFTDEP("hmac"); ++MODULE_SOFTDEP("md4"); ++MODULE_SOFTDEP("md5"); ++MODULE_SOFTDEP("nls"); ++MODULE_SOFTDEP("aes"); ++MODULE_SOFTDEP("cmac"); ++MODULE_SOFTDEP("sha256"); ++MODULE_SOFTDEP("sha512"); ++MODULE_SOFTDEP("aead2"); ++MODULE_SOFTDEP("ccm"); ++MODULE_SOFTDEP("gcm"); + module_init(init_cifs) + module_exit(exit_cifs) diff --git a/patches.suse/cifs-enable-change-notification-for-SMB2-1-dialect.patch b/patches.suse/cifs-enable-change-notification-for-SMB2-1-dialect.patch new file mode 100644 index 0000000..8e82ad5 --- /dev/null +++ b/patches.suse/cifs-enable-change-notification-for-SMB2-1-dialect.patch @@ -0,0 +1,35 @@ +From: Steve French +Date: Wed, 12 Feb 2020 22:37:08 -0600 +Subject: [PATCH] cifs: enable change notification for SMB2.1 dialect +Git-commit: 2c6251ad91afc2e3c671c904702e8d121d3d50c0 +References: bsc#1144333 +Patch-mainline: v5.6-rc2 + +It was originally enabled only for SMB3 or later dialects, but +had requests to add it to SMB2.1 mounts as well given the +large number of systems at that dialect level. + +Signed-off-by: Steve French +Reported-by: L Walsh +Acked-by: Ronnie Sahlberg +Acked-by: Paulo Alcantara +--- + fs/cifs/smb2ops.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c +index baa825f4cec0..aef33630e315 100644 +--- a/fs/cifs/smb2ops.c ++++ b/fs/cifs/smb2ops.c +@@ -4795,6 +4795,7 @@ struct smb_version_operations smb21_operations = { + .wp_retry_size = smb2_wp_retry_size, + .dir_needs_close = smb2_dir_needs_close, + .enum_snapshots = smb3_enum_snapshots, ++ .notify = smb3_notify, + .get_dfs_refer = smb2_get_dfs_refer, + .select_sectype = smb2_select_sectype, + #ifdef CONFIG_CIFS_XATTR +-- +2.25.1 + + diff --git a/patches.suse/cifs-fail-i-o-on-soft-mounts-if-sessionsetup-errors-out.patch b/patches.suse/cifs-fail-i-o-on-soft-mounts-if-sessionsetup-errors-out.patch new file mode 100644 index 0000000..ef3b25e --- /dev/null +++ b/patches.suse/cifs-fail-i-o-on-soft-mounts-if-sessionsetup-errors-out.patch @@ -0,0 +1,54 @@ +From: Ronnie Sahlberg +Date: Wed, 5 Feb 2020 11:08:01 +1000 +Subject: [PATCH] cifs: fail i/o on soft mounts if sessionsetup errors out +Git-commit: b0dd940e582b6a60296b9847a54012a4b080dc72 +References: bsc#1144333 +Patch-mainline: v5.6-rc1 + +RHBZ: 1579050 + +If we have a soft mount we should fail commands for session-setup +failures (such as the password having changed/ account being deleted/ ...) +and return an error back to the application. + +Signed-off-by: Ronnie Sahlberg +Signed-off-by: Steve French +CC: Stable +Acked-by: Paulo Alcantara +--- + fs/cifs/smb2pdu.c | 10 ++++++++-- + 1 file changed, 8 insertions(+), 2 deletions(-) + +diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c +index 14f209f7376f..7996d81230aa 100644 +--- a/fs/cifs/smb2pdu.c ++++ b/fs/cifs/smb2pdu.c +@@ -350,9 +350,14 @@ smb2_reconnect(__le16 smb2_command, struct cifs_tcon *tcon) + } + + rc = cifs_negotiate_protocol(0, tcon->ses); +- if (!rc && tcon->ses->need_reconnect) ++ if (!rc && tcon->ses->need_reconnect) { + rc = cifs_setup_session(0, tcon->ses, nls_codepage); +- ++ if ((rc == -EACCES) && !tcon->retry) { ++ rc = -EHOSTDOWN; ++ mutex_unlock(&tcon->ses->session_mutex); ++ goto failed; ++ } ++ } + if (rc || !tcon->need_reconnect) { + mutex_unlock(&tcon->ses->session_mutex); + goto out; +@@ -397,6 +402,7 @@ smb2_reconnect(__le16 smb2_command, struct cifs_tcon *tcon) + case SMB2_SET_INFO: + rc = -EAGAIN; + } ++failed: + unload_nls(nls_codepage); + return rc; + } +-- +2.25.1 + + diff --git a/patches.suse/cifs-fix-NULL-dereference-in-match_prepath.patch b/patches.suse/cifs-fix-NULL-dereference-in-match_prepath.patch new file mode 100644 index 0000000..632494e --- /dev/null +++ b/patches.suse/cifs-fix-NULL-dereference-in-match_prepath.patch @@ -0,0 +1,42 @@ +From: Ronnie Sahlberg +Date: Wed, 22 Jan 2020 11:07:56 +1000 +Subject: [PATCH] cifs: fix NULL dereference in match_prepath +Git-commit: fe1292686333d1dadaf84091f585ee903b9ddb84 +References: bsc#1144333 +Patch-mainline: v5.6-rc1 + +RHBZ: 1760879 + +Fix an oops in match_prepath() by making sure that the prepath string is not +NULL before we pass it into strcmp(). + +This is similar to other checks we make for example in cifs_root_iget() + +Signed-off-by: Ronnie Sahlberg +Signed-off-by: Steve French +Acked-by: Paulo Alcantara +--- + fs/cifs/connect.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c +index 05ea0e2b7e0e..0aa3623ae0e1 100644 +--- a/fs/cifs/connect.c ++++ b/fs/cifs/connect.c +@@ -3709,8 +3709,10 @@ match_prepath(struct super_block *sb, struct cifs_mnt_data *mnt_data) + { + struct cifs_sb_info *old = CIFS_SB(sb); + struct cifs_sb_info *new = mnt_data->cifs_sb; +- bool old_set = old->mnt_cifs_flags & CIFS_MOUNT_USE_PREFIX_PATH; +- bool new_set = new->mnt_cifs_flags & CIFS_MOUNT_USE_PREFIX_PATH; ++ bool old_set = (old->mnt_cifs_flags & CIFS_MOUNT_USE_PREFIX_PATH) && ++ old->prepath; ++ bool new_set = (new->mnt_cifs_flags & CIFS_MOUNT_USE_PREFIX_PATH) && ++ new->prepath; + + if (old_set && new_set && !strcmp(new->prepath, old->prepath)) + return 1; +-- +2.25.1 + + diff --git a/patches.suse/cifs-fix-a-comment-for-the-timeouts-when-sending-echos.patch b/patches.suse/cifs-fix-a-comment-for-the-timeouts-when-sending-echos.patch new file mode 100644 index 0000000..cfbf455 --- /dev/null +++ b/patches.suse/cifs-fix-a-comment-for-the-timeouts-when-sending-echos.patch @@ -0,0 +1,33 @@ +From: Ronnie Sahlberg +Date: Wed, 24 Jul 2019 11:43:49 +1000 +Subject: [PATCH] cifs: fix a comment for the timeouts when sending echos +Git-commit: becc2ba26ae65bfeaece35a1b67e8a54eb9677cf +References: bsc#1144333 +Patch-mainline: v5.4-rc1 + +Clarify a trivial comment + +Signed-off-by: Ronnie Sahlberg +Signed-off-by: Steve French +Acked-by: Paulo Alcantara +--- + fs/cifs/connect.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c +index 5299effa6f7d..4fe559821aff 100644 +--- a/fs/cifs/connect.c ++++ b/fs/cifs/connect.c +@@ -712,7 +712,7 @@ server_unresponsive(struct TCP_Server_Info *server) + * We need to wait 3 echo intervals to make sure we handle such + * situations right: + * 1s client sends a normal SMB request +- * 3s client gets a response ++ * 2s client gets a response + * 30s echo workqueue job pops, and decides we got a response recently + * and don't need to send another + * ... +-- +2.25.1 + + diff --git a/patches.suse/cifs-fix-dereference-on-ses-before-it-is-null-checked.patch b/patches.suse/cifs-fix-dereference-on-ses-before-it-is-null-checked.patch new file mode 100644 index 0000000..60e7631 --- /dev/null +++ b/patches.suse/cifs-fix-dereference-on-ses-before-it-is-null-checked.patch @@ -0,0 +1,80 @@ +From: Colin Ian King +Date: Mon, 2 Sep 2019 16:10:59 +0100 +Subject: [PATCH] cifs: fix dereference on ses before it is null checked +Git-commit: ac6ad7a8c9f6f1fd43262b2273a45ec1fdd3a981 +References: bsc#1144333 +Patch-mainline: v5.4-rc1 + +The assignment of pointer server dereferences pointer ses, however, +this dereference occurs before ses is null checked and hence we +have a potential null pointer dereference. Fix this by only +dereferencing ses after it has been null checked. + +Addresses-Coverity: ("Dereference before null check") +Fixes: 2808c6639104 ("cifs: add new debugging macro cifs_server_dbg") +Signed-off-by: Colin Ian King +Signed-off-by: Steve French +Acked-by: Paulo Alcantara +--- + fs/cifs/smb2pdu.c | 11 ++++++++--- + fs/cifs/transport.c | 3 ++- + 2 files changed, 10 insertions(+), 4 deletions(-) + +diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c +index dbc6ef50dd45..0e92983de0b7 100644 +--- a/fs/cifs/smb2pdu.c ++++ b/fs/cifs/smb2pdu.c +@@ -2759,8 +2759,10 @@ SMB2_ioctl(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid, + else + return -EIO; + ++ if (!ses) ++ return -EIO; + server = ses->server; +- if (!ses || !(server)) ++ if (!server) + return -EIO; + + if (smb3_encryption_required(tcon)) +@@ -3058,13 +3060,16 @@ query_info(const unsigned int xid, struct cifs_tcon *tcon, + int rc = 0; + int resp_buftype = CIFS_NO_BUFFER; + struct cifs_ses *ses = tcon->ses; +- struct TCP_Server_Info *server = ses->server; ++ struct TCP_Server_Info *server; + int flags = 0; + bool allocated = false; + + cifs_dbg(FYI, "Query Info\n"); + +- if (!ses || !(server)) ++ if (!ses) ++ return -EIO; ++ server = ses->server; ++ if (!server) + return -EIO; + + if (smb3_encryption_required(tcon)) +diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c +index 0d60bd2f4dca..a90bd4d75b4d 100644 +--- a/fs/cifs/transport.c ++++ b/fs/cifs/transport.c +@@ -1242,12 +1242,13 @@ SendReceive(const unsigned int xid, struct cifs_ses *ses, + struct kvec iov = { .iov_base = in_buf, .iov_len = len }; + struct smb_rqst rqst = { .rq_iov = &iov, .rq_nvec = 1 }; + struct cifs_credits credits = { .value = 1, .instance = 0 }; +- struct TCP_Server_Info *server = ses->server; ++ struct TCP_Server_Info *server; + + if (ses == NULL) { + cifs_dbg(VFS, "Null smb session\n"); + return -EIO; + } ++ server = ses->server; + if (server == NULL) { + cifs_dbg(VFS, "Null tcp session\n"); + return -EIO; +-- +2.25.1 + + diff --git a/patches.suse/cifs-fix-mode-bits-from-dir-listing-when-mounted-with-modefromsid.patch b/patches.suse/cifs-fix-mode-bits-from-dir-listing-when-mounted-with-modefromsid.patch new file mode 100644 index 0000000..4755485 --- /dev/null +++ b/patches.suse/cifs-fix-mode-bits-from-dir-listing-when-mounted-with-modefromsid.patch @@ -0,0 +1,56 @@ +From: Aurelien Aptel +Date: Thu, 6 Feb 2020 18:16:55 +0100 +Subject: [PATCH] cifs: fix mode bits from dir listing when mounted with + modefromsid +Git-commit: e3e056c35108661e418c803adfc054bf683426e7 +References: bsc#1144333 +Patch-mainline: v5.6-rc1 + +When mounting with -o modefromsid, the mode bits are stored in an +ACE. Directory enumeration (e.g. ls -l /mnt) triggers an SMB Query Dir +which does not include ACEs in its response. The mode bits in this +case are silently set to a default value of 755 instead. + +This patch marks the dentry created during the directory enumeration +as needing re-evaluation (i.e. additional Query Info with ACEs) so +that the mode bits can be properly extracted. + +Quick repro: + +$ mount.cifs //win19.test/data /mnt -o ...,modefromsid +$ touch /mnt/foo && chmod 751 /mnt/foo +$ stat /mnt/foo + # reports 751 (OK) +$ sleep 2 + # dentry older than 1s by default get invalidated +$ ls -l /mnt + # since dentry invalid, ls does a Query Dir + # and reports foo as 755 (WRONG) + +Signed-off-by: Aurelien Aptel +Signed-off-by: Steve French +CC: Stable +Reviewed-by: Pavel Shilovsky +Acked-by: Paulo Alcantara +--- + fs/cifs/readdir.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c +index d17587c2c4ab..ba9dadf3be24 100644 +--- a/fs/cifs/readdir.c ++++ b/fs/cifs/readdir.c +@@ -196,7 +196,8 @@ cifs_fill_common_info(struct cifs_fattr *fattr, struct cifs_sb_info *cifs_sb) + * may look wrong since the inodes may not have timed out by the time + * "ls" does a stat() call on them. + */ +- if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) ++ if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) || ++ (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MODE_FROM_SID)) + fattr->cf_flags |= CIFS_FATTR_NEED_REVAL; + + if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL && +-- +2.25.1 + + diff --git a/patches.suse/cifs-fix-potential-mismatch-of-UNC-paths.patch b/patches.suse/cifs-fix-potential-mismatch-of-UNC-paths.patch new file mode 100644 index 0000000..679cecf --- /dev/null +++ b/patches.suse/cifs-fix-potential-mismatch-of-UNC-paths.patch @@ -0,0 +1,39 @@ +From: "Paulo Alcantara (SUSE)" +Date: Thu, 20 Feb 2020 19:49:35 -0300 +Subject: [PATCH] cifs: fix potential mismatch of UNC paths +Git-commit: 154255233830e1e4dd0d99ac929a5dce588c0b81 +References: bsc#1144333 +Patch-mainline: v5.6-rc4 + +Ensure that full_path is an UNC path that contains '\\' as delimiter, +which is required by cifs_build_devname(). + +The build_path_from_dentry_optional_prefix() function may return a +path with '/' as delimiter when using SMB1 UNIX extensions, for +example. + +Signed-off-by: Paulo Alcantara (SUSE) +Signed-off-by: Steve French +Acked-by: Ronnie Sahlberg +Acked-by: Paulo Alcantara +--- + fs/cifs/cifs_dfs_ref.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/fs/cifs/cifs_dfs_ref.c b/fs/cifs/cifs_dfs_ref.c +index 606f26d862dc..cc3ada12848d 100644 +--- a/fs/cifs/cifs_dfs_ref.c ++++ b/fs/cifs/cifs_dfs_ref.c +@@ -324,6 +324,8 @@ static struct vfsmount *cifs_dfs_do_automount(struct dentry *mntpt) + if (full_path == NULL) + goto cdda_exit; + ++ convert_delimiter(full_path, '\\'); ++ + cifs_dbg(FYI, "%s: full_path: %s\n", __func__, full_path); + + if (!cifs_sb_master_tlink(cifs_sb)) { +-- +2.25.1 + + diff --git a/patches.suse/cifs-fix-rename-by-ensuring-source-handle-opened-wit.patch b/patches.suse/cifs-fix-rename-by-ensuring-source-handle-opened-wit.patch new file mode 100644 index 0000000..b91ea19 --- /dev/null +++ b/patches.suse/cifs-fix-rename-by-ensuring-source-handle-opened-wit.patch @@ -0,0 +1,332 @@ +From: Aurelien Aptel +Date: Fri, 21 Feb 2020 11:19:06 +0100 +Subject: [PATCH] cifs: fix rename() by ensuring source handle opened with + DELETE bit +Git-commit: 86f740f2aed5ea7fe1aa86dc2df0fb4ab0f71088 +References: bsc#1144333 +Patch-mainline: v5.6-rc4 + +To rename a file in SMB2 we open it with the DELETE access and do a +special SetInfo on it. If the handle is missing the DELETE bit the +server will fail the SetInfo with STATUS_ACCESS_DENIED. + +We currently try to reuse any existing opened handle we have with +cifs_get_writable_path(). That function looks for handles with WRITE +access but doesn't check for DELETE, making rename() fail if it finds +a handle to reuse. Simple reproducer below. + +To select handles with the DELETE bit, this patch adds a flag argument +to cifs_get_writable_path() and find_writable_file() and the existing +'bool fsuid_only' argument is converted to a flag. + +The cifsFileInfo struct only stores the UNIX open mode but not the +original SMB access flags. Since the DELETE bit is not mapped in that +mode, this patch stores the access mask in cifs_fid on file open, +which is accessible from cifsFileInfo. + +Simple reproducer: + + #include + #include + #include + #include + #include + #include + #define E(s) perror(s), exit(1) + + int main(int argc, char *argv[]) + { + int fd, ret; + if (argc != 3) { + fprintf(stderr, "Usage: %s A B\n" + "create&open A in write mode, " + "rename A to B, close A\n", argv[0]); + return 0; + } + + fd = openat(AT_FDCWD, argv[1], O_WRONLY|O_CREAT|O_SYNC, 0666); + if (fd == -1) E("openat()"); + + ret = rename(argv[1], argv[2]); + if (ret) E("rename()"); + + ret = close(fd); + if (ret) E("close()"); + + return ret; + } + +$ gcc -o bugrename bugrename.c +$ ./bugrename /mnt/a /mnt/b +rename(): Permission denied + +Fixes: 8de9e86c67ba ("cifs: create a helper to find a writeable handle by path name") +CC: Stable +Signed-off-by: Aurelien Aptel +Signed-off-by: Steve French +Reviewed-by: Pavel Shilovsky +Reviewed-by: Paulo Alcantara (SUSE) +Acked-by: Paulo Alcantara +--- + fs/cifs/cifsglob.h | 7 +++++++ + fs/cifs/cifsproto.h | 5 +++-- + fs/cifs/cifssmb.c | 3 ++- + fs/cifs/file.c | 19 ++++++++++++------- + fs/cifs/inode.c | 6 +++--- + fs/cifs/smb1ops.c | 2 +- + fs/cifs/smb2inode.c | 4 ++-- + fs/cifs/smb2ops.c | 3 ++- + fs/cifs/smb2pdu.c | 1 + + 9 files changed, 33 insertions(+), 17 deletions(-) + +diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h +index de82cfa44b1a..0d956360e984 100644 +--- a/fs/cifs/cifsglob.h ++++ b/fs/cifs/cifsglob.h +@@ -1281,6 +1281,7 @@ struct cifs_fid { + __u64 volatile_fid; /* volatile file id for smb2 */ + __u8 lease_key[SMB2_LEASE_KEY_SIZE]; /* lease key for smb2 */ + __u8 create_guid[16]; ++ __u32 access; + struct cifs_pending_open *pending_open; + unsigned int epoch; + #ifdef CONFIG_CIFS_DEBUG2 +@@ -1741,6 +1742,12 @@ static inline bool is_retryable_error(int error) + return false; + } + ++ ++/* cifs_get_writable_file() flags */ ++#define FIND_WR_ANY 0 ++#define FIND_WR_FSUID_ONLY 1 ++#define FIND_WR_WITH_DELETE 2 ++ + #define MID_FREE 0 + #define MID_REQUEST_ALLOCATED 1 + #define MID_REQUEST_SUBMITTED 2 +diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h +index 89eaaf46d1ca..e5cb681ec138 100644 +--- a/fs/cifs/cifsproto.h ++++ b/fs/cifs/cifsproto.h +@@ -134,11 +134,12 @@ extern bool backup_cred(struct cifs_sb_info *); + extern bool is_size_safe_to_change(struct cifsInodeInfo *, __u64 eof); + extern void cifs_update_eof(struct cifsInodeInfo *cifsi, loff_t offset, + unsigned int bytes_written); +-extern struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *, bool); ++extern struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *, int); + extern int cifs_get_writable_file(struct cifsInodeInfo *cifs_inode, +- bool fsuid_only, ++ int flags, + struct cifsFileInfo **ret_file); + extern int cifs_get_writable_path(struct cifs_tcon *tcon, const char *name, ++ int flags, + struct cifsFileInfo **ret_file); + extern struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *, bool); + extern int cifs_get_readable_path(struct cifs_tcon *tcon, const char *name, +diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c +index 3c89569e7210..6f6fb3606a5d 100644 +--- a/fs/cifs/cifssmb.c ++++ b/fs/cifs/cifssmb.c +@@ -1492,6 +1492,7 @@ CIFS_open(const unsigned int xid, struct cifs_open_parms *oparms, int *oplock, + *oplock = rsp->OplockLevel; + /* cifs fid stays in le */ + oparms->fid->netfid = rsp->Fid; ++ oparms->fid->access = desired_access; + + /* Let caller know file was created so we can set the mode. */ + /* Do we care about the CreateAction in any other cases? */ +@@ -2115,7 +2116,7 @@ cifs_writev_requeue(struct cifs_writedata *wdata) + wdata2->tailsz = tailsz; + wdata2->bytes = cur_len; + +- rc = cifs_get_writable_file(CIFS_I(inode), false, ++ rc = cifs_get_writable_file(CIFS_I(inode), FIND_WR_ANY, + &wdata2->cfile); + if (!wdata2->cfile) { + cifs_dbg(VFS, "No writable handle to retry writepages rc=%d\n", +diff --git a/fs/cifs/file.c b/fs/cifs/file.c +index bc9516ab4b34..3b942ecdd4be 100644 +--- a/fs/cifs/file.c ++++ b/fs/cifs/file.c +@@ -1958,7 +1958,7 @@ struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *cifs_inode, + + /* Return -EBADF if no handle is found and general rc otherwise */ + int +-cifs_get_writable_file(struct cifsInodeInfo *cifs_inode, bool fsuid_only, ++cifs_get_writable_file(struct cifsInodeInfo *cifs_inode, int flags, + struct cifsFileInfo **ret_file) + { + struct cifsFileInfo *open_file, *inv_file = NULL; +@@ -1966,7 +1966,8 @@ cifs_get_writable_file(struct cifsInodeInfo *cifs_inode, bool fsuid_only, + bool any_available = false; + int rc = -EBADF; + unsigned int refind = 0; +- ++ bool fsuid_only = flags & FIND_WR_FSUID_ONLY; ++ bool with_delete = flags & FIND_WR_WITH_DELETE; + *ret_file = NULL; + + /* +@@ -1998,6 +1999,8 @@ cifs_get_writable_file(struct cifsInodeInfo *cifs_inode, bool fsuid_only, + continue; + if (fsuid_only && !uid_eq(open_file->uid, current_fsuid())) + continue; ++ if (with_delete && !(open_file->fid.access & DELETE)) ++ continue; + if (OPEN_FMODE(open_file->f_flags) & FMODE_WRITE) { + if (!open_file->invalidHandle) { + /* found a good writable file */ +@@ -2045,12 +2048,12 @@ cifs_get_writable_file(struct cifsInodeInfo *cifs_inode, bool fsuid_only, + } + + struct cifsFileInfo * +-find_writable_file(struct cifsInodeInfo *cifs_inode, bool fsuid_only) ++find_writable_file(struct cifsInodeInfo *cifs_inode, int flags) + { + struct cifsFileInfo *cfile; + int rc; + +- rc = cifs_get_writable_file(cifs_inode, fsuid_only, &cfile); ++ rc = cifs_get_writable_file(cifs_inode, flags, &cfile); + if (rc) + cifs_dbg(FYI, "couldn't find writable handle rc=%d", rc); + +@@ -2059,6 +2062,7 @@ find_writable_file(struct cifsInodeInfo *cifs_inode, bool fsuid_only) + + int + cifs_get_writable_path(struct cifs_tcon *tcon, const char *name, ++ int flags, + struct cifsFileInfo **ret_file) + { + struct list_head *tmp; +@@ -2085,7 +2089,7 @@ cifs_get_writable_path(struct cifs_tcon *tcon, const char *name, + kfree(full_path); + cinode = CIFS_I(d_inode(cfile->dentry)); + spin_unlock(&tcon->open_file_lock); +- return cifs_get_writable_file(cinode, 0, ret_file); ++ return cifs_get_writable_file(cinode, flags, ret_file); + } + + spin_unlock(&tcon->open_file_lock); +@@ -2162,7 +2166,8 @@ static int cifs_partialpagewrite(struct page *page, unsigned from, unsigned to) + if (mapping->host->i_size - offset < (loff_t)to) + to = (unsigned)(mapping->host->i_size - offset); + +- rc = cifs_get_writable_file(CIFS_I(mapping->host), false, &open_file); ++ rc = cifs_get_writable_file(CIFS_I(mapping->host), FIND_WR_ANY, ++ &open_file); + if (!rc) { + bytes_written = cifs_write(open_file, open_file->pid, + write_data, to - from, &offset); +@@ -2355,7 +2360,7 @@ static int cifs_writepages(struct address_space *mapping, + if (cfile) + cifsFileInfo_put(cfile); + +- rc = cifs_get_writable_file(CIFS_I(inode), false, &cfile); ++ rc = cifs_get_writable_file(CIFS_I(inode), FIND_WR_ANY, &cfile); + + /* in case of an error store it to return later */ + if (rc) +diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c +index 1c6f659110d0..49dbf11e2c3f 100644 +--- a/fs/cifs/inode.c ++++ b/fs/cifs/inode.c +@@ -2282,7 +2282,7 @@ cifs_set_file_size(struct inode *inode, struct iattr *attrs, + * writebehind data than the SMB timeout for the SetPathInfo + * request would allow + */ +- open_file = find_writable_file(cifsInode, true); ++ open_file = find_writable_file(cifsInode, FIND_WR_FSUID_ONLY); + if (open_file) { + tcon = tlink_tcon(open_file->tlink); + server = tcon->ses->server; +@@ -2432,7 +2432,7 @@ cifs_setattr_unix(struct dentry *direntry, struct iattr *attrs) + args->ctime = NO_CHANGE_64; + + args->device = 0; +- open_file = find_writable_file(cifsInode, true); ++ open_file = find_writable_file(cifsInode, FIND_WR_FSUID_ONLY); + if (open_file) { + u16 nfid = open_file->fid.netfid; + u32 npid = open_file->pid; +@@ -2535,7 +2535,7 @@ cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs) + rc = 0; + + if (attrs->ia_valid & ATTR_MTIME) { +- rc = cifs_get_writable_file(cifsInode, false, &wfile); ++ rc = cifs_get_writable_file(cifsInode, FIND_WR_ANY, &wfile); + if (!rc) { + tcon = tlink_tcon(wfile->tlink); + rc = tcon->ses->server->ops->flush(xid, tcon, &wfile->fid); +diff --git a/fs/cifs/smb1ops.c b/fs/cifs/smb1ops.c +index eb994e313c6a..b130efaf8feb 100644 +--- a/fs/cifs/smb1ops.c ++++ b/fs/cifs/smb1ops.c +@@ -766,7 +766,7 @@ smb_set_file_info(struct inode *inode, const char *full_path, + struct cifs_tcon *tcon; + + /* if the file is already open for write, just use that fileid */ +- open_file = find_writable_file(cinode, true); ++ open_file = find_writable_file(cinode, FIND_WR_FSUID_ONLY); + if (open_file) { + fid.netfid = open_file->fid.netfid; + netpid = open_file->pid; +diff --git a/fs/cifs/smb2inode.c b/fs/cifs/smb2inode.c +index 1cf207564ff9..a8c301ae00ed 100644 +--- a/fs/cifs/smb2inode.c ++++ b/fs/cifs/smb2inode.c +@@ -521,7 +521,7 @@ smb2_mkdir_setinfo(struct inode *inode, const char *name, + cifs_i = CIFS_I(inode); + dosattrs = cifs_i->cifsAttrs | ATTR_READONLY; + data.Attributes = cpu_to_le32(dosattrs); +- cifs_get_writable_path(tcon, name, &cfile); ++ cifs_get_writable_path(tcon, name, FIND_WR_ANY, &cfile); + tmprc = smb2_compound_op(xid, tcon, cifs_sb, name, + FILE_WRITE_ATTRIBUTES, FILE_CREATE, + CREATE_NOT_FILE, ACL_NO_MODE, +@@ -577,7 +577,7 @@ smb2_rename_path(const unsigned int xid, struct cifs_tcon *tcon, + { + struct cifsFileInfo *cfile; + +- cifs_get_writable_path(tcon, from_name, &cfile); ++ cifs_get_writable_path(tcon, from_name, FIND_WR_WITH_DELETE, &cfile); + + return smb2_set_path_attr(xid, tcon, from_name, to_name, + cifs_sb, DELETE, SMB2_OP_RENAME, cfile); +diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c +index e47190cae163..c31e84ee3c39 100644 +--- a/fs/cifs/smb2ops.c ++++ b/fs/cifs/smb2ops.c +@@ -1364,6 +1364,7 @@ smb2_set_fid(struct cifsFileInfo *cfile, struct cifs_fid *fid, __u32 oplock) + + cfile->fid.persistent_fid = fid->persistent_fid; + cfile->fid.volatile_fid = fid->volatile_fid; ++ cfile->fid.access = fid->access; + #ifdef CONFIG_CIFS_DEBUG2 + cfile->fid.mid = fid->mid; + #endif /* CIFS_DEBUG2 */ +@@ -3327,7 +3328,7 @@ static loff_t smb3_llseek(struct file *file, struct cifs_tcon *tcon, loff_t offs + * some servers (Windows2016) will not reflect recent writes in + * QUERY_ALLOCATED_RANGES until SMB2_flush is called. + */ +- wrcfile = find_writable_file(cifsi, false); ++ wrcfile = find_writable_file(cifsi, FIND_WR_ANY); + if (wrcfile) { + filemap_write_and_wait(inode->i_mapping); + smb2_flush_file(xid, tcon, &wrcfile->fid); +diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c +index 1234f9ccab03..28c0be5e69b7 100644 +--- a/fs/cifs/smb2pdu.c ++++ b/fs/cifs/smb2pdu.c +@@ -2771,6 +2771,7 @@ SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms, __le16 *path, + atomic_inc(&tcon->num_remote_opens); + oparms->fid->persistent_fid = rsp->PersistentFileId; + oparms->fid->volatile_fid = rsp->VolatileFileId; ++ oparms->fid->access = oparms->desired_access; + #ifdef CONFIG_CIFS_DEBUG2 + oparms->fid->mid = le64_to_cpu(rsp->sync_hdr.MessageId); + #endif /* CIFS_DEBUG2 */ +-- +2.25.1 + + diff --git a/patches.suse/cifs-fix-soft-mounts-hanging-in-the-reconnect-code-2.patch b/patches.suse/cifs-fix-soft-mounts-hanging-in-the-reconnect-code-2.patch new file mode 100644 index 0000000..ae75342 --- /dev/null +++ b/patches.suse/cifs-fix-soft-mounts-hanging-in-the-reconnect-code-2.patch @@ -0,0 +1,56 @@ +From 09c40b15351c1bb1af035f7f6df167366d552790 Mon Sep 17 00:00:00 2001 +From: Ronnie Sahlberg +Date: Thu, 6 Feb 2020 13:55:19 +1000 +Subject: [PATCH] cifs: fix soft mounts hanging in the reconnect code +Git-commit: 09c40b15351c1bb1af035f7f6df167366d552790 +References: bsc#1144333 +Patch-mainline: v5.6-rc1 + +RHBZ: 1795423 + +This is the SMB1 version of a patch we already have for SMB2 + +In recent DFS updates we have a new variable controlling how many times we will +retry to reconnect the share. +If DFS is not used, then this variable is initialized to 0 in: + +static inline int +dfs_cache_get_nr_tgts(const struct dfs_cache_tgt_list *tl) +{ + return tl ? tl->tl_numtgts : 0; +} + +This means that in the reconnect loop in smb2_reconnect() we will immediately wrap retries to -1 +and never actually get to pass this conditional: + + if (--retries) + continue; + +The effect is that we no longer reach the point where we fail the commands with -EHOSTDOWN +and basically the kernel threads are virtually hung and unkillable. + +Signed-off-by: Ronnie Sahlberg +Signed-off-by: Steve French +Reviewed-by: Aurelien Aptel +Reviewed-by: Paulo Alcantara (SUSE) +Acked-by: Paulo Alcantara +--- + fs/cifs/cifssmb.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c +index a481296f417f..3c89569e7210 100644 +--- a/fs/cifs/cifssmb.c ++++ b/fs/cifs/cifssmb.c +@@ -260,7 +260,7 @@ cifs_reconnect_tcon(struct cifs_tcon *tcon, int smb_command) + if (server->tcpStatus != CifsNeedReconnect) + break; + +- if (--retries) ++ if (retries && --retries) + continue; + + /* +-- +2.25.1 + diff --git a/patches.suse/cifs-fix-soft-mounts-hanging-in-the-reconnect-code.patch b/patches.suse/cifs-fix-soft-mounts-hanging-in-the-reconnect-code.patch new file mode 100644 index 0000000..e4137a1 --- /dev/null +++ b/patches.suse/cifs-fix-soft-mounts-hanging-in-the-reconnect-code.patch @@ -0,0 +1,55 @@ +From: Ronnie Sahlberg +Date: Fri, 31 Jan 2020 05:52:51 +1000 +Subject: [PATCH] cifs: fix soft mounts hanging in the reconnect code +Git-commit: c54849ddd832ae0a45cab16bcd1ed2db7da090d7 +References: bsc#1144333 +Patch-mainline: v5.6-rc1 + +RHBZ: 1795429 + +In recent DFS updates we have a new variable controlling how many times we will +retry to reconnect the share. +If DFS is not used, then this variable is initialized to 0 in: + +static inline int +dfs_cache_get_nr_tgts(const struct dfs_cache_tgt_list *tl) +{ + return tl ? tl->tl_numtgts : 0; +} + +This means that in the reconnect loop in smb2_reconnect() we will immediately wrap retries to -1 +and never actually get to pass this conditional: + + if (--retries) + continue; + +The effect is that we no longer reach the point where we fail the commands with -EHOSTDOWN +and basically the kernel threads are virtually hung and unkillable. + +Fixes: a3a53b7603798fd8 (cifs: Add support for failover in smb2_reconnect()) +Signed-off-by: Ronnie Sahlberg +Signed-off-by: Steve French +Reviewed-by: Paulo Alcantara (SUSE) +CC: Stable +Acked-by: Paulo Alcantara +--- + fs/cifs/smb2pdu.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c +index 7edba3e6d5e6..14f209f7376f 100644 +--- a/fs/cifs/smb2pdu.c ++++ b/fs/cifs/smb2pdu.c +@@ -312,7 +312,7 @@ smb2_reconnect(__le16 smb2_command, struct cifs_tcon *tcon) + if (server->tcpStatus != CifsNeedReconnect) + break; + +- if (--retries) ++ if (retries && --retries) + continue; + + /* +-- +2.25.1 + + diff --git a/patches.suse/cifs-fix-unitialized-variable-poential-problem-with-network-I-O-cac.patch b/patches.suse/cifs-fix-unitialized-variable-poential-problem-with-network-I-O-cac.patch new file mode 100644 index 0000000..19e1698 --- /dev/null +++ b/patches.suse/cifs-fix-unitialized-variable-poential-problem-with-network-I-O-cac.patch @@ -0,0 +1,42 @@ +From: Steve French +Date: Thu, 16 Jan 2020 15:58:00 -0600 +Subject: [PATCH] cifs: fix unitialized variable poential problem with network + I/O cache lock patch +Git-commit: 463a7b457c02250a84faa1d23c52da9e3364aed2 +References: bsc#1144333 +Patch-mainline: v5.6-rc1 + +static analysis with Coverity detected an issue with the following +commit: + + Author: Paulo Alcantara (SUSE) + Date: Wed Dec 4 17:38:03 2019 -0300 + + cifs: Avoid doing network I/O while holding cache lock + +Addresses-Coverity: ("Uninitialized pointer read") +Reported-by: Colin Ian King +Signed-off-by: Paulo Alcantara (SUSE) +Signed-off-by: Steve French +Acked-by: Paulo Alcantara +--- + fs/cifs/dfs_cache.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/fs/cifs/dfs_cache.c b/fs/cifs/dfs_cache.c +index 2bbfe283fb52..b0315b7270b4 100644 +--- a/fs/cifs/dfs_cache.c ++++ b/fs/cifs/dfs_cache.c +@@ -1349,7 +1349,7 @@ static struct cifs_ses *find_root_ses(struct vol_info *vi, + char *mdata = NULL, *devname = NULL; + struct TCP_Server_Info *server; + struct cifs_ses *ses; +- struct smb_vol vol; ++ struct smb_vol vol = {NULL}; + + rpath = get_dfs_root(path); + if (IS_ERR(rpath)) +-- +2.25.1 + + diff --git a/patches.suse/cifs-get-mode-bits-from-special-sid-on-stat.patch b/patches.suse/cifs-get-mode-bits-from-special-sid-on-stat.patch new file mode 100644 index 0000000..3e8f75c --- /dev/null +++ b/patches.suse/cifs-get-mode-bits-from-special-sid-on-stat.patch @@ -0,0 +1,164 @@ +From: Steve French +Date: Fri, 19 Jul 2019 06:30:07 +0000 +Subject: [PATCH] cifs: get mode bits from special sid on stat +Git-commit: e2f8fbfb8d09c06decde162090fac3ee220aa280 +References: bsc#1144333 +Patch-mainline: v5.4-rc1 + +When mounting with "modefromsid" retrieve mode bits from +special SID (S-1-5-88-3) on stat. Subsequent patch will fix +setattr (chmod) to save mode bits in S-1-5-88-3- + +Note that when an ACE matching S-1-5-88-3 is not found, we +default the mode to an approximation based on the owner, group +and everyone permissions (as with the "cifsacl" mount option). + +See See e.g. + https://docs.microsoft.com/en-us/previous-versions/windows/it-pro/windows-server-2008-R2-and-2008/hh509017(v=ws.10) + +Signed-off-by: Steve French +Acked-by: Paulo Alcantara +--- + fs/cifs/cifsacl.c | 37 ++++++++++++++++++++++++++----------- + fs/cifs/cifsproto.h | 1 + + fs/cifs/inode.c | 13 +++++++++++-- + 3 files changed, 38 insertions(+), 13 deletions(-) + +diff --git a/fs/cifs/cifsacl.c b/fs/cifs/cifsacl.c +index 1d377b7f2860..7fe4509e6c03 100644 +--- a/fs/cifs/cifsacl.c ++++ b/fs/cifs/cifsacl.c +@@ -701,10 +701,9 @@ static void dump_ace(struct cifs_ace *pace, char *end_of_acl) + } + #endif + +- + static void parse_dacl(struct cifs_acl *pdacl, char *end_of_acl, + struct cifs_sid *pownersid, struct cifs_sid *pgrpsid, +- struct cifs_fattr *fattr) ++ struct cifs_fattr *fattr, bool mode_from_special_sid) + { + int i; + int num_aces = 0; +@@ -757,22 +756,34 @@ static void parse_dacl(struct cifs_acl *pdacl, char *end_of_acl, + #ifdef CONFIG_CIFS_DEBUG2 + dump_ace(ppace[i], end_of_acl); + #endif +- if (compare_sids(&(ppace[i]->sid), pownersid) == 0) ++ if (mode_from_special_sid && ++ (compare_sids(&(ppace[i]->sid), ++ &sid_unix_NFS_mode) == 0)) { ++ /* ++ * Full permissions are: ++ * 07777 = S_ISUID | S_ISGID | S_ISVTX | ++ * S_IRWXU | S_IRWXG | S_IRWXO ++ */ ++ fattr->cf_mode &= ~07777; ++ fattr->cf_mode |= ++ le32_to_cpu(ppace[i]->sid.sub_auth[2]); ++ break; ++ } else if (compare_sids(&(ppace[i]->sid), pownersid) == 0) + access_flags_to_mode(ppace[i]->access_req, + ppace[i]->type, + &fattr->cf_mode, + &user_mask); +- if (compare_sids(&(ppace[i]->sid), pgrpsid) == 0) ++ else if (compare_sids(&(ppace[i]->sid), pgrpsid) == 0) + access_flags_to_mode(ppace[i]->access_req, + ppace[i]->type, + &fattr->cf_mode, + &group_mask); +- if (compare_sids(&(ppace[i]->sid), &sid_everyone) == 0) ++ else if (compare_sids(&(ppace[i]->sid), &sid_everyone) == 0) + access_flags_to_mode(ppace[i]->access_req, + ppace[i]->type, + &fattr->cf_mode, + &other_mask); +- if (compare_sids(&(ppace[i]->sid), &sid_authusers) == 0) ++ else if (compare_sids(&(ppace[i]->sid), &sid_authusers) == 0) + access_flags_to_mode(ppace[i]->access_req, + ppace[i]->type, + &fattr->cf_mode, +@@ -851,7 +862,8 @@ static int parse_sid(struct cifs_sid *psid, char *end_of_acl) + + /* Convert CIFS ACL to POSIX form */ + static int parse_sec_desc(struct cifs_sb_info *cifs_sb, +- struct cifs_ntsd *pntsd, int acl_len, struct cifs_fattr *fattr) ++ struct cifs_ntsd *pntsd, int acl_len, struct cifs_fattr *fattr, ++ bool get_mode_from_special_sid) + { + int rc = 0; + struct cifs_sid *owner_sid_ptr, *group_sid_ptr; +@@ -900,7 +912,7 @@ static int parse_sec_desc(struct cifs_sb_info *cifs_sb, + + if (dacloffset) + parse_dacl(dacl_ptr, end_of_acl, owner_sid_ptr, +- group_sid_ptr, fattr); ++ group_sid_ptr, fattr, get_mode_from_special_sid); + else + cifs_dbg(FYI, "no ACL\n"); /* BB grant all or default perms? */ + +@@ -1128,8 +1140,8 @@ int set_cifs_acl(struct cifs_ntsd *pnntsd, __u32 acllen, + /* Translate the CIFS ACL (similar to NTFS ACL) for a file into mode bits */ + int + cifs_acl_to_fattr(struct cifs_sb_info *cifs_sb, struct cifs_fattr *fattr, +- struct inode *inode, const char *path, +- const struct cifs_fid *pfid) ++ struct inode *inode, bool mode_from_special_sid, ++ const char *path, const struct cifs_fid *pfid) + { + struct cifs_ntsd *pntsd = NULL; + u32 acllen = 0; +@@ -1156,8 +1168,11 @@ cifs_acl_to_fattr(struct cifs_sb_info *cifs_sb, struct cifs_fattr *fattr, + if (IS_ERR(pntsd)) { + rc = PTR_ERR(pntsd); + cifs_dbg(VFS, "%s: error %d getting sec desc\n", __func__, rc); ++ } else if (mode_from_special_sid) { ++ rc = parse_sec_desc(cifs_sb, pntsd, acllen, fattr, true); + } else { +- rc = parse_sec_desc(cifs_sb, pntsd, acllen, fattr); ++ /* get approximated mode from ACL */ ++ rc = parse_sec_desc(cifs_sb, pntsd, acllen, fattr, false); + kfree(pntsd); + if (rc) + cifs_dbg(VFS, "parse sec desc failed rc = %d\n", rc); +diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h +index 592a6cea2b79..dd75746e60cd 100644 +--- a/fs/cifs/cifsproto.h ++++ b/fs/cifs/cifsproto.h +@@ -197,6 +197,7 @@ extern int cifs_rename_pending_delete(const char *full_path, + const unsigned int xid); + extern int cifs_acl_to_fattr(struct cifs_sb_info *cifs_sb, + struct cifs_fattr *fattr, struct inode *inode, ++ bool get_mode_from_special_sid, + const char *path, const struct cifs_fid *pfid); + extern int id_mode_to_cifs_acl(struct inode *inode, const char *path, __u64, + kuid_t, kgid_t); +diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c +index 56ca4b8ccaba..c1e620ebcf7c 100644 +--- a/fs/cifs/inode.c ++++ b/fs/cifs/inode.c +@@ -893,8 +893,17 @@ cifs_get_inode_info(struct inode **inode, const char *full_path, + } + + /* fill in 0777 bits from ACL */ +- if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) { +- rc = cifs_acl_to_fattr(cifs_sb, &fattr, *inode, full_path, fid); ++ if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MODE_FROM_SID) { ++ rc = cifs_acl_to_fattr(cifs_sb, &fattr, *inode, true, ++ full_path, fid); ++ if (rc) { ++ cifs_dbg(FYI, "%s: Get mode from SID failed. rc=%d\n", ++ __func__, rc); ++ goto cgii_exit; ++ } ++ } else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) { ++ rc = cifs_acl_to_fattr(cifs_sb, &fattr, *inode, false, ++ full_path, fid); + if (rc) { + cifs_dbg(FYI, "%s: Getting ACL failed with error: %d\n", + __func__, rc); +-- +2.25.1 + + diff --git a/patches.suse/cifs-handle-prefix-paths-in-reconnect.patch b/patches.suse/cifs-handle-prefix-paths-in-reconnect.patch new file mode 100644 index 0000000..489c22d --- /dev/null +++ b/patches.suse/cifs-handle-prefix-paths-in-reconnect.patch @@ -0,0 +1,388 @@ +From fac55a2a6164dd9562119aa0f5848d5afb08cb55 Mon Sep 17 00:00:00 2001 +From: "Paulo Alcantara (SUSE)" +Date: Thu, 20 Feb 2020 19:49:34 -0300 +Subject: [PATCH] cifs: handle prefix paths in reconnect +Patch-mainline: Not yet, in for-next branch +References: bsc#1144333 + +For the case where we have a DFS path like below and we're currently +connected to targetA: + + //dfsroot/link -> //targetA/share/foo, //targetB/share/bar + +after failover, we should make sure to update cifs_sb->prepath so the +next operations will use the new prefix path "/bar". + +Besides, in order to simplify the use of different prefix paths, +enforce CIFS_MOUNT_USE_PREFIX_PATH for DFS mounts so we don't have to +revalidate the root dentry every time we set a new prefix path. + +Signed-off-by: Paulo Alcantara (SUSE) +Signed-off-by: Steve French +Acked-by: Ronnie Sahlberg +Reviewed-by: Aurelien Aptel +Signed-off-by: Steve French +Acked-by: Paulo Alcantara +--- + fs/cifs/cifsproto.h | 5 +++ + fs/cifs/cifssmb.c | 19 +++++++++--- + fs/cifs/connect.c | 63 +++++++--------------------------------- + fs/cifs/dfs_cache.c | 38 ++++++++++++++++++++++++ + fs/cifs/dfs_cache.h | 4 ++ + fs/cifs/misc.c | 80 ++++++++++++++++++++++++++++++++++++++++++++++++++++ + fs/cifs/smb2pdu.c | 19 +++++++++--- + 7 files changed, 169 insertions(+), 59 deletions(-) + +--- a/fs/cifs/cifsproto.h ++++ b/fs/cifs/cifsproto.h +@@ -594,6 +594,11 @@ int smb2_parse_query_directory(struct ci + int resp_buftype, + struct cifs_search_info *srch_inf); + ++struct super_block *cifs_get_tcp_super(struct TCP_Server_Info *server); ++void cifs_put_tcp_super(struct super_block *sb); ++int update_super_prepath(struct cifs_tcon *tcon, const char *prefix, ++ size_t prefix_len); ++ + #ifdef CONFIG_CIFS_DFS_UPCALL + static inline int get_dfs_path(const unsigned int xid, struct cifs_ses *ses, + const char *old_path, +--- a/fs/cifs/cifssmb.c ++++ b/fs/cifs/cifssmb.c +@@ -162,9 +162,18 @@ static int __cifs_reconnect_tcon(const s + + for (it = dfs_cache_get_tgt_iterator(&tl); it; + it = dfs_cache_get_next_tgt(&tl, it)) { +- const char *tgt = dfs_cache_get_tgt_name(it); ++ const char *share, *prefix; ++ size_t share_len, prefix_len; + +- extract_unc_hostname(tgt, &dfs_host, &dfs_host_len); ++ rc = dfs_cache_get_tgt_share(it, &share, &share_len, &prefix, ++ &prefix_len); ++ if (rc) { ++ cifs_dbg(VFS, "%s: failed to parse target share %d\n", ++ __func__, rc); ++ continue; ++ } ++ ++ extract_unc_hostname(share, &dfs_host, &dfs_host_len); + + if (dfs_host_len != tcp_host_len + || strncasecmp(dfs_host, tcp_host, dfs_host_len) != 0) { +@@ -175,11 +184,13 @@ static int __cifs_reconnect_tcon(const s + continue; + } + +- scnprintf(tree, MAX_TREE_SIZE, "\\%s", tgt); ++ scnprintf(tree, MAX_TREE_SIZE, "\\%.*s", (int)share_len, share); + + rc = CIFSTCon(0, tcon->ses, tree, tcon, nlsc); +- if (!rc) ++ if (!rc) { ++ rc = update_super_prepath(tcon, prefix, prefix_len); + break; ++ } + if (rc == -EREMOTE) + break; + } +--- a/fs/cifs/connect.c ++++ b/fs/cifs/connect.c +@@ -57,7 +57,6 @@ + #include "smb2proto.h" + #include "smbdirect.h" + #include "dns_resolve.h" +-#include "cifsfs.h" + #ifdef CONFIG_CIFS_DFS_UPCALL + #include "dfs_cache.h" + #endif +@@ -384,54 +383,7 @@ static inline int reconn_set_ipaddr(stru + #endif + + #ifdef CONFIG_CIFS_DFS_UPCALL +-struct super_cb_data { +- struct TCP_Server_Info *server; +- struct super_block *sb; +-}; +- + /* These functions must be called with server->srv_mutex held */ +- +-static void super_cb(struct super_block *sb, void *arg) +-{ +- struct super_cb_data *d = arg; +- struct cifs_sb_info *cifs_sb; +- struct cifs_tcon *tcon; +- +- if (d->sb) +- return; +- +- cifs_sb = CIFS_SB(sb); +- tcon = cifs_sb_master_tcon(cifs_sb); +- if (tcon->ses->server == d->server) +- d->sb = sb; +-} +- +-static struct super_block *get_tcp_super(struct TCP_Server_Info *server) +-{ +- struct super_cb_data d = { +- .server = server, +- .sb = NULL, +- }; +- +- iterate_supers_type(&cifs_fs_type, super_cb, &d); +- +- if (unlikely(!d.sb)) +- return ERR_PTR(-ENOENT); +- /* +- * Grab an active reference in order to prevent automounts (DFS links) +- * of expiring and then freeing up our cifs superblock pointer while +- * we're doing failover. +- */ +- cifs_sb_active(d.sb); +- return d.sb; +-} +- +-static inline void put_tcp_super(struct super_block *sb) +-{ +- if (!IS_ERR_OR_NULL(sb)) +- cifs_sb_deactive(sb); +-} +- + static void reconn_inval_dfs_target(struct TCP_Server_Info *server, + struct cifs_sb_info *cifs_sb, + struct dfs_cache_tgt_list *tgt_list, +@@ -503,7 +455,7 @@ cifs_reconnect(struct TCP_Server_Info *s + server->nr_targets = 1; + #ifdef CONFIG_CIFS_DFS_UPCALL + spin_unlock(&GlobalMid_Lock); +- sb = get_tcp_super(server); ++ sb = cifs_get_tcp_super(server); + if (IS_ERR(sb)) { + rc = PTR_ERR(sb); + cifs_dbg(FYI, "%s: will not do DFS failover: rc = %d\n", +@@ -530,7 +482,7 @@ cifs_reconnect(struct TCP_Server_Info *s + spin_unlock(&GlobalMid_Lock); + #ifdef CONFIG_CIFS_DFS_UPCALL + dfs_cache_free_tgts(&tgt_list); +- put_tcp_super(sb); ++ cifs_put_tcp_super(sb); + #endif + return rc; + } else +@@ -661,7 +613,7 @@ cifs_reconnect(struct TCP_Server_Info *s + + } + +- put_tcp_super(sb); ++ cifs_put_tcp_super(sb); + #endif + if (server->tcpStatus == CifsNeedNegotiate) + mod_delayed_work(cifsiod_wq, &server->echo, 0); +@@ -4927,6 +4879,15 @@ int cifs_mount(struct cifs_sb_info *cifs + * dentry revalidation to think the dentry are stale (ESTALE). + */ + cifs_autodisable_serverino(cifs_sb); ++ /* ++ * Force the use of prefix path to support failover on DFS paths that ++ * resolve to targets that have different prefix paths. ++ */ ++ cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_USE_PREFIX_PATH; ++ kfree(cifs_sb->prepath); ++ cifs_sb->prepath = vol->prepath; ++ vol->prepath = NULL; ++ + out: + free_xid(xid); + return mount_setup_tlink(cifs_sb, ses, tcon); +--- a/fs/cifs/dfs_cache.c ++++ b/fs/cifs/dfs_cache.c +@@ -1257,6 +1257,44 @@ void dfs_cache_del_vol(const char *fullp + kref_put(&vi->refcnt, vol_release); + } + ++/** ++ * dfs_cache_get_tgt_share - parse a DFS target ++ * ++ * @it: DFS target iterator. ++ * @share: tree name. ++ * @share_len: length of tree name. ++ * @prefix: prefix path. ++ * @prefix_len: length of prefix path. ++ * ++ * Return zero if target was parsed correctly, otherwise non-zero. ++ */ ++int dfs_cache_get_tgt_share(const struct dfs_cache_tgt_iterator *it, ++ const char **share, size_t *share_len, ++ const char **prefix, size_t *prefix_len) ++{ ++ char *s, sep; ++ ++ if (!it || !share || !share_len || !prefix || !prefix_len) ++ return -EINVAL; ++ ++ sep = it->it_name[0]; ++ if (sep != '\\' && sep != '/') ++ return -EINVAL; ++ ++ s = strchr(it->it_name + 1, sep); ++ if (!s) ++ return -EINVAL; ++ ++ s = strchrnul(s + 1, sep); ++ ++ *share = it->it_name; ++ *share_len = s - it->it_name; ++ *prefix = *s ? s + 1 : s; ++ *prefix_len = &it->it_name[strlen(it->it_name)] - *prefix; ++ ++ return 0; ++} ++ + /* Get all tcons that are within a DFS namespace and can be refreshed */ + static void get_tcons(struct TCP_Server_Info *server, struct list_head *head) + { +--- a/fs/cifs/dfs_cache.h ++++ b/fs/cifs/dfs_cache.h +@@ -49,6 +49,10 @@ extern int dfs_cache_update_vol(const ch + struct TCP_Server_Info *server); + extern void dfs_cache_del_vol(const char *fullpath); + ++extern int dfs_cache_get_tgt_share(const struct dfs_cache_tgt_iterator *it, ++ const char **share, size_t *share_len, ++ const char **prefix, size_t *prefix_len); ++ + static inline struct dfs_cache_tgt_iterator * + dfs_cache_get_next_tgt(struct dfs_cache_tgt_list *tl, + struct dfs_cache_tgt_iterator *it) +--- a/fs/cifs/misc.c ++++ b/fs/cifs/misc.c +@@ -31,6 +31,7 @@ + #include "nterr.h" + #include "cifs_unicode.h" + #include "smb2pdu.h" ++#include "cifsfs.h" + + extern mempool_t *cifs_sm_req_poolp; + extern mempool_t *cifs_req_poolp; +@@ -1038,3 +1039,82 @@ int copy_path_name(char *dst, const char + name_len++; + return name_len; + } ++ ++struct super_cb_data { ++ struct TCP_Server_Info *server; ++ struct super_block *sb; ++}; ++ ++static void super_cb(struct super_block *sb, void *arg) ++{ ++ struct super_cb_data *d = arg; ++ struct cifs_sb_info *cifs_sb; ++ struct cifs_tcon *tcon; ++ ++ if (d->sb) ++ return; ++ ++ cifs_sb = CIFS_SB(sb); ++ tcon = cifs_sb_master_tcon(cifs_sb); ++ if (tcon->ses->server == d->server) ++ d->sb = sb; ++} ++ ++struct super_block *cifs_get_tcp_super(struct TCP_Server_Info *server) ++{ ++ struct super_cb_data d = { ++ .server = server, ++ .sb = NULL, ++ }; ++ ++ iterate_supers_type(&cifs_fs_type, super_cb, &d); ++ ++ if (unlikely(!d.sb)) ++ return ERR_PTR(-ENOENT); ++ /* ++ * Grab an active reference in order to prevent automounts (DFS links) ++ * of expiring and then freeing up our cifs superblock pointer while ++ * we're doing failover. ++ */ ++ cifs_sb_active(d.sb); ++ return d.sb; ++} ++ ++void cifs_put_tcp_super(struct super_block *sb) ++{ ++ if (!IS_ERR_OR_NULL(sb)) ++ cifs_sb_deactive(sb); ++} ++ ++int update_super_prepath(struct cifs_tcon *tcon, const char *prefix, ++ size_t prefix_len) ++{ ++ struct super_block *sb; ++ struct cifs_sb_info *cifs_sb; ++ int rc = 0; ++ ++ sb = cifs_get_tcp_super(tcon->ses->server); ++ if (IS_ERR(sb)) ++ return PTR_ERR(sb); ++ ++ cifs_sb = CIFS_SB(sb); ++ ++ kfree(cifs_sb->prepath); ++ ++ if (*prefix && prefix_len) { ++ cifs_sb->prepath = kstrndup(prefix, prefix_len, GFP_ATOMIC); ++ if (!cifs_sb->prepath) { ++ rc = -ENOMEM; ++ goto out; ++ } ++ ++ convert_delimiter(cifs_sb->prepath, CIFS_DIR_SEP(cifs_sb)); ++ } else ++ cifs_sb->prepath = NULL; ++ ++ cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_USE_PREFIX_PATH; ++ ++out: ++ cifs_put_tcp_super(sb); ++ return rc; ++} +--- a/fs/cifs/smb2pdu.c ++++ b/fs/cifs/smb2pdu.c +@@ -193,9 +193,18 @@ static int __smb2_reconnect(const struct + + for (it = dfs_cache_get_tgt_iterator(&tl); it; + it = dfs_cache_get_next_tgt(&tl, it)) { +- const char *tgt = dfs_cache_get_tgt_name(it); ++ const char *share, *prefix; ++ size_t share_len, prefix_len; + +- extract_unc_hostname(tgt, &dfs_host, &dfs_host_len); ++ rc = dfs_cache_get_tgt_share(it, &share, &share_len, &prefix, ++ &prefix_len); ++ if (rc) { ++ cifs_dbg(VFS, "%s: failed to parse target share %d\n", ++ __func__, rc); ++ continue; ++ } ++ ++ extract_unc_hostname(share, &dfs_host, &dfs_host_len); + + if (dfs_host_len != tcp_host_len + || strncasecmp(dfs_host, tcp_host, dfs_host_len) != 0) { +@@ -206,11 +215,13 @@ static int __smb2_reconnect(const struct + continue; + } + +- scnprintf(tree, MAX_TREE_SIZE, "\\%s", tgt); ++ scnprintf(tree, MAX_TREE_SIZE, "\\%.*s", (int)share_len, share); + + rc = SMB2_tcon(0, tcon->ses, tree, tcon, nlsc); +- if (!rc) ++ if (!rc) { ++ rc = update_super_prepath(tcon, prefix, prefix_len); + break; ++ } + if (rc == -EREMOTE) + break; + } diff --git a/patches.suse/cifs-log-warning-message-once-if-out-of-disk-space.patch b/patches.suse/cifs-log-warning-message-once-if-out-of-disk-space.patch new file mode 100644 index 0000000..397ec5c --- /dev/null +++ b/patches.suse/cifs-log-warning-message-once-if-out-of-disk-space.patch @@ -0,0 +1,41 @@ +From: Steve French +Date: Wed, 5 Feb 2020 16:52:11 -0600 +Subject: [PATCH] cifs: log warning message (once) if out of disk space +Git-commit: d6fd41905ec577851734623fb905b1763801f5ef +References: bsc#1144333 +Patch-mainline: v5.6-rc1 + +We ran into a confusing problem where an application wasn't checking +return code on close and so user didn't realize that the application +ran out of disk space. log a warning message (once) in these +cases. For example: + + [ 8407.391909] Out of space writing to \\oleg-server\small-share + +Signed-off-by: Steve French +Reported-by: Oleg Kravtsov +Reviewed-by: Ronnie Sahlberg +Reviewed-by: Pavel Shilovsky +Acked-by: Paulo Alcantara +--- + fs/cifs/smb2pdu.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c +index 7996d81230aa..1a732ff71de4 100644 +--- a/fs/cifs/smb2pdu.c ++++ b/fs/cifs/smb2pdu.c +@@ -4029,6 +4029,9 @@ smb2_writev_callback(struct mid_q_entry *mid) + wdata->cfile->fid.persistent_fid, + tcon->tid, tcon->ses->Suid, wdata->offset, + wdata->bytes, wdata->result); ++ if (wdata->result == -ENOSPC) ++ printk_once(KERN_WARNING "Out of space writing to %s\n", ++ tcon->treeName); + } else + trace_smb3_write_done(0 /* no xid */, + wdata->cfile->fid.persistent_fid, +-- +2.25.1 + + diff --git a/patches.suse/cifs-make-sure-we-do-not-overflow-the-max-EA-buffer-size.patch b/patches.suse/cifs-make-sure-we-do-not-overflow-the-max-EA-buffer-size.patch new file mode 100644 index 0000000..493bddc --- /dev/null +++ b/patches.suse/cifs-make-sure-we-do-not-overflow-the-max-EA-buffer-size.patch @@ -0,0 +1,80 @@ +From: Ronnie Sahlberg +Date: Thu, 13 Feb 2020 12:14:47 +1000 +Subject: [PATCH] cifs: make sure we do not overflow the max EA buffer size +Git-commit: 85db6b7ae65f33be4bb44f1c28261a3faa126437 +References: bsc#1144333 +Patch-mainline: v5.6-rc2 + +RHBZ: 1752437 + +Before we add a new EA we should check that this will not overflow +the maximum buffer we have available to read the EAs back. +Otherwise we can get into a situation where the EAs are so big that +we can not read them back to the client and thus we can not list EAs +anymore or delete them. + +Signed-off-by: Ronnie Sahlberg +Signed-off-by: Steve French +CC: Stable +Acked-by: Paulo Alcantara +--- + fs/cifs/smb2ops.c | 35 ++++++++++++++++++++++++++++++++++- + 1 file changed, 34 insertions(+), 1 deletion(-) + +diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c +index aef33630e315..e47190cae163 100644 +--- a/fs/cifs/smb2ops.c ++++ b/fs/cifs/smb2ops.c +@@ -1116,7 +1116,8 @@ smb2_set_ea(const unsigned int xid, struct cifs_tcon *tcon, + void *data[1]; + struct smb2_file_full_ea_info *ea = NULL; + struct kvec close_iov[1]; +- int rc; ++ struct smb2_query_info_rsp *rsp; ++ int rc, used_len = 0; + + if (smb3_encryption_required(tcon)) + flags |= CIFS_TRANSFORM_REQ; +@@ -1139,6 +1140,38 @@ smb2_set_ea(const unsigned int xid, struct cifs_tcon *tcon, + cifs_sb); + if (rc == -ENODATA) + goto sea_exit; ++ } else { ++ /* If we are adding a attribute we should first check ++ * if there will be enough space available to store ++ * the new EA. If not we should not add it since we ++ * would not be able to even read the EAs back. ++ */ ++ rc = smb2_query_info_compound(xid, tcon, utf16_path, ++ FILE_READ_EA, ++ FILE_FULL_EA_INFORMATION, ++ SMB2_O_INFO_FILE, ++ CIFSMaxBufSize - ++ MAX_SMB2_CREATE_RESPONSE_SIZE - ++ MAX_SMB2_CLOSE_RESPONSE_SIZE, ++ &rsp_iov[1], &resp_buftype[1], cifs_sb); ++ if (rc == 0) { ++ rsp = (struct smb2_query_info_rsp *)rsp_iov[1].iov_base; ++ used_len = le32_to_cpu(rsp->OutputBufferLength); ++ } ++ free_rsp_buf(resp_buftype[1], rsp_iov[1].iov_base); ++ resp_buftype[1] = CIFS_NO_BUFFER; ++ memset(&rsp_iov[1], 0, sizeof(rsp_iov[1])); ++ rc = 0; ++ ++ /* Use a fudge factor of 256 bytes in case we collide ++ * with a different set_EAs command. ++ */ ++ if(CIFSMaxBufSize - MAX_SMB2_CREATE_RESPONSE_SIZE - ++ MAX_SMB2_CLOSE_RESPONSE_SIZE - 256 < ++ used_len + ea_name_len + ea_value_len + 1) { ++ rc = -ENOSPC; ++ goto sea_exit; ++ } + } + } + +-- +2.25.1 + + diff --git a/patches.suse/cifs-make-use-of-cap_unix-ses-in-cifs_reconnect_tcon.patch b/patches.suse/cifs-make-use-of-cap_unix-ses-in-cifs_reconnect_tcon.patch new file mode 100644 index 0000000..111463a --- /dev/null +++ b/patches.suse/cifs-make-use-of-cap_unix-ses-in-cifs_reconnect_tcon.patch @@ -0,0 +1,35 @@ +From e4a82861aa43d81cdeb039c3854ccfd7b17c6e3a Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Mon, 24 Feb 2020 14:15:00 +0100 +Subject: [PATCH] cifs: make use of cap_unix(ses) in cifs_reconnect_tcon() +Patch-mainline: Not yet, in for-next branch +References: bsc#1144333 + +cap_unix(ses) defaults to false for SMB2. + +Signed-off-by: Stefan Metzmacher +Signed-off-by: Steve French +Reviewed-by: Pavel Shilovsky +Reviewed-by: Aurelien Aptel +Signed-off-by: Steve French +Acked-by: Paulo Alcantara +--- + fs/cifs/cifssmb.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c +index b173ff22560b..140efc1a9374 100644 +--- a/fs/cifs/cifssmb.c ++++ b/fs/cifs/cifssmb.c +@@ -331,7 +331,7 @@ cifs_reconnect_tcon(struct cifs_tcon *tcon, int smb_command) + atomic_inc(&tconInfoReconnectCount); + + /* tell server Unix caps we support */ +- if (ses->capabilities & CAP_UNIX) ++ if (cap_unix(ses)) + reset_cifs_unix_caps(0, tcon, NULL, NULL); + + /* +-- +2.25.1 + diff --git a/patches.suse/cifs-modefromsid-make-room-for-4-ACE.patch b/patches.suse/cifs-modefromsid-make-room-for-4-ACE.patch new file mode 100644 index 0000000..21113b8 --- /dev/null +++ b/patches.suse/cifs-modefromsid-make-room-for-4-ACE.patch @@ -0,0 +1,35 @@ +From: Aurelien Aptel +Date: Mon, 16 Sep 2019 04:28:36 +0200 +Subject: [PATCH] cifs: modefromsid: make room for 4 ACE +Git-commit: 0892ba693f304ce3e9ca1f0a64a5cfc051454996 +References: bsc#1144333 +Patch-mainline: v5.4-rc1 + +when mounting with modefromsid, we end up writing 4 ACE in a security +descriptor that only has room for 3, thus triggering an out-of-bounds +write. fix this by changing the min size of a security descriptor. + +Signed-off-by: Aurelien Aptel +Signed-off-by: Steve French +Acked-by: Paulo Alcantara +--- + fs/cifs/cifsacl.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/fs/cifs/cifsacl.h b/fs/cifs/cifsacl.h +index dd95a6fa24bf..eb428349f29a 100644 +--- a/fs/cifs/cifsacl.h ++++ b/fs/cifs/cifsacl.h +@@ -45,7 +45,7 @@ + */ + #define DEFAULT_SEC_DESC_LEN (sizeof(struct cifs_ntsd) + \ + sizeof(struct cifs_acl) + \ +- (sizeof(struct cifs_ace) * 3)) ++ (sizeof(struct cifs_ace) * 4)) + + /* + * Maximum size of a string representation of a SID: +-- +2.25.1 + + diff --git a/patches.suse/cifs-modefromsid-write-mode-ACE-first.patch b/patches.suse/cifs-modefromsid-write-mode-ACE-first.patch new file mode 100644 index 0000000..23f1a62 --- /dev/null +++ b/patches.suse/cifs-modefromsid-write-mode-ACE-first.patch @@ -0,0 +1,88 @@ +From: Aurelien Aptel +Date: Tue, 17 Sep 2019 01:47:27 +0200 +Subject: [PATCH] cifs: modefromsid: write mode ACE first +Git-commit: e37a02c7ebb9fa9af301c47c8c5a579cc51b509b +References: bsc#1144333 +Patch-mainline: v5.4-rc1 + +DACL should start with mode ACE first but we are putting it at the +end. reorder them to put it first. + +Signed-off-by: Aurelien Aptel +Signed-off-by: Steve French +Acked-by: Paulo Alcantara +--- + fs/cifs/cifsacl.c | 36 +++++++++++++++++++----------------- + 1 file changed, 19 insertions(+), 17 deletions(-) + +diff --git a/fs/cifs/cifsacl.c b/fs/cifs/cifsacl.c +index 3e0c5ed9ca20..f842944a5c76 100644 +--- a/fs/cifs/cifsacl.c ++++ b/fs/cifs/cifsacl.c +@@ -809,30 +809,21 @@ static int set_chmod_dacl(struct cifs_acl *pndacl, struct cifs_sid *pownersid, + struct cifs_sid *pgrpsid, __u64 nmode, bool modefromsid) + { + u16 size = 0; ++ u32 num_aces = 0; + struct cifs_acl *pnndacl; + + pnndacl = (struct cifs_acl *)((char *)pndacl + sizeof(struct cifs_acl)); + +- size += fill_ace_for_sid((struct cifs_ace *) ((char *)pnndacl + size), +- pownersid, nmode, S_IRWXU); +- size += fill_ace_for_sid((struct cifs_ace *)((char *)pnndacl + size), +- pgrpsid, nmode, S_IRWXG); +- size += fill_ace_for_sid((struct cifs_ace *)((char *)pnndacl + size), +- &sid_everyone, nmode, S_IRWXO); +- +- /* TBD: Move this ACE to the top of ACE list instead of bottom */ + if (modefromsid) { + struct cifs_ace *pntace = + (struct cifs_ace *)((char *)pnndacl + size); + int i; + +- pntace->type = ACCESS_DENIED; ++ pntace->type = ACCESS_ALLOWED; + pntace->flags = 0x0; ++ pntace->access_req = 0; + pntace->sid.num_subauth = 3; + pntace->sid.revision = 1; +- /* size = 1 + 1 + 2 + 4 + 1 + 1 + 6 + (psid->num_subauth * 4) */ +- pntace->size = cpu_to_le16(28); +- size += 28; + for (i = 0; i < NUM_AUTHS; i++) + pntace->sid.authority[i] = + sid_unix_NFS_mode.authority[i]; +@@ -840,12 +831,23 @@ static int set_chmod_dacl(struct cifs_acl *pndacl, struct cifs_sid *pownersid, + pntace->sid.sub_auth[1] = sid_unix_NFS_mode.sub_auth[1]; + pntace->sid.sub_auth[2] = cpu_to_le32(nmode & 07777); + +- pndacl->num_aces = cpu_to_le32(4); +- size += fill_ace_for_sid((struct cifs_ace *)((char *)pnndacl + size), +- &sid_unix_NFS_mode, nmode, S_IRWXO); +- } else +- pndacl->num_aces = cpu_to_le32(3); ++ /* size = 1 + 1 + 2 + 4 + 1 + 1 + 6 + (psid->num_subauth*4) */ ++ pntace->size = cpu_to_le16(28); ++ size += 28; ++ num_aces++; ++ } + ++ size += fill_ace_for_sid((struct cifs_ace *) ((char *)pnndacl + size), ++ pownersid, nmode, S_IRWXU); ++ num_aces++; ++ size += fill_ace_for_sid((struct cifs_ace *)((char *)pnndacl + size), ++ pgrpsid, nmode, S_IRWXG); ++ num_aces++; ++ size += fill_ace_for_sid((struct cifs_ace *)((char *)pnndacl + size), ++ &sid_everyone, nmode, S_IRWXO); ++ num_aces++; ++ ++ pndacl->num_aces = cpu_to_le32(num_aces); + pndacl->size = cpu_to_le16(size + sizeof(struct cifs_acl)); + + return 0; +-- +2.25.1 + + diff --git a/patches.suse/cifs-move-cifsFileInfo_put-logic-into-a-work-queue.patch b/patches.suse/cifs-move-cifsFileInfo_put-logic-into-a-work-queue.patch index c03a1a5..eca42e6 100644 --- a/patches.suse/cifs-move-cifsFileInfo_put-logic-into-a-work-queue.patch +++ b/patches.suse/cifs-move-cifsFileInfo_put-logic-into-a-work-queue.patch @@ -267,10 +267,10 @@ Acked-by: Paulo Alcantara private_data != NULL) { @@ -471,7 +474,7 @@ Acked-by: Paulo Alcantara private_data = NULL; } -@@ -4640,7 +4664,7 @@ void cifs_oplock_break(struct work_struc +@@ -4755,7 +4779,7 @@ void cifs_oplock_break(struct work_struc cinode); cifs_dbg(FYI, "Oplock release rc = %d\n", rc); } diff --git a/patches.suse/cifs-plumb-smb2-POSIX-dir-enumeration.patch b/patches.suse/cifs-plumb-smb2-POSIX-dir-enumeration.patch new file mode 100644 index 0000000..43f287b --- /dev/null +++ b/patches.suse/cifs-plumb-smb2-POSIX-dir-enumeration.patch @@ -0,0 +1,258 @@ +From 8ba286ed01e06e0a1663ad09850718b1a63238a1 Mon Sep 17 00:00:00 2001 +From: Aurelien Aptel +Date: Sat, 8 Feb 2020 15:50:58 +0100 +Subject: [PATCH] cifs: plumb smb2 POSIX dir enumeration +Patch-mainline: Not yet, in for-next branch +References: bsc#1144333 + +* add code to request POSIX info level +* parse dir entries and fill cifs_fattr to get correct inode data + +since the POSIX payload is variable size the number of entries in a +FIND response needs to be computed differently. + +Dirs and regular files are properly reported along with mode bits, +hardlink number, c/m/atime. No special files yet (see below). + +Current experimental version of Samba with the extension unfortunately +has issues with wildcards and needs the following patch: + +> --- i/source3/smbd/smb2_query_directory.c +> +++ w/source3/smbd/smb2_query_directory.c +> @@ -397,9 +397,7 @@ smbd_smb2_query_directory_send(TALLOC_CTX +> *mem_ctx, +> } +> } +> +> - if (!state->smbreq->posix_pathnames) { +> wcard_has_wild = ms_has_wild(state->in_file_name); +> - } +> +> /* Ensure we've canonicalized any search path if not a wildcard. */ +> if (!wcard_has_wild) { +> + +Also for special files despite reporting them as reparse point samba +doesn't set the reparse tag field. This patch will mark them as needing +re-evaluation but the re-evaluate code doesn't deal with it yet. + +Signed-off-by: Aurelien Aptel +Signed-off-by: Steve French +Acked-by: Paulo Alcantara +--- + fs/cifs/readdir.c | 82 +++++++++++++++++++++++++++++++++++++++++++++++ + fs/cifs/smb2pdu.c | 34 ++++++++++++++++---- + 2 files changed, 109 insertions(+), 7 deletions(-) + +diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c +index ba9dadf3be24..19e4a5d3b4ca 100644 +--- a/fs/cifs/readdir.c ++++ b/fs/cifs/readdir.c +@@ -32,6 +32,7 @@ + #include "cifs_debug.h" + #include "cifs_fs_sb.h" + #include "cifsfs.h" ++#include "smb2proto.h" + + /* + * To be safe - for UCS to UTF-8 with strings loaded with the rare long +@@ -217,6 +218,60 @@ cifs_fill_common_info(struct cifs_fattr *fattr, struct cifs_sb_info *cifs_sb) + } + } + ++/* Fill a cifs_fattr struct with info from SMB_FIND_FILE_POSIX_INFO. */ ++static void ++cifs_posix_to_fattr(struct cifs_fattr *fattr, struct smb2_posix_info *info, ++ struct cifs_sb_info *cifs_sb) ++{ ++ struct smb2_posix_info_parsed parsed; ++ ++ posix_info_parse(info, NULL, &parsed); ++ ++ memset(fattr, 0, sizeof(*fattr)); ++ fattr->cf_uniqueid = le64_to_cpu(info->Inode); ++ fattr->cf_bytes = le64_to_cpu(info->AllocationSize); ++ fattr->cf_eof = le64_to_cpu(info->EndOfFile); ++ ++ fattr->cf_atime = cifs_NTtimeToUnix(info->LastAccessTime); ++ fattr->cf_mtime = cifs_NTtimeToUnix(info->LastWriteTime); ++ fattr->cf_ctime = cifs_NTtimeToUnix(info->CreationTime); ++ ++ fattr->cf_nlink = le32_to_cpu(info->HardLinks); ++ fattr->cf_cifsattrs = le32_to_cpu(info->DosAttributes); ++ ++ /* ++ * Since we set the inode type below we need to mask off ++ * to avoid strange results if bits set above. ++ * XXX: why not make server&client use the type bits? ++ */ ++ fattr->cf_mode = le32_to_cpu(info->Mode) & ~S_IFMT; ++ ++ cifs_dbg(VFS, "XXX dev %d, reparse %d, mode %o", ++ le32_to_cpu(info->DeviceId), ++ le32_to_cpu(info->ReparseTag), ++ le32_to_cpu(info->Mode)); ++ ++ if (fattr->cf_cifsattrs & ATTR_DIRECTORY) { ++ fattr->cf_mode |= S_IFDIR; ++ fattr->cf_dtype = DT_DIR; ++ } else { ++ /* ++ * mark anything that is not a dir as regular ++ * file. special files should have the REPARSE ++ * attribute and will be marked as needing revaluation ++ */ ++ fattr->cf_mode |= S_IFREG; ++ fattr->cf_dtype = DT_REG; ++ } ++ ++ if (reparse_file_needs_reval(fattr)) ++ fattr->cf_flags |= CIFS_FATTR_NEED_REVAL; ++ ++ /* TODO map SIDs */ ++ fattr->cf_uid = cifs_sb->mnt_uid; ++ fattr->cf_gid = cifs_sb->mnt_gid; ++} ++ + static void __dir_info_to_fattr(struct cifs_fattr *fattr, const void *info) + { + const FILE_DIRECTORY_INFO *fi = info; +@@ -359,6 +414,8 @@ initiate_cifs_search(const unsigned int xid, struct file *file) + /* if (cap_unix(tcon->ses) { */ + if (tcon->unix_ext) + cifsFile->srch_inf.info_level = SMB_FIND_FILE_UNIX; ++ else if (tcon->posix_extensions) ++ cifsFile->srch_inf.info_level = SMB_FIND_FILE_POSIX_INFO; + else if ((tcon->ses->capabilities & + tcon->ses->server->vals->cap_nt_find) == 0) { + cifsFile->srch_inf.info_level = SMB_FIND_FILE_INFO_STANDARD; +@@ -451,6 +508,23 @@ struct cifs_dirent { + u64 ino; + }; + ++static void cifs_fill_dirent_posix(struct cifs_dirent *de, ++ const struct smb2_posix_info *info) ++{ ++ struct smb2_posix_info_parsed parsed; ++ ++ /* payload should have already been checked at this point */ ++ if (posix_info_parse(info, NULL, &parsed) < 0) { ++ cifs_dbg(VFS, "invalid POSIX info payload"); ++ return; ++ } ++ ++ de->name = parsed.name; ++ de->namelen = parsed.name_len; ++ de->resume_key = info->Ignored; ++ de->ino = le64_to_cpu(info->Inode); ++} ++ + static void cifs_fill_dirent_unix(struct cifs_dirent *de, + const FILE_UNIX_INFO *info, bool is_unicode) + { +@@ -511,6 +585,9 @@ static int cifs_fill_dirent(struct cifs_dirent *de, const void *info, + memset(de, 0, sizeof(*de)); + + switch (level) { ++ case SMB_FIND_FILE_POSIX_INFO: ++ cifs_fill_dirent_posix(de, info); ++ break; + case SMB_FIND_FILE_UNIX: + cifs_fill_dirent_unix(de, info, is_unicode); + break; +@@ -786,6 +863,11 @@ static int cifs_filldir(char *find_entry, struct file *file, + } + + switch (file_info->srch_inf.info_level) { ++ case SMB_FIND_FILE_POSIX_INFO: ++ cifs_posix_to_fattr(&fattr, ++ (struct smb2_posix_info *)find_entry, ++ cifs_sb); ++ break; + case SMB_FIND_FILE_UNIX: + cifs_unix_basic_to_fattr(&fattr, + &((FILE_UNIX_INFO *)find_entry)->basic, +diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c +index 08d6a130e512..7356017a0821 100644 +--- a/fs/cifs/smb2pdu.c ++++ b/fs/cifs/smb2pdu.c +@@ -4398,7 +4398,8 @@ static int posix_info_extra_size(const void *beg, const void *end) + } + + static unsigned int +-num_entries(char *bufstart, char *end_of_buf, char **lastentry, size_t size) ++num_entries(int infotype, char *bufstart, char *end_of_buf, char **lastentry, ++ size_t size) + { + int len; + unsigned int entrycount = 0; +@@ -4422,8 +4423,13 @@ num_entries(char *bufstart, char *end_of_buf, char **lastentry, size_t size) + entryptr = entryptr + next_offset; + dir_info = (FILE_DIRECTORY_INFO *)entryptr; + +- len = le32_to_cpu(dir_info->FileNameLength); +- if (entryptr + len < entryptr || ++ if (infotype == SMB_FIND_FILE_POSIX_INFO) ++ len = posix_info_extra_size(entryptr, end_of_buf); ++ else ++ len = le32_to_cpu(dir_info->FileNameLength); ++ ++ if (len < 0 || ++ entryptr + len < entryptr || + entryptr + len > end_of_buf || + entryptr + len + size > end_of_buf) { + cifs_dbg(VFS, "directory entry name would overflow frame end of buf %p\n", +@@ -4473,6 +4479,9 @@ int SMB2_query_directory_init(const unsigned int xid, + case SMB_FIND_FILE_ID_FULL_DIR_INFO: + req->FileInformationClass = FILEID_FULL_DIRECTORY_INFORMATION; + break; ++ case SMB_FIND_FILE_POSIX_INFO: ++ req->FileInformationClass = SMB_FIND_FILE_POSIX_INFO; ++ break; + default: + cifs_tcon_dbg(VFS, "info level %u isn't supported\n", + info_level); +@@ -4538,6 +4547,10 @@ smb2_parse_query_directory(struct cifs_tcon *tcon, + case SMB_FIND_FILE_ID_FULL_DIR_INFO: + info_buf_size = sizeof(SEARCH_ID_FULL_DIR_INFO) - 1; + break; ++ case SMB_FIND_FILE_POSIX_INFO: ++ /* note that posix payload are variable size */ ++ info_buf_size = sizeof(struct smb2_posix_info); ++ break; + default: + cifs_tcon_dbg(VFS, "info level %u isn't supported\n", + srch_inf->info_level); +@@ -4547,8 +4560,10 @@ smb2_parse_query_directory(struct cifs_tcon *tcon, + rc = smb2_validate_iov(le16_to_cpu(rsp->OutputBufferOffset), + le32_to_cpu(rsp->OutputBufferLength), rsp_iov, + info_buf_size); +- if (rc) ++ if (rc) { ++ cifs_tcon_dbg(VFS, "bad info payload"); + return rc; ++ } + + srch_inf->unicode = true; + +@@ -4562,9 +4577,14 @@ smb2_parse_query_directory(struct cifs_tcon *tcon, + srch_inf->srch_entries_start = srch_inf->last_entry = + (char *)rsp + le16_to_cpu(rsp->OutputBufferOffset); + end_of_smb = rsp_iov->iov_len + (char *)rsp; +- srch_inf->entries_in_buffer = +- num_entries(srch_inf->srch_entries_start, end_of_smb, +- &srch_inf->last_entry, info_buf_size); ++ ++ srch_inf->entries_in_buffer = num_entries( ++ srch_inf->info_level, ++ srch_inf->srch_entries_start, ++ end_of_smb, ++ &srch_inf->last_entry, ++ info_buf_size); ++ + srch_inf->index_of_last_entry += srch_inf->entries_in_buffer; + cifs_dbg(FYI, "num entries %d last_index %lld srch start %p srch end %p\n", + srch_inf->entries_in_buffer, srch_inf->index_of_last_entry, +-- +2.25.1 + diff --git a/patches.suse/cifs-potential-unintitliazed-error-code-in-cifs_geta.patch b/patches.suse/cifs-potential-unintitliazed-error-code-in-cifs_geta.patch new file mode 100644 index 0000000..1b7bbf7 --- /dev/null +++ b/patches.suse/cifs-potential-unintitliazed-error-code-in-cifs_geta.patch @@ -0,0 +1,37 @@ +From 32d590417fed2fc1c05b1a04a3c1b40ebd26aa7f Mon Sep 17 00:00:00 2001 +From: Dan Carpenter +Date: Fri, 28 Feb 2020 12:22:59 +0300 +Subject: [PATCH] cifs: potential unintitliazed error code in cifs_getattr() +Patch-mainline: Not yet, in for-next branch +References: bsc#1144333 + +Smatch complains that "rc" could be uninitialized. + + fs/cifs/inode.c:2206 cifs_getattr() error: uninitialized symbol 'rc'. + +Changing it to "return 0;" improves readability as well. + +Fixes: cc1baf98c8f6 ("cifs: do not ignore the SYNC flags in getattr") +Signed-off-by: Dan Carpenter +Signed-off-by: Steve French +Acked-by: Paulo Alcantara +--- + fs/cifs/inode.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c +index 84b8ebaa5932..aad7d2cad9a0 100644 +--- a/fs/cifs/inode.c ++++ b/fs/cifs/inode.c +@@ -2203,7 +2203,7 @@ int cifs_getattr(const struct path *path, struct kstat *stat, + if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID)) + stat->gid = current_fsgid(); + } +- return rc; ++ return 0; + } + + int cifs_fiemap(struct inode *inode, struct fiemap_extent_info *fei, u64 start, +-- +2.25.1 + diff --git a/patches.suse/cifs-prepare-SMB2_query_directory-to-be-used-with-compounding.patch b/patches.suse/cifs-prepare-SMB2_query_directory-to-be-used-with-compounding.patch new file mode 100644 index 0000000..e00ead4 --- /dev/null +++ b/patches.suse/cifs-prepare-SMB2_query_directory-to-be-used-with-compounding.patch @@ -0,0 +1,223 @@ +From: Ronnie Sahlberg +Date: Wed, 8 Jan 2020 13:08:04 +1000 +Subject: [PATCH] cifs: prepare SMB2_query_directory to be used with + compounding +Git-commit: 0a17799cc02f81c4c82c2de6f7071701714c2267 +References: bsc#1144333 +Patch-mainline: v5.6-rc1 + +Signed-off-by: Ronnie Sahlberg +Signed-off-by: Steve French +Reviewed-by: Pavel Shilovsky +Acked-by: Paulo Alcantara +--- + fs/cifs/smb2pdu.c | 113 +++++++++++++++++++++++++++++--------------- + fs/cifs/smb2pdu.h | 2 + + fs/cifs/smb2proto.h | 5 ++ + 3 files changed, 83 insertions(+), 37 deletions(-) + +diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c +index 9434f6dd8df3..50466062c1da 100644 +--- a/fs/cifs/smb2pdu.c ++++ b/fs/cifs/smb2pdu.c +@@ -4296,56 +4296,38 @@ num_entries(char *bufstart, char *end_of_buf, char **lastentry, size_t size) + /* + * Readdir/FindFirst + */ +-int +-SMB2_query_directory(const unsigned int xid, struct cifs_tcon *tcon, +- u64 persistent_fid, u64 volatile_fid, int index, +- struct cifs_search_info *srch_inf) ++int SMB2_query_directory_init(const unsigned int xid, ++ struct cifs_tcon *tcon, struct smb_rqst *rqst, ++ u64 persistent_fid, u64 volatile_fid, ++ int index, int info_level) + { +- struct smb_rqst rqst; ++ struct TCP_Server_Info *server = tcon->ses->server; + struct smb2_query_directory_req *req; +- struct smb2_query_directory_rsp *rsp = NULL; +- struct kvec iov[2]; +- struct kvec rsp_iov; +- int rc = 0; +- int len; +- int resp_buftype = CIFS_NO_BUFFER; + unsigned char *bufptr; +- struct TCP_Server_Info *server; +- struct cifs_ses *ses = tcon->ses; + __le16 asteriks = cpu_to_le16('*'); +- char *end_of_smb; +- unsigned int output_size = CIFSMaxBufSize; +- size_t info_buf_size; +- int flags = 0; ++ unsigned int output_size = CIFSMaxBufSize - ++ MAX_SMB2_CREATE_RESPONSE_SIZE - ++ MAX_SMB2_CLOSE_RESPONSE_SIZE; + unsigned int total_len; +- +- if (ses && (ses->server)) +- server = ses->server; +- else +- return -EIO; ++ struct kvec *iov = rqst->rq_iov; ++ int len, rc; + + rc = smb2_plain_req_init(SMB2_QUERY_DIRECTORY, tcon, (void **) &req, + &total_len); + if (rc) + return rc; + +- if (smb3_encryption_required(tcon)) +- flags |= CIFS_TRANSFORM_REQ; +- +- switch (srch_inf->info_level) { ++ switch (info_level) { + case SMB_FIND_FILE_DIRECTORY_INFO: + req->FileInformationClass = FILE_DIRECTORY_INFORMATION; +- info_buf_size = sizeof(FILE_DIRECTORY_INFO) - 1; + break; + case SMB_FIND_FILE_ID_FULL_DIR_INFO: + req->FileInformationClass = FILEID_FULL_DIRECTORY_INFORMATION; +- info_buf_size = sizeof(SEARCH_ID_FULL_DIR_INFO) - 1; + break; + default: + cifs_tcon_dbg(VFS, "info level %u isn't supported\n", +- srch_inf->info_level); +- rc = -EINVAL; +- goto qdir_exit; ++ info_level); ++ return -EINVAL; + } + + req->FileIndex = cpu_to_le32(index); +@@ -4374,15 +4356,56 @@ SMB2_query_directory(const unsigned int xid, struct cifs_tcon *tcon, + iov[1].iov_base = (char *)(req->Buffer); + iov[1].iov_len = len; + +- memset(&rqst, 0, sizeof(struct smb_rqst)); +- rqst.rq_iov = iov; +- rqst.rq_nvec = 2; +- + trace_smb3_query_dir_enter(xid, persistent_fid, tcon->tid, + tcon->ses->Suid, index, output_size); + ++ return 0; ++} ++ ++void SMB2_query_directory_free(struct smb_rqst *rqst) ++{ ++ if (rqst && rqst->rq_iov) { ++ cifs_small_buf_release(rqst->rq_iov[0].iov_base); /* request */ ++ } ++} ++ ++int ++SMB2_query_directory(const unsigned int xid, struct cifs_tcon *tcon, ++ u64 persistent_fid, u64 volatile_fid, int index, ++ struct cifs_search_info *srch_inf) ++{ ++ struct smb_rqst rqst; ++ struct kvec iov[SMB2_QUERY_DIRECTORY_IOV_SIZE]; ++ struct smb2_query_directory_rsp *rsp = NULL; ++ int resp_buftype = CIFS_NO_BUFFER; ++ struct kvec rsp_iov; ++ int rc = 0; ++ struct TCP_Server_Info *server; ++ struct cifs_ses *ses = tcon->ses; ++ char *end_of_smb; ++ size_t info_buf_size; ++ int flags = 0; ++ ++ if (ses && (ses->server)) ++ server = ses->server; ++ else ++ return -EIO; ++ ++ if (smb3_encryption_required(tcon)) ++ flags |= CIFS_TRANSFORM_REQ; ++ ++ memset(&rqst, 0, sizeof(struct smb_rqst)); ++ memset(&iov, 0, sizeof(iov)); ++ rqst.rq_iov = iov; ++ rqst.rq_nvec = SMB2_QUERY_DIRECTORY_IOV_SIZE; ++ ++ rc = SMB2_query_directory_init(xid, tcon, &rqst, persistent_fid, ++ volatile_fid, index, ++ srch_inf->info_level); ++ if (rc) ++ goto qdir_exit; ++ + rc = cifs_send_recv(xid, ses, &rqst, &resp_buftype, flags, &rsp_iov); +- cifs_small_buf_release(req); + rsp = (struct smb2_query_directory_rsp *)rsp_iov.iov_base; + + if (rc) { +@@ -4400,6 +4423,20 @@ SMB2_query_directory(const unsigned int xid, struct cifs_tcon *tcon, + goto qdir_exit; + } + ++ switch (srch_inf->info_level) { ++ case SMB_FIND_FILE_DIRECTORY_INFO: ++ info_buf_size = sizeof(FILE_DIRECTORY_INFO) - 1; ++ break; ++ case SMB_FIND_FILE_ID_FULL_DIR_INFO: ++ info_buf_size = sizeof(SEARCH_ID_FULL_DIR_INFO) - 1; ++ break; ++ default: ++ cifs_tcon_dbg(VFS, "info level %u isn't supported\n", ++ srch_inf->info_level); ++ rc = -EINVAL; ++ goto qdir_exit; ++ } ++ + rc = smb2_validate_iov(le16_to_cpu(rsp->OutputBufferOffset), + le32_to_cpu(rsp->OutputBufferLength), &rsp_iov, + info_buf_size); +@@ -4435,11 +4472,13 @@ SMB2_query_directory(const unsigned int xid, struct cifs_tcon *tcon, + else + cifs_tcon_dbg(VFS, "illegal search buffer type\n"); + ++ resp_buftype = CIFS_NO_BUFFER; ++ + trace_smb3_query_dir_done(xid, persistent_fid, tcon->tid, + tcon->ses->Suid, index, srch_inf->entries_in_buffer); +- return rc; + + qdir_exit: ++ SMB2_query_directory_free(&rqst); + free_rsp_buf(resp_buftype, rsp); + return rc; + } +diff --git a/fs/cifs/smb2pdu.h b/fs/cifs/smb2pdu.h +index 7b1c379fdf7a..4c43dbd1e089 100644 +--- a/fs/cifs/smb2pdu.h ++++ b/fs/cifs/smb2pdu.h +@@ -1282,6 +1282,8 @@ struct smb2_echo_rsp { + #define SMB2_INDEX_SPECIFIED 0x04 + #define SMB2_REOPEN 0x10 + ++#define SMB2_QUERY_DIRECTORY_IOV_SIZE 2 ++ + struct smb2_query_directory_req { + struct smb2_sync_hdr sync_hdr; + __le16 StructureSize; /* Must be 33 */ +diff --git a/fs/cifs/smb2proto.h b/fs/cifs/smb2proto.h +index 27d29f2eb6c8..6c678e00046f 100644 +--- a/fs/cifs/smb2proto.h ++++ b/fs/cifs/smb2proto.h +@@ -197,6 +197,11 @@ extern int SMB2_echo(struct TCP_Server_Info *server); + extern int SMB2_query_directory(const unsigned int xid, struct cifs_tcon *tcon, + u64 persistent_fid, u64 volatile_fid, int index, + struct cifs_search_info *srch_inf); ++extern int SMB2_query_directory_init(unsigned int xid, struct cifs_tcon *tcon, ++ struct smb_rqst *rqst, ++ u64 persistent_fid, u64 volatile_fid, ++ int index, int info_level); ++extern void SMB2_query_directory_free(struct smb_rqst *rqst); + extern int SMB2_set_eof(const unsigned int xid, struct cifs_tcon *tcon, + u64 persistent_fid, u64 volatile_fid, u32 pid, + __le64 *eof); +-- +2.25.1 + + diff --git a/patches.suse/cifs-print-warning-once-if-mounting-with-vers-1.0.patch b/patches.suse/cifs-print-warning-once-if-mounting-with-vers-1.0.patch new file mode 100644 index 0000000..0f0c86b --- /dev/null +++ b/patches.suse/cifs-print-warning-once-if-mounting-with-vers-1.0.patch @@ -0,0 +1,37 @@ +From 3cb4e3ff0a1eb5554d96942a2095c9868642af1f Mon Sep 17 00:00:00 2001 +From: Steve French +Date: Fri, 28 Feb 2020 01:32:37 -0600 +Subject: [PATCH] cifs: print warning once if mounting with vers=1.0 +Patch-mainline: Not yet, in for-next branch +References: bsc#1144333 + +We really, really don't want people using insecure dialects +unless they realize what they are doing ... + +Add print once warning if mounting with vers=1.0 (older SMB1/CIFS +dialect) instead of the default (SMB2.1 or later, typically +SMB3.1.1). + +Signed-off-by: Steve French +Acked-by: Paulo Alcantara +--- + fs/cifs/connect.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c +index f4d12b79ceed..27577d71d942 100644 +--- a/fs/cifs/connect.c ++++ b/fs/cifs/connect.c +@@ -1471,6 +1471,9 @@ cifs_parse_smb_version(char *value, struct smb_vol *vol, bool is_smb3) + cifs_dbg(VFS, "vers=1.0 (cifs) not permitted when mounting with smb3\n"); + return 1; + } ++ printk_once(KERN_WARNING "Use of the less secure dialect " ++ "vers=1.0 is not recommended unless required for " ++ "access to very old servers\n"); + vol->ops = &smb1_operations; + vol->vals = &smb1_values; + break; +-- +2.25.1 + diff --git a/patches.suse/cifs-remove-redundant-assignment-to-pointer-pneg_ctxt.patch b/patches.suse/cifs-remove-redundant-assignment-to-pointer-pneg_ctxt.patch new file mode 100644 index 0000000..5e446dc --- /dev/null +++ b/patches.suse/cifs-remove-redundant-assignment-to-pointer-pneg_ctxt.patch @@ -0,0 +1,36 @@ +From: Colin Ian King +Date: Mon, 2 Dec 2019 18:59:42 +0000 +Subject: [PATCH] cifs: remove redundant assignment to pointer pneg_ctxt +Git-commit: a9f76cf82719aea0f41bfcae57e17ffec39743d0 +References: bsc#1144333 +Patch-mainline: v5.5-rc1 + +The pointer pneg_ctxt is being initialized with a value that is never +read and it is being updated later with a new value. The assignment +is redundant and can be removed. + +Addresses-Coverity: ("Unused value") +Signed-off-by: Colin Ian King +Signed-off-by: Steve French +Acked-by: Paulo Alcantara +--- + fs/cifs/smb2pdu.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c +index ed77f94dbf1d..be0de8a63e57 100644 +--- a/fs/cifs/smb2pdu.c ++++ b/fs/cifs/smb2pdu.c +@@ -554,7 +554,7 @@ static void + assemble_neg_contexts(struct smb2_negotiate_req *req, + struct TCP_Server_Info *server, unsigned int *total_len) + { +- char *pneg_ctxt = (char *)req; ++ char *pneg_ctxt; + unsigned int ctxt_len; + + if (*total_len > 200) { +-- +2.25.1 + + diff --git a/patches.suse/cifs-remove-redundant-assignment-to-variable-rc.patch b/patches.suse/cifs-remove-redundant-assignment-to-variable-rc.patch new file mode 100644 index 0000000..62eff21 --- /dev/null +++ b/patches.suse/cifs-remove-redundant-assignment-to-variable-rc.patch @@ -0,0 +1,36 @@ +From: Colin Ian King +Date: Wed, 31 Jul 2019 10:05:26 +0100 +Subject: [PATCH] cifs: remove redundant assignment to variable rc +Git-commit: 1efd4fc72e1f1a7313aa66e1c0269f1041eba2ce +References: bsc#1144333 +Patch-mainline: v5.4-rc1 + +Variable rc is being initialized with a value that is never read +and rc is being re-assigned a little later on. The assignment is +redundant and hence can be removed. + +Addresses-Coverity: ("Unused value") +Signed-off-by: Colin Ian King +Signed-off-by: Steve French +Acked-by: Paulo Alcantara +--- + fs/cifs/smb2pdu.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c +index ee5d74988a9f..a653c429e8dc 100644 +--- a/fs/cifs/smb2pdu.c ++++ b/fs/cifs/smb2pdu.c +@@ -3617,7 +3617,7 @@ SMB2_read(const unsigned int xid, struct cifs_io_parms *io_parms, + unsigned int *nbytes, char **buf, int *buf_type) + { + struct smb_rqst rqst; +- int resp_buftype, rc = -EACCES; ++ int resp_buftype, rc; + struct smb2_read_plain_req *req = NULL; + struct smb2_read_rsp *rsp = NULL; + struct kvec iov[1]; +-- +2.25.1 + + diff --git a/patches.suse/cifs-remove-set-but-not-used-variable-server-2.patch b/patches.suse/cifs-remove-set-but-not-used-variable-server-2.patch new file mode 100644 index 0000000..bb1a201 --- /dev/null +++ b/patches.suse/cifs-remove-set-but-not-used-variable-server-2.patch @@ -0,0 +1,45 @@ +From c4985c3d9902dcd66f0b61d048560ef2cc415542 Mon Sep 17 00:00:00 2001 +From: YueHaibing +Date: Fri, 17 Jan 2020 10:57:17 +0800 +Subject: [PATCH] cifs: remove set but not used variable 'server' +Git-commit: c4985c3d9902dcd66f0b61d048560ef2cc415542 +References: bsc#1144333 +Patch-mainline: v5.6-rc1 + +fs/cifs/smb2pdu.c: In function 'SMB2_query_directory': +fs/cifs/smb2pdu.c:4444:26: warning: + variable 'server' set but not used [-Wunused-but-set-variable] + struct TCP_Server_Info *server; + +It is not used, so remove it. + +Reported-by: Hulk Robot +Signed-off-by: YueHaibing +Signed-off-by: Steve French +Acked-by: Paulo Alcantara +--- + fs/cifs/smb2pdu.c | 5 +---- + 1 file changed, 1 insertion(+), 4 deletions(-) + +diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c +index a23ca3d0dcd9..64d5a36a1901 100644 +--- a/fs/cifs/smb2pdu.c ++++ b/fs/cifs/smb2pdu.c +@@ -4441,13 +4441,10 @@ SMB2_query_directory(const unsigned int xid, struct cifs_tcon *tcon, + int resp_buftype = CIFS_NO_BUFFER; + struct kvec rsp_iov; + int rc = 0; +- struct TCP_Server_Info *server; + struct cifs_ses *ses = tcon->ses; + int flags = 0; + +- if (ses && (ses->server)) +- server = ses->server; +- else ++ if (!ses || !(ses->server)) + return -EIO; + + if (smb3_encryption_required(tcon)) +-- +2.25.1 + diff --git a/patches.suse/cifs-remove-set-but-not-used-variables.patch b/patches.suse/cifs-remove-set-but-not-used-variables.patch new file mode 100644 index 0000000..5e79a3f --- /dev/null +++ b/patches.suse/cifs-remove-set-but-not-used-variables.patch @@ -0,0 +1,82 @@ +From: YueHaibing +Date: Fri, 23 Aug 2019 20:15:35 +0800 +Subject: [PATCH] cifs: remove set but not used variables +Git-commit: 31ebdc11340abfdb02b7cdbfcc5531b7f479d58d +References: bsc#1144333 +Patch-mainline: v5.4-rc1 + +Fixes gcc '-Wunused-but-set-variable' warning: + +fs/cifs/file.c: In function cifs_lock: +fs/cifs/file.c:1696:24: warning: variable cinode set but not used [-Wunused-but-set-variable] +fs/cifs/file.c: In function cifs_write: +fs/cifs/file.c:1765:23: warning: variable cifs_sb set but not used [-Wunused-but-set-variable] +fs/cifs/file.c: In function collect_uncached_read_data: +fs/cifs/file.c:3578:20: warning: variable tcon set but not used [-Wunused-but-set-variable] + +'cinode' is never used since introduced by +commit 03776f4516bc ("CIFS: Simplify byte range locking code") +'cifs_sb' is not used since commit cb7e9eabb2b5 ("CIFS: Use +multicredits for SMB 2.1/3 writes"). +'tcon' is not used since commit d26e2903fc10 ("smb3: fix bytes_read statistics") + +Reported-by: Hulk Robot +Signed-off-by: YueHaibing +Signed-off-by: Steve French +Acked-by: Paulo Alcantara +--- + fs/cifs/file.c | 7 ------- + 1 file changed, 7 deletions(-) + +diff --git a/fs/cifs/file.c b/fs/cifs/file.c +index ab07ae882e62..f16f6d2b5217 100644 +--- a/fs/cifs/file.c ++++ b/fs/cifs/file.c +@@ -1693,7 +1693,6 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *flock) + bool posix_lck = false; + struct cifs_sb_info *cifs_sb; + struct cifs_tcon *tcon; +- struct cifsInodeInfo *cinode; + struct cifsFileInfo *cfile; + __u32 type; + +@@ -1710,7 +1709,6 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *flock) + cifs_read_flock(flock, &type, &lock, &unlock, &wait_flag, + tcon->ses->server); + cifs_sb = CIFS_FILE_SB(file); +- cinode = CIFS_I(file_inode(file)); + + if (cap_unix(tcon->ses) && + (CIFS_UNIX_FCNTL_CAP & le64_to_cpu(tcon->fsUnixInfo.Capability)) && +@@ -1762,7 +1760,6 @@ cifs_write(struct cifsFileInfo *open_file, __u32 pid, const char *write_data, + int rc = 0; + unsigned int bytes_written = 0; + unsigned int total_written; +- struct cifs_sb_info *cifs_sb; + struct cifs_tcon *tcon; + struct TCP_Server_Info *server; + unsigned int xid; +@@ -1770,8 +1767,6 @@ cifs_write(struct cifsFileInfo *open_file, __u32 pid, const char *write_data, + struct cifsInodeInfo *cifsi = CIFS_I(d_inode(dentry)); + struct cifs_io_parms io_parms; + +- cifs_sb = CIFS_SB(dentry->d_sb); +- + cifs_dbg(FYI, "write %zd bytes to offset %lld of %pd\n", + write_size, *offset, dentry); + +@@ -3575,10 +3570,8 @@ collect_uncached_read_data(struct cifs_aio_ctx *ctx) + struct cifs_readdata *rdata, *tmp; + struct iov_iter *to = &ctx->iter; + struct cifs_sb_info *cifs_sb; +- struct cifs_tcon *tcon; + int rc; + +- tcon = tlink_tcon(ctx->cfile->tlink); + cifs_sb = CIFS_SB(ctx->cfile->dentry->d_sb); + + mutex_lock(&ctx->aio_mutex); +-- +2.25.1 + + diff --git a/patches.suse/cifs-remove-unused-variable-sid_user-.patch b/patches.suse/cifs-remove-unused-variable-sid_user-.patch new file mode 100644 index 0000000..a56be66 --- /dev/null +++ b/patches.suse/cifs-remove-unused-variable-sid_user-.patch @@ -0,0 +1,36 @@ +From: YueHaibing +Date: Wed, 23 Oct 2019 21:55:59 +0800 +Subject: [PATCH] cifs: remove unused variable 'sid_user' +Git-commit: be1bf978e5d7cf26a78091ce1dd7c77ac64a658f +References: bsc#1144333 +Patch-mainline: v5.5-rc1 + +fs/cifs/cifsacl.c:43:30: warning: + sid_user defined but not used [-Wunused-const-variable=] + +It is never used, so remove it. + +Signed-off-by: YueHaibing +Signed-off-by: Steve French +Acked-by: Paulo Alcantara +--- + fs/cifs/cifsacl.c | 2 -- + 1 file changed, 2 deletions(-) + +diff --git a/fs/cifs/cifsacl.c b/fs/cifs/cifsacl.c +index f842944a5c76..06ffe52bdcfa 100644 +--- a/fs/cifs/cifsacl.c ++++ b/fs/cifs/cifsacl.c +@@ -39,8 +39,6 @@ static const struct cifs_sid sid_everyone = { + /* security id for Authenticated Users system group */ + static const struct cifs_sid sid_authusers = { + 1, 1, {0, 0, 0, 0, 0, 5}, {cpu_to_le32(11)} }; +-/* group users */ +-static const struct cifs_sid sid_user = {1, 2 , {0, 0, 0, 0, 0, 5}, {} }; + + /* S-1-22-1 Unmapped Unix users */ + static const struct cifs_sid sid_unix_users = {1, 1, {0, 0, 0, 0, 0, 22}, +-- +2.25.1 + + diff --git a/patches.suse/cifs-remove-unused-variable.patch b/patches.suse/cifs-remove-unused-variable.patch new file mode 100644 index 0000000..a904a47 --- /dev/null +++ b/patches.suse/cifs-remove-unused-variable.patch @@ -0,0 +1,63 @@ +From: zhengbin +Date: Tue, 20 Aug 2019 22:00:47 +0800 +Subject: [PATCH] cifs: remove unused variable +Git-commit: 2617474bfa33ab6c47c515e57dfbe754f8970640 +References: bsc#1144333 +Patch-mainline: v5.4-rc1 + +In smb3_punch_hole, variable cifsi set but not used, remove it. +In cifs_lock, variable netfid set but not used, remove it. + +Reported-by: Hulk Robot +Signed-off-by: zhengbin +Signed-off-by: Steve French +Acked-by: Paulo Alcantara +--- + fs/cifs/file.c | 2 -- + fs/cifs/smb2ops.c | 2 -- + 2 files changed, 4 deletions(-) + +diff --git a/fs/cifs/file.c b/fs/cifs/file.c +index 97090693d182..ab07ae882e62 100644 +--- a/fs/cifs/file.c ++++ b/fs/cifs/file.c +@@ -1695,7 +1695,6 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *flock) + struct cifs_tcon *tcon; + struct cifsInodeInfo *cinode; + struct cifsFileInfo *cfile; +- __u16 netfid; + __u32 type; + + rc = -EACCES; +@@ -1711,7 +1710,6 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *flock) + cifs_read_flock(flock, &type, &lock, &unlock, &wait_flag, + tcon->ses->server); + cifs_sb = CIFS_FILE_SB(file); +- netfid = cfile->fid.netfid; + cinode = CIFS_I(file_inode(file)); + + if (cap_unix(tcon->ses) && +diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c +index 461a68fdff1f..070d0b7b21dc 100644 +--- a/fs/cifs/smb2ops.c ++++ b/fs/cifs/smb2ops.c +@@ -2960,7 +2960,6 @@ static long smb3_punch_hole(struct file *file, struct cifs_tcon *tcon, + loff_t offset, loff_t len) + { + struct inode *inode; +- struct cifsInodeInfo *cifsi; + struct cifsFileInfo *cfile = file->private_data; + struct file_zero_data_information fsctl_buf; + long rc; +@@ -2970,7 +2969,6 @@ static long smb3_punch_hole(struct file *file, struct cifs_tcon *tcon, + xid = get_xid(); + + inode = d_inode(cfile->dentry); +- cifsi = CIFS_I(inode); + + /* Need to make file sparse, if not already, before freeing range. */ + /* Consider adding equivalent for compressed since it could also work */ +-- +2.25.1 + + diff --git a/patches.suse/cifs-rename-a-variable-in-SendReceive-.patch b/patches.suse/cifs-rename-a-variable-in-SendReceive-.patch new file mode 100644 index 0000000..3a9e627 --- /dev/null +++ b/patches.suse/cifs-rename-a-variable-in-SendReceive-.patch @@ -0,0 +1,35 @@ +From: Dan Carpenter +Date: Fri, 25 Oct 2019 13:35:08 +0300 +Subject: [PATCH] cifs: rename a variable in SendReceive() +Git-commit: 8bd3754cff3aa6e80e73cb56042cdc6f76d6510e +References: bsc#1144333 +Patch-mainline: v5.5-rc1 + +Smatch gets confused because we sometimes refer to "server->srv_mutex" and +sometimes to "sess->server->srv_mutex". They refer to the same lock so +let's just make this consistent. + +Signed-off-by: Dan Carpenter +Signed-off-by: Steve French +Acked-by: Paulo Alcantara +--- + fs/cifs/transport.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c +index ca3de62688d6..f27842fb9f75 100644 +--- a/fs/cifs/transport.c ++++ b/fs/cifs/transport.c +@@ -1287,7 +1287,7 @@ SendReceive(const unsigned int xid, struct cifs_ses *ses, + + rc = allocate_mid(ses, in_buf, &midQ); + if (rc) { +- mutex_unlock(&ses->server->srv_mutex); ++ mutex_unlock(&server->srv_mutex); + /* Update # of requests on wire to server */ + add_credits(server, &credits, 0); + return rc; +-- +2.25.1 + + diff --git a/patches.suse/cifs-rename-posix-create-rsp.patch b/patches.suse/cifs-rename-posix-create-rsp.patch new file mode 100644 index 0000000..7d09a0b --- /dev/null +++ b/patches.suse/cifs-rename-posix-create-rsp.patch @@ -0,0 +1,90 @@ +From 2f94a73640d561ac1c73816fd88ca963423491c3 Mon Sep 17 00:00:00 2001 +From: Aurelien Aptel +Date: Sat, 8 Feb 2020 15:50:56 +0100 +Subject: [PATCH] cifs: rename posix create rsp +Patch-mainline: Not yet, in for-next branch +References: bsc#1144333 + +little progress on the posix create response. + +* rename struct to create_posix_rsp to match with the request + create_posix context +* make struct packed +* pass smb info struct for parse_posix_ctxt to fill +* use smb info struct as param +* update TODO + +What needs to be done: + +SMB2_open() has an optional smb info out argument that it will fill. +Callers making use of this are: + +- smb3_query_mf_symlink (need to investigate) +- smb2_open_file + +Callers of smb2_open_file (via server->ops->open) are passing an +smbinfo struct but that struct cannot hold POSIX information. All the +call stack needs to be changed for a different info type. Maybe pass +SMB generic struct like cifs_fattr instead. + +Signed-off-by: Aurelien Aptel +Signed-off-by: Steve French +Acked-by: Paulo Alcantara +--- + fs/cifs/smb2pdu.c | 13 +++++++++---- + fs/cifs/smb2pdu.h | 10 ++++++---- + 2 files changed, 15 insertions(+), 8 deletions(-) + +--- a/fs/cifs/smb2pdu.c ++++ b/fs/cifs/smb2pdu.c +@@ -1928,13 +1928,18 @@ parse_query_id_ctxt(struct create_contex + } + + static void +-parse_posix_ctxt(struct create_context *cc, struct smb_posix_info *pposix_inf) ++parse_posix_ctxt(struct create_context *cc, struct smb2_file_all_info *info) + { +- /* struct smb_posix_info *ppinf = (struct smb_posix_info *)cc; */ ++ /* struct create_posix_rsp *posix = (struct create_posix_rsp *)cc; */ + +- /* TODO: Need to add parsing for the context and return */ ++ /* ++ * TODO: Need to add parsing for the context and return. Can ++ * smb2_file_all_info hold POSIX data? Need to change the ++ * passed type from SMB2_open. ++ */ + printk_once(KERN_WARNING + "SMB3 3.11 POSIX response context not completed yet\n"); ++ + } + + void +@@ -1972,7 +1977,7 @@ smb2_parse_contexts(struct TCP_Server_In + parse_query_id_ctxt(cc, buf); + else if ((le16_to_cpu(cc->NameLength) == 16)) { + if (memcmp(name, smb3_create_tag_posix, 16) == 0) +- parse_posix_ctxt(cc, NULL); ++ parse_posix_ctxt(cc, buf); + } + /* else { + cifs_dbg(FYI, "Context not matched with len %d\n", +--- a/fs/cifs/smb2pdu.h ++++ b/fs/cifs/smb2pdu.h +@@ -1604,11 +1604,13 @@ struct smb2_file_id_information { + extern char smb2_padding[7]; + + /* equivalent of the contents of SMB3.1.1 POSIX open context response */ +-struct smb_posix_info { ++struct create_posix_rsp { + __le32 nlink; + __le32 reparse_tag; + __le32 mode; +- kuid_t uid; +- kuid_t gid; +-}; ++ /* ++ * var sized owner SID ++ * var sized group SID ++ */ ++} __packed; + #endif /* _SMB2PDU_H */ diff --git a/patches.suse/cifs-replace-various-strncpy-with-strscpy-and-similar.patch b/patches.suse/cifs-replace-various-strncpy-with-strscpy-and-similar.patch new file mode 100644 index 0000000..3538582 --- /dev/null +++ b/patches.suse/cifs-replace-various-strncpy-with-strscpy-and-similar.patch @@ -0,0 +1,592 @@ +From: Ronnie Sahlberg +Date: Tue, 27 Aug 2019 09:30:14 +1000 +Subject: [PATCH] cifs: replace various strncpy with strscpy and similar +Git-commit: 340625e618e1b37a72a02f07aa7144ae0ab0b19e +References: bsc#1144333 +Patch-mainline: v5.3-rc7 + +Using strscpy is cleaner, and avoids some problems with +handling maximum length strings. Linus noticed the +original problem and Aurelien pointed out some additional +problems. Fortunately most of this is SMB1 code (and +in particular the ASCII string handling older, which +is less common). + +Reported-by: Linus Torvalds +Reviewed-by: Aurelien Aptel +Signed-off-by: Ronnie Sahlberg +Signed-off-by: Steve French +Acked-by: Paulo Alcantara +--- + fs/cifs/cifsproto.h | 1 + + fs/cifs/cifssmb.c | 197 +++++++++++++++----------------------------- + fs/cifs/connect.c | 7 +- + fs/cifs/dir.c | 5 +- + fs/cifs/misc.c | 22 +++++ + fs/cifs/sess.c | 26 ++++-- + 6 files changed, 112 insertions(+), 146 deletions(-) + +diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h +index e23234207fc2..592a6cea2b79 100644 +--- a/fs/cifs/cifsproto.h ++++ b/fs/cifs/cifsproto.h +@@ -579,6 +579,7 @@ extern void rqst_page_get_length(struct smb_rqst *rqst, unsigned int page, + unsigned int *len, unsigned int *offset); + + void extract_unc_hostname(const char *unc, const char **h, size_t *len); ++int copy_path_name(char *dst, const char *src); + + #ifdef CONFIG_CIFS_DFS_UPCALL + static inline int get_dfs_path(const unsigned int xid, struct cifs_ses *ses, +diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c +index e2f95965065d..3907653e63c7 100644 +--- a/fs/cifs/cifssmb.c ++++ b/fs/cifs/cifssmb.c +@@ -942,10 +942,8 @@ CIFSPOSIXDelFile(const unsigned int xid, struct cifs_tcon *tcon, + PATH_MAX, nls_codepage, remap); + name_len++; /* trailing null */ + name_len *= 2; +- } else { /* BB add path length overrun check */ +- name_len = strnlen(fileName, PATH_MAX); +- name_len++; /* trailing null */ +- strncpy(pSMB->FileName, fileName, name_len); ++ } else { ++ name_len = copy_path_name(pSMB->FileName, fileName); + } + + params = 6 + name_len; +@@ -1015,10 +1013,8 @@ CIFSSMBDelFile(const unsigned int xid, struct cifs_tcon *tcon, const char *name, + remap); + name_len++; /* trailing null */ + name_len *= 2; +- } else { /* BB improve check for buffer overruns BB */ +- name_len = strnlen(name, PATH_MAX); +- name_len++; /* trailing null */ +- strncpy(pSMB->fileName, name, name_len); ++ } else { ++ name_len = copy_path_name(pSMB->fileName, name); + } + pSMB->SearchAttributes = + cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM); +@@ -1062,10 +1058,8 @@ CIFSSMBRmDir(const unsigned int xid, struct cifs_tcon *tcon, const char *name, + remap); + name_len++; /* trailing null */ + name_len *= 2; +- } else { /* BB improve check for buffer overruns BB */ +- name_len = strnlen(name, PATH_MAX); +- name_len++; /* trailing null */ +- strncpy(pSMB->DirName, name, name_len); ++ } else { ++ name_len = copy_path_name(pSMB->DirName, name); + } + + pSMB->BufferFormat = 0x04; +@@ -1107,10 +1101,8 @@ CIFSSMBMkDir(const unsigned int xid, struct cifs_tcon *tcon, const char *name, + remap); + name_len++; /* trailing null */ + name_len *= 2; +- } else { /* BB improve check for buffer overruns BB */ +- name_len = strnlen(name, PATH_MAX); +- name_len++; /* trailing null */ +- strncpy(pSMB->DirName, name, name_len); ++ } else { ++ name_len = copy_path_name(pSMB->DirName, name); + } + + pSMB->BufferFormat = 0x04; +@@ -1157,10 +1149,8 @@ CIFSPOSIXCreate(const unsigned int xid, struct cifs_tcon *tcon, + PATH_MAX, nls_codepage, remap); + name_len++; /* trailing null */ + name_len *= 2; +- } else { /* BB improve the check for buffer overruns BB */ +- name_len = strnlen(name, PATH_MAX); +- name_len++; /* trailing null */ +- strncpy(pSMB->FileName, name, name_len); ++ } else { ++ name_len = copy_path_name(pSMB->FileName, name); + } + + params = 6 + name_len; +@@ -1324,11 +1314,9 @@ SMBLegacyOpen(const unsigned int xid, struct cifs_tcon *tcon, + fileName, PATH_MAX, nls_codepage, remap); + name_len++; /* trailing null */ + name_len *= 2; +- } else { /* BB improve check for buffer overruns BB */ ++ } else { + count = 0; /* no pad */ +- name_len = strnlen(fileName, PATH_MAX); +- name_len++; /* trailing null */ +- strncpy(pSMB->fileName, fileName, name_len); ++ name_len = copy_path_name(pSMB->fileName, fileName); + } + if (*pOplock & REQ_OPLOCK) + pSMB->OpenFlags = cpu_to_le16(REQ_OPLOCK); +@@ -1442,11 +1430,8 @@ CIFS_open(const unsigned int xid, struct cifs_open_parms *oparms, int *oplock, + /* BB improve check for buffer overruns BB */ + /* no pad */ + count = 0; +- name_len = strnlen(path, PATH_MAX); +- /* trailing null */ +- name_len++; ++ name_len = copy_path_name(req->fileName, path); + req->NameLength = cpu_to_le16(name_len); +- strncpy(req->fileName, path, name_len); + } + + if (*oplock & REQ_OPLOCK) +@@ -2812,15 +2797,10 @@ CIFSSMBRename(const unsigned int xid, struct cifs_tcon *tcon, + remap); + name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ; + name_len2 *= 2; /* convert to bytes */ +- } else { /* BB improve the check for buffer overruns BB */ +- name_len = strnlen(from_name, PATH_MAX); +- name_len++; /* trailing null */ +- strncpy(pSMB->OldFileName, from_name, name_len); +- name_len2 = strnlen(to_name, PATH_MAX); +- name_len2++; /* trailing null */ ++ } else { ++ name_len = copy_path_name(pSMB->OldFileName, from_name); ++ name_len2 = copy_path_name(pSMB->OldFileName+name_len+1, to_name); + pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */ +- strncpy(&pSMB->OldFileName[name_len + 1], to_name, name_len2); +- name_len2++; /* trailing null */ + name_len2++; /* signature byte */ + } + +@@ -2962,15 +2942,10 @@ CIFSSMBCopy(const unsigned int xid, struct cifs_tcon *tcon, + toName, PATH_MAX, nls_codepage, remap); + name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ; + name_len2 *= 2; /* convert to bytes */ +- } else { /* BB improve the check for buffer overruns BB */ +- name_len = strnlen(fromName, PATH_MAX); +- name_len++; /* trailing null */ +- strncpy(pSMB->OldFileName, fromName, name_len); +- name_len2 = strnlen(toName, PATH_MAX); +- name_len2++; /* trailing null */ ++ } else { ++ name_len = copy_path_name(pSMB->OldFileName, fromName); + pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */ +- strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2); +- name_len2++; /* trailing null */ ++ name_len2 = copy_path_name(pSMB->OldFileName+name_len+1, toName); + name_len2++; /* signature byte */ + } + +@@ -3021,10 +2996,8 @@ CIFSUnixCreateSymLink(const unsigned int xid, struct cifs_tcon *tcon, + name_len++; /* trailing null */ + name_len *= 2; + +- } else { /* BB improve the check for buffer overruns BB */ +- name_len = strnlen(fromName, PATH_MAX); +- name_len++; /* trailing null */ +- strncpy(pSMB->FileName, fromName, name_len); ++ } else { ++ name_len = copy_path_name(pSMB->FileName, fromName); + } + params = 6 + name_len; + pSMB->MaxSetupCount = 0; +@@ -3044,10 +3017,8 @@ CIFSUnixCreateSymLink(const unsigned int xid, struct cifs_tcon *tcon, + PATH_MAX, nls_codepage, remap); + name_len_target++; /* trailing null */ + name_len_target *= 2; +- } else { /* BB improve the check for buffer overruns BB */ +- name_len_target = strnlen(toName, PATH_MAX); +- name_len_target++; /* trailing null */ +- strncpy(data_offset, toName, name_len_target); ++ } else { ++ name_len_target = copy_path_name(data_offset, toName); + } + + pSMB->MaxParameterCount = cpu_to_le16(2); +@@ -3109,10 +3080,8 @@ CIFSUnixCreateHardLink(const unsigned int xid, struct cifs_tcon *tcon, + name_len++; /* trailing null */ + name_len *= 2; + +- } else { /* BB improve the check for buffer overruns BB */ +- name_len = strnlen(toName, PATH_MAX); +- name_len++; /* trailing null */ +- strncpy(pSMB->FileName, toName, name_len); ++ } else { ++ name_len = copy_path_name(pSMB->FileName, toName); + } + params = 6 + name_len; + pSMB->MaxSetupCount = 0; +@@ -3131,10 +3100,8 @@ CIFSUnixCreateHardLink(const unsigned int xid, struct cifs_tcon *tcon, + PATH_MAX, nls_codepage, remap); + name_len_target++; /* trailing null */ + name_len_target *= 2; +- } else { /* BB improve the check for buffer overruns BB */ +- name_len_target = strnlen(fromName, PATH_MAX); +- name_len_target++; /* trailing null */ +- strncpy(data_offset, fromName, name_len_target); ++ } else { ++ name_len_target = copy_path_name(data_offset, fromName); + } + + pSMB->MaxParameterCount = cpu_to_le16(2); +@@ -3213,15 +3180,10 @@ CIFSCreateHardLink(const unsigned int xid, struct cifs_tcon *tcon, + remap); + name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ; + name_len2 *= 2; /* convert to bytes */ +- } else { /* BB improve the check for buffer overruns BB */ +- name_len = strnlen(from_name, PATH_MAX); +- name_len++; /* trailing null */ +- strncpy(pSMB->OldFileName, from_name, name_len); +- name_len2 = strnlen(to_name, PATH_MAX); +- name_len2++; /* trailing null */ ++ } else { ++ name_len = copy_path_name(pSMB->OldFileName, from_name); + pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */ +- strncpy(&pSMB->OldFileName[name_len + 1], to_name, name_len2); +- name_len2++; /* trailing null */ ++ name_len2 = copy_path_name(pSMB->OldFileName+name_len+1, to_name); + name_len2++; /* signature byte */ + } + +@@ -3271,10 +3233,8 @@ CIFSSMBUnixQuerySymLink(const unsigned int xid, struct cifs_tcon *tcon, + remap); + name_len++; /* trailing null */ + name_len *= 2; +- } else { /* BB improve the check for buffer overruns BB */ +- name_len = strnlen(searchName, PATH_MAX); +- name_len++; /* trailing null */ +- strncpy(pSMB->FileName, searchName, name_len); ++ } else { ++ name_len = copy_path_name(pSMB->FileName, searchName); + } + + params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ; +@@ -3691,10 +3651,8 @@ CIFSSMBGetPosixACL(const unsigned int xid, struct cifs_tcon *tcon, + name_len *= 2; + pSMB->FileName[name_len] = 0; + pSMB->FileName[name_len+1] = 0; +- } else { /* BB improve the check for buffer overruns BB */ +- name_len = strnlen(searchName, PATH_MAX); +- name_len++; /* trailing null */ +- strncpy(pSMB->FileName, searchName, name_len); ++ } else { ++ name_len = copy_path_name(pSMB->FileName, searchName); + } + + params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ; +@@ -3776,10 +3734,8 @@ CIFSSMBSetPosixACL(const unsigned int xid, struct cifs_tcon *tcon, + PATH_MAX, nls_codepage, remap); + name_len++; /* trailing null */ + name_len *= 2; +- } else { /* BB improve the check for buffer overruns BB */ +- name_len = strnlen(fileName, PATH_MAX); +- name_len++; /* trailing null */ +- strncpy(pSMB->FileName, fileName, name_len); ++ } else { ++ name_len = copy_path_name(pSMB->FileName, fileName); + } + params = 6 + name_len; + pSMB->MaxParameterCount = cpu_to_le16(2); +@@ -4184,9 +4140,7 @@ SMBQueryInformation(const unsigned int xid, struct cifs_tcon *tcon, + name_len++; /* trailing null */ + name_len *= 2; + } else { +- name_len = strnlen(search_name, PATH_MAX); +- name_len++; /* trailing null */ +- strncpy(pSMB->FileName, search_name, name_len); ++ name_len = copy_path_name(pSMB->FileName, search_name); + } + pSMB->BufferFormat = 0x04; + name_len++; /* account for buffer type byte */ +@@ -4321,10 +4275,8 @@ CIFSSMBQPathInfo(const unsigned int xid, struct cifs_tcon *tcon, + PATH_MAX, nls_codepage, remap); + name_len++; /* trailing null */ + name_len *= 2; +- } else { /* BB improve the check for buffer overruns BB */ +- name_len = strnlen(search_name, PATH_MAX); +- name_len++; /* trailing null */ +- strncpy(pSMB->FileName, search_name, name_len); ++ } else { ++ name_len = copy_path_name(pSMB->FileName, search_name); + } + + params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */; +@@ -4490,10 +4442,8 @@ CIFSSMBUnixQPathInfo(const unsigned int xid, struct cifs_tcon *tcon, + PATH_MAX, nls_codepage, remap); + name_len++; /* trailing null */ + name_len *= 2; +- } else { /* BB improve the check for buffer overruns BB */ +- name_len = strnlen(searchName, PATH_MAX); +- name_len++; /* trailing null */ +- strncpy(pSMB->FileName, searchName, name_len); ++ } else { ++ name_len = copy_path_name(pSMB->FileName, searchName); + } + + params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */; +@@ -4593,17 +4543,16 @@ CIFSFindFirst(const unsigned int xid, struct cifs_tcon *tcon, + pSMB->FileName[name_len+1] = 0; + name_len += 2; + } +- } else { /* BB add check for overrun of SMB buf BB */ +- name_len = strnlen(searchName, PATH_MAX); +-/* BB fix here and in unicode clause above ie +- if (name_len > buffersize-header) +- free buffer exit; BB */ +- strncpy(pSMB->FileName, searchName, name_len); ++ } else { ++ name_len = copy_path_name(pSMB->FileName, searchName); + if (msearch) { +- pSMB->FileName[name_len] = CIFS_DIR_SEP(cifs_sb); +- pSMB->FileName[name_len+1] = '*'; +- pSMB->FileName[name_len+2] = 0; +- name_len += 3; ++ if (WARN_ON_ONCE(name_len > PATH_MAX-2)) ++ name_len = PATH_MAX-2; ++ /* overwrite nul byte */ ++ pSMB->FileName[name_len-1] = CIFS_DIR_SEP(cifs_sb); ++ pSMB->FileName[name_len] = '*'; ++ pSMB->FileName[name_len+1] = 0; ++ name_len += 2; + } + } + +@@ -4898,10 +4847,8 @@ CIFSGetSrvInodeNumber(const unsigned int xid, struct cifs_tcon *tcon, + remap); + name_len++; /* trailing null */ + name_len *= 2; +- } else { /* BB improve the check for buffer overruns BB */ +- name_len = strnlen(search_name, PATH_MAX); +- name_len++; /* trailing null */ +- strncpy(pSMB->FileName, search_name, name_len); ++ } else { ++ name_len = copy_path_name(pSMB->FileName, search_name); + } + + params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ; +@@ -5008,9 +4955,7 @@ CIFSGetDFSRefer(const unsigned int xid, struct cifs_ses *ses, + name_len++; /* trailing null */ + name_len *= 2; + } else { /* BB improve the check for buffer overruns BB */ +- name_len = strnlen(search_name, PATH_MAX); +- name_len++; /* trailing null */ +- strncpy(pSMB->RequestFileName, search_name, name_len); ++ name_len = copy_path_name(pSMB->RequestFileName, search_name); + } + + if (ses->server->sign) +@@ -5663,10 +5608,8 @@ CIFSSMBSetEOF(const unsigned int xid, struct cifs_tcon *tcon, + PATH_MAX, cifs_sb->local_nls, remap); + name_len++; /* trailing null */ + name_len *= 2; +- } else { /* BB improve the check for buffer overruns BB */ +- name_len = strnlen(file_name, PATH_MAX); +- name_len++; /* trailing null */ +- strncpy(pSMB->FileName, file_name, name_len); ++ } else { ++ name_len = copy_path_name(pSMB->FileName, file_name); + } + params = 6 + name_len; + data_count = sizeof(struct file_end_of_file_info); +@@ -5959,10 +5902,8 @@ CIFSSMBSetPathInfo(const unsigned int xid, struct cifs_tcon *tcon, + PATH_MAX, nls_codepage, remap); + name_len++; /* trailing null */ + name_len *= 2; +- } else { /* BB improve the check for buffer overruns BB */ +- name_len = strnlen(fileName, PATH_MAX); +- name_len++; /* trailing null */ +- strncpy(pSMB->FileName, fileName, name_len); ++ } else { ++ name_len = copy_path_name(pSMB->FileName, fileName); + } + + params = 6 + name_len; +@@ -6040,10 +5981,8 @@ CIFSSMBSetAttrLegacy(unsigned int xid, struct cifs_tcon *tcon, char *fileName, + PATH_MAX, nls_codepage); + name_len++; /* trailing null */ + name_len *= 2; +- } else { /* BB improve the check for buffer overruns BB */ +- name_len = strnlen(fileName, PATH_MAX); +- name_len++; /* trailing null */ +- strncpy(pSMB->fileName, fileName, name_len); ++ } else { ++ name_len = copy_path_name(pSMB->fileName, fileName); + } + pSMB->attr = cpu_to_le16(dos_attrs); + pSMB->BufferFormat = 0x04; +@@ -6203,10 +6142,8 @@ CIFSSMBUnixSetPathInfo(const unsigned int xid, struct cifs_tcon *tcon, + PATH_MAX, nls_codepage, remap); + name_len++; /* trailing null */ + name_len *= 2; +- } else { /* BB improve the check for buffer overruns BB */ +- name_len = strnlen(file_name, PATH_MAX); +- name_len++; /* trailing null */ +- strncpy(pSMB->FileName, file_name, name_len); ++ } else { ++ name_len = copy_path_name(pSMB->FileName, file_name); + } + + params = 6 + name_len; +@@ -6298,10 +6235,8 @@ CIFSSMBQAllEAs(const unsigned int xid, struct cifs_tcon *tcon, + PATH_MAX, nls_codepage, remap); + list_len++; /* trailing null */ + list_len *= 2; +- } else { /* BB improve the check for buffer overruns BB */ +- list_len = strnlen(searchName, PATH_MAX); +- list_len++; /* trailing null */ +- strncpy(pSMB->FileName, searchName, list_len); ++ } else { ++ list_len = copy_path_name(pSMB->FileName, searchName); + } + + params = 2 /* level */ + 4 /* reserved */ + list_len /* includes NUL */; +@@ -6480,10 +6415,8 @@ CIFSSMBSetEA(const unsigned int xid, struct cifs_tcon *tcon, + PATH_MAX, nls_codepage, remap); + name_len++; /* trailing null */ + name_len *= 2; +- } else { /* BB improve the check for buffer overruns BB */ +- name_len = strnlen(fileName, PATH_MAX); +- name_len++; /* trailing null */ +- strncpy(pSMB->FileName, fileName, name_len); ++ } else { ++ name_len = copy_path_name(pSMB->FileName, fileName); + } + + params = 6 + name_len; +diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c +index ddefddeffd06..5299effa6f7d 100644 +--- a/fs/cifs/connect.c ++++ b/fs/cifs/connect.c +@@ -4231,16 +4231,19 @@ build_unc_path_to_root(const struct smb_vol *vol, + strlen(vol->prepath) + 1 : 0; + unsigned int unc_len = strnlen(vol->UNC, MAX_TREE_SIZE + 1); + ++ if (unc_len > MAX_TREE_SIZE) ++ return ERR_PTR(-EINVAL); ++ + full_path = kmalloc(unc_len + pplen + 1, GFP_KERNEL); + if (full_path == NULL) + return ERR_PTR(-ENOMEM); + +- strncpy(full_path, vol->UNC, unc_len); ++ memcpy(full_path, vol->UNC, unc_len); + pos = full_path + unc_len; + + if (pplen) { + *pos = CIFS_DIR_SEP(cifs_sb); +- strncpy(pos + 1, vol->prepath, pplen); ++ memcpy(pos + 1, vol->prepath, pplen); + pos += pplen; + } + +diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c +index f26a48dd2e39..be424e81e3ad 100644 +--- a/fs/cifs/dir.c ++++ b/fs/cifs/dir.c +@@ -69,11 +69,10 @@ cifs_build_path_to_root(struct smb_vol *vol, struct cifs_sb_info *cifs_sb, + return full_path; + + if (dfsplen) +- strncpy(full_path, tcon->treeName, dfsplen); ++ memcpy(full_path, tcon->treeName, dfsplen); + full_path[dfsplen] = CIFS_DIR_SEP(cifs_sb); +- strncpy(full_path + dfsplen + 1, vol->prepath, pplen); ++ memcpy(full_path + dfsplen + 1, vol->prepath, pplen); + convert_delimiter(full_path, CIFS_DIR_SEP(cifs_sb)); +- full_path[dfsplen + pplen] = 0; /* add trailing null */ + return full_path; + } + +diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c +index f383877a6511..5ad83bdb9bea 100644 +--- a/fs/cifs/misc.c ++++ b/fs/cifs/misc.c +@@ -1011,3 +1011,25 @@ void extract_unc_hostname(const char *unc, const char **h, size_t *len) + *h = unc; + *len = end - unc; + } ++ ++/** ++ * copy_path_name - copy src path to dst, possibly truncating ++ * ++ * returns number of bytes written (including trailing nul) ++ */ ++int copy_path_name(char *dst, const char *src) ++{ ++ int name_len; ++ ++ /* ++ * PATH_MAX includes nul, so if strlen(src) >= PATH_MAX it ++ * will truncate and strlen(dst) will be PATH_MAX-1 ++ */ ++ name_len = strscpy(dst, src, PATH_MAX); ++ if (WARN_ON_ONCE(name_len < 0)) ++ name_len = PATH_MAX-1; ++ ++ /* we count the trailing nul */ ++ name_len++; ++ return name_len; ++} +diff --git a/fs/cifs/sess.c b/fs/cifs/sess.c +index dcd49ad60c83..4c764ff7edd2 100644 +--- a/fs/cifs/sess.c ++++ b/fs/cifs/sess.c +@@ -159,13 +159,16 @@ static void ascii_ssetup_strings(char **pbcc_area, struct cifs_ses *ses, + const struct nls_table *nls_cp) + { + char *bcc_ptr = *pbcc_area; ++ int len; + + /* copy user */ + /* BB what about null user mounts - check that we do this BB */ + /* copy user */ + if (ses->user_name != NULL) { +- strncpy(bcc_ptr, ses->user_name, CIFS_MAX_USERNAME_LEN); +- bcc_ptr += strnlen(ses->user_name, CIFS_MAX_USERNAME_LEN); ++ len = strscpy(bcc_ptr, ses->user_name, CIFS_MAX_USERNAME_LEN); ++ if (WARN_ON_ONCE(len < 0)) ++ len = CIFS_MAX_USERNAME_LEN - 1; ++ bcc_ptr += len; + } + /* else null user mount */ + *bcc_ptr = 0; +@@ -173,8 +176,10 @@ static void ascii_ssetup_strings(char **pbcc_area, struct cifs_ses *ses, + + /* copy domain */ + if (ses->domainName != NULL) { +- strncpy(bcc_ptr, ses->domainName, CIFS_MAX_DOMAINNAME_LEN); +- bcc_ptr += strnlen(ses->domainName, CIFS_MAX_DOMAINNAME_LEN); ++ len = strscpy(bcc_ptr, ses->domainName, CIFS_MAX_DOMAINNAME_LEN); ++ if (WARN_ON_ONCE(len < 0)) ++ len = CIFS_MAX_DOMAINNAME_LEN - 1; ++ bcc_ptr += len; + } /* else we will send a null domain name + so the server will default to its own domain */ + *bcc_ptr = 0; +@@ -242,9 +247,10 @@ static void decode_ascii_ssetup(char **pbcc_area, __u16 bleft, + + kfree(ses->serverOS); + +- ses->serverOS = kzalloc(len + 1, GFP_KERNEL); ++ ses->serverOS = kmalloc(len + 1, GFP_KERNEL); + if (ses->serverOS) { +- strncpy(ses->serverOS, bcc_ptr, len); ++ memcpy(ses->serverOS, bcc_ptr, len); ++ ses->serverOS[len] = 0; + if (strncmp(ses->serverOS, "OS/2", 4) == 0) + cifs_dbg(FYI, "OS/2 server\n"); + } +@@ -258,9 +264,11 @@ static void decode_ascii_ssetup(char **pbcc_area, __u16 bleft, + + kfree(ses->serverNOS); + +- ses->serverNOS = kzalloc(len + 1, GFP_KERNEL); +- if (ses->serverNOS) +- strncpy(ses->serverNOS, bcc_ptr, len); ++ ses->serverNOS = kmalloc(len + 1, GFP_KERNEL); ++ if (ses->serverNOS) { ++ memcpy(ses->serverNOS, bcc_ptr, len); ++ ses->serverNOS[len] = 0; ++ } + + bcc_ptr += len + 1; + bleft -= len + 1; +-- +2.25.1 + + diff --git a/patches.suse/cifs-set-correct-max-buffer-size-for-smb2_ioctl_init-.patch b/patches.suse/cifs-set-correct-max-buffer-size-for-smb2_ioctl_init-.patch new file mode 100644 index 0000000..4f93127 --- /dev/null +++ b/patches.suse/cifs-set-correct-max-buffer-size-for-smb2_ioctl_init-.patch @@ -0,0 +1,50 @@ +From: Ronnie Sahlberg +Date: Wed, 8 Jan 2020 13:08:07 +1000 +Subject: [PATCH] cifs: set correct max-buffer-size for smb2_ioctl_init() +Git-commit: 731b82bb1750a906c1e7f070aedf5505995ebea7 +References: bsc#1144333 +Patch-mainline: v5.6-rc1 + +Fix two places where we need to adjust down the max response size for +ioctl when it is used together with compounding. + +Signed-off-by: Ronnie Sahlberg +Signed-off-by: Steve French +Reviewed-by: Pavel Shilovsky +CC: Stable +Acked-by: Paulo Alcantara +--- + fs/cifs/smb2ops.c | 9 +++++++-- + 1 file changed, 7 insertions(+), 2 deletions(-) + +diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c +index ccaff438b94d..2e532f053b8c 100644 +--- a/fs/cifs/smb2ops.c ++++ b/fs/cifs/smb2ops.c +@@ -1523,7 +1523,9 @@ smb2_ioctl_query_info(const unsigned int xid, + COMPOUND_FID, COMPOUND_FID, + qi.info_type, true, buffer, + qi.output_buffer_length, +- CIFSMaxBufSize); ++ CIFSMaxBufSize - ++ MAX_SMB2_CREATE_RESPONSE_SIZE - ++ MAX_SMB2_CLOSE_RESPONSE_SIZE); + } + } else if (qi.flags == PASSTHRU_SET_INFO) { + /* Can eventually relax perm check since server enforces too */ +@@ -2769,7 +2771,10 @@ smb2_query_symlink(const unsigned int xid, struct cifs_tcon *tcon, + + rc = SMB2_ioctl_init(tcon, &rqst[1], fid.persistent_fid, + fid.volatile_fid, FSCTL_GET_REPARSE_POINT, +- true /* is_fctl */, NULL, 0, CIFSMaxBufSize); ++ true /* is_fctl */, NULL, 0, ++ CIFSMaxBufSize - ++ MAX_SMB2_CREATE_RESPONSE_SIZE - ++ MAX_SMB2_CLOSE_RESPONSE_SIZE); + if (rc) + goto querty_exit; + +-- +2.25.1 + + diff --git a/patches.suse/cifs-smbd-Add-messages-on-RDMA-session-destroy-and-reconnection.patch b/patches.suse/cifs-smbd-Add-messages-on-RDMA-session-destroy-and-reconnection.patch new file mode 100644 index 0000000..f4d8166 --- /dev/null +++ b/patches.suse/cifs-smbd-Add-messages-on-RDMA-session-destroy-and-reconnection.patch @@ -0,0 +1,46 @@ +From: Long Li +Date: Wed, 16 Oct 2019 13:51:53 -0700 +Subject: [PATCH] cifs: smbd: Add messages on RDMA session destroy and + reconnection +Git-commit: d63cdbae60ac6fbb2864bd3d8df7404f12b7407d +References: bsc#1144333 +Patch-mainline: v5.5-rc1 + +Log these activities to help production support. + +Signed-off-by: Long Li +Cc: stable@vger.kernel.org +Signed-off-by: Steve French +Acked-by: Paulo Alcantara +--- + fs/cifs/smbdirect.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/fs/cifs/smbdirect.c b/fs/cifs/smbdirect.c +index 64c5b872220d..5462cf752432 100644 +--- a/fs/cifs/smbdirect.c ++++ b/fs/cifs/smbdirect.c +@@ -1476,6 +1476,7 @@ void smbd_destroy(struct TCP_Server_Info *server) + info->transport_status = SMBD_DESTROYED; + + destroy_workqueue(info->workqueue); ++ log_rdma_event(INFO, "rdma session destroyed\n"); + kfree(info); + } + +@@ -1505,8 +1506,9 @@ int smbd_reconnect(struct TCP_Server_Info *server) + log_rdma_event(INFO, "creating rdma session\n"); + server->smbd_conn = smbd_get_connection( + server, (struct sockaddr *) &server->dstaddr); +- log_rdma_event(INFO, "created rdma session info=%p\n", +- server->smbd_conn); ++ ++ if (server->smbd_conn) ++ cifs_dbg(VFS, "RDMA transport re-established\n"); + + return server->smbd_conn ? 0 : -ENOENT; + } +-- +2.25.1 + + diff --git a/patches.suse/cifs-smbd-Invalidate-and-deregister-memory-registration-on-re-send.patch b/patches.suse/cifs-smbd-Invalidate-and-deregister-memory-registration-on-re-send.patch new file mode 100644 index 0000000..c6ad837 --- /dev/null +++ b/patches.suse/cifs-smbd-Invalidate-and-deregister-memory-registration-on-re-send.patch @@ -0,0 +1,63 @@ +From: Long Li +Date: Tue, 15 Oct 2019 22:54:50 +0000 +Subject: [PATCH] cifs: smbd: Invalidate and deregister memory registration on + re-send for direct I/O +Git-commit: b7a55bbd6d5402bfbadcfb3904e3c75b38ab5ba4 +References: bsc#1144333 +Patch-mainline: v5.5-rc1 + +On re-send, there might be a reconnect and all prevoius memory registrations +need to be invalidated and deregistered. + +Signed-off-by: Long Li +Signed-off-by: Steve French +Acked-by: Paulo Alcantara +--- + fs/cifs/file.c | 20 ++++++++++++++++++-- + 1 file changed, 18 insertions(+), 2 deletions(-) + +diff --git a/fs/cifs/file.c b/fs/cifs/file.c +index a80ec683ea32..67e7d0ffe385 100644 +--- a/fs/cifs/file.c ++++ b/fs/cifs/file.c +@@ -2803,9 +2803,17 @@ cifs_resend_wdata(struct cifs_writedata *wdata, struct list_head *wdata_list, + if (!rc) { + if (wdata->cfile->invalidHandle) + rc = -EAGAIN; +- else ++ else { ++#ifdef CONFIG_CIFS_SMB_DIRECT ++ if (wdata->mr) { ++ wdata->mr->need_invalidate = true; ++ smbd_deregister_mr(wdata->mr); ++ wdata->mr = NULL; ++ } ++#endif + rc = server->ops->async_writev(wdata, + cifs_uncached_writedata_release); ++ } + } + + /* If the write was successfully sent, we are done */ +@@ -3528,8 +3536,16 @@ static int cifs_resend_rdata(struct cifs_readdata *rdata, + if (!rc) { + if (rdata->cfile->invalidHandle) + rc = -EAGAIN; +- else ++ else { ++#ifdef CONFIG_CIFS_SMB_DIRECT ++ if (rdata->mr) { ++ rdata->mr->need_invalidate = true; ++ smbd_deregister_mr(rdata->mr); ++ rdata->mr = NULL; ++ } ++#endif + rc = server->ops->async_readv(rdata); ++ } + } + + /* If the read was successfully sent, we are done */ +-- +2.25.1 + + diff --git a/patches.suse/cifs-smbd-Only-queue-work-for-error-recovery-on-memory-registratio.patch b/patches.suse/cifs-smbd-Only-queue-work-for-error-recovery-on-memory-registratio.patch new file mode 100644 index 0000000..679c9cc --- /dev/null +++ b/patches.suse/cifs-smbd-Only-queue-work-for-error-recovery-on-memory-registratio.patch @@ -0,0 +1,69 @@ +From: Long Li +Date: Wed, 16 Oct 2019 13:51:55 -0700 +Subject: [PATCH] cifs: smbd: Only queue work for error recovery on memory + registration +Git-commit: c21ce58eab1eda4c66507897207e20c82e62a5ac +References: bsc#1144333 +Patch-mainline: v5.5-rc1 + +It's not necessary to queue invalidated memory registration to work queue, as +all we need to do is to unmap the SG and make it usable again. This can save +CPU cycles in normal data paths as memory registration errors are rare and +normally only happens during reconnection. + +Signed-off-by: Long Li +Cc: stable@vger.kernel.org +Signed-off-by: Steve French +Acked-by: Paulo Alcantara +--- + fs/cifs/smbdirect.c | 26 +++++++++++++++----------- + 1 file changed, 15 insertions(+), 11 deletions(-) + +diff --git a/fs/cifs/smbdirect.c b/fs/cifs/smbdirect.c +index d91f2f60e2df..5b1b97e9e0c9 100644 +--- a/fs/cifs/smbdirect.c ++++ b/fs/cifs/smbdirect.c +@@ -2271,12 +2271,7 @@ static void smbd_mr_recovery_work(struct work_struct *work) + int rc; + + list_for_each_entry(smbdirect_mr, &info->mr_list, list) { +- if (smbdirect_mr->state == MR_INVALIDATED) +- ib_dma_unmap_sg( +- info->id->device, smbdirect_mr->sgl, +- smbdirect_mr->sgl_count, +- smbdirect_mr->dir); +- else if (smbdirect_mr->state == MR_ERROR) { ++ if (smbdirect_mr->state == MR_ERROR) { + + /* recover this MR entry */ + rc = ib_dereg_mr(smbdirect_mr->mr); +@@ -2604,11 +2599,20 @@ int smbd_deregister_mr(struct smbd_mr *smbdirect_mr) + */ + smbdirect_mr->state = MR_INVALIDATED; + +- /* +- * Schedule the work to do MR recovery for future I/Os +- * MR recovery is slow and we don't want it to block the current I/O +- */ +- queue_work(info->workqueue, &info->mr_recovery_work); ++ if (smbdirect_mr->state == MR_INVALIDATED) { ++ ib_dma_unmap_sg( ++ info->id->device, smbdirect_mr->sgl, ++ smbdirect_mr->sgl_count, ++ smbdirect_mr->dir); ++ smbdirect_mr->state = MR_READY; ++ if (atomic_inc_return(&info->mr_ready_count) == 1) ++ wake_up_interruptible(&info->wait_mr); ++ } else ++ /* ++ * Schedule the work to do MR recovery for future I/Os MR ++ * recovery is slow and don't want it to block current I/O ++ */ ++ queue_work(info->workqueue, &info->mr_recovery_work); + + done: + if (atomic_dec_and_test(&info->mr_used_count)) +-- +2.25.1 + + diff --git a/patches.suse/cifs-smbd-Return-EAGAIN-when-transport-is-reconnecting.patch b/patches.suse/cifs-smbd-Return-EAGAIN-when-transport-is-reconnecting.patch new file mode 100644 index 0000000..8b02247 --- /dev/null +++ b/patches.suse/cifs-smbd-Return-EAGAIN-when-transport-is-reconnecting.patch @@ -0,0 +1,41 @@ +From: Long Li +Date: Wed, 16 Oct 2019 13:51:56 -0700 +Subject: [PATCH] cifs: smbd: Return -EAGAIN when transport is reconnecting +Git-commit: 4357d45f50e58672e1d17648d792f27df01dfccd +References: bsc#1144333 +Patch-mainline: v5.5-rc1 + +During reconnecting, the transport may have already been destroyed and is in +the process being reconnected. In this case, return -EAGAIN to not fail and +to retry this I/O. + +Signed-off-by: Long Li +Cc: stable@vger.kernel.org +Signed-off-by: Steve French +Acked-by: Paulo Alcantara +--- + fs/cifs/transport.c | 7 +++++-- + 1 file changed, 5 insertions(+), 2 deletions(-) + +diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c +index 19300e0cf1d6..4104f59e5bd6 100644 +--- a/fs/cifs/transport.c ++++ b/fs/cifs/transport.c +@@ -325,8 +325,11 @@ __smb_send_rqst(struct TCP_Server_Info *server, int num_rqst, + int val = 1; + __be32 rfc1002_marker; + +- if (cifs_rdma_enabled(server) && server->smbd_conn) { +- rc = smbd_send(server, num_rqst, rqst); ++ if (cifs_rdma_enabled(server)) { ++ /* return -EAGAIN when connecting or reconnecting */ ++ rc = -EAGAIN; ++ if (server->smbd_conn) ++ rc = smbd_send(server, num_rqst, rqst); + goto smbd_done; + } + +-- +2.25.1 + + diff --git a/patches.suse/cifs-smbd-Return-ECONNABORTED-when-trasnport-is-not-in-connected-.patch b/patches.suse/cifs-smbd-Return-ECONNABORTED-when-trasnport-is-not-in-connected-.patch new file mode 100644 index 0000000..8b2fe13 --- /dev/null +++ b/patches.suse/cifs-smbd-Return-ECONNABORTED-when-trasnport-is-not-in-connected-.patch @@ -0,0 +1,35 @@ +From: Long Li +Date: Wed, 16 Oct 2019 13:51:54 -0700 +Subject: [PATCH] cifs: smbd: Return -ECONNABORTED when trasnport is not in + connected state +Git-commit: acd4680e2bef2405a0e1ef2149fbb01cce7e116c +References: bsc#1144333 +Patch-mainline: v5.5-rc1 + +The transport should return this error so the upper layer will reconnect. + +Signed-off-by: Long Li +Cc: stable@vger.kernel.org +Signed-off-by: Steve French +Acked-by: Paulo Alcantara +--- + fs/cifs/smbdirect.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/fs/cifs/smbdirect.c b/fs/cifs/smbdirect.c +index 5462cf752432..d91f2f60e2df 100644 +--- a/fs/cifs/smbdirect.c ++++ b/fs/cifs/smbdirect.c +@@ -1972,7 +1972,7 @@ static int smbd_recv_buf(struct smbd_connection *info, char *buf, + + if (info->transport_status != SMBD_CONNECTED) { + log_read(ERR, "disconnected\n"); +- return 0; ++ return -ECONNABORTED; + } + + goto again; +-- +2.25.1 + + diff --git a/patches.suse/cifs-smbd-Return-EINVAL-when-the-number-of-iovs-exceeds-SMBDIRECT.patch b/patches.suse/cifs-smbd-Return-EINVAL-when-the-number-of-iovs-exceeds-SMBDIRECT.patch new file mode 100644 index 0000000..7017f79 --- /dev/null +++ b/patches.suse/cifs-smbd-Return-EINVAL-when-the-number-of-iovs-exceeds-SMBDIRECT.patch @@ -0,0 +1,37 @@ +From: Long Li +Date: Wed, 16 Oct 2019 13:51:52 -0700 +Subject: [PATCH] cifs: smbd: Return -EINVAL when the number of iovs exceeds + SMBDIRECT_MAX_SGE +Git-commit: 37941ea17d3f8eb2f5ac2f59346fab9e8439271a +References: bsc#1144333 +Patch-mainline: v5.5-rc1 + +While it's not friendly to fail user processes that issue more iovs +than we support, at least we should return the correct error code so the +user process gets a chance to retry with smaller number of iovs. + +Signed-off-by: Long Li +Cc: stable@vger.kernel.org +Signed-off-by: Steve French +Acked-by: Paulo Alcantara +--- + fs/cifs/smbdirect.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/fs/cifs/smbdirect.c b/fs/cifs/smbdirect.c +index 3c91fa97c9a8..64c5b872220d 100644 +--- a/fs/cifs/smbdirect.c ++++ b/fs/cifs/smbdirect.c +@@ -1069,7 +1069,7 @@ static int smbd_post_send_data( + + if (n_vec > SMBDIRECT_MAX_SGE) { + cifs_dbg(VFS, "Can't fit data to SGL, n_vec=%d\n", n_vec); +- return -ENOMEM; ++ return -EINVAL; + } + + sg_init_table(sgl, n_vec); +-- +2.25.1 + + diff --git a/patches.suse/cifs-use-PTR_ERR_OR_ZERO-to-simplify-code.patch b/patches.suse/cifs-use-PTR_ERR_OR_ZERO-to-simplify-code.patch new file mode 100644 index 0000000..88acdb5 --- /dev/null +++ b/patches.suse/cifs-use-PTR_ERR_OR_ZERO-to-simplify-code.patch @@ -0,0 +1,35 @@ +From: Chen Zhou +Date: Wed, 22 Jan 2020 18:20:30 +0800 +Subject: [PATCH] cifs: use PTR_ERR_OR_ZERO() to simplify code +Git-commit: 050d2a8b6992fd012773e75de9f82d45e3b3dfff +References: bsc#1144333 +Patch-mainline: v5.6-rc1 + +PTR_ERR_OR_ZERO contains if(IS_ERR(...)) + PTR_ERR, just use +PTR_ERR_OR_ZERO directly. + +Signed-off-by: Chen Zhou +Signed-off-by: Steve French +Reviewed-by: Paulo Alcantara (SUSE) +Acked-by: Paulo Alcantara +--- + fs/cifs/dfs_cache.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/fs/cifs/dfs_cache.c b/fs/cifs/dfs_cache.c +index b0315b7270b4..9a384d1e27b4 100644 +--- a/fs/cifs/dfs_cache.c ++++ b/fs/cifs/dfs_cache.c +@@ -661,7 +661,7 @@ static int __dfs_cache_find(const unsigned int xid, struct cifs_ses *ses, + */ + if (noreq) { + up_read(&htable_rw_lock); +- return IS_ERR(ce) ? PTR_ERR(ce) : 0; ++ return PTR_ERR_OR_ZERO(ce); + } + + if (!IS_ERR(ce)) { +-- +2.25.1 + + diff --git a/patches.suse/cifs-use-compounding-for-open-and-first-query-dir-for-readdir-.patch b/patches.suse/cifs-use-compounding-for-open-and-first-query-dir-for-readdir-.patch new file mode 100644 index 0000000..8c61be1 --- /dev/null +++ b/patches.suse/cifs-use-compounding-for-open-and-first-query-dir-for-readdir-.patch @@ -0,0 +1,165 @@ +From: Ronnie Sahlberg +Date: Wed, 8 Jan 2020 13:08:06 +1000 +Subject: [PATCH] cifs: use compounding for open and first query-dir for + readdir() +Git-commit: 37478608f0eb6f232e62791683875a1f557b1b10 +References: bsc#1144333 +Patch-mainline: v5.6-rc1 + +Combine the initial SMB2_Open and the first SMB2_Query_Directory in a compound. +This shaves one round-trip of each directory listing, changing it from 4 to 3 +for small directories. + +Signed-off-by: Ronnie Sahlberg +Signed-off-by: Steve French +Reviewed-by: Pavel Shilovsky +Acked-by: Paulo Alcantara +--- + fs/cifs/cifsproto.h | 3 ++ + fs/cifs/smb2ops.c | 96 +++++++++++++++++++++++++++++++++++++++------ + 2 files changed, 87 insertions(+), 12 deletions(-) + +diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h +index 9c229408a251..f6f3cc90cd18 100644 +--- a/fs/cifs/cifsproto.h ++++ b/fs/cifs/cifsproto.h +@@ -596,6 +596,9 @@ bool is_ses_using_iface(struct cifs_ses *ses, struct cifs_server_iface *iface); + + void extract_unc_hostname(const char *unc, const char **h, size_t *len); + int copy_path_name(char *dst, const char *src); ++int smb2_parse_query_directory(struct cifs_tcon *tcon, struct kvec *rsp_iov, ++ int resp_buftype, ++ struct cifs_search_info *srch_inf); + + #ifdef CONFIG_CIFS_DFS_UPCALL + static inline int get_dfs_path(const unsigned int xid, struct cifs_ses *ses, +diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c +index 2c500226315d..ccaff438b94d 100644 +--- a/fs/cifs/smb2ops.c ++++ b/fs/cifs/smb2ops.c +@@ -2053,14 +2053,33 @@ smb2_query_dir_first(const unsigned int xid, struct cifs_tcon *tcon, + struct cifs_search_info *srch_inf) + { + __le16 *utf16_path; +- int rc; +- __u8 oplock = SMB2_OPLOCK_LEVEL_NONE; ++ struct smb_rqst rqst[2]; ++ struct kvec rsp_iov[2]; ++ int resp_buftype[2]; ++ struct kvec open_iov[SMB2_CREATE_IOV_SIZE]; ++ struct kvec qd_iov[SMB2_QUERY_DIRECTORY_IOV_SIZE]; ++ int rc, flags = 0; ++ u8 oplock = SMB2_OPLOCK_LEVEL_NONE; + struct cifs_open_parms oparms; ++ struct smb2_query_directory_rsp *qd_rsp = NULL; ++ struct smb2_create_rsp *op_rsp = NULL; + + utf16_path = cifs_convert_path_to_utf16(path, cifs_sb); + if (!utf16_path) + return -ENOMEM; + ++ if (smb3_encryption_required(tcon)) ++ flags |= CIFS_TRANSFORM_REQ; ++ ++ memset(rqst, 0, sizeof(rqst)); ++ resp_buftype[0] = resp_buftype[1] = CIFS_NO_BUFFER; ++ memset(rsp_iov, 0, sizeof(rsp_iov)); ++ ++ /* Open */ ++ memset(&open_iov, 0, sizeof(open_iov)); ++ rqst[0].rq_iov = open_iov; ++ rqst[0].rq_nvec = SMB2_CREATE_IOV_SIZE; ++ + oparms.tcon = tcon; + oparms.desired_access = FILE_READ_ATTRIBUTES | FILE_READ_DATA; + oparms.disposition = FILE_OPEN; +@@ -2071,22 +2090,75 @@ smb2_query_dir_first(const unsigned int xid, struct cifs_tcon *tcon, + oparms.fid = fid; + oparms.reconnect = false; + +- rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, NULL, NULL); +- kfree(utf16_path); +- if (rc) { +- cifs_dbg(FYI, "open dir failed rc=%d\n", rc); +- return rc; +- } ++ rc = SMB2_open_init(tcon, &rqst[0], &oplock, &oparms, utf16_path); ++ if (rc) ++ goto qdf_free; ++ smb2_set_next_command(tcon, &rqst[0]); + ++ /* Query directory */ + srch_inf->entries_in_buffer = 0; + srch_inf->index_of_last_entry = 2; + +- rc = SMB2_query_directory(xid, tcon, fid->persistent_fid, +- fid->volatile_fid, 0, srch_inf); +- if (rc) { +- cifs_dbg(FYI, "query directory failed rc=%d\n", rc); ++ memset(&qd_iov, 0, sizeof(qd_iov)); ++ rqst[1].rq_iov = qd_iov; ++ rqst[1].rq_nvec = SMB2_QUERY_DIRECTORY_IOV_SIZE; ++ ++ rc = SMB2_query_directory_init(xid, tcon, &rqst[1], ++ COMPOUND_FID, COMPOUND_FID, ++ 0, srch_inf->info_level); ++ if (rc) ++ goto qdf_free; ++ ++ smb2_set_related(&rqst[1]); ++ ++ rc = compound_send_recv(xid, tcon->ses, flags, 2, rqst, ++ resp_buftype, rsp_iov); ++ ++ /* If the open failed there is nothing to do */ ++ op_rsp = (struct smb2_create_rsp *)rsp_iov[0].iov_base; ++ if (op_rsp == NULL || op_rsp->sync_hdr.Status != STATUS_SUCCESS) { ++ cifs_dbg(FYI, "query_dir_first: open failed rc=%d\n", rc); ++ goto qdf_free; ++ } ++ fid->persistent_fid = op_rsp->PersistentFileId; ++ fid->volatile_fid = op_rsp->VolatileFileId; ++ ++ /* Anything else than ENODATA means a genuine error */ ++ if (rc && rc != -ENODATA) { + SMB2_close(xid, tcon, fid->persistent_fid, fid->volatile_fid); ++ cifs_dbg(FYI, "query_dir_first: query directory failed rc=%d\n", rc); ++ trace_smb3_query_dir_err(xid, fid->persistent_fid, ++ tcon->tid, tcon->ses->Suid, 0, 0, rc); ++ goto qdf_free; + } ++ ++ qd_rsp = (struct smb2_query_directory_rsp *)rsp_iov[1].iov_base; ++ if (qd_rsp->sync_hdr.Status == STATUS_NO_MORE_FILES) { ++ trace_smb3_query_dir_done(xid, fid->persistent_fid, ++ tcon->tid, tcon->ses->Suid, 0, 0); ++ srch_inf->endOfSearch = true; ++ rc = 0; ++ goto qdf_free; ++ } ++ ++ rc = smb2_parse_query_directory(tcon, &rsp_iov[1], resp_buftype[1], ++ srch_inf); ++ if (rc) { ++ trace_smb3_query_dir_err(xid, fid->persistent_fid, tcon->tid, ++ tcon->ses->Suid, 0, 0, rc); ++ goto qdf_free; ++ } ++ resp_buftype[1] = CIFS_NO_BUFFER; ++ ++ trace_smb3_query_dir_done(xid, fid->persistent_fid, tcon->tid, ++ tcon->ses->Suid, 0, srch_inf->entries_in_buffer); ++ ++ qdf_free: ++ kfree(utf16_path); ++ SMB2_open_free(&rqst[0]); ++ SMB2_query_directory_free(&rqst[1]); ++ free_rsp_buf(resp_buftype[0], rsp_iov[0].iov_base); ++ free_rsp_buf(resp_buftype[1], rsp_iov[1].iov_base); + return rc; + } + +-- +2.25.1 + + diff --git a/patches.suse/cifs-use-mod_delayed_work-for-server-reconnect-if-al.patch b/patches.suse/cifs-use-mod_delayed_work-for-server-reconnect-if-al.patch new file mode 100644 index 0000000..48169bb --- /dev/null +++ b/patches.suse/cifs-use-mod_delayed_work-for-server-reconnect-if-al.patch @@ -0,0 +1,44 @@ +From 113dd2ced64509668c786615f47d870e2f4c1d3c Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Mon, 24 Feb 2020 14:14:59 +0100 +Subject: [PATCH] cifs: use mod_delayed_work() for &server->reconnect if + already queued +Patch-mainline: Not yet, in for-next branch +References: bsc#1144333 + +mod_delayed_work() is safer than queue_delayed_work() if there's a +chance that the work is already in the queue. + +Signed-off-by: Stefan Metzmacher +Reviewed-by: Pavel Shilovsky +Signed-off-by: Steve French +Acked-by: Paulo Alcantara +--- + fs/cifs/smb2pdu.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c +index 8c23c10cafd2..0f4cc8606cbc 100644 +--- a/fs/cifs/smb2pdu.c ++++ b/fs/cifs/smb2pdu.c +@@ -389,7 +389,7 @@ smb2_reconnect(__le16 smb2_command, struct cifs_tcon *tcon) + } + + if (smb2_command != SMB2_INTERNAL_CMD) +- queue_delayed_work(cifsiod_wq, &server->reconnect, 0); ++ mod_delayed_work(cifsiod_wq, &server->reconnect, 0); + + atomic_inc(&tconInfoReconnectCount); + out: +@@ -3570,7 +3570,7 @@ SMB2_echo(struct TCP_Server_Info *server) + + if (server->tcpStatus == CifsNeedNegotiate) { + /* No need to send echo on newly established connections */ +- queue_delayed_work(cifsiod_wq, &server->reconnect, 0); ++ mod_delayed_work(cifsiod_wq, &server->reconnect, 0); + return rc; + } + +-- +2.25.1 + diff --git a/patches.suse/clk-imx-align-imx-sc-clock-msg-structs-to-4.patch b/patches.suse/clk-imx-align-imx-sc-clock-msg-structs-to-4.patch new file mode 100644 index 0000000..539e733 --- /dev/null +++ b/patches.suse/clk-imx-align-imx-sc-clock-msg-structs-to-4.patch @@ -0,0 +1,54 @@ +From a0ae04a25650fd51b7106e742d27333e502173c6 Mon Sep 17 00:00:00 2001 +From: Leonard Crestez +Date: Thu, 20 Feb 2020 18:29:32 +0200 +Subject: clk: imx: Align imx sc clock msg structs to 4 +Git-commit: a0ae04a25650fd51b7106e742d27333e502173c6 +Patch-mainline: v5.6 +References: bsc#1111666 git-fixes + +The imx SC api strongly assumes that messages are composed out of +4-bytes words but some of our message structs have odd sizeofs. + +This produces many oopses with CONFIG_KASAN=y. + +Fix by marking with __aligned(4). + +Fixes: fe37b4820417 ("clk: imx: add scu clock common part") +Signed-off-by: Leonard Crestez +Link: https://lkml.kernel.org/r/10e97a04980d933b2cfecb6b124bf9046b6e4f16.1582216144.git.leonard.crestez@nxp.com +Signed-off-by: Stephen Boyd +Acked-by: Nicolas Saenz Julienne +Acked-by: Takashi Iwai +--- + drivers/clk/imx/clk-scu.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/drivers/clk/imx/clk-scu.c b/drivers/clk/imx/clk-scu.c +index fbef740704d0..3c5c42d8833e 100644 +--- a/drivers/clk/imx/clk-scu.c ++++ b/drivers/clk/imx/clk-scu.c +@@ -43,12 +43,12 @@ struct imx_sc_msg_req_set_clock_rate { + __le32 rate; + __le16 resource; + u8 clk; +-} __packed; ++} __packed __aligned(4); + + struct req_get_clock_rate { + __le16 resource; + u8 clk; +-} __packed; ++} __packed __aligned(4); + + struct resp_get_clock_rate { + __le32 rate; +@@ -121,7 +121,7 @@ struct imx_sc_msg_req_clock_enable { + u8 clk; + u8 enable; + u8 autog; +-} __packed; ++} __packed __aligned(4); + + static inline struct clk_scu *to_clk_scu(struct clk_hw *hw) + { + diff --git a/patches.suse/cls_rsvp-fix-rsvp_policy.patch b/patches.suse/cls_rsvp-fix-rsvp_policy.patch new file mode 100644 index 0000000..6d932a7 --- /dev/null +++ b/patches.suse/cls_rsvp-fix-rsvp_policy.patch @@ -0,0 +1,99 @@ +From: Eric Dumazet +Date: Fri, 31 Jan 2020 15:27:04 -0800 +Subject: cls_rsvp: fix rsvp_policy +Git-commit: cb3c0e6bdf64d0d124e94ce43cbe4ccbb9b37f51 +Patch-mainline: 5.6-rc1 +References: networking-stable-20_02_05 + +NLA_BINARY can be confusing, since .len value represents +the max size of the blob. + +cls_rsvp really wants user space to provide long enough data +for TCA_RSVP_DST and TCA_RSVP_SRC attributes. + +BUG: KMSAN: uninit-value in rsvp_get net/sched/cls_rsvp.h:258 [inline] +BUG: KMSAN: uninit-value in gen_handle net/sched/cls_rsvp.h:402 [inline] +BUG: KMSAN: uninit-value in rsvp_change+0x1ae9/0x4220 net/sched/cls_rsvp.h:572 +CPU: 1 PID: 13228 Comm: syz-executor.1 Not tainted 5.5.0-rc5-syzkaller #0 +Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011 +Call Trace: + __dump_stack lib/dump_stack.c:77 [inline] + dump_stack+0x1c9/0x220 lib/dump_stack.c:118 + kmsan_report+0xf7/0x1e0 mm/kmsan/kmsan_report.c:118 + __msan_warning+0x58/0xa0 mm/kmsan/kmsan_instr.c:215 + rsvp_get net/sched/cls_rsvp.h:258 [inline] + gen_handle net/sched/cls_rsvp.h:402 [inline] + rsvp_change+0x1ae9/0x4220 net/sched/cls_rsvp.h:572 + tc_new_tfilter+0x31fe/0x5010 net/sched/cls_api.c:2104 + rtnetlink_rcv_msg+0xcb7/0x1570 net/core/rtnetlink.c:5415 + netlink_rcv_skb+0x451/0x650 net/netlink/af_netlink.c:2477 + rtnetlink_rcv+0x50/0x60 net/core/rtnetlink.c:5442 + netlink_unicast_kernel net/netlink/af_netlink.c:1302 [inline] + netlink_unicast+0xf9e/0x1100 net/netlink/af_netlink.c:1328 + netlink_sendmsg+0x1248/0x14d0 net/netlink/af_netlink.c:1917 + sock_sendmsg_nosec net/socket.c:639 [inline] + sock_sendmsg net/socket.c:659 [inline] + ____sys_sendmsg+0x12b6/0x1350 net/socket.c:2330 + ___sys_sendmsg net/socket.c:2384 [inline] + __sys_sendmsg+0x451/0x5f0 net/socket.c:2417 + __do_sys_sendmsg net/socket.c:2426 [inline] + __se_sys_sendmsg+0x97/0xb0 net/socket.c:2424 + __x64_sys_sendmsg+0x4a/0x70 net/socket.c:2424 + do_syscall_64+0xb8/0x160 arch/x86/entry/common.c:296 + entry_SYSCALL_64_after_hwframe+0x44/0xa9 +RIP: 0033:0x45b349 +Code: ad b6 fb ff c3 66 2e 0f 1f 84 00 00 00 00 00 66 90 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 0f 83 7b b6 fb ff c3 66 2e 0f 1f 84 00 00 00 00 +RSP: 002b:00007f269d43dc78 EFLAGS: 00000246 ORIG_RAX: 000000000000002e +RAX: ffffffffffffffda RBX: 00007f269d43e6d4 RCX: 000000000045b349 +RDX: 0000000000000000 RSI: 00000000200001c0 RDI: 0000000000000003 +RBP: 000000000075bfc8 R08: 0000000000000000 R09: 0000000000000000 +R10: 0000000000000000 R11: 0000000000000246 R12: 00000000ffffffff +R13: 00000000000009c2 R14: 00000000004cb338 R15: 000000000075bfd4 + +Uninit was created at: + kmsan_save_stack_with_flags mm/kmsan/kmsan.c:144 [inline] + kmsan_internal_poison_shadow+0x66/0xd0 mm/kmsan/kmsan.c:127 + kmsan_slab_alloc+0x8a/0xe0 mm/kmsan/kmsan_hooks.c:82 + slab_alloc_node mm/slub.c:2774 [inline] + __kmalloc_node_track_caller+0xb40/0x1200 mm/slub.c:4382 + __kmalloc_reserve net/core/skbuff.c:141 [inline] + __alloc_skb+0x2fd/0xac0 net/core/skbuff.c:209 + alloc_skb include/linux/skbuff.h:1049 [inline] + netlink_alloc_large_skb net/netlink/af_netlink.c:1174 [inline] + netlink_sendmsg+0x7d3/0x14d0 net/netlink/af_netlink.c:1892 + sock_sendmsg_nosec net/socket.c:639 [inline] + sock_sendmsg net/socket.c:659 [inline] + ____sys_sendmsg+0x12b6/0x1350 net/socket.c:2330 + ___sys_sendmsg net/socket.c:2384 [inline] + __sys_sendmsg+0x451/0x5f0 net/socket.c:2417 + __do_sys_sendmsg net/socket.c:2426 [inline] + __se_sys_sendmsg+0x97/0xb0 net/socket.c:2424 + __x64_sys_sendmsg+0x4a/0x70 net/socket.c:2424 + do_syscall_64+0xb8/0x160 arch/x86/entry/common.c:296 + entry_SYSCALL_64_after_hwframe+0x44/0xa9 + +Fixes: 6fa8c0144b77 ("[NET_SCHED]: Use nla_policy for attribute validation in classifiers") +Signed-off-by: Eric Dumazet +Reported-by: syzbot +Acked-by: Cong Wang +Signed-off-by: Jakub Kicinski +Signed-off-by: Jiri Slaby +--- + net/sched/cls_rsvp.h | 6 ++---- + 1 file changed, 2 insertions(+), 4 deletions(-) + +--- a/net/sched/cls_rsvp.h ++++ b/net/sched/cls_rsvp.h +@@ -453,10 +453,8 @@ static u32 gen_tunnel(struct rsvp_head * + + static const struct nla_policy rsvp_policy[TCA_RSVP_MAX + 1] = { + [TCA_RSVP_CLASSID] = { .type = NLA_U32 }, +- [TCA_RSVP_DST] = { .type = NLA_BINARY, +- .len = RSVP_DST_LEN * sizeof(u32) }, +- [TCA_RSVP_SRC] = { .type = NLA_BINARY, +- .len = RSVP_DST_LEN * sizeof(u32) }, ++ [TCA_RSVP_DST] = { .len = RSVP_DST_LEN * sizeof(u32) }, ++ [TCA_RSVP_SRC] = { .len = RSVP_DST_LEN * sizeof(u32) }, + [TCA_RSVP_PINFO] = { .len = sizeof(struct tc_rsvp_pinfo) }, + }; + diff --git a/patches.suse/configfs-Fix-bool-initialization-comparison.patch b/patches.suse/configfs-Fix-bool-initialization-comparison.patch new file mode 100644 index 0000000..6ebe6a6 --- /dev/null +++ b/patches.suse/configfs-Fix-bool-initialization-comparison.patch @@ -0,0 +1,68 @@ +From 3f6928c347707a65cee10a9f54b85ad5fb078b3f Mon Sep 17 00:00:00 2001 +From: Thomas Meyer +Date: Sat, 7 Oct 2017 16:02:21 +0200 +Subject: [PATCH] configfs: Fix bool initialization/comparison +Git-commit: 3f6928c347707a65cee10a9f54b85ad5fb078b3f +Patch-mainline: v4.15-rc1 +References: bsc#1051510 + +Bool initializations should use true and false. Bool tests don't need +comparisons. + +Signed-off-by: Thomas Meyer +Signed-off-by: Christoph Hellwig +Acked-by: Takashi Iwai + +--- + fs/configfs/file.c | 12 ++++++------ + 1 file changed, 6 insertions(+), 6 deletions(-) + +diff --git a/fs/configfs/file.c b/fs/configfs/file.c +index 39da1103d341..62580dba3552 100644 +--- a/fs/configfs/file.c ++++ b/fs/configfs/file.c +@@ -166,7 +166,7 @@ configfs_read_bin_file(struct file *file, char __user *buf, + retval = -ETXTBSY; + goto out; + } +- buffer->read_in_progress = 1; ++ buffer->read_in_progress = true; + + if (buffer->needs_read_fill) { + /* perform first read with buf == NULL to get extent */ +@@ -325,7 +325,7 @@ configfs_write_bin_file(struct file *file, const char __user *buf, + len = -ETXTBSY; + goto out; + } +- buffer->write_in_progress = 1; ++ buffer->write_in_progress = true; + + /* buffer grows? */ + if (*ppos + count > buffer->bin_buffer_size) { +@@ -429,8 +429,8 @@ static int check_perm(struct inode * inode, struct file * file, int type) + } + mutex_init(&buffer->mutex); + buffer->needs_read_fill = 1; +- buffer->read_in_progress = 0; +- buffer->write_in_progress = 0; ++ buffer->read_in_progress = false; ++ buffer->write_in_progress = false; + buffer->ops = ops; + file->private_data = buffer; + goto Done; +@@ -488,10 +488,10 @@ static int configfs_release_bin_file(struct inode *inode, struct file *filp) + ssize_t len = 0; + int ret; + +- buffer->read_in_progress = 0; ++ buffer->read_in_progress = false; + + if (buffer->write_in_progress) { +- buffer->write_in_progress = 0; ++ buffer->write_in_progress = false; + + len = bin_attr->write(item, buffer->bin_buffer, + buffer->bin_buffer_size); +-- +2.16.4 + diff --git a/patches.suse/core-Don-t-skip-generic-XDP-program-execution-for-cl.patch b/patches.suse/core-Don-t-skip-generic-XDP-program-execution-for-cl.patch new file mode 100644 index 0000000..8333067 --- /dev/null +++ b/patches.suse/core-Don-t-skip-generic-XDP-program-execution-for-cl.patch @@ -0,0 +1,137 @@ +From: =?UTF-8?q?Toke=20H=C3=B8iland-J=C3=B8rgensen?= +Date: Mon, 10 Feb 2020 17:10:46 +0100 +Subject: core: Don't skip generic XDP program execution for cloned SKBs +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit +Patch-mainline: v5.6-rc2 +Git-commit: ad1e03b2b3d4430baaa109b77bc308dc73050de3 +References: bsc#1109837 + +The current generic XDP handler skips execution of XDP programs entirely if +an SKB is marked as cloned. This leads to some surprising behaviour, as +packets can end up being cloned in various ways, which will make an XDP +program not see all the traffic on an interface. + +This was discovered by a simple test case where an XDP program that always +returns XDP_DROP is installed on a veth device. When combining this with +the Scapy packet sniffer (which uses an AF_PACKET) socket on the sending +side, SKBs reliably end up in the cloned state, causing them to be passed +through to the receiving interface instead of being dropped. A minimal +reproducer script for this is included below. + +This patch fixed the issue by simply triggering the existing linearisation +code for cloned SKBs instead of skipping the XDP program execution. This +behaviour is in line with the behaviour of the native XDP implementation +for the veth driver, which will reallocate and copy the SKB data if the SKB +is marked as shared. + +Reproducer Python script (requires BCC and Scapy): + +from scapy.all import TCP, IP, Ether, sendp, sniff, AsyncSniffer, Raw, UDP +from bcc import BPF +import time, sys, subprocess, shlex + +SKB_MODE = (1 << 1) +DRV_MODE = (1 << 2) +PYTHON=sys.executable + +def client(): + time.sleep(2) + # Sniffing on the sender causes skb_cloned() to be set + s = AsyncSniffer() + s.start() + + for p in range(10): + sendp(Ether(dst="aa:aa:aa:aa:aa:aa", src="cc:cc:cc:cc:cc:cc")/IP()/UDP()/Raw("Test"), + verbose=False) + time.sleep(0.1) + + s.stop() + return 0 + +def server(mode): + prog = BPF(text="int dummy_drop(struct xdp_md *ctx) {return XDP_DROP;}") + func = prog.load_func("dummy_drop", BPF.XDP) + prog.attach_xdp("a_to_b", func, mode) + + time.sleep(1) + + s = sniff(iface="a_to_b", count=10, timeout=15) + if len(s): + print(f"Got {len(s)} packets - should have gotten 0") + return 1 + else: + print("Got no packets - as expected") + return 0 + +if len(sys.argv) < 2: + print(f"Usage: {sys.argv[0]} ") + sys.exit(1) + +if sys.argv[1] == "client": + sys.exit(client()) +elif sys.argv[1] == "server": + mode = SKB_MODE if sys.argv[2] == 'skb' else DRV_MODE + sys.exit(server(mode)) +else: + try: + mode = sys.argv[1] + if mode not in ('skb', 'drv'): + print(f"Usage: {sys.argv[0]} ") + sys.exit(1) + print(f"Running in {mode} mode") + + for cmd in [ + 'ip netns add netns_a', + 'ip netns add netns_b', + 'ip -n netns_a link add a_to_b type veth peer name b_to_a netns netns_b', + # Disable ipv6 to make sure there's no address autoconf traffic + 'ip netns exec netns_a sysctl -qw net.ipv6.conf.a_to_b.disable_ipv6=1', + 'ip netns exec netns_b sysctl -qw net.ipv6.conf.b_to_a.disable_ipv6=1', + 'ip -n netns_a link set dev a_to_b address aa:aa:aa:aa:aa:aa', + 'ip -n netns_b link set dev b_to_a address cc:cc:cc:cc:cc:cc', + 'ip -n netns_a link set dev a_to_b up', + 'ip -n netns_b link set dev b_to_a up']: + subprocess.check_call(shlex.split(cmd)) + + server = subprocess.Popen(shlex.split(f"ip netns exec netns_a {PYTHON} {sys.argv[0]} server {mode}")) + client = subprocess.Popen(shlex.split(f"ip netns exec netns_b {PYTHON} {sys.argv[0]} client")) + + client.wait() + server.wait() + sys.exit(server.returncode) + + finally: + subprocess.run(shlex.split("ip netns delete netns_a")) + subprocess.run(shlex.split("ip netns delete netns_b")) + +Fixes: d445516966dc ("net: xdp: support xdp generic on virtual devices") +Reported-by: Stepan Horacek +Suggested-by: Paolo Abeni +Signed-off-by: Toke Høiland-Jørgensen +Signed-off-by: David S. Miller +Acked-by: Thomas Bogendoerfer +--- + net/core/dev.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/net/core/dev.c ++++ b/net/core/dev.c +@@ -4260,14 +4260,14 @@ static u32 netif_receive_generic_xdp(str + /* Reinjected packets coming from act_mirred or similar should + * not get XDP generic processing. + */ +- if (skb_cloned(skb) || skb_is_tc_redirected(skb)) ++ if (skb_is_tc_redirected(skb)) + return XDP_PASS; + + /* XDP packets must be linear and must have sufficient headroom + * of XDP_PACKET_HEADROOM bytes. This is the guarantee that also + * native XDP provides, thus we need to do it here as well. + */ +- if (skb_is_nonlinear(skb) || ++ if (skb_cloned(skb) || skb_is_nonlinear(skb) || + skb_headroom(skb) < XDP_PACKET_HEADROOM) { + int hroom = XDP_PACKET_HEADROOM - skb_headroom(skb); + int troom = skb->tail + skb->data_len - skb->end; diff --git a/patches.suse/cpufreq-Register-drivers-only-after-CPU-devices-have.patch b/patches.suse/cpufreq-Register-drivers-only-after-CPU-devices-have.patch new file mode 100644 index 0000000..1d00195 --- /dev/null +++ b/patches.suse/cpufreq-Register-drivers-only-after-CPU-devices-have.patch @@ -0,0 +1,69 @@ +From 46770be0cf94149ca48be87719bda1d951066644 Mon Sep 17 00:00:00 2001 +From: Viresh Kumar +Date: Thu, 14 Nov 2019 09:06:17 +0530 +Subject: [PATCH] cpufreq: Register drivers only after CPU devices have been registered +Git-commit: 46770be0cf94149ca48be87719bda1d951066644 +Patch-mainline: v5.5-rc1 +References: bsc#1051510 + +The cpufreq core heavily depends on the availability of the struct +device for CPUs and if they aren't available at the time cpufreq driver +is registered, we will never succeed in making cpufreq work. + +This happens due to following sequence of events: + +- cpufreq_register_driver() + - subsys_interface_register() + - return 0; //successful registration of driver + +... at a later point of time + +- register_cpu(); + - device_register(); + - bus_probe_device(); + - sif->add_dev(); + - cpufreq_add_dev(); + - get_cpu_device(); //FAILS + - per_cpu(cpu_sys_devices, num) = &cpu->dev; //used by get_cpu_device() + - return 0; //CPU registered successfully + +Because the per-cpu variable cpu_sys_devices is set only after the CPU +device is regsitered, cpufreq will never be able to get it when +cpufreq_add_dev() is called. + +This patch avoids this failure by making sure device structure of at +least CPU0 is available when the cpufreq driver is registered, else +return -EPROBE_DEFER. + +Reported-by: Bjorn Andersson +Co-developed-by: Amit Kucheria +Signed-off-by: Viresh Kumar +Tested-by: Amit Kucheria +Signed-off-by: Rafael J. Wysocki +Acked-by: Takashi Iwai + +--- + drivers/cpufreq/cpufreq.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c +index 0a10cf9d0b1a..7fc1a686f2f6 100644 +--- a/drivers/cpufreq/cpufreq.c ++++ b/drivers/cpufreq/cpufreq.c +@@ -2637,6 +2637,13 @@ int cpufreq_register_driver(struct cpufreq_driver *driver_data) + if (cpufreq_disabled()) + return -ENODEV; + ++ /* ++ * The cpufreq core depends heavily on the availability of device ++ * structure, make sure they are available before proceeding further. ++ */ ++ if (!get_cpu_device(0)) ++ return -EPROBE_DEFER; ++ + if (!driver_data || !driver_data->verify || !driver_data->init || + !(driver_data->setpolicy || driver_data->target_index || + driver_data->target) || +-- +2.16.4 + diff --git a/patches.suse/cpufreq-powernv-Fix-unsafe-notifiers.patch b/patches.suse/cpufreq-powernv-Fix-unsafe-notifiers.patch new file mode 100644 index 0000000..8866cbf --- /dev/null +++ b/patches.suse/cpufreq-powernv-Fix-unsafe-notifiers.patch @@ -0,0 +1,66 @@ +From 966c08de7c2c9bcac13e2cb9e769a39582d5389f Mon Sep 17 00:00:00 2001 +From: Oliver O'Halloran +Date: Thu, 6 Feb 2020 17:26:22 +1100 +Subject: [PATCH] cpufreq: powernv: Fix unsafe notifiers + +References: bsc#1065729 +Patch-mainline: v5.7-rc1 +Git-commit: 966c08de7c2c9bcac13e2cb9e769a39582d5389f + +The PowerNV cpufreq driver registers two notifiers: one to catch +throttle messages from the OCC and one to bump the CPU frequency back +to normal before a reboot. Both require the cpufreq driver to be +registered in order to function since the notifier callbacks use +various cpufreq_*() functions. + +Right now we register both notifiers before we've initialised the +driver. This seems to work, but we should head off any protential +problems by registering the notifiers after the driver is initialised. + +Signed-off-by: Oliver O'Halloran +Reviewed-by: Gautham R. Shenoy +Signed-off-by: Michael Ellerman +Link: https://lore.kernel.org/r/20200206062622.28235-2-oohall@gmail.com +Acked-by: Michal Suchanek +--- + drivers/cpufreq/powernv-cpufreq.c | 11 +++++------ + 1 file changed, 5 insertions(+), 6 deletions(-) + +diff --git a/drivers/cpufreq/powernv-cpufreq.c b/drivers/cpufreq/powernv-cpufreq.c +index 1806b1da4366..03798c4326c6 100644 +--- a/drivers/cpufreq/powernv-cpufreq.c ++++ b/drivers/cpufreq/powernv-cpufreq.c +@@ -1114,9 +1114,6 @@ static int __init powernv_cpufreq_init(void) + if (rc) + goto out; + +- register_reboot_notifier(&powernv_cpufreq_reboot_nb); +- opal_message_notifier_register(OPAL_MSG_OCC, &powernv_cpufreq_opal_nb); +- + if (powernv_pstate_info.wof_enabled) + powernv_cpufreq_driver.boost_enabled = true; + else +@@ -1125,15 +1122,17 @@ static int __init powernv_cpufreq_init(void) + rc = cpufreq_register_driver(&powernv_cpufreq_driver); + if (rc) { + pr_info("Failed to register the cpufreq driver (%d)\n", rc); +- goto cleanup_notifiers; ++ goto cleanup; + } + + if (powernv_pstate_info.wof_enabled) + cpufreq_enable_boost_support(); + ++ register_reboot_notifier(&powernv_cpufreq_reboot_nb); ++ opal_message_notifier_register(OPAL_MSG_OCC, &powernv_cpufreq_opal_nb); ++ + return 0; +-cleanup_notifiers: +- unregister_all_notifiers(); ++cleanup: + clean_chip_info(); + out: + pr_info("Platform driver disabled. System does not support PState control\n"); +-- +2.23.0 + diff --git a/patches.suse/cpufreq-powernv-Fix-use-after-free.patch b/patches.suse/cpufreq-powernv-Fix-use-after-free.patch new file mode 100644 index 0000000..f1e1162 --- /dev/null +++ b/patches.suse/cpufreq-powernv-Fix-use-after-free.patch @@ -0,0 +1,50 @@ +From d0a72efac89d1c35ac55197895201b7b94c5e6ef Mon Sep 17 00:00:00 2001 +From: Oliver O'Halloran +Date: Thu, 6 Feb 2020 17:26:21 +1100 +Subject: [PATCH] cpufreq: powernv: Fix use-after-free + +References: bsc#1065729 +Patch-mainline: v5.7-rc1 +Git-commit: d0a72efac89d1c35ac55197895201b7b94c5e6ef + +The cpufreq driver has a use-after-free that we can hit if: + +a) There's an OCC message pending when the notifier is registered, and +b) The cpufreq driver fails to register with the core. + +When a) occurs the notifier schedules a workqueue item to handle the +message. The backing work_struct is located on chips[].throttle and +when b) happens we clean up by freeing the array. Once we get to +the (now free) queued item and the kernel crashes. + +Fixes: c5e29ea7ac14 ("cpufreq: powernv: Fix bugs in powernv_cpufreq_{init/exit}") +Cc: stable@vger.kernel.org # v4.6+ +Signed-off-by: Oliver O'Halloran +Reviewed-by: Gautham R. Shenoy +Signed-off-by: Michael Ellerman +Link: https://lore.kernel.org/r/20200206062622.28235-1-oohall@gmail.com +Acked-by: Michal Suchanek +--- + drivers/cpufreq/powernv-cpufreq.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/drivers/cpufreq/powernv-cpufreq.c b/drivers/cpufreq/powernv-cpufreq.c +index 56f4bc0d209e..1806b1da4366 100644 +--- a/drivers/cpufreq/powernv-cpufreq.c ++++ b/drivers/cpufreq/powernv-cpufreq.c +@@ -1080,6 +1080,12 @@ static int init_chip_info(void) + + static inline void clean_chip_info(void) + { ++ int i; ++ ++ /* flush any pending work items */ ++ if (chips) ++ for (i = 0; i < nr_chips; i++) ++ cancel_work_sync(&chips[i].throttle); + kfree(chips); + } + +-- +2.23.0 + diff --git a/patches.suse/cpuidle-Do-not-unset-the-driver-if-it-is-there-alrea.patch b/patches.suse/cpuidle-Do-not-unset-the-driver-if-it-is-there-alrea.patch new file mode 100644 index 0000000..f7d4b5f --- /dev/null +++ b/patches.suse/cpuidle-Do-not-unset-the-driver-if-it-is-there-alrea.patch @@ -0,0 +1,63 @@ +From 918c1fe9fbbe46fcf56837ff21f0ef96424e8b29 Mon Sep 17 00:00:00 2001 +From: Zhenzhong Duan +Date: Wed, 23 Oct 2019 09:57:14 +0800 +Subject: [PATCH] cpuidle: Do not unset the driver if it is there already +Git-commit: 918c1fe9fbbe46fcf56837ff21f0ef96424e8b29 +Patch-mainline: v5.5-rc1 +References: bsc#1051510 + +Fix __cpuidle_set_driver() to check if any of the CPUs in the mask has +a driver different from drv already and, if so, return -EBUSY before +updating any cpuidle_drivers per-CPU pointers. + +Fixes: 82467a5a885d ("cpuidle: simplify multiple driver support") +Cc: 3.11+ # 3.11+ +Signed-off-by: Zhenzhong Duan +[ rjw: Subject & changelog ] + +Signed-off-by: Rafael J. Wysocki +Acked-by: Takashi Iwai + +--- + drivers/cpuidle/driver.c | 15 +++++++-------- + 1 file changed, 7 insertions(+), 8 deletions(-) + +diff --git a/drivers/cpuidle/driver.c b/drivers/cpuidle/driver.c +index 80c1a830d991..9db154224999 100644 +--- a/drivers/cpuidle/driver.c ++++ b/drivers/cpuidle/driver.c +@@ -62,24 +62,23 @@ static inline void __cpuidle_unset_driver(struct cpuidle_driver *drv) + * __cpuidle_set_driver - set per CPU driver variables for the given driver. + * @drv: a valid pointer to a struct cpuidle_driver + * +- * For each CPU in the driver's cpumask, unset the registered driver per CPU +- * to @drv. +- * +- * Returns 0 on success, -EBUSY if the CPUs have driver(s) already. ++ * Returns 0 on success, -EBUSY if any CPU in the cpumask have a driver ++ * different from drv already. + */ + static inline int __cpuidle_set_driver(struct cpuidle_driver *drv) + { + int cpu; + + for_each_cpu(cpu, drv->cpumask) { ++ struct cpuidle_driver *old_drv; + +- if (__cpuidle_get_cpu_driver(cpu)) { +- __cpuidle_unset_driver(drv); ++ old_drv = __cpuidle_get_cpu_driver(cpu); ++ if (old_drv && old_drv != drv) + return -EBUSY; +- } ++ } + ++ for_each_cpu(cpu, drv->cpumask) + per_cpu(cpuidle_drivers, cpu) = drv; +- } + + return 0; + } +-- +2.16.4 + diff --git a/patches.suse/crypto-arm64-sha-ce-implement-export-import.patch b/patches.suse/crypto-arm64-sha-ce-implement-export-import.patch new file mode 100644 index 0000000..1df1dfe --- /dev/null +++ b/patches.suse/crypto-arm64-sha-ce-implement-export-import.patch @@ -0,0 +1,118 @@ +From d282eeeb112a00b05595a034ac4cae8532a4c2fc Mon Sep 17 00:00:00 2001 +From: Corentin Labbe +Date: Mon, 24 Feb 2020 14:47:41 +0000 +Subject: [PATCH] crypto: arm64/sha-ce - implement export/import +Git-commit: d282eeeb112a00b05595a034ac4cae8532a4c2fc +Patch-mainline: v5.7-rc1 +References: bsc#1051510 + +When an ahash algorithm fallback to another ahash and that fallback is +shaXXX-CE, doing export/import lead to error like this: +Alg: ahash: sha1-sun8i-ce export() overran state buffer on test vector 0, cfg=\"import/export\" + +This is due to the descsize of shaxxx-ce being larger than struct shaxxx_state +off by an u32. +For fixing this, let's implement export/import which rip the finalize +variant instead of using generic export/import. + +Fixes: 6ba6c74dfc6b ("arm64/crypto: SHA-224/SHA-256 using ARMv8 Crypto Extensions") +Fixes: 2c98833a42cd ("arm64/crypto: SHA-1 using ARMv8 Crypto Extensions") + +Signed-off-by: Corentin Labbe +Reviewed-by: Ard Biesheuvel +Signed-off-by: Herbert Xu +Acked-by: Takashi Iwai + +--- + arch/arm64/crypto/sha1-ce-glue.c | 20 ++++++++++++++++++++ + arch/arm64/crypto/sha2-ce-glue.c | 23 +++++++++++++++++++++++ + 2 files changed, 43 insertions(+) + +diff --git a/arch/arm64/crypto/sha1-ce-glue.c b/arch/arm64/crypto/sha1-ce-glue.c +index 63c875d3314b..565ef604ca04 100644 +--- a/arch/arm64/crypto/sha1-ce-glue.c ++++ b/arch/arm64/crypto/sha1-ce-glue.c +@@ -91,12 +91,32 @@ static int sha1_ce_final(struct shash_desc *desc, u8 *out) + return sha1_base_finish(desc, out); + } + ++static int sha1_ce_export(struct shash_desc *desc, void *out) ++{ ++ struct sha1_ce_state *sctx = shash_desc_ctx(desc); ++ ++ memcpy(out, &sctx->sst, sizeof(struct sha1_state)); ++ return 0; ++} ++ ++static int sha1_ce_import(struct shash_desc *desc, const void *in) ++{ ++ struct sha1_ce_state *sctx = shash_desc_ctx(desc); ++ ++ memcpy(&sctx->sst, in, sizeof(struct sha1_state)); ++ sctx->finalize = 0; ++ return 0; ++} ++ + static struct shash_alg alg = { + .init = sha1_base_init, + .update = sha1_ce_update, + .final = sha1_ce_final, + .finup = sha1_ce_finup, ++ .import = sha1_ce_import, ++ .export = sha1_ce_export, + .descsize = sizeof(struct sha1_ce_state), ++ .statesize = sizeof(struct sha1_state), + .digestsize = SHA1_DIGEST_SIZE, + .base = { + .cra_name = "sha1", +diff --git a/arch/arm64/crypto/sha2-ce-glue.c b/arch/arm64/crypto/sha2-ce-glue.c +index a8e67bafba3d..9450d19b9e6e 100644 +--- a/arch/arm64/crypto/sha2-ce-glue.c ++++ b/arch/arm64/crypto/sha2-ce-glue.c +@@ -109,12 +109,32 @@ static int sha256_ce_final(struct shash_desc *desc, u8 *out) + return sha256_base_finish(desc, out); + } + ++static int sha256_ce_export(struct shash_desc *desc, void *out) ++{ ++ struct sha256_ce_state *sctx = shash_desc_ctx(desc); ++ ++ memcpy(out, &sctx->sst, sizeof(struct sha256_state)); ++ return 0; ++} ++ ++static int sha256_ce_import(struct shash_desc *desc, const void *in) ++{ ++ struct sha256_ce_state *sctx = shash_desc_ctx(desc); ++ ++ memcpy(&sctx->sst, in, sizeof(struct sha256_state)); ++ sctx->finalize = 0; ++ return 0; ++} ++ + static struct shash_alg algs[] = { { + .init = sha224_base_init, + .update = sha256_ce_update, + .final = sha256_ce_final, + .finup = sha256_ce_finup, ++ .export = sha256_ce_export, ++ .import = sha256_ce_import, + .descsize = sizeof(struct sha256_ce_state), ++ .statesize = sizeof(struct sha256_state), + .digestsize = SHA224_DIGEST_SIZE, + .base = { + .cra_name = "sha224", +@@ -128,7 +148,10 @@ static struct shash_alg algs[] = { { + .update = sha256_ce_update, + .final = sha256_ce_final, + .finup = sha256_ce_finup, ++ .export = sha256_ce_export, ++ .import = sha256_ce_import, + .descsize = sizeof(struct sha256_ce_state), ++ .statesize = sizeof(struct sha256_state), + .digestsize = SHA256_DIGEST_SIZE, + .base = { + .cra_name = "sha256", +-- +2.16.4 + diff --git a/patches.suse/crypto-mxs-dcp-fix-scatterlist-linearization-for-has.patch b/patches.suse/crypto-mxs-dcp-fix-scatterlist-linearization-for-has.patch new file mode 100644 index 0000000..9684fad --- /dev/null +++ b/patches.suse/crypto-mxs-dcp-fix-scatterlist-linearization-for-has.patch @@ -0,0 +1,119 @@ +From fa03481b6e2e82355c46644147b614f18c7a8161 Mon Sep 17 00:00:00 2001 +From: Rosioru Dragos +Date: Tue, 25 Feb 2020 17:05:52 +0200 +Subject: [PATCH] crypto: mxs-dcp - fix scatterlist linearization for hash +Mime-version: 1.0 +Content-type: text/plain; charset=UTF-8 +Content-transfer-encoding: 8bit +Git-commit: fa03481b6e2e82355c46644147b614f18c7a8161 +Patch-mainline: v5.7-rc1 +References: bsc#1051510 + +The incorrect traversal of the scatterlist, during the linearization phase +lead to computing the hash value of the wrong input buffer. +New implementation uses scatterwalk_map_and_copy() +to address this issue. + +Cc: +Fixes: 15b59e7c3733 ("crypto: mxs - Add Freescale MXS DCP driver") +Signed-off-by: Rosioru Dragos +Reviewed-by: Horia Geantă +Signed-off-by: Herbert Xu +Acked-by: Takashi Iwai + +--- + drivers/crypto/mxs-dcp.c | 58 +++++++++++++++++++++++------------------------- + 1 file changed, 28 insertions(+), 30 deletions(-) + +diff --git a/drivers/crypto/mxs-dcp.c b/drivers/crypto/mxs-dcp.c +index 435ac1c83df9..d84530293036 100644 +--- a/drivers/crypto/mxs-dcp.c ++++ b/drivers/crypto/mxs-dcp.c +@@ -20,6 +20,7 @@ + #include + #include + #include ++#include + + #define DCP_MAX_CHANS 4 + #define DCP_BUF_SZ PAGE_SIZE +@@ -611,49 +612,46 @@ static int dcp_sha_req_to_buf(struct crypto_async_request *arq) + struct dcp_async_ctx *actx = crypto_ahash_ctx(tfm); + struct dcp_sha_req_ctx *rctx = ahash_request_ctx(req); + struct hash_alg_common *halg = crypto_hash_alg_common(tfm); +- const int nents = sg_nents(req->src); + + uint8_t *in_buf = sdcp->coh->sha_in_buf; + uint8_t *out_buf = sdcp->coh->sha_out_buf; + +- uint8_t *src_buf; +- + struct scatterlist *src; + +- unsigned int i, len, clen; ++ unsigned int i, len, clen, oft = 0; + int ret; + + int fin = rctx->fini; + if (fin) + rctx->fini = 0; + +- for_each_sg(req->src, src, nents, i) { +- src_buf = sg_virt(src); +- len = sg_dma_len(src); +- +- do { +- if (actx->fill + len > DCP_BUF_SZ) +- clen = DCP_BUF_SZ - actx->fill; +- else +- clen = len; +- +- memcpy(in_buf + actx->fill, src_buf, clen); +- len -= clen; +- src_buf += clen; +- actx->fill += clen; ++ src = req->src; ++ len = req->nbytes; + +- /* +- * If we filled the buffer and still have some +- * more data, submit the buffer. +- */ +- if (len && actx->fill == DCP_BUF_SZ) { +- ret = mxs_dcp_run_sha(req); +- if (ret) +- return ret; +- actx->fill = 0; +- rctx->init = 0; +- } +- } while (len); ++ while (len) { ++ if (actx->fill + len > DCP_BUF_SZ) ++ clen = DCP_BUF_SZ - actx->fill; ++ else ++ clen = len; ++ ++ scatterwalk_map_and_copy(in_buf + actx->fill, src, oft, clen, ++ 0); ++ ++ len -= clen; ++ oft += clen; ++ actx->fill += clen; ++ ++ /* ++ * If we filled the buffer and still have some ++ * more data, submit the buffer. ++ */ ++ if (len && actx->fill == DCP_BUF_SZ) { ++ ret = mxs_dcp_run_sha(req); ++ if (ret) ++ return ret; ++ actx->fill = 0; ++ rctx->init = 0; ++ } + } + + if (fin) { +-- +2.16.4 + diff --git a/patches.suse/crypto-tcrypt-fix-printed-skcipher-a-sync-mode.patch b/patches.suse/crypto-tcrypt-fix-printed-skcipher-a-sync-mode.patch new file mode 100644 index 0000000..85b6a5b --- /dev/null +++ b/patches.suse/crypto-tcrypt-fix-printed-skcipher-a-sync-mode.patch @@ -0,0 +1,46 @@ +From 8e3b7fd7ea554ccb1bdc596bfbcdaf56f7ab017c Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Horia=20Geant=C4=83?= +Date: Wed, 5 Feb 2020 12:19:58 +0200 +Subject: [PATCH] crypto: tcrypt - fix printed skcipher [a]sync mode +Mime-version: 1.0 +Content-type: text/plain; charset=UTF-8 +Content-transfer-encoding: 8bit +Git-commit: 8e3b7fd7ea554ccb1bdc596bfbcdaf56f7ab017c +Patch-mainline: v5.7-rc1 +References: bsc#1051510 + +When running tcrypt skcipher speed tests, logs contain things like: +testing speed of async ecb(des3_ede) (ecb(des3_ede-generic)) encryption +Or: +testing speed of async ecb(aes) (ecb(aes-ce)) encryption + +The algorithm implementations are sync, not async. +Fix this inaccuracy. + +Fixes: 7166e589da5b6 ("crypto: tcrypt - Use skcipher") +Signed-off-by: Horia Geantă +Signed-off-by: Herbert Xu +Acked-by: Takashi Iwai + +--- + crypto/tcrypt.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/crypto/tcrypt.c b/crypto/tcrypt.c +index f42f486e90e8..ba0b7702f2e9 100644 +--- a/crypto/tcrypt.c ++++ b/crypto/tcrypt.c +@@ -1514,8 +1514,8 @@ static void test_skcipher_speed(const char *algo, int enc, unsigned int secs, + return; + } + +- pr_info("\ntesting speed of async %s (%s) %s\n", algo, +- get_driver_name(crypto_skcipher, tfm), e); ++ pr_info("\ntesting speed of %s %s (%s) %s\n", async ? "async" : "sync", ++ algo, get_driver_name(crypto_skcipher, tfm), e); + + req = skcipher_request_alloc(tfm, GFP_KERNEL); + if (!req) { +-- +2.16.4 + diff --git a/patches.suse/debugfs-call-debugfs_real_fops-only-after-debugfs_fi.patch b/patches.suse/debugfs-call-debugfs_real_fops-only-after-debugfs_fi.patch new file mode 100644 index 0000000..242ffca --- /dev/null +++ b/patches.suse/debugfs-call-debugfs_real_fops-only-after-debugfs_fi.patch @@ -0,0 +1,62 @@ +From: Nicolai Stange +Date: Tue, 31 Oct 2017 00:15:53 +0100 +Subject: debugfs: call debugfs_real_fops() only after debugfs_file_get() +Patch-mainline: v4.15-rc1 +Git-commit: 154b9d7512ae012aca7b4e90af67a72419ad1941 +References: bsc#1159198 + +The current implementation of debugfs_real_fops() relies on a +debugfs_fsdata instance to be installed at ->d_fsdata. + +With future patches introducing lazy allocation of these, this requirement +will be guaranteed to be fullfilled only inbetween a +debugfs_file_get()/debugfs_file_put() pair. + +The full proxies' fops implemented by debugfs happen to be the only +offenders. Fix them up by moving their debugfs_real_fops() calls past those +to debugfs_file_get(). + +full_proxy_release() is special as it doesn't invoke debugfs_file_get() at +all. Leave it alone for now. + +Signed-off-by: Nicolai Stange +Signed-off-by: Greg Kroah-Hartman +Acked-by: Nicolai Stange +--- + fs/debugfs/file.c | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +--- a/fs/debugfs/file.c ++++ b/fs/debugfs/file.c +@@ -144,13 +144,13 @@ const struct file_operations debugfs_ope + static ret_type full_proxy_ ## name(proto) \ + { \ + struct dentry *dentry = F_DENTRY(filp); \ +- const struct file_operations *real_fops = \ +- debugfs_real_fops(filp); \ ++ const struct file_operations *real_fops; \ + ret_type r; \ + \ + r = debugfs_file_get(dentry); \ + if (unlikely(r)) \ + return r; \ ++ real_fops = debugfs_real_fops(filp); \ + r = real_fops->name(args); \ + debugfs_file_put(dentry); \ + return r; \ +@@ -177,13 +177,14 @@ FULL_PROXY_FUNC(unlocked_ioctl, long, fi + static unsigned int full_proxy_poll(struct file *filp, + struct poll_table_struct *wait) + { +- const struct file_operations *real_fops = debugfs_real_fops(filp); + struct dentry *dentry = F_DENTRY(filp); + unsigned int r = 0; ++ const struct file_operations *real_fops; + + if (debugfs_file_get(dentry)) + return POLLHUP; + ++ real_fops = debugfs_real_fops(filp); + r = real_fops->poll(filp, wait); + debugfs_file_put(dentry); + return r; diff --git a/patches.suse/debugfs-debugfs_use_start-finish-do-not-exist-anymor.patch b/patches.suse/debugfs-debugfs_use_start-finish-do-not-exist-anymor.patch new file mode 100644 index 0000000..e5003ff --- /dev/null +++ b/patches.suse/debugfs-debugfs_use_start-finish-do-not-exist-anymor.patch @@ -0,0 +1,32 @@ +From: Sergey Senozhatsky +Date: Sun, 30 Dec 2018 12:46:52 +0900 +Subject: debugfs: debugfs_use_start/finish do not exist anymore +Patch-mainline: v5.1-rc1 +Git-commit: 0eeb27311f3a06b39ed51027260fb46c8b04357c +References: bsc#1159198 + +debugfs_use_file_start() and debugfs_use_file_finish() do not exist +since commit c9afbec27089 ("debugfs: purge obsolete SRCU based removal +protection"); tweak debugfs_create_file_unsafe() comment. + +Signed-off-by: Sergey Senozhatsky +Reviewed-by: Rafael J. Wysocki +Signed-off-by: Greg Kroah-Hartman +Acked-by: Nicolai Stange +--- + fs/debugfs/inode.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/fs/debugfs/inode.c ++++ b/fs/debugfs/inode.c +@@ -431,8 +431,8 @@ EXPORT_SYMBOL_GPL(debugfs_create_file); + * debugfs core. + * + * It is your responsibility to protect your struct file_operation +- * methods against file removals by means of debugfs_use_file_start() +- * and debugfs_use_file_finish(). ->open() is still protected by ++ * methods against file removals by means of debugfs_file_get() ++ * and debugfs_file_put(). ->open() is still protected by + * debugfs though. + * + * Any struct file_operations defined by means of diff --git a/patches.suse/debugfs-defer-debugfs_fsdata-allocation-to-first-usa.patch b/patches.suse/debugfs-defer-debugfs_fsdata-allocation-to-first-usa.patch new file mode 100644 index 0000000..3a0a0de --- /dev/null +++ b/patches.suse/debugfs-defer-debugfs_fsdata-allocation-to-first-usa.patch @@ -0,0 +1,233 @@ +From: Nicolai Stange +Date: Tue, 31 Oct 2017 00:15:54 +0100 +Subject: debugfs: defer debugfs_fsdata allocation to first usage +Patch-mainline: v4.15-rc1 +Git-commit: 7d39bc50c47b3f8ed0e1a9d671ecb9ec02f10a2d +References: bsc#1159198 + +Currently, __debugfs_create_file allocates one struct debugfs_fsdata +instance for every file created. However, there are potentially many +debugfs file around, most of which are never touched by userspace. + +Thus, defer the allocations to the first usage, i.e. to the first +debugfs_file_get(). + +A dentry's ->d_fsdata starts out to point to the "real", user provided +fops. After a debugfs_fsdata instance has been allocated (and the real +fops pointer has been moved over into its ->real_fops member), +->d_fsdata is changed to point to it from then on. The two cases are +distinguished by setting BIT(0) for the real fops case. + +struct debugfs_fsdata's foremost purpose is to track active users and to +make debugfs_remove() block until they are done. Since no debugfs_fsdata +instance means no active users, make debugfs_remove() return immediately +in this case. + +Take care of possible races between debugfs_file_get() and +debugfs_remove(): either debugfs_remove() must see a debugfs_fsdata +instance and thus wait for possible active users or debugfs_file_get() must +see a dead dentry and return immediately. + +Make a dentry's ->d_release(), i.e. debugfs_release_dentry(), check whether +->d_fsdata is actually a debugfs_fsdata instance before kfree()ing it. + +Similarly, make debugfs_real_fops() check whether ->d_fsdata is actually +a debugfs_fsdata instance before returning it, otherwise emit a warning. + +The set of possible error codes returned from debugfs_file_get() has grown +from -EIO to -EIO and -ENOMEM. Make open_proxy_open() and full_proxy_open() +pass the -ENOMEM onwards to their callers. + +Signed-off-by: Nicolai Stange +Signed-off-by: Greg Kroah-Hartman +Acked-by: Nicolai Stange +--- + fs/debugfs/file.c | 55 +++++++++++++++++++++++++++++++++++++++++--------- + fs/debugfs/inode.c | 36 +++++++++++++++++--------------- + fs/debugfs/internal.h | 8 +++++++ + 3 files changed, 73 insertions(+), 26 deletions(-) + +--- a/fs/debugfs/file.c ++++ b/fs/debugfs/file.c +@@ -53,6 +53,15 @@ const struct file_operations *debugfs_re + { + struct debugfs_fsdata *fsd = F_DENTRY(filp)->d_fsdata; + ++ if ((unsigned long)fsd & DEBUGFS_FSDATA_IS_REAL_FOPS_BIT) { ++ /* ++ * Urgh, we've been called w/o a protecting ++ * debugfs_file_get(). ++ */ ++ WARN_ON(1); ++ return NULL; ++ } ++ + return fsd->real_fops; + } + EXPORT_SYMBOL_GPL(debugfs_real_fops); +@@ -74,9 +83,35 @@ EXPORT_SYMBOL_GPL(debugfs_real_fops); + */ + int debugfs_file_get(struct dentry *dentry) + { +- struct debugfs_fsdata *fsd = dentry->d_fsdata; ++ struct debugfs_fsdata *fsd; ++ void *d_fsd; + +- /* Avoid starvation of removers. */ ++ d_fsd = READ_ONCE(dentry->d_fsdata); ++ if (!((unsigned long)d_fsd & DEBUGFS_FSDATA_IS_REAL_FOPS_BIT)) { ++ fsd = d_fsd; ++ } else { ++ fsd = kmalloc(sizeof(*fsd), GFP_KERNEL); ++ if (!fsd) ++ return -ENOMEM; ++ ++ fsd->real_fops = (void *)((unsigned long)d_fsd & ++ ~DEBUGFS_FSDATA_IS_REAL_FOPS_BIT); ++ refcount_set(&fsd->active_users, 1); ++ init_completion(&fsd->active_users_drained); ++ if (cmpxchg(&dentry->d_fsdata, d_fsd, fsd) != d_fsd) { ++ kfree(fsd); ++ fsd = READ_ONCE(dentry->d_fsdata); ++ } ++ } ++ ++ /* ++ * In case of a successful cmpxchg() above, this check is ++ * strictly necessary and must follow it, see the comment in ++ * __debugfs_remove_file(). ++ * OTOH, if the cmpxchg() hasn't been executed or wasn't ++ * successful, this serves the purpose of not starving ++ * removers. ++ */ + if (d_unlinked(dentry)) + return -EIO; + +@@ -98,7 +133,7 @@ EXPORT_SYMBOL_GPL(debugfs_file_get); + */ + void debugfs_file_put(struct dentry *dentry) + { +- struct debugfs_fsdata *fsd = dentry->d_fsdata; ++ struct debugfs_fsdata *fsd = READ_ONCE(dentry->d_fsdata); + + if (refcount_dec_and_test(&fsd->active_users)) + complete(&fsd->active_users_drained); +@@ -109,10 +144,11 @@ static int open_proxy_open(struct inode + { + struct dentry *dentry = F_DENTRY(filp); + const struct file_operations *real_fops = NULL; +- int r = 0; ++ int r; + +- if (debugfs_file_get(dentry)) +- return -ENOENT; ++ r = debugfs_file_get(dentry); ++ if (r) ++ return r == -EIO ? -ENOENT : r; + + real_fops = debugfs_real_fops(filp); + real_fops = fops_get(real_fops); +@@ -233,10 +269,11 @@ static int full_proxy_open(struct inode + struct dentry *dentry = F_DENTRY(filp); + const struct file_operations *real_fops = NULL; + struct file_operations *proxy_fops = NULL; +- int r = 0; ++ int r; + +- if (debugfs_file_get(dentry)) +- return -ENOENT; ++ r = debugfs_file_get(dentry); ++ if (r) ++ return r == -EIO ? -ENOENT : r; + + real_fops = debugfs_real_fops(filp); + real_fops = fops_get(real_fops); +--- a/fs/debugfs/inode.c ++++ b/fs/debugfs/inode.c +@@ -184,7 +184,10 @@ static const struct super_operations deb + + static void debugfs_release_dentry(struct dentry *dentry) + { +- kfree(dentry->d_fsdata); ++ void *fsd = dentry->d_fsdata; ++ ++ if (!((unsigned long)fsd & DEBUGFS_FSDATA_IS_REAL_FOPS_BIT)) ++ kfree(dentry->d_fsdata); + } + + static struct vfsmount *debugfs_automount(struct path *path) +@@ -346,35 +349,25 @@ static struct dentry *__debugfs_create_f + { + struct dentry *dentry; + struct inode *inode; +- struct debugfs_fsdata *fsd; +- +- fsd = kmalloc(sizeof(*fsd), GFP_KERNEL); +- if (!fsd) +- return NULL; + + if (!(mode & S_IFMT)) + mode |= S_IFREG; + BUG_ON(!S_ISREG(mode)); + dentry = start_creating(name, parent); + +- if (IS_ERR(dentry)) { +- kfree(fsd); ++ if (IS_ERR(dentry)) + return NULL; +- } + + inode = debugfs_get_inode(dentry->d_sb); +- if (unlikely(!inode)) { +- kfree(fsd); ++ if (unlikely(!inode)) + return failed_creating(dentry); +- } + + inode->i_mode = mode; + inode->i_private = data; + + inode->i_fop = proxy_fops; +- fsd->real_fops = real_fops; +- refcount_set(&fsd->active_users, 1); +- dentry->d_fsdata = fsd; ++ dentry->d_fsdata = (void *)((unsigned long)real_fops | ++ DEBUGFS_FSDATA_IS_REAL_FOPS_BIT); + + d_instantiate(dentry, inode); + fsnotify_create(d_inode(dentry->d_parent), dentry); +@@ -637,8 +630,17 @@ static void __debugfs_remove_file(struct + + simple_unlink(d_inode(parent), dentry); + d_delete(dentry); +- fsd = dentry->d_fsdata; +- init_completion(&fsd->active_users_drained); ++ ++ /* ++ * Paired with the closing smp_mb() implied by a successful ++ * cmpxchg() in debugfs_file_get(): either ++ * debugfs_file_get() must see a dead dentry or we must see a ++ * debugfs_fsdata instance at ->d_fsdata here (or both). ++ */ ++ smp_mb(); ++ fsd = READ_ONCE(dentry->d_fsdata); ++ if ((unsigned long)fsd & DEBUGFS_FSDATA_IS_REAL_FOPS_BIT) ++ return; + if (!refcount_dec_and_test(&fsd->active_users)) + wait_for_completion(&fsd->active_users_drained); + } +--- a/fs/debugfs/internal.h ++++ b/fs/debugfs/internal.h +@@ -25,4 +25,12 @@ struct debugfs_fsdata { + struct completion active_users_drained; + }; + ++/* ++ * A dentry's ->d_fsdata either points to the real fops or to a ++ * dynamically allocated debugfs_fsdata instance. ++ * In order to distinguish between these two cases, a real fops ++ * pointer gets its lowest bit set. ++ */ ++#define DEBUGFS_FSDATA_IS_REAL_FOPS_BIT BIT(0) ++ + #endif /* _DEBUGFS_INTERNAL_H_ */ diff --git a/patches.suse/debugfs-simplify-__debugfs_remove_file.patch b/patches.suse/debugfs-simplify-__debugfs_remove_file.patch new file mode 100644 index 0000000..d827712 --- /dev/null +++ b/patches.suse/debugfs-simplify-__debugfs_remove_file.patch @@ -0,0 +1,63 @@ +From: Amir Goldstein +Date: Sun, 26 May 2019 17:34:07 +0300 +Subject: debugfs: simplify __debugfs_remove_file() +Patch-mainline: v5.3-rc1 +Git-commit: 823e545c027795997f29ec5c255aff605cf39e85 +References: bsc#1159198 + +Move simple_unlink()+d_delete() from __debugfs_remove_file() into +caller __debugfs_remove() and rename helper for post remove file to +__debugfs_file_removed(). + +This will simplify adding fsnotify_unlink() hook. + +Cc: Greg Kroah-Hartman +Reviewed-by: Greg Kroah-Hartman +Signed-off-by: Amir Goldstein +Signed-off-by: Jan Kara +Acked-by: Nicolai Stange +--- + fs/debugfs/inode.c | 20 ++++++++------------ + 1 file changed, 8 insertions(+), 12 deletions(-) + +--- a/fs/debugfs/inode.c ++++ b/fs/debugfs/inode.c +@@ -629,13 +629,10 @@ struct dentry *debugfs_create_symlink(co + } + EXPORT_SYMBOL_GPL(debugfs_create_symlink); + +-static void __debugfs_remove_file(struct dentry *dentry, struct dentry *parent) ++static void __debugfs_file_removed(struct dentry *dentry) + { + struct debugfs_fsdata *fsd; + +- simple_unlink(d_inode(parent), dentry); +- d_delete(dentry); +- + /* + * Paired with the closing smp_mb() implied by a successful + * cmpxchg() in debugfs_file_get(): either +@@ -656,16 +653,15 @@ static int __debugfs_remove(struct dentr + + if (simple_positive(dentry)) { + dget(dentry); +- if (!d_is_reg(dentry)) { +- if (d_is_dir(dentry)) +- ret = simple_rmdir(d_inode(parent), dentry); +- else +- simple_unlink(d_inode(parent), dentry); +- if (!ret) +- d_delete(dentry); ++ if (d_is_dir(dentry)) { ++ ret = simple_rmdir(d_inode(parent), dentry); + } else { +- __debugfs_remove_file(dentry, parent); ++ simple_unlink(d_inode(parent), dentry); + } ++ if (!ret) ++ d_delete(dentry); ++ if (d_is_reg(dentry)) ++ __debugfs_file_removed(dentry); + dput(dentry); + } + return ret; diff --git a/patches.suse/devlink-report-0-after-hitting-end-in-region-read.patch b/patches.suse/devlink-report-0-after-hitting-end-in-region-read.patch new file mode 100644 index 0000000..49409bf --- /dev/null +++ b/patches.suse/devlink-report-0-after-hitting-end-in-region-read.patch @@ -0,0 +1,53 @@ +From: Jacob Keller +Date: Tue, 4 Feb 2020 15:59:50 -0800 +Subject: devlink: report 0 after hitting end in region read +Patch-mainline: v5.6-rc1 +Git-commit: d5b90e99e1d51b7b5d2b74fbc4c2db236a510913 +References: bsc#1109837 + +commit fdd41ec21e15 ("devlink: Return right error code in case of errors +for region read") modified the region read code to report errors +properly in unexpected cases. + +In the case where the start_offset and ret_offset match, it unilaterally +converted this into an error. This causes an issue for the "dump" +version of the command. In this case, the devlink region dump will +always report an invalid argument: + +000000000000ffd0 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff +000000000000ffe0 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff +devlink answers: Invalid argument +000000000000fff0 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + +This occurs because the expected flow for the dump is to return 0 after +there is no further data. + +The simplest fix would be to stop converting the error code to -EINVAL +if start_offset == ret_offset. However, avoid unnecessary work by +checking for when start_offset is larger than the region size and +returning 0 upfront. + +Fixes: fdd41ec21e15 ("devlink: Return right error code in case of errors for region read") +Signed-off-by: Jacob Keller +Acked-by: Jiri Pirko +Signed-off-by: David S. Miller +Acked-by: Thomas Bogendoerfer +--- + net/core/devlink.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +--- a/net/core/devlink.c ++++ b/net/core/devlink.c +@@ -3544,6 +3544,12 @@ static int devlink_nl_cmd_region_read_du + goto out_unlock; + } + ++ /* return 0 if there is no further data to read */ ++ if (start_offset >= region->size) { ++ err = 0; ++ goto out_unlock; ++ } ++ + hdr = genlmsg_put(skb, NETLINK_CB(cb->skb).portid, cb->nlh->nlmsg_seq, + &devlink_nl_family, NLM_F_ACK | NLM_F_MULTI, + DEVLINK_CMD_REGION_READ); diff --git a/patches.suse/dmaengine-coh901318-Fix-a-double-lock-bug-in-dma_tc_.patch b/patches.suse/dmaengine-coh901318-Fix-a-double-lock-bug-in-dma_tc_.patch new file mode 100644 index 0000000..7bd9f73 --- /dev/null +++ b/patches.suse/dmaengine-coh901318-Fix-a-double-lock-bug-in-dma_tc_.patch @@ -0,0 +1,45 @@ +From 36d5d22090d13fd3a7a8c9663a711cbe6970aac8 Mon Sep 17 00:00:00 2001 +From: Dan Carpenter +Date: Mon, 17 Feb 2020 17:40:50 +0300 +Subject: [PATCH] dmaengine: coh901318: Fix a double lock bug in dma_tc_handle() +Git-commit: 36d5d22090d13fd3a7a8c9663a711cbe6970aac8 +Patch-mainline: v5.6-rc5 +References: bsc#1051510 + +The caller is already holding the lock so this will deadlock. + +Fixes: 0b58828c923e ("DMAENGINE: COH 901 318 remove irq counting") +Signed-off-by: Dan Carpenter +Link: https://lore.kernel.org/r/20200217144050.3i4ymbytogod4ijn@kili.mountain +Signed-off-by: Vinod Koul +Acked-by: Takashi Iwai + +--- + drivers/dma/coh901318.c | 4 ---- + 1 file changed, 4 deletions(-) + +diff --git a/drivers/dma/coh901318.c b/drivers/dma/coh901318.c +index e51d836afcc7..1092d4ce723e 100644 +--- a/drivers/dma/coh901318.c ++++ b/drivers/dma/coh901318.c +@@ -1947,8 +1947,6 @@ static void dma_tc_handle(struct coh901318_chan *cohc) + return; + } + +- spin_lock(&cohc->lock); +- + /* + * When we reach this point, at least one queue item + * should have been moved over from cohc->queue to +@@ -1969,8 +1967,6 @@ static void dma_tc_handle(struct coh901318_chan *cohc) + if (coh901318_queue_start(cohc) == NULL) + cohc->busy = 0; + +- spin_unlock(&cohc->lock); +- + /* + * This tasklet will remove items from cohc->active + * and thus terminates them. +-- +2.16.4 + diff --git a/patches.suse/dmaengine-ste_dma40-fix-unneeded-variable-warning.patch b/patches.suse/dmaengine-ste_dma40-fix-unneeded-variable-warning.patch new file mode 100644 index 0000000..d8f8e96 --- /dev/null +++ b/patches.suse/dmaengine-ste_dma40-fix-unneeded-variable-warning.patch @@ -0,0 +1,56 @@ +From 5d6fb560729a5d5554e23db8d00eb57cd0021083 Mon Sep 17 00:00:00 2001 +From: Arnd Bergmann +Date: Fri, 12 Jul 2019 11:13:30 +0200 +Subject: [PATCH] dmaengine: ste_dma40: fix unneeded variable warning +Git-commit: 5d6fb560729a5d5554e23db8d00eb57cd0021083 +Patch-mainline: v5.3-rc5 +References: bsc#1051510 + +clang-9 points out that there are two variables that depending on the +configuration may only be used in an ARRAY_SIZE() expression but not +Referenced: + +drivers/dma/ste_dma40.c:145:12: error: variable 'd40_backup_regs' is not needed and will not be emitted [-Werror,-Wunneeded-internal-declaration] +static u32 d40_backup_regs[] = { + ^ +drivers/dma/ste_dma40.c:214:12: error: variable 'd40_backup_regs_chan' is not needed and will not be emitted [-Werror,-Wunneeded-internal-declaration] +static u32 d40_backup_regs_chan[] = { + +Mark these __maybe_unused to shut up the warning. + +Signed-off-by: Arnd Bergmann +Reviewed-by: Nathan Chancellor +Reviewed-by: Linus Walleij +Link: https://lore.kernel.org/r/20190712091357.744515-1-arnd@arndb.de +Signed-off-by: Vinod Koul +Acked-by: Takashi Iwai + +--- + drivers/dma/ste_dma40.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/dma/ste_dma40.c b/drivers/dma/ste_dma40.c +index 89d710899010..de8bfd9a76e9 100644 +--- a/drivers/dma/ste_dma40.c ++++ b/drivers/dma/ste_dma40.c +@@ -142,7 +142,7 @@ enum d40_events { + * when the DMA hw is powered off. + * TODO: Add save/restore of D40_DREG_GCC on dma40 v3 or later, if that works. + */ +-static u32 d40_backup_regs[] = { ++static __maybe_unused u32 d40_backup_regs[] = { + D40_DREG_LCPA, + D40_DREG_LCLA, + D40_DREG_PRMSE, +@@ -211,7 +211,7 @@ static u32 d40_backup_regs_v4b[] = { + + #define BACKUP_REGS_SZ_V4B ARRAY_SIZE(d40_backup_regs_v4b) + +-static u32 d40_backup_regs_chan[] = { ++static __maybe_unused u32 d40_backup_regs_chan[] = { + D40_CHAN_REG_SSCFG, + D40_CHAN_REG_SSELT, + D40_CHAN_REG_SSPTR, +-- +2.16.4 + diff --git a/patches.suse/driver-core-Print-device-when-resources-present-in-r.patch b/patches.suse/driver-core-Print-device-when-resources-present-in-r.patch new file mode 100644 index 0000000..929b863 --- /dev/null +++ b/patches.suse/driver-core-Print-device-when-resources-present-in-r.patch @@ -0,0 +1,45 @@ +From 7c35e699c88bd60734277b26962783c60e04b494 Mon Sep 17 00:00:00 2001 +From: Geert Uytterhoeven +Date: Fri, 6 Dec 2019 14:22:19 +0100 +Subject: [PATCH] driver core: Print device when resources present in really_probe() +Git-commit: 7c35e699c88bd60734277b26962783c60e04b494 +Patch-mainline: v5.6-rc1 +References: bsc#1051510 + +If a device already has devres items attached before probing, a warning +backtrace is printed. However, this backtrace does not reveal the +offending device, leaving the user uninformed. Furthermore, using +WARN_ON() causes systems with panic-on-warn to reboot. + +Fix this by replacing the WARN_ON() by a dev_crit() message. +Abort probing the device, to prevent doing more damage to the device's +resources. + +Signed-off-by: Geert Uytterhoeven +Link: https://lore.kernel.org/r/20191206132219.28908-1-geert+renesas@glider.be +Signed-off-by: Greg Kroah-Hartman +Acked-by: Takashi Iwai + +--- + drivers/base/dd.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/drivers/base/dd.c b/drivers/base/dd.c +index d811e60610d3..b25bcab2a26b 100644 +--- a/drivers/base/dd.c ++++ b/drivers/base/dd.c +@@ -516,7 +516,10 @@ static int really_probe(struct device *dev, struct device_driver *drv) + atomic_inc(&probe_count); + pr_debug("bus: '%s': %s: probing driver %s with device %s\n", + drv->bus->name, __func__, drv->name, dev_name(dev)); +- WARN_ON(!list_empty(&dev->devres_head)); ++ if (!list_empty(&dev->devres_head)) { ++ dev_crit(dev, "Resources present before probing\n"); ++ return -EBUSY; ++ } + + re_probe: + dev->driver = drv; +-- +2.16.4 + diff --git a/patches.suse/driver-core-platform-Prevent-resouce-overflow-from-c.patch b/patches.suse/driver-core-platform-Prevent-resouce-overflow-from-c.patch new file mode 100644 index 0000000..7621292 --- /dev/null +++ b/patches.suse/driver-core-platform-Prevent-resouce-overflow-from-c.patch @@ -0,0 +1,69 @@ +From 39cc539f90d035a293240c9443af50be55ee81b8 Mon Sep 17 00:00:00 2001 +From: Simon Schwartz +Date: Tue, 10 Dec 2019 17:41:37 -0500 +Subject: [PATCH] driver core: platform: Prevent resouce overflow from causing infinite loops +Git-commit: 39cc539f90d035a293240c9443af50be55ee81b8 +Patch-mainline: v5.6-rc1 +References: bsc#1051510 + +num_resources in the platform_device struct is declared as a u32. The +for loops that iterate over num_resources use an int as the counter, +which can cause infinite loops on architectures with smaller ints. +Change the loop counters to u32. + +Signed-off-by: Simon Schwartz +Link: https://lore.kernel.org/r/2201ce63a2a171ffd2ed14e867875316efcf71db.camel@theschwartz.xyz +Signed-off-by: Greg Kroah-Hartman +Acked-by: Takashi Iwai + +--- + drivers/base/platform.c | 10 ++++++---- + 1 file changed, 6 insertions(+), 4 deletions(-) + +--- a/drivers/base/platform.c ++++ b/drivers/base/platform.c +@@ -28,6 +28,7 @@ + #include + #include + #include ++#include + + #include "base.h" + #include "power/power.h" +@@ -68,7 +69,7 @@ void __weak arch_setup_pdev_archdata(str + struct resource *platform_get_resource(struct platform_device *dev, + unsigned int type, unsigned int num) + { +- int i; ++ u32 i; + + for (i = 0; i < dev->num_resources; i++) { + struct resource *r = &dev->resource[i]; +@@ -163,7 +164,7 @@ struct resource *platform_get_resource_b + unsigned int type, + const char *name) + { +- int i; ++ u32 i; + + for (i = 0; i < dev->num_resources; i++) { + struct resource *r = &dev->resource[i]; +@@ -360,7 +361,8 @@ EXPORT_SYMBOL_GPL(platform_device_add_pr + */ + int platform_device_add(struct platform_device *pdev) + { +- int i, ret; ++ u32 i; ++ int ret; + + if (!pdev) + return -EINVAL; +@@ -447,7 +449,7 @@ EXPORT_SYMBOL_GPL(platform_device_add); + */ + void platform_device_del(struct platform_device *pdev) + { +- int i; ++ u32 i; + + if (pdev) { + device_remove_properties(&pdev->dev); diff --git a/patches.suse/driver-core-platform-fix-u32-greater-or-equal-to-zer.patch b/patches.suse/driver-core-platform-fix-u32-greater-or-equal-to-zer.patch new file mode 100644 index 0000000..8afa703 --- /dev/null +++ b/patches.suse/driver-core-platform-fix-u32-greater-or-equal-to-zer.patch @@ -0,0 +1,41 @@ +From 0707cfa5c3ef58effb143db9db6d6e20503f9dec Mon Sep 17 00:00:00 2001 +From: Colin Ian King +Date: Thu, 16 Jan 2020 17:57:58 +0000 +Subject: [PATCH] driver core: platform: fix u32 greater or equal to zero comparison +Git-commit: 0707cfa5c3ef58effb143db9db6d6e20503f9dec +Patch-mainline: v5.6-rc1 +References: bsc#1051510 + +Currently the check that a u32 variable i is >= 0 is always true because +the unsigned variable will never be negative, causing the loop to run +forever. Fix this by changing the pre-decrement check to a zero check on +i followed by a decrement of i. + +Addresses-coverity: ("Unsigned compared against 0") +Fixes: 39cc539f90d0 ("driver core: platform: Prevent resouce overflow from causing infinite loops") +Signed-off-by: Colin Ian King +Reviewed-by: Rafael J. Wysocki +Link: https://lore.kernel.org/r/20200116175758.88396-1-colin.king@canonical.com +Signed-off-by: Greg Kroah-Hartman +Acked-by: Takashi Iwai + +--- + drivers/base/platform.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/base/platform.c b/drivers/base/platform.c +index 864b53b3d598..7fa654f1288b 100644 +--- a/drivers/base/platform.c ++++ b/drivers/base/platform.c +@@ -571,7 +571,7 @@ int platform_device_add(struct platform_device *pdev) + pdev->id = PLATFORM_DEVID_AUTO; + } + +- while (--i >= 0) { ++ while (i--) { + struct resource *r = &pdev->resource[i]; + if (r->parent) + release_resource(r); +-- +2.16.4 + diff --git a/patches.suse/drm-amd-display-Add-link_rate-quirk-for-Apple-15-MBP.patch b/patches.suse/drm-amd-display-Add-link_rate-quirk-for-Apple-15-MBP.patch new file mode 100644 index 0000000..609f9d7 --- /dev/null +++ b/patches.suse/drm-amd-display-Add-link_rate-quirk-for-Apple-15-MBP.patch @@ -0,0 +1,67 @@ +From dec9de2ada523b344eb2428abfedf9d6cd0a0029 Mon Sep 17 00:00:00 2001 +From: Mario Kleiner +Date: Fri, 28 Feb 2020 22:36:07 +0100 +Subject: [PATCH] drm/amd/display: Add link_rate quirk for Apple 15" MBP 2017 +Git-commit: dec9de2ada523b344eb2428abfedf9d6cd0a0029 +Patch-mainline: v5.6-rc7 +References: bsc#1111666 + +This fixes a problem found on the MacBookPro 2017 Retina panel: + +The panel reports 10 bpc color depth in its EDID, and the +firmware chooses link settings at boot which support enough +bandwidth for 10 bpc (324000 kbit/sec aka LINK_RATE_RBR2 +aka 0xc), but the DP_MAX_LINK_RATE dpcd register only reports +2.7 Gbps (multiplier value 0xa) as possible, in direct +contradiction of what the firmware successfully set up. + +This restricts the panel to 8 bpc, not providing the full +color depth of the panel on Linux <= 5.5. Additionally, commit +'4a8ca46bae8a ("drm/amd/display: Default max bpc to 16 for eDP")' +introduced into Linux 5.6-rc1 will unclamp panel depth to +its full 10 bpc, thereby requiring a eDP bandwidth for all +modes that exceeds the bandwidth available and causes all modes +to fail validation -> No modes for the laptop panel -> failure +to set any mode -> Panel goes dark. + +This patch adds a quirk specific to the MBP 2017 15" Retina +panel to override reported max link rate to the correct maximum +of 0xc = LINK_RATE_RBR2 to fix the darkness and reduced display +precision. + +Please apply for Linux 5.6+ to avoid regressing Apple MBP panel +support. + +Signed-off-by: Mario Kleiner +Signed-off-by: Alex Deucher +Acked-by: Takashi Iwai + +--- + drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c | 11 +++++++++++ + 1 file changed, 11 insertions(+) + +diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c +index cb731c1d30b1..fd9e69634c50 100644 +--- a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c ++++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c +@@ -3401,6 +3401,17 @@ static bool retrieve_link_cap(struct dc_link *link) + sink_id.ieee_device_id, + sizeof(sink_id.ieee_device_id)); + ++ /* Quirk Apple MBP 2017 15" Retina panel: Wrong DP_MAX_LINK_RATE */ ++ { ++ uint8_t str_mbp_2017[] = { 101, 68, 21, 101, 98, 97 }; ++ ++ if ((link->dpcd_caps.sink_dev_id == 0x0010fa) && ++ !memcmp(link->dpcd_caps.sink_dev_id_str, str_mbp_2017, ++ sizeof(str_mbp_2017))) { ++ link->reported_link_cap.link_rate = 0x0c; ++ } ++ } ++ + core_link_read_dpcd( + link, + DP_SINK_HW_REVISION_START, +-- +2.16.4 + diff --git a/patches.suse/drm-amd-display-Fix-wrongly-passed-static-prefix.patch b/patches.suse/drm-amd-display-Fix-wrongly-passed-static-prefix.patch new file mode 100644 index 0000000..63093f8 --- /dev/null +++ b/patches.suse/drm-amd-display-Fix-wrongly-passed-static-prefix.patch @@ -0,0 +1,49 @@ +From fa1d7297d09472fc4edd618196aad27281ba2644 Mon Sep 17 00:00:00 2001 +From: Takashi Iwai +Date: Thu, 28 Nov 2019 09:27:14 +0100 +Subject: [PATCH] drm/amd/display: Fix wrongly passed static prefix +Mime-version: 1.0 +Content-type: text/plain; charset=UTF-8 +Content-transfer-encoding: 8bit +Git-commit: fa1d7297d09472fc4edd618196aad27281ba2644 +Patch-mainline: v5.7-rc1 +References: bsc#1111666 + +Currently, gcc spews a warning as: + drivers/gpu/drm/amd/amdgpu/../display/dc/dcn10/dcn10_hubbub.c: In function ‘hubbub1_verify_allow_pstate_change_high’: + ./include/drm/drm_print.h:316:2: warning: ‘debug_data’ may be used uninitialized in this function [-Wmaybe-uninitialized] + +This is because the code checks against a static value although it's +basically a constant and guaranteed to be set. + +This patch changes the type prefix from static to const for addressing +the compile warning above and also for letting the compiler optimize +better. + +Fixes: 62d591a8e00c ("drm/amd/display: create new files for hubbub functions") +Reviewed-by: Harry Wentland +Signed-off-by: Takashi Iwai +Signed-off-by: Alex Deucher + +--- + drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubbub.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubbub.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubbub.c +index 870735deaca7..3e851713cf8d 100644 +--- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubbub.c ++++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubbub.c +@@ -128,8 +128,8 @@ bool hubbub1_verify_allow_pstate_change_high( + * pstate takes around ~100us on linux. Unknown currently as to + * why it takes that long on linux + */ +- static unsigned int pstate_wait_timeout_us = 200; +- static unsigned int pstate_wait_expected_timeout_us = 40; ++ const unsigned int pstate_wait_timeout_us = 200; ++ const unsigned int pstate_wait_expected_timeout_us = 40; + static unsigned int max_sampled_pstate_wait_us; /* data collection */ + static bool forced_pstate_allow; /* help with revert wa */ + +-- +2.16.4 + diff --git a/patches.suse/drm-amd-display-remove-duplicated-assignment-to-grph.patch b/patches.suse/drm-amd-display-remove-duplicated-assignment-to-grph.patch new file mode 100644 index 0000000..9086b00 --- /dev/null +++ b/patches.suse/drm-amd-display-remove-duplicated-assignment-to-grph.patch @@ -0,0 +1,37 @@ +From d785476c608c621b345dd9396e8b21e90375cb0e Mon Sep 17 00:00:00 2001 +From: Colin Ian King +Date: Fri, 8 Nov 2019 14:45:27 +0000 +Subject: [PATCH] drm/amd/display: remove duplicated assignment to grph_obj_type +Git-commit: d785476c608c621b345dd9396e8b21e90375cb0e +Patch-mainline: v5.6-rc1 +References: bsc#1051510 + +Variable grph_obj_type is being assigned twice, one of these is +redundant so remove it. + +Addresses-coverity: ("Evaluation order violation") +Signed-off-by: Colin Ian King +Signed-off-by: Alex Deucher +Acked-by: Takashi Iwai + +--- + drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c +index be6d0cfe41ae..9ba80d828876 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c +@@ -365,8 +365,7 @@ bool amdgpu_atombios_get_connector_info_from_object_table(struct amdgpu_device * + router.ddc_valid = false; + router.cd_valid = false; + for (j = 0; j < ((le16_to_cpu(path->usSize) - 8) / 2); j++) { +- uint8_t grph_obj_type= +- grph_obj_type = ++ uint8_t grph_obj_type = + (le16_to_cpu(path->usGraphicObjIds[j]) & + OBJECT_TYPE_MASK) >> OBJECT_TYPE_SHIFT; + +-- +2.16.4 + diff --git a/patches.suse/drm-amdgpu-fix-typo-for-vcn1-idle-check.patch b/patches.suse/drm-amdgpu-fix-typo-for-vcn1-idle-check.patch new file mode 100644 index 0000000..cfe23b3 --- /dev/null +++ b/patches.suse/drm-amdgpu-fix-typo-for-vcn1-idle-check.patch @@ -0,0 +1,35 @@ +From acfc62dc68770aa665cc606891f6df7d6d1e52c0 Mon Sep 17 00:00:00 2001 +From: James Zhu +Date: Wed, 18 Mar 2020 17:09:05 -0400 +Subject: [PATCH] drm/amdgpu: fix typo for vcn1 idle check +Git-commit: acfc62dc68770aa665cc606891f6df7d6d1e52c0 +Patch-mainline: v5.6-rc7 +References: bsc#1111666 + +fix typo for vcn1 idle check + +Signed-off-by: James Zhu +Reviewed-by: Leo Liu +Signed-off-by: Alex Deucher +Acked-by: Takashi Iwai + +--- + drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c +index 71f61afdc655..09b0572b838d 100644 +--- a/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c ++++ b/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c +@@ -1352,7 +1352,7 @@ static int vcn_v1_0_set_clockgating_state(void *handle, + + if (enable) { + /* wait for STATUS to clear */ +- if (vcn_v1_0_is_idle(handle)) ++ if (!vcn_v1_0_is_idle(handle)) + return -EBUSY; + vcn_v1_0_enable_clock_gating(adev); + } else { +-- +2.16.4 + diff --git a/patches.suse/drm-bridge-dw-hdmi-fix-AVI-frame-colorimetry.patch b/patches.suse/drm-bridge-dw-hdmi-fix-AVI-frame-colorimetry.patch new file mode 100644 index 0000000..9dc3064 --- /dev/null +++ b/patches.suse/drm-bridge-dw-hdmi-fix-AVI-frame-colorimetry.patch @@ -0,0 +1,83 @@ +From e8dca30f7118461d47e1c3510d0e31b277439151 Mon Sep 17 00:00:00 2001 +From: Jernej Skrabec +Date: Thu, 5 Mar 2020 00:25:09 +0100 +Subject: [PATCH] drm/bridge: dw-hdmi: fix AVI frame colorimetry +Git-commit: e8dca30f7118461d47e1c3510d0e31b277439151 +Patch-mainline: v5.6-rc7 +References: bsc#1051510 + +CTA-861-F explicitly states that for RGB colorspace colorimetry should +be set to "none". Fix that. + +Acked-by: Laurent Pinchart +Fixes: def23aa7e982 ("drm: bridge: dw-hdmi: Switch to V4L bus format and encodings") +Signed-off-by: Jernej Skrabec +Link: https://patchwork.freedesktop.org/patch/msgid/20200304232512.51616-2-jernej.skrabec@siol.net +Acked-by: Takashi Iwai + +--- + drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 46 +++++++++++++++++-------------- + 1 file changed, 26 insertions(+), 20 deletions(-) + +diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +index 67fca439bbfb..24965e53d351 100644 +--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c ++++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +@@ -1624,28 +1624,34 @@ static void hdmi_config_AVI(struct dw_hdmi *hdmi, struct drm_display_mode *mode) + frame.colorspace = HDMI_COLORSPACE_RGB; + + /* Set up colorimetry */ +- switch (hdmi->hdmi_data.enc_out_encoding) { +- case V4L2_YCBCR_ENC_601: +- if (hdmi->hdmi_data.enc_in_encoding == V4L2_YCBCR_ENC_XV601) +- frame.colorimetry = HDMI_COLORIMETRY_EXTENDED; +- else ++ if (!hdmi_bus_fmt_is_rgb(hdmi->hdmi_data.enc_out_bus_format)) { ++ switch (hdmi->hdmi_data.enc_out_encoding) { ++ case V4L2_YCBCR_ENC_601: ++ if (hdmi->hdmi_data.enc_in_encoding == V4L2_YCBCR_ENC_XV601) ++ frame.colorimetry = HDMI_COLORIMETRY_EXTENDED; ++ else ++ frame.colorimetry = HDMI_COLORIMETRY_ITU_601; ++ frame.extended_colorimetry = ++ HDMI_EXTENDED_COLORIMETRY_XV_YCC_601; ++ break; ++ case V4L2_YCBCR_ENC_709: ++ if (hdmi->hdmi_data.enc_in_encoding == V4L2_YCBCR_ENC_XV709) ++ frame.colorimetry = HDMI_COLORIMETRY_EXTENDED; ++ else ++ frame.colorimetry = HDMI_COLORIMETRY_ITU_709; ++ frame.extended_colorimetry = ++ HDMI_EXTENDED_COLORIMETRY_XV_YCC_709; ++ break; ++ default: /* Carries no data */ + frame.colorimetry = HDMI_COLORIMETRY_ITU_601; ++ frame.extended_colorimetry = ++ HDMI_EXTENDED_COLORIMETRY_XV_YCC_601; ++ break; ++ } ++ } else { ++ frame.colorimetry = HDMI_COLORIMETRY_NONE; + frame.extended_colorimetry = +- HDMI_EXTENDED_COLORIMETRY_XV_YCC_601; +- break; +- case V4L2_YCBCR_ENC_709: +- if (hdmi->hdmi_data.enc_in_encoding == V4L2_YCBCR_ENC_XV709) +- frame.colorimetry = HDMI_COLORIMETRY_EXTENDED; +- else +- frame.colorimetry = HDMI_COLORIMETRY_ITU_709; +- frame.extended_colorimetry = +- HDMI_EXTENDED_COLORIMETRY_XV_YCC_709; +- break; +- default: /* Carries no data */ +- frame.colorimetry = HDMI_COLORIMETRY_ITU_601; +- frame.extended_colorimetry = +- HDMI_EXTENDED_COLORIMETRY_XV_YCC_601; +- break; ++ HDMI_EXTENDED_COLORIMETRY_XV_YCC_601; + } + + frame.scan_mode = HDMI_SCAN_MODE_NONE; +-- +2.16.4 + diff --git a/patches.suse/drm-drm_dp_mst-remove-set-but-not-used-variable-orig.patch b/patches.suse/drm-drm_dp_mst-remove-set-but-not-used-variable-orig.patch new file mode 100644 index 0000000..519d471 --- /dev/null +++ b/patches.suse/drm-drm_dp_mst-remove-set-but-not-used-variable-orig.patch @@ -0,0 +1,53 @@ +From b37ea8bff730aca844fb3bd202af2108476245fd Mon Sep 17 00:00:00 2001 +From: Bo YU +Date: Sat, 18 Jan 2020 16:06:28 +0800 +Subject: [PATCH] drm/drm_dp_mst:remove set but not used variable 'origlen' +Mime-version: 1.0 +Content-type: text/plain; charset=UTF-8 +Content-transfer-encoding: 8bit +Git-commit: b37ea8bff730aca844fb3bd202af2108476245fd +Patch-mainline: v5.7-rc1 +References: bsc#1051510 + +Fixes gcc '-Wunused-but-set-variable' warning: + +drivers/gpu/drm/drm_dp_mst_topology.c:3693:16: warning: variable +‘origlen’ set but not used [-Wunused-but-set-variable] + int replylen, origlen, curreply; + +It looks like never use variable origlen after assign value to it. + +Fixes: ad7f8a1f9ced ("drm/helper: add Displayport multi-stream helper (v0.6)") +Signed-off-by: Bo YU +Signed-off-by: Daniel Vetter +Link: https://patchwork.freedesktop.org/patch/msgid/20200118080628.mxcx7bfwdas5m7un@kaowomen.cn +Acked-by: Takashi Iwai + +--- + drivers/gpu/drm/drm_dp_mst_topology.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/drivers/gpu/drm/drm_dp_mst_topology.c b/drivers/gpu/drm/drm_dp_mst_topology.c +index f45e36f04ca9..80f758025c4c 100644 +--- a/drivers/gpu/drm/drm_dp_mst_topology.c ++++ b/drivers/gpu/drm/drm_dp_mst_topology.c +@@ -3639,7 +3639,7 @@ static bool drm_dp_get_one_sb_msg(struct drm_dp_mst_topology_mgr *mgr, bool up) + { + int len; + u8 replyblock[32]; +- int replylen, origlen, curreply; ++ int replylen, curreply; + int ret; + struct drm_dp_sideband_msg_rx *msg; + int basereg = up ? DP_SIDEBAND_MSG_UP_REQ_BASE : DP_SIDEBAND_MSG_DOWN_REP_BASE; +@@ -3659,7 +3659,6 @@ static bool drm_dp_get_one_sb_msg(struct drm_dp_mst_topology_mgr *mgr, bool up) + } + replylen = msg->curchunk_len + msg->curchunk_hdrlen; + +- origlen = replylen; + replylen -= len; + curreply = len; + while (replylen > 0) { +-- +2.16.4 + diff --git a/patches.suse/drm-exynos-dsi-fix-workaround-for-the-legacy-clock-n.patch b/patches.suse/drm-exynos-dsi-fix-workaround-for-the-legacy-clock-n.patch new file mode 100644 index 0000000..c1da10d --- /dev/null +++ b/patches.suse/drm-exynos-dsi-fix-workaround-for-the-legacy-clock-n.patch @@ -0,0 +1,74 @@ +From c0fd99d659ba5582e09625c7a985d63fc2ca74b5 Mon Sep 17 00:00:00 2001 +From: Marek Szyprowski +Date: Thu, 20 Feb 2020 13:30:12 +0100 +Subject: [PATCH] drm/exynos: dsi: fix workaround for the legacy clock name +Git-commit: c0fd99d659ba5582e09625c7a985d63fc2ca74b5 +Patch-mainline: v5.6-rc5 +References: bsc#1111666 + +Writing to the built-in strings arrays doesn't work if driver is loaded +as kernel module. This is also considered as a bad pattern. Fix this by +adding a call to clk_get() with legacy clock name. This fixes following +kernel oops if driver is loaded as module: + +Unable to handle kernel paging request at virtual address bf047978 + pgd = (ptrval) + [bf047978] *pgd=59344811, *pte=5903c6df, *ppte=5903c65f + Internal error: Oops: 80f [#1] SMP ARM + Modules linked in: mc exynosdrm(+) analogix_dp rtc_s3c exynos_ppmu i2c_gpio + CPU: 1 PID: 212 Comm: systemd-udevd Not tainted 5.6.0-rc2-next-20200219 #326 + videodev: Linux video capture interface: v2.00 + Hardware name: Samsung Exynos (Flattened Device Tree) + PC is at exynos_dsi_probe+0x1f0/0x384 [exynosdrm] + LR is at exynos_dsi_probe+0x1dc/0x384 [exynosdrm] + ... + Process systemd-udevd (pid: 212, stack limit = 0x(ptrval)) + ... + [] (exynos_dsi_probe [exynosdrm]) from [] (platform_drv_probe+0x6c/0xa4) + [] (platform_drv_probe) from [] (really_probe+0x210/0x350) + [] (really_probe) from [] (driver_probe_device+0x60/0x1a0) + [] (driver_probe_device) from [] (device_driver_attach+0x58/0x60) + [] (device_driver_attach) from [] (__driver_attach+0x80/0xbc) + [] (__driver_attach) from [] (bus_for_each_dev+0x68/0xb4) + [] (bus_for_each_dev) from [] (bus_add_driver+0x130/0x1e8) + [] (bus_add_driver) from [] (driver_register+0x78/0x110) + [] (driver_register) from [] (exynos_drm_init+0xe8/0x11c [exynosdrm]) + [] (exynos_drm_init [exynosdrm]) from [] (do_one_initcall+0x50/0x220) + [] (do_one_initcall) from [] (do_init_module+0x60/0x210) + [] (do_init_module) from [] (load_module+0x1c0c/0x2310) + [] (load_module) from [] (sys_finit_module+0xac/0xbc) + [] (sys_finit_module) from [] (ret_fast_syscall+0x0/0x54) + Exception stack(0xd979bfa8 to 0xd979bff0) + ... + ---[ end trace db16efe05faab470 ]--- + +Signed-off-by: Marek Szyprowski +Reviewed-by: Andrzej Hajda +Signed-off-by: Inki Dae +Acked-by: Takashi Iwai + +--- + drivers/gpu/drm/exynos/exynos_drm_dsi.c | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +diff --git a/drivers/gpu/drm/exynos/exynos_drm_dsi.c b/drivers/gpu/drm/exynos/exynos_drm_dsi.c +index 3f6fcd453d33..a85365c56d4d 100644 +--- a/drivers/gpu/drm/exynos/exynos_drm_dsi.c ++++ b/drivers/gpu/drm/exynos/exynos_drm_dsi.c +@@ -1788,9 +1788,10 @@ static int exynos_dsi_probe(struct platform_device *pdev) + dsi->clks[i] = devm_clk_get(dev, clk_names[i]); + if (IS_ERR(dsi->clks[i])) { + if (strcmp(clk_names[i], "sclk_mipi") == 0) { +- strcpy(clk_names[i], OLD_SCLK_MIPI_CLK_NAME); +- i--; +- continue; ++ dsi->clks[i] = devm_clk_get(dev, ++ OLD_SCLK_MIPI_CLK_NAME); ++ if (!IS_ERR(dsi->clks[i])) ++ continue; + } + + dev_info(dev, "failed to get the clock: %s\n", +-- +2.16.4 + diff --git a/patches.suse/drm-exynos-dsi-propagate-error-value-and-silence-mea.patch b/patches.suse/drm-exynos-dsi-propagate-error-value-and-silence-mea.patch new file mode 100644 index 0000000..2b0b911 --- /dev/null +++ b/patches.suse/drm-exynos-dsi-propagate-error-value-and-silence-mea.patch @@ -0,0 +1,35 @@ +From 0a9d1e3f3f038785ebc72d53f1c409d07f6b4ff5 Mon Sep 17 00:00:00 2001 +From: Marek Szyprowski +Date: Thu, 27 Feb 2020 08:06:37 +0100 +Subject: [PATCH] drm/exynos: dsi: propagate error value and silence meaningless warning +Git-commit: 0a9d1e3f3f038785ebc72d53f1c409d07f6b4ff5 +Patch-mainline: v5.6-rc5 +References: bsc#1111666 + +Properly propagate error value from devm_regulator_bulk_get() and don't +confuse user with meaningless warning about failure in getting regulators +in case of deferred probe. + +Signed-off-by: Marek Szyprowski +Reviewed-by: Krzysztof Kozlowski +Signed-off-by: Inki Dae +Acked-by: Takashi Iwai + +--- + drivers/gpu/drm/exynos/exynos_drm_dsi.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +--- a/drivers/gpu/drm/exynos/exynos_drm_dsi.c ++++ b/drivers/gpu/drm/exynos/exynos_drm_dsi.c +@@ -1722,8 +1722,9 @@ static int exynos_dsi_probe(struct platf + ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(dsi->supplies), + dsi->supplies); + if (ret) { +- dev_info(dev, "failed to get regulators: %d\n", ret); +- return -EPROBE_DEFER; ++ if (ret != -EPROBE_DEFER) ++ dev_info(dev, "failed to get regulators: %d\n", ret); ++ return ret; + } + + dsi->clks = devm_kzalloc(dev, diff --git a/patches.suse/drm-gma500-Fixup-fbdev-stolen-size-usage-evaluation.patch b/patches.suse/drm-gma500-Fixup-fbdev-stolen-size-usage-evaluation.patch new file mode 100644 index 0000000..7ffd6de --- /dev/null +++ b/patches.suse/drm-gma500-Fixup-fbdev-stolen-size-usage-evaluation.patch @@ -0,0 +1,61 @@ +From fd1a5e521c3c083bb43ea731aae0f8b95f12b9bd Mon Sep 17 00:00:00 2001 +From: Paul Kocialkowski +Date: Thu, 7 Nov 2019 16:30:48 +0100 +Subject: [PATCH] drm/gma500: Fixup fbdev stolen size usage evaluation +Git-commit: fd1a5e521c3c083bb43ea731aae0f8b95f12b9bd +Patch-mainline: v5.6-rc1 +References: bsc#1051510 + +psbfb_probe performs an evaluation of the required size from the stolen +GTT memory, but gets it wrong in two distinct ways: +- The resulting size must be page-size-aligned; +- The size to allocate is derived from the surface dimensions, not the fb + dimensions. + +When two connectors are connected with different modes, the smallest will +be stored in the fb dimensions, but the size that needs to be allocated must +match the largest (surface) dimensions. This is what is used in the actual +allocation code. + +Fix this by correcting the evaluation to conform to the two points above. +It allows correctly switching to 16bpp when one connector is e.g. 1920x1080 +and the other is 1024x768. + +Signed-off-by: Paul Kocialkowski +Signed-off-by: Patrik Jakobsson +Link: https://patchwork.freedesktop.org/patch/msgid/20191107153048.843881-1-paul.kocialkowski@bootlin.com +Acked-by: Takashi Iwai + +--- + drivers/gpu/drm/gma500/framebuffer.c | 8 ++++++-- + 1 file changed, 6 insertions(+), 2 deletions(-) + +diff --git a/drivers/gpu/drm/gma500/framebuffer.c b/drivers/gpu/drm/gma500/framebuffer.c +index 218f3bb15276..90237abee088 100644 +--- a/drivers/gpu/drm/gma500/framebuffer.c ++++ b/drivers/gpu/drm/gma500/framebuffer.c +@@ -462,6 +462,7 @@ static int psbfb_probe(struct drm_fb_helper *helper, + container_of(helper, struct psb_fbdev, psb_fb_helper); + struct drm_device *dev = psb_fbdev->psb_fb_helper.dev; + struct drm_psb_private *dev_priv = dev->dev_private; ++ unsigned int fb_size; + int bytespp; + + bytespp = sizes->surface_bpp / 8; +@@ -471,8 +472,11 @@ static int psbfb_probe(struct drm_fb_helper *helper, + /* If the mode will not fit in 32bit then switch to 16bit to get + a console on full resolution. The X mode setting server will + allocate its own 32bit GEM framebuffer */ +- if (ALIGN(sizes->fb_width * bytespp, 64) * sizes->fb_height > +- dev_priv->vram_stolen_size) { ++ fb_size = ALIGN(sizes->surface_width * bytespp, 64) * ++ sizes->surface_height; ++ fb_size = ALIGN(fb_size, PAGE_SIZE); ++ ++ if (fb_size > dev_priv->vram_stolen_size) { + sizes->surface_bpp = 16; + sizes->surface_depth = 16; + } +-- +2.16.4 + diff --git a/patches.suse/drm-i915-gvt-fix-orphan-vgpu-dmabuf_objs-lifetime b/patches.suse/drm-i915-gvt-fix-orphan-vgpu-dmabuf_objs-lifetime new file mode 100644 index 0000000..f74ee6f --- /dev/null +++ b/patches.suse/drm-i915-gvt-fix-orphan-vgpu-dmabuf_objs-lifetime @@ -0,0 +1,43 @@ +From: Tina Zhang +Date: Tue, 25 Feb 2020 13:35:27 +0800 +Subject: drm/i915/gvt: Fix orphan vgpu dmabuf_objs' lifetime +Git-commit: b549c252b1292aea959cd9b83537fcb9384a6112 +Patch-mainline: v5.6-rc4 +References: git-fixes + +Deleting dmabuf item's list head after releasing its container can lead +to KASAN-reported issue: + + BUG: KASAN: use-after-free in __list_del_entry_valid+0x15/0xf0 + Read of size 8 at addr ffff88818a4598a8 by task kworker/u8:3/13119 + +So fix this issue by puting deleting dmabuf_objs ahead of releasing its +container. + +Fixes: dfb6ae4e14bd6 ("drm/i915/gvt: Handle orphan dmabuf_objs") +Signed-off-by: Tina Zhang +Reviewed-by: Zhenyu Wang +Signed-off-by: Zhenyu Wang +Link: http://patchwork.freedesktop.org/patch/msgid/20200225053527.8336-2-tina.zhang@intel.com + +Acked-by: Petr Tesarik +--- + drivers/gpu/drm/i915/gvt/dmabuf.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/gpu/drm/i915/gvt/dmabuf.c ++++ b/drivers/gpu/drm/i915/gvt/dmabuf.c +@@ -148,12 +148,12 @@ static void dmabuf_gem_object_free(struc + dmabuf_obj = container_of(pos, + struct intel_vgpu_dmabuf_obj, list); + if (dmabuf_obj == obj) { ++ list_del(pos); + intel_gvt_hypervisor_put_vfio_device(vgpu); + idr_remove(&vgpu->object_idr, + dmabuf_obj->dmabuf_id); + kfree(dmabuf_obj->info); + kfree(dmabuf_obj); +- list_del(pos); + break; + } + } diff --git a/patches.suse/drm-i915-gvt-fix-unnecessary-schedule-timer-when-no-vgpu-exits b/patches.suse/drm-i915-gvt-fix-unnecessary-schedule-timer-when-no-vgpu-exits new file mode 100644 index 0000000..bd67da3 --- /dev/null +++ b/patches.suse/drm-i915-gvt-fix-unnecessary-schedule-timer-when-no-vgpu-exits @@ -0,0 +1,54 @@ +From: Zhenyu Wang +Date: Tue, 3 Mar 2020 13:54:12 +0800 +Subject: drm/i915/gvt: Fix unnecessary schedule timer when no vGPU exits +Git-commit: 04d6067f1f19e70a418f92fa3170cf7fe53b7fdf +Patch-mainline: v5.6-rc6 +References: git-fixes + +>From commit f25a49ab8ab9 ("drm/i915/gvt: Use vgpu_lock to protect per +vgpu access") the vgpu idr destroy is moved later than vgpu resource +destroy, then it would fail to stop timer for schedule policy clean +which to check vgpu idr for any left vGPU. So this trys to destroy +vgpu idr earlier. + +Cc: Colin Xu +Fixes: f25a49ab8ab9 ("drm/i915/gvt: Use vgpu_lock to protect per vgpu access") +Acked-by: Colin Xu +Signed-off-by: Zhenyu Wang +Link: http://patchwork.freedesktop.org/patch/msgid/20200229055445.31481-1-zhenyuw@linux.intel.com + +Acked-by: Petr Tesarik +--- + drivers/gpu/drm/i915/gvt/vgpu.c | 12 +++++++++--- + 1 file changed, 9 insertions(+), 3 deletions(-) + +--- a/drivers/gpu/drm/i915/gvt/vgpu.c ++++ b/drivers/gpu/drm/i915/gvt/vgpu.c +@@ -272,10 +272,17 @@ void intel_gvt_destroy_vgpu(struct intel + { + struct intel_gvt *gvt = vgpu->gvt; + +- mutex_lock(&vgpu->vgpu_lock); +- + WARN(vgpu->active, "vGPU is still active!\n"); + ++ /* ++ * remove idr first so later clean can judge if need to stop ++ * service if no active vgpu. ++ */ ++ mutex_lock(&gvt->lock); ++ idr_remove(&gvt->vgpu_idr, vgpu->id); ++ mutex_unlock(&gvt->lock); ++ ++ mutex_lock(&vgpu->vgpu_lock); + intel_gvt_debugfs_remove_vgpu(vgpu); + intel_vgpu_clean_sched_policy(vgpu); + intel_vgpu_clean_submission(vgpu); +@@ -290,7 +297,6 @@ void intel_gvt_destroy_vgpu(struct intel + mutex_unlock(&vgpu->vgpu_lock); + + mutex_lock(&gvt->lock); +- idr_remove(&gvt->vgpu_idr, vgpu->id); + if (idr_is_empty(&gvt->vgpu_idr)) + intel_gvt_clean_irq(gvt); + intel_gvt_update_vgpu_types(gvt); diff --git a/patches.suse/drm-i915-program-mbus-with-rmw-during-initialization b/patches.suse/drm-i915-program-mbus-with-rmw-during-initialization new file mode 100644 index 0000000..1bf9db8 --- /dev/null +++ b/patches.suse/drm-i915-program-mbus-with-rmw-during-initialization @@ -0,0 +1,55 @@ +From: Matt Roper +Date: Thu, 27 Feb 2020 16:43:19 -0800 +Subject: drm/i915: Program MBUS with rmw during initialization +Git-commit: c725161924f9a5872a3e53b73345a6026a5c170e +Patch-mainline: v5.6-rc5 +References: git-fixes + +It wasn't terribly clear from the bspec's wording, but after discussion +with the hardware folks, it turns out that we need to preserve the +pre-existing contents of the MBUS ABOX control register when +initializing a few specific bits. + +Bspec: 49213 +Bspec: 50096 +Fixes: 4cb4585e5a7f ("drm/i915/icl: initialize MBus during display init") +Cc: Stanislav Lisovskiy +Signed-off-by: Matt Roper +Link: https://patchwork.freedesktop.org/patch/msgid/20200204011032.582737-1-matthew.d.roper@intel.com +Reviewed-by: Matt Atwood +(cherry picked from commit 837b63e6087838d0f1e612d448405419199d8033) +Signed-off-by: Jani Nikula +Link: https://patchwork.freedesktop.org/patch/msgid/20200228004320.127142-1-matthew.d.roper@intel.com + +Acked-by: Petr Tesarik +--- + drivers/gpu/drm/i915/intel_runtime_pm.c | 16 +++++++++++----- + 1 file changed, 11 insertions(+), 5 deletions(-) + +--- a/drivers/gpu/drm/i915/intel_runtime_pm.c ++++ b/drivers/gpu/drm/i915/intel_runtime_pm.c +@@ -3342,13 +3342,19 @@ static void icl_dbuf_disable(struct drm_ + + static void icl_mbus_init(struct drm_i915_private *dev_priv) + { +- uint32_t val; ++ u32 mask, val; + +- val = MBUS_ABOX_BT_CREDIT_POOL1(16) | +- MBUS_ABOX_BT_CREDIT_POOL2(16) | +- MBUS_ABOX_B_CREDIT(1) | +- MBUS_ABOX_BW_CREDIT(1); ++ mask = MBUS_ABOX_BT_CREDIT_POOL1_MASK | ++ MBUS_ABOX_BT_CREDIT_POOL2_MASK | ++ MBUS_ABOX_B_CREDIT_MASK | ++ MBUS_ABOX_BW_CREDIT_MASK; + ++ val = I915_READ(MBUS_ABOX_CTL); ++ val &= ~mask; ++ val |= MBUS_ABOX_BT_CREDIT_POOL1(16) | ++ MBUS_ABOX_BT_CREDIT_POOL2(16) | ++ MBUS_ABOX_B_CREDIT(1) | ++ MBUS_ABOX_BW_CREDIT(1); + I915_WRITE(MBUS_ABOX_CTL, val); + } + diff --git a/patches.suse/drm-mediatek-handle-events-when-enabling-disabling-c.patch b/patches.suse/drm-mediatek-handle-events-when-enabling-disabling-c.patch new file mode 100644 index 0000000..1fa622c --- /dev/null +++ b/patches.suse/drm-mediatek-handle-events-when-enabling-disabling-c.patch @@ -0,0 +1,51 @@ +From 411f5c1eacfebb1f6e40b653d29447cdfe7282aa Mon Sep 17 00:00:00 2001 +From: Bibby Hsieh +Date: Tue, 10 Dec 2019 13:05:21 +0800 +Subject: [PATCH] drm/mediatek: handle events when enabling/disabling crtc +Git-commit: 411f5c1eacfebb1f6e40b653d29447cdfe7282aa +Patch-mainline: v5.6-rc1 +References: bsc#1051510 + +The driver currently handles vblank events only when updating planes on +an already enabled CRTC. The atomic update API however allows requesting +an event when enabling or disabling a CRTC. This currently leads to +event objects being leaked in the kernel and to events not being sent +out. Fix it. + +Signed-off-by: Bibby Hsieh +Signed-off-by: CK Hu +Acked-by: Takashi Iwai + +--- + drivers/gpu/drm/mediatek/mtk_drm_crtc.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c +index 3305a94fc930..4132cd114a03 100644 +--- a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c ++++ b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c +@@ -328,6 +328,7 @@ static int mtk_crtc_ddp_hw_init(struct mtk_drm_crtc *mtk_crtc) + static void mtk_crtc_ddp_hw_fini(struct mtk_drm_crtc *mtk_crtc) + { + struct drm_device *drm = mtk_crtc->base.dev; ++ struct drm_crtc *crtc = &mtk_crtc->base; + int i; + + DRM_DEBUG_DRIVER("%s\n", __func__); +@@ -353,6 +354,13 @@ static void mtk_crtc_ddp_hw_fini(struct mtk_drm_crtc *mtk_crtc) + mtk_disp_mutex_unprepare(mtk_crtc->mutex); + + pm_runtime_put(drm->dev); ++ ++ if (crtc->state->event && !crtc->state->active) { ++ spin_lock_irq(&crtc->dev->event_lock); ++ drm_crtc_send_vblank_event(crtc, crtc->state->event); ++ crtc->state->event = NULL; ++ spin_unlock_irq(&crtc->dev->event_lock); ++ } + } + + static void mtk_crtc_ddp_config(struct drm_crtc *crtc) +-- +2.16.4 + diff --git a/patches.suse/drm-msm-Set-dma-maximum-segment-size-for-mdss.patch b/patches.suse/drm-msm-Set-dma-maximum-segment-size-for-mdss.patch new file mode 100644 index 0000000..26ef1e3 --- /dev/null +++ b/patches.suse/drm-msm-Set-dma-maximum-segment-size-for-mdss.patch @@ -0,0 +1,90 @@ +From db735fc4036bbe1fbe606819b5f0ff26cc76cdff Mon Sep 17 00:00:00 2001 +From: Sean Paul +Date: Tue, 21 Jan 2020 11:18:48 -0800 +Subject: [PATCH] drm/msm: Set dma maximum segment size for mdss +Git-commit: db735fc4036bbe1fbe606819b5f0ff26cc76cdff +Patch-mainline: v5.6-rc2 +References: bsc#1051510 + +Turning on CONFIG_DMA_API_DEBUG_SG results in the following error: + +[ 12.078665] msm ae00000.mdss: DMA-API: mapping sg segment longer than device claims to support [len=3526656] [max=65536] +[ 12.089870] WARNING: CPU: 6 PID: 334 at /mnt/host/source/src/third_party/kernel/v4.19/kernel/dma/debug.c:1301 debug_dma_map_sg+0x1dc/0x318 +[ 12.102655] Modules linked in: joydev +[ 12.106442] CPU: 6 PID: 334 Comm: frecon Not tainted 4.19.0 #2 +[ 12.112450] Hardware name: Google Cheza (rev3+) (DT) +[ 12.117566] pstate: 60400009 (nZCv daif +PAN -UAO) +[ 12.122506] pc : debug_dma_map_sg+0x1dc/0x318 +[ 12.126995] lr : debug_dma_map_sg+0x1dc/0x318 +[ 12.131487] sp : ffffff800cc3ba80 +[ 12.134913] x29: ffffff800cc3ba80 x28: 0000000000000000 +[ 12.140395] x27: 0000000000000004 x26: 0000000000000004 +[ 12.145868] x25: ffffff8008e55b18 x24: 0000000000000000 +[ 12.151337] x23: 00000000ffffffff x22: ffffff800921c000 +[ 12.156809] x21: ffffffc0fa75b080 x20: ffffffc0f7195090 +[ 12.162280] x19: ffffffc0f1c53280 x18: 0000000000000000 +[ 12.167749] x17: 0000000000000000 x16: 0000000000000000 +[ 12.173218] x15: 0000000000000000 x14: 0720072007200720 +[ 12.178689] x13: 0720072007200720 x12: 0720072007200720 +[ 12.184161] x11: 0720072007200720 x10: 0720072007200720 +[ 12.189641] x9 : ffffffc0f1fc6b60 x8 : 0000000000000000 +[ 12.195110] x7 : ffffff8008132ce0 x6 : 0000000000000000 +[ 12.200585] x5 : 0000000000000000 x4 : ffffff8008134734 +[ 12.206058] x3 : ffffff800cc3b830 x2 : ffffffc0f1fc6240 +[ 12.211532] x1 : 25045a74f48a7400 x0 : 25045a74f48a7400 +[ 12.217006] Call trace: +[ 12.219535] debug_dma_map_sg+0x1dc/0x318 +[ 12.223671] get_pages+0x19c/0x20c +[ 12.227177] msm_gem_fault+0x64/0xfc +[ 12.230874] __do_fault+0x3c/0x140 +[ 12.234383] __handle_mm_fault+0x70c/0xdb8 +[ 12.238603] handle_mm_fault+0xac/0xc4 +[ 12.242473] do_page_fault+0x1bc/0x3d4 +[ 12.246342] do_translation_fault+0x54/0x88 +[ 12.250652] do_mem_abort+0x60/0xf0 +[ 12.254250] el0_da+0x20/0x24 +[ 12.257317] irq event stamp: 67260 +[ 12.260828] hardirqs last enabled at (67259): [] console_unlock+0x214/0x608 +[ 12.269693] hardirqs last disabled at (67260): [] do_debug_exception+0x5c/0x178 +[ 12.278820] softirqs last enabled at (67256): [] __do_softirq+0x4d4/0x520 +[ 12.287510] softirqs last disabled at (67249): [] irq_exit+0xa8/0x100 +[ 12.295742] ---[ end trace e63cfc40c313ffab ]--- + +The root of the problem is that the default segment size for sgt is +(UINT_MAX & PAGE_MASK), and the default segment size for device dma is +64K. As such, if you compare the 2, you would deduce that the sg segment +will overflow the device's capacity. In reality, the hardware can +accommodate the larger sg segments, it's just not initializing its max +segment properly. This patch initializes the max segment size for the +mdss device, which gets rid of that pesky warning. + +Reported-by: Stephen Boyd +Tested-by: Stephen Boyd +Tested-by: Sai Prakash Ranjan +Reviewed-by: Rob Clark +Signed-off-by: Sean Paul +Signed-off-by: Douglas Anderson +Link: https://patchwork.freedesktop.org/patch/msgid/20200121111813.REPOST.1.I92c66a35fb13f368095b05287bdabdbe88ca6922@changeid +Acked-by: Takashi Iwai + +--- + drivers/gpu/drm/msm/msm_drv.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +--- a/drivers/gpu/drm/msm/msm_drv.c ++++ b/drivers/gpu/drm/msm/msm_drv.c +@@ -428,6 +428,14 @@ static int msm_drm_init(struct device *d + if (ret) + goto err_msm_uninit; + ++ if (!dev->dma_parms) { ++ dev->dma_parms = devm_kzalloc(dev, sizeof(*dev->dma_parms), ++ GFP_KERNEL); ++ if (!dev->dma_parms) ++ return -ENOMEM; ++ } ++ dma_set_max_seg_size(dev, DMA_BIT_MASK(32)); ++ + msm_gem_shrinker_init(ddev); + + switch (get_mdp_ver(pdev)) { diff --git a/patches.suse/drm-msm-mdp4-Adjust-indentation-in-mdp4_dsi_encoder_.patch b/patches.suse/drm-msm-mdp4-Adjust-indentation-in-mdp4_dsi_encoder_.patch deleted file mode 100644 index c06964c..0000000 --- a/patches.suse/drm-msm-mdp4-Adjust-indentation-in-mdp4_dsi_encoder_.patch +++ /dev/null @@ -1,51 +0,0 @@ -From 251e3cb1418ff3f5061ee31335e346e852b16573 Mon Sep 17 00:00:00 2001 -From: Nathan Chancellor -Date: Mon, 9 Dec 2019 13:32:30 -0700 -Subject: [PATCH] drm: msm: mdp4: Adjust indentation in mdp4_dsi_encoder_enable -Git-commit: 251e3cb1418ff3f5061ee31335e346e852b16573 -Patch-mainline: v5.6-rc1 -References: bsc#1111666 - -Clang warns: - -../drivers/gpu/drm/msm/disp/mdp4/mdp4_dsi_encoder.c:124:3: warning: -misleading indentation; statement is not part of the previous 'if' -[-Wmisleading-indentation] - mdp4_crtc_set_config(encoder->crtc, - ^ -../drivers/gpu/drm/msm/disp/mdp4/mdp4_dsi_encoder.c:121:2: note: -previous statement is here - if (mdp4_dsi_encoder->enabled) - ^ - -This warning occurs because there is a space after the tab on this line. -Remove it so that the indentation is consistent with the Linux kernel -coding style and clang no longer warns. - -Fixes: 776638e73a19 ("drm/msm/dsi: Add a mdp4 encoder for DSI") -Link: https://github.com/ClangBuiltLinux/linux/issues/792 -Signed-off-by: Nathan Chancellor -Reviewed-by: Nick Desaulniers -Signed-off-by: Rob Clark -Acked-by: Takashi Iwai - ---- - drivers/gpu/drm/msm/disp/mdp4/mdp4_dsi_encoder.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/drivers/gpu/drm/msm/disp/mdp4/mdp4_dsi_encoder.c b/drivers/gpu/drm/msm/disp/mdp4/mdp4_dsi_encoder.c -index 772f0753ed38..aaf2f26f8505 100644 ---- a/drivers/gpu/drm/msm/disp/mdp4/mdp4_dsi_encoder.c -+++ b/drivers/gpu/drm/msm/disp/mdp4/mdp4_dsi_encoder.c -@@ -121,7 +121,7 @@ static void mdp4_dsi_encoder_enable(struct drm_encoder *encoder) - if (mdp4_dsi_encoder->enabled) - return; - -- mdp4_crtc_set_config(encoder->crtc, -+ mdp4_crtc_set_config(encoder->crtc, - MDP4_DMA_CONFIG_PACK_ALIGN_MSB | - MDP4_DMA_CONFIG_DEFLKR_EN | - MDP4_DMA_CONFIG_DITHER_EN | --- -2.16.4 - diff --git a/patches.suse/drm-nouveau-disp-nv50-prevent-oops-when-no-channel-m.patch b/patches.suse/drm-nouveau-disp-nv50-prevent-oops-when-no-channel-m.patch new file mode 100644 index 0000000..ab6985a --- /dev/null +++ b/patches.suse/drm-nouveau-disp-nv50-prevent-oops-when-no-channel-m.patch @@ -0,0 +1,40 @@ +From 0e6176c6d286316e9431b4f695940cfac4ffe6c2 Mon Sep 17 00:00:00 2001 +From: Ben Skeggs +Date: Tue, 28 Jan 2020 14:39:26 +1000 +Subject: [PATCH] drm/nouveau/disp/nv50-: prevent oops when no channel method map provided +Git-commit: 0e6176c6d286316e9431b4f695940cfac4ffe6c2 +Patch-mainline: v5.6-rc1 +References: bsc#1051510 + +The implementations for most channel types contains a map of methods to +priv registers in order to provide debugging info when a disp exception +has been raised. + +This info is missing from the implementation of PIO channels as they're +rather simplistic already, however, if an exception is raised by one of +them, we'd end up triggering a NULL-pointer deref. Not ideal... + +Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=206299 +Signed-off-by: Ben Skeggs +Acked-by: Takashi Iwai + +--- + drivers/gpu/drm/nouveau/nvkm/engine/disp/channv50.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/channv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/channv50.c +index bcf32d92ee5a..50e3539f33d2 100644 +--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/channv50.c ++++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/channv50.c +@@ -74,6 +74,8 @@ nv50_disp_chan_mthd(struct nv50_disp_chan *chan, int debug) + + if (debug > subdev->debug) + return; ++ if (!mthd) ++ return; + + for (i = 0; (list = mthd->data[i].mthd) != NULL; i++) { + u32 base = chan->head * mthd->addr; +-- +2.16.4 + diff --git a/patches.suse/drm-nouveau-gr-gk20a-gm200-add-terminators-to-method.patch b/patches.suse/drm-nouveau-gr-gk20a-gm200-add-terminators-to-method.patch new file mode 100644 index 0000000..79e0e71 --- /dev/null +++ b/patches.suse/drm-nouveau-gr-gk20a-gm200-add-terminators-to-method.patch @@ -0,0 +1,75 @@ +From 7adc77aa0e11f25b0e762859219c70852cd8d56f Mon Sep 17 00:00:00 2001 +From: Ben Skeggs +Date: Thu, 9 Jan 2020 11:46:15 +1000 +Subject: [PATCH] drm/nouveau/gr/gk20a,gm200-: add terminators to method lists read from fw +Git-commit: 7adc77aa0e11f25b0e762859219c70852cd8d56f +Patch-mainline: v5.6-rc1 +References: bsc#1051510 + +Method init is typically ordered by class in the FW image as ThreeD, +TwoD, Compute. + +Due to a bug in parsing the FW into our internal format, we've been +accidentally sending Twod + Compute methods to the ThreeD class, as +well as Compute methods to the TwoD class - oops. + +Signed-off-by: Ben Skeggs +Acked-by: Takashi Iwai + +--- + drivers/gpu/drm/nouveau/nvkm/engine/gr/gk20a.c | 21 +++++++++++---------- + 1 file changed, 11 insertions(+), 10 deletions(-) + +diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk20a.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk20a.c +index 500cb08dd608..b57ab5cea9a1 100644 +--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk20a.c ++++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk20a.c +@@ -143,23 +143,24 @@ gk20a_gr_av_to_method(struct gf100_gr *gr, const char *fw_name, + + nent = (fuc.size / sizeof(struct gk20a_fw_av)); + +- pack = vzalloc((sizeof(*pack) * max_classes) + +- (sizeof(*init) * (nent + 1))); ++ pack = vzalloc((sizeof(*pack) * (max_classes + 1)) + ++ (sizeof(*init) * (nent + max_classes + 1))); + if (!pack) { + ret = -ENOMEM; + goto end; + } + +- init = (void *)(pack + max_classes); ++ init = (void *)(pack + max_classes + 1); + +- for (i = 0; i < nent; i++) { +- struct gf100_gr_init *ent = &init[i]; ++ for (i = 0; i < nent; i++, init++) { + struct gk20a_fw_av *av = &((struct gk20a_fw_av *)fuc.data)[i]; + u32 class = av->addr & 0xffff; + u32 addr = (av->addr & 0xffff0000) >> 14; + + if (prevclass != class) { +- pack[classidx].init = ent; ++ if (prevclass) /* Add terminator to the method list. */ ++ init++; ++ pack[classidx].init = init; + pack[classidx].type = class; + prevclass = class; + if (++classidx >= max_classes) { +@@ -169,10 +170,10 @@ gk20a_gr_av_to_method(struct gf100_gr *gr, const char *fw_name, + } + } + +- ent->addr = addr; +- ent->data = av->data; +- ent->count = 1; +- ent->pitch = 1; ++ init->addr = addr; ++ init->data = av->data; ++ init->count = 1; ++ init->pitch = 1; + } + + *ppack = pack; +-- +2.16.4 + diff --git a/patches.suse/drm-nouveau-kms-gv100-re-set-lut-after-clearing-for-modesets b/patches.suse/drm-nouveau-kms-gv100-re-set-lut-after-clearing-for-modesets new file mode 100644 index 0000000..ed5d43d --- /dev/null +++ b/patches.suse/drm-nouveau-kms-gv100-re-set-lut-after-clearing-for-modesets @@ -0,0 +1,40 @@ +From: Lyude Paul +Date: Wed, 12 Feb 2020 18:11:49 -0500 +Subject: drm/nouveau/kms/gv100-: Re-set LUT after clearing for modesets +Git-commit: f287d3d19769b1d22cba4e51fa0487f2697713c9 +Patch-mainline: v5.6-rc3 +References: git-fixes + +While certain modeset operations on gv100+ need us to temporarily +disable the LUT, we make the mistake of sometimes neglecting to +reprogram the LUT after such modesets. In particular, moving a head from +one encoder to another seems to trigger this quite often. GV100+ is very +picky about having a LUT in most scenarios, so this causes the display +engine to hang with the following error code: + +disp: chid 1 stat 00005080 reason 5 [INVALID_STATE] mthd 0200 data +00000001 code 0000002d) + +So, fix this by always re-programming the LUT if we're clearing it in a +state where the wndw is still visible, and has a XLUT handle programmed. + +Signed-off-by: Lyude Paul +Fixes: facaed62b4cb ("drm/nouveau/kms/gv100: initial support") +Cc: # v4.18+ +Signed-off-by: Ben Skeggs +Acked-by: Petr Tesarik +--- + drivers/gpu/drm/nouveau/dispnv50/wndw.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/drivers/gpu/drm/nouveau/dispnv50/wndw.c ++++ b/drivers/gpu/drm/nouveau/dispnv50/wndw.c +@@ -408,6 +408,8 @@ nv50_wndw_atomic_check(struct drm_plane + asyw->clr.ntfy = armw->ntfy.handle != 0; + asyw->clr.sema = armw->sema.handle != 0; + asyw->clr.xlut = armw->xlut.handle != 0; ++ if (asyw->clr.xlut && asyw->visible) ++ asyw->set.xlut = asyw->xlut.handle != 0; + if (wndw->func->image_clr) + asyw->clr.image = armw->image.handle[0] != 0; + } diff --git a/patches.suse/drm-remove-the-newline-for-CRC-source-name.patch b/patches.suse/drm-remove-the-newline-for-CRC-source-name.patch new file mode 100644 index 0000000..ee97e6f --- /dev/null +++ b/patches.suse/drm-remove-the-newline-for-CRC-source-name.patch @@ -0,0 +1,43 @@ +From 72a848f5c46bab4c921edc9cbffd1ab273b2be17 Mon Sep 17 00:00:00 2001 +From: Dingchen Zhang +Date: Mon, 10 Jun 2019 09:47:51 -0400 +Subject: [PATCH] drm: remove the newline for CRC source name. +Git-commit: 72a848f5c46bab4c921edc9cbffd1ab273b2be17 +Patch-mainline: v5.6-rc1 +References: bsc#1051510 + +userspace may transfer a newline, and this terminating newline +is replaced by a '\0' to avoid followup issues. + +'len-1' is the index to replace the newline of CRC source name. + +V3: typo fix (Sam) + +V2: update patch subject, body and format. (Sam) + +Cc: Leo Li +Cc: Harry Wentland +Cc: Sam Ravnborg +Signed-off-by: Dingchen Zhang +Reviewed-by: Sam Ravnborg +Signed-off-by: Alex Deucher +Link: https://patchwork.freedesktop.org/patch/msgid/20190610134751.14356-1-dingchen.zhang@amd.com +Acked-by: Takashi Iwai + +--- + drivers/gpu/drm/drm_debugfs_crc.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/gpu/drm/drm_debugfs_crc.c ++++ b/drivers/gpu/drm/drm_debugfs_crc.c +@@ -101,8 +101,8 @@ static ssize_t crc_control_write(struct + if (IS_ERR(source)) + return PTR_ERR(source); + +- if (source[len] == '\n') +- source[len] = '\0'; ++ if (source[len - 1] == '\n') ++ source[len - 1] = '\0'; + + spin_lock_irq(&crc->lock); + diff --git a/patches.suse/drm-sun4i-de2-de3-remove-unsupported-vi-layer-formats b/patches.suse/drm-sun4i-de2-de3-remove-unsupported-vi-layer-formats new file mode 100644 index 0000000..351ccab --- /dev/null +++ b/patches.suse/drm-sun4i-de2-de3-remove-unsupported-vi-layer-formats @@ -0,0 +1,63 @@ +From: Jernej Skrabec +Date: Mon, 24 Feb 2020 18:38:55 +0100 +Subject: drm/sun4i: de2/de3: Remove unsupported VI layer formats +Git-commit: a4769905f0ae32cae4f096f646ab03b8b4794c74 +Patch-mainline: v5.6-rc5 +References: git-fixes + +YUV444 and YVU444 are planar formats, but HW format RGB888 is packed. +This means that those two mappings were never correct. Remove them. + +Fixes: 60a3dcf96aa8 ("drm/sun4i: Add DE2 definitions for YUV formats") +Acked-by: Maxime Ripard +Signed-off-by: Jernej Skrabec +Link: https://patchwork.freedesktop.org/patch/msgid/20200224173901.174016-2-jernej.skrabec@siol.net + +Acked-by: Petr Tesarik +--- + drivers/gpu/drm/sun4i/sun8i_mixer.c | 12 ------------ + drivers/gpu/drm/sun4i/sun8i_vi_layer.c | 2 -- + 2 files changed, 14 deletions(-) + +--- a/drivers/gpu/drm/sun4i/sun8i_mixer.c ++++ b/drivers/gpu/drm/sun4i/sun8i_mixer.c +@@ -201,12 +201,6 @@ static const struct de2_fmt_info de2_for + .csc = SUN8I_CSC_MODE_YUV2RGB, + }, + { +- .drm_fmt = DRM_FORMAT_YUV444, +- .de2_fmt = SUN8I_MIXER_FBFMT_RGB888, +- .rgb = true, +- .csc = SUN8I_CSC_MODE_YUV2RGB, +- }, +- { + .drm_fmt = DRM_FORMAT_YUV422, + .de2_fmt = SUN8I_MIXER_FBFMT_YUV422, + .rgb = false, +@@ -225,12 +219,6 @@ static const struct de2_fmt_info de2_for + .csc = SUN8I_CSC_MODE_YUV2RGB, + }, + { +- .drm_fmt = DRM_FORMAT_YVU444, +- .de2_fmt = SUN8I_MIXER_FBFMT_RGB888, +- .rgb = true, +- .csc = SUN8I_CSC_MODE_YVU2RGB, +- }, +- { + .drm_fmt = DRM_FORMAT_YVU422, + .de2_fmt = SUN8I_MIXER_FBFMT_YUV422, + .rgb = false, +--- a/drivers/gpu/drm/sun4i/sun8i_vi_layer.c ++++ b/drivers/gpu/drm/sun4i/sun8i_vi_layer.c +@@ -363,11 +363,9 @@ static const u32 sun8i_vi_layer_formats[ + DRM_FORMAT_YUV411, + DRM_FORMAT_YUV420, + DRM_FORMAT_YUV422, +- DRM_FORMAT_YUV444, + DRM_FORMAT_YVU411, + DRM_FORMAT_YVU420, + DRM_FORMAT_YVU422, +- DRM_FORMAT_YVU444, + }; + + struct sun8i_vi_layer *sun8i_vi_layer_init_one(struct drm_device *drm, diff --git a/patches.suse/drm-sun4i-dsi-Use-NULL-to-signify-no-panel.patch b/patches.suse/drm-sun4i-dsi-Use-NULL-to-signify-no-panel.patch new file mode 100644 index 0000000..2d85657 --- /dev/null +++ b/patches.suse/drm-sun4i-dsi-Use-NULL-to-signify-no-panel.patch @@ -0,0 +1,72 @@ +From 0e4e3fb4901d19f49e5c0a582f383b10dda8d1c5 Mon Sep 17 00:00:00 2001 +From: Samuel Holland +Date: Tue, 11 Feb 2020 01:28:56 -0600 +Subject: [PATCH] drm/sun4i: dsi: Use NULL to signify "no panel" +Git-commit: 0e4e3fb4901d19f49e5c0a582f383b10dda8d1c5 +Patch-mainline: v5.7-rc1 +References: bsc#1111666 + +The continued use of an ERR_PTR to signify "no panel" outside of +sun6i_dsi_attach is confusing because it is a double negative. Because +the connector always reports itself as connected, there is also the +possibility of sending an ERR_PTR to drm_panel_get_modes(), which would +crash. + +Solve both of these by only storing the panel pointer if it is valid. + +Fixes: 133add5b5ad4 ("drm/sun4i: Add Allwinner A31 MIPI-DSI controller support") +Signed-off-by: Samuel Holland +Signed-off-by: Maxime Ripard +Link: https://patchwork.freedesktop.org/patch/msgid/20200211072858.30784-2-samuel@sholland.org +Acked-by: Takashi Iwai + +--- + drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c | 14 ++++++++------ + 1 file changed, 8 insertions(+), 6 deletions(-) + +--- a/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c ++++ b/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c +@@ -643,7 +643,7 @@ static void sun6i_dsi_encoder_enable(str + sun6i_dphy_init(dsi->dphy, device->lanes); + sun6i_dphy_power_on(dsi->dphy, device->lanes); + +- if (!IS_ERR(dsi->panel)) ++ if (dsi->panel) + drm_panel_prepare(dsi->panel); + + /* +@@ -658,7 +658,7 @@ static void sun6i_dsi_encoder_enable(str + * ordering on the panels I've tested it with, so I guess this + * will do for now, until that IP is better understood. + */ +- if (!IS_ERR(dsi->panel)) ++ if (dsi->panel) + drm_panel_enable(dsi->panel); + + sun6i_dsi_start(dsi, DSI_START_HSC); +@@ -674,7 +674,7 @@ static void sun6i_dsi_encoder_disable(st + + DRM_DEBUG_DRIVER("Disabling DSI output\n"); + +- if (!IS_ERR(dsi->panel)) { ++ if (dsi->panel) { + drm_panel_disable(dsi->panel); + drm_panel_unprepare(dsi->panel); + } +@@ -836,11 +836,13 @@ static int sun6i_dsi_attach(struct mipi_ + struct mipi_dsi_device *device) + { + struct sun6i_dsi *dsi = host_to_sun6i_dsi(host); ++ struct drm_panel *panel = of_drm_find_panel(device->dev.of_node); + ++ if (IS_ERR(panel)) ++ return PTR_ERR(panel); ++ ++ dsi->panel = panel; + dsi->device = device; +- dsi->panel = of_drm_find_panel(device->dev.of_node); +- if (IS_ERR(dsi->panel)) +- return PTR_ERR(dsi->panel); + + dev_info(host->dev, "Attached device %s\n", device->name); + diff --git a/patches.suse/drm-sun4i-fix-de2-vi-layer-format-support b/patches.suse/drm-sun4i-fix-de2-vi-layer-format-support new file mode 100644 index 0000000..084c8ae --- /dev/null +++ b/patches.suse/drm-sun4i-fix-de2-vi-layer-format-support @@ -0,0 +1,166 @@ +From: Jernej Skrabec +Date: Mon, 24 Feb 2020 18:38:57 +0100 +Subject: drm/sun4i: Fix DE2 VI layer format support +Git-commit: 20896ef137340e9426cf322606f764452f5eb960 +Patch-mainline: v5.6-rc5 +References: git-fixes + +DE2 VI layer doesn't support blending which means alpha channel is +ignored. Replace all formats with alpha with "don't care" (X) channel. + +Fixes: 7480ba4d7571 ("drm/sun4i: Add support for DE2 VI planes") +Acked-by: Maxime Ripard +Signed-off-by: Jernej Skrabec +Link: https://patchwork.freedesktop.org/patch/msgid/20200224173901.174016-4-jernej.skrabec@siol.net + +Acked-by: Petr Tesarik +--- + drivers/gpu/drm/sun4i/sun8i_mixer.c | 56 +++++++++++++++++++++++++++++++++ + drivers/gpu/drm/sun4i/sun8i_vi_layer.c | 22 ++++++------ + 2 files changed, 67 insertions(+), 11 deletions(-) + +--- a/drivers/gpu/drm/sun4i/sun8i_mixer.c ++++ b/drivers/gpu/drm/sun4i/sun8i_mixer.c +@@ -111,46 +111,102 @@ static const struct de2_fmt_info de2_for + .csc = SUN8I_CSC_MODE_OFF, + }, + { ++ /* for DE2 VI layer which ignores alpha */ ++ .drm_fmt = DRM_FORMAT_XRGB4444, ++ .de2_fmt = SUN8I_MIXER_FBFMT_ARGB4444, ++ .rgb = true, ++ .csc = SUN8I_CSC_MODE_OFF, ++ }, ++ { + .drm_fmt = DRM_FORMAT_ABGR4444, + .de2_fmt = SUN8I_MIXER_FBFMT_ABGR4444, + .rgb = true, + .csc = SUN8I_CSC_MODE_OFF, + }, + { ++ /* for DE2 VI layer which ignores alpha */ ++ .drm_fmt = DRM_FORMAT_XBGR4444, ++ .de2_fmt = SUN8I_MIXER_FBFMT_ABGR4444, ++ .rgb = true, ++ .csc = SUN8I_CSC_MODE_OFF, ++ }, ++ { + .drm_fmt = DRM_FORMAT_RGBA4444, + .de2_fmt = SUN8I_MIXER_FBFMT_RGBA4444, + .rgb = true, + .csc = SUN8I_CSC_MODE_OFF, + }, + { ++ /* for DE2 VI layer which ignores alpha */ ++ .drm_fmt = DRM_FORMAT_RGBX4444, ++ .de2_fmt = SUN8I_MIXER_FBFMT_RGBA4444, ++ .rgb = true, ++ .csc = SUN8I_CSC_MODE_OFF, ++ }, ++ { + .drm_fmt = DRM_FORMAT_BGRA4444, + .de2_fmt = SUN8I_MIXER_FBFMT_BGRA4444, + .rgb = true, + .csc = SUN8I_CSC_MODE_OFF, + }, + { ++ /* for DE2 VI layer which ignores alpha */ ++ .drm_fmt = DRM_FORMAT_BGRX4444, ++ .de2_fmt = SUN8I_MIXER_FBFMT_BGRA4444, ++ .rgb = true, ++ .csc = SUN8I_CSC_MODE_OFF, ++ }, ++ { + .drm_fmt = DRM_FORMAT_ARGB1555, + .de2_fmt = SUN8I_MIXER_FBFMT_ARGB1555, + .rgb = true, + .csc = SUN8I_CSC_MODE_OFF, + }, + { ++ /* for DE2 VI layer which ignores alpha */ ++ .drm_fmt = DRM_FORMAT_XRGB1555, ++ .de2_fmt = SUN8I_MIXER_FBFMT_ARGB1555, ++ .rgb = true, ++ .csc = SUN8I_CSC_MODE_OFF, ++ }, ++ { + .drm_fmt = DRM_FORMAT_ABGR1555, + .de2_fmt = SUN8I_MIXER_FBFMT_ABGR1555, + .rgb = true, + .csc = SUN8I_CSC_MODE_OFF, + }, + { ++ /* for DE2 VI layer which ignores alpha */ ++ .drm_fmt = DRM_FORMAT_XBGR1555, ++ .de2_fmt = SUN8I_MIXER_FBFMT_ABGR1555, ++ .rgb = true, ++ .csc = SUN8I_CSC_MODE_OFF, ++ }, ++ { + .drm_fmt = DRM_FORMAT_RGBA5551, + .de2_fmt = SUN8I_MIXER_FBFMT_RGBA5551, + .rgb = true, + .csc = SUN8I_CSC_MODE_OFF, + }, + { ++ /* for DE2 VI layer which ignores alpha */ ++ .drm_fmt = DRM_FORMAT_RGBX5551, ++ .de2_fmt = SUN8I_MIXER_FBFMT_RGBA5551, ++ .rgb = true, ++ .csc = SUN8I_CSC_MODE_OFF, ++ }, ++ { + .drm_fmt = DRM_FORMAT_BGRA5551, + .de2_fmt = SUN8I_MIXER_FBFMT_BGRA5551, + .rgb = true, + .csc = SUN8I_CSC_MODE_OFF, ++ }, ++ { ++ /* for DE2 VI layer which ignores alpha */ ++ .drm_fmt = DRM_FORMAT_BGRX5551, ++ .de2_fmt = SUN8I_MIXER_FBFMT_BGRA5551, ++ .rgb = true, ++ .csc = SUN8I_CSC_MODE_OFF, + }, + { + .drm_fmt = DRM_FORMAT_UYVY, +--- a/drivers/gpu/drm/sun4i/sun8i_vi_layer.c ++++ b/drivers/gpu/drm/sun4i/sun8i_vi_layer.c +@@ -330,26 +330,26 @@ static const struct drm_plane_funcs sun8 + }; + + /* +- * While all RGB formats are supported, VI planes don't support +- * alpha blending, so there is no point having formats with alpha +- * channel if their opaque analog exist. ++ * While DE2 VI layer supports same RGB formats as UI layer, alpha ++ * channel is ignored. This structure lists all unique variants ++ * where alpha channel is replaced with "don't care" (X) channel. + */ + static const u32 sun8i_vi_layer_formats[] = { +- DRM_FORMAT_ABGR1555, +- DRM_FORMAT_ABGR4444, +- DRM_FORMAT_ARGB1555, +- DRM_FORMAT_ARGB4444, + DRM_FORMAT_BGR565, + DRM_FORMAT_BGR888, +- DRM_FORMAT_BGRA5551, +- DRM_FORMAT_BGRA4444, ++ DRM_FORMAT_BGRX4444, ++ DRM_FORMAT_BGRX5551, + DRM_FORMAT_BGRX8888, + DRM_FORMAT_RGB565, + DRM_FORMAT_RGB888, +- DRM_FORMAT_RGBA4444, +- DRM_FORMAT_RGBA5551, ++ DRM_FORMAT_RGBX4444, ++ DRM_FORMAT_RGBX5551, + DRM_FORMAT_RGBX8888, ++ DRM_FORMAT_XBGR1555, ++ DRM_FORMAT_XBGR4444, + DRM_FORMAT_XBGR8888, ++ DRM_FORMAT_XRGB1555, ++ DRM_FORMAT_XRGB4444, + DRM_FORMAT_XRGB8888, + + DRM_FORMAT_NV16, diff --git a/patches.suse/drm-v3d-Replace-wait_for-macros-to-remove-use-of-msl.patch b/patches.suse/drm-v3d-Replace-wait_for-macros-to-remove-use-of-msl.patch new file mode 100644 index 0000000..a4908da --- /dev/null +++ b/patches.suse/drm-v3d-Replace-wait_for-macros-to-remove-use-of-msl.patch @@ -0,0 +1,93 @@ +From 9daee6141cc9c75b09659b02b1cb9eeb2f5e16cc Mon Sep 17 00:00:00 2001 +From: James Hughes +Date: Mon, 17 Feb 2020 15:31:45 +0000 +Subject: [PATCH] drm/v3d: Replace wait_for macros to remove use of msleep +Git-commit: 9daee6141cc9c75b09659b02b1cb9eeb2f5e16cc +Patch-mainline: v5.7-rc1 +References: bsc#1111666 + +The wait_for macro's for Broadcom V3D driver used msleep, which is +inappropriate due to its inaccuracy at low values (minimum wait time +is about 30ms on the Raspberry Pi). This sleep was triggering in +v3d_clean_caches(), causing us to only be able to dispatch ~33 compute +jobs per second. + +This patch replaces the macro with the one from the Intel i915 version +which uses usleep_range to provide more accurate waits. + +V2: Split from the vc4 patch so that we can confidently apply to stable (by anholt) + +Signed-off-by: James Hughes +Signed-off-by: Eric Anholt +Link: https://patchwork.freedesktop.org/patch/msgid/20200217153145.13780-1-james.hughes@raspberrypi.com +Link: https://github.com/raspberrypi/linux/issues/3460 +Fixes: 57692c94dcbe ("drm/v3d: Introduce a new DRM driver for Broadcom V3D V3.x+") +Acked-by: Takashi Iwai + +--- + drivers/gpu/drm/v3d/v3d_drv.h | 41 ++++++++++++++++++++++++++++------------- + 1 file changed, 28 insertions(+), 13 deletions(-) + +diff --git a/drivers/gpu/drm/v3d/v3d_drv.h b/drivers/gpu/drm/v3d/v3d_drv.h +index 9a35c555ec52..ac2603334587 100644 +--- a/drivers/gpu/drm/v3d/v3d_drv.h ++++ b/drivers/gpu/drm/v3d/v3d_drv.h +@@ -254,27 +254,42 @@ struct v3d_csd_job { + }; + + /** +- * _wait_for - magic (register) wait macro ++ * __wait_for - magic wait macro + * +- * Does the right thing for modeset paths when run under kdgb or similar atomic +- * contexts. Note that it's important that we check the condition again after +- * having timed out, since the timeout could be due to preemption or similar and +- * we've never had a chance to check the condition before the timeout. ++ * Macro to help avoid open coding check/wait/timeout patterns. Note that it's ++ * important that we check the condition again after having timed out, since the ++ * timeout could be due to preemption or similar and we've never had a chance to ++ * check the condition before the timeout. + */ +-#define wait_for(COND, MS) ({ \ +- unsigned long timeout__ = jiffies + msecs_to_jiffies(MS) + 1; \ +- int ret__ = 0; \ +- while (!(COND)) { \ +- if (time_after(jiffies, timeout__)) { \ +- if (!(COND)) \ +- ret__ = -ETIMEDOUT; \ ++#define __wait_for(OP, COND, US, Wmin, Wmax) ({ \ ++ const ktime_t end__ = ktime_add_ns(ktime_get_raw(), 1000ll * (US)); \ ++ long wait__ = (Wmin); /* recommended min for usleep is 10 us */ \ ++ int ret__; \ ++ might_sleep(); \ ++ for (;;) { \ ++ const bool expired__ = ktime_after(ktime_get_raw(), end__); \ ++ OP; \ ++ /* Guarantee COND check prior to timeout */ \ ++ barrier(); \ ++ if (COND) { \ ++ ret__ = 0; \ + break; \ + } \ +- msleep(1); \ ++ if (expired__) { \ ++ ret__ = -ETIMEDOUT; \ ++ break; \ ++ } \ ++ usleep_range(wait__, wait__ * 2); \ ++ if (wait__ < (Wmax)) \ ++ wait__ <<= 1; \ + } \ + ret__; \ + }) + ++#define _wait_for(COND, US, Wmin, Wmax) __wait_for(, (COND), (US), (Wmin), \ ++ (Wmax)) ++#define wait_for(COND, MS) _wait_for((COND), (MS) * 1000, 10, 1000) ++ + static inline unsigned long nsecs_to_jiffies_timeout(const u64 n) + { + /* nsecs_to_jiffies64() does not guard against overflow */ +-- +2.16.4 + diff --git a/patches.suse/drm-vc4-fix-hdmi-mode-validation.patch b/patches.suse/drm-vc4-fix-hdmi-mode-validation.patch new file mode 100644 index 0000000..7c6844e --- /dev/null +++ b/patches.suse/drm-vc4-fix-hdmi-mode-validation.patch @@ -0,0 +1,57 @@ +From: Nicolas Saenz Julienne +Date: Thu, 26 Mar 2020 13:20:01 +0100 +Subject: drm/vc4: Fix HDMI mode validation +Git-repo: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git +Git-commit: b1e7396a1d0e6af6806337fdaaa44098d6b3343c +Patch-mainline: Queued in subsystem maintainer repo +References: git-fixes + +Current mode validation impedes setting up some video modes which should +be supported otherwise. Namely 1920x1200@60Hz. + +Fix this by lowering the minimum HDMI state machine clock to pixel clock +ratio allowed. + +Fixes: 32e823c63e90 ("drm/vc4: Reject HDMI modes with too high of clocks.") +Reported-by: Stefan Wahren +Suggested-by: Dave Stevenson +Signed-off-by: Nicolas Saenz Julienne +Signed-off-by: Maxime Ripard +Link: https://patchwork.freedesktop.org/patch/msgid/20200326122001.22215-1-nsaenzjulienne@suse.de +--- + drivers/gpu/drm/vc4/vc4_hdmi.c | 20 ++++++++++++++++---- + 1 file changed, 16 insertions(+), 4 deletions(-) + +diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c +index cea18dc15f77..340719238753 100644 +--- a/drivers/gpu/drm/vc4/vc4_hdmi.c ++++ b/drivers/gpu/drm/vc4/vc4_hdmi.c +@@ -681,11 +681,23 @@ static enum drm_mode_status + vc4_hdmi_encoder_mode_valid(struct drm_encoder *crtc, + const struct drm_display_mode *mode) + { +- /* HSM clock must be 108% of the pixel clock. Additionally, +- * the AXI clock needs to be at least 25% of pixel clock, but +- * HSM ends up being the limiting factor. ++ /* ++ * As stated in RPi's vc4 firmware "HDMI state machine (HSM) clock must ++ * be faster than pixel clock, infinitesimally faster, tested in ++ * simulation. Otherwise, exact value is unimportant for HDMI ++ * operation." This conflicts with bcm2835's vc4 documentation, which ++ * states HSM's clock has to be at least 108% of the pixel clock. ++ * ++ * Real life tests reveal that vc4's firmware statement holds up, and ++ * users are able to use pixel clocks closer to HSM's, namely for ++ * 1920x1200@60Hz. So it was decided to have leave a 1% margin between ++ * both clocks. Which, for RPi0-3 implies a maximum pixel clock of ++ * 162MHz. ++ * ++ * Additionally, the AXI clock needs to be at least 25% of ++ * pixel clock, but HSM ends up being the limiting factor. + */ +- if (mode->clock > HSM_CLOCK_FREQ / (1000 * 108 / 100)) ++ if (mode->clock > HSM_CLOCK_FREQ / (1000 * 101 / 100)) + return MODE_CLOCK_HIGH; + + return MODE_OK; + diff --git a/patches.suse/dt-bindings-allow-up-to-four-clocks-for-orion-mdio.patch b/patches.suse/dt-bindings-allow-up-to-four-clocks-for-orion-mdio.patch new file mode 100644 index 0000000..67503d6 --- /dev/null +++ b/patches.suse/dt-bindings-allow-up-to-four-clocks-for-orion-mdio.patch @@ -0,0 +1,38 @@ +From 80785f5a22e9073e2ded5958feb7f220e066d17b Mon Sep 17 00:00:00 2001 +From: Josua Mayer +Date: Tue, 9 Jul 2019 15:00:58 +0200 +Subject: [PATCH] dt-bindings: allow up to four clocks for orion-mdio +Git-commit: 80785f5a22e9073e2ded5958feb7f220e066d17b +Patch-mainline: v5.3-rc1 +References: bsc#1051510 + +Armada 8040 needs four clocks to be enabled for MDIO accesses to work. +Update the binding to allow the extra clock to be specified. + +Cc: stable@vger.kernel.org +Fixes: 6d6a331f44a1 ("dt-bindings: allow up to three clocks for orion-mdio") +Reviewed-by: Andrew Lunn +Signed-off-by: Josua Mayer +Signed-off-by: David S. Miller +Acked-by: Takashi Iwai + +--- + Documentation/devicetree/bindings/net/marvell-orion-mdio.txt | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/Documentation/devicetree/bindings/net/marvell-orion-mdio.txt b/Documentation/devicetree/bindings/net/marvell-orion-mdio.txt +index 42cd81090a2c..3f3cfc1d8d4d 100644 +--- a/Documentation/devicetree/bindings/net/marvell-orion-mdio.txt ++++ b/Documentation/devicetree/bindings/net/marvell-orion-mdio.txt +@@ -16,7 +16,7 @@ Required properties: + + Optional properties: + - interrupts: interrupt line number for the SMI error/done interrupt +-- clocks: phandle for up to three required clocks for the MDIO instance ++- clocks: phandle for up to four required clocks for the MDIO instance + + The child nodes of the MDIO driver are the individual PHY devices + connected to this MDIO bus. They must have a "reg" property given the +-- +2.16.4 + diff --git a/patches.suse/edac-ghes-fix-locking-and-memory-barrier-issues.patch b/patches.suse/edac-ghes-fix-locking-and-memory-barrier-issues.patch index f378723..8ae9e4a 100644 --- a/patches.suse/edac-ghes-fix-locking-and-memory-barrier-issues.patch +++ b/patches.suse/edac-ghes-fix-locking-and-memory-barrier-issues.patch @@ -139,12 +139,12 @@ Link: https://lkml.kernel.org/r/20191105200732.3053-1-rrichter@marvell.com struct edac_mc_layer layers[1]; struct ghes_edac_dimm_fill dimm_fill; + unsigned long flags; - int idx; + int idx = -1; - /* Check if safe to enable on this system */ -@@ -451,11 +465,14 @@ int ghes_edac_register(struct ghes *ghes - if (!force_load && idx < 0) - return -ENODEV; + if (IS_ENABLED(CONFIG_X86)) { +@@ -455,11 +469,14 @@ int ghes_edac_register(struct ghes *ghes + idx = 0; + } + /* finish another registration/unregistration instance first */ + mutex_lock(&ghes_reg_mutex); @@ -159,7 +159,7 @@ Link: https://lkml.kernel.org/r/20191105200732.3053-1-rrichter@marvell.com /* Get the number of DIMMs */ dmi_walk(ghes_edac_count_dimms, &num_dimm); -@@ -473,12 +490,13 @@ int ghes_edac_register(struct ghes *ghes +@@ -477,12 +494,13 @@ int ghes_edac_register(struct ghes *ghes mci = edac_mc_alloc(0, ARRAY_SIZE(layers), layers, sizeof(struct ghes_edac_pvt)); if (!mci) { pr_info("Can't allocate memory for EDAC data\n"); @@ -177,7 +177,7 @@ Link: https://lkml.kernel.org/r/20191105200732.3053-1-rrichter@marvell.com mci->pdev = dev; mci->mtype_cap = MEM_FLAG_EMPTY; -@@ -521,20 +539,47 @@ int ghes_edac_register(struct ghes *ghes +@@ -525,20 +543,47 @@ int ghes_edac_register(struct ghes *ghes if (rc < 0) { pr_info("Can't register at EDAC core\n"); edac_mc_free(mci); diff --git a/patches.suse/edac-mc-fix-use-after-free-and-memleaks-during-device-removal.patch b/patches.suse/edac-mc-fix-use-after-free-and-memleaks-during-device-removal.patch new file mode 100644 index 0000000..a8d6efd --- /dev/null +++ b/patches.suse/edac-mc-fix-use-after-free-and-memleaks-during-device-removal.patch @@ -0,0 +1,140 @@ +From: Robert Richter +Date: Wed, 12 Feb 2020 18:25:18 +0100 +Subject: EDAC/mc: Fix use-after-free and memleaks during device removal +Git-commit: 216aa145aaf379a50b17afc812db71d893bd6683 +Patch-mainline: v5.6-rc2 +References: bsc#1114279 + +A test kernel with the options DEBUG_TEST_DRIVER_REMOVE, KASAN and +DEBUG_KMEMLEAK set, revealed several issues when removing an mci device: + +1) Use-after-free: + +On 27.11.19 17:07:33, John Garry wrote: +> [ 22.104498] BUG: KASAN: use-after-free in +> edac_remove_sysfs_mci_device+0x148/0x180 + +The use-after-free is caused by the mci_for_each_dimm() macro called in +edac_remove_sysfs_mci_device(). The iterator was introduced with + + c498afaf7df8 ("EDAC: Introduce an mci_for_each_dimm() iterator"). + +The iterator loop calls device_unregister(&dimm->dev), which removes +the sysfs entry of the device, but also frees the dimm struct in +dimm_attr_release(). When incrementing the loop in mci_for_each_dimm(), +the dimm struct is accessed again, after having been freed already. + +The fix is to free all the mci device's subsequent dimm and csrow +objects at a later point, in _edac_mc_free(), when the mci device itself +is being freed. + +This keeps the data structures intact and the mci device can be +fully used until its removal. The change allows the safe usage of +mci_for_each_dimm() to release dimm devices from sysfs. + +2) Memory leaks: + +Following memory leaks have been detected: + + # grep edac /sys/kernel/debug/kmemleak | sort | uniq -c + 1 [<000000003c0f58f9>] edac_mc_alloc+0x3bc/0x9d0 # mci->csrows + 16 [<00000000bb932dc0>] edac_mc_alloc+0x49c/0x9d0 # csr->channels + 16 [<00000000e2734dba>] edac_mc_alloc+0x518/0x9d0 # csr->channels[chn] + 1 [<00000000eb040168>] edac_mc_alloc+0x5c8/0x9d0 # mci->dimms + 34 [<00000000ef737c29>] ghes_edac_register+0x1c8/0x3f8 # see edac_mc_alloc() + +All leaks are from memory allocated by edac_mc_alloc(). + +Note: The test above shows that edac_mc_alloc() was called here from +ghes_edac_register(), thus both functions show up in the stack trace +but the module causing the leaks is edac_mc. The comments with the data +structures involved were made manually by analyzing the objdump. + +The data structures listed above and created by edac_mc_alloc() are +not properly removed during device removal, which is done in +edac_mc_free(). + +There are two paths implemented to remove the device depending on device +registration, _edac_mc_free() is called if the device is not registered +and edac_unregister_sysfs() otherwise. + +The implemenations differ. For the sysfs case, the mci device removal +lacks the removal of subsequent data structures (csrows, channels, +dimms). This causes the memory leaks (see mci_attr_release()). + + [ bp: Massage commit message. ] + +Fixes: c498afaf7df8 ("EDAC: Introduce an mci_for_each_dimm() iterator") +Fixes: faa2ad09c01c ("edac_mc: edac_mc_free() cannot assume mem_ctl_info is registered in sysfs.") +Fixes: 7a623c039075 ("edac: rewrite the sysfs code to use struct device") +Reported-by: John Garry +Signed-off-by: Robert Richter +Signed-off-by: Borislav Petkov +Tested-by: John Garry +Cc: +Link: https://lkml.kernel.org/r/20200212120340.4764-3-rrichter@marvell.com +--- + drivers/edac/edac_mc.c | 12 +++--------- + drivers/edac/edac_mc_sysfs.c | 15 +++------------ + 2 files changed, 6 insertions(+), 21 deletions(-) + +--- a/drivers/edac/edac_mc.c ++++ b/drivers/edac/edac_mc.c +@@ -506,16 +506,10 @@ void edac_mc_free(struct mem_ctl_info *m + { + edac_dbg(1, "\n"); + +- /* If we're not yet registered with sysfs free only what was allocated +- * in edac_mc_alloc(). +- */ +- if (!device_is_registered(&mci->dev)) { +- _edac_mc_free(mci); +- return; +- } ++ if (device_is_registered(&mci->dev)) ++ edac_unregister_sysfs(mci); + +- /* the mci instance is freed here, when the sysfs object is dropped */ +- edac_unregister_sysfs(mci); ++ _edac_mc_free(mci); + } + EXPORT_SYMBOL_GPL(edac_mc_free); + +--- a/drivers/edac/edac_mc_sysfs.c ++++ b/drivers/edac/edac_mc_sysfs.c +@@ -276,10 +276,7 @@ static const struct attribute_group *csr + + static void csrow_attr_release(struct device *dev) + { +- struct csrow_info *csrow = container_of(dev, struct csrow_info, dev); +- +- edac_dbg(1, "Releasing csrow device %s\n", dev_name(dev)); +- kfree(csrow); ++ /* release device with _edac_mc_free() */ + } + + static struct device_type csrow_attr_type = { +@@ -616,10 +613,7 @@ static const struct attribute_group *dim + + static void dimm_attr_release(struct device *dev) + { +- struct dimm_info *dimm = container_of(dev, struct dimm_info, dev); +- +- edac_dbg(1, "Releasing dimm device %s\n", dev_name(dev)); +- kfree(dimm); ++ /* release device with _edac_mc_free() */ + } + + static struct device_type dimm_attr_type = { +@@ -892,10 +886,7 @@ static const struct attribute_group *mci + + static void mci_attr_release(struct device *dev) + { +- struct mem_ctl_info *mci = container_of(dev, struct mem_ctl_info, dev); +- +- edac_dbg(1, "Releasing csrow device %s\n", dev_name(dev)); +- kfree(mci); ++ /* release device with _edac_mc_free() */ + } + + static struct device_type mci_attr_type = { diff --git a/patches.suse/efi-Don-t-attempt-to-map-RCI2-config-table-if-it-doe.patch b/patches.suse/efi-Don-t-attempt-to-map-RCI2-config-table-if-it-doe.patch new file mode 100644 index 0000000..874ed7f --- /dev/null +++ b/patches.suse/efi-Don-t-attempt-to-map-RCI2-config-table-if-it-doe.patch @@ -0,0 +1,70 @@ +From: Ard Biesheuvel +Date: Tue, 10 Dec 2019 10:09:45 +0100 +Subject: efi: Don't attempt to map RCI2 config table if it doesn't exist +Patch-mainline: v5.5-rc3 +Git-commit: a470552ee8965da0fe6fd4df0aa39c4cda652c7c +References: jsc#ECO-366, bsc#1168367 + +Commit: + + 1c5fecb61255aa12 ("efi: Export Runtime Configuration Interface table to sysfs") + +... added support for a Dell specific UEFI configuration table, but +failed to take into account that mapping the table should not be +attempted unless the table actually exists. If it doesn't exist, +the code usually fails silently unless pr_debug() prints are +enabled. However, on 32-bit PAE x86, the splat below is produced due +to the attempt to map the placeholder value EFI_INVALID_TABLE_ADDR +which we use for non-existing UEFI configuration tables, and which +equals ULONG_MAX. + + memremap attempted on mixed range 0x00000000ffffffff size: 0x1e + WARNING: CPU: 1 PID: 1 at kernel/iomem.c:81 memremap+0x1a3/0x1c0 + Modules linked in: + CPU: 1 PID: 1 Comm: swapper/0 Not tainted 5.4.2-smp-mine #1 + Hardware name: Hewlett-Packard HP Z400 Workstation/0B4Ch, BIOS 786G3 v03.61 03/05/2018 + EIP: memremap+0x1a3/0x1c0 + ... + Call Trace: + ? map_properties+0x473/0x473 + ? efi_rci2_sysfs_init+0x2c/0x154 + ? map_properties+0x473/0x473 + ? do_one_initcall+0x49/0x1d4 + ? parse_args+0x1e8/0x2a0 + ? do_early_param+0x7a/0x7a + ? kernel_init_freeable+0x139/0x1c2 + ? rest_init+0x8e/0x8e + ? kernel_init+0xd/0xf2 + ? ret_from_fork+0x2e/0x38 + +Fix this by checking whether the table exists before attempting to map it. + +Reported-by: Richard Narron +Tested-by: Richard Narron +Signed-off-by: Ard Biesheuvel +Cc: linux-efi@vger.kernel.org +Fixes: 1c5fecb61255aa12 ("efi: Export Runtime Configuration Interface table to sysfs") +Link: https://lkml.kernel.org/r/20191210090945.11501-2-ardb@kernel.org +Signed-off-by: Ingo Molnar +Acked-by: Lee, Chun-Yi +--- + drivers/firmware/efi/rci2-table.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/firmware/efi/rci2-table.c b/drivers/firmware/efi/rci2-table.c +index 76b0c354a027..de1a9a1f9f14 100644 +--- a/drivers/firmware/efi/rci2-table.c ++++ b/drivers/firmware/efi/rci2-table.c +@@ -81,6 +81,9 @@ static int __init efi_rci2_sysfs_init(void) + struct kobject *tables_kobj; + int ret = -ENOMEM; + ++ if (rci2_table_phys == EFI_INVALID_TABLE_ADDR) ++ return 0; ++ + rci2_base = memremap(rci2_table_phys, + sizeof(struct rci2_table_global_hdr), + MEMREMAP_WB); +-- +2.16.4 + diff --git a/patches.suse/efi-Export-Runtime-Configuration-Interface-table-to--1c5fecb6.patch b/patches.suse/efi-Export-Runtime-Configuration-Interface-table-to--1c5fecb6.patch new file mode 100644 index 0000000..2285e07 --- /dev/null +++ b/patches.suse/efi-Export-Runtime-Configuration-Interface-table-to--1c5fecb6.patch @@ -0,0 +1,275 @@ +From: Narendra K +Date: Wed, 10 Jul 2019 18:59:15 +0000 +Subject: efi: Export Runtime Configuration Interface table to sysfs +Patch-mainline: v5.4-rc1 +Git-commit: 1c5fecb61255aa12a16c4c06335ab68979865914 +References: jsc#ECO-366, bsc#1168367 + +System firmware advertises the address of the 'Runtime +Configuration Interface table version 2 (RCI2)' via +an EFI Configuration Table entry. This code retrieves the RCI2 +table from the address and exports it to sysfs as a binary +attribute 'rci2' under /sys/firmware/efi/tables directory. +The approach adopted is similar to the attribute 'DMI' under +/sys/firmware/dmi/tables. + +RCI2 table contains BIOS HII in XML format and is used to populate +BIOS setup page in Dell EMC OpenManage Server Administrator tool. +The BIOS setup page contains BIOS tokens which can be configured. + +Signed-off-by: Narendra K +Reviewed-by: Mario Limonciello +Signed-off-by: Ard Biesheuvel +Acked-by: Lee, Chun-Yi +--- + Documentation/ABI/testing/sysfs-firmware-efi | 8 + + arch/x86/platform/efi/efi.c | 3 + drivers/firmware/efi/Kconfig | 13 ++ + drivers/firmware/efi/Makefile | 1 + drivers/firmware/efi/efi.c | 3 + drivers/firmware/efi/rci2-table.c | 147 +++++++++++++++++++++++++++ + include/linux/efi.h | 5 + 7 files changed, 180 insertions(+) + create mode 100644 drivers/firmware/efi/rci2-table.c + +--- a/Documentation/ABI/testing/sysfs-firmware-efi ++++ b/Documentation/ABI/testing/sysfs-firmware-efi +@@ -28,3 +28,11 @@ Description: Displays the physical addre + versions are always printed first, i.e. ACPI20 comes + before ACPI. + Users: dmidecode ++ ++What: /sys/firmware/efi/tables/rci2 ++Date: July 2019 ++Contact: Narendra K , linux-bugs@dell.com ++Description: Displays the content of the Runtime Configuration Interface ++ Table version 2 on Dell EMC PowerEdge systems in binary format ++Users: It is used by Dell EMC OpenManage Server Administrator tool to ++ populate BIOS setup page. +--- a/arch/x86/platform/efi/efi.c ++++ b/arch/x86/platform/efi/efi.c +@@ -81,6 +81,9 @@ static const unsigned long * const efi_t + &efi.esrt, + &efi.properties_table, + &efi.mem_attr_table, ++#ifdef CONFIG_EFI_RCI2_TABLE ++ &rci2_table_phys, ++#endif + }; + + u64 efi_setup; /* efi setup_data physical address */ +--- a/drivers/firmware/efi/Kconfig ++++ b/drivers/firmware/efi/Kconfig +@@ -142,6 +142,19 @@ config APPLE_PROPERTIES + + If unsure, say Y if you have a Mac. Otherwise N. + ++config EFI_RCI2_TABLE ++ bool "EFI Runtime Configuration Interface Table Version 2 Support" ++ help ++ Displays the content of the Runtime Configuration Interface ++ Table version 2 on Dell EMC PowerEdge systems as a binary ++ attribute 'rci2' under /sys/firmware/efi/tables directory. ++ ++ RCI2 table contains BIOS HII in XML format and is used to populate ++ BIOS setup page in Dell EMC OpenManage Server Administrator tool. ++ The BIOS setup page contains BIOS tokens which can be configured. ++ ++ Say Y here for Dell EMC PowerEdge systems. ++ + endmenu + + config UEFI_CPER +--- a/drivers/firmware/efi/Makefile ++++ b/drivers/firmware/efi/Makefile +@@ -24,6 +24,7 @@ obj-$(CONFIG_EFI_BOOTLOADER_CONTROL) += + obj-$(CONFIG_EFI_TEST) += test/ + obj-$(CONFIG_EFI_DEV_PATH_PARSER) += dev-path-parser.o + obj-$(CONFIG_APPLE_PROPERTIES) += apple-properties.o ++obj-$(CONFIG_EFI_RCI2_TABLE) += rci2-table.o + + arm-obj-$(CONFIG_EFI) := arm-init.o arm-runtime.o + obj-$(CONFIG_ARM) += $(arm-obj-y) +--- a/drivers/firmware/efi/efi.c ++++ b/drivers/firmware/efi/efi.c +@@ -445,6 +445,9 @@ static __initdata efi_config_table_type_ + {EFI_MEMORY_ATTRIBUTES_TABLE_GUID, "MEMATTR", &efi.mem_attr_table}, + {LINUX_EFI_RANDOM_SEED_TABLE_GUID, "RNG", &efi.rng_seed}, + {LINUX_EFI_MEMRESERVE_TABLE_GUID, "MEMRESERVE", &efi.mem_reserve}, ++#ifdef CONFIG_EFI_RCI2_TABLE ++ {DELLEMC_EFI_RCI2_TABLE_GUID, NULL, &rci2_table_phys}, ++#endif + {NULL_GUID, NULL, NULL}, + }; + +--- /dev/null ++++ b/drivers/firmware/efi/rci2-table.c +@@ -0,0 +1,147 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Export Runtime Configuration Interface Table Version 2 (RCI2) ++ * to sysfs ++ * ++ * Copyright (C) 2019 Dell Inc ++ * by Narendra K ++ * ++ * System firmware advertises the address of the RCI2 Table via ++ * an EFI Configuration Table entry. This code retrieves the RCI2 ++ * table from the address and exports it to sysfs as a binary ++ * attribute 'rci2' under /sys/firmware/efi/tables directory. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define RCI_SIGNATURE "_RC_" ++ ++struct rci2_table_global_hdr { ++ u16 type; ++ u16 resvd0; ++ u16 hdr_len; ++ u8 rci2_sig[4]; ++ u16 resvd1; ++ u32 resvd2; ++ u32 resvd3; ++ u8 major_rev; ++ u8 minor_rev; ++ u16 num_of_structs; ++ u32 rci2_len; ++ u16 rci2_chksum; ++} __packed; ++ ++static u8 *rci2_base; ++static u32 rci2_table_len; ++unsigned long rci2_table_phys __ro_after_init = EFI_INVALID_TABLE_ADDR; ++ ++static ssize_t raw_table_read(struct file *file, struct kobject *kobj, ++ struct bin_attribute *attr, char *buf, ++ loff_t pos, size_t count) ++{ ++ memcpy(buf, attr->private + pos, count); ++ return count; ++} ++ ++static BIN_ATTR(rci2, S_IRUSR, raw_table_read, NULL, 0); ++ ++static u16 checksum(void) ++{ ++ u8 len_is_odd = rci2_table_len % 2; ++ u32 chksum_len = rci2_table_len; ++ u16 *base = (u16 *)rci2_base; ++ u8 buf[2] = {0}; ++ u32 offset = 0; ++ u16 chksum = 0; ++ ++ if (len_is_odd) ++ chksum_len -= 1; ++ ++ while (offset < chksum_len) { ++ chksum += *base; ++ offset += 2; ++ base++; ++ } ++ ++ if (len_is_odd) { ++ buf[0] = *(u8 *)base; ++ chksum += *(u16 *)(buf); ++ } ++ ++ return chksum; ++} ++ ++int __init efi_rci2_sysfs_init(void) ++{ ++ struct kobject *tables_kobj; ++ int ret = -ENOMEM; ++ ++ rci2_base = memremap(rci2_table_phys, ++ sizeof(struct rci2_table_global_hdr), ++ MEMREMAP_WB); ++ if (!rci2_base) { ++ pr_debug("RCI2 table init failed - could not map RCI2 table\n"); ++ goto err; ++ } ++ ++ if (strncmp(rci2_base + ++ offsetof(struct rci2_table_global_hdr, rci2_sig), ++ RCI_SIGNATURE, 4)) { ++ pr_debug("RCI2 table init failed - incorrect signature\n"); ++ ret = -ENODEV; ++ goto err_unmap; ++ } ++ ++ rci2_table_len = *(u32 *)(rci2_base + ++ offsetof(struct rci2_table_global_hdr, ++ rci2_len)); ++ ++ memunmap(rci2_base); ++ ++ if (!rci2_table_len) { ++ pr_debug("RCI2 table init failed - incorrect table length\n"); ++ goto err; ++ } ++ ++ rci2_base = memremap(rci2_table_phys, rci2_table_len, MEMREMAP_WB); ++ if (!rci2_base) { ++ pr_debug("RCI2 table - could not map RCI2 table\n"); ++ goto err; ++ } ++ ++ if (checksum() != 0) { ++ pr_debug("RCI2 table - incorrect checksum\n"); ++ ret = -ENODEV; ++ goto err_unmap; ++ } ++ ++ tables_kobj = kobject_create_and_add("tables", efi_kobj); ++ if (!tables_kobj) { ++ pr_debug("RCI2 table - tables_kobj creation failed\n"); ++ goto err_unmap; ++ } ++ ++ bin_attr_rci2.size = rci2_table_len; ++ bin_attr_rci2.private = rci2_base; ++ ret = sysfs_create_bin_file(tables_kobj, &bin_attr_rci2); ++ if (ret != 0) { ++ pr_debug("RCI2 table - rci2 sysfs bin file creation failed\n"); ++ kobject_del(tables_kobj); ++ kobject_put(tables_kobj); ++ goto err_unmap; ++ } ++ ++ return 0; ++ ++ err_unmap: ++ memunmap(rci2_base); ++ err: ++ pr_debug("RCI2 table - sysfs initialization failed\n"); ++ return ret; ++} ++late_initcall(efi_rci2_sysfs_init); +--- a/include/linux/efi.h ++++ b/include/linux/efi.h +@@ -628,6 +628,9 @@ void efi_native_runtime_setup(void); + #define LINUX_EFI_RANDOM_SEED_TABLE_GUID EFI_GUID(0x1ce1e5bc, 0x7ceb, 0x42f2, 0x81, 0xe5, 0x8a, 0xad, 0xf1, 0x80, 0xf5, 0x7b) + #define LINUX_EFI_MEMRESERVE_TABLE_GUID EFI_GUID(0x888eb0c6, 0x8ede, 0x4ff5, 0xa8, 0xf0, 0x9a, 0xee, 0x5c, 0xb9, 0x77, 0xc2) + ++/* OEM GUIDs */ ++#define DELLEMC_EFI_RCI2_TABLE_GUID EFI_GUID(0x2d9f28a2, 0xa886, 0x456a, 0x97, 0xa8, 0xf1, 0x1e, 0xf2, 0x4f, 0xf4, 0x55) ++ + typedef struct { + efi_guid_t guid; + u64 table; +@@ -1600,6 +1603,8 @@ struct linux_efi_random_seed { + u8 bits[]; + }; + ++extern unsigned long rci2_table_phys; ++ + struct linux_efi_memreserve { + int size; // allocated size of the array + atomic_t count; // number of entries used diff --git a/patches.suse/efi-Fix-a-race-and-a-buffer-overflow-while-reading-e-286d3250.patch b/patches.suse/efi-Fix-a-race-and-a-buffer-overflow-while-reading-e-286d3250.patch new file mode 100644 index 0000000..19006d2 --- /dev/null +++ b/patches.suse/efi-Fix-a-race-and-a-buffer-overflow-while-reading-e-286d3250.patch @@ -0,0 +1,135 @@ +From: Vladis Dronov +Date: Sun, 8 Mar 2020 09:08:54 +0100 +Subject: efi: Fix a race and a buffer overflow while reading efivars via sysfs +Patch-mainline: v5.6-rc6 +Git-commit: 286d3250c9d6437340203fb64938bea344729a0e +References: bsc#1164893 + +There is a race and a buffer overflow corrupting a kernel memory while +reading an EFI variable with a size more than 1024 bytes via the older +sysfs method. This happens because accessing struct efi_variable in +efivar_{attr,size,data}_read() and friends is not protected from +a concurrent access leading to a kernel memory corruption and, at best, +to a crash. The race scenario is the following: + +CPU0: CPU1: +efivar_attr_read() + var->DataSize = 1024; + efivar_entry_get(... &var->DataSize) + down_interruptible(&efivars_lock) + efivar_attr_read() // same EFI var + var->DataSize = 1024; + efivar_entry_get(... &var->DataSize) + down_interruptible(&efivars_lock) + virt_efi_get_variable() + // returns EFI_BUFFER_TOO_SMALL but + // var->DataSize is set to a real + // var size more than 1024 bytes + up(&efivars_lock) + virt_efi_get_variable() + // called with var->DataSize set + // to a real var size, returns + // successfully and overwrites + // a 1024-bytes kernel buffer + up(&efivars_lock) + +This can be reproduced by concurrent reading of an EFI variable which size +is more than 1024 bytes: + + ts# for cpu in $(seq 0 $(nproc --ignore=1)); do ( taskset -c $cpu \ + cat /sys/firmware/efi/vars/KEKDefault*/size & ) ; done + +Fix this by using a local variable for a var's data buffer size so it +does not get overwritten. + +Fixes: e14ab23dde12b80d ("efivars: efivar_entry API") +Reported-by: Bob Sanders and the LTP testsuite +Signed-off-by: Vladis Dronov +Signed-off-by: Ard Biesheuvel +Signed-off-by: Ingo Molnar +Cc: +Link: https://lore.kernel.org/r/20200305084041.24053-2-vdronov@redhat.com +Link: https://lore.kernel.org/r/20200308080859.21568-24-ardb@kernel.org +Acked-by: Lee, Chun-Yi +--- + drivers/firmware/efi/efivars.c | 29 ++++++++++++++++++++--------- + 1 file changed, 20 insertions(+), 9 deletions(-) + +--- a/drivers/firmware/efi/efivars.c ++++ b/drivers/firmware/efi/efivars.c +@@ -139,13 +139,16 @@ static ssize_t + efivar_attr_read(struct efivar_entry *entry, char *buf) + { + struct efi_variable *var = &entry->var; ++ unsigned long size = sizeof(var->Data); + char *str = buf; ++ int ret; + + if (!entry || !buf) + return -EINVAL; + +- var->DataSize = 1024; +- if (efivar_entry_get(entry, &var->Attributes, &var->DataSize, var->Data)) ++ ret = efivar_entry_get(entry, &var->Attributes, &size, var->Data); ++ var->DataSize = size; ++ if (ret) + return -EIO; + + if (var->Attributes & EFI_VARIABLE_NON_VOLATILE) +@@ -172,13 +175,16 @@ static ssize_t + efivar_size_read(struct efivar_entry *entry, char *buf) + { + struct efi_variable *var = &entry->var; ++ unsigned long size = sizeof(var->Data); + char *str = buf; ++ int ret; + + if (!entry || !buf) + return -EINVAL; + +- var->DataSize = 1024; +- if (efivar_entry_get(entry, &var->Attributes, &var->DataSize, var->Data)) ++ ret = efivar_entry_get(entry, &var->Attributes, &size, var->Data); ++ var->DataSize = size; ++ if (ret) + return -EIO; + + str += sprintf(str, "0x%lx\n", var->DataSize); +@@ -189,12 +195,15 @@ static ssize_t + efivar_data_read(struct efivar_entry *entry, char *buf) + { + struct efi_variable *var = &entry->var; ++ unsigned long size = sizeof(var->Data); ++ int ret; + + if (!entry || !buf) + return -EINVAL; + +- var->DataSize = 1024; +- if (efivar_entry_get(entry, &var->Attributes, &var->DataSize, var->Data)) ++ ret = efivar_entry_get(entry, &var->Attributes, &size, var->Data); ++ var->DataSize = size; ++ if (ret) + return -EIO; + + memcpy(buf, var->Data, var->DataSize); +@@ -314,14 +323,16 @@ efivar_show_raw(struct efivar_entry *ent + { + struct efi_variable *var = &entry->var; + struct compat_efi_variable *compat; ++ unsigned long datasize = sizeof(var->Data); + size_t size; ++ int ret; + + if (!entry || !buf) + return 0; + +- var->DataSize = 1024; +- if (efivar_entry_get(entry, &entry->var.Attributes, +- &entry->var.DataSize, entry->var.Data)) ++ ret = efivar_entry_get(entry, &var->Attributes, &datasize, var->Data); ++ var->DataSize = datasize; ++ if (ret) + return -EIO; + + if (is_compat()) { diff --git a/patches.suse/efi-x86-move-efi_is_table_address-into-arch-x86.patch b/patches.suse/efi-x86-move-efi_is_table_address-into-arch-x86.patch new file mode 100644 index 0000000..e4963f7 --- /dev/null +++ b/patches.suse/efi-x86-move-efi_is_table_address-into-arch-x86.patch @@ -0,0 +1,170 @@ +From: Ard Biesheuvel +Date: Tue, 25 Jun 2019 15:36:45 +0200 +Subject: efi: x86: move efi_is_table_address() into arch/x86 +Patch-mainline: v5.4-rc1 +Git-commit: e55f31a599478fb06a5a5d95e019e963322535cb +References: jsc#ECO-366, bsc#1168367 + +The function efi_is_table_address() and the associated array of table +pointers is specific to x86. Since we will be adding some more x86 +specific tables, let's move this code out of the generic code first. + +Signed-off-by: Ard Biesheuvel +Acked-by: Lee, Chun-Yi +--- + arch/x86/include/asm/efi.h | 5 +++++ + arch/x86/mm/ioremap.c | 1 + + arch/x86/platform/efi/efi.c | 33 +++++++++++++++++++++++++++++++++ + drivers/firmware/efi/efi.c | 33 --------------------------------- + include/linux/efi.h | 7 ------- + 5 files changed, 39 insertions(+), 40 deletions(-) + +--- a/arch/x86/include/asm/efi.h ++++ b/arch/x86/include/asm/efi.h +@@ -245,6 +245,7 @@ static inline bool efi_is_64bit(void) + __efi_early()->runtime_services), __VA_ARGS__) + + extern bool efi_reboot_required(void); ++extern bool efi_is_table_address(unsigned long phys_addr); + + #else + static inline void parse_efi_setup(u64 phys_addr, u32 data_len) {} +@@ -252,6 +253,10 @@ static inline bool efi_reboot_required(v + { + return false; + } ++static inline bool efi_is_table_address(unsigned long phys_addr) ++{ ++ return false; ++} + #endif /* CONFIG_EFI */ + + #endif /* _ASM_X86_EFI_H */ +--- a/arch/x86/mm/ioremap.c ++++ b/arch/x86/mm/ioremap.c +@@ -18,6 +18,7 @@ + + #include + #include ++#include + #include + #include + #include +--- a/arch/x86/platform/efi/efi.c ++++ b/arch/x86/platform/efi/efi.c +@@ -64,6 +64,25 @@ static efi_config_table_type_t arch_tabl + {NULL_GUID, NULL, NULL}, + }; + ++static const unsigned long * const efi_tables[] = { ++ &efi.mps, ++ &efi.acpi, ++ &efi.acpi20, ++ &efi.smbios, ++ &efi.smbios3, ++ &efi.sal_systab, ++ &efi.boot_info, ++ &efi.hcdp, ++ &efi.uga, ++ &efi.uv_systab, ++ &efi.fw_vendor, ++ &efi.runtime, ++ &efi.config_table, ++ &efi.esrt, ++ &efi.properties_table, ++ &efi.mem_attr_table, ++}; ++ + u64 efi_setup; /* efi setup_data physical address */ + + static int add_efi_memmap __initdata; +@@ -1065,3 +1084,17 @@ static int __init arch_parse_efi_cmdline + return 0; + } + early_param("efi", arch_parse_efi_cmdline); ++ ++bool efi_is_table_address(unsigned long phys_addr) ++{ ++ unsigned int i; ++ ++ if (phys_addr == EFI_INVALID_TABLE_ADDR) ++ return false; ++ ++ for (i = 0; i < ARRAY_SIZE(efi_tables); i++) ++ if (*(efi_tables[i]) == phys_addr) ++ return true; ++ ++ return false; ++} +--- a/drivers/firmware/efi/efi.c ++++ b/drivers/firmware/efi/efi.c +@@ -56,25 +56,6 @@ struct efi __read_mostly efi = { + }; + EXPORT_SYMBOL(efi); + +-static unsigned long *efi_tables[] = { +- &efi.mps, +- &efi.acpi, +- &efi.acpi20, +- &efi.smbios, +- &efi.smbios3, +- &efi.sal_systab, +- &efi.boot_info, +- &efi.hcdp, +- &efi.uga, +- &efi.uv_systab, +- &efi.fw_vendor, +- &efi.runtime, +- &efi.config_table, +- &efi.esrt, +- &efi.properties_table, +- &efi.mem_attr_table, +-}; +- + static bool disable_runtime; + static int __init setup_noefi(char *arg) + { +@@ -910,20 +891,6 @@ int efi_status_to_err(efi_status_t statu + return err; + } + +-bool efi_is_table_address(unsigned long phys_addr) +-{ +- unsigned int i; +- +- if (phys_addr == EFI_INVALID_TABLE_ADDR) +- return false; +- +- for (i = 0; i < ARRAY_SIZE(efi_tables); i++) +- if (*(efi_tables[i]) == phys_addr) +- return true; +- +- return false; +-} +- + static DEFINE_SPINLOCK(efi_mem_reserve_persistent_lock); + static struct linux_efi_memreserve *efi_memreserve_root __ro_after_init; + +--- a/include/linux/efi.h ++++ b/include/linux/efi.h +@@ -1129,8 +1129,6 @@ static inline bool efi_enabled(int featu + return test_bit(feature, &efi.flags) != 0; + } + extern void efi_reboot(enum reboot_mode reboot_mode, const char *__unused); +- +-extern bool efi_is_table_address(unsigned long phys_addr); + #else + static inline bool efi_enabled(int feature) + { +@@ -1144,11 +1142,6 @@ efi_capsule_pending(int *reset_type) + { + return false; + } +- +-static inline bool efi_is_table_address(unsigned long phys_addr) +-{ +- return false; +-} + #endif + + extern int efi_status_to_err(efi_status_t status); diff --git a/patches.suse/ethtool-Factored-out-similar-ethtool-link-settings-f.patch b/patches.suse/ethtool-Factored-out-similar-ethtool-link-settings-f.patch new file mode 100644 index 0000000..f918668 --- /dev/null +++ b/patches.suse/ethtool-Factored-out-similar-ethtool-link-settings-f.patch @@ -0,0 +1,91 @@ +From 70ae1e127b486704c62d3537d69ca65c446d4d83 Mon Sep 17 00:00:00 2001 +From: Cris Forno +Date: Fri, 28 Feb 2020 14:12:04 -0600 +Subject: [PATCH] ethtool: Factored out similar ethtool link settings for + virtual devices to core + +References: bsc#1136157 ltc#177197 +Patch-mainline: v5.7-rc1 +Git-commit: 70ae1e127b486704c62d3537d69ca65c446d4d83 + +Three virtual devices (ibmveth, virtio_net, and netvsc) all have +similar code to set link settings and validate ethtool command. To +eliminate duplication of code, it is factored out into core/ethtool.c. + +Signed-off-by: Cris Forno +Signed-off-by: David S. Miller +Acked-by: Michal Suchanek +--- + include/linux/ethtool.h | 6 ++++++ + net/ethtool/ioctl.c | 39 +++++++++++++++++++++++++++++++++++++++ + 2 files changed, 45 insertions(+) + +--- a/include/linux/ethtool.h ++++ b/include/linux/ethtool.h +@@ -402,4 +402,11 @@ struct ethtool_ops { + int (*set_fecparam)(struct net_device *, + struct ethtool_fecparam *); + }; ++ ++bool ethtool_virtdev_validate_cmd(const struct ethtool_link_ksettings *cmd); ++int ethtool_virtdev_set_link_ksettings(struct net_device *dev, ++ const struct ethtool_link_ksettings *cmd, ++ u32 *dev_speed, u8 *dev_duplex); ++ ++ + #endif /* _LINUX_ETHTOOL_H */ +--- a/net/core/ethtool.c ++++ b/net/core/ethtool.c +@@ -632,6 +632,24 @@ static int load_link_ksettings_from_user + return 0; + } + ++/* Check if the user is trying to change anything besides speed/duplex */ ++bool ethtool_virtdev_validate_cmd(const struct ethtool_link_ksettings *cmd) ++{ ++ struct ethtool_link_settings base2 = {}; ++ ++ base2.speed = cmd->base.speed; ++ base2.port = PORT_OTHER; ++ base2.duplex = cmd->base.duplex; ++ base2.cmd = cmd->base.cmd; ++ base2.link_mode_masks_nwords = cmd->base.link_mode_masks_nwords; ++ ++ return !memcmp(&base2, &cmd->base, sizeof(base2)) && ++ bitmap_empty(cmd->link_modes.supported, ++ __ETHTOOL_LINK_MODE_MASK_NBITS) && ++ bitmap_empty(cmd->link_modes.lp_advertising, ++ __ETHTOOL_LINK_MODE_MASK_NBITS); ++} ++ + /* convert a kernel internal ethtool_link_ksettings to + * ethtool_link_usettings in user space. return 0 on success, errno on + * error. +@@ -771,6 +789,27 @@ static int ethtool_set_link_ksettings(st + return dev->ethtool_ops->set_link_ksettings(dev, &link_ksettings); + } + ++int ethtool_virtdev_set_link_ksettings(struct net_device *dev, ++ const struct ethtool_link_ksettings *cmd, ++ u32 *dev_speed, u8 *dev_duplex) ++{ ++ u32 speed; ++ u8 duplex; ++ ++ speed = cmd->base.speed; ++ duplex = cmd->base.duplex; ++ /* don't allow custom speed and duplex */ ++ if (!ethtool_validate_speed(speed) || ++ !ethtool_validate_duplex(duplex) || ++ !ethtool_virtdev_validate_cmd(cmd)) ++ return -EINVAL; ++ *dev_speed = speed; ++ *dev_duplex = duplex; ++ ++ return 0; ++} ++EXPORT_SYMBOL(ethtool_virtdev_set_link_ksettings); ++ + /* Query device for its ethtool_cmd settings. + * + * Backward compatibility note: for compatibility with legacy ethtool, diff --git a/patches.suse/ext4-Avoid-ENOSPC-when-avoiding-to-reuse-recently-de.patch b/patches.suse/ext4-Avoid-ENOSPC-when-avoiding-to-reuse-recently-de.patch new file mode 100644 index 0000000..1d8c937 --- /dev/null +++ b/patches.suse/ext4-Avoid-ENOSPC-when-avoiding-to-reuse-recently-de.patch @@ -0,0 +1,72 @@ +From 6768261ea1c8203052eea2bfedc7101036697b6e Mon Sep 17 00:00:00 2001 +From: Jan Kara +Date: Wed, 18 Mar 2020 12:51:50 +0100 +Subject: [PATCH] ext4: Avoid ENOSPC when avoiding to reuse recently deleted + inodes +Patch-mainline: Not yet, in ext4 tree, expected 5.7-rc1 +References: bsc#1165019 + +When ext4 is running on a filesystem without a journal, it tries not to +reuse recently deleted inodes to provide better chances for filesystem +recovery in case of crash. However this logic forbids reuse of freed +inodes for up to 5 minutes and especially for filesystems with smaller +number of inodes can lead to ENOSPC errors returned when allocating new +inodes. + +Fix the problem by allowing to reuse recently deleted inode if there's +no other inode free in the scanned range. + +Signed-off-by: Jan Kara +Signed-off-by: Theodore Ts'o +Acked-by: Jan Kara +--- + fs/ext4/ialloc.c | 23 ++++++++++++++++++----- + 1 file changed, 18 insertions(+), 5 deletions(-) + +diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c +index f95ee99091e4..74f0fe145370 100644 +--- a/fs/ext4/ialloc.c ++++ b/fs/ext4/ialloc.c +@@ -712,21 +712,34 @@ static int recently_deleted(struct super_block *sb, ext4_group_t group, int ino) + static int find_inode_bit(struct super_block *sb, ext4_group_t group, + struct buffer_head *bitmap, unsigned long *ino) + { ++ bool check_recently_deleted = EXT4_SB(sb)->s_journal == NULL; ++ unsigned long recently_deleted_ino = EXT4_INODES_PER_GROUP(sb); ++ + next: + *ino = ext4_find_next_zero_bit((unsigned long *) + bitmap->b_data, + EXT4_INODES_PER_GROUP(sb), *ino); + if (*ino >= EXT4_INODES_PER_GROUP(sb)) +- return 0; ++ goto not_found; + +- if ((EXT4_SB(sb)->s_journal == NULL) && +- recently_deleted(sb, group, *ino)) { ++ if (check_recently_deleted && recently_deleted(sb, group, *ino)) { ++ recently_deleted_ino = *ino; + *ino = *ino + 1; + if (*ino < EXT4_INODES_PER_GROUP(sb)) + goto next; +- return 0; ++ goto not_found; + } +- ++ return 1; ++not_found: ++ if (recently_deleted_ino >= EXT4_INODES_PER_GROUP(sb)) ++ return 0; ++ /* ++ * Not reusing recently deleted inodes is mostly a preference. We don't ++ * want to report ENOSPC or skew allocation patterns because of that. ++ * So return even recently deleted inode if we could find better in the ++ * given range. ++ */ ++ *ino = recently_deleted_ino; + return 1; + } + +-- +2.16.4 + diff --git a/patches.suse/fat-fix-uninit-memory-access-for-partial-initialized.patch b/patches.suse/fat-fix-uninit-memory-access-for-partial-initialized.patch new file mode 100644 index 0000000..4b14c79 --- /dev/null +++ b/patches.suse/fat-fix-uninit-memory-access-for-partial-initialized.patch @@ -0,0 +1,78 @@ +From bc87302a093f0eab45cd4e250c2021299f712ec6 Mon Sep 17 00:00:00 2001 +From: OGAWA Hirofumi +Date: Thu, 5 Mar 2020 22:28:36 -0800 +Subject: [PATCH] fat: fix uninit-memory access for partial initialized inode +Git-commit: bc87302a093f0eab45cd4e250c2021299f712ec6 +Patch-mainline: v5.6-rc5 +References: bsc#1051510 + +When get an error in the middle of reading an inode, some fields in the +inode might be still not initialized. And then the evict_inode path may +access those fields via iput(). + +To fix, this makes sure that inode fields are initialized. + +Reported-by: syzbot+9d82b8de2992579da5d0@syzkaller.appspotmail.com +Signed-off-by: Andrew Morton +Signed-off-by: OGAWA Hirofumi +Cc: +Link: http://lkml.kernel.org/r/871rqnreqx.fsf@mail.parknet.co.jp +Signed-off-by: Linus Torvalds +Acked-by: Takashi Iwai + +--- + fs/fat/inode.c | 19 +++++++------------ + 1 file changed, 7 insertions(+), 12 deletions(-) + +diff --git a/fs/fat/inode.c b/fs/fat/inode.c +index 594b05ae16c9..71946da84388 100644 +--- a/fs/fat/inode.c ++++ b/fs/fat/inode.c +@@ -750,6 +750,13 @@ static struct inode *fat_alloc_inode(struct super_block *sb) + return NULL; + + init_rwsem(&ei->truncate_lock); ++ /* Zeroing to allow iput() even if partial initialized inode. */ ++ ei->mmu_private = 0; ++ ei->i_start = 0; ++ ei->i_logstart = 0; ++ ei->i_attrs = 0; ++ ei->i_pos = 0; ++ + return &ei->vfs_inode; + } + +@@ -1374,16 +1381,6 @@ static int parse_options(struct super_block *sb, char *options, int is_vfat, + return 0; + } + +-static void fat_dummy_inode_init(struct inode *inode) +-{ +- /* Initialize this dummy inode to work as no-op. */ +- MSDOS_I(inode)->mmu_private = 0; +- MSDOS_I(inode)->i_start = 0; +- MSDOS_I(inode)->i_logstart = 0; +- MSDOS_I(inode)->i_attrs = 0; +- MSDOS_I(inode)->i_pos = 0; +-} +- + static int fat_read_root(struct inode *inode) + { + struct msdos_sb_info *sbi = MSDOS_SB(inode->i_sb); +@@ -1844,13 +1841,11 @@ int fat_fill_super(struct super_block *sb, void *data, int silent, int isvfat, + fat_inode = new_inode(sb); + if (!fat_inode) + goto out_fail; +- fat_dummy_inode_init(fat_inode); + sbi->fat_inode = fat_inode; + + fsinfo_inode = new_inode(sb); + if (!fsinfo_inode) + goto out_fail; +- fat_dummy_inode_init(fsinfo_inode); + fsinfo_inode->i_ino = MSDOS_FSINFO_INO; + sbi->fsinfo_inode = fsinfo_inode; + insert_inode_hash(fsinfo_inode); +-- +2.16.4 + diff --git a/patches.suse/fat-work-around-race-with-userspace-s-read-via-block.patch b/patches.suse/fat-work-around-race-with-userspace-s-read-via-block.patch new file mode 100644 index 0000000..edfa996 --- /dev/null +++ b/patches.suse/fat-work-around-race-with-userspace-s-read-via-block.patch @@ -0,0 +1,102 @@ +From 07bfa4415ab607e459b69bd86aa7e7602ce10b4f Mon Sep 17 00:00:00 2001 +From: OGAWA Hirofumi +Date: Mon, 23 Sep 2019 15:32:53 -0700 +Subject: [PATCH] fat: work around race with userspace's read via blockdev while mounting +Git-commit: 07bfa4415ab607e459b69bd86aa7e7602ce10b4f +Patch-mainline: v5.4-rc1 +References: bsc#1051510 + +If userspace reads the buffer via blockdev while mounting, +sb_getblk()+modify can race with buffer read via blockdev. + +For example, + + FS userspace + bh = sb_getblk() + modify bh->b_data + read + ll_rw_block(bh) + fill bh->b_data by on-disk data + /* lost modified data by FS */ + set_buffer_uptodate(bh) + set_buffer_uptodate(bh) + +Userspace should not use the blockdev while mounting though, the udev +seems to be already doing this. Although I think the udev should try to +avoid this, workaround the race by small overhead. + +Link: http://lkml.kernel.org/r/87pnk7l3sw.fsf_-_@mail.parknet.co.jp +Signed-off-by: OGAWA Hirofumi +Reported-by: Jan Stancek +Tested-by: Jan Stancek +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +Acked-by: Takashi Iwai + +--- + fs/fat/dir.c | 13 +++++++++++-- + fs/fat/fatent.c | 3 +++ + 2 files changed, 14 insertions(+), 2 deletions(-) + +--- a/fs/fat/dir.c ++++ b/fs/fat/dir.c +@@ -1098,8 +1098,11 @@ static int fat_zeroed_cluster(struct ino + err = -ENOMEM; + goto error; + } ++ /* Avoid race with userspace read via bdev */ ++ lock_buffer(bhs[n]); + memset(bhs[n]->b_data, 0, sb->s_blocksize); + set_buffer_uptodate(bhs[n]); ++ unlock_buffer(bhs[n]); + mark_buffer_dirty_inode(bhs[n], dir); + + n++; +@@ -1156,6 +1159,8 @@ int fat_alloc_new_dir(struct inode *dir, + fat_time_unix2fat(sbi, ts, &time, &date, &time_cs); + + de = (struct msdos_dir_entry *)bhs[0]->b_data; ++ /* Avoid race with userspace read via bdev */ ++ lock_buffer(bhs[0]); + /* filling the new directory slots ("." and ".." entries) */ + memcpy(de[0].name, MSDOS_DOT, MSDOS_NAME); + memcpy(de[1].name, MSDOS_DOTDOT, MSDOS_NAME); +@@ -1178,6 +1183,7 @@ int fat_alloc_new_dir(struct inode *dir, + de[0].size = de[1].size = 0; + memset(de + 2, 0, sb->s_blocksize - 2 * sizeof(*de)); + set_buffer_uptodate(bhs[0]); ++ unlock_buffer(bhs[0]); + mark_buffer_dirty_inode(bhs[0], dir); + + err = fat_zeroed_cluster(dir, blknr, 1, bhs, MAX_BUF_PER_PAGE); +@@ -1235,11 +1241,14 @@ static int fat_add_new_entries(struct in + + /* fill the directory entry */ + copy = min(size, sb->s_blocksize); ++ /* Avoid race with userspace read via bdev */ ++ lock_buffer(bhs[n]); + memcpy(bhs[n]->b_data, slots, copy); +- slots += copy; +- size -= copy; + set_buffer_uptodate(bhs[n]); ++ unlock_buffer(bhs[n]); + mark_buffer_dirty_inode(bhs[n], dir); ++ slots += copy; ++ size -= copy; + if (!size) + break; + n++; +--- a/fs/fat/fatent.c ++++ b/fs/fat/fatent.c +@@ -389,8 +389,11 @@ static int fat_mirror_bhs(struct super_b + err = -ENOMEM; + goto error; + } ++ /* Avoid race with userspace read via bdev */ ++ lock_buffer(c_bh); + memcpy(c_bh->b_data, bhs[n]->b_data, sb->s_blocksize); + set_buffer_uptodate(c_bh); ++ unlock_buffer(c_bh); + mark_buffer_dirty_inode(c_bh, sbi->fat_inode); + if (sb->s_flags & MS_SYNCHRONOUS) + err = sync_dirty_buffer(c_bh); diff --git a/patches.suse/fbdev-g364fb-Fix-build-failure.patch b/patches.suse/fbdev-g364fb-Fix-build-failure.patch new file mode 100644 index 0000000..ba9344a --- /dev/null +++ b/patches.suse/fbdev-g364fb-Fix-build-failure.patch @@ -0,0 +1,112 @@ +From c584f9532115aecf24ba126dd5c528c994b6950f Mon Sep 17 00:00:00 2001 +From: Finn Thain +Date: Fri, 7 Feb 2020 10:01:13 +1100 +Subject: [PATCH] fbdev/g364fb: Fix build failure +Mime-version: 1.0 +Content-type: text/plain; charset=UTF-8 +Content-transfer-encoding: 8bit +Git-commit: c584f9532115aecf24ba126dd5c528c994b6950f +Patch-mainline: v5.7-rc1 +References: bsc#1051510 + +This patch resolves these compiler errors and warnings -- + + CC drivers/video/fbdev/g364fb.o +Drivers/video/fbdev/g364fb.c: In function 'g364fb_cursor': +drivers/video/fbdev/g364fb.c:137:9: error: 'x' undeclared (first use in this function) +drivers/video/fbdev/g364fb.c:137:9: note: each undeclared identifier is reported only once for each function it appears in +drivers/video/fbdev/g364fb.c:137:7: error: implicit declaration of function 'fontwidth' [-Werror=implicit-function-declaration] +drivers/video/fbdev/g364fb.c:137:23: error: 'p' undeclared (first use in this function) +drivers/video/fbdev/g364fb.c:137:38: error: 'y' undeclared (first use in this function) +drivers/video/fbdev/g364fb.c:137:7: error: implicit declaration of function 'fontheight' [-Werror=implicit-function-declaration] +Drivers/video/fbdev/g364fb.c: In function 'g364fb_init': +drivers/video/fbdev/g364fb.c:233:24: error: 'fbvar' undeclared (first use in this function) +drivers/video/fbdev/g364fb.c:234:24: error: 'xres' undeclared (first use in this function) +drivers/video/fbdev/g364fb.c:201:14: warning: unused variable 'j' [-Wunused-variable] +drivers/video/fbdev/g364fb.c:197:25: warning: unused variable 'pal_ptr' [-Wunused-variable] + +The MIPS Magnum framebuffer console now works when tested in QEMU. + +Cc: Bartlomiej Zolnierkiewicz +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Reviewed-by: Philippe Mathieu-Daudé +Signed-off-by: Finn Thain +Acked-by: Bartlomiej Zolnierkiewicz +Tested-by: Philippe Mathieu-Daudé +Signed-off-by: Paul Burton +Cc: Ralf Baechle +Cc: James Hogan +Cc: Thomas Bogendoerfer +Cc: linux-mips@vger.kernel.org +Cc: linux-kernel@vger.kernel.org +Cc: dri-devel@lists.freedesktop.org +Cc: linux-fbdev@vger.kernel.org +Acked-by: Takashi Iwai + +--- + drivers/video/fbdev/g364fb.c | 29 +++-------------------------- + 1 file changed, 3 insertions(+), 26 deletions(-) + +--- a/drivers/video/fbdev/g364fb.c ++++ b/drivers/video/fbdev/g364fb.c +@@ -108,7 +108,6 @@ static int g364fb_pan_display(struct fb_ + static int g364fb_setcolreg(u_int regno, u_int red, u_int green, + u_int blue, u_int transp, + struct fb_info *info); +-static int g364fb_cursor(struct fb_info *info, struct fb_cursor *cursor); + static int g364fb_blank(int blank, struct fb_info *info); + + static struct fb_ops g364fb_ops = { +@@ -119,28 +118,8 @@ static struct fb_ops g364fb_ops = { + .fb_fillrect = cfb_fillrect, + .fb_copyarea = cfb_copyarea, + .fb_imageblit = cfb_imageblit, +- .fb_cursor = g364fb_cursor, + }; + +-int g364fb_cursor(struct fb_info *info, struct fb_cursor *cursor) +-{ +- +- switch (cursor->enable) { +- case CM_ERASE: +- *(unsigned int *) CTLA_REG |= CURS_TOGGLE; +- break; +- +- case CM_MOVE: +- case CM_DRAW: +- *(unsigned int *) CTLA_REG &= ~CURS_TOGGLE; +- *(unsigned int *) CURS_POS_REG = +- ((x * fontwidth(p)) << 12) | ((y * fontheight(p)) - +- info->var.yoffset); +- break; +- } +- return 0; +-} +- + /* + * Pan or Wrap the Display + * +@@ -194,11 +173,9 @@ static int g364fb_setcolreg(u_int regno, + */ + int __init g364fb_init(void) + { +- volatile unsigned int *pal_ptr = +- (volatile unsigned int *) CLR_PAL_REG; + volatile unsigned int *curs_pal_ptr = + (volatile unsigned int *) CURS_PAL_REG; +- int mem, i, j; ++ int mem, i; + + if (fb_get_options("g364fb", NULL)) + return -ENODEV; +@@ -230,8 +207,8 @@ int __init g364fb_init(void) + */ + *(unsigned short *) (CURS_PAT_REG + 14 * 64) = 0xffff; + *(unsigned short *) (CURS_PAT_REG + 15 * 64) = 0xffff; +- fb_var.xres_virtual = fbvar.xres; +- fb_fix.line_length = (xres / 8) * fb_var.bits_per_pixel; ++ fb_var.xres_virtual = fb_var.xres; ++ fb_fix.line_length = fb_var.xres_virtual * fb_var.bits_per_pixel / 8; + fb_fix.smem_start = 0x40000000; /* physical address */ + /* get size of video memory; this is special for the JAZZ hardware */ + mem = (r4030_read_reg32(JAZZ_R4030_CONFIG) >> 8) & 3; diff --git a/patches.suse/firmware-arm_sdei-fix-double-lock-on-hibernate-with-.patch b/patches.suse/firmware-arm_sdei-fix-double-lock-on-hibernate-with-.patch new file mode 100644 index 0000000..7b1b8b1 --- /dev/null +++ b/patches.suse/firmware-arm_sdei-fix-double-lock-on-hibernate-with-.patch @@ -0,0 +1,118 @@ +From 6ded0b61cf638bf9f8efe60ab8ba23db60ea9763 Mon Sep 17 00:00:00 2001 +From: James Morse +Date: Fri, 21 Feb 2020 16:35:06 +0000 +Subject: [PATCH] firmware: arm_sdei: fix double-lock on hibernate with shared events +Git-commit: 6ded0b61cf638bf9f8efe60ab8ba23db60ea9763 +Patch-mainline: v5.7-rc1 +References: bsc#1111666 + +SDEI has private events that must be registered on each CPU. When +CPUs come and go they must re-register and re-enable their private +events. Each event has flags to indicate whether this should happen +to protect against an event being registered on a CPU coming online, +while all the others are unregistering the event. + +These flags are protected by the sdei_list_lock spinlock, because +the cpuhp callbacks can't take the mutex. + +Hibernate needs to unregister all events, but keep the in-memory +re-register and re-enable as they are. sdei_unregister_shared() +takes the spinlock to walk the list, then calls _sdei_event_unregister() +on each shared event. _sdei_event_unregister() tries to take the +same spinlock to update re-register and re-enable. This doesn't go +so well. + +Push the re-register and re-enable updates out to their callers. +sdei_unregister_shared() doesn't want these values updated, so +doesn't need to do anything. + +This also fixes shared events getting lost over hibernate as this +path made them look unregistered. + +Fixes: da351827240e ("firmware: arm_sdei: Add support for CPU and system power states") +Reported-by: Liguang Zhang +Signed-off-by: James Morse +Signed-off-by: Catalin Marinas +Acked-by: Takashi Iwai + +--- + drivers/firmware/arm_sdei.c | 32 +++++++++++++++----------------- + 1 file changed, 15 insertions(+), 17 deletions(-) + +diff --git a/drivers/firmware/arm_sdei.c b/drivers/firmware/arm_sdei.c +index a479023fa036..77eaa9a2fd15 100644 +--- a/drivers/firmware/arm_sdei.c ++++ b/drivers/firmware/arm_sdei.c +@@ -491,11 +491,6 @@ static int _sdei_event_unregister(struct sdei_event *event) + { + lockdep_assert_held(&sdei_events_lock); + +- spin_lock(&sdei_list_lock); +- event->reregister = false; +- event->reenable = false; +- spin_unlock(&sdei_list_lock); +- + if (event->type == SDEI_EVENT_TYPE_SHARED) + return sdei_api_event_unregister(event->event_num); + +@@ -518,6 +513,11 @@ int sdei_event_unregister(u32 event_num) + break; + } + ++ spin_lock(&sdei_list_lock); ++ event->reregister = false; ++ event->reenable = false; ++ spin_unlock(&sdei_list_lock); ++ + err = _sdei_event_unregister(event); + if (err) + break; +@@ -585,26 +585,15 @@ static int _sdei_event_register(struct sdei_event *event) + + lockdep_assert_held(&sdei_events_lock); + +- spin_lock(&sdei_list_lock); +- event->reregister = true; +- spin_unlock(&sdei_list_lock); +- + if (event->type == SDEI_EVENT_TYPE_SHARED) + return sdei_api_event_register(event->event_num, + sdei_entry_point, + event->registered, + SDEI_EVENT_REGISTER_RM_ANY, 0); + +- + err = sdei_do_cross_call(_local_event_register, event); +- if (err) { +- spin_lock(&sdei_list_lock); +- event->reregister = false; +- event->reenable = false; +- spin_unlock(&sdei_list_lock); +- ++ if (err) + sdei_do_cross_call(_local_event_unregister, event); +- } + + return err; + } +@@ -632,8 +621,17 @@ int sdei_event_register(u32 event_num, sdei_event_callback *cb, void *arg) + break; + } + ++ spin_lock(&sdei_list_lock); ++ event->reregister = true; ++ spin_unlock(&sdei_list_lock); ++ + err = _sdei_event_register(event); + if (err) { ++ spin_lock(&sdei_list_lock); ++ event->reregister = false; ++ event->reenable = false; ++ spin_unlock(&sdei_list_lock); ++ + sdei_event_destroy(event); + pr_warn("Failed to register event %u: %d\n", event_num, + err); +-- +2.16.4 + diff --git a/patches.suse/firmware-arm_sdei-fix-possible-double-lock-on-hibern.patch b/patches.suse/firmware-arm_sdei-fix-possible-double-lock-on-hibern.patch new file mode 100644 index 0000000..c950af9 --- /dev/null +++ b/patches.suse/firmware-arm_sdei-fix-possible-double-lock-on-hibern.patch @@ -0,0 +1,93 @@ +From c66d52b1026717135c5030c65e344750161d159b Mon Sep 17 00:00:00 2001 +From: Liguang Zhang +Date: Fri, 21 Feb 2020 16:35:07 +0000 +Subject: [PATCH] firmware: arm_sdei: fix possible double-lock on hibernate error path +Git-commit: c66d52b1026717135c5030c65e344750161d159b +Patch-mainline: v5.7-rc1 +References: bsc#1111666 + +We call sdei_reregister_event() with sdei_list_lock held, if the register +fails we call sdei_event_destroy() which also acquires sdei_list_lock +thus creating A-A deadlock. + +Add '_llocked' to sdei_reregister_event(), to indicate the list lock +is held, and add a _llocked variant of sdei_event_destroy(). + +Fixes: da351827240e ("firmware: arm_sdei: Add support for CPU and system power states") +Signed-off-by: Liguang Zhang +[expanded subject, added wrappers instead of duplicating contents] + +Signed-off-by: James Morse +Signed-off-by: Catalin Marinas +Acked-by: Takashi Iwai + +--- + drivers/firmware/arm_sdei.c | 19 +++++++++++++------ + 1 file changed, 13 insertions(+), 6 deletions(-) + +diff --git a/drivers/firmware/arm_sdei.c b/drivers/firmware/arm_sdei.c +index 77eaa9a2fd15..f15f459e9df0 100644 +--- a/drivers/firmware/arm_sdei.c ++++ b/drivers/firmware/arm_sdei.c +@@ -280,13 +280,12 @@ static struct sdei_event *sdei_event_create(u32 event_num, + return event; + } + +-static void sdei_event_destroy(struct sdei_event *event) ++static void sdei_event_destroy_llocked(struct sdei_event *event) + { + lockdep_assert_held(&sdei_events_lock); ++ lockdep_assert_held(&sdei_list_lock); + +- spin_lock(&sdei_list_lock); + list_del(&event->list); +- spin_unlock(&sdei_list_lock); + + if (event->type == SDEI_EVENT_TYPE_SHARED) + kfree(event->registered); +@@ -296,6 +295,13 @@ static void sdei_event_destroy(struct sdei_event *event) + kfree(event); + } + ++static void sdei_event_destroy(struct sdei_event *event) ++{ ++ spin_lock(&sdei_list_lock); ++ sdei_event_destroy_llocked(event); ++ spin_unlock(&sdei_list_lock); ++} ++ + static int sdei_api_get_version(u64 *version) + { + return invoke_sdei_fn(SDEI_1_0_FN_SDEI_VERSION, 0, 0, 0, 0, 0, version); +@@ -643,16 +649,17 @@ int sdei_event_register(u32 event_num, sdei_event_callback *cb, void *arg) + } + EXPORT_SYMBOL(sdei_event_register); + +-static int sdei_reregister_event(struct sdei_event *event) ++static int sdei_reregister_event_llocked(struct sdei_event *event) + { + int err; + + lockdep_assert_held(&sdei_events_lock); ++ lockdep_assert_held(&sdei_list_lock); + + err = _sdei_event_register(event); + if (err) { + pr_err("Failed to re-register event %u\n", event->event_num); +- sdei_event_destroy(event); ++ sdei_event_destroy_llocked(event); + return err; + } + +@@ -681,7 +688,7 @@ static int sdei_reregister_shared(void) + continue; + + if (event->reregister) { +- err = sdei_reregister_event(event); ++ err = sdei_reregister_event_llocked(event); + if (err) + break; + } +-- +2.16.4 + diff --git a/patches.suse/firmware-imx-misc-align-imx-sc-msg-structs-to-4.patch b/patches.suse/firmware-imx-misc-align-imx-sc-msg-structs-to-4.patch new file mode 100644 index 0000000..c8b2099 --- /dev/null +++ b/patches.suse/firmware-imx-misc-align-imx-sc-msg-structs-to-4.patch @@ -0,0 +1,49 @@ +From: Leonard Crestez +Date: Thu, 20 Feb 2020 18:29:34 +0200 +Subject: firmware: imx: misc: Align imx sc msg structs to 4 +Git-commit: 1e6a4eba693ac72e6f91b4252458c933110e5f4c +Patch-mainline: v5.6-rc5 +References: git-fixes + +The imx SC api strongly assumes that messages are composed out of +4-bytes words but some of our message structs have odd sizeofs. + +This produces many oopses with CONFIG_KASAN=y: + + BUG: KASAN: stack-out-of-bounds in imx_mu_send_data+0x108/0x1f0 + +It shouldn't cause an issues in normal use because these structs are +always allocated on the stack. + +Fixes: 15e1f2bc8b3b ("firmware: imx: add misc svc support") +Signed-off-by: Leonard Crestez +Signed-off-by: Shawn Guo +Acked-by: Nicolas Saenz Julienne +--- + drivers/firmware/imx/misc.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +--- a/drivers/firmware/imx/misc.c ++++ b/drivers/firmware/imx/misc.c +@@ -16,18 +16,18 @@ struct imx_sc_msg_req_misc_set_ctrl { + u32 ctrl; + u32 val; + u16 resource; +-} __packed; ++} __packed __aligned(4); + + struct imx_sc_msg_req_misc_get_ctrl { + struct imx_sc_rpc_msg hdr; + u32 ctrl; + u16 resource; +-} __packed; ++} __packed __aligned(4); + + struct imx_sc_msg_resp_misc_get_ctrl { + struct imx_sc_rpc_msg hdr; + u32 val; +-} __packed; ++} __packed __aligned(4); + + /* + * This function sets a miscellaneous control value. diff --git a/patches.suse/firmware-imx-scu-ensure-sequential-tx.patch b/patches.suse/firmware-imx-scu-ensure-sequential-tx.patch new file mode 100644 index 0000000..c7c2008 --- /dev/null +++ b/patches.suse/firmware-imx-scu-ensure-sequential-tx.patch @@ -0,0 +1,85 @@ +From: Leonard Crestez +Date: Thu, 20 Feb 2020 18:10:01 +0200 +Subject: firmware: imx: scu: Ensure sequential TX +Git-commit: 26d0fba29c96241de8a9d16f045b1de49875884c +Patch-mainline: v5.6-rc5 +References: git-fixes + +SCU requires that all messages words are written sequentially but linux MU +driver implements multiple independent channels for each register so ordering +between different channels must be ensured by SCU API interface. + +Wait for tx_done before every send to ensure that no queueing happens at the +mailbox channel level. + +Fixes: edbee095fafb ("firmware: imx: add SCU firmware driver support") +Signed-off-by: Leonard Crestez +Cc: +Reviewed-by: Peng Fan +Reviewed-by:: Oleksij Rempel +Signed-off-by: Shawn Guo +Acked-by: Nicolas Saenz Julienne +--- + drivers/firmware/imx/imx-scu.c | 27 +++++++++++++++++++++++++++ + 1 file changed, 27 insertions(+) + +diff --git a/drivers/firmware/imx/imx-scu.c b/drivers/firmware/imx/imx-scu.c +index 03b43b7a6d1d..f71eaa5bf52d 100644 +--- a/drivers/firmware/imx/imx-scu.c ++++ b/drivers/firmware/imx/imx-scu.c +@@ -29,6 +29,7 @@ struct imx_sc_chan { + struct mbox_client cl; + struct mbox_chan *ch; + int idx; ++ struct completion tx_done; + }; + + struct imx_sc_ipc { +@@ -100,6 +101,14 @@ int imx_scu_get_handle(struct imx_sc_ipc **ipc) + } + EXPORT_SYMBOL(imx_scu_get_handle); + ++/* Callback called when the word of a message is ack-ed, eg read by SCU */ ++static void imx_scu_tx_done(struct mbox_client *cl, void *mssg, int r) ++{ ++ struct imx_sc_chan *sc_chan = container_of(cl, struct imx_sc_chan, cl); ++ ++ complete(&sc_chan->tx_done); ++} ++ + static void imx_scu_rx_callback(struct mbox_client *c, void *msg) + { + struct imx_sc_chan *sc_chan = container_of(c, struct imx_sc_chan, cl); +@@ -149,6 +158,19 @@ static int imx_scu_ipc_write(struct imx_sc_ipc *sc_ipc, void *msg) + + for (i = 0; i < hdr->size; i++) { + sc_chan = &sc_ipc->chans[i % 4]; ++ ++ /* ++ * SCU requires that all messages words are written ++ * sequentially but linux MU driver implements multiple ++ * independent channels for each register so ordering between ++ * different channels must be ensured by SCU API interface. ++ * ++ * Wait for tx_done before every send to ensure that no ++ * queueing happens at the mailbox channel level. ++ */ ++ wait_for_completion(&sc_chan->tx_done); ++ reinit_completion(&sc_chan->tx_done); ++ + ret = mbox_send_message(sc_chan->ch, &data[i]); + if (ret < 0) + return ret; +@@ -247,6 +269,11 @@ static int imx_scu_probe(struct platform_device *pdev) + cl->knows_txdone = true; + cl->rx_callback = imx_scu_rx_callback; + ++ /* Initial tx_done completion as "done" */ ++ cl->tx_done = imx_scu_tx_done; ++ init_completion(&sc_chan->tx_done); ++ complete(&sc_chan->tx_done); ++ + sc_chan->sc_ipc = sc_ipc; + sc_chan->idx = i % 4; + sc_chan->ch = mbox_request_channel_byname(cl, chan_name); + diff --git a/patches.suse/firmware-imx-scu-pd-align-imx-sc-msg-structs-to-4.patch b/patches.suse/firmware-imx-scu-pd-align-imx-sc-msg-structs-to-4.patch new file mode 100644 index 0000000..206ec48 --- /dev/null +++ b/patches.suse/firmware-imx-scu-pd-align-imx-sc-msg-structs-to-4.patch @@ -0,0 +1,36 @@ +From: Leonard Crestez +Date: Thu, 20 Feb 2020 18:29:35 +0200 +Subject: firmware: imx: scu-pd: Align imx sc msg structs to 4 +Git-commit: 7c1a1c814ccc858633c761951c2546041202b24e +Patch-mainline: v5.6-rc5 +References: git-fixes + +The imx SC api strongly assumes that messages are composed out of +4-bytes words but some of our message structs have odd sizeofs. + +This produces many oopses with CONFIG_KASAN=y. + +Fix by marking with __aligned(4). + +Fixes: c800cd7824bd ("firmware: imx: add SCU power domain driver") +Signed-off-by: Leonard Crestez +Signed-off-by: Shawn Guo +Acked-by: Nicolas Saenz Julienne +--- + drivers/firmware/imx/scu-pd.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/firmware/imx/scu-pd.c b/drivers/firmware/imx/scu-pd.c +index b556612207e5..af3ae0087de4 100644 +--- a/drivers/firmware/imx/scu-pd.c ++++ b/drivers/firmware/imx/scu-pd.c +@@ -61,7 +61,7 @@ struct imx_sc_msg_req_set_resource_power_mode { + struct imx_sc_rpc_msg hdr; + u16 resource; + u8 mode; +-} __packed; ++} __packed __aligned(4); + + #define IMX_SCU_PD_NAME_SIZE 20 + struct imx_sc_pm_domain { + diff --git a/patches.suse/fix-memory-leak-in-large-read-decrypt-offload.patch b/patches.suse/fix-memory-leak-in-large-read-decrypt-offload.patch new file mode 100644 index 0000000..ad03ecf --- /dev/null +++ b/patches.suse/fix-memory-leak-in-large-read-decrypt-offload.patch @@ -0,0 +1,41 @@ +From: Steve French +Date: Sat, 26 Oct 2019 16:00:44 -0500 +Subject: [PATCH] fix memory leak in large read decrypt offload +Git-commit: a08d897bc04f23c608dadde5c31ef194911e78bb +References: bsc#1144333 +Patch-mainline: v5.4-rc6 + +Spotted by Ronnie. + +Reviewed-by: Ronnie Sahlberg +Signed-off-by: Steve French +Acked-by: Paulo Alcantara +--- + fs/cifs/smb2ops.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c +index 4c0922596467..cd55af9b7cc5 100644 +--- a/fs/cifs/smb2ops.c ++++ b/fs/cifs/smb2ops.c +@@ -4084,6 +4084,7 @@ static void smb2_decrypt_offload(struct work_struct *work) + + kfree(dw->ppages); + cifs_small_buf_release(dw->buf); ++ kfree(dw); + } + + +@@ -4157,7 +4158,7 @@ receive_encrypted_read(struct TCP_Server_Info *server, struct mid_q_entry **mid, + dw->server = server; + dw->ppages = pages; + dw->len = len; +- queue_work(cifsiod_wq, &dw->decrypt); ++ queue_work(decrypt_wq, &dw->decrypt); + *num_mids = 0; /* worker thread takes care of finding mid */ + return -1; + } +-- +2.25.1 + + diff --git a/patches.suse/floppy-check-FDC-index-for-errors-before-assigning-i.patch b/patches.suse/floppy-check-FDC-index-for-errors-before-assigning-i.patch new file mode 100644 index 0000000..6f98411 --- /dev/null +++ b/patches.suse/floppy-check-FDC-index-for-errors-before-assigning-i.patch @@ -0,0 +1,69 @@ +From 2e90ca68b0d2f5548804f22f0dd61145516171e3 Mon Sep 17 00:00:00 2001 +From: Linus Torvalds +Date: Fri, 21 Feb 2020 12:43:35 -0800 +Subject: [PATCH] floppy: check FDC index for errors before assigning it +Git-commit: 2e90ca68b0d2f5548804f22f0dd61145516171e3 +Patch-mainline: v5.6-rc4 +References: CVE-2020-9383 bsc#1165111 + +Jordy Zomer reported a KASAN out-of-bounds read in the floppy driver in +wait_til_ready(). + +Which on the face of it can't happen, since as Willy Tarreau points out, +the function does no particular memory access. Except through the FDCS +macro, which just indexes a static allocation through teh current fdc, +which is always checked against N_FDC. + +Except the checking happens after we've already assigned the value. + +The floppy driver is a disgrace (a lot of it going back to my original +horrd "design"), and has no real maintainer. Nobody has the hardware, +and nobody really cares. But it still gets used in virtual environment +because it's one of those things that everybody supports. + +The whole thing should be re-written, or at least parts of it should be +seriously cleaned up. The 'current fdc' index, which is used by the +FDCS macro, and which is often shadowed by a local 'fdc' variable, is a +prime example of how not to write code. + +But because nobody has the hardware or the motivation, let's just fix up +the immediate problem with a nasty band-aid: test the fdc index before +actually assigning it to the static 'fdc' variable. + +Reported-by: Jordy Zomer +Cc: Willy Tarreau +Cc: Dan Carpenter +Signed-off-by: Linus Torvalds +Acked-by: Takashi Iwai + +--- + drivers/block/floppy.c | 7 +++++-- + 1 file changed, 5 insertions(+), 2 deletions(-) + +diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c +index cd3612e4e2e1..8ef65c085640 100644 +--- a/drivers/block/floppy.c ++++ b/drivers/block/floppy.c +@@ -853,14 +853,17 @@ static void reset_fdc_info(int mode) + /* selects the fdc and drive, and enables the fdc's input/dma. */ + static void set_fdc(int drive) + { ++ unsigned int new_fdc = fdc; ++ + if (drive >= 0 && drive < N_DRIVE) { +- fdc = FDC(drive); ++ new_fdc = FDC(drive); + current_drive = drive; + } +- if (fdc != 1 && fdc != 0) { ++ if (new_fdc >= N_FDC) { + pr_info("bad fdc value\n"); + return; + } ++ fdc = new_fdc; + set_dor(fdc, ~0, 8); + #if N_FDC > 1 + set_dor(1 - fdc, ~8, 0); +-- +2.16.4 + diff --git a/patches.suse/fs-cifs-Initialize-filesystem-timestamp-ranges.patch b/patches.suse/fs-cifs-Initialize-filesystem-timestamp-ranges.patch new file mode 100644 index 0000000..b3a571a --- /dev/null +++ b/patches.suse/fs-cifs-Initialize-filesystem-timestamp-ranges.patch @@ -0,0 +1,62 @@ +From: Deepa Dinamani +Date: Fri, 22 Mar 2019 14:32:35 -0700 +Subject: [PATCH] fs: cifs: Initialize filesystem timestamp ranges +Git-commit: cb7a69e605908c34aad47644afeb26a765ade8d7 +References: bsc#1144333 +Patch-mainline: v5.3-rc7 + +Fill in the appropriate limits to avoid inconsistencies +in the vfs cached inode times when timestamps are +outside the permitted range. + +Also fixed cnvrtDosUnixTm calculations to avoid int overflow +while computing maximum date. + + References: + +http://cifs.com/ + +https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-cifs/d416ff7c-c536-406e-a951-4f04b2fd1d2b + +Signed-off-by: Deepa Dinamani +Acked-by: Jeff Layton +Cc: sfrench@samba.org +Cc: linux-cifs@vger.kernel.org +Acked-by: Paulo Alcantara +--- + fs/cifs/netmisc.c | 13 +++++++------ + 1 file changed, 7 insertions(+), 6 deletions(-) + +--- a/fs/cifs/netmisc.c ++++ b/fs/cifs/netmisc.c +@@ -962,7 +962,8 @@ static const int total_days_of_prev_mont + struct timespec cnvrtDosUnixTm(__le16 le_date, __le16 le_time, int offset) + { + struct timespec ts; +- int sec, min, days, month, year; ++ int sec, days; ++ int min, day, month, year; + u16 date = le16_to_cpu(le_date); + u16 time = le16_to_cpu(le_time); + SMB_TIME *st = (SMB_TIME *)&time; +@@ -978,15 +979,15 @@ struct timespec cnvrtDosUnixTm(__le16 le + sec += 60 * 60 * st->Hours; + if (st->Hours > 24) + cifs_dbg(VFS, "illegal hours %d\n", st->Hours); +- days = sd->Day; ++ day = sd->Day; + month = sd->Month; +- if (days < 1 || days > 31 || month < 1 || month > 12) { +- cifs_dbg(VFS, "illegal date, month %d day: %d\n", month, days); +- days = clamp(days, 1, 31); ++ if (day < 1 || day > 31 || month < 1 || month > 12) { ++ cifs_dbg(VFS, "illegal date, month %d day: %d\n", month, day); ++ day = clamp(day, 1, 31); + month = clamp(month, 1, 12); + } + month -= 1; +- days += total_days_of_prev_months[month]; ++ days = day + total_days_of_prev_months[month]; + days += 3652; /* account for difference in days between 1980 and 1970 */ + year = sd->Year; + days += year * 365; diff --git a/patches.suse/fs-cifs-cifssmb-c-use-true-false-for-bool-variable.patch b/patches.suse/fs-cifs-cifssmb-c-use-true-false-for-bool-variable.patch new file mode 100644 index 0000000..146c58e --- /dev/null +++ b/patches.suse/fs-cifs-cifssmb-c-use-true-false-for-bool-variable.patch @@ -0,0 +1,46 @@ +From: zhengbin +Date: Wed, 25 Dec 2019 11:30:21 +0800 +Subject: [PATCH] fs/cifs/cifssmb.c: use true,false for bool variable +Git-commit: 01d1bd76a170c1cf1864b3b3ef1f8502f189148e +References: bsc#1144333 +Patch-mainline: v5.6-rc1 + +Fixes coccicheck warning: + +fs/cifs/cifssmb.c:4622:3-22: WARNING: Assignment of 0/1 to bool variable +fs/cifs/cifssmb.c:4756:3-22: WARNING: Assignment of 0/1 to bool variable + +Reported-by: Hulk Robot +Signed-off-by: zhengbin +Signed-off-by: Steve French +Acked-by: Paulo Alcantara +--- + fs/cifs/cifssmb.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c +index cc86a67225d1..a481296f417f 100644 +--- a/fs/cifs/cifssmb.c ++++ b/fs/cifs/cifssmb.c +@@ -4619,7 +4619,7 @@ CIFSFindFirst(const unsigned int xid, struct cifs_tcon *tcon, + psrch_inf->unicode = false; + + psrch_inf->ntwrk_buf_start = (char *)pSMBr; +- psrch_inf->smallBuf = 0; ++ psrch_inf->smallBuf = false; + psrch_inf->srch_entries_start = + (char *) &pSMBr->hdr.Protocol + + le16_to_cpu(pSMBr->t2.DataOffset); +@@ -4753,7 +4753,7 @@ int CIFSFindNext(const unsigned int xid, struct cifs_tcon *tcon, + cifs_buf_release(psrch_inf->ntwrk_buf_start); + psrch_inf->srch_entries_start = response_data; + psrch_inf->ntwrk_buf_start = (char *)pSMB; +- psrch_inf->smallBuf = 0; ++ psrch_inf->smallBuf = false; + if (parms->EndofSearch) + psrch_inf->endOfSearch = true; + else +-- +2.25.1 + + diff --git a/patches.suse/fs-cifs-cifsssmb-remove-redundant-assignment-to-variable-ret.patch b/patches.suse/fs-cifs-cifsssmb-remove-redundant-assignment-to-variable-ret.patch new file mode 100644 index 0000000..0003158 --- /dev/null +++ b/patches.suse/fs-cifs-cifsssmb-remove-redundant-assignment-to-variable-ret.patch @@ -0,0 +1,37 @@ +From: Colin Ian King +Date: Tue, 23 Jul 2019 16:09:19 +0100 +Subject: [PATCH] fs: cifs: cifsssmb: remove redundant assignment to variable + ret +Git-commit: 1afdea4f19a97ed98f65c41fd11c77e5264838ae +References: bsc#1144333 +Patch-mainline: v5.4-rc1 + +The variable ret is being initialized however this is never read +and later it is being reassigned to a new value. The initialization +is redundant and hence can be removed. + +Addresses-Coverity: ("Unused Value") +Signed-off-by: Colin Ian King +Signed-off-by: Steve French +Acked-by: Paulo Alcantara +--- + fs/cifs/cifssmb.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c +index 3907653e63c7..dbee2132e419 100644 +--- a/fs/cifs/cifssmb.c ++++ b/fs/cifs/cifssmb.c +@@ -1393,7 +1393,7 @@ int + CIFS_open(const unsigned int xid, struct cifs_open_parms *oparms, int *oplock, + FILE_ALL_INFO *buf) + { +- int rc = -EACCES; ++ int rc; + OPEN_REQ *req = NULL; + OPEN_RSP *rsp = NULL; + int bytes_returned; +-- +2.25.1 + + diff --git a/patches.suse/fs-cifs-mute-Wunused-const-variable-message.patch b/patches.suse/fs-cifs-mute-Wunused-const-variable-message.patch new file mode 100644 index 0000000..9a928f6 --- /dev/null +++ b/patches.suse/fs-cifs-mute-Wunused-const-variable-message.patch @@ -0,0 +1,42 @@ +From: Austin Kim +Date: Tue, 1 Oct 2019 16:34:13 +0900 +Subject: [PATCH] fs: cifs: mute -Wunused-const-variable message +Git-commit: dd19c106a36690b47bb1acc68372f2b472b495b8 +References: bsc#1144333 +Patch-mainline: v5.4-rc3 + +After 'Initial git repository build' commit, +'mapping_table_ERRHRD' variable has not been used. + +So 'mapping_table_ERRHRD' const variable could be removed +to mute below warning message: + + fs/cifs/netmisc.c:120:40: warning: unused variable 'mapping_table_ERRHRD' [-Wunused-const-variable] + static const struct smb_to_posix_error mapping_table_ERRHRD[] = { + ^ +Signed-off-by: Austin Kim +Signed-off-by: Steve French +Acked-by: Paulo Alcantara +--- + fs/cifs/netmisc.c | 4 ---- + 1 file changed, 4 deletions(-) + +diff --git a/fs/cifs/netmisc.c b/fs/cifs/netmisc.c +index 49c17ee18254..9b41436fb8db 100644 +--- a/fs/cifs/netmisc.c ++++ b/fs/cifs/netmisc.c +@@ -117,10 +117,6 @@ static const struct smb_to_posix_error mapping_table_ERRSRV[] = { + {0, 0} + }; + +-static const struct smb_to_posix_error mapping_table_ERRHRD[] = { +- {0, 0} +-}; +- + /* + * Convert a string containing text IPv4 or IPv6 address to binary form. + * +-- +2.25.1 + + diff --git a/patches.suse/fs-cifs-sess-c-Remove-set-but-not-used-variable-capabilities-.patch b/patches.suse/fs-cifs-sess-c-Remove-set-but-not-used-variable-capabilities-.patch new file mode 100644 index 0000000..5dc879f --- /dev/null +++ b/patches.suse/fs-cifs-sess-c-Remove-set-but-not-used-variable-capabilities-.patch @@ -0,0 +1,46 @@ +From: zhengbin +Date: Tue, 24 Sep 2019 10:13:47 +0800 +Subject: [PATCH] fs/cifs/sess.c: Remove set but not used variable + 'capabilities' +Git-commit: 8559ad8e89185ca55d8c9ef1e0b20f58578a4055 +References: bsc#1144333 +Patch-mainline: v5.4-rc1 + +Fixes gcc '-Wunused-but-set-variable' warning: + +fs/cifs/sess.c: In function sess_auth_lanman: +fs/cifs/sess.c:910:8: warning: variable capabilities set but not used [-Wunused-but-set-variable] + +Reported-by: Hulk Robot +Signed-off-by: zhengbin +Signed-off-by: Steve French +Acked-by: Paulo Alcantara +--- + fs/cifs/sess.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/fs/cifs/sess.c b/fs/cifs/sess.c +index 4c764ff7edd2..85bd644f9773 100644 +--- a/fs/cifs/sess.c ++++ b/fs/cifs/sess.c +@@ -698,7 +698,6 @@ sess_auth_lanman(struct sess_data *sess_data) + char *bcc_ptr; + struct cifs_ses *ses = sess_data->ses; + char lnm_session_key[CIFS_AUTH_RESP_SIZE]; +- __u32 capabilities; + __u16 bytes_remaining; + + /* lanman 2 style sessionsetup */ +@@ -709,7 +708,7 @@ sess_auth_lanman(struct sess_data *sess_data) + + pSMB = (SESSION_SETUP_ANDX *)sess_data->iov[0].iov_base; + bcc_ptr = sess_data->iov[2].iov_base; +- capabilities = cifs_ssetup_hdr(ses, pSMB); ++ (void)cifs_ssetup_hdr(ses, pSMB); + + pSMB->req.hdr.Flags2 &= ~SMBFLG2_UNICODE; + +-- +2.25.1 + + diff --git a/patches.suse/fs-cifs-smb2ops-c-use-true-false-for-bool-variable.patch b/patches.suse/fs-cifs-smb2ops-c-use-true-false-for-bool-variable.patch new file mode 100644 index 0000000..94148f9 --- /dev/null +++ b/patches.suse/fs-cifs-smb2ops-c-use-true-false-for-bool-variable.patch @@ -0,0 +1,36 @@ +From: zhengbin +Date: Wed, 25 Dec 2019 11:30:20 +0800 +Subject: [PATCH] fs/cifs/smb2ops.c: use true,false for bool variable +Git-commit: 720aec01262d49dbce17d862d8cdbfd3cfef4261 +References: bsc#1144333 +Patch-mainline: v5.6-rc1 + +Fixes coccicheck warning: + +fs/cifs/smb2ops.c:807:2-36: WARNING: Assignment of 0/1 to bool variable + +Reported-by: Hulk Robot +Signed-off-by: zhengbin +Signed-off-by: Steve French +Acked-by: Paulo Alcantara +--- + fs/cifs/smb2ops.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c +index 6250370c1170..2c500226315d 100644 +--- a/fs/cifs/smb2ops.c ++++ b/fs/cifs/smb2ops.c +@@ -804,7 +804,7 @@ int open_shroot(unsigned int xid, struct cifs_tcon *tcon, struct cifs_fid *pfid) + sizeof(struct smb2_file_all_info), + &rsp_iov[1], sizeof(struct smb2_file_all_info), + (char *)&tcon->crfid.file_all_info)) +- tcon->crfid.file_all_info_is_valid = 1; ++ tcon->crfid.file_all_info_is_valid = true; + + oshr_exit: + mutex_unlock(&tcon->crfid.fid_mutex); +-- +2.25.1 + + diff --git a/patches.suse/fs-cifs-smb2pdu-c-Make-SMB2_notify_init-static.patch b/patches.suse/fs-cifs-smb2pdu-c-Make-SMB2_notify_init-static.patch new file mode 100644 index 0000000..d10efc5 --- /dev/null +++ b/patches.suse/fs-cifs-smb2pdu-c-Make-SMB2_notify_init-static.patch @@ -0,0 +1,36 @@ +From: zhengbin +Date: Mon, 23 Sep 2019 15:06:18 +0800 +Subject: [PATCH] fs/cifs/smb2pdu.c: Make SMB2_notify_init static +Git-commit: 388962e8e9ce8b253e91cbaed94e78a07dc92d84 +References: bsc#1144333 +Patch-mainline: v5.4-rc1 + +Fix sparse warnings: + +fs/cifs/smb2pdu.c:3200:1: warning: symbol 'SMB2_notify_init' was not declared. Should it be static? + +Reported-by: Hulk Robot +Signed-off-by: zhengbin +Signed-off-by: Steve French +Acked-by: Paulo Alcantara +--- + fs/cifs/smb2pdu.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c +index 5f2491efd950..ea08e6159481 100644 +--- a/fs/cifs/smb2pdu.c ++++ b/fs/cifs/smb2pdu.c +@@ -3181,7 +3181,7 @@ SMB2_get_srv_num(const unsigned int xid, struct cifs_tcon *tcon, + * See MS-SMB2 2.2.35 and 2.2.36 + */ + +-int ++static int + SMB2_notify_init(const unsigned int xid, struct smb_rqst *rqst, + struct cifs_tcon *tcon, u64 persistent_fid, u64 volatile_fid, + u32 completion_filter, bool watch_tree) +-- +2.25.1 + + diff --git a/patches.suse/fs-xfs-fix-f_ffree-value-for-statfs-when-project-quo.patch b/patches.suse/fs-xfs-fix-f_ffree-value-for-statfs-when-project-quo.patch new file mode 100644 index 0000000..c8614f3 --- /dev/null +++ b/patches.suse/fs-xfs-fix-f_ffree-value-for-statfs-when-project-quo.patch @@ -0,0 +1,36 @@ +From de7243057e7cefa923fa5f467c0f1ec24eef41d2 Mon Sep 17 00:00:00 2001 +From: Ye Yin +Date: Fri, 23 Nov 2018 09:55:18 -0800 +Subject: [PATCH] fs/xfs: fix f_ffree value for statfs when project quota is + set +Git-commit: de7243057e7cefa923fa5f467c0f1ec24eef41d2 +Patch-mainline: v4.20-rc6 +References: bsc#1165985 + +When project is set, we should use inode limit minus the used count + +Signed-off-by: Ye Yin +Reviewed-by: Darrick J. Wong +Signed-off-by: Darrick J. Wong +Acked-by: Anthony Iliopoulos + +--- + fs/xfs/xfs_qm_bhv.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/fs/xfs/xfs_qm_bhv.c b/fs/xfs/xfs_qm_bhv.c +index 73a1d77ec187..3091e4bc04ef 100644 +--- a/fs/xfs/xfs_qm_bhv.c ++++ b/fs/xfs/xfs_qm_bhv.c +@@ -40,7 +40,7 @@ xfs_fill_statvfs_from_dquot( + statp->f_files = limit; + statp->f_ffree = + (statp->f_files > dqp->q_res_icount) ? +- (statp->f_ffree - dqp->q_res_icount) : 0; ++ (statp->f_files - dqp->q_res_icount) : 0; + } + } + +-- +2.16.4 + diff --git a/patches.suse/ftrace-kprobe-show-the-maxactive-number-on-kprobe_events.patch b/patches.suse/ftrace-kprobe-show-the-maxactive-number-on-kprobe_events.patch new file mode 100644 index 0000000..f3883fb --- /dev/null +++ b/patches.suse/ftrace-kprobe-show-the-maxactive-number-on-kprobe_events.patch @@ -0,0 +1,35 @@ +From: Masami Hiramatsu +Date: Tue, 24 Mar 2020 16:34:48 +0900 +Subject: ftrace/kprobe: Show the maxactive number on kprobe_events +Git-commit: 6a13a0d7b4d1171ef9b80ad69abc37e1daa941b3 +Patch-mainline: v5.7-rc1 +References: git-fixes + +Show maxactive parameter on kprobe_events. +This allows user to save the current configuration and +restore it without losing maxactive parameter. + +Link: http://lkml.kernel.org/r/4762764a-6df7-bc93-ed60-e336146dce1f@gmail.com +Link: http://lkml.kernel.org/r/158503528846.22706.5549974121212526020.stgit@devnote2 + +Cc: stable@vger.kernel.org +Fixes: 696ced4fb1d76 ("tracing/kprobes: expose maxactive for kretprobe in kprobe_events") +Reported-by: Taeung Song +Signed-off-by: Masami Hiramatsu +Signed-off-by: Steven Rostedt (VMware) +Acked-by: Miroslav Benes +--- + kernel/trace/trace_kprobe.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/kernel/trace/trace_kprobe.c ++++ b/kernel/trace/trace_kprobe.c +@@ -857,6 +857,8 @@ static int probes_seq_show(struct seq_fi + int i; + + seq_putc(m, trace_kprobe_is_return(tk) ? 'r' : 'p'); ++ if (trace_kprobe_is_return(tk) && tk->rp.maxactive) ++ seq_printf(m, "%d", tk->rp.maxactive); + seq_printf(m, ":%s/%s", tk->tp.call.class->system, + trace_event_name(&tk->tp.call)); + diff --git a/patches.suse/gtp-make-sure-only-SOCK_DGRAM-UDP-sockets-are-accept.patch b/patches.suse/gtp-make-sure-only-SOCK_DGRAM-UDP-sockets-are-accept.patch new file mode 100644 index 0000000..351f9f8 --- /dev/null +++ b/patches.suse/gtp-make-sure-only-SOCK_DGRAM-UDP-sockets-are-accept.patch @@ -0,0 +1,115 @@ +From: Eric Dumazet +Date: Tue, 21 Jan 2020 23:17:14 -0800 +Subject: gtp: make sure only SOCK_DGRAM UDP sockets are accepted +Git-commit: 940ba14986657a50c15f694efca1beba31fa568f +Patch-mainline: 5.5 +References: networking-stable-20_01_27 + +A malicious user could use RAW sockets and fool +GTP using them as standard SOCK_DGRAM UDP sockets. + +BUG: KMSAN: uninit-value in udp_tunnel_encap_enable include/net/udp_tunnel.h:174 [inline] +BUG: KMSAN: uninit-value in setup_udp_tunnel_sock+0x45e/0x6f0 net/ipv4/udp_tunnel.c:85 +CPU: 0 PID: 11262 Comm: syz-executor613 Not tainted 5.5.0-rc5-syzkaller #0 +Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011 +Call Trace: + __dump_stack lib/dump_stack.c:77 [inline] + dump_stack+0x1c9/0x220 lib/dump_stack.c:118 + kmsan_report+0xf7/0x1e0 mm/kmsan/kmsan_report.c:118 + __msan_warning+0x58/0xa0 mm/kmsan/kmsan_instr.c:215 + udp_tunnel_encap_enable include/net/udp_tunnel.h:174 [inline] + setup_udp_tunnel_sock+0x45e/0x6f0 net/ipv4/udp_tunnel.c:85 + gtp_encap_enable_socket+0x37f/0x5a0 drivers/net/gtp.c:827 + gtp_encap_enable drivers/net/gtp.c:844 [inline] + gtp_newlink+0xfb/0x1e50 drivers/net/gtp.c:666 + __rtnl_newlink net/core/rtnetlink.c:3305 [inline] + rtnl_newlink+0x2973/0x3920 net/core/rtnetlink.c:3363 + rtnetlink_rcv_msg+0x1153/0x1570 net/core/rtnetlink.c:5424 + netlink_rcv_skb+0x451/0x650 net/netlink/af_netlink.c:2477 + rtnetlink_rcv+0x50/0x60 net/core/rtnetlink.c:5442 + netlink_unicast_kernel net/netlink/af_netlink.c:1302 [inline] + netlink_unicast+0xf9e/0x1100 net/netlink/af_netlink.c:1328 + netlink_sendmsg+0x1248/0x14d0 net/netlink/af_netlink.c:1917 + sock_sendmsg_nosec net/socket.c:639 [inline] + sock_sendmsg net/socket.c:659 [inline] + ____sys_sendmsg+0x12b6/0x1350 net/socket.c:2330 + ___sys_sendmsg net/socket.c:2384 [inline] + __sys_sendmsg+0x451/0x5f0 net/socket.c:2417 + __do_sys_sendmsg net/socket.c:2426 [inline] + __se_sys_sendmsg+0x97/0xb0 net/socket.c:2424 + __x64_sys_sendmsg+0x4a/0x70 net/socket.c:2424 + do_syscall_64+0xb8/0x160 arch/x86/entry/common.c:296 + entry_SYSCALL_64_after_hwframe+0x44/0xa9 +RIP: 0033:0x441359 +Code: e8 ac e8 ff ff 48 83 c4 18 c3 0f 1f 80 00 00 00 00 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 0f 83 eb 08 fc ff c3 66 2e 0f 1f 84 00 00 00 00 +RSP: 002b:00007fff1cd0ac28 EFLAGS: 00000246 ORIG_RAX: 000000000000002e +RAX: ffffffffffffffda RBX: 0000000000000000 RCX: 0000000000441359 +RDX: 0000000000000000 RSI: 0000000020000100 RDI: 0000000000000003 +RBP: 00000000006cb018 R08: 00000000004002c8 R09: 00000000004002c8 +R10: 00000000004002c8 R11: 0000000000000246 R12: 00000000004020d0 +R13: 0000000000402160 R14: 0000000000000000 R15: 0000000000000000 + +Uninit was created at: + kmsan_save_stack_with_flags+0x3c/0x90 mm/kmsan/kmsan.c:144 + kmsan_internal_alloc_meta_for_pages mm/kmsan/kmsan_shadow.c:307 [inline] + kmsan_alloc_page+0x12a/0x310 mm/kmsan/kmsan_shadow.c:336 + __alloc_pages_nodemask+0x57f2/0x5f60 mm/page_alloc.c:4800 + alloc_pages_current+0x67d/0x990 mm/mempolicy.c:2207 + alloc_pages include/linux/gfp.h:534 [inline] + alloc_slab_page+0x111/0x12f0 mm/slub.c:1511 + allocate_slab mm/slub.c:1656 [inline] + new_slab+0x2bc/0x1130 mm/slub.c:1722 + new_slab_objects mm/slub.c:2473 [inline] + ___slab_alloc+0x1533/0x1f30 mm/slub.c:2624 + __slab_alloc mm/slub.c:2664 [inline] + slab_alloc_node mm/slub.c:2738 [inline] + slab_alloc mm/slub.c:2783 [inline] + kmem_cache_alloc+0xb23/0xd70 mm/slub.c:2788 + sk_prot_alloc+0xf2/0x620 net/core/sock.c:1597 + sk_alloc+0xf0/0xbe0 net/core/sock.c:1657 + inet_create+0x7c7/0x1370 net/ipv4/af_inet.c:321 + __sock_create+0x8eb/0xf00 net/socket.c:1420 + sock_create net/socket.c:1471 [inline] + __sys_socket+0x1a1/0x600 net/socket.c:1513 + __do_sys_socket net/socket.c:1522 [inline] + __se_sys_socket+0x8d/0xb0 net/socket.c:1520 + __x64_sys_socket+0x4a/0x70 net/socket.c:1520 + do_syscall_64+0xb8/0x160 arch/x86/entry/common.c:296 + entry_SYSCALL_64_after_hwframe+0x44/0xa9 + +Fixes: 459aa660eb1d ("gtp: add initial driver for datapath of GPRS Tunneling Protocol (GTP-U)") +Signed-off-by: Eric Dumazet +Cc: Pablo Neira +Reported-by: syzbot +Signed-off-by: David S. Miller +Signed-off-by: Jiri Slaby +--- + drivers/net/gtp.c | 8 +++++--- + 1 file changed, 5 insertions(+), 3 deletions(-) + +--- a/drivers/net/gtp.c ++++ b/drivers/net/gtp.c +@@ -793,18 +793,20 @@ static struct sock *gtp_encap_enable_soc + return NULL; + } + +- if (sock->sk->sk_protocol != IPPROTO_UDP) { ++ sk = sock->sk; ++ if (sk->sk_protocol != IPPROTO_UDP || ++ sk->sk_type != SOCK_DGRAM || ++ (sk->sk_family != AF_INET && sk->sk_family != AF_INET6)) { + pr_debug("socket fd=%d not UDP\n", fd); + sk = ERR_PTR(-EINVAL); + goto out_sock; + } + +- if (rcu_dereference_sk_user_data(sock->sk)) { ++ if (rcu_dereference_sk_user_data(sk)) { + sk = ERR_PTR(-EBUSY); + goto out_sock; + } + +- sk = sock->sk; + sock_hold(sk); + + tuncfg.sk_user_data = gtp; diff --git a/patches.suse/gtp-use-__GFP_NOWARN-to-avoid-memalloc-warning.patch b/patches.suse/gtp-use-__GFP_NOWARN-to-avoid-memalloc-warning.patch new file mode 100644 index 0000000..ea77bcd --- /dev/null +++ b/patches.suse/gtp-use-__GFP_NOWARN-to-avoid-memalloc-warning.patch @@ -0,0 +1,66 @@ +From: Taehee Yoo +Date: Tue, 4 Feb 2020 03:24:59 +0000 +Subject: gtp: use __GFP_NOWARN to avoid memalloc warning +Git-commit: bd5cd35b782abf5437fbd01dfaee12437d20e832 +Patch-mainline: 5.6-rc1 +References: networking-stable-20_02_05 + +gtp hashtable size is received by user-space. +So, this hashtable size could be too large. If so, kmalloc will internally +print a warning message. +This warning message is actually not necessary for the gtp module. +So, this patch adds __GFP_NOWARN to avoid this message. + +Splat looks like: +[ 2171.200049][ T1860] WARNING: CPU: 1 PID: 1860 at mm/page_alloc.c:4713 __alloc_pages_nodemask+0x2f3/0x740 +[ 2171.238885][ T1860] Modules linked in: gtp veth openvswitch nsh nf_conncount nf_nat nf_conntrack nf_defrag_ipv] +[ 2171.262680][ T1860] CPU: 1 PID: 1860 Comm: gtp-link Not tainted 5.5.0+ #321 +[ 2171.263567][ T1860] Hardware name: innotek GmbH VirtualBox/VirtualBox, BIOS VirtualBox 12/01/2006 +[ 2171.264681][ T1860] RIP: 0010:__alloc_pages_nodemask+0x2f3/0x740 +[ 2171.265332][ T1860] Code: 64 fe ff ff 65 48 8b 04 25 c0 0f 02 00 48 05 f0 12 00 00 41 be 01 00 00 00 49 89 47 0 +[ 2171.267301][ T1860] RSP: 0018:ffff8880b51af1f0 EFLAGS: 00010246 +[ 2171.268320][ T1860] RAX: ffffed1016a35e43 RBX: 0000000000000000 RCX: 0000000000000000 +[ 2171.269517][ T1860] RDX: 0000000000000000 RSI: 000000000000000b RDI: 0000000000000000 +[ 2171.270305][ T1860] RBP: 0000000000040cc0 R08: ffffed1018893109 R09: dffffc0000000000 +[ 2171.275973][ T1860] R10: 0000000000000001 R11: ffffed1018893108 R12: 1ffff11016a35e43 +[ 2171.291039][ T1860] R13: 000000000000000b R14: 000000000000000b R15: 00000000000f4240 +[ 2171.292328][ T1860] FS: 00007f53cbc83740(0000) GS:ffff8880da000000(0000) knlGS:0000000000000000 +[ 2171.293409][ T1860] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 +[ 2171.294586][ T1860] CR2: 000055f540014508 CR3: 00000000b49f2004 CR4: 00000000000606e0 +[ 2171.295424][ T1860] Call Trace: +[ 2171.295756][ T1860] ? mark_held_locks+0xa5/0xe0 +[ 2171.296659][ T1860] ? __alloc_pages_slowpath+0x21b0/0x21b0 +[ 2171.298283][ T1860] ? gtp_encap_enable_socket+0x13e/0x400 [gtp] +[ 2171.298962][ T1860] ? alloc_pages_current+0xc1/0x1a0 +[ 2171.299475][ T1860] kmalloc_order+0x22/0x80 +[ 2171.299936][ T1860] kmalloc_order_trace+0x1d/0x140 +[ 2171.300437][ T1860] __kmalloc+0x302/0x3a0 +[ 2171.300896][ T1860] gtp_newlink+0x293/0xba0 [gtp] +[ ... ] + +Fixes: 459aa660eb1d ("gtp: add initial driver for datapath of GPRS Tunneling Protocol (GTP-U)") +Signed-off-by: Taehee Yoo +Signed-off-by: David S. Miller +Signed-off-by: Jiri Slaby +--- + drivers/net/gtp.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +--- a/drivers/net/gtp.c ++++ b/drivers/net/gtp.c +@@ -757,11 +757,13 @@ static int gtp_hashtable_new(struct gtp_ + { + int i; + +- gtp->addr_hash = kmalloc(sizeof(struct hlist_head) * hsize, GFP_KERNEL); ++ gtp->addr_hash = kmalloc(sizeof(struct hlist_head) * hsize, ++ GFP_KERNEL | __GFP_NOWARN); + if (gtp->addr_hash == NULL) + return -ENOMEM; + +- gtp->tid_hash = kmalloc(sizeof(struct hlist_head) * hsize, GFP_KERNEL); ++ gtp->tid_hash = kmalloc(sizeof(struct hlist_head) * hsize, ++ GFP_KERNEL | __GFP_NOWARN); + if (gtp->tid_hash == NULL) + goto err1; + diff --git a/patches.suse/hv_netvsc-Fix-memory-leak-when-removing-rndis-device.patch b/patches.suse/hv_netvsc-Fix-memory-leak-when-removing-rndis-device.patch new file mode 100644 index 0000000..ab899f6 --- /dev/null +++ b/patches.suse/hv_netvsc-Fix-memory-leak-when-removing-rndis-device.patch @@ -0,0 +1,59 @@ +From: Mohammed Gamal +Date: Tue, 14 Jan 2020 15:09:50 +0200 +Subject: hv_netvsc: Fix memory leak when removing rndis device +Git-commit: 536dc5df2808efbefc5acee334d3c4f701790ec0 +Patch-mainline: 5.5-rc7 +References: networking-stable-20_01_20 + +kmemleak detects the following memory leak when hot removing +a network device: + +unreferenced object 0xffff888083f63600 (size 256): + comm "kworker/0:1", pid 12, jiffies 4294831717 (age 1113.676s) + hex dump (first 32 bytes): + 00 40 c7 33 80 88 ff ff 00 00 00 00 10 00 00 00 .@.3............ + 00 00 00 00 ad 4e ad de ff ff ff ff 00 00 00 00 .....N.......... + backtrace: + [<00000000d4a8f5be>] rndis_filter_device_add+0x117/0x11c0 [hv_netvsc] + [<000000009c02d75b>] netvsc_probe+0x5e7/0xbf0 [hv_netvsc] + [<00000000ddafce23>] vmbus_probe+0x74/0x170 [hv_vmbus] + [<00000000046e64f1>] really_probe+0x22f/0xb50 + [<000000005cc35eb7>] driver_probe_device+0x25e/0x370 + [<0000000043c642b2>] bus_for_each_drv+0x11f/0x1b0 + [<000000005e3d09f0>] __device_attach+0x1c6/0x2f0 + [<00000000a72c362f>] bus_probe_device+0x1a6/0x260 + [<0000000008478399>] device_add+0x10a3/0x18e0 + [<00000000cf07b48c>] vmbus_device_register+0xe7/0x1e0 [hv_vmbus] + [<00000000d46cf032>] vmbus_add_channel_work+0x8ab/0x1770 [hv_vmbus] + [<000000002c94bb64>] process_one_work+0x919/0x17d0 + [<0000000096de6781>] worker_thread+0x87/0xb40 + [<00000000fbe7397e>] kthread+0x333/0x3f0 + [<000000004f844269>] ret_from_fork+0x3a/0x50 + +rndis_filter_device_add() allocates an instance of struct rndis_device +which never gets deallocated as rndis_filter_device_remove() sets +net_device->extension which points to the rndis_device struct to NULL, +leaving the rndis_device dangling. + +Since net_device->extension is eventually freed in free_netvsc_device(), +we refrain from setting it to NULL inside rndis_filter_device_remove() + +Signed-off-by: Mohammed Gamal +Reviewed-by: Haiyang Zhang +Signed-off-by: David S. Miller +Signed-off-by: Jiri Slaby +--- + drivers/net/hyperv/rndis_filter.c | 2 -- + 1 file changed, 2 deletions(-) + +--- a/drivers/net/hyperv/rndis_filter.c ++++ b/drivers/net/hyperv/rndis_filter.c +@@ -1316,8 +1316,6 @@ void rndis_filter_device_remove(struct h + /* Halt and release the rndis device */ + rndis_filter_halt_device(net_dev, rndis_dev); + +- net_dev->extension = NULL; +- + netvsc_device_remove(dev); + } + diff --git a/patches.suse/hwmon-adt7462-Fix-an-error-return-in-ADT7462_REG_VOL.patch b/patches.suse/hwmon-adt7462-Fix-an-error-return-in-ADT7462_REG_VOL.patch new file mode 100644 index 0000000..72a07ef --- /dev/null +++ b/patches.suse/hwmon-adt7462-Fix-an-error-return-in-ADT7462_REG_VOL.patch @@ -0,0 +1,40 @@ +From 44f2f882909fedfc3a56e4b90026910456019743 Mon Sep 17 00:00:00 2001 +From: Dan Carpenter +Date: Tue, 3 Mar 2020 13:16:08 +0300 +Subject: [PATCH] hwmon: (adt7462) Fix an error return in ADT7462_REG_VOLT() +Git-commit: 44f2f882909fedfc3a56e4b90026910456019743 +Patch-mainline: v5.6-rc5 +References: bsc#1051510 + +This is only called from adt7462_update_device(). The caller expects it +to return zero on error. I fixed a similar issue earlier in commit +a4bf06d58f21 ("hwmon: (adt7462) ADT7462_REG_VOLT_MAX() should return 0") +but I missed this one. + +Fixes: c0b4e3ab0c76 ("adt7462: new hwmon driver") +Signed-off-by: Dan Carpenter +Reviewed-by: Darrick J. Wong +Link: https://lore.kernel.org/r/20200303101608.kqjwfcazu2ylhi2a@kili.mountain +Signed-off-by: Guenter Roeck +Acked-by: Takashi Iwai + +--- + drivers/hwmon/adt7462.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/hwmon/adt7462.c b/drivers/hwmon/adt7462.c +index 9632e2e3c4bb..319a0519ebdb 100644 +--- a/drivers/hwmon/adt7462.c ++++ b/drivers/hwmon/adt7462.c +@@ -413,7 +413,7 @@ static int ADT7462_REG_VOLT(struct adt7462_data *data, int which) + return 0x95; + break; + } +- return -ENODEV; ++ return 0; + } + + /* Provide labels for sysfs */ +-- +2.16.4 + diff --git a/patches.suse/i2c-hix5hd2-add-missed-clk_disable_unprepare-in-remo.patch b/patches.suse/i2c-hix5hd2-add-missed-clk_disable_unprepare-in-remo.patch new file mode 100644 index 0000000..84dcc9e --- /dev/null +++ b/patches.suse/i2c-hix5hd2-add-missed-clk_disable_unprepare-in-remo.patch @@ -0,0 +1,35 @@ +From e1b9f99ff8c40bba6e59de9ad4a659447b1e4112 Mon Sep 17 00:00:00 2001 +From: Chuhong Yuan +Date: Mon, 4 Nov 2019 23:00:48 +0800 +Subject: [PATCH] i2c: hix5hd2: add missed clk_disable_unprepare in remove +Git-commit: e1b9f99ff8c40bba6e59de9ad4a659447b1e4112 +Patch-mainline: v5.6 +References: bsc#1051510 + +The driver forgets to disable and unprepare clk when remove. +Add a call to clk_disable_unprepare to fix it. + +Signed-off-by: Chuhong Yuan +Signed-off-by: Wolfram Sang +Cc: stable@kernel.org +Acked-by: Takashi Iwai + +--- + drivers/i2c/busses/i2c-hix5hd2.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/i2c/busses/i2c-hix5hd2.c b/drivers/i2c/busses/i2c-hix5hd2.c +index 8497c7a95dd4..224f830f77f9 100644 +--- a/drivers/i2c/busses/i2c-hix5hd2.c ++++ b/drivers/i2c/busses/i2c-hix5hd2.c +@@ -477,6 +477,7 @@ static int hix5hd2_i2c_remove(struct platform_device *pdev) + i2c_del_adapter(&priv->adap); + pm_runtime_disable(priv->dev); + pm_runtime_set_suspended(priv->dev); ++ clk_disable_unprepare(priv->clk); + + return 0; + } +-- +2.16.4 + diff --git a/patches.suse/i2c-jz4780-silence-log-flood-on-txabrt.patch b/patches.suse/i2c-jz4780-silence-log-flood-on-txabrt.patch new file mode 100644 index 0000000..cfc1250 --- /dev/null +++ b/patches.suse/i2c-jz4780-silence-log-flood-on-txabrt.patch @@ -0,0 +1,75 @@ +From 9e661cedcc0a072d91a32cb88e0515ea26e35711 Mon Sep 17 00:00:00 2001 +From: Wolfram Sang +Date: Wed, 12 Feb 2020 10:35:30 +0100 +Subject: [PATCH] i2c: jz4780: silence log flood on txabrt +Git-commit: 9e661cedcc0a072d91a32cb88e0515ea26e35711 +Patch-mainline: v5.6-rc4 +References: bsc#1051510 + +The printout for txabrt is way too talkative and is highly annoying with +scanning programs like 'i2cdetect'. Reduce it to the minimum, the rest +can be gained by I2C core debugging and datasheet information. Also, +make it a debug printout, it won't help the regular user. + +Fixes: ba92222ed63a ("i2c: jz4780: Add i2c bus controller driver for Ingenic JZ4780") +Reported-by: H. Nikolaus Schaller +Tested-by: H. Nikolaus Schaller +Signed-off-by: Wolfram Sang +Acked-by: Takashi Iwai + +--- + drivers/i2c/busses/i2c-jz4780.c | 36 ++---------------------------------- + 1 file changed, 2 insertions(+), 34 deletions(-) + +--- a/drivers/i2c/busses/i2c-jz4780.c ++++ b/drivers/i2c/busses/i2c-jz4780.c +@@ -82,25 +82,6 @@ + #define JZ4780_I2C_STA_TFNF BIT(1) + #define JZ4780_I2C_STA_ACT BIT(0) + +-static const char * const jz4780_i2c_abrt_src[] = { +- "ABRT_7B_ADDR_NOACK", +- "ABRT_10ADDR1_NOACK", +- "ABRT_10ADDR2_NOACK", +- "ABRT_XDATA_NOACK", +- "ABRT_GCALL_NOACK", +- "ABRT_GCALL_READ", +- "ABRT_HS_ACKD", +- "SBYTE_ACKDET", +- "ABRT_HS_NORSTRT", +- "SBYTE_NORSTRT", +- "ABRT_10B_RD_NORSTRT", +- "ABRT_MASTER_DIS", +- "ARB_LOST", +- "SLVFLUSH_TXFIFO", +- "SLV_ARBLOST", +- "SLVRD_INTX", +-}; +- + #define JZ4780_I2C_INTST_IGC BIT(11) + #define JZ4780_I2C_INTST_ISTT BIT(10) + #define JZ4780_I2C_INTST_ISTP BIT(9) +@@ -538,21 +519,8 @@ done: + + static void jz4780_i2c_txabrt(struct jz4780_i2c *i2c, int src) + { +- int i; +- +- dev_err(&i2c->adap.dev, "txabrt: 0x%08x\n", src); +- dev_err(&i2c->adap.dev, "device addr=%x\n", +- jz4780_i2c_readw(i2c, JZ4780_I2C_TAR)); +- dev_err(&i2c->adap.dev, "send cmd count:%d %d\n", +- i2c->cmd, i2c->cmd_buf[i2c->cmd]); +- dev_err(&i2c->adap.dev, "receive data count:%d %d\n", +- i2c->cmd, i2c->data_buf[i2c->cmd]); +- +- for (i = 0; i < 16; i++) { +- if (src & BIT(i)) +- dev_dbg(&i2c->adap.dev, "I2C TXABRT[%d]=%s\n", +- i, jz4780_i2c_abrt_src[i]); +- } ++ dev_dbg(&i2c->adap.dev, "txabrt: 0x%08x, cmd: %d, send: %d, recv: %d\n", ++ src, i2c->cmd, i2c->cmd_buf[i2c->cmd], i2c->data_buf[i2c->cmd]); + } + + static inline int jz4780_i2c_xfer_read(struct jz4780_i2c *i2c, diff --git a/patches.suse/ibmveth-Update-ethtool-settings-to-reflect-virtual-p.patch b/patches.suse/ibmveth-Update-ethtool-settings-to-reflect-virtual-p.patch deleted file mode 100644 index 652b1ef..0000000 --- a/patches.suse/ibmveth-Update-ethtool-settings-to-reflect-virtual-p.patch +++ /dev/null @@ -1,154 +0,0 @@ -From 3417314b96d0a872057942f928e08a35460f0153 Mon Sep 17 00:00:00 2001 -From: Thomas Falcon -Date: Fri, 3 May 2019 09:28:33 -0500 -Subject: [PATCH net-next] ibmveth: Update ethtool settings to reflect virtual - properties - -References: bsc#1136157, LTC#177197 -Patch-mainline: submitted https://patchwork.ozlabs.org/patch/1142940/ - -As a paravirtual ethernet adapter, the current hardcoded ethtool -link settings no longer reflect the actual capable speed of the -interface. There is no way for the virtual adapter to determine -the true speed, duplex, and other backing hardware specifications -at this time. - -To avoid confusion, initially define them as unknown or other. -Finally allow the user to alter speed and duplex settings to match -the capabilities of underlying hardware and to allow some features -that rely on certain ethtool reporting, such as LACP. This is based -on the implementation in virtio_net. - -Signed-off-by: Thomas Falcon -Acked-by: Michal Suchanek ---- - drivers/net/ethernet/ibm/ibmveth.c | 83 ++++++++++++++++++++++++++++---------- - drivers/net/ethernet/ibm/ibmveth.h | 3 ++ - 2 files changed, 64 insertions(+), 22 deletions(-) - ---- a/drivers/net/ethernet/ibm/ibmveth.c -+++ b/drivers/net/ethernet/ibm/ibmveth.c -@@ -725,31 +725,68 @@ static int ibmveth_close(struct net_devi - return 0; - } - --static int netdev_get_link_ksettings(struct net_device *dev, -- struct ethtool_link_ksettings *cmd) -+static bool -+ibmveth_validate_ethtool_cmd(const struct ethtool_link_ksettings *cmd) - { -- u32 supported, advertising; -+ struct ethtool_link_ksettings diff1 = *cmd; -+ struct ethtool_link_ksettings diff2 = {}; - -- supported = (SUPPORTED_1000baseT_Full | SUPPORTED_Autoneg | -- SUPPORTED_FIBRE); -- advertising = (ADVERTISED_1000baseT_Full | ADVERTISED_Autoneg | -- ADVERTISED_FIBRE); -- cmd->base.speed = SPEED_1000; -- cmd->base.duplex = DUPLEX_FULL; -- cmd->base.port = PORT_FIBRE; -- cmd->base.phy_address = 0; -- cmd->base.autoneg = AUTONEG_ENABLE; -- -- ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.supported, -- supported); -- ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.advertising, -- advertising); -+ diff2.base.port = PORT_OTHER; -+ diff1.base.speed = 0; -+ diff1.base.duplex = 0; -+ diff1.base.cmd = 0; -+ diff1.base.link_mode_masks_nwords = 0; -+ ethtool_link_ksettings_zero_link_mode(&diff1, advertising); -+ -+ return !memcmp(&diff1.base, &diff2.base, sizeof(diff1.base)) && -+ bitmap_empty(diff1.link_modes.supported, -+ __ETHTOOL_LINK_MODE_MASK_NBITS) && -+ bitmap_empty(diff1.link_modes.advertising, -+ __ETHTOOL_LINK_MODE_MASK_NBITS) && -+ bitmap_empty(diff1.link_modes.lp_advertising, -+ __ETHTOOL_LINK_MODE_MASK_NBITS); -+} -+ -+static int ibmveth_set_link_ksettings(struct net_device *dev, -+ const struct ethtool_link_ksettings *cmd) -+{ -+ struct ibmveth_adapter *adapter = netdev_priv(dev); -+ u32 speed; -+ u8 duplex; -+ -+ speed = cmd->base.speed; -+ duplex = cmd->base.duplex; -+ /* don't allow custom speed and duplex */ -+ if (!ethtool_validate_speed(speed) || -+ !ethtool_validate_duplex(duplex) || -+ !ibmveth_validate_ethtool_cmd(cmd)) -+ return -EINVAL; -+ adapter->speed = speed; -+ adapter->duplex = duplex; -+ -+ return 0; -+} -+ -+static int ibmveth_get_link_ksettings(struct net_device *dev, -+ struct ethtool_link_ksettings *cmd) -+{ -+ struct ibmveth_adapter *adapter = netdev_priv(dev); -+ -+ cmd->base.speed = adapter->speed; -+ cmd->base.duplex = adapter->duplex; -+ cmd->base.port = PORT_OTHER; - - return 0; - } - --static void netdev_get_drvinfo(struct net_device *dev, -- struct ethtool_drvinfo *info) -+static void ibmveth_init_link_settings(struct ibmveth_adapter *adapter) -+{ -+ adapter->duplex = DUPLEX_UNKNOWN; -+ adapter->speed = SPEED_UNKNOWN; -+} -+ -+static void ibmveth_get_drvinfo(struct net_device *dev, -+ struct ethtool_drvinfo *info) - { - strlcpy(info->driver, ibmveth_driver_name, sizeof(info->driver)); - strlcpy(info->version, ibmveth_driver_version, sizeof(info->version)); -@@ -978,12 +1015,13 @@ static void ibmveth_get_ethtool_stats(st - } - - static const struct ethtool_ops netdev_ethtool_ops = { -- .get_drvinfo = netdev_get_drvinfo, -+ .get_drvinfo = ibmveth_get_drvinfo, - .get_link = ethtool_op_get_link, - .get_strings = ibmveth_get_strings, - .get_sset_count = ibmveth_get_sset_count, - .get_ethtool_stats = ibmveth_get_ethtool_stats, -- .get_link_ksettings = netdev_get_link_ksettings, -+ .get_link_ksettings = ibmveth_get_link_ksettings, -+ .set_link_ksettings = ibmveth_set_link_ksettings - }; - - static int ibmveth_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) -@@ -1661,6 +1699,7 @@ static int ibmveth_probe(struct vio_dev - adapter->netdev = netdev; - adapter->mcastFilterSize = be32_to_cpu(*mcastFilterSize_p); - adapter->pool_config = 0; -+ ibmveth_init_link_settings(adapter); - - netif_napi_add(netdev, &adapter->napi, ibmveth_poll, 16); - ---- a/drivers/net/ethernet/ibm/ibmveth.h -+++ b/drivers/net/ethernet/ibm/ibmveth.h -@@ -174,6 +174,9 @@ struct ibmveth_adapter { - u64 tx_send_failed; - u64 tx_large_packets; - u64 rx_large_packets; -+ /* Ethtool settings */ -+ u8 duplex; -+ u32 speed; - }; - - /* diff --git a/patches.suse/ibmvfc-Fix-NULL-return-compiler-warning.patch b/patches.suse/ibmvfc-Fix-NULL-return-compiler-warning.patch new file mode 100644 index 0000000..19acdf6 --- /dev/null +++ b/patches.suse/ibmvfc-Fix-NULL-return-compiler-warning.patch @@ -0,0 +1,36 @@ +From b893eb0141cb4b896b275d00bea2deb64f6f1eac Mon Sep 17 00:00:00 2001 +From: Brian King +Date: Mon, 2 Mar 2020 08:39:21 -0600 +Subject: [PATCH] scsi: ibmvfc: Fix NULL return compiler warning + +References: bsc#1161951 ltc#183551 +Patch-mainline: v5.7-rc1 +Git-commit: b893eb0141cb4b896b275d00bea2deb64f6f1eac + +Fix up a compiler warning introduced via 54b04c99d02e + +Link: https://lore.kernel.org/r/1583159961-15903-1-git-send-email-brking@linux.vnet.ibm.com +Fixes: 54b04c99d02e ("scsi: ibmvfc: Avoid loss of all paths during SVC node reboot") +Signed-off-by: Brian King +Signed-off-by: Martin K. Petersen +Acked-by: Michal Suchanek +--- + drivers/scsi/ibmvscsi/ibmvfc.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/scsi/ibmvscsi/ibmvfc.c b/drivers/scsi/ibmvscsi/ibmvfc.c +index 84dd8c5145c8..7da9e060b270 100644 +--- a/drivers/scsi/ibmvscsi/ibmvfc.c ++++ b/drivers/scsi/ibmvscsi/ibmvfc.c +@@ -3641,7 +3641,7 @@ static void ibmvfc_tgt_implicit_logout_and_del(struct ibmvfc_target *tgt) + struct ibmvfc_event *evt; + + if (vhost->discovery_threads >= disc_threads) +- return NULL; ++ return; + + vhost->discovery_threads++; + evt = __ibmvfc_tgt_get_implicit_logout_evt(tgt, +-- +2.23.0 + diff --git a/patches.suse/ibmvnic-Do-not-process-device-remove-during-device-r.patch b/patches.suse/ibmvnic-Do-not-process-device-remove-during-device-r.patch new file mode 100644 index 0000000..5ccf7ca --- /dev/null +++ b/patches.suse/ibmvnic-Do-not-process-device-remove-during-device-r.patch @@ -0,0 +1,116 @@ +From 7d7195a026bac47ac9943f11f84b7546276209dd Mon Sep 17 00:00:00 2001 +From: Juliet Kim +Date: Tue, 10 Mar 2020 09:23:58 -0500 +Subject: [PATCH] ibmvnic: Do not process device remove during device reset + +References: bsc#1065729 +Patch-mainline: v5.6 or v5.6-rc6 (next release) +Git-commit: 7d7195a026bac47ac9943f11f84b7546276209dd + +The ibmvnic driver does not check the device state when the device +is removed. If the device is removed while a device reset is being +processed, the remove may free structures needed by the reset, +causing an oops. + +Fix this by checking the device state before processing device remove. + +Signed-off-by: Juliet Kim +Signed-off-by: David S. Miller +Acked-by: Michal Suchanek +--- + drivers/net/ethernet/ibm/ibmvnic.c | 24 ++++++++++++++++++++++-- + drivers/net/ethernet/ibm/ibmvnic.h | 6 +++++- + 2 files changed, 27 insertions(+), 3 deletions(-) + +diff --git a/drivers/net/ethernet/ibm/ibmvnic.c b/drivers/net/ethernet/ibm/ibmvnic.c +index c75239d8820f..4bd33245bad6 100644 +--- a/drivers/net/ethernet/ibm/ibmvnic.c ++++ b/drivers/net/ethernet/ibm/ibmvnic.c +@@ -2142,6 +2142,8 @@ static void __ibmvnic_reset(struct work_struct *work) + { + struct ibmvnic_rwi *rwi; + struct ibmvnic_adapter *adapter; ++ bool saved_state = false; ++ unsigned long flags; + u32 reset_state; + int rc = 0; + +@@ -2153,17 +2155,25 @@ static void __ibmvnic_reset(struct work_struct *work) + return; + } + +- reset_state = adapter->state; +- + rwi = get_next_rwi(adapter); + while (rwi) { ++ spin_lock_irqsave(&adapter->state_lock, flags); ++ + if (adapter->state == VNIC_REMOVING || + adapter->state == VNIC_REMOVED) { ++ spin_unlock_irqrestore(&adapter->state_lock, flags); + kfree(rwi); + rc = EBUSY; + break; + } + ++ if (!saved_state) { ++ reset_state = adapter->state; ++ adapter->state = VNIC_RESETTING; ++ saved_state = true; ++ } ++ spin_unlock_irqrestore(&adapter->state_lock, flags); ++ + if (rwi->reset_reason == VNIC_RESET_CHANGE_PARAM) { + /* CHANGE_PARAM requestor holds rtnl_lock */ + rc = do_change_param_reset(adapter, rwi, reset_state); +@@ -5091,6 +5101,7 @@ static int ibmvnic_probe(struct vio_dev *dev, const struct vio_device_id *id) + __ibmvnic_delayed_reset); + INIT_LIST_HEAD(&adapter->rwi_list); + spin_lock_init(&adapter->rwi_lock); ++ spin_lock_init(&adapter->state_lock); + mutex_init(&adapter->fw_lock); + init_completion(&adapter->init_done); + init_completion(&adapter->fw_done); +@@ -5163,8 +5174,17 @@ static int ibmvnic_remove(struct vio_dev *dev) + { + struct net_device *netdev = dev_get_drvdata(&dev->dev); + struct ibmvnic_adapter *adapter = netdev_priv(netdev); ++ unsigned long flags; ++ ++ spin_lock_irqsave(&adapter->state_lock, flags); ++ if (adapter->state == VNIC_RESETTING) { ++ spin_unlock_irqrestore(&adapter->state_lock, flags); ++ return -EBUSY; ++ } + + adapter->state = VNIC_REMOVING; ++ spin_unlock_irqrestore(&adapter->state_lock, flags); ++ + rtnl_lock(); + unregister_netdevice(netdev); + +diff --git a/drivers/net/ethernet/ibm/ibmvnic.h b/drivers/net/ethernet/ibm/ibmvnic.h +index 60eccaf91b12..f8416e1d4cf0 100644 +--- a/drivers/net/ethernet/ibm/ibmvnic.h ++++ b/drivers/net/ethernet/ibm/ibmvnic.h +@@ -941,7 +941,8 @@ enum vnic_state {VNIC_PROBING = 1, + VNIC_CLOSING, + VNIC_CLOSED, + VNIC_REMOVING, +- VNIC_REMOVED}; ++ VNIC_REMOVED, ++ VNIC_RESETTING}; + + enum ibmvnic_reset_reason {VNIC_RESET_FAILOVER = 1, + VNIC_RESET_MOBILITY, +@@ -1090,4 +1091,7 @@ struct ibmvnic_adapter { + + struct ibmvnic_tunables desired; + struct ibmvnic_tunables fallback; ++ ++ /* Used for serializatin of state field */ ++ spinlock_t state_lock; + }; +-- +2.23.0 + diff --git a/patches.suse/ibmvnic-Warn-unknown-speed-message-only-when-carrier.patch b/patches.suse/ibmvnic-Warn-unknown-speed-message-only-when-carrier.patch new file mode 100644 index 0000000..57e8d93 --- /dev/null +++ b/patches.suse/ibmvnic-Warn-unknown-speed-message-only-when-carrier.patch @@ -0,0 +1,59 @@ +From dd0f9d896d167ab37732dd83986adc3a017a13b4 Mon Sep 17 00:00:00 2001 +From: Murilo Fossa Vicentini +Date: Mon, 16 Sep 2019 11:50:37 -0300 +Subject: [PATCH] ibmvnic: Warn unknown speed message only when carrier is + present + +References: bsc#1065729 +Patch-mainline: v5.4-rc1 +Git-commit: dd0f9d896d167ab37732dd83986adc3a017a13b4 + +With commit 0655f9943df2 ("net/ibmvnic: Update carrier state after link +state change") we are now able to detect when the carrier is properly +present in the device, so only report an unexpected unknown speed when it +is properly detected. Unknown speed is expected to be seen by the device +in case the backing device has no link detected. + +Reported-by: Abdul Haleem +Tested-by: Abdul Haleem +Signed-off-by: Murilo Fossa Vicentini +Reviewed-by: Thomas Falcon +Acked-by: Michal Suchanek +--- + drivers/net/ethernet/ibm/ibmvnic.c | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +diff --git a/drivers/net/ethernet/ibm/ibmvnic.c b/drivers/net/ethernet/ibm/ibmvnic.c +index 2e5172f61564..3816fff75bb5 100644 +--- a/drivers/net/ethernet/ibm/ibmvnic.c ++++ b/drivers/net/ethernet/ibm/ibmvnic.c +@@ -4312,13 +4312,14 @@ static int handle_query_phys_parms_rsp(union ibmvnic_crq *crq, + { + struct net_device *netdev = adapter->netdev; + int rc; ++ __be32 rspeed = cpu_to_be32(crq->query_phys_parms_rsp.speed); + + rc = crq->query_phys_parms_rsp.rc.code; + if (rc) { + netdev_err(netdev, "Error %d in QUERY_PHYS_PARMS\n", rc); + return rc; + } +- switch (cpu_to_be32(crq->query_phys_parms_rsp.speed)) { ++ switch (rspeed) { + case IBMVNIC_10MBPS: + adapter->speed = SPEED_10; + break; +@@ -4344,8 +4345,8 @@ static int handle_query_phys_parms_rsp(union ibmvnic_crq *crq, + adapter->speed = SPEED_100000; + break; + default: +- netdev_warn(netdev, "Unknown speed 0x%08x\n", +- cpu_to_be32(crq->query_phys_parms_rsp.speed)); ++ if (netif_carrier_ok(netdev)) ++ netdev_warn(netdev, "Unknown speed 0x%08x\n", rspeed); + adapter->speed = SPEED_UNKNOWN; + } + if (crq->query_phys_parms_rsp.flags1 & IBMVNIC_FULL_DUPLEX) +-- +2.23.0 + diff --git a/patches.suse/ibmvscsi-Protect-ibmvscsi_head-from-concurrent-modif.patch b/patches.suse/ibmvscsi-Protect-ibmvscsi_head-from-concurrent-modif.patch index cbf0711..800256f 100644 --- a/patches.suse/ibmvscsi-Protect-ibmvscsi_head-from-concurrent-modif.patch +++ b/patches.suse/ibmvscsi-Protect-ibmvscsi_head-from-concurrent-modif.patch @@ -25,17 +25,19 @@ Acked-by: Michal Suchanek drivers/scsi/ibmvscsi/ibmvscsi.c | 5 +++++ 1 file changed, 5 insertions(+) +diff --git a/drivers/scsi/ibmvscsi/ibmvscsi.c b/drivers/scsi/ibmvscsi/ibmvscsi.c +index 1135e74646e2..2b22969f3f63 100644 --- a/drivers/scsi/ibmvscsi/ibmvscsi.c +++ b/drivers/scsi/ibmvscsi/ibmvscsi.c @@ -96,6 +96,7 @@ static int client_reserve = 1; - static char partition_name[97] = "UNKNOWN"; + static char partition_name[96] = "UNKNOWN"; static unsigned int partition_number = -1; static LIST_HEAD(ibmvscsi_head); +static DEFINE_SPINLOCK(ibmvscsi_driver_lock); static struct scsi_transport_template *ibmvscsi_transport_template; -@@ -2274,7 +2275,9 @@ static int ibmvscsi_probe(struct vio_dev +@@ -2270,7 +2271,9 @@ static int ibmvscsi_probe(struct vio_dev *vdev, const struct vio_device_id *id) } dev_set_drvdata(&vdev->dev, hostdata); @@ -45,7 +47,7 @@ Acked-by: Michal Suchanek return 0; add_srp_port_failed: -@@ -2296,7 +2299,9 @@ static int ibmvscsi_probe(struct vio_dev +@@ -2292,7 +2295,9 @@ static int ibmvscsi_probe(struct vio_dev *vdev, const struct vio_device_id *id) static int ibmvscsi_remove(struct vio_dev *vdev) { struct ibmvscsi_host_data *hostdata = dev_get_drvdata(&vdev->dev); @@ -55,3 +57,6 @@ Acked-by: Michal Suchanek unmap_persist_bufs(hostdata); release_event_pool(&hostdata->pool, hostdata); ibmvscsi_release_crq_queue(&hostdata->queue, hostdata, +-- +2.23.0 + diff --git a/patches.suse/iio-gyro-adis16136-check-ret-val-for-non-zero-vs-les.patch b/patches.suse/iio-gyro-adis16136-check-ret-val-for-non-zero-vs-les.patch new file mode 100644 index 0000000..eb83c0c --- /dev/null +++ b/patches.suse/iio-gyro-adis16136-check-ret-val-for-non-zero-vs-les.patch @@ -0,0 +1,124 @@ +From 26ba6db672698641223eece20beeb59a60032eb9 Mon Sep 17 00:00:00 2001 +From: Alexandru Ardelean +Date: Fri, 1 Nov 2019 11:34:56 +0200 +Subject: [PATCH] iio: gyro: adis16136: check ret val for non-zero vs less-than-zero +Git-commit: 26ba6db672698641223eece20beeb59a60032eb9 +Patch-mainline: v5.5-rc1 +References: bsc#1051510 + +The ADIS library functions return zero on success, and negative values for +error. Positive values aren't returned, but we only care about the success +value (which is zero). + +This change is mostly needed so that the compiler won't make any inferences +about some about values being potentially un-initialized. This only +triggers after making some functions inline, because the compiler can +better follow return paths. + +Signed-off-by: Alexandru Ardelean +Signed-off-by: Jonathan Cameron +Acked-by: Takashi Iwai + +--- + drivers/iio/gyro/adis16136.c | 24 ++++++++++++------------ + 1 file changed, 12 insertions(+), 12 deletions(-) + +diff --git a/drivers/iio/gyro/adis16136.c b/drivers/iio/gyro/adis16136.c +index 5bec7ad53d8b..d637d52d051a 100644 +--- a/drivers/iio/gyro/adis16136.c ++++ b/drivers/iio/gyro/adis16136.c +@@ -80,19 +80,19 @@ static ssize_t adis16136_show_serial(struct file *file, + + ret = adis_read_reg_16(&adis16136->adis, ADIS16136_REG_SERIAL_NUM, + &serial); +- if (ret < 0) ++ if (ret) + return ret; + + ret = adis_read_reg_16(&adis16136->adis, ADIS16136_REG_LOT1, &lot1); +- if (ret < 0) ++ if (ret) + return ret; + + ret = adis_read_reg_16(&adis16136->adis, ADIS16136_REG_LOT2, &lot2); +- if (ret < 0) ++ if (ret) + return ret; + + ret = adis_read_reg_16(&adis16136->adis, ADIS16136_REG_LOT3, &lot3); +- if (ret < 0) ++ if (ret) + return ret; + + len = snprintf(buf, sizeof(buf), "%.4x%.4x%.4x-%.4x\n", lot1, lot2, +@@ -116,7 +116,7 @@ static int adis16136_show_product_id(void *arg, u64 *val) + + ret = adis_read_reg_16(&adis16136->adis, ADIS16136_REG_PROD_ID, + &prod_id); +- if (ret < 0) ++ if (ret) + return ret; + + *val = prod_id; +@@ -134,7 +134,7 @@ static int adis16136_show_flash_count(void *arg, u64 *val) + + ret = adis_read_reg_16(&adis16136->adis, ADIS16136_REG_FLASH_CNT, + &flash_count); +- if (ret < 0) ++ if (ret) + return ret; + + *val = flash_count; +@@ -191,7 +191,7 @@ static int adis16136_get_freq(struct adis16136 *adis16136, unsigned int *freq) + int ret; + + ret = adis_read_reg_16(&adis16136->adis, ADIS16136_REG_SMPL_PRD, &t); +- if (ret < 0) ++ if (ret) + return ret; + + *freq = 32768 / (t + 1); +@@ -228,7 +228,7 @@ static ssize_t adis16136_read_frequency(struct device *dev, + int ret; + + ret = adis16136_get_freq(adis16136, &freq); +- if (ret < 0) ++ if (ret) + return ret; + + return sprintf(buf, "%d\n", freq); +@@ -256,7 +256,7 @@ static int adis16136_set_filter(struct iio_dev *indio_dev, int val) + int i, ret; + + ret = adis16136_get_freq(adis16136, &freq); +- if (ret < 0) ++ if (ret) + return ret; + + for (i = ARRAY_SIZE(adis16136_3db_divisors) - 1; i >= 1; i--) { +@@ -277,11 +277,11 @@ static int adis16136_get_filter(struct iio_dev *indio_dev, int *val) + mutex_lock(&indio_dev->mlock); + + ret = adis_read_reg_16(&adis16136->adis, ADIS16136_REG_AVG_CNT, &val16); +- if (ret < 0) ++ if (ret) + goto err_unlock; + + ret = adis16136_get_freq(adis16136, &freq); +- if (ret < 0) ++ if (ret) + goto err_unlock; + + *val = freq / adis16136_3db_divisors[val16 & 0x07]; +@@ -318,7 +318,7 @@ static int adis16136_read_raw(struct iio_dev *indio_dev, + case IIO_CHAN_INFO_CALIBBIAS: + ret = adis_read_reg_32(&adis16136->adis, + ADIS16136_REG_GYRO_OFF2, &val32); +- if (ret < 0) ++ if (ret) + return ret; + + *val = sign_extend32(val32, 31); +-- +2.16.4 + diff --git a/patches.suse/iio-imu-adis-check-ret-val-for-non-zero-vs-less-than.patch b/patches.suse/iio-imu-adis-check-ret-val-for-non-zero-vs-less-than.patch new file mode 100644 index 0000000..1fe57da --- /dev/null +++ b/patches.suse/iio-imu-adis-check-ret-val-for-non-zero-vs-less-than.patch @@ -0,0 +1,41 @@ +From 6a39ab3b195c125d3fe49d0b0b613c2e1dbbc5a2 Mon Sep 17 00:00:00 2001 +From: Alexandru Ardelean +Date: Fri, 1 Nov 2019 11:35:00 +0200 +Subject: [PATCH] iio: imu: adis: check ret val for non-zero vs less-than-zero +Git-commit: 6a39ab3b195c125d3fe49d0b0b613c2e1dbbc5a2 +Patch-mainline: v5.5-rc1 +References: bsc#1051510 + +The ADIS library functions return zero on success, and negative values for +error. Positive values aren't returned, but we only care about the success +value (which is zero). + +This change is mostly needed so that the compiler won't make any inferences +about some about values being potentially un-initialized. This only +triggers after making some functions inline, because the compiler can +better follow return paths. + +Signed-off-by: Alexandru Ardelean +Signed-off-by: Jonathan Cameron +Acked-by: Takashi Iwai + +--- + drivers/iio/imu/adis.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/iio/imu/adis.c b/drivers/iio/imu/adis.c +index 1631c255deab..dc2f9e061d98 100644 +--- a/drivers/iio/imu/adis.c ++++ b/drivers/iio/imu/adis.c +@@ -286,7 +286,7 @@ int adis_check_status(struct adis *adis) + int i; + + ret = adis_read_reg_16(adis, adis->data->diag_stat_reg, &status); +- if (ret < 0) ++ if (ret) + return ret; + + status &= adis->data->status_error_mask; +-- +2.16.4 + diff --git a/patches.suse/iio-imu-adis16400-check-ret-val-for-non-zero-vs-less.patch b/patches.suse/iio-imu-adis16400-check-ret-val-for-non-zero-vs-less.patch new file mode 100644 index 0000000..722357e --- /dev/null +++ b/patches.suse/iio-imu-adis16400-check-ret-val-for-non-zero-vs-less.patch @@ -0,0 +1,116 @@ +From fe4b7f917e8fa20c1a9dd2b3f417acd3b063c880 Mon Sep 17 00:00:00 2001 +From: Alexandru Ardelean +Date: Fri, 1 Nov 2019 11:34:57 +0200 +Subject: [PATCH] iio: imu: adis16400: check ret val for non-zero vs less-than-zero +Git-commit: fe4b7f917e8fa20c1a9dd2b3f417acd3b063c880 +Patch-mainline: v5.5-rc1 +References: bsc#1051510 + +The ADIS library functions return zero on success, and negative values for +error. Positive values aren't returned, but we only care about the success +value (which is zero). + +This change is mostly needed so that the compiler won't make any inferences +about some about values being potentially un-initialized. This only +triggers after making some functions inline, because the compiler can +better follow return paths. + +Signed-off-by: Alexandru Ardelean +Signed-off-by: Jonathan Cameron +Acked-by: Takashi Iwai + +--- + drivers/iio/imu/adis16400_core.c | 22 +++++++++++----------- + 1 file changed, 11 insertions(+), 11 deletions(-) + +--- a/drivers/iio/imu/adis16400_core.c ++++ b/drivers/iio/imu/adis16400_core.c +@@ -46,16 +46,16 @@ static ssize_t adis16400_show_serial_num + int ret; + + ret = adis_read_reg_16(&st->adis, ADIS16334_LOT_ID1, &lot1); +- if (ret < 0) ++ if (ret) + return ret; + + ret = adis_read_reg_16(&st->adis, ADIS16334_LOT_ID2, &lot2); +- if (ret < 0) ++ if (ret) + return ret; + + ret = adis_read_reg_16(&st->adis, ADIS16334_SERIAL_NUMBER, + &serial_number); +- if (ret < 0) ++ if (ret) + return ret; + + len = snprintf(buf, sizeof(buf), "%.4x-%.4x-%.4x\n", lot1, lot2, +@@ -78,7 +78,7 @@ static int adis16400_show_product_id(voi + int ret; + + ret = adis_read_reg_16(&st->adis, ADIS16400_PRODUCT_ID, &prod_id); +- if (ret < 0) ++ if (ret) + return ret; + + *val = prod_id; +@@ -95,7 +95,7 @@ static int adis16400_show_flash_count(vo + int ret; + + ret = adis_read_reg_16(&st->adis, ADIS16400_FLASH_CNT, &flash_count); +- if (ret < 0) ++ if (ret) + return ret; + + *val = flash_count; +@@ -151,7 +151,7 @@ static int adis16334_get_freq(struct adi + uint16_t t; + + ret = adis_read_reg_16(&st->adis, ADIS16400_SMPL_PRD, &t); +- if (ret < 0) ++ if (ret) + return ret; + + t >>= ADIS16334_RATE_DIV_SHIFT; +@@ -183,7 +183,7 @@ static int adis16400_get_freq(struct adi + uint16_t t; + + ret = adis_read_reg_16(&st->adis, ADIS16400_SMPL_PRD, &t); +- if (ret < 0) ++ if (ret) + return ret; + + sps = (t & ADIS16400_SMPL_PRD_TIME_BASE) ? 52851 : 1638404; +@@ -240,7 +240,7 @@ static int adis16400_set_filter(struct i + } + + ret = adis_read_reg_16(&st->adis, ADIS16400_SENS_AVG, &val16); +- if (ret < 0) ++ if (ret) + return ret; + + ret = adis_write_reg_16(&st->adis, ADIS16400_SENS_AVG, +@@ -439,7 +439,7 @@ static int adis16400_read_raw(struct iio + ret = adis_read_reg_16(&st->adis, + ADIS16400_SENS_AVG, + &val16); +- if (ret < 0) { ++ if (ret) { + mutex_unlock(&indio_dev->mlock); + return ret; + } +@@ -450,12 +450,12 @@ static int adis16400_read_raw(struct iio + *val2 = (ret % 1000) * 1000; + } + mutex_unlock(&indio_dev->mlock); +- if (ret < 0) ++ if (ret) + return ret; + return IIO_VAL_INT_PLUS_MICRO; + case IIO_CHAN_INFO_SAMP_FREQ: + ret = st->variant->get_freq(st); +- if (ret < 0) ++ if (ret) + return ret; + *val = ret / 1000; + *val2 = (ret % 1000) * 1000; diff --git a/patches.suse/iio-imu-adis16480-check-ret-val-for-non-zero-vs-less.patch b/patches.suse/iio-imu-adis16480-check-ret-val-for-non-zero-vs-less.patch new file mode 100644 index 0000000..af699ee --- /dev/null +++ b/patches.suse/iio-imu-adis16480-check-ret-val-for-non-zero-vs-less.patch @@ -0,0 +1,122 @@ +From 92c7529fc1bf3e607ed90c941e55bc244e04a256 Mon Sep 17 00:00:00 2001 +From: Alexandru Ardelean +Date: Fri, 1 Nov 2019 11:34:59 +0200 +Subject: [PATCH] iio: imu: adis16480: check ret val for non-zero vs less-than-zero +Git-commit: 92c7529fc1bf3e607ed90c941e55bc244e04a256 +Patch-mainline: v5.5-rc1 +References: bsc#1051510 + +The ADIS library functions return zero on success, and negative values for +error. Positive values aren't returned, but we only care about the success +value (which is zero). + +This change is mostly needed so that the compiler won't make any inferences +about some about values being potentially un-initialized. This only +triggers after making some functions inline, because the compiler can +better follow return paths. + +Signed-off-by: Alexandru Ardelean +Signed-off-by: Jonathan Cameron +Acked-by: Takashi Iwai + +--- + drivers/iio/imu/adis16480.c | 22 +++++++++++----------- + 1 file changed, 11 insertions(+), 11 deletions(-) + +--- a/drivers/iio/imu/adis16480.c ++++ b/drivers/iio/imu/adis16480.c +@@ -134,7 +134,7 @@ static ssize_t adis16480_show_firmware_r + int ret; + + ret = adis_read_reg_16(&adis16480->adis, ADIS16480_REG_FIRM_REV, &rev); +- if (ret < 0) ++ if (ret) + return ret; + + len = scnprintf(buf, sizeof(buf), "%x.%x\n", rev >> 8, rev & 0xff); +@@ -159,11 +159,11 @@ static ssize_t adis16480_show_firmware_d + int ret; + + ret = adis_read_reg_16(&adis16480->adis, ADIS16480_REG_FIRM_Y, &year); +- if (ret < 0) ++ if (ret) + return ret; + + ret = adis_read_reg_16(&adis16480->adis, ADIS16480_REG_FIRM_DM, &md); +- if (ret < 0) ++ if (ret) + return ret; + + len = snprintf(buf, sizeof(buf), "%.2x-%.2x-%.4x\n", +@@ -187,7 +187,7 @@ static int adis16480_show_serial_number( + + ret = adis_read_reg_16(&adis16480->adis, ADIS16480_REG_SERIAL_NUM, + &serial); +- if (ret < 0) ++ if (ret) + return ret; + + *val = serial; +@@ -205,7 +205,7 @@ static int adis16480_show_product_id(voi + + ret = adis_read_reg_16(&adis16480->adis, ADIS16480_REG_PROD_ID, + &prod_id); +- if (ret < 0) ++ if (ret) + return ret; + + *val = prod_id; +@@ -223,7 +223,7 @@ static int adis16480_show_flash_count(vo + + ret = adis_read_reg_32(&adis16480->adis, ADIS16480_REG_FLASH_CNT, + &flash_count); +- if (ret < 0) ++ if (ret) + return ret; + + *val = flash_count; +@@ -291,7 +291,7 @@ static int adis16480_get_freq(struct iio + unsigned freq; + + ret = adis_read_reg_16(&st->adis, ADIS16480_REG_DEC_RATE, &t); +- if (ret < 0) ++ if (ret) + return ret; + + freq = 2460000 / (t + 1); +@@ -385,7 +385,7 @@ static int adis16480_get_calibbias(struc + ret = -EINVAL; + } + +- if (ret < 0) ++ if (ret) + return ret; + + return IIO_VAL_INT; +@@ -412,7 +412,7 @@ static int adis16480_get_calibscale(stru + int ret; + + ret = adis_read_reg_16(&st->adis, reg, &val16); +- if (ret < 0) ++ if (ret) + return ret; + + *scale = sign_extend32(val16, 15); +@@ -451,7 +451,7 @@ static int adis16480_get_filter_freq(str + enable_mask = BIT(offset + 2); + + ret = adis_read_reg_16(&st->adis, reg, &val); +- if (ret < 0) ++ if (ret) + return ret; + + if (!(val & enable_mask)) +@@ -477,7 +477,7 @@ static int adis16480_set_filter_freq(str + enable_mask = BIT(offset + 2); + + ret = adis_read_reg_16(&st->adis, reg, &val); +- if (ret < 0) ++ if (ret) + return ret; + + if (freq == 0) { diff --git a/patches.suse/iio-magnetometer-ak8974-Fix-negative-raw-values-in-s.patch b/patches.suse/iio-magnetometer-ak8974-Fix-negative-raw-values-in-s.patch new file mode 100644 index 0000000..f9c3189 --- /dev/null +++ b/patches.suse/iio-magnetometer-ak8974-Fix-negative-raw-values-in-s.patch @@ -0,0 +1,45 @@ +From b500c086e4110829a308c23e83a7cdc65b26228a Mon Sep 17 00:00:00 2001 +From: Stephan Gerhold +Date: Fri, 14 Feb 2020 12:03:24 +0100 +Subject: [PATCH] iio: magnetometer: ak8974: Fix negative raw values in sysfs +Mime-version: 1.0 +Content-type: text/plain; charset=UTF-8 +Content-transfer-encoding: 8bit +Git-commit: b500c086e4110829a308c23e83a7cdc65b26228a +Patch-mainline: v5.6-rc7 +References: bsc#1051510 + +At the moment, reading from in_magn_*_raw in sysfs tends to return +large values around 65000, even though the output of ak8974 is actually +limited to ±32768. This happens because the value is never converted +to the signed 16-bit integer variant. + +Add an explicit cast to s16 to fix this. + +Fixes: 7c94a8b2ee8c ("iio: magn: add a driver for AK8974") +Signed-off-by: Stephan Gerhold +Reviewed-by: Linus Waleij +Cc: +Signed-off-by: Jonathan Cameron +Acked-by: Takashi Iwai + +--- + drivers/iio/magnetometer/ak8974.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/iio/magnetometer/ak8974.c b/drivers/iio/magnetometer/ak8974.c +index fc7e910f8e8b..d32996702110 100644 +--- a/drivers/iio/magnetometer/ak8974.c ++++ b/drivers/iio/magnetometer/ak8974.c +@@ -564,7 +564,7 @@ static int ak8974_read_raw(struct iio_dev *indio_dev, + * We read all axes and discard all but one, for optimized + * reading, use the triggered buffer. + */ +- *val = le16_to_cpu(hw_values[chan->address]); ++ *val = (s16)le16_to_cpu(hw_values[chan->address]); + + ret = IIO_VAL_INT; + } +-- +2.16.4 + diff --git a/patches.suse/iio-potentiostat-lmp9100-fix-iio_triggered_buffer_-p.patch b/patches.suse/iio-potentiostat-lmp9100-fix-iio_triggered_buffer_-p.patch new file mode 100644 index 0000000..2cf85e6 --- /dev/null +++ b/patches.suse/iio-potentiostat-lmp9100-fix-iio_triggered_buffer_-p.patch @@ -0,0 +1,73 @@ +From d7cf5f60474cf591db771bc15e3b7320be5399e0 Mon Sep 17 00:00:00 2001 +From: Alexandru Ardelean +Date: Wed, 4 Mar 2020 11:41:05 +0200 +Subject: [PATCH] iio: potentiostat: lmp9100: fix iio_triggered_buffer_{predisable,postenable} positions +Git-commit: d7cf5f60474cf591db771bc15e3b7320be5399e0 +Patch-mainline: v5.7-rc1 +References: bsc#1051510 + +The iio_triggered_buffer_{predisable,postenable} functions attach/detach +the poll functions. + +For the predisable hook, the disable code should occur before detaching +the poll func, and for the postenable hook, the poll func should be +attached before the enable code. + +The lmp9100 was attaching a poll function but never detaching it via any +IIO disable hook. + +This change adds the detaching of the poll function, and moves/renames +lmp91000_buffer_preenable() function to lmp91000_buffer_postenable(). +The idea is to make it more symmetrical, so that when the +iio_triggered_buffer_{predisable,postenable} functions get removed, it's +easier to see. + +Fixes: 67e17300dc1d7 ("iio: potentiostat: add LMP91000 support") +Signed-off-by: Alexandru Ardelean +Signed-off-by: Jonathan Cameron +Acked-by: Takashi Iwai + +--- + drivers/iio/potentiostat/lmp91000.c | 18 +++++++++++++----- + 1 file changed, 13 insertions(+), 5 deletions(-) + +--- a/drivers/iio/potentiostat/lmp91000.c ++++ b/drivers/iio/potentiostat/lmp91000.c +@@ -287,11 +287,20 @@ static const struct iio_trigger_ops lmp9 + }; + + +-static int lmp91000_buffer_preenable(struct iio_dev *indio_dev) ++static int lmp91000_buffer_postenable(struct iio_dev *indio_dev) + { + struct lmp91000_data *data = iio_priv(indio_dev); ++ int err; + +- return iio_channel_start_all_cb(data->cb_buffer); ++ err = iio_triggered_buffer_postenable(indio_dev); ++ if (err) ++ return err; ++ ++ err = iio_channel_start_all_cb(data->cb_buffer); ++ if (err) ++ iio_triggered_buffer_predisable(indio_dev); ++ ++ return err; + } + + static int lmp91000_buffer_predisable(struct iio_dev *indio_dev) +@@ -300,12 +309,11 @@ static int lmp91000_buffer_predisable(st + + iio_channel_stop_all_cb(data->cb_buffer); + +- return 0; ++ return iio_triggered_buffer_predisable(indio_dev); + } + + static const struct iio_buffer_setup_ops lmp91000_buffer_setup_ops = { +- .preenable = lmp91000_buffer_preenable, +- .postenable = iio_triggered_buffer_postenable, ++ .postenable = lmp91000_buffer_postenable, + .predisable = lmp91000_buffer_predisable, + }; + diff --git a/patches.suse/intel_th-Fix-user-visible-error-codes.patch b/patches.suse/intel_th-Fix-user-visible-error-codes.patch new file mode 100644 index 0000000..7d8f0f5 --- /dev/null +++ b/patches.suse/intel_th-Fix-user-visible-error-codes.patch @@ -0,0 +1,52 @@ +From ce666be89a8a09c5924ff08fc32e119f974bdab6 Mon Sep 17 00:00:00 2001 +From: Alexander Shishkin +Date: Tue, 17 Mar 2020 08:22:14 +0200 +Subject: [PATCH] intel_th: Fix user-visible error codes +Git-commit: ce666be89a8a09c5924ff08fc32e119f974bdab6 +Patch-mainline: v5.6-rc7 +References: bsc#1051510 + +There are a few places in the driver that end up returning ENOTSUPP to +the user, replace those with EINVAL. + +Signed-off-by: Alexander Shishkin +Reviewed-by: Andy Shevchenko +Fixes: ba82664c134ef ("intel_th: Add Memory Storage Unit driver") +Cc: stable@vger.kernel.org # v4.4+ +Link: https://lore.kernel.org/r/20200317062215.15598-6-alexander.shishkin@linux.intel.com +Signed-off-by: Greg Kroah-Hartman +Acked-by: Takashi Iwai + +--- + drivers/hwtracing/intel_th/msu.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +--- a/drivers/hwtracing/intel_th/msu.c ++++ b/drivers/hwtracing/intel_th/msu.c +@@ -499,7 +499,7 @@ static int msc_configure(struct msc *msc + lockdep_assert_held(&msc->buf_mutex); + + if (msc->mode > MSC_MODE_MULTI) +- return -ENOTSUPP; ++ return -EINVAL; + + if (msc->mode == MSC_MODE_MULTI) + msc_buffer_clear_hw_header(msc); +@@ -950,7 +950,7 @@ static int msc_buffer_alloc(struct msc * + } else if (msc->mode == MSC_MODE_MULTI) { + ret = msc_buffer_multi_alloc(msc, nr_pages, nr_wins); + } else { +- ret = -ENOTSUPP; ++ ret = -EINVAL; + } + + if (!ret) { +@@ -1173,7 +1173,7 @@ static ssize_t intel_th_msc_read(struct + if (ret >= 0) + *ppos = iter->offset; + } else { +- ret = -ENOTSUPP; ++ ret = -EINVAL; + } + + put_count: diff --git a/patches.suse/intel_th-pci-Add-Elkhart-Lake-CPU-support.patch b/patches.suse/intel_th-pci-Add-Elkhart-Lake-CPU-support.patch new file mode 100644 index 0000000..718b7c3 --- /dev/null +++ b/patches.suse/intel_th-pci-Add-Elkhart-Lake-CPU-support.patch @@ -0,0 +1,35 @@ +From add492d2e9446a77ede9bb43699ec85ca8fc1aba Mon Sep 17 00:00:00 2001 +From: Alexander Shishkin +Date: Tue, 17 Mar 2020 08:22:15 +0200 +Subject: [PATCH] intel_th: pci: Add Elkhart Lake CPU support +Git-commit: add492d2e9446a77ede9bb43699ec85ca8fc1aba +Patch-mainline: v5.6-rc7 +References: bsc#1051510 + +This adds support for the Trace Hub in Elkhart Lake CPU. + +Signed-off-by: Alexander Shishkin +Reviewed-by: Andy Shevchenko +Cc: stable@vger.kernel.org +Link: https://lore.kernel.org/r/20200317062215.15598-7-alexander.shishkin@linux.intel.com +Signed-off-by: Greg Kroah-Hartman +Acked-by: Takashi Iwai + +--- + drivers/hwtracing/intel_th/pci.c | 5 +++++ + 1 file changed, 5 insertions(+) + +--- a/drivers/hwtracing/intel_th/pci.c ++++ b/drivers/hwtracing/intel_th/pci.c +@@ -189,6 +189,11 @@ static const struct pci_device_id intel_ + .driver_data = (kernel_ulong_t)&intel_th_2x, + }, + { ++ /* Elkhart Lake CPU */ ++ PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x4529), ++ .driver_data = (kernel_ulong_t)&intel_th_2x, ++ }, ++ { + /* Tiger Lake PCH */ + PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xa0a6), + .driver_data = (kernel_ulong_t)&intel_th_2x, diff --git a/patches.suse/iommu-amd-Remap-the-IOMMU-device-table-with-the-memo.patch b/patches.suse/iommu-amd-Remap-the-IOMMU-device-table-with-the-memo.patch new file mode 100644 index 0000000..7243252 --- /dev/null +++ b/patches.suse/iommu-amd-Remap-the-IOMMU-device-table-with-the-memo.patch @@ -0,0 +1,68 @@ +From 8780158cf977ea5f9912931a30b3d575b36dba22 Mon Sep 17 00:00:00 2001 +From: Lianbo Jiang +Date: Sun, 30 Sep 2018 11:10:32 +0800 +Subject: [PATCH] iommu/amd: Remap the IOMMU device table with the memory + encryption mask for kdump +References: bsc#1141895 +Git-commit: 8780158cf977ea5f9912931a30b3d575b36dba22 +Patch-mainline: v4.20-rc1 + +The kdump kernel copies the IOMMU device table from the old device table +which is encrypted when SME is enabled in the first kernel. So remap the +old device table with the memory encryption mask in the kdump kernel. + + [ bp: Massage commit message. ] + +Signed-off-by: Lianbo Jiang +Signed-off-by: Borislav Petkov +Reviewed-by: Tom Lendacky +Acked-by: Joerg Roedel +Cc: kexec@lists.infradead.org +Cc: tglx@linutronix.de +Cc: mingo@redhat.com +Cc: hpa@zytor.com +Cc: akpm@linux-foundation.org +Cc: dan.j.williams@intel.com +Cc: bhelgaas@google.com +Cc: baiyaowei@cmss.chinamobile.com +Cc: tiwai@suse.de +Cc: brijesh.singh@amd.com +Cc: dyoung@redhat.com +Cc: bhe@redhat.com +Link: https://lkml.kernel.org/r/20180930031033.22110-4-lijiang@redhat.com +--- + drivers/iommu/amd_iommu_init.c | 14 ++++++++++++-- + 1 file changed, 12 insertions(+), 2 deletions(-) + +diff --git a/drivers/iommu/amd_iommu_init.c b/drivers/iommu/amd_iommu_init.c +index 84b3e4445d46..3931c7de7c69 100644 +--- a/drivers/iommu/amd_iommu_init.c ++++ b/drivers/iommu/amd_iommu_init.c +@@ -902,12 +902,22 @@ static bool copy_device_table(void) + } + } + +- old_devtb_phys = entry & PAGE_MASK; ++ /* ++ * When SME is enabled in the first kernel, the entry includes the ++ * memory encryption mask(sme_me_mask), we must remove the memory ++ * encryption mask to obtain the true physical address in kdump kernel. ++ */ ++ old_devtb_phys = __sme_clr(entry) & PAGE_MASK; ++ + if (old_devtb_phys >= 0x100000000ULL) { + pr_err("The address of old device table is above 4G, not trustworthy!\n"); + return false; + } +- old_devtb = memremap(old_devtb_phys, dev_table_size, MEMREMAP_WB); ++ old_devtb = (sme_active() && is_kdump_kernel()) ++ ? (__force void *)ioremap_encrypted(old_devtb_phys, ++ dev_table_size) ++ : memremap(old_devtb_phys, dev_table_size, MEMREMAP_WB); ++ + if (!old_devtb) + return false; + +-- +2.16.4 + diff --git a/patches.suse/iommu-amd-check-feature-support-bit-before-accessing-msi-capability-registers b/patches.suse/iommu-amd-check-feature-support-bit-before-accessing-msi-capability-registers new file mode 100644 index 0000000..bd38604 --- /dev/null +++ b/patches.suse/iommu-amd-check-feature-support-bit-before-accessing-msi-capability-registers @@ -0,0 +1,78 @@ +From: Suravee Suthikulpanit +Date: Wed, 20 Nov 2019 07:55:48 -0600 +Subject: iommu/amd: Check feature support bit before accessing MSI capability + registers +Git-commit: 813071438e83d338ba5cfe98b3b26c890dc0a6c0 +Patch-mainline: v5.6-rc1 +References: bsc#1166101 + +The IOMMU MMIO access to MSI capability registers is available only if +the EFR[MsiCapMmioSup] is set. Current implementation assumes this bit +is set if the EFR[XtSup] is set, which might not be the case. + +Fix by checking the EFR[MsiCapMmioSup] before accessing the MSI address +low/high and MSI data registers via the MMIO. + +Fixes: 66929812955b ('iommu/amd: Add support for X2APIC IOMMU interrupts') +Signed-off-by: Suravee Suthikulpanit +Signed-off-by: Joerg Roedel +--- + drivers/iommu/amd_iommu_init.c | 17 ++++++++++++----- + drivers/iommu/amd_iommu_types.h | 1 + + 2 files changed, 13 insertions(+), 5 deletions(-) + +diff --git a/drivers/iommu/amd_iommu_init.c b/drivers/iommu/amd_iommu_init.c +index 1b65302e07b1..f46e4aba3d91 100644 +--- a/drivers/iommu/amd_iommu_init.c ++++ b/drivers/iommu/amd_iommu_init.c +@@ -149,7 +149,7 @@ bool amd_iommu_dump; + bool amd_iommu_irq_remap __read_mostly; + + int amd_iommu_guest_ir = AMD_IOMMU_GUEST_IR_VAPIC; +-static int amd_iommu_xt_mode = IRQ_REMAP_X2APIC_MODE; ++static int amd_iommu_xt_mode = IRQ_REMAP_XAPIC_MODE; + + static bool amd_iommu_detected; + static bool __initdata amd_iommu_disabled; +@@ -1534,8 +1534,15 @@ static int __init init_iommu_one(struct amd_iommu *iommu, struct ivhd_header *h) + iommu->mmio_phys_end = MMIO_CNTR_CONF_OFFSET; + if (((h->efr_reg & (0x1 << IOMMU_EFR_GASUP_SHIFT)) == 0)) + amd_iommu_guest_ir = AMD_IOMMU_GUEST_IR_LEGACY; +- if (((h->efr_reg & (0x1 << IOMMU_EFR_XTSUP_SHIFT)) == 0)) +- amd_iommu_xt_mode = IRQ_REMAP_XAPIC_MODE; ++ /* ++ * Note: Since iommu_update_intcapxt() leverages ++ * the IOMMU MMIO access to MSI capability block registers ++ * for MSI address lo/hi/data, we need to check both ++ * EFR[XtSup] and EFR[MsiCapMmioSup] for x2APIC support. ++ */ ++ if ((h->efr_reg & BIT(IOMMU_EFR_XTSUP_SHIFT)) && ++ (h->efr_reg & BIT(IOMMU_EFR_MSICAPMMIOSUP_SHIFT))) ++ amd_iommu_xt_mode = IRQ_REMAP_X2APIC_MODE; + break; + default: + return -EINVAL; +@@ -1984,8 +1991,8 @@ static int iommu_init_intcapxt(struct amd_iommu *iommu) + struct irq_affinity_notify *notify = &iommu->intcapxt_notify; + + /** +- * IntCapXT requires XTSup=1, which can be inferred +- * amd_iommu_xt_mode. ++ * IntCapXT requires XTSup=1 and MsiCapMmioSup=1, ++ * which can be inferred from amd_iommu_xt_mode. + */ + if (amd_iommu_xt_mode != IRQ_REMAP_X2APIC_MODE) + return 0; +diff --git a/drivers/iommu/amd_iommu_types.h b/drivers/iommu/amd_iommu_types.h +index f52f59d5c6bd..f8a7945f3df9 100644 +--- a/drivers/iommu/amd_iommu_types.h ++++ b/drivers/iommu/amd_iommu_types.h +@@ -383,6 +383,7 @@ + /* IOMMU Extended Feature Register (EFR) */ + #define IOMMU_EFR_XTSUP_SHIFT 2 + #define IOMMU_EFR_GASUP_SHIFT 7 ++#define IOMMU_EFR_MSICAPMMIOSUP_SHIFT 46 + + #define MAX_DOMAIN_ID 65536 + + diff --git a/patches.suse/iommu-amd-only-support-x2apic-with-ivhd-type-11h-40h b/patches.suse/iommu-amd-only-support-x2apic-with-ivhd-type-11h-40h new file mode 100644 index 0000000..b16edb7 --- /dev/null +++ b/patches.suse/iommu-amd-only-support-x2apic-with-ivhd-type-11h-40h @@ -0,0 +1,49 @@ +From: Suravee Suthikulpanit +Date: Wed, 20 Nov 2019 07:55:49 -0600 +Subject: iommu/amd: Only support x2APIC with IVHD type 11h/40h +Git-commit: 966b753cf3969553ca50bacd2b8c4ddade5ecc9e +Patch-mainline: v5.6-rc1 +References: bsc#1166102 + +Current implementation for IOMMU x2APIC support makes use of +the MMIO access to MSI capability block registers, which requires +checking EFR[MsiCapMmioSup]. However, only IVHD type 11h/40h contain +the information, and not in the IVHD type 10h IOMMU feature reporting +field. Since the BIOS in newer systems, which supports x2APIC, would +normally contain IVHD type 11h/40h, remove the IOMMU_FEAT_XTSUP_SHIFT +check for IVHD type 10h, and only support x2APIC with IVHD type 11h/40h. + +Fixes: 66929812955b ('iommu/amd: Add support for X2APIC IOMMU interrupts') +Signed-off-by: Suravee Suthikulpanit +Signed-off-by: Joerg Roedel +--- + drivers/iommu/amd_iommu_init.c | 2 -- + drivers/iommu/amd_iommu_types.h | 1 - + 2 files changed, 3 deletions(-) + +diff --git a/drivers/iommu/amd_iommu_init.c b/drivers/iommu/amd_iommu_init.c +index f46e4aba3d91..36649592ddf3 100644 +--- a/drivers/iommu/amd_iommu_init.c ++++ b/drivers/iommu/amd_iommu_init.c +@@ -1523,8 +1523,6 @@ static int __init init_iommu_one(struct amd_iommu *iommu, struct ivhd_header *h) + iommu->mmio_phys_end = MMIO_CNTR_CONF_OFFSET; + if (((h->efr_attr & (0x1 << IOMMU_FEAT_GASUP_SHIFT)) == 0)) + amd_iommu_guest_ir = AMD_IOMMU_GUEST_IR_LEGACY; +- if (((h->efr_attr & (0x1 << IOMMU_FEAT_XTSUP_SHIFT)) == 0)) +- amd_iommu_xt_mode = IRQ_REMAP_XAPIC_MODE; + break; + case 0x11: + case 0x40: +diff --git a/drivers/iommu/amd_iommu_types.h b/drivers/iommu/amd_iommu_types.h +index f8a7945f3df9..798e1533a147 100644 +--- a/drivers/iommu/amd_iommu_types.h ++++ b/drivers/iommu/amd_iommu_types.h +@@ -377,7 +377,6 @@ + #define IOMMU_CAP_EFR 27 + + /* IOMMU Feature Reporting Field (for IVHD type 10h */ +-#define IOMMU_FEAT_XTSUP_SHIFT 0 + #define IOMMU_FEAT_GASUP_SHIFT 6 + + /* IOMMU Extended Feature Register (EFR) */ + diff --git a/patches.suse/iommu-dma-fix-msi-reservation-allocation b/patches.suse/iommu-dma-fix-msi-reservation-allocation new file mode 100644 index 0000000..e7eb70f --- /dev/null +++ b/patches.suse/iommu-dma-fix-msi-reservation-allocation @@ -0,0 +1,65 @@ +From: Marc Zyngier +Date: Wed, 4 Mar 2020 11:11:17 +0000 +Subject: iommu/dma: Fix MSI reservation allocation +Git-commit: 65ac74f1de3334852fb7d9b1b430fa5a06524276 +Patch-mainline: v5.6-rc6 +References: bsc#1166730 + +The way cookie_init_hw_msi_region() allocates the iommu_dma_msi_page +structures doesn't match the way iommu_put_dma_cookie() frees them. + +The former performs a single allocation of all the required structures, +while the latter tries to free them one at a time. It doesn't quite +work for the main use case (the GICv3 ITS where the range is 64kB) +when the base granule size is 4kB. + +This leads to a nice slab corruption on teardown, which is easily +observable by simply creating a VF on a SRIOV-capable device, and +tearing it down immediately (no need to even make use of it). +Fortunately, this only affects systems where the ITS isn't translated +by the SMMU, which are both rare and non-standard. + +Fix it by allocating iommu_dma_msi_page structures one at a time. + +Fixes: 7c1b058c8b5a3 ("iommu/dma: Handle IOMMU API reserved regions") +Signed-off-by: Marc Zyngier +Reviewed-by: Eric Auger +Cc: Robin Murphy +Cc: Joerg Roedel +Cc: Will Deacon +Cc: stable@vger.kernel.org +Reviewed-by: Robin Murphy +Signed-off-by: Joerg Roedel +--- + drivers/iommu/dma-iommu.c | 16 ++++++++-------- + 1 file changed, 8 insertions(+), 8 deletions(-) + +diff --git a/drivers/iommu/dma-iommu.c b/drivers/iommu/dma-iommu.c +index a2e96a5fd9a7..ba128d1cdaee 100644 +--- a/drivers/iommu/dma-iommu.c ++++ b/drivers/iommu/dma-iommu.c +@@ -177,15 +177,15 @@ static int cookie_init_hw_msi_region(struct iommu_dma_cookie *cookie, + start -= iova_offset(iovad, start); + num_pages = iova_align(iovad, end - start) >> iova_shift(iovad); + +- msi_page = kcalloc(num_pages, sizeof(*msi_page), GFP_KERNEL); +- if (!msi_page) +- return -ENOMEM; +- + for (i = 0; i < num_pages; i++) { +- msi_page[i].phys = start; +- msi_page[i].iova = start; +- INIT_LIST_HEAD(&msi_page[i].list); +- list_add(&msi_page[i].list, &cookie->msi_page_list); ++ msi_page = kmalloc(sizeof(*msi_page), GFP_KERNEL); ++ if (!msi_page) ++ return -ENOMEM; ++ ++ msi_page->phys = start; ++ msi_page->iova = start; ++ INIT_LIST_HEAD(&msi_page->list); ++ list_add(&msi_page->list, &cookie->msi_page_list); + start += iovad->granule; + } + + diff --git a/patches.suse/iommu-vt-d-dmar-replace-warn_taint-with-pr_warn-add_taint b/patches.suse/iommu-vt-d-dmar-replace-warn_taint-with-pr_warn-add_taint new file mode 100644 index 0000000..3160fe7 --- /dev/null +++ b/patches.suse/iommu-vt-d-dmar-replace-warn_taint-with-pr_warn-add_taint @@ -0,0 +1,99 @@ +From: Hans de Goede +Date: Mon, 9 Mar 2020 15:01:37 +0100 +Subject: iommu/vt-d: dmar: replace WARN_TAINT with pr_warn + add_taint +Git-commit: 59833696442c674acbbd297772ba89e7ad8c753d +Patch-mainline: v5.6-rc6 +References: bsc#1166731 + +Quoting from the comment describing the WARN functions in +include/asm-generic/bug.h: + + * WARN(), WARN_ON(), WARN_ON_ONCE, and so on can be used to report + * significant kernel issues that need prompt attention if they should ever + * appear at runtime. + * + * Do not use these macros when checking for invalid external inputs + +The (buggy) firmware tables which the dmar code was calling WARN_TAINT +for really are invalid external inputs. They are not under the kernel's +control and the issues in them cannot be fixed by a kernel update. +So logging a backtrace, which invites bug reports to be filed about this, +is not helpful. + +Some distros, e.g. Fedora, have tools watching for the kernel backtraces +logged by the WARN macros and offer the user an option to file a bug for +this when these are encountered. The WARN_TAINT in warn_invalid_dmar() ++ another iommu WARN_TAINT, addressed in another patch, have lead to over +a 100 bugs being filed this way. + +This commit replaces the WARN_TAINT("...") calls, with +pr_warn(FW_BUG "...") + add_taint(TAINT_FIRMWARE_WORKAROUND, ...) calls +avoiding the backtrace and thus also avoiding bug-reports being filed +about this against the kernel. + +Fixes: fd0c8894893c ("intel-iommu: Set a more specific taint flag for invalid BIOS DMAR tables") +Fixes: e625b4a95d50 ("iommu/vt-d: Parse ANDD records") +Signed-off-by: Hans de Goede +Signed-off-by: Joerg Roedel +Acked-by: Lu Baolu +Cc: stable@vger.kernel.org +Link: https://lore.kernel.org/r/20200309140138.3753-2-hdegoede@redhat.com +BugLink: https://bugzilla.redhat.com/show_bug.cgi?id=1564895 +--- + drivers/iommu/dmar.c | 11 ++++++----- + 1 file changed, 6 insertions(+), 5 deletions(-) + +diff --git a/drivers/iommu/dmar.c b/drivers/iommu/dmar.c +index 7b16c4db40b4..c000ddff822e 100644 +--- a/drivers/iommu/dmar.c ++++ b/drivers/iommu/dmar.c +@@ -441,12 +441,13 @@ static int __init dmar_parse_one_andd(struct acpi_dmar_header *header, + + /* Check for NUL termination within the designated length */ + if (strnlen(andd->device_name, header->length - 8) == header->length - 8) { +- WARN_TAINT(1, TAINT_FIRMWARE_WORKAROUND, ++ pr_warn(FW_BUG + "Your BIOS is broken; ANDD object name is not NUL-terminated\n" + "BIOS vendor: %s; Ver: %s; Product Version: %s\n", + dmi_get_system_info(DMI_BIOS_VENDOR), + dmi_get_system_info(DMI_BIOS_VERSION), + dmi_get_system_info(DMI_PRODUCT_VERSION)); ++ add_taint(TAINT_FIRMWARE_WORKAROUND, LOCKDEP_STILL_OK); + return -EINVAL; + } + pr_info("ANDD device: %x name: %s\n", andd->device_number, +@@ -472,14 +473,14 @@ static int dmar_parse_one_rhsa(struct acpi_dmar_header *header, void *arg) + return 0; + } + } +- WARN_TAINT( +- 1, TAINT_FIRMWARE_WORKAROUND, ++ pr_warn(FW_BUG + "Your BIOS is broken; RHSA refers to non-existent DMAR unit at %llx\n" + "BIOS vendor: %s; Ver: %s; Product Version: %s\n", + drhd->reg_base_addr, + dmi_get_system_info(DMI_BIOS_VENDOR), + dmi_get_system_info(DMI_BIOS_VERSION), + dmi_get_system_info(DMI_PRODUCT_VERSION)); ++ add_taint(TAINT_FIRMWARE_WORKAROUND, LOCKDEP_STILL_OK); + + return 0; + } +@@ -828,14 +829,14 @@ int __init dmar_table_init(void) + + static void warn_invalid_dmar(u64 addr, const char *message) + { +- WARN_TAINT_ONCE( +- 1, TAINT_FIRMWARE_WORKAROUND, ++ pr_warn_once(FW_BUG + "Your BIOS is broken; DMAR reported at address %llx%s!\n" + "BIOS vendor: %s; Ver: %s; Product Version: %s\n", + addr, message, + dmi_get_system_info(DMI_BIOS_VENDOR), + dmi_get_system_info(DMI_BIOS_VERSION), + dmi_get_system_info(DMI_PRODUCT_VERSION)); ++ add_taint(TAINT_FIRMWARE_WORKAROUND, LOCKDEP_STILL_OK); + } + + static int __ref + diff --git a/patches.suse/iommu-vt-d-fix-a-bug-in-intel_iommu_iova_to_phys-for-huge-page b/patches.suse/iommu-vt-d-fix-a-bug-in-intel_iommu_iova_to_phys-for-huge-page new file mode 100644 index 0000000..f88d57f --- /dev/null +++ b/patches.suse/iommu-vt-d-fix-a-bug-in-intel_iommu_iova_to_phys-for-huge-page @@ -0,0 +1,40 @@ +From: Yonghyun Hwang +Date: Wed, 26 Feb 2020 12:30:06 -0800 +Subject: iommu/vt-d: Fix a bug in intel_iommu_iova_to_phys() for huge page +Git-commit: 77a1bce84bba01f3f143d77127b72e872b573795 +Patch-mainline: v5.6-rc6 +References: bsc#1166732 + +intel_iommu_iova_to_phys() has a bug when it translates an IOVA for a huge +page onto its corresponding physical address. This commit fixes the bug by +accomodating the level of page entry for the IOVA and adds IOVA's lower +address to the physical address. + +Cc: +Acked-by: Lu Baolu +Reviewed-by: Moritz Fischer +Signed-off-by: Yonghyun Hwang +Fixes: 3871794642579 ("VT-d: Changes to support KVM") +Signed-off-by: Joerg Roedel +--- + drivers/iommu/intel-iommu.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c +index 6fa6de2b6ad5..33593fea0250 100644 +--- a/drivers/iommu/intel-iommu.c ++++ b/drivers/iommu/intel-iommu.c +@@ -5700,8 +5700,10 @@ static phys_addr_t intel_iommu_iova_to_phys(struct iommu_domain *domain, + u64 phys = 0; + + pte = pfn_to_dma_pte(dmar_domain, iova >> VTD_PAGE_SHIFT, &level); +- if (pte) +- phys = dma_pte_addr(pte); ++ if (pte && dma_pte_present(pte)) ++ phys = dma_pte_addr(pte) + ++ (iova & (BIT_MASK(level_to_offset_bits(level) + ++ VTD_PAGE_SHIFT) - 1)); + + return phys; + } + diff --git a/patches.suse/iommu-vt-d-fix-compile-warning-from-intel-svm-h b/patches.suse/iommu-vt-d-fix-compile-warning-from-intel-svm-h new file mode 100644 index 0000000..56b0a62 --- /dev/null +++ b/patches.suse/iommu-vt-d-fix-compile-warning-from-intel-svm-h @@ -0,0 +1,40 @@ +From: Joerg Roedel +Date: Mon, 10 Feb 2020 10:36:56 +0100 +Subject: iommu/vt-d: Fix compile warning from intel-svm.h +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit +Git-commit: e7598fac323aad0e502415edeffd567315994dd6 +Patch-mainline: v5.6-rc3 +References: bsc#1166103 + +The intel_svm_is_pasid_valid() needs to be marked inline, otherwise it +causes the compile warning below: + + CC [M] drivers/dma/idxd/cdev.o +In file included from drivers/dma/idxd/cdev.c:9:0: +./include/linux/intel-svm.h:125:12: warning: ‘intel_svm_is_pasid_valid’ defined but not used [-Wunused-function] + static int intel_svm_is_pasid_valid(struct device *dev, int pasid) + ^~~~~~~~~~~~~~~~~~~~~~~~ + +Reported-by: Borislav Petkov +Fixes: 15060aba71711 ('iommu/vt-d: Helper function to query if a pasid has any active users') +Signed-off-by: Joerg Roedel +--- + include/linux/intel-svm.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/include/linux/intel-svm.h b/include/linux/intel-svm.h +index 94f047a8a845..d7c403d0dd27 100644 +--- a/include/linux/intel-svm.h ++++ b/include/linux/intel-svm.h +@@ -122,7 +122,7 @@ static inline int intel_svm_unbind_mm(struct device *dev, int pasid) + BUG(); + } + +-static int intel_svm_is_pasid_valid(struct device *dev, int pasid) ++static inline int intel_svm_is_pasid_valid(struct device *dev, int pasid) + { + return -EINVAL; + } + diff --git a/patches.suse/iommu-vt-d-fix-the-wrong-printing-in-rhsa-parsing b/patches.suse/iommu-vt-d-fix-the-wrong-printing-in-rhsa-parsing new file mode 100644 index 0000000..4bcaea1 --- /dev/null +++ b/patches.suse/iommu-vt-d-fix-the-wrong-printing-in-rhsa-parsing @@ -0,0 +1,35 @@ +From: Zhenzhong Duan +Date: Thu, 12 Mar 2020 14:09:54 +0800 +Subject: iommu/vt-d: Fix the wrong printing in RHSA parsing +Git-commit: b0bb0c22c4db623f2e7b1a471596fbf1c22c6dc5 +Patch-mainline: v5.6-rc6 +References: bsc#1166733 + +When base address in RHSA structure doesn't match base address in +each DRHD structure, the base address in last DRHD is printed out. + +This doesn't make sense when there are multiple DRHD units, fix it +by printing the buggy RHSA's base address. + +Signed-off-by: Lu Baolu +Signed-off-by: Zhenzhong Duan +Fixes: fd0c8894893cb ("intel-iommu: Set a more specific taint flag for invalid BIOS DMAR tables") +Signed-off-by: Joerg Roedel +--- + drivers/iommu/dmar.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/iommu/dmar.c b/drivers/iommu/dmar.c +index c000ddff822e..c7b1461e8d0a 100644 +--- a/drivers/iommu/dmar.c ++++ b/drivers/iommu/dmar.c +@@ -476,7 +476,7 @@ static int dmar_parse_one_rhsa(struct acpi_dmar_header *header, void *arg) + pr_warn(FW_BUG + "Your BIOS is broken; RHSA refers to non-existent DMAR unit at %llx\n" + "BIOS vendor: %s; Ver: %s; Product Version: %s\n", +- drhd->reg_base_addr, ++ rhsa->base_address, + dmi_get_system_info(DMI_BIOS_VENDOR), + dmi_get_system_info(DMI_BIOS_VERSION), + dmi_get_system_info(DMI_PRODUCT_VERSION)); + diff --git a/patches.suse/iommu-vt-d-ignore-devices-with-out-of-spec-domain-number b/patches.suse/iommu-vt-d-ignore-devices-with-out-of-spec-domain-number new file mode 100644 index 0000000..26a8038 --- /dev/null +++ b/patches.suse/iommu-vt-d-ignore-devices-with-out-of-spec-domain-number @@ -0,0 +1,69 @@ +From: Daniel Drake +Date: Thu, 12 Mar 2020 14:09:55 +0800 +Subject: iommu/vt-d: Ignore devices with out-of-spec domain number +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit +Git-commit: da72a379b2ec0bad3eb265787f7008bead0b040c +Patch-mainline: v5.6-rc6 +References: bsc#1166734 + +VMD subdevices are created with a PCI domain ID of 0x10000 or +higher. + +These subdevices are also handled like all other PCI devices by +dmar_pci_bus_notifier(). + +However, when dmar_alloc_pci_notify_info() take records of such devices, +it will truncate the domain ID to a u16 value (in info->seg). +The device at (e.g.) 10000:00:02.0 is then treated by the DMAR code as if +it is 0000:00:02.0. + +In the unlucky event that a real device also exists at 0000:00:02.0 and +also has a device-specific entry in the DMAR table, +dmar_insert_dev_scope() will crash on: +   BUG_ON(i >= devices_cnt); + +That's basically a sanity check that only one PCI device matches a +single DMAR entry; in this case we seem to have two matching devices. + +Fix this by ignoring devices that have a domain number higher than +what can be looked up in the DMAR table. + +This problem was carefully diagnosed by Jian-Hong Pan. + +Signed-off-by: Lu Baolu +Signed-off-by: Daniel Drake +Fixes: 59ce0515cdaf3 ("iommu/vt-d: Update DRHD/RMRR/ATSR device scope caches when PCI hotplug happens") +Signed-off-by: Joerg Roedel +--- + drivers/iommu/dmar.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/drivers/iommu/dmar.c b/drivers/iommu/dmar.c +index c7b1461e8d0a..f77dae7ba7d4 100644 +--- a/drivers/iommu/dmar.c ++++ b/drivers/iommu/dmar.c +@@ -28,6 +28,7 @@ + #include + #include + #include ++#include + #include + #include + +@@ -128,6 +129,13 @@ dmar_alloc_pci_notify_info(struct pci_dev *dev, unsigned long event) + + BUG_ON(dev->is_virtfn); + ++ /* ++ * Ignore devices that have a domain number higher than what can ++ * be looked up in DMAR, e.g. VMD subdevices with domain 0x10000 ++ */ ++ if (pci_domain_nr(dev->bus) > U16_MAX) ++ return NULL; ++ + /* Only generate path[] for device addition event */ + if (event == BUS_NOTIFY_ADD_DEVICE) + for (tmp = dev; tmp; tmp = tmp->bus->self) + diff --git a/patches.suse/iommu-vt-d-quirk_ioat_snb_local_iommu-replace-warn_taint-with-pr_warn-add_taint b/patches.suse/iommu-vt-d-quirk_ioat_snb_local_iommu-replace-warn_taint-with-pr_warn-add_taint new file mode 100644 index 0000000..c27406b --- /dev/null +++ b/patches.suse/iommu-vt-d-quirk_ioat_snb_local_iommu-replace-warn_taint-with-pr_warn-add_taint @@ -0,0 +1,53 @@ +From: Hans de Goede +Date: Mon, 9 Mar 2020 19:25:10 +0100 +Subject: iommu/vt-d: quirk_ioat_snb_local_iommu: replace WARN_TAINT with + pr_warn + add_taint +Git-commit: 81ee85d0462410de8eeeec1b9761941fd6ed8c7b +Patch-mainline: v5.6-rc6 +References: bsc#1166735 + +Quoting from the comment describing the WARN functions in +include/asm-generic/bug.h: + + * WARN(), WARN_ON(), WARN_ON_ONCE, and so on can be used to report + * significant kernel issues that need prompt attention if they should ever + * appear at runtime. + * + * Do not use these macros when checking for invalid external inputs + +The (buggy) firmware tables which the dmar code was calling WARN_TAINT +for really are invalid external inputs. They are not under the kernel's +control and the issues in them cannot be fixed by a kernel update. +So logging a backtrace, which invites bug reports to be filed about this, +is not helpful. + +Fixes: 556ab45f9a77 ("ioat2: catch and recover from broken vtd configurations v6") +Signed-off-by: Hans de Goede +Acked-by: Lu Baolu +Link: https://lore.kernel.org/r/20200309182510.373875-1-hdegoede@redhat.com +BugLink: https://bugzilla.redhat.com/show_bug.cgi?id=701847 +Signed-off-by: Joerg Roedel +--- + drivers/iommu/intel-iommu.c | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c +index bdcdfff6015b..2943d3600b7c 100644 +--- a/drivers/iommu/intel-iommu.c ++++ b/drivers/iommu/intel-iommu.c +@@ -4261,10 +4261,11 @@ static void quirk_ioat_snb_local_iommu(struct pci_dev *pdev) + + /* we know that the this iommu should be at offset 0xa000 from vtbar */ + drhd = dmar_find_matched_drhd_unit(pdev); +- if (WARN_TAINT_ONCE(!drhd || drhd->reg_base_addr - vtbar != 0xa000, +- TAINT_FIRMWARE_WORKAROUND, +- "BIOS assigned incorrect VT-d unit for Intel(R) QuickData Technology device\n")) ++ if (!drhd || drhd->reg_base_addr - vtbar != 0xa000) { ++ pr_warn_once(FW_BUG "BIOS assigned incorrect VT-d unit for Intel(R) QuickData Technology device\n"); ++ add_taint(TAINT_FIRMWARE_WORKAROUND, LOCKDEP_STILL_OK); + pdev->dev.archdata.iommu = DUMMY_DEVICE_DOMAIN_INFO; ++ } + } + DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IOAT_SNB, quirk_ioat_snb_local_iommu); + + diff --git a/patches.suse/ipmi-fix-hung-processes-in-__get_guid.patch b/patches.suse/ipmi-fix-hung-processes-in-__get_guid.patch new file mode 100644 index 0000000..085f74f --- /dev/null +++ b/patches.suse/ipmi-fix-hung-processes-in-__get_guid.patch @@ -0,0 +1,72 @@ +From 32830a0534700f86366f371b150b17f0f0d140d7 Mon Sep 17 00:00:00 2001 +From: Wen Yang +Date: Fri, 3 Apr 2020 17:04:08 +0800 +Subject: [PATCH] ipmi: fix hung processes in __get_guid() +Git-commit: 32830a0534700f86366f371b150b17f0f0d140d7 +Patch-mainline: v5.7-rc1 +References: bsc#1111666 + +The wait_event() function is used to detect command completion. +When send_guid_cmd() returns an error, smi_send() has not been +called to send data. Therefore, wait_event() should not be used +on the error path, otherwise it will cause the following warning: + +[ 1361.588808] systemd-udevd D 0 1501 1436 0x00000004 +[ 1361.588813] ffff883f4b1298c0 0000000000000000 ffff883f4b188000 ffff887f7e3d9f40 +[ 1361.677952] ffff887f64bd4280 ffffc90037297a68 ffffffff8173ca3b ffffc90000000010 +[ 1361.767077] 00ffc90037297ad0 ffff887f7e3d9f40 0000000000000286 ffff883f4b188000 +[ 1361.856199] Call Trace: +[ 1361.885578] [] ? __schedule+0x23b/0x780 +[ 1361.951406] [] schedule+0x36/0x80 +[ 1362.010979] [] get_guid+0x118/0x150 [ipmi_msghandler] +[ 1362.091281] [] ? prepare_to_wait_event+0x100/0x100 +[ 1362.168533] [] ipmi_register_smi+0x405/0x940 [ipmi_msghandler] +[ 1362.258337] [] try_smi_init+0x529/0x950 [ipmi_si] +[ 1362.334521] [] ? std_irq_setup+0xd0/0xd0 [ipmi_si] +[ 1362.411701] [] init_ipmi_si+0x492/0x9e0 [ipmi_si] +[ 1362.487917] [] ? ipmi_pci_probe+0x280/0x280 [ipmi_si] +[ 1362.568219] [] do_one_initcall+0x50/0x180 +[ 1362.636109] [] ? kmem_cache_alloc_trace+0x142/0x190 +[ 1362.714330] [] do_init_module+0x5f/0x200 +[ 1362.781208] [] load_module+0x1898/0x1de0 +[ 1362.848069] [] ? __symbol_put+0x60/0x60 +[ 1362.913886] [] ? security_kernel_post_read_file+0x6b/0x80 +[ 1362.998514] [] SYSC_finit_module+0xe5/0x120 +[ 1363.068463] [] ? SYSC_finit_module+0xe5/0x120 +[ 1363.140513] [] SyS_finit_module+0xe/0x10 +[ 1363.207364] [] do_syscall_64+0x74/0x180 + +Fixes: 50c812b2b951 ("[PATCH] ipmi: add full sysfs support") +Signed-off-by: Wen Yang +Cc: Corey Minyard +Cc: Arnd Bergmann +Cc: Greg Kroah-Hartman +Cc: openipmi-developer@lists.sourceforge.net +Cc: linux-kernel@vger.kernel.org +Cc: stable@vger.kernel.org # 2.6.17- +Message-id: <20200403090408.58745-1-wenyang@linux.alibaba.com> +Signed-off-by: Corey Minyard +Acked-by: Takashi Iwai + +--- + drivers/char/ipmi/ipmi_msghandler.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c +index 64ba16dcb681..c48d8f086382 100644 +--- a/drivers/char/ipmi/ipmi_msghandler.c ++++ b/drivers/char/ipmi/ipmi_msghandler.c +@@ -3193,8 +3193,8 @@ static void __get_guid(struct ipmi_smi *intf) + if (rv) + /* Send failed, no GUID available. */ + bmc->dyn_guid_set = 0; +- +- wait_event(intf->waitq, bmc->dyn_guid_set != 2); ++ else ++ wait_event(intf->waitq, bmc->dyn_guid_set != 2); + + /* dyn_guid_set makes the guid data available. */ + smp_rmb(); +-- +2.16.4 + diff --git a/patches.suse/ipmi-ssif-Handle-a-possible-NULL-pointer-reference.patch b/patches.suse/ipmi-ssif-Handle-a-possible-NULL-pointer-reference.patch new file mode 100644 index 0000000..417f877 --- /dev/null +++ b/patches.suse/ipmi-ssif-Handle-a-possible-NULL-pointer-reference.patch @@ -0,0 +1,45 @@ +From 6b8526d3abc02c08a2f888e8c20b7ac9e5776dfe Mon Sep 17 00:00:00 2001 +From: Corey Minyard +Date: Mon, 23 Dec 2019 10:42:19 -0600 +Subject: [PATCH] ipmi:ssif: Handle a possible NULL pointer reference +Git-commit: 6b8526d3abc02c08a2f888e8c20b7ac9e5776dfe +Patch-mainline: v5.6-rc2 +References: bsc#1051510 + +In error cases a NULL can be passed to memcpy. The length will always +be zero, so it doesn't really matter, but go ahead and check for NULL, +anyway, to be more precise and avoid static analysis errors. + +Reported-by: kbuild test robot +Signed-off-by: Corey Minyard +Acked-by: Takashi Iwai + +--- + drivers/char/ipmi/ipmi_ssif.c | 10 +++++++--- + 1 file changed, 7 insertions(+), 3 deletions(-) + +diff --git a/drivers/char/ipmi/ipmi_ssif.c b/drivers/char/ipmi/ipmi_ssif.c +index 22c6a2e61236..8ac390c2b514 100644 +--- a/drivers/char/ipmi/ipmi_ssif.c ++++ b/drivers/char/ipmi/ipmi_ssif.c +@@ -775,10 +775,14 @@ static void msg_done_handler(struct ssif_info *ssif_info, int result, + flags = ipmi_ssif_lock_cond(ssif_info, &oflags); + msg = ssif_info->curr_msg; + if (msg) { ++ if (data) { ++ if (len > IPMI_MAX_MSG_LENGTH) ++ len = IPMI_MAX_MSG_LENGTH; ++ memcpy(msg->rsp, data, len); ++ } else { ++ len = 0; ++ } + msg->rsp_size = len; +- if (msg->rsp_size > IPMI_MAX_MSG_LENGTH) +- msg->rsp_size = IPMI_MAX_MSG_LENGTH; +- memcpy(msg->rsp, data, msg->rsp_size); + ssif_info->curr_msg = NULL; + } + +-- +2.16.4 + diff --git a/patches.suse/ipv4-ensure-rcu_read_lock-in-cipso_v4_error.patch b/patches.suse/ipv4-ensure-rcu_read_lock-in-cipso_v4_error.patch new file mode 100644 index 0000000..a81c115 --- /dev/null +++ b/patches.suse/ipv4-ensure-rcu_read_lock-in-cipso_v4_error.patch @@ -0,0 +1,44 @@ +From: Matteo Croce +Date: Fri, 21 Feb 2020 12:28:38 +0100 +Subject: ipv4: ensure rcu_read_lock() in cipso_v4_error() +Git-commit: 3e72dfdf8227b052393f71d820ec7599909dddc2 +Patch-mainline: 5.6-rc4 +References: git-fixes + +Similarly to commit c543cb4a5f07 ("ipv4: ensure rcu_read_lock() in +ipv4_link_failure()"), __ip_options_compile() must be called under rcu +protection. + +Fixes: 3da1ed7ac398 ("net: avoid use IPCB in cipso_v4_error") +Suggested-by: Guillaume Nault +Signed-off-by: Matteo Croce +Acked-by: Paul Moore +Signed-off-by: David S. Miller +Signed-off-by: Jiri Slaby +--- + net/ipv4/cipso_ipv4.c | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +--- a/net/ipv4/cipso_ipv4.c ++++ b/net/ipv4/cipso_ipv4.c +@@ -1738,6 +1738,7 @@ void cipso_v4_error(struct sk_buff *skb, + { + unsigned char optbuf[sizeof(struct ip_options) + 40]; + struct ip_options *opt = (struct ip_options *)optbuf; ++ int res; + + if (ip_hdr(skb)->protocol == IPPROTO_ICMP || error != -EACCES) + return; +@@ -1749,7 +1750,11 @@ void cipso_v4_error(struct sk_buff *skb, + + memset(opt, 0, sizeof(struct ip_options)); + opt->optlen = ip_hdr(skb)->ihl*4 - sizeof(struct iphdr); +- if (__ip_options_compile(dev_net(skb->dev), opt, skb, NULL)) ++ rcu_read_lock(); ++ res = __ip_options_compile(dev_net(skb->dev), opt, skb, NULL); ++ rcu_read_unlock(); ++ ++ if (res) + return; + + if (gateway) diff --git a/patches.suse/ipv6-restrict-IPV6_ADDRFORM-operation.patch b/patches.suse/ipv6-restrict-IPV6_ADDRFORM-operation.patch new file mode 100644 index 0000000..12be282 --- /dev/null +++ b/patches.suse/ipv6-restrict-IPV6_ADDRFORM-operation.patch @@ -0,0 +1,105 @@ +From: Eric Dumazet +Date: Tue, 25 Feb 2020 11:52:29 -0800 +Subject: ipv6: restrict IPV6_ADDRFORM operation +Patch-mainline: v5.6-rc4 +Git-commit: b6f6118901d1e867ac9177bbff3b00b185bd4fdc +References: bsc#1109837 + +IPV6_ADDRFORM is able to transform IPv6 socket to IPv4 one. +While this operation sounds illogical, we have to support it. + +One of the things it does for TCP socket is to switch sk->sk_prot +to tcp_prot. + +We now have other layers playing with sk->sk_prot, so we should make +sure to not interfere with them. + +This patch makes sure sk_prot is the default pointer for TCP IPv6 socket. + +syzbot reported : +BUG: kernel NULL pointer dereference, address: 0000000000000000 +PGD a0113067 P4D a0113067 PUD a8771067 PMD 0 +Oops: 0010 [#1] PREEMPT SMP KASAN +CPU: 0 PID: 10686 Comm: syz-executor.0 Not tainted 5.6.0-rc2-syzkaller #0 +Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011 +RIP: 0010:0x0 +Code: Bad RIP value. +RSP: 0018:ffffc9000281fce0 EFLAGS: 00010246 +RAX: 1ffffffff15f48ac RBX: ffffffff8afa4560 RCX: dffffc0000000000 +RDX: 0000000000000000 RSI: 0000000000000000 RDI: ffff8880a69a8f40 +RBP: ffffc9000281fd10 R08: ffffffff86ed9b0c R09: ffffed1014d351f5 +R10: ffffed1014d351f5 R11: 0000000000000000 R12: ffff8880920d3098 +R13: 1ffff1101241a613 R14: ffff8880a69a8f40 R15: 0000000000000000 +FS: 00007f2ae75db700(0000) GS:ffff8880aea00000(0000) knlGS:0000000000000000 +CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 +CR2: ffffffffffffffd6 CR3: 00000000a3b85000 CR4: 00000000001406f0 +DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 +DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 +Call Trace: + inet_release+0x165/0x1c0 net/ipv4/af_inet.c:427 + __sock_release net/socket.c:605 [inline] + sock_close+0xe1/0x260 net/socket.c:1283 + __fput+0x2e4/0x740 fs/file_table.c:280 + ____fput+0x15/0x20 fs/file_table.c:313 + task_work_run+0x176/0x1b0 kernel/task_work.c:113 + tracehook_notify_resume include/linux/tracehook.h:188 [inline] + exit_to_usermode_loop arch/x86/entry/common.c:164 [inline] + prepare_exit_to_usermode+0x480/0x5b0 arch/x86/entry/common.c:195 + syscall_return_slowpath+0x113/0x4a0 arch/x86/entry/common.c:278 + do_syscall_64+0x11f/0x1c0 arch/x86/entry/common.c:304 + entry_SYSCALL_64_after_hwframe+0x49/0xbe +RIP: 0033:0x45c429 +Code: ad b6 fb ff c3 66 2e 0f 1f 84 00 00 00 00 00 66 90 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 0f 83 7b b6 fb ff c3 66 2e 0f 1f 84 00 00 00 00 +RSP: 002b:00007f2ae75dac78 EFLAGS: 00000246 ORIG_RAX: 0000000000000036 +RAX: 0000000000000000 RBX: 00007f2ae75db6d4 RCX: 000000000045c429 +RDX: 0000000000000001 RSI: 000000000000011a RDI: 0000000000000004 +RBP: 000000000076bf20 R08: 0000000000000038 R09: 0000000000000000 +R10: 0000000020000180 R11: 0000000000000246 R12: 00000000ffffffff +R13: 0000000000000a9d R14: 00000000004ccfb4 R15: 000000000076bf2c +Modules linked in: +CR2: 0000000000000000 +---[ end trace 82567b5207e87bae ]--- +RIP: 0010:0x0 +Code: Bad RIP value. +RSP: 0018:ffffc9000281fce0 EFLAGS: 00010246 +RAX: 1ffffffff15f48ac RBX: ffffffff8afa4560 RCX: dffffc0000000000 +RDX: 0000000000000000 RSI: 0000000000000000 RDI: ffff8880a69a8f40 +RBP: ffffc9000281fd10 R08: ffffffff86ed9b0c R09: ffffed1014d351f5 +R10: ffffed1014d351f5 R11: 0000000000000000 R12: ffff8880920d3098 +R13: 1ffff1101241a613 R14: ffff8880a69a8f40 R15: 0000000000000000 +FS: 00007f2ae75db700(0000) GS:ffff8880aea00000(0000) knlGS:0000000000000000 +CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 +CR2: ffffffffffffffd6 CR3: 00000000a3b85000 CR4: 00000000001406f0 +DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 +DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 + +Fixes: 604326b41a6f ("bpf, sockmap: convert to generic sk_msg interface") +Signed-off-by: Eric Dumazet +Reported-by: syzbot+1938db17e275e85dc328@syzkaller.appspotmail.com +Cc: Daniel Borkmann +Signed-off-by: David S. Miller +Acked-by: Thomas Bogendoerfer +--- + net/ipv6/ipv6_sockglue.c | 10 ++++++++-- + 1 file changed, 8 insertions(+), 2 deletions(-) + +--- a/net/ipv6/ipv6_sockglue.c ++++ b/net/ipv6/ipv6_sockglue.c +@@ -185,9 +185,15 @@ static int do_ipv6_setsockopt(struct soc + retv = -EBUSY; + break; + } +- } else if (sk->sk_protocol != IPPROTO_TCP) ++ } else if (sk->sk_protocol == IPPROTO_TCP) { ++ if (sk->sk_prot != &tcpv6_prot) { ++ retv = -EBUSY; ++ break; ++ } ++ break; ++ } else { + break; +- ++ } + if (sk->sk_state != TCP_ESTABLISHED) { + retv = -ENOTCONN; + break; diff --git a/patches.suse/irqchip-bcm2835-Quiesce-IRQs-left-enabled-by-bootloa.patch b/patches.suse/irqchip-bcm2835-Quiesce-IRQs-left-enabled-by-bootloa.patch new file mode 100644 index 0000000..d6dd708 --- /dev/null +++ b/patches.suse/irqchip-bcm2835-Quiesce-IRQs-left-enabled-by-bootloa.patch @@ -0,0 +1,92 @@ +From bd59b343a9c902c522f006e6d71080f4893bbf42 Mon Sep 17 00:00:00 2001 +From: Lukas Wunner +Date: Tue, 25 Feb 2020 10:50:41 +0100 +Subject: [PATCH] irqchip/bcm2835: Quiesce IRQs left enabled by bootloader +Git-commit: bd59b343a9c902c522f006e6d71080f4893bbf42 +Patch-mainline: v5.7-rc1 +References: bsc#1051510 + +Per the spec, the BCM2835's IRQs are all disabled when coming out of +power-on reset. Its IRQ driver assumes that's still the case when the +kernel boots and does not perform any initialization of the registers. +However the Raspberry Pi Foundation's bootloader leaves the USB +interrupt enabled when handing over control to the kernel. + +Quiesce IRQs and the FIQ if they were left enabled and log a message to +let users know that they should update the bootloader once a fixed +version is released. + +If the USB interrupt is not quiesced and the USB driver later on claims +the FIQ (as it does on the Raspberry Pi Foundation's downstream kernel), +interrupt latency for all other peripherals increases and occasional +lockups occur. That's because both the FIQ and the normal USB interrupt +fire simultaneously: + +On a multicore Raspberry Pi, if normal interrupts are routed to CPU 0 +and the FIQ to CPU 1 (hardcoded in the Foundation's kernel), then a USB +interrupt causes CPU 0 to spin in bcm2836_chained_handle_irq() until the +FIQ on CPU 1 has cleared it. Other peripherals' interrupts are starved +as long. I've seen CPU 0 blocked for up to 2.9 msec. eMMC throughput +on a Compute Module 3 irregularly dips to 23.0 MB/s without this commit +but remains relatively constant at 23.5 MB/s with this commit. + +The lockups occur when CPU 0 receives a USB interrupt while holding a +lock which CPU 1 is trying to acquire while the FIQ is temporarily +disabled on CPU 1. At best users get RCU CPU stall warnings, but most +of the time the system just freezes. + +Fixes: 89214f009c1d ("ARM: bcm2835: add interrupt controller driver") +Signed-off-by: Lukas Wunner +Signed-off-by: Marc Zyngier +Reviewed-by: Florian Fainelli +Reviewed-by: Nicolas Saenz Julienne +Link: https://lore.kernel.org/r/f97868ba4e9b86ddad71f44ec9d8b3b7d8daa1ea.1582618537.git.lukas@wunner.de +Acked-by: Takashi Iwai + +--- + drivers/irqchip/irq-bcm2835.c | 15 +++++++++++++++ + 1 file changed, 15 insertions(+) + +diff --git a/drivers/irqchip/irq-bcm2835.c b/drivers/irqchip/irq-bcm2835.c +index 418245d31921..a1e004af23e7 100644 +--- a/drivers/irqchip/irq-bcm2835.c ++++ b/drivers/irqchip/irq-bcm2835.c +@@ -61,6 +61,7 @@ + | SHORTCUT1_MASK | SHORTCUT2_MASK) + + #define REG_FIQ_CONTROL 0x0c ++#define FIQ_CONTROL_ENABLE BIT(7) + + #define NR_BANKS 3 + #define IRQS_PER_BANK 32 +@@ -135,6 +136,7 @@ static int __init armctrl_of_init(struct device_node *node, + { + void __iomem *base; + int irq, b, i; ++ u32 reg; + + base = of_iomap(node, 0); + if (!base) +@@ -157,6 +159,19 @@ static int __init armctrl_of_init(struct device_node *node, + handle_level_irq); + irq_set_probe(irq); + } ++ ++ reg = readl_relaxed(intc.enable[b]); ++ if (reg) { ++ writel_relaxed(reg, intc.disable[b]); ++ pr_err(FW_BUG "Bootloader left irq enabled: " ++ "bank %d irq %*pbl\n", b, IRQS_PER_BANK, ®); ++ } ++ } ++ ++ reg = readl_relaxed(base + REG_FIQ_CONTROL); ++ if (reg & FIQ_CONTROL_ENABLE) { ++ writel_relaxed(0, base + REG_FIQ_CONTROL); ++ pr_err(FW_BUG "Bootloader left fiq enabled\n"); + } + + if (is_2836) { +-- +2.16.4 + diff --git a/patches.suse/irqdomain-Fix-a-memory-leak-in-irq_domain_push_irq.patch b/patches.suse/irqdomain-Fix-a-memory-leak-in-irq_domain_push_irq.patch new file mode 100644 index 0000000..f949f2d --- /dev/null +++ b/patches.suse/irqdomain-Fix-a-memory-leak-in-irq_domain_push_irq.patch @@ -0,0 +1,58 @@ +From 0f394daef89b38d58c91118a2b08b8a1b316703b Mon Sep 17 00:00:00 2001 +From: Kevin Hao +Date: Mon, 20 Jan 2020 12:35:47 +0800 +Subject: [PATCH] irqdomain: Fix a memory leak in irq_domain_push_irq() +Git-commit: 0f394daef89b38d58c91118a2b08b8a1b316703b +Patch-mainline: v5.6-rc1 +References: bsc#1051510 + +Fix a memory leak reported by kmemleak: +unreferenced object 0xffff000bc6f50e80 (size 128): + comm "kworker/23:2", pid 201, jiffies 4294894947 (age 942.132s) + hex dump (first 32 bytes): + 00 00 00 00 41 00 00 00 86 c0 03 00 00 00 00 00 ....A........... + 00 a0 b2 c6 0b 00 ff ff 40 51 fd 10 00 80 ff ff ........@Q...... + backtrace: + [<00000000e62d2240>] kmem_cache_alloc_trace+0x1a4/0x320 + [<00000000279143c9>] irq_domain_push_irq+0x7c/0x188 + [<00000000d9f4c154>] thunderx_gpio_probe+0x3ac/0x438 + [<00000000fd09ec22>] pci_device_probe+0xe4/0x198 + [<00000000d43eca75>] really_probe+0xdc/0x320 + [<00000000d3ebab09>] driver_probe_device+0x5c/0xf0 + [<000000005b3ecaa0>] __device_attach_driver+0x88/0xc0 + [<000000004e5915f5>] bus_for_each_drv+0x7c/0xc8 + [<0000000079d4db41>] __device_attach+0xe4/0x140 + [<00000000883bbda9>] device_initial_probe+0x18/0x20 + [<000000003be59ef6>] bus_probe_device+0x98/0xa0 + [<0000000039b03d3f>] deferred_probe_work_func+0x74/0xa8 + [<00000000870934ce>] process_one_work+0x1c8/0x470 + [<00000000e3cce570>] worker_thread+0x1f8/0x428 + [<000000005d64975e>] kthread+0xfc/0x128 + [<00000000f0eaa764>] ret_from_fork+0x10/0x18 + +Fixes: 495c38d3001f ("irqdomain: Add irq_domain_{push,pop}_irq() functions") +Signed-off-by: Kevin Hao +Signed-off-by: Marc Zyngier +Cc: stable@vger.kernel.org +Link: https://lore.kernel.org/r/20200120043547.22271-1-haokexin@gmail.com +Acked-by: Takashi Iwai + +--- + kernel/irq/irqdomain.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c +index 7a8808c8dfec..7527e5ef6fe5 100644 +--- a/kernel/irq/irqdomain.c ++++ b/kernel/irq/irqdomain.c +@@ -1476,6 +1476,7 @@ int irq_domain_push_irq(struct irq_domain *domain, int virq, void *arg) + if (rv) { + /* Restore the original irq_data. */ + *root_irq_data = *child_irq_data; ++ kfree(child_irq_data); + goto error; + } + +-- +2.16.4 + diff --git a/patches.suse/iwlegacy-Fix-Wcast-function-type.patch b/patches.suse/iwlegacy-Fix-Wcast-function-type.patch new file mode 100644 index 0000000..c8c71b6 --- /dev/null +++ b/patches.suse/iwlegacy-Fix-Wcast-function-type.patch @@ -0,0 +1,65 @@ +From da5e57e8a6a3e69dac2937ba63fa86355628fbb2 Mon Sep 17 00:00:00 2001 +From: Phong Tran +Date: Wed, 27 Nov 2019 00:55:28 +0700 +Subject: [PATCH] iwlegacy: Fix -Wcast-function-type +Git-commit: da5e57e8a6a3e69dac2937ba63fa86355628fbb2 +Patch-mainline: v5.6-rc1 +References: bsc#1051510 + +correct usage prototype of callback in tasklet_init(). +Report by https://github.com/KSPP/linux/issues/20 + +Signed-off-by: Phong Tran +Reviewed-by: Kees Cook +Signed-off-by: Kalle Valo +Acked-by: Takashi Iwai + +--- + drivers/net/wireless/intel/iwlegacy/3945-mac.c | 5 +++-- + drivers/net/wireless/intel/iwlegacy/4965-mac.c | 5 +++-- + 2 files changed, 6 insertions(+), 4 deletions(-) + +--- a/drivers/net/wireless/intel/iwlegacy/3945-mac.c ++++ b/drivers/net/wireless/intel/iwlegacy/3945-mac.c +@@ -1399,8 +1399,9 @@ il3945_dump_nic_error_log(struct il_priv + } + + static void +-il3945_irq_tasklet(struct il_priv *il) ++il3945_irq_tasklet(unsigned long data) + { ++ struct il_priv *il = (struct il_priv *)data; + u32 inta, handled = 0; + u32 inta_fh; + unsigned long flags; +@@ -3432,7 +3433,7 @@ il3945_setup_deferred_work(struct il_pri + timer_setup(&il->watchdog, il_bg_watchdog, 0); + + tasklet_init(&il->irq_tasklet, +- (void (*)(unsigned long))il3945_irq_tasklet, ++ il3945_irq_tasklet, + (unsigned long)il); + } + +--- a/drivers/net/wireless/intel/iwlegacy/4965-mac.c ++++ b/drivers/net/wireless/intel/iwlegacy/4965-mac.c +@@ -4363,8 +4363,9 @@ il4965_synchronize_irq(struct il_priv *i + } + + static void +-il4965_irq_tasklet(struct il_priv *il) ++il4965_irq_tasklet(unsigned long data) + { ++ struct il_priv *il = (struct il_priv *)data; + u32 inta, handled = 0; + u32 inta_fh; + unsigned long flags; +@@ -6264,7 +6265,7 @@ il4965_setup_deferred_work(struct il_pri + timer_setup(&il->watchdog, il_bg_watchdog, 0); + + tasklet_init(&il->irq_tasklet, +- (void (*)(unsigned long))il4965_irq_tasklet, ++ il4965_irq_tasklet, + (unsigned long)il); + } + diff --git a/patches.suse/iwlwifi-mvm-Do-not-require-PHY_SKU-NVM-section-for-3.patch b/patches.suse/iwlwifi-mvm-Do-not-require-PHY_SKU-NVM-section-for-3.patch new file mode 100644 index 0000000..f7abb36 --- /dev/null +++ b/patches.suse/iwlwifi-mvm-Do-not-require-PHY_SKU-NVM-section-for-3.patch @@ -0,0 +1,45 @@ +From a9149d243f259ad8f02b1e23dfe8ba06128f15e1 Mon Sep 17 00:00:00 2001 +From: Dan Moulding +Date: Tue, 28 Jan 2020 02:31:07 -0700 +Subject: [PATCH] iwlwifi: mvm: Do not require PHY_SKU NVM section for 3168 devices +Git-commit: a9149d243f259ad8f02b1e23dfe8ba06128f15e1 +Patch-mainline: v5.6-rc6 +References: bsc#1166632 + +The logic for checking required NVM sections was recently fixed in +commit b3f20e098293 ("iwlwifi: mvm: fix NVM check for 3168 +devices"). However, with that fixed the else is now taken for 3168 +devices and within the else clause there is a mandatory check for the +PHY_SKU section. This causes the parsing to fail for 3168 devices. + +The PHY_SKU section is really only mandatory for the IWL_NVM_EXT +layout (the phy_sku parameter of iwl_parse_nvm_data is only used when +the NVM type is IWL_NVM_EXT). So this changes the PHY_SKU section +check so that it's only mandatory for IWL_NVM_EXT. + +Fixes: b3f20e098293 ("iwlwifi: mvm: fix NVM check for 3168 devices") +Signed-off-by: Dan Moulding +Signed-off-by: Kalle Valo +Acked-by: Takashi Iwai + +--- + drivers/net/wireless/intel/iwlwifi/mvm/nvm.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/nvm.c b/drivers/net/wireless/intel/iwlwifi/mvm/nvm.c +index 70b29bf16bb9..60296a754af2 100644 +--- a/drivers/net/wireless/intel/iwlwifi/mvm/nvm.c ++++ b/drivers/net/wireless/intel/iwlwifi/mvm/nvm.c +@@ -308,7 +308,8 @@ iwl_parse_nvm_sections(struct iwl_mvm *mvm) + } + + /* PHY_SKU section is mandatory in B0 */ +- if (!mvm->nvm_sections[NVM_SECTION_TYPE_PHY_SKU].data) { ++ if (mvm->trans->cfg->nvm_type == IWL_NVM_EXT && ++ !mvm->nvm_sections[NVM_SECTION_TYPE_PHY_SKU].data) { + IWL_ERR(mvm, + "Can't parse phy_sku in B0, empty sections\n"); + return NULL; +-- +2.16.4 + diff --git a/patches.suse/iwlwifi-mvm-Fix-thermal-zone-registration.patch b/patches.suse/iwlwifi-mvm-Fix-thermal-zone-registration.patch new file mode 100644 index 0000000..38a64eb --- /dev/null +++ b/patches.suse/iwlwifi-mvm-Fix-thermal-zone-registration.patch @@ -0,0 +1,47 @@ +From baa6cf8450b72dcab11f37c47efce7c5b9b8ad0f Mon Sep 17 00:00:00 2001 +From: Andrei Otcheretianski +Date: Fri, 31 Jan 2020 15:45:24 +0200 +Subject: [PATCH] iwlwifi: mvm: Fix thermal zone registration +Git-commit: baa6cf8450b72dcab11f37c47efce7c5b9b8ad0f +Patch-mainline: v5.6-rc1 +References: bsc#1051510 + +Use a unique name when registering a thermal zone. Otherwise, with +multiple NICS, we hit the following warning during the unregistration. + +Warning: CPU: 2 PID: 3525 at fs/sysfs/group.c:255 RIP: 0010:sysfs_remove_group+0x80/0x90 Call Trace: dpm_sysfs_remove+0x57/0x60 device_del+0x5a/0x350 ? sscanf+0x4e/0x70 device_unregister+0x1a/0x60 hwmon_device_unregister+0x4a/0xa0 thermal_remove_hwmon_sysfs+0x175/0x1d0 thermal_zone_device_unregister+0x188/0x1e0 iwl_mvm_thermal_exit+0xe7/0x100 [iwlmvm] iwl_op_mode_mvm_stop+0x27/0x180 [iwlmvm] _iwl_op_mode_stop.isra.3+0x2b/0x50 [iwlwifi] iwl_opmode_deregister+0x90/0xa0 [iwlwifi] __exit_compat+0x10/0x2c7 [iwlmvm] __x64_sys_delete_module+0x13f/0x270 do_syscall_64+0x5a/0x110 entry_SYSCALL_64_after_hwframe+0x44/0xa9 + +Signed-off-by: Andrei Otcheretianski +Signed-off-by: Luca Coelho +Signed-off-by: Kalle Valo +Acked-by: Takashi Iwai + +--- + drivers/net/wireless/intel/iwlwifi/mvm/tt.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/tt.c b/drivers/net/wireless/intel/iwlwifi/mvm/tt.c +index b5a16f00bada..fcad25ffd811 100644 +--- a/drivers/net/wireless/intel/iwlwifi/mvm/tt.c ++++ b/drivers/net/wireless/intel/iwlwifi/mvm/tt.c +@@ -734,7 +734,8 @@ static struct thermal_zone_device_ops tzone_ops = { + static void iwl_mvm_thermal_zone_register(struct iwl_mvm *mvm) + { + int i; +- char name[] = "iwlwifi"; ++ char name[16]; ++ static atomic_t counter = ATOMIC_INIT(0); + + if (!iwl_mvm_is_tt_in_fw(mvm)) { + mvm->tz_device.tzone = NULL; +@@ -744,6 +745,7 @@ static void iwl_mvm_thermal_zone_register(struct iwl_mvm *mvm) + + BUILD_BUG_ON(ARRAY_SIZE(name) >= THERMAL_NAME_LENGTH); + ++ sprintf(name, "iwlwifi_%u", atomic_inc_return(&counter) & 0xFF); + mvm->tz_device.tzone = thermal_zone_device_register(name, + IWL_MAX_DTS_TRIPS, + IWL_WRITABLE_TRIPS_MSK, +-- +2.16.4 + diff --git a/patches.suse/kdump-proc-vmcore-enable-kdumping-encrypted-memory-w.patch b/patches.suse/kdump-proc-vmcore-enable-kdumping-encrypted-memory-w.patch new file mode 100644 index 0000000..98d611d --- /dev/null +++ b/patches.suse/kdump-proc-vmcore-enable-kdumping-encrypted-memory-w.patch @@ -0,0 +1,223 @@ +From 992b649a3f013465d8128da02e5449def662a4c3 Mon Sep 17 00:00:00 2001 +From: Lianbo Jiang +Date: Sun, 30 Sep 2018 16:37:41 +0800 +Subject: [PATCH] kdump, proc/vmcore: Enable kdumping encrypted memory with SME + enabled +References: bsc#1141895 +Git-commit: 992b649a3f013465d8128da02e5449def662a4c3 +Patch-mainline: v4.20-rc1 + +In the kdump kernel, the memory of the first kernel needs to be dumped +into the vmcore file. + +If SME is enabled in the first kernel, the old memory has to be remapped +with the memory encryption mask in order to access it properly. + +Split copy_oldmem_page() functionality to handle encrypted memory +properly. + + [ bp: Heavily massage everything. ] + +Signed-off-by: Lianbo Jiang +Signed-off-by: Borislav Petkov +Cc: kexec@lists.infradead.org +Cc: tglx@linutronix.de +Cc: mingo@redhat.com +Cc: hpa@zytor.com +Cc: akpm@linux-foundation.org +Cc: dan.j.williams@intel.com +Cc: bhelgaas@google.com +Cc: baiyaowei@cmss.chinamobile.com +Cc: tiwai@suse.de +Cc: brijesh.singh@amd.com +Cc: dyoung@redhat.com +Cc: bhe@redhat.com +Cc: jroedel@suse.de +Link: https://lkml.kernel.org/r/be7b47f9-6be6-e0d1-2c2a-9125bc74b818@redhat.com +--- + arch/x86/kernel/crash_dump_64.c | 60 ++++++++++++++++++++++++++++------------- + fs/proc/vmcore.c | 24 ++++++++++++----- + include/linux/crash_dump.h | 4 +++ + 3 files changed, 63 insertions(+), 25 deletions(-) + +diff --git a/arch/x86/kernel/crash_dump_64.c b/arch/x86/kernel/crash_dump_64.c +index 4f2e0778feac..eb8ab3915268 100644 +--- a/arch/x86/kernel/crash_dump_64.c ++++ b/arch/x86/kernel/crash_dump_64.c +@@ -11,40 +11,62 @@ + #include + #include + +-/** +- * copy_oldmem_page - copy one page from "oldmem" +- * @pfn: page frame number to be copied +- * @buf: target memory address for the copy; this can be in kernel address +- * space or user address space (see @userbuf) +- * @csize: number of bytes to copy +- * @offset: offset in bytes into the page (based on pfn) to begin the copy +- * @userbuf: if set, @buf is in user address space, use copy_to_user(), +- * otherwise @buf is in kernel address space, use memcpy(). +- * +- * Copy a page from "oldmem". For this page, there is no pte mapped +- * in the current kernel. We stitch up a pte, similar to kmap_atomic. +- */ +-ssize_t copy_oldmem_page(unsigned long pfn, char *buf, +- size_t csize, unsigned long offset, int userbuf) ++static ssize_t __copy_oldmem_page(unsigned long pfn, char *buf, size_t csize, ++ unsigned long offset, int userbuf, ++ bool encrypted) + { + void *vaddr; + + if (!csize) + return 0; + +- vaddr = ioremap_cache(pfn << PAGE_SHIFT, PAGE_SIZE); ++ if (encrypted) ++ vaddr = (__force void *)ioremap_encrypted(pfn << PAGE_SHIFT, PAGE_SIZE); ++ else ++ vaddr = (__force void *)ioremap_cache(pfn << PAGE_SHIFT, PAGE_SIZE); ++ + if (!vaddr) + return -ENOMEM; + + if (userbuf) { +- if (copy_to_user(buf, vaddr + offset, csize)) { +- iounmap(vaddr); ++ if (copy_to_user((void __user *)buf, vaddr + offset, csize)) { ++ iounmap((void __iomem *)vaddr); + return -EFAULT; + } + } else + memcpy(buf, vaddr + offset, csize); + + set_iounmap_nonlazy(); +- iounmap(vaddr); ++ iounmap((void __iomem *)vaddr); + return csize; + } ++ ++/** ++ * copy_oldmem_page - copy one page of memory ++ * @pfn: page frame number to be copied ++ * @buf: target memory address for the copy; this can be in kernel address ++ * space or user address space (see @userbuf) ++ * @csize: number of bytes to copy ++ * @offset: offset in bytes into the page (based on pfn) to begin the copy ++ * @userbuf: if set, @buf is in user address space, use copy_to_user(), ++ * otherwise @buf is in kernel address space, use memcpy(). ++ * ++ * Copy a page from the old kernel's memory. For this page, there is no pte ++ * mapped in the current kernel. We stitch up a pte, similar to kmap_atomic. ++ */ ++ssize_t copy_oldmem_page(unsigned long pfn, char *buf, size_t csize, ++ unsigned long offset, int userbuf) ++{ ++ return __copy_oldmem_page(pfn, buf, csize, offset, userbuf, false); ++} ++ ++/** ++ * copy_oldmem_page_encrypted - same as copy_oldmem_page() above but ioremap the ++ * memory with the encryption mask set to accomodate kdump on SME-enabled ++ * machines. ++ */ ++ssize_t copy_oldmem_page_encrypted(unsigned long pfn, char *buf, size_t csize, ++ unsigned long offset, int userbuf) ++{ ++ return __copy_oldmem_page(pfn, buf, csize, offset, userbuf, true); ++} +diff --git a/fs/proc/vmcore.c b/fs/proc/vmcore.c +index cbde728f8ac6..42c32d06f7da 100644 +--- a/fs/proc/vmcore.c ++++ b/fs/proc/vmcore.c +@@ -24,6 +24,8 @@ + #include + #include + #include ++#include ++#include + #include + #include "internal.h" + +@@ -98,7 +100,8 @@ static int pfn_is_ram(unsigned long pfn) + + /* Reads a page from the oldmem device from given offset. */ + static ssize_t read_from_oldmem(char *buf, size_t count, +- u64 *ppos, int userbuf) ++ u64 *ppos, int userbuf, ++ bool encrypted) + { + unsigned long pfn, offset; + size_t nr_bytes; +@@ -120,8 +123,15 @@ static ssize_t read_from_oldmem(char *buf, size_t count, + if (pfn_is_ram(pfn) == 0) + memset(buf, 0, nr_bytes); + else { +- tmp = copy_oldmem_page(pfn, buf, nr_bytes, +- offset, userbuf); ++ if (encrypted) ++ tmp = copy_oldmem_page_encrypted(pfn, buf, ++ nr_bytes, ++ offset, ++ userbuf); ++ else ++ tmp = copy_oldmem_page(pfn, buf, nr_bytes, ++ offset, userbuf); ++ + if (tmp < 0) + return tmp; + } +@@ -155,7 +165,7 @@ void __weak elfcorehdr_free(unsigned long long addr) + */ + ssize_t __weak elfcorehdr_read(char *buf, size_t count, u64 *ppos) + { +- return read_from_oldmem(buf, count, ppos, 0); ++ return read_from_oldmem(buf, count, ppos, 0, false); + } + + /* +@@ -163,7 +173,7 @@ ssize_t __weak elfcorehdr_read(char *buf, size_t count, u64 *ppos) + */ + ssize_t __weak elfcorehdr_read_notes(char *buf, size_t count, u64 *ppos) + { +- return read_from_oldmem(buf, count, ppos, 0); ++ return read_from_oldmem(buf, count, ppos, 0, sme_active()); + } + + /* +@@ -173,6 +183,7 @@ int __weak remap_oldmem_pfn_range(struct vm_area_struct *vma, + unsigned long from, unsigned long pfn, + unsigned long size, pgprot_t prot) + { ++ prot = pgprot_encrypted(prot); + return remap_pfn_range(vma, from, pfn, size, prot); + } + +@@ -351,7 +362,8 @@ static ssize_t __read_vmcore(char *buffer, size_t buflen, loff_t *fpos, + m->offset + m->size - *fpos, + buflen); + start = m->paddr + *fpos - m->offset; +- tmp = read_from_oldmem(buffer, tsz, &start, userbuf); ++ tmp = read_from_oldmem(buffer, tsz, &start, ++ userbuf, sme_active()); + if (tmp < 0) + return tmp; + buflen -= tsz; +diff --git a/include/linux/crash_dump.h b/include/linux/crash_dump.h +index 3e4ba9d753c8..f774c5eb9e3c 100644 +--- a/include/linux/crash_dump.h ++++ b/include/linux/crash_dump.h +@@ -26,6 +26,10 @@ extern int remap_oldmem_pfn_range(struct vm_area_struct *vma, + + extern ssize_t copy_oldmem_page(unsigned long, char *, size_t, + unsigned long, int); ++extern ssize_t copy_oldmem_page_encrypted(unsigned long pfn, char *buf, ++ size_t csize, unsigned long offset, ++ int userbuf); ++ + void vmcore_cleanup(void); + + /* Architecture code defines this if there are other possible ELF +-- +2.16.4 + diff --git a/patches.suse/kexec-allocate-decrypted-control-pages-for-kdump-if.patch b/patches.suse/kexec-allocate-decrypted-control-pages-for-kdump-if.patch new file mode 100644 index 0000000..44e02df --- /dev/null +++ b/patches.suse/kexec-allocate-decrypted-control-pages-for-kdump-if.patch @@ -0,0 +1,70 @@ +From 9cf38d5559e813cccdba8b44c82cc46ba48d0896 Mon Sep 17 00:00:00 2001 +From: Lianbo Jiang +Date: Sun, 30 Sep 2018 11:10:31 +0800 +Subject: [PATCH] kexec: Allocate decrypted control pages for kdump if SME is + enabled +References: bsc#1141895 +Git-commit: 9cf38d5559e813cccdba8b44c82cc46ba48d0896 +Patch-mainline: v4.20-rc1 + +When SME is enabled in the first kernel, it needs to allocate decrypted +pages for kdump because when the kdump kernel boots, these pages need to +be accessed decrypted in the initial boot stage, before SME is enabled. + + [ bp: clean up text. ] + +Signed-off-by: Lianbo Jiang +Signed-off-by: Borislav Petkov +Reviewed-by: Tom Lendacky +Cc: kexec@lists.infradead.org +Cc: tglx@linutronix.de +Cc: mingo@redhat.com +Cc: hpa@zytor.com +Cc: akpm@linux-foundation.org +Cc: dan.j.williams@intel.com +Cc: bhelgaas@google.com +Cc: baiyaowei@cmss.chinamobile.com +Cc: tiwai@suse.de +Cc: brijesh.singh@amd.com +Cc: dyoung@redhat.com +Cc: bhe@redhat.com +Cc: jroedel@suse.de +Link: https://lkml.kernel.org/r/20180930031033.22110-3-lijiang@redhat.com +--- + kernel/kexec_core.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/kernel/kexec_core.c b/kernel/kexec_core.c +index 23a83a4da38a..86ef06d3dbe3 100644 +--- a/kernel/kexec_core.c ++++ b/kernel/kexec_core.c +@@ -471,6 +471,10 @@ static struct page *kimage_alloc_crash_control_pages(struct kimage *image, + } + } + ++ /* Ensure that these pages are decrypted if SME is enabled. */ ++ if (pages) ++ arch_kexec_post_alloc_pages(page_address(pages), 1 << order, 0); ++ + return pages; + } + +@@ -867,6 +871,7 @@ static int kimage_load_crash_segment(struct kimage *image, + result = -ENOMEM; + goto out; + } ++ arch_kexec_post_alloc_pages(page_address(page), 1, 0); + ptr = kmap(page); + ptr += maddr & ~PAGE_MASK; + mchunk = min_t(size_t, mbytes, +@@ -884,6 +889,7 @@ static int kimage_load_crash_segment(struct kimage *image, + result = copy_from_user(ptr, buf, uchunk); + kexec_flush_icache_page(page); + kunmap(page); ++ arch_kexec_pre_free_pages(page_address(page), 1); + if (result) { + result = -EFAULT; + goto out; +-- +2.16.4 + diff --git a/patches.suse/kvm-vmx-check-descriptor-table-exits-on-instruction-emulation b/patches.suse/kvm-vmx-check-descriptor-table-exits-on-instruction-emulation new file mode 100644 index 0000000..0db3f06 --- /dev/null +++ b/patches.suse/kvm-vmx-check-descriptor-table-exits-on-instruction-emulation @@ -0,0 +1,68 @@ +From: Oliver Upton +Date: Sat, 29 Feb 2020 11:30:14 -0800 +Subject: KVM: VMX: check descriptor table exits on instruction emulation +Git-commit: 86f7e90ce840aa1db407d3ea6e9b3a52b2ce923c +Patch-mainline: v5.6-rc4 +References: bsc#1166104 + +KVM emulates UMIP on hardware that doesn't support it by setting the +'descriptor table exiting' VM-execution control and performing +instruction emulation. When running nested, this emulation is broken as +KVM refuses to emulate L2 instructions by default. + +Correct this regression by allowing the emulation of descriptor table +instructions if L1 hasn't requested 'descriptor table exiting'. + +Fixes: 07721feee46b ("KVM: nVMX: Don't emulate instructions in guest mode") +Reported-by: Jan Kiszka +Cc: stable@vger.kernel.org +Cc: Paolo Bonzini +Cc: Jim Mattson +Signed-off-by: Oliver Upton +Signed-off-by: Paolo Bonzini +Acked-by: Joerg Roedel +--- + arch/x86/kvm/vmx/vmx.c | 15 +++++++++++++++ + 1 file changed, 15 insertions(+) + +--- a/arch/x86/kvm/vmx.c ++++ b/arch/x86/kvm/vmx.c +@@ -12416,6 +12416,7 @@ static int vmx_check_intercept_io(struct + else + intercept = nested_vmx_check_io_bitmaps(vcpu, port, size); + ++ /* FIXME: produce nested vmexit and return X86EMUL_INTERCEPTED. */ + return intercept ? X86EMUL_UNHANDLEABLE : X86EMUL_CONTINUE; + } + +@@ -12423,6 +12424,8 @@ static int vmx_check_intercept(struct kv + struct x86_instruction_info *info, + enum x86_intercept_stage stage) + { ++ struct vmcs12 *vmcs12 = get_vmcs12(vcpu); ++ + switch (info->intercept) { + case x86_intercept_in: + case x86_intercept_ins: +@@ -12430,6 +12433,20 @@ static int vmx_check_intercept(struct kv + case x86_intercept_outs: + return vmx_check_intercept_io(vcpu, info); + ++ case x86_intercept_lgdt: ++ case x86_intercept_lidt: ++ case x86_intercept_lldt: ++ case x86_intercept_ltr: ++ case x86_intercept_sgdt: ++ case x86_intercept_sidt: ++ case x86_intercept_sldt: ++ case x86_intercept_str: ++ if (!nested_cpu_has2(vmcs12, SECONDARY_EXEC_DESC)) ++ return X86EMUL_CONTINUE; ++ ++ /* FIXME: produce nested vmexit and return X86EMUL_INTERCEPTED. */ ++ break; ++ + /* TODO: check more intercepts... */ + default: + break; + diff --git a/patches.suse/l2tp-Allow-duplicate-session-creation-with-UDP.patch b/patches.suse/l2tp-Allow-duplicate-session-creation-with-UDP.patch new file mode 100644 index 0000000..33f2522 --- /dev/null +++ b/patches.suse/l2tp-Allow-duplicate-session-creation-with-UDP.patch @@ -0,0 +1,45 @@ +From: Ridge Kennedy +Date: Tue, 4 Feb 2020 12:24:00 +1300 +Subject: l2tp: Allow duplicate session creation with UDP +Git-commit: 0d0d9a388a858e271bb70e71e99e7fe2a6fd6f64 +Patch-mainline: 5.6-rc1 +References: networking-stable-20_02_05 + +In the past it was possible to create multiple L2TPv3 sessions with the +same session id as long as the sessions belonged to different tunnels. +The resulting sessions had issues when used with IP encapsulated tunnels, +but worked fine with UDP encapsulated ones. Some applications began to +rely on this behaviour to avoid having to negotiate unique session ids. + +Some time ago a change was made to require session ids to be unique across +all tunnels, breaking the applications making use of this "feature". + +This change relaxes the duplicate session id check to allow duplicates +if both of the colliding sessions belong to UDP encapsulated tunnels. + +Fixes: dbdbc73b4478 ("l2tp: fix duplicate session creation") +Signed-off-by: Ridge Kennedy +Acked-by: James Chapman +Signed-off-by: David S. Miller +Signed-off-by: Jiri Slaby +--- + net/l2tp/l2tp_core.c | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +--- a/net/l2tp/l2tp_core.c ++++ b/net/l2tp/l2tp_core.c +@@ -299,8 +299,13 @@ int l2tp_session_register(struct l2tp_se + + spin_lock_bh(&pn->l2tp_session_hlist_lock); + ++ /* IP encap expects session IDs to be globally unique, while ++ * UDP encap doesn't. ++ */ + hlist_for_each_entry(session_walk, g_head, global_hlist) +- if (session_walk->session_id == session->session_id) { ++ if (session_walk->session_id == session->session_id && ++ (session_walk->tunnel->encap == L2TP_ENCAPTYPE_IP || ++ tunnel->encap == L2TP_ENCAPTYPE_IP)) { + err = -EEXIST; + goto err_tlock_pnlock; + } diff --git a/patches.suse/libceph-add-scatterlist-messenger-data-type.patch b/patches.suse/libceph-add-scatterlist-messenger-data-type.patch index bf66ce2..ed4b678 100644 --- a/patches.suse/libceph-add-scatterlist-messenger-data-type.patch +++ b/patches.suse/libceph-add-scatterlist-messenger-data-type.patch @@ -34,8 +34,8 @@ Acked-by: Luis Henriques }; #ifdef CONFIG_BLOCK -@@ -179,6 +180,11 @@ struct ceph_msg_data { - unsigned int alignment; /* first page */ +@@ -180,6 +181,11 @@ struct ceph_msg_data { + bool own_pages; }; struct ceph_pagelist *pagelist; + struct { @@ -46,7 +46,7 @@ Acked-by: Luis Henriques }; }; -@@ -203,6 +209,10 @@ struct ceph_msg_data_cursor { +@@ -204,6 +210,10 @@ struct ceph_msg_data_cursor { struct page *page; /* page from list */ size_t offset; /* bytes from list */ }; @@ -57,7 +57,7 @@ Acked-by: Luis Henriques }; }; -@@ -363,6 +373,8 @@ void ceph_msg_data_add_bio(struct ceph_m +@@ -365,6 +375,8 @@ void ceph_msg_data_add_bio(struct ceph_m #endif /* CONFIG_BLOCK */ void ceph_msg_data_add_bvecs(struct ceph_msg *msg, struct ceph_bvec_iter *bvec_pos); @@ -103,7 +103,7 @@ Acked-by: Luis Henriques struct ceph_pagelist *pagelist); --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c -@@ -920,6 +920,75 @@ static bool ceph_msg_data_bvecs_advance( +@@ -922,6 +922,75 @@ static bool ceph_msg_data_bvecs_advance( } /* @@ -179,7 +179,7 @@ Acked-by: Luis Henriques * For a page array, a piece comes from the first page in the array * that has not already been fully consumed. */ -@@ -1105,6 +1174,9 @@ static void __ceph_msg_data_cursor_init( +@@ -1107,6 +1176,9 @@ static void __ceph_msg_data_cursor_init( case CEPH_MSG_DATA_BVECS: ceph_msg_data_bvecs_cursor_init(cursor, length); break; @@ -189,7 +189,7 @@ Acked-by: Luis Henriques case CEPH_MSG_DATA_NONE: default: /* BUG(); */ -@@ -1153,6 +1225,9 @@ static struct page *ceph_msg_data_next(s +@@ -1155,6 +1227,9 @@ static struct page *ceph_msg_data_next(s case CEPH_MSG_DATA_BVECS: page = ceph_msg_data_bvecs_next(cursor, page_offset, length); break; @@ -199,7 +199,7 @@ Acked-by: Luis Henriques case CEPH_MSG_DATA_NONE: default: page = NULL; -@@ -1194,6 +1269,9 @@ static void ceph_msg_data_advance(struct +@@ -1196,6 +1271,9 @@ static void ceph_msg_data_advance(struct case CEPH_MSG_DATA_BVECS: new_piece = ceph_msg_data_bvecs_advance(cursor, bytes); break; @@ -209,7 +209,7 @@ Acked-by: Luis Henriques case CEPH_MSG_DATA_NONE: default: BUG(); -@@ -3307,6 +3385,23 @@ void ceph_msg_data_add_bvecs(struct ceph +@@ -3311,6 +3389,23 @@ void ceph_msg_data_add_bvecs(struct ceph } EXPORT_SYMBOL(ceph_msg_data_add_bvecs); diff --git a/patches.suse/libnvdimm-dimm-maximize-label-transfer-size.patch b/patches.suse/libnvdimm-dimm-maximize-label-transfer-size.patch index e1194a8..ca0c25d 100644 --- a/patches.suse/libnvdimm-dimm-maximize-label-transfer-size.patch +++ b/patches.suse/libnvdimm-dimm-maximize-label-transfer-size.patch @@ -1,9 +1,11 @@ +From d11cf4a7321b538563b0ab30dc0d1f18f9c56226 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Wed, 10 Oct 2018 16:38:24 -0700 -Subject: libnvdimm, dimm: Maximize label transfer size -Git-commit: d11cf4a7321b538563b0ab30dc0d1f18f9c56226 -Patch-mainline: v4.20-rc1 +Subject: [PATCH] libnvdimm, dimm: Maximize label transfer size + References: bsc#1111921, bsc#1113408, FATE#326765, bsc#1113972 +Patch-mainline: v4.20-rc1 +Git-commit: d11cf4a7321b538563b0ab30dc0d1f18f9c56226 Use kvzalloc() to bypass the arbitrary PAGE_SIZE limit of label transfer operations. Given the expense of calling into firmware, maximize the @@ -23,12 +25,14 @@ Signed-off-by: Alexander Duyck Signed-off-by: Dan Williams Acked-by: Johannes Thumshirn --- - drivers/nvdimm/dimm_devs.c | 13 ++++++------- + drivers/nvdimm/dimm_devs.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) +diff --git a/drivers/nvdimm/dimm_devs.c b/drivers/nvdimm/dimm_devs.c +index 863cabc35215..75ac78017b15 100644 --- a/drivers/nvdimm/dimm_devs.c +++ b/drivers/nvdimm/dimm_devs.c -@@ -110,8 +110,8 @@ int nvdimm_init_config_data(struct nvdim +@@ -111,8 +111,8 @@ int nvdimm_init_config_data(struct nvdimm_drvdata *ndd) if (!ndd->data) return -ENOMEM; @@ -39,16 +43,16 @@ Acked-by: Johannes Thumshirn if (!cmd) return -ENOMEM; -@@ -133,7 +133,7 @@ int nvdimm_init_config_data(struct nvdim +@@ -134,7 +134,7 @@ int nvdimm_init_config_data(struct nvdimm_drvdata *ndd) memcpy(ndd->data + offset, cmd->out_buf, cmd->in_length); } - dev_dbg(ndd->dev, "%s: len: %zu rc: %d\n", __func__, offset, rc); + dev_dbg(ndd->dev, "len: %zu rc: %d\n", offset, rc); - kfree(cmd); + kvfree(cmd); return rc; } -@@ -156,9 +156,8 @@ int nvdimm_set_config_data(struct nvdimm +@@ -157,9 +157,8 @@ int nvdimm_set_config_data(struct nvdimm_drvdata *ndd, size_t offset, if (offset + len > ndd->nsarea.config_size) return -ENXIO; @@ -60,7 +64,7 @@ Acked-by: Johannes Thumshirn if (!cmd) return -ENOMEM; -@@ -182,7 +181,7 @@ int nvdimm_set_config_data(struct nvdimm +@@ -183,7 +182,7 @@ int nvdimm_set_config_data(struct nvdimm_drvdata *ndd, size_t offset, break; } } @@ -69,3 +73,6 @@ Acked-by: Johannes Thumshirn return rc; } +-- +2.23.0 + diff --git a/patches.suse/libnvdimm-namespace-fix-label-tracking-error.patch b/patches.suse/libnvdimm-namespace-fix-label-tracking-error.patch index dbe756d..3142498 100644 --- a/patches.suse/libnvdimm-namespace-fix-label-tracking-error.patch +++ b/patches.suse/libnvdimm-namespace-fix-label-tracking-error.patch @@ -1,9 +1,11 @@ +From c4703ce11c23423d4b46e3d59aef7979814fd608 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Tue, 30 Apr 2019 21:51:21 -0700 -Subject: libnvdimm/namespace: Fix label tracking error +Subject: [PATCH] libnvdimm/namespace: Fix label tracking error + +References: bsc#1142350 Patch-mainline: v5.2-rc1 Git-commit: c4703ce11c23423d4b46e3d59aef7979814fd608 -References: bsc#1142350 Users have reported intermittent occurrences of DIMM initialization failures due to duplicate allocations of address capacity detected in @@ -49,14 +51,16 @@ Cc: Johannes Thumshirn Signed-off-by: Dan Williams Acked-by: Johannes Thumshirn --- - drivers/nvdimm/label.c | 29 ++++++++++++++++------------- - drivers/nvdimm/namespace_devs.c | 15 +++++++++++++++ - drivers/nvdimm/nd.h | 4 ++++ + drivers/nvdimm/label.c | 29 ++++++++++++++++------------- + drivers/nvdimm/namespace_devs.c | 15 +++++++++++++++ + drivers/nvdimm/nd.h | 4 ++++ 3 files changed, 35 insertions(+), 13 deletions(-) +diff --git a/drivers/nvdimm/label.c b/drivers/nvdimm/label.c +index f3d753d3169c..2030805aa216 100644 --- a/drivers/nvdimm/label.c +++ b/drivers/nvdimm/label.c -@@ -758,6 +758,17 @@ static const guid_t *to_abstraction_guid +@@ -756,6 +756,17 @@ static const guid_t *to_abstraction_guid(enum nvdimm_claim_class claim_class, return &guid_null; } @@ -74,7 +78,7 @@ Acked-by: Johannes Thumshirn static int __pmem_label_update(struct nd_region *nd_region, struct nd_mapping *nd_mapping, struct nd_namespace_pmem *nspm, int pos, unsigned long flags) -@@ -765,9 +776,9 @@ static int __pmem_label_update(struct nd +@@ -763,9 +774,9 @@ static int __pmem_label_update(struct nd_region *nd_region, struct nd_namespace_common *ndns = &nspm->nsio.common; struct nd_interleave_set *nd_set = nd_region->nd_set; struct nvdimm_drvdata *ndd = to_ndd(nd_mapping); @@ -85,7 +89,7 @@ Acked-by: Johannes Thumshirn struct nd_label_id label_id; struct resource *res; unsigned long *free; -@@ -836,18 +847,10 @@ static int __pmem_label_update(struct nd +@@ -834,18 +845,10 @@ static int __pmem_label_update(struct nd_region *nd_region, list_for_each_entry(label_ent, &nd_mapping->labels, list) { if (!label_ent->label) continue; @@ -97,7 +101,7 @@ Acked-by: Johannes Thumshirn - break; - } - if (victim) { -- dev_dbg(ndd->dev, "%s: free: %d\n", __func__, slot); +- dev_dbg(ndd->dev, "free: %d\n", slot); - slot = to_slot(ndd, victim->label); - nd_label_free_slot(ndd, slot); - victim->label = NULL; @@ -108,9 +112,11 @@ Acked-by: Johannes Thumshirn } /* update index */ +diff --git a/drivers/nvdimm/namespace_devs.c b/drivers/nvdimm/namespace_devs.c +index f293556cbbf6..d0214644e334 100644 --- a/drivers/nvdimm/namespace_devs.c +++ b/drivers/nvdimm/namespace_devs.c -@@ -1233,12 +1233,27 @@ static int namespace_update_uuid(struct +@@ -1247,12 +1247,27 @@ static int namespace_update_uuid(struct nd_region *nd_region, for (i = 0; i < nd_region->ndr_mappings; i++) { struct nd_mapping *nd_mapping = &nd_region->mapping[i]; struct nvdimm_drvdata *ndd = to_ndd(nd_mapping); @@ -138,9 +144,11 @@ Acked-by: Johannes Thumshirn } kfree(*old_uuid); out: +diff --git a/drivers/nvdimm/nd.h b/drivers/nvdimm/nd.h +index a5ac3b240293..191d62af0e51 100644 --- a/drivers/nvdimm/nd.h +++ b/drivers/nvdimm/nd.h -@@ -120,8 +120,12 @@ struct nd_percpu_lane { +@@ -113,8 +113,12 @@ struct nd_percpu_lane { spinlock_t lock; }; @@ -153,4 +161,6 @@ Acked-by: Johannes Thumshirn struct nd_namespace_label *label; }; +-- +2.23.0 diff --git a/patches.suse/libnvdimm-pfn-fix-fsdax-mode-namespace-info-block-ze.patch b/patches.suse/libnvdimm-pfn-fix-fsdax-mode-namespace-info-block-ze.patch new file mode 100644 index 0000000..2e642ac --- /dev/null +++ b/patches.suse/libnvdimm-pfn-fix-fsdax-mode-namespace-info-block-ze.patch @@ -0,0 +1,155 @@ +From 7e3e888dfc138089f4c15a81b418e88f0978f744 Mon Sep 17 00:00:00 2001 +From: Dan Williams +Date: Thu, 18 Jul 2019 15:58:36 -0700 +Subject: [PATCH] libnvdimm/pfn: fix fsdax-mode namespace info-block + zero-fields +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +References: bsc#1165929 +Patch-mainline: v5.3-rc1 +Git-commit: 7e3e888dfc138089f4c15a81b418e88f0978f744 + +At namespace creation time there is the potential for the "expected to +be zero" fields of a 'pfn' info-block to be filled with indeterminate +data. While the kernel buffer is zeroed on allocation it is immediately +overwritten by nd_pfn_validate() filling it with the current contents of +the on-media info-block location. For fields like, 'flags' and the +'padding' it potentially means that future implementations can not rely on +those fields being zero. + +In preparation to stop using the 'start_pad' and 'end_trunc' fields for +section alignment, arrange for fields that are not explicitly +initialized to be guaranteed zero. Bump the minor version to indicate +it is safe to assume the 'padding' and 'flags' are zero. Otherwise, +this corruption is expected to benign since all other critical fields +are explicitly initialized. + +Note The cc: stable is about spreading this new policy to as many +kernels as possible not fixing an issue in those kernels. It is not +until the change titled "libnvdimm/pfn: Stop padding pmem namespaces to +section alignment" where this improper initialization becomes a problem. +So if someone decides to backport "libnvdimm/pfn: Stop padding pmem +namespaces to section alignment" (which is not tagged for stable), make +sure this pre-requisite is flagged. + +Link: http://lkml.kernel.org/r/156092356065.979959.6681003754765958296.stgit@dwillia2-desk3.amr.corp.intel.com +Fixes: 32ab0a3f5170 ("libnvdimm, pmem: 'struct page' for pmem") +Signed-off-by: Dan Williams +Tested-by: Aneesh Kumar K.V [ppc64] +Cc: +Cc: David Hildenbrand +Cc: Jane Chu +Cc: Jeff Moyer +Cc: Jérôme Glisse +Cc: Jonathan Corbet +Cc: Logan Gunthorpe +Cc: Michal Hocko +Cc: Mike Rapoport +Cc: Oscar Salvador +Cc: Pavel Tatashin +Cc: Toshi Kani +Cc: Vlastimil Babka +Cc: Wei Yang +Cc: Jason Gunthorpe +Cc: Christoph Hellwig +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +Acked-by: Michal Suchanek +--- + drivers/nvdimm/dax_devs.c | 2 +- + drivers/nvdimm/pfn.h | 1 + + drivers/nvdimm/pfn_devs.c | 18 +++++++++++++++--- + 3 files changed, 17 insertions(+), 4 deletions(-) + +diff --git a/drivers/nvdimm/dax_devs.c b/drivers/nvdimm/dax_devs.c +index 49fc18ee0565..6d22b0f83b3b 100644 +--- a/drivers/nvdimm/dax_devs.c ++++ b/drivers/nvdimm/dax_devs.c +@@ -118,7 +118,7 @@ int nd_dax_probe(struct device *dev, struct nd_namespace_common *ndns) + nvdimm_bus_unlock(&ndns->dev); + if (!dax_dev) + return -ENOMEM; +- pfn_sb = devm_kzalloc(dev, sizeof(*pfn_sb), GFP_KERNEL); ++ pfn_sb = devm_kmalloc(dev, sizeof(*pfn_sb), GFP_KERNEL); + nd_pfn->pfn_sb = pfn_sb; + rc = nd_pfn_validate(nd_pfn, DAX_SIG); + dev_dbg(dev, "dax: %s\n", rc == 0 ? dev_name(dax_dev) : ""); +diff --git a/drivers/nvdimm/pfn.h b/drivers/nvdimm/pfn.h +index f58b849e455b..dfb2bcda8f5a 100644 +--- a/drivers/nvdimm/pfn.h ++++ b/drivers/nvdimm/pfn.h +@@ -28,6 +28,7 @@ struct nd_pfn_sb { + __le32 end_trunc; + /* minor-version-2 record the base alignment of the mapping */ + __le32 align; ++ /* minor-version-3 guarantee the padding and flags are zero */ + u8 padding[4000]; + __le64 checksum; + }; +diff --git a/drivers/nvdimm/pfn_devs.c b/drivers/nvdimm/pfn_devs.c +index 55fb6b7433ed..06f465c0baf3 100644 +--- a/drivers/nvdimm/pfn_devs.c ++++ b/drivers/nvdimm/pfn_devs.c +@@ -412,6 +412,15 @@ static int nd_pfn_clear_memmap_errors(struct nd_pfn *nd_pfn) + return 0; + } + ++/** ++ * nd_pfn_validate - read and validate info-block ++ * @nd_pfn: fsdax namespace runtime state / properties ++ * @sig: 'devdax' or 'fsdax' signature ++ * ++ * Upon return the info-block buffer contents (->pfn_sb) are ++ * indeterminate when validation fails, and a coherent info-block ++ * otherwise. ++ */ + int nd_pfn_validate(struct nd_pfn *nd_pfn, const char *sig) + { + u64 checksum, offset; +@@ -557,7 +566,7 @@ int nd_pfn_probe(struct device *dev, struct nd_namespace_common *ndns) + nvdimm_bus_unlock(&ndns->dev); + if (!pfn_dev) + return -ENOMEM; +- pfn_sb = devm_kzalloc(dev, sizeof(*pfn_sb), GFP_KERNEL); ++ pfn_sb = devm_kmalloc(dev, sizeof(*pfn_sb), GFP_KERNEL); + nd_pfn = to_nd_pfn(pfn_dev); + nd_pfn->pfn_sb = pfn_sb; + rc = nd_pfn_validate(nd_pfn, PFN_SIG); +@@ -693,7 +702,7 @@ static int nd_pfn_init(struct nd_pfn *nd_pfn) + u64 checksum; + int rc; + +- pfn_sb = devm_kzalloc(&nd_pfn->dev, sizeof(*pfn_sb), GFP_KERNEL); ++ pfn_sb = devm_kmalloc(&nd_pfn->dev, sizeof(*pfn_sb), GFP_KERNEL); + if (!pfn_sb) + return -ENOMEM; + +@@ -702,11 +711,14 @@ static int nd_pfn_init(struct nd_pfn *nd_pfn) + sig = DAX_SIG; + else + sig = PFN_SIG; ++ + rc = nd_pfn_validate(nd_pfn, sig); + if (rc != -ENODEV) + return rc; + + /* no info block, do init */; ++ memset(pfn_sb, 0, sizeof(*pfn_sb)); ++ + nd_region = to_nd_region(nd_pfn->dev.parent); + if (nd_region->ro) { + dev_info(&nd_pfn->dev, +@@ -759,7 +771,7 @@ static int nd_pfn_init(struct nd_pfn *nd_pfn) + memcpy(pfn_sb->uuid, nd_pfn->uuid, 16); + memcpy(pfn_sb->parent_uuid, nd_dev_to_uuid(&ndns->dev), 16); + pfn_sb->version_major = cpu_to_le16(1); +- pfn_sb->version_minor = cpu_to_le16(2); ++ pfn_sb->version_minor = cpu_to_le16(3); + pfn_sb->start_pad = cpu_to_le32(start_pad); + pfn_sb->end_trunc = cpu_to_le32(end_trunc); + pfn_sb->align = cpu_to_le32(nd_pfn->align); +-- +2.23.0 + diff --git a/patches.suse/libnvdimm-pfn_dev-Don-t-clear-device-memmap-area-dur.patch b/patches.suse/libnvdimm-pfn_dev-Don-t-clear-device-memmap-area-dur.patch new file mode 100644 index 0000000..af8c8bd --- /dev/null +++ b/patches.suse/libnvdimm-pfn_dev-Don-t-clear-device-memmap-area-dur.patch @@ -0,0 +1,63 @@ +From c1f45d86a522d568aef541dbbc066ccac262b4c3 Mon Sep 17 00:00:00 2001 +From: "Aneesh Kumar K.V" +Date: Fri, 1 Nov 2019 08:57:28 +0530 +Subject: [PATCH] libnvdimm/pfn_dev: Don't clear device memmap area during + generic namespace probe + +References: bsc#1165929 bsc#1165950 +Patch-mainline: v5.5-rc1 +Git-commit: c1f45d86a522d568aef541dbbc066ccac262b4c3 + +nvdimm core use nd_pfn_validate when looking for devdax or fsdax namespace. In this +case device resources are allocated against nd_namespace_io dev. In-order to +allow remap of range in nd_pfn_clear_memmap_error(), move the device memmap +area clearing while initializing pfn namespace. With this device +resource are allocated against nd_pfn and we can use nd_pfn->dev for remapping. + +This also avoids calling nd_pfn_clear_mmap_errors twice. Once while probing the +namespace and second while initializing a pfn namespace. + +Signed-off-by: Aneesh Kumar K.V +Link: https://lore.kernel.org/r/20191101032728.113001-1-aneesh.kumar@linux.ibm.com +Signed-off-by: Dan Williams +Acked-by: Michal Suchanek +--- + drivers/nvdimm/pfn_devs.c | 8 +++++++- + 1 file changed, 7 insertions(+), 1 deletion(-) + +diff --git a/drivers/nvdimm/pfn_devs.c b/drivers/nvdimm/pfn_devs.c +index 60d81fae06ee..96727fd493f7 100644 +--- a/drivers/nvdimm/pfn_devs.c ++++ b/drivers/nvdimm/pfn_devs.c +@@ -591,7 +591,7 @@ int nd_pfn_validate(struct nd_pfn *nd_pfn, const char *sig) + return -ENXIO; + } + +- return nd_pfn_clear_memmap_errors(nd_pfn); ++ return 0; + } + EXPORT_SYMBOL(nd_pfn_validate); + +@@ -729,6 +729,8 @@ static int nd_pfn_init(struct nd_pfn *nd_pfn) + sig = PFN_SIG; + + rc = nd_pfn_validate(nd_pfn, sig); ++ if (rc == 0) ++ return nd_pfn_clear_memmap_errors(nd_pfn); + if (rc != -ENODEV) + return rc; + +@@ -796,6 +798,10 @@ static int nd_pfn_init(struct nd_pfn *nd_pfn) + checksum = nd_sb_checksum((struct nd_gen_sb *) pfn_sb); + pfn_sb->checksum = cpu_to_le64(checksum); + ++ rc = nd_pfn_clear_memmap_errors(nd_pfn); ++ if (rc) ++ return rc; ++ + return nvdimm_write_bytes(ndns, SZ_4K, pfn_sb, sizeof(*pfn_sb), 0); + } + +-- +2.23.0 + diff --git a/patches.suse/libnvdimm-pmem-Restore-page-attributes-when-clearing.patch b/patches.suse/libnvdimm-pmem-Restore-page-attributes-when-clearing.patch index 2f3c149..a368129 100644 --- a/patches.suse/libnvdimm-pmem-Restore-page-attributes-when-clearing.patch +++ b/patches.suse/libnvdimm-pmem-Restore-page-attributes-when-clearing.patch @@ -2,9 +2,10 @@ From c953cc987ab87d180e1d5de2f1c217abe33aac77 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Fri, 13 Jul 2018 21:50:37 -0700 Subject: [PATCH] libnvdimm, pmem: Restore page attributes when clearing errors -Git-commit: c953cc987ab87d180e1d5de2f1c217abe33aac77 -Patch-mainline: v4.19-rc1 + References: bsc#1107783 +Patch-mainline: v4.19-rc1 +Git-commit: c953cc987ab87d180e1d5de2f1c217abe33aac77 Use clear_mce_nospec() to restore WB mode for the kernel linear mapping of a pmem page that was marked 'HWPoison'. A page with 'HWPoison' set @@ -16,12 +17,13 @@ The 'HWPoison' flag is only cleared when overwriting an entire page. Signed-off-by: Dan Williams Signed-off-by: Dave Jiang Acked-by: Jan Kara - --- - drivers/nvdimm/pmem.c | 26 ++++++++++++++++++++++++++ - drivers/nvdimm/pmem.h | 13 +++++++++++++ + drivers/nvdimm/pmem.c | 26 ++++++++++++++++++++++++++ + drivers/nvdimm/pmem.h | 13 +++++++++++++ 2 files changed, 39 insertions(+) +diff --git a/drivers/nvdimm/pmem.c b/drivers/nvdimm/pmem.c +index 8b1fd7f1a224..55c7a69751d3 100644 --- a/drivers/nvdimm/pmem.c +++ b/drivers/nvdimm/pmem.c @@ -20,6 +20,7 @@ @@ -32,7 +34,7 @@ Acked-by: Jan Kara #include #include #include -@@ -51,6 +52,30 @@ static struct nd_region *to_region(struc +@@ -51,6 +52,30 @@ static struct nd_region *to_region(struct pmem_device *pmem) return to_nd_region(to_dev(pmem)->parent); } @@ -63,14 +65,15 @@ Acked-by: Jan Kara static blk_status_t pmem_clear_poison(struct pmem_device *pmem, phys_addr_t offset, unsigned int len) { -@@ -65,6 +90,7 @@ static blk_status_t pmem_clear_poison(st +@@ -65,6 +90,7 @@ static blk_status_t pmem_clear_poison(struct pmem_device *pmem, if (cleared < len) rc = BLK_STS_IOERR; if (cleared > 0 && cleared / 512) { + hwpoison_clear(pmem, pmem->phys_addr + offset, cleared); cleared /= 512; - dev_dbg(dev, "%s: %#llx clear %ld sector%s\n", __func__, + dev_dbg(dev, "%#llx clear %ld sector%s\n", (unsigned long long) sector, cleared, +diff --git a/drivers/nvdimm/pmem.h b/drivers/nvdimm/pmem.h --- a/drivers/nvdimm/pmem.h +++ b/drivers/nvdimm/pmem.h @@ -1,5 +1,6 @@ @@ -80,7 +83,7 @@ Acked-by: Jan Kara #include #include #include -@@ -26,4 +27,16 @@ struct pmem_device { +@@ -27,4 +28,16 @@ struct pmem_device { long __pmem_direct_access(struct pmem_device *pmem, pgoff_t pgoff, long nr_pages, void **kaddr, pfn_t *pfn); @@ -97,3 +100,6 @@ Acked-by: Jan Kara +} +#endif #endif /* __NVDIMM_PMEM_H__ */ +-- +2.23.0 + diff --git a/patches.suse/libnvdimm-remove-redundant-__func__-in-dev_dbg.patch b/patches.suse/libnvdimm-remove-redundant-__func__-in-dev_dbg.patch new file mode 100644 index 0000000..0d49ce7 --- /dev/null +++ b/patches.suse/libnvdimm-remove-redundant-__func__-in-dev_dbg.patch @@ -0,0 +1,615 @@ +From 426824d63b77bde61422ed6e19ac7c62c1f06fca Mon Sep 17 00:00:00 2001 +From: Dan Williams +Date: Mon, 5 Mar 2018 16:39:31 -0800 +Subject: [PATCH] libnvdimm: remove redundant __func__ in dev_dbg + +References: bsc#1165929 +Patch-mainline: v4.17-rc1 +Git-commit: 426824d63b77bde61422ed6e19ac7c62c1f06fca + +Dynamic debug can be instructed to add the function name to the debug +output using the +f switch, so there is no need for the libnvdimm +modules to do it again. If a user decides to add the +f switch for +libnvdimm's dynamic debug this results in double prints of the function +name. + +Reported-by: Johannes Thumshirn +Reported-by: Ross Zwisler +Signed-off-by: Dan Williams +Acked-by: Michal Suchanek +--- + drivers/nvdimm/btt_devs.c | 21 +++++++------- + drivers/nvdimm/bus.c | 13 ++++----- + drivers/nvdimm/claim.c | 2 +- + drivers/nvdimm/core.c | 6 ++-- + drivers/nvdimm/dax_devs.c | 5 ++-- + drivers/nvdimm/dimm_devs.c | 7 ++--- + drivers/nvdimm/label.c | 51 +++++++++++++++------------------ + drivers/nvdimm/namespace_devs.c | 38 +++++++++++------------- + drivers/nvdimm/pfn_devs.c | 25 ++++++++-------- + drivers/nvdimm/pmem.c | 2 +- + 10 files changed, 77 insertions(+), 93 deletions(-) + +diff --git a/drivers/nvdimm/btt_devs.c b/drivers/nvdimm/btt_devs.c +index d58925295aa7..795ad4ff35ca 100644 +--- a/drivers/nvdimm/btt_devs.c ++++ b/drivers/nvdimm/btt_devs.c +@@ -26,7 +26,7 @@ static void nd_btt_release(struct device *dev) + struct nd_region *nd_region = to_nd_region(dev->parent); + struct nd_btt *nd_btt = to_nd_btt(dev); + +- dev_dbg(dev, "%s\n", __func__); ++ dev_dbg(dev, "trace\n"); + nd_detach_ndns(&nd_btt->dev, &nd_btt->ndns); + ida_simple_remove(&nd_region->btt_ida, nd_btt->id); + kfree(nd_btt->uuid); +@@ -74,8 +74,8 @@ static ssize_t sector_size_store(struct device *dev, + nvdimm_bus_lock(dev); + rc = nd_size_select_store(dev, buf, &nd_btt->lbasize, + btt_lbasize_supported); +- dev_dbg(dev, "%s: result: %zd wrote: %s%s", __func__, +- rc, buf, buf[len - 1] == '\n' ? "" : "\n"); ++ dev_dbg(dev, "result: %zd wrote: %s%s", rc, buf, ++ buf[len - 1] == '\n' ? "" : "\n"); + nvdimm_bus_unlock(dev); + device_unlock(dev); + +@@ -101,8 +101,8 @@ static ssize_t uuid_store(struct device *dev, + + device_lock(dev); + rc = nd_uuid_store(dev, &nd_btt->uuid, buf, len); +- dev_dbg(dev, "%s: result: %zd wrote: %s%s", __func__, +- rc, buf, buf[len - 1] == '\n' ? "" : "\n"); ++ dev_dbg(dev, "result: %zd wrote: %s%s", rc, buf, ++ buf[len - 1] == '\n' ? "" : "\n"); + device_unlock(dev); + + return rc ? rc : len; +@@ -131,8 +131,8 @@ static ssize_t namespace_store(struct device *dev, + device_lock(dev); + nvdimm_bus_lock(dev); + rc = nd_namespace_store(dev, &nd_btt->ndns, buf, len); +- dev_dbg(dev, "%s: result: %zd wrote: %s%s", __func__, +- rc, buf, buf[len - 1] == '\n' ? "" : "\n"); ++ dev_dbg(dev, "result: %zd wrote: %s%s", rc, buf, ++ buf[len - 1] == '\n' ? "" : "\n"); + nvdimm_bus_unlock(dev); + device_unlock(dev); + +@@ -206,8 +206,8 @@ static struct device *__nd_btt_create(struct nd_region *nd_region, + dev->groups = nd_btt_attribute_groups; + device_initialize(&nd_btt->dev); + if (ndns && !__nd_attach_ndns(&nd_btt->dev, ndns, &nd_btt->ndns)) { +- dev_dbg(&ndns->dev, "%s failed, already claimed by %s\n", +- __func__, dev_name(ndns->claim)); ++ dev_dbg(&ndns->dev, "failed, already claimed by %s\n", ++ dev_name(ndns->claim)); + put_device(dev); + return NULL; + } +@@ -346,8 +346,7 @@ int nd_btt_probe(struct device *dev, struct nd_namespace_common *ndns) + return -ENOMEM; + btt_sb = devm_kzalloc(dev, sizeof(*btt_sb), GFP_KERNEL); + rc = __nd_btt_probe(to_nd_btt(btt_dev), ndns, btt_sb); +- dev_dbg(dev, "%s: btt: %s\n", __func__, +- rc == 0 ? dev_name(btt_dev) : ""); ++ dev_dbg(dev, "btt: %s\n", rc == 0 ? dev_name(btt_dev) : ""); + if (rc < 0) { + struct nd_btt *nd_btt = to_nd_btt(btt_dev); + +diff --git a/drivers/nvdimm/bus.c b/drivers/nvdimm/bus.c +index 78eabc3a1ab1..0ebc8c4dd0fa 100644 +--- a/drivers/nvdimm/bus.c ++++ b/drivers/nvdimm/bus.c +@@ -984,8 +984,8 @@ static int __nd_ioctl(struct nvdimm_bus *nvdimm_bus, struct nvdimm *nvdimm, + + if (cmd == ND_CMD_CALL) { + func = pkg.nd_command; +- dev_dbg(dev, "%s:%s, idx: %llu, in: %u, out: %u, len %llu\n", +- __func__, dimm_name, pkg.nd_command, ++ dev_dbg(dev, "%s, idx: %llu, in: %u, out: %u, len %llu\n", ++ dimm_name, pkg.nd_command, + in_len, out_len, buf_len); + } + +@@ -996,8 +996,8 @@ static int __nd_ioctl(struct nvdimm_bus *nvdimm_bus, struct nvdimm *nvdimm, + u32 copy; + + if (out_size == UINT_MAX) { +- dev_dbg(dev, "%s:%s unknown output size cmd: %s field: %d\n", +- __func__, dimm_name, cmd_name, i); ++ dev_dbg(dev, "%s unknown output size cmd: %s field: %d\n", ++ dimm_name, cmd_name, i); + return -EFAULT; + } + if (out_len < sizeof(out_env)) +@@ -1012,9 +1012,8 @@ static int __nd_ioctl(struct nvdimm_bus *nvdimm_bus, struct nvdimm *nvdimm, + + buf_len = (u64) out_len + (u64) in_len; + if (buf_len > ND_IOCTL_MAX_BUFLEN) { +- dev_dbg(dev, "%s:%s cmd: %s buf_len: %llu > %d\n", __func__, +- dimm_name, cmd_name, buf_len, +- ND_IOCTL_MAX_BUFLEN); ++ dev_dbg(dev, "%s cmd: %s buf_len: %llu > %d\n", dimm_name, ++ cmd_name, buf_len, ND_IOCTL_MAX_BUFLEN); + return -EINVAL; + } + +diff --git a/drivers/nvdimm/claim.c b/drivers/nvdimm/claim.c +index b2fc29b8279b..30852270484f 100644 +--- a/drivers/nvdimm/claim.c ++++ b/drivers/nvdimm/claim.c +@@ -148,7 +148,7 @@ ssize_t nd_namespace_store(struct device *dev, + char *name; + + if (dev->driver) { +- dev_dbg(dev, "%s: -EBUSY\n", __func__); ++ dev_dbg(dev, "namespace already active\n"); + return -EBUSY; + } + +diff --git a/drivers/nvdimm/core.c b/drivers/nvdimm/core.c +index 1dc527660637..acce050856a8 100644 +--- a/drivers/nvdimm/core.c ++++ b/drivers/nvdimm/core.c +@@ -134,7 +134,7 @@ static void nvdimm_map_release(struct kref *kref) + nvdimm_map = container_of(kref, struct nvdimm_map, kref); + nvdimm_bus = nvdimm_map->nvdimm_bus; + +- dev_dbg(&nvdimm_bus->dev, "%s: %pa\n", __func__, &nvdimm_map->offset); ++ dev_dbg(&nvdimm_bus->dev, "%pa\n", &nvdimm_map->offset); + list_del(&nvdimm_map->list); + if (nvdimm_map->flags) + memunmap(nvdimm_map->mem); +@@ -230,8 +230,8 @@ static int nd_uuid_parse(struct device *dev, u8 *uuid_out, const char *buf, + + for (i = 0; i < 16; i++) { + if (!isxdigit(str[0]) || !isxdigit(str[1])) { +- dev_dbg(dev, "%s: pos: %d buf[%zd]: %c buf[%zd]: %c\n", +- __func__, i, str - buf, str[0], ++ dev_dbg(dev, "pos: %d buf[%zd]: %c buf[%zd]: %c\n", ++ i, str - buf, str[0], + str + 1 - buf, str[1]); + return -EINVAL; + } +diff --git a/drivers/nvdimm/dax_devs.c b/drivers/nvdimm/dax_devs.c +index 1bf2bd318371..0453f49dc708 100644 +--- a/drivers/nvdimm/dax_devs.c ++++ b/drivers/nvdimm/dax_devs.c +@@ -24,7 +24,7 @@ static void nd_dax_release(struct device *dev) + struct nd_dax *nd_dax = to_nd_dax(dev); + struct nd_pfn *nd_pfn = &nd_dax->nd_pfn; + +- dev_dbg(dev, "%s\n", __func__); ++ dev_dbg(dev, "trace\n"); + nd_detach_ndns(dev, &nd_pfn->ndns); + ida_simple_remove(&nd_region->dax_ida, nd_pfn->id); + kfree(nd_pfn->uuid); +@@ -129,8 +129,7 @@ int nd_dax_probe(struct device *dev, struct nd_namespace_common *ndns) + pfn_sb = devm_kzalloc(dev, sizeof(*pfn_sb), GFP_KERNEL); + nd_pfn->pfn_sb = pfn_sb; + rc = nd_pfn_validate(nd_pfn, DAX_SIG); +- dev_dbg(dev, "%s: dax: %s\n", __func__, +- rc == 0 ? dev_name(dax_dev) : ""); ++ dev_dbg(dev, "dax: %s\n", rc == 0 ? dev_name(dax_dev) : ""); + if (rc < 0) { + nd_detach_ndns(dax_dev, &nd_pfn->ndns); + put_device(dax_dev); +diff --git a/drivers/nvdimm/dimm_devs.c b/drivers/nvdimm/dimm_devs.c +index 097794d9f786..e00d45522b80 100644 +--- a/drivers/nvdimm/dimm_devs.c ++++ b/drivers/nvdimm/dimm_devs.c +@@ -131,7 +131,7 @@ int nvdimm_init_config_data(struct nvdimm_drvdata *ndd) + } + memcpy(ndd->data + offset, cmd->out_buf, cmd->in_length); + } +- dev_dbg(ndd->dev, "%s: len: %zu rc: %d\n", __func__, offset, rc); ++ dev_dbg(ndd->dev, "len: %zu rc: %d\n", offset, rc); + kfree(cmd); + + return rc; +@@ -266,8 +266,7 @@ void nvdimm_drvdata_release(struct kref *kref) + struct device *dev = ndd->dev; + struct resource *res, *_r; + +- dev_dbg(dev, "%s\n", __func__); +- ++ dev_dbg(dev, "trace\n"); + nvdimm_bus_lock(dev); + for_each_dpa_resource_safe(ndd, res, _r) + nvdimm_free_dpa(ndd, res); +@@ -660,7 +659,7 @@ int nvdimm_bus_check_dimm_count(struct nvdimm_bus *nvdimm_bus, int dimm_count) + nd_synchronize(); + + device_for_each_child(&nvdimm_bus->dev, &count, count_dimms); +- dev_dbg(&nvdimm_bus->dev, "%s: count: %d\n", __func__, count); ++ dev_dbg(&nvdimm_bus->dev, "count: %d\n", count); + if (count != dimm_count) + return -ENXIO; + return 0; +diff --git a/drivers/nvdimm/label.c b/drivers/nvdimm/label.c +index de66c02f6140..c858cfadea40 100644 +--- a/drivers/nvdimm/label.c ++++ b/drivers/nvdimm/label.c +@@ -121,8 +121,7 @@ static int __nd_label_validate(struct nvdimm_drvdata *ndd) + + memcpy(sig, nsindex[i]->sig, NSINDEX_SIG_LEN); + if (memcmp(sig, NSINDEX_SIGNATURE, NSINDEX_SIG_LEN) != 0) { +- dev_dbg(dev, "%s: nsindex%d signature invalid\n", +- __func__, i); ++ dev_dbg(dev, "nsindex%d signature invalid\n", i); + continue; + } + +@@ -135,8 +134,8 @@ static int __nd_label_validate(struct nvdimm_drvdata *ndd) + labelsize = 128; + + if (labelsize != sizeof_namespace_label(ndd)) { +- dev_dbg(dev, "%s: nsindex%d labelsize %d invalid\n", +- __func__, i, nsindex[i]->labelsize); ++ dev_dbg(dev, "nsindex%d labelsize %d invalid\n", ++ i, nsindex[i]->labelsize); + continue; + } + +@@ -145,30 +144,28 @@ static int __nd_label_validate(struct nvdimm_drvdata *ndd) + sum = nd_fletcher64(nsindex[i], sizeof_namespace_index(ndd), 1); + nsindex[i]->checksum = __cpu_to_le64(sum_save); + if (sum != sum_save) { +- dev_dbg(dev, "%s: nsindex%d checksum invalid\n", +- __func__, i); ++ dev_dbg(dev, "nsindex%d checksum invalid\n", i); + continue; + } + + seq = __le32_to_cpu(nsindex[i]->seq); + if ((seq & NSINDEX_SEQ_MASK) == 0) { +- dev_dbg(dev, "%s: nsindex%d sequence: %#x invalid\n", +- __func__, i, seq); ++ dev_dbg(dev, "nsindex%d sequence: %#x invalid\n", i, seq); + continue; + } + + /* sanity check the index against expected values */ + if (__le64_to_cpu(nsindex[i]->myoff) + != i * sizeof_namespace_index(ndd)) { +- dev_dbg(dev, "%s: nsindex%d myoff: %#llx invalid\n", +- __func__, i, (unsigned long long) ++ dev_dbg(dev, "nsindex%d myoff: %#llx invalid\n", ++ i, (unsigned long long) + __le64_to_cpu(nsindex[i]->myoff)); + continue; + } + if (__le64_to_cpu(nsindex[i]->otheroff) + != (!i) * sizeof_namespace_index(ndd)) { +- dev_dbg(dev, "%s: nsindex%d otheroff: %#llx invalid\n", +- __func__, i, (unsigned long long) ++ dev_dbg(dev, "nsindex%d otheroff: %#llx invalid\n", ++ i, (unsigned long long) + __le64_to_cpu(nsindex[i]->otheroff)); + continue; + } +@@ -176,8 +173,7 @@ static int __nd_label_validate(struct nvdimm_drvdata *ndd) + size = __le64_to_cpu(nsindex[i]->mysize); + if (size > sizeof_namespace_index(ndd) + || size < sizeof(struct nd_namespace_index)) { +- dev_dbg(dev, "%s: nsindex%d mysize: %#llx invalid\n", +- __func__, i, size); ++ dev_dbg(dev, "nsindex%d mysize: %#llx invalid\n", i, size); + continue; + } + +@@ -185,9 +181,8 @@ static int __nd_label_validate(struct nvdimm_drvdata *ndd) + if (nslot * sizeof_namespace_label(ndd) + + 2 * sizeof_namespace_index(ndd) + > ndd->nsarea.config_size) { +- dev_dbg(dev, "%s: nsindex%d nslot: %u invalid, config_size: %#x\n", +- __func__, i, nslot, +- ndd->nsarea.config_size); ++ dev_dbg(dev, "nsindex%d nslot: %u invalid, config_size: %#x\n", ++ i, nslot, ndd->nsarea.config_size); + continue; + } + valid[i] = true; +@@ -356,8 +351,8 @@ static bool slot_valid(struct nvdimm_drvdata *ndd, + sum = nd_fletcher64(nd_label, sizeof_namespace_label(ndd), 1); + nd_label->checksum = __cpu_to_le64(sum_save); + if (sum != sum_save) { +- dev_dbg(ndd->dev, "%s fail checksum. slot: %d expect: %#llx\n", +- __func__, slot, sum); ++ dev_dbg(ndd->dev, "fail checksum. slot: %d expect: %#llx\n", ++ slot, sum); + return false; + } + } +@@ -422,8 +417,8 @@ int nd_label_active_count(struct nvdimm_drvdata *ndd) + u64 dpa = __le64_to_cpu(nd_label->dpa); + + dev_dbg(ndd->dev, +- "%s: slot%d invalid slot: %d dpa: %llx size: %llx\n", +- __func__, slot, label_slot, dpa, size); ++ "slot%d invalid slot: %d dpa: %llx size: %llx\n", ++ slot, label_slot, dpa, size); + continue; + } + count++; +@@ -650,7 +645,7 @@ static int __pmem_label_update(struct nd_region *nd_region, + slot = nd_label_alloc_slot(ndd); + if (slot == UINT_MAX) + return -ENXIO; +- dev_dbg(ndd->dev, "%s: allocated: %d\n", __func__, slot); ++ dev_dbg(ndd->dev, "allocated: %d\n", slot); + + nd_label = to_label(ndd, slot); + memset(nd_label, 0, sizeof_namespace_label(ndd)); +@@ -678,7 +673,7 @@ static int __pmem_label_update(struct nd_region *nd_region, + sum = nd_fletcher64(nd_label, sizeof_namespace_label(ndd), 1); + nd_label->checksum = __cpu_to_le64(sum); + } +- nd_dbg_dpa(nd_region, ndd, res, "%s\n", __func__); ++ nd_dbg_dpa(nd_region, ndd, res, "\n"); + + /* update label */ + offset = nd_label_offset(ndd, nd_label); +@@ -700,7 +695,7 @@ static int __pmem_label_update(struct nd_region *nd_region, + break; + } + if (victim) { +- dev_dbg(ndd->dev, "%s: free: %d\n", __func__, slot); ++ dev_dbg(ndd->dev, "free: %d\n", slot); + slot = to_slot(ndd, victim->label); + nd_label_free_slot(ndd, slot); + victim->label = NULL; +@@ -868,7 +863,7 @@ static int __blk_label_update(struct nd_region *nd_region, + slot = nd_label_alloc_slot(ndd); + if (slot == UINT_MAX) + goto abort; +- dev_dbg(ndd->dev, "%s: allocated: %d\n", __func__, slot); ++ dev_dbg(ndd->dev, "allocated: %d\n", slot); + + nd_label = to_label(ndd, slot); + memset(nd_label, 0, sizeof_namespace_label(ndd)); +@@ -928,7 +923,7 @@ static int __blk_label_update(struct nd_region *nd_region, + + /* free up now unused slots in the new index */ + for_each_set_bit(slot, victim_map, victim_map ? nslot : 0) { +- dev_dbg(ndd->dev, "%s: free: %d\n", __func__, slot); ++ dev_dbg(ndd->dev, "free: %d\n", slot); + nd_label_free_slot(ndd, slot); + } + +@@ -1092,7 +1087,7 @@ static int del_labels(struct nd_mapping *nd_mapping, u8 *uuid) + active--; + slot = to_slot(ndd, nd_label); + nd_label_free_slot(ndd, slot); +- dev_dbg(ndd->dev, "%s: free: %d\n", __func__, slot); ++ dev_dbg(ndd->dev, "free: %d\n", slot); + list_move_tail(&label_ent->list, &list); + label_ent->label = NULL; + } +@@ -1100,7 +1095,7 @@ static int del_labels(struct nd_mapping *nd_mapping, u8 *uuid) + + if (active == 0) { + nd_mapping_free_labels(nd_mapping); +- dev_dbg(ndd->dev, "%s: no more active labels\n", __func__); ++ dev_dbg(ndd->dev, "no more active labels\n"); + } + mutex_unlock(&nd_mapping->lock); + +diff --git a/drivers/nvdimm/namespace_devs.c b/drivers/nvdimm/namespace_devs.c +index 658ada497be0..89b40ff83025 100644 +--- a/drivers/nvdimm/namespace_devs.c ++++ b/drivers/nvdimm/namespace_devs.c +@@ -421,7 +421,7 @@ static ssize_t alt_name_store(struct device *dev, + rc = __alt_name_store(dev, buf, len); + if (rc >= 0) + rc = nd_namespace_label_update(nd_region, dev); +- dev_dbg(dev, "%s: %s(%zd)\n", __func__, rc < 0 ? "fail " : "", rc); ++ dev_dbg(dev, "%s(%zd)\n", rc < 0 ? "fail " : "", rc); + nvdimm_bus_unlock(dev); + device_unlock(dev); + +@@ -1007,7 +1007,7 @@ static ssize_t __size_store(struct device *dev, unsigned long long val) + if (uuid_not_set(uuid, dev, __func__)) + return -ENXIO; + if (nd_region->ndr_mappings == 0) { +- dev_dbg(dev, "%s: not associated with dimm(s)\n", __func__); ++ dev_dbg(dev, "not associated with dimm(s)\n"); + return -ENXIO; + } + +@@ -1105,8 +1105,7 @@ static ssize_t size_store(struct device *dev, + *uuid = NULL; + } + +- dev_dbg(dev, "%s: %llx %s (%d)\n", __func__, val, rc < 0 +- ? "fail" : "success", rc); ++ dev_dbg(dev, "%llx %s (%d)\n", val, rc < 0 ? "fail" : "success", rc); + + nvdimm_bus_unlock(dev); + device_unlock(dev); +@@ -1270,8 +1269,8 @@ static ssize_t uuid_store(struct device *dev, + rc = nd_namespace_label_update(nd_region, dev); + else + kfree(uuid); +- dev_dbg(dev, "%s: result: %zd wrote: %s%s", __func__, +- rc, buf, buf[len - 1] == '\n' ? "" : "\n"); ++ dev_dbg(dev, "result: %zd wrote: %s%s", rc, buf, ++ buf[len - 1] == '\n' ? "" : "\n"); + nvdimm_bus_unlock(dev); + device_unlock(dev); + +@@ -1355,9 +1354,8 @@ static ssize_t sector_size_store(struct device *dev, + rc = nd_size_select_store(dev, buf, lbasize, supported); + if (rc >= 0) + rc = nd_namespace_label_update(nd_region, dev); +- dev_dbg(dev, "%s: result: %zd %s: %s%s", __func__, +- rc, rc < 0 ? "tried" : "wrote", buf, +- buf[len - 1] == '\n' ? "" : "\n"); ++ dev_dbg(dev, "result: %zd %s: %s%s", rc, rc < 0 ? "tried" : "wrote", ++ buf, buf[len - 1] == '\n' ? "" : "\n"); + nvdimm_bus_unlock(dev); + device_unlock(dev); + +@@ -1519,7 +1517,7 @@ static ssize_t holder_class_store(struct device *dev, + rc = __holder_class_store(dev, buf); + if (rc >= 0) + rc = nd_namespace_label_update(nd_region, dev); +- dev_dbg(dev, "%s: %s(%zd)\n", __func__, rc < 0 ? "fail " : "", rc); ++ dev_dbg(dev, "%s(%zd)\n", rc < 0 ? "fail " : "", rc); + nvdimm_bus_unlock(dev); + device_unlock(dev); + +@@ -1717,8 +1715,7 @@ struct nd_namespace_common *nvdimm_namespace_common_probe(struct device *dev) + if (uuid_not_set(nsblk->uuid, &ndns->dev, __func__)) + return ERR_PTR(-ENODEV); + if (!nsblk->lbasize) { +- dev_dbg(&ndns->dev, "%s: sector size not set\n", +- __func__); ++ dev_dbg(&ndns->dev, "sector size not set\n"); + return ERR_PTR(-ENODEV); + } + if (!nd_namespace_blk_validate(nsblk)) +@@ -1798,9 +1795,7 @@ static bool has_uuid_at_pos(struct nd_region *nd_region, u8 *uuid, + } + + if (found_uuid) { +- dev_dbg(ndd->dev, +- "%s duplicate entry for uuid\n", +- __func__); ++ dev_dbg(ndd->dev, "duplicate entry for uuid\n"); + return false; + } + found_uuid = true; +@@ -1994,14 +1989,13 @@ static struct device *create_namespace_pmem(struct nd_region *nd_region, + namespace_pmem_release(dev); + switch (rc) { + case -EINVAL: +- dev_dbg(&nd_region->dev, "%s: invalid label(s)\n", __func__); ++ dev_dbg(&nd_region->dev, "invalid label(s)\n"); + break; + case -ENODEV: +- dev_dbg(&nd_region->dev, "%s: label not found\n", __func__); ++ dev_dbg(&nd_region->dev, "label not found\n"); + break; + default: +- dev_dbg(&nd_region->dev, "%s: unexpected err: %d\n", +- __func__, rc); ++ dev_dbg(&nd_region->dev, "unexpected err: %d\n", rc); + break; + } + return ERR_PTR(rc); +@@ -2334,8 +2328,8 @@ static struct device **scan_labels(struct nd_region *nd_region) + + } + +- dev_dbg(&nd_region->dev, "%s: discovered %d %s namespace%s\n", +- __func__, count, is_nd_blk(&nd_region->dev) ++ dev_dbg(&nd_region->dev, "discovered %d %s namespace%s\n", ++ count, is_nd_blk(&nd_region->dev) + ? "blk" : "pmem", count == 1 ? "" : "s"); + + if (count == 0) { +@@ -2467,7 +2461,7 @@ static int init_active_labels(struct nd_region *nd_region) + get_ndd(ndd); + + count = nd_label_active_count(ndd); +- dev_dbg(ndd->dev, "%s: %d\n", __func__, count); ++ dev_dbg(ndd->dev, "count: %d\n", count); + if (!count) + continue; + for (j = 0; j < count; j++) { +diff --git a/drivers/nvdimm/pfn_devs.c b/drivers/nvdimm/pfn_devs.c +index f5c4e8c6e29d..e7e42130a375 100644 +--- a/drivers/nvdimm/pfn_devs.c ++++ b/drivers/nvdimm/pfn_devs.c +@@ -27,7 +27,7 @@ static void nd_pfn_release(struct device *dev) + struct nd_region *nd_region = to_nd_region(dev->parent); + struct nd_pfn *nd_pfn = to_nd_pfn(dev); + +- dev_dbg(dev, "%s\n", __func__); ++ dev_dbg(dev, "trace\n"); + nd_detach_ndns(&nd_pfn->dev, &nd_pfn->ndns); + ida_simple_remove(&nd_region->pfn_ida, nd_pfn->id); + kfree(nd_pfn->uuid); +@@ -94,8 +94,8 @@ static ssize_t mode_store(struct device *dev, + else + rc = -EINVAL; + } +- dev_dbg(dev, "%s: result: %zd wrote: %s%s", __func__, +- rc, buf, buf[len - 1] == '\n' ? "" : "\n"); ++ dev_dbg(dev, "result: %zd wrote: %s%s", rc, buf, ++ buf[len - 1] == '\n' ? "" : "\n"); + nvdimm_bus_unlock(dev); + device_unlock(dev); + +@@ -144,8 +144,8 @@ static ssize_t align_store(struct device *dev, + nvdimm_bus_lock(dev); + rc = nd_size_select_store(dev, buf, &nd_pfn->align, + nd_pfn_supported_alignments()); +- dev_dbg(dev, "%s: result: %zd wrote: %s%s", __func__, +- rc, buf, buf[len - 1] == '\n' ? "" : "\n"); ++ dev_dbg(dev, "result: %zd wrote: %s%s", rc, buf, ++ buf[len - 1] == '\n' ? "" : "\n"); + nvdimm_bus_unlock(dev); + device_unlock(dev); + +@@ -171,8 +171,8 @@ static ssize_t uuid_store(struct device *dev, + + device_lock(dev); + rc = nd_uuid_store(dev, &nd_pfn->uuid, buf, len); +- dev_dbg(dev, "%s: result: %zd wrote: %s%s", __func__, +- rc, buf, buf[len - 1] == '\n' ? "" : "\n"); ++ dev_dbg(dev, "result: %zd wrote: %s%s", rc, buf, ++ buf[len - 1] == '\n' ? "" : "\n"); + device_unlock(dev); + + return rc ? rc : len; +@@ -201,8 +201,8 @@ static ssize_t namespace_store(struct device *dev, + device_lock(dev); + nvdimm_bus_lock(dev); + rc = nd_namespace_store(dev, &nd_pfn->ndns, buf, len); +- dev_dbg(dev, "%s: result: %zd wrote: %s%s", __func__, +- rc, buf, buf[len - 1] == '\n' ? "" : "\n"); ++ dev_dbg(dev, "result: %zd wrote: %s%s", rc, buf, ++ buf[len - 1] == '\n' ? "" : "\n"); + nvdimm_bus_unlock(dev); + device_unlock(dev); + +@@ -314,8 +314,8 @@ struct device *nd_pfn_devinit(struct nd_pfn *nd_pfn, + dev = &nd_pfn->dev; + device_initialize(&nd_pfn->dev); + if (ndns && !__nd_attach_ndns(&nd_pfn->dev, ndns, &nd_pfn->ndns)) { +- dev_dbg(&ndns->dev, "%s failed, already claimed by %s\n", +- __func__, dev_name(ndns->claim)); ++ dev_dbg(&ndns->dev, "failed, already claimed by %s\n", ++ dev_name(ndns->claim)); + put_device(dev); + return NULL; + } +@@ -510,8 +510,7 @@ int nd_pfn_probe(struct device *dev, struct nd_namespace_common *ndns) + nd_pfn = to_nd_pfn(pfn_dev); + nd_pfn->pfn_sb = pfn_sb; + rc = nd_pfn_validate(nd_pfn, PFN_SIG); +- dev_dbg(dev, "%s: pfn: %s\n", __func__, +- rc == 0 ? dev_name(pfn_dev) : ""); ++ dev_dbg(dev, "pfn: %s\n", rc == 0 ? dev_name(pfn_dev) : ""); + if (rc < 0) { + nd_detach_ndns(pfn_dev, &nd_pfn->ndns); + put_device(pfn_dev); +diff --git a/drivers/nvdimm/pmem.c b/drivers/nvdimm/pmem.c +index 06f8dcc52ca6..906d31e56261 100644 +--- a/drivers/nvdimm/pmem.c ++++ b/drivers/nvdimm/pmem.c +@@ -66,7 +66,7 @@ static blk_status_t pmem_clear_poison(struct pmem_device *pmem, + rc = BLK_STS_IOERR; + if (cleared > 0 && cleared / 512) { + cleared /= 512; +- dev_dbg(dev, "%s: %#llx clear %ld sector%s\n", __func__, ++ dev_dbg(dev, "%#llx clear %ld sector%s\n", + (unsigned long long) sector, cleared, + cleared > 1 ? "s" : ""); + badblocks_clear(&pmem->bb, sector, cleared); +-- +2.23.0 + diff --git a/patches.suse/lpfc-add-support-for-translating-an-RSCN-rcv-into-a-.patch b/patches.suse/lpfc-add-support-for-translating-an-RSCN-rcv-into-a-.patch new file mode 100644 index 0000000..04ad106 --- /dev/null +++ b/patches.suse/lpfc-add-support-for-translating-an-RSCN-rcv-into-a-.patch @@ -0,0 +1,110 @@ +From: James Smart +Date: Tue, 14 May 2019 14:58:07 -0700 +Subject: lpfc: add support for translating an RSCN rcv into a discovery rescan +Patch-mainline: v5.3-rc1 +Git-commit: 6f2589f478795c46a61696d7d7c2f47a0bc6cfe3 +References: bsc#1164777 bsc#1164780 bsc#1165211 + +This patch updates RSCN receive processing to check for the remote +port being an NVME port, and if so, invoke the nvme_fc callback to +rescan the remote port. The rescan will generate a discovery udev +event. + +Signed-off-by: Dick Kennedy +Signed-off-by: James Smart +Reviewed-by: Hannes Reinecke +Reviewed-by: Arun Easi +Signed-off-by: Sagi Grimberg +Signed-off-by: Christoph Hellwig +Acked-by: Daniel Wagner +--- + drivers/scsi/lpfc/lpfc_crtn.h | 2 + + drivers/scsi/lpfc/lpfc_els.c | 5 ++++ + drivers/scsi/lpfc/lpfc_nvme.c | 44 ++++++++++++++++++++++++++++++++++++++++++ + 3 files changed, 51 insertions(+) + +--- a/drivers/scsi/lpfc/lpfc_crtn.h ++++ b/drivers/scsi/lpfc/lpfc_crtn.h +@@ -557,6 +557,8 @@ void lpfc_ras_stop_fwlog(struct lpfc_hba + int lpfc_check_fwlog_support(struct lpfc_hba *phba); + + /* NVME interfaces. */ ++void lpfc_nvme_rescan_port(struct lpfc_vport *vport, ++ struct lpfc_nodelist *ndlp); + void lpfc_nvme_unregister_port(struct lpfc_vport *vport, + struct lpfc_nodelist *ndlp); + int lpfc_nvme_register_port(struct lpfc_vport *vport, +--- a/drivers/scsi/lpfc/lpfc_els.c ++++ b/drivers/scsi/lpfc/lpfc_els.c +@@ -6326,6 +6326,8 @@ lpfc_rscn_recovery_check(struct lpfc_vpo + continue; + } + ++ if (ndlp->nlp_fc4_type & NLP_FC4_NVME) ++ lpfc_nvme_rescan_port(vport, ndlp); + + lpfc_disc_state_machine(vport, ndlp, NULL, + NLP_EVT_DEVICE_RECOVERY); +@@ -6437,6 +6439,9 @@ lpfc_els_rcv_rscn(struct lpfc_vport *vpo + "2024 pt2pt RSCN %08x Data: x%x x%x\n", + *lp, vport->fc_flag, payload_len); + lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL); ++ ++ if (ndlp->nlp_fc4_type & NLP_FC4_NVME) ++ lpfc_nvme_rescan_port(vport, ndlp); + return 0; + } + +--- a/drivers/scsi/lpfc/lpfc_nvme.c ++++ b/drivers/scsi/lpfc/lpfc_nvme.c +@@ -2402,6 +2402,50 @@ lpfc_nvme_register_port(struct lpfc_vpor + #endif + } + ++/** ++ * lpfc_nvme_rescan_port - Check to see if we should rescan this remoteport ++ * ++ * If the ndlp represents an NVME Target, that we are logged into, ++ * ping the NVME FC Transport layer to initiate a device rescan ++ * on this remote NPort. ++ */ ++void ++lpfc_nvme_rescan_port(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) ++{ ++#if (IS_ENABLED(CONFIG_NVME_FC)) ++ struct lpfc_nvme_rport *rport; ++ struct nvme_fc_remote_port *remoteport; ++ ++ rport = ndlp->nrport; ++ ++ lpfc_printf_vlog(vport, KERN_INFO, LOG_NVME_DISC, ++ "6170 Rescan NPort DID x%06x type x%x " ++ "state x%x rport %p\n", ++ ndlp->nlp_DID, ndlp->nlp_type, ndlp->nlp_state, rport); ++ if (!rport) ++ goto input_err; ++ remoteport = rport->remoteport; ++ if (!remoteport) ++ goto input_err; ++ ++ /* Only rescan if we are an NVME target in the MAPPED state */ ++ if (remoteport->port_role & FC_PORT_ROLE_NVME_DISCOVERY && ++ ndlp->nlp_state == NLP_STE_MAPPED_NODE) { ++ nvme_fc_rescan_remoteport(remoteport); ++ ++ lpfc_printf_vlog(vport, KERN_ERR, LOG_NVME_DISC, ++ "6172 NVME rescanned DID x%06x " ++ "port_state x%x\n", ++ ndlp->nlp_DID, remoteport->port_state); ++ } ++ return; ++input_err: ++ lpfc_printf_vlog(vport, KERN_ERR, LOG_NVME_DISC, ++ "6169 State error: lport %p, rport%p FCID x%06x\n", ++ vport->localport, ndlp->rport, ndlp->nlp_DID); ++#endif ++} ++ + /* lpfc_nvme_unregister_port - unbind the DID and port_role from this rport. + * + * There is no notion of Devloss or rport recovery from the current diff --git a/patches.suse/lpfc-add-support-to-generate-RSCN-events-for-nport.patch b/patches.suse/lpfc-add-support-to-generate-RSCN-events-for-nport.patch new file mode 100644 index 0000000..74eeb2a --- /dev/null +++ b/patches.suse/lpfc-add-support-to-generate-RSCN-events-for-nport.patch @@ -0,0 +1,274 @@ +From: James Smart +Date: Tue, 14 May 2019 14:58:05 -0700 +Subject: lpfc: add support to generate RSCN events for nport +Patch-mainline: v5.3-rc1 +Git-commit: f60cb93bbfecf1ad13713af285c3793e861fc9b2 +References: bsc#1164777 bsc#1164780 bsc#1165211 + +This patch adds general RSCN support: + + - The ability to transmit an RSCN to the port on the other end of + the link (regular port if pt2pt, or fabric controller if fabric). + - And general recognition of an RSCN ELS when an ELS is received. + +Signed-off-by: Dick Kennedy +Signed-off-by: James Smart +Reviewed-by: Hannes Reinecke +Reviewed-by: Arun Easi +Signed-off-by: Sagi Grimberg +Signed-off-by: Christoph Hellwig +Acked-by: Daniel Wagner +--- + drivers/scsi/lpfc/lpfc.h | 1 + drivers/scsi/lpfc/lpfc_crtn.h | 2 + drivers/scsi/lpfc/lpfc_els.c | 122 +++++++++++++++++++++++++++++++++++++++ + drivers/scsi/lpfc/lpfc_hbadisc.c | 35 +++++++++++ + drivers/scsi/lpfc/lpfc_hw.h | 2 + drivers/scsi/lpfc/lpfc_sli.c | 1 + 6 files changed, 163 insertions(+) + +--- a/drivers/scsi/lpfc/lpfc.h ++++ b/drivers/scsi/lpfc/lpfc.h +@@ -274,6 +274,7 @@ struct lpfc_stats { + uint32_t elsXmitADISC; + uint32_t elsXmitLOGO; + uint32_t elsXmitSCR; ++ uint32_t elsXmitRSCN; + uint32_t elsXmitRNID; + uint32_t elsXmitFARP; + uint32_t elsXmitFARPR; +--- a/drivers/scsi/lpfc/lpfc_crtn.h ++++ b/drivers/scsi/lpfc/lpfc_crtn.h +@@ -141,6 +141,7 @@ int lpfc_issue_els_adisc(struct lpfc_vpo + int lpfc_issue_els_logo(struct lpfc_vport *, struct lpfc_nodelist *, uint8_t); + int lpfc_issue_els_npiv_logo(struct lpfc_vport *, struct lpfc_nodelist *); + int lpfc_issue_els_scr(struct lpfc_vport *, uint32_t, uint8_t); ++int lpfc_issue_els_rscn(struct lpfc_vport *vport, uint8_t retry); + int lpfc_issue_fabric_reglogin(struct lpfc_vport *); + int lpfc_els_free_iocb(struct lpfc_hba *, struct lpfc_iocbq *); + int lpfc_ct_free_iocb(struct lpfc_hba *, struct lpfc_iocbq *); +@@ -355,6 +356,7 @@ void lpfc_mbox_timeout_handler(struct lp + struct lpfc_nodelist *lpfc_findnode_did(struct lpfc_vport *, uint32_t); + struct lpfc_nodelist *lpfc_findnode_wwpn(struct lpfc_vport *, + struct lpfc_name *); ++struct lpfc_nodelist *lpfc_findnode_mapped(struct lpfc_vport *vport); + + int lpfc_sli_issue_mbox_wait(struct lpfc_hba *, LPFC_MBOXQ_t *, uint32_t); + +--- a/drivers/scsi/lpfc/lpfc_els.c ++++ b/drivers/scsi/lpfc/lpfc_els.c +@@ -30,6 +30,8 @@ + #include + #include + #include ++#include ++#include + + #include "lpfc_hw4.h" + #include "lpfc_hw.h" +@@ -3079,6 +3081,116 @@ lpfc_issue_els_scr(struct lpfc_vport *vp + } + + /** ++ * lpfc_issue_els_rscn - Issue an RSCN to the Fabric Controller (Fabric) ++ * or the other nport (pt2pt). ++ * @vport: pointer to a host virtual N_Port data structure. ++ * @retry: number of retries to the command IOCB. ++ * ++ * This routine issues a RSCN to the Fabric Controller (DID 0xFFFFFD) ++ * when connected to a fabric, or to the remote port when connected ++ * in point-to-point mode. When sent to the Fabric Controller, it will ++ * replay the RSCN to registered recipients. ++ * ++ * Note that, in lpfc_prep_els_iocb() routine, the reference count of ndlp ++ * will be incremented by 1 for holding the ndlp and the reference to ndlp ++ * will be stored into the context1 field of the IOCB for the completion ++ * callback function to the RSCN ELS command. ++ * ++ * Return code ++ * 0 - Successfully issued RSCN command ++ * 1 - Failed to issue RSCN command ++ **/ ++int ++lpfc_issue_els_rscn(struct lpfc_vport *vport, uint8_t retry) ++{ ++ struct lpfc_hba *phba = vport->phba; ++ struct lpfc_iocbq *elsiocb; ++ struct lpfc_nodelist *ndlp; ++ struct { ++ struct fc_els_rscn rscn; ++ struct fc_els_rscn_page portid; ++ } *event; ++ uint32_t nportid; ++ uint16_t cmdsize = sizeof(*event); ++ ++ /* Not supported for private loop */ ++ if (phba->fc_topology == LPFC_TOPOLOGY_LOOP && ++ !(vport->fc_flag & FC_PUBLIC_LOOP)) ++ return 1; ++ ++ if (vport->fc_flag & FC_PT2PT) { ++ /* find any mapped nport - that would be the other nport */ ++ ndlp = lpfc_findnode_mapped(vport); ++ if (!ndlp) ++ return 1; ++ } else { ++ nportid = FC_FID_FCTRL; ++ /* find the fabric controller node */ ++ ndlp = lpfc_findnode_did(vport, nportid); ++ if (!ndlp) { ++ /* if one didn't exist, make one */ ++ ndlp = lpfc_nlp_init(vport, nportid); ++ if (!ndlp) ++ return 1; ++ lpfc_enqueue_node(vport, ndlp); ++ } else if (!NLP_CHK_NODE_ACT(ndlp)) { ++ ndlp = lpfc_enable_node(vport, ndlp, ++ NLP_STE_UNUSED_NODE); ++ if (!ndlp) ++ return 1; ++ } ++ } ++ ++ elsiocb = lpfc_prep_els_iocb(vport, 1, cmdsize, retry, ndlp, ++ ndlp->nlp_DID, ELS_CMD_RSCN_XMT); ++ ++ if (!elsiocb) { ++ /* This will trigger the release of the node just ++ * allocated ++ */ ++ lpfc_nlp_put(ndlp); ++ return 1; ++ } ++ ++ event = ((struct lpfc_dmabuf *)elsiocb->context2)->virt; ++ ++ event->rscn.rscn_cmd = ELS_RSCN; ++ event->rscn.rscn_page_len = sizeof(struct fc_els_rscn_page); ++ event->rscn.rscn_plen = cpu_to_be16(cmdsize); ++ ++ nportid = vport->fc_myDID; ++ /* appears that page flags must be 0 for fabric to broadcast RSCN */ ++ event->portid.rscn_page_flags = 0; ++ event->portid.rscn_fid[0] = (nportid & 0x00FF0000) >> 16; ++ event->portid.rscn_fid[1] = (nportid & 0x0000FF00) >> 8; ++ event->portid.rscn_fid[2] = nportid & 0x000000FF; ++ ++ lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD, ++ "Issue RSCN: did:x%x", ++ ndlp->nlp_DID, 0, 0); ++ ++ phba->fc_stat.elsXmitRSCN++; ++ elsiocb->iocb_cmpl = lpfc_cmpl_els_cmd; ++ if (lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, elsiocb, 0) == ++ IOCB_ERROR) { ++ /* The additional lpfc_nlp_put will cause the following ++ * lpfc_els_free_iocb routine to trigger the rlease of ++ * the node. ++ */ ++ lpfc_nlp_put(ndlp); ++ lpfc_els_free_iocb(phba, elsiocb); ++ return 1; ++ } ++ /* This will cause the callback-function lpfc_cmpl_els_cmd to ++ * trigger the release of node. ++ */ ++ if (!(vport->fc_flag & FC_PT2PT)) ++ lpfc_nlp_put(ndlp); ++ ++ return 0; ++} ++ ++/** + * lpfc_issue_els_farpr - Issue a farp to an node on a vport + * @vport: pointer to a host virtual N_Port data structure. + * @nportid: N_Port identifier to the remote node. +@@ -6318,6 +6430,16 @@ lpfc_els_rcv_rscn(struct lpfc_vport *vpo + fc_host_post_event(shost, fc_get_event_number(), + FCH_EVT_RSCN, lp[i]); + ++ /* Check if RSCN is coming from a direct-connected remote NPort */ ++ if (vport->fc_flag & FC_PT2PT) { ++ /* If so, just ACC it, no other action needed for now */ ++ lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, ++ "2024 pt2pt RSCN %08x Data: x%x x%x\n", ++ *lp, vport->fc_flag, payload_len); ++ lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL); ++ return 0; ++ } ++ + /* If we are about to begin discovery, just ACC the RSCN. + * Discovery processing will satisfy it. + */ +--- a/drivers/scsi/lpfc/lpfc_hbadisc.c ++++ b/drivers/scsi/lpfc/lpfc_hbadisc.c +@@ -5277,6 +5277,41 @@ lpfc_findnode_did(struct lpfc_vport *vpo + } + + struct lpfc_nodelist * ++lpfc_findnode_mapped(struct lpfc_vport *vport) ++{ ++ struct Scsi_Host *shost = lpfc_shost_from_vport(vport); ++ struct lpfc_nodelist *ndlp; ++ uint32_t data1; ++ unsigned long iflags; ++ ++ spin_lock_irqsave(shost->host_lock, iflags); ++ ++ list_for_each_entry(ndlp, &vport->fc_nodes, nlp_listp) { ++ if (ndlp->nlp_state == NLP_STE_UNMAPPED_NODE || ++ ndlp->nlp_state == NLP_STE_MAPPED_NODE) { ++ data1 = (((uint32_t)ndlp->nlp_state << 24) | ++ ((uint32_t)ndlp->nlp_xri << 16) | ++ ((uint32_t)ndlp->nlp_type << 8) | ++ ((uint32_t)ndlp->nlp_rpi & 0xff)); ++ spin_unlock_irqrestore(shost->host_lock, iflags); ++ lpfc_printf_vlog(vport, KERN_INFO, LOG_NODE, ++ "2025 FIND node DID " ++ "Data: x%p x%x x%x x%x %p\n", ++ ndlp, ndlp->nlp_DID, ++ ndlp->nlp_flag, data1, ++ ndlp->active_rrqs_xri_bitmap); ++ return ndlp; ++ } ++ } ++ spin_unlock_irqrestore(shost->host_lock, iflags); ++ ++ /* FIND node did NOT FOUND */ ++ lpfc_printf_vlog(vport, KERN_INFO, LOG_NODE, ++ "2026 FIND mapped did NOT FOUND.\n"); ++ return NULL; ++} ++ ++struct lpfc_nodelist * + lpfc_setup_disc_node(struct lpfc_vport *vport, uint32_t did) + { + struct Scsi_Host *shost = lpfc_shost_from_vport(vport); +--- a/drivers/scsi/lpfc/lpfc_hw.h ++++ b/drivers/scsi/lpfc/lpfc_hw.h +@@ -601,6 +601,7 @@ struct fc_vft_header { + #define ELS_CMD_RPL 0x57000000 + #define ELS_CMD_FAN 0x60000000 + #define ELS_CMD_RSCN 0x61040000 ++#define ELS_CMD_RSCN_XMT 0x61040008 + #define ELS_CMD_SCR 0x62000000 + #define ELS_CMD_RNID 0x78000000 + #define ELS_CMD_LIRR 0x7A000000 +@@ -642,6 +643,7 @@ struct fc_vft_header { + #define ELS_CMD_RPL 0x57 + #define ELS_CMD_FAN 0x60 + #define ELS_CMD_RSCN 0x0461 ++#define ELS_CMD_RSCN_XMT 0x08000461 + #define ELS_CMD_SCR 0x62 + #define ELS_CMD_RNID 0x78 + #define ELS_CMD_LIRR 0x7A +--- a/drivers/scsi/lpfc/lpfc_sli.c ++++ b/drivers/scsi/lpfc/lpfc_sli.c +@@ -9405,6 +9405,7 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba + if (if_type >= LPFC_SLI_INTF_IF_TYPE_2) { + if (pcmd && (*pcmd == ELS_CMD_FLOGI || + *pcmd == ELS_CMD_SCR || ++ *pcmd == ELS_CMD_RSCN_XMT || + *pcmd == ELS_CMD_FDISC || + *pcmd == ELS_CMD_LOGO || + *pcmd == ELS_CMD_PLOGI)) { diff --git a/patches.suse/mac80211-Do-not-send-mesh-HWMP-PREQ-if-HWMP-is-disab.patch b/patches.suse/mac80211-Do-not-send-mesh-HWMP-PREQ-if-HWMP-is-disab.patch new file mode 100644 index 0000000..4cd0cba --- /dev/null +++ b/patches.suse/mac80211-Do-not-send-mesh-HWMP-PREQ-if-HWMP-is-disab.patch @@ -0,0 +1,38 @@ +From ba32679cac50c38fdf488296f96b1f3175532b8e Mon Sep 17 00:00:00 2001 +From: Nicolas Cavallari +Date: Thu, 5 Mar 2020 15:04:09 +0100 +Subject: [PATCH] mac80211: Do not send mesh HWMP PREQ if HWMP is disabled +Git-commit: ba32679cac50c38fdf488296f96b1f3175532b8e +Patch-mainline: v5.6-rc6 +References: bsc#1051510 + +When trying to transmit to an unknown destination, the mesh code would +unconditionally transmit a HWMP PREQ even if HWMP is not the current +path selection algorithm. + +Signed-off-by: Nicolas Cavallari +Link: https://lore.kernel.org/r/20200305140409.12204-1-cavallar@lri.fr +Signed-off-by: Johannes Berg +Acked-by: Takashi Iwai + +--- + net/mac80211/mesh_hwmp.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c +index d69983370381..38a0383dfbcf 100644 +--- a/net/mac80211/mesh_hwmp.c ++++ b/net/mac80211/mesh_hwmp.c +@@ -1152,7 +1152,8 @@ int mesh_nexthop_resolve(struct ieee80211_sub_if_data *sdata, + } + } + +- if (!(mpath->flags & MESH_PATH_RESOLVING)) ++ if (!(mpath->flags & MESH_PATH_RESOLVING) && ++ mesh_path_sel_is_hwmp(sdata)) + mesh_queue_preq(mpath, PREQ_Q_F_START); + + if (skb_queue_len(&mpath->frame_queue) >= MESH_FRAME_QUEUE_LEN) +-- +2.16.4 + diff --git a/patches.suse/mac80211-consider-more-elements-in-parsing-CRC.patch b/patches.suse/mac80211-consider-more-elements-in-parsing-CRC.patch new file mode 100644 index 0000000..d2f9793 --- /dev/null +++ b/patches.suse/mac80211-consider-more-elements-in-parsing-CRC.patch @@ -0,0 +1,66 @@ +From a04564c99bb4a92f805a58e56b2d22cc4978f152 Mon Sep 17 00:00:00 2001 +From: Johannes Berg +Date: Fri, 31 Jan 2020 13:12:58 +0200 +Subject: [PATCH] mac80211: consider more elements in parsing CRC +Git-commit: a04564c99bb4a92f805a58e56b2d22cc4978f152 +Patch-mainline: v5.6-rc2 +References: bsc#1051510 + +We only use the parsing CRC for checking if a beacon changed, +and elements with an ID > 63 cannot be represented in the +filter. Thus, like we did before with WMM and Cisco vendor +elements, just statically add these forgotten items to the +Crc: - WLAN_EID_VHT_OPERATION - WLAN_EID_OPMODE_NOTIF + +I guess that in most cases when VHT/HE operation change, the HT +operation also changed, and so the change was picked up, but we +did notice that pure operating mode notification changes were +ignored. + +Signed-off-by: Johannes Berg +Signed-off-by: Luca Coelho +Link: https://lore.kernel.org/r/20200131111300.891737-22-luca@coelho.fi +[restrict to VHT for the mac80211 branch] + +Acked-by: Takashi Iwai + +--- + net/mac80211/util.c | 18 ++++++++++++------ + 1 file changed, 12 insertions(+), 6 deletions(-) + +diff --git a/net/mac80211/util.c b/net/mac80211/util.c +index 32a7a53833c0..739e90555d8b 100644 +--- a/net/mac80211/util.c ++++ b/net/mac80211/util.c +@@ -1063,16 +1063,22 @@ _ieee802_11_parse_elems_crc(const u8 *start, size_t len, bool action, + elem_parse_failed = true; + break; + case WLAN_EID_VHT_OPERATION: +- if (elen >= sizeof(struct ieee80211_vht_operation)) ++ if (elen >= sizeof(struct ieee80211_vht_operation)) { + elems->vht_operation = (void *)pos; +- else +- elem_parse_failed = true; ++ if (calc_crc) ++ crc = crc32_be(crc, pos - 2, elen + 2); ++ break; ++ } ++ elem_parse_failed = true; + break; + case WLAN_EID_OPMODE_NOTIF: +- if (elen > 0) ++ if (elen > 0) { + elems->opmode_notif = pos; +- else +- elem_parse_failed = true; ++ if (calc_crc) ++ crc = crc32_be(crc, pos - 2, elen + 2); ++ break; ++ } ++ elem_parse_failed = true; + break; + case WLAN_EID_MESH_ID: + elems->mesh_id = pos; +-- +2.16.4 + diff --git a/patches.suse/mac80211-free-peer-keys-before-vif-down-in-mesh.patch b/patches.suse/mac80211-free-peer-keys-before-vif-down-in-mesh.patch index cf3954d..6f70fee 100644 --- a/patches.suse/mac80211-free-peer-keys-before-vif-down-in-mesh.patch +++ b/patches.suse/mac80211-free-peer-keys-before-vif-down-in-mesh.patch @@ -4,7 +4,7 @@ Date: Tue, 28 May 2019 16:36:16 -0700 Subject: [PATCH] mac80211: free peer keys before vif down in mesh Git-commit: 0112fa557c3bb3a002bc85760dc3761d737264d3 Patch-mainline: v5.2-rc6 -References: bsc#1111666 +References: bsc#1051510 bsc#1111666 freeing peer keys after vif down is resulting in peer key uninstall to fail due to interface lookup failure. so fix that. diff --git a/patches.suse/mac80211-mesh-fix-RCU-warning.patch b/patches.suse/mac80211-mesh-fix-RCU-warning.patch index ef0b086..a8036b6 100644 --- a/patches.suse/mac80211-mesh-fix-RCU-warning.patch +++ b/patches.suse/mac80211-mesh-fix-RCU-warning.patch @@ -4,7 +4,7 @@ Date: Fri, 24 May 2019 21:16:24 -0700 Subject: [PATCH] mac80211: mesh: fix RCU warning Git-commit: 551842446ed695641a00782cd118cbb064a416a1 Patch-mainline: v5.2-rc6 -References: bsc#1111666 +References: bsc#1051510 bsc#1111666 ifmsh->csa is an RCU-protected pointer. The writer context in ieee80211_mesh_finish_csa() is already mutually diff --git a/patches.suse/mac80211-only-warn-once-on-chanctx_conf-being-NULL.patch b/patches.suse/mac80211-only-warn-once-on-chanctx_conf-being-NULL.patch index bcd2941..6f65eeb 100644 --- a/patches.suse/mac80211-only-warn-once-on-chanctx_conf-being-NULL.patch +++ b/patches.suse/mac80211-only-warn-once-on-chanctx_conf-being-NULL.patch @@ -4,7 +4,7 @@ Date: Fri, 14 Jun 2019 19:01:52 +0800 Subject: [PATCH] mac80211: only warn once on chanctx_conf being NULL Git-commit: 563572340173865a9a356e6bb02579e6998a876d Patch-mainline: v5.2-rc6 -References: bsc#1111666 +References: bsc#1051510 bsc#1111666 In multiple SSID cases, it takes time to prepare every AP interface to be ready in initializing phase. If a sta already knows everything it diff --git a/patches.suse/mac80211-rx-avoid-RCU-list-traversal-under-mutex.patch b/patches.suse/mac80211-rx-avoid-RCU-list-traversal-under-mutex.patch new file mode 100644 index 0000000..38fcf98 --- /dev/null +++ b/patches.suse/mac80211-rx-avoid-RCU-list-traversal-under-mutex.patch @@ -0,0 +1,39 @@ +From 253216ffb2a002a682c6f68bd3adff5b98b71de8 Mon Sep 17 00:00:00 2001 +From: Madhuparna Bhowmik +Date: Sun, 23 Feb 2020 20:03:02 +0530 +Subject: [PATCH] mac80211: rx: avoid RCU list traversal under mutex +Git-commit: 253216ffb2a002a682c6f68bd3adff5b98b71de8 +Patch-mainline: v5.6-rc4 +References: bsc#1051510 + +local->sta_mtx is held in __ieee80211_check_fast_rx_iface(). +No need to use list_for_each_entry_rcu() as it also requires +a cond argument to avoid false lockdep warnings when not used in +RCU read-side section (with CONFIG_PROVE_RCU_LIST). +Therefore use list_for_each_entry(); + +Signed-off-by: Madhuparna Bhowmik +Link: https://lore.kernel.org/r/20200223143302.15390-1-madhuparnabhowmik10@gmail.com +Signed-off-by: Johannes Berg +Acked-by: Takashi Iwai + +--- + net/mac80211/rx.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c +index 0e05ff037672..0ba98ad9bc85 100644 +--- a/net/mac80211/rx.c ++++ b/net/mac80211/rx.c +@@ -4114,7 +4114,7 @@ void __ieee80211_check_fast_rx_iface(struct ieee80211_sub_if_data *sdata) + + lockdep_assert_held(&local->sta_mtx); + +- list_for_each_entry_rcu(sta, &local->sta_list, list) { ++ list_for_each_entry(sta, &local->sta_list, list) { + if (sdata != sta->sdata && + (!sta->sdata->bss || sta->sdata->bss != sdata->bss)) + continue; +-- +2.16.4 + diff --git a/patches.suse/macsec-add-missing-attribute-validation-for-port.patch b/patches.suse/macsec-add-missing-attribute-validation-for-port.patch new file mode 100644 index 0000000..2826301 --- /dev/null +++ b/patches.suse/macsec-add-missing-attribute-validation-for-port.patch @@ -0,0 +1,35 @@ +From 31d9a1c524964bac77b7f9d0a1ac140dc6b57461 Mon Sep 17 00:00:00 2001 +From: Jakub Kicinski +Date: Mon, 2 Mar 2020 21:05:17 -0800 +Subject: [PATCH] macsec: add missing attribute validation for port +Git-commit: 31d9a1c524964bac77b7f9d0a1ac140dc6b57461 +Patch-mainline: v5.6-rc6 +References: bsc#1051510 + +Add missing attribute validation for IFLA_MACSEC_PORT +to the netlink policy. + +Fixes: c09440f7dcb3 ("macsec: introduce IEEE 802.1AE driver") +Signed-off-by: Jakub Kicinski +Signed-off-by: David S. Miller +Acked-by: Takashi Iwai + +--- + drivers/net/macsec.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/net/macsec.c b/drivers/net/macsec.c +index 45bfd99f17fa..5af424eeea86 100644 +--- a/drivers/net/macsec.c ++++ b/drivers/net/macsec.c +@@ -3342,6 +3342,7 @@ static const struct device_type macsec_type = { + + static const struct nla_policy macsec_rtnl_policy[IFLA_MACSEC_MAX + 1] = { + [IFLA_MACSEC_SCI] = { .type = NLA_U64 }, ++ [IFLA_MACSEC_PORT] = { .type = NLA_U16 }, + [IFLA_MACSEC_ICV_LEN] = { .type = NLA_U8 }, + [IFLA_MACSEC_CIPHER_SUITE] = { .type = NLA_U64 }, + [IFLA_MACSEC_WINDOW] = { .type = NLA_U32 }, +-- +2.16.4 + diff --git a/patches.suse/macsec-fix-refcnt-leak-in-module-exit-routine.patch b/patches.suse/macsec-fix-refcnt-leak-in-module-exit-routine.patch new file mode 100644 index 0000000..5197f0b --- /dev/null +++ b/patches.suse/macsec-fix-refcnt-leak-in-module-exit-routine.patch @@ -0,0 +1,71 @@ +From 2bce1ebed17da54c65042ec2b962e3234bad5b47 Mon Sep 17 00:00:00 2001 +From: Taehee Yoo +Date: Mon, 21 Oct 2019 18:47:55 +0000 +Subject: [PATCH] macsec: fix refcnt leak in module exit routine +Git-commit: 2bce1ebed17da54c65042ec2b962e3234bad5b47 +Patch-mainline: v5.4-rc6 +References: bsc#1051510 + +When a macsec interface is created, it increases a refcnt to a lower +device(real device). when macsec interface is deleted, the refcnt is +decreased in macsec_free_netdev(), which is ->priv_destructor() of +macsec interface. + +The problem scenario is this. +When nested macsec interfaces are exiting, the exit routine of the +macsec module makes refcnt leaks. + +Test commands: + ip link add dummy0 type dummy + ip link add macsec0 link dummy0 type macsec + ip link add macsec1 link macsec0 type macsec + modprobe -rv macsec + +[ 208.629433] unregister_netdevice: waiting for macsec0 to become free. Usage count = 1 + +Steps of exit routine of macsec module are below. +1. Calls ->dellink() in __rtnl_link_unregister(). +2. Checks refcnt and wait refcnt to be 0 if refcnt is not 0 in +netdev_run_todo(). +3. Calls ->priv_destruvtor() in netdev_run_todo(). + +Step2 checks refcnt, but step3 decreases refcnt. +So, step2 waits forever. + +This patch makes the macsec module do not hold a refcnt of the lower +device because it already holds a refcnt of the lower device with +netdev_upper_dev_link(). + +Fixes: c09440f7dcb3 ("macsec: introduce IEEE 802.1AE driver") +Signed-off-by: Taehee Yoo +Signed-off-by: David S. Miller +Acked-by: Takashi Iwai + +--- + drivers/net/macsec.c | 4 ---- + 1 file changed, 4 deletions(-) + +--- a/drivers/net/macsec.c ++++ b/drivers/net/macsec.c +@@ -2988,12 +2988,10 @@ static const struct nla_policy macsec_rt + static void macsec_free_netdev(struct net_device *dev) + { + struct macsec_dev *macsec = macsec_priv(dev); +- struct net_device *real_dev = macsec->real_dev; + + free_percpu(macsec->stats); + free_percpu(macsec->secy.tx_sc.stats); + +- dev_put(real_dev); + } + + static void macsec_setup(struct net_device *dev) +@@ -3234,8 +3232,6 @@ static int macsec_newlink(struct net *ne + if (err < 0) + return err; + +- dev_hold(real_dev); +- + macsec->nest_level = dev_get_nest_level(real_dev) + 1; + netdev_lockdep_set_classes(dev); + lockdep_set_class_and_subclass(&dev->addr_list_lock, diff --git a/patches.suse/md-display-timeout-error.patch b/patches.suse/md-display-timeout-error.patch index 76b6dd6..0db86df 100644 --- a/patches.suse/md-display-timeout-error.patch +++ b/patches.suse/md-display-timeout-error.patch @@ -19,7 +19,7 @@ Signed-off-by: Neil Brown --- a/drivers/md/md.c +++ b/drivers/md/md.c -@@ -783,8 +783,10 @@ static void super_written(struct bio *bi +@@ -865,8 +865,10 @@ static void super_written(struct bio *bi if (bio->bi_status) { pr_err("md: super_written gets error=%d\n", bio->bi_status); md_error(mddev, rdev); @@ -32,7 +32,7 @@ Signed-off-by: Neil Brown set_bit(MD_SB_NEED_REWRITE, &mddev->sb_flags); set_bit(LastDev, &rdev->flags); } -@@ -1136,6 +1138,7 @@ static int super_90_validate(struct mdde +@@ -1231,6 +1233,7 @@ static int super_90_validate(struct mdde rdev->raid_disk = -1; clear_bit(Faulty, &rdev->flags); @@ -40,7 +40,7 @@ Signed-off-by: Neil Brown clear_bit(In_sync, &rdev->flags); clear_bit(Bitmap_sync, &rdev->flags); clear_bit(WriteMostly, &rdev->flags); -@@ -1633,6 +1636,7 @@ static int super_1_validate(struct mddev +@@ -1746,6 +1749,7 @@ static int super_1_validate(struct mddev rdev->raid_disk = -1; clear_bit(Faulty, &rdev->flags); @@ -48,7 +48,7 @@ Signed-off-by: Neil Brown clear_bit(In_sync, &rdev->flags); clear_bit(Bitmap_sync, &rdev->flags); clear_bit(WriteMostly, &rdev->flags); -@@ -1755,6 +1759,9 @@ static int super_1_validate(struct mddev +@@ -1872,6 +1876,9 @@ static int super_1_validate(struct mddev break; case MD_DISK_ROLE_JOURNAL: /* journal device */ if (!(le32_to_cpu(sb->feature_map) & MD_FEATURE_JOURNAL)) { @@ -58,7 +58,7 @@ Signed-off-by: Neil Brown /* journal device without journal feature */ pr_warn("md: journal device provided without journal feature, ignoring the device\n"); return -EINVAL; -@@ -1763,6 +1770,11 @@ static int super_1_validate(struct mddev +@@ -1880,6 +1887,11 @@ static int super_1_validate(struct mddev rdev->journal_tail = le64_to_cpu(sb->journal_tail); rdev->raid_disk = 0; break; @@ -70,7 +70,7 @@ Signed-off-by: Neil Brown default: rdev->saved_raid_disk = role; if ((le32_to_cpu(sb->feature_map) & -@@ -1941,9 +1953,12 @@ retry: +@@ -2065,9 +2077,12 @@ retry: rdev_for_each(rdev2, mddev) { i = rdev2->desc_nr; @@ -86,7 +86,7 @@ Signed-off-by: Neil Brown sb->dev_roles[i] = cpu_to_le16(rdev2->raid_disk); else if (test_bit(Journal, &rdev2->flags)) sb->dev_roles[i] = cpu_to_le16(MD_DISK_ROLE_JOURNAL); -@@ -2698,6 +2713,8 @@ state_show(struct md_rdev *rdev, char *p +@@ -2824,6 +2839,8 @@ state_show(struct md_rdev *rdev, char *p (!test_bit(ExternalBbl, &flags) && rdev->badblocks.unacked_exist)) len += sprintf(page+len, "faulty%s", sep); @@ -95,7 +95,7 @@ Signed-off-by: Neil Brown if (test_bit(In_sync, &flags)) len += sprintf(page+len, "in_sync%s", sep); if (test_bit(Journal, &flags)) -@@ -2753,6 +2770,11 @@ state_store(struct md_rdev *rdev, const +@@ -2879,6 +2896,11 @@ state_store(struct md_rdev *rdev, const err = 0; else err = -EBUSY; @@ -107,7 +107,7 @@ Signed-off-by: Neil Brown } else if (cmd_match(buf, "remove")) { if (rdev->mddev->pers) { clear_bit(Blocked, &rdev->flags); -@@ -3000,6 +3022,7 @@ slot_store(struct md_rdev *rdev, const c +@@ -3130,6 +3152,7 @@ slot_store(struct md_rdev *rdev, const c rdev->raid_disk = slot; /* assume it is working */ clear_bit(Faulty, &rdev->flags); @@ -115,7 +115,7 @@ Signed-off-by: Neil Brown clear_bit(WriteMostly, &rdev->flags); set_bit(In_sync, &rdev->flags); sysfs_notify_dirent_safe(rdev->sysfs_state); -@@ -6313,9 +6336,11 @@ static int get_disk_info(struct mddev *m +@@ -6498,9 +6521,11 @@ static int get_disk_info(struct mddev *m info.minor = MINOR(rdev->bdev->bd_dev); info.raid_disk = rdev->raid_disk; info.state = 0; @@ -129,7 +129,7 @@ Signed-off-by: Neil Brown info.state |= (1<flags)) seq_printf(seq, "(J)"); if (test_bit(Faulty, &rdev->flags)) { @@ -143,9 +143,9 @@ Signed-off-by: Neil Brown if (rdev->raid_disk < 0) --- a/drivers/md/md.h +++ b/drivers/md/md.h -@@ -200,6 +200,9 @@ enum flag_bits { - * it didn't fail, so don't use FailFast - * any more for metadata +@@ -213,6 +213,9 @@ enum flag_bits { + * check if there is collision between raid1 + * serial bios. */ + Timeout, /* Device fault due to timeout. + * 'Faulty' is required to be set. @@ -155,7 +155,7 @@ Signed-off-by: Neil Brown static inline int is_badblock(struct md_rdev *rdev, sector_t s, int sectors, --- a/drivers/md/raid10.c +++ b/drivers/md/raid10.c -@@ -394,6 +394,7 @@ static void raid10_end_read_request(stru +@@ -395,6 +395,7 @@ static void raid10_end_read_request(stru slot = r10_bio->read_slot; rdev = r10_bio->devs[slot].rdev; @@ -163,7 +163,7 @@ Signed-off-by: Neil Brown /* * this branch is our 'one mirror IO has finished' event handler: */ -@@ -484,6 +485,7 @@ static void raid10_end_write_request(str +@@ -485,6 +486,7 @@ static void raid10_end_write_request(str repl = 0; rdev = conf->mirrors[dev].rdev; } @@ -171,16 +171,16 @@ Signed-off-by: Neil Brown /* * this branch is our 'one mirror IO has finished' event handler: */ -@@ -510,6 +512,8 @@ static void raid10_end_write_request(str - */ - set_bit(R10BIO_WriteError, &r10_bio->state); - else { -+ if (bio->bi_status == BLK_STS_TIMEOUT) -+ set_bit(Timeout, &rdev->flags); - r10_bio->devs[slot].bio = NULL; - to_put = bio; - dec_rdev = 1; -@@ -926,7 +930,11 @@ static void flush_pending_writes(struct +@@ -515,6 +517,8 @@ static void raid10_end_write_request(str + if (!test_bit(Faulty, &rdev->flags)) + set_bit(R10BIO_WriteError, &r10_bio->state); + else { ++ if (bio->bi_status == BLK_STS_TIMEOUT) ++ set_bit(Timeout, &rdev->flags); + r10_bio->devs[slot].bio = NULL; + to_put = bio; + dec_rdev = 1; +@@ -950,7 +954,11 @@ static void flush_pending_writes(struct bio->bi_next = NULL; bio_set_dev(bio, rdev->bdev); if (test_bit(Faulty, &rdev->flags)) { @@ -193,7 +193,7 @@ Signed-off-by: Neil Brown } else if (unlikely((bio_op(bio) == REQ_OP_DISCARD) && !blk_queue_discard(bio->bi_disk->queue))) /* Just ignore it */ -@@ -1111,7 +1119,11 @@ static void raid10_unplug(struct blk_plu +@@ -1135,7 +1143,11 @@ static void raid10_unplug(struct blk_plu bio->bi_next = NULL; bio_set_dev(bio, rdev->bdev); if (test_bit(Faulty, &rdev->flags)) { @@ -206,7 +206,7 @@ Signed-off-by: Neil Brown } else if (unlikely((bio_op(bio) == REQ_OP_DISCARD) && !blk_queue_discard(bio->bi_disk->queue))) /* Just ignore it */ -@@ -2104,6 +2116,9 @@ static void sync_request_write(struct md +@@ -2112,6 +2124,9 @@ static void sync_request_write(struct md } else if (test_bit(FailFast, &rdev->flags)) { /* Just give up on this device */ md_error(rdev->mddev, rdev); @@ -216,7 +216,7 @@ Signed-off-by: Neil Brown continue; } /* Ok, we need to write this bio, either to correct an -@@ -2367,6 +2382,7 @@ static void fix_read_error(struct r10con +@@ -2375,6 +2390,7 @@ static void fix_read_error(struct r10con struct md_rdev *rdev; int max_read_errors = atomic_read(&mddev->max_corr_read_errors); int d = r10_bio->devs[r10_bio->read_slot].devnum; @@ -224,7 +224,7 @@ Signed-off-by: Neil Brown /* still own a reference to this rdev, so it cannot * have been cleared recently. -@@ -2390,6 +2406,9 @@ static void fix_read_error(struct r10con +@@ -2398,6 +2414,9 @@ static void fix_read_error(struct r10con pr_notice("md/raid10:%s: %s: Failing raid device\n", mdname(mddev), b); md_error(mddev, rdev); @@ -234,7 +234,7 @@ Signed-off-by: Neil Brown r10_bio->devs[r10_bio->read_slot].bio = IO_BLOCKED; return; } -@@ -2631,9 +2650,12 @@ static void handle_read_error(struct mdd +@@ -2639,9 +2658,12 @@ static void handle_read_error(struct mdd freeze_array(conf, 1); fix_read_error(conf, mddev, r10_bio); unfreeze_array(conf); @@ -249,7 +249,7 @@ Signed-off-by: Neil Brown rdev_dec_pending(rdev, mddev); allow_barrier(conf); r10_bio->state = 0; -@@ -2668,8 +2690,13 @@ static void handle_write_completed(struc +@@ -2676,8 +2698,13 @@ static void handle_write_completed(struc if (!rdev_set_badblocks( rdev, r10_bio->devs[m].addr, @@ -264,7 +264,7 @@ Signed-off-by: Neil Brown } rdev = conf->mirrors[dev].replacement; if (r10_bio->devs[m].repl_bio == NULL || -@@ -2685,8 +2712,13 @@ static void handle_write_completed(struc +@@ -2693,8 +2720,13 @@ static void handle_write_completed(struc if (!rdev_set_badblocks( rdev, r10_bio->devs[m].addr, @@ -279,7 +279,7 @@ Signed-off-by: Neil Brown } } put_buf(r10_bio); -@@ -4817,6 +4849,9 @@ static void end_reshape_write(struct bio +@@ -4900,6 +4932,9 @@ static void end_reshape_write(struct bio if (bio->bi_status) { /* FIXME should record badblock */ md_error(mddev, rdev); diff --git a/patches.suse/md-don-t-report-active-array_state-until-after-reval.patch b/patches.suse/md-don-t-report-active-array_state-until-after-reval.patch index e17e044..c0690b1 100644 --- a/patches.suse/md-don-t-report-active-array_state-until-after-reval.patch +++ b/patches.suse/md-don-t-report-active-array_state-until-after-reval.patch @@ -47,7 +47,7 @@ Acked-by: NeilBrown --- a/drivers/md/md.c +++ b/drivers/md/md.c -@@ -4152,7 +4152,7 @@ array_state_show(struct mddev *mddev, ch +@@ -4196,7 +4196,7 @@ array_state_show(struct mddev *mddev, ch { enum array_state st = inactive; @@ -56,7 +56,7 @@ Acked-by: NeilBrown switch(mddev->ro) { case 1: st = readonly; -@@ -5713,9 +5713,6 @@ int md_run(struct mddev *mddev) +@@ -5764,9 +5764,6 @@ int md_run(struct mddev *mddev) md_update_sb(mddev, 0); md_new_event(mddev); @@ -65,8 +65,8 @@ Acked-by: NeilBrown - sysfs_notify(&mddev->kobj, NULL, "degraded"); return 0; - abort: -@@ -5736,6 +5733,7 @@ static int do_md_run(struct mddev *mddev + bitmap_abort: +@@ -5794,6 +5791,7 @@ static int do_md_run(struct mddev *mddev { int err; @@ -74,7 +74,7 @@ Acked-by: NeilBrown err = md_run(mddev); if (err) goto out; -@@ -5753,9 +5751,14 @@ static int do_md_run(struct mddev *mddev +@@ -5814,9 +5812,14 @@ static int do_md_run(struct mddev *mddev set_capacity(mddev->gendisk, mddev->array_sectors); revalidate_disk(mddev->gendisk); @@ -91,7 +91,7 @@ Acked-by: NeilBrown --- a/drivers/md/md.h +++ b/drivers/md/md.h -@@ -246,6 +246,9 @@ enum mddev_flags { +@@ -256,6 +256,9 @@ enum mddev_flags { MD_UPDATING_SB, /* md_check_recovery is updating the metadata * without explicitly holding reconfig_mutex. */ diff --git a/patches.suse/media-dib0700-fix-rc-endpoint-lookup.patch b/patches.suse/media-dib0700-fix-rc-endpoint-lookup.patch new file mode 100644 index 0000000..d928541 --- /dev/null +++ b/patches.suse/media-dib0700-fix-rc-endpoint-lookup.patch @@ -0,0 +1,50 @@ +From f52981019ad8d6718de79b425a574c6bddf81f7c Mon Sep 17 00:00:00 2001 +From: Johan Hovold +Date: Fri, 3 Jan 2020 17:35:12 +0100 +Subject: [PATCH] media: dib0700: fix rc endpoint lookup +Git-commit: f52981019ad8d6718de79b425a574c6bddf81f7c +Patch-mainline: v5.7-rc1 +References: bsc#1051510 + +Make sure to use the current alternate setting when verifying the +interface descriptors to avoid submitting an URB to an invalid endpoint. + +Failing to do so could cause the driver to misbehave or trigger a WARN() +in usb_submit_urb() that kernels with panic_on_warn set would choke on. + +Fixes: c4018fa2e4c0 ("[media] dib0700: fix RC support on Hauppauge Nova-TD") +Cc: stable # 3.16 +Signed-off-by: Johan Hovold +Signed-off-by: Sean Young +Signed-off-by: Mauro Carvalho Chehab +Acked-by: Takashi Iwai + +--- + drivers/media/usb/dvb-usb/dib0700_core.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/media/usb/dvb-usb/dib0700_core.c b/drivers/media/usb/dvb-usb/dib0700_core.c +index e53c58ab6488..ef62dd6c5ae4 100644 +--- a/drivers/media/usb/dvb-usb/dib0700_core.c ++++ b/drivers/media/usb/dvb-usb/dib0700_core.c +@@ -818,7 +818,7 @@ int dib0700_rc_setup(struct dvb_usb_device *d, struct usb_interface *intf) + + /* Starting in firmware 1.20, the RC info is provided on a bulk pipe */ + +- if (intf->altsetting[0].desc.bNumEndpoints < rc_ep + 1) ++ if (intf->cur_altsetting->desc.bNumEndpoints < rc_ep + 1) + return -ENODEV; + + purb = usb_alloc_urb(0, GFP_KERNEL); +@@ -838,7 +838,7 @@ int dib0700_rc_setup(struct dvb_usb_device *d, struct usb_interface *intf) + * Some devices like the Hauppauge NovaTD model 52009 use an interrupt + * endpoint, while others use a bulk one. + */ +- e = &intf->altsetting[0].endpoint[rc_ep].desc; ++ e = &intf->cur_altsetting->endpoint[rc_ep].desc; + if (usb_endpoint_dir_in(e)) { + if (usb_endpoint_xfer_bulk(e)) { + pipe = usb_rcvbulkpipe(d->udev, rc_ep); +-- +2.16.4 + diff --git a/patches.suse/media-go7007-Fix-URB-type-for-interrupt-handling.patch b/patches.suse/media-go7007-Fix-URB-type-for-interrupt-handling.patch new file mode 100644 index 0000000..7442b85 --- /dev/null +++ b/patches.suse/media-go7007-Fix-URB-type-for-interrupt-handling.patch @@ -0,0 +1,57 @@ +From a3ea410cac41b19a5490aad7fe6d9a9a772e646e Mon Sep 17 00:00:00 2001 +From: Takashi Iwai +Date: Thu, 6 Feb 2020 16:45:27 +0100 +Subject: [PATCH] media: go7007: Fix URB type for interrupt handling +Mime-version: 1.0 +Content-type: text/plain; charset=UTF-8 +Content-transfer-encoding: 8bit +Git-commit: a3ea410cac41b19a5490aad7fe6d9a9a772e646e +Patch-mainline: v5.7-rc1 +References: bsc#1051510 + +Josef reported that his old-and-good Plextor ConvertX M402U video +converter spews lots of WARNINGs on the recent kernels, and it turned +out that the device uses a bulk endpoint for interrupt handling just +like 2250 board. + +For fixing it, generalize the check with the proper verification of +the endpoint instead of hard-coded board type check. + +Fixes: 7e5219d18e93 ("[media] go7007: Fix 2250 urb type") +Reported-and-tested-by: Josef Möllers +Buglink: https://bugzilla.suse.com/show_bug.cgi?id=1162583 +Buglink: https://bugzilla.kernel.org/show_bug.cgi?id=206427 + +Signed-off-by: Takashi Iwai +Signed-off-by: Hans Verkuil +Signed-off-by: Mauro Carvalho Chehab + +--- + drivers/media/usb/go7007/go7007-usb.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/drivers/media/usb/go7007/go7007-usb.c b/drivers/media/usb/go7007/go7007-usb.c +index ff2aa057c1fb..f889c9d740cd 100644 +--- a/drivers/media/usb/go7007/go7007-usb.c ++++ b/drivers/media/usb/go7007/go7007-usb.c +@@ -1044,6 +1044,7 @@ static int go7007_usb_probe(struct usb_interface *intf, + struct go7007_usb *usb; + const struct go7007_usb_board *board; + struct usb_device *usbdev = interface_to_usbdev(intf); ++ struct usb_host_endpoint *ep; + unsigned num_i2c_devs; + char *name; + int video_pipe, i, v_urb_len; +@@ -1140,7 +1141,8 @@ static int go7007_usb_probe(struct usb_interface *intf, + if (usb->intr_urb->transfer_buffer == NULL) + goto allocfail; + +- if (go->board_id == GO7007_BOARDID_SENSORAY_2250) ++ ep = usb->usbdev->ep_in[4]; ++ if (usb_endpoint_type(&ep->desc) == USB_ENDPOINT_XFER_BULK) + usb_fill_bulk_urb(usb->intr_urb, usb->usbdev, + usb_rcvbulkpipe(usb->usbdev, 4), + usb->intr_urb->transfer_buffer, 2*sizeof(u16), +-- +2.16.4 + diff --git a/patches.suse/media-ov6650-Fix-.get_fmt-V4L2_SUBDEV_FORMAT_TRY-sup.patch b/patches.suse/media-ov6650-Fix-.get_fmt-V4L2_SUBDEV_FORMAT_TRY-sup.patch new file mode 100644 index 0000000..c3e3219 --- /dev/null +++ b/patches.suse/media-ov6650-Fix-.get_fmt-V4L2_SUBDEV_FORMAT_TRY-sup.patch @@ -0,0 +1,51 @@ +From 39034bb0c26b76a2c3abc54aa28c185f18b40c2f Mon Sep 17 00:00:00 2001 +From: Janusz Krzysztofik +Date: Tue, 3 Sep 2019 17:11:41 -0300 +Subject: [PATCH] media: ov6650: Fix .get_fmt() V4L2_SUBDEV_FORMAT_TRY support +Git-commit: 39034bb0c26b76a2c3abc54aa28c185f18b40c2f +Patch-mainline: v5.5-rc1 +References: bsc#1051510 + +Commit da298c6d98d5 ("[media] v4l2: replace video op g_mbus_fmt by pad +op get_fmt") converted a former ov6650_g_fmt() video operation callback +to an ov6650_get_fmt() pad operation callback. However, the converted +function disregards a format->which flag that pad operations should +obey and always returns active frame format settings. + +That can be fixed by always responding to V4L2_SUBDEV_FORMAT_TRY with +-EINVAL, or providing the response from a pad config argument, likely +updated by a former user call to V4L2_SUBDEV_FORMAT_TRY .set_fmt(). +Since implementation of the latter is trivial, go for it. + +Fixes: da298c6d98d5 ("[media] v4l2: replace video op g_mbus_fmt by pad op get_fmt") +Signed-off-by: Janusz Krzysztofik +Signed-off-by: Sakari Ailus +Signed-off-by: Mauro Carvalho Chehab +Acked-by: Takashi Iwai + +--- + drivers/media/i2c/soc_camera/ov6650.c | 12 +++++++++--- + 1 file changed, 9 insertions(+), 3 deletions(-) + +--- a/drivers/media/i2c/soc_camera/ov6650.c ++++ b/drivers/media/i2c/soc_camera/ov6650.c +@@ -524,10 +524,16 @@ static int ov6650_get_fmt(struct v4l2_su + *mf = ov6650_def_fmt; + + /* update media bus format code and frame size */ +- mf->width = priv->rect.width >> priv->half_scale; +- mf->height = priv->rect.height >> priv->half_scale; +- mf->code = priv->code; ++ if (format->which == V4L2_SUBDEV_FORMAT_TRY) { ++ mf->width = cfg->try_fmt.width; ++ mf->height = cfg->try_fmt.height; ++ mf->code = cfg->try_fmt.code; + ++ } else { ++ mf->width = priv->rect.width >> priv->half_scale; ++ mf->height = priv->rect.height >> priv->half_scale; ++ mf->code = priv->code; ++ } + return 0; + } + diff --git a/patches.suse/media-ov6650-Fix-some-format-attributes-not-under-co.patch b/patches.suse/media-ov6650-Fix-some-format-attributes-not-under-co.patch new file mode 100644 index 0000000..c718689 --- /dev/null +++ b/patches.suse/media-ov6650-Fix-some-format-attributes-not-under-co.patch @@ -0,0 +1,127 @@ +From 1c6a2b63095154bbf9e8f38d79487a728331bf65 Mon Sep 17 00:00:00 2001 +From: Janusz Krzysztofik +Date: Tue, 3 Sep 2019 17:11:40 -0300 +Subject: [PATCH] media: ov6650: Fix some format attributes not under control +Git-commit: 1c6a2b63095154bbf9e8f38d79487a728331bf65 +Patch-mainline: v5.5-rc1 +References: bsc#1051510 + +User arguments passed to .get/set_fmt() pad operation callbacks may +contain unsupported values. The driver takes control over frame size +and pixel code as well as colorspace and field attributes but has never +cared for remainig format attributes, i.e., ycbcr_enc, quantization +and xfer_func, introduced by commit 11ff030c7365 ("[media] +V4l2-mediabus: improve colorspace support"). Fix it. + +Set up a static v4l2_mbus_framefmt structure with attributes +initialized to reasonable defaults and use it for updating content of +user provided arguments. In case of V4L2_SUBDEV_FORMAT_ACTIVE, +postpone frame size update, now performed from inside ov6650_s_fmt() +helper, util the user argument is first updated in ov6650_set_fmt() with +default frame format content. For V4L2_SUBDEV_FORMAT_TRY, don't copy +all attributes to pad config, only those handled by the driver, then +fill the response with the default frame format updated with resulting +pad config format code and frame size. + +Fixes: 11ff030c7365 ("[media] v4l2-mediabus: improve colorspace support") +Signed-off-by: Janusz Krzysztofik +Signed-off-by: Sakari Ailus +Signed-off-by: Mauro Carvalho Chehab +Acked-by: Takashi Iwai + +--- + drivers/media/i2c/soc_camera/ov6650.c | 51 ++++++++++++++++++++++++++-------- + 1 file changed, 39 insertions(+), 12 deletions(-) + +--- a/drivers/media/i2c/soc_camera/ov6650.c ++++ b/drivers/media/i2c/soc_camera/ov6650.c +@@ -215,6 +215,17 @@ static u32 ov6650_codes[] = { + MEDIA_BUS_FMT_Y8_1X8, + }; + ++static const struct v4l2_mbus_framefmt ov6650_def_fmt = { ++ .width = W_CIF, ++ .height = H_CIF, ++ .code = MEDIA_BUS_FMT_SBGGR8_1X8, ++ .colorspace = V4L2_COLORSPACE_SRGB, ++ .field = V4L2_FIELD_NONE, ++ .ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT, ++ .quantization = V4L2_QUANTIZATION_DEFAULT, ++ .xfer_func = V4L2_XFER_FUNC_DEFAULT, ++}; ++ + /* read a register */ + static int ov6650_reg_read(struct i2c_client *client, u8 reg, u8 *val) + { +@@ -509,11 +520,13 @@ static int ov6650_get_fmt(struct v4l2_su + if (format->pad) + return -EINVAL; + ++ /* initialize response with default media bus frame format */ ++ *mf = ov6650_def_fmt; ++ ++ /* update media bus format code and frame size */ + mf->width = priv->rect.width >> priv->half_scale; + mf->height = priv->rect.height >> priv->half_scale; + mf->code = priv->code; +- mf->colorspace = V4L2_COLORSPACE_SRGB; +- mf->field = V4L2_FIELD_NONE; + + return 0; + } +@@ -673,10 +686,6 @@ static int ov6650_s_fmt(struct v4l2_subd + if (!ret) + ret = ov6650_reg_rmw(client, REG_COML, coml_set, coml_mask); + +- if (!ret) { +- mf->width = priv->rect.width >> half_scale; +- mf->height = priv->rect.height >> half_scale; +- } + return ret; + } + +@@ -695,9 +704,6 @@ static int ov6650_set_fmt(struct v4l2_su + v4l_bound_align_image(&mf->width, 2, W_CIF, 1, + &mf->height, 2, H_CIF, 1, 0); + +- mf->field = V4L2_FIELD_NONE; +- mf->colorspace = V4L2_COLORSPACE_SRGB; +- + switch (mf->code) { + case MEDIA_BUS_FMT_Y10_1X10: + mf->code = MEDIA_BUS_FMT_Y8_1X8; +@@ -714,10 +720,31 @@ static int ov6650_set_fmt(struct v4l2_su + break; + } + +- if (format->which == V4L2_SUBDEV_FORMAT_ACTIVE) +- return ov6650_s_fmt(sd, mf); +- cfg->try_fmt = *mf; ++ if (format->which == V4L2_SUBDEV_FORMAT_TRY) { ++ /* store media bus format code and frame size in pad config */ ++ cfg->try_fmt.width = mf->width; ++ cfg->try_fmt.height = mf->height; ++ cfg->try_fmt.code = mf->code; ++ ++ /* return default mbus frame format updated with pad config */ ++ *mf = ov6650_def_fmt; ++ mf->width = cfg->try_fmt.width; ++ mf->height = cfg->try_fmt.height; ++ mf->code = cfg->try_fmt.code; ++ ++ } else { ++ /* apply new media bus format code and frame size */ ++ int ret = ov6650_s_fmt(sd, mf); + ++ if (ret) ++ return ret; ++ ++ /* return default format updated with active size and code */ ++ *mf = ov6650_def_fmt; ++ mf->width = priv->rect.width >> priv->half_scale; ++ mf->height = priv->rect.height >> priv->half_scale; ++ mf->code = priv->code; ++ } + return 0; + } + diff --git a/patches.suse/media-ov6650-Fix-stored-crop-rectangle-not-in-sync-w.patch b/patches.suse/media-ov6650-Fix-stored-crop-rectangle-not-in-sync-w.patch new file mode 100644 index 0000000..4f05568 --- /dev/null +++ b/patches.suse/media-ov6650-Fix-stored-crop-rectangle-not-in-sync-w.patch @@ -0,0 +1,53 @@ +From 1463b371aff0682c70141f7521db13cc4bbf3016 Mon Sep 17 00:00:00 2001 +From: Janusz Krzysztofik +Date: Tue, 3 Sep 2019 17:11:44 -0300 +Subject: [PATCH] media: ov6650: Fix stored crop rectangle not in sync with hardware +Git-commit: 1463b371aff0682c70141f7521db13cc4bbf3016 +Patch-mainline: v5.5-rc1 +References: bsc#1051510 + +The driver stores crop rectangle settings supposed to be in line with +hardware state in a device private structure. Since the driver initial +submission, crop rectangle width and height settings are not updated +correctly when rectangle offset settings are applied on hardware. If +an error occurs while the device is updated, the stored settings my no +longer reflect hardware state and consecutive calls to .get_selection() +as well as .get/set_fmt() may return incorrect information. That in +turn may affect ability of a bridge device to use correct DMA transfer +settings if such incorrect informamtion on active frame format returned +by .get/set_fmt() is used. + +Assuming a failed update of the device means its actual settings haven't +changed, update crop rectangle width and height settings stored in the +device private structure correctly while the rectangle offset is +successfully applied on hardware so the stored values always reflect +actual hardware state to the extent possible. + +Fixes: 2f6e2404799a ("[media] SoC Camera: add driver for OV6650 sensor") +Signed-off-by: Janusz Krzysztofik +Signed-off-by: Sakari Ailus +Signed-off-by: Mauro Carvalho Chehab +Acked-by: Takashi Iwai + +--- + drivers/media/i2c/soc_camera/ov6650.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/drivers/media/i2c/soc_camera/ov6650.c ++++ b/drivers/media/i2c/soc_camera/ov6650.c +@@ -490,6 +490,7 @@ static int ov6650_set_selection(struct v + + ret = ov6650_reg_write(client, REG_HSTRT, sel->r.left >> 1); + if (!ret) { ++ priv->rect.width += priv->rect.left - sel->r.left; + priv->rect.left = sel->r.left; + ret = ov6650_reg_write(client, REG_HSTOP, + (sel->r.left + sel->r.width) >> 1); +@@ -499,6 +500,7 @@ static int ov6650_set_selection(struct v + ret = ov6650_reg_write(client, REG_VSTRT, sel->r.top >> 1); + } + if (!ret) { ++ priv->rect.height += priv->rect.top - sel->r.top; + priv->rect.top = sel->r.top; + ret = ov6650_reg_write(client, REG_VSTOP, + (sel->r.top + sel->r.height) >> 1); diff --git a/patches.suse/media-ov6650-Fix-stored-frame-format-not-in-sync-wit.patch b/patches.suse/media-ov6650-Fix-stored-frame-format-not-in-sync-wit.patch new file mode 100644 index 0000000..0888001 --- /dev/null +++ b/patches.suse/media-ov6650-Fix-stored-frame-format-not-in-sync-wit.patch @@ -0,0 +1,66 @@ +From 3143b459de4cdcce67b36827476c966e93c1cf01 Mon Sep 17 00:00:00 2001 +From: Janusz Krzysztofik +Date: Tue, 3 Sep 2019 17:11:43 -0300 +Subject: [PATCH] media: ov6650: Fix stored frame format not in sync with hardware +Git-commit: 3143b459de4cdcce67b36827476c966e93c1cf01 +Patch-mainline: v5.5-rc1 +References: bsc#1051510 + +The driver stores frame format settings supposed to be in line with +hardware state in a device private structure. Since the driver initial +submission, those settings are updated before they are actually applied +on hardware. If an error occurs on device update, the stored settings +my not reflect hardware state anymore and consecutive calls to +.get_fmt() may return incorrect information. That in turn may affect +ability of a bridge device to use correct DMA transfer settings if such +incorrect informmation on active frame format returned by .get_fmt() is +used. + +Assuming a failed device update means its state hasn't changed, update +frame format related settings stored in the device private structure +only after they are successfully applied so the stored values always +reflect hardware state as closely as possible. + +Fixes: 2f6e2404799a ("[media] SoC Camera: add driver for OV6650 sensor") +Signed-off-by: Janusz Krzysztofik +Signed-off-by: Sakari Ailus +Signed-off-by: Mauro Carvalho Chehab +Acked-by: Takashi Iwai + +--- + drivers/media/i2c/soc_camera/ov6650.c | 9 ++++++--- + 1 file changed, 6 insertions(+), 3 deletions(-) + +--- a/drivers/media/i2c/soc_camera/ov6650.c ++++ b/drivers/media/i2c/soc_camera/ov6650.c +@@ -628,7 +628,6 @@ static int ov6650_s_fmt(struct v4l2_subd + dev_err(&client->dev, "Pixel format not handled: 0x%x\n", code); + return -EINVAL; + } +- priv->code = code; + + if (code == MEDIA_BUS_FMT_Y8_1X8 || + code == MEDIA_BUS_FMT_SBGGR8_1X8) { +@@ -649,7 +648,6 @@ static int ov6650_s_fmt(struct v4l2_subd + dev_dbg(&client->dev, "max resolution: CIF\n"); + coma_mask |= COMA_QCIF; + } +- priv->half_scale = half_scale; + + if (sense) { + if (sense->master_clock == 8000000) { +@@ -689,8 +687,13 @@ static int ov6650_s_fmt(struct v4l2_subd + ret = ov6650_reg_rmw(client, REG_COMA, coma_set, coma_mask); + if (!ret) + ret = ov6650_reg_write(client, REG_CLKRC, clkrc); +- if (!ret) ++ if (!ret) { ++ priv->half_scale = half_scale; ++ + ret = ov6650_reg_rmw(client, REG_COML, coml_set, coml_mask); ++ } ++ if (!ret) ++ priv->code = code; + + return ret; + } diff --git a/patches.suse/media-tda10071-fix-unsigned-sign-extension-overflow.patch b/patches.suse/media-tda10071-fix-unsigned-sign-extension-overflow.patch new file mode 100644 index 0000000..7a090c9 --- /dev/null +++ b/patches.suse/media-tda10071-fix-unsigned-sign-extension-overflow.patch @@ -0,0 +1,52 @@ +From a7463e2dc698075132de9905b89f495df888bb79 Mon Sep 17 00:00:00 2001 +From: Colin Ian King +Date: Mon, 10 Feb 2020 15:26:46 +0100 +Subject: [PATCH] media: tda10071: fix unsigned sign extension overflow +Git-commit: a7463e2dc698075132de9905b89f495df888bb79 +Patch-mainline: v5.7-rc1 +References: bsc#1051510 + +The shifting of buf[3] by 24 bits to the left will be promoted to +a 32 bit signed int and then sign-extended to an unsigned long. In +the unlikely event that the the top bit of buf[3] is set then all +then all the upper bits end up as also being set because of +the sign-extension and this affect the ev->post_bit_error sum. +Fix this by using the temporary u32 variable bit_error to avoid +the sign-extension promotion. This also removes the need to do the +computation twice. + +Addresses-coverity: ("Unintended sign extension") + +Fixes: 267897a4708f ("[media] tda10071: implement DVBv5 statistics") +Signed-off-by: Colin Ian King +Signed-off-by: Sean Young +Signed-off-by: Mauro Carvalho Chehab +Acked-by: Takashi Iwai + +--- + drivers/media/dvb-frontends/tda10071.c | 9 +++++---- + 1 file changed, 5 insertions(+), 4 deletions(-) + +diff --git a/drivers/media/dvb-frontends/tda10071.c b/drivers/media/dvb-frontends/tda10071.c +index 1953b00b3e48..685c0ac71819 100644 +--- a/drivers/media/dvb-frontends/tda10071.c ++++ b/drivers/media/dvb-frontends/tda10071.c +@@ -470,10 +470,11 @@ static int tda10071_read_status(struct dvb_frontend *fe, enum fe_status *status) + goto error; + + if (dev->delivery_system == SYS_DVBS) { +- dev->dvbv3_ber = buf[0] << 24 | buf[1] << 16 | +- buf[2] << 8 | buf[3] << 0; +- dev->post_bit_error += buf[0] << 24 | buf[1] << 16 | +- buf[2] << 8 | buf[3] << 0; ++ u32 bit_error = buf[0] << 24 | buf[1] << 16 | ++ buf[2] << 8 | buf[3] << 0; ++ ++ dev->dvbv3_ber = bit_error; ++ dev->post_bit_error += bit_error; + c->post_bit_error.stat[0].scale = FE_SCALE_COUNTER; + c->post_bit_error.stat[0].uvalue = dev->post_bit_error; + dev->block_error += buf[4] << 8 | buf[5] << 0; +-- +2.16.4 + diff --git a/patches.suse/media-usbtv-fix-control-message-timeouts.patch b/patches.suse/media-usbtv-fix-control-message-timeouts.patch new file mode 100644 index 0000000..153ce11 --- /dev/null +++ b/patches.suse/media-usbtv-fix-control-message-timeouts.patch @@ -0,0 +1,70 @@ +From 536f561d871c5781bc33d26d415685211b94032e Mon Sep 17 00:00:00 2001 +From: Johan Hovold +Date: Mon, 13 Jan 2020 18:18:18 +0100 +Subject: [PATCH] media: usbtv: fix control-message timeouts +Git-commit: 536f561d871c5781bc33d26d415685211b94032e +Patch-mainline: v5.7-rc1 +References: bsc#1051510 + +The driver was issuing synchronous uninterruptible control requests +without using a timeout. This could lead to the driver hanging on +various user requests due to a malfunctioning (or malicious) device +until the device is physically disconnected. + +The USB upper limit of five seconds per request should be more than +enough. + +Fixes: f3d27f34fdd7 ("[media] usbtv: Add driver for Fushicai USBTV007 video frame grabber") +Fixes: c53a846c48f2 ("[media] usbtv: add video controls") +Cc: stable # 3.11 +Signed-off-by: Johan Hovold +Acked-by: Lubomir Rintel +Reviewed-by: Greg Kroah-Hartman +Signed-off-by: Hans Verkuil +Signed-off-by: Mauro Carvalho Chehab +Acked-by: Takashi Iwai + +--- + drivers/media/usb/usbtv/usbtv-core.c | 2 +- + drivers/media/usb/usbtv/usbtv-video.c | 5 +++-- + 2 files changed, 4 insertions(+), 3 deletions(-) + +diff --git a/drivers/media/usb/usbtv/usbtv-core.c b/drivers/media/usb/usbtv/usbtv-core.c +index 5095c380b2c1..ee9c656d121f 100644 +--- a/drivers/media/usb/usbtv/usbtv-core.c ++++ b/drivers/media/usb/usbtv/usbtv-core.c +@@ -56,7 +56,7 @@ int usbtv_set_regs(struct usbtv *usbtv, const u16 regs[][2], int size) + + ret = usb_control_msg(usbtv->udev, pipe, USBTV_REQUEST_REG, + USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, +- value, index, NULL, 0, 0); ++ value, index, NULL, 0, USB_CTRL_GET_TIMEOUT); + if (ret < 0) + return ret; + } +diff --git a/drivers/media/usb/usbtv/usbtv-video.c b/drivers/media/usb/usbtv/usbtv-video.c +index 3d9284a09ee5..b249f037900c 100644 +--- a/drivers/media/usb/usbtv/usbtv-video.c ++++ b/drivers/media/usb/usbtv/usbtv-video.c +@@ -800,7 +800,8 @@ static int usbtv_s_ctrl(struct v4l2_ctrl *ctrl) + ret = usb_control_msg(usbtv->udev, + usb_rcvctrlpipe(usbtv->udev, 0), USBTV_CONTROL_REG, + USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, +- 0, USBTV_BASE + 0x0244, (void *)data, 3, 0); ++ 0, USBTV_BASE + 0x0244, (void *)data, 3, ++ USB_CTRL_GET_TIMEOUT); + if (ret < 0) + goto error; + } +@@ -851,7 +852,7 @@ static int usbtv_s_ctrl(struct v4l2_ctrl *ctrl) + ret = usb_control_msg(usbtv->udev, usb_sndctrlpipe(usbtv->udev, 0), + USBTV_CONTROL_REG, + USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, +- 0, index, (void *)data, size, 0); ++ 0, index, (void *)data, size, USB_CTRL_SET_TIMEOUT); + + error: + if (ret < 0) +-- +2.16.4 + diff --git a/patches.suse/media-uvcvideo-Refactor-teardown-of-uvc-on-USB-disconnect.patch b/patches.suse/media-uvcvideo-Refactor-teardown-of-uvc-on-USB-disconnect.patch new file mode 100644 index 0000000..356668f --- /dev/null +++ b/patches.suse/media-uvcvideo-Refactor-teardown-of-uvc-on-USB-disconnect.patch @@ -0,0 +1,179 @@ +From 10e1fdb95809ed21406f53b5b4f064673a1b9ceb Mon Sep 17 00:00:00 2001 +From: Daniel Axtens +Date: Sun, 23 Apr 2017 00:53:49 -0400 +Subject: [PATCH] media: uvcvideo: Refactor teardown of uvc on USB disconnect + +References: bsc#1164507 +Patch-mainline: v5.0-rc1 +Git-commit: 10e1fdb95809ed21406f53b5b4f064673a1b9ceb + +Currently, disconnecting a USB webcam while it is in use prints out a +number of warnings, such as: + +WARNING: CPU: 2 PID: 3118 at /build/linux-ezBi1T/linux-4.8.0/fs/sysfs/group.c:237 sysfs_remove_group+0x8b/0x90 +sysfs group ffffffffa7cd0780 not found for kobject 'event13' + +This has been noticed before. [0] + +This is because of the order in which things are torn down. + +If there are no streams active during a USB disconnect: + + - uvc_disconnect() is invoked via device_del() through the bus + notifier mechanism. + + - this calls uvc_unregister_video(). + + - uvc_unregister_video() unregisters the video device for each + stream, + + - because there are no streams open, it calls uvc_delete() + + - uvc_delete() calls uvc_status_cleanup(), which cleans up the status + input device. + + - uvc_delete() calls media_device_unregister(), which cleans up the + media device + + - uvc_delete(), uvc_unregister_video() and uvc_disconnect() all + return, and we end up back in device_del(). + + - device_del() then cleans up the sysfs folder for the camera with + dpm_sysfs_remove(). Because uvc_status_cleanup() and + media_device_unregister() have already been called, this all works + nicely. + +If, on the other hand, there *are* streams active during a USB disconnect: + + - uvc_disconnect() is invoked + + - this calls uvc_unregister_video() + + - uvc_unregister_video() unregisters the video device for each + stream, + + - uvc_unregister_video() and uvc_disconnect() return, and we end up + back in device_del(). + + - device_del() then cleans up the sysfs folder for the camera with + dpm_sysfs_remove(). Because the status input device and the media + device are children of the USB device, this also deletes their + sysfs folders. + + - Sometime later, the final stream is closed, invoking uvc_release(). + + - uvc_release() calls uvc_delete() + + - uvc_delete() calls uvc_status_cleanup(), which cleans up the status + input device. Because the sysfs directory has already been removed, + this causes a WARNing. + + - uvc_delete() calls media_device_unregister(), which cleans up the + media device. Because the sysfs directory has already been removed, + this causes another WARNing. + +To fix this, we need to make sure the devices are always unregistered +before the end of uvc_disconnect(). To this, move the unregistration +into the disconnect path: + + - split uvc_status_cleanup() into two parts, one on disconnect that + unregisters and one on delete that frees. + + - move v4l2_device_unregister() and media_device_unregister() into + the disconnect path. + +[0]: https://lkml.org/lkml/2016/12/8/657 + +[Renamed uvc_input_cleanup() to uvc_input_unregister()] + +Signed-off-by: Daniel Axtens +Reviewed-by: gfigueira@suse.com +Acked-by: Greg Kroah-Hartman +Signed-off-by: Laurent Pinchart +Signed-off-by: Mauro Carvalho Chehab +Acked-by: Michal Suchanek +--- + drivers/media/usb/uvc/uvc_driver.c | 13 +++++++++---- + drivers/media/usb/uvc/uvc_status.c | 12 ++++++++---- + drivers/media/usb/uvc/uvcvideo.h | 1 + + 3 files changed, 18 insertions(+), 8 deletions(-) + +--- a/drivers/media/usb/uvc/uvc_driver.c ++++ b/drivers/media/usb/uvc/uvc_driver.c +@@ -1812,11 +1812,7 @@ static void uvc_delete(struct uvc_device + usb_put_intf(dev->intf); + usb_put_dev(dev->udev); + +- if (dev->vdev.dev) +- v4l2_device_unregister(&dev->vdev); + #ifdef CONFIG_MEDIA_CONTROLLER +- if (media_devnode_is_registered(dev->mdev.devnode)) +- media_device_unregister(&dev->mdev); + media_device_cleanup(&dev->mdev); + #endif + +@@ -1884,6 +1880,15 @@ static void uvc_unregister_video(struct + uvc_debugfs_cleanup_stream(stream); + } + ++ uvc_status_unregister(dev); ++ ++ if (dev->vdev.dev) ++ v4l2_device_unregister(&dev->vdev); ++#ifdef CONFIG_MEDIA_CONTROLLER ++ if (media_devnode_is_registered(dev->mdev.devnode)) ++ media_device_unregister(&dev->mdev); ++#endif ++ + /* Decrement the stream count and call uvc_delete explicitly if there + * are no stream left. + */ +--- a/drivers/media/usb/uvc/uvc_status.c ++++ b/drivers/media/usb/uvc/uvc_status.c +@@ -54,7 +54,7 @@ error: + return ret; + } + +-static void uvc_input_cleanup(struct uvc_device *dev) ++static void uvc_input_unregister(struct uvc_device *dev) + { + if (dev->input) + input_unregister_device(dev->input); +@@ -71,7 +71,7 @@ static void uvc_input_report_key(struct + + #else + #define uvc_input_init(dev) +-#define uvc_input_cleanup(dev) ++#define uvc_input_unregister(dev) + #define uvc_input_report_key(dev, code, value) + #endif /* CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV */ + +@@ -198,12 +198,16 @@ int uvc_status_init(struct uvc_device *d + return 0; + } + +-void uvc_status_cleanup(struct uvc_device *dev) ++void uvc_status_unregister(struct uvc_device *dev) + { + usb_kill_urb(dev->int_urb); ++ uvc_input_unregister(dev); ++} ++ ++void uvc_status_cleanup(struct uvc_device *dev) ++{ + usb_free_urb(dev->int_urb); + kfree(dev->status); +- uvc_input_cleanup(dev); + } + + int uvc_status_start(struct uvc_device *dev, gfp_t flags) +--- a/drivers/media/usb/uvc/uvcvideo.h ++++ b/drivers/media/usb/uvc/uvcvideo.h +@@ -712,6 +712,7 @@ void uvc_video_clock_update(struct uvc_s + + /* Status */ + extern int uvc_status_init(struct uvc_device *dev); ++void uvc_status_unregister(struct uvc_device *dev); + extern void uvc_status_cleanup(struct uvc_device *dev); + extern int uvc_status_start(struct uvc_device *dev, gfp_t flags); + extern void uvc_status_stop(struct uvc_device *dev); diff --git a/patches.suse/media-v4l-event-Add-subscription-to-list-before-call.patch b/patches.suse/media-v4l-event-Add-subscription-to-list-before-call.patch new file mode 100644 index 0000000..183d87d --- /dev/null +++ b/patches.suse/media-v4l-event-Add-subscription-to-list-before-call.patch @@ -0,0 +1,116 @@ +From 92539d3eda2c090b382699bbb896d4b54e9bdece Mon Sep 17 00:00:00 2001 +From: Sakari Ailus +Date: Mon, 5 Nov 2018 09:35:44 -0500 +Subject: [PATCH] media: v4l: event: Add subscription to list before calling "add" operation +Git-commit: 92539d3eda2c090b382699bbb896d4b54e9bdece +Patch-mainline: v4.20-rc4 +References: CVE-2019-9458 bsc#1168295 + +Patch ad608fbcf166 changed how events were subscribed to address an issue +elsewhere. As a side effect of that change, the "add" callback was called +before the event subscription was added to the list of subscribed events, +causing the first event queued by the add callback (and possibly other +events arriving soon afterwards) to be lost. + +Fix this by adding the subscription to the list before calling the "add" +callback, and clean up afterwards if that fails. + +Fixes: ad608fbcf166 ("media: v4l: event: Prevent freeing event subscriptions while accessed") + +Reported-by: Dave Stevenson +Signed-off-by: Sakari Ailus +Tested-by: Dave Stevenson +Reviewed-by: Hans Verkuil +Tested-by: Hans Verkuil +Cc: stable@vger.kernel.org (for 4.14 and up) +Signed-off-by: Mauro Carvalho Chehab +Acked-by: Takashi Iwai + +--- + drivers/media/v4l2-core/v4l2-event.c | 44 +++++++++++++++++++---------------- + 1 file changed, 24 insertions(+), 20 deletions(-) + +--- a/drivers/media/v4l2-core/v4l2-event.c ++++ b/drivers/media/v4l2-core/v4l2-event.c +@@ -192,6 +192,22 @@ int v4l2_event_pending(struct v4l2_fh *f + } + EXPORT_SYMBOL_GPL(v4l2_event_pending); + ++static void __v4l2_event_unsubscribe(struct v4l2_subscribed_event *sev) ++{ ++ struct v4l2_fh *fh = sev->fh; ++ unsigned int i; ++ ++ lockdep_assert_held(&fh->subscribe_lock); ++ assert_spin_locked(&fh->vdev->fh_lock); ++ ++ /* Remove any pending events for this subscription */ ++ for (i = 0; i < sev->in_use; i++) { ++ list_del(&sev->events[sev_pos(sev, i)].list); ++ fh->navailable--; ++ } ++ list_del(&sev->list); ++} ++ + int v4l2_event_subscribe(struct v4l2_fh *fh, + const struct v4l2_event_subscription *sub, unsigned elems, + const struct v4l2_subscribed_event_ops *ops) +@@ -223,27 +239,22 @@ int v4l2_event_subscribe(struct v4l2_fh + + spin_lock_irqsave(&fh->vdev->fh_lock, flags); + found_ev = v4l2_event_subscribed(fh, sub->type, sub->id); ++ if (!found_ev) ++ list_add(&sev->list, &fh->subscribed); + spin_unlock_irqrestore(&fh->vdev->fh_lock, flags); + + if (found_ev) { +- /* Already listening */ + kfree(sev); +- goto out_unlock; +- } +- +- if (sev->ops && sev->ops->add) { ++ } else if (sev->ops && sev->ops->add) { + ret = sev->ops->add(sev, elems); + if (ret) { ++ spin_lock_irqsave(&fh->vdev->fh_lock, flags); ++ __v4l2_event_unsubscribe(sev); ++ spin_unlock_irqrestore(&fh->vdev->fh_lock, flags); + kfree(sev); +- goto out_unlock; + } + } + +- spin_lock_irqsave(&fh->vdev->fh_lock, flags); +- list_add(&sev->list, &fh->subscribed); +- spin_unlock_irqrestore(&fh->vdev->fh_lock, flags); +- +-out_unlock: + mutex_unlock(&fh->subscribe_lock); + + return ret; +@@ -278,7 +289,6 @@ int v4l2_event_unsubscribe(struct v4l2_f + { + struct v4l2_subscribed_event *sev; + unsigned long flags; +- int i; + + if (sub->type == V4L2_EVENT_ALL) { + v4l2_event_unsubscribe_all(fh); +@@ -290,14 +300,8 @@ int v4l2_event_unsubscribe(struct v4l2_f + spin_lock_irqsave(&fh->vdev->fh_lock, flags); + + sev = v4l2_event_subscribed(fh, sub->type, sub->id); +- if (sev != NULL) { +- /* Remove any pending events for this subscription */ +- for (i = 0; i < sev->in_use; i++) { +- list_del(&sev->events[sev_pos(sev, i)].list); +- fh->navailable--; +- } +- list_del(&sev->list); +- } ++ if (sev != NULL) ++ __v4l2_event_unsubscribe(sev); + + spin_unlock_irqrestore(&fh->vdev->fh_lock, flags); + diff --git a/patches.suse/media-v4l-event-Prevent-freeing-event-subscriptions-.patch b/patches.suse/media-v4l-event-Prevent-freeing-event-subscriptions-.patch new file mode 100644 index 0000000..cd8b51c --- /dev/null +++ b/patches.suse/media-v4l-event-Prevent-freeing-event-subscriptions-.patch @@ -0,0 +1,168 @@ +From ad608fbcf166fec809e402d548761768f602702c Mon Sep 17 00:00:00 2001 +From: Sakari Ailus +Date: Tue, 11 Sep 2018 05:32:37 -0400 +Subject: [PATCH] media: v4l: event: Prevent freeing event subscriptions while accessed +Git-commit: ad608fbcf166fec809e402d548761768f602702c +Patch-mainline: v4.19-rc7 +References: CVE-2019-9458 bsc#1168295 + +The event subscriptions are added to the subscribed event list while +holding a spinlock, but that lock is subsequently released while still +accessing the subscription object. This makes it possible to unsubscribe +the event --- and freeing the subscription object's memory --- while +the subscription object is simultaneously accessed. + +Prevent this by adding a mutex to serialise the event subscription and +unsubscription. This also gives a guarantee to the callback ops that the +add op has returned before the del op is called. + +This change also results in making the elems field less special: +subscriptions are only added to the event list once they are fully +initialised. + +Signed-off-by: Sakari Ailus +Reviewed-by: Hans Verkuil +Reviewed-by: Laurent Pinchart +Cc: stable@vger.kernel.org # for 4.14 and up +Fixes: c3b5b0241f62 ("V4L/DVB: V4L: Events: Add backend") +Signed-off-by: Mauro Carvalho Chehab +Acked-by: Takashi Iwai + +--- + drivers/media/v4l2-core/v4l2-event.c | 38 ++++++++++++++++++----------------- + drivers/media/v4l2-core/v4l2-fh.c | 2 + + include/media/v4l2-fh.h | 4 +++ + 3 files changed, 26 insertions(+), 18 deletions(-) + +--- a/drivers/media/v4l2-core/v4l2-event.c ++++ b/drivers/media/v4l2-core/v4l2-event.c +@@ -114,14 +114,6 @@ static void __v4l2_event_queue_fh(struct + if (sev == NULL) + return; + +- /* +- * If the event has been added to the fh->subscribed list, but its +- * add op has not completed yet elems will be 0, treat this as +- * not being subscribed. +- */ +- if (!sev->elems) +- return; +- + /* Increase event sequence number on fh. */ + fh->sequence++; + +@@ -207,6 +199,7 @@ int v4l2_event_subscribe(struct v4l2_fh + struct v4l2_subscribed_event *sev, *found_ev; + unsigned long flags; + unsigned i; ++ int ret = 0; + + if (sub->type == V4L2_EVENT_ALL) + return -EINVAL; +@@ -224,31 +217,36 @@ int v4l2_event_subscribe(struct v4l2_fh + sev->flags = sub->flags; + sev->fh = fh; + sev->ops = ops; ++ sev->elems = elems; ++ ++ mutex_lock(&fh->subscribe_lock); + + spin_lock_irqsave(&fh->vdev->fh_lock, flags); + found_ev = v4l2_event_subscribed(fh, sub->type, sub->id); +- if (!found_ev) +- list_add(&sev->list, &fh->subscribed); + spin_unlock_irqrestore(&fh->vdev->fh_lock, flags); + + if (found_ev) { ++ /* Already listening */ + kfree(sev); +- return 0; /* Already listening */ ++ goto out_unlock; + } + + if (sev->ops && sev->ops->add) { +- int ret = sev->ops->add(sev, elems); ++ ret = sev->ops->add(sev, elems); + if (ret) { +- sev->ops = NULL; +- v4l2_event_unsubscribe(fh, sub); +- return ret; ++ kfree(sev); ++ goto out_unlock; + } + } + +- /* Mark as ready for use */ +- sev->elems = elems; ++ spin_lock_irqsave(&fh->vdev->fh_lock, flags); ++ list_add(&sev->list, &fh->subscribed); ++ spin_unlock_irqrestore(&fh->vdev->fh_lock, flags); ++ ++out_unlock: ++ mutex_unlock(&fh->subscribe_lock); + +- return 0; ++ return ret; + } + EXPORT_SYMBOL_GPL(v4l2_event_subscribe); + +@@ -287,6 +285,8 @@ int v4l2_event_unsubscribe(struct v4l2_f + return 0; + } + ++ mutex_lock(&fh->subscribe_lock); ++ + spin_lock_irqsave(&fh->vdev->fh_lock, flags); + + sev = v4l2_event_subscribed(fh, sub->type, sub->id); +@@ -304,6 +304,8 @@ int v4l2_event_unsubscribe(struct v4l2_f + if (sev && sev->ops && sev->ops->del) + sev->ops->del(sev); + ++ mutex_unlock(&fh->subscribe_lock); ++ + kfree(sev); + + return 0; +--- a/drivers/media/v4l2-core/v4l2-fh.c ++++ b/drivers/media/v4l2-core/v4l2-fh.c +@@ -45,6 +45,7 @@ void v4l2_fh_init(struct v4l2_fh *fh, st + INIT_LIST_HEAD(&fh->available); + INIT_LIST_HEAD(&fh->subscribed); + fh->sequence = -1; ++ mutex_init(&fh->subscribe_lock); + } + EXPORT_SYMBOL_GPL(v4l2_fh_init); + +@@ -90,6 +91,7 @@ void v4l2_fh_exit(struct v4l2_fh *fh) + return; + v4l_disable_media_source(fh->vdev); + v4l2_event_unsubscribe_all(fh); ++ mutex_destroy(&fh->subscribe_lock); + fh->vdev = NULL; + } + EXPORT_SYMBOL_GPL(v4l2_fh_exit); +--- a/include/media/v4l2-fh.h ++++ b/include/media/v4l2-fh.h +@@ -37,10 +37,13 @@ struct v4l2_ctrl_handler; + * @prio: priority of the file handler, as defined by &enum v4l2_priority + * + * @wait: event' s wait queue ++ * @subscribe_lock: serialise changes to the subscribed list; guarantee that ++ * the add and del event callbacks are orderly called + * @subscribed: list of subscribed events + * @available: list of events waiting to be dequeued + * @navailable: number of available events at @available list + * @sequence: event sequence number ++ * + * @m2m_ctx: pointer to &struct v4l2_m2m_ctx + */ + struct v4l2_fh { +@@ -51,6 +54,7 @@ struct v4l2_fh { + + /* Events */ + wait_queue_head_t wait; ++ struct mutex subscribe_lock; + struct list_head subscribed; + struct list_head available; + unsigned int navailable; diff --git a/patches.suse/media-v4l2-core-fix-entity-initialization-in-device_.patch b/patches.suse/media-v4l2-core-fix-entity-initialization-in-device_.patch new file mode 100644 index 0000000..118ae3c --- /dev/null +++ b/patches.suse/media-v4l2-core-fix-entity-initialization-in-device_.patch @@ -0,0 +1,62 @@ +From aead0ffbf078e0098ca6cfd1625029ff9347b10d Mon Sep 17 00:00:00 2001 +From: Eugen Hristev +Date: Wed, 26 Feb 2020 16:28:16 +0100 +Subject: [PATCH] media: v4l2-core: fix entity initialization in device_register_subdev +Git-commit: aead0ffbf078e0098ca6cfd1625029ff9347b10d +Patch-mainline: v5.7-rc1 +References: bsc#1051510 + +The entity variable was being initialized in the wrong place, before the +parameters have been checked. +To solve this, completely removed the entity variable and replaced it +with the initialization value : &sd->entity. +This will avoid dereferencing 'sd' pointer before it's being checked if +it's NULL. + +Fixes: 61f5db549dde ("[media] v4l: Make v4l2_subdev inherit from media_entity") + +Signed-off-by: Eugen Hristev +Acked-by: Sakari Ailus +Signed-off-by: Hans Verkuil +Signed-off-by: Mauro Carvalho Chehab +Acked-by: Takashi Iwai + +--- + drivers/media/v4l2-core/v4l2-device.c | 7 ++----- + 1 file changed, 2 insertions(+), 5 deletions(-) + +diff --git a/drivers/media/v4l2-core/v4l2-device.c b/drivers/media/v4l2-core/v4l2-device.c +index 41da73ce2e98..c69941214bb2 100644 +--- a/drivers/media/v4l2-core/v4l2-device.c ++++ b/drivers/media/v4l2-core/v4l2-device.c +@@ -111,9 +111,6 @@ EXPORT_SYMBOL_GPL(v4l2_device_unregister); + int v4l2_device_register_subdev(struct v4l2_device *v4l2_dev, + struct v4l2_subdev *sd) + { +-#if defined(CONFIG_MEDIA_CONTROLLER) +- struct media_entity *entity = &sd->entity; +-#endif + int err; + + /* Check for valid input */ +@@ -143,7 +140,7 @@ int v4l2_device_register_subdev(struct v4l2_device *v4l2_dev, + #if defined(CONFIG_MEDIA_CONTROLLER) + /* Register the entity. */ + if (v4l2_dev->mdev) { +- err = media_device_register_entity(v4l2_dev->mdev, entity); ++ err = media_device_register_entity(v4l2_dev->mdev, &sd->entity); + if (err < 0) + goto error_module; + } +@@ -163,7 +160,7 @@ int v4l2_device_register_subdev(struct v4l2_device *v4l2_dev, + + error_unregister: + #if defined(CONFIG_MEDIA_CONTROLLER) +- media_device_unregister_entity(entity); ++ media_device_unregister_entity(&sd->entity); + #endif + error_module: + if (!sd->owner_v4l2_dev) +-- +2.16.4 + diff --git a/patches.suse/media-vsp1-tidyup-VI6_HGT_LBn_H-macro.patch b/patches.suse/media-vsp1-tidyup-VI6_HGT_LBn_H-macro.patch new file mode 100644 index 0000000..29a2117 --- /dev/null +++ b/patches.suse/media-vsp1-tidyup-VI6_HGT_LBn_H-macro.patch @@ -0,0 +1,46 @@ +From bd59f412d17f81a41e35c884d3caacf34c9e4940 Mon Sep 17 00:00:00 2001 +From: Kuninori Morimoto +Date: Tue, 10 Dec 2019 22:55:57 -0300 +Subject: [PATCH] media: vsp1: tidyup VI6_HGT_LBn_H() macro +Git-commit: bd59f412d17f81a41e35c884d3caacf34c9e4940 +Patch-mainline: v5.7-rc1 +References: bsc#1051510 + +The address of VSP2_VI6_HGT_LBx_H are + VSP2_VI6_HGT_LB0_H : 0x3428 + VSP2_VI6_HGT_LB1_H : 0x3430 + VSP2_VI6_HGT_LB2_H : 0x3438 + VSP2_VI6_HGT_LB3_H : 0x3440 + +Thus, VI6_HGT_LBn_H() macro should start from 0x3420 instead of 0x3430. +This patch fixes it. + +Fixes: 26e0ca22c3b8 ("[media] v4l: Renesas R-Car VSP1 driver") + +Reported-by: Koji Matsuoka +Signed-off-by: Kuninori Morimoto +Reviewed-by: Kieran Bingham +Signed-off-by: Laurent Pinchart +Signed-off-by: Mauro Carvalho Chehab +Acked-by: Takashi Iwai + +--- + drivers/media/platform/vsp1/vsp1_regs.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/media/platform/vsp1/vsp1_regs.h b/drivers/media/platform/vsp1/vsp1_regs.h +index 5c67ff92d97a..fe3130db1fa2 100644 +--- a/drivers/media/platform/vsp1/vsp1_regs.h ++++ b/drivers/media/platform/vsp1/vsp1_regs.h +@@ -706,7 +706,7 @@ + #define VI6_HGT_HUE_AREA_LOWER_SHIFT 16 + #define VI6_HGT_HUE_AREA_UPPER_SHIFT 0 + #define VI6_HGT_LB_TH 0x3424 +-#define VI6_HGT_LBn_H(n) (0x3438 + (n) * 8) ++#define VI6_HGT_LBn_H(n) (0x3428 + (n) * 8) + #define VI6_HGT_LBn_V(n) (0x342c + (n) * 8) + #define VI6_HGT_HISTO(m, n) (0x3450 + (m) * 128 + (n) * 4) + #define VI6_HGT_MAXMIN 0x3750 +-- +2.16.4 + diff --git a/patches.suse/media-xirlink_cit-add-missing-descriptor-sanity-chec.patch b/patches.suse/media-xirlink_cit-add-missing-descriptor-sanity-chec.patch new file mode 100644 index 0000000..c0590c1 --- /dev/null +++ b/patches.suse/media-xirlink_cit-add-missing-descriptor-sanity-chec.patch @@ -0,0 +1,86 @@ +From a246b4d547708f33ff4d4b9a7a5dbac741dc89d8 Mon Sep 17 00:00:00 2001 +From: Johan Hovold +Date: Fri, 3 Jan 2020 17:35:11 +0100 +Subject: [PATCH] media: xirlink_cit: add missing descriptor sanity checks +Git-commit: a246b4d547708f33ff4d4b9a7a5dbac741dc89d8 +Patch-mainline: v5.7-rc1 +References: bsc#1051510 + +Make sure to check that we have two alternate settings and at least one +endpoint before accessing the second altsetting structure and +dereferencing the endpoint arrays. + +This specifically avoids dereferencing NULL-pointers or corrupting +memory when a device does not have the expected descriptors. + +Note that the sanity check in cit_get_packet_size() is not redundant as +the driver is mixing looking up altsettings by index and by number, +which may not coincide. + +Fixes: 659fefa0eb17 ("V4L/DVB: gspca_xirlink_cit: Add support for camera with a bcd version of 0.01") +Fixes: 59f8b0bf3c12 ("V4L/DVB: gspca_xirlink_cit: support bandwidth changing for devices with 1 alt setting") +Cc: stable # 2.6.37 +Cc: Hans de Goede +Signed-off-by: Johan Hovold +Signed-off-by: Hans Verkuil +Signed-off-by: Mauro Carvalho Chehab +Acked-by: Takashi Iwai + +--- + drivers/media/usb/gspca/xirlink_cit.c | 18 +++++++++++++++++- + 1 file changed, 17 insertions(+), 1 deletion(-) + +diff --git a/drivers/media/usb/gspca/xirlink_cit.c b/drivers/media/usb/gspca/xirlink_cit.c +index 934a90bd78c2..c579b100f066 100644 +--- a/drivers/media/usb/gspca/xirlink_cit.c ++++ b/drivers/media/usb/gspca/xirlink_cit.c +@@ -1442,6 +1442,9 @@ static int cit_get_packet_size(struct gspca_dev *gspca_dev) + return -EIO; + } + ++ if (alt->desc.bNumEndpoints < 1) ++ return -ENODEV; ++ + return le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize); + } + +@@ -2626,6 +2629,7 @@ static int sd_start(struct gspca_dev *gspca_dev) + + static int sd_isoc_init(struct gspca_dev *gspca_dev) + { ++ struct usb_interface_cache *intfc; + struct usb_host_interface *alt; + int max_packet_size; + +@@ -2641,8 +2645,17 @@ static int sd_isoc_init(struct gspca_dev *gspca_dev) + break; + } + ++ intfc = gspca_dev->dev->actconfig->intf_cache[0]; ++ ++ if (intfc->num_altsetting < 2) ++ return -ENODEV; ++ ++ alt = &intfc->altsetting[1]; ++ ++ if (alt->desc.bNumEndpoints < 1) ++ return -ENODEV; ++ + /* Start isoc bandwidth "negotiation" at max isoc bandwidth */ +- alt = &gspca_dev->dev->actconfig->intf_cache[0]->altsetting[1]; + alt->endpoint[0].desc.wMaxPacketSize = cpu_to_le16(max_packet_size); + + return 0; +@@ -2665,6 +2678,9 @@ static int sd_isoc_nego(struct gspca_dev *gspca_dev) + break; + } + ++ /* ++ * Existence of altsetting and endpoint was verified in sd_isoc_init() ++ */ + alt = &gspca_dev->dev->actconfig->intf_cache[0]->altsetting[1]; + packet_size = le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize); + if (packet_size <= min_packet_size) +-- +2.16.4 + diff --git a/patches.suse/mfd-dln2-Fix-sanity-checking-for-endpoints.patch b/patches.suse/mfd-dln2-Fix-sanity-checking-for-endpoints.patch new file mode 100644 index 0000000..bd30d63 --- /dev/null +++ b/patches.suse/mfd-dln2-Fix-sanity-checking-for-endpoints.patch @@ -0,0 +1,61 @@ +From fb945c95a482200876993977008b67ea658bd938 Mon Sep 17 00:00:00 2001 +From: Andy Shevchenko +Date: Wed, 26 Feb 2020 16:51:58 +0200 +Subject: [PATCH] mfd: dln2: Fix sanity checking for endpoints +Git-commit: fb945c95a482200876993977008b67ea658bd938 +Patch-mainline: v5.7-rc1 +References: bsc#1051510 + +While the commit 2b8bd606b1e6 ("mfd: dln2: More sanity checking for endpoints") +tries to harden the sanity checks it made at the same time a regression, +i.e. mixed in and out endpoints. Obviously it should have been not tested on +real hardware at that time, but unluckily it didn't happen. + +So, fix above mentioned typo and make device being enumerated again. + +While here, introduce an enumerator for magic values to prevent similar issue +to happen in the future. + +Fixes: 2b8bd606b1e6 ("mfd: dln2: More sanity checking for endpoints") +Cc: Oliver Neukum +Cc: Greg Kroah-Hartman +Signed-off-by: Andy Shevchenko +Signed-off-by: Lee Jones +Acked-by: Takashi Iwai + +--- + drivers/mfd/dln2.c | 9 +++++++-- + 1 file changed, 7 insertions(+), 2 deletions(-) + +diff --git a/drivers/mfd/dln2.c b/drivers/mfd/dln2.c +index 7841c11411d0..4faa8d2e5d04 100644 +--- a/drivers/mfd/dln2.c ++++ b/drivers/mfd/dln2.c +@@ -90,6 +90,11 @@ struct dln2_mod_rx_slots { + spinlock_t lock; + }; + ++enum dln2_endpoint { ++ DLN2_EP_OUT = 0, ++ DLN2_EP_IN = 1, ++}; ++ + struct dln2_dev { + struct usb_device *usb_dev; + struct usb_interface *interface; +@@ -733,10 +738,10 @@ static int dln2_probe(struct usb_interface *interface, + hostif->desc.bNumEndpoints < 2) + return -ENODEV; + +- epin = &hostif->endpoint[0].desc; +- epout = &hostif->endpoint[1].desc; ++ epout = &hostif->endpoint[DLN2_EP_OUT].desc; + if (!usb_endpoint_is_bulk_out(epout)) + return -ENODEV; ++ epin = &hostif->endpoint[DLN2_EP_IN].desc; + if (!usb_endpoint_is_bulk_in(epin)) + return -ENODEV; + +-- +2.16.4 + diff --git a/patches.suse/misc-pci_endpoint_test-Fix-to-support-10-pci-endpoin.patch b/patches.suse/misc-pci_endpoint_test-Fix-to-support-10-pci-endpoin.patch new file mode 100644 index 0000000..454514c --- /dev/null +++ b/patches.suse/misc-pci_endpoint_test-Fix-to-support-10-pci-endpoin.patch @@ -0,0 +1,37 @@ +From 6b443e5c80b67a7b8a85b33d052d655ef9064e90 Mon Sep 17 00:00:00 2001 +From: Kishon Vijay Abraham I +Date: Tue, 17 Mar 2020 15:31:57 +0530 +Subject: [PATCH] misc: pci_endpoint_test: Fix to support > 10 pci-endpoint-test devices +Git-commit: 6b443e5c80b67a7b8a85b33d052d655ef9064e90 +Patch-mainline: v5.7-rc1 +References: bsc#1051510 + +Adding more than 10 pci-endpoint-test devices results in +"kobject_add_internal failed for pci-endpoint-test.1 with -EEXIST, don't +try to register things with the same name in the same directory". This +is because commit 2c156ac71c6b ("misc: Add host side PCI driver for PCI +test function device") limited the length of the "name" to 20 characters. +Change the length of the name to 24 in order to support upto 10000 +pci-endpoint-test devices. + +Fixes: 2c156ac71c6b ("misc: Add host side PCI driver for PCI test function device") +Signed-off-by: Kishon Vijay Abraham I +Signed-off-by: Lorenzo Pieralisi +Cc: stable@vger.kernel.org # v4.14+ +Acked-by: Takashi Iwai + +--- + drivers/misc/pci_endpoint_test.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/misc/pci_endpoint_test.c ++++ b/drivers/misc/pci_endpoint_test.c +@@ -385,7 +385,7 @@ static int pci_endpoint_test_probe(struc + int err; + int irq; + int id; +- char name[20]; ++ char name[24]; + enum pci_barno bar; + void __iomem *base; + struct device *dev = &pdev->dev; diff --git a/patches.suse/mlxsw-spectrum-Wipe-xstats.backlog-of-down-ports.patch b/patches.suse/mlxsw-spectrum-Wipe-xstats.backlog-of-down-ports.patch new file mode 100644 index 0000000..d578229 --- /dev/null +++ b/patches.suse/mlxsw-spectrum-Wipe-xstats.backlog-of-down-ports.patch @@ -0,0 +1,64 @@ +From: Petr Machata +Date: Wed, 15 Jan 2020 13:53:48 +0200 +Subject: mlxsw: spectrum: Wipe xstats.backlog of down ports +Patch-mainline: v5.5-rc7 +Git-commit: ca7609ff3680c51d6c29897f3117aa2ad904f92a +References: bsc#1112374 + +Per-port counter cache used by Qdiscs is updated periodically, unless the +port is down. The fact that the cache is not updated for down ports is no +problem for most counters, which are relative in nature. However, backlog +is absolute in nature, and if there is a non-zero value in the cache around +the time that the port goes down, that value just stays there. This value +then leaks to offloaded Qdiscs that report non-zero backlog even if +there (obviously) is no traffic. + +The HW does not keep backlog of a downed port, so do likewise: as the port +goes down, wipe the backlog value from xstats. + +Fixes: 075ab8adaf4e ("mlxsw: spectrum: Collect tclass related stats periodically") +Signed-off-by: Petr Machata +Acked-by: Jiri Pirko +Signed-off-by: Ido Schimmel +Signed-off-by: David S. Miller +Acked-by: Thomas Bogendoerfer +--- + drivers/net/ethernet/mellanox/mlxsw/spectrum.c | 13 +++++++++++++ + 1 file changed, 13 insertions(+) + +--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c ++++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c +@@ -1063,6 +1063,9 @@ static void update_stats_cache(struct wo + periodic_hw_stats.update_dw.work); + + if (!netif_carrier_ok(mlxsw_sp_port->dev)) ++ /* Note: mlxsw_sp_port_down_wipe_counters() clears the cache as ++ * necessary when port goes down. ++ */ + goto out; + + mlxsw_sp_port_get_hw_stats(mlxsw_sp_port->dev, +@@ -3226,6 +3229,15 @@ static int mlxsw_sp_port_unsplit(struct + return 0; + } + ++static void ++mlxsw_sp_port_down_wipe_counters(struct mlxsw_sp_port *mlxsw_sp_port) ++{ ++ int i; ++ ++ for (i = 0; i < TC_MAX_QUEUE; i++) ++ mlxsw_sp_port->periodic_hw_stats.xstats.backlog[i] = 0; ++} ++ + static void mlxsw_sp_pude_event_func(const struct mlxsw_reg_info *reg, + char *pude_pl, void *priv) + { +@@ -3246,6 +3258,7 @@ static void mlxsw_sp_pude_event_func(con + } else { + netdev_info(mlxsw_sp_port->dev, "link down\n"); + netif_carrier_off(mlxsw_sp_port->dev); ++ mlxsw_sp_port_down_wipe_counters(mlxsw_sp_port); + } + } + diff --git a/patches.suse/mlxsw-spectrum_qdisc-Include-MC-TCs-in-Qdisc-counter.patch b/patches.suse/mlxsw-spectrum_qdisc-Include-MC-TCs-in-Qdisc-counter.patch new file mode 100644 index 0000000..91d5568 --- /dev/null +++ b/patches.suse/mlxsw-spectrum_qdisc-Include-MC-TCs-in-Qdisc-counter.patch @@ -0,0 +1,106 @@ +From: Petr Machata +Date: Wed, 15 Jan 2020 13:53:49 +0200 +Subject: mlxsw: spectrum_qdisc: Include MC TCs in Qdisc counters +Patch-mainline: v5.5-rc7 +Git-commit: 85005b82e59fa7bb7388b12594ab2067bf73d66c +References: bsc#1112374 + +mlxsw configures Spectrum in such a way that BUM traffic is passed not +through its nominal traffic class TC, but through its MC counterpart TC+8. +However, when collecting statistics, Qdiscs only look at the nominal TC and +ignore the MC TC. + +Add two helpers to compute the value for logical TC from the constituents, +one for backlog, the other for tail drops. Use them throughout instead of +going through the xstats pointer directly. + +Counters for TX bytes and packets are deduced from packet priority +counters, and therefore already include BUM traffic. wred_drop counter is +irrelevant on MC TCs, because RED is not enabled on them. + +Fixes: 7b8195306694 ("mlxsw: spectrum: Configure MC-aware mode on mlxsw ports") +Signed-off-by: Petr Machata +Acked-by: Jiri Pirko +Signed-off-by: Ido Schimmel +Signed-off-by: David S. Miller +Acked-by: Thomas Bogendoerfer +--- + drivers/net/ethernet/mellanox/mlxsw/spectrum_qdisc.c | 30 ++++++++++++++----- + 1 file changed, 23 insertions(+), 7 deletions(-) + +--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_qdisc.c ++++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_qdisc.c +@@ -195,6 +195,20 @@ mlxsw_sp_qdisc_get_xstats(struct mlxsw_s + return -EOPNOTSUPP; + } + ++static u64 ++mlxsw_sp_xstats_backlog(struct mlxsw_sp_port_xstats *xstats, int tclass_num) ++{ ++ return xstats->backlog[tclass_num] + ++ xstats->backlog[tclass_num + 8]; ++} ++ ++static u64 ++mlxsw_sp_xstats_tail_drop(struct mlxsw_sp_port_xstats *xstats, int tclass_num) ++{ ++ return xstats->tail_drop[tclass_num] + ++ xstats->tail_drop[tclass_num + 8]; ++} ++ + static void + mlxsw_sp_qdisc_bstats_per_priority_get(struct mlxsw_sp_port_xstats *xstats, + u8 prio_bitmap, u64 *tx_packets, +@@ -269,7 +283,7 @@ mlxsw_sp_setup_tc_qdisc_red_clean_stats( + &stats_base->tx_bytes); + red_base->prob_mark = xstats->ecn; + red_base->prob_drop = xstats->wred_drop[tclass_num]; +- red_base->pdrop = xstats->tail_drop[tclass_num]; ++ red_base->pdrop = mlxsw_sp_xstats_tail_drop(xstats, tclass_num); + + stats_base->overlimits = red_base->prob_drop + red_base->prob_mark; + stats_base->drops = red_base->prob_drop + red_base->pdrop; +@@ -369,7 +383,8 @@ mlxsw_sp_qdisc_get_red_xstats(struct mlx + + early_drops = xstats->wred_drop[tclass_num] - xstats_base->prob_drop; + marks = xstats->ecn - xstats_base->prob_mark; +- pdrops = xstats->tail_drop[tclass_num] - xstats_base->pdrop; ++ pdrops = mlxsw_sp_xstats_tail_drop(xstats, tclass_num) - ++ xstats_base->pdrop; + + res->pdrop += pdrops; + res->prob_drop += early_drops; +@@ -402,9 +417,10 @@ mlxsw_sp_qdisc_get_red_stats(struct mlxs + + overlimits = xstats->wred_drop[tclass_num] + xstats->ecn - + stats_base->overlimits; +- drops = xstats->wred_drop[tclass_num] + xstats->tail_drop[tclass_num] - ++ drops = xstats->wred_drop[tclass_num] + ++ mlxsw_sp_xstats_tail_drop(xstats, tclass_num) - + stats_base->drops; +- backlog = xstats->backlog[tclass_num]; ++ backlog = mlxsw_sp_xstats_backlog(xstats, tclass_num); + + _bstats_update(stats_ptr->bstats, tx_bytes, tx_packets); + stats_ptr->qstats->overlimits += overlimits; +@@ -575,9 +591,9 @@ mlxsw_sp_qdisc_get_prio_stats(struct mlx + tx_packets = stats->tx_packets - stats_base->tx_packets; + + for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) { +- drops += xstats->tail_drop[i]; ++ drops += mlxsw_sp_xstats_tail_drop(xstats, i); + drops += xstats->wred_drop[i]; +- backlog += xstats->backlog[i]; ++ backlog += mlxsw_sp_xstats_backlog(xstats, i); + } + drops = drops - stats_base->drops; + +@@ -613,7 +629,7 @@ mlxsw_sp_setup_tc_qdisc_prio_clean_stats + + stats_base->drops = 0; + for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) { +- stats_base->drops += xstats->tail_drop[i]; ++ stats_base->drops += mlxsw_sp_xstats_tail_drop(xstats, i); + stats_base->drops += xstats->wred_drop[i]; + } + diff --git a/patches.suse/mmc-sdhci-of-at91-fix-cd-gpios-for-SAMA5D2.patch b/patches.suse/mmc-sdhci-of-at91-fix-cd-gpios-for-SAMA5D2.patch new file mode 100644 index 0000000..b501f31 --- /dev/null +++ b/patches.suse/mmc-sdhci-of-at91-fix-cd-gpios-for-SAMA5D2.patch @@ -0,0 +1,55 @@ +From 53dd0a7cd65edc83b0c243d1c08377c8b876b2ee Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Micha=C5=82=20Miros=C5=82aw?= +Date: Sun, 15 Mar 2020 17:44:25 +0100 +Subject: [PATCH] mmc: sdhci-of-at91: fix cd-gpios for SAMA5D2 +Mime-version: 1.0 +Content-type: text/plain; charset=UTF-8 +Content-transfer-encoding: 8bit +Git-commit: 53dd0a7cd65edc83b0c243d1c08377c8b876b2ee +Patch-mainline: v5.6-rc7 +References: bsc#1051510 + +SAMA5D2x doesn't drive CMD line if GPIO is used as CD line (at least +SAMA5D27 doesn't). Fix this by forcing card-detect in the module +if module-controlled CD is not used. + +Fixed commit addresses the problem only for non-removable cards. This +amends it to also cover gpio-cd case. + +Cc: stable@vger.kernel.org +Fixes: 7a1e3f143176 ("mmc: sdhci-of-at91: force card detect value for non removable devices") +Signed-off-by: Michał Mirosław +Acked-by: Adrian Hunter +Link: https://lore.kernel.org/r/8d10950d9940468577daef4772b82a071b204716.1584290561.git.mirq-linux@rere.qmqm.pl +Signed-off-by: Ulf Hansson +Acked-by: Takashi Iwai + +--- + drivers/mmc/host/sdhci-of-at91.c | 8 ++++++-- + 1 file changed, 6 insertions(+), 2 deletions(-) + +--- a/drivers/mmc/host/sdhci-of-at91.c ++++ b/drivers/mmc/host/sdhci-of-at91.c +@@ -124,7 +124,8 @@ static void sdhci_at91_reset(struct sdhc + { + sdhci_reset(host, mask); + +- if (host->mmc->caps & MMC_CAP_NONREMOVABLE) ++ if ((host->mmc->caps & MMC_CAP_NONREMOVABLE) ++ || mmc_gpio_get_cd(host->mmc) >= 0) + sdhci_at91_set_force_card_detect(host); + } + +@@ -356,8 +357,11 @@ static int sdhci_at91_probe(struct platf + * detection procedure using the SDMCC_CD signal is bypassed. + * This bit is reset when a software reset for all command is performed + * so we need to implement our own reset function to set back this bit. ++ * ++ * WA: SAMA5D2 doesn't drive CMD if using CD GPIO line. + */ +- if (host->mmc->caps & MMC_CAP_NONREMOVABLE) ++ if ((host->mmc->caps & MMC_CAP_NONREMOVABLE) ++ || mmc_gpio_get_cd(host->mmc) >= 0) + sdhci_at91_set_force_card_detect(host); + + pm_runtime_put_autosuspend(&pdev->dev); diff --git a/patches.suse/module-Only-return-EEXIST-for-modules-that-.patch b/patches.suse/module-Only-return-EEXIST-for-modules-that-.patch new file mode 100644 index 0000000..766829b --- /dev/null +++ b/patches.suse/module-Only-return-EEXIST-for-modules-that-.patch @@ -0,0 +1,74 @@ +From 6e6de3dee51a439f76eb73c22ae2ffd2c9384712 Mon Sep 17 00:00:00 2001 +From: Prarit Bhargava +Date: Wed, 29 May 2019 07:26:25 -0400 +Subject: [PATCH] kernel/module.c: Only return -EEXIST for modules that have finished loading +Patch-mainline: v5.3 +Git-commit: 6e6de3dee51a439f76eb73c22ae2ffd2c9384712 +References: bsc#1165488 + +Microsoft HyperV disables the X86_FEATURE_SMCA bit on AMD systems, and +linux guests boot with repeated errors: + +amd64_edac_mod: Unknown symbol amd_unregister_ecc_decoder (err -2) +amd64_edac_mod: Unknown symbol amd_register_ecc_decoder (err -2) +amd64_edac_mod: Unknown symbol amd_report_gart_errors (err -2) +amd64_edac_mod: Unknown symbol amd_unregister_ecc_decoder (err -2) +amd64_edac_mod: Unknown symbol amd_register_ecc_decoder (err -2) +amd64_edac_mod: Unknown symbol amd_report_gart_errors (err -2) + +The warnings occur because the module code erroneously returns -EEXIST +for modules that have failed to load and are in the process of being +removed from the module list. + +module amd64_edac_mod has a dependency on module edac_mce_amd. Using +modules.dep, systemd will load edac_mce_amd for every request of +amd64_edac_mod. When the edac_mce_amd module loads, the module has +state MODULE_STATE_UNFORMED and once the module load fails and the state +becomes MODULE_STATE_GOING. Another request for edac_mce_amd module +executes and add_unformed_module() will erroneously return -EEXIST even +though the previous instance of edac_mce_amd has MODULE_STATE_GOING. +Upon receiving -EEXIST, systemd attempts to load amd64_edac_mod, which +fails because of unknown symbols from edac_mce_amd. + +add_unformed_module() must wait to return for any case other than +MODULE_STATE_LIVE to prevent a race between multiple loads of +dependent modules. + +Signed-off-by: Prarit Bhargava +Signed-off-by: Barret Rhoden +Cc: David Arcari +Cc: Jessica Yu +Cc: Heiko Carstens +Signed-off-by: Jessica Yu +Acked-by: Jessica Yu +--- + kernel/module.c | 6 ++---- + 1 file changed, 2 insertions(+), 4 deletions(-) + +diff --git a/kernel/module.c b/kernel/module.c +index 6e6712b3aaf5..1e7dcbe527af 100644 +--- a/kernel/module.c ++++ b/kernel/module.c +@@ -3397,8 +3397,7 @@ static bool finished_loading(const char *name) + sched_annotate_sleep(); + mutex_lock(&module_mutex); + mod = find_module_all(name, strlen(name), true); +- ret = !mod || mod->state == MODULE_STATE_LIVE +- || mod->state == MODULE_STATE_GOING; ++ ret = !mod || mod->state == MODULE_STATE_LIVE; + mutex_unlock(&module_mutex); + + return ret; +@@ -3588,8 +3587,7 @@ static int add_unformed_module(struct module *mod) + mutex_lock(&module_mutex); + old = find_module_all(mod->name, strlen(mod->name), true); + if (old != NULL) { +- if (old->state == MODULE_STATE_COMING +- || old->state == MODULE_STATE_UNFORMED) { ++ if (old->state != MODULE_STATE_LIVE) { + /* Wait in case it fails to load. */ + mutex_unlock(&module_mutex); + err = wait_event_interruptible(module_wq, +-- +2.16.4 + diff --git a/patches.suse/module-wakeup-processes-in-module_wq-on-mod.patch b/patches.suse/module-wakeup-processes-in-module_wq-on-mod.patch new file mode 100644 index 0000000..ee60d56 --- /dev/null +++ b/patches.suse/module-wakeup-processes-in-module_wq-on-mod.patch @@ -0,0 +1,60 @@ +From 5d603311615f612320bb77bd2a82553ef1ced5b7 Mon Sep 17 00:00:00 2001 +From: Konstantin Khorenko +Date: Wed, 13 Nov 2019 12:29:50 +0300 +Subject: [PATCH] kernel/module.c: wakeup processes in module_wq on module unload +Git-commit: 5d603311615f612320bb77bd2a82553ef1ced5b7 +Patch-mainline: v5.5 +References: bsc#1165488 + +Fix the race between load and unload a kernel module. + +sys_delete_module() + try_stop_module() + mod->state = _GOING + add_unformed_module() + old = find_module_all() + (old->state == _GOING => + wait_event_interruptible()) + + During pre-condition + finished_loading() rets 0 + schedule() + (never gets waken up later) + free_module() + mod->state = _UNFORMED + list_del_rcu(&mod->list) + (dels mod from "modules" list) + +return + +The race above leads to modprobe hanging forever on loading +a module. + +Error paths on loading module call wake_up_all(&module_wq) after +freeing module, so let's do the same on straight module unload. + +Fixes: 6e6de3dee51a ("kernel/module.c: Only return -EEXIST for modules that have finished loading") +Reviewed-by: Prarit Bhargava +Signed-off-by: Konstantin Khorenko +Signed-off-by: Jessica Yu +Acked-by: Jessica Yu +--- + kernel/module.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/kernel/module.c b/kernel/module.c +index 26c13173da3d..bdbf95726cb7 100644 +--- a/kernel/module.c ++++ b/kernel/module.c +@@ -1033,6 +1033,8 @@ SYSCALL_DEFINE2(delete_module, const char __user *, name_user, + strlcpy(last_unloaded_module, mod->name, sizeof(last_unloaded_module)); + + free_module(mod); ++ /* someone could wait for the module in add_unformed_module() */ ++ wake_up_all(&module_wq); + return 0; + out: + mutex_unlock(&module_mutex); +-- +2.16.4 + diff --git a/patches.suse/msft-hv-1634-hv_netvsc-pass-netvsc_device-to-rndis-halt.patch b/patches.suse/msft-hv-1634-hv_netvsc-pass-netvsc_device-to-rndis-halt.patch index 978e9d4..f40ff16 100644 --- a/patches.suse/msft-hv-1634-hv_netvsc-pass-netvsc_device-to-rndis-halt.patch +++ b/patches.suse/msft-hv-1634-hv_netvsc-pass-netvsc_device-to-rndis-halt.patch @@ -3,7 +3,7 @@ Date: Fri, 16 Mar 2018 15:44:27 -0700 Patch-mainline: v4.17-rc1 Subject: hv_netvsc: pass netvsc_device to rndis halt Git-commit: 0e96460e620df7f9a13c352b68b06f02eec3de94 -References: bsc#1107207 +References: bsc#1107207 networking-stable-20_01_20 The caller has a valid pointer, pass it to rndis_filter_halt_device and avoid any possible RCU races here. diff --git a/patches.suse/mwifiex-set-needed_headroom-not-hard_header_len.patch b/patches.suse/mwifiex-set-needed_headroom-not-hard_header_len.patch new file mode 100644 index 0000000..aa22a8b --- /dev/null +++ b/patches.suse/mwifiex-set-needed_headroom-not-hard_header_len.patch @@ -0,0 +1,56 @@ +From 9454f7a895b822dd8fb4588fc55fda7c96728869 Mon Sep 17 00:00:00 2001 +From: Brian Norris +Date: Wed, 26 Feb 2020 16:05:11 -0800 +Subject: [PATCH] mwifiex: set needed_headroom, not hard_header_len +Git-commit: 9454f7a895b822dd8fb4588fc55fda7c96728869 +Patch-mainline: v5.7-rc1 +References: bsc#1051510 + +hard_header_len provides limitations for things like AF_PACKET, such +that we don't allow transmitting packets smaller than this. + +needed_headroom provides a suggested minimum headroom for SKBs, so that +we can trivally add our headers to the front. + +The latter is the correct field to use in this case, while the former +mostly just prevents sending small AF_PACKET frames. + +In any case, mwifiex already does its own bounce buffering [1] if we +don't have enough headroom, so hints (not hard limits) are all that are +needed. + +This is the essentially the same bug (and fix) that brcmfmac had, fixed +in commit cb39288fd6bb ("brcmfmac: use ndev->needed_headroom to reserve +additional header space"). + +[1] mwifiex_hard_start_xmit(): + if (skb_headroom(skb) < MWIFIEX_MIN_DATA_HEADER_LEN) { + [...] + /* Insufficient skb headroom - allocate a new skb */ + +Fixes: 5e6e3a92b9a4 ("wireless: mwifiex: initial commit for Marvell mwifiex driver") +Signed-off-by: Brian Norris +Acked-by: Ganapathi Bhat +Signed-off-by: Kalle Valo +Acked-by: Takashi Iwai + +--- + drivers/net/wireless/marvell/mwifiex/cfg80211.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/wireless/marvell/mwifiex/cfg80211.c b/drivers/net/wireless/marvell/mwifiex/cfg80211.c +index 0a6da6fe2f89..1566d2197906 100644 +--- a/drivers/net/wireless/marvell/mwifiex/cfg80211.c ++++ b/drivers/net/wireless/marvell/mwifiex/cfg80211.c +@@ -3052,7 +3052,7 @@ struct wireless_dev *mwifiex_add_virtual_intf(struct wiphy *wiphy, + + dev->flags |= IFF_BROADCAST | IFF_MULTICAST; + dev->watchdog_timeo = MWIFIEX_DEFAULT_WATCHDOG_TIMEOUT; +- dev->hard_header_len += MWIFIEX_MIN_DATA_HEADER_LEN; ++ dev->needed_headroom = MWIFIEX_MIN_DATA_HEADER_LEN; + dev->ethtool_ops = &mwifiex_ethtool_ops; + + mdev_priv = netdev_priv(dev); +-- +2.16.4 + diff --git a/patches.suse/net-Fix-Tx-hash-bound-checking.patch b/patches.suse/net-Fix-Tx-hash-bound-checking.patch new file mode 100644 index 0000000..443518d --- /dev/null +++ b/patches.suse/net-Fix-Tx-hash-bound-checking.patch @@ -0,0 +1,39 @@ +From: Amritha Nambiar +Date: Mon, 24 Feb 2020 10:56:00 -0800 +Subject: net: Fix Tx hash bound checking +Patch-mainline: v5.6-rc4 +Git-commit: 6e11d1578fba8d09d03a286740ffcf336d53928c +References: bsc#1109837 + +Fixes the lower and upper bounds when there are multiple TCs and +traffic is on the the same TC on the same device. + +The lower bound is represented by 'qoffset' and the upper limit for +hash value is 'qcount + qoffset'. This gives a clean Rx to Tx queue +mapping when there are multiple TCs, as the queue indices for upper TCs +will be offset by 'qoffset'. + +v2: Fixed commit description based on comments. + +Fixes: 1b837d489e06 ("net: Revoke export for __skb_tx_hash, update it to just be static skb_tx_hash") +Fixes: eadec877ce9c ("net: Add support for subordinate traffic classes to netdev_pick_tx") +Signed-off-by: Amritha Nambiar +Reviewed-by: Alexander Duyck +Reviewed-by: Sridhar Samudrala +Signed-off-by: David S. Miller +Acked-by: Thomas Bogendoerfer +--- + net/core/dev.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/net/core/dev.c ++++ b/net/core/dev.c +@@ -2790,6 +2790,8 @@ static u16 skb_tx_hash(const struct net_ + + if (skb_rx_queue_recorded(skb)) { + hash = skb_get_rx_queue(skb); ++ if (hash >= qoffset) ++ hash -= qoffset; + while (unlikely(hash >= qcount)) + hash -= qcount; + return hash + qoffset; diff --git a/patches.suse/net-cxgb3_main-Add-CAP_NET_ADMIN-check-to-CHELSIO_GE.patch b/patches.suse/net-cxgb3_main-Add-CAP_NET_ADMIN-check-to-CHELSIO_GE.patch new file mode 100644 index 0000000..0c48a4e --- /dev/null +++ b/patches.suse/net-cxgb3_main-Add-CAP_NET_ADMIN-check-to-CHELSIO_GE.patch @@ -0,0 +1,48 @@ +From: Michael Ellerman +Date: Fri, 24 Jan 2020 20:41:44 +1100 +Subject: net: cxgb3_main: Add CAP_NET_ADMIN check to CHELSIO_GET_MEM +Git-commit: 3546d8f1bbe992488ed91592cf6bf76e7114791a +Patch-mainline: 5.5 +References: networking-stable-20_01_27 + +The cxgb3 driver for "Chelsio T3-based gigabit and 10Gb Ethernet +adapters" implements a custom ioctl as SIOCCHIOCTL/SIOCDEVPRIVATE in +cxgb_extension_ioctl(). + +One of the subcommands of the ioctl is CHELSIO_GET_MEM, which appears +to read memory directly out of the adapter and return it to userspace. +It's not entirely clear what the contents of the adapter memory +contains, but the assumption is that it shouldn't be accessible to all +users. + +So add a CAP_NET_ADMIN check to the CHELSIO_GET_MEM case. Put it after +the is_offload() check, which matches two of the other subcommands in +the same function which also check for is_offload() and CAP_NET_ADMIN. + +Found by Ilja by code inspection, not tested as I don't have the +required hardware. + +Reported-by: Ilja Van Sprundel +Signed-off-by: Michael Ellerman +Signed-off-by: David S. Miller +Signed-off-by: Jiri Slaby +--- + drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c b/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c +index 58f89f6a040f..97ff8608f0ab 100644 +--- a/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c ++++ b/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c +@@ -2448,6 +2448,8 @@ static int cxgb_extension_ioctl(struct net_device *dev, void __user *useraddr) + + if (!is_offload(adapter)) + return -EOPNOTSUPP; ++ if (!capable(CAP_NET_ADMIN)) ++ return -EPERM; + if (!(adapter->flags & FULL_INIT_DONE)) + return -EIO; /* need the memory controllers */ + if (copy_from_user(&t, useraddr, sizeof(t))) +-- +2.25.1 + diff --git a/patches.suse/net-dsa-mv88e6xxx-Preserve-priority-when-setting-CPU.patch b/patches.suse/net-dsa-mv88e6xxx-Preserve-priority-when-setting-CPU.patch new file mode 100644 index 0000000..eae3901 --- /dev/null +++ b/patches.suse/net-dsa-mv88e6xxx-Preserve-priority-when-setting-CPU.patch @@ -0,0 +1,48 @@ +From: Andrew Lunn +Date: Sat, 4 Jan 2020 23:14:51 +0100 +Subject: net: dsa: mv88e6xxx: Preserve priority when setting CPU port. +Git-commit: d8dc2c9676e614ef62f54a155b50076888c8a29a +Patch-mainline: 5.5-rc6 +References: networking-stable-20_01_11 + +The 6390 family uses an extended register to set the port connected to +the CPU. The lower 5 bits indicate the port, the upper three bits are +the priority of the frames as they pass through the switch, what +egress queue they should use, etc. Since frames being set to the CPU +are typically management frames, BPDU, IGMP, ARP, etc set the priority +to 7, the reset default, and the highest. + +Fixes: 33641994a676 ("net: dsa: mv88e6xxx: Monitor and Management tables") +Signed-off-by: Andrew Lunn +Tested-by: Chris Healy +Signed-off-by: David S. Miller +Signed-off-by: Jiri Slaby +--- + drivers/net/dsa/mv88e6xxx/global1.c | 5 +++++ + drivers/net/dsa/mv88e6xxx/mv88e6xxx.h | 1 + + 2 files changed, 6 insertions(+) + +--- a/drivers/net/dsa/mv88e6xxx/global1.c ++++ b/drivers/net/dsa/mv88e6xxx/global1.c +@@ -277,6 +277,11 @@ int mv88e6390_g1_set_egress_port(struct + + int mv88e6390_g1_set_cpu_port(struct mv88e6xxx_chip *chip, int port) + { ++ /* Use the default high priority for management frames sent to ++ * the CPU. ++ */ ++ port |= MV88E6390_G1_MONITOR_MGMT_CTL_PTR_CPU_DEST_MGMTPRI; ++ + return mv88e6390_g1_monitor_write(chip, GLOBAL_MONITOR_CONTROL_CPU_DEST, + port); + } +--- a/drivers/net/dsa/mv88e6xxx/mv88e6xxx.h ++++ b/drivers/net/dsa/mv88e6xxx/mv88e6xxx.h +@@ -320,6 +320,7 @@ + #define GLOBAL_MONITOR_CONTROL_INGRESS (0x20 << 8) + #define GLOBAL_MONITOR_CONTROL_EGRESS (0x21 << 8) + #define GLOBAL_MONITOR_CONTROL_CPU_DEST (0x30 << 8) ++#define MV88E6390_G1_MONITOR_MGMT_CTL_PTR_CPU_DEST_MGMTPRI 0x00e0 + #define GLOBAL_CONTROL_2 0x1c + #define GLOBAL_CONTROL_2_NO_CASCADE 0xe000 + #define GLOBAL_CONTROL_2_MULTIPLE_CASCADE 0xf000 diff --git a/patches.suse/net-dsa-tag_qca-Make-sure-there-is-headroom-for-tag.patch b/patches.suse/net-dsa-tag_qca-Make-sure-there-is-headroom-for-tag.patch new file mode 100644 index 0000000..a442e56 --- /dev/null +++ b/patches.suse/net-dsa-tag_qca-Make-sure-there-is-headroom-for-tag.patch @@ -0,0 +1,31 @@ +From: Per Forlin +Date: Thu, 13 Feb 2020 15:37:09 +0100 +Subject: net: dsa: tag_qca: Make sure there is headroom for tag +Git-commit: 04fb91243a853dbde216d829c79d9632e52aa8d9 +Patch-mainline: 5.6-rc2 +References: networking-stable-20_02_19 + +Passing tag size to skb_cow_head will make sure +there is enough headroom for the tag data. +This change does not introduce any overhead in case there +is already available headroom for tag. + +Signed-off-by: Per Forlin +Reviewed-by: Florian Fainelli +Signed-off-by: David S. Miller +Signed-off-by: Jiri Slaby +--- + net/dsa/tag_qca.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/net/dsa/tag_qca.c ++++ b/net/dsa/tag_qca.c +@@ -41,7 +41,7 @@ static struct sk_buff *qca_tag_xmit(stru + struct dsa_slave_priv *p = netdev_priv(dev); + u16 *phdr, hdr; + +- if (skb_cow_head(skb, 0) < 0) ++ if (skb_cow_head(skb, QCA_HDR_LEN) < 0) + goto out_free; + + skb_push(skb, QCA_HDR_LEN); diff --git a/patches.suse/net-dsa-tag_qca-fix-doubled-Tx-statistics.patch b/patches.suse/net-dsa-tag_qca-fix-doubled-Tx-statistics.patch new file mode 100644 index 0000000..4834c05 --- /dev/null +++ b/patches.suse/net-dsa-tag_qca-fix-doubled-Tx-statistics.patch @@ -0,0 +1,35 @@ +From: Alexander Lobakin +Date: Wed, 15 Jan 2020 11:56:52 +0300 +Subject: net: dsa: tag_qca: fix doubled Tx statistics +Git-commit: bd5874da57edd001b35cf28ae737779498c16a56 +Patch-mainline: 5.5-rc7 +References: networking-stable-20_01_20 + +DSA subsystem takes care of netdev statistics since commit 4ed70ce9f01c +("net: dsa: Refactor transmit path to eliminate duplication"), so +any accounting inside tagger callbacks is redundant and can lead to +messing up the stats. +This bug is present in Qualcomm tagger since day 0. + +Fixes: cafdc45c949b ("net-next: dsa: add Qualcomm tag RX/TX handler") +Reviewed-by: Andrew Lunn +Signed-off-by: Alexander Lobakin +Reviewed-by: Florian Fainelli +Signed-off-by: David S. Miller +Signed-off-by: Jiri Slaby +--- + net/dsa/tag_qca.c | 3 --- + 1 file changed, 3 deletions(-) + +--- a/net/dsa/tag_qca.c ++++ b/net/dsa/tag_qca.c +@@ -41,9 +41,6 @@ static struct sk_buff *qca_tag_xmit(stru + struct dsa_slave_priv *p = netdev_priv(dev); + u16 *phdr, hdr; + +- dev->stats.tx_packets++; +- dev->stats.tx_bytes += skb->len; +- + if (skb_cow_head(skb, 0) < 0) + goto out_free; + diff --git a/patches.suse/net-ena-add-pci-shutdown-handler-to-allow-safe-kexec.patch b/patches.suse/net-ena-add-pci-shutdown-handler-to-allow-safe-kexec.patch new file mode 100644 index 0000000..9bc32b4 --- /dev/null +++ b/patches.suse/net-ena-add-pci-shutdown-handler-to-allow-safe-kexec.patch @@ -0,0 +1,126 @@ +From: "Guilherme G. Piccoli" +Subject: net: ena: Add PCI shutdown handler to allow safe kexec +Git-commit: 428c491332bca498c8eb2127669af51506c346c7 +Patch-mainline: v5.6 +References: bsc#1167421, bsc#1167423 +Acked-by: Jiri Bohac + +Currently ENA only provides the PCI remove() handler, used during rmmod +for example. This is not called on shutdown/kexec path; we are potentially +creating a failure scenario on kexec: + +(a) Kexec is triggered, no shutdown() / remove() handler is called for ENA; +instead pci_device_shutdown() clears the master bit of the PCI device, +stopping all DMA transactions; + +(b) Kexec reboot happens and the device gets enabled again, likely having +its FW with that DMA transaction buffered; then it may trigger the (now +invalid) memory operation in the new kernel, corrupting kernel memory area. + +This patch aims to prevent this, by implementing a shutdown() handler +quite similar to the remove() one - the difference being the handling +of the netdev, which is unregistered on remove(), but following the +convention observed in other drivers, it's only detached on shutdown(). + +This prevents an odd issue in AWS Nitro instances, in which after the 2nd +kexec the next one will fail with an initrd corruption, caused by a wild +DMA write to invalid kernel memory. The lspci output for the adapter +present in my instance is: + +00:05.0 Ethernet controller [0200]: Amazon.com, Inc. Elastic Network +Adapter (ENA) [1d0f:ec20] + +Suggested-by: Gavin Shan +Signed-off-by: Guilherme G. Piccoli +Acked-by: Sameeh Jubran +Signed-off-by: David S. Miller + +--- + drivers/net/ethernet/amazon/ena/ena_netdev.c | 51 +++++++++++++++++++++------ + 1 file changed, 41 insertions(+), 10 deletions(-) + +--- a/drivers/net/ethernet/amazon/ena/ena_netdev.c ++++ b/drivers/net/ethernet/amazon/ena/ena_netdev.c +@@ -3668,13 +3668,15 @@ static int ena_sriov_configure(struct pc + /*****************************************************************************/ + /*****************************************************************************/ + +-/* ena_remove - Device Removal Routine ++/* __ena_shutoff - Helper used in both PCI remove/shutdown routines + * @pdev: PCI device information struct ++ * @shutdown: Is it a shutdown operation? If false, means it is a removal + * +- * ena_remove is called by the PCI subsystem to alert the driver +- * that it should release a PCI device. ++ * __ena_shutoff is a helper routine that does the real work on shutdown and ++ * removal paths; the difference between those paths is with regards to whether ++ * dettach or unregister the netdevice. + */ +-static void ena_remove(struct pci_dev *pdev) ++static void __ena_shutoff(struct pci_dev *pdev, bool shutdown) + { + struct ena_adapter *adapter = pci_get_drvdata(pdev); + struct ena_com_dev *ena_dev; +@@ -3693,13 +3695,17 @@ static void ena_remove(struct pci_dev *p + + cancel_work_sync(&adapter->reset_task); + +- rtnl_lock(); ++ rtnl_lock(); /* lock released inside the below if-else block */ + ena_destroy_device(adapter, true); +- rtnl_unlock(); +- +- unregister_netdev(netdev); +- +- free_netdev(netdev); ++ if (shutdown) { ++ netif_device_detach(netdev); ++ dev_close(netdev); ++ rtnl_unlock(); ++ } else { ++ rtnl_unlock(); ++ unregister_netdev(netdev); ++ free_netdev(netdev); ++ } + + ena_com_rss_destroy(ena_dev); + +@@ -3716,6 +3722,30 @@ static void ena_remove(struct pci_dev *p + vfree(ena_dev); + } + ++/* ena_remove - Device Removal Routine ++ * @pdev: PCI device information struct ++ * ++ * ena_remove is called by the PCI subsystem to alert the driver ++ * that it should release a PCI device. ++ */ ++ ++static void ena_remove(struct pci_dev *pdev) ++{ ++ __ena_shutoff(pdev, false); ++} ++ ++/* ena_shutdown - Device Shutdown Routine ++ * @pdev: PCI device information struct ++ * ++ * ena_shutdown is called by the PCI subsystem to alert the driver that ++ * a shutdown/reboot (or kexec) is happening and device must be disabled. ++ */ ++ ++static void ena_shutdown(struct pci_dev *pdev) ++{ ++ __ena_shutoff(pdev, true); ++} ++ + #ifdef CONFIG_PM + /* ena_suspend - PM suspend callback + * @pdev: PCI device information struct +@@ -3765,6 +3795,7 @@ static struct pci_driver ena_pci_driver + .id_table = ena_pci_tbl, + .probe = ena_probe, + .remove = ena_remove, ++ .shutdown = ena_shutdown, + #ifdef CONFIG_PM + .suspend = ena_suspend, + .resume = ena_resume, diff --git a/patches.suse/net-ethtool-Introduce-link_ksettings-API-for-virtual.patch b/patches.suse/net-ethtool-Introduce-link_ksettings-API-for-virtual.patch new file mode 100644 index 0000000..37afeb4 --- /dev/null +++ b/patches.suse/net-ethtool-Introduce-link_ksettings-API-for-virtual.patch @@ -0,0 +1,267 @@ +From 9aedc6e2f1c6708120b80748556fb6ad0567d15d Mon Sep 17 00:00:00 2001 +From: Cris Forno +Date: Fri, 28 Feb 2020 14:12:05 -0600 +Subject: [PATCH] net/ethtool: Introduce link_ksettings API for virtual network + devices + +References: bsc#1136157 ltc#177197 +Patch-mainline: v5.7-rc1 +Git-commit: 9aedc6e2f1c6708120b80748556fb6ad0567d15d + +With the ethtool_virtdev_set_link_ksettings function in core/ethtool.c, +ibmveth, netvsc, and virtio now use the core's helper function. + +Funtionality changes that pertain to ibmveth driver include: + + 1. Changed the initial hardcoded link speed to 1GB. + + 2. Added support for allowing a user to change the reported link + speed via ethtool. + +Functionality changes to the netvsc driver include: + + 1. When netvsc_get_link_ksettings is called, it will defer to the VF + device if it exists to pull accelerated networking values, otherwise + pull default or user-defined values. + + 2. Similarly, if netvsc_set_link_ksettings called and a VF device + exists, the real values of speed and duplex are changed. + +Signed-off-by: Cris Forno +Signed-off-by: David S. Miller +Acked-by: Michal Suchanek +--- + drivers/net/ethernet/ibm/ibmveth.c | 57 +++++++++++++++++------------- + drivers/net/ethernet/ibm/ibmveth.h | 3 ++ + drivers/net/hyperv/netvsc_drv.c | 41 ++++++++------------- + drivers/net/virtio_net.c | 39 ++------------------ + 4 files changed, 53 insertions(+), 87 deletions(-) + +diff --git a/drivers/net/ethernet/ibm/ibmveth.c b/drivers/net/ethernet/ibm/ibmveth.c +index 84121aab7ff1..1fdbd7649f0f 100644 +--- a/drivers/net/ethernet/ibm/ibmveth.c ++++ b/drivers/net/ethernet/ibm/ibmveth.c +@@ -712,29 +712,36 @@ static int ibmveth_close(struct net_device *netdev) + return 0; + } + +-static int netdev_get_link_ksettings(struct net_device *dev, +- struct ethtool_link_ksettings *cmd) ++static int ibmveth_set_link_ksettings(struct net_device *dev, ++ const struct ethtool_link_ksettings *cmd) + { +- u32 supported, advertising; +- +- supported = (SUPPORTED_1000baseT_Full | SUPPORTED_Autoneg | +- SUPPORTED_FIBRE); +- advertising = (ADVERTISED_1000baseT_Full | ADVERTISED_Autoneg | +- ADVERTISED_FIBRE); +- cmd->base.speed = SPEED_1000; +- cmd->base.duplex = DUPLEX_FULL; +- cmd->base.port = PORT_FIBRE; +- cmd->base.phy_address = 0; +- cmd->base.autoneg = AUTONEG_ENABLE; +- +- ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.supported, +- supported); +- ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.advertising, +- advertising); ++ struct ibmveth_adapter *adapter = netdev_priv(dev); ++ ++ return ethtool_virtdev_set_link_ksettings(dev, cmd, ++ &adapter->speed, ++ &adapter->duplex); ++} ++ ++static int ibmveth_get_link_ksettings(struct net_device *dev, ++ struct ethtool_link_ksettings *cmd) ++{ ++ struct ibmveth_adapter *adapter = netdev_priv(dev); ++ ++ cmd->base.speed = adapter->speed; ++ cmd->base.duplex = adapter->duplex; ++ cmd->base.port = PORT_OTHER; + + return 0; + } + ++static void ibmveth_init_link_settings(struct net_device *dev) ++{ ++ struct ibmveth_adapter *adapter = netdev_priv(dev); ++ ++ adapter->speed = SPEED_1000; ++ adapter->duplex = DUPLEX_FULL; ++} ++ + static void netdev_get_drvinfo(struct net_device *dev, + struct ethtool_drvinfo *info) + { +@@ -965,12 +972,13 @@ static void ibmveth_get_ethtool_stats(struct net_device *dev, + } + + static const struct ethtool_ops netdev_ethtool_ops = { +- .get_drvinfo = netdev_get_drvinfo, +- .get_link = ethtool_op_get_link, +- .get_strings = ibmveth_get_strings, +- .get_sset_count = ibmveth_get_sset_count, +- .get_ethtool_stats = ibmveth_get_ethtool_stats, +- .get_link_ksettings = netdev_get_link_ksettings, ++ .get_drvinfo = netdev_get_drvinfo, ++ .get_link = ethtool_op_get_link, ++ .get_strings = ibmveth_get_strings, ++ .get_sset_count = ibmveth_get_sset_count, ++ .get_ethtool_stats = ibmveth_get_ethtool_stats, ++ .get_link_ksettings = ibmveth_get_link_ksettings, ++ .set_link_ksettings = ibmveth_set_link_ksettings, + }; + + static int ibmveth_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) +@@ -1674,6 +1682,7 @@ static int ibmveth_probe(struct vio_dev *dev, const struct vio_device_id *id) + adapter->netdev = netdev; + adapter->mcastFilterSize = be32_to_cpu(*mcastFilterSize_p); + adapter->pool_config = 0; ++ ibmveth_init_link_settings(netdev); + + netif_napi_add(netdev, &adapter->napi, ibmveth_poll, 16); + +diff --git a/drivers/net/ethernet/ibm/ibmveth.h b/drivers/net/ethernet/ibm/ibmveth.h +index 4e9bf3421f4f..27dfff200166 100644 +--- a/drivers/net/ethernet/ibm/ibmveth.h ++++ b/drivers/net/ethernet/ibm/ibmveth.h +@@ -162,6 +162,9 @@ struct ibmveth_adapter { + u64 tx_send_failed; + u64 tx_large_packets; + u64 rx_large_packets; ++ /* Ethtool settings */ ++ u8 duplex; ++ u32 speed; + }; + + /* +diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c +index 245ce2374035..d8e86bdbfba1 100644 +--- a/drivers/net/hyperv/netvsc_drv.c ++++ b/drivers/net/hyperv/netvsc_drv.c +@@ -1140,23 +1140,6 @@ static int netvsc_set_channels(struct net_device *net, + return ret; + } + +-static bool +-netvsc_validate_ethtool_ss_cmd(const struct ethtool_link_ksettings *cmd) +-{ +- struct ethtool_link_ksettings diff1 = *cmd; +- struct ethtool_link_ksettings diff2 = {}; +- +- diff1.base.speed = 0; +- diff1.base.duplex = 0; +- /* advertising and cmd are usually set */ +- ethtool_link_ksettings_zero_link_mode(&diff1, advertising); +- diff1.base.cmd = 0; +- /* We set port to PORT_OTHER */ +- diff2.base.port = PORT_OTHER; +- +- return !memcmp(&diff1, &diff2, sizeof(diff1)); +-} +- + static void netvsc_init_settings(struct net_device *dev) + { + struct net_device_context *ndc = netdev_priv(dev); +@@ -1173,6 +1156,12 @@ static int netvsc_get_link_ksettings(struct net_device *dev, + struct ethtool_link_ksettings *cmd) + { + struct net_device_context *ndc = netdev_priv(dev); ++ struct net_device *vf_netdev; ++ ++ vf_netdev = rtnl_dereference(ndc->vf_netdev); ++ ++ if (vf_netdev) ++ return __ethtool_get_link_ksettings(vf_netdev, cmd); + + cmd->base.speed = ndc->speed; + cmd->base.duplex = ndc->duplex; +@@ -1185,18 +1174,18 @@ static int netvsc_set_link_ksettings(struct net_device *dev, + const struct ethtool_link_ksettings *cmd) + { + struct net_device_context *ndc = netdev_priv(dev); +- u32 speed; ++ struct net_device *vf_netdev = rtnl_dereference(ndc->vf_netdev); + +- speed = cmd->base.speed; +- if (!ethtool_validate_speed(speed) || +- !ethtool_validate_duplex(cmd->base.duplex) || +- !netvsc_validate_ethtool_ss_cmd(cmd)) +- return -EINVAL; ++ if (vf_netdev) { ++ if (!vf_netdev->ethtool_ops->set_link_ksettings) ++ return -EOPNOTSUPP; + +- ndc->speed = speed; +- ndc->duplex = cmd->base.duplex; ++ return vf_netdev->ethtool_ops->set_link_ksettings(vf_netdev, ++ cmd); ++ } + +- return 0; ++ return ethtool_virtdev_set_link_ksettings(dev, cmd, ++ &ndc->speed, &ndc->duplex); + } + + static int netvsc_change_mtu(struct net_device *ndev, int mtu) +diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c +index 12d115ef5e74..84c0d9581f93 100644 +--- a/drivers/net/virtio_net.c ++++ b/drivers/net/virtio_net.c +@@ -2178,48 +2178,13 @@ static void virtnet_get_channels(struct net_device *dev, + channels->other_count = 0; + } + +-/* Check if the user is trying to change anything besides speed/duplex */ +-static bool +-virtnet_validate_ethtool_cmd(const struct ethtool_link_ksettings *cmd) +-{ +- struct ethtool_link_ksettings diff1 = *cmd; +- struct ethtool_link_ksettings diff2 = {}; +- +- /* cmd is always set so we need to clear it, validate the port type +- * and also without autonegotiation we can ignore advertising +- */ +- diff1.base.speed = 0; +- diff2.base.port = PORT_OTHER; +- ethtool_link_ksettings_zero_link_mode(&diff1, advertising); +- diff1.base.duplex = 0; +- diff1.base.cmd = 0; +- diff1.base.link_mode_masks_nwords = 0; +- +- return !memcmp(&diff1.base, &diff2.base, sizeof(diff1.base)) && +- bitmap_empty(diff1.link_modes.supported, +- __ETHTOOL_LINK_MODE_MASK_NBITS) && +- bitmap_empty(diff1.link_modes.advertising, +- __ETHTOOL_LINK_MODE_MASK_NBITS) && +- bitmap_empty(diff1.link_modes.lp_advertising, +- __ETHTOOL_LINK_MODE_MASK_NBITS); +-} +- + static int virtnet_set_link_ksettings(struct net_device *dev, + const struct ethtool_link_ksettings *cmd) + { + struct virtnet_info *vi = netdev_priv(dev); +- u32 speed; +- +- speed = cmd->base.speed; +- /* don't allow custom speed and duplex */ +- if (!ethtool_validate_speed(speed) || +- !ethtool_validate_duplex(cmd->base.duplex) || +- !virtnet_validate_ethtool_cmd(cmd)) +- return -EINVAL; +- vi->speed = speed; +- vi->duplex = cmd->base.duplex; + +- return 0; ++ return ethtool_virtdev_set_link_ksettings(dev, cmd, ++ &vi->speed, &vi->duplex); + } + + static int virtnet_get_link_ksettings(struct net_device *dev, +-- +2.23.0 + diff --git a/patches.suse/net-hns-fix-soft-lockup-when-there-is-not-enough-mem.patch b/patches.suse/net-hns-fix-soft-lockup-when-there-is-not-enough-mem.patch new file mode 100644 index 0000000..3cc1934 --- /dev/null +++ b/patches.suse/net-hns-fix-soft-lockup-when-there-is-not-enough-mem.patch @@ -0,0 +1,55 @@ +From: Yonglong Liu +Date: Thu, 16 Jan 2020 15:41:17 +0800 +Subject: net: hns: fix soft lockup when there is not enough memory +Git-commit: 49edd6a2c456150870ddcef5b7ed11b21d849e13 +Patch-mainline: 5.5-rc7 +References: networking-stable-20_01_20 + +When there is not enough memory and napi_alloc_skb() return NULL, +the HNS driver will print error message, and than try again, if +the memory is not enough for a while, huge error message and the +retry operation will cause soft lockup. + +When napi_alloc_skb() return NULL because of no memory, we can +get a warn_alloc() call trace, so this patch deletes the error +message. We already use polling mode to handle irq, but the +retry operation will render the polling weight inactive, this +patch just return budget when the rx is not completed to avoid +dead loop. + +Fixes: 36eedfde1a36 ("net: hns: Optimize hns_nic_common_poll for better performance") +Fixes: b5996f11ea54 ("net: add Hisilicon Network Subsystem basic ethernet support") +Signed-off-by: Yonglong Liu +Signed-off-by: David S. Miller +Signed-off-by: Jiri Slaby +--- + drivers/net/ethernet/hisilicon/hns/hns_enet.c | 4 +--- + 1 file changed, 1 insertion(+), 3 deletions(-) + +--- a/drivers/net/ethernet/hisilicon/hns/hns_enet.c ++++ b/drivers/net/ethernet/hisilicon/hns/hns_enet.c +@@ -674,7 +674,6 @@ static int hns_nic_poll_rx_skb(struct hn + skb = *out_skb = napi_alloc_skb(&ring_data->napi, + HNS_RX_HEAD_SIZE); + if (unlikely(!skb)) { +- netdev_err(ndev, "alloc rx skb fail\n"); + ring->stats.sw_err_cnt++; + return -ENOMEM; + } +@@ -1182,7 +1181,6 @@ static int hns_nic_common_poll(struct na + container_of(napi, struct hns_nic_ring_data, napi); + struct hnae_ring *ring = ring_data->ring; + +-try_again: + clean_complete += ring_data->poll_one( + ring_data, budget - clean_complete, + ring_data->ex_process); +@@ -1192,7 +1190,7 @@ try_again: + napi_complete(napi); + ring->q->handle->dev->ops->toggle_ring_irq(ring, 0); + } else { +- goto try_again; ++ return budget; + } + } + diff --git a/patches.suse/net-hns3-fix-a-copying-IPv6-address-error-in-hclge_f.patch b/patches.suse/net-hns3-fix-a-copying-IPv6-address-error-in-hclge_f.patch new file mode 100644 index 0000000..4943fa2 --- /dev/null +++ b/patches.suse/net-hns3-fix-a-copying-IPv6-address-error-in-hclge_f.patch @@ -0,0 +1,57 @@ +From: Guangbin Huang +Date: Fri, 14 Feb 2020 09:53:43 +0800 +Subject: net: hns3: fix a copying IPv6 address error in + hclge_fd_get_flow_tuples() +Patch-mainline: v5.6-rc2 +Git-commit: 47327c9315b2f3ae4ab659457977a26669631f20 +References: bsc#1104353 FATE#326415 + +The IPv6 address defined in struct in6_addr is specified as +big endian, but there is no specified endian in struct +hclge_fd_rule_tuples, so it will cause a problem if directly +use memcpy() to copy ipv6 address between these two structures +since this field in struct hclge_fd_rule_tuples is little endian. + +This patch fixes this problem by using be32_to_cpu() to convert +endian of IPv6 address of struct in6_addr before copying. + +Fixes: d93ed94fbeaf ("net: hns3: add aRFS support for PF") +Signed-off-by: Guangbin Huang +Signed-off-by: Huazhong Tan +Signed-off-by: David S. Miller +Acked-by: Thomas Bogendoerfer +--- + drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c | 15 +++++++++------ + 1 file changed, 9 insertions(+), 6 deletions(-) + +--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c ++++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +@@ -5395,6 +5395,9 @@ static int hclge_get_all_rules(struct hn + static void hclge_fd_get_flow_tuples(const struct flow_keys *fkeys, + struct hclge_fd_rule_tuples *tuples) + { ++#define flow_ip6_src fkeys->addrs.v6addrs.src.in6_u.u6_addr32 ++#define flow_ip6_dst fkeys->addrs.v6addrs.dst.in6_u.u6_addr32 ++ + tuples->ether_proto = be16_to_cpu(fkeys->basic.n_proto); + tuples->ip_proto = fkeys->basic.ip_proto; + tuples->dst_port = be16_to_cpu(fkeys->ports.dst); +@@ -5403,12 +5406,12 @@ static void hclge_fd_get_flow_tuples(con + tuples->src_ip[3] = be32_to_cpu(fkeys->addrs.v4addrs.src); + tuples->dst_ip[3] = be32_to_cpu(fkeys->addrs.v4addrs.dst); + } else { +- memcpy(tuples->src_ip, +- fkeys->addrs.v6addrs.src.in6_u.u6_addr32, +- sizeof(tuples->src_ip)); +- memcpy(tuples->dst_ip, +- fkeys->addrs.v6addrs.dst.in6_u.u6_addr32, +- sizeof(tuples->dst_ip)); ++ int i; ++ ++ for (i = 0; i < IPV6_SIZE; i++) { ++ tuples->src_ip[i] = be32_to_cpu(flow_ip6_src[i]); ++ tuples->dst_ip[i] = be32_to_cpu(flow_ip6_dst[i]); ++ } + } + } + diff --git a/patches.suse/net-hsr-fix-possible-NULL-deref-in-hsr_handle_frame.patch b/patches.suse/net-hsr-fix-possible-NULL-deref-in-hsr_handle_frame.patch new file mode 100644 index 0000000..cd7210d --- /dev/null +++ b/patches.suse/net-hsr-fix-possible-NULL-deref-in-hsr_handle_frame.patch @@ -0,0 +1,60 @@ +From: Eric Dumazet +Date: Mon, 3 Feb 2020 10:15:07 -0800 +Subject: net: hsr: fix possible NULL deref in hsr_handle_frame() +Git-commit: 2b5b8251bc9fe2f9118411f037862ee17cf81e97 +Patch-mainline: 5.6-rc1 +References: networking-stable-20_02_05 + +hsr_port_get_rcu() can return NULL, so we need to be careful. + +general protection fault, probably for non-canonical address 0xdffffc0000000006: 0000 [#1] PREEMPT SMP KASAN +KASAN: null-ptr-deref in range [0x0000000000000030-0x0000000000000037] +CPU: 1 PID: 10249 Comm: syz-executor.5 Not tainted 5.5.0-syzkaller #0 +Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011 +RIP: 0010:__read_once_size include/linux/compiler.h:199 [inline] +RIP: 0010:hsr_addr_is_self+0x86/0x330 net/hsr/hsr_framereg.c:44 +Code: 04 00 f3 f3 f3 65 48 8b 04 25 28 00 00 00 48 89 45 d0 31 c0 e8 6b ff 94 f9 4c 89 f2 48 b8 00 00 00 00 00 fc ff df 48 c1 ea 03 <80> 3c 02 00 0f 85 75 02 00 00 48 8b 43 30 49 39 c6 49 89 47 c0 0f +RSP: 0018:ffffc90000da8a90 EFLAGS: 00010206 +RAX: dffffc0000000000 RBX: 0000000000000000 RCX: ffffffff87e0cc33 +RDX: 0000000000000006 RSI: ffffffff87e035d5 RDI: 0000000000000000 +RBP: ffffc90000da8b20 R08: ffff88808e7de040 R09: ffffed1015d2707c +R10: ffffed1015d2707b R11: ffff8880ae9383db R12: ffff8880a689bc5e +R13: 1ffff920001b5153 R14: 0000000000000030 R15: ffffc90000da8af8 +FS: 00007fd7a42be700(0000) GS:ffff8880ae900000(0000) knlGS:0000000000000000 +CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 +CR2: 0000001b32338000 CR3: 00000000a928c000 CR4: 00000000001406e0 +DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 +DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 +Call Trace: + + hsr_handle_frame+0x1c5/0x630 net/hsr/hsr_slave.c:31 + __netif_receive_skb_core+0xfbc/0x30b0 net/core/dev.c:5099 + __netif_receive_skb_one_core+0xa8/0x1a0 net/core/dev.c:5196 + __netif_receive_skb+0x2c/0x1d0 net/core/dev.c:5312 + process_backlog+0x206/0x750 net/core/dev.c:6144 + napi_poll net/core/dev.c:6582 [inline] + net_rx_action+0x508/0x1120 net/core/dev.c:6650 + __do_softirq+0x262/0x98c kernel/softirq.c:292 + do_softirq_own_stack+0x2a/0x40 arch/x86/entry/entry_64.S:1082 + + +Fixes: c5a759117210 ("net/hsr: Use list_head (and rcu) instead of array for slave devices.") +Signed-off-by: Eric Dumazet +Reported-by: syzbot +Signed-off-by: David S. Miller +Signed-off-by: Jiri Slaby +--- + net/hsr/hsr_slave.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/net/hsr/hsr_slave.c ++++ b/net/hsr/hsr_slave.c +@@ -32,6 +32,8 @@ static rx_handler_result_t hsr_handle_fr + + rcu_read_lock(); /* hsr->node_db, hsr->ports */ + port = hsr_port_get_rcu(skb->dev); ++ if (!port) ++ goto finish_pass; + + if (hsr_addr_is_self(port->hsr, eth_hdr(skb)->h_source)) { + /* Directly kill frames sent by ourselves */ diff --git a/patches.suse/net-ip6_gre-fix-moving-ip6gre-between-namespaces.patch b/patches.suse/net-ip6_gre-fix-moving-ip6gre-between-namespaces.patch new file mode 100644 index 0000000..3e82227 --- /dev/null +++ b/patches.suse/net-ip6_gre-fix-moving-ip6gre-between-namespaces.patch @@ -0,0 +1,36 @@ +From: Niko Kortstrom +Date: Thu, 16 Jan 2020 11:43:27 +0200 +Subject: net: ip6_gre: fix moving ip6gre between namespaces +Git-commit: 690afc165bb314354667f67157c1a1aea7dc797a +Patch-mainline: 5.5 +References: networking-stable-20_01_27 + +Support for moving IPv4 GRE tunnels between namespaces was added in +commit b57708add314 ("gre: add x-netns support"). The respective change +for IPv6 tunnels, commit 22f08069e8b4 ("ip6gre: add x-netns support") +did not drop NETIF_F_NETNS_LOCAL flag so moving them from one netns to +another is still denied in IPv6 case. Drop NETIF_F_NETNS_LOCAL flag from +ip6gre tunnels to allow moving ip6gre tunnel endpoints between network +namespaces. + +[js] no ERSPAN and collect_md support in 4.12 + +Signed-off-by: Niko Kortstrom +Acked-by: Nicolas Dichtel +Acked-by: William Tu +Signed-off-by: David S. Miller +Signed-off-by: Jiri Slaby +--- + net/ipv6/ip6_gre.c | 1 - + 1 file changed, 1 deletion(-) + +--- a/net/ipv6/ip6_gre.c ++++ b/net/ipv6/ip6_gre.c +@@ -1345,7 +1345,6 @@ static void ip6gre_tap_setup(struct net_ + dev->needs_free_netdev = true; + dev->priv_destructor = ip6gre_dev_free; + +- dev->features |= NETIF_F_NETNS_LOCAL; + dev->priv_flags &= ~IFF_TX_SKB_SHARING; + dev->priv_flags |= IFF_LIVE_ADDR_CHANGE; + netif_keep_dst(dev); diff --git a/patches.suse/net-ip6_tunnel-fix-namespaces-move.patch b/patches.suse/net-ip6_tunnel-fix-namespaces-move.patch new file mode 100644 index 0000000..6e30db3 --- /dev/null +++ b/patches.suse/net-ip6_tunnel-fix-namespaces-move.patch @@ -0,0 +1,40 @@ +From: William Dauchy +Date: Tue, 21 Jan 2020 21:49:54 +0100 +Subject: net, ip6_tunnel: fix namespaces move +Git-commit: 5311a69aaca30fa849c3cc46fb25f75727fb72d0 +Patch-mainline: 5.5 +References: networking-stable-20_01_27 + +in the same manner as commit d0f418516022 ("net, ip_tunnel: fix +namespaces move"), fix namespace moving as it was broken since commit +8d79266bc48c ("ip6_tunnel: add collect_md mode to IPv6 tunnel"), but for +ipv6 this time; there is no reason to keep it for ip6_tunnel. + +Fixes: 8d79266bc48c ("ip6_tunnel: add collect_md mode to IPv6 tunnel") +Signed-off-by: William Dauchy +Acked-by: Nicolas Dichtel +Signed-off-by: David S. Miller +Signed-off-by: Jiri Slaby +--- + net/ipv6/ip6_tunnel.c | 4 +--- + 1 file changed, 1 insertion(+), 3 deletions(-) + +diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c +index 2f376dbc37d5..b5dd20c4599b 100644 +--- a/net/ipv6/ip6_tunnel.c ++++ b/net/ipv6/ip6_tunnel.c +@@ -1877,10 +1877,8 @@ static int ip6_tnl_dev_init(struct net_device *dev) + if (err) + return err; + ip6_tnl_link_config(t); +- if (t->parms.collect_md) { +- dev->features |= NETIF_F_NETNS_LOCAL; ++ if (t->parms.collect_md) + netif_keep_dst(dev); +- } + return 0; + } + +-- +2.25.1 + diff --git a/patches.suse/net-ip_tunnel-fix-namespaces-move.patch b/patches.suse/net-ip_tunnel-fix-namespaces-move.patch new file mode 100644 index 0000000..d87312f --- /dev/null +++ b/patches.suse/net-ip_tunnel-fix-namespaces-move.patch @@ -0,0 +1,43 @@ +From: William Dauchy +Date: Tue, 21 Jan 2020 15:26:24 +0100 +Subject: net, ip_tunnel: fix namespaces move +Git-commit: d0f418516022c32ecceaf4275423e5bd3f8743a9 +Patch-mainline: 5.5 +References: networking-stable-20_01_27 + +in the same manner as commit 690afc165bb3 ("net: ip6_gre: fix moving +ip6gre between namespaces"), fix namespace moving as it was broken since +commit 2e15ea390e6f ("ip_gre: Add support to collect tunnel metadata."). +Indeed, the ip6_gre commit removed the local flag for collect_md +condition, so there is no reason to keep it for ip_gre/ip_tunnel. + +this patch will fix both ip_tunnel and ip_gre modules. + +Fixes: 2e15ea390e6f ("ip_gre: Add support to collect tunnel metadata.") +Signed-off-by: William Dauchy +Acked-by: Nicolas Dichtel +Signed-off-by: David S. Miller +Signed-off-by: Jiri Slaby +--- + net/ipv4/ip_tunnel.c | 4 +--- + 1 file changed, 1 insertion(+), 3 deletions(-) + +diff --git a/net/ipv4/ip_tunnel.c b/net/ipv4/ip_tunnel.c +index 0fe2a5d3e258..74e1d964a615 100644 +--- a/net/ipv4/ip_tunnel.c ++++ b/net/ipv4/ip_tunnel.c +@@ -1236,10 +1236,8 @@ int ip_tunnel_init(struct net_device *dev) + iph->version = 4; + iph->ihl = 5; + +- if (tunnel->collect_md) { +- dev->features |= NETIF_F_NETNS_LOCAL; ++ if (tunnel->collect_md) + netif_keep_dst(dev); +- } + return 0; + } + EXPORT_SYMBOL_GPL(ip_tunnel_init); +-- +2.25.1 + diff --git a/patches.suse/net-macb-Limit-maximum-GEM-TX-length-in-TSO.patch b/patches.suse/net-macb-Limit-maximum-GEM-TX-length-in-TSO.patch new file mode 100644 index 0000000..0696473 --- /dev/null +++ b/patches.suse/net-macb-Limit-maximum-GEM-TX-length-in-TSO.patch @@ -0,0 +1,39 @@ +From: Harini Katakam +Date: Wed, 5 Feb 2020 18:08:12 +0530 +Subject: net: macb: Limit maximum GEM TX length in TSO +Git-commit: f822e9c4ffa511a5c681cf866287d9383a3b6f1b +Patch-mainline: 5.6-rc1 +References: networking-stable-20_02_09 + +GEM_MAX_TX_LEN currently resolves to 0x3FF8 for any IP version supporting +TSO with full 14bits of length field in payload descriptor. But an IP +errata causes false amba_error (bit 6 of ISR) when length in payload +descriptors is specified above 16387. The error occurs because the DMA +falsely concludes that there is not enough space in SRAM for incoming +payload. These errors were observed continuously under stress of large +packets using iperf on a version where SRAM was 16K for each queue. This +errata will be documented shortly and affects all versions since TSO +functionality was added. Hence limit the max length to 0x3FC0 (rounded). + +Signed-off-by: Harini Katakam +Signed-off-by: David S. Miller +Signed-off-by: Jiri Slaby +--- + drivers/net/ethernet/cadence/macb.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +--- a/drivers/net/ethernet/cadence/macb.c ++++ b/drivers/net/ethernet/cadence/macb.c +@@ -66,7 +66,11 @@ + /* Max length of transmit frame must be a multiple of 8 bytes */ + #define MACB_TX_LEN_ALIGN 8 + #define MACB_MAX_TX_LEN ((unsigned int)((1 << MACB_TX_FRMLEN_SIZE) - 1) & ~((unsigned int)(MACB_TX_LEN_ALIGN - 1))) +-#define GEM_MAX_TX_LEN ((unsigned int)((1 << GEM_TX_FRMLEN_SIZE) - 1) & ~((unsigned int)(MACB_TX_LEN_ALIGN - 1))) ++/* Limit maximum TX length as per Cadence TSO errata. This is to avoid a ++ * false amba_error in TX path from the DMA assuming there is not enough ++ * space in the SRAM (16KB) even when there is. ++ */ ++#define GEM_MAX_TX_LEN (unsigned int)(0x3FC0) + + #define GEM_MTU_MIN_SIZE ETH_MIN_MTU + #define MACB_NETIF_LSO NETIF_F_TSO diff --git a/patches.suse/net-macb-Remove-unnecessary-alignment-check-for-TSO.patch b/patches.suse/net-macb-Remove-unnecessary-alignment-check-for-TSO.patch new file mode 100644 index 0000000..cff741f --- /dev/null +++ b/patches.suse/net-macb-Remove-unnecessary-alignment-check-for-TSO.patch @@ -0,0 +1,45 @@ +From: Harini Katakam +Date: Wed, 5 Feb 2020 18:08:11 +0530 +Subject: net: macb: Remove unnecessary alignment check for TSO +Git-commit: 41c1ef978c8d0259c6636e6d2d854777e92650eb +Patch-mainline: 5.6-rc1 +References: networking-stable-20_02_09 + +The IP TSO implementation does NOT require the length to be a +multiple of 8. That is only a requirement for UFO as per IP +documentation. Hence, exit macb_features_check function in the +beginning if the protocol is not UDP. Only when it is UDP, +proceed further to the alignment checks. Update comments to +reflect the same. Also remove dead code checking for protocol +TCP when calculating header length. + +Fixes: 1629dd4f763c ("cadence: Add LSO support.") +Signed-off-by: Harini Katakam +Signed-off-by: David S. Miller +Signed-off-by: Jiri Slaby +--- + drivers/net/ethernet/cadence/macb.c | 8 +++----- + 1 file changed, 3 insertions(+), 5 deletions(-) + +--- a/drivers/net/ethernet/cadence/macb.c ++++ b/drivers/net/ethernet/cadence/macb.c +@@ -1489,16 +1489,14 @@ static netdev_features_t macb_features_c + + /* Validate LSO compatibility */ + +- /* there is only one buffer */ +- if (!skb_is_nonlinear(skb)) ++ /* there is only one buffer or protocol is not UDP */ ++ if (!skb_is_nonlinear(skb) || (ip_hdr(skb)->protocol != IPPROTO_UDP)) + return features; + + /* length of header */ + hdrlen = skb_transport_offset(skb); +- if (ip_hdr(skb)->protocol == IPPROTO_TCP) +- hdrlen += tcp_hdrlen(skb); + +- /* For LSO: ++ /* For UFO only: + * When software supplies two or more payload buffers all payload buffers + * apart from the last must be a multiple of 8 bytes in size. + */ diff --git a/patches.suse/net-mlx5-Fix-lowest-FDB-pool-size.patch b/patches.suse/net-mlx5-Fix-lowest-FDB-pool-size.patch new file mode 100644 index 0000000..9b87696 --- /dev/null +++ b/patches.suse/net-mlx5-Fix-lowest-FDB-pool-size.patch @@ -0,0 +1,35 @@ +From: Paul Blakey +Date: Tue, 31 Dec 2019 17:04:15 +0200 +Subject: net/mlx5: Fix lowest FDB pool size +Patch-mainline: v5.5 +Git-commit: 93b8a7ecb7287cc9b0196f12a25b57c2462d11dc +References: bsc#1103990 FATE#326006 + +The pool sizes represent the pool sizes in the fw. when we request +a pool size from fw, it will return the next possible group. +We track how many pools the fw has left and start requesting groups +from the big to the small. +When we start request 4k group, which doesn't exists in fw, fw +wants to allocate the next possible size, 64k, but will fail since +its exhausted. The correct smallest pool size in fw is 128 and not 4k. + +Fixes: e52c28024008 ("net/mlx5: E-Switch, Add chains and priorities") +Signed-off-by: Paul Blakey +Reviewed-by: Roi Dayan +Signed-off-by: Saeed Mahameed +Acked-by: Thomas Bogendoerfer +--- + drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c +@@ -602,7 +602,7 @@ out: + */ + #define ESW_SIZE (16 * 1024 * 1024) + const unsigned int ESW_POOLS[4] = { 4 * 1024 * 1024, 1 * 1024 * 1024, +- 64 * 1024, 4 * 1024 }; ++ 64 * 1024, 128 }; + + static int + get_sz_from_pool(struct mlx5_eswitch *esw) diff --git a/patches.suse/net-mlx5-IPsec-Fix-esp-modify-function-attribute.patch b/patches.suse/net-mlx5-IPsec-Fix-esp-modify-function-attribute.patch new file mode 100644 index 0000000..286e39c --- /dev/null +++ b/patches.suse/net-mlx5-IPsec-Fix-esp-modify-function-attribute.patch @@ -0,0 +1,33 @@ +From: Raed Salem +Date: Tue, 24 Dec 2019 09:54:45 +0200 +Subject: net/mlx5: IPsec, Fix esp modify function attribute +Patch-mainline: v5.6-rc1 +Git-commit: 0dc2c534f17c05bed0622b37a744bc38b48ca88a +References: bsc#1103990 FATE#326006 + +The function mlx5_fpga_esp_validate_xfrm_attrs is wrongly used +with negative negation as zero value indicates success but it +used as failure return value instead. + +Fix by remove the unary not negation operator. + +Fixes: 05564d0ae075 ("net/mlx5: Add flow-steering commands for FPGA IPSec implementation") +Signed-off-by: Raed Salem +Reviewed-by: Boris Pismenny +Signed-off-by: Saeed Mahameed +Acked-by: Thomas Bogendoerfer +--- + drivers/net/ethernet/mellanox/mlx5/core/fpga/ipsec.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/net/ethernet/mellanox/mlx5/core/fpga/ipsec.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/fpga/ipsec.c +@@ -1472,7 +1472,7 @@ int mlx5_fpga_esp_modify_xfrm(struct mlx + if (!memcmp(&xfrm->attrs, attrs, sizeof(xfrm->attrs))) + return 0; + +- if (!mlx5_fpga_esp_validate_xfrm_attrs(mdev, attrs)) { ++ if (mlx5_fpga_esp_validate_xfrm_attrs(mdev, attrs)) { + mlx5_core_warn(mdev, "Tried to create an esp with unsupported attrs\n"); + return -EOPNOTSUPP; + } diff --git a/patches.suse/net-mlx5-IPsec-fix-memory-leak-at-mlx5_fpga_ipsec_de.patch b/patches.suse/net-mlx5-IPsec-fix-memory-leak-at-mlx5_fpga_ipsec_de.patch new file mode 100644 index 0000000..806c58c --- /dev/null +++ b/patches.suse/net-mlx5-IPsec-fix-memory-leak-at-mlx5_fpga_ipsec_de.patch @@ -0,0 +1,33 @@ +From: Raed Salem +Date: Wed, 23 Oct 2019 16:41:21 +0300 +Subject: net/mlx5: IPsec, fix memory leak at mlx5_fpga_ipsec_delete_sa_ctx +Patch-mainline: v5.6-rc1 +Git-commit: 08db2cf577487f5123aebcc2f913e0b8a2c14b43 +References: bsc#1103990 FATE#326006 + +SA context is allocated at mlx5_fpga_ipsec_create_sa_ctx, +however the counterpart mlx5_fpga_ipsec_delete_sa_ctx function +nullifies sa_ctx pointer without freeing the memory allocated, +hence the memory leak. + +Fix by free SA context when the SA is released. + +Fixes: d6c4f0298cec ("net/mlx5: Refactor accel IPSec code") +Signed-off-by: Raed Salem +Reviewed-by: Boris Pismenny +Signed-off-by: Saeed Mahameed +Acked-by: Thomas Bogendoerfer +--- + drivers/net/ethernet/mellanox/mlx5/core/fpga/ipsec.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/net/ethernet/mellanox/mlx5/core/fpga/ipsec.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/fpga/ipsec.c +@@ -848,6 +848,7 @@ void mlx5_fpga_ipsec_delete_sa_ctx(void + mutex_lock(&fpga_xfrm->lock); + if (!--fpga_xfrm->num_rules) { + mlx5_fpga_ipsec_release_sa_ctx(fpga_xfrm->sa_ctx); ++ kfree(fpga_xfrm->sa_ctx); + fpga_xfrm->sa_ctx = NULL; + } + mutex_unlock(&fpga_xfrm->lock); diff --git a/patches.suse/net-mlx5-Update-the-list-of-the-PCI-supported-device-505a7f54.patch b/patches.suse/net-mlx5-Update-the-list-of-the-PCI-supported-device-505a7f54.patch new file mode 100644 index 0000000..892490a --- /dev/null +++ b/patches.suse/net-mlx5-Update-the-list-of-the-PCI-supported-device-505a7f54.patch @@ -0,0 +1,28 @@ +From: Meir Lichtinger +Date: Thu, 12 Dec 2019 16:09:33 +0200 +Subject: net/mlx5: Update the list of the PCI supported devices +Patch-mainline: v5.5 +Git-commit: 505a7f5478062c6cd11e22022d9f1bf64cd8eab3 +References: bsc#1127611 + +Add the upcoming ConnectX-7 device ID. + +Fixes: 85327a9c4150 ("net/mlx5: Update the list of the PCI supported devices") +Signed-off-by: Meir Lichtinger +Reviewed-by: Eran Ben Elisha +Signed-off-by: Saeed Mahameed +Acked-by: Thomas Bogendoerfer +--- + drivers/net/ethernet/mellanox/mlx5/core/main.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/net/ethernet/mellanox/mlx5/core/main.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/main.c +@@ -1652,6 +1652,7 @@ static const struct pci_device_id mlx5_c + { PCI_VDEVICE(MELLANOX, 0x101d) }, /* ConnectX-6 Dx */ + { PCI_VDEVICE(MELLANOX, 0x101e), MLX5_PCI_DEV_IS_VF}, /* ConnectX Family mlx5Gen Virtual Function */ + { PCI_VDEVICE(MELLANOX, 0x101f) }, /* ConnectX-6 LX */ ++ { PCI_VDEVICE(MELLANOX, 0x1021) }, /* ConnectX-7 */ + { PCI_VDEVICE(MELLANOX, 0xa2d2) }, /* BlueField integrated ConnectX-5 network controller */ + { PCI_VDEVICE(MELLANOX, 0xa2d3), MLX5_PCI_DEV_IS_VF}, /* BlueField integrated ConnectX-5 network controller VF */ + { PCI_VDEVICE(MELLANOX, 0xa2d6) }, /* BlueField-2 integrated ConnectX-6 Dx network controller */ diff --git a/patches.suse/net-mlxfw-Verify-FSM-error-code-translation-doesn-t-.patch b/patches.suse/net-mlxfw-Verify-FSM-error-code-translation-doesn-t-.patch new file mode 100644 index 0000000..1dfb88b --- /dev/null +++ b/patches.suse/net-mlxfw-Verify-FSM-error-code-translation-doesn-t-.patch @@ -0,0 +1,33 @@ +From: Eran Ben Elisha +Date: Sun, 17 Nov 2019 10:18:59 +0200 +Subject: net/mlxfw: Verify FSM error code translation doesn't exceed array + size +Patch-mainline: v5.4 +Git-commit: 30e9e0550bf693c94bc15827781fe42dd60be634 +References: bsc#1051858 + +Array mlxfw_fsm_state_err_str contains value to string translation, when +values are provided by mlxfw_dev. If value is larger than +MLXFW_FSM_STATE_ERR_MAX, return "unknown error" as expected instead of +reading an address than exceed array size. + +Fixes: 410ed13cae39 ("Add the mlxfw module for Mellanox firmware flash process") +Signed-off-by: Eran Ben Elisha +Acked-by: Jiri Pirko +Signed-off-by: Saeed Mahameed +Acked-by: Thomas Bogendoerfer +--- + drivers/net/ethernet/mellanox/mlxfw/mlxfw_fsm.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/drivers/net/ethernet/mellanox/mlxfw/mlxfw_fsm.c ++++ b/drivers/net/ethernet/mellanox/mlxfw/mlxfw_fsm.c +@@ -86,6 +86,8 @@ retry: + return err; + + if (fsm_state_err != MLXFW_FSM_STATE_ERR_OK) { ++ fsm_state_err = min_t(enum mlxfw_fsm_state_err, ++ fsm_state_err, MLXFW_FSM_STATE_ERR_MAX); + pr_err("Firmware flash failed: %s\n", + mlxfw_fsm_state_err_str[fsm_state_err]); + return -EINVAL; diff --git a/patches.suse/net-mvneta-move-rx_dropped-and-rx_errors-in-per-cpu-.patch b/patches.suse/net-mvneta-move-rx_dropped-and-rx_errors-in-per-cpu-.patch new file mode 100644 index 0000000..3338caa --- /dev/null +++ b/patches.suse/net-mvneta-move-rx_dropped-and-rx_errors-in-per-cpu-.patch @@ -0,0 +1,95 @@ +From: Lorenzo Bianconi +Date: Thu, 6 Feb 2020 10:14:39 +0100 +Subject: net: mvneta: move rx_dropped and rx_errors in per-cpu stats +Git-commit: c35947b8ff8acca33134ee39c31708233765c31a +Patch-mainline: 5.6-rc1 +References: networking-stable-20_02_09 + +Move rx_dropped and rx_errors counters in mvneta_pcpu_stats in order to +avoid possible races updating statistics + +Fixes: 562e2f467e71 ("net: mvneta: Improve the buffer allocation method for SWBM") +Fixes: dc35a10f68d3 ("net: mvneta: bm: add support for hardware buffer management") +Fixes: c5aff18204da ("net: mvneta: driver for Marvell Armada 370/XP network unit") +Signed-off-by: Lorenzo Bianconi +Signed-off-by: David S. Miller +Signed-off-by: Jiri Slaby +--- + drivers/net/ethernet/marvell/mvneta.c | 19 ++++++++++++++----- + 1 file changed, 14 insertions(+), 5 deletions(-) + +--- a/drivers/net/ethernet/marvell/mvneta.c ++++ b/drivers/net/ethernet/marvell/mvneta.c +@@ -361,6 +361,8 @@ struct mvneta_pcpu_stats { + struct u64_stats_sync syncp; + u64 rx_packets; + u64 rx_bytes; ++ u64 rx_dropped; ++ u64 rx_errors; + u64 tx_packets; + u64 tx_bytes; + }; +@@ -665,6 +667,8 @@ mvneta_get_stats64(struct net_device *de + struct mvneta_pcpu_stats *cpu_stats; + u64 rx_packets; + u64 rx_bytes; ++ u64 rx_dropped; ++ u64 rx_errors; + u64 tx_packets; + u64 tx_bytes; + +@@ -673,19 +677,20 @@ mvneta_get_stats64(struct net_device *de + start = u64_stats_fetch_begin_irq(&cpu_stats->syncp); + rx_packets = cpu_stats->rx_packets; + rx_bytes = cpu_stats->rx_bytes; ++ rx_dropped = cpu_stats->rx_dropped; ++ rx_errors = cpu_stats->rx_errors; + tx_packets = cpu_stats->tx_packets; + tx_bytes = cpu_stats->tx_bytes; + } while (u64_stats_fetch_retry_irq(&cpu_stats->syncp, start)); + + stats->rx_packets += rx_packets; + stats->rx_bytes += rx_bytes; ++ stats->rx_dropped += rx_dropped; ++ stats->rx_errors += rx_errors; + stats->tx_packets += tx_packets; + stats->tx_bytes += tx_bytes; + } + +- stats->rx_errors = dev->stats.rx_errors; +- stats->rx_dropped = dev->stats.rx_dropped; +- + stats->tx_dropped = dev->stats.tx_dropped; + } + +@@ -1704,8 +1709,14 @@ static u32 mvneta_txq_desc_csum(int l3_o + static void mvneta_rx_error(struct mvneta_port *pp, + struct mvneta_rx_desc *rx_desc) + { ++ struct mvneta_pcpu_stats *stats = this_cpu_ptr(pp->stats); + u32 status = rx_desc->status; + ++ /* update per-cpu counter */ ++ u64_stats_update_begin(&stats->syncp); ++ stats->rx_errors++; ++ u64_stats_update_end(&stats->syncp); ++ + if (!mvneta_rxq_desc_is_first_last(status)) { + netdev_err(pp->dev, + "bad rx status %08x (buffer oversize), size=%d\n", +@@ -1960,7 +1971,6 @@ static int mvneta_rx_swbm(struct napi_st + (rx_status & MVNETA_RXD_ERR_SUMMARY)) { + mvneta_rx_error(pp, rx_desc); + err_drop_frame: +- dev->stats.rx_errors++; + /* leave the descriptor untouched */ + continue; + } +@@ -2085,7 +2095,6 @@ err_drop_frame_ret_pool: + mvneta_bm_pool_put_bp(pp->bm_priv, bm_pool, + rx_desc->buf_phys_addr); + err_drop_frame: +- dev->stats.rx_errors++; + mvneta_rx_error(pp, rx_desc); + /* leave the descriptor untouched */ + continue; diff --git a/patches.suse/net-nfc-Avoid-stalls-when-nfc_alloc_send_skb-returne.patch b/patches.suse/net-nfc-Avoid-stalls-when-nfc_alloc_send_skb-returne.patch new file mode 100644 index 0000000..70a2a1d --- /dev/null +++ b/patches.suse/net-nfc-Avoid-stalls-when-nfc_alloc_send_skb-returne.patch @@ -0,0 +1,53 @@ +From 3bc53be9db21040b5d2de4d455f023c8c494aa68 Mon Sep 17 00:00:00 2001 +From: Tetsuo Handa +Date: Wed, 18 Jul 2018 18:57:27 +0900 +Subject: [PATCH] net/nfc: Avoid stalls when nfc_alloc_send_skb() returned NULL. +Git-commit: 3bc53be9db21040b5d2de4d455f023c8c494aa68 +Patch-mainline: v4.18-rc6 +References: bsc#1051510 + +syzbot is reporting stalls at nfc_llcp_send_ui_frame() [1]. This is +because nfc_llcp_send_ui_frame() is retrying the loop without any delay +when nonblocking nfc_alloc_send_skb() returned NULL. + +Since there is no need to use MSG_DONTWAIT if we retry until +sock_alloc_send_pskb() succeeds, let's use blocking call. +Also, in case an unexpected error occurred, let's break the loop +if blocking nfc_alloc_send_skb() failed. + +[1] https://syzkaller.appspot.com/bug?id=4a131cc571c3733e0eff6bc673f4e36ae48f19c6 + +Signed-off-by: Tetsuo Handa +Reported-by: syzbot +Signed-off-by: David S. Miller +Acked-by: Takashi Iwai + +--- + net/nfc/llcp_commands.c | 9 ++++++--- + 1 file changed, 6 insertions(+), 3 deletions(-) + +diff --git a/net/nfc/llcp_commands.c b/net/nfc/llcp_commands.c +index 2ceefa183cee..6a196e438b6c 100644 +--- a/net/nfc/llcp_commands.c ++++ b/net/nfc/llcp_commands.c +@@ -752,11 +752,14 @@ int nfc_llcp_send_ui_frame(struct nfc_llcp_sock *sock, u8 ssap, u8 dsap, + pr_debug("Fragment %zd bytes remaining %zd", + frag_len, remaining_len); + +- pdu = nfc_alloc_send_skb(sock->dev, &sock->sk, MSG_DONTWAIT, ++ pdu = nfc_alloc_send_skb(sock->dev, &sock->sk, 0, + frag_len + LLCP_HEADER_SIZE, &err); + if (pdu == NULL) { +- pr_err("Could not allocate PDU\n"); +- continue; ++ pr_err("Could not allocate PDU (error=%d)\n", err); ++ len -= remaining_len; ++ if (len == 0) ++ len = err; ++ break; + } + + pdu = llcp_add_header(pdu, dsap, ssap, LLCP_PDU_UI); +-- +2.16.4 + diff --git a/patches.suse/net-nfc-fix-bounds-checking-bugs-on-pipe.patch b/patches.suse/net-nfc-fix-bounds-checking-bugs-on-pipe.patch new file mode 100644 index 0000000..37ddc02 --- /dev/null +++ b/patches.suse/net-nfc-fix-bounds-checking-bugs-on-pipe.patch @@ -0,0 +1,72 @@ +From a3aefbfe45751bf7b338c181b97608e276b5bb73 Mon Sep 17 00:00:00 2001 +From: Dan Carpenter +Date: Wed, 4 Mar 2020 17:24:31 +0300 +Subject: [PATCH] net: nfc: fix bounds checking bugs on "pipe" +Git-commit: a3aefbfe45751bf7b338c181b97608e276b5bb73 +Patch-mainline: v5.6-rc6 +References: bsc#1051510 + +This is similar to commit 674d9de02aa7 ("NFC: Fix possible memory +corruption when handling SHDLC I-Frame commands") and commit d7ee81ad09f0 +("nfc: nci: Add some bounds checking in nci_hci_cmd_received()") which +added range checks on "pipe". + +The "pipe" variable comes skb->data[0] in nfc_hci_msg_rx_work(). +It's in the 0-255 range. We're using it as the array index into the +hdev->pipes[] array which has NFC_HCI_MAX_PIPES (128) members. + +Fixes: 118278f20aa8 ("NFC: hci: Add pipes table to reference them with a tuple {gate, host}") +Signed-off-by: Dan Carpenter +Signed-off-by: David S. Miller +Acked-by: Takashi Iwai + +--- + net/nfc/hci/core.c | 19 ++++++++++++++++--- + 1 file changed, 16 insertions(+), 3 deletions(-) + +diff --git a/net/nfc/hci/core.c b/net/nfc/hci/core.c +index 6f1b096e601c..43811b5219b5 100644 +--- a/net/nfc/hci/core.c ++++ b/net/nfc/hci/core.c +@@ -181,13 +181,20 @@ void nfc_hci_resp_received(struct nfc_hci_dev *hdev, u8 result, + void nfc_hci_cmd_received(struct nfc_hci_dev *hdev, u8 pipe, u8 cmd, + struct sk_buff *skb) + { +- u8 gate = hdev->pipes[pipe].gate; + u8 status = NFC_HCI_ANY_OK; + struct hci_create_pipe_resp *create_info; + struct hci_delete_pipe_noti *delete_info; + struct hci_all_pipe_cleared_noti *cleared_info; ++ u8 gate; + +- pr_debug("from gate %x pipe %x cmd %x\n", gate, pipe, cmd); ++ pr_debug("from pipe %x cmd %x\n", pipe, cmd); ++ ++ if (pipe >= NFC_HCI_MAX_PIPES) { ++ status = NFC_HCI_ANY_E_NOK; ++ goto exit; ++ } ++ ++ gate = hdev->pipes[pipe].gate; + + switch (cmd) { + case NFC_HCI_ADM_NOTIFY_PIPE_CREATED: +@@ -375,8 +382,14 @@ void nfc_hci_event_received(struct nfc_hci_dev *hdev, u8 pipe, u8 event, + struct sk_buff *skb) + { + int r = 0; +- u8 gate = hdev->pipes[pipe].gate; ++ u8 gate; ++ ++ if (pipe >= NFC_HCI_MAX_PIPES) { ++ pr_err("Discarded event %x to invalid pipe %x\n", event, pipe); ++ goto exit; ++ } + ++ gate = hdev->pipes[pipe].gate; + if (gate == NFC_HCI_INVALID_GATE) { + pr_err("Discarded event %x to unopened pipe %x\n", event, pipe); + goto exit; +-- +2.16.4 + diff --git a/patches.suse/net-rtnetlink-validate-IFLA_MTU-attribute-in-rtnl_cr.patch b/patches.suse/net-rtnetlink-validate-IFLA_MTU-attribute-in-rtnl_cr.patch new file mode 100644 index 0000000..a00091c --- /dev/null +++ b/patches.suse/net-rtnetlink-validate-IFLA_MTU-attribute-in-rtnl_cr.patch @@ -0,0 +1,177 @@ +From: Eric Dumazet +Date: Tue, 21 Jan 2020 22:47:29 -0800 +Subject: net: rtnetlink: validate IFLA_MTU attribute in rtnl_create_link() +Git-commit: d836f5c69d87473ff65c06a6123e5b2cf5e56f5b +Patch-mainline: 5.5 +References: networking-stable-20_01_27 + +rtnl_create_link() needs to apply dev->min_mtu and dev->max_mtu +checks that we apply in do_setlink() + +Otherwise malicious users can crash the kernel, for example after +an integer overflow : + +BUG: KASAN: use-after-free in memset include/linux/string.h:365 [inline] +BUG: KASAN: use-after-free in __alloc_skb+0x37b/0x5e0 net/core/skbuff.c:238 +Write of size 32 at addr ffff88819f20b9c0 by task swapper/0/0 + +CPU: 0 PID: 0 Comm: swapper/0 Not tainted 5.5.0-rc1-syzkaller #0 +Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011 +Call Trace: + + __dump_stack lib/dump_stack.c:77 [inline] + dump_stack+0x197/0x210 lib/dump_stack.c:118 + print_address_description.constprop.0.cold+0xd4/0x30b mm/kasan/report.c:374 + __kasan_report.cold+0x1b/0x41 mm/kasan/report.c:506 + kasan_report+0x12/0x20 mm/kasan/common.c:639 + check_memory_region_inline mm/kasan/generic.c:185 [inline] + check_memory_region+0x134/0x1a0 mm/kasan/generic.c:192 + memset+0x24/0x40 mm/kasan/common.c:108 + memset include/linux/string.h:365 [inline] + __alloc_skb+0x37b/0x5e0 net/core/skbuff.c:238 + alloc_skb include/linux/skbuff.h:1049 [inline] + alloc_skb_with_frags+0x93/0x590 net/core/skbuff.c:5664 + sock_alloc_send_pskb+0x7ad/0x920 net/core/sock.c:2242 + sock_alloc_send_skb+0x32/0x40 net/core/sock.c:2259 + mld_newpack+0x1d7/0x7f0 net/ipv6/mcast.c:1609 + add_grhead.isra.0+0x299/0x370 net/ipv6/mcast.c:1713 + add_grec+0x7db/0x10b0 net/ipv6/mcast.c:1844 + mld_send_cr net/ipv6/mcast.c:1970 [inline] + mld_ifc_timer_expire+0x3d3/0x950 net/ipv6/mcast.c:2477 + call_timer_fn+0x1ac/0x780 kernel/time/timer.c:1404 + expire_timers kernel/time/timer.c:1449 [inline] + __run_timers kernel/time/timer.c:1773 [inline] + __run_timers kernel/time/timer.c:1740 [inline] + run_timer_softirq+0x6c3/0x1790 kernel/time/timer.c:1786 + __do_softirq+0x262/0x98c kernel/softirq.c:292 + invoke_softirq kernel/softirq.c:373 [inline] + irq_exit+0x19b/0x1e0 kernel/softirq.c:413 + exiting_irq arch/x86/include/asm/apic.h:536 [inline] + smp_apic_timer_interrupt+0x1a3/0x610 arch/x86/kernel/apic/apic.c:1137 + apic_timer_interrupt+0xf/0x20 arch/x86/entry/entry_64.S:829 + +RIP: 0010:native_safe_halt+0xe/0x10 arch/x86/include/asm/irqflags.h:61 +Code: 98 6b ea f9 eb 8a cc cc cc cc cc cc e9 07 00 00 00 0f 00 2d 44 1c 60 00 f4 c3 66 90 e9 07 00 00 00 0f 00 2d 34 1c 60 00 fb f4 cc 55 48 89 e5 41 57 41 56 41 55 41 54 53 e8 4e 5d 9a f9 e8 79 +RSP: 0018:ffffffff89807ce8 EFLAGS: 00000286 ORIG_RAX: ffffffffffffff13 +RAX: 1ffffffff13266ae RBX: ffffffff8987a1c0 RCX: 0000000000000000 +RDX: dffffc0000000000 RSI: 0000000000000006 RDI: ffffffff8987aa54 +RBP: ffffffff89807d18 R08: ffffffff8987a1c0 R09: 0000000000000000 +R10: 0000000000000000 R11: 0000000000000000 R12: dffffc0000000000 +R13: ffffffff8a799980 R14: 0000000000000000 R15: 0000000000000000 + arch_cpu_idle+0xa/0x10 arch/x86/kernel/process.c:690 + default_idle_call+0x84/0xb0 kernel/sched/idle.c:94 + cpuidle_idle_call kernel/sched/idle.c:154 [inline] + do_idle+0x3c8/0x6e0 kernel/sched/idle.c:269 + cpu_startup_entry+0x1b/0x20 kernel/sched/idle.c:361 + rest_init+0x23b/0x371 init/main.c:451 + arch_call_rest_init+0xe/0x1b + start_kernel+0x904/0x943 init/main.c:784 + x86_64_start_reservations+0x29/0x2b arch/x86/kernel/head64.c:490 + x86_64_start_kernel+0x77/0x7b arch/x86/kernel/head64.c:471 + secondary_startup_64+0xa4/0xb0 arch/x86/kernel/head_64.S:242 + +The buggy address belongs to the page: +page:ffffea00067c82c0 refcount:0 mapcount:0 mapping:0000000000000000 index:0x0 +raw: 057ffe0000000000 ffffea00067c82c8 ffffea00067c82c8 0000000000000000 +raw: 0000000000000000 0000000000000000 00000000ffffffff 0000000000000000 +page dumped because: kasan: bad access detected + +Memory state around the buggy address: + ffff88819f20b880: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ffff88819f20b900: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff +>ffff88819f20b980: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ^ + ffff88819f20ba00: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ffff88819f20ba80: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + +Fixes: 61e84623ace3 ("net: centralize net_device min/max MTU checking") +Signed-off-by: Eric Dumazet +Reported-by: syzbot +Signed-off-by: David S. Miller +Signed-off-by: Jiri Slaby +--- + include/linux/netdevice.h | 1 + + net/core/dev.c | 32 ++++++++++++++++++++------------ + net/core/rtnetlink.c | 13 +++++++++++-- + 3 files changed, 32 insertions(+), 14 deletions(-) + +--- a/include/linux/netdevice.h ++++ b/include/linux/netdevice.h +@@ -3303,6 +3303,7 @@ void __dev_notify_flags(struct net_devic + int dev_set_alias(struct net_device *, const char *, size_t); + int dev_change_net_namespace(struct net_device *, struct net *, const char *); + int __dev_set_mtu(struct net_device *, int); ++int dev_validate_mtu(struct net_device *dev, int mtu); + int dev_set_mtu(struct net_device *, int); + int dev_change_tx_queue_len(struct net_device *, unsigned long); + void dev_set_group(struct net_device *, int); +--- a/net/core/dev.c ++++ b/net/core/dev.c +@@ -6841,6 +6841,23 @@ static int __dev_set_mtu(struct net_devi + } + EXPORT_SYMBOL(__dev_set_mtu); + ++int dev_validate_mtu(struct net_device *dev, int new_mtu) ++{ ++ /* MTU must be positive, and in range */ ++ if (new_mtu < 0 || new_mtu < dev->min_mtu) { ++ net_err_ratelimited("%s: Invalid MTU %d requested, hw min %d\n", ++ dev->name, new_mtu, dev->min_mtu); ++ return -EINVAL; ++ } ++ ++ if (dev->max_mtu > 0 && new_mtu > dev->max_mtu) { ++ net_err_ratelimited("%s: Invalid MTU %d requested, hw max %d\n", ++ dev->name, new_mtu, dev->max_mtu); ++ return -EINVAL; ++ } ++ return 0; ++} ++ + /** + * dev_set_mtu - Change maximum transfer unit + * @dev: device +@@ -6855,18 +6872,9 @@ int dev_set_mtu(struct net_device *dev, + if (new_mtu == dev->mtu) + return 0; + +- /* MTU must be positive, and in range */ +- if (new_mtu < 0 || new_mtu < dev->min_mtu) { +- net_err_ratelimited("%s: Invalid MTU %d requested, hw min %d\n", +- dev->name, new_mtu, dev->min_mtu); +- return -EINVAL; +- } +- +- if (dev->max_mtu > 0 && new_mtu > dev->max_mtu) { +- net_err_ratelimited("%s: Invalid MTU %d requested, hw max %d\n", +- dev->name, new_mtu, dev->max_mtu); +- return -EINVAL; +- } ++ err = dev_validate_mtu(dev, new_mtu); ++ if (err) ++ return err; + + if (!netif_device_present(dev)) + return -ENODEV; +--- a/net/core/rtnetlink.c ++++ b/net/core/rtnetlink.c +@@ -2496,8 +2496,17 @@ struct net_device *rtnl_create_link(stru + dev->rtnl_link_ops = ops; + dev->rtnl_link_state = RTNL_LINK_INITIALIZING; + +- if (tb[IFLA_MTU]) +- dev->mtu = nla_get_u32(tb[IFLA_MTU]); ++ if (tb[IFLA_MTU]) { ++ u32 mtu = nla_get_u32(tb[IFLA_MTU]); ++ int err; ++ ++ err = dev_validate_mtu(dev, mtu); ++ if (err) { ++ free_netdev(dev); ++ return ERR_PTR(err); ++ } ++ dev->mtu = mtu; ++ } + if (tb[IFLA_ADDRESS]) { + memcpy(dev->dev_addr, nla_data(tb[IFLA_ADDRESS]), + nla_len(tb[IFLA_ADDRESS])); diff --git a/patches.suse/net-sch_prio-When-ungrafting-replace-with-FIFO.patch b/patches.suse/net-sch_prio-When-ungrafting-replace-with-FIFO.patch new file mode 100644 index 0000000..ed2f79e --- /dev/null +++ b/patches.suse/net-sch_prio-When-ungrafting-replace-with-FIFO.patch @@ -0,0 +1,46 @@ +From: Petr Machata +Date: Mon, 6 Jan 2020 18:01:56 +0000 +Subject: net: sch_prio: When ungrafting, replace with FIFO +Git-commit: 240ce7f6428ff5188b9eedc066e1e4d645b8635f +Patch-mainline: 5.5-rc6 +References: networking-stable-20_01_11 + +When a child Qdisc is removed from one of the PRIO Qdisc's bands, it is +replaced unconditionally by a NOOP qdisc. As a result, any traffic hitting +that band gets dropped. That is incorrect--no Qdisc was explicitly added +when PRIO was created, and after removal, none should have to be added +either. + +Fix PRIO by first attempting to create a default Qdisc and only falling +back to noop when that fails. This pattern of attempting to create an +invisible FIFO, using NOOP only as a fallback, is also seen in other +Qdiscs. + +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Signed-off-by: Petr Machata +Acked-by: Jiri Pirko +Signed-off-by: David S. Miller +Signed-off-by: Jiri Slaby +--- + net/sched/sch_prio.c | 10 ++++++++-- + 1 file changed, 8 insertions(+), 2 deletions(-) + +--- a/net/sched/sch_prio.c ++++ b/net/sched/sch_prio.c +@@ -244,8 +244,14 @@ static int prio_graft(struct Qdisc *sch, + bool any_qdisc_is_offloaded; + int err; + +- if (new == NULL) +- new = &noop_qdisc; ++ if (!new) { ++ new = qdisc_create_dflt(sch->dev_queue, &pfifo_qdisc_ops, ++ TC_H_MAKE(sch->handle, arg), extack); ++ if (!new) ++ new = &noop_qdisc; ++ else ++ qdisc_hash_add(new, true); ++ } + + *old = qdisc_replace(sch, new, &q->queues[band]); + diff --git a/patches.suse/net-sched-flower-add-missing-validation-of-TCA_FLOWE.patch b/patches.suse/net-sched-flower-add-missing-validation-of-TCA_FLOWE.patch new file mode 100644 index 0000000..6baa06f --- /dev/null +++ b/patches.suse/net-sched-flower-add-missing-validation-of-TCA_FLOWE.patch @@ -0,0 +1,31 @@ +From: Davide Caratti +Date: Tue, 11 Feb 2020 19:33:40 +0100 +Subject: net/sched: flower: add missing validation of TCA_FLOWER_FLAGS +Git-commit: e2debf0852c4d66ba1a8bde12869b196094c70a7 +Patch-mainline: 5.6-rc2 +References: networking-stable-20_02_19 + +unlike other classifiers that can be offloaded (i.e. users can set flags +like 'skip_hw' and 'skip_sw'), 'cls_flower' doesn't validate the size of +netlink attribute 'TCA_FLOWER_FLAGS' provided by user: add a proper entry +to fl_policy. + +Fixes: 5b33f48842fa ("net/flower: Introduce hardware offload support") +Signed-off-by: Davide Caratti +Acked-by: Jiri Pirko +Signed-off-by: David S. Miller +Signed-off-by: Jiri Slaby +--- + net/sched/cls_flower.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/net/sched/cls_flower.c ++++ b/net/sched/cls_flower.c +@@ -422,6 +422,7 @@ static const struct nla_policy fl_policy + [TCA_FLOWER_KEY_ENC_IP_TTL_MASK] = { .type = NLA_U8 }, + [TCA_FLOWER_KEY_ENC_OPTS] = { .type = NLA_NESTED }, + [TCA_FLOWER_KEY_ENC_OPTS_MASK] = { .type = NLA_NESTED }, ++ [TCA_FLOWER_FLAGS] = { .type = NLA_U32 }, + }; + + static const struct nla_policy diff --git a/patches.suse/net-sched-matchall-add-missing-validation-of-TCA_MAT.patch b/patches.suse/net-sched-matchall-add-missing-validation-of-TCA_MAT.patch new file mode 100644 index 0000000..1b76174 --- /dev/null +++ b/patches.suse/net-sched-matchall-add-missing-validation-of-TCA_MAT.patch @@ -0,0 +1,31 @@ +From: Davide Caratti +Date: Tue, 11 Feb 2020 19:33:39 +0100 +Subject: net/sched: matchall: add missing validation of TCA_MATCHALL_FLAGS +Git-commit: 1afa3cc90f8fb745c777884d79eaa1001d6927a6 +Patch-mainline: 5.6-rc2 +References: networking-stable-20_02_19 + +unlike other classifiers that can be offloaded (i.e. users can set flags +like 'skip_hw' and 'skip_sw'), 'cls_matchall' doesn't validate the size +of netlink attribute 'TCA_MATCHALL_FLAGS' provided by user: add a proper +entry to mall_policy. + +Fixes: b87f7936a932 ("net/sched: Add match-all classifier hw offloading.") +Signed-off-by: Davide Caratti +Acked-by: Jiri Pirko +Signed-off-by: David S. Miller +Signed-off-by: Jiri Slaby +--- + net/sched/cls_matchall.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/net/sched/cls_matchall.c ++++ b/net/sched/cls_matchall.c +@@ -114,6 +114,7 @@ static unsigned long mall_get(struct tcf + static const struct nla_policy mall_policy[TCA_MATCHALL_MAX + 1] = { + [TCA_MATCHALL_UNSPEC] = { .type = NLA_UNSPEC }, + [TCA_MATCHALL_CLASSID] = { .type = NLA_U32 }, ++ [TCA_MATCHALL_FLAGS] = { .type = NLA_U32 }, + }; + + static int mall_set_parms(struct net *net, struct tcf_proto *tp, diff --git a/patches.suse/net-smc-add-fallback-check-to-connect b/patches.suse/net-smc-add-fallback-check-to-connect new file mode 100644 index 0000000..644641c --- /dev/null +++ b/patches.suse/net-smc-add-fallback-check-to-connect @@ -0,0 +1,92 @@ +From: Ursula Braun +Date: Thu, 12 Dec 2019 22:35:58 +0100 +Subject: net/smc: add fallback check to connect() +Git-commit: 86434744fedf0cfe07a9eee3f4632c0e25c1d136 +Patch-mainline: v5.5-rc3 +References: git-fixes + +FASTOPEN setsockopt() or sendmsg() may switch the SMC socket to fallback +mode. Once fallback mode is active, the native TCP socket functions are +called. Nevertheless there is a small race window, when FASTOPEN +setsockopt/sendmsg runs in parallel to a connect(), and switch the +socket into fallback mode before connect() takes the sock lock. +Make sure the SMC-specific connect setup is omitted in this case. + +This way a syzbot-reported refcount problem is fixed, triggered by +different threads running non-blocking connect() and FASTOPEN_KEY +setsockopt. + +Reported-by: syzbot+96d3f9ff6a86d37e44c8@syzkaller.appspotmail.com +Fixes: 6d6dd528d5af ("net/smc: fix refcount non-blocking connect() -part 2") +Signed-off-by: Ursula Braun +Signed-off-by: Karsten Graul +Signed-off-by: Jakub Kicinski +Acked-by: Petr Tesarik +--- + net/smc/af_smc.c | 14 ++++++++------ + 1 file changed, 8 insertions(+), 6 deletions(-) + +--- a/net/smc/af_smc.c ++++ b/net/smc/af_smc.c +@@ -843,6 +843,8 @@ static int smc_connect(struct socket *so + goto out; + + sock_hold(&smc->sk); /* sock put in passive closing */ ++ if (smc->use_fallback) ++ goto out; + if (flags & O_NONBLOCK) { + if (schedule_work(&smc->connect_work)) + smc->connect_nonblock = 1; +@@ -1724,8 +1726,6 @@ static int smc_setsockopt(struct socket + sk->sk_err = smc->clcsock->sk->sk_err; + sk->sk_error_report(sk); + } +- if (rc) +- return rc; + + if (optlen < sizeof(int)) + return -EINVAL; +@@ -1733,6 +1733,8 @@ static int smc_setsockopt(struct socket + return -EFAULT; + + lock_sock(sk); ++ if (rc || smc->use_fallback) ++ goto out; + switch (optname) { + case TCP_ULP: + case TCP_FASTOPEN: +@@ -1742,15 +1744,14 @@ static int smc_setsockopt(struct socket + smc_switch_to_fallback(smc); + smc->fallback_rsn = SMC_CLC_DECL_OPTUNSUPP; + } else { +- if (!smc->use_fallback) +- rc = -EINVAL; ++ rc = -EINVAL; + } + break; + case TCP_NODELAY: + if (sk->sk_state != SMC_INIT && + sk->sk_state != SMC_LISTEN && + sk->sk_state != SMC_CLOSED) { +- if (val && !smc->use_fallback) ++ if (val) + mod_delayed_work(system_wq, &smc->conn.tx_work, + 0); + } +@@ -1759,7 +1760,7 @@ static int smc_setsockopt(struct socket + if (sk->sk_state != SMC_INIT && + sk->sk_state != SMC_LISTEN && + sk->sk_state != SMC_CLOSED) { +- if (!val && !smc->use_fallback) ++ if (!val) + mod_delayed_work(system_wq, &smc->conn.tx_work, + 0); + } +@@ -1770,6 +1771,7 @@ static int smc_setsockopt(struct socket + default: + break; + } ++out: + release_sock(sk); + + return rc; diff --git a/patches.suse/net-smc-fix-cleanup-for-linkgroup-setup-failures b/patches.suse/net-smc-fix-cleanup-for-linkgroup-setup-failures new file mode 100644 index 0000000..7209149 --- /dev/null +++ b/patches.suse/net-smc-fix-cleanup-for-linkgroup-setup-failures @@ -0,0 +1,152 @@ +From: Ursula Braun +Date: Tue, 25 Feb 2020 16:34:36 +0100 +Subject: net/smc: fix cleanup for linkgroup setup failures +Git-commit: 51e3dfa8906ace90c809235b3d3afebc166b6433 +Patch-mainline: v5.6-rc4 +References: git-fixes + +If an SMC connection to a certain peer is setup the first time, +a new linkgroup is created. In case of setup failures, such a +linkgroup is unusable and should disappear. As a first step the +linkgroup is removed from the linkgroup list in smc_lgr_forget(). + +There are 2 problems: +smc_listen_decline() might be called before linkgroup creation +resulting in a crash due to calling smc_lgr_forget() with +parameter NULL. +If a setup failure occurs after linkgroup creation, the connection +is never unregistered from the linkgroup, preventing linkgroup +freeing. + +This patch introduces an enhanced smc_lgr_cleanup_early() function +which +* contains a linkgroup check for early smc_listen_decline() + invocations +* invokes smc_conn_free() to guarantee unregistering of the + connection. +* schedules fast linkgroup removal of the unusable linkgroup + +And the unused function smcd_conn_free() is removed from smc_core.h. + +Fixes: 3b2dec2603d5b ("net/smc: restructure client and server code in af_smc") +Fixes: 2a0674fffb6bc ("net/smc: improve abnormal termination of link groups") +Signed-off-by: Ursula Braun +Signed-off-by: Karsten Graul +Signed-off-by: David S. Miller +Acked-by: Petr Tesarik +--- + net/smc/af_smc.c | 25 +++++++++++++++---------- + net/smc/smc_core.c | 12 ++++++++++++ + net/smc/smc_core.h | 2 +- + 3 files changed, 28 insertions(+), 11 deletions(-) + +--- a/net/smc/af_smc.c ++++ b/net/smc/af_smc.c +@@ -498,15 +498,18 @@ static int smc_connect_decline_fallback( + static int smc_connect_abort(struct smc_sock *smc, int reason_code, + int local_contact) + { ++ bool is_smcd = smc->conn.lgr->is_smcd; ++ + if (local_contact == SMC_FIRST_CONTACT) +- smc_lgr_forget(smc->conn.lgr); +- if (smc->conn.lgr->is_smcd) ++ smc_lgr_cleanup_early(&smc->conn); ++ else ++ smc_conn_free(&smc->conn); ++ if (is_smcd) + /* there is only one lgr role for SMC-D; use server lock */ + mutex_unlock(&smc_server_lgr_pending); + else + mutex_unlock(&smc_client_lgr_pending); + +- smc_conn_free(&smc->conn); + smc->connect_nonblock = 0; + return reason_code; + } +@@ -1094,7 +1097,6 @@ static void smc_listen_out_err(struct sm + if (newsmcsk->sk_state == SMC_INIT) + sock_put(&new_smc->sk); /* passive closing */ + newsmcsk->sk_state = SMC_CLOSED; +- smc_conn_free(&new_smc->conn); + + smc_listen_out(new_smc); + } +@@ -1105,12 +1107,13 @@ static void smc_listen_decline(struct sm + { + /* RDMA setup failed, switch back to TCP */ + if (local_contact == SMC_FIRST_CONTACT) +- smc_lgr_forget(new_smc->conn.lgr); ++ smc_lgr_cleanup_early(&new_smc->conn); ++ else ++ smc_conn_free(&new_smc->conn); + if (reason_code < 0) { /* error, no fallback possible */ + smc_listen_out_err(new_smc); + return; + } +- smc_conn_free(&new_smc->conn); + smc_switch_to_fallback(new_smc); + new_smc->fallback_rsn = reason_code; + if (reason_code && reason_code != SMC_CLC_DECL_PEERDECL) { +@@ -1173,16 +1176,18 @@ static int smc_listen_ism_init(struct sm + new_smc->conn.lgr->vlan_id, + new_smc->conn.lgr->smcd)) { + if (ini->cln_first_contact == SMC_FIRST_CONTACT) +- smc_lgr_forget(new_smc->conn.lgr); +- smc_conn_free(&new_smc->conn); ++ smc_lgr_cleanup_early(&new_smc->conn); ++ else ++ smc_conn_free(&new_smc->conn); + return SMC_CLC_DECL_SMCDNOTALK; + } + + /* Create send and receive buffers */ + if (smc_buf_create(new_smc, true)) { + if (ini->cln_first_contact == SMC_FIRST_CONTACT) +- smc_lgr_forget(new_smc->conn.lgr); +- smc_conn_free(&new_smc->conn); ++ smc_lgr_cleanup_early(&new_smc->conn); ++ else ++ smc_conn_free(&new_smc->conn); + return SMC_CLC_DECL_MEM; + } + +--- a/net/smc/smc_core.c ++++ b/net/smc/smc_core.c +@@ -135,6 +135,18 @@ static void smc_lgr_unregister_conn(stru + write_unlock_bh(&lgr->conns_lock); + } + ++void smc_lgr_cleanup_early(struct smc_connection *conn) ++{ ++ struct smc_link_group *lgr = conn->lgr; ++ ++ if (!lgr) ++ return; ++ ++ smc_conn_free(conn); ++ smc_lgr_forget(lgr); ++ smc_lgr_schedule_free_work_fast(lgr); ++} ++ + /* Send delete link, either as client to request the initiation + * of the DELETE LINK sequence from server; or as server to + * initiate the delete processing. See smc_llc_rx_delete_link(). +--- a/net/smc/smc_core.h ++++ b/net/smc/smc_core.h +@@ -284,6 +284,7 @@ struct smc_clc_msg_accept_confirm; + struct smc_clc_msg_local; + + void smc_lgr_forget(struct smc_link_group *lgr); ++void smc_lgr_cleanup_early(struct smc_connection *conn); + void smc_lgr_terminate(struct smc_link_group *lgr); + void smc_port_terminate(struct smc_ib_device *smcibdev, u8 ibport); + void smc_smcd_terminate(struct smcd_dev *dev, u64 peer_gid, +@@ -302,7 +303,6 @@ int smc_vlan_by_tcpsk(struct socket *clc + + void smc_conn_free(struct smc_connection *conn); + int smc_conn_create(struct smc_sock *smc, struct smc_init_info *ini); +-void smcd_conn_free(struct smc_connection *conn); + void smc_lgr_schedule_free_work_fast(struct smc_link_group *lgr); + void smc_core_exit(void); + diff --git a/patches.suse/net-smc-fix-leak-of-kernel-memory-to-user-space.patch b/patches.suse/net-smc-fix-leak-of-kernel-memory-to-user-space.patch new file mode 100644 index 0000000..da2a0b5 --- /dev/null +++ b/patches.suse/net-smc-fix-leak-of-kernel-memory-to-user-space.patch @@ -0,0 +1,109 @@ +From: Eric Dumazet +Date: Mon, 10 Feb 2020 11:36:13 -0800 +Subject: net/smc: fix leak of kernel memory to user space +Git-commit: 457fed775c97ac2c0cd1672aaf2ff2c8a6235e87 +Patch-mainline: 5.6-rc2 +References: networking-stable-20_02_19 + +As nlmsg_put() does not clear the memory that is reserved, +it this the caller responsability to make sure all of this +memory will be written, in order to not reveal prior content. + +While we are at it, we can provide the socket cookie even +if clsock is not set. + +syzbot reported : + +BUG: KMSAN: uninit-value in __arch_swab32 arch/x86/include/uapi/asm/swab.h:10 [inline] +BUG: KMSAN: uninit-value in __fswab32 include/uapi/linux/swab.h:59 [inline] +BUG: KMSAN: uninit-value in __swab32p include/uapi/linux/swab.h:179 [inline] +BUG: KMSAN: uninit-value in __be32_to_cpup include/uapi/linux/byteorder/little_endian.h:82 [inline] +BUG: KMSAN: uninit-value in get_unaligned_be32 include/linux/unaligned/access_ok.h:30 [inline] +BUG: KMSAN: uninit-value in ____bpf_skb_load_helper_32 net/core/filter.c:240 [inline] +BUG: KMSAN: uninit-value in ____bpf_skb_load_helper_32_no_cache net/core/filter.c:255 [inline] +BUG: KMSAN: uninit-value in bpf_skb_load_helper_32_no_cache+0x14a/0x390 net/core/filter.c:252 +CPU: 1 PID: 5262 Comm: syz-executor.5 Not tainted 5.5.0-rc5-syzkaller #0 +Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011 +Call Trace: + __dump_stack lib/dump_stack.c:77 [inline] + dump_stack+0x1c9/0x220 lib/dump_stack.c:118 + kmsan_report+0xf7/0x1e0 mm/kmsan/kmsan_report.c:118 + __msan_warning+0x58/0xa0 mm/kmsan/kmsan_instr.c:215 + __arch_swab32 arch/x86/include/uapi/asm/swab.h:10 [inline] + __fswab32 include/uapi/linux/swab.h:59 [inline] + __swab32p include/uapi/linux/swab.h:179 [inline] + __be32_to_cpup include/uapi/linux/byteorder/little_endian.h:82 [inline] + get_unaligned_be32 include/linux/unaligned/access_ok.h:30 [inline] + ____bpf_skb_load_helper_32 net/core/filter.c:240 [inline] + ____bpf_skb_load_helper_32_no_cache net/core/filter.c:255 [inline] + bpf_skb_load_helper_32_no_cache+0x14a/0x390 net/core/filter.c:252 + +Uninit was created at: + kmsan_save_stack_with_flags mm/kmsan/kmsan.c:144 [inline] + kmsan_internal_poison_shadow+0x66/0xd0 mm/kmsan/kmsan.c:127 + kmsan_kmalloc_large+0x73/0xc0 mm/kmsan/kmsan_hooks.c:128 + kmalloc_large_node_hook mm/slub.c:1406 [inline] + kmalloc_large_node+0x282/0x2c0 mm/slub.c:3841 + __kmalloc_node_track_caller+0x44b/0x1200 mm/slub.c:4368 + __kmalloc_reserve net/core/skbuff.c:141 [inline] + __alloc_skb+0x2fd/0xac0 net/core/skbuff.c:209 + alloc_skb include/linux/skbuff.h:1049 [inline] + netlink_dump+0x44b/0x1ab0 net/netlink/af_netlink.c:2224 + __netlink_dump_start+0xbb2/0xcf0 net/netlink/af_netlink.c:2352 + netlink_dump_start include/linux/netlink.h:233 [inline] + smc_diag_handler_dump+0x2ba/0x300 net/smc/smc_diag.c:242 + sock_diag_rcv_msg+0x211/0x610 net/core/sock_diag.c:256 + netlink_rcv_skb+0x451/0x650 net/netlink/af_netlink.c:2477 + sock_diag_rcv+0x63/0x80 net/core/sock_diag.c:275 + netlink_unicast_kernel net/netlink/af_netlink.c:1302 [inline] + netlink_unicast+0xf9e/0x1100 net/netlink/af_netlink.c:1328 + netlink_sendmsg+0x1248/0x14d0 net/netlink/af_netlink.c:1917 + sock_sendmsg_nosec net/socket.c:639 [inline] + sock_sendmsg net/socket.c:659 [inline] + kernel_sendmsg+0x433/0x440 net/socket.c:679 + sock_no_sendpage+0x235/0x300 net/core/sock.c:2740 + kernel_sendpage net/socket.c:3776 [inline] + sock_sendpage+0x1e1/0x2c0 net/socket.c:937 + pipe_to_sendpage+0x38c/0x4c0 fs/splice.c:458 + splice_from_pipe_feed fs/splice.c:512 [inline] + __splice_from_pipe+0x539/0xed0 fs/splice.c:636 + splice_from_pipe fs/splice.c:671 [inline] + generic_splice_sendpage+0x1d5/0x2d0 fs/splice.c:844 + do_splice_from fs/splice.c:863 [inline] + do_splice fs/splice.c:1170 [inline] + __do_sys_splice fs/splice.c:1447 [inline] + __se_sys_splice+0x2380/0x3350 fs/splice.c:1427 + __x64_sys_splice+0x6e/0x90 fs/splice.c:1427 + do_syscall_64+0xb8/0x160 arch/x86/entry/common.c:296 + entry_SYSCALL_64_after_hwframe+0x44/0xa9 + +Fixes: f16a7dd5cf27 ("smc: netlink interface for SMC sockets") +Signed-off-by: Eric Dumazet +Cc: Ursula Braun +Signed-off-by: David S. Miller +Signed-off-by: Jiri Slaby +--- + net/smc/smc_diag.c | 5 ++--- + 1 file changed, 2 insertions(+), 3 deletions(-) + +--- a/net/smc/smc_diag.c ++++ b/net/smc/smc_diag.c +@@ -38,16 +38,15 @@ static void smc_diag_msg_common_fill(str + { + struct smc_sock *smc = smc_sk(sk); + ++ memset(r, 0, sizeof(*r)); + r->diag_family = sk->sk_family; ++ sock_diag_save_cookie(sk, r->id.idiag_cookie); + if (!smc->clcsock) + return; + r->id.idiag_sport = htons(smc->clcsock->sk->sk_num); + r->id.idiag_dport = smc->clcsock->sk->sk_dport; + r->id.idiag_if = smc->clcsock->sk->sk_bound_dev_if; +- sock_diag_save_cookie(sk, r->id.idiag_cookie); + if (sk->sk_protocol == SMCPROTO_SMC) { +- memset(&r->id.idiag_src, 0, sizeof(r->id.idiag_src)); +- memset(&r->id.idiag_dst, 0, sizeof(r->id.idiag_dst)); + r->id.idiag_src[0] = smc->clcsock->sk->sk_rcv_saddr; + r->id.idiag_dst[0] = smc->clcsock->sk->sk_daddr; + #if IS_ENABLED(CONFIG_IPV6) diff --git a/patches.suse/net-smc-no-peer-id-in-clc-decline-for-smcd b/patches.suse/net-smc-no-peer-id-in-clc-decline-for-smcd new file mode 100644 index 0000000..7bc5c7d --- /dev/null +++ b/patches.suse/net-smc-no-peer-id-in-clc-decline-for-smcd @@ -0,0 +1,32 @@ +From: Ursula Braun +Date: Fri, 14 Feb 2020 08:59:00 +0100 +Subject: net/smc: no peer ID in CLC decline for SMCD +Git-commit: 369537c97024dca99303a8d4d6ab38b4f54d3909 +Patch-mainline: v5.6-rc2 +References: git-fixes + +Just SMCR requires a CLC Peer ID, but not SMCD. The field should be +zero for SMCD. + +Fixes: c758dfddc1b5 ("net/smc: add SMC-D support in CLC messages") +Signed-off-by: Ursula Braun +Signed-off-by: Karsten Graul +Signed-off-by: David S. Miller +Acked-by: Petr Tesarik +--- + net/smc/smc_clc.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +--- a/net/smc/smc_clc.c ++++ b/net/smc/smc_clc.c +@@ -368,7 +368,9 @@ int smc_clc_send_decline(struct smc_sock + dclc.hdr.length = htons(sizeof(struct smc_clc_msg_decline)); + dclc.hdr.version = SMC_CLC_V1; + dclc.hdr.flag = (peer_diag_info == SMC_CLC_DECL_SYNCERR) ? 1 : 0; +- memcpy(dclc.id_for_peer, local_systemid, sizeof(local_systemid)); ++ if (smc->conn.lgr && !smc->conn.lgr->is_smcd) ++ memcpy(dclc.id_for_peer, local_systemid, ++ sizeof(local_systemid)); + dclc.peer_diagnosis = htonl(peer_diag_info); + memcpy(dclc.trl.eyecatcher, SMC_EYECATCHER, sizeof(SMC_EYECATCHER)); + diff --git a/patches.suse/net-smc-transfer-fasync_list-in-case-of-fallback b/patches.suse/net-smc-transfer-fasync_list-in-case-of-fallback new file mode 100644 index 0000000..8e94ca3 --- /dev/null +++ b/patches.suse/net-smc-transfer-fasync_list-in-case-of-fallback @@ -0,0 +1,37 @@ +From: Ursula Braun +Date: Fri, 14 Feb 2020 08:58:59 +0100 +Subject: net/smc: transfer fasync_list in case of fallback +Git-commit: 67f562e3e147750a02b2a91d21a163fc44a1d13e +Patch-mainline: v5.6-rc2 +References: git-fixes + +SMC does not work together with FASTOPEN. If sendmsg() is called with +flag MSG_FASTOPEN in SMC_INIT state, the SMC-socket switches to +fallback mode. To handle the previous ioctl FIOASYNC call correctly +in this case, it is necessary to transfer the socket wait queue +fasync_list to the internal TCP socket. + +Reported-by: syzbot+4b1fe8105f8044a26162@syzkaller.appspotmail.com +Fixes: ee9dfbef02d18 ("net/smc: handle sockopts forcing fallback") +Signed-off-by: Ursula Braun +Signed-off-by: Karsten Graul +Signed-off-by: David S. Miller +Acked-by: Petr Tesarik + +[ ptesarik: wq is a pointer in SLE15-SP1, because we do not + have commit 333f7909a8573145811c4ab7d8c9092301707721. ] +--- + net/smc/af_smc.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/net/smc/af_smc.c ++++ b/net/smc/af_smc.c +@@ -456,6 +456,8 @@ static void smc_switch_to_fallback(struc + if (smc->sk.sk_socket && smc->sk.sk_socket->file) { + smc->clcsock->file = smc->sk.sk_socket->file; + smc->clcsock->file->private_data = smc->clcsock; ++ smc->clcsock->wq->fasync_list = ++ smc->sk.sk_socket->wq->fasync_list; + } + } + diff --git a/patches.suse/net-stmmac-Delete-txtimer-in-suspend.patch b/patches.suse/net-stmmac-Delete-txtimer-in-suspend.patch new file mode 100644 index 0000000..d47e975 --- /dev/null +++ b/patches.suse/net-stmmac-Delete-txtimer-in-suspend.patch @@ -0,0 +1,63 @@ +From: Nicolin Chen +Date: Fri, 31 Jan 2020 18:01:24 -0800 +Subject: net: stmmac: Delete txtimer in suspend() +Git-commit: 14b41a2959fbaa50932699d32ceefd6643abacc6 +Patch-mainline: 5.6-rc1 +References: networking-stable-20_02_05 + +When running v5.5 with a rootfs on NFS, memory abort may happen in +the system resume stage: + Unable to handle kernel paging request at virtual address dead00000000012a + [dead00000000012a] address between user and kernel address ranges + pc : run_timer_softirq+0x334/0x3d8 + lr : run_timer_softirq+0x244/0x3d8 + x1 : ffff800011cafe80 x0 : dead000000000122 + Call trace: + run_timer_softirq+0x334/0x3d8 + efi_header_end+0x114/0x234 + irq_exit+0xd0/0xd8 + __handle_domain_irq+0x60/0xb0 + gic_handle_irq+0x58/0xa8 + el1_irq+0xb8/0x180 + arch_cpu_idle+0x10/0x18 + do_idle+0x1d8/0x2b0 + cpu_startup_entry+0x24/0x40 + secondary_start_kernel+0x1b4/0x208 + Code: f9000693 a9400660 f9000020 b4000040 (f9000401) + ---[ end trace bb83ceeb4c482071 ]--- + Kernel panic - not syncing: Fatal exception in interrupt + SMP: stopping secondary CPUs + SMP: failed to stop secondary CPUs 2-3 + Kernel Offset: disabled + CPU features: 0x00002,2300aa30 + Memory Limit: none + ---[ end Kernel panic - not syncing: Fatal exception in interrupt ]--- + +It's found that stmmac_xmit() and stmmac_resume() sometimes might +run concurrently, possibly resulting in a race condition between +mod_timer() and setup_timer(), being called by stmmac_xmit() and +stmmac_resume() respectively. + +Since the resume() runs setup_timer() every time, it'd be safer to +have del_timer_sync() in the suspend() as the counterpart. + +[js] only single timer, not per-queue in 4.12 + +Signed-off-by: Nicolin Chen +Signed-off-by: Jakub Kicinski +Signed-off-by: Jiri Slaby +--- + drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c ++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +@@ -4357,6 +4357,8 @@ int stmmac_suspend(struct device *dev) + + stmmac_disable_all_queues(priv); + ++ del_timer_sync(&priv->txtimer); ++ + /* Stop TX/RX DMA */ + stmmac_stop_all_dma(priv); + diff --git a/patches.suse/net-stmmac-dwmac-sunxi-Allow-all-RGMII-modes.patch b/patches.suse/net-stmmac-dwmac-sunxi-Allow-all-RGMII-modes.patch new file mode 100644 index 0000000..8ae12a9 --- /dev/null +++ b/patches.suse/net-stmmac-dwmac-sunxi-Allow-all-RGMII-modes.patch @@ -0,0 +1,30 @@ +From: Chen-Yu Tsai +Date: Mon, 6 Jan 2020 11:09:22 +0800 +Subject: net: stmmac: dwmac-sunxi: Allow all RGMII modes +Git-commit: 52cc73e5404c7ba0cbfc50cb4c265108c84b3d5a +Patch-mainline: 5.5-rc6 +References: networking-stable-20_01_11 + +Allow all the RGMII modes to be used. This would allow us to represent +the hardware better in the device tree with RGMII_ID where in most +cases the PHY's internal delay for both RX and TX are used. + +Fixes: af0bd4e9ba80 ("net: stmmac: sunxi platform extensions for GMAC in Allwinner A20 SoC's") +Signed-off-by: Chen-Yu Tsai +Signed-off-by: David S. Miller +Signed-off-by: Jiri Slaby +--- + drivers/net/ethernet/stmicro/stmmac/dwmac-sunxi.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-sunxi.c ++++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-sunxi.c +@@ -53,7 +53,7 @@ static int sun7i_gmac_init(struct platfo + * rate, which then uses the auto-reparenting feature of the + * clock driver, and enabling/disabling the clock. + */ +- if (gmac->interface == PHY_INTERFACE_MODE_RGMII) { ++ if (phy_interface_mode_is_rgmii(gmac->interface)) { + clk_set_rate(gmac->tx_clk, SUN7I_GMAC_GMII_RGMII_RATE); + clk_prepare_enable(gmac->tx_clk); + gmac->clk_enabled = 1; diff --git a/patches.suse/net-sysfs-Fix-reference-count-leak.patch b/patches.suse/net-sysfs-Fix-reference-count-leak.patch new file mode 100644 index 0000000..9b2adc7 --- /dev/null +++ b/patches.suse/net-sysfs-Fix-reference-count-leak.patch @@ -0,0 +1,97 @@ +From: Jouni Hogander +Date: Mon, 20 Jan 2020 09:51:03 +0200 +Subject: net-sysfs: Fix reference count leak +Git-commit: cb626bf566eb4433318d35681286c494f04fedcc +Patch-mainline: 5.5 +References: networking-stable-20_01_27 + +Netdev_register_kobject is calling device_initialize. In case of error +reference taken by device_initialize is not given up. + +Drivers are supposed to call free_netdev in case of error. In non-error +case the last reference is given up there and device release sequence +is triggered. In error case this reference is kept and the release +sequence is never started. + +Fix this by setting reg_state as NETREG_UNREGISTERED if registering +fails. + +This is the rootcause for couple of memory leaks reported by Syzkaller: + +BUG: memory leak unreferenced object 0xffff8880675ca008 (size 256): + comm "netdev_register", pid 281, jiffies 4294696663 (age 6.808s) + hex dump (first 32 bytes): + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ + backtrace: + [<0000000058ca4711>] kmem_cache_alloc_trace+0x167/0x280 + [<000000002340019b>] device_add+0x882/0x1750 + [<000000001d588c3a>] netdev_register_kobject+0x128/0x380 + [<0000000011ef5535>] register_netdevice+0xa1b/0xf00 + [<000000007fcf1c99>] __tun_chr_ioctl+0x20d5/0x3dd0 + [<000000006a5b7b2b>] tun_chr_ioctl+0x2f/0x40 + [<00000000f30f834a>] do_vfs_ioctl+0x1c7/0x1510 + [<00000000fba062ea>] ksys_ioctl+0x99/0xb0 + [<00000000b1c1b8d2>] __x64_sys_ioctl+0x78/0xb0 + [<00000000984cabb9>] do_syscall_64+0x16f/0x580 + [<000000000bde033d>] entry_SYSCALL_64_after_hwframe+0x44/0xa9 + [<00000000e6ca2d9f>] 0xffffffffffffffff + +BUG: memory leak +unreferenced object 0xffff8880668ba588 (size 8): + comm "kobject_set_nam", pid 286, jiffies 4294725297 (age 9.871s) + hex dump (first 8 bytes): + 6e 72 30 00 cc be df 2b nr0....+ + backtrace: + [<00000000a322332a>] __kmalloc_track_caller+0x16e/0x290 + [<00000000236fd26b>] kstrdup+0x3e/0x70 + [<00000000dd4a2815>] kstrdup_const+0x3e/0x50 + [<0000000049a377fc>] kvasprintf_const+0x10e/0x160 + [<00000000627fc711>] kobject_set_name_vargs+0x5b/0x140 + [<0000000019eeab06>] dev_set_name+0xc0/0xf0 + [<0000000069cb12bc>] netdev_register_kobject+0xc8/0x320 + [<00000000f2e83732>] register_netdevice+0xa1b/0xf00 + [<000000009e1f57cc>] __tun_chr_ioctl+0x20d5/0x3dd0 + [<000000009c560784>] tun_chr_ioctl+0x2f/0x40 + [<000000000d759e02>] do_vfs_ioctl+0x1c7/0x1510 + [<00000000351d7c31>] ksys_ioctl+0x99/0xb0 + [<000000008390040a>] __x64_sys_ioctl+0x78/0xb0 + [<0000000052d196b7>] do_syscall_64+0x16f/0x580 + [<0000000019af9236>] entry_SYSCALL_64_after_hwframe+0x44/0xa9 + [<00000000bc384531>] 0xffffffffffffffff + +v3 -> v4: + Set reg_state to NETREG_UNREGISTERED if registering fails + +v2 -> v3: +* Replaced BUG_ON with WARN_ON in free_netdev and netdev_release + +v1 -> v2: +* Relying on driver calling free_netdev rather than calling + put_device directly in error path + +Reported-by: syzbot+ad8ca40ecd77896d51e2@syzkaller.appspotmail.com +Cc: David Miller +Cc: Greg Kroah-Hartman +Cc: Lukas Bulwahn +Signed-off-by: Jouni Hogander +Signed-off-by: David S. Miller +Signed-off-by: Jiri Slaby +--- + net/core/dev.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +--- a/net/core/dev.c ++++ b/net/core/dev.c +@@ -7617,8 +7617,10 @@ int register_netdevice(struct net_device + goto err_uninit; + + ret = netdev_register_kobject(dev); +- if (ret) ++ if (ret) { ++ dev->reg_state = NETREG_UNREGISTERED; + goto err_uninit; ++ } + dev->reg_state = NETREG_REGISTERED; + + __netdev_update_features(dev); diff --git a/patches.suse/net-systemport-Avoid-RBUF-stuck-in-Wake-on-LAN-mode.patch b/patches.suse/net-systemport-Avoid-RBUF-stuck-in-Wake-on-LAN-mode.patch new file mode 100644 index 0000000..2dca84e --- /dev/null +++ b/patches.suse/net-systemport-Avoid-RBUF-stuck-in-Wake-on-LAN-mode.patch @@ -0,0 +1,35 @@ +From: Florian Fainelli +Date: Wed, 5 Feb 2020 12:32:04 -0800 +Subject: net: systemport: Avoid RBUF stuck in Wake-on-LAN mode +Git-commit: 263a425a482fc495d6d3f9a29b9103a664c38b69 +Patch-mainline: 5.6-rc1 +References: networking-stable-20_02_09 + +After a number of suspend and resume cycles, it is possible for the RBUF +to be stuck in Wake-on-LAN mode, despite the MPD enable bit being +cleared which instructed the RBUF to exit that mode. + +Avoid creating that problematic condition by clearing the RX_EN and +TX_EN bits in the UniMAC prior to disable the Magic Packet Detector +logic which is guaranteed to make the RBUF exit Wake-on-LAN mode. + +Fixes: 83e82f4c706b ("net: systemport: add Wake-on-LAN support") +Signed-off-by: Florian Fainelli +Signed-off-by: David S. Miller +Signed-off-by: Jiri Slaby +--- + drivers/net/ethernet/broadcom/bcmsysport.c | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/drivers/net/ethernet/broadcom/bcmsysport.c ++++ b/drivers/net/ethernet/broadcom/bcmsysport.c +@@ -2246,6 +2246,9 @@ static int bcm_sysport_resume(struct dev + + umac_reset(priv); + ++ /* Disable the UniMAC RX/TX */ ++ umac_enable_set(priv, CMD_RX_EN | CMD_TX_EN, 0); ++ + /* We may have been suspended and never received a WOL event that + * would turn off MPD detection, take care of that now + */ diff --git a/patches.suse/net-tls-fix-async-operation.patch b/patches.suse/net-tls-fix-async-operation.patch new file mode 100644 index 0000000..e34dd37 --- /dev/null +++ b/patches.suse/net-tls-fix-async-operation.patch @@ -0,0 +1,45 @@ +From: Jakub Kicinski +Date: Fri, 10 Jan 2020 04:38:32 -0800 +Subject: net/tls: fix async operation +Patch-mainline: v5.5-rc7 +Git-commit: db885e66d268884dc72967279b7e84f522556abc +References: bsc#1109837 + +Mallesham reports the TLS with async accelerator was broken by +commit d10523d0b3d7 ("net/tls: free the record on encryption error") +because encryption can return -EINPROGRESS in such setups, which +should not be treated as an error. + +The error is also present in the BPF path (likely copied from there). + +Reported-by: Mallesham Jatharakonda +Fixes: d3b18ad31f93 ("tls: add bpf support to sk_msg handling") +Fixes: d10523d0b3d7 ("net/tls: free the record on encryption error") +Signed-off-by: Jakub Kicinski +Reviewed-by: Simon Horman +Signed-off-by: David S. Miller +Acked-by: Thomas Bogendoerfer +--- + net/tls/tls_sw.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/net/tls/tls_sw.c ++++ b/net/tls/tls_sw.c +@@ -695,7 +695,7 @@ static int bpf_exec_tx_verdict(struct sk + psock = sk_psock_get(sk); + if (!psock || !policy) { + err = tls_push_record(sk, flags, record_type); +- if (err) { ++ if (err && err != -EINPROGRESS) { + *copied -= sk_msg_free(sk, msg); + tls_free_open_rec(sk); + } +@@ -718,7 +718,7 @@ more_data: + switch (psock->eval) { + case __SK_PASS: + err = tls_push_record(sk, flags, record_type); +- if (err < 0) { ++ if (err && err != -EINPROGRESS) { + *copied -= sk_msg_free(sk, msg); + tls_free_open_rec(sk); + goto out_err; diff --git a/patches.suse/net-tls-free-the-record-on-encryption-error.patch b/patches.suse/net-tls-free-the-record-on-encryption-error.patch new file mode 100644 index 0000000..35c3d92 --- /dev/null +++ b/patches.suse/net-tls-free-the-record-on-encryption-error.patch @@ -0,0 +1,47 @@ +From: Jakub Kicinski +Date: Wed, 27 Nov 2019 12:16:40 -0800 +Subject: net/tls: free the record on encryption error +Patch-mainline: v5.5-rc1 +Git-commit: d10523d0b3d78153ee58d19853ced26c9004c8c4 +References: bsc#1109837 + +When tls_do_encryption() fails the SG lists are left with the +SG_END and SG_CHAIN marks in place. One could hope that once +encryption fails we will never see the record again, but that +is in fact not true. Commit d3b18ad31f93 ("tls: add bpf support +to sk_msg handling") added special handling to ENOMEM and ENOSPC +errors which mean we may see the same record re-submitted. + +As suggested by John free the record, the BPF code is already +doing just that. + +Reported-by: syzbot+df0d4ec12332661dd1f9@syzkaller.appspotmail.com +Fixes: d3b18ad31f93 ("tls: add bpf support to sk_msg handling") +Signed-off-by: Jakub Kicinski +Reviewed-by: Simon Horman +Acked-by: John Fastabend +Signed-off-by: David S. Miller +Acked-by: Thomas Bogendoerfer +--- + net/tls/tls_sw.c | 10 ++++++++-- + 1 file changed, 8 insertions(+), 2 deletions(-) + +--- a/net/tls/tls_sw.c ++++ b/net/tls/tls_sw.c +@@ -693,8 +693,14 @@ static int bpf_exec_tx_verdict(struct sk + + policy = !(flags & MSG_SENDPAGE_NOPOLICY); + psock = sk_psock_get(sk); +- if (!psock || !policy) +- return tls_push_record(sk, flags, record_type); ++ if (!psock || !policy) { ++ err = tls_push_record(sk, flags, record_type); ++ if (err) { ++ *copied -= sk_msg_free(sk, msg); ++ tls_free_open_rec(sk); ++ } ++ return err; ++ } + more_data: + enospc = sk_msg_full(msg); + if (psock->eval == __SK_NONE) diff --git a/patches.suse/net-tls-take-into-account-that-bpf_exec_tx_verdict-m.patch b/patches.suse/net-tls-take-into-account-that-bpf_exec_tx_verdict-m.patch new file mode 100644 index 0000000..572bc0f --- /dev/null +++ b/patches.suse/net-tls-take-into-account-that-bpf_exec_tx_verdict-m.patch @@ -0,0 +1,64 @@ +From: Jakub Kicinski +Date: Wed, 27 Nov 2019 12:16:39 -0800 +Subject: net/tls: take into account that bpf_exec_tx_verdict() may free the + record +Patch-mainline: v5.5-rc1 +Git-commit: c329ef9684de9517d82af5b4758c9e1b64a8a11a +References: bsc#1109837 + +bpf_exec_tx_verdict() may free the record if tls_push_record() +fails, or if the entire record got consumed by BPF. Re-check +ctx->open_rec before touching the data. + +Fixes: d3b18ad31f93 ("tls: add bpf support to sk_msg handling") +Signed-off-by: Jakub Kicinski +Reviewed-by: Simon Horman +Acked-by: John Fastabend +Signed-off-by: David S. Miller +Acked-by: Thomas Bogendoerfer +--- + net/tls/tls_sw.c | 13 ++++++++----- + 1 file changed, 8 insertions(+), 5 deletions(-) + +--- a/net/tls/tls_sw.c ++++ b/net/tls/tls_sw.c +@@ -906,7 +906,7 @@ alloc_encrypted: + num_async++; + else if (ret == -ENOMEM) + goto wait_for_memory; +- else if (ret == -ENOSPC) ++ else if (ctx->open_rec && ret == -ENOSPC) + goto rollback_iter; + else if (ret != -EAGAIN) + goto send_end; +@@ -975,11 +975,12 @@ wait_for_memory: + ret = sk_stream_wait_memory(sk, &timeo); + if (ret) { + trim_sgl: +- tls_trim_both_msgs(sk, orig_size); ++ if (ctx->open_rec) ++ tls_trim_both_msgs(sk, orig_size); + goto send_end; + } + +- if (msg_en->sg.size < required_size) ++ if (ctx->open_rec && msg_en->sg.size < required_size) + goto alloc_encrypted; + } + +@@ -1118,11 +1119,13 @@ wait_for_sndbuf: + wait_for_memory: + ret = sk_stream_wait_memory(sk, &timeo); + if (ret) { +- tls_trim_both_msgs(sk, msg_pl->sg.size); ++ if (ctx->open_rec) ++ tls_trim_both_msgs(sk, msg_pl->sg.size); + goto sendpage_end; + } + +- goto alloc_payload; ++ if (ctx->open_rec) ++ goto alloc_payload; + } + + if (num_async) { diff --git a/patches.suse/net-usb-lan78xx-Add-.ndo_features_check.patch b/patches.suse/net-usb-lan78xx-Add-.ndo_features_check.patch new file mode 100644 index 0000000..c552a38 --- /dev/null +++ b/patches.suse/net-usb-lan78xx-Add-.ndo_features_check.patch @@ -0,0 +1,60 @@ +From: James Hughes +Date: Mon, 20 Jan 2020 11:12:40 +0000 +Subject: net: usb: lan78xx: Add .ndo_features_check +Git-commit: ce896476c65d72b4b99fa09c2f33436b4198f034 +Patch-mainline: 5.5 +References: networking-stable-20_01_27 + +As reported by Eric Dumazet, there are still some outstanding +cases where the driver does not handle TSO correctly when skb's +are over a certain size. Most cases have been fixed, this patch +should ensure that forwarded SKB's that are greater than +MAX_SINGLE_PACKET_SIZE - TX_OVERHEAD are software segmented +and handled correctly. + +Signed-off-by: James Hughes +Reviewed-by: Eric Dumazet +Signed-off-by: David S. Miller +Signed-off-by: Jiri Slaby +--- + drivers/net/usb/lan78xx.c | 15 +++++++++++++++ + 1 file changed, 15 insertions(+) + +--- a/drivers/net/usb/lan78xx.c ++++ b/drivers/net/usb/lan78xx.c +@@ -31,6 +31,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -3568,6 +3569,19 @@ static void lan78xx_tx_timeout(struct ne + tasklet_schedule(&dev->bh); + } + ++static netdev_features_t lan78xx_features_check(struct sk_buff *skb, ++ struct net_device *netdev, ++ netdev_features_t features) ++{ ++ if (skb->len + TX_OVERHEAD > MAX_SINGLE_PACKET_SIZE) ++ features &= ~NETIF_F_GSO_MASK; ++ ++ features = vlan_features_check(skb, features); ++ features = vxlan_features_check(skb, features); ++ ++ return features; ++} ++ + static const struct net_device_ops lan78xx_netdev_ops = { + .ndo_open = lan78xx_open, + .ndo_stop = lan78xx_stop, +@@ -3581,6 +3595,7 @@ static const struct net_device_ops lan78 + .ndo_set_features = lan78xx_set_features, + .ndo_vlan_rx_add_vid = lan78xx_vlan_rx_add_vid, + .ndo_vlan_rx_kill_vid = lan78xx_vlan_rx_kill_vid, ++ .ndo_features_check = lan78xx_features_check, + }; + + static void lan78xx_stat_monitor(unsigned long param) diff --git a/patches.suse/net-usb-lan78xx-fix-possible-skb-leak.patch b/patches.suse/net-usb-lan78xx-fix-possible-skb-leak.patch new file mode 100644 index 0000000..635d11b --- /dev/null +++ b/patches.suse/net-usb-lan78xx-fix-possible-skb-leak.patch @@ -0,0 +1,50 @@ +From: Eric Dumazet +Date: Tue, 7 Jan 2020 10:57:01 -0800 +Subject: net: usb: lan78xx: fix possible skb leak +Git-commit: 47240ba0cd09bb6fe6db9889582048324999dfa4 +Patch-mainline: 5.5-rc6 +References: networking-stable-20_01_11 + +If skb_linearize() fails, we need to free the skb. + +TSO makes skb bigger, and this bug might be the reason +Raspberry Pi 3B+ users had to disable TSO. + +Fixes: 55d7de9de6c3 ("Microchip's LAN7800 family USB 2/3 to 10/100/1000 Ethernet device driver") +Signed-off-by: Eric Dumazet +Reported-by: RENARD Pierre-Francois +Cc: Stefan Wahren +Cc: Woojung Huh +Cc: Microchip Linux Driver Support +Signed-off-by: David S. Miller +Signed-off-by: Jiri Slaby +--- + drivers/net/usb/lan78xx.c | 9 +++------ + 1 file changed, 3 insertions(+), 6 deletions(-) + +--- a/drivers/net/usb/lan78xx.c ++++ b/drivers/net/usb/lan78xx.c +@@ -2647,11 +2647,6 @@ static int lan78xx_stop(struct net_devic + return 0; + } + +-static int lan78xx_linearize(struct sk_buff *skb) +-{ +- return skb_linearize(skb); +-} +- + static struct sk_buff *lan78xx_tx_prep(struct lan78xx_net *dev, + struct sk_buff *skb, gfp_t flags) + { +@@ -2662,8 +2657,10 @@ static struct sk_buff *lan78xx_tx_prep(s + return NULL; + } + +- if (lan78xx_linearize(skb) < 0) ++ if (skb_linearize(skb)) { ++ dev_kfree_skb_any(skb); + return NULL; ++ } + + tx_cmd_a = (u32)(skb->len & TX_CMD_A_LEN_MASK_) | TX_CMD_A_FCS_; + diff --git a/patches.suse/net-wan-fsl_ucc_hdlc-fix-out-of-bounds-write-on-arra.patch b/patches.suse/net-wan-fsl_ucc_hdlc-fix-out-of-bounds-write-on-arra.patch new file mode 100644 index 0000000..968c5e4 --- /dev/null +++ b/patches.suse/net-wan-fsl_ucc_hdlc-fix-out-of-bounds-write-on-arra.patch @@ -0,0 +1,33 @@ +From: Colin Ian King +Date: Tue, 14 Jan 2020 14:54:48 +0000 +Subject: net/wan/fsl_ucc_hdlc: fix out of bounds write on array utdm_info +Git-commit: ddf420390526ede3b9ff559ac89f58cb59d9db2f +Patch-mainline: 5.5-rc7 +References: networking-stable-20_01_20 + +Array utdm_info is declared as an array of MAX_HDLC_NUM (4) elements +however up to UCC_MAX_NUM (8) elements are potentially being written +to it. Currently we have an array out-of-bounds write error on the +last 4 elements. Fix this by making utdm_info UCC_MAX_NUM elements in +size. + +Addresses-Coverity: ("Out-of-bounds write") +Fixes: c19b6d246a35 ("drivers/net: support hdlc function for QE-UCC") +Signed-off-by: Colin Ian King +Signed-off-by: David S. Miller +Signed-off-by: Jiri Slaby +--- + drivers/net/wan/fsl_ucc_hdlc.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/net/wan/fsl_ucc_hdlc.c ++++ b/drivers/net/wan/fsl_ucc_hdlc.c +@@ -77,7 +77,7 @@ static struct ucc_tdm_info utdm_primary_ + }, + }; + +-static struct ucc_tdm_info utdm_info[MAX_HDLC_NUM]; ++static struct ucc_tdm_info utdm_info[UCC_MAX_NUM]; + + static int uhdlc_init(struct ucc_hdlc_private *priv) + { diff --git a/patches.suse/net_sched-ematch-reject-invalid-TCF_EM_SIMPLE.patch b/patches.suse/net_sched-ematch-reject-invalid-TCF_EM_SIMPLE.patch new file mode 100644 index 0000000..e421ff4 --- /dev/null +++ b/patches.suse/net_sched-ematch-reject-invalid-TCF_EM_SIMPLE.patch @@ -0,0 +1,77 @@ +From: Eric Dumazet +Date: Fri, 24 Jan 2020 14:57:20 -0800 +Subject: net_sched: ematch: reject invalid TCF_EM_SIMPLE +Git-commit: 55cd9f67f1e45de8517cdaab985fb8e56c0bc1d8 +Patch-mainline: 5.6-rc1 +References: networking-stable-20_01_30 + +It is possible for malicious userspace to set TCF_EM_SIMPLE bit +even for matches that should not have this bit set. + +This can fool two places using tcf_em_is_simple() + +1) tcf_em_tree_destroy() -> memory leak of em->data + if ops->destroy() is NULL + +2) tcf_em_tree_dump() wrongly report/leak 4 low-order bytes + of a kernel pointer. + +BUG: memory leak +unreferenced object 0xffff888121850a40 (size 32): + comm "syz-executor927", pid 7193, jiffies 4294941655 (age 19.840s) + hex dump (first 32 bytes): + 00 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 ................ + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ + backtrace: + [<00000000f67036ea>] kmemleak_alloc_recursive include/linux/kmemleak.h:43 [inline] + [<00000000f67036ea>] slab_post_alloc_hook mm/slab.h:586 [inline] + [<00000000f67036ea>] slab_alloc mm/slab.c:3320 [inline] + [<00000000f67036ea>] __do_kmalloc mm/slab.c:3654 [inline] + [<00000000f67036ea>] __kmalloc_track_caller+0x165/0x300 mm/slab.c:3671 + [<00000000fab0cc8e>] kmemdup+0x27/0x60 mm/util.c:127 + [<00000000d9992e0a>] kmemdup include/linux/string.h:453 [inline] + [<00000000d9992e0a>] em_nbyte_change+0x5b/0x90 net/sched/em_nbyte.c:32 + [<000000007e04f711>] tcf_em_validate net/sched/ematch.c:241 [inline] + [<000000007e04f711>] tcf_em_tree_validate net/sched/ematch.c:359 [inline] + [<000000007e04f711>] tcf_em_tree_validate+0x332/0x46f net/sched/ematch.c:300 + [<000000007a769204>] basic_set_parms net/sched/cls_basic.c:157 [inline] + [<000000007a769204>] basic_change+0x1d7/0x5f0 net/sched/cls_basic.c:219 + [<00000000e57a5997>] tc_new_tfilter+0x566/0xf70 net/sched/cls_api.c:2104 + [<0000000074b68559>] rtnetlink_rcv_msg+0x3b2/0x4b0 net/core/rtnetlink.c:5415 + [<00000000b7fe53fb>] netlink_rcv_skb+0x61/0x170 net/netlink/af_netlink.c:2477 + [<00000000e83a40d0>] rtnetlink_rcv+0x1d/0x30 net/core/rtnetlink.c:5442 + [<00000000d62ba933>] netlink_unicast_kernel net/netlink/af_netlink.c:1302 [inline] + [<00000000d62ba933>] netlink_unicast+0x223/0x310 net/netlink/af_netlink.c:1328 + [<0000000088070f72>] netlink_sendmsg+0x2c0/0x570 net/netlink/af_netlink.c:1917 + [<00000000f70b15ea>] sock_sendmsg_nosec net/socket.c:639 [inline] + [<00000000f70b15ea>] sock_sendmsg+0x54/0x70 net/socket.c:659 + [<00000000ef95a9be>] ____sys_sendmsg+0x2d0/0x300 net/socket.c:2330 + [<00000000b650f1ab>] ___sys_sendmsg+0x8a/0xd0 net/socket.c:2384 + [<0000000055bfa74a>] __sys_sendmsg+0x80/0xf0 net/socket.c:2417 + [<000000002abac183>] __do_sys_sendmsg net/socket.c:2426 [inline] + [<000000002abac183>] __se_sys_sendmsg net/socket.c:2424 [inline] + [<000000002abac183>] __x64_sys_sendmsg+0x23/0x30 net/socket.c:2424 + +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Signed-off-by: Eric Dumazet +Reported-by: syzbot+03c4738ed29d5d366ddf@syzkaller.appspotmail.com +Cc: Cong Wang +Acked-by: Cong Wang +Signed-off-by: David S. Miller +Signed-off-by: Jiri Slaby +--- + net/sched/ematch.c | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/net/sched/ematch.c ++++ b/net/sched/ematch.c +@@ -242,6 +242,9 @@ static int tcf_em_validate(struct tcf_pr + goto errout; + + if (em->ops->change) { ++ err = -EINVAL; ++ if (em_hdr->flags & TCF_EM_SIMPLE) ++ goto errout; + err = em->ops->change(net, data, data_len, em); + if (err < 0) + goto errout; diff --git a/patches.suse/net_sched-fix-a-resource-leak-in-tcindex_set_parms.patch b/patches.suse/net_sched-fix-a-resource-leak-in-tcindex_set_parms.patch new file mode 100644 index 0000000..104628b --- /dev/null +++ b/patches.suse/net_sched-fix-a-resource-leak-in-tcindex_set_parms.patch @@ -0,0 +1,45 @@ +From: Cong Wang +Date: Tue, 4 Feb 2020 11:10:12 -0800 +Subject: net_sched: fix a resource leak in tcindex_set_parms() +Git-commit: 52b5ae501c045010aeeb1d5ac0373ff161a88291 +Patch-mainline: 5.6-rc1 +References: networking-stable-20_02_09 + +Jakub noticed there is a potential resource leak in +tcindex_set_parms(): when tcindex_filter_result_init() fails +and it jumps to 'errout1' which doesn't release the memory +and resources allocated by tcindex_alloc_perfect_hash(). + +We should just jump to 'errout_alloc' which calls +tcindex_free_perfect_hash(). + +Fixes: b9a24bb76bf6 ("net_sched: properly handle failure case of tcf_exts_init()") +Reported-by: Jakub Kicinski +Cc: Jamal Hadi Salim +Cc: Jiri Pirko +Signed-off-by: Cong Wang +Signed-off-by: David S. Miller +Signed-off-by: Jiri Slaby +--- + net/sched/cls_tcindex.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +--- a/net/sched/cls_tcindex.c ++++ b/net/sched/cls_tcindex.c +@@ -337,7 +337,7 @@ tcindex_set_parms(struct net *net, struc + + err = tcindex_filter_result_init(&new_filter_result); + if (err < 0) +- goto errout1; ++ goto errout_alloc; + if (old_r) + cr = r->res; + +@@ -456,7 +456,6 @@ errout_alloc: + tcindex_free_perfect_hash(cp); + else if (balloc == 2) + kfree(cp->h); +-errout1: + tcf_exts_destroy(&new_filter_result.exts); + errout: + kfree(cp); diff --git a/patches.suse/net_sched-fix-an-OOB-access-in-cls_tcindex.patch b/patches.suse/net_sched-fix-an-OOB-access-in-cls_tcindex.patch new file mode 100644 index 0000000..5e95555 --- /dev/null +++ b/patches.suse/net_sched-fix-an-OOB-access-in-cls_tcindex.patch @@ -0,0 +1,98 @@ +From: Cong Wang +Date: Sun, 2 Feb 2020 21:14:35 -0800 +Subject: net_sched: fix an OOB access in cls_tcindex +Git-commit: 599be01ee567b61f4471ee8078870847d0a11e8e +Patch-mainline: 5.6-rc1 +References: networking-stable-20_02_05 + +As Eric noticed, tcindex_alloc_perfect_hash() uses cp->hash +to compute the size of memory allocation, but cp->hash is +set again after the allocation, this caused an out-of-bound +access. + +So we have to move all cp->hash initialization and computation +before the memory allocation. Move cp->mask and cp->shift together +as cp->hash may need them for computation too. + +Reported-and-tested-by: syzbot+35d4dea36c387813ed31@syzkaller.appspotmail.com +Fixes: 331b72922c5f ("net: sched: RCU cls_tcindex") +Cc: Eric Dumazet +Cc: John Fastabend +Cc: Jamal Hadi Salim +Cc: Jiri Pirko +Cc: Jakub Kicinski +Signed-off-by: Cong Wang +Signed-off-by: David S. Miller +Signed-off-by: Jiri Slaby +--- + net/sched/cls_tcindex.c | 40 ++++++++++++++++++++-------------------- + 1 file changed, 20 insertions(+), 20 deletions(-) + +--- a/net/sched/cls_tcindex.c ++++ b/net/sched/cls_tcindex.c +@@ -305,12 +305,31 @@ tcindex_set_parms(struct net *net, struc + cp->fall_through = p->fall_through; + cp->tp = tp; + ++ if (tb[TCA_TCINDEX_HASH]) ++ cp->hash = nla_get_u32(tb[TCA_TCINDEX_HASH]); ++ ++ if (tb[TCA_TCINDEX_MASK]) ++ cp->mask = nla_get_u16(tb[TCA_TCINDEX_MASK]); ++ ++ if (tb[TCA_TCINDEX_SHIFT]) ++ cp->shift = nla_get_u32(tb[TCA_TCINDEX_SHIFT]); ++ ++ if (!cp->hash) { ++ /* Hash not specified, use perfect hash if the upper limit ++ * of the hashing index is below the threshold. ++ */ ++ if ((cp->mask >> cp->shift) < PERFECT_HASH_THRESHOLD) ++ cp->hash = (cp->mask >> cp->shift) + 1; ++ else ++ cp->hash = DEFAULT_HASH_SIZE; ++ } ++ + if (p->perfect) { + int i; + + if (tcindex_alloc_perfect_hash(cp) < 0) + goto errout; +- for (i = 0; i < cp->hash; i++) ++ for (i = 0; i < min(cp->hash, p->hash); i++) + cp->perfect[i].res = p->perfect[i].res; + balloc = 1; + } +@@ -322,15 +341,6 @@ tcindex_set_parms(struct net *net, struc + if (old_r) + cr = r->res; + +- if (tb[TCA_TCINDEX_HASH]) +- cp->hash = nla_get_u32(tb[TCA_TCINDEX_HASH]); +- +- if (tb[TCA_TCINDEX_MASK]) +- cp->mask = nla_get_u16(tb[TCA_TCINDEX_MASK]); +- +- if (tb[TCA_TCINDEX_SHIFT]) +- cp->shift = nla_get_u32(tb[TCA_TCINDEX_SHIFT]); +- + err = -EBUSY; + + /* Hash already allocated, make sure that we still meet the +@@ -348,16 +358,6 @@ tcindex_set_parms(struct net *net, struc + if (tb[TCA_TCINDEX_FALL_THROUGH]) + cp->fall_through = nla_get_u32(tb[TCA_TCINDEX_FALL_THROUGH]); + +- if (!cp->hash) { +- /* Hash not specified, use perfect hash if the upper limit +- * of the hashing index is below the threshold. +- */ +- if ((cp->mask >> cp->shift) < PERFECT_HASH_THRESHOLD) +- cp->hash = (cp->mask >> cp->shift) + 1; +- else +- cp->hash = DEFAULT_HASH_SIZE; +- } +- + if (!cp->perfect && !cp->h) + cp->alloc_hash = cp->hash; + diff --git a/patches.suse/net_sched-fix-datalen-for-ematch.patch b/patches.suse/net_sched-fix-datalen-for-ematch.patch new file mode 100644 index 0000000..0c335bc --- /dev/null +++ b/patches.suse/net_sched-fix-datalen-for-ematch.patch @@ -0,0 +1,50 @@ +From: Cong Wang +Date: Wed, 22 Jan 2020 15:42:02 -0800 +Subject: net_sched: fix datalen for ematch +Git-commit: 61678d28d4a45ef376f5d02a839cc37509ae9281 +Patch-mainline: 5.5 +References: networking-stable-20_01_27 + +syzbot reported an out-of-bound access in em_nbyte. As initially +analyzed by Eric, this is because em_nbyte sets its own em->datalen +in em_nbyte_change() other than the one specified by user, but this +value gets overwritten later by its caller tcf_em_validate(). +We should leave em->datalen untouched to respect their choices. + +I audit all the in-tree ematch users, all of those implement +->change() set em->datalen, so we can just avoid setting it twice +in this case. + +Reported-and-tested-by: syzbot+5af9a90dad568aa9f611@syzkaller.appspotmail.com +Reported-by: syzbot+2f07903a5b05e7f36410@syzkaller.appspotmail.com +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Cc: Eric Dumazet +Signed-off-by: Cong Wang +Reviewed-by: Eric Dumazet +Signed-off-by: David S. Miller +Signed-off-by: Jiri Slaby +--- + net/sched/ematch.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/net/sched/ematch.c b/net/sched/ematch.c +index 8f2ad706784d..d0140a92694a 100644 +--- a/net/sched/ematch.c ++++ b/net/sched/ematch.c +@@ -263,12 +263,12 @@ static int tcf_em_validate(struct tcf_proto *tp, + } + em->data = (unsigned long) v; + } ++ em->datalen = data_len; + } + } + + em->matchid = em_hdr->matchid; + em->flags = em_hdr->flags; +- em->datalen = data_len; + em->net = net; + + err = 0; +-- +2.25.1 + diff --git a/patches.suse/net_sched-keep-alloc_hash-updated-after-hash-allocat.patch b/patches.suse/net_sched-keep-alloc_hash-updated-after-hash-allocat.patch new file mode 100644 index 0000000..2a5ad2c --- /dev/null +++ b/patches.suse/net_sched-keep-alloc_hash-updated-after-hash-allocat.patch @@ -0,0 +1,37 @@ +From: Cong Wang +Date: Wed, 11 Mar 2020 22:42:28 -0700 +Subject: net_sched: keep alloc_hash updated after hash allocation +Git-commit: 0d1c3530e1bd38382edef72591b78e877e0edcd3 +Patch-mainline: 5.6 +References: git-fixes + +In commit 599be01ee567 ("net_sched: fix an OOB access in cls_tcindex") +I moved cp->hash calculation before the first +tcindex_alloc_perfect_hash(), but cp->alloc_hash is left untouched. +This difference could lead to another out of bound access. + +cp->alloc_hash should always be the size allocated, we should +update it after this tcindex_alloc_perfect_hash(). + +Reported-and-tested-by: syzbot+dcc34d54d68ef7d2d53d@syzkaller.appspotmail.com +Reported-and-tested-by: syzbot+c72da7b9ed57cde6fca2@syzkaller.appspotmail.com +Fixes: 599be01ee567 ("net_sched: fix an OOB access in cls_tcindex") +Cc: Jamal Hadi Salim +Cc: Jiri Pirko +Signed-off-by: Cong Wang +Signed-off-by: David S. Miller +Signed-off-by: Jiri Slaby +--- + net/sched/cls_tcindex.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/net/sched/cls_tcindex.c ++++ b/net/sched/cls_tcindex.c +@@ -329,6 +329,7 @@ tcindex_set_parms(struct net *net, struc + + if (tcindex_alloc_perfect_hash(cp) < 0) + goto errout; ++ cp->alloc_hash = cp->hash; + for (i = 0; i < min(cp->hash, p->hash); i++) + cp->perfect[i].res = p->perfect[i].res; + balloc = 1; diff --git a/patches.suse/nvdimm-split-label-init-out-from-the-logic-for-getting-config-data.patch b/patches.suse/nvdimm-split-label-init-out-from-the-logic-for-getting-config-data.patch index 518cfdb..aad7075 100644 --- a/patches.suse/nvdimm-split-label-init-out-from-the-logic-for-getting-config-data.patch +++ b/patches.suse/nvdimm-split-label-init-out-from-the-logic-for-getting-config-data.patch @@ -1,9 +1,12 @@ +From 2d657d17f72d2ae70c02f0d0ea6a04ad0f016b57 Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Wed, 10 Oct 2018 16:39:20 -0700 -Subject: nvdimm: Split label init out from the logic for getting config data -Git-commit: 2d657d17f72d2ae70c02f0d0ea6a04ad0f016b57 -Patch-mainline: v4.20-rc1 +Subject: [PATCH] nvdimm: Split label init out from the logic for getting + config data + References: bsc#1111921, bsc#1113408, FATE#326765, bsc#1113972 +Patch-mainline: v4.20-rc1 +Git-commit: 2d657d17f72d2ae70c02f0d0ea6a04ad0f016b57 This patch splits the initialization of the label data into two functions. One for doing the init, and another for reading the actual configuration @@ -24,16 +27,18 @@ Signed-off-by: Alexander Duyck Signed-off-by: Dan Williams Acked-by: Johannes Thumshirn --- - drivers/nvdimm/dimm.c | 2 - - drivers/nvdimm/dimm_devs.c | 49 +++++++++++++++++---------------------------- - drivers/nvdimm/label.c | 38 ++++++++++++++++++++++++++++++++++ - drivers/nvdimm/label.h | 1 - drivers/nvdimm/nd.h | 2 + + drivers/nvdimm/dimm.c | 2 +- + drivers/nvdimm/dimm_devs.c | 49 +++++++++++++++----------------------- + drivers/nvdimm/label.c | 38 +++++++++++++++++++++++++++++ + drivers/nvdimm/label.h | 1 + + drivers/nvdimm/nd.h | 2 ++ 5 files changed, 61 insertions(+), 31 deletions(-) +diff --git a/drivers/nvdimm/dimm.c b/drivers/nvdimm/dimm.c +index 6c8fb7590838..07bf96948553 100644 --- a/drivers/nvdimm/dimm.c +++ b/drivers/nvdimm/dimm.c -@@ -75,7 +75,7 @@ static int nvdimm_probe(struct device *d +@@ -75,7 +75,7 @@ static int nvdimm_probe(struct device *dev) * DIMM capacity. We fail the dimm probe to prevent regions from * attempting to parse the label area. */ @@ -42,9 +47,11 @@ Acked-by: Johannes Thumshirn if (rc == -EACCES) nvdimm_set_locked(dev); if (rc) +diff --git a/drivers/nvdimm/dimm_devs.c b/drivers/nvdimm/dimm_devs.c +index 75ac78017b15..6c3de2317390 100644 --- a/drivers/nvdimm/dimm_devs.c +++ b/drivers/nvdimm/dimm_devs.c -@@ -85,55 +85,47 @@ int nvdimm_init_nsarea(struct nvdimm_drv +@@ -85,55 +85,47 @@ int nvdimm_init_nsarea(struct nvdimm_drvdata *ndd) return cmd_rc; } @@ -74,11 +81,11 @@ Acked-by: Johannes Thumshirn + if (offset + len > ndd->nsarea.config_size) return -ENXIO; - } -- + - ndd->data = kvmalloc(ndd->nsarea.config_size, GFP_KERNEL); - if (!ndd->data) - return -ENOMEM; - +- - max_cmd_size = min_t(u32, ndd->nsarea.config_size, ndd->nsarea.max_xfer); + max_cmd_size = min_t(u32, len, ndd->nsarea.max_xfer); cmd = kvzalloc(max_cmd_size + sizeof(*cmd), GFP_KERNEL); @@ -115,11 +122,11 @@ Acked-by: Johannes Thumshirn + /* out_buf should be valid, copy it into our output buffer */ + memcpy(buf + buf_offset, cmd->out_buf, cmd->in_length); } -- dev_dbg(ndd->dev, "%s: len: %zu rc: %d\n", __func__, offset, rc); +- dev_dbg(ndd->dev, "len: %zu rc: %d\n", offset, rc); kvfree(cmd); return rc; -@@ -151,9 +143,6 @@ int nvdimm_set_config_data(struct nvdimm +@@ -151,9 +143,6 @@ int nvdimm_set_config_data(struct nvdimm_drvdata *ndd, size_t offset, if (rc) return rc; @@ -129,9 +136,11 @@ Acked-by: Johannes Thumshirn if (offset + len > ndd->nsarea.config_size) return -ENXIO; +diff --git a/drivers/nvdimm/label.c b/drivers/nvdimm/label.c +index 43bad0d5bdb6..563f24af01b5 100644 --- a/drivers/nvdimm/label.c +++ b/drivers/nvdimm/label.c -@@ -422,6 +422,44 @@ int nd_label_reserve_dpa(struct nvdimm_d +@@ -417,6 +417,44 @@ int nd_label_reserve_dpa(struct nvdimm_drvdata *ndd) return 0; } @@ -176,6 +185,8 @@ Acked-by: Johannes Thumshirn int nd_label_active_count(struct nvdimm_drvdata *ndd) { struct nd_namespace_index *nsindex; +diff --git a/drivers/nvdimm/label.h b/drivers/nvdimm/label.h +index 18bbe183b3a9..685afb3de0fe 100644 --- a/drivers/nvdimm/label.h +++ b/drivers/nvdimm/label.h @@ -141,6 +141,7 @@ struct nvdimm_drvdata; @@ -186,9 +197,11 @@ Acked-by: Johannes Thumshirn size_t sizeof_namespace_index(struct nvdimm_drvdata *ndd); int nd_label_active_count(struct nvdimm_drvdata *ndd); struct nd_namespace_label *nd_label_active(struct nvdimm_drvdata *ndd, int n); +diff --git a/drivers/nvdimm/nd.h b/drivers/nvdimm/nd.h +index 98317e7ce5b5..e79cc8e5c114 100644 --- a/drivers/nvdimm/nd.h +++ b/drivers/nvdimm/nd.h -@@ -241,6 +241,8 @@ struct nvdimm_drvdata *to_ndd(struct nd_ +@@ -241,6 +241,8 @@ struct nvdimm_drvdata *to_ndd(struct nd_mapping *nd_mapping); int nvdimm_check_config_data(struct device *dev); int nvdimm_init_nsarea(struct nvdimm_drvdata *ndd); int nvdimm_init_config_data(struct nvdimm_drvdata *ndd); @@ -197,3 +210,6 @@ Acked-by: Johannes Thumshirn int nvdimm_set_config_data(struct nvdimm_drvdata *ndd, size_t offset, void *buf, size_t len); long nvdimm_clear_poison(struct device *dev, phys_addr_t phys, +-- +2.23.0 + diff --git a/patches.suse/nvme-Fix-parsing-of-ANA-log-page.patch b/patches.suse/nvme-Fix-parsing-of-ANA-log-page.patch new file mode 100644 index 0000000..bce80ec --- /dev/null +++ b/patches.suse/nvme-Fix-parsing-of-ANA-log-page.patch @@ -0,0 +1,53 @@ +From: Prabhath Sajeepa +Date: Mon, 28 Oct 2019 16:56:48 -0600 +Subject: [PATCH] nvme: Fix parsing of ANA log page +Patch-Mainline: v5.5-rc1 +Git-commit: 64fab7290dc3561729bbc1e35895a517eb2e549e +References: bsc#1166658 + +Check validity of offset into ANA log buffer before accessing +nvme_ana_group_desc. This check ensures the size of ANA log buffer >= +offset + sizeof(nvme_ana_group_desc) + +Reviewed-by: Sagi Grimberg +Signed-off-by: Prabhath Sajeepa +Signed-off-by: Keith Busch +Signed-off-by: Jens Axboe +Acked-by: Hannes Reinecke +--- + drivers/nvme/host/multipath.c | 12 ++++++++---- + 1 file changed, 8 insertions(+), 4 deletions(-) + +diff --git a/drivers/nvme/host/multipath.c b/drivers/nvme/host/multipath.c +index 103c04fa7746..682be6195a95 100644 +--- a/drivers/nvme/host/multipath.c ++++ b/drivers/nvme/host/multipath.c +@@ -445,8 +445,14 @@ static int nvme_parse_ana_log(struct nvme_ctrl *ctrl, void *data, + + for (i = 0; i < le16_to_cpu(ctrl->ana_log_buf->ngrps); i++) { + struct nvme_ana_group_desc *desc = base + offset; +- u32 nr_nsids = le32_to_cpu(desc->nnsids); +- size_t nsid_buf_size = nr_nsids * sizeof(__le32); ++ u32 nr_nsids; ++ size_t nsid_buf_size; ++ ++ if (WARN_ON_ONCE(offset > ctrl->ana_log_size - sizeof(*desc))) ++ return -EINVAL; ++ ++ nr_nsids = le32_to_cpu(desc->nnsids); ++ nsid_buf_size = nr_nsids * sizeof(__le32); + + if (WARN_ON_ONCE(desc->grpid == 0)) + return -EINVAL; +@@ -466,8 +472,6 @@ static int nvme_parse_ana_log(struct nvme_ctrl *ctrl, void *data, + return error; + + offset += nsid_buf_size; +- if (WARN_ON_ONCE(offset > ctrl->ana_log_size - sizeof(*desc))) +- return -EINVAL; + } + + return 0; +-- +2.16.4 + diff --git a/patches.suse/nvme-Translate-more-status-codes-to-blk_status_t.patch b/patches.suse/nvme-Translate-more-status-codes-to-blk_status_t.patch new file mode 100644 index 0000000..4b6e825 --- /dev/null +++ b/patches.suse/nvme-Translate-more-status-codes-to-blk_status_t.patch @@ -0,0 +1,37 @@ +From: Keith Busch +Date: Fri, 6 Dec 2019 04:50:44 +0900 +Subject: [PATCH] nvme: Translate more status codes to blk_status_t +Patch-Mainline: v5.5-rc6 +Git-commit: 35038bffa87da282010b91108cadd13238bb5bbd +References: bsc#1156510 + +Decode interrupted command and not ready namespace nvme status codes to +BLK_STS_TARGET. These are not generic IO errors and should use a non-path +specific error so that it can use the non-failover retry path. + +Reported-by: John Meneghini +Cc: Hannes Reinecke +Reviewed-by: Christoph Hellwig +Signed-off-by: Keith Busch +Signed-off-by: Jens Axboe +Acked-by: Hannes Reinecke +--- + drivers/nvme/host/core.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c +index 667f18f465be..5dc32b72e7fa 100644 +--- a/drivers/nvme/host/core.c ++++ b/drivers/nvme/host/core.c +@@ -222,6 +222,8 @@ static blk_status_t nvme_error_status(u16 status) + case NVME_SC_CAP_EXCEEDED: + return BLK_STS_NOSPC; + case NVME_SC_LBA_RANGE: ++ case NVME_SC_CMD_INTERRUPTED: ++ case NVME_SC_NS_NOT_READY: + return BLK_STS_TARGET; + case NVME_SC_BAD_ATTRIBUTES: + case NVME_SC_ONCS_NOT_SUPPORTED: +-- +2.16.4 + diff --git a/patches.suse/nvme-fix-a-possible-deadlock-when-passthru-commands-.patch b/patches.suse/nvme-fix-a-possible-deadlock-when-passthru-commands-.patch new file mode 100644 index 0000000..adcecff --- /dev/null +++ b/patches.suse/nvme-fix-a-possible-deadlock-when-passthru-commands-.patch @@ -0,0 +1,200 @@ +From: Sagi Grimberg +Date: Wed, 31 Jul 2019 11:00:26 -0700 +Subject: nvme: fix a possible deadlock when passthru commands sent to a + multipath device +Patch-mainline: v5.3-rc5 +Git-commit: b9156daeb1601d69007b7e50efcf89d69d72ec1d +References: bsc#1158983 + +When the user issues a command with side effects, we will end up freezing +the namespace request queue when updating disk info (and the same for +the corresponding mpath disk node). + +However, we are not freezing the mpath node request queue, +which means that mpath I/O can still come in and block on blk_queue_enter +(called from nvme_ns_head_make_request -> direct_make_request). + +This is a deadlock, because blk_queue_enter will block until the inner +namespace request queue is unfroze, but that process is blocked because +the namespace revalidation is trying to update the mpath disk info +and freeze its request queue (which will never complete because +of the I/O that is blocked on blk_queue_enter). + +Fix this by freezing all the subsystem nsheads request queues before +executing the passthru command. Given that these commands are infrequent +we should not worry about this temporary I/O freeze to keep things sane. + +Here is the matching hang traces: +-- +[ 374.465002] INFO: task systemd-udevd:17994 blocked for more than 122 seconds. +[ 374.472975] Not tainted 5.2.0-rc3-mpdebug+ #42 +[ 374.478522] "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message. +[ 374.487274] systemd-udevd D 0 17994 1 0x00000000 +[ 374.493407] Call Trace: +[ 374.496145] __schedule+0x2ef/0x620 +[ 374.500047] schedule+0x38/0xa0 +[ 374.503569] blk_queue_enter+0x139/0x220 +[ 374.507959] ? remove_wait_queue+0x60/0x60 +[ 374.512540] direct_make_request+0x60/0x130 +[ 374.517219] nvme_ns_head_make_request+0x11d/0x420 [nvme_core] +[ 374.523740] ? generic_make_request_checks+0x307/0x6f0 +[ 374.529484] generic_make_request+0x10d/0x2e0 +[ 374.534356] submit_bio+0x75/0x140 +[ 374.538163] ? guard_bio_eod+0x32/0xe0 +[ 374.542361] submit_bh_wbc+0x171/0x1b0 +[ 374.546553] block_read_full_page+0x1ed/0x330 +[ 374.551426] ? check_disk_change+0x70/0x70 +[ 374.556008] ? scan_shadow_nodes+0x30/0x30 +[ 374.560588] blkdev_readpage+0x18/0x20 +[ 374.564783] do_read_cache_page+0x301/0x860 +[ 374.569463] ? blkdev_writepages+0x10/0x10 +[ 374.574037] ? prep_new_page+0x88/0x130 +[ 374.578329] ? get_page_from_freelist+0xa2f/0x1280 +[ 374.583688] ? __alloc_pages_nodemask+0x179/0x320 +[ 374.588947] read_cache_page+0x12/0x20 +[ 374.593142] read_dev_sector+0x2d/0xd0 +[ 374.597337] read_lba+0x104/0x1f0 +[ 374.601046] find_valid_gpt+0xfa/0x720 +[ 374.605243] ? string_nocheck+0x58/0x70 +[ 374.609534] ? find_valid_gpt+0x720/0x720 +[ 374.614016] efi_partition+0x89/0x430 +[ 374.618113] ? string+0x48/0x60 +[ 374.621632] ? snprintf+0x49/0x70 +[ 374.625339] ? find_valid_gpt+0x720/0x720 +[ 374.629828] check_partition+0x116/0x210 +[ 374.634214] rescan_partitions+0xb6/0x360 +[ 374.638699] __blkdev_reread_part+0x64/0x70 +[ 374.643377] blkdev_reread_part+0x23/0x40 +[ 374.647860] blkdev_ioctl+0x48c/0x990 +[ 374.651956] block_ioctl+0x41/0x50 +[ 374.655766] do_vfs_ioctl+0xa7/0x600 +[ 374.659766] ? locks_lock_inode_wait+0xb1/0x150 +[ 374.664832] ksys_ioctl+0x67/0x90 +[ 374.668539] __x64_sys_ioctl+0x1a/0x20 +[ 374.672732] do_syscall_64+0x5a/0x1c0 +[ 374.676828] entry_SYSCALL_64_after_hwframe+0x44/0xa9 + +[ 374.738474] INFO: task nvmeadm:49141 blocked for more than 123 seconds. +[ 374.745871] Not tainted 5.2.0-rc3-mpdebug+ #42 +[ 374.751419] "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message. +[ 374.760170] nvmeadm D 0 49141 36333 0x00004080 +[ 374.766301] Call Trace: +[ 374.769038] __schedule+0x2ef/0x620 +[ 374.772939] schedule+0x38/0xa0 +[ 374.776452] blk_mq_freeze_queue_wait+0x59/0x100 +[ 374.781614] ? remove_wait_queue+0x60/0x60 +[ 374.786192] blk_mq_freeze_queue+0x1a/0x20 +[ 374.790773] nvme_update_disk_info.isra.57+0x5f/0x350 [nvme_core] +[ 374.797582] ? nvme_identify_ns.isra.50+0x71/0xc0 [nvme_core] +[ 374.804006] __nvme_revalidate_disk+0xe5/0x110 [nvme_core] +[ 374.810139] nvme_revalidate_disk+0xa6/0x120 [nvme_core] +[ 374.816078] ? nvme_submit_user_cmd+0x11e/0x320 [nvme_core] +[ 374.822299] nvme_user_cmd+0x264/0x370 [nvme_core] +[ 374.827661] nvme_dev_ioctl+0x112/0x1d0 [nvme_core] +[ 374.833114] do_vfs_ioctl+0xa7/0x600 +[ 374.837117] ? __audit_syscall_entry+0xdd/0x130 +[ 374.842184] ksys_ioctl+0x67/0x90 +[ 374.845891] __x64_sys_ioctl+0x1a/0x20 +[ 374.850082] do_syscall_64+0x5a/0x1c0 +[ 374.854178] entry_SYSCALL_64_after_hwframe+0x44/0xa9 +-- + +Reported-by: James Puthukattukaran +Tested-by: James Puthukattukaran +Reviewed-by: Keith Busch +Signed-off-by: Sagi Grimberg +Acked-by: Daniel Wagner +--- + drivers/nvme/host/core.c | 5 +++++ + drivers/nvme/host/multipath.c | 30 ++++++++++++++++++++++++++++++ + drivers/nvme/host/nvme.h | 12 ++++++++++++ + 3 files changed, 47 insertions(+) + +--- a/drivers/nvme/host/core.c ++++ b/drivers/nvme/host/core.c +@@ -1209,6 +1209,9 @@ static u32 nvme_passthru_start(struct nv + */ + if (effects & (NVME_CMD_EFFECTS_LBCC | NVME_CMD_EFFECTS_CSE_MASK)) { + mutex_lock(&ctrl->scan_lock); ++ mutex_lock(&ctrl->subsys->lock); ++ nvme_mpath_start_freeze(ctrl->subsys); ++ nvme_mpath_wait_freeze(ctrl->subsys); + nvme_start_freeze(ctrl); + nvme_wait_freeze(ctrl); + } +@@ -1239,6 +1242,8 @@ static void nvme_passthru_end(struct nvm + nvme_update_formats(ctrl); + if (effects & (NVME_CMD_EFFECTS_LBCC | NVME_CMD_EFFECTS_CSE_MASK)) { + nvme_unfreeze(ctrl); ++ nvme_mpath_unfreeze(ctrl->subsys); ++ mutex_unlock(&ctrl->subsys->lock); + mutex_unlock(&ctrl->scan_lock); + } + if (effects & NVME_CMD_EFFECTS_CCC) +--- a/drivers/nvme/host/multipath.c ++++ b/drivers/nvme/host/multipath.c +@@ -20,6 +20,36 @@ module_param(multipath, bool, 0444); + MODULE_PARM_DESC(multipath, + "turn on native support for multiple controllers per subsystem"); + ++void nvme_mpath_unfreeze(struct nvme_subsystem *subsys) ++{ ++ struct nvme_ns_head *h; ++ ++ lockdep_assert_held(&subsys->lock); ++ list_for_each_entry(h, &subsys->nsheads, entry) ++ if (h->disk) ++ blk_mq_unfreeze_queue(h->disk->queue); ++} ++ ++void nvme_mpath_wait_freeze(struct nvme_subsystem *subsys) ++{ ++ struct nvme_ns_head *h; ++ ++ lockdep_assert_held(&subsys->lock); ++ list_for_each_entry(h, &subsys->nsheads, entry) ++ if (h->disk) ++ blk_mq_freeze_queue_wait(h->disk->queue); ++} ++ ++void nvme_mpath_start_freeze(struct nvme_subsystem *subsys) ++{ ++ struct nvme_ns_head *h; ++ ++ lockdep_assert_held(&subsys->lock); ++ list_for_each_entry(h, &subsys->nsheads, entry) ++ if (h->disk) ++ blk_freeze_queue_start(h->disk->queue); ++} ++ + /* + * If multipathing is enabled we need to always use the subsystem instance + * number for numbering our devices to avoid conflicts between subsystems that +--- a/drivers/nvme/host/nvme.h ++++ b/drivers/nvme/host/nvme.h +@@ -477,6 +477,9 @@ static inline bool nvme_ctrl_use_ana(str + return ctrl->ana_log_buf != NULL; + } + ++void nvme_mpath_unfreeze(struct nvme_subsystem *subsys); ++void nvme_mpath_wait_freeze(struct nvme_subsystem *subsys); ++void nvme_mpath_start_freeze(struct nvme_subsystem *subsys); + void nvme_set_disk_name(char *disk_name, struct nvme_ns *ns, + struct nvme_ctrl *ctrl, int *flags); + void nvme_failover_req(struct request *req); +@@ -552,6 +555,15 @@ static inline void nvme_mpath_uninit(str + static inline void nvme_mpath_stop(struct nvme_ctrl *ctrl) + { + } ++static inline void nvme_mpath_unfreeze(struct nvme_subsystem *subsys) ++{ ++} ++static inline void nvme_mpath_wait_freeze(struct nvme_subsystem *subsys) ++{ ++} ++static inline void nvme_mpath_start_freeze(struct nvme_subsystem *subsys) ++{ ++} + #endif /* CONFIG_NVME_MULTIPATH */ + + #ifdef CONFIG_NVM diff --git a/patches.suse/nvme-fix-controller-removal-race-with-scan-work.patch b/patches.suse/nvme-fix-controller-removal-race-with-scan-work.patch new file mode 100644 index 0000000..f780105 --- /dev/null +++ b/patches.suse/nvme-fix-controller-removal-race-with-scan-work.patch @@ -0,0 +1,209 @@ +From: Sagi Grimberg +Date: Thu, 25 Jul 2019 11:56:57 -0700 +Subject: nvme: fix controller removal race with scan work +Patch-mainline: v5.3-rc5 +Git-commit: 0157ec8dad3c8fc9bc9790f76e0831ffdaf2e7f0 +References: bsc#1158983 + +With multipath enabled, nvme_scan_work() can read from the device +(through nvme_mpath_add_disk()) and hang [1]. However, with fabrics, +once ctrl->state is set to NVME_CTRL_DELETING, the reads will hang +(see nvmf_check_ready()) and the mpath stack device make_request +will block if head->list is not empty. However, when the head->list +consistst of only DELETING/DEAD controllers, we should actually not +block, but rather fail immediately. + +In addition, before we go ahead and remove the namespaces, make sure +to clear the current path and kick the requeue list so that the +request will fast fail upon requeuing. + +[1]: +-- + INFO: task kworker/u4:3:166 blocked for more than 120 seconds. + Not tainted 5.2.0-rc6-vmlocalyes-00005-g808c8c2dc0cf #316 + "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message. + kworker/u4:3 D 0 166 2 0x80004000 + Workqueue: nvme-wq nvme_scan_work + Call Trace: + __schedule+0x851/0x1400 + schedule+0x99/0x210 + io_schedule+0x21/0x70 + do_read_cache_page+0xa57/0x1330 + read_cache_page+0x4a/0x70 + read_dev_sector+0xbf/0x380 + amiga_partition+0xc4/0x1230 + check_partition+0x30f/0x630 + rescan_partitions+0x19a/0x980 + __blkdev_get+0x85a/0x12f0 + blkdev_get+0x2a5/0x790 + __device_add_disk+0xe25/0x1250 + device_add_disk+0x13/0x20 + nvme_mpath_set_live+0x172/0x2b0 + nvme_update_ns_ana_state+0x130/0x180 + nvme_set_ns_ana_state+0x9a/0xb0 + nvme_parse_ana_log+0x1c3/0x4a0 + nvme_mpath_add_disk+0x157/0x290 + nvme_validate_ns+0x1017/0x1bd0 + nvme_scan_work+0x44d/0x6a0 + process_one_work+0x7d7/0x1240 + worker_thread+0x8e/0xff0 + kthread+0x2c3/0x3b0 + ret_from_fork+0x35/0x40 + + INFO: task kworker/u4:1:1034 blocked for more than 120 seconds. + Not tainted 5.2.0-rc6-vmlocalyes-00005-g808c8c2dc0cf #316 + "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message. + kworker/u4:1 D 0 1034 2 0x80004000 + Workqueue: nvme-delete-wq nvme_delete_ctrl_work + Call Trace: + __schedule+0x851/0x1400 + schedule+0x99/0x210 + schedule_timeout+0x390/0x830 + wait_for_completion+0x1a7/0x310 + __flush_work+0x241/0x5d0 + flush_work+0x10/0x20 + nvme_remove_namespaces+0x85/0x3d0 + nvme_do_delete_ctrl+0xb4/0x1e0 + nvme_delete_ctrl_work+0x15/0x20 + process_one_work+0x7d7/0x1240 + worker_thread+0x8e/0xff0 + kthread+0x2c3/0x3b0 + ret_from_fork+0x35/0x40 +-- + +Reported-by: Logan Gunthorpe +Tested-by: Logan Gunthorpe +Reviewed-by: Logan Gunthorpe +Reviewed-by: Ming Lei +Signed-off-by: Sagi Grimberg +Acked-by: Daniel Wagner +--- + drivers/nvme/host/core.c | 7 ++++++ + drivers/nvme/host/multipath.c | 46 ++++++++++++++++++++++++++++++++++++------ + drivers/nvme/host/nvme.h | 9 ++++++-- + 3 files changed, 54 insertions(+), 8 deletions(-) + +--- a/drivers/nvme/host/core.c ++++ b/drivers/nvme/host/core.c +@@ -3389,6 +3389,13 @@ void nvme_remove_namespaces(struct nvme_ + struct nvme_ns *ns, *next; + LIST_HEAD(ns_list); + ++ /* ++ * make sure to requeue I/O to all namespaces as these ++ * might result from the scan itself and must complete ++ * for the scan_work to make progress ++ */ ++ nvme_mpath_clear_ctrl_paths(ctrl); ++ + /* prevent racing with ns scanning */ + flush_work(&ctrl->scan_work); + +--- a/drivers/nvme/host/multipath.c ++++ b/drivers/nvme/host/multipath.c +@@ -142,18 +142,34 @@ static const char *nvme_ana_state_names[ + [NVME_ANA_CHANGE] = "change", + }; + +-void nvme_mpath_clear_current_path(struct nvme_ns *ns) ++bool nvme_mpath_clear_current_path(struct nvme_ns *ns) + { + struct nvme_ns_head *head = ns->head; ++ bool changed = false; + int node; + + if (!head) +- return; ++ goto out; + + for_each_node(node) { +- if (ns == rcu_access_pointer(head->current_path[node])) ++ if (ns == rcu_access_pointer(head->current_path[node])) { + rcu_assign_pointer(head->current_path[node], NULL); ++ changed = true; ++ } + } ++out: ++ return changed; ++} ++ ++void nvme_mpath_clear_ctrl_paths(struct nvme_ctrl *ctrl) ++{ ++ struct nvme_ns *ns; ++ ++ mutex_lock(&ctrl->scan_lock); ++ list_for_each_entry(ns, &ctrl->namespaces, list) ++ if (nvme_mpath_clear_current_path(ns)) ++ kblockd_schedule_work(&ns->head->requeue_work); ++ mutex_unlock(&ctrl->scan_lock); + } + + static bool nvme_path_is_disabled(struct nvme_ns *ns) +@@ -264,6 +280,24 @@ inline struct nvme_ns *nvme_find_path(st + return ns; + } + ++static bool nvme_available_path(struct nvme_ns_head *head) ++{ ++ struct nvme_ns *ns; ++ ++ list_for_each_entry_rcu(ns, &head->list, siblings) { ++ switch (ns->ctrl->state) { ++ case NVME_CTRL_LIVE: ++ case NVME_CTRL_RESETTING: ++ case NVME_CTRL_CONNECTING: ++ /* fallthru */ ++ return true; ++ default: ++ break; ++ } ++ } ++ return false; ++} ++ + static blk_qc_t nvme_ns_head_make_request(struct request_queue *q, + struct bio *bio) + { +@@ -290,14 +324,14 @@ static blk_qc_t nvme_ns_head_make_reques + disk_devt(ns->head->disk), + bio->bi_iter.bi_sector); + ret = direct_make_request(bio); +- } else if (!list_empty_careful(&head->list)) { +- dev_warn_ratelimited(dev, "no path available - requeuing I/O\n"); ++ } else if (nvme_available_path(head)) { ++ dev_warn_ratelimited(dev, "no usable path - requeuing I/O\n"); + + spin_lock_irq(&head->requeue_lock); + bio_list_add(&head->requeue_list, bio); + spin_unlock_irq(&head->requeue_lock); + } else { +- dev_warn_ratelimited(dev, "no path - failing I/O\n"); ++ dev_warn_ratelimited(dev, "no available path - failing I/O\n"); + + bio->bi_status = BLK_STS_IOERR; + bio_endio(bio); +--- a/drivers/nvme/host/nvme.h ++++ b/drivers/nvme/host/nvme.h +@@ -490,7 +490,8 @@ void nvme_mpath_remove_disk(struct nvme_ + int nvme_mpath_init(struct nvme_ctrl *ctrl, struct nvme_id_ctrl *id); + void nvme_mpath_uninit(struct nvme_ctrl *ctrl); + void nvme_mpath_stop(struct nvme_ctrl *ctrl); +-void nvme_mpath_clear_current_path(struct nvme_ns *ns); ++bool nvme_mpath_clear_current_path(struct nvme_ns *ns); ++void nvme_mpath_clear_ctrl_paths(struct nvme_ctrl *ctrl); + struct nvme_ns *nvme_find_path(struct nvme_ns_head *head); + + static inline void nvme_mpath_check_last_path(struct nvme_ns *ns) +@@ -538,7 +539,11 @@ static inline void nvme_mpath_add_disk(s + static inline void nvme_mpath_remove_disk(struct nvme_ns_head *head) + { + } +-static inline void nvme_mpath_clear_current_path(struct nvme_ns *ns) ++static inline bool nvme_mpath_clear_current_path(struct nvme_ns *ns) ++{ ++ return false; ++} ++static inline void nvme_mpath_clear_ctrl_paths(struct nvme_ctrl *ctrl) + { + } + static inline void nvme_mpath_check_last_path(struct nvme_ns *ns) diff --git a/patches.suse/nvme-multipath-also-check-for-a-disabled-path-if-the.patch b/patches.suse/nvme-multipath-also-check-for-a-disabled-path-if-the.patch new file mode 100644 index 0000000..7c58aa7 --- /dev/null +++ b/patches.suse/nvme-multipath-also-check-for-a-disabled-path-if-the.patch @@ -0,0 +1,33 @@ +From: Hannes Reinecke +Date: Thu, 4 Jul 2019 08:10:46 +0200 +Subject: nvme-multipath: also check for a disabled path if there is a single + sibling +Patch-mainline: v5.3-rc1 +Git-commit: 2032d074716a811440aa9cd2e971a0716646d6af +References: bsc#1158983 + +When we have a singular list in nvme_round_robin_path() we still +need to check its validity. + +Signed-off-by: Hannes Reinecke +Signed-off-by: Christoph Hellwig +Acked-by: Daniel Wagner +--- + drivers/nvme/host/multipath.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +--- a/drivers/nvme/host/multipath.c ++++ b/drivers/nvme/host/multipath.c +@@ -191,8 +191,11 @@ static struct nvme_ns *nvme_round_robin_ + { + struct nvme_ns *ns, *found, *fallback = NULL; + +- if (list_is_singular(&head->list)) ++ if (list_is_singular(&head->list)) { ++ if (nvme_path_is_disabled(old)) ++ return NULL; + return old; ++ } + + for (ns = nvme_next_ns(head, old); + ns != old; diff --git a/patches.suse/nvme-multipath-disable-native-NVMe-multipath-per-def.patch b/patches.suse/nvme-multipath-disable-native-NVMe-multipath-per-def.patch index fb32cac..6c3bf48 100644 --- a/patches.suse/nvme-multipath-disable-native-NVMe-multipath-per-def.patch +++ b/patches.suse/nvme-multipath-disable-native-NVMe-multipath-per-def.patch @@ -25,5 +25,5 @@ Signed-off-by: Hannes Reinecke - "turn on native support for multiple controllers per subsystem"); + "native support for multiple controllers per subsystem (default: off)"); - /* - * If multipathing is enabled we need to always use the subsystem instance + void nvme_mpath_unfreeze(struct nvme_subsystem *subsys) + { diff --git a/patches.suse/nvme-multipath-do-not-select-namespaces-which-are-ab.patch b/patches.suse/nvme-multipath-do-not-select-namespaces-which-are-ab.patch new file mode 100644 index 0000000..1a25b4e --- /dev/null +++ b/patches.suse/nvme-multipath-do-not-select-namespaces-which-are-ab.patch @@ -0,0 +1,32 @@ +From: Hannes Reinecke +Date: Thu, 4 Jul 2019 08:10:47 +0200 +Subject: nvme-multipath: do not select namespaces which are about to be + removed +Patch-mainline: v5.3-rc1 +Git-commit: 04e70bd4a0264a3d488a9eff6e116d7dc9a77967 +References: bsc#1158983 + +nvme_ns_remove() will first set the NVME_NS_REMOVING flag before removing +it from the list at the very last step. +So to avoid selecting a namespace in nvme_find_path() which is about to be +removed check the NVME_NS_REMOVING flag, too, when selecting a new path. + +Signed-off-by: Hannes Reinecke +Signed-off-by: Christoph Hellwig +Acked-by: Daniel Wagner +--- + drivers/nvme/host/multipath.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/drivers/nvme/host/multipath.c ++++ b/drivers/nvme/host/multipath.c +@@ -134,7 +134,8 @@ void nvme_mpath_clear_current_path(struc + static bool nvme_path_is_disabled(struct nvme_ns *ns) + { + return ns->ctrl->state != NVME_CTRL_LIVE || +- test_bit(NVME_NS_ANA_PENDING, &ns->flags); ++ test_bit(NVME_NS_ANA_PENDING, &ns->flags) || ++ test_bit(NVME_NS_REMOVING, &ns->flags); + } + + static struct nvme_ns *__nvme_find_path(struct nvme_ns_head *head, int node) diff --git a/patches.suse/nvme-multipath-factor-out-a-nvme_path_is_disabled-he.patch b/patches.suse/nvme-multipath-factor-out-a-nvme_path_is_disabled-he.patch new file mode 100644 index 0000000..539454f --- /dev/null +++ b/patches.suse/nvme-multipath-factor-out-a-nvme_path_is_disabled-he.patch @@ -0,0 +1,52 @@ +From: Hannes Reinecke +Date: Thu, 4 Jul 2019 08:10:46 +0200 +Subject: nvme-multipath: factor out a nvme_path_is_disabled helper +Patch-mainline: v5.3-rc1 +Git-commit: ca7ae5c966bd4c00626d6ba05d68219f3c1fba36 +References: bsc#1158983 + +Factor our a common helper to check if a path has been disabled +by something other than the per-namespace ANA state. + +Signed-off-by: Hannes Reinecke +[hch: split from a bigger patch] +Signed-off-by: Christoph Hellwig +Acked-by: Daniel Wagner +--- + drivers/nvme/host/multipath.c | 12 ++++++++---- + 1 file changed, 8 insertions(+), 4 deletions(-) + +--- a/drivers/nvme/host/multipath.c ++++ b/drivers/nvme/host/multipath.c +@@ -131,14 +131,19 @@ void nvme_mpath_clear_current_path(struc + } + } + ++static bool nvme_path_is_disabled(struct nvme_ns *ns) ++{ ++ return ns->ctrl->state != NVME_CTRL_LIVE || ++ test_bit(NVME_NS_ANA_PENDING, &ns->flags); ++} ++ + static struct nvme_ns *__nvme_find_path(struct nvme_ns_head *head, int node) + { + int found_distance = INT_MAX, fallback_distance = INT_MAX, distance; + struct nvme_ns *found = NULL, *fallback = NULL, *ns; + + list_for_each_entry_rcu(ns, &head->list, siblings) { +- if (ns->ctrl->state != NVME_CTRL_LIVE || +- test_bit(NVME_NS_ANA_PENDING, &ns->flags)) ++ if (nvme_path_is_disabled(ns)) + continue; + + if (READ_ONCE(head->subsys->iopolicy) == NVME_IOPOLICY_NUMA) +@@ -192,8 +197,7 @@ static struct nvme_ns *nvme_round_robin_ + for (ns = nvme_next_ns(head, old); + ns != old; + ns = nvme_next_ns(head, ns)) { +- if (ns->ctrl->state != NVME_CTRL_LIVE || +- test_bit(NVME_NS_ANA_PENDING, &ns->flags)) ++ if (nvme_path_is_disabled(ns)) + continue; + + if (ns->ana_state == NVME_ANA_OPTIMIZED) { diff --git a/patches.suse/nvme-multipath-fix-crash-in-nvme_mpath_clear_ctrl_pa.patch b/patches.suse/nvme-multipath-fix-crash-in-nvme_mpath_clear_ctrl_pa.patch new file mode 100644 index 0000000..89b6de6 --- /dev/null +++ b/patches.suse/nvme-multipath-fix-crash-in-nvme_mpath_clear_ctrl_pa.patch @@ -0,0 +1,74 @@ +From: Anton Eidelman +Date: Fri, 1 Nov 2019 17:27:55 -0700 +Subject: nvme-multipath: fix crash in nvme_mpath_clear_ctrl_paths +Patch-mainline: v5.4-rc7 +Git-commit: 763303a83a095a88c3a8a0d1abf97165db2e8bf5 +References: bsc#1158983 + +nvme_mpath_clear_ctrl_paths() iterates through +the ctrl->namespaces list while holding ctrl->scan_lock. +This does not seem to be the correct way of protecting +from concurrent list modification. + +Specifically, nvme_scan_work() sorts ctrl->namespaces +AFTER unlocking scan_lock. + +This may result in the following (rare) crash in ctrl disconnect +during scan_work: + + BUG: kernel NULL pointer dereference, address: 0000000000000050 + Oops: 0000 [#1] SMP PTI + CPU: 0 PID: 3995 Comm: nvme 5.3.5-050305-generic + RIP: 0010:nvme_mpath_clear_current_path+0xe/0x90 [nvme_core] + ... + Call Trace: + nvme_mpath_clear_ctrl_paths+0x3c/0x70 [nvme_core] + nvme_remove_namespaces+0x35/0xe0 [nvme_core] + nvme_do_delete_ctrl+0x47/0x90 [nvme_core] + nvme_sysfs_delete+0x49/0x60 [nvme_core] + dev_attr_store+0x17/0x30 + sysfs_kf_write+0x3e/0x50 + kernfs_fop_write+0x11e/0x1a0 + __vfs_write+0x1b/0x40 + vfs_write+0xb9/0x1a0 + ksys_write+0x67/0xe0 + __x64_sys_write+0x1a/0x20 + do_syscall_64+0x5a/0x130 + entry_SYSCALL_64_after_hwframe+0x44/0xa9 + RIP: 0033:0x7f8d02bfb154 + +Fix: +After taking scan_lock in nvme_mpath_clear_ctrl_paths() +down_read(&ctrl->namespaces_rwsem) as well to make list traversal safe. +This will not cause deadlocks because taking scan_lock never happens +while holding the namespaces_rwsem. +Moreover, scan work downs namespaces_rwsem in the same order. + +Alternative: sort ctrl->namespaces in nvme_scan_work() +while still holding the scan_lock. +This would leave nvme_mpath_clear_ctrl_paths() without correct protection +against ctrl->namespaces modification by anyone other than scan_work. + +Reviewed-by: Sagi Grimberg +Reviewed-by: Christoph Hellwig +Signed-off-by: Anton Eidelman +Signed-off-by: Keith Busch +Acked-by: Daniel Wagner +--- + drivers/nvme/host/multipath.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/drivers/nvme/host/multipath.c ++++ b/drivers/nvme/host/multipath.c +@@ -166,9 +166,11 @@ void nvme_mpath_clear_ctrl_paths(struct + struct nvme_ns *ns; + + mutex_lock(&ctrl->scan_lock); ++ down_read(&ctrl->namespaces_rwsem); + list_for_each_entry(ns, &ctrl->namespaces, list) + if (nvme_mpath_clear_current_path(ns)) + kblockd_schedule_work(&ns->head->requeue_work); ++ up_read(&ctrl->namespaces_rwsem); + mutex_unlock(&ctrl->scan_lock); + } + diff --git a/patches.suse/nvme-multipath-fix-possible-I-O-hang-when-paths-are-.patch b/patches.suse/nvme-multipath-fix-possible-I-O-hang-when-paths-are-.patch new file mode 100644 index 0000000..578c893 --- /dev/null +++ b/patches.suse/nvme-multipath-fix-possible-I-O-hang-when-paths-are-.patch @@ -0,0 +1,45 @@ +From: Anton Eidelman +Date: Mon, 12 Aug 2019 23:00:36 +0300 +Subject: nvme-multipath: fix possible I/O hang when paths are updated +Patch-mainline: v5.3-rc6 +Git-commit: 504db087aaccdb32af61539916409f7dca31ceb5 +References: bsc#1158983 + +nvme_state_set_live() making a path available triggers requeue_work +in order to resubmit requests that ended up on requeue_list when no +paths were available. + +This requeue_work may race with concurrent nvme_ns_head_make_request() +that do not observe the live path yet. +Such concurrent requests may by made by either: +- New IO submission. +- Requeue_work triggered by nvme_failover_req() or another ana_work. + +A race may cause requeue_work capture the state of requeue_list before +more requests get onto the list. These requests will stay on the list +forever unless requeue_work is triggered again. + +In order to prevent such race, nvme_state_set_live() should +synchronize_srcu(&head->srcu) before triggering the requeue_work and +prevent nvme_ns_head_make_request referencing an old snapshot of the +path list. + +Reviewed-by: Christoph Hellwig +Signed-off-by: Anton Eidelman +Signed-off-by: Sagi Grimberg +Signed-off-by: Jens Axboe +Acked-by: Daniel Wagner +--- + drivers/nvme/host/multipath.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/nvme/host/multipath.c ++++ b/drivers/nvme/host/multipath.c +@@ -303,6 +303,7 @@ static void nvme_mpath_set_live(struct n + srcu_read_unlock(&head->srcu, srcu_idx); + } + ++ synchronize_srcu(&ns->head->srcu); + kblockd_schedule_work(&ns->head->requeue_work); + } + diff --git a/patches.suse/nvme-multipath-fix-possible-io-hang-after-ctrl-recon.patch b/patches.suse/nvme-multipath-fix-possible-io-hang-after-ctrl-recon.patch new file mode 100644 index 0000000..7eb20b2 --- /dev/null +++ b/patches.suse/nvme-multipath-fix-possible-io-hang-after-ctrl-recon.patch @@ -0,0 +1,58 @@ +From: Anton Eidelman +Date: Fri, 18 Oct 2019 11:32:50 -0700 +Subject: nvme-multipath: fix possible io hang after ctrl reconnect +Patch-mainline: v5.4-rc6 +Git-commit: af8fd0424713a2adb812d10d55e86718152cf656 +References: bsc#1158983 + +The following scenario results in an IO hang: +1) ctrl completes a request with NVME_SC_ANA_TRANSITION. + NVME_NS_ANA_PENDING bit in ns->flags is set and ana_work is triggered. +2) ana_work: nvme_read_ana_log() tries to get the ANA log page from the ctrl. + This fails because ctrl disconnects. + Therefore nvme_update_ns_ana_state() is not called + and NVME_NS_ANA_PENDING bit in ns->flags is not cleared. +3) ctrl reconnects: nvme_mpath_init(ctrl,...) calls + nvme_read_ana_log(ctrl, groups_only=true). + However, nvme_update_ana_state() does not update namespaces + because nr_nsids = 0 (due to groups_only mode). +4) scan_work calls nvme_validate_ns() finds the ns and re-validates OK. + +Result: +The ctrl is now live but NVME_NS_ANA_PENDING bit in ns->flags is still set. +Consequently ctrl will never be considered a viable path by __nvme_find_path(). +IO will hang if ctrl is the only or the last path to the namespace. + +More generally, while ctrl is reconnecting, its ANA state may change. +And because nvme_mpath_init() requests ANA log in groups_only mode, +these changes are not propagated to the existing ctrl namespaces. +This may result in a mal-function or an IO hang. + +Solution: +nvme_mpath_init() will nvme_read_ana_log() with groups_only set to false. +This will not harm the new ctrl case (no namespaces present), +and will make sure the ANA state of namespaces gets updated after reconnect. + +Note: Another option would be for nvme_mpath_init() to invoke +nvme_parse_ana_log(..., nvme_set_ns_ana_state) for each existing namespace. + +Reviewed-by: Sagi Grimberg +Signed-off-by: Anton Eidelman +Signed-off-by: Keith Busch +Signed-off-by: Jens Axboe +Acked-by: Daniel Wagner +--- + drivers/nvme/host/multipath.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/nvme/host/multipath.c ++++ b/drivers/nvme/host/multipath.c +@@ -739,7 +739,7 @@ int nvme_mpath_init(struct nvme_ctrl *ct + goto out; + } + +- error = nvme_read_ana_log(ctrl, true); ++ error = nvme_read_ana_log(ctrl, false); + if (error) + goto out_free_ana_log_buf; + return 0; diff --git a/patches.suse/nvme-multipath-remove-unused-groups_only-mode-in-ana.patch b/patches.suse/nvme-multipath-remove-unused-groups_only-mode-in-ana.patch new file mode 100644 index 0000000..e9743cd --- /dev/null +++ b/patches.suse/nvme-multipath-remove-unused-groups_only-mode-in-ana.patch @@ -0,0 +1,55 @@ +From: Anton Eidelman +Date: Fri, 18 Oct 2019 11:32:51 -0700 +Subject: nvme-multipath: remove unused groups_only mode in ana log +Patch-mainline: v5.4-rc6 +Git-commit: 86cccfbf773fafb88898c5627aa3727b02bc4708 +References: bsc#1158983 + +groups_only mode in nvme_read_ana_log() is no longer used: remove it. + +Reviewed-by: Sagi Grimberg +Signed-off-by: Anton Eidelman +Signed-off-by: Keith Busch +Signed-off-by: Jens Axboe +Acked-by: Daniel Wagner +--- + drivers/nvme/host/multipath.c | 9 ++++----- + 1 file changed, 4 insertions(+), 5 deletions(-) + +--- a/drivers/nvme/host/multipath.c ++++ b/drivers/nvme/host/multipath.c +@@ -546,14 +546,13 @@ static int nvme_update_ana_state(struct + return 0; + } + +-static int nvme_read_ana_log(struct nvme_ctrl *ctrl, bool groups_only) ++static int nvme_read_ana_log(struct nvme_ctrl *ctrl) + { + u32 nr_change_groups = 0; + int error; + + mutex_lock(&ctrl->ana_lock); +- error = nvme_get_log(ctrl, NVME_NSID_ALL, NVME_LOG_ANA, +- groups_only ? NVME_ANA_LOG_RGO : 0, ++ error = nvme_get_log(ctrl, NVME_NSID_ALL, NVME_LOG_ANA, 0, + ctrl->ana_log_buf, ctrl->ana_log_size, 0); + if (error) { + dev_warn(ctrl->device, "Failed to get ANA log: %d\n", error); +@@ -589,7 +588,7 @@ static void nvme_ana_work(struct work_st + { + struct nvme_ctrl *ctrl = container_of(work, struct nvme_ctrl, ana_work); + +- nvme_read_ana_log(ctrl, false); ++ nvme_read_ana_log(ctrl); + } + + static void nvme_anatt_timeout(struct timer_list *t) +@@ -739,7 +738,7 @@ int nvme_mpath_init(struct nvme_ctrl *ct + goto out; + } + +- error = nvme_read_ana_log(ctrl, false); ++ error = nvme_read_ana_log(ctrl); + if (error) + goto out_free_ana_log_buf; + return 0; diff --git a/patches.suse/nvme-multipath-round-robin-I-O-policy.patch b/patches.suse/nvme-multipath-round-robin-I-O-policy.patch index 8d32b16..015700a 100644 --- a/patches.suse/nvme-multipath-round-robin-I-O-policy.patch +++ b/patches.suse/nvme-multipath-round-robin-I-O-policy.patch @@ -1,30 +1,30 @@ From: Hannes Reinecke -Date: Thu, 15 Nov 2018 12:31:17 +0100 -Subject: [PATCH] nvme-multipath: round-robin I/O policy -References: bsc#1110705 -Patch-Mainline: submitted linux-nvme 2019/01/25 +Date: Mon, 18 Feb 2019 11:43:26 +0100 +Subject: nvme-multipath: round-robin I/O policy +Patch-mainline: v5.1-rc1 +Git-commit: 75c10e73272484bc3a940a9c8e4ec39a7a1b8c21 +References: bsc#1158983 -Implement a simple round-robin I/O policy for multipathing. -Path selection is done in two rounds, first iterating across all -optimized paths, and, if that doesn't return any valid paths, -iterate over all optimized and non-optimized paths. -If no paths are found we're using the existing algorithm. -This patch also implements a sysfs attribute 'iopolicy' to switch -between the current, NUMA-aware I/O policy and the 'round-robin' -I/O policy. +Implement a simple round-robin I/O policy for multipathing. Path +selection is done in two rounds, first iterating across all optimized +paths, and if that doesn't return any valid paths, iterate over all +optimized and non-optimized paths. If no paths are found, use the +existing algorithm. Also add a sysfs attribute 'iopolicy' to switch +between the current NUMA-aware I/O policy and the 'round-robin' I/O +policy. Signed-off-by: Hannes Reinecke +Signed-off-by: Christoph Hellwig +Acked-by: Daniel Wagner --- - drivers/nvme/host/core.c | 6 +++ - drivers/nvme/host/multipath.c | 102 +++++++++++++++++++++++++++++++++++++++++- - drivers/nvme/host/nvme.h | 12 +++++ - 3 files changed, 119 insertions(+), 1 deletion(-) + drivers/nvme/host/core.c | 6 ++ + drivers/nvme/host/multipath.c | 86 +++++++++++++++++++++++++++++++++++++++++- + drivers/nvme/host/nvme.h | 9 ++++ + 3 files changed, 100 insertions(+), 1 deletion(-) -diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c -index 6b2617e213cc..7f595086f6c6 100644 --- a/drivers/nvme/host/core.c +++ b/drivers/nvme/host/core.c -@@ -2232,6 +2232,9 @@ static struct attribute *nvme_subsys_attrs[] = { +@@ -2237,6 +2237,9 @@ static struct attribute *nvme_subsys_att &subsys_attr_serial.attr, &subsys_attr_firmware_rev.attr, &subsys_attr_subsysnqn.attr, @@ -34,7 +34,7 @@ index 6b2617e213cc..7f595086f6c6 100644 NULL, }; -@@ -2284,6 +2287,9 @@ static int nvme_init_subsystem(struct nvme_ctrl *ctrl, struct nvme_id_ctrl *id) +@@ -2289,6 +2292,9 @@ static int nvme_init_subsystem(struct nv memcpy(subsys->firmware_rev, id->fr, sizeof(subsys->firmware_rev)); subsys->vendor_id = le16_to_cpu(id->vid); subsys->cmic = id->cmic; @@ -44,11 +44,9 @@ index 6b2617e213cc..7f595086f6c6 100644 subsys->dev.class = nvme_subsys_class; subsys->dev.release = nvme_release_subsystem; -diff --git a/drivers/nvme/host/multipath.c b/drivers/nvme/host/multipath.c -index 8b58a6ca5bf4..6122ff5aa438 100644 --- a/drivers/nvme/host/multipath.c +++ b/drivers/nvme/host/multipath.c -@@ -141,7 +141,10 @@ static struct nvme_ns *__nvme_find_path(struct nvme_ns_head *head, int node) +@@ -141,7 +141,10 @@ static struct nvme_ns *__nvme_find_path( test_bit(NVME_NS_ANA_PENDING, &ns->flags)) continue; @@ -60,73 +58,64 @@ index 8b58a6ca5bf4..6122ff5aa438 100644 switch (ns->ana_state) { case NVME_ANA_OPTIMIZED: -@@ -168,6 +171,56 @@ static struct nvme_ns *__nvme_find_path(struct nvme_ns_head *head, int node) +@@ -168,6 +171,47 @@ static struct nvme_ns *__nvme_find_path( return found; } -+static struct nvme_ns *__nvme_rr_next_path(struct nvme_ns_head *head, int node, -+ struct nvme_ns *old) ++static struct nvme_ns *nvme_next_ns(struct nvme_ns_head *head, ++ struct nvme_ns *ns) +{ -+ struct nvme_ns *ns, *found = NULL; -+ bool try_nonoptimized = false; ++ ns = list_next_or_null_rcu(&head->list, &ns->siblings, struct nvme_ns, ++ siblings); ++ if (ns) ++ return ns; ++ return list_first_or_null_rcu(&head->list, struct nvme_ns, siblings); ++} + -+ if (!old) -+ return NULL; -+retry: -+ ns = old; -+ do { -+ ns = list_next_or_null_rcu(&head->list, &ns->siblings, -+ struct nvme_ns, siblings); -+ if (!ns) { -+ ns = list_first_or_null_rcu(&head->list, struct nvme_ns, -+ siblings); -+ if (!ns) -+ return NULL; ++static struct nvme_ns *nvme_round_robin_path(struct nvme_ns_head *head, ++ int node, struct nvme_ns *old) ++{ ++ struct nvme_ns *ns, *found, *fallback = NULL; + -+ if (ns == old) -+ /* -+ * The list consists of just one entry. -+ * Sorry for the noise :-) -+ */ -+ return old; -+ } -+ if (!ns->disk || ns->ctrl->state != NVME_CTRL_LIVE || ++ if (list_is_singular(&head->list)) ++ return old; ++ ++ for (ns = nvme_next_ns(head, old); ++ ns != old; ++ ns = nvme_next_ns(head, ns)) { ++ if (ns->ctrl->state != NVME_CTRL_LIVE || + test_bit(NVME_NS_ANA_PENDING, &ns->flags)) + continue; + + if (ns->ana_state == NVME_ANA_OPTIMIZED) { + found = ns; -+ break; -+ } -+ if (try_nonoptimized && -+ ns->ana_state == NVME_ANA_NONOPTIMIZED) { -+ found = ns; -+ break; ++ goto out; + } -+ } while (ns != old); -+ -+ if (found) -+ rcu_assign_pointer(head->current_path[node], found); -+ else if (!try_nonoptimized) { -+ try_nonoptimized = true; -+ goto retry; ++ if (ns->ana_state == NVME_ANA_NONOPTIMIZED) ++ fallback = ns; + } ++ ++ if (!fallback) ++ return NULL; ++ found = fallback; ++out: ++ rcu_assign_pointer(head->current_path[node], found); + return found; +} + static inline bool nvme_path_is_optimized(struct nvme_ns *ns) { return ns->ctrl->state == NVME_CTRL_LIVE && -@@ -180,6 +233,8 @@ inline struct nvme_ns *nvme_find_path(struct nvme_ns_head *head) +@@ -180,6 +224,8 @@ inline struct nvme_ns *nvme_find_path(st struct nvme_ns *ns; ns = srcu_dereference(head->current_path[node], &head->srcu); -+ if (READ_ONCE(head->subsys->iopolicy) == NVME_IOPOLICY_RR) -+ ns = __nvme_rr_next_path(head, node, ns); ++ if (READ_ONCE(head->subsys->iopolicy) == NVME_IOPOLICY_RR && ns) ++ ns = nvme_round_robin_path(head, node, ns); if (unlikely(!ns || !nvme_path_is_optimized(ns))) ns = __nvme_find_path(head, node); return ns; -@@ -487,6 +542,51 @@ void nvme_mpath_stop(struct nvme_ctrl *ctrl) +@@ -487,6 +533,44 @@ void nvme_mpath_stop(struct nvme_ctrl *c cancel_work_sync(&ctrl->ana_work); } @@ -135,9 +124,8 @@ index 8b58a6ca5bf4..6122ff5aa438 100644 + __ATTR(_name, _mode, _show, _store) + +static const char *nvme_iopolicy_names[] = { -+ [NVME_IOPOLICY_UNKNOWN] = "unknown", -+ [NVME_IOPOLICY_NUMA] = "numa", -+ [NVME_IOPOLICY_RR] = "round-robin", ++ [NVME_IOPOLICY_NUMA] = "numa", ++ [NVME_IOPOLICY_RR] = "round-robin", +}; + +static ssize_t nvme_subsys_iopolicy_show(struct device *dev, @@ -145,32 +133,26 @@ index 8b58a6ca5bf4..6122ff5aa438 100644 +{ + struct nvme_subsystem *subsys = + container_of(dev, struct nvme_subsystem, dev); -+ int iopolicy = NVME_IOPOLICY_UNKNOWN; + -+ if (iopolicy < ARRAY_SIZE(nvme_iopolicy_names)) -+ iopolicy = READ_ONCE(subsys->iopolicy); -+ return sprintf(buf, "%s\n", nvme_iopolicy_names[iopolicy]); ++ return sprintf(buf, "%s\n", ++ nvme_iopolicy_names[READ_ONCE(subsys->iopolicy)]); +} + +static ssize_t nvme_subsys_iopolicy_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ -+ enum nvme_iopolicy iopolicy = NVME_IOPOLICY_UNKNOWN; + struct nvme_subsystem *subsys = + container_of(dev, struct nvme_subsystem, dev); ++ int i; + -+ if (!strncmp(buf, nvme_iopolicy_names[NVME_IOPOLICY_NUMA], -+ strlen(nvme_iopolicy_names[NVME_IOPOLICY_NUMA]))) -+ iopolicy = NVME_IOPOLICY_NUMA; -+ else if (!strncmp(buf, nvme_iopolicy_names[NVME_IOPOLICY_RR], -+ strlen(nvme_iopolicy_names[NVME_IOPOLICY_RR]))) -+ iopolicy = NVME_IOPOLICY_RR; -+ -+ if (iopolicy == NVME_IOPOLICY_UNKNOWN) -+ return -EINVAL; ++ for (i = 0; i < ARRAY_SIZE(nvme_iopolicy_names); i++) { ++ if (sysfs_streq(buf, nvme_iopolicy_names[i])) { ++ WRITE_ONCE(subsys->iopolicy, i); ++ return count; ++ } ++ } + -+ WRITE_ONCE(subsys->iopolicy, iopolicy); -+ return count; ++ return -EINVAL; +} +SUBSYS_ATTR_RW(iopolicy, S_IRUGO | S_IWUSR, + nvme_subsys_iopolicy_show, nvme_subsys_iopolicy_store); @@ -178,26 +160,21 @@ index 8b58a6ca5bf4..6122ff5aa438 100644 static ssize_t ana_grpid_show(struct device *dev, struct device_attribute *attr, char *buf) { -diff --git a/drivers/nvme/host/nvme.h b/drivers/nvme/host/nvme.h -index b84be08bbbe0..7967837b6a8c 100644 --- a/drivers/nvme/host/nvme.h +++ b/drivers/nvme/host/nvme.h -@@ -243,6 +243,14 @@ struct nvme_ctrl { +@@ -249,6 +249,11 @@ struct nvme_ctrl { struct nvmf_ctrl_options *opts; }; -+#ifdef CONFIG_NVME_MULTIPATH +enum nvme_iopolicy { -+ NVME_IOPOLICY_UNKNOWN, + NVME_IOPOLICY_NUMA, + NVME_IOPOLICY_RR, +}; -+#endif + struct nvme_subsystem { int instance; struct device dev; -@@ -262,6 +270,9 @@ struct nvme_subsystem { +@@ -268,6 +273,9 @@ struct nvme_subsystem { u8 cmic; u16 vendor_id; struct ida ns_ida; @@ -207,7 +184,7 @@ index b84be08bbbe0..7967837b6a8c 100644 }; /* -@@ -482,6 +493,7 @@ static inline void nvme_mpath_check_last_path(struct nvme_ns *ns) +@@ -488,6 +496,7 @@ static inline void nvme_mpath_check_last extern struct device_attribute dev_attr_ana_grpid; extern struct device_attribute dev_attr_ana_state; @@ -215,6 +192,3 @@ index b84be08bbbe0..7967837b6a8c 100644 #else static inline bool nvme_ctrl_use_ana(struct nvme_ctrl *ctrl) --- -2.16.4 - diff --git a/patches.suse/nvme-resync-include-linux-nvme.h-with-nvmecli.patch b/patches.suse/nvme-resync-include-linux-nvme.h-with-nvmecli.patch new file mode 100644 index 0000000..8a1b436 --- /dev/null +++ b/patches.suse/nvme-resync-include-linux-nvme.h-with-nvmecli.patch @@ -0,0 +1,172 @@ +From: Revanth Rajashekar +Date: Mon, 14 Oct 2019 11:16:07 -0600 +Subject: [PATCH] nvme: resync include/linux/nvme.h with nvmecli +Patch-Mainline: v5.5-rc1 +Git-commit: 48c9e85b23464a7d1e3ebd70b79cc3a2d97d3222 +References: bsc#1156510 + +Update enumerations and structures in include/linux/nvme.h +to resync with the nvmecli. + +All the updates are mentioned in the ratified NVMe 1.4 spec +https://nvmexpress.org/wp-content/uploads/NVM-Express-1_4-2019.06.10-Ratified.pdf + +Reviewed-by: Christoph Hellwig +Signed-off-by: Revanth Rajashekar +Signed-off-by: Keith Busch +Signed-off-by: Jens Axboe +Acked-by: Hannes Reinecke +--- + include/linux/nvme.h | 53 +++++++++++++++++++++++++++++++++++++++++++++++++--- + 1 file changed, 50 insertions(+), 3 deletions(-) + +diff --git a/include/linux/nvme.h b/include/linux/nvme.h +index a260cd754f28..3eca4f7d8510 100644 +--- a/include/linux/nvme.h ++++ b/include/linux/nvme.h +@@ -107,8 +107,22 @@ enum { + NVME_REG_AQA = 0x0024, /* Admin Queue Attributes */ + NVME_REG_ASQ = 0x0028, /* Admin SQ Base Address */ + NVME_REG_ACQ = 0x0030, /* Admin CQ Base Address */ +- NVME_REG_CMBLOC = 0x0038, /* Controller Memory Buffer Location */ ++ NVME_REG_CMBLOC = 0x0038, /* Controller Memory Buffer Location */ + NVME_REG_CMBSZ = 0x003c, /* Controller Memory Buffer Size */ ++ NVME_REG_BPINFO = 0x0040, /* Boot Partition Information */ ++ NVME_REG_BPRSEL = 0x0044, /* Boot Partition Read Select */ ++ NVME_REG_BPMBL = 0x0048, /* Boot Partition Memory Buffer ++ * Location ++ */ ++ NVME_REG_PMRCAP = 0x0e00, /* Persistent Memory Capabilities */ ++ NVME_REG_PMRCTL = 0x0e04, /* Persistent Memory Region Control */ ++ NVME_REG_PMRSTS = 0x0e08, /* Persistent Memory Region Status */ ++ NVME_REG_PMREBS = 0x0e0c, /* Persistent Memory Region Elasticity ++ * Buffer Size ++ */ ++ NVME_REG_PMRSWTP = 0x0e10, /* Persistent Memory Region Sustained ++ * Write Throughput ++ */ + NVME_REG_DBS = 0x1000, /* SQ 0 Tail Doorbell */ + }; + +@@ -295,6 +309,14 @@ enum { + NVME_CTRL_OACS_DIRECTIVES = 1 << 5, + NVME_CTRL_OACS_DBBUF_SUPP = 1 << 8, + NVME_CTRL_LPA_CMD_EFFECTS_LOG = 1 << 1, ++ NVME_CTRL_CTRATT_128_ID = 1 << 0, ++ NVME_CTRL_CTRATT_NON_OP_PSP = 1 << 1, ++ NVME_CTRL_CTRATT_NVM_SETS = 1 << 2, ++ NVME_CTRL_CTRATT_READ_RECV_LVLS = 1 << 3, ++ NVME_CTRL_CTRATT_ENDURANCE_GROUPS = 1 << 4, ++ NVME_CTRL_CTRATT_PREDICTABLE_LAT = 1 << 5, ++ NVME_CTRL_CTRATT_NAMESPACE_GRANULARITY = 1 << 7, ++ NVME_CTRL_CTRATT_UUID_LIST = 1 << 9, + }; + + struct nvme_lbaf { +@@ -352,6 +374,9 @@ enum { + NVME_ID_CNS_NS_PRESENT = 0x11, + NVME_ID_CNS_CTRL_NS_LIST = 0x12, + NVME_ID_CNS_CTRL_LIST = 0x13, ++ NVME_ID_CNS_SCNDRY_CTRL_LIST = 0x15, ++ NVME_ID_CNS_NS_GRANULARITY = 0x16, ++ NVME_ID_CNS_UUID_LIST = 0x17, + }; + + enum { +@@ -409,7 +434,8 @@ struct nvme_smart_log { + __u8 avail_spare; + __u8 spare_thresh; + __u8 percent_used; +- __u8 rsvd6[26]; ++ __u8 endu_grp_crit_warn_sumry; ++ __u8 rsvd7[25]; + __u8 data_units_read[16]; + __u8 data_units_written[16]; + __u8 host_reads[16]; +@@ -423,7 +449,11 @@ struct nvme_smart_log { + __le32 warning_temp_time; + __le32 critical_comp_time; + __le16 temp_sensor[8]; +- __u8 rsvd216[296]; ++ __le32 thm_temp1_trans_count; ++ __le32 thm_temp2_trans_count; ++ __le32 thm_temp1_total_time; ++ __le32 thm_temp2_total_time; ++ __u8 rsvd232[280]; + }; + + struct nvme_fw_slot_info_log { +@@ -440,6 +470,7 @@ enum { + NVME_CMD_EFFECTS_NIC = 1 << 3, + NVME_CMD_EFFECTS_CCC = 1 << 4, + NVME_CMD_EFFECTS_CSE_MASK = 3 << 16, ++ NVME_CMD_EFFECTS_UUID_SEL = 1 << 19, + }; + + struct nvme_effects_log { +@@ -563,6 +594,7 @@ enum nvme_opcode { + nvme_cmd_compare = 0x05, + nvme_cmd_write_zeroes = 0x08, + nvme_cmd_dsm = 0x09, ++ nvme_cmd_verify = 0x0c, + nvme_cmd_resv_register = 0x0d, + nvme_cmd_resv_report = 0x0e, + nvme_cmd_resv_acquire = 0x11, +@@ -806,10 +838,14 @@ enum nvme_admin_opcode { + nvme_admin_ns_mgmt = 0x0d, + nvme_admin_activate_fw = 0x10, + nvme_admin_download_fw = 0x11, ++ nvme_admin_dev_self_test = 0x14, + nvme_admin_ns_attach = 0x15, + nvme_admin_keep_alive = 0x18, + nvme_admin_directive_send = 0x19, + nvme_admin_directive_recv = 0x1a, ++ nvme_admin_virtual_mgmt = 0x1c, ++ nvme_admin_nvme_mi_send = 0x1d, ++ nvme_admin_nvme_mi_recv = 0x1e, + nvme_admin_dbbuf = 0x7C, + nvme_admin_format_nvm = 0x80, + nvme_admin_security_send = 0x81, +@@ -873,6 +909,7 @@ enum { + NVME_FEAT_PLM_CONFIG = 0x13, + NVME_FEAT_PLM_WINDOW = 0x14, + NVME_FEAT_HOST_BEHAVIOR = 0x16, ++ NVME_FEAT_SANITIZE = 0x17, + NVME_FEAT_SW_PROGRESS = 0x80, + NVME_FEAT_HOST_ID = 0x81, + NVME_FEAT_RESV_MASK = 0x82, +@@ -883,6 +920,10 @@ enum { + NVME_LOG_FW_SLOT = 0x03, + NVME_LOG_CHANGED_NS = 0x04, + NVME_LOG_CMD_EFFECTS = 0x05, ++ NVME_LOG_DEVICE_SELF_TEST = 0x06, ++ NVME_LOG_TELEMETRY_HOST = 0x07, ++ NVME_LOG_TELEMETRY_CTRL = 0x08, ++ NVME_LOG_ENDURANCE_GROUP = 0x09, + NVME_LOG_ANA = 0x0c, + NVME_LOG_DISC = 0x70, + NVME_LOG_RESERVATION = 0x80, +@@ -1290,7 +1331,11 @@ enum { + NVME_SC_SGL_INVALID_OFFSET = 0x16, + NVME_SC_SGL_INVALID_SUBTYPE = 0x17, + ++ NVME_SC_SANITIZE_FAILED = 0x1C, ++ NVME_SC_SANITIZE_IN_PROGRESS = 0x1D, ++ + NVME_SC_NS_WRITE_PROTECTED = 0x20, ++ NVME_SC_CMD_INTERRUPTED = 0x21, + + NVME_SC_LBA_RANGE = 0x80, + NVME_SC_CAP_EXCEEDED = 0x81, +@@ -1328,6 +1373,8 @@ enum { + NVME_SC_NS_NOT_ATTACHED = 0x11a, + NVME_SC_THIN_PROV_NOT_SUPP = 0x11b, + NVME_SC_CTRL_LIST_INVALID = 0x11c, ++ NVME_SC_BP_WRITE_PROHIBITED = 0x11e, ++ NVME_SC_PMR_SAN_PROHIBITED = 0x123, + + /* + * I/O Command Set Specific - NVM commands: +-- +2.16.4 + diff --git a/patches.suse/orinoco-avoid-assertion-in-case-of-NULL-pointer.patch b/patches.suse/orinoco-avoid-assertion-in-case-of-NULL-pointer.patch new file mode 100644 index 0000000..d8b6adc --- /dev/null +++ b/patches.suse/orinoco-avoid-assertion-in-case-of-NULL-pointer.patch @@ -0,0 +1,37 @@ +From c705f9fc6a1736dcf6ec01f8206707c108dca824 Mon Sep 17 00:00:00 2001 +From: Aditya Pakki +Date: Sun, 15 Dec 2019 13:58:58 -0600 +Subject: [PATCH] orinoco: avoid assertion in case of NULL pointer +Git-commit: c705f9fc6a1736dcf6ec01f8206707c108dca824 +Patch-mainline: v5.6-rc1 +References: bsc#1051510 + +In ezusb_init, if upriv is NULL, the code crashes. However, the caller +in ezusb_probe can handle the error and print the failure message. +The patch replaces the BUG_ON call to error return. + +Signed-off-by: Aditya Pakki +Signed-off-by: Kalle Valo +Acked-by: Takashi Iwai + +--- + drivers/net/wireless/intersil/orinoco/orinoco_usb.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/wireless/intersil/orinoco/orinoco_usb.c b/drivers/net/wireless/intersil/orinoco/orinoco_usb.c +index 8c79b963bcff..e753f43e0162 100644 +--- a/drivers/net/wireless/intersil/orinoco/orinoco_usb.c ++++ b/drivers/net/wireless/intersil/orinoco/orinoco_usb.c +@@ -1361,7 +1361,8 @@ static int ezusb_init(struct hermes *hw) + int retval; + + BUG_ON(in_interrupt()); +- BUG_ON(!upriv); ++ if (!upriv) ++ return -EINVAL; + + upriv->reply_count = 0; + /* Write the MAGIC number on the simulated registers to keep +-- +2.16.4 + diff --git a/patches.suse/pci-dpc-fix-print-aer-status-in-dpc-event-handling b/patches.suse/pci-dpc-fix-print-aer-status-in-dpc-event-handling index ef613a9..de8d60a 100644 --- a/patches.suse/pci-dpc-fix-print-aer-status-in-dpc-event-handling +++ b/patches.suse/pci-dpc-fix-print-aer-status-in-dpc-event-handling @@ -23,7 +23,7 @@ Cc: stable@vger.kernel.org # v4.19+ Acked-by: Joerg Roedel --- - drivers/pci/pcie/dpc.c | 27 ++++++++++++++++++++++++++- + drivers/pci/pcie/dpc.c | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) --- a/drivers/pci/pcie/dpc.c @@ -57,7 +57,7 @@ Acked-by: Joerg Roedel static irqreturn_t dpc_handler(int irq, void *context) { struct aer_err_info info; -@@ -183,7 +205,9 @@ static irqreturn_t dpc_handler(int irq, +@@ -183,9 +205,12 @@ static irqreturn_t dpc_handler(int irq, /* show RP PIO error detail information */ if (dpc->rp_extensions && reason == 3 && ext_reason == 0) dpc_process_rp_pio_error(dpc); @@ -67,4 +67,7 @@ Acked-by: Joerg Roedel + aer_get_device_error_info(pdev, &info)) { aer_print_error(pdev, &info); pci_cleanup_aer_uncorrect_error_status(pdev); ++ pci_aer_clear_fatal_status(pdev); } + + /* We configure DPC so it only triggers on ERR_FATAL */ diff --git a/patches.suse/perf-amd-uncore-replace-manual-sampling-check-with-cap_no_interrupt-flag.patch b/patches.suse/perf-amd-uncore-replace-manual-sampling-check-with-cap_no_interrupt-flag.patch new file mode 100644 index 0000000..5284eda --- /dev/null +++ b/patches.suse/perf-amd-uncore-replace-manual-sampling-check-with-cap_no_interrupt-flag.patch @@ -0,0 +1,80 @@ +From: Kim Phillips +Date: Wed, 11 Mar 2020 14:13:21 -0500 +Subject: perf/amd/uncore: Replace manual sampling check with CAP_NO_INTERRUPT + flag +Git-commit: f967140dfb7442e2db0868b03b961f9c59418a1b +Patch-mainline: v5.6-rc6 +References: bsc#1114279 + +Enable the sampling check in kernel/events/core.c::perf_event_open(), +which returns the more appropriate -EOPNOTSUPP. + +BEFORE: + + $ sudo perf record -a -e instructions,l3_request_g1.caching_l3_cache_accesses true + Error: + The sys_perf_event_open() syscall returned with 22 (Invalid argument) for event (l3_request_g1.caching_l3_cache_accesses). + /bin/dmesg | grep -i perf may provide additional information. + +With nothing relevant in dmesg. + +AFTER: + + $ sudo perf record -a -e instructions,l3_request_g1.caching_l3_cache_accesses true + Error: + l3_request_g1.caching_l3_cache_accesses: PMU Hardware doesn't support sampling/overflow-interrupts. Try 'perf stat' + +Fixes: c43ca5091a37 ("perf/x86/amd: Add support for AMD NB and L2I "uncore" counters") +Signed-off-by: Kim Phillips +Signed-off-by: Borislav Petkov +Acked-by: Peter Zijlstra +Cc: stable@vger.kernel.org +Link: https://lkml.kernel.org/r/20200311191323.13124-1-kim.phillips@amd.com +--- + arch/x86/events/amd/uncore.c | 14 +++++++------- + 1 file changed, 7 insertions(+), 7 deletions(-) + +--- a/arch/x86/events/amd/uncore.c ++++ b/arch/x86/events/amd/uncore.c +@@ -191,20 +191,18 @@ static int amd_uncore_event_init(struct + + /* + * NB and Last level cache counters (MSRs) are shared across all cores +- * that share the same NB / Last level cache. Interrupts can be directed +- * to a single target core, however, event counts generated by processes +- * running on other cores cannot be masked out. So we do not support +- * sampling and per-thread events. ++ * that share the same NB / Last level cache. On family 16h and below, ++ * Interrupts can be directed to a single target core, however, event ++ * counts generated by processes running on other cores cannot be masked ++ * out. So we do not support sampling and per-thread events via ++ * CAP_NO_INTERRUPT, and we do not enable counter overflow interrupts: + */ +- if (is_sampling_event(event) || event->attach_state & PERF_ATTACH_TASK) +- return -EINVAL; + + /* NB and Last level cache counters do not have usr/os/guest/host bits */ + if (event->attr.exclude_user || event->attr.exclude_kernel || + event->attr.exclude_host || event->attr.exclude_guest) + return -EINVAL; + +- /* and we do not enable counter overflow interrupts */ + hwc->config = event->attr.config & AMD64_RAW_EVENT_MASK_NB; + hwc->idx = -1; + +@@ -298,6 +296,7 @@ static struct pmu amd_nb_pmu = { + .start = amd_uncore_start, + .stop = amd_uncore_stop, + .read = amd_uncore_read, ++ .capabilities = PERF_PMU_CAP_NO_INTERRUPT, + }; + + static struct pmu amd_llc_pmu = { +@@ -308,6 +307,7 @@ static struct pmu amd_llc_pmu = { + .start = amd_uncore_start, + .stop = amd_uncore_stop, + .read = amd_uncore_read, ++ .capabilities = PERF_PMU_CAP_NO_INTERRUPT, + }; + + static struct amd_uncore *amd_uncore_alloc(unsigned int cpu) diff --git a/patches.suse/pinctrl-baytrail-Do-not-clear-IRQ-flags-on-direct-ir.patch b/patches.suse/pinctrl-baytrail-Do-not-clear-IRQ-flags-on-direct-ir.patch new file mode 100644 index 0000000..f648395 --- /dev/null +++ b/patches.suse/pinctrl-baytrail-Do-not-clear-IRQ-flags-on-direct-ir.patch @@ -0,0 +1,55 @@ +From a23680594da7a9e2696dbcf4f023e9273e2fa40b Mon Sep 17 00:00:00 2001 +From: Hans de Goede +Date: Sat, 28 Dec 2019 00:04:47 +0100 +Subject: [PATCH] pinctrl: baytrail: Do not clear IRQ flags on direct-irq enabled pins +Git-commit: a23680594da7a9e2696dbcf4f023e9273e2fa40b +Patch-mainline: v5.6-rc1 +References: bsc#1051510 + +Suspending Goodix touchscreens requires changing the interrupt pin to +output before sending them a power-down command. Followed by wiggling +the interrupt pin to wake the device up, after which it is put back +in input mode. + +On Bay Trail devices with a Goodix touchscreen direct-irq mode is used +in combination with listing the pin as a normal GpioIo resource. + +This works fine, until the goodix driver gets rmmod-ed and then insmod-ed +again. In this case byt_gpio_disable_free() calls +byt_gpio_clear_triggering() which clears the IRQ flags and after that the +(direct) IRQ no longer triggers. + +This commit fixes this by adding a check for the BYT_DIRECT_IRQ_EN flag +to byt_gpio_clear_triggering(). + +Note that byt_gpio_clear_triggering() only gets called from +byt_gpio_disable_free() for direct-irq enabled pins, as these are excluded +from the irq_valid mask by byt_init_irq_valid_mask(). + +Signed-off-by: Hans de Goede +Acked-by: Mika Westerberg +Reviewed-by: Linus Walleij +Signed-off-by: Andy Shevchenko +Acked-by: Takashi Iwai + +--- + drivers/pinctrl/intel/pinctrl-baytrail.c | 8 +++++++- + 1 file changed, 7 insertions(+), 1 deletion(-) + +--- a/drivers/pinctrl/intel/pinctrl-baytrail.c ++++ b/drivers/pinctrl/intel/pinctrl-baytrail.c +@@ -957,7 +957,13 @@ static void byt_gpio_clear_triggering(st + + raw_spin_lock_irqsave(&vg->lock, flags); + value = readl(reg); +- value &= ~(BYT_TRIG_POS | BYT_TRIG_NEG | BYT_TRIG_LVL); ++ ++ /* Do not clear direct-irq enabled IRQs (from gpio_disable_free) */ ++ if (value & BYT_DIRECT_IRQ_EN) ++ /* nothing to do */ ; ++ else ++ value &= ~(BYT_TRIG_POS | BYT_TRIG_NEG | BYT_TRIG_LVL); ++ + writel(value, reg); + raw_spin_unlock_irqrestore(&vg->lock, flags); + } diff --git a/patches.suse/pinctrl-core-Remove-extra-kref_get-which-blocks-hogs.patch b/patches.suse/pinctrl-core-Remove-extra-kref_get-which-blocks-hogs.patch new file mode 100644 index 0000000..c0bc476 --- /dev/null +++ b/patches.suse/pinctrl-core-Remove-extra-kref_get-which-blocks-hogs.patch @@ -0,0 +1,38 @@ +From aafd56fc79041bf36f97712d4b35208cbe07db90 Mon Sep 17 00:00:00 2001 +From: Charles Keepax +Date: Fri, 28 Feb 2020 15:41:42 +0000 +Subject: [PATCH] pinctrl: core: Remove extra kref_get which blocks hogs being freed +Git-commit: aafd56fc79041bf36f97712d4b35208cbe07db90 +Patch-mainline: v5.6-rc6 +References: bsc#1051510 + +kref_init starts with the reference count at 1, which will be balanced +by the pinctrl_put in pinctrl_unregister. The additional kref_get in +pinctrl_claim_hogs will increase this count to 2 and cause the hogs to +not get freed when pinctrl_unregister is called. + +Fixes: 6118714275f0 ("pinctrl: core: Fix pinctrl_register_and_init() with pinctrl_enable()") +Signed-off-by: Charles Keepax +Link: https://lore.kernel.org/r/20200228154142.13860-1-ckeepax@opensource.cirrus.com +Signed-off-by: Linus Walleij +Acked-by: Takashi Iwai + +--- + drivers/pinctrl/core.c | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/drivers/pinctrl/core.c b/drivers/pinctrl/core.c +index 446d84fe0e31..f23c55e22195 100644 +--- a/drivers/pinctrl/core.c ++++ b/drivers/pinctrl/core.c +@@ -2021,7 +2021,6 @@ static int pinctrl_claim_hogs(struct pinctrl_dev *pctldev) + return PTR_ERR(pctldev->p); + } + +- kref_get(&pctldev->p->users); + pctldev->hog_default = + pinctrl_lookup_state(pctldev->p, PINCTRL_STATE_DEFAULT); + if (IS_ERR(pctldev->hog_default)) { +-- +2.16.4 + diff --git a/patches.suse/pinctrl-imx-scu-align-imx-sc-msg-structs-to-4.patch b/patches.suse/pinctrl-imx-scu-align-imx-sc-msg-structs-to-4.patch new file mode 100644 index 0000000..215a692 --- /dev/null +++ b/patches.suse/pinctrl-imx-scu-align-imx-sc-msg-structs-to-4.patch @@ -0,0 +1,43 @@ +From: Leonard Crestez +Date: Thu, 20 Feb 2020 18:29:37 +0200 +Subject: pinctrl: imx: scu: Align imx sc msg structs to 4 +Git-commit: 4c48e549f39f8ed10cf8a0b6cb96f5eddf0391ce +Patch-mainline: v5.6 or v5.6-rc6 (next release) +References: git-fixes + +The imx SC api strongly assumes that messages are composed out of +4-bytes words but some of our message structs have odd sizeofs. + +This produces many oopses with CONFIG_KASAN=y. + +Fix by marking with __aligned(4). + +Fixes: b96eea718bf6 ("pinctrl: fsl: add scu based pinctrl support") +Signed-off-by: Leonard Crestez +Link: https://lore.kernel.org/r/bd7ad5fd755739a6d8d5f4f65e03b3ca4f457bd2.1582216144.git.leonard.crestez@nxp.com +Signed-off-by: Linus Walleij +Acked-by: Nicolas Saenz Julienne +--- + drivers/pinctrl/freescale/pinctrl-scu.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/pinctrl/freescale/pinctrl-scu.c b/drivers/pinctrl/freescale/pinctrl-scu.c +index 73bf1d9f9cc6..23cf04bdfc55 100644 +--- a/drivers/pinctrl/freescale/pinctrl-scu.c ++++ b/drivers/pinctrl/freescale/pinctrl-scu.c +@@ -23,12 +23,12 @@ struct imx_sc_msg_req_pad_set { + struct imx_sc_rpc_msg hdr; + u32 val; + u16 pad; +-} __packed; ++} __packed __aligned(4); + + struct imx_sc_msg_req_pad_get { + struct imx_sc_rpc_msg hdr; + u16 pad; +-} __packed; ++} __packed __aligned(4); + + struct imx_sc_msg_resp_pad_get { + struct imx_sc_rpc_msg hdr; + diff --git a/patches.suse/pinctrl-sh-pfc-sh7264-Fix-CAN-function-GPIOs.patch b/patches.suse/pinctrl-sh-pfc-sh7264-Fix-CAN-function-GPIOs.patch new file mode 100644 index 0000000..731adea --- /dev/null +++ b/patches.suse/pinctrl-sh-pfc-sh7264-Fix-CAN-function-GPIOs.patch @@ -0,0 +1,94 @@ +From 55b1cb1f03ad5eea39897d0c74035e02deddcff2 Mon Sep 17 00:00:00 2001 +From: Geert Uytterhoeven +Date: Wed, 18 Dec 2019 20:48:09 +0100 +Subject: [PATCH] pinctrl: sh-pfc: sh7264: Fix CAN function GPIOs +Git-commit: 55b1cb1f03ad5eea39897d0c74035e02deddcff2 +Patch-mainline: v5.6-rc1 +References: bsc#1051510 + +pinmux_func_gpios[] contains a hole due to the missing function GPIO +definition for the "CTX0&CTX1" signal, which is the logical "AND" of the +two CAN outputs. + +Fix this by: + - Renaming CRX0_CRX1_MARK to CTX0_CTX1_MARK, as PJ2MD[2:0]=010 + configures the combined "CTX0&CTX1" output signal, + - Renaming CRX0X1_MARK to CRX0_CRX1_MARK, as PJ3MD[1:0]=10 configures + the shared "CRX0/CRX1" input signal, which is fed to both CAN + inputs, + - Adding the missing function GPIO definition for "CTX0&CTX1" to + pinmux_func_gpios[], + - Moving all CAN enums next to each other. + +See SH7262 Group, SH7264 Group User's Manual: Hardware, Rev. 4.00: + [1] Figure 1.2 (3) (Pin Assignment for the SH7264 Group (1-Mbyte + Version), + [2] Figure 1.2 (4) Pin Assignment for the SH7264 Group (640-Kbyte + Version, + [3] Table 1.4 List of Pins, + [4] Figure 20.29 Connection Example when Using This Module as 1-Channel + Module (64 Mailboxes x 1 Channel), + [5] Table 32.10 Multiplexed Pins (Port J), + [6] Section 32.2.30 (3) Port J Control Register 0 (PJCR0). + +Note that the last 2 disagree about PJ2MD[2:0], which is probably the +root cause of this bug. But considering [4], "CTx0&CTx1" in [5] must +be correct, and "CRx0&CRx1" in [6] must be wrong. + +Signed-off-by: Geert Uytterhoeven +Link: https://lore.kernel.org/r/20191218194812.12741-4-geert+renesas@glider.be +Acked-by: Takashi Iwai + +--- + drivers/pinctrl/sh-pfc/pfc-sh7264.c | 9 ++++----- + 1 file changed, 4 insertions(+), 5 deletions(-) + +diff --git a/drivers/pinctrl/sh-pfc/pfc-sh7264.c b/drivers/pinctrl/sh-pfc/pfc-sh7264.c +index 4117bd8c0f41..908837ea487b 100644 +--- a/drivers/pinctrl/sh-pfc/pfc-sh7264.c ++++ b/drivers/pinctrl/sh-pfc/pfc-sh7264.c +@@ -497,17 +497,15 @@ enum { + SD_WP_MARK, SD_CLK_MARK, SD_CMD_MARK, + CRX0_MARK, CRX1_MARK, + CTX0_MARK, CTX1_MARK, ++ CRX0_CRX1_MARK, CTX0_CTX1_MARK, + + PWM1A_MARK, PWM1B_MARK, PWM1C_MARK, PWM1D_MARK, + PWM1E_MARK, PWM1F_MARK, PWM1G_MARK, PWM1H_MARK, + PWM2A_MARK, PWM2B_MARK, PWM2C_MARK, PWM2D_MARK, + PWM2E_MARK, PWM2F_MARK, PWM2G_MARK, PWM2H_MARK, + IERXD_MARK, IETXD_MARK, +- CRX0_CRX1_MARK, + WDTOVF_MARK, + +- CRX0X1_MARK, +- + /* DMAC */ + TEND0_MARK, DACK0_MARK, DREQ0_MARK, + TEND1_MARK, DACK1_MARK, DREQ1_MARK, +@@ -995,12 +993,12 @@ static const u16 pinmux_data[] = { + + PINMUX_DATA(PJ3_DATA, PJ3MD_00), + PINMUX_DATA(CRX1_MARK, PJ3MD_01), +- PINMUX_DATA(CRX0X1_MARK, PJ3MD_10), ++ PINMUX_DATA(CRX0_CRX1_MARK, PJ3MD_10), + PINMUX_DATA(IRQ1_PJ_MARK, PJ3MD_11), + + PINMUX_DATA(PJ2_DATA, PJ2MD_000), + PINMUX_DATA(CTX1_MARK, PJ2MD_001), +- PINMUX_DATA(CRX0_CRX1_MARK, PJ2MD_010), ++ PINMUX_DATA(CTX0_CTX1_MARK, PJ2MD_010), + PINMUX_DATA(CS2_MARK, PJ2MD_011), + PINMUX_DATA(SCK0_MARK, PJ2MD_100), + PINMUX_DATA(LCD_M_DISP_MARK, PJ2MD_101), +@@ -1245,6 +1243,7 @@ static const struct pinmux_func pinmux_func_gpios[] = { + GPIO_FN(CTX1), + GPIO_FN(CRX1), + GPIO_FN(CTX0), ++ GPIO_FN(CTX0_CTX1), + GPIO_FN(CRX0), + GPIO_FN(CRX0_CRX1), + +-- +2.16.4 + diff --git a/patches.suse/pinctrl-sh-pfc-sh7269-Fix-CAN-function-GPIOs.patch b/patches.suse/pinctrl-sh-pfc-sh7269-Fix-CAN-function-GPIOs.patch new file mode 100644 index 0000000..e8eaf60 --- /dev/null +++ b/patches.suse/pinctrl-sh-pfc-sh7269-Fix-CAN-function-GPIOs.patch @@ -0,0 +1,184 @@ +From 02aeb2f21530c98fc3ca51028eda742a3fafbd9f Mon Sep 17 00:00:00 2001 +From: Geert Uytterhoeven +Date: Wed, 18 Dec 2019 20:48:10 +0100 +Subject: [PATCH] pinctrl: sh-pfc: sh7269: Fix CAN function GPIOs +Mime-version: 1.0 +Content-type: text/plain; charset=UTF-8 +Content-transfer-encoding: 8bit +Git-commit: 02aeb2f21530c98fc3ca51028eda742a3fafbd9f +Patch-mainline: v5.6-rc1 +References: bsc#1051510 + +pinmux_func_gpios[] contains a hole due to the missing function GPIO +definition for the "CTX0&CTX1" signal, which is the logical "AND" of the +first two CAN outputs. + +A closer look reveals other issues: + - Some functionality is available on alternative pins, but the + PINMUX_DATA() entries is using the wrong marks, + - Several configurations are missing. + +Fix this by: + - Renaming CTX0CTX1CTX2_MARK, CRX0CRX1_PJ22_MARK, and + CRX0CRX1CRX2_PJ20_MARK to CTX0_CTX1_CTX2_MARK, CRX0_CRX1_PJ22_MARK, + resp. CRX0_CRX1_CRX2_PJ20_MARK for consistency with the + corresponding enum IDs, + - Adding all missing enum IDs and marks, + - Use the right (*_PJ2x) variants for alternative pins, + - Adding all missing configurations to pinmux_data[], + - Adding all missing function GPIO definitions to pinmux_func_gpios[]. + +See SH7268 Group, SH7269 Group User’s Manual: Hardware, Rev. 2.00: + [1] Table 1.4 List of Pins + [2] Figure 23.29 Connection Example when Using Channels 0 and 1 as One + Channel (64 Mailboxes × 1 Channel) and Channel 2 as One Channel + (32 Mailboxes × 1 Channel), + [3] Figure 23.30 Connection Example when Using Channels 0, 1, and 2 as + One Channel (96 Mailboxes × 1 Channel), + [4] Table 48.3 Multiplexed Pins (Port B), + [5] Table 48.4 Multiplexed Pins (Port C), + [6] Table 48.10 Multiplexed Pins (Port J), + [7] Section 48.2.4 Port B Control Registers 0 to 5 (PBCR0 to PBCR5). + +Signed-off-by: Geert Uytterhoeven +Link: https://lore.kernel.org/r/20191218194812.12741-5-geert+renesas@glider.be +Acked-by: Takashi Iwai + +--- + arch/sh/include/cpu-sh2a/cpu/sh7269.h | 11 ++++++++-- + drivers/pinctrl/sh-pfc/pfc-sh7269.c | 39 ++++++++++++++++++++++++----------- + 2 files changed, 36 insertions(+), 14 deletions(-) + +diff --git a/arch/sh/include/cpu-sh2a/cpu/sh7269.h b/arch/sh/include/cpu-sh2a/cpu/sh7269.h +index d516e5d48818..b887cc402b71 100644 +--- a/arch/sh/include/cpu-sh2a/cpu/sh7269.h ++++ b/arch/sh/include/cpu-sh2a/cpu/sh7269.h +@@ -78,8 +78,15 @@ enum { + GPIO_FN_WDTOVF, + + /* CAN */ +- GPIO_FN_CTX1, GPIO_FN_CRX1, GPIO_FN_CTX0, GPIO_FN_CTX0_CTX1, +- GPIO_FN_CRX0, GPIO_FN_CRX0_CRX1, GPIO_FN_CRX0_CRX1_CRX2, ++ GPIO_FN_CTX2, GPIO_FN_CRX2, ++ GPIO_FN_CTX1, GPIO_FN_CRX1, ++ GPIO_FN_CTX0, GPIO_FN_CRX0, ++ GPIO_FN_CTX0_CTX1, GPIO_FN_CRX0_CRX1, ++ GPIO_FN_CTX0_CTX1_CTX2, GPIO_FN_CRX0_CRX1_CRX2, ++ GPIO_FN_CTX2_PJ21, GPIO_FN_CRX2_PJ20, ++ GPIO_FN_CTX1_PJ23, GPIO_FN_CRX1_PJ22, ++ GPIO_FN_CTX0_CTX1_PJ23, GPIO_FN_CRX0_CRX1_PJ22, ++ GPIO_FN_CTX0_CTX1_CTX2_PJ21, GPIO_FN_CRX0_CRX1_CRX2_PJ20, + + /* DMAC */ + GPIO_FN_TEND0, GPIO_FN_DACK0, GPIO_FN_DREQ0, +diff --git a/drivers/pinctrl/sh-pfc/pfc-sh7269.c b/drivers/pinctrl/sh-pfc/pfc-sh7269.c +index 6cbb18ef77dc..d20974a55d93 100644 +--- a/drivers/pinctrl/sh-pfc/pfc-sh7269.c ++++ b/drivers/pinctrl/sh-pfc/pfc-sh7269.c +@@ -737,13 +737,12 @@ enum { + CRX0_MARK, CTX0_MARK, + CRX1_MARK, CTX1_MARK, + CRX2_MARK, CTX2_MARK, +- CRX0_CRX1_MARK, +- CRX0_CRX1_CRX2_MARK, +- CTX0CTX1CTX2_MARK, ++ CRX0_CRX1_MARK, CTX0_CTX1_MARK, ++ CRX0_CRX1_CRX2_MARK, CTX0_CTX1_CTX2_MARK, + CRX1_PJ22_MARK, CTX1_PJ23_MARK, + CRX2_PJ20_MARK, CTX2_PJ21_MARK, +- CRX0CRX1_PJ22_MARK, +- CRX0CRX1CRX2_PJ20_MARK, ++ CRX0_CRX1_PJ22_MARK, CTX0_CTX1_PJ23_MARK, ++ CRX0_CRX1_CRX2_PJ20_MARK, CTX0_CTX1_CTX2_PJ21_MARK, + + /* VDC */ + DV_CLK_MARK, +@@ -821,6 +820,7 @@ static const u16 pinmux_data[] = { + PINMUX_DATA(CS3_MARK, PC8MD_001), + PINMUX_DATA(TXD7_MARK, PC8MD_010), + PINMUX_DATA(CTX1_MARK, PC8MD_011), ++ PINMUX_DATA(CTX0_CTX1_MARK, PC8MD_100), + + PINMUX_DATA(PC7_DATA, PC7MD_000), + PINMUX_DATA(CKE_MARK, PC7MD_001), +@@ -833,11 +833,12 @@ static const u16 pinmux_data[] = { + PINMUX_DATA(CAS_MARK, PC6MD_001), + PINMUX_DATA(SCK7_MARK, PC6MD_010), + PINMUX_DATA(CTX0_MARK, PC6MD_011), ++ PINMUX_DATA(CTX0_CTX1_CTX2_MARK, PC6MD_100), + + PINMUX_DATA(PC5_DATA, PC5MD_000), + PINMUX_DATA(RAS_MARK, PC5MD_001), + PINMUX_DATA(CRX0_MARK, PC5MD_011), +- PINMUX_DATA(CTX0CTX1CTX2_MARK, PC5MD_100), ++ PINMUX_DATA(CTX0_CTX1_CTX2_MARK, PC5MD_100), + PINMUX_DATA(IRQ0_PC_MARK, PC5MD_101), + + PINMUX_DATA(PC4_DATA, PC4MD_00), +@@ -1289,30 +1290,32 @@ static const u16 pinmux_data[] = { + PINMUX_DATA(LCD_DATA23_PJ23_MARK, PJ23MD_010), + PINMUX_DATA(LCD_TCON6_MARK, PJ23MD_011), + PINMUX_DATA(IRQ3_PJ_MARK, PJ23MD_100), +- PINMUX_DATA(CTX1_MARK, PJ23MD_101), ++ PINMUX_DATA(CTX1_PJ23_MARK, PJ23MD_101), ++ PINMUX_DATA(CTX0_CTX1_PJ23_MARK, PJ23MD_110), + + PINMUX_DATA(PJ22_DATA, PJ22MD_000), + PINMUX_DATA(DV_DATA22_MARK, PJ22MD_001), + PINMUX_DATA(LCD_DATA22_PJ22_MARK, PJ22MD_010), + PINMUX_DATA(LCD_TCON5_MARK, PJ22MD_011), + PINMUX_DATA(IRQ2_PJ_MARK, PJ22MD_100), +- PINMUX_DATA(CRX1_MARK, PJ22MD_101), +- PINMUX_DATA(CRX0_CRX1_MARK, PJ22MD_110), ++ PINMUX_DATA(CRX1_PJ22_MARK, PJ22MD_101), ++ PINMUX_DATA(CRX0_CRX1_PJ22_MARK, PJ22MD_110), + + PINMUX_DATA(PJ21_DATA, PJ21MD_000), + PINMUX_DATA(DV_DATA21_MARK, PJ21MD_001), + PINMUX_DATA(LCD_DATA21_PJ21_MARK, PJ21MD_010), + PINMUX_DATA(LCD_TCON4_MARK, PJ21MD_011), + PINMUX_DATA(IRQ1_PJ_MARK, PJ21MD_100), +- PINMUX_DATA(CTX2_MARK, PJ21MD_101), ++ PINMUX_DATA(CTX2_PJ21_MARK, PJ21MD_101), ++ PINMUX_DATA(CTX0_CTX1_CTX2_PJ21_MARK, PJ21MD_110), + + PINMUX_DATA(PJ20_DATA, PJ20MD_000), + PINMUX_DATA(DV_DATA20_MARK, PJ20MD_001), + PINMUX_DATA(LCD_DATA20_PJ20_MARK, PJ20MD_010), + PINMUX_DATA(LCD_TCON3_MARK, PJ20MD_011), + PINMUX_DATA(IRQ0_PJ_MARK, PJ20MD_100), +- PINMUX_DATA(CRX2_MARK, PJ20MD_101), +- PINMUX_DATA(CRX0CRX1CRX2_PJ20_MARK, PJ20MD_110), ++ PINMUX_DATA(CRX2_PJ20_MARK, PJ20MD_101), ++ PINMUX_DATA(CRX0_CRX1_CRX2_PJ20_MARK, PJ20MD_110), + + PINMUX_DATA(PJ19_DATA, PJ19MD_000), + PINMUX_DATA(DV_DATA19_MARK, PJ19MD_001), +@@ -1663,12 +1666,24 @@ static const struct pinmux_func pinmux_func_gpios[] = { + GPIO_FN(WDTOVF), + + /* CAN */ ++ GPIO_FN(CTX2), ++ GPIO_FN(CRX2), + GPIO_FN(CTX1), + GPIO_FN(CRX1), + GPIO_FN(CTX0), + GPIO_FN(CRX0), ++ GPIO_FN(CTX0_CTX1), + GPIO_FN(CRX0_CRX1), ++ GPIO_FN(CTX0_CTX1_CTX2), + GPIO_FN(CRX0_CRX1_CRX2), ++ GPIO_FN(CTX2_PJ21), ++ GPIO_FN(CRX2_PJ20), ++ GPIO_FN(CTX1_PJ23), ++ GPIO_FN(CRX1_PJ22), ++ GPIO_FN(CTX0_CTX1_PJ23), ++ GPIO_FN(CRX0_CRX1_PJ22), ++ GPIO_FN(CTX0_CTX1_CTX2_PJ21), ++ GPIO_FN(CRX0_CRX1_CRX2_PJ20), + + /* DMAC */ + GPIO_FN(TEND0), +-- +2.16.4 + diff --git a/patches.suse/pkt_sched-fq-do-not-accept-silly-TCA_FQ_QUANTUM.patch b/patches.suse/pkt_sched-fq-do-not-accept-silly-TCA_FQ_QUANTUM.patch new file mode 100644 index 0000000..d08faa3 --- /dev/null +++ b/patches.suse/pkt_sched-fq-do-not-accept-silly-TCA_FQ_QUANTUM.patch @@ -0,0 +1,46 @@ +From: Eric Dumazet +Date: Mon, 6 Jan 2020 06:10:39 -0800 +Subject: pkt_sched: fq: do not accept silly TCA_FQ_QUANTUM +Git-commit: d9e15a2733067c9328fb56d98fe8e574fa19ec31 +Patch-mainline: 5.5-rc6 +References: networking-stable-20_01_11 + +As diagnosed by Florian : + +If TCA_FQ_QUANTUM is set to 0x80000000, fq_deueue() +can loop forever in : + +if (f->credit <= 0) { + f->credit += q->quantum; + goto begin; +} + +... because f->credit is either 0 or -2147483648. + +Let's limit TCA_FQ_QUANTUM to no more than 1 << 20 : +This max value should limit risks of breaking user setups +while fixing this bug. + +[js] no extack in 4.12 yet. + +Fixes: afe4fd062416 ("pkt_sched: fq: Fair Queue packet scheduler") +Signed-off-by: Eric Dumazet +Diagnosed-by: Florian Westphal +Reported-by: syzbot+dc9071cc5a85950bdfce@syzkaller.appspotmail.com +Signed-off-by: David S. Miller +Signed-off-by: Jiri Slaby +--- + net/sched/sch_fq.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/net/sched/sch_fq.c ++++ b/net/sched/sch_fq.c +@@ -734,7 +734,7 @@ static int fq_change(struct Qdisc *sch, + if (tb[TCA_FQ_QUANTUM]) { + u32 quantum = nla_get_u32(tb[TCA_FQ_QUANTUM]); + +- if (quantum > 0) ++ if (quantum > 0 && quantum <= (1 << 20)) + q->quantum = quantum; + else + err = -EINVAL; diff --git a/patches.suse/platform-mellanox-fix-potential-deadlock-in-the-tmfi.patch b/patches.suse/platform-mellanox-fix-potential-deadlock-in-the-tmfi.patch new file mode 100644 index 0000000..ca1166b --- /dev/null +++ b/patches.suse/platform-mellanox-fix-potential-deadlock-in-the-tmfi.patch @@ -0,0 +1,121 @@ +From: Liming Sun +Date: Fri, 20 Dec 2019 12:04:33 -0500 +Subject: platform/mellanox: fix potential deadlock in the tmfifo driver +Patch-mainline: v5.5-rc7 +Git-commit: 638bc4ca3d28c25986cce4cbad69d9b8abf1e434 +References: bsc#1136333 jsc#SLE-4994 + +This commit fixes the potential deadlock caused by the console Rx +and Tx processing at the same time. Rx and Tx both take the console +and tmfifo spinlock but in different order which causes potential +deadlock. The fix is to use different tmfifo spinlock for Rx and +Tx since they protect different resources and it's safe to split +the lock. + +Below is the reported call trace when copying/pasting large string +in the console. + +Rx: + _raw_spin_lock_irqsave (hvc lock) + __hvc_poll + hvc_poll + in_intr + vring_interrupt + mlxbf_tmfifo_rxtx_one_desc (tmfifo lock) + mlxbf_tmfifo_rxtx + mlxbf_tmfifo_work_rxtx +Tx: + _raw_spin_lock_irqsave (tmfifo lock) + mlxbf_tmfifo_virtio_notify + virtqueue_notify + virtqueue_kick + put_chars + hvc_push + hvc_write (hvc lock) + ... + do_tty_write + tty_write + +Fixes: 1357dfd7261f ("platform/mellanox: Add TmFifo driver for Mellanox BlueField Soc") +Cc: # 5.4+ +Reviewed-by: David Woods +Signed-off-by: Liming Sun +Signed-off-by: Andy Shevchenko +Acked-by: Thomas Bogendoerfer +--- + drivers/platform/mellanox/mlxbf-tmfifo.c | 19 ++++++++++--------- + 1 file changed, 10 insertions(+), 9 deletions(-) + +--- a/drivers/platform/mellanox/mlxbf-tmfifo.c ++++ b/drivers/platform/mellanox/mlxbf-tmfifo.c +@@ -149,7 +149,7 @@ struct mlxbf_tmfifo_irq_info { + * @work: work struct for deferred process + * @timer: background timer + * @vring: Tx/Rx ring +- * @spin_lock: spin lock ++ * @spin_lock: Tx/Rx spin lock + * @is_ready: ready flag + */ + struct mlxbf_tmfifo { +@@ -164,7 +164,7 @@ struct mlxbf_tmfifo { + struct work_struct work; + struct timer_list timer; + struct mlxbf_tmfifo_vring *vring[2]; +- spinlock_t spin_lock; /* spin lock */ ++ spinlock_t spin_lock[2]; /* spin lock */ + bool is_ready; + }; + +@@ -525,7 +525,7 @@ static void mlxbf_tmfifo_console_tx(stru + writeq(*(u64 *)&hdr, fifo->tx_base + MLXBF_TMFIFO_TX_DATA); + + /* Use spin-lock to protect the 'cons->tx_buf'. */ +- spin_lock_irqsave(&fifo->spin_lock, flags); ++ spin_lock_irqsave(&fifo->spin_lock[0], flags); + + while (size > 0) { + addr = cons->tx_buf.buf + cons->tx_buf.tail; +@@ -552,7 +552,7 @@ static void mlxbf_tmfifo_console_tx(stru + } + } + +- spin_unlock_irqrestore(&fifo->spin_lock, flags); ++ spin_unlock_irqrestore(&fifo->spin_lock[0], flags); + } + + /* Rx/Tx one word in the descriptor buffer. */ +@@ -731,9 +731,9 @@ static bool mlxbf_tmfifo_rxtx_one_desc(s + fifo->vring[is_rx] = NULL; + + /* Notify upper layer that packet is done. */ +- spin_lock_irqsave(&fifo->spin_lock, flags); ++ spin_lock_irqsave(&fifo->spin_lock[is_rx], flags); + vring_interrupt(0, vring->vq); +- spin_unlock_irqrestore(&fifo->spin_lock, flags); ++ spin_unlock_irqrestore(&fifo->spin_lock[is_rx], flags); + } + + mlxbf_tmfifo_desc_done: +@@ -852,10 +852,10 @@ static bool mlxbf_tmfifo_virtio_notify(s + * worker handler. + */ + if (vring->vdev_id == VIRTIO_ID_CONSOLE) { +- spin_lock_irqsave(&fifo->spin_lock, flags); ++ spin_lock_irqsave(&fifo->spin_lock[0], flags); + tm_vdev = fifo->vdev[VIRTIO_ID_CONSOLE]; + mlxbf_tmfifo_console_output(tm_vdev, vring); +- spin_unlock_irqrestore(&fifo->spin_lock, flags); ++ spin_unlock_irqrestore(&fifo->spin_lock[0], flags); + } else if (test_and_set_bit(MLXBF_TM_TX_LWM_IRQ, + &fifo->pend_events)) { + return true; +@@ -1189,7 +1189,8 @@ static int mlxbf_tmfifo_probe(struct pla + if (!fifo) + return -ENOMEM; + +- spin_lock_init(&fifo->spin_lock); ++ spin_lock_init(&fifo->spin_lock[0]); ++ spin_lock_init(&fifo->spin_lock[1]); + INIT_WORK(&fifo->work, mlxbf_tmfifo_work_handler); + mutex_init(&fifo->lock); + diff --git a/patches.suse/platform-x86-pmc_atom-Add-Lex-2I385SW-to-critclk_sys.patch b/patches.suse/platform-x86-pmc_atom-Add-Lex-2I385SW-to-critclk_sys.patch new file mode 100644 index 0000000..067ff7b --- /dev/null +++ b/patches.suse/platform-x86-pmc_atom-Add-Lex-2I385SW-to-critclk_sys.patch @@ -0,0 +1,50 @@ +From 95b31e35239e5e1689e3d965d692a313c71bd8ab Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Georg=20M=C3=BCller?= +Date: Mon, 3 Feb 2020 21:11:06 +0100 +Subject: [PATCH] platform/x86: pmc_atom: Add Lex 2I385SW to critclk_systems DMI table +Mime-version: 1.0 +Content-type: text/plain; charset=UTF-8 +Content-transfer-encoding: 8bit +Git-commit: 95b31e35239e5e1689e3d965d692a313c71bd8ab +Patch-mainline: v5.7-rc1 +References: bsc#1051510 + +The Lex 2I385SW board has two Intel I211 ethernet controllers. Without +this patch, only the first port is usable. The second port fails to +start with the following message: + + igb: probe of 0000:02:00.0 failed with error -2 + +Fixes: 648e921888ad ("clk: x86: Stop marking clocks as CLK_IS_CRITICAL") +Tested-by: Georg Müller +Signed-off-by: Georg Müller +Reviewed-by: Hans de Goede +Signed-off-by: Andy Shevchenko +Acked-by: Takashi Iwai + +--- + drivers/platform/x86/pmc_atom.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/drivers/platform/x86/pmc_atom.c b/drivers/platform/x86/pmc_atom.c +index 3e3c66dfec2e..ca684ed760d1 100644 +--- a/drivers/platform/x86/pmc_atom.c ++++ b/drivers/platform/x86/pmc_atom.c +@@ -383,6 +383,14 @@ static const struct dmi_system_id critclk_systems[] = { + DMI_MATCH(DMI_PRODUCT_NAME, "3I380D"), + }, + }, ++ { ++ /* pmc_plt_clk* - are used for ethernet controllers */ ++ .ident = "Lex 2I385SW", ++ .matches = { ++ DMI_MATCH(DMI_SYS_VENDOR, "Lex BayTrail"), ++ DMI_MATCH(DMI_PRODUCT_NAME, "2I385SW"), ++ }, ++ }, + { + /* pmc_plt_clk* - are used for ethernet controllers */ + .ident = "Beckhoff CB3163", +-- +2.16.4 + diff --git a/patches.suse/powerpc-64-mark-start_here_multiplatform-as-__ref.patch b/patches.suse/powerpc-64-mark-start_here_multiplatform-as-__ref.patch new file mode 100644 index 0000000..a7d0197 --- /dev/null +++ b/patches.suse/powerpc-64-mark-start_here_multiplatform-as-__ref.patch @@ -0,0 +1,49 @@ +From 9c4e4c90ec24652921e31e9551fcaedc26eec86d Mon Sep 17 00:00:00 2001 +From: Christophe Leroy +Date: Fri, 10 May 2019 06:31:28 +0000 +Subject: [PATCH] powerpc/64: mark start_here_multiplatform as __ref + +References: bsc#1148868 +Patch-mainline: v5.3-rc1 +Git-commit: 9c4e4c90ec24652921e31e9551fcaedc26eec86d + +Otherwise, the following warning is encountered: + +WARNING: vmlinux.o(.text+0x3dc6): Section mismatch in reference from the variable start_here_multiplatform to the function .init.text:.early_setup() +The function start_here_multiplatform() references +the function __init .early_setup(). +This is often because start_here_multiplatform lacks a __init +annotation or the annotation of .early_setup is wrong. + +Fixes: 56c46bba9bbf ("powerpc/64: Fix booting large kernels with STRICT_KERNEL_RWX") +Cc: Russell Currey +Signed-off-by: Christophe Leroy +Signed-off-by: Michael Ellerman +Acked-by: Michal Suchanek +--- + arch/powerpc/kernel/head_64.S | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/arch/powerpc/kernel/head_64.S b/arch/powerpc/kernel/head_64.S +index 5321a11c2835..259be7f6d551 100644 +--- a/arch/powerpc/kernel/head_64.S ++++ b/arch/powerpc/kernel/head_64.S +@@ -904,6 +904,7 @@ p_toc: .8byte __toc_start + 0x8000 - 0b + /* + * This is where the main kernel code starts. + */ ++__REF + start_here_multiplatform: + /* set up the TOC */ + bl relative_toc +@@ -979,6 +980,7 @@ start_here_multiplatform: + RFI + b . /* prevent speculative execution */ + ++ .previous + /* This is where all platforms converge execution */ + + start_here_common: +-- +2.23.0 + diff --git a/patches.suse/powerpc-64-tm-Don-t-let-userspace-set-regs-trap-via-.patch b/patches.suse/powerpc-64-tm-Don-t-let-userspace-set-regs-trap-via-.patch new file mode 100644 index 0000000..79ff7bd --- /dev/null +++ b/patches.suse/powerpc-64-tm-Don-t-let-userspace-set-regs-trap-via-.patch @@ -0,0 +1,69 @@ +From c7def7fbdeaa25feaa19caf4a27c5d10bd8789e4 Mon Sep 17 00:00:00 2001 +From: Michael Ellerman +Date: Tue, 31 Mar 2020 22:47:19 +1100 +Subject: [PATCH] powerpc/64/tm: Don't let userspace set regs->trap via + sigreturn + +References: bsc#1118338 ltc#173734 +Patch-mainline: v5.7-rc1 +Git-commit: c7def7fbdeaa25feaa19caf4a27c5d10bd8789e4 + +In restore_tm_sigcontexts() we take the trap value directly from the +user sigcontext with no checking: + + err |= __get_user(regs->trap, &sc->gp_regs[PT_TRAP]); + +This means we can be in the kernel with an arbitrary regs->trap value. + +Although that's not immediately problematic, there is a risk we could +trigger one of the uses of CHECK_FULL_REGS(): + + #define CHECK_FULL_REGS(regs) BUG_ON(regs->trap & 1) + +It can also cause us to unnecessarily save non-volatile GPRs again in +save_nvgprs(), which shouldn't be problematic but is still wrong. + +It's also possible it could trick the syscall restart machinery, which +relies on regs->trap not being == 0xc00 (see 9a81c16b5275 ("powerpc: +fix double syscall restarts")), though I haven't been able to make +that happen. + +Finally it doesn't match the behaviour of the non-TM case, in +restore_sigcontext() which zeroes regs->trap. + +So change restore_tm_sigcontexts() to zero regs->trap. + +This was discovered while testing Nick's upcoming rewrite of the +syscall entry path. In that series the call to save_nvgprs() prior to +signal handling (do_notify_resume()) is removed, which leaves the +low-bit of regs->trap uncleared which can then trigger the FULL_REGS() +WARNs in setup_tm_sigcontexts(). + +Fixes: 2b0a576d15e0 ("powerpc: Add new transactional memory state to the signal context") +Cc: stable@vger.kernel.org # v3.9+ +Signed-off-by: Michael Ellerman +Link: https://lore.kernel.org/r/20200401023836.3286664-1-mpe@ellerman.id.au +Acked-by: Michal Suchanek +--- + arch/powerpc/kernel/signal_64.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/arch/powerpc/kernel/signal_64.c b/arch/powerpc/kernel/signal_64.c +index 84ed2e77ef9c..adfde59cf4ba 100644 +--- a/arch/powerpc/kernel/signal_64.c ++++ b/arch/powerpc/kernel/signal_64.c +@@ -473,8 +473,10 @@ static long restore_tm_sigcontexts(struct task_struct *tsk, + err |= __get_user(tsk->thread.ckpt_regs.ccr, + &sc->gp_regs[PT_CCR]); + ++ /* Don't allow userspace to set the trap value */ ++ regs->trap = 0; ++ + /* These regs are not checkpointed; they can go in 'regs'. */ +- err |= __get_user(regs->trap, &sc->gp_regs[PT_TRAP]); + err |= __get_user(regs->dar, &sc->gp_regs[PT_DAR]); + err |= __get_user(regs->dsisr, &sc->gp_regs[PT_DSISR]); + err |= __get_user(regs->result, &sc->gp_regs[PT_RESULT]); +-- +2.23.0 + diff --git a/patches.suse/powerpc-64s-Fix-section-mismatch-warnings-from-boot-.patch b/patches.suse/powerpc-64s-Fix-section-mismatch-warnings-from-boot-.patch new file mode 100644 index 0000000..6294f8e --- /dev/null +++ b/patches.suse/powerpc-64s-Fix-section-mismatch-warnings-from-boot-.patch @@ -0,0 +1,116 @@ +From 6eeb9b3b9ce588f14a697737a30d0702b5a20293 Mon Sep 17 00:00:00 2001 +From: Michael Ellerman +Date: Tue, 25 Feb 2020 14:13:28 +1100 +Subject: [PATCH] powerpc/64s: Fix section mismatch warnings from boot code + +References: bsc#1148868 +Patch-mainline: v5.7-rc1 +Git-commit: 6eeb9b3b9ce588f14a697737a30d0702b5a20293 + +We currently have two section mismatch warnings: + + The function __boot_from_prom() references + the function __init prom_init(). + + The function start_here_common() references + the function __init start_kernel(). + +The warnings are correct, we do have branches from non-init code into +init code, which is freed after boot. But we don't expect to ever +execute any of that early boot code after boot, if we did that would +be a bug. In particular calling into OF after boot would be fatal +because OF is no longer resident. + +So for now fix the warnings by marking the relevant functions as +__REF, which puts them in the ".ref.text" section. + +This causes some reordering of the functions in the final link: + + @@ -217,10 +217,9 @@ + c00000000000b088 t generic_secondary_common_init + c00000000000b124 t __mmu_off + c00000000000b14c t __start_initialization_multiplatform + -c00000000000b1ac t __boot_from_prom + -c00000000000b1ec t __after_prom_start + -c00000000000b260 t p_end + -c00000000000b27c T copy_and_flush + +c00000000000b1ac t __after_prom_start + +c00000000000b220 t p_end + +c00000000000b23c T copy_and_flush + c00000000000b300 T __secondary_start + c00000000000b300 t copy_to_here + c00000000000b344 t start_secondary_prolog + @@ -228,8 +227,9 @@ + c00000000000b36c t enable_64b_mode + c00000000000b388 T relative_toc + c00000000000b3a8 t p_toc + -c00000000000b3b0 t start_here_common + -c00000000000b3d0 t start_here_multiplatform + +c00000000000b3b0 t __boot_from_prom + +c00000000000b3f0 t start_here_multiplatform + +c00000000000b480 t start_here_common + c00000000000b880 T system_call_common + c00000000000b974 t system_call + c00000000000b9dc t system_call_exit + +In particular __boot_from_prom moves after copy_to_here, which means +it's not copied to zero in the first stage of copy of the kernel to +zero. + +But that's OK, because we only call __boot_from_prom before we do the +copy, so it makes no difference when it's copied. The call sequence +is: + __start + -> __start_initialization_multiplatform + -> __boot_from_prom + -> __start + -> __start_initialization_multiplatform + -> __after_prom_start + -> copy_and_flush + -> copy_and_flush (relocated to 0) + -> start_here_multiplatform + -> early_setup + +Reported-by: Mauricio Faria de Oliveira +Reported-by: Roman Bolshakov +Signed-off-by: Michael Ellerman +Link: https://lore.kernel.org/r/20200225031328.14676-1-mpe@ellerman.id.au +Acked-by: Michal Suchanek +--- + arch/powerpc/kernel/head_64.S | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +--- a/arch/powerpc/kernel/head_64.S ++++ b/arch/powerpc/kernel/head_64.S +@@ -536,6 +536,7 @@ __start_initialization_multiplatform: + b __after_prom_start + #endif /* CONFIG_PPC_BOOK3E */ + ++__REF + __boot_from_prom: + #ifdef CONFIG_PPC_OF_BOOT_TRAMPOLINE + /* Save parameters */ +@@ -573,6 +574,7 @@ __boot_from_prom: + /* We never return. We also hit that trap if trying to boot + * from OF while CONFIG_PPC_OF_BOOT_TRAMPOLINE isn't selected */ + trap ++ .previous + + __after_prom_start: + #ifdef CONFIG_RELOCATABLE +@@ -976,7 +978,6 @@ start_here_multiplatform: + RFI + b . /* prevent speculative execution */ + +- .previous + /* This is where all platforms converge execution */ + + start_here_common: +@@ -999,6 +1000,7 @@ start_here_common: + + /* Not reached */ + BUG_OPCODE ++ .previous + + /* + * We put a few things here that have to be page-aligned. diff --git a/patches.suse/powerpc-64s-radix-Fix-memory-hotplug-section-page-ta.patch b/patches.suse/powerpc-64s-radix-Fix-memory-hotplug-section-page-ta.patch index e2ed9ce..e567348 100644 --- a/patches.suse/powerpc-64s-radix-Fix-memory-hotplug-section-page-ta.patch +++ b/patches.suse/powerpc-64s-radix-Fix-memory-hotplug-section-page-ta.patch @@ -1,4 +1,4 @@ -From 980b5a1456759e51b3e236f973623ee69aa222df Mon Sep 17 00:00:00 2001 +From 8f51e3929470942e6a8744061254fdeef646cd36 Mon Sep 17 00:00:00 2001 From: Nicholas Piggin Date: Wed, 24 Jul 2019 18:46:34 +1000 Subject: [PATCH] powerpc/64s/radix: Fix memory hotplug section page table @@ -32,18 +32,14 @@ Acked-by: Michal Suchanek 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/powerpc/mm/pgtable-radix.c b/arch/powerpc/mm/pgtable-radix.c -index 08d8e6b0614d..ecd6d082c9e8 100644 --- a/arch/powerpc/mm/pgtable-radix.c +++ b/arch/powerpc/mm/pgtable-radix.c -@@ -804,7 +804,7 @@ static void remove_pagetable(unsigned long start, unsigned long end) +@@ -808,7 +808,7 @@ static void __meminit remove_pagetable(u - int __ref radix__create_section_mapping(unsigned long start, unsigned long end) + int __meminit radix__create_section_mapping(unsigned long start, unsigned long end) { - return create_physical_mapping(start, end); + return create_physical_mapping(__pa(start), __pa(end)); } - int radix__remove_section_mapping(unsigned long start, unsigned long end) --- -2.23.0 - + int __meminit radix__remove_section_mapping(unsigned long start, unsigned long end) diff --git a/patches.suse/powerpc-avoid-adjusting-memory_limit-for-capture-ker.patch b/patches.suse/powerpc-avoid-adjusting-memory_limit-for-capture-ker.patch deleted file mode 100644 index fb9bc09..0000000 --- a/patches.suse/powerpc-avoid-adjusting-memory_limit-for-capture-ker.patch +++ /dev/null @@ -1,105 +0,0 @@ -From 5189c44bcdcc903120a3a793c4de78066dfc9c00 Mon Sep 17 00:00:00 2001 -Message-Id: <5189c44bcdcc903120a3a793c4de78066dfc9c00.1582043081.git.msuchanek@suse.de> -In-Reply-To: -From: Hari Bathini -Date: Fri, 28 Jun 2019 00:51:19 +0530 -Subject: [PATCH rebased 2/2] powerpc: avoid adjusting memory_limit for capture - kernel memory reservation - -Patch-mainline: submitted https://patchwork.ozlabs.org/patch/1240173/ -References: bsc#1140025 ltc#176086 - -Currently, if memory_limit is specified and it overlaps with memory to -be reserved for capture kernel, memory_limit is adjusted to accommodate -capture kernel. With memory reservation for capture kernel moved later -(after enforcing memory limit), this adjustment no longer holds water. -So, avoid adjusting memory_limit and error out instead. - -Signed-off-by: Hari Bathini -Acked-by: Michal Suchanek ---- - arch/powerpc/kernel/fadump.c | 16 ---------------- - arch/powerpc/kernel/machine_kexec.c | 22 +++++++++++----------- - 2 files changed, 11 insertions(+), 27 deletions(-) - -diff --git a/arch/powerpc/kernel/fadump.c b/arch/powerpc/kernel/fadump.c -index 4eab972..a784695 100644 ---- a/arch/powerpc/kernel/fadump.c -+++ b/arch/powerpc/kernel/fadump.c -@@ -476,22 +476,6 @@ int __init fadump_reserve_mem(void) - #endif - } - -- /* -- * Calculate the memory boundary. -- * If memory_limit is less than actual memory boundary then reserve -- * the memory for fadump beyond the memory_limit and adjust the -- * memory_limit accordingly, so that the running kernel can run with -- * specified memory_limit. -- */ -- if (memory_limit && memory_limit < memblock_end_of_DRAM()) { -- size = get_fadump_area_size(); -- if ((memory_limit + size) < memblock_end_of_DRAM()) -- memory_limit += size; -- else -- memory_limit = memblock_end_of_DRAM(); -- printk(KERN_INFO "Adjusted memory_limit for firmware-assisted" -- " dump, now %#016llx\n", memory_limit); -- } - if (memory_limit) - memory_boundary = memory_limit; - else -diff --git a/arch/powerpc/kernel/machine_kexec.c b/arch/powerpc/kernel/machine_kexec.c -index c4ed328..fc5533b 100644 ---- a/arch/powerpc/kernel/machine_kexec.c -+++ b/arch/powerpc/kernel/machine_kexec.c -@@ -125,10 +125,8 @@ void __init reserve_crashkernel(void) - crashk_res.end = crash_base + crash_size - 1; - } - -- if (crashk_res.end == crashk_res.start) { -- crashk_res.start = crashk_res.end = 0; -- return; -- } -+ if (crashk_res.end == crashk_res.start) -+ goto error_out; - - /* We might have got these values via the command line or the - * device tree, either way sanitise them now. */ -@@ -170,15 +168,13 @@ void __init reserve_crashkernel(void) - if (overlaps_crashkernel(__pa(_stext), _end - _stext)) { - printk(KERN_WARNING - "Crash kernel can not overlap current kernel\n"); -- crashk_res.start = crashk_res.end = 0; -- return; -+ goto error_out; - } - - /* Crash kernel trumps memory limit */ - if (memory_limit && memory_limit <= crashk_res.end) { -- memory_limit = crashk_res.end + 1; -- printk("Adjusted memory limit for crashkernel, now 0x%llx\n", -- memory_limit); -+ pr_err("Crash kernel size can't exceed memory_limit\n"); -+ goto error_out; - } - - printk(KERN_INFO "Reserving %ldMB of memory at %ldMB " -@@ -190,9 +186,13 @@ void __init reserve_crashkernel(void) - if (!memblock_is_region_memory(crashk_res.start, crash_size) || - memblock_reserve(crashk_res.start, crash_size)) { - pr_err("Failed to reserve memory for crashkernel!\n"); -- crashk_res.start = crashk_res.end = 0; -- return; -+ goto error_out; - } -+ -+ return; -+error_out: -+ crashk_res.start = crashk_res.end = 0; -+ return; - } - - int overlaps_crashkernel(unsigned long start, unsigned long size) - - diff --git a/patches.suse/powerpc-drmem-avoid-NULL-pointer-dereference-when-dr.patch b/patches.suse/powerpc-drmem-avoid-NULL-pointer-dereference-when-dr.patch new file mode 100644 index 0000000..6195ca4 --- /dev/null +++ b/patches.suse/powerpc-drmem-avoid-NULL-pointer-dereference-when-dr.patch @@ -0,0 +1,107 @@ +From a83836dbc53e96f13fec248ecc201d18e1e3111d Mon Sep 17 00:00:00 2001 +From: Libor Pechacek +Date: Fri, 31 Jan 2020 14:28:29 +0100 +Subject: [PATCH] powerpc/pseries: Avoid NULL pointer dereference when drmem is + unavailable + +References: bsc#1160659 +Patch-mainline: v5.7-rc1 +Git-commit: a83836dbc53e96f13fec248ecc201d18e1e3111d + +In guests without hotplugagble memory drmem structure is only zero +initialized. Trying to manipulate DLPAR parameters results in a crash. + + $ echo "memory add count 1" > /sys/kernel/dlpar + Oops: Kernel access of bad area, sig: 11 [#1] + LE PAGE_SIZE=64K MMU=Hash SMP NR_CPUS=2048 NUMA pSeries + ... + NIP: c0000000000ff294 LR: c0000000000ff248 CTR: 0000000000000000 + REGS: c0000000fb9d3880 TRAP: 0300 Tainted: G E (5.5.0-rc6-2-default) + MSR: 8000000000009033 CR: 28242428 XER: 20000000 + CFAR: c0000000009a6c10 DAR: 0000000000000010 DSISR: 40000000 IRQMASK: 0 + ... + NIP dlpar_memory+0x6e4/0xd00 + LR dlpar_memory+0x698/0xd00 + Call Trace: + dlpar_memory+0x698/0xd00 (unreliable) + handle_dlpar_errorlog+0xc0/0x190 + dlpar_store+0x198/0x4a0 + kobj_attr_store+0x30/0x50 + sysfs_kf_write+0x64/0x90 + kernfs_fop_write+0x1b0/0x290 + __vfs_write+0x3c/0x70 + vfs_write+0xd0/0x260 + ksys_write+0xdc/0x130 + system_call+0x5c/0x68 + +Taking closer look at the code, I can see that for_each_drmem_lmb is a +macro expanding into `for (lmb = &drmem_info->lmbs[0]; lmb <= +&drmem_info->lmbs[drmem_info->n_lmbs - 1]; lmb++)`. When drmem_info->lmbs +is NULL, the loop would iterate through the whole address range if it +weren't stopped by the NULL pointer dereference on the next line. + +This patch aligns for_each_drmem_lmb and for_each_drmem_lmb_in_range +macro behavior with the common C semantics, where the end marker does +not belong to the scanned range, and alters get_lmb_range() semantics. +As a side effect, the wraparound observed in the crash is prevented. + +Fixes: 6c6ea53725b3 ("powerpc/mm: Separate ibm, dynamic-memory data from DT format") +Cc: stable@vger.kernel.org # v4.16+ +Signed-off-by: Libor Pechacek +Signed-off-by: Michal Suchanek +Signed-off-by: Michael Ellerman +Link: https://lore.kernel.org/r/20200131132829.10281-1-msuchanek@suse.de +--- + arch/powerpc/include/asm/drmem.h | 4 ++-- + arch/powerpc/platforms/pseries/hotplug-memory.c | 8 ++++---- + 2 files changed, 6 insertions(+), 6 deletions(-) + +diff --git a/arch/powerpc/include/asm/drmem.h b/arch/powerpc/include/asm/drmem.h +index 3d76e1c388c2..28c3d936fdf3 100644 +--- a/arch/powerpc/include/asm/drmem.h ++++ b/arch/powerpc/include/asm/drmem.h +@@ -27,12 +27,12 @@ struct drmem_lmb_info { + extern struct drmem_lmb_info *drmem_info; + + #define for_each_drmem_lmb_in_range(lmb, start, end) \ +- for ((lmb) = (start); (lmb) <= (end); (lmb)++) ++ for ((lmb) = (start); (lmb) < (end); (lmb)++) + + #define for_each_drmem_lmb(lmb) \ + for_each_drmem_lmb_in_range((lmb), \ + &drmem_info->lmbs[0], \ +- &drmem_info->lmbs[drmem_info->n_lmbs - 1]) ++ &drmem_info->lmbs[drmem_info->n_lmbs]) + + /* + * The of_drconf_cell_v1 struct defines the layout of the LMB data +diff --git a/arch/powerpc/platforms/pseries/hotplug-memory.c b/arch/powerpc/platforms/pseries/hotplug-memory.c +index a4d40a3ceea3..fd22ec41c008 100644 +--- a/arch/powerpc/platforms/pseries/hotplug-memory.c ++++ b/arch/powerpc/platforms/pseries/hotplug-memory.c +@@ -223,7 +223,7 @@ static int get_lmb_range(u32 drc_index, int n_lmbs, + struct drmem_lmb **end_lmb) + { + struct drmem_lmb *lmb, *start, *end; +- struct drmem_lmb *last_lmb; ++ struct drmem_lmb *limit; + + start = NULL; + for_each_drmem_lmb(lmb) { +@@ -236,10 +236,10 @@ static int get_lmb_range(u32 drc_index, int n_lmbs, + if (!start) + return -EINVAL; + +- end = &start[n_lmbs - 1]; ++ end = &start[n_lmbs]; + +- last_lmb = &drmem_info->lmbs[drmem_info->n_lmbs - 1]; +- if (end > last_lmb) ++ limit = &drmem_info->lmbs[drmem_info->n_lmbs]; ++ if (end > limit) + return -EINVAL; + + *start_lmb = start; +-- +2.23.0 + diff --git a/patches.suse/powerpc-fix-hardware-PMU-exception-bug-on-PowerVM-co.patch b/patches.suse/powerpc-fix-hardware-PMU-exception-bug-on-PowerVM-co.patch new file mode 100644 index 0000000..38e4fdd --- /dev/null +++ b/patches.suse/powerpc-fix-hardware-PMU-exception-bug-on-PowerVM-co.patch @@ -0,0 +1,50 @@ +From fc37a1632d40c80c067eb1bc235139f5867a2667 Mon Sep 17 00:00:00 2001 +From: "Desnes A. Nunes do Rosario" +Date: Thu, 27 Feb 2020 10:47:15 -0300 +Subject: [PATCH] powerpc: fix hardware PMU exception bug on PowerVM + compatibility mode systems + +References: bsc#1056686 +Patch-mainline: v5.6-rc5 +Git-commit: fc37a1632d40c80c067eb1bc235139f5867a2667 + +PowerVM systems running compatibility mode on a few Power8 revisions are +still vulnerable to the hardware defect that loses PMU exceptions arriving +prior to a context switch. + +The software fix for this issue is enabled through the CPU_FTR_PMAO_BUG +cpu_feature bit, nevertheless this bit also needs to be set for PowerVM +compatibility mode systems. + +Fixes: 68f2f0d431d9ea4 ("powerpc: Add a cpu feature CPU_FTR_PMAO_BUG") +Signed-off-by: Desnes A. Nunes do Rosario +Reviewed-by: Leonardo Bras +Signed-off-by: Michael Ellerman +Link: https://lore.kernel.org/r/20200227134715.9715-1-desnesn@linux.ibm.com +Acked-by: Michal Suchanek +--- + arch/powerpc/kernel/cputable.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/arch/powerpc/kernel/cputable.c b/arch/powerpc/kernel/cputable.c +index e745abc5457a..245be4fafe13 100644 +--- a/arch/powerpc/kernel/cputable.c ++++ b/arch/powerpc/kernel/cputable.c +@@ -2193,11 +2193,13 @@ static struct cpu_spec * __init setup_cpu_spec(unsigned long offset, + * oprofile_cpu_type already has a value, then we are + * possibly overriding a real PVR with a logical one, + * and, in that case, keep the current value for +- * oprofile_cpu_type. ++ * oprofile_cpu_type. Futhermore, let's ensure that the ++ * fix for the PMAO bug is enabled on compatibility mode. + */ + if (old.oprofile_cpu_type != NULL) { + t->oprofile_cpu_type = old.oprofile_cpu_type; + t->oprofile_type = old.oprofile_type; ++ t->cpu_features |= old.cpu_features & CPU_FTR_PMAO_BUG; + } + } + +-- +2.23.0 + diff --git a/patches.suse/powerpc-kprobes-Ignore-traps-that-happened-in-real-m.patch b/patches.suse/powerpc-kprobes-Ignore-traps-that-happened-in-real-m.patch new file mode 100644 index 0000000..167c111 --- /dev/null +++ b/patches.suse/powerpc-kprobes-Ignore-traps-that-happened-in-real-m.patch @@ -0,0 +1,78 @@ +From 21f8b2fa3ca5b01f7a2b51b89ce97a3705a15aa0 Mon Sep 17 00:00:00 2001 +From: Christophe Leroy +Date: Tue, 18 Feb 2020 19:38:27 +0000 +Subject: [PATCH] powerpc/kprobes: Ignore traps that happened in real mode + +References: bsc#1065729 +Patch-mainline: v5.7-rc1 +Git-commit: 21f8b2fa3ca5b01f7a2b51b89ce97a3705a15aa0 + +When a program check exception happens while MMU translation is +disabled, following Oops happens in kprobe_handler() in the following +code: + + } else if (*addr != BREAKPOINT_INSTRUCTION) { + + BUG: Unable to handle kernel data access on read at 0x0000e268 + Faulting instruction address: 0xc000ec34 + Oops: Kernel access of bad area, sig: 11 [#1] + BE PAGE_SIZE=16K PREEMPT CMPC885 + Modules linked in: + CPU: 0 PID: 429 Comm: cat Not tainted 5.6.0-rc1-s3k-dev-00824-g84195dc6c58a #3267 + NIP: c000ec34 LR: c000ecd8 CTR: c019cab8 + REGS: ca4d3b58 TRAP: 0300 Not tainted (5.6.0-rc1-s3k-dev-00824-g84195dc6c58a) + MSR: 00001032 CR: 2a4d3c52 XER: 00000000 + DAR: 0000e268 DSISR: c0000000 + GPR00: c000b09c ca4d3c10 c66d0620 00000000 ca4d3c60 00000000 00009032 00000000 + GPR08: 00020000 00000000 c087de44 c000afe0 c66d0ad0 100d3dd6 fffffff3 00000000 + GPR16: 00000000 00000041 00000000 ca4d3d70 00000000 00000000 0000416d 00000000 + GPR24: 00000004 c53b6128 00000000 0000e268 00000000 c07c0000 c07bb6fc ca4d3c60 + NIP [c000ec34] kprobe_handler+0x128/0x290 + LR [c000ecd8] kprobe_handler+0x1cc/0x290 + Call Trace: + [ca4d3c30] [c000b09c] program_check_exception+0xbc/0x6fc + [ca4d3c50] [c000e43c] ret_from_except_full+0x0/0x4 + --- interrupt: 700 at 0xe268 + Instruction dump: + 913e0008 81220000 38600001 3929ffff 91220000 80010024 bb410008 7c0803a6 + 38210020 4e800020 38600000 4e800020 <813b0000> 6d2a7fe0 2f8a0008 419e0154 + ---[ end trace 5b9152d4cdadd06d ]--- + +kprobe is not prepared to handle events in real mode and functions +running in real mode should have been blacklisted, so kprobe_handler() +can safely bail out telling 'this trap is not mine' for any trap that +happened while in real-mode. + +If the trap happened with MSR_IR or MSR_DR cleared, return 0 +immediately. + +Reported-by: Larry Finger +Fixes: 6cc89bad60a6 ("powerpc/kprobes: Invoke handlers directly") +Cc: stable@vger.kernel.org # v4.10+ +Signed-off-by: Christophe Leroy +Reviewed-by: Masami Hiramatsu +Reviewed-by: Naveen N. Rao +Signed-off-by: Michael Ellerman +Link: https://lore.kernel.org/r/424331e2006e7291a1bfe40e7f3fa58825f565e1.1582054578.git.christophe.leroy@c-s.fr +Acked-by: Michal Suchanek +--- + arch/powerpc/kernel/kprobes.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/arch/powerpc/kernel/kprobes.c b/arch/powerpc/kernel/kprobes.c +index 3aaff3365134..81efb605113e 100644 +--- a/arch/powerpc/kernel/kprobes.c ++++ b/arch/powerpc/kernel/kprobes.c +@@ -264,6 +264,9 @@ int kprobe_handler(struct pt_regs *regs) + if (user_mode(regs)) + return 0; + ++ if (!(regs->msr & MSR_IR) || !(regs->msr & MSR_DR)) ++ return 0; ++ + /* + * We don't want to be preempted for the entire + * duration of kprobe processing +-- +2.23.0 + diff --git a/patches.suse/powerpc-mm-Fix-section-mismatch-warning-in-stop_mach.patch b/patches.suse/powerpc-mm-Fix-section-mismatch-warning-in-stop_mach.patch new file mode 100644 index 0000000..2bfcb8b --- /dev/null +++ b/patches.suse/powerpc-mm-Fix-section-mismatch-warning-in-stop_mach.patch @@ -0,0 +1,144 @@ +From bde709a70884bfc790da6fbc4467c91e8d41c51b Mon Sep 17 00:00:00 2001 +From: Mauricio Faria de Oliveira +Date: Fri, 9 Mar 2018 17:45:58 -0300 +Subject: [PATCH] powerpc/mm: Fix section mismatch warning in + stop_machine_change_mapping() + +References: bsc#1148868 +Patch-mainline: v4.17-rc1 +Git-commit: bde709a70884bfc790da6fbc4467c91e8d41c51b + +Fix the warning messages for stop_machine_change_mapping(), and a number +of other affected functions in its call chain. + +All modified functions are under CONFIG_MEMORY_HOTPLUG, so __meminit +is okay (keeps them / does not discard them). + +Boot-tested on powernv/power9/radix-mmu and pseries/power8/hash-mmu. + + $ make -j$(nproc) CONFIG_DEBUG_SECTION_MISMATCH=y vmlinux + ... + MODPOST vmlinux.o + WARNING: vmlinux.o(.text+0x6b130): Section mismatch in reference from the function stop_machine_change_mapping() to the function .meminit.text:create_physical_mapping() + The function stop_machine_change_mapping() references + the function __meminit create_physical_mapping(). + This is often because stop_machine_change_mapping lacks a __meminit + annotation or the annotation of create_physical_mapping is wrong. + + WARNING: vmlinux.o(.text+0x6b13c): Section mismatch in reference from the function stop_machine_change_mapping() to the function .meminit.text:create_physical_mapping() + The function stop_machine_change_mapping() references + the function __meminit create_physical_mapping(). + This is often because stop_machine_change_mapping lacks a __meminit + annotation or the annotation of create_physical_mapping is wrong. + ... + +Signed-off-by: Mauricio Faria de Oliveira +Acked-by: Balbir Singh +Signed-off-by: Michael Ellerman +Acked-by: Michal Suchanek +--- + arch/powerpc/mm/mem.c | 4 ++-- + arch/powerpc/mm/pgtable-book3s64.c | 4 ++-- + arch/powerpc/mm/pgtable-radix.c | 12 ++++++------ + 3 files changed, 10 insertions(+), 10 deletions(-) + +--- a/arch/powerpc/mm/mem.c ++++ b/arch/powerpc/mm/mem.c +@@ -126,7 +126,7 @@ int __weak remove_section_mapping(unsign + return -ENODEV; + } + +-int arch_add_memory(int nid, u64 start, u64 size, struct vmem_altmap *altmap, ++int __meminit arch_add_memory(int nid, u64 start, u64 size, struct vmem_altmap *altmap, + bool want_memblock) + { + unsigned long start_pfn = start >> PAGE_SHIFT; +@@ -147,7 +147,7 @@ int arch_add_memory(int nid, u64 start, + } + + #ifdef CONFIG_MEMORY_HOTREMOVE +-int arch_remove_memory(u64 start, u64 size, struct vmem_altmap *altmap) ++int __meminit arch_remove_memory(u64 start, u64 size, struct vmem_altmap *altmap) + { + unsigned long start_pfn = start >> PAGE_SHIFT; + unsigned long nr_pages = size >> PAGE_SHIFT; +diff --git a/arch/powerpc/mm/pgtable-book3s64.c b/arch/powerpc/mm/pgtable-book3s64.c +index 422e80253a33..bd6ca74acf9e 100644 +--- a/arch/powerpc/mm/pgtable-book3s64.c ++++ b/arch/powerpc/mm/pgtable-book3s64.c +@@ -155,7 +155,7 @@ void mmu_cleanup_all(void) + } + + #ifdef CONFIG_MEMORY_HOTPLUG +-int create_section_mapping(unsigned long start, unsigned long end) ++int __meminit create_section_mapping(unsigned long start, unsigned long end) + { + if (radix_enabled()) + return radix__create_section_mapping(start, end); +@@ -163,7 +163,7 @@ int create_section_mapping(unsigned long start, unsigned long end) + return hash__create_section_mapping(start, end); + } + +-int remove_section_mapping(unsigned long start, unsigned long end) ++int __meminit remove_section_mapping(unsigned long start, unsigned long end) + { + if (radix_enabled()) + return radix__remove_section_mapping(start, end); +diff --git a/arch/powerpc/mm/pgtable-radix.c b/arch/powerpc/mm/pgtable-radix.c +index 2e10a964e290..ab9db0afd2c8 100644 +--- a/arch/powerpc/mm/pgtable-radix.c ++++ b/arch/powerpc/mm/pgtable-radix.c +@@ -695,7 +695,7 @@ struct change_mapping_params { + unsigned long aligned_end; + }; + +-static int stop_machine_change_mapping(void *data) ++static int __meminit stop_machine_change_mapping(void *data) + { + struct change_mapping_params *params = + (struct change_mapping_params *)data; +@@ -742,7 +742,7 @@ static void remove_pte_table(pte_t *pte_start, unsigned long addr, + /* + * clear the pte and potentially split the mapping helper + */ +-static void split_kernel_mapping(unsigned long addr, unsigned long end, ++static void __meminit split_kernel_mapping(unsigned long addr, unsigned long end, + unsigned long size, pte_t *pte) + { + unsigned long mask = ~(size - 1); +@@ -835,7 +835,7 @@ static void remove_pud_table(pud_t *pud_start, unsigned long addr, + } + } + +-static void remove_pagetable(unsigned long start, unsigned long end) ++static void __meminit remove_pagetable(unsigned long start, unsigned long end) + { + unsigned long addr, next; + pud_t *pud_base; +@@ -863,12 +863,12 @@ static void remove_pagetable(unsigned long start, unsigned long end) + radix__flush_tlb_kernel_range(start, end); + } + +-int __ref radix__create_section_mapping(unsigned long start, unsigned long end) ++int __meminit radix__create_section_mapping(unsigned long start, unsigned long end) + { + return create_physical_mapping(start, end); + } + +-int radix__remove_section_mapping(unsigned long start, unsigned long end) ++int __meminit radix__remove_section_mapping(unsigned long start, unsigned long end) + { + remove_pagetable(start, end); + return 0; +@@ -888,7 +888,7 @@ int __meminit radix__vmemmap_create_mapping(unsigned long start, + } + + #ifdef CONFIG_MEMORY_HOTPLUG +-void radix__vmemmap_remove_mapping(unsigned long start, unsigned long page_size) ++void __meminit radix__vmemmap_remove_mapping(unsigned long start, unsigned long page_size) + { + remove_pagetable(start, start + page_size); + } +-- +2.23.0 + diff --git a/patches.suse/powerpc-pseries-Fix-of_read_drc_info_cell-to-point-a.patch b/patches.suse/powerpc-pseries-Fix-of_read_drc_info_cell-to-point-a.patch new file mode 100644 index 0000000..af828d3 --- /dev/null +++ b/patches.suse/powerpc-pseries-Fix-of_read_drc_info_cell-to-point-a.patch @@ -0,0 +1,59 @@ +From c5e76fa05b2df519b9f08571cc57e623c1569faa Mon Sep 17 00:00:00 2001 +From: Tyrel Datwyler +Date: Fri, 6 Mar 2020 20:45:47 -0600 +Subject: [PATCH] powerpc/pseries: Fix of_read_drc_info_cell() to point at next + record + +References: bsc#1165980 ltc#183834 +Patch-mainline: v5.7-rc1 +Git-commit: c5e76fa05b2df519b9f08571cc57e623c1569faa + +The expectation is that when calling of_read_drc_info_cell() +repeatedly to parse multiple drc-info records that the in/out curval +parameter points at the start of the next record on return. However, +the current behavior has curval still pointing at the final value of +the record just parsed. The result of which is that if the +ibm,drc-info property contains multiple properties the parsed value +of the drc_type for any record after the first has the power_domain +value of the previous record appended to the type string. + +eg: observed the following 0xffffffff prepended to PHB + + drc-info: type: \xff\xff\xff\xffPHB, prefix: PHB , index_start: 0x20000001 + drc-info: suffix_start: 1, sequential_elems: 3072, sequential_inc: 1 + drc-info: power-domain: 0xffffffff, last_index: 0x20000c00 + +In practice PHBs are the only type of connector in the ibm,drc-info +property that has multiple records. So, it breaks PHB hotplug, but by +chance not PCI, CPU, slot, or memory because they happen to only ever +be a single record. + +Fix by incrementing curval past the power_domain value to point at +drc_type string of next record. + +Fixes: e83636ac3334 ("pseries/drc-info: Search DRC properties for CPU indexes") +Signed-off-by: Tyrel Datwyler +Acked-by: Nathan Lynch +Signed-off-by: Michael Ellerman +Link: https://lore.kernel.org/r/20200307024547.5748-1-tyreld@linux.ibm.com +Acked-by: Michal Suchanek +--- + arch/powerpc/platforms/pseries/of_helpers.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/arch/powerpc/platforms/pseries/of_helpers.c b/arch/powerpc/platforms/pseries/of_helpers.c +index 66dfd8256712..23241c71ef37 100644 +--- a/arch/powerpc/platforms/pseries/of_helpers.c ++++ b/arch/powerpc/platforms/pseries/of_helpers.c +@@ -88,7 +88,7 @@ int of_read_drc_info_cell(struct property **prop, const __be32 **curval, + return -EINVAL; + + /* Should now know end of current entry */ +- (*curval) = (void *)p2; ++ (*curval) = (void *)(++p2); + data->last_drc_index = data->drc_index_start + + ((data->num_sequential_elems - 1) * data->sequential_inc); + +-- +2.23.0 + diff --git a/patches.suse/powerpc-pseries-Track-LMB-nid-instead-of-using-devic.patch b/patches.suse/powerpc-pseries-Track-LMB-nid-instead-of-using-devic.patch index 50b4452..2cd6d39 100644 --- a/patches.suse/powerpc-pseries-Track-LMB-nid-instead-of-using-devic.patch +++ b/patches.suse/powerpc-pseries-Track-LMB-nid-instead-of-using-devic.patch @@ -1,4 +1,4 @@ -From 1ff2c601b5456fc30bc044e060a9de3b42a3780c Mon Sep 17 00:00:00 2001 +From b2d3b5ee66f2a04a918cc043cec0c9ed3de58f40 Mon Sep 17 00:00:00 2001 From: Nathan Fontenot Date: Tue, 2 Oct 2018 10:35:59 -0500 Subject: [PATCH] powerpc/pseries: Track LMB nid instead of using device tree @@ -53,13 +53,13 @@ Signed-off-by: Nathan Fontenot Signed-off-by: Michael Ellerman Acked-by: Michal Suchanek --- - arch/powerpc/include/asm/drmem.h | 26 +++++++++++++++++++ - arch/powerpc/mm/drmem.c | 6 ++++- - .../platforms/pseries/hotplug-memory.c | 19 +++++++------- - 3 files changed, 41 insertions(+), 10 deletions(-) + arch/powerpc/include/asm/drmem.h | 21 +++++++++++++++++++ + arch/powerpc/mm/drmem.c | 6 +++++- + .../platforms/pseries/hotplug-memory.c | 17 +++++++-------- + 3 files changed, 34 insertions(+), 10 deletions(-) diff --git a/arch/powerpc/include/asm/drmem.h b/arch/powerpc/include/asm/drmem.h -index ce242b9ea8c6..7f3279b014db 100644 +index 7c1d8e74b25d..7f3279b014db 100644 --- a/arch/powerpc/include/asm/drmem.h +++ b/arch/powerpc/include/asm/drmem.h @@ -17,6 +17,9 @@ struct drmem_lmb { @@ -72,15 +72,10 @@ index ce242b9ea8c6..7f3279b014db 100644 }; struct drmem_lmb_info { -@@ -99,4 +102,27 @@ void __init walk_drmem_lmbs_early(unsigned long node, - void (*func)(struct drmem_lmb *, const __be32 **)); - #endif +@@ -104,4 +107,22 @@ static inline void invalidate_lmb_associativity_index(struct drmem_lmb *lmb) + lmb->aa_index = 0xffffffff; + } -+static inline void invalidate_lmb_associativity_index(struct drmem_lmb *lmb) -+{ -+ lmb->aa_index = 0xffffffff; -+} -+ +#ifdef CONFIG_MEMORY_HOTPLUG +static inline void lmb_set_nid(struct drmem_lmb *lmb) +{ @@ -101,10 +96,10 @@ index ce242b9ea8c6..7f3279b014db 100644 + #endif /* _ASM_POWERPC_LMB_H */ diff --git a/arch/powerpc/mm/drmem.c b/arch/powerpc/mm/drmem.c -index f03c19372a0f..cec5739f63d2 100644 +index 3f1803672c9b..641891df2046 100644 --- a/arch/powerpc/mm/drmem.c +++ b/arch/powerpc/mm/drmem.c -@@ -367,8 +367,10 @@ static void __init init_drmem_v1_lmbs(const __be32 *prop) +@@ -366,8 +366,10 @@ static void __init init_drmem_v1_lmbs(const __be32 *prop) if (!drmem_info->lmbs) return; @@ -116,7 +111,7 @@ index f03c19372a0f..cec5739f63d2 100644 } static void __init init_drmem_v2_lmbs(const __be32 *prop) -@@ -413,6 +415,8 @@ static void __init init_drmem_v2_lmbs(const __be32 *prop) +@@ -412,6 +414,8 @@ static void __init init_drmem_v2_lmbs(const __be32 *prop) lmb->aa_index = dr_cell.aa_index; lmb->flags = dr_cell.flags; @@ -126,10 +121,9 @@ index f03c19372a0f..cec5739f63d2 100644 } } diff --git a/arch/powerpc/platforms/pseries/hotplug-memory.c b/arch/powerpc/platforms/pseries/hotplug-memory.c -index c1578f54c626..fbb497cd4aa0 100644 --- a/arch/powerpc/platforms/pseries/hotplug-memory.c +++ b/arch/powerpc/platforms/pseries/hotplug-memory.c -@@ -411,7 +411,7 @@ static int dlpar_add_lmb(struct drmem_lmb *); +@@ -379,7 +379,7 @@ static int dlpar_add_lmb(struct drmem_lmb *); static int dlpar_remove_lmb(struct drmem_lmb *lmb) { unsigned long block_sz; @@ -138,7 +132,7 @@ index c1578f54c626..fbb497cd4aa0 100644 if (!lmb_is_removable(lmb)) return -EINVAL; -@@ -421,14 +421,16 @@ static int dlpar_remove_lmb(struct drmem_lmb *lmb) +@@ -389,14 +389,14 @@ static int dlpar_remove_lmb(struct drmem_lmb *lmb) return rc; block_sz = pseries_memory_block_size(); @@ -150,14 +144,12 @@ index c1578f54c626..fbb497cd4aa0 100644 /* Update memory regions for memory remove */ memblock_remove(lmb->base_addr, block_sz); - dlpar_remove_device_tree_lmb(lmb); + invalidate_lmb_associativity_index(lmb); + lmb_clear_nid(lmb); -+ lmb->flags &= ~DRCONF_MEM_ASSIGNED; -+ - return 0; - } + lmb->flags &= ~DRCONF_MEM_ASSIGNED; -@@ -683,7 +685,7 @@ static int dlpar_memory_remove_by_ic(u32 lmbs_to_remove, u32 drc_index) + return 0; +@@ -653,7 +653,7 @@ static int dlpar_memory_remove_by_ic(u32 lmbs_to_remove, u32 drc_index) static int dlpar_add_lmb(struct drmem_lmb *lmb) { unsigned long block_sz; @@ -166,7 +158,7 @@ index c1578f54c626..fbb497cd4aa0 100644 if (lmb->flags & DRCONF_MEM_ASSIGNED) return -EINVAL; -@@ -696,13 +698,11 @@ static int dlpar_add_lmb(struct drmem_lmb *lmb) +@@ -664,13 +664,11 @@ static int dlpar_add_lmb(struct drmem_lmb *lmb) return rc; } @@ -180,19 +172,19 @@ index c1578f54c626..fbb497cd4aa0 100644 - rc = add_memory(nid, lmb->base_addr, block_sz); + rc = add_memory(lmb->nid, lmb->base_addr, block_sz); if (rc) { - dlpar_remove_device_tree_lmb(lmb); + invalidate_lmb_associativity_index(lmb); return rc; -@@ -710,8 +710,9 @@ static int dlpar_add_lmb(struct drmem_lmb *lmb) +@@ -678,8 +676,9 @@ static int dlpar_add_lmb(struct drmem_lmb *lmb) rc = dlpar_online_lmb(lmb); if (rc) { - remove_memory(nid, lmb->base_addr, block_sz); + remove_memory(lmb->nid, lmb->base_addr, block_sz); - dlpar_remove_device_tree_lmb(lmb); + invalidate_lmb_associativity_index(lmb); + lmb_clear_nid(lmb); } else { lmb->flags |= DRCONF_MEM_ASSIGNED; } -- -2.19.2 +2.23.0 diff --git a/patches.suse/powerpc-pseries-ddw-Extend-upper-limit-for-huge-DMA-.patch b/patches.suse/powerpc-pseries-ddw-Extend-upper-limit-for-huge-DMA-.patch new file mode 100644 index 0000000..5dd156a --- /dev/null +++ b/patches.suse/powerpc-pseries-ddw-Extend-upper-limit-for-huge-DMA-.patch @@ -0,0 +1,59 @@ +From 54fc3c681ded9437e4548e2501dc1136b23cfa9a Mon Sep 17 00:00:00 2001 +From: Alexey Kardashevskiy +Date: Tue, 31 Mar 2020 12:23:38 +1100 +Subject: [PATCH] powerpc/pseries/ddw: Extend upper limit for huge DMA window + for persistent memory + +References: FATE#327775 bsc#1142685 ltc#179509 +Patch-mainline: v5.7-rc1 +Git-commit: 54fc3c681ded9437e4548e2501dc1136b23cfa9a + +Unlike normal memory ("memory" compatible type in the FDT), the +persistent memory ("ibm,pmemory" in the FDT) can be mapped anywhere in +the guest physical space and it can be used for DMA. + +In order to maintain 1:1 mapping via the huge DMA window, we need to +know the maximum physical address at the time of the window setup. So +far we've been looking at "memory" nodes but "ibm,pmemory" does not +have fixed addresses and the persistent memory may be mapped +afterwards. + +Since the persistent memory is still backed with page structs, use +MAX_PHYSMEM_BITS as the upper limit. + +This effectively disables huge DMA window in LPAR under pHyp if +persistent memory is present but this is the best we can do for the +moment. + +Signed-off-by: Alexey Kardashevskiy +Tested-by: Wen Xiong +Signed-off-by: Michael Ellerman +Link: https://lore.kernel.org/r/20200331012338.23773-1-aik@ozlabs.ru +Acked-by: Michal Suchanek +--- + arch/powerpc/platforms/pseries/iommu.c | 9 +++++++++ + 1 file changed, 9 insertions(+) + +diff --git a/arch/powerpc/platforms/pseries/iommu.c b/arch/powerpc/platforms/pseries/iommu.c +index 2e0a8eab5588..6d47b4a3ce39 100644 +--- a/arch/powerpc/platforms/pseries/iommu.c ++++ b/arch/powerpc/platforms/pseries/iommu.c +@@ -945,6 +945,15 @@ static phys_addr_t ddw_memory_hotplug_max(void) + phys_addr_t max_addr = memory_hotplug_max(); + struct device_node *memory; + ++ /* ++ * The "ibm,pmemory" can appear anywhere in the address space. ++ * Assuming it is still backed by page structs, set the upper limit ++ * for the huge DMA window as MAX_PHYSMEM_BITS. ++ */ ++ if (of_find_node_by_type(NULL, "ibm,pmemory")) ++ return (sizeof(phys_addr_t) * 8 <= MAX_PHYSMEM_BITS) ? ++ (phys_addr_t) -1 : (1ULL << MAX_PHYSMEM_BITS); ++ + for_each_node_by_type(memory, "memory") { + unsigned long start, size; + int n_mem_addr_cells, n_mem_size_cells, len; +-- +2.23.0 + diff --git a/patches.suse/powerpc-pseries-group-lmb-operation-and-memblock-s.patch b/patches.suse/powerpc-pseries-group-lmb-operation-and-memblock-s.patch new file mode 100644 index 0000000..c5bdb88 --- /dev/null +++ b/patches.suse/powerpc-pseries-group-lmb-operation-and-memblock-s.patch @@ -0,0 +1,95 @@ +From a235863387220d22de0b1b9e848ba6d872266a9d Mon Sep 17 00:00:00 2001 +From: Pingfan Liu +Date: Tue, 11 Feb 2020 10:59:41 +0800 +Subject: [PATCH 1/2] powerpc/pseries: group lmb operation and memblock's + +References: bsc#1165404 ltc#183498 +PAtch-mainline: submitted https://patchwork.ozlabs.org/patch/1236132/ + +This patch prepares for the incoming patch which swaps the order of KOBJ_ +uevent and dt's updating. + +It has no functional effect, just groups lmb operation and memblock's in +order to insert dt updating operation easily, and makes it easier to +review. + +Signed-off-by: Pingfan Liu +Cc: Michael Ellerman +Cc: Benjamin Herrenschmidt +Cc: Paul Mackerras +Cc: Hari Bathini +To: linuxppc-dev@lists.ozlabs.org +Cc: kexec@lists.infradead.org +Acked-by: Michal Suchanek +--- + .../platforms/pseries/hotplug-memory.c | 26 ++++++++++++------- + 1 file changed, 17 insertions(+), 9 deletions(-) + +diff --git a/arch/powerpc/platforms/pseries/hotplug-memory.c b/arch/powerpc/platforms/pseries/hotplug-memory.c +--- a/arch/powerpc/platforms/pseries/hotplug-memory.c ++++ b/arch/powerpc/platforms/pseries/hotplug-memory.c +@@ -377,7 +377,8 @@ static int dlpar_add_lmb(struct drmem_lmb *); + static int dlpar_remove_lmb(struct drmem_lmb *lmb) + { + unsigned long block_sz; +- int rc; ++ phys_addr_t base_addr; ++ int rc, nid; + + if (!lmb_is_removable(lmb)) + return -EINVAL; +@@ -386,17 +387,19 @@ static int dlpar_remove_lmb(struct drmem_lmb *lmb) + if (rc) + return rc; + ++ base_addr = lmb->base_addr; ++ nid = lmb->nid; + block_sz = pseries_memory_block_size(); + +- remove_memory(lmb->nid, lmb->base_addr, block_sz); +- +- /* Update memory regions for memory remove */ +- memblock_remove(lmb->base_addr, block_sz); +- + invalidate_lmb_associativity_index(lmb); + lmb_clear_nid(lmb); + lmb->flags &= ~DRCONF_MEM_ASSIGNED; + ++ remove_memory(nid, base_addr, block_sz); ++ ++ /* Update memory regions for memory remove */ ++ memblock_remove(base_addr, block_sz); ++ + return 0; + } + +@@ -663,6 +666,8 @@ static int dlpar_add_lmb(struct drmem_lmb *lmb) + } + + lmb_set_nid(lmb); ++ lmb->flags |= DRCONF_MEM_ASSIGNED; ++ + block_sz = memory_block_size_bytes(); + + /* Add the memory */ +@@ -674,11 +679,14 @@ static int dlpar_add_lmb(struct drmem_lmb *lmb) + + rc = dlpar_online_lmb(lmb); + if (rc) { +- remove_memory(lmb->nid, lmb->base_addr, block_sz); ++ int nid = lmb->nid; ++ phys_addr_t base_addr = lmb->base_addr; ++ + invalidate_lmb_associativity_index(lmb); + lmb_clear_nid(lmb); +- } else { +- lmb->flags |= DRCONF_MEM_ASSIGNED; ++ lmb->flags &= ~DRCONF_MEM_ASSIGNED; ++ ++ remove_memory(nid, base_addr, block_sz); + } + + return rc; +-- +2.23.0 + diff --git a/patches.suse/powerpc-pseries-iommu-Fix-set-but-not-used-values.patch b/patches.suse/powerpc-pseries-iommu-Fix-set-but-not-used-values.patch new file mode 100644 index 0000000..fb8a5ec --- /dev/null +++ b/patches.suse/powerpc-pseries-iommu-Fix-set-but-not-used-values.patch @@ -0,0 +1,93 @@ +From c05f57fdc34a3d00c9ee28a35772e9d11b5ce100 Mon Sep 17 00:00:00 2001 +From: Qian Cai +Date: Sat, 6 Apr 2019 22:48:08 -0400 +Subject: [PATCH] powerpc/pseries/iommu: Fix set but not used values + +References: FATE#327775 bsc#1142685 ltc#179509 +Patch-mainline: v5.2-rc1 +Git-commit: c05f57fdc34a3d00c9ee28a35772e9d11b5ce100 + +The commit b7d6bf4fdd47 ("powerpc/pseries/pci: Remove obsolete SW +invalidate") left 2 variables unused. + + arch/powerpc/platforms/pseries/iommu.c:108:17: warning: variable 'tces' set but not used + __be64 *tcep, *tces; + ^~~~ + + arch/powerpc/platforms/pseries/iommu.c:132:17: warning: variable 'tces' set but not used + __be64 *tcep, *tces; + ^~~~ + +Also, the commit 68c0449ea16d ("powerpc/pseries/iommu: Use memory@ +nodes in max RAM address calculation") set "ranges" in +ddw_memory_hotplug_max() but never use it. + + arch/powerpc/platforms/pseries/iommu.c: In function 'ddw_memory_hotplug_max': + arch/powerpc/platforms/pseries/iommu.c:948:7: warning: variable 'ranges' set but not used + int ranges, n_mem_addr_cells, n_mem_size_cells, len; + ^~~~~~ + +Signed-off-by: Qian Cai +Reviewed-by: Mukesh Ojha +Signed-off-by: Michael Ellerman +Acked-by: Michal Suchanek +--- + arch/powerpc/platforms/pseries/iommu.c | 13 +++++-------- + 1 file changed, 5 insertions(+), 8 deletions(-) + +diff --git a/arch/powerpc/platforms/pseries/iommu.c b/arch/powerpc/platforms/pseries/iommu.c +index 36eb1ddbac69..03bbb299320e 100644 +--- a/arch/powerpc/platforms/pseries/iommu.c ++++ b/arch/powerpc/platforms/pseries/iommu.c +@@ -105,7 +105,7 @@ static int tce_build_pSeries(struct iommu_table *tbl, long index, + unsigned long attrs) + { + u64 proto_tce; +- __be64 *tcep, *tces; ++ __be64 *tcep; + u64 rpn; + + proto_tce = TCE_PCI_READ; // Read allowed +@@ -113,7 +113,7 @@ static int tce_build_pSeries(struct iommu_table *tbl, long index, + if (direction != DMA_TO_DEVICE) + proto_tce |= TCE_PCI_WRITE; + +- tces = tcep = ((__be64 *)tbl->it_base) + index; ++ tcep = ((__be64 *)tbl->it_base) + index; + + while (npages--) { + /* can't move this out since we might cross MEMBLOCK boundary */ +@@ -129,9 +129,9 @@ static int tce_build_pSeries(struct iommu_table *tbl, long index, + + static void tce_free_pSeries(struct iommu_table *tbl, long index, long npages) + { +- __be64 *tcep, *tces; ++ __be64 *tcep; + +- tces = tcep = ((__be64 *)tbl->it_base) + index; ++ tcep = ((__be64 *)tbl->it_base) + index; + + while (npages--) + *(tcep++) = 0; +@@ -945,7 +945,7 @@ static phys_addr_t ddw_memory_hotplug_max(void) + + for_each_node_by_type(memory, "memory") { + unsigned long start, size; +- int ranges, n_mem_addr_cells, n_mem_size_cells, len; ++ int n_mem_addr_cells, n_mem_size_cells, len; + const __be32 *memcell_buf; + + memcell_buf = of_get_property(memory, "reg", &len); +@@ -955,9 +955,6 @@ static phys_addr_t ddw_memory_hotplug_max(void) + n_mem_addr_cells = of_n_addr_cells(memory); + n_mem_size_cells = of_n_size_cells(memory); + +- /* ranges in cell */ +- ranges = (len >> 2) / (n_mem_addr_cells + n_mem_size_cells); +- + start = of_read_number(memcell_buf, n_mem_addr_cells); + memcell_buf += n_mem_addr_cells; + size = of_read_number(memcell_buf, n_mem_size_cells); +-- +2.23.0 + diff --git a/patches.suse/powerpc-pseries-iommu-Use-memory-nodes-in-max-RAM-ad.patch b/patches.suse/powerpc-pseries-iommu-Use-memory-nodes-in-max-RAM-ad.patch new file mode 100644 index 0000000..1f1cbb9 --- /dev/null +++ b/patches.suse/powerpc-pseries-iommu-Use-memory-nodes-in-max-RAM-ad.patch @@ -0,0 +1,82 @@ +From 68c0449ea16d775e762b532afddb4d6a5f161877 Mon Sep 17 00:00:00 2001 +From: Alexey Kardashevskiy +Date: Wed, 19 Dec 2018 19:52:18 +1100 +Subject: [PATCH] powerpc/pseries/iommu: Use memory@ nodes in max RAM address + calculation + +References: FATE#327775 bsc#1142685 ltc#179509 +Patch-mainline: v5.0-rc1 +Git-commit: 68c0449ea16d775e762b532afddb4d6a5f161877 + +We might have memory@ nodes with "linux,usable-memory" set to zero +(for example, to replicate powernv's behaviour for GPU coherent memory) +which means that the memory needs an extra initialization but since +it can be used afterwards, the pseries platform will try mapping it +for DMA so the DMA window needs to cover those memory regions too; +if the window cannot cover new memory regions, the memory onlining fails. + +This walks through the memory nodes to find the highest RAM address to +let a huge DMA window cover that too in case this memory gets onlined +later. + +Signed-off-by: Alexey Kardashevskiy +Signed-off-by: Michael Ellerman +Acked-by: Michal Suchanek +--- + arch/powerpc/platforms/pseries/iommu.c | 33 +++++++++++++++++++++++++- + 1 file changed, 32 insertions(+), 1 deletion(-) + +diff --git a/arch/powerpc/platforms/pseries/iommu.c b/arch/powerpc/platforms/pseries/iommu.c +index 06f02960b439..cbcc8ceddd87 100644 +--- a/arch/powerpc/platforms/pseries/iommu.c ++++ b/arch/powerpc/platforms/pseries/iommu.c +@@ -964,6 +964,37 @@ struct failed_ddw_pdn { + + static LIST_HEAD(failed_ddw_pdn_list); + ++static phys_addr_t ddw_memory_hotplug_max(void) ++{ ++ phys_addr_t max_addr = memory_hotplug_max(); ++ struct device_node *memory; ++ ++ for_each_node_by_type(memory, "memory") { ++ unsigned long start, size; ++ int ranges, n_mem_addr_cells, n_mem_size_cells, len; ++ const __be32 *memcell_buf; ++ ++ memcell_buf = of_get_property(memory, "reg", &len); ++ if (!memcell_buf || len <= 0) ++ continue; ++ ++ n_mem_addr_cells = of_n_addr_cells(memory); ++ n_mem_size_cells = of_n_size_cells(memory); ++ ++ /* ranges in cell */ ++ ranges = (len >> 2) / (n_mem_addr_cells + n_mem_size_cells); ++ ++ start = of_read_number(memcell_buf, n_mem_addr_cells); ++ memcell_buf += n_mem_addr_cells; ++ size = of_read_number(memcell_buf, n_mem_size_cells); ++ memcell_buf += n_mem_size_cells; ++ ++ max_addr = max_t(phys_addr_t, max_addr, start + size); ++ } ++ ++ return max_addr; ++} ++ + /* + * If the PE supports dynamic dma windows, and there is space for a table + * that can map all pages in a linear offset, then setup such a table, +@@ -1053,7 +1084,7 @@ static u64 enable_ddw(struct pci_dev *dev, struct device_node *pdn) + } + /* verify the window * number of ptes will map the partition */ + /* check largest block * page size > max memory hotplug addr */ +- max_addr = memory_hotplug_max(); ++ max_addr = ddw_memory_hotplug_max(); + if (query.largest_available_block < (max_addr >> page_shift)) { + dev_dbg(&dev->dev, "can't map partition max 0x%llx with %u " + "%llu-sized pages\n", max_addr, query.largest_available_block, +-- +2.23.0 + diff --git a/patches.suse/powerpc-pseries-memory-hotplug-Fix-return-value-type.patch b/patches.suse/powerpc-pseries-memory-hotplug-Fix-return-value-type.patch index cbdad24..ba0bb76 100644 --- a/patches.suse/powerpc-pseries-memory-hotplug-Fix-return-value-type.patch +++ b/patches.suse/powerpc-pseries-memory-hotplug-Fix-return-value-type.patch @@ -13,8 +13,6 @@ update_lmb_associativity_index(), but find_aa_index() may return -1 when dlpar_clone_property() fails. So change find_aa_index() to return a bool, which indicates whether 'aa_index' was found or not. -[in 4.12 there is additional indirection so need to pass aa_index twice] - Fixes: c05a5a40969e ("powerpc/pseries: Dynamic add entires to associativity lookup array") Signed-off-by: YueHaibing Reviewed-by: Nathan Fontenot nfont@linux.vnet.ibm.com> @@ -25,9 +23,11 @@ Acked-by: Michal Suchanek .../platforms/pseries/hotplug-memory.c | 61 +++++++++---------- 1 file changed, 28 insertions(+), 33 deletions(-) +diff --git a/arch/powerpc/platforms/pseries/hotplug-memory.c b/arch/powerpc/platforms/pseries/hotplug-memory.c +index 9a15d39995e5..2b796da822c2 100644 --- a/arch/powerpc/platforms/pseries/hotplug-memory.c +++ b/arch/powerpc/platforms/pseries/hotplug-memory.c -@@ -101,11 +101,12 @@ static struct property *dlpar_clone_prop +@@ -101,11 +101,12 @@ static struct property *dlpar_clone_property(struct property *prop, return new_prop; } @@ -44,7 +44,7 @@ Acked-by: Michal Suchanek int aa_arrays, aa_array_entries, aa_array_sz; int i, index; -@@ -121,75 +122,68 @@ static u32 find_aa_index(struct device_n +@@ -121,46 +122,39 @@ static u32 find_aa_index(struct device_node *dr_node, aa_array_entries = be32_to_cpu(assoc_arrays[1]); aa_array_sz = aa_array_entries * sizeof(u32); @@ -71,16 +71,26 @@ Acked-by: Michal Suchanek - return -1; - - assoc_arrays = new_prop->value; -- ++ new_prop_size = ala_prop->length + aa_array_sz; ++ new_prop = dlpar_clone_property(ala_prop, new_prop_size); ++ if (!new_prop) ++ return false; + - /* increment the number of entries in the lookup array */ - assoc_arrays[0] = cpu_to_be32(aa_arrays + 1); -- ++ assoc_arrays = new_prop->value; + - /* copy the new associativity into the lookup array */ - index = aa_arrays * aa_array_entries + 2; - memcpy(&assoc_arrays[index], &lmb_assoc[1], aa_array_sz); -- ++ /* increment the number of entries in the lookup array */ ++ assoc_arrays[0] = cpu_to_be32(aa_arrays + 1); + - of_update_property(dr_node, new_prop); -- ++ /* copy the new associativity into the lookup array */ ++ index = aa_arrays * aa_array_entries + 2; ++ memcpy(&assoc_arrays[index], &lmb_assoc[1], aa_array_sz); + - /* - * The associativity lookup array index for this lmb is - * number of entries - 1 since we added its associativity @@ -88,23 +98,9 @@ Acked-by: Michal Suchanek - */ - aa_index = be32_to_cpu(assoc_arrays[0]) - 1; - } -+ new_prop_size = ala_prop->length + aa_array_sz; -+ new_prop = dlpar_clone_property(ala_prop, new_prop_size); -+ if (!new_prop) -+ return false; -+ -+ assoc_arrays = new_prop->value; -+ -+ /* increment the number of entries in the lookup array */ -+ assoc_arrays[0] = cpu_to_be32(aa_arrays + 1); ++ of_update_property(dr_node, new_prop); - return aa_index; -+ /* copy the new associativity into the lookup array */ -+ index = aa_arrays * aa_array_entries + 2; -+ memcpy(&assoc_arrays[index], &lmb_assoc[1], aa_array_sz); -+ -+ of_update_property(dr_node, new_prop); -+ + /* + * The associativity lookup array index for this lmb is + * number of entries - 1 since we added its associativity @@ -114,73 +110,29 @@ Acked-by: Michal Suchanek + return true; } --static u32 lookup_lmb_associativity_index(struct drmem_lmb *lmb) -+static u32 lookup_lmb_associativity_index(struct drmem_lmb *lmb, u32 *aa_index) - { - struct device_node *parent, *lmb_node, *dr_node; + static int update_lmb_associativity_index(struct drmem_lmb *lmb) +@@ -169,6 +163,7 @@ static int update_lmb_associativity_index(struct drmem_lmb *lmb) struct property *ala_prop; const u32 *lmb_assoc; -- u32 aa_index; + u32 aa_index; + bool found; parent = of_find_node_by_path("/"); if (!parent) -- return -ENODEV; -+ return false; - - lmb_node = dlpar_configure_connector(cpu_to_be32(lmb->drc_index), - parent); - of_node_put(parent); - if (!lmb_node) -- return -EINVAL; -+ return false; - - lmb_assoc = of_get_property(lmb_node, "ibm,associativity", NULL); - if (!lmb_assoc) { - dlpar_free_cc_nodes(lmb_node); -- return -ENODEV; -+ return false; - } - - dr_node = of_find_node_by_path("/ibm,dynamic-reconfiguration-memory"); - if (!dr_node) { - dlpar_free_cc_nodes(lmb_node); -- return -ENODEV; -+ return false; - } - - ala_prop = of_find_property(dr_node, "ibm,associativity-lookup-arrays", -@@ -197,26 +191,27 @@ static u32 lookup_lmb_associativity_inde - if (!ala_prop) { - of_node_put(dr_node); - dlpar_free_cc_nodes(lmb_node); -- return -ENODEV; -+ return false; +@@ -200,11 +195,11 @@ static int update_lmb_associativity_index(struct drmem_lmb *lmb) + return -ENODEV; } - aa_index = find_aa_index(dr_node, ala_prop, lmb_assoc); -+ found = find_aa_index(dr_node, ala_prop, lmb_assoc, aa_index); ++ found = find_aa_index(dr_node, ala_prop, lmb_assoc, &aa_index); dlpar_free_cc_nodes(lmb_node); -- return aa_index; -+ return found; - } - static int dlpar_add_device_tree_lmb(struct drmem_lmb *lmb) - { - int rc, aa_index; -+ bool found; - - lmb->flags |= DRCONF_MEM_ASSIGNED; - -- aa_index = lookup_lmb_associativity_index(lmb); - if (aa_index < 0) { -+ found = lookup_lmb_associativity_index(lmb, &aa_index); + if (!found) { - pr_err("Couldn't find associativity index for drc index %x\n", - lmb->drc_index); -- return aa_index; -+ return -ENODEV; + pr_err("Could not find LMB associativity\n"); + return -1; } - - lmb->aa_index = aa_index; +-- +2.23.0 + diff --git a/patches.suse/powerpc-pseries-memory-hotplug-Only-update-DT-once-p.patch b/patches.suse/powerpc-pseries-memory-hotplug-Only-update-DT-once-p.patch new file mode 100644 index 0000000..b74827e --- /dev/null +++ b/patches.suse/powerpc-pseries-memory-hotplug-Only-update-DT-once-p.patch @@ -0,0 +1,167 @@ +From 063b8b1251fd069f3740339fca56119d218f11ba Mon Sep 17 00:00:00 2001 +From: Nathan Fontenot +Date: Fri, 20 Apr 2018 15:29:48 -0500 +Subject: [PATCH] powerpc/pseries/memory-hotplug: Only update DT once per + memory DLPAR request + +References: bsc#1165404 ltc#183498 +Patch-mainline: v4.20-rc1 +Git-commit: 063b8b1251fd069f3740339fca56119d218f11ba + +The updates to powerpc numa and memory hotplug code now use the +in-kernel LMB array instead of the device tree. This change allows the +pseries memory DLPAR code to only update the device tree once after +successfully handling a DLPAR request. + +Prior to the in-kernel LMB array, the numa code looked up the affinity +for memory being added in the device tree, the code now looks this up +in the LMB array. This change means the memory hotplug code can just +update the affinity for an LMB in the LMB array instead of updating +the device tree. + +This also provides a savings in kernel memory. When updating the +device tree old properties are never free'ed since there is no +usecount on properties. This behavior leads to a new copy of the +property being allocated every time a LMB is added or removed (i.e. a +request to add 100 LMBs creates 100 new copies of the property). With +this update only a single new property is created when a DLPAR request +completes successfully. + +Signed-off-by: Nathan Fontenot +Signed-off-by: Michael Ellerman +Acked-by: Michal Suchanek +--- + arch/powerpc/include/asm/drmem.h | 5 ++ + .../platforms/pseries/hotplug-memory.c | 55 ++++++------------- + 2 files changed, 21 insertions(+), 39 deletions(-) + +diff --git a/arch/powerpc/include/asm/drmem.h b/arch/powerpc/include/asm/drmem.h +index ce242b9ea8c6..7c1d8e74b25d 100644 +--- a/arch/powerpc/include/asm/drmem.h ++++ b/arch/powerpc/include/asm/drmem.h +@@ -99,4 +99,9 @@ void __init walk_drmem_lmbs_early(unsigned long node, + void (*func)(struct drmem_lmb *, const __be32 **)); + #endif + ++static inline void invalidate_lmb_associativity_index(struct drmem_lmb *lmb) ++{ ++ lmb->aa_index = 0xffffffff; ++} ++ + #endif /* _ASM_POWERPC_LMB_H */ +diff --git a/arch/powerpc/platforms/pseries/hotplug-memory.c b/arch/powerpc/platforms/pseries/hotplug-memory.c +index c1578f54c626..9a15d39995e5 100644 +--- a/arch/powerpc/platforms/pseries/hotplug-memory.c ++++ b/arch/powerpc/platforms/pseries/hotplug-memory.c +@@ -163,7 +163,7 @@ static u32 find_aa_index(struct device_node *dr_node, + return aa_index; + } + +-static u32 lookup_lmb_associativity_index(struct drmem_lmb *lmb) ++static int update_lmb_associativity_index(struct drmem_lmb *lmb) + { + struct device_node *parent, *lmb_node, *dr_node; + struct property *ala_prop; +@@ -203,43 +203,14 @@ static u32 lookup_lmb_associativity_index(struct drmem_lmb *lmb) + aa_index = find_aa_index(dr_node, ala_prop, lmb_assoc); + + dlpar_free_cc_nodes(lmb_node); +- return aa_index; +-} +- +-static int dlpar_add_device_tree_lmb(struct drmem_lmb *lmb) +-{ +- int rc, aa_index; +- +- lmb->flags |= DRCONF_MEM_ASSIGNED; + +- aa_index = lookup_lmb_associativity_index(lmb); + if (aa_index < 0) { +- pr_err("Couldn't find associativity index for drc index %x\n", +- lmb->drc_index); +- return aa_index; ++ pr_err("Could not find LMB associativity\n"); ++ return -1; + } + + lmb->aa_index = aa_index; +- +- rtas_hp_event = true; +- rc = drmem_update_dt(); +- rtas_hp_event = false; +- +- return rc; +-} +- +-static int dlpar_remove_device_tree_lmb(struct drmem_lmb *lmb) +-{ +- int rc; +- +- lmb->flags &= ~DRCONF_MEM_ASSIGNED; +- lmb->aa_index = 0xffffffff; +- +- rtas_hp_event = true; +- rc = drmem_update_dt(); +- rtas_hp_event = false; +- +- return rc; ++ return 0; + } + + static struct memory_block *lmb_to_memblock(struct drmem_lmb *lmb) +@@ -428,7 +399,9 @@ static int dlpar_remove_lmb(struct drmem_lmb *lmb) + /* Update memory regions for memory remove */ + memblock_remove(lmb->base_addr, block_sz); + +- dlpar_remove_device_tree_lmb(lmb); ++ invalidate_lmb_associativity_index(lmb); ++ lmb->flags &= ~DRCONF_MEM_ASSIGNED; ++ + return 0; + } + +@@ -688,10 +661,8 @@ static int dlpar_add_lmb(struct drmem_lmb *lmb) + if (lmb->flags & DRCONF_MEM_ASSIGNED) + return -EINVAL; + +- rc = dlpar_add_device_tree_lmb(lmb); ++ rc = update_lmb_associativity_index(lmb); + if (rc) { +- pr_err("Couldn't update device tree for drc index %x\n", +- lmb->drc_index); + dlpar_release_drc(lmb->drc_index); + return rc; + } +@@ -704,14 +675,14 @@ static int dlpar_add_lmb(struct drmem_lmb *lmb) + /* Add the memory */ + rc = add_memory(nid, lmb->base_addr, block_sz); + if (rc) { +- dlpar_remove_device_tree_lmb(lmb); ++ invalidate_lmb_associativity_index(lmb); + return rc; + } + + rc = dlpar_online_lmb(lmb); + if (rc) { + remove_memory(nid, lmb->base_addr, block_sz); +- dlpar_remove_device_tree_lmb(lmb); ++ invalidate_lmb_associativity_index(lmb); + } else { + lmb->flags |= DRCONF_MEM_ASSIGNED; + } +@@ -958,6 +929,12 @@ int dlpar_memory(struct pseries_hp_errorlog *hp_elog) + break; + } + ++ if (!rc) { ++ rtas_hp_event = true; ++ rc = drmem_update_dt(); ++ rtas_hp_event = false; ++ } ++ + unlock_device_hotplug(); + return rc; + } +-- +2.23.0 + diff --git a/patches.suse/powerpc-pseries-update-device-tree-before-ejecting-h.patch b/patches.suse/powerpc-pseries-update-device-tree-before-ejecting-h.patch new file mode 100644 index 0000000..edc5a70 --- /dev/null +++ b/patches.suse/powerpc-pseries-update-device-tree-before-ejecting-h.patch @@ -0,0 +1,108 @@ +From 9ae86aa5d7e10e5587a13f6ff29dfe26f115d238 Mon Sep 17 00:00:00 2001 +From: Pingfan Liu +Date: Tue, 11 Feb 2020 10:59:42 +0800 +Subject: [PATCH 2/2] powerpc/pseries: update device tree before ejecting + hotplug uevents + +References: bsc#1165404 ltc#183498 +Patch-mainline: submitted https://patchwork.ozlabs.org/patch/1236133/ + +A bug is observed on pseries by taking the following steps on rhel: +-1. drmgr -c mem -r -q 5 +-2. echo c > /proc/sysrq-trigger + +And then, the failure looks like: +kdump: saving to /sysroot//var/crash/127.0.0.1-2020-01-16-02:06:14/ +kdump: saving vmcore-dmesg.txt +kdump: saving vmcore-dmesg.txt complete +kdump: saving vmcore + Checking for memory holes : [ 0.0 %] / Checking for memory holes : [100.0 %] | Excluding unnecessary pages : [100.0 %] \ Copying data : [ 0.3 %] - eta: 38s[ 44.337636] hash-mmu: mm: Hashing failure ! EA=0x7fffba400000 access=0x8000000000000004 current=makedumpfile +[ 44.337663] hash-mmu: trap=0x300 vsid=0x13a109c ssize=1 base psize=2 psize 2 pte=0xc000000050000504 +[ 44.337677] hash-mmu: mm: Hashing failure ! EA=0x7fffba400000 access=0x8000000000000004 current=makedumpfile +[ 44.337692] hash-mmu: trap=0x300 vsid=0x13a109c ssize=1 base psize=2 psize 2 pte=0xc000000050000504 +[ 44.337708] makedumpfile[469]: unhandled signal 7 at 00007fffba400000 nip 00007fffbbc4d7fc lr 000000011356ca3c code 2 +[ 44.338548] Core dump to |/bin/false pipe failed +/lib/kdump-lib-initramfs.sh: line 98: 469 Bus error $CORE_COLLECTOR /proc/vmcore $_mp/$KDUMP_PATH/$HOST_IP-$DATEDIR/vmcore-incomplete +kdump: saving vmcore failed + +* Root cause * + After analyzing, it turns out that in the current implementation, +when hot-removing lmb, the KOBJ_REMOVE event ejects before the dt updating as +the code remove_memory() comes before drmem_update_dt(). + +>From a viewpoint of listener and publisher, the publisher notifies the +listener before data is ready. This introduces a problem where udev +launches kexec-tools (due to KOBJ_REMOVE) and loads a stale dt before +updating. And in capture kernel, makedumpfile will access the memory based +on the stale dt info, and hit a SIGBUS error due to an un-existed lmb. + +* Fix * + In order to fix this issue, update dt before remove_memory(), and +accordingly the same rule in hot-add path. + +This will introduce extra dt updating payload for each involved lmb when hotplug. +But it should be fine since drmem_update_dt() is memory based operation and +hotplug is not a hot path. + +Signed-off-by: Pingfan Liu +Cc: Michael Ellerman +Cc: Benjamin Herrenschmidt +Cc: Paul Mackerras +Cc: Hari Bathini +To: linuxppc-dev@lists.ozlabs.org +Cc: kexec@lists.infradead.org +Tested-by: Hari Bathini +Acked-by: Michal Suchanek +--- + arch/powerpc/platforms/pseries/hotplug-memory.c | 15 +++++++++------ + 1 file changed, 9 insertions(+), 6 deletions(-) + +diff --git a/arch/powerpc/platforms/pseries/hotplug-memory.c b/arch/powerpc/platforms/pseries/hotplug-memory.c +--- a/arch/powerpc/platforms/pseries/hotplug-memory.c ++++ b/arch/powerpc/platforms/pseries/hotplug-memory.c +@@ -394,6 +394,9 @@ static int dlpar_remove_lmb(struct drmem_lmb *lmb) + invalidate_lmb_associativity_index(lmb); + lmb_clear_nid(lmb); + lmb->flags &= ~DRCONF_MEM_ASSIGNED; ++ rtas_hp_event = true; ++ drmem_update_dt(); ++ rtas_hp_event = false; + + remove_memory(nid, base_addr, block_sz); + +@@ -667,6 +670,9 @@ static int dlpar_add_lmb(struct drmem_lmb *lmb) + + lmb_set_nid(lmb); + lmb->flags |= DRCONF_MEM_ASSIGNED; ++ rtas_hp_event = true; ++ drmem_update_dt(); ++ rtas_hp_event = false; + + block_sz = memory_block_size_bytes(); + +@@ -685,6 +691,9 @@ static int dlpar_add_lmb(struct drmem_lmb *lmb) + invalidate_lmb_associativity_index(lmb); + lmb_clear_nid(lmb); + lmb->flags &= ~DRCONF_MEM_ASSIGNED; ++ rtas_hp_event = true; ++ drmem_update_dt(); ++ rtas_hp_event = false; + + remove_memory(nid, base_addr, block_sz); + } +@@ -941,12 +950,6 @@ int dlpar_memory(struct pseries_hp_errorlog *hp_elog) + break; + } + +- if (!rc) { +- rtas_hp_event = true; +- rc = drmem_update_dt(); +- rtas_hp_event = false; +- } +- + unlock_device_hotplug(); + return rc; + } +-- +2.23.0 + diff --git a/patches.suse/powerpc-reserve-memory-for-capture-kernel-after-huge.patch b/patches.suse/powerpc-reserve-memory-for-capture-kernel-after-huge.patch deleted file mode 100644 index b8cf2ec..0000000 --- a/patches.suse/powerpc-reserve-memory-for-capture-kernel-after-huge.patch +++ /dev/null @@ -1,60 +0,0 @@ -From f0e3acbcd3ba16d06d4f3e51b90655c69004768c Mon Sep 17 00:00:00 2001 -Message-Id: -From: Hari Bathini -Date: Fri, 28 Jun 2019 00:51:09 +0530 -Subject: [PATCH rebased 1/2] powerpc: reserve memory for capture kernel after - hugepages init - -Patch-mainline: submitted https://patchwork.ozlabs.org/patch/1240173/ -References: bsc#1140025 ltc#176086 - -Sometimes, memory reservation for KDump/FADump can overlap with memory -marked for hugepages. This overlap leads to error, hang in KDump case -and copy error reported by f/w in case of FADump, while trying to -capture dump. Report error while setting up memory for the capture -kernel instead of running into issues while capturing dump, by moving -KDump/FADump reservation below MMU early init and failing gracefully -when hugepages memory overlaps with capture kernel memory. - -Signed-off-by: Hari Bathini -Acked-by: Michal Suchanek ---- - arch/powerpc/kernel/prom.c | 16 ++++++++-------- - 1 file changed, 8 insertions(+), 8 deletions(-) - -diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c -index 7159e79..454e19cf 100644 ---- a/arch/powerpc/kernel/prom.c -+++ b/arch/powerpc/kernel/prom.c -@@ -731,14 +731,6 @@ void __init early_init_devtree(void *params) - if (PHYSICAL_START > MEMORY_START) - memblock_reserve(MEMORY_START, 0x8000); - reserve_kdump_trampoline(); --#ifdef CONFIG_FA_DUMP -- /* -- * If we fail to reserve memory for firmware-assisted dump then -- * fallback to kexec based kdump. -- */ -- if (fadump_reserve_mem() == 0) --#endif -- reserve_crashkernel(); - early_reserve_mem(); - - /* Ensure that total memory size is page-aligned. */ -@@ -777,6 +769,14 @@ void __init early_init_devtree(void *params) - #endif - - mmu_early_init_devtree(); -+#ifdef CONFIG_FA_DUMP -+ /* -+ * If we fail to reserve memory for firmware-assisted dump then -+ * fallback to kexec based kdump. -+ */ -+ if (fadump_reserve_mem() == 0) -+#endif -+ reserve_crashkernel(); - - #ifdef CONFIG_PPC_POWERNV - /* Scan and build the list of machine check recoverable ranges */ - - diff --git a/patches.suse/powerpc-smp-Use-nid-as-fallback-for-package_id.patch b/patches.suse/powerpc-smp-Use-nid-as-fallback-for-package_id.patch new file mode 100644 index 0000000..416ac6d --- /dev/null +++ b/patches.suse/powerpc-smp-Use-nid-as-fallback-for-package_id.patch @@ -0,0 +1,151 @@ +From a05f0e5be4e81e4977d3f92aaf7688ee0cb7d5db Mon Sep 17 00:00:00 2001 +From: Srikar Dronamraju +Date: Wed, 29 Jan 2020 19:21:21 +0530 +Subject: [PATCH] powerpc/smp: Use nid as fallback for package_id + +References: bsc#1165813 ltc#184091 +Patch-mainline: v5.7-rc1 +Git-commit: a05f0e5be4e81e4977d3f92aaf7688ee0cb7d5db + +package_id is to match cores that are part of the same chip. On +PowerNV machines, package_id defaults to chip_id. However ibm,chip_id +property is not present in device-tree of PowerVM LPARs. Hence lscpu +output shows one core per socket and multiple cores. + +To overcome this, use nid as the package_id on PowerVM LPARs. + +Before the patch: + + Architecture: ppc64le + Byte Order: Little Endian + CPU(s): 128 + On-line CPU(s) list: 0-127 + Thread(s) per core: 8 + Core(s) per socket: 1 <---------------------- + Socket(s): 16 <---------------------- + NUMA node(s): 2 + Model: 2.2 (pvr 004e 0202) + Model name: POWER9 (architected), altivec supported + Hypervisor vendor: pHyp + Virtualization type: para + L1d cache: 32K + L1i cache: 32K + L2 cache: 512K + L3 cache: 10240K + NUMA node0 CPU(s): 0-63 + NUMA node1 CPU(s): 64-127 + # + # cat /sys/devices/system/cpu/cpu0/topology/physical_package_id + -1 + +After the patch: + + Architecture: ppc64le + Byte Order: Little Endian + CPU(s): 128 + On-line CPU(s) list: 0-127 + Thread(s) per core: 8 <--------------------- + Core(s) per socket: 8 <--------------------- + Socket(s): 2 + NUMA node(s): 2 + Model: 2.2 (pvr 004e 0202) + Model name: POWER9 (architected), altivec supported + Hypervisor vendor: pHyp + Virtualization type: para + L1d cache: 32K + L1i cache: 32K + L2 cache: 512K + L3 cache: 10240K + NUMA node0 CPU(s): 0-63 + NUMA node1 CPU(s): 64-127 + # + # cat /sys/devices/system/cpu/cpu0/topology/physical_package_id + 0 + +Now lscpu output is more in line with the system configuration. + +Signed-off-by: Srikar Dronamraju +[mpe: Use pkg_id instead of ppid, tweak change log and comment] +Signed-off-by: Michael Ellerman +Link: https://lore.kernel.org/r/20200129135121.24617-1-srikar@linux.vnet.ibm.com +Acked-by: Michal Suchanek +--- + arch/powerpc/include/asm/topology.h | 6 ++++++ + arch/powerpc/kernel/smp.c | 30 ++++++++++++++++++++++++++--- + 2 files changed, 33 insertions(+), 3 deletions(-) + +diff --git a/arch/powerpc/include/asm/topology.h b/arch/powerpc/include/asm/topology.h +index 2f7e1ea5089e..e2e1ccd4a18d 100644 +--- a/arch/powerpc/include/asm/topology.h ++++ b/arch/powerpc/include/asm/topology.h +@@ -134,7 +134,13 @@ static inline void shared_proc_topology_init(void) {} + #ifdef CONFIG_PPC64 + #include + ++#ifdef CONFIG_PPC_SPLPAR ++int get_physical_package_id(int cpu); ++#define topology_physical_package_id(cpu) (get_physical_package_id(cpu)) ++#else + #define topology_physical_package_id(cpu) (cpu_to_chip_id(cpu)) ++#endif ++ + #define topology_sibling_cpumask(cpu) (per_cpu(cpu_sibling_map, cpu)) + #define topology_core_cpumask(cpu) (per_cpu(cpu_core_map, cpu)) + #define topology_core_id(cpu) (cpu_to_core_id(cpu)) +diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c +index ea6adbf6a221..f68cde82bdf3 100644 +--- a/arch/powerpc/kernel/smp.c ++++ b/arch/powerpc/kernel/smp.c +@@ -1185,10 +1185,34 @@ static inline void add_cpu_to_smallcore_masks(int cpu) + } + } + ++int get_physical_package_id(int cpu) ++{ ++ int pkg_id = cpu_to_chip_id(cpu); ++ ++#ifdef CONFIG_PPC_SPLPAR ++ /* ++ * If the platform is PowerNV or Guest on KVM, ibm,chip-id is ++ * defined. Hence we would return the chip-id as the result of ++ * get_physical_package_id. ++ */ ++ if (pkg_id == -1 && firmware_has_feature(FW_FEATURE_LPAR)) { ++ struct device_node *np = of_get_cpu_node(cpu, NULL); ++ ++ if (np) { ++ pkg_id = of_node_to_nid(np); ++ of_node_put(np); ++ } ++ } ++#endif /* CONFIG_PPC_SPLPAR */ ++ ++ return pkg_id; ++} ++EXPORT_SYMBOL_GPL(get_physical_package_id); ++ + static void add_cpu_to_masks(int cpu) + { + int first_thread = cpu_first_thread_sibling(cpu); +- int chipid = cpu_to_chip_id(cpu); ++ int pkg_id = get_physical_package_id(cpu); + int i; + + /* +@@ -1217,11 +1241,11 @@ static void add_cpu_to_masks(int cpu) + for_each_cpu(i, cpu_l2_cache_mask(cpu)) + set_cpus_related(cpu, i, cpu_core_mask); + +- if (chipid == -1) ++ if (pkg_id == -1) + return; + + for_each_cpu(i, cpu_online_mask) +- if (cpu_to_chip_id(i) == chipid) ++ if (get_physical_package_id(i) == pkg_id) + set_cpus_related(cpu, i, cpu_core_mask); + } + +-- +2.23.0 + diff --git a/patches.suse/powerpc-vmlinux.lds-Explicitly-retain-.gnu.hash.patch b/patches.suse/powerpc-vmlinux.lds-Explicitly-retain-.gnu.hash.patch new file mode 100644 index 0000000..7f530f3 --- /dev/null +++ b/patches.suse/powerpc-vmlinux.lds-Explicitly-retain-.gnu.hash.patch @@ -0,0 +1,48 @@ +From ead983604c5a390f1e3ce085945b60e82f08dbbe Mon Sep 17 00:00:00 2001 +From: Michael Ellerman +Date: Thu, 27 Feb 2020 15:59:32 +1100 +Subject: [PATCH] powerpc/vmlinux.lds: Explicitly retain .gnu.hash + +References: bsc#1148868 +Patch-mainline: v5.7-rc1 +Git-commit: ead983604c5a390f1e3ce085945b60e82f08dbbe + +Relocatable kernel builds produce a warning about .gnu.hash being an +orphan section: + + ld: warning: orphan section `.gnu.hash' from `linker stubs' being placed in section `.gnu.hash' + +If we try to discard it the build fails: + + ld -EL -m elf64lppc -pie --orphan-handling=warn --build-id -o + .tmp_vmlinux1 -T ./arch/powerpc/kernel/vmlinux.lds --whole-archive + arch/powerpc/kernel/head_64.o arch/powerpc/kernel/entry_64.o + ... + sound/built-in.a net/built-in.a virt/built-in.a --no-whole-archive + --start-group lib/lib.a --end-group + ld: could not find section .gnu.hash + +So add an entry to explicitly retain it, as we do for .hash. + +Signed-off-by: Michael Ellerman +Link: https://lore.kernel.org/r/20200227045933.22967-1-mpe@ellerman.id.au +Acked-by: Michal Suchanek +--- + arch/powerpc/kernel/vmlinux.lds.S | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/arch/powerpc/kernel/vmlinux.lds.S b/arch/powerpc/kernel/vmlinux.lds.S +index a32d478a7f41..b17d665a4e07 100644 +--- a/arch/powerpc/kernel/vmlinux.lds.S ++++ b/arch/powerpc/kernel/vmlinux.lds.S +@@ -256,6 +256,7 @@ SECTIONS + *(.dynamic) + } + .hash : AT(ADDR(.hash) - LOAD_OFFSET) { *(.hash) } ++ .gnu.hash : AT(ADDR(.gnu.hash) - LOAD_OFFSET) { *(.gnu.hash) } + .interp : AT(ADDR(.interp) - LOAD_OFFSET) { *(.interp) } + .rela.dyn : AT(ADDR(.rela.dyn) - LOAD_OFFSET) + { +-- +2.23.0 + diff --git a/patches.suse/powerpc-xive-Replace-msleep-x-with-msleep-OPAL_BUSY_.patch b/patches.suse/powerpc-xive-Replace-msleep-x-with-msleep-OPAL_BUSY_.patch new file mode 100644 index 0000000..08b9349 --- /dev/null +++ b/patches.suse/powerpc-xive-Replace-msleep-x-with-msleep-OPAL_BUSY_.patch @@ -0,0 +1,136 @@ +From 9c3250a127901c93b23723dc5859c71a0d068fb8 Mon Sep 17 00:00:00 2001 +From: Daniel Klamt +Date: Thu, 12 Jul 2018 00:03:04 +0200 +Subject: [PATCH] powerpc/xive: Replace msleep(x) with + msleep(OPAL_BUSY_DELAY_MS) + +References: bsc#1085030 +Patch-mainline: v4.19-rc1 +Git-commit: 9c3250a127901c93b23723dc5859c71a0d068fb8 + +Replace msleep(x) with with msleep(OPAL_BUSY_DELAY_MS) to document +these sleeps are to wait for opal (firmware). + +Signed-off-by: Daniel Klamt +Signed-off-by: Bjoern Noetel +Signed-off-by: Michael Ellerman +Acked-by: Michal Suchanek +--- + arch/powerpc/sysdev/xive/native.c | 24 ++++++++++++------------ + 1 file changed, 12 insertions(+), 12 deletions(-) + +diff --git a/arch/powerpc/sysdev/xive/native.c b/arch/powerpc/sysdev/xive/native.c +index 311185b9960a..39ab5ad58297 100644 +--- a/arch/powerpc/sysdev/xive/native.c ++++ b/arch/powerpc/sysdev/xive/native.c +@@ -109,7 +109,7 @@ int xive_native_configure_irq(u32 hw_irq, u32 target, u8 prio, u32 sw_irq) + rc = opal_xive_set_irq_config(hw_irq, target, prio, sw_irq); + if (rc != OPAL_BUSY) + break; +- msleep(1); ++ msleep(OPAL_BUSY_DELAY_MS); + } + return rc == 0 ? 0 : -ENXIO; + } +@@ -163,7 +163,7 @@ int xive_native_configure_queue(u32 vp_id, struct xive_q *q, u8 prio, + rc = opal_xive_set_queue_info(vp_id, prio, qpage_phys, order, flags); + if (rc != OPAL_BUSY) + break; +- msleep(1); ++ msleep(OPAL_BUSY_DELAY_MS); + } + if (rc) { + pr_err("Error %lld setting queue for prio %d\n", rc, prio); +@@ -190,7 +190,7 @@ static void __xive_native_disable_queue(u32 vp_id, struct xive_q *q, u8 prio) + rc = opal_xive_set_queue_info(vp_id, prio, 0, 0, 0); + if (rc != OPAL_BUSY) + break; +- msleep(1); ++ msleep(OPAL_BUSY_DELAY_MS); + } + if (rc) + pr_err("Error %lld disabling queue for prio %d\n", rc, prio); +@@ -253,7 +253,7 @@ static int xive_native_get_ipi(unsigned int cpu, struct xive_cpu *xc) + for (;;) { + irq = opal_xive_allocate_irq(chip_id); + if (irq == OPAL_BUSY) { +- msleep(1); ++ msleep(OPAL_BUSY_DELAY_MS); + continue; + } + if (irq < 0) { +@@ -275,7 +275,7 @@ u32 xive_native_alloc_irq(void) + rc = opal_xive_allocate_irq(OPAL_XIVE_ANY_CHIP); + if (rc != OPAL_BUSY) + break; +- msleep(1); ++ msleep(OPAL_BUSY_DELAY_MS); + } + if (rc < 0) + return 0; +@@ -289,7 +289,7 @@ void xive_native_free_irq(u32 irq) + s64 rc = opal_xive_free_irq(irq); + if (rc != OPAL_BUSY) + break; +- msleep(1); ++ msleep(OPAL_BUSY_DELAY_MS); + } + } + EXPORT_SYMBOL_GPL(xive_native_free_irq); +@@ -305,7 +305,7 @@ static void xive_native_put_ipi(unsigned int cpu, struct xive_cpu *xc) + for (;;) { + rc = opal_xive_free_irq(xc->hw_ipi); + if (rc == OPAL_BUSY) { +- msleep(1); ++ msleep(OPAL_BUSY_DELAY_MS); + continue; + } + xc->hw_ipi = 0; +@@ -400,7 +400,7 @@ static void xive_native_setup_cpu(unsigned int cpu, struct xive_cpu *xc) + rc = opal_xive_set_vp_info(vp, OPAL_XIVE_VP_ENABLED, 0); + if (rc != OPAL_BUSY) + break; +- msleep(1); ++ msleep(OPAL_BUSY_DELAY_MS); + } + if (rc) { + pr_err("Failed to enable pool VP on CPU %d\n", cpu); +@@ -444,7 +444,7 @@ static void xive_native_teardown_cpu(unsigned int cpu, struct xive_cpu *xc) + rc = opal_xive_set_vp_info(vp, 0, 0); + if (rc != OPAL_BUSY) + break; +- msleep(1); ++ msleep(OPAL_BUSY_DELAY_MS); + } + } + +@@ -645,7 +645,7 @@ u32 xive_native_alloc_vp_block(u32 max_vcpus) + rc = opal_xive_alloc_vp_block(order); + switch (rc) { + case OPAL_BUSY: +- msleep(1); ++ msleep(OPAL_BUSY_DELAY_MS); + break; + case OPAL_XIVE_PROVISIONING: + if (!xive_native_provision_pages()) +@@ -687,7 +687,7 @@ int xive_native_enable_vp(u32 vp_id, bool single_escalation) + rc = opal_xive_set_vp_info(vp_id, flags, 0); + if (rc != OPAL_BUSY) + break; +- msleep(1); ++ msleep(OPAL_BUSY_DELAY_MS); + } + return rc ? -EIO : 0; + } +@@ -701,7 +701,7 @@ int xive_native_disable_vp(u32 vp_id) + rc = opal_xive_set_vp_info(vp_id, 0, 0); + if (rc != OPAL_BUSY) + break; +- msleep(1); ++ msleep(OPAL_BUSY_DELAY_MS); + } + return rc ? -EIO : 0; + } +-- +2.23.0 + diff --git a/patches.suse/powerpc-xive-Use-XIVE_BAD_IRQ-instead-of-zero-to-cat.patch b/patches.suse/powerpc-xive-Use-XIVE_BAD_IRQ-instead-of-zero-to-cat.patch new file mode 100644 index 0000000..a0709b3 --- /dev/null +++ b/patches.suse/powerpc-xive-Use-XIVE_BAD_IRQ-instead-of-zero-to-cat.patch @@ -0,0 +1,147 @@ +From b1a504a6500df50e83b701b7946b34fce27ad8a3 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?C=C3=A9dric=20Le=20Goater?= +Date: Fri, 6 Mar 2020 16:01:40 +0100 +Subject: [PATCH] powerpc/xive: Use XIVE_BAD_IRQ instead of zero to catch non + configured IPIs +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +References: bsc#1085030 +Patch-mainline: v5.7-rc1 +Git-commit: b1a504a6500df50e83b701b7946b34fce27ad8a3 + +When a CPU is brought up, an IPI number is allocated and recorded +under the XIVE CPU structure. Invalid IPI numbers are tracked with +interrupt number 0x0. + +On the PowerNV platform, the interrupt number space starts at 0x10 and +this works fine. However, on the sPAPR platform, it is possible to +allocate the interrupt number 0x0 and this raises an issue when CPU 0 +is unplugged. The XIVE spapr driver tracks allocated interrupt numbers +in a bitmask and it is not correctly updated when interrupt number 0x0 +is freed. It stays allocated and it is then impossible to reallocate. + +Fix by using the XIVE_BAD_IRQ value instead of zero on both platforms. + +Reported-by: David Gibson +Fixes: eac1e731b59e ("powerpc/xive: guest exploitation of the XIVE interrupt controller") +Cc: stable@vger.kernel.org # v4.14+ +Signed-off-by: Cédric Le Goater +Reviewed-by: David Gibson +Tested-by: David Gibson +Signed-off-by: Michael Ellerman +Link: https://lore.kernel.org/r/20200306150143.5551-2-clg@kaod.org +Acked-by: Michal Suchanek +--- + arch/powerpc/sysdev/xive/common.c | 12 +++--------- + arch/powerpc/sysdev/xive/native.c | 4 ++-- + arch/powerpc/sysdev/xive/spapr.c | 4 ++-- + arch/powerpc/sysdev/xive/xive-internal.h | 7 +++++++ + 4 files changed, 14 insertions(+), 13 deletions(-) + +diff --git a/arch/powerpc/sysdev/xive/common.c b/arch/powerpc/sysdev/xive/common.c +index 9651ca061828..0e918fe6a4ec 100644 +--- a/arch/powerpc/sysdev/xive/common.c ++++ b/arch/powerpc/sysdev/xive/common.c +@@ -68,13 +68,6 @@ static u32 xive_ipi_irq; + /* Xive state for each CPU */ + static DEFINE_PER_CPU(struct xive_cpu *, xive_cpu); + +-/* +- * A "disabled" interrupt should never fire, to catch problems +- * we set its logical number to this +- */ +-#define XIVE_BAD_IRQ 0x7fffffff +-#define XIVE_MAX_IRQ (XIVE_BAD_IRQ - 1) +- + /* An invalid CPU target */ + #define XIVE_INVALID_TARGET (-1) + +@@ -1150,7 +1143,7 @@ static int xive_setup_cpu_ipi(unsigned int cpu) + xc = per_cpu(xive_cpu, cpu); + + /* Check if we are already setup */ +- if (xc->hw_ipi != 0) ++ if (xc->hw_ipi != XIVE_BAD_IRQ) + return 0; + + /* Grab an IPI from the backend, this will populate xc->hw_ipi */ +@@ -1187,7 +1180,7 @@ static void xive_cleanup_cpu_ipi(unsigned int cpu, struct xive_cpu *xc) + /* Disable the IPI and free the IRQ data */ + + /* Already cleaned up ? */ +- if (xc->hw_ipi == 0) ++ if (xc->hw_ipi == XIVE_BAD_IRQ) + return; + + /* Mask the IPI */ +@@ -1343,6 +1336,7 @@ static int xive_prepare_cpu(unsigned int cpu) + if (np) + xc->chip_id = of_get_ibm_chip_id(np); + of_node_put(np); ++ xc->hw_ipi = XIVE_BAD_IRQ; + + per_cpu(xive_cpu, cpu) = xc; + } +diff --git a/arch/powerpc/sysdev/xive/native.c b/arch/powerpc/sysdev/xive/native.c +index 0ff6b739052c..50e1a8e02497 100644 +--- a/arch/powerpc/sysdev/xive/native.c ++++ b/arch/powerpc/sysdev/xive/native.c +@@ -312,7 +312,7 @@ static void xive_native_put_ipi(unsigned int cpu, struct xive_cpu *xc) + s64 rc; + + /* Free the IPI */ +- if (!xc->hw_ipi) ++ if (xc->hw_ipi == XIVE_BAD_IRQ) + return; + for (;;) { + rc = opal_xive_free_irq(xc->hw_ipi); +@@ -320,7 +320,7 @@ static void xive_native_put_ipi(unsigned int cpu, struct xive_cpu *xc) + msleep(OPAL_BUSY_DELAY_MS); + continue; + } +- xc->hw_ipi = 0; ++ xc->hw_ipi = XIVE_BAD_IRQ; + break; + } + } +diff --git a/arch/powerpc/sysdev/xive/spapr.c b/arch/powerpc/sysdev/xive/spapr.c +index 55dc61cb4867..3f15615712b5 100644 +--- a/arch/powerpc/sysdev/xive/spapr.c ++++ b/arch/powerpc/sysdev/xive/spapr.c +@@ -560,11 +560,11 @@ static int xive_spapr_get_ipi(unsigned int cpu, struct xive_cpu *xc) + + static void xive_spapr_put_ipi(unsigned int cpu, struct xive_cpu *xc) + { +- if (!xc->hw_ipi) ++ if (xc->hw_ipi == XIVE_BAD_IRQ) + return; + + xive_irq_bitmap_free(xc->hw_ipi); +- xc->hw_ipi = 0; ++ xc->hw_ipi = XIVE_BAD_IRQ; + } + #endif /* CONFIG_SMP */ + +diff --git a/arch/powerpc/sysdev/xive/xive-internal.h b/arch/powerpc/sysdev/xive/xive-internal.h +index 59cd366e7933..382980f4de2d 100644 +--- a/arch/powerpc/sysdev/xive/xive-internal.h ++++ b/arch/powerpc/sysdev/xive/xive-internal.h +@@ -5,6 +5,13 @@ + #ifndef __XIVE_INTERNAL_H + #define __XIVE_INTERNAL_H + ++/* ++ * A "disabled" interrupt should never fire, to catch problems ++ * we set its logical number to this ++ */ ++#define XIVE_BAD_IRQ 0x7fffffff ++#define XIVE_MAX_IRQ (XIVE_BAD_IRQ - 1) ++ + /* Each CPU carry one of these with various per-CPU state */ + struct xive_cpu { + #ifdef CONFIG_SMP +-- +2.23.0 + diff --git a/patches.suse/ptr_ring-add-include-of-linux-mm.h.patch b/patches.suse/ptr_ring-add-include-of-linux-mm.h.patch new file mode 100644 index 0000000..49e8799 --- /dev/null +++ b/patches.suse/ptr_ring-add-include-of-linux-mm.h.patch @@ -0,0 +1,33 @@ +From: Jesper Dangaard Brouer +Date: Mon, 13 Jan 2020 11:22:16 +0100 +Subject: ptr_ring: add include of linux/mm.h +Patch-mainline: v5.6-rc1 +Git-commit: 0eac8ce95bb386838121189b2aa2216cd070f143 +References: bsc#1109837 + +Commit 0bf7800f1799 ("ptr_ring: try vmalloc() when kmalloc() fails") +started to use kvmalloc_array and kvfree, which are defined in mm.h, +the previous functions kcalloc and kfree, which are defined in slab.h. + +Add the missing include of linux/mm.h. This went unnoticed as other +include files happened to include mm.h. + +Fixes: 0bf7800f1799 ("ptr_ring: try vmalloc() when kmalloc() fails") +Signed-off-by: Jesper Dangaard Brouer +Acked-by: Michael S. Tsirkin +Signed-off-by: Jakub Kicinski +Acked-by: Thomas Bogendoerfer +--- + include/linux/ptr_ring.h | 1 + + 1 file changed, 1 insertion(+) + +--- a/include/linux/ptr_ring.h ++++ b/include/linux/ptr_ring.h +@@ -28,6 +28,7 @@ + #include + #include + #include ++#include + #include + #endif + diff --git a/patches.suse/pxa168fb-fix-release-function-mismatch-in-probe-fail.patch b/patches.suse/pxa168fb-fix-release-function-mismatch-in-probe-fail.patch new file mode 100644 index 0000000..a3ff13f --- /dev/null +++ b/patches.suse/pxa168fb-fix-release-function-mismatch-in-probe-fail.patch @@ -0,0 +1,38 @@ +From 28388b3325e3fe21faed85280d12bb68c2ff63fc Mon Sep 17 00:00:00 2001 +From: Chuhong Yuan +Date: Fri, 6 Dec 2019 00:06:13 +0800 +Subject: [PATCH] pxa168fb: fix release function mismatch in probe failure +Git-commit: 28388b3325e3fe21faed85280d12bb68c2ff63fc +Patch-mainline: v5.7-rc1 +References: bsc#1051510 + +The driver uses kfree() to release the resource allocated by +framebuffer_alloc(), which does not match. +Use framebuffer_release() instead to fix it. + +Fixes: 638772c7553f ("fb: add support of LCD display controller on pxa168/910 (base layer)") +Signed-off-by: Chuhong Yuan +Signed-off-by: Bartlomiej Zolnierkiewicz +Link: https://patchwork.freedesktop.org/patch/msgid/20191205160613.32075-1-hslester96@gmail.com +Acked-by: Takashi Iwai + +--- + drivers/video/fbdev/pxa168fb.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/video/fbdev/pxa168fb.c b/drivers/video/fbdev/pxa168fb.c +index 362d3dfe8287..3679698fffd1 100644 +--- a/drivers/video/fbdev/pxa168fb.c ++++ b/drivers/video/fbdev/pxa168fb.c +@@ -769,7 +769,7 @@ static int pxa168fb_probe(struct platform_device *pdev) + dma_free_wc(fbi->dev, info->fix.smem_len, + info->screen_base, fbi->fb_start_dma); + failed_free_info: +- kfree(info); ++ framebuffer_release(info); + + dev_err(&pdev->dev, "frame buffer device init failed with %d\n", ret); + return ret; +-- +2.16.4 + diff --git a/patches.suse/qla2xxx-Enable-T10-DIF-with-FC-NVMe-enabled.patch b/patches.suse/qla2xxx-Enable-T10-DIF-with-FC-NVMe-enabled.patch deleted file mode 100644 index 812185c..0000000 --- a/patches.suse/qla2xxx-Enable-T10-DIF-with-FC-NVMe-enabled.patch +++ /dev/null @@ -1,77 +0,0 @@ -From: Himanshu Madhani -Date: Tue, 24 Apr 2018 21:22:05 -0700 -Subject: qla2xxx: Enable T10-DIF with FC-NVMe enabled -Patch-mainline: No, SLE15 specific -References: bsc#1091264 - -Signed-off-by: Himanshu Madhani -Acked-by: Johannes Thumshirn ---- - drivers/scsi/qla2xxx/qla_attr.c | 2 +- - drivers/scsi/qla2xxx/qla_init.c | 2 +- - drivers/scsi/qla2xxx/qla_os.c | 10 +++------- - 3 files changed, 5 insertions(+), 9 deletions(-) - ---- a/drivers/scsi/qla2xxx/qla_attr.c -+++ b/drivers/scsi/qla2xxx/qla_attr.c -@@ -2823,7 +2823,7 @@ qla24xx_vport_create(struct fc_vport *fc - fc_vport_set_state(fc_vport, FC_VPORT_LINKDOWN); - } - -- if (IS_T10_PI_CAPABLE(ha) && ql2xenabledif) { -+ if (IS_T10_PI_CAPABLE(ha) && ql2xenabledif && !ql2xnvmeenable) { - if (ha->fw_attributes & BIT_4) { - int prot = 0, guard; - ---- a/drivers/scsi/qla2xxx/qla_init.c -+++ b/drivers/scsi/qla2xxx/qla_init.c -@@ -8917,7 +8917,7 @@ struct qla_qpair *qla2xxx_create_qpair(s - /* init qpair to this cpu. Will adjust at run time. */ - qla_cpu_update(qpair, smp_processor_id()); - -- if (IS_T10_PI_CAPABLE(ha) && ql2xenabledif) { -+ if (IS_T10_PI_CAPABLE(ha) && ql2xenabledif && !ql2xnvmeenable) { - if (ha->fw_attributes & BIT_4) - qpair->difdix_supported = 1; - } ---- a/drivers/scsi/qla2xxx/qla_os.c -+++ b/drivers/scsi/qla2xxx/qla_os.c -@@ -122,11 +122,7 @@ MODULE_PARM_DESC(ql2xmaxqdepth, - "Maximum queue depth to set for each LUN. " - "Default is 64."); - --#if (IS_ENABLED(CONFIG_NVME_FC)) --int ql2xenabledif; --#else - int ql2xenabledif = 2; --#endif - module_param(ql2xenabledif, int, S_IRUGO); - MODULE_PARM_DESC(ql2xenabledif, - " Enable T10-CRC-DIF:\n" -@@ -3109,7 +3105,7 @@ qla2x00_probe_one(struct pci_dev *pdev, - host->max_id = ha->max_fibre_devices; - host->cmd_per_lun = 3; - host->unique_id = host->host_no; -- if (IS_T10_PI_CAPABLE(ha) && ql2xenabledif) -+ if (IS_T10_PI_CAPABLE(ha) && ql2xenabledif && !ql2xnvmeenable) - host->max_cmd_len = 32; - else - host->max_cmd_len = MAX_CMDSZ; -@@ -3337,7 +3333,7 @@ skip_dpc: - "Detected hba at address=%p.\n", - ha); - -- if (IS_T10_PI_CAPABLE(ha) && ql2xenabledif) { -+ if (IS_T10_PI_CAPABLE(ha) && ql2xenabledif && !ql2xnvmeenable) { - if (ha->fw_attributes & BIT_4) { - int prot = 0, guard; - -@@ -4005,7 +4001,7 @@ qla2x00_mem_alloc(struct qla_hw_data *ha - "init_cb=%p gid_list=%p, srb_mempool=%p s_dma_pool=%p.\n", - ha->init_cb, ha->gid_list, ha->srb_mempool, ha->s_dma_pool); - -- if (IS_P3P_TYPE(ha) || ql2xenabledif) { -+ if (IS_P3P_TYPE(ha) || (ql2xenabledif && !ql2xnvmeenable)) { - ha->dl_dma_pool = dma_pool_create(name, &ha->pdev->dev, - DSD_LIST_DMA_POOL_SIZE, 8, 0); - if (!ha->dl_dma_pool) { diff --git a/patches.suse/qmi_wwan-re-add-DW5821e-pre-production-variant.patch b/patches.suse/qmi_wwan-re-add-DW5821e-pre-production-variant.patch new file mode 100644 index 0000000..62cdd7f --- /dev/null +++ b/patches.suse/qmi_wwan-re-add-DW5821e-pre-production-variant.patch @@ -0,0 +1,73 @@ +From 88bf54603f6f2c137dfee1abf6436ceac3528d2d Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Bj=C3=B8rn=20Mork?= +Date: Sat, 8 Feb 2020 15:50:36 +0100 +Subject: [PATCH] qmi_wwan: re-add DW5821e pre-production variant +Mime-version: 1.0 +Content-type: text/plain; charset=UTF-8 +Content-transfer-encoding: 8bit +Git-commit: 88bf54603f6f2c137dfee1abf6436ceac3528d2d +Patch-mainline: v5.6-rc2 +References: bsc#1051510 + +Commit f25e1392fdb5 removed the support for the pre-production variant +of the Dell DW5821e to avoid probing another USB interface unnecessarily. +However, the pre-production samples are found in the wild, and this lack +of support is causing problems for users of such samples. It is therefore +necessary to support both variants. + +Matching on both interfaces 0 and 1 is not expected to cause any problem +with either variant, as only the QMI function will be probed successfully +on either. Interface 1 will be rejected based on the HID class for the +production variant: + +T: Bus=01 Lev=03 Prnt=04 Port=00 Cnt=01 Dev#= 16 Spd=480 MxCh= 0 +D: Ver= 2.10 Cls=ef(misc ) Sub=02 Prot=01 MxPS=64 #Cfgs= 2 +P: Vendor=413c ProdID=81d7 Rev=03.18 +S: Manufacturer=DELL +S: Product=DW5821e Snapdragon X20 LTE +S: SerialNumber=0123456789ABCDEF +C: #Ifs= 6 Cfg#= 1 Atr=a0 MxPwr=500mA +I: If#= 0 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=ff Prot=ff Driver=qmi_wwan +I: If#= 1 Alt= 0 #EPs= 1 Cls=03(HID ) Sub=00 Prot=00 Driver=usbhid +I: If#= 2 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=00 Prot=00 Driver=option +I: If#= 3 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=00 Prot=00 Driver=option +I: If#= 4 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=00 Prot=00 Driver=option +I: If#= 5 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=ff Prot=ff Driver=option + +And interface 0 will be rejected based on too few endpoints for the +pre-production variant: + +T: Bus=01 Lev=02 Prnt=02 Port=03 Cnt=03 Dev#= 7 Spd=480 MxCh= 0 +D: Ver= 2.10 Cls=ef(misc ) Sub=02 Prot=01 MxPS=64 #Cfgs= 2 +P: Vendor=413c ProdID=81d7 Rev= 3.18 +C: #Ifs= 5 Cfg#= 1 Atr=a0 MxPwr=500mA +I: If#= 0 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=ff Prot=ff Driver= +I: If#= 1 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=ff Prot=ff Driver=qmi_wwan + +Fixes: f25e1392fdb5 ("qmi_wwan: fix interface number for DW5821e production firmware") +Link: https://whrl.pl/Rf0vNk +Reported-by: Lars Melin +Cc: Aleksander Morgado +Signed-off-by: Bjørn Mork +Signed-off-by: David S. Miller +Acked-by: Takashi Iwai + +--- + drivers/net/usb/qmi_wwan.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c +index 9485c8d1de8a..839cef720cf6 100644 +--- a/drivers/net/usb/qmi_wwan.c ++++ b/drivers/net/usb/qmi_wwan.c +@@ -1363,6 +1363,7 @@ static const struct usb_device_id products[] = { + {QMI_FIXED_INTF(0x413c, 0x81b6, 8)}, /* Dell Wireless 5811e */ + {QMI_FIXED_INTF(0x413c, 0x81b6, 10)}, /* Dell Wireless 5811e */ + {QMI_FIXED_INTF(0x413c, 0x81d7, 0)}, /* Dell Wireless 5821e */ ++ {QMI_FIXED_INTF(0x413c, 0x81d7, 1)}, /* Dell Wireless 5821e preproduction config */ + {QMI_FIXED_INTF(0x413c, 0x81e0, 0)}, /* Dell Wireless 5821e with eSIM support*/ + {QMI_FIXED_INTF(0x03f0, 0x4e1d, 8)}, /* HP lt4111 LTE/EV-DO/HSPA+ Gobi 4G Module */ + {QMI_FIXED_INTF(0x03f0, 0x9d1d, 1)}, /* HP lt4120 Snapdragon X5 LTE */ +-- +2.16.4 + diff --git a/patches.suse/qmi_wwan-unconditionally-reject-2-ep-interfaces.patch b/patches.suse/qmi_wwan-unconditionally-reject-2-ep-interfaces.patch new file mode 100644 index 0000000..0000172 --- /dev/null +++ b/patches.suse/qmi_wwan-unconditionally-reject-2-ep-interfaces.patch @@ -0,0 +1,135 @@ +From 00516d13d4cfa56ce39da144db2dbf08b09b9357 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Bj=C3=B8rn=20Mork?= +Date: Sat, 8 Feb 2020 16:55:04 +0100 +Subject: [PATCH] qmi_wwan: unconditionally reject 2 ep interfaces +Mime-version: 1.0 +Content-type: text/plain; charset=UTF-8 +Content-transfer-encoding: 8bit +Git-commit: 00516d13d4cfa56ce39da144db2dbf08b09b9357 +Patch-mainline: v5.6-rc2 +References: bsc#1051510 + +We have been using the fact that the QMI and DIAG functions +usually are the only ones with class/subclass/protocol being +ff/ff/ff on Quectel modems. This has allowed us to match the +QMI function without knowing the exact interface number, +which can vary depending on firmware configuration. + +The ability to silently reject the DIAG function, which is +usually handled by the option driver, is important for this +method to work. This is done based on the knowledge that it +has exactly 2 bulk endpoints. QMI function control interfaces +will have either 3 or 1 endpoint. This rule is universal so +the quirk condition can be removed. + +The fixed layouts known from the Gobi1k and Gobi2k modems +have been gradually replaced by more dynamic layouts, and +many vendors now use configurable layouts without changing +device IDs. Renaming the class/subclass/protocol matching +macro makes it more obvious that this is now not Quectel +specific anymore. + +Cc: Kristian Evensen +Cc: Aleksander Morgado +Signed-off-by: Bjørn Mork +Signed-off-by: David S. Miller +Acked-by: Takashi Iwai + +--- + drivers/net/usb/qmi_wwan.c | 42 +++++++++++++++--------------------------- + 1 file changed, 15 insertions(+), 27 deletions(-) + +diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c +index 839cef720cf6..3b7a3b8a5e06 100644 +--- a/drivers/net/usb/qmi_wwan.c ++++ b/drivers/net/usb/qmi_wwan.c +@@ -61,7 +61,6 @@ enum qmi_wwan_flags { + + enum qmi_wwan_quirks { + QMI_WWAN_QUIRK_DTR = 1 << 0, /* needs "set DTR" request */ +- QMI_WWAN_QUIRK_QUECTEL_DYNCFG = 1 << 1, /* check num. endpoints */ + }; + + struct qmimux_hdr { +@@ -916,16 +915,6 @@ static const struct driver_info qmi_wwan_info_quirk_dtr = { + .data = QMI_WWAN_QUIRK_DTR, + }; + +-static const struct driver_info qmi_wwan_info_quirk_quectel_dyncfg = { +- .description = "WWAN/QMI device", +- .flags = FLAG_WWAN | FLAG_SEND_ZLP, +- .bind = qmi_wwan_bind, +- .unbind = qmi_wwan_unbind, +- .manage_power = qmi_wwan_manage_power, +- .rx_fixup = qmi_wwan_rx_fixup, +- .data = QMI_WWAN_QUIRK_DTR | QMI_WWAN_QUIRK_QUECTEL_DYNCFG, +-}; +- + #define HUAWEI_VENDOR_ID 0x12D1 + + /* map QMI/wwan function by a fixed interface number */ +@@ -946,14 +935,18 @@ static const struct driver_info qmi_wwan_info_quirk_quectel_dyncfg = { + #define QMI_GOBI_DEVICE(vend, prod) \ + QMI_FIXED_INTF(vend, prod, 0) + +-/* Quectel does not use fixed interface numbers on at least some of their +- * devices. We need to check the number of endpoints to ensure that we bind to +- * the correct interface. ++/* Many devices have QMI and DIAG functions which are distinguishable ++ * from other vendor specific functions by class, subclass and ++ * protocol all being 0xff. The DIAG function has exactly 2 endpoints ++ * and is silently rejected when probed. ++ * ++ * This makes it possible to match dynamically numbered QMI functions ++ * as seen on e.g. many Quectel modems. + */ +-#define QMI_QUIRK_QUECTEL_DYNCFG(vend, prod) \ ++#define QMI_MATCH_FF_FF_FF(vend, prod) \ + USB_DEVICE_AND_INTERFACE_INFO(vend, prod, USB_CLASS_VENDOR_SPEC, \ + USB_SUBCLASS_VENDOR_SPEC, 0xff), \ +- .driver_info = (unsigned long)&qmi_wwan_info_quirk_quectel_dyncfg ++ .driver_info = (unsigned long)&qmi_wwan_info_quirk_dtr + + static const struct usb_device_id products[] = { + /* 1. CDC ECM like devices match on the control interface */ +@@ -1059,10 +1052,10 @@ static const struct usb_device_id products[] = { + USB_DEVICE_AND_INTERFACE_INFO(0x03f0, 0x581d, USB_CLASS_VENDOR_SPEC, 1, 7), + .driver_info = (unsigned long)&qmi_wwan_info, + }, +- {QMI_QUIRK_QUECTEL_DYNCFG(0x2c7c, 0x0125)}, /* Quectel EC25, EC20 R2.0 Mini PCIe */ +- {QMI_QUIRK_QUECTEL_DYNCFG(0x2c7c, 0x0306)}, /* Quectel EP06/EG06/EM06 */ +- {QMI_QUIRK_QUECTEL_DYNCFG(0x2c7c, 0x0512)}, /* Quectel EG12/EM12 */ +- {QMI_QUIRK_QUECTEL_DYNCFG(0x2c7c, 0x0800)}, /* Quectel RM500Q-GL */ ++ {QMI_MATCH_FF_FF_FF(0x2c7c, 0x0125)}, /* Quectel EC25, EC20 R2.0 Mini PCIe */ ++ {QMI_MATCH_FF_FF_FF(0x2c7c, 0x0306)}, /* Quectel EP06/EG06/EM06 */ ++ {QMI_MATCH_FF_FF_FF(0x2c7c, 0x0512)}, /* Quectel EG12/EM12 */ ++ {QMI_MATCH_FF_FF_FF(0x2c7c, 0x0800)}, /* Quectel RM500Q-GL */ + + /* 3. Combined interface devices matching on interface number */ + {QMI_FIXED_INTF(0x0408, 0xea42, 4)}, /* Yota / Megafon M100-1 */ +@@ -1455,7 +1448,6 @@ static int qmi_wwan_probe(struct usb_interface *intf, + { + struct usb_device_id *id = (struct usb_device_id *)prod; + struct usb_interface_descriptor *desc = &intf->cur_altsetting->desc; +- const struct driver_info *info; + + /* Workaround to enable dynamic IDs. This disables usbnet + * blacklisting functionality. Which, if required, can be +@@ -1491,12 +1483,8 @@ static int qmi_wwan_probe(struct usb_interface *intf, + * different. Ignore the current interface if the number of endpoints + * equals the number for the diag interface (two). + */ +- info = (void *)id->driver_info; +- +- if (info->data & QMI_WWAN_QUIRK_QUECTEL_DYNCFG) { +- if (desc->bNumEndpoints == 2) +- return -ENODEV; +- } ++ if (desc->bNumEndpoints == 2) ++ return -ENODEV; + + return usbnet_probe(intf, id); + } +-- +2.16.4 + diff --git a/patches.suse/raid5-cache-Need-to-do-start-part-job-after-adding-j.patch b/patches.suse/raid5-cache-Need-to-do-start-part-job-after-adding-j.patch deleted file mode 100644 index 9eb5c67..0000000 --- a/patches.suse/raid5-cache-Need-to-do-start-part-job-after-adding-j.patch +++ /dev/null @@ -1,60 +0,0 @@ -From d9771f5ec46c282d518b453c793635dbdc3a2a94 Mon Sep 17 00:00:00 2001 -From: Xiao Ni -Date: Fri, 14 Jun 2019 15:41:05 -0700 -Subject: [PATCH] raid5-cache: Need to do start() part job after adding journal - device -Git-commit: d9771f5ec46c282d518b453c793635dbdc3a2a94 -Patch-mainline: v5.3-rc1 -References: git fixes - -commit d5d885fd514f ("md: introduce new personality funciton start()") -splits the init job to two parts. The first part run() does the jobs that -do not require the md threads. The second part start() does the jobs that -require the md threads. - -Now it just does run() in adding new journal device. It needs to do the -second part start() too. - -Fixes: d5d885fd514f ("md: introduce new personality funciton start()") -Cc: stable@vger.kernel.org #v4.9+ -Reported-by: Michal Soltys -Signed-off-by: Xiao Ni -Signed-off-by: Song Liu -Signed-off-by: Jens Axboe -Signed-off-by: Coly Li ---- - drivers/md/raid5.c | 11 +++++++++-- - 1 file changed, 9 insertions(+), 2 deletions(-) - -diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c -index b83bce2beb66..da94cbaa1a9e 100644 ---- a/drivers/md/raid5.c -+++ b/drivers/md/raid5.c -@@ -7672,7 +7672,7 @@ static int raid5_remove_disk(struct mddev *mddev, struct md_rdev *rdev) - static int raid5_add_disk(struct mddev *mddev, struct md_rdev *rdev) - { - struct r5conf *conf = mddev->private; -- int err = -EEXIST; -+ int ret, err = -EEXIST; - int disk; - struct disk_info *p; - int first = 0; -@@ -7687,7 +7687,14 @@ static int raid5_add_disk(struct mddev *mddev, struct md_rdev *rdev) - * The array is in readonly mode if journal is missing, so no - * write requests running. We should be safe - */ -- log_init(conf, rdev, false); -+ ret = log_init(conf, rdev, false); -+ if (ret) -+ return ret; -+ -+ ret = r5l_start(conf->log); -+ if (ret) -+ return ret; -+ - return 0; - } - if (mddev->recovery_disabled == conf->recovery_disabled) --- -2.16.4 - diff --git a/patches.suse/remoteproc-Initialize-rproc_class-before-use.patch b/patches.suse/remoteproc-Initialize-rproc_class-before-use.patch new file mode 100644 index 0000000..3e8136e --- /dev/null +++ b/patches.suse/remoteproc-Initialize-rproc_class-before-use.patch @@ -0,0 +1,73 @@ +From a8f40111d184098cd2b3dc0c7170c42250a5fa09 Mon Sep 17 00:00:00 2001 +From: Brandon Maier +Date: Thu, 30 May 2019 17:52:23 -0500 +Subject: [PATCH] remoteproc: Initialize rproc_class before use +Git-commit: a8f40111d184098cd2b3dc0c7170c42250a5fa09 +Patch-mainline: v5.6-rc1 +References: bsc#1051510 + +The remoteproc_core and remoteproc drivers all initialize with module_init(). +However remoteproc drivers need the rproc_class during their probe. If one of +the remoteproc drivers runs init and gets through probe before +remoteproc_init() runs, a NULL pointer access of rproc_class's `glue_dirs` +spinlock occurs. + +> Unable to handle kernel NULL pointer dereference at virtual address 000000dc +> pgd = c0004000 +> [000000dc] *pgd=00000000 +> Internal error: Oops: 5 [#1] PREEMPT ARM +> Modules linked in: +> CPU: 0 PID: 1 Comm: swapper Tainted: G W 4.14.106-rt56 #1 +> Hardware name: Generic OMAP36xx (Flattened Device Tree) +> task: c6050000 task.stack: c604a000 +> PC is at rt_spin_lock+0x40/0x6c +> LR is at rt_spin_lock+0x28/0x6c +> pc : [] lr : [] psr: 60000013 +> sp : c604bdc0 ip : 00000000 fp : 00000000 +> r10: 00000000 r9 : c61c7c10 r8 : c6269c20 +> r7 : c0905888 r6 : c6269c20 r5 : 00000000 r4 : 000000d4 +> r3 : 000000dc r2 : c6050000 r1 : 00000002 r0 : 000000d4 +> Flags: nZCv IRQs on FIQs on Mode SVC_32 ISA ARM Segment none +... +> [] (rt_spin_lock) from [] (get_device_parent+0x54/0x17c) +> [] (get_device_parent) from [] (device_add+0xe0/0x5b4) +> [] (device_add) from [] (rproc_add+0x18/0xd8) +> [] (rproc_add) from [] (my_rproc_probe+0x158/0x204) +> [] (my_rproc_probe) from [] (platform_drv_probe+0x34/0x70) +> [] (platform_drv_probe) from [] (driver_probe_device+0x2c8/0x420) +> [] (driver_probe_device) from [] (__driver_attach+0x100/0x11c) +> [] (__driver_attach) from [] (bus_for_each_dev+0x7c/0xc0) +> [] (bus_for_each_dev) from [] (bus_add_driver+0x1cc/0x264) +> [] (bus_add_driver) from [] (driver_register+0x78/0xf8) +> [] (driver_register) from [] (do_one_initcall+0x100/0x190) +> [] (do_one_initcall) from [] (kernel_init_freeable+0x130/0x1d0) +> [] (kernel_init_freeable) from [] (kernel_init+0x8/0x114) +> [] (kernel_init) from [] (ret_from_fork+0x14/0x24) +> Code: e2843008 e3c2203f f5d3f000 e5922010 (e193cf9f) +> ---[ end trace 0000000000000002 ]--- + +Signed-off-by: Brandon Maier +Link: https://lore.kernel.org/r/20190530225223.136420-1-brandon.maier@rockwellcollins.com +Signed-off-by: Bjorn Andersson +Acked-by: Takashi Iwai + +--- + drivers/remoteproc/remoteproc_core.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/remoteproc/remoteproc_core.c b/drivers/remoteproc/remoteproc_core.c +index 307df98347ba..8115f945151b 100644 +--- a/drivers/remoteproc/remoteproc_core.c ++++ b/drivers/remoteproc/remoteproc_core.c +@@ -2223,7 +2223,7 @@ static int __init remoteproc_init(void) + + return 0; + } +-module_init(remoteproc_init); ++subsys_initcall(remoteproc_init); + + static void __exit remoteproc_exit(void) + { +-- +2.16.4 + diff --git a/patches.suse/revert-btrfs-qgroup-move-half-of-the-qgroup-accounting-time-out-of-commit-trans.patch b/patches.suse/revert-btrfs-qgroup-move-half-of-the-qgroup-accounting-time-out-of-commit-trans.patch index 48b920d..4cbfec9 100644 --- a/patches.suse/revert-btrfs-qgroup-move-half-of-the-qgroup-accounting-time-out-of-commit-trans.patch +++ b/patches.suse/revert-btrfs-qgroup-move-half-of-the-qgroup-accounting-time-out-of-commit-trans.patch @@ -47,7 +47,7 @@ Acked-by: Jeff Mahoney --- a/fs/btrfs/delayed-ref.c +++ b/fs/btrfs/delayed-ref.c -@@ -615,13 +615,11 @@ add_delayed_ref_head(struct btrfs_fs_inf +@@ -636,13 +636,11 @@ add_delayed_ref_head(struct btrfs_fs_inf struct btrfs_trans_handle *trans, struct btrfs_delayed_ref_head *head_ref, struct btrfs_qgroup_extent_record *qrecord, @@ -62,7 +62,7 @@ Acked-by: Jeff Mahoney delayed_refs = &trans->transaction->delayed_refs; -@@ -630,8 +628,6 @@ add_delayed_ref_head(struct btrfs_fs_inf +@@ -651,8 +649,6 @@ add_delayed_ref_head(struct btrfs_fs_inf if (btrfs_qgroup_trace_extent_nolock(fs_info, delayed_refs, qrecord)) kfree(qrecord); @@ -71,7 +71,7 @@ Acked-by: Jeff Mahoney } trace_add_delayed_ref_head(fs_info, head_ref, action); -@@ -657,8 +653,6 @@ add_delayed_ref_head(struct btrfs_fs_inf +@@ -682,8 +678,6 @@ add_delayed_ref_head(struct btrfs_fs_inf atomic_inc(&delayed_refs->num_entries); trans->delayed_ref_updates++; } @@ -80,7 +80,7 @@ Acked-by: Jeff Mahoney if (new_ref_mod) *new_ref_mod = head_ref->total_ref_mod; -@@ -731,7 +725,6 @@ int btrfs_add_delayed_tree_ref(struct bt +@@ -756,7 +750,6 @@ int btrfs_add_delayed_tree_ref(struct bt struct btrfs_delayed_ref_head *head_ref; struct btrfs_delayed_ref_root *delayed_refs; struct btrfs_qgroup_extent_record *record = NULL; @@ -88,7 +88,7 @@ Acked-by: Jeff Mahoney bool is_system; int action = generic_ref->action; int level = generic_ref->tree_ref.level; -@@ -785,8 +778,7 @@ int btrfs_add_delayed_tree_ref(struct bt +@@ -810,8 +803,7 @@ int btrfs_add_delayed_tree_ref(struct bt * the spin lock */ head_ref = add_delayed_ref_head(fs_info, trans, head_ref, record, @@ -98,7 +98,7 @@ Acked-by: Jeff Mahoney ret = insert_delayed_ref(trans, delayed_refs, head_ref, &ref->node); -@@ -798,8 +790,6 @@ int btrfs_add_delayed_tree_ref(struct bt +@@ -829,8 +821,6 @@ int btrfs_add_delayed_tree_ref(struct bt if (ret > 0) kmem_cache_free(btrfs_delayed_tree_ref_cachep, ref); @@ -107,7 +107,7 @@ Acked-by: Jeff Mahoney return 0; free_head_ref: -@@ -822,7 +812,6 @@ int btrfs_add_delayed_data_ref(struct bt +@@ -853,7 +843,6 @@ int btrfs_add_delayed_data_ref(struct bt struct btrfs_delayed_ref_head *head_ref; struct btrfs_delayed_ref_root *delayed_refs; struct btrfs_qgroup_extent_record *record = NULL; @@ -115,7 +115,7 @@ Acked-by: Jeff Mahoney int action = generic_ref->action; int ret; u64 bytenr = generic_ref->bytenr; -@@ -881,8 +870,7 @@ int btrfs_add_delayed_data_ref(struct bt +@@ -912,8 +901,7 @@ int btrfs_add_delayed_data_ref(struct bt * the spin lock */ head_ref = add_delayed_ref_head(fs_info, trans, head_ref, record, @@ -125,7 +125,7 @@ Acked-by: Jeff Mahoney ret = insert_delayed_ref(trans, delayed_refs, head_ref, &ref->node); spin_unlock(&delayed_refs->lock); -@@ -893,8 +881,6 @@ int btrfs_add_delayed_data_ref(struct bt +@@ -930,8 +918,6 @@ int btrfs_add_delayed_data_ref(struct bt if (ret > 0) kmem_cache_free(btrfs_delayed_data_ref_cachep, ref); @@ -134,7 +134,7 @@ Acked-by: Jeff Mahoney return 0; } -@@ -920,7 +906,7 @@ int btrfs_add_delayed_extent_op(struct b +@@ -957,7 +943,7 @@ int btrfs_add_delayed_extent_op(struct b add_delayed_ref_head(fs_info, trans, head_ref, NULL, BTRFS_UPDATE_DELAYED_HEAD, @@ -142,7 +142,7 @@ Acked-by: Jeff Mahoney + NULL, NULL); spin_unlock(&delayed_refs->lock); - return 0; + --- a/fs/btrfs/qgroup.c +++ b/fs/btrfs/qgroup.c @@ -1507,28 +1507,6 @@ int btrfs_qgroup_trace_extent_nolock(str diff --git a/patches.suse/rtlwifi-rtl8192de-Fix-missing-callback-that-tests-fo.patch b/patches.suse/rtlwifi-rtl8192de-Fix-missing-callback-that-tests-fo.patch deleted file mode 100644 index 9d3de81..0000000 --- a/patches.suse/rtlwifi-rtl8192de-Fix-missing-callback-that-tests-fo.patch +++ /dev/null @@ -1,80 +0,0 @@ -From 3155db7613edea8fb943624062baf1e4f9cfbfd6 Mon Sep 17 00:00:00 2001 -From: Larry Finger -Date: Mon, 11 Nov 2019 13:40:45 -0600 -Subject: [PATCH] rtlwifi: rtl8192de: Fix missing callback that tests for hw release of buffer -Git-commit: 3155db7613edea8fb943624062baf1e4f9cfbfd6 -Patch-mainline: v5.5-rc1 -References: bsc#1111666 - -In commit 38506ecefab9 ("rtlwifi: rtl_pci: Start modification for -new drivers"), a callback needed to check if the hardware has released -a buffer indicating that a DMA operation is completed was not added. - -Fixes: 38506ecefab9 ("rtlwifi: rtl_pci: Start modification for new drivers") -Cc: Stable # v3.18+ -Signed-off-by: Larry Finger -Signed-off-by: Kalle Valo -Acked-by: Takashi Iwai - ---- - drivers/net/wireless/realtek/rtlwifi/rtl8192de/sw.c | 1 + - drivers/net/wireless/realtek/rtlwifi/rtl8192de/trx.c | 17 +++++++++++++++++ - drivers/net/wireless/realtek/rtlwifi/rtl8192de/trx.h | 2 ++ - 3 files changed, 20 insertions(+) - -diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/sw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/sw.c -index 99e5cd9a5c86..1dbdddce0823 100644 ---- a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/sw.c -+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/sw.c -@@ -216,6 +216,7 @@ static struct rtl_hal_ops rtl8192de_hal_ops = { - .led_control = rtl92de_led_control, - .set_desc = rtl92de_set_desc, - .get_desc = rtl92de_get_desc, -+ .is_tx_desc_closed = rtl92de_is_tx_desc_closed, - .tx_polling = rtl92de_tx_polling, - .enable_hw_sec = rtl92de_enable_hw_security_config, - .set_key = rtl92de_set_key, -diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/trx.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/trx.c -index b4561923a70a..92c9fb45f800 100644 ---- a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/trx.c -+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/trx.c -@@ -823,6 +823,23 @@ u64 rtl92de_get_desc(struct ieee80211_hw *hw, - return ret; - } - -+bool rtl92de_is_tx_desc_closed(struct ieee80211_hw *hw, -+ u8 hw_queue, u16 index) -+{ -+ struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); -+ struct rtl8192_tx_ring *ring = &rtlpci->tx_ring[hw_queue]; -+ u8 *entry = (u8 *)(&ring->desc[ring->idx]); -+ u8 own = (u8)rtl92de_get_desc(hw, entry, true, HW_DESC_OWN); -+ -+ /* a beacon packet will only use the first -+ * descriptor by defaut, and the own bit may not -+ * be cleared by the hardware -+ */ -+ if (own) -+ return false; -+ return true; -+} -+ - void rtl92de_tx_polling(struct ieee80211_hw *hw, u8 hw_queue) - { - struct rtl_priv *rtlpriv = rtl_priv(hw); -diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/trx.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/trx.h -index 36820070fd76..635989e15282 100644 ---- a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/trx.h -+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/trx.h -@@ -715,6 +715,8 @@ void rtl92de_set_desc(struct ieee80211_hw *hw, u8 *pdesc, bool istx, - u8 desc_name, u8 *val); - u64 rtl92de_get_desc(struct ieee80211_hw *hw, - u8 *p_desc, bool istx, u8 desc_name); -+bool rtl92de_is_tx_desc_closed(struct ieee80211_hw *hw, -+ u8 hw_queue, u16 index); - void rtl92de_tx_polling(struct ieee80211_hw *hw, u8 hw_queue); - void rtl92de_tx_fill_cmddesc(struct ieee80211_hw *hw, u8 *pdesc, - bool b_firstseg, bool b_lastseg, --- -2.16.4 - diff --git a/patches.suse/rtlwifi-rtl_pci-Fix-Wcast-function-type.patch b/patches.suse/rtlwifi-rtl_pci-Fix-Wcast-function-type.patch new file mode 100644 index 0000000..c5fa8e3 --- /dev/null +++ b/patches.suse/rtlwifi-rtl_pci-Fix-Wcast-function-type.patch @@ -0,0 +1,58 @@ +From cb775c88da5d48a85d99d95219f637b6fad2e0e9 Mon Sep 17 00:00:00 2001 +From: Phong Tran +Date: Wed, 27 Nov 2019 00:55:29 +0700 +Subject: [PATCH] rtlwifi: rtl_pci: Fix -Wcast-function-type +Git-commit: cb775c88da5d48a85d99d95219f637b6fad2e0e9 +Patch-mainline: v5.6-rc1 +References: bsc#1051510 + +correct usage prototype of callback in tasklet_init(). +Report by https://github.com/KSPP/linux/issues/20 + +Signed-off-by: Phong Tran +Reviewed-by: Kees Cook +Signed-off-by: Kalle Valo +Acked-by: Takashi Iwai + +--- + drivers/net/wireless/realtek/rtlwifi/pci.c | 10 ++++++---- + 1 file changed, 6 insertions(+), 4 deletions(-) + +diff --git a/drivers/net/wireless/realtek/rtlwifi/pci.c b/drivers/net/wireless/realtek/rtlwifi/pci.c +index f88d26535978..25335bd2873b 100644 +--- a/drivers/net/wireless/realtek/rtlwifi/pci.c ++++ b/drivers/net/wireless/realtek/rtlwifi/pci.c +@@ -1061,13 +1061,15 @@ static irqreturn_t _rtl_pci_interrupt(int irq, void *dev_id) + return ret; + } + +-static void _rtl_pci_irq_tasklet(struct ieee80211_hw *hw) ++static void _rtl_pci_irq_tasklet(unsigned long data) + { ++ struct ieee80211_hw *hw = (struct ieee80211_hw *)data; + _rtl_pci_tx_chk_waitq(hw); + } + +-static void _rtl_pci_prepare_bcn_tasklet(struct ieee80211_hw *hw) ++static void _rtl_pci_prepare_bcn_tasklet(unsigned long data) + { ++ struct ieee80211_hw *hw = (struct ieee80211_hw *)data; + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); +@@ -1193,10 +1195,10 @@ static void _rtl_pci_init_struct(struct ieee80211_hw *hw, + + /*task */ + tasklet_init(&rtlpriv->works.irq_tasklet, +- (void (*)(unsigned long))_rtl_pci_irq_tasklet, ++ _rtl_pci_irq_tasklet, + (unsigned long)hw); + tasklet_init(&rtlpriv->works.irq_prepare_bcn_tasklet, +- (void (*)(unsigned long))_rtl_pci_prepare_bcn_tasklet, ++ _rtl_pci_prepare_bcn_tasklet, + (unsigned long)hw); + INIT_WORK(&rtlpriv->works.lps_change_work, + rtl_lps_change_work_callback); +-- +2.16.4 + diff --git a/patches.suse/rxrpc-Fix-insufficient-receive-notification-generati.patch b/patches.suse/rxrpc-Fix-insufficient-receive-notification-generati.patch new file mode 100644 index 0000000..5f21c0a --- /dev/null +++ b/patches.suse/rxrpc-Fix-insufficient-receive-notification-generati.patch @@ -0,0 +1,38 @@ +From: David Howells +Date: Thu, 30 Jan 2020 21:50:36 +0000 +Subject: rxrpc: Fix insufficient receive notification generation +Git-commit: f71dbf2fb28489a79bde0dca1c8adfb9cdb20a6b +Patch-mainline: 5.6-rc1 +References: networking-stable-20_02_05 + +In rxrpc_input_data(), rxrpc_notify_socket() is called if the base sequence +number of the packet is immediately following the hard-ack point at the end +of the function. However, this isn't sufficient, since the recvmsg side +may have been advancing the window and then overrun the position in which +we're adding - at which point rx_hard_ack >= seq0 and no notification is +generated. + +Fix this by always generating a notification at the end of the input +function. + +Without this, a long call may stall, possibly indefinitely. + +Fixes: 248f219cb8bc ("rxrpc: Rewrite the data and ack handling code") +Signed-off-by: David Howells +Signed-off-by: Jiri Slaby +--- + net/rxrpc/input.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +--- a/net/rxrpc/input.c ++++ b/net/rxrpc/input.c +@@ -580,8 +580,7 @@ ack: + immediate_ack, true, + rxrpc_propose_ack_input_data); + +- if (sp->hdr.seq == READ_ONCE(call->rx_hard_ack) + 1) +- rxrpc_notify_socket(call); ++ rxrpc_notify_socket(call); + _leave(" [queued]"); + } + diff --git a/patches.suse/s390-mm-fix-dynamic-pagetable-upgrade-for-hugetlbfs b/patches.suse/s390-mm-fix-dynamic-pagetable-upgrade-for-hugetlbfs new file mode 100644 index 0000000..8e79c18 --- /dev/null +++ b/patches.suse/s390-mm-fix-dynamic-pagetable-upgrade-for-hugetlbfs @@ -0,0 +1,180 @@ +From: Gerald Schaefer +Date: Thu, 16 Jan 2020 19:59:04 +0100 +Subject: s390/mm: fix dynamic pagetable upgrade for hugetlbfs +Git-commit: 5f490a520bcb393389a4d44bec90afcb332eb112 +Patch-mainline: v5.6-rc1 +References: bsc#1165182 LTC#184102 + +Commit ee71d16d22bb ("s390/mm: make TASK_SIZE independent from the number +of page table levels") changed the logic of TASK_SIZE and also removed the +arch_mmap_check() implementation for s390. This combination has a subtle +effect on how get_unmapped_area() for hugetlbfs pages works. It is now +possible that a user process establishes a hugetlbfs mapping at an address +above 4 TB, without triggering a dynamic pagetable upgrade from 3 to 4 +levels. + +This is because hugetlbfs mappings will not use mm->get_unmapped_area, but +rather file->f_op->get_unmapped_area, which currently is the generic +implementation of hugetlb_get_unmapped_area() that does not know about s390 +dynamic pagetable upgrades, but with the new definition of TASK_SIZE, it +will now allow mappings above 4 TB. + +Subsequent access to such a mapped address above 4 TB will result in a page +fault loop, because the CPU cannot translate such a large address with 3 +pagetable levels. The fault handler will try to map in a hugepage at the +address, but due to the folded pagetable logic it will end up with creating +entries in the 3 level pagetable, possibly overwriting existing mappings, +and then it all repeats when the access is retried. + +Apart from the page fault loop, this can have various nasty effects, e.g. +kernel panic from one of the BUG_ON() checks in memory management code, +or even data loss if an existing mapping gets overwritten. + +Fix this by implementing HAVE_ARCH_HUGETLB_UNMAPPED_AREA support for s390, +providing an s390 version for hugetlb_get_unmapped_area() with pagetable +upgrade support similar to arch_get_unmapped_area(), which will then be +used instead of the generic version. + +Fixes: ee71d16d22bb ("s390/mm: make TASK_SIZE independent from the number of page table levels") +Cc: # 4.12+ +Signed-off-by: Gerald Schaefer +Signed-off-by: Vasily Gorbik +[ ptesarik: v4.12 does not implement 5-level paging, so crst_table_upgrade() + takes only one argument. ] +Signed-off-by: Petr Tesarik +--- + arch/s390/include/asm/page.h | 2 + arch/s390/mm/hugetlbpage.c | 100 ++++++++++++++++++++++++++++++++++++++++++- + 2 files changed, 101 insertions(+), 1 deletion(-) + +--- a/arch/s390/include/asm/page.h ++++ b/arch/s390/include/asm/page.h +@@ -28,6 +28,8 @@ + #define ARCH_HAS_PREPARE_HUGEPAGE + #define ARCH_HAS_HUGEPAGE_CLEAR_FLUSH + ++#define HAVE_ARCH_HUGETLB_UNMAPPED_AREA ++ + #include + #ifndef __ASSEMBLY__ + +--- a/arch/s390/mm/hugetlbpage.c ++++ b/arch/s390/mm/hugetlbpage.c +@@ -1,7 +1,7 @@ + /* + * IBM System z Huge TLB Page Support for Kernel. + * +- * Copyright IBM Corp. 2007,2016 ++ * Copyright IBM Corp. 2007,2020 + * Author(s): Gerald Schaefer + */ + +@@ -10,6 +10,9 @@ + + #include + #include ++#include ++#include ++#include + + /* + * If the bit selected by single-bit bitmask "a" is set within "x", move +@@ -233,3 +236,98 @@ static __init int setup_hugepagesz(char + return 1; + } + __setup("hugepagesz=", setup_hugepagesz); ++ ++static unsigned long hugetlb_get_unmapped_area_bottomup(struct file *file, ++ unsigned long addr, unsigned long len, ++ unsigned long pgoff, unsigned long flags) ++{ ++ struct hstate *h = hstate_file(file); ++ struct vm_unmapped_area_info info; ++ ++ info.flags = 0; ++ info.length = len; ++ info.low_limit = current->mm->mmap_base; ++ info.high_limit = TASK_SIZE; ++ info.align_mask = PAGE_MASK & ~huge_page_mask(h); ++ info.align_offset = 0; ++ return vm_unmapped_area(&info); ++} ++ ++static unsigned long hugetlb_get_unmapped_area_topdown(struct file *file, ++ unsigned long addr0, unsigned long len, ++ unsigned long pgoff, unsigned long flags) ++{ ++ struct hstate *h = hstate_file(file); ++ struct vm_unmapped_area_info info; ++ unsigned long addr; ++ ++ info.flags = VM_UNMAPPED_AREA_TOPDOWN; ++ info.length = len; ++ info.low_limit = max(PAGE_SIZE, mmap_min_addr); ++ info.high_limit = current->mm->mmap_base; ++ info.align_mask = PAGE_MASK & ~huge_page_mask(h); ++ info.align_offset = 0; ++ addr = vm_unmapped_area(&info); ++ ++ /* ++ * A failed mmap() very likely causes application failure, ++ * so fall back to the bottom-up function here. This scenario ++ * can happen with large stack limits and large mmap() ++ * allocations. ++ */ ++ if (addr & ~PAGE_MASK) { ++ VM_BUG_ON(addr != -ENOMEM); ++ info.flags = 0; ++ info.low_limit = TASK_UNMAPPED_BASE; ++ info.high_limit = TASK_SIZE; ++ addr = vm_unmapped_area(&info); ++ } ++ ++ return addr; ++} ++ ++unsigned long hugetlb_get_unmapped_area(struct file *file, unsigned long addr, ++ unsigned long len, unsigned long pgoff, unsigned long flags) ++{ ++ struct hstate *h = hstate_file(file); ++ struct mm_struct *mm = current->mm; ++ struct vm_area_struct *vma; ++ int rc; ++ ++ if (len & ~huge_page_mask(h)) ++ return -EINVAL; ++ if (len > TASK_SIZE - mmap_min_addr) ++ return -ENOMEM; ++ ++ if (flags & MAP_FIXED) { ++ if (prepare_hugepage_range(file, addr, len)) ++ return -EINVAL; ++ goto check_asce_limit; ++ } ++ ++ if (addr) { ++ addr = ALIGN(addr, huge_page_size(h)); ++ vma = find_vma(mm, addr); ++ if (TASK_SIZE - len >= addr && addr >= mmap_min_addr && ++ (!vma || addr + len <= vm_start_gap(vma))) ++ goto check_asce_limit; ++ } ++ ++ if (mm->get_unmapped_area == arch_get_unmapped_area) ++ addr = hugetlb_get_unmapped_area_bottomup(file, addr, len, ++ pgoff, flags); ++ else ++ addr = hugetlb_get_unmapped_area_topdown(file, addr, len, ++ pgoff, flags); ++ if (addr & ~PAGE_MASK) ++ return addr; ++ ++check_asce_limit: ++ if (addr + len > current->mm->context.asce_limit && ++ addr + len <= TASK_SIZE) { ++ rc = crst_table_upgrade(mm); ++ if (rc) ++ return (unsigned long) rc; ++ } ++ return addr; ++} diff --git a/patches.suse/s390-pci-fix-unexpected-write-combine-on-resource b/patches.suse/s390-pci-fix-unexpected-write-combine-on-resource new file mode 100644 index 0000000..b226cf0 --- /dev/null +++ b/patches.suse/s390-pci-fix-unexpected-write-combine-on-resource @@ -0,0 +1,47 @@ +From: Niklas Schnelle +Date: Thu, 27 Feb 2020 12:17:18 +0100 +Subject: s390/pci: Fix unexpected write combine on resource +Git-commit: df057c914a9c219ac8b8ed22caf7da2f80c1fe26 +Patch-mainline: v5.6-rc5 +References: bsc#1168552 LTC#184761 git-fixes + +In the initial MIO support introduced in + +commit 71ba41c9b1d9 ("s390/pci: provide support for MIO instructions") + +zpci_map_resource() and zpci_setup_resources() default to using the +mio_wb address as the resource's start address. This means users of the +mapping, which includes most drivers, will get write combining on PCI +Stores. This may lead to problems when drivers expect write through +behavior when not using an explicit ioremap_wc(). + +Cc: stable@vger.kernel.org +Fixes: 71ba41c9b1d9 ("s390/pci: provide support for MIO instructions") +Signed-off-by: Niklas Schnelle +Reviewed-by: Pierre Morel +Signed-off-by: Vasily Gorbik +Acked-by: Petr Tesarik +--- + arch/s390/pci/pci.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/arch/s390/pci/pci.c ++++ b/arch/s390/pci/pci.c +@@ -427,7 +427,7 @@ static void zpci_map_resources(struct pc + + if (zpci_use_mio(zdev)) + pdev->resource[i].start = +- (resource_size_t __force) zdev->bars[i].mio_wb; ++ (resource_size_t __force) zdev->bars[i].mio_wt; + else + pdev->resource[i].start = (resource_size_t __force) + pci_iomap_range_fh(pdev, i, 0, 0); +@@ -534,7 +534,7 @@ static int zpci_setup_bus_resources(stru + flags |= IORESOURCE_MEM_64; + + if (zpci_use_mio(zdev)) +- addr = (unsigned long) zdev->bars[i].mio_wb; ++ addr = (unsigned long) zdev->bars[i].mio_wt; + else + addr = ZPCI_ADDR(entry); + size = 1UL << zdev->bars[i].size; diff --git a/patches.suse/s390-qeth-fix-potential-deadlock-on-workqueue-flush b/patches.suse/s390-qeth-fix-potential-deadlock-on-workqueue-flush new file mode 100644 index 0000000..61aa6c1 --- /dev/null +++ b/patches.suse/s390-qeth-fix-potential-deadlock-on-workqueue-flush @@ -0,0 +1,201 @@ +From: Julian Wiedmann +Date: Wed, 20 Nov 2019 14:20:56 +0100 +Subject: s390/qeth: fix potential deadlock on workqueue flush +Git-commit: c8183f5489020afc08dd9d88c3e4ee0e3c820733 +Patch-mainline: v5.4 +References: bsc#1165185 LTC#184108 + +Description: qeth: fix potential deadlock on workqueue flush +Symptom: Deadlock when tearing down a L2 qeth device. +Problem: The L2 bridgeport code uses the coarse 'conf_mutex' for + guarding access to its configuration state. + This can result in a deadlock when qeth_l2_stop_card() - + called under the conf_mutex - blocks on flush_workqueue() + to wait for the completion of pending bridgeport workers. + Such workers would also need to aquire the conf_mutex, + stalling indefinitely. +Solution: Introduce a lock that specifically guards the bridgeport + configuration, so that the workers no longer need the + conf_mutex. +Reproduction: Tear down a L2 device concurrently to when qeth processes + a bridgeport event on that device. + +Upstream-Description: + + s390/qeth: fix potential deadlock on workqueue flush + + The L2 bridgeport code uses the coarse 'conf_mutex' for guarding access + to its configuration state. + This can result in a deadlock when qeth_l2_stop_card() - called under the + conf_mutex - blocks on flush_workqueue() to wait for the completion of + pending bridgeport workers. Such workers would also need to aquire + the conf_mutex, stalling indefinitely. + + Introduce a lock that specifically guards the bridgeport configuration, + so that the workers no longer need the conf_mutex. + Wrapping qeth_l2_promisc_to_bridge() in this fine-grained lock then also + fixes a theoretical race against a concurrent qeth_bridge_port_role_store() + operation. + +Fixes: c0a2e4d10d93 ("s390/qeth: conclude all event processing before offlining a card") +Signed-off-by: Julian Wiedmann +Reviewed-by: Alexandra Winter +Signed-off-by: David S. Miller +Signed-off-by: Petr Tesarik +[ ptesarik: First hunk patches code added by upstream commit + 59b757a9bf2bd30173029fa7bd6821239d6a7242, but since SLE15-SP1 also + misses commit d0c748256611f8612728bcbf9933eb103c077763 (and possibly + other changes), the mutex cannot be added to qeth_l2_set_rx_mode, + as that one runs under netif_addr_lock_bh(). ] +--- + drivers/s390/net/qeth_core.h | 1 + + drivers/s390/net/qeth_l2_main.c | 13 +++++++++---- + drivers/s390/net/qeth_l2_sys.c | 14 +++++++++++++- + 3 files changed, 23 insertions(+), 5 deletions(-) + +--- a/drivers/s390/net/qeth_core.h ++++ b/drivers/s390/net/qeth_core.h +@@ -819,6 +819,7 @@ struct qeth_card { + struct service_level qeth_service_level; + struct qdio_ssqd_desc ssqd; + debug_info_t *debug; ++ struct mutex sbp_lock; + struct mutex conf_mutex; + struct mutex discipline_mutex; + struct napi_struct napi; +--- a/drivers/s390/net/qeth_l2_main.c ++++ b/drivers/s390/net/qeth_l2_main.c +@@ -801,6 +801,8 @@ static int qeth_l2_probe_device(struct c + struct qeth_card *card = dev_get_drvdata(&gdev->dev); + int rc; + ++ mutex_init(&card->sbp_lock); ++ + if (gdev->dev.type == &qeth_generic_devtype) { + rc = qeth_l2_create_device_attributes(&gdev->dev); + if (rc) +@@ -968,10 +970,13 @@ static int __qeth_l2_set_online(struct c + rc = -ENODEV; + goto out_remove; + } ++ ++ mutex_lock(&card->sbp_lock); + qeth_bridgeport_query_support(card); + if (card->options.sbp.supported_funcs) + dev_info(&card->gdev->dev, + "The device represents a Bridge Capable Port\n"); ++ mutex_unlock(&card->sbp_lock); + + rc = qeth_l2_setup_netdev(card, carrier_ok); + if (rc) +@@ -1412,9 +1417,9 @@ static void qeth_bridge_state_change_wor + + /* Role should not change by itself, but if it did, */ + /* information from the hardware is authoritative. */ +- mutex_lock(&data->card->conf_mutex); ++ mutex_lock(&data->card->sbp_lock); + data->card->options.sbp.role = entry->role; +- mutex_unlock(&data->card->conf_mutex); ++ mutex_unlock(&data->card->sbp_lock); + + snprintf(env_locrem, sizeof(env_locrem), "BRIDGEPORT=statechange"); + snprintf(env_role, sizeof(env_role), "ROLE=%s", +@@ -1480,9 +1485,9 @@ static void qeth_bridge_host_event_worke + : (data->hostevs.lost_event_mask == 0x02) + ? "Bridge port state change" + : "Unknown reason"); +- mutex_lock(&data->card->conf_mutex); ++ mutex_lock(&data->card->sbp_lock); + data->card->options.sbp.hostnotification = 0; +- mutex_unlock(&data->card->conf_mutex); ++ mutex_unlock(&data->card->sbp_lock); + qeth_bridge_emit_host_event(data->card, anev_abort, + 0, NULL, NULL); + } else +--- a/drivers/s390/net/qeth_l2_sys.c ++++ b/drivers/s390/net/qeth_l2_sys.c +@@ -23,6 +23,7 @@ static ssize_t qeth_bridge_port_role_sta + if (qeth_l2_vnicc_is_in_use(card)) + return sprintf(buf, "n/a (VNIC characteristics)\n"); + ++ mutex_lock(&card->sbp_lock); + if (qeth_card_hw_is_reachable(card) && + card->options.sbp.supported_funcs) + rc = qeth_bridgeport_query_ports(card, +@@ -56,6 +57,7 @@ static ssize_t qeth_bridge_port_role_sta + else + rc = sprintf(buf, "%s\n", word); + } ++ mutex_unlock(&card->sbp_lock); + + return rc; + } +@@ -90,6 +92,7 @@ static ssize_t qeth_bridge_port_role_sto + return -EINVAL; + + mutex_lock(&card->conf_mutex); ++ mutex_lock(&card->sbp_lock); + + if (qeth_l2_vnicc_is_in_use(card)) + rc = -EBUSY; +@@ -103,6 +106,7 @@ static ssize_t qeth_bridge_port_role_sto + } else + card->options.sbp.role = role; + ++ mutex_unlock(&card->sbp_lock); + mutex_unlock(&card->conf_mutex); + + return rc ? rc : count; +@@ -157,6 +161,7 @@ static ssize_t qeth_bridgeport_hostnotif + return rc; + + mutex_lock(&card->conf_mutex); ++ mutex_lock(&card->sbp_lock); + + if (qeth_l2_vnicc_is_in_use(card)) + rc = -EBUSY; +@@ -167,6 +172,7 @@ static ssize_t qeth_bridgeport_hostnotif + } else + card->options.sbp.hostnotification = enable; + ++ mutex_unlock(&card->sbp_lock); + mutex_unlock(&card->conf_mutex); + + return rc ? rc : count; +@@ -222,6 +228,7 @@ static ssize_t qeth_bridgeport_reflect_s + return -EINVAL; + + mutex_lock(&card->conf_mutex); ++ mutex_lock(&card->sbp_lock); + + if (qeth_l2_vnicc_is_in_use(card)) + rc = -EBUSY; +@@ -233,6 +240,7 @@ static ssize_t qeth_bridgeport_reflect_s + rc = 0; + } + ++ mutex_unlock(&card->sbp_lock); + mutex_unlock(&card->conf_mutex); + + return rc ? rc : count; +@@ -268,6 +276,8 @@ void qeth_l2_setup_bridgeport_attrs(stru + return; + if (!card->options.sbp.supported_funcs) + return; ++ ++ mutex_lock(&card->sbp_lock); + if (card->options.sbp.role != QETH_SBP_ROLE_NONE) { + /* Conditional to avoid spurious error messages */ + qeth_bridgeport_setrole(card, card->options.sbp.role); +@@ -279,8 +289,10 @@ void qeth_l2_setup_bridgeport_attrs(stru + rc = qeth_bridgeport_an_set(card, 1); + if (rc) + card->options.sbp.hostnotification = 0; +- } else ++ } else { + qeth_bridgeport_an_set(card, 0); ++ } ++ mutex_unlock(&card->sbp_lock); + } + + /* VNIC CHARS support */ diff --git a/patches.suse/s390-uv-fix-handling-of-length-extensions b/patches.suse/s390-uv-fix-handling-of-length-extensions new file mode 100644 index 0000000..3fdefcb --- /dev/null +++ b/patches.suse/s390-uv-fix-handling-of-length-extensions @@ -0,0 +1,36 @@ +From: Christian Borntraeger +Date: Mon, 10 Feb 2020 11:27:37 -0500 +Subject: s390/uv: Fix handling of length extensions +Git-commit: 27dc0700c3be7c681cea03c5230b93d02f623492 +Patch-mainline: v5.6-rc2 +References: git-fixes + +The query parameter block might contain additional information and can +be extended in the future. If the size of the block does not suffice we +get an error code of rc=0x100. The buffer will contain all information +up to the specified size and the hypervisor/guest simply do not need the +additional information as they do not know about the new data. That +means that we can (and must) accept rc=0x100 as success. + +Cc: stable@vger.kernel.org +Reviewed-by: Cornelia Huck +Fixes: 5abb9351dfd9 ("s390/uv: introduce guest side ultravisor code") +Signed-off-by: Christian Borntraeger +Signed-off-by: Vasily Gorbik +Acked-by: Petr Tesarik +--- + arch/s390/kernel/uv.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/arch/s390/kernel/uv.c ++++ b/arch/s390/kernel/uv.c +@@ -14,7 +14,8 @@ void uv_query_info(void) + if (!test_facility(158)) + return; + +- if (uv_call(0, (uint64_t)&uvcb)) ++ /* rc==0x100 means that there is additional data we do not process */ ++ if (uv_call(0, (uint64_t)&uvcb) && uvcb.header.rc != 0x100) + return; + + if (test_bit_inv(BIT_UVC_CMD_SET_SHARED_ACCESS, (unsigned long *)uvcb.inst_calls_list) && diff --git a/patches.suse/scsi-fc-Update-Descriptor-definition-and-add-RDF-and.patch b/patches.suse/scsi-fc-Update-Descriptor-definition-and-add-RDF-and.patch new file mode 100644 index 0000000..404de74 --- /dev/null +++ b/patches.suse/scsi-fc-Update-Descriptor-definition-and-add-RDF-and.patch @@ -0,0 +1,307 @@ +From: James Smart +Date: Mon, 10 Feb 2020 09:31:54 -0800 +Subject: scsi: fc: Update Descriptor definition and add RDF and Link Integrity + FPINs +Patch-mainline: v5.7-rc1 +Git-commit: 73ec6d2748dc35db2b32cf3c182a27c4a0837b9b +References: bsc#1164777 bsc#1164780 bsc#1165211 + +Update the FC headers for the RDF ELS and populate out the FPIN ELS and the +Link integrity FPIN payload. + +RDF is used to register for diagnostic events. +FPIN is how the fabric reports a diagnostic event. + +Specifically, this patch: + + - Adds the formal definition of TLV descriptors that are now used in a lot + of the FC spec. The simplistic fc_fn_desc structure, basically no more + than the tlv definition, is removed. + + - Small tlv helper functions are added as defines. + + - The list of known Descriptor tags (identifying the TLV) is expanded and + a name initializer introduced. + + - The LSRI descriptor, returned in many new ELS response payloads is + added. + + - The RDF ELS code is added, and the RDF request response structures + added. + + - The FPIN els definition is corrected. + + - A full definition of a Link Integrity Notification descriptor is added, + +[mkp: rolled in kbuild warning fix] + +Link: https://lore.kernel.org/r/20200210173155.547-2-jsmart2021@gmail.com +Reported-by: kbuild test robot +Signed-off-by: James Smart +Reviewed-by: Hannes Reinecke +Signed-off-by: Martin K. Petersen +Acked-by: Daniel Wagner +--- + include/uapi/scsi/fc/fc_els.h | 211 +++++++++++++++++++++++++++++++++++++++--- + 1 file changed, 196 insertions(+), 15 deletions(-) + +--- a/include/uapi/scsi/fc/fc_els.h ++++ b/include/uapi/scsi/fc/fc_els.h +@@ -21,6 +21,7 @@ + #define _FC_ELS_H_ + + #include ++#include + + /* + * Fibre Channel Switch - Enhanced Link Services definitions. +@@ -52,6 +53,7 @@ enum fc_els_cmd { + ELS_REC = 0x13, /* read exchange concise */ + ELS_SRR = 0x14, /* sequence retransmission request */ + ELS_FPIN = 0x16, /* Fabric Performance Impact Notification */ ++ ELS_RDF = 0x19, /* Register Diagnostic Functions */ + ELS_PRLI = 0x20, /* process login */ + ELS_PRLO = 0x21, /* process logout */ + ELS_SCN = 0x22, /* state change notification */ +@@ -120,6 +122,7 @@ enum fc_els_cmd { + [ELS_REC] = "REC", \ + [ELS_SRR] = "SRR", \ + [ELS_FPIN] = "FPIN", \ ++ [ELS_RDF] = "RDF", \ + [ELS_PRLI] = "PRLI", \ + [ELS_PRLO] = "PRLO", \ + [ELS_SCN] = "SCN", \ +@@ -220,6 +223,99 @@ enum fc_els_rjt_explan { + }; + + /* ++ * Link Service TLV Descriptor Tag Values ++ */ ++enum fc_ls_tlv_dtag { ++ ELS_DTAG_LS_REQ_INFO = 0x00000001, ++ /* Link Service Request Information Descriptor */ ++ ELS_DTAG_LNK_INTEGRITY = 0x00020001, ++ /* Link Integrity Notification Descriptor */ ++ ELS_DTAG_DELIVERY = 0x00020002, ++ /* Delivery Notification Descriptor */ ++ ELS_DTAG_PEER_CONGEST = 0x00020003, ++ /* Peer Congestion Notification Descriptor */ ++ ELS_DTAG_CONGESTION = 0x00020004, ++ /* Congestion Notification Descriptor */ ++ ELS_DTAG_FPIN_REGISTER = 0x00030001, ++ /* FPIN Registration Descriptor */ ++}; ++ ++/* ++ * Initializer useful for decoding table. ++ * Please keep this in sync with the above definitions. ++ */ ++#define FC_LS_TLV_DTAG_INIT { \ ++ { ELS_DTAG_LS_REQ_INFO, "Link Service Request Information" }, \ ++ { ELS_DTAG_LNK_INTEGRITY, "Link Integrity Notification" }, \ ++ { ELS_DTAG_DELIVERY, "Delivery Notification Present" }, \ ++ { ELS_DTAG_PEER_CONGEST, "Peer Congestion Notification" }, \ ++ { ELS_DTAG_CONGESTION, "Congestion Notification" }, \ ++ { ELS_DTAG_FPIN_REGISTER, "FPIN Registration" }, \ ++} ++ ++ ++/* ++ * Generic Link Service TLV Descriptor format ++ * ++ * This structure, as it defines no payload, will also be referred to ++ * as the "tlv header" - which contains the tag and len fields. ++ */ ++struct fc_tlv_desc { ++ __be32 desc_tag; /* Notification Descriptor Tag */ ++ __be32 desc_len; /* Length of Descriptor (in bytes). ++ * Size of descriptor excluding ++ * desc_tag and desc_len fields. ++ */ ++ __u8 desc_value[0]; /* Descriptor Value */ ++}; ++ ++/* Descriptor tag and len fields are considered the mandatory header ++ * for a descriptor ++ */ ++#define FC_TLV_DESC_HDR_SZ sizeof(struct fc_tlv_desc) ++ ++/* ++ * Macro, used when initializing payloads, to return the descriptor length. ++ * Length is size of descriptor minus the tag and len fields. ++ */ ++#define FC_TLV_DESC_LENGTH_FROM_SZ(desc) \ ++ (sizeof(desc) - FC_TLV_DESC_HDR_SZ) ++ ++/* Macro, used on received payloads, to return the descriptor length */ ++#define FC_TLV_DESC_SZ_FROM_LENGTH(tlv) \ ++ (__be32_to_cpu((tlv)->desc_len) + FC_TLV_DESC_HDR_SZ) ++ ++/* ++ * This helper is used to walk descriptors in a descriptor list. ++ * Given the address of the current descriptor, which minimally contains a ++ * tag and len field, calculate the address of the next descriptor based ++ * on the len field. ++ */ ++static inline void *fc_tlv_next_desc(void *desc) ++{ ++ struct fc_tlv_desc *tlv = desc; ++ ++ return (desc + FC_TLV_DESC_SZ_FROM_LENGTH(tlv)); ++} ++ ++ ++/* ++ * Link Service Request Information Descriptor ++ */ ++struct fc_els_lsri_desc { ++ __be32 desc_tag; /* descriptor tag (0x0000 0001) */ ++ __be32 desc_len; /* Length of Descriptor (in bytes) (4). ++ * Size of descriptor excluding ++ * desc_tag and desc_len fields. ++ */ ++ struct { ++ __u8 cmd; /* ELS cmd byte */ ++ __u8 bytes[3]; /* bytes 1..3 */ ++ } rqst_w0; /* Request word 0 */ ++}; ++ ++ ++/* + * Common service parameters (N ports). + */ + struct fc_els_csp { +@@ -831,24 +927,61 @@ enum fc_els_clid_ic { + }; + + ++enum fc_fpin_li_event_types { ++ FPIN_LI_UNKNOWN = 0x0, ++ FPIN_LI_LINK_FAILURE = 0x1, ++ FPIN_LI_LOSS_OF_SYNC = 0x2, ++ FPIN_LI_LOSS_OF_SIG = 0x3, ++ FPIN_LI_PRIM_SEQ_ERR = 0x4, ++ FPIN_LI_INVALID_TX_WD = 0x5, ++ FPIN_LI_INVALID_CRC = 0x6, ++ FPIN_LI_DEVICE_SPEC = 0xF, ++}; ++ + /* +- * Fabric Notification Descriptor Tag values ++ * Initializer useful for decoding table. ++ * Please keep this in sync with the above definitions. + */ +-enum fc_fn_dtag { +- ELS_FN_DTAG_LNK_INTEGRITY = 0x00020001, /* Link Integrity */ +- ELS_FN_DTAG_PEER_CONGEST = 0x00020003, /* Peer Congestion */ +- ELS_FN_DTAG_CONGESTION = 0x00020004, /* Congestion */ +-}; ++#define FC_FPIN_LI_EVT_TYPES_INIT { \ ++ { FPIN_LI_UNKNOWN, "Unknown" }, \ ++ { FPIN_LI_LINK_FAILURE, "Link Failure" }, \ ++ { FPIN_LI_LOSS_OF_SYNC, "Loss of Synchronization" }, \ ++ { FPIN_LI_LOSS_OF_SIG, "Loss of Signal" }, \ ++ { FPIN_LI_PRIM_SEQ_ERR, "Primitive Sequence Protocol Error" }, \ ++ { FPIN_LI_INVALID_TX_WD, "Invalid Transmission Word" }, \ ++ { FPIN_LI_INVALID_CRC, "Invalid CRC" }, \ ++ { FPIN_LI_DEVICE_SPEC, "Device Specific" }, \ ++} ++ + + /* +- * Fabric Notification Descriptor ++ * Link Integrity Notification Descriptor + */ +-struct fc_fn_desc { +- __be32 fn_desc_tag; /* Notification Descriptor Tag */ +- __be32 fn_desc_value_len; /* Length of Descriptor Value field +- * (in bytes) +- */ +- __u8 fn_desc_value[0]; /* Descriptor Value */ ++struct fc_fn_li_desc { ++ __be32 desc_tag; /* Descriptor Tag (0x00020001) */ ++ __be32 desc_len; /* Length of Descriptor (in bytes). ++ * Size of descriptor excluding ++ * desc_tag and desc_len fields. ++ */ ++ __be64 detecting_wwpn; /* Port Name that detected event */ ++ __be64 attached_wwpn; /* Port Name of device attached to ++ * detecting Port Name ++ */ ++ __be16 event_type; /* see enum fc_fpin_li_event_types */ ++ __be16 event_modifier; /* Implementation specific value ++ * describing the event type ++ */ ++ __be32 event_threshold;/* duration in ms of the link ++ * integrity detection cycle ++ */ ++ __be32 event_count; /* minimum number of event ++ * occurrences during the event ++ * threshold to caause the LI event ++ */ ++ __be32 pname_count; /* number of portname_list elements */ ++ __be64 pname_list[0]; /* list of N_Port_Names accessible ++ * through the attached port ++ */ + }; + + /* +@@ -857,8 +990,56 @@ struct fc_fn_desc { + struct fc_els_fpin { + __u8 fpin_cmd; /* command (0x16) */ + __u8 fpin_zero[3]; /* specified as zero - part of cmd */ +- __be32 fpin_desc_cnt; /* count of descriptors */ +- struct fc_fn_desc fpin_desc[0]; /* Descriptor list */ ++ __be32 desc_len; /* Length of Descriptor List (in bytes). ++ * Size of ELS excluding fpin_cmd, ++ * fpin_zero and desc_len fields. ++ */ ++ struct fc_tlv_desc fpin_desc[0]; /* Descriptor list */ ++}; ++ ++/* Diagnostic Function Descriptor - FPIN Registration */ ++struct fc_df_desc_fpin_reg { ++ __be32 desc_tag; /* FPIN Registration (0x00030001) */ ++ __be32 desc_len; /* Length of Descriptor (in bytes). ++ * Size of descriptor excluding ++ * desc_tag and desc_len fields. ++ */ ++ __be32 count; /* Number of desc_tags elements */ ++ __be32 desc_tags[0]; /* Array of Descriptor Tags. ++ * Each tag indicates a function ++ * supported by the N_Port (request) ++ * or by the N_Port and Fabric ++ * Controller (reply; may be a subset ++ * of the request). ++ * See ELS_FN_DTAG_xxx for tag values. ++ */ ++}; ++ ++/* ++ * ELS_RDF - Register Diagnostic Functions ++ */ ++struct fc_els_rdf { ++ __u8 fpin_cmd; /* command (0x19) */ ++ __u8 fpin_zero[3]; /* specified as zero - part of cmd */ ++ __be32 desc_len; /* Length of Descriptor List (in bytes). ++ * Size of ELS excluding fpin_cmd, ++ * fpin_zero and desc_len fields. ++ */ ++ struct fc_tlv_desc desc[0]; /* Descriptor list */ ++}; ++ ++/* ++ * ELS RDF LS_ACC Response. ++ */ ++struct fc_els_rdf_resp { ++ struct fc_els_ls_acc acc_hdr; ++ __be32 desc_list_len; /* Length of response (in ++ * bytes). Excludes acc_hdr ++ * and desc_list_len fields. ++ */ ++ struct fc_els_lsri_desc lsri; ++ struct fc_tlv_desc desc[0]; /* Supported Descriptor list */ + }; + ++ + #endif /* _FC_ELS_H_ */ diff --git a/patches.suse/scsi-fnic-do-not-queue-commands-during-fwreset.patch b/patches.suse/scsi-fnic-do-not-queue-commands-during-fwreset.patch new file mode 100644 index 0000000..9fe8250 --- /dev/null +++ b/patches.suse/scsi-fnic-do-not-queue-commands-during-fwreset.patch @@ -0,0 +1,40 @@ +From: Hannes Reinecke +Date: Thu, 16 Jan 2020 11:20:53 +0100 +Subject: scsi: fnic: do not queue commands during fwreset +Git-commit: 0e2209629fec427ba75a6351486153a9feddd36b +Patch-mainline: v5.5 +References: bsc#1146539 + +When a link is going down the driver will be calling fnic_cleanup_io(), +which will traverse all commands and calling 'done' for each found command. +While the traversal is handled under the host_lock, calling 'done' happens +after the host_lock is being dropped. + +As fnic_queuecommand_lck() is being called with the host_lock held, it +might well be that it will pick the command being selected for abortion +from the above routine and enqueue it for sending, but then 'done' is being +called on that very command from the above routine. + +Which of course confuses the hell out of the scsi midlayer. + +So fix this by not queueing commands when fnic_cleanup_io is active. + +Link: https://lore.kernel.org/r/20200116102053.62755-1-hare@suse.de +Signed-off-by: Hannes Reinecke +Signed-off-by: Martin K. Petersen +--- + drivers/scsi/fnic/fnic_scsi.c | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/drivers/scsi/fnic/fnic_scsi.c ++++ b/drivers/scsi/fnic/fnic_scsi.c +@@ -446,6 +446,9 @@ static int fnic_queuecommand_lck(struct + if (unlikely(fnic_chk_state_flags_locked(fnic, FNIC_FLAGS_IO_BLOCKED))) + return SCSI_MLQUEUE_HOST_BUSY; + ++ if (unlikely(fnic_chk_state_flags_locked(fnic, FNIC_FLAGS_FWRESET))) ++ return SCSI_MLQUEUE_HOST_BUSY; ++ + rport = starget_to_rport(scsi_target(sc->device)); + if (!rport) { + FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host, diff --git a/patches.suse/scsi-ibmvfc-Add-failed-PRLI-to-cmd_status-lookup-arr.patch b/patches.suse/scsi-ibmvfc-Add-failed-PRLI-to-cmd_status-lookup-arr.patch new file mode 100644 index 0000000..538f617 --- /dev/null +++ b/patches.suse/scsi-ibmvfc-Add-failed-PRLI-to-cmd_status-lookup-arr.patch @@ -0,0 +1,36 @@ +From 95237c25d8d08ebc451dd2d793f7e765f57b0c9f Mon Sep 17 00:00:00 2001 +From: Tyrel Datwyler +Date: Wed, 20 Mar 2019 14:56:52 -0500 +Subject: [PATCH] scsi: ibmvfc: Add failed PRLI to cmd_status lookup array + +References: bsc#1161951 ltc#183551 +Patch-mainline: v5.1-rc3 +Git-commit: 95237c25d8d08ebc451dd2d793f7e765f57b0c9f + +The VIOS uses the SCSI_ERROR class to report PRLI failures. These errors +are indicated with the combination of a IBMVFC_FC_SCSI_ERROR return status +and 0x8000 error code. Add these codes to cmd_status[] with appropriate +human readable error message. + +Signed-off-by: Tyrel Datwyler +Signed-off-by: Martin K. Petersen +Acked-by: Michal Suchanek +--- + drivers/scsi/ibmvscsi/ibmvfc.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/scsi/ibmvscsi/ibmvfc.c b/drivers/scsi/ibmvscsi/ibmvfc.c +index c3ce27039552..18ee2a8ec3d5 100644 +--- a/drivers/scsi/ibmvscsi/ibmvfc.c ++++ b/drivers/scsi/ibmvscsi/ibmvfc.c +@@ -139,6 +139,7 @@ static const struct { + { IBMVFC_FC_FAILURE, IBMVFC_VENDOR_SPECIFIC, DID_ERROR, 1, 1, "vendor specific" }, + + { IBMVFC_FC_SCSI_ERROR, 0, DID_OK, 1, 0, "SCSI error" }, ++ { IBMVFC_FC_SCSI_ERROR, IBMVFC_COMMAND_FAILED, DID_ERROR, 0, 1, "PRLI to device failed." }, + }; + + static void ibmvfc_npiv_login(struct ibmvfc_host *); +-- +2.23.0 + diff --git a/patches.suse/scsi-ibmvfc-Avoid-loss-of-all-paths-during-SVC-node-.patch b/patches.suse/scsi-ibmvfc-Avoid-loss-of-all-paths-during-SVC-node-.patch new file mode 100644 index 0000000..0bfee41 --- /dev/null +++ b/patches.suse/scsi-ibmvfc-Avoid-loss-of-all-paths-during-SVC-node-.patch @@ -0,0 +1,461 @@ +From 54b04c99d02e4c3e442fcb1e77f4ca6515be8826 Mon Sep 17 00:00:00 2001 +From: Brian King +Date: Wed, 26 Feb 2020 19:45:43 -0600 +Subject: [PATCH] scsi: ibmvfc: Avoid loss of all paths during SVC node reboot + +References: bsc#1161951 ltc#183551 +Patch-mainline: v5.7-rc1 +Git-commit: ed830385a2b1fbfcd1d08744b00587df5592162b + +When an SVC node goes down as part of a node reboot, its WWPNs are moved to +the remaining node. When the node is back online, its WWPNs are moved +back. The result is that the WWPN moves from one NPort_ID to another, then +back again. The ibmvfc driver was forcing the old port to be removed, but +not sending an implicit logout. When the WWPN showed up at the new +location, the PLOGI failed as there was already a login established for the +old scsi id. The patch below fixes this by ensuring we always send an +implicit logout for any scsi id associated with an rport prior to calling +fc_remote_port_delete. + +Link: https://lore.kernel.org/r/1582767943-16611-1-git-send-email-brking@linux.vnet.ibm.com +Signed-off-by: Brian King +Signed-off-by: Martin K. Petersen +Acked-by: Michal Suchanek +--- + drivers/scsi/ibmvscsi/ibmvfc.c | 207 +++++++++++++++++++++++++++------ + drivers/scsi/ibmvscsi/ibmvfc.h | 3 +- + 2 files changed, 173 insertions(+), 37 deletions(-) + +diff --git a/drivers/scsi/ibmvscsi/ibmvfc.c b/drivers/scsi/ibmvscsi/ibmvfc.c +index df897df5cafe..84dd8c5145c8 100644 +--- a/drivers/scsi/ibmvscsi/ibmvfc.c ++++ b/drivers/scsi/ibmvscsi/ibmvfc.c +@@ -133,6 +133,7 @@ static void ibmvfc_tgt_send_prli(struct ibmvfc_target *); + static void ibmvfc_tgt_send_plogi(struct ibmvfc_target *); + static void ibmvfc_tgt_query_target(struct ibmvfc_target *); + static void ibmvfc_npiv_logout(struct ibmvfc_host *); ++static void ibmvfc_tgt_implicit_logout_and_del(struct ibmvfc_target *); + + static const char *unknown_error = "unknown error"; + +@@ -413,22 +414,44 @@ static const char *ibmvfc_get_fc_type(u16 status) + * @tgt: ibmvfc target struct + * @action: action to perform + * ++ * Returns: ++ * 0 if action changed / non-zero if not changed + **/ +-static void ibmvfc_set_tgt_action(struct ibmvfc_target *tgt, ++static int ibmvfc_set_tgt_action(struct ibmvfc_target *tgt, + enum ibmvfc_target_action action) + { ++ int rc = -EINVAL; ++ + switch (tgt->action) { ++ case IBMVFC_TGT_ACTION_LOGOUT_RPORT: ++ if (action == IBMVFC_TGT_ACTION_LOGOUT_RPORT_WAIT || ++ action == IBMVFC_TGT_ACTION_DEL_RPORT) { ++ tgt->action = action; ++ rc = 0; ++ } ++ break; ++ case IBMVFC_TGT_ACTION_LOGOUT_RPORT_WAIT: ++ if (action == IBMVFC_TGT_ACTION_DEL_RPORT) { ++ tgt->action = action; ++ rc = 0; ++ } ++ break; + case IBMVFC_TGT_ACTION_DEL_RPORT: +- if (action == IBMVFC_TGT_ACTION_DELETED_RPORT) ++ if (action == IBMVFC_TGT_ACTION_DELETED_RPORT) { + tgt->action = action; ++ rc = 0; ++ } + case IBMVFC_TGT_ACTION_DELETED_RPORT: + break; + default: +- if (action == IBMVFC_TGT_ACTION_DEL_RPORT) ++ if (action >= IBMVFC_TGT_ACTION_LOGOUT_RPORT) + tgt->add_rport = 0; + tgt->action = action; ++ rc = 0; + break; + } ++ ++ return rc; + } + + /** +@@ -536,6 +559,19 @@ static void ibmvfc_reinit_host(struct ibmvfc_host *vhost) + wake_up(&vhost->work_wait_q); + } + ++/** ++ * ibmvfc_del_tgt - Schedule cleanup and removal of the target ++ * @tgt: ibmvfc target struct ++ * @job_step: job step to perform ++ * ++ **/ ++static void ibmvfc_del_tgt(struct ibmvfc_target *tgt) ++{ ++ if (!ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_LOGOUT_RPORT)) ++ tgt->job_step = ibmvfc_tgt_implicit_logout_and_del; ++ wake_up(&tgt->vhost->work_wait_q); ++} ++ + /** + * ibmvfc_link_down - Handle a link down event from the adapter + * @vhost: ibmvfc host struct +@@ -550,7 +586,7 @@ static void ibmvfc_link_down(struct ibmvfc_host *vhost, + ENTER; + scsi_block_requests(vhost->host); + list_for_each_entry(tgt, &vhost->targets, queue) +- ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_DEL_RPORT); ++ ibmvfc_del_tgt(tgt); + ibmvfc_set_host_state(vhost, state); + ibmvfc_set_host_action(vhost, IBMVFC_HOST_ACTION_TGT_DEL); + vhost->events_to_log |= IBMVFC_AE_LINKDOWN; +@@ -583,7 +619,7 @@ static void ibmvfc_init_host(struct ibmvfc_host *vhost) + vhost->async_crq.cur = 0; + + list_for_each_entry(tgt, &vhost->targets, queue) +- ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_DEL_RPORT); ++ ibmvfc_del_tgt(tgt); + scsi_block_requests(vhost->host); + ibmvfc_set_host_action(vhost, IBMVFC_HOST_ACTION_INIT); + vhost->job_step = ibmvfc_npiv_login; +@@ -1500,7 +1536,7 @@ static void ibmvfc_relogin(struct scsi_device *sdev) + + list_for_each_entry(tgt, &vhost->targets, queue) { + if (rport == tgt->rport) { +- ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_DEL_RPORT); ++ ibmvfc_del_tgt(tgt); + break; + } + } +@@ -2686,7 +2722,7 @@ static void ibmvfc_handle_async(struct ibmvfc_async_crq *crq, + if (tgt->need_login && be64_to_cpu(crq->event) == IBMVFC_AE_ELS_LOGO) + tgt->logo_rcvd = 1; + if (!tgt->need_login || be64_to_cpu(crq->event) == IBMVFC_AE_ELS_PLOGI) { +- ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_DEL_RPORT); ++ ibmvfc_del_tgt(tgt); + ibmvfc_reinit_host(vhost); + } + } +@@ -3220,8 +3256,8 @@ static void ibmvfc_tasklet(void *data) + static void ibmvfc_init_tgt(struct ibmvfc_target *tgt, + void (*job_step) (struct ibmvfc_target *)) + { +- ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_INIT); +- tgt->job_step = job_step; ++ if (!ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_INIT)) ++ tgt->job_step = job_step; + wake_up(&tgt->vhost->work_wait_q); + } + +@@ -3237,7 +3273,7 @@ static int ibmvfc_retry_tgt_init(struct ibmvfc_target *tgt, + void (*job_step) (struct ibmvfc_target *)) + { + if (++tgt->init_retries > IBMVFC_MAX_TGT_INIT_RETRIES) { +- ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_DEL_RPORT); ++ ibmvfc_del_tgt(tgt); + wake_up(&tgt->vhost->work_wait_q); + return 0; + } else +@@ -3312,13 +3348,13 @@ static void ibmvfc_tgt_prli_done(struct ibmvfc_event *evt) + tgt->ids.roles |= FC_PORT_ROLE_FCP_INITIATOR; + tgt->add_rport = 1; + } else +- ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_DEL_RPORT); ++ ibmvfc_del_tgt(tgt); + } else if (prli_rsp[index].retry) + ibmvfc_retry_tgt_init(tgt, ibmvfc_tgt_send_prli); + else +- ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_DEL_RPORT); ++ ibmvfc_del_tgt(tgt); + } else +- ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_DEL_RPORT); ++ ibmvfc_del_tgt(tgt); + break; + case IBMVFC_MAD_DRIVER_FAILED: + break; +@@ -3335,7 +3371,7 @@ static void ibmvfc_tgt_prli_done(struct ibmvfc_event *evt) + else if (ibmvfc_retry_cmd(be16_to_cpu(rsp->status), be16_to_cpu(rsp->error))) + level += ibmvfc_retry_tgt_init(tgt, ibmvfc_tgt_send_prli); + else +- ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_DEL_RPORT); ++ ibmvfc_del_tgt(tgt); + + tgt_log(tgt, level, "Process Login failed: %s (%x:%x) rc=0x%02X\n", + ibmvfc_get_cmd_error(be16_to_cpu(rsp->status), be16_to_cpu(rsp->error)), +@@ -3434,7 +3470,7 @@ static void ibmvfc_tgt_plogi_done(struct ibmvfc_event *evt) + if (ibmvfc_retry_cmd(be16_to_cpu(rsp->status), be16_to_cpu(rsp->error))) + level += ibmvfc_retry_tgt_init(tgt, ibmvfc_tgt_send_plogi); + else +- ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_DEL_RPORT); ++ ibmvfc_del_tgt(tgt); + + tgt_log(tgt, level, "Port Login failed: %s (%x:%x) %s (%x) %s (%x) rc=0x%02X\n", + ibmvfc_get_cmd_error(be16_to_cpu(rsp->status), be16_to_cpu(rsp->error)), +@@ -3515,33 +3551,28 @@ static void ibmvfc_tgt_implicit_logout_done(struct ibmvfc_event *evt) + break; + } + +- if (vhost->action == IBMVFC_HOST_ACTION_TGT_INIT) +- ibmvfc_init_tgt(tgt, ibmvfc_tgt_send_plogi); +- else if (vhost->action == IBMVFC_HOST_ACTION_QUERY_TGTS && +- tgt->scsi_id != tgt->new_scsi_id) +- ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_DEL_RPORT); ++ ibmvfc_init_tgt(tgt, ibmvfc_tgt_send_plogi); + kref_put(&tgt->kref, ibmvfc_release_tgt); + wake_up(&vhost->work_wait_q); + } + + /** +- * ibmvfc_tgt_implicit_logout - Initiate an Implicit Logout for specified target ++ * __ibmvfc_tgt_get_implicit_logout_evt - Allocate and init an event for implicit logout + * @tgt: ibmvfc target struct + * ++ * Returns: ++ * Allocated and initialized ibmvfc_event struct + **/ +-static void ibmvfc_tgt_implicit_logout(struct ibmvfc_target *tgt) ++static struct ibmvfc_event *__ibmvfc_tgt_get_implicit_logout_evt(struct ibmvfc_target *tgt, ++ void (*done) (struct ibmvfc_event *)) + { + struct ibmvfc_implicit_logout *mad; + struct ibmvfc_host *vhost = tgt->vhost; + struct ibmvfc_event *evt; + +- if (vhost->discovery_threads >= disc_threads) +- return; +- + kref_get(&tgt->kref); + evt = ibmvfc_get_event(vhost); +- vhost->discovery_threads++; +- ibmvfc_init_event(evt, ibmvfc_tgt_implicit_logout_done, IBMVFC_MAD_FORMAT); ++ ibmvfc_init_event(evt, done, IBMVFC_MAD_FORMAT); + evt->tgt = tgt; + mad = &evt->iu.implicit_logout; + memset(mad, 0, sizeof(*mad)); +@@ -3549,6 +3580,25 @@ static void ibmvfc_tgt_implicit_logout(struct ibmvfc_target *tgt) + mad->common.opcode = cpu_to_be32(IBMVFC_IMPLICIT_LOGOUT); + mad->common.length = cpu_to_be16(sizeof(*mad)); + mad->old_scsi_id = cpu_to_be64(tgt->scsi_id); ++ return evt; ++} ++ ++/** ++ * ibmvfc_tgt_implicit_logout - Initiate an Implicit Logout for specified target ++ * @tgt: ibmvfc target struct ++ * ++ **/ ++static void ibmvfc_tgt_implicit_logout(struct ibmvfc_target *tgt) ++{ ++ struct ibmvfc_host *vhost = tgt->vhost; ++ struct ibmvfc_event *evt; ++ ++ if (vhost->discovery_threads >= disc_threads) ++ return; ++ ++ vhost->discovery_threads++; ++ evt = __ibmvfc_tgt_get_implicit_logout_evt(tgt, ++ ibmvfc_tgt_implicit_logout_done); + + ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_INIT_WAIT); + if (ibmvfc_send_event(evt, vhost, default_timeout)) { +@@ -3559,6 +3609,53 @@ static void ibmvfc_tgt_implicit_logout(struct ibmvfc_target *tgt) + tgt_dbg(tgt, "Sent Implicit Logout\n"); + } + ++/** ++ * ibmvfc_tgt_implicit_logout_and_del_done - Completion handler for Implicit Logout MAD ++ * @evt: ibmvfc event struct ++ * ++ **/ ++static void ibmvfc_tgt_implicit_logout_and_del_done(struct ibmvfc_event *evt) ++{ ++ struct ibmvfc_target *tgt = evt->tgt; ++ struct ibmvfc_host *vhost = evt->vhost; ++ struct ibmvfc_passthru_mad *mad = &evt->xfer_iu->passthru; ++ u32 status = be16_to_cpu(mad->common.status); ++ ++ vhost->discovery_threads--; ++ ibmvfc_free_event(evt); ++ ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_DEL_RPORT); ++ ++ tgt_dbg(tgt, "Implicit Logout %s\n", (status == IBMVFC_MAD_SUCCESS) ? "succeeded" : "failed"); ++ kref_put(&tgt->kref, ibmvfc_release_tgt); ++ wake_up(&vhost->work_wait_q); ++} ++ ++/** ++ * ibmvfc_tgt_implicit_logout_and_del - Initiate an Implicit Logout for specified target ++ * @tgt: ibmvfc target struct ++ * ++ **/ ++static void ibmvfc_tgt_implicit_logout_and_del(struct ibmvfc_target *tgt) ++{ ++ struct ibmvfc_host *vhost = tgt->vhost; ++ struct ibmvfc_event *evt; ++ ++ if (vhost->discovery_threads >= disc_threads) ++ return NULL; ++ ++ vhost->discovery_threads++; ++ evt = __ibmvfc_tgt_get_implicit_logout_evt(tgt, ++ ibmvfc_tgt_implicit_logout_and_del_done); ++ ++ ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_LOGOUT_RPORT_WAIT); ++ if (ibmvfc_send_event(evt, vhost, default_timeout)) { ++ vhost->discovery_threads--; ++ ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_DEL_RPORT); ++ kref_put(&tgt->kref, ibmvfc_release_tgt); ++ } else ++ tgt_dbg(tgt, "Sent Implicit Logout\n"); ++} ++ + /** + * ibmvfc_adisc_needs_plogi - Does device need PLOGI? + * @mad: ibmvfc passthru mad struct +@@ -3600,13 +3697,13 @@ static void ibmvfc_tgt_adisc_done(struct ibmvfc_event *evt) + case IBMVFC_MAD_SUCCESS: + tgt_dbg(tgt, "ADISC succeeded\n"); + if (ibmvfc_adisc_needs_plogi(mad, tgt)) +- ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_DEL_RPORT); ++ ibmvfc_del_tgt(tgt); + break; + case IBMVFC_MAD_DRIVER_FAILED: + break; + case IBMVFC_MAD_FAILED: + default: +- ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_DEL_RPORT); ++ ibmvfc_del_tgt(tgt); + fc_reason = (be32_to_cpu(mad->fc_iu.response[1]) & 0x00ff0000) >> 16; + fc_explain = (be32_to_cpu(mad->fc_iu.response[1]) & 0x0000ff00) >> 8; + tgt_info(tgt, "ADISC failed: %s (%x:%x) %s (%x) %s (%x) rc=0x%02X\n", +@@ -3799,9 +3896,8 @@ static void ibmvfc_tgt_query_target_done(struct ibmvfc_event *evt) + switch (status) { + case IBMVFC_MAD_SUCCESS: + tgt_dbg(tgt, "Query Target succeeded\n"); +- tgt->new_scsi_id = be64_to_cpu(rsp->scsi_id); + if (be64_to_cpu(rsp->scsi_id) != tgt->scsi_id) +- ibmvfc_init_tgt(tgt, ibmvfc_tgt_implicit_logout); ++ ibmvfc_del_tgt(tgt); + else + ibmvfc_init_tgt(tgt, ibmvfc_tgt_adisc); + break; +@@ -3815,11 +3911,11 @@ static void ibmvfc_tgt_query_target_done(struct ibmvfc_event *evt) + if ((be16_to_cpu(rsp->status) & IBMVFC_FABRIC_MAPPED) == IBMVFC_FABRIC_MAPPED && + be16_to_cpu(rsp->error) == IBMVFC_UNABLE_TO_PERFORM_REQ && + be16_to_cpu(rsp->fc_explain) == IBMVFC_PORT_NAME_NOT_REG) +- ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_DEL_RPORT); ++ ibmvfc_del_tgt(tgt); + else if (ibmvfc_retry_cmd(be16_to_cpu(rsp->status), be16_to_cpu(rsp->error))) + level += ibmvfc_retry_tgt_init(tgt, ibmvfc_tgt_query_target); + else +- ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_DEL_RPORT); ++ ibmvfc_del_tgt(tgt); + + tgt_log(tgt, level, "Query Target failed: %s (%x:%x) %s (%x) %s (%x) rc=0x%02X\n", + ibmvfc_get_cmd_error(be16_to_cpu(rsp->status), be16_to_cpu(rsp->error)), +@@ -3896,7 +3992,6 @@ static int ibmvfc_alloc_target(struct ibmvfc_host *vhost, u64 scsi_id) + tgt = mempool_alloc(vhost->tgt_pool, GFP_NOIO); + memset(tgt, 0, sizeof(*tgt)); + tgt->scsi_id = scsi_id; +- tgt->new_scsi_id = scsi_id; + tgt->vhost = vhost; + tgt->need_login = 1; + tgt->cancel_key = vhost->task_set++; +@@ -4188,6 +4283,25 @@ static int ibmvfc_dev_init_to_do(struct ibmvfc_host *vhost) + return 0; + } + ++/** ++ * ibmvfc_dev_logo_to_do - Is there target logout work to do? ++ * @vhost: ibmvfc host struct ++ * ++ * Returns: ++ * 1 if work to do / 0 if not ++ **/ ++static int ibmvfc_dev_logo_to_do(struct ibmvfc_host *vhost) ++{ ++ struct ibmvfc_target *tgt; ++ ++ list_for_each_entry(tgt, &vhost->targets, queue) { ++ if (tgt->action == IBMVFC_TGT_ACTION_LOGOUT_RPORT || ++ tgt->action == IBMVFC_TGT_ACTION_LOGOUT_RPORT_WAIT) ++ return 1; ++ } ++ return 0; ++} ++ + /** + * __ibmvfc_work_to_do - Is there task level work to do? (no locking) + * @vhost: ibmvfc host struct +@@ -4217,11 +4331,20 @@ static int __ibmvfc_work_to_do(struct ibmvfc_host *vhost) + if (tgt->action == IBMVFC_TGT_ACTION_INIT_WAIT) + return 0; + return 1; ++ case IBMVFC_HOST_ACTION_TGT_DEL: ++ case IBMVFC_HOST_ACTION_TGT_DEL_FAILED: ++ if (vhost->discovery_threads == disc_threads) ++ return 0; ++ list_for_each_entry(tgt, &vhost->targets, queue) ++ if (tgt->action == IBMVFC_TGT_ACTION_LOGOUT_RPORT) ++ return 1; ++ list_for_each_entry(tgt, &vhost->targets, queue) ++ if (tgt->action == IBMVFC_TGT_ACTION_LOGOUT_RPORT_WAIT) ++ return 0; ++ return 1; + case IBMVFC_HOST_ACTION_LOGO: + case IBMVFC_HOST_ACTION_INIT: + case IBMVFC_HOST_ACTION_ALLOC_TGTS: +- case IBMVFC_HOST_ACTION_TGT_DEL: +- case IBMVFC_HOST_ACTION_TGT_DEL_FAILED: + case IBMVFC_HOST_ACTION_QUERY: + case IBMVFC_HOST_ACTION_RESET: + case IBMVFC_HOST_ACTION_REENABLE: +@@ -4390,6 +4513,18 @@ static void ibmvfc_do_work(struct ibmvfc_host *vhost) + break; + case IBMVFC_HOST_ACTION_TGT_DEL: + case IBMVFC_HOST_ACTION_TGT_DEL_FAILED: ++ list_for_each_entry(tgt, &vhost->targets, queue) { ++ if (tgt->action == IBMVFC_TGT_ACTION_LOGOUT_RPORT) { ++ tgt->job_step(tgt); ++ break; ++ } ++ } ++ ++ if (ibmvfc_dev_logo_to_do(vhost)) { ++ spin_unlock_irqrestore(vhost->host->host_lock, flags); ++ return; ++ } ++ + list_for_each_entry(tgt, &vhost->targets, queue) { + if (tgt->action == IBMVFC_TGT_ACTION_DEL_RPORT) { + tgt_dbg(tgt, "Deleting rport\n"); +diff --git a/drivers/scsi/ibmvscsi/ibmvfc.h b/drivers/scsi/ibmvscsi/ibmvfc.h +index 7da89f4d26b2..907889f1fa9d 100644 +--- a/drivers/scsi/ibmvscsi/ibmvfc.h ++++ b/drivers/scsi/ibmvscsi/ibmvfc.h +@@ -596,6 +596,8 @@ enum ibmvfc_target_action { + IBMVFC_TGT_ACTION_NONE = 0, + IBMVFC_TGT_ACTION_INIT, + IBMVFC_TGT_ACTION_INIT_WAIT, ++ IBMVFC_TGT_ACTION_LOGOUT_RPORT, ++ IBMVFC_TGT_ACTION_LOGOUT_RPORT_WAIT, + IBMVFC_TGT_ACTION_DEL_RPORT, + IBMVFC_TGT_ACTION_DELETED_RPORT, + }; +@@ -604,7 +606,6 @@ struct ibmvfc_target { + struct list_head queue; + struct ibmvfc_host *vhost; + u64 scsi_id; +- u64 new_scsi_id; + struct fc_rport *rport; + int target_id; + enum ibmvfc_target_action action; +-- +2.23.0 + diff --git a/patches.suse/scsi-ibmvfc-Byte-swap-status-and-error-codes-when-lo.patch b/patches.suse/scsi-ibmvfc-Byte-swap-status-and-error-codes-when-lo.patch new file mode 100644 index 0000000..a2dc7c2 --- /dev/null +++ b/patches.suse/scsi-ibmvfc-Byte-swap-status-and-error-codes-when-lo.patch @@ -0,0 +1,119 @@ +From 3e6f7de43f4960fba8322b16531b0d6624a9322d Mon Sep 17 00:00:00 2001 +From: Tyrel Datwyler +Date: Wed, 20 Mar 2019 14:56:53 -0500 +Subject: [PATCH] scsi: ibmvfc: Byte swap status and error codes when logging + +References: bsc#1161951 ltc#183551 +Patch-mainline: v5.1-rc3 +Git-commit: 3e6f7de43f4960fba8322b16531b0d6624a9322d + +Status and error codes are returned in big endian from the VIOS. The values +are translated into a human readable format when logged, but the values are +also logged. This patch byte swaps those values so that they are consistent +between BE and LE platforms. + +Signed-off-by: Tyrel Datwyler +Signed-off-by: Martin K. Petersen +Acked-by: Michal Suchanek +--- + drivers/scsi/ibmvscsi/ibmvfc.c | 28 +++++++++++++++------------- + 1 file changed, 15 insertions(+), 13 deletions(-) + +diff --git a/drivers/scsi/ibmvscsi/ibmvfc.c b/drivers/scsi/ibmvscsi/ibmvfc.c +index 18ee2a8ec3d5..33dda4d32f65 100644 +--- a/drivers/scsi/ibmvscsi/ibmvfc.c ++++ b/drivers/scsi/ibmvscsi/ibmvfc.c +@@ -1497,7 +1497,7 @@ static void ibmvfc_log_error(struct ibmvfc_event *evt) + + scmd_printk(KERN_ERR, cmnd, "Command (%02X) : %s (%x:%x) " + "flags: %x fcp_rsp: %x, resid=%d, scsi_status: %x\n", +- cmnd->cmnd[0], err, vfc_cmd->status, vfc_cmd->error, ++ cmnd->cmnd[0], err, be16_to_cpu(vfc_cmd->status), be16_to_cpu(vfc_cmd->error), + rsp->flags, rsp_code, scsi_get_resid(cmnd), rsp->scsi_status); + } + +@@ -2023,7 +2023,7 @@ static int ibmvfc_reset_device(struct scsi_device *sdev, int type, char *desc) + sdev_printk(KERN_ERR, sdev, "%s reset failed: %s (%x:%x) " + "flags: %x fcp_rsp: %x, scsi_status: %x\n", desc, + ibmvfc_get_cmd_error(be16_to_cpu(rsp_iu.cmd.status), be16_to_cpu(rsp_iu.cmd.error)), +- rsp_iu.cmd.status, rsp_iu.cmd.error, fc_rsp->flags, rsp_code, ++ be16_to_cpu(rsp_iu.cmd.status), be16_to_cpu(rsp_iu.cmd.error), fc_rsp->flags, rsp_code, + fc_rsp->scsi_status); + rsp_rc = -EIO; + } else +@@ -2382,7 +2382,7 @@ static int ibmvfc_abort_task_set(struct scsi_device *sdev) + sdev_printk(KERN_ERR, sdev, "Abort failed: %s (%x:%x) " + "flags: %x fcp_rsp: %x, scsi_status: %x\n", + ibmvfc_get_cmd_error(be16_to_cpu(rsp_iu.cmd.status), be16_to_cpu(rsp_iu.cmd.error)), +- rsp_iu.cmd.status, rsp_iu.cmd.error, fc_rsp->flags, rsp_code, ++ be16_to_cpu(rsp_iu.cmd.status), be16_to_cpu(rsp_iu.cmd.error), fc_rsp->flags, rsp_code, + fc_rsp->scsi_status); + rsp_rc = -EIO; + } else +@@ -3349,7 +3349,7 @@ static void ibmvfc_tgt_prli_done(struct ibmvfc_event *evt) + + tgt_log(tgt, level, "Process Login failed: %s (%x:%x) rc=0x%02X\n", + ibmvfc_get_cmd_error(be16_to_cpu(rsp->status), be16_to_cpu(rsp->error)), +- rsp->status, rsp->error, status); ++ be16_to_cpu(rsp->status), be16_to_cpu(rsp->error), status); + break; + } + +@@ -3447,9 +3447,10 @@ static void ibmvfc_tgt_plogi_done(struct ibmvfc_event *evt) + ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_DEL_RPORT); + + tgt_log(tgt, level, "Port Login failed: %s (%x:%x) %s (%x) %s (%x) rc=0x%02X\n", +- ibmvfc_get_cmd_error(be16_to_cpu(rsp->status), be16_to_cpu(rsp->error)), rsp->status, rsp->error, +- ibmvfc_get_fc_type(be16_to_cpu(rsp->fc_type)), rsp->fc_type, +- ibmvfc_get_ls_explain(be16_to_cpu(rsp->fc_explain)), rsp->fc_explain, status); ++ ibmvfc_get_cmd_error(be16_to_cpu(rsp->status), be16_to_cpu(rsp->error)), ++ be16_to_cpu(rsp->status), be16_to_cpu(rsp->error), ++ ibmvfc_get_fc_type(be16_to_cpu(rsp->fc_type)), be16_to_cpu(rsp->fc_type), ++ ibmvfc_get_ls_explain(be16_to_cpu(rsp->fc_explain)), be16_to_cpu(rsp->fc_explain), status); + break; + } + +@@ -3620,7 +3621,7 @@ static void ibmvfc_tgt_adisc_done(struct ibmvfc_event *evt) + fc_explain = (be32_to_cpu(mad->fc_iu.response[1]) & 0x0000ff00) >> 8; + tgt_info(tgt, "ADISC failed: %s (%x:%x) %s (%x) %s (%x) rc=0x%02X\n", + ibmvfc_get_cmd_error(be16_to_cpu(mad->iu.status), be16_to_cpu(mad->iu.error)), +- mad->iu.status, mad->iu.error, ++ be16_to_cpu(mad->iu.status), be16_to_cpu(mad->iu.error), + ibmvfc_get_fc_type(fc_reason), fc_reason, + ibmvfc_get_ls_explain(fc_explain), fc_explain, status); + break; +@@ -3832,9 +3833,10 @@ static void ibmvfc_tgt_query_target_done(struct ibmvfc_event *evt) + + tgt_log(tgt, level, "Query Target failed: %s (%x:%x) %s (%x) %s (%x) rc=0x%02X\n", + ibmvfc_get_cmd_error(be16_to_cpu(rsp->status), be16_to_cpu(rsp->error)), +- rsp->status, rsp->error, ibmvfc_get_fc_type(be16_to_cpu(rsp->fc_type)), +- rsp->fc_type, ibmvfc_get_gs_explain(be16_to_cpu(rsp->fc_explain)), +- rsp->fc_explain, status); ++ be16_to_cpu(rsp->status), be16_to_cpu(rsp->error), ++ ibmvfc_get_fc_type(be16_to_cpu(rsp->fc_type)), be16_to_cpu(rsp->fc_type), ++ ibmvfc_get_gs_explain(be16_to_cpu(rsp->fc_explain)), be16_to_cpu(rsp->fc_explain), ++ status); + break; + } + +@@ -3960,7 +3962,7 @@ static void ibmvfc_discover_targets_done(struct ibmvfc_event *evt) + level += ibmvfc_retry_host_init(vhost); + ibmvfc_log(vhost, level, "Discover Targets failed: %s (%x:%x)\n", + ibmvfc_get_cmd_error(be16_to_cpu(rsp->status), be16_to_cpu(rsp->error)), +- rsp->status, rsp->error); ++ be16_to_cpu(rsp->status), be16_to_cpu(rsp->error)); + break; + case IBMVFC_MAD_DRIVER_FAILED: + break; +@@ -4025,7 +4027,7 @@ static void ibmvfc_npiv_login_done(struct ibmvfc_event *evt) + ibmvfc_link_down(vhost, IBMVFC_LINK_DEAD); + ibmvfc_log(vhost, level, "NPIV Login failed: %s (%x:%x)\n", + ibmvfc_get_cmd_error(be16_to_cpu(rsp->status), be16_to_cpu(rsp->error)), +- rsp->status, rsp->error); ++ be16_to_cpu(rsp->status), be16_to_cpu(rsp->error)); + ibmvfc_free_event(evt); + return; + case IBMVFC_MAD_CRQ_ERROR: +-- +2.23.0 + diff --git a/patches.suse/scsi-ibmvfc-Clean-up-transport-events.patch b/patches.suse/scsi-ibmvfc-Clean-up-transport-events.patch new file mode 100644 index 0000000..6cbb002 --- /dev/null +++ b/patches.suse/scsi-ibmvfc-Clean-up-transport-events.patch @@ -0,0 +1,72 @@ +From d6e2635b9cf7982102750c5d9e4ba1474afa0981 Mon Sep 17 00:00:00 2001 +From: Tyrel Datwyler +Date: Wed, 20 Mar 2019 14:56:54 -0500 +Subject: [PATCH] scsi: ibmvfc: Clean up transport events + +References: bsc#1161951 ltc#183551 +Patch-mainline: v5.1-rc3 +Git-commit: d6e2635b9cf7982102750c5d9e4ba1474afa0981 + +No change to functionality. Simply make transport event messages a little +clearer, and rework CRQ format enums such that we have separate enums for +INIT messages and XPORT events. + +[mkp: typo] + +Signed-off-by: Tyrel Datwyler +Signed-off-by: Martin K. Petersen +Acked-by: Michal Suchanek +--- + drivers/scsi/ibmvscsi/ibmvfc.c | 8 +++++--- + drivers/scsi/ibmvscsi/ibmvfc.h | 7 ++++++- + 2 files changed, 11 insertions(+), 4 deletions(-) + +diff --git a/drivers/scsi/ibmvscsi/ibmvfc.c b/drivers/scsi/ibmvscsi/ibmvfc.c +index 33dda4d32f65..3ad997ac3510 100644 +--- a/drivers/scsi/ibmvscsi/ibmvfc.c ++++ b/drivers/scsi/ibmvscsi/ibmvfc.c +@@ -2756,16 +2756,18 @@ static void ibmvfc_handle_crq(struct ibmvfc_crq *crq, struct ibmvfc_host *vhost) + ibmvfc_set_host_action(vhost, IBMVFC_HOST_ACTION_NONE); + if (crq->format == IBMVFC_PARTITION_MIGRATED) { + /* We need to re-setup the interpartition connection */ +- dev_info(vhost->dev, "Re-enabling adapter\n"); ++ dev_info(vhost->dev, "Partition migrated, Re-enabling adapter\n"); + vhost->client_migrated = 1; + ibmvfc_purge_requests(vhost, DID_REQUEUE); + ibmvfc_link_down(vhost, IBMVFC_LINK_DOWN); + ibmvfc_set_host_action(vhost, IBMVFC_HOST_ACTION_REENABLE); +- } else { +- dev_err(vhost->dev, "Virtual adapter failed (rc=%d)\n", crq->format); ++ } else if (crq->format == IBMVFC_PARTNER_FAILED || crq->format == IBMVFC_PARTNER_DEREGISTER) { ++ dev_err(vhost->dev, "Host partner adapter deregistered or failed (rc=%d)\n", crq->format); + ibmvfc_purge_requests(vhost, DID_ERROR); + ibmvfc_link_down(vhost, IBMVFC_LINK_DOWN); + ibmvfc_set_host_action(vhost, IBMVFC_HOST_ACTION_RESET); ++ } else { ++ dev_err(vhost->dev, "Received unknown transport event from partner (rc=%d)\n", crq->format); + } + return; + case IBMVFC_CRQ_CMD_RSP: +diff --git a/drivers/scsi/ibmvscsi/ibmvfc.h b/drivers/scsi/ibmvscsi/ibmvfc.h +index b81a53c4a9a8..459cc288ba1d 100644 +--- a/drivers/scsi/ibmvscsi/ibmvfc.h ++++ b/drivers/scsi/ibmvscsi/ibmvfc.h +@@ -78,9 +78,14 @@ enum ibmvfc_crq_valid { + IBMVFC_CRQ_XPORT_EVENT = 0xFF, + }; + +-enum ibmvfc_crq_format { ++enum ibmvfc_crq_init_msg { + IBMVFC_CRQ_INIT = 0x01, + IBMVFC_CRQ_INIT_COMPLETE = 0x02, ++}; ++ ++enum ibmvfc_crq_xport_evts { ++ IBMVFC_PARTNER_FAILED = 0x01, ++ IBMVFC_PARTNER_DEREGISTER = 0x02, + IBMVFC_PARTITION_MIGRATED = 0x06, + }; + +-- +2.23.0 + diff --git a/patches.suse/scsi-ibmvfc-Do-not-call-fc_block_scsi_eh-on-host-res.patch b/patches.suse/scsi-ibmvfc-Do-not-call-fc_block_scsi_eh-on-host-res.patch index 5b59007..951763b 100644 --- a/patches.suse/scsi-ibmvfc-Do-not-call-fc_block_scsi_eh-on-host-res.patch +++ b/patches.suse/scsi-ibmvfc-Do-not-call-fc_block_scsi_eh-on-host-res.patch @@ -1,9 +1,11 @@ +From 8d8a3f594c2e0f6bd94d3a0503bae67ad653585e Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Fri, 25 Aug 2017 13:56:58 +0200 Subject: [PATCH] scsi: ibmvfc: Do not call fc_block_scsi_eh() on host reset -Git-commit: 8d8a3f594c2e0f6bd94d3a0503bae67ad653585e + +References: bsc#1118139 bsc#1161951 ltc#183551 Patch-mainline: v4.14-rc1 -References: bsc#1118139 +Git-commit: 8d8a3f594c2e0f6bd94d3a0503bae67ad653585e When we're resetting the host any remote port states will be reset anyway, so it's pointless to wait for dev_loss_tmo during host reset. @@ -12,7 +14,7 @@ Signed-off-by: Hannes Reinecke Reviewed-by: Christoph Hellwig Reviewed-by: Johannes Thumshirn Signed-off-by: Martin K. Petersen -Acked-by: Hannes Reinecke +Acked-by: Michal Suchanek --- drivers/scsi/ibmvscsi/ibmvfc.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) @@ -40,5 +42,5 @@ index cc4e05be8d4a..51f52480bf34 100644 } -- -2.12.3 +2.23.0 diff --git a/patches.suse/scsi-ibmvfc-Mark-expected-switch-fall-throughs.patch b/patches.suse/scsi-ibmvfc-Mark-expected-switch-fall-throughs.patch new file mode 100644 index 0000000..a754a68 --- /dev/null +++ b/patches.suse/scsi-ibmvfc-Mark-expected-switch-fall-throughs.patch @@ -0,0 +1,83 @@ +From 4c73598732f7954867d95e315e5465b6ce7767a0 Mon Sep 17 00:00:00 2001 +From: "Gustavo A. R. Silva" +Date: Sun, 28 Jul 2019 19:26:08 -0500 +Subject: [PATCH] scsi: ibmvfc: Mark expected switch fall-throughs + +References: bsc#1161951 ltc#183551 +Patch-mainline: v5.4-rc1 +Git-commit: 4c73598732f7954867d95e315e5465b6ce7767a0 + +Mark switch cases where we are expecting to fall through. + +This patch fixes the following warnings: + +drivers/scsi/ibmvscsi/ibmvfc.c: In function 'ibmvfc_npiv_login_done': +drivers/scsi/ibmvscsi/ibmvfc.c:4022:3: warning: this statement may fall through [-Wimplicit-fallthrough=] + ibmvfc_retry_host_init(vhost); + ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +drivers/scsi/ibmvscsi/ibmvfc.c:4023:2: note: here + case IBMVFC_MAD_DRIVER_FAILED: + ^~~~ +drivers/scsi/ibmvscsi/ibmvfc.c: In function 'ibmvfc_bsg_request': +drivers/scsi/ibmvscsi/ibmvfc.c:1830:11: warning: this statement may fall through [-Wimplicit-fallthrough=] + port_id = (bsg_request->rqst_data.h_els.port_id[0] << 16) | + ~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + (bsg_request->rqst_data.h_els.port_id[1] << 8) | + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + bsg_request->rqst_data.h_els.port_id[2]; + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +drivers/scsi/ibmvscsi/ibmvfc.c:1833:2: note: here + case FC_BSG_RPT_ELS: + ^~~~ +drivers/scsi/ibmvscsi/ibmvfc.c:1838:11: warning: this statement may fall through [-Wimplicit-fallthrough=] + port_id = (bsg_request->rqst_data.h_ct.port_id[0] << 16) | + ~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + (bsg_request->rqst_data.h_ct.port_id[1] << 8) | + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + bsg_request->rqst_data.h_ct.port_id[2]; + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +drivers/scsi/ibmvscsi/ibmvfc.c:1841:2: note: here + case FC_BSG_RPT_CT: + ^~~~ + +Reported-by: Stephen Rothwell +Signed-off-by: Gustavo A. R. Silva +Reviewed-by: Kees Cook +Acked-by: Tyrel Datwyler +Signed-off-by: Martin K. Petersen +Acked-by: Michal Suchanek +--- + drivers/scsi/ibmvscsi/ibmvfc.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/scsi/ibmvscsi/ibmvfc.c b/drivers/scsi/ibmvscsi/ibmvfc.c +index acd16e0d52cf..fe38d92c9c9f 100644 +--- a/drivers/scsi/ibmvscsi/ibmvfc.c ++++ b/drivers/scsi/ibmvscsi/ibmvfc.c +@@ -1830,6 +1830,7 @@ static int ibmvfc_bsg_request(struct bsg_job *job) + port_id = (bsg_request->rqst_data.h_els.port_id[0] << 16) | + (bsg_request->rqst_data.h_els.port_id[1] << 8) | + bsg_request->rqst_data.h_els.port_id[2]; ++ /* fall through */ + case FC_BSG_RPT_ELS: + fc_flags = IBMVFC_FC_ELS; + break; +@@ -1838,6 +1839,7 @@ static int ibmvfc_bsg_request(struct bsg_job *job) + port_id = (bsg_request->rqst_data.h_ct.port_id[0] << 16) | + (bsg_request->rqst_data.h_ct.port_id[1] << 8) | + bsg_request->rqst_data.h_ct.port_id[2]; ++ /* fall through */ + case FC_BSG_RPT_CT: + fc_flags = IBMVFC_FC_CT_IU; + break; +@@ -4020,6 +4022,7 @@ static void ibmvfc_npiv_login_done(struct ibmvfc_event *evt) + return; + case IBMVFC_MAD_CRQ_ERROR: + ibmvfc_retry_host_init(vhost); ++ /* fall through */ + case IBMVFC_MAD_DRIVER_FAILED: + ibmvfc_free_event(evt); + return; +-- +2.23.0 + diff --git a/patches.suse/scsi-ibmvfc-Remove-failed-from-logged-errors.patch b/patches.suse/scsi-ibmvfc-Remove-failed-from-logged-errors.patch new file mode 100644 index 0000000..f2e3ce8 --- /dev/null +++ b/patches.suse/scsi-ibmvfc-Remove-failed-from-logged-errors.patch @@ -0,0 +1,46 @@ +From 6dc6a944d58aea3d9de3828318b0fffdb60a7097 Mon Sep 17 00:00:00 2001 +From: Tyrel Datwyler +Date: Wed, 20 Mar 2019 14:56:51 -0500 +Subject: [PATCH] scsi: ibmvfc: Remove "failed" from logged errors + +References: bsc#1161951 ltc#183551 +Patch-mainline: v5.1-rc3 +Git-commit: 6dc6a944d58aea3d9de3828318b0fffdb60a7097 + +The text of messages logged with ibmvfc_log_error() always contain the term +"failed". In the case of cancelled commands during EH they are reported +back by the VIOS using error codes. This can be confusing to somebody +looking at these log messages as to whether a command was successfully +cancelled. The following real log message for example it is unclear if the +transaction was actaully cancelled. + +<6>sd 0:0:1:1: Cancelling outstanding commands. +<3>sd 0:0:1:1: [sde] Command (28) failed: transaction cancelled (2:6) flags: 0 fcp_rsp: 0, resid=0, scsi_status: 0 + +Remove prefixing of "failed" to all error logged messages. The +ibmvfc_log_error() function translates the returned error/status codes to a +human readable message already. + +Signed-off-by: Tyrel Datwyler +Signed-off-by: Martin K. Petersen +Acked-by: Michal Suchanek +--- + drivers/scsi/ibmvscsi/ibmvfc.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/scsi/ibmvscsi/ibmvfc.c b/drivers/scsi/ibmvscsi/ibmvfc.c +index dbaa4f131433..c3ce27039552 100644 +--- a/drivers/scsi/ibmvscsi/ibmvfc.c ++++ b/drivers/scsi/ibmvscsi/ibmvfc.c +@@ -1494,7 +1494,7 @@ static void ibmvfc_log_error(struct ibmvfc_event *evt) + if (rsp->flags & FCP_RSP_LEN_VALID) + rsp_code = rsp->data.info.rsp_code; + +- scmd_printk(KERN_ERR, cmnd, "Command (%02X) failed: %s (%x:%x) " ++ scmd_printk(KERN_ERR, cmnd, "Command (%02X) : %s (%x:%x) " + "flags: %x fcp_rsp: %x, resid=%d, scsi_status: %x\n", + cmnd->cmnd[0], err, vfc_cmd->status, vfc_cmd->error, + rsp->flags, rsp_code, scsi_get_resid(cmnd), rsp->scsi_status); +-- +2.23.0 + diff --git a/patches.suse/scsi-ibmvfc-Remove-unneeded-semicolons.patch b/patches.suse/scsi-ibmvfc-Remove-unneeded-semicolons.patch index 50a2bdd..376d584 100644 --- a/patches.suse/scsi-ibmvfc-Remove-unneeded-semicolons.patch +++ b/patches.suse/scsi-ibmvfc-Remove-unneeded-semicolons.patch @@ -1,13 +1,15 @@ +From f36cfe6a06572cdb5379a9321f62bf2a794ad627 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christopher=20D=C3=ADaz=20Riveros?= Date: Wed, 17 Jan 2018 20:38:39 -0500 Subject: [PATCH] scsi: ibmvfc: Remove unneeded semicolons -Git-commit: f36cfe6a06572cdb5379a9321f62bf2a794ad627 -Patch-mainline: v4.16-rc1 -References: bsc#1118139 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit +References: bsc#1118139 bsc#1161951 ltc#183551 +Patch-mainline: v4.16-rc1 +Git-commit: f36cfe6a06572cdb5379a9321f62bf2a794ad627 + Trivial fix removes unneeded semicolons after switch blocks. This issue was detected by using the Coccinelle software. @@ -15,7 +17,7 @@ This issue was detected by using the Coccinelle software. Signed-off-by: Christopher Díaz Riveros Acked-by: Tyrel Datwyler Signed-off-by: Martin K. Petersen -Acked-by: Hannes Reinecke +Acked-by: Michal Suchanek --- drivers/scsi/ibmvscsi/ibmvfc.c | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) @@ -178,5 +180,5 @@ index 0d2f7eb3acb6..b1b1d3a3b173 100644 spin_unlock_irqrestore(vhost->host->host_lock, flags); } -- -2.12.3 +2.23.0 diff --git a/patches.suse/scsi-ibmvfc-constify-dev_pm_ops-structures.patch b/patches.suse/scsi-ibmvfc-constify-dev_pm_ops-structures.patch new file mode 100644 index 0000000..b45e79e --- /dev/null +++ b/patches.suse/scsi-ibmvfc-constify-dev_pm_ops-structures.patch @@ -0,0 +1,45 @@ +From e4a80c31f2e863295cb2351f23ae486b0513a705 Mon Sep 17 00:00:00 2001 +From: Arvind Yadav +Date: Thu, 29 Jun 2017 13:24:41 +0530 +Subject: [PATCH] scsi: ibmvfc: constify dev_pm_ops structures. + +References: bsc#1161951 ltc#183551 +Patch-mainline: v4.13-rc1 +Git-commit: e4a80c31f2e863295cb2351f23ae486b0513a705 + +dev_pm_ops are not supposed to change at runtime. All functions +working with dev_pm_ops provided by work with const +dev_pm_ops. So mark the non-const structs as const. + +File size before: + text data bss dec hex filename + 41937 1296 20 43253 a8f5 drivers/scsi/ibmvscsi/ibmvfc.o + +File size After adding 'const': + text data bss dec hex filename + 42129 1104 20 43253 a8f5 drivers/scsi/ibmvscsi/ibmvfc.o + +Signed-off-by: Arvind Yadav +Acked-by: Tyrel Datwyler +Signed-off-by: Martin K. Petersen +Acked-by: Michal Suchanek +--- + drivers/scsi/ibmvscsi/ibmvfc.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/scsi/ibmvscsi/ibmvfc.c b/drivers/scsi/ibmvscsi/ibmvfc.c +index 26cd3c28186a..cc4e05be8d4a 100644 +--- a/drivers/scsi/ibmvscsi/ibmvfc.c ++++ b/drivers/scsi/ibmvscsi/ibmvfc.c +@@ -4935,7 +4935,7 @@ static struct vio_device_id ibmvfc_device_table[] = { + }; + MODULE_DEVICE_TABLE(vio, ibmvfc_device_table); + +-static struct dev_pm_ops ibmvfc_pm_ops = { ++static const struct dev_pm_ops ibmvfc_pm_ops = { + .resume = ibmvfc_resume + }; + +-- +2.23.0 + diff --git a/patches.suse/scsi-ibmvfc-ibmvscsi-ibmvscsi_tgt-constify-vio_devic.patch b/patches.suse/scsi-ibmvfc-ibmvscsi-ibmvscsi_tgt-constify-vio_devic.patch new file mode 100644 index 0000000..e551a85 --- /dev/null +++ b/patches.suse/scsi-ibmvfc-ibmvscsi-ibmvscsi_tgt-constify-vio_devic.patch @@ -0,0 +1,64 @@ +From e4df3eaa6e72459767cbf9b883fdfd2d28197583 Mon Sep 17 00:00:00 2001 +From: Arvind Yadav +Date: Thu, 17 Aug 2017 19:15:05 +0530 +Subject: [PATCH] scsi: ibmvfc: ibmvscsi: ibmvscsi_tgt: constify vio_device_id + +References: bsc#1161951 ltc#183551 +Patch-mainline: v4.14-rc1 +Git-commit: e4df3eaa6e72459767cbf9b883fdfd2d28197583 + +vio_device_id are not supposed to change at runtime. All functions +working with vio_device_id provided by work with const +vio_device_id. So mark the non-const structs as const. + +Signed-off-by: Arvind Yadav +Signed-off-by: Martin K. Petersen +Acked-by: Michal Suchanek +--- + drivers/scsi/ibmvscsi/ibmvfc.c | 2 +- + drivers/scsi/ibmvscsi/ibmvscsi.c | 2 +- + drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c | 2 +- + 3 files changed, 3 insertions(+), 3 deletions(-) + +diff --git a/drivers/scsi/ibmvscsi/ibmvfc.c b/drivers/scsi/ibmvscsi/ibmvfc.c +index 51f52480bf34..b491af31a5f8 100644 +--- a/drivers/scsi/ibmvscsi/ibmvfc.c ++++ b/drivers/scsi/ibmvscsi/ibmvfc.c +@@ -4925,7 +4925,7 @@ static unsigned long ibmvfc_get_desired_dma(struct vio_dev *vdev) + return pool_dma + ((512 * 1024) * driver_template.cmd_per_lun); + } + +-static struct vio_device_id ibmvfc_device_table[] = { ++static const struct vio_device_id ibmvfc_device_table[] = { + {"fcp", "IBM,vfc-client"}, + { "", "" } + }; +diff --git a/drivers/scsi/ibmvscsi/ibmvscsi.c b/drivers/scsi/ibmvscsi/ibmvscsi.c +index da22b3665cb0..7d156b161482 100644 +--- a/drivers/scsi/ibmvscsi/ibmvscsi.c ++++ b/drivers/scsi/ibmvscsi/ibmvscsi.c +@@ -2330,7 +2330,7 @@ static int ibmvscsi_resume(struct device *dev) + * ibmvscsi_device_table: Used by vio.c to match devices in the device tree we + * support. + */ +-static struct vio_device_id ibmvscsi_device_table[] = { ++static const struct vio_device_id ibmvscsi_device_table[] = { + {"vscsi", "IBM,v-scsi"}, + { "", "" } + }; +diff --git a/drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c b/drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c +index 1f75d0380516..785fb42f6650 100644 +--- a/drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c ++++ b/drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c +@@ -4086,7 +4086,7 @@ static struct class ibmvscsis_class = { + .dev_groups = ibmvscsis_dev_groups, + }; + +-static struct vio_device_id ibmvscsis_device_table[] = { ++static const struct vio_device_id ibmvscsis_device_table[] = { + { "v-scsi-host", "IBM,v-scsi-host" }, + { "", "" } + }; +-- +2.23.0 + diff --git a/patches.suse/scsi-ibmvscsi-Don-t-use-rc-uninitialized-in-ibmvscsi.patch b/patches.suse/scsi-ibmvscsi-Don-t-use-rc-uninitialized-in-ibmvscsi.patch new file mode 100644 index 0000000..b2aa929 --- /dev/null +++ b/patches.suse/scsi-ibmvscsi-Don-t-use-rc-uninitialized-in-ibmvscsi.patch @@ -0,0 +1,67 @@ +From 961ed94e8a83d8881546a278bf844699af92a502 Mon Sep 17 00:00:00 2001 +From: Nathan Chancellor +Date: Mon, 3 Jun 2019 16:44:06 -0700 +Subject: [PATCH] scsi: ibmvscsi: Don't use rc uninitialized in + ibmvscsi_do_work + +References: bsc#1161951 ltc#183551 +Patch-mainline: v5.3-rc1 +Git-commit: 961ed94e8a83d8881546a278bf844699af92a502 + +clang warns: + +drivers/scsi/ibmvscsi/ibmvscsi.c:2126:7: warning: variable 'rc' is used +uninitialized whenever switch case is taken [-Wsometimes-uninitialized] + case IBMVSCSI_HOST_ACTION_NONE: + ^~~~~~~~~~~~~~~~~~~~~~~~~ +drivers/scsi/ibmvscsi/ibmvscsi.c:2151:6: note: uninitialized use occurs +here + if (rc) { + ^~ + +Initialize rc in the IBMVSCSI_HOST_ACTION_UNBLOCK case statement then +shuffle IBMVSCSI_HOST_ACTION_NONE down to the default case statement and +make it return early so that rc is never used uninitialized in this +function. + +Fixes: 035a3c4046b5 ("scsi: ibmvscsi: redo driver work thread to use enum action states") +Link: https://github.com/ClangBuiltLinux/linux/issues/502 +Suggested-by: Michael Ellerman +Suggested-by: Tyrel Datwyler +Signed-off-by: Nathan Chancellor +Acked-by: Tyrel Datwyler +Signed-off-by: Martin K. Petersen +Acked-by: Michal Suchanek +--- + drivers/scsi/ibmvscsi/ibmvscsi.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/drivers/scsi/ibmvscsi/ibmvscsi.c b/drivers/scsi/ibmvscsi/ibmvscsi.c +index 727c31dc11a0..fcfaf037b5bf 100644 +--- a/drivers/scsi/ibmvscsi/ibmvscsi.c ++++ b/drivers/scsi/ibmvscsi/ibmvscsi.c +@@ -2123,8 +2123,8 @@ static void ibmvscsi_do_work(struct ibmvscsi_host_data *hostdata) + + spin_lock_irqsave(hostdata->host->host_lock, flags); + switch (hostdata->action) { +- case IBMVSCSI_HOST_ACTION_NONE: + case IBMVSCSI_HOST_ACTION_UNBLOCK: ++ rc = 0; + break; + case IBMVSCSI_HOST_ACTION_RESET: + spin_unlock_irqrestore(hostdata->host->host_lock, flags); +@@ -2142,8 +2142,10 @@ static void ibmvscsi_do_work(struct ibmvscsi_host_data *hostdata) + if (!rc) + rc = ibmvscsi_send_crq(hostdata, 0xC001000000000000LL, 0); + break; ++ case IBMVSCSI_HOST_ACTION_NONE: + default: +- break; ++ spin_unlock_irqrestore(hostdata->host->host_lock, flags); ++ return; + } + + hostdata->action = IBMVSCSI_HOST_ACTION_NONE; +-- +2.23.0 + diff --git a/patches.suse/scsi-ibmvscsi-Improve-strings-handling.patch b/patches.suse/scsi-ibmvscsi-Improve-strings-handling.patch new file mode 100644 index 0000000..92ffa13 --- /dev/null +++ b/patches.suse/scsi-ibmvscsi-Improve-strings-handling.patch @@ -0,0 +1,64 @@ +From 1262dc09dc9ae7bf4ad00b6a2c5ed6a6936bcd10 Mon Sep 17 00:00:00 2001 +From: Breno Leitao +Date: Tue, 26 Jun 2018 17:35:16 -0300 +Subject: [PATCH] scsi: ibmvscsi: Improve strings handling + +References: bsc#1161951 ltc#183551 +Patch-mainline: v4.19-rc1 +Git-commit: 1262dc09dc9ae7bf4ad00b6a2c5ed6a6936bcd10 + +Currently an open firmware property is copied into partition_name variable +without keeping a room for \0. + +Later one, this variable (partition_name), which is 97 bytes long, is +strncpyed into ibmvcsci_host_data->madapter_info->partition_name, which is +96 bytes long, possibly truncating it 'again' and removing the \0. + +This patch simply decreases the partition name to 96 and just copy using +strlcpy() which guarantees that the string is \0 terminated. I think there +is no issue if this there is a truncation in this very first copy, i.e, +when the open firmware property is read and copied into the driver for the +very first time; + +This issue also causes the following warning on GCC 8: + + drivers/scsi/ibmvscsi/ibmvscsi.c:281:2: warning: strncpy output may be truncated copying 96 bytes from a string of length 96 [-Wstringop-truncation] + ... + inlined from ibmvscsi_probe at drivers/scsi/ibmvscsi/ibmvscsi.c:2221:7: + drivers/scsi/ibmvscsi/ibmvscsi.c:265:3: warning: strncpy specified bound 97 equals destination size [-Wstringop-truncation] + +CC: Bart Van Assche +CC: Tyrel Datwyler +Signed-off-by: Breno Leitao +Acked-by: Tyrel Datwyler +Signed-off-by: Martin K. Petersen +Acked-by: Michal Suchanek +--- + drivers/scsi/ibmvscsi/ibmvscsi.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/scsi/ibmvscsi/ibmvscsi.c b/drivers/scsi/ibmvscsi/ibmvscsi.c +index 44916282ebd4..02689298325b 100644 +--- a/drivers/scsi/ibmvscsi/ibmvscsi.c ++++ b/drivers/scsi/ibmvscsi/ibmvscsi.c +@@ -93,7 +93,7 @@ static int max_requests = IBMVSCSI_MAX_REQUESTS_DEFAULT; + static int max_events = IBMVSCSI_MAX_REQUESTS_DEFAULT + 2; + static int fast_fail = 1; + static int client_reserve = 1; +-static char partition_name[97] = "UNKNOWN"; ++static char partition_name[96] = "UNKNOWN"; + static unsigned int partition_number = -1; + static LIST_HEAD(ibmvscsi_head); + +@@ -262,7 +262,7 @@ static void gather_partition_info(void) + + ppartition_name = of_get_property(of_root, "ibm,partition-name", NULL); + if (ppartition_name) +- strncpy(partition_name, ppartition_name, ++ strlcpy(partition_name, ppartition_name, + sizeof(partition_name)); + p_number_ptr = of_get_property(of_root, "ibm,partition-no", NULL); + if (p_number_ptr) +-- +2.23.0 + diff --git a/patches.suse/scsi-ibmvscsi-Wire-up-host_reset-in-the-driver-s-scs.patch b/patches.suse/scsi-ibmvscsi-Wire-up-host_reset-in-the-driver-s-scs.patch new file mode 100644 index 0000000..10156d4 --- /dev/null +++ b/patches.suse/scsi-ibmvscsi-Wire-up-host_reset-in-the-driver-s-scs.patch @@ -0,0 +1,56 @@ +From 2e22520475037f97b5a3234591183105ecf9845b Mon Sep 17 00:00:00 2001 +From: Tyrel Datwyler +Date: Thu, 2 May 2019 19:50:56 -0500 +Subject: [PATCH] scsi: ibmvscsi: Wire up host_reset() in the driver's + scsi_host_template + +References: bsc#1161951 ltc#183551 +Patch-mainline: v5.3-rc1 +Git-commit: 2e22520475037f97b5a3234591183105ecf9845b + +Wire up the host_reset function in our driver_template to allow a user +requested adpater reset via the host_reset sysfs attribute. + +Example: + +echo "adapter" > /sys/class/scsi_host/host0/host_reset + +Signed-off-by: Tyrel Datwyler +Signed-off-by: Martin K. Petersen +Acked-by: Michal Suchanek +--- + drivers/scsi/ibmvscsi/ibmvscsi.c | 11 +++++++++++ + 1 file changed, 11 insertions(+) + +diff --git a/drivers/scsi/ibmvscsi/ibmvscsi.c b/drivers/scsi/ibmvscsi/ibmvscsi.c +index 8cec5230fe31..65fc8ca962c5 100644 +--- a/drivers/scsi/ibmvscsi/ibmvscsi.c ++++ b/drivers/scsi/ibmvscsi/ibmvscsi.c +@@ -2050,6 +2050,16 @@ static struct device_attribute ibmvscsi_host_config = { + .show = show_host_config, + }; + ++static int ibmvscsi_host_reset(struct Scsi_Host *shost, int reset_type) ++{ ++ struct ibmvscsi_host_data *hostdata = shost_priv(shost); ++ ++ dev_info(hostdata->dev, "Initiating adapter reset!\n"); ++ ibmvscsi_reset_host(hostdata); ++ ++ return 0; ++} ++ + static struct device_attribute *ibmvscsi_attrs[] = { + &ibmvscsi_host_vhost_loc, + &ibmvscsi_host_vhost_name, +@@ -2076,6 +2086,7 @@ static struct scsi_host_template driver_template = { + .eh_host_reset_handler = ibmvscsi_eh_host_reset_handler, + .slave_configure = ibmvscsi_slave_configure, + .change_queue_depth = ibmvscsi_change_queue_depth, ++ .host_reset = ibmvscsi_host_reset, + .cmd_per_lun = IBMVSCSI_CMDS_PER_LUN_DEFAULT, + .can_queue = IBMVSCSI_MAX_REQUESTS_DEFAULT, + .this_id = -1, +-- +2.23.0 + diff --git a/patches.suse/scsi-ibmvscsi-change-strncpy-truncation-to-strlcpy.patch b/patches.suse/scsi-ibmvscsi-change-strncpy-truncation-to-strlcpy.patch new file mode 100644 index 0000000..1912ac4 --- /dev/null +++ b/patches.suse/scsi-ibmvscsi-change-strncpy-truncation-to-strlcpy.patch @@ -0,0 +1,42 @@ +From a544523887007ba2b6bd73419c4e2f0ab9bb3633 Mon Sep 17 00:00:00 2001 +From: Dominique Martinet +Date: Fri, 13 Jul 2018 03:25:56 +0200 +Subject: [PATCH] scsi: ibmvscsi: change strncpy+truncation to strlcpy + +References: bsc#1161951 ltc#183551 +Patch-mainline: v4.19-rc1 +Git-commit: a544523887007ba2b6bd73419c4e2f0ab9bb3633 + +Generated by scripts/coccinelle/misc/strncpy_truncation.cocci + +Signed-off-by: Dominique Martinet +Signed-off-by: Martin K. Petersen +Acked-by: Michal Suchanek +--- + drivers/scsi/ibmvscsi/ibmvscsi.c | 6 ++---- + 1 file changed, 2 insertions(+), 4 deletions(-) + +diff --git a/drivers/scsi/ibmvscsi/ibmvscsi.c b/drivers/scsi/ibmvscsi/ibmvscsi.c +index 02689298325b..9df8a1a2299c 100644 +--- a/drivers/scsi/ibmvscsi/ibmvscsi.c ++++ b/drivers/scsi/ibmvscsi/ibmvscsi.c +@@ -1274,14 +1274,12 @@ static void send_mad_capabilities(struct ibmvscsi_host_data *hostdata) + if (hostdata->client_migrated) + hostdata->caps.flags |= cpu_to_be32(CLIENT_MIGRATED); + +- strncpy(hostdata->caps.name, dev_name(&hostdata->host->shost_gendev), ++ strlcpy(hostdata->caps.name, dev_name(&hostdata->host->shost_gendev), + sizeof(hostdata->caps.name)); +- hostdata->caps.name[sizeof(hostdata->caps.name) - 1] = '\0'; + + location = of_get_property(of_node, "ibm,loc-code", NULL); + location = location ? location : dev_name(hostdata->dev); +- strncpy(hostdata->caps.loc, location, sizeof(hostdata->caps.loc)); +- hostdata->caps.loc[sizeof(hostdata->caps.loc) - 1] = '\0'; ++ strlcpy(hostdata->caps.loc, location, sizeof(hostdata->caps.loc)); + + req->common.type = cpu_to_be32(VIOSRP_CAPABILITIES_TYPE); + req->buffer = cpu_to_be64(hostdata->caps_addr); +-- +2.23.0 + diff --git a/patches.suse/scsi-ibmvscsi-constify-dev_pm_ops-structures.patch b/patches.suse/scsi-ibmvscsi-constify-dev_pm_ops-structures.patch new file mode 100644 index 0000000..79afb07 --- /dev/null +++ b/patches.suse/scsi-ibmvscsi-constify-dev_pm_ops-structures.patch @@ -0,0 +1,45 @@ +From e6b53a752ba76e1268b04052c9ec06555e3f6995 Mon Sep 17 00:00:00 2001 +From: Arvind Yadav +Date: Thu, 29 Jun 2017 13:13:55 +0530 +Subject: [PATCH] scsi: ibmvscsi: constify dev_pm_ops structures. + +References: bsc#1161951 ltc#183551 +Patch-mainline: v4.13-rc1 +Git-commit: e6b53a752ba76e1268b04052c9ec06555e3f6995 + +dev_pm_ops are not supposed to change at runtime. All functions working +with dev_pm_ops provided by work with const +dev_pm_ops. So mark the non-const structs as const. + +File size before: + text data bss dec hex filename + 17956 1456 8 19420 4bdc drivers/scsi/ibmvscsi/ibmvscsi.o + +File size After adding 'const': + text data bss dec hex filename + 18164 1264 8 19436 4bec drivers/scsi/ibmvscsi/ibmvscsi.o + +Signed-off-by: Arvind Yadav +Acked-by: Tyrel Datwyler +Signed-off-by: Martin K. Petersen +Acked-by: Michal Suchanek +--- + drivers/scsi/ibmvscsi/ibmvscsi.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/scsi/ibmvscsi/ibmvscsi.c b/drivers/scsi/ibmvscsi/ibmvscsi.c +index 1deb0a9f14a6..da22b3665cb0 100644 +--- a/drivers/scsi/ibmvscsi/ibmvscsi.c ++++ b/drivers/scsi/ibmvscsi/ibmvscsi.c +@@ -2336,7 +2336,7 @@ static struct vio_device_id ibmvscsi_device_table[] = { + }; + MODULE_DEVICE_TABLE(vio, ibmvscsi_device_table); + +-static struct dev_pm_ops ibmvscsi_pm_ops = { ++static const struct dev_pm_ops ibmvscsi_pm_ops = { + .resume = ibmvscsi_resume + }; + +-- +2.23.0 + diff --git a/patches.suse/scsi-ibmvscsi-fix-tripping-of-blk_mq_run_hw_queue-WA.patch b/patches.suse/scsi-ibmvscsi-fix-tripping-of-blk_mq_run_hw_queue-WA.patch new file mode 100644 index 0000000..7b2a369 --- /dev/null +++ b/patches.suse/scsi-ibmvscsi-fix-tripping-of-blk_mq_run_hw_queue-WA.patch @@ -0,0 +1,95 @@ +From aa343c695aa59f03f31a2f989b8c977a727e46e3 Mon Sep 17 00:00:00 2001 +From: Tyrel Datwyler +Date: Thu, 2 May 2019 19:50:58 -0500 +Subject: [PATCH] scsi: ibmvscsi: fix tripping of blk_mq_run_hw_queue WARN_ON + +References: bsc#1161951 ltc#183551 +Patch-mainline: v5.3-rc1 +Git-commit: aa343c695aa59f03f31a2f989b8c977a727e46e3 + +After a successful SRP login response we call scsi_unblock_requests() to +kick any pending IOs. The callback to process this SRP response happens in +a tasklet and therefore is in softirq context. The result of such is that +when blk-mq is enabled, it is no longer safe to call scsi_unblock_requests() +from this context. The result of duing so triggers the following WARN_ON +splat in dmesg after a host reset or CRQ reenablement. + +WARNING: CPU: 0 PID: 0 at block/blk-mq.c:1375 __blk_mq_run_hw_queue+0x120/0x180 +Modules linked in: +CPU: 0 PID: 0 Comm: swapper/0 Not tainted 5.0.0-rc8 #4 +NIP [c0000000009771e0] __blk_mq_run_hw_queue+0x120/0x180 +LR [c000000000977484] __blk_mq_delay_run_hw_queue+0x244/0x250 +Call Trace: + +__blk_mq_delay_run_hw_queue+0x244/0x250 +blk_mq_run_hw_queue+0x8c/0x1c0 +blk_mq_run_hw_queues+0x60/0x90 +scsi_run_queue+0x1e4/0x3b0 +scsi_run_host_queues+0x48/0x80 +login_rsp+0xb0/0x100 +ibmvscsi_handle_crq+0x30c/0x3e0 +ibmvscsi_task+0x54/0xe0 +tasklet_action_common.isra.3+0xc4/0x1a0 +__do_softirq+0x174/0x3f4 +irq_exit+0xf0/0x120 +__do_irq+0xb0/0x210 +call_do_irq+0x14/0x24 +do_IRQ+0x9c/0x130 +hardware_interrupt_common+0x14c/0x150 + +This patch fixes the issue by introducing a new host action for unblocking +the scsi requests in our seperate work thread. + +Signed-off-by: Tyrel Datwyler +Signed-off-by: Martin K. Petersen +Acked-by: Michal Suchanek +--- + drivers/scsi/ibmvscsi/ibmvscsi.c | 5 ++++- + drivers/scsi/ibmvscsi/ibmvscsi.h | 1 + + 2 files changed, 5 insertions(+), 1 deletion(-) + +diff --git a/drivers/scsi/ibmvscsi/ibmvscsi.c b/drivers/scsi/ibmvscsi/ibmvscsi.c +index 8df82c58e7b9..727c31dc11a0 100644 +--- a/drivers/scsi/ibmvscsi/ibmvscsi.c ++++ b/drivers/scsi/ibmvscsi/ibmvscsi.c +@@ -1179,7 +1179,8 @@ static void login_rsp(struct srp_event_struct *evt_struct) + be32_to_cpu(evt_struct->xfer_iu->srp.login_rsp.req_lim_delta)); + + /* If we had any pending I/Os, kick them */ +- scsi_unblock_requests(hostdata->host); ++ hostdata->action = IBMVSCSI_HOST_ACTION_UNBLOCK; ++ wake_up(&hostdata->work_wait_q); + } + + /** +@@ -2123,6 +2124,7 @@ static void ibmvscsi_do_work(struct ibmvscsi_host_data *hostdata) + spin_lock_irqsave(hostdata->host->host_lock, flags); + switch (hostdata->action) { + case IBMVSCSI_HOST_ACTION_NONE: ++ case IBMVSCSI_HOST_ACTION_UNBLOCK: + break; + case IBMVSCSI_HOST_ACTION_RESET: + spin_unlock_irqrestore(hostdata->host->host_lock, flags); +@@ -2164,6 +2166,7 @@ static int __ibmvscsi_work_to_do(struct ibmvscsi_host_data *hostdata) + return 0; + case IBMVSCSI_HOST_ACTION_RESET: + case IBMVSCSI_HOST_ACTION_REENABLE: ++ case IBMVSCSI_HOST_ACTION_UNBLOCK: + default: + break; + } +diff --git a/drivers/scsi/ibmvscsi/ibmvscsi.h b/drivers/scsi/ibmvscsi/ibmvscsi.h +index 04bcbc832dc9..d9bf502334ba 100644 +--- a/drivers/scsi/ibmvscsi/ibmvscsi.h ++++ b/drivers/scsi/ibmvscsi/ibmvscsi.h +@@ -92,6 +92,7 @@ enum ibmvscsi_host_action { + IBMVSCSI_HOST_ACTION_NONE = 0, + IBMVSCSI_HOST_ACTION_RESET, + IBMVSCSI_HOST_ACTION_REENABLE, ++ IBMVSCSI_HOST_ACTION_UNBLOCK, + }; + + /* all driver data associated with a host adapter */ +-- +2.23.0 + diff --git a/patches.suse/scsi-ibmvscsi-redo-driver-work-thread-to-use-enum-ac.patch b/patches.suse/scsi-ibmvscsi-redo-driver-work-thread-to-use-enum-ac.patch new file mode 100644 index 0000000..ff137f0 --- /dev/null +++ b/patches.suse/scsi-ibmvscsi-redo-driver-work-thread-to-use-enum-ac.patch @@ -0,0 +1,163 @@ +From 6e40de8b6b3cfa7288bb4a1fee2c7173f53b7345 Mon Sep 17 00:00:00 2001 +From: Tyrel Datwyler +Date: Thu, 2 May 2019 19:50:57 -0500 +Subject: [PATCH] scsi: ibmvscsi: redo driver work thread to use enum action + states + +References: bsc#1161951 ltc#183551 +Patch-mainline: v5.3-rc1 +Git-commit: 6e40de8b6b3cfa7288bb4a1fee2c7173f53b7345 + +The current implemenation relies on two flags in the driver's private host +structure to signal the need for a host reset or to reenable the CRQ after +a LPAR migration. This patch does away with those flags and introduces a +single action flag and defined enums for the supported kthread work +actions. Lastly, the if/else logic is replaced with a switch statement. + +Signed-off-by: Tyrel Datwyler +Signed-off-by: Martin K. Petersen +Acked-by: Michal Suchanek +--- + drivers/scsi/ibmvscsi/ibmvscsi.c | 61 ++++++++++++++++++++++---------- + drivers/scsi/ibmvscsi/ibmvscsi.h | 9 +++-- + 2 files changed, 49 insertions(+), 21 deletions(-) + +diff --git a/drivers/scsi/ibmvscsi/ibmvscsi.c b/drivers/scsi/ibmvscsi/ibmvscsi.c +index 65fc8ca962c5..8df82c58e7b9 100644 +--- a/drivers/scsi/ibmvscsi/ibmvscsi.c ++++ b/drivers/scsi/ibmvscsi/ibmvscsi.c +@@ -828,7 +828,7 @@ static void ibmvscsi_reset_host(struct ibmvscsi_host_data *hostdata) + atomic_set(&hostdata->request_limit, 0); + + purge_requests(hostdata, DID_ERROR); +- hostdata->reset_crq = 1; ++ hostdata->action = IBMVSCSI_HOST_ACTION_RESET; + wake_up(&hostdata->work_wait_q); + } + +@@ -1797,7 +1797,7 @@ static void ibmvscsi_handle_crq(struct viosrp_crq *crq, + /* We need to re-setup the interpartition connection */ + dev_info(hostdata->dev, "Re-enabling adapter!\n"); + hostdata->client_migrated = 1; +- hostdata->reenable_crq = 1; ++ hostdata->action = IBMVSCSI_HOST_ACTION_REENABLE; + purge_requests(hostdata, DID_REQUEUE); + wake_up(&hostdata->work_wait_q); + } else { +@@ -2116,48 +2116,71 @@ static unsigned long ibmvscsi_get_desired_dma(struct vio_dev *vdev) + + static void ibmvscsi_do_work(struct ibmvscsi_host_data *hostdata) + { ++ unsigned long flags; + int rc; + char *action = "reset"; + +- if (hostdata->reset_crq) { +- smp_rmb(); +- hostdata->reset_crq = 0; +- ++ spin_lock_irqsave(hostdata->host->host_lock, flags); ++ switch (hostdata->action) { ++ case IBMVSCSI_HOST_ACTION_NONE: ++ break; ++ case IBMVSCSI_HOST_ACTION_RESET: ++ spin_unlock_irqrestore(hostdata->host->host_lock, flags); + rc = ibmvscsi_reset_crq_queue(&hostdata->queue, hostdata); ++ spin_lock_irqsave(hostdata->host->host_lock, flags); + if (!rc) + rc = ibmvscsi_send_crq(hostdata, 0xC001000000000000LL, 0); + vio_enable_interrupts(to_vio_dev(hostdata->dev)); +- } else if (hostdata->reenable_crq) { +- smp_rmb(); ++ break; ++ case IBMVSCSI_HOST_ACTION_REENABLE: + action = "enable"; ++ spin_unlock_irqrestore(hostdata->host->host_lock, flags); + rc = ibmvscsi_reenable_crq_queue(&hostdata->queue, hostdata); +- hostdata->reenable_crq = 0; ++ spin_lock_irqsave(hostdata->host->host_lock, flags); + if (!rc) + rc = ibmvscsi_send_crq(hostdata, 0xC001000000000000LL, 0); +- } else +- return; ++ break; ++ default: ++ break; ++ } ++ ++ hostdata->action = IBMVSCSI_HOST_ACTION_NONE; + + if (rc) { + atomic_set(&hostdata->request_limit, -1); + dev_err(hostdata->dev, "error after %s\n", action); + } ++ spin_unlock_irqrestore(hostdata->host->host_lock, flags); + + scsi_unblock_requests(hostdata->host); + } + +-static int ibmvscsi_work_to_do(struct ibmvscsi_host_data *hostdata) ++static int __ibmvscsi_work_to_do(struct ibmvscsi_host_data *hostdata) + { + if (kthread_should_stop()) + return 1; +- else if (hostdata->reset_crq) { +- smp_rmb(); +- return 1; +- } else if (hostdata->reenable_crq) { +- smp_rmb(); +- return 1; ++ switch (hostdata->action) { ++ case IBMVSCSI_HOST_ACTION_NONE: ++ return 0; ++ case IBMVSCSI_HOST_ACTION_RESET: ++ case IBMVSCSI_HOST_ACTION_REENABLE: ++ default: ++ break; + } + +- return 0; ++ return 1; ++} ++ ++static int ibmvscsi_work_to_do(struct ibmvscsi_host_data *hostdata) ++{ ++ unsigned long flags; ++ int rc; ++ ++ spin_lock_irqsave(hostdata->host->host_lock, flags); ++ rc = __ibmvscsi_work_to_do(hostdata); ++ spin_unlock_irqrestore(hostdata->host->host_lock, flags); ++ ++ return rc; + } + + static int ibmvscsi_work(void *data) +diff --git a/drivers/scsi/ibmvscsi/ibmvscsi.h b/drivers/scsi/ibmvscsi/ibmvscsi.h +index 3a7875575616..04bcbc832dc9 100644 +--- a/drivers/scsi/ibmvscsi/ibmvscsi.h ++++ b/drivers/scsi/ibmvscsi/ibmvscsi.h +@@ -88,13 +88,18 @@ struct event_pool { + dma_addr_t iu_token; + }; + ++enum ibmvscsi_host_action { ++ IBMVSCSI_HOST_ACTION_NONE = 0, ++ IBMVSCSI_HOST_ACTION_RESET, ++ IBMVSCSI_HOST_ACTION_REENABLE, ++}; ++ + /* all driver data associated with a host adapter */ + struct ibmvscsi_host_data { + struct list_head host_list; + atomic_t request_limit; + int client_migrated; +- int reset_crq; +- int reenable_crq; ++ enum ibmvscsi_host_action action; + struct device *dev; + struct event_pool pool; + struct crq_queue queue; +-- +2.23.0 + diff --git a/patches.suse/scsi-libsas-fix-a-race-condition-when-smp-task-timeo.patch b/patches.suse/scsi-libsas-fix-a-race-condition-when-smp-task-timeo.patch index 34e20d3..a46ee07 100644 --- a/patches.suse/scsi-libsas-fix-a-race-condition-when-smp-task-timeo.patch +++ b/patches.suse/scsi-libsas-fix-a-race-condition-when-smp-task-timeo.patch @@ -3,7 +3,7 @@ Date: Tue, 25 Sep 2018 10:56:54 +0800 Subject: scsi: libsas: fix a race condition when smp task timeout Patch-mainline: v4.20-rc1 Git-commit: b90cd6f2b905905fb42671009dc0e27c310a16ae -References: FATE#326253 +References: FATE#326253 CVE-2018-20836 bsc#1134395 When the lldd is processing the complete sas task in interrupt and set the task stat as SAS_TASK_STATE_DONE, the smp timeout timer is able to be diff --git a/patches.suse/scsi-lpfc-Change-default-SCSI-LUN-QD-to-64.patch b/patches.suse/scsi-lpfc-Change-default-SCSI-LUN-QD-to-64.patch new file mode 100644 index 0000000..ea1fb48 --- /dev/null +++ b/patches.suse/scsi-lpfc-Change-default-SCSI-LUN-QD-to-64.patch @@ -0,0 +1,46 @@ +From 763a18cbf79b0395ae09e63dc4d77335e4f88368 Mon Sep 17 00:00:00 2001 +From: Dick Kennedy +Date: Mon, 23 Mar 2020 09:19:35 -0700 +Subject: [PATCH] scsi: lpfc: Change default SCSI LUN QD to 64 + +References: bsc#1164777 bsc#1164780 bsc#1165211 jsc#SLE-8654 +Patch-mainline: v5.7-rc1 +Git-commit: 763a18cbf79b0395ae09e63dc4d77335e4f88368 + +The default lun queue depth by the driver has been 30 for many years. +However, this value, when used with more recent hardware, has actually +throttled some tests that concentrate io on a lun. + +Increase the default lun queue depth to 64. + +Queue full handling, reported by the target, remains in effect and +unchanged. + +Link: https://lore.kernel.org/r/20200323161935.40341-1-jsmart2021@gmail.com +Signed-off-by: Dick Kennedy +Signed-off-by: James Smart +Signed-off-by: Martin K. Petersen +Acked-by: Daniel Wagner +--- + drivers/scsi/lpfc/lpfc_attr.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c +index 3260e76e55b9..fae1c93353ac 100644 +--- a/drivers/scsi/lpfc/lpfc_attr.c ++++ b/drivers/scsi/lpfc/lpfc_attr.c +@@ -3805,9 +3805,9 @@ LPFC_VPORT_ATTR_R(enable_da_id, 1, 0, 1, + + /* + # lun_queue_depth: This parameter is used to limit the number of outstanding +-# commands per FCP LUN. Value range is [1,512]. Default value is 30. ++# commands per FCP LUN. + */ +-LPFC_VPORT_ATTR_R(lun_queue_depth, 30, 1, 512, ++LPFC_VPORT_ATTR_R(lun_queue_depth, 64, 1, 512, + "Max number of FCP commands we can queue to a specific LUN"); + + /* +-- +2.23.0 + diff --git a/patches.suse/scsi-lpfc-Clean-up-hba-max_lun_queue_depth-checks.patch b/patches.suse/scsi-lpfc-Clean-up-hba-max_lun_queue_depth-checks.patch new file mode 100644 index 0000000..4f3bc9e --- /dev/null +++ b/patches.suse/scsi-lpfc-Clean-up-hba-max_lun_queue_depth-checks.patch @@ -0,0 +1,82 @@ +From: James Smart +Date: Mon, 27 Jan 2020 16:23:09 -0800 +Subject: scsi: lpfc: Clean up hba max_lun_queue_depth checks +Patch-mainline: v5.7-rc1 +Git-commit: f6770e7d2329f0b05223fffea9eb821fd2dd038a +References: bsc#1164777 bsc#1164780 bsc#1165211 + +The current code does some odd +1 over maximum xri count checks and +requires that the lun_queue_count can't be bigger than maximum xri count +divided by 8. These items are bogus. + +Clean the code up to cap lun_queue_count to maximum xri count. + +Link: https://lore.kernel.org/r/20200128002312.16346-10-jsmart2021@gmail.com +Signed-off-by: Dick Kennedy +Signed-off-by: James Smart +Signed-off-by: Martin K. Petersen +Acked-by: Daniel Wagner +--- + drivers/scsi/lpfc/lpfc_attr.c | 3 --- + drivers/scsi/lpfc/lpfc_init.c | 17 ++++------------- + drivers/scsi/lpfc/lpfc_sli.c | 9 --------- + 3 files changed, 4 insertions(+), 25 deletions(-) + +--- a/drivers/scsi/lpfc/lpfc_attr.c ++++ b/drivers/scsi/lpfc/lpfc_attr.c +@@ -3875,9 +3875,6 @@ LPFC_VPORT_ATTR_R(enable_da_id, 1, 0, 1, + /* + # lun_queue_depth: This parameter is used to limit the number of outstanding + # commands per FCP LUN. Value range is [1,512]. Default value is 30. +-# If this parameter value is greater than 1/8th the maximum number of exchanges +-# supported by the HBA port, then the lun queue depth will be reduced to +-# 1/8th the maximum number of exchanges. + */ + LPFC_VPORT_ATTR_R(lun_queue_depth, 30, 1, 512, + "Max number of FCP commands we can queue to a specific LUN"); +--- a/drivers/scsi/lpfc/lpfc_init.c ++++ b/drivers/scsi/lpfc/lpfc_init.c +@@ -512,21 +512,12 @@ lpfc_config_port_post(struct lpfc_hba *p + lpfc_sli_read_link_ste(phba); + + /* Reset the DFT_HBA_Q_DEPTH to the max xri */ +- i = (mb->un.varRdConfig.max_xri + 1); +- if (phba->cfg_hba_queue_depth > i) { ++ if (phba->cfg_hba_queue_depth > mb->un.varRdConfig.max_xri) { + lpfc_printf_log(phba, KERN_WARNING, LOG_INIT, + "3359 HBA queue depth changed from %d to %d\n", +- phba->cfg_hba_queue_depth, i); +- phba->cfg_hba_queue_depth = i; +- } +- +- /* Reset the DFT_LUN_Q_DEPTH to (max xri >> 3) */ +- i = (mb->un.varRdConfig.max_xri >> 3); +- if (phba->pport->cfg_lun_queue_depth > i) { +- lpfc_printf_log(phba, KERN_WARNING, LOG_INIT, +- "3360 LUN queue depth changed from %d to %d\n", +- phba->pport->cfg_lun_queue_depth, i); +- phba->pport->cfg_lun_queue_depth = i; ++ phba->cfg_hba_queue_depth, ++ mb->un.varRdConfig.max_xri); ++ phba->cfg_hba_queue_depth = mb->un.varRdConfig.max_xri; + } + + phba->lmt = mb->un.varRdConfig.lmt; +--- a/drivers/scsi/lpfc/lpfc_sli.c ++++ b/drivers/scsi/lpfc/lpfc_sli.c +@@ -7378,15 +7378,6 @@ lpfc_sli4_hba_setup(struct lpfc_hba *phb + phba->vpd.rev.fcphHigh, phba->vpd.rev.fcphLow, + phba->vpd.rev.feaLevelHigh, phba->vpd.rev.feaLevelLow); + +- /* Reset the DFT_LUN_Q_DEPTH to (max xri >> 3) */ +- rc = (phba->sli4_hba.max_cfg_param.max_xri >> 3); +- if (phba->pport->cfg_lun_queue_depth > rc) { +- lpfc_printf_log(phba, KERN_WARNING, LOG_INIT, +- "3362 LUN queue depth changed from %d to %d\n", +- phba->pport->cfg_lun_queue_depth, rc); +- phba->pport->cfg_lun_queue_depth = rc; +- } +- + if (bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf) == + LPFC_SLI_INTF_IF_TYPE_0) { + lpfc_set_features(phba, mboxq, LPFC_SET_UE_RECOVERY); diff --git a/patches.suse/scsi-lpfc-Copyright-updates-for-12.6.0.4-patches.patch b/patches.suse/scsi-lpfc-Copyright-updates-for-12.6.0.4-patches.patch new file mode 100644 index 0000000..3f34ed3 --- /dev/null +++ b/patches.suse/scsi-lpfc-Copyright-updates-for-12.6.0.4-patches.patch @@ -0,0 +1,137 @@ +From: James Smart +Date: Mon, 27 Jan 2020 16:23:12 -0800 +Subject: scsi: lpfc: Copyright updates for 12.6.0.4 patches +Patch-mainline: v5.7-rc1 +Git-commit: 145e5a8a5cbd0c608dfe653c92edb70a580bdbf6 +References: bsc#1164777 bsc#1164780 bsc#1165211 + +Update copyrights to 2020 for files modified in the 12.6.0.4 patch set. + +Link: https://lore.kernel.org/r/20200128002312.16346-13-jsmart2021@gmail.com +Signed-off-by: Dick Kennedy +Signed-off-by: James Smart +Signed-off-by: Martin K. Petersen +Acked-by: Daniel Wagner +--- + drivers/scsi/lpfc/lpfc.h | 2 +- + drivers/scsi/lpfc/lpfc_attr.c | 2 +- + drivers/scsi/lpfc/lpfc_ct.c | 2 +- + drivers/scsi/lpfc/lpfc_els.c | 2 +- + drivers/scsi/lpfc/lpfc_hbadisc.c | 2 +- + drivers/scsi/lpfc/lpfc_hw.h | 2 +- + drivers/scsi/lpfc/lpfc_init.c | 2 +- + drivers/scsi/lpfc/lpfc_scsi.c | 2 +- + drivers/scsi/lpfc/lpfc_sli.c | 2 +- + drivers/scsi/lpfc/lpfc_version.h | 2 +- + 10 files changed, 10 insertions(+), 10 deletions(-) + +--- a/drivers/scsi/lpfc/lpfc.h ++++ b/drivers/scsi/lpfc/lpfc.h +@@ -1,7 +1,7 @@ + /******************************************************************* + * This file is part of the Emulex Linux Device Driver for * + * Fibre Channel Host Bus Adapters. * +- * Copyright (C) 2017-2019 Broadcom. All Rights Reserved. The term * ++ * Copyright (C) 2017-2020 Broadcom. All Rights Reserved. The term * + * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. * + * Copyright (C) 2004-2016 Emulex. All rights reserved. * + * EMULEX and SLI are trademarks of Emulex. * +--- a/drivers/scsi/lpfc/lpfc_attr.c ++++ b/drivers/scsi/lpfc/lpfc_attr.c +@@ -1,7 +1,7 @@ + /******************************************************************* + * This file is part of the Emulex Linux Device Driver for * + * Fibre Channel Host Bus Adapters. * +- * Copyright (C) 2017-2019 Broadcom. All Rights Reserved. The term * ++ * Copyright (C) 2017-2020 Broadcom. All Rights Reserved. The term * + * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. * + * Copyright (C) 2004-2016 Emulex. All rights reserved. * + * EMULEX and SLI are trademarks of Emulex. * +--- a/drivers/scsi/lpfc/lpfc_ct.c ++++ b/drivers/scsi/lpfc/lpfc_ct.c +@@ -1,7 +1,7 @@ + /******************************************************************* + * This file is part of the Emulex Linux Device Driver for * + * Fibre Channel Host Bus Adapters. * +- * Copyright (C) 2017-2019 Broadcom. All Rights Reserved. The term * ++ * Copyright (C) 2017-2020 Broadcom. All Rights Reserved. The term * + * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. * + * Copyright (C) 2004-2016 Emulex. All rights reserved. * + * EMULEX and SLI are trademarks of Emulex. * +--- a/drivers/scsi/lpfc/lpfc_els.c ++++ b/drivers/scsi/lpfc/lpfc_els.c +@@ -1,7 +1,7 @@ + /******************************************************************* + * This file is part of the Emulex Linux Device Driver for * + * Fibre Channel Host Bus Adapters. * +- * Copyright (C) 2017-2019 Broadcom. All Rights Reserved. The term * ++ * Copyright (C) 2017-2020 Broadcom. All Rights Reserved. The term * + * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. * + * Copyright (C) 2004-2016 Emulex. All rights reserved. * + * EMULEX and SLI are trademarks of Emulex. * +--- a/drivers/scsi/lpfc/lpfc_hbadisc.c ++++ b/drivers/scsi/lpfc/lpfc_hbadisc.c +@@ -1,7 +1,7 @@ + /******************************************************************* + * This file is part of the Emulex Linux Device Driver for * + * Fibre Channel Host Bus Adapters. * +- * Copyright (C) 2017-2019 Broadcom. All Rights Reserved. The term * ++ * Copyright (C) 2017-2020 Broadcom. All Rights Reserved. The term * + * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. * + * Copyright (C) 2004-2016 Emulex. All rights reserved. * + * EMULEX and SLI are trademarks of Emulex. * +--- a/drivers/scsi/lpfc/lpfc_hw.h ++++ b/drivers/scsi/lpfc/lpfc_hw.h +@@ -1,7 +1,7 @@ + /******************************************************************* + * This file is part of the Emulex Linux Device Driver for * + * Fibre Channel Host Bus Adapters. * +- * Copyright (C) 2017-2018 Broadcom. All Rights Reserved. The term * ++ * Copyright (C) 2017-2020 Broadcom. All Rights Reserved. The term * + * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. * + * Copyright (C) 2004-2016 Emulex. All rights reserved. * + * EMULEX and SLI are trademarks of Emulex. * +--- a/drivers/scsi/lpfc/lpfc_init.c ++++ b/drivers/scsi/lpfc/lpfc_init.c +@@ -1,7 +1,7 @@ + /******************************************************************* + * This file is part of the Emulex Linux Device Driver for * + * Fibre Channel Host Bus Adapters. * +- * Copyright (C) 2017-2019 Broadcom. All Rights Reserved. The term * ++ * Copyright (C) 2017-2020 Broadcom. All Rights Reserved. The term * + * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. * + * Copyright (C) 2004-2016 Emulex. All rights reserved. * + * EMULEX and SLI are trademarks of Emulex. * +--- a/drivers/scsi/lpfc/lpfc_scsi.c ++++ b/drivers/scsi/lpfc/lpfc_scsi.c +@@ -1,7 +1,7 @@ + /******************************************************************* + * This file is part of the Emulex Linux Device Driver for * + * Fibre Channel Host Bus Adapters. * +- * Copyright (C) 2017-2019 Broadcom. All Rights Reserved. The term * ++ * Copyright (C) 2017-2020 Broadcom. All Rights Reserved. The term * + * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. * + * Copyright (C) 2004-2016 Emulex. All rights reserved. * + * EMULEX and SLI are trademarks of Emulex. * +--- a/drivers/scsi/lpfc/lpfc_sli.c ++++ b/drivers/scsi/lpfc/lpfc_sli.c +@@ -1,7 +1,7 @@ + /******************************************************************* + * This file is part of the Emulex Linux Device Driver for * + * Fibre Channel Host Bus Adapters. * +- * Copyright (C) 2017-2019 Broadcom. All Rights Reserved. The term * ++ * Copyright (C) 2017-2020 Broadcom. All Rights Reserved. The term * + * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. * + * Copyright (C) 2004-2016 Emulex. All rights reserved. * + * EMULEX and SLI are trademarks of Emulex. * +--- a/drivers/scsi/lpfc/lpfc_version.h ++++ b/drivers/scsi/lpfc/lpfc_version.h +@@ -1,7 +1,7 @@ + /******************************************************************* + * This file is part of the Emulex Linux Device Driver for * + * Fibre Channel Host Bus Adapters. * +- * Copyright (C) 2017-2019 Broadcom. All Rights Reserved. The term * ++ * Copyright (C) 2017-2020 Broadcom. All Rights Reserved. The term * + * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. * + * Copyright (C) 2004-2016 Emulex. All rights reserved. * + * EMULEX and SLI are trademarks of Emulex. * diff --git a/patches.suse/scsi-lpfc-Fix-Fabric-hostname-registration-if-system.patch b/patches.suse/scsi-lpfc-Fix-Fabric-hostname-registration-if-system.patch new file mode 100644 index 0000000..e18ce79 --- /dev/null +++ b/patches.suse/scsi-lpfc-Fix-Fabric-hostname-registration-if-system.patch @@ -0,0 +1,179 @@ +From: James Smart +Date: Wed, 18 Dec 2019 15:58:02 -0800 +Subject: scsi: lpfc: Fix Fabric hostname registration if system hostname + changes +Patch-mainline: v5.6-rc1 +Git-commit: e3ba04c9bad1d1c7f15df43da25e878045150777 +References: bsc#1164777 bsc#1164780 bsc#1165211 + +There are reports of multiple ports on the same system displaying different +hostnames in fabric FDMI displays. + +Currently, the driver registers the hostname at initialization and obtains +the hostname via init_utsname()->nodename queried at the time the FC link +comes up. Unfortunately, if the machine hostname is updated after +initialization, such as via DHCP or admin command, the value registered +initially will be incorrect. + +Fix by having the driver save the hostname that was registered with FDMI. +The driver then runs a heartbeat action that will check the hostname. If +the name changes, reregister the FMDI data. + +The hostname is used in RSNN_NN, FDMI RPA and FDMI RHBA. + +Link: https://lore.kernel.org/r/20191218235808.31922-5-jsmart2021@gmail.com +Signed-off-by: Dick Kennedy +Signed-off-by: James Smart +Signed-off-by: Martin K. Petersen +Acked-by: Daniel Wagner +--- + drivers/scsi/lpfc/lpfc.h | 2 + + drivers/scsi/lpfc/lpfc_crtn.h | 2 - + drivers/scsi/lpfc/lpfc_ct.c | 48 ++++++++++++++++++++++++++++++--------- + drivers/scsi/lpfc/lpfc_hbadisc.c | 5 ++++ + drivers/scsi/lpfc/lpfc_init.c | 2 - + 5 files changed, 46 insertions(+), 13 deletions(-) + +--- a/drivers/scsi/lpfc/lpfc.h ++++ b/drivers/scsi/lpfc/lpfc.h +@@ -1221,6 +1221,8 @@ struct lpfc_hba { + #define LPFC_POLL_HB 1 /* slowpath heartbeat */ + #define LPFC_POLL_FASTPATH 0 /* called from fastpath */ + #define LPFC_POLL_SLOWPATH 1 /* called from slowpath */ ++ ++ char os_host_name[MAXHOSTNAMELEN]; + }; + + static inline struct Scsi_Host * +--- a/drivers/scsi/lpfc/lpfc_crtn.h ++++ b/drivers/scsi/lpfc/lpfc_crtn.h +@@ -179,7 +179,7 @@ int lpfc_issue_gidft(struct lpfc_vport * + int lpfc_get_gidft_type(struct lpfc_vport *vport, struct lpfc_iocbq *iocbq); + int lpfc_ns_cmd(struct lpfc_vport *, int, uint8_t, uint32_t); + int lpfc_fdmi_cmd(struct lpfc_vport *, struct lpfc_nodelist *, int, uint32_t); +-void lpfc_fdmi_num_disc_check(struct lpfc_vport *); ++void lpfc_fdmi_change_check(struct lpfc_vport *vport); + void lpfc_delayed_disc_tmo(struct timer_list *); + void lpfc_delayed_disc_timeout_handler(struct lpfc_vport *); + +--- a/drivers/scsi/lpfc/lpfc_ct.c ++++ b/drivers/scsi/lpfc/lpfc_ct.c +@@ -1511,7 +1511,7 @@ lpfc_vport_symbolic_node_name(struct lpf + if (strlcat(symbol, tmp, size) >= size) + goto buffer_done; + +- scnprintf(tmp, sizeof(tmp), " HN:%s", init_utsname()->nodename); ++ scnprintf(tmp, sizeof(tmp), " HN:%s", vport->phba->os_host_name); + if (strlcat(symbol, tmp, size) >= size) + goto buffer_done; + +@@ -2000,14 +2000,16 @@ lpfc_cmpl_ct_disc_fdmi(struct lpfc_hba * + + + /** +- * lpfc_fdmi_num_disc_check - Check how many mapped NPorts we are connected to ++ * lpfc_fdmi_change_check - Check for changed FDMI parameters + * @vport: pointer to a host virtual N_Port data structure. + * +- * Called from hbeat timeout routine to check if the number of discovered +- * ports has changed. If so, re-register thar port Attribute. ++ * Check how many mapped NPorts we are connected to ++ * Check if our hostname changed ++ * Called from hbeat timeout routine to check if any FDMI parameters ++ * changed. If so, re-register those Attributes. + */ + void +-lpfc_fdmi_num_disc_check(struct lpfc_vport *vport) ++lpfc_fdmi_change_check(struct lpfc_vport *vport) + { + struct lpfc_hba *phba = vport->phba; + struct lpfc_nodelist *ndlp; +@@ -2020,17 +2022,41 @@ lpfc_fdmi_num_disc_check(struct lpfc_vpo + if (!(vport->fc_flag & FC_FABRIC)) + return; + ++ ndlp = lpfc_findnode_did(vport, FDMI_DID); ++ if (!ndlp || !NLP_CHK_NODE_ACT(ndlp)) ++ return; ++ ++ /* Check if system hostname changed */ ++ if (strcmp(phba->os_host_name, init_utsname()->nodename)) { ++ memset(phba->os_host_name, 0, sizeof(phba->os_host_name)); ++ scnprintf(phba->os_host_name, sizeof(phba->os_host_name), "%s", ++ init_utsname()->nodename); ++ lpfc_ns_cmd(vport, SLI_CTNS_RSNN_NN, 0, 0); ++ ++ /* Since this effects multiple HBA and PORT attributes, we need ++ * de-register and go thru the whole FDMI registration cycle. ++ * DHBA -> DPRT -> RHBA -> RPA (physical port) ++ * DPRT -> RPRT (vports) ++ */ ++ if (vport->port_type == LPFC_PHYSICAL_PORT) ++ lpfc_fdmi_cmd(vport, ndlp, SLI_MGMT_DHBA, 0); ++ else ++ lpfc_fdmi_cmd(vport, ndlp, SLI_MGMT_DPRT, 0); ++ ++ /* Since this code path registers all the port attributes ++ * we can just return without further checking. ++ */ ++ return; ++ } ++ + if (!(vport->fdmi_port_mask & LPFC_FDMI_PORT_ATTR_num_disc)) + return; + ++ /* Check if the number of mapped NPorts changed */ + cnt = lpfc_find_map_node(vport); + if (cnt == vport->fdmi_num_disc) + return; + +- ndlp = lpfc_findnode_did(vport, FDMI_DID); +- if (!ndlp || !NLP_CHK_NODE_ACT(ndlp)) +- return; +- + if (vport->port_type == LPFC_PHYSICAL_PORT) { + lpfc_fdmi_cmd(vport, ndlp, SLI_MGMT_RPA, + LPFC_FDMI_PORT_ATTR_num_disc); +@@ -2618,8 +2644,8 @@ lpfc_fdmi_port_attr_host_name(struct lpf + ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue; + memset(ae, 0, 256); + +- snprintf(ae->un.AttrString, sizeof(ae->un.AttrString), "%s", +- init_utsname()->nodename); ++ scnprintf(ae->un.AttrString, sizeof(ae->un.AttrString), "%s", ++ vport->phba->os_host_name); + + len = strnlen(ae->un.AttrString, sizeof(ae->un.AttrString)); + len += (len & 3) ? (4 - (len & 3)) : 4; +--- a/drivers/scsi/lpfc/lpfc_hbadisc.c ++++ b/drivers/scsi/lpfc/lpfc_hbadisc.c +@@ -28,6 +28,7 @@ + #include + #include + #include ++#include + + #include + #include +@@ -3315,6 +3316,10 @@ lpfc_mbx_process_link_up(struct lpfc_hba + lpfc_sli4_clear_fcf_rr_bmask(phba); + } + ++ /* Prepare for LINK up registrations */ ++ memset(phba->os_host_name, 0, sizeof(phba->os_host_name)); ++ scnprintf(phba->os_host_name, sizeof(phba->os_host_name), "%s", ++ init_utsname()->nodename); + return; + out: + lpfc_vport_set_state(vport, FC_VPORT_FAILED); +--- a/drivers/scsi/lpfc/lpfc_init.c ++++ b/drivers/scsi/lpfc/lpfc_init.c +@@ -1362,7 +1362,7 @@ lpfc_hb_timeout_handler(struct lpfc_hba + if (vports != NULL) + for (i = 0; i <= phba->max_vports && vports[i] != NULL; i++) { + lpfc_rcv_seq_check_edtov(vports[i]); +- lpfc_fdmi_num_disc_check(vports[i]); ++ lpfc_fdmi_change_check(vports[i]); + } + lpfc_destroy_vport_work_array(phba, vports); + diff --git a/patches.suse/scsi-lpfc-Fix-MDS-Latency-Diagnostics-Err-drop-rates.patch b/patches.suse/scsi-lpfc-Fix-MDS-Latency-Diagnostics-Err-drop-rates.patch new file mode 100644 index 0000000..70ba310 --- /dev/null +++ b/patches.suse/scsi-lpfc-Fix-MDS-Latency-Diagnostics-Err-drop-rates.patch @@ -0,0 +1,56 @@ +From: James Smart +Date: Wed, 18 Dec 2019 15:58:06 -0800 +Subject: scsi: lpfc: Fix MDS Latency Diagnostics Err-drop rates +Patch-mainline: v5.6-rc1 +Git-commit: 999fbbceb8312a764b318cf19510273291ec3575 +References: bsc#1164777 bsc#1164780 bsc#1165211 + +When running Cisco-MDS diagnostics which perform driver-level frame loop +back, the switch is reporting errors. Diagnostic has a limit on latency +that is not being met by the driver. + +The requirement of Latency frames is that they should be responded back by +the host with a maximum delay of few hundreds of microseconds. If the +switch doesn't get response frames within this time frame, it fails the +test. + +Test is failing as the lpfc-wq workqueue was overwhelmed by the packet rate +and in some cases, the work element yielded to other kernel elements. + +To resolve, reduce the outstanding load allowed by the adapter. This +ensures the driver spends a reasonable amount of time doing loopback and +can do so such that latency values can be met. Load is managed by reducing +the number of receive buffers posted such that the link can be +backpressured to reduce load. + +Link: https://lore.kernel.org/r/20191218235808.31922-9-jsmart2021@gmail.com +Signed-off-by: Dick Kennedy +Signed-off-by: James Smart +Signed-off-by: Martin K. Petersen +Acked-by: Daniel Wagner +--- + drivers/scsi/lpfc/lpfc_sli.c | 13 +++++++++++-- + 1 file changed, 11 insertions(+), 2 deletions(-) + +--- a/drivers/scsi/lpfc/lpfc_sli.c ++++ b/drivers/scsi/lpfc/lpfc_sli.c +@@ -4918,8 +4918,17 @@ static int + lpfc_sli4_rb_setup(struct lpfc_hba *phba) + { + phba->hbq_in_use = 1; +- phba->hbqs[LPFC_ELS_HBQ].entry_count = +- lpfc_hbq_defs[LPFC_ELS_HBQ]->entry_count; ++ /** ++ * Specific case when the MDS diagnostics is enabled and supported. ++ * The receive buffer count is truncated to manage the incoming ++ * traffic. ++ **/ ++ if (phba->cfg_enable_mds_diags && phba->mds_diags_support) ++ phba->hbqs[LPFC_ELS_HBQ].entry_count = ++ lpfc_hbq_defs[LPFC_ELS_HBQ]->entry_count >> 1; ++ else ++ phba->hbqs[LPFC_ELS_HBQ].entry_count = ++ lpfc_hbq_defs[LPFC_ELS_HBQ]->entry_count; + phba->hbq_count = 1; + lpfc_sli_hbqbuf_init_hbqs(phba, LPFC_ELS_HBQ); + /* Initially populate or replenish the HBQs */ diff --git a/patches.suse/scsi-lpfc-Fix-RQ-buffer-leakage-when-no-IOCBs-availa.patch b/patches.suse/scsi-lpfc-Fix-RQ-buffer-leakage-when-no-IOCBs-availa.patch new file mode 100644 index 0000000..8cd2a04 --- /dev/null +++ b/patches.suse/scsi-lpfc-Fix-RQ-buffer-leakage-when-no-IOCBs-availa.patch @@ -0,0 +1,51 @@ +From: James Smart +Date: Mon, 27 Jan 2020 16:23:01 -0800 +Subject: scsi: lpfc: Fix RQ buffer leakage when no IOCBs available +Patch-mainline: v5.7-rc1 +Git-commit: 39c4f1a965a9244c3ba60695e8ff8da065ec6ac4 +References: bsc#1164777 bsc#1164780 bsc#1165211 + +The driver is occasionally seeing the following SLI Port error, requiring +reset and reinit: + + Port Status Event: ... error 1=0x52004a01, error 2=0x218 + +The failure means an RQ timeout. That is, the adapter had received +asynchronous receive frames, ran out of buffer slots to place the frames, +and the driver did not replenish the buffer slots before a timeout +occurred. The driver should not be so slow in replenishing buffers that a +timeout can occur. + +When the driver received all the frames of a sequence, it allocates an IOCB +to put the frames in. In a situation where there was no IOCB available for +the frame of a sequence, the RQ buffer corresponding to the first frame of +the sequence was not returned to the FW. Eventually, with enough traffic +encountering the situation, the timeout occurred. + +Fix by releasing the buffer back to firmware whenever there is no IOCB for +the first frame. + +[mkp: typo] + +Link: https://lore.kernel.org/r/20200128002312.16346-2-jsmart2021@gmail.com +Signed-off-by: Dick Kennedy +Signed-off-by: James Smart +Signed-off-by: Martin K. Petersen +Acked-by: Daniel Wagner +--- + drivers/scsi/lpfc/lpfc_sli.c | 4 ++++ + 1 file changed, 4 insertions(+) + +--- a/drivers/scsi/lpfc/lpfc_sli.c ++++ b/drivers/scsi/lpfc/lpfc_sli.c +@@ -17957,6 +17957,10 @@ lpfc_prep_seq(struct lpfc_vport *vport, + list_add_tail(&iocbq->list, &first_iocbq->list); + } + } ++ /* Free the sequence's header buffer */ ++ if (!first_iocbq) ++ lpfc_in_buf_free(vport->phba, &seq_dmabuf->dbuf); ++ + return first_iocbq; + } + diff --git a/patches.suse/scsi-lpfc-Fix-Rework-setting-of-fdmi-symbolic-node-n.patch b/patches.suse/scsi-lpfc-Fix-Rework-setting-of-fdmi-symbolic-node-n.patch new file mode 100644 index 0000000..18f4d95 --- /dev/null +++ b/patches.suse/scsi-lpfc-Fix-Rework-setting-of-fdmi-symbolic-node-n.patch @@ -0,0 +1,90 @@ +From: James Smart +Date: Wed, 18 Dec 2019 15:58:00 -0800 +Subject: scsi: lpfc: Fix: Rework setting of fdmi symbolic node name + registration +Patch-mainline: v5.6-rc1 +Git-commit: df9166bfa7750bade5737ffc91fbd432e0354442 +References: bsc#1164777 bsc#1164780 bsc#1165211 + +This patch reworks the fdmi symbolic node name data for the following two +issues: + + - Correcting extraneous periods following the DV and HN fdmi data fields. + + - Avoiding buffer overflow issues when formatting the data. + +The fix to the fist issue is to just remove the characters. + +The fix to the second issue has all data being staged in temporary storage +before being moved to the real buffer. + +Link: https://lore.kernel.org/r/20191218235808.31922-3-jsmart2021@gmail.com +Signed-off-by: Dick Kennedy +Signed-off-by: James Smart +Signed-off-by: Martin K. Petersen +Acked-by: Daniel Wagner +--- + drivers/scsi/lpfc/lpfc_ct.c | 48 ++++++++++++++++++++++---------------------- + 1 file changed, 25 insertions(+), 23 deletions(-) + +--- a/drivers/scsi/lpfc/lpfc_ct.c ++++ b/drivers/scsi/lpfc/lpfc_ct.c +@@ -1493,33 +1493,35 @@ int + lpfc_vport_symbolic_node_name(struct lpfc_vport *vport, char *symbol, + size_t size) + { +- char fwrev[FW_REV_STR_SIZE]; +- int n; ++ char fwrev[FW_REV_STR_SIZE] = {0}; ++ char tmp[MAXHOSTNAMELEN] = {0}; + +- lpfc_decode_firmware_rev(vport->phba, fwrev, 0); ++ memset(symbol, 0, size); ++ ++ scnprintf(tmp, sizeof(tmp), "Emulex %s", vport->phba->ModelName); ++ if (strlcat(symbol, tmp, size) >= size) ++ goto buffer_done; + +- n = scnprintf(symbol, size, "Emulex %s", vport->phba->ModelName); +- if (size < n) +- return n; +- +- n += scnprintf(symbol + n, size - n, " FV%s", fwrev); +- if (size < n) +- return n; +- +- n += scnprintf(symbol + n, size - n, " DV%s.", +- lpfc_release_version); +- if (size < n) +- return n; +- +- n += scnprintf(symbol + n, size - n, " HN:%s.", +- init_utsname()->nodename); +- if (size < n) +- return n; ++ lpfc_decode_firmware_rev(vport->phba, fwrev, 0); ++ scnprintf(tmp, sizeof(tmp), " FV%s", fwrev); ++ if (strlcat(symbol, tmp, size) >= size) ++ goto buffer_done; ++ ++ scnprintf(tmp, sizeof(tmp), " DV%s", lpfc_release_version); ++ if (strlcat(symbol, tmp, size) >= size) ++ goto buffer_done; ++ ++ scnprintf(tmp, sizeof(tmp), " HN:%s", init_utsname()->nodename); ++ if (strlcat(symbol, tmp, size) >= size) ++ goto buffer_done; + + /* Note :- OS name is "Linux" */ +- n += scnprintf(symbol + n, size - n, " OS:%s", +- init_utsname()->sysname); +- return n; ++ scnprintf(tmp, sizeof(tmp), " OS:%s", init_utsname()->sysname); ++ strlcat(symbol, tmp, size); ++ ++buffer_done: ++ return strnlen(symbol, size); ++ + } + + static uint32_t diff --git a/patches.suse/scsi-lpfc-Fix-broken-Credit-Recovery-after-driver-lo.patch b/patches.suse/scsi-lpfc-Fix-broken-Credit-Recovery-after-driver-lo.patch new file mode 100644 index 0000000..f0b89ef --- /dev/null +++ b/patches.suse/scsi-lpfc-Fix-broken-Credit-Recovery-after-driver-lo.patch @@ -0,0 +1,143 @@ +From: James Smart +Date: Mon, 27 Jan 2020 16:23:03 -0800 +Subject: scsi: lpfc: Fix broken Credit Recovery after driver load +Patch-mainline: v5.7-rc1 +Git-commit: 835214f5d5f516a38069bc077c879c7da00d6108 +References: bsc#1164777 bsc#1164780 bsc#1165211 + +When driver is set to enable bb credit recovery, the switch displayed the +setting as inactive. If the link bounces, it switches to Active. + +During link up processing, the driver currently does a MBX_READ_SPARAM +followed by a MBX_CONFIG_LINK. These mbox commands are queued to be +executed, one at a time and the completion is processed by the worker +thread. Since the MBX_READ_SPARAM is done BEFORE the MBX_CONFIG_LINK, the +BB_SC_N bit is never set the the returned values. BB Credit recovery status +only gets set after the driver requests the feature in CONFIG_LINK, which +is done after the link up. Thus the ordering of READ_SPARAM needs to follow +the CONFIG_LINK. + +Fix by reordering so that READ_SPARAM is done after CONFIG_LINK. Added a +HBA_DEFER_FLOGI flag so that any FLOGI handling waits until after the +READ_SPARAM is done so that the proper BB credit value is set in the FLOGI +payload. + +Fixes: 6bfb16208298 ("scsi: lpfc: Fix configuration of BB credit recovery in service parameters") +Cc: # v5.4+ +Link: https://lore.kernel.org/r/20200128002312.16346-4-jsmart2021@gmail.com +Signed-off-by: Dick Kennedy +Signed-off-by: James Smart +Signed-off-by: Martin K. Petersen +Acked-by: Daniel Wagner +--- + drivers/scsi/lpfc/lpfc.h | 1 + drivers/scsi/lpfc/lpfc_hbadisc.c | 59 +++++++++++++++++++++++++-------------- + 2 files changed, 40 insertions(+), 20 deletions(-) + +--- a/drivers/scsi/lpfc/lpfc.h ++++ b/drivers/scsi/lpfc/lpfc.h +@@ -748,6 +748,7 @@ struct lpfc_hba { + * capability + */ + #define HBA_FLOGI_ISSUED 0x100000 /* FLOGI was issued */ ++#define HBA_DEFER_FLOGI 0x800000 /* Defer FLOGI till read_sparm cmpl */ + + uint32_t fcp_ring_in_use; /* When polling test if intr-hndlr active*/ + struct lpfc_dmabuf slim2p; +--- a/drivers/scsi/lpfc/lpfc_hbadisc.c ++++ b/drivers/scsi/lpfc/lpfc_hbadisc.c +@@ -1163,13 +1163,16 @@ lpfc_mbx_cmpl_local_config_link(struct l + } + + /* Start discovery by sending a FLOGI. port_state is identically +- * LPFC_FLOGI while waiting for FLOGI cmpl ++ * LPFC_FLOGI while waiting for FLOGI cmpl. Check if sending ++ * the FLOGI is being deferred till after MBX_READ_SPARAM completes. + */ +- if (vport->port_state != LPFC_FLOGI) +- lpfc_initial_flogi(vport); +- else if (vport->fc_flag & FC_PT2PT) +- lpfc_disc_start(vport); +- ++ if (vport->port_state != LPFC_FLOGI) { ++ if (!(phba->hba_flag & HBA_DEFER_FLOGI)) ++ lpfc_initial_flogi(vport); ++ } else { ++ if (vport->fc_flag & FC_PT2PT) ++ lpfc_disc_start(vport); ++ } + return; + + out: +@@ -3094,6 +3097,14 @@ lpfc_mbx_cmpl_read_sparam(struct lpfc_hb + lpfc_mbuf_free(phba, mp->virt, mp->phys); + kfree(mp); + mempool_free(pmb, phba->mbox_mem_pool); ++ ++ /* Check if sending the FLOGI is being deferred to after we get ++ * up to date CSPs from MBX_READ_SPARAM. ++ */ ++ if (phba->hba_flag & HBA_DEFER_FLOGI) { ++ lpfc_initial_flogi(vport); ++ phba->hba_flag &= ~HBA_DEFER_FLOGI; ++ } + return; + + out: +@@ -3224,6 +3235,23 @@ lpfc_mbx_process_link_up(struct lpfc_hba + } + + lpfc_linkup(phba); ++ sparam_mbox = NULL; ++ ++ if (!(phba->hba_flag & HBA_FCOE_MODE)) { ++ cfglink_mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); ++ if (!cfglink_mbox) ++ goto out; ++ vport->port_state = LPFC_LOCAL_CFG_LINK; ++ lpfc_config_link(phba, cfglink_mbox); ++ cfglink_mbox->vport = vport; ++ cfglink_mbox->mbox_cmpl = lpfc_mbx_cmpl_local_config_link; ++ rc = lpfc_sli_issue_mbox(phba, cfglink_mbox, MBX_NOWAIT); ++ if (rc == MBX_NOT_FINISHED) { ++ mempool_free(cfglink_mbox, phba->mbox_mem_pool); ++ goto out; ++ } ++ } ++ + sparam_mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); + if (!sparam_mbox) + goto out; +@@ -3244,20 +3272,7 @@ lpfc_mbx_process_link_up(struct lpfc_hba + goto out; + } + +- if (!(phba->hba_flag & HBA_FCOE_MODE)) { +- cfglink_mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); +- if (!cfglink_mbox) +- goto out; +- vport->port_state = LPFC_LOCAL_CFG_LINK; +- lpfc_config_link(phba, cfglink_mbox); +- cfglink_mbox->vport = vport; +- cfglink_mbox->mbox_cmpl = lpfc_mbx_cmpl_local_config_link; +- rc = lpfc_sli_issue_mbox(phba, cfglink_mbox, MBX_NOWAIT); +- if (rc == MBX_NOT_FINISHED) { +- mempool_free(cfglink_mbox, phba->mbox_mem_pool); +- goto out; +- } +- } else { ++ if (phba->hba_flag & HBA_FCOE_MODE) { + vport->port_state = LPFC_VPORT_UNKNOWN; + /* + * Add the driver's default FCF record at FCF index 0 now. This +@@ -3314,6 +3329,10 @@ lpfc_mbx_process_link_up(struct lpfc_hba + } + /* Reset FCF roundrobin bmask for new discovery */ + lpfc_sli4_clear_fcf_rr_bmask(phba); ++ } else { ++ if (phba->bbcredit_support && phba->cfg_enable_bbcr && ++ !(phba->link_flag & LS_LOOPBACK_MODE)) ++ phba->hba_flag |= HBA_DEFER_FLOGI; + } + + /* Prepare for LINK up registrations */ diff --git a/patches.suse/scsi-lpfc-Fix-compiler-warning-on-frame-size.patch b/patches.suse/scsi-lpfc-Fix-compiler-warning-on-frame-size.patch new file mode 100644 index 0000000..6ee1ced --- /dev/null +++ b/patches.suse/scsi-lpfc-Fix-compiler-warning-on-frame-size.patch @@ -0,0 +1,94 @@ +From: James Smart +Date: Mon, 27 Jan 2020 16:23:06 -0800 +Subject: scsi: lpfc: Fix compiler warning on frame size +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit +Patch-mainline: v5.7-rc1 +Git-commit: a99c80742af4b58bfd2d16cada8ee73cb9618649 +References: bsc#1164777 bsc#1164780 bsc#1165211 + +The following error is see from the compiler: + + drivers/scsi/lpfc/lpfc_init.c: In function + ‘lpfc_cpuhp_get_eq’: drivers/scsi/lpfc/lpfc_init.c:12660:1: + error: the frame size of 1032 bytes is larger than 1024 bytes + [-Werror=frame-larger-than=] + +The issue is due to allocating a cpumask on the stack. + +Fix by converting to a dynamical allocation of the cpu mask. + +Link: https://lore.kernel.org/r/20200128002312.16346-7-jsmart2021@gmail.com +Signed-off-by: Dick Kennedy +Signed-off-by: James Smart +Signed-off-by: Martin K. Petersen +Acked-by: Daniel Wagner +--- + drivers/scsi/lpfc/lpfc_init.c | 20 ++++++++++++++------ + 1 file changed, 14 insertions(+), 6 deletions(-) + +--- a/drivers/scsi/lpfc/lpfc_init.c ++++ b/drivers/scsi/lpfc/lpfc_init.c +@@ -11106,15 +11106,19 @@ found_any: + * @cpu: cpu going offline + * @eqlist: + */ +-static void ++static int + lpfc_cpuhp_get_eq(struct lpfc_hba *phba, unsigned int cpu, + struct list_head *eqlist) + { + const struct cpumask *maskp; + struct lpfc_queue *eq; +- cpumask_t tmp; ++ struct cpumask *tmp; + u16 idx; + ++ tmp = kzalloc(cpumask_size(), GFP_KERNEL); ++ if (!tmp) ++ return -ENOMEM; ++ + for (idx = 0; idx < phba->cfg_irq_chann; idx++) { + maskp = pci_irq_get_affinity(phba->pcidev, idx); + if (!maskp) +@@ -11124,7 +11128,7 @@ lpfc_cpuhp_get_eq(struct lpfc_hba *phba, + * then we don't need to poll the eq attached + * to it. + */ +- if (!cpumask_and(&tmp, maskp, cpumask_of(cpu))) ++ if (!cpumask_and(tmp, maskp, cpumask_of(cpu))) + continue; + /* get the cpus that are online and are affini- + * tized to this irq vector. If the count is +@@ -11132,8 +11136,8 @@ lpfc_cpuhp_get_eq(struct lpfc_hba *phba, + * down this vector. Since this cpu has not + * gone offline yet, we need >1. + */ +- cpumask_and(&tmp, maskp, cpu_online_mask); +- if (cpumask_weight(&tmp) > 1) ++ cpumask_and(tmp, maskp, cpu_online_mask); ++ if (cpumask_weight(tmp) > 1) + continue; + + /* Now that we have an irq to shutdown, get the eq +@@ -11144,6 +11148,8 @@ lpfc_cpuhp_get_eq(struct lpfc_hba *phba, + eq = phba->sli4_hba.hba_eq_hdl[idx].eq; + list_add(&eq->_poll_list, eqlist); + } ++ kfree(tmp); ++ return 0; + } + + static void __lpfc_cpuhp_remove(struct lpfc_hba *phba) +@@ -11314,7 +11320,9 @@ static int lpfc_cpu_offline(unsigned int + + lpfc_irq_rebalance(phba, cpu, true); + +- lpfc_cpuhp_get_eq(phba, cpu, &eqlist); ++ retval = lpfc_cpuhp_get_eq(phba, cpu, &eqlist); ++ if (retval) ++ return retval; + + /* start polling on these eq's */ + list_for_each_entry_safe(eq, next, &eqlist, _poll_list) { diff --git a/patches.suse/scsi-lpfc-Fix-coverity-errors-in-fmdi-attribute-hand.patch b/patches.suse/scsi-lpfc-Fix-coverity-errors-in-fmdi-attribute-hand.patch new file mode 100644 index 0000000..3f5f70e --- /dev/null +++ b/patches.suse/scsi-lpfc-Fix-coverity-errors-in-fmdi-attribute-hand.patch @@ -0,0 +1,531 @@ +From: James Smart +Date: Mon, 27 Jan 2020 16:23:07 -0800 +Subject: scsi: lpfc: Fix coverity errors in fmdi attribute handling +Patch-mainline: v5.7-rc1 +Git-commit: 4cb9e1ddaa145be9ed67b6a7de98ca705a43f998 +References: bsc#1164777 bsc#1164780 bsc#1165211 + +Coverity reported a memory corruption error for the fdmi attributes +routines: + + CID 15768 [Memory Corruption] Out-of-bounds access on FDMI + +Sloppy coding of the fmdi structures. In both the lpfc_fdmi_attr_def and +lpfc_fdmi_reg_port_list structures, a field was placed at the start of +payload that may have variable content. The field was given an arbitrary +type (uint32_t). The code then uses the field name to derive an address, +which it used in things such as memset and memcpy. The memset sizes or +memcpy lengths were larger than the arbitrary type, thus coverity reported +an error. + +Fix by replacing the arbitrary fields with the real field structures +describing the payload. + +Link: https://lore.kernel.org/r/20200128002312.16346-8-jsmart2021@gmail.com +Signed-off-by: Dick Kennedy +Signed-off-by: James Smart +Signed-off-by: Martin K. Petersen +Acked-by: Daniel Wagner +--- + drivers/scsi/lpfc/lpfc_ct.c | 137 ++++++++++++++++++++++---------------------- + drivers/scsi/lpfc/lpfc_hw.h | 36 +++++------ + 2 files changed, 85 insertions(+), 88 deletions(-) + +--- a/drivers/scsi/lpfc/lpfc_ct.c ++++ b/drivers/scsi/lpfc/lpfc_ct.c +@@ -2073,8 +2073,8 @@ lpfc_fdmi_hba_attr_wwnn(struct lpfc_vpor + struct lpfc_fdmi_attr_entry *ae; + uint32_t size; + +- ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue; +- memset(ae, 0, sizeof(struct lpfc_name)); ++ ae = &ad->AttrValue; ++ memset(ae, 0, sizeof(*ae)); + + memcpy(&ae->un.AttrWWN, &vport->fc_sparam.nodeName, + sizeof(struct lpfc_name)); +@@ -2090,8 +2090,8 @@ lpfc_fdmi_hba_attr_manufacturer(struct l + struct lpfc_fdmi_attr_entry *ae; + uint32_t len, size; + +- ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue; +- memset(ae, 0, 256); ++ ae = &ad->AttrValue; ++ memset(ae, 0, sizeof(*ae)); + + /* This string MUST be consistent with other FC platforms + * supported by Broadcom. +@@ -2115,8 +2115,8 @@ lpfc_fdmi_hba_attr_sn(struct lpfc_vport + struct lpfc_fdmi_attr_entry *ae; + uint32_t len, size; + +- ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue; +- memset(ae, 0, 256); ++ ae = &ad->AttrValue; ++ memset(ae, 0, sizeof(*ae)); + + strncpy(ae->un.AttrString, phba->SerialNumber, + sizeof(ae->un.AttrString)); +@@ -2137,8 +2137,8 @@ lpfc_fdmi_hba_attr_model(struct lpfc_vpo + struct lpfc_fdmi_attr_entry *ae; + uint32_t len, size; + +- ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue; +- memset(ae, 0, 256); ++ ae = &ad->AttrValue; ++ memset(ae, 0, sizeof(*ae)); + + strncpy(ae->un.AttrString, phba->ModelName, + sizeof(ae->un.AttrString)); +@@ -2158,8 +2158,8 @@ lpfc_fdmi_hba_attr_description(struct lp + struct lpfc_fdmi_attr_entry *ae; + uint32_t len, size; + +- ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue; +- memset(ae, 0, 256); ++ ae = &ad->AttrValue; ++ memset(ae, 0, sizeof(*ae)); + + strncpy(ae->un.AttrString, phba->ModelDesc, + sizeof(ae->un.AttrString)); +@@ -2181,8 +2181,8 @@ lpfc_fdmi_hba_attr_hdw_ver(struct lpfc_v + struct lpfc_fdmi_attr_entry *ae; + uint32_t i, j, incr, size; + +- ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue; +- memset(ae, 0, 256); ++ ae = &ad->AttrValue; ++ memset(ae, 0, sizeof(*ae)); + + /* Convert JEDEC ID to ascii for hardware version */ + incr = vp->rev.biuRev; +@@ -2211,8 +2211,8 @@ lpfc_fdmi_hba_attr_drvr_ver(struct lpfc_ + struct lpfc_fdmi_attr_entry *ae; + uint32_t len, size; + +- ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue; +- memset(ae, 0, 256); ++ ae = &ad->AttrValue; ++ memset(ae, 0, sizeof(*ae)); + + strncpy(ae->un.AttrString, lpfc_release_version, + sizeof(ae->un.AttrString)); +@@ -2233,8 +2233,8 @@ lpfc_fdmi_hba_attr_rom_ver(struct lpfc_v + struct lpfc_fdmi_attr_entry *ae; + uint32_t len, size; + +- ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue; +- memset(ae, 0, 256); ++ ae = &ad->AttrValue; ++ memset(ae, 0, sizeof(*ae)); + + if (phba->sli_rev == LPFC_SLI_REV4) + lpfc_decode_firmware_rev(phba, ae->un.AttrString, 1); +@@ -2258,8 +2258,8 @@ lpfc_fdmi_hba_attr_fmw_ver(struct lpfc_v + struct lpfc_fdmi_attr_entry *ae; + uint32_t len, size; + +- ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue; +- memset(ae, 0, 256); ++ ae = &ad->AttrValue; ++ memset(ae, 0, sizeof(*ae)); + + lpfc_decode_firmware_rev(phba, ae->un.AttrString, 1); + len = strnlen(ae->un.AttrString, +@@ -2278,8 +2278,8 @@ lpfc_fdmi_hba_attr_os_ver(struct lpfc_vp + struct lpfc_fdmi_attr_entry *ae; + uint32_t len, size; + +- ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue; +- memset(ae, 0, 256); ++ ae = &ad->AttrValue; ++ memset(ae, 0, sizeof(*ae)); + + snprintf(ae->un.AttrString, sizeof(ae->un.AttrString), "%s %s %s", + init_utsname()->sysname, +@@ -2301,7 +2301,7 @@ lpfc_fdmi_hba_attr_ct_len(struct lpfc_vp + struct lpfc_fdmi_attr_entry *ae; + uint32_t size; + +- ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue; ++ ae = &ad->AttrValue; + + ae->un.AttrInt = cpu_to_be32(LPFC_MAX_CT_SIZE); + size = FOURBYTES + sizeof(uint32_t); +@@ -2317,8 +2317,8 @@ lpfc_fdmi_hba_attr_symbolic_name(struct + struct lpfc_fdmi_attr_entry *ae; + uint32_t len, size; + +- ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue; +- memset(ae, 0, 256); ++ ae = &ad->AttrValue; ++ memset(ae, 0, sizeof(*ae)); + + len = lpfc_vport_symbolic_node_name(vport, + ae->un.AttrString, 256); +@@ -2336,7 +2336,7 @@ lpfc_fdmi_hba_attr_vendor_info(struct lp + struct lpfc_fdmi_attr_entry *ae; + uint32_t size; + +- ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue; ++ ae = &ad->AttrValue; + + /* Nothing is defined for this currently */ + ae->un.AttrInt = cpu_to_be32(0); +@@ -2353,7 +2353,7 @@ lpfc_fdmi_hba_attr_num_ports(struct lpfc + struct lpfc_fdmi_attr_entry *ae; + uint32_t size; + +- ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue; ++ ae = &ad->AttrValue; + + /* Each driver instance corresponds to a single port */ + ae->un.AttrInt = cpu_to_be32(1); +@@ -2370,8 +2370,8 @@ lpfc_fdmi_hba_attr_fabric_wwnn(struct lp + struct lpfc_fdmi_attr_entry *ae; + uint32_t size; + +- ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue; +- memset(ae, 0, sizeof(struct lpfc_name)); ++ ae = &ad->AttrValue; ++ memset(ae, 0, sizeof(*ae)); + + memcpy(&ae->un.AttrWWN, &vport->fabric_nodename, + sizeof(struct lpfc_name)); +@@ -2389,8 +2389,8 @@ lpfc_fdmi_hba_attr_bios_ver(struct lpfc_ + struct lpfc_fdmi_attr_entry *ae; + uint32_t len, size; + +- ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue; +- memset(ae, 0, 256); ++ ae = &ad->AttrValue; ++ memset(ae, 0, sizeof(*ae)); + + strlcat(ae->un.AttrString, phba->BIOSVersion, + sizeof(ae->un.AttrString)); +@@ -2410,7 +2410,7 @@ lpfc_fdmi_hba_attr_bios_state(struct lpf + struct lpfc_fdmi_attr_entry *ae; + uint32_t size; + +- ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue; ++ ae = &ad->AttrValue; + + /* Driver doesn't have access to this information */ + ae->un.AttrInt = cpu_to_be32(0); +@@ -2427,8 +2427,8 @@ lpfc_fdmi_hba_attr_vendor_id(struct lpfc + struct lpfc_fdmi_attr_entry *ae; + uint32_t len, size; + +- ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue; +- memset(ae, 0, 256); ++ ae = &ad->AttrValue; ++ memset(ae, 0, sizeof(*ae)); + + strncpy(ae->un.AttrString, "EMULEX", + sizeof(ae->un.AttrString)); +@@ -2450,8 +2450,8 @@ lpfc_fdmi_port_attr_fc4type(struct lpfc_ + struct lpfc_fdmi_attr_entry *ae; + uint32_t size; + +- ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue; +- memset(ae, 0, 32); ++ ae = &ad->AttrValue; ++ memset(ae, 0, sizeof(*ae)); + + ae->un.AttrTypes[2] = 0x01; /* Type 0x8 - FCP */ + ae->un.AttrTypes[7] = 0x01; /* Type 0x20 - CT */ +@@ -2475,7 +2475,7 @@ lpfc_fdmi_port_attr_support_speed(struct + struct lpfc_fdmi_attr_entry *ae; + uint32_t size; + +- ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue; ++ ae = &ad->AttrValue; + + ae->un.AttrInt = 0; + if (!(phba->hba_flag & HBA_FCOE_MODE)) { +@@ -2529,7 +2529,7 @@ lpfc_fdmi_port_attr_speed(struct lpfc_vp + struct lpfc_fdmi_attr_entry *ae; + uint32_t size; + +- ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue; ++ ae = &ad->AttrValue; + + if (!(phba->hba_flag & HBA_FCOE_MODE)) { + switch (phba->fc_linkspeed) { +@@ -2599,7 +2599,7 @@ lpfc_fdmi_port_attr_max_frame(struct lpf + struct lpfc_fdmi_attr_entry *ae; + uint32_t size; + +- ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue; ++ ae = &ad->AttrValue; + + hsp = (struct serv_parm *)&vport->fc_sparam; + ae->un.AttrInt = (((uint32_t) hsp->cmn.bbRcvSizeMsb & 0x0F) << 8) | +@@ -2619,8 +2619,8 @@ lpfc_fdmi_port_attr_os_devname(struct lp + struct lpfc_fdmi_attr_entry *ae; + uint32_t len, size; + +- ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue; +- memset(ae, 0, 256); ++ ae = &ad->AttrValue; ++ memset(ae, 0, sizeof(*ae)); + + snprintf(ae->un.AttrString, sizeof(ae->un.AttrString), + "/sys/class/scsi_host/host%d", shost->host_no); +@@ -2640,8 +2640,8 @@ lpfc_fdmi_port_attr_host_name(struct lpf + struct lpfc_fdmi_attr_entry *ae; + uint32_t len, size; + +- ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue; +- memset(ae, 0, 256); ++ ae = &ad->AttrValue; ++ memset(ae, 0, sizeof(*ae)); + + scnprintf(ae->un.AttrString, sizeof(ae->un.AttrString), "%s", + vport->phba->os_host_name); +@@ -2661,8 +2661,8 @@ lpfc_fdmi_port_attr_wwnn(struct lpfc_vpo + struct lpfc_fdmi_attr_entry *ae; + uint32_t size; + +- ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue; +- memset(ae, 0, sizeof(struct lpfc_name)); ++ ae = &ad->AttrValue; ++ memset(ae, 0, sizeof(*ae)); + + memcpy(&ae->un.AttrWWN, &vport->fc_sparam.nodeName, + sizeof(struct lpfc_name)); +@@ -2679,8 +2679,8 @@ lpfc_fdmi_port_attr_wwpn(struct lpfc_vpo + struct lpfc_fdmi_attr_entry *ae; + uint32_t size; + +- ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue; +- memset(ae, 0, sizeof(struct lpfc_name)); ++ ae = &ad->AttrValue; ++ memset(ae, 0, sizeof(*ae)); + + memcpy(&ae->un.AttrWWN, &vport->fc_sparam.portName, + sizeof(struct lpfc_name)); +@@ -2697,8 +2697,8 @@ lpfc_fdmi_port_attr_symbolic_name(struct + struct lpfc_fdmi_attr_entry *ae; + uint32_t len, size; + +- ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue; +- memset(ae, 0, 256); ++ ae = &ad->AttrValue; ++ memset(ae, 0, sizeof(*ae)); + + len = lpfc_vport_symbolic_port_name(vport, ae->un.AttrString, 256); + len += (len & 3) ? (4 - (len & 3)) : 4; +@@ -2716,7 +2716,7 @@ lpfc_fdmi_port_attr_port_type(struct lpf + struct lpfc_fdmi_attr_entry *ae; + uint32_t size; + +- ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue; ++ ae = &ad->AttrValue; + if (phba->fc_topology == LPFC_TOPOLOGY_LOOP) + ae->un.AttrInt = cpu_to_be32(LPFC_FDMI_PORTTYPE_NLPORT); + else +@@ -2734,7 +2734,7 @@ lpfc_fdmi_port_attr_class(struct lpfc_vp + struct lpfc_fdmi_attr_entry *ae; + uint32_t size; + +- ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue; ++ ae = &ad->AttrValue; + ae->un.AttrInt = cpu_to_be32(FC_COS_CLASS2 | FC_COS_CLASS3); + size = FOURBYTES + sizeof(uint32_t); + ad->AttrLen = cpu_to_be16(size); +@@ -2749,8 +2749,8 @@ lpfc_fdmi_port_attr_fabric_wwpn(struct l + struct lpfc_fdmi_attr_entry *ae; + uint32_t size; + +- ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue; +- memset(ae, 0, sizeof(struct lpfc_name)); ++ ae = &ad->AttrValue; ++ memset(ae, 0, sizeof(*ae)); + + memcpy(&ae->un.AttrWWN, &vport->fabric_portname, + sizeof(struct lpfc_name)); +@@ -2767,8 +2767,8 @@ lpfc_fdmi_port_attr_active_fc4type(struc + struct lpfc_fdmi_attr_entry *ae; + uint32_t size; + +- ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue; +- memset(ae, 0, 32); ++ ae = &ad->AttrValue; ++ memset(ae, 0, sizeof(*ae)); + + ae->un.AttrTypes[2] = 0x01; /* Type 0x8 - FCP */ + ae->un.AttrTypes[7] = 0x01; /* Type 0x20 - CT */ +@@ -2790,7 +2790,7 @@ lpfc_fdmi_port_attr_port_state(struct lp + struct lpfc_fdmi_attr_entry *ae; + uint32_t size; + +- ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue; ++ ae = &ad->AttrValue; + /* Link Up - operational */ + ae->un.AttrInt = cpu_to_be32(LPFC_FDMI_PORTSTATE_ONLINE); + size = FOURBYTES + sizeof(uint32_t); +@@ -2806,7 +2806,7 @@ lpfc_fdmi_port_attr_num_disc(struct lpfc + struct lpfc_fdmi_attr_entry *ae; + uint32_t size; + +- ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue; ++ ae = &ad->AttrValue; + vport->fdmi_num_disc = lpfc_find_map_node(vport); + ae->un.AttrInt = cpu_to_be32(vport->fdmi_num_disc); + size = FOURBYTES + sizeof(uint32_t); +@@ -2822,7 +2822,7 @@ lpfc_fdmi_port_attr_nportid(struct lpfc_ + struct lpfc_fdmi_attr_entry *ae; + uint32_t size; + +- ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue; ++ ae = &ad->AttrValue; + ae->un.AttrInt = cpu_to_be32(vport->fc_myDID); + size = FOURBYTES + sizeof(uint32_t); + ad->AttrLen = cpu_to_be16(size); +@@ -2837,8 +2837,8 @@ lpfc_fdmi_smart_attr_service(struct lpfc + struct lpfc_fdmi_attr_entry *ae; + uint32_t len, size; + +- ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue; +- memset(ae, 0, 256); ++ ae = &ad->AttrValue; ++ memset(ae, 0, sizeof(*ae)); + + strncpy(ae->un.AttrString, "Smart SAN Initiator", + sizeof(ae->un.AttrString)); +@@ -2858,8 +2858,8 @@ lpfc_fdmi_smart_attr_guid(struct lpfc_vp + struct lpfc_fdmi_attr_entry *ae; + uint32_t size; + +- ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue; +- memset(ae, 0, 256); ++ ae = &ad->AttrValue; ++ memset(ae, 0, sizeof(*ae)); + + memcpy(&ae->un.AttrString, &vport->fc_sparam.nodeName, + sizeof(struct lpfc_name)); +@@ -2879,8 +2879,8 @@ lpfc_fdmi_smart_attr_version(struct lpfc + struct lpfc_fdmi_attr_entry *ae; + uint32_t len, size; + +- ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue; +- memset(ae, 0, 256); ++ ae = &ad->AttrValue; ++ memset(ae, 0, sizeof(*ae)); + + strncpy(ae->un.AttrString, "Smart SAN Version 2.0", + sizeof(ae->un.AttrString)); +@@ -2901,8 +2901,8 @@ lpfc_fdmi_smart_attr_model(struct lpfc_v + struct lpfc_fdmi_attr_entry *ae; + uint32_t len, size; + +- ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue; +- memset(ae, 0, 256); ++ ae = &ad->AttrValue; ++ memset(ae, 0, sizeof(*ae)); + + strncpy(ae->un.AttrString, phba->ModelName, + sizeof(ae->un.AttrString)); +@@ -2921,7 +2921,7 @@ lpfc_fdmi_smart_attr_port_info(struct lp + struct lpfc_fdmi_attr_entry *ae; + uint32_t size; + +- ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue; ++ ae = &ad->AttrValue; + + /* SRIOV (type 3) is not supported */ + if (vport->vpi) +@@ -2941,7 +2941,7 @@ lpfc_fdmi_smart_attr_qos(struct lpfc_vpo + struct lpfc_fdmi_attr_entry *ae; + uint32_t size; + +- ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue; ++ ae = &ad->AttrValue; + ae->un.AttrInt = cpu_to_be32(0); + size = FOURBYTES + sizeof(uint32_t); + ad->AttrLen = cpu_to_be16(size); +@@ -2956,7 +2956,7 @@ lpfc_fdmi_smart_attr_security(struct lpf + struct lpfc_fdmi_attr_entry *ae; + uint32_t size; + +- ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue; ++ ae = &ad->AttrValue; + ae->un.AttrInt = cpu_to_be32(1); + size = FOURBYTES + sizeof(uint32_t); + ad->AttrLen = cpu_to_be16(size); +@@ -3104,7 +3104,8 @@ lpfc_fdmi_cmd(struct lpfc_vport *vport, + /* Registered Port List */ + /* One entry (port) per adapter */ + rh->rpl.EntryCnt = cpu_to_be32(1); +- memcpy(&rh->rpl.pe, &phba->pport->fc_sparam.portName, ++ memcpy(&rh->rpl.pe.PortName, ++ &phba->pport->fc_sparam.portName, + sizeof(struct lpfc_name)); + + /* point to the HBA attribute block */ +--- a/drivers/scsi/lpfc/lpfc_hw.h ++++ b/drivers/scsi/lpfc/lpfc_hw.h +@@ -1338,25 +1338,8 @@ struct fc_rdp_res_frame { + /* lpfc_sli_ct_request defines the CT_IU preamble for FDMI commands */ + #define SLI_CT_FDMI_Subtypes 0x10 /* Management Service Subtype */ + +-/* +- * Registered Port List Format +- */ +-struct lpfc_fdmi_reg_port_list { +- uint32_t EntryCnt; +- uint32_t pe; /* Variable-length array */ +-}; +- +- + /* Definitions for HBA / Port attribute entries */ + +-struct lpfc_fdmi_attr_def { /* Defined in TLV format */ +- /* Structure is in Big Endian format */ +- uint32_t AttrType:16; +- uint32_t AttrLen:16; +- uint32_t AttrValue; /* Marks start of Value (ATTRIBUTE_ENTRY) */ +-}; +- +- + /* Attribute Entry */ + struct lpfc_fdmi_attr_entry { + union { +@@ -1367,7 +1350,13 @@ struct lpfc_fdmi_attr_entry { + } un; + }; + +-#define LPFC_FDMI_MAX_AE_SIZE sizeof(struct lpfc_fdmi_attr_entry) ++struct lpfc_fdmi_attr_def { /* Defined in TLV format */ ++ /* Structure is in Big Endian format */ ++ uint32_t AttrType:16; ++ uint32_t AttrLen:16; ++ /* Marks start of Value (ATTRIBUTE_ENTRY) */ ++ struct lpfc_fdmi_attr_entry AttrValue; ++} __packed; + + /* + * HBA Attribute Block +@@ -1392,12 +1381,19 @@ struct lpfc_fdmi_hba_ident { + }; + + /* ++ * Registered Port List Format ++ */ ++struct lpfc_fdmi_reg_port_list { ++ uint32_t EntryCnt; ++ struct lpfc_fdmi_port_entry pe; ++} __packed; ++ ++/* + * Register HBA(RHBA) + */ + struct lpfc_fdmi_reg_hba { + struct lpfc_fdmi_hba_ident hi; +- struct lpfc_fdmi_reg_port_list rpl; /* variable-length array */ +-/* struct lpfc_fdmi_attr_block ab; */ ++ struct lpfc_fdmi_reg_port_list rpl; + }; + + /* diff --git a/patches.suse/scsi-lpfc-Fix-crash-after-handling-a-pci-error.patch b/patches.suse/scsi-lpfc-Fix-crash-after-handling-a-pci-error.patch new file mode 100644 index 0000000..6889be7 --- /dev/null +++ b/patches.suse/scsi-lpfc-Fix-crash-after-handling-a-pci-error.patch @@ -0,0 +1,40 @@ +From: James Smart +Date: Sun, 22 Mar 2020 11:12:57 -0700 +Subject: scsi: lpfc: Fix crash after handling a pci error +Patch-mainline: v5.7-rc1 +Git-commit: 4cd70891308dfb875ef31060c4a4aa8872630a2e +References: bsc#1164777 bsc#1164780 bsc#1165211 + +Injecting EEH on a 32GB card is causing kernel oops + +The pci error handler is doing an IO flush and the offline code is also +doing an IO flush. When the 1st flush is complete the hdwq is destroyed +(freed), yet the second flush accesses the hdwq and crashes. + +Added a check in lpfc_sli4_fush_io_rings to check both the HBA_IOQ_FLUSH +flag and the hdwq pointer to see if it is already set and not already +freed. + +Link: https://lore.kernel.org/r/20200322181304.37655-6-jsmart2021@gmail.com +Signed-off-by: James Smart +Signed-off-by: Dick Kennedy +Signed-off-by: Martin K. Petersen +Acked-by: Daniel Wagner +--- + drivers/scsi/lpfc/lpfc_sli.c | 5 +++++ + 1 file changed, 5 insertions(+) + +--- a/drivers/scsi/lpfc/lpfc_sli.c ++++ b/drivers/scsi/lpfc/lpfc_sli.c +@@ -4046,6 +4046,11 @@ lpfc_sli_flush_io_rings(struct lpfc_hba + struct lpfc_iocbq *piocb, *next_iocb; + + spin_lock_irq(&phba->hbalock); ++ if (phba->hba_flag & HBA_IOQ_FLUSH || ++ !phba->sli4_hba.hdwq) { ++ spin_unlock_irq(&phba->hbalock); ++ return; ++ } + /* Indicate the I/O queues are flushed */ + phba->hba_flag |= HBA_IOQ_FLUSH; + spin_unlock_irq(&phba->hbalock); diff --git a/patches.suse/scsi-lpfc-Fix-crash-in-target-side-cable-pulls-hitti.patch b/patches.suse/scsi-lpfc-Fix-crash-in-target-side-cable-pulls-hitti.patch new file mode 100644 index 0000000..5a601a4 --- /dev/null +++ b/patches.suse/scsi-lpfc-Fix-crash-in-target-side-cable-pulls-hitti.patch @@ -0,0 +1,69 @@ +From: James Smart +Date: Sun, 22 Mar 2020 11:12:59 -0700 +Subject: scsi: lpfc: Fix crash in target side cable pulls hitting + WAIT_FOR_UNREG +Patch-mainline: v5.7-rc1 +Git-commit: 807e7353d8a7105ce884d22b0dbc034993c6679c +References: bsc#1164777 bsc#1164780 bsc#1165211 + +Kernel is crashing with the following stacktrace: + + BUG: unable to handle kernel NULL pointer dereference at + 00000000000005bc + IP: lpfc_nvme_register_port+0x1a8/0x3a0 [lpfc] + ... + Call Trace: + lpfc_nlp_state_cleanup+0x2b2/0x500 [lpfc] + lpfc_nlp_set_state+0xd7/0x1a0 [lpfc] + lpfc_cmpl_prli_prli_issue+0x1f7/0x450 [lpfc] + lpfc_disc_state_machine+0x7a/0x1e0 [lpfc] + lpfc_cmpl_els_prli+0x16f/0x1e0 [lpfc] + lpfc_sli_sp_handle_rspiocb+0x5b2/0x690 [lpfc] + lpfc_sli_handle_slow_ring_event_s4+0x182/0x230 [lpfc] + lpfc_do_work+0x87f/0x1570 [lpfc] + kthread+0x10d/0x130 + ret_from_fork+0x35/0x40 + +During target side fault injections, it is possible to hit the +NLP_WAIT_FOR_UNREG case in lpfc_nvme_remoteport_delete. A prior commit +fixed a rebind and delete race condition, but called lpfc_nlp_put +unconditionally. This triggered a deletion and the crash. + +Fix by movng nlp_put to inside the NLP_WAIT_FOR_UNREG case, where the nlp +will be being unregistered/removed. Leave the reference if the flag isn't +set. + +Link: https://lore.kernel.org/r/20200322181304.37655-8-jsmart2021@gmail.com +Fixes: b15bd3e6212e ("scsi: lpfc: Fix nvme remoteport registration race conditions") +Signed-off-by: James Smart +Signed-off-by: Dick Kennedy +Signed-off-by: Martin K. Petersen +Acked-by: Daniel Wagner +--- + drivers/scsi/lpfc/lpfc_nvme.c | 14 ++++++++------ + 1 file changed, 8 insertions(+), 6 deletions(-) + +--- a/drivers/scsi/lpfc/lpfc_nvme.c ++++ b/drivers/scsi/lpfc/lpfc_nvme.c +@@ -382,13 +382,15 @@ lpfc_nvme_remoteport_delete(struct nvme_ + if (ndlp->upcall_flags & NLP_WAIT_FOR_UNREG) { + ndlp->nrport = NULL; + ndlp->upcall_flags &= ~NLP_WAIT_FOR_UNREG; +- } +- spin_unlock_irq(&vport->phba->hbalock); ++ spin_unlock_irq(&vport->phba->hbalock); + +- /* Remove original register reference. The host transport +- * won't reference this rport/remoteport any further. +- */ +- lpfc_nlp_put(ndlp); ++ /* Remove original register reference. The host transport ++ * won't reference this rport/remoteport any further. ++ */ ++ lpfc_nlp_put(ndlp); ++ } else { ++ spin_unlock_irq(&vport->phba->hbalock); ++ } + + rport_err: + return; diff --git a/patches.suse/scsi-lpfc-Fix-disablement-of-FC-AL-on-lpe35000-model.patch b/patches.suse/scsi-lpfc-Fix-disablement-of-FC-AL-on-lpe35000-model.patch new file mode 100644 index 0000000..fabcbe7 --- /dev/null +++ b/patches.suse/scsi-lpfc-Fix-disablement-of-FC-AL-on-lpe35000-model.patch @@ -0,0 +1,63 @@ +From: James Smart +Date: Wed, 18 Dec 2019 15:58:04 -0800 +Subject: scsi: lpfc: Fix disablement of FC-AL on lpe35000 models +Patch-mainline: v5.6-rc1 +Git-commit: a052ce848d4358c0094efc2c8f9aec0a31358e42 +References: bsc#1164777 bsc#1164780 bsc#1165211 + +The order of the flags/checks for adapters where FC-AL is supported +erroneously excluded lpe35000 adapter models. Also noted that the G7 flags +for Loop and Persistent topology are incorrect. They should follow the +rules as G6. + +Rework the logic to enable LPe35000 FC-AL support. Collapse G7 support +logic to the same rules as G6. + +Link: https://lore.kernel.org/r/20191218235808.31922-7-jsmart2021@gmail.com +Signed-off-by: Dick Kennedy +Signed-off-by: James Smart +Signed-off-by: Martin K. Petersen +Acked-by: Daniel Wagner +--- + drivers/scsi/lpfc/lpfc_attr.c | 9 ++++----- + drivers/scsi/lpfc/lpfc_init.c | 8 -------- + 2 files changed, 4 insertions(+), 13 deletions(-) + +--- a/drivers/scsi/lpfc/lpfc_attr.c ++++ b/drivers/scsi/lpfc/lpfc_attr.c +@@ -4130,14 +4130,13 @@ lpfc_topology_store(struct device *dev, + /* + * The 'topology' is not a configurable parameter if : + * - persistent topology enabled +- * - G7 adapters +- * - G6 with no private loop support ++ * - G7/G6 with no private loop support + */ + +- if (((phba->hba_flag & HBA_PERSISTENT_TOPO) || ++ if ((phba->hba_flag & HBA_PERSISTENT_TOPO || + (!phba->sli4_hba.pc_sli4_params.pls && +- phba->pcidev->device == PCI_DEVICE_ID_LANCER_G6_FC) || +- phba->pcidev->device == PCI_DEVICE_ID_LANCER_G7_FC) && ++ (phba->pcidev->device == PCI_DEVICE_ID_LANCER_G6_FC || ++ phba->pcidev->device == PCI_DEVICE_ID_LANCER_G7_FC))) && + val == 4) { + lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT, + "3114 Loop mode not supported\n"); +--- a/drivers/scsi/lpfc/lpfc_init.c ++++ b/drivers/scsi/lpfc/lpfc_init.c +@@ -8320,14 +8320,6 @@ lpfc_map_topology(struct lpfc_hba *phba, + phba->hba_flag |= HBA_PERSISTENT_TOPO; + switch (phba->pcidev->device) { + case PCI_DEVICE_ID_LANCER_G7_FC: +- if (tf || (pt == LINK_FLAGS_LOOP)) { +- /* Invalid values from FW - use driver params */ +- phba->hba_flag &= ~HBA_PERSISTENT_TOPO; +- } else { +- /* Prism only supports PT2PT topology */ +- phba->cfg_topology = FLAGS_TOPOLOGY_MODE_PT_PT; +- } +- break; + case PCI_DEVICE_ID_LANCER_G6_FC: + if (!tf) { + phba->cfg_topology = ((pt == LINK_FLAGS_LOOP) diff --git a/patches.suse/scsi-lpfc-Fix-driver-nvme-rescan-logging.patch b/patches.suse/scsi-lpfc-Fix-driver-nvme-rescan-logging.patch new file mode 100644 index 0000000..991886a --- /dev/null +++ b/patches.suse/scsi-lpfc-Fix-driver-nvme-rescan-logging.patch @@ -0,0 +1,114 @@ +From: James Smart +Date: Wed, 14 Aug 2019 16:56:50 -0700 +Subject: scsi: lpfc: Fix driver nvme rescan logging +Patch-mainline: v5.4-rc1 +Git-commit: a6d10f24a04d658078582fc0a89b20f050c0ae68 +References: bsc#1164777 bsc#1164780 bsc#1165211 + +In situations where zoning is not being used, thus NVMe initiators see +other NVMe initiators as well as NVMe targets, a link bounce on an +initiator will cause the NVMe initiators to spew "6169" State Error +messages. + +The driver is not qualifying whether the remote port is a NVMe targer or +not before calling the lpfc_nvme_rescan_port(), which validates the role +and prints the message if its only an NVMe initiator. + +Fix by the following: + + - Before calling lpfc_nvme_rescan_port() ensure that the node is a NVMe + storage target or a NVMe discovery controller. + + - Clean up implementation of lpfc_nvme_rescan_port. remoteport pointer + will always be NULL if a NVMe initiator only. But, grabbing of + remoteport pointer should be done under lock to coincide with the + registering of the remote port with the fc transport. + +Signed-off-by: Dick Kennedy +Signed-off-by: James Smart +Signed-off-by: Martin K. Petersen +Acked-by: Daniel Wagner +--- + drivers/scsi/lpfc/lpfc_els.c | 12 ++++++++++-- + drivers/scsi/lpfc/lpfc_nvme.c | 31 +++++++++++++++++-------------- + 2 files changed, 27 insertions(+), 16 deletions(-) + +--- a/drivers/scsi/lpfc/lpfc_els.c ++++ b/drivers/scsi/lpfc/lpfc_els.c +@@ -6360,7 +6360,11 @@ lpfc_rscn_recovery_check(struct lpfc_vpo + continue; + } + +- if (ndlp->nlp_fc4_type & NLP_FC4_NVME) ++ /* Check to see if we need to NVME rescan this target ++ * remoteport. ++ */ ++ if (ndlp->nlp_fc4_type & NLP_FC4_NVME && ++ ndlp->nlp_type & (NLP_NVME_TARGET | NLP_NVME_DISCOVERY)) + lpfc_nvme_rescan_port(vport, ndlp); + + lpfc_disc_state_machine(vport, ndlp, NULL, +@@ -6474,7 +6478,11 @@ lpfc_els_rcv_rscn(struct lpfc_vport *vpo + *lp, vport->fc_flag, payload_len); + lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL); + +- if (ndlp->nlp_fc4_type & NLP_FC4_NVME) ++ /* Check to see if we need to NVME rescan this target ++ * remoteport. ++ */ ++ if (ndlp->nlp_fc4_type & NLP_FC4_NVME && ++ ndlp->nlp_type & (NLP_NVME_TARGET | NLP_NVME_DISCOVERY)) + lpfc_nvme_rescan_port(vport, ndlp); + return 0; + } +--- a/drivers/scsi/lpfc/lpfc_nvme.c ++++ b/drivers/scsi/lpfc/lpfc_nvme.c +@@ -2426,20 +2426,23 @@ void + lpfc_nvme_rescan_port(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) + { + #if (IS_ENABLED(CONFIG_NVME_FC)) +- struct lpfc_nvme_rport *rport; +- struct nvme_fc_remote_port *remoteport; ++ struct lpfc_nvme_rport *nrport; ++ struct nvme_fc_remote_port *remoteport = NULL; + +- rport = ndlp->nrport; ++ spin_lock_irq(&vport->phba->hbalock); ++ nrport = lpfc_ndlp_get_nrport(ndlp); ++ if (nrport) ++ remoteport = nrport->remoteport; ++ spin_unlock_irq(&vport->phba->hbalock); + + lpfc_printf_vlog(vport, KERN_INFO, LOG_NVME_DISC, + "6170 Rescan NPort DID x%06x type x%x " +- "state x%x rport %p\n", +- ndlp->nlp_DID, ndlp->nlp_type, ndlp->nlp_state, rport); +- if (!rport) +- goto input_err; +- remoteport = rport->remoteport; +- if (!remoteport) +- goto input_err; ++ "state x%x nrport x%px remoteport x%px\n", ++ ndlp->nlp_DID, ndlp->nlp_type, ndlp->nlp_state, ++ nrport, remoteport); ++ ++ if (!nrport || !remoteport) ++ goto rescan_exit; + + /* Only rescan if we are an NVME target in the MAPPED state */ + if (remoteport->port_role & FC_PORT_ROLE_NVME_DISCOVERY && +@@ -2452,10 +2455,10 @@ lpfc_nvme_rescan_port(struct lpfc_vport + ndlp->nlp_DID, remoteport->port_state); + } + return; +-input_err: +- lpfc_printf_vlog(vport, KERN_ERR, LOG_NVME_DISC, +- "6169 State error: lport %p, rport%p FCID x%06x\n", +- vport->localport, ndlp->rport, ndlp->nlp_DID); ++ rescan_exit: ++ lpfc_printf_vlog(vport, KERN_INFO, LOG_NVME_DISC, ++ "6169 Skip NVME Rport Rescan, NVME remoteport " ++ "unregistered\n"); + #endif + } + diff --git a/patches.suse/scsi-lpfc-Fix-erroneous-cpu-limit-of-128-on-I-O-stat.patch b/patches.suse/scsi-lpfc-Fix-erroneous-cpu-limit-of-128-on-I-O-stat.patch new file mode 100644 index 0000000..49a8789 --- /dev/null +++ b/patches.suse/scsi-lpfc-Fix-erroneous-cpu-limit-of-128-on-I-O-stat.patch @@ -0,0 +1,746 @@ +From 840eda9602d30342486e85e7e96499f565572e4b Mon Sep 17 00:00:00 2001 +From: James Smart +Date: Sun, 22 Mar 2020 11:13:00 -0700 +Subject: [PATCH] scsi: lpfc: Fix erroneous cpu limit of 128 on I/O statistics + +References: bsc#1164777 bsc#1164780 bsc#1165211 +Patch-mainline: v5.7-rc1 +Git-commit: 840eda9602d30342486e85e7e96499f565572e4b + +The cpu io statistics were capped by a hard define limit of 128. This +effectively was a max number of CPUs, not an actual CPU count, nor actual +CPU numbers which can be even larger than both of those values. This made +stats off/misleading and on large CPU count systems, wrong. + +Fix the stats so that all CPUs can have a stats struct. Fix the looping +such that it loops by hdwq, finds CPUs that used the hdwq, and sum the +stats, then display. + +Link: https://lore.kernel.org/r/20200322181304.37655-9-jsmart2021@gmail.com +Signed-off-by: James Smart +Signed-off-by: Dick Kennedy +Signed-off-by: Martin K. Petersen +Acked-by: Daniel Wagner +--- + drivers/scsi/lpfc/lpfc.h | 9 +- + drivers/scsi/lpfc/lpfc_debugfs.c | 204 ++++++++++++++++++------------- + drivers/scsi/lpfc/lpfc_debugfs.h | 1 - + drivers/scsi/lpfc/lpfc_init.c | 28 +++++ + drivers/scsi/lpfc/lpfc_nvme.c | 45 ++++--- + drivers/scsi/lpfc/lpfc_nvmet.c | 55 ++++----- + drivers/scsi/lpfc/lpfc_scsi.c | 23 +--- + drivers/scsi/lpfc/lpfc_sli4.h | 19 +-- + 8 files changed, 215 insertions(+), 169 deletions(-) + +diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h +index e940a49f9f02..e4924b9fa69c 100644 +--- a/drivers/scsi/lpfc/lpfc.h ++++ b/drivers/scsi/lpfc/lpfc.h +@@ -481,7 +481,7 @@ struct lpfc_vport { + struct dentry *debug_nvmestat; + struct dentry *debug_scsistat; + struct dentry *debug_nvmektime; +- struct dentry *debug_cpucheck; ++ struct dentry *debug_hdwqstat; + struct dentry *vport_debugfs_root; + struct lpfc_debugfs_trc *disc_trc; + atomic_t disc_trc_cnt; +@@ -1175,12 +1175,11 @@ struct lpfc_hba { + uint16_t sfp_warning; + + #ifdef CONFIG_SCSI_LPFC_DEBUG_FS +- uint16_t cpucheck_on; ++ uint16_t hdwqstat_on; + #define LPFC_CHECK_OFF 0 + #define LPFC_CHECK_NVME_IO 1 +-#define LPFC_CHECK_NVMET_RCV 2 +-#define LPFC_CHECK_NVMET_IO 4 +-#define LPFC_CHECK_SCSI_IO 8 ++#define LPFC_CHECK_NVMET_IO 2 ++#define LPFC_CHECK_SCSI_IO 4 + uint16_t ktime_on; + uint64_t ktime_data_samples; + uint64_t ktime_status_samples; +diff --git a/drivers/scsi/lpfc/lpfc_debugfs.c b/drivers/scsi/lpfc/lpfc_debugfs.c +index 819335b16c2e..1b8be1006cbe 100644 +--- a/drivers/scsi/lpfc/lpfc_debugfs.c ++++ b/drivers/scsi/lpfc/lpfc_debugfs.c +@@ -1603,42 +1603,50 @@ lpfc_debugfs_nvmeio_trc_data(struct lpfc_hba *phba, char *buf, int size) + } + + /** +- * lpfc_debugfs_cpucheck_data - Dump target node list to a buffer ++ * lpfc_debugfs_hdwqstat_data - Dump I/O stats to a buffer + * @vport: The vport to gather target node info from. + * @buf: The buffer to dump log into. + * @size: The maximum amount of data to process. + * + * Description: +- * This routine dumps the NVME statistics associated with @vport ++ * This routine dumps the NVME + SCSI statistics associated with @vport + * + * Return Value: + * This routine returns the amount of bytes that were dumped into @buf and will + * not exceed @size. + **/ + static int +-lpfc_debugfs_cpucheck_data(struct lpfc_vport *vport, char *buf, int size) ++lpfc_debugfs_hdwqstat_data(struct lpfc_vport *vport, char *buf, int size) + { + struct lpfc_hba *phba = vport->phba; + struct lpfc_sli4_hdw_queue *qp; +- int i, j, max_cnt; +- int len = 0; ++ struct lpfc_hdwq_stat *c_stat; ++ int i, j, len; + uint32_t tot_xmt; + uint32_t tot_rcv; + uint32_t tot_cmpl; ++ char tmp[LPFC_MAX_SCSI_INFO_TMP_LEN] = {0}; + +- len += scnprintf(buf + len, PAGE_SIZE - len, +- "CPUcheck %s ", +- (phba->cpucheck_on & LPFC_CHECK_NVME_IO ? +- "Enabled" : "Disabled")); +- if (phba->nvmet_support) { +- len += scnprintf(buf + len, PAGE_SIZE - len, +- "%s\n", +- (phba->cpucheck_on & LPFC_CHECK_NVMET_RCV ? +- "Rcv Enabled\n" : "Rcv Disabled\n")); +- } else { +- len += scnprintf(buf + len, PAGE_SIZE - len, "\n"); +- } +- max_cnt = size - LPFC_DEBUG_OUT_LINE_SZ; ++ scnprintf(tmp, sizeof(tmp), "HDWQ Stats:\n\n"); ++ if (strlcat(buf, tmp, size) >= size) ++ goto buffer_done; ++ ++ scnprintf(tmp, sizeof(tmp), "(NVME Accounting: %s) ", ++ (phba->hdwqstat_on & ++ (LPFC_CHECK_NVME_IO | LPFC_CHECK_NVMET_IO) ? ++ "Enabled" : "Disabled")); ++ if (strlcat(buf, tmp, size) >= size) ++ goto buffer_done; ++ ++ scnprintf(tmp, sizeof(tmp), "(SCSI Accounting: %s) ", ++ (phba->hdwqstat_on & LPFC_CHECK_SCSI_IO ? ++ "Enabled" : "Disabled")); ++ if (strlcat(buf, tmp, size) >= size) ++ goto buffer_done; ++ ++ scnprintf(tmp, sizeof(tmp), "\n\n"); ++ if (strlcat(buf, tmp, size) >= size) ++ goto buffer_done; + + for (i = 0; i < phba->cfg_hdw_queue; i++) { + qp = &phba->sli4_hba.hdwq[i]; +@@ -1646,46 +1654,76 @@ lpfc_debugfs_cpucheck_data(struct lpfc_vport *vport, char *buf, int size) + tot_rcv = 0; + tot_xmt = 0; + tot_cmpl = 0; +- for (j = 0; j < LPFC_CHECK_CPU_CNT; j++) { +- tot_xmt += qp->cpucheck_xmt_io[j]; +- tot_cmpl += qp->cpucheck_cmpl_io[j]; +- if (phba->nvmet_support) +- tot_rcv += qp->cpucheck_rcv_io[j]; +- } + +- /* Only display Hardware Qs with something */ +- if (!tot_xmt && !tot_cmpl && !tot_rcv) +- continue; ++ for_each_present_cpu(j) { ++ c_stat = per_cpu_ptr(phba->sli4_hba.c_stat, j); ++ ++ /* Only display for this HDWQ */ ++ if (i != c_stat->hdwq_no) ++ continue; + +- len += scnprintf(buf + len, PAGE_SIZE - len, +- "HDWQ %03d: ", i); +- for (j = 0; j < LPFC_CHECK_CPU_CNT; j++) { + /* Only display non-zero counters */ +- if (!qp->cpucheck_xmt_io[j] && +- !qp->cpucheck_cmpl_io[j] && +- !qp->cpucheck_rcv_io[j]) ++ if (!c_stat->xmt_io && !c_stat->cmpl_io && ++ !c_stat->rcv_io) + continue; ++ ++ if (!tot_xmt && !tot_cmpl && !tot_rcv) { ++ /* Print HDWQ string only the first time */ ++ scnprintf(tmp, sizeof(tmp), "[HDWQ %d]:\t", i); ++ if (strlcat(buf, tmp, size) >= size) ++ goto buffer_done; ++ } ++ ++ tot_xmt += c_stat->xmt_io; ++ tot_cmpl += c_stat->cmpl_io; ++ if (phba->nvmet_support) ++ tot_rcv += c_stat->rcv_io; ++ ++ scnprintf(tmp, sizeof(tmp), "| [CPU %d]: ", j); ++ if (strlcat(buf, tmp, size) >= size) ++ goto buffer_done; ++ + if (phba->nvmet_support) { +- len += scnprintf(buf + len, PAGE_SIZE - len, +- "CPU %03d: %x/%x/%x ", j, +- qp->cpucheck_rcv_io[j], +- qp->cpucheck_xmt_io[j], +- qp->cpucheck_cmpl_io[j]); ++ scnprintf(tmp, sizeof(tmp), ++ "XMT 0x%x CMPL 0x%x RCV 0x%x |", ++ c_stat->xmt_io, c_stat->cmpl_io, ++ c_stat->rcv_io); ++ if (strlcat(buf, tmp, size) >= size) ++ goto buffer_done; + } else { +- len += scnprintf(buf + len, PAGE_SIZE - len, +- "CPU %03d: %x/%x ", j, +- qp->cpucheck_xmt_io[j], +- qp->cpucheck_cmpl_io[j]); ++ scnprintf(tmp, sizeof(tmp), ++ "XMT 0x%x CMPL 0x%x |", ++ c_stat->xmt_io, c_stat->cmpl_io); ++ if (strlcat(buf, tmp, size) >= size) ++ goto buffer_done; + } + } +- len += scnprintf(buf + len, PAGE_SIZE - len, +- "Total: %x\n", tot_xmt); +- if (len >= max_cnt) { +- len += scnprintf(buf + len, PAGE_SIZE - len, +- "Truncated ...\n"); +- return len; ++ ++ /* Check if nothing to display */ ++ if (!tot_xmt && !tot_cmpl && !tot_rcv) ++ continue; ++ ++ scnprintf(tmp, sizeof(tmp), "\t->\t[HDWQ Total: "); ++ if (strlcat(buf, tmp, size) >= size) ++ goto buffer_done; ++ ++ if (phba->nvmet_support) { ++ scnprintf(tmp, sizeof(tmp), ++ "XMT 0x%x CMPL 0x%x RCV 0x%x]\n\n", ++ tot_xmt, tot_cmpl, tot_rcv); ++ if (strlcat(buf, tmp, size) >= size) ++ goto buffer_done; ++ } else { ++ scnprintf(tmp, sizeof(tmp), ++ "XMT 0x%x CMPL 0x%x]\n\n", ++ tot_xmt, tot_cmpl); ++ if (strlcat(buf, tmp, size) >= size) ++ goto buffer_done; + } + } ++ ++buffer_done: ++ len = strnlen(buf, size); + return len; + } + +@@ -2921,7 +2959,7 @@ lpfc_debugfs_nvmeio_trc_write(struct file *file, const char __user *buf, + } + + static int +-lpfc_debugfs_cpucheck_open(struct inode *inode, struct file *file) ++lpfc_debugfs_hdwqstat_open(struct inode *inode, struct file *file) + { + struct lpfc_vport *vport = inode->i_private; + struct lpfc_debug *debug; +@@ -2932,14 +2970,14 @@ lpfc_debugfs_cpucheck_open(struct inode *inode, struct file *file) + goto out; + + /* Round to page boundary */ +- debug->buffer = kmalloc(LPFC_CPUCHECK_SIZE, GFP_KERNEL); ++ debug->buffer = kcalloc(1, LPFC_SCSISTAT_SIZE, GFP_KERNEL); + if (!debug->buffer) { + kfree(debug); + goto out; + } + +- debug->len = lpfc_debugfs_cpucheck_data(vport, debug->buffer, +- LPFC_CPUCHECK_SIZE); ++ debug->len = lpfc_debugfs_hdwqstat_data(vport, debug->buffer, ++ LPFC_SCSISTAT_SIZE); + + debug->i_private = inode->i_private; + file->private_data = debug; +@@ -2950,16 +2988,16 @@ lpfc_debugfs_cpucheck_open(struct inode *inode, struct file *file) + } + + static ssize_t +-lpfc_debugfs_cpucheck_write(struct file *file, const char __user *buf, ++lpfc_debugfs_hdwqstat_write(struct file *file, const char __user *buf, + size_t nbytes, loff_t *ppos) + { + struct lpfc_debug *debug = file->private_data; + struct lpfc_vport *vport = (struct lpfc_vport *)debug->i_private; + struct lpfc_hba *phba = vport->phba; +- struct lpfc_sli4_hdw_queue *qp; ++ struct lpfc_hdwq_stat *c_stat; + char mybuf[64]; + char *pbuf; +- int i, j; ++ int i; + + if (nbytes > 64) + nbytes = 64; +@@ -2972,41 +3010,39 @@ lpfc_debugfs_cpucheck_write(struct file *file, const char __user *buf, + + if ((strncmp(pbuf, "on", sizeof("on") - 1) == 0)) { + if (phba->nvmet_support) +- phba->cpucheck_on |= LPFC_CHECK_NVMET_IO; ++ phba->hdwqstat_on |= LPFC_CHECK_NVMET_IO; + else +- phba->cpucheck_on |= (LPFC_CHECK_NVME_IO | ++ phba->hdwqstat_on |= (LPFC_CHECK_NVME_IO | + LPFC_CHECK_SCSI_IO); + return strlen(pbuf); + } else if ((strncmp(pbuf, "nvme_on", sizeof("nvme_on") - 1) == 0)) { + if (phba->nvmet_support) +- phba->cpucheck_on |= LPFC_CHECK_NVMET_IO; ++ phba->hdwqstat_on |= LPFC_CHECK_NVMET_IO; + else +- phba->cpucheck_on |= LPFC_CHECK_NVME_IO; ++ phba->hdwqstat_on |= LPFC_CHECK_NVME_IO; + return strlen(pbuf); + } else if ((strncmp(pbuf, "scsi_on", sizeof("scsi_on") - 1) == 0)) { +- phba->cpucheck_on |= LPFC_CHECK_SCSI_IO; ++ if (!phba->nvmet_support) ++ phba->hdwqstat_on |= LPFC_CHECK_SCSI_IO; + return strlen(pbuf); +- } else if ((strncmp(pbuf, "rcv", +- sizeof("rcv") - 1) == 0)) { +- if (phba->nvmet_support) +- phba->cpucheck_on |= LPFC_CHECK_NVMET_RCV; +- else +- return -EINVAL; ++ } else if ((strncmp(pbuf, "nvme_off", sizeof("nvme_off") - 1) == 0)) { ++ phba->hdwqstat_on &= ~(LPFC_CHECK_NVME_IO | ++ LPFC_CHECK_NVMET_IO); ++ return strlen(pbuf); ++ } else if ((strncmp(pbuf, "scsi_off", sizeof("scsi_off") - 1) == 0)) { ++ phba->hdwqstat_on &= ~LPFC_CHECK_SCSI_IO; + return strlen(pbuf); + } else if ((strncmp(pbuf, "off", + sizeof("off") - 1) == 0)) { +- phba->cpucheck_on = LPFC_CHECK_OFF; ++ phba->hdwqstat_on = LPFC_CHECK_OFF; + return strlen(pbuf); + } else if ((strncmp(pbuf, "zero", + sizeof("zero") - 1) == 0)) { +- for (i = 0; i < phba->cfg_hdw_queue; i++) { +- qp = &phba->sli4_hba.hdwq[i]; +- +- for (j = 0; j < LPFC_CHECK_CPU_CNT; j++) { +- qp->cpucheck_rcv_io[j] = 0; +- qp->cpucheck_xmt_io[j] = 0; +- qp->cpucheck_cmpl_io[j] = 0; +- } ++ for_each_present_cpu(i) { ++ c_stat = per_cpu_ptr(phba->sli4_hba.c_stat, i); ++ c_stat->xmt_io = 0; ++ c_stat->cmpl_io = 0; ++ c_stat->rcv_io = 0; + } + return strlen(pbuf); + } +@@ -5451,13 +5487,13 @@ static const struct file_operations lpfc_debugfs_op_nvmeio_trc = { + .release = lpfc_debugfs_release, + }; + +-#undef lpfc_debugfs_op_cpucheck +-static const struct file_operations lpfc_debugfs_op_cpucheck = { ++#undef lpfc_debugfs_op_hdwqstat ++static const struct file_operations lpfc_debugfs_op_hdwqstat = { + .owner = THIS_MODULE, +- .open = lpfc_debugfs_cpucheck_open, ++ .open = lpfc_debugfs_hdwqstat_open, + .llseek = lpfc_debugfs_lseek, + .read = lpfc_debugfs_read, +- .write = lpfc_debugfs_cpucheck_write, ++ .write = lpfc_debugfs_hdwqstat_write, + .release = lpfc_debugfs_release, + }; + +@@ -6081,11 +6117,11 @@ lpfc_debugfs_initialize(struct lpfc_vport *vport) + vport->vport_debugfs_root, + vport, &lpfc_debugfs_op_nvmektime); + +- snprintf(name, sizeof(name), "cpucheck"); +- vport->debug_cpucheck = ++ snprintf(name, sizeof(name), "hdwqstat"); ++ vport->debug_hdwqstat = + debugfs_create_file(name, 0644, + vport->vport_debugfs_root, +- vport, &lpfc_debugfs_op_cpucheck); ++ vport, &lpfc_debugfs_op_hdwqstat); + + /* + * The following section is for additional directories/files for the +@@ -6219,8 +6255,8 @@ lpfc_debugfs_terminate(struct lpfc_vport *vport) + debugfs_remove(vport->debug_nvmektime); /* nvmektime */ + vport->debug_nvmektime = NULL; + +- debugfs_remove(vport->debug_cpucheck); /* cpucheck */ +- vport->debug_cpucheck = NULL; ++ debugfs_remove(vport->debug_hdwqstat); /* hdwqstat */ ++ vport->debug_hdwqstat = NULL; + + if (vport->vport_debugfs_root) { + debugfs_remove(vport->vport_debugfs_root); /* vportX */ +diff --git a/drivers/scsi/lpfc/lpfc_debugfs.h b/drivers/scsi/lpfc/lpfc_debugfs.h +index 20f2537af511..6643b9bfd4f3 100644 +--- a/drivers/scsi/lpfc/lpfc_debugfs.h ++++ b/drivers/scsi/lpfc/lpfc_debugfs.h +@@ -47,7 +47,6 @@ + /* nvmestat output buffer size */ + #define LPFC_NVMESTAT_SIZE 8192 + #define LPFC_NVMEKTIME_SIZE 8192 +-#define LPFC_CPUCHECK_SIZE 8192 + #define LPFC_NVMEIO_TRC_SIZE 8192 + + /* scsistat output buffer size */ +diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c +index 1dadf247a0aa..4104bdcdbb6f 100644 +--- a/drivers/scsi/lpfc/lpfc_init.c ++++ b/drivers/scsi/lpfc/lpfc_init.c +@@ -6951,6 +6951,17 @@ lpfc_sli4_driver_resource_setup(struct lpfc_hba *phba) + rc = -ENOMEM; + goto out_free_hba_cpu_map; + } ++ ++#ifdef CONFIG_SCSI_LPFC_DEBUG_FS ++ phba->sli4_hba.c_stat = alloc_percpu(struct lpfc_hdwq_stat); ++ if (!phba->sli4_hba.c_stat) { ++ lpfc_printf_log(phba, KERN_ERR, LOG_INIT, ++ "3332 Failed allocating per cpu hdwq stats\n"); ++ rc = -ENOMEM; ++ goto out_free_hba_eq_info; ++ } ++#endif ++ + /* + * Enable sr-iov virtual functions if supported and configured + * through the module parameter. +@@ -6970,6 +6981,10 @@ lpfc_sli4_driver_resource_setup(struct lpfc_hba *phba) + + return 0; + ++#ifdef CONFIG_SCSI_LPFC_DEBUG_FS ++out_free_hba_eq_info: ++ free_percpu(phba->sli4_hba.eq_info); ++#endif + out_free_hba_cpu_map: + kfree(phba->sli4_hba.cpu_map); + out_free_hba_eq_hdl: +@@ -7008,6 +7023,9 @@ lpfc_sli4_driver_resource_unset(struct lpfc_hba *phba) + struct lpfc_fcf_conn_entry *conn_entry, *next_conn_entry; + + free_percpu(phba->sli4_hba.eq_info); ++#ifdef CONFIG_SCSI_LPFC_DEBUG_FS ++ free_percpu(phba->sli4_hba.c_stat); ++#endif + + /* Free memory allocated for msi-x interrupt vector to CPU mapping */ + kfree(phba->sli4_hba.cpu_map); +@@ -10848,6 +10866,9 @@ lpfc_cpu_affinity_check(struct lpfc_hba *phba, int vectors) + #ifdef CONFIG_X86 + struct cpuinfo_x86 *cpuinfo; + #endif ++#ifdef CONFIG_SCSI_LPFC_DEBUG_FS ++ struct lpfc_hdwq_stat *c_stat; ++#endif + + max_phys_id = 0; + min_phys_id = LPFC_VECTOR_MAP_EMPTY; +@@ -11099,10 +11120,17 @@ lpfc_cpu_affinity_check(struct lpfc_hba *phba, int vectors) + idx = 0; + for_each_possible_cpu(cpu) { + cpup = &phba->sli4_hba.cpu_map[cpu]; ++#ifdef CONFIG_SCSI_LPFC_DEBUG_FS ++ c_stat = per_cpu_ptr(phba->sli4_hba.c_stat, cpu); ++ c_stat->hdwq_no = cpup->hdwq; ++#endif + if (cpup->hdwq != LPFC_VECTOR_MAP_EMPTY) + continue; + + cpup->hdwq = idx++ % phba->cfg_hdw_queue; ++#ifdef CONFIG_SCSI_LPFC_DEBUG_FS ++ c_stat->hdwq_no = cpup->hdwq; ++#endif + lpfc_printf_log(phba, KERN_INFO, LOG_INIT, + "3340 Set Affinity: not present " + "CPU %d hdwq %d\n", +diff --git a/drivers/scsi/lpfc/lpfc_nvme.c b/drivers/scsi/lpfc/lpfc_nvme.c +index 32b28651039e..38936b7ce043 100644 +--- a/drivers/scsi/lpfc/lpfc_nvme.c ++++ b/drivers/scsi/lpfc/lpfc_nvme.c +@@ -1012,6 +1012,9 @@ lpfc_nvme_io_cmd_wqe_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pwqeIn, + uint32_t code, status, idx; + uint16_t cid, sqhd, data; + uint32_t *ptr; ++#ifdef CONFIG_SCSI_LPFC_DEBUG_FS ++ int cpu; ++#endif + + /* Sanity check on return of outstanding command */ + if (!lpfc_ncmd) { +@@ -1184,19 +1187,15 @@ lpfc_nvme_io_cmd_wqe_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pwqeIn, + phba->ktime_last_cmd = lpfc_ncmd->ts_data_nvme; + lpfc_nvme_ktime(phba, lpfc_ncmd); + } +- if (unlikely(phba->cpucheck_on & LPFC_CHECK_NVME_IO)) { +- uint32_t cpu; +- idx = lpfc_ncmd->cur_iocbq.hba_wqidx; ++ if (unlikely(phba->hdwqstat_on & LPFC_CHECK_NVME_IO)) { + cpu = raw_smp_processor_id(); +- if (cpu < LPFC_CHECK_CPU_CNT) { +- if (lpfc_ncmd->cpu != cpu) +- lpfc_printf_vlog(vport, +- KERN_INFO, LOG_NVME_IOERR, +- "6701 CPU Check cmpl: " +- "cpu %d expect %d\n", +- cpu, lpfc_ncmd->cpu); +- phba->sli4_hba.hdwq[idx].cpucheck_cmpl_io[cpu]++; +- } ++ this_cpu_inc(phba->sli4_hba.c_stat->cmpl_io); ++ if (lpfc_ncmd->cpu != cpu) ++ lpfc_printf_vlog(vport, ++ KERN_INFO, LOG_NVME_IOERR, ++ "6701 CPU Check cmpl: " ++ "cpu %d expect %d\n", ++ cpu, lpfc_ncmd->cpu); + } + #endif + +@@ -1745,19 +1744,17 @@ lpfc_nvme_fcp_io_submit(struct nvme_fc_local_port *pnvme_lport, + if (lpfc_ncmd->ts_cmd_start) + lpfc_ncmd->ts_cmd_wqput = ktime_get_ns(); + +- if (phba->cpucheck_on & LPFC_CHECK_NVME_IO) { ++ if (phba->hdwqstat_on & LPFC_CHECK_NVME_IO) { + cpu = raw_smp_processor_id(); +- if (cpu < LPFC_CHECK_CPU_CNT) { +- lpfc_ncmd->cpu = cpu; +- if (idx != cpu) +- lpfc_printf_vlog(vport, +- KERN_INFO, LOG_NVME_IOERR, +- "6702 CPU Check cmd: " +- "cpu %d wq %d\n", +- lpfc_ncmd->cpu, +- lpfc_queue_info->index); +- phba->sli4_hba.hdwq[idx].cpucheck_xmt_io[cpu]++; +- } ++ this_cpu_inc(phba->sli4_hba.c_stat->xmt_io); ++ lpfc_ncmd->cpu = cpu; ++ if (idx != cpu) ++ lpfc_printf_vlog(vport, ++ KERN_INFO, LOG_NVME_IOERR, ++ "6702 CPU Check cmd: " ++ "cpu %d wq %d\n", ++ lpfc_ncmd->cpu, ++ lpfc_queue_info->index); + } + #endif + return 0; +diff --git a/drivers/scsi/lpfc/lpfc_nvmet.c b/drivers/scsi/lpfc/lpfc_nvmet.c +index ae89d1450912..565419bf8d74 100644 +--- a/drivers/scsi/lpfc/lpfc_nvmet.c ++++ b/drivers/scsi/lpfc/lpfc_nvmet.c +@@ -707,7 +707,7 @@ lpfc_nvmet_xmt_fcp_op_cmp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdwqe, + struct lpfc_nvmet_rcv_ctx *ctxp; + uint32_t status, result, op, start_clean, logerr; + #ifdef CONFIG_SCSI_LPFC_DEBUG_FS +- uint32_t id; ++ int id; + #endif + + ctxp = cmdwqe->context2; +@@ -814,16 +814,14 @@ lpfc_nvmet_xmt_fcp_op_cmp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdwqe, + rsp->done(rsp); + } + #ifdef CONFIG_SCSI_LPFC_DEBUG_FS +- if (phba->cpucheck_on & LPFC_CHECK_NVMET_IO) { ++ if (phba->hdwqstat_on & LPFC_CHECK_NVMET_IO) { + id = raw_smp_processor_id(); +- if (id < LPFC_CHECK_CPU_CNT) { +- if (ctxp->cpu != id) +- lpfc_printf_log(phba, KERN_INFO, LOG_NVME_IOERR, +- "6704 CPU Check cmdcmpl: " +- "cpu %d expect %d\n", +- id, ctxp->cpu); +- phba->sli4_hba.hdwq[rsp->hwqid].cpucheck_cmpl_io[id]++; +- } ++ this_cpu_inc(phba->sli4_hba.c_stat->cmpl_io); ++ if (ctxp->cpu != id) ++ lpfc_printf_log(phba, KERN_INFO, LOG_NVME_IOERR, ++ "6704 CPU Check cmdcmpl: " ++ "cpu %d expect %d\n", ++ id, ctxp->cpu); + } + #endif + } +@@ -931,6 +929,9 @@ lpfc_nvmet_xmt_fcp_op(struct nvmet_fc_target_port *tgtport, + struct lpfc_sli_ring *pring; + unsigned long iflags; + int rc; ++#ifdef CONFIG_SCSI_LPFC_DEBUG_FS ++ int id; ++#endif + + if (phba->pport->load_flag & FC_UNLOADING) { + rc = -ENODEV; +@@ -954,16 +955,14 @@ lpfc_nvmet_xmt_fcp_op(struct nvmet_fc_target_port *tgtport, + if (!ctxp->hdwq) + ctxp->hdwq = &phba->sli4_hba.hdwq[rsp->hwqid]; + +- if (phba->cpucheck_on & LPFC_CHECK_NVMET_IO) { +- int id = raw_smp_processor_id(); +- if (id < LPFC_CHECK_CPU_CNT) { +- if (rsp->hwqid != id) +- lpfc_printf_log(phba, KERN_INFO, LOG_NVME_IOERR, +- "6705 CPU Check OP: " +- "cpu %d expect %d\n", +- id, rsp->hwqid); +- phba->sli4_hba.hdwq[rsp->hwqid].cpucheck_xmt_io[id]++; +- } ++ if (phba->hdwqstat_on & LPFC_CHECK_NVMET_IO) { ++ id = raw_smp_processor_id(); ++ this_cpu_inc(phba->sli4_hba.c_stat->xmt_io); ++ if (rsp->hwqid != id) ++ lpfc_printf_log(phba, KERN_INFO, LOG_NVME_IOERR, ++ "6705 CPU Check OP: " ++ "cpu %d expect %d\n", ++ id, rsp->hwqid); + ctxp->cpu = id; /* Setup cpu for cmpl check */ + } + #endif +@@ -2270,15 +2269,13 @@ lpfc_nvmet_unsol_fcp_buffer(struct lpfc_hba *phba, + size = nvmebuf->bytes_recv; + + #ifdef CONFIG_SCSI_LPFC_DEBUG_FS +- if (phba->cpucheck_on & LPFC_CHECK_NVMET_RCV) { +- if (current_cpu < LPFC_CHECK_CPU_CNT) { +- if (idx != current_cpu) +- lpfc_printf_log(phba, KERN_INFO, LOG_NVME_IOERR, +- "6703 CPU Check rcv: " +- "cpu %d expect %d\n", +- current_cpu, idx); +- phba->sli4_hba.hdwq[idx].cpucheck_rcv_io[current_cpu]++; +- } ++ if (phba->hdwqstat_on & LPFC_CHECK_NVMET_IO) { ++ this_cpu_inc(phba->sli4_hba.c_stat->rcv_io); ++ if (idx != current_cpu) ++ lpfc_printf_log(phba, KERN_INFO, LOG_NVME_IOERR, ++ "6703 CPU Check rcv: " ++ "cpu %d expect %d\n", ++ current_cpu, idx); + } + #endif + +diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c +index be62795715f7..3caa4fd2b55f 100644 +--- a/drivers/scsi/lpfc/lpfc_scsi.c ++++ b/drivers/scsi/lpfc/lpfc_scsi.c +@@ -3805,9 +3805,6 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn, + struct Scsi_Host *shost; + int idx; + uint32_t logit = LOG_FCP; +-#ifdef CONFIG_SCSI_LPFC_DEBUG_FS +- int cpu; +-#endif + + /* Guard against abort handler being called at same time */ + spin_lock(&lpfc_cmd->buf_lock); +@@ -3826,11 +3823,8 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn, + phba->sli4_hba.hdwq[idx].scsi_cstat.io_cmpls++; + + #ifdef CONFIG_SCSI_LPFC_DEBUG_FS +- if (unlikely(phba->cpucheck_on & LPFC_CHECK_SCSI_IO)) { +- cpu = raw_smp_processor_id(); +- if (cpu < LPFC_CHECK_CPU_CNT && phba->sli4_hba.hdwq) +- phba->sli4_hba.hdwq[idx].cpucheck_cmpl_io[cpu]++; +- } ++ if (unlikely(phba->hdwqstat_on & LPFC_CHECK_SCSI_IO)) ++ this_cpu_inc(phba->sli4_hba.c_stat->cmpl_io); + #endif + shost = cmd->device->host; + +@@ -4503,9 +4497,6 @@ lpfc_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *cmnd) + struct lpfc_io_buf *lpfc_cmd; + struct fc_rport *rport = starget_to_rport(scsi_target(cmnd->device)); + int err, idx; +-#ifdef CONFIG_SCSI_LPFC_DEBUG_FS +- int cpu; +-#endif + + rdata = lpfc_rport_data_from_scsi_device(cmnd->device); + +@@ -4626,14 +4617,8 @@ lpfc_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *cmnd) + lpfc_scsi_prep_cmnd(vport, lpfc_cmd, ndlp); + + #ifdef CONFIG_SCSI_LPFC_DEBUG_FS +- if (unlikely(phba->cpucheck_on & LPFC_CHECK_SCSI_IO)) { +- cpu = raw_smp_processor_id(); +- if (cpu < LPFC_CHECK_CPU_CNT) { +- struct lpfc_sli4_hdw_queue *hdwq = +- &phba->sli4_hba.hdwq[lpfc_cmd->hdwq_no]; +- hdwq->cpucheck_xmt_io[cpu]++; +- } +- } ++ if (unlikely(phba->hdwqstat_on & LPFC_CHECK_SCSI_IO)) ++ this_cpu_inc(phba->sli4_hba.c_stat->xmt_io); + #endif + err = lpfc_sli_issue_iocb(phba, LPFC_FCP_RING, + &lpfc_cmd->cur_iocbq, SLI_IOCB_RET_IOCB); +diff --git a/drivers/scsi/lpfc/lpfc_sli4.h b/drivers/scsi/lpfc/lpfc_sli4.h +index d963ca871383..8da7429e385a 100644 +--- a/drivers/scsi/lpfc/lpfc_sli4.h ++++ b/drivers/scsi/lpfc/lpfc_sli4.h +@@ -697,13 +697,6 @@ struct lpfc_sli4_hdw_queue { + struct lpfc_lock_stat lock_conflict; + #endif + +-#ifdef CONFIG_SCSI_LPFC_DEBUG_FS +-#define LPFC_CHECK_CPU_CNT 128 +- uint32_t cpucheck_rcv_io[LPFC_CHECK_CPU_CNT]; +- uint32_t cpucheck_xmt_io[LPFC_CHECK_CPU_CNT]; +- uint32_t cpucheck_cmpl_io[LPFC_CHECK_CPU_CNT]; +-#endif +- + /* Per HDWQ pool resources */ + struct list_head sgl_list; + struct list_head cmd_rsp_buf_list; +@@ -740,6 +733,15 @@ struct lpfc_sli4_hdw_queue { + #define lpfc_qp_spin_lock(lock, qp, lstat) spin_lock(lock) + #endif + ++#ifdef CONFIG_SCSI_LPFC_DEBUG_FS ++struct lpfc_hdwq_stat { ++ u32 hdwq_no; ++ u32 rcv_io; ++ u32 xmt_io; ++ u32 cmpl_io; ++}; ++#endif ++ + struct lpfc_sli4_hba { + void __iomem *conf_regs_memmap_p; /* Kernel memory mapped address for + * config space registers +@@ -921,6 +923,9 @@ struct lpfc_sli4_hba { + struct cpumask numa_mask; + uint16_t curr_disp_cpu; + struct lpfc_eq_intr_info __percpu *eq_info; ++#ifdef CONFIG_SCSI_LPFC_DEBUG_FS ++ struct lpfc_hdwq_stat __percpu *c_stat; ++#endif + uint32_t conf_trunk; + #define lpfc_conf_trunk_port0_WORD conf_trunk + #define lpfc_conf_trunk_port0_SHIFT 0 +-- +2.23.0 + diff --git a/patches.suse/scsi-lpfc-Fix-improper-flag-check-for-IO-type.patch b/patches.suse/scsi-lpfc-Fix-improper-flag-check-for-IO-type.patch new file mode 100644 index 0000000..8ccbb5e --- /dev/null +++ b/patches.suse/scsi-lpfc-Fix-improper-flag-check-for-IO-type.patch @@ -0,0 +1,42 @@ +From: James Smart +Date: Wed, 18 Dec 2019 15:58:07 -0800 +Subject: scsi: lpfc: Fix improper flag check for IO type +Patch-mainline: v5.6-rc1 +Git-commit: c438d0628aa5cf9af57c7cd65794551622ea800d +References: bsc#1164777 bsc#1164780 bsc#1165211 + +Current driver code looks at iocb types and uses a "==" comparison on the +flags to determine type. If another flag were set, it would disrupt the +comparison. + +Fix by converting to a bitwise & operation. + +Link: https://lore.kernel.org/r/20191218235808.31922-10-jsmart2021@gmail.com +Signed-off-by: Dick Kennedy +Signed-off-by: James Smart +Signed-off-by: Martin K. Petersen +Acked-by: Daniel Wagner +--- + drivers/scsi/lpfc/lpfc_scsi.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/scsi/lpfc/lpfc_scsi.c ++++ b/drivers/scsi/lpfc/lpfc_scsi.c +@@ -481,7 +481,7 @@ lpfc_sli4_vport_delete_fcp_xri_aborted(s + spin_lock(&qp->abts_io_buf_list_lock); + list_for_each_entry_safe(psb, next_psb, + &qp->lpfc_abts_io_buf_list, list) { +- if (psb->cur_iocbq.iocb_flag == LPFC_IO_NVME) ++ if (psb->cur_iocbq.iocb_flag & LPFC_IO_NVME) + continue; + + if (psb->rdata && psb->rdata->pnode && +@@ -528,7 +528,7 @@ lpfc_sli4_io_xri_aborted(struct lpfc_hba + list_del_init(&psb->list); + psb->flags &= ~LPFC_SBUF_XBUSY; + psb->status = IOSTAT_SUCCESS; +- if (psb->cur_iocbq.iocb_flag == LPFC_IO_NVME) { ++ if (psb->cur_iocbq.iocb_flag & LPFC_IO_NVME) { + qp->abts_nvme_io_bufs--; + spin_unlock(&qp->abts_io_buf_list_lock); + spin_unlock_irqrestore(&phba->hbalock, iflag); diff --git a/patches.suse/scsi-lpfc-Fix-incomplete-NVME-discovery-when-target.patch b/patches.suse/scsi-lpfc-Fix-incomplete-NVME-discovery-when-target.patch new file mode 100644 index 0000000..5284f54 --- /dev/null +++ b/patches.suse/scsi-lpfc-Fix-incomplete-NVME-discovery-when-target.patch @@ -0,0 +1,207 @@ +From: James Smart +Date: Wed, 18 Dec 2019 15:57:59 -0800 +Subject: scsi: lpfc: Fix incomplete NVME discovery when target +Patch-mainline: v5.6-rc1 +Git-commit: be0709e449ac9d9753a5c17e5b770d6e5e930e4a +References: bsc#1164777 bsc#1164780 bsc#1165211 + +NVMe device re-discovery does not complete. Dev_loss_tmo messages seen on +initiator after recovery from a link disturbance. + +The failing case is the following: + +When the driver (as a NVME target) receives a PLOGI, the driver initiates +an "unreg rpi" mailbox command. While the mailbox command is in progress, +the driver requests that an ACC be sent to the initiator. The target's ACC +is received by the initiator and the initiator then transmits a PLOGI. The +driver receives the PLOGI prior to receiving the completion for the PLOGI +response WQE that sent the ACC. (Different delivery sources from the hw so +the race is very possible). Given the PLOGI is prior to the ACC completion +(signifying PLOGI exchange complete), the driver LS_RJT's the PRLI. The +"unreg rpi" mailbox then completes. Since PRLI has been received, the +driver transmits a PLOGI to restart discovery, which the initiator then +ACC's. If the driver processes the (re)PLOGI ACC prior to the completing +the handling for the earlier ACC it sent the intiators original PLOGI, +there is no state change for completion of the (re)PLOGI. The ndlp remains +in "PLOGI Sent" and the initiator continues sending PRLI's which are +rejected by the target until timeout or retry is reached. + +Fix by: When in target mode, defer sending an ACC for the received PLOGI +until unreg RPI completes. + +Link: https://lore.kernel.org/r/20191218235808.31922-2-jsmart2021@gmail.com +Signed-off-by: Dick Kennedy +Signed-off-by: James Smart +Signed-off-by: Martin K. Petersen +Acked-by: Daniel Wagner +--- + drivers/scsi/lpfc/lpfc_nportdisc.c | 108 +++++++++++++++++++++++++++++++++---- + 1 file changed, 99 insertions(+), 9 deletions(-) + +--- a/drivers/scsi/lpfc/lpfc_nportdisc.c ++++ b/drivers/scsi/lpfc/lpfc_nportdisc.c +@@ -308,7 +308,7 @@ lpfc_defer_pt2pt_acc(struct lpfc_hba *ph + mb->mbxStatus); + mempool_free(login_mbox, phba->mbox_mem_pool); + mempool_free(link_mbox, phba->mbox_mem_pool); +- lpfc_sli_release_iocbq(phba, save_iocb); ++ kfree(save_iocb); + return; + } + +@@ -325,7 +325,61 @@ lpfc_defer_pt2pt_acc(struct lpfc_hba *ph + } + + mempool_free(link_mbox, phba->mbox_mem_pool); +- lpfc_sli_release_iocbq(phba, save_iocb); ++ kfree(save_iocb); ++} ++ ++/** ++ * lpfc_defer_tgt_acc - Progress SLI4 target rcv PLOGI handler ++ * @phba: Pointer to HBA context object. ++ * @pmb: Pointer to mailbox object. ++ * ++ * This function provides the unreg rpi mailbox completion handler for a tgt. ++ * The routine frees the memory resources associated with the completed ++ * mailbox command and transmits the ELS ACC. ++ * ++ * This routine is only called if we are SLI4, acting in target ++ * mode and the remote NPort issues the PLOGI after link up. ++ **/ ++void ++lpfc_defer_acc_rsp(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) ++{ ++ struct lpfc_vport *vport = pmb->vport; ++ struct lpfc_nodelist *ndlp = pmb->ctx_ndlp; ++ LPFC_MBOXQ_t *mbox = pmb->context3; ++ struct lpfc_iocbq *piocb = NULL; ++ int rc; ++ ++ if (mbox) { ++ pmb->context3 = NULL; ++ piocb = mbox->context3; ++ mbox->context3 = NULL; ++ } ++ ++ /* ++ * Complete the unreg rpi mbx request, and update flags. ++ * This will also restart any deferred events. ++ */ ++ lpfc_nlp_get(ndlp); ++ lpfc_sli4_unreg_rpi_cmpl_clr(phba, pmb); ++ ++ if (!piocb) { ++ lpfc_printf_vlog(vport, KERN_ERR, LOG_DISCOVERY | LOG_ELS, ++ "4578 PLOGI ACC fail\n"); ++ if (mbox) ++ mempool_free(mbox, phba->mbox_mem_pool); ++ goto out; ++ } ++ ++ rc = lpfc_els_rsp_acc(vport, ELS_CMD_PLOGI, piocb, ndlp, mbox); ++ if (rc) { ++ lpfc_printf_vlog(vport, KERN_ERR, LOG_DISCOVERY | LOG_ELS, ++ "4579 PLOGI ACC fail %x\n", rc); ++ if (mbox) ++ mempool_free(mbox, phba->mbox_mem_pool); ++ } ++ kfree(piocb); ++out: ++ lpfc_nlp_put(ndlp); + } + + static int +@@ -345,6 +399,7 @@ lpfc_rcv_plogi(struct lpfc_vport *vport, + struct lpfc_iocbq *save_iocb; + struct ls_rjt stat; + uint32_t vid, flag; ++ u16 rpi; + int rc, defer_acc; + + memset(&stat, 0, sizeof (struct ls_rjt)); +@@ -488,7 +543,7 @@ lpfc_rcv_plogi(struct lpfc_vport *vport, + link_mbox->vport = vport; + link_mbox->ctx_ndlp = ndlp; + +- save_iocb = lpfc_sli_get_iocbq(phba); ++ save_iocb = kzalloc(sizeof(*save_iocb), GFP_KERNEL); + if (!save_iocb) + goto out; + /* Save info from cmd IOCB used in rsp */ +@@ -513,7 +568,36 @@ lpfc_rcv_plogi(struct lpfc_vport *vport, + goto out; + + /* Registering an existing RPI behaves differently for SLI3 vs SLI4 */ +- if (phba->sli_rev == LPFC_SLI_REV4) ++ if (phba->nvmet_support && !defer_acc) { ++ link_mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); ++ if (!link_mbox) ++ goto out; ++ ++ /* As unique identifiers such as iotag would be overwritten ++ * with those from the cmdiocb, allocate separate temporary ++ * storage for the copy. ++ */ ++ save_iocb = kzalloc(sizeof(*save_iocb), GFP_KERNEL); ++ if (!save_iocb) ++ goto out; ++ ++ /* Unreg RPI is required for SLI4. */ ++ rpi = phba->sli4_hba.rpi_ids[ndlp->nlp_rpi]; ++ lpfc_unreg_login(phba, vport->vpi, rpi, link_mbox); ++ link_mbox->vport = vport; ++ link_mbox->ctx_ndlp = ndlp; ++ link_mbox->mbox_cmpl = lpfc_defer_acc_rsp; ++ ++ if (((ndlp->nlp_DID & Fabric_DID_MASK) != Fabric_DID_MASK) && ++ (!(vport->fc_flag & FC_OFFLINE_MODE))) ++ ndlp->nlp_flag |= NLP_UNREG_INP; ++ ++ /* Save info from cmd IOCB used in rsp */ ++ memcpy(save_iocb, cmdiocb, sizeof(*save_iocb)); ++ ++ /* Delay sending ACC till unreg RPI completes. */ ++ defer_acc = 1; ++ } else if (phba->sli_rev == LPFC_SLI_REV4) + lpfc_unreg_rpi(vport, ndlp); + + rc = lpfc_reg_rpi(phba, vport->vpi, icmd->un.rcvels.remoteID, +@@ -553,6 +637,9 @@ lpfc_rcv_plogi(struct lpfc_vport *vport, + if ((vport->port_type == LPFC_NPIV_PORT && + vport->cfg_restrict_login)) { + ++ /* no deferred ACC */ ++ kfree(save_iocb); ++ + /* In order to preserve RPIs, we want to cleanup + * the default RPI the firmware created to rcv + * this ELS request. The only way to do this is +@@ -571,8 +658,12 @@ lpfc_rcv_plogi(struct lpfc_vport *vport, + } + if (defer_acc) { + /* So the order here should be: +- * Issue CONFIG_LINK mbox +- * CONFIG_LINK cmpl ++ * SLI3 pt2pt ++ * Issue CONFIG_LINK mbox ++ * CONFIG_LINK cmpl ++ * SLI4 tgt ++ * Issue UNREG RPI mbx ++ * UNREG RPI cmpl + * Issue PLOGI ACC + * PLOGI ACC cmpl + * Issue REG_LOGIN mbox +@@ -596,10 +687,9 @@ lpfc_rcv_plogi(struct lpfc_vport *vport, + out: + if (defer_acc) + lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY, +- "4577 pt2pt discovery failure: %p %p %p\n", ++ "4577 discovery failure: %p %p %p\n", + save_iocb, link_mbox, login_mbox); +- if (save_iocb) +- lpfc_sli_release_iocbq(phba, save_iocb); ++ kfree(save_iocb); + if (link_mbox) + mempool_free(link_mbox, phba->mbox_mem_pool); + if (login_mbox) diff --git a/patches.suse/scsi-lpfc-Fix-kasan-slab-out-of-bounds-error-in-lpfc.patch b/patches.suse/scsi-lpfc-Fix-kasan-slab-out-of-bounds-error-in-lpfc.patch new file mode 100644 index 0000000..6dcd74c --- /dev/null +++ b/patches.suse/scsi-lpfc-Fix-kasan-slab-out-of-bounds-error-in-lpfc.patch @@ -0,0 +1,55 @@ +From: James Smart +Date: Sun, 22 Mar 2020 11:12:53 -0700 +Subject: scsi: lpfc: Fix kasan slab-out-of-bounds error in lpfc_unreg_login +Patch-mainline: v5.7-rc1 +Git-commit: 38503943c89f0bafd9e3742f63f872301d44cbea +References: bsc#1164777 bsc#1164780 bsc#1165211 + +The following kasan bug was called out: + + BUG: KASAN: slab-out-of-bounds in lpfc_unreg_login+0x7c/0xc0 [lpfc] + Read of size 2 at addr ffff889fc7c50a22 by task lpfc_worker_3/6676 + ... + Call Trace: + dump_stack+0x96/0xe0 + ? lpfc_unreg_login+0x7c/0xc0 [lpfc] + print_address_description.constprop.6+0x1b/0x220 + ? lpfc_unreg_login+0x7c/0xc0 [lpfc] + ? lpfc_unreg_login+0x7c/0xc0 [lpfc] + __kasan_report.cold.9+0x37/0x7c + ? lpfc_unreg_login+0x7c/0xc0 [lpfc] + kasan_report+0xe/0x20 + lpfc_unreg_login+0x7c/0xc0 [lpfc] + lpfc_sli_def_mbox_cmpl+0x334/0x430 [lpfc] + ... + +When processing the completion of a "Reg Rpi" login mailbox command in +lpfc_sli_def_mbox_cmpl, a call may be made to lpfc_unreg_login. The vpi is +extracted from the completing mailbox context and passed as an input for +the next. However, the vpi stored in the mailbox command context is an +absolute vpi, which for SLI4 represents both base + offset. When used with +a non-zero base component, (function id > 0) this results in an +out-of-range access beyond the allocated phba->vpi_ids array. + +Fix by subtracting the function's base value to get an accurate vpi number. + +Link: https://lore.kernel.org/r/20200322181304.37655-2-jsmart2021@gmail.com +Signed-off-by: James Smart +Signed-off-by: Dick Kennedy +Signed-off-by: Martin K. Petersen +Acked-by: Daniel Wagner +--- + drivers/scsi/lpfc/lpfc_sli.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/drivers/scsi/lpfc/lpfc_sli.c ++++ b/drivers/scsi/lpfc/lpfc_sli.c +@@ -2511,6 +2511,8 @@ lpfc_sli_def_mbox_cmpl(struct lpfc_hba * + !pmb->u.mb.mbxStatus) { + rpi = pmb->u.mb.un.varWords[0]; + vpi = pmb->u.mb.un.varRegLogin.vpi; ++ if (phba->sli_rev == LPFC_SLI_REV4) ++ vpi -= phba->sli4_hba.max_cfg_param.vpi_base; + lpfc_unreg_login(phba, vpi, rpi, pmb); + pmb->vport = vport; + pmb->mbox_cmpl = lpfc_sli_def_mbox_cmpl; diff --git a/patches.suse/scsi-lpfc-Fix-lockdep-error-register-non-static-key.patch b/patches.suse/scsi-lpfc-Fix-lockdep-error-register-non-static-key.patch new file mode 100644 index 0000000..82e2246 --- /dev/null +++ b/patches.suse/scsi-lpfc-Fix-lockdep-error-register-non-static-key.patch @@ -0,0 +1,88 @@ +From: James Smart +Date: Sun, 22 Mar 2020 11:12:54 -0700 +Subject: scsi: lpfc: Fix lockdep error - register non-static key +Patch-mainline: v5.7-rc1 +Git-commit: f861f596714bed06069f1109b89e51f3855c4ddf +References: bsc#1164777 bsc#1164780 bsc#1165211 + +The following lockdep error was reported when unloading the lpfc driver: + + INFO: trying to register non-static key. + the code is fine but needs lockdep annotation. + turning off the locking correctness validator. + ... + Call Trace: + dump_stack+0x96/0xe0 + register_lock_class+0x8b8/0x8c0 + ? lockdep_hardirqs_on+0x190/0x280 + ? is_dynamic_key+0x150/0x150 + ? wait_for_completion_interruptible+0x2a0/0x2a0 + ? wake_up_q+0xd0/0xd0 + __lock_acquire+0xda/0x21a0 + ? register_lock_class+0x8c0/0x8c0 + ? synchronize_rcu_expedited+0x500/0x500 + ? __call_rcu+0x850/0x850 + lock_acquire+0xf3/0x1f0 + ? del_timer_sync+0x5/0xb0 + del_timer_sync+0x3c/0xb0 + ? del_timer_sync+0x5/0xb0 + lpfc_pci_remove_one.cold.102+0x8b7/0x935 [lpfc] + ... + +Unloading the driver resulted in a call to del_timer_sync for the +cpuhp_poll_timer. However the call to setup the timer had never been made, +so the timer structures used by lockdep checking were not initialized. + +Unconditionally call setup_timer for the cpuhp_poll_timer during driver +initialization. Calls to start the timer remain "as needed". + +Link: https://lore.kernel.org/r/20200322181304.37655-3-jsmart2021@gmail.com +Signed-off-by: James Smart +Signed-off-by: Dick Kennedy +Signed-off-by: Martin K. Petersen +Acked-by: Daniel Wagner +--- + drivers/scsi/lpfc/lpfc_init.c | 5 ++--- + drivers/scsi/lpfc/lpfc_sli.c | 6 ++---- + 2 files changed, 4 insertions(+), 7 deletions(-) + +--- a/drivers/scsi/lpfc/lpfc_init.c ++++ b/drivers/scsi/lpfc/lpfc_init.c +@@ -11173,11 +11173,9 @@ static void lpfc_cpuhp_add(struct lpfc_h + + rcu_read_lock(); + +- if (!list_empty(&phba->poll_list)) { +- timer_setup(&phba->cpuhp_poll_timer, lpfc_sli4_poll_hbtimer, 0); ++ if (!list_empty(&phba->poll_list)) + mod_timer(&phba->cpuhp_poll_timer, + jiffies + msecs_to_jiffies(LPFC_POLL_HB)); +- } + + rcu_read_unlock(); + +@@ -13149,6 +13147,7 @@ lpfc_pci_probe_one_s4(struct pci_dev *pd + lpfc_sli4_ras_setup(phba); + + INIT_LIST_HEAD(&phba->poll_list); ++ timer_setup(&phba->cpuhp_poll_timer, lpfc_sli4_poll_hbtimer, 0); + cpuhp_state_add_instance_nocalls(lpfc_cpuhp_state, &phba->cpuhp); + + return 0; +--- a/drivers/scsi/lpfc/lpfc_sli.c ++++ b/drivers/scsi/lpfc/lpfc_sli.c +@@ -14451,12 +14451,10 @@ static inline void lpfc_sli4_add_to_poll + { + struct lpfc_hba *phba = eq->phba; + +- if (list_empty(&phba->poll_list)) { +- timer_setup(&phba->cpuhp_poll_timer, lpfc_sli4_poll_hbtimer, 0); +- /* kickstart slowpath processing for this eq */ ++ /* kickstart slowpath processing if needed */ ++ if (list_empty(&phba->poll_list)) + mod_timer(&phba->cpuhp_poll_timer, + jiffies + msecs_to_jiffies(LPFC_POLL_HB)); +- } + + list_add_rcu(&eq->_poll_list, &phba->poll_list); + synchronize_rcu(); diff --git a/patches.suse/scsi-lpfc-Fix-lpfc-overwrite-of-sg_cnt-field-in-nvme.patch b/patches.suse/scsi-lpfc-Fix-lpfc-overwrite-of-sg_cnt-field-in-nvme.patch new file mode 100644 index 0000000..782a426 --- /dev/null +++ b/patches.suse/scsi-lpfc-Fix-lpfc-overwrite-of-sg_cnt-field-in-nvme.patch @@ -0,0 +1,65 @@ +From: James Smart +Date: Sun, 22 Mar 2020 11:12:55 -0700 +Subject: scsi: lpfc: Fix lpfc overwrite of sg_cnt field in nvmefc_tgt_fcp_req +Patch-mainline: v5.7-rc1 +Git-commit: e7f4034912d08a5fdfd7bdbcf9e86e885de1de21 +References: bsc#1164777 bsc#1164780 bsc#1165211 + +In lpfc_nvmet_prep_fcp_wqe() the line "rsp->sg_cnt = 0" is modifying the +transport's data structure. This may result in the transport believing the +s/g list was already freed, thus may not unmap/free it properly. Lpfc +driver should not modify the transport data structure. + +The zeroing of the sg_cnt is to avoid use of the transport's sgl in a +subsequent loop where the driver builds the necessary requests for the +adapter firmware to complete the IO. + +Change LLDD to use a local copy of the transport sg_cnt when building +requests to be passed to the adapter fw. + +Link: https://lore.kernel.org/r/20200322181304.37655-4-jsmart2021@gmail.com +Signed-off-by: James Smart +Signed-off-by: Dick Kennedy +Signed-off-by: Martin K. Petersen +Acked-by: Daniel Wagner +--- + drivers/scsi/lpfc/lpfc_nvmet.c | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +--- a/drivers/scsi/lpfc/lpfc_nvmet.c ++++ b/drivers/scsi/lpfc/lpfc_nvmet.c +@@ -2581,7 +2581,7 @@ lpfc_nvmet_prep_fcp_wqe(struct lpfc_hba + union lpfc_wqe128 *wqe; + struct ulp_bde64 *bde; + dma_addr_t physaddr; +- int i, cnt; ++ int i, cnt, nsegs; + int do_pbde; + int xc = 1; + +@@ -2612,6 +2612,7 @@ lpfc_nvmet_prep_fcp_wqe(struct lpfc_hba + phba->cfg_nvme_seg_cnt); + return NULL; + } ++ nsegs = rsp->sg_cnt; + + tgtp = (struct lpfc_nvmet_tgtport *)phba->targetport->private; + nvmewqe = ctxp->wqeq; +@@ -2851,7 +2852,7 @@ lpfc_nvmet_prep_fcp_wqe(struct lpfc_hba + wqe->fcp_trsp.rsvd_12_15[0] = 0; + + /* Use rspbuf, NOT sg list */ +- rsp->sg_cnt = 0; ++ nsegs = 0; + sgl->word2 = 0; + atomic_inc(&tgtp->xmt_fcp_rsp); + break; +@@ -2868,7 +2869,7 @@ lpfc_nvmet_prep_fcp_wqe(struct lpfc_hba + nvmewqe->drvrTimeout = (phba->fc_ratov * 3) + LPFC_DRVR_TIMEOUT; + nvmewqe->context1 = ndlp; + +- for_each_sg(rsp->sg, sgel, rsp->sg_cnt, i) { ++ for_each_sg(rsp->sg, sgel, nsegs, i) { + physaddr = sg_dma_address(sgel); + cnt = sg_dma_len(sgel); + sgl->addr_hi = putPaddrHigh(physaddr); diff --git a/patches.suse/scsi-lpfc-Fix-lpfc_io_buf-resource-leak-in-lpfc_get_.patch b/patches.suse/scsi-lpfc-Fix-lpfc_io_buf-resource-leak-in-lpfc_get_.patch new file mode 100644 index 0000000..fb385b3 --- /dev/null +++ b/patches.suse/scsi-lpfc-Fix-lpfc_io_buf-resource-leak-in-lpfc_get_.patch @@ -0,0 +1,38 @@ +From: James Smart +Date: Mon, 27 Jan 2020 16:23:02 -0800 +Subject: scsi: lpfc: Fix lpfc_io_buf resource leak in lpfc_get_scsi_buf_s4 + error path +Patch-mainline: v5.7-rc1 +Git-commit: 0ab384a49c548baf132ccef249f78d9c6c506380 +References: bsc#1164777 bsc#1164780 bsc#1165211 + +If a call to lpfc_get_cmd_rsp_buf_per_hdwq returns NULL (memory allocation +failure), a previously allocated lpfc_io_buf resource is leaked. + +Fix by releasing the lpfc_io_buf resource in the failure path. + +Fixes: d79c9e9d4b3d ("scsi: lpfc: Support dynamic unbounded SGL lists on G7 hardware.") +Cc: # v5.4+ +Link: https://lore.kernel.org/r/20200128002312.16346-3-jsmart2021@gmail.com +Signed-off-by: Dick Kennedy +Signed-off-by: James Smart +Signed-off-by: Martin K. Petersen +Acked-by: Daniel Wagner +--- + drivers/scsi/lpfc/lpfc_scsi.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +--- a/drivers/scsi/lpfc/lpfc_scsi.c ++++ b/drivers/scsi/lpfc/lpfc_scsi.c +@@ -671,8 +671,10 @@ lpfc_get_scsi_buf_s4(struct lpfc_hba *ph + lpfc_cmd->prot_data_type = 0; + #endif + tmp = lpfc_get_cmd_rsp_buf_per_hdwq(phba, lpfc_cmd); +- if (!tmp) ++ if (!tmp) { ++ lpfc_release_io_buf(phba, lpfc_cmd, lpfc_cmd->hdwq); + return NULL; ++ } + + lpfc_cmd->fcp_cmnd = tmp->fcp_cmnd; + lpfc_cmd->fcp_rsp = tmp->fcp_rsp; diff --git a/patches.suse/scsi-lpfc-Fix-memory-leak-on-lpfc_bsg_write_ebuf_set.patch b/patches.suse/scsi-lpfc-Fix-memory-leak-on-lpfc_bsg_write_ebuf_set.patch new file mode 100644 index 0000000..cb487df --- /dev/null +++ b/patches.suse/scsi-lpfc-Fix-memory-leak-on-lpfc_bsg_write_ebuf_set.patch @@ -0,0 +1,61 @@ +From: Bo Wu +Date: Sat, 7 Dec 2019 03:22:46 +0000 +Subject: scsi: lpfc: Fix memory leak on lpfc_bsg_write_ebuf_set func +Patch-mainline: v5.5-rc2 +Git-commit: 9a1b0b9a6dab452fb0e39fe96880c4faf3878369 +References: bsc#1164777 bsc#1164780 bsc#1165211 + +When phba->mbox_ext_buf_ctx.seqNum != phba->mbox_ext_buf_ctx.numBuf, +dd_data should be freed before return SLI_CONFIG_HANDLED. + +When lpfc_sli_issue_mbox func return fails, pmboxq should be also freed in +job_error tag. + +Link: https://lore.kernel.org/r/EDBAAA0BBBA2AC4E9C8B6B81DEEE1D6915E7A966@DGGEML525-MBS.china.huawei.com +Signed-off-by: Bo Wu +Reviewed-by: Zhiqiang Liu +Reviewed-by: James Smart +Signed-off-by: Martin K. Petersen +Acked-by: Daniel Wagner +--- + drivers/scsi/lpfc/lpfc_bsg.c | 15 +++++++++------ + 1 file changed, 9 insertions(+), 6 deletions(-) + +--- a/drivers/scsi/lpfc/lpfc_bsg.c ++++ b/drivers/scsi/lpfc/lpfc_bsg.c +@@ -4492,12 +4492,6 @@ lpfc_bsg_write_ebuf_set(struct lpfc_hba + phba->mbox_ext_buf_ctx.seqNum++; + nemb_tp = phba->mbox_ext_buf_ctx.nembType; + +- dd_data = kmalloc(sizeof(struct bsg_job_data), GFP_KERNEL); +- if (!dd_data) { +- rc = -ENOMEM; +- goto job_error; +- } +- + pbuf = (uint8_t *)dmabuf->virt; + size = job->request_payload.payload_len; + sg_copy_to_buffer(job->request_payload.sg_list, +@@ -4534,6 +4528,13 @@ lpfc_bsg_write_ebuf_set(struct lpfc_hba + "2968 SLI_CONFIG ext-buffer wr all %d " + "ebuffers received\n", + phba->mbox_ext_buf_ctx.numBuf); ++ ++ dd_data = kmalloc(sizeof(struct bsg_job_data), GFP_KERNEL); ++ if (!dd_data) { ++ rc = -ENOMEM; ++ goto job_error; ++ } ++ + /* mailbox command structure for base driver */ + pmboxq = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); + if (!pmboxq) { +@@ -4582,6 +4583,8 @@ lpfc_bsg_write_ebuf_set(struct lpfc_hba + return SLI_CONFIG_HANDLED; + + job_error: ++ if (pmboxq) ++ mempool_free(pmboxq, phba->mbox_mem_pool); + lpfc_bsg_dma_page_free(phba, dmabuf); + kfree(dd_data); + diff --git a/patches.suse/scsi-lpfc-Fix-missing-check-for-CSF-in-Write-Object-.patch b/patches.suse/scsi-lpfc-Fix-missing-check-for-CSF-in-Write-Object-.patch new file mode 100644 index 0000000..960879f --- /dev/null +++ b/patches.suse/scsi-lpfc-Fix-missing-check-for-CSF-in-Write-Object-.patch @@ -0,0 +1,67 @@ +From: James Smart +Date: Wed, 18 Dec 2019 15:58:01 -0800 +Subject: scsi: lpfc: Fix missing check for CSF in Write Object Mbox Rsp +Patch-mainline: v5.6-rc1 +Git-commit: f3d0a8acc5a88435186d242376db05788a891516 +References: bsc#1164777 bsc#1164780 bsc#1165211 + +When the WriteObject mailbox response has change_status set to is 0x2 +(Firmware Reset) or 0x04 (Port Migration Reset), the CSF field should also +be checked to see if a fw reset is sufficient to enable all new features in +the updated firmware image. If not, a fw reset would start the new +firmware, but with a feature level equal to existing firmware. To enable +the new features, a chip reset/pci slot reset would be required. + +Check the CSF bit when change_status is 0x2 or 0x4 to know whether to +perform a pci bus reset or fw reset. + +Link: https://lore.kernel.org/r/20191218235808.31922-4-jsmart2021@gmail.com +Signed-off-by: Dick Kennedy +Signed-off-by: James Smart +Signed-off-by: Martin K. Petersen +Acked-by: Daniel Wagner +--- + drivers/scsi/lpfc/lpfc_hw4.h | 3 +++ + drivers/scsi/lpfc/lpfc_sli.c | 12 +++++++++++- + 2 files changed, 14 insertions(+), 1 deletion(-) + +--- a/drivers/scsi/lpfc/lpfc_hw4.h ++++ b/drivers/scsi/lpfc/lpfc_hw4.h +@@ -3925,6 +3925,9 @@ struct lpfc_mbx_wr_object { + #define LPFC_CHANGE_STATUS_FW_RESET 0x02 + #define LPFC_CHANGE_STATUS_PORT_MIGRATION 0x04 + #define LPFC_CHANGE_STATUS_PCI_RESET 0x05 ++#define lpfc_wr_object_csf_SHIFT 8 ++#define lpfc_wr_object_csf_MASK 0x00000001 ++#define lpfc_wr_object_csf_WORD word5 + } response; + } u; + }; +--- a/drivers/scsi/lpfc/lpfc_sli.c ++++ b/drivers/scsi/lpfc/lpfc_sli.c +@@ -19456,7 +19456,7 @@ lpfc_wr_object(struct lpfc_hba *phba, st + struct lpfc_mbx_wr_object *wr_object; + LPFC_MBOXQ_t *mbox; + int rc = 0, i = 0; +- uint32_t shdr_status, shdr_add_status, shdr_change_status; ++ uint32_t shdr_status, shdr_add_status, shdr_change_status, shdr_csf; + uint32_t mbox_tmo; + struct lpfc_dmabuf *dmabuf; + uint32_t written = 0; +@@ -19513,6 +19513,16 @@ lpfc_wr_object(struct lpfc_hba *phba, st + if (check_change_status) { + shdr_change_status = bf_get(lpfc_wr_object_change_status, + &wr_object->u.response); ++ ++ if (shdr_change_status == LPFC_CHANGE_STATUS_FW_RESET || ++ shdr_change_status == LPFC_CHANGE_STATUS_PORT_MIGRATION) { ++ shdr_csf = bf_get(lpfc_wr_object_csf, ++ &wr_object->u.response); ++ if (shdr_csf) ++ shdr_change_status = ++ LPFC_CHANGE_STATUS_PCI_RESET; ++ } ++ + switch (shdr_change_status) { + case (LPFC_CHANGE_STATUS_PHYS_DEV_RESET): + lpfc_printf_log(phba, KERN_INFO, LOG_INIT, diff --git a/patches.suse/scsi-lpfc-Fix-ras_log-via-debugfs.patch b/patches.suse/scsi-lpfc-Fix-ras_log-via-debugfs.patch new file mode 100644 index 0000000..d4ecd25 --- /dev/null +++ b/patches.suse/scsi-lpfc-Fix-ras_log-via-debugfs.patch @@ -0,0 +1,56 @@ +From: James Smart +Date: Wed, 18 Dec 2019 15:58:03 -0800 +Subject: scsi: lpfc: Fix ras_log via debugfs +Patch-mainline: v5.6-rc1 +Git-commit: 9a20cc10fa0504693d2dadb90b2ae185755abc09 +References: bsc#1164777 bsc#1164780 bsc#1165211 + +/sys/kernel/debug/lpfc/fn0/ras_log always shows the same ras_log even if +there are link bounce events triggered via issue_lip + +Dynamic FW logging had logic that prematurely breaks from the buffer +filling loop. + +Fix the check for buffer overrun by looking before copying and restricting +copy length to the remaining buffer. When copying, ensure space for NULL +character is left in the buffer. While in the routine - ensure the buffer +is cleared before adding elements. + +Link: https://lore.kernel.org/r/20191218235808.31922-6-jsmart2021@gmail.com +Signed-off-by: Dick Kennedy +Signed-off-by: James Smart +Signed-off-by: Martin K. Petersen +Acked-by: Daniel Wagner +--- + drivers/scsi/lpfc/lpfc_debugfs.c | 11 +++++++++-- + 1 file changed, 9 insertions(+), 2 deletions(-) + +--- a/drivers/scsi/lpfc/lpfc_debugfs.c ++++ b/drivers/scsi/lpfc/lpfc_debugfs.c +@@ -2085,6 +2085,8 @@ static int lpfc_debugfs_ras_log_data(str + int copied = 0; + struct lpfc_dmabuf *dmabuf, *next; + ++ memset(buffer, 0, size); ++ + spin_lock_irq(&phba->hbalock); + if (phba->ras_fwlog.state != ACTIVE) { + spin_unlock_irq(&phba->hbalock); +@@ -2094,10 +2096,15 @@ static int lpfc_debugfs_ras_log_data(str + + list_for_each_entry_safe(dmabuf, next, + &phba->ras_fwlog.fwlog_buff_list, list) { ++ /* Check if copying will go over size and a '\0' char */ ++ if ((copied + LPFC_RAS_MAX_ENTRY_SIZE) >= (size - 1)) { ++ memcpy(buffer + copied, dmabuf->virt, ++ size - copied - 1); ++ copied += size - copied - 1; ++ break; ++ } + memcpy(buffer + copied, dmabuf->virt, LPFC_RAS_MAX_ENTRY_SIZE); + copied += LPFC_RAS_MAX_ENTRY_SIZE; +- if (size > copied) +- break; + } + return copied; + } diff --git a/patches.suse/scsi-lpfc-Fix-registration-of-ELS-type-support-in-fd.patch b/patches.suse/scsi-lpfc-Fix-registration-of-ELS-type-support-in-fd.patch new file mode 100644 index 0000000..113871c --- /dev/null +++ b/patches.suse/scsi-lpfc-Fix-registration-of-ELS-type-support-in-fd.patch @@ -0,0 +1,41 @@ +From: James Smart +Date: Mon, 27 Jan 2020 16:23:04 -0800 +Subject: scsi: lpfc: Fix registration of ELS type support in fdmi +Patch-mainline: v5.7-rc1 +Git-commit: 792f3b90be2aeedf5e076bbe6c5808e693f51c23 +References: bsc#1164777 bsc#1164780 bsc#1165211 + +Adjust FC4 Types in FDMI settings + +The driver sets FDMI information registring ELS as a FC4 type. ELS is a +fc3 type and should not be registered. + +Fix by removing ELS type bit when we register for FDMI Port attributes. + +Link: https://lore.kernel.org/r/20200128002312.16346-5-jsmart2021@gmail.com +Signed-off-by: Dick Kennedy +Signed-off-by: James Smart +Signed-off-by: Martin K. Petersen +Acked-by: Daniel Wagner +--- + drivers/scsi/lpfc/lpfc_ct.c | 2 -- + 1 file changed, 2 deletions(-) + +--- a/drivers/scsi/lpfc/lpfc_ct.c ++++ b/drivers/scsi/lpfc/lpfc_ct.c +@@ -2453,7 +2453,6 @@ lpfc_fdmi_port_attr_fc4type(struct lpfc_ + ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue; + memset(ae, 0, 32); + +- ae->un.AttrTypes[3] = 0x02; /* Type 0x1 - ELS */ + ae->un.AttrTypes[2] = 0x01; /* Type 0x8 - FCP */ + ae->un.AttrTypes[7] = 0x01; /* Type 0x20 - CT */ + +@@ -2771,7 +2770,6 @@ lpfc_fdmi_port_attr_active_fc4type(struc + ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue; + memset(ae, 0, 32); + +- ae->un.AttrTypes[3] = 0x02; /* Type 0x1 - ELS */ + ae->un.AttrTypes[2] = 0x01; /* Type 0x8 - FCP */ + ae->un.AttrTypes[7] = 0x01; /* Type 0x20 - CT */ + diff --git a/patches.suse/scsi-lpfc-Fix-release-of-hwq-to-clear-the-eq-relatio.patch b/patches.suse/scsi-lpfc-Fix-release-of-hwq-to-clear-the-eq-relatio.patch new file mode 100644 index 0000000..c827511 --- /dev/null +++ b/patches.suse/scsi-lpfc-Fix-release-of-hwq-to-clear-the-eq-relatio.patch @@ -0,0 +1,35 @@ +From: James Smart +Date: Mon, 27 Jan 2020 16:23:05 -0800 +Subject: scsi: lpfc: Fix release of hwq to clear the eq relationship +Patch-mainline: v5.7-rc1 +Git-commit: 821bc882accaaaf1bbecf5c0ecef659443e3e8cb +References: bsc#1164777 bsc#1164780 bsc#1165211 + +When performing reset testing, the eq's list for related hwqs was getting +corrupted. In cases where there is not a 1:1 eq to hwq, the eq is +shared. The eq maintains a list of hwqs utilizing it in case of cpu +offlining and polling. During the reset, the hwqs are being torn down so +they can be recreated. The recreation was getting confused by seeing a +non-null eq assignment on the eq and the eq list became corrupt. + +Correct by clearing the hdwq eq assignment when the hwq is cleaned up. + +Link: https://lore.kernel.org/r/20200128002312.16346-6-jsmart2021@gmail.com +Signed-off-by: Dick Kennedy +Signed-off-by: James Smart +Signed-off-by: Martin K. Petersen +Acked-by: Daniel Wagner +--- + drivers/scsi/lpfc/lpfc_init.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/scsi/lpfc/lpfc_init.c ++++ b/drivers/scsi/lpfc/lpfc_init.c +@@ -9235,6 +9235,7 @@ lpfc_sli4_release_hdwq(struct lpfc_hba * + /* Free the CQ/WQ corresponding to the Hardware Queue */ + lpfc_sli4_queue_free(hdwq[idx].io_cq); + lpfc_sli4_queue_free(hdwq[idx].io_wq); ++ hdwq[idx].hba_eq = NULL; + hdwq[idx].io_cq = NULL; + hdwq[idx].io_wq = NULL; + if (phba->cfg_xpsgl && !phba->nvmet_support) diff --git a/patches.suse/scsi-lpfc-Fix-scsi-host-template-for-SLI3-vports.patch b/patches.suse/scsi-lpfc-Fix-scsi-host-template-for-SLI3-vports.patch new file mode 100644 index 0000000..c6e2d0e --- /dev/null +++ b/patches.suse/scsi-lpfc-Fix-scsi-host-template-for-SLI3-vports.patch @@ -0,0 +1,243 @@ +From: James Smart +Date: Sun, 22 Mar 2020 11:12:56 -0700 +Subject: scsi: lpfc: Fix scsi host template for SLI3 vports +Patch-mainline: v5.7-rc1 +Git-commit: c90b448023582200c54595232e7c004c93d52ae1 +References: bsc#1164777 bsc#1164780 bsc#1165211 + +SCSI layer sends driver IOs with more s/g segments than driver can handle. +This results in "Too many sg segments from dma_map_sg. Config 64, seg_cnt +219" error messages from the lpfc_scsi_prep_dma_buf_s3() routine. + +The was due to use the driver using individual templates for pport and +vport, host reset enabled or not, nvme vs scsi, etc. In the end, there was +a combination for a vport that didn't match the pport. + +Rather than enumerating more templates and more discretionary assignments, +revert to a base template that is copied to a template specific to the +pport/vport. Then, based on role, attributes and sli type, modify the +fields that are different for that port. Added a log message to +lpfc_create_port to validate values. + +Link: https://lore.kernel.org/r/20200322181304.37655-5-jsmart2021@gmail.com +Signed-off-by: James Smart +Signed-off-by: Dick Kennedy +Signed-off-by: Martin K. Petersen +Acked-by: Daniel Wagner +--- + drivers/scsi/lpfc/lpfc.h | 5 ++ + drivers/scsi/lpfc/lpfc_crtn.h | 2 - + drivers/scsi/lpfc/lpfc_init.c | 75 ++++++++++++++++++++++++++++-------------- + drivers/scsi/lpfc/lpfc_scsi.c | 50 ---------------------------- + 4 files changed, 55 insertions(+), 77 deletions(-) + +--- a/drivers/scsi/lpfc/lpfc.h ++++ b/drivers/scsi/lpfc/lpfc.h +@@ -1224,6 +1224,11 @@ struct lpfc_hba { + #define LPFC_POLL_SLOWPATH 1 /* called from slowpath */ + + char os_host_name[MAXHOSTNAMELEN]; ++ ++ /* SCSI host template information - for physical port */ ++ struct scsi_host_template port_template; ++ /* SCSI host template information - for all vports */ ++ struct scsi_host_template vport_template; + }; + + static inline struct Scsi_Host * +--- a/drivers/scsi/lpfc/lpfc_crtn.h ++++ b/drivers/scsi/lpfc/lpfc_crtn.h +@@ -404,9 +404,7 @@ void lpfc_free_sysfs_attr(struct lpfc_vp + extern struct device_attribute *lpfc_hba_attrs[]; + extern struct device_attribute *lpfc_vport_attrs[]; + extern struct scsi_host_template lpfc_template; +-extern struct scsi_host_template lpfc_template_no_hr; + extern struct scsi_host_template lpfc_template_nvme; +-extern struct scsi_host_template lpfc_vport_template; + extern struct fc_function_template lpfc_transport_functions; + extern struct fc_function_template lpfc_vport_transport_functions; + +--- a/drivers/scsi/lpfc/lpfc_init.c ++++ b/drivers/scsi/lpfc/lpfc_init.c +@@ -4232,6 +4232,7 @@ lpfc_create_port(struct lpfc_hba *phba, + { + struct lpfc_vport *vport; + struct Scsi_Host *shost = NULL; ++ struct scsi_host_template *template; + int error = 0; + int i; + uint64_t wwn; +@@ -4260,22 +4261,50 @@ lpfc_create_port(struct lpfc_hba *phba, + } + } + +- if (phba->cfg_enable_fc4_type & LPFC_ENABLE_FCP) { +- if (dev != &phba->pcidev->dev) { +- shost = scsi_host_alloc(&lpfc_vport_template, +- sizeof(struct lpfc_vport)); ++ /* Seed template for SCSI host registration */ ++ if (dev == &phba->pcidev->dev) { ++ template = &phba->port_template; ++ ++ if (phba->cfg_enable_fc4_type & LPFC_ENABLE_FCP) { ++ /* Seed physical port template */ ++ memcpy(template, &lpfc_template, sizeof(*template)); ++ ++ if (use_no_reset_hba) { ++ /* template is for a no reset SCSI Host */ ++ template->max_sectors = 0xffff; ++ template->eh_host_reset_handler = NULL; ++ } ++ ++ /* Template for all vports this physical port creates */ ++ memcpy(&phba->vport_template, &lpfc_template, ++ sizeof(*template)); ++ phba->vport_template.max_sectors = 0xffff; ++ phba->vport_template.shost_attrs = lpfc_vport_attrs; ++ phba->vport_template.eh_bus_reset_handler = NULL; ++ phba->vport_template.eh_host_reset_handler = NULL; ++ phba->vport_template.vendor_id = 0; ++ ++ /* Initialize the host templates with updated value */ ++ if (phba->sli_rev == LPFC_SLI_REV4) { ++ template->sg_tablesize = phba->cfg_scsi_seg_cnt; ++ phba->vport_template.sg_tablesize = ++ phba->cfg_scsi_seg_cnt; ++ } else { ++ template->sg_tablesize = phba->cfg_sg_seg_cnt; ++ phba->vport_template.sg_tablesize = ++ phba->cfg_sg_seg_cnt; ++ } ++ + } else { +- if (!use_no_reset_hba) +- shost = scsi_host_alloc(&lpfc_template, +- sizeof(struct lpfc_vport)); +- else +- shost = scsi_host_alloc(&lpfc_template_no_hr, +- sizeof(struct lpfc_vport)); +- } +- } else if (phba->cfg_enable_fc4_type & LPFC_ENABLE_NVME) { +- shost = scsi_host_alloc(&lpfc_template_nvme, +- sizeof(struct lpfc_vport)); ++ /* NVMET is for physical port only */ ++ memcpy(template, &lpfc_template_nvme, ++ sizeof(*template)); ++ } ++ } else { ++ template = &phba->vport_template; + } ++ ++ shost = scsi_host_alloc(template, sizeof(struct lpfc_vport)); + if (!shost) + goto out; + +@@ -4330,6 +4359,12 @@ lpfc_create_port(struct lpfc_hba *phba, + vport->port_type = LPFC_PHYSICAL_PORT; + } + ++ lpfc_printf_log(phba, KERN_INFO, LOG_INIT | LOG_FCP, ++ "9081 CreatePort TMPLATE type %x TBLsize %d " ++ "SEGcnt %d/%d\n", ++ vport->port_type, shost->sg_tablesize, ++ phba->cfg_scsi_seg_cnt, phba->cfg_sg_seg_cnt); ++ + /* Initialize all internally managed lists. */ + INIT_LIST_HEAD(&vport->fc_nodes); + INIT_LIST_HEAD(&vport->rcv_buffer_list); +@@ -6301,11 +6336,6 @@ lpfc_sli_driver_resource_setup(struct lp + * used to create the sg_dma_buf_pool must be dynamically calculated. + */ + +- /* Initialize the host templates the configured values. */ +- lpfc_vport_template.sg_tablesize = phba->cfg_sg_seg_cnt; +- lpfc_template_no_hr.sg_tablesize = phba->cfg_sg_seg_cnt; +- lpfc_template.sg_tablesize = phba->cfg_sg_seg_cnt; +- + if (phba->sli_rev == LPFC_SLI_REV4) + entry_sz = sizeof(struct sli4_sge); + else +@@ -6346,7 +6376,7 @@ lpfc_sli_driver_resource_setup(struct lp + } + + lpfc_printf_log(phba, KERN_INFO, LOG_INIT | LOG_FCP, +- "9088 sg_tablesize:%d dmabuf_size:%d total_bde:%d\n", ++ "9088 INIT sg_tablesize:%d dmabuf_size:%d total_bde:%d\n", + phba->cfg_sg_seg_cnt, phba->cfg_sg_dma_buf_size, + phba->cfg_total_seg_cnt); + +@@ -6816,11 +6846,6 @@ lpfc_sli4_driver_resource_setup(struct l + phba->cfg_nvme_seg_cnt = phba->cfg_sg_seg_cnt; + } + +- /* Initialize the host templates with the updated values. */ +- lpfc_vport_template.sg_tablesize = phba->cfg_scsi_seg_cnt; +- lpfc_template.sg_tablesize = phba->cfg_scsi_seg_cnt; +- lpfc_template_no_hr.sg_tablesize = phba->cfg_scsi_seg_cnt; +- + lpfc_printf_log(phba, KERN_INFO, LOG_INIT | LOG_FCP, + "9087 sg_seg_cnt:%d dmabuf_size:%d " + "total:%d scsi:%d nvme:%d\n", +--- a/drivers/scsi/lpfc/lpfc_scsi.c ++++ b/drivers/scsi/lpfc/lpfc_scsi.c +@@ -6024,32 +6024,6 @@ struct scsi_host_template lpfc_template_ + .track_queue_depth = 0, + }; + +-struct scsi_host_template lpfc_template_no_hr = { +- .module = THIS_MODULE, +- .name = LPFC_DRIVER_NAME, +- .proc_name = LPFC_DRIVER_NAME, +- .info = lpfc_info, +- .queuecommand = lpfc_queuecommand, +- .eh_timed_out = fc_eh_timed_out, +- .eh_abort_handler = lpfc_abort_handler, +- .eh_device_reset_handler = lpfc_device_reset_handler, +- .eh_target_reset_handler = lpfc_target_reset_handler, +- .eh_bus_reset_handler = lpfc_bus_reset_handler, +- .slave_alloc = lpfc_slave_alloc, +- .slave_configure = lpfc_slave_configure, +- .slave_destroy = lpfc_slave_destroy, +- .scan_finished = lpfc_scan_finished, +- .this_id = -1, +- .sg_tablesize = LPFC_DEFAULT_SG_SEG_CNT, +- .cmd_per_lun = LPFC_CMD_PER_LUN, +- .use_clustering = ENABLE_CLUSTERING, +- .shost_attrs = lpfc_hba_attrs, +- .max_sectors = 0xFFFFFFFF, +- .vendor_id = LPFC_NL_VENDOR_ID, +- .change_queue_depth = scsi_change_queue_depth, +- .track_queue_depth = 1, +-}; +- + struct scsi_host_template lpfc_template = { + .module = THIS_MODULE, + .name = LPFC_DRIVER_NAME, +@@ -6076,27 +6050,3 @@ struct scsi_host_template lpfc_template + .change_queue_depth = scsi_change_queue_depth, + .track_queue_depth = 1, + }; +- +-struct scsi_host_template lpfc_vport_template = { +- .module = THIS_MODULE, +- .name = LPFC_DRIVER_NAME, +- .proc_name = LPFC_DRIVER_NAME, +- .info = lpfc_info, +- .queuecommand = lpfc_queuecommand, +- .eh_timed_out = fc_eh_timed_out, +- .eh_abort_handler = lpfc_abort_handler, +- .eh_device_reset_handler = lpfc_device_reset_handler, +- .eh_target_reset_handler = lpfc_target_reset_handler, +- .slave_alloc = lpfc_slave_alloc, +- .slave_configure = lpfc_slave_configure, +- .slave_destroy = lpfc_slave_destroy, +- .scan_finished = lpfc_scan_finished, +- .this_id = -1, +- .sg_tablesize = LPFC_DEFAULT_SG_SEG_CNT, +- .cmd_per_lun = LPFC_CMD_PER_LUN, +- .use_clustering = ENABLE_CLUSTERING, +- .shost_attrs = lpfc_vport_attrs, +- .max_sectors = 0xFFFF, +- .change_queue_depth = scsi_change_queue_depth, +- .track_queue_depth = 1, +-}; diff --git a/patches.suse/scsi-lpfc-Fix-unmap-of-dpp-bars-affecting-next-drive.patch b/patches.suse/scsi-lpfc-Fix-unmap-of-dpp-bars-affecting-next-drive.patch new file mode 100644 index 0000000..52859b1 --- /dev/null +++ b/patches.suse/scsi-lpfc-Fix-unmap-of-dpp-bars-affecting-next-drive.patch @@ -0,0 +1,33 @@ +From: James Smart +Date: Wed, 18 Dec 2019 15:58:05 -0800 +Subject: scsi: lpfc: Fix unmap of dpp bars affecting next driver load +Patch-mainline: v5.6-rc1 +Git-commit: 0b4391946da872e825efa3edfa932e44ae6e9cf9 +References: bsc#1164777 bsc#1164780 bsc#1165211 + +When unattaching, the driver did not unmap the DPP bar. This caused the +next load of the driver, which attempts to enable wc, to not work correctly +and wc to be disabled due to an address mapping overlap. + +Fix by unmapping on unattach. + +Link: https://lore.kernel.org/r/20191218235808.31922-8-jsmart2021@gmail.com +Signed-off-by: Dick Kennedy +Signed-off-by: James Smart +Signed-off-by: Martin K. Petersen +Acked-by: Daniel Wagner +--- + drivers/scsi/lpfc/lpfc_init.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/drivers/scsi/lpfc/lpfc_init.c ++++ b/drivers/scsi/lpfc/lpfc_init.c +@@ -10441,6 +10441,8 @@ lpfc_sli4_pci_mem_unset(struct lpfc_hba + case LPFC_SLI_INTF_IF_TYPE_6: + iounmap(phba->sli4_hba.drbl_regs_memmap_p); + iounmap(phba->sli4_hba.conf_regs_memmap_p); ++ if (phba->sli4_hba.dpp_regs_memmap_p) ++ iounmap(phba->sli4_hba.dpp_regs_memmap_p); + break; + case LPFC_SLI_INTF_IF_TYPE_1: + default: diff --git a/patches.suse/scsi-lpfc-Fix-update-of-wq-consumer-index-in-lpfc_sl.patch b/patches.suse/scsi-lpfc-Fix-update-of-wq-consumer-index-in-lpfc_sl.patch new file mode 100644 index 0000000..7329b6e --- /dev/null +++ b/patches.suse/scsi-lpfc-Fix-update-of-wq-consumer-index-in-lpfc_sl.patch @@ -0,0 +1,54 @@ +From: James Smart +Date: Sun, 22 Mar 2020 11:12:58 -0700 +Subject: scsi: lpfc: Fix update of wq consumer index in lpfc_sli4_wq_release +Patch-mainline: v5.7-rc1 +Git-commit: 1543af381e7b784fbc896047a037b6d9ee6e9b6f +References: bsc#1164777 bsc#1164780 bsc#1165211 + +The lpfc_sli4_wq_release() routine iterates for each interim value when +updating the wq consuemr index. This wastes cycles and possibly confuses +things as thevalue itterates (and the modulo logic is being applied). + +There's no reason for this. Just set it to the value from the hw. + +Link: https://lore.kernel.org/r/20200322181304.37655-7-jsmart2021@gmail.com +Signed-off-by: James Smart +Signed-off-by: Dick Kennedy +Signed-off-by: Martin K. Petersen +Acked-by: Daniel Wagner +--- + drivers/scsi/lpfc/lpfc_sli.c | 17 ++++------------- + 1 file changed, 4 insertions(+), 13 deletions(-) + +--- a/drivers/scsi/lpfc/lpfc_sli.c ++++ b/drivers/scsi/lpfc/lpfc_sli.c +@@ -230,25 +230,16 @@ lpfc_sli4_wq_put(struct lpfc_queue *q, u + * This routine will update the HBA index of a queue to reflect consumption of + * Work Queue Entries by the HBA. When the HBA indicates that it has consumed + * an entry the host calls this function to update the queue's internal +- * pointers. This routine returns the number of entries that were consumed by +- * the HBA. ++ * pointers. + **/ +-static uint32_t ++static void + lpfc_sli4_wq_release(struct lpfc_queue *q, uint32_t index) + { +- uint32_t released = 0; +- + /* sanity check on queue memory */ + if (unlikely(!q)) +- return 0; ++ return; + +- if (q->hba_index == index) +- return 0; +- do { +- q->hba_index = ((q->hba_index + 1) % q->entry_count); +- released++; +- } while (q->hba_index != index); +- return released; ++ q->hba_index = index; + } + + /** diff --git a/patches.suse/scsi-lpfc-Make-debugfs-ktime-stats-generic-for-NVME-.patch b/patches.suse/scsi-lpfc-Make-debugfs-ktime-stats-generic-for-NVME-.patch new file mode 100644 index 0000000..a6fa75e --- /dev/null +++ b/patches.suse/scsi-lpfc-Make-debugfs-ktime-stats-generic-for-NVME-.patch @@ -0,0 +1,464 @@ +From 2fcbc569b9f51810d01f23b780ce5f5ef72410b9 Mon Sep 17 00:00:00 2001 +From: James Smart +Date: Sun, 22 Mar 2020 11:13:02 -0700 +Subject: [PATCH] scsi: lpfc: Make debugfs ktime stats generic for NVME and + SCSI + +References: bsc#1164777 bsc#1164780 bsc#1165211 +Patch-mainline: v5.7-rc1 +Git-commit: 2fcbc569b9f51810d01f23b780ce5f5ef72410b9 + +Currently driver ktime stats, measuring code paths, is NVME-specific. + +Convert the stats routines such that the code paths are generic, providing +status for NVME and SCSI. Added ktime stat calls in SCSI queuecommand and +cmpl routines. + +Link: https://lore.kernel.org/r/20200322181304.37655-11-jsmart2021@gmail.com +Signed-off-by: James Smart +Signed-off-by: Dick Kennedy +Signed-off-by: Martin K. Petersen +Acked-by: Daniel Wagner +--- + drivers/scsi/lpfc/lpfc.h | 2 +- + drivers/scsi/lpfc/lpfc_crtn.h | 1 + + drivers/scsi/lpfc/lpfc_debugfs.c | 129 +++++++++++++++++++++++++------ + drivers/scsi/lpfc/lpfc_debugfs.h | 2 +- + drivers/scsi/lpfc/lpfc_nvme.c | 88 +-------------------- + drivers/scsi/lpfc/lpfc_scsi.c | 23 ++++++ + drivers/scsi/lpfc/lpfc_sli.h | 2 +- + 7 files changed, 137 insertions(+), 110 deletions(-) + +diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h +index e4924b9fa69c..747eda6ff8a4 100644 +--- a/drivers/scsi/lpfc/lpfc.h ++++ b/drivers/scsi/lpfc/lpfc.h +@@ -480,7 +480,7 @@ struct lpfc_vport { + struct dentry *debug_nodelist; + struct dentry *debug_nvmestat; + struct dentry *debug_scsistat; +- struct dentry *debug_nvmektime; ++ struct dentry *debug_ioktime; + struct dentry *debug_hdwqstat; + struct dentry *vport_debugfs_root; + struct lpfc_debugfs_trc *disc_trc; +diff --git a/drivers/scsi/lpfc/lpfc_crtn.h b/drivers/scsi/lpfc/lpfc_crtn.h +index a0ef3bac0612..76dc8d9493d2 100644 +--- a/drivers/scsi/lpfc/lpfc_crtn.h ++++ b/drivers/scsi/lpfc/lpfc_crtn.h +@@ -588,6 +588,7 @@ struct lpfc_io_buf *lpfc_get_io_buf(struct lpfc_hba *phba, + int); + void lpfc_release_io_buf(struct lpfc_hba *phba, struct lpfc_io_buf *ncmd, + struct lpfc_sli4_hdw_queue *qp); ++void lpfc_io_ktime(struct lpfc_hba *phba, struct lpfc_io_buf *ncmd); + void lpfc_nvme_cmd_template(void); + void lpfc_nvmet_cmd_template(void); + void lpfc_nvme_cancel_iocb(struct lpfc_hba *phba, struct lpfc_iocbq *pwqeIn); +diff --git a/drivers/scsi/lpfc/lpfc_debugfs.c b/drivers/scsi/lpfc/lpfc_debugfs.c +index 1b8be1006cbe..8a6e02aa553f 100644 +--- a/drivers/scsi/lpfc/lpfc_debugfs.c ++++ b/drivers/scsi/lpfc/lpfc_debugfs.c +@@ -1300,8 +1300,88 @@ lpfc_debugfs_scsistat_data(struct lpfc_vport *vport, char *buf, int size) + return len; + } + ++void ++lpfc_io_ktime(struct lpfc_hba *phba, struct lpfc_io_buf *lpfc_cmd) ++{ ++ uint64_t seg1, seg2, seg3, seg4; ++ uint64_t segsum; ++ ++ if (!lpfc_cmd->ts_last_cmd || ++ !lpfc_cmd->ts_cmd_start || ++ !lpfc_cmd->ts_cmd_wqput || ++ !lpfc_cmd->ts_isr_cmpl || ++ !lpfc_cmd->ts_data_io) ++ return; ++ ++ if (lpfc_cmd->ts_data_io < lpfc_cmd->ts_cmd_start) ++ return; ++ if (lpfc_cmd->ts_cmd_start < lpfc_cmd->ts_last_cmd) ++ return; ++ if (lpfc_cmd->ts_cmd_wqput < lpfc_cmd->ts_cmd_start) ++ return; ++ if (lpfc_cmd->ts_isr_cmpl < lpfc_cmd->ts_cmd_wqput) ++ return; ++ if (lpfc_cmd->ts_data_io < lpfc_cmd->ts_isr_cmpl) ++ return; ++ /* ++ * Segment 1 - Time from Last FCP command cmpl is handed ++ * off to NVME Layer to start of next command. ++ * Segment 2 - Time from Driver receives a IO cmd start ++ * from NVME Layer to WQ put is done on IO cmd. ++ * Segment 3 - Time from Driver WQ put is done on IO cmd ++ * to MSI-X ISR for IO cmpl. ++ * Segment 4 - Time from MSI-X ISR for IO cmpl to when ++ * cmpl is handled off to the NVME Layer. ++ */ ++ seg1 = lpfc_cmd->ts_cmd_start - lpfc_cmd->ts_last_cmd; ++ if (seg1 > 5000000) /* 5 ms - for sequential IOs only */ ++ seg1 = 0; ++ ++ /* Calculate times relative to start of IO */ ++ seg2 = (lpfc_cmd->ts_cmd_wqput - lpfc_cmd->ts_cmd_start); ++ segsum = seg2; ++ seg3 = lpfc_cmd->ts_isr_cmpl - lpfc_cmd->ts_cmd_start; ++ if (segsum > seg3) ++ return; ++ seg3 -= segsum; ++ segsum += seg3; ++ ++ seg4 = lpfc_cmd->ts_data_io - lpfc_cmd->ts_cmd_start; ++ if (segsum > seg4) ++ return; ++ seg4 -= segsum; ++ ++ phba->ktime_data_samples++; ++ phba->ktime_seg1_total += seg1; ++ if (seg1 < phba->ktime_seg1_min) ++ phba->ktime_seg1_min = seg1; ++ else if (seg1 > phba->ktime_seg1_max) ++ phba->ktime_seg1_max = seg1; ++ phba->ktime_seg2_total += seg2; ++ if (seg2 < phba->ktime_seg2_min) ++ phba->ktime_seg2_min = seg2; ++ else if (seg2 > phba->ktime_seg2_max) ++ phba->ktime_seg2_max = seg2; ++ phba->ktime_seg3_total += seg3; ++ if (seg3 < phba->ktime_seg3_min) ++ phba->ktime_seg3_min = seg3; ++ else if (seg3 > phba->ktime_seg3_max) ++ phba->ktime_seg3_max = seg3; ++ phba->ktime_seg4_total += seg4; ++ if (seg4 < phba->ktime_seg4_min) ++ phba->ktime_seg4_min = seg4; ++ else if (seg4 > phba->ktime_seg4_max) ++ phba->ktime_seg4_max = seg4; ++ ++ lpfc_cmd->ts_last_cmd = 0; ++ lpfc_cmd->ts_cmd_start = 0; ++ lpfc_cmd->ts_cmd_wqput = 0; ++ lpfc_cmd->ts_isr_cmpl = 0; ++ lpfc_cmd->ts_data_io = 0; ++} ++ + /** +- * lpfc_debugfs_nvmektime_data - Dump target node list to a buffer ++ * lpfc_debugfs_ioktime_data - Dump target node list to a buffer + * @vport: The vport to gather target node info from. + * @buf: The buffer to dump log into. + * @size: The maximum amount of data to process. +@@ -1314,13 +1394,13 @@ lpfc_debugfs_scsistat_data(struct lpfc_vport *vport, char *buf, int size) + * not exceed @size. + **/ + static int +-lpfc_debugfs_nvmektime_data(struct lpfc_vport *vport, char *buf, int size) ++lpfc_debugfs_ioktime_data(struct lpfc_vport *vport, char *buf, int size) + { + struct lpfc_hba *phba = vport->phba; + int len = 0; + + if (phba->nvmet_support == 0) { +- /* NVME Initiator */ ++ /* Initiator */ + len += scnprintf(buf + len, PAGE_SIZE - len, + "ktime %s: Total Samples: %lld\n", + (phba->ktime_on ? "Enabled" : "Disabled"), +@@ -1330,8 +1410,8 @@ lpfc_debugfs_nvmektime_data(struct lpfc_vport *vport, char *buf, int size) + + len += scnprintf( + buf + len, PAGE_SIZE - len, +- "Segment 1: Last NVME Cmd cmpl " +- "done -to- Start of next NVME cnd (in driver)\n"); ++ "Segment 1: Last Cmd cmpl " ++ "done -to- Start of next Cmd (in driver)\n"); + len += scnprintf( + buf + len, PAGE_SIZE - len, + "avg:%08lld min:%08lld max %08lld\n", +@@ -1341,7 +1421,7 @@ lpfc_debugfs_nvmektime_data(struct lpfc_vport *vport, char *buf, int size) + phba->ktime_seg1_max); + len += scnprintf( + buf + len, PAGE_SIZE - len, +- "Segment 2: Driver start of NVME cmd " ++ "Segment 2: Driver start of Cmd " + "-to- Firmware WQ doorbell\n"); + len += scnprintf( + buf + len, PAGE_SIZE - len, +@@ -1364,7 +1444,7 @@ lpfc_debugfs_nvmektime_data(struct lpfc_vport *vport, char *buf, int size) + len += scnprintf( + buf + len, PAGE_SIZE - len, + "Segment 4: MSI-X ISR cmpl -to- " +- "NVME cmpl done\n"); ++ "Cmd cmpl done\n"); + len += scnprintf( + buf + len, PAGE_SIZE - len, + "avg:%08lld min:%08lld max %08lld\n", +@@ -2727,7 +2807,7 @@ lpfc_debugfs_scsistat_write(struct file *file, const char __user *buf, + } + + static int +-lpfc_debugfs_nvmektime_open(struct inode *inode, struct file *file) ++lpfc_debugfs_ioktime_open(struct inode *inode, struct file *file) + { + struct lpfc_vport *vport = inode->i_private; + struct lpfc_debug *debug; +@@ -2738,14 +2818,14 @@ lpfc_debugfs_nvmektime_open(struct inode *inode, struct file *file) + goto out; + + /* Round to page boundary */ +- debug->buffer = kmalloc(LPFC_NVMEKTIME_SIZE, GFP_KERNEL); ++ debug->buffer = kmalloc(LPFC_IOKTIME_SIZE, GFP_KERNEL); + if (!debug->buffer) { + kfree(debug); + goto out; + } + +- debug->len = lpfc_debugfs_nvmektime_data(vport, debug->buffer, +- LPFC_NVMEKTIME_SIZE); ++ debug->len = lpfc_debugfs_ioktime_data(vport, debug->buffer, ++ LPFC_IOKTIME_SIZE); + + debug->i_private = inode->i_private; + file->private_data = debug; +@@ -2756,8 +2836,8 @@ lpfc_debugfs_nvmektime_open(struct inode *inode, struct file *file) + } + + static ssize_t +-lpfc_debugfs_nvmektime_write(struct file *file, const char __user *buf, +- size_t nbytes, loff_t *ppos) ++lpfc_debugfs_ioktime_write(struct file *file, const char __user *buf, ++ size_t nbytes, loff_t *ppos) + { + struct lpfc_debug *debug = file->private_data; + struct lpfc_vport *vport = (struct lpfc_vport *)debug->i_private; +@@ -5467,13 +5547,13 @@ static const struct file_operations lpfc_debugfs_op_scsistat = { + .release = lpfc_debugfs_release, + }; + +-#undef lpfc_debugfs_op_nvmektime +-static const struct file_operations lpfc_debugfs_op_nvmektime = { ++#undef lpfc_debugfs_op_ioktime ++static const struct file_operations lpfc_debugfs_op_ioktime = { + .owner = THIS_MODULE, +- .open = lpfc_debugfs_nvmektime_open, ++ .open = lpfc_debugfs_ioktime_open, + .llseek = lpfc_debugfs_lseek, + .read = lpfc_debugfs_read, +- .write = lpfc_debugfs_nvmektime_write, ++ .write = lpfc_debugfs_ioktime_write, + .release = lpfc_debugfs_release, + }; + +@@ -6111,11 +6191,16 @@ lpfc_debugfs_initialize(struct lpfc_vport *vport) + goto debug_failed; + } + +- snprintf(name, sizeof(name), "nvmektime"); +- vport->debug_nvmektime = ++ snprintf(name, sizeof(name), "ioktime"); ++ vport->debug_ioktime = + debugfs_create_file(name, 0644, + vport->vport_debugfs_root, +- vport, &lpfc_debugfs_op_nvmektime); ++ vport, &lpfc_debugfs_op_ioktime); ++ if (!vport->debug_ioktime) { ++ lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT, ++ "0815 Cannot create debugfs ioktime\n"); ++ goto debug_failed; ++ } + + snprintf(name, sizeof(name), "hdwqstat"); + vport->debug_hdwqstat = +@@ -6252,8 +6337,8 @@ lpfc_debugfs_terminate(struct lpfc_vport *vport) + debugfs_remove(vport->debug_scsistat); /* scsistat */ + vport->debug_scsistat = NULL; + +- debugfs_remove(vport->debug_nvmektime); /* nvmektime */ +- vport->debug_nvmektime = NULL; ++ debugfs_remove(vport->debug_ioktime); /* ioktime */ ++ vport->debug_ioktime = NULL; + + debugfs_remove(vport->debug_hdwqstat); /* hdwqstat */ + vport->debug_hdwqstat = NULL; +diff --git a/drivers/scsi/lpfc/lpfc_debugfs.h b/drivers/scsi/lpfc/lpfc_debugfs.h +index 6643b9bfd4f3..7ab6d3b08698 100644 +--- a/drivers/scsi/lpfc/lpfc_debugfs.h ++++ b/drivers/scsi/lpfc/lpfc_debugfs.h +@@ -46,7 +46,7 @@ + + /* nvmestat output buffer size */ + #define LPFC_NVMESTAT_SIZE 8192 +-#define LPFC_NVMEKTIME_SIZE 8192 ++#define LPFC_IOKTIME_SIZE 8192 + #define LPFC_NVMEIO_TRC_SIZE 8192 + + /* scsistat output buffer size */ +diff --git a/drivers/scsi/lpfc/lpfc_nvme.c b/drivers/scsi/lpfc/lpfc_nvme.c +index 38936b7ce043..0db052a5f542 100644 +--- a/drivers/scsi/lpfc/lpfc_nvme.c ++++ b/drivers/scsi/lpfc/lpfc_nvme.c +@@ -899,88 +899,6 @@ lpfc_nvme_adj_fcp_sgls(struct lpfc_vport *vport, + sgl->sge_len = cpu_to_le32(nCmd->rsplen); + } + +-#ifdef CONFIG_SCSI_LPFC_DEBUG_FS +-static void +-lpfc_nvme_ktime(struct lpfc_hba *phba, +- struct lpfc_io_buf *lpfc_ncmd) +-{ +- uint64_t seg1, seg2, seg3, seg4; +- uint64_t segsum; +- +- if (!lpfc_ncmd->ts_last_cmd || +- !lpfc_ncmd->ts_cmd_start || +- !lpfc_ncmd->ts_cmd_wqput || +- !lpfc_ncmd->ts_isr_cmpl || +- !lpfc_ncmd->ts_data_nvme) +- return; +- +- if (lpfc_ncmd->ts_data_nvme < lpfc_ncmd->ts_cmd_start) +- return; +- if (lpfc_ncmd->ts_cmd_start < lpfc_ncmd->ts_last_cmd) +- return; +- if (lpfc_ncmd->ts_cmd_wqput < lpfc_ncmd->ts_cmd_start) +- return; +- if (lpfc_ncmd->ts_isr_cmpl < lpfc_ncmd->ts_cmd_wqput) +- return; +- if (lpfc_ncmd->ts_data_nvme < lpfc_ncmd->ts_isr_cmpl) +- return; +- /* +- * Segment 1 - Time from Last FCP command cmpl is handed +- * off to NVME Layer to start of next command. +- * Segment 2 - Time from Driver receives a IO cmd start +- * from NVME Layer to WQ put is done on IO cmd. +- * Segment 3 - Time from Driver WQ put is done on IO cmd +- * to MSI-X ISR for IO cmpl. +- * Segment 4 - Time from MSI-X ISR for IO cmpl to when +- * cmpl is handled off to the NVME Layer. +- */ +- seg1 = lpfc_ncmd->ts_cmd_start - lpfc_ncmd->ts_last_cmd; +- if (seg1 > 5000000) /* 5 ms - for sequential IOs only */ +- seg1 = 0; +- +- /* Calculate times relative to start of IO */ +- seg2 = (lpfc_ncmd->ts_cmd_wqput - lpfc_ncmd->ts_cmd_start); +- segsum = seg2; +- seg3 = lpfc_ncmd->ts_isr_cmpl - lpfc_ncmd->ts_cmd_start; +- if (segsum > seg3) +- return; +- seg3 -= segsum; +- segsum += seg3; +- +- seg4 = lpfc_ncmd->ts_data_nvme - lpfc_ncmd->ts_cmd_start; +- if (segsum > seg4) +- return; +- seg4 -= segsum; +- +- phba->ktime_data_samples++; +- phba->ktime_seg1_total += seg1; +- if (seg1 < phba->ktime_seg1_min) +- phba->ktime_seg1_min = seg1; +- else if (seg1 > phba->ktime_seg1_max) +- phba->ktime_seg1_max = seg1; +- phba->ktime_seg2_total += seg2; +- if (seg2 < phba->ktime_seg2_min) +- phba->ktime_seg2_min = seg2; +- else if (seg2 > phba->ktime_seg2_max) +- phba->ktime_seg2_max = seg2; +- phba->ktime_seg3_total += seg3; +- if (seg3 < phba->ktime_seg3_min) +- phba->ktime_seg3_min = seg3; +- else if (seg3 > phba->ktime_seg3_max) +- phba->ktime_seg3_max = seg3; +- phba->ktime_seg4_total += seg4; +- if (seg4 < phba->ktime_seg4_min) +- phba->ktime_seg4_min = seg4; +- else if (seg4 > phba->ktime_seg4_max) +- phba->ktime_seg4_max = seg4; +- +- lpfc_ncmd->ts_last_cmd = 0; +- lpfc_ncmd->ts_cmd_start = 0; +- lpfc_ncmd->ts_cmd_wqput = 0; +- lpfc_ncmd->ts_isr_cmpl = 0; +- lpfc_ncmd->ts_data_nvme = 0; +-} +-#endif + + /** + * lpfc_nvme_io_cmd_wqe_cmpl - Complete an NVME-over-FCP IO +@@ -1183,9 +1101,9 @@ lpfc_nvme_io_cmd_wqe_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pwqeIn, + #ifdef CONFIG_SCSI_LPFC_DEBUG_FS + if (lpfc_ncmd->ts_cmd_start) { + lpfc_ncmd->ts_isr_cmpl = pwqeIn->isr_timestamp; +- lpfc_ncmd->ts_data_nvme = ktime_get_ns(); +- phba->ktime_last_cmd = lpfc_ncmd->ts_data_nvme; +- lpfc_nvme_ktime(phba, lpfc_ncmd); ++ lpfc_ncmd->ts_data_io = ktime_get_ns(); ++ phba->ktime_last_cmd = lpfc_ncmd->ts_data_io; ++ lpfc_io_ktime(phba, lpfc_ncmd); + } + if (unlikely(phba->hdwqstat_on & LPFC_CHECK_NVME_IO)) { + cpu = raw_smp_processor_id(); +diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c +index 3caa4fd2b55f..ad62fb3f3a54 100644 +--- a/drivers/scsi/lpfc/lpfc_scsi.c ++++ b/drivers/scsi/lpfc/lpfc_scsi.c +@@ -4025,6 +4025,14 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn, + lpfc_cmd->pCmd = NULL; + spin_unlock(&lpfc_cmd->buf_lock); + ++#ifdef CONFIG_SCSI_LPFC_DEBUG_FS ++ if (lpfc_cmd->ts_cmd_start) { ++ lpfc_cmd->ts_isr_cmpl = pIocbIn->isr_timestamp; ++ lpfc_cmd->ts_data_io = ktime_get_ns(); ++ phba->ktime_last_cmd = lpfc_cmd->ts_data_io; ++ lpfc_io_ktime(phba, lpfc_cmd); ++ } ++#endif + /* The sdev is not guaranteed to be valid post scsi_done upcall. */ + cmd->scsi_done(cmd); + +@@ -4497,6 +4505,12 @@ lpfc_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *cmnd) + struct lpfc_io_buf *lpfc_cmd; + struct fc_rport *rport = starget_to_rport(scsi_target(cmnd->device)); + int err, idx; ++#ifdef CONFIG_SCSI_LPFC_DEBUG_FS ++ uint64_t start = 0L; ++ ++ if (phba->ktime_on) ++ start = ktime_get_ns(); ++#endif + + rdata = lpfc_rport_data_from_scsi_device(cmnd->device); + +@@ -4622,6 +4636,15 @@ lpfc_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *cmnd) + #endif + err = lpfc_sli_issue_iocb(phba, LPFC_FCP_RING, + &lpfc_cmd->cur_iocbq, SLI_IOCB_RET_IOCB); ++#ifdef CONFIG_SCSI_LPFC_DEBUG_FS ++ if (start) { ++ lpfc_cmd->ts_cmd_start = start; ++ lpfc_cmd->ts_last_cmd = phba->ktime_last_cmd; ++ lpfc_cmd->ts_cmd_wqput = ktime_get_ns(); ++ } else { ++ lpfc_cmd->ts_cmd_start = 0; ++ } ++#endif + if (err) { + lpfc_printf_vlog(vport, KERN_INFO, LOG_FCP, + "3376 FCP could not issue IOCB err %x" +diff --git a/drivers/scsi/lpfc/lpfc_sli.h b/drivers/scsi/lpfc/lpfc_sli.h +index 7bcf922a8be2..93d976ea8c5d 100644 +--- a/drivers/scsi/lpfc/lpfc_sli.h ++++ b/drivers/scsi/lpfc/lpfc_sli.h +@@ -446,6 +446,6 @@ struct lpfc_io_buf { + uint64_t ts_last_cmd; + uint64_t ts_cmd_wqput; + uint64_t ts_isr_cmpl; +- uint64_t ts_data_nvme; ++ uint64_t ts_data_io; + #endif + }; +-- +2.23.0 + diff --git a/patches.suse/scsi-lpfc-Make-lpfc_defer_acc_rsp-static.patch b/patches.suse/scsi-lpfc-Make-lpfc_defer_acc_rsp-static.patch new file mode 100644 index 0000000..7cc92ad --- /dev/null +++ b/patches.suse/scsi-lpfc-Make-lpfc_defer_acc_rsp-static.patch @@ -0,0 +1,33 @@ +From: YueHaibing +Date: Tue, 7 Jan 2020 09:49:56 +0800 +Subject: scsi: lpfc: Make lpfc_defer_acc_rsp static +Patch-mainline: v5.6-rc1 +Git-commit: fdb827e4a3f84cb92e286a821114ac0ad79c8281 +References: bsc#1164777 bsc#1164780 bsc#1165211 + +Fix sparse warning: + +drivers/scsi/lpfc/lpfc_nportdisc.c:344:1: warning: + symbol 'lpfc_defer_acc_rsp' was not declared. Should it be static? + +Link: https://lore.kernel.org/r/20200107014956.41748-1-yuehaibing@huawei.com +Reported-by: Hulk Robot +Reviewed-by: James Smart +Signed-off-by: YueHaibing +Signed-off-by: Martin K. Petersen +Acked-by: Daniel Wagner +--- + drivers/scsi/lpfc/lpfc_nportdisc.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/scsi/lpfc/lpfc_nportdisc.c ++++ b/drivers/scsi/lpfc/lpfc_nportdisc.c +@@ -340,7 +340,7 @@ lpfc_defer_pt2pt_acc(struct lpfc_hba *ph + * This routine is only called if we are SLI4, acting in target + * mode and the remote NPort issues the PLOGI after link up. + **/ +-void ++static void + lpfc_defer_acc_rsp(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) + { + struct lpfc_vport *vport = pmb->vport; diff --git a/patches.suse/scsi-lpfc-Remove-handler-for-obsolete-ELS-Read-Port-.patch b/patches.suse/scsi-lpfc-Remove-handler-for-obsolete-ELS-Read-Port-.patch new file mode 100644 index 0000000..ac74820 --- /dev/null +++ b/patches.suse/scsi-lpfc-Remove-handler-for-obsolete-ELS-Read-Port-.patch @@ -0,0 +1,322 @@ +From: James Smart +Date: Mon, 27 Jan 2020 16:23:08 -0800 +Subject: scsi: lpfc: Remove handler for obsolete ELS - Read Port Status (RPS) +Patch-mainline: v5.7-rc1 +Git-commit: 6cde2e3e2813f598a39c8e5688480b76b2f40b10 +References: bsc#1164777 bsc#1164780 bsc#1165211 + +There was report of an odd "Fix me..." log message, which was tracked down +to the lpfc_els_rcv_rps() routine. This was in handling of a very old and +obsolete ELS - Read Port Status. The RPS ELS was defined in FC-LS-1, but +deprecated in FC-LS-2, and removed from all later FC-LS revisions. It was +replaced by the Read Diagnostic Parameters (RDP) ELS and the Link Error +Status Block descriptor. + +There should be no support for the RSP ELS. Remove support from driver. + +Link: https://lore.kernel.org/r/20200128002312.16346-9-jsmart2021@gmail.com +Signed-off-by: Dick Kennedy +Signed-off-by: James Smart +Signed-off-by: Martin K. Petersen +Acked-by: Daniel Wagner +--- + drivers/scsi/lpfc/lpfc.h | 1 + drivers/scsi/lpfc/lpfc_els.c | 193 +------------------------------------------ + drivers/scsi/lpfc/lpfc_hw.h | 20 ---- + 3 files changed, 5 insertions(+), 209 deletions(-) + +--- a/drivers/scsi/lpfc/lpfc.h ++++ b/drivers/scsi/lpfc/lpfc.h +@@ -262,7 +262,6 @@ struct lpfc_stats { + uint32_t elsRcvPRLI; + uint32_t elsRcvLIRR; + uint32_t elsRcvRLS; +- uint32_t elsRcvRPS; + uint32_t elsRcvRPL; + uint32_t elsRcvRRQ; + uint32_t elsRcvRTV; +--- a/drivers/scsi/lpfc/lpfc_els.c ++++ b/drivers/scsi/lpfc/lpfc_els.c +@@ -7000,108 +7000,12 @@ lpfc_els_rsp_rls_acc(struct lpfc_hba *ph + } + + /** +- * lpfc_els_rsp_rps_acc - Completion callbk func for MBX_READ_LNK_STAT mbox cmd +- * @phba: pointer to lpfc hba data structure. +- * @pmb: pointer to the driver internal queue element for mailbox command. +- * +- * This routine is the completion callback function for the MBX_READ_LNK_STAT +- * mailbox command. This callback function is to actually send the Accept +- * (ACC) response to a Read Port Status (RPS) unsolicited IOCB event. It +- * collects the link statistics from the completion of the MBX_READ_LNK_STAT +- * mailbox command, constructs the RPS response with the link statistics +- * collected, and then invokes the lpfc_sli_issue_iocb() routine to send ACC +- * response to the RPS. +- * +- * Note that, in lpfc_prep_els_iocb() routine, the reference count of ndlp +- * will be incremented by 1 for holding the ndlp and the reference to ndlp +- * will be stored into the context1 field of the IOCB for the completion +- * callback function to the RPS Accept Response ELS IOCB command. +- * +- **/ +-static void +-lpfc_els_rsp_rps_acc(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) +-{ +- MAILBOX_t *mb; +- IOCB_t *icmd; +- RPS_RSP *rps_rsp; +- uint8_t *pcmd; +- struct lpfc_iocbq *elsiocb; +- struct lpfc_nodelist *ndlp; +- uint16_t status; +- uint16_t oxid; +- uint16_t rxid; +- uint32_t cmdsize; +- +- mb = &pmb->u.mb; +- +- ndlp = (struct lpfc_nodelist *)pmb->ctx_ndlp; +- rxid = (uint16_t)((unsigned long)(pmb->ctx_buf) & 0xffff); +- oxid = (uint16_t)(((unsigned long)(pmb->ctx_buf) >> 16) & 0xffff); +- pmb->ctx_ndlp = NULL; +- pmb->ctx_buf = NULL; +- +- if (mb->mbxStatus) { +- mempool_free(pmb, phba->mbox_mem_pool); +- return; +- } +- +- cmdsize = sizeof(RPS_RSP) + sizeof(uint32_t); +- mempool_free(pmb, phba->mbox_mem_pool); +- elsiocb = lpfc_prep_els_iocb(phba->pport, 0, cmdsize, +- lpfc_max_els_tries, ndlp, +- ndlp->nlp_DID, ELS_CMD_ACC); +- +- /* Decrement the ndlp reference count from previous mbox command */ +- lpfc_nlp_put(ndlp); +- +- if (!elsiocb) +- return; +- +- icmd = &elsiocb->iocb; +- icmd->ulpContext = rxid; +- icmd->unsli3.rcvsli3.ox_id = oxid; +- +- pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt); +- *((uint32_t *) (pcmd)) = ELS_CMD_ACC; +- pcmd += sizeof(uint32_t); /* Skip past command */ +- rps_rsp = (RPS_RSP *)pcmd; +- +- if (phba->fc_topology != LPFC_TOPOLOGY_LOOP) +- status = 0x10; +- else +- status = 0x8; +- if (phba->pport->fc_flag & FC_FABRIC) +- status |= 0x4; +- +- rps_rsp->rsvd1 = 0; +- rps_rsp->portStatus = cpu_to_be16(status); +- rps_rsp->linkFailureCnt = cpu_to_be32(mb->un.varRdLnk.linkFailureCnt); +- rps_rsp->lossSyncCnt = cpu_to_be32(mb->un.varRdLnk.lossSyncCnt); +- rps_rsp->lossSignalCnt = cpu_to_be32(mb->un.varRdLnk.lossSignalCnt); +- rps_rsp->primSeqErrCnt = cpu_to_be32(mb->un.varRdLnk.primSeqErrCnt); +- rps_rsp->invalidXmitWord = cpu_to_be32(mb->un.varRdLnk.invalidXmitWord); +- rps_rsp->crcCnt = cpu_to_be32(mb->un.varRdLnk.crcCnt); +- /* Xmit ELS RPS ACC response tag */ +- lpfc_printf_vlog(ndlp->vport, KERN_INFO, LOG_ELS, +- "0118 Xmit ELS RPS ACC response tag x%x xri x%x, " +- "did x%x, nlp_flag x%x, nlp_state x%x, rpi x%x\n", +- elsiocb->iotag, elsiocb->iocb.ulpContext, +- ndlp->nlp_DID, ndlp->nlp_flag, ndlp->nlp_state, +- ndlp->nlp_rpi); +- elsiocb->iocb_cmpl = lpfc_cmpl_els_rsp; +- phba->fc_stat.elsXmitACC++; +- if (lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, elsiocb, 0) == IOCB_ERROR) +- lpfc_els_free_iocb(phba, elsiocb); +- return; +-} +- +-/** + * lpfc_els_rcv_rls - Process an unsolicited rls iocb + * @vport: pointer to a host virtual N_Port data structure. + * @cmdiocb: pointer to lpfc command iocb data structure. + * @ndlp: pointer to a node-list data structure. + * +- * This routine processes Read Port Status (RPL) IOCB received as an ++ * This routine processes Read Link Status (RLS) IOCB received as an + * ELS unsolicited event. It first checks the remote port state. If the + * remote port is not in NLP_STE_UNMAPPED_NODE state or NLP_STE_MAPPED_NODE + * state, it invokes the lpfc_els_rsl_reject() routine to send the reject +@@ -7123,7 +7027,7 @@ lpfc_els_rcv_rls(struct lpfc_vport *vpor + + if ((ndlp->nlp_state != NLP_STE_UNMAPPED_NODE) && + (ndlp->nlp_state != NLP_STE_MAPPED_NODE)) +- /* reject the unsolicited RPS request and done with it */ ++ /* reject the unsolicited RLS request and done with it */ + goto reject_out; + + mbox = mempool_alloc(phba->mbox_mem_pool, GFP_ATOMIC); +@@ -7171,7 +7075,7 @@ reject_out: + * Note that, in lpfc_prep_els_iocb() routine, the reference count of ndlp + * will be incremented by 1 for holding the ndlp and the reference to ndlp + * will be stored into the context1 field of the IOCB for the completion +- * callback function to the RPS Accept Response ELS IOCB command. ++ * callback function to the RTV Accept Response ELS IOCB command. + * + * Return codes + * 0 - Successfully processed rtv iocb (currently always return 0) +@@ -7190,7 +7094,7 @@ lpfc_els_rcv_rtv(struct lpfc_vport *vpor + + if ((ndlp->nlp_state != NLP_STE_UNMAPPED_NODE) && + (ndlp->nlp_state != NLP_STE_MAPPED_NODE)) +- /* reject the unsolicited RPS request and done with it */ ++ /* reject the unsolicited RTV request and done with it */ + goto reject_out; + + cmdsize = sizeof(struct RTV_RSP) + sizeof(uint32_t); +@@ -7243,84 +7147,7 @@ reject_out: + return 0; + } + +-/* lpfc_els_rcv_rps - Process an unsolicited rps iocb +- * @vport: pointer to a host virtual N_Port data structure. +- * @cmdiocb: pointer to lpfc command iocb data structure. +- * @ndlp: pointer to a node-list data structure. +- * +- * This routine processes Read Port Status (RPS) IOCB received as an +- * ELS unsolicited event. It first checks the remote port state. If the +- * remote port is not in NLP_STE_UNMAPPED_NODE state or NLP_STE_MAPPED_NODE +- * state, it invokes the lpfc_els_rsp_reject() routine to send the reject +- * response. Otherwise, it issue the MBX_READ_LNK_STAT mailbox command +- * for reading the HBA link statistics. It is for the callback function, +- * lpfc_els_rsp_rps_acc(), set to the MBX_READ_LNK_STAT mailbox command +- * to actually sending out RPS Accept (ACC) response. +- * +- * Return codes +- * 0 - Successfully processed rps iocb (currently always return 0) +- **/ +-static int +-lpfc_els_rcv_rps(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, +- struct lpfc_nodelist *ndlp) +-{ +- struct lpfc_hba *phba = vport->phba; +- uint32_t *lp; +- uint8_t flag; +- LPFC_MBOXQ_t *mbox; +- struct lpfc_dmabuf *pcmd; +- RPS *rps; +- struct ls_rjt stat; +- +- if ((ndlp->nlp_state != NLP_STE_UNMAPPED_NODE) && +- (ndlp->nlp_state != NLP_STE_MAPPED_NODE)) +- /* reject the unsolicited RPS request and done with it */ +- goto reject_out; +- +- pcmd = (struct lpfc_dmabuf *) cmdiocb->context2; +- lp = (uint32_t *) pcmd->virt; +- flag = (be32_to_cpu(*lp++) & 0xf); +- rps = (RPS *) lp; +- +- if ((flag == 0) || +- ((flag == 1) && (be32_to_cpu(rps->un.portNum) == 0)) || +- ((flag == 2) && (memcmp(&rps->un.portName, &vport->fc_portname, +- sizeof(struct lpfc_name)) == 0))) { +- +- printk("Fix me....\n"); +- dump_stack(); +- mbox = mempool_alloc(phba->mbox_mem_pool, GFP_ATOMIC); +- if (mbox) { +- lpfc_read_lnk_stat(phba, mbox); +- mbox->ctx_buf = (void *)((unsigned long) +- ((cmdiocb->iocb.unsli3.rcvsli3.ox_id << 16) | +- cmdiocb->iocb.ulpContext)); /* rx_id */ +- mbox->ctx_ndlp = lpfc_nlp_get(ndlp); +- mbox->vport = vport; +- mbox->mbox_cmpl = lpfc_els_rsp_rps_acc; +- if (lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT) +- != MBX_NOT_FINISHED) +- /* Mbox completion will send ELS Response */ +- return 0; +- /* Decrement reference count used for the failed mbox +- * command. +- */ +- lpfc_nlp_put(ndlp); +- mempool_free(mbox, phba->mbox_mem_pool); +- } +- } +- +-reject_out: +- /* issue rejection response */ +- stat.un.b.lsRjtRsvd0 = 0; +- stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC; +- stat.un.b.lsRjtRsnCodeExp = LSEXP_CANT_GIVE_DATA; +- stat.un.b.vendorUnique = 0; +- lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp, NULL); +- return 0; +-} +- +-/* lpfc_issue_els_rrq - Process an unsolicited rps iocb ++/* lpfc_issue_els_rrq - Process an unsolicited rrq iocb + * @vport: pointer to a host virtual N_Port data structure. + * @ndlp: pointer to a node-list data structure. + * @did: DID of the target. +@@ -8497,16 +8324,6 @@ lpfc_els_unsol_buffer(struct lpfc_hba *p + if (newnode) + lpfc_nlp_put(ndlp); + break; +- case ELS_CMD_RPS: +- lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL, +- "RCV RPS: did:x%x/ste:x%x flg:x%x", +- did, vport->port_state, ndlp->nlp_flag); +- +- phba->fc_stat.elsRcvRPS++; +- lpfc_els_rcv_rps(vport, elsiocb, ndlp); +- if (newnode) +- lpfc_nlp_put(ndlp); +- break; + case ELS_CMD_RPL: + lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL, + "RCV RPL: did:x%x/ste:x%x flg:x%x", +--- a/drivers/scsi/lpfc/lpfc_hw.h ++++ b/drivers/scsi/lpfc/lpfc_hw.h +@@ -597,7 +597,6 @@ struct fc_vft_header { + #define ELS_CMD_ADISC 0x52000000 + #define ELS_CMD_FARP 0x54000000 + #define ELS_CMD_FARPR 0x55000000 +-#define ELS_CMD_RPS 0x56000000 + #define ELS_CMD_RPL 0x57000000 + #define ELS_CMD_FAN 0x60000000 + #define ELS_CMD_RSCN 0x61040000 +@@ -638,7 +637,6 @@ struct fc_vft_header { + #define ELS_CMD_ADISC 0x52 + #define ELS_CMD_FARP 0x54 + #define ELS_CMD_FARPR 0x55 +-#define ELS_CMD_RPS 0x56 + #define ELS_CMD_RPL 0x57 + #define ELS_CMD_FAN 0x60 + #define ELS_CMD_RSCN 0x0461 +@@ -917,24 +915,6 @@ typedef struct _RNID { /* Structure is + } un; + } __packed RNID; + +-typedef struct _RPS { /* Structure is in Big Endian format */ +- union { +- uint32_t portNum; +- struct lpfc_name portName; +- } un; +-} RPS; +- +-typedef struct _RPS_RSP { /* Structure is in Big Endian format */ +- uint16_t rsvd1; +- uint16_t portStatus; +- uint32_t linkFailureCnt; +- uint32_t lossSyncCnt; +- uint32_t lossSignalCnt; +- uint32_t primSeqErrCnt; +- uint32_t invalidXmitWord; +- uint32_t crcCnt; +-} RPS_RSP; +- + struct RLS { /* Structure is in Big Endian format */ + uint32_t rls; + #define rls_rsvd_SHIFT 24 diff --git a/patches.suse/scsi-lpfc-Remove-prototype-FIPS-DSS-options-from-SLI.patch b/patches.suse/scsi-lpfc-Remove-prototype-FIPS-DSS-options-from-SLI.patch new file mode 100644 index 0000000..14584af --- /dev/null +++ b/patches.suse/scsi-lpfc-Remove-prototype-FIPS-DSS-options-from-SLI.patch @@ -0,0 +1,278 @@ +From 0e75461a684f64c07da090da24491b6c589a7d15 Mon Sep 17 00:00:00 2001 +From: James Smart +Date: Sun, 22 Mar 2020 11:13:03 -0700 +Subject: [PATCH] scsi: lpfc: Remove prototype FIPS/DSS options from SLI-3 + +References: bsc#1164777 bsc#1164780 bsc#1165211 +Patch-mainline: v5.7-rc1 +Git-commit: 0e75461a684f64c07da090da24491b6c589a7d15 + +During code review, identified dss feature that was a prototype only and +was never productized in SLI3. They shouldn't be there and prevents reuse +of the command areas. + +Remove any code in the driver to deal with dss, including code to deal with +fips, which is associated with the dss feature. + +Link: https://lore.kernel.org/r/20200322181304.37655-12-jsmart2021@gmail.com +Signed-off-by: James Smart +Signed-off-by: Dick Kennedy +Signed-off-by: Martin K. Petersen +Acked-by: Daniel Wagner +--- + drivers/scsi/lpfc/lpfc.h | 9 +---- + drivers/scsi/lpfc/lpfc_attr.c | 69 ----------------------------------- + drivers/scsi/lpfc/lpfc_hw.h | 20 +++------- + drivers/scsi/lpfc/lpfc_mbox.c | 2 - + drivers/scsi/lpfc/lpfc_sli.c | 17 --------- + 5 files changed, 8 insertions(+), 109 deletions(-) + +diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h +index 747eda6ff8a4..8e2a356911a9 100644 +--- a/drivers/scsi/lpfc/lpfc.h ++++ b/drivers/scsi/lpfc/lpfc.h +@@ -207,8 +207,7 @@ typedef struct lpfc_vpd { + } rev; + struct { + #ifdef __BIG_ENDIAN_BITFIELD +- uint32_t rsvd3 :19; /* Reserved */ +- uint32_t cdss : 1; /* Configure Data Security SLI */ ++ uint32_t rsvd3 :20; /* Reserved */ + uint32_t rsvd2 : 3; /* Reserved */ + uint32_t cbg : 1; /* Configure BlockGuard */ + uint32_t cmv : 1; /* Configure Max VPIs */ +@@ -230,8 +229,7 @@ typedef struct lpfc_vpd { + uint32_t cmv : 1; /* Configure Max VPIs */ + uint32_t cbg : 1; /* Configure BlockGuard */ + uint32_t rsvd2 : 3; /* Reserved */ +- uint32_t cdss : 1; /* Configure Data Security SLI */ +- uint32_t rsvd3 :19; /* Reserved */ ++ uint32_t rsvd3 :20; /* Reserved */ + #endif + } sli3Feat; + } lpfc_vpd_t; +@@ -887,7 +885,6 @@ struct lpfc_hba { + #define LPFC_INITIALIZE_LINK 0 /* do normal init_link mbox */ + #define LPFC_DELAY_INIT_LINK 1 /* layered driver hold off */ + #define LPFC_DELAY_INIT_LINK_INDEFINITELY 2 /* wait, manual intervention */ +- uint32_t cfg_enable_dss; + uint32_t cfg_fdmi_on; + #define LPFC_FDMI_NO_SUPPORT 0 /* FDMI not supported */ + #define LPFC_FDMI_SUPPORT 1 /* FDMI supported? */ +@@ -1156,8 +1153,6 @@ struct lpfc_hba { + uint32_t iocb_cnt; + uint32_t iocb_max; + atomic_t sdev_cnt; +- uint8_t fips_spec_rev; +- uint8_t fips_level; + spinlock_t devicelock; /* lock for luns list */ + mempool_t *device_data_mem_pool; + struct list_head luns; +diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c +--- a/drivers/scsi/lpfc/lpfc_attr.c ++++ b/drivers/scsi/lpfc/lpfc_attr.c +@@ -2230,66 +2230,6 @@ lpfc_poll_store(struct device *dev, struct device_attribute *attr, + return strlen(buf); + } + +-/** +- * lpfc_fips_level_show - Return the current FIPS level for the HBA +- * @dev: class unused variable. +- * @attr: device attribute, not used. +- * @buf: on return contains the module description text. +- * +- * Returns: size of formatted string. +- **/ +-static ssize_t +-lpfc_fips_level_show(struct device *dev, struct device_attribute *attr, +- char *buf) +-{ +- struct Scsi_Host *shost = class_to_shost(dev); +- struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata; +- struct lpfc_hba *phba = vport->phba; +- +- return scnprintf(buf, PAGE_SIZE, "%d\n", phba->fips_level); +-} +- +-/** +- * lpfc_fips_rev_show - Return the FIPS Spec revision for the HBA +- * @dev: class unused variable. +- * @attr: device attribute, not used. +- * @buf: on return contains the module description text. +- * +- * Returns: size of formatted string. +- **/ +-static ssize_t +-lpfc_fips_rev_show(struct device *dev, struct device_attribute *attr, +- char *buf) +-{ +- struct Scsi_Host *shost = class_to_shost(dev); +- struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata; +- struct lpfc_hba *phba = vport->phba; +- +- return scnprintf(buf, PAGE_SIZE, "%d\n", phba->fips_spec_rev); +-} +- +-/** +- * lpfc_dss_show - Return the current state of dss and the configured state +- * @dev: class converted to a Scsi_host structure. +- * @attr: device attribute, not used. +- * @buf: on return contains the formatted text. +- * +- * Returns: size of formatted string. +- **/ +-static ssize_t +-lpfc_dss_show(struct device *dev, struct device_attribute *attr, +- char *buf) +-{ +- struct Scsi_Host *shost = class_to_shost(dev); +- struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata; +- struct lpfc_hba *phba = vport->phba; +- +- return scnprintf(buf, PAGE_SIZE, "%s - %sOperational\n", +- (phba->cfg_enable_dss) ? "Enabled" : "Disabled", +- (phba->sli3_options & LPFC_SLI3_DSS_ENABLED) ? +- "" : "Not "); +-} +- + /** + * lpfc_sriov_hw_max_virtfn_show - Return maximum number of virtual functions + * @dev: class converted to a Scsi_host structure. +@@ -2705,9 +2645,6 @@ static DEVICE_ATTR(max_xri, S_IRUGO, lpfc_max_xri_show, NULL); + static DEVICE_ATTR(used_xri, S_IRUGO, lpfc_used_xri_show, NULL); + static DEVICE_ATTR(npiv_info, S_IRUGO, lpfc_npiv_info_show, NULL); + static DEVICE_ATTR(lpfc_temp_sensor, S_IRUGO, lpfc_temp_sensor_show, NULL); +-static DEVICE_ATTR(lpfc_fips_level, S_IRUGO, lpfc_fips_level_show, NULL); +-static DEVICE_ATTR(lpfc_fips_rev, S_IRUGO, lpfc_fips_rev_show, NULL); +-static DEVICE_ATTR(lpfc_dss, S_IRUGO, lpfc_dss_show, NULL); + static DEVICE_ATTR(lpfc_sriov_hw_max_virtfn, S_IRUGO, + lpfc_sriov_hw_max_virtfn_show, NULL); + static DEVICE_ATTR(protocol, S_IRUGO, lpfc_sli4_protocol_show, NULL); +@@ -6251,9 +6188,6 @@ struct device_attribute *lpfc_hba_attrs[] = { + &dev_attr_pt, + &dev_attr_txq_hw, + &dev_attr_txcmplq_hw, +- &dev_attr_lpfc_fips_level, +- &dev_attr_lpfc_fips_rev, +- &dev_attr_lpfc_dss, + &dev_attr_lpfc_sriov_hw_max_virtfn, + &dev_attr_protocol, + &dev_attr_lpfc_xlane_supported, +@@ -6289,8 +6223,6 @@ struct device_attribute *lpfc_vport_attrs[] = { + &dev_attr_lpfc_max_scsicmpl_time, + &dev_attr_lpfc_stat_data_ctrl, + &dev_attr_lpfc_static_vport, +- &dev_attr_lpfc_fips_level, +- &dev_attr_lpfc_fips_rev, + NULL, + }; + +@@ -7399,7 +7331,6 @@ lpfc_get_cfgparam(struct lpfc_hba *phba) + lpfc_suppress_link_up_init(phba, lpfc_suppress_link_up); + lpfc_delay_discovery_init(phba, lpfc_delay_discovery); + lpfc_sli_mode_init(phba, lpfc_sli_mode); +- phba->cfg_enable_dss = 1; + lpfc_enable_mds_diags_init(phba, lpfc_enable_mds_diags); + lpfc_ras_fwlog_buffsize_init(phba, lpfc_ras_fwlog_buffsize); + lpfc_ras_fwlog_level_init(phba, lpfc_ras_fwlog_level); +diff --git a/drivers/scsi/lpfc/lpfc_hw.h b/drivers/scsi/lpfc/lpfc_hw.h +index ae51c0dbba0a..c20034b3101c 100644 +--- a/drivers/scsi/lpfc/lpfc_hw.h ++++ b/drivers/scsi/lpfc/lpfc_hw.h +@@ -3262,8 +3262,7 @@ typedef struct { + #endif + + #ifdef __BIG_ENDIAN_BITFIELD +- uint32_t rsvd1 : 19; /* Reserved */ +- uint32_t cdss : 1; /* Configure Data Security SLI */ ++ uint32_t rsvd1 : 20; /* Reserved */ + uint32_t casabt : 1; /* Configure async abts status notice */ + uint32_t rsvd2 : 2; /* Reserved */ + uint32_t cbg : 1; /* Configure BlockGuard */ +@@ -3287,12 +3286,10 @@ typedef struct { + uint32_t cbg : 1; /* Configure BlockGuard */ + uint32_t rsvd2 : 2; /* Reserved */ + uint32_t casabt : 1; /* Configure async abts status notice */ +- uint32_t cdss : 1; /* Configure Data Security SLI */ +- uint32_t rsvd1 : 19; /* Reserved */ ++ uint32_t rsvd1 : 20; /* Reserved */ + #endif + #ifdef __BIG_ENDIAN_BITFIELD +- uint32_t rsvd3 : 19; /* Reserved */ +- uint32_t gdss : 1; /* Configure Data Security SLI */ ++ uint32_t rsvd3 : 20; /* Reserved */ + uint32_t gasabt : 1; /* Grant async abts status notice */ + uint32_t rsvd4 : 2; /* Reserved */ + uint32_t gbg : 1; /* Grant BlockGuard */ +@@ -3316,8 +3313,7 @@ typedef struct { + uint32_t gbg : 1; /* Grant BlockGuard */ + uint32_t rsvd4 : 2; /* Reserved */ + uint32_t gasabt : 1; /* Grant async abts status notice */ +- uint32_t gdss : 1; /* Configure Data Security SLI */ +- uint32_t rsvd3 : 19; /* Reserved */ ++ uint32_t rsvd3 : 20; /* Reserved */ + #endif + + #ifdef __BIG_ENDIAN_BITFIELD +@@ -3339,15 +3335,11 @@ typedef struct { + uint32_t rsvd6; /* Reserved */ + + #ifdef __BIG_ENDIAN_BITFIELD +- uint32_t fips_rev : 3; /* FIPS Spec Revision */ +- uint32_t fips_level : 4; /* FIPS Level */ +- uint32_t sec_err : 9; /* security crypto error */ ++ uint32_t rsvd7 : 16; + uint32_t max_vpi : 16; /* Max number of virt N-Ports */ + #else /* __LITTLE_ENDIAN */ + uint32_t max_vpi : 16; /* Max number of virt N-Ports */ +- uint32_t sec_err : 9; /* security crypto error */ +- uint32_t fips_level : 4; /* FIPS Level */ +- uint32_t fips_rev : 3; /* FIPS Spec Revision */ ++ uint32_t rsvd7 : 16; + #endif + + } CONFIG_PORT_VAR; +diff --git a/drivers/scsi/lpfc/lpfc_mbox.c b/drivers/scsi/lpfc/lpfc_mbox.c +index d1773c01d2b3..e35b52b66d6c 100644 +--- a/drivers/scsi/lpfc/lpfc_mbox.c ++++ b/drivers/scsi/lpfc/lpfc_mbox.c +@@ -1299,8 +1299,6 @@ lpfc_config_port(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) + if (phba->sli_rev == LPFC_SLI_REV3 && phba->vpd.sli3Feat.cerbm) { + if (phba->cfg_enable_bg) + mb->un.varCfgPort.cbg = 1; /* configure BlockGuard */ +- if (phba->cfg_enable_dss) +- mb->un.varCfgPort.cdss = 1; /* Configure Security */ + mb->un.varCfgPort.cerbm = 1; /* Request HBQs */ + mb->un.varCfgPort.ccrp = 1; /* Command Ring Polling */ + mb->un.varCfgPort.max_hbq = lpfc_sli_hbq_count(); +diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c +index 52ccaebd6f2c..b6fb665e6ec4 100644 +--- a/drivers/scsi/lpfc/lpfc_sli.c ++++ b/drivers/scsi/lpfc/lpfc_sli.c +@@ -5032,23 +5032,6 @@ lpfc_sli_config_port(struct lpfc_hba *phba, int sli_mode) + + } else + phba->max_vpi = 0; +- phba->fips_level = 0; +- phba->fips_spec_rev = 0; +- if (pmb->u.mb.un.varCfgPort.gdss) { +- phba->sli3_options |= LPFC_SLI3_DSS_ENABLED; +- phba->fips_level = pmb->u.mb.un.varCfgPort.fips_level; +- phba->fips_spec_rev = pmb->u.mb.un.varCfgPort.fips_rev; +- lpfc_printf_log(phba, KERN_INFO, LOG_INIT, +- "2850 Security Crypto Active. FIPS x%d " +- "(Spec Rev: x%d)", +- phba->fips_level, phba->fips_spec_rev); +- } +- if (pmb->u.mb.un.varCfgPort.sec_err) { +- lpfc_printf_log(phba, KERN_ERR, LOG_INIT, +- "2856 Config Port Security Crypto " +- "Error: x%x ", +- pmb->u.mb.un.varCfgPort.sec_err); +- } + if (pmb->u.mb.un.varCfgPort.gerbm) + phba->sli3_options |= LPFC_SLI3_HBQ_ENABLED; + if (pmb->u.mb.un.varCfgPort.gcrp) +-- +2.23.0 + diff --git a/patches.suse/scsi-lpfc-Update-lpfc-version-to-12.6.0.3.patch b/patches.suse/scsi-lpfc-Update-lpfc-version-to-12.6.0.3.patch new file mode 100644 index 0000000..3970fb1 --- /dev/null +++ b/patches.suse/scsi-lpfc-Update-lpfc-version-to-12.6.0.3.patch @@ -0,0 +1,29 @@ +From: James Smart +Date: Wed, 18 Dec 2019 15:58:08 -0800 +Subject: scsi: lpfc: Update lpfc version to 12.6.0.3 +Patch-mainline: v5.6-rc1 +Git-commit: 6d67e8473386e6133fd5d7ce0be887a7972672d6 +References: bsc#1164777 bsc#1164780 bsc#1165211 + +Update lpfc version to 12.6.0.3 + +Link: https://lore.kernel.org/r/20191218235808.31922-11-jsmart2021@gmail.com +Signed-off-by: Dick Kennedy +Signed-off-by: James Smart +Signed-off-by: Martin K. Petersen +Acked-by: Daniel Wagner +--- + drivers/scsi/lpfc/lpfc_version.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/scsi/lpfc/lpfc_version.h ++++ b/drivers/scsi/lpfc/lpfc_version.h +@@ -20,7 +20,7 @@ + * included with this package. * + *******************************************************************/ + +-#define LPFC_DRIVER_VERSION "12.6.0.2" ++#define LPFC_DRIVER_VERSION "12.6.0.3" + #define LPFC_DRIVER_NAME "lpfc" + + /* Used for SLI 2/3 */ diff --git a/patches.suse/scsi-lpfc-Update-lpfc-version-to-12.6.0.4.patch b/patches.suse/scsi-lpfc-Update-lpfc-version-to-12.6.0.4.patch new file mode 100644 index 0000000..3e63b88 --- /dev/null +++ b/patches.suse/scsi-lpfc-Update-lpfc-version-to-12.6.0.4.patch @@ -0,0 +1,29 @@ +From: James Smart +Date: Mon, 27 Jan 2020 16:23:11 -0800 +Subject: scsi: lpfc: Update lpfc version to 12.6.0.4 +Patch-mainline: v5.7-rc1 +Git-commit: ad6203f975263752e9738a33eacbc92f5bb6f636 +References: bsc#1164777 bsc#1164780 bsc#1165211 + +Update lpfc version to 12.6.0.4 + +Link: https://lore.kernel.org/r/20200128002312.16346-12-jsmart2021@gmail.com +Signed-off-by: Dick Kennedy +Signed-off-by: James Smart +Signed-off-by: Martin K. Petersen +Acked-by: Daniel Wagner +--- + drivers/scsi/lpfc/lpfc_version.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/scsi/lpfc/lpfc_version.h ++++ b/drivers/scsi/lpfc/lpfc_version.h +@@ -20,7 +20,7 @@ + * included with this package. * + *******************************************************************/ + +-#define LPFC_DRIVER_VERSION "12.6.0.3" ++#define LPFC_DRIVER_VERSION "12.6.0.4" + #define LPFC_DRIVER_NAME "lpfc" + + /* Used for SLI 2/3 */ diff --git a/patches.suse/scsi-lpfc-Update-lpfc-version-to-12.8.0.0.patch b/patches.suse/scsi-lpfc-Update-lpfc-version-to-12.8.0.0.patch new file mode 100644 index 0000000..7629786 --- /dev/null +++ b/patches.suse/scsi-lpfc-Update-lpfc-version-to-12.8.0.0.patch @@ -0,0 +1,36 @@ +From d75e119e60ceaaaaf32624f5a82842df4d78aed7 Mon Sep 17 00:00:00 2001 +From: James Smart +Date: Sun, 22 Mar 2020 11:13:04 -0700 +Subject: [PATCH] scsi: lpfc: Update lpfc version to 12.8.0.0 + +References: bsc#1164777 bsc#1164780 bsc#1165211 +Patch-mainline: v5.7-rc1 +Git-commit: d75e119e60ceaaaaf32624f5a82842df4d78aed7 + +Update lpfc version to 12.8.0.0 + +Link: https://lore.kernel.org/r/20200322181304.37655-13-jsmart2021@gmail.com +Signed-off-by: James Smart +Signed-off-by: Dick Kennedy +Signed-off-by: Martin K. Petersen +Acked-by: Daniel Wagner +--- + drivers/scsi/lpfc/lpfc_version.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/scsi/lpfc/lpfc_version.h b/drivers/scsi/lpfc/lpfc_version.h +index c4ab006e6ecc..ca40c47cfbe0 100644 +--- a/drivers/scsi/lpfc/lpfc_version.h ++++ b/drivers/scsi/lpfc/lpfc_version.h +@@ -20,7 +20,7 @@ + * included with this package. * + *******************************************************************/ + +-#define LPFC_DRIVER_VERSION "12.6.0.4" ++#define LPFC_DRIVER_VERSION "12.8.0.0" + #define LPFC_DRIVER_NAME "lpfc" + + /* Used for SLI 2/3 */ +-- +2.23.0 + diff --git a/patches.suse/scsi-lpfc-add-RDF-registration-and-Link-Integrity-FP.patch b/patches.suse/scsi-lpfc-add-RDF-registration-and-Link-Integrity-FP.patch new file mode 100644 index 0000000..f7c1c43 --- /dev/null +++ b/patches.suse/scsi-lpfc-add-RDF-registration-and-Link-Integrity-FP.patch @@ -0,0 +1,590 @@ +From: James Smart +Date: Mon, 10 Feb 2020 09:31:55 -0800 +Subject: scsi: lpfc: add RDF registration and Link Integrity FPIN logging +Patch-mainline: v5.7-rc1 +Git-commit: df3fe76658ed47617741819a501e2bd2ae446962 +References: bsc#1164777 bsc#1164780 bsc#1165211 + +This patch modifies lpfc to register for Link Integrity events via the use +of an RDF ELS and to perform Link Integrity FPIN logging. + +Specifically, the driver was modified to: + + - Format and issue the RDF ELS immediately following SCR registration. + This registers the ability of the driver to receive FPIN ELS. + + - Adds decoding of the FPIN els into the received descriptors, with + logging of the Link Integrity event information. After decoding, the ELS + is delivered to the scsi fc transport to be delivered to any user-space + applications. + + - To aid in logging, simple helpers were added to create enum to name + string lookup functions that utilize the initialization helpers from the + fc_els.h header. + + - Note: base header definitions for the ELS's don't populate the + descriptor payloads. As such, lpfc creates it's own version of the + structures, using the base definitions (mostly headers) and additionally + declaring the descriptors that will complete the population of the ELS. + +Link: https://lore.kernel.org/r/20200210173155.547-3-jsmart2021@gmail.com +Signed-off-by: Dick Kennedy +Signed-off-by: James Smart +Signed-off-by: Martin K. Petersen +Acked-by: Daniel Wagner +--- + drivers/scsi/lpfc/lpfc.h | 29 +++ + drivers/scsi/lpfc/lpfc_crtn.h | 3 + drivers/scsi/lpfc/lpfc_els.c | 324 ++++++++++++++++++++++++++++++++++++--- + drivers/scsi/lpfc/lpfc_hbadisc.c | 4 + drivers/scsi/lpfc/lpfc_hw.h | 4 + drivers/scsi/lpfc/lpfc_hw4.h | 19 ++ + drivers/scsi/lpfc/lpfc_sli.c | 1 + 7 files changed, 361 insertions(+), 23 deletions(-) + +--- a/drivers/scsi/lpfc/lpfc.h ++++ b/drivers/scsi/lpfc/lpfc.h +@@ -1352,3 +1352,32 @@ lpfc_sli4_mod_hba_eq_delay(struct lpfc_h + writel(reg_data.word0, phba->sli4_hba.u.if_type2.EQDregaddr); + eq->q_mode = delay; + } ++ ++ ++/* ++ * Macro that declares tables and a routine to perform enum type to ++ * ascii string lookup. ++ * ++ * Defines a table for an enum. Uses xxx_INIT defines for ++ * the enum to populate the table. Macro defines a routine (named ++ * by caller) that will search all elements of the table for the key ++ * and return the name string if found or "Unrecognized" if not found. ++ */ ++#define DECLARE_ENUM2STR_LOOKUP(routine, enum_name, enum_init) \ ++static struct { \ ++ enum enum_name value; \ ++ char *name; \ ++} fc_##enum_name##_e2str_names[] = enum_init; \ ++static const char *routine(enum enum_name table_key) \ ++{ \ ++ int i; \ ++ char *name = "Unrecognized"; \ ++ \ ++ for (i = 0; i < ARRAY_SIZE(fc_##enum_name##_e2str_names); i++) {\ ++ if (fc_##enum_name##_e2str_names[i].value == table_key) {\ ++ name = fc_##enum_name##_e2str_names[i].name; \ ++ break; \ ++ } \ ++ } \ ++ return name; \ ++} +--- a/drivers/scsi/lpfc/lpfc_crtn.h ++++ b/drivers/scsi/lpfc/lpfc_crtn.h +@@ -140,9 +140,10 @@ int lpfc_issue_els_prli(struct lpfc_vpor + int lpfc_issue_els_adisc(struct lpfc_vport *, struct lpfc_nodelist *, uint8_t); + int lpfc_issue_els_logo(struct lpfc_vport *, struct lpfc_nodelist *, uint8_t); + int lpfc_issue_els_npiv_logo(struct lpfc_vport *, struct lpfc_nodelist *); +-int lpfc_issue_els_scr(struct lpfc_vport *, uint32_t, uint8_t); ++int lpfc_issue_els_scr(struct lpfc_vport *vport, uint8_t retry); + int lpfc_issue_els_rscn(struct lpfc_vport *vport, uint8_t retry); + int lpfc_issue_fabric_reglogin(struct lpfc_vport *); ++int lpfc_issue_els_rdf(struct lpfc_vport *vport, uint8_t retry); + int lpfc_els_free_iocb(struct lpfc_hba *, struct lpfc_iocbq *); + int lpfc_ct_free_iocb(struct lpfc_hba *, struct lpfc_iocbq *); + int lpfc_els_rsp_acc(struct lpfc_vport *, uint32_t, struct lpfc_iocbq *, +--- a/drivers/scsi/lpfc/lpfc_els.c ++++ b/drivers/scsi/lpfc/lpfc_els.c +@@ -3008,10 +3008,9 @@ lpfc_issue_els_logo(struct lpfc_vport *v + * This routine is a generic completion callback function for ELS commands. + * Specifically, it is the callback function which does not need to perform + * any command specific operations. It is currently used by the ELS command +- * issuing routines for the ELS State Change Request (SCR), +- * lpfc_issue_els_scr(), and the ELS Fibre Channel Address Resolution +- * Protocol Response (FARPR) routine, lpfc_issue_els_farpr(). Other than +- * certain debug loggings, this callback function simply invokes the ++ * issuing routines for RSCN, lpfc_issue_els_rscn, and the ELS Fibre Channel ++ * Address Resolution Protocol Response (FARPR) routine, lpfc_issue_els_farpr(). ++ * Other than certain debug loggings, this callback function simply invokes the + * lpfc_els_chk_latt() routine to check whether link went down during the + * discovery process. + **/ +@@ -3025,14 +3024,117 @@ lpfc_cmpl_els_cmd(struct lpfc_hba *phba, + irsp = &rspiocb->iocb; + + lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD, ++ "ELS cmd cmpl: status:x%x/x%x did:x%x", ++ irsp->ulpStatus, irsp->un.ulpWord[4], ++ irsp->un.elsreq64.remoteID); ++ ++ /* ELS cmd tag completes */ ++ lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, ++ "0106 ELS cmd tag x%x completes Data: x%x x%x x%x\n", ++ irsp->ulpIoTag, irsp->ulpStatus, ++ irsp->un.ulpWord[4], irsp->ulpTimeout); ++ ++ /* Check to see if link went down during discovery */ ++ lpfc_els_chk_latt(vport); ++ lpfc_els_free_iocb(phba, cmdiocb); ++} ++ ++/** ++ * lpfc_cmpl_els_disc_cmd - Completion callback function for Discovery ELS cmd ++ * @phba: pointer to lpfc hba data structure. ++ * @cmdiocb: pointer to lpfc command iocb data structure. ++ * @rspiocb: pointer to lpfc response iocb data structure. ++ * ++ * This routine is a generic completion callback function for Discovery ELS cmd. ++ * Currently used by the ELS command issuing routines for the ELS State Change ++ * Request (SCR), lpfc_issue_els_scr() and the ELS RDF, lpfc_issue_els_rdf(). ++ * These commands will be retried once only for ELS timeout errors. ++ **/ ++static void ++lpfc_cmpl_els_disc_cmd(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, ++ struct lpfc_iocbq *rspiocb) ++{ ++ struct lpfc_vport *vport = cmdiocb->vport; ++ IOCB_t *irsp; ++ struct lpfc_els_rdf_rsp *prdf; ++ struct lpfc_dmabuf *pcmd, *prsp; ++ u32 *pdata; ++ u32 cmd; ++ ++ irsp = &rspiocb->iocb; ++ ++ lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD, + "ELS cmd cmpl: status:x%x/x%x did:x%x", + irsp->ulpStatus, irsp->un.ulpWord[4], + irsp->un.elsreq64.remoteID); + /* ELS cmd tag completes */ + lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, +- "0106 ELS cmd tag x%x completes Data: x%x x%x x%x\n", ++ "0217 ELS cmd tag x%x completes Data: x%x x%x x%x " ++ "x%x\n", + irsp->ulpIoTag, irsp->ulpStatus, +- irsp->un.ulpWord[4], irsp->ulpTimeout); ++ irsp->un.ulpWord[4], irsp->ulpTimeout, ++ cmdiocb->retry); ++ ++ pcmd = (struct lpfc_dmabuf *)cmdiocb->context2; ++ if (!pcmd) ++ goto out; ++ ++ pdata = (u32 *)pcmd->virt; ++ if (!pdata) ++ goto out; ++ cmd = *pdata; ++ ++ /* Only 1 retry for ELS Timeout only */ ++ if (irsp->ulpStatus == IOSTAT_LOCAL_REJECT && ++ ((irsp->un.ulpWord[4] & IOERR_PARAM_MASK) == ++ IOERR_SEQUENCE_TIMEOUT)) { ++ cmdiocb->retry++; ++ if (cmdiocb->retry <= 1) { ++ switch (cmd) { ++ case ELS_CMD_SCR: ++ lpfc_issue_els_scr(vport, cmdiocb->retry); ++ break; ++ case ELS_CMD_RDF: ++ cmdiocb->context1 = NULL; /* save ndlp refcnt */ ++ lpfc_issue_els_rdf(vport, cmdiocb->retry); ++ break; ++ } ++ goto out; ++ } ++ phba->fc_stat.elsRetryExceeded++; ++ } ++ if (irsp->ulpStatus) { ++ /* ELS discovery cmd completes with error */ ++ lpfc_printf_vlog(vport, KERN_WARNING, LOG_ELS, ++ "4203 ELS cmd x%x error: x%x x%X\n", cmd, ++ irsp->ulpStatus, irsp->un.ulpWord[4]); ++ goto out; ++ } ++ ++ /* The RDF response doesn't have any impact on the running driver ++ * but the notification descriptors are dumped here for support. ++ */ ++ if (cmd == ELS_CMD_RDF) { ++ int i; ++ ++ prsp = list_get_first(&pcmd->list, struct lpfc_dmabuf, list); ++ if (!prsp) ++ goto out; ++ ++ prdf = (struct lpfc_els_rdf_rsp *)prsp->virt; ++ if (!prdf) ++ goto out; ++ ++ for (i = 0; i < ELS_RDF_REG_TAG_CNT && ++ i < be32_to_cpu(prdf->reg_d1.reg_desc.count); i++) ++ lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, ++ "4677 Fabric RDF Notication Grant Data: " ++ "0x%08x\n", ++ be32_to_cpu( ++ prdf->reg_d1.desc_tags[i])); ++ } ++ ++out: + /* Check to see if link went down during discovery */ + lpfc_els_chk_latt(vport); + lpfc_els_free_iocb(phba, cmdiocb); +@@ -3042,11 +3144,10 @@ lpfc_cmpl_els_cmd(struct lpfc_hba *phba, + /** + * lpfc_issue_els_scr - Issue a scr to an node on a vport + * @vport: pointer to a host virtual N_Port data structure. +- * @nportid: N_Port identifier to the remote node. +- * @retry: number of retries to the command IOCB. ++ * @retry: retry counter for the command IOCB. + * + * This routine issues a State Change Request (SCR) to a fabric node +- * on a @vport. The remote node @nportid is passed into the function. It ++ * on a @vport. The remote node is Fabric Controller (0xfffffd). It + * first search the @vport node list to find the matching ndlp. If no such + * ndlp is found, a new ndlp shall be created for this (SCR) purpose. An + * IOCB is allocated, payload prepared, and the lpfc_sli_issue_iocb() +@@ -3062,7 +3163,7 @@ lpfc_cmpl_els_cmd(struct lpfc_hba *phba, + * 1 - Failed to issue scr command + **/ + int +-lpfc_issue_els_scr(struct lpfc_vport *vport, uint32_t nportid, uint8_t retry) ++lpfc_issue_els_scr(struct lpfc_vport *vport, uint8_t retry) + { + struct lpfc_hba *phba = vport->phba; + struct lpfc_iocbq *elsiocb; +@@ -3072,9 +3173,9 @@ lpfc_issue_els_scr(struct lpfc_vport *vp + + cmdsize = (sizeof(uint32_t) + sizeof(SCR)); + +- ndlp = lpfc_findnode_did(vport, nportid); ++ ndlp = lpfc_findnode_did(vport, Fabric_Cntl_DID); + if (!ndlp) { +- ndlp = lpfc_nlp_init(vport, nportid); ++ ndlp = lpfc_nlp_init(vport, Fabric_Cntl_DID); + if (!ndlp) + return 1; + lpfc_enqueue_node(vport, ndlp); +@@ -3109,7 +3210,7 @@ lpfc_issue_els_scr(struct lpfc_vport *vp + ndlp->nlp_DID, 0, 0); + + phba->fc_stat.elsXmitSCR++; +- elsiocb->iocb_cmpl = lpfc_cmpl_els_cmd; ++ elsiocb->iocb_cmpl = lpfc_cmpl_els_disc_cmd; + if (lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, elsiocb, 0) == + IOCB_ERROR) { + /* The additional lpfc_nlp_put will cause the following +@@ -3339,6 +3440,102 @@ lpfc_issue_els_farpr(struct lpfc_vport * + /* This will cause the callback-function lpfc_cmpl_els_cmd to + * trigger the release of the node. + */ ++ /* Don't release reference count as RDF is likely outstanding */ ++ return 0; ++} ++ ++/** ++ * lpfc_issue_els_rdf - Register for diagnostic functions from the fabric. ++ * @vport: pointer to a host virtual N_Port data structure. ++ * @retry: retry counter for the command IOCB. ++ * ++ * This routine issues an ELS RDF to the Fabric Controller to register ++ * for diagnostic functions. ++ * ++ * Note that, in lpfc_prep_els_iocb() routine, the reference count of ndlp ++ * will be incremented by 1 for holding the ndlp and the reference to ndlp ++ * will be stored into the context1 field of the IOCB for the completion ++ * callback function to the RDF ELS command. ++ * ++ * Return code ++ * 0 - Successfully issued rdf command ++ * 1 - Failed to issue rdf command ++ **/ ++int ++lpfc_issue_els_rdf(struct lpfc_vport *vport, uint8_t retry) ++{ ++ struct lpfc_hba *phba = vport->phba; ++ struct lpfc_iocbq *elsiocb; ++ struct lpfc_els_rdf_req *prdf; ++ struct lpfc_nodelist *ndlp; ++ uint16_t cmdsize; ++ ++ cmdsize = sizeof(*prdf); ++ ++ ndlp = lpfc_findnode_did(vport, Fabric_Cntl_DID); ++ if (!ndlp) { ++ ndlp = lpfc_nlp_init(vport, Fabric_Cntl_DID); ++ if (!ndlp) ++ return -ENODEV; ++ lpfc_enqueue_node(vport, ndlp); ++ } else if (!NLP_CHK_NODE_ACT(ndlp)) { ++ ndlp = lpfc_enable_node(vport, ndlp, NLP_STE_UNUSED_NODE); ++ if (!ndlp) ++ return -ENODEV; ++ } ++ ++ /* RDF ELS is not required on an NPIV VN_Port. */ ++ if (vport->port_type == LPFC_NPIV_PORT) { ++ lpfc_nlp_put(ndlp); ++ return -EACCES; ++ } ++ ++ elsiocb = lpfc_prep_els_iocb(vport, 1, cmdsize, retry, ndlp, ++ ndlp->nlp_DID, ELS_CMD_RDF); ++ if (!elsiocb) { ++ /* This will trigger the release of the node just ++ * allocated ++ */ ++ lpfc_nlp_put(ndlp); ++ return -ENOMEM; ++ } ++ ++ /* Configure the payload for the supported FPIN events. */ ++ prdf = (struct lpfc_els_rdf_req *) ++ (((struct lpfc_dmabuf *)elsiocb->context2)->virt); ++ memset(prdf, 0, cmdsize); ++ prdf->rdf.fpin_cmd = ELS_RDF; ++ prdf->rdf.desc_len = cpu_to_be32(sizeof(struct lpfc_els_rdf_req) - ++ sizeof(struct fc_els_rdf)); ++ prdf->reg_d1.reg_desc.desc_tag = cpu_to_be32(ELS_DTAG_FPIN_REGISTER); ++ prdf->reg_d1.reg_desc.desc_len = cpu_to_be32( ++ FC_TLV_DESC_LENGTH_FROM_SZ(prdf->reg_d1)); ++ prdf->reg_d1.reg_desc.count = cpu_to_be32(ELS_RDF_REG_TAG_CNT); ++ prdf->reg_d1.desc_tags[0] = cpu_to_be32(ELS_DTAG_LNK_INTEGRITY); ++ ++ lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD, ++ "Issue RDF: did:x%x", ++ ndlp->nlp_DID, 0, 0); ++ ++ lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, ++ "6444 Xmit RDF to remote NPORT x%x\n", ++ ndlp->nlp_DID); ++ ++ elsiocb->iocb_cmpl = lpfc_cmpl_els_disc_cmd; ++ if (lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, elsiocb, 0) == ++ IOCB_ERROR) { ++ /* The additional lpfc_nlp_put will cause the following ++ * lpfc_els_free_iocb routine to trigger the rlease of ++ * the node. ++ */ ++ lpfc_nlp_put(ndlp); ++ lpfc_els_free_iocb(phba, elsiocb); ++ return -EIO; ++ } ++ ++ /* An RDF was issued - this put ensures the ndlp is cleaned up ++ * when the RDF completes. ++ */ + lpfc_nlp_put(ndlp); + return 0; + } +@@ -8137,6 +8334,90 @@ lpfc_send_els_event(struct lpfc_vport *v + } + + ++DECLARE_ENUM2STR_LOOKUP(lpfc_get_tlv_dtag_nm, fc_ls_tlv_dtag, ++ FC_LS_TLV_DTAG_INIT); ++ ++DECLARE_ENUM2STR_LOOKUP(lpfc_get_fpin_li_event_nm, fc_fpin_li_event_types, ++ FC_FPIN_LI_EVT_TYPES_INIT); ++ ++/** ++ * lpfc_els_rcv_fpin_li - Process an FPIN Link Integrity Event. ++ * @vport: Pointer to vport object. ++ * @lnk_not: Pointer to the Link Integrity Notification Descriptor. ++ * ++ * This function processes a link integrity FPIN event by ++ * logging a message ++ **/ ++static void ++lpfc_els_rcv_fpin_li(struct lpfc_vport *vport, struct fc_tlv_desc *tlv) ++{ ++ struct fc_fn_li_desc *li = (struct fc_fn_li_desc *)tlv; ++ const char *li_evt_str; ++ u32 li_evt; ++ ++ li_evt = be16_to_cpu(li->event_type); ++ li_evt_str = lpfc_get_fpin_li_event_nm(li_evt); ++ ++ lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, ++ "4680 FPIN Link Integrity %s (x%x) " ++ "Detecting PN x%016llx Attached PN x%016llx " ++ "Duration %d mSecs Count %d Port Cnt %d\n", ++ li_evt_str, li_evt, ++ be64_to_cpu(li->detecting_wwpn), ++ be64_to_cpu(li->attached_wwpn), ++ be32_to_cpu(li->event_threshold), ++ be32_to_cpu(li->event_count), ++ be32_to_cpu(li->pname_count)); ++} ++ ++static void ++lpfc_els_rcv_fpin(struct lpfc_vport *vport, struct fc_els_fpin *fpin, ++ u32 fpin_length) ++{ ++ struct fc_tlv_desc *tlv; ++ const char *dtag_nm; ++ uint32_t desc_cnt = 0, bytes_remain; ++ u32 dtag; ++ ++ /* FPINs handled only if we are in the right discovery state */ ++ if (vport->port_state < LPFC_DISC_AUTH) ++ return; ++ ++ /* make sure there is the full fpin header */ ++ if (fpin_length < sizeof(struct fc_els_fpin)) ++ return; ++ ++ tlv = (struct fc_tlv_desc *)&fpin->fpin_desc[0]; ++ bytes_remain = fpin_length - offsetof(struct fc_els_fpin, fpin_desc); ++ bytes_remain = min_t(u32, bytes_remain, be32_to_cpu(fpin->desc_len)); ++ ++ /* process each descriptor */ ++ while (bytes_remain >= FC_TLV_DESC_HDR_SZ && ++ bytes_remain >= FC_TLV_DESC_SZ_FROM_LENGTH(tlv)) { ++ ++ dtag = be32_to_cpu(tlv->desc_tag); ++ switch (dtag) { ++ case ELS_DTAG_LNK_INTEGRITY: ++ lpfc_els_rcv_fpin_li(vport, tlv); ++ break; ++ default: ++ dtag_nm = lpfc_get_tlv_dtag_nm(dtag); ++ lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS, ++ "4678 skipped FPIN descriptor[%d]: " ++ "tag x%x (%s)\n", ++ desc_cnt, dtag, dtag_nm); ++ break; ++ } ++ ++ desc_cnt++; ++ bytes_remain -= FC_TLV_DESC_SZ_FROM_LENGTH(tlv); ++ tlv = fc_tlv_next_desc(tlv); ++ } ++ ++ fc_host_fpin_rcv(lpfc_shost_from_vport(vport), fpin_length, ++ (char *)fpin); ++} ++ + /** + * lpfc_els_unsol_buffer - Process an unsolicited event data buffer + * @phba: pointer to lpfc hba data structure. +@@ -8158,7 +8439,7 @@ lpfc_els_unsol_buffer(struct lpfc_hba *p + struct Scsi_Host *shost; + struct lpfc_nodelist *ndlp; + struct ls_rjt stat; +- uint32_t *payload; ++ uint32_t *payload, payload_len; + uint32_t cmd, did, newnode; + uint8_t rjt_exp, rjt_err = 0, init_link = 0; + IOCB_t *icmd = &elsiocb->iocb; +@@ -8169,6 +8450,7 @@ lpfc_els_unsol_buffer(struct lpfc_hba *p + + newnode = 0; + payload = ((struct lpfc_dmabuf *)elsiocb->context2)->virt; ++ payload_len = elsiocb->iocb.unsli3.rcvsli3.acc_len; + cmd = *payload; + if ((phba->sli3_options & LPFC_SLI3_HBQ_ENABLED) == 0) + lpfc_post_buffer(phba, pring, 1); +@@ -8514,12 +8796,14 @@ lpfc_els_unsol_buffer(struct lpfc_hba *p + rjt_exp = LSEXP_INVALID_OX_RX; + break; + case ELS_CMD_FPIN: +- /* +- * Received FPIN from fabric - pass it to the +- * transport FPIN handler. +- */ +- fc_host_fpin_rcv(shost, elsiocb->iocb.unsli3.rcvsli3.acc_len, +- (char *)payload); ++ lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL, ++ "RCV FPIN: did:x%x/ste:x%x flg:x%x", ++ did, vport->port_state, ndlp->nlp_flag); ++ ++ lpfc_els_rcv_fpin(vport, (struct fc_els_fpin *)payload, ++ payload_len); ++ ++ /* There are no replies, so no rjt codes */ + break; + default: + lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL, +--- a/drivers/scsi/lpfc/lpfc_hbadisc.c ++++ b/drivers/scsi/lpfc/lpfc_hbadisc.c +@@ -4089,7 +4089,9 @@ out: + FC_TYPE_NVME); + + /* Issue SCR just before NameServer GID_FT Query */ +- lpfc_issue_els_scr(vport, SCR_DID, 0); ++ lpfc_issue_els_scr(vport, 0); ++ ++ lpfc_issue_els_rdf(vport, 0); + } + + vport->fc_ns_retry = 0; +--- a/drivers/scsi/lpfc/lpfc_hw.h ++++ b/drivers/scsi/lpfc/lpfc_hw.h +@@ -22,7 +22,7 @@ + + #define FDMI_DID 0xfffffaU + #define NameServer_DID 0xfffffcU +-#define SCR_DID 0xfffffdU ++#define Fabric_Cntl_DID 0xfffffdU + #define Fabric_DID 0xfffffeU + #define Bcast_DID 0xffffffU + #define Mask_DID 0xffffffU +@@ -588,6 +588,7 @@ struct fc_vft_header { + #define ELS_CMD_RRQ 0x12000000 + #define ELS_CMD_REC 0x13000000 + #define ELS_CMD_RDP 0x18000000 ++#define ELS_CMD_RDF 0x19000000 + #define ELS_CMD_PRLI 0x20100014 + #define ELS_CMD_NVMEPRLI 0x20140018 + #define ELS_CMD_PRLO 0x21100014 +@@ -629,6 +630,7 @@ struct fc_vft_header { + #define ELS_CMD_RRQ 0x12 + #define ELS_CMD_REC 0x13 + #define ELS_CMD_RDP 0x18 ++#define ELS_CMD_RDF 0x19 + #define ELS_CMD_PRLI 0x14001020 + #define ELS_CMD_NVMEPRLI 0x18001420 + #define ELS_CMD_PRLO 0x14001021 +--- a/drivers/scsi/lpfc/lpfc_hw4.h ++++ b/drivers/scsi/lpfc/lpfc_hw4.h +@@ -20,6 +20,8 @@ + * included with this package. * + *******************************************************************/ + ++#include ++ + /* Macros to deal with bit fields. Each bit field must have 3 #defines + * associated with it (_SHIFT, _MASK, and _WORD). + * EG. For a bit field that is in the 7th bit of the "field4" field of a +@@ -4795,6 +4797,23 @@ struct send_frame_wqe { + uint32_t fc_hdr_wd5; /* word 15 */ + }; + ++#define ELS_RDF_REG_TAG_CNT 1 ++struct lpfc_els_rdf_reg_desc { ++ struct fc_df_desc_fpin_reg reg_desc; /* descriptor header */ ++ __be32 desc_tags[ELS_RDF_REG_TAG_CNT]; ++ /* tags in reg_desc */ ++}; ++ ++struct lpfc_els_rdf_req { ++ struct fc_els_rdf rdf; /* hdr up to descriptors */ ++ struct lpfc_els_rdf_reg_desc reg_d1; /* 1st descriptor */ ++}; ++ ++struct lpfc_els_rdf_rsp { ++ struct fc_els_rdf_resp rdf_resp; /* hdr up to descriptors */ ++ struct lpfc_els_rdf_reg_desc reg_d1; /* 1st descriptor */ ++}; ++ + union lpfc_wqe { + uint32_t words[16]; + struct lpfc_wqe_generic generic; +--- a/drivers/scsi/lpfc/lpfc_sli.c ++++ b/drivers/scsi/lpfc/lpfc_sli.c +@@ -9466,6 +9466,7 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba + if (if_type >= LPFC_SLI_INTF_IF_TYPE_2) { + if (pcmd && (*pcmd == ELS_CMD_FLOGI || + *pcmd == ELS_CMD_SCR || ++ *pcmd == ELS_CMD_RDF || + *pcmd == ELS_CMD_RSCN_XMT || + *pcmd == ELS_CMD_FDISC || + *pcmd == ELS_CMD_LOGO || diff --git a/patches.suse/scsi-lpfc-fix-spelling-mistake-Notication-Notificati.patch b/patches.suse/scsi-lpfc-fix-spelling-mistake-Notication-Notificati.patch new file mode 100644 index 0000000..28edb89 --- /dev/null +++ b/patches.suse/scsi-lpfc-fix-spelling-mistake-Notication-Notificati.patch @@ -0,0 +1,31 @@ +From: Colin Ian King +Date: Fri, 21 Feb 2020 15:48:41 +0000 +Subject: scsi: lpfc: fix spelling mistake "Notication" -> "Notification" +Patch-mainline: v5.7-rc1 +Git-commit: 162e250031cc6caca35738813720e4ed83f1b1bb +References: bsc#1164777 bsc#1164780 bsc#1165211 + +There is a spelling mistake in a lpfc_printf_vlog info message. Fix it. + +[mkp: fix spelling mistake in commit description] + +Link: https://lore.kernel.org/linux-scsi/20200221154841.77791-1-colin.king@canonical.com +Reviewed-by: James Smart +Signed-off-by: Colin Ian King +Signed-off-by: Martin K. Petersen +Acked-by: Daniel Wagner +--- + drivers/scsi/lpfc/lpfc_els.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/scsi/lpfc/lpfc_els.c ++++ b/drivers/scsi/lpfc/lpfc_els.c +@@ -3128,7 +3128,7 @@ lpfc_cmpl_els_disc_cmd(struct lpfc_hba * + for (i = 0; i < ELS_RDF_REG_TAG_CNT && + i < be32_to_cpu(prdf->reg_d1.reg_desc.count); i++) + lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, +- "4677 Fabric RDF Notication Grant Data: " ++ "4677 Fabric RDF Notification Grant Data: " + "0x%08x\n", + be32_to_cpu( + prdf->reg_d1.desc_tags[i])); diff --git a/patches.suse/scsi-lpfc-fix-spelling-mistakes-of-asynchronous.patch b/patches.suse/scsi-lpfc-fix-spelling-mistakes-of-asynchronous.patch new file mode 100644 index 0000000..91e0940 --- /dev/null +++ b/patches.suse/scsi-lpfc-fix-spelling-mistakes-of-asynchronous.patch @@ -0,0 +1,74 @@ +From: Colin Ian King +Date: Wed, 18 Dec 2019 08:43:01 +0000 +Subject: scsi: lpfc: fix spelling mistakes of asynchronous +Patch-mainline: v5.5-rc4 +Git-commit: 291c2548458d3a8b326bfa8d7abbba86e036faf7 +References: bsc#1164777 bsc#1164780 bsc#1165211 + +There are spelling mistakes of asynchronous in a lpfc_printf_log message +and comments. Fix these. + +Link: https://lore.kernel.org/r/20191218084301.627555-1-colin.king@canonical.com +Signed-off-by: Colin Ian King +Reviewed-by: James Smart +Signed-off-by: Martin K. Petersen +Acked-by: Daniel Wagner +--- + drivers/scsi/lpfc/lpfc_init.c | 2 +- + drivers/scsi/lpfc/lpfc_sli.c | 10 +++++----- + 2 files changed, 6 insertions(+), 6 deletions(-) + +--- a/drivers/scsi/lpfc/lpfc_init.c ++++ b/drivers/scsi/lpfc/lpfc_init.c +@@ -5884,7 +5884,7 @@ void lpfc_sli4_async_event_proc(struct l + break; + default: + lpfc_printf_log(phba, KERN_ERR, LOG_SLI, +- "1804 Invalid asynchrous event code: " ++ "1804 Invalid asynchronous event code: " + "x%x\n", bf_get(lpfc_trailer_code, + &cq_event->cqe.mcqe_cmpl)); + break; +--- a/drivers/scsi/lpfc/lpfc_sli.c ++++ b/drivers/scsi/lpfc/lpfc_sli.c +@@ -8562,7 +8562,7 @@ lpfc_sli4_async_mbox_unblock(struct lpfc + psli->sli_flag &= ~LPFC_SLI_ASYNC_MBX_BLK; + spin_unlock_irq(&phba->hbalock); + +- /* wake up worker thread to post asynchronlous mailbox command */ ++ /* wake up worker thread to post asynchronous mailbox command */ + lpfc_worker_wake_up(phba); + } + +@@ -8830,7 +8830,7 @@ lpfc_sli_issue_mbox_s4(struct lpfc_hba * + return rc; + } + +- /* Now, interrupt mode asynchrous mailbox command */ ++ /* Now, interrupt mode asynchronous mailbox command */ + rc = lpfc_mbox_cmd_check(phba, mboxq); + if (rc) { + lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_SLI, +@@ -13118,11 +13118,11 @@ lpfc_cq_event_setup(struct lpfc_hba *phb + } + + /** +- * lpfc_sli4_sp_handle_async_event - Handle an asynchroous event ++ * lpfc_sli4_sp_handle_async_event - Handle an asynchronous event + * @phba: Pointer to HBA context object. + * @cqe: Pointer to mailbox completion queue entry. + * +- * This routine process a mailbox completion queue entry with asynchrous ++ * This routine process a mailbox completion queue entry with asynchronous + * event. + * + * Return: true if work posted to worker thread, otherwise false. +@@ -13276,7 +13276,7 @@ out_no_mqe_complete: + * @cqe: Pointer to mailbox completion queue entry. + * + * This routine process a mailbox completion queue entry, it invokes the +- * proper mailbox complete handling or asynchrous event handling routine ++ * proper mailbox complete handling or asynchronous event handling routine + * according to the MCQE's async bit. + * + * Return: true if work posted to worker thread, otherwise false. diff --git a/patches.suse/scsi-qla2xxx-Add-16.0GT-for-PCI-String.patch b/patches.suse/scsi-qla2xxx-Add-16.0GT-for-PCI-String.patch new file mode 100644 index 0000000..d2bff17 --- /dev/null +++ b/patches.suse/scsi-qla2xxx-Add-16.0GT-for-PCI-String.patch @@ -0,0 +1,29 @@ +From: Himanshu Madhani +Date: Wed, 26 Feb 2020 14:40:05 -0800 +Subject: scsi: qla2xxx: Add 16.0GT for PCI String +Patch-mainline: v5.7-rc1 +Git-commit: efd39a2ad6ff6d1187caac8491d710f41b6a93ab +References: bsc#1157424 + +This patch adds 16.0GT for readable display string. + +Link: https://lore.kernel.org/r/20200226224022.24518-2-hmadhani@marvell.com +Signed-off-by: Himanshu Madhani +Signed-off-by: Martin K. Petersen +Acked-by: Daniel Wagner +--- + drivers/scsi/qla2xxx/qla_os.c | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/drivers/scsi/qla2xxx/qla_os.c ++++ b/drivers/scsi/qla2xxx/qla_os.c +@@ -602,6 +602,9 @@ qla24xx_pci_info_str(struct scsi_qla_hos + case 3: + speed_str = "8.0GT/s"; + break; ++ case 4: ++ speed_str = "16.0GT/s"; ++ break; + default: + speed_str = ""; + break; diff --git a/patches.suse/scsi-qla2xxx-Add-beacon-LED-config-sysfs-interface.patch b/patches.suse/scsi-qla2xxx-Add-beacon-LED-config-sysfs-interface.patch new file mode 100644 index 0000000..36e6490 --- /dev/null +++ b/patches.suse/scsi-qla2xxx-Add-beacon-LED-config-sysfs-interface.patch @@ -0,0 +1,225 @@ +From: Joe Carnuccio +Date: Wed, 12 Feb 2020 13:44:12 -0800 +Subject: scsi: qla2xxx: Add beacon LED config sysfs interface +Patch-mainline: v5.7-rc1 +Git-commit: 07553b1e83b46414caa693ba10d1a16487409b61 +References: bsc#1157424 + +This patch provides an interface to do the following (using MBC 0x3B): + + - Displays (in hex) the LED config words for all three LEDs. + + - Programs the config words for one LED or for all three LEDs. + +The sysfs node defined is named beacon_config. + +First, to allow driver to gain LED control, do this: + # echo 1 > /sys/class/scsi_host/host#/beacon + +Then, to display config words for all three LEDs do this: + # cat /sys/class/scsi_host/host#/beacon_config + +To set config words for all three LEDs do this: + # echo 3 xxxx yyyy zzzz > /sys/class/scsi_host/host#/beacon_config + +Or, to set config word for a specific single LED n do this: + # echo n xxxx > /sys/class/scsi_host/host#/beacon_config + where n is the LED number (0, 1, 2) + +Finally, to restore LED control back to firmware, do this: + # echo 0 > /sys/class/scsi_host/host#/beacon + +Link: https://lore.kernel.org/r/20200212214436.25532-2-hmadhani@marvell.com +Signed-off-by: Joe Carnuccio +Signed-off-by: Himanshu Madhani +Signed-off-by: Martin K. Petersen +Acked-by: Daniel Wagner +--- + drivers/scsi/qla2xxx/qla_attr.c | 76 ++++++++++++++++++++++++++++++++++++++++ + drivers/scsi/qla2xxx/qla_def.h | 1 + drivers/scsi/qla2xxx/qla_gbl.h | 1 + drivers/scsi/qla2xxx/qla_mbx.c | 57 ++++++++++++++++++++++++++++++ + 4 files changed, 135 insertions(+) + +--- a/drivers/scsi/qla2xxx/qla_attr.c ++++ b/drivers/scsi/qla2xxx/qla_attr.c +@@ -1324,6 +1324,79 @@ qla2x00_beacon_store(struct device *dev, + } + + static ssize_t ++qla2x00_beacon_config_show(struct device *dev, struct device_attribute *attr, ++ char *buf) ++{ ++ scsi_qla_host_t *vha = shost_priv(class_to_shost(dev)); ++ struct qla_hw_data *ha = vha->hw; ++ uint16_t led[3] = { 0 }; ++ ++ if (!IS_QLA2031(ha) && !IS_QLA27XX(ha) && !IS_QLA28XX(ha)) ++ return -EPERM; ++ ++ if (ql26xx_led_config(vha, 0, led)) ++ return scnprintf(buf, PAGE_SIZE, "\n"); ++ ++ return scnprintf(buf, PAGE_SIZE, "%#04hx %#04hx %#04hx\n", ++ led[0], led[1], led[2]); ++} ++ ++static ssize_t ++qla2x00_beacon_config_store(struct device *dev, struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ scsi_qla_host_t *vha = shost_priv(class_to_shost(dev)); ++ struct qla_hw_data *ha = vha->hw; ++ uint16_t options = BIT_0; ++ uint16_t led[3] = { 0 }; ++ uint16_t word[4]; ++ int n; ++ ++ if (!IS_QLA2031(ha) && !IS_QLA27XX(ha) && !IS_QLA28XX(ha)) ++ return -EPERM; ++ ++ n = sscanf(buf, "%hx %hx %hx %hx", word+0, word+1, word+2, word+3); ++ if (n == 4) { ++ if (word[0] == 3) { ++ options |= BIT_3|BIT_2|BIT_1; ++ led[0] = word[1]; ++ led[1] = word[2]; ++ led[2] = word[3]; ++ goto write; ++ } ++ return -EINVAL; ++ } ++ ++ if (n == 2) { ++ /* check led index */ ++ if (word[0] == 0) { ++ options |= BIT_2; ++ led[0] = word[1]; ++ goto write; ++ } ++ if (word[0] == 1) { ++ options |= BIT_3; ++ led[1] = word[1]; ++ goto write; ++ } ++ if (word[0] == 2) { ++ options |= BIT_1; ++ led[2] = word[1]; ++ goto write; ++ } ++ return -EINVAL; ++ } ++ ++ return -EINVAL; ++ ++write: ++ if (ql26xx_led_config(vha, options, led)) ++ return -EFAULT; ++ ++ return count; ++} ++ ++static ssize_t + qla2x00_optrom_bios_version_show(struct device *dev, + struct device_attribute *attr, char *buf) + { +@@ -2264,6 +2337,8 @@ static DEVICE_ATTR(zio_timer, S_IRUGO | + qla2x00_zio_timer_store); + static DEVICE_ATTR(beacon, S_IRUGO | S_IWUSR, qla2x00_beacon_show, + qla2x00_beacon_store); ++static DEVICE_ATTR(beacon_config, 0644, qla2x00_beacon_config_show, ++ qla2x00_beacon_config_store); + static DEVICE_ATTR(optrom_bios_version, S_IRUGO, + qla2x00_optrom_bios_version_show, NULL); + static DEVICE_ATTR(optrom_efi_version, S_IRUGO, +@@ -2327,6 +2402,7 @@ struct device_attribute *qla2x00_host_at + &dev_attr_zio, + &dev_attr_zio_timer, + &dev_attr_beacon, ++ &dev_attr_beacon_config, + &dev_attr_optrom_bios_version, + &dev_attr_optrom_efi_version, + &dev_attr_optrom_fcode_version, +--- a/drivers/scsi/qla2xxx/qla_def.h ++++ b/drivers/scsi/qla2xxx/qla_def.h +@@ -1134,6 +1134,7 @@ static inline bool qla2xxx_is_valid_mbs( + #define MBC_GET_FIRMWARE_OPTION 0x28 /* Get Firmware Options. */ + #define MBC_GET_MEM_OFFLOAD_CNTRL_STAT 0x34 /* Memory Offload ctrl/Stat*/ + #define MBC_SET_FIRMWARE_OPTION 0x38 /* Set Firmware Options. */ ++#define MBC_SET_GET_FC_LED_CONFIG 0x3b /* Set/Get FC LED config */ + #define MBC_LOOP_PORT_BYPASS 0x40 /* Loop Port Bypass. */ + #define MBC_LOOP_PORT_ENABLE 0x41 /* Loop Port Enable. */ + #define MBC_GET_RESOURCE_COUNTS 0x42 /* Get Resource Counts. */ +--- a/drivers/scsi/qla2xxx/qla_gbl.h ++++ b/drivers/scsi/qla2xxx/qla_gbl.h +@@ -844,6 +844,7 @@ extern void qla82xx_clear_pending_mbx(sc + extern int qla82xx_read_temperature(scsi_qla_host_t *); + extern int qla8044_read_temperature(scsi_qla_host_t *); + extern int qla2x00_read_sfp_dev(struct scsi_qla_host *, char *, int); ++extern int ql26xx_led_config(scsi_qla_host_t *, uint16_t, uint16_t *); + + /* BSG related functions */ + extern int qla24xx_bsg_request(struct bsg_job *); +--- a/drivers/scsi/qla2xxx/qla_mbx.c ++++ b/drivers/scsi/qla2xxx/qla_mbx.c +@@ -6688,3 +6688,60 @@ int qla2xxx_read_remote_register(scsi_ql + + return rval; + } ++ ++int ++ql26xx_led_config(scsi_qla_host_t *vha, uint16_t options, uint16_t *led) ++{ ++ struct qla_hw_data *ha = vha->hw; ++ mbx_cmd_t mc; ++ mbx_cmd_t *mcp = &mc; ++ int rval; ++ ++ if (!IS_QLA2031(ha) && !IS_QLA27XX(ha) && !IS_QLA28XX(ha)) ++ return QLA_FUNCTION_FAILED; ++ ++ ql_dbg(ql_dbg_mbx, vha, 0x7070, "Entered %s (options=%x).\n", ++ __func__, options); ++ ++ mcp->mb[0] = MBC_SET_GET_FC_LED_CONFIG; ++ mcp->mb[1] = options; ++ mcp->out_mb = MBX_1|MBX_0; ++ mcp->in_mb = MBX_1|MBX_0; ++ if (options & BIT_0) { ++ if (options & BIT_1) { ++ mcp->mb[2] = led[2]; ++ mcp->out_mb |= MBX_2; ++ } ++ if (options & BIT_2) { ++ mcp->mb[3] = led[0]; ++ mcp->out_mb |= MBX_3; ++ } ++ if (options & BIT_3) { ++ mcp->mb[4] = led[1]; ++ mcp->out_mb |= MBX_4; ++ } ++ } else { ++ mcp->in_mb |= MBX_4|MBX_3|MBX_2; ++ } ++ mcp->tov = MBX_TOV_SECONDS; ++ mcp->flags = 0; ++ rval = qla2x00_mailbox_command(vha, mcp); ++ if (rval) { ++ ql_dbg(ql_dbg_mbx, vha, 0x7071, "Failed %s %x (mb=%x,%x)\n", ++ __func__, rval, mcp->mb[0], mcp->mb[1]); ++ return rval; ++ } ++ ++ if (options & BIT_0) { ++ ha->beacon_blink_led = 0; ++ ql_dbg(ql_dbg_mbx, vha, 0x7072, "Done %s\n", __func__); ++ } else { ++ led[2] = mcp->mb[2]; ++ led[0] = mcp->mb[3]; ++ led[1] = mcp->mb[4]; ++ ql_dbg(ql_dbg_mbx, vha, 0x7073, "Done %s (led=%x,%x,%x)\n", ++ __func__, led[0], led[1], led[2]); ++ } ++ ++ return rval; ++} diff --git a/patches.suse/scsi-qla2xxx-Add-changes-in-preparation-for-vendor-e.patch b/patches.suse/scsi-qla2xxx-Add-changes-in-preparation-for-vendor-e.patch new file mode 100644 index 0000000..4a13614 --- /dev/null +++ b/patches.suse/scsi-qla2xxx-Add-changes-in-preparation-for-vendor-e.patch @@ -0,0 +1,441 @@ +From: Joe Carnuccio +Date: Wed, 12 Feb 2020 13:44:17 -0800 +Subject: scsi: qla2xxx: Add changes in preparation for vendor extended + FDMI/RDP +Patch-mainline: v5.7-rc1 +Git-commit: 818c7f87a177781bc155a2bfa39066c89c5a6cdc +References: bsc#1157424 + +This patch prepares code for implementing Vendor specific extended FDMI/RDP +commands. It also addes support for MBC_GET_PORT_DATABASE and +MBC_GET_RNID_PARAMS commands. + +Link: https://lore.kernel.org/r/20200212214436.25532-7-hmadhani@marvell.com +Signed-off-by: Joe Carnuccio +Signed-off-by: Himanshu Madhani +Signed-off-by: Martin K. Petersen +Acked-by: Daniel Wagner +--- + drivers/scsi/qla2xxx/qla_def.h | 3 + drivers/scsi/qla2xxx/qla_fw.h | 4 + + drivers/scsi/qla2xxx/qla_gbl.h | 12 +++ + drivers/scsi/qla2xxx/qla_gs.c | 15 ++-- + drivers/scsi/qla2xxx/qla_init.c | 28 ++++++--- + drivers/scsi/qla2xxx/qla_mbx.c | 121 ++++++++++++++++++++++++++++++++++------ + drivers/scsi/qla2xxx/qla_mid.c | 3 + drivers/scsi/qla2xxx/qla_os.c | 4 - + 8 files changed, 155 insertions(+), 35 deletions(-) + +--- a/drivers/scsi/qla2xxx/qla_def.h ++++ b/drivers/scsi/qla2xxx/qla_def.h +@@ -1261,7 +1261,9 @@ static inline bool qla2xxx_is_valid_mbs( + #define MBX_1 BIT_1 + #define MBX_0 BIT_0 + ++#define RNID_TYPE_ELS_CMD 0x5 + #define RNID_TYPE_PORT_LOGIN 0x7 ++#define RNID_BUFFER_CREDITS 0x8 + #define RNID_TYPE_SET_VERSION 0x9 + #define RNID_TYPE_ASIC_TEMP 0xC + +@@ -4459,6 +4461,7 @@ typedef struct scsi_qla_host { + uint8_t node_name[WWN_SIZE]; + uint8_t port_name[WWN_SIZE]; + uint8_t fabric_node_name[WWN_SIZE]; ++ uint8_t fabric_port_name[WWN_SIZE]; + + struct nvme_fc_local_port *nvme_local_port; + struct completion nvme_del_done; +--- a/drivers/scsi/qla2xxx/qla_fw.h ++++ b/drivers/scsi/qla2xxx/qla_fw.h +@@ -31,6 +31,9 @@ + #define PDO_FORCE_ADISC BIT_1 + #define PDO_FORCE_PLOGI BIT_0 + ++struct buffer_credit_24xx { ++ u32 parameter[28]; ++}; + + #define PORT_DATABASE_24XX_SIZE 64 + struct port_database_24xx { +@@ -1883,6 +1886,7 @@ struct nvram_81xx { + * BIT 6-15 = Unused + */ + uint16_t enhanced_features; ++ + uint16_t reserved_24[4]; + + /* Offset 416. */ +--- a/drivers/scsi/qla2xxx/qla_gbl.h ++++ b/drivers/scsi/qla2xxx/qla_gbl.h +@@ -32,6 +32,8 @@ extern int qla81xx_nvram_config(struct s + extern void qla2x00_update_fw_options(struct scsi_qla_host *); + extern void qla24xx_update_fw_options(scsi_qla_host_t *); + extern void qla81xx_update_fw_options(scsi_qla_host_t *); ++extern void qla83xx_update_fw_options(scsi_qla_host_t *); ++ + extern int qla2x00_load_risc(struct scsi_qla_host *, uint32_t *); + extern int qla24xx_load_risc(scsi_qla_host_t *, uint32_t *); + extern int qla81xx_load_risc(scsi_qla_host_t *, uint32_t *); +@@ -142,6 +144,7 @@ extern int qlport_down_retry; + extern int ql2xplogiabsentdevice; + extern int ql2xloginretrycount; + extern int ql2xfdmienable; ++extern int ql2xsmartsan; + extern int ql2xallocfwdump; + extern int ql2xextended_error_logging; + extern int ql2xiidmaenable; +@@ -354,6 +357,9 @@ extern int + qla2x00_get_port_database(scsi_qla_host_t *, fc_port_t *, uint8_t); + + extern int ++qla24xx_get_port_database(scsi_qla_host_t *, u16, struct port_database_24xx *); ++ ++extern int + qla2x00_get_firmware_state(scsi_qla_host_t *, uint16_t *); + + extern int +@@ -452,6 +458,10 @@ extern int + qla25xx_set_driver_version(scsi_qla_host_t *, char *); + + extern int ++qla24xx_get_buffer_credits(scsi_qla_host_t *, struct buffer_credit_24xx *, ++ dma_addr_t); ++ ++extern int + qla2x00_read_sfp(scsi_qla_host_t *, dma_addr_t, uint8_t *, + uint16_t, uint16_t, uint16_t, uint16_t); + +@@ -656,7 +666,7 @@ extern void *qla24xx_prep_ms_fdmi_iocb(s + extern int qla2x00_fdmi_register(scsi_qla_host_t *); + extern int qla2x00_gfpn_id(scsi_qla_host_t *, sw_info_t *); + extern int qla2x00_gpsc(scsi_qla_host_t *, sw_info_t *); +-extern void qla2x00_get_sym_node_name(scsi_qla_host_t *, uint8_t *, size_t); ++extern size_t qla2x00_get_sym_node_name(scsi_qla_host_t *, uint8_t *, size_t); + extern int qla2x00_chk_ms_status(scsi_qla_host_t *, ms_iocb_entry_t *, + struct ct_sns_rsp *, const char *); + extern void qla2x00_async_iocb_timeout(void *data); +--- a/drivers/scsi/qla2xxx/qla_gs.c ++++ b/drivers/scsi/qla2xxx/qla_gs.c +@@ -844,19 +844,18 @@ done: + return rval; + } + +-void ++size_t + qla2x00_get_sym_node_name(scsi_qla_host_t *vha, uint8_t *snn, size_t size) + { + struct qla_hw_data *ha = vha->hw; + + if (IS_QLAFX00(ha)) +- snprintf(snn, size, "%s FW:v%s DVR:v%s", ha->model_number, +- ha->mr.fw_version, qla2x00_version_str); +- else +- snprintf(snn, size, +- "%s FW:v%d.%02d.%02d DVR:v%s", ha->model_number, +- ha->fw_major_version, ha->fw_minor_version, +- ha->fw_subminor_version, qla2x00_version_str); ++ return scnprintf(snn, size, "%s FW:v%s DVR:v%s", ++ ha->model_number, ha->mr.fw_version, qla2x00_version_str); ++ ++ return scnprintf(snn, size, "%s FW:v%d.%02d.%02d DVR:v%s", ++ ha->model_number, ha->fw_major_version, ha->fw_minor_version, ++ ha->fw_subminor_version, qla2x00_version_str); + } + + /** +--- a/drivers/scsi/qla2xxx/qla_init.c ++++ b/drivers/scsi/qla2xxx/qla_init.c +@@ -5541,24 +5541,22 @@ qla2x00_configure_fabric(scsi_qla_host_t + } + vha->device_flags |= SWITCH_FOUND; + ++ rval = qla2x00_get_port_name(vha, loop_id, vha->fabric_port_name, 0); ++ if (rval != QLA_SUCCESS) ++ ql_dbg(ql_dbg_disc, vha, 0x20ff, ++ "Failed to get Fabric Port Name\n"); + + if (qla_tgt_mode_enabled(vha) || qla_dual_mode_enabled(vha)) { + rval = qla2x00_send_change_request(vha, 0x3, 0); + if (rval != QLA_SUCCESS) + ql_log(ql_log_warn, vha, 0x121, +- "Failed to enable receiving of RSCN requests: 0x%x.\n", +- rval); ++ "Failed to enable receiving of RSCN requests: 0x%x.\n", ++ rval); + } + +- + do { + qla2x00_mgmt_svr_login(vha); + +- /* FDMI support. */ +- if (ql2xfdmienable && +- test_and_clear_bit(REGISTER_FDMI_NEEDED, &vha->dpc_flags)) +- qla2x00_fdmi_register(vha); +- + /* Ensure we are logged into the SNS. */ + loop_id = NPH_SNS_LID(ha); + rval = ha->isp_ops->fabric_login(vha, loop_id, 0xff, 0xff, +@@ -5570,6 +5568,12 @@ qla2x00_configure_fabric(scsi_qla_host_t + set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags); + return rval; + } ++ ++ /* FDMI support. */ ++ if (ql2xfdmienable && ++ test_and_clear_bit(REGISTER_FDMI_NEEDED, &vha->dpc_flags)) ++ qla2x00_fdmi_register(vha); ++ + if (test_and_clear_bit(REGISTER_FC4_NEEDED, &vha->dpc_flags)) { + if (qla2x00_rft_id(vha)) { + /* EMPTY */ +@@ -8664,6 +8668,14 @@ qla82xx_restart_isp(scsi_qla_host_t *vha + } + + void ++qla83xx_update_fw_options(scsi_qla_host_t *vha) ++{ ++ struct qla_hw_data *ha = vha->hw; ++ ++ qla2x00_set_fw_options(vha, ha->fw_options); ++} ++ ++void + qla81xx_update_fw_options(scsi_qla_host_t *vha) + { + struct qla_hw_data *ha = vha->hw; +--- a/drivers/scsi/qla2xxx/qla_mbx.c ++++ b/drivers/scsi/qla2xxx/qla_mbx.c +@@ -643,7 +643,6 @@ qla2x00_load_ram(scsi_qla_host_t *vha, d + return rval; + } + +-#define EXTENDED_BB_CREDITS BIT_0 + #define NVME_ENABLE_FLAG BIT_3 + static inline uint16_t qla25xx_set_sfp_lr_dist(struct qla_hw_data *ha) + { +@@ -1410,12 +1409,12 @@ qla2x00_issue_iocb_timeout(scsi_qla_host + + mcp->mb[0] = MBC_IOCB_COMMAND_A64; + mcp->mb[1] = 0; +- mcp->mb[2] = MSW(phys_addr); +- mcp->mb[3] = LSW(phys_addr); ++ mcp->mb[2] = MSW(LSD(phys_addr)); ++ mcp->mb[3] = LSW(LSD(phys_addr)); + mcp->mb[6] = MSW(MSD(phys_addr)); + mcp->mb[7] = LSW(MSD(phys_addr)); + mcp->out_mb = MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0; +- mcp->in_mb = MBX_2|MBX_0; ++ mcp->in_mb = MBX_1|MBX_0; + mcp->tov = tov; + mcp->flags = 0; + rval = qla2x00_mailbox_command(vha, mcp); +@@ -1424,13 +1423,14 @@ qla2x00_issue_iocb_timeout(scsi_qla_host + /*EMPTY*/ + ql_dbg(ql_dbg_mbx, vha, 0x1039, "Failed=%x.\n", rval); + } else { +- sts_entry_t *sts_entry = (sts_entry_t *) buffer; ++ sts_entry_t *sts_entry = buffer; + + /* Mask reserved bits. */ + sts_entry->entry_status &= + IS_FWI2_CAPABLE(vha->hw) ? RF_MASK_24XX : RF_MASK; + ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x103a, +- "Done %s.\n", __func__); ++ "Done %s (status=%x).\n", __func__, ++ sts_entry->entry_status); + } + + return rval; +@@ -2045,6 +2045,57 @@ gpd_error_out: + return rval; + } + ++int ++qla24xx_get_port_database(scsi_qla_host_t *vha, u16 nport_handle, ++ struct port_database_24xx *pdb) ++{ ++ mbx_cmd_t mc; ++ mbx_cmd_t *mcp = &mc; ++ dma_addr_t pdb_dma; ++ int rval; ++ ++ ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1115, ++ "Entered %s.\n", __func__); ++ ++ memset(pdb, 0, sizeof(*pdb)); ++ ++ pdb_dma = dma_map_single(&vha->hw->pdev->dev, pdb, ++ sizeof(*pdb), DMA_FROM_DEVICE); ++ if (!pdb_dma) { ++ ql_log(ql_log_warn, vha, 0x1116, "Failed to map dma buffer.\n"); ++ return QLA_MEMORY_ALLOC_FAILED; ++ } ++ ++ mcp->mb[0] = MBC_GET_PORT_DATABASE; ++ mcp->mb[1] = nport_handle; ++ mcp->mb[2] = MSW(LSD(pdb_dma)); ++ mcp->mb[3] = LSW(LSD(pdb_dma)); ++ mcp->mb[6] = MSW(MSD(pdb_dma)); ++ mcp->mb[7] = LSW(MSD(pdb_dma)); ++ mcp->mb[9] = 0; ++ mcp->mb[10] = 0; ++ mcp->out_mb = MBX_10|MBX_9|MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0; ++ mcp->in_mb = MBX_1|MBX_0; ++ mcp->buf_size = sizeof(*pdb); ++ mcp->flags = MBX_DMA_IN; ++ mcp->tov = vha->hw->login_timeout * 2; ++ rval = qla2x00_mailbox_command(vha, mcp); ++ ++ if (rval != QLA_SUCCESS) { ++ ql_dbg(ql_dbg_mbx, vha, 0x111a, ++ "Failed=%x mb[0]=%x mb[1]=%x.\n", ++ rval, mcp->mb[0], mcp->mb[1]); ++ } else { ++ ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x111b, ++ "Done %s.\n", __func__); ++ } ++ ++ dma_unmap_single(&vha->hw->pdev->dev, pdb_dma, ++ sizeof(*pdb), DMA_FROM_DEVICE); ++ ++ return rval; ++} ++ + /* + * qla2x00_get_firmware_state + * Get adapter firmware state. +@@ -3060,18 +3111,19 @@ qla24xx_get_isp_stats(scsi_qla_host_t *v + int rval; + mbx_cmd_t mc; + mbx_cmd_t *mcp = &mc; +- uint32_t *iter, dwords; ++ uint32_t *iter = (void *)stats; ++ ushort dwords = sizeof(*stats)/sizeof(*iter); + + ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1088, + "Entered %s.\n", __func__); + + memset(&mc, 0, sizeof(mc)); + mc.mb[0] = MBC_GET_LINK_PRIV_STATS; +- mc.mb[2] = MSW(stats_dma); +- mc.mb[3] = LSW(stats_dma); ++ mc.mb[2] = MSW(LSD(stats_dma)); ++ mc.mb[3] = LSW(LSD(stats_dma)); + mc.mb[6] = MSW(MSD(stats_dma)); + mc.mb[7] = LSW(MSD(stats_dma)); +- mc.mb[8] = sizeof(struct link_statistics) / 4; ++ mc.mb[8] = dwords; + mc.mb[9] = cpu_to_le16(vha->vp_idx); + mc.mb[10] = cpu_to_le16(options); + +@@ -3086,8 +3138,6 @@ qla24xx_get_isp_stats(scsi_qla_host_t *v + ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x108a, + "Done %s.\n", __func__); + /* Re-endianize - firmware data is le32. */ +- dwords = sizeof(struct link_statistics) / 4; +- iter = &stats->link_fail_cnt; + for ( ; dwords--; iter++) + le32_to_cpus(iter); + } +@@ -4827,6 +4877,45 @@ qla24xx_get_port_login_templ(scsi_qla_ho + return rval; + } + ++int ++qla24xx_get_buffer_credits(scsi_qla_host_t *vha, struct buffer_credit_24xx *bbc, ++ dma_addr_t bbc_dma) ++{ ++ mbx_cmd_t mc; ++ mbx_cmd_t *mcp = &mc; ++ int rval; ++ ++ if (!IS_FWI2_CAPABLE(vha->hw)) ++ return QLA_FUNCTION_FAILED; ++ ++ ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x118e, ++ "Entered %s.\n", __func__); ++ ++ mcp->mb[0] = MBC_GET_RNID_PARAMS; ++ mcp->mb[1] = RNID_BUFFER_CREDITS << 8; ++ mcp->mb[2] = MSW(LSD(bbc_dma)); ++ mcp->mb[3] = LSW(LSD(bbc_dma)); ++ mcp->mb[6] = MSW(MSD(bbc_dma)); ++ mcp->mb[7] = LSW(MSD(bbc_dma)); ++ mcp->mb[8] = sizeof(*bbc) / sizeof(*bbc->parameter); ++ mcp->out_mb = MBX_8|MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0; ++ mcp->in_mb = MBX_1|MBX_0; ++ mcp->buf_size = sizeof(*bbc); ++ mcp->flags = MBX_DMA_IN; ++ mcp->tov = MBX_TOV_SECONDS; ++ rval = qla2x00_mailbox_command(vha, mcp); ++ ++ if (rval != QLA_SUCCESS) { ++ ql_dbg(ql_dbg_mbx, vha, 0x118f, ++ "Failed=%x mb[0]=%x,%x.\n", rval, mcp->mb[0], mcp->mb[1]); ++ } else { ++ ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1190, ++ "Done %s.\n", __func__); ++ } ++ ++ return rval; ++} ++ + static int + qla2x00_read_asic_temperature(scsi_qla_host_t *vha, uint16_t *temp) + { +@@ -4880,8 +4969,8 @@ qla2x00_read_sfp(scsi_qla_host_t *vha, d + + mcp->mb[0] = MBC_READ_SFP; + mcp->mb[1] = dev; +- mcp->mb[2] = MSW(sfp_dma); +- mcp->mb[3] = LSW(sfp_dma); ++ mcp->mb[2] = MSW(LSD(sfp_dma)); ++ mcp->mb[3] = LSW(LSD(sfp_dma)); + mcp->mb[6] = MSW(MSD(sfp_dma)); + mcp->mb[7] = LSW(MSD(sfp_dma)); + mcp->mb[8] = len; +@@ -4934,8 +5023,8 @@ qla2x00_write_sfp(scsi_qla_host_t *vha, + + mcp->mb[0] = MBC_WRITE_SFP; + mcp->mb[1] = dev; +- mcp->mb[2] = MSW(sfp_dma); +- mcp->mb[3] = LSW(sfp_dma); ++ mcp->mb[2] = MSW(LSD(sfp_dma)); ++ mcp->mb[3] = LSW(LSD(sfp_dma)); + mcp->mb[6] = MSW(MSD(sfp_dma)); + mcp->mb[7] = LSW(MSD(sfp_dma)); + mcp->mb[8] = len; +--- a/drivers/scsi/qla2xxx/qla_mid.c ++++ b/drivers/scsi/qla2xxx/qla_mid.c +@@ -509,6 +509,9 @@ qla24xx_create_vhost(struct fc_vport *fc + vha->mgmt_svr_loop_id = qla2x00_reserve_mgmt_server_loop_id(vha); + + vha->dpc_flags = 0L; ++ ha->dpc_active = 0; ++ set_bit(REGISTER_FDMI_NEEDED, &vha->dpc_flags); ++ set_bit(REGISTER_FC4_NEEDED, &vha->dpc_flags); + + /* + * To fix the issue of processing a parent's RSCN for the vport before +--- a/drivers/scsi/qla2xxx/qla_os.c ++++ b/drivers/scsi/qla2xxx/qla_os.c +@@ -2293,7 +2293,7 @@ static struct isp_operations qla81xx_isp + .config_rings = qla24xx_config_rings, + .reset_adapter = qla24xx_reset_adapter, + .nvram_config = qla81xx_nvram_config, +- .update_fw_options = qla81xx_update_fw_options, ++ .update_fw_options = qla83xx_update_fw_options, + .load_risc = qla81xx_load_risc, + .pci_info_str = qla24xx_pci_info_str, + .fw_version_str = qla24xx_fw_version_str, +@@ -2410,7 +2410,7 @@ static struct isp_operations qla83xx_isp + .config_rings = qla24xx_config_rings, + .reset_adapter = qla24xx_reset_adapter, + .nvram_config = qla81xx_nvram_config, +- .update_fw_options = qla81xx_update_fw_options, ++ .update_fw_options = qla83xx_update_fw_options, + .load_risc = qla81xx_load_risc, + .pci_info_str = qla24xx_pci_info_str, + .fw_version_str = qla24xx_fw_version_str, diff --git a/patches.suse/scsi-qla2xxx-Add-deferred-queue-for-processing-ABTS-.patch b/patches.suse/scsi-qla2xxx-Add-deferred-queue-for-processing-ABTS-.patch new file mode 100644 index 0000000..b256ae0 --- /dev/null +++ b/patches.suse/scsi-qla2xxx-Add-deferred-queue-for-processing-ABTS-.patch @@ -0,0 +1,526 @@ +From: Joe Carnuccio +Date: Wed, 12 Feb 2020 13:44:24 -0800 +Subject: scsi: qla2xxx: Add deferred queue for processing ABTS and RDP +Patch-mainline: v5.7-rc1 +Git-commit: 576bfde80b28232a1dfcf0466986ed2934146d0a +References: bsc#1157424 + +This patch adds deferred queue for processing aborts and RDP in the driver. + +Link: https://lore.kernel.org/r/20200212214436.25532-14-hmadhani@marvell.com +Signed-off-by: Joe Carnuccio +Signed-off-by: Himanshu Madhani +Signed-off-by: Martin K. Petersen +Acked-by: Daniel Wagner +--- + drivers/scsi/qla2xxx/qla_def.h | 15 +++ + drivers/scsi/qla2xxx/qla_fw.h | 91 +++++++++++++++++++++++- + drivers/scsi/qla2xxx/qla_gbl.h | 2 + drivers/scsi/qla2xxx/qla_isr.c | 154 +++++++++++++++++++++++++++++++++++++++-- + drivers/scsi/qla2xxx/qla_mid.c | 7 + + drivers/scsi/qla2xxx/qla_os.c | 62 +++++++++++----- + 6 files changed, 304 insertions(+), 27 deletions(-) + +--- a/drivers/scsi/qla2xxx/qla_def.h ++++ b/drivers/scsi/qla2xxx/qla_def.h +@@ -4474,6 +4474,15 @@ struct active_regions { + #define QLA_SET_DATA_RATE_NOLR 1 + #define QLA_SET_DATA_RATE_LR 2 /* Set speed and initiate LR */ + ++struct purex_item { ++ struct list_head list; ++ struct scsi_qla_host *vha; ++ void (*process_item)(struct scsi_qla_host *vha, void *pkt); ++ struct { ++ uint8_t iocb[64]; ++ } iocb; ++}; ++ + /* + * Qlogic scsi host structure + */ +@@ -4664,7 +4673,11 @@ typedef struct scsi_qla_host { + uint16_t ql2xexchoffld; + uint16_t ql2xiniexchg; + +- void *purex_data; ++ struct purex_list { ++ struct list_head head; ++ spinlock_t lock; ++ } purex_list; ++ + struct name_list_extended gnl; + /* Count of active session/fcport */ + int fcport_count; +--- a/drivers/scsi/qla2xxx/qla_fw.h ++++ b/drivers/scsi/qla2xxx/qla_fw.h +@@ -727,7 +727,7 @@ struct ct_entry_24xx { + * ISP queue - PUREX IOCB entry structure definition + */ + #define PUREX_IOCB_TYPE 0x51 /* CT Pass Through IOCB entry */ +-typedef struct purex_entry_24xx { ++struct purex_entry_24xx { + uint8_t entry_type; /* Entry type. */ + uint8_t entry_count; /* Entry count. */ + uint8_t sys_define; /* System defined. */ +@@ -763,9 +763,7 @@ typedef struct purex_entry_24xx { + uint32_t param; + + uint8_t els_frame_payload[20]; +-} purex_entry_24xx_t; +- +-#define PUREX_ENTRY_SIZE (sizeof(purex_entry_24xx_t)) ++}; + + /* + * ISP queue - ELS Pass-Through entry structure definition. +@@ -1000,6 +998,91 @@ struct abort_entry_24xx { + uint8_t reserved_2[12]; + }; + ++#define ABTS_RCV_TYPE 0x54 ++#define ABTS_RSP_TYPE 0x55 ++struct abts_entry_24xx { ++ uint8_t entry_type; ++ uint8_t entry_count; ++ uint8_t handle_count; ++ uint8_t entry_status; ++ ++ uint32_t handle; /* type 0x55 only */ ++ ++ uint16_t comp_status; /* type 0x55 only */ ++ uint16_t nport_handle; /* type 0x54 only */ ++ ++ uint16_t control_flags; /* type 0x55 only */ ++ uint8_t vp_idx; ++ uint8_t sof_type; /* sof_type is upper nibble */ ++ ++ uint32_t rx_xch_addr; ++ ++ uint8_t d_id[3]; ++ uint8_t r_ctl; ++ ++ uint8_t s_id[3]; ++ uint8_t cs_ctl; ++ ++ uint8_t f_ctl[3]; ++ uint8_t type; ++ ++ uint16_t seq_cnt; ++ uint8_t df_ctl; ++ uint8_t seq_id; ++ ++ uint16_t rx_id; ++ uint16_t ox_id; ++ ++ uint32_t param; ++ ++ union { ++ struct { ++ uint32_t subcode3; ++ uint32_t rsvd; ++ uint32_t subcode1; ++ uint32_t subcode2; ++ } error; ++ struct { ++ uint16_t rsrvd1; ++ uint8_t last_seq_id; ++ uint8_t seq_id_valid; ++ uint16_t aborted_rx_id; ++ uint16_t aborted_ox_id; ++ uint16_t high_seq_cnt; ++ uint16_t low_seq_cnt; ++ } ba_acc; ++ struct { ++ uint8_t vendor_unique; ++ uint8_t explanation; ++ uint8_t reason; ++ } ba_rjt; ++ } payload; ++ ++ uint32_t rx_xch_addr_to_abort; ++} __packed; ++ ++/* ABTS payload explanation values */ ++#define BA_RJT_EXP_NO_ADDITIONAL 0 ++#define BA_RJT_EXP_INV_OX_RX_ID 3 ++#define BA_RJT_EXP_SEQ_ABORTED 5 ++ ++/* ABTS payload reason values */ ++#define BA_RJT_RSN_INV_CMD_CODE 1 ++#define BA_RJT_RSN_LOGICAL_ERROR 3 ++#define BA_RJT_RSN_LOGICAL_BUSY 5 ++#define BA_RJT_RSN_PROTOCOL_ERROR 7 ++#define BA_RJT_RSN_UNABLE_TO_PERFORM 9 ++#define BA_RJT_RSN_VENDOR_SPECIFIC 0xff ++ ++/* FC_F values */ ++#define FC_TYPE_BLD 0x000 /* Basic link data */ ++#define FC_F_CTL_RSP_CNTXT 0x800000 /* Responder of exchange */ ++#define FC_F_CTL_LAST_SEQ 0x100000 /* Last sequence */ ++#define FC_F_CTL_END_SEQ 0x80000 /* Last sequence */ ++#define FC_F_CTL_SEQ_INIT 0x010000 /* Sequence initiative */ ++#define FC_ROUTING_BLD 0x80 /* Basic link data frame */ ++#define FC_R_CTL_BLD_BA_ACC 0x04 /* BA_ACC (basic accept) */ ++ + /* + * ISP I/O Register Set structure definitions. + */ +--- a/drivers/scsi/qla2xxx/qla_gbl.h ++++ b/drivers/scsi/qla2xxx/qla_gbl.h +@@ -230,6 +230,7 @@ void qla2x00_handle_login_done_event(str + int qla24xx_post_gnl_work(struct scsi_qla_host *, fc_port_t *); + int qla24xx_post_relogin_work(struct scsi_qla_host *vha); + void qla2x00_wait_for_sess_deletion(scsi_qla_host_t *); ++void qla24xx_process_purex_rdp(struct scsi_qla_host *vha, void *pkt); + + /* + * Global Functions in qla_mid.c source file. +@@ -928,6 +929,7 @@ void qlt_remove_target_resources(struct + void qlt_clr_qp_table(struct scsi_qla_host *vha); + void qlt_set_mode(struct scsi_qla_host *); + int qla2x00_set_data_rate(scsi_qla_host_t *vha, uint16_t mode); ++extern void qla24xx_process_purex_list(struct purex_list *); + + /* nvme.c */ + void qla_nvme_unregister_remote_port(struct fc_port *fcport); +--- a/drivers/scsi/qla2xxx/qla_isr.c ++++ b/drivers/scsi/qla2xxx/qla_isr.c +@@ -31,13 +31,144 @@ const char *const port_state_str[] = { + "ONLINE" + }; + +-static void qla24xx_purex_iocb(scsi_qla_host_t *vha, struct req_que *req, +- struct sts_entry_24xx *pkt) ++static void qla24xx_purex_iocb(scsi_qla_host_t *vha, void *pkt, ++ void (*process_item)(struct scsi_qla_host *vha, void *pkt)) + { +- memcpy(vha->purex_data, pkt, PUREX_ENTRY_SIZE); ++ struct purex_list *list = &vha->purex_list; ++ struct purex_item *item; ++ ulong flags; ++ ++ item = kzalloc(sizeof(*item), GFP_KERNEL); ++ if (!item) { ++ ql_log(ql_log_warn, vha, 0x5092, ++ ">> Failed allocate purex list item.\n"); ++ return; ++ } ++ ++ item->vha = vha; ++ item->process_item = process_item; ++ memcpy(&item->iocb, pkt, sizeof(item->iocb)); ++ ++ spin_lock_irqsave(&list->lock, flags); ++ list_add_tail(&item->list, &list->head); ++ spin_unlock_irqrestore(&list->lock, flags); ++ + set_bit(PROCESS_PUREX_IOCB, &vha->dpc_flags); + } + ++static void ++qla24xx_process_abts(struct scsi_qla_host *vha, void *pkt) ++{ ++ struct abts_entry_24xx *abts = pkt; ++ struct qla_hw_data *ha = vha->hw; ++ struct els_entry_24xx *rsp_els; ++ struct abts_entry_24xx *abts_rsp; ++ dma_addr_t dma; ++ uint32_t fctl; ++ int rval; ++ ++ ql_dbg(ql_dbg_init, vha, 0x0286, "%s: entered.\n", __func__); ++ ++ ql_log(ql_log_warn, vha, 0x0287, ++ "Processing ABTS xchg=%#x oxid=%#x rxid=%#x seqid=%#x seqcnt=%#x\n", ++ abts->rx_xch_addr_to_abort, abts->ox_id, abts->rx_id, ++ abts->seq_id, abts->seq_cnt); ++ ql_dbg(ql_dbg_init + ql_dbg_verbose, vha, 0x0287, ++ "-------- ABTS RCV -------\n"); ++ ql_dump_buffer(ql_dbg_init + ql_dbg_verbose, vha, 0x0287, ++ (uint8_t *)abts, sizeof(*abts)); ++ ++ rsp_els = dma_alloc_coherent(&ha->pdev->dev, sizeof(*rsp_els), &dma, ++ GFP_KERNEL); ++ if (!rsp_els) { ++ ql_log(ql_log_warn, vha, 0x0287, ++ "Failed allocate dma buffer ABTS/ELS RSP.\n"); ++ return; ++ } ++ ++ /* terminate exchange */ ++ memset(rsp_els, 0, sizeof(*rsp_els)); ++ rsp_els->entry_type = ELS_IOCB_TYPE; ++ rsp_els->entry_count = 1; ++ rsp_els->nport_handle = ~0; ++ rsp_els->rx_xchg_address = abts->rx_xch_addr_to_abort; ++ rsp_els->control_flags = EPD_RX_XCHG; ++ ql_dbg(ql_dbg_init, vha, 0x0283, ++ "Sending ELS Response to terminate exchange %#x...\n", ++ abts->rx_xch_addr_to_abort); ++ ql_dbg(ql_dbg_init + ql_dbg_verbose, vha, 0x0283, ++ "-------- ELS RSP -------\n"); ++ ql_dump_buffer(ql_dbg_init + ql_dbg_verbose, vha, 0x0283, ++ (uint8_t *)rsp_els, sizeof(*rsp_els)); ++ rval = qla2x00_issue_iocb(vha, rsp_els, dma, 0); ++ if (rval) { ++ ql_log(ql_log_warn, vha, 0x0288, ++ "%s: iocb failed to execute -> %x\n", __func__, rval); ++ } else if (rsp_els->comp_status) { ++ ql_log(ql_log_warn, vha, 0x0289, ++ "%s: iocb failed to complete -> completion=%#x subcode=(%#x,%#x)\n", ++ __func__, rsp_els->comp_status, ++ rsp_els->error_subcode_1, rsp_els->error_subcode_2); ++ } else { ++ ql_dbg(ql_dbg_init, vha, 0x028a, ++ "%s: abort exchange done.\n", __func__); ++ } ++ ++ /* send ABTS response */ ++ abts_rsp = (void *)rsp_els; ++ memset(abts_rsp, 0, sizeof(*abts_rsp)); ++ abts_rsp->entry_type = ABTS_RSP_TYPE; ++ abts_rsp->entry_count = 1; ++ abts_rsp->nport_handle = abts->nport_handle; ++ abts_rsp->vp_idx = abts->vp_idx; ++ abts_rsp->sof_type = abts->sof_type & 0xf0; ++ abts_rsp->rx_xch_addr = abts->rx_xch_addr; ++ abts_rsp->d_id[0] = abts->s_id[0]; ++ abts_rsp->d_id[1] = abts->s_id[1]; ++ abts_rsp->d_id[2] = abts->s_id[2]; ++ abts_rsp->r_ctl = FC_ROUTING_BLD | FC_R_CTL_BLD_BA_ACC; ++ abts_rsp->s_id[0] = abts->d_id[0]; ++ abts_rsp->s_id[1] = abts->d_id[1]; ++ abts_rsp->s_id[2] = abts->d_id[2]; ++ abts_rsp->cs_ctl = abts->cs_ctl; ++ /* include flipping bit23 in fctl */ ++ fctl = ~(abts->f_ctl[2] | 0x7F) << 16 | ++ FC_F_CTL_LAST_SEQ | FC_F_CTL_END_SEQ | FC_F_CTL_SEQ_INIT; ++ abts_rsp->f_ctl[0] = fctl >> 0 & 0xff; ++ abts_rsp->f_ctl[1] = fctl >> 8 & 0xff; ++ abts_rsp->f_ctl[2] = fctl >> 16 & 0xff; ++ abts_rsp->type = FC_TYPE_BLD; ++ abts_rsp->rx_id = abts->rx_id; ++ abts_rsp->ox_id = abts->ox_id; ++ abts_rsp->payload.ba_acc.aborted_rx_id = abts->rx_id; ++ abts_rsp->payload.ba_acc.aborted_ox_id = abts->ox_id; ++ abts_rsp->payload.ba_acc.high_seq_cnt = ~0; ++ abts_rsp->rx_xch_addr_to_abort = abts->rx_xch_addr_to_abort; ++ ql_dbg(ql_dbg_init, vha, 0x028b, ++ "Sending BA ACC response to ABTS %#x...\n", ++ abts->rx_xch_addr_to_abort); ++ ql_dbg(ql_dbg_init + ql_dbg_verbose, vha, 0x028b, ++ "-------- ELS RSP -------\n"); ++ ql_dump_buffer(ql_dbg_init + ql_dbg_verbose, vha, 0x028b, ++ (uint8_t *)abts_rsp, sizeof(*abts_rsp)); ++ rval = qla2x00_issue_iocb(vha, abts_rsp, dma, 0); ++ if (rval) { ++ ql_log(ql_log_warn, vha, 0x028c, ++ "%s: iocb failed to execute -> %x\n", __func__, rval); ++ } else if (abts_rsp->comp_status) { ++ ql_log(ql_log_warn, vha, 0x028d, ++ "%s: iocb failed to complete -> completion=%#x subcode=(%#x,%#x)\n", ++ __func__, abts_rsp->comp_status, ++ abts_rsp->payload.error.subcode1, ++ abts_rsp->payload.error.subcode2); ++ } else { ++ ql_dbg(ql_dbg_init, vha, 0x028ea, ++ "%s: done.\n", __func__); ++ } ++ ++ dma_free_coherent(&ha->pdev->dev, sizeof(*rsp_els), rsp_els, dma); ++} ++ + /** + * qla2100_intr_handler() - Process interrupts for the ISP2100 and ISP2200. + * @irq: interrupt number +@@ -3085,6 +3216,11 @@ process_err: + qla24xx_els_ct_entry(vha, rsp->req, pkt, ELS_IOCB_TYPE); + break; + case ABTS_RECV_24XX: ++ if (qla_ini_mode_enabled(vha)) { ++ qla24xx_purex_iocb(vha, pkt, ++ qla24xx_process_abts); ++ break; ++ } + if (IS_QLA83XX(ha) || IS_QLA27XX(ha) || + IS_QLA28XX(ha)) { + /* ensure that the ATIO queue is empty */ +@@ -3130,8 +3266,18 @@ process_err: + (struct vp_ctrl_entry_24xx *)pkt); + break; + case PUREX_IOCB_TYPE: +- qla24xx_purex_iocb(vha, rsp->req, pkt); ++ { ++ struct purex_entry_24xx *purex = (void *)pkt; ++ ++ if (purex->els_frame_payload[3] != ELS_COMMAND_RDP) { ++ ql_dbg(ql_dbg_init, vha, 0x5091, ++ "Discarding ELS Request opcode %#x...\n", ++ purex->els_frame_payload[3]); ++ break; ++ } ++ qla24xx_purex_iocb(vha, pkt, qla24xx_process_purex_rdp); + break; ++ } + default: + /* Type Not Supported. */ + ql_dbg(ql_dbg_async, vha, 0x5042, +--- a/drivers/scsi/qla2xxx/qla_mid.c ++++ b/drivers/scsi/qla2xxx/qla_mid.c +@@ -361,6 +361,13 @@ qla2x00_do_dpc_vp(scsi_qla_host_t *vha) + } + } + ++ if (test_bit(PROCESS_PUREX_IOCB, &vha->dpc_flags)) { ++ if (atomic_read(&vha->loop_state) == LOOP_READY) { ++ qla24xx_process_purex_list(&vha->purex_list); ++ clear_bit(PROCESS_PUREX_IOCB, &vha->dpc_flags); ++ } ++ } ++ + if (test_bit(FCPORT_UPDATE_NEEDED, &vha->dpc_flags)) { + ql_dbg(ql_dbg_dpc, vha, 0x4016, + "FCPort update scheduled.\n"); +--- a/drivers/scsi/qla2xxx/qla_os.c ++++ b/drivers/scsi/qla2xxx/qla_os.c +@@ -3292,11 +3292,6 @@ qla2x00_probe_one(struct pci_dev *pdev, + goto probe_failed; + } + +- base_vha->purex_data = kzalloc(PUREX_ENTRY_SIZE, GFP_KERNEL); +- if (!base_vha->purex_data) +- ql_log(ql_log_warn, base_vha, 0x7118, +- "Failed to allocate memory for PUREX data\n"); +- + if (IS_QLAFX00(ha)) + host->can_queue = QLAFX00_MAX_CANQUEUE; + else +@@ -3487,7 +3482,6 @@ skip_dpc: + return 0; + + probe_failed: +- kfree(base_vha->purex_data); + if (base_vha->gnl.l) { + dma_free_coherent(&ha->pdev->dev, base_vha->gnl.size, + base_vha->gnl.l, base_vha->gnl.ldma); +@@ -3804,8 +3798,6 @@ qla2x00_remove_one(struct pci_dev *pdev) + + qla84xx_put_chip(base_vha); + +- kfree(base_vha->purex_data); +- + /* Disable timer */ + if (base_vha->timer_active) + qla2x00_stop_timer(base_vha); +@@ -3847,6 +3839,20 @@ qla2x00_remove_one(struct pci_dev *pdev) + pci_disable_device(pdev); + } + ++static inline void ++qla24xx_free_purex_list(struct purex_list *list) ++{ ++ struct list_head *item, *next; ++ ulong flags; ++ ++ spin_lock_irqsave(&list->lock, flags); ++ list_for_each_safe(item, next, &list->head) { ++ list_del(item); ++ kfree(list_entry(item, struct purex_item, list)); ++ } ++ spin_unlock_irqrestore(&list->lock, flags); ++} ++ + static void + qla2x00_free_device(scsi_qla_host_t *vha) + { +@@ -3880,6 +3886,8 @@ qla2x00_free_device(scsi_qla_host_t *vha + } + + ++ qla24xx_free_purex_list(&vha->purex_list); ++ + qla2x00_mem_free(ha); + + qla82xx_md_free(vha); +@@ -4851,6 +4859,9 @@ struct scsi_qla_host *qla2x00_create_hos + INIT_LIST_HEAD(&vha->gpnid_list); + INIT_WORK(&vha->iocb_work, qla2x00_iocb_work_fn); + ++ INIT_LIST_HEAD(&vha->purex_list.head); ++ spin_lock_init(&vha->purex_list.lock); ++ + spin_lock_init(&vha->work_lock); + spin_lock_init(&vha->cmd_list_lock); + init_waitqueue_head(&vha->fcport_waitQ); +@@ -5873,7 +5884,7 @@ qla25xx_rdp_port_speed_currently(struct + * vha: SCSI qla host + * purex: RDP request received by HBA + */ +-static int qla24xx_process_purex_iocb(struct scsi_qla_host *vha, void *pkt) ++void qla24xx_process_purex_rdp(struct scsi_qla_host *vha, void *pkt) + { + struct qla_hw_data *ha = vha->hw; + struct purex_entry_24xx *purex = pkt; +@@ -5889,7 +5900,7 @@ static int qla24xx_process_purex_iocb(st + struct buffer_credit_24xx *bbc = NULL; + uint8_t *sfp = NULL; + uint16_t sfp_flags = 0; +- int rval = -ENOMEM; ++ int rval; + + ql_dbg(ql_dbg_init + ql_dbg_verbose, vha, 0x0180, + "%s: Enter\n", __func__); +@@ -6314,8 +6325,23 @@ dealloc: + if (rsp_els) + dma_free_coherent(&ha->pdev->dev, sizeof(*rsp_els), + rsp_els, rsp_els_dma); ++} + +- return rval; ++void qla24xx_process_purex_list(struct purex_list *list) ++{ ++ struct list_head head = LIST_HEAD_INIT(head); ++ struct purex_item *item, *next; ++ ulong flags; ++ ++ spin_lock_irqsave(&list->lock, flags); ++ list_splice_init(&list->head, &head); ++ spin_unlock_irqrestore(&list->lock, flags); ++ ++ list_for_each_entry_safe(item, next, &head, list) { ++ list_del(&item->list); ++ item->process_item(item->vha, &item->iocb); ++ kfree(item); ++ } + } + + void +@@ -6665,8 +6691,6 @@ qla2x00_disable_board_on_pci_error(struc + + base_vha->flags.online = 0; + +- kfree(base_vha->purex_data); +- + qla2x00_destroy_deferred_work(ha); + + /* +@@ -6890,11 +6914,13 @@ qla2x00_do_dpc(void *data) + } + } + +- if (test_bit(PROCESS_PUREX_IOCB, &base_vha->dpc_flags) && +- (atomic_read(&base_vha->loop_state) == LOOP_READY)) { +- qla24xx_process_purex_iocb(base_vha, +- base_vha->purex_data); +- clear_bit(PROCESS_PUREX_IOCB, &base_vha->dpc_flags); ++ if (test_bit(PROCESS_PUREX_IOCB, &base_vha->dpc_flags)) { ++ if (atomic_read(&base_vha->loop_state) == LOOP_READY) { ++ qla24xx_process_purex_list ++ (&base_vha->purex_list); ++ clear_bit(PROCESS_PUREX_IOCB, ++ &base_vha->dpc_flags); ++ } + } + + if (test_and_clear_bit(FCPORT_UPDATE_NEEDED, diff --git a/patches.suse/scsi-qla2xxx-Add-endianizer-macro-calls-to-fc-host-s.patch b/patches.suse/scsi-qla2xxx-Add-endianizer-macro-calls-to-fc-host-s.patch new file mode 100644 index 0000000..2c51df9 --- /dev/null +++ b/patches.suse/scsi-qla2xxx-Add-endianizer-macro-calls-to-fc-host-s.patch @@ -0,0 +1,156 @@ +From: Joe Carnuccio +Date: Wed, 12 Feb 2020 13:44:16 -0800 +Subject: scsi: qla2xxx: Add endianizer macro calls to fc host stats +Patch-mainline: v5.7-rc1 +Git-commit: 974c086045446a7cdad5de26ff691d9ac82a24a6 +References: bsc#1157424 + +This patch fixes endian warning for fc_host_stats. + +Link: https://lore.kernel.org/r/20200212214436.25532-6-hmadhani@marvell.com +Signed-off-by: Joe Carnuccio +Signed-off-by: Himanshu Madhani +Signed-off-by: Martin K. Petersen +Acked-by: Daniel Wagner +--- + drivers/scsi/qla2xxx/qla_attr.c | 36 ++++++++++++-------- + drivers/scsi/qla2xxx/qla_def.h | 69 +++++++++++++++++++--------------------- + 2 files changed, 54 insertions(+), 51 deletions(-) + +--- a/drivers/scsi/qla2xxx/qla_attr.c ++++ b/drivers/scsi/qla2xxx/qla_attr.c +@@ -2745,22 +2745,28 @@ qla2x00_get_fc_host_stats(struct Scsi_Ho + if (rval != QLA_SUCCESS) + goto done_free; + +- p->link_failure_count = stats->link_fail_cnt; +- p->loss_of_sync_count = stats->loss_sync_cnt; +- p->loss_of_signal_count = stats->loss_sig_cnt; +- p->prim_seq_protocol_err_count = stats->prim_seq_err_cnt; +- p->invalid_tx_word_count = stats->inval_xmit_word_cnt; +- p->invalid_crc_count = stats->inval_crc_cnt; ++ p->link_failure_count = le32_to_cpu(stats->link_fail_cnt); ++ p->loss_of_sync_count = le32_to_cpu(stats->loss_sync_cnt); ++ p->loss_of_signal_count = le32_to_cpu(stats->loss_sig_cnt); ++ p->prim_seq_protocol_err_count = le32_to_cpu(stats->prim_seq_err_cnt); ++ p->invalid_tx_word_count = le32_to_cpu(stats->inval_xmit_word_cnt); ++ p->invalid_crc_count = le32_to_cpu(stats->inval_crc_cnt); + if (IS_FWI2_CAPABLE(ha)) { +- p->lip_count = stats->lip_cnt; +- p->tx_frames = stats->tx_frames; +- p->rx_frames = stats->rx_frames; +- p->dumped_frames = stats->discarded_frames; +- p->nos_count = stats->nos_rcvd; ++ p->lip_count = le32_to_cpu(stats->lip_cnt); ++ p->tx_frames = le32_to_cpu(stats->tx_frames); ++ p->rx_frames = le32_to_cpu(stats->rx_frames); ++ p->dumped_frames = le32_to_cpu(stats->discarded_frames); ++ p->nos_count = le32_to_cpu(stats->nos_rcvd); + p->error_frames = +- stats->dropped_frames + stats->discarded_frames; +- p->rx_words = vha->qla_stats.input_bytes; +- p->tx_words = vha->qla_stats.output_bytes; ++ le32_to_cpu(stats->dropped_frames) + ++ le32_to_cpu(stats->discarded_frames); ++ if (IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha)) { ++ p->rx_words = le64_to_cpu(stats->fpm_recv_word_cnt); ++ p->tx_words = le64_to_cpu(stats->fpm_xmit_word_cnt); ++ } else { ++ p->rx_words = vha->qla_stats.input_bytes; ++ p->tx_words = vha->qla_stats.output_bytes; ++ } + } + p->fcp_control_requests = vha->qla_stats.control_requests; + p->fcp_input_requests = vha->qla_stats.input_requests; +@@ -2768,7 +2774,7 @@ qla2x00_get_fc_host_stats(struct Scsi_Ho + p->fcp_input_megabytes = vha->qla_stats.input_bytes >> 20; + p->fcp_output_megabytes = vha->qla_stats.output_bytes >> 20; + p->seconds_since_last_reset = +- get_jiffies_64() - vha->qla_stats.jiffies_at_last_reset; ++ get_jiffies_64() - vha->qla_stats.jiffies_at_last_reset; + do_div(p->seconds_since_last_reset, HZ); + + done_free: +--- a/drivers/scsi/qla2xxx/qla_def.h ++++ b/drivers/scsi/qla2xxx/qla_def.h +@@ -1475,47 +1475,44 @@ typedef struct { + #define GLSO_USE_DID BIT_3 + + struct link_statistics { +- uint32_t link_fail_cnt; +- uint32_t loss_sync_cnt; +- uint32_t loss_sig_cnt; +- uint32_t prim_seq_err_cnt; +- uint32_t inval_xmit_word_cnt; +- uint32_t inval_crc_cnt; +- uint32_t lip_cnt; +- uint32_t link_up_cnt; +- uint32_t link_down_loop_init_tmo; +- uint32_t link_down_los; +- uint32_t link_down_loss_rcv_clk; ++ __le32 link_fail_cnt; ++ __le32 loss_sync_cnt; ++ __le32 loss_sig_cnt; ++ __le32 prim_seq_err_cnt; ++ __le32 inval_xmit_word_cnt; ++ __le32 inval_crc_cnt; ++ __le32 lip_cnt; ++ __le32 link_up_cnt; ++ __le32 link_down_loop_init_tmo; ++ __le32 link_down_los; ++ __le32 link_down_loss_rcv_clk; + uint32_t reserved0[5]; +- uint32_t port_cfg_chg; ++ __le32 port_cfg_chg; + uint32_t reserved1[11]; +- uint32_t rsp_q_full; +- uint32_t atio_q_full; +- uint32_t drop_ae; +- uint32_t els_proto_err; +- uint32_t reserved2; +- uint32_t tx_frames; +- uint32_t rx_frames; +- uint32_t discarded_frames; +- uint32_t dropped_frames; ++ __le32 rsp_q_full; ++ __le32 atio_q_full; ++ __le32 drop_ae; ++ __le32 els_proto_err; ++ __le32 reserved2; ++ __le32 tx_frames; ++ __le32 rx_frames; ++ __le32 discarded_frames; ++ __le32 dropped_frames; + uint32_t reserved3; +- uint32_t nos_rcvd; ++ __le32 nos_rcvd; + uint32_t reserved4[4]; +- uint32_t tx_prjt; +- uint32_t rcv_exfail; +- uint32_t rcv_abts; +- uint32_t seq_frm_miss; +- uint32_t corr_err; +- uint32_t mb_rqst; +- uint32_t nport_full; +- uint32_t eofa; ++ __le32 tx_prjt; ++ __le32 rcv_exfail; ++ __le32 rcv_abts; ++ __le32 seq_frm_miss; ++ __le32 corr_err; ++ __le32 mb_rqst; ++ __le32 nport_full; ++ __le32 eofa; + uint32_t reserved5; +- uint32_t fpm_recv_word_cnt_lo; +- uint32_t fpm_recv_word_cnt_hi; +- uint32_t fpm_disc_word_cnt_lo; +- uint32_t fpm_disc_word_cnt_hi; +- uint32_t fpm_xmit_word_cnt_lo; +- uint32_t fpm_xmit_word_cnt_hi; ++ __le64 fpm_recv_word_cnt; ++ __le64 fpm_disc_word_cnt; ++ __le64 fpm_xmit_word_cnt; + uint32_t reserved6[70]; + }; + diff --git a/patches.suse/scsi-qla2xxx-Add-fixes-for-mailbox-command.patch b/patches.suse/scsi-qla2xxx-Add-fixes-for-mailbox-command.patch new file mode 100644 index 0000000..bd87537 --- /dev/null +++ b/patches.suse/scsi-qla2xxx-Add-fixes-for-mailbox-command.patch @@ -0,0 +1,42 @@ +From: Himanshu Madhani +Date: Wed, 12 Feb 2020 13:44:34 -0800 +Subject: scsi: qla2xxx: Add fixes for mailbox command +Patch-mainline: v5.7-rc1 +Git-commit: 345f574dac85276d1471492c6e90c57e3f90a4f3 +References: bsc#1157424 + +This patch fixes: + +- qla2x00_issue_iocb_timeout will now return if chip is down + +- only check for sp->qpair in abort handling + +Link: https://lore.kernel.org/r/20200212214436.25532-24-hmadhani@marvell.com +Signed-off-by: Himanshu Madhani +Signed-off-by: Martin K. Petersen +Acked-by: Daniel Wagner +--- + drivers/scsi/qla2xxx/qla_mbx.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +--- a/drivers/scsi/qla2xxx/qla_mbx.c ++++ b/drivers/scsi/qla2xxx/qla_mbx.c +@@ -1404,6 +1404,9 @@ qla2x00_issue_iocb_timeout(scsi_qla_host + mbx_cmd_t mc; + mbx_cmd_t *mcp = &mc; + ++ if (qla2x00_chip_is_down(vha)) ++ return QLA_INVALID_COMMAND; ++ + ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1038, + "Entered %s.\n", __func__); + +@@ -1475,7 +1478,7 @@ qla2x00_abort_command(srb_t *sp) + ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x103b, + "Entered %s.\n", __func__); + +- if (vha->flags.qpairs_available && sp->qpair) ++ if (sp->qpair) + req = sp->qpair->req; + else + req = vha->req; diff --git a/patches.suse/scsi-qla2xxx-Add-ql2xrdpenable-module-parameter-for-.patch b/patches.suse/scsi-qla2xxx-Add-ql2xrdpenable-module-parameter-for-.patch new file mode 100644 index 0000000..ceafa8b --- /dev/null +++ b/patches.suse/scsi-qla2xxx-Add-ql2xrdpenable-module-parameter-for-.patch @@ -0,0 +1,101 @@ +From: Joe Carnuccio +Date: Wed, 12 Feb 2020 13:44:19 -0800 +Subject: scsi: qla2xxx: Add ql2xrdpenable module parameter for RDP +Patch-mainline: v5.7-rc1 +Git-commit: bd7de0b1c3947e176effb5f5b4a47eab79db771e +References: bsc#1157424 + +This patch provides separate module parameter ql2xrdpenable to turn on/off +RDP capability in the driver. However, if ql2xsmartsan parameter is +enabled, it will also turn on ql2xfdmienable parameter since it is required +for RDP to work. + +Link: https://lore.kernel.org/r/20200212214436.25532-9-hmadhani@marvell.com +Signed-off-by: Joe Carnuccio +Signed-off-by: Himanshu Madhani +Signed-off-by: Martin K. Petersen +Acked-by: Daniel Wagner +--- + drivers/scsi/qla2xxx/qla_gbl.h | 1 + + drivers/scsi/qla2xxx/qla_init.c | 12 +++++++++--- + drivers/scsi/qla2xxx/qla_os.c | 10 +++++++++- + 3 files changed, 19 insertions(+), 4 deletions(-) + +--- a/drivers/scsi/qla2xxx/qla_gbl.h ++++ b/drivers/scsi/qla2xxx/qla_gbl.h +@@ -144,6 +144,7 @@ extern int qlport_down_retry; + extern int ql2xplogiabsentdevice; + extern int ql2xloginretrycount; + extern int ql2xfdmienable; ++extern int ql2xrdpenable; + extern int ql2xsmartsan; + extern int ql2xallocfwdump; + extern int ql2xextended_error_logging; +--- a/drivers/scsi/qla2xxx/qla_init.c ++++ b/drivers/scsi/qla2xxx/qla_init.c +@@ -2272,6 +2272,12 @@ qla2x00_initialize_adapter(scsi_qla_host + ql_dbg(ql_dbg_init, vha, 0x0078, + "Verifying loaded RISC code...\n"); + ++ /* If smartsan enabled then require fdmi and rdp enabled */ ++ if (ql2xsmartsan) { ++ ql2xfdmienable = 1; ++ ql2xrdpenable = 1; ++ } ++ + if (qla2x00_isp_firmware(vha) != QLA_SUCCESS) { + rval = ha->isp_ops->chip_diag(vha); + if (rval) +@@ -3710,7 +3716,7 @@ enable_82xx_npiv: + } + + /* Enable PUREX PASSTHRU */ +- if (ql2xsmartsan) ++ if (ql2xrdpenable) + qla25xx_set_els_cmds_supported(vha); + } else + goto failed; +@@ -3945,7 +3951,7 @@ qla24xx_update_fw_options(scsi_qla_host_ + } + + enable_purex: +- if (ql2xsmartsan) ++ if (ql2xrdpenable) + ha->fw_options[1] |= ADD_FO1_ENABLE_PUREX_IOCB; + + qla2x00_set_fw_options(vha, ha->fw_options); +@@ -8682,7 +8688,7 @@ qla83xx_update_fw_options(scsi_qla_host_ + { + struct qla_hw_data *ha = vha->hw; + +- if (ql2xsmartsan) ++ if (ql2xrdpenable) + ha->fw_options[1] |= ADD_FO1_ENABLE_PUREX_IOCB; + + qla2x00_set_fw_options(vha, ha->fw_options); +--- a/drivers/scsi/qla2xxx/qla_os.c ++++ b/drivers/scsi/qla2xxx/qla_os.c +@@ -113,7 +113,8 @@ module_param(ql2xfdmienable, int, S_IRUG + module_param_named(fdmi, ql2xfdmienable, int, S_IRUGO|S_IWUSR); + MODULE_PARM_DESC(ql2xfdmienable, + "Enables FDMI registrations. " +- "0 - no FDMI. Default is 1 - perform FDMI."); ++ "0 - no FDMI registrations. " ++ "1 - provide FDMI registrations (default)."); + + #define MAX_Q_DEPTH 64 + static int ql2xmaxqdepth = MAX_Q_DEPTH; +@@ -314,6 +315,13 @@ MODULE_PARM_DESC(ql2xsmartsan, + " Default is 0 - No SmartSAN registration," + " 1 - Register SmartSAN Management Attributes."); + ++int ql2xrdpenable; ++module_param(ql2xrdpenable, int, 0444); ++module_param_named(rdpenable, ql2xrdpenable, int, 0444); ++MODULE_PARM_DESC(ql2xrdpenable, ++ "Enables RDP responses. " ++ "0 - no RDP responses (default). " ++ "1 - provide RDP responses."); + + static void qla2x00_clear_drv_active(struct qla_hw_data *); + static void qla2x00_free_device(scsi_qla_host_t *); diff --git a/patches.suse/scsi-qla2xxx-Add-sysfs-node-for-D-Port-Diagnostics-A.patch b/patches.suse/scsi-qla2xxx-Add-sysfs-node-for-D-Port-Diagnostics-A.patch new file mode 100644 index 0000000..ced8301 --- /dev/null +++ b/patches.suse/scsi-qla2xxx-Add-sysfs-node-for-D-Port-Diagnostics-A.patch @@ -0,0 +1,77 @@ +From: Joe Carnuccio +Date: Wed, 12 Feb 2020 13:44:14 -0800 +Subject: scsi: qla2xxx: Add sysfs node for D-Port Diagnostics AEN data +Patch-mainline: v5.7-rc1 +Git-commit: e6ad2b79b82f41a51f90c95686c39cd8be4a35f3 +References: bsc#1157424 + +This patch adds sysfs node to show D-Port diag data. + +Link: https://lore.kernel.org/r/20200212214436.25532-4-hmadhani@marvell.com +Signed-off-by: Joe Carnuccio +Signed-off-by: Himanshu Madhani +Signed-off-by: Martin K. Petersen +Acked-by: Daniel Wagner +--- + drivers/scsi/qla2xxx/qla_attr.c | 21 +++++++++++++++++++++ + drivers/scsi/qla2xxx/qla_def.h | 1 + + drivers/scsi/qla2xxx/qla_isr.c | 1 + + 3 files changed, 23 insertions(+) + +--- a/drivers/scsi/qla2xxx/qla_attr.c ++++ b/drivers/scsi/qla2xxx/qla_attr.c +@@ -2323,6 +2323,26 @@ qla2x00_port_no_show(struct device *dev, + return scnprintf(buf, PAGE_SIZE, "%u\n", vha->hw->port_no); + } + ++static ssize_t ++qla2x00_dport_diagnostics_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ scsi_qla_host_t *vha = shost_priv(class_to_shost(dev)); ++ ++ if (!IS_QLA83XX(vha->hw) && !IS_QLA27XX(vha->hw) && ++ !IS_QLA28XX(vha->hw)) ++ return scnprintf(buf, PAGE_SIZE, "\n"); ++ ++ if (!*vha->dport_data) ++ return scnprintf(buf, PAGE_SIZE, "\n"); ++ ++ return scnprintf(buf, PAGE_SIZE, "%04x %04x %04x %04x\n", ++ vha->dport_data[0], vha->dport_data[1], ++ vha->dport_data[2], vha->dport_data[3]); ++} ++static DEVICE_ATTR(dport_diagnostics, 0444, ++ qla2x00_dport_diagnostics_show, NULL); ++ + static DEVICE_ATTR(driver_version, S_IRUGO, qla2x00_driver_version_show, NULL); + static DEVICE_ATTR(fw_version, S_IRUGO, qla2x00_fw_version_show, NULL); + static DEVICE_ATTR(serial_num, S_IRUGO, qla2x00_serial_num_show, NULL); +@@ -2431,6 +2451,7 @@ struct device_attribute *qla2x00_host_at + &dev_attr_port_speed, + &dev_attr_port_no, + &dev_attr_fw_attr, ++ &dev_attr_dport_diagnostics, + NULL, /* reserve for qlini_mode */ + NULL, /* reserve for ql2xiniexchg */ + NULL, /* reserve for ql2xexchoffld */ +--- a/drivers/scsi/qla2xxx/qla_def.h ++++ b/drivers/scsi/qla2xxx/qla_def.h +@@ -4541,6 +4541,7 @@ typedef struct scsi_qla_host { + uint8_t n2n_node_name[WWN_SIZE]; + uint8_t n2n_port_name[WWN_SIZE]; + uint16_t n2n_id; ++ __le16 dport_data[4]; + struct list_head gpnid_list; + struct fab_scan scan; + +--- a/drivers/scsi/qla2xxx/qla_isr.c ++++ b/drivers/scsi/qla2xxx/qla_isr.c +@@ -1254,6 +1254,7 @@ global_port_update: + ql_dbg(ql_dbg_async, vha, 0x5052, + "D-Port Diagnostics: %04x %04x %04x %04x\n", + mb[0], mb[1], mb[2], mb[3]); ++ memcpy(vha->dport_data, mb, sizeof(vha->dport_data)); + if (IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha)) { + static char *results[] = { + "start", "done(pass)", "done(error)", "undefined" }; diff --git a/patches.suse/scsi-qla2xxx-Add-vendor-extended-FDMI-commands.patch b/patches.suse/scsi-qla2xxx-Add-vendor-extended-FDMI-commands.patch new file mode 100644 index 0000000..161dae8 --- /dev/null +++ b/patches.suse/scsi-qla2xxx-Add-vendor-extended-FDMI-commands.patch @@ -0,0 +1,2213 @@ +From: Joe Carnuccio +Date: Wed, 12 Feb 2020 13:44:20 -0800 +Subject: scsi: qla2xxx: Add vendor extended FDMI commands +Patch-mainline: v5.7-rc1 +Git-commit: 52bfb089d9d384a1ac0f6d94da7636eb9373a8f9 +References: bsc#1157424 + +This patch adds support for extended FDMI commands and cleans up code to +reduce duplication. + +Link: https://lore.kernel.org/r/20200212214436.25532-10-hmadhani@marvell.com +Signed-off-by: Joe Carnuccio +Signed-off-by: Himanshu Madhani +Signed-off-by: Martin K. Petersen +Acked-by: Daniel Wagner +--- + drivers/scsi/qla2xxx/qla_def.h | 134 +-- + drivers/scsi/qla2xxx/qla_gs.c | 1681 ++++++++++++++++++----------------------- + 2 files changed, 827 insertions(+), 988 deletions(-) + +--- a/drivers/scsi/qla2xxx/qla_def.h ++++ b/drivers/scsi/qla2xxx/qla_def.h +@@ -2627,10 +2627,11 @@ static const char * const port_dstate_st + #define GFF_ID_RSP_SIZE (16 + 128) + + /* +- * HBA attribute types. ++ * FDMI HBA attribute types. + */ +-#define FDMI_HBA_ATTR_COUNT 9 +-#define FDMIV2_HBA_ATTR_COUNT 17 ++#define FDMI1_HBA_ATTR_COUNT 9 ++#define FDMI2_HBA_ATTR_COUNT 17 ++ + #define FDMI_HBA_NODE_NAME 0x1 + #define FDMI_HBA_MANUFACTURER 0x2 + #define FDMI_HBA_SERIAL_NUMBER 0x3 +@@ -2642,12 +2643,13 @@ static const char * const port_dstate_st + #define FDMI_HBA_FIRMWARE_VERSION 0x9 + #define FDMI_HBA_OS_NAME_AND_VERSION 0xa + #define FDMI_HBA_MAXIMUM_CT_PAYLOAD_LENGTH 0xb ++ + #define FDMI_HBA_NODE_SYMBOLIC_NAME 0xc +-#define FDMI_HBA_VENDOR_ID 0xd ++#define FDMI_HBA_VENDOR_SPECIFIC_INFO 0xd + #define FDMI_HBA_NUM_PORTS 0xe + #define FDMI_HBA_FABRIC_NAME 0xf + #define FDMI_HBA_BOOT_BIOS_NAME 0x10 +-#define FDMI_HBA_TYPE_VENDOR_IDENTIFIER 0xe0 ++#define FDMI_HBA_VENDOR_IDENTIFIER 0xe0 + + struct ct_fdmi_hba_attr { + uint16_t type; +@@ -2664,31 +2666,9 @@ struct ct_fdmi_hba_attr { + uint8_t fw_version[32]; + uint8_t os_version[128]; + uint32_t max_ct_len; +- } a; +-}; +- +-struct ct_fdmi_hba_attributes { +- uint32_t count; +- struct ct_fdmi_hba_attr entry[FDMI_HBA_ATTR_COUNT]; +-}; + +-struct ct_fdmiv2_hba_attr { +- uint16_t type; +- uint16_t len; +- union { +- uint8_t node_name[WWN_SIZE]; +- uint8_t manufacturer[64]; +- uint8_t serial_num[32]; +- uint8_t model[16+1]; +- uint8_t model_desc[80]; +- uint8_t hw_version[16]; +- uint8_t driver_version[32]; +- uint8_t orom_version[16]; +- uint8_t fw_version[32]; +- uint8_t os_version[128]; +- uint32_t max_ct_len; + uint8_t sym_name[256]; +- uint32_t vendor_id; ++ uint32_t vendor_specific_info; + uint32_t num_ports; + uint8_t fabric_name[WWN_SIZE]; + uint8_t bios_name[32]; +@@ -2696,22 +2676,30 @@ struct ct_fdmiv2_hba_attr { + } a; + }; + +-struct ct_fdmiv2_hba_attributes { ++struct ct_fdmi1_hba_attributes { + uint32_t count; +- struct ct_fdmiv2_hba_attr entry[FDMIV2_HBA_ATTR_COUNT]; ++ struct ct_fdmi_hba_attr entry[FDMI1_HBA_ATTR_COUNT]; ++}; ++ ++struct ct_fdmi2_hba_attributes { ++ uint32_t count; ++ struct ct_fdmi_hba_attr entry[FDMI2_HBA_ATTR_COUNT]; + }; + + /* +- * Port attribute types. ++ * FDMI Port attribute types. + */ +-#define FDMI_PORT_ATTR_COUNT 6 +-#define FDMIV2_PORT_ATTR_COUNT 16 ++#define FDMI1_PORT_ATTR_COUNT 6 ++#define FDMI2_PORT_ATTR_COUNT 16 ++#define FDMI2_SMARTSAN_PORT_ATTR_COUNT 23 ++ + #define FDMI_PORT_FC4_TYPES 0x1 + #define FDMI_PORT_SUPPORT_SPEED 0x2 + #define FDMI_PORT_CURRENT_SPEED 0x3 + #define FDMI_PORT_MAX_FRAME_SIZE 0x4 + #define FDMI_PORT_OS_DEVICE_NAME 0x5 + #define FDMI_PORT_HOST_NAME 0x6 ++ + #define FDMI_PORT_NODE_NAME 0x7 + #define FDMI_PORT_NAME 0x8 + #define FDMI_PORT_SYM_NAME 0x9 +@@ -2721,7 +2709,15 @@ struct ct_fdmiv2_hba_attributes { + #define FDMI_PORT_FC4_TYPE 0xd + #define FDMI_PORT_STATE 0x101 + #define FDMI_PORT_COUNT 0x102 +-#define FDMI_PORT_ID 0x103 ++#define FDMI_PORT_IDENTIFIER 0x103 ++ ++#define FDMI_SMARTSAN_SERVICE 0xF100 ++#define FDMI_SMARTSAN_GUID 0xF101 ++#define FDMI_SMARTSAN_VERSION 0xF102 ++#define FDMI_SMARTSAN_PROD_NAME 0xF103 ++#define FDMI_SMARTSAN_PORT_INFO 0xF104 ++#define FDMI_SMARTSAN_QOS_SUPPORT 0xF105 ++#define FDMI_SMARTSAN_SECURITY_SUPPORT 0xF106 + + #define FDMI_PORT_SPEED_1GB 0x1 + #define FDMI_PORT_SPEED_2GB 0x2 +@@ -2737,7 +2733,7 @@ struct ct_fdmiv2_hba_attributes { + #define FC_CLASS_3 0x08 + #define FC_CLASS_2_3 0x0C + +-struct ct_fdmiv2_port_attr { ++struct ct_fdmi_port_attr { + uint16_t type; + uint16_t len; + union { +@@ -2747,6 +2743,7 @@ struct ct_fdmiv2_port_attr { + uint32_t max_frame_size; + uint8_t os_dev_name[32]; + uint8_t host_name[256]; ++ + uint8_t node_name[WWN_SIZE]; + uint8_t port_name[WWN_SIZE]; + uint8_t port_sym_name[128]; +@@ -2757,35 +2754,38 @@ struct ct_fdmiv2_port_attr { + uint32_t port_state; + uint32_t num_ports; + uint32_t port_id; ++ ++ uint8_t smartsan_service[24]; ++ uint8_t smartsan_guid[16]; ++ uint8_t smartsan_version[24]; ++ uint8_t smartsan_prod_name[16]; ++ uint32_t smartsan_port_info; ++ uint32_t smartsan_qos_support; ++ uint32_t smartsan_security_support; + } a; + }; + +-/* +- * Port Attribute Block. +- */ +-struct ct_fdmiv2_port_attributes { ++struct ct_fdmi1_port_attributes { + uint32_t count; +- struct ct_fdmiv2_port_attr entry[FDMIV2_PORT_ATTR_COUNT]; ++ struct ct_fdmi_port_attr entry[FDMI1_PORT_ATTR_COUNT]; + }; + +-struct ct_fdmi_port_attr { +- uint16_t type; +- uint16_t len; +- union { +- uint8_t fc4_types[32]; +- uint32_t sup_speed; +- uint32_t cur_speed; +- uint32_t max_frame_size; +- uint8_t os_dev_name[32]; +- uint8_t host_name[256]; +- } a; +-}; +- +-struct ct_fdmi_port_attributes { ++struct ct_fdmi2_port_attributes { + uint32_t count; +- struct ct_fdmi_port_attr entry[FDMI_PORT_ATTR_COUNT]; ++ struct ct_fdmi_port_attr entry[FDMI2_PORT_ATTR_COUNT]; + }; + ++#define FDMI_ATTR_TYPELEN(obj) \ ++ (sizeof((obj)->type) + sizeof((obj)->len)) ++ ++#define FDMI_ATTR_ALIGNMENT(len) \ ++ (4 - ((len) & 3)) ++ ++/* FDMI register call options */ ++#define CALLOPT_FDMI1 0 ++#define CALLOPT_FDMI2 1 ++#define CALLOPT_FDMI2_SMARTSAN 2 ++ + /* FDMI definitions. */ + #define GRHL_CMD 0x100 + #define GHAT_CMD 0x101 +@@ -2796,10 +2796,13 @@ struct ct_fdmi_port_attributes { + #define RHBA_RSP_SIZE 16 + + #define RHAT_CMD 0x201 ++ + #define RPRT_CMD 0x210 ++#define RPRT_RSP_SIZE 24 + + #define RPA_CMD 0x211 + #define RPA_RSP_SIZE 16 ++#define SMARTSAN_RPA_RSP_SIZE 24 + + #define DHBA_CMD 0x300 + #define DHBA_REQ_SIZE (16 + 8) +@@ -2882,30 +2885,24 @@ struct ct_sns_req { + uint8_t hba_identifier[8]; + uint32_t entry_count; + uint8_t port_name[8]; +- struct ct_fdmi_hba_attributes attrs; ++ struct ct_fdmi2_hba_attributes attrs; + } rhba; + + struct { + uint8_t hba_identifier[8]; +- uint32_t entry_count; +- uint8_t port_name[8]; +- struct ct_fdmiv2_hba_attributes attrs; +- } rhba2; +- +- struct { +- uint8_t hba_identifier[8]; +- struct ct_fdmi_hba_attributes attrs; ++ struct ct_fdmi1_hba_attributes attrs; + } rhat; + + struct { + uint8_t port_name[8]; +- struct ct_fdmi_port_attributes attrs; ++ struct ct_fdmi2_port_attributes attrs; + } rpa; + + struct { ++ uint8_t hba_identifier[8]; + uint8_t port_name[8]; +- struct ct_fdmiv2_port_attributes attrs; +- } rpa2; ++ struct ct_fdmi2_port_attributes attrs; ++ } rprt; + + struct { + uint8_t port_name[8]; +@@ -3019,7 +3016,7 @@ struct ct_sns_rsp { + struct { + uint32_t entry_count; + uint8_t port_name[8]; +- struct ct_fdmi_hba_attributes attrs; ++ struct ct_fdmi1_hba_attributes attrs; + } ghat; + + struct { +@@ -3690,6 +3687,7 @@ struct rdp_rsp_payload { + #define RDP_PORT_SPEED_8GB BIT_11 + #define RDP_PORT_SPEED_16GB BIT_10 + #define RDP_PORT_SPEED_32GB BIT_9 ++#define RDP_PORT_SPEED_64GB BIT_8 + #define RDP_PORT_SPEED_UNKNOWN BIT_0 + + struct scsi_qlt_host { +--- a/drivers/scsi/qla2xxx/qla_gs.c ++++ b/drivers/scsi/qla2xxx/qla_gs.c +@@ -19,6 +19,8 @@ static int qla_async_rffid(scsi_qla_host + static int qla_async_rnnid(scsi_qla_host_t *, port_id_t *, u8*); + static int qla_async_rsnn_nn(scsi_qla_host_t *); + ++ ++ + /** + * qla2x00_prep_ms_iocb() - Prepare common MS/CT IOCB fields for SNS CT query. + * @vha: HA context +@@ -1500,747 +1502,732 @@ qla2x00_prep_ct_fdmi_req(struct ct_sns_p + return &p->p.req; + } + ++static uint ++qla25xx_fdmi_port_speed_capability(struct qla_hw_data *ha) ++{ ++ if (IS_CNA_CAPABLE(ha)) ++ return FDMI_PORT_SPEED_10GB; ++ if (IS_QLA28XX(ha) || IS_QLA27XX(ha)) { ++ uint speeds = 0; ++ ++ if (ha->max_supported_speed == 2) { ++ if (ha->min_supported_speed <= 6) ++ speeds |= FDMI_PORT_SPEED_64GB; ++ } ++ if (ha->max_supported_speed == 2 || ++ ha->max_supported_speed == 1) { ++ if (ha->min_supported_speed <= 5) ++ speeds |= FDMI_PORT_SPEED_32GB; ++ } ++ if (ha->max_supported_speed == 2 || ++ ha->max_supported_speed == 1 || ++ ha->max_supported_speed == 0) { ++ if (ha->min_supported_speed <= 4) ++ speeds |= FDMI_PORT_SPEED_16GB; ++ } ++ if (ha->max_supported_speed == 1 || ++ ha->max_supported_speed == 0) { ++ if (ha->min_supported_speed <= 3) ++ speeds |= FDMI_PORT_SPEED_8GB; ++ } ++ if (ha->max_supported_speed == 0) { ++ if (ha->min_supported_speed <= 2) ++ speeds |= FDMI_PORT_SPEED_4GB; ++ } ++ return speeds; ++ } ++ if (IS_QLA2031(ha)) ++ return FDMI_PORT_SPEED_16GB|FDMI_PORT_SPEED_8GB| ++ FDMI_PORT_SPEED_4GB; ++ if (IS_QLA25XX(ha)) ++ return FDMI_PORT_SPEED_8GB|FDMI_PORT_SPEED_4GB| ++ FDMI_PORT_SPEED_2GB|FDMI_PORT_SPEED_1GB; ++ if (IS_QLA24XX_TYPE(ha)) ++ return FDMI_PORT_SPEED_4GB|FDMI_PORT_SPEED_2GB| ++ FDMI_PORT_SPEED_1GB; ++ if (IS_QLA23XX(ha)) ++ return FDMI_PORT_SPEED_2GB|FDMI_PORT_SPEED_1GB; ++ return FDMI_PORT_SPEED_1GB; ++} ++static uint ++qla25xx_fdmi_port_speed_currently(struct qla_hw_data *ha) ++{ ++ switch (ha->link_data_rate) { ++ case PORT_SPEED_1GB: ++ return FDMI_PORT_SPEED_1GB; ++ case PORT_SPEED_2GB: ++ return FDMI_PORT_SPEED_2GB; ++ case PORT_SPEED_4GB: ++ return FDMI_PORT_SPEED_4GB; ++ case PORT_SPEED_8GB: ++ return FDMI_PORT_SPEED_8GB; ++ case PORT_SPEED_10GB: ++ return FDMI_PORT_SPEED_10GB; ++ case PORT_SPEED_16GB: ++ return FDMI_PORT_SPEED_16GB; ++ case PORT_SPEED_32GB: ++ return FDMI_PORT_SPEED_32GB; ++ case PORT_SPEED_64GB: ++ return FDMI_PORT_SPEED_64GB; ++ default: ++ return FDMI_PORT_SPEED_UNKNOWN; ++ } ++} ++ + /** +- * qla2x00_fdmi_rhba() - perform RHBA FDMI registration ++ * qla2x00_hba_attributes() perform HBA attributes registration + * @vha: HA context ++ * @entries: number of entries to use ++ * @callopt: Option to issue extended or standard FDMI ++ * command parameter + * + * Returns 0 on success. + */ +-static int +-qla2x00_fdmi_rhba(scsi_qla_host_t *vha) ++static unsigned long ++qla2x00_hba_attributes(scsi_qla_host_t *vha, void *entries, ++ unsigned int callopt) + { +- int rval, alen; +- uint32_t size, sn; +- +- ms_iocb_entry_t *ms_pkt; +- struct ct_sns_req *ct_req; +- struct ct_sns_rsp *ct_rsp; +- void *entries; +- struct ct_fdmi_hba_attr *eiter; + struct qla_hw_data *ha = vha->hw; +- +- /* Issue RHBA */ +- /* Prepare common MS IOCB */ +- /* Request size adjusted after CT preparation */ +- ms_pkt = ha->isp_ops->prep_ms_fdmi_iocb(vha, 0, RHBA_RSP_SIZE); +- +- /* Prepare CT request */ +- ct_req = qla2x00_prep_ct_fdmi_req(ha->ct_sns, RHBA_CMD, RHBA_RSP_SIZE); +- ct_rsp = &ha->ct_sns->p.rsp; +- +- /* Prepare FDMI command arguments -- attribute block, attributes. */ +- memcpy(ct_req->req.rhba.hba_identifier, vha->port_name, WWN_SIZE); +- ct_req->req.rhba.entry_count = cpu_to_be32(1); +- memcpy(ct_req->req.rhba.port_name, vha->port_name, WWN_SIZE); +- size = 2 * WWN_SIZE + 4 + 4; +- +- /* Attributes */ +- ct_req->req.rhba.attrs.count = +- cpu_to_be32(FDMI_HBA_ATTR_COUNT); +- entries = &ct_req->req; ++ struct init_cb_24xx *icb24 = (void *)ha->init_cb; ++ struct new_utsname *p_sysid = utsname(); ++ struct ct_fdmi_hba_attr *eiter; ++ uint16_t alen; ++ unsigned long size = 0; + + /* Nodename. */ + eiter = entries + size; + eiter->type = cpu_to_be16(FDMI_HBA_NODE_NAME); +- eiter->len = cpu_to_be16(4 + WWN_SIZE); +- memcpy(eiter->a.node_name, vha->node_name, WWN_SIZE); +- size += 4 + WWN_SIZE; +- +- ql_dbg(ql_dbg_disc, vha, 0x2025, +- "NodeName = %8phN.\n", eiter->a.node_name); +- ++ memcpy(eiter->a.node_name, vha->node_name, sizeof(eiter->a.node_name)); ++ alen = sizeof(eiter->a.node_name); ++ alen += FDMI_ATTR_TYPELEN(eiter); ++ eiter->len = cpu_to_be16(alen); ++ size += alen; ++ ql_dbg(ql_dbg_disc, vha, 0x20a0, ++ "NODENAME = %016llx.\n", wwn_to_u64(eiter->a.node_name)); + /* Manufacturer. */ + eiter = entries + size; + eiter->type = cpu_to_be16(FDMI_HBA_MANUFACTURER); +- alen = strlen(QLA2XXX_MANUFACTURER); +- snprintf(eiter->a.manufacturer, sizeof(eiter->a.manufacturer), +- "%s", "QLogic Corporation"); +- alen += 4 - (alen & 3); +- eiter->len = cpu_to_be16(4 + alen); +- size += 4 + alen; +- +- ql_dbg(ql_dbg_disc, vha, 0x2026, +- "Manufacturer = %s.\n", eiter->a.manufacturer); +- ++ alen = scnprintf( ++ eiter->a.manufacturer, sizeof(eiter->a.manufacturer), ++ "%s", "QLogic Corporation"); ++ alen += FDMI_ATTR_ALIGNMENT(alen); ++ alen += FDMI_ATTR_TYPELEN(eiter); ++ eiter->len = cpu_to_be16(alen); ++ size += alen; ++ ql_dbg(ql_dbg_disc, vha, 0x20a1, ++ "MANUFACTURER = %s.\n", eiter->a.manufacturer); + /* Serial number. */ + eiter = entries + size; + eiter->type = cpu_to_be16(FDMI_HBA_SERIAL_NUMBER); +- if (IS_FWI2_CAPABLE(ha)) +- qla2xxx_get_vpd_field(vha, "SN", eiter->a.serial_num, +- sizeof(eiter->a.serial_num)); +- else { +- sn = ((ha->serial0 & 0x1f) << 16) | +- (ha->serial2 << 8) | ha->serial1; +- snprintf(eiter->a.serial_num, sizeof(eiter->a.serial_num), +- "%c%05d", 'A' + sn / 100000, sn % 100000); ++ alen = 0; ++ if (IS_FWI2_CAPABLE(ha)) { ++ alen = qla2xxx_get_vpd_field(vha, "SN", ++ eiter->a.serial_num, sizeof(eiter->a.serial_num)); + } +- alen = strlen(eiter->a.serial_num); +- alen += 4 - (alen & 3); +- eiter->len = cpu_to_be16(4 + alen); +- size += 4 + alen; +- +- ql_dbg(ql_dbg_disc, vha, 0x2027, +- "Serial no. = %s.\n", eiter->a.serial_num); +- ++ if (!alen) { ++ uint32_t sn = ((ha->serial0 & 0x1f) << 16) | ++ (ha->serial2 << 8) | ha->serial1; ++ alen = scnprintf( ++ eiter->a.serial_num, sizeof(eiter->a.serial_num), ++ "%c%05d", 'A' + sn / 100000, sn % 100000); ++ } ++ alen += FDMI_ATTR_ALIGNMENT(alen); ++ alen += FDMI_ATTR_TYPELEN(eiter); ++ eiter->len = cpu_to_be16(alen); ++ size += alen; ++ ql_dbg(ql_dbg_disc, vha, 0x20a2, ++ "SERIAL NUMBER = %s.\n", eiter->a.serial_num); + /* Model name. */ + eiter = entries + size; + eiter->type = cpu_to_be16(FDMI_HBA_MODEL); +- snprintf(eiter->a.model, sizeof(eiter->a.model), +- "%s", ha->model_number); +- alen = strlen(eiter->a.model); +- alen += 4 - (alen & 3); +- eiter->len = cpu_to_be16(4 + alen); +- size += 4 + alen; +- +- ql_dbg(ql_dbg_disc, vha, 0x2028, +- "Model Name = %s.\n", eiter->a.model); +- ++ alen = scnprintf( ++ eiter->a.model, sizeof(eiter->a.model), ++ "%s", ha->model_number); ++ alen += FDMI_ATTR_ALIGNMENT(alen); ++ alen += FDMI_ATTR_TYPELEN(eiter); ++ eiter->len = cpu_to_be16(alen); ++ size += alen; ++ ql_dbg(ql_dbg_disc, vha, 0x20a3, ++ "MODEL NAME = %s.\n", eiter->a.model); + /* Model description. */ + eiter = entries + size; + eiter->type = cpu_to_be16(FDMI_HBA_MODEL_DESCRIPTION); +- snprintf(eiter->a.model_desc, sizeof(eiter->a.model_desc), +- "%s", ha->model_desc); +- alen = strlen(eiter->a.model_desc); +- alen += 4 - (alen & 3); +- eiter->len = cpu_to_be16(4 + alen); +- size += 4 + alen; +- +- ql_dbg(ql_dbg_disc, vha, 0x2029, +- "Model Desc = %s.\n", eiter->a.model_desc); +- ++ alen = scnprintf( ++ eiter->a.model_desc, sizeof(eiter->a.model_desc), ++ "%s", ha->model_desc); ++ alen += FDMI_ATTR_ALIGNMENT(alen); ++ alen += FDMI_ATTR_TYPELEN(eiter); ++ eiter->len = cpu_to_be16(alen); ++ size += alen; ++ ql_dbg(ql_dbg_disc, vha, 0x20a4, ++ "MODEL DESCRIPTION = %s.\n", eiter->a.model_desc); + /* Hardware version. */ + eiter = entries + size; + eiter->type = cpu_to_be16(FDMI_HBA_HARDWARE_VERSION); +- if (!IS_FWI2_CAPABLE(ha)) { +- snprintf(eiter->a.hw_version, sizeof(eiter->a.hw_version), +- "HW:%s", ha->adapter_id); +- } else if (qla2xxx_get_vpd_field(vha, "MN", eiter->a.hw_version, +- sizeof(eiter->a.hw_version))) { +- ; +- } else if (qla2xxx_get_vpd_field(vha, "EC", eiter->a.hw_version, +- sizeof(eiter->a.hw_version))) { +- ; +- } else { +- snprintf(eiter->a.hw_version, sizeof(eiter->a.hw_version), +- "HW:%s", ha->adapter_id); ++ alen = 0; ++ if (IS_FWI2_CAPABLE(ha)) { ++ if (!alen) { ++ alen = qla2xxx_get_vpd_field(vha, "MN", ++ eiter->a.hw_version, sizeof(eiter->a.hw_version)); ++ } ++ if (!alen) { ++ alen = qla2xxx_get_vpd_field(vha, "EC", ++ eiter->a.hw_version, sizeof(eiter->a.hw_version)); ++ } + } +- alen = strlen(eiter->a.hw_version); +- alen += 4 - (alen & 3); +- eiter->len = cpu_to_be16(4 + alen); +- size += 4 + alen; +- +- ql_dbg(ql_dbg_disc, vha, 0x202a, +- "Hardware ver = %s.\n", eiter->a.hw_version); +- ++ if (!alen) { ++ alen = scnprintf( ++ eiter->a.hw_version, sizeof(eiter->a.hw_version), ++ "HW:%s", ha->adapter_id); ++ } ++ alen += FDMI_ATTR_ALIGNMENT(alen); ++ alen += FDMI_ATTR_TYPELEN(eiter); ++ eiter->len = cpu_to_be16(alen); ++ size += alen; ++ ql_dbg(ql_dbg_disc, vha, 0x20a5, ++ "HARDWARE VERSION = %s.\n", eiter->a.hw_version); + /* Driver version. */ + eiter = entries + size; + eiter->type = cpu_to_be16(FDMI_HBA_DRIVER_VERSION); +- snprintf(eiter->a.driver_version, sizeof(eiter->a.driver_version), +- "%s", qla2x00_version_str); +- alen = strlen(eiter->a.driver_version); +- alen += 4 - (alen & 3); +- eiter->len = cpu_to_be16(4 + alen); +- size += 4 + alen; +- +- ql_dbg(ql_dbg_disc, vha, 0x202b, +- "Driver ver = %s.\n", eiter->a.driver_version); +- ++ alen = scnprintf( ++ eiter->a.driver_version, sizeof(eiter->a.driver_version), ++ "%s", qla2x00_version_str); ++ alen += FDMI_ATTR_ALIGNMENT(alen); ++ alen += FDMI_ATTR_TYPELEN(eiter); ++ eiter->len = cpu_to_be16(alen); ++ size += alen; ++ ql_dbg(ql_dbg_disc, vha, 0x20a6, ++ "DRIVER VERSION = %s.\n", eiter->a.driver_version); + /* Option ROM version. */ + eiter = entries + size; + eiter->type = cpu_to_be16(FDMI_HBA_OPTION_ROM_VERSION); +- snprintf(eiter->a.orom_version, sizeof(eiter->a.orom_version), +- "%d.%02d", ha->bios_revision[1], ha->bios_revision[0]); +- alen = strlen(eiter->a.orom_version); +- alen += 4 - (alen & 3); +- eiter->len = cpu_to_be16(4 + alen); +- size += 4 + alen; +- +- ql_dbg(ql_dbg_disc, vha , 0x202c, +- "Optrom vers = %s.\n", eiter->a.orom_version); ++ alen = scnprintf( ++ eiter->a.orom_version, sizeof(eiter->a.orom_version), ++ "%d.%02d", ha->bios_revision[1], ha->bios_revision[0]); ++ alen += FDMI_ATTR_ALIGNMENT(alen); ++ alen += FDMI_ATTR_TYPELEN(eiter); ++ eiter->len = cpu_to_be16(alen); ++ size += alen; + ++ ql_dbg(ql_dbg_disc, vha, 0x20a7, ++ "OPTROM VERSION = %d.%02d.\n", ++ eiter->a.orom_version[1], eiter->a.orom_version[0]); + /* Firmware version */ + eiter = entries + size; + eiter->type = cpu_to_be16(FDMI_HBA_FIRMWARE_VERSION); + ha->isp_ops->fw_version_str(vha, eiter->a.fw_version, + sizeof(eiter->a.fw_version)); +- alen = strlen(eiter->a.fw_version); +- alen += 4 - (alen & 3); +- eiter->len = cpu_to_be16(4 + alen); +- size += 4 + alen; +- +- ql_dbg(ql_dbg_disc, vha, 0x202d, +- "Firmware vers = %s.\n", eiter->a.fw_version); +- +- /* Update MS request size. */ +- qla2x00_update_ms_fdmi_iocb(vha, size + 16); +- +- ql_dbg(ql_dbg_disc, vha, 0x202e, +- "RHBA identifier = %8phN size=%d.\n", +- ct_req->req.rhba.hba_identifier, size); +- ql_dump_buffer(ql_dbg_disc + ql_dbg_buffer, vha, 0x2076, +- entries, size); +- +- /* Execute MS IOCB */ +- rval = qla2x00_issue_iocb(vha, ha->ms_iocb, ha->ms_iocb_dma, +- sizeof(ms_iocb_entry_t)); +- if (rval != QLA_SUCCESS) { +- /*EMPTY*/ +- ql_dbg(ql_dbg_disc, vha, 0x2030, +- "RHBA issue IOCB failed (%d).\n", rval); +- } else if (qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp, "RHBA") != +- QLA_SUCCESS) { +- rval = QLA_FUNCTION_FAILED; +- if (ct_rsp->header.reason_code == CT_REASON_CANNOT_PERFORM && +- ct_rsp->header.explanation_code == +- CT_EXPL_ALREADY_REGISTERED) { +- ql_dbg(ql_dbg_disc, vha, 0x2034, +- "HBA already registered.\n"); +- rval = QLA_ALREADY_REGISTERED; +- } else { +- ql_dbg(ql_dbg_disc, vha, 0x20ad, +- "RHBA FDMI registration failed, CT Reason code: 0x%x, CT Explanation 0x%x\n", +- ct_rsp->header.reason_code, +- ct_rsp->header.explanation_code); +- } +- } else { +- ql_dbg(ql_dbg_disc, vha, 0x2035, +- "RHBA exiting normally.\n"); +- } +- +- return rval; ++ alen += FDMI_ATTR_ALIGNMENT(alen); ++ alen += FDMI_ATTR_TYPELEN(eiter); ++ eiter->len = cpu_to_be16(alen); ++ size += alen; ++ ql_dbg(ql_dbg_disc, vha, 0x20a8, ++ "FIRMWARE VERSION = %s.\n", eiter->a.fw_version); ++ if (callopt == CALLOPT_FDMI1) ++ goto done; ++ /* OS Name and Version */ ++ eiter = entries + size; ++ eiter->type = cpu_to_be16(FDMI_HBA_OS_NAME_AND_VERSION); ++ alen = 0; ++ if (p_sysid) { ++ alen = scnprintf( ++ eiter->a.os_version, sizeof(eiter->a.os_version), ++ "%s %s %s", ++ p_sysid->sysname, p_sysid->release, p_sysid->machine); ++ } ++ if (!alen) { ++ alen = scnprintf( ++ eiter->a.os_version, sizeof(eiter->a.os_version), ++ "%s %s", ++ "Linux", fc_host_system_hostname(vha->host)); ++ } ++ alen += FDMI_ATTR_ALIGNMENT(alen); ++ alen += FDMI_ATTR_TYPELEN(eiter); ++ eiter->len = cpu_to_be16(alen); ++ size += alen; ++ ql_dbg(ql_dbg_disc, vha, 0x20a9, ++ "OS VERSION = %s.\n", eiter->a.os_version); ++ /* MAX CT Payload Length */ ++ eiter = entries + size; ++ eiter->type = cpu_to_be16(FDMI_HBA_MAXIMUM_CT_PAYLOAD_LENGTH); ++ eiter->a.max_ct_len = cpu_to_be32(le16_to_cpu(IS_FWI2_CAPABLE(ha) ? ++ icb24->frame_payload_size : ha->init_cb->frame_payload_size)); ++ alen = sizeof(eiter->a.max_ct_len); ++ alen += FDMI_ATTR_TYPELEN(eiter); ++ eiter->len = cpu_to_be16(alen); ++ size += alen; ++ ql_dbg(ql_dbg_disc, vha, 0x20aa, ++ "CT PAYLOAD LENGTH = 0x%x.\n", be32_to_cpu(eiter->a.max_ct_len)); ++ /* Node Sybolic Name */ ++ eiter = entries + size; ++ eiter->type = cpu_to_be16(FDMI_HBA_NODE_SYMBOLIC_NAME); ++ alen = qla2x00_get_sym_node_name(vha, eiter->a.sym_name, ++ sizeof(eiter->a.sym_name)); ++ alen += FDMI_ATTR_ALIGNMENT(alen); ++ alen += FDMI_ATTR_TYPELEN(eiter); ++ eiter->len = cpu_to_be16(alen); ++ size += alen; ++ ql_dbg(ql_dbg_disc, vha, 0x20ab, ++ "SYMBOLIC NAME = %s.\n", eiter->a.sym_name); ++ /* Vendor Specific information */ ++ eiter = entries + size; ++ eiter->type = cpu_to_be16(FDMI_HBA_VENDOR_SPECIFIC_INFO); ++ eiter->a.vendor_specific_info = cpu_to_be32(PCI_VENDOR_ID_QLOGIC); ++ alen = sizeof(eiter->a.vendor_specific_info); ++ alen += FDMI_ATTR_TYPELEN(eiter); ++ eiter->len = cpu_to_be16(alen); ++ size += alen; ++ ql_dbg(ql_dbg_disc, vha, 0x20ac, ++ "VENDOR SPECIFIC INFO = 0x%x.\n", ++ be32_to_cpu(eiter->a.vendor_specific_info)); ++ /* Num Ports */ ++ eiter = entries + size; ++ eiter->type = cpu_to_be16(FDMI_HBA_NUM_PORTS); ++ eiter->a.num_ports = cpu_to_be32(1); ++ alen = sizeof(eiter->a.num_ports); ++ alen += FDMI_ATTR_TYPELEN(eiter); ++ eiter->len = cpu_to_be16(alen); ++ size += alen; ++ ql_dbg(ql_dbg_disc, vha, 0x20ad, ++ "PORT COUNT = %x.\n", be32_to_cpu(eiter->a.num_ports)); ++ /* Fabric Name */ ++ eiter = entries + size; ++ eiter->type = cpu_to_be16(FDMI_HBA_FABRIC_NAME); ++ memcpy(eiter->a.fabric_name, vha->fabric_node_name, ++ sizeof(eiter->a.fabric_name)); ++ alen = sizeof(eiter->a.fabric_name); ++ alen += FDMI_ATTR_TYPELEN(eiter); ++ eiter->len = cpu_to_be16(alen); ++ size += alen; ++ ql_dbg(ql_dbg_disc, vha, 0x20ae, ++ "FABRIC NAME = %016llx.\n", wwn_to_u64(eiter->a.fabric_name)); ++ /* BIOS Version */ ++ eiter = entries + size; ++ eiter->type = cpu_to_be16(FDMI_HBA_BOOT_BIOS_NAME); ++ alen = scnprintf( ++ eiter->a.bios_name, sizeof(eiter->a.bios_name), ++ "BIOS %d.%02d", ha->bios_revision[1], ha->bios_revision[0]); ++ alen += FDMI_ATTR_ALIGNMENT(alen); ++ alen += FDMI_ATTR_TYPELEN(eiter); ++ eiter->len = cpu_to_be16(alen); ++ size += alen; ++ ql_dbg(ql_dbg_disc, vha, 0x20af, ++ "BIOS NAME = %s\n", eiter->a.bios_name); ++ /* Vendor Identifier */ ++ eiter = entries + size; ++ eiter->type = cpu_to_be16(FDMI_HBA_VENDOR_IDENTIFIER); ++ alen = scnprintf( ++ eiter->a.vendor_identifier, sizeof(eiter->a.vendor_identifier), ++ "%s", "QLGC"); ++ alen += FDMI_ATTR_ALIGNMENT(alen); ++ alen += FDMI_ATTR_TYPELEN(eiter); ++ eiter->len = cpu_to_be16(alen); ++ size += alen; ++ ql_dbg(ql_dbg_disc, vha, 0x20b0, ++ "VENDOR IDENTIFIER = %s.\n", eiter->a.vendor_identifier); ++done: ++ return size; + } + + /** +- * qla2x00_fdmi_rpa() - perform RPA registration ++ * qla2x00_port_attributes() perform Port attributes registration + * @vha: HA context ++ * @entries: number of entries to use ++ * @callopt: Option to issue extended or standard FDMI ++ * command parameter + * + * Returns 0 on success. + */ +-static int +-qla2x00_fdmi_rpa(scsi_qla_host_t *vha) ++static unsigned long ++qla2x00_port_attributes(scsi_qla_host_t *vha, void *entries, ++ unsigned int callopt) + { +- int rval, alen; +- uint32_t size; + struct qla_hw_data *ha = vha->hw; +- ms_iocb_entry_t *ms_pkt; +- struct ct_sns_req *ct_req; +- struct ct_sns_rsp *ct_rsp; +- void *entries; ++ struct init_cb_24xx *icb24 = (void *)ha->init_cb; ++ struct new_utsname *p_sysid = utsname(); ++ char *hostname = p_sysid ? ++ p_sysid->nodename : fc_host_system_hostname(vha->host); + struct ct_fdmi_port_attr *eiter; +- struct init_cb_24xx *icb24 = (struct init_cb_24xx *)ha->init_cb; +- struct new_utsname *p_sysid = NULL; +- +- /* Issue RPA */ +- /* Prepare common MS IOCB */ +- /* Request size adjusted after CT preparation */ +- ms_pkt = ha->isp_ops->prep_ms_fdmi_iocb(vha, 0, RPA_RSP_SIZE); +- +- /* Prepare CT request */ +- ct_req = qla2x00_prep_ct_fdmi_req(ha->ct_sns, RPA_CMD, +- RPA_RSP_SIZE); +- ct_rsp = &ha->ct_sns->p.rsp; +- +- /* Prepare FDMI command arguments -- attribute block, attributes. */ +- memcpy(ct_req->req.rpa.port_name, vha->port_name, WWN_SIZE); +- size = WWN_SIZE + 4; +- +- /* Attributes */ +- ct_req->req.rpa.attrs.count = cpu_to_be32(FDMI_PORT_ATTR_COUNT); +- entries = &ct_req->req; ++ uint16_t alen; ++ unsigned long size = 0; + + /* FC4 types. */ + eiter = entries + size; + eiter->type = cpu_to_be16(FDMI_PORT_FC4_TYPES); +- eiter->len = cpu_to_be16(4 + 32); ++ eiter->a.fc4_types[0] = 0x00; ++ eiter->a.fc4_types[1] = 0x00; + eiter->a.fc4_types[2] = 0x01; +- size += 4 + 32; +- +- ql_dbg(ql_dbg_disc, vha, 0x2039, +- "FC4_TYPES=%02x %02x.\n", +- eiter->a.fc4_types[2], +- eiter->a.fc4_types[1]); +- ++ eiter->a.fc4_types[3] = 0x00; ++ alen = sizeof(eiter->a.fc4_types); ++ alen += FDMI_ATTR_TYPELEN(eiter); ++ eiter->len = cpu_to_be16(alen); ++ size += alen; ++ ql_dbg(ql_dbg_disc, vha, 0x20c0, ++ "FC4 TYPES = %016llx.\n", *(uint64_t *)eiter->a.fc4_types); ++ if (vha->flags.nvme_enabled) { ++ eiter->a.fc4_types[6] = 1; /* NVMe type 28h */ ++ ql_dbg(ql_dbg_disc, vha, 0x211f, ++ "NVME FC4 Type = %02x 0x0 0x0 0x0 0x0 0x0.\n", ++ eiter->a.fc4_types[6]); ++ } + /* Supported speed. */ + eiter = entries + size; + eiter->type = cpu_to_be16(FDMI_PORT_SUPPORT_SPEED); +- eiter->len = cpu_to_be16(4 + 4); +- if (IS_CNA_CAPABLE(ha)) +- eiter->a.sup_speed = cpu_to_be32( +- FDMI_PORT_SPEED_10GB); +- else if (IS_QLA27XX(ha) || IS_QLA28XX(ha)) +- eiter->a.sup_speed = cpu_to_be32( +- FDMI_PORT_SPEED_32GB| +- FDMI_PORT_SPEED_16GB| +- FDMI_PORT_SPEED_8GB); +- else if (IS_QLA2031(ha)) +- eiter->a.sup_speed = cpu_to_be32( +- FDMI_PORT_SPEED_16GB| +- FDMI_PORT_SPEED_8GB| +- FDMI_PORT_SPEED_4GB); +- else if (IS_QLA25XX(ha)) +- eiter->a.sup_speed = cpu_to_be32( +- FDMI_PORT_SPEED_8GB| +- FDMI_PORT_SPEED_4GB| +- FDMI_PORT_SPEED_2GB| +- FDMI_PORT_SPEED_1GB); +- else if (IS_QLA24XX_TYPE(ha)) +- eiter->a.sup_speed = cpu_to_be32( +- FDMI_PORT_SPEED_4GB| +- FDMI_PORT_SPEED_2GB| +- FDMI_PORT_SPEED_1GB); +- else if (IS_QLA23XX(ha)) +- eiter->a.sup_speed = cpu_to_be32( +- FDMI_PORT_SPEED_2GB| +- FDMI_PORT_SPEED_1GB); +- else +- eiter->a.sup_speed = cpu_to_be32( +- FDMI_PORT_SPEED_1GB); +- size += 4 + 4; +- +- ql_dbg(ql_dbg_disc, vha, 0x203a, +- "Supported_Speed=%x.\n", eiter->a.sup_speed); +- ++ eiter->a.sup_speed = cpu_to_be32( ++ qla25xx_fdmi_port_speed_capability(ha)); ++ alen = sizeof(eiter->a.sup_speed); ++ alen += FDMI_ATTR_TYPELEN(eiter); ++ eiter->len = cpu_to_be16(alen); ++ size += alen; ++ ql_dbg(ql_dbg_disc, vha, 0x20c1, ++ "SUPPORTED SPEED = %x.\n", be32_to_cpu(eiter->a.sup_speed)); + /* Current speed. */ + eiter = entries + size; + eiter->type = cpu_to_be16(FDMI_PORT_CURRENT_SPEED); +- eiter->len = cpu_to_be16(4 + 4); +- switch (ha->link_data_rate) { +- case PORT_SPEED_1GB: +- eiter->a.cur_speed = +- cpu_to_be32(FDMI_PORT_SPEED_1GB); +- break; +- case PORT_SPEED_2GB: +- eiter->a.cur_speed = +- cpu_to_be32(FDMI_PORT_SPEED_2GB); +- break; +- case PORT_SPEED_4GB: +- eiter->a.cur_speed = +- cpu_to_be32(FDMI_PORT_SPEED_4GB); +- break; +- case PORT_SPEED_8GB: +- eiter->a.cur_speed = +- cpu_to_be32(FDMI_PORT_SPEED_8GB); +- break; +- case PORT_SPEED_10GB: +- eiter->a.cur_speed = +- cpu_to_be32(FDMI_PORT_SPEED_10GB); +- break; +- case PORT_SPEED_16GB: +- eiter->a.cur_speed = +- cpu_to_be32(FDMI_PORT_SPEED_16GB); +- break; +- case PORT_SPEED_32GB: +- eiter->a.cur_speed = +- cpu_to_be32(FDMI_PORT_SPEED_32GB); +- break; +- default: +- eiter->a.cur_speed = +- cpu_to_be32(FDMI_PORT_SPEED_UNKNOWN); +- break; +- } +- size += 4 + 4; +- +- ql_dbg(ql_dbg_disc, vha, 0x203b, +- "Current_Speed=%x.\n", eiter->a.cur_speed); +- ++ eiter->a.cur_speed = cpu_to_be32( ++ qla25xx_fdmi_port_speed_currently(ha)); ++ alen = sizeof(eiter->a.cur_speed); ++ alen += FDMI_ATTR_TYPELEN(eiter); ++ eiter->len = cpu_to_be16(alen); ++ size += alen; ++ ql_dbg(ql_dbg_disc, vha, 0x20c2, ++ "CURRENT SPEED = %x.\n", be32_to_cpu(eiter->a.cur_speed)); + /* Max frame size. */ + eiter = entries + size; + eiter->type = cpu_to_be16(FDMI_PORT_MAX_FRAME_SIZE); +- eiter->len = cpu_to_be16(4 + 4); +- eiter->a.max_frame_size = IS_FWI2_CAPABLE(ha) ? +- le16_to_cpu(icb24->frame_payload_size) : +- le16_to_cpu(ha->init_cb->frame_payload_size); +- eiter->a.max_frame_size = cpu_to_be32(eiter->a.max_frame_size); +- size += 4 + 4; +- +- ql_dbg(ql_dbg_disc, vha, 0x203c, +- "Max_Frame_Size=%x.\n", eiter->a.max_frame_size); +- ++ eiter->a.max_frame_size = cpu_to_be32(le16_to_cpu(IS_FWI2_CAPABLE(ha) ? ++ icb24->frame_payload_size : ha->init_cb->frame_payload_size)); ++ alen = sizeof(eiter->a.max_frame_size); ++ alen += FDMI_ATTR_TYPELEN(eiter); ++ eiter->len = cpu_to_be16(alen); ++ size += alen; ++ ql_dbg(ql_dbg_disc, vha, 0x20c3, ++ "MAX FRAME SIZE = %x.\n", be32_to_cpu(eiter->a.max_frame_size)); + /* OS device name. */ + eiter = entries + size; + eiter->type = cpu_to_be16(FDMI_PORT_OS_DEVICE_NAME); +- snprintf(eiter->a.os_dev_name, sizeof(eiter->a.os_dev_name), +- "%s:host%lu", QLA2XXX_DRIVER_NAME, vha->host_no); +- alen = strlen(eiter->a.os_dev_name); +- alen += 4 - (alen & 3); +- eiter->len = cpu_to_be16(4 + alen); +- size += 4 + alen; +- +- ql_dbg(ql_dbg_disc, vha, 0x204b, +- "OS_Device_Name=%s.\n", eiter->a.os_dev_name); +- ++ alen = scnprintf( ++ eiter->a.os_dev_name, sizeof(eiter->a.os_dev_name), ++ "%s:host%lu", QLA2XXX_DRIVER_NAME, vha->host_no); ++ alen += FDMI_ATTR_ALIGNMENT(alen); ++ alen += FDMI_ATTR_TYPELEN(eiter); ++ eiter->len = cpu_to_be16(alen); ++ size += alen; ++ ql_dbg(ql_dbg_disc, vha, 0x20c4, ++ "OS DEVICE NAME = %s.\n", eiter->a.os_dev_name); + /* Hostname. */ + eiter = entries + size; + eiter->type = cpu_to_be16(FDMI_PORT_HOST_NAME); +- p_sysid = utsname(); +- if (p_sysid) { +- snprintf(eiter->a.host_name, sizeof(eiter->a.host_name), +- "%s", p_sysid->nodename); +- } else { +- snprintf(eiter->a.host_name, sizeof(eiter->a.host_name), +- "%s", fc_host_system_hostname(vha->host)); +- } +- alen = strlen(eiter->a.host_name); +- alen += 4 - (alen & 3); +- eiter->len = cpu_to_be16(4 + alen); +- size += 4 + alen; +- +- ql_dbg(ql_dbg_disc, vha, 0x203d, "HostName=%s.\n", eiter->a.host_name); +- +- /* Update MS request size. */ +- qla2x00_update_ms_fdmi_iocb(vha, size + 16); +- +- ql_dbg(ql_dbg_disc, vha, 0x203e, +- "RPA portname %016llx, size = %d.\n", +- wwn_to_u64(ct_req->req.rpa.port_name), size); +- ql_dump_buffer(ql_dbg_disc + ql_dbg_buffer, vha, 0x2079, +- entries, size); +- +- /* Execute MS IOCB */ +- rval = qla2x00_issue_iocb(vha, ha->ms_iocb, ha->ms_iocb_dma, +- sizeof(ms_iocb_entry_t)); +- if (rval != QLA_SUCCESS) { +- /*EMPTY*/ +- ql_dbg(ql_dbg_disc, vha, 0x2040, +- "RPA issue IOCB failed (%d).\n", rval); +- } else if (qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp, "RPA") != +- QLA_SUCCESS) { +- rval = QLA_FUNCTION_FAILED; +- if (ct_rsp->header.reason_code == CT_REASON_CANNOT_PERFORM && +- ct_rsp->header.explanation_code == +- CT_EXPL_ALREADY_REGISTERED) { +- ql_dbg(ql_dbg_disc, vha, 0x20cd, +- "RPA already registered.\n"); +- rval = QLA_ALREADY_REGISTERED; +- } +- +- } else { +- ql_dbg(ql_dbg_disc, vha, 0x2041, +- "RPA exiting normally.\n"); +- } +- +- return rval; +-} +- +-/** +- * qla2x00_fdmiv2_rhba() - perform RHBA FDMI v2 registration +- * @vha: HA context +- * +- * Returns 0 on success. +- */ +-static int +-qla2x00_fdmiv2_rhba(scsi_qla_host_t *vha) +-{ +- int rval, alen; +- uint32_t size, sn; +- ms_iocb_entry_t *ms_pkt; +- struct ct_sns_req *ct_req; +- struct ct_sns_rsp *ct_rsp; +- void *entries; +- struct ct_fdmiv2_hba_attr *eiter; +- struct qla_hw_data *ha = vha->hw; +- struct new_utsname *p_sysid = NULL; +- +- /* Issue RHBA */ +- /* Prepare common MS IOCB */ +- /* Request size adjusted after CT preparation */ +- ms_pkt = ha->isp_ops->prep_ms_fdmi_iocb(vha, 0, RHBA_RSP_SIZE); +- +- /* Prepare CT request */ +- ct_req = qla2x00_prep_ct_fdmi_req(ha->ct_sns, RHBA_CMD, +- RHBA_RSP_SIZE); +- ct_rsp = &ha->ct_sns->p.rsp; ++ if (!*hostname || !strncmp(hostname, "(none)", 6)) ++ hostname = "Linux-default"; ++ alen = scnprintf( ++ eiter->a.host_name, sizeof(eiter->a.host_name), ++ "%s", hostname); ++ alen += FDMI_ATTR_ALIGNMENT(alen); ++ alen += FDMI_ATTR_TYPELEN(eiter); ++ eiter->len = cpu_to_be16(alen); ++ size += alen; ++ ql_dbg(ql_dbg_disc, vha, 0x20c5, ++ "HOSTNAME = %s.\n", eiter->a.host_name); + +- /* Prepare FDMI command arguments -- attribute block, attributes. */ +- memcpy(ct_req->req.rhba2.hba_identifier, vha->port_name, WWN_SIZE); +- ct_req->req.rhba2.entry_count = cpu_to_be32(1); +- memcpy(ct_req->req.rhba2.port_name, vha->port_name, WWN_SIZE); +- size = 2 * WWN_SIZE + 4 + 4; +- +- /* Attributes */ +- ct_req->req.rhba2.attrs.count = cpu_to_be32(FDMIV2_HBA_ATTR_COUNT); +- entries = &ct_req->req; ++ if (callopt == CALLOPT_FDMI1) ++ goto done; + +- /* Nodename. */ ++ /* Node Name */ + eiter = entries + size; +- eiter->type = cpu_to_be16(FDMI_HBA_NODE_NAME); +- eiter->len = cpu_to_be16(4 + WWN_SIZE); +- memcpy(eiter->a.node_name, vha->node_name, WWN_SIZE); +- size += 4 + WWN_SIZE; +- +- ql_dbg(ql_dbg_disc, vha, 0x207d, +- "NodeName = %016llx.\n", wwn_to_u64(eiter->a.node_name)); ++ eiter->type = cpu_to_be16(FDMI_PORT_NODE_NAME); ++ memcpy(eiter->a.node_name, vha->node_name, sizeof(eiter->a.node_name)); ++ alen = sizeof(eiter->a.node_name); ++ alen += FDMI_ATTR_TYPELEN(eiter); ++ eiter->len = cpu_to_be16(alen); ++ size += alen; ++ ql_dbg(ql_dbg_disc, vha, 0x20c6, ++ "NODENAME = %016llx.\n", wwn_to_u64(eiter->a.node_name)); + +- /* Manufacturer. */ ++ /* Port Name */ + eiter = entries + size; +- eiter->type = cpu_to_be16(FDMI_HBA_MANUFACTURER); +- snprintf(eiter->a.manufacturer, sizeof(eiter->a.manufacturer), +- "%s", "QLogic Corporation"); +- eiter->a.manufacturer[strlen("QLogic Corporation")] = '\0'; +- alen = strlen(eiter->a.manufacturer); +- alen += 4 - (alen & 3); +- eiter->len = cpu_to_be16(4 + alen); +- size += 4 + alen; +- +- ql_dbg(ql_dbg_disc, vha, 0x20a5, +- "Manufacturer = %s.\n", eiter->a.manufacturer); ++ eiter->type = cpu_to_be16(FDMI_PORT_NAME); ++ memcpy(eiter->a.port_name, vha->port_name, sizeof(eiter->a.port_name)); ++ alen = sizeof(eiter->a.port_name); ++ alen += FDMI_ATTR_TYPELEN(eiter); ++ eiter->len = cpu_to_be16(alen); ++ size += alen; ++ ql_dbg(ql_dbg_disc, vha, 0x20c7, ++ "PORTNAME = %016llx.\n", wwn_to_u64(eiter->a.port_name)); + +- /* Serial number. */ ++ /* Port Symbolic Name */ + eiter = entries + size; +- eiter->type = cpu_to_be16(FDMI_HBA_SERIAL_NUMBER); +- if (IS_FWI2_CAPABLE(ha)) +- qla2xxx_get_vpd_field(vha, "SN", eiter->a.serial_num, +- sizeof(eiter->a.serial_num)); +- else { +- sn = ((ha->serial0 & 0x1f) << 16) | +- (ha->serial2 << 8) | ha->serial1; +- snprintf(eiter->a.serial_num, sizeof(eiter->a.serial_num), +- "%c%05d", 'A' + sn / 100000, sn % 100000); +- } +- alen = strlen(eiter->a.serial_num); +- alen += 4 - (alen & 3); +- eiter->len = cpu_to_be16(4 + alen); +- size += 4 + alen; +- +- ql_dbg(ql_dbg_disc, vha, 0x20a6, +- "Serial no. = %s.\n", eiter->a.serial_num); ++ eiter->type = cpu_to_be16(FDMI_PORT_SYM_NAME); ++ alen = qla2x00_get_sym_node_name(vha, eiter->a.port_sym_name, ++ sizeof(eiter->a.port_sym_name)); ++ alen += FDMI_ATTR_ALIGNMENT(alen); ++ alen += FDMI_ATTR_TYPELEN(eiter); ++ eiter->len = cpu_to_be16(alen); ++ size += alen; ++ ql_dbg(ql_dbg_disc, vha, 0x20c8, ++ "PORT SYMBOLIC NAME = %s\n", eiter->a.port_sym_name); + +- /* Model name. */ ++ /* Port Type */ + eiter = entries + size; +- eiter->type = cpu_to_be16(FDMI_HBA_MODEL); +- snprintf(eiter->a.model, sizeof(eiter->a.model), +- "%s", ha->model_number); +- alen = strlen(eiter->a.model); +- alen += 4 - (alen & 3); +- eiter->len = cpu_to_be16(4 + alen); +- size += 4 + alen; +- +- ql_dbg(ql_dbg_disc, vha, 0x20a7, +- "Model Name = %s.\n", eiter->a.model); ++ eiter->type = cpu_to_be16(FDMI_PORT_TYPE); ++ eiter->a.port_type = cpu_to_be32(NS_NX_PORT_TYPE); ++ alen = sizeof(eiter->a.port_type); ++ alen += FDMI_ATTR_TYPELEN(eiter); ++ eiter->len = cpu_to_be16(alen); ++ size += alen; ++ ql_dbg(ql_dbg_disc, vha, 0x20c9, ++ "PORT TYPE = %x.\n", be32_to_cpu(eiter->a.port_type)); + +- /* Model description. */ ++ /* Supported Class of Service */ + eiter = entries + size; +- eiter->type = cpu_to_be16(FDMI_HBA_MODEL_DESCRIPTION); +- snprintf(eiter->a.model_desc, sizeof(eiter->a.model_desc), +- "%s", ha->model_desc); +- alen = strlen(eiter->a.model_desc); +- alen += 4 - (alen & 3); +- eiter->len = cpu_to_be16(4 + alen); +- size += 4 + alen; +- +- ql_dbg(ql_dbg_disc, vha, 0x20a8, +- "Model Desc = %s.\n", eiter->a.model_desc); ++ eiter->type = cpu_to_be16(FDMI_PORT_SUPP_COS); ++ eiter->a.port_supported_cos = cpu_to_be32(FC_CLASS_3); ++ alen = sizeof(eiter->a.port_supported_cos); ++ alen += FDMI_ATTR_TYPELEN(eiter); ++ eiter->len = cpu_to_be16(alen); ++ size += alen; ++ ql_dbg(ql_dbg_disc, vha, 0x20ca, ++ "SUPPORTED COS = %08x\n", be32_to_cpu(eiter->a.port_supported_cos)); + +- /* Hardware version. */ ++ /* Port Fabric Name */ + eiter = entries + size; +- eiter->type = cpu_to_be16(FDMI_HBA_HARDWARE_VERSION); +- if (!IS_FWI2_CAPABLE(ha)) { +- snprintf(eiter->a.hw_version, sizeof(eiter->a.hw_version), +- "HW:%s", ha->adapter_id); +- } else if (qla2xxx_get_vpd_field(vha, "MN", eiter->a.hw_version, +- sizeof(eiter->a.hw_version))) { +- ; +- } else if (qla2xxx_get_vpd_field(vha, "EC", eiter->a.hw_version, +- sizeof(eiter->a.hw_version))) { +- ; +- } else { +- snprintf(eiter->a.hw_version, sizeof(eiter->a.hw_version), +- "HW:%s", ha->adapter_id); +- } +- alen = strlen(eiter->a.hw_version); +- alen += 4 - (alen & 3); +- eiter->len = cpu_to_be16(4 + alen); +- size += 4 + alen; +- +- ql_dbg(ql_dbg_disc, vha, 0x20a9, +- "Hardware ver = %s.\n", eiter->a.hw_version); ++ eiter->type = cpu_to_be16(FDMI_PORT_FABRIC_NAME); ++ memcpy(eiter->a.fabric_name, vha->fabric_node_name, ++ sizeof(eiter->a.fabric_name)); ++ alen = sizeof(eiter->a.fabric_name); ++ alen += FDMI_ATTR_TYPELEN(eiter); ++ eiter->len = cpu_to_be16(alen); ++ size += alen; ++ ql_dbg(ql_dbg_disc, vha, 0x20cb, ++ "FABRIC NAME = %016llx.\n", wwn_to_u64(eiter->a.fabric_name)); + +- /* Driver version. */ ++ /* FC4_type */ + eiter = entries + size; +- eiter->type = cpu_to_be16(FDMI_HBA_DRIVER_VERSION); +- snprintf(eiter->a.driver_version, sizeof(eiter->a.driver_version), +- "%s", qla2x00_version_str); +- alen = strlen(eiter->a.driver_version); +- alen += 4 - (alen & 3); +- eiter->len = cpu_to_be16(4 + alen); +- size += 4 + alen; +- +- ql_dbg(ql_dbg_disc, vha, 0x20aa, +- "Driver ver = %s.\n", eiter->a.driver_version); ++ eiter->type = cpu_to_be16(FDMI_PORT_FC4_TYPE); ++ eiter->a.port_fc4_type[0] = 0x00; ++ eiter->a.port_fc4_type[1] = 0x00; ++ eiter->a.port_fc4_type[2] = 0x01; ++ eiter->a.port_fc4_type[3] = 0x00; ++ alen = sizeof(eiter->a.port_fc4_type); ++ alen += FDMI_ATTR_TYPELEN(eiter); ++ eiter->len = cpu_to_be16(alen); ++ size += alen; ++ ql_dbg(ql_dbg_disc, vha, 0x20cc, ++ "PORT ACTIVE FC4 TYPE = %016llx.\n", ++ *(uint64_t *)eiter->a.port_fc4_type); + +- /* Option ROM version. */ ++ /* Port State */ + eiter = entries + size; +- eiter->type = cpu_to_be16(FDMI_HBA_OPTION_ROM_VERSION); +- snprintf(eiter->a.orom_version, sizeof(eiter->a.orom_version), +- "%d.%02d", ha->bios_revision[1], ha->bios_revision[0]); +- alen = strlen(eiter->a.orom_version); +- alen += 4 - (alen & 3); +- eiter->len = cpu_to_be16(4 + alen); +- size += 4 + alen; +- +- ql_dbg(ql_dbg_disc, vha , 0x20ab, +- "Optrom version = %d.%02d.\n", eiter->a.orom_version[1], +- eiter->a.orom_version[0]); ++ eiter->type = cpu_to_be16(FDMI_PORT_STATE); ++ eiter->a.port_state = cpu_to_be32(2); ++ alen = sizeof(eiter->a.port_state); ++ alen += FDMI_ATTR_TYPELEN(eiter); ++ eiter->len = cpu_to_be16(alen); ++ size += alen; ++ ql_dbg(ql_dbg_disc, vha, 0x20cd, ++ "PORT_STATE = %x.\n", be32_to_cpu(eiter->a.port_state)); + +- /* Firmware version */ ++ /* Number of Ports */ + eiter = entries + size; +- eiter->type = cpu_to_be16(FDMI_HBA_FIRMWARE_VERSION); +- ha->isp_ops->fw_version_str(vha, eiter->a.fw_version, +- sizeof(eiter->a.fw_version)); +- alen = strlen(eiter->a.fw_version); +- alen += 4 - (alen & 3); +- eiter->len = cpu_to_be16(4 + alen); +- size += 4 + alen; +- +- ql_dbg(ql_dbg_disc, vha, 0x20ac, +- "Firmware vers = %s.\n", eiter->a.fw_version); ++ eiter->type = cpu_to_be16(FDMI_PORT_COUNT); ++ eiter->a.num_ports = cpu_to_be32(1); ++ alen = sizeof(eiter->a.num_ports); ++ alen += FDMI_ATTR_TYPELEN(eiter); ++ eiter->len = cpu_to_be16(alen); ++ size += alen; ++ ql_dbg(ql_dbg_disc, vha, 0x20ce, ++ "PORT COUNT = %x.\n", be32_to_cpu(eiter->a.num_ports)); + +- /* OS Name and Version */ ++ /* Port Identifier */ + eiter = entries + size; +- eiter->type = cpu_to_be16(FDMI_HBA_OS_NAME_AND_VERSION); +- p_sysid = utsname(); +- if (p_sysid) { +- snprintf(eiter->a.os_version, sizeof(eiter->a.os_version), +- "%s %s %s", +- p_sysid->sysname, p_sysid->release, p_sysid->version); +- } else { +- snprintf(eiter->a.os_version, sizeof(eiter->a.os_version), +- "%s %s", "Linux", fc_host_system_hostname(vha->host)); +- } +- alen = strlen(eiter->a.os_version); +- alen += 4 - (alen & 3); +- eiter->len = cpu_to_be16(4 + alen); +- size += 4 + alen; ++ eiter->type = cpu_to_be16(FDMI_PORT_IDENTIFIER); ++ eiter->a.port_id = cpu_to_be32(vha->d_id.b24); ++ alen = sizeof(eiter->a.port_id); ++ alen += FDMI_ATTR_TYPELEN(eiter); ++ eiter->len = cpu_to_be16(alen); ++ size += alen; ++ ql_dbg(ql_dbg_disc, vha, 0x20cf, ++ "PORT ID = %x.\n", be32_to_cpu(eiter->a.port_id)); + +- ql_dbg(ql_dbg_disc, vha, 0x20ae, +- "OS Name and Version = %s.\n", eiter->a.os_version); ++ if (callopt == CALLOPT_FDMI2 || !ql2xsmartsan) ++ goto done; + +- /* MAX CT Payload Length */ ++ /* Smart SAN Service Category (Populate Smart SAN Initiator)*/ + eiter = entries + size; +- eiter->type = cpu_to_be16(FDMI_HBA_MAXIMUM_CT_PAYLOAD_LENGTH); +- eiter->a.max_ct_len = cpu_to_be32(ha->frame_payload_size); +- eiter->a.max_ct_len = cpu_to_be32(eiter->a.max_ct_len); +- eiter->len = cpu_to_be16(4 + 4); +- size += 4 + 4; ++ eiter->type = cpu_to_be16(FDMI_SMARTSAN_SERVICE); ++ alen = scnprintf( ++ eiter->a.smartsan_service, sizeof(eiter->a.smartsan_service), ++ "%s", "Smart SAN Initiator"); ++ alen += FDMI_ATTR_ALIGNMENT(alen); ++ alen += FDMI_ATTR_TYPELEN(eiter); ++ eiter->len = cpu_to_be16(alen); ++ size += alen; ++ ql_dbg(ql_dbg_disc, vha, 0x20d0, ++ "SMARTSAN SERVICE CATEGORY = %s.\n", eiter->a.smartsan_service); ++ ++ /* Smart SAN GUID (NWWN+PWWN) */ ++ eiter = entries + size; ++ eiter->type = cpu_to_be16(FDMI_SMARTSAN_GUID); ++ memcpy(eiter->a.smartsan_guid, vha->node_name, WWN_SIZE); ++ memcpy(eiter->a.smartsan_guid + WWN_SIZE, vha->port_name, WWN_SIZE); ++ alen = sizeof(eiter->a.smartsan_guid); ++ alen += FDMI_ATTR_TYPELEN(eiter); ++ eiter->len = cpu_to_be16(alen); ++ size += alen; ++ ql_dbg(ql_dbg_disc, vha, 0x20d1, ++ "Smart SAN GUID = %016llx-%016llx\n", ++ wwn_to_u64(eiter->a.smartsan_guid), ++ wwn_to_u64(eiter->a.smartsan_guid + WWN_SIZE)); ++ ++ /* Smart SAN Version (populate "Smart SAN Version 1.0") */ ++ eiter = entries + size; ++ eiter->type = cpu_to_be16(FDMI_SMARTSAN_VERSION); ++ alen = scnprintf( ++ eiter->a.smartsan_version, sizeof(eiter->a.smartsan_version), ++ "%s", "Smart SAN Version 2.0"); ++ alen += FDMI_ATTR_ALIGNMENT(alen); ++ alen += FDMI_ATTR_TYPELEN(eiter); ++ eiter->len = cpu_to_be16(alen); ++ size += alen; ++ ql_dbg(ql_dbg_disc, vha, 0x20d2, ++ "SMARTSAN VERSION = %s\n", eiter->a.smartsan_version); ++ ++ /* Smart SAN Product Name (Specify Adapter Model No) */ ++ eiter = entries + size; ++ eiter->type = cpu_to_be16(FDMI_SMARTSAN_PROD_NAME); ++ alen = scnprintf(eiter->a.smartsan_prod_name, ++ sizeof(eiter->a.smartsan_prod_name), ++ "ISP%04x", ha->pdev->device); ++ alen += FDMI_ATTR_ALIGNMENT(alen); ++ alen += FDMI_ATTR_TYPELEN(eiter); ++ eiter->len = cpu_to_be16(alen); ++ size += alen; ++ ql_dbg(ql_dbg_disc, vha, 0x20d3, ++ "SMARTSAN PRODUCT NAME = %s\n", eiter->a.smartsan_prod_name); ++ ++ /* Smart SAN Port Info (specify: 1=Physical, 2=NPIV, 3=SRIOV) */ ++ eiter = entries + size; ++ eiter->type = cpu_to_be16(FDMI_SMARTSAN_PORT_INFO); ++ eiter->a.smartsan_port_info = cpu_to_be32(vha->vp_idx ? 2 : 1); ++ alen = sizeof(eiter->a.smartsan_port_info); ++ alen += FDMI_ATTR_TYPELEN(eiter); ++ eiter->len = cpu_to_be16(alen); ++ size += alen; ++ ql_dbg(ql_dbg_disc, vha, 0x20d4, ++ "SMARTSAN PORT INFO = %x\n", eiter->a.smartsan_port_info); ++ ++ /* Smart SAN Security Support */ ++ eiter = entries + size; ++ eiter->type = cpu_to_be16(FDMI_SMARTSAN_SECURITY_SUPPORT); ++ eiter->a.smartsan_security_support = cpu_to_be32(1); ++ alen = sizeof(eiter->a.smartsan_security_support); ++ alen += FDMI_ATTR_TYPELEN(eiter); ++ eiter->len = cpu_to_be16(alen); ++ size += alen; ++ ql_dbg(ql_dbg_disc, vha, 0x20d6, ++ "SMARTSAN SECURITY SUPPORT = %d\n", ++ be32_to_cpu(eiter->a.smartsan_security_support)); + +- ql_dbg(ql_dbg_disc, vha, 0x20af, +- "CT Payload Length = 0x%x.\n", eiter->a.max_ct_len); ++done: ++ return size; ++} + +- /* Node Sybolic Name */ +- eiter = entries + size; +- eiter->type = cpu_to_be16(FDMI_HBA_NODE_SYMBOLIC_NAME); +- qla2x00_get_sym_node_name(vha, eiter->a.sym_name, +- sizeof(eiter->a.sym_name)); +- alen = strlen(eiter->a.sym_name); +- alen += 4 - (alen & 3); +- eiter->len = cpu_to_be16(4 + alen); +- size += 4 + alen; ++/** ++ * qla2x00_fdmi_rhba() - perform RHBA FDMI registration ++ * @vha: HA context ++ * @callopt: Option to issue FDMI registration ++ * ++ * Returns 0 on success. ++ */ ++static int ++qla2x00_fdmi_rhba(scsi_qla_host_t *vha, unsigned int callopt) ++{ ++ struct qla_hw_data *ha = vha->hw; ++ unsigned long size = 0; ++ unsigned int rval, count; ++ ms_iocb_entry_t *ms_pkt; ++ struct ct_sns_req *ct_req; ++ struct ct_sns_rsp *ct_rsp; ++ void *entries; + +- ql_dbg(ql_dbg_disc, vha, 0x20b0, +- "Symbolic Name = %s.\n", eiter->a.sym_name); ++ count = callopt != CALLOPT_FDMI1 ? ++ FDMI2_HBA_ATTR_COUNT : FDMI1_HBA_ATTR_COUNT; + +- /* Vendor Id */ +- eiter = entries + size; +- eiter->type = cpu_to_be16(FDMI_HBA_VENDOR_ID); +- eiter->a.vendor_id = cpu_to_be32(0x1077); +- eiter->len = cpu_to_be16(4 + 4); +- size += 4 + 4; ++ size = RHBA_RSP_SIZE; + +- ql_dbg(ql_dbg_disc, vha, 0x20b1, +- "Vendor Id = %x.\n", eiter->a.vendor_id); ++ ql_dbg(ql_dbg_disc, vha, 0x20e0, ++ "RHBA (callopt=%x count=%u size=%lu).\n", callopt, count, size); + +- /* Num Ports */ +- eiter = entries + size; +- eiter->type = cpu_to_be16(FDMI_HBA_NUM_PORTS); +- eiter->a.num_ports = cpu_to_be32(1); +- eiter->len = cpu_to_be16(4 + 4); +- size += 4 + 4; ++ /* Request size adjusted after CT preparation */ ++ ms_pkt = ha->isp_ops->prep_ms_fdmi_iocb(vha, 0, size); + +- ql_dbg(ql_dbg_disc, vha, 0x20b2, +- "Port Num = %x.\n", eiter->a.num_ports); ++ /* Prepare CT request */ ++ ct_req = qla2x00_prep_ct_fdmi_req(ha->ct_sns, RHBA_CMD, size); ++ ct_rsp = &ha->ct_sns->p.rsp; + +- /* Fabric Name */ +- eiter = entries + size; +- eiter->type = cpu_to_be16(FDMI_HBA_FABRIC_NAME); +- memcpy(eiter->a.fabric_name, vha->fabric_node_name, WWN_SIZE); +- eiter->len = cpu_to_be16(4 + WWN_SIZE); +- size += 4 + WWN_SIZE; ++ /* Prepare FDMI command entries */ ++ memcpy(ct_req->req.rhba.hba_identifier, vha->port_name, ++ sizeof(ct_req->req.rhba.hba_identifier)); ++ size += sizeof(ct_req->req.rhba.hba_identifier); + +- ql_dbg(ql_dbg_disc, vha, 0x20b3, +- "Fabric Name = %016llx.\n", wwn_to_u64(eiter->a.fabric_name)); ++ ct_req->req.rhba.entry_count = cpu_to_be32(1); ++ size += sizeof(ct_req->req.rhba.entry_count); + +- /* BIOS Version */ +- eiter = entries + size; +- eiter->type = cpu_to_be16(FDMI_HBA_BOOT_BIOS_NAME); +- snprintf(eiter->a.bios_name, sizeof(eiter->a.bios_name), +- "BIOS %d.%02d", ha->bios_revision[1], ha->bios_revision[0]); +- alen = strlen(eiter->a.bios_name); +- alen += 4 - (alen & 3); +- eiter->len = cpu_to_be16(4 + alen); +- size += 4 + alen; ++ memcpy(ct_req->req.rhba.port_name, vha->port_name, ++ sizeof(ct_req->req.rhba.port_name)); ++ size += sizeof(ct_req->req.rhba.port_name); + +- ql_dbg(ql_dbg_disc, vha, 0x20b4, +- "BIOS Name = %s\n", eiter->a.bios_name); ++ /* Attribute count */ ++ ct_req->req.rhba.attrs.count = cpu_to_be32(count); ++ size += sizeof(ct_req->req.rhba.attrs.count); + +- /* Vendor Identifier */ +- eiter = entries + size; +- eiter->type = cpu_to_be16(FDMI_HBA_TYPE_VENDOR_IDENTIFIER); +- snprintf(eiter->a.vendor_identifier, sizeof(eiter->a.vendor_identifier), +- "%s", "QLGC"); +- alen = strlen(eiter->a.vendor_identifier); +- alen += 4 - (alen & 3); +- eiter->len = cpu_to_be16(4 + alen); +- size += 4 + alen; ++ /* Attribute block */ ++ entries = &ct_req->req.rhba.attrs.entry; + +- ql_dbg(ql_dbg_disc, vha, 0x201b, +- "Vendor Identifier = %s.\n", eiter->a.vendor_identifier); ++ size += qla2x00_hba_attributes(vha, entries, callopt); + + /* Update MS request size. */ + qla2x00_update_ms_fdmi_iocb(vha, size + 16); + +- ql_dbg(ql_dbg_disc, vha, 0x20b5, +- "RHBA identifier = %016llx.\n", +- wwn_to_u64(ct_req->req.rhba2.hba_identifier)); +- ql_dump_buffer(ql_dbg_disc + ql_dbg_buffer, vha, 0x20b6, ++ ql_dbg(ql_dbg_disc, vha, 0x20e1, ++ "RHBA %016llx %016llx.\n", ++ wwn_to_u64(ct_req->req.rhba.hba_identifier), ++ wwn_to_u64(ct_req->req.rhba.port_name)); ++ ++ ql_dump_buffer(ql_dbg_disc + ql_dbg_buffer, vha, 0x20e2, + entries, size); + + /* Execute MS IOCB */ + rval = qla2x00_issue_iocb(vha, ha->ms_iocb, ha->ms_iocb_dma, +- sizeof(ms_iocb_entry_t)); +- if (rval != QLA_SUCCESS) { +- /*EMPTY*/ +- ql_dbg(ql_dbg_disc, vha, 0x20b7, +- "RHBA issue IOCB failed (%d).\n", rval); +- } else if (qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp, "RHBA") != +- QLA_SUCCESS) { +- rval = QLA_FUNCTION_FAILED; ++ sizeof(*ha->ms_iocb)); ++ if (rval) { ++ ql_dbg(ql_dbg_disc, vha, 0x20e3, ++ "RHBA iocb failed (%d).\n", rval); ++ return rval; ++ } + ++ rval = qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp, "RHBA"); ++ if (rval) { + if (ct_rsp->header.reason_code == CT_REASON_CANNOT_PERFORM && + ct_rsp->header.explanation_code == + CT_EXPL_ALREADY_REGISTERED) { +- ql_dbg(ql_dbg_disc, vha, 0x20b8, +- "HBA already registered.\n"); +- rval = QLA_ALREADY_REGISTERED; +- } else { +- ql_dbg(ql_dbg_disc, vha, 0x2016, +- "RHBA FDMI v2 failed, CT Reason code: 0x%x, CT Explanation 0x%x\n", +- ct_rsp->header.reason_code, +- ct_rsp->header.explanation_code); ++ ql_dbg(ql_dbg_disc, vha, 0x20e4, ++ "RHBA already registered.\n"); ++ return QLA_ALREADY_REGISTERED; + } +- } else { +- ql_dbg(ql_dbg_disc, vha, 0x20b9, +- "RHBA FDMI V2 exiting normally.\n"); ++ ++ ql_dbg(ql_dbg_disc, vha, 0x20e5, ++ "RHBA failed, CT Reason %#x, CT Explanation %#x\n", ++ ct_rsp->header.reason_code, ++ ct_rsp->header.explanation_code); ++ return rval; + } + ++ ql_dbg(ql_dbg_disc, vha, 0x20e6, "RHBA exiting normally.\n"); + return rval; + } + +-/** +- * qla2x00_fdmi_dhba() - +- * @vha: HA context +- * +- * Returns 0 on success. +- */ ++ + static int + qla2x00_fdmi_dhba(scsi_qla_host_t *vha) + { +@@ -2249,22 +2236,17 @@ qla2x00_fdmi_dhba(scsi_qla_host_t *vha) + ms_iocb_entry_t *ms_pkt; + struct ct_sns_req *ct_req; + struct ct_sns_rsp *ct_rsp; +- + /* Issue RPA */ + /* Prepare common MS IOCB */ + ms_pkt = ha->isp_ops->prep_ms_fdmi_iocb(vha, DHBA_REQ_SIZE, + DHBA_RSP_SIZE); +- + /* Prepare CT request */ + ct_req = qla2x00_prep_ct_fdmi_req(ha->ct_sns, DHBA_CMD, DHBA_RSP_SIZE); + ct_rsp = &ha->ct_sns->p.rsp; +- + /* Prepare FDMI command arguments -- portname. */ + memcpy(ct_req->req.dhba.port_name, vha->port_name, WWN_SIZE); +- + ql_dbg(ql_dbg_disc, vha, 0x2036, + "DHBA portname = %8phN.\n", ct_req->req.dhba.port_name); +- + /* Execute MS IOCB */ + rval = qla2x00_issue_iocb(vha, ha->ms_iocb, ha->ms_iocb_dma, + sizeof(ms_iocb_entry_t)); +@@ -2279,337 +2261,178 @@ qla2x00_fdmi_dhba(scsi_qla_host_t *vha) + ql_dbg(ql_dbg_disc, vha, 0x2038, + "DHBA exiting normally.\n"); + } +- + return rval; + } + + /** +- * qla2x00_fdmiv2_rpa() - ++ * qla2x00_fdmi_rprt() perform RPRT registration + * @vha: HA context ++ * @callopt: Option to issue extended or standard FDMI ++ * command parameter + * + * Returns 0 on success. + */ + static int +-qla2x00_fdmiv2_rpa(scsi_qla_host_t *vha) ++qla2x00_fdmi_rprt(scsi_qla_host_t *vha, int callopt) + { +- int rval, alen; +- uint32_t size; ++ struct scsi_qla_host *base_vha = pci_get_drvdata(vha->hw->pdev); + struct qla_hw_data *ha = vha->hw; ++ ulong size = 0; ++ uint rval, count; + ms_iocb_entry_t *ms_pkt; + struct ct_sns_req *ct_req; + struct ct_sns_rsp *ct_rsp; + void *entries; +- struct ct_fdmiv2_port_attr *eiter; +- struct init_cb_24xx *icb24 = (struct init_cb_24xx *)ha->init_cb; +- struct new_utsname *p_sysid = NULL; +- +- /* Issue RPA */ +- /* Prepare common MS IOCB */ +- /* Request size adjusted after CT preparation */ +- ms_pkt = ha->isp_ops->prep_ms_fdmi_iocb(vha, 0, RPA_RSP_SIZE); +- ++ count = callopt == CALLOPT_FDMI2_SMARTSAN && ql2xsmartsan ? ++ FDMI2_SMARTSAN_PORT_ATTR_COUNT : ++ callopt != CALLOPT_FDMI1 ? ++ FDMI2_PORT_ATTR_COUNT : FDMI1_PORT_ATTR_COUNT; ++ ++ size = RPRT_RSP_SIZE; ++ ql_dbg(ql_dbg_disc, vha, 0x20e8, ++ "RPRT (callopt=%x count=%u size=%lu).\n", callopt, count, size); ++ /* Request size adjusted after CT preparation */ ++ ms_pkt = ha->isp_ops->prep_ms_fdmi_iocb(vha, 0, size); + /* Prepare CT request */ +- ct_req = qla2x00_prep_ct_fdmi_req(ha->ct_sns, RPA_CMD, RPA_RSP_SIZE); ++ ct_req = qla2x00_prep_ct_fdmi_req(ha->ct_sns, RPRT_CMD, size); + ct_rsp = &ha->ct_sns->p.rsp; +- +- /* Prepare FDMI command arguments -- attribute block, attributes. */ +- memcpy(ct_req->req.rpa2.port_name, vha->port_name, WWN_SIZE); +- size = WWN_SIZE + 4; +- +- /* Attributes */ +- ct_req->req.rpa2.attrs.count = cpu_to_be32(FDMIV2_PORT_ATTR_COUNT); +- entries = &ct_req->req; +- +- /* FC4 types. */ +- eiter = entries + size; +- eiter->type = cpu_to_be16(FDMI_PORT_FC4_TYPES); +- eiter->len = cpu_to_be16(4 + 32); +- eiter->a.fc4_types[2] = 0x01; +- size += 4 + 32; +- +- ql_dbg(ql_dbg_disc, vha, 0x20ba, +- "FC4_TYPES=%02x %02x.\n", +- eiter->a.fc4_types[2], +- eiter->a.fc4_types[1]); +- +- if (vha->flags.nvme_enabled) { +- eiter->a.fc4_types[6] = 1; /* NVMe type 28h */ +- ql_dbg(ql_dbg_disc, vha, 0x211f, +- "NVME FC4 Type = %02x 0x0 0x0 0x0 0x0 0x0.\n", +- eiter->a.fc4_types[6]); +- } +- +- /* Supported speed. */ +- eiter = entries + size; +- eiter->type = cpu_to_be16(FDMI_PORT_SUPPORT_SPEED); +- eiter->len = cpu_to_be16(4 + 4); +- if (IS_CNA_CAPABLE(ha)) +- eiter->a.sup_speed = cpu_to_be32( +- FDMI_PORT_SPEED_10GB); +- else if (IS_QLA27XX(ha) || IS_QLA28XX(ha)) +- eiter->a.sup_speed = cpu_to_be32( +- FDMI_PORT_SPEED_32GB| +- FDMI_PORT_SPEED_16GB| +- FDMI_PORT_SPEED_8GB); +- else if (IS_QLA2031(ha)) +- eiter->a.sup_speed = cpu_to_be32( +- FDMI_PORT_SPEED_16GB| +- FDMI_PORT_SPEED_8GB| +- FDMI_PORT_SPEED_4GB); +- else if (IS_QLA25XX(ha)) +- eiter->a.sup_speed = cpu_to_be32( +- FDMI_PORT_SPEED_8GB| +- FDMI_PORT_SPEED_4GB| +- FDMI_PORT_SPEED_2GB| +- FDMI_PORT_SPEED_1GB); +- else if (IS_QLA24XX_TYPE(ha)) +- eiter->a.sup_speed = cpu_to_be32( +- FDMI_PORT_SPEED_4GB| +- FDMI_PORT_SPEED_2GB| +- FDMI_PORT_SPEED_1GB); +- else if (IS_QLA23XX(ha)) +- eiter->a.sup_speed = cpu_to_be32( +- FDMI_PORT_SPEED_2GB| +- FDMI_PORT_SPEED_1GB); +- else +- eiter->a.sup_speed = cpu_to_be32( +- FDMI_PORT_SPEED_1GB); +- size += 4 + 4; +- +- ql_dbg(ql_dbg_disc, vha, 0x20bb, +- "Supported Port Speed = %x.\n", eiter->a.sup_speed); +- +- /* Current speed. */ +- eiter = entries + size; +- eiter->type = cpu_to_be16(FDMI_PORT_CURRENT_SPEED); +- eiter->len = cpu_to_be16(4 + 4); +- switch (ha->link_data_rate) { +- case PORT_SPEED_1GB: +- eiter->a.cur_speed = cpu_to_be32(FDMI_PORT_SPEED_1GB); +- break; +- case PORT_SPEED_2GB: +- eiter->a.cur_speed = cpu_to_be32(FDMI_PORT_SPEED_2GB); +- break; +- case PORT_SPEED_4GB: +- eiter->a.cur_speed = cpu_to_be32(FDMI_PORT_SPEED_4GB); +- break; +- case PORT_SPEED_8GB: +- eiter->a.cur_speed = cpu_to_be32(FDMI_PORT_SPEED_8GB); +- break; +- case PORT_SPEED_10GB: +- eiter->a.cur_speed = cpu_to_be32(FDMI_PORT_SPEED_10GB); +- break; +- case PORT_SPEED_16GB: +- eiter->a.cur_speed = cpu_to_be32(FDMI_PORT_SPEED_16GB); +- break; +- case PORT_SPEED_32GB: +- eiter->a.cur_speed = cpu_to_be32(FDMI_PORT_SPEED_32GB); +- break; +- default: +- eiter->a.cur_speed = cpu_to_be32(FDMI_PORT_SPEED_UNKNOWN); +- break; ++ /* Prepare FDMI command entries */ ++ memcpy(ct_req->req.rprt.hba_identifier, base_vha->port_name, ++ sizeof(ct_req->req.rprt.hba_identifier)); ++ size += sizeof(ct_req->req.rprt.hba_identifier); ++ memcpy(ct_req->req.rprt.port_name, vha->port_name, ++ sizeof(ct_req->req.rprt.port_name)); ++ size += sizeof(ct_req->req.rprt.port_name); ++ /* Attribute count */ ++ ct_req->req.rprt.attrs.count = cpu_to_be32(count); ++ size += sizeof(ct_req->req.rprt.attrs.count); ++ /* Attribute block */ ++ entries = ct_req->req.rprt.attrs.entry; ++ size += qla2x00_port_attributes(vha, entries, callopt); ++ /* Update MS request size. */ ++ qla2x00_update_ms_fdmi_iocb(vha, size + 16); ++ ql_dbg(ql_dbg_disc, vha, 0x20e9, ++ "RPRT %016llx %016llx.\n", ++ wwn_to_u64(ct_req->req.rprt.port_name), ++ wwn_to_u64(ct_req->req.rprt.port_name)); ++ ql_dump_buffer(ql_dbg_disc + ql_dbg_buffer, vha, 0x20ea, ++ entries, size); ++ /* Execute MS IOCB */ ++ rval = qla2x00_issue_iocb(vha, ha->ms_iocb, ha->ms_iocb_dma, ++ sizeof(*ha->ms_iocb)); ++ if (rval) { ++ ql_dbg(ql_dbg_disc, vha, 0x20eb, ++ "RPRT iocb failed (%d).\n", rval); ++ return rval; + } +- size += 4 + 4; +- +- ql_dbg(ql_dbg_disc, vha, 0x2017, +- "Current_Speed = %x.\n", eiter->a.cur_speed); +- +- /* Max frame size. */ +- eiter = entries + size; +- eiter->type = cpu_to_be16(FDMI_PORT_MAX_FRAME_SIZE); +- eiter->len = cpu_to_be16(4 + 4); +- eiter->a.max_frame_size = IS_FWI2_CAPABLE(ha) ? +- le16_to_cpu(icb24->frame_payload_size) : +- le16_to_cpu(ha->init_cb->frame_payload_size); +- eiter->a.max_frame_size = cpu_to_be32(eiter->a.max_frame_size); +- size += 4 + 4; +- +- ql_dbg(ql_dbg_disc, vha, 0x20bc, +- "Max_Frame_Size = %x.\n", eiter->a.max_frame_size); +- +- /* OS device name. */ +- eiter = entries + size; +- eiter->type = cpu_to_be16(FDMI_PORT_OS_DEVICE_NAME); +- alen = strlen(QLA2XXX_DRIVER_NAME); +- snprintf(eiter->a.os_dev_name, sizeof(eiter->a.os_dev_name), +- "%s:host%lu", QLA2XXX_DRIVER_NAME, vha->host_no); +- alen += 4 - (alen & 3); +- eiter->len = cpu_to_be16(4 + alen); +- size += 4 + alen; +- +- ql_dbg(ql_dbg_disc, vha, 0x20be, +- "OS_Device_Name = %s.\n", eiter->a.os_dev_name); ++ rval = qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp, "RPRT"); ++ if (rval) { ++ if (ct_rsp->header.reason_code == CT_REASON_CANNOT_PERFORM && ++ ct_rsp->header.explanation_code == ++ CT_EXPL_ALREADY_REGISTERED) { ++ ql_dbg(ql_dbg_disc, vha, 0x20ec, ++ "RPRT already registered.\n"); ++ return QLA_ALREADY_REGISTERED; ++ } + +- /* Hostname. */ +- eiter = entries + size; +- eiter->type = cpu_to_be16(FDMI_PORT_HOST_NAME); +- p_sysid = utsname(); +- if (p_sysid) { +- snprintf(eiter->a.host_name, sizeof(eiter->a.host_name), +- "%s", p_sysid->nodename); +- } else { +- snprintf(eiter->a.host_name, sizeof(eiter->a.host_name), +- "%s", fc_host_system_hostname(vha->host)); ++ ql_dbg(ql_dbg_disc, vha, 0x20ed, ++ "RPRT failed, CT Reason code: %#x, CT Explanation %#x\n", ++ ct_rsp->header.reason_code, ++ ct_rsp->header.explanation_code); ++ return rval; + } +- alen = strlen(eiter->a.host_name); +- alen += 4 - (alen & 3); +- eiter->len = cpu_to_be16(4 + alen); +- size += 4 + alen; +- +- ql_dbg(ql_dbg_disc, vha, 0x201a, +- "HostName=%s.\n", eiter->a.host_name); +- +- /* Node Name */ +- eiter = entries + size; +- eiter->type = cpu_to_be16(FDMI_PORT_NODE_NAME); +- memcpy(eiter->a.node_name, vha->node_name, WWN_SIZE); +- eiter->len = cpu_to_be16(4 + WWN_SIZE); +- size += 4 + WWN_SIZE; +- +- ql_dbg(ql_dbg_disc, vha, 0x20c0, +- "Node Name = %016llx.\n", wwn_to_u64(eiter->a.node_name)); +- +- /* Port Name */ +- eiter = entries + size; +- eiter->type = cpu_to_be16(FDMI_PORT_NAME); +- memcpy(eiter->a.port_name, vha->port_name, WWN_SIZE); +- eiter->len = cpu_to_be16(4 + WWN_SIZE); +- size += 4 + WWN_SIZE; +- +- ql_dbg(ql_dbg_disc, vha, 0x20c1, +- "Port Name = %016llx.\n", wwn_to_u64(eiter->a.port_name)); +- +- /* Port Symbolic Name */ +- eiter = entries + size; +- eiter->type = cpu_to_be16(FDMI_PORT_SYM_NAME); +- qla2x00_get_sym_node_name(vha, eiter->a.port_sym_name, +- sizeof(eiter->a.port_sym_name)); +- alen = strlen(eiter->a.port_sym_name); +- alen += 4 - (alen & 3); +- eiter->len = cpu_to_be16(4 + alen); +- size += 4 + alen; +- +- ql_dbg(ql_dbg_disc, vha, 0x20c2, +- "port symbolic name = %s\n", eiter->a.port_sym_name); +- +- /* Port Type */ +- eiter = entries + size; +- eiter->type = cpu_to_be16(FDMI_PORT_TYPE); +- eiter->a.port_type = cpu_to_be32(NS_NX_PORT_TYPE); +- eiter->len = cpu_to_be16(4 + 4); +- size += 4 + 4; +- +- ql_dbg(ql_dbg_disc, vha, 0x20c3, +- "Port Type = %x.\n", eiter->a.port_type); +- +- /* Class of Service */ +- eiter = entries + size; +- eiter->type = cpu_to_be16(FDMI_PORT_SUPP_COS); +- eiter->a.port_supported_cos = cpu_to_be32(FC_CLASS_3); +- eiter->len = cpu_to_be16(4 + 4); +- size += 4 + 4; +- +- ql_dbg(ql_dbg_disc, vha, 0x20c4, +- "Supported COS = %08x\n", eiter->a.port_supported_cos); +- +- /* Port Fabric Name */ +- eiter = entries + size; +- eiter->type = cpu_to_be16(FDMI_PORT_FABRIC_NAME); +- memcpy(eiter->a.fabric_name, vha->fabric_node_name, WWN_SIZE); +- eiter->len = cpu_to_be16(4 + WWN_SIZE); +- size += 4 + WWN_SIZE; +- +- ql_dbg(ql_dbg_disc, vha, 0x20c5, +- "Fabric Name = %016llx.\n", wwn_to_u64(eiter->a.fabric_name)); +- +- /* FC4_type */ +- eiter = entries + size; +- eiter->type = cpu_to_be16(FDMI_PORT_FC4_TYPE); +- eiter->a.port_fc4_type[0] = 0; +- eiter->a.port_fc4_type[1] = 0; +- eiter->a.port_fc4_type[2] = 1; +- eiter->a.port_fc4_type[3] = 0; +- eiter->len = cpu_to_be16(4 + 32); +- size += 4 + 32; ++ ql_dbg(ql_dbg_disc, vha, 0x20ee, "RPRT exiting normally.\n"); ++ return rval; ++} + +- ql_dbg(ql_dbg_disc, vha, 0x20c6, +- "Port Active FC4 Type = %02x %02x.\n", +- eiter->a.port_fc4_type[2], eiter->a.port_fc4_type[1]); ++/** ++ * qla2x00_fdmi_rpa() - perform RPA registration ++ * @vha: HA context ++ * @callopt: Option to issue FDMI registration ++ * ++ * Returns 0 on success. ++ */ ++static int ++qla2x00_fdmi_rpa(scsi_qla_host_t *vha, uint callopt) ++{ ++ struct qla_hw_data *ha = vha->hw; ++ ulong size = 0; ++ uint rval, count; ++ ms_iocb_entry_t *ms_pkt; ++ struct ct_sns_req *ct_req; ++ struct ct_sns_rsp *ct_rsp; ++ void *entries; + +- if (vha->flags.nvme_enabled) { +- eiter->a.port_fc4_type[4] = 0; +- eiter->a.port_fc4_type[5] = 0; +- eiter->a.port_fc4_type[6] = 1; /* NVMe type 28h */ +- ql_dbg(ql_dbg_disc, vha, 0x2120, +- "NVME Port Active FC4 Type = %02x 0x0 0x0 0x0 0x0 0x0.\n", +- eiter->a.port_fc4_type[6]); +- } ++ count = ++ callopt == CALLOPT_FDMI2_SMARTSAN && ql2xsmartsan ? ++ FDMI2_SMARTSAN_PORT_ATTR_COUNT : ++ callopt != CALLOPT_FDMI1 ? ++ FDMI2_PORT_ATTR_COUNT : FDMI1_PORT_ATTR_COUNT; ++ ++ size = ++ callopt != CALLOPT_FDMI1 ? ++ SMARTSAN_RPA_RSP_SIZE : RPA_RSP_SIZE; + +- /* Port State */ +- eiter = entries + size; +- eiter->type = cpu_to_be16(FDMI_PORT_STATE); +- eiter->a.port_state = cpu_to_be32(1); +- eiter->len = cpu_to_be16(4 + 4); +- size += 4 + 4; ++ ql_dbg(ql_dbg_disc, vha, 0x20f0, ++ "RPA (callopt=%x count=%u size=%lu).\n", callopt, count, size); + +- ql_dbg(ql_dbg_disc, vha, 0x20c7, +- "Port State = %x.\n", eiter->a.port_state); ++ /* Request size adjusted after CT preparation */ ++ ms_pkt = ha->isp_ops->prep_ms_fdmi_iocb(vha, 0, size); + +- /* Number of Ports */ +- eiter = entries + size; +- eiter->type = cpu_to_be16(FDMI_PORT_COUNT); +- eiter->a.num_ports = cpu_to_be32(1); +- eiter->len = cpu_to_be16(4 + 4); +- size += 4 + 4; ++ /* Prepare CT request */ ++ ct_req = qla2x00_prep_ct_fdmi_req(ha->ct_sns, RPA_CMD, size); ++ ct_rsp = &ha->ct_sns->p.rsp; + +- ql_dbg(ql_dbg_disc, vha, 0x20c8, +- "Number of ports = %x.\n", eiter->a.num_ports); ++ /* Prepare FDMI command entries. */ ++ memcpy(ct_req->req.rpa.port_name, vha->port_name, ++ sizeof(ct_req->req.rpa.port_name)); ++ size += sizeof(ct_req->req.rpa.port_name); ++ ++ /* Attribute count */ ++ ct_req->req.rpa.attrs.count = cpu_to_be32(count); ++ size += sizeof(ct_req->req.rpa.attrs.count); + +- /* Port Id */ +- eiter = entries + size; +- eiter->type = cpu_to_be16(FDMI_PORT_ID); +- eiter->a.port_id = cpu_to_be32(vha->d_id.b24); +- eiter->len = cpu_to_be16(4 + 4); +- size += 4 + 4; ++ /* Attribute block */ ++ entries = ct_req->req.rpa.attrs.entry; + +- ql_dbg(ql_dbg_disc, vha, 0x201c, +- "Port Id = %x.\n", eiter->a.port_id); ++ size += qla2x00_port_attributes(vha, entries, callopt); + + /* Update MS request size. */ + qla2x00_update_ms_fdmi_iocb(vha, size + 16); + +- ql_dbg(ql_dbg_disc, vha, 0x2018, +- "RPA portname= %8phN size=%d.\n", ct_req->req.rpa.port_name, size); +- ql_dump_buffer(ql_dbg_disc + ql_dbg_buffer, vha, 0x20ca, ++ ql_dbg(ql_dbg_disc, vha, 0x20f1, ++ "RPA %016llx.\n", wwn_to_u64(ct_req->req.rpa.port_name)); ++ ++ ql_dump_buffer(ql_dbg_disc + ql_dbg_buffer, vha, 0x20f2, + entries, size); + + /* Execute MS IOCB */ + rval = qla2x00_issue_iocb(vha, ha->ms_iocb, ha->ms_iocb_dma, +- sizeof(ms_iocb_entry_t)); +- if (rval != QLA_SUCCESS) { +- /*EMPTY*/ +- ql_dbg(ql_dbg_disc, vha, 0x20cb, +- "RPA FDMI v2 issue IOCB failed (%d).\n", rval); +- } else if (qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp, "RPA") != +- QLA_SUCCESS) { +- rval = QLA_FUNCTION_FAILED; ++ sizeof(*ha->ms_iocb)); ++ if (rval) { ++ ql_dbg(ql_dbg_disc, vha, 0x20f3, ++ "RPA iocb failed (%d).\n", rval); ++ return rval; ++ } ++ ++ rval = qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp, "RPA"); ++ if (rval) { + if (ct_rsp->header.reason_code == CT_REASON_CANNOT_PERFORM && + ct_rsp->header.explanation_code == + CT_EXPL_ALREADY_REGISTERED) { +- ql_dbg(ql_dbg_disc, vha, 0x20ce, +- "RPA FDMI v2 already registered\n"); +- rval = QLA_ALREADY_REGISTERED; +- } else { +- ql_dbg(ql_dbg_disc, vha, 0x2020, +- "RPA FDMI v2 failed, CT Reason code: 0x%x, CT Explanation 0x%x\n", +- ct_rsp->header.reason_code, +- ct_rsp->header.explanation_code); ++ ql_dbg(ql_dbg_disc, vha, 0x20f4, ++ "RPA already registered.\n"); ++ return QLA_ALREADY_REGISTERED; + } +- } else { +- ql_dbg(ql_dbg_disc, vha, 0x20cc, +- "RPA FDMI V2 exiting normally.\n"); ++ ++ ql_dbg(ql_dbg_disc, vha, 0x20f5, ++ "RPA failed, CT Reason code: %#x, CT Explanation %#x\n", ++ ct_rsp->header.reason_code, ++ ct_rsp->header.explanation_code); ++ return rval; + } + ++ ql_dbg(ql_dbg_disc, vha, 0x20f6, "RPA exiting normally.\n"); + return rval; + } + +@@ -2622,18 +2445,31 @@ qla2x00_fdmiv2_rpa(scsi_qla_host_t *vha) + int + qla2x00_fdmi_register(scsi_qla_host_t *vha) + { +- int rval = QLA_FUNCTION_FAILED; ++ int rval = QLA_SUCCESS; + struct qla_hw_data *ha = vha->hw; + + if (IS_QLA2100(ha) || IS_QLA2200(ha) || + IS_QLAFX00(ha)) +- return QLA_FUNCTION_FAILED; ++ return rval; + + rval = qla2x00_mgmt_svr_login(vha); + if (rval) + return rval; + +- rval = qla2x00_fdmiv2_rhba(vha); ++ /* For npiv/vport send rprt only */ ++ if (vha->vp_idx) { ++ if (ql2xsmartsan) ++ rval = qla2x00_fdmi_rprt(vha, CALLOPT_FDMI2_SMARTSAN); ++ if (rval || !ql2xsmartsan) ++ rval = qla2x00_fdmi_rprt(vha, CALLOPT_FDMI2); ++ if (rval) ++ rval = qla2x00_fdmi_rprt(vha, CALLOPT_FDMI1); ++ ++ return rval; ++ } ++ ++ /* Try fdmi2 first, if fails then try fdmi1 */ ++ rval = qla2x00_fdmi_rhba(vha, CALLOPT_FDMI2); + if (rval) { + if (rval != QLA_ALREADY_REGISTERED) + goto try_fdmi; +@@ -2642,18 +2478,22 @@ qla2x00_fdmi_register(scsi_qla_host_t *v + if (rval) + goto try_fdmi; + +- rval = qla2x00_fdmiv2_rhba(vha); ++ rval = qla2x00_fdmi_rhba(vha, CALLOPT_FDMI2); + if (rval) + goto try_fdmi; + } +- rval = qla2x00_fdmiv2_rpa(vha); ++ ++ if (ql2xsmartsan) ++ rval = qla2x00_fdmi_rpa(vha, CALLOPT_FDMI2_SMARTSAN); ++ if (rval || !ql2xsmartsan) ++ rval = qla2x00_fdmi_rpa(vha, CALLOPT_FDMI2); + if (rval) + goto try_fdmi; + +- goto out; ++ return rval; + + try_fdmi: +- rval = qla2x00_fdmi_rhba(vha); ++ rval = qla2x00_fdmi_rhba(vha, CALLOPT_FDMI1); + if (rval) { + if (rval != QLA_ALREADY_REGISTERED) + return rval; +@@ -2662,12 +2502,13 @@ try_fdmi: + if (rval) + return rval; + +- rval = qla2x00_fdmi_rhba(vha); ++ rval = qla2x00_fdmi_rhba(vha, CALLOPT_FDMI1); + if (rval) + return rval; + } +- rval = qla2x00_fdmi_rpa(vha); +-out: ++ ++ rval = qla2x00_fdmi_rpa(vha, CALLOPT_FDMI1); ++ + return rval; + } + diff --git a/patches.suse/scsi-qla2xxx-Add-vendor-extended-RDP-additions-and-a.patch b/patches.suse/scsi-qla2xxx-Add-vendor-extended-RDP-additions-and-a.patch new file mode 100644 index 0000000..6757072 --- /dev/null +++ b/patches.suse/scsi-qla2xxx-Add-vendor-extended-RDP-additions-and-a.patch @@ -0,0 +1,1016 @@ +From: Joe Carnuccio +Date: Wed, 12 Feb 2020 13:44:18 -0800 +Subject: scsi: qla2xxx: Add vendor extended RDP additions and amendments +Patch-mainline: v5.7-rc1 +Git-commit: d83a80ee57f0cb38baccc75e96bc56ac47d300b3 +References: bsc#1157424 + +This patch adds RDP command support in the driver. With the help of new +ql2xsmartsan parameter, driver will use PUREX IOCB mode to send RDP command +to switch and will be able to receive various diagnostic data. + +Link: https://lore.kernel.org/r/20200212214436.25532-8-hmadhani@marvell.com +Signed-off-by: Joe Carnuccio +Signed-off-by: Himanshu Madhani +Signed-off-by: Martin K. Petersen +Acked-by: Daniel Wagner +--- + drivers/scsi/qla2xxx/qla_def.h | 135 +++++++++ + drivers/scsi/qla2xxx/qla_fw.h | 44 +++ + drivers/scsi/qla2xxx/qla_gbl.h | 3 + drivers/scsi/qla2xxx/qla_init.c | 15 + + drivers/scsi/qla2xxx/qla_isr.c | 10 + drivers/scsi/qla2xxx/qla_mbx.c | 58 ++++ + drivers/scsi/qla2xxx/qla_os.c | 546 +++++++++++++++++++++++++++++++++++++++- + 7 files changed, 807 insertions(+), 4 deletions(-) + +--- a/drivers/scsi/qla2xxx/qla_def.h ++++ b/drivers/scsi/qla2xxx/qla_def.h +@@ -1267,6 +1267,9 @@ static inline bool qla2xxx_is_valid_mbs( + #define RNID_TYPE_SET_VERSION 0x9 + #define RNID_TYPE_ASIC_TEMP 0xC + ++#define ELS_CMD_MAP_SIZE 32 ++#define ELS_COMMAND_RDP 0x18 ++ + /* + * Firmware state codes from get firmware state mailbox command + */ +@@ -3562,6 +3565,133 @@ struct qlfc_fw { + uint32_t len; + }; + ++struct rdp_req_payload { ++ uint32_t els_request; ++ uint32_t desc_list_len; ++ ++ /* NPIV descriptor */ ++ struct { ++ uint32_t desc_tag; ++ uint32_t desc_len; ++ uint8_t reserved; ++ uint8_t nport_id[3]; ++ } npiv_desc; ++}; ++ ++struct rdp_rsp_payload { ++ struct { ++ uint32_t cmd; ++ uint32_t len; ++ } hdr; ++ ++ /* LS Request Info descriptor */ ++ struct { ++ uint32_t desc_tag; ++ uint32_t desc_len; ++ uint32_t req_payload_word_0; ++ } ls_req_info_desc; ++ ++ /* LS Request Info descriptor */ ++ struct { ++ uint32_t desc_tag; ++ uint32_t desc_len; ++ uint32_t req_payload_word_0; ++ } ls_req_info_desc2; ++ ++ /* SFP diagnostic param descriptor */ ++ struct { ++ uint32_t desc_tag; ++ uint32_t desc_len; ++ uint16_t temperature; ++ uint16_t vcc; ++ uint16_t tx_bias; ++ uint16_t tx_power; ++ uint16_t rx_power; ++ uint16_t sfp_flags; ++ } sfp_diag_desc; ++ ++ /* Port Speed Descriptor */ ++ struct { ++ uint32_t desc_tag; ++ uint32_t desc_len; ++ uint16_t speed_capab; ++ uint16_t operating_speed; ++ } port_speed_desc; ++ ++ /* Link Error Status Descriptor */ ++ struct { ++ uint32_t desc_tag; ++ uint32_t desc_len; ++ uint32_t link_fail_cnt; ++ uint32_t loss_sync_cnt; ++ uint32_t loss_sig_cnt; ++ uint32_t prim_seq_err_cnt; ++ uint32_t inval_xmit_word_cnt; ++ uint32_t inval_crc_cnt; ++ uint8_t pn_port_phy_type; ++ uint8_t reserved[3]; ++ } ls_err_desc; ++ ++ /* Port name description with diag param */ ++ struct { ++ uint32_t desc_tag; ++ uint32_t desc_len; ++ uint8_t WWNN[WWN_SIZE]; ++ uint8_t WWPN[WWN_SIZE]; ++ } port_name_diag_desc; ++ ++ /* Port Name desc for Direct attached Fx_Port or Nx_Port */ ++ struct { ++ uint32_t desc_tag; ++ uint32_t desc_len; ++ uint8_t WWNN[WWN_SIZE]; ++ uint8_t WWPN[WWN_SIZE]; ++ } port_name_direct_desc; ++ ++ /* Buffer Credit descriptor */ ++ struct { ++ uint32_t desc_tag; ++ uint32_t desc_len; ++ uint32_t fcport_b2b; ++ uint32_t attached_fcport_b2b; ++ uint32_t fcport_rtt; ++ } buffer_credit_desc; ++ ++ /* Optical Element Data Descriptor */ ++ struct { ++ uint32_t desc_tag; ++ uint32_t desc_len; ++ uint16_t high_alarm; ++ uint16_t low_alarm; ++ uint16_t high_warn; ++ uint16_t low_warn; ++ uint32_t element_flags; ++ } optical_elmt_desc[5]; ++ ++ /* Optical Product Data Descriptor */ ++ struct { ++ uint32_t desc_tag; ++ uint32_t desc_len; ++ uint8_t vendor_name[16]; ++ uint8_t part_number[16]; ++ uint8_t serial_number[16]; ++ uint8_t revision[4]; ++ uint8_t date[8]; ++ } optical_prod_desc; ++}; ++ ++#define RDP_DESC_LEN(obj) \ ++ (sizeof(obj) - sizeof((obj).desc_tag) - sizeof((obj).desc_len)) ++ ++#define RDP_PORT_SPEED_1GB BIT_15 ++#define RDP_PORT_SPEED_2GB BIT_14 ++#define RDP_PORT_SPEED_4GB BIT_13 ++#define RDP_PORT_SPEED_10GB BIT_12 ++#define RDP_PORT_SPEED_8GB BIT_11 ++#define RDP_PORT_SPEED_16GB BIT_10 ++#define RDP_PORT_SPEED_32GB BIT_9 ++#define RDP_PORT_SPEED_UNKNOWN BIT_0 ++ + struct scsi_qlt_host { + void *target_lport_ptr; + struct mutex tgt_mutex; +@@ -3965,6 +4095,8 @@ struct qla_hw_data { + + #define SFP_DEV_SIZE 512 + #define SFP_BLOCK_SIZE 64 ++#define SFP_RTDI_LEN SFP_BLOCK_SIZE ++ + void *sfp_data; + dma_addr_t sfp_data_dma; + +@@ -4424,6 +4556,8 @@ typedef struct scsi_qla_host { + #define ISP_ABORT_TO_ROM 33 + #define VPORT_DELETE 34 + ++#define PROCESS_PUREX_IOCB 63 ++ + unsigned long pci_flags; + #define PFLG_DISCONNECTED 0 /* PCI device removed */ + #define PFLG_DRIVER_REMOVING 1 /* PCI driver .remove */ +@@ -4532,6 +4666,7 @@ typedef struct scsi_qla_host { + uint16_t ql2xexchoffld; + uint16_t ql2xiniexchg; + ++ void *purex_data; + struct name_list_extended gnl; + /* Count of active session/fcport */ + int fcport_count; +--- a/drivers/scsi/qla2xxx/qla_fw.h ++++ b/drivers/scsi/qla2xxx/qla_fw.h +@@ -724,6 +724,50 @@ struct ct_entry_24xx { + }; + + /* ++ * ISP queue - PUREX IOCB entry structure definition ++ */ ++#define PUREX_IOCB_TYPE 0x51 /* CT Pass Through IOCB entry */ ++typedef struct purex_entry_24xx { ++ uint8_t entry_type; /* Entry type. */ ++ uint8_t entry_count; /* Entry count. */ ++ uint8_t sys_define; /* System defined. */ ++ uint8_t entry_status; /* Entry Status. */ ++ ++ uint16_t reserved1; ++ uint8_t vp_idx; ++ uint8_t reserved2; ++ ++ uint16_t status_flags; ++ uint16_t nport_handle; ++ ++ uint16_t frame_size; ++ uint16_t trunc_frame_size; ++ ++ uint32_t rx_xchg_addr; ++ ++ uint8_t d_id[3]; ++ uint8_t r_ctl; ++ ++ uint8_t s_id[3]; ++ uint8_t cs_ctl; ++ ++ uint8_t f_ctl[3]; ++ uint8_t type; ++ ++ uint16_t seq_cnt; ++ uint8_t df_ctl; ++ uint8_t seq_id; ++ ++ uint16_t rx_id; ++ uint16_t ox_id; ++ uint32_t param; ++ ++ uint8_t els_frame_payload[20]; ++} purex_entry_24xx_t; ++ ++#define PUREX_ENTRY_SIZE (sizeof(purex_entry_24xx_t)) ++ ++/* + * ISP queue - ELS Pass-Through entry structure definition. + */ + #define ELS_IOCB_TYPE 0x53 /* ELS Pass-Through IOCB entry */ +--- a/drivers/scsi/qla2xxx/qla_gbl.h ++++ b/drivers/scsi/qla2xxx/qla_gbl.h +@@ -458,6 +458,9 @@ extern int + qla25xx_set_driver_version(scsi_qla_host_t *, char *); + + extern int ++qla25xx_set_els_cmds_supported(scsi_qla_host_t *); ++ ++extern int + qla24xx_get_buffer_credits(scsi_qla_host_t *, struct buffer_credit_24xx *, + dma_addr_t); + +--- a/drivers/scsi/qla2xxx/qla_init.c ++++ b/drivers/scsi/qla2xxx/qla_init.c +@@ -3708,6 +3708,10 @@ enable_82xx_npiv: + "ISP Firmware failed checksum.\n"); + goto failed; + } ++ ++ /* Enable PUREX PASSTHRU */ ++ if (ql2xsmartsan) ++ qla25xx_set_els_cmds_supported(vha); + } else + goto failed; + +@@ -3929,7 +3933,7 @@ qla24xx_update_fw_options(scsi_qla_host_ + + /* Update Serial Link options. */ + if ((le16_to_cpu(ha->fw_seriallink_options24[0]) & BIT_0) == 0) +- return; ++ goto enable_purex; + + rval = qla2x00_set_serdes_params(vha, + le16_to_cpu(ha->fw_seriallink_options24[1]), +@@ -3939,6 +3943,12 @@ qla24xx_update_fw_options(scsi_qla_host_ + ql_log(ql_log_warn, vha, 0x0104, + "Unable to update Serial Link options (%x).\n", rval); + } ++ ++enable_purex: ++ if (ql2xsmartsan) ++ ha->fw_options[1] |= ADD_FO1_ENABLE_PUREX_IOCB; ++ ++ qla2x00_set_fw_options(vha, ha->fw_options); + } + + void +@@ -8672,6 +8682,9 @@ qla83xx_update_fw_options(scsi_qla_host_ + { + struct qla_hw_data *ha = vha->hw; + ++ if (ql2xsmartsan) ++ ha->fw_options[1] |= ADD_FO1_ENABLE_PUREX_IOCB; ++ + qla2x00_set_fw_options(vha, ha->fw_options); + } + +--- a/drivers/scsi/qla2xxx/qla_isr.c ++++ b/drivers/scsi/qla2xxx/qla_isr.c +@@ -31,6 +31,13 @@ const char *const port_state_str[] = { + "ONLINE" + }; + ++static void qla24xx_purex_iocb(scsi_qla_host_t *vha, struct req_que *req, ++ struct sts_entry_24xx *pkt) ++{ ++ memcpy(vha->purex_data, pkt, PUREX_ENTRY_SIZE); ++ set_bit(PROCESS_PUREX_IOCB, &vha->dpc_flags); ++} ++ + /** + * qla2100_intr_handler() - Process interrupts for the ISP2100 and ISP2200. + * @irq: interrupt number +@@ -3116,6 +3123,9 @@ process_err: + qla_ctrlvp_completed(vha, rsp->req, + (struct vp_ctrl_entry_24xx *)pkt); + break; ++ case PUREX_IOCB_TYPE: ++ qla24xx_purex_iocb(vha, rsp->req, pkt); ++ break; + default: + /* Type Not Supported. */ + ql_dbg(ql_dbg_async, vha, 0x5042, +--- a/drivers/scsi/qla2xxx/qla_mbx.c ++++ b/drivers/scsi/qla2xxx/qla_mbx.c +@@ -4878,6 +4878,64 @@ qla24xx_get_port_login_templ(scsi_qla_ho + } + + int ++qla25xx_set_els_cmds_supported(scsi_qla_host_t *vha) ++{ ++ int rval; ++ mbx_cmd_t mc; ++ mbx_cmd_t *mcp = &mc; ++ uint8_t *els_cmd_map; ++ dma_addr_t els_cmd_map_dma; ++ uint cmd_opcode = ELS_COMMAND_RDP; ++ uint index = cmd_opcode / 8; ++ uint bit = cmd_opcode % 8; ++ struct qla_hw_data *ha = vha->hw; ++ ++ if (!IS_QLA25XX(ha) && !IS_QLA2031(ha) && !IS_QLA27XX(ha)) ++ return QLA_SUCCESS; ++ ++ ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1197, ++ "Entered %s.\n", __func__); ++ ++ els_cmd_map = dma_alloc_coherent(&ha->pdev->dev, ELS_CMD_MAP_SIZE, ++ &els_cmd_map_dma, GFP_KERNEL); ++ if (!els_cmd_map) { ++ ql_log(ql_log_warn, vha, 0x7101, ++ "Failed to allocate RDP els command param.\n"); ++ return QLA_MEMORY_ALLOC_FAILED; ++ } ++ ++ memset(els_cmd_map, 0, ELS_CMD_MAP_SIZE); ++ ++ els_cmd_map[index] |= 1 << bit; ++ ++ mcp->mb[0] = MBC_SET_RNID_PARAMS; ++ mcp->mb[1] = RNID_TYPE_ELS_CMD << 8; ++ mcp->mb[2] = MSW(LSD(els_cmd_map_dma)); ++ mcp->mb[3] = LSW(LSD(els_cmd_map_dma)); ++ mcp->mb[6] = MSW(MSD(els_cmd_map_dma)); ++ mcp->mb[7] = LSW(MSD(els_cmd_map_dma)); ++ mcp->out_mb = MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0; ++ mcp->in_mb = MBX_1|MBX_0; ++ mcp->tov = MBX_TOV_SECONDS; ++ mcp->flags = MBX_DMA_OUT; ++ mcp->buf_size = ELS_CMD_MAP_SIZE; ++ rval = qla2x00_mailbox_command(vha, mcp); ++ ++ if (rval != QLA_SUCCESS) { ++ ql_dbg(ql_dbg_mbx, vha, 0x118d, ++ "Failed=%x (%x,%x).\n", rval, mcp->mb[0], mcp->mb[1]); ++ } else { ++ ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x118c, ++ "Done %s.\n", __func__); ++ } ++ ++ dma_free_coherent(&ha->pdev->dev, DMA_POOL_SIZE, ++ els_cmd_map, els_cmd_map_dma); ++ ++ return rval; ++} ++ ++int + qla24xx_get_buffer_credits(scsi_qla_host_t *vha, struct buffer_credit_24xx *bbc, + dma_addr_t bbc_dma) + { +--- a/drivers/scsi/qla2xxx/qla_os.c ++++ b/drivers/scsi/qla2xxx/qla_os.c +@@ -306,6 +306,15 @@ MODULE_PARM_DESC(ql2xdifbundlinginternal + "0 (Default). Based on check.\n" + "1 Force using internal buffers\n"); + ++int ql2xsmartsan; ++module_param(ql2xsmartsan, int, 0444); ++module_param_named(smartsan, ql2xsmartsan, int, 0444); ++MODULE_PARM_DESC(ql2xsmartsan, ++ "Send SmartSAN Management Attributes for FDMI Registration." ++ " Default is 0 - No SmartSAN registration," ++ " 1 - Register SmartSAN Management Attributes."); ++ ++ + static void qla2x00_clear_drv_active(struct qla_hw_data *); + static void qla2x00_free_device(scsi_qla_host_t *); + static int qla2xxx_map_queues(struct Scsi_Host *shost); +@@ -3275,6 +3284,11 @@ qla2x00_probe_one(struct pci_dev *pdev, + goto probe_failed; + } + ++ base_vha->purex_data = kzalloc(PUREX_ENTRY_SIZE, GFP_KERNEL); ++ if (!base_vha->purex_data) ++ ql_log(ql_log_warn, base_vha, 0x7118, ++ "Failed to allocate memory for PUREX data\n"); ++ + if (IS_QLAFX00(ha)) + host->can_queue = QLAFX00_MAX_CANQUEUE; + else +@@ -3465,6 +3479,7 @@ skip_dpc: + return 0; + + probe_failed: ++ kfree(base_vha->purex_data); + if (base_vha->gnl.l) { + dma_free_coherent(&ha->pdev->dev, base_vha->gnl.size, + base_vha->gnl.l, base_vha->gnl.ldma); +@@ -3781,6 +3796,8 @@ qla2x00_remove_one(struct pci_dev *pdev) + + qla84xx_put_chip(base_vha); + ++ kfree(base_vha->purex_data); ++ + /* Disable timer */ + if (base_vha->timer_active) + qla2x00_stop_timer(base_vha); +@@ -5746,6 +5763,518 @@ retry_lock: + return; + } + ++static uint ++qla25xx_rdp_port_speed_capability(struct qla_hw_data *ha) ++{ ++ if (IS_CNA_CAPABLE(ha)) ++ return RDP_PORT_SPEED_10GB; ++ ++ if (IS_QLA27XX(ha)) { ++ if (FW_ABILITY_MAX_SPEED(ha) == FW_ABILITY_MAX_SPEED_32G) ++ return RDP_PORT_SPEED_32GB|RDP_PORT_SPEED_16GB| ++ RDP_PORT_SPEED_8GB; ++ ++ return RDP_PORT_SPEED_16GB|RDP_PORT_SPEED_8GB| ++ RDP_PORT_SPEED_4GB; ++ } ++ ++ if (IS_QLA2031(ha)) ++ return RDP_PORT_SPEED_16GB|RDP_PORT_SPEED_8GB| ++ RDP_PORT_SPEED_4GB; ++ ++ if (IS_QLA25XX(ha)) ++ return RDP_PORT_SPEED_8GB|RDP_PORT_SPEED_4GB| ++ RDP_PORT_SPEED_2GB|RDP_PORT_SPEED_1GB; ++ ++ if (IS_QLA24XX_TYPE(ha)) ++ return RDP_PORT_SPEED_4GB|RDP_PORT_SPEED_2GB| ++ RDP_PORT_SPEED_1GB; ++ ++ if (IS_QLA23XX(ha)) ++ return RDP_PORT_SPEED_2GB|RDP_PORT_SPEED_1GB; ++ ++ return RDP_PORT_SPEED_1GB; ++} ++ ++static uint ++qla25xx_rdp_port_speed_currently(struct qla_hw_data *ha) ++{ ++ switch (ha->link_data_rate) { ++ case PORT_SPEED_1GB: ++ return RDP_PORT_SPEED_1GB; ++ ++ case PORT_SPEED_2GB: ++ return RDP_PORT_SPEED_2GB; ++ ++ case PORT_SPEED_4GB: ++ return RDP_PORT_SPEED_4GB; ++ ++ case PORT_SPEED_8GB: ++ return RDP_PORT_SPEED_8GB; ++ ++ case PORT_SPEED_10GB: ++ return RDP_PORT_SPEED_10GB; ++ ++ case PORT_SPEED_16GB: ++ return RDP_PORT_SPEED_16GB; ++ ++ case PORT_SPEED_32GB: ++ return RDP_PORT_SPEED_32GB; ++ ++ default: ++ return RDP_PORT_SPEED_UNKNOWN; ++ } ++} ++ ++/* ++ * Function Name: qla24xx_process_purex_iocb ++ * ++ * Description: ++ * Prepare a RDP response and send to Fabric switch ++ * ++ * PARAMETERS: ++ * vha: SCSI qla host ++ * purex: RDP request received by HBA ++ */ ++static int qla24xx_process_purex_iocb(struct scsi_qla_host *vha, void *pkt) ++{ ++ struct qla_hw_data *ha = vha->hw; ++ struct purex_entry_24xx *purex = pkt; ++ struct port_database_24xx *pdb = NULL; ++ dma_addr_t rsp_els_dma; ++ dma_addr_t rsp_payload_dma; ++ dma_addr_t stat_dma; ++ dma_addr_t bbc_dma; ++ dma_addr_t sfp_dma; ++ struct els_entry_24xx *rsp_els = NULL; ++ struct rdp_rsp_payload *rsp_payload = NULL; ++ struct link_statistics *stat = NULL; ++ struct buffer_credit_24xx *bbc = NULL; ++ uint8_t *sfp = NULL; ++ uint16_t sfp_flags = 0; ++ int rval = -ENOMEM; ++ ++ ql_dbg(ql_dbg_init + ql_dbg_verbose, vha, 0x0180, ++ "%s: Enter\n", __func__); ++ ++ ql_dbg(ql_dbg_init + ql_dbg_verbose, vha, 0x0181, ++ "-------- ELS REQ -------\n"); ++ ql_dump_buffer(ql_dbg_init + ql_dbg_verbose, vha, 0x0182, ++ (void *)purex, sizeof(*purex)); ++ ++ rsp_els = dma_alloc_coherent(&ha->pdev->dev, sizeof(*rsp_els), ++ &rsp_els_dma, GFP_KERNEL); ++ if (!rsp_els) ++ goto dealloc; ++ ++ rsp_payload = dma_alloc_coherent(&ha->pdev->dev, sizeof(*rsp_payload), ++ &rsp_payload_dma, GFP_KERNEL); ++ if (!rsp_payload) ++ goto dealloc; ++ ++ sfp = dma_alloc_coherent(&ha->pdev->dev, SFP_RTDI_LEN, ++ &sfp_dma, GFP_KERNEL); ++ ++ stat = dma_alloc_coherent(&ha->pdev->dev, sizeof(*stat), ++ &stat_dma, GFP_KERNEL); ++ ++ bbc = dma_alloc_coherent(&ha->pdev->dev, sizeof(*bbc), ++ &bbc_dma, GFP_KERNEL); ++ ++ /* Prepare Response IOCB */ ++ memset(rsp_els, 0, sizeof(*rsp_els)); ++ rsp_els->entry_type = ELS_IOCB_TYPE; ++ rsp_els->entry_count = 1; ++ rsp_els->sys_define = 0; ++ rsp_els->entry_status = 0; ++ rsp_els->handle = 0; ++ rsp_els->nport_handle = purex->nport_handle; ++ rsp_els->tx_dsd_count = 1; ++ rsp_els->vp_index = purex->vp_idx; ++ rsp_els->sof_type = EST_SOFI3; ++ rsp_els->rx_xchg_address = purex->rx_xchg_addr; ++ rsp_els->rx_dsd_count = 0; ++ rsp_els->opcode = purex->els_frame_payload[0]; ++ ++ rsp_els->port_id[0] = purex->s_id[0]; ++ rsp_els->port_id[1] = purex->s_id[1]; ++ rsp_els->port_id[2] = purex->s_id[2]; ++ ++ rsp_els->control_flags = EPD_ELS_ACC; ++ rsp_els->rx_byte_count = 0; ++ rsp_els->tx_byte_count = cpu_to_le32(sizeof(*rsp_payload)); ++ ++ put_unaligned_le64(rsp_payload_dma, &rsp_els->tx_address); ++ rsp_els->tx_len = rsp_els->tx_byte_count; ++ ++ rsp_els->rx_address = 0; ++ rsp_els->rx_len = 0; ++ ++ if (sizeof(*rsp_payload) <= 0x100) ++ goto accept; ++ ++ pdb = kzalloc(sizeof(*pdb), GFP_KERNEL); ++ if (!pdb) ++ goto reduce; ++ ++ rval = qla24xx_get_port_database(vha, purex->nport_handle, pdb); ++ if (rval) ++ goto reduce; ++ ++ if (pdb->port_id[0] != purex->s_id[2] || ++ pdb->port_id[1] != purex->s_id[1] || ++ pdb->port_id[2] != purex->s_id[0]) ++ goto reduce; ++ ++ if (pdb->current_login_state == PDS_PLOGI_COMPLETE || ++ pdb->current_login_state == PDS_PRLI_COMPLETE) ++ goto accept; ++ ++reduce: ++ ql_dbg(ql_dbg_init, vha, 0x016e, "Requesting port is not logged in.\n"); ++ rsp_els->tx_byte_count = rsp_els->tx_len = ++ offsetof(struct rdp_rsp_payload, buffer_credit_desc); ++ ql_dbg(ql_dbg_init, vha, 0x016f, "Reduced response payload size %u.\n", ++ rsp_els->tx_byte_count); ++ ++accept: ++ /* Prepare Response Payload */ ++ rsp_payload->hdr.cmd = cpu_to_be32(0x2 << 24); /* LS_ACC */ ++ rsp_payload->hdr.len = cpu_to_be32( ++ rsp_els->tx_byte_count - sizeof(rsp_payload->hdr)); ++ ++ /* Link service Request Info Descriptor */ ++ rsp_payload->ls_req_info_desc.desc_tag = cpu_to_be32(0x1); ++ rsp_payload->ls_req_info_desc.desc_len = ++ cpu_to_be32(RDP_DESC_LEN(rsp_payload->ls_req_info_desc)); ++ rsp_payload->ls_req_info_desc.req_payload_word_0 = ++ cpu_to_be32p((uint32_t *)purex->els_frame_payload); ++ ++ /* Link service Request Info Descriptor 2 */ ++ rsp_payload->ls_req_info_desc2.desc_tag = cpu_to_be32(0x1); ++ rsp_payload->ls_req_info_desc2.desc_len = ++ cpu_to_be32(RDP_DESC_LEN(rsp_payload->ls_req_info_desc2)); ++ rsp_payload->ls_req_info_desc2.req_payload_word_0 = ++ cpu_to_be32p((uint32_t *)purex->els_frame_payload); ++ ++ if (sfp) { ++ /* SFP Flags */ ++ memset(sfp, 0, SFP_RTDI_LEN); ++ rval = qla2x00_read_sfp(vha, sfp_dma, sfp, 0xa0, 0x7, 2, 0); ++ if (!rval) { ++ /* SFP Flags bits 3-0: Port Tx Laser Type */ ++ if (sfp[0] & BIT_2 || sfp[1] & (BIT_6|BIT_5)) ++ sfp_flags |= BIT_0; /* short wave */ ++ else if (sfp[0] & BIT_1) ++ sfp_flags |= BIT_1; /* long wave 1310nm */ ++ else if (sfp[1] & BIT_4) ++ sfp_flags |= BIT_1|BIT_0; /* long wave 1550nm */ ++ } ++ ++ /* SFP Type */ ++ memset(sfp, 0, SFP_RTDI_LEN); ++ rval = qla2x00_read_sfp(vha, sfp_dma, sfp, 0xa0, 0x0, 1, 0); ++ if (!rval) { ++ sfp_flags |= BIT_4; /* optical */ ++ if (sfp[0] == 0x3) ++ sfp_flags |= BIT_6; /* sfp+ */ ++ } ++ ++ /* SFP Diagnostics */ ++ memset(sfp, 0, SFP_RTDI_LEN); ++ rval = qla2x00_read_sfp(vha, sfp_dma, sfp, 0xa2, 0x60, 10, 0); ++ if (!rval && sfp_flags) { ++ uint16_t *trx = (void *)sfp; /* already be16 */ ++ ++ rsp_payload->sfp_diag_desc.desc_tag = ++ cpu_to_be32(0x10000); ++ rsp_payload->sfp_diag_desc.desc_len = ++ cpu_to_be32(RDP_DESC_LEN(rsp_payload->sfp_diag_desc)); ++ rsp_payload->sfp_diag_desc.temperature = trx[0]; ++ rsp_payload->sfp_diag_desc.vcc = trx[1]; ++ rsp_payload->sfp_diag_desc.tx_bias = trx[2]; ++ rsp_payload->sfp_diag_desc.tx_power = trx[3]; ++ rsp_payload->sfp_diag_desc.rx_power = trx[4]; ++ rsp_payload->sfp_diag_desc.sfp_flags = ++ cpu_to_be16(sfp_flags); ++ } ++ } ++ ++ /* Port Speed Descriptor */ ++ rsp_payload->port_speed_desc.desc_tag = cpu_to_be32(0x10001); ++ rsp_payload->port_speed_desc.desc_len = ++ cpu_to_be32(RDP_DESC_LEN(rsp_payload->port_speed_desc)); ++ rsp_payload->port_speed_desc.speed_capab = cpu_to_be16( ++ qla25xx_rdp_port_speed_capability(ha)); ++ rsp_payload->port_speed_desc.operating_speed = cpu_to_be16( ++ qla25xx_rdp_port_speed_currently(ha)); ++ ++ if (stat) { ++ rval = qla24xx_get_isp_stats(vha, stat, stat_dma, 0); ++ if (!rval) { ++ /* Link Error Status Descriptor */ ++ rsp_payload->ls_err_desc.desc_tag = ++ cpu_to_be32(0x10002); ++ rsp_payload->ls_err_desc.desc_len = ++ cpu_to_be32(RDP_DESC_LEN(rsp_payload->ls_err_desc)); ++ rsp_payload->ls_err_desc.link_fail_cnt = ++ cpu_to_be32(stat->link_fail_cnt); ++ rsp_payload->ls_err_desc.loss_sync_cnt = ++ cpu_to_be32(stat->loss_sync_cnt); ++ rsp_payload->ls_err_desc.loss_sig_cnt = ++ cpu_to_be32(stat->loss_sig_cnt); ++ rsp_payload->ls_err_desc.prim_seq_err_cnt = ++ cpu_to_be32(stat->prim_seq_err_cnt); ++ rsp_payload->ls_err_desc.inval_xmit_word_cnt = ++ cpu_to_be32(stat->inval_xmit_word_cnt); ++ rsp_payload->ls_err_desc.inval_crc_cnt = ++ cpu_to_be32(stat->inval_crc_cnt); ++ rsp_payload->ls_err_desc.pn_port_phy_type |= BIT_6; ++ } ++ } ++ ++ /* Portname Descriptor */ ++ rsp_payload->port_name_diag_desc.desc_tag = cpu_to_be32(0x10003); ++ rsp_payload->port_name_diag_desc.desc_len = ++ cpu_to_be32(RDP_DESC_LEN(rsp_payload->port_name_diag_desc)); ++ memcpy(rsp_payload->port_name_diag_desc.WWNN, ++ vha->node_name, ++ sizeof(rsp_payload->port_name_diag_desc.WWNN)); ++ memcpy(rsp_payload->port_name_diag_desc.WWPN, ++ vha->port_name, ++ sizeof(rsp_payload->port_name_diag_desc.WWPN)); ++ ++ /* F-Port Portname Descriptor */ ++ rsp_payload->port_name_direct_desc.desc_tag = cpu_to_be32(0x10003); ++ rsp_payload->port_name_direct_desc.desc_len = ++ cpu_to_be32(RDP_DESC_LEN(rsp_payload->port_name_direct_desc)); ++ memcpy(rsp_payload->port_name_direct_desc.WWNN, ++ vha->fabric_node_name, ++ sizeof(rsp_payload->port_name_direct_desc.WWNN)); ++ memcpy(rsp_payload->port_name_direct_desc.WWPN, ++ vha->fabric_port_name, ++ sizeof(rsp_payload->port_name_direct_desc.WWPN)); ++ ++ if (rsp_els->tx_byte_count < sizeof(*rsp_payload)) ++ goto send; ++ ++ if (bbc) { ++ memset(bbc, 0, sizeof(*bbc)); ++ rval = qla24xx_get_buffer_credits(vha, bbc, bbc_dma); ++ if (!rval) { ++ /* Bufer Credit Descriptor */ ++ rsp_payload->buffer_credit_desc.desc_tag = ++ cpu_to_be32(0x10006); ++ rsp_payload->buffer_credit_desc.desc_len = ++ cpu_to_be32(RDP_DESC_LEN( ++ rsp_payload->buffer_credit_desc)); ++ rsp_payload->buffer_credit_desc.fcport_b2b = ++ cpu_to_be32(LSW(bbc->parameter[0])); ++ rsp_payload->buffer_credit_desc.attached_fcport_b2b = ++ cpu_to_be32(0); ++ rsp_payload->buffer_credit_desc.fcport_rtt = ++ cpu_to_be32(0); ++ } ++ } ++ ++ if (sfp) { ++ memset(sfp, 0, SFP_RTDI_LEN); ++ rval = qla2x00_read_sfp(vha, sfp_dma, sfp, 0xa2, 0, 64, 0); ++ if (!rval) { ++ uint16_t *trx = (void *)sfp; /* already be16 */ ++ ++ /* Optical Element Descriptor, Temperature */ ++ rsp_payload->optical_elmt_desc[0].desc_tag = ++ cpu_to_be32(0x10007); ++ rsp_payload->optical_elmt_desc[0].desc_len = ++ cpu_to_be32(RDP_DESC_LEN( ++ *rsp_payload->optical_elmt_desc)); ++ rsp_payload->optical_elmt_desc[0].high_alarm = trx[0]; ++ rsp_payload->optical_elmt_desc[0].low_alarm = trx[1]; ++ rsp_payload->optical_elmt_desc[0].high_warn = trx[2]; ++ rsp_payload->optical_elmt_desc[0].low_warn = trx[3]; ++ rsp_payload->optical_elmt_desc[0].element_flags = ++ cpu_to_be32(1 << 28); ++ ++ /* Optical Element Descriptor, Voltage */ ++ rsp_payload->optical_elmt_desc[1].desc_tag = ++ cpu_to_be32(0x10007); ++ rsp_payload->optical_elmt_desc[1].desc_len = ++ cpu_to_be32(RDP_DESC_LEN( ++ *rsp_payload->optical_elmt_desc)); ++ rsp_payload->optical_elmt_desc[1].high_alarm = trx[4]; ++ rsp_payload->optical_elmt_desc[1].low_alarm = trx[5]; ++ rsp_payload->optical_elmt_desc[1].high_warn = trx[6]; ++ rsp_payload->optical_elmt_desc[1].low_warn = trx[7]; ++ rsp_payload->optical_elmt_desc[1].element_flags = ++ cpu_to_be32(2 << 28); ++ ++ /* Optical Element Descriptor, Tx Bias Current */ ++ rsp_payload->optical_elmt_desc[2].desc_tag = ++ cpu_to_be32(0x10007); ++ rsp_payload->optical_elmt_desc[2].desc_len = ++ cpu_to_be32(RDP_DESC_LEN( ++ *rsp_payload->optical_elmt_desc)); ++ rsp_payload->optical_elmt_desc[2].high_alarm = trx[8]; ++ rsp_payload->optical_elmt_desc[2].low_alarm = trx[9]; ++ rsp_payload->optical_elmt_desc[2].high_warn = trx[10]; ++ rsp_payload->optical_elmt_desc[2].low_warn = trx[11]; ++ rsp_payload->optical_elmt_desc[2].element_flags = ++ cpu_to_be32(3 << 28); ++ ++ /* Optical Element Descriptor, Tx Power */ ++ rsp_payload->optical_elmt_desc[3].desc_tag = ++ cpu_to_be32(0x10007); ++ rsp_payload->optical_elmt_desc[3].desc_len = ++ cpu_to_be32(RDP_DESC_LEN( ++ *rsp_payload->optical_elmt_desc)); ++ rsp_payload->optical_elmt_desc[3].high_alarm = trx[12]; ++ rsp_payload->optical_elmt_desc[3].low_alarm = trx[13]; ++ rsp_payload->optical_elmt_desc[3].high_warn = trx[14]; ++ rsp_payload->optical_elmt_desc[3].low_warn = trx[15]; ++ rsp_payload->optical_elmt_desc[3].element_flags = ++ cpu_to_be32(4 << 28); ++ ++ /* Optical Element Descriptor, Rx Power */ ++ rsp_payload->optical_elmt_desc[4].desc_tag = ++ cpu_to_be32(0x10007); ++ rsp_payload->optical_elmt_desc[4].desc_len = ++ cpu_to_be32(RDP_DESC_LEN( ++ *rsp_payload->optical_elmt_desc)); ++ rsp_payload->optical_elmt_desc[4].high_alarm = trx[16]; ++ rsp_payload->optical_elmt_desc[4].low_alarm = trx[17]; ++ rsp_payload->optical_elmt_desc[4].high_warn = trx[18]; ++ rsp_payload->optical_elmt_desc[4].low_warn = trx[19]; ++ rsp_payload->optical_elmt_desc[4].element_flags = ++ cpu_to_be32(5 << 28); ++ } ++ ++ memset(sfp, 0, SFP_RTDI_LEN); ++ rval = qla2x00_read_sfp(vha, sfp_dma, sfp, 0xa2, 112, 64, 0); ++ if (!rval) { ++ /* Temperature high/low alarm/warning */ ++ rsp_payload->optical_elmt_desc[0].element_flags |= ++ cpu_to_be32( ++ (sfp[0] >> 7 & 1) << 3 | ++ (sfp[0] >> 6 & 1) << 2 | ++ (sfp[4] >> 7 & 1) << 1 | ++ (sfp[4] >> 6 & 1) << 0); ++ ++ /* Voltage high/low alarm/warning */ ++ rsp_payload->optical_elmt_desc[1].element_flags |= ++ cpu_to_be32( ++ (sfp[0] >> 5 & 1) << 3 | ++ (sfp[0] >> 4 & 1) << 2 | ++ (sfp[4] >> 5 & 1) << 1 | ++ (sfp[4] >> 4 & 1) << 0); ++ ++ /* Tx Bias Current high/low alarm/warning */ ++ rsp_payload->optical_elmt_desc[2].element_flags |= ++ cpu_to_be32( ++ (sfp[0] >> 3 & 1) << 3 | ++ (sfp[0] >> 2 & 1) << 2 | ++ (sfp[4] >> 3 & 1) << 1 | ++ (sfp[4] >> 2 & 1) << 0); ++ ++ /* Tx Power high/low alarm/warning */ ++ rsp_payload->optical_elmt_desc[3].element_flags |= ++ cpu_to_be32( ++ (sfp[0] >> 1 & 1) << 3 | ++ (sfp[0] >> 0 & 1) << 2 | ++ (sfp[4] >> 1 & 1) << 1 | ++ (sfp[4] >> 0 & 1) << 0); ++ ++ /* Rx Power high/low alarm/warning */ ++ rsp_payload->optical_elmt_desc[4].element_flags |= ++ cpu_to_be32( ++ (sfp[1] >> 7 & 1) << 3 | ++ (sfp[1] >> 6 & 1) << 2 | ++ (sfp[5] >> 7 & 1) << 1 | ++ (sfp[5] >> 6 & 1) << 0); ++ } ++ } ++ ++ if (sfp) { ++ memset(sfp, 0, SFP_RTDI_LEN); ++ rval = qla2x00_read_sfp(vha, sfp_dma, sfp, 0xa0, 20, 64, 0); ++ if (!rval) { ++ /* Optical Product Data Descriptor */ ++ rsp_payload->optical_prod_desc.desc_tag = ++ cpu_to_be32(0x10008); ++ rsp_payload->optical_prod_desc.desc_len = ++ cpu_to_be32(RDP_DESC_LEN( ++ rsp_payload->optical_prod_desc)); ++ memcpy(rsp_payload->optical_prod_desc.vendor_name, ++ sfp + 0, ++ sizeof(rsp_payload->optical_prod_desc.vendor_name)); ++ memcpy(rsp_payload->optical_prod_desc.part_number, ++ sfp + 20, ++ sizeof(rsp_payload->optical_prod_desc.part_number)); ++ memcpy(rsp_payload->optical_prod_desc.revision, ++ sfp + 36, ++ sizeof(rsp_payload->optical_prod_desc.revision)); ++ memcpy(rsp_payload->optical_prod_desc.serial_number, ++ sfp + 48, ++ sizeof(rsp_payload->optical_prod_desc.serial_number)); ++ } ++ ++ memset(sfp, 0, SFP_RTDI_LEN); ++ rval = qla2x00_read_sfp(vha, sfp_dma, sfp, 0xa0, 84, 8, 0); ++ if (!rval) { ++ memcpy(rsp_payload->optical_prod_desc.date, ++ sfp + 0, ++ sizeof(rsp_payload->optical_prod_desc.date)); ++ } ++ } ++ ++send: ++ ql_dbg(ql_dbg_init, vha, 0x0183, ++ "Sending ELS Response to RDP Request...\n"); ++ ql_dbg(ql_dbg_init + ql_dbg_verbose, vha, 0x0184, ++ "-------- ELS RSP -------\n"); ++ ql_dump_buffer(ql_dbg_init + ql_dbg_verbose, vha, 0x0185, ++ (void *)rsp_els, sizeof(*rsp_els)); ++ ql_dbg(ql_dbg_init + ql_dbg_verbose, vha, 0x0186, ++ "-------- ELS RSP PAYLOAD -------\n"); ++ ql_dump_buffer(ql_dbg_init + ql_dbg_verbose, vha, 0x0187, ++ (void *)rsp_payload, rsp_els->tx_byte_count); ++ ++ rval = qla2x00_issue_iocb(vha, rsp_els, rsp_els_dma, 0); ++ ++ if (rval != QLA_SUCCESS) { ++ ql_log(ql_log_warn, vha, 0x0188, ++ "%s: failed to issue IOCB (%x).\n", __func__, rval); ++ } else if (rsp_els->entry_status != 0) { ++ ql_log(ql_log_warn, vha, 0x0189, ++ "%s: failed to complete IOCB -- error status (%x).\n", ++ __func__, rsp_els->entry_status); ++ rval = QLA_FUNCTION_FAILED; ++ } else { ++ ql_dbg(ql_dbg_init, vha, 0x018a, "%s: done.\n", __func__); ++ } ++ ++dealloc: ++ kfree(pdb); ++ ++ if (bbc) ++ dma_free_coherent(&ha->pdev->dev, sizeof(*bbc), ++ bbc, bbc_dma); ++ if (stat) ++ dma_free_coherent(&ha->pdev->dev, sizeof(*stat), ++ stat, stat_dma); ++ if (sfp) ++ dma_free_coherent(&ha->pdev->dev, SFP_RTDI_LEN, ++ sfp, sfp_dma); ++ if (rsp_payload) ++ dma_free_coherent(&ha->pdev->dev, sizeof(*rsp_payload), ++ rsp_payload, rsp_payload_dma); ++ if (rsp_els) ++ dma_free_coherent(&ha->pdev->dev, sizeof(*rsp_els), ++ rsp_els, rsp_els_dma); ++ ++ return rval; ++} ++ + void + qla83xx_idc_unlock(scsi_qla_host_t *base_vha, uint16_t requester_id) + { +@@ -6093,6 +6622,8 @@ qla2x00_disable_board_on_pci_error(struc + + base_vha->flags.online = 0; + ++ kfree(base_vha->purex_data); ++ + qla2x00_destroy_deferred_work(ha); + + /* +@@ -6316,6 +6847,13 @@ qla2x00_do_dpc(void *data) + } + } + ++ if (test_bit(PROCESS_PUREX_IOCB, &base_vha->dpc_flags) && ++ (atomic_read(&base_vha->loop_state) == LOOP_READY)) { ++ qla24xx_process_purex_iocb(base_vha, ++ base_vha->purex_data); ++ clear_bit(PROCESS_PUREX_IOCB, &base_vha->dpc_flags); ++ } ++ + if (test_and_clear_bit(FCPORT_UPDATE_NEEDED, + &base_vha->dpc_flags)) { + qla2x00_update_fcports(base_vha); +@@ -6706,7 +7244,8 @@ qla2x00_timer(scsi_qla_host_t *vha) + test_bit(ISP_UNRECOVERABLE, &vha->dpc_flags) || + test_bit(FCOE_CTX_RESET_NEEDED, &vha->dpc_flags) || + test_bit(VP_DPC_NEEDED, &vha->dpc_flags) || +- test_bit(RELOGIN_NEEDED, &vha->dpc_flags))) { ++ test_bit(RELOGIN_NEEDED, &vha->dpc_flags) || ++ test_bit(PROCESS_PUREX_IOCB, &vha->dpc_flags))) { + ql_dbg(ql_dbg_timer, vha, 0x600b, + "isp_abort_needed=%d loop_resync_needed=%d " + "fcport_update_needed=%d start_dpc=%d " +@@ -6719,12 +7258,13 @@ qla2x00_timer(scsi_qla_host_t *vha) + ql_dbg(ql_dbg_timer, vha, 0x600c, + "beacon_blink_needed=%d isp_unrecoverable=%d " + "fcoe_ctx_reset_needed=%d vp_dpc_needed=%d " +- "relogin_needed=%d.\n", ++ "relogin_needed=%d, Process_purex_iocb=%d.\n", + test_bit(BEACON_BLINK_NEEDED, &vha->dpc_flags), + test_bit(ISP_UNRECOVERABLE, &vha->dpc_flags), + test_bit(FCOE_CTX_RESET_NEEDED, &vha->dpc_flags), + test_bit(VP_DPC_NEEDED, &vha->dpc_flags), +- test_bit(RELOGIN_NEEDED, &vha->dpc_flags)); ++ test_bit(RELOGIN_NEEDED, &vha->dpc_flags), ++ test_bit(PROCESS_PUREX_IOCB, &vha->dpc_flags)); + qla2xxx_wake_dpc(vha); + } + diff --git a/patches.suse/scsi-qla2xxx-Avoid-setting-firmware-options-twice-in.patch b/patches.suse/scsi-qla2xxx-Avoid-setting-firmware-options-twice-in.patch new file mode 100644 index 0000000..b04a92d --- /dev/null +++ b/patches.suse/scsi-qla2xxx-Avoid-setting-firmware-options-twice-in.patch @@ -0,0 +1,54 @@ +From: Giridhar Malavali +Date: Wed, 26 Feb 2020 14:40:06 -0800 +Subject: scsi: qla2xxx: Avoid setting firmware options twice in + 24xx_update_fw_options. +Patch-mainline: v5.7-rc1 +Git-commit: 9ef4847a80d317e4033c2ecf0e73e54c5fd4771d +References: bsc#1157424 + +This patch moves ql2xrdpenable check earlier to avoids setting +fw_option once again before exiting qla24xx_update_fw_options. + +Link: https://lore.kernel.org/r/20200226224022.24518-3-hmadhani@marvell.com +Signed-off-by: Himanshu Madhani +Signed-off-by: Giridhar Malavali +Signed-off-by: Martin K. Petersen +Acked-by: Daniel Wagner +--- + drivers/scsi/qla2xxx/qla_init.c | 11 ++++------- + 1 file changed, 4 insertions(+), 7 deletions(-) + +--- a/drivers/scsi/qla2xxx/qla_init.c ++++ b/drivers/scsi/qla2xxx/qla_init.c +@@ -3929,6 +3929,9 @@ qla24xx_update_fw_options(scsi_qla_host_ + ha->fw_options[2] &= ~BIT_8; + } + ++ if (ql2xrdpenable) ++ ha->fw_options[1] |= ADD_FO1_ENABLE_PUREX_IOCB; ++ + ql_dbg(ql_dbg_init, vha, 0x00e8, + "%s, add FW options 1-3 = 0x%04x 0x%04x 0x%04x mode %x\n", + __func__, ha->fw_options[1], ha->fw_options[2], +@@ -3939,7 +3942,7 @@ qla24xx_update_fw_options(scsi_qla_host_ + + /* Update Serial Link options. */ + if ((le16_to_cpu(ha->fw_seriallink_options24[0]) & BIT_0) == 0) +- goto enable_purex; ++ return; + + rval = qla2x00_set_serdes_params(vha, + le16_to_cpu(ha->fw_seriallink_options24[1]), +@@ -3949,12 +3952,6 @@ qla24xx_update_fw_options(scsi_qla_host_ + ql_log(ql_log_warn, vha, 0x0104, + "Unable to update Serial Link options (%x).\n", rval); + } +- +-enable_purex: +- if (ql2xrdpenable) +- ha->fw_options[1] |= ADD_FO1_ENABLE_PUREX_IOCB; +- +- qla2x00_set_fw_options(vha, ha->fw_options); + } + + void diff --git a/patches.suse/scsi-qla2xxx-Check-locking-assumptions-at-runtime-in.patch b/patches.suse/scsi-qla2xxx-Check-locking-assumptions-at-runtime-in.patch new file mode 100644 index 0000000..520a6d8 --- /dev/null +++ b/patches.suse/scsi-qla2xxx-Check-locking-assumptions-at-runtime-in.patch @@ -0,0 +1,35 @@ +From: Bart Van Assche +Date: Wed, 22 Jan 2020 20:23:40 -0800 +Subject: scsi: qla2xxx: Check locking assumptions at runtime in + qla2x00_abort_srb() +Patch-mainline: v5.7-rc1 +Git-commit: 2494c2868d6e0eaaefd42f4fd2d260a8c35d240d +References: bsc#1157424 + +Document the locking assumptions this function relies on and also verify +these locking assumptions at runtime. + +Cc: Quinn Tran +Cc: Daniel Wagner +Link: https://lore.kernel.org/r/20200123042345.23886-2-bvanassche@acm.org +Acked-by: Himanshu Madhani +Reviewed-by: Martin Wilck +Reviewed-by: Roman Bolshakov +Signed-off-by: Bart Van Assche +Signed-off-by: Martin K. Petersen +Acked-by: Daniel Wagner +--- + drivers/scsi/qla2xxx/qla_os.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/drivers/scsi/qla2xxx/qla_os.c ++++ b/drivers/scsi/qla2xxx/qla_os.c +@@ -1706,6 +1706,8 @@ static void qla2x00_abort_srb(struct qla + bool ret_cmd; + uint32_t ratov_j; + ++ lockdep_assert_held(qp->qp_lock_ptr); ++ + if (qla2x00_chip_is_down(vha)) { + sp->done(sp, res); + return; diff --git a/patches.suse/scsi-qla2xxx-Cleanup-ELS-PUREX-iocb-fields.patch b/patches.suse/scsi-qla2xxx-Cleanup-ELS-PUREX-iocb-fields.patch new file mode 100644 index 0000000..2fb7baf --- /dev/null +++ b/patches.suse/scsi-qla2xxx-Cleanup-ELS-PUREX-iocb-fields.patch @@ -0,0 +1,193 @@ +From: Joe Carnuccio +Date: Wed, 12 Feb 2020 13:44:23 -0800 +Subject: scsi: qla2xxx: Cleanup ELS/PUREX iocb fields +Patch-mainline: v5.7-rc1 +Git-commit: 09e382bc3dd946cfee74044d18d1886567874300 +References: bsc#1157424 + +This patch does the following to improve RDP processing: + + - Rename field port_id to d_id in ELS and PUREX iocb structs to match FW + spec. + + - Remove redundant comments from ELS and PUREX iocb structs. + + - Refactor fields in ELS iocb struct for error subcode common access. + + - Properly use error subcode fields in rdp processing routine. + + - Add print logs for alloc failure in purex rdp processing routine. + +Link: https://lore.kernel.org/r/20200212214436.25532-13-hmadhani@marvell.com +Signed-off-by: Joe Carnuccio +Signed-off-by: Himanshu Madhani +Signed-off-by: Martin K. Petersen +Acked-by: Daniel Wagner +--- + drivers/scsi/qla2xxx/qla_fw.h | 41 +++++++++++++++++++++++++--------------- + drivers/scsi/qla2xxx/qla_iocb.c | 12 +++++------ + drivers/scsi/qla2xxx/qla_os.c | 28 ++++++++++++++++----------- + 3 files changed, 49 insertions(+), 32 deletions(-) + +--- a/drivers/scsi/qla2xxx/qla_fw.h ++++ b/drivers/scsi/qla2xxx/qla_fw.h +@@ -779,9 +779,8 @@ struct els_entry_24xx { + + uint32_t handle; /* System handle. */ + +- uint16_t reserved_1; +- +- uint16_t nport_handle; /* N_PORT handle. */ ++ uint16_t comp_status; /* response only */ ++ uint16_t nport_handle; + + uint16_t tx_dsd_count; + +@@ -796,7 +795,7 @@ struct els_entry_24xx { + uint8_t opcode; + uint8_t reserved_2; + +- uint8_t port_id[3]; ++ uint8_t d_id[3]; + uint8_t s_id[3]; + + uint16_t control_flags; /* Control flags. */ +@@ -808,13 +807,24 @@ struct els_entry_24xx { + #define ECF_CLR_PASSTHRU_PEND BIT_12 + #define ECF_INCL_FRAME_HDR BIT_11 + +- __le32 rx_byte_count; +- __le32 tx_byte_count; +- +- __le64 tx_address __packed; /* Data segment 0 address. */ +- __le32 tx_len; /* Data segment 0 length. */ +- __le64 rx_address __packed; /* Data segment 1 address. */ +- __le32 rx_len; /* Data segment 1 length. */ ++ union { ++ struct { ++ __le32 rx_byte_count; ++ __le32 tx_byte_count; ++ ++ __le64 tx_address __packed; /* DSD 0 address. */ ++ __le32 tx_len; /* DSD 0 length. */ ++ ++ __le64 rx_address __packed; /* DSD 1 address. */ ++ __le32 rx_len; /* DSD 1 length. */ ++ }; ++ struct { ++ uint32_t total_byte_count; ++ uint32_t error_subcode_1; ++ uint32_t error_subcode_2; ++ uint32_t error_subcode_3; ++ }; ++ }; + }; + + struct els_sts_entry_24xx { +@@ -840,15 +850,16 @@ struct els_sts_entry_24xx { + uint8_t opcode; + uint8_t reserved_3; + +- uint8_t port_id[3]; +- uint8_t reserved_4; +- +- uint16_t reserved_5; ++ uint8_t d_id[3]; ++ uint8_t s_id[3]; + + uint16_t control_flags; /* Control flags. */ + uint32_t total_byte_count; + uint32_t error_subcode_1; + uint32_t error_subcode_2; ++ uint32_t error_subcode_3; ++ ++ uint32_t reserved_4[4]; + }; + /* + * ISP queue - Mailbox Command entry structure definition. +--- a/drivers/scsi/qla2xxx/qla_iocb.c ++++ b/drivers/scsi/qla2xxx/qla_iocb.c +@@ -2686,9 +2686,9 @@ qla24xx_els_logo_iocb(srb_t *sp, struct + els_iocb->rx_dsd_count = 0; + els_iocb->opcode = elsio->u.els_logo.els_cmd; + +- els_iocb->port_id[0] = sp->fcport->d_id.b.al_pa; +- els_iocb->port_id[1] = sp->fcport->d_id.b.area; +- els_iocb->port_id[2] = sp->fcport->d_id.b.domain; ++ els_iocb->d_id[0] = sp->fcport->d_id.b.al_pa; ++ els_iocb->d_id[1] = sp->fcport->d_id.b.area; ++ els_iocb->d_id[2] = sp->fcport->d_id.b.domain; + /* For SID the byte order is different than DID */ + els_iocb->s_id[1] = vha->d_id.b.al_pa; + els_iocb->s_id[2] = vha->d_id.b.area; +@@ -3032,9 +3032,9 @@ qla24xx_els_iocb(srb_t *sp, struct els_e + sp->type == SRB_ELS_CMD_RPT ? + bsg_request->rqst_data.r_els.els_code : + bsg_request->rqst_data.h_els.command_code; +- els_iocb->port_id[0] = sp->fcport->d_id.b.al_pa; +- els_iocb->port_id[1] = sp->fcport->d_id.b.area; +- els_iocb->port_id[2] = sp->fcport->d_id.b.domain; ++ els_iocb->d_id[0] = sp->fcport->d_id.b.al_pa; ++ els_iocb->d_id[1] = sp->fcport->d_id.b.area; ++ els_iocb->d_id[2] = sp->fcport->d_id.b.domain; + els_iocb->control_flags = 0; + els_iocb->rx_byte_count = + cpu_to_le32(bsg_job->reply_payload.payload_len); +--- a/drivers/scsi/qla2xxx/qla_os.c ++++ b/drivers/scsi/qla2xxx/qla_os.c +@@ -5901,13 +5901,19 @@ static int qla24xx_process_purex_iocb(st + + rsp_els = dma_alloc_coherent(&ha->pdev->dev, sizeof(*rsp_els), + &rsp_els_dma, GFP_KERNEL); +- if (!rsp_els) ++ if (!rsp_els) { ++ ql_log(ql_log_warn, vha, 0x0183, ++ "Failed allocate dma buffer ELS RSP.\n"); + goto dealloc; ++ } + + rsp_payload = dma_alloc_coherent(&ha->pdev->dev, sizeof(*rsp_payload), + &rsp_payload_dma, GFP_KERNEL); +- if (!rsp_payload) ++ if (!rsp_payload) { ++ ql_log(ql_log_warn, vha, 0x0184, ++ "Failed allocate dma buffer ELS RSP payload.\n"); + goto dealloc; ++ } + + sfp = dma_alloc_coherent(&ha->pdev->dev, SFP_RTDI_LEN, + &sfp_dma, GFP_KERNEL); +@@ -5933,9 +5939,9 @@ static int qla24xx_process_purex_iocb(st + rsp_els->rx_dsd_count = 0; + rsp_els->opcode = purex->els_frame_payload[0]; + +- rsp_els->port_id[0] = purex->s_id[0]; +- rsp_els->port_id[1] = purex->s_id[1]; +- rsp_els->port_id[2] = purex->s_id[2]; ++ rsp_els->d_id[0] = purex->s_id[0]; ++ rsp_els->d_id[1] = purex->s_id[1]; ++ rsp_els->d_id[2] = purex->s_id[2]; + + rsp_els->control_flags = EPD_ELS_ACC; + rsp_els->rx_byte_count = 0; +@@ -6278,14 +6284,14 @@ send: + + rval = qla2x00_issue_iocb(vha, rsp_els, rsp_els_dma, 0); + +- if (rval != QLA_SUCCESS) { ++ if (rval) { + ql_log(ql_log_warn, vha, 0x0188, +- "%s: failed to issue IOCB (%x).\n", __func__, rval); +- } else if (rsp_els->entry_status != 0) { ++ "%s: iocb failed to execute -> %x\n", __func__, rval); ++ } else if (rsp_els->comp_status) { + ql_log(ql_log_warn, vha, 0x0189, +- "%s: failed to complete IOCB -- error status (%x).\n", +- __func__, rsp_els->entry_status); +- rval = QLA_FUNCTION_FAILED; ++ "%s: iocb failed to complete -> completion=%#x subcode=(%#x,%#x)\n", ++ __func__, rsp_els->comp_status, ++ rsp_els->error_subcode_1, rsp_els->error_subcode_2); + } else { + ql_dbg(ql_dbg_init, vha, 0x018a, "%s: done.\n", __func__); + } diff --git a/patches.suse/scsi-qla2xxx-Convert-MAKE_HANDLE-from-a-define-into-.patch b/patches.suse/scsi-qla2xxx-Convert-MAKE_HANDLE-from-a-define-into-.patch new file mode 100644 index 0000000..25bc7ff --- /dev/null +++ b/patches.suse/scsi-qla2xxx-Convert-MAKE_HANDLE-from-a-define-into-.patch @@ -0,0 +1,258 @@ +From: Bart Van Assche +Date: Wed, 19 Feb 2020 20:34:40 -0800 +Subject: scsi: qla2xxx: Convert MAKE_HANDLE() from a define into an inline + function +Patch-mainline: v5.7-rc1 +Git-commit: c25eb70a10243c1ad24e74375aceb65ab8951e93 +References: bsc#1157424 + +This patch allows sparse to verify the endianness of the arguments passed +to make_handle(). + +Link: https://lore.kernel.org/r/20200220043441.20504-5-bvanassche@acm.org +Cc: Roman Bolshakov +Cc: Daniel Wagner +Cc: Martin Wilck +Cc: Quinn Tran +Reviewed-by: Daniel Wagner +Reviewed-by: Roman Bolshakov +Acked-by: Himanshu Madhani +Signed-off-by: Bart Van Assche +Signed-off-by: Martin K. Petersen +--- + drivers/scsi/qla2xxx/qla_def.h | 5 ++++- + drivers/scsi/qla2xxx/qla_iocb.c | 22 +++++++++++----------- + drivers/scsi/qla2xxx/qla_mbx.c | 10 +++++----- + drivers/scsi/qla2xxx/qla_mr.c | 8 ++++---- + drivers/scsi/qla2xxx/qla_nvme.c | 2 +- + drivers/scsi/qla2xxx/qla_target.c | 6 +++--- + 6 files changed, 28 insertions(+), 25 deletions(-) + +--- a/drivers/scsi/qla2xxx/qla_def.h ++++ b/drivers/scsi/qla2xxx/qla_def.h +@@ -119,7 +119,10 @@ typedef struct { + #define LSD(x) ((uint32_t)((uint64_t)(x))) + #define MSD(x) ((uint32_t)((((uint64_t)(x)) >> 16) >> 16)) + +-#define MAKE_HANDLE(x, y) ((uint32_t)((((uint32_t)(x)) << 16) | (uint32_t)(y))) ++static inline uint32_t make_handle(uint16_t x, uint16_t y) ++{ ++ return ((uint32_t)x << 16) | y; ++} + + /* + * I/O register +--- a/drivers/scsi/qla2xxx/qla_iocb.c ++++ b/drivers/scsi/qla2xxx/qla_iocb.c +@@ -530,7 +530,7 @@ __qla2x00_marker(struct scsi_qla_host *v + int_to_scsilun(lun, (struct scsi_lun *)&mrk24->lun); + host_to_fcp_swap(mrk24->lun, sizeof(mrk24->lun)); + mrk24->vp_index = vha->vp_idx; +- mrk24->handle = MAKE_HANDLE(req->id, mrk24->handle); ++ mrk24->handle = make_handle(req->id, mrk24->handle); + } else { + SET_TARGET_ID(ha, mrk->target, loop_id); + mrk->lun = cpu_to_le16((uint16_t)lun); +@@ -1655,7 +1655,7 @@ qla24xx_start_scsi(srb_t *sp) + req->cnt -= req_cnt; + + cmd_pkt = (struct cmd_type_7 *)req->ring_ptr; +- cmd_pkt->handle = MAKE_HANDLE(req->id, handle); ++ cmd_pkt->handle = make_handle(req->id, handle); + + /* Zero out remaining portion of packet. */ + /* tagged queuing modifier -- default is TSK_SIMPLE (0). */ +@@ -1843,7 +1843,7 @@ qla24xx_dif_start_scsi(srb_t *sp) + + /* Fill-in common area */ + cmd_pkt = (struct cmd_type_crc_2 *)req->ring_ptr; +- cmd_pkt->handle = MAKE_HANDLE(req->id, handle); ++ cmd_pkt->handle = make_handle(req->id, handle); + + clr_ptr = (uint32_t *)cmd_pkt + 2; + memset(clr_ptr, 0, REQUEST_ENTRY_SIZE - 8); +@@ -1975,7 +1975,7 @@ qla2xxx_start_scsi_mq(srb_t *sp) + req->cnt -= req_cnt; + + cmd_pkt = (struct cmd_type_7 *)req->ring_ptr; +- cmd_pkt->handle = MAKE_HANDLE(req->id, handle); ++ cmd_pkt->handle = make_handle(req->id, handle); + + /* Zero out remaining portion of packet. */ + /* tagged queuing modifier -- default is TSK_SIMPLE (0). */ +@@ -2178,7 +2178,7 @@ qla2xxx_dif_start_scsi_mq(srb_t *sp) + + /* Fill-in common area */ + cmd_pkt = (struct cmd_type_crc_2 *)req->ring_ptr; +- cmd_pkt->handle = MAKE_HANDLE(req->id, handle); ++ cmd_pkt->handle = make_handle(req->id, handle); + + clr_ptr = (uint32_t *)cmd_pkt + 2; + memset(clr_ptr, 0, REQUEST_ENTRY_SIZE - 8); +@@ -2491,7 +2491,7 @@ qla24xx_tm_iocb(srb_t *sp, struct tsk_mg + + tsk->entry_type = TSK_MGMT_IOCB_TYPE; + tsk->entry_count = 1; +- tsk->handle = MAKE_HANDLE(req->id, tsk->handle); ++ tsk->handle = make_handle(req->id, tsk->handle); + tsk->nport_handle = cpu_to_le16(fcport->loop_id); + tsk->timeout = cpu_to_le16(ha->r_a_tov / 10 * 2); + tsk->control_flags = cpu_to_le32(flags); +@@ -3362,7 +3362,7 @@ sufficient_dsds: + } + + cmd_pkt = (struct cmd_type_6 *)req->ring_ptr; +- cmd_pkt->handle = MAKE_HANDLE(req->id, handle); ++ cmd_pkt->handle = make_handle(req->id, handle); + + /* Zero out remaining portion of packet. */ + /* tagged queuing modifier -- default is TSK_SIMPLE (0). */ +@@ -3433,7 +3433,7 @@ sufficient_dsds: + goto queuing_error; + + cmd_pkt = (struct cmd_type_7 *)req->ring_ptr; +- cmd_pkt->handle = MAKE_HANDLE(req->id, handle); ++ cmd_pkt->handle = make_handle(req->id, handle); + + /* Zero out remaining portion of packet. */ + /* tagged queuing modifier -- default is TSK_SIMPLE (0).*/ +@@ -3538,7 +3538,7 @@ qla24xx_abort_iocb(srb_t *sp, struct abo + memset(abt_iocb, 0, sizeof(struct abort_entry_24xx)); + abt_iocb->entry_type = ABORT_IOCB_TYPE; + abt_iocb->entry_count = 1; +- abt_iocb->handle = cpu_to_le32(MAKE_HANDLE(req->id, sp->handle)); ++ abt_iocb->handle = cpu_to_le32(make_handle(req->id, sp->handle)); + if (sp->fcport) { + abt_iocb->nport_handle = cpu_to_le16(sp->fcport->loop_id); + abt_iocb->port_id[0] = sp->fcport->d_id.b.al_pa; +@@ -3546,7 +3546,7 @@ qla24xx_abort_iocb(srb_t *sp, struct abo + abt_iocb->port_id[2] = sp->fcport->d_id.b.domain; + } + abt_iocb->handle_to_abort = +- cpu_to_le32(MAKE_HANDLE(aio->u.abt.req_que_no, ++ cpu_to_le32(make_handle(aio->u.abt.req_que_no, + aio->u.abt.cmd_hndl)); + abt_iocb->vp_index = vha->vp_idx; + abt_iocb->req_que_no = cpu_to_le16(aio->u.abt.req_que_no); +@@ -3909,7 +3909,7 @@ qla2x00_start_bidir(srb_t *sp, struct sc + } + + cmd_pkt = (struct cmd_bidir *)req->ring_ptr; +- cmd_pkt->handle = MAKE_HANDLE(req->id, handle); ++ cmd_pkt->handle = make_handle(req->id, handle); + + /* Zero out remaining portion of packet. */ + /* tagged queuing modifier -- default is TSK_SIMPLE (0).*/ +--- a/drivers/scsi/qla2xxx/qla_mbx.c ++++ b/drivers/scsi/qla2xxx/qla_mbx.c +@@ -2437,7 +2437,7 @@ qla24xx_login_fabric(scsi_qla_host_t *vh + + lg->entry_type = LOGINOUT_PORT_IOCB_TYPE; + lg->entry_count = 1; +- lg->handle = MAKE_HANDLE(req->id, lg->handle); ++ lg->handle = make_handle(req->id, lg->handle); + lg->nport_handle = cpu_to_le16(loop_id); + lg->control_flags = cpu_to_le16(LCF_COMMAND_PLOGI); + if (opt & BIT_0) +@@ -2707,7 +2707,7 @@ qla24xx_fabric_logout(scsi_qla_host_t *v + req = vha->req; + lg->entry_type = LOGINOUT_PORT_IOCB_TYPE; + lg->entry_count = 1; +- lg->handle = MAKE_HANDLE(req->id, lg->handle); ++ lg->handle = make_handle(req->id, lg->handle); + lg->nport_handle = cpu_to_le16(loop_id); + lg->control_flags = + cpu_to_le16(LCF_COMMAND_LOGO|LCF_IMPL_LOGO| +@@ -3197,9 +3197,9 @@ qla24xx_abort_command(srb_t *sp) + + abt->entry_type = ABORT_IOCB_TYPE; + abt->entry_count = 1; +- abt->handle = MAKE_HANDLE(req->id, abt->handle); ++ abt->handle = make_handle(req->id, abt->handle); + abt->nport_handle = cpu_to_le16(fcport->loop_id); +- abt->handle_to_abort = MAKE_HANDLE(req->id, handle); ++ abt->handle_to_abort = make_handle(req->id, handle); + abt->port_id[0] = fcport->d_id.b.al_pa; + abt->port_id[1] = fcport->d_id.b.area; + abt->port_id[2] = fcport->d_id.b.domain; +@@ -3276,7 +3276,7 @@ __qla24xx_issue_tmf(char *name, uint32_t + + tsk->p.tsk.entry_type = TSK_MGMT_IOCB_TYPE; + tsk->p.tsk.entry_count = 1; +- tsk->p.tsk.handle = MAKE_HANDLE(req->id, tsk->p.tsk.handle); ++ tsk->p.tsk.handle = make_handle(req->id, tsk->p.tsk.handle); + tsk->p.tsk.nport_handle = cpu_to_le16(fcport->loop_id); + tsk->p.tsk.timeout = cpu_to_le16(ha->r_a_tov / 10 * 2); + tsk->p.tsk.control_flags = cpu_to_le32(type); +--- a/drivers/scsi/qla2xxx/qla_mr.c ++++ b/drivers/scsi/qla2xxx/qla_mr.c +@@ -3135,7 +3135,7 @@ qlafx00_start_scsi(srb_t *sp) + + memset(&lcmd_pkt, 0, REQUEST_ENTRY_SIZE); + +- lcmd_pkt.handle = MAKE_HANDLE(req->id, sp->handle); ++ lcmd_pkt.handle = make_handle(req->id, sp->handle); + lcmd_pkt.reserved_0 = 0; + lcmd_pkt.port_path_ctrl = 0; + lcmd_pkt.reserved_1 = 0; +@@ -3205,7 +3205,7 @@ qlafx00_tm_iocb(srb_t *sp, struct tsk_mg + memset(&tm_iocb, 0, sizeof(struct tsk_mgmt_entry_fx00)); + tm_iocb.entry_type = TSK_MGMT_IOCB_TYPE_FX00; + tm_iocb.entry_count = 1; +- tm_iocb.handle = cpu_to_le32(MAKE_HANDLE(req->id, sp->handle)); ++ tm_iocb.handle = cpu_to_le32(make_handle(req->id, sp->handle)); + tm_iocb.reserved_0 = 0; + tm_iocb.tgt_id = cpu_to_le16(sp->fcport->tgt_id); + tm_iocb.control_flags = cpu_to_le32(fxio->u.tmf.flags); +@@ -3231,9 +3231,9 @@ qlafx00_abort_iocb(srb_t *sp, struct abo + memset(&abt_iocb, 0, sizeof(struct abort_iocb_entry_fx00)); + abt_iocb.entry_type = ABORT_IOCB_TYPE_FX00; + abt_iocb.entry_count = 1; +- abt_iocb.handle = cpu_to_le32(MAKE_HANDLE(req->id, sp->handle)); ++ abt_iocb.handle = cpu_to_le32(make_handle(req->id, sp->handle)); + abt_iocb.abort_handle = +- cpu_to_le32(MAKE_HANDLE(req->id, fxio->u.abt.cmd_hndl)); ++ cpu_to_le32(make_handle(req->id, fxio->u.abt.cmd_hndl)); + abt_iocb.tgt_id_sts = cpu_to_le16(sp->fcport->tgt_id); + abt_iocb.req_que_no = cpu_to_le16(req->id); + +--- a/drivers/scsi/qla2xxx/qla_nvme.c ++++ b/drivers/scsi/qla2xxx/qla_nvme.c +@@ -424,7 +424,7 @@ static inline int qla2x00_start_nvme_mq( + req->cnt -= req_cnt; + + cmd_pkt = (struct cmd_nvme *)req->ring_ptr; +- cmd_pkt->handle = MAKE_HANDLE(req->id, handle); ++ cmd_pkt->handle = make_handle(req->id, handle); + + /* Zero out remaining portion of packet. */ + clr_ptr = (uint32_t *)cmd_pkt + 2; +--- a/drivers/scsi/qla2xxx/qla_target.c ++++ b/drivers/scsi/qla2xxx/qla_target.c +@@ -1767,7 +1767,7 @@ static int qlt_build_abts_resp_iocb(stru + qpair->req->outstanding_cmds[h] = (srb_t *)mcmd; + } + +- resp->handle = MAKE_HANDLE(qpair->req->id, h); ++ resp->handle = make_handle(qpair->req->id, h); + resp->entry_type = ABTS_RESP_24XX; + resp->entry_count = 1; + resp->nport_handle = abts->nport_handle; +@@ -2589,7 +2589,7 @@ static int qlt_24xx_build_ctio_pkt(struc + } else + qpair->req->outstanding_cmds[h] = (srb_t *)prm->cmd; + +- pkt->handle = MAKE_HANDLE(qpair->req->id, h); ++ pkt->handle = make_handle(qpair->req->id, h); + pkt->handle |= CTIO_COMPLETION_HANDLE_MARK; + pkt->nport_handle = cpu_to_le16(prm->cmd->loop_id); + pkt->timeout = cpu_to_le16(QLA_TGT_TIMEOUT); +@@ -3102,7 +3102,7 @@ qlt_build_ctio_crc2_pkt(struct qla_qpair + } else + qpair->req->outstanding_cmds[h] = (srb_t *)prm->cmd; + +- pkt->handle = MAKE_HANDLE(qpair->req->id, h); ++ pkt->handle = make_handle(qpair->req->id, h); + pkt->handle |= CTIO_COMPLETION_HANDLE_MARK; + pkt->nport_handle = cpu_to_le16(prm->cmd->loop_id); + pkt->timeout = cpu_to_le16(QLA_TGT_TIMEOUT); diff --git a/patches.suse/scsi-qla2xxx-Correction-to-selection-of-loopback-ech.patch b/patches.suse/scsi-qla2xxx-Correction-to-selection-of-loopback-ech.patch new file mode 100644 index 0000000..3efa0b9 --- /dev/null +++ b/patches.suse/scsi-qla2xxx-Correction-to-selection-of-loopback-ech.patch @@ -0,0 +1,45 @@ +From: Joe Carnuccio +Date: Wed, 12 Feb 2020 13:44:28 -0800 +Subject: scsi: qla2xxx: Correction to selection of loopback/echo test +Patch-mainline: v5.7-rc1 +Git-commit: 64d21b314173c46d5c88a55cf559b0677e39d884 +References: bsc#1157424 + +This fixes loopback and echo test options. + +Link: https://lore.kernel.org/r/20200212214436.25532-18-hmadhani@marvell.com +Signed-off-by: Joe Carnuccio +Signed-off-by: Himanshu Madhani +Signed-off-by: Martin K. Petersen +Acked-by: Daniel Wagner +--- + drivers/scsi/qla2xxx/qla_bsg.c | 11 ++++++----- + 1 file changed, 6 insertions(+), 5 deletions(-) + +--- a/drivers/scsi/qla2xxx/qla_bsg.c ++++ b/drivers/scsi/qla2xxx/qla_bsg.c +@@ -728,7 +728,7 @@ qla2x00_process_loopback(struct bsg_job + uint16_t response[MAILBOX_REGISTER_COUNT]; + uint16_t config[4], new_config[4]; + uint8_t *fw_sts_ptr; +- uint8_t *req_data = NULL; ++ void *req_data = NULL; + dma_addr_t req_data_dma; + uint32_t req_data_len; + uint8_t *rsp_data = NULL; +@@ -806,10 +806,11 @@ qla2x00_process_loopback(struct bsg_job + bsg_request->rqst_data.h_vendor.vendor_cmd[2]; + + if (atomic_read(&vha->loop_state) == LOOP_READY && +- (ha->current_topology == ISP_CFG_F || +- (get_unaligned_le32(req_data) == ELS_OPCODE_BYTE && +- req_data_len == MAX_ELS_FRAME_PAYLOAD)) && +- elreq.options == EXTERNAL_LOOPBACK) { ++ ((ha->current_topology == ISP_CFG_F && (elreq.options & 7) >= 2) || ++ ((IS_QLA81XX(ha) || IS_QLA8031(ha) || IS_QLA8044(ha)) && ++ get_unaligned_le32(req_data) == ELS_OPCODE_BYTE && ++ req_data_len == MAX_ELS_FRAME_PAYLOAD && ++ elreq.options == EXTERNAL_LOOPBACK))) { + type = "FC_BSG_HST_VENDOR_ECHO_DIAG"; + ql_dbg(ql_dbg_user, vha, 0x701e, + "BSG request type: %s.\n", type); diff --git a/patches.suse/scsi-qla2xxx-Display-message-for-FCE-enabled.patch b/patches.suse/scsi-qla2xxx-Display-message-for-FCE-enabled.patch new file mode 100644 index 0000000..56b68c7 --- /dev/null +++ b/patches.suse/scsi-qla2xxx-Display-message-for-FCE-enabled.patch @@ -0,0 +1,52 @@ +From: Himanshu Madhani +Date: Wed, 12 Feb 2020 13:44:21 -0800 +Subject: scsi: qla2xxx: Display message for FCE enabled +Patch-mainline: v5.7-rc1 +Git-commit: 75666f4a8c4103fb120717140c26cdbf6b1bf053 +References: bsc#1157424 + +During Link up phase and Data rate MBX command response, print message +indicating FCE is enabled. + +Link: https://lore.kernel.org/r/20200212214436.25532-11-hmadhani@marvell.com +Signed-off-by: Himanshu Madhani +Signed-off-by: Martin K. Petersen +Acked-by: Daniel Wagner +--- + drivers/scsi/qla2xxx/qla_isr.c | 6 ++++++ + drivers/scsi/qla2xxx/qla_mbx.c | 9 +++++++++ + 2 files changed, 15 insertions(+) + +--- a/drivers/scsi/qla2xxx/qla_isr.c ++++ b/drivers/scsi/qla2xxx/qla_isr.c +@@ -820,6 +820,12 @@ skip_rio: + "LOOP UP detected (%s Gbps).\n", + qla2x00_get_link_speed_str(ha, ha->link_data_rate)); + ++ if (IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha)) { ++ if (mb[2] & BIT_0) ++ ql_log(ql_log_info, vha, 0x11a0, ++ "FEC=enabled (link up).\n"); ++ } ++ + vha->flags.management_server_logged_in = 0; + qla2x00_post_aen_work(vha, FCH_EVT_LINKUP, ha->link_data_rate); + +--- a/drivers/scsi/qla2xxx/qla_mbx.c ++++ b/drivers/scsi/qla2xxx/qla_mbx.c +@@ -5554,6 +5554,15 @@ qla2x00_get_data_rate(scsi_qla_host_t *v + ql_dbg(ql_dbg_mbx, vha, 0x1107, + "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]); + } else { ++ if (mcp->mb[1] != 0x7) ++ ha->link_data_rate = mcp->mb[1]; ++ ++ if (IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha)) { ++ if (mcp->mb[4] & BIT_0) ++ ql_log(ql_log_info, vha, 0x11a2, ++ "FEC=enabled (data rate).\n"); ++ } ++ + ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1108, + "Done %s.\n", __func__); + if (mcp->mb[1] != 0x7) diff --git a/patches.suse/scsi-qla2xxx-Fix-FCP-SCSI-FC4-flag-passing-error.patch b/patches.suse/scsi-qla2xxx-Fix-FCP-SCSI-FC4-flag-passing-error.patch new file mode 100644 index 0000000..83f0134 --- /dev/null +++ b/patches.suse/scsi-qla2xxx-Fix-FCP-SCSI-FC4-flag-passing-error.patch @@ -0,0 +1,79 @@ +From: Quinn Tran +Date: Wed, 26 Feb 2020 14:40:08 -0800 +Subject: scsi: qla2xxx: Fix FCP-SCSI FC4 flag passing error +Patch-mainline: v5.7-rc1 +Git-commit: 8e0e063af0d1be30245a08fab0515a3cccfcd513 +References: bsc#1157424 + +This patch fixes issue where incorrect flag was used for sending +switch commands. + +Link: https://lore.kernel.org/r/20200226224022.24518-5-hmadhani@marvell.com +Fixes: e8c72ba51a15 ("[SCSI] qla2xxx: Use GFF_ID to check FCP-SCSI FC4 type before logging into Nx_Ports") +Fixes: a4239945b8ad ("scsi: qla2xxx: Add switch command to simplify fabric discovery") +Signed-off-by: Himanshu Madhani +Signed-off-by: Quinn Tran +Signed-off-by: Martin K. Petersen +Acked-by: Daniel Wagner +--- + drivers/scsi/qla2xxx/qla_gs.c | 4 ++-- + drivers/scsi/qla2xxx/qla_init.c | 4 ++-- + drivers/scsi/qla2xxx/qla_target.c | 4 ++-- + 3 files changed, 6 insertions(+), 6 deletions(-) + +--- a/drivers/scsi/qla2xxx/qla_gs.c ++++ b/drivers/scsi/qla2xxx/qla_gs.c +@@ -2733,7 +2733,7 @@ qla2x00_gff_id(scsi_qla_host_t *vha, sw_ + for (i = 0; i < ha->max_fibre_devices; i++) { + /* Set default FC4 Type as UNKNOWN so the default is to + * Process this port */ +- list[i].fc4_type = FC4_TYPE_UNKNOWN; ++ list[i].fc4_type = 0; + + /* Do not attempt GFF_ID if we are not FWI_2 capable */ + if (!IS_FWI2_CAPABLE(ha)) +@@ -3083,7 +3083,7 @@ void qla24xx_handle_gpnid_event(scsi_qla + "%s %d %8phC post new sess\n", + __func__, __LINE__, ea->port_name); + qla24xx_post_newsess_work(vha, &ea->id, +- ea->port_name, NULL, NULL, FC4_TYPE_UNKNOWN); ++ ea->port_name, NULL, NULL, 0); + } + } + } +--- a/drivers/scsi/qla2xxx/qla_init.c ++++ b/drivers/scsi/qla2xxx/qla_init.c +@@ -1045,7 +1045,7 @@ static void qla24xx_async_gnl_sp_done(sr + __func__, __LINE__, (u8 *)&wwn, id.b24); + wwnn = wwn_to_u64(e->node_name); + qla24xx_post_newsess_work(vha, &id, (u8 *)&wwn, +- (u8 *)&wwnn, NULL, FC4_TYPE_UNKNOWN); ++ (u8 *)&wwnn, NULL, 0); + } + } + +@@ -5828,7 +5828,7 @@ qla2x00_find_all_fabric_devs(scsi_qla_ho + /* Bypass ports whose FCP-4 type is not FCP_SCSI */ + if (ql2xgffidenable && + (!(new_fcport->fc4_type & FS_FC4TYPE_FCP) && +- new_fcport->fc4_type != FC4_TYPE_UNKNOWN)) ++ new_fcport->fc4_type != 0)) + continue; + + spin_lock_irqsave(&vha->hw->tgt.sess_lock, flags); +--- a/drivers/scsi/qla2xxx/qla_target.c ++++ b/drivers/scsi/qla2xxx/qla_target.c +@@ -4748,11 +4748,11 @@ static int qlt_handle_login(struct scsi_ + qla24xx_post_newsess_work(vha, &port_id, + iocb->u.isp24.port_name, + iocb->u.isp24.u.plogi.node_name, +- pla, FC4_TYPE_UNKNOWN); ++ pla, 0); + else + qla24xx_post_newsess_work(vha, &port_id, + iocb->u.isp24.port_name, NULL, +- pla, FC4_TYPE_UNKNOWN); ++ pla, 0); + + goto out; + } diff --git a/patches.suse/scsi-qla2xxx-Fix-I-Os-being-passed-down-when-FC-devi.patch b/patches.suse/scsi-qla2xxx-Fix-I-Os-being-passed-down-when-FC-devi.patch new file mode 100644 index 0000000..83dd294 --- /dev/null +++ b/patches.suse/scsi-qla2xxx-Fix-I-Os-being-passed-down-when-FC-devi.patch @@ -0,0 +1,49 @@ +From: Arun Easi +Date: Fri, 13 Mar 2020 01:50:01 -0700 +Subject: scsi: qla2xxx: Fix I/Os being passed down when FC device is being + deleted +Patch-mainline: v5.6 +Git-commit: 78c3e5e6cde8193467427ed9e5f90a0d585625a1 +References: bsc#1157424 + +I/Os could be passed down while the device FC SCSI device is being deleted. +This would result in unnecessary delay of I/O and driver messages (when +extended logging is set). + +[mkp: fixed commit hash and added SoB for Nilesh] + +Link: https://lore.kernel.org/r/20200313085001.3781-1-njavali@marvell.com +Fixes: 3c75ad1d87c7 ("scsi: qla2xxx: Remove defer flag to indicate immeadiate port loss") # v5.6-rc1+ +Tested-by: Laurence Oberman +Reviewed-by: Laurence Oberman +Reviewed-by: Ewan D. Milne +Reviewed-by: Roman Bolshakov +Reviewed-by: Himanshu Madhani +Signed-off-by: Arun Easi +Signed-off-by: Nilesh Javali +Signed-off-by: Martin K. Petersen +Acked-by: Daniel Wagner +--- + drivers/scsi/qla2xxx/qla_os.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/scsi/qla2xxx/qla_os.c ++++ b/drivers/scsi/qla2xxx/qla_os.c +@@ -870,7 +870,7 @@ qla2xxx_queuecommand(struct Scsi_Host *h + goto qc24_fail_command; + } + +- if (atomic_read(&fcport->state) != FCS_ONLINE) { ++ if (atomic_read(&fcport->state) != FCS_ONLINE || fcport->deleted) { + if (atomic_read(&fcport->state) == FCS_DEVICE_DEAD || + atomic_read(&base_vha->loop_state) == LOOP_DEAD) { + ql_dbg(ql_dbg_io, vha, 0x3005, +@@ -952,7 +952,7 @@ qla2xxx_mqueuecommand(struct Scsi_Host * + goto qc24_fail_command; + } + +- if (atomic_read(&fcport->state) != FCS_ONLINE) { ++ if (atomic_read(&fcport->state) != FCS_ONLINE || fcport->deleted) { + if (atomic_read(&fcport->state) == FCS_DEVICE_DEAD || + atomic_read(&base_vha->loop_state) == LOOP_DEAD) { + ql_dbg(ql_dbg_io, vha, 0x3077, diff --git a/patches.suse/scsi-qla2xxx-Fix-NPIV-instantiation-after-FW-dump.patch b/patches.suse/scsi-qla2xxx-Fix-NPIV-instantiation-after-FW-dump.patch new file mode 100644 index 0000000..16e50d7 --- /dev/null +++ b/patches.suse/scsi-qla2xxx-Fix-NPIV-instantiation-after-FW-dump.patch @@ -0,0 +1,31 @@ +From: Quinn Tran +Date: Wed, 26 Feb 2020 14:40:17 -0800 +Subject: scsi: qla2xxx: Fix NPIV instantiation after FW dump +Patch-mainline: v5.7-rc1 +Git-commit: ab391abdc191c2a2874098df86d1fe4b9762ef60 +References: bsc#1157424 + +NPIV re-enable code was blocked after FW had been initialized. The +blocking check was too broad. Reduce the check to make sure if FW is +initialized or not. + +Link: https://lore.kernel.org/r/20200226224022.24518-14-hmadhani@marvell.com +Signed-off-by: Himanshu Madhani +Signed-off-by: Quinn Tran +Signed-off-by: Martin K. Petersen +Acked-by: Daniel Wagner +--- + drivers/scsi/qla2xxx/qla_mbx.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/scsi/qla2xxx/qla_mbx.c ++++ b/drivers/scsi/qla2xxx/qla_mbx.c +@@ -1387,7 +1387,7 @@ qla2x00_issue_iocb_timeout(scsi_qla_host + mbx_cmd_t mc; + mbx_cmd_t *mcp = &mc; + +- if (qla2x00_chip_is_down(vha)) ++ if (!vha->hw->flags.fw_started) + return QLA_INVALID_COMMAND; + + ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1038, diff --git a/patches.suse/scsi-qla2xxx-Fix-RDP-respond-data-format.patch b/patches.suse/scsi-qla2xxx-Fix-RDP-respond-data-format.patch new file mode 100644 index 0000000..da93d12 --- /dev/null +++ b/patches.suse/scsi-qla2xxx-Fix-RDP-respond-data-format.patch @@ -0,0 +1,229 @@ +From: Quinn Tran +Date: Wed, 26 Feb 2020 14:40:16 -0800 +Subject: scsi: qla2xxx: Fix RDP respond data format +Patch-mainline: v5.7-rc1 +Git-commit: 770538c3012ac8ff92d5e4ae18850588c188c5fa +References: bsc#1157424 + +RPD information failed to display by switch cli command. This is +caused by driver failure to properly format RDP response data with +data descriptor to allow switch to parse it correctly. + +Link: https://lore.kernel.org/r/20200226224022.24518-13-hmadhani@marvell.com +Signed-off-by: Himanshu Madhani +Signed-off-by: Quinn Tran +Signed-off-by: Martin K. Petersen +Acked-by: Daniel Wagner +--- + drivers/scsi/qla2xxx/qla_os.c | 102 +++++++++++++++++++----------------------- + 1 file changed, 47 insertions(+), 55 deletions(-) + +--- a/drivers/scsi/qla2xxx/qla_os.c ++++ b/drivers/scsi/qla2xxx/qla_os.c +@@ -5986,7 +5986,6 @@ void qla24xx_process_purex_rdp(struct sc + &bbc_dma, GFP_KERNEL); + + /* Prepare Response IOCB */ +- memset(rsp_els, 0, sizeof(*rsp_els)); + rsp_els->entry_type = ELS_IOCB_TYPE; + rsp_els->entry_count = 1; + rsp_els->sys_define = 0; +@@ -6033,6 +6032,11 @@ void qla24xx_process_purex_rdp(struct sc + rsp_payload->ls_req_info_desc2.req_payload_word_0 = + cpu_to_be32p((uint32_t *)purex->els_frame_payload); + ++ ++ rsp_payload->sfp_diag_desc.desc_tag = cpu_to_be32(0x10000); ++ rsp_payload->sfp_diag_desc.desc_len = ++ cpu_to_be32(RDP_DESC_LEN(rsp_payload->sfp_diag_desc)); ++ + if (sfp) { + /* SFP Flags */ + memset(sfp, 0, SFP_RTDI_LEN); +@@ -6056,23 +6060,18 @@ void qla24xx_process_purex_rdp(struct sc + sfp_flags |= BIT_6; /* sfp+ */ + } + ++ rsp_payload->sfp_diag_desc.sfp_flags = cpu_to_be16(sfp_flags); ++ + /* SFP Diagnostics */ + memset(sfp, 0, SFP_RTDI_LEN); + rval = qla2x00_read_sfp(vha, sfp_dma, sfp, 0xa2, 0x60, 10, 0); +- if (!rval && sfp_flags) { ++ if (!rval) { + uint16_t *trx = (void *)sfp; /* already be16 */ +- +- rsp_payload->sfp_diag_desc.desc_tag = +- cpu_to_be32(0x10000); +- rsp_payload->sfp_diag_desc.desc_len = +- cpu_to_be32(RDP_DESC_LEN(rsp_payload->sfp_diag_desc)); + rsp_payload->sfp_diag_desc.temperature = trx[0]; + rsp_payload->sfp_diag_desc.vcc = trx[1]; + rsp_payload->sfp_diag_desc.tx_bias = trx[2]; + rsp_payload->sfp_diag_desc.tx_power = trx[3]; + rsp_payload->sfp_diag_desc.rx_power = trx[4]; +- rsp_payload->sfp_diag_desc.sfp_flags = +- cpu_to_be16(sfp_flags); + } + } + +@@ -6085,14 +6084,14 @@ void qla24xx_process_purex_rdp(struct sc + rsp_payload->port_speed_desc.operating_speed = cpu_to_be16( + qla25xx_rdp_port_speed_currently(ha)); + ++ /* Link Error Status Descriptor */ ++ rsp_payload->ls_err_desc.desc_tag = cpu_to_be32(0x10002); ++ rsp_payload->ls_err_desc.desc_len = ++ cpu_to_be32(RDP_DESC_LEN(rsp_payload->ls_err_desc)); ++ + if (stat) { + rval = qla24xx_get_isp_stats(vha, stat, stat_dma, 0); + if (!rval) { +- /* Link Error Status Descriptor */ +- rsp_payload->ls_err_desc.desc_tag = +- cpu_to_be32(0x10002); +- rsp_payload->ls_err_desc.desc_len = +- cpu_to_be32(RDP_DESC_LEN(rsp_payload->ls_err_desc)); + rsp_payload->ls_err_desc.link_fail_cnt = + cpu_to_be32(stat->link_fail_cnt); + rsp_payload->ls_err_desc.loss_sync_cnt = +@@ -6131,28 +6130,47 @@ void qla24xx_process_purex_rdp(struct sc + vha->fabric_port_name, + sizeof(rsp_payload->port_name_direct_desc.WWPN)); + ++ /* Bufer Credit Descriptor */ ++ rsp_payload->buffer_credit_desc.desc_tag = cpu_to_be32(0x10006); ++ rsp_payload->buffer_credit_desc.desc_len = ++ cpu_to_be32(RDP_DESC_LEN(rsp_payload->buffer_credit_desc)); ++ rsp_payload->buffer_credit_desc.fcport_b2b = 0; ++ rsp_payload->buffer_credit_desc.attached_fcport_b2b = cpu_to_be32(0); ++ rsp_payload->buffer_credit_desc.fcport_rtt = cpu_to_be32(0); ++ + if (bbc) { + memset(bbc, 0, sizeof(*bbc)); + rval = qla24xx_get_buffer_credits(vha, bbc, bbc_dma); + if (!rval) { +- /* Bufer Credit Descriptor */ +- rsp_payload->buffer_credit_desc.desc_tag = +- cpu_to_be32(0x10006); +- rsp_payload->buffer_credit_desc.desc_len = +- cpu_to_be32(RDP_DESC_LEN( +- rsp_payload->buffer_credit_desc)); + rsp_payload->buffer_credit_desc.fcport_b2b = + cpu_to_be32(LSW(bbc->parameter[0])); +- rsp_payload->buffer_credit_desc.attached_fcport_b2b = +- cpu_to_be32(0); +- rsp_payload->buffer_credit_desc.fcport_rtt = +- cpu_to_be32(0); + } + } + + if (rsp_payload_length < sizeof(*rsp_payload)) + goto send; + ++ /* Optical Element Descriptor, Temperature */ ++ rsp_payload->optical_elmt_desc[0].desc_tag = cpu_to_be32(0x10007); ++ rsp_payload->optical_elmt_desc[0].desc_len = ++ cpu_to_be32(RDP_DESC_LEN(*rsp_payload->optical_elmt_desc)); ++ /* Optical Element Descriptor, Voltage */ ++ rsp_payload->optical_elmt_desc[1].desc_tag = cpu_to_be32(0x10007); ++ rsp_payload->optical_elmt_desc[1].desc_len = ++ cpu_to_be32(RDP_DESC_LEN(*rsp_payload->optical_elmt_desc)); ++ /* Optical Element Descriptor, Tx Bias Current */ ++ rsp_payload->optical_elmt_desc[2].desc_tag = cpu_to_be32(0x10007); ++ rsp_payload->optical_elmt_desc[2].desc_len = ++ cpu_to_be32(RDP_DESC_LEN(*rsp_payload->optical_elmt_desc)); ++ /* Optical Element Descriptor, Tx Power */ ++ rsp_payload->optical_elmt_desc[3].desc_tag = cpu_to_be32(0x10007); ++ rsp_payload->optical_elmt_desc[3].desc_len = ++ cpu_to_be32(RDP_DESC_LEN(*rsp_payload->optical_elmt_desc)); ++ /* Optical Element Descriptor, Rx Power */ ++ rsp_payload->optical_elmt_desc[4].desc_tag = cpu_to_be32(0x10007); ++ rsp_payload->optical_elmt_desc[4].desc_len = ++ cpu_to_be32(RDP_DESC_LEN(*rsp_payload->optical_elmt_desc)); ++ + if (sfp) { + memset(sfp, 0, SFP_RTDI_LEN); + rval = qla2x00_read_sfp(vha, sfp_dma, sfp, 0xa2, 0, 64, 0); +@@ -6160,11 +6178,6 @@ void qla24xx_process_purex_rdp(struct sc + uint16_t *trx = (void *)sfp; /* already be16 */ + + /* Optical Element Descriptor, Temperature */ +- rsp_payload->optical_elmt_desc[0].desc_tag = +- cpu_to_be32(0x10007); +- rsp_payload->optical_elmt_desc[0].desc_len = +- cpu_to_be32(RDP_DESC_LEN( +- *rsp_payload->optical_elmt_desc)); + rsp_payload->optical_elmt_desc[0].high_alarm = trx[0]; + rsp_payload->optical_elmt_desc[0].low_alarm = trx[1]; + rsp_payload->optical_elmt_desc[0].high_warn = trx[2]; +@@ -6173,11 +6186,6 @@ void qla24xx_process_purex_rdp(struct sc + cpu_to_be32(1 << 28); + + /* Optical Element Descriptor, Voltage */ +- rsp_payload->optical_elmt_desc[1].desc_tag = +- cpu_to_be32(0x10007); +- rsp_payload->optical_elmt_desc[1].desc_len = +- cpu_to_be32(RDP_DESC_LEN( +- *rsp_payload->optical_elmt_desc)); + rsp_payload->optical_elmt_desc[1].high_alarm = trx[4]; + rsp_payload->optical_elmt_desc[1].low_alarm = trx[5]; + rsp_payload->optical_elmt_desc[1].high_warn = trx[6]; +@@ -6186,11 +6194,6 @@ void qla24xx_process_purex_rdp(struct sc + cpu_to_be32(2 << 28); + + /* Optical Element Descriptor, Tx Bias Current */ +- rsp_payload->optical_elmt_desc[2].desc_tag = +- cpu_to_be32(0x10007); +- rsp_payload->optical_elmt_desc[2].desc_len = +- cpu_to_be32(RDP_DESC_LEN( +- *rsp_payload->optical_elmt_desc)); + rsp_payload->optical_elmt_desc[2].high_alarm = trx[8]; + rsp_payload->optical_elmt_desc[2].low_alarm = trx[9]; + rsp_payload->optical_elmt_desc[2].high_warn = trx[10]; +@@ -6199,11 +6202,6 @@ void qla24xx_process_purex_rdp(struct sc + cpu_to_be32(3 << 28); + + /* Optical Element Descriptor, Tx Power */ +- rsp_payload->optical_elmt_desc[3].desc_tag = +- cpu_to_be32(0x10007); +- rsp_payload->optical_elmt_desc[3].desc_len = +- cpu_to_be32(RDP_DESC_LEN( +- *rsp_payload->optical_elmt_desc)); + rsp_payload->optical_elmt_desc[3].high_alarm = trx[12]; + rsp_payload->optical_elmt_desc[3].low_alarm = trx[13]; + rsp_payload->optical_elmt_desc[3].high_warn = trx[14]; +@@ -6212,11 +6210,6 @@ void qla24xx_process_purex_rdp(struct sc + cpu_to_be32(4 << 28); + + /* Optical Element Descriptor, Rx Power */ +- rsp_payload->optical_elmt_desc[4].desc_tag = +- cpu_to_be32(0x10007); +- rsp_payload->optical_elmt_desc[4].desc_len = +- cpu_to_be32(RDP_DESC_LEN( +- *rsp_payload->optical_elmt_desc)); + rsp_payload->optical_elmt_desc[4].high_alarm = trx[16]; + rsp_payload->optical_elmt_desc[4].low_alarm = trx[17]; + rsp_payload->optical_elmt_desc[4].high_warn = trx[18]; +@@ -6270,16 +6263,15 @@ void qla24xx_process_purex_rdp(struct sc + } + } + ++ /* Optical Product Data Descriptor */ ++ rsp_payload->optical_prod_desc.desc_tag = cpu_to_be32(0x10008); ++ rsp_payload->optical_prod_desc.desc_len = ++ cpu_to_be32(RDP_DESC_LEN(rsp_payload->optical_prod_desc)); ++ + if (sfp) { + memset(sfp, 0, SFP_RTDI_LEN); + rval = qla2x00_read_sfp(vha, sfp_dma, sfp, 0xa0, 20, 64, 0); + if (!rval) { +- /* Optical Product Data Descriptor */ +- rsp_payload->optical_prod_desc.desc_tag = +- cpu_to_be32(0x10008); +- rsp_payload->optical_prod_desc.desc_len = +- cpu_to_be32(RDP_DESC_LEN( +- rsp_payload->optical_prod_desc)); + memcpy(rsp_payload->optical_prod_desc.vendor_name, + sfp + 0, + sizeof(rsp_payload->optical_prod_desc.vendor_name)); diff --git a/patches.suse/scsi-qla2xxx-Fix-RDP-response-size.patch b/patches.suse/scsi-qla2xxx-Fix-RDP-response-size.patch new file mode 100644 index 0000000..acc59d9 --- /dev/null +++ b/patches.suse/scsi-qla2xxx-Fix-RDP-response-size.patch @@ -0,0 +1,115 @@ +From: Himanshu Madhani +Date: Wed, 12 Feb 2020 13:44:26 -0800 +Subject: scsi: qla2xxx: Fix RDP response size +Patch-mainline: v5.7-rc1 +Git-commit: 84f7d2e7b1f5203050b47cfa65e284182d32f203 +References: bsc#1157424 + +This patch fixes RDP length in case when driver needs to reduce length of +RDP response + +Link: https://lore.kernel.org/r/20200212214436.25532-16-hmadhani@marvell.com +Signed-off-by: Himanshu Madhani +Signed-off-by: Martin K. Petersen +Acked-by: Daniel Wagner +--- + drivers/scsi/qla2xxx/qla_os.c | 53 +++++++++++++++--------------------------- + 1 file changed, 19 insertions(+), 34 deletions(-) + +--- a/drivers/scsi/qla2xxx/qla_os.c ++++ b/drivers/scsi/qla2xxx/qla_os.c +@@ -5788,6 +5788,7 @@ qla25xx_rdp_rsp_reduce_size(struct scsi_ + { + char fwstr[16]; + u32 sid = purex->s_id[2] << 16 | purex->s_id[1] << 8 | purex->s_id[0]; ++ struct port_database_24xx *pdb; + + /* Domain Controller is always logged-out. */ + /* if RDP request is not from Domain Controller: */ +@@ -5796,6 +5797,24 @@ qla25xx_rdp_rsp_reduce_size(struct scsi_ + + ql_dbg(ql_dbg_init, vha, 0x0181, "%s: s_id=%#x\n", __func__, sid); + ++ pdb = kzalloc(sizeof(*pdb), GFP_KERNEL); ++ if (!pdb) { ++ ql_dbg(ql_dbg_init, vha, 0x0181, ++ "%s: Failed allocate pdb\n", __func__); ++ } else if (qla24xx_get_port_database(vha, purex->nport_handle, pdb)) { ++ ql_dbg(ql_dbg_init, vha, 0x0181, ++ "%s: Failed get pdb sid=%x\n", __func__, sid); ++ } else if (pdb->current_login_state != PDS_PLOGI_COMPLETE && ++ pdb->current_login_state != PDS_PRLI_COMPLETE) { ++ ql_dbg(ql_dbg_init, vha, 0x0181, ++ "%s: Port not logged in sid=%#x\n", __func__, sid); ++ } else { ++ /* RDP request is from logged in port */ ++ kfree(pdb); ++ return false; ++ } ++ kfree(pdb); ++ + vha->hw->isp_ops->fw_version_str(vha, fwstr, sizeof(fwstr)); + fwstr[strcspn(fwstr, " ")] = 0; + /* if FW version allows RDP response length upto 2048 bytes: */ +@@ -5914,7 +5933,6 @@ void qla24xx_process_purex_rdp(struct sc + { + struct qla_hw_data *ha = vha->hw; + struct purex_entry_24xx *purex = pkt; +- struct port_database_24xx *pdb = NULL; + dma_addr_t rsp_els_dma; + dma_addr_t rsp_payload_dma; + dma_addr_t stat_dma; +@@ -5999,34 +6017,6 @@ void qla24xx_process_purex_rdp(struct sc + rsp_els->rx_address = 0; + rsp_els->rx_len = 0; + +- if (sizeof(*rsp_payload) <= 0x100) +- goto accept; +- +- pdb = kzalloc(sizeof(*pdb), GFP_KERNEL); +- if (!pdb) +- goto reduce; +- +- rval = qla24xx_get_port_database(vha, purex->nport_handle, pdb); +- if (rval) +- goto reduce; +- +- if (pdb->port_id[0] != purex->s_id[2] || +- pdb->port_id[1] != purex->s_id[1] || +- pdb->port_id[2] != purex->s_id[0]) +- goto reduce; +- +- if (pdb->current_login_state == PDS_PLOGI_COMPLETE || +- pdb->current_login_state == PDS_PRLI_COMPLETE) +- goto accept; +- +-reduce: +- ql_dbg(ql_dbg_init, vha, 0x016e, "Requesting port is not logged in.\n"); +- rsp_els->tx_byte_count = rsp_els->tx_len = +- offsetof(struct rdp_rsp_payload, buffer_credit_desc); +- ql_dbg(ql_dbg_init, vha, 0x016f, "Reduced response payload size %u.\n", +- rsp_els->tx_byte_count); +- +-accept: + /* Prepare Response Payload */ + rsp_payload->hdr.cmd = cpu_to_be32(0x2 << 24); /* LS_ACC */ + rsp_payload->hdr.len = cpu_to_be32( +@@ -6144,9 +6134,6 @@ accept: + vha->fabric_port_name, + sizeof(rsp_payload->port_name_direct_desc.WWPN)); + +- if (rsp_els->tx_byte_count < sizeof(*rsp_payload)) +- goto send; +- + if (bbc) { + memset(bbc, 0, sizeof(*bbc)); + rval = qla24xx_get_buffer_credits(vha, bbc, bbc_dma); +@@ -6346,8 +6333,6 @@ send: + } + + dealloc: +- kfree(pdb); +- + if (bbc) + dma_free_coherent(&ha->pdev->dev, sizeof(*bbc), + bbc, bbc_dma); diff --git a/patches.suse/scsi-qla2xxx-Fix-control-flags-for-login-logout-IOCB.patch b/patches.suse/scsi-qla2xxx-Fix-control-flags-for-login-logout-IOCB.patch new file mode 100644 index 0000000..237196e --- /dev/null +++ b/patches.suse/scsi-qla2xxx-Fix-control-flags-for-login-logout-IOCB.patch @@ -0,0 +1,62 @@ +From: Himanshu Madhani +Date: Wed, 12 Feb 2020 13:44:33 -0800 +Subject: scsi: qla2xxx: Fix control flags for login/logout IOCB +Patch-mainline: v5.7-rc1 +Git-commit: 419ae5fe73e50084fa794934fb62fab34f564b7c +References: bsc#1157424 + +This patch fixes control flag options for login/logout IOCB. + +Link: https://lore.kernel.org/r/20200212214436.25532-23-hmadhani@marvell.com +Signed-off-by: Himanshu Madhani +Signed-off-by: Martin K. Petersen +Acked-by: Daniel Wagner +--- + drivers/scsi/qla2xxx/qla_iocb.c | 8 +++++--- + 1 file changed, 5 insertions(+), 3 deletions(-) + +--- a/drivers/scsi/qla2xxx/qla_iocb.c ++++ b/drivers/scsi/qla2xxx/qla_iocb.c +@@ -2362,6 +2362,8 @@ qla24xx_login_iocb(srb_t *sp, struct log + struct srb_iocb *lio = &sp->u.iocb_cmd; + + logio->entry_type = LOGINOUT_PORT_IOCB_TYPE; ++ logio->control_flags = cpu_to_le16(LCF_COMMAND_PLOGI); ++ + if (lio->u.logio.flags & SRB_LOGIN_PRLI_ONLY) { + logio->control_flags = cpu_to_le16(LCF_COMMAND_PRLI); + } else { +@@ -2941,7 +2943,6 @@ qla24xx_els_dcmd2_iocb(scsi_qla_host_t * + sp->fcport = fcport; + + elsio->timeout = qla2x00_els_dcmd2_iocb_timeout; +- init_completion(&elsio->u.els_plogi.comp); + if (wait) + sp->flags = SRB_WAKEUP_ON_COMP; + +@@ -2951,7 +2952,7 @@ qla24xx_els_dcmd2_iocb(scsi_qla_host_t * + elsio->u.els_plogi.tx_size = elsio->u.els_plogi.rx_size = DMA_POOL_SIZE; + + ptr = elsio->u.els_plogi.els_plogi_pyld = +- dma_alloc_coherent(&ha->pdev->dev, DMA_POOL_SIZE, ++ dma_alloc_coherent(&ha->pdev->dev, elsio->u.els_plogi.tx_size, + &elsio->u.els_plogi.els_plogi_pyld_dma, GFP_KERNEL); + + if (!elsio->u.els_plogi.els_plogi_pyld) { +@@ -2960,7 +2961,7 @@ qla24xx_els_dcmd2_iocb(scsi_qla_host_t * + } + + resp_ptr = elsio->u.els_plogi.els_resp_pyld = +- dma_alloc_coherent(&ha->pdev->dev, DMA_POOL_SIZE, ++ dma_alloc_coherent(&ha->pdev->dev, elsio->u.els_plogi.rx_size, + &elsio->u.els_plogi.els_resp_pyld_dma, GFP_KERNEL); + + if (!elsio->u.els_plogi.els_resp_pyld) { +@@ -2984,6 +2985,7 @@ qla24xx_els_dcmd2_iocb(scsi_qla_host_t * + (uint8_t *)elsio->u.els_plogi.els_plogi_pyld, + sizeof(*elsio->u.els_plogi.els_plogi_pyld)); + ++ init_completion(&elsio->u.els_plogi.comp); + rval = qla2x00_start_sp(sp); + if (rval != QLA_SUCCESS) { + rval = QLA_FUNCTION_FAILED; diff --git a/patches.suse/scsi-qla2xxx-Fix-qla2x00_echo_test-based-on-ISP-type.patch b/patches.suse/scsi-qla2xxx-Fix-qla2x00_echo_test-based-on-ISP-type.patch new file mode 100644 index 0000000..ac64be5 --- /dev/null +++ b/patches.suse/scsi-qla2xxx-Fix-qla2x00_echo_test-based-on-ISP-type.patch @@ -0,0 +1,36 @@ +From: Joe Carnuccio +Date: Wed, 12 Feb 2020 13:44:29 -0800 +Subject: scsi: qla2xxx: Fix qla2x00_echo_test() based on ISP type +Patch-mainline: v5.7-rc1 +Git-commit: 83cfd3dc002fc730387a1ec5fa0d4097cc31ee9f +References: bsc#1157424 + +Ths patch fixes MBX in-direction for setting right bits for +qla2x00_echo_test() + +Link: https://lore.kernel.org/r/20200212214436.25532-19-hmadhani@marvell.com +Signed-off-by: Joe Carnuccio +Signed-off-by: Himanshu Madhani +Signed-off-by: Martin K. Petersen +Acked-by: Daniel Wagner +--- + drivers/scsi/qla2xxx/qla_mbx.c | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +--- a/drivers/scsi/qla2xxx/qla_mbx.c ++++ b/drivers/scsi/qla2xxx/qla_mbx.c +@@ -5317,10 +5317,11 @@ qla2x00_echo_test(scsi_qla_host_t *vha, + mcp->out_mb |= MBX_2; + + mcp->in_mb = MBX_0; +- if (IS_QLA24XX_TYPE(ha) || IS_QLA25XX(ha) || +- IS_CNA_CAPABLE(ha) || IS_QLA2031(ha)) ++ if (IS_CNA_CAPABLE(ha) || IS_QLA24XX_TYPE(ha) || IS_QLA25XX(ha) || ++ IS_QLA2031(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha)) + mcp->in_mb |= MBX_1; +- if (IS_CNA_CAPABLE(ha) || IS_QLA2031(ha)) ++ if (IS_CNA_CAPABLE(ha) || IS_QLA2031(ha) || IS_QLA27XX(ha) || ++ IS_QLA28XX(ha)) + mcp->in_mb |= MBX_3; + + mcp->tov = MBX_TOV_SECONDS; diff --git a/patches.suse/scsi-qla2xxx-Fix-sparse-warning-reported-by-kbuild-b.patch b/patches.suse/scsi-qla2xxx-Fix-sparse-warning-reported-by-kbuild-b.patch new file mode 100644 index 0000000..41cf29b --- /dev/null +++ b/patches.suse/scsi-qla2xxx-Fix-sparse-warning-reported-by-kbuild-b.patch @@ -0,0 +1,66 @@ +From: Himanshu Madhani +Date: Thu, 27 Feb 2020 12:11:48 -0800 +Subject: scsi: qla2xxx: Fix sparse warning reported by kbuild bot +Patch-mainline: v5.7-rc1 +Git-commit: 0a36fd6cef5e3a11a273300e777a26cb26274547 +References: bsc#1157424 + +this patch fixes following sparse warnings + + >> drivers/scsi/qla2xxx/qla_tmpl.c:873:32: sparse: sparse: incorrect type in assignment (different base types) + >> drivers/scsi/qla2xxx/qla_tmpl.c:873:32: sparse: expected unsigned int [usertype] capture_timestamp + >> drivers/scsi/qla2xxx/qla_tmpl.c:873:32: sparse: got restricted __le32 [usertype] + drivers/scsi/qla2xxx/qla_tmpl.c:885:29: sparse: sparse: incorrect type in assignment (different base types) + >> drivers/scsi/qla2xxx/qla_tmpl.c:885:29: sparse: expected unsigned int + + vim +873 drivers/scsi/qla2xxx/qla_tmpl.c + + 869 + 870 static void + 871 qla27xx_time_stamp(struct qla27xx_fwdt_template *tmp) + 872 { +> 873 tmp->capture_timestamp = cpu_to_le32(jiffies); + 874 } + 875 + 876 static void + 877 qla27xx_driver_info(struct qla27xx_fwdt_template *tmp) + 878 { + 879 uint8_t v[] = { 0, 0, 0, 0, 0, 0 }; + 880 + 881 WARN_ON_ONCE(sscanf(qla2x00_version_str, + 882 "%hhu.%hhu.%hhu.%hhu.%hhu.%hhu", + 883 v+0, v+1, v+2, v+3, v+4, v+5) != 6); + 884 +> 885 tmp->driver_info[0] = cpu_to_le32( + 886 v[3] << 24 | v[2] << 16 | v[1] << 8 | v[0]); + 887 tmp->driver_info[1] = cpu_to_le32(v[5] << 8 | v[4]); + 888 tmp->driver_info[2] = __constant_cpu_to_le32(0x12345678); + 889 } + 890 + +Link: https://lore.kernel.org/r/20200227201148.13973-1-hmadhani@marvell.com +Fixes: a31056ddc665 ("scsi: qla2xxx: Use endian macros to assign static fields in fwdump header") +Reported-by: kbuild test robot +Signed-off-by: Himanshu Madhani +Signed-off-by: Martin K. Petersen +Acked-by: Daniel Wagner +--- + drivers/scsi/qla2xxx/qla_tmpl.h | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/scsi/qla2xxx/qla_tmpl.h ++++ b/drivers/scsi/qla2xxx/qla_tmpl.h +@@ -18,11 +18,11 @@ struct __packed qla27xx_fwdt_template { + + __le32 entry_count; + uint32_t template_version; +- uint32_t capture_timestamp; ++ __le32 capture_timestamp; + uint32_t template_checksum; + + uint32_t reserved_2; +- uint32_t driver_info[3]; ++ __le32 driver_info[3]; + + uint32_t saved_state[16]; + diff --git a/patches.suse/scsi-qla2xxx-Fix-sparse-warnings-triggered-by-the-PC.patch b/patches.suse/scsi-qla2xxx-Fix-sparse-warnings-triggered-by-the-PC.patch new file mode 100644 index 0000000..4a58717 --- /dev/null +++ b/patches.suse/scsi-qla2xxx-Fix-sparse-warnings-triggered-by-the-PC.patch @@ -0,0 +1,70 @@ +From: Bart Van Assche +Date: Wed, 19 Feb 2020 20:34:39 -0800 +Subject: scsi: qla2xxx: Fix sparse warnings triggered by the PCI state + checking code +Patch-mainline: v5.7-rc1 +Git-commit: 471298cab82d255e358901ea5baff24abe1a53b8 +References: bsc#1157424 + +This patch fixes the following sparse warnings: + +drivers/scsi/qla2xxx/qla_mbx.c:120:21: warning: restricted pci_channel_state_t degrades to integer +drivers/scsi/qla2xxx/qla_mbx.c:120:37: warning: restricted pci_channel_state_t degrades to integer + +>From include/linux/pci.h: + +enum pci_channel_state { + /* I/O channel is in normal state */ + pci_channel_io_normal = (__force pci_channel_state_t) 1, + + /* I/O to channel is blocked */ + pci_channel_io_frozen = (__force pci_channel_state_t) 2, + + /* PCI card is dead */ + pci_channel_io_perm_failure = (__force pci_channel_state_t) 3, +}; + +Link: https://lore.kernel.org/r/20200220043441.20504-4-bvanassche@acm.org +Cc: Roman Bolshakov +Cc: Martin Wilck +Cc: Quinn Tran +Reviewed-by: Daniel Wagner +Reviewed-by: Roman Bolshakov +Acked-by: Himanshu Madhani +Signed-off-by: Bart Van Assche +Signed-off-by: Martin K. Petersen +--- + drivers/scsi/qla2xxx/qla_mbx.c | 5 ++--- + drivers/scsi/qla2xxx/qla_mr.c | 5 ++--- + 2 files changed, 4 insertions(+), 6 deletions(-) + +--- a/drivers/scsi/qla2xxx/qla_mbx.c ++++ b/drivers/scsi/qla2xxx/qla_mbx.c +@@ -117,10 +117,9 @@ qla2x00_mailbox_command(scsi_qla_host_t + + ql_dbg(ql_dbg_mbx, vha, 0x1000, "Entered %s.\n", __func__); + +- if (ha->pdev->error_state > pci_channel_io_frozen) { ++ if (ha->pdev->error_state == pci_channel_io_perm_failure) { + ql_log(ql_log_warn, vha, 0x1001, +- "error_state is greater than pci_channel_io_frozen, " +- "exiting.\n"); ++ "PCI channel failed permanently, exiting.\n"); + return QLA_FUNCTION_TIMEOUT; + } + +--- a/drivers/scsi/qla2xxx/qla_mr.c ++++ b/drivers/scsi/qla2xxx/qla_mr.c +@@ -53,10 +53,9 @@ qlafx00_mailbox_command(scsi_qla_host_t + struct qla_hw_data *ha = vha->hw; + scsi_qla_host_t *base_vha = pci_get_drvdata(ha->pdev); + +- if (ha->pdev->error_state > pci_channel_io_frozen) { ++ if (ha->pdev->error_state == pci_channel_io_perm_failure) { + ql_log(ql_log_warn, vha, 0x115c, +- "error_state is greater than pci_channel_io_frozen, " +- "exiting.\n"); ++ "PCI channel failed permanently, exiting.\n"); + return QLA_FUNCTION_TIMEOUT; + } + diff --git a/patches.suse/scsi-qla2xxx-Fix-unbound-NVME-response-length.patch b/patches.suse/scsi-qla2xxx-Fix-unbound-NVME-response-length.patch index 2beec4c..2dcdf3a 100644 --- a/patches.suse/scsi-qla2xxx-Fix-unbound-NVME-response-length.patch +++ b/patches.suse/scsi-qla2xxx-Fix-unbound-NVME-response-length.patch @@ -1,10 +1,11 @@ +From 00fe717ee1ea3c2979db4f94b1533c57aed8dea9 Mon Sep 17 00:00:00 2001 From: Arun Easi Date: Thu, 23 Jan 2020 20:50:14 -0800 -Subject: scsi: qla2xxx: Fix unbound NVME response length -Patch-mainline: Queued in subsystem maintainer repository -Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/mkp/scsi.git -Git-commit: 538e574b23489452ab06f61e83c1f6b5f984ab7e +Subject: [PATCH] scsi: qla2xxx: Fix unbound NVME response length + References: bsc#1157966 bsc#1158013 bsc#1157424 +Patch-mainline: v5.6-rc1 +Git-commit: 00fe717ee1ea3c2979db4f94b1533c57aed8dea9 On certain cases when response length is less than 32, NVME response data is supplied inline in IOCB. This is indicated by some combination of state @@ -21,14 +22,16 @@ Reviewed-by: Ewan D. Milne Signed-off-by: Martin K. Petersen Acked-by: Daniel Wagner --- - drivers/scsi/qla2xxx/qla_dbg.c | 6 ------ - drivers/scsi/qla2xxx/qla_dbg.h | 6 ++++++ - drivers/scsi/qla2xxx/qla_isr.c | 12 ++++++++++++ + drivers/scsi/qla2xxx/qla_dbg.c | 6 ------ + drivers/scsi/qla2xxx/qla_dbg.h | 6 ++++++ + drivers/scsi/qla2xxx/qla_isr.c | 12 ++++++++++++ 3 files changed, 18 insertions(+), 6 deletions(-) +diff --git a/drivers/scsi/qla2xxx/qla_dbg.c b/drivers/scsi/qla2xxx/qla_dbg.c +index e5500bba06ca..88a56e8480f7 100644 --- a/drivers/scsi/qla2xxx/qla_dbg.c +++ b/drivers/scsi/qla2xxx/qla_dbg.c -@@ -2519,12 +2519,6 @@ qla83xx_fw_dump_failed: +@@ -2519,12 +2519,6 @@ qla83xx_fw_dump(scsi_qla_host_t *vha, int hardware_locked) /* Driver Debug Functions. */ /****************************************************************************/ @@ -41,9 +44,11 @@ Acked-by: Daniel Wagner /* * This function is for formatting and logging debug information. * It is to be used when vha is available. It formats the message +diff --git a/drivers/scsi/qla2xxx/qla_dbg.h b/drivers/scsi/qla2xxx/qla_dbg.h +index bb01b680ce9f..433e95502808 100644 --- a/drivers/scsi/qla2xxx/qla_dbg.h +++ b/drivers/scsi/qla2xxx/qla_dbg.h -@@ -374,3 +374,9 @@ extern int qla24xx_dump_ram(struct qla_h +@@ -374,3 +374,9 @@ extern int qla24xx_dump_ram(struct qla_hw_data *, uint32_t, uint32_t *, extern void qla24xx_pause_risc(struct device_reg_24xx __iomem *, struct qla_hw_data *); extern int qla24xx_soft_reset(struct qla_hw_data *); @@ -53,9 +58,11 @@ Acked-by: Daniel Wagner +{ + return (level & ql2xextended_error_logging) == level; +} +diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c +index e7bad0bfffda..e40705d38cea 100644 --- a/drivers/scsi/qla2xxx/qla_isr.c +++ b/drivers/scsi/qla2xxx/qla_isr.c -@@ -1939,6 +1939,18 @@ static void qla24xx_nvme_iocb_entry(scsi +@@ -1939,6 +1939,18 @@ static void qla24xx_nvme_iocb_entry(scsi_qla_host_t *vha, struct req_que *req, inbuf = (uint32_t *)&sts->nvme_ersp_data; outbuf = (uint32_t *)fd->rspaddr; iocb->u.nvme.rsp_pyld_len = le16_to_cpu(sts->nvme_rsp_pyld_len); @@ -74,3 +81,6 @@ Acked-by: Daniel Wagner iter = iocb->u.nvme.rsp_pyld_len >> 2; for (; iter; iter--) *outbuf++ = swab32(*inbuf++); +-- +2.23.0 + diff --git a/patches.suse/scsi-qla2xxx-Force-semaphore-on-flash-validation-fai.patch b/patches.suse/scsi-qla2xxx-Force-semaphore-on-flash-validation-fai.patch new file mode 100644 index 0000000..6eaff15 --- /dev/null +++ b/patches.suse/scsi-qla2xxx-Force-semaphore-on-flash-validation-fai.patch @@ -0,0 +1,64 @@ +From: Quinn Tran +Date: Wed, 26 Feb 2020 14:40:15 -0800 +Subject: scsi: qla2xxx: Force semaphore on flash validation failure +Patch-mainline: v5.7-rc1 +Git-commit: cad9c2d28ec69f1d0370b2ba5abe309b0b709be4 +References: bsc#1157424 + +For single port 28XX adapter, the second core can still run in the +background. The flash semaphore can be held by the non-active core. +This patch tell MPI FW to check for this case and clear the semaphore +from the non-active core. + +Link: https://lore.kernel.org/r/20200226224022.24518-12-hmadhani@marvell.com +Signed-off-by: Himanshu Madhani +Signed-off-by: Quinn Tran +Signed-off-by: Martin K. Petersen +Acked-by: Daniel Wagner +--- + drivers/scsi/qla2xxx/qla_mbx.c | 16 ++++++++++++++++ + 1 file changed, 16 insertions(+) + +--- a/drivers/scsi/qla2xxx/qla_mbx.c ++++ b/drivers/scsi/qla2xxx/qla_mbx.c +@@ -666,10 +666,14 @@ qla2x00_execute_fw(scsi_qla_host_t *vha, + struct qla_hw_data *ha = vha->hw; + mbx_cmd_t mc; + mbx_cmd_t *mcp = &mc; ++ u8 semaphore = 0; ++#define EXE_FW_FORCE_SEMAPHORE BIT_7 ++ u8 retry = 3; + + ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1025, + "Entered %s.\n", __func__); + ++again: + mcp->mb[0] = MBC_EXECUTE_FIRMWARE; + mcp->out_mb = MBX_0; + mcp->in_mb = MBX_0; +@@ -711,6 +715,9 @@ qla2x00_execute_fw(scsi_qla_host_t *vha, + if (ha->flags.exchoffld_enabled) + mcp->mb[4] |= ENABLE_EXCHANGE_OFFLD; + ++ if (semaphore) ++ mcp->mb[11] |= EXE_FW_FORCE_SEMAPHORE; ++ + mcp->out_mb |= MBX_4 | MBX_3 | MBX_2 | MBX_1 | MBX_11; + mcp->in_mb |= MBX_3 | MBX_2 | MBX_1; + } else { +@@ -727,6 +734,15 @@ qla2x00_execute_fw(scsi_qla_host_t *vha, + rval = qla2x00_mailbox_command(vha, mcp); + + if (rval != QLA_SUCCESS) { ++ if (IS_QLA28XX(ha) && rval == QLA_COMMAND_ERROR && ++ mcp->mb[1] == 0x27 && retry) { ++ semaphore = 1; ++ retry--; ++ ql_dbg(ql_dbg_async, vha, 0x1026, ++ "Exe FW: force semaphore.\n"); ++ goto again; ++ } ++ + ql_dbg(ql_dbg_mbx, vha, 0x1026, + "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]); + return rval; diff --git a/patches.suse/scsi-qla2xxx-Handle-NVME-status-iocb-correctly.patch b/patches.suse/scsi-qla2xxx-Handle-NVME-status-iocb-correctly.patch new file mode 100644 index 0000000..f0fee4d --- /dev/null +++ b/patches.suse/scsi-qla2xxx-Handle-NVME-status-iocb-correctly.patch @@ -0,0 +1,101 @@ +From: Arun Easi +Date: Wed, 26 Feb 2020 14:40:20 -0800 +Subject: scsi: qla2xxx: Handle NVME status iocb correctly +Patch-mainline: v5.7-rc1 +Git-commit: 3d582b34992ba2fe4065f01019f0c08d12916faa +References: bsc#1157424 + +Certain state flags bit combinations are not checked and not handled +correctly. Plus, do not log a normal underrun situation where there is +no frame drop. + +Link: https://lore.kernel.org/r/20200226224022.24518-17-hmadhani@marvell.com +Signed-off-by: Himanshu Madhani +Signed-off-by: Arun Easi +Signed-off-by: Martin K. Petersen +Acked-by: Daniel Wagner +--- + drivers/scsi/qla2xxx/qla_isr.c | 47 ++++++++++++++++++++++++++++++++++------- + 1 file changed, 39 insertions(+), 8 deletions(-) + +--- a/drivers/scsi/qla2xxx/qla_isr.c ++++ b/drivers/scsi/qla2xxx/qla_isr.c +@@ -2064,6 +2064,7 @@ static void qla24xx_nvme_iocb_entry(scsi + struct nvmefc_fcp_req *fd; + uint16_t ret = QLA_SUCCESS; + uint16_t comp_status = le16_to_cpu(sts->comp_status); ++ int logit = 0; + + iocb = &sp->u.iocb_cmd; + fcport = sp->fcport; +@@ -2074,6 +2075,12 @@ static void qla24xx_nvme_iocb_entry(scsi + if (unlikely(iocb->u.nvme.aen_op)) + atomic_dec(&sp->vha->hw->nvme_active_aen_cnt); + ++ if (unlikely(comp_status != CS_COMPLETE)) ++ logit = 1; ++ ++ fd->transferred_length = fd->payload_length - ++ le32_to_cpu(sts->residual_len); ++ + /* + * State flags: Bit 6 and 0. + * If 0 is set, we don't care about 6. +@@ -2084,8 +2091,20 @@ static void qla24xx_nvme_iocb_entry(scsi + */ + if (!(state_flags & (SF_FCP_RSP_DMA | SF_NVME_ERSP))) { + iocb->u.nvme.rsp_pyld_len = 0; +- } else if ((state_flags & SF_FCP_RSP_DMA)) { ++ } else if ((state_flags & (SF_FCP_RSP_DMA | SF_NVME_ERSP)) == ++ (SF_FCP_RSP_DMA | SF_NVME_ERSP)) { ++ /* Response already DMA'd to fd->rspaddr. */ + iocb->u.nvme.rsp_pyld_len = le16_to_cpu(sts->nvme_rsp_pyld_len); ++ } else if ((state_flags & SF_FCP_RSP_DMA)) { ++ /* ++ * Non-zero value in first 12 bytes of NVMe_RSP IU, treat this ++ * as an error. ++ */ ++ iocb->u.nvme.rsp_pyld_len = 0; ++ fd->transferred_length = 0; ++ ql_dbg(ql_dbg_io, fcport->vha, 0x307a, ++ "Unexpected values in NVMe_RSP IU.\n"); ++ logit = 1; + } else if (state_flags & SF_NVME_ERSP) { + uint32_t *inbuf, *outbuf; + uint16_t iter; +@@ -2096,16 +2115,28 @@ static void qla24xx_nvme_iocb_entry(scsi + iter = iocb->u.nvme.rsp_pyld_len >> 2; + for (; iter; iter--) + *outbuf++ = swab32(*inbuf++); +- } else { /* unhandled case */ +- ql_log(ql_log_warn, fcport->vha, 0x503a, +- "NVME-%s error. Unhandled state_flags of %x\n", +- sp->name, state_flags); + } + +- fd->transferred_length = fd->payload_length - +- le32_to_cpu(sts->residual_len); ++ if (state_flags & SF_NVME_ERSP) { ++ struct nvme_fc_ersp_iu *rsp_iu = fd->rspaddr; ++ u32 tgt_xfer_len; ++ ++ tgt_xfer_len = be32_to_cpu(rsp_iu->xfrd_len); ++ if (fd->transferred_length != tgt_xfer_len) { ++ ql_dbg(ql_dbg_io, fcport->vha, 0x3079, ++ "Dropped frame(s) detected (sent/rcvd=%u/%u).\n", ++ tgt_xfer_len, fd->transferred_length); ++ logit = 1; ++ } else if (comp_status == CS_DATA_UNDERRUN) { ++ /* ++ * Do not log if this is just an underflow and there ++ * is no data loss. ++ */ ++ logit = 0; ++ } ++ } + +- if (unlikely(comp_status != CS_COMPLETE)) ++ if (unlikely(logit)) + ql_log(ql_log_warn, fcport->vha, 0x5060, + "NVME-%s ERR Handling - hdl=%x status(%x) tr_len:%x resid=%x ox_id=%x\n", + sp->name, sp->handle, comp_status, diff --git a/patches.suse/scsi-qla2xxx-Handle-cases-for-limiting-RDP-response-.patch b/patches.suse/scsi-qla2xxx-Handle-cases-for-limiting-RDP-response-.patch new file mode 100644 index 0000000..d1a6914 --- /dev/null +++ b/patches.suse/scsi-qla2xxx-Handle-cases-for-limiting-RDP-response-.patch @@ -0,0 +1,108 @@ +From: Joe Carnuccio +Date: Wed, 12 Feb 2020 13:44:25 -0800 +Subject: scsi: qla2xxx: Handle cases for limiting RDP response payload length +Patch-mainline: v5.7-rc1 +Git-commit: 4879237cd28eebb9350a7e6d970677997abe2b9d +References: bsc#1157424 + +This patch reduces RDP response payload length, if requesting port is a +domain controller (sid 0xfffc01) and fw is earlier than 8.09.00 and fw is +not 8.05.65 then limit the RDP response payload length to maximum of 256 +bytes by terminating the response just before the optical element +descriptor. + +Link: https://lore.kernel.org/r/20200212214436.25532-15-hmadhani@marvell.com +Signed-off-by: Himanshu Madhani +Signed-off-by: Joe Carnuccio +Signed-off-by: Martin K. Petersen +Acked-by: Daniel Wagner +--- + drivers/scsi/qla2xxx/qla_os.c | 42 ++++++++++++++++++++++++++++++++++++++++-- + 1 file changed, 40 insertions(+), 2 deletions(-) + +--- a/drivers/scsi/qla2xxx/qla_os.c ++++ b/drivers/scsi/qla2xxx/qla_os.c +@@ -5782,6 +5782,32 @@ retry_lock: + return; + } + ++static bool ++qla25xx_rdp_rsp_reduce_size(struct scsi_qla_host *vha, ++ struct purex_entry_24xx *purex) ++{ ++ char fwstr[16]; ++ u32 sid = purex->s_id[2] << 16 | purex->s_id[1] << 8 | purex->s_id[0]; ++ ++ /* Domain Controller is always logged-out. */ ++ /* if RDP request is not from Domain Controller: */ ++ if (sid != 0xfffc01) ++ return false; ++ ++ ql_dbg(ql_dbg_init, vha, 0x0181, "%s: s_id=%#x\n", __func__, sid); ++ ++ vha->hw->isp_ops->fw_version_str(vha, fwstr, sizeof(fwstr)); ++ fwstr[strcspn(fwstr, " ")] = 0; ++ /* if FW version allows RDP response length upto 2048 bytes: */ ++ if (strcmp(fwstr, "8.09.00") > 0 || strcmp(fwstr, "8.05.65") == 0) ++ return false; ++ ++ ql_dbg(ql_dbg_init, vha, 0x0181, "%s: fw=%s\n", __func__, fwstr); ++ ++ /* RDP response length is to be reduced to maximum 256 bytes */ ++ return true; ++} ++ + static uint + qla25xx_rdp_port_speed_capability(struct qla_hw_data *ha) + { +@@ -5900,6 +5926,7 @@ void qla24xx_process_purex_rdp(struct sc + struct buffer_credit_24xx *bbc = NULL; + uint8_t *sfp = NULL; + uint16_t sfp_flags = 0; ++ uint rsp_payload_length = sizeof(*rsp_payload); + int rval; + + ql_dbg(ql_dbg_init + ql_dbg_verbose, vha, 0x0180, +@@ -5910,6 +5937,14 @@ void qla24xx_process_purex_rdp(struct sc + ql_dump_buffer(ql_dbg_init + ql_dbg_verbose, vha, 0x0182, + (void *)purex, sizeof(*purex)); + ++ if (qla25xx_rdp_rsp_reduce_size(vha, purex)) { ++ rsp_payload_length = ++ offsetof(typeof(*rsp_payload), optical_elmt_desc); ++ ql_dbg(ql_dbg_init, vha, 0x0181, ++ "Reducing RSP payload length to %u bytes...\n", ++ rsp_payload_length); ++ } ++ + rsp_els = dma_alloc_coherent(&ha->pdev->dev, sizeof(*rsp_els), + &rsp_els_dma, GFP_KERNEL); + if (!rsp_els) { +@@ -5956,7 +5991,7 @@ void qla24xx_process_purex_rdp(struct sc + + rsp_els->control_flags = EPD_ELS_ACC; + rsp_els->rx_byte_count = 0; +- rsp_els->tx_byte_count = cpu_to_le32(sizeof(*rsp_payload)); ++ rsp_els->tx_byte_count = cpu_to_le32(rsp_payload_length); + + put_unaligned_le64(rsp_payload_dma, &rsp_els->tx_address); + rsp_els->tx_len = rsp_els->tx_byte_count; +@@ -6131,6 +6166,9 @@ accept: + } + } + ++ if (rsp_payload_length < sizeof(*rsp_payload)) ++ goto send; ++ + if (sfp) { + memset(sfp, 0, SFP_RTDI_LEN); + rval = qla2x00_read_sfp(vha, sfp_dma, sfp, 0xa2, 0, 64, 0); +@@ -6291,7 +6329,7 @@ send: + ql_dbg(ql_dbg_init + ql_dbg_verbose, vha, 0x0186, + "-------- ELS RSP PAYLOAD -------\n"); + ql_dump_buffer(ql_dbg_init + ql_dbg_verbose, vha, 0x0187, +- (void *)rsp_payload, rsp_els->tx_byte_count); ++ (void *)rsp_payload, rsp_payload_length); + + rval = qla2x00_issue_iocb(vha, rsp_els, rsp_els_dma, 0); + diff --git a/patches.suse/scsi-qla2xxx-Improved-secure-flash-support-messages.patch b/patches.suse/scsi-qla2xxx-Improved-secure-flash-support-messages.patch new file mode 100644 index 0000000..7bccf0c --- /dev/null +++ b/patches.suse/scsi-qla2xxx-Improved-secure-flash-support-messages.patch @@ -0,0 +1,56 @@ +From: Michael Hernandez +Date: Wed, 26 Feb 2020 14:40:09 -0800 +Subject: scsi: qla2xxx: Improved secure flash support messages +Patch-mainline: v5.7-rc1 +Git-commit: 4ba836f686284ef1eab0cf7a8f3402e24e6dc4cd +References: bsc#1157424 + +This patch improved message for Secure Flash support. No +functionality has been changed. + +Link: https://lore.kernel.org/r/20200226224022.24518-6-hmadhani@marvell.com +Signed-off-by: Himanshu Madhani +Signed-off-by: Michael Hernandez +Signed-off-by: Martin K. Petersen +Acked-by: Daniel Wagner +--- + drivers/scsi/qla2xxx/qla_init.c | 6 +++--- + drivers/scsi/qla2xxx/qla_mbx.c | 10 ++++++---- + 2 files changed, 9 insertions(+), 7 deletions(-) + +--- a/drivers/scsi/qla2xxx/qla_init.c ++++ b/drivers/scsi/qla2xxx/qla_init.c +@@ -2221,10 +2221,10 @@ qla2x00_initialize_adapter(scsi_qla_host + + /* Check for secure flash support */ + if (IS_QLA28XX(ha)) { +- if (RD_REG_DWORD(®->mailbox12) & BIT_0) { +- ql_log(ql_log_info, vha, 0xffff, "Adapter is Secure\n"); ++ if (RD_REG_DWORD(®->mailbox12) & BIT_0) + ha->flags.secure_adapter = 1; +- } ++ ql_log(ql_log_info, vha, 0xffff, "Secure Adapter: %s\n", ++ (ha->flags.secure_adapter) ? "Yes" : "No"); + } + + +--- a/drivers/scsi/qla2xxx/qla_mbx.c ++++ b/drivers/scsi/qla2xxx/qla_mbx.c +@@ -1135,11 +1135,13 @@ qla2x00_get_fw_version(scsi_qla_host_t * + ha->fw_ddr_ram_start = (mcp->mb[23] << 16) | mcp->mb[22]; + ha->fw_ddr_ram_end = (mcp->mb[25] << 16) | mcp->mb[24]; + if (IS_QLA28XX(ha)) { +- if (mcp->mb[16] & BIT_10) { +- ql_log(ql_log_info, vha, 0xffff, +- "FW support secure flash updates\n"); ++ if (mcp->mb[16] & BIT_10) + ha->flags.secure_fw = 1; +- } ++ ++ ql_log(ql_log_info, vha, 0xffff, ++ "Secure Flash Update in FW: %s\n", ++ (ha->flags.secure_fw) ? "Supported" : ++ "Not Supported"); + } + } + diff --git a/patches.suse/scsi-qla2xxx-Move-free-of-fcport-out-of-interrupt-co.patch b/patches.suse/scsi-qla2xxx-Move-free-of-fcport-out-of-interrupt-co.patch new file mode 100644 index 0000000..4fdcb14 --- /dev/null +++ b/patches.suse/scsi-qla2xxx-Move-free-of-fcport-out-of-interrupt-co.patch @@ -0,0 +1,48 @@ +From: Joe Carnuccio +Date: Wed, 12 Feb 2020 13:44:13 -0800 +Subject: scsi: qla2xxx: Move free of fcport out of interrupt context +Patch-mainline: v5.7-rc1 +Git-commit: 054f4382417098b4d0028f8145fa214d448792d7 +References: bsc#1157424 + +This patch moves freeing of fcport out of interrupt context. + +Link: https://lore.kernel.org/r/20200212214436.25532-3-hmadhani@marvell.com +Signed-off-by: Joe Carnuccio +Signed-off-by: Himanshu Madhani +Signed-off-by: Martin K. Petersen +Acked-by: Daniel Wagner +--- + drivers/scsi/qla2xxx/qla_bsg.c | 14 ++++++++++++-- + 1 file changed, 12 insertions(+), 2 deletions(-) + +--- a/drivers/scsi/qla2xxx/qla_bsg.c ++++ b/drivers/scsi/qla2xxx/qla_bsg.c +@@ -11,6 +11,14 @@ + #include + #include + ++static void qla2xxx_free_fcport_work(struct work_struct *work) ++{ ++ struct fc_port *fcport = container_of(work, typeof(*fcport), ++ free_work); ++ ++ qla2x00_free_fcport(fcport); ++} ++ + /* BSG support for ELS/CT pass through */ + void qla2x00_bsg_job_done(srb_t *sp, int res) + { +@@ -53,8 +61,10 @@ void qla2x00_bsg_sp_free(srb_t *sp) + + if (sp->type == SRB_CT_CMD || + sp->type == SRB_FXIOCB_BCMD || +- sp->type == SRB_ELS_CMD_HST) +- qla2x00_free_fcport(sp->fcport); ++ sp->type == SRB_ELS_CMD_HST) { ++ INIT_WORK(&sp->fcport->free_work, qla2xxx_free_fcport_work); ++ queue_work(ha->wq, &sp->fcport->free_work); ++ } + + qla2x00_rel_sp(sp); + } diff --git a/patches.suse/scsi-qla2xxx-Print-portname-for-logging-in-qla24xx_l.patch b/patches.suse/scsi-qla2xxx-Print-portname-for-logging-in-qla24xx_l.patch new file mode 100644 index 0000000..9edbd7e --- /dev/null +++ b/patches.suse/scsi-qla2xxx-Print-portname-for-logging-in-qla24xx_l.patch @@ -0,0 +1,50 @@ +From: Joe Carnuccio +Date: Wed, 12 Feb 2020 13:44:30 -0800 +Subject: scsi: qla2xxx: Print portname for logging in qla24xx_logio_entry() +Patch-mainline: v5.7-rc1 +Git-commit: cbe729a63d5a2c5909c6ae7e54665059496e43b9 +References: bsc#1157424 + +Add port name in the messages file to help debugging of Login/Logout IOCBs + +Link: https://lore.kernel.org/r/20200212214436.25532-20-hmadhani@marvell.com +Signed-off-by: Joe Carnuccio +Signed-off-by: Himanshu Madhani +Signed-off-by: Martin K. Petersen +Acked-by: Daniel Wagner +--- + drivers/scsi/qla2xxx/qla_isr.c | 16 ++++++---------- + 1 file changed, 6 insertions(+), 10 deletions(-) + +--- a/drivers/scsi/qla2xxx/qla_isr.c ++++ b/drivers/scsi/qla2xxx/qla_isr.c +@@ -1899,11 +1899,9 @@ qla24xx_logio_entry(scsi_qla_host_t *vha + } + + if (le16_to_cpu(logio->comp_status) == CS_COMPLETE) { +- ql_dbg(ql_dbg_async, fcport->vha, 0x5036, +- "Async-%s complete - %8phC hdl=%x portid=%02x%02x%02x " +- "iop0=%x.\n", type, fcport->port_name, sp->handle, +- fcport->d_id.b.domain, +- fcport->d_id.b.area, fcport->d_id.b.al_pa, ++ ql_dbg(ql_dbg_async, sp->vha, 0x5036, ++ "Async-%s complete: handle=%x pid=%06x wwpn=%8phC iop0=%x\n", ++ type, sp->handle, fcport->d_id.b24, fcport->port_name, + le32_to_cpu(logio->io_parameter[0])); + + vha->hw->exch_starvation = 0; +@@ -1982,11 +1980,9 @@ qla24xx_logio_entry(scsi_qla_host_t *vha + break; + } + +- ql_dbg(ql_dbg_async, fcport->vha, 0x5037, +- "Async-%s failed - %8phC hdl=%x portid=%02x%02x%02x comp=%x " +- "iop0=%x iop1=%x.\n", type, fcport->port_name, +- sp->handle, fcport->d_id.b.domain, +- fcport->d_id.b.area, fcport->d_id.b.al_pa, ++ ql_dbg(ql_dbg_async, sp->vha, 0x5037, ++ "Async-%s failed: handle=%x pid=%06x wwpn=%8phC comp_status=%x iop0=%x iop1=%x\n", ++ type, sp->handle, fcport->d_id.b24, fcport->port_name, + le16_to_cpu(logio->comp_status), + le32_to_cpu(logio->io_parameter[0]), + le32_to_cpu(logio->io_parameter[1])); diff --git a/patches.suse/scsi-qla2xxx-Remove-restriction-of-FC-T10-PI-and-FC-.patch b/patches.suse/scsi-qla2xxx-Remove-restriction-of-FC-T10-PI-and-FC-.patch new file mode 100644 index 0000000..f80230f --- /dev/null +++ b/patches.suse/scsi-qla2xxx-Remove-restriction-of-FC-T10-PI-and-FC-.patch @@ -0,0 +1,33 @@ +From: Quinn Tran +Date: Wed, 26 Feb 2020 14:40:19 -0800 +Subject: scsi: qla2xxx: Remove restriction of FC T10-PI and FC-NVMe +Patch-mainline: v5.7-rc1 +Git-commit: 3e4615a292b47632d409f0d53a23da85e039b031 +References: bsc#1157424 + +T10-PI and FC-NVMe are not mutually exclusive. This patch removes +restrictions where if FC-NVMe is enabled T10-PI defaults to disabled. + +Link: https://lore.kernel.org/r/20200226224022.24518-16-hmadhani@marvell.com +Signed-off-by: Himanshu Madhani +Signed-off-by: Quinn Tran +Signed-off-by: Martin K. Petersen +Acked-by: Daniel Wagner +--- + drivers/scsi/qla2xxx/qla_os.c | 4 ---- + 1 file changed, 4 deletions(-) + +--- a/drivers/scsi/qla2xxx/qla_os.c ++++ b/drivers/scsi/qla2xxx/qla_os.c +@@ -123,11 +123,7 @@ MODULE_PARM_DESC(ql2xmaxqdepth, + "Maximum queue depth to set for each LUN. " + "Default is 64."); + +-#if (IS_ENABLED(CONFIG_NVME_FC)) +-int ql2xenabledif; +-#else + int ql2xenabledif = 2; +-#endif + module_param(ql2xenabledif, int, S_IRUGO); + MODULE_PARM_DESC(ql2xenabledif, + " Enable T10-CRC-DIF:\n" diff --git a/patches.suse/scsi-qla2xxx-Return-appropriate-failure-through-BSG-.patch b/patches.suse/scsi-qla2xxx-Return-appropriate-failure-through-BSG-.patch new file mode 100644 index 0000000..cfc496d --- /dev/null +++ b/patches.suse/scsi-qla2xxx-Return-appropriate-failure-through-BSG-.patch @@ -0,0 +1,81 @@ +From: Michael Hernandez +Date: Wed, 26 Feb 2020 14:40:10 -0800 +Subject: scsi: qla2xxx: Return appropriate failure through BSG Interface +Patch-mainline: v5.7-rc1 +Git-commit: 1b81e7f3019d632a707e07927e946ffbbc102910 +References: bsc#1157424 + +This patch ensures flash updates API calls return possible failure +status through BSG interface to the application. + +Link: https://lore.kernel.org/r/20200226224022.24518-7-hmadhani@marvell.com +Signed-off-by: Himanshu Madhani +Signed-off-by: Michael Hernandez +Signed-off-by: Martin K. Petersen +Acked-by: Daniel Wagner +--- + drivers/scsi/qla2xxx/qla_bsg.c | 9 +++++++-- + drivers/scsi/qla2xxx/qla_sup.c | 13 ++++++++----- + 2 files changed, 15 insertions(+), 7 deletions(-) + +--- a/drivers/scsi/qla2xxx/qla_bsg.c ++++ b/drivers/scsi/qla2xxx/qla_bsg.c +@@ -1517,10 +1517,15 @@ qla2x00_update_optrom(struct bsg_job *bs + bsg_job->request_payload.sg_cnt, ha->optrom_buffer, + ha->optrom_region_size); + +- ha->isp_ops->write_optrom(vha, ha->optrom_buffer, ++ rval = ha->isp_ops->write_optrom(vha, ha->optrom_buffer, + ha->optrom_region_start, ha->optrom_region_size); + +- bsg_reply->result = DID_OK; ++ if (rval) { ++ bsg_reply->result = -EINVAL; ++ rval = -EINVAL; ++ } else { ++ bsg_reply->result = DID_OK; ++ } + vfree(ha->optrom_buffer); + ha->optrom_buffer = NULL; + ha->optrom_state = QLA_SWAITING; +--- a/drivers/scsi/qla2xxx/qla_sup.c ++++ b/drivers/scsi/qla2xxx/qla_sup.c +@@ -2683,7 +2683,7 @@ qla28xx_write_flash_data(scsi_qla_host_t + uint32_t sec_mask, rest_addr, fdata; + void *optrom = NULL; + dma_addr_t optrom_dma; +- int rval; ++ int rval, ret; + struct secure_flash_update_block *sfub; + dma_addr_t sfub_dma; + uint32_t offset = faddr << 2; +@@ -2939,11 +2939,12 @@ qla28xx_write_flash_data(scsi_qla_host_t + write_protect: + ql_log(ql_log_warn + ql_dbg_verbose, vha, 0x7095, + "Protect flash...\n"); +- rval = qla24xx_protect_flash(vha); +- if (rval) { ++ ret = qla24xx_protect_flash(vha); ++ if (ret) { + qla81xx_fac_semaphore_access(vha, FAC_SEMAPHORE_UNLOCK); + ql_log(ql_log_warn, vha, 0x7099, + "Failed protect flash\n"); ++ rval = QLA_COMMAND_ERROR; + } + + if (reset_to_rom == true) { +@@ -2951,10 +2952,12 @@ write_protect: + set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags); + qla2xxx_wake_dpc(vha); + +- rval = qla2x00_wait_for_hba_online(vha); +- if (rval != QLA_SUCCESS) ++ ret = qla2x00_wait_for_hba_online(vha); ++ if (ret != QLA_SUCCESS) { + ql_log(ql_log_warn, vha, 0xffff, + "Adapter did not come out of reset\n"); ++ rval = QLA_COMMAND_ERROR; ++ } + } + + done: diff --git a/patches.suse/scsi-qla2xxx-Save-rscn_gen-for-new-fcport.patch b/patches.suse/scsi-qla2xxx-Save-rscn_gen-for-new-fcport.patch new file mode 100644 index 0000000..8c6795b --- /dev/null +++ b/patches.suse/scsi-qla2xxx-Save-rscn_gen-for-new-fcport.patch @@ -0,0 +1,27 @@ +From: Himanshu Madhani +Date: Wed, 12 Feb 2020 13:44:32 -0800 +Subject: scsi: qla2xxx: Save rscn_gen for new fcport +Patch-mainline: v5.7-rc1 +Git-commit: d26a8982c9bd92ce3596eb4f86e922cdaf6751e5 +References: bsc#1157424 + +Add missing rscn_gen when creating new fcport. + +Link: https://lore.kernel.org/r/20200212214436.25532-22-hmadhani@marvell.com +Signed-off-by: Himanshu Madhani +Signed-off-by: Martin K. Petersen +Acked-by: Daniel Wagner +--- + drivers/scsi/qla2xxx/qla_gs.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/scsi/qla2xxx/qla_gs.c ++++ b/drivers/scsi/qla2xxx/qla_gs.c +@@ -3487,6 +3487,7 @@ void qla24xx_async_gnnft_done(scsi_qla_h + if (memcmp(rp->port_name, fcport->port_name, WWN_SIZE)) + continue; + fcport->scan_state = QLA_FCPORT_FOUND; ++ fcport->last_rscn_gen = fcport->rscn_gen; + found = true; + /* + * If device was not a fabric device before. diff --git a/patches.suse/scsi-qla2xxx-Serialize-fc_port-alloc-in-N2N.patch b/patches.suse/scsi-qla2xxx-Serialize-fc_port-alloc-in-N2N.patch new file mode 100644 index 0000000..b9559ef --- /dev/null +++ b/patches.suse/scsi-qla2xxx-Serialize-fc_port-alloc-in-N2N.patch @@ -0,0 +1,47 @@ +From: Quinn Tran +Date: Wed, 26 Feb 2020 14:40:18 -0800 +Subject: scsi: qla2xxx: Serialize fc_port alloc in N2N +Patch-mainline: v5.7-rc1 +Git-commit: 11efe8755d73efd153d6459240866b6d52448f19 +References: bsc#1157424 + +For N2N, fc_port struct is created during report id acquisition. At +later time, the loop resync (fabric, n2n, loop) would trigger the rest +of the login using the created fc_port struct. The loop resync logic +can trigger another fc_port allocation if the 1st allocation was not +able to execute. This patch prevents the 2nd allocation trigger. + +Link: https://lore.kernel.org/r/20200226224022.24518-15-hmadhani@marvell.com +Signed-off-by: Himanshu Madhani +Signed-off-by: Quinn Tran +Signed-off-by: Martin K. Petersen +Acked-by: Daniel Wagner +--- + drivers/scsi/qla2xxx/qla_init.c | 1 + + drivers/scsi/qla2xxx/qla_os.c | 5 ++--- + 2 files changed, 3 insertions(+), 3 deletions(-) + +--- a/drivers/scsi/qla2xxx/qla_init.c ++++ b/drivers/scsi/qla2xxx/qla_init.c +@@ -5147,6 +5147,7 @@ skip_login: + set_bit(LOCAL_LOOP_UPDATE, &vha->dpc_flags); + set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags); + } ++ return QLA_FUNCTION_FAILED; + } + + found_devs = 0; +--- a/drivers/scsi/qla2xxx/qla_os.c ++++ b/drivers/scsi/qla2xxx/qla_os.c +@@ -5216,9 +5216,8 @@ void qla24xx_create_new_sess(struct scsi + fcport->n2n_flag = 1; + } + fcport->fw_login_state = 0; +- /* +- * wait link init done before sending login +- */ ++ ++ schedule_delayed_work(&vha->scan.scan_work, 5); + } else { + qla24xx_fcport_handle_login(vha, fcport); + } diff --git a/patches.suse/scsi-qla2xxx-Set-Nport-ID-for-N2N.patch b/patches.suse/scsi-qla2xxx-Set-Nport-ID-for-N2N.patch new file mode 100644 index 0000000..6903864 --- /dev/null +++ b/patches.suse/scsi-qla2xxx-Set-Nport-ID-for-N2N.patch @@ -0,0 +1,90 @@ +From: Quinn Tran +Date: Wed, 26 Feb 2020 14:40:21 -0800 +Subject: scsi: qla2xxx: Set Nport ID for N2N +Patch-mainline: v5.7-rc1 +Git-commit: ad8a260aa80d4dfa9588fd5d23b71ec922f61c8b +References: bsc#1157424 + +When transitioning from loop to N2N, stale NPort ID is not +re-assigned. Stale ID can collide with remote device. This patch will +re-assign NPort ID on N2N is detected. + +Link: https://lore.kernel.org/r/20200226224022.24518-18-hmadhani@marvell.com +Signed-off-by: Himanshu Madhani +Signed-off-by: Quinn Tran +Signed-off-by: Martin K. Petersen +Acked-by: Daniel Wagner +--- + drivers/scsi/qla2xxx/qla_mbx.c | 42 ++++++++++++++++++++++------------------- + 1 file changed, 23 insertions(+), 19 deletions(-) + +--- a/drivers/scsi/qla2xxx/qla_mbx.c ++++ b/drivers/scsi/qla2xxx/qla_mbx.c +@@ -3924,11 +3924,29 @@ qla24xx_report_id_acquisition(scsi_qla_h + fcport->scan_state = QLA_FCPORT_SCAN; + fcport->n2n_flag = 0; + } ++ id.b24 = 0; ++ if (wwn_to_u64(vha->port_name) > ++ wwn_to_u64(rptid_entry->u.f1.port_name)) { ++ vha->d_id.b24 = 0; ++ vha->d_id.b.al_pa = 1; ++ ha->flags.n2n_bigger = 1; ++ ++ id.b.al_pa = 2; ++ ql_dbg(ql_dbg_async, vha, 0x5075, ++ "Format 1: assign local id %x remote id %x\n", ++ vha->d_id.b24, id.b24); ++ } else { ++ ql_dbg(ql_dbg_async, vha, 0x5075, ++ "Format 1: Remote login - Waiting for WWPN %8phC.\n", ++ rptid_entry->u.f1.port_name); ++ ha->flags.n2n_bigger = 0; ++ } + + fcport = qla2x00_find_fcport_by_wwpn(vha, + rptid_entry->u.f1.port_name, 1); + spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags); + ++ + if (fcport) { + fcport->plogi_nack_done_deadline = jiffies + HZ; + fcport->dm_login_expire = jiffies + 2*HZ; +@@ -3939,6 +3957,11 @@ qla24xx_report_id_acquisition(scsi_qla_h + if (vha->flags.nvme_enabled) + fcport->fc4_type |= FS_FC4TYPE_NVME; + ++ if (wwn_to_u64(vha->port_name) > ++ wwn_to_u64(fcport->port_name)) { ++ fcport->d_id = id; ++ } ++ + switch (fcport->disc_state) { + case DSC_DELETED: + set_bit(RELOGIN_NEEDED, +@@ -3951,25 +3974,6 @@ qla24xx_report_id_acquisition(scsi_qla_h + break; + } + } else { +- id.b24 = 0; +- if (wwn_to_u64(vha->port_name) > +- wwn_to_u64(rptid_entry->u.f1.port_name)) { +- vha->d_id.b24 = 0; +- vha->d_id.b.al_pa = 1; +- ha->flags.n2n_bigger = 1; +- ha->flags.n2n_ae = 0; +- +- id.b.al_pa = 2; +- ql_dbg(ql_dbg_async, vha, 0x5075, +- "Format 1: assign local id %x remote id %x\n", +- vha->d_id.b24, id.b24); +- } else { +- ql_dbg(ql_dbg_async, vha, 0x5075, +- "Format 1: Remote login - Waiting for WWPN %8phC.\n", +- rptid_entry->u.f1.port_name); +- ha->flags.n2n_bigger = 0; +- ha->flags.n2n_ae = 1; +- } + qla24xx_post_newsess_work(vha, &id, + rptid_entry->u.f1.port_name, + rptid_entry->u.f1.node_name, diff --git a/patches.suse/scsi-qla2xxx-Show-correct-port-speed-capabilities-fo.patch b/patches.suse/scsi-qla2xxx-Show-correct-port-speed-capabilities-fo.patch new file mode 100644 index 0000000..478eae2 --- /dev/null +++ b/patches.suse/scsi-qla2xxx-Show-correct-port-speed-capabilities-fo.patch @@ -0,0 +1,76 @@ +From: Himanshu Madhani +Date: Wed, 12 Feb 2020 13:44:22 -0800 +Subject: scsi: qla2xxx: Show correct port speed capabilities for RDP command +Patch-mainline: v5.7-rc1 +Git-commit: 8b01e4db834db611555cc4ec5d8d9550024361af +References: bsc#1157424 + +This patch correctly displays port speed capability and current speed for +RDP command. + +Link: https://lore.kernel.org/r/20200212214436.25532-12-hmadhani@marvell.com +Signed-off-by: Himanshu Madhani +Signed-off-by: Martin K. Petersen +Acked-by: Daniel Wagner +--- + drivers/scsi/qla2xxx/qla_os.c | 41 +++++++++++++++++++++++++++++++++++------ + 1 file changed, 35 insertions(+), 6 deletions(-) + +--- a/drivers/scsi/qla2xxx/qla_os.c ++++ b/drivers/scsi/qla2xxx/qla_os.c +@@ -5777,13 +5777,39 @@ qla25xx_rdp_port_speed_capability(struct + if (IS_CNA_CAPABLE(ha)) + return RDP_PORT_SPEED_10GB; + +- if (IS_QLA27XX(ha)) { +- if (FW_ABILITY_MAX_SPEED(ha) == FW_ABILITY_MAX_SPEED_32G) +- return RDP_PORT_SPEED_32GB|RDP_PORT_SPEED_16GB| +- RDP_PORT_SPEED_8GB; ++ if (IS_QLA27XX(ha) || IS_QLA28XX(ha)) { ++ unsigned int speeds = 0; + +- return RDP_PORT_SPEED_16GB|RDP_PORT_SPEED_8GB| +- RDP_PORT_SPEED_4GB; ++ if (ha->max_supported_speed == 2) { ++ if (ha->min_supported_speed <= 6) ++ speeds |= RDP_PORT_SPEED_64GB; ++ } ++ ++ if (ha->max_supported_speed == 2 || ++ ha->max_supported_speed == 1) { ++ if (ha->min_supported_speed <= 5) ++ speeds |= RDP_PORT_SPEED_32GB; ++ } ++ ++ if (ha->max_supported_speed == 2 || ++ ha->max_supported_speed == 1 || ++ ha->max_supported_speed == 0) { ++ if (ha->min_supported_speed <= 4) ++ speeds |= RDP_PORT_SPEED_16GB; ++ } ++ ++ if (ha->max_supported_speed == 1 || ++ ha->max_supported_speed == 0) { ++ if (ha->min_supported_speed <= 3) ++ speeds |= RDP_PORT_SPEED_8GB; ++ } ++ ++ if (ha->max_supported_speed == 0) { ++ if (ha->min_supported_speed <= 2) ++ speeds |= RDP_PORT_SPEED_4GB; ++ } ++ ++ return speeds; + } + + if (IS_QLA2031(ha)) +@@ -5829,6 +5855,9 @@ qla25xx_rdp_port_speed_currently(struct + case PORT_SPEED_32GB: + return RDP_PORT_SPEED_32GB; + ++ case PORT_SPEED_64GB: ++ return RDP_PORT_SPEED_64GB; ++ + default: + return RDP_PORT_SPEED_UNKNOWN; + } diff --git a/patches.suse/scsi-qla2xxx-Simplify-the-code-for-aborting-SCSI-com.patch b/patches.suse/scsi-qla2xxx-Simplify-the-code-for-aborting-SCSI-com.patch new file mode 100644 index 0000000..98e5b94 --- /dev/null +++ b/patches.suse/scsi-qla2xxx-Simplify-the-code-for-aborting-SCSI-com.patch @@ -0,0 +1,135 @@ +From: Bart Van Assche +Date: Wed, 19 Feb 2020 20:34:37 -0800 +Subject: scsi: qla2xxx: Simplify the code for aborting SCSI commands +Patch-mainline: v5.7-rc1 +Git-commit: c81ef0ed4477c637d1f1dd96ecd8e8fbe18b7283 +References: bsc#1157424 + +Since the SCSI core does not reuse the tag of the SCSI command that is +being aborted by .eh_abort() before .eh_abort() has finished it is not +necessary to check from inside that callback whether or not the SCSI +command has already completed. Instead, rely on the firmware to return an +error code when attempting to abort a command that has already +completed. Additionally, rely on the firmware to return an error code when +attempting to abort an already aborted command. + +In qla2x00_abort_srb(), use blk_mq_request_started() instead of +sp->completed and sp->aborted. + +Link: https://lore.kernel.org/r/20200220043441.20504-2-bvanassche@acm.org +Cc: Martin Wilck +Cc: Quinn Tran +Reviewed-by: Daniel Wagner +Reviewed-by: Roman Bolshakov +Acked-by: Himanshu Madhani +Signed-off-by: Bart Van Assche +Signed-off-by: Martin K. Petersen +--- + drivers/scsi/qla2xxx/qla_def.h | 3 --- + drivers/scsi/qla2xxx/qla_isr.c | 5 ----- + drivers/scsi/qla2xxx/qla_os.c | 27 ++++++++++++++------------- + 3 files changed, 14 insertions(+), 21 deletions(-) + +--- a/drivers/scsi/qla2xxx/qla_def.h ++++ b/drivers/scsi/qla2xxx/qla_def.h +@@ -597,9 +597,6 @@ typedef struct srb { + struct fc_port *fcport; + struct scsi_qla_host *vha; + unsigned int start_timer:1; +- unsigned int abort:1; +- unsigned int aborted:1; +- unsigned int completed:1; + + uint32_t handle; + uint16_t flags; +--- a/drivers/scsi/qla2xxx/qla_isr.c ++++ b/drivers/scsi/qla2xxx/qla_isr.c +@@ -2645,11 +2645,6 @@ qla2x00_status_entry(scsi_qla_host_t *vh + return; + } + +- if (sp->abort) +- sp->aborted = 1; +- else +- sp->completed = 1; +- + if (sp->cmd_type != TYPE_SRB) { + req->outstanding_cmds[handle] = NULL; + ql_dbg(ql_dbg_io, vha, 0x3015, +--- a/drivers/scsi/qla2xxx/qla_os.c ++++ b/drivers/scsi/qla2xxx/qla_os.c +@@ -1276,17 +1276,6 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd) + return SUCCESS; + + spin_lock_irqsave(qpair->qp_lock_ptr, flags); +- if (sp->completed) { +- spin_unlock_irqrestore(qpair->qp_lock_ptr, flags); +- return SUCCESS; +- } +- +- if (sp->abort || sp->aborted) { +- spin_unlock_irqrestore(qpair->qp_lock_ptr, flags); +- return FAILED; +- } +- +- sp->abort = 1; + sp->comp = ∁ + spin_unlock_irqrestore(qpair->qp_lock_ptr, flags); + +@@ -1711,6 +1700,10 @@ qla2x00_loop_reset(scsi_qla_host_t *vha) + return QLA_SUCCESS; + } + ++/* ++ * The caller must ensure that no completion interrupts will happen ++ * while this function is in progress. ++ */ + static void qla2x00_abort_srb(struct qla_qpair *qp, srb_t *sp, const int res, + unsigned long *flags) + __releases(qp->qp_lock_ptr) +@@ -1719,6 +1712,7 @@ static void qla2x00_abort_srb(struct qla + DECLARE_COMPLETION_ONSTACK(comp); + scsi_qla_host_t *vha = qp->vha; + struct qla_hw_data *ha = vha->hw; ++ struct scsi_cmnd *cmd = GET_CMD_SP(sp); + int rval; + bool ret_cmd; + uint32_t ratov_j; +@@ -1740,7 +1734,6 @@ static void qla2x00_abort_srb(struct qla + } + + sp->comp = ∁ +- sp->abort = 1; + spin_unlock_irqrestore(qp->qp_lock_ptr, *flags); + + rval = ha->isp_ops->abort_command(sp); +@@ -1764,13 +1757,17 @@ static void qla2x00_abort_srb(struct qla + } + + spin_lock_irqsave(qp->qp_lock_ptr, *flags); +- if (ret_cmd && (!sp->completed || !sp->aborted)) ++ if (ret_cmd && blk_mq_request_started(cmd->request)) + sp->done(sp, res); + } else { + sp->done(sp, res); + } + } + ++/* ++ * The caller must ensure that no completion interrupts will happen ++ * while this function is in progress. ++ */ + static void + __qla2x00_abort_all_cmds(struct qla_qpair *qp, int res) + { +@@ -1817,6 +1814,10 @@ __qla2x00_abort_all_cmds(struct qla_qpai + spin_unlock_irqrestore(qp->qp_lock_ptr, flags); + } + ++/* ++ * The caller must ensure that no completion interrupts will happen ++ * while this function is in progress. ++ */ + void + qla2x00_abort_all_cmds(scsi_qla_host_t *vha, int res) + { diff --git a/patches.suse/scsi-qla2xxx-Suppress-endianness-complaints-in-qla2x.patch b/patches.suse/scsi-qla2xxx-Suppress-endianness-complaints-in-qla2x.patch new file mode 100644 index 0000000..419f4a8 --- /dev/null +++ b/patches.suse/scsi-qla2xxx-Suppress-endianness-complaints-in-qla2x.patch @@ -0,0 +1,65 @@ +From: Bart Van Assche +Date: Wed, 19 Feb 2020 20:34:38 -0800 +Subject: scsi: qla2xxx: Suppress endianness complaints in + qla2x00_configure_local_loop() +Patch-mainline: v5.7-rc1 +Git-commit: 1ee5ac365c2a554b59b0e7445455d93a0577662b +References: bsc#1157424 + +Instead of changing endianness in-place, write the data in CPU endian +format in another buffer and copy that buffer back. This patch does not +change any functionality but silences some sparse endianness warnings. + +Link: https://lore.kernel.org/r/20200220043441.20504-3-bvanassche@acm.org +Cc: Roman Bolshakov +Cc: Martin Wilck +Cc: Quinn Tran +Reviewed-by: Daniel Wagner +Reviewed-by: Roman Bolshakov +Signed-off-by: Bart Van Assche +Signed-off-by: Martin K. Petersen +--- + drivers/scsi/qla2xxx/qla_def.h | 2 +- + drivers/scsi/qla2xxx/qla_init.c | 11 +++++------ + 2 files changed, 6 insertions(+), 7 deletions(-) + +--- a/drivers/scsi/qla2xxx/qla_def.h ++++ b/drivers/scsi/qla2xxx/qla_def.h +@@ -414,7 +414,7 @@ struct els_logo_payload { + struct els_plogi_payload { + uint8_t opcode; + uint8_t rsvd[3]; +- uint8_t data[112]; ++ __be32 data[112 / 4]; + }; + + struct ct_arg { +--- a/drivers/scsi/qla2xxx/qla_init.c ++++ b/drivers/scsi/qla2xxx/qla_init.c +@@ -5076,7 +5076,7 @@ qla2x00_configure_local_loop(scsi_qla_ho + if (N2N_TOPO(ha)) { + if (test_and_clear_bit(N2N_LOGIN_NEEDED, &vha->dpc_flags)) { + /* borrowing */ +- u32 *bp, i, sz; ++ u32 *bp, sz; + + memset(ha->init_cb, 0, ha->init_cb_size); + sz = min_t(int, sizeof(struct els_plogi_payload), +@@ -5084,13 +5084,12 @@ qla2x00_configure_local_loop(scsi_qla_ho + rval = qla24xx_get_port_login_templ(vha, + ha->init_cb_dma, (void *)ha->init_cb, sz); + if (rval == QLA_SUCCESS) { ++ __be32 *q = &ha->plogi_els_payld.data[0]; ++ + bp = (uint32_t *)ha->init_cb; +- for (i = 0; i < sz/4 ; i++, bp++) +- *bp = cpu_to_be32(*bp); ++ cpu_to_be32_array(q, bp, sz / 4); + +- memcpy(&ha->plogi_els_payld.data, +- (void *)ha->init_cb, +- sizeof(ha->plogi_els_payld.data)); ++ memcpy(bp, q, sizeof(ha->plogi_els_payld.data)); + } else { + ql_dbg(ql_dbg_init, vha, 0x00d1, + "PLOGI ELS param read fail.\n"); diff --git a/patches.suse/scsi-qla2xxx-Update-BPM-enablement-semantics.patch b/patches.suse/scsi-qla2xxx-Update-BPM-enablement-semantics.patch new file mode 100644 index 0000000..dd84211 --- /dev/null +++ b/patches.suse/scsi-qla2xxx-Update-BPM-enablement-semantics.patch @@ -0,0 +1,392 @@ +From: Andrew Vasquez +Date: Wed, 26 Feb 2020 14:40:13 -0800 +Subject: scsi: qla2xxx: Update BPM enablement semantics. +Patch-mainline: v5.7-rc1 +Git-commit: b0f18eee6fc1ee21c07abb55e9ccabc9ed9c09f0 +References: bsc#1157424 + +commit e4e3a2ce9556 ("scsi: qla2xxx: Add ability to autodetect SFP +type") takes a heavy handed approach to BPM (Buffer Plus Management) +enablement: + +1) During hardware initialization, if an LR-capable transceiver is + recognized, the driver schedules a disruptive post-initialization + chip-reset (ISP-ABORT) to allow the BPM settings to be sent to the + firmware. This chip-reset will result in (short-term) path-loss to + all fc-rports and their attached SCSI devices. + +2) LR-detection is triggered during any link-up event, resulting in a + refresh and potential chip-reset + +Based on firmware-team guidance, upon LR-capable transceiver +recognition, the driver's hardware initialization code will now +re-execute firmware with the new BPM settings, then continue on with +driver initialization. To address the second issue, the driver +performs LR-capable detection upon the driver receiving a +transceiver-insertion asynchronous event from firmware. No short-term +path loss is needed with this new semantic. + +Link: https://lore.kernel.org/r/20200226224022.24518-10-hmadhani@marvell.com +Signed-off-by: Himanshu Madhani +Signed-off-by: Andrew Vasquez +Signed-off-by: Martin K. Petersen +Acked-by: Daniel Wagner +--- + drivers/scsi/qla2xxx/qla_def.h | 20 +++++---- + drivers/scsi/qla2xxx/qla_fw.h | 3 - + drivers/scsi/qla2xxx/qla_gbl.h | 2 + drivers/scsi/qla2xxx/qla_init.c | 88 ++++++++++++++++++++++++++++------------ + drivers/scsi/qla2xxx/qla_isr.c | 9 ++-- + drivers/scsi/qla2xxx/qla_mbx.c | 48 +++------------------ + drivers/scsi/qla2xxx/qla_os.c | 22 +++------- + 7 files changed, 97 insertions(+), 95 deletions(-) + +--- a/drivers/scsi/qla2xxx/qla_def.h ++++ b/drivers/scsi/qla2xxx/qla_def.h +@@ -1049,6 +1049,7 @@ static inline bool qla2xxx_is_valid_mbs( + #define MBA_TEMPERATURE_ALERT 0x8070 /* Temperature Alert */ + #define MBA_DPORT_DIAGNOSTICS 0x8080 /* D-port Diagnostics */ + #define MBA_TRANS_INSERT 0x8130 /* Transceiver Insertion */ ++#define MBA_TRANS_REMOVE 0x8131 /* Transceiver Removal */ + #define MBA_FW_INIT_FAILURE 0x8401 /* Firmware initialization failure */ + #define MBA_MIRROR_LUN_CHANGE 0x8402 /* Mirror LUN State Change + Notification */ +@@ -3802,8 +3803,8 @@ struct qla_hw_data { + uint32_t fw_started:1; + uint32_t fw_init_done:1; + +- uint32_t detected_lr_sfp:1; +- uint32_t using_lr_setting:1; ++ uint32_t lr_detected:1; ++ + uint32_t rida_fmt2:1; + uint32_t purge_mbox:1; + uint32_t n2n_bigger:1; +@@ -3812,7 +3813,7 @@ struct qla_hw_data { + } flags; + + uint16_t max_exchg; +- uint16_t long_range_distance; /* 32G & above */ ++ uint16_t lr_distance; /* 32G & above */ + #define LR_DISTANCE_5K 1 + #define LR_DISTANCE_10K 0 + +@@ -4969,11 +4970,14 @@ struct sff_8247_a0 { + u8 resv2[128]; + }; + +-#define AUTO_DETECT_SFP_SUPPORT(_vha)\ +- (ql2xautodetectsfp && !_vha->vp_idx && \ +- (IS_QLA25XX(_vha->hw) || IS_QLA81XX(_vha->hw) ||\ +- IS_QLA83XX(_vha->hw) || IS_QLA27XX(_vha->hw) || \ +- IS_QLA28XX(_vha->hw))) ++/* BPM -- Buffer Plus Management support. */ ++#define IS_BPM_CAPABLE(ha) \ ++ (IS_QLA25XX(ha) || IS_QLA81XX(ha) || IS_QLA83XX(ha) || \ ++ IS_QLA27XX(ha) || IS_QLA28XX(ha)) ++#define IS_BPM_RANGE_CAPABLE(ha) \ ++ (IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha)) ++#define IS_BPM_ENABLED(vha) \ ++ (ql2xautodetectsfp && !vha->vp_idx && IS_BPM_CAPABLE(vha->hw)) + + #define FLASH_SEMAPHORE_REGISTER_ADDR 0x00101016 + +--- a/drivers/scsi/qla2xxx/qla_fw.h ++++ b/drivers/scsi/qla2xxx/qla_fw.h +@@ -1867,9 +1867,8 @@ struct access_chip_rsp_84xx { + + /* LR Distance bit positions */ + #define LR_DIST_NV_POS 2 ++#define LR_DIST_NV_MASK 0xf + #define LR_DIST_FW_POS 12 +-#define LR_DIST_FW_SHIFT (LR_DIST_FW_POS - LR_DIST_NV_POS) +-#define LR_DIST_FW_FIELD(x) ((x) << LR_DIST_FW_SHIFT & 0xf000) + + /* FAC semaphore defines */ + #define FAC_SEMAPHORE_UNLOCK 0 +--- a/drivers/scsi/qla2xxx/qla_gbl.h ++++ b/drivers/scsi/qla2xxx/qla_gbl.h +@@ -109,7 +109,7 @@ int qla24xx_async_notify_ack(scsi_qla_ho + int qla24xx_post_newsess_work(struct scsi_qla_host *, port_id_t *, u8 *, u8*, + void *, u8); + int qla24xx_fcport_handle_login(struct scsi_qla_host *, fc_port_t *); +-int qla24xx_detect_sfp(scsi_qla_host_t *vha); ++int qla24xx_detect_sfp(scsi_qla_host_t *); + int qla24xx_post_gpdb_work(struct scsi_qla_host *, fc_port_t *, u8); + + extern void qla28xx_get_aux_images(struct scsi_qla_host *, +--- a/drivers/scsi/qla2xxx/qla_init.c ++++ b/drivers/scsi/qla2xxx/qla_init.c +@@ -3550,53 +3550,77 @@ static void qla2xxx_print_sfp_info(struc + } + + +-/* +- * Return Code: +- * QLA_SUCCESS: no action +- * QLA_INTERFACE_ERROR: SFP is not there. +- * QLA_FUNCTION_FAILED: detected New SFP ++/** ++ * qla24xx_detect_sfp() ++ * ++ * @vha: adapter state pointer. ++ * ++ * @return ++ * 0 -- Configure firmware to use short-range settings -- normal ++ * buffer-to-buffer credits. ++ * ++ * 1 -- Configure firmware to use long-range settings -- extra ++ * buffer-to-buffer credits should be allocated with ++ * ha->lr_distance containing distance settings from NVRAM or SFP ++ * (if supported). + */ + int + qla24xx_detect_sfp(scsi_qla_host_t *vha) + { +- int rc = QLA_SUCCESS; ++ int rc, used_nvram; + struct sff_8247_a0 *a; + struct qla_hw_data *ha = vha->hw; ++ struct nvram_81xx *nv = ha->nvram; ++#define LR_DISTANCE_UNKNOWN 2 ++ static const char * const types[] = { "Short", "Long" }; ++ static const char * const lengths[] = { "(10km)", "(5km)", "" }; ++ u8 ll = 0; ++ ++ /* Seed with NVRAM settings. */ ++ used_nvram = 0; ++ ha->flags.lr_detected = 0; ++ if (IS_BPM_RANGE_CAPABLE(ha) && ++ (nv->enhanced_features & NEF_LR_DIST_ENABLE)) { ++ used_nvram = 1; ++ ha->flags.lr_detected = 1; ++ ha->lr_distance = ++ (nv->enhanced_features >> LR_DIST_NV_POS) ++ & LR_DIST_NV_MASK; ++ } + +- if (!AUTO_DETECT_SFP_SUPPORT(vha)) ++ if (!IS_BPM_ENABLED(vha)) + goto out; +- ++ /* Determine SR/LR capabilities of SFP/Transceiver. */ + rc = qla2x00_read_sfp_dev(vha, NULL, 0); + if (rc) + goto out; + ++ used_nvram = 0; + a = (struct sff_8247_a0 *)vha->hw->sfp_data; + qla2xxx_print_sfp_info(vha); + +- if (a->fc_ll_cc7 & FC_LL_VL || a->fc_ll_cc7 & FC_LL_L) { +- /* long range */ +- ha->flags.detected_lr_sfp = 1; ++ ha->flags.lr_detected = 0; ++ ll = a->fc_ll_cc7; ++ if (ll & FC_LL_VL || ll & FC_LL_L) { ++ /* Long range, track length. */ ++ ha->flags.lr_detected = 1; + + if (a->length_km > 5 || a->length_100m > 50) +- ha->long_range_distance = LR_DISTANCE_10K; ++ ha->lr_distance = LR_DISTANCE_10K; + else +- ha->long_range_distance = LR_DISTANCE_5K; +- +- if (ha->flags.detected_lr_sfp != ha->flags.using_lr_setting) +- ql_dbg(ql_dbg_async, vha, 0x507b, +- "Detected Long Range SFP.\n"); +- } else { +- /* short range */ +- ha->flags.detected_lr_sfp = 0; +- if (ha->flags.using_lr_setting) +- ql_dbg(ql_dbg_async, vha, 0x5084, +- "Detected Short Range SFP.\n"); ++ ha->lr_distance = LR_DISTANCE_5K; + } + + if (!vha->flags.init_done) + rc = QLA_SUCCESS; + out: +- return rc; ++ ql_dbg(ql_dbg_async, vha, 0x507b, ++ "SFP detect: %s-Range SFP %s (nvr=%x ll=%x lr=%x lrd=%x).\n", ++ types[ha->flags.lr_detected], ++ ha->flags.lr_detected ? lengths[ha->lr_distance] : ++ lengths[LR_DISTANCE_UNKNOWN], ++ used_nvram, ll, ha->flags.lr_detected, ha->lr_distance); ++ return ha->flags.lr_detected; + } + + /** +@@ -3614,6 +3638,7 @@ qla2x00_setup_chip(scsi_qla_host_t *vha) + struct device_reg_2xxx __iomem *reg = &ha->iobase->isp; + unsigned long flags; + uint16_t fw_major_version; ++ int done_once = 0; + + if (IS_P3P_TYPE(ha)) { + rval = ha->isp_ops->load_risc(vha, &srisc_address); +@@ -3634,6 +3659,7 @@ qla2x00_setup_chip(scsi_qla_host_t *vha) + + qla81xx_mpi_sync(vha); + ++execute_fw_with_lr: + /* Load firmware sequences */ + rval = ha->isp_ops->load_risc(vha, &srisc_address); + if (rval == QLA_SUCCESS) { +@@ -3655,7 +3681,15 @@ qla2x00_setup_chip(scsi_qla_host_t *vha) + rval = qla2x00_execute_fw(vha, srisc_address); + /* Retrieve firmware information. */ + if (rval == QLA_SUCCESS) { +- qla24xx_detect_sfp(vha); ++ /* Enable BPM support? */ ++ if (!done_once++ && qla24xx_detect_sfp(vha)) { ++ ql_dbg(ql_dbg_init, vha, 0x00ca, ++ "Re-starting firmware -- BPM.\n"); ++ /* Best-effort - re-init. */ ++ ha->isp_ops->reset_chip(vha); ++ ha->isp_ops->chip_diag(vha); ++ goto execute_fw_with_lr; ++ } + + if ((IS_QLA83XX(ha) || IS_QLA27XX(ha) || + IS_QLA28XX(ha)) && +@@ -3932,6 +3966,10 @@ qla24xx_update_fw_options(scsi_qla_host_ + if (ql2xrdpenable) + ha->fw_options[1] |= ADD_FO1_ENABLE_PUREX_IOCB; + ++ /* Enable Async 8130/8131 events -- transceiver insertion/removal */ ++ if (IS_BPM_RANGE_CAPABLE(ha)) ++ ha->fw_options[3] |= BIT_10; ++ + ql_dbg(ql_dbg_init, vha, 0x00e8, + "%s, add FW options 1-3 = 0x%04x 0x%04x 0x%04x mode %x\n", + __func__, ha->fw_options[1], ha->fw_options[2], +--- a/drivers/scsi/qla2xxx/qla_isr.c ++++ b/drivers/scsi/qla2xxx/qla_isr.c +@@ -960,10 +960,6 @@ skip_rio: + vha->flags.management_server_logged_in = 0; + qla2x00_post_aen_work(vha, FCH_EVT_LINKUP, ha->link_data_rate); + +- if (AUTO_DETECT_SFP_SUPPORT(vha)) { +- set_bit(DETECT_SFP_CHANGE, &vha->dpc_flags); +- qla2xxx_wake_dpc(vha); +- } + break; + + case MBA_LOOP_DOWN: /* Loop Down Event */ +@@ -1436,6 +1432,11 @@ global_port_update: + case MBA_TRANS_INSERT: + ql_dbg(ql_dbg_async, vha, 0x5091, + "Transceiver Insertion: %04x\n", mb[1]); ++ set_bit(DETECT_SFP_CHANGE, &vha->dpc_flags); ++ break; ++ ++ case MBA_TRANS_REMOVE: ++ ql_dbg(ql_dbg_async, vha, 0x5091, "Transceiver Removal\n"); + break; + + default: +--- a/drivers/scsi/qla2xxx/qla_mbx.c ++++ b/drivers/scsi/qla2xxx/qla_mbx.c +@@ -643,28 +643,6 @@ qla2x00_load_ram(scsi_qla_host_t *vha, d + } + + #define NVME_ENABLE_FLAG BIT_3 +-static inline uint16_t qla25xx_set_sfp_lr_dist(struct qla_hw_data *ha) +-{ +- uint16_t mb4 = BIT_0; +- +- if (IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha)) +- mb4 |= ha->long_range_distance << LR_DIST_FW_POS; +- +- return mb4; +-} +- +-static inline uint16_t qla25xx_set_nvr_lr_dist(struct qla_hw_data *ha) +-{ +- uint16_t mb4 = BIT_0; +- +- if (IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha)) { +- struct nvram_81xx *nv = ha->nvram; +- +- mb4 |= LR_DIST_FW_FIELD(nv->enhanced_features); +- } +- +- return mb4; +-} + + /* + * qla2x00_execute_fw +@@ -701,25 +679,13 @@ qla2x00_execute_fw(scsi_qla_host_t *vha, + mcp->mb[3] = 0; + mcp->mb[4] = 0; + mcp->mb[11] = 0; +- ha->flags.using_lr_setting = 0; +- if (IS_QLA25XX(ha) || IS_QLA81XX(ha) || IS_QLA83XX(ha) || +- IS_QLA27XX(ha) || IS_QLA28XX(ha)) { +- if (ql2xautodetectsfp) { +- if (ha->flags.detected_lr_sfp) { +- mcp->mb[4] |= +- qla25xx_set_sfp_lr_dist(ha); +- ha->flags.using_lr_setting = 1; +- } +- } else { +- struct nvram_81xx *nv = ha->nvram; +- /* set LR distance if specified in nvram */ +- if (nv->enhanced_features & +- NEF_LR_DIST_ENABLE) { +- mcp->mb[4] |= +- qla25xx_set_nvr_lr_dist(ha); +- ha->flags.using_lr_setting = 1; +- } +- } ++ ++ /* Enable BPM? */ ++ if (ha->flags.lr_detected) { ++ mcp->mb[4] = BIT_0; ++ if (IS_BPM_RANGE_CAPABLE(ha)) ++ mcp->mb[4] |= ++ ha->lr_distance << LR_DIST_FW_POS; + } + + if (ql2xnvmeenable && (IS_QLA27XX(ha) || IS_QLA28XX(ha))) +--- a/drivers/scsi/qla2xxx/qla_os.c ++++ b/drivers/scsi/qla2xxx/qla_os.c +@@ -3476,13 +3476,6 @@ skip_dpc: + if (test_bit(UNLOADING, &base_vha->dpc_flags)) + return -ENODEV; + +- if (ha->flags.detected_lr_sfp) { +- ql_log(ql_log_info, base_vha, 0xffff, +- "Reset chip to pick up LR SFP setting\n"); +- set_bit(ISP_ABORT_NEEDED, &base_vha->dpc_flags); +- qla2xxx_wake_dpc(base_vha); +- } +- + return 0; + + probe_failed: +@@ -6894,13 +6887,14 @@ qla2x00_do_dpc(void *data) + } + + if (test_and_clear_bit(DETECT_SFP_CHANGE, +- &base_vha->dpc_flags) && +- !test_bit(ISP_ABORT_NEEDED, &base_vha->dpc_flags)) { +- qla24xx_detect_sfp(base_vha); +- +- if (ha->flags.detected_lr_sfp != +- ha->flags.using_lr_setting) +- set_bit(ISP_ABORT_NEEDED, &base_vha->dpc_flags); ++ &base_vha->dpc_flags)) { ++ /* Semantic: ++ * - NO-OP -- await next ISP-ABORT. Preferred method ++ * to minimize disruptions that will occur ++ * when a forced chip-reset occurs. ++ * - Force -- ISP-ABORT scheduled. ++ */ ++ /* set_bit(ISP_ABORT_NEEDED, &base_vha->dpc_flags); */ + } + + if (test_and_clear_bit diff --git a/patches.suse/scsi-qla2xxx-Update-driver-version-to-10.01.00.24-k.patch b/patches.suse/scsi-qla2xxx-Update-driver-version-to-10.01.00.24-k.patch new file mode 100644 index 0000000..3436744 --- /dev/null +++ b/patches.suse/scsi-qla2xxx-Update-driver-version-to-10.01.00.24-k.patch @@ -0,0 +1,26 @@ +From: Himanshu Madhani +Date: Wed, 12 Feb 2020 13:44:36 -0800 +Subject: scsi: qla2xxx: Update driver version to 10.01.00.24-k +Patch-mainline: v5.7-rc1 +Git-commit: 1939295a8dfa7be1cea478d6d7d283c091b780d4 +References: bsc#1157424 + +Link: https://lore.kernel.org/r/20200212214436.25532-26-hmadhani@marvell.com +Signed-off-by: Himanshu Madhani +Signed-off-by: Martin K. Petersen +Acked-by: Daniel Wagner +--- + drivers/scsi/qla2xxx/qla_version.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/scsi/qla2xxx/qla_version.h ++++ b/drivers/scsi/qla2xxx/qla_version.h +@@ -7,7 +7,7 @@ + /* + * Driver version + */ +-#define QLA2XXX_VERSION "10.01.00.22-k" ++#define QLA2XXX_VERSION "10.01.00.24-k" + + #define QLA_DRIVER_MAJOR_VER 10 + #define QLA_DRIVER_MINOR_VER 1 diff --git a/patches.suse/scsi-qla2xxx-Update-driver-version-to-10.01.00.25-k.patch b/patches.suse/scsi-qla2xxx-Update-driver-version-to-10.01.00.25-k.patch new file mode 100644 index 0000000..cc9f8e5 --- /dev/null +++ b/patches.suse/scsi-qla2xxx-Update-driver-version-to-10.01.00.25-k.patch @@ -0,0 +1,26 @@ +From: Himanshu Madhani +Date: Wed, 26 Feb 2020 14:40:22 -0800 +Subject: scsi: qla2xxx: Update driver version to 10.01.00.25-k +Patch-mainline: v5.7-rc1 +Git-commit: 4cbca7ea9edaab268f344c2bcd22afcb7370569f +References: bsc#1157424 + +Link: https://lore.kernel.org/r/20200226224022.24518-19-hmadhani@marvell.com +Signed-off-by: Himanshu Madhani +Signed-off-by: Martin K. Petersen +Acked-by: Daniel Wagner +--- + drivers/scsi/qla2xxx/qla_version.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/scsi/qla2xxx/qla_version.h ++++ b/drivers/scsi/qla2xxx/qla_version.h +@@ -7,7 +7,7 @@ + /* + * Driver version + */ +-#define QLA2XXX_VERSION "10.01.00.24-k" ++#define QLA2XXX_VERSION "10.01.00.25-k" + + #define QLA_DRIVER_MAJOR_VER 10 + #define QLA_DRIVER_MINOR_VER 1 diff --git a/patches.suse/scsi-qla2xxx-Use-FC-generic-update-firmware-options-.patch b/patches.suse/scsi-qla2xxx-Use-FC-generic-update-firmware-options-.patch new file mode 100644 index 0000000..fe56da5 --- /dev/null +++ b/patches.suse/scsi-qla2xxx-Use-FC-generic-update-firmware-options-.patch @@ -0,0 +1,128 @@ +From: Giridhar Malavali +Date: Wed, 26 Feb 2020 14:40:07 -0800 +Subject: scsi: qla2xxx: Use FC generic update firmware options routine for + ISP27xx +Patch-mainline: v5.7-rc1 +Git-commit: 37efd51f75f30b48c2d19ee94eeccfd4325c3cb4 +References: bsc#1157424 + +This patch uses generic firmware update options for FCoE based +adapters as well to reduce code duplication. + +Link: https://lore.kernel.org/r/20200226224022.24518-4-hmadhani@marvell.com +Signed-off-by: Himanshu Madhani +Signed-off-by: Giridhar Malavali +Signed-off-by: Martin K. Petersen +Acked-by: Daniel Wagner +--- + drivers/scsi/qla2xxx/qla_gbl.h | 2 - + drivers/scsi/qla2xxx/qla_init.c | 66 ---------------------------------------- + drivers/scsi/qla2xxx/qla_os.c | 4 +- + 3 files changed, 2 insertions(+), 70 deletions(-) + +--- a/drivers/scsi/qla2xxx/qla_gbl.h ++++ b/drivers/scsi/qla2xxx/qla_gbl.h +@@ -31,8 +31,6 @@ extern int qla24xx_nvram_config(struct s + extern int qla81xx_nvram_config(struct scsi_qla_host *); + extern void qla2x00_update_fw_options(struct scsi_qla_host *); + extern void qla24xx_update_fw_options(scsi_qla_host_t *); +-extern void qla81xx_update_fw_options(scsi_qla_host_t *); +-extern void qla83xx_update_fw_options(scsi_qla_host_t *); + + extern int qla2x00_load_risc(struct scsi_qla_host *, uint32_t *); + extern int qla24xx_load_risc(scsi_qla_host_t *, uint32_t *); +--- a/drivers/scsi/qla2xxx/qla_init.c ++++ b/drivers/scsi/qla2xxx/qla_init.c +@@ -8679,72 +8679,6 @@ qla82xx_restart_isp(scsi_qla_host_t *vha + return status; + } + +-void +-qla83xx_update_fw_options(scsi_qla_host_t *vha) +-{ +- struct qla_hw_data *ha = vha->hw; +- +- if (ql2xrdpenable) +- ha->fw_options[1] |= ADD_FO1_ENABLE_PUREX_IOCB; +- +- qla2x00_set_fw_options(vha, ha->fw_options); +-} +- +-void +-qla81xx_update_fw_options(scsi_qla_host_t *vha) +-{ +- struct qla_hw_data *ha = vha->hw; +- +- /* Hold status IOCBs until ABTS response received. */ +- if (ql2xfwholdabts) +- ha->fw_options[3] |= BIT_12; +- +- /* Set Retry FLOGI in case of P2P connection */ +- if (ha->operating_mode == P2P) { +- ha->fw_options[2] |= BIT_3; +- ql_dbg(ql_dbg_disc, vha, 0x2103, +- "(%s): Setting FLOGI retry BIT in fw_options[2]: 0x%x\n", +- __func__, ha->fw_options[2]); +- } +- +- /* Move PUREX, ABTS RX & RIDA to ATIOQ */ +- if (ql2xmvasynctoatio) { +- if (qla_tgt_mode_enabled(vha) || +- qla_dual_mode_enabled(vha)) +- ha->fw_options[2] |= BIT_11; +- else +- ha->fw_options[2] &= ~BIT_11; +- } +- +- if (qla_tgt_mode_enabled(vha) || +- qla_dual_mode_enabled(vha)) { +- /* FW auto send SCSI status during */ +- ha->fw_options[1] |= BIT_8; +- ha->fw_options[10] |= (u16)SAM_STAT_BUSY << 8; +- +- /* FW perform Exchange validation */ +- ha->fw_options[2] |= BIT_4; +- } else { +- ha->fw_options[1] &= ~BIT_8; +- ha->fw_options[10] &= 0x00ff; +- +- ha->fw_options[2] &= ~BIT_4; +- } +- +- if (ql2xetsenable) { +- /* Enable ETS Burst. */ +- memset(ha->fw_options, 0, sizeof(ha->fw_options)); +- ha->fw_options[2] |= BIT_9; +- } +- +- ql_dbg(ql_dbg_init, vha, 0x00e9, +- "%s, add FW options 1-3 = 0x%04x 0x%04x 0x%04x mode %x\n", +- __func__, ha->fw_options[1], ha->fw_options[2], +- ha->fw_options[3], vha->host->active_mode); +- +- qla2x00_set_fw_options(vha, ha->fw_options); +-} +- + /* + * qla24xx_get_fcp_prio + * Gets the fcp cmd priority value for the logged in port. +--- a/drivers/scsi/qla2xxx/qla_os.c ++++ b/drivers/scsi/qla2xxx/qla_os.c +@@ -2314,7 +2314,7 @@ static struct isp_operations qla81xx_isp + .config_rings = qla24xx_config_rings, + .reset_adapter = qla24xx_reset_adapter, + .nvram_config = qla81xx_nvram_config, +- .update_fw_options = qla83xx_update_fw_options, ++ .update_fw_options = qla24xx_update_fw_options, + .load_risc = qla81xx_load_risc, + .pci_info_str = qla24xx_pci_info_str, + .fw_version_str = qla24xx_fw_version_str, +@@ -2431,7 +2431,7 @@ static struct isp_operations qla83xx_isp + .config_rings = qla24xx_config_rings, + .reset_adapter = qla24xx_reset_adapter, + .nvram_config = qla81xx_nvram_config, +- .update_fw_options = qla83xx_update_fw_options, ++ .update_fw_options = qla24xx_update_fw_options, + .load_risc = qla81xx_load_risc, + .pci_info_str = qla24xx_pci_info_str, + .fw_version_str = qla24xx_fw_version_str, diff --git a/patches.suse/scsi-qla2xxx-Use-QLA_FW_STOPPED-macro-to-propagate-f.patch b/patches.suse/scsi-qla2xxx-Use-QLA_FW_STOPPED-macro-to-propagate-f.patch new file mode 100644 index 0000000..7757ccc --- /dev/null +++ b/patches.suse/scsi-qla2xxx-Use-QLA_FW_STOPPED-macro-to-propagate-f.patch @@ -0,0 +1,29 @@ +From: Himanshu Madhani +Date: Wed, 12 Feb 2020 13:44:35 -0800 +Subject: scsi: qla2xxx: Use QLA_FW_STOPPED macro to propagate flag +Patch-mainline: v5.7-rc1 +Git-commit: 0fc5b7e62322e1aa8384013ee1caff3f87d30207 +References: bsc#1157424 + +This patch uses QLA_FW_STOPPED macro so that flag is propogated to all the +QPairs. + +Link: https://lore.kernel.org/r/20200212214436.25532-25-hmadhani@marvell.com +Signed-off-by: Himanshu Madhani +Signed-off-by: Martin K. Petersen +Acked-by: Daniel Wagner +--- + drivers/scsi/qla2xxx/qla_init.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/scsi/qla2xxx/qla_init.c ++++ b/drivers/scsi/qla2xxx/qla_init.c +@@ -6676,7 +6676,7 @@ qla2x00_abort_isp_cleanup(scsi_qla_host_ + ha->flags.n2n_ae = 0; + ha->flags.lip_ae = 0; + ha->current_topology = 0; +- ha->flags.fw_started = 0; ++ QLA_FW_STOPPED(ha); + ha->flags.fw_init_done = 0; + ha->chip_reset++; + ha->base_qpair->chip_reset = ha->chip_reset; diff --git a/patches.suse/scsi-qla2xxx-Use-a-dedicated-interrupt-handler-for-h.patch b/patches.suse/scsi-qla2xxx-Use-a-dedicated-interrupt-handler-for-h.patch new file mode 100644 index 0000000..f09e97e --- /dev/null +++ b/patches.suse/scsi-qla2xxx-Use-a-dedicated-interrupt-handler-for-h.patch @@ -0,0 +1,111 @@ +From: Andrew Vasquez +Date: Wed, 26 Feb 2020 14:40:11 -0800 +Subject: scsi: qla2xxx: Use a dedicated interrupt handler for + 'handshake-required' ISPs +Patch-mainline: v5.7-rc1 +Git-commit: 7b2a73963c91cf6bad6b8f58636560cd1f3cf319 +References: bsc#1157424 + +There's no point checking flags.disable_msix_handshake in the +interrupt handler hot-path. Instead perform the check during +queue-pair instantiation and use the proper interrupt handler. + +Link: https://lore.kernel.org/r/20200226224022.24518-8-hmadhani@marvell.com +Signed-off-by: Himanshu Madhani +Signed-off-by: Andrew Vasquez +Signed-off-by: Martin K. Petersen +Acked-by: Daniel Wagner +--- + drivers/scsi/qla2xxx/qla_def.h | 1 + + drivers/scsi/qla2xxx/qla_gbl.h | 2 ++ + drivers/scsi/qla2xxx/qla_isr.c | 31 ++++++++++++++++++++++++------- + drivers/scsi/qla2xxx/qla_mid.c | 3 ++- + 4 files changed, 29 insertions(+), 8 deletions(-) + +--- a/drivers/scsi/qla2xxx/qla_def.h ++++ b/drivers/scsi/qla2xxx/qla_def.h +@@ -3250,6 +3250,7 @@ struct isp_operations { + #define QLA_MSIX_RSP_Q 0x01 + #define QLA_ATIO_VECTOR 0x02 + #define QLA_MSIX_QPAIR_MULTIQ_RSP_Q 0x03 ++#define QLA_MSIX_QPAIR_MULTIQ_RSP_Q_HS 0x04 + + #define QLA_MIDX_DEFAULT 0 + #define QLA_MIDX_RSP_Q 1 +--- a/drivers/scsi/qla2xxx/qla_gbl.h ++++ b/drivers/scsi/qla2xxx/qla_gbl.h +@@ -565,6 +565,8 @@ qla2x00_process_completed_request(struct + uint32_t); + extern irqreturn_t + qla2xxx_msix_rsp_q(int irq, void *dev_id); ++extern irqreturn_t ++qla2xxx_msix_rsp_q_hs(int irq, void *dev_id); + fc_port_t *qla2x00_find_fcport_by_loopid(scsi_qla_host_t *, uint16_t); + fc_port_t *qla2x00_find_fcport_by_wwpn(scsi_qla_host_t *, u8 *, u8); + fc_port_t *qla2x00_find_fcport_by_nportid(scsi_qla_host_t *, port_id_t *, u8); +--- a/drivers/scsi/qla2xxx/qla_isr.c ++++ b/drivers/scsi/qla2xxx/qla_isr.c +@@ -3584,6 +3584,25 @@ qla2xxx_msix_rsp_q(int irq, void *dev_id + { + struct qla_hw_data *ha; + struct qla_qpair *qpair; ++ ++ qpair = dev_id; ++ if (!qpair) { ++ ql_log(ql_log_info, NULL, 0x505b, ++ "%s: NULL response queue pointer.\n", __func__); ++ return IRQ_NONE; ++ } ++ ha = qpair->hw; ++ ++ queue_work(ha->wq, &qpair->q_work); ++ ++ return IRQ_HANDLED; ++} ++ ++irqreturn_t ++qla2xxx_msix_rsp_q_hs(int irq, void *dev_id) ++{ ++ struct qla_hw_data *ha; ++ struct qla_qpair *qpair; + struct device_reg_24xx __iomem *reg; + unsigned long flags; + +@@ -3595,13 +3614,10 @@ qla2xxx_msix_rsp_q(int irq, void *dev_id + } + ha = qpair->hw; + +- /* Clear the interrupt, if enabled, for this response queue */ +- if (unlikely(!ha->flags.disable_msix_handshake)) { +- reg = &ha->iobase->isp24; +- spin_lock_irqsave(&ha->hardware_lock, flags); +- WRT_REG_DWORD(®->hccr, HCCRX_CLR_RISC_INT); +- spin_unlock_irqrestore(&ha->hardware_lock, flags); +- } ++ reg = &ha->iobase->isp24; ++ spin_lock_irqsave(&ha->hardware_lock, flags); ++ WRT_REG_DWORD(®->hccr, HCCRX_CLR_RISC_INT); ++ spin_unlock_irqrestore(&ha->hardware_lock, flags); + + queue_work(ha->wq, &qpair->q_work); + +@@ -3620,6 +3636,7 @@ static const struct qla_init_msix_entry + { "rsp_q", qla24xx_msix_rsp_q }, + { "atio_q", qla83xx_msix_atio_q }, + { "qpair_multiq", qla2xxx_msix_rsp_q }, ++ { "qpair_multiq_hs", qla2xxx_msix_rsp_q_hs }, + }; + + static const struct qla_init_msix_entry qla82xx_msix_entries[] = { +--- a/drivers/scsi/qla2xxx/qla_mid.c ++++ b/drivers/scsi/qla2xxx/qla_mid.c +@@ -896,7 +896,8 @@ qla25xx_create_rsp_que(struct qla_hw_dat + rsp->rsp_q_out); + + ret = qla25xx_request_irq(ha, qpair, qpair->msix, +- QLA_MSIX_QPAIR_MULTIQ_RSP_Q); ++ ha->flags.disable_msix_handshake ? ++ QLA_MSIX_QPAIR_MULTIQ_RSP_Q : QLA_MSIX_QPAIR_MULTIQ_RSP_Q_HS); + if (ret) + goto que_failed; + diff --git a/patches.suse/scsi-qla2xxx-Use-correct-ISP28xx-active-FW-region.patch b/patches.suse/scsi-qla2xxx-Use-correct-ISP28xx-active-FW-region.patch new file mode 100644 index 0000000..e2cd824 --- /dev/null +++ b/patches.suse/scsi-qla2xxx-Use-correct-ISP28xx-active-FW-region.patch @@ -0,0 +1,29 @@ +From: Quinn Tran +Date: Wed, 12 Feb 2020 13:44:31 -0800 +Subject: scsi: qla2xxx: Use correct ISP28xx active FW region +Patch-mainline: v5.7-rc1 +Git-commit: 8d4926d13076a89c1f750fe5af4c082d8ea15008 +References: bsc#1157424 + +For ISP28xx, use 28xx call to retrieve active FW region. + +Link: https://lore.kernel.org/r/20200212214436.25532-21-hmadhani@marvell.com +Signed-off-by: Himanshu Madhani +Signed-off-by: Quinn Tran +Signed-off-by: Martin K. Petersen +Acked-by: Daniel Wagner +--- + drivers/scsi/qla2xxx/qla_bsg.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/scsi/qla2xxx/qla_bsg.c ++++ b/drivers/scsi/qla2xxx/qla_bsg.c +@@ -2415,7 +2415,7 @@ qla2x00_get_flash_image_status(struct bs + regions.global_image = active_regions.global; + + if (IS_QLA28XX(ha)) { +- qla27xx_get_active_image(vha, &active_regions); ++ qla28xx_get_aux_images(vha, &active_regions); + regions.board_config = active_regions.aux.board_config; + regions.vpd_nvram = active_regions.aux.vpd_nvram; + regions.npiv_config_0_1 = active_regions.aux.npiv_config_0_1; diff --git a/patches.suse/scsi-qla2xxx-Use-endian-macros-to-assign-static-fiel.patch b/patches.suse/scsi-qla2xxx-Use-endian-macros-to-assign-static-fiel.patch new file mode 100644 index 0000000..8527efc --- /dev/null +++ b/patches.suse/scsi-qla2xxx-Use-endian-macros-to-assign-static-fiel.patch @@ -0,0 +1,59 @@ +From: Joe Carnuccio +Date: Wed, 12 Feb 2020 13:44:27 -0800 +Subject: scsi: qla2xxx: Use endian macros to assign static fields in fwdump + header +Patch-mainline: v5.7-rc1 +Git-commit: a31056ddc6651b457d72d8d71d32143764df86d2 +References: bsc#1157424 + +This takes care of big endian architectures. + +Link: https://lore.kernel.org/r/20200212214436.25532-17-hmadhani@marvell.com +Signed-off-by: Joe Carnuccio +Signed-off-by: Himanshu Madhani +Signed-off-by: Martin K. Petersen +Acked-by: Daniel Wagner +--- + drivers/scsi/qla2xxx/qla_tmpl.c | 17 +++++++++-------- + 1 file changed, 9 insertions(+), 8 deletions(-) + +--- a/drivers/scsi/qla2xxx/qla_tmpl.c ++++ b/drivers/scsi/qla2xxx/qla_tmpl.c +@@ -870,7 +870,7 @@ bailout: + static void + qla27xx_time_stamp(struct qla27xx_fwdt_template *tmp) + { +- tmp->capture_timestamp = jiffies; ++ tmp->capture_timestamp = cpu_to_le32(jiffies); + } + + static void +@@ -882,9 +882,10 @@ qla27xx_driver_info(struct qla27xx_fwdt_ + "%hhu.%hhu.%hhu.%hhu.%hhu.%hhu", + v+0, v+1, v+2, v+3, v+4, v+5) != 6); + +- tmp->driver_info[0] = v[3] << 24 | v[2] << 16 | v[1] << 8 | v[0]; +- tmp->driver_info[1] = v[5] << 8 | v[4]; +- tmp->driver_info[2] = 0x12345678; ++ tmp->driver_info[0] = cpu_to_le32( ++ v[3] << 24 | v[2] << 16 | v[1] << 8 | v[0]); ++ tmp->driver_info[1] = cpu_to_le32(v[5] << 8 | v[4]); ++ tmp->driver_info[2] = __constant_cpu_to_le32(0x12345678); + } + + static void +@@ -894,10 +895,10 @@ qla27xx_firmware_info(struct scsi_qla_ho + tmp->firmware_version[0] = vha->hw->fw_major_version; + tmp->firmware_version[1] = vha->hw->fw_minor_version; + tmp->firmware_version[2] = vha->hw->fw_subminor_version; +- tmp->firmware_version[3] = +- vha->hw->fw_attributes_h << 16 | vha->hw->fw_attributes; +- tmp->firmware_version[4] = +- vha->hw->fw_attributes_ext[1] << 16 | vha->hw->fw_attributes_ext[0]; ++ tmp->firmware_version[3] = cpu_to_le32( ++ vha->hw->fw_attributes_h << 16 | vha->hw->fw_attributes); ++ tmp->firmware_version[4] = cpu_to_le32( ++ vha->hw->fw_attributes_ext[1] << 16 | vha->hw->fw_attributes_ext[0]); + } + + static void diff --git a/patches.suse/scsi-qla2xxx-add-more-FW-debug-information.patch b/patches.suse/scsi-qla2xxx-add-more-FW-debug-information.patch new file mode 100644 index 0000000..6ddf181 --- /dev/null +++ b/patches.suse/scsi-qla2xxx-add-more-FW-debug-information.patch @@ -0,0 +1,51 @@ +From: Quinn Tran +Date: Wed, 26 Feb 2020 14:40:14 -0800 +Subject: scsi: qla2xxx: add more FW debug information +Patch-mainline: v5.7-rc1 +Git-commit: a82c307e69c465e4d80cc15fde3c00f5b95832d6 +References: bsc#1157424 + +Per FW request, MB 1-7 should be logged for 8002 error. + +Link: https://lore.kernel.org/r/20200226224022.24518-11-hmadhani@marvell.com +Signed-off-by: Himanshu Madhani +Signed-off-by: Quinn Tran +Signed-off-by: Martin K. Petersen +Acked-by: Daniel Wagner +--- + drivers/scsi/qla2xxx/qla_isr.c | 24 ++++++++++++++++++------ + 1 file changed, 18 insertions(+), 6 deletions(-) + +--- a/drivers/scsi/qla2xxx/qla_isr.c ++++ b/drivers/scsi/qla2xxx/qla_isr.c +@@ -854,12 +854,24 @@ skip_rio: + break; + + case MBA_SYSTEM_ERR: /* System Error */ +- mbx = (IS_QLA81XX(ha) || IS_QLA83XX(ha) || IS_QLA27XX(ha) || +- IS_QLA28XX(ha)) ? +- RD_REG_WORD(®24->mailbox7) : 0; +- ql_log(ql_log_warn, vha, 0x5003, +- "ISP System Error - mbx1=%xh mbx2=%xh mbx3=%xh " +- "mbx7=%xh.\n", mb[1], mb[2], mb[3], mbx); ++ mbx = 0; ++ if (IS_QLA81XX(ha) || IS_QLA83XX(ha) || ++ IS_QLA27XX(ha) || IS_QLA28XX(ha)) { ++ u16 m[4]; ++ ++ m[0] = RD_REG_WORD(®24->mailbox4); ++ m[1] = RD_REG_WORD(®24->mailbox5); ++ m[2] = RD_REG_WORD(®24->mailbox6); ++ mbx = m[3] = RD_REG_WORD(®24->mailbox7); ++ ++ ql_log(ql_log_warn, vha, 0x5003, ++ "ISP System Error - mbx1=%xh mbx2=%xh mbx3=%xh mbx4=%xh mbx5=%xh mbx6=%xh mbx7=%xh.\n", ++ mb[1], mb[2], mb[3], m[0], m[1], m[2], m[3]); ++ } else ++ ql_log(ql_log_warn, vha, 0x5003, ++ "ISP System Error - mbx1=%xh mbx2=%xh mbx3=%xh.\n ", ++ mb[1], mb[2], mb[3]); ++ + ha->fw_dump_mpi = + (IS_QLA27XX(ha) || IS_QLA28XX(ha)) && + RD_REG_WORD(®24->mailbox7) & BIT_8; diff --git a/patches.suse/scsi-qla2xxx-fix-FW-resource-count-values.patch b/patches.suse/scsi-qla2xxx-fix-FW-resource-count-values.patch new file mode 100644 index 0000000..bd6f677 --- /dev/null +++ b/patches.suse/scsi-qla2xxx-fix-FW-resource-count-values.patch @@ -0,0 +1,48 @@ +From: Quinn Tran +Date: Wed, 26 Feb 2020 14:40:12 -0800 +Subject: scsi: qla2xxx: fix FW resource count values +Patch-mainline: v5.7-rc1 +Git-commit: ce1ee122e0f048fc67c1259489f0802a28049bfd +References: bsc#1157424 + +This patch fixes issue where current and original exchanges count +were swapped for intiator and targets. + +Also fix IOCB count for current and original which were swapped. + +Link: https://lore.kernel.org/r/20200226224022.24518-9-hmadhani@marvell.com +Signed-off-by: Himanshu Madhani +Signed-off-by: Quinn Tran +Signed-off-by: Martin K. Petersen +Acked-by: Daniel Wagner +--- + drivers/scsi/qla2xxx/qla_dfs.c | 11 +++++------ + 1 file changed, 5 insertions(+), 6 deletions(-) + +--- a/drivers/scsi/qla2xxx/qla_dfs.c ++++ b/drivers/scsi/qla2xxx/qla_dfs.c +@@ -134,11 +134,11 @@ qla_dfs_fw_resource_cnt_show(struct seq_ + } else { + seq_puts(s, "FW Resource count\n\n"); + seq_printf(s, "Original TGT exchg count[%d]\n", mb[1]); +- seq_printf(s, "current TGT exchg count[%d]\n", mb[2]); +- seq_printf(s, "original Initiator Exchange count[%d]\n", mb[3]); +- seq_printf(s, "Current Initiator Exchange count[%d]\n", mb[6]); +- seq_printf(s, "Original IOCB count[%d]\n", mb[7]); +- seq_printf(s, "Current IOCB count[%d]\n", mb[10]); ++ seq_printf(s, "Current TGT exchg count[%d]\n", mb[2]); ++ seq_printf(s, "Current Initiator Exchange count[%d]\n", mb[3]); ++ seq_printf(s, "Original Initiator Exchange count[%d]\n", mb[6]); ++ seq_printf(s, "Current IOCB count[%d]\n", mb[7]); ++ seq_printf(s, "Original IOCB count[%d]\n", mb[10]); + seq_printf(s, "MAX VP count[%d]\n", mb[11]); + seq_printf(s, "MAX FCF count[%d]\n", mb[12]); + seq_printf(s, "Current free pageable XCB buffer cnt[%d]\n", +@@ -149,7 +149,6 @@ qla_dfs_fw_resource_cnt_show(struct seq_ + mb[22]); + seq_printf(s, "Original Target fast XCB buffer cnt[%d]\n", + mb[23]); +- + } + + return 0; diff --git a/patches.suse/scsi-tcm_qla2xxx-Make-qlt_alloc_qfull_cmd-set-cmd-se.patch b/patches.suse/scsi-tcm_qla2xxx-Make-qlt_alloc_qfull_cmd-set-cmd-se.patch new file mode 100644 index 0000000..4b6acd6 --- /dev/null +++ b/patches.suse/scsi-tcm_qla2xxx-Make-qlt_alloc_qfull_cmd-set-cmd-se.patch @@ -0,0 +1,169 @@ +From: Bart Van Assche +Date: Fri, 3 Jan 2020 11:27:19 -0800 +Subject: scsi: tcm_qla2xxx: Make qlt_alloc_qfull_cmd() set cmd->se_cmd.map_tag +Patch-mainline: v5.7-rc1 +Git-commit: 80363e1b673b242fa5f5578a7b1e3fa03bf4729a +References: bsc#1157424 + +Reduce code duplication by introducing the tcm_qla2xxx_{get,rel}_cmd() +functions. Introduce these functions in the tcm_qla2xxx.c source files such +that the qla_target.c source file becomes independent of the SCSI target +core header files. This patch fixes a bug, namely by ensuring that +qlt_alloc_qfull_cmd() sets cmd->se_cmd.map_tag. + +Cc: Himanshu Madhani +Link: https://lore.kernel.org/r/20200103192719.205158-1-bvanassche@acm.org +Acked-by: Himanshu Madhani +Signed-off-by: Bart Van Assche +Signed-off-by: Martin K. Petersen +Acked-by: Daniel Wagner +--- + drivers/scsi/qla2xxx/qla_target.c | 28 +++++++--------------------- + drivers/scsi/qla2xxx/qla_target.h | 2 ++ + drivers/scsi/qla2xxx/tcm_qla2xxx.c | 26 ++++++++++++++++++++++++++ + 3 files changed, 35 insertions(+), 21 deletions(-) + +--- a/drivers/scsi/qla2xxx/qla_target.c ++++ b/drivers/scsi/qla2xxx/qla_target.c +@@ -36,8 +36,6 @@ + #include + #include + #include +-#include +-#include + + #include "qla_def.h" + #include "qla_target.h" +@@ -3825,7 +3823,7 @@ void qlt_free_cmd(struct qla_tgt_cmd *cm + return; + } + cmd->jiffies_at_free = get_jiffies_64(); +- percpu_ida_free(&sess->se_sess->sess_tag_pool, cmd->se_cmd.map_tag); ++ cmd->vha->hw->tgt.tgt_ops->rel_cmd(cmd); + } + EXPORT_SYMBOL(qlt_free_cmd); + +@@ -4159,9 +4157,9 @@ out_term: + qlt_send_term_exchange(qpair, NULL, &cmd->atio, 1, 0); + + qlt_decr_num_pend_cmds(vha); +- percpu_ida_free(&sess->se_sess->sess_tag_pool, cmd->se_cmd.map_tag); +- spin_unlock_irqrestore(qpair->qp_lock_ptr, flags); + ++ spin_unlock_irqrestore(qpair->qp_lock_ptr, flags); ++ cmd->vha->hw->tgt.tgt_ops->rel_cmd(cmd); + ha->tgt.tgt_ops->put_sess(sess); + } + +@@ -4286,23 +4284,18 @@ static struct qla_tgt_cmd *qlt_get_tag(s + struct fc_port *sess, + struct atio_from_isp *atio) + { +- struct se_session *se_sess = sess->se_sess; + struct qla_tgt_cmd *cmd; +- int tag; + +- tag = percpu_ida_alloc(&se_sess->sess_tag_pool, TASK_RUNNING); +- if (tag < 0) ++ cmd = vha->hw->tgt.tgt_ops->get_cmd(sess); ++ if (!cmd) + return NULL; + +- cmd = &((struct qla_tgt_cmd *)se_sess->sess_cmd_map)[tag]; +- memset(cmd, 0, sizeof(struct qla_tgt_cmd)); + cmd->cmd_type = TYPE_TGT_CMD; + memcpy(&cmd->atio, atio, sizeof(*atio)); + cmd->state = QLA_TGT_STATE_NEW; + cmd->tgt = vha->vha_tgt.qla_tgt; + qlt_incr_num_pend_cmds(vha); + cmd->vha = vha; +- cmd->se_cmd.map_tag = tag; + cmd->sess = sess; + cmd->loop_id = sess->loop_id; + cmd->conf_compl_supported = sess->conf_compl_supported; +@@ -5360,9 +5353,7 @@ qlt_alloc_qfull_cmd(struct scsi_qla_host + struct qla_tgt *tgt = vha->vha_tgt.qla_tgt; + struct qla_hw_data *ha = vha->hw; + struct fc_port *sess; +- struct se_session *se_sess; + struct qla_tgt_cmd *cmd; +- int tag; + unsigned long flags; + + if (unlikely(tgt->tgt_stop)) { +@@ -5392,10 +5383,8 @@ qlt_alloc_qfull_cmd(struct scsi_qla_host + if (!sess) + return; + +- se_sess = sess->se_sess; +- +- tag = percpu_ida_alloc(&se_sess->sess_tag_pool, TASK_RUNNING); +- if (tag < 0) { ++ cmd = ha->tgt.tgt_ops->get_cmd(sess); ++ if (!cmd) { + ql_dbg(ql_dbg_io, vha, 0x3009, + "qla_target(%d): %s: Allocation of cmd failed\n", + vha->vp_idx, __func__); +@@ -5410,9 +5399,6 @@ qlt_alloc_qfull_cmd(struct scsi_qla_host + return; + } + +- cmd = &((struct qla_tgt_cmd *)se_sess->sess_cmd_map)[tag]; +- memset(cmd, 0, sizeof(struct qla_tgt_cmd)); +- + qlt_incr_num_pend_cmds(vha); + INIT_LIST_HEAD(&cmd->cmd_list); + memcpy(&cmd->atio, atio, sizeof(*atio)); +--- a/drivers/scsi/qla2xxx/qla_target.h ++++ b/drivers/scsi/qla2xxx/qla_target.h +@@ -680,6 +680,8 @@ struct qla_tgt_func_tmpl { + void (*handle_data)(struct qla_tgt_cmd *); + int (*handle_tmr)(struct qla_tgt_mgmt_cmd *, u64, uint16_t, + uint32_t); ++ struct qla_tgt_cmd *(*get_cmd)(struct fc_port *); ++ void (*rel_cmd)(struct qla_tgt_cmd *); + void (*free_cmd)(struct qla_tgt_cmd *); + void (*free_mcmd)(struct qla_tgt_mgmt_cmd *); + void (*free_session)(struct fc_port *); +--- a/drivers/scsi/qla2xxx/tcm_qla2xxx.c ++++ b/drivers/scsi/qla2xxx/tcm_qla2xxx.c +@@ -286,6 +286,30 @@ static void tcm_qla2xxx_complete_free(st + transport_generic_free_cmd(&cmd->se_cmd, 0); + } + ++static struct qla_tgt_cmd *tcm_qla2xxx_get_cmd(struct fc_port *sess) ++{ ++ struct se_session *se_sess = sess->se_sess; ++ struct qla_tgt_cmd *cmd; ++ int tag; ++ ++ tag = percpu_ida_alloc(&se_sess->sess_tag_pool, TASK_RUNNING); ++ if (tag < 0) ++ return NULL; ++ ++ cmd = &((struct qla_tgt_cmd *)se_sess->sess_cmd_map)[tag]; ++ memset(cmd, 0, sizeof(struct qla_tgt_cmd)); ++ cmd->se_cmd.map_tag = tag; ++ ++ return cmd; ++} ++ ++static void tcm_qla2xxx_rel_cmd(struct qla_tgt_cmd *cmd) ++{ ++ struct fc_port *sess = cmd->sess; ++ ++ percpu_ida_free(&sess->se_sess->sess_tag_pool, cmd->se_cmd.map_tag); ++} ++ + /* + * Called from qla_target_template->free_cmd(), and will call + * tcm_qla2xxx_release_cmd via normal struct target_core_fabric_ops +@@ -1601,6 +1625,8 @@ static struct qla_tgt_func_tmpl tcm_qla2 + .handle_cmd = tcm_qla2xxx_handle_cmd, + .handle_data = tcm_qla2xxx_handle_data, + .handle_tmr = tcm_qla2xxx_handle_tmr, ++ .get_cmd = tcm_qla2xxx_get_cmd, ++ .rel_cmd = tcm_qla2xxx_rel_cmd, + .free_cmd = tcm_qla2xxx_free_cmd, + .free_mcmd = tcm_qla2xxx_free_mcmd, + .free_session = tcm_qla2xxx_free_session, diff --git a/patches.suse/sctp-free-cmd-obj.chunk-for-the-unprocessed-SCTP_CMD.patch b/patches.suse/sctp-free-cmd-obj.chunk-for-the-unprocessed-SCTP_CMD.patch new file mode 100644 index 0000000..243cdae --- /dev/null +++ b/patches.suse/sctp-free-cmd-obj.chunk-for-the-unprocessed-SCTP_CMD.patch @@ -0,0 +1,92 @@ +From: Xin Long +Date: Sat, 4 Jan 2020 14:15:02 +0800 +Subject: sctp: free cmd->obj.chunk for the unprocessed SCTP_CMD_REPLY +Git-commit: be7a7729207797476b6666f046d765bdf9630407 +Patch-mainline: 5.5-rc6 +References: networking-stable-20_01_11 + +This patch is to fix a memleak caused by no place to free cmd->obj.chunk +for the unprocessed SCTP_CMD_REPLY. This issue occurs when failing to +process a cmd while there're still SCTP_CMD_REPLY cmds on the cmd seq +with an allocated chunk in cmd->obj.chunk. + +So fix it by freeing cmd->obj.chunk for each SCTP_CMD_REPLY cmd left on +the cmd seq when any cmd returns error. While at it, also remove 'nomem' +label. + +Reported-by: syzbot+107c4aff5f392bf1517f@syzkaller.appspotmail.com +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Signed-off-by: Xin Long +Signed-off-by: David S. Miller +Signed-off-by: Jiri Slaby +--- + net/sctp/sm_sideeffect.c | 28 ++++++++++++++++++---------- + 1 file changed, 18 insertions(+), 10 deletions(-) + +--- a/net/sctp/sm_sideeffect.c ++++ b/net/sctp/sm_sideeffect.c +@@ -1336,8 +1336,10 @@ static int sctp_cmd_interpreter(sctp_eve + /* Generate an INIT ACK chunk. */ + new_obj = sctp_make_init_ack(asoc, chunk, GFP_ATOMIC, + 0); +- if (!new_obj) +- goto nomem; ++ if (!new_obj) { ++ error = -ENOMEM; ++ break; ++ } + + sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, + SCTP_CHUNK(new_obj)); +@@ -1359,7 +1361,8 @@ static int sctp_cmd_interpreter(sctp_eve + if (!new_obj) { + if (cmd->obj.chunk) + sctp_chunk_free(cmd->obj.chunk); +- goto nomem; ++ error = -ENOMEM; ++ break; + } + sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, + SCTP_CHUNK(new_obj)); +@@ -1406,8 +1409,10 @@ static int sctp_cmd_interpreter(sctp_eve + + /* Generate a SHUTDOWN chunk. */ + new_obj = sctp_make_shutdown(asoc, chunk); +- if (!new_obj) +- goto nomem; ++ if (!new_obj) { ++ error = -ENOMEM; ++ break; ++ } + sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, + SCTP_CHUNK(new_obj)); + break; +@@ -1733,11 +1738,17 @@ static int sctp_cmd_interpreter(sctp_eve + break; + } + +- if (error) ++ if (error) { ++ cmd = sctp_next_cmd(commands); ++ while (cmd) { ++ if (cmd->verb == SCTP_CMD_REPLY) ++ sctp_chunk_free(cmd->obj.chunk); ++ cmd = sctp_next_cmd(commands); ++ } + break; ++ } + } + +-out: + /* If this is in response to a received chunk, wait until + * we are done with the packet to open the queue so that we don't + * send multiple packets in response to a single request. +@@ -1752,8 +1763,5 @@ out: + sp->data_ready_signalled = 0; + + return error; +-nomem: +- error = -ENOMEM; +- goto out; + } + diff --git a/patches.suse/serdev-ttyport-restore-client-ops-on-deregistration.patch b/patches.suse/serdev-ttyport-restore-client-ops-on-deregistration.patch new file mode 100644 index 0000000..28a0079 --- /dev/null +++ b/patches.suse/serdev-ttyport-restore-client-ops-on-deregistration.patch @@ -0,0 +1,116 @@ +From 0c5aae59270fb1f827acce182786094c9ccf598e Mon Sep 17 00:00:00 2001 +From: Johan Hovold +Date: Mon, 10 Feb 2020 15:57:30 +0100 +Subject: [PATCH] serdev: ttyport: restore client ops on deregistration +Git-commit: 0c5aae59270fb1f827acce182786094c9ccf598e +Patch-mainline: v5.6-rc3 +References: bsc#1051510 + +The serdev tty-port controller driver should reset the tty-port client +operations also on deregistration to avoid a NULL-pointer dereference in +case the port is later re-registered as a normal tty device. + +Note that this can only happen with tty drivers such as 8250 which have +statically allocated port structures that can end up being reused and +where a later registration would not register a serdev controller (e.g. +due to registration errors or if the devicetree has been changed in +between). + +Specifically, this can be an issue for any statically defined ports that +would be registered by 8250 core when an 8250 driver is being unbound. + +Fixes: bed35c6dfa6a ("serdev: add a tty port controller driver") +Cc: stable # 4.11 +Reported-by: Loic Poulain +Signed-off-by: Johan Hovold +Link: https://lore.kernel.org/r/20200210145730.22762-1-johan@kernel.org +Signed-off-by: Greg Kroah-Hartman +Acked-by: Takashi Iwai + +--- + drivers/tty/serdev/serdev-ttyport.c | 6 ++---- + drivers/tty/tty_port.c | 5 +++-- + include/linux/tty.h | 2 ++ + 3 files changed, 7 insertions(+), 6 deletions(-) + +diff --git a/drivers/tty/serdev/serdev-ttyport.c b/drivers/tty/serdev/serdev-ttyport.c +index d1cdd2ab8b4c..d367803e2044 100644 +--- a/drivers/tty/serdev/serdev-ttyport.c ++++ b/drivers/tty/serdev/serdev-ttyport.c +@@ -265,7 +265,6 @@ struct device *serdev_tty_port_register(struct tty_port *port, + struct device *parent, + struct tty_driver *drv, int idx) + { +- const struct tty_port_client_operations *old_ops; + struct serdev_controller *ctrl; + struct serport *serport; + int ret; +@@ -284,7 +283,6 @@ struct device *serdev_tty_port_register(struct tty_port *port, + + ctrl->ops = &ctrl_ops; + +- old_ops = port->client_ops; + port->client_ops = &client_ops; + port->client_data = ctrl; + +@@ -297,7 +295,7 @@ struct device *serdev_tty_port_register(struct tty_port *port, + + err_reset_data: + port->client_data = NULL; +- port->client_ops = old_ops; ++ port->client_ops = &tty_port_default_client_ops; + serdev_controller_put(ctrl); + + return ERR_PTR(ret); +@@ -312,8 +310,8 @@ int serdev_tty_port_unregister(struct tty_port *port) + return -ENODEV; + + serdev_controller_remove(ctrl); +- port->client_ops = NULL; + port->client_data = NULL; ++ port->client_ops = &tty_port_default_client_ops; + serdev_controller_put(ctrl); + + return 0; +diff --git a/drivers/tty/tty_port.c b/drivers/tty/tty_port.c +index 044c3cbdcfa4..ea80bf872f54 100644 +--- a/drivers/tty/tty_port.c ++++ b/drivers/tty/tty_port.c +@@ -52,10 +52,11 @@ static void tty_port_default_wakeup(struct tty_port *port) + } + } + +-static const struct tty_port_client_operations default_client_ops = { ++const struct tty_port_client_operations tty_port_default_client_ops = { + .receive_buf = tty_port_default_receive_buf, + .write_wakeup = tty_port_default_wakeup, + }; ++EXPORT_SYMBOL_GPL(tty_port_default_client_ops); + + void tty_port_init(struct tty_port *port) + { +@@ -68,7 +69,7 @@ void tty_port_init(struct tty_port *port) + spin_lock_init(&port->lock); + port->close_delay = (50 * HZ) / 100; + port->closing_wait = (3000 * HZ) / 100; +- port->client_ops = &default_client_ops; ++ port->client_ops = &tty_port_default_client_ops; + kref_init(&port->kref); + } + EXPORT_SYMBOL(tty_port_init); +diff --git a/include/linux/tty.h b/include/linux/tty.h +index bfa4e2ee94a9..bd5fe0e907e8 100644 +--- a/include/linux/tty.h ++++ b/include/linux/tty.h +@@ -225,6 +225,8 @@ struct tty_port_client_operations { + void (*write_wakeup)(struct tty_port *port); + }; + ++extern const struct tty_port_client_operations tty_port_default_client_ops; ++ + struct tty_port { + struct tty_bufhead buf; /* Locked internally */ + struct tty_struct *tty; /* Back pointer */ +-- +2.16.4 + diff --git a/patches.suse/simple_recursive_removal-kernel-side-rm-rf-for-ramfs.patch b/patches.suse/simple_recursive_removal-kernel-side-rm-rf-for-ramfs.patch new file mode 100644 index 0000000..b61ec79 --- /dev/null +++ b/patches.suse/simple_recursive_removal-kernel-side-rm-rf-for-ramfs.patch @@ -0,0 +1,486 @@ +From: Al Viro +Date: Mon, 18 Nov 2019 09:43:10 -0500 +Subject: simple_recursive_removal(): kernel-side rm -rf for ramfs-style + filesystems +Patch-mainline: v5.6-rc1 +Git-commit: a3d1e7eb5abe3aa1095bc75d1a6760d3809bd672 +References: bsc#1159198 CVE-2019-19770 + +two requirements: no file creations in IS_DEADDIR and no cross-directory +renames whatsoever. + +Signed-off-by: Al Viro +[nstange@suse.de: + - fix diff context + - skip calls to non-existent fsnotify hooks +] +Acked-by: Nicolai Stange +--- + fs/debugfs/inode.c | 118 +++++--------------------------------------- + fs/libfs.c | 65 ++++++++++++++++++++++++ + fs/tracefs/inode.c | 111 ++++------------------------------------- + include/linux/debugfs.h | 2 + include/linux/fs.h | 2 + include/linux/tracefs.h | 1 + kernel/trace/trace.c | 4 - + kernel/trace/trace_events.c | 6 +- + kernel/trace/trace_hwlat.c | 2 + 9 files changed, 99 insertions(+), 212 deletions(-) + +--- a/fs/debugfs/inode.c ++++ b/fs/debugfs/inode.c +@@ -315,7 +315,10 @@ static struct dentry *start_creating(con + parent = debugfs_mount->mnt_root; + + inode_lock(d_inode(parent)); +- dentry = lookup_one_len(name, parent, strlen(name)); ++ if (unlikely(IS_DEADDIR(d_inode(parent)))) ++ dentry = ERR_PTR(-ENOENT); ++ else ++ dentry = lookup_one_len(name, parent, strlen(name)); + if (!IS_ERR(dentry) && d_really_is_positive(dentry)) { + dput(dentry); + dentry = ERR_PTR(-EEXIST); +@@ -643,59 +646,15 @@ static void __debugfs_file_removed(struc + wait_for_completion(&fsd->active_users_drained); + } + +-static int __debugfs_remove(struct dentry *dentry, struct dentry *parent) ++static void remove_one(struct dentry *victim) + { +- int ret = 0; +- +- if (simple_positive(dentry)) { +- dget(dentry); +- if (d_is_dir(dentry)) { +- ret = simple_rmdir(d_inode(parent), dentry); +- } else { +- simple_unlink(d_inode(parent), dentry); +- } +- if (!ret) +- d_delete(dentry); +- if (d_is_reg(dentry)) +- __debugfs_file_removed(dentry); +- dput(dentry); +- } +- return ret; +-} +- +-/** +- * debugfs_remove - removes a file or directory from the debugfs filesystem +- * @dentry: a pointer to a the dentry of the file or directory to be +- * removed. If this parameter is NULL or an error value, nothing +- * will be done. +- * +- * This function removes a file or directory in debugfs that was previously +- * created with a call to another debugfs function (like +- * debugfs_create_file() or variants thereof.) +- * +- * This function is required to be called in order for the file to be +- * removed, no automatic cleanup of files will happen when a module is +- * removed, you are responsible here. +- */ +-void debugfs_remove(struct dentry *dentry) +-{ +- struct dentry *parent; +- int ret; +- +- if (IS_ERR_OR_NULL(dentry)) +- return; +- +- parent = dentry->d_parent; +- inode_lock(d_inode(parent)); +- ret = __debugfs_remove(dentry, parent); +- inode_unlock(d_inode(parent)); +- if (!ret) +- simple_release_fs(&debugfs_mount, &debugfs_mount_count); ++ if (d_is_reg(victim)) ++ __debugfs_file_removed(victim); ++ simple_release_fs(&debugfs_mount, &debugfs_mount_count); + } +-EXPORT_SYMBOL_GPL(debugfs_remove); + + /** +- * debugfs_remove_recursive - recursively removes a directory ++ * debugfs_remove - recursively removes a directory + * @dentry: a pointer to a the dentry of the directory to be removed. If this + * parameter is NULL or an error value, nothing will be done. + * +@@ -707,65 +666,16 @@ EXPORT_SYMBOL_GPL(debugfs_remove); + * removed, no automatic cleanup of files will happen when a module is + * removed, you are responsible here. + */ +-void debugfs_remove_recursive(struct dentry *dentry) ++void debugfs_remove(struct dentry *dentry) + { +- struct dentry *child, *parent; +- + if (IS_ERR_OR_NULL(dentry)) + return; + +- parent = dentry; +- down: +- inode_lock(d_inode(parent)); +- loop: +- /* +- * The parent->d_subdirs is protected by the d_lock. Outside that +- * lock, the child can be unlinked and set to be freed which can +- * use the d_u.d_child as the rcu head and corrupt this list. +- */ +- spin_lock(&parent->d_lock); +- list_for_each_entry(child, &parent->d_subdirs, d_child) { +- if (!simple_positive(child)) +- continue; +- +- /* perhaps simple_empty(child) makes more sense */ +- if (!list_empty(&child->d_subdirs)) { +- spin_unlock(&parent->d_lock); +- inode_unlock(d_inode(parent)); +- parent = child; +- goto down; +- } +- +- spin_unlock(&parent->d_lock); +- +- if (!__debugfs_remove(child, parent)) +- simple_release_fs(&debugfs_mount, &debugfs_mount_count); +- +- /* +- * The parent->d_lock protects agaist child from unlinking +- * from d_subdirs. When releasing the parent->d_lock we can +- * no longer trust that the next pointer is valid. +- * Restart the loop. We'll skip this one with the +- * simple_positive() check. +- */ +- goto loop; +- } +- spin_unlock(&parent->d_lock); +- +- inode_unlock(d_inode(parent)); +- child = parent; +- parent = parent->d_parent; +- inode_lock(d_inode(parent)); +- +- if (child != dentry) +- /* go up */ +- goto loop; +- +- if (!__debugfs_remove(child, parent)) +- simple_release_fs(&debugfs_mount, &debugfs_mount_count); +- inode_unlock(d_inode(parent)); ++ simple_pin_fs(&debug_fs_type, &debugfs_mount, &debugfs_mount_count); ++ simple_recursive_removal(dentry, remove_one); ++ simple_release_fs(&debugfs_mount, &debugfs_mount_count); + } +-EXPORT_SYMBOL_GPL(debugfs_remove_recursive); ++EXPORT_SYMBOL_GPL(debugfs_remove); + + /** + * debugfs_rename - rename a file/directory in the debugfs filesystem +--- a/fs/libfs.c ++++ b/fs/libfs.c +@@ -229,6 +229,71 @@ const struct inode_operations simple_dir + }; + EXPORT_SYMBOL(simple_dir_inode_operations); + ++static struct dentry *find_next_child(struct dentry *parent, struct dentry *prev) ++{ ++ struct dentry *child = NULL; ++ struct list_head *p = prev ? &prev->d_child : &parent->d_subdirs; ++ ++ spin_lock(&parent->d_lock); ++ while ((p = p->next) != &parent->d_subdirs) { ++ struct dentry *d = container_of(p, struct dentry, d_child); ++ if (simple_positive(d)) { ++ spin_lock_nested(&d->d_lock, DENTRY_D_LOCK_NESTED); ++ if (simple_positive(d)) ++ child = dget_dlock(d); ++ spin_unlock(&d->d_lock); ++ if (likely(child)) ++ break; ++ } ++ } ++ spin_unlock(&parent->d_lock); ++ dput(prev); ++ return child; ++} ++ ++void simple_recursive_removal(struct dentry *dentry, ++ void (*callback)(struct dentry *)) ++{ ++ struct dentry *this = dget(dentry); ++ while (true) { ++ struct dentry *victim = NULL, *child; ++ struct inode *inode = this->d_inode; ++ ++ inode_lock(inode); ++ if (d_is_dir(this)) ++ inode->i_flags |= S_DEAD; ++ while ((child = find_next_child(this, victim)) == NULL) { ++ // kill and ascend ++ // update metadata while it's still locked ++ inode->i_ctime = current_time(inode); ++ clear_nlink(inode); ++ inode_unlock(inode); ++ victim = this; ++ this = this->d_parent; ++ inode = this->d_inode; ++ inode_lock(inode); ++ if (simple_positive(victim)) { ++ d_invalidate(victim); // avoid lost mounts ++ if (callback) ++ callback(victim); ++ dput(victim); // unpin it ++ } ++ if (victim == dentry) { ++ inode->i_ctime = inode->i_mtime = ++ current_time(inode); ++ if (d_is_dir(dentry)) ++ drop_nlink(inode); ++ inode_unlock(inode); ++ dput(dentry); ++ return; ++ } ++ } ++ inode_unlock(inode); ++ this = child; ++ } ++} ++EXPORT_SYMBOL(simple_recursive_removal); ++ + static const struct super_operations simple_super_operations = { + .statfs = simple_statfs, + }; +--- a/fs/tracefs/inode.c ++++ b/fs/tracefs/inode.c +@@ -335,7 +335,10 @@ static struct dentry *start_creating(con + parent = tracefs_mount->mnt_root; + + inode_lock(parent->d_inode); +- dentry = lookup_one_len(name, parent, strlen(name)); ++ if (unlikely(IS_DEADDIR(parent->d_inode))) ++ dentry = ERR_PTR(-ENOENT); ++ else ++ dentry = lookup_one_len(name, parent, strlen(name)); + if (!IS_ERR(dentry) && dentry->d_inode) { + dput(dentry); + dentry = ERR_PTR(-EEXIST); +@@ -500,119 +503,27 @@ struct dentry *tracefs_create_instance_d + return dentry; + } + +-static int __tracefs_remove(struct dentry *dentry, struct dentry *parent) ++static void remove_one(struct dentry *victim) + { +- int ret = 0; +- +- if (simple_positive(dentry)) { +- if (dentry->d_inode) { +- dget(dentry); +- switch (dentry->d_inode->i_mode & S_IFMT) { +- case S_IFDIR: +- ret = simple_rmdir(parent->d_inode, dentry); +- break; +- default: +- simple_unlink(parent->d_inode, dentry); +- break; +- } +- if (!ret) +- d_delete(dentry); +- dput(dentry); +- } +- } +- return ret; +-} +- +-/** +- * tracefs_remove - removes a file or directory from the tracefs filesystem +- * @dentry: a pointer to a the dentry of the file or directory to be +- * removed. +- * +- * This function removes a file or directory in tracefs that was previously +- * created with a call to another tracefs function (like +- * tracefs_create_file() or variants thereof.) +- */ +-void tracefs_remove(struct dentry *dentry) +-{ +- struct dentry *parent; +- int ret; +- +- if (IS_ERR_OR_NULL(dentry)) +- return; +- +- parent = dentry->d_parent; +- inode_lock(parent->d_inode); +- ret = __tracefs_remove(dentry, parent); +- inode_unlock(parent->d_inode); +- if (!ret) +- simple_release_fs(&tracefs_mount, &tracefs_mount_count); ++ simple_release_fs(&tracefs_mount, &tracefs_mount_count); + } + + /** +- * tracefs_remove_recursive - recursively removes a directory ++ * tracefs_remove - recursively removes a directory + * @dentry: a pointer to a the dentry of the directory to be removed. + * + * This function recursively removes a directory tree in tracefs that + * was previously created with a call to another tracefs function + * (like tracefs_create_file() or variants thereof.) + */ +-void tracefs_remove_recursive(struct dentry *dentry) ++void tracefs_remove(struct dentry *dentry) + { +- struct dentry *child, *parent; +- + if (IS_ERR_OR_NULL(dentry)) + return; + +- parent = dentry; +- down: +- inode_lock(parent->d_inode); +- loop: +- /* +- * The parent->d_subdirs is protected by the d_lock. Outside that +- * lock, the child can be unlinked and set to be freed which can +- * use the d_u.d_child as the rcu head and corrupt this list. +- */ +- spin_lock(&parent->d_lock); +- list_for_each_entry(child, &parent->d_subdirs, d_child) { +- if (!simple_positive(child)) +- continue; +- +- /* perhaps simple_empty(child) makes more sense */ +- if (!list_empty(&child->d_subdirs)) { +- spin_unlock(&parent->d_lock); +- inode_unlock(parent->d_inode); +- parent = child; +- goto down; +- } +- +- spin_unlock(&parent->d_lock); +- +- if (!__tracefs_remove(child, parent)) +- simple_release_fs(&tracefs_mount, &tracefs_mount_count); +- +- /* +- * The parent->d_lock protects agaist child from unlinking +- * from d_subdirs. When releasing the parent->d_lock we can +- * no longer trust that the next pointer is valid. +- * Restart the loop. We'll skip this one with the +- * simple_positive() check. +- */ +- goto loop; +- } +- spin_unlock(&parent->d_lock); +- +- inode_unlock(parent->d_inode); +- child = parent; +- parent = parent->d_parent; +- inode_lock(parent->d_inode); +- +- if (child != dentry) +- /* go up */ +- goto loop; +- +- if (!__tracefs_remove(child, parent)) +- simple_release_fs(&tracefs_mount, &tracefs_mount_count); +- inode_unlock(parent->d_inode); ++ simple_pin_fs(&trace_fs_type, &tracefs_mount, &tracefs_mount_count); ++ simple_recursive_removal(dentry, remove_one); ++ simple_release_fs(&tracefs_mount, &tracefs_mount_count); + } + + /** +--- a/include/linux/debugfs.h ++++ b/include/linux/debugfs.h +@@ -85,7 +85,7 @@ struct dentry *debugfs_create_automount( + void *data); + + void debugfs_remove(struct dentry *dentry); +-void debugfs_remove_recursive(struct dentry *dentry); ++#define debugfs_remove_recursive debugfs_remove + + const struct file_operations *debugfs_real_fops(const struct file *filp); + +--- a/include/linux/fs.h ++++ b/include/linux/fs.h +@@ -3068,6 +3068,8 @@ extern int simple_unlink(struct inode *, + extern int simple_rmdir(struct inode *, struct dentry *); + extern int simple_rename(struct inode *, struct dentry *, + struct inode *, struct dentry *, unsigned int); ++extern void simple_recursive_removal(struct dentry *, ++ void (*callback)(struct dentry *)); + extern int noop_fsync(struct file *, loff_t, loff_t, int); + extern int noop_set_page_dirty(struct page *page); + extern void noop_invalidatepage(struct page *page, unsigned int offset, +--- a/include/linux/tracefs.h ++++ b/include/linux/tracefs.h +@@ -32,7 +32,6 @@ struct dentry *tracefs_create_file(const + struct dentry *tracefs_create_dir(const char *name, struct dentry *parent); + + void tracefs_remove(struct dentry *dentry); +-void tracefs_remove_recursive(struct dentry *dentry); + + struct dentry *tracefs_create_instance_dir(const char *name, struct dentry *parent, + int (*mkdir)(const char *name), +--- a/kernel/trace/trace.c ++++ b/kernel/trace/trace.c +@@ -7570,7 +7570,7 @@ static int instance_mkdir(const char *na + + ret = event_trace_add_tracer(tr->dir, tr); + if (ret) { +- tracefs_remove_recursive(tr->dir); ++ tracefs_remove(tr->dir); + goto out_free_tr; + } + +@@ -7635,7 +7635,7 @@ static int instance_rmdir(const char *na + event_trace_del_tracer(tr); + ftrace_clear_pids(tr); + ftrace_destroy_function_files(tr); +- tracefs_remove_recursive(tr->dir); ++ tracefs_remove(tr->dir); + free_trace_buffers(tr); + + for (i = 0; i < tr->nr_topts; i++) { +--- a/kernel/trace/trace_events.c ++++ b/kernel/trace/trace_events.c +@@ -663,7 +663,7 @@ static void remove_subsystem(struct trac + return; + + if (!--dir->nr_events) { +- tracefs_remove_recursive(dir->entry); ++ tracefs_remove(dir->entry); + list_del(&dir->list); + __put_system_dir(dir); + } +@@ -682,7 +682,7 @@ static void remove_event_file_dir(struct + } + spin_unlock(&dir->d_lock); + +- tracefs_remove_recursive(dir); ++ tracefs_remove(dir); + } + + list_del(&file->list); +@@ -2986,7 +2986,7 @@ int event_trace_del_tracer(struct trace_ + + down_write(&trace_event_sem); + __trace_remove_event_dirs(tr); +- tracefs_remove_recursive(tr->event_dir); ++ tracefs_remove(tr->event_dir); + up_write(&trace_event_sem); + + tr->event_dir = NULL; +--- a/kernel/trace/trace_hwlat.c ++++ b/kernel/trace/trace_hwlat.c +@@ -550,7 +550,7 @@ static int init_tracefs(void) + return 0; + + err: +- tracefs_remove_recursive(top_dir); ++ tracefs_remove(top_dir); + return -ENOMEM; + } + diff --git a/patches.suse/slcan-Don-t-transmit-uninitialized-stack-data-in-pad.patch b/patches.suse/slcan-Don-t-transmit-uninitialized-stack-data-in-pad.patch new file mode 100644 index 0000000..23025a4 --- /dev/null +++ b/patches.suse/slcan-Don-t-transmit-uninitialized-stack-data-in-pad.patch @@ -0,0 +1,56 @@ +From b9258a2cece4ec1f020715fe3554bc2e360f6264 Mon Sep 17 00:00:00 2001 +From: Richard Palethorpe +Date: Wed, 1 Apr 2020 12:06:39 +0200 +Subject: [PATCH] slcan: Don't transmit uninitialized stack data in padding +Git-commit: b9258a2cece4ec1f020715fe3554bc2e360f6264 +Patch-mainline: v5.7-rc1 +References: CVE-2020-11494 bsc#1168424 + +struct can_frame contains some padding which is not explicitly zeroed in +slc_bump. This uninitialized data will then be transmitted if the stack +initialization hardening feature is not enabled (CONFIG_INIT_STACK_ALL). + +This commit just zeroes the whole struct including the padding. + +Signed-off-by: Richard Palethorpe +Fixes: a1044e36e457 ("can: add slcan driver for serial/USB-serial CAN adapters") +Reviewed-by: Kees Cook +Cc: linux-can@vger.kernel.org +Cc: netdev@vger.kernel.org +Cc: security@kernel.org +Cc: wg@grandegger.com +Cc: mkl@pengutronix.de +Cc: davem@davemloft.net +Acked-by: Marc Kleine-Budde +Signed-off-by: David S. Miller +Acked-by: Takashi Iwai + +--- + drivers/net/can/slcan.c | 4 +--- + 1 file changed, 1 insertion(+), 3 deletions(-) + +diff --git a/drivers/net/can/slcan.c b/drivers/net/can/slcan.c +index 086dfb1b9d0b..91cdc0a2b1a7 100644 +--- a/drivers/net/can/slcan.c ++++ b/drivers/net/can/slcan.c +@@ -148,7 +148,7 @@ static void slc_bump(struct slcan *sl) + u32 tmpid; + char *cmd = sl->rbuff; + +- cf.can_id = 0; ++ memset(&cf, 0, sizeof(cf)); + + switch (*cmd) { + case 'r': +@@ -187,8 +187,6 @@ static void slc_bump(struct slcan *sl) + else + return; + +- *(u64 *) (&cf.data) = 0; /* clear payload */ +- + /* RTR frames may have a dlc > 0 but they never have any data bytes */ + if (!(cf.can_id & CAN_RTR_FLAG)) { + for (i = 0; i < cf.can_dlc; i++) { +-- +2.16.4 + diff --git a/patches.suse/smb3-Add-defines-for-new-information-level-FileIdInformation.patch b/patches.suse/smb3-Add-defines-for-new-information-level-FileIdInformation.patch new file mode 100644 index 0000000..3ebdd40 --- /dev/null +++ b/patches.suse/smb3-Add-defines-for-new-information-level-FileIdInformation.patch @@ -0,0 +1,48 @@ +From: Steve French +Date: Thu, 6 Feb 2020 12:32:03 -0600 +Subject: [PATCH] smb3: Add defines for new information level, + FileIdInformation +Git-commit: 51d92d69f77b121d8093af82eb3bd2e8e631be55 +References: bsc#1144333 +Patch-mainline: v5.6-rc1 + +See MS-FSCC 2.4.43. Valid to be quried from most +Windows servers (among others). + +Signed-off-by: Steve French +Reviewed-by: Aurelien Aptel +Acked-by: Paulo Alcantara +--- + fs/cifs/smb2pdu.h | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/fs/cifs/smb2pdu.h b/fs/cifs/smb2pdu.h +index ca2123d7f199..fa03df130f1a 100644 +--- a/fs/cifs/smb2pdu.h ++++ b/fs/cifs/smb2pdu.h +@@ -1519,6 +1519,7 @@ struct smb3_fs_vol_info { + #define FILE_NORMALIZED_NAME_INFORMATION 48 + #define FILEID_GLOBAL_TX_DIRECTORY_INFORMATION 50 + #define FILE_STANDARD_LINK_INFORMATION 54 ++#define FILE_ID_INFORMATION 59 + + struct smb2_file_internal_info { + __le64 IndexNumber; +@@ -1593,6 +1594,13 @@ struct smb2_file_network_open_info { + __le32 Reserved; + } __packed; /* level 34 Query also similar returned in close rsp and open rsp */ + ++/* See MS-FSCC 2.4.43 */ ++struct smb2_file_id_information { ++ __le64 VolumeSerialNumber; ++ __u64 PersistentFileId; /* opaque endianness */ ++ __u64 VolatileFileId; /* opaque endianness */ ++} __packed; /* level 59 */ ++ + extern char smb2_padding[7]; + + /* equivalent of the contents of SMB3.1.1 POSIX open context response */ +-- +2.25.1 + + diff --git a/patches.suse/smb3-Add-missing-reparse-tags.patch b/patches.suse/smb3-Add-missing-reparse-tags.patch new file mode 100644 index 0000000..26a3239 --- /dev/null +++ b/patches.suse/smb3-Add-missing-reparse-tags.patch @@ -0,0 +1,44 @@ +From: Steve French +Date: Tue, 24 Sep 2019 23:27:34 -0500 +Subject: [PATCH] smb3: Add missing reparse tags +Git-commit: 131ea1ed3322c6ec06eb8f276f226c8a1f3bbf1b +References: bsc#1144333 +Patch-mainline: v5.4-rc1 + +Additional reparse tags were described for WSL and file sync. +Add missing defines for these tags. Some will be useful for +POSIX extensions (as discussed at Storage Developer Conference). + +Signed-off-by: Steve French +Reviewed-by: Aurelien Aptel +Acked-by: Paulo Alcantara +--- + fs/cifs/smbfsctl.h | 11 +++++++++++ + 1 file changed, 11 insertions(+) + +diff --git a/fs/cifs/smbfsctl.h b/fs/cifs/smbfsctl.h +index 08628e6a42ac..1ff28529cf4b 100644 +--- a/fs/cifs/smbfsctl.h ++++ b/fs/cifs/smbfsctl.h +@@ -144,6 +144,17 @@ + #define IO_REPARSE_APPXSTREAM 0xC0000014 + /* NFS symlinks, Win 8/SMB3 and later */ + #define IO_REPARSE_TAG_NFS 0x80000014 ++/* ++ * AzureFileSync - see ++ * https://docs.microsoft.com/en-us/azure/storage/files/storage-sync-cloud-tiering ++ */ ++#define IO_REPARSE_TAG_AZ_FILE_SYNC 0x8000001e ++/* WSL reparse tags */ ++#define IO_REPARSE_TAG_LX_SYMLINK 0xA000001D ++#define IO_REPARSE_TAG_AF_UNIX 0x80000023 ++#define IO_REPARSE_TAG_LX_FIFO 0x80000024 ++#define IO_REPARSE_TAG_LX_CHR 0x80000025 ++#define IO_REPARSE_TAG_LX_BLK 0x80000026 + + /* fsctl flags */ + /* If Flags is set to this value, the request is an FSCTL not ioctl request */ +-- +2.25.1 + + diff --git a/patches.suse/smb3-Fix-regression-in-time-handling.patch b/patches.suse/smb3-Fix-regression-in-time-handling.patch new file mode 100644 index 0000000..08d771d --- /dev/null +++ b/patches.suse/smb3-Fix-regression-in-time-handling.patch @@ -0,0 +1,48 @@ +From: Steve French +Date: Tue, 8 Oct 2019 00:27:14 -0500 +Subject: [PATCH] smb3: Fix regression in time handling +Git-commit: d4cfbf04b2aafcb657eb8ea0835e5cf51d371448 +References: bsc#1144333 +Patch-mainline: v5.4-rc3 + +Fixes: cb7a69e60590 ("cifs: Initialize filesystem timestamp ranges") + +Only very old servers (e.g. OS/2 and DOS) did not support +DCE TIME (100 nanosecond granularity). Fix the checks used +to set minimum and maximum times. + +Fixes xfstest generic/258 (on 5.4-rc1 and later) + +CC: Deepa Dinamani +Acked-by: Jeff Layton +Signed-off-by: Steve French +Reviewed-by: Pavel Shilovsky +Acked-by: Paulo Alcantara +--- + fs/cifs/cifsfs.c | 15 +++++++++++++-- + 1 file changed, 13 insertions(+), 2 deletions(-) + +--- a/fs/cifs/cifsfs.c ++++ b/fs/cifs/cifsfs.c +@@ -159,8 +159,19 @@ cifs_read_super(struct super_block *sb) + else + sb->s_maxbytes = MAX_NON_LFS; + +- /* BB FIXME fix time_gran to be larger for LANMAN sessions */ +- sb->s_time_gran = 100; ++ /* Some very old servers like DOS and OS/2 used 2 second granularity */ ++ if ((tcon->ses->server->vals->protocol_id == SMB10_PROT_ID) && ++ ((tcon->ses->capabilities & ++ tcon->ses->server->vals->cap_nt_find) == 0) && ++ !tcon->unix_ext) { ++ sb->s_time_gran = 1000000000; /* 1 second is max allowed gran */ ++ } else { ++ /* ++ * Almost every server, including all SMB2+, uses DCE TIME ++ * ie 100 nanosecond units, since 1601. See MS-DTYP and MS-FSCC ++ */ ++ sb->s_time_gran = 100; ++ } + + sb->s_magic = CIFS_MAGIC_NUMBER; + sb->s_op = &cifs_super_ops; diff --git a/patches.suse/smb3-add-debug-messages-for-closing-unmatched-open.patch b/patches.suse/smb3-add-debug-messages-for-closing-unmatched-open.patch new file mode 100644 index 0000000..ea65ae8 --- /dev/null +++ b/patches.suse/smb3-add-debug-messages-for-closing-unmatched-open.patch @@ -0,0 +1,115 @@ +From: Ronnie Sahlberg +Date: Thu, 14 Nov 2019 12:32:12 -0600 +Subject: [PATCH] smb3: add debug messages for closing unmatched open +Git-commit: 87bc2376fffae6821869c988edbb45a14527b258 +References: bsc#1144333 +Patch-mainline: v5.5-rc1 + +Helps distinguish between an interrupted close and a truly +unmatched open. + +Signed-off-by: Ronnie Sahlberg +Signed-off-by: Steve French +Acked-by: Paulo Alcantara +--- + fs/cifs/cifsglob.h | 2 ++ + fs/cifs/smb2misc.c | 42 ++++++++++++++++++++++++++++++++---------- + 2 files changed, 34 insertions(+), 10 deletions(-) + +diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h +index 5d2dd04b55a6..57453226469d 100644 +--- a/fs/cifs/cifsglob.h ++++ b/fs/cifs/cifsglob.h +@@ -1552,6 +1552,8 @@ struct close_cancelled_open { + struct cifs_fid fid; + struct cifs_tcon *tcon; + struct work_struct work; ++ __u64 mid; ++ __u16 cmd; + }; + + /* Make code in transport.c a little cleaner by moving +diff --git a/fs/cifs/smb2misc.c b/fs/cifs/smb2misc.c +index 5668fb7d94e5..289915f0915d 100644 +--- a/fs/cifs/smb2misc.c ++++ b/fs/cifs/smb2misc.c +@@ -729,19 +729,35 @@ smb2_cancelled_close_fid(struct work_struct *work) + { + struct close_cancelled_open *cancelled = container_of(work, + struct close_cancelled_open, work); ++ struct cifs_tcon *tcon = cancelled->tcon; ++ int rc; + +- cifs_dbg(VFS, "Close unmatched open\n"); ++ if (cancelled->mid) ++ cifs_tcon_dbg(VFS, "Close unmatched open for MID:%llx\n", ++ cancelled->mid); ++ else ++ cifs_tcon_dbg(VFS, "Close interrupted close\n"); + +- SMB2_close(0, cancelled->tcon, cancelled->fid.persistent_fid, +- cancelled->fid.volatile_fid); +- cifs_put_tcon(cancelled->tcon); ++ rc = SMB2_close(0, tcon, cancelled->fid.persistent_fid, ++ cancelled->fid.volatile_fid); ++ if (rc) ++ cifs_tcon_dbg(VFS, "Close cancelled mid failed rc:%d\n", rc); ++ ++ cifs_put_tcon(tcon); + kfree(cancelled); + } + +-/* Caller should already has an extra reference to @tcon */ ++/* ++ * Caller should already has an extra reference to @tcon ++ * This function is used to queue work to close a handle to prevent leaks ++ * on the server. ++ * We handle two cases. If an open was interrupted after we sent the ++ * SMB2_CREATE to the server but before we processed the reply, and second ++ * if a close was interrupted before we sent the SMB2_CLOSE to the server. ++ */ + static int +-__smb2_handle_cancelled_close(struct cifs_tcon *tcon, __u64 persistent_fid, +- __u64 volatile_fid) ++__smb2_handle_cancelled_cmd(struct cifs_tcon *tcon, __u16 cmd, __u64 mid, ++ __u64 persistent_fid, __u64 volatile_fid) + { + struct close_cancelled_open *cancelled; + +@@ -752,6 +768,8 @@ __smb2_handle_cancelled_close(struct cifs_tcon *tcon, __u64 persistent_fid, + cancelled->fid.persistent_fid = persistent_fid; + cancelled->fid.volatile_fid = volatile_fid; + cancelled->tcon = tcon; ++ cancelled->cmd = cmd; ++ cancelled->mid = mid; + INIT_WORK(&cancelled->work, smb2_cancelled_close_fid); + WARN_ON(queue_work(cifsiod_wq, &cancelled->work) == false); + +@@ -769,7 +787,8 @@ smb2_handle_cancelled_close(struct cifs_tcon *tcon, __u64 persistent_fid, + tcon->tc_count++; + spin_unlock(&cifs_tcp_ses_lock); + +- rc = __smb2_handle_cancelled_close(tcon, persistent_fid, volatile_fid); ++ rc = __smb2_handle_cancelled_cmd(tcon, SMB2_CLOSE_HE, 0, ++ persistent_fid, volatile_fid); + if (rc) + cifs_put_tcon(tcon); + +@@ -793,8 +812,11 @@ smb2_handle_cancelled_mid(char *buffer, struct TCP_Server_Info *server) + if (!tcon) + return -ENOENT; + +- rc = __smb2_handle_cancelled_close(tcon, rsp->PersistentFileId, +- rsp->VolatileFileId); ++ rc = __smb2_handle_cancelled_cmd(tcon, ++ le16_to_cpu(sync_hdr->Command), ++ le64_to_cpu(sync_hdr->MessageId), ++ rsp->PersistentFileId, ++ rsp->VolatileFileId); + if (rc) + cifs_put_tcon(tcon); + +-- +2.25.1 + + diff --git a/patches.suse/smb3-add-dynamic-tracepoints-for-flush-and-close.patch b/patches.suse/smb3-add-dynamic-tracepoints-for-flush-and-close.patch new file mode 100644 index 0000000..e6d6d4b --- /dev/null +++ b/patches.suse/smb3-add-dynamic-tracepoints-for-flush-and-close.patch @@ -0,0 +1,123 @@ +From: Steve French +Date: Tue, 3 Sep 2019 18:35:42 -0500 +Subject: [PATCH] smb3: add dynamic tracepoints for flush and close +Git-commit: f90f979726bc37275995035dbbd55ce8f9b0acde +References: bsc#1144333 +Patch-mainline: v5.4-rc1 + +We only had dynamic tracepoints on errors in flush +and close, but may be helpful to trace enter +and non-error exits for those. Sample trace examples +(excerpts) from "cp" and "dd" show two of the new +tracepoints. + + cp-22823 [002] .... 123439.179701: smb3_enter: _cifsFileInfo_put: xid=10 + cp-22823 [002] .... 123439.179705: smb3_close_enter: xid=10 sid=0x98871327 tid=0xfcd585ff fid=0xc7f84682 + cp-22823 [002] .... 123439.179711: smb3_cmd_enter: sid=0x98871327 tid=0xfcd585ff cmd=6 mid=43 + cp-22823 [002] .... 123439.180175: smb3_cmd_done: sid=0x98871327 tid=0xfcd585ff cmd=6 mid=43 + cp-22823 [002] .... 123439.180179: smb3_close_done: xid=10 sid=0x98871327 tid=0xfcd585ff fid=0xc7f84682 + + dd-22981 [003] .... 123696.946011: smb3_flush_enter: xid=24 sid=0x98871327 tid=0xfcd585ff fid=0x1917736f + dd-22981 [003] .... 123696.946013: smb3_cmd_enter: sid=0x98871327 tid=0xfcd585ff cmd=7 mid=123 + dd-22981 [003] .... 123696.956639: smb3_cmd_done: sid=0x98871327 tid=0x0 cmd=7 mid=123 + dd-22981 [003] .... 123696.956644: smb3_flush_done: xid=24 sid=0x98871327 tid=0xfcd585ff fid=0x1917736f + +Signed-off-by: Steve French +Reviewed-by: Ronnie Sahlberg +Acked-by: Paulo Alcantara +--- + fs/cifs/smb2pdu.c | 10 ++++++++-- + fs/cifs/trace.h | 35 +++++++++++++++++++++++++++++++++++ + 2 files changed, 43 insertions(+), 2 deletions(-) + +diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c +index 0e92983de0b7..4c9c34cdf05f 100644 +--- a/fs/cifs/smb2pdu.c ++++ b/fs/cifs/smb2pdu.c +@@ -2918,6 +2918,7 @@ SMB2_close_flags(const unsigned int xid, struct cifs_tcon *tcon, + rqst.rq_iov = iov; + rqst.rq_nvec = 1; + ++ trace_smb3_close_enter(xid, persistent_fid, tcon->tid, ses->Suid); + rc = SMB2_close_init(tcon, &rqst, persistent_fid, volatile_fid); + if (rc) + goto close_exit; +@@ -2930,7 +2931,9 @@ SMB2_close_flags(const unsigned int xid, struct cifs_tcon *tcon, + trace_smb3_close_err(xid, persistent_fid, tcon->tid, ses->Suid, + rc); + goto close_exit; +- } ++ } else ++ trace_smb3_close_done(xid, persistent_fid, tcon->tid, ++ ses->Suid); + + atomic_dec(&tcon->num_remote_opens); + +@@ -3353,13 +3356,16 @@ SMB2_flush(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid, + if (rc) + goto flush_exit; + ++ trace_smb3_flush_enter(xid, persistent_fid, tcon->tid, ses->Suid); + rc = cifs_send_recv(xid, ses, &rqst, &resp_buftype, flags, &rsp_iov); + + if (rc != 0) { + cifs_stats_fail_inc(tcon, SMB2_FLUSH_HE); + trace_smb3_flush_err(xid, persistent_fid, tcon->tid, ses->Suid, + rc); +- } ++ } else ++ trace_smb3_flush_done(xid, persistent_fid, tcon->tid, ++ ses->Suid); + + flush_exit: + SMB2_flush_free(&rqst); +diff --git a/fs/cifs/trace.h b/fs/cifs/trace.h +index 99c4d799c24b..f1339f4a2d07 100644 +--- a/fs/cifs/trace.h ++++ b/fs/cifs/trace.h +@@ -117,6 +117,41 @@ DEFINE_SMB3_RW_DONE_EVENT(falloc_done); + /* + * For handle based calls other than read and write, and get/set info + */ ++DECLARE_EVENT_CLASS(smb3_fd_class, ++ TP_PROTO(unsigned int xid, ++ __u64 fid, ++ __u32 tid, ++ __u64 sesid), ++ TP_ARGS(xid, fid, tid, sesid), ++ TP_STRUCT__entry( ++ __field(unsigned int, xid) ++ __field(__u64, fid) ++ __field(__u32, tid) ++ __field(__u64, sesid) ++ ), ++ TP_fast_assign( ++ __entry->xid = xid; ++ __entry->fid = fid; ++ __entry->tid = tid; ++ __entry->sesid = sesid; ++ ), ++ TP_printk("\txid=%u sid=0x%llx tid=0x%x fid=0x%llx", ++ __entry->xid, __entry->sesid, __entry->tid, __entry->fid) ++) ++ ++#define DEFINE_SMB3_FD_EVENT(name) \ ++DEFINE_EVENT(smb3_fd_class, smb3_##name, \ ++ TP_PROTO(unsigned int xid, \ ++ __u64 fid, \ ++ __u32 tid, \ ++ __u64 sesid), \ ++ TP_ARGS(xid, fid, tid, sesid)) ++ ++DEFINE_SMB3_FD_EVENT(flush_enter); ++DEFINE_SMB3_FD_EVENT(flush_done); ++DEFINE_SMB3_FD_EVENT(close_enter); ++DEFINE_SMB3_FD_EVENT(close_done); ++ + DECLARE_EVENT_CLASS(smb3_fd_err_class, + TP_PROTO(unsigned int xid, + __u64 fid, +-- +2.25.1 + + diff --git a/patches.suse/smb3-add-missing-flag-definitions.patch b/patches.suse/smb3-add-missing-flag-definitions.patch new file mode 100644 index 0000000..bc45da4 --- /dev/null +++ b/patches.suse/smb3-add-missing-flag-definitions.patch @@ -0,0 +1,37 @@ +From: Steve French +Date: Thu, 25 Jul 2019 18:19:42 -0500 +Subject: [PATCH] smb3: add missing flag definitions +Git-commit: 59519803a9adb991876cd0bb055b4791d7e26cef +References: bsc#1144333 +Patch-mainline: v5.4-rc1 + +SMB3 and 3.1.1 added two additional flags including +the priority mask. Add them to our protocol definitions +in smb2pdu.h. See MS-SMB2 2.2.1.2 + +Signed-off-by: Steve French +Signed-off-by: Ronnie Sahlberg +Reviewed-by: Pavel Shilovsky +Acked-by: Paulo Alcantara +--- + fs/cifs/smb2pdu.h | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/fs/cifs/smb2pdu.h b/fs/cifs/smb2pdu.h +index 747de9317659..ea735d59c36e 100644 +--- a/fs/cifs/smb2pdu.h ++++ b/fs/cifs/smb2pdu.h +@@ -143,7 +143,9 @@ struct smb2_transform_hdr { + #define SMB2_FLAGS_ASYNC_COMMAND cpu_to_le32(0x00000002) + #define SMB2_FLAGS_RELATED_OPERATIONS cpu_to_le32(0x00000004) + #define SMB2_FLAGS_SIGNED cpu_to_le32(0x00000008) ++#define SMB2_FLAGS_PRIORITY_MASK cpu_to_le32(0x00000070) /* SMB3.1.1 */ + #define SMB2_FLAGS_DFS_OPERATIONS cpu_to_le32(0x10000000) ++#define SMB2_FLAGS_REPLAY_OPERATION cpu_to_le32(0x20000000) /* SMB3 & up */ + + /* + * Definitions for SMB2 Protocol Data Units (network frames) +-- +2.25.1 + + diff --git a/patches.suse/smb3-add-missing-worker-function-for-SMB3-change-notify.patch b/patches.suse/smb3-add-missing-worker-function-for-SMB3-change-notify.patch new file mode 100644 index 0000000..02df283 --- /dev/null +++ b/patches.suse/smb3-add-missing-worker-function-for-SMB3-change-notify.patch @@ -0,0 +1,141 @@ +From: Steve French +Date: Sun, 15 Sep 2019 22:38:52 -0500 +Subject: [PATCH] smb3: add missing worker function for SMB3 change notify +Git-commit: c3498185b7898d770f9f7148c78b9daade5e54ec +References: bsc#1144333 +Patch-mainline: v5.4-rc1 + +SMB3 change notify is important to allow applications to wait +on directory change events of different types (e.g. adding +and deleting files from others systems). Add worker functions +for this. + +Acked-by: Aurelien Aptel +Signed-off-by: Steve French +Acked-by: Paulo Alcantara +--- + fs/cifs/smb2pdu.c | 85 +++++++++++++++++++++++++++++++++++++++++++++++ + fs/cifs/trace.h | 3 ++ + 2 files changed, 88 insertions(+) + +diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c +index ce647cfdc04f..87066f1af12c 100644 +--- a/fs/cifs/smb2pdu.c ++++ b/fs/cifs/smb2pdu.c +@@ -3175,6 +3175,91 @@ SMB2_get_srv_num(const unsigned int xid, struct cifs_tcon *tcon, + (void **)&uniqueid, NULL); + } + ++/* ++ * CHANGE_NOTIFY Request is sent to get notifications on changes to a directory ++ * See MS-SMB2 2.2.35 and 2.2.36 ++ */ ++ ++int ++SMB2_notify_init(const unsigned int xid, struct smb_rqst *rqst, ++ struct cifs_tcon *tcon, u64 persistent_fid, u64 volatile_fid, ++ u32 completion_filter, bool watch_tree) ++{ ++ struct smb2_change_notify_req *req; ++ struct kvec *iov = rqst->rq_iov; ++ unsigned int total_len; ++ int rc; ++ ++ rc = smb2_plain_req_init(SMB2_CHANGE_NOTIFY, tcon, (void **) &req, &total_len); ++ if (rc) ++ return rc; ++ ++ req->PersistentFileId = persistent_fid; ++ req->VolatileFileId = volatile_fid; ++ req->OutputBufferLength = SMB2_MAX_BUFFER_SIZE - MAX_SMB2_HDR_SIZE; ++ req->CompletionFilter = cpu_to_le32(completion_filter); ++ if (watch_tree) ++ req->Flags = cpu_to_le16(SMB2_WATCH_TREE); ++ else ++ req->Flags = 0; ++ ++ iov[0].iov_base = (char *)req; ++ iov[0].iov_len = total_len; ++ ++ return 0; ++} ++ ++int ++SMB2_change_notify(const unsigned int xid, struct cifs_tcon *tcon, ++ u64 persistent_fid, u64 volatile_fid, bool watch_tree, ++ u32 completion_filter) ++{ ++ struct cifs_ses *ses = tcon->ses; ++ struct smb_rqst rqst; ++ struct kvec iov[1]; ++ struct kvec rsp_iov = {NULL, 0}; ++ int resp_buftype = CIFS_NO_BUFFER; ++ int flags = 0; ++ int rc = 0; ++ ++ cifs_dbg(FYI, "change notify\n"); ++ if (!ses || !(ses->server)) ++ return -EIO; ++ ++ if (smb3_encryption_required(tcon)) ++ flags |= CIFS_TRANSFORM_REQ; ++ ++ memset(&rqst, 0, sizeof(struct smb_rqst)); ++ memset(&iov, 0, sizeof(iov)); ++ rqst.rq_iov = iov; ++ rqst.rq_nvec = 1; ++ ++ rc = SMB2_notify_init(xid, &rqst, tcon, persistent_fid, volatile_fid, ++ completion_filter, watch_tree); ++ if (rc) ++ goto cnotify_exit; ++ ++ trace_smb3_notify_enter(xid, persistent_fid, tcon->tid, ses->Suid, ++ (u8)watch_tree, completion_filter); ++ rc = cifs_send_recv(xid, ses, &rqst, &resp_buftype, flags, &rsp_iov); ++ ++ if (rc != 0) { ++ cifs_stats_fail_inc(tcon, SMB2_CHANGE_NOTIFY_HE); ++ trace_smb3_notify_err(xid, persistent_fid, tcon->tid, ses->Suid, ++ (u8)watch_tree, completion_filter, rc); ++ } else ++ trace_smb3_notify_done(xid, persistent_fid, tcon->tid, ++ ses->Suid, (u8)watch_tree, completion_filter); ++ ++ cnotify_exit: ++ if (rqst.rq_iov) ++ cifs_small_buf_release(rqst.rq_iov[0].iov_base); /* request */ ++ free_rsp_buf(resp_buftype, rsp_iov.iov_base); ++ return rc; ++} ++ ++ ++ + /* + * This is a no-op for now. We're not really interested in the reply, but + * rather in the fact that the server sent one and that server->lstrp +diff --git a/fs/cifs/trace.h b/fs/cifs/trace.h +index f1339f4a2d07..e7e350b13d6a 100644 +--- a/fs/cifs/trace.h ++++ b/fs/cifs/trace.h +@@ -235,6 +235,8 @@ DEFINE_EVENT(smb3_inf_enter_class, smb3_##name, \ + + DEFINE_SMB3_INF_ENTER_EVENT(query_info_enter); + DEFINE_SMB3_INF_ENTER_EVENT(query_info_done); ++DEFINE_SMB3_INF_ENTER_EVENT(notify_enter); ++DEFINE_SMB3_INF_ENTER_EVENT(notify_done); + + DECLARE_EVENT_CLASS(smb3_inf_err_class, + TP_PROTO(unsigned int xid, +@@ -281,6 +283,7 @@ DEFINE_EVENT(smb3_inf_err_class, smb3_##name, \ + + DEFINE_SMB3_INF_ERR_EVENT(query_info_err); + DEFINE_SMB3_INF_ERR_EVENT(set_info_err); ++DEFINE_SMB3_INF_ERR_EVENT(notify_err); + DEFINE_SMB3_INF_ERR_EVENT(fsctl_err); + + DECLARE_EVENT_CLASS(smb3_inf_compound_enter_class, +-- +2.25.1 + + diff --git a/patches.suse/smb3-add-mount-option-to-allow-RW-caching-of-share-accessed-by-only.patch b/patches.suse/smb3-add-mount-option-to-allow-RW-caching-of-share-accessed-by-only.patch new file mode 100644 index 0000000..7a1fd56 --- /dev/null +++ b/patches.suse/smb3-add-mount-option-to-allow-RW-caching-of-share-accessed-by-only.patch @@ -0,0 +1,158 @@ +From: Steve French +Date: Fri, 30 Aug 2019 02:12:41 -0500 +Subject: [PATCH] smb3: add mount option to allow RW caching of share accessed + by only 1 client +Git-commit: 41e033fecdc891da629113c4f8ee80500b7656d6 +References: bsc#1144333 +Patch-mainline: v5.4-rc1 + +If a share is known to be only to be accessed by one client, we +can aggressively cache writes not just reads to it. + +Add "cache=" option (cache=singleclient) for mounting read write shares +(that will not be read or written to from other clients while we have +it mounted) in order to improve performance. + +Signed-off-by: Steve French +Acked-by: Paulo Alcantara +--- + fs/cifs/cifs_fs_sb.h | 1 + + fs/cifs/cifsfs.c | 2 ++ + fs/cifs/cifsglob.h | 5 +++-- + fs/cifs/connect.c | 20 +++++++++++++++++++- + 4 files changed, 25 insertions(+), 3 deletions(-) + +diff --git a/fs/cifs/cifs_fs_sb.h b/fs/cifs/cifs_fs_sb.h +index 286a104c4761..6e7c4427369d 100644 +--- a/fs/cifs/cifs_fs_sb.h ++++ b/fs/cifs/cifs_fs_sb.h +@@ -54,6 +54,7 @@ + #define CIFS_MOUNT_NO_DFS 0x8000000 /* disable DFS resolving */ + #define CIFS_MOUNT_MODE_FROM_SID 0x10000000 /* retrieve mode from special ACE */ + #define CIFS_MOUNT_RO_CACHE 0x20000000 /* assumes share will not change */ ++#define CIFS_MOUNT_RW_CACHE 0x40000000 /* assumes only client accessing */ + + struct cifs_sb_info { + struct rb_root tlink_tree; +diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c +index 970251bc0661..de90e665ef11 100644 +--- a/fs/cifs/cifsfs.c ++++ b/fs/cifs/cifsfs.c +@@ -400,6 +400,8 @@ cifs_show_cache_flavor(struct seq_file *s, struct cifs_sb_info *cifs_sb) + seq_puts(s, "strict"); + else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO) + seq_puts(s, "none"); ++ else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RW_CACHE) ++ seq_puts(s, "singleclient"); /* assume only one client access */ + else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RO_CACHE) + seq_puts(s, "ro"); /* read only caching assumed */ + else +diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h +index 3f12da7f2f7f..fa5abe3a8514 100644 +--- a/fs/cifs/cifsglob.h ++++ b/fs/cifs/cifsglob.h +@@ -560,6 +560,7 @@ struct smb_vol { + bool direct_io:1; + bool strict_io:1; /* strict cache behavior */ + bool cache_ro:1; ++ bool cache_rw:1; + bool remap:1; /* set to remap seven reserved chars in filenames */ + bool sfu_remap:1; /* remap seven reserved chars ala SFU */ + bool posix_paths:1; /* unset to not ask for posix pathnames. */ +@@ -622,7 +623,7 @@ struct smb_vol { + CIFS_MOUNT_CIFS_BACKUPUID | CIFS_MOUNT_CIFS_BACKUPGID | \ + CIFS_MOUNT_UID_FROM_ACL | CIFS_MOUNT_NO_HANDLE_CACHE | \ + CIFS_MOUNT_NO_DFS | CIFS_MOUNT_MODE_FROM_SID | \ +- CIFS_MOUNT_RO_CACHE) ++ CIFS_MOUNT_RO_CACHE | CIFS_MOUNT_RW_CACHE) + + /** + * Generic VFS superblock mount flags (s_flags) to consider when +@@ -1370,7 +1371,7 @@ void cifsFileInfo_put(struct cifsFileInfo *cifs_file); + + #define CIFS_CACHE_READ(cinode) ((cinode->oplock & CIFS_CACHE_READ_FLG) || (CIFS_SB(cinode->vfs_inode.i_sb)->mnt_cifs_flags & CIFS_MOUNT_RO_CACHE)) + #define CIFS_CACHE_HANDLE(cinode) (cinode->oplock & CIFS_CACHE_HANDLE_FLG) +-#define CIFS_CACHE_WRITE(cinode) (cinode->oplock & CIFS_CACHE_WRITE_FLG) ++#define CIFS_CACHE_WRITE(cinode) ((cinode->oplock & CIFS_CACHE_WRITE_FLG) || (CIFS_SB(cinode->vfs_inode.i_sb)->mnt_cifs_flags & CIFS_MOUNT_RW_CACHE)) + + /* + * One of these for each file inode +diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c +index 072c01f4e9c1..d9a995588c74 100644 +--- a/fs/cifs/connect.c ++++ b/fs/cifs/connect.c +@@ -299,6 +299,7 @@ enum { + Opt_cache_strict, + Opt_cache_none, + Opt_cache_ro, ++ Opt_cache_rw, + Opt_cache_err + }; + +@@ -307,6 +308,7 @@ static const match_table_t cifs_cacheflavor_tokens = { + { Opt_cache_strict, "strict" }, + { Opt_cache_none, "none" }, + { Opt_cache_ro, "ro" }, ++ { Opt_cache_rw, "singleclient" }, + { Opt_cache_err, NULL } + }; + +@@ -1421,21 +1423,31 @@ cifs_parse_cache_flavor(char *value, struct smb_vol *vol) + vol->direct_io = false; + vol->strict_io = false; + vol->cache_ro = false; ++ vol->cache_rw = false; + break; + case Opt_cache_strict: + vol->direct_io = false; + vol->strict_io = true; + vol->cache_ro = false; ++ vol->cache_rw = false; + break; + case Opt_cache_none: + vol->direct_io = true; + vol->strict_io = false; + vol->cache_ro = false; ++ vol->cache_rw = false; + break; + case Opt_cache_ro: + vol->direct_io = false; + vol->strict_io = false; + vol->cache_ro = true; ++ vol->cache_rw = false; ++ break; ++ case Opt_cache_rw: ++ vol->direct_io = false; ++ vol->strict_io = false; ++ vol->cache_ro = false; ++ vol->cache_rw = true; + break; + default: + cifs_dbg(VFS, "bad cache= option: %s\n", value); +@@ -4054,6 +4066,10 @@ int cifs_setup_cifs_sb(struct smb_vol *pvolume_info, + if (pvolume_info->cache_ro) { + cifs_dbg(VFS, "mounting share with read only caching. Ensure that the share will not be modified while in use.\n"); + cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_RO_CACHE; ++ } else if (pvolume_info->cache_rw) { ++ cifs_dbg(VFS, "mounting share in single client RW caching mode. Ensure that no other systems will be accessing the share.\n"); ++ cifs_sb->mnt_cifs_flags |= (CIFS_MOUNT_RO_CACHE | ++ CIFS_MOUNT_RW_CACHE); + } + if (pvolume_info->mfsymlinks) { + if (pvolume_info->sfu_emul) { +@@ -4203,8 +4219,10 @@ static int mount_get_conns(struct smb_vol *vol, struct cifs_sb_info *cifs_sb, + if (tcon->fsDevInfo.DeviceCharacteristics & + FILE_READ_ONLY_DEVICE) + cifs_dbg(VFS, "mounted to read only share\n"); +- else ++ else if ((cifs_sb->mnt_cifs_flags & ++ CIFS_MOUNT_RW_CACHE) == 0) + cifs_dbg(VFS, "read only mount of RW share\n"); ++ /* no need to log a RW mount of a typical RW share */ + } + } + +-- +2.25.1 + + diff --git a/patches.suse/smb3-add-mount-option-to-allow-forced-caching-of-read-only-share.patch b/patches.suse/smb3-add-mount-option-to-allow-forced-caching-of-read-only-share.patch new file mode 100644 index 0000000..2e4aed2 --- /dev/null +++ b/patches.suse/smb3-add-mount-option-to-allow-forced-caching-of-read-only-share.patch @@ -0,0 +1,139 @@ +From: Steve French +Date: Tue, 27 Aug 2019 23:58:54 -0500 +Subject: [PATCH] smb3: add mount option to allow forced caching of read only + share +Git-commit: 83bbfa706dda668deb60e96df20327fc79e1716f +References: bsc#1144333 +Patch-mainline: v5.4-rc1 + +If a share is immutable (at least for the period that it will +be mounted) it would be helpful to not have to revalidate +dentries repeatedly that we know can not be changed remotely. + +Add "cache=" option (cache=ro) for mounting read only shares +in order to improve performance in cases in which we know that +the share will not be changing while it is in use. + +Signed-off-by: Steve French +Acked-by: Paulo Alcantara +--- + fs/cifs/cifs_fs_sb.h | 1 + + fs/cifs/cifsfs.c | 2 ++ + fs/cifs/cifsglob.h | 6 ++++-- + fs/cifs/connect.c | 14 ++++++++++++++ + 4 files changed, 21 insertions(+), 2 deletions(-) + +diff --git a/fs/cifs/cifs_fs_sb.h b/fs/cifs/cifs_fs_sb.h +index b326d2ca3765..286a104c4761 100644 +--- a/fs/cifs/cifs_fs_sb.h ++++ b/fs/cifs/cifs_fs_sb.h +@@ -53,6 +53,7 @@ + #define CIFS_MOUNT_NO_HANDLE_CACHE 0x4000000 /* disable caching dir handles */ + #define CIFS_MOUNT_NO_DFS 0x8000000 /* disable DFS resolving */ + #define CIFS_MOUNT_MODE_FROM_SID 0x10000000 /* retrieve mode from special ACE */ ++#define CIFS_MOUNT_RO_CACHE 0x20000000 /* assumes share will not change */ + + struct cifs_sb_info { + struct rb_root tlink_tree; +diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c +index 3289b566463f..970251bc0661 100644 +--- a/fs/cifs/cifsfs.c ++++ b/fs/cifs/cifsfs.c +@@ -400,6 +400,8 @@ cifs_show_cache_flavor(struct seq_file *s, struct cifs_sb_info *cifs_sb) + seq_puts(s, "strict"); + else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO) + seq_puts(s, "none"); ++ else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RO_CACHE) ++ seq_puts(s, "ro"); /* read only caching assumed */ + else + seq_puts(s, "loose"); + } +diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h +index fe610e7e3670..3f12da7f2f7f 100644 +--- a/fs/cifs/cifsglob.h ++++ b/fs/cifs/cifsglob.h +@@ -559,6 +559,7 @@ struct smb_vol { + bool server_ino:1; /* use inode numbers from server ie UniqueId */ + bool direct_io:1; + bool strict_io:1; /* strict cache behavior */ ++ bool cache_ro:1; + bool remap:1; /* set to remap seven reserved chars in filenames */ + bool sfu_remap:1; /* remap seven reserved chars ala SFU */ + bool posix_paths:1; /* unset to not ask for posix pathnames. */ +@@ -620,7 +621,8 @@ struct smb_vol { + CIFS_MOUNT_MULTIUSER | CIFS_MOUNT_STRICT_IO | \ + CIFS_MOUNT_CIFS_BACKUPUID | CIFS_MOUNT_CIFS_BACKUPGID | \ + CIFS_MOUNT_UID_FROM_ACL | CIFS_MOUNT_NO_HANDLE_CACHE | \ +- CIFS_MOUNT_NO_DFS | CIFS_MOUNT_MODE_FROM_SID) ++ CIFS_MOUNT_NO_DFS | CIFS_MOUNT_MODE_FROM_SID | \ ++ CIFS_MOUNT_RO_CACHE) + + /** + * Generic VFS superblock mount flags (s_flags) to consider when +@@ -1366,7 +1368,7 @@ void cifsFileInfo_put(struct cifsFileInfo *cifs_file); + #define CIFS_CACHE_RW_FLG (CIFS_CACHE_READ_FLG | CIFS_CACHE_WRITE_FLG) + #define CIFS_CACHE_RHW_FLG (CIFS_CACHE_RW_FLG | CIFS_CACHE_HANDLE_FLG) + +-#define CIFS_CACHE_READ(cinode) (cinode->oplock & CIFS_CACHE_READ_FLG) ++#define CIFS_CACHE_READ(cinode) ((cinode->oplock & CIFS_CACHE_READ_FLG) || (CIFS_SB(cinode->vfs_inode.i_sb)->mnt_cifs_flags & CIFS_MOUNT_RO_CACHE)) + #define CIFS_CACHE_HANDLE(cinode) (cinode->oplock & CIFS_CACHE_HANDLE_FLG) + #define CIFS_CACHE_WRITE(cinode) (cinode->oplock & CIFS_CACHE_WRITE_FLG) + +diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c +index 1efbbfffddba..4e622953dd5a 100644 +--- a/fs/cifs/connect.c ++++ b/fs/cifs/connect.c +@@ -298,6 +298,7 @@ enum { + Opt_cache_loose, + Opt_cache_strict, + Opt_cache_none, ++ Opt_cache_ro, + Opt_cache_err + }; + +@@ -305,6 +306,7 @@ static const match_table_t cifs_cacheflavor_tokens = { + { Opt_cache_loose, "loose" }, + { Opt_cache_strict, "strict" }, + { Opt_cache_none, "none" }, ++ { Opt_cache_ro, "ro" }, + { Opt_cache_err, NULL } + }; + +@@ -1418,14 +1420,22 @@ cifs_parse_cache_flavor(char *value, struct smb_vol *vol) + case Opt_cache_loose: + vol->direct_io = false; + vol->strict_io = false; ++ vol->cache_ro = false; + break; + case Opt_cache_strict: + vol->direct_io = false; + vol->strict_io = true; ++ vol->cache_ro = false; + break; + case Opt_cache_none: + vol->direct_io = true; + vol->strict_io = false; ++ vol->cache_ro = false; ++ break; ++ case Opt_cache_ro: ++ vol->direct_io = false; ++ vol->strict_io = false; ++ vol->cache_ro = true; + break; + default: + cifs_dbg(VFS, "bad cache= option: %s\n", value); +@@ -4041,6 +4051,10 @@ int cifs_setup_cifs_sb(struct smb_vol *pvolume_info, + cifs_dbg(FYI, "mounting share using direct i/o\n"); + cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DIRECT_IO; + } ++ if (pvolume_info->cache_ro) { ++ cifs_dbg(VFS, "mounting share with read only caching. Ensure that the share will not be modified while in use.\n"); ++ cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_RO_CACHE; ++ } + if (pvolume_info->mfsymlinks) { + if (pvolume_info->sfu_emul) { + /* +-- +2.25.1 + + diff --git a/patches.suse/smb3-add-one-more-dynamic-tracepoint-missing-from-strict-fsync-path.patch b/patches.suse/smb3-add-one-more-dynamic-tracepoint-missing-from-strict-fsync-path.patch new file mode 100644 index 0000000..da069e0 --- /dev/null +++ b/patches.suse/smb3-add-one-more-dynamic-tracepoint-missing-from-strict-fsync-path.patch @@ -0,0 +1,36 @@ +From: Steve French +Date: Thu, 6 Feb 2020 16:04:59 -0600 +Subject: [PATCH] smb3: add one more dynamic tracepoint missing from strict + fsync path +Git-commit: 2391ca41b476078da5cf72c2fe82ae9f03da8b38 +References: bsc#1144333 +Patch-mainline: v5.6-rc1 + +We didn't have a dynamic trace point for catching errors in +file_write_and_wait_range error cases in cifs_strict_fsync. + +Since not all apps check for write behind errors, it can be +important for debugging to be able to trace these error +paths. + +Suggested-and-reviewed-by: Pavel Shilovsky +Signed-off-by: Steve French +Acked-by: Paulo Alcantara +--- + fs/cifs/file.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +--- a/fs/cifs/file.c ++++ b/fs/cifs/file.c +@@ -2610,8 +2610,10 @@ int cifs_strict_fsync(struct file *file, + struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); + + rc = filemap_write_and_wait_range(inode->i_mapping, start, end); +- if (rc) ++ if (rc) { ++ trace_cifs_fsync_err(inode->i_ino, rc); + return rc; ++ } + inode_lock(inode); + + xid = get_xid(); diff --git a/patches.suse/smb3-add-some-more-descriptive-messages-about-share-when-mounting-c.patch b/patches.suse/smb3-add-some-more-descriptive-messages-about-share-when-mounting-c.patch new file mode 100644 index 0000000..f8da1f1 --- /dev/null +++ b/patches.suse/smb3-add-some-more-descriptive-messages-about-share-when-mounting-c.patch @@ -0,0 +1,52 @@ +From: Steve French +Date: Thu, 29 Aug 2019 22:33:38 -0500 +Subject: [PATCH] smb3: add some more descriptive messages about share when + mounting cache=ro +Git-commit: 1981ebaabd88a9b3e550b6163c570a498c32a1f5 +References: bsc#1144333 +Patch-mainline: v5.4-rc1 + +Add some additional logging so the user can see if the share they +mounted with cache=ro is considered read only by the server + +CIFS: Attempting to mount //localhost/test +CIFS VFS: mounting share with read only caching. Ensure that the share will not be modified while in use. +CIFS VFS: read only mount of RW share + +CIFS: Attempting to mount //localhost/test-ro +CIFS VFS: mounting share with read only caching. Ensure that the share will not be modified while in use. +CIFS VFS: mounted to read only share + +Signed-off-by: Steve French +Reviewed-by: Ronnie Sahlberg +Acked-by: Paulo Alcantara +--- + fs/cifs/connect.c | 10 +++++++++- + 1 file changed, 9 insertions(+), 1 deletion(-) + +diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c +index 4e622953dd5a..072c01f4e9c1 100644 +--- a/fs/cifs/connect.c ++++ b/fs/cifs/connect.c +@@ -4197,8 +4197,16 @@ static int mount_get_conns(struct smb_vol *vol, struct cifs_sb_info *cifs_sb, + tcon->unix_ext = 0; /* server does not support them */ + + /* do not care if a following call succeed - informational */ +- if (!tcon->pipe && server->ops->qfs_tcon) ++ if (!tcon->pipe && server->ops->qfs_tcon) { + server->ops->qfs_tcon(*xid, tcon); ++ if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RO_CACHE) { ++ if (tcon->fsDevInfo.DeviceCharacteristics & ++ FILE_READ_ONLY_DEVICE) ++ cifs_dbg(VFS, "mounted to read only share\n"); ++ else ++ cifs_dbg(VFS, "read only mount of RW share\n"); ++ } ++ } + + cifs_sb->wsize = server->ops->negotiate_wsize(tcon, vol); + cifs_sb->rsize = server->ops->negotiate_rsize(tcon, vol); +-- +2.25.1 + + diff --git a/patches.suse/smb3-allow-decryption-keys-to-be-dumped-by-admin-for-debugging.patch b/patches.suse/smb3-allow-decryption-keys-to-be-dumped-by-admin-for-debugging.patch new file mode 100644 index 0000000..b661788 --- /dev/null +++ b/patches.suse/smb3-allow-decryption-keys-to-be-dumped-by-admin-for-debugging.patch @@ -0,0 +1,107 @@ +From: Steve French +Date: Thu, 19 Sep 2019 04:00:55 -0500 +Subject: [PATCH] smb3: allow decryption keys to be dumped by admin for + debugging +Git-commit: 7e7db86c7e1088e768438fe6c894d748b0c32abe +References: bsc#1144333 +Patch-mainline: v5.4-rc1 + +In order to debug certain problems it is important to be able +to decrypt network traces (e.g. wireshark) but to do this we +need to be able to dump out the encryption/decryption keys. +Dumping them to an ioctl is safer than dumping then to dmesg, +(and better than showing all keys in a pseudofile). + +Restrict this to root (CAP_SYS_ADMIN), and only for a mount +that this admin has access to. + +Sample smbinfo output: +SMB3.0 encryption +Session Id: 0x82d2ec52 +Session Key: a5 6d 81 d0 e c1 ca e1 d8 13 aa 20 e8 f2 cc 71 +Server Encryption Key: 1a c3 be ba 3d fc dc 3c e bc 93 9e 50 9e 19 c1 +Server Decryption Key: e0 d4 d9 43 1b a2 1b e3 d8 76 77 49 56 f7 20 88 + +Reviewed-by: Aurelien Aptel +Pavel Shilovsky +Signed-off-by: Steve French +Acked-by: Paulo Alcantara +--- + fs/cifs/cifs_ioctl.h | 9 +++++++++ + fs/cifs/ioctl.c | 29 +++++++++++++++++++++++++++++ + 2 files changed, 38 insertions(+) + +diff --git a/fs/cifs/cifs_ioctl.h b/fs/cifs/cifs_ioctl.h +index 6c3bd07868d7..0f0dc1c1fe41 100644 +--- a/fs/cifs/cifs_ioctl.h ++++ b/fs/cifs/cifs_ioctl.h +@@ -57,9 +57,18 @@ struct smb_query_info { + /* char buffer[]; */ + } __packed; + ++struct smb3_key_debug_info { ++ __u64 Suid; ++ __u16 cipher_type; ++ __u8 auth_key[16]; /* SMB2_NTLMV2_SESSKEY_SIZE */ ++ __u8 smb3encryptionkey[SMB3_SIGN_KEY_SIZE]; ++ __u8 smb3decryptionkey[SMB3_SIGN_KEY_SIZE]; ++} __packed; ++ + #define CIFS_IOCTL_MAGIC 0xCF + #define CIFS_IOC_COPYCHUNK_FILE _IOW(CIFS_IOCTL_MAGIC, 3, int) + #define CIFS_IOC_SET_INTEGRITY _IO(CIFS_IOCTL_MAGIC, 4) + #define CIFS_IOC_GET_MNT_INFO _IOR(CIFS_IOCTL_MAGIC, 5, struct smb_mnt_fs_info) + #define CIFS_ENUMERATE_SNAPSHOTS _IOR(CIFS_IOCTL_MAGIC, 6, struct smb_snapshot_array) + #define CIFS_QUERY_INFO _IOWR(CIFS_IOCTL_MAGIC, 7, struct smb_query_info) ++#define CIFS_DUMP_KEY _IOWR(CIFS_IOCTL_MAGIC, 8, struct smb3_key_debug_info) +diff --git a/fs/cifs/ioctl.c b/fs/cifs/ioctl.c +index 76ddd98b6298..1a01e108d75e 100644 +--- a/fs/cifs/ioctl.c ++++ b/fs/cifs/ioctl.c +@@ -164,6 +164,7 @@ static long smb_mnt_get_fsinfo(unsigned int xid, struct cifs_tcon *tcon, + long cifs_ioctl(struct file *filep, unsigned int command, unsigned long arg) + { + struct inode *inode = file_inode(filep); ++ struct smb3_key_debug_info pkey_inf; + int rc = -ENOTTY; /* strange error - but the precedent */ + unsigned int xid; + struct cifsFileInfo *pSMBFile = filep->private_data; +@@ -270,6 +271,34 @@ long cifs_ioctl(struct file *filep, unsigned int command, unsigned long arg) + else + rc = -EOPNOTSUPP; + break; ++ case CIFS_DUMP_KEY: ++ if (pSMBFile == NULL) ++ break; ++ if (!capable(CAP_SYS_ADMIN)) { ++ rc = -EACCES; ++ break; ++ } ++ ++ tcon = tlink_tcon(pSMBFile->tlink); ++ if (!smb3_encryption_required(tcon)) { ++ rc = -EOPNOTSUPP; ++ break; ++ } ++ pkey_inf.cipher_type = ++ le16_to_cpu(tcon->ses->server->cipher_type); ++ pkey_inf.Suid = tcon->ses->Suid; ++ memcpy(pkey_inf.auth_key, tcon->ses->auth_key.response, ++ 16 /* SMB2_NTLMV2_SESSKEY_SIZE */); ++ memcpy(pkey_inf.smb3decryptionkey, ++ tcon->ses->smb3decryptionkey, SMB3_SIGN_KEY_SIZE); ++ memcpy(pkey_inf.smb3encryptionkey, ++ tcon->ses->smb3encryptionkey, SMB3_SIGN_KEY_SIZE); ++ if (copy_to_user((void __user *)arg, &pkey_inf, ++ sizeof(struct smb3_key_debug_info))) ++ rc = -EFAULT; ++ else ++ rc = 0; ++ break; + default: + cifs_dbg(FYI, "unsupported ioctl\n"); + break; +-- +2.25.1 + + diff --git a/patches.suse/smb3-allow-disabling-requesting-leases.patch b/patches.suse/smb3-allow-disabling-requesting-leases.patch new file mode 100644 index 0000000..d9c3000 --- /dev/null +++ b/patches.suse/smb3-allow-disabling-requesting-leases.patch @@ -0,0 +1,127 @@ +From: Steve French +Date: Wed, 11 Sep 2019 21:46:20 -0500 +Subject: [PATCH] smb3: allow disabling requesting leases +Git-commit: 3e7a02d47872081f4b6234a9f72500f1d10f060c +References: bsc#1144333 +Patch-mainline: v5.4-rc1 + +In some cases to work around server bugs or performance +problems it can be helpful to be able to disable requesting +SMB2.1/SMB3 leases on a particular mount (not to all servers +and all shares we are mounted to). Add new mount parm +"nolease" which turns off requesting leases on directory +or file opens. Currently the only way to disable leases is +globally through a module load parameter. This is more +granular. + +Suggested-by: Pavel Shilovsky +Signed-off-by: Steve French +Reviewed-by: Ronnie Sahlberg +Reviewed-by: Pavel Shilovsky +CC: Stable +Acked-by: Paulo Alcantara +--- + fs/cifs/cifsfs.c | 2 ++ + fs/cifs/cifsglob.h | 2 ++ + fs/cifs/connect.c | 9 ++++++++- + fs/cifs/smb2pdu.c | 2 +- + 4 files changed, 13 insertions(+), 2 deletions(-) + +diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c +index c1b685072063..69601a9b29ad 100644 +--- a/fs/cifs/cifsfs.c ++++ b/fs/cifs/cifsfs.c +@@ -438,6 +438,8 @@ cifs_show_options(struct seq_file *s, struct dentry *root) + cifs_show_security(s, tcon->ses); + cifs_show_cache_flavor(s, cifs_sb); + ++ if (tcon->no_lease) ++ seq_puts(s, ",nolease"); + if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER) + seq_puts(s, ",multiuser"); + else if (tcon->ses->user_name) +diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h +index ef2199913217..09b60ec5de3e 100644 +--- a/fs/cifs/cifsglob.h ++++ b/fs/cifs/cifsglob.h +@@ -579,6 +579,7 @@ struct smb_vol { + bool noblocksnd:1; + bool noautotune:1; + bool nostrictsync:1; /* do not force expensive SMBflush on every sync */ ++ bool no_lease:1; /* disable requesting leases */ + bool fsc:1; /* enable fscache */ + bool mfsymlinks:1; /* use Minshall+French Symlinks */ + bool multiuser:1; +@@ -1090,6 +1091,7 @@ struct cifs_tcon { + bool need_reopen_files:1; /* need to reopen tcon file handles */ + bool use_resilient:1; /* use resilient instead of durable handles */ + bool use_persistent:1; /* use persistent instead of durable handles */ ++ bool no_lease:1; /* Do not request leases on files or directories */ + __le32 capabilities; + __u32 share_flags; + __u32 maximal_access; +diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c +index df1ccb581828..e16b6cc1e31b 100644 +--- a/fs/cifs/connect.c ++++ b/fs/cifs/connect.c +@@ -74,7 +74,7 @@ enum { + Opt_user_xattr, Opt_nouser_xattr, + Opt_forceuid, Opt_noforceuid, + Opt_forcegid, Opt_noforcegid, +- Opt_noblocksend, Opt_noautotune, ++ Opt_noblocksend, Opt_noautotune, Opt_nolease, + Opt_hard, Opt_soft, Opt_perm, Opt_noperm, + Opt_mapposix, Opt_nomapposix, + Opt_mapchars, Opt_nomapchars, Opt_sfu, +@@ -135,6 +135,7 @@ static const match_table_t cifs_mount_option_tokens = { + { Opt_noforcegid, "noforcegid" }, + { Opt_noblocksend, "noblocksend" }, + { Opt_noautotune, "noautotune" }, ++ { Opt_nolease, "nolease" }, + { Opt_hard, "hard" }, + { Opt_soft, "soft" }, + { Opt_perm, "perm" }, +@@ -1738,6 +1739,9 @@ cifs_parse_mount_options(const char *mountdata, const char *devname, + case Opt_noautotune: + vol->noautotune = 1; + break; ++ case Opt_nolease: ++ vol->no_lease = 1; ++ break; + case Opt_hard: + vol->retry = 1; + break; +@@ -3294,6 +3298,8 @@ static int match_tcon(struct cifs_tcon *tcon, struct smb_vol *volume_info) + return 0; + if (tcon->handle_timeout != volume_info->handle_timeout) + return 0; ++ if (tcon->no_lease != volume_info->no_lease) ++ return 0; + return 1; + } + +@@ -3516,6 +3522,7 @@ cifs_get_tcon(struct cifs_ses *ses, struct smb_vol *volume_info) + tcon->nocase = volume_info->nocase; + tcon->nohandlecache = volume_info->nohandlecache; + tcon->local_lease = volume_info->local_lease; ++ tcon->no_lease = volume_info->no_lease; + INIT_LIST_HEAD(&tcon->pending_opens); + + spin_lock(&cifs_tcp_ses_lock); +diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c +index 01d5c4af2458..ce647cfdc04f 100644 +--- a/fs/cifs/smb2pdu.c ++++ b/fs/cifs/smb2pdu.c +@@ -2459,7 +2459,7 @@ SMB2_open_init(struct cifs_tcon *tcon, struct smb_rqst *rqst, __u8 *oplock, + iov[1].iov_len = uni_path_len; + iov[1].iov_base = path; + +- if (!server->oplocks) ++ if ((!server->oplocks) || (tcon->no_lease)) + *oplock = SMB2_OPLOCK_LEVEL_NONE; + + if (!(server->capabilities & SMB2_GLOBAL_CAP_LEASING) || +-- +2.25.1 + + diff --git a/patches.suse/smb3-allow-parallelizing-decryption-of-reads.patch b/patches.suse/smb3-allow-parallelizing-decryption-of-reads.patch new file mode 100644 index 0000000..e95de22 --- /dev/null +++ b/patches.suse/smb3-allow-parallelizing-decryption-of-reads.patch @@ -0,0 +1,211 @@ +From: Steve French +Date: Sat, 7 Sep 2019 01:09:49 -0500 +Subject: [PATCH] smb3: allow parallelizing decryption of reads +Git-commit: 35cf94a397280b9e27576ac1480f631bdd3e7b70 +References: bsc#1144333 +Patch-mainline: v5.4-rc1 + +decrypting large reads on encrypted shares can be slow (e.g. adding +multiple milliseconds per-read on non-GCM capable servers or +when mounting with dialects prior to SMB3.1.1) - allow parallelizing +of read decryption by launching worker threads. + +Testing to Samba on localhost showed 25% improvement. +Testing to remote server showed very large improvement when +doing more than one 'cp' command was called at one time. + +Signed-off-by: Steve French +Signed-off-by: Ronnie Sahlberg +Acked-by: Paulo Alcantara +--- + fs/cifs/cifsfs.c | 17 +++++++++- + fs/cifs/cifsglob.h | 1 + + fs/cifs/smb2ops.c | 83 ++++++++++++++++++++++++++++++++++++++++++++-- + 3 files changed, 97 insertions(+), 4 deletions(-) + +diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c +index de90e665ef11..b0ea332af35c 100644 +--- a/fs/cifs/cifsfs.c ++++ b/fs/cifs/cifsfs.c +@@ -109,6 +109,7 @@ extern mempool_t *cifs_req_poolp; + extern mempool_t *cifs_mid_poolp; + + struct workqueue_struct *cifsiod_wq; ++struct workqueue_struct *decrypt_wq; + struct workqueue_struct *cifsoplockd_wq; + __u32 cifs_lock_secret; + +@@ -1499,11 +1500,22 @@ init_cifs(void) + goto out_clean_proc; + } + ++ /* ++ * BB Consider setting limit!=0 maybe to min(num_of_cores - 1, 3) so we ++ * don't launch too many worker threads ++ */ ++ decrypt_wq = alloc_workqueue("smb3decryptd", ++ WQ_FREEZABLE|WQ_MEM_RECLAIM, 0); ++ if (!decrypt_wq) { ++ rc = -ENOMEM; ++ goto out_destroy_cifsiod_wq; ++ } ++ + cifsoplockd_wq = alloc_workqueue("cifsoplockd", + WQ_FREEZABLE|WQ_MEM_RECLAIM, 0); + if (!cifsoplockd_wq) { + rc = -ENOMEM; +- goto out_destroy_cifsiod_wq; ++ goto out_destroy_decrypt_wq; + } + + rc = cifs_fscache_register(); +@@ -1569,6 +1581,8 @@ init_cifs(void) + cifs_fscache_unregister(); + out_destroy_cifsoplockd_wq: + destroy_workqueue(cifsoplockd_wq); ++out_destroy_decrypt_wq: ++ destroy_workqueue(decrypt_wq); + out_destroy_cifsiod_wq: + destroy_workqueue(cifsiod_wq); + out_clean_proc: +@@ -1595,6 +1609,7 @@ exit_cifs(void) + cifs_destroy_inodecache(); + cifs_fscache_unregister(); + destroy_workqueue(cifsoplockd_wq); ++ destroy_workqueue(decrypt_wq); + destroy_workqueue(cifsiod_wq); + cifs_proc_clean(); + } +diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h +index 1f53dee211d8..d66106ac031a 100644 +--- a/fs/cifs/cifsglob.h ++++ b/fs/cifs/cifsglob.h +@@ -1892,6 +1892,7 @@ void cifs_queue_oplock_break(struct cifsFileInfo *cfile); + + extern const struct slow_work_ops cifs_oplock_break_ops; + extern struct workqueue_struct *cifsiod_wq; ++extern struct workqueue_struct *decrypt_wq; + extern struct workqueue_struct *cifsoplockd_wq; + extern __u32 cifs_lock_secret; + +diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c +index 83b02d74d48e..c74284484947 100644 +--- a/fs/cifs/smb2ops.c ++++ b/fs/cifs/smb2ops.c +@@ -4017,8 +4017,58 @@ handle_read_data(struct TCP_Server_Info *server, struct mid_q_entry *mid, + return length; + } + ++struct smb2_decrypt_work { ++ struct work_struct decrypt; ++ struct TCP_Server_Info *server; ++ struct page **ppages; ++ char *buf; ++ unsigned int npages; ++ unsigned int len; ++}; ++ ++ ++static void smb2_decrypt_offload(struct work_struct *work) ++{ ++ struct smb2_decrypt_work *dw = container_of(work, ++ struct smb2_decrypt_work, decrypt); ++ int i, rc; ++ struct mid_q_entry *mid; ++ ++ rc = decrypt_raw_data(dw->server, dw->buf, dw->server->vals->read_rsp_size, ++ dw->ppages, dw->npages, dw->len); ++ if (rc) { ++ cifs_dbg(VFS, "error decrypting rc=%d\n", rc); ++ goto free_pages; ++ } ++ ++ mid = smb2_find_mid(dw->server, dw->buf); ++ if (mid == NULL) ++ cifs_dbg(FYI, "mid not found\n"); ++ else { ++ mid->decrypted = true; ++ rc = handle_read_data(dw->server, mid, dw->buf, ++ dw->server->vals->read_rsp_size, ++ dw->ppages, dw->npages, dw->len); ++ } ++ ++ dw->server->lstrp = jiffies; ++ ++ mid->callback(mid); ++ ++ cifs_mid_q_entry_release(mid); ++ ++free_pages: ++ for (i = dw->npages-1; i >= 0; i--) ++ put_page(dw->ppages[i]); ++ ++ kfree(dw->ppages); ++ cifs_small_buf_release(dw->buf); ++} ++ ++ + static int +-receive_encrypted_read(struct TCP_Server_Info *server, struct mid_q_entry **mid) ++receive_encrypted_read(struct TCP_Server_Info *server, struct mid_q_entry **mid, ++ int *num_mids) + { + char *buf = server->smallbuf; + struct smb2_transform_hdr *tr_hdr = (struct smb2_transform_hdr *)buf; +@@ -4028,7 +4078,9 @@ receive_encrypted_read(struct TCP_Server_Info *server, struct mid_q_entry **mid) + unsigned int buflen = server->pdu_size; + int rc; + int i = 0; ++ struct smb2_decrypt_work *dw; + ++ *num_mids = 1; + len = min_t(unsigned int, buflen, server->vals->read_rsp_size + + sizeof(struct smb2_transform_hdr)) - HEADER_SIZE(server) + 1; + +@@ -4064,6 +4116,32 @@ receive_encrypted_read(struct TCP_Server_Info *server, struct mid_q_entry **mid) + if (rc) + goto free_pages; + ++ /* ++ * For large reads, offload to different thread for better performance, ++ * use more cores decrypting which can be expensive ++ */ ++ ++ /* TODO: make the size limit to enable decrypt offload configurable */ ++ if (server->pdu_size > (512 * 1024)) { ++ dw = kmalloc(sizeof(struct smb2_decrypt_work), GFP_KERNEL); ++ if (dw == NULL) ++ goto non_offloaded_decrypt; ++ ++ dw->buf = server->smallbuf; ++ server->smallbuf = (char *)cifs_small_buf_get(); ++ ++ INIT_WORK(&dw->decrypt, smb2_decrypt_offload); ++ ++ dw->npages = npages; ++ dw->server = server; ++ dw->ppages = pages; ++ dw->len = len; ++ queue_work(cifsiod_wq, &dw->decrypt); ++ *num_mids = 0; /* worker thread takes care of finding mid */ ++ return -1; ++ } ++ ++non_offloaded_decrypt: + rc = decrypt_raw_data(server, buf, server->vals->read_rsp_size, + pages, npages, len); + if (rc) +@@ -4210,8 +4288,7 @@ smb3_receive_transform(struct TCP_Server_Info *server, + + /* TODO: add support for compounds containing READ. */ + if (pdu_length > CIFSMaxBufSize + MAX_HEADER_SIZE(server)) { +- *num_mids = 1; +- return receive_encrypted_read(server, &mids[0]); ++ return receive_encrypted_read(server, &mids[0], num_mids); + } + + return receive_encrypted_standard(server, mids, bufs, num_mids); +-- +2.25.1 + + diff --git a/patches.suse/smb3-allow-skipping-signature-verification-for-perf-sensitive-confi.patch b/patches.suse/smb3-allow-skipping-signature-verification-for-perf-sensitive-confi.patch new file mode 100644 index 0000000..ba374ac --- /dev/null +++ b/patches.suse/smb3-allow-skipping-signature-verification-for-perf-sensitive-confi.patch @@ -0,0 +1,121 @@ +From: Steve French +Date: Tue, 3 Sep 2019 21:18:49 -0500 +Subject: [PATCH] smb3: allow skipping signature verification for perf + sensitive configurations +Git-commit: 4f5c10f1ad45ae453822113dd0fe39ed757037fb +References: bsc#1144333 +Patch-mainline: v5.4-rc1 + +Add new mount option "signloosely" which enables signing but skips the +sometimes expensive signing checks in the responses (signatures are +calculated and sent correctly in the SMB2/SMB3 requests even with this +mount option but skipped in the responses). Although weaker for security +(and also data integrity in case a packet were corrupted), this can provide +enough of a performance benefit (calculating the signature to verify a +packet can be expensive especially for large packets) to be useful in +some cases. + +Signed-off-by: Steve French +Reviewed-by: Ronnie Sahlberg +Acked-by: Paulo Alcantara +--- + fs/cifs/cifsglob.h | 2 ++ + fs/cifs/connect.c | 13 ++++++++++--- + fs/cifs/smb2transport.c | 1 + + 3 files changed, 13 insertions(+), 3 deletions(-) + +diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h +index fa5abe3a8514..1f53dee211d8 100644 +--- a/fs/cifs/cifsglob.h ++++ b/fs/cifs/cifsglob.h +@@ -542,6 +542,7 @@ struct smb_vol { + umode_t dir_mode; + enum securityEnum sectype; /* sectype requested via mnt opts */ + bool sign; /* was signing requested via mnt opts? */ ++ bool ignore_signature:1; + bool retry:1; + bool intr:1; + bool setuids:1; +@@ -681,6 +682,7 @@ struct TCP_Server_Info { + char server_GUID[16]; + __u16 sec_mode; + bool sign; /* is signing enabled on this connection? */ ++ bool ignore_signature:1; /* skip validation of signatures in SMB2/3 rsp */ + bool session_estab; /* mark when very first sess is established */ + int echo_credits; /* echo reserved slots */ + int oplock_credits; /* oplock break reserved slots */ +diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c +index 85f8d943a05a..17882cede197 100644 +--- a/fs/cifs/connect.c ++++ b/fs/cifs/connect.c +@@ -91,7 +91,7 @@ enum { + Opt_serverino, Opt_noserverino, + Opt_rwpidforward, Opt_cifsacl, Opt_nocifsacl, + Opt_acl, Opt_noacl, Opt_locallease, +- Opt_sign, Opt_seal, Opt_noac, ++ Opt_sign, Opt_ignore_signature, Opt_seal, Opt_noac, + Opt_fsc, Opt_mfsymlinks, + Opt_multiuser, Opt_sloppy, Opt_nosharesock, + Opt_persistent, Opt_nopersistent, +@@ -183,6 +183,7 @@ static const match_table_t cifs_mount_option_tokens = { + { Opt_noacl, "noacl" }, + { Opt_locallease, "locallease" }, + { Opt_sign, "sign" }, ++ { Opt_ignore_signature, "signloosely" }, + { Opt_seal, "seal" }, + { Opt_noac, "noac" }, + { Opt_fsc, "fsc" }, +@@ -1877,6 +1878,10 @@ cifs_parse_mount_options(const char *mountdata, const char *devname, + case Opt_sign: + vol->sign = true; + break; ++ case Opt_ignore_signature: ++ vol->sign = true; ++ vol->ignore_signature = true; ++ break; + case Opt_seal: + /* we do not do the following in secFlags because seal + * is a per tree connection (mount) not a per socket +@@ -2608,6 +2613,9 @@ static int match_server(struct TCP_Server_Info *server, struct smb_vol *vol) + if (server->rdma != vol->rdma) + return 0; + ++ if (server->ignore_signature != vol->ignore_signature) ++ return 0; ++ + return 1; + } + +@@ -2785,7 +2793,7 @@ cifs_get_tcp_session(struct smb_vol *volume_info) + tcp_ses->tcpStatus = CifsNeedNegotiate; + + tcp_ses->nr_targets = 1; +- ++ tcp_ses->ignore_signature = volume_info->ignore_signature; + /* thread spawned, put it on the list */ + spin_lock(&cifs_tcp_ses_lock); + list_add(&tcp_ses->tcp_ses_list, &cifs_tcp_ses_list); +@@ -3235,7 +3243,6 @@ cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb_vol *volume_info) + + ses->sectype = volume_info->sectype; + ses->sign = volume_info->sign; +- + mutex_lock(&ses->session_mutex); + rc = cifs_negotiate_protocol(xid, ses); + if (!rc) +diff --git a/fs/cifs/smb2transport.c b/fs/cifs/smb2transport.c +index b02242eacb55..148d7942c796 100644 +--- a/fs/cifs/smb2transport.c ++++ b/fs/cifs/smb2transport.c +@@ -522,6 +522,7 @@ smb2_verify_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server) + if ((shdr->Command == SMB2_NEGOTIATE) || + (shdr->Command == SMB2_SESSION_SETUP) || + (shdr->Command == SMB2_OPLOCK_BREAK) || ++ server->ignore_signature || + (!server->session_estab)) + return 0; + +-- +2.25.1 + + diff --git a/patches.suse/smb3-cleanup-some-recent-endian-errors-spotted-by-updated-sparse.patch b/patches.suse/smb3-cleanup-some-recent-endian-errors-spotted-by-updated-sparse.patch new file mode 100644 index 0000000..c9214de --- /dev/null +++ b/patches.suse/smb3-cleanup-some-recent-endian-errors-spotted-by-updated-sparse.patch @@ -0,0 +1,68 @@ +From: Steve French +Date: Tue, 1 Oct 2019 21:25:46 -0500 +Subject: [PATCH] smb3: cleanup some recent endian errors spotted by updated + sparse +Git-commit: 52870d5048919004b6629d1a2f2b0a99c23b9960 +References: bsc#1144333 +Patch-mainline: v5.4-rc3 + +Now that sparse has been fixed, it spotted a couple recent minor +endian errors (and removed one additional sparse warning). + +Thanks to Luc Van Oostenryck for his help fixing sparse. + +Signed-off-by: Steve French +Reviewed-by: Ronnie Sahlberg +Acked-by: Paulo Alcantara +--- + fs/cifs/connect.c | 2 +- + fs/cifs/smb2pdu.c | 3 ++- + fs/cifs/smb2proto.h | 4 ++++ + 3 files changed, 7 insertions(+), 2 deletions(-) + +diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c +index 2850c3ce4391..b724227b853c 100644 +--- a/fs/cifs/connect.c ++++ b/fs/cifs/connect.c +@@ -4264,7 +4264,7 @@ static int mount_get_conns(struct smb_vol *vol, struct cifs_sb_info *cifs_sb, + server->ops->qfs_tcon(*xid, tcon); + if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RO_CACHE) { + if (tcon->fsDevInfo.DeviceCharacteristics & +- FILE_READ_ONLY_DEVICE) ++ cpu_to_le32(FILE_READ_ONLY_DEVICE)) + cifs_dbg(VFS, "mounted to read only share\n"); + else if ((cifs_sb->mnt_cifs_flags & + CIFS_MOUNT_RW_CACHE) == 0) +diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c +index 85f9d614d968..fd5f2b4b7582 100644 +--- a/fs/cifs/smb2pdu.c ++++ b/fs/cifs/smb2pdu.c +@@ -3217,7 +3217,8 @@ SMB2_notify_init(const unsigned int xid, struct smb_rqst *rqst, + + req->PersistentFileId = persistent_fid; + req->VolatileFileId = volatile_fid; +- req->OutputBufferLength = SMB2_MAX_BUFFER_SIZE - MAX_SMB2_HDR_SIZE; ++ req->OutputBufferLength = ++ cpu_to_le32(SMB2_MAX_BUFFER_SIZE - MAX_SMB2_HDR_SIZE); + req->CompletionFilter = cpu_to_le32(completion_filter); + if (watch_tree) + req->Flags = cpu_to_le16(SMB2_WATCH_TREE); +diff --git a/fs/cifs/smb2proto.h b/fs/cifs/smb2proto.h +index da3a6d580808..71b2930b8e0b 100644 +--- a/fs/cifs/smb2proto.h ++++ b/fs/cifs/smb2proto.h +@@ -150,6 +150,10 @@ extern int SMB2_ioctl_init(struct cifs_tcon *tcon, struct smb_rqst *rqst, + bool is_fsctl, char *in_data, u32 indatalen, + __u32 max_response_size); + extern void SMB2_ioctl_free(struct smb_rqst *rqst); ++extern int SMB2_change_notify(const unsigned int xid, struct cifs_tcon *tcon, ++ u64 persistent_fid, u64 volatile_fid, bool watch_tree, ++ u32 completion_filter); ++ + extern int SMB2_close(const unsigned int xid, struct cifs_tcon *tcon, + u64 persistent_file_id, u64 volatile_file_id); + extern int SMB2_close_flags(const unsigned int xid, struct cifs_tcon *tcon, +-- +2.25.1 + + diff --git a/patches.suse/smb3-display-max-smb3-requests-in-flight-at-any-one-time.patch b/patches.suse/smb3-display-max-smb3-requests-in-flight-at-any-one-time.patch new file mode 100644 index 0000000..4609e0e --- /dev/null +++ b/patches.suse/smb3-display-max-smb3-requests-in-flight-at-any-one-time.patch @@ -0,0 +1,127 @@ +From: Steve French +Date: Mon, 9 Sep 2019 22:57:11 -0500 +Subject: [PATCH] smb3: display max smb3 requests in flight at any one time +Git-commit: 1b63f1840e787516bf2d3e5c27c2d22fe23cfb37 +References: bsc#1144333 +Patch-mainline: v5.4-rc1 + +Displayed in /proc/fs/cifs/Stats once for each +socket we are connected to. + +This allows us to find out what the maximum number of +requests that had been in flight (at any one time). Note that +/proc/fs/cifs/Stats can be reset if you want to look for +maximum over a small period of time. + +Sample output (immediately after mount): + +Resources in use +CIFS Session: 1 +Share (unique mount targets): 2 +SMB Request/Response Buffer: 1 Pool size: 5 +SMB Small Req/Resp Buffer: 1 Pool size: 30 +Operations (MIDs): 0 + +0 session 0 share reconnects +Total vfs operations: 5 maximum at one time: 2 + +Max requests in flight: 2 +1) \\localhost\scratch +SMBs: 18 +Bytes read: 0 Bytes written: 0 +... + +Signed-off-by: Steve French +Reviewed-by: Pavel Shilovsky +Acked-by: Paulo Alcantara +--- + fs/cifs/cifs_debug.c | 2 ++ + fs/cifs/cifsglob.h | 1 + + fs/cifs/connect.c | 1 + + fs/cifs/smb2ops.c | 2 ++ + fs/cifs/transport.c | 4 ++++ + 5 files changed, 10 insertions(+) + +diff --git a/fs/cifs/cifs_debug.c b/fs/cifs/cifs_debug.c +index a38d796f5ffe..0b4eee3bed66 100644 +--- a/fs/cifs/cifs_debug.c ++++ b/fs/cifs/cifs_debug.c +@@ -452,6 +452,7 @@ static ssize_t cifs_stats_proc_write(struct file *file, + list_for_each(tmp1, &cifs_tcp_ses_list) { + server = list_entry(tmp1, struct TCP_Server_Info, + tcp_ses_list); ++ server->max_in_flight = 0; + #ifdef CONFIG_CIFS_STATS2 + for (i = 0; i < NUMBER_OF_SMB2_COMMANDS; i++) { + atomic_set(&server->num_cmds[i], 0); +@@ -526,6 +527,7 @@ static int cifs_stats_proc_show(struct seq_file *m, void *v) + list_for_each(tmp1, &cifs_tcp_ses_list) { + server = list_entry(tmp1, struct TCP_Server_Info, + tcp_ses_list); ++ seq_printf(m, "\nMax requests in flight: %d", server->max_in_flight); + #ifdef CONFIG_CIFS_STATS2 + seq_puts(m, "\nTotal time spent processing by command. Time "); + seq_printf(m, "units are jiffies (%d per second)\n", HZ); +diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h +index 6987fbc5a24a..ef2199913217 100644 +--- a/fs/cifs/cifsglob.h ++++ b/fs/cifs/cifsglob.h +@@ -677,6 +677,7 @@ struct TCP_Server_Info { + unsigned int credits; /* send no more requests at once */ + unsigned int max_credits; /* can override large 32000 default at mnt */ + unsigned int in_flight; /* number of requests on the wire to server */ ++ unsigned int max_in_flight; /* max number of requests that were on wire */ + spinlock_t req_lock; /* protect the two values above */ + struct mutex srv_mutex; + struct task_struct *tsk; +diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c +index e70112d67b0e..df1ccb581828 100644 +--- a/fs/cifs/connect.c ++++ b/fs/cifs/connect.c +@@ -2728,6 +2728,7 @@ cifs_get_tcp_session(struct smb_vol *volume_info) + tcp_ses->tcp_nodelay = volume_info->sockopt_tcp_nodelay; + tcp_ses->rdma = volume_info->rdma; + tcp_ses->in_flight = 0; ++ tcp_ses->max_in_flight = 0; + tcp_ses->credits = 1; + init_waitqueue_head(&tcp_ses->response_q); + init_waitqueue_head(&tcp_ses->request_q); +diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c +index 72b3e39d7f4f..9b74149b471f 100644 +--- a/fs/cifs/smb2ops.c ++++ b/fs/cifs/smb2ops.c +@@ -203,6 +203,8 @@ smb2_wait_mtu_credits(struct TCP_Server_Info *server, unsigned int size, + credits->instance = server->reconnect_instance; + server->credits -= credits->value; + server->in_flight++; ++ if (server->in_flight > server->max_in_flight) ++ server->max_in_flight = server->in_flight; + break; + } + } +diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c +index 4fccb90492e9..308ad0f495e1 100644 +--- a/fs/cifs/transport.c ++++ b/fs/cifs/transport.c +@@ -532,6 +532,8 @@ wait_for_free_credits(struct TCP_Server_Info *server, const int num_credits, + if ((flags & CIFS_TIMEOUT_MASK) == CIFS_NON_BLOCKING) { + /* oplock breaks must not be held up */ + server->in_flight++; ++ if (server->in_flight > server->max_in_flight) ++ server->max_in_flight = server->in_flight; + *credits -= 1; + *instance = server->reconnect_instance; + spin_unlock(&server->req_lock); +@@ -608,6 +610,8 @@ wait_for_free_credits(struct TCP_Server_Info *server, const int num_credits, + if ((flags & CIFS_TIMEOUT_MASK) != CIFS_BLOCKING_OP) { + *credits -= num_credits; + server->in_flight += num_credits; ++ if (server->in_flight > server->max_in_flight) ++ server->max_in_flight = server->in_flight; + *instance = server->reconnect_instance; + } + spin_unlock(&server->req_lock); +-- +2.25.1 + + diff --git a/patches.suse/smb3-dump-in_send-and-num_waiters-stats-counters-by-default.patch b/patches.suse/smb3-dump-in_send-and-num_waiters-stats-counters-by-default.patch new file mode 100644 index 0000000..5cec8ae --- /dev/null +++ b/patches.suse/smb3-dump-in_send-and-num_waiters-stats-counters-by-default.patch @@ -0,0 +1,98 @@ +From: Steve French +Date: Thu, 21 Nov 2019 17:26:35 -0600 +Subject: [PATCH] smb3: dump in_send and num_waiters stats counters by default +Git-commit: 1ae9a5a5515729f43b2513bba68a462f240b3e04 +References: bsc#1144333 +Patch-mainline: v5.5-rc1 + +Number of requests in_send and the number of waiters on sendRecv +are useful counters in various cases, move them from +CONFIG_CIFS_STATS2 to be on by default especially with multichannel + +Signed-off-by: Steve French +Acked-by: Ronnie Sahlberg +Acked-by: Paulo Alcantara +--- + fs/cifs/cifs_debug.c | 3 +-- + fs/cifs/cifsglob.h | 26 +++++--------------------- + 2 files changed, 6 insertions(+), 23 deletions(-) + +diff --git a/fs/cifs/cifs_debug.c b/fs/cifs/cifs_debug.c +index efb2928ff6c8..393c42cab7d3 100644 +--- a/fs/cifs/cifs_debug.c ++++ b/fs/cifs/cifs_debug.c +@@ -365,11 +365,10 @@ static int cifs_debug_data_proc_show(struct seq_file *m, void *v) + server->srv_count, + server->sec_mode, in_flight(server)); + +-#ifdef CONFIG_CIFS_STATS2 + seq_printf(m, " In Send: %d In MaxReq Wait: %d", + atomic_read(&server->in_send), + atomic_read(&server->num_waiters)); +-#endif ++ + /* dump session id helpful for use with network trace */ + seq_printf(m, " SessionId: 0x%llx", ses->Suid); + if (ses->session_flags & SMB2_SESSION_FLAG_ENCRYPT_DATA) +diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h +index 2fc3d77463d3..d34a4ed8c57d 100644 +--- a/fs/cifs/cifsglob.h ++++ b/fs/cifs/cifsglob.h +@@ -743,12 +743,12 @@ struct TCP_Server_Info { + /* Total size of this PDU. Only valid from cifs_demultiplex_thread */ + unsigned int pdu_size; + unsigned int total_read; /* total amount of data read in this pass */ +-#ifdef CONFIG_CIFS_FSCACHE +- struct fscache_cookie *fscache; /* client index cache cookie */ +-#endif +-#ifdef CONFIG_CIFS_STATS2 + atomic_t in_send; /* requests trying to send */ + atomic_t num_waiters; /* blocked waiting to get in sendrecv */ ++#ifdef CONFIG_CIFS_FSCACHE ++ struct fscache_cookie *fscache; /* client index cache cookie */ ++#endif ++#ifdef CONFIG_CIFS_STATS2 + atomic_t num_cmds[NUMBER_OF_SMB2_COMMANDS]; /* total requests by cmd */ + atomic_t smb2slowcmd[NUMBER_OF_SMB2_COMMANDS]; /* count resps > 1 sec */ + __u64 time_per_cmd[NUMBER_OF_SMB2_COMMANDS]; /* total time per cmd */ +@@ -1606,8 +1606,6 @@ struct close_cancelled_open { + + /* Make code in transport.c a little cleaner by moving + update of optional stats into function below */ +-#ifdef CONFIG_CIFS_STATS2 +- + static inline void cifs_in_send_inc(struct TCP_Server_Info *server) + { + atomic_inc(&server->in_send); +@@ -1628,26 +1626,12 @@ static inline void cifs_num_waiters_dec(struct TCP_Server_Info *server) + atomic_dec(&server->num_waiters); + } + ++#ifdef CONFIG_CIFS_STATS2 + static inline void cifs_save_when_sent(struct mid_q_entry *mid) + { + mid->when_sent = jiffies; + } + #else +-static inline void cifs_in_send_inc(struct TCP_Server_Info *server) +-{ +-} +-static inline void cifs_in_send_dec(struct TCP_Server_Info *server) +-{ +-} +- +-static inline void cifs_num_waiters_inc(struct TCP_Server_Info *server) +-{ +-} +- +-static inline void cifs_num_waiters_dec(struct TCP_Server_Info *server) +-{ +-} +- + static inline void cifs_save_when_sent(struct mid_q_entry *mid) + { + } +-- +2.25.1 + + diff --git a/patches.suse/smb3-enable-offload-of-decryption-of-large-reads-via-mount-option.patch b/patches.suse/smb3-enable-offload-of-decryption-of-large-reads-via-mount-option.patch new file mode 100644 index 0000000..c1ba8b8 --- /dev/null +++ b/patches.suse/smb3-enable-offload-of-decryption-of-large-reads-via-mount-option.patch @@ -0,0 +1,135 @@ +From: Steve French +Date: Sun, 8 Sep 2019 23:22:02 -0500 +Subject: [PATCH] smb3: enable offload of decryption of large reads via mount + option +Git-commit: 563317ec3083f7e126d7e30821ff8505ac338ee5 +References: bsc#1144333 +Patch-mainline: v5.4-rc1 + +Disable offload of the decryption of encrypted read responses +by default (equivalent to setting this new mount option "esize=0"). + +Allow setting the minimum encrypted read response size that we +will choose to offload to a worker thread - it is now configurable +via on a new mount option "esize=" + +Depending on which encryption mechanism (GCM vs. CCM) and +the number of reads that will be issued in parallel and the +performance of the network and CPU on the client, it may make +sense to enable this since it can provide substantial benefit when +multiple large reads are in flight at the same time. + +Signed-off-by: Steve French +Signed-off-by: Ronnie Sahlberg +Acked-by: Paulo Alcantara +--- + fs/cifs/cifsfs.c | 2 ++ + fs/cifs/cifsglob.h | 2 ++ + fs/cifs/connect.c | 13 +++++++++++++ + fs/cifs/smb2ops.c | 4 ++-- + 4 files changed, 19 insertions(+), 2 deletions(-) + +diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c +index b0ea332af35c..ebf85a5d95e4 100644 +--- a/fs/cifs/cifsfs.c ++++ b/fs/cifs/cifsfs.c +@@ -559,6 +559,8 @@ cifs_show_options(struct seq_file *s, struct dentry *root) + seq_printf(s, ",rsize=%u", cifs_sb->rsize); + seq_printf(s, ",wsize=%u", cifs_sb->wsize); + seq_printf(s, ",bsize=%u", cifs_sb->bsize); ++ if (tcon->ses->server->min_offload) ++ seq_printf(s, ",esize=%u", tcon->ses->server->min_offload); + seq_printf(s, ",echo_interval=%lu", + tcon->ses->server->echo_interval / HZ); + +diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h +index d66106ac031a..6987fbc5a24a 100644 +--- a/fs/cifs/cifsglob.h ++++ b/fs/cifs/cifsglob.h +@@ -592,6 +592,7 @@ struct smb_vol { + unsigned int bsize; + unsigned int rsize; + unsigned int wsize; ++ unsigned int min_offload; + bool sockopt_tcp_nodelay:1; + unsigned long actimeo; /* attribute cache timeout (jiffies) */ + struct smb_version_operations *ops; +@@ -745,6 +746,7 @@ struct TCP_Server_Info { + #endif /* STATS2 */ + unsigned int max_read; + unsigned int max_write; ++ unsigned int min_offload; + __le16 compress_algorithm; + __le16 cipher_type; + /* save initital negprot hash */ +diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c +index 17882cede197..e70112d67b0e 100644 +--- a/fs/cifs/connect.c ++++ b/fs/cifs/connect.c +@@ -103,6 +103,7 @@ enum { + Opt_backupuid, Opt_backupgid, Opt_uid, + Opt_cruid, Opt_gid, Opt_file_mode, + Opt_dirmode, Opt_port, ++ Opt_min_enc_offload, + Opt_blocksize, Opt_rsize, Opt_wsize, Opt_actimeo, + Opt_echo_interval, Opt_max_credits, Opt_handletimeout, + Opt_snapshot, +@@ -207,6 +208,7 @@ static const match_table_t cifs_mount_option_tokens = { + { Opt_dirmode, "dirmode=%s" }, + { Opt_dirmode, "dir_mode=%s" }, + { Opt_port, "port=%s" }, ++ { Opt_min_enc_offload, "esize=%s" }, + { Opt_blocksize, "bsize=%s" }, + { Opt_rsize, "rsize=%s" }, + { Opt_wsize, "wsize=%s" }, +@@ -2016,6 +2018,13 @@ cifs_parse_mount_options(const char *mountdata, const char *devname, + } + port = (unsigned short)option; + break; ++ case Opt_min_enc_offload: ++ if (get_option_ul(args, &option)) { ++ cifs_dbg(VFS, "Invalid minimum encrypted read offload size (esize)\n"); ++ goto cifs_parse_mount_err; ++ } ++ vol->min_offload = option; ++ break; + case Opt_blocksize: + if (get_option_ul(args, &option)) { + cifs_dbg(VFS, "%s: Invalid blocksize value\n", +@@ -2616,6 +2625,9 @@ static int match_server(struct TCP_Server_Info *server, struct smb_vol *vol) + if (server->ignore_signature != vol->ignore_signature) + return 0; + ++ if (server->min_offload != vol->min_offload) ++ return 0; ++ + return 1; + } + +@@ -2790,6 +2802,7 @@ cifs_get_tcp_session(struct smb_vol *volume_info) + module_put(THIS_MODULE); + goto out_err_crypto_release; + } ++ tcp_ses->min_offload = volume_info->min_offload; + tcp_ses->tcpStatus = CifsNeedNegotiate; + + tcp_ses->nr_targets = 1; +diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c +index c74284484947..1cfb8d518132 100644 +--- a/fs/cifs/smb2ops.c ++++ b/fs/cifs/smb2ops.c +@@ -4121,8 +4121,8 @@ receive_encrypted_read(struct TCP_Server_Info *server, struct mid_q_entry **mid, + * use more cores decrypting which can be expensive + */ + +- /* TODO: make the size limit to enable decrypt offload configurable */ +- if (server->pdu_size > (512 * 1024)) { ++ if ((server->min_offload) && ++ (server->pdu_size >= server->min_offload)) { + dw = kmalloc(sizeof(struct smb2_decrypt_work), GFP_KERNEL); + if (dw == NULL) + goto non_offloaded_decrypt; +-- +2.25.1 + + diff --git a/patches.suse/smb3-fix-default-permissions-on-new-files-when-mounting-with-modefr.patch b/patches.suse/smb3-fix-default-permissions-on-new-files-when-mounting-with-modefr.patch new file mode 100644 index 0000000..10cf74f --- /dev/null +++ b/patches.suse/smb3-fix-default-permissions-on-new-files-when-mounting-with-modefr.patch @@ -0,0 +1,111 @@ +From: Steve French +Date: Thu, 16 Jan 2020 19:55:33 -0600 +Subject: [PATCH] smb3: fix default permissions on new files when mounting with + modefromsid +Git-commit: 643fbceef48e5b22bf8e0905f903e908b5d2ba69 +References: bsc#1144333 +Patch-mainline: v5.6-rc1 + +When mounting with "modefromsid" mount parm most servers will require +that some default permissions are given to users in the ACL on newly +created files, files created with the new 'sd context' - when passing in +an sd context on create, permissions are not inherited from the parent +directory, so in addition to the ACE with the special SID which contains +the mode, we also must pass in an ACE allowing users to access the file +(GENERIC_ALL for authenticated users seemed like a reasonable default, +although later we could allow a mount option or config switch to make +it GENERIC_ALL for EVERYONE special sid). + +CC: Stable +Signed-off-by: Steve French +Reviewed-By: Ronnie Sahlberg +Reviewed-by: Pavel Shilovsky +Acked-by: Paulo Alcantara +--- + fs/cifs/cifsacl.c | 20 ++++++++++++++++++++ + fs/cifs/cifsproto.h | 1 + + fs/cifs/smb2pdu.c | 11 ++++++++--- + 3 files changed, 29 insertions(+), 3 deletions(-) + +diff --git a/fs/cifs/cifsacl.c b/fs/cifs/cifsacl.c +index 96ae72b556ac..fb41e51dd574 100644 +--- a/fs/cifs/cifsacl.c ++++ b/fs/cifs/cifsacl.c +@@ -802,6 +802,26 @@ static void parse_dacl(struct cifs_acl *pdacl, char *end_of_acl, + return; + } + ++unsigned int setup_authusers_ACE(struct cifs_ace *pntace) ++{ ++ int i; ++ unsigned int ace_size = 20; ++ ++ pntace->type = ACCESS_ALLOWED_ACE_TYPE; ++ pntace->flags = 0x0; ++ pntace->access_req = cpu_to_le32(GENERIC_ALL); ++ pntace->sid.num_subauth = 1; ++ pntace->sid.revision = 1; ++ for (i = 0; i < NUM_AUTHS; i++) ++ pntace->sid.authority[i] = sid_authusers.authority[i]; ++ ++ pntace->sid.sub_auth[0] = sid_authusers.sub_auth[0]; ++ ++ /* size = 1 + 1 + 2 + 4 + 1 + 1 + 6 + (psid->num_subauth*4) */ ++ pntace->size = cpu_to_le16(ace_size); ++ return ace_size; ++} ++ + /* + * Fill in the special SID based on the mode. See + * http://technet.microsoft.com/en-us/library/hh509017(v=ws.10).aspx +diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h +index f6f3cc90cd18..948bf3474db1 100644 +--- a/fs/cifs/cifsproto.h ++++ b/fs/cifs/cifsproto.h +@@ -213,6 +213,7 @@ extern struct cifs_ntsd *get_cifs_acl_by_fid(struct cifs_sb_info *, + const struct cifs_fid *, u32 *); + extern int set_cifs_acl(struct cifs_ntsd *, __u32, struct inode *, + const char *, int); ++extern unsigned int setup_authusers_ACE(struct cifs_ace *pace); + extern unsigned int setup_special_mode_ACE(struct cifs_ace *pace, __u64 nmode); + + extern void dequeue_mid(struct mid_q_entry *mid, bool malformed); +diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c +index 64d5a36a1901..7edba3e6d5e6 100644 +--- a/fs/cifs/smb2pdu.c ++++ b/fs/cifs/smb2pdu.c +@@ -2199,13 +2199,14 @@ create_sd_buf(umode_t mode, unsigned int *len) + struct cifs_ace *pace; + unsigned int sdlen, acelen; + +- *len = roundup(sizeof(struct crt_sd_ctxt) + sizeof(struct cifs_ace), 8); ++ *len = roundup(sizeof(struct crt_sd_ctxt) + sizeof(struct cifs_ace) * 2, ++ 8); + buf = kzalloc(*len, GFP_KERNEL); + if (buf == NULL) + return buf; + + sdlen = sizeof(struct smb3_sd) + sizeof(struct smb3_acl) + +- sizeof(struct cifs_ace); ++ 2 * sizeof(struct cifs_ace); + + buf->ccontext.DataOffset = cpu_to_le16(offsetof + (struct crt_sd_ctxt, sd)); +@@ -2232,8 +2233,12 @@ create_sd_buf(umode_t mode, unsigned int *len) + /* create one ACE to hold the mode embedded in reserved special SID */ + pace = (struct cifs_ace *)(sizeof(struct crt_sd_ctxt) + (char *)buf); + acelen = setup_special_mode_ACE(pace, (__u64)mode); ++ /* and one more ACE to allow access for authenticated users */ ++ pace = (struct cifs_ace *)(acelen + (sizeof(struct crt_sd_ctxt) + ++ (char *)buf)); ++ acelen += setup_authusers_ACE(pace); + buf->acl.AclSize = cpu_to_le16(sizeof(struct cifs_acl) + acelen); +- buf->acl.AceCount = cpu_to_le16(1); ++ buf->acl.AceCount = cpu_to_le16(2); + return buf; + } + +-- +2.25.1 + + diff --git a/patches.suse/smb3-fix-mode-passed-in-on-create-for-modetosid-mount-option.patch b/patches.suse/smb3-fix-mode-passed-in-on-create-for-modetosid-mount-option.patch new file mode 100644 index 0000000..e360159 --- /dev/null +++ b/patches.suse/smb3-fix-mode-passed-in-on-create-for-modetosid-mount-option.patch @@ -0,0 +1,278 @@ +From: Steve French +Date: Fri, 6 Dec 2019 02:02:38 -0600 +Subject: [PATCH] smb3: fix mode passed in on create for modetosid mount option +Git-commit: fdef665ba44ad5ed154af2acfb19ae2ee3bf5dcc +References: bsc#1144333 +Patch-mainline: v5.5-rc1 + +When using the special SID to store the mode bits in an ACE (See +http://technet.microsoft.com/en-us/library/hh509017(v=ws.10).aspx) +which is enabled with mount parm "modefromsid" we were not +passing in the mode via SMB3 create (although chmod was enabled). +SMB3 create allows a security descriptor context to be passed +in (which is more atomic and thus preferable to setting the mode +bits after create via a setinfo). + +This patch enables setting the mode bits on create when using +modefromsid mount option. In addition it fixes an endian +error in the definition of the Control field flags in the SMB3 +security descriptor. It also makes the ACE type of the special +SID better match the documentation (and behavior of servers +which use this to store mode bits in SMB3 ACLs). + +Signed-off-by: Steve French +Acked-by: Ronnie Sahlberg +Reviewed-by: Pavel Shilovsky +Acked-by: Paulo Alcantara +--- + fs/cifs/cifsacl.c | 42 +++++++++++++++++---------- + fs/cifs/cifsacl.h | 32 ++++++++++---------- + fs/cifs/cifsproto.h | 1 + + fs/cifs/smb2pdu.c | 71 +++++++++++++++++++++++++++++++++++++++++++-- + fs/cifs/smb2pdu.h | 10 +++++++ + 5 files changed, 122 insertions(+), 34 deletions(-) + +diff --git a/fs/cifs/cifsacl.c b/fs/cifs/cifsacl.c +index 06ffe52bdcfa..96ae72b556ac 100644 +--- a/fs/cifs/cifsacl.c ++++ b/fs/cifs/cifsacl.c +@@ -802,6 +802,31 @@ static void parse_dacl(struct cifs_acl *pdacl, char *end_of_acl, + return; + } + ++/* ++ * Fill in the special SID based on the mode. See ++ * http://technet.microsoft.com/en-us/library/hh509017(v=ws.10).aspx ++ */ ++unsigned int setup_special_mode_ACE(struct cifs_ace *pntace, __u64 nmode) ++{ ++ int i; ++ unsigned int ace_size = 28; ++ ++ pntace->type = ACCESS_DENIED_ACE_TYPE; ++ pntace->flags = 0x0; ++ pntace->access_req = 0; ++ pntace->sid.num_subauth = 3; ++ pntace->sid.revision = 1; ++ for (i = 0; i < NUM_AUTHS; i++) ++ pntace->sid.authority[i] = sid_unix_NFS_mode.authority[i]; ++ ++ pntace->sid.sub_auth[0] = sid_unix_NFS_mode.sub_auth[0]; ++ pntace->sid.sub_auth[1] = sid_unix_NFS_mode.sub_auth[1]; ++ pntace->sid.sub_auth[2] = cpu_to_le32(nmode & 07777); ++ ++ /* size = 1 + 1 + 2 + 4 + 1 + 1 + 6 + (psid->num_subauth*4) */ ++ pntace->size = cpu_to_le16(ace_size); ++ return ace_size; ++} + + static int set_chmod_dacl(struct cifs_acl *pndacl, struct cifs_sid *pownersid, + struct cifs_sid *pgrpsid, __u64 nmode, bool modefromsid) +@@ -815,23 +840,8 @@ static int set_chmod_dacl(struct cifs_acl *pndacl, struct cifs_sid *pownersid, + if (modefromsid) { + struct cifs_ace *pntace = + (struct cifs_ace *)((char *)pnndacl + size); +- int i; + +- pntace->type = ACCESS_ALLOWED; +- pntace->flags = 0x0; +- pntace->access_req = 0; +- pntace->sid.num_subauth = 3; +- pntace->sid.revision = 1; +- for (i = 0; i < NUM_AUTHS; i++) +- pntace->sid.authority[i] = +- sid_unix_NFS_mode.authority[i]; +- pntace->sid.sub_auth[0] = sid_unix_NFS_mode.sub_auth[0]; +- pntace->sid.sub_auth[1] = sid_unix_NFS_mode.sub_auth[1]; +- pntace->sid.sub_auth[2] = cpu_to_le32(nmode & 07777); +- +- /* size = 1 + 1 + 2 + 4 + 1 + 1 + 6 + (psid->num_subauth*4) */ +- pntace->size = cpu_to_le16(28); +- size += 28; ++ size += setup_special_mode_ACE(pntace, nmode); + num_aces++; + } + +diff --git a/fs/cifs/cifsacl.h b/fs/cifs/cifsacl.h +index 439b99cefeb0..21d7dee98d01 100644 +--- a/fs/cifs/cifsacl.h ++++ b/fs/cifs/cifsacl.h +@@ -147,22 +147,22 @@ struct smb3_sd { + } __packed; + + /* Meaning of 'Control' field flags */ +-#define ACL_CONTROL_SR 0x0001 /* Self relative */ +-#define ACL_CONTROL_RM 0x0002 /* Resource manager control bits */ +-#define ACL_CONTROL_PS 0x0004 /* SACL protected from inherits */ +-#define ACL_CONTROL_PD 0x0008 /* DACL protected from inherits */ +-#define ACL_CONTROL_SI 0x0010 /* SACL Auto-Inherited */ +-#define ACL_CONTROL_DI 0x0020 /* DACL Auto-Inherited */ +-#define ACL_CONTROL_SC 0x0040 /* SACL computed through inheritance */ +-#define ACL_CONTROL_DC 0x0080 /* DACL computed through inheritence */ +-#define ACL_CONTROL_SS 0x0100 /* Create server ACL */ +-#define ACL_CONTROL_DT 0x0200 /* DACL provided by trusteed source */ +-#define ACL_CONTROL_SD 0x0400 /* SACL defaulted */ +-#define ACL_CONTROL_SP 0x0800 /* SACL is present on object */ +-#define ACL_CONTROL_DD 0x1000 /* DACL defaulted */ +-#define ACL_CONTROL_DP 0x2000 /* DACL is present on object */ +-#define ACL_CONTROL_GD 0x4000 /* Group was defaulted */ +-#define ACL_CONTROL_OD 0x8000 /* User was defaulted */ ++#define ACL_CONTROL_SR 0x8000 /* Self relative */ ++#define ACL_CONTROL_RM 0x4000 /* Resource manager control bits */ ++#define ACL_CONTROL_PS 0x2000 /* SACL protected from inherits */ ++#define ACL_CONTROL_PD 0x1000 /* DACL protected from inherits */ ++#define ACL_CONTROL_SI 0x0800 /* SACL Auto-Inherited */ ++#define ACL_CONTROL_DI 0x0400 /* DACL Auto-Inherited */ ++#define ACL_CONTROL_SC 0x0200 /* SACL computed through inheritance */ ++#define ACL_CONTROL_DC 0x0100 /* DACL computed through inheritence */ ++#define ACL_CONTROL_SS 0x0080 /* Create server ACL */ ++#define ACL_CONTROL_DT 0x0040 /* DACL provided by trusted source */ ++#define ACL_CONTROL_SD 0x0020 /* SACL defaulted */ ++#define ACL_CONTROL_SP 0x0010 /* SACL is present on object */ ++#define ACL_CONTROL_DD 0x0008 /* DACL defaulted */ ++#define ACL_CONTROL_DP 0x0004 /* DACL is present on object */ ++#define ACL_CONTROL_GD 0x0002 /* Group was defaulted */ ++#define ACL_CONTROL_OD 0x0001 /* User was defaulted */ + + /* Meaning of AclRevision flags */ + #define ACL_REVISION 0x02 /* See section 2.4.4.1 of MS-DTYP */ +diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h +index 1ed695336f62..9c229408a251 100644 +--- a/fs/cifs/cifsproto.h ++++ b/fs/cifs/cifsproto.h +@@ -213,6 +213,7 @@ extern struct cifs_ntsd *get_cifs_acl_by_fid(struct cifs_sb_info *, + const struct cifs_fid *, u32 *); + extern int set_cifs_acl(struct cifs_ntsd *, __u32, struct inode *, + const char *, int); ++extern unsigned int setup_special_mode_ACE(struct cifs_ace *pace, __u64 nmode); + + extern void dequeue_mid(struct mid_q_entry *mid, bool malformed); + extern int cifs_read_from_socket(struct TCP_Server_Info *server, char *buf, +diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c +index 187a5ce68806..b77643e02157 100644 +--- a/fs/cifs/smb2pdu.c ++++ b/fs/cifs/smb2pdu.c +@@ -2191,6 +2191,72 @@ add_twarp_context(struct kvec *iov, unsigned int *num_iovec, __u64 timewarp) + return 0; + } + ++/* See MS-SMB2 2.2.13.2.2 and MS-DTYP 2.4.6 */ ++static struct crt_sd_ctxt * ++create_sd_buf(umode_t mode, unsigned int *len) ++{ ++ struct crt_sd_ctxt *buf; ++ struct cifs_ace *pace; ++ unsigned int sdlen, acelen; ++ ++ *len = roundup(sizeof(struct crt_sd_ctxt) + sizeof(struct cifs_ace), 8); ++ buf = kzalloc(*len, GFP_KERNEL); ++ if (buf == NULL) ++ return buf; ++ ++ sdlen = sizeof(struct smb3_sd) + sizeof(struct smb3_acl) + ++ sizeof(struct cifs_ace); ++ ++ buf->ccontext.DataOffset = cpu_to_le16(offsetof ++ (struct crt_sd_ctxt, sd)); ++ buf->ccontext.DataLength = cpu_to_le32(sdlen); ++ buf->ccontext.NameOffset = cpu_to_le16(offsetof ++ (struct crt_sd_ctxt, Name)); ++ buf->ccontext.NameLength = cpu_to_le16(4); ++ /* SMB2_CREATE_SD_BUFFER_TOKEN is "SecD" */ ++ buf->Name[0] = 'S'; ++ buf->Name[1] = 'e'; ++ buf->Name[2] = 'c'; ++ buf->Name[3] = 'D'; ++ buf->sd.Revision = 1; /* Must be one see MS-DTYP 2.4.6 */ ++ /* ++ * ACL is "self relative" ie ACL is stored in contiguous block of memory ++ * and "DP" ie the DACL is present ++ */ ++ buf->sd.Control = cpu_to_le16(ACL_CONTROL_SR | ACL_CONTROL_DP); ++ ++ /* offset owner, group and Sbz1 and SACL are all zero */ ++ buf->sd.OffsetDacl = cpu_to_le32(sizeof(struct smb3_sd)); ++ buf->acl.AclRevision = ACL_REVISION; /* See 2.4.4.1 of MS-DTYP */ ++ ++ /* create one ACE to hold the mode embedded in reserved special SID */ ++ pace = (struct cifs_ace *)(sizeof(struct crt_sd_ctxt) + (char *)buf); ++ acelen = setup_special_mode_ACE(pace, (__u64)mode); ++ buf->acl.AclSize = cpu_to_le16(sizeof(struct cifs_acl) + acelen); ++ buf->acl.AceCount = cpu_to_le16(1); ++ return buf; ++} ++ ++static int ++add_sd_context(struct kvec *iov, unsigned int *num_iovec, umode_t mode) ++{ ++ struct smb2_create_req *req = iov[0].iov_base; ++ unsigned int num = *num_iovec; ++ unsigned int len = 0; ++ ++ iov[num].iov_base = create_sd_buf(mode, &len); ++ if (iov[num].iov_base == NULL) ++ return -ENOMEM; ++ iov[num].iov_len = len; ++ if (!req->CreateContextsOffset) ++ req->CreateContextsOffset = cpu_to_le32( ++ sizeof(struct smb2_create_req) + ++ iov[num - 1].iov_len); ++ le32_add_cpu(&req->CreateContextsLength, len); ++ *num_iovec = num + 1; ++ return 0; ++} ++ + static struct crt_query_id_ctxt * + create_query_id_buf(void) + { +@@ -2563,7 +2629,7 @@ SMB2_open_init(struct cifs_tcon *tcon, struct smb_rqst *rqst, __u8 *oplock, + return rc; + } + +- if ((oparms->disposition == FILE_CREATE) && ++ if ((oparms->disposition != FILE_OPEN) && + (oparms->mode != ACL_NO_MODE)) { + if (n_iov > 2) { + struct create_context *ccontext = +@@ -2572,7 +2638,8 @@ SMB2_open_init(struct cifs_tcon *tcon, struct smb_rqst *rqst, __u8 *oplock, + cpu_to_le32(iov[n_iov-1].iov_len); + } + +- /* rc = add_sd_context(iov, &n_iov, oparms->mode); */ ++ cifs_dbg(FYI, "add sd with mode 0x%x\n", oparms->mode); ++ rc = add_sd_context(iov, &n_iov, oparms->mode); + if (rc) + return rc; + } +diff --git a/fs/cifs/smb2pdu.h b/fs/cifs/smb2pdu.h +index fa2533da316d..7b1c379fdf7a 100644 +--- a/fs/cifs/smb2pdu.h ++++ b/fs/cifs/smb2pdu.h +@@ -25,6 +25,7 @@ + #define _SMB2PDU_H + + #include ++#include + + /* + * Note that, due to trying to use names similar to the protocol specifications, +@@ -855,6 +856,15 @@ struct crt_query_id_ctxt { + __u8 Name[8]; + } __packed; + ++struct crt_sd_ctxt { ++ struct create_context ccontext; ++ __u8 Name[8]; ++ struct smb3_sd sd; ++ struct smb3_acl acl; ++ /* Followed by at least 4 ACEs */ ++} __packed; ++ ++ + #define COPY_CHUNK_RES_KEY_SIZE 24 + struct resume_key_req { + char ResumeKey[COPY_CHUNK_RES_KEY_SIZE]; +-- +2.25.1 + + diff --git a/patches.suse/smb3-fix-performance-regression-with-setting-mtime.patch b/patches.suse/smb3-fix-performance-regression-with-setting-mtime.patch new file mode 100644 index 0000000..2b07d48 --- /dev/null +++ b/patches.suse/smb3-fix-performance-regression-with-setting-mtime.patch @@ -0,0 +1,67 @@ +From 9b7af89ee823b2a95c2d1dd7ca70b02d8ce792d7 Mon Sep 17 00:00:00 2001 +From: Steve French +Date: Mon, 24 Feb 2020 17:37:39 -0600 +Subject: [PATCH] smb3: fix performance regression with setting mtime +Patch-mainline: Not yet, in for-next branch +References: bsc#1144333 + +There are cases when we don't want to send the SMB2 flush operation +(e.g. when user specifies mount parm "nostrictsync") and it can be +a very expensive operation on the server. In most cases in order +to set mtime, we simply need to flush (write) the dirtry pages from +the client and send the writes to the server not also send a flush +protocol operation to the server. + +Fixes: aa081859b10c ("cifs: flush before set-info if we have writeable handles") +CC: Stable +Signed-off-by: Steve French +Acked-by: Paulo Alcantara +--- + fs/cifs/inode.c | 23 ++++++++++++----------- + 1 file changed, 12 insertions(+), 11 deletions(-) + +diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c +index aad7d2cad9a0..e6d66977a81d 100644 +--- a/fs/cifs/inode.c ++++ b/fs/cifs/inode.c +@@ -2528,25 +2528,26 @@ cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs) + + /* + * Attempt to flush data before changing attributes. We need to do +- * this for ATTR_SIZE and ATTR_MTIME for sure, and if we change the +- * ownership or mode then we may also need to do this. Here, we take +- * the safe way out and just do the flush on all setattr requests. If +- * the flush returns error, store it to report later and continue. ++ * this for ATTR_SIZE and ATTR_MTIME. If the flush of the data ++ * returns error, store it to report later and continue. + * + * BB: This should be smarter. Why bother flushing pages that + * will be truncated anyway? Also, should we error out here if +- * the flush returns error? ++ * the flush returns error? Do we need to check for ATTR_MTIME_SET flag? + */ +- rc = filemap_write_and_wait(inode->i_mapping); +- if (is_interrupt_error(rc)) { +- rc = -ERESTARTSYS; +- goto cifs_setattr_exit; ++ if (attrs->ia_valid & (ATTR_MTIME | ATTR_SIZE | ATTR_CTIME)) { ++ rc = filemap_write_and_wait(inode->i_mapping); ++ if (is_interrupt_error(rc)) { ++ rc = -ERESTARTSYS; ++ goto cifs_setattr_exit; ++ } ++ mapping_set_error(inode->i_mapping, rc); + } + +- mapping_set_error(inode->i_mapping, rc); + rc = 0; + +- if (attrs->ia_valid & ATTR_MTIME) { ++ if ((attrs->ia_valid & ATTR_MTIME) && ++ !(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOSSYNC)) { + rc = cifs_get_writable_file(cifsInode, FIND_WR_ANY, &wfile); + if (!rc) { + tcon = tlink_tcon(wfile->tlink); +-- +2.25.1 + diff --git a/patches.suse/smb3-fix-potential-null-dereference-in-decrypt-offload.patch b/patches.suse/smb3-fix-potential-null-dereference-in-decrypt-offload.patch new file mode 100644 index 0000000..f6c4204 --- /dev/null +++ b/patches.suse/smb3-fix-potential-null-dereference-in-decrypt-offload.patch @@ -0,0 +1,52 @@ +From: Steve French +Date: Fri, 13 Sep 2019 16:47:31 -0500 +Subject: [PATCH] smb3: fix potential null dereference in decrypt offload +Git-commit: 2255397c33425b9c43e36ab01479842258dedccb +References: bsc#1144333 +Patch-mainline: v5.4-rc1 + +commit a091c5f67c99 ("smb3: allow parallelizing decryption of reads") +had a potential null dereference + +Reported-by: kbuild test robot +Reported-by: Dan Carpenter +Suggested-by: Pavel Shilovsky +Signed-off-by: Steve French +Acked-by: Paulo Alcantara +--- + fs/cifs/smb2ops.c | 9 +++------ + 1 file changed, 3 insertions(+), 6 deletions(-) + +diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c +index 5776d7b0a97e..eaed18061314 100644 +--- a/fs/cifs/smb2ops.c ++++ b/fs/cifs/smb2ops.c +@@ -4055,6 +4055,7 @@ static void smb2_decrypt_offload(struct work_struct *work) + goto free_pages; + } + ++ dw->server->lstrp = jiffies; + mid = smb2_find_mid(dw->server, dw->buf); + if (mid == NULL) + cifs_dbg(FYI, "mid not found\n"); +@@ -4063,14 +4064,10 @@ static void smb2_decrypt_offload(struct work_struct *work) + rc = handle_read_data(dw->server, mid, dw->buf, + dw->server->vals->read_rsp_size, + dw->ppages, dw->npages, dw->len); ++ mid->callback(mid); ++ cifs_mid_q_entry_release(mid); + } + +- dw->server->lstrp = jiffies; +- +- mid->callback(mid); +- +- cifs_mid_q_entry_release(mid); +- + free_pages: + for (i = dw->npages-1; i >= 0; i--) + put_page(dw->ppages[i]); +-- +2.25.1 + + diff --git a/patches.suse/smb3-fix-problem-with-null-cifs-super-block-with-previous-patch.patch b/patches.suse/smb3-fix-problem-with-null-cifs-super-block-with-previous-patch.patch new file mode 100644 index 0000000..a5e2660 --- /dev/null +++ b/patches.suse/smb3-fix-problem-with-null-cifs-super-block-with-previous-patch.patch @@ -0,0 +1,49 @@ +From: Steve French +Date: Tue, 4 Feb 2020 13:02:59 -0600 +Subject: [PATCH] smb3: fix problem with null cifs super block with previous + patch +Git-commit: 87f93d82e0952da18af4d978e7d887b4c5326c0b +References: bsc#1144333 +Patch-mainline: v5.6-rc1 + +Add check for null cifs_sb to create_options helper + +Signed-off-by: Steve French +Reviewed-by: Amir Goldstein +Reviewed-by: Aurelien Aptel +Acked-by: Paulo Alcantara +--- + fs/cifs/cifsproto.h | 2 +- + fs/cifs/smb2ops.c | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h +index 748bd00cb5f1..89eaaf46d1ca 100644 +--- a/fs/cifs/cifsproto.h ++++ b/fs/cifs/cifsproto.h +@@ -614,7 +614,7 @@ static inline int get_dfs_path(const unsigned int xid, struct cifs_ses *ses, + + static inline int cifs_create_options(struct cifs_sb_info *cifs_sb, int options) + { +- if (backup_cred(cifs_sb)) ++ if (cifs_sb && (backup_cred(cifs_sb))) + return options | CREATE_OPEN_BACKUP_INTENT; + else + return options; +diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c +index 33bb86cae369..ac6628e28b12 100644 +--- a/fs/cifs/smb2ops.c ++++ b/fs/cifs/smb2ops.c +@@ -2407,7 +2407,7 @@ smb2_queryfs(const unsigned int xid, struct cifs_tcon *tcon, + FS_FULL_SIZE_INFORMATION, + SMB2_O_INFO_FILESYSTEM, + sizeof(struct smb2_fs_full_size_info), +- &rsp_iov, &buftype, NULL); ++ &rsp_iov, &buftype, cifs_sb); + if (rc) + goto qfs_exit; + +-- +2.25.1 + + diff --git a/patches.suse/smb3-improve-check-for-when-we-send-the-security-descriptor-context.patch b/patches.suse/smb3-improve-check-for-when-we-send-the-security-descriptor-context.patch new file mode 100644 index 0000000..db88e64 --- /dev/null +++ b/patches.suse/smb3-improve-check-for-when-we-send-the-security-descriptor-context.patch @@ -0,0 +1,39 @@ +From: Steve French +Date: Sat, 7 Dec 2019 17:38:22 -0600 +Subject: [PATCH] smb3: improve check for when we send the security descriptor + context on create +Git-commit: 231e2a0ba56733c95cb77d8920e76502b2134e72 +References: bsc#1144333 +Patch-mainline: v5.5-rc1 + +We had cases in the previous patch where we were sending the security +descriptor context on SMB3 open (file create) in cases when we hadn't +mounted with with "modefromsid" mount option. + +Add check for that mount flag before calling ad_sd_context in +open init. + +Signed-off-by: Steve French +Reviewed-by: Pavel Shilovsky +Acked-by: Paulo Alcantara +--- + fs/cifs/smb2pdu.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c +index b77643e02157..0ab6b1200288 100644 +--- a/fs/cifs/smb2pdu.c ++++ b/fs/cifs/smb2pdu.c +@@ -2630,6 +2630,8 @@ SMB2_open_init(struct cifs_tcon *tcon, struct smb_rqst *rqst, __u8 *oplock, + } + + if ((oparms->disposition != FILE_OPEN) && ++ (oparms->cifs_sb) && ++ (oparms->cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MODE_FROM_SID) && + (oparms->mode != ACL_NO_MODE)) { + if (n_iov > 2) { + struct create_context *ccontext = +-- +2.25.1 + + diff --git a/patches.suse/smb3-log-warning-if-CSC-policy-conflicts-with-cache-mount-option.patch b/patches.suse/smb3-log-warning-if-CSC-policy-conflicts-with-cache-mount-option.patch new file mode 100644 index 0000000..109e699 --- /dev/null +++ b/patches.suse/smb3-log-warning-if-CSC-policy-conflicts-with-cache-mount-option.patch @@ -0,0 +1,43 @@ +From: Steve French +Date: Tue, 3 Sep 2019 17:49:46 -0500 +Subject: [PATCH] smb3: log warning if CSC policy conflicts with cache mount + option +Git-commit: cae53f70f812c845fcedb577b0d40ec97ee4b920 +References: bsc#1144333 +Patch-mainline: v5.4-rc1 + +If the server config (e.g. Samba smb.conf "csc policy = disable) +for the share indicates that the share should not be cached, log +a warning message if forced client side caching ("cache=ro" or +"cache=singleclient") is requested on mount. + +Signed-off-by: Steve French +Reviewed-by: Ronnie Sahlberg +Acked-by: Paulo Alcantara +--- + fs/cifs/connect.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c +index d9a995588c74..85f8d943a05a 100644 +--- a/fs/cifs/connect.c ++++ b/fs/cifs/connect.c +@@ -3478,6 +3478,14 @@ cifs_get_tcon(struct cifs_ses *ses, struct smb_vol *volume_info) + tcon->use_resilient = true; + } + ++ /* If the user really knows what they are doing they can override */ ++ if (tcon->share_flags & SMB2_SHAREFLAG_NO_CACHING) { ++ if (volume_info->cache_ro) ++ cifs_dbg(VFS, "cache=ro requested on mount but NO_CACHING flag set on share\n"); ++ else if (volume_info->cache_rw) ++ cifs_dbg(VFS, "cache=singleclient requested on mount but NO_CACHING flag set on share\n"); ++ } ++ + /* + * We can have only one retry value for a connection to a share so for + * resources mounted more than once to the same server share the last +-- +2.25.1 + + diff --git a/patches.suse/smb3-missing-ACL-related-flags.patch b/patches.suse/smb3-missing-ACL-related-flags.patch new file mode 100644 index 0000000..b1ec949 --- /dev/null +++ b/patches.suse/smb3-missing-ACL-related-flags.patch @@ -0,0 +1,123 @@ +From: Steve French +Date: Thu, 26 Sep 2019 04:37:18 -0500 +Subject: [PATCH] smb3: missing ACL related flags +Git-commit: ff3ee62a55869b1a64266b5c15af16f2eb37c8a7 +References: bsc#1144333 +Patch-mainline: v5.4-rc1 + +Various SMB3 ACL related flags (for security descriptor and +ACEs for example) were missing and some fields are different +in SMB3 and CIFS. Update cifsacl.h definitions based on +current MS-DTYP specification. + +Signed-off-by: Steve French +Reviewed-by: Ronnie Sahlberg +Reviewed-by: Aurelien Aptel +Acked-by: Paulo Alcantara +--- + fs/cifs/cifsacl.h | 81 ++++++++++++++++++++++++++++++++++++++++++++++- + 1 file changed, 80 insertions(+), 1 deletion(-) + +diff --git a/fs/cifs/cifsacl.h b/fs/cifs/cifsacl.h +index eb428349f29a..439b99cefeb0 100644 +--- a/fs/cifs/cifsacl.h ++++ b/fs/cifs/cifsacl.h +@@ -90,14 +90,93 @@ struct cifs_acl { + __le32 num_aces; + } __attribute__((packed)); + ++/* ACE types - see MS-DTYP 2.4.4.1 */ ++#define ACCESS_ALLOWED_ACE_TYPE 0x00 ++#define ACCESS_DENIED_ACE_TYPE 0x01 ++#define SYSTEM_AUDIT_ACE_TYPE 0x02 ++#define SYSTEM_ALARM_ACE_TYPE 0x03 ++#define ACCESS_ALLOWED_COMPOUND_ACE_TYPE 0x04 ++#define ACCESS_ALLOWED_OBJECT_ACE_TYPE 0x05 ++#define ACCESS_DENIED_OBJECT_ACE_TYPE 0x06 ++#define SYSTEM_AUDIT_OBJECT_ACE_TYPE 0x07 ++#define SYSTEM_ALARM_OBJECT_ACE_TYPE 0x08 ++#define ACCESS_ALLOWED_CALLBACK_ACE_TYPE 0x09 ++#define ACCESS_DENIED_CALLBACK_ACE_TYPE 0x0A ++#define ACCESS_ALLOWED_CALLBACK_OBJECT_ACE_TYPE 0x0B ++#define ACCESS_DENIED_CALLBACK_OBJECT_ACE_TYPE 0x0C ++#define SYSTEM_AUDIT_CALLBACK_ACE_TYPE 0x0D ++#define SYSTEM_ALARM_CALLBACK_ACE_TYPE 0x0E /* Reserved */ ++#define SYSTEM_AUDIT_CALLBACK_OBJECT_ACE_TYPE 0x0F ++#define SYSTEM_ALARM_CALLBACK_OBJECT_ACE_TYPE 0x10 /* reserved */ ++#define SYSTEM_MANDATORY_LABEL_ACE_TYPE 0x11 ++#define SYSTEM_RESOURCE_ATTRIBUTE_ACE_TYPE 0x12 ++#define SYSTEM_SCOPED_POLICY_ID_ACE_TYPE 0x13 ++ ++/* ACE flags */ ++#define OBJECT_INHERIT_ACE 0x01 ++#define CONTAINER_INHERIT_ACE 0x02 ++#define NO_PROPAGATE_INHERIT_ACE 0x04 ++#define INHERIT_ONLY_ACE 0x08 ++#define INHERITED_ACE 0x10 ++#define SUCCESSFUL_ACCESS_ACE_FLAG 0x40 ++#define FAILED_ACCESS_ACE_FLAG 0x80 ++ + struct cifs_ace { +- __u8 type; ++ __u8 type; /* see above and MS-DTYP 2.4.4.1 */ + __u8 flags; + __le16 size; + __le32 access_req; + struct cifs_sid sid; /* ie UUID of user or group who gets these perms */ + } __attribute__((packed)); + ++/* ++ * The current SMB3 form of security descriptor is similar to what was used for ++ * cifs (see above) but some fields are split, and fields in the struct below ++ * matches names of fields to the the spec, MS-DTYP (see sections 2.4.5 and ++ * 2.4.6). Note that "CamelCase" fields are used in this struct in order to ++ * match the MS-DTYP and MS-SMB2 specs which define the wire format. ++ */ ++struct smb3_sd { ++ __u8 Revision; /* revision level, MUST be one */ ++ __u8 Sbz1; /* only meaningful if 'RM' flag set below */ ++ __le16 Control; ++ __le32 OffsetOwner; ++ __le32 OffsetGroup; ++ __le32 OffsetSacl; ++ __le32 OffsetDacl; ++} __packed; ++ ++/* Meaning of 'Control' field flags */ ++#define ACL_CONTROL_SR 0x0001 /* Self relative */ ++#define ACL_CONTROL_RM 0x0002 /* Resource manager control bits */ ++#define ACL_CONTROL_PS 0x0004 /* SACL protected from inherits */ ++#define ACL_CONTROL_PD 0x0008 /* DACL protected from inherits */ ++#define ACL_CONTROL_SI 0x0010 /* SACL Auto-Inherited */ ++#define ACL_CONTROL_DI 0x0020 /* DACL Auto-Inherited */ ++#define ACL_CONTROL_SC 0x0040 /* SACL computed through inheritance */ ++#define ACL_CONTROL_DC 0x0080 /* DACL computed through inheritence */ ++#define ACL_CONTROL_SS 0x0100 /* Create server ACL */ ++#define ACL_CONTROL_DT 0x0200 /* DACL provided by trusteed source */ ++#define ACL_CONTROL_SD 0x0400 /* SACL defaulted */ ++#define ACL_CONTROL_SP 0x0800 /* SACL is present on object */ ++#define ACL_CONTROL_DD 0x1000 /* DACL defaulted */ ++#define ACL_CONTROL_DP 0x2000 /* DACL is present on object */ ++#define ACL_CONTROL_GD 0x4000 /* Group was defaulted */ ++#define ACL_CONTROL_OD 0x8000 /* User was defaulted */ ++ ++/* Meaning of AclRevision flags */ ++#define ACL_REVISION 0x02 /* See section 2.4.4.1 of MS-DTYP */ ++#define ACL_REVISION_DS 0x04 /* Additional AceTypes allowed */ ++ ++struct smb3_acl { ++ u8 AclRevision; /* revision level */ ++ u8 Sbz1; /* MBZ */ ++ __le16 AclSize; ++ __le16 AceCount; ++ __le16 Sbz2; /* MBZ */ ++} __packed; ++ ++ + /* + * Minimum security identifier can be one for system defined Users + * and Groups such as NULL SID and World or Built-in accounts such +-- +2.25.1 + + diff --git a/patches.suse/smb3-only-offload-decryption-of-read-responses-if-multiple-requests.patch b/patches.suse/smb3-only-offload-decryption-of-read-responses-if-multiple-requests.patch new file mode 100644 index 0000000..517ef82 --- /dev/null +++ b/patches.suse/smb3-only-offload-decryption-of-read-responses-if-multiple-requests.patch @@ -0,0 +1,58 @@ +From: Steve French +Date: Mon, 9 Sep 2019 13:30:15 -0500 +Subject: [PATCH] smb3: only offload decryption of read responses if multiple + requests +Git-commit: 10328c44cc1506dd82fd835efcaafd519866c464 +References: bsc#1144333 +Patch-mainline: v5.4-rc1 + +No point in offloading read decryption if no other requests on the +wire + +Signed-off-by: Steve French +Signed-off-by: Ronnie Sahlberg +Acked-by: Paulo Alcantara +--- + fs/cifs/cifsfs.c | 9 ++++++--- + fs/cifs/smb2ops.c | 2 +- + 2 files changed, 7 insertions(+), 4 deletions(-) + +diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c +index ebf85a5d95e4..c1b685072063 100644 +--- a/fs/cifs/cifsfs.c ++++ b/fs/cifs/cifsfs.c +@@ -1503,11 +1503,14 @@ init_cifs(void) + } + + /* +- * BB Consider setting limit!=0 maybe to min(num_of_cores - 1, 3) so we +- * don't launch too many worker threads ++ * Consider in future setting limit!=0 maybe to min(num_of_cores - 1, 3) ++ * so that we don't launch too many worker threads but ++ * Documentation/workqueue.txt recommends setting it to 0 + */ ++ ++ /* WQ_UNBOUND allows decrypt tasks to run on any CPU */ + decrypt_wq = alloc_workqueue("smb3decryptd", +- WQ_FREEZABLE|WQ_MEM_RECLAIM, 0); ++ WQ_UNBOUND|WQ_FREEZABLE|WQ_MEM_RECLAIM, 0); + if (!decrypt_wq) { + rc = -ENOMEM; + goto out_destroy_cifsiod_wq; +diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c +index 1cfb8d518132..72b3e39d7f4f 100644 +--- a/fs/cifs/smb2ops.c ++++ b/fs/cifs/smb2ops.c +@@ -4121,7 +4121,7 @@ receive_encrypted_read(struct TCP_Server_Info *server, struct mid_q_entry **mid, + * use more cores decrypting which can be expensive + */ + +- if ((server->min_offload) && ++ if ((server->min_offload) && (server->in_flight > 1) && + (server->pdu_size >= server->min_offload)) { + dw = kmalloc(sizeof(struct smb2_decrypt_work), GFP_KERNEL); + if (dw == NULL) +-- +2.25.1 + + diff --git a/patches.suse/smb3-pass-mode-bits-into-create-calls.patch b/patches.suse/smb3-pass-mode-bits-into-create-calls.patch new file mode 100644 index 0000000..d44294d --- /dev/null +++ b/patches.suse/smb3-pass-mode-bits-into-create-calls.patch @@ -0,0 +1,280 @@ +From: Steve French +Date: Wed, 25 Sep 2019 00:32:13 -0500 +Subject: [PATCH] smb3: pass mode bits into create calls +Git-commit: c3ca78e2174413c136d62ebdf8039580fe72b504 +References: bsc#1144333 +Patch-mainline: v5.4-rc1 + +We need to populate an ACL (security descriptor open context) +on file and directory correct. This patch passes in the +mode. Followon patch will build the open context and the +security descriptor (from the mode) that goes in the open +context. + +Signed-off-by: Steve French +Reviewed-by: Aurelien Aptel +Acked-by: Paulo Alcantara +--- + fs/cifs/cifsglob.h | 6 ++++-- + fs/cifs/cifsproto.h | 3 ++- + fs/cifs/cifssmb.c | 3 ++- + fs/cifs/inode.c | 3 ++- + fs/cifs/smb2inode.c | 34 +++++++++++++++++++--------------- + fs/cifs/smb2pdu.c | 20 ++++++++++++++++++++ + fs/cifs/smb2proto.h | 3 ++- + 7 files changed, 51 insertions(+), 21 deletions(-) + +diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h +index 54e204589cb9..2e960e1049db 100644 +--- a/fs/cifs/cifsglob.h ++++ b/fs/cifs/cifsglob.h +@@ -331,8 +331,9 @@ struct smb_version_operations { + umode_t mode, struct cifs_tcon *tcon, + const char *full_path, + struct cifs_sb_info *cifs_sb); +- int (*mkdir)(const unsigned int, struct cifs_tcon *, const char *, +- struct cifs_sb_info *); ++ int (*mkdir)(const unsigned int xid, struct inode *inode, umode_t mode, ++ struct cifs_tcon *tcon, const char *name, ++ struct cifs_sb_info *sb); + /* set info on created directory */ + void (*mkdir_setinfo)(struct inode *, const char *, + struct cifs_sb_info *, struct cifs_tcon *, +@@ -1209,6 +1210,7 @@ struct cifs_search_info { + bool smallBuf:1; /* so we know which buf_release function to call */ + }; + ++#define ACL_NO_MODE -1 + struct cifs_open_parms { + struct cifs_tcon *tcon; + struct cifs_sb_info *cifs_sb; +diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h +index 99b1b1ef558c..e53e9f62b87b 100644 +--- a/fs/cifs/cifsproto.h ++++ b/fs/cifs/cifsproto.h +@@ -372,7 +372,8 @@ extern int CIFSSMBUnixSetPathInfo(const unsigned int xid, + const struct nls_table *nls_codepage, + int remap); + +-extern int CIFSSMBMkDir(const unsigned int xid, struct cifs_tcon *tcon, ++extern int CIFSSMBMkDir(const unsigned int xid, struct inode *inode, ++ umode_t mode, struct cifs_tcon *tcon, + const char *name, struct cifs_sb_info *cifs_sb); + extern int CIFSSMBRmDir(const unsigned int xid, struct cifs_tcon *tcon, + const char *name, struct cifs_sb_info *cifs_sb); +diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c +index dbee2132e419..4f554f019a98 100644 +--- a/fs/cifs/cifssmb.c ++++ b/fs/cifs/cifssmb.c +@@ -1078,7 +1078,8 @@ CIFSSMBRmDir(const unsigned int xid, struct cifs_tcon *tcon, const char *name, + } + + int +-CIFSSMBMkDir(const unsigned int xid, struct cifs_tcon *tcon, const char *name, ++CIFSSMBMkDir(const unsigned int xid, struct inode *inode, umode_t mode, ++ struct cifs_tcon *tcon, const char *name, + struct cifs_sb_info *cifs_sb) + { + int rc = 0; +diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c +index 26cdfbf1e164..3bae2e53f0b8 100644 +--- a/fs/cifs/inode.c ++++ b/fs/cifs/inode.c +@@ -1622,13 +1622,14 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, umode_t mode) + } + + /* BB add setting the equivalent of mode via CreateX w/ACLs */ +- rc = server->ops->mkdir(xid, tcon, full_path, cifs_sb); ++ rc = server->ops->mkdir(xid, inode, mode, tcon, full_path, cifs_sb); + if (rc) { + cifs_dbg(FYI, "cifs_mkdir returned 0x%x\n", rc); + d_drop(direntry); + goto mkdir_out; + } + ++ /* TODO: skip this for smb2/smb3 */ + rc = cifs_mkdir_qinfo(inode, direntry, mode, full_path, cifs_sb, tcon, + xid); + mkdir_out: +diff --git a/fs/cifs/smb2inode.c b/fs/cifs/smb2inode.c +index d2a3fb7e5c8d..4121ac1163ca 100644 +--- a/fs/cifs/smb2inode.c ++++ b/fs/cifs/smb2inode.c +@@ -51,7 +51,7 @@ static int + smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon, + struct cifs_sb_info *cifs_sb, const char *full_path, + __u32 desired_access, __u32 create_disposition, +- __u32 create_options, void *ptr, int command, ++ __u32 create_options, umode_t mode, void *ptr, int command, + struct cifsFileInfo *cfile) + { + int rc; +@@ -103,6 +103,7 @@ smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon, + oparms.create_options |= CREATE_OPEN_BACKUP_INTENT; + oparms.fid = &fid; + oparms.reconnect = false; ++ oparms.mode = mode; + + memset(&open_iov, 0, sizeof(open_iov)); + rqst[num_rqst].rq_iov = open_iov; +@@ -478,7 +479,7 @@ smb2_query_path_info(const unsigned int xid, struct cifs_tcon *tcon, + cifs_get_readable_path(tcon, full_path, &cfile); + rc = smb2_compound_op(xid, tcon, cifs_sb, full_path, + FILE_READ_ATTRIBUTES, FILE_OPEN, create_options, +- smb2_data, SMB2_OP_QUERY_INFO, cfile); ++ ACL_NO_MODE, smb2_data, SMB2_OP_QUERY_INFO, cfile); + if (rc == -EOPNOTSUPP) { + *symlink = true; + create_options |= OPEN_REPARSE_POINT; +@@ -486,8 +487,8 @@ smb2_query_path_info(const unsigned int xid, struct cifs_tcon *tcon, + /* Failed on a symbolic link - query a reparse point info */ + rc = smb2_compound_op(xid, tcon, cifs_sb, full_path, + FILE_READ_ATTRIBUTES, FILE_OPEN, +- create_options, smb2_data, +- SMB2_OP_QUERY_INFO, NULL); ++ create_options, ACL_NO_MODE, ++ smb2_data, SMB2_OP_QUERY_INFO, NULL); + } + if (rc) + goto out; +@@ -499,12 +500,14 @@ smb2_query_path_info(const unsigned int xid, struct cifs_tcon *tcon, + } + + int +-smb2_mkdir(const unsigned int xid, struct cifs_tcon *tcon, const char *name, ++smb2_mkdir(const unsigned int xid, struct inode *parent_inode, umode_t mode, ++ struct cifs_tcon *tcon, const char *name, + struct cifs_sb_info *cifs_sb) + { + return smb2_compound_op(xid, tcon, cifs_sb, name, + FILE_WRITE_ATTRIBUTES, FILE_CREATE, +- CREATE_NOT_FILE, NULL, SMB2_OP_MKDIR, NULL); ++ CREATE_NOT_FILE, mode, NULL, SMB2_OP_MKDIR, ++ NULL); + } + + void +@@ -525,8 +528,8 @@ smb2_mkdir_setinfo(struct inode *inode, const char *name, + cifs_get_writable_path(tcon, name, &cfile); + tmprc = smb2_compound_op(xid, tcon, cifs_sb, name, + FILE_WRITE_ATTRIBUTES, FILE_CREATE, +- CREATE_NOT_FILE, &data, SMB2_OP_SET_INFO, +- cfile); ++ CREATE_NOT_FILE, ACL_NO_MODE, ++ &data, SMB2_OP_SET_INFO, cfile); + if (tmprc == 0) + cifs_i->cifsAttrs = dosattrs; + } +@@ -536,7 +539,7 @@ smb2_rmdir(const unsigned int xid, struct cifs_tcon *tcon, const char *name, + struct cifs_sb_info *cifs_sb) + { + return smb2_compound_op(xid, tcon, cifs_sb, name, DELETE, FILE_OPEN, +- CREATE_NOT_FILE, ++ CREATE_NOT_FILE, ACL_NO_MODE, + NULL, SMB2_OP_RMDIR, NULL); + } + +@@ -546,7 +549,7 @@ smb2_unlink(const unsigned int xid, struct cifs_tcon *tcon, const char *name, + { + return smb2_compound_op(xid, tcon, cifs_sb, name, DELETE, FILE_OPEN, + CREATE_DELETE_ON_CLOSE | OPEN_REPARSE_POINT, +- NULL, SMB2_OP_DELETE, NULL); ++ ACL_NO_MODE, NULL, SMB2_OP_DELETE, NULL); + } + + static int +@@ -564,7 +567,8 @@ smb2_set_path_attr(const unsigned int xid, struct cifs_tcon *tcon, + goto smb2_rename_path; + } + rc = smb2_compound_op(xid, tcon, cifs_sb, from_name, access, +- FILE_OPEN, 0, smb2_to_name, command, cfile); ++ FILE_OPEN, 0, ACL_NO_MODE, smb2_to_name, ++ command, cfile); + smb2_rename_path: + kfree(smb2_to_name); + return rc; +@@ -601,8 +605,8 @@ smb2_set_path_size(const unsigned int xid, struct cifs_tcon *tcon, + __le64 eof = cpu_to_le64(size); + + return smb2_compound_op(xid, tcon, cifs_sb, full_path, +- FILE_WRITE_DATA, FILE_OPEN, 0, &eof, +- SMB2_OP_SET_EOF, NULL); ++ FILE_WRITE_DATA, FILE_OPEN, 0, ACL_NO_MODE, ++ &eof, SMB2_OP_SET_EOF, NULL); + } + + int +@@ -623,8 +627,8 @@ smb2_set_file_info(struct inode *inode, const char *full_path, + return PTR_ERR(tlink); + + rc = smb2_compound_op(xid, tlink_tcon(tlink), cifs_sb, full_path, +- FILE_WRITE_ATTRIBUTES, FILE_OPEN, 0, buf, +- SMB2_OP_SET_INFO, NULL); ++ FILE_WRITE_ATTRIBUTES, FILE_OPEN, ++ 0, ACL_NO_MODE, buf, SMB2_OP_SET_INFO, NULL); + cifs_put_tlink(tlink); + return rc; + } +diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c +index ea08e6159481..85f9d614d968 100644 +--- a/fs/cifs/smb2pdu.c ++++ b/fs/cifs/smb2pdu.c +@@ -751,6 +751,8 @@ add_posix_context(struct kvec *iov, unsigned int *num_iovec, umode_t mode) + unsigned int num = *num_iovec; + + iov[num].iov_base = create_posix_buf(mode); ++ if (mode == -1) ++ cifs_dbg(VFS, "illegal mode\n"); /* BB REMOVEME */ + if (iov[num].iov_base == NULL) + return -ENOMEM; + iov[num].iov_len = sizeof(struct create_posix); +@@ -2417,6 +2419,7 @@ SMB2_open_init(struct cifs_tcon *tcon, struct smb_rqst *rqst, __u8 *oplock, + /* File attributes ignored on open (used in create though) */ + req->FileAttributes = cpu_to_le32(file_attributes); + req->ShareAccess = FILE_SHARE_ALL_LE; ++ + req->CreateDisposition = cpu_to_le32(oparms->disposition); + req->CreateOptions = cpu_to_le32(oparms->create_options & CREATE_OPTIONS_MASK); + req->NameOffset = cpu_to_le16(sizeof(struct smb2_create_req)); +@@ -2518,6 +2521,23 @@ SMB2_open_init(struct cifs_tcon *tcon, struct smb_rqst *rqst, __u8 *oplock, + return rc; + } + ++ /* TODO: add handling for the mode on create */ ++ if (oparms->disposition == FILE_CREATE) ++ cifs_dbg(VFS, "mode is 0x%x\n", oparms->mode); /* BB REMOVEME */ ++ ++ if ((oparms->disposition == FILE_CREATE) && (oparms->mode != -1)) { ++ if (n_iov > 2) { ++ struct create_context *ccontext = ++ (struct create_context *)iov[n_iov-1].iov_base; ++ ccontext->Next = ++ cpu_to_le32(iov[n_iov-1].iov_len); ++ } ++ ++ /* rc = add_sd_context(iov, &n_iov, oparms->mode); */ ++ if (rc) ++ return rc; ++ } ++ + if (n_iov > 2) { + struct create_context *ccontext = + (struct create_context *)iov[n_iov-1].iov_base; +diff --git a/fs/cifs/smb2proto.h b/fs/cifs/smb2proto.h +index 67a91b11fd59..da3a6d580808 100644 +--- a/fs/cifs/smb2proto.h ++++ b/fs/cifs/smb2proto.h +@@ -84,7 +84,8 @@ extern int smb311_posix_mkdir(const unsigned int xid, struct inode *inode, + umode_t mode, struct cifs_tcon *tcon, + const char *full_path, + struct cifs_sb_info *cifs_sb); +-extern int smb2_mkdir(const unsigned int xid, struct cifs_tcon *tcon, ++extern int smb2_mkdir(const unsigned int xid, struct inode *inode, ++ umode_t mode, struct cifs_tcon *tcon, + const char *name, struct cifs_sb_info *cifs_sb); + extern void smb2_mkdir_setinfo(struct inode *inode, const char *full_path, + struct cifs_sb_info *cifs_sb, +-- +2.25.1 + + diff --git a/patches.suse/smb3-print-warning-once-if-posix-context-returned-on-open.patch b/patches.suse/smb3-print-warning-once-if-posix-context-returned-on-open.patch new file mode 100644 index 0000000..1e41cde --- /dev/null +++ b/patches.suse/smb3-print-warning-once-if-posix-context-returned-on-open.patch @@ -0,0 +1,86 @@ +From: Steve French +Date: Thu, 6 Feb 2020 17:31:56 -0600 +Subject: [PATCH] smb3: print warning once if posix context returned on open +Git-commit: ab3459d8f0ef52c38119ed58c4c29139efc7022c +References: bsc#1144333 +Patch-mainline: v5.6-rc1 + +SMB3.1.1 POSIX Context processing is not complete yet - so print warning +(once) if server returns it on open. + +Signed-off-by: Steve French +Reviewed-by: Aurelien Aptel +Acked-by: Paulo Alcantara +--- + fs/cifs/smb2pdu.c | 22 ++++++++++++++++++++++ + fs/cifs/smb2pdu.h | 8 ++++++++ + 2 files changed, 30 insertions(+) + +diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c +index 47cce0bd1afe..1234f9ccab03 100644 +--- a/fs/cifs/smb2pdu.c ++++ b/fs/cifs/smb2pdu.c +@@ -1939,6 +1939,16 @@ parse_query_id_ctxt(struct create_context *cc, struct smb2_file_all_info *buf) + buf->IndexNumber = pdisk_id->DiskFileId; + } + ++static void ++parse_posix_ctxt(struct create_context *cc, struct smb_posix_info *pposix_inf) ++{ ++ /* struct smb_posix_info *ppinf = (struct smb_posix_info *)cc; */ ++ ++ /* TODO: Need to add parsing for the context and return */ ++ printk_once(KERN_WARNING ++ "SMB3 3.11 POSIX response context not completed yet\n"); ++} ++ + void + smb2_parse_contexts(struct TCP_Server_Info *server, + struct smb2_create_rsp *rsp, +@@ -1950,6 +1960,9 @@ smb2_parse_contexts(struct TCP_Server_Info *server, + unsigned int next; + unsigned int remaining; + char *name; ++ const char smb3_create_tag_posix[] = {0x93, 0xAD, 0x25, 0x50, 0x9C, ++ 0xB4, 0x11, 0xE7, 0xB4, 0x23, 0x83, ++ 0xDE, 0x96, 0x8B, 0xCD, 0x7C}; + + *oplock = 0; + data_offset = (char *)rsp + le32_to_cpu(rsp->CreateContextsOffset); +@@ -1969,6 +1982,15 @@ smb2_parse_contexts(struct TCP_Server_Info *server, + else if (buf && (le16_to_cpu(cc->NameLength) == 4) && + strncmp(name, SMB2_CREATE_QUERY_ON_DISK_ID, 4) == 0) + parse_query_id_ctxt(cc, buf); ++ else if ((le16_to_cpu(cc->NameLength) == 16)) { ++ if (memcmp(name, smb3_create_tag_posix, 16) == 0) ++ parse_posix_ctxt(cc, NULL); ++ } ++ /* else { ++ cifs_dbg(FYI, "Context not matched with len %d\n", ++ le16_to_cpu(cc->NameLength)); ++ cifs_dump_mem("Cctxt name: ", name, 4); ++ } */ + + next = le32_to_cpu(cc->Next); + if (!next) +diff --git a/fs/cifs/smb2pdu.h b/fs/cifs/smb2pdu.h +index 4c43dbd1e089..ca2123d7f199 100644 +--- a/fs/cifs/smb2pdu.h ++++ b/fs/cifs/smb2pdu.h +@@ -1595,4 +1595,12 @@ struct smb2_file_network_open_info { + + extern char smb2_padding[7]; + ++/* equivalent of the contents of SMB3.1.1 POSIX open context response */ ++struct smb_posix_info { ++ __le32 nlink; ++ __le32 reparse_tag; ++ __le32 mode; ++ kuid_t uid; ++ kuid_t gid; ++}; + #endif /* _SMB2PDU_H */ +-- +2.25.1 + + diff --git a/patches.suse/smb3-query-attributes-on-file-close.patch b/patches.suse/smb3-query-attributes-on-file-close.patch new file mode 100644 index 0000000..7ccc7a0 --- /dev/null +++ b/patches.suse/smb3-query-attributes-on-file-close.patch @@ -0,0 +1,322 @@ +From: Steve French +Date: Mon, 2 Dec 2019 21:46:54 -0600 +Subject: [PATCH] smb3: query attributes on file close +Git-commit: 43f8a6a74ee2442b9410ed297f5d4c77e7cb5ace +References: bsc#1144333 +Patch-mainline: v5.5-rc1 + +Since timestamps on files on most servers can be updated at +close, and since timestamps on our dentries default to one +second we can have stale timestamps in some common cases +(e.g. open, write, close, stat, wait one second, stat - will +show different mtime for the first and second stat). + +The SMB2/SMB3 protocol allows querying timestamps at close +so add the code to request timestamp and attr information +(which is cheap for the server to provide) to be returned +when a file is closed (it is not needed for the many +paths that call SMB2_close that are from compounded +query infos and close nor is it needed for some of +the cases where a directory close immediately follows a +directory open. + +Signed-off-by: Steve French +Acked-by: Ronnie Sahlberg +Reviewed-by: Aurelien Aptel +Reviewed-by: Pavel Shilovsky +Acked-by: Paulo Alcantara +--- + fs/cifs/cifsglob.h | 3 +++ + fs/cifs/file.c | 4 +++- + fs/cifs/smb2inode.c | 2 +- + fs/cifs/smb2ops.c | 49 +++++++++++++++++++++++++++++++++++++++++---- + fs/cifs/smb2pdu.c | 38 +++++++++++++++++++++++++++-------- + fs/cifs/smb2pdu.h | 11 ++++++++++ + fs/cifs/smb2proto.h | 5 ++++- + 7 files changed, 97 insertions(+), 15 deletions(-) + +diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h +index d34a4ed8c57d..5b976e01dd6b 100644 +--- a/fs/cifs/cifsglob.h ++++ b/fs/cifs/cifsglob.h +@@ -368,6 +368,9 @@ struct smb_version_operations { + /* close a file */ + void (*close)(const unsigned int, struct cifs_tcon *, + struct cifs_fid *); ++ /* close a file, returning file attributes and timestamps */ ++ void (*close_getattr)(const unsigned int xid, struct cifs_tcon *tcon, ++ struct cifsFileInfo *pfile_info); + /* send a flush request to the server */ + int (*flush)(const unsigned int, struct cifs_tcon *, struct cifs_fid *); + /* async read from the server */ +diff --git a/fs/cifs/file.c b/fs/cifs/file.c +index 9ae41042fa3d..043288b5c728 100644 +--- a/fs/cifs/file.c ++++ b/fs/cifs/file.c +@@ -496,7 +496,9 @@ void _cifsFileInfo_put(struct cifsFileInfo *cifs_file, + unsigned int xid; + + xid = get_xid(); +- if (server->ops->close) ++ if (server->ops->close_getattr) ++ server->ops->close_getattr(xid, tcon, cifs_file); ++ else if (server->ops->close) + server->ops->close(xid, tcon, &cifs_file->fid); + _free_xid(xid); + } +diff --git a/fs/cifs/smb2inode.c b/fs/cifs/smb2inode.c +index 4121ac1163ca..18c7a33adceb 100644 +--- a/fs/cifs/smb2inode.c ++++ b/fs/cifs/smb2inode.c +@@ -313,7 +313,7 @@ smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon, + rqst[num_rqst].rq_iov = close_iov; + rqst[num_rqst].rq_nvec = 1; + rc = SMB2_close_init(tcon, &rqst[num_rqst], COMPOUND_FID, +- COMPOUND_FID); ++ COMPOUND_FID, false); + smb2_set_related(&rqst[num_rqst]); + if (rc) + goto finished; +diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c +index a7f328f79c6f..a5c96bc522cb 100644 +--- a/fs/cifs/smb2ops.c ++++ b/fs/cifs/smb2ops.c +@@ -1178,7 +1178,7 @@ smb2_set_ea(const unsigned int xid, struct cifs_tcon *tcon, + memset(&close_iov, 0, sizeof(close_iov)); + rqst[2].rq_iov = close_iov; + rqst[2].rq_nvec = 1; +- rc = SMB2_close_init(tcon, &rqst[2], COMPOUND_FID, COMPOUND_FID); ++ rc = SMB2_close_init(tcon, &rqst[2], COMPOUND_FID, COMPOUND_FID, false); + smb2_set_related(&rqst[2]); + + rc = compound_send_recv(xid, ses, flags, 3, rqst, +@@ -1332,6 +1332,45 @@ smb2_close_file(const unsigned int xid, struct cifs_tcon *tcon, + SMB2_close(xid, tcon, fid->persistent_fid, fid->volatile_fid); + } + ++static void ++smb2_close_getattr(const unsigned int xid, struct cifs_tcon *tcon, ++ struct cifsFileInfo *cfile) ++{ ++ struct smb2_file_network_open_info file_inf; ++ struct inode *inode; ++ int rc; ++ ++ rc = __SMB2_close(xid, tcon, cfile->fid.persistent_fid, ++ cfile->fid.volatile_fid, &file_inf); ++ if (rc) ++ return; ++ ++ inode = d_inode(cfile->dentry); ++ ++ spin_lock(&inode->i_lock); ++ CIFS_I(inode)->time = jiffies; ++ ++ /* Creation time should not need to be updated on close */ ++ if (file_inf.LastWriteTime) ++ inode->i_mtime = cifs_NTtimeToUnix(file_inf.LastWriteTime); ++ if (file_inf.ChangeTime) ++ inode->i_ctime = cifs_NTtimeToUnix(file_inf.ChangeTime); ++ if (file_inf.LastAccessTime) ++ inode->i_atime = cifs_NTtimeToUnix(file_inf.LastAccessTime); ++ ++ /* ++ * i_blocks is not related to (i_size / i_blksize), ++ * but instead 512 byte (2**9) size is required for ++ * calculating num blocks. ++ */ ++ if (le64_to_cpu(file_inf.AllocationSize) > 4096) ++ inode->i_blocks = ++ (512 - 1 + le64_to_cpu(file_inf.AllocationSize)) >> 9; ++ ++ /* End of file and Attributes should not have to be updated on close */ ++ spin_unlock(&inode->i_lock); ++} ++ + static int + SMB2_request_res_key(const unsigned int xid, struct cifs_tcon *tcon, + u64 persistent_fid, u64 volatile_fid, +@@ -1512,7 +1551,7 @@ smb2_ioctl_query_info(const unsigned int xid, + rqst[2].rq_iov = close_iov; + rqst[2].rq_nvec = 1; + +- rc = SMB2_close_init(tcon, &rqst[2], COMPOUND_FID, COMPOUND_FID); ++ rc = SMB2_close_init(tcon, &rqst[2], COMPOUND_FID, COMPOUND_FID, false); + if (rc) + goto iqinf_exit; + smb2_set_related(&rqst[2]); +@@ -2241,7 +2280,7 @@ smb2_query_info_compound(const unsigned int xid, struct cifs_tcon *tcon, + rqst[2].rq_iov = close_iov; + rqst[2].rq_nvec = 1; + +- rc = SMB2_close_init(tcon, &rqst[2], COMPOUND_FID, COMPOUND_FID); ++ rc = SMB2_close_init(tcon, &rqst[2], COMPOUND_FID, COMPOUND_FID, false); + if (rc) + goto qic_exit; + smb2_set_related(&rqst[2]); +@@ -2654,7 +2693,7 @@ smb2_query_symlink(const unsigned int xid, struct cifs_tcon *tcon, + rqst[2].rq_iov = close_iov; + rqst[2].rq_nvec = 1; + +- rc = SMB2_close_init(tcon, &rqst[2], COMPOUND_FID, COMPOUND_FID); ++ rc = SMB2_close_init(tcon, &rqst[2], COMPOUND_FID, COMPOUND_FID, false); + if (rc) + goto querty_exit; + +@@ -4707,6 +4746,7 @@ struct smb_version_operations smb30_operations = { + .open = smb2_open_file, + .set_fid = smb2_set_fid, + .close = smb2_close_file, ++ .close_getattr = smb2_close_getattr, + .flush = smb2_flush_file, + .async_readv = smb2_async_readv, + .async_writev = smb2_async_writev, +@@ -4816,6 +4856,7 @@ struct smb_version_operations smb311_operations = { + .open = smb2_open_file, + .set_fid = smb2_set_fid, + .close = smb2_close_file, ++ .close_getattr = smb2_close_getattr, + .flush = smb2_flush_file, + .async_readv = smb2_async_readv, + .async_writev = smb2_async_writev, +diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c +index cec53eb8a6da..187a5ce68806 100644 +--- a/fs/cifs/smb2pdu.c ++++ b/fs/cifs/smb2pdu.c +@@ -2932,7 +2932,7 @@ SMB2_set_compression(const unsigned int xid, struct cifs_tcon *tcon, + + int + SMB2_close_init(struct cifs_tcon *tcon, struct smb_rqst *rqst, +- u64 persistent_fid, u64 volatile_fid) ++ u64 persistent_fid, u64 volatile_fid, bool query_attrs) + { + struct smb2_close_req *req; + struct kvec *iov = rqst->rq_iov; +@@ -2945,6 +2945,10 @@ SMB2_close_init(struct cifs_tcon *tcon, struct smb_rqst *rqst, + + req->PersistentFileId = persistent_fid; + req->VolatileFileId = volatile_fid; ++ if (query_attrs) ++ req->Flags = SMB2_CLOSE_FLAG_POSTQUERY_ATTRIB; ++ else ++ req->Flags = 0; + iov[0].iov_base = (char *)req; + iov[0].iov_len = total_len; + +@@ -2959,8 +2963,9 @@ SMB2_close_free(struct smb_rqst *rqst) + } + + int +-SMB2_close(const unsigned int xid, struct cifs_tcon *tcon, +- u64 persistent_fid, u64 volatile_fid) ++__SMB2_close(const unsigned int xid, struct cifs_tcon *tcon, ++ u64 persistent_fid, u64 volatile_fid, ++ struct smb2_file_network_open_info *pbuf) + { + struct smb_rqst rqst; + struct smb2_close_rsp *rsp = NULL; +@@ -2970,6 +2975,7 @@ SMB2_close(const unsigned int xid, struct cifs_tcon *tcon, + int resp_buftype = CIFS_NO_BUFFER; + int rc = 0; + int flags = 0; ++ bool query_attrs = false; + + cifs_dbg(FYI, "Close\n"); + +@@ -2984,8 +2990,13 @@ SMB2_close(const unsigned int xid, struct cifs_tcon *tcon, + rqst.rq_iov = iov; + rqst.rq_nvec = 1; + ++ /* check if need to ask server to return timestamps in close response */ ++ if (pbuf) ++ query_attrs = true; ++ + trace_smb3_close_enter(xid, persistent_fid, tcon->tid, ses->Suid); +- rc = SMB2_close_init(tcon, &rqst, persistent_fid, volatile_fid); ++ rc = SMB2_close_init(tcon, &rqst, persistent_fid, volatile_fid, ++ query_attrs); + if (rc) + goto close_exit; + +@@ -2997,14 +3008,18 @@ SMB2_close(const unsigned int xid, struct cifs_tcon *tcon, + trace_smb3_close_err(xid, persistent_fid, tcon->tid, ses->Suid, + rc); + goto close_exit; +- } else ++ } else { + trace_smb3_close_done(xid, persistent_fid, tcon->tid, + ses->Suid); ++ /* ++ * Note that have to subtract 4 since struct network_open_info ++ * has a final 4 byte pad that close response does not have ++ */ ++ if (pbuf) ++ memcpy(pbuf, (char *)&rsp->CreationTime, sizeof(*pbuf) - 4); ++ } + + atomic_dec(&tcon->num_remote_opens); +- +- /* BB FIXME - decode close response, update inode for caching */ +- + close_exit: + SMB2_close_free(&rqst); + free_rsp_buf(resp_buftype, rsp); +@@ -3022,6 +3037,13 @@ SMB2_close(const unsigned int xid, struct cifs_tcon *tcon, + return rc; + } + ++int ++SMB2_close(const unsigned int xid, struct cifs_tcon *tcon, ++ u64 persistent_fid, u64 volatile_fid) ++{ ++ return __SMB2_close(xid, tcon, persistent_fid, volatile_fid, NULL); ++} ++ + int + smb2_validate_iov(unsigned int offset, unsigned int buffer_length, + struct kvec *iov, unsigned int min_buf_size) +diff --git a/fs/cifs/smb2pdu.h b/fs/cifs/smb2pdu.h +index f264e1d36fe1..fa2533da316d 100644 +--- a/fs/cifs/smb2pdu.h ++++ b/fs/cifs/smb2pdu.h +@@ -1570,6 +1570,17 @@ struct smb2_file_eof_info { /* encoding of request for level 10 */ + __le64 EndOfFile; /* new end of file value */ + } __packed; /* level 20 Set */ + ++struct smb2_file_network_open_info { ++ __le64 CreationTime; ++ __le64 LastAccessTime; ++ __le64 LastWriteTime; ++ __le64 ChangeTime; ++ __le64 AllocationSize; ++ __le64 EndOfFile; ++ __le32 Attributes; ++ __le32 Reserved; ++} __packed; /* level 34 Query also similar returned in close rsp and open rsp */ ++ + extern char smb2_padding[7]; + + #endif /* _SMB2PDU_H */ +diff --git a/fs/cifs/smb2proto.h b/fs/cifs/smb2proto.h +index 5caeaa99cb7c..a18272c987fe 100644 +--- a/fs/cifs/smb2proto.h ++++ b/fs/cifs/smb2proto.h +@@ -155,10 +155,13 @@ extern int SMB2_change_notify(const unsigned int xid, struct cifs_tcon *tcon, + u64 persistent_fid, u64 volatile_fid, bool watch_tree, + u32 completion_filter); + ++extern int __SMB2_close(const unsigned int xid, struct cifs_tcon *tcon, ++ u64 persistent_fid, u64 volatile_fid, ++ struct smb2_file_network_open_info *pbuf); + extern int SMB2_close(const unsigned int xid, struct cifs_tcon *tcon, + u64 persistent_file_id, u64 volatile_file_id); + extern int SMB2_close_init(struct cifs_tcon *tcon, struct smb_rqst *rqst, +- u64 persistent_file_id, u64 volatile_file_id); ++ u64 persistent_fid, u64 volatile_fid, bool query_attrs); + extern void SMB2_close_free(struct smb_rqst *rqst); + extern int SMB2_flush(const unsigned int xid, struct cifs_tcon *tcon, + u64 persistent_file_id, u64 volatile_file_id); +-- +2.25.1 + + diff --git a/patches.suse/smb3-remove-noisy-debug-message-and-minor-cleanup.patch b/patches.suse/smb3-remove-noisy-debug-message-and-minor-cleanup.patch new file mode 100644 index 0000000..56d8946 --- /dev/null +++ b/patches.suse/smb3-remove-noisy-debug-message-and-minor-cleanup.patch @@ -0,0 +1,79 @@ +From: Steve French +Date: Sat, 5 Oct 2019 10:53:58 -0500 +Subject: [PATCH] smb3: remove noisy debug message and minor cleanup +Git-commit: d0959b080b1faa9741857ef607c90531b66e2fb8 +References: bsc#1144333 +Patch-mainline: v5.4-rc3 + +Message was intended only for developer temporary build +In addition cleanup two minor warnings noticed by Coverity +and a trivial change to workaround a sparse warning + +Signed-off-by: Steve French +Reviewed-by: Pavel Shilovsky +Acked-by: Paulo Alcantara +--- + fs/cifs/cifsglob.h | 2 +- + fs/cifs/connect.c | 2 +- + fs/cifs/smb2pdu.c | 11 ++++------- + 3 files changed, 6 insertions(+), 9 deletions(-) + +diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h +index 2e960e1049db..50dfd9049370 100644 +--- a/fs/cifs/cifsglob.h ++++ b/fs/cifs/cifsglob.h +@@ -1210,7 +1210,7 @@ struct cifs_search_info { + bool smallBuf:1; /* so we know which buf_release function to call */ + }; + +-#define ACL_NO_MODE -1 ++#define ACL_NO_MODE ((umode_t)(-1)) + struct cifs_open_parms { + struct cifs_tcon *tcon; + struct cifs_sb_info *cifs_sb; +diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c +index b724227b853c..a64dfa95a925 100644 +--- a/fs/cifs/connect.c ++++ b/fs/cifs/connect.c +@@ -4445,7 +4445,7 @@ static int setup_dfs_tgt_conn(const char *path, + int rc; + struct dfs_info3_param ref = {0}; + char *mdata = NULL, *fake_devname = NULL; +- struct smb_vol fake_vol = {0}; ++ struct smb_vol fake_vol = {NULL}; + + cifs_dbg(FYI, "%s: dfs path: %s\n", __func__, path); + +diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c +index fd5f2b4b7582..05149862aea4 100644 +--- a/fs/cifs/smb2pdu.c ++++ b/fs/cifs/smb2pdu.c +@@ -751,8 +751,8 @@ add_posix_context(struct kvec *iov, unsigned int *num_iovec, umode_t mode) + unsigned int num = *num_iovec; + + iov[num].iov_base = create_posix_buf(mode); +- if (mode == -1) +- cifs_dbg(VFS, "illegal mode\n"); /* BB REMOVEME */ ++ if (mode == ACL_NO_MODE) ++ cifs_dbg(FYI, "illegal mode\n"); + if (iov[num].iov_base == NULL) + return -ENOMEM; + iov[num].iov_len = sizeof(struct create_posix); +@@ -2521,11 +2521,8 @@ SMB2_open_init(struct cifs_tcon *tcon, struct smb_rqst *rqst, __u8 *oplock, + return rc; + } + +- /* TODO: add handling for the mode on create */ +- if (oparms->disposition == FILE_CREATE) +- cifs_dbg(VFS, "mode is 0x%x\n", oparms->mode); /* BB REMOVEME */ +- +- if ((oparms->disposition == FILE_CREATE) && (oparms->mode != -1)) { ++ if ((oparms->disposition == FILE_CREATE) && ++ (oparms->mode != ACL_NO_MODE)) { + if (n_iov > 2) { + struct create_context *ccontext = + (struct create_context *)iov[n_iov-1].iov_base; +-- +2.25.1 + + diff --git a/patches.suse/smb3-remove-unused-flag-passed-into-close-functions.patch b/patches.suse/smb3-remove-unused-flag-passed-into-close-functions.patch new file mode 100644 index 0000000..92b8039 --- /dev/null +++ b/patches.suse/smb3-remove-unused-flag-passed-into-close-functions.patch @@ -0,0 +1,90 @@ +From: Steve French +Date: Mon, 2 Dec 2019 17:55:41 -0600 +Subject: [PATCH] smb3: remove unused flag passed into close functions +Git-commit: 9e8fae2597405ab1deac8909928eb8e99876f639 +References: bsc#1144333 +Patch-mainline: v5.5-rc1 + +close was relayered to allow passing in an async flag which +is no longer needed in this path. Remove the unneeded parameter +"flags" passed in on close. + +Signed-off-by: Steve French +Reviewed-by: Pavel Shilovsky +Reviewed-by: Ronnie Sahlberg +Acked-by: Paulo Alcantara +--- + fs/cifs/smb2pdu.c | 19 +++++-------------- + fs/cifs/smb2proto.h | 2 -- + 2 files changed, 5 insertions(+), 16 deletions(-) + +diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c +index be0de8a63e57..cec53eb8a6da 100644 +--- a/fs/cifs/smb2pdu.c ++++ b/fs/cifs/smb2pdu.c +@@ -2959,8 +2959,8 @@ SMB2_close_free(struct smb_rqst *rqst) + } + + int +-SMB2_close_flags(const unsigned int xid, struct cifs_tcon *tcon, +- u64 persistent_fid, u64 volatile_fid, int flags) ++SMB2_close(const unsigned int xid, struct cifs_tcon *tcon, ++ u64 persistent_fid, u64 volatile_fid) + { + struct smb_rqst rqst; + struct smb2_close_rsp *rsp = NULL; +@@ -2969,6 +2969,7 @@ SMB2_close_flags(const unsigned int xid, struct cifs_tcon *tcon, + struct kvec rsp_iov; + int resp_buftype = CIFS_NO_BUFFER; + int rc = 0; ++ int flags = 0; + + cifs_dbg(FYI, "Close\n"); + +@@ -3007,27 +3008,17 @@ SMB2_close_flags(const unsigned int xid, struct cifs_tcon *tcon, + close_exit: + SMB2_close_free(&rqst); + free_rsp_buf(resp_buftype, rsp); +- return rc; +-} +- +-int +-SMB2_close(const unsigned int xid, struct cifs_tcon *tcon, +- u64 persistent_fid, u64 volatile_fid) +-{ +- int rc; +- int tmp_rc; +- +- rc = SMB2_close_flags(xid, tcon, persistent_fid, volatile_fid, 0); + + /* retry close in a worker thread if this one is interrupted */ + if (rc == -EINTR) { ++ int tmp_rc; ++ + tmp_rc = smb2_handle_cancelled_close(tcon, persistent_fid, + volatile_fid); + if (tmp_rc) + cifs_dbg(VFS, "handle cancelled close fid 0x%llx returned error %d\n", + persistent_fid, tmp_rc); + } +- + return rc; + } + +diff --git a/fs/cifs/smb2proto.h b/fs/cifs/smb2proto.h +index d21a5fcc8d06..5caeaa99cb7c 100644 +--- a/fs/cifs/smb2proto.h ++++ b/fs/cifs/smb2proto.h +@@ -157,8 +157,6 @@ extern int SMB2_change_notify(const unsigned int xid, struct cifs_tcon *tcon, + + extern int SMB2_close(const unsigned int xid, struct cifs_tcon *tcon, + u64 persistent_file_id, u64 volatile_file_id); +-extern int SMB2_close_flags(const unsigned int xid, struct cifs_tcon *tcon, +- u64 persistent_fid, u64 volatile_fid, int flags); + extern int SMB2_close_init(struct cifs_tcon *tcon, struct smb_rqst *rqst, + u64 persistent_file_id, u64 volatile_file_id); + extern void SMB2_close_free(struct smb_rqst *rqst); +-- +2.25.1 + + diff --git a/patches.suse/staging-rtl8188eu-Add-ASUS-USB-N10-Nano-B1-to-device.patch b/patches.suse/staging-rtl8188eu-Add-ASUS-USB-N10-Nano-B1-to-device.patch new file mode 100644 index 0000000..b7bc798 --- /dev/null +++ b/patches.suse/staging-rtl8188eu-Add-ASUS-USB-N10-Nano-B1-to-device.patch @@ -0,0 +1,37 @@ +From 38ef48f7d4b7342f145a1b4f96023bde99aeb245 Mon Sep 17 00:00:00 2001 +From: Larry Finger +Date: Sat, 21 Mar 2020 13:00:11 -0500 +Subject: [PATCH] staging: rtl8188eu: Add ASUS USB-N10 Nano B1 to device table +Git-commit: 38ef48f7d4b7342f145a1b4f96023bde99aeb245 +Patch-mainline: v5.7-rc1 +References: bsc#1051510 + +The ASUS USB-N10 Nano B1 has been reported as a new RTL8188EU device. +Add it to the device tables. + +Signed-off-by: Larry Finger +Reported-by: kovi +Cc: Stable +Link: https://lore.kernel.org/r/20200321180011.26153-1-Larry.Finger@lwfinger.net +Signed-off-by: Greg Kroah-Hartman +Acked-by: Takashi Iwai + +--- + drivers/staging/rtl8188eu/os_dep/usb_intf.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/staging/rtl8188eu/os_dep/usb_intf.c b/drivers/staging/rtl8188eu/os_dep/usb_intf.c +index 845c8817281c..f7f09c0d273f 100644 +--- a/drivers/staging/rtl8188eu/os_dep/usb_intf.c ++++ b/drivers/staging/rtl8188eu/os_dep/usb_intf.c +@@ -32,6 +32,7 @@ static const struct usb_device_id rtw_usb_id_tbl[] = { + /****** 8188EUS ********/ + {USB_DEVICE(0x056e, 0x4008)}, /* Elecom WDC-150SU2M */ + {USB_DEVICE(0x07b8, 0x8179)}, /* Abocom - Abocom */ ++ {USB_DEVICE(0x0B05, 0x18F0)}, /* ASUS USB-N10 Nano B1 */ + {USB_DEVICE(0x2001, 0x330F)}, /* DLink DWA-125 REV D1 */ + {USB_DEVICE(0x2001, 0x3310)}, /* Dlink DWA-123 REV D1 */ + {USB_DEVICE(0x2001, 0x3311)}, /* DLink GO-USB-N150 REV B1 */ +-- +2.16.4 + diff --git a/patches.suse/staging-rtl8188eu-Fix-potential-overuse-of-kernel-me.patch b/patches.suse/staging-rtl8188eu-Fix-potential-overuse-of-kernel-me.patch new file mode 100644 index 0000000..2eef725 --- /dev/null +++ b/patches.suse/staging-rtl8188eu-Fix-potential-overuse-of-kernel-me.patch @@ -0,0 +1,44 @@ +From 4ddf8ab8d15ddbc52eefb44eb64e38466ce1f70f Mon Sep 17 00:00:00 2001 +From: Larry Finger +Date: Mon, 10 Feb 2020 12:02:32 -0600 +Subject: [PATCH] staging: rtl8188eu: Fix potential overuse of kernel memory +Git-commit: 4ddf8ab8d15ddbc52eefb44eb64e38466ce1f70f +Patch-mainline: v5.6-rc3 +References: bsc#1051510 + +In routine wpa_supplicant_ioctl(), the user-controlled p->length is +checked to be at least the size of struct ieee_param size, but the code +does not detect the case where p->length is greater than the size +of the struct, thus a malicious user could be wasting kernel memory. +Fixes commit a2c60d42d97c ("Add files for new driver - part 16"). + +Reported by: Pietro Oliva +Cc: Pietro Oliva +Cc: Stable +Fixes commit a2c60d42d97c ("Add files for new driver - part 16"). + +Signed-off-by: Larry Finger +Link: https://lore.kernel.org/r/20200210180235.21691-4-Larry.Finger@lwfinger.net +Signed-off-by: Greg Kroah-Hartman +Acked-by: Takashi Iwai + +--- + drivers/staging/rtl8188eu/os_dep/ioctl_linux.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/staging/rtl8188eu/os_dep/ioctl_linux.c b/drivers/staging/rtl8188eu/os_dep/ioctl_linux.c +index 7d21f5799640..acca3ae8b254 100644 +--- a/drivers/staging/rtl8188eu/os_dep/ioctl_linux.c ++++ b/drivers/staging/rtl8188eu/os_dep/ioctl_linux.c +@@ -2009,7 +2009,7 @@ static int wpa_supplicant_ioctl(struct net_device *dev, struct iw_point *p) + struct ieee_param *param; + uint ret = 0; + +- if (p->length < sizeof(struct ieee_param) || !p->pointer) { ++ if (!p->pointer || p->length != sizeof(struct ieee_param)) { + ret = -EINVAL; + goto out; + } +-- +2.16.4 + diff --git a/patches.suse/staging-rtl8188eu-Fix-potential-security-hole.patch b/patches.suse/staging-rtl8188eu-Fix-potential-security-hole.patch new file mode 100644 index 0000000..3ba78a5 --- /dev/null +++ b/patches.suse/staging-rtl8188eu-Fix-potential-security-hole.patch @@ -0,0 +1,46 @@ +From 499c405b2b80bb3a04425ba3541d20305e014d3e Mon Sep 17 00:00:00 2001 +From: Larry Finger +Date: Mon, 10 Feb 2020 12:02:30 -0600 +Subject: [PATCH] staging: rtl8188eu: Fix potential security hole +Git-commit: 499c405b2b80bb3a04425ba3541d20305e014d3e +Patch-mainline: v5.6-rc3 +References: bsc#1051510 + +In routine rtw_hostapd_ioctl(), the user-controlled p->length is assumed +to be at least the size of struct ieee_param size, but this assumption is +never checked. This could result in out-of-bounds read/write on kernel +heap in case a p->length less than the size of struct ieee_param is +specified by the user. If p->length is allowed to be greater than the size +of the struct, then a malicious user could be wasting kernel memory. +Fixes commit a2c60d42d97c ("Add files for new driver - part 16"). + +Reported by: Pietro Oliva + +Cc: Pietro Oliva +Cc: Stable +Fixes: a2c60d42d97c ("staging: r8188eu: Add files for new driver - part 16") +Signed-off-by: Larry Finger +Link: https://lore.kernel.org/r/20200210180235.21691-2-Larry.Finger@lwfinger.net +Signed-off-by: Greg Kroah-Hartman +Acked-by: Takashi Iwai + +--- + drivers/staging/rtl8188eu/os_dep/ioctl_linux.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/staging/rtl8188eu/os_dep/ioctl_linux.c b/drivers/staging/rtl8188eu/os_dep/ioctl_linux.c +index 9b6ea86d1dcf..7d21f5799640 100644 +--- a/drivers/staging/rtl8188eu/os_dep/ioctl_linux.c ++++ b/drivers/staging/rtl8188eu/os_dep/ioctl_linux.c +@@ -2796,7 +2796,7 @@ static int rtw_hostapd_ioctl(struct net_device *dev, struct iw_point *p) + goto out; + } + +- if (!p->pointer) { ++ if (!p->pointer || p->length != sizeof(struct ieee_param)) { + ret = -EINVAL; + goto out; + } +-- +2.16.4 + diff --git a/patches.suse/staging-rtl8723bs-Fix-potential-overuse-of-kernel-me.patch b/patches.suse/staging-rtl8723bs-Fix-potential-overuse-of-kernel-me.patch new file mode 100644 index 0000000..486556b --- /dev/null +++ b/patches.suse/staging-rtl8723bs-Fix-potential-overuse-of-kernel-me.patch @@ -0,0 +1,44 @@ +From 23954cb078febfc63a755301fe77e06bccdb4d2a Mon Sep 17 00:00:00 2001 +From: Larry Finger +Date: Mon, 10 Feb 2020 12:02:33 -0600 +Subject: [PATCH] staging: rtl8723bs: Fix potential overuse of kernel memory +Git-commit: 23954cb078febfc63a755301fe77e06bccdb4d2a +Patch-mainline: v5.6-rc3 +References: bsc#1051510 + +In routine wpa_supplicant_ioctl(), the user-controlled p->length is +checked to be at least the size of struct ieee_param size, but the code +does not detect the case where p->length is greater than the size +of the struct, thus a malicious user could be wasting kernel memory. +Fixes commit 554c0a3abf216 ("staging: Add rtl8723bs sdio wifi driver"). + +Reported by: Pietro Oliva + +Cc: Pietro Oliva +Cc: Stable +Fixes: 554c0a3abf216 ("staging: Add rtl8723bs sdio wifi driver"). +Signed-off-by: Larry Finger +Link: https://lore.kernel.org/r/20200210180235.21691-5-Larry.Finger@lwfinger.net +Signed-off-by: Greg Kroah-Hartman +Acked-by: Takashi Iwai + +--- + drivers/staging/rtl8723bs/os_dep/ioctl_linux.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/staging/rtl8723bs/os_dep/ioctl_linux.c b/drivers/staging/rtl8723bs/os_dep/ioctl_linux.c +index 3128766dd50e..2ac0d84f090e 100644 +--- a/drivers/staging/rtl8723bs/os_dep/ioctl_linux.c ++++ b/drivers/staging/rtl8723bs/os_dep/ioctl_linux.c +@@ -3373,7 +3373,7 @@ static int wpa_supplicant_ioctl(struct net_device *dev, struct iw_point *p) + + /* down(&ieee->wx_sem); */ + +- if (p->length < sizeof(struct ieee_param) || !p->pointer) { ++ if (!p->pointer || p->length != sizeof(struct ieee_param)) { + ret = -EINVAL; + goto out; + } +-- +2.16.4 + diff --git a/patches.suse/staging-rtl8723bs-Fix-potential-security-hole.patch b/patches.suse/staging-rtl8723bs-Fix-potential-security-hole.patch new file mode 100644 index 0000000..d18410a --- /dev/null +++ b/patches.suse/staging-rtl8723bs-Fix-potential-security-hole.patch @@ -0,0 +1,46 @@ +From ac33597c0c0d1d819dccfe001bcd0acef7107e7c Mon Sep 17 00:00:00 2001 +From: Larry Finger +Date: Mon, 10 Feb 2020 12:02:31 -0600 +Subject: [PATCH] staging: rtl8723bs: Fix potential security hole +Git-commit: ac33597c0c0d1d819dccfe001bcd0acef7107e7c +Patch-mainline: v5.6-rc3 +References: bsc#1051510 + +In routine rtw_hostapd_ioctl(), the user-controlled p->length is assumed +to be at least the size of struct ieee_param size, but this assumption is +never checked. This could result in out-of-bounds read/write on kernel +heap in case a p->length less than the size of struct ieee_param is +specified by the user. If p->length is allowed to be greater than the size +of the struct, then a malicious user could be wasting kernel memory. +Fixes commit 554c0a3abf216 ("0taging: Add rtl8723bs sdio wifi driver"). + +Reported by: Pietro Oliva +Cc: Pietro Oliva +Cc: Stable +Fixes 554c0a3abf216 ("0taging: Add rtl8723bs sdio wifi driver"). + +Signed-off-by: Larry Finger +Link: https://lore.kernel.org/r/20200210180235.21691-3-Larry.Finger@lwfinger.net +Signed-off-by: Greg Kroah-Hartman +Acked-by: Takashi Iwai + +--- + drivers/staging/rtl8723bs/os_dep/ioctl_linux.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/staging/rtl8723bs/os_dep/ioctl_linux.c b/drivers/staging/rtl8723bs/os_dep/ioctl_linux.c +index db6528a01229..3128766dd50e 100644 +--- a/drivers/staging/rtl8723bs/os_dep/ioctl_linux.c ++++ b/drivers/staging/rtl8723bs/os_dep/ioctl_linux.c +@@ -4207,7 +4207,7 @@ static int rtw_hostapd_ioctl(struct net_device *dev, struct iw_point *p) + + + /* if (p->length < sizeof(struct ieee_param) || !p->pointer) { */ +- if (!p->pointer) { ++ if (!p->pointer || p->length != sizeof(*param)) { + ret = -EINVAL; + goto out; + } +-- +2.16.4 + diff --git a/patches.suse/staging-vt6656-fix-sign-of-rx_dbm-to-bb_pre_ed_rssi.patch b/patches.suse/staging-vt6656-fix-sign-of-rx_dbm-to-bb_pre_ed_rssi.patch new file mode 100644 index 0000000..bf0af3b --- /dev/null +++ b/patches.suse/staging-vt6656-fix-sign-of-rx_dbm-to-bb_pre_ed_rssi.patch @@ -0,0 +1,36 @@ +From 93134df520f23f4e9998c425b8987edca7016817 Mon Sep 17 00:00:00 2001 +From: Malcolm Priestley +Date: Tue, 4 Feb 2020 19:34:02 +0000 +Subject: [PATCH] staging: vt6656: fix sign of rx_dbm to bb_pre_ed_rssi. +Git-commit: 93134df520f23f4e9998c425b8987edca7016817 +Patch-mainline: v5.6-rc3 +References: bsc#1051510 + +bb_pre_ed_rssi is an u8 rx_dm always returns negative signed +values add minus operator to always yield positive. + +fixes issue where rx sensitivity is always set to maximum because +the unsigned numbers were always greater then 100. + +Fixes: 63b9907f58f1 ("staging: vt6656: mac80211 conversion: create rx function.") +Cc: stable +Signed-off-by: Malcolm Priestley +Link: https://lore.kernel.org/r/aceac98c-6e69-3ce1-dfec-2bf27b980221@gmail.com +Signed-off-by: Greg Kroah-Hartman +Acked-by: Takashi Iwai + +--- + drivers/staging/vt6656/dpc.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/staging/vt6656/dpc.c ++++ b/drivers/staging/vt6656/dpc.c +@@ -140,7 +140,7 @@ int vnt_rx_data(struct vnt_private *priv + + vnt_rf_rssi_to_dbm(priv, *rssi, &rx_dbm); + +- priv->bb_pre_ed_rssi = (u8)rx_dbm + 1; ++ priv->bb_pre_ed_rssi = (u8)-rx_dbm + 1; + priv->current_rssi = priv->bb_pre_ed_rssi; + + frame = skb_data + 8; diff --git a/patches.suse/staging-wlan-ng-fix-ODEBUG-bug-in-prism2sta_disconne.patch b/patches.suse/staging-wlan-ng-fix-ODEBUG-bug-in-prism2sta_disconne.patch new file mode 100644 index 0000000..f55469e --- /dev/null +++ b/patches.suse/staging-wlan-ng-fix-ODEBUG-bug-in-prism2sta_disconne.patch @@ -0,0 +1,36 @@ +From a1f165a6b738f0c9d744bad4af7a53909278f5fc Mon Sep 17 00:00:00 2001 +From: Qiujun Huang +Date: Wed, 25 Mar 2020 15:06:46 +0800 +Subject: [PATCH] staging: wlan-ng: fix ODEBUG bug in prism2sta_disconnect_usb +Git-commit: a1f165a6b738f0c9d744bad4af7a53909278f5fc +Patch-mainline: v5.7-rc1 +References: bsc#1051510 + +We should cancel hw->usb_work before kfree(hw). + +Reported-by: syzbot+6d2e7f6fa90e27be9d62@syzkaller.appspotmail.com +Signed-off-by: Qiujun Huang +Cc: stable +Link: https://lore.kernel.org/r/1585120006-30042-1-git-send-email-hqjagain@gmail.com +Signed-off-by: Greg Kroah-Hartman +Acked-by: Takashi Iwai + +--- + drivers/staging/wlan-ng/prism2usb.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/staging/wlan-ng/prism2usb.c b/drivers/staging/wlan-ng/prism2usb.c +index 352556f6870a..4689b2170e4f 100644 +--- a/drivers/staging/wlan-ng/prism2usb.c ++++ b/drivers/staging/wlan-ng/prism2usb.c +@@ -180,6 +180,7 @@ static void prism2sta_disconnect_usb(struct usb_interface *interface) + + cancel_work_sync(&hw->link_bh); + cancel_work_sync(&hw->commsqual_bh); ++ cancel_work_sync(&hw->usb_work); + + /* Now we complete any outstanding commands + * and tell everyone who is waiting for their +-- +2.16.4 + diff --git a/patches.suse/staging-wlan-ng-fix-use-after-free-Read-in-hfa384x_u.patch b/patches.suse/staging-wlan-ng-fix-use-after-free-Read-in-hfa384x_u.patch new file mode 100644 index 0000000..019eb8e --- /dev/null +++ b/patches.suse/staging-wlan-ng-fix-use-after-free-Read-in-hfa384x_u.patch @@ -0,0 +1,40 @@ +From 1165dd73e811a07d947aee218510571f516081f6 Mon Sep 17 00:00:00 2001 +From: Qiujun Huang +Date: Thu, 26 Mar 2020 21:18:50 +0800 +Subject: [PATCH] staging: wlan-ng: fix use-after-free Read in hfa384x_usbin_callback +Git-commit: 1165dd73e811a07d947aee218510571f516081f6 +Patch-mainline: v5.7-rc1 +References: bsc#1051510 + +We can't handle the case length > WLAN_DATA_MAXLEN. +Because the size of rxfrm->data is WLAN_DATA_MAXLEN(2312), and we can't +read more than that. + +Thanks-to: Hillf Danton +Reported-and-tested-by: syzbot+7d42d68643a35f71ac8a@syzkaller.appspotmail.com +Signed-off-by: Qiujun Huang +Cc: stable +Link: https://lore.kernel.org/r/20200326131850.17711-1-hqjagain@gmail.com +Signed-off-by: Greg Kroah-Hartman +Acked-by: Takashi Iwai + +--- + drivers/staging/wlan-ng/hfa384x_usb.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/staging/wlan-ng/hfa384x_usb.c b/drivers/staging/wlan-ng/hfa384x_usb.c +index e38acb58cd5e..fa1bf8b069fd 100644 +--- a/drivers/staging/wlan-ng/hfa384x_usb.c ++++ b/drivers/staging/wlan-ng/hfa384x_usb.c +@@ -3376,6 +3376,8 @@ static void hfa384x_int_rxmonitor(struct wlandevice *wlandev, + WLAN_HDR_A4_LEN + WLAN_DATA_MAXLEN + WLAN_CRC_LEN)) { + pr_debug("overlen frm: len=%zd\n", + skblen - sizeof(struct p80211_caphdr)); ++ ++ return; + } + + skb = dev_alloc_skb(skblen); +-- +2.16.4 + diff --git a/patches.suse/tcp-clear-tp-data_segs-in-out-in-tcp_disconnect.patch b/patches.suse/tcp-clear-tp-data_segs-in-out-in-tcp_disconnect.patch new file mode 100644 index 0000000..5443938 --- /dev/null +++ b/patches.suse/tcp-clear-tp-data_segs-in-out-in-tcp_disconnect.patch @@ -0,0 +1,35 @@ +From: Eric Dumazet +Date: Fri, 31 Jan 2020 10:32:41 -0800 +Subject: tcp: clear tp->data_segs{in|out} in tcp_disconnect() +Git-commit: db7ffee6f3eb3683cdcaeddecc0a630a14546fe3 +Patch-mainline: 5.6-rc1 +References: networking-stable-20_02_05 + +tp->data_segs_in and tp->data_segs_out need to be cleared +in tcp_disconnect(). + +tcp_disconnect() is rarely used, but it is worth fixing it. + +Fixes: a44d6eacdaf5 ("tcp: Add RFC4898 tcpEStatsPerfDataSegsOut/In") +Signed-off-by: Eric Dumazet +Cc: Martin KaFai Lau +Cc: Yuchung Cheng +Cc: Neal Cardwell +Acked-by: Neal Cardwell +Signed-off-by: Jakub Kicinski +Signed-off-by: Jiri Slaby +--- + net/ipv4/tcp.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/net/ipv4/tcp.c ++++ b/net/ipv4/tcp.c +@@ -2246,6 +2246,8 @@ int tcp_disconnect(struct sock *sk, int + tcp_saved_syn_free(tp); + tp->bytes_acked = 0; + tp->bytes_received = 0; ++ tp->data_segs_in = 0; ++ tp->data_segs_out = 0; + + /* Clean up fastopen related fields */ + tcp_free_fastopen_req(tp); diff --git a/patches.suse/tcp-clear-tp-delivered-in-tcp_disconnect.patch b/patches.suse/tcp-clear-tp-delivered-in-tcp_disconnect.patch new file mode 100644 index 0000000..f1b7bdb --- /dev/null +++ b/patches.suse/tcp-clear-tp-delivered-in-tcp_disconnect.patch @@ -0,0 +1,34 @@ +From: Eric Dumazet +Date: Fri, 31 Jan 2020 10:22:47 -0800 +Subject: tcp: clear tp->delivered in tcp_disconnect() +Git-commit: 2fbdd56251b5c62f96589f39eded277260de7267 +Patch-mainline: 5.6-rc1 +References: networking-stable-20_02_05 + +tp->delivered needs to be cleared in tcp_disconnect(). + +tcp_disconnect() is rarely used, but it is worth fixing it. + +Fixes: ddf1af6fa00e ("tcp: new delivery accounting") +Signed-off-by: Eric Dumazet +Cc: Yuchung Cheng +Cc: Neal Cardwell +Acked-by: Yuchung Cheng +Acked-by: Neal Cardwell +Acked-by: Soheil Hassas Yeganeh +Signed-off-by: Jakub Kicinski +Signed-off-by: Jiri Slaby +--- + net/ipv4/tcp.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/net/ipv4/tcp.c ++++ b/net/ipv4/tcp.c +@@ -2228,6 +2228,7 @@ int tcp_disconnect(struct sock *sk, int + tp->snd_ssthresh = TCP_INFINITE_SSTHRESH; + tp->snd_cwnd_cnt = 0; + tp->window_clamp = 0; ++ tp->delivered = 0; + tcp_set_ca_state(sk, TCP_CA_Open); + tp->is_sack_reneg = 0; + tcp_clear_retrans(tp); diff --git a/patches.suse/tcp-clear-tp-segs_-in-out-in-tcp_disconnect.patch b/patches.suse/tcp-clear-tp-segs_-in-out-in-tcp_disconnect.patch new file mode 100644 index 0000000..b5f3900 --- /dev/null +++ b/patches.suse/tcp-clear-tp-segs_-in-out-in-tcp_disconnect.patch @@ -0,0 +1,34 @@ +From: Eric Dumazet +Date: Fri, 31 Jan 2020 10:44:50 -0800 +Subject: tcp: clear tp->segs_{in|out} in tcp_disconnect() +Git-commit: 784f8344de750a41344f4bbbebb8507a730fc99c +Patch-mainline: 5.6-rc1 +References: networking-stable-20_02_05 + +tp->segs_in and tp->segs_out need to be cleared in tcp_disconnect(). + +tcp_disconnect() is rarely used, but it is worth fixing it. + +Fixes: 2efd055c53c0 ("tcp: add tcpi_segs_in and tcpi_segs_out to tcp_info") +Signed-off-by: Eric Dumazet +Cc: Marcelo Ricardo Leitner +Cc: Yuchung Cheng +Cc: Neal Cardwell +Acked-by: Neal Cardwell +Signed-off-by: Jakub Kicinski +Signed-off-by: Jiri Slaby +--- + net/ipv4/tcp.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/net/ipv4/tcp.c ++++ b/net/ipv4/tcp.c +@@ -2244,6 +2244,8 @@ int tcp_disconnect(struct sock *sk, int + dst_release(sk->sk_rx_dst); + sk->sk_rx_dst = NULL; + tcp_saved_syn_free(tp); ++ tp->segs_in = 0; ++ tp->segs_out = 0; + tp->bytes_acked = 0; + tp->bytes_received = 0; + tp->data_segs_in = 0; diff --git a/patches.suse/tcp-clear-tp-total_retrans-in-tcp_disconnect.patch b/patches.suse/tcp-clear-tp-total_retrans-in-tcp_disconnect.patch new file mode 100644 index 0000000..9f66bcc --- /dev/null +++ b/patches.suse/tcp-clear-tp-total_retrans-in-tcp_disconnect.patch @@ -0,0 +1,30 @@ +From: Eric Dumazet +Date: Fri, 31 Jan 2020 09:14:47 -0800 +Subject: tcp: clear tp->total_retrans in tcp_disconnect() +Git-commit: c13c48c00a6bc1febc73902505bdec0967bd7095 +Patch-mainline: 5.6-rc1 +References: networking-stable-20_02_05 + +total_retrans needs to be cleared in tcp_disconnect(). + +tcp_disconnect() is rarely used, but it is worth fixing it. + +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Signed-off-by: Eric Dumazet +Cc: SeongJae Park +Signed-off-by: Jakub Kicinski +Signed-off-by: Jiri Slaby +--- + net/ipv4/tcp.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/net/ipv4/tcp.c ++++ b/net/ipv4/tcp.c +@@ -2231,6 +2231,7 @@ int tcp_disconnect(struct sock *sk, int + tcp_set_ca_state(sk, TCP_CA_Open); + tp->is_sack_reneg = 0; + tcp_clear_retrans(tp); ++ tp->total_retrans = 0; + inet_csk_delack_init(sk); + /* Initialize rcv_mss to TCP_MIN_MSS to avoid division by 0 + * issue in __tcp_select_window() diff --git a/patches.suse/tcp-fix-marked-lost-packets-not-being-retransmitted.patch b/patches.suse/tcp-fix-marked-lost-packets-not-being-retransmitted.patch new file mode 100644 index 0000000..eabe34e --- /dev/null +++ b/patches.suse/tcp-fix-marked-lost-packets-not-being-retransmitted.patch @@ -0,0 +1,81 @@ +From: Pengcheng Yang +Date: Tue, 14 Jan 2020 17:23:40 +0800 +Subject: tcp: fix marked lost packets not being retransmitted +Git-commit: e176b1ba476cf36f723cfcc7a9e57f3cb47dec70 +Patch-mainline: 5.5-rc7 +References: networking-stable-20_01_20 + +When the packet pointed to by retransmit_skb_hint is unlinked by ACK, +retransmit_skb_hint will be set to NULL in tcp_clean_rtx_queue(). +If packet loss is detected at this time, retransmit_skb_hint will be set +to point to the current packet loss in tcp_verify_retransmit_hint(), +then the packets that were previously marked lost but not retransmitted +due to the restriction of cwnd will be skipped and cannot be +retransmitted. + +To fix this, when retransmit_skb_hint is NULL, retransmit_skb_hint can +be reset only after all marked lost packets are retransmitted +(retrans_out >= lost_out), otherwise we need to traverse from +tcp_rtx_queue_head in tcp_xmit_retransmit_queue(). + +Packetdrill to demonstrate: + +// Disable RACK and set max_reordering to keep things simple + 0 `sysctl -q net.ipv4.tcp_recovery=0` + +0 `sysctl -q net.ipv4.tcp_max_reordering=3` + +// Establish a connection + +0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3 + +0 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0 + +0 bind(3, ..., ...) = 0 + +0 listen(3, 1) = 0 + + +.1 < S 0:0(0) win 32792 + +0 > S. 0:0(0) ack 1 <...> + +.01 < . 1:1(0) ack 1 win 257 + +0 accept(3, ..., ...) = 4 + +// Send 8 data segments + +0 write(4, ..., 8000) = 8000 + +0 > P. 1:8001(8000) ack 1 + +// Enter recovery and 1:3001 is marked lost + +.01 < . 1:1(0) ack 1 win 257 + +0 < . 1:1(0) ack 1 win 257 + +0 < . 1:1(0) ack 1 win 257 + +// Retransmit 1:1001, now retransmit_skb_hint points to 1001:2001 + +0 > . 1:1001(1000) ack 1 + +// 1001:2001 was ACKed causing retransmit_skb_hint to be set to NULL + +.01 < . 1:1(0) ack 2001 win 257 +// Now retransmit_skb_hint points to 4001:5001 which is now marked lost + +// BUG: 2001:3001 was not retransmitted + +0 > . 2001:3001(1000) ack 1 + +Signed-off-by: Pengcheng Yang +Acked-by: Neal Cardwell +Tested-by: Neal Cardwell +Signed-off-by: David S. Miller +Signed-off-by: Jiri Slaby +--- + net/ipv4/tcp_input.c | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +--- a/net/ipv4/tcp_input.c ++++ b/net/ipv4/tcp_input.c +@@ -929,9 +929,10 @@ static void tcp_update_reordering(struct + /* This must be called before lost_out is incremented */ + static void tcp_verify_retransmit_hint(struct tcp_sock *tp, struct sk_buff *skb) + { +- if (!tp->retransmit_skb_hint || +- before(TCP_SKB_CB(skb)->seq, +- TCP_SKB_CB(tp->retransmit_skb_hint)->seq)) ++ if ((!tp->retransmit_skb_hint && tp->retrans_out >= tp->lost_out) || ++ (tp->retransmit_skb_hint && ++ before(TCP_SKB_CB(skb)->seq, ++ TCP_SKB_CB(tp->retransmit_skb_hint)->seq))) + tp->retransmit_skb_hint = skb; + } + diff --git a/patches.suse/tcp-fix-old-stuff-D-SACK-causing-SACK-to-be-treated-.patch b/patches.suse/tcp-fix-old-stuff-D-SACK-causing-SACK-to-be-treated-.patch new file mode 100644 index 0000000..3ae80d0 --- /dev/null +++ b/patches.suse/tcp-fix-old-stuff-D-SACK-causing-SACK-to-be-treated-.patch @@ -0,0 +1,44 @@ +From: Pengcheng Yang +Date: Mon, 30 Dec 2019 17:54:41 +0800 +Subject: tcp: fix "old stuff" D-SACK causing SACK to be treated as D-SACK +Git-commit: c9655008e7845bcfdaac10a1ed8554ec167aea88 +Patch-mainline: 5.5-rc6 +References: networking-stable-20_01_11 + +When we receive a D-SACK, where the sequence number satisfies: + undo_marker <= start_seq < end_seq <= prior_snd_una +we consider this is a valid D-SACK and tcp_is_sackblock_valid() +returns true, then this D-SACK is discarded as "old stuff", +but the variable first_sack_index is not marked as negative +in tcp_sacktag_write_queue(). + +If this D-SACK also carries a SACK that needs to be processed +(for example, the previous SACK segment was lost), this SACK +will be treated as a D-SACK in the following processing of +tcp_sacktag_write_queue(), which will eventually lead to +incorrect updates of undo_retrans and reordering. + +Fixes: fd6dad616d4f ("[TCP]: Earlier SACK block verification & simplify access to them") +Signed-off-by: Pengcheng Yang +Signed-off-by: Eric Dumazet +Signed-off-by: David S. Miller +Signed-off-by: Jiri Slaby +--- + net/ipv4/tcp_input.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +--- a/net/ipv4/tcp_input.c ++++ b/net/ipv4/tcp_input.c +@@ -1748,8 +1748,11 @@ tcp_sacktag_write_queue(struct sock *sk, + } + + /* Ignore very old stuff early */ +- if (!after(sp[used_sacks].end_seq, prior_snd_una)) ++ if (!after(sp[used_sacks].end_seq, prior_snd_una)) { ++ if (i == 0) ++ first_sack_index = -1; + continue; ++ } + + used_sacks++; + } diff --git a/patches.suse/tcp_bbr-improve-arithmetic-division-in-bbr_update_bw.patch b/patches.suse/tcp_bbr-improve-arithmetic-division-in-bbr_update_bw.patch new file mode 100644 index 0000000..16d70a6 --- /dev/null +++ b/patches.suse/tcp_bbr-improve-arithmetic-division-in-bbr_update_bw.patch @@ -0,0 +1,37 @@ +From: Wen Yang +Date: Mon, 20 Jan 2020 18:04:56 +0800 +Subject: tcp_bbr: improve arithmetic division in bbr_update_bw() +Git-commit: 5b2f1f3070b6447b76174ea8bfb7390dc6253ebd +Patch-mainline: 5.5 +References: networking-stable-20_01_27 + +do_div() does a 64-by-32 division. Use div64_long() instead of it +if the divisor is long, to avoid truncation to 32-bit. +And as a nice side effect also cleans up the function a bit. + +Signed-off-by: Wen Yang +Cc: Eric Dumazet +Cc: "David S. Miller" +Cc: Alexey Kuznetsov +Cc: Hideaki YOSHIFUJI +Cc: netdev@vger.kernel.org +Cc: linux-kernel@vger.kernel.org +Signed-off-by: Eric Dumazet +Signed-off-by: David S. Miller +Signed-off-by: Jiri Slaby +--- + net/ipv4/tcp_bbr.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +--- a/net/ipv4/tcp_bbr.c ++++ b/net/ipv4/tcp_bbr.c +@@ -678,8 +678,7 @@ static void bbr_update_bw(struct sock *s + * bandwidth sample. Delivered is in packets and interval_us in uS and + * ratio will be <<1 for most connections. So delivered is first scaled. + */ +- bw = (u64)rs->delivered * BW_UNIT; +- do_div(bw, rs->interval_us); ++ bw = div64_long((u64)rs->delivered * BW_UNIT, rs->interval_us); + + /* If this sample is application-limited, it is likely to have a very + * low delivered count that represents application behavior rather than diff --git a/patches.suse/thermal-devfreq_cooling-inline-all-stubs-for-CONFIG_.patch b/patches.suse/thermal-devfreq_cooling-inline-all-stubs-for-CONFIG_.patch new file mode 100644 index 0000000..8d5fce4 --- /dev/null +++ b/patches.suse/thermal-devfreq_cooling-inline-all-stubs-for-CONFIG_.patch @@ -0,0 +1,52 @@ +From 3f5b9959041e0db6dacbea80bb833bff5900999f Mon Sep 17 00:00:00 2001 +From: Martin Blumenstingl +Date: Fri, 3 Apr 2020 22:51:33 +0200 +Subject: [PATCH] thermal: devfreq_cooling: inline all stubs for CONFIG_DEVFREQ_THERMAL=n +Git-commit: 3f5b9959041e0db6dacbea80bb833bff5900999f +Patch-mainline: v5.7-rc1 +References: bsc#1051510 + +When CONFIG_DEVFREQ_THERMAL is disabled all functions except +of_devfreq_cooling_register_power() were already inlined. Also inline +the last function to avoid compile errors when multiple drivers call +of_devfreq_cooling_register_power() when CONFIG_DEVFREQ_THERMAL is not +set. Compilation failed with the following message: + multiple definition of `of_devfreq_cooling_register_power' +(which then lists all usages of of_devfreq_cooling_register_power()) + +Thomas Zimmermann reported this problem [0] on a kernel config with +CONFIG_DRM_LIMA={m,y}, CONFIG_DRM_PANFROST={m,y} and +CONFIG_DEVFREQ_THERMAL=n after both, the lima and panfrost drivers +gained devfreq cooling support. + +[0] https://www.spinics.net/lists/dri-devel/msg252825.html + +Fixes: a76caf55e5b356 ("thermal: Add devfreq cooling") +Cc: stable@vger.kernel.org +Reported-by: Thomas Zimmermann +Signed-off-by: Martin Blumenstingl +Tested-by: Thomas Zimmermann +Signed-off-by: Daniel Lezcano +Link: https://lore.kernel.org/r/20200403205133.1101808-1-martin.blumenstingl@googlemail.com +Acked-by: Takashi Iwai + +--- + include/linux/devfreq_cooling.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/include/linux/devfreq_cooling.h b/include/linux/devfreq_cooling.h +index 4635f95000a4..79a6e37a1d6f 100644 +--- a/include/linux/devfreq_cooling.h ++++ b/include/linux/devfreq_cooling.h +@@ -75,7 +75,7 @@ void devfreq_cooling_unregister(struct thermal_cooling_device *dfc); + + #else /* !CONFIG_DEVFREQ_THERMAL */ + +-struct thermal_cooling_device * ++static inline struct thermal_cooling_device * + of_devfreq_cooling_register_power(struct device_node *np, struct devfreq *df, + struct devfreq_cooling_power *dfc_power) + { +-- +2.16.4 + diff --git a/patches.suse/tick-broadcast-hrtimer-fix-a-race-in-bc_set_next.patch b/patches.suse/tick-broadcast-hrtimer-fix-a-race-in-bc_set_next.patch new file mode 100644 index 0000000..7bb079a --- /dev/null +++ b/patches.suse/tick-broadcast-hrtimer-fix-a-race-in-bc_set_next.patch @@ -0,0 +1,166 @@ +From: Balasubramani Vivekanandan +Subject: tick: broadcast-hrtimer: Fix a race in bc_set_next +Git-commit: b9023b91dd020ad7e093baa5122b6968c48cc9e0 +Patch-mainline: v5.4 +References: bsc#1164551 +Acked-by: Jiri Bohac + +When a cpu requests broadcasting, before starting the tick broadcast +hrtimer, bc_set_next() checks if the timer callback (bc_handler) is active +using hrtimer_try_to_cancel(). But hrtimer_try_to_cancel() does not provide +the required synchronization when the callback is active on other core. + +The callback could have already executed tick_handle_oneshot_broadcast() +and could have also returned. But still there is a small time window where +the hrtimer_try_to_cancel() returns -1. In that case bc_set_next() returns +without doing anything, but the next_event of the tick broadcast clock +device is already set to a timeout value. + +In the race condition diagram below, CPU #1 is running the timer callback +and CPU #2 is entering idle state and so calls bc_set_next(). + +In the worst case, the next_event will contain an expiry time, but the +hrtimer will not be started which happens when the racing callback returns +HRTIMER_NORESTART. The hrtimer might never recover if all further requests +from the CPUs to subscribe to tick broadcast have timeout greater than the +next_event of tick broadcast clock device. This leads to cascading of +failures and finally noticed as rcu stall warnings + +Here is a depiction of the race condition + +CPU #1 (Running timer callback) CPU #2 (Enter idle + and subscribe to + tick broadcast) +--------------------- --------------------- + +__run_hrtimer() tick_broadcast_enter() + + bc_handler() __tick_broadcast_oneshot_control() + + tick_handle_oneshot_broadcast() + + raw_spin_lock(&tick_broadcast_lock); + + dev->next_event = KTIME_MAX; //wait for tick_broadcast_lock + //next_event for tick broadcast clock + set to KTIME_MAX since no other cores + subscribed to tick broadcasting + + raw_spin_unlock(&tick_broadcast_lock); + + if (dev->next_event == KTIME_MAX) + return HRTIMER_NORESTART + // callback function exits without + restarting the hrtimer //tick_broadcast_lock acquired + raw_spin_lock(&tick_broadcast_lock); + + tick_broadcast_set_event() + + clockevents_program_event() + + dev->next_event = expires; + + bc_set_next() + + hrtimer_try_to_cancel() + //returns -1 since the timer + callback is active. Exits without + restarting the timer + cpu_base->running = NULL; + +The comment that hrtimer cannot be armed from within the callback is +wrong. It is fine to start the hrtimer from within the callback. Also it is +safe to start the hrtimer from the enter/exit idle code while the broadcast +handler is active. The enter/exit idle code and the broadcast handler are +synchronized using tick_broadcast_lock. So there is no need for the +existing try to cancel logic. All this can be removed which will eliminate +the race condition as well. + +Fixes: 5d1638acb9f6 ("tick: Introduce hrtimer based broadcast") +Originally-by: Thomas Gleixner +Signed-off-by: Balasubramani Vivekanandan +Signed-off-by: Thomas Gleixner +Cc: stable@vger.kernel.org +Link: https://lkml.kernel.org/r/20190926135101.12102-2-balasubramani_vivekanandan@mentor.com + +--- + kernel/time/tick-broadcast-hrtimer.c | 57 +++++++++++++++++------------------ + 1 file changed, 29 insertions(+), 28 deletions(-) + +--- a/kernel/time/tick-broadcast-hrtimer.c ++++ b/kernel/time/tick-broadcast-hrtimer.c +@@ -43,34 +43,39 @@ static int bc_shutdown(struct clock_even + */ + static int bc_set_next(ktime_t expires, struct clock_event_device *bc) + { +- int bc_moved; + /* +- * We try to cancel the timer first. If the callback is on +- * flight on some other cpu then we let it handle it. If we +- * were able to cancel the timer nothing can rearm it as we +- * own broadcast_lock. ++ * This is called either from enter/exit idle code or from the ++ * broadcast handler. In all cases tick_broadcast_lock is held. + * +- * However we can also be called from the event handler of +- * ce_broadcast_hrtimer itself when it expires. We cannot +- * restart the timer because we are in the callback, but we +- * can set the expiry time and let the callback return +- * HRTIMER_RESTART. ++ * hrtimer_cancel() cannot be called here neither from the ++ * broadcast handler nor from the enter/exit idle code. The idle ++ * code can run into the problem described in bc_shutdown() and the ++ * broadcast handler cannot wait for itself to complete for obvious ++ * reasons. + * +- * Since we are in the idle loop at this point and because +- * hrtimer_{start/cancel} functions call into tracing, +- * calls to these functions must be bound within RCU_NONIDLE. ++ * Each caller tries to arm the hrtimer on its own CPU, but if the ++ * hrtimer callbback function is currently running, then ++ * hrtimer_start() cannot move it and the timer stays on the CPU on ++ * which it is assigned at the moment. ++ * ++ * As this can be called from idle code, the hrtimer_start() ++ * invocation has to be wrapped with RCU_NONIDLE() as ++ * hrtimer_start() can call into tracing. + */ +- RCU_NONIDLE({ +- bc_moved = hrtimer_try_to_cancel(&bctimer) >= 0; +- if (bc_moved) +- hrtimer_start(&bctimer, expires, +- HRTIMER_MODE_ABS_PINNED);}); +- if (bc_moved) { +- /* Bind the "device" to the cpu */ +- bc->bound_on = smp_processor_id(); +- } else if (bc->bound_on == smp_processor_id()) { +- hrtimer_set_expires(&bctimer, expires); +- } ++ RCU_NONIDLE( { ++ hrtimer_start(&bctimer, expires, HRTIMER_MODE_ABS_PINNED); ++ /* ++ * The core tick broadcast mode expects bc->bound_on to be set ++ * correctly to prevent a CPU which has the broadcast hrtimer ++ * armed from going deep idle. ++ * ++ * As tick_broadcast_lock is held, nothing can change the cpu ++ * base which was just established in hrtimer_start() above. So ++ * the below access is safe even without holding the hrtimer ++ * base lock. ++ */ ++ bc->bound_on = bctimer.base->cpu_base->cpu; ++ } ); + return 0; + } + +@@ -96,10 +101,6 @@ static enum hrtimer_restart bc_handler(s + { + ce_broadcast_hrtimer.event_handler(&ce_broadcast_hrtimer); + +- if (clockevent_state_oneshot(&ce_broadcast_hrtimer)) +- if (ce_broadcast_hrtimer.next_event != KTIME_MAX) +- return HRTIMER_RESTART; +- + return HRTIMER_NORESTART; + } + diff --git a/patches.suse/tpm-ibmvtpm-Wait-for-buffer-to-be-set-before-proceed.patch b/patches.suse/tpm-ibmvtpm-Wait-for-buffer-to-be-set-before-proceed.patch new file mode 100644 index 0000000..429b529 --- /dev/null +++ b/patches.suse/tpm-ibmvtpm-Wait-for-buffer-to-be-set-before-proceed.patch @@ -0,0 +1,79 @@ +From d8d74ea3c00214aee1e1826ca18e77944812b9b4 Mon Sep 17 00:00:00 2001 +From: Stefan Berger +Date: Thu, 12 Mar 2020 11:53:31 -0400 +Subject: [PATCH] tpm: ibmvtpm: Wait for buffer to be set before proceeding + +References: bsc#1065729 +Patch-mainline: v5.7-rc1 +Git-commit: d8d74ea3c00214aee1e1826ca18e77944812b9b4 + +Synchronize with the results from the CRQs before continuing with +the initialization. This avoids trying to send TPM commands while +the rtce buffer has not been allocated, yet. + +This patch fixes an existing race condition that may occurr if the +hypervisor does not quickly respond to the VTPM_GET_RTCE_BUFFER_SIZE +request sent during initialization and therefore the ibmvtpm->rtce_buf +has not been allocated at the time the first TPM command is sent. + +Fixes: 132f76294744 ("drivers/char/tpm: Add new device driver to support IBM vTPM") +Signed-off-by: Stefan Berger +Acked-by: Nayna Jain +Tested-by: Nayna Jain +Reviewed-by: Jarkko Sakkinen +Signed-off-by: Jarkko Sakkinen +Acked-by: Michal Suchanek +--- + drivers/char/tpm/tpm_ibmvtpm.c | 9 +++++++++ + drivers/char/tpm/tpm_ibmvtpm.h | 1 + + 2 files changed, 10 insertions(+) + +diff --git a/drivers/char/tpm/tpm_ibmvtpm.c b/drivers/char/tpm/tpm_ibmvtpm.c +index 78cc52690177..cfe40e7b1ba4 100644 +--- a/drivers/char/tpm/tpm_ibmvtpm.c ++++ b/drivers/char/tpm/tpm_ibmvtpm.c +@@ -571,6 +571,7 @@ static irqreturn_t ibmvtpm_interrupt(int irq, void *vtpm_instance) + */ + while ((crq = ibmvtpm_crq_get_next(ibmvtpm)) != NULL) { + ibmvtpm_crq_process(crq, ibmvtpm); ++ wake_up_interruptible(&ibmvtpm->crq_queue.wq); + crq->valid = 0; + smp_wmb(); + } +@@ -618,6 +619,7 @@ static int tpm_ibmvtpm_probe(struct vio_dev *vio_dev, + } + + crq_q->num_entry = CRQ_RES_BUF_SIZE / sizeof(*crq_q->crq_addr); ++ init_waitqueue_head(&crq_q->wq); + ibmvtpm->crq_dma_handle = dma_map_single(dev, crq_q->crq_addr, + CRQ_RES_BUF_SIZE, + DMA_BIDIRECTIONAL); +@@ -670,6 +672,13 @@ static int tpm_ibmvtpm_probe(struct vio_dev *vio_dev, + if (rc) + goto init_irq_cleanup; + ++ if (!wait_event_timeout(ibmvtpm->crq_queue.wq, ++ ibmvtpm->rtce_buf != NULL, ++ HZ)) { ++ dev_err(dev, "CRQ response timed out\n"); ++ goto init_irq_cleanup; ++ } ++ + return tpm_chip_register(chip); + init_irq_cleanup: + do { +diff --git a/drivers/char/tpm/tpm_ibmvtpm.h b/drivers/char/tpm/tpm_ibmvtpm.h +index 7983f1a33267..b92aa7d3e93e 100644 +--- a/drivers/char/tpm/tpm_ibmvtpm.h ++++ b/drivers/char/tpm/tpm_ibmvtpm.h +@@ -26,6 +26,7 @@ struct ibmvtpm_crq_queue { + struct ibmvtpm_crq *crq_addr; + u32 index; + u32 num_entry; ++ wait_queue_head_t wq; + }; + + struct ibmvtpm_dev { +-- +2.23.0 + diff --git a/patches.suse/tracing-blktrace-Fix-to-allow-setting-same-value.patch b/patches.suse/tracing-blktrace-Fix-to-allow-setting-same-value.patch index 7a2462c..2c6f171 100644 --- a/patches.suse/tracing-blktrace-Fix-to-allow-setting-same-value.patch +++ b/patches.suse/tracing-blktrace-Fix-to-allow-setting-same-value.patch @@ -49,7 +49,7 @@ diff --git a/kernel/trace/blktrace.c b/kernel/trace/blktrace.c index b951aa1fac61..96457ad8d720 100644 --- a/kernel/trace/blktrace.c +++ b/kernel/trace/blktrace.c -@@ -1841,6 +1841,10 @@ static ssize_t sysfs_blk_trace_attr_store(struct device *dev, +@@ -1730,6 +1730,10 @@ static ssize_t sysfs_blk_trace_attr_stor mutex_lock(&q->blk_trace_mutex); if (attr == &dev_attr_enable) { diff --git a/patches.suse/tty-evh_bytechan-Fix-out-of-bounds-accesses.patch b/patches.suse/tty-evh_bytechan-Fix-out-of-bounds-accesses.patch new file mode 100644 index 0000000..a23ddad --- /dev/null +++ b/patches.suse/tty-evh_bytechan-Fix-out-of-bounds-accesses.patch @@ -0,0 +1,115 @@ +From 3670664b5da555a2a481449b3baafff113b0ac35 Mon Sep 17 00:00:00 2001 +From: Stephen Rothwell +Date: Thu, 9 Jan 2020 18:39:12 +1100 +Subject: [PATCH] tty: evh_bytechan: Fix out of bounds accesses +Mime-version: 1.0 +Content-type: text/plain; charset=UTF-8 +Content-transfer-encoding: 8bit +Git-commit: 3670664b5da555a2a481449b3baafff113b0ac35 +Patch-mainline: v5.7-rc1 +References: bsc#1051510 + +ev_byte_channel_send() assumes that its third argument is a 16 byte +array. Some places where it is called it may not be (or we can't +easily tell if it is). Newer compilers have started producing warnings +about this, so make sure we actually pass a 16 byte array. + +There may be more elegant solutions to this, but the driver is quite +old and hasn't been updated in many years. + +The warnings (from a powerpc allyesconfig build) are: + + In file included from include/linux/byteorder/big_endian.h:5, + from arch/powerpc/include/uapi/asm/byteorder.h:14, + from include/asm-generic/bitops/le.h:6, + from arch/powerpc/include/asm/bitops.h:250, + from include/linux/bitops.h:29, + from include/linux/kernel.h:12, + from include/asm-generic/bug.h:19, + from arch/powerpc/include/asm/bug.h:109, + from include/linux/bug.h:5, + from include/linux/mmdebug.h:5, + from include/linux/gfp.h:5, + from include/linux/slab.h:15, + from drivers/tty/ehv_bytechan.c:24: + drivers/tty/ehv_bytechan.c: In function ‘ehv_bc_udbg_putc’: + arch/powerpc/include/asm/epapr_hcalls.h:298:20: warning: array subscript 1 is outside array bounds of ‘const char[1]’ [-Warray-bounds] + 298 | r6 = be32_to_cpu(p[1]); + include/uapi/linux/byteorder/big_endian.h:40:51: note: in definition of macro ‘__be32_to_cpu’ + 40 | #define __be32_to_cpu(x) ((__force __u32)(__be32)(x)) + | ^ + arch/powerpc/include/asm/epapr_hcalls.h:298:7: note: in expansion of macro ‘be32_to_cpu’ + 298 | r6 = be32_to_cpu(p[1]); + | ^~~~~~~~~~~ + drivers/tty/ehv_bytechan.c:166:13: note: while referencing ‘data’ + 166 | static void ehv_bc_udbg_putc(char c) + | ^~~~~~~~~~~~~~~~ + +Fixes: dcd83aaff1c8 ("tty/powerpc: introduce the ePAPR embedded hypervisor byte channel driver") +Signed-off-by: Stephen Rothwell +Tested-by: Laurentiu Tudor +[mpe: Trim warnings from change log] +Signed-off-by: Michael Ellerman +Link: https://lore.kernel.org/r/20200109183912.5fcb52aa@canb.auug.org.au +Acked-by: Takashi Iwai + +--- + drivers/tty/ehv_bytechan.c | 21 ++++++++++++++++++--- + 1 file changed, 18 insertions(+), 3 deletions(-) + +diff --git a/drivers/tty/ehv_bytechan.c b/drivers/tty/ehv_bytechan.c +index 769e0a5d1dfc..3c6dd06ec5fb 100644 +--- a/drivers/tty/ehv_bytechan.c ++++ b/drivers/tty/ehv_bytechan.c +@@ -136,6 +136,21 @@ static int find_console_handle(void) + return 1; + } + ++static unsigned int local_ev_byte_channel_send(unsigned int handle, ++ unsigned int *count, ++ const char *p) ++{ ++ char buffer[EV_BYTE_CHANNEL_MAX_BYTES]; ++ unsigned int c = *count; ++ ++ if (c < sizeof(buffer)) { ++ memcpy(buffer, p, c); ++ memset(&buffer[c], 0, sizeof(buffer) - c); ++ p = buffer; ++ } ++ return ev_byte_channel_send(handle, count, p); ++} ++ + /*************************** EARLY CONSOLE DRIVER ***************************/ + + #ifdef CONFIG_PPC_EARLY_DEBUG_EHV_BC +@@ -154,7 +169,7 @@ static void byte_channel_spin_send(const char data) + + do { + count = 1; +- ret = ev_byte_channel_send(CONFIG_PPC_EARLY_DEBUG_EHV_BC_HANDLE, ++ ret = local_ev_byte_channel_send(CONFIG_PPC_EARLY_DEBUG_EHV_BC_HANDLE, + &count, &data); + } while (ret == EV_EAGAIN); + } +@@ -221,7 +236,7 @@ static int ehv_bc_console_byte_channel_send(unsigned int handle, const char *s, + while (count) { + len = min_t(unsigned int, count, EV_BYTE_CHANNEL_MAX_BYTES); + do { +- ret = ev_byte_channel_send(handle, &len, s); ++ ret = local_ev_byte_channel_send(handle, &len, s); + } while (ret == EV_EAGAIN); + count -= len; + s += len; +@@ -401,7 +416,7 @@ static void ehv_bc_tx_dequeue(struct ehv_bc_data *bc) + CIRC_CNT_TO_END(bc->head, bc->tail, BUF_SIZE), + EV_BYTE_CHANNEL_MAX_BYTES); + +- ret = ev_byte_channel_send(bc->handle, &len, bc->buf + bc->tail); ++ ret = local_ev_byte_channel_send(bc->handle, &len, bc->buf + bc->tail); + + /* 'len' is valid only if the return code is 0 or EV_EAGAIN */ + if (!ret || (ret == EV_EAGAIN)) +-- +2.16.4 + diff --git a/patches.suse/tty-serial-atmel-manage-shutdown-in-case-of-RS485-or.patch b/patches.suse/tty-serial-atmel-manage-shutdown-in-case-of-RS485-or.patch new file mode 100644 index 0000000..f3253c8 --- /dev/null +++ b/patches.suse/tty-serial-atmel-manage-shutdown-in-case-of-RS485-or.patch @@ -0,0 +1,41 @@ +From 04b5bfe3dc94e64d0590c54045815cb5183fb095 Mon Sep 17 00:00:00 2001 +From: Nicolas Ferre +Date: Mon, 10 Feb 2020 16:20:53 +0100 +Subject: [PATCH] tty/serial: atmel: manage shutdown in case of RS485 or ISO7816 mode +Git-commit: 04b5bfe3dc94e64d0590c54045815cb5183fb095 +Patch-mainline: v5.6-rc3 +References: bsc#1051510 + +In atmel_shutdown() we call atmel_stop_rx() and atmel_stop_tx() functions. +Prevent the rx restart that is implemented in RS485 or ISO7816 modes when +calling atmel_stop_tx() by using the atomic information tasklet_shutdown +that is already in place for this purpose. + +Fixes: 98f2082c3ac4 ("tty/serial: atmel: enforce tasklet init and termination sequences") +Signed-off-by: Nicolas Ferre +Cc: stable +Link: https://lore.kernel.org/r/20200210152053.8289-1-nicolas.ferre@microchip.com +Signed-off-by: Greg Kroah-Hartman +Acked-by: Takashi Iwai + +--- + drivers/tty/serial/atmel_serial.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c +index c15c398c88a9..a39c87a7c2e1 100644 +--- a/drivers/tty/serial/atmel_serial.c ++++ b/drivers/tty/serial/atmel_serial.c +@@ -570,7 +570,8 @@ static void atmel_stop_tx(struct uart_port *port) + atmel_uart_writel(port, ATMEL_US_IDR, atmel_port->tx_done_mask); + + if (atmel_uart_is_half_duplex(port)) +- atmel_start_rx(port); ++ if (!atomic_read(&atmel_port->tasklet_shutdown)) ++ atmel_start_rx(port); + + } + +-- +2.16.4 + diff --git a/patches.suse/tty-serial-imx-setup-the-correct-sg-entry-for-tx-dma.patch b/patches.suse/tty-serial-imx-setup-the-correct-sg-entry-for-tx-dma.patch new file mode 100644 index 0000000..667994d --- /dev/null +++ b/patches.suse/tty-serial-imx-setup-the-correct-sg-entry-for-tx-dma.patch @@ -0,0 +1,115 @@ +From f76707831829530ffdd3888bebc108aecefccaa0 Mon Sep 17 00:00:00 2001 +From: Fugang Duan +Date: Tue, 11 Feb 2020 14:16:01 +0800 +Subject: [PATCH] tty: serial: imx: setup the correct sg entry for tx dma +Mime-version: 1.0 +Content-type: text/plain; charset=UTF-8 +Content-transfer-encoding: 8bit +Git-commit: f76707831829530ffdd3888bebc108aecefccaa0 +Patch-mainline: v5.6-rc3 +References: bsc#1051510 + +There has oops as below happen on i.MX8MP EVK platform that has +6G bytes DDR memory. + +when (xmit->tail < xmit->head) && (xmit->head == 0), +it setups one sg entry with sg->length is zero: + sg_set_buf(sgl + 1, xmit->buf, xmit->head); + +if xmit->buf is allocated from >4G address space, and SDMA only +support <4G address space, then dma_map_sg() will call swiotlb_map() +to do bounce buffer copying and mapping. + +But swiotlb_map() don't allow sg entry's length is zero, otherwise +report BUG_ON(). + +So the patch is to correct the tx DMA scatter list. + +Oops: +[ 287.675715] kernel BUG at kernel/dma/swiotlb.c:497! +[ 287.680592] Internal error: Oops - BUG: 0 [#1] PREEMPT SMP +[ 287.686075] Modules linked in: +[ 287.689133] CPU: 0 PID: 0 Comm: swapper/0 Not tainted 5.4.3-00016-g3fdc4e0-dirty #10 +[ 287.696872] Hardware name: FSL i.MX8MP EVK (DT) +[ 287.701402] pstate: 80000085 (Nzcv daIf -PAN -UAO) +[ 287.706199] pc : swiotlb_tbl_map_single+0x1fc/0x310 +[ 287.711076] lr : swiotlb_map+0x60/0x148 +[ 287.714909] sp : ffff800010003c00 +[ 287.718221] x29: ffff800010003c00 x28: 0000000000000000 +[ 287.723533] x27: 0000000000000040 x26: ffff800011ae0000 +[ 287.728844] x25: ffff800011ae09f8 x24: 0000000000000000 +[ 287.734155] x23: 00000001b7af9000 x22: 0000000000000000 +[ 287.739465] x21: ffff000176409c10 x20: 00000000001f7ffe +[ 287.744776] x19: ffff000176409c10 x18: 000000000000002e +[ 287.750087] x17: 0000000000000000 x16: 0000000000000000 +[ 287.755397] x15: 0000000000000000 x14: 0000000000000000 +[ 287.760707] x13: ffff00017f334000 x12: 0000000000000001 +[ 287.766018] x11: 00000000001fffff x10: 0000000000000000 +[ 287.771328] x9 : 0000000000000003 x8 : 0000000000000000 +[ 287.776638] x7 : 0000000000000000 x6 : 0000000000000000 +[ 287.781949] x5 : 0000000000200000 x4 : 0000000000000000 +[ 287.787259] x3 : 0000000000000001 x2 : 00000001b7af9000 +[ 287.792570] x1 : 00000000fbfff000 x0 : 0000000000000000 +[ 287.797881] Call trace: +[ 287.800328] swiotlb_tbl_map_single+0x1fc/0x310 +[ 287.804859] swiotlb_map+0x60/0x148 +[ 287.808347] dma_direct_map_page+0xf0/0x130 +[ 287.812530] dma_direct_map_sg+0x78/0xe0 +[ 287.816453] imx_uart_dma_tx+0x134/0x2f8 +[ 287.820374] imx_uart_dma_tx_callback+0xd8/0x168 +[ 287.824992] vchan_complete+0x194/0x200 +[ 287.828828] tasklet_action_common.isra.0+0x154/0x1a0 +[ 287.833879] tasklet_action+0x24/0x30 +[ 287.837540] __do_softirq+0x120/0x23c +[ 287.841202] irq_exit+0xb8/0xd8 +[ 287.844343] __handle_domain_irq+0x64/0xb8 +[ 287.848438] gic_handle_irq+0x5c/0x148 +[ 287.852185] el1_irq+0xb8/0x180 +[ 287.855327] cpuidle_enter_state+0x84/0x360 +[ 287.859508] cpuidle_enter+0x34/0x48 +[ 287.863083] call_cpuidle+0x18/0x38 +[ 287.866571] do_idle+0x1e0/0x280 +[ 287.869798] cpu_startup_entry+0x20/0x40 +[ 287.873721] rest_init+0xd4/0xe0 +[ 287.876949] arch_call_rest_init+0xc/0x14 +[ 287.880958] start_kernel+0x420/0x44c +[ 287.884622] Code: 9124c021 9417aff8 a94363f7 17ffffd5 (d4210000) +[ 287.890718] ---[ end trace 5bc44c4ab6b009ce ]--- +[ 287.895334] Kernel panic - not syncing: Fatal exception in interrupt +[ 287.901686] SMP: stopping secondary CPUs +[ 288.905607] SMP: failed to stop secondary CPUs 0-1 +[ 288.910395] Kernel Offset: disabled +[ 288.913882] CPU features: 0x0002,2000200c +[ 288.917888] Memory Limit: none +[ 288.920944] ---[ end Kernel panic - not syncing: Fatal exception in interrupt ]--- + +Reported-by: Eagle Zhou +Tested-by: Eagle Zhou +Signed-off-by: Fugang Duan +Cc: stable +Fixes: 7942f8577f2a ("serial: imx: TX DMA: clean up sg initialization") +Reviewed-by: Uwe Kleine-König +Link: https://lore.kernel.org/r/1581401761-6378-1-git-send-email-fugang.duan@nxp.com +Signed-off-by: Greg Kroah-Hartman +Acked-by: Takashi Iwai + +--- + drivers/tty/serial/imx.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c +index 0c6c63166250..d337782b3648 100644 +--- a/drivers/tty/serial/imx.c ++++ b/drivers/tty/serial/imx.c +@@ -599,7 +599,7 @@ static void imx_uart_dma_tx(struct imx_port *sport) + + sport->tx_bytes = uart_circ_chars_pending(xmit); + +- if (xmit->tail < xmit->head) { ++ if (xmit->tail < xmit->head || xmit->head == 0) { + sport->dma_tx_nents = 1; + sg_init_one(sgl, xmit->buf + xmit->tail, sport->tx_bytes); + } else { +-- +2.16.4 + diff --git a/patches.suse/ttyprintk-fix-a-potential-deadlock-in-interrupt-cont.patch b/patches.suse/ttyprintk-fix-a-potential-deadlock-in-interrupt-cont.patch new file mode 100644 index 0000000..7ef3a91 --- /dev/null +++ b/patches.suse/ttyprintk-fix-a-potential-deadlock-in-interrupt-cont.patch @@ -0,0 +1,109 @@ +From: Zhenzhong Duan +Date: Mon, 13 Jan 2020 11:48:42 +0800 +Subject: ttyprintk: fix a potential deadlock in interrupt context issue +Git-commit: 9a655c77ff8fc65699a3f98e237db563b37c439b +Patch-mainline: 5.6-rc1 +References: git-fixes + +tpk_write()/tpk_close() could be interrupted when holding a mutex, then +in timer handler tpk_write() may be called again trying to acquire same +mutex, lead to deadlock. + +Google syzbot reported this issue with CONFIG_DEBUG_ATOMIC_SLEEP +enabled: + +BUG: sleeping function called from invalid context at +kernel/locking/mutex.c:938 +in_atomic(): 1, irqs_disabled(): 0, non_block: 0, pid: 0, name: swapper/1 +1 lock held by swapper/1/0: +... +Call Trace: + + dump_stack+0x197/0x210 + ___might_sleep.cold+0x1fb/0x23e + __might_sleep+0x95/0x190 + __mutex_lock+0xc5/0x13c0 + mutex_lock_nested+0x16/0x20 + tpk_write+0x5d/0x340 + resync_tnc+0x1b6/0x320 + call_timer_fn+0x1ac/0x780 + run_timer_softirq+0x6c3/0x1790 + __do_softirq+0x262/0x98c + irq_exit+0x19b/0x1e0 + smp_apic_timer_interrupt+0x1a3/0x610 + apic_timer_interrupt+0xf/0x20 + + +See link https://syzkaller.appspot.com/bug?extid=2eeef62ee31f9460ad65 for +more details. + +Fix it by using spinlock in process context instead of mutex and having +interrupt disabled in critical section. + +Reported-by: syzbot+2eeef62ee31f9460ad65@syzkaller.appspotmail.com +Signed-off-by: Zhenzhong Duan +Cc: Arnd Bergmann +Cc: Greg Kroah-Hartman +Link: https://lore.kernel.org/r/20200113034842.435-1-zhenzhong.duan@gmail.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Jiri Slaby +--- + drivers/char/ttyprintk.c | 15 +++++++++------ + 1 file changed, 9 insertions(+), 6 deletions(-) + +--- a/drivers/char/ttyprintk.c ++++ b/drivers/char/ttyprintk.c +@@ -18,10 +18,11 @@ + #include + #include + #include ++#include + + struct ttyprintk_port { + struct tty_port port; +- struct mutex port_write_mutex; ++ spinlock_t spinlock; + }; + + static struct ttyprintk_port tpk_port; +@@ -100,11 +101,12 @@ static int tpk_open(struct tty_struct *t + static void tpk_close(struct tty_struct *tty, struct file *filp) + { + struct ttyprintk_port *tpkp = tty->driver_data; ++ unsigned long flags; + +- mutex_lock(&tpkp->port_write_mutex); ++ spin_lock_irqsave(&tpkp->spinlock, flags); + /* flush tpk_printk buffer */ + tpk_printk(NULL, 0); +- mutex_unlock(&tpkp->port_write_mutex); ++ spin_unlock_irqrestore(&tpkp->spinlock, flags); + + tty_port_close(&tpkp->port, tty, filp); + } +@@ -116,13 +118,14 @@ static int tpk_write(struct tty_struct * + const unsigned char *buf, int count) + { + struct ttyprintk_port *tpkp = tty->driver_data; ++ unsigned long flags; + int ret; + + + /* exclusive use of tpk_printk within this tty */ +- mutex_lock(&tpkp->port_write_mutex); ++ spin_lock_irqsave(&tpkp->spinlock, flags); + ret = tpk_printk(buf, count); +- mutex_unlock(&tpkp->port_write_mutex); ++ spin_unlock_irqrestore(&tpkp->spinlock, flags); + + return ret; + } +@@ -172,7 +175,7 @@ static int __init ttyprintk_init(void) + { + int ret = -ENOMEM; + +- mutex_init(&tpk_port.port_write_mutex); ++ spin_lock_init(&tpk_port.spinlock); + + ttyprintk_driver = tty_alloc_driver(1, + TTY_DRIVER_RESET_TERMIOS | diff --git a/patches.suse/tun-add-mutex_unlock-call-and-napi.skb-clearing-in-t.patch b/patches.suse/tun-add-mutex_unlock-call-and-napi.skb-clearing-in-t.patch new file mode 100644 index 0000000..97db906 --- /dev/null +++ b/patches.suse/tun-add-mutex_unlock-call-and-napi.skb-clearing-in-t.patch @@ -0,0 +1,42 @@ +From: Eric Dumazet +Date: Wed, 22 Jan 2020 09:07:35 -0800 +Subject: tun: add mutex_unlock() call and napi.skb clearing in tun_get_user() +Patch-mainline: v5.5 +Git-commit: 1efba987c48629c0c64703bb4ea76ca1a3771d17 +References: bsc#1109837 + +If both IFF_NAPI_FRAGS mode and XDP are enabled, and the XDP program +consumes the skb, we need to clear the napi.skb (or risk +a use-after-free) and release the mutex (or risk a deadlock) + +WARNING: lock held when returning to user space! +5.5.0-rc6-syzkaller #0 Not tainted +------------------------------------------------ +syz-executor.0/455 is leaving the kernel with locks still held! +1 lock held by syz-executor.0/455: + #0: ffff888098f6e748 (&tfile->napi_mutex){+.+.}, at: tun_get_user+0x1604/0x3fc0 drivers/net/tun.c:1835 + +Fixes: 90e33d459407 ("tun: enable napi_gro_frags() for TUN/TAP driver") +Signed-off-by: Eric Dumazet +Reported-by: syzbot +Cc: Petar Penkov +Cc: Willem de Bruijn +Signed-off-by: David S. Miller +Acked-by: Thomas Bogendoerfer +--- + drivers/net/tun.c | 4 ++++ + 1 file changed, 4 insertions(+) + +--- a/drivers/net/tun.c ++++ b/drivers/net/tun.c +@@ -1918,6 +1918,10 @@ drop: + if (ret != XDP_PASS) { + rcu_read_unlock(); + local_bh_enable(); ++ if (frags) { ++ tfile->napi.skb = NULL; ++ mutex_unlock(&tfile->napi_mutex); ++ } + return total_len; + } + } diff --git a/patches.suse/usb-audio-v2-Add-uac2_effect_unit_descriptor-definit.patch b/patches.suse/usb-audio-v2-Add-uac2_effect_unit_descriptor-definit.patch new file mode 100644 index 0000000..4623810 --- /dev/null +++ b/patches.suse/usb-audio-v2-Add-uac2_effect_unit_descriptor-definit.patch @@ -0,0 +1,47 @@ +From 10fa9512769fa3b15ea29f4f331f4604c17b4b2c Mon Sep 17 00:00:00 2001 +From: Takashi Iwai +Date: Thu, 13 Feb 2020 12:20:58 +0100 +Subject: [PATCH] usb: audio-v2: Add uac2_effect_unit_descriptor definition +Git-commit: 10fa9512769fa3b15ea29f4f331f4604c17b4b2c +Patch-mainline: v5.7-rc1 +References: bsc#1051510 + +The UAC2 Effect Unit Descriptor has a slightly different definition +from other similar ones like Processing Unit or Extension Unit. +Define it here so that it can be used in USB-audio driver in a later +patch. + +Acked-by: Greg Kroah-Hartman +Link: https://lore.kernel.org/r/20200213112059.18745-2-tiwai@suse.de +Signed-off-by: Takashi Iwai + +--- + include/linux/usb/audio-v2.h | 12 ++++++++++++ + 1 file changed, 12 insertions(+) + +diff --git a/include/linux/usb/audio-v2.h b/include/linux/usb/audio-v2.h +index ba4b3e3327ff..cb9900b34b67 100644 +--- a/include/linux/usb/audio-v2.h ++++ b/include/linux/usb/audio-v2.h +@@ -156,6 +156,18 @@ struct uac2_feature_unit_descriptor { + __u8 bmaControls[0]; /* variable length */ + } __attribute__((packed)); + ++/* 4.7.2.10 Effect Unit Descriptor */ ++ ++struct uac2_effect_unit_descriptor { ++ __u8 bLength; ++ __u8 bDescriptorType; ++ __u8 bDescriptorSubtype; ++ __u8 bUnitID; ++ __le16 wEffectType; ++ __u8 bSourceID; ++ __u8 bmaControls[]; /* variable length */ ++} __attribute__((packed)); ++ + /* 4.9.2 Class-Specific AS Interface Descriptor */ + + struct uac2_as_header_descriptor { +-- +2.16.4 + diff --git a/patches.suse/usb-gadget-f_fs-Fix-use-after-free-issue-as-part-of-.patch b/patches.suse/usb-gadget-f_fs-Fix-use-after-free-issue-as-part-of-.patch new file mode 100644 index 0000000..6de9bc7 --- /dev/null +++ b/patches.suse/usb-gadget-f_fs-Fix-use-after-free-issue-as-part-of-.patch @@ -0,0 +1,43 @@ +From f63ec55ff904b2f2e126884fcad93175f16ab4bb Mon Sep 17 00:00:00 2001 +From: Sriharsha Allenki +Date: Thu, 26 Mar 2020 17:26:20 +0530 +Subject: [PATCH] usb: gadget: f_fs: Fix use after free issue as part of queue failure +Git-commit: f63ec55ff904b2f2e126884fcad93175f16ab4bb +Patch-mainline: v5.7-rc1 +References: bsc#1051510 + +In AIO case, the request is freed up if ep_queue fails. +However, io_data->req still has the reference to this freed +request. In the case of this failure if there is aio_cancel +call on this io_data it will lead to an invalid dequeue +operation and a potential use after free issue. +Fix this by setting the io_data->req to NULL when the request +is freed as part of queue failure. + +Fixes: 2e4c7553cd6f ("usb: gadget: f_fs: add aio support") +Signed-off-by: Sriharsha Allenki +Cc: stable +Reviewed-by: Peter Chen +Link: https://lore.kernel.org/r/20200326115620.12571-1-sallenki@codeaurora.org +Signed-off-by: Greg Kroah-Hartman +Acked-by: Takashi Iwai + +--- + drivers/usb/gadget/function/f_fs.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/usb/gadget/function/f_fs.c b/drivers/usb/gadget/function/f_fs.c +index 571917677d35..767f30b86645 100644 +--- a/drivers/usb/gadget/function/f_fs.c ++++ b/drivers/usb/gadget/function/f_fs.c +@@ -1120,6 +1120,7 @@ static ssize_t ffs_epfile_io(struct file *file, struct ffs_io_data *io_data) + + ret = usb_ep_queue(ep->ep, req, GFP_ATOMIC); + if (unlikely(ret)) { ++ io_data->req = NULL; + usb_ep_free_request(ep->ep, req); + goto error_lock; + } +-- +2.16.4 + diff --git a/patches.suse/usb-musb-fix-crash-with-highmen-PIO-and-usbmon.patch b/patches.suse/usb-musb-fix-crash-with-highmen-PIO-and-usbmon.patch new file mode 100644 index 0000000..eda258f --- /dev/null +++ b/patches.suse/usb-musb-fix-crash-with-highmen-PIO-and-usbmon.patch @@ -0,0 +1,84 @@ +From 52974d94a206ce428d9d9b6eaa208238024be82a Mon Sep 17 00:00:00 2001 +From: Mans Rullgard +Date: Mon, 16 Mar 2020 16:11:35 -0500 +Subject: [PATCH] usb: musb: fix crash with highmen PIO and usbmon +Git-commit: 52974d94a206ce428d9d9b6eaa208238024be82a +Patch-mainline: v5.7-rc1 +References: bsc#1051510 + +When handling a PIO bulk transfer with highmem buffer, a temporary +mapping is assigned to urb->transfer_buffer. After the transfer is +complete, an invalid address is left behind in this pointer. This is +not ordinarily a problem since nothing touches that buffer before the +urb is released. However, when usbmon is active, usbmon_urb_complete() +calls (indirectly) mon_bin_get_data() which does access the transfer +buffer if it is set. To prevent an invalid memory access here, reset +urb->transfer_buffer to NULL when finished (musb_host_rx()), or do not +set it at all (musb_host_tx()). + +Fixes: 8e8a55165469 ("usb: musb: host: Handle highmem in PIO mode") +Signed-off-by: Mans Rullgard +Cc: stable@vger.kernel.org +Signed-off-by: Bin Liu +Link: https://lore.kernel.org/r/20200316211136.2274-8-b-liu@ti.com +Signed-off-by: Greg Kroah-Hartman +Acked-by: Takashi Iwai + +--- + drivers/usb/musb/musb_host.c | 17 +++++------------ + 1 file changed, 5 insertions(+), 12 deletions(-) + +diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c +index 1c813c37462a..8736f4251a22 100644 +--- a/drivers/usb/musb/musb_host.c ++++ b/drivers/usb/musb/musb_host.c +@@ -1436,10 +1436,7 @@ void musb_host_tx(struct musb *musb, u8 epnum) + * We need to map sg if the transfer_buffer is + * NULL. + */ +- if (!urb->transfer_buffer) +- qh->use_sg = true; +- +- if (qh->use_sg) { ++ if (!urb->transfer_buffer) { + /* sg_miter_start is already done in musb_ep_program */ + if (!sg_miter_next(&qh->sg_miter)) { + dev_err(musb->controller, "error: sg list empty\n"); +@@ -1447,9 +1444,8 @@ void musb_host_tx(struct musb *musb, u8 epnum) + status = -EINVAL; + goto done; + } +- urb->transfer_buffer = qh->sg_miter.addr; + length = min_t(u32, length, qh->sg_miter.length); +- musb_write_fifo(hw_ep, length, urb->transfer_buffer); ++ musb_write_fifo(hw_ep, length, qh->sg_miter.addr); + qh->sg_miter.consumed = length; + sg_miter_stop(&qh->sg_miter); + } else { +@@ -1458,11 +1454,6 @@ void musb_host_tx(struct musb *musb, u8 epnum) + + qh->segsize = length; + +- if (qh->use_sg) { +- if (offset + length >= urb->transfer_buffer_length) +- qh->use_sg = false; +- } +- + musb_ep_select(mbase, epnum); + musb_writew(epio, MUSB_TXCSR, + MUSB_TXCSR_H_WZC_BITS | MUSB_TXCSR_TXPKTRDY); +@@ -1977,8 +1968,10 @@ void musb_host_rx(struct musb *musb, u8 epnum) + urb->actual_length += xfer_len; + qh->offset += xfer_len; + if (done) { +- if (qh->use_sg) ++ if (qh->use_sg) { + qh->use_sg = false; ++ urb->transfer_buffer = NULL; ++ } + + if (urb->status == -EINPROGRESS) + urb->status = status; +-- +2.16.4 + diff --git a/patches.suse/vhost-check-docket-sk_family-instead-of-call-getname.patch b/patches.suse/vhost-check-docket-sk_family-instead-of-call-getname.patch new file mode 100644 index 0000000..4395b97 --- /dev/null +++ b/patches.suse/vhost-check-docket-sk_family-instead-of-call-getname.patch @@ -0,0 +1,57 @@ +From: =?UTF-8?q?Eugenio=20P=C3=A9rez?= +Date: Fri, 21 Feb 2020 12:06:56 +0100 +Subject: vhost: Check docket sk_family instead of call getname +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit +Git-commit: 42d84c8490f9f0931786f1623191fcab397c3d64 +Patch-mainline: v5.6-rc4 +References: bsc#1167629 CVE-2020-10942 + +Doing so, we save one call to get data we already have in the struct. + +Also, since there is no guarantee that getname use sockaddr_ll +parameter beyond its size, we add a little bit of security here. +It should do not do beyond MAX_ADDR_LEN, but syzbot found that +ax25_getname writes more (72 bytes, the size of full_sockaddr_ax25, +versus 20 + 32 bytes of sockaddr_ll + MAX_ADDR_LEN in syzbot repro). + +Fixes: 3a4d5c94e9593 ("vhost_net: a kernel-level virtio server") +Reported-by: syzbot+f2a62d07a5198c819c7b@syzkaller.appspotmail.com +Signed-off-by: Eugenio Pérez +Acked-by: Michael S. Tsirkin +Signed-off-by: David S. Miller +Acked-by: Borislav Petkov +--- + drivers/vhost/net.c | 13 ++----------- + 1 file changed, 2 insertions(+), 11 deletions(-) + +--- a/drivers/vhost/net.c ++++ b/drivers/vhost/net.c +@@ -927,11 +927,7 @@ static int vhost_net_release(struct inod + + static struct socket *get_raw_socket(int fd) + { +- struct { +- struct sockaddr_ll sa; +- char buf[MAX_ADDR_LEN]; +- } uaddr; +- int uaddr_len = sizeof uaddr, r; ++ int r; + struct socket *sock = sockfd_lookup(fd, &r); + + if (!sock) +@@ -943,12 +939,7 @@ static struct socket *get_raw_socket(int + goto err; + } + +- r = sock->ops->getname(sock, (struct sockaddr *)&uaddr.sa, +- &uaddr_len, 0); +- if (r) +- goto err; +- +- if (uaddr.sa.sll_family != AF_PACKET) { ++ if (sock->sk->sk_family != AF_PACKET) { + r = -EPFNOSUPPORT; + goto err; + } diff --git a/patches.suse/virtio-blk-improve-virtqueue-error-to-BLK_STS.patch b/patches.suse/virtio-blk-improve-virtqueue-error-to-BLK_STS.patch new file mode 100644 index 0000000..47b6b31 --- /dev/null +++ b/patches.suse/virtio-blk-improve-virtqueue-error-to-BLK_STS.patch @@ -0,0 +1,47 @@ +From 3d973b2e9a625996ee997c7303cd793b9d197c65 Mon Sep 17 00:00:00 2001 +From: Halil Pasic +Date: Thu, 13 Feb 2020 13:37:28 +0100 +Subject: [PATCH] virtio-blk: improve virtqueue error to BLK_STS +Git-commit: 3d973b2e9a625996ee997c7303cd793b9d197c65 +Patch-mainline: v5.6-rc6 +References: bsc#1167627 + +Let's change the mapping between virtqueue_add errors to BLK_STS +statuses, so that -ENOSPC, which indicates virtqueue full is still +mapped to BLK_STS_DEV_RESOURCE, but -ENOMEM which indicates non-device +specific resource outage is mapped to BLK_STS_RESOURCE. + +Signed-off-by: Halil Pasic +Link: https://lore.kernel.org/r/20200213123728.61216-3-pasic@linux.ibm.com +Signed-off-by: Michael S. Tsirkin +Reviewed-by: Stefan Hajnoczi +Acked-by: Takashi Iwai + +--- + drivers/block/virtio_blk.c | 9 +++++++-- + 1 file changed, 7 insertions(+), 2 deletions(-) + +diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c +index adfe43f5ffe4..0736248999b0 100644 +--- a/drivers/block/virtio_blk.c ++++ b/drivers/block/virtio_blk.c +@@ -251,9 +251,14 @@ static blk_status_t virtio_queue_rq(struct blk_mq_hw_ctx *hctx, + if (err == -ENOSPC) + blk_mq_stop_hw_queue(hctx); + spin_unlock_irqrestore(&vblk->vqs[qid].lock, flags); +- if (err == -ENOMEM || err == -ENOSPC) ++ switch (err) { ++ case -ENOSPC: + return BLK_STS_DEV_RESOURCE; +- return BLK_STS_IOERR; ++ case -ENOMEM: ++ return BLK_STS_RESOURCE; ++ default: ++ return BLK_STS_IOERR; ++ } + } + + if (bd->last && virtqueue_kick_prepare(vblk->vqs[qid].vq)) +-- +2.16.4 + diff --git a/patches.suse/vlan-fix-memory-leak-in-vlan_dev_set_egress_priority.patch b/patches.suse/vlan-fix-memory-leak-in-vlan_dev_set_egress_priority.patch new file mode 100644 index 0000000..86391a3 --- /dev/null +++ b/patches.suse/vlan-fix-memory-leak-in-vlan_dev_set_egress_priority.patch @@ -0,0 +1,98 @@ +From: Eric Dumazet +Date: Tue, 7 Jan 2020 01:42:24 -0800 +Subject: vlan: fix memory leak in vlan_dev_set_egress_priority +Git-commit: 9bbd917e0bec9aebdbd0c8dbc966caec15eb33e9 +Patch-mainline: 5.5-rc6 +References: networking-stable-20_01_11 + +There are few cases where the ndo_uninit() handler might be not +called if an error happens while device is initialized. + +Since vlan_newlink() calls vlan_changelink() before +trying to register the netdevice, we need to make sure +vlan_dev_uninit() has been called at least once, +or we might leak allocated memory. + +BUG: memory leak +unreferenced object 0xffff888122a206c0 (size 32): + comm "syz-executor511", pid 7124, jiffies 4294950399 (age 32.240s) + hex dump (first 32 bytes): + 00 00 00 00 00 00 61 73 00 00 00 00 00 00 00 00 ......as........ + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ + backtrace: + [<000000000eb3bb85>] kmemleak_alloc_recursive include/linux/kmemleak.h:43 [inline] + [<000000000eb3bb85>] slab_post_alloc_hook mm/slab.h:586 [inline] + [<000000000eb3bb85>] slab_alloc mm/slab.c:3320 [inline] + [<000000000eb3bb85>] kmem_cache_alloc_trace+0x145/0x2c0 mm/slab.c:3549 + [<000000007b99f620>] kmalloc include/linux/slab.h:556 [inline] + [<000000007b99f620>] vlan_dev_set_egress_priority+0xcc/0x150 net/8021q/vlan_dev.c:194 + [<000000007b0cb745>] vlan_changelink+0xd6/0x140 net/8021q/vlan_netlink.c:126 + [<0000000065aba83a>] vlan_newlink+0x135/0x200 net/8021q/vlan_netlink.c:181 + [<00000000fb5dd7a2>] __rtnl_newlink+0x89a/0xb80 net/core/rtnetlink.c:3305 + [<00000000ae4273a1>] rtnl_newlink+0x4e/0x80 net/core/rtnetlink.c:3363 + [<00000000decab39f>] rtnetlink_rcv_msg+0x178/0x4b0 net/core/rtnetlink.c:5424 + [<00000000accba4ee>] netlink_rcv_skb+0x61/0x170 net/netlink/af_netlink.c:2477 + [<00000000319fe20f>] rtnetlink_rcv+0x1d/0x30 net/core/rtnetlink.c:5442 + [<00000000d51938dc>] netlink_unicast_kernel net/netlink/af_netlink.c:1302 [inline] + [<00000000d51938dc>] netlink_unicast+0x223/0x310 net/netlink/af_netlink.c:1328 + [<00000000e539ac79>] netlink_sendmsg+0x2c0/0x570 net/netlink/af_netlink.c:1917 + [<000000006250c27e>] sock_sendmsg_nosec net/socket.c:639 [inline] + [<000000006250c27e>] sock_sendmsg+0x54/0x70 net/socket.c:659 + [<00000000e2a156d1>] ____sys_sendmsg+0x2d0/0x300 net/socket.c:2330 + [<000000008c87466e>] ___sys_sendmsg+0x8a/0xd0 net/socket.c:2384 + [<00000000110e3054>] __sys_sendmsg+0x80/0xf0 net/socket.c:2417 + [<00000000d71077c8>] __do_sys_sendmsg net/socket.c:2426 [inline] + [<00000000d71077c8>] __se_sys_sendmsg net/socket.c:2424 [inline] + [<00000000d71077c8>] __x64_sys_sendmsg+0x23/0x30 net/socket.c:2424 + +Fixe: 07b5b17e157b ("[VLAN]: Use rtnl_link API") +Signed-off-by: Eric Dumazet +Reported-by: syzbot +Signed-off-by: David S. Miller +Signed-off-by: Jiri Slaby +--- + net/8021q/vlan.h | 1 + + net/8021q/vlan_dev.c | 3 ++- + net/8021q/vlan_netlink.c | 9 +++++---- + 3 files changed, 8 insertions(+), 5 deletions(-) + +--- a/net/8021q/vlan.h ++++ b/net/8021q/vlan.h +@@ -109,6 +109,7 @@ int vlan_check_real_dev(struct net_devic + void vlan_setup(struct net_device *dev); + int register_vlan_dev(struct net_device *dev, struct netlink_ext_ack *extack); + void unregister_vlan_dev(struct net_device *dev, struct list_head *head); ++void vlan_dev_uninit(struct net_device *dev); + bool vlan_dev_inherit_address(struct net_device *dev, + struct net_device *real_dev); + +--- a/net/8021q/vlan_dev.c ++++ b/net/8021q/vlan_dev.c +@@ -610,7 +610,8 @@ static int vlan_dev_init(struct net_devi + return 0; + } + +-static void vlan_dev_uninit(struct net_device *dev) ++/* Note: this function might be called multiple times for the same device. */ ++void vlan_dev_uninit(struct net_device *dev) + { + struct vlan_priority_tci_mapping *pm; + struct vlan_dev_priv *vlan = vlan_dev_priv(dev); +--- a/net/8021q/vlan_netlink.c ++++ b/net/8021q/vlan_netlink.c +@@ -156,10 +156,11 @@ static int vlan_newlink(struct net *src_ + return -EINVAL; + + err = vlan_changelink(dev, tb, data, extack); +- if (err < 0) +- return err; +- +- return register_vlan_dev(dev, extack); ++ if (!err) ++ err = register_vlan_dev(dev, extack); ++ if (err) ++ vlan_dev_uninit(dev); ++ return err; + } + + static inline size_t vlan_qos_map_size(unsigned int n) diff --git a/patches.suse/vlan-vlan_changelink-should-propagate-errors.patch b/patches.suse/vlan-vlan_changelink-should-propagate-errors.patch new file mode 100644 index 0000000..29050ad --- /dev/null +++ b/patches.suse/vlan-vlan_changelink-should-propagate-errors.patch @@ -0,0 +1,47 @@ +From: Eric Dumazet +Date: Tue, 7 Jan 2020 01:42:25 -0800 +Subject: vlan: vlan_changelink() should propagate errors +Git-commit: eb8ef2a3c50092bb018077c047b8dba1ce0e78e3 +Patch-mainline: 5.5-rc6 +References: networking-stable-20_01_11 + +Both vlan_dev_change_flags() and vlan_dev_set_egress_priority() +can return an error. vlan_changelink() should not ignore them. + +Fixes: 07b5b17e157b ("[VLAN]: Use rtnl_link API") +Signed-off-by: Eric Dumazet +Signed-off-by: David S. Miller +Signed-off-by: Jiri Slaby +--- + net/8021q/vlan_netlink.c | 10 +++++++--- + 1 file changed, 7 insertions(+), 3 deletions(-) + +--- a/net/8021q/vlan_netlink.c ++++ b/net/8021q/vlan_netlink.c +@@ -94,11 +94,13 @@ static int vlan_changelink(struct net_de + struct ifla_vlan_flags *flags; + struct ifla_vlan_qos_mapping *m; + struct nlattr *attr; +- int rem; ++ int rem, err; + + if (data[IFLA_VLAN_FLAGS]) { + flags = nla_data(data[IFLA_VLAN_FLAGS]); +- vlan_dev_change_flags(dev, flags->flags, flags->mask); ++ err = vlan_dev_change_flags(dev, flags->flags, flags->mask); ++ if (err) ++ return err; + } + if (data[IFLA_VLAN_INGRESS_QOS]) { + nla_for_each_nested(attr, data[IFLA_VLAN_INGRESS_QOS], rem) { +@@ -109,7 +111,9 @@ static int vlan_changelink(struct net_de + if (data[IFLA_VLAN_EGRESS_QOS]) { + nla_for_each_nested(attr, data[IFLA_VLAN_EGRESS_QOS], rem) { + m = nla_data(attr); +- vlan_dev_set_egress_priority(dev, m->from, m->to); ++ err = vlan_dev_set_egress_priority(dev, m->from, m->to); ++ if (err) ++ return err; + } + } + return 0; diff --git a/patches.suse/vt-selection-close-sel_buffer-race.patch b/patches.suse/vt-selection-close-sel_buffer-race.patch index ab51197..033e63e 100644 --- a/patches.suse/vt-selection-close-sel_buffer-race.patch +++ b/patches.suse/vt-selection-close-sel_buffer-race.patch @@ -1,9 +1,8 @@ From: Jiri Slaby Date: Mon, 10 Feb 2020 09:11:31 +0100 Subject: vt: selection, close sel_buffer race -Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty.git#tty-linus Git-commit: 07e6124a1a46b4b5a9b3cacc0c306b50da87abf5 -Patch-mainline: Queued in subsystem maintainer repository +Patch-mainline: 5.6-rc3 References: bnc#1162928 CVE-2020-8648 syzkaller reported this UAF: diff --git a/patches.suse/vt-selection-handle-pending-signals-in-paste_selecti.patch b/patches.suse/vt-selection-handle-pending-signals-in-paste_selecti.patch index a2ebabd..e373959 100644 --- a/patches.suse/vt-selection-handle-pending-signals-in-paste_selecti.patch +++ b/patches.suse/vt-selection-handle-pending-signals-in-paste_selecti.patch @@ -1,9 +1,8 @@ From: Jiri Slaby Date: Mon, 10 Feb 2020 09:11:30 +0100 Subject: vt: selection, handle pending signals in paste_selection -Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty.git#tty-linus Git-commit: 687bff0cd08f790d540cfb7b2349f0d876cdddec -Patch-mainline: Queued in subsystem maintainer repository +Patch-mainline: 5.6-rc3 References: bnc#1162928 CVE-2020-8648 When pasting a selection to a vt, the task is set as INTERRUPTIBLE while diff --git a/patches.suse/vt-selection-push-console-lock-down.patch b/patches.suse/vt-selection-push-console-lock-down.patch new file mode 100644 index 0000000..4d3d112 --- /dev/null +++ b/patches.suse/vt-selection-push-console-lock-down.patch @@ -0,0 +1,64 @@ +From: Jiri Slaby +Date: Fri, 28 Feb 2020 12:54:05 +0100 +Subject: vt: selection, push console lock down +Git-commit: 4b70dd57a15d2f4685ac6e38056bad93e81e982f +Patch-mainline: 5.6-rc5 +References: bnc#1162928 CVE-2020-8648 + +We need to nest the console lock in sel_lock, so we have to push it down +a bit. Fortunately, the callers of set_selection_* just lock the console +lock around the function call. So moving it down is easy. + +In the next patch, we switch the order. + +Signed-off-by: Jiri Slaby +Fixes: 07e6124a1a46 ("vt: selection, close sel_buffer race") +Cc: stable +Link: https://lore.kernel.org/r/20200228115406.5735-1-jslaby@suse.cz +Signed-off-by: Greg Kroah-Hartman +--- + drivers/tty/vt/selection.c | 13 ++++++++++++- + drivers/tty/vt/vt.c | 2 -- + 2 files changed, 12 insertions(+), 3 deletions(-) + +--- a/drivers/tty/vt/selection.c ++++ b/drivers/tty/vt/selection.c +@@ -156,7 +156,7 @@ static int store_utf8(u16 c, char *p) + * The entire selection process is managed under the console_lock. It's + * a lot under the lock but its hardly a performance path + */ +-int set_selection(const struct tiocl_selection __user *sel, struct tty_struct *tty) ++static int __set_selection(const struct tiocl_selection __user *sel, struct tty_struct *tty) + { + struct vc_data *vc = vc_cons[fg_console].d; + int sel_mode, new_sel_start, new_sel_end, spc; +@@ -332,6 +332,17 @@ unlock: + return ret; + } + ++int set_selection(const struct tiocl_selection __user *sel, struct tty_struct *tty) ++{ ++ int ret; ++ ++ console_lock(); ++ ret = __set_selection(sel, tty); ++ console_unlock(); ++ ++ return ret; ++} ++ + /* Insert the contents of the selection buffer into the + * queue of the tty associated with the current console. + * Invoked by ioctl(). +--- a/drivers/tty/vt/vt.c ++++ b/drivers/tty/vt/vt.c +@@ -2688,9 +2688,7 @@ int tioclinux(struct tty_struct *tty, un + switch (type) + { + case TIOCL_SETSEL: +- console_lock(); + ret = set_selection((struct tiocl_selection __user *)(p+1), tty); +- console_unlock(); + break; + case TIOCL_PASTESEL: + ret = paste_selection(tty); diff --git a/patches.suse/vt-selection-push-sel_lock-up.patch b/patches.suse/vt-selection-push-sel_lock-up.patch new file mode 100644 index 0000000..f052947 --- /dev/null +++ b/patches.suse/vt-selection-push-sel_lock-up.patch @@ -0,0 +1,142 @@ +From: Jiri Slaby +Date: Fri, 28 Feb 2020 12:54:06 +0100 +Subject: vt: selection, push sel_lock up +Git-commit: e8c75a30a23c6ba63f4ef6895cbf41fd42f21aa2 +Patch-mainline: 5.6-rc5 +References: bnc#1162928 CVE-2020-8648 + +sel_lock cannot nest in the console lock. Thanks to syzkaller, the +kernel states firmly: + +> WARNING: possible circular locking dependency detected +> 5.6.0-rc3-syzkaller #0 Not tainted +> ------------------------------------------------------ +> syz-executor.4/20336 is trying to acquire lock: +> ffff8880a2e952a0 (&tty->termios_rwsem){++++}, at: tty_unthrottle+0x22/0x100 drivers/tty/tty_ioctl.c:136 +> +> but task is already holding lock: +> ffffffff89462e70 (sel_lock){+.+.}, at: paste_selection+0x118/0x470 drivers/tty/vt/selection.c:374 +> +> which lock already depends on the new lock. +> +> the existing dependency chain (in reverse order) is: +> +> -> #2 (sel_lock){+.+.}: +> mutex_lock_nested+0x1b/0x30 kernel/locking/mutex.c:1118 +> set_selection_kernel+0x3b8/0x18a0 drivers/tty/vt/selection.c:217 +> set_selection_user+0x63/0x80 drivers/tty/vt/selection.c:181 +> tioclinux+0x103/0x530 drivers/tty/vt/vt.c:3050 +> vt_ioctl+0x3f1/0x3a30 drivers/tty/vt/vt_ioctl.c:364 + +This is ioctl(TIOCL_SETSEL). +Locks held on the path: console_lock -> sel_lock + +> -> #1 (console_lock){+.+.}: +> console_lock+0x46/0x70 kernel/printk/printk.c:2289 +> con_flush_chars+0x50/0x650 drivers/tty/vt/vt.c:3223 +> n_tty_write+0xeae/0x1200 drivers/tty/n_tty.c:2350 +> do_tty_write drivers/tty/tty_io.c:962 [inline] +> tty_write+0x5a1/0x950 drivers/tty/tty_io.c:1046 + +This is write(). +Locks held on the path: termios_rwsem -> console_lock + +> -> #0 (&tty->termios_rwsem){++++}: +> down_write+0x57/0x140 kernel/locking/rwsem.c:1534 +> tty_unthrottle+0x22/0x100 drivers/tty/tty_ioctl.c:136 +> mkiss_receive_buf+0x12aa/0x1340 drivers/net/hamradio/mkiss.c:902 +> tty_ldisc_receive_buf+0x12f/0x170 drivers/tty/tty_buffer.c:465 +> paste_selection+0x346/0x470 drivers/tty/vt/selection.c:389 +> tioclinux+0x121/0x530 drivers/tty/vt/vt.c:3055 +> vt_ioctl+0x3f1/0x3a30 drivers/tty/vt/vt_ioctl.c:364 + +This is ioctl(TIOCL_PASTESEL). +Locks held on the path: sel_lock -> termios_rwsem + +> other info that might help us debug this: +> +> Chain exists of: +> &tty->termios_rwsem --> console_lock --> sel_lock + +Clearly. From the above, we have: + console_lock -> sel_lock + sel_lock -> termios_rwsem + termios_rwsem -> console_lock + +Fix this by reversing the console_lock -> sel_lock dependency in +ioctl(TIOCL_SETSEL). First, lock sel_lock, then console_lock. + +Signed-off-by: Jiri Slaby +Reported-by: syzbot+26183d9746e62da329b8@syzkaller.appspotmail.com +Fixes: 07e6124a1a46 ("vt: selection, close sel_buffer race") +Cc: stable +Link: https://lore.kernel.org/r/20200228115406.5735-2-jslaby@suse.cz +Signed-off-by: Greg Kroah-Hartman +--- + drivers/tty/vt/selection.c | 16 +++++++--------- + 1 file changed, 7 insertions(+), 9 deletions(-) + +--- a/drivers/tty/vt/selection.c ++++ b/drivers/tty/vt/selection.c +@@ -203,7 +203,6 @@ static int __set_selection(const struct + pe = tmp; + } + +- mutex_lock(&sel_lock); + if (sel_cons != vc_cons[fg_console].d) { + clear_selection(); + sel_cons = vc_cons[fg_console].d; +@@ -249,10 +248,9 @@ static int __set_selection(const struct + break; + case TIOCL_SELPOINTER: + highlight_pointer(pe); +- goto unlock; ++ return 0; + default: +- ret = -EINVAL; +- goto unlock; ++ return -EINVAL; + } + + /* remove the pointer */ +@@ -274,7 +272,7 @@ static int __set_selection(const struct + else if (new_sel_start == sel_start) + { + if (new_sel_end == sel_end) /* no action required */ +- goto unlock; ++ return 0; + else if (new_sel_end > sel_end) /* extend to right */ + highlight(sel_end + 2, new_sel_end); + else /* contract from right */ +@@ -301,8 +299,7 @@ static int __set_selection(const struct + if (!bp) { + printk(KERN_WARNING "selection: kmalloc() failed\n"); + clear_selection(); +- ret = -ENOMEM; +- goto unlock; ++ return -ENOMEM; + } + kfree(sel_buffer); + sel_buffer = bp; +@@ -327,8 +324,7 @@ static int __set_selection(const struct + } + } + sel_buffer_lth = bp - sel_buffer; +-unlock: +- mutex_unlock(&sel_lock); ++ + return ret; + } + +@@ -336,9 +332,11 @@ int set_selection(const struct tiocl_sel + { + int ret; + ++ mutex_lock(&sel_lock); + console_lock(); + ret = __set_selection(sel, tty); + console_unlock(); ++ mutex_unlock(&sel_lock); + + return ret; + } diff --git a/patches.suse/vxlan-fix-tos-value-before-xmit.patch b/patches.suse/vxlan-fix-tos-value-before-xmit.patch new file mode 100644 index 0000000..f187317 --- /dev/null +++ b/patches.suse/vxlan-fix-tos-value-before-xmit.patch @@ -0,0 +1,43 @@ +From: Hangbin Liu +Date: Thu, 2 Jan 2020 17:23:45 +0800 +Subject: vxlan: fix tos value before xmit +Git-commit: 71130f29979c7c7956b040673e6b9d5643003176 +Patch-mainline: 5.5-rc6 +References: networking-stable-20_01_11 + +Before ip_tunnel_ecn_encap() and udp_tunnel_xmit_skb() we should filter +tos value by RT_TOS() instead of using config tos directly. + +vxlan_get_route() would filter the tos to fl4.flowi4_tos but we didn't +return it back, as geneve_get_v4_rt() did. So we have to use RT_TOS() +directly in function ip_tunnel_ecn_encap(). + +Fixes: 206aaafcd279 ("VXLAN: Use IP Tunnels tunnel ENC encap API") +Fixes: 1400615d64cf ("vxlan: allow setting ipv6 traffic class") +Signed-off-by: Hangbin Liu +Signed-off-by: David S. Miller +Signed-off-by: Jiri Slaby +--- + drivers/net/vxlan.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/net/vxlan.c ++++ b/drivers/net/vxlan.c +@@ -2203,7 +2203,7 @@ static void vxlan_xmit_one(struct sk_buf + ndst = &rt->dst; + skb_tunnel_check_pmtu(skb, ndst, VXLAN_HEADROOM); + +- tos = ip_tunnel_ecn_encap(tos, old_iph, skb); ++ tos = ip_tunnel_ecn_encap(RT_TOS(tos), old_iph, skb); + ttl = ttl ? : ip4_dst_hoplimit(&rt->dst); + err = vxlan_build_skb(skb, ndst, sizeof(struct iphdr), + vni, md, flags, udp_sum); +@@ -2241,7 +2241,7 @@ static void vxlan_xmit_one(struct sk_buf + + skb_tunnel_check_pmtu(skb, ndst, VXLAN6_HEADROOM); + +- tos = ip_tunnel_ecn_encap(tos, old_iph, skb); ++ tos = ip_tunnel_ecn_encap(RT_TOS(tos), old_iph, skb); + ttl = ttl ? : ip6_dst_hoplimit(ndst); + skb_scrub_packet(skb, xnet); + err = vxlan_build_skb(skb, ndst, sizeof(struct ipv6hdr), diff --git a/patches.suse/x86-cpu-amd-enable-the-fixed-instructions-retired-counter-irperf.patch b/patches.suse/x86-cpu-amd-enable-the-fixed-instructions-retired-counter-irperf.patch new file mode 100644 index 0000000..ae1caff --- /dev/null +++ b/patches.suse/x86-cpu-amd-enable-the-fixed-instructions-retired-counter-irperf.patch @@ -0,0 +1,114 @@ +From: Kim Phillips +Date: Wed, 19 Feb 2020 18:52:43 +0100 +Subject: x86/cpu/amd: Enable the fixed Instructions Retired counter IRPERF +Git-commit: 21b5ee59ef18e27d85810584caf1f7ddc705ea83 +Patch-mainline: v5.6-rc3 +References: bsc#1114279 + +Commit + + aaf248848db50 ("perf/x86/msr: Add AMD IRPERF (Instructions Retired) + performance counter") + +added support for access to the free-running counter via 'perf -e +msr/irperf/', but when exercised, it always returns a 0 count: + +BEFORE: + + $ perf stat -e instructions,msr/irperf/ true + + Performance counter stats for 'true': + + 624,833 instructions + 0 msr/irperf/ + +Simply set its enable bit - HWCR bit 30 - to make it start counting. + +Enablement is restricted to all machines advertising IRPERF capability, +except those susceptible to an erratum that makes the IRPERF return +bad values. + +That erratum occurs in Family 17h models 00-1fh [1], but not in F17h +models 20h and above [2]. + +AFTER (on a family 17h model 31h machine): + + $ perf stat -e instructions,msr/irperf/ true + + Performance counter stats for 'true': + + 621,690 instructions + 622,490 msr/irperf/ + +[1] Revision Guide for AMD Family 17h Models 00h-0Fh Processors +[2] Revision Guide for AMD Family 17h Models 30h-3Fh Processors + +The revision guides are available from the bugzilla Link below. + + [ bp: Massage commit message. ] + +Fixes: aaf248848db50 ("perf/x86/msr: Add AMD IRPERF (Instructions Retired) performance counter") +Signed-off-by: Kim Phillips +Signed-off-by: Borislav Petkov +Cc: Peter Zijlstra +Cc: stable@vger.kernel.org +Link: https://bugzilla.kernel.org/show_bug.cgi?id=206537 +Link: http://lkml.kernel.org/r/20200214201805.13830-1-kim.phillips@amd.com +--- + arch/x86/include/asm/msr-index.h | 2 ++ + arch/x86/kernel/cpu/amd.c | 14 ++++++++++++++ + 2 files changed, 16 insertions(+) + +diff --git a/arch/x86/include/asm/msr-index.h b/arch/x86/include/asm/msr-index.h +index ebe1685e92dd..d5e517d1c3dd 100644 +--- a/arch/x86/include/asm/msr-index.h ++++ b/arch/x86/include/asm/msr-index.h +@@ -512,6 +512,8 @@ + #define MSR_K7_HWCR 0xc0010015 + #define MSR_K7_HWCR_SMMLOCK_BIT 0 + #define MSR_K7_HWCR_SMMLOCK BIT_ULL(MSR_K7_HWCR_SMMLOCK_BIT) ++#define MSR_K7_HWCR_IRPERF_EN_BIT 30 ++#define MSR_K7_HWCR_IRPERF_EN BIT_ULL(MSR_K7_HWCR_IRPERF_EN_BIT) + #define MSR_K7_FID_VID_CTL 0xc0010041 + #define MSR_K7_FID_VID_STATUS 0xc0010042 + +diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c +index ac83a0fef628..1f875fbe1384 100644 +--- a/arch/x86/kernel/cpu/amd.c ++++ b/arch/x86/kernel/cpu/amd.c +@@ -28,6 +28,7 @@ + + static const int amd_erratum_383[]; + static const int amd_erratum_400[]; ++static const int amd_erratum_1054[]; + static bool cpu_has_amd_erratum(struct cpuinfo_x86 *cpu, const int *erratum); + + /* +@@ -972,6 +973,15 @@ static void init_amd(struct cpuinfo_x86 *c) + /* AMD CPUs don't reset SS attributes on SYSRET, Xen does. */ + if (!cpu_has(c, X86_FEATURE_XENPV)) + set_cpu_bug(c, X86_BUG_SYSRET_SS_ATTRS); ++ ++ /* ++ * Turn on the Instructions Retired free counter on machines not ++ * susceptible to erratum #1054 "Instructions Retired Performance ++ * Counter May Be Inaccurate". ++ */ ++ if (cpu_has(c, X86_FEATURE_IRPERF) && ++ !cpu_has_amd_erratum(c, amd_erratum_1054)) ++ msr_set_bit(MSR_K7_HWCR, MSR_K7_HWCR_IRPERF_EN_BIT); + } + + #ifdef CONFIG_X86_32 +@@ -1099,6 +1109,10 @@ static const int amd_erratum_400[] = + static const int amd_erratum_383[] = + AMD_OSVW_ERRATUM(3, AMD_MODEL_RANGE(0x10, 0, 0, 0xff, 0xf)); + ++/* #1054: Instructions Retired Performance Counter May Be Inaccurate */ ++static const int amd_erratum_1054[] = ++ AMD_OSVW_ERRATUM(0, AMD_MODEL_RANGE(0x17, 0, 0, 0x2f, 0xf)); ++ + + static bool cpu_has_amd_erratum(struct cpuinfo_x86 *cpu, const int *erratum) + { + diff --git a/patches.suse/x86-ioremap-Add-an-ioremap_encrypted-helper.patch b/patches.suse/x86-ioremap-Add-an-ioremap_encrypted-helper.patch new file mode 100644 index 0000000..b0046f1 --- /dev/null +++ b/patches.suse/x86-ioremap-Add-an-ioremap_encrypted-helper.patch @@ -0,0 +1,162 @@ +From c3a7a61c192ec350330128edb13db33a9bc0ace1 Mon Sep 17 00:00:00 2001 +From: Lianbo Jiang +Date: Thu, 27 Sep 2018 15:19:51 +0800 +Subject: [PATCH] x86/ioremap: Add an ioremap_encrypted() helper +References: bsc#1141895 +Git-commit: c3a7a61c192ec350330128edb13db33a9bc0ace1 +Patch-mainline: v4.20-rc1 + +When SME is enabled, the memory is encrypted in the first kernel. In +this case, SME also needs to be enabled in the kdump kernel, and we have +to remap the old memory with the memory encryption mask. + +The case of concern here is if SME is active in the first kernel, +and it is active too in the kdump kernel. There are four cases to be +considered: + +a. dump vmcore + It is encrypted in the first kernel, and needs be read out in the + kdump kernel. + +b. crash notes + When dumping vmcore, the people usually need to read useful + information from notes, and the notes is also encrypted. + +c. iommu device table + It's encrypted in the first kernel, kdump kernel needs to access its + content to analyze and get information it needs. + +d. mmio of AMD iommu + not encrypted in both kernels + +Add a new bool parameter @encrypted to __ioremap_caller(). If set, +memory will be remapped with the SME mask. + +Add a new function ioremap_encrypted() to explicitly pass in a true +value for @encrypted. Use ioremap_encrypted() for the above a, b, c +cases. + + [ bp: cleanup commit message, extern defs in io.h and drop forgotten + include. ] + +Signed-off-by: Lianbo Jiang +Signed-off-by: Borislav Petkov +Reviewed-by: Tom Lendacky +Cc: kexec@lists.infradead.org +Cc: tglx@linutronix.de +Cc: mingo@redhat.com +Cc: hpa@zytor.com +Cc: akpm@linux-foundation.org +Cc: dan.j.williams@intel.com +Cc: bhelgaas@google.com +Cc: baiyaowei@cmss.chinamobile.com +Cc: tiwai@suse.de +Cc: brijesh.singh@amd.com +Cc: dyoung@redhat.com +Cc: bhe@redhat.com +Cc: jroedel@suse.de +Link: https://lkml.kernel.org/r/20180927071954.29615-2-lijiang@redhat.com +--- + arch/x86/include/asm/io.h | 3 ++- + arch/x86/mm/ioremap.c | 24 ++++++++++++++++-------- + 2 files changed, 18 insertions(+), 9 deletions(-) + +diff --git a/arch/x86/include/asm/io.h b/arch/x86/include/asm/io.h +index 6de64840dd22..6df53efcecfd 100644 +--- a/arch/x86/include/asm/io.h ++++ b/arch/x86/include/asm/io.h +@@ -187,6 +187,8 @@ extern void __iomem *ioremap_nocache(resource_size_t offset, unsigned long size) + + extern void __iomem *ioremap_cache(resource_size_t offset, unsigned long size); + extern void __iomem *ioremap_prot(resource_size_t offset, unsigned long size, unsigned long prot_val); ++extern void __iomem *ioremap_encrypted(resource_size_t phys_addr, unsigned long size); ++#define ioremap_encrypted ioremap_encrypted + + /** + * ioremap - map bus memory into CPU space +diff --git a/arch/x86/mm/ioremap.c b/arch/x86/mm/ioremap.c +index c63a545ec199..24e0920a9b25 100644 +--- a/arch/x86/mm/ioremap.c ++++ b/arch/x86/mm/ioremap.c +@@ -131,7 +131,8 @@ static void __ioremap_check_mem(resource_size_t addr, unsigned long size, + * caller shouldn't need to know that small detail. + */ + static void __iomem *__ioremap_caller(resource_size_t phys_addr, +- unsigned long size, enum page_cache_mode pcm, void *caller) ++ unsigned long size, enum page_cache_mode pcm, ++ void *caller, bool encrypted) + { + unsigned long offset, vaddr; + resource_size_t last_addr; +@@ -199,7 +200,7 @@ static void __iomem *__ioremap_caller(resource_size_t phys_addr, + * resulting mapping. + */ + prot = PAGE_KERNEL_IO; +- if (sev_active() && mem_flags.desc_other) ++ if ((sev_active() && mem_flags.desc_other) || encrypted) + prot = pgprot_encrypted(prot); + + switch (pcm) { +@@ -291,7 +292,7 @@ void __iomem *ioremap_nocache(resource_size_t phys_addr, unsigned long size) + enum page_cache_mode pcm = _PAGE_CACHE_MODE_UC_MINUS; + + return __ioremap_caller(phys_addr, size, pcm, +- __builtin_return_address(0)); ++ __builtin_return_address(0), false); + } + EXPORT_SYMBOL(ioremap_nocache); + +@@ -324,7 +325,7 @@ void __iomem *ioremap_uc(resource_size_t phys_addr, unsigned long size) + enum page_cache_mode pcm = _PAGE_CACHE_MODE_UC; + + return __ioremap_caller(phys_addr, size, pcm, +- __builtin_return_address(0)); ++ __builtin_return_address(0), false); + } + EXPORT_SYMBOL_GPL(ioremap_uc); + +@@ -341,7 +342,7 @@ EXPORT_SYMBOL_GPL(ioremap_uc); + void __iomem *ioremap_wc(resource_size_t phys_addr, unsigned long size) + { + return __ioremap_caller(phys_addr, size, _PAGE_CACHE_MODE_WC, +- __builtin_return_address(0)); ++ __builtin_return_address(0), false); + } + EXPORT_SYMBOL(ioremap_wc); + +@@ -358,14 +359,21 @@ EXPORT_SYMBOL(ioremap_wc); + void __iomem *ioremap_wt(resource_size_t phys_addr, unsigned long size) + { + return __ioremap_caller(phys_addr, size, _PAGE_CACHE_MODE_WT, +- __builtin_return_address(0)); ++ __builtin_return_address(0), false); + } + EXPORT_SYMBOL(ioremap_wt); + ++void __iomem *ioremap_encrypted(resource_size_t phys_addr, unsigned long size) ++{ ++ return __ioremap_caller(phys_addr, size, _PAGE_CACHE_MODE_WB, ++ __builtin_return_address(0), true); ++} ++EXPORT_SYMBOL(ioremap_encrypted); ++ + void __iomem *ioremap_cache(resource_size_t phys_addr, unsigned long size) + { + return __ioremap_caller(phys_addr, size, _PAGE_CACHE_MODE_WB, +- __builtin_return_address(0)); ++ __builtin_return_address(0), false); + } + EXPORT_SYMBOL(ioremap_cache); + +@@ -374,7 +382,7 @@ void __iomem *ioremap_prot(resource_size_t phys_addr, unsigned long size, + { + return __ioremap_caller(phys_addr, size, + pgprot2cachemode(__pgprot(prot_val)), +- __builtin_return_address(0)); ++ __builtin_return_address(0), false); + } + EXPORT_SYMBOL(ioremap_prot); + +-- +2.16.4 + diff --git a/patches.suse/x86-kdump-Export-the-SME-mask-to-vmcoreinfo.patch b/patches.suse/x86-kdump-Export-the-SME-mask-to-vmcoreinfo.patch new file mode 100644 index 0000000..4247a48 --- /dev/null +++ b/patches.suse/x86-kdump-Export-the-SME-mask-to-vmcoreinfo.patch @@ -0,0 +1,64 @@ +From 65f750e5457aef9a8085a99d613fea0430303e93 Mon Sep 17 00:00:00 2001 +From: Lianbo Jiang +Date: Thu, 10 Jan 2019 20:19:44 +0800 +Subject: [PATCH] x86/kdump: Export the SME mask to vmcoreinfo +References: bsc#1141895 +Git-commit: 65f750e5457aef9a8085a99d613fea0430303e93 +Patch-mainline: v5.1-rc1 + +On AMD SME machines, makedumpfile tools need to know whether the crashed +kernel was encrypted. + +If SME is enabled in the first kernel, the crashed kernel's page table +entries (pgd/pud/pmd/pte) contain the memory encryption mask which +makedumpfile needs to remove in order to obtain the true physical +address. + +Export that mask in a vmcoreinfo variable. + + [ bp: Massage commit message and move define at the end of the + function. ] + +Signed-off-by: Lianbo Jiang +Signed-off-by: Borislav Petkov +Cc: "H. Peter Anvin" +Cc: Andrew Morton +Cc: Baoquan He +Cc: Dave Young +Cc: Ingo Molnar +Cc: Thomas Gleixner +Cc: Tom Lendacky +Cc: anderson@redhat.com +Cc: k-hagio@ab.jp.nec.com +Cc: kexec@lists.infradead.org +Cc: linux-doc@vger.kernel.org +Cc: x86-ml +Link: https://lkml.kernel.org/r/20190110121944.6050-3-lijiang@redhat.com +--- + arch/x86/kernel/machine_kexec_64.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/arch/x86/kernel/machine_kexec_64.c b/arch/x86/kernel/machine_kexec_64.c +index 4c8acdfdc5a7..ceba408ea982 100644 +--- a/arch/x86/kernel/machine_kexec_64.c ++++ b/arch/x86/kernel/machine_kexec_64.c +@@ -352,6 +352,8 @@ void machine_kexec(struct kimage *image) + + void arch_crash_save_vmcoreinfo(void) + { ++ u64 sme_mask = sme_me_mask; ++ + VMCOREINFO_NUMBER(phys_base); + VMCOREINFO_SYMBOL(init_top_pgt); + +@@ -364,6 +366,7 @@ void arch_crash_save_vmcoreinfo(void) + vmcoreinfo_append_str("KERNELOFFSET=%lx\n", + kaslr_offset()); + VMCOREINFO_NUMBER(KERNEL_IMAGE_SIZE); ++ VMCOREINFO_NUMBER(sme_mask); + } + + /* arch-dependent functionality related to kexec file-based syscall */ +-- +2.16.4 + diff --git a/patches.suse/x86-mce-amd-fix-kobject-lifetime.patch b/patches.suse/x86-mce-amd-fix-kobject-lifetime.patch new file mode 100644 index 0000000..41ff520 --- /dev/null +++ b/patches.suse/x86-mce-amd-fix-kobject-lifetime.patch @@ -0,0 +1,86 @@ +From: Thomas Gleixner +Date: Thu, 13 Feb 2020 19:01:34 +0100 +Subject: x86/mce/amd: Fix kobject lifetime +Git-commit: 51dede9c05df2b78acd6dcf6a17d21f0877d2d7b +Patch-mainline: v5.6-rc3 +References: bsc#1114279 + +Accessing the MCA thresholding controls in sysfs concurrently with CPU +hotplug can lead to a couple of KASAN-reported issues: + + BUG: KASAN: use-after-free in sysfs_file_ops+0x155/0x180 + Read of size 8 at addr ffff888367578940 by task grep/4019 + +and + + BUG: KASAN: use-after-free in show_error_count+0x15c/0x180 + Read of size 2 at addr ffff888368a05514 by task grep/4454 + +for example. Both result from the fact that the threshold block +creation/teardown code frees the descriptor memory itself instead of +defining proper ->release function and leaving it to the driver core to +take care of that, after all sysfs accesses have completed. + +Do that and get rid of the custom freeing code, fixing the above UAFs in +the process. + + [ bp: write commit message. ] + +Fixes: 95268664390b ("[PATCH] x86_64: mce_amd support for family 0x10 processors") +Signed-off-by: Thomas Gleixner +Signed-off-by: Borislav Petkov +Cc: +Link: https://lkml.kernel.org/r/20200214082801.13836-1-bp@alien8.de +--- + arch/x86/kernel/cpu/mcheck/mce_amd.c | 17 +++++++++++------ + 1 file changed, 11 insertions(+), 6 deletions(-) + +diff --git a/arch/x86/kernel/cpu/mcheck/mce_amd.c b/arch/x86/kernel/cpu/mcheck/mce_amd.c +index e7313e5c497c..52de616a8065 100644 +--- a/arch/x86/kernel/cpu/mcheck/mce_amd.c ++++ b/arch/x86/kernel/cpu/mcheck/mce_amd.c +@@ -1163,9 +1163,12 @@ static const struct sysfs_ops threshold_ops = { + .store = store, + }; + ++static void threshold_block_release(struct kobject *kobj); ++ + static struct kobj_type threshold_ktype = { + .sysfs_ops = &threshold_ops, + .default_attrs = default_attrs, ++ .release = threshold_block_release, + }; + + static const char *get_name(unsigned int bank, struct threshold_block *b) +@@ -1367,8 +1370,12 @@ static int threshold_create_bank(unsigned int cpu, unsigned int bank) + return err; + } + +-static void deallocate_threshold_block(unsigned int cpu, +- unsigned int bank) ++static void threshold_block_release(struct kobject *kobj) ++{ ++ kfree(to_block(kobj)); ++} ++ ++static void deallocate_threshold_block(unsigned int cpu, unsigned int bank) + { + struct threshold_block *pos = NULL; + struct threshold_block *tmp = NULL; +@@ -1378,13 +1385,11 @@ static void deallocate_threshold_block(unsigned int cpu, + return; + + list_for_each_entry_safe(pos, tmp, &head->blocks->miscj, miscj) { +- kobject_put(&pos->kobj); + list_del(&pos->miscj); +- kfree(pos); ++ kobject_put(&pos->kobj); + } + +- kfree(per_cpu(threshold_banks, cpu)[bank]->blocks); +- per_cpu(threshold_banks, cpu)[bank]->blocks = NULL; ++ kobject_put(&head->blocks->kobj); + } + + static void __threshold_remove_blocks(struct threshold_bank *b) + diff --git a/patches.suse/x86-mce-amd-publish-the-bank-pointer-only-after-setup-has-succeeded.patch b/patches.suse/x86-mce-amd-publish-the-bank-pointer-only-after-setup-has-succeeded.patch new file mode 100644 index 0000000..3c61dc7 --- /dev/null +++ b/patches.suse/x86-mce-amd-publish-the-bank-pointer-only-after-setup-has-succeeded.patch @@ -0,0 +1,100 @@ +From: Borislav Petkov +Date: Tue, 4 Feb 2020 13:28:41 +0100 +Subject: x86/mce/amd: Publish the bank pointer only after setup has succeeded +Git-commit: 6e5cf31fbe651bed7ba1df768f2e123531132417 +Patch-mainline: v5.6-rc3 +References: bsc#1114279 + +threshold_create_bank() creates a bank descriptor per MCA error +thresholding counter which can be controlled over sysfs. It publishes +the pointer to that bank in a per-CPU variable and then goes on to +create additional thresholding blocks if the bank has such. + +However, that creation of additional blocks in +allocate_threshold_blocks() can fail, leading to a use-after-free +through the per-CPU pointer. + +Therefore, publish that pointer only after all blocks have been setup +successfully. + +Fixes: 019f34fccfd5 ("x86, MCE, AMD: Move shared bank to node descriptor") +Reported-by: Saar Amar +Reported-by: Dan Carpenter +Signed-off-by: Borislav Petkov +Cc: +Link: http://lkml.kernel.org/r/20200128140846.phctkvx5btiexvbx@kili.mountain +--- + arch/x86/kernel/cpu/mcheck/mce_amd.c | 33 ++++++++++++++++----------------- + 1 file changed, 16 insertions(+), 17 deletions(-) + +--- a/arch/x86/kernel/cpu/mcheck/mce_amd.c ++++ b/arch/x86/kernel/cpu/mcheck/mce_amd.c +@@ -1133,8 +1133,9 @@ static const char *get_name(unsigned int + return buf_mcatype; + } + +-static int allocate_threshold_blocks(unsigned int cpu, unsigned int bank, +- unsigned int block, u32 address) ++static int allocate_threshold_blocks(unsigned int cpu, struct threshold_bank *tb, ++ unsigned int bank, unsigned int block, ++ u32 address) + { + struct threshold_block *b = NULL; + u32 low, high; +@@ -1178,16 +1179,12 @@ static int allocate_threshold_blocks(uns + + INIT_LIST_HEAD(&b->miscj); + +- if (per_cpu(threshold_banks, cpu)[bank]->blocks) { +- list_add(&b->miscj, +- &per_cpu(threshold_banks, cpu)[bank]->blocks->miscj); +- } else { +- per_cpu(threshold_banks, cpu)[bank]->blocks = b; +- } ++ if (tb->blocks) ++ list_add(&b->miscj, &tb->blocks->miscj); ++ else ++ tb->blocks = b; + +- err = kobject_init_and_add(&b->kobj, &threshold_ktype, +- per_cpu(threshold_banks, cpu)[bank]->kobj, +- get_name(bank, b)); ++ err = kobject_init_and_add(&b->kobj, &threshold_ktype, tb->kobj, get_name(bank, b)); + if (err) + goto out_free; + recurse: +@@ -1195,7 +1192,7 @@ recurse: + if (!address) + return 0; + +- err = allocate_threshold_blocks(cpu, bank, block, address); ++ err = allocate_threshold_blocks(cpu, tb, bank, block, address); + if (err) + goto out_free; + +@@ -1280,8 +1277,6 @@ static int threshold_create_bank(unsigne + goto out_free; + } + +- per_cpu(threshold_banks, cpu)[bank] = b; +- + if (is_shared_bank(bank)) { + atomic_set(&b->cpus, 1); + +@@ -1292,9 +1287,13 @@ static int threshold_create_bank(unsigne + } + } + +- err = allocate_threshold_blocks(cpu, bank, 0, msr_ops.misc(bank)); +- if (!err) +- goto out; ++ err = allocate_threshold_blocks(cpu, b, bank, 0, msr_ops.misc(bank)); ++ if (err) ++ goto out_free; ++ ++ per_cpu(threshold_banks, cpu)[bank] = b; ++ ++ return 0; + + out_free: + kfree(b); diff --git a/patches.suse/x86-mce-fix-logic-and-comments-around-msr_ppin_ctl.patch b/patches.suse/x86-mce-fix-logic-and-comments-around-msr_ppin_ctl.patch new file mode 100644 index 0000000..fde009a --- /dev/null +++ b/patches.suse/x86-mce-fix-logic-and-comments-around-msr_ppin_ctl.patch @@ -0,0 +1,65 @@ +From: Tony Luck +Date: Tue, 25 Feb 2020 17:17:37 -0800 +Subject: x86/mce: Fix logic and comments around MSR_PPIN_CTL +Git-commit: 59b5809655bdafb0767d3fd00a3e41711aab07e6 +Patch-mainline: v5.6-rc6 +References: bsc#1114279 + +There are two implemented bits in the PPIN_CTL MSR: + +Bit 0: LockOut (R/WO) + Set 1 to prevent further writes to MSR_PPIN_CTL. + +Bit 1: Enable_PPIN (R/W) + If 1, enables MSR_PPIN to be accessible using RDMSR. + If 0, an attempt to read MSR_PPIN will cause #GP. + +So there are four defined values: + 0: PPIN is disabled, PPIN_CTL may be updated + 1: PPIN is disabled. PPIN_CTL is locked against updates + 2: PPIN is enabled. PPIN_CTL may be updated + 3: PPIN is enabled. PPIN_CTL is locked against updates + +Code would only enable the X86_FEATURE_INTEL_PPIN feature for case "2". +When it should have done so for both case "2" and case "3". + +Fix the final test to just check for the enable bit. Also fix some of +the other comments in this function. + +Fixes: 3f5a7896a509 ("x86/mce: Include the PPIN in MCE records when available") +Signed-off-by: Tony Luck +Signed-off-by: Borislav Petkov +Cc: +Link: https://lkml.kernel.org/r/20200226011737.9958-1-tony.luck@intel.com +--- + arch/x86/kernel/cpu/mcheck/mce_intel.c | 9 +++++---- + 1 file changed, 5 insertions(+), 4 deletions(-) + +diff --git a/arch/x86/kernel/cpu/mcheck/mce_intel.c b/arch/x86/kernel/cpu/mcheck/mce_intel.c +index 5627b1091b85..f996ffb887bc 100644 +--- a/arch/x86/kernel/cpu/mcheck/mce_intel.c ++++ b/arch/x86/kernel/cpu/mcheck/mce_intel.c +@@ -493,17 +493,18 @@ static void intel_ppin_init(struct cpuinfo_x86 *c) + return; + + if ((val & 3UL) == 1UL) { +- /* PPIN available but disabled: */ ++ /* PPIN locked in disabled mode */ + return; + } + +- /* If PPIN is disabled, but not locked, try to enable: */ +- if (!(val & 3UL)) { ++ /* If PPIN is disabled, try to enable */ ++ if (!(val & 2UL)) { + wrmsrl_safe(MSR_PPIN_CTL, val | 2UL); + rdmsrl_safe(MSR_PPIN_CTL, &val); + } + +- if ((val & 3UL) == 2UL) ++ /* Is the enable bit set? */ ++ if (val & 2UL) + set_cpu_cap(c, X86_FEATURE_INTEL_PPIN); + } + } + diff --git a/patches.suse/x86-mm-split-vmalloc_sync_all.patch b/patches.suse/x86-mm-split-vmalloc_sync_all.patch new file mode 100644 index 0000000..5a08b69 --- /dev/null +++ b/patches.suse/x86-mm-split-vmalloc_sync_all.patch @@ -0,0 +1,202 @@ +From: Joerg Roedel +Subject: x86/mm: Split vmalloc_sync_all() +Patch-mainline: v5.6-rc7 +Git-commit: 763802b53a427ed3cbd419dbba255c414fdd9e7c +References: bsc#1165741 + +Commit 3f8fd02b1bf1 ("mm/vmalloc: Sync unmappings in +__purge_vmap_area_lazy()") introduced a call to vmalloc_sync_all() in the +vunmap() code-path. While this change was necessary to maintain +correctness on x86-32-pae kernels, it also adds additional cycles for +architectures that don't need it. + +Specifically on x86-64 with CONFIG_VMAP_STACK=y some people reported +severe performance regressions in micro-benchmarks because it now also +calls the x86-64 implementation of vmalloc_sync_all() on vunmap(). But +the vmalloc_sync_all() implementation on x86-64 is only needed for newly +created mappings. + +To avoid the unnecessary work on x86-64 and to gain the performance back, +split up vmalloc_sync_all() into two functions: + + * vmalloc_sync_mappings(), and + * vmalloc_sync_unmappings() + +Most call-sites to vmalloc_sync_all() only care about new mappings being +synchronized. The only exception is the new call-site added in the above +mentioned commit. + +Shile Zhang directed us to a report of an 80% regression in reaim +throughput. + +Link: http://lkml.kernel.org/r/20191009124418.8286-1-joro@8bytes.org +Link: https://lists.01.org/hyperkitty/list/lkp@lists.01.org/thread/4D3JPPHBNOSPFK2KEPC6KGKS6J25AIDB/ +Link: http://lkml.kernel.org/r/20191113095530.228959-1-shile.zhang@linux.alibaba.com +Fixes: 3f8fd02b1bf1 ("mm/vmalloc: Sync unmappings in __purge_vmap_area_lazy()") +Signed-off-by: Joerg Roedel +Reported-by: kernel test robot +Reported-by: Shile Zhang +Acked-by: Rafael J. Wysocki [GHES] +Tested-by: Borislav Petkov +Cc: Dave Hansen +Cc: Andy Lutomirski +Cc: Peter Zijlstra +Cc: Thomas Gleixner +Cc: Ingo Molnar +Cc: +Signed-off-by: Andrew Morton +Signed-off-by: Michal Hocko + +--- + + arch/x86/mm/fault.c | 26 ++++++++++++++++++++++++-- + drivers/acpi/apei/ghes.c | 2 +- + include/linux/vmalloc.h | 5 +++-- + kernel/notifier.c | 2 +- + mm/nommu.c | 10 +++++++--- + mm/vmalloc.c | 11 +++++++---- + 6 files changed, 43 insertions(+), 13 deletions(-) + +--- a/arch/x86/mm/fault.c ++++ b/arch/x86/mm/fault.c +@@ -271,7 +271,7 @@ static inline pmd_t *vmalloc_sync_one(pg + return pmd_k; + } + +-void vmalloc_sync_all(void) ++static void vmalloc_sync(void) + { + unsigned long address; + +@@ -298,6 +298,16 @@ void vmalloc_sync_all(void) + } + } + ++void vmalloc_sync_mappings(void) ++{ ++ vmalloc_sync(); ++} ++ ++void vmalloc_sync_unmappings(void) ++{ ++ vmalloc_sync(); ++} ++ + /* + * 32-bit: + * +@@ -400,11 +410,23 @@ out: + + #else /* CONFIG_X86_64: */ + +-void vmalloc_sync_all(void) ++void vmalloc_sync_mappings(void) + { ++ /* ++ * 64-bit mappings might allocate new p4d/pud pages ++ * that need to be propagated to all tasks' PGDs. ++ */ + sync_global_pgds(VMALLOC_START & PGDIR_MASK, VMALLOC_END); + } + ++void vmalloc_sync_unmappings(void) ++{ ++ /* ++ * Unmappings never allocate or free p4d/pud pages. ++ * No work is required here. ++ */ ++} ++ + /* + * 64-bit: + * +--- a/drivers/acpi/apei/ghes.c ++++ b/drivers/acpi/apei/ghes.c +@@ -201,7 +201,7 @@ static int ghes_estatus_pool_expand(unsi + * New allocation must be visible in all pgd before it can be found by + * an NMI allocating from the pool. + */ +- vmalloc_sync_all(); ++ vmalloc_sync_mappings(); + + return gen_pool_add(ghes_estatus_pool, addr, PAGE_ALIGN(len), -1); + } +--- a/include/linux/vmalloc.h ++++ b/include/linux/vmalloc.h +@@ -105,8 +105,9 @@ extern int remap_vmalloc_range_partial(s + + extern int remap_vmalloc_range(struct vm_area_struct *vma, void *addr, + unsigned long pgoff); +-void vmalloc_sync_all(void); +- ++void vmalloc_sync_mappings(void); ++void vmalloc_sync_unmappings(void); ++ + /* + * Lowlevel-APIs (not for driver use!) + */ +--- a/kernel/notifier.c ++++ b/kernel/notifier.c +@@ -552,7 +552,7 @@ NOKPROBE_SYMBOL(notify_die); + + int register_die_notifier(struct notifier_block *nb) + { +- vmalloc_sync_all(); ++ vmalloc_sync_mappings(); + return atomic_notifier_chain_register(&die_chain, nb); + } + EXPORT_SYMBOL_GPL(register_die_notifier); +--- a/mm/nommu.c ++++ b/mm/nommu.c +@@ -450,10 +450,14 @@ void vm_unmap_aliases(void) + EXPORT_SYMBOL_GPL(vm_unmap_aliases); + + /* +- * Implement a stub for vmalloc_sync_all() if the architecture chose not to +- * have one. ++ * Implement a stub for vmalloc_sync_[un]mapping() if the architecture ++ * chose not to have one. + */ +-void __weak vmalloc_sync_all(void) ++void __weak vmalloc_sync_mappings(void) ++{ ++} ++ ++void __weak vmalloc_sync_unmappings(void) + { + } + +--- a/mm/vmalloc.c ++++ b/mm/vmalloc.c +@@ -1764,7 +1764,7 @@ void *__vmalloc_node_range(unsigned long + * First make sure the mappings are removed from all page-tables + * before they are freed. + */ +- vmalloc_sync_all(); ++ vmalloc_sync_unmappings(); + + /* + * In this function, newly allocated vm_struct has VM_UNINITIALIZED +@@ -2309,16 +2309,19 @@ int remap_vmalloc_range(struct vm_area_s + EXPORT_SYMBOL(remap_vmalloc_range); + + /* +- * Implement a stub for vmalloc_sync_all() if the architecture chose not to +- * have one. ++ * Implement stubs for vmalloc_sync_[un]mappings () if the architecture chose ++ * not to have one. + * + * The purpose of this function is to make sure the vmalloc area + * mappings are identical in all page-tables in the system. + */ +-void __weak vmalloc_sync_all(void) ++void __weak vmalloc_sync_mappings(void) + { + } + ++void __weak vmalloc_sync_unmappings(void) ++{ ++} + + static int f(pte_t *pte, pgtable_t table, unsigned long addr, void *data) + { diff --git a/patches.suse/x86-pkeys-manually-set-x86_feature_ospke-to-preserve-existing-changes.patch b/patches.suse/x86-pkeys-manually-set-x86_feature_ospke-to-preserve-existing-changes.patch new file mode 100644 index 0000000..426b6d0 --- /dev/null +++ b/patches.suse/x86-pkeys-manually-set-x86_feature_ospke-to-preserve-existing-changes.patch @@ -0,0 +1,55 @@ +From: Sean Christopherson +Date: Wed, 26 Feb 2020 15:16:15 -0800 +Subject: x86/pkeys: Manually set X86_FEATURE_OSPKE to preserve existing changes +Git-commit: 735a6dd02222d8d070c7bb748f25895239ca8c92 +Patch-mainline: v5.6-rc5 +References: bsc#1114279 + +Explicitly set X86_FEATURE_OSPKE via set_cpu_cap() instead of calling +get_cpu_cap() to pull the feature bit from CPUID after enabling CR4.PKE. +Invoking get_cpu_cap() effectively wipes out any {set,clear}_cpu_cap() +changes that were made between this_cpu->c_init() and setup_pku(), as +all non-synthetic feature words are reinitialized from the CPU's CPUID +values. + +Blasting away capability updates manifests most visibility when running +on a VMX capable CPU, but with VMX disabled by BIOS. To indicate that +VMX is disabled, init_ia32_feat_ctl() clears X86_FEATURE_VMX, using +clear_cpu_cap() instead of setup_clear_cpu_cap() so that KVM can report +which CPU is misconfigured (KVM needs to probe every CPU anyways). +Restoring X86_FEATURE_VMX from CPUID causes KVM to think VMX is enabled, +ultimately leading to an unexpected #GP when KVM attempts to do VMXON. + +Arguably, init_ia32_feat_ctl() should use setup_clear_cpu_cap() and let +KVM figure out a different way to report the misconfigured CPU, but VMX +is not the only feature bit that is affected, i.e. there is precedent +that tweaking feature bits via {set,clear}_cpu_cap() after ->c_init() +is expected to work. Most notably, x86_init_rdrand()'s clearing of +X86_FEATURE_RDRAND when RDRAND malfunctions is also overwritten. + +Fixes: 0697694564c8 ("x86/mm/pkeys: Actually enable Memory Protection Keys in the CPU") +Reported-by: Jacob Keller +Signed-off-by: Sean Christopherson +Signed-off-by: Borislav Petkov +Acked-by: Dave Hansen +Tested-by: Jacob Keller +Cc: stable@vger.kernel.org +Link: https://lkml.kernel.org/r/20200226231615.13664-1-sean.j.christopherson@intel.com +--- + arch/x86/kernel/cpu/common.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c +index 52c9bfbbdb2a..4cdb123ff66a 100644 +--- a/arch/x86/kernel/cpu/common.c ++++ b/arch/x86/kernel/cpu/common.c +@@ -445,7 +445,7 @@ static __always_inline void setup_pku(struct cpuinfo_x86 *c) + * cpuid bit to be set. We need to ensure that we + * update that bit in this CPU's "cpu_info". + */ +- get_cpu_cap(c); ++ set_cpu_cap(c, X86_FEATURE_OSPKE); + } + + #ifdef CONFIG_X86_INTEL_MEMORY_PROTECTION_KEYS + diff --git a/patches.suse/xfs-also-remove-cached-ACLs-when-removing-the-underl.patch b/patches.suse/xfs-also-remove-cached-ACLs-when-removing-the-underl.patch new file mode 100644 index 0000000..721ae58 --- /dev/null +++ b/patches.suse/xfs-also-remove-cached-ACLs-when-removing-the-underl.patch @@ -0,0 +1,45 @@ +From 8cde9f259c7d91d05b12cc68993a9643d6b4e45f Mon Sep 17 00:00:00 2001 +From: Christoph Hellwig +Date: Tue, 7 Jan 2020 15:25:38 -0800 +Subject: [PATCH] xfs: also remove cached ACLs when removing the underlying + attr +Git-commit: 8cde9f259c7d91d05b12cc68993a9643d6b4e45f +Patch-mainline: v5.6-rc1 +References: bsc#1165873 + +We should not just invalidate the ACL when setting the underlying +attribute, but also when removing it. The ioctl interface gets that +right, but the normal xattr inteface skipped the xfs_forget_acl due +to an early return. + +Signed-off-by: Christoph Hellwig +Reviewed-by: Darrick J. Wong +Signed-off-by: Darrick J. Wong +Acked-by: Anthony Iliopoulos + +--- + fs/xfs/xfs_xattr.c | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +diff --git a/fs/xfs/xfs_xattr.c b/fs/xfs/xfs_xattr.c +index 383f0203d103..2288f20ae282 100644 +--- a/fs/xfs/xfs_xattr.c ++++ b/fs/xfs/xfs_xattr.c +@@ -74,10 +74,11 @@ xfs_xattr_set(const struct xattr_handler *handler, struct dentry *unused, + if (flags & XATTR_REPLACE) + xflags |= ATTR_REPLACE; + +- if (!value) +- return xfs_attr_remove(ip, (unsigned char *)name, xflags); +- error = xfs_attr_set(ip, (unsigned char *)name, ++ if (value) ++ error = xfs_attr_set(ip, (unsigned char *)name, + (void *)value, size, xflags); ++ else ++ error = xfs_attr_remove(ip, (unsigned char *)name, xflags); + if (!error) + xfs_forget_acl(inode, name, xflags); + +-- +2.16.4 + diff --git a/patches.suse/xfs-bulkstat-should-copy-lastip-whenever-userspace-s.patch b/patches.suse/xfs-bulkstat-should-copy-lastip-whenever-userspace-s.patch new file mode 100644 index 0000000..50db15c --- /dev/null +++ b/patches.suse/xfs-bulkstat-should-copy-lastip-whenever-userspace-s.patch @@ -0,0 +1,74 @@ +From f16fe3ecde6237256eeacb3cd582217ffe62c647 Mon Sep 17 00:00:00 2001 +From: "Darrick J. Wong" +Date: Tue, 2 Jul 2019 09:39:39 -0700 +Subject: [PATCH] xfs: bulkstat should copy lastip whenever userspace supplies + one +Git-commit: f16fe3ecde6237256eeacb3cd582217ffe62c647 +Patch-mainline: v5.3-rc1 +References: bsc#1165984 + +When userspace passes in a @lastip pointer we should copy the results +back, even if the @ocount pointer is NULL. + +Signed-off-by: Darrick J. Wong +Reviewed-by: Brian Foster +Acked-by: Anthony Iliopoulos + +--- + fs/xfs/xfs_ioctl.c | 13 ++++++------- + fs/xfs/xfs_ioctl32.c | 13 ++++++------- + 2 files changed, 12 insertions(+), 14 deletions(-) + +diff --git a/fs/xfs/xfs_ioctl.c b/fs/xfs/xfs_ioctl.c +index 7f1732ad6c40..8bc74ae3b72a 100644 +--- a/fs/xfs/xfs_ioctl.c ++++ b/fs/xfs/xfs_ioctl.c +@@ -759,14 +759,13 @@ xfs_ioc_bulkstat( + if (error) + return error; + +- if (bulkreq.ocount != NULL) { +- if (copy_to_user(bulkreq.lastip, &inlast, +- sizeof(xfs_ino_t))) +- return -EFAULT; ++ if (bulkreq.lastip != NULL && ++ copy_to_user(bulkreq.lastip, &inlast, sizeof(xfs_ino_t))) ++ return -EFAULT; + +- if (copy_to_user(bulkreq.ocount, &count, sizeof(count))) +- return -EFAULT; +- } ++ if (bulkreq.ocount != NULL && ++ copy_to_user(bulkreq.ocount, &count, sizeof(count))) ++ return -EFAULT; + + return 0; + } +diff --git a/fs/xfs/xfs_ioctl32.c b/fs/xfs/xfs_ioctl32.c +index d1967fe67472..3c3fb16685b1 100644 +--- a/fs/xfs/xfs_ioctl32.c ++++ b/fs/xfs/xfs_ioctl32.c +@@ -305,14 +305,13 @@ xfs_compat_ioc_bulkstat( + if (error) + return error; + +- if (bulkreq.ocount != NULL) { +- if (copy_to_user(bulkreq.lastip, &inlast, +- sizeof(xfs_ino_t))) +- return -EFAULT; ++ if (bulkreq.lastip != NULL && ++ copy_to_user(bulkreq.lastip, &inlast, sizeof(xfs_ino_t))) ++ return -EFAULT; + +- if (copy_to_user(bulkreq.ocount, &count, sizeof(count))) +- return -EFAULT; +- } ++ if (bulkreq.ocount != NULL && ++ copy_to_user(bulkreq.ocount, &count, sizeof(count))) ++ return -EFAULT; + + return 0; + } +-- +2.16.4 + diff --git a/patches.suse/xhci-Force-Maximum-Packet-size-for-Full-speed-bulk-d.patch b/patches.suse/xhci-Force-Maximum-Packet-size-for-Full-speed-bulk-d.patch new file mode 100644 index 0000000..45efb58 --- /dev/null +++ b/patches.suse/xhci-Force-Maximum-Packet-size-for-Full-speed-bulk-d.patch @@ -0,0 +1,56 @@ +From f148b9f402ef002b57bcff3964d45abc8ffb6c3f Mon Sep 17 00:00:00 2001 +From: Mathias Nyman +Date: Mon, 10 Feb 2020 15:45:50 +0200 +Subject: [PATCH] xhci: Force Maximum Packet size for Full-speed bulk devices to valid range. +Git-commit: f148b9f402ef002b57bcff3964d45abc8ffb6c3f +Patch-mainline: v5.6-rc3 +References: bsc#1051510 + +A Full-speed bulk USB audio device (DJ-Tech CTRL) with a invalid Maximum +Packet Size of 4 causes a xHC "Parameter Error" at enumeration. + +This is because valid Maximum packet sizes for Full-speed bulk endpoints +are 8, 16, 32 and 64 bytes. Hosts are not required to support other values +than these. See usb 2 specs section 5.8.3 for details. + +The device starts working after forcing the maximum packet size to 8. +This is most likely the case with other devices as well, so force the +maximum packet size to a valid range. + +Cc: stable@vger.kernel.org +Reported-by: Rene D Obermueller +Signed-off-by: Mathias Nyman +Link: https://lore.kernel.org/r/20200210134553.9144-2-mathias.nyman@linux.intel.com +Signed-off-by: Greg Kroah-Hartman +Acked-by: Takashi Iwai + +--- + drivers/usb/host/xhci-mem.c | 12 +++++++++--- + 1 file changed, 9 insertions(+), 3 deletions(-) + +diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c +index 3b1388fa2f36..0e2701649369 100644 +--- a/drivers/usb/host/xhci-mem.c ++++ b/drivers/usb/host/xhci-mem.c +@@ -1475,9 +1475,15 @@ int xhci_endpoint_init(struct xhci_hcd *xhci, + /* Allow 3 retries for everything but isoc, set CErr = 3 */ + if (!usb_endpoint_xfer_isoc(&ep->desc)) + err_count = 3; +- /* Some devices get this wrong */ +- if (usb_endpoint_xfer_bulk(&ep->desc) && udev->speed == USB_SPEED_HIGH) +- max_packet = 512; ++ /* HS bulk max packet should be 512, FS bulk supports 8, 16, 32 or 64 */ ++ if (usb_endpoint_xfer_bulk(&ep->desc)) { ++ if (udev->speed == USB_SPEED_HIGH) ++ max_packet = 512; ++ if (udev->speed == USB_SPEED_FULL) { ++ max_packet = rounddown_pow_of_two(max_packet); ++ max_packet = clamp_val(max_packet, 8, 64); ++ } ++ } + /* xHCI 1.0 and 1.1 indicates that ctrl ep avg TRB Length should be 8 */ + if (usb_endpoint_xfer_control(&ep->desc) && xhci->hci_version >= 0x100) + avg_trb_len = 8; +-- +2.16.4 + diff --git a/patches.suse/xhci-fix-runtime-pm-enabling-for-quirky-Intel-hosts.patch b/patches.suse/xhci-fix-runtime-pm-enabling-for-quirky-Intel-hosts.patch new file mode 100644 index 0000000..831b5f2 --- /dev/null +++ b/patches.suse/xhci-fix-runtime-pm-enabling-for-quirky-Intel-hosts.patch @@ -0,0 +1,60 @@ +From 024d411e9c5d49eb96c825af52a3ce2682895676 Mon Sep 17 00:00:00 2001 +From: Mathias Nyman +Date: Mon, 10 Feb 2020 15:45:52 +0200 +Subject: [PATCH] xhci: fix runtime pm enabling for quirky Intel hosts +Git-commit: 024d411e9c5d49eb96c825af52a3ce2682895676 +Patch-mainline: v5.6-rc3 +References: bsc#1051510 + +Intel hosts that need the XHCI_PME_STUCK_QUIRK flag should enable +runtime pm by calling xhci_pme_acpi_rtd3_enable() before +usb_hcd_pci_probe() calls pci_dev_run_wake(). +Otherwise usage count for the device won't be decreased, and runtime +suspend is prevented. + +usb_hcd_pci_probe() only decreases the usage count if device can +generate run-time wake-up events, i.e. when pci_dev_run_wake() +returns true. + +This issue was exposed by pci_dev_run_wake() change in +commit 8feaec33b986 ("PCI / PM: Always check PME wakeup capability for +runtime wakeup support") +and should be backported to kernels with that change + +Cc: # 4.13+ +Signed-off-by: Mathias Nyman +Link: https://lore.kernel.org/r/20200210134553.9144-4-mathias.nyman@linux.intel.com +Signed-off-by: Greg Kroah-Hartman +Acked-by: Takashi Iwai + +--- + drivers/usb/host/xhci-pci.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c +index 4917c5b033fa..da7c2db41671 100644 +--- a/drivers/usb/host/xhci-pci.c ++++ b/drivers/usb/host/xhci-pci.c +@@ -302,6 +302,9 @@ static int xhci_pci_setup(struct usb_hcd *hcd) + if (!usb_hcd_is_primary_hcd(hcd)) + return 0; + ++ if (xhci->quirks & XHCI_PME_STUCK_QUIRK) ++ xhci_pme_acpi_rtd3_enable(pdev); ++ + xhci_dbg(xhci, "Got SBRN %u\n", (unsigned int) xhci->sbrn); + + /* Find any debug ports */ +@@ -359,9 +362,6 @@ static int xhci_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) + HCC_MAX_PSA(xhci->hcc_params) >= 4) + xhci->shared_hcd->can_do_streams = 1; + +- if (xhci->quirks & XHCI_PME_STUCK_QUIRK) +- xhci_pme_acpi_rtd3_enable(dev); +- + /* USB-2 and USB-3 roothubs initialized, allow runtime pm suspend */ + pm_runtime_put_noidle(&dev->dev); + +-- +2.16.4 + diff --git a/scripts/git_sort/git_sort.py b/scripts/git_sort/git_sort.py index b1d5af1..7558516 100755 --- a/scripts/git_sort/git_sort.py +++ b/scripts/git_sort/git_sort.py @@ -246,6 +246,11 @@ remotes = ( Head(RepoURL("git://git.infradead.org/users/hch/dma-mapping.git"), "for-next"), Head(RepoURL("thermal/linux.git"), "thermal/linux-next"), Head(RepoURL("git://github.com/cminyard/linux-ipmi.git"), "for-next"), + Head(RepoURL("ras/ras.git"), "edac-for-next"), + Head(RepoURL("linusw/linux-pinctrl.git"), "for-next"), + Head(RepoURL("efi/efi.git"), "next"), + Head(RepoURL("ulfh/mmc.git"), "next"), + Head(RepoURL("masahiroy/linux-kbuild.git"), "for-next"), ) diff --git a/scripts/supported-conf-fixup b/scripts/supported-conf-fixup index e7c7144..7f0b4b5 100755 --- a/scripts/supported-conf-fixup +++ b/scripts/supported-conf-fixup @@ -172,7 +172,7 @@ while () { s/#.*$//; # Strip comments s/\s+$//; # Strip trailing whitespace next if m/^$/; # Skip blank lines - s/^([+-]([\w\d]+)?\s)*\s*//; # Strip guards + s/^([+-]([\w\d-]+)?\s)*\s*//; # Strip guards my $new_entry = { 'line' => $., @@ -368,8 +368,8 @@ sub modcmp $mod2 =~ s/\s*#.*$//mg; # Strip comments $mod1 =~ s/\n//g; # Strip empty lines $mod2 =~ s/\n//g; # Strip empty lines - $mod1 =~ s/^([+-]([\w\d]+)?\s)*\s*//; # Strip guards - $mod2 =~ s/^([+-]([\w\d]+)?\s)*\s*//; # Strip guards + $mod1 =~ s/^([+-]([\w\d-]+)?\s)*\s*//; # Strip guards + $mod2 =~ s/^([+-]([\w\d-]+)?\s)*\s*//; # Strip guards # Masks must always go after explict module names they match return 1 if $mod1 =~ m/^(.*)\/\*$/ && substr($mod2, 0, length($1)) eq $1; diff --git a/series.conf b/series.conf index 5f58f31..d5c149e 100644 --- a/series.conf +++ b/series.conf @@ -1410,6 +1410,7 @@ patches.suse/0038-staging-fsl-mc-dpio-Propagate-error-code.patch patches.suse/0039-staging-fsl-dpaa2-eth-fix-a-couple-of-implicit-inclu.patch patches.suse/0040-staging-fsl-mc-drop-macros-with-possible-side-effect.patch + patches.suse/0001-staging-ccree-use-signal-safe-completion-wait.patch patches.suse/staging-rtl8188eu-style-fixes.patch patches.suse/0009-iio-adc-ina2xx-Make-use-of-attribute-flags-consisten.patch patches.suse/0011-iio-adc-Fix-integration-time-averaging-for-INA219-22.patch @@ -2940,6 +2941,7 @@ patches.suse/btrfs-use-bio_clone_bioset_partial-to-simplify-DIO-s.patch patches.suse/btrfs-change-how-we-iterate-bios-in-endio.patch patches.suse/Btrfs-work-around-maybe-uninitialized-warning.patch + patches.suse/btrfs-cleanup-root-usage-by-btrfs_get_alloc_profile.patch patches.suse/0001-Btrfs-skip-commit-transaction-if-we-don-t-have-enoug.patch patches.suse/btrfs-separate-space_info-create-update.patch patches.suse/btrfs-refactor-update_space_info.patch @@ -3464,6 +3466,8 @@ patches.suse/scsi-cxlflash-18-Avoid-double-free-of-character-device.patch patches.suse/scsi-cxlflash-19-Update-send_tmf-parameters.patch patches.suse/scsi-cxlflash-20-Update-debug-prints-in-reset-handlers.patch + patches.suse/scsi-ibmvscsi-constify-dev_pm_ops-structures.patch + patches.suse/scsi-ibmvfc-constify-dev_pm_ops-structures.patch patches.suse/scsi-hisi_sas-optimise-DMA-slot-memory.patch patches.suse/scsi-lpfc-spin_lock_irq-is-not-nestable.patch patches.suse/scsi-lpfc-don-t-double-count-abort-errors.patch @@ -5880,7 +5884,7 @@ patches.suse/powerpc-mm-hash-Free-the-subpage_prot_table-correctl.patch patches.suse/0001-arm64-atomics-Remove-from-asm-constraint-in-lse-atom.patch patches.suse/0012-perf-Convert-to-using-pOF-instead-of-full_name.patch - patches.suse/0013-perf-qcom_l2-fix-column-exclusion-check.patch + patches.suse/0001-perf-qcom_l2-fix-column-exclusion-check.patch patches.suse/0001-arm64-sysreg-Fix-unprotected-macro-argmuent-in-write.patch patches.suse/0014-drivers-perf-arm_pmu-Request-PMU-SPIs-with-IRQF_PER_.patch patches.suse/KVM-VMX-remove-unused-field.patch @@ -7626,6 +7630,7 @@ patches.suse/exports-from-rcu_idle_exit-and-rcu_idle_enter.patch patches.suse/net-netfilter-nf_conntrack_core-Fix-net_conntrack_lo.patch patches.suse/srcu-Provide-ordering-for-CPU-not-involved-in-grace-.patch + patches.suse/0001-tools-Update-include-uapi-linux-fcntl.h-copy-from-th.patch patches.suse/perf-pmu-events-support-additional-power8-pvr-in-mapfile.patch patches.suse/perf-vendor-events-add-power9-pmu-events.patch patches.suse/perf-vendor-events-add-power9-pvrs-to-mapfile.patch @@ -9935,6 +9940,7 @@ patches.suse/scsi-mptsas-Fixup-device-hotplug-for-VMWare-ESXi.patch patches.suse/scsi-ses-Fix-racy-cleanup-of-sys-in-remove_dev.patch patches.suse/scsi-Fix-the-kerneldoc-for-scsi_initialize_rq.patch + patches.suse/scsi-ibmvfc-ibmvscsi-ibmvscsi_tgt-constify-vio_devic.patch patches.suse/scsi-cxlflash-23-Remove-unnecessary-existence-check.patch patches.suse/scsi-cxlflash-24-Avoid-double-mutex-unlock.patch patches.suse/scsi-cxlflash-25-Fix-vlun-resize-failure-in-the-shrink-.patch @@ -10275,6 +10281,7 @@ patches.suse/0011-btrfs-add-cond_resched-calls-when-resolving-backrefs.patch patches.suse/0012-btrfs-allow-backref-search-checks-for-shared-extents.patch patches.suse/0013-btrfs-clean-up-extraneous-computations-in-add_delaye.patch + patches.suse/btrfs-remove-redundant-argument-of-flush_space.patch patches.suse/btrfs-use-GFP_KERNEL-in-mount-and-remount.patch patches.suse/btrfs-account-for-pinned-bytes-in-should_alloc_chunk.patch patches.suse/btrfs-fix-readdir-deadlock-with-pagefault.patch @@ -10942,6 +10949,7 @@ patches.suse/0022-md-fix-a-race-condition-for-flush-request-handling.patch patches.suse/0023-dm-raid-fix-a-race-condition-in-request-handling.patch patches.suse/0024-md-raid5-cap-worker-count.patch + patches.suse/Btrfs-do-not-reset-bio-bi_ops-while-writing-bio.patch patches.suse/btrfs-clear-ordered-flag-on-cleaning-up-ordered-extents.patch patches.suse/btrfs-finish-ordered-extent-cleaning-if-no-progress-is-found.patch patches.suse/btrfs-fix-null-pointer-dereference-from-free_reloc_roots.patch @@ -12331,6 +12339,8 @@ patches.suse/btrfs-copy-fsid-to-super_block-s_uuid.patch patches.suse/btrfs-Remove-unused-parameters-from-various-function.patch patches.suse/btrfs-remove-redundant-argument-of-_link_block_group.patch + patches.suse/0001-Btrfs-make-plug-in-writing-meta-blocks-really-work.patch + patches.suse/0002-Btrfs-remove-bio_flags-which-indicates-a-meta-block-.patch patches.suse/btrfs-change-how-we-decide-to-commit-transactions-du.patch patches.suse/0001-btrfs-Refactor-check_leaf-function-for-later-expansi.patch patches.suse/0002-btrfs-Check-if-item-pointer-overlaps-with-the-item-i.patch @@ -12343,6 +12353,8 @@ patches.suse/0008-btrfs-tree-checker-Enhance-output-for-check_csum_ite.patch patches.suse/0009-btrfs-tree-checker-Enhance-output-for-check_extent_d.patch patches.suse/0010-btrfs-tree-checker-use-zu-format-string-for-size_t.patch + patches.suse/0003-btrfs-pass-root-to-various-extent-ref-mod-functions.patch + patches.suse/0005-btrfs-only-check-delayed-ref-usage-in-should_end_transaction.patch patches.suse/0001-btrfs-add-a-helper-to-return-a-head-ref.patch patches.suse/0002-btrfs-move-extent_op-cleanup-to-a-helper.patch patches.suse/0003-btrfs-breakout-empty-head-cleanup-to-a-helper.patch @@ -12350,6 +12362,7 @@ patches.suse/0005-btrfs-move-all-ref-head-cleanup-to-the-helper-functi.patch patches.suse/0006-btrfs-remove-delayed_ref_node-from-ref_head.patch patches.suse/0020-btrfs-remove-type-argument-from-comp_tree_refs.patch + patches.suse/0013-btrfs-add-assertions-for-releasing-trans-handle-reservations.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 @@ -12357,6 +12370,7 @@ patches.suse/0021-btrfs-switch-args-for-comp_-_refs.patch patches.suse/0022-btrfs-add-a-comp_refs-helper.patch patches.suse/0001-btrfs-track-refs-in-a-rb_tree-instead-of-a-list.patch + patches.suse/0020-btrfs-don-t-call-btrfs_start_delalloc_roots-in-flushoncommit.patch patches.suse/btrfs-move-btrfs_truncate_block-out-of-trans-handle.patch patches.suse/btrfs-Fix-bug-for-misused-dev_t-when-lookup-in-dev-s.patch patches.suse/jfs-remove-increment-of-i_version-counter.patch @@ -12387,6 +12401,7 @@ patches.suse/fanotify-fix-fsnotify_prepare_user_wait-failure.patch patches.suse/udf-Avoid-overflow-when-session-starts-at-large-offs.patch patches.suse/isofs-fix-timestamps-beyond-2027.patch + patches.suse/configfs-Fix-bool-initialization-comparison.patch patches.suse/configfs-make-ci_type-field-some-pointers-and-functi.patch patches.suse/nullb-make-config_item_type-const.patch patches.suse/nvmet-make-config_item_type-const.patch @@ -12609,6 +12624,7 @@ patches.suse/blk-mq-don-t-allocate-driver-tag-upfront-for-flush-r.patch patches.suse/0001-nbd-wait-uninterruptible-for-the-dead-timeout.patch patches.suse/0001-nbd-don-t-start-req-until-after-the-dead-connection-.patch + patches.suse/blktrace-fix-unlocked-access-to-init-start-stop-tear.patch patches.suse/nvme-move-the-dying-queue-check-from-cancel-to-compl.patch patches.suse/nvme-always-unregister-the-integrity-profile-in-__nv.patch patches.suse/nvme-don-t-pass-struct-nvme_ns-to-nvme_init_integrit.patch @@ -13855,6 +13871,7 @@ patches.suse/mlxsw-spectrum_router-Populate-adjacency-entries-acc.patch patches.suse/mlxsw-spectrum-Increase-number-of-linear-entries.patch patches.suse/mlxsw-spectrum-Add-another-partition-to-KVD-linear.patch + patches.suse/batman-adv-Avoid-spurious-warnings-from-bat_v-neigh_.patch patches.suse/net-hns3-fix-a-bug-when-alloc-new-buffer.patch patches.suse/net-hns3-fix-the-bug-when-map-buffer-fail.patch patches.suse/net-hns3-fix-the-ops-check-in-hns3_get_rxnfc.patch @@ -16140,6 +16157,8 @@ patches.suse/debugfs-convert-to-debugfs_file_get-and-put.patch patches.suse/IB-hfi1-convert-to-debugfs_file_get-and-put.patch patches.suse/debugfs-purge-obsolete-SRCU-based-removal-protection.patch + patches.suse/debugfs-call-debugfs_real_fops-only-after-debugfs_fi.patch + patches.suse/debugfs-defer-debugfs_fsdata-allocation-to-first-usa.patch patches.suse/msft-hv-1506-vmbus-add-per-channel-sysfs-info.patch patches.suse/msft-hv-1519-vmbus-initialize-reserved-fields-in-messages.patch patches.suse/genwqe-Take-R-W-permissions-into-account-when-dealing-with-memory-pages.patch @@ -17989,6 +18008,7 @@ patches.suse/btrfs-bail-out-gracefully-rather-than-bug_on.patch patches.suse/btrfs-move-definition-of-the-function-btrfs_find_new.patch patches.suse/btrfs-fix-reported-number-of-inode-blocks-after-buff.patch + patches.suse/0022-btrfs-clear-space-cache-inode-generation-always.patch patches.suse/0011-btrfs-tree-checker-Fix-false-panic-for-sanity-test.patch patches.suse/btrfs-incremental-send-fix-wrong-unlink-path-after-renaming-file.patch patches.suse/nfsd-Fix-stateid-races-between-OPEN-and-CLOSE.patch @@ -18078,6 +18098,7 @@ patches.suse/0035-bcache-Fix-building-error-on-MIPS.patch patches.suse/0036-bcache-recover-data-from-backing-when-data-is-clean.patch patches.suse/0037-bcache-check-return-value-of-register_shrinker.patch + patches.suse/blktrace-fix-trace-mutex-deadlock.patch patches.suse/nvme-rdma-don-t-suppress-send-completions.patch patches.suse/nvme-rdma-don-t-complete-requests-before-a-send-work.patch patches.suse/nvme-rdma-wait-for-local-invalidation-before-complet.patch @@ -19728,8 +19749,24 @@ patches.suse/update-internal-version-number-for-cifs-ko.patch patches.suse/fs-cifs-cifsacl-c-Fixes-typo-in-a-comment.patch patches.suse/btrfs-fix-memory-barriers-usage-with-device-stats-counters.patch + patches.suse/btrfs-Remove-redundant-mirror_num-arg.patch patches.suse/0012-btrfs-tree-checker-Add-checker-for-dir-item.patch + patches.suse/0001-btrfs-sink-get_extent-parameter-to-extent_writepages.patch + patches.suse/0002-btrfs-sink-get_extent-parameter-to-extent_write_lock.patch + patches.suse/0003-btrfs-sink-get_extent-parameter-to-extent_write_full.patch + patches.suse/0004-btrfs-drop-get_extent-from-extent_page_data.patch + patches.suse/0005-btrfs-sink-get_extent-parameter-to-extent_fiemap.patch + patches.suse/0006-btrfs-sink-get_extent-parameter-to-get_extent_skip_h.patch + patches.suse/0007-btrfs-sink-get_extent-parameter-to-extent_readpages.patch + patches.suse/btrfs-switch-to-on-stack-csum-buffer-in-csum_tree_bl.patch patches.suse/0013-btrfs-tree-checker-use-zu-format-string-for-size_t.patch + patches.suse/0001-btrfs-sink-extent_write_locked_range-tree-parameter.patch + patches.suse/0002-btrfs-sink-extent_write_full_page-tree-argument.patch + patches.suse/0003-btrfs-Rename-bin_search-btrfs_bin_search.patch + patches.suse/0004-btrfs-merge-two-flush_write_bio-helpers.patch + patches.suse/0005-btrfs-sink-flush_fn-to-extent_write_cache_pages.patch + patches.suse/0006-btrfs-sink-writepage-parameter-to-extent_write_cache.patch + patches.suse/0007-btrfs-unify-extent_page_data-type-passed-as-void.patch patches.suse/0001-btrfs-Improve-btrfs_search_slot-description.patch patches.suse/btrfs-add-support-for-fallocate-s-zero-range-operati.patch patches.suse/btrfs-fix-missing-inode-i_size-update-after-zero-ran.patch @@ -19834,7 +19871,7 @@ patches.suse/0026-of-Add-helper-for-mapping-device-node-to-logical-CPU.patch patches.suse/0047-arm_pmu-Use-of_cpu_node_to_id-helper.patch patches.suse/0048-perf-ARM-DynamIQ-Shared-Unit-PMU-support.patch - patches.suse/0001-KVM-arm64-Store-vcpu-on-the-stack-during-__guest_ent.patch + patches.suse/KVM-arm64-Store-vcpu-on-the-stack-during-__guest_ent.patch patches.suse/KVM-arm-arm64-Convert-kvm_host_cpu_state-to-a-static.patch patches.suse/0003-KVM-arm64-Change-hyp_panic-s-dependency-on-tpidr_el2.patch patches.suse/0004-arm64-alternatives-use-tpidr_el2-on-VHE-hosts.patch @@ -19953,7 +19990,7 @@ patches.suse/xfs-allow-xfs_lock_two_inodes-to-take-different-EXCL.patch patches.suse/xfs-only-grab-shared-inode-locks-for-source-file-dur.patch patches.suse/iomap-warn-on-zero-length-mappings.patch - patches.suse/0010-md-introduce-new-personality-funciton-start.patch + patches.suse/0003-md-introduce-new-personality-funciton-start.patch patches.suse/0113-md-raid1-raid10-silence-warning-about-wait-within-wa.patch patches.suse/0114-md-r5cache-print-more-info-of-log-recovery.patch patches.suse/0115-raid5-ppl-PPL-support-for-disks-with-write-back-cach.patch @@ -27214,6 +27251,7 @@ patches.suse/selftests-bpf-Count-tests-skipped-by-unpriv.patch patches.suse/selftests-bpf-Only-run-tests-if-bpf_disabled.patch patches.suse/bpf-Remove-unused-callee_saved-array.patch + patches.suse/bpf-x64-save-several-bytes-by-using-mov-over-movabsq.patch patches.suse/bpf-x64-save-5-bytes-in-prologue-when-ebpf-insns-cam.patch patches.suse/bpf-add-various-jit-test-cases.patch patches.suse/samples-bpf-Add-program-for-CPU-state-statistics.patch @@ -28067,7 +28105,9 @@ patches.suse/xfs-detect-agfl-count-corruption-and-reset-agfl.patch patches.suse/xfs-sanity-check-the-unused-space-before-trying-to-u.patch patches.suse/xfs-catch-inode-allocation-state-mismatch-corruption.patch + patches.suse/btrfs-add-enospc_debug-printing-in-metadata_reserve_bytes.patch patches.suse/btrfs-do-not-check-inode-s-runtime-flags-under-root-orphan_lock.patch + patches.suse/btrfs-remove-btrfs_inode-delayed_iput_count.patch patches.suse/0014-btrfs-tree-checker-Replace-root-parameter-with-fs_in.patch patches.suse/0001-btrfs-qgroup-Fix-root-item-corruption-when-multiple-.patch patches.suse/btrfs-handle-error-from-btrfs_uuid_tree_rem-call-in-btrfs_ioctl_set_received_subvol.patch @@ -29041,6 +29081,7 @@ patches.suse/PCI-PM-Clear-PCIe-PME-Status-bit-in-core-not-PCIe-po.patch patches.suse/PCI-PM-Clear-PCIe-PME-Status-bit-for-Root-Complex-Ev.patch patches.suse/PCI-portdrv-Disable-port-driver-in-compat-mode.patch + patches.suse/PCI-portdrv-Remove-pcie_port_bus_type-link-order-dep.patch patches.suse/0001-PCI-portdrv-Simplify-PCIe-feature-permission-checkin.patch patches.suse/0001-PCI-portdrv-Rename-and-reverse-sense-of-pcie_ports_a.patch patches.suse/PCI-AER-Use-cached-AER-Capability-offset.patch @@ -29111,7 +29152,7 @@ patches.suse/powerpc-mm-slice-remove-radix-calls-to-the-slice-cod.patch patches.suse/cxl-Fix-timebase-synchronization-status-on-P9.patch patches.suse/powerpc-npu-dma.c-Fix-crash-after-__mmu_notifier_reg.patch - patches.suse/0039-lib-raid6-altivec-Add-vpermxor-implementation-for-ra.patch + patches.suse/0004-lib-raid6-altivec-Add-vpermxor-implementation-for-ra.patch patches.suse/0040-lib-raid6-Build-proper-raid6test-files-on-powerpc.patch patches.suse/powerpc-Remove-unused-flush_dcache_phys_range.patch patches.suse/powerpc-Use-feature-bit-for-RTC-presence-rather-than.patch @@ -29144,6 +29185,7 @@ patches.suse/powerpc-pseries-Use-the-security-flags-in-pseries_se.patch patches.suse/powerpc-64s-Wire-up-cpu_show_spectre_v1.patch patches.suse/powerpc-64s-Wire-up-cpu_show_spectre_v2.patch + patches.suse/powerpc-mm-Fix-section-mismatch-warning-in-stop_mach.patch patches.suse/powerpc-lpar-debug-Initialize-flags-before-printing-.patch patches.suse/powerpc-mm-Fix-typo-in-comments.patch patches.suse/powerpc-Add-ppc_breakpoint_available.patch @@ -29332,6 +29374,7 @@ patches.suse/rtc-ac100-Fix-ac100-determine-rate-bug patches.suse/rtc-hctosys-Ensure-system-time-doesn-t-overflow-time patches.suse/rtc-snvs-Fix-usage-of-snvs_rtc_enable + patches.suse/libnvdimm-remove-redundant-__func__-in-dev_dbg.patch patches.suse/nfit_test-improve-structure-offset-handling.patch patches.suse/nfit_test-fix-buffer-overrun-add-sanity-check.patch patches.suse/nfit_test-prevent-parsing-error-of-nfit_test-0.patch @@ -30587,6 +30630,7 @@ patches.suse/mlx4_core-allocate-ICM-memory-in-page-size-chunks.patch patches.suse/batman-adv-Avoid-race-in-TT-TVLV-allocator-helper.patch patches.suse/batman-adv-Fix-TT-sync-flags-for-intermediate-TT-res.patch + patches.suse/batman-adv-prevent-TT-request-storms-by-not-sending-.patch patches.suse/selftests-bpf-config-enable-NET_SCH_INGRESS-for-xdp_.patch patches.suse/bpf-properly-enforce-index-mask-to-prevent-out-of-bo.patch patches.suse/ibmvnic-Fix-partial-success-login-retries.patch @@ -30874,6 +30918,7 @@ patches.suse/cifs_lookup-switch-to-d_splice_alias-.patch patches.suse/btrfs-remove-wrong-use-of-volume_mutex-from-btrfs_dev_replace_start.patch patches.suse/btrfs-track-running-balance-in-a-simpler-way.patch + patches.suse/btrfs-move-btrfs_raid_group-values-to-btrfs_raid_attr-table.patch patches.suse/0001-btrfs-Factor-out-common-delayed-refs-init-code.patch patches.suse/0002-btrfs-Use-init_delayed_ref_common-in-add_delayed_tre.patch patches.suse/0003-btrfs-Use-init_delayed_ref_common-in-add_delayed_dat.patch @@ -30901,6 +30946,7 @@ patches.suse/0003-Btrfs-reuse-cmp-workspace-in-EXTENT_SAME-ioctl.patch patches.suse/0004-btrfs-use-kvzalloc-for-EXTENT_SAME-temporary-data.patch patches.suse/0005-Btrfs-fix-clone-vs-chattr-NODATASUM-race.patch + patches.suse/btrfs-drop-unused-space_info-parameter-from-create_space_info.patch patches.suse/0003-Btrfs-remove-superfluous-free_extent_buffer-in-read_.patch patches.suse/0004-Btrfs-use-more-straightforward-extent_buffer_uptodat.patch patches.suse/0005-Btrfs-move-get-root-out-of-btrfs_search_slot-to-a-he.patch @@ -30908,6 +30954,7 @@ patches.suse/0007-Btrfs-remove-always-true-check-in-unlock_up.patch patches.suse/0008-Btrfs-remove-unused-check-of-skip_locking.patch patches.suse/btrfs-return-error-value-if-create_io_em-failed-in-cow_file_range.patch + patches.suse/btrfs-clean-up-error-handling-in-btrfs_truncate.patch patches.suse/0001-dlm-fix-a-clerical-error-when-set-SCTP_NODELAY.patch patches.suse/0002-dlm-make-sctp_connect_to_sock-return-in-specified-ti.patch patches.suse/0003-dlm-remove-O_NONBLOCK-flag-in-sctp_connect_to_sock.patch @@ -32452,6 +32499,7 @@ patches.suse/EDAC-ghes-Add-DDR4-and-NVDIMM-memory-types.patch patches.suse/EDAC-skx-Fix-skx_edac-build-error-when-ACPI_NFIT-m.patch patches.suse/EDAC-altera-Fix-ARM64-build-warning + patches.suse/EDAC-ghes-Make-platform-based-whitelisting-x86-only.patch patches.suse/ipmi-Add-a-way-to-tune-some-timeouts.patch patches.suse/ipmi-Add-a-maintenance-mode-for-IPMB-messages.patch patches.suse/ipmi-watchdog-Rework-locking-and-handling.patch @@ -32495,7 +32543,8 @@ patches.suse/branch-check-fix-long-int-truncation-when-profiling-.patch patches.suse/ompiler.h-enable-builtin-overflow-checkers-and-add-.patch patches.suse/overflow.h-Add-allocation-size-calculation-helpers.patch - patches.suse/0001-device-Use-overflow-helpers-for-devm_kmalloc.patch + patches.suse/0005-mm-Use-overflow-helpers-in-kvmalloc.patch + patches.suse/0006-device-Use-overflow-helpers-for-devm_kmalloc.patch patches.suse/0008-net-netsec-enable-tx-irq-during-open-callback.patch patches.suse/0009-net-socionext-reset-hardware-in-ndo_stop.patch patches.suse/liquidio-Enhanced-ethtool-stats.patch @@ -32777,6 +32826,7 @@ patches.suse/bpf-migrate-ebpf-ld_abs-ld_ind-tests-to-test_verifie.patch patches.suse/bpf-implement-ld_abs-ld_ind-in-native-bpf.patch patches.suse/bpf-add-skb_load_bytes_relative-helper.patch + patches.suse/bpf-x64-remove-ld_abs-ld_ind.patch patches.suse/bpf-sync-tools-bpf.h-uapi-header.patch patches.suse/bpf-unify-main-prog-and-subprog.patch patches.suse/bpf-centre-subprog-information-fields.patch @@ -34073,13 +34123,13 @@ patches.suse/staging-vc04_services-remove-struct-vchiq_debugfs_in patches.suse/staging-vc04_services-vchiq_debugfs_log_entry-can-be patches.suse/staging-vc04_services-no-need-to-save-the-log-debufs - patches.suse/0074-md-fix-an-error-code-format-and-remove-unsed-bio_sec.patch + patches.suse/0007-md-fix-an-error-code-format-and-remove-unsed-bio_sec.patch patches.suse/0001-raid10-check-bio-in-r10buf_pool_free-to-void-NULL-po.patch patches.suse/0001-md-fix-two-problems-with-setting-the-re-add-device-s.patch - patches.suse/0075-raid5-copy-write-hint-from-origin-bio-to-stripe.patch + patches.suse/0008-raid5-copy-write-hint-from-origin-bio-to-stripe.patch patches.suse/md-fix-NULL-dereference-of-mddev-pers-in-remove_and_.patch patches.suse/md-raid1-add-error-handling-of-read-error-from-FailF.patch - patches.suse/0076-md-raid5-Assigning-NULL-to-sh-batch_head-before-test.patch + patches.suse/0009-md-raid5-Assigning-NULL-to-sh-batch_head-before-test.patch patches.suse/0005-soc-rockchip-power-domain-Use-of_clk_get_parent_coun.patch patches.suse/clk-qcom-Base-rcg-parent-rate-off-plan-frequency patches.suse/0003-clk-bulk-silently-error-out-on-EPROBE_DEFER.patch @@ -34826,7 +34876,7 @@ patches.suse/x86-mce-check-for-alternate-indication-of-machine-check-recovery-on-skylake patches.suse/x86-mce-do-not-overwrite-mci_status-in-mce_no_way_out patches.suse/x86-mce-fix-incorrect-machine-check-from-unknown-source-message - patches.suse/0079-atomic-Add-irqsave-variant-of-atomic_dec_and_lock.patch + patches.suse/0010-atomic-Add-irqsave-variant-of-atomic_dec_and_lock.patch patches.suse/0001-locking-qspinlock-Fix-build-for-anonymous-union-in-o.patch patches.suse/x86-pti-xenpv-dont-report-as-vulnerable.patch patches.suse/x86-spectre_v1-Disable-compiler-optimizations-over-a.patch @@ -35258,6 +35308,7 @@ patches.suse/s390-sles15sp1-00-12-25-net-smc-take-sock-lock-in-smc_ioctl.patch patches.suse/octeon_mgmt-Fix-MIX-registers-configuration-on-MTU-s.patch patches.suse/ipv6-ila-select-CONFIG_DST_CACHE.patch + patches.suse/net-nfc-Avoid-stalls-when-nfc_alloc_send_skb-returne.patch patches.suse/s390-sles15sp1-00-12-32-net-smc-add-error-handling-for-get_user.patch patches.suse/s390-sles15sp1-00-12-35-net-smc-reset-recv-timeout-after-clc-handshake.patch patches.suse/lib-rhashtable-consider-param-min_size-when-setting-.patch @@ -35706,10 +35757,12 @@ patches.suse/binfmt_elf-Respect-error-return-from-regset-active.patch patches.suse/hwmon-k10temp-27c-offset-needed-for-threadripper2.patch patches.suse/hwmon-k10temp-support-threadripper-2920x-2970wx-simplify.patch + patches.suse/btrfs-remove-fs_info-from-do_chunk_alloc.patch patches.suse/btrfs-check-integrity-Fix-NULL-pointer-dereference-f.patch patches.suse/0001-btrfs-Don-t-remove-block-group-still-has-pinned-down.patch patches.suse/0015-btrfs-tree-checker-Verify-block_group_item.patch patches.suse/0016-btrfs-tree-checker-Detect-invalid-and-empty-essentia.patch + patches.suse/btrfs-refactor-block-group-replication-factor-calculation-to-a-helper.patch patches.suse/Btrfs-fix-btrfs_write_inode-vs-delayed-iput-deadlock.patch patches.suse/btrfs-fix-mount-failure-after-fsync-due-to-hard-link.patch patches.suse/btrfs-fix-send-failure-when-root-has-deleted-files-s.patch @@ -35886,7 +35939,7 @@ patches.suse/0227-bcache-don-t-clone-bio-in-bch_data_verify.patch patches.suse/exofs-use-bio_clone_fast-in-_write_mirror.patch patches.suse/block-remove-bio_clone_kmalloc.patch - patches.suse/0087-md-remove-a-bogus-comment.patch + patches.suse/0011-md-remove-a-bogus-comment.patch patches.suse/0088-block-allow-max_discard_segments-to-be-stacked.patch patches.suse/nvme.h-resync-with-nvme-cli.patch patches.suse/nvme-move-init-of-keep_alive-work-item-to-controller.patch @@ -35983,9 +36036,9 @@ patches.suse/0001-md-cluster-clear-another-node-s-suspend_area-after-t.patch patches.suse/0002-md-cluster-show-array-s-status-more-accurate.patch patches.suse/0003-md-cluster-don-t-send-msg-if-array-is-closing.patch - patches.suse/0098-md-r5cache-remove-redundant-pointer-bio.patch - patches.suse/0099-drivers-md-raid5-Use-irqsave-variant-of-atomic_dec_a.patch - patches.suse/0100-drivers-md-raid5-Do-not-disable-irq-on-release_inact.patch + patches.suse/0012-md-r5cache-remove-redundant-pointer-bio.patch + patches.suse/0013-drivers-md-raid5-Use-irqsave-variant-of-atomic_dec_a.patch + patches.suse/0014-drivers-md-raid5-Do-not-disable-irq-on-release_inact.patch patches.suse/md-raid5-fix-data-corruption-of-replacements-after-o.patch patches.suse/configfs-replace-strncpy-with-memcpy.patch patches.suse/configfs-fix-registered-group-removal.patch @@ -38776,6 +38829,7 @@ patches.suse/scsi-tcmu-add-module-wide-block-reset_netlink-suppor.patch patches.suse/scsi-read-host_busy-via-scsi_host_busy.patch patches.suse/scsi-tcmu-Don-t-pass-KERN_ERR-to-pr_err.patch + patches.suse/scsi-ibmvscsi-Improve-strings-handling.patch patches.suse/scsi-sd_zbc-Remove-an-assignment-from-sd_zbc_setup_r.patch patches.suse/scsi-target-tcm_loop-avoid-that-static-checkers-warn-about-dead-code patches.suse/scsi-lpfc-Add-Buffer-overflow-check-when-nvme_info-l.patch @@ -38808,6 +38862,7 @@ patches.suse/scsi-hisi_sas-tidy-hisi_sas_task_prep.patch patches.suse/scsi-hisi_sas-add-memory-barrier-in-task-delivery-function.patch patches.suse/scsi-hisi_sas-add-sata-fis-check-for-v3-hw.patch + patches.suse/scsi-ibmvscsi-change-strncpy-truncation-to-strlcpy.patch patches.suse/scsi-lpfc-remove-null-check-on-nvmebuf.patch patches.suse/scsi-target_core_user-fix-double-unlock.patch patches.suse/scsi-tcmu-initialize-list-head.patch @@ -38855,7 +38910,14 @@ patches.suse/evm-Don-t-deadlock-if-a-crypto-algorithm-is-unavaila.patch patches.suse/integrity-prevent-deadlock-during-digsig-verificatio.patch patches.suse/PCI-AER-Expose-internal-API-for-obtaining-AER-inform.patch + patches.suse/PCI-AER-Clear-only-ERR_FATAL-status-bits-during-fata.patch + patches.suse/PCI-AER-Clear-only-ERR_NONFATAL-bits-during-non-fata.patch + patches.suse/PCI-AER-Factor-out-ERR_NONFATAL-status-bit-clearing.patch + patches.suse/PCI-AER-Remove-ERR_FATAL-code-from-ERR_NONFATAL-path.patch + patches.suse/PCI-AER-Clear-device-status-bits-during-ERR_FATAL-an.patch + patches.suse/PCI-AER-Clear-device-status-bits-during-ERR_COR-hand.patch patches.suse/PCI-portdrv-Remove-pcie_portdrv_err_handler.slot_res.patch + patches.suse/PCI-AER-Don-t-clear-AER-bits-if-error-handling-is-Fi.patch patches.suse/igb-Remove-unnecessary-include-of-linux-pci-aspm.h.patch patches.suse/ath9k-Remove-unnecessary-include-of-linux-pci-aspm.h.patch patches.suse/iwlwifi-Remove-unnecessary-include-of-linux-pci-aspm.patch @@ -38960,6 +39022,7 @@ patches.suse/0003-modsign-log-module-name-in-the-event-of-an-error.patch patches.suse/0004-ARM-module-fix-modsign-build-error.patch patches.suse/powerpc-kdump-Handle-crashkernel-memory-reservation-.patch + patches.suse/powerpc-xive-Replace-msleep-x-with-msleep-OPAL_BUSY_.patch patches.suse/powerpc-64s-Remove-POWER9-DD1-support.patch patches.suse/powerpc-powernv-Move-TCE-manupulation-code-to-its-ow.patch patches.suse/KVM-PPC-Make-iommu_table-it_userspace-big-endian.patch @@ -40594,6 +40657,7 @@ patches.suse/fbdev-omapfb-fix-omapfb_memory_read-infoleak.patch patches.suse/sysfs-Do-not-return-POSIX-ACL-xattrs-via-listxattr.patch patches.suse/HID-intel-ish-hid-Enable-Ice-Lake-mobile.patch + patches.suse/media-v4l-event-Prevent-freeing-event-subscriptions-.patch patches.suse/xen-xsa270-fix.patch patches.suse/net-hns-fix-for-unmapping-problem-when-SMMU-is-on.patch patches.suse/tipc-fix-flow-control-accounting-for-implicit-connec.patch @@ -41106,6 +41170,10 @@ patches.suse/0001-x86-xen-Fix-boot-loader-version-reported-for-PVH-gue.patch patches.suse/msft-hv-1772-x86-hyperv-Suppress-PCI-Fatal-No-config-space-access.patch patches.suse/msft-hv-1773-x86-hyperv-Remove-unused-include.patch + patches.suse/x86-ioremap-Add-an-ioremap_encrypted-helper.patch + patches.suse/kexec-allocate-decrypted-control-pages-for-kdump-if.patch + patches.suse/iommu-amd-Remap-the-IOMMU-device-table-with-the-memo.patch + patches.suse/kdump-proc-vmcore-enable-kdumping-encrypted-memory-w.patch patches.suse/x86-kexec-correct-kexec_backup_src_end-off-by-one-error.patch patches.suse/resource-include-resource-end-in-walk_-interfaces.patch patches.suse/msft-hv-1782-x86-hyperv-Add-GUEST_IDLE_MSR-support.patch @@ -41937,6 +42005,7 @@ patches.suse/igc-Add-code-for-PHY-support.patch patches.suse/igc-Add-setup-link-functionality.patch patches.suse/igc-Add-watchdog.patch + patches.suse/atm-zatm-Fix-empty-body-Clang-warnings.patch patches.suse/bnxt_en-Copy-and-paste-bug-in-extended-tx_stats.patch patches.suse/cxgb4-fix-the-error-path-of-cxgb4_uld_register.patch patches.suse/net-mlx5-Refactor-fragmented-buffer-struct-fields-an.patch @@ -42000,6 +42069,7 @@ patches.suse/btrfs-fix-error-handling-in-btrfs_dev_replace_start.patch patches.suse/0001-btrfs-Enhance-btrfs_trim_fs-function-to-handle-error.patch patches.suse/0002-btrfs-Ensure-btrfs_trim_fs-can-trim-the-whole-filesy.patch + patches.suse/0001-btrfs-wait-on-caching-when-putting-the-bg-cache.patch patches.suse/0001-btrfs-qgroup-Introduce-trace-event-to-analyse-the-nu.patch patches.suse/0002-btrfs-qgroup-Introduce-function-to-trace-two-swaped-.patch patches.suse/0003-btrfs-qgroup-Introduce-function-to-find-all-new-tree.patch @@ -42008,10 +42078,15 @@ patches.suse/0006-btrfs-qgroup-Only-trace-data-extents-in-leaves-if-we.patch patches.suse/0001-btrfs-tree-checker-Check-level-for-leaves-and-nodes.patch patches.suse/Btrfs-kill-btrfs_clear_path_blocking.patch + patches.suse/0002-btrfs-release-metadata-before-running-delayed-refs.patch patches.suse/0008-btrfs-protect-space-cache-inode-alloc-with-GFP_NOFS.patch + patches.suse/0004-btrfs-reset-max_extent_size-on-clear-in-a-bitmap.patch patches.suse/btrfs-make-sure-we-create-all-new-block-groups.patch + patches.suse/0006-btrfs-assert-on-non-empty-delayed-iputs.patch + patches.suse/0007-btrfs-drop-min_size-from-evict_refill_and_join.patch patches.suse/btrfs-fix-warning-when-replaying-log-after-fsync-of-.patch patches.suse/btrfs-fix-wrong-dentries-after-fsync-of-file-that-go.patch + patches.suse/btrfs-delayed-ref-pass-delayed_refs-directly-to-btrfs_delayed_ref_lock.patch patches.suse/gfs2_meta-mount-can-get-NULL-dev_name.patch patches.suse/gfs2-Don-t-leave-s_fs_info-pointing-to-freed-memory-.patch patches.suse/xfs-remove-XFS_IO_INVALID.patch @@ -42087,11 +42162,21 @@ patches.suse/PCI-ACPI-Correct-error-message-for-ASPM-disabling.patch patches.suse/PCI-ASPM-Do-not-initialize-link-state-when-aspm_disa.patch patches.suse/PCI-Add-support-for-Immediate-Readiness.patch + patches.suse/PCI-Simplify-disconnected-marking.patch patches.suse/0001-PCI-pciehp-Differentiate-between-surprise-and-safe-r.patch patches.suse/0001-PCI-pciehp-Drop-hotplug_slot_ops-wrappers.patch patches.suse/0001-PCI-pciehp-Tolerate-Presence-Detect-hardwired-to-zer.patch patches.suse/0001-PCI-pciehp-Unify-controller-and-slot-structs.patch + patches.suse/PCI-portdrv-Initialize-service-drivers-directly.patch patches.suse/PCI-portdrv-Restore-PCI-config-state-on-slot-reset.patch + patches.suse/PCI-AER-Take-reference-on-error-devices.patch + patches.suse/PCI-AER-Don-t-read-upstream-ports-below-fatal-errors.patch + patches.suse/PCI-ERR-Use-slot-reset-if-available.patch + patches.suse/PCI-ERR-Handle-fatal-error-recovery.patch + patches.suse/PCI-ERR-Run-error-recovery-callbacks-for-all-affecte.patch + patches.suse/PCI-ERR-Simplify-broadcast-callouts.patch + patches.suse/PCI-ERR-Always-report-current-recovery-status-for-ud.patch + patches.suse/PCI-Unify-device-inaccessible.patch patches.suse/0001-PCI-Do-not-skip-power-managed-bridges-in-pci_enable_.patch patches.suse/0001-PCI-ACPI-Enable-wake-automatically-for-power-managed.patch patches.suse/0001-PCI-pciehp-Disable-hotplug-interrupt-during-suspend.patch @@ -42102,6 +42187,7 @@ patches.suse/0001-PCI-PME-Implement-runtime-PM-callbacks.patch patches.suse/0001-ACPI-property-Allow-multiple-property-compatible-_DS.patch patches.suse/0001-PCI-ACPI-Whitelist-D3-for-more-PCIe-hotplug-ports.patch + patches.suse/PCI-ERR-Remove-duplicated-include-from-err.c.patch patches.suse/PCI-Remove-pci_unmap_addr-wrappers-for-DMA-API.patch patches.suse/PCI-Add-Device-IDs-for-Intel-GPU-spurious-interrupt-.patch patches.suse/PCI-MSI-Warn-and-return-error-if-driver-enables-MSI-.patch @@ -42755,10 +42841,21 @@ patches.suse/0001-dm-ioctl-harden-copy_params-s-copy_from_user-from-ma.patch patches.suse/0001-dm-zoned-fix-metadata-block-ref-counting.patch patches.suse/0001-dm-zoned-fix-various-dmz_get_mblock-issues.patch + patches.suse/0016-raid5-block-failing-device-if-raid-will-be-failed.patch + patches.suse/0017-md-raid10-Fix-raid10-replace-hang-when-new-added-dis.patch patches.suse/MD-fix-invalid-stored-role-for-a-disk.patch patches.suse/md-allow-metadata-updates-while-suspending-an-array-.patch - patches.suse/0166-md-remove-redundant-code-that-is-no-longer-reachable.patch + patches.suse/0018-md-remove-redundant-code-that-is-no-longer-reachable.patch + patches.suse/0019-md-bitmap-use-mddev_suspend-resume-instead-of-quiesc.patch patches.suse/MD-fix-invalid-stored-role-for-a-disk-try2.patch + patches.suse/0020-md-cluster-raid10-resize-all-the-bitmaps-before-star.patch + patches.suse/0021-md-cluster-raid10-support-add-disk-under-grow-mode.patch + patches.suse/0022-md-cluster-introduce-resync_info_get-interface-for-s.patch + patches.suse/0023-md-cluster-raid10-call-update_size-in-md_reap_sync_t.patch + patches.suse/0024-md-cluster-raid10-don-t-call-remove_and_add_spares-d.patch + patches.suse/0025-md-cluster-bitmap-don-t-call-md_bitmap_sync_with_clu.patch + patches.suse/0026-md-cluster-send-BITMAP_NEEDS_SYNC-message-if-reshapi.patch + patches.suse/0027-md-cluster-remove-suspend_info.patch patches.suse/smb3-do-not-display-confusing-message-on-mount-to-Azure-servers.patch patches.suse/cifs-Use-kmemdup-rather-than-duplicating-its-implementation-in-smb3.patch patches.suse/cifs-remove-set-but-not-used-variable-cifs_sb-.patch @@ -42827,6 +42924,7 @@ patches.suse/powernv-pseries-consolidate-code-for-mce-early-handl.patch patches.suse/powerpc-consolidate-mno-sched-epilog-into-FTRACE-fla.patch patches.suse/powerpc-avoid-mno-sched-epilog-on-GCC-4.9-and-newer.patch + patches.suse/powerpc-pseries-memory-hotplug-Only-update-DT-once-p.patch patches.suse/powerpc-pseries-Remove-prrn_work-workqueue.patch patches.suse/powerpc-pseries-Remove-unneeded-uses-of-dlpar-work-q.patch patches.suse/powerpc-pseries-Disable-CPU-hotplug-across-migration.patch @@ -43219,6 +43317,12 @@ patches.suse/btrfs-fix-null-pointer-dereference-on-compressed-wri.patch patches.suse/0002-Btrfs-fix-assertion-on-fsync-of-regular-file-when-us.patch patches.suse/btrfs-fix-deadlock-when-writing-out-free-space-cache.patch + patches.suse/0008-btrfs-reset-max_extent_size-properly.patch + patches.suse/0009-btrfs-set-max_extent_size-properly.patch + patches.suse/0010-btrfs-don-t-use-ctl-free_space-for-max_extent_size.patch + patches.suse/0011-btrfs-only-free-reserved-extent-if-we-didn-t-insert-it.patch + patches.suse/0012-btrfs-fix-insert_reserved-error-handling.patch + patches.suse/0013-btrfs-don-t-run-delayed_iputs-in-commit.patch patches.suse/0006-Btrfs-fix-use-after-free-during-inode-eviction.patch patches.suse/0007-Btrfs-fix-use-after-free-when-dumping-free-space.patch patches.suse/cpufreq_intel_pstate_Fix_compilation_for_not_CONFIG_ACPI.patch @@ -43409,6 +43513,7 @@ patches.suse/netfilter-ipv6-fix-oops-when-defragmenting-locally-g.patch patches.suse/netfilter-conntrack-fix-calculation-of-next-bucket-n.patch patches.suse/HID-hiddev-fix-potential-Spectre-v1.patch + patches.suse/0001-Revert-HID-add-NOGET-quirk-for-Eaton-Ellipse-MAX-UPS.patch patches.suse/hwmon-core-Fix-double-free-in-__hwmon_device_registe.patch patches.suse/hwmon-ibmpowernv-Remove-bogus-__init-annotations.patch patches.suse/mtd-docg3-don-t-set-conflicting-BCH_CONST_PARAMS-opt.patch @@ -43476,6 +43581,7 @@ patches.suse/0009-Btrfs-fix-deadlock-on-tree-root-leaf-when-finding-fr.patch patches.suse/0010-Btrfs-fix-infinite-loop-on-inode-eviction-after-dedu.patch patches.suse/0011-Btrfs-fix-data-corruption-due-to-cloning-of-eof-bloc.patch + patches.suse/btrfs-fix-missing-delayed-iputs-on-unmount.patch patches.suse/ice-Set-carrier-state-and-start-stop-queues-in-rebui.patch patches.suse/ice-Check-for-reset-in-progress-during-remove.patch patches.suse/ice-Fix-dead-device-link-issue-with-flow-control.patch @@ -43579,6 +43685,7 @@ patches.suse/tipc-don-t-assume-linear-buffer-when-reading-ancilla.patch patches.suse/ipv6-Fix-PMTU-updates-for-UDP-raw-sockets-in-presenc.patch patches.suse/tuntap-fix-multiqueue-rx.patch + patches.suse/media-v4l-event-Add-subscription-to-list-before-call.patch patches.suse/media-omap3isp-Unregister-media-device-as-first.patch patches.suse/scsi-qla2xxx-Timeouts-occur-on-surprise-removal-of-Q.patch patches.suse/mtd-spi-nor-Fix-Cadence-QSPI-page-fault-kernel-panic.patch @@ -43921,6 +44028,7 @@ patches.suse/virtio-s390-avoid-race-on-vcdev-config patches.suse/virtio-s390-fix-race-in-ccw_io_helper patches.suse/vhost-vsock-fix-use-after-free-in-network-stack-call.patch + patches.suse/fs-xfs-fix-f_ffree-value-for-statfs-when-project-quo.patch patches.suse/splice-dont-read-more-than-available-pipe-space.patch patches.suse/clk-mvebu-Off-by-one-bugs-in-cp110_of_clk_get.patch patches.suse/clk-mmp-Off-by-one-in-mmp_clk_add.patch @@ -44405,6 +44513,7 @@ patches.suse/media-v4l2-tpg-array-index-could-become-negative.patch patches.suse/media-vivid-free-bitmap_cap-when-updating-std-timing.patch patches.suse/media-vb2-be-sure-to-unlock-mutex-on-errors.patch + patches.suse/media-uvcvideo-Refactor-teardown-of-uvc-on-USB-disconnect.patch patches.suse/media-DaVinci-VPBE-fix-error-handling-in-vpbe_initia.patch patches.suse/media-firewire-Fix-app_info-parameter-type-in-avc_ca.patch patches.suse/media-stkwebcam-Bugfix-for-wrong-return-values.patch @@ -44580,6 +44689,7 @@ patches.suse/powerpc-tm-Print-scratch-value.patch patches.suse/powerpc-tm-Unset-MSR-TS-if-not-recheckpointing.patch patches.suse/powerpc-pkeys-Fix-handling-of-pkey-state-across-fork.patch + patches.suse/powerpc-pseries-iommu-Use-memory-nodes-in-max-RAM-ad.patch patches.suse/powerpc-Fix-HMIs-on-big-endian-with-CONFIG_RELOCATAB.patch patches.suse/pstore-ram-Do-not-treat-empty-buffers-as-valid.patch patches.suse/pstore-Convert-buf_lock-to-semaphore.patch @@ -44953,10 +45063,22 @@ patches.suse/crypto-mxc-scc-fix-build-warnings-on-ARM64.patch patches.suse/gfs2-Get-rid-of-potential-double-freeing-in-gfs2_cre.patch patches.suse/gfs2-Fix-loop-in-gfs2_rbm_find.patch + patches.suse/btrfs-extent-tree-detect-bytes_may_use-underflow-earlier.patch + patches.suse/btrfs-extent-tree-detect-bytes_pinned-underflow-earlier.patch patches.suse/0001-btrfs-harden-agaist-duplicate-fsid-on-scanned-device.patch patches.suse/0001-Btrfs-fix-fsync-of-files-with-multiple-hard-links-in.patch patches.suse/btrfs-fix-error-handling-in-btrfs_cleanup_ordered_extents.patch + patches.suse/0001-btrfs-add-btrfs_delete_ref_head-helper.patch patches.suse/0003-btrfs-add-cleanup_ref_head_accounting-helper.patch + patches.suse/0003-btrfs-cleanup-extent_op-handling.patch + patches.suse/0004-btrfs-only-track-ref_heads-in-delayed_ref_updates.patch + patches.suse/0005-btrfs-introduce-delayed_refs_rsv.patch + patches.suse/0006-btrfs-update-may_commit_transaction-to-use-the-delayed-refs-rsv.patch + patches.suse/0007-btrfs-add-new-flushing-states-for-the-delayed-refs-rsv.patch + patches.suse/0008-btrfs-rework-btrfs_check_space_for_delayed_refs.patch + patches.suse/0009-btrfs-don-t-run-delayed-refs-in-the-end-transaction-logic.patch + patches.suse/0010-btrfs-fix-truncate-throttling.patch + patches.suse/0011-btrfs-catch-cow-on-deleting-snapshots.patch patches.suse/btrfs-run-delayed-items-before-dropping-the-snapshot.patch patches.suse/0011-Btrfs-send-fix-race-with-transaction-commits-that-cr.patch patches.suse/dlm-fix-invalid-free.patch @@ -45548,6 +45670,11 @@ patches.suse/drm-amd-display-validate-extended-dongle-caps.patch patches.suse/0003-drm-amd-display-Fix-MST-dp_blank-REG_WAIT-timeout.patch patches.suse/0004-drm-amdgpu-Add-new-VegaM-pci-id.patch + patches.suse/0028-md-remove-set-but-not-used-variable-bi_rdev.patch + patches.suse/0029-lib-raid6-add-missing-include-for-raid6test.patch + patches.suse/0030-lib-raid6-avoid-__attribute_const__-redefinition.patch + patches.suse/0031-lib-raid6-add-option-to-skip-algo-benchmarking.patch + patches.suse/0032-raid10-refactor-common-wait-code-from-regular-read-w.patch patches.suse/0001-md-fix-raid10-hang-issue-caused-by-barrier.patch patches.suse/ext4-make-sure-enough-credits-are-reserved-for-diore.patch patches.suse/ext4-fix-a-potential-fiemap-page-fault-deadlock-w-in.patch @@ -45693,6 +45820,7 @@ patches.suse/powerpc-tm-Limit-TM-code-inside-PPC_TRANSACTIONAL_ME.patch patches.suse/PCI-MSI-Return-ENOSPC-from-pci_alloc_irq_vectors_aff.patch patches.suse/media-v4l-ioctl-Validate-num_planes-for-debug-messag.patch + patches.suse/0033-md-Make-bio_alloc_mddev-use-bio_alloc_bioset.patch patches.suse/nbd-Use-set_blocksize-to-set-device-blocksize.patch patches.suse/blockdev-Fix-livelocks-on-loop-device.patch patches.suse/nvmet-tcp-fix-uninitialized-variable-access.patch @@ -45715,6 +45843,9 @@ patches.suse/acpi-nfit-fix-race-accessing-memdev-in-nfit_get_smbios_id.patch patches.suse/libnvdimm-security-fix-nvdimm_security_state-state-request-selection.patch patches.suse/0004-btrfs-handle-delayed-ref-head-accounting-cleanup-in-.patch + patches.suse/0014-btrfs-wait-on-ordered-extents-on-abort-cleanup.patch + patches.suse/0015-btrfs-run-delayed-iputs-before-committing.patch + patches.suse/0016-btrfs-wakeup-cleaner-thread-when-adding-delayed-iput.patch patches.suse/0008-netfilter-nf_tables-fix-leaking-object-reference-cou.patch patches.suse/net-ipv4-Fix-memory-leak-in-network-namespace-disman.patch patches.suse/Revert-igb-reduce-CPU0-latency-when-updating-statist.patch @@ -45919,6 +46050,7 @@ patches.suse/md-raid5-fix-out-of-memory-during-raid-cache-recover.patch patches.suse/blk-mq-fix-a-hung-issue-when-fsync.patch patches.suse/0002-Btrfs-fix-deadlock-when-allocating-tree-block-during.patch + patches.suse/0017-btrfs-don-t-end-the-transaction-for-delayed-refs-in-throttle.patch patches.suse/0005-btrfs-clean-up-pending-block-groups-when-transaction.patch patches.suse/x86-speculation-remove-redundant-arch_smt_update-invocation.patch patches.suse/x86-cpu-Add-Atom-Tremont-Jacobsville.patch @@ -46659,6 +46791,7 @@ patches.suse/misc-hpilo-Do-not-claim-unsupported-hardware.patch patches.suse/intel_th-gth-Fix-an-off-by-one-in-output-unassigning.patch patches.suse/msft-hv-1843-Drivers-hv-vmbus-Expose-counters-for-interrupts-and-.patch + patches.suse/debugfs-debugfs_use_start-finish-do-not-exist-anymor.patch patches.suse/driver-core-Establish-order-of-operations-for-device.patch patches.suse/device-core-Consolidate-locking-and-unlocking-of-par.patch patches.suse/driver-core-Probe-devices-asynchronously-instead-of-.patch @@ -46694,12 +46827,25 @@ patches.suse/0001-USB-serial-ftdi_sio-add-ID-for-Hjelmslund-Electronic.patch patches.suse/usb-chipidea-Grab-the-legacy-USB-PHY-by-phandle-firs.patch patches.suse/ext2-Fix-underflow-in-ext2_max_size.patch + patches.suse/0001-btrfs-make-btrfs_destroy_delayed_refs-use-btrfs_delayed_ref_lock.patch + patches.suse/0002-btrfs-make-btrfs_destroy_delayed_refs-use-btrfs_delete_ref_head.patch + patches.suse/0003-btrfs-call-btrfs_create_pending_block_groups-unconditionally.patch patches.suse/0001-btrfs-relocation-Delay-reloc-tree-deletion-after-mer.patch patches.suse/0002-btrfs-qgroup-Refactor-btrfs_qgroup_trace_subtree_swa.patch patches.suse/0003-btrfs-qgroup-Introduce-per-root-swapped-blocks-infra.patch patches.suse/0004-btrfs-qgroup-Use-delayed-subtree-rescan-for-balance.patch patches.suse/0005-btrfs-qgroup-Cleanup-old-subtree-swap-code.patch patches.suse/0001-btrfs-qgroup-Remove-duplicated-trace-points-for-qgro.patch + patches.suse/btrfs-output-enospc-debug-info-in-inc_block_group_ro.patch + patches.suse/0004-btrfs-replace-cleaner_delayed_iput_mutex-with-a-waitqueue.patch + patches.suse/0005-btrfs-check-if-there-are-free-block-groups-for-commit.patch + patches.suse/0006-btrfs-dump-block_rsv-details-when-dumping-space-info.patch + patches.suse/0007-btrfs-don-t-use-global-reserve-for-chunk-allocation.patch + patches.suse/0008-btrfs-don-t-enospc-all-tickets-on-flush-failure.patch + patches.suse/0009-btrfs-loop-in-inode_rsv_refill.patch + patches.suse/0010-btrfs-be-more-explicit-about-allowed-flush-states.patch + patches.suse/0011-btrfs-reserve-extra-space-during-evict.patch + patches.suse/btrfs-extent_io-Kill-the-forward-declaration-of-flus.patch patches.suse/0001-btrfs-qgroup-Move-reserved-data-accounting-from-btrf.patch patches.suse/btrfs-fix-fsync-after-succession-of-renames-of-diffe.patch patches.suse/btrfs-fix-fsync-after-succession-of-renames-and-unli.patch @@ -46733,6 +46879,7 @@ patches.suse/powerpc-mm-Check-secondary-hash-page-table.patch patches.suse/x86-resctrl-remove-duplicate-msr_misc_feature_control-definition.patch patches.suse/x86-fpu-track-avx-512-usage-of-tasks + patches.suse/x86-kdump-Export-the-SME-mask-to-vmcoreinfo.patch patches.suse/lib-div64.c-off-by-one-in-shift.patch patches.suse/drivers-rapidio-rio_cm.c-fix-potential-oops-in-riocm.patch patches.suse/sysctl-handle-overflow-in-proc_get_long.patch @@ -46836,6 +46983,8 @@ patches.suse/drivers-provide-devm_platform_ioremap_resource.patch patches.suse/drivers-depend-on-has_iomem-for-devm_platform_ioremap_resource patches.suse/gpio-gpio-omap-fix-level-interrupt-idling.patch + patches.suse/0034-md-linear-use-struct_size-in-kzalloc.patch + patches.suse/0035-raid1-simplify-raid1_error-function.patch patches.suse/cdrom-Fix-race-condition-in-cdrom_sysctl_register.patch patches.suse/0275-bcache-never-writeback-a-discard-operation.patch patches.suse/0276-bcache-not-use-hard-coded-memset-size-in-bch_cache_a.patch @@ -46857,6 +47006,7 @@ patches.suse/0292-bcache-fix-input-overflow-to-cache-set-sysfs-file-io.patch patches.suse/0293-bcache-use-REQ_META-REQ_PRIO-to-indicate-bio-for-met.patch patches.suse/block-don-t-use-bio-bi_vcnt-to-figure-out-segment-number.patch + patches.suse/nvme-multipath-round-robin-I-O-policy.patch patches.suse/documentation-document-arm64-kpti-control patches.suse/doc-rcu-Suspicious-RCU-usage-is-a-warning.patch patches.suse/CIFS-Fix-leaking-locked-VFS-cache-pages-in-writeback-retry.patch @@ -47191,6 +47341,7 @@ patches.suse/x86-add-tsx-force-abort-cpuid-msr patches.suse/perf-x86-intel-implement-support-for-tsx-force-abort.patch patches.suse/kernel-sysctl.c-add-missing-range-check-in-do_proc_d.patch + patches.suse/0036-md-convert-to-kvmalloc.patch patches.suse/fsdevpts-always-delete-dcache-dentry-s-in-dput.patch patches.suse/splice-dont-merge-into-linked-buffers.patch patches.suse/vfs-fix-preadv64v2-and-pwritev64v2-compat-syscalls-w.patch @@ -47351,6 +47502,7 @@ patches.suse/SMB3-Allow-SMB3-FSCTL-queries-to-be-sent-to-server-from-tools.patch patches.suse/CIFS-fix-POSIX-lock-leak-and-invalid-ptr-deref.patch patches.suse/powerpc-powernv-Fix-compile-without-CONFIG_TRACEPOIN.patch + patches.suse/0037-raid5-set-write-hint-for-PPL.patch patches.suse/It-s-wrong-to-add-len-to-sector_nr-in-raid10-reshape.patch patches.suse/md-Fix-failed-allocation-of-md_register_thread.patch patches.suse/nvme-fc-reject-reconnect-if-io-queue-count-is-reduce.patch @@ -47529,6 +47681,10 @@ patches.suse/scsi-sd-Quiesce-warning-if-device-does-not-report-op.patch patches.suse/scsi-zfcp-fix-rport-unblock-if-deleted-scsi-devices-on-scsi_host patches.suse/scsi-zfcp-fix-scsi_eh-host-reset-with-port_forced-erp-for-non-npiv-fcp-devices + patches.suse/scsi-ibmvfc-Remove-failed-from-logged-errors.patch + patches.suse/scsi-ibmvfc-Add-failed-PRLI-to-cmd_status-lookup-arr.patch + patches.suse/scsi-ibmvfc-Byte-swap-status-and-error-codes-when-lo.patch + patches.suse/scsi-ibmvfc-Clean-up-transport-events.patch patches.suse/iommu-don-t-print-warning-when-iommu-driver-only-supports-unmanaged-domains patches.suse/iommu-amd-reserve-exclusion-range-in-iova-domain patches.suse/mm-Fix-modifying-of-page-protection-by-insert_pfn.patch @@ -48080,8 +48236,17 @@ patches.suse/livepatch-convert-error-about-unsupported-reliable-stacktrace-into-a-warning.patch patches.suse/livepatch-remove-custom-kobject-state-handling.patch patches.suse/livepatch-remove-duplicated-code-for-early-initialization.patch + patches.suse/btrfs-factor-our-read-write-stage-off-csum_tree_bloc.patch patches.suse/0001-btrfs-Don-t-panic-when-we-can-t-find-a-root-key.patch patches.suse/0001-btrfs-reloc-Fix-NULL-pointer-dereference-due-to-expa.patch + patches.suse/0001-btrfs-extent_io-Move-the-BUG_ON-in-flush_write_bio-o.patch + patches.suse/0002-btrfs-extent_io-Handle-errors-better-in-extent_write.patch + patches.suse/0003-btrfs-extent_io-Handle-errors-better-in-btree_write_.patch + patches.suse/0004-btrfs-extent_io-Kill-dead-condition-in-extent_write_.patch + patches.suse/0005-btrfs-extent_io-Handle-errors-better-in-extent_write.patch + patches.suse/0006-btrfs-extent_io-add-proper-error-handling-to-lock_ex.patch + patches.suse/0007-btrfs-extent_io-Handle-errors-better-in-extent_write.patch + patches.suse/0001-btrfs-fix-panic-during-relocation-after-ENOSPC-befor.patch patches.suse/0001-btrfs-Move-btrfs_check_chunk_valid-to-tree-check.-ch.patch patches.suse/0002-btrfs-tree-checker-Make-chunk-item-checker-messages-.patch patches.suse/0003-btrfs-tree-checker-Make-btrfs_check_chunk_valid-retu.patch @@ -48104,6 +48269,8 @@ patches.suse/0020-btrfs-tree-checker-get-fs_info-from-eb-in-dev_item_e.patch patches.suse/0021-btrfs-tree-checker-get-fs_info-from-eb-in-check_dev_.patch patches.suse/0022-btrfs-tree-checker-get-fs_info-from-eb-in-check_inod.patch + patches.suse/0001-btrfs-tree-checker-Remove-comprehensive-root-owner-c.patch + patches.suse/0002-btrfs-Do-mandatory-tree-block-check-before-submittin.patch patches.suse/0001-btrfs-delayed-ref-Introduce-better-documented-delaye.patch patches.suse/0002-btrfs-extent-tree-Open-code-process_func-in-__btrfs_.patch patches.suse/0003-btrfs-delayed-ref-Use-btrfs_ref-to-refactor-btrfs_ad.patch @@ -48115,6 +48282,8 @@ patches.suse/btrfs-send-flush-dellaloc-in-order-to-avoid-data-los.patch patches.suse/Btrfs-fix-race-between-send-and-deduplication-that-l.patch patches.suse/btrfs-improve-performance-on-fsync-of-files-with-mul.patch + patches.suse/btrfs-track-dio-bytes-in-flight.patch + patches.suse/btrfs-reserve-delalloc-metadata-differently.patch patches.suse/scsi-be2iscsi-be_iscsi-mark-expected-switch-fall-through patches.suse/scsi-be2iscsi-be_main-mark-expected-switch-fall-through patches.suse/scsi-csiostor-csio_wr-mark-expected-switch-fall-through @@ -48152,12 +48321,19 @@ patches.suse/leds-avoid-races-with-workqueue.patch patches.suse/md-batch-flush-requests.patch patches.suse/md-add-mddev-pers-to-avoid-potential-NULL-pointer-de.patch + patches.suse/0038-md-add-a-missing-endianness-conversion-in-check_sb_c.patch + patches.suse/0039-md-use-correct-types-in-md_bitmap_print_sb.patch + patches.suse/0040-md-use-correct-type-in-super_1_load.patch + patches.suse/0041-md-use-correct-type-in-super_1_sync.patch + patches.suse/0043-md-add-__acquires-__releases-annotations-to-un-lock_.patch + patches.suse/0044-md-add-__acquires-__releases-annotations-to-handle_a.patch patches.suse/block-disk_events-introduce-event-flags.patch patches.suse/Revert-ide-unexport-DISK_EVENT_MEDIA_CHANGE-for-i.patch patches.suse/Revert-block-unexport-DISK_EVENT_MEDIA_CHANGE-for.patch patches.suse/block-check_events-don-t-bother-with-events-if-un.patch patches.suse/block-don-t-show-io_timeout-if-driver-has-no-timeout.patch patches.suse/block-fix-use-after-free-on-gendisk.patch + patches.suse/0045-md-return-ENODEV-if-rdev-has-no-mddev-assigned.patch patches.suse/md-raid-raid5-preserve-the-writeback-action-after-th.patch patches.suse/0001-bcache-fix-crashes-stopping-bcache-device-before-rea.patch patches.suse/0002-bcache-fix-inaccurate-result-of-unused-buckets.patch @@ -48918,6 +49094,7 @@ patches.suse/vlan-disable-SIOCSHWTSTAMP-in-container.patch patches.suse/packet-Fix-error-path-in-packet_init.patch patches.suse/nfp-bpf-fix-static-check-error-through-tightening-sh.patch + patches.suse/powerpc-pseries-iommu-Fix-set-but-not-used-values.patch patches.suse/powerpc-crypto-Use-cheaper-random-numbers-for-crc-vp.patch patches.suse/powerpc-numa-improve-control-of-topology-updates.patch patches.suse/powerpc-numa-document-topology_updates_enabled-disab.patch @@ -49026,6 +49203,7 @@ patches.suse/powerpc-mm-radix-mark-__radix__flush_tlb_range_psize.patch patches.suse/powerpc-mm-radix-mark-as-__tlbie_pid-and-friends-as_.patch patches.suse/include-linux-bitops.h-sanitize-rotate-primitives.patch + patches.suse/binfmt_elf-move-brk-out-of-mmap-when-doing-direct-lo.patch patches.suse/rapidio-fix-a-NULL-pointer-dereference-when-create_w.patch patches.suse/IB-mlx5-Verify-DEVX-general-object-type-correctly.patch patches.suse/net-mlx5-Set-completion-EQs-as-shared-resources.patch @@ -49455,6 +49633,7 @@ patches.suse/Input-synaptics-enable-SMBus-on-ThinkPad-E480-and-E5.patch patches.suse/apparmor-enforce-nullbyte-at-end-of-tag-string.patch patches.suse/PCI-PM-Skip-devices-in-D0-for-suspend-to-idle.patch + patches.suse/0046-md-fix-for-divide-error-in-status_resync.patch patches.suse/mmc-core-complete-HS400-before-checking-status.patch patches.suse/mmc-core-API-to-temporarily-disable-retuning-for-SDI.patch patches.suse/brcmfmac-sdio-Disable-auto-tuning-around-commands-ex.patch @@ -49688,7 +49867,20 @@ patches.suse/cpufreq-brcmstb-avs-cpufreq-Fix-types-for-voltage-fr.patch patches.suse/cpufreq-add-driver-for-raspberry-pi.patch patches.suse/ACPICA-Clear-status-of-GPEs-on-first-direct-enable.patch - patches.suse/raid5-cache-Need-to-do-start-part-job-after-adding-j.patch + patches.suse/0047-raid5-cache-Need-to-do-start-part-job-after-adding-j.patch + patches.suse/0048-md-md.c-Return-ENODEV-when-mddev-is-NULL-in-rdev_att.patch + patches.suse/0049-md-fix-spelling-typo-and-add-necessary-space.patch + patches.suse/0050-md-raid1-get-rid-of-extra-blank-line-and-space.patch + patches.suse/0051-md-raid10-Use-struct_size-in-kmalloc.patch + patches.suse/0052-md-raid10-read-balance-chooses-idlest-disk-for-SSD.patch + patches.suse/0053-md-raid1-fix-potential-data-inconsistency-issue-with.patch + patches.suse/0054-md-introduce-mddev_create-destroy_wb_pool-for-the-ch.patch + patches.suse/0055-md-bitmap-create-and-destroy-wb_info_pool-with-the-c.patch + patches.suse/0056-md-bitmap-create-and-destroy-wb_info_pool-with-the-c.patch + patches.suse/0057-md-add-bitmap_abort-label-in-md_run.patch + patches.suse/lpfc-add-support-to-generate-RSCN-events-for-nport.patch + patches.suse/lpfc-add-support-for-translating-an-RSCN-rcv-into-a-.patch + patches.suse/0058-md-raid1-Fix-a-warning-message-in-remove_wb.patch patches.suse/0022-bcache-don-t-set-max-writeback-rate-if-gc-is-running.patch patches.suse/0023-bcache-check-c-gc_thread-by-IS_ERR_OR_NULL-in-cache_.patch patches.suse/0024-bcache-fix-return-value-error-in-bch_journal_read.patch @@ -49731,6 +49923,7 @@ patches.suse/libata-don-t-request-sense-data-on-ZAC-ATA-devices.patch patches.suse/documentation-dma-api-fix-a-function-name-of-max_mapping_size patches.suse/docs-move-protection-keys.rst-to-the-core-api-book.patch + patches.suse/debugfs-simplify-__debugfs_remove_file.patch patches.suse/udf-Fix-incorrect-final-NOT_ALLOCATED-hole-extent-le.patch patches.suse/fscrypt-don-t-set-policy-for-a-dead-directory.patch patches.suse/mm-add-filemap_fdatawait_range_keep_errors.patch @@ -49933,6 +50126,7 @@ patches.suse/nfc-fix-potential-illegal-memory-access.patch patches.suse/tcp-Reset-bytes_acked-and-bytes_received-when-discon.patch patches.suse/net-tls-fix-socket-wmem-accounting-on-fallback-with-.patch + patches.suse/dt-bindings-allow-up-to-four-clocks-for-orion-mdio.patch patches.suse/irqchip-gic-v3-its-Fix-misuse-of-GENMASK-macro.patch patches.suse/stacktrace-use-pf_kthread-to-check-for-kernel-threads.patch patches.suse/x86-alternatives-fix-int3_emulate_call-selftest-stack-corruption.patch @@ -49960,6 +50154,9 @@ patches.suse/scsi-lpfc-Fix-BFS-crash-with-DIX-enabled.patch patches.suse/scsi-lpfc-Fix-kernel-warnings-related-to-smp_process.patch patches.suse/scsi-lpfc-Update-lpfc-version-to-12.2.0.3.patch + patches.suse/scsi-ibmvscsi-Wire-up-host_reset-in-the-driver-s-scs.patch + patches.suse/scsi-ibmvscsi-redo-driver-work-thread-to-use-enum-ac.patch + patches.suse/scsi-ibmvscsi-fix-tripping-of-blk_mq_run_hw_queue-WA.patch patches.suse/scsi-hpsa-fix-an-uninitialized-read-and-dereference-of-pointer-dev patches.suse/scsi-mpt3sas_ctl-fix-double-fetch-bug-in-ctl_ioctl_main patches.suse/scsi-hisi_sas-Reduce-HISI_SAS_SGE_PAGE_CNT-in-size.patch @@ -49968,6 +50165,7 @@ patches.suse/scsi-qla2xxx-remove-double-assignment-in-qla2x00_upd.patch patches.suse/scsi-lpfc-Remove-set-but-not-used-variables-qp.patch patches.suse/scsi-lpfc-Make-some-symbols-static.patch + patches.suse/scsi-ibmvscsi-Don-t-use-rc-uninitialized-in-ibmvscsi.patch patches.suse/scsi-lpfc-Avoid-unused-function-warnings.patch patches.suse/scsi-mpt3sas-function-pointers-of-request-descriptor.patch patches.suse/scsi-mpt3sas-Add-Atomic-RequestDescriptor-support-on.patch @@ -50072,6 +50270,7 @@ patches.suse/s390-fix-setting-of-mio-addressing-control patches.suse/s390-pci-add-mio_enabled-attribute patches.suse/s390-unwind-avoid-int-overflow-in-outside_of_stack.patch + patches.suse/xfs-bulkstat-should-copy-lastip-whenever-userspace-s.patch patches.suse/9p-virtio-Add-cleanup-path-in-p9_virtio_init.patch patches.suse/9p-xen-Add-cleanup-path-in-p9_trans_xen_init.patch patches.suse/Input-synaptics-enable-SMBUS-on-T480-thinkpad-trackp.patch @@ -50087,6 +50286,7 @@ patches.suse/powerpc-cacheinfo-add-cacheinfo_teardown-cacheinfo_r.patch patches.suse/powerpc-pseries-mobility-prevent-cpu-hotplug-during-.patch patches.suse/powerpc-pseries-mobility-rebuild-cacheinfo-hierarchy.patch + patches.suse/powerpc-64-mark-start_here_multiplatform-as-__ref.patch patches.suse/powerpc-watchpoint-Restore-NV-GPRs-while-returning-f.patch patches.suse/powerpc-rtas-retry-when-cpu-offline-races-with-suspe.patch patches.suse/powerpc-64s-Rename-PPC_INVALIDATE_ERAT-to-PPC_ISA_3_.patch @@ -50188,12 +50388,41 @@ patches.suse/0001-PCI-qcom-Ensure-that-PERST-is-asserted-for-at-least-.patch patches.suse/PCI-tegra-Enable-Relaxed-Ordering-only-for-Tegra20-T.patch patches.suse/0001-PCI-xilinx-nwl-Fix-Multi-MSI-data-programming.patch + patches.suse/nvme-multipath-factor-out-a-nvme_path_is_disabled-he.patch + patches.suse/nvme-multipath-also-check-for-a-disabled-path-if-the.patch + patches.suse/nvme-multipath-do-not-select-namespaces-which-are-ab.patch patches.suse/nvme-fc-fix-module-unloads-while-lports-still-pendin.patch patches.suse/btrfs-ensure-btrfs_init_dev_replace_tgtdev-sees-up-to-date-values.patch + patches.suse/btrfs-extent-tree-add-lockdep-assert-when-updating-space-info.patch + patches.suse/btrfs-extent-tree-add-trace-events-for-space-info-numbers-update.patch patches.suse/btrfs-fix-data-loss-after-inode-eviction-renaming-it.patch + patches.suse/btrfs-qgroup-Don-t-hold-qgroup_ioctl_lock-in-btrfs_q.patch patches.suse/Btrfs-prevent-send-failures-and-crashes-due-to-concu.patch patches.suse/btrfs-fix-fsync-not-persisting-dentry-deletions-due-.patch patches.suse/btrfs-add-missing-inode-version-ctime-and-mtime-upda.patch + patches.suse/0001-btrfs-run-delayed-iput-at-unlink-time.patch + patches.suse/0002-btrfs-move-space_info-to-space-info-h.patch + patches.suse/0003-btrfs-rename-do_chunk_alloc-to-btrfs_chunk_alloc.patch + patches.suse/0004-btrfs-export-space_info_add_-bytes.patch + patches.suse/0005-btrfs-move-the-space_info-handling-code-to-space-info-c.patch + patches.suse/0006-btrfs-move-and-export-can_overcommit.patch + patches.suse/0007-btrfs-move-the-space-info-update-macro-to-space-info-h.patch + patches.suse/0008-btrfs-move-btrfs_space_info_add_-bytes-to-space-info-c.patch + patches.suse/0009-btrfs-export-block_rsv_use_bytes.patch + patches.suse/0010-btrfs-move-dump_space_info-to-space-info-c.patch + patches.suse/0011-btrfs-move-reserve_metadata_bytes-and-supporting-code-to-space-info-c.patch + patches.suse/0012-btrfs-unexport-can_overcommit.patch + patches.suse/0013-btrfs-move-btrfs_block_rsv-definitions-into-it-s-own-header.patch + patches.suse/0014-btrfs-export-btrfs_block_rsv_add_bytes.patch + patches.suse/0015-btrfs-export-_btrfs_block_rsv_release.patch + patches.suse/0016-btrfs-cleanup-the-target-logic-in-_btrfs_block_rsv_release.patch + patches.suse/0017-btrfs-stop-using-block_rsv_release_bytes-everywhere.patch + patches.suse/0018-btrfs-migrate-the-block-rsv-code-to-block-rsv-c.patch + patches.suse/0019-btrfs-migrate-the-global_block_rsv-helpers-to-block-rsv-c.patch + patches.suse/0020-btrfs-migrate-the-delayed-refs-rsv-code.patch + patches.suse/0021-btrfs-migrate-btrfs_trans_release_chunk_metadata.patch + patches.suse/0022-btrfs-migrate-the-delalloc-space-stuff-to-it-s-own-home.patch + patches.suse/0023-btrfs-move-the-subvolume-reservation-stuff-out-of-extent-tree-c.patch patches.suse/0022-drivers-rapidio-devices-rio_mport_cdev.c-NUL-termina.patch patches.suse/drivers-pps-pps.c-clear-offset-flags-in-PPS_SETPARAM.patch patches.suse/0001-device-dax-fix-memory-and-resource-leak-if-hotplug-f.patch @@ -50281,12 +50510,15 @@ patches.suse/cifs-fix-crash-in-cifs_dfs_do_automount.patch patches.suse/cifs-fix-crash-in-smb2_compound_op-smb2_set_next_command-.patch patches.suse/smb3-smbdirect-no-longer-experimental.patch + patches.suse/module-Only-return-EEXIST-for-modules-that-.patch patches.suse/NFSv4-Handle-the-special-Linux-file-open-access-mode.patch + patches.suse/NFS-send-state-management-on-a-single-connection.patch patches.suse/NFS-Cleanup-if-nfs_match_client-is-interrupted.patch patches.suse/xprtrdma-Fix-use-after-free-in-rpcrdma_post_recvs.patch patches.suse/pnfs-flexfiles-Fix-PTR_ERR-dereferences-in-ff_layout.patch patches.suse/dm-zoned-fix-zone-state-management-race.patch patches.suse/resource-fix-locking-in-find_next_iomem_res.patch + patches.suse/libnvdimm-pfn-fix-fsdax-mode-namespace-info-block-ze.patch patches.suse/net-neigh-fix-multiple-neigh-timer-scheduling.patch patches.suse/0015-ISDN-hfcsusb-checking-idx-of-ep-configuration.patch patches.suse/be2net-Signal-that-the-device-cannot-transmit-during.patch @@ -50552,10 +50784,13 @@ patches.suse/ALSA-hda-Add-a-generic-reboot_notify.patch patches.suse/ALSA-usb-audio-Fix-an-OOB-bug-in-parse_audio_mixer_u.patch patches.suse/ALSA-usb-audio-Fix-a-stack-buffer-overflow-bug-in-ch.patch + patches.suse/dmaengine-ste_dma40-fix-unneeded-variable-warning.patch patches.suse/i2c-emev2-avoid-race-when-unregistering-slave-client.patch patches.suse/nvme-multipath-revalidate-nvme_ns_head-gendisk-in-nv.patch patches.suse/nvme-core-Fix-extra-device_put-call-on-error-path.patch + patches.suse/nvme-fix-a-possible-deadlock-when-passthru-commands-.patch patches.suse/nvme-rdma-drain-qp.patch + patches.suse/nvme-fix-controller-removal-race-with-scan-work.patch patches.suse/0001-usb-gadget-udc-renesas_usb3-Fix-sysfs-interface-of-r.patch patches.suse/usb-gadget-composite-Clear-suspended-on-reset-discon.patch patches.suse/USB-core-Fix-races-in-character-device-registration-.patch @@ -50618,6 +50853,7 @@ patches.suse/dm-btree-fix-order-of-block-initialization-in-btree_.patch patches.suse/dm-space-map-metadata-fix-missing-store-of-apply_bop.patch patches.suse/dm-table-fix-invalid-memory-accesses-with-too-high-s.patch + patches.suse/nvme-multipath-fix-possible-I-O-hang-when-paths-are-.patch patches.suse/IB-mlx5-Consolidate-use_umr-checks-into-single-funct.patch patches.suse/IB-mlx5-Fix-MR-re-registration-flow-to-use-UMR-prope.patch patches.suse/drm-nouveau-Don-t-retry-infinitely-when-receiving-no.patch @@ -50657,6 +50893,7 @@ patches.suse/SUNRPC-Handle-connection-breakages-correctly-in-call.patch patches.suse/cifs-set-domainName-when-a-domain-key-is-used-in-multiuser.patch patches.suse/cifs-Use-kzfree-to-zero-out-the-password.patch + patches.suse/cifs-replace-various-strncpy-with-strscpy-and-similar.patch patches.suse/0001-drm-amdgpu-Add-APTX-quirk-for-Dell-Latitude-5495.patch patches.suse/0001-drm-i915-Don-t-deballoon-unused-ggtt-drm_mm_node-in-.patch patches.suse/drm-i915-Call-dma_set_max_seg_size-in-i915_driver_hw.patch @@ -50716,6 +50953,7 @@ patches.suse/virtio_ring-fix-unmap-of-indirect-descriptors patches.suse/vhost-make-sure-log_num-in_num.patch patches.suse/Btrfs-fix-assertion-failure-during-fsync-and-use-of-.patch + patches.suse/Btrfs-fix-unwritten-extent-buffers-and-hangs-on-futu.patch patches.suse/0001-drm-i915-Restore-relaxed-padding-OCL_OOB_SUPPRES_ENA.patch patches.suse/sctp-use-transport-pf_retrans-in-sctp_do_8_2_transpo.patch patches.suse/Bluetooth-btrtl-Additional-Realtek-8822CE-Bluetooth-.patch @@ -50772,7 +51010,10 @@ patches.suse/qla2xxx-remove-SGI-SN2-support.patch patches.suse/soc-renesas-rcar-sysc-Add-goto-to-of_node_put-before.patch patches.suse/objtool-clobber-user-cflags-variable.patch + patches.suse/efi-x86-move-efi_is_table_address-into-arch-x86.patch + patches.suse/efi-Export-Runtime-Configuration-Interface-table-to--1c5fecb6.patch patches.suse/efi-cper-print-AER-info-of-PCIe-fatal-error.patch + patches.suse/0001-tools-lib-traceevent-Do-not-free-tep-cmdlines-in-add.patch patches.suse/x86-kconfig-remove-x86_direct_gbpages-dependency-on-debug_pagealloc.patch patches.suse/platform-x86-pmc_atom-Add-Siemens-SIMATIC-IPC227E-to.patch patches.suse/tools-power-x86-intel-speed-select-Fix-a-read-overfl.patch @@ -50789,16 +51030,32 @@ patches.suse/blk-mq-introduce-blk_mq_tagset_wait_completed_reques.patch patches.suse/nvme-don-t-abort-completed-request-in-nvme_cancel_re.patch patches.suse/nvme-wait-until-all-completed-request-s-complete-fn-.patch + patches.suse/0059-raid1-use-an-int-as-the-return-value-of-raise_barrie.patch patches.suse/md-raid6-Set-R5_ReadError-when-there-is-read-failure.patch + patches.suse/0060-md-raid1-end-bio-when-the-device-faulty.patch + patches.suse/0061-md-raid10-end-bio-when-the-device-faulty.patch + patches.suse/0062-md-allow-last-device-to-be-forcibly-removed-from-RAI.patch + patches.suse/0063-md-don-t-set-In_sync-if-array-is-frozen.patch + patches.suse/0064-md-don-t-call-spare_active-in-md_reap_sync_thread-if.patch + patches.suse/0065-raid1-factor-out-a-common-routine-to-handle-the-comp.patch patches.suse/floppy-fix-usercopy-direction.patch patches.suse/blk-mq-fix-memory-leak-in-blk_mq_init_allocated_queue-error.patch patches.suse/md-only-call-set_in_sync-when-it-is-expected-to-succ.patch patches.suse/md-don-t-report-active-array_state-until-after-reval.patch + patches.suse/0066-raid5-improve-too-many-read-errors-msg-by-adding-lim.patch patches.suse/nvme-multipath-fix-ana-log-nsid-lookup-when-nsid-is-.patch patches.suse/0001-bcache-add-cond_resched-in-__bch_cache_cmp.patch patches.suse/0002-bcache-Fix-an-error-code-in-bch_dump_read.patch patches.suse/0003-closures-fix-a-race-on-wakeup-from-closure_sync.patch + patches.suse/0067-md-raid0-linear-Mark-array-as-broken-and-fail-BIOs-i.patch + patches.suse/0068-md-raid1-fail-run-raid1-array-when-active-disk-less-.patch + patches.suse/0069-md-raid5-use-bio_end_sector-to-calculate-last_sector.patch + patches.suse/0070-raid5-don-t-increment-read_errors-on-EILSEQ-return.patch + patches.suse/0071-raid5-don-t-set-STRIPE_HANDLE-to-stripe-which-is-in-.patch patches.suse/0001-md-raid0-avoid-RAID0-data-corruption-due-to-layout-c.patch + patches.suse/0072-md-add-feature-flag-MD_FEATURE_RAID0_LAYOUT.patch + patches.suse/0073-raid5-remove-STRIPE_OPS_REQ_PENDING.patch + patches.suse/0074-raid5-use-bio_end_sector-in-r5_next_bio.patch patches.suse/mmc-sdhci-Fix-incorrect-switch-to-HS-mode.patch patches.suse/ALSA-firewire-tascam-handle-error-code-when-getting-.patch patches.suse/ALSA-firewire-tascam-check-intermediate-state-of-clo.patch @@ -50911,6 +51168,7 @@ patches.suse/net-hns3-change-GFP-flag-during-lock-period.patch patches.suse/NFC-fix-attrs-checks-in-netlink-interface.patch patches.suse/bnxt_en-Update-firmware-interface-spec.-to-1.10.0.89.patch + patches.suse/bnxt_en-Support-all-variants-of-the-5750X-chip-famil.patch patches.suse/bnxt_en-Add-PCI-IDs-for-57500-series-NPAR-devices.patch patches.suse/net-mlx5e-Print-a-warning-when-LRO-feature-is-droppe.patch patches.suse/net-hns3-do-not-query-unsupported-commands-in-debugf.patch @@ -50945,18 +51203,90 @@ patches.suse/bnxt_en-Increase-timeout-for-HWRM_DBG_COREDUMP_XX-co.patch patches.suse/0001-xen-netfront-do-not-assume-sk_buff_head-list-is-empt.patch patches.suse/0001-btrfs-tree-checker-Add-ROOT_ITEM-check.patch + patches.suse/0001-btrfs-move-btrfs_add_free_space-out-of-a-header-file.patch + patches.suse/0002-btrfs-move-basic-block_group-definitions-to-their-own-header.patch + patches.suse/0003-btrfs-migrate-the-block-group-lookup-code.patch + patches.suse/0004-btrfs-migrate-the-block-group-ref-counting-stuff.patch + patches.suse/0005-btrfs-migrate-nocow-and-reservation-helpers.patch + patches.suse/0006-btrfs-export-the-block-group-caching-helpers.patch + patches.suse/0007-btrfs-export-the-excluded-extents-helpers.patch + patches.suse/0008-btrfs-export-the-caching-control-helpers.patch + patches.suse/0009-btrfs-temporarily-export-fragment_free_space.patch + patches.suse/0010-btrfs-make-caching_thread-use-btrfs_find_next_key.patch + patches.suse/0011-btrfs-migrate-the-block-group-caching-code.patch + patches.suse/0012-btrfs-temporarily-export-inc_block_group_ro.patch + patches.suse/0013-btrfs-migrate-the-block-group-removal-code.patch + patches.suse/0014-btrfs-migrate-the-block-group-read-creation-code.patch + patches.suse/0015-btrfs-temporarily-export-btrfs_get_restripe_target.patch + patches.suse/0016-btrfs-migrate-inc-dec_block_group_ro-code.patch + patches.suse/0017-btrfs-migrate-the-dirty-bg-writeout-code.patch + patches.suse/0018-btrfs-export-block-group-accounting-helpers.patch + patches.suse/0019-btrfs-migrate-the-block-group-space-accounting-helpers.patch + patches.suse/0020-btrfs-migrate-the-chunk-allocation-code.patch + patches.suse/0021-btrfs-migrate-the-alloc_profile-helpers.patch + patches.suse/0022-btrfs-migrate-the-block-group-cleanup-code.patch + patches.suse/0023-btrfs-unexport-the-temporary-exported-functions.patch + patches.suse/0001-btrfs-add-a-flush-step-for-delayed-iputs.patch + patches.suse/0002-btrfs-unify-error-handling-for-ticket-flushing.patch + patches.suse/0003-btrfs-factor-out-the-ticket-flush-handling.patch + patches.suse/0004-btrfs-refactor-priority_reclaim_metadata_space.patch + patches.suse/0005-btrfs-introduce-an-evict-flushing-state.patch patches.suse/Btrfs-fix-use-after-free-when-using-the-tree-modific.patch patches.suse/0001-btrfs-tree-checker-Add-EXTENT_ITEM-and-METADATA_ITEM.patch patches.suse/0002-btrfs-tree-checker-Add-simple-keyed-refs-check.patch patches.suse/0003-btrfs-tree-checker-Add-EXTENT_DATA_REF-check.patch + patches.suse/0006-btrfs-rename-the-btrfs_calc_-metadata_size-helpers.patch + patches.suse/0007-btrfs-only-reserve-metadata_size-for-inodes.patch + patches.suse/0008-btrfs-do-not-allow-reservations-if-we-have-pending-tickets.patch + patches.suse/0009-btrfs-roll-tracepoint-into-btrfs_space_info_update-helper.patch + patches.suse/0010-btrfs-add-space-reservation-tracepoint-for-reserved-bytes.patch + patches.suse/0011-btrfs-stop-partially-refilling-tickets-when-releasing-space.patch + patches.suse/0012-btrfs-refactor-the-ticket-wakeup-code.patch + patches.suse/0013-btrfs-rework-wake_all_tickets.patch + patches.suse/0014-btrfs-fix-may_commit_transaction-to-deal-with-no-partial-filling.patch + patches.suse/0015-btrfs-remove-orig_bytes-from-reserve_ticket.patch + patches.suse/0016-btrfs-rename-btrfs_space_info_add_old_bytes.patch + patches.suse/0017-btrfs-change-the-minimum-global-reserve-size.patch + patches.suse/0018-btrfs-always-reserve-our-entire-size-for-the-global-reserve.patch + patches.suse/0019-btrfs-use-btrfs_try_granting_tickets-in-update_global_rsv.patch + patches.suse/0020-btrfs-do-not-account-global-reserve-in-can_overcommit.patch + patches.suse/0021-btrfs-add-enospc-debug-messages-for-ticket-failure.patch + patches.suse/fs-cifs-Initialize-filesystem-timestamp-ranges.patch + patches.suse/cifs-fix-a-comment-for-the-timeouts-when-sending-echos.patch + patches.suse/fs-cifs-cifsssmb-remove-redundant-assignment-to-variable-ret.patch + patches.suse/cifs-get-mode-bits-from-special-sid-on-stat.patch + patches.suse/cifs-allow-chmod-to-set-mode-bits-using-special-sid.patch patches.suse/cifs-prepare-SMB2_Flush-to-be-usable-in-compounds.patch + patches.suse/cifs-add-passthrough-for-smb2-setinfo.patch + patches.suse/smb3-add-missing-flag-definitions.patch + patches.suse/cifs-remove-redundant-assignment-to-variable-rc.patch + patches.suse/cifs-remove-unused-variable.patch patches.suse/smb3-Incorrect-size-for-netname-negotiate-context.patch + patches.suse/cifs-remove-set-but-not-used-variables.patch patches.suse/cifs-create-a-helper-to-find-a-writeable-handle-by-path-name.patch patches.suse/cifs-use-existing-handle-for-compound_op-OP_SET_INFO-when-possible.patch + patches.suse/cifs-add-new-debugging-macro-cifs_server_dbg.patch + patches.suse/cifs-fix-dereference-on-ses-before-it-is-null-checked.patch + patches.suse/smb3-add-mount-option-to-allow-forced-caching-of-read-only-share.patch + patches.suse/smb3-add-some-more-descriptive-messages-about-share-when-mounting-c.patch + patches.suse/smb3-add-mount-option-to-allow-RW-caching-of-share-accessed-by-only.patch + patches.suse/smb3-log-warning-if-CSC-policy-conflicts-with-cache-mount-option.patch + patches.suse/smb3-add-dynamic-tracepoints-for-flush-and-close.patch + patches.suse/smb3-allow-skipping-signature-verification-for-perf-sensitive-confi.patch patches.suse/smb3-fix-signing-verification-of-large-reads.patch + patches.suse/cifs-add-a-debug-macro-that-prints-server-share-for-errors.patch + patches.suse/smb3-allow-parallelizing-decryption-of-reads.patch + patches.suse/smb3-enable-offload-of-decryption-of-large-reads-via-mount-option.patch patches.suse/cifs-add-a-helper-to-find-an-existing-readable-handle-to-a-file.patch + patches.suse/smb3-only-offload-decryption-of-read-responses-if-multiple-requests.patch + patches.suse/smb3-display-max-smb3-requests-in-flight-at-any-one-time.patch patches.suse/smb3-improve-handling-of-share-deleted-and-share-recreated-.patch + patches.suse/smb3-allow-disabling-requesting-leases.patch patches.suse/smb3-fix-unmount-hang-in-open_shroot.patch + patches.suse/smb3-fix-potential-null-dereference-in-decrypt-offload.patch + patches.suse/cifs-modefromsid-make-room-for-4-ACE.patch + patches.suse/smb3-add-missing-worker-function-for-SMB3-change-notify.patch + patches.suse/cifs-modefromsid-write-mode-ACE-first.patch patches.suse/ipmi_si-Only-schedule-continuously-in-the-thread-in-.patch patches.suse/pinctrl-tegra-Fix-write-barrier-placement-in-pmx_wri.patch patches.suse/0001-drm-i915-Fix-various-tracepoints-for-gen2.patch @@ -51013,7 +51343,7 @@ patches.suse/clk-at91-fix-update-bit-maps-on-CFG_MOR-write.patch patches.suse/clk-at91-select-parent-if-main-oscillator-or-bypass-.patch patches.suse/printk-Do-not-lose-last-line-in-kmsg-buffer-dump.patch - patches.suse/0002-drm-amdkfd-fix-a-use-after-free-race-with-mmu_notife.patch + patches.suse/0001-drm-amdkfd-fix-a-use-after-free-race-with-mmu_notife.patch patches.suse/RDMA-hns-Fix-comparison-of-unsigned-long-variable-en.patch patches.suse/RDMA-hns-Remove-the-some-magic-number.patch patches.suse/RDMA-hns-Add-reset-process-for-function-clear.patch @@ -51039,6 +51369,7 @@ patches.suse/scsi-qla2xxx-Fix-hang-in-fcport-delete-path.patch patches.suse/scsi-qla2xxx-Allow-NVMe-IO-to-resume-with-short-cabl.patch patches.suse/scsi-qla2xxx-Update-driver-version-to-10.01.00.18-k.patch + patches.suse/scsi-ibmvfc-Mark-expected-switch-fall-throughs.patch patches.suse/scsi-qla2xxx-Make-qla2x00_abort_srb-again-decrease-t.patch patches.suse/scsi-qla2xxx-Really-fix-qla2xxx_eh_abort.patch patches.suse/scsi-qla2xxx-Improve-Linux-kernel-coding-style-confo.patch @@ -51119,6 +51450,7 @@ patches.suse/scsi-lpfc-Fix-loss-of-remote-port-after-devloss-due-.patch patches.suse/scsi-lpfc-Fix-propagation-of-devloss_tmo-setting-to-.patch patches.suse/scsi-lpfc-Fix-sg_seg_cnt-for-HBAs-that-don-t-support.patch + patches.suse/scsi-lpfc-Fix-driver-nvme-rescan-logging.patch patches.suse/scsi-lpfc-Fix-error-in-remote-port-address-change.patch patches.suse/scsi-lpfc-Fix-deadlock-on-host_lock-during-cable-pul.patch patches.suse/scsi-lpfc-Fix-crash-due-to-port-reset-racing-vs-adap.patch @@ -51195,6 +51527,7 @@ patches.suse/hypfs-fix-error-number-left-in-struct-pointer-member patches.suse/platform-x86-pmc_atom-Add-Siemens-SIMATIC-IPC277E-to.patch patches.suse/platform-x86-i2c-multi-instantiate-Derive-the-device.patch + patches.suse/fat-work-around-race-with-userspace-s-read-via-block.patch patches.suse/mm-page_owner-record-page-owner-for-each-subpage.patch patches.suse/mm-page_owner-keep-owner-info-when-freeing-the-page.patch patches.suse/mm-page_owner-debug_pagealloc-save-and-dump-freeing-stack-trace.patch @@ -51213,6 +51546,7 @@ patches.suse/s390-topology-avoid-firing-events-before-kobjs-are-created patches.suse/s390-cio-avoid-calling-strlen-on-null-pointer patches.suse/s390-cio-exclude-subchannels-with-no-parent-from-pseudo-check + patches.suse/binfmt_elf-Do-not-move-brk-for-INTERP-less-ET_EXEC.patch patches.suse/drm-radeon-Bail-earlier-when-radeon.cik_-si_support-.patch patches.suse/drm-amdgpu-Check-for-valid-number-of-registers-to-re.patch patches.suse/drm-amdgpu-Fix-KFD-related-kernel-oops-on-Hawaii.patch @@ -51233,6 +51567,7 @@ patches.suse/powerpc-book3s64-radix-Rename-CPU_FTR_P9_TLBIE_BUG-f.patch patches.suse/powerpc-mm-Fixup-tlbie-vs-mtpidr-mtlpidr-ordering-is.patch patches.suse/usbnet-sanity-checking-of-packet-sizes-and-device-mt.patch + patches.suse/ibmvnic-Warn-unknown-speed-message-only-when-carrier.patch patches.suse/net-sched-act_sample-don-t-push-mac-header-on-ip6gre.patch patches.suse/sch_netem-fix-a-divide-by-zero-in-tabledist.patch patches.suse/cdc_ncm-fix-divide-by-zero-caused-by-invalid-wMaxPac.patch @@ -51268,15 +51603,23 @@ patches.suse/i2c-riic-Clear-NACK-in-tend-isr.patch patches.suse/libnvdimm-altmap-track-namespace-boundaries-in-altmap.patch patches.suse/libnvdimm-prevent-nvdimm-from-requesting-key-when-security.patch + patches.suse/smb3-allow-decryption-keys-to-be-dumped-by-admin-for-debugging.patch patches.suse/smb3-fix-leak-in-open-on-server-perf-counter.patch + patches.suse/fs-cifs-smb2pdu-c-Make-SMB2_notify_init-static.patch + patches.suse/fs-cifs-sess-c-Remove-set-but-not-used-variable-capabilities-.patch patches.suse/CIFS-fix-max-ea-value-size.patch + patches.suse/smb3-Add-missing-reparse-tags.patch + patches.suse/smb3-pass-mode-bits-into-create-calls.patch + patches.suse/smb3-missing-ACL-related-flags.patch patches.suse/CIFS-Fix-oplock-handling-for-SMB-2-1-protocols.patch patches.suse/mmc-sdhci-improve-ADMA-error-reporting.patch patches.suse/mmc-sdhci-of-esdhc-set-DMA-snooping-based-on-DMA-coh.patch patches.suse/0001-Btrfs-fix-selftests-failure-due-to-uninitialized-i_m.patch + patches.suse/btrfs-adjust-dirty_metadata_bytes-after-writeback-fa.patch patches.suse/0001-btrfs-relocation-fix-use-after-free-on-dead-relocati.patch patches.suse/0001-btrfs-qgroup-Fix-the-wrong-target-io_tree-when-freei.patch patches.suse/0002-btrfs-qgroup-Fix-reserved-data-space-leak-if-we-have.patch + patches.suse/tick-broadcast-hrtimer-fix-a-race-in-bc_set_next.patch patches.suse/drm-amdgpu-fix-multiple-memory-leaks-in-acp_hw_init.patch patches.suse/drm-amd-display-memory-leak.patch patches.suse/0001-xen-xenbus-fix-self-deadlock-after-killing-user-proc.patch @@ -51320,8 +51663,12 @@ patches.suse/xfs-Fix-tail-rounding-in-xfs_alloc_file_space.patch patches.suse/drm-amdgpu-fix-memory-leak.patch patches.suse/drm-i915-cml-Add-second-PCH-ID-for-CMP.patch + patches.suse/smb3-cleanup-some-recent-endian-errors-spotted-by-updated-sparse.patch + patches.suse/fs-cifs-mute-Wunused-const-variable-message.patch patches.suse/cifs-use-cifsInodeInfo-open_file_lock-while-iterating-to-avoid-a-p.patch patches.suse/CIFS-Gracefully-handle-QueryInfo-errors-during-open.patch + patches.suse/smb3-remove-noisy-debug-message-and-minor-cleanup.patch + patches.suse/smb3-Fix-regression-in-time-handling.patch patches.suse/CIFS-Force-revalidate-inode-when-dentry-is-stale.patch patches.suse/CIFS-Force-reval-dentry-if-LOOKUP_REVAL-flag-is-set.patch patches.suse/s390-cio-fix-virtio-ccw-dma-without-pv @@ -51431,6 +51778,7 @@ patches.suse/0001-btrfs-qgroup-Always-free-PREALLOC-META-reserve-in-bt.patch patches.suse/0001-btrfs-tracepoints-Fix-wrong-parameter-order-for-qgro.patch patches.suse/0001-btrfs-tracepoints-Fix-bad-entry-members-of-qgroup-ev.patch + patches.suse/btrfs-fix-qgroup-double-free-after-failure-to-reserve-metadata-for-delalloc.patch patches.suse/Btrfs-check-for-the-full-sync-flag-while-holding-the.patch patches.suse/edac-ghes-fix-use-after-free-in-ghes_edac-remove-path.patch patches.suse/ALSA-hda-realtek-Add-support-for-ALC711.patch @@ -51467,12 +51815,16 @@ patches.suse/Revert-ALSA-hda-Flush-interrupts-on-disabling.patch patches.suse/ALSA-timer-Fix-mutex-deadlock-at-releasing-card.patch patches.suse/RDMA-hns-Prevent-memory-leaks-of-eq-buf_list.patch + patches.suse/0001-drm-etnaviv-fix-dumping-of-iommuv2.patch patches.suse/drm-amdgpu-powerplay-vega10-allow-undervolting-in-p7.patch patches.suse/KVM-vmx-svm-always-run-with-EFER.NXE-1-when-shadow-p.patch + patches.suse/nvme-multipath-fix-possible-io-hang-after-ctrl-recon.patch + patches.suse/nvme-multipath-remove-unused-groups_only-mode-in-ana.patch patches.suse/net-mlx5-prevent-memory-leak-in-mlx5_fpga_conn_creat.patch patches.suse/r8152-add-device-id-for-Lenovo-ThinkPad-USB-C-Dock-G.patch patches.suse/net-openvswitch-free-vport-unless-register_netdevice.patch patches.suse/bonding-fix-unexpected-IFF_BONDING-bit-unset.patch + patches.suse/macsec-fix-refcnt-leak-in-module-exit-routine.patch patches.suse/net-smc-fix-closing-of-fallback-smc-sockets patches.suse/net-smc-keep-vlan_id-for-smc-r-in-smc_listen_work patches.suse/netns-fix-GFP-flags-in-rtnl_net_notifyid.patch @@ -51510,6 +51862,7 @@ patches.suse/scsi-qla2xxx-Initialized-mailbox-to-prevent-driver-l.patch patches.suse/scsi-qla2xxx-Fix-partial-flash-write-of-MBI.patch patches.suse/scsi-qla2xxx-stop-timer-in-shutdown-path.patch + patches.suse/fix-memory-leak-in-large-read-decrypt-offload.patch patches.suse/usb-gadget-udc-atmel-Fix-interrupt-storm-in-FIFO-mod.patch patches.suse/USB-ldusb-fix-ring-buffer-locking.patch patches.suse/USB-ldusb-fix-control-message-timeout.patch @@ -51536,6 +51889,7 @@ patches.suse/ceph-add-missing-check-in-d_revalidate-snapdir-handling.patch patches.suse/ceph-don-t-try-to-handle-hashed-dentries-in-non-o_creat-atomic_open.patch patches.suse/pwm-bcm-iproc-Prevent-unloading-the-driver-module-wh.patch + patches.suse/nvme-multipath-fix-crash-in-nvme_mpath_clear_ctrl_pa.patch patches.suse/cgroup-writeback-don-t-switch-wbs-immediately-on-dea.patch patches.suse/dccp-do-not-leak-jiffies-on-the-wire.patch patches.suse/can-gs_usb-gs_can_open-prevent-memory-leak.patch @@ -51573,6 +51927,7 @@ patches.suse/ice-fix-potential-infinite-loop-because-loop-counter.patch patches.suse/watchdog-meson-Fix-the-wrong-value-of-left-time.patch patches.suse/0001-btrfs-tree-checker-Fix-wrong-check-on-max-devid.patch + patches.suse/btrfs-fix-race-leading-to-metadata-space-leak-after-task-received-signal.patch patches.suse/pinctrl-cherryview-Fix-irq_valid_mask-calculation.patch patches.suse/pinctrl-cherryview-Allocate-IRQ-chip-dynamic.patch patches.suse/SMB3-Fix-persistent-handles-reconnect.patch @@ -51656,10 +52011,12 @@ patches.suse/net-sched-ensure-opts_len-IP_TUNNEL_OPTS_MAX-in-act_.patch patches.suse/net-mlx4_en-Fix-wrong-limitation-for-number-of-TX-ri.patch patches.suse/net-sched-act_pedit-fix-WARN-in-the-traffic-path.patch + patches.suse/s390-qeth-fix-potential-deadlock-on-workqueue-flush patches.suse/s390-qeth-return-proper-errno-on-io-error patches.suse/net-ibmvnic-Ignore-H_FUNCTION-return-from-H_EOI-to-t.patch patches.suse/net-mlx5e-Fix-set-vf-link-state-error-flow.patch patches.suse/net-mlx5-Update-the-list-of-the-PCI-supported-device-b7eca940.patch + patches.suse/net-mlxfw-Verify-FSM-error-code-translation-doesn-t-.patch patches.suse/0001-nfc-port100-handle-command-failure-cleanly.patch patches.suse/sfc-Only-cancel-the-PPS-workqueue-if-it-exists.patch patches.suse/msft-hv-1986-hv_netvsc-Fix-offset-usage-in-netvsc_send_table.patch @@ -51668,9 +52025,18 @@ patches.suse/0001-virtio_ring-fix-return-code-on-DMA-mapping-fails.patch patches.suse/virtio_console-allocate-inbufs-in-add_port-only-if-i.patch patches.suse/tpm-add-check-after-commands-attribs-tab-allocation.patch + patches.suse/0075-fcntl-fix-typo-in-RWH_WRITE_LIFE_NOT_SET-r-w-hint-na.patch patches.suse/blk-mq-avoid-sysfs-buffer-overflow-with-too-many-CPU.patch patches.suse/blk-mq-make-sure-that-line-break-can-be-printed.patch + patches.suse/0076-md-raid0-Fix-an-error-message-in-raid0_make_request.patch + patches.suse/0077-md-bitmap-avoid-race-window-between-md_bitmap_resize.patch + patches.suse/0078-md-no-longer-compare-spare-disk-superblock-events-in.patch patches.suse/loop-fix-no-unmap-write-zeroes-request-behavior.patch + patches.suse/nvme-resync-include-linux-nvme.h-with-nvmecli.patch + patches.suse/nvme-Fix-parsing-of-ANA-log-page.patch + patches.suse/0079-md-raid1-avoid-soft-lockup-under-high-load.patch + patches.suse/0080-md-avoid-invalid-memory-access-for-array-sb-dev_role.patch + patches.suse/0081-md-raid10-prevent-access-of-uninitialized-resync_pag.patch patches.suse/0004-bcache-fix-a-lost-wake-up-problem-caused-by-mca_cann.patch patches.suse/0005-bcache-fix-static-checker-warning-in-bcache_device_f.patch patches.suse/0006-bcache-add-more-accurate-error-messages-in-read_supe.patch @@ -51682,6 +52048,8 @@ patches.suse/0012-bcache-at-least-try-to-shrink-1-node-in-bch_mca_scan.patch patches.suse/0013-bcache-remove-the-extra-cflags-for-request.o.patch patches.suse/0014-bcache-don-t-export-symbols.patch + patches.suse/0082-drivers-md-raid5.c-use-the-new-spelling-of-RWH_WRITE.patch + patches.suse/0083-drivers-md-raid5-ppl.c-use-the-new-spelling-of-RWH_W.patch patches.suse/nbd-prevent-memory-leak.patch patches.suse/mtd-spear_smi-Fix-Write-Burst-mode.patch patches.suse/mtd-spi-nor-fix-silent-truncation-in-spi_nor_read.patch @@ -51751,7 +52119,7 @@ patches.suse/net-ath10k-Fix-a-NULL-ptr-deref-bug.patch patches.suse/0001-rt2800-remove-errornous-duplicate-condition.patch patches.suse/rtlwifi-rtl8192de-Fix-missing-code-to-retrieve-RX-bu.patch - patches.suse/rtlwifi-rtl8192de-Fix-missing-callback-that-tests-fo.patch + patches.suse/0001-rtlwifi-rtl8192de-Fix-missing-callback-that-tests-fo.patch patches.suse/rtlwifi-rtl8192de-Fix-missing-enable-interrupt-flag.patch patches.suse/bpf-skmsg-fix-potential-psock-NULL-pointer-dereferen.patch patches.suse/mac80211-consider-QoS-Null-frames-for-STA_NULLFUNC_A.patch @@ -51772,13 +52140,16 @@ patches.suse/x86-speculation-fix-incorrect-mds-taa-mitigation-status.patch patches.suse/x86-speculation-fix-redundant-mds-mitigation-message.patch patches.suse/stacktrace-get-rid-of-unneeded-pattern.patch + patches.suse/cpuidle-Do-not-unset-the-driver-if-it-is-there-alrea.patch patches.suse/cpufreq-powernv-fix-stack-bloat-and-hard-limit-on-nu.patch + patches.suse/cpufreq-Register-drivers-only-after-CPU-devices-have.patch patches.suse/PM-devfreq-Check-NULL-governor-in-available_governor.patch patches.suse/PM-devfreq-Lock-devfreq-in-trans_stat_show.patch patches.suse/ALSA-hda-Fix-pending-unsol-events-at-shutdown.patch patches.suse/ALSA-usb-audio-sound-usb-usb-true-false-for-bool-ret.patch patches.suse/ALSA-firewire-motu-Correct-a-typo-in-the-clock-proc-.patch patches.suse/ALSA-6fire-Drop-the-dead-code.patch + patches.suse/ASoC-pcm-update-FE-BE-trigger-order-based-on-the-com.patch patches.suse/ALSA-pcm-Yet-another-missing-check-of-non-cached-buf.patch patches.suse/ALSA-hda-hdmi-Clean-up-Intel-platform-specific-fixup.patch patches.suse/ALSA-usb-audio-Add-skip_validation-option.patch @@ -51800,6 +52171,10 @@ patches.suse/0001-media-ov6650-Fix-control-handler-not-freed-on-init-e.patch patches.suse/0001-media-ov6650-Fix-crop-rectangle-alignment-not-passed.patch patches.suse/0001-media-ov6650-Fix-incorrect-use-of-JPEG-colorspace.patch + patches.suse/media-ov6650-Fix-some-format-attributes-not-under-co.patch + patches.suse/media-ov6650-Fix-.get_fmt-V4L2_SUBDEV_FORMAT_TRY-sup.patch + patches.suse/media-ov6650-Fix-stored-frame-format-not-in-sync-wit.patch + patches.suse/media-ov6650-Fix-stored-crop-rectangle-not-in-sync-w.patch patches.suse/media-rc-prevent-memory-leak-in-cx23888_ir_probe.patch patches.suse/media-usbvision-Fix-races-among-open-close-and-disco.patch patches.suse/media-ti-vpe-vpe-Fix-Motion-Vector-vpdma-stride.patch @@ -51838,12 +52213,14 @@ patches.suse/usbip-tools-fix-fd-leakage-in-the-function-of-read_a.patch patches.suse/0001-USB-chaoskey-fix-error-case-of-a-timeout.patch patches.suse/0001-USBIP-add-config-dependency-for-SGL_ALLOC.patch + patches.suse/0001-usbip-Fix-uninitialized-symbol-nents-in-stub_recv_cm.patch patches.suse/USB-serial-mos7840-add-USB-ID-to-support-Moxa-UPort-.patch patches.suse/USB-serial-option-add-support-for-DW5821e-with-eSIM-.patch patches.suse/USB-serial-mos7720-fix-remote-wakeup.patch patches.suse/USB-serial-mos7840-fix-remote-wakeup.patch patches.suse/USB-serial-option-add-support-for-Foxconn-T77W968-LT.patch patches.suse/USB-serial-ftdi_sio-add-device-IDs-for-U-Blox-C099-F.patch + patches.suse/0001-usb-host-xhci-update-event-ring-dequeue-pointer-on-p.patch patches.suse/usb-gadget-u_serial-add-missing-port-entry-locking.patch patches.suse/usb-serial-cp201x-support-Mark-10-digital-force-gaug.patch patches.suse/USB-uas-honor-flag-to-avoid-CAPACITY16.patch @@ -51874,6 +52251,10 @@ patches.suse/staging-rtl8192e-fix-potential-use-after-free.patch patches.suse/staging-rtl8723bs-Add-024c-0525-to-the-list-of-SDIO-.patch patches.suse/staging-rtl8723bs-Drop-ACPI-device-ids.patch + patches.suse/iio-gyro-adis16136-check-ret-val-for-non-zero-vs-les.patch + patches.suse/iio-imu-adis16400-check-ret-val-for-non-zero-vs-less.patch + patches.suse/iio-imu-adis16480-check-ret-val-for-non-zero-vs-less.patch + patches.suse/iio-imu-adis-check-ret-val-for-non-zero-vs-less-than.patch patches.suse/iio-imu-adis16480-assign-bias-value-only-if-operatio.patch patches.suse/iio-imu-adis-assign-read-val-in-debugfs-hook-only-if.patch patches.suse/iio-imu-adis-assign-value-only-if-return-code-zero-i.patch @@ -51901,21 +52282,38 @@ patches.suse/ext4-fix-a-bug-in-ext4_wait_for_tail_page_commit.patch patches.suse/ext4-add-more-paranoia-checking-in-ext4_expand_extra.patch patches.suse/ext4-work-around-deleting-a-file-with-i_nlink-0-safe.patch + patches.suse/cifs-rename-a-variable-in-SendReceive-.patch + patches.suse/cifs-remove-unused-variable-sid_user-.patch patches.suse/cifs-add-support-for-flock.patch patches.suse/CIFS-remove-set-but-not-used-variables-cinode-and-netfid-.patch + patches.suse/cifs-Don-t-display-RDMA-transport-on-reconnect.patch + patches.suse/cifs-smbd-Invalidate-and-deregister-memory-registration-on-re-send.patch + patches.suse/cifs-smbd-Return-EINVAL-when-the-number-of-iovs-exceeds-SMBDIRECT.patch + patches.suse/cifs-smbd-Add-messages-on-RDMA-session-destroy-and-reconnection.patch + patches.suse/cifs-smbd-Return-ECONNABORTED-when-trasnport-is-not-in-connected-.patch + patches.suse/CIFS-Use-memdup_user-rather-than-duplicating-its-implementation.patch + patches.suse/CIFS-Use-common-error-handling-code-in-smb2_ioctl_query_info-.patch + patches.suse/CIFS-Return-directly-after-a-failed-build_path_from_dentry-in-cif.patch patches.suse/cifs-close-the-shared-root-handle-on-tree-disconnect.patch patches.suse/smb3-remove-confusing-dmesg-when-mounting-with-encryption-seal-.patch patches.suse/CIFS-Respect-O_SYNC-and-O_DIRECT-flags-during-reconnect.patch patches.suse/CIFS-Close-open-handle-after-interrupted-close.patch patches.suse/CIFS-Fix-NULL-pointer-dereference-in-mid-callback.patch patches.suse/CIFS-Do-not-miss-cancelled-OPEN-responses.patch + patches.suse/smb3-add-debug-messages-for-closing-unmatched-open.patch + patches.suse/cifs-smbd-Only-queue-work-for-error-recovery-on-memory-registratio.patch + patches.suse/cifs-smbd-Return-EAGAIN-when-transport-is-reconnecting.patch + patches.suse/cifs-don-t-use-pre-for-MODULE_SOFTDEP.patch patches.suse/CIFS-Fix-SMB2-oplock-break-processing.patch + patches.suse/CIFS-refactor-cifs_get_inode_info-.patch patches.suse/cifs-move-cifsFileInfo_put-logic-into-a-work-queue.patch patches.suse/CIFS-Properly-process-SMB3-lease-breaks.patch + patches.suse/smb3-dump-in_send-and-num_waiters-stats-counters-by-default.patch patches.suse/cifs-Fix-use-after-free-bug-in-cifs_reconnect-.patch patches.suse/cifs-Fix-lookup-of-root-ses-in-DFS-referral-cache.patch patches.suse/cifs-Fix-potential-softlockups-while-refreshing-DFS-cache.patch patches.suse/cifs-Fix-retrieval-of-DFS-referrals-in-cifs_mount-.patch + patches.suse/CIFS-fix-a-white-space-issue-in-cifs_get_inode_info-.patch patches.suse/quota-fix-livelock-in-dquot_writeback_dquots.patch patches.suse/quota-Check-that-quota-is-not-dirty-before-release.patch patches.suse/ext2-check-err-when-partial-NULL.patch @@ -51956,10 +52354,13 @@ patches.suse/platform-x86-hp-wmi-Fix-ACPI-errors-caused-by-passin.patch patches.suse/cdrom-respect-device-capabilities-during-opening-act.patch patches.suse/sr_vendor-support-Beurer-GL50-evo-CD-on-a-chip-devic.patch + patches.suse/libnvdimm-pfn_dev-Don-t-clear-device-memmap-area-dur.patch patches.suse/libnvdimm-namespace-Differentiate-between-probe-mapp.patch patches.suse/libnvdimm-export-the-target_node-attribute-for-regions-and-namespaces.patch patches.suse/Input-synaptics-rmi4-simplify-data-read-in-rmi_f54_w.patch patches.suse/Input-synaptics-switch-another-X1-Carbon-6-to-RMI-SM.patch + patches.suse/net-tls-take-into-account-that-bpf_exec_tx_verdict-m.patch + patches.suse/net-tls-free-the-record-on-encryption-error.patch patches.suse/tipc-fix-wrong-timeout-input-for-tipc_wait_for_cond.patch patches.suse/net-sched-fix-tc-s-class-show-no-bstats-on-class-wit.patch patches.suse/openvswitch-drop-unneeded-BUG_ON-in-ovs_flow_cmd_bui.patch @@ -52095,6 +52496,7 @@ patches.suse/drm-limit-to-INT_MAX-in-create_blob-ioctl.patch patches.suse/thermal-Fix-deadlock-in-thermal-thermal_zone_device_.patch patches.suse/moduleparam-fix-parameter-description-mismatch.patch + patches.suse/module-wakeup-processes-in-module_wq-on-mod.patch patches.suse/fsnamei.c-pull-positivity-check-into-follow_managed.patch patches.suse/new-helper-lookup_positive_unlocked.patch patches.suse/fix-dget_parent-fastpath-race.patch @@ -52111,10 +52513,16 @@ patches.suse/powerpc-xive-Skip-ioremap-of-ESB-pages-for-LSI-inter.patch patches.suse/powerpc-Fix-vDSO-clock_getres.patch patches.suse/powerpc-archrandom-fix-arch_get_random_seed_int.patch + patches.suse/SUNRPC-Fix-svcauth_gss_proxy_init.patch patches.suse/Input-goodix-add-upside-down-quirk-for-Teclast-X89-t.patch patches.suse/Input-synaptics-rmi4-don-t-increment-rmiaddr-for-SMB.patch patches.suse/CIFS-Fix-NULL-pointer-dereference-in-smb2_push_mandatory_locks.patch patches.suse/fs-cifs-Fix-atime-update-check-vs-mtime.patch + patches.suse/cifs-remove-redundant-assignment-to-pointer-pneg_ctxt.patch + patches.suse/smb3-remove-unused-flag-passed-into-close-functions.patch + patches.suse/smb3-query-attributes-on-file-close.patch + patches.suse/smb3-fix-mode-passed-in-on-create-for-modetosid-mount-option.patch + patches.suse/smb3-improve-check-for-when-we-send-the-security-descriptor-context.patch patches.suse/lpfc-size-cpu-map-by-last-cpu-id-set.patch patches.suse/scsi-qla2xxx-fix-rports-not-being-mark-as-lost-in-sy.patch patches.suse/scsi-qla2xxx-unregister-ports-after-GPN_FT-failure.patch @@ -52132,6 +52540,9 @@ patches.suse/inet-protect-against-too-small-mtu-values.patch patches.suse/net-ethernet-ti-cpsw-fix-extra-rx-interrupt.patch patches.suse/vhost-vsock-accept-only-packets-with-the-right-dst_c.patch + patches.suse/0084-raid5-need-to-set-STRIPE_HANDLE-for-batch-head.patch + patches.suse/0085-md-raid1-check-rdev-before-reference-in-raid1_sync_r.patch + patches.suse/0086-md-make-sure-desc_nr-less-than-MD_SB_DISKS.patch patches.suse/dma-buf-Fix-memory-leak-in-sync_file_merge.patch patches.suse/drm-meson-venc-cvbs-fix-CVBS-mode-matching.patch patches.suse/ALSA-echoaudio-simplify-get_audio_levels.patch @@ -52162,6 +52573,7 @@ patches.suse/scsi-qla2xxx-Correctly-retrieve-and-interpret-active.patch patches.suse/scsi-qla2xxx-Added-support-for-MPI-and-PEP-regions-f.patch patches.suse/scsi-qla2xxx-Fix-incorrect-SFUB-length-used-for-Secu.patch + patches.suse/scsi-lpfc-Fix-memory-leak-on-lpfc_bsg_write_ebuf_set.patch patches.suse/0001-scsi-qla2xxx-Ignore-NULL-pointer-in-tcm_qla2xxx_free.patch patches.suse/0002-scsi-qla2xxx-Use-explicit-LOGO-in-target-mode.patch patches.suse/0003-scsi-qla2xxx-Initialize-free_work-before-flushing-it.patch @@ -52177,6 +52589,7 @@ patches.suse/0013-scsi-qla2xxx-Add-debug-dump-of-LOGO-payload-and-ELS-.patch patches.suse/scsi-libsas-stop-discovering-if-oob-mode-is-disconnected patches.suse/IB-mlx5-Fix-steering-rule-of-drop-and-count.patch + patches.suse/efi-Don-t-attempt-to-map-RCI2-config-table-if-it-doe.patch patches.suse/regulator-rn5t618-fix-module-aliases.patch patches.suse/btrfs-do-not-call-synchronize_srcu-in-inode_tree_del.patch patches.suse/btrfs-don-t-double-lock-the-subvol_sem-for-rename-exchange.patch @@ -52238,6 +52651,7 @@ patches.suse/gtp-fix-wrong-condition-in-gtp_genl_dump_pdp.patch patches.suse/gtp-fix-an-use-after-free-in-ipv4_pdp_find.patch patches.suse/gtp-avoid-zero-size-hashtable.patch + patches.suse/net-smc-add-fallback-check-to-connect patches.suse/mwifiex-fix-possible-heap-overflow-in-mwifiex_proces.patch patches.suse/mwifiex-Fix-heap-overflow-in-mmwifiex_process_tdls_a.patch patches.suse/net-qlogic-Fix-error-paths-in-ql_alloc_large_buffers.patch @@ -52252,6 +52666,9 @@ patches.suse/ext4-check-for-directory-entries-too-close-to-block-.patch patches.suse/gpio-Fix-error-message-on-out-of-range-GPIO-in-looku.patch patches.suse/scsi-lpfc-fix-build-failure-with-DEBUGFS-disabled.patch + patches.suse/scsi-lpfc-fix-spelling-mistakes-of-asynchronous.patch + patches.suse/cifs-Adjust-indentation-in-smb2_open_file.patch + patches.suse/cifs-Optimize-readdir-on-reparse-points.patch patches.suse/udp-fix-integer-overflow-while-computing-available-s.patch patches.suse/net-mlxfw-Fix-out-of-memory-error-in-mfa2-flash-burn.patch patches.suse/pstore-ram-Write-new-dumps-to-start-of-recycled-zone.patch @@ -52273,13 +52690,24 @@ patches.suse/watchdog-rn5t618_wdt-fix-module-aliases.patch patches.suse/ftrace-avoid-potential-division-by-zero-in-function-profiler.patch patches.suse/kernel-trace-fix-do-not-unregister-tracepoints-when-register-sched_migrate_task-fail.patch + patches.suse/tcp-fix-old-stuff-D-SACK-causing-SACK-to-be-treated-.patch + patches.suse/vxlan-fix-tos-value-before-xmit.patch patches.suse/can-can_dropped_invalid_skb-ensure-an-initialized-he.patch patches.suse/can-gs_usb-gs_usb_probe-use-descriptors-of-current-a.patch patches.suse/can-mscan-mscan_rx_poll-fix-rx-path-lockup-when-retu.patch + patches.suse/sctp-free-cmd-obj.chunk-for-the-unprocessed-SCTP_CMD.patch + patches.suse/net-dsa-mv88e6xxx-Preserve-priority-when-setting-CPU.patch + patches.suse/vlan-fix-memory-leak-in-vlan_dev_set_egress_priority.patch + patches.suse/vlan-vlan_changelink-should-propagate-errors.patch + patches.suse/net-usb-lan78xx-fix-possible-skb-leak.patch + patches.suse/net-stmmac-dwmac-sunxi-Allow-all-RGMII-modes.patch + patches.suse/pkt_sched-fq-do-not-accept-silly-TCA_FQ_QUANTUM.patch patches.suse/mlxsw-spectrum_qdisc-Ignore-grafting-of-invisible-FI.patch + patches.suse/net-sch_prio-When-ungrafting-replace-with-FIFO.patch patches.suse/macvlan-do-not-assume-mac_header-is-set-in-macvlan_b.patch patches.suse/HID-hidraw-Fix-returning-EPOLLOUT-from-hidraw_poll.patch patches.suse/HID-uhid-Fix-returning-EPOLLOUT-from-uhid_char_poll.patch + patches.suse/0001-Input-add-safety-guards-to-input_set_keycode.patch patches.suse/RDMA-bnxt_re-Avoid-freeing-MR-resources-if-dereg-fai.patch patches.suse/IB-hfi1-Don-t-cancel-unused-work-item.patch patches.suse/drm-dp_mst-correct-the-shifting-in-DP_REMOTE_I2C_REA.patch @@ -52289,6 +52717,7 @@ patches.suse/ALSA-usb-audio-Apply-the-sample-rate-quirk-for-Bose-.patch patches.suse/ALSA-hda-realtek-Set-EAPD-control-to-default-for-ALC.patch patches.suse/ALSA-hda-realtek-Add-quirk-for-the-bass-speaker-on-L.patch + patches.suse/nvme-Translate-more-status-codes-to-blk_status_t.patch patches.suse/staging-comedi-adv_pci1710-fix-AI-channels-16-31-for.patch patches.suse/chardev-Avoid-potential-use-after-free-in-chrdev_ope.patch patches.suse/0001-USB-core-fix-check-for-duplicate-endpoints.patch @@ -52297,12 +52726,14 @@ patches.suse/0001-USB-serial-option-add-Telit-ME910G1-0x110a-compositi.patch patches.suse/0001-USB-serial-option-add-ZLP-support-for-0x1bc7-0x9010.patch patches.suse/usb-musb-fix-idling-for-suspend-after-disconnect-int.patch + patches.suse/0001-usb-musb-Disable-pullup-at-init.patch patches.suse/HID-hidraw-uhid-Always-report-EPOLLOUT.patch patches.suse/iommu-remove-device-link-to-group-on-failure patches.suse/iommu-vt-d-unlink-device-if-failed-to-add-to-group patches.suse/drm-i915-gen9-Clear-residual-context-state-on-contex.patch patches.suse/mm-debug_pagealloc-don-t-rely-on-static-keys-too-ear.patch patches.suse/fix-autofs-regression-caused-by-follow_managed-changes.patch + patches.suse/platform-mellanox-fix-potential-deadlock-in-the-tmfi.patch patches.suse/platform-x86-asus-wmi-Fix-keyboard-brightness-cannot.patch patches.suse/clk-Don-t-try-to-enable-critical-clocks-if-prepare-f.patch patches.suse/clk-mmp2-Fix-the-order-of-timer-mux-parents.patch @@ -52327,6 +52758,7 @@ patches.suse/x86-resctrl-fix-potential-memory-leak.patch patches.suse/drm-i915-Add-missing-include-file-linux-math64.h.patch patches.suse/sh_eth-check-sh_eth_cpu_data-dual_port-when-dumping-.patch + patches.suse/net-tls-fix-async-operation.patch patches.suse/qmi_wwan-Add-support-for-Quectel-RM500Q.patch patches.suse/NFC-pn533-fix-bulk-message-timeout.patch patches.suse/net-usb-lan78xx-limit-size-of-local-TSO-packets.patch @@ -52339,16 +52771,25 @@ patches.suse/cfg80211-fix-memory-leak-in-cfg80211_cqm_rssi_update.patch patches.suse/cfg80211-check-for-set_wiphy_params.patch patches.suse/cfg80211-fix-page-refcount-issue-in-A-MSDU-decap.patch + patches.suse/mlxsw-spectrum-Wipe-xstats.backlog-of-down-ports.patch + patches.suse/mlxsw-spectrum_qdisc-Include-MC-TCs-in-Qdisc-counter.patch + patches.suse/tcp-fix-marked-lost-packets-not-being-retransmitted.patch + patches.suse/hv_netvsc-Fix-memory-leak-when-removing-rndis-device.patch patches.suse/batman-adv-Fix-DAT-candidate-selection-on-little-end.patch + patches.suse/net-wan-fsl_ucc_hdlc-fix-out-of-bounds-write-on-arra.patch patches.suse/bpf-sockmap-Read-psock-ingress_msg-before-sk_receive.patch patches.suse/bpf-Fix-incorrect-verifier-simulation-of-ARSH-under-.patch patches.suse/macvlan-use-skb_reset_mac_header-in-macvlan_queue_xm.patch + patches.suse/net-dsa-tag_qca-fix-doubled-Tx-statistics.patch + patches.suse/net-hns-fix-soft-lockup-when-there-is-not-enough-mem.patch + patches.suse/bnxt_en-Fix-NTUPLE-firmware-command-failures.patch patches.suse/hwmon-nct7802-Fix-voltage-limits-to-wrong-registers.patch patches.suse/hwmon-adt7475-Make-volt2reg-return-same-reg-as-reg2v.patch patches.suse/hwmon-core-Do-not-use-device-managed-functions-for-m.patch patches.suse/tracing-xen-ordered-comparison-of-function-pointers.patch patches.suse/mmc-tegra-fix-SDR50-tuning-override.patch patches.suse/mmc-sdhci-fix-minimum-clock-rate-for-v3-controller.patch + patches.suse/0003-drm-i915-userptr-fix-size-calculation.patch patches.suse/powerpc-xive-Discard-ESB-load-value-when-interrupt-i.patch patches.suse/iommu-amd-fix-iommu-perf-counter-clobbering-during-init patches.suse/Input-sun4i-ts-add-a-check-for-devm_thermal_zone_of_.patch @@ -52362,17 +52803,40 @@ patches.suse/Input-pm8xxx-vib-fix-handling-of-separate-enable-reg.patch patches.suse/0001-btrfs-scrub-Require-mandatory-block-group-RO-for-dev.patch patches.suse/0001-btrfs-dev-replace-remove-warning-for-unknown-return-.patch + patches.suse/net-ip6_gre-fix-moving-ip6gre-between-namespaces.patch + patches.suse/net-sysfs-Fix-reference-count-leak.patch + patches.suse/tcp_bbr-improve-arithmetic-division-in-bbr_update_bw.patch + patches.suse/net-usb-lan78xx-Add-.ndo_features_check.patch + patches.suse/net-ip_tunnel-fix-namespaces-move.patch patches.suse/can-slip-Protect-tty-disc_data-in-write_wakeup-and-c.patch + patches.suse/net-ip6_tunnel-fix-namespaces-move.patch + patches.suse/net-rtnetlink-validate-IFLA_MTU-attribute-in-rtnl_cr.patch + patches.suse/gtp-make-sure-only-SOCK_DGRAM-UDP-sockets-are-accept.patch patches.suse/r8152-get-default-setting-of-WOL-before-initializing.patch + patches.suse/tun-add-mutex_unlock-call-and-napi.skb-clearing-in-t.patch patches.suse/libertas-Fix-two-buffer-overflows-at-parsing-bss-des.patch patches.suse/iwlwifi-mvm-fix-NVM-check-for-3168-devices.patch + patches.suse/net_sched-fix-datalen-for-ematch.patch + patches.suse/net-cxgb3_main-Add-CAP_NET_ADMIN-check-to-CHELSIO_GE.patch + patches.suse/net-mlx5-Fix-lowest-FDB-pool-size.patch + patches.suse/net-mlx5-Update-the-list-of-the-PCI-supported-device-505a7f54.patch patches.suse/firestream-fix-memory-leaks.patch patches.suse/do_last-fetch-directory--i_mode-and--i_uid-before-its-too-late.patch + patches.suse/scsi-fnic-do-not-queue-commands-during-fwreset.patch + patches.suse/EDAC-skx_common-downgrade-message-importance-on-miss.patch patches.suse/mmc-spi-Toggle-SPI-polarity-do-not-hardcode-it.patch patches.suse/livepatch-selftest-clean-up-shadow-variable-names-and-type.patch patches.suse/livepatch-samples-selftest-use-klp_shadow_alloc-api-correctly.patch patches.suse/regulator-rk808-Lower-log-level-on-optional-GPIOs-be.patch + patches.suse/apei-ghes-Do-not-delay-GHES-polling.patch patches.suse/ACPI-video-Do-not-export-a-non-working-backlight-int.patch + patches.suse/0087-md-bitmap-small-cleanups.patch + patches.suse/0088-raid6-test-fix-a-compilation-error.patch + patches.suse/0089-raid6-test-fix-a-compilation-warning.patch + patches.suse/0090-md-raid6-fix-algorithm-choice-under-larger-PAGE_SIZE.patch + patches.suse/0091-raid5-remove-worker_cnt_per_group-argument-from-allo.patch + patches.suse/0092-md-rename-wb-stuffs.patch + patches.suse/0093-md-fix-a-typo-s-creat-create.patch patches.suse/0015-lib-crc64-include-linux-crc64.h-for-crc64_be.patch patches.suse/0016-bcache-add-code-comments-for-state-pool-in-__btree_s.patch patches.suse/0017-bcache-avoid-unnecessary-btree-nodes-flushing-in-btr.patch @@ -52381,11 +52845,37 @@ patches.suse/0020-bcache-reap-c-btree_cache_freeable-from-the-tail-in-.patch patches.suse/0021-bcache-reap-from-tail-of-c-btree_cache-in-bch_mca_sc.patch patches.suse/clocksource-drivers-bcm2835_timer-Fix-memory-leak-of.patch + patches.suse/irqdomain-Fix-a-memory-leak-in-irq_domain_push_irq.patch patches.suse/x86-cpu-update-cached-hle-state-on-write-to-tsx_ctrl_cpuid_clear patches.suse/x86-resctrl-check-monitoring-static-key-in-the-mbm-overflow-handler.patch patches.suse/Btrfs-fix-infinite-loop-during-fsync-after-rename-op.patch patches.suse/ubifs-don-t-trigger-assertion-on-invalid-no-key-file.patch + patches.suse/fs-cifs-smb2ops-c-use-true-false-for-bool-variable.patch + patches.suse/fs-cifs-cifssmb-c-use-true-false-for-bool-variable.patch + patches.suse/cifs-prepare-SMB2_query_directory-to-be-used-with-compounding.patch + patches.suse/cifs-create-a-helper-function-to-parse-the-query-directory-response.patch + patches.suse/cifs-use-compounding-for-open-and-first-query-dir-for-readdir-.patch + patches.suse/cifs-set-correct-max-buffer-size-for-smb2_ioctl_init-.patch + patches.suse/cifs-Clean-up-DFS-referral-cache.patch + patches.suse/cifs-Get-rid-of-kstrdup_const-d-paths.patch + patches.suse/cifs-Introduce-helpers-for-finding-TCP-connection.patch + patches.suse/cifs-Merge-is_path_valid-into-get_normalized_path-.patch + patches.suse/cifs-Fix-potential-deadlock-when-updating-vol-in-cifs_reconnect-.patch + patches.suse/cifs-Avoid-doing-network-I-O-while-holding-cache-lock.patch + patches.suse/cifs-Fix-return-value-in-__update_cache_entry.patch + patches.suse/cifs-fix-unitialized-variable-poential-problem-with-network-I-O-cac.patch + patches.suse/cifs-Fix-mount-options-set-in-automount.patch + patches.suse/cifs-Fix-memory-allocation-in-__smb2_handle_cancelled_cmd-.patch + patches.suse/cifs-remove-set-but-not-used-variable-server-2.patch + patches.suse/CIFS-Add-support-for-setting-owner-info-dos-attributes-and-create.patch + patches.suse/smb3-fix-default-permissions-on-new-files-when-mounting-with-modefr.patch + patches.suse/cifs-fix-NULL-dereference-in-match_prepath.patch + patches.suse/cifs-add-support-for-fallocate-mode-0-for-non-sparse-files.patch + patches.suse/cifs-use-PTR_ERR_OR_ZERO-to-simplify-code.patch + patches.suse/CIFS-Fix-task-struct-use-after-free-on-reconnect.patch + patches.suse/0001-crypto-pcrypt-Fix-user-after-free-on-module-unload.patch patches.suse/crypto-pcrypt-Do-not-clear-MAY_SLEEP-flag-in-origina.patch + patches.suse/0001-padata-always-acquire-cpu_hotplug_lock-before-pinst-.patch patches.suse/crypto-af_alg-Use-bh_lock_sock-in-sk_destruct.patch patches.suse/crypto-api-Check-spawn-alg-under-lock-in-crypto_drop.patch patches.suse/crypto-api-Fix-race-condition-in-crypto_spawn_alg.patch @@ -52393,9 +52883,13 @@ patches.suse/crypto-chelsio-fix-writing-tfm-flags-to-wrong-place.patch patches.suse/crypto-atmel-sha-fix-error-handling-when-setting-hma.patch patches.suse/crypto-caam-qi2-fix-typo-in-algorithm-s-driver-name.patch + patches.suse/NFC-port100-Convert-cpu_to_le16-le16_to_cpu-E1-E2-to.patch patches.suse/ppp-Adjust-indentation-into-ppp_async_input.patch patches.suse/NFC-pn544-Adjust-indentation-in-pn544_hci_check_pres.patch patches.suse/brcmfmac-Fix-memory-leak-in-brcmf_p2p_create_p2pdev.patch + patches.suse/b43legacy-Fix-Wcast-function-type.patch + patches.suse/iwlegacy-Fix-Wcast-function-type.patch + patches.suse/rtlwifi-rtl_pci-Fix-Wcast-function-type.patch patches.suse/bcma-remove-set-but-not-used-variable-sizel.patch patches.suse/brcmfmac-Fix-use-after-free-in-brcmf_sdio_readframes.patch patches.suse/mwifiex-delete-unused-mwifiex_get_intf_num.patch @@ -52405,7 +52899,10 @@ patches.suse/rsi_91x_usb-fix-interface-sanity-check.patch patches.suse/zd1211rw-fix-storage-endpoint-lookup.patch patches.suse/brcmfmac-Fix-memory-leak-in-brcmf_usbdev_qinit.patch + patches.suse/orinoco-avoid-assertion-in-case-of-NULL-pointer.patch patches.suse/ath9k-fix-storage-endpoint-lookup.patch + patches.suse/ptr_ring-add-include-of-linux-mm.h.patch + patches.suse/net_sched-ematch-reject-invalid-TCF_EM_SIMPLE.patch patches.suse/Bluetooth-Fix-race-condition-in-hci_release_sock.patch patches.suse/mwifiex-drop-most-magic-numbers-from-mwifiex_process.patch patches.suse/brcmfmac-sdio-Fix-OOB-interrupt-initialization-on-br.patch @@ -52415,25 +52912,35 @@ patches.suse/Revert-ath10k-fix-DMA-related-firmware-crashes-on-mu.patch patches.suse/ath10k-Correct-the-DMA-direction-for-management-tx-b.patch patches.suse/ALSA-control-remove-useless-assignment-in-.info-call.patch + patches.suse/ALSA-usx2y-Adjust-indentation-in-snd_usX2Y_hwdep_dsp.patch + patches.suse/ALSA-usb-audio-fix-Corsair-Virtuoso-mixer-label-coll.patch patches.suse/ALSA-hda-constify-copied-structure.patch patches.suse/ALSA-hda-Constify-snd_kcontrol_new-items.patch patches.suse/ALSA-hda-Constify-snd_pci_quirk-tables.patch patches.suse/ALSA-hda-constify-and-cleanup-static-NodeID-tables.patch patches.suse/ALSA-sh-Fix-unused-variable-warnings.patch patches.suse/ALSA-hda-realtek-Apply-mic-mute-LED-quirk-for-Dell-E.patch + patches.suse/ALSA-usb-audio-Use-lower-hex-numbers-for-IDs.patch patches.suse/ALSA-hda-realtek-More-constifications.patch patches.suse/ALSA-hda-More-constifications.patch patches.suse/ALSA-sh-Fix-compile-warning-wrt-const.patch patches.suse/ALSA-hda-patch_realtek-fix-empty-macro-usage-in-if-b.patch + patches.suse/ALSA-usb-audio-Add-boot-quirk-for-MOTU-M-Series.patch patches.suse/ALSA-hda-correct-kernel-doc-parameter-descriptions.patch patches.suse/ALSA-hda-patch_hdmi-remove-warnings-with-empty-body.patch + patches.suse/ALSA-usb-audio-unlock-on-error-in-probe.patch + patches.suse/ALSA-usb-audio-add-implicit-fb-quirk-for-MOTU-M-Seri.patch patches.suse/ALSA-hda-analog-Minor-optimization-for-SPDIF-mux-con.patch patches.suse/ALSA-hda-realtek-Add-Headset-Mic-supported-for-HP-cP.patch patches.suse/ALSA-hda-hdmi-add-retry-logic-to-parse_intel_hdmi.patch patches.suse/ALSA-hda-Add-docking-station-support-for-Lenovo-Thin.patch patches.suse/ALSA-hda-Add-Clevo-W65_67SB-the-power_save-blacklist.patch + patches.suse/ALSA-usb-audio-add-quirks-for-Line6-Helix-devices-fw.patch patches.suse/s390-ftrace-generate-traced-function-stack-frame.patch patches.suse/pinctrl-sh-pfc-r8a7778-Fix-duplicate-SDSELF_B-and-SD.patch + patches.suse/pinctrl-sh-pfc-sh7264-Fix-CAN-function-GPIOs.patch + patches.suse/pinctrl-sh-pfc-sh7269-Fix-CAN-function-GPIOs.patch + patches.suse/pinctrl-baytrail-Do-not-clear-IRQ-flags-on-direct-ir.patch patches.suse/usb-gadget-legacy-set-max_speed-to-super-speed.patch patches.suse/usb-dwc3-turn-off-VBUS-when-leaving-host-mode.patch patches.suse/usb-gadget-f_ncm-Use-atomic_t-to-track-in-flight-req.patch @@ -52443,11 +52950,15 @@ patches.suse/USB-serial-ir-usb-add-missing-endpoint-sanity-check.patch patches.suse/USB-serial-ir-usb-fix-link-speed-handling.patch patches.suse/USB-serial-ir-usb-fix-IrLAP-framing.patch + patches.suse/ttyprintk-fix-a-potential-deadlock-in-interrupt-cont.patch patches.suse/serial-8250_bcm2835aux-Fix-line-mismatch-on-driver-u.patch patches.suse/staging-vt6656-correct-packet-types-for-CTS-protect-.patch patches.suse/staging-vt6656-use-NULLFUCTION-stack-on-mac80211.patch patches.suse/staging-vt6656-Fix-false-Tx-excessive-retries-report.patch patches.suse/staging-wlan-ng-ensure-error-return-is-actually-retu.patch + patches.suse/driver-core-platform-Prevent-resouce-overflow-from-c.patch + patches.suse/driver-core-Print-device-when-resources-present-in-r.patch + patches.suse/driver-core-platform-fix-u32-greater-or-equal-to-zer.patch patches.suse/namei-only-return-ECHILD-from-follow_dotdot_rcu.patch patches.suse/scsi-qla2xxx-Remove-defer-flag-to-indicate-immeadiat.patch patches.suse/scsi-qla2xxx-Fix-fabric-scan-hang.patch @@ -52463,12 +52974,24 @@ patches.suse/scsi-qla2xxx-Fix-stuck-session-in-GNL.patch patches.suse/scsi-qla2xxx-Fix-mtcp-dump-collection-failure.patch patches.suse/scsi-qla2xxx-Update-driver-version-to-10.01.00.22-k.patch + patches.suse/scsi-lpfc-Fix-incomplete-NVME-discovery-when-target.patch + patches.suse/scsi-lpfc-Fix-Rework-setting-of-fdmi-symbolic-node-n.patch + patches.suse/scsi-lpfc-Fix-missing-check-for-CSF-in-Write-Object-.patch + patches.suse/scsi-lpfc-Fix-Fabric-hostname-registration-if-system.patch + patches.suse/scsi-lpfc-Fix-ras_log-via-debugfs.patch + patches.suse/scsi-lpfc-Fix-disablement-of-FC-AL-on-lpe35000-model.patch + patches.suse/scsi-lpfc-Fix-unmap-of-dpp-bars-affecting-next-drive.patch + patches.suse/scsi-lpfc-Fix-MDS-Latency-Diagnostics-Err-drop-rates.patch + patches.suse/scsi-lpfc-Fix-improper-flag-check-for-IO-type.patch + patches.suse/scsi-lpfc-Update-lpfc-version-to-12.6.0.3.patch patches.suse/scsi-qla2xxx-Improve-readability-of-the-code-that-ha.patch patches.suse/scsi-qla2xxx-Fix-the-endianness-of-the-qla82xx_get_f.patch patches.suse/scsi-qla2xxx-Use-get_unaligned_-instead-of-open-codi.patch + patches.suse/scsi-lpfc-Make-lpfc_defer_acc_rsp-static.patch patches.suse/scsi-qla2xxx-Fix-a-NULL-pointer-dereference-in-an-er.patch patches.suse/power-supply-ltc2941-battery-gauge-fix-use-after-fre.patch patches.suse/drm-ttm-ttm_tt_init_fields-can-be-static.patch + patches.suse/drm-gma500-Fixup-fbdev-stolen-size-usage-evaluation.patch patches.suse/drm-rect-Avoid-division-by-zero.patch patches.suse/drm-rect-update-kerneldoc-for-drm_rect_clip_scaled.patch patches.suse/drm-amdgpu-remove-4-set-but-not-used-variable-in-amd.patch @@ -52478,22 +53001,33 @@ patches.suse/drm-amdgpu-remove-set-but-not-used-variable-dig.patch patches.suse/drm-amdgpu-remove-always-false-comparison-in-amdgpu_.patch patches.suse/drm-amdgpu-remove-set-but-not-used-variable-mc_share.patch + patches.suse/drm-amd-display-remove-duplicated-assignment-to-grph.patch patches.suse/0012-drm-amdgpu-remove-set-but-not-used-variable-mc_share.patch patches.suse/drm-amdgpu-remove-set-but-not-used-variable-amdgpu_c.patch patches.suse/drm-amdgpu-remove-set-but-not-used-variable-invalid.patch patches.suse/drm-amd-powerplay-remove-set-but-not-used-variable-u.patch + patches.suse/0001-drm-rcar-du-Recognize-renesas-vsps-in-addition-to-vs.patch + patches.suse/0001-drm-mipi_dbi-Fix-off-by-one-bugs-in-mipi_dbi_blank.patch patches.suse/0001-pxa168fb-Fix-the-function-used-to-release-some-memor.patch patches.suse/drm-rockchip-lvds-Fix-indentation-of-a-define.patch patches.suse/drm-bridge-dw-hdmi-constify-copied-structure.patch + patches.suse/0001-drm-atmel-hlcdc-enable-clock-before-configuring-timi.patch + patches.suse/drm-remove-the-newline-for-CRC-source-name.patch + patches.suse/drm-mediatek-handle-events-when-enabling-disabling-c.patch + patches.suse/0001-drm-mediatek-disable-all-the-planes-in-atomic_disabl.patch + patches.suse/0001-drm-mediatek-Add-gamma-property-according-to-hardwar.patch patches.suse/drm-nouveau-secboot-gm20b-initialize-pointer-in-gm20.patch + patches.suse/drm-nouveau-gr-gk20a-gm200-add-terminators-to-method.patch patches.suse/drm-nouveau-Fix-copy-paste-error-in-nouveau_fence_wa.patch - patches.suse/drm-msm-mdp4-Adjust-indentation-in-mdp4_dsi_encoder_.patch + patches.suse/0001-drm-msm-mdp4-Adjust-indentation-in-mdp4_dsi_encoder_.patch patches.suse/drm-vmwgfx-prevent-memory-leak-in-vmw_cmdbuf_res_add.patch + patches.suse/drm-nouveau-disp-nv50-prevent-oops-when-no-channel-m.patch patches.suse/ext4-fix-deadlock-allocating-crypto-bounce-page-from.patch patches.suse/jbd2-clear-JBD2_ABORT-flag-before-journal_reset-to-u.patch patches.suse/jbd2-switch-to-use-jbd2_journal_abort-when-failed-to.patch patches.suse/ext4-jbd2-ensure-panic-when-aborting-with-zero-errno.patch patches.suse/jbd2-make-sure-ESHUTDOWN-to-be-recorded-in-the-journ.patch + patches.suse/xfs-also-remove-cached-ACLs-when-removing-the-underl.patch patches.suse/reiserfs-Fix-memory-leak-of-journal-device-string.patch patches.suse/reiserfs-Fix-spurious-unlock-in-reiserfs_fill_super-.patch patches.suse/ubifs-Fix-FS_IOC_SETFLAGS-unexpectedly-clearing-encr.patch @@ -52520,6 +53054,9 @@ patches.suse/media-v4l2-core-set-pages-dirty-upon-releasing-DMA-b.patch patches.suse/lib-test_kasan.c-fix-memory-leak-in-kmalloc_oob_krea.patch patches.suse/lib-scatterlist.c-adjust-indentation-in-__sg_alloc_t.patch + patches.suse/0001-PM-core-Fix-handling-of-devices-deleted-during-syste.patch + patches.suse/RDMA-uverbs-Verify-MR-access-flags.patch + patches.suse/RDMA-cma-Fix-unbalanced-cm_id-reference-count-during.patch patches.suse/media-gspca-zero-usb_buf.patch patches.suse/media-dvb-usb-dvb-usb-urb.c-initialize-actlen-to-0.patch patches.suse/media-digitv-don-t-continue-if-remote-control-state-.patch @@ -52527,19 +53064,24 @@ patches.suse/media-v4l2-rect.h-fix-v4l2_rect_map_inside-top-left-.patch patches.suse/media-iguanair-fix-endpoint-sanity-check.patch patches.suse/media-uvcvideo-Avoid-cyclic-entity-chains-due-to-mal.patch + patches.suse/PCI-AER-Log-which-device-prevents-error-recovery.patch + patches.suse/PCI-AER-Factor-message-prefixes-with-dev_fmt.patch patches.suse/PCI-Don-t-disable-bridge-BARs-when-assigning-bus-res.patch patches.suse/PCI-switchtec-Fix-vep_vector_number-ioread-width.patch patches.suse/PCI-IOV-Fix-memory-leak-in-pci_iov_add_virtfn.patch patches.suse/vfs-fix-do_last-regression.patch + patches.suse/cifs-fix-soft-mounts-hanging-in-the-reconnect-code.patch patches.suse/mfd-dln2-More-sanity-checking-for-endpoints.patch patches.suse/mfd-da9062-Fix-watchdog-compatible-string.patch patches.suse/mfd-rn5t618-Mark-ADC-control-register-volatile.patch patches.suse/Btrfs-fix-race-between-adding-and-putting-tree-mod-s.patch + patches.suse/Input-edt-ft5x06-work-around-first-register-access-e.patch patches.suse/clk-sunxi-ng-add-mux-and-pll-notifiers-for-A64-CPU-c.patch patches.suse/clk-tegra-Mark-fuse-clock-as-critical.patch patches.suse/percpu-separate-decrypted-varaibles-anytime-encryption-can-be-enabled.patch patches.suse/rtc-hym8563-Return-EINVAL-if-the-time-is-known-to-be.patch patches.suse/rtc-cmos-Stop-using-shared-IRQ.patch + patches.suse/remoteproc-Initialize-rproc_class-before-use.patch patches.suse/powerpc-pseries-Allow-not-having-ibm-hypertas-functi.patch patches.suse/powerpc-xmon-don-t-access-ASDR-in-VMs.patch patches.suse/powerpc-pseries-Advance-pfn-if-section-is-not-presen.patch @@ -52548,8 +53090,24 @@ patches.suse/powerpc-papr_scm-Fix-leaking-bus_desc.provider_name-.patch patches.suse/powerpc-mm-Remove-kvm-radix-prefetch-workaround-for-.patch patches.suse/powerpc-pseries-lparcfg-Fix-display-of-Maximum-Memor.patch + patches.suse/tcp-clear-tp-total_retrans-in-tcp_disconnect.patch + patches.suse/tcp-clear-tp-delivered-in-tcp_disconnect.patch + patches.suse/tcp-clear-tp-data_segs-in-out-in-tcp_disconnect.patch + patches.suse/tcp-clear-tp-segs_-in-out-in-tcp_disconnect.patch + patches.suse/cls_rsvp-fix-rsvp_policy.patch + patches.suse/rxrpc-Fix-insufficient-receive-notification-generati.patch + patches.suse/net-stmmac-Delete-txtimer-in-suspend.patch + patches.suse/bnxt_en-Fix-TC-queue-mapping.patch + patches.suse/net-hsr-fix-possible-NULL-deref-in-hsr_handle_frame.patch + patches.suse/net_sched-fix-an-OOB-access-in-cls_tcindex.patch + patches.suse/l2tp-Allow-duplicate-session-creation-with-UDP.patch + patches.suse/gtp-use-__GFP_NOWARN-to-avoid-memalloc-warning.patch + patches.suse/simple_recursive_removal-kernel-side-rm-rf-for-ramfs.patch + patches.suse/s390-mm-fix-dynamic-pagetable-upgrade-for-hugetlbfs patches.suse/0001-xen-balloon-Support-xend-based-toolstack-take-two.patch patches.suse/iommu-arm-smmu-v3-populate-vmid-field-for-cmdq_op_tlbi_nh_va + patches.suse/iommu-amd-check-feature-support-bit-before-accessing-msi-capability-registers + patches.suse/iommu-amd-only-support-x2apic-with-ivhd-type-11h-40h patches.suse/pwm-omap-dmtimer-Remove-PWM-chip-in-.remove-before-m.patch patches.suse/pwm-Remove-set-but-not-set-variable-pwm.patch patches.suse/ata-ahci-Add-shutdown-to-freeze-hardware-resources-o.patch @@ -52564,47 +53122,431 @@ patches.suse/tracing-annotate-ftrace_graph_notrace_hash-pointer-with-_rcu.patch patches.suse/ftrace-add-comment-to-why-rcu_dereference_sched-is-open-coded.patch patches.suse/ftrace-protect-ftrace_graph_hash-with-ftrace_sync.patch + patches.suse/ceph-remove-the-extra-slashes-in-the-server-path.patch patches.suse/ALSA-hda-Reset-stream-if-DMA-RUN-bit-not-cleared.patch patches.suse/ALSA-hda-Add-JasperLake-PCI-ID-and-codec-vid.patch patches.suse/ALSA-usb-audio-Fix-endianess-in-descriptor-validatio.patch patches.suse/ALSA-dummy-Fix-PCM-format-loop-in-proc-output.patch patches.suse/ALSA-hda-realtek-Fixed-one-of-HP-ALC671-platform-Hea.patch patches.suse/ALSA-hda-Clear-RIRB-status-before-reading-WP.patch + patches.suse/KVM-s390-ENOTSUPP-EOPNOTSUPP-fixups.patch + patches.suse/KVM-s390-do-not-clobber-registers-during-guest-reset.patch patches.suse/clk-qcom-rcg2-Don-t-crash-if-our-parent-can-t-be-fou.patch patches.suse/drm-amd-display-Retrain-dongles-when-SINK_COUNT-beco.patch + patches.suse/0001-drm-amd-dm-mst-Ignore-payload-update-failures.patch patches.suse/soc-tegra-fuse-Correct-straps-address-for-older-Tegr.patch + patches.suse/net_sched-fix-a-resource-leak-in-tcindex_set_parms.patch + patches.suse/devlink-report-0-after-hitting-end-in-region-read.patch + patches.suse/bonding-alb-properly-access-headers-in-bond_alb_xmit.patch + patches.suse/net-macb-Remove-unnecessary-alignment-check-for-TSO.patch + patches.suse/net-macb-Limit-maximum-GEM-TX-length-in-TSO.patch + patches.suse/net-mvneta-move-rx_dropped-and-rx_errors-in-per-cpu-.patch + patches.suse/net-systemport-Avoid-RBUF-stuck-in-Wake-on-LAN-mode.patch + patches.suse/net-mlx5-IPsec-Fix-esp-modify-function-attribute.patch + patches.suse/net-mlx5-IPsec-fix-memory-leak-at-mlx5_fpga_ipsec_de.patch patches.suse/mwifiex-fix-unbalanced-locking-in-mwifiex_process_co.patch patches.suse/libertas-dont-exit-from-lbs_ibss_join_existing-with.patch patches.suse/libertas-make-lbs_ibss_join_existing-return-error.patch + patches.suse/iwlwifi-mvm-Fix-thermal-zone-registration.patch patches.suse/iwlwifi-don-t-throw-error-when-trying-to-remove-IGTK.patch + patches.suse/scsi-qla2xxx-Fix-unbound-NVME-response-length.patch patches.suse/clocksource-Prevent-double-add_timer_on-for-watchdog.patch + patches.suse/SMB3-Backup-intent-flag-missing-from-some-more-ops.patch + patches.suse/smb3-fix-problem-with-null-cifs-super-block-with-previous-patch.patch + patches.suse/cifs-fail-i-o-on-soft-mounts-if-sessionsetup-errors-out.patch + patches.suse/cifs-log-warning-message-once-if-out-of-disk-space.patch + patches.suse/cifs-Add-tracepoints-for-errors-on-flush-or-fsync.patch + patches.suse/cifs-fix-soft-mounts-hanging-in-the-reconnect-code-2.patch + patches.suse/cifs-add-SMB3-change-notification-support.patch + patches.suse/cifs-fix-mode-bits-from-dir-listing-when-mounted-with-modefromsid.patch + patches.suse/smb3-add-one-more-dynamic-tracepoint-missing-from-strict-fsync-path.patch + patches.suse/smb3-print-warning-once-if-posix-context-returned-on-open.patch + patches.suse/smb3-Add-defines-for-new-information-level-FileIdInformation.patch patches.suse/kconfig-fix-broken-dependency-in-randconfig-generate.patch + patches.suse/drm-msm-Set-dma-maximum-segment-size-for-mdss.patch + patches.suse/ALSA-usb-audio-Apply-48kHz-fixed-rate-playback-for-J.patch + patches.suse/ALSA-usb-audio-Fix-UAC2-3-effect-unit-parsing.patch patches.suse/0001-ALSA-usb-audio-Apply-sample-rate-quirk-for-Audioengi.patch + patches.suse/ALSA-hda-realtek-Add-more-codec-supported-Headset-Bu.patch patches.suse/0001-ALSA-hda-realtek-Fix-silent-output-on-MSI-GL73.patch + patches.suse/ALSA-usb-audio-Add-clock-validity-quirk-for-Denon-MC.patch + patches.suse/qmi_wwan-re-add-DW5821e-pre-production-variant.patch + patches.suse/qmi_wwan-unconditionally-reject-2-ep-interfaces.patch + patches.suse/core-Don-t-skip-generic-XDP-program-execution-for-cl.patch + patches.suse/net-smc-fix-leak-of-kernel-memory-to-user-space.patch patches.suse/0001-enic-prevent-waking-up-stopped-tx-queues-over-watchd.patch + patches.suse/net-sched-matchall-add-missing-validation-of-TCA_MAT.patch + patches.suse/net-sched-flower-add-missing-validation-of-TCA_FLOWE.patch + patches.suse/net-hns3-fix-a-copying-IPv6-address-error-in-hclge_f.patch + patches.suse/net-smc-transfer-fasync_list-in-case-of-fallback + patches.suse/net-smc-no-peer-id-in-clc-decline-for-smcd + patches.suse/mac80211-consider-more-elements-in-parsing-CRC.patch + patches.suse/cfg80211-check-wiphy-driver-existence-for-drvinfo-re.patch + patches.suse/net-dsa-tag_qca-Make-sure-there-is-headroom-for-tag.patch + patches.suse/ceph-canonicalize-server-path-in-place.patch patches.suse/perf-x86-intel-fix-inaccurate-period-in-context-switch-for-auto-reload patches.suse/hwmon-pmbus-ltc2978-Fix-PMBus-polling-of-MFR_COMMON-.patch + patches.suse/s390-uv-fix-handling-of-length-extensions + patches.suse/RDMA-hfi1-Fix-memory-leak-in-_dev_comp_vect_mappings.patch + patches.suse/IB-hfi1-Close-window-for-pq-and-request-coliding.patch + patches.suse/Input-synaptics-switch-T470s-to-RMI4-by-default.patch + patches.suse/Input-synaptics-enable-SMBus-on-ThinkPad-L470.patch + patches.suse/Input-synaptics-remove-the-LEN0049-dmi-id-from-topbu.patch patches.suse/ext4-fix-checksum-errors-with-indexed-dirs.patch patches.suse/ext4-add-cond_resched-to-ext4_protect_reserved_inode.patch patches.suse/jbd2-move-the-clearing-of-b_modified-flag-to-the-jou.patch patches.suse/jbd2-do-not-clear-the-BH_Mapped-flag-when-forgetting.patch patches.suse/ext4-improve-explanation-of-a-mount-failure-caused-b.patch patches.suse/cifs-fix-mount-option-display-for-sec-krb5i.patch + patches.suse/cifs-Fix-mode-output-in-debugging-statements.patch + patches.suse/cifs-enable-change-notification-for-SMB2-1-dialect.patch + patches.suse/cifs-make-sure-we-do-not-overflow-the-max-EA-buffer-size.patch patches.suse/0027-bcache-ignore-pending-signals-when-creating-gc-and-a.patch patches.suse/0028-bcache-Revert-bcache-shrink-btree-node-cache-after-b.patch patches.suse/0029-bcache-remove-macro-nr_to_fifo_front.patch patches.suse/nvme-fix-the-parameter-order-for-nvme_get_log-in-nvm.patch + patches.suse/edac-mc-fix-use-after-free-and-memleaks-during-device-removal.patch + patches.suse/ipmi-ssif-Handle-a-possible-NULL-pointer-reference.patch patches.suse/ALSA-seq-Avoid-concurrent-access-to-queue-flags.patch patches.suse/ALSA-seq-Fix-concurrent-access-to-queue-current-tick.patch + patches.suse/ALSA-hda-realtek-Apply-quirk-for-MSI-GP63-too.patch + patches.suse/ALSA-hda-realtek-Apply-quirk-for-yet-another-MSI-lap.patch patches.suse/ALSA-hda-Use-scnprintf-for-printing-texts-for-sysfs-.patch patches.suse/ASoC-sun8i-codec-Fix-setting-DAI-data-format.patch + patches.suse/iommu-vt-d-fix-compile-warning-from-intel-svm-h + patches.suse/NFC-pn544-Fix-a-typo-in-a-debug-message.patch patches.suse/net-sched-correct-flower-port-blocking.patch + patches.suse/bpf-offload-Replace-bitwise-AND-by-logical-AND-in-bp.patch + patches.suse/bnxt_en-Improve-device-shutdown-method.patch + patches.suse/bnxt_en-Issue-PCIe-FLR-in-kdump-kernel-to-cleanup-pe.patch + patches.suse/drm-nouveau-kms-gv100-re-set-lut-after-clearing-for-modesets + patches.suse/0001-drm-i915-Wean-off-drm_pci_alloc-drm_pci_free.patch + patches.suse/xhci-Force-Maximum-Packet-size-for-Full-speed-bulk-d.patch + patches.suse/xhci-fix-runtime-pm-enabling-for-quirky-Intel-hosts.patch + patches.suse/0001-xhci-apply-XHCI_PME_STUCK_QUIRK-to-Intel-Comet-Lake-.patch + patches.suse/0001-usb-uas-fix-a-plug-unplug-racing.patch + patches.suse/0001-USB-hub-Don-t-record-a-connect-change-event-during-r.patch + patches.suse/0001-USB-core-add-endpoint-blacklist-quirk.patch + patches.suse/0001-USB-quirks-blacklist-duplicate-ep-on-Sound-Devices-U.patch + patches.suse/0001-USB-Fix-novation-SourceControl-XL-after-suspend.patch + patches.suse/0001-USB-misc-iowarrior-add-support-for-2-OEMed-devices.patch + patches.suse/0001-USB-misc-iowarrior-add-support-for-the-28-and-28L-de.patch + patches.suse/0001-thunderbolt-Prevent-crash-if-non-active-NVMem-file-i.patch + patches.suse/0001-usb-gadget-composite-Fix-bMaxPower-for-SuperSpeedPlu.patch + patches.suse/0001-usb-dwc2-Fix-in-ISOC-request-length-checking.patch + patches.suse/0001-USB-misc-iowarrior-add-support-for-the-100-device.patch + patches.suse/serdev-ttyport-restore-client-ops-on-deregistration.patch + patches.suse/tty-serial-atmel-manage-shutdown-in-case-of-RS485-or.patch + patches.suse/tty-serial-imx-setup-the-correct-sg-entry-for-tx-dma.patch + patches.suse/vt-selection-handle-pending-signals-in-paste_selecti.patch + patches.suse/vt-selection-close-sel_buffer-race.patch + patches.suse/staging-vt6656-fix-sign-of-rx_dbm-to-bb_pre_ed_rssi.patch + patches.suse/staging-rtl8188eu-Fix-potential-security-hole.patch + patches.suse/staging-rtl8723bs-Fix-potential-security-hole.patch + patches.suse/staging-rtl8188eu-Fix-potential-overuse-of-kernel-me.patch + patches.suse/staging-rtl8723bs-Fix-potential-overuse-of-kernel-me.patch patches.suse/powerpc-tm-Fix-clearing-MSR-TS-in-current-when-recla.patch patches.suse/0001-xen-Enable-interrupts-when-calling-_cond_resched.patch + patches.suse/x86-cpu-amd-enable-the-fixed-instructions-retired-counter-irperf.patch + patches.suse/x86-mce-amd-publish-the-bank-pointer-only-after-setup-has-succeeded.patch + patches.suse/x86-mce-amd-fix-kobject-lifetime.patch patches.suse/0001-ext4-fix-mount-failure-with-quota-configured-as-modu.patch + patches.suse/0002-Btrfs-fix-btrfs_wait_ordered_range-so-that-it-waits-.patch + patches.suse/floppy-check-FDC-index-for-errors-before-assigning-i.patch patches.suse/kvm-nvmx-don-t-emulate-instructions-in-guest-mode patches.suse/kvm-nvmx-refactor-io-bitmap-checks-into-helper-function patches.suse/kvm-nvmx-check-io-instruction-vm-exit-conditions + patches.suse/HID-apple-Add-support-for-recent-firmware-on-Magic-K.patch + patches.suse/HID-core-fix-off-by-one-memset-in-hid_report_raw_eve.patch + patches.suse/0001-HID-hiddev-Fix-race-in-in-hiddev_disconnect.patch + patches.suse/vhost-check-docket-sk_family-instead-of-call-getname.patch + patches.suse/ipv4-ensure-rcu_read_lock-in-cipso_v4_error.patch + patches.suse/cfg80211-check-reg_rule-for-NULL-in-handle_channel_c.patch + patches.suse/mac80211-rx-avoid-RCU-list-traversal-under-mutex.patch + patches.suse/net-Fix-Tx-hash-bound-checking.patch + patches.suse/net-smc-fix-cleanup-for-linkgroup-setup-failures + patches.suse/ipv6-restrict-IPV6_ADDRFORM-operation.patch + patches.suse/0001-amdgpu-gmc_v9-save-restore-sdpif-regs-during-S3.patch + patches.suse/0001-drm-i915-gvt-Separate-display-reset-from-ALL_ENGINES.patch + patches.suse/drm-i915-gvt-fix-orphan-vgpu-dmabuf_objs-lifetime + patches.suse/acpi-watchdog-allow-disabling-wdat-at-boot.patch + patches.suse/ACPICA-Introduce-ACPI_ACCESS_BYTE_WIDTH-macro.patch + patches.suse/ACPI-watchdog-Fix-gas-access_width-usage.patch + patches.suse/acpi-watchdog-set-default-timeout-in-probe.patch + patches.suse/blktrace-Protect-q-blk_trace-with-RCU.patch + patches.suse/i2c-jz4780-silence-log-flood-on-txabrt.patch + patches.suse/kvm-vmx-check-descriptor-table-exits-on-instruction-emulation + patches.suse/x86-pkeys-manually-set-x86_feature_ospke-to-preserve-existing-changes.patch + patches.suse/cifs-don-t-leak-EAGAIN-for-stat-during-reconnect.patch + patches.suse/cifs-fix-potential-mismatch-of-UNC-paths.patch + patches.suse/cifs-add-missing-mount-option-to-proc-mounts.patch + patches.suse/cifs-fix-rename-by-ensuring-source-handle-opened-wit.patch + patches.suse/cifs-Use-define-in-cifs_dbg.patch + patches.suse/dmaengine-coh901318-Fix-a-double-lock-bug-in-dma_tc_.patch + patches.suse/drm-exynos-dsi-propagate-error-value-and-silence-mea.patch + patches.suse/drm-exynos-dsi-fix-workaround-for-the-legacy-clock-n.patch + patches.suse/drm-sun4i-de2-de3-remove-unsupported-vi-layer-formats + patches.suse/drm-sun4i-fix-de2-vi-layer-format-support + patches.suse/drm-i915-program-mbus-with-rmw-during-initialization + patches.suse/0001-drm-i915-selftests-Fix-return-in-assert_mmap_offset.patch + patches.suse/fat-fix-uninit-memory-access-for-partial-initialized.patch + patches.suse/hwmon-adt7462-Fix-an-error-return-in-ADT7462_REG_VOL.patch + patches.suse/0001-vgacon-Fix-a-UAF-in-vgacon_invert_region.patch + patches.suse/ALSA-hda-realtek-Fix-a-regression-for-mute-led-on-Le.patch + patches.suse/ALSA-hda-realtek-Add-Headset-Mic-supported.patch + patches.suse/ALSA-hda-realtek-Add-Headset-Button-supported-for-Th.patch + patches.suse/ALSA-hda-realtek-Fix-silent-output-on-Gigabyte-X570-.patch + patches.suse/ALSA-hda-realtek-Enable-the-headset-of-ASUS-B9450FA-.patch + patches.suse/ASoC-pcm-Fix-possible-buffer-overflow-in-dpcm-state-.patch + patches.suse/ASoC-topology-Fix-memleak-in-soc_tplg_link_elems_loa.patch + patches.suse/ASoC-pcm512x-Fix-unbalanced-regulator-enable-call-in.patch + patches.suse/ASoC-dapm-Correct-DAPM-handling-of-active-widgets-du.patch + patches.suse/powerpc-fix-hardware-PMU-exception-bug-on-PowerVM-co.patch + patches.suse/s390-pci-fix-unexpected-write-combine-on-resource + patches.suse/blktrace-fix-dereference-after-null-check.patch + patches.suse/0001-usb-quirks-add-NO_LPM-quirk-for-Logitech-Screen-Shar.patch + patches.suse/0001-usb-storage-Add-quirk-for-Samsung-Fit-flash.patch + patches.suse/0001-usb-core-hub-do-error-out-if-usb_autopm_get_interfac.patch + patches.suse/0001-usb-core-port-do-error-out-if-usb_autopm_get_interfa.patch + patches.suse/vt-selection-push-console-lock-down.patch + patches.suse/vt-selection-push-sel_lock-up.patch + patches.suse/firmware-imx-scu-ensure-sequential-tx.patch + patches.suse/firmware-imx-misc-align-imx-sc-msg-structs-to-4.patch + patches.suse/firmware-imx-scu-pd-align-imx-sc-msg-structs-to-4.patch + patches.suse/0001-virtio-blk-fix-hw_queue-stopped-on-arbitrary-error.patch + patches.suse/virtio-blk-improve-virtqueue-error-to-BLK_STS.patch + patches.suse/pinctrl-imx-scu-align-imx-sc-msg-structs-to-4.patch + patches.suse/pinctrl-core-Remove-extra-kref_get-which-blocks-hogs.patch + patches.suse/macsec-add-missing-attribute-validation-for-port.patch + patches.suse/iwlwifi-mvm-Do-not-require-PHY_SKU-NVM-section-for-3.patch + patches.suse/net-nfc-fix-bounds-checking-bugs-on-pipe.patch + patches.suse/batman-adv-Don-t-schedule-OGM-for-disabled-interface.patch + patches.suse/cgroup-memcg-net-do-not-associate-sock-with-unrelated-cgroup.patch + patches.suse/ibmvnic-Do-not-process-device-remove-during-device-r.patch + patches.suse/mac80211-Do-not-send-mesh-HWMP-PREQ-if-HWMP-is-disab.patch + patches.suse/drm-i915-gvt-fix-unnecessary-schedule-timer-when-no-vgpu-exits + patches.suse/iommu-vt-d-fix-a-bug-in-intel_iommu_iova_to_phys-for-huge-page + patches.suse/iommu-dma-fix-msi-reservation-allocation + patches.suse/iommu-vt-d-dmar-replace-warn_taint-with-pr_warn-add_taint + patches.suse/iommu-vt-d-quirk_ioat_snb_local_iommu-replace-warn_taint-with-pr_warn-add_taint + patches.suse/iommu-vt-d-fix-the-wrong-printing-in-rhsa-parsing + patches.suse/iommu-vt-d-ignore-devices-with-out-of-spec-domain-number + patches.suse/efi-Fix-a-race-and-a-buffer-overflow-while-reading-e-286d3250.patch + patches.suse/x86-mce-fix-logic-and-comments-around-msr_ppin_ctl.patch + patches.suse/perf-amd-uncore-replace-manual-sampling-check-with-cap_no_interrupt-flag.patch + patches.suse/mmc-sdhci-of-at91-fix-cd-gpios-for-SAMA5D2.patch + patches.suse/drm-bridge-dw-hdmi-fix-AVI-frame-colorimetry.patch + patches.suse/0001-drm-lease-fix-WARNING-in-idr_destroy.patch + patches.suse/0001-drm-amd-amdgpu-Fix-GPR-read-from-debugfs-v2.patch + patches.suse/drm-amd-display-Add-link_rate-quirk-for-Apple-15-MBP.patch + patches.suse/drm-amdgpu-fix-typo-for-vcn1-idle-check.patch + patches.suse/ALSA-pcm-oss-Avoid-plugin-buffer-overflow.patch + patches.suse/ALSA-line6-Fix-endless-MIDI-read-loop.patch + patches.suse/ALSA-hda-realtek-Fix-pop-noise-on-ALC225.patch + patches.suse/ALSA-pcm-oss-Remove-WARNING-from-snd_pcm_plug_alloc-.patch + patches.suse/ALSA-seq-virmidi-Fix-running-status-after-receiving-.patch + patches.suse/ALSA-seq-oss-Fix-running-status-after-receiving-syse.patch + patches.suse/ALSA-hda-realtek-Enable-headset-mic-of-Acer-X2660G-w.patch + patches.suse/ALSA-hda-realtek-Enable-the-headset-of-Acer-N50-600-.patch + patches.suse/0001-xhci-Do-not-open-code-__print_symbolic-in-xhci-trace.patch + patches.suse/0001-usb-xhci-apply-XHCI_SUSPEND_DELAY-to-AMD-XHCI-contro.patch + patches.suse/0001-USB-Disable-LPM-on-WD19-s-Realtek-Hub.patch + patches.suse/0001-usb-host-xhci-plat-add-a-shutdown.patch + patches.suse/0001-usb-quirks-add-NO_LPM-quirk-for-RTL8153-based-ethern.patch + patches.suse/0001-USB-cdc-acm-fix-rounding-error-in-TIOCSSERIAL.patch + patches.suse/0001-USB-serial-option-add-ME910G1-ECM-composition-0x110b.patch + patches.suse/0001-USB-serial-pl2303-add-device-id-for-HP-LD381.patch + patches.suse/iio-magnetometer-ak8974-Fix-negative-raw-values-in-s.patch + patches.suse/intel_th-Fix-user-visible-error-codes.patch + patches.suse/intel_th-pci-Add-Elkhart-Lake-CPU-support.patch + patches.suse/x86-mm-split-vmalloc_sync_all.patch + patches.suse/net_sched-keep-alloc_hash-updated-after-hash-allocat.patch + patches.suse/NFC-fdp-Fix-a-signedness-bug-in-fdp_nci_send_patch.patch + patches.suse/net-ena-add-pci-shutdown-handler-to-allow-safe-kexec.patch + patches.suse/0001-ceph-check-pool_flag_full-nearfull-in-addition-to-osdmap_full-nearfull.patch + patches.suse/0002-libceph-fix-alloc_msg_with_page_vector-memory-leaks.patch + patches.suse/Input-raydium_i2c_ts-fix-error-codes-in-raydium_i2c_.patch + patches.suse/Input-synaptics-enable-RMI-on-HP-Envy-13-ad105ng.patch + patches.suse/Input-avoid-BIT-macro-usage-in-the-serio.h-UAPI-head.patch + patches.suse/clk-imx-align-imx-sc-clock-msg-structs-to-4.patch + patches.suse/scsi-qla2xxx-Fix-I-Os-being-passed-down-when-FC-devi.patch + patches.suse/i2c-hix5hd2-add-missed-clk_disable_unprepare-in-remo.patch + patches.suse/bpf-Explicitly-memset-the-bpf_attr-structure.patch + patches.suse/bpf-Explicitly-memset-some-bpf-info-structures-decla.patch + patches.suse/tpm-ibmvtpm-Wait-for-buffer-to-be-set-before-proceed.patch + patches.suse/media-usbtv-fix-control-message-timeouts.patch + patches.suse/media-dib0700-fix-rc-endpoint-lookup.patch + patches.suse/media-vsp1-tidyup-VI6_HGT_LBn_H-macro.patch + patches.suse/media-go7007-Fix-URB-type-for-interrupt-handling.patch + patches.suse/media-v4l2-core-fix-entity-initialization-in-device_.patch + patches.suse/media-tda10071-fix-unsigned-sign-extension-overflow.patch + patches.suse/0001-media-ov519-add-missing-endpoint-sanity-checks.patch + patches.suse/0001-media-stv06xx-add-missing-descriptor-sanity-checks.patch + patches.suse/media-xirlink_cit-add-missing-descriptor-sanity-chec.patch + patches.suse/usb-musb-fix-crash-with-highmen-PIO-and-usbmon.patch + patches.suse/USB-serial-io_edgeport-fix-slab-out-of-bounds-read-i.patch + patches.suse/usb-gadget-f_fs-Fix-use-after-free-issue-as-part-of-.patch + patches.suse/iio-potentiostat-lmp9100-fix-iio_triggered_buffer_-p.patch + patches.suse/staging-rtl8188eu-Add-ASUS-USB-N10-Nano-B1-to-device.patch + patches.suse/staging-wlan-ng-fix-ODEBUG-bug-in-prism2sta_disconne.patch + patches.suse/staging-wlan-ng-fix-use-after-free-Read-in-hfa384x_u.patch + patches.suse/PCI-switchtec-Fix-init_completion-race-condition-wit.patch + patches.suse/irqchip-bcm2835-Quiesce-IRQs-left-enabled-by-bootloa.patch + patches.suse/fbdev-g364fb-Fix-build-failure.patch + patches.suse/firmware-arm_sdei-fix-double-lock-on-hibernate-with-.patch + patches.suse/firmware-arm_sdei-fix-possible-double-lock-on-hibern.patch + patches.suse/platform-x86-pmc_atom-Add-Lex-2I385SW-to-critclk_sys.patch + patches.suse/ethtool-Factored-out-similar-ethtool-link-settings-f.patch + patches.suse/net-ethtool-Introduce-link_ksettings-API-for-virtual.patch + patches.suse/brcmfmac-abort-and-release-host-after-error.patch + patches.suse/mwifiex-set-needed_headroom-not-hard_header_len.patch + patches.suse/ath9k-Handle-txpower-changes-even-when-TPC-is-disabl.patch + patches.suse/Crypto-chelsio-Fixes-a-hang-issue-during-driver-regi.patch + patches.suse/Crypto-chelsio-Fixes-a-deadlock-between-rtnl_lock-an.patch + patches.suse/crypto-tcrypt-fix-printed-skcipher-a-sync-mode.patch + patches.suse/crypto-arm64-sha-ce-implement-export-import.patch + patches.suse/crypto-mxs-dcp-fix-scatterlist-linearization-for-has.patch + patches.suse/pxa168fb-fix-release-function-mismatch-in-probe-fail.patch + patches.suse/drm-drm_dp_mst-remove-set-but-not-used-variable-orig.patch + patches.suse/drm-sun4i-dsi-Use-NULL-to-signify-no-panel.patch + patches.suse/drm-amd-display-Fix-wrongly-passed-static-prefix.patch + patches.suse/drm-v3d-Replace-wait_for-macros-to-remove-use-of-msl.patch + patches.suse/ALSA-hda-ca0132-Add-Recon3Di-quirk-to-handle-integra.patch + patches.suse/ALSA-hda-realtek-Enable-mute-LED-on-an-HP-system.patch + patches.suse/ALSA-hda-realtek-a-fake-key-event-is-triggered-by-ru.patch + patches.suse/ALSA-via82xx-Fix-endianness-annotations.patch + patches.suse/ALSA-emu10k1-Fix-endianness-annotations.patch + patches.suse/ALSA-pcm-Use-a-macro-for-parameter-masks-to-reduce-t.patch + patches.suse/ALSA-hdsp-remove-redundant-assignment-to-variable-er.patch + patches.suse/ALSA-hda-remove-redundant-assignment-to-variable-tim.patch + patches.suse/ALSA-ali5451-remove-redundant-variable-capture_flag.patch + patches.suse/ALSA-info-remove-redundant-assignment-to-variable-c.patch + patches.suse/ALSA-core-Replace-zero-length-array-with-flexible-ar.patch + patches.suse/ALSA-usb-midi-Replace-zero-length-array-with-flexibl.patch + patches.suse/ALSA-hda-ca0132-Replace-zero-length-array-with-flexi.patch + patches.suse/ALSA-hda_codec-Replace-zero-length-array-with-flexib.patch + patches.suse/ALSA-usb-audio-Don-t-create-a-mixer-element-with-bog.patch + patches.suse/ALSA-pcm-oss-Unlock-mutex-temporarily-for-sleeping-a.patch + patches.suse/usb-audio-v2-Add-uac2_effect_unit_descriptor-definit.patch + patches.suse/ALSA-usb-audio-Parse-source-ID-of-UAC2-effect-unit.patch + patches.suse/ALSA-korg1212-fix-if-statement-empty-body-warnings.patch + patches.suse/ALSA-usb-audio-Add-support-for-MOTU-MicroBook-IIc.patch + patches.suse/ALSA-pcm-Fix-superfluous-snprintf-usage.patch + patches.suse/ALSA-hda-Use-scnprintf-for-string-truncation.patch + patches.suse/ALSA-usb-audio-Fix-mixer-controls-USB-interface-for-.patch + patches.suse/ALSA-usb-audio-Create-a-registration-quirk-for-Kings.patch + patches.suse/ALSA-core-Add-snd_device_get_state-helper.patch + patches.suse/ALSA-usb-audio-Rewrite-registration-quirk-handling.patch + patches.suse/ALSA-usb-audio-Add-delayed_register-option.patch + patches.suse/ALSA-usb-audio-Inform-devices-that-need-delayed-regi.patch + patches.suse/ALSA-hda-default-enable-CA0132-DSP-support.patch + patches.suse/ASoC-jz4740-i2s-Fix-divider-written-at-incorrect-off.patch + patches.suse/ASoC-Intel-mrfld-return-error-codes-when-an-error-oc.patch + patches.suse/ALSA-pcm.h-add-for_each_pcm_streams.patch + patches.suse/ALSA-usx2y-use-for_each_pcm_streams-macro.patch + patches.suse/ASoC-sun8i-codec-Remove-unused-dev-from-codec-struct.patch + patches.suse/ASoC-Intel-mrfld-fix-incorrect-check-on-p-sink.patch + patches.suse/ALSA-hda-realtek-Set-principled-PC-Beep-configuratio.patch + patches.suse/ALSA-hda-realtek-Remove-now-unnecessary-XPS-13-headp.patch + patches.suse/ALSA-usb-audio-Fix-case-when-USB-MIDI-interface-has-.patch + patches.suse/scsi-tcm_qla2xxx-Make-qlt_alloc_qfull_cmd-set-cmd-se.patch + patches.suse/scsi-qla2xxx-Check-locking-assumptions-at-runtime-in.patch + patches.suse/scsi-lpfc-Fix-RQ-buffer-leakage-when-no-IOCBs-availa.patch + patches.suse/scsi-lpfc-Fix-lpfc_io_buf-resource-leak-in-lpfc_get_.patch + patches.suse/scsi-lpfc-Fix-broken-Credit-Recovery-after-driver-lo.patch + patches.suse/scsi-lpfc-Fix-registration-of-ELS-type-support-in-fd.patch + patches.suse/scsi-lpfc-Fix-release-of-hwq-to-clear-the-eq-relatio.patch + patches.suse/scsi-lpfc-Fix-compiler-warning-on-frame-size.patch + patches.suse/scsi-lpfc-Fix-coverity-errors-in-fmdi-attribute-hand.patch + patches.suse/scsi-lpfc-Remove-handler-for-obsolete-ELS-Read-Port-.patch + patches.suse/scsi-lpfc-Clean-up-hba-max_lun_queue_depth-checks.patch + patches.suse/scsi-lpfc-Update-lpfc-version-to-12.6.0.4.patch + patches.suse/scsi-lpfc-Copyright-updates-for-12.6.0.4-patches.patch + patches.suse/scsi-fc-Update-Descriptor-definition-and-add-RDF-and.patch + patches.suse/scsi-lpfc-add-RDF-registration-and-Link-Integrity-FP.patch + patches.suse/scsi-qla2xxx-Add-beacon-LED-config-sysfs-interface.patch + patches.suse/scsi-qla2xxx-Move-free-of-fcport-out-of-interrupt-co.patch + patches.suse/scsi-qla2xxx-Add-sysfs-node-for-D-Port-Diagnostics-A.patch + patches.suse/scsi-qla2xxx-Add-endianizer-macro-calls-to-fc-host-s.patch + patches.suse/scsi-qla2xxx-Add-changes-in-preparation-for-vendor-e.patch + patches.suse/scsi-qla2xxx-Add-vendor-extended-RDP-additions-and-a.patch + patches.suse/scsi-qla2xxx-Add-ql2xrdpenable-module-parameter-for-.patch + patches.suse/scsi-qla2xxx-Add-vendor-extended-FDMI-commands.patch + patches.suse/scsi-qla2xxx-Display-message-for-FCE-enabled.patch + patches.suse/scsi-qla2xxx-Show-correct-port-speed-capabilities-fo.patch + patches.suse/scsi-qla2xxx-Cleanup-ELS-PUREX-iocb-fields.patch + patches.suse/scsi-qla2xxx-Add-deferred-queue-for-processing-ABTS-.patch + patches.suse/scsi-qla2xxx-Handle-cases-for-limiting-RDP-response-.patch + patches.suse/scsi-qla2xxx-Fix-RDP-response-size.patch + patches.suse/scsi-qla2xxx-Use-endian-macros-to-assign-static-fiel.patch + patches.suse/scsi-qla2xxx-Correction-to-selection-of-loopback-ech.patch + patches.suse/scsi-qla2xxx-Fix-qla2x00_echo_test-based-on-ISP-type.patch + patches.suse/scsi-qla2xxx-Print-portname-for-logging-in-qla24xx_l.patch + patches.suse/scsi-qla2xxx-Use-correct-ISP28xx-active-FW-region.patch + patches.suse/scsi-qla2xxx-Save-rscn_gen-for-new-fcport.patch + patches.suse/scsi-qla2xxx-Fix-control-flags-for-login-logout-IOCB.patch + patches.suse/scsi-qla2xxx-Add-fixes-for-mailbox-command.patch + patches.suse/scsi-qla2xxx-Use-QLA_FW_STOPPED-macro-to-propagate-f.patch + patches.suse/scsi-qla2xxx-Update-driver-version-to-10.01.00.24-k.patch + patches.suse/scsi-lpfc-fix-spelling-mistake-Notication-Notificati.patch + patches.suse/scsi-qla2xxx-Fix-sparse-warning-reported-by-kbuild-b.patch + patches.suse/scsi-qla2xxx-Simplify-the-code-for-aborting-SCSI-com.patch + patches.suse/scsi-qla2xxx-Suppress-endianness-complaints-in-qla2x.patch + patches.suse/scsi-qla2xxx-Fix-sparse-warnings-triggered-by-the-PC.patch + patches.suse/scsi-qla2xxx-Convert-MAKE_HANDLE-from-a-define-into-.patch + patches.suse/scsi-qla2xxx-Add-16.0GT-for-PCI-String.patch + patches.suse/scsi-qla2xxx-Avoid-setting-firmware-options-twice-in.patch + patches.suse/scsi-qla2xxx-Use-FC-generic-update-firmware-options-.patch + patches.suse/scsi-qla2xxx-Fix-FCP-SCSI-FC4-flag-passing-error.patch + patches.suse/scsi-qla2xxx-Improved-secure-flash-support-messages.patch + patches.suse/scsi-qla2xxx-Return-appropriate-failure-through-BSG-.patch + patches.suse/scsi-qla2xxx-Use-a-dedicated-interrupt-handler-for-h.patch + patches.suse/scsi-qla2xxx-fix-FW-resource-count-values.patch + patches.suse/scsi-qla2xxx-Update-BPM-enablement-semantics.patch + patches.suse/scsi-qla2xxx-add-more-FW-debug-information.patch + patches.suse/scsi-qla2xxx-Force-semaphore-on-flash-validation-fai.patch + patches.suse/scsi-qla2xxx-Fix-RDP-respond-data-format.patch + patches.suse/scsi-qla2xxx-Fix-NPIV-instantiation-after-FW-dump.patch + patches.suse/scsi-qla2xxx-Serialize-fc_port-alloc-in-N2N.patch + patches.suse/scsi-qla2xxx-Remove-restriction-of-FC-T10-PI-and-FC-.patch + patches.suse/scsi-qla2xxx-Handle-NVME-status-iocb-correctly.patch + patches.suse/scsi-qla2xxx-Set-Nport-ID-for-N2N.patch + patches.suse/scsi-qla2xxx-Update-driver-version-to-10.01.00.25-k.patch + patches.suse/scsi-ibmvfc-Avoid-loss-of-all-paths-during-SVC-node-.patch + patches.suse/ibmvfc-Fix-NULL-return-compiler-warning.patch + patches.suse/PCI-ASPM-Clear-the-correct-bits-when-enabling-L1-sub.patch + patches.suse/PCI-endpoint-Fix-clearing-start-entry-in-configfs.patch + patches.suse/misc-pci_endpoint_test-Fix-to-support-10-pci-endpoin.patch + patches.suse/ftrace-kprobe-show-the-maxactive-number-on-kprobe_events.patch + patches.suse/powerpc-drmem-avoid-NULL-pointer-dereference-when-dr.patch + patches.suse/powerpc-smp-Use-nid-as-fallback-for-package_id.patch + patches.suse/cpufreq-powernv-Fix-use-after-free.patch + patches.suse/cpufreq-powernv-Fix-unsafe-notifiers.patch + patches.suse/tty-evh_bytechan-Fix-out-of-bounds-accesses.patch + patches.suse/powerpc-pseries-Fix-of_read_drc_info_cell-to-point-a.patch + patches.suse/powerpc-64s-Fix-section-mismatch-warnings-from-boot-.patch + patches.suse/powerpc-kprobes-Ignore-traps-that-happened-in-real-m.patch + patches.suse/powerpc-xive-Use-XIVE_BAD_IRQ-instead-of-zero-to-cat.patch + patches.suse/powerpc-64-tm-Don-t-let-userspace-set-regs-trap-via-.patch + patches.suse/powerpc-vmlinux.lds-Explicitly-retain-.gnu.hash.patch + patches.suse/slcan-Don-t-transmit-uninitialized-stack-data-in-pad.patch + patches.suse/mfd-dln2-Fix-sanity-checking-for-endpoints.patch + patches.suse/thermal-devfreq_cooling-inline-all-stubs-for-CONFIG_.patch + patches.suse/drm-vc4-fix-hdmi-mode-validation.patch + patches.suse/powerpc-pseries-ddw-Extend-upper-limit-for-huge-DMA-.patch + patches.suse/scsi-lpfc-Fix-kasan-slab-out-of-bounds-error-in-lpfc.patch + patches.suse/scsi-lpfc-Fix-lockdep-error-register-non-static-key.patch + patches.suse/scsi-lpfc-Fix-lpfc-overwrite-of-sg_cnt-field-in-nvme.patch + patches.suse/scsi-lpfc-Fix-scsi-host-template-for-SLI3-vports.patch + patches.suse/scsi-lpfc-Fix-crash-after-handling-a-pci-error.patch + patches.suse/scsi-lpfc-Fix-update-of-wq-consumer-index-in-lpfc_sl.patch + patches.suse/scsi-lpfc-Fix-crash-in-target-side-cable-pulls-hitti.patch + patches.suse/scsi-lpfc-Fix-erroneous-cpu-limit-of-128-on-I-O-stat.patch + patches.suse/scsi-lpfc-Make-debugfs-ktime-stats-generic-for-NVME-.patch + patches.suse/scsi-lpfc-Remove-prototype-FIPS-DSS-options-from-SLI.patch + patches.suse/scsi-lpfc-Update-lpfc-version-to-12.8.0.0.patch + patches.suse/scsi-lpfc-Change-default-SCSI-LUN-QD-to-64.patch + patches.suse/ipmi-fix-hung-processes-in-__get_guid.patch # dhowells/linux-fs keys-uefi patches.suse/0001-KEYS-Allow-unrestricted-boot-time-addition-of-keys-t.patch @@ -52618,15 +53560,25 @@ patches.suse/cifs-handle-netapp-error-codes.patch patches.suse/powerpc-add-link-stack-flush-mitigation-in-debugfs.patch patches.suse/powerpc-pseries-mobility-notify-network-peers-after-.patch - patches.suse/cifs-Fix-mount-options-set-in-automount.patch - patches.suse/cifs-Fix-memory-allocation-in-__smb2_handle_cancelle.patch - patches.suse/powerpc-reserve-memory-for-capture-kernel-after-huge.patch - patches.suse/powerpc-avoid-adjusting-memory_limit-for-capture-ker.patch + patches.suse/powerpc-pseries-group-lmb-operation-and-memblock-s.patch + patches.suse/powerpc-pseries-update-device-tree-before-ejecting-h.patch + patches.suse/cifs-do-not-ignore-the-SYNC-flags-in-getattr.patch + patches.suse/cifs-potential-unintitliazed-error-code-in-cifs_geta.patch + patches.suse/cifs-handle-prefix-paths-in-reconnect.patch + patches.suse/cifs-call-wake_up-server-response_q-inside-of-cifs_r.patch + patches.suse/cifs-use-mod_delayed_work-for-server-reconnect-if-al.patch + patches.suse/cifs-make-use-of-cap_unix-ses-in-cifs_reconnect_tcon.patch + patches.suse/smb3-fix-performance-regression-with-setting-mtime.patch + patches.suse/cifs-print-warning-once-if-mounting-with-vers-1.0.patch + patches.suse/cifs-rename-posix-create-rsp.patch + patches.suse/cifs-add-smb2-POSIX-info-level.patch + patches.suse/cifs-plumb-smb2-POSIX-dir-enumeration.patch + patches.suse/cifs-add-SMB2_open-arg-to-return-POSIX-data.patch + patches.suse/cifs-do-d_move-in-rename.patch ######################################################## # end of sorted patches ######################################################## - patches.suse/scsi-qla2xxx-Fix-unbound-NVME-response-length.patch # ras/edac-for-next, 5.4 queue patches.suse/edac-amd64-support-more-than-two-controllers-for-chip-selects-handling.patch @@ -52639,9 +53591,6 @@ ######################################################## # upstream patches broken after a merge ######################################################## -+colyli patches.suse/0077-MD-fix-lock-contention-for-flush-bios.patch -+colyli patches.suse/0167-md-fix-memleak-for-mempool.patch -+colyli patches.suse/0168-MD-Memory-leak-when-flush-bio-size-is-zero.patch ######################################################## # @@ -52785,6 +53734,13 @@ patches.suse/lustre-Simplify-ib_post_-send-recv-srq_recv-calls.patch patches.suse/mm-Adjust-watermark-boost-factor-tunable.patch + patches.suse/btrfs-improve-global-reserve-stealing-logic.patch + patches.suse/btrfs-allow-us-to-use-up-to-90-of-the-global-rsv-for-unlink.patch + patches.suse/btrfs-account-for-trans_block_rsv-in-may_commit_transaction.patch + patches.suse/btrfs-only-check-priority-tickets-for-priority-flushing.patch + patches.suse/btrfs-run-btrfs_try_granting_tickets-if-a-priority-ticket-fails.patch + patches.suse/btrfs-force-chunk-allocation-if-our-global-rsv-is-larger-than-metadata.patch + # bnc#1102831 patches.suse/mm-sched-numa-Remove-remaining-traces-of-NUMA-rate-limiting.patch @@ -52878,8 +53834,6 @@ patches.suse/acpi_thinkpad_introduce_acpi_root_table_boot_param.patch patches.suse/acpi_thermal_passive_blacklist.patch patches.suse/ACPI-acpi_pad-Do-not-launch-acpi_pad-threads-on-idle-cpus.patch - patches.suse/acpi-watchdog-allow-disabling-wdat-at-boot.patch - patches.suse/acpi-watchdog-set-default-timeout-in-probe.patch ######################################################## # Driver core @@ -52957,6 +53911,7 @@ patches.suse/ext4-unsupported-features.patch patches.suse/btrfs-8888-add-allow_unsupported-module-parameter.patch + patches.suse/btrfs-qgroup-Mark-qgroup-inconsistent-if-we-re-inher.patch patches.suse/btrfs-provide-super_operations-get_inode_dev patches.suse/btrfs-fs-super.c-add-new-super-block-devices-super_block_d.patch patches.suse/btrfs-btrfs-use-the-new-VFS-super_block_dev.patch @@ -52973,6 +53928,7 @@ patches.suse/ext4-dont-warn-when-enabling-DAX.patch patches.suse/jbd2-flush_descriptor-Do-not-decrease-buffer-head-s-ref-count.patch + patches.suse/ext4-Avoid-ENOSPC-when-avoiding-to-reuse-recently-de.patch ######################################################## # NFS @@ -53008,7 +53964,6 @@ ######################################################## # Storage ######################################################## - patches.suse/nvme-multipath-round-robin-I-O-policy.patch patches.suse/ch-add-missing-mutex_lock-mutex_unlock-in-ch_release.patch patches.suse/ch-fixup-refcounting-imbalance-for-SCSI-devices.patch patches.suse/qla2xxx-always-allocate-qla_tgt_wq.patch @@ -53039,7 +53994,6 @@ patches.suse/cdrom-turn-off-autoclose-by-default.patch patches.suse/scsi-sr-workaround-VMware-ESXi-cdrom-emulation-bug.patch - patches.suse/qla2xxx-Enable-T10-DIF-with-FC-NVMe-enabled.patch patches.suse/scsi-release-sg-list-in-scsi_release_buffers.patch patches.kabi/kabi-protect-RDMA_DRIVER_EFA.patch @@ -53082,7 +54036,6 @@ # Out-of-tree networking ######################################################## patches.suse/bsc1084332-0003-lan78xx-Enable-LEDs-and-auto-negotiation.patch - patches.suse/ibmveth-Update-ethtool-settings-to-reflect-virtual-p.patch patches.suse/irda-Fix-memory-leak-caused-by-repeated-binds-of-ird.patch patches.suse/irda-Only-insert-new-objects-into-the-global-databas.patch patches.suse/qed-use-specical-suse-engineering-version.patch @@ -53133,8 +54086,6 @@ patches.suse/tty-Don-t-return-EAGAIN-in-blocking-read.patch patches.suse/tty-make-R3964-line-discipline-fail.patch - patches.suse/vt-selection-handle-pending-signals-in-paste_selecti.patch - patches.suse/vt-selection-close-sel_buffer-race.patch patches.suse/nvdimm-testing-provide-SZ_4G.patch @@ -53338,10 +54289,11 @@ # KVM patches.suse/0001-kvm-Introduce-nopvspin-kernel-parameter.patch + patches.kabi/md-backport-kabi.patch + patches.kabi/KVM-Fix-kABI.patch patches.kabi/qla2xxx-kABI-fixes-for-v10.01.00.18-k.patch - patches.kabi/scsi-qla2xxx-kabi-fix-for-double-scsi_done-for-abort-path.patch patches.kabi/kABI-Fix-kABI-for-struct-amd_iommu.patch patches.kabi/scsi-libsas-kabi-protect-struct-sas-task-slow.patch @@ -53362,6 +54314,8 @@ patches.kabi/kabi-fix-vmem_altmap.patch + patches.kabi/scsi-fc-kABI-fixes-for-new-ELS_FPIN-definition.patch + # IFU kABI Fix patches.kabi/kABI-Fix-for-IFU-patches.patch @@ -53374,6 +54328,13 @@ patches.kabi/bpf-protect-new-fields-in-bpf-structs.patch patches.kabi/libnvdimm-fix-devm_nsio_enable-kabi.patch + patches.kabi/pcie_port_bus_type-kabi-compat.patch + patches.kabi/debugfs-kabi-restore-debugfs_remove_recursive.patch + + patches.kabi/v4l2_fh-kabi-workaround.patch + + patches.kabi/kabi-nvme-multipath-fix-iopolicy.patch + ######################################################## # You'd better have a good reason for adding a patch # below here.