From: Greg Kroah-Hartman Date: Mon, 28 Feb 2022 11:11:51 +0000 (+0100) Subject: 4.9-stable patches X-Git-Tag: v4.9.304~8 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=678a607160b72c074170915a5af9013311209f2c;p=thirdparty%2Fkernel%2Fstable-queue.git 4.9-stable patches added patches: fget-clarify-and-improve-__fget_files-implementation.patch memblock-use-kfree-to-release-kmalloced-memblock-regions.patch --- diff --git a/queue-4.9/fget-clarify-and-improve-__fget_files-implementation.patch b/queue-4.9/fget-clarify-and-improve-__fget_files-implementation.patch new file mode 100644 index 00000000000..7f19a66fa22 --- /dev/null +++ b/queue-4.9/fget-clarify-and-improve-__fget_files-implementation.patch @@ -0,0 +1,141 @@ +From foo@baz Mon Feb 28 12:05:58 PM CET 2022 +From: Baokun Li +Date: Sat, 26 Feb 2022 14:33:24 +0800 +Subject: fget: clarify and improve __fget_files() implementation +To: +Cc: , , , , , , , , +Message-ID: <20220226063324.168514-1-libaokun1@huawei.com> + +From: Linus Torvalds + +commit e386dfc56f837da66d00a078e5314bc8382fab83 upstream. + +Commit 054aa8d439b9 ("fget: check that the fd still exists after getting +a ref to it") fixed a race with getting a reference to a file just as it +was being closed. It was a fairly minimal patch, and I didn't think +re-checking the file pointer lookup would be a measurable overhead, +since it was all right there and cached. + +But I was wrong, as pointed out by the kernel test robot. + +The 'poll2' case of the will-it-scale.per_thread_ops benchmark regressed +quite noticeably. Admittedly it seems to be a very artificial test: +doing "poll()" system calls on regular files in a very tight loop in +multiple threads. + +That means that basically all the time is spent just looking up file +descriptors without ever doing anything useful with them (not that doing +'poll()' on a regular file is useful to begin with). And as a result it +shows the extra "re-check fd" cost as a sore thumb. + +Happily, the regression is fixable by just writing the code to loook up +the fd to be better and clearer. There's still a cost to verify the +file pointer, but now it's basically in the noise even for that +benchmark that does nothing else - and the code is more understandable +and has better comments too. + +[ Side note: this patch is also a classic case of one that looks very + messy with the default greedy Myers diff - it's much more legible with + either the patience of histogram diff algorithm ] + +Link: https://lore.kernel.org/lkml/20211210053743.GA36420@xsang-OptiPlex-9020/ +Link: https://lore.kernel.org/lkml/20211213083154.GA20853@linux.intel.com/ +Reported-by: kernel test robot +Tested-by: Carel Si +Cc: Jann Horn +Cc: Miklos Szeredi +Signed-off-by: Linus Torvalds +Signed-off-by: Baokun Li +Signed-off-by: Greg Kroah-Hartman +--- + fs/file.c | 73 ++++++++++++++++++++++++++++++++++++++++++++++++-------------- + 1 file changed, 57 insertions(+), 16 deletions(-) + +--- a/fs/file.c ++++ b/fs/file.c +@@ -692,28 +692,69 @@ void do_close_on_exec(struct files_struc + spin_unlock(&files->file_lock); + } + +-static struct file *__fget(unsigned int fd, fmode_t mask, unsigned int refs) ++static inline struct file *__fget_files_rcu(struct files_struct *files, ++ unsigned int fd, fmode_t mask, unsigned int refs) + { +- struct files_struct *files = current->files; +- struct file *file; ++ for (;;) { ++ struct file *file; ++ struct fdtable *fdt = rcu_dereference_raw(files->fdt); ++ struct file __rcu **fdentry; + +- rcu_read_lock(); +-loop: +- file = fcheck_files(files, fd); +- if (file) { +- /* File object ref couldn't be taken. +- * dup2() atomicity guarantee is the reason +- * we loop to catch the new file (or NULL pointer) ++ if (unlikely(fd >= fdt->max_fds)) ++ return NULL; ++ ++ fdentry = fdt->fd + array_index_nospec(fd, fdt->max_fds); ++ file = rcu_dereference_raw(*fdentry); ++ if (unlikely(!file)) ++ return NULL; ++ ++ if (unlikely(file->f_mode & mask)) ++ return NULL; ++ ++ /* ++ * Ok, we have a file pointer. However, because we do ++ * this all locklessly under RCU, we may be racing with ++ * that file being closed. ++ * ++ * Such a race can take two forms: ++ * ++ * (a) the file ref already went down to zero, ++ * and get_file_rcu_many() fails. Just try ++ * again: + */ +- if (file->f_mode & mask) +- file = NULL; +- else if (!get_file_rcu_many(file, refs)) +- goto loop; +- else if (__fcheck_files(files, fd) != file) { ++ if (unlikely(!get_file_rcu_many(file, refs))) ++ continue; ++ ++ /* ++ * (b) the file table entry has changed under us. ++ * Note that we don't need to re-check the 'fdt->fd' ++ * pointer having changed, because it always goes ++ * hand-in-hand with 'fdt'. ++ * ++ * If so, we need to put our refs and try again. ++ */ ++ if (unlikely(rcu_dereference_raw(files->fdt) != fdt) || ++ unlikely(rcu_dereference_raw(*fdentry) != file)) { + fput_many(file, refs); +- goto loop; ++ continue; + } ++ ++ /* ++ * Ok, we have a ref to the file, and checked that it ++ * still exists. ++ */ ++ return file; + } ++} ++ ++ ++static struct file *__fget(unsigned int fd, fmode_t mask, unsigned int refs) ++{ ++ struct files_struct *files = current->files; ++ struct file *file; ++ ++ rcu_read_lock(); ++ file = __fget_files_rcu(files, fd, mask, refs); + rcu_read_unlock(); + + return file; diff --git a/queue-4.9/memblock-use-kfree-to-release-kmalloced-memblock-regions.patch b/queue-4.9/memblock-use-kfree-to-release-kmalloced-memblock-regions.patch new file mode 100644 index 00000000000..f978032049a --- /dev/null +++ b/queue-4.9/memblock-use-kfree-to-release-kmalloced-memblock-regions.patch @@ -0,0 +1,46 @@ +From c94afc46cae7ad41b2ad6a99368147879f4b0e56 Mon Sep 17 00:00:00 2001 +From: Miaohe Lin +Date: Thu, 17 Feb 2022 22:53:27 +0800 +Subject: memblock: use kfree() to release kmalloced memblock regions + +From: Miaohe Lin + +commit c94afc46cae7ad41b2ad6a99368147879f4b0e56 upstream. + +memblock.{reserved,memory}.regions may be allocated using kmalloc() in +memblock_double_array(). Use kfree() to release these kmalloced regions +indicated by memblock_{reserved,memory}_in_slab. + +Signed-off-by: Miaohe Lin +Fixes: 3010f876500f ("mm: discard memblock data later") +Signed-off-by: Mike Rapoport +Signed-off-by: Greg Kroah-Hartman +--- + mm/memblock.c | 10 ++++++++-- + 1 file changed, 8 insertions(+), 2 deletions(-) + +--- a/mm/memblock.c ++++ b/mm/memblock.c +@@ -272,14 +272,20 @@ void __init memblock_discard(void) + addr = __pa(memblock.reserved.regions); + size = PAGE_ALIGN(sizeof(struct memblock_region) * + memblock.reserved.max); +- __memblock_free_late(addr, size); ++ if (memblock_reserved_in_slab) ++ kfree(memblock.reserved.regions); ++ else ++ __memblock_free_late(addr, size); + } + + if (memblock.memory.regions != memblock_memory_init_regions) { + addr = __pa(memblock.memory.regions); + size = PAGE_ALIGN(sizeof(struct memblock_region) * + memblock.memory.max); +- __memblock_free_late(addr, size); ++ if (memblock_memory_in_slab) ++ kfree(memblock.memory.regions); ++ else ++ __memblock_free_late(addr, size); + } + } + #endif diff --git a/queue-4.9/series b/queue-4.9/series index f49057c814d..3f19a49b7f3 100644 --- a/queue-4.9/series +++ b/queue-4.9/series @@ -25,3 +25,5 @@ usb-dwc3-gadget-let-the-interrupt-handler-disable-bottom-halves.patch xhci-prevent-futile-urb-re-submissions-due-to-incorrect-return-value.patch tty-n_gsm-fix-encoding-of-control-signal-octet-bit-dv.patch tty-n_gsm-fix-proper-link-termination-after-failed-open.patch +memblock-use-kfree-to-release-kmalloced-memblock-regions.patch +fget-clarify-and-improve-__fget_files-implementation.patch