Merge tag 'mm-nonmm-stable-2026-06-21-10-22' of git://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm

Pull non-MM updates from Andrew Morton:

 - "taskstats: fix TGID dead-thread stat retention" (Yiyang Chen)

   Fix a taskstats TGID aggregation bug where fields added in the TGID
   query path were not preserved after thread exit, and adds a kselftest
   covering the regression.

 - "lib/tests: string_helpers: Slight improvements" (Andy Shevchenko)

   Improve lib/tests/string_helpers_kunit.c a little

 - "lib/base64: decode fixes" (Josh Law)

   Address minor issues in lib/base64.c

 - "selftests/filelock: Make output more kselftestish" (Mark Brown)

   Make the output from the ofdlocks test a bit easier for tooling to
   work with. Also ignore the generated file

 - "uaccess: unify inline vs outline copy_{from,to}_user() selection"
   (Yury Norov)

   Simplify the usercopy code by removing the selectability of inlining
   copy_{from,to}_user().

 - "ocfs2: validate inline xattr header consumers" (ZhengYuan Huang)

   Fix a number of possible issues in the ocfs2 xattr code

 - "lib and lib/cmdline enhancements" (Dmitry Antipov)

   Provide additional robustness checking in the cmdline handling code
   and its in-kernel testing and selftests

 - "cleanup the RAID6 P/Q library" (Christoph Hellwig)

   Clean up the RAID6 P/Q library to match the recent updates to the
   RAID 5 XOR library and other CRC/crypto libraries

 - "ocfs2: harden inode validators against forged metadata" (Michael
   Bommarito)

   Add three structural checks to OCFS2 dinode validation so malformed
   on-disk fields are rejected before ocfs2_populate_inode() copies them
   into the in-core inode

 - "lib/raid: replace __get_free_pages() call with kmalloc()" (Mike
   Rapoport)

   Clean up the lib/raid code by using kmalloc() in more places

* tag 'mm-nonmm-stable-2026-06-21-10-22' of git://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm: (108 commits)
  ocfs2: fix circular locking dependency in ocfs2_dio_end_io_write
  ocfs2: fix NULL h_transaction deref in ocfs2_assure_trans_credits
  lib: interval_tree_test: validate benchmark parameters
  ocfs2: avoid moving extents to occupied clusters
  treewide: fix transposed "sign" typos and update spelling.txt
  ocfs2: fix UBSAN array-index-out-of-bounds in ocfs2_sum_rightmost_rec
  fat: reject BPB volumes whose data area starts beyond total sectors
  selftests/uevent: increase __UEVENT_BUFFER_SIZE to avoid ENOBUFS on busy systems
  lib/test_firmware: allocate the configured into_buf size
  fs: efs: remove unneeded debug prints
  checkpatch: cuppress warnings when Reported-by: is followed by Link:
  MAINTAINERS: add Alexander as a kcov reviewer
  mailmap: update Alexander Sverdlin's Email addresses
  fs: fat: inode: replace sprintf() with scnprintf()
  ocfs2: fix out-of-bounds write in ocfs2_remove_refcount_extent
  ocfs2: fix race between ocfs2_control_install_private() and ocfs2_control_release()
  ocfs2/dlm: require a ref for locking_state debugfs open
  ocfs2: reject FITRIM ranges shorter than a cluster
  ocfs2: validate fast symlink target during inode read
  ocfs2: add journal NULL check in ocfs2_checkpoint_inode()
  ...
This commit is contained in:
Linus Torvalds
2026-06-21 13:20:19 -07:00
174 changed files with 3224 additions and 2203 deletions

View File

@@ -481,6 +481,7 @@ ForEachMacros:
- 'genradix_for_each'
- 'genradix_for_each_from'
- 'genradix_for_each_reverse'
- 'guard'
- 'hash_for_each'
- 'hash_for_each_possible'
- 'hash_for_each_possible_rcu'
@@ -674,6 +675,7 @@ ForEachMacros:
- 'rq_list_for_each'
- 'rq_list_for_each_safe'
- 'sample_read_group__for_each'
- 'scoped_guard'
- 'scsi_for_each_prot_sg'
- 'scsi_for_each_sg'
- 'sctp_for_each_hentry'

View File

@@ -36,13 +36,14 @@ Alexander Lobakin <alobakin@pm.me> <bloodyreaper@yandex.ru>
Alexander Mikhalitsyn <alexander@mihalicyn.com> <alexander.mikhalitsyn@virtuozzo.com>
Alexander Mikhalitsyn <alexander@mihalicyn.com> <aleksandr.mikhalitsyn@canonical.com>
Alexander Mikhalitsyn <alexander@mihalicyn.com> <aleksandr.mikhalitsyn@futurfusion.io>
Alexander Sverdlin <alexander.sverdlin@gmail.com> <alexander.sverdlin.ext@nsn.com>
Alexander Sverdlin <alexander.sverdlin@gmail.com> <alexander.sverdlin@gmx.de>
Alexander Sverdlin <alexander.sverdlin@gmail.com> <alexander.sverdlin@nokia.com>
Alexander Sverdlin <alexander.sverdlin@gmail.com> <alexander.sverdlin@nsn.com>
Alexander Sverdlin <alexander.sverdlin@gmail.com> <alexander.sverdlin@siemens.com>
Alexander Sverdlin <alexander.sverdlin@gmail.com> <alexander.sverdlin@sysgo.com>
Alexander Sverdlin <alexander.sverdlin@gmail.com> <subaparts@yandex.ru>
Alexander Sverdlin <alex@sverdlin.org> <alexander.sverdlin.ext@nsn.com>
Alexander Sverdlin <alex@sverdlin.org> <alexander.sverdlin@gmail.com>
Alexander Sverdlin <alex@sverdlin.org> <alexander.sverdlin@gmx.de>
Alexander Sverdlin <alex@sverdlin.org> <alexander.sverdlin@nokia.com>
Alexander Sverdlin <alex@sverdlin.org> <alexander.sverdlin@nsn.com>
Alexander Sverdlin <alex@sverdlin.org> <alexander.sverdlin@sysgo.com>
Alexander Sverdlin <alex@sverdlin.org> <asv@kernel.org>
Alexander Sverdlin <alex@sverdlin.org> <subaparts@yandex.ru>
Alexandre Belloni <alexandre.belloni@bootlin.com> <alexandre.belloni@free-electrons.com>
Alexandre Ghiti <alex@ghiti.fr> <alexandre.ghiti@canonical.com>
Alexei Avshalom Lazar <quic_ailizaro@quicinc.com> <ailizaro@codeaurora.org>
@@ -438,6 +439,7 @@ John Stultz <johnstul@us.ibm.com>
Jonas Gorski <jonas.gorski@gmail.com> <jogo@openwrt.org>
Jonathan Cameron <jic23@kernel.org> <jonathan.cameron@huawei.com>
Jordan Crouse <jordan@cosmicpenguin.net> <jcrouse@codeaurora.org>
Jorge Ramirez-Ortiz <jorge.ramirez@oss.qualcomm.com> <jorge.ramirez-ortiz@linaro.org>
<josh@joshtriplett.org> <josh@freedesktop.org>
<josh@joshtriplett.org> <josh@kernel.org>
<josh@joshtriplett.org> <josht@linux.vnet.ibm.com>

View File

@@ -3373,6 +3373,10 @@ N: Anil Ravindranath
E: anil_ravindranath@pmc-sierra.com
D: PMC-Sierra MaxRAID driver
N: Dwaipayan Ray
E: dwaipayanray1@gmail.com
D: checkpatch improvements
N: Eric S. Raymond
E: esr@thyrsus.com
W: http://www.tuxedo.org/~esr/

View File

@@ -82,9 +82,9 @@ xor_val xor a series of source buffers and set a flag if the
pq generate the p+q (raid6 syndrome) from a series of source buffers
pq_val validate that a p and or q buffer are in sync with a given series of
sources
datap (raid6_datap_recov) recover a raid6 data block and the p block
datap (raid6_recov_datap) recover a raid6 data block and the p block
from the given sources
2data (raid6_2data_recov) recover 2 raid6 data blocks from the given
2data (raid6_recov_2data) recover 2 raid6 data blocks from the given
sources
======== ====================================================================

View File

@@ -184,6 +184,13 @@ Available options:
Override checking of perl version. Runtime errors may be encountered after
enabling this flag if the perl version does not meet the minimum specified.
- --spdx-cxx-comments
Don't force C comments ``/* */`` for SPDX license (required by old
toolchains), allow also C++ comments ``//``.
NOTE: it should *not* be used for Linux mainline.
- --codespell
Use the codespell dictionary for checking spelling errors.
@@ -210,6 +217,13 @@ Available options:
Display the help text.
Configuration file
==================
Default configuration options can be stored in ``.checkpatch.conf``, search
path: ``.:$HOME:.scripts`` or in a directory specified by ``$CHECKPATCH_CONFIG_DIR``
environment variable (falling back to the default search path).
Message Levels
==============

View File

@@ -237,6 +237,9 @@ Both ``kcov_remote_start`` and ``kcov_remote_stop`` annotations and the
collection sections. The way a handle is used depends on the context where the
matching code section executes.
A thread can use two separate KCOV instances to collect remote coverage and
normal coverage at the same time.
KCOV supports collecting remote coverage from the following contexts:
1. Global kernel background tasks. These are the tasks that are spawned during
@@ -262,6 +265,9 @@ gets saved to the ``kcov_handle`` field in the current ``task_struct`` and
needs to be passed to the newly spawned local tasks via custom kernel code
modifications. Those tasks should in turn use the passed handle in their
``kcov_remote_start`` and ``kcov_remote_stop`` annotations.
In the kernel, common handles are wrapped in a ``kcov_common_handle_id``, which
consumes no space in builds without ``CONFIG_KCOV``; subsystems that integrate
with this mechanism should not need to use any ``#ifdef CONFIG_KCOV`` or such.
KCOV follows a predefined format for both global and common handles. Each
handle is a ``u64`` integer. Currently, only the one top and the lower 4 bytes

View File

@@ -6020,8 +6020,6 @@ F: drivers/input/keyboard/charlieplex_keypad.c
CHECKPATCH
M: Andy Whitcroft <apw@canonical.com>
M: Joe Perches <joe@perches.com>
R: Dwaipayan Ray <dwaipayanray1@gmail.com>
R: Lukas Bulwahn <lukas.bulwahn@gmail.com>
S: Maintained
F: scripts/checkpatch.pl
@@ -13933,8 +13931,9 @@ F: fs/proc/kcore.c
F: include/linux/kcore.h
KCOV
R: Dmitry Vyukov <dvyukov@google.com>
R: Andrey Konovalov <andreyknvl@gmail.com>
R: Alexander Potapenko <glider@google.com>
R: Dmitry Vyukov <dvyukov@google.com>
L: kasan-dev@googlegroups.com
S: Maintained
B: https://bugzilla.kernel.org/buglist.cgi?component=Sanitizers&product=Memory%20Management
@@ -25051,7 +25050,7 @@ F: drivers/md/md*
F: drivers/md/raid*
F: include/linux/raid/
F: include/uapi/linux/raid/
F: lib/raid6/
F: lib/raid/raid6/
SOLIDRUN CLEARFOG SUPPORT
M: Russell King <linux@armlinux.org.uk>

View File

@@ -829,12 +829,6 @@ endif # KBUILD_EXTMOD
# Defaults to vmlinux, but the arch makefile usually adds further targets
all: vmlinux
CFLAGS_GCOV := -fprofile-arcs -ftest-coverage
ifdef CONFIG_CC_IS_GCC
CFLAGS_GCOV += -fno-tree-loop-im
endif
export CFLAGS_GCOV
# The arch Makefiles can override CC_FLAGS_FTRACE. We may also append it later.
ifdef CONFIG_FUNCTION_TRACER
CC_FLAGS_FTRACE := -pg
@@ -1162,6 +1156,27 @@ endif
# Ensure compilers do not transform certain loops into calls to wcslen()
KBUILD_CFLAGS += -fno-builtin-wcslen
CFLAGS_GCOV := -fprofile-arcs -ftest-coverage
ifdef CONFIG_CC_IS_GCC
CFLAGS_GCOV += -fno-tree-loop-im
# Use atomic counter updates to avoid concurrent-access crashes in GCOV.
# Only enable if -fprofile-update=prefer-atomic does not introduce new
# undefined symbols (e.g. libatomic calls that the kernel cannot link).
CFLAGS_GCOV += $(call try-run,\
echo 'long long x; void f(void){x++;}' | \
$(CC) $(KBUILD_CPPFLAGS) $(KBUILD_CFLAGS) -w -fprofile-arcs \
-ftest-coverage -x c - -c -o "$$TMP.base" && \
echo 'long long x; void f(void){x++;}' | \
$(CC) $(KBUILD_CPPFLAGS) $(KBUILD_CFLAGS) -w -fprofile-arcs \
-ftest-coverage -fprofile-update=prefer-atomic \
-x c - -c -o "$$TMP" && \
$(NM) "$$TMP.base" | grep ' U ' > "$$TMP.ubase" || true ; \
$(NM) "$$TMP" | grep ' U ' > "$$TMP.utest" || true ; \
cmp -s "$$TMP.ubase" "$$TMP.utest",\
-fprofile-update=prefer-atomic)
endif
export CFLAGS_GCOV
# change __FILE__ to the relative path to the source directory
ifdef building_out_of_srctree
KBUILD_CPPFLAGS += -fmacro-prefix-map=$(srcroot)/=

View File

@@ -628,8 +628,7 @@ static inline unsigned long __clear_user(void __user *to, unsigned long n)
return res;
}
#define INLINE_COPY_TO_USER
#define INLINE_COPY_FROM_USER
#define INLINE_COPY_USER
#define __clear_user __clear_user

View File

@@ -616,8 +616,7 @@ raw_copy_to_user(void __user *to, const void *from, unsigned long n)
}
#define __clear_user(addr, n) (memset((void __force *)addr, 0, n), 0)
#endif
#define INLINE_COPY_TO_USER
#define INLINE_COPY_FROM_USER
#define INLINE_COPY_USER
static inline unsigned long __must_check clear_user(void __user *to, unsigned long n)
{

View File

@@ -562,7 +562,7 @@ &sdc1_rclk {
*
* This has entries that are defined by Qcard even if they go to the main
* board. In cases where the pulls may be board dependent we defer those
* settings to the board device tree. Drive strengths tend to be assinged here
* settings to the board device tree. Drive strengths tend to be assigned here
* but could conceivably be overwridden by board device trees.
*/

View File

@@ -456,8 +456,7 @@ do { \
unsafe_copy_loop(__ucu_dst, __ucu_src, __ucu_len, u8, label); \
} while (0)
#define INLINE_COPY_TO_USER
#define INLINE_COPY_FROM_USER
#define INLINE_COPY_USER
extern unsigned long __must_check __arch_clear_user(void __user *to, unsigned long n);
static inline unsigned long __must_check __clear_user(void __user *to, unsigned long n)

View File

@@ -26,8 +26,7 @@ unsigned long raw_copy_from_user(void *to, const void __user *from,
unsigned long n);
unsigned long raw_copy_to_user(void __user *to, const void *from,
unsigned long n);
#define INLINE_COPY_FROM_USER
#define INLINE_COPY_TO_USER
#define INLINE_COPY_USER
__kernel_size_t __clear_user_hexagon(void __user *dest, unsigned long count);
#define __clear_user(a, s) __clear_user_hexagon((a), (s))

View File

@@ -292,8 +292,7 @@ raw_copy_to_user(void __user *to, const void *from, unsigned long n)
return __copy_user((__force void *)to, from, n);
}
#define INLINE_COPY_FROM_USER
#define INLINE_COPY_TO_USER
#define INLINE_COPY_USER
/*
* __clear_user: - Zero a block of memory in user space, with less checking.

View File

@@ -377,8 +377,7 @@ raw_copy_to_user(void __user *to, const void *from, unsigned long n)
return __constant_copy_to_user(to, from, n);
return __generic_copy_to_user(to, from, n);
}
#define INLINE_COPY_FROM_USER
#define INLINE_COPY_TO_USER
#define INLINE_COPY_USER
#define __get_kernel_nofault(dst, src, type, err_label) \
do { \

View File

@@ -250,8 +250,7 @@ raw_copy_to_user(void __user *to, const void *from, unsigned long n)
{
return __copy_tofrom_user(to, (__force const void __user *)from, n);
}
#define INLINE_COPY_FROM_USER
#define INLINE_COPY_TO_USER
#define INLINE_COPY_USER
/*
* Copy a null terminated string from userspace.

View File

@@ -433,8 +433,7 @@ raw_copy_to_user(void __user *to, const void *from, unsigned long n)
return __cu_len_r;
}
#define INLINE_COPY_FROM_USER
#define INLINE_COPY_TO_USER
#define INLINE_COPY_USER
extern __kernel_size_t __bzero(void __user *addr, __kernel_size_t size);

View File

@@ -57,8 +57,7 @@ extern unsigned long
raw_copy_from_user(void *to, const void __user *from, unsigned long n);
extern unsigned long
raw_copy_to_user(void __user *to, const void *from, unsigned long n);
#define INLINE_COPY_FROM_USER
#define INLINE_COPY_TO_USER
#define INLINE_COPY_USER
extern long strncpy_from_user(char *__to, const char __user *__from,
long __len);

View File

@@ -218,8 +218,7 @@ raw_copy_to_user(void __user *to, const void *from, unsigned long size)
{
return __copy_tofrom_user((__force void *)to, from, size);
}
#define INLINE_COPY_FROM_USER
#define INLINE_COPY_TO_USER
#define INLINE_COPY_USER
extern unsigned long __clear_user(void __user *addr, unsigned long size);

View File

@@ -197,7 +197,6 @@ unsigned long __must_check raw_copy_to_user(void __user *dst, const void *src,
unsigned long len);
unsigned long __must_check raw_copy_from_user(void *dst, const void __user *src,
unsigned long len);
#define INLINE_COPY_TO_USER
#define INLINE_COPY_FROM_USER
#define INLINE_COPY_USER
#endif /* __PARISC_UACCESS_H */

View File

@@ -406,9 +406,6 @@ config ARCH_RV32I
bool "RV32I"
depends on NONPORTABLE
select 32BIT
select GENERIC_LIB_ASHLDI3
select GENERIC_LIB_ASHRDI3
select GENERIC_LIB_LSHRDI3
select GENERIC_LIB_UCMPDI2
config ARCH_RV64I

View File

@@ -5,6 +5,10 @@
#include <linux/ftrace.h>
#include <asm-generic/asm-prototypes.h>
long long __lshrdi3(long long a, int b);
long long __ashrdi3(long long a, int b);
long long __ashldi3(long long a, int b);
long long __lshrti3(long long a, int b);
long long __ashrti3(long long a, int b);
long long __ashlti3(long long a, int b);

View File

@@ -32,6 +32,15 @@ __efistub___init_text_end = __init_text_end;
__efistub_sysfb_primary_display = sysfb_primary_display;
#endif
/*
* These double-word integer shifts are used by the library code, and
* the first two of them are required to link EFI stub. Note __ashrdi3()
* is not actually used by the stub but this may change in the future.
*/
PROVIDE(__efistub___lshrdi3 = __lshrdi3);
PROVIDE(__efistub___ashldi3 = __ashldi3);
PROVIDE(__efistub___ashrdi3 = __ashrdi3);
#endif
#endif /* __RISCV_KERNEL_IMAGE_VARS_H */

View File

@@ -16,6 +16,7 @@ ifeq ($(CONFIG_MMU), y)
lib-$(CONFIG_RISCV_ISA_V) += uaccess_vector.o
endif
lib-$(CONFIG_MMU) += uaccess.o
lib-$(CONFIG_32BIT) += ashldi3.o ashrdi3.o lshrdi3.o
lib-$(CONFIG_64BIT) += tishift.o
lib-$(CONFIG_RISCV_ISA_ZICBOZ) += clear_page.o
obj-$(CONFIG_FUNCTION_ERROR_INJECTION) += error-inject.o

36
arch/riscv/lib/ashldi3.S Normal file
View File

@@ -0,0 +1,36 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
/**
* Adopted for the Linux kernel from IPXE project, see
* https://github.com/ipxe/ipxe/blob/master/src/arch/riscv32/libgcc/llshift.S
*/
#include <linux/linkage.h>
#include <asm/asm.h>
/**
* Shift left
*
* @v a1:a0 Value to shift
* @v a2 Shift amount
* @ret a1:a0 Shifted value
*/
SYM_FUNC_START(__ashldi3)
/* Perform shift by 32 bits, if applicable */
li t0, 32
sub t1, t0, a2
bgtz t1, 1f
mv a1, a0
mv a0, zero
1: /* Perform shift by modulo-32 bits, if applicable */
andi a2, a2, 0x1f
beqz a2, 2f
srl t2, a0, t1
sll a0, a0, a2
sll a1, a1, a2
or a1, a1, t2
2: ret
SYM_FUNC_END(__ashldi3)
EXPORT_SYMBOL(__ashldi3)

36
arch/riscv/lib/ashrdi3.S Normal file
View File

@@ -0,0 +1,36 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
/**
* Adopted for the Linux kernel from IPXE project, see
* https://github.com/ipxe/ipxe/blob/master/src/arch/riscv32/libgcc/llshift.S
*/
#include <linux/linkage.h>
#include <asm/asm.h>
/**
* Arithmetic shift right
*
* @v a1:a0 Value to shift
* @v a2 Shift amount
* @ret a1:a0 Shifted value
*/
SYM_FUNC_START(__ashrdi3)
/* Perform shift by 32 bits, if applicable */
li t0, 32
sub t1, t0, a2
bgtz t1, 1f
mv a0, a1
srai a1, a1, 31
1: /* Perform shift by modulo-32 bits, if applicable */
andi a2, a2, 0x1f
beqz a2, 2f
sll t2, a1, t1
sra a1, a1, a2
srl a0, a0, a2
or a0, a0, t2
2: ret
SYM_FUNC_END(__ashrdi3)
EXPORT_SYMBOL(__ashrdi3)

36
arch/riscv/lib/lshrdi3.S Normal file
View File

@@ -0,0 +1,36 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
/**
* Adopted for the Linux kernel from IPXE project, see
* https://github.com/ipxe/ipxe/blob/master/src/arch/riscv32/libgcc/llshift.S
*/
#include <linux/linkage.h>
#include <asm/asm.h>
/**
* Logical shift right
*
* @v a1:a0 Value to shift
* @v a2 Shift amount
* @ret a1:a0 Shifted value
*/
SYM_FUNC_START(__lshrdi3)
/* Perform shift by 32 bits, if applicable */
li t0, 32
sub t1, t0, a2
bgtz t1, 1f
mv a0, a1
mv a1, zero
1: /* Perform shift by modulo-32 bits, if applicable */
andi a2, a2, 0x1f
beqz a2, 2f
sll t2, a1, t1
srl a1, a1, a2
srl a0, a0, a2
or a0, a0, t2
2: ret
SYM_FUNC_END(__lshrdi3)
EXPORT_SYMBOL(__lshrdi3)

View File

@@ -30,8 +30,7 @@ void debug_user_asce(int exit);
#define uaccess_kmsan_or_inline __always_inline
#endif
#define INLINE_COPY_FROM_USER
#define INLINE_COPY_TO_USER
#define INLINE_COPY_USER
static uaccess_kmsan_or_inline __must_check unsigned long
raw_copy_from_user(void *to, const void __user *from, unsigned long size)

View File

@@ -95,8 +95,7 @@ raw_copy_to_user(void __user *to, const void *from, unsigned long n)
{
return __copy_user((__force void *)to, from, n);
}
#define INLINE_COPY_FROM_USER
#define INLINE_COPY_TO_USER
#define INLINE_COPY_USER
/*
* Clear the area and return remaining number of bytes

View File

@@ -190,8 +190,7 @@ static inline unsigned long raw_copy_from_user(void *to, const void __user *from
return __copy_user((__force void __user *) to, from, n);
}
#define INLINE_COPY_FROM_USER
#define INLINE_COPY_TO_USER
#define INLINE_COPY_USER
static inline unsigned long __clear_user(void __user *addr, unsigned long size)
{

View File

@@ -231,8 +231,7 @@ unsigned long __must_check raw_copy_from_user(void *to,
unsigned long __must_check raw_copy_to_user(void __user *to,
const void *from,
unsigned long size);
#define INLINE_COPY_FROM_USER
#define INLINE_COPY_TO_USER
#define INLINE_COPY_USER
unsigned long __must_check raw_copy_in_user(void __user *to,
const void __user *from,

View File

@@ -27,8 +27,7 @@ static inline int __access_ok(const void __user *ptr, unsigned long size);
#define __access_ok __access_ok
#define __clear_user __clear_user
#define INLINE_COPY_FROM_USER
#define INLINE_COPY_TO_USER
#define INLINE_COPY_USER
#include <asm-generic/uaccess.h>

View File

@@ -237,8 +237,7 @@ raw_copy_to_user(void __user *to, const void *from, unsigned long n)
prefetch(from);
return __xtensa_copy_user((__force void *)to, from, n);
}
#define INLINE_COPY_FROM_USER
#define INLINE_COPY_TO_USER
#define INLINE_COPY_USER
/*
* We need to return the number of bytes not cleared. Our memset()

View File

@@ -6,14 +6,14 @@ config MODULE_SIG_KEY
default "certs/signing_key.pem"
depends on MODULE_SIG || (IMA_APPRAISE_MODSIG && MODULES)
help
Provide the file name of a private key/certificate in PEM format,
or a PKCS#11 URI according to RFC7512. The file should contain, or
the URI should identify, both the certificate and its corresponding
private key.
Provide the file name of a private key/certificate in PEM format,
or a PKCS#11 URI according to RFC7512. The file should contain, or
the URI should identify, both the certificate and its corresponding
private key.
If this option is unchanged from its default "certs/signing_key.pem",
then the kernel will automatically generate the private key and
certificate as described in Documentation/admin-guide/module-signing.rst
If this option is unchanged from its default "certs/signing_key.pem",
then the kernel will automatically generate the private key and
certificate as described in Documentation/admin-guide/module-signing.rst
choice
prompt "Type of module signing key to be generated"

View File

@@ -8,6 +8,7 @@
#include <linux/module.h>
#include <linux/dma-mapping.h>
#include <linux/raid/pq.h>
#include <linux/raid/pq_tables.h>
#include <linux/async_tx.h>
#include <linux/gfp.h>
@@ -119,7 +120,7 @@ do_sync_gen_syndrome(struct page **blocks, unsigned int *offsets, int disks,
for (i = 0; i < disks; i++) {
if (blocks[i] == NULL) {
BUG_ON(i > disks - 3); /* P or Q can't be zero */
srcs[i] = raid6_get_zero_page();
srcs[i] = page_address(ZERO_PAGE(0));
} else {
srcs[i] = page_address(blocks[i]) + offsets[i];
@@ -131,11 +132,11 @@ do_sync_gen_syndrome(struct page **blocks, unsigned int *offsets, int disks,
}
}
if (submit->flags & ASYNC_TX_PQ_XOR_DST) {
BUG_ON(!raid6_call.xor_syndrome);
BUG_ON(!raid6_can_xor_syndrome());
if (start >= 0)
raid6_call.xor_syndrome(disks, start, stop, len, srcs);
raid6_xor_syndrome(disks, start, stop, len, srcs);
} else
raid6_call.gen_syndrome(disks, len, srcs);
raid6_gen_syndrome(disks, len, srcs);
async_tx_sync_epilog(submit);
}

View File

@@ -11,6 +11,7 @@
#include <linux/module.h>
#include <linux/dma-mapping.h>
#include <linux/raid/pq.h>
#include <linux/raid/pq_tables.h>
#include <linux/async_tx.h>
#include <linux/dmaengine.h>
@@ -414,11 +415,11 @@ async_raid6_2data_recov(int disks, size_t bytes, int faila, int failb,
async_tx_quiesce(&submit->depend_tx);
for (i = 0; i < disks; i++)
if (blocks[i] == NULL)
ptrs[i] = raid6_get_zero_page();
ptrs[i] = page_address(ZERO_PAGE(0));
else
ptrs[i] = page_address(blocks[i]) + offs[i];
raid6_2data_recov(disks, bytes, faila, failb, ptrs);
raid6_recov_2data(disks, bytes, faila, failb, ptrs);
async_tx_sync_epilog(submit);
@@ -497,11 +498,11 @@ async_raid6_datap_recov(int disks, size_t bytes, int faila,
async_tx_quiesce(&submit->depend_tx);
for (i = 0; i < disks; i++)
if (blocks[i] == NULL)
ptrs[i] = raid6_get_zero_page();
ptrs[i] = page_address(ZERO_PAGE(0));
else
ptrs[i] = page_address(blocks[i]) + offs[i];
raid6_datap_recov(disks, bytes, faila, ptrs);
raid6_recov_datap(disks, bytes, faila, ptrs);
async_tx_sync_epilog(submit);

View File

@@ -40,6 +40,7 @@
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/raid/pq.h>
#include <linux/raid/pq_tables.h>
#include "dmaengine.h"

View File

@@ -95,8 +95,10 @@ CFLAGS_zboot-decompress-gzip.o += -I$(srctree)/lib/zlib_inflate
zboot-obj-$(CONFIG_KERNEL_ZSTD) := zboot-decompress-zstd.o lib-xxhash.o
CFLAGS_zboot-decompress-zstd.o += -I$(srctree)/lib/zstd
zboot-obj-$(CONFIG_RISCV) += lib-clz_ctz.o lib-ashldi3.o
zboot-obj-$(CONFIG_LOONGARCH) += lib-clz_ctz.o lib-ashldi3.o
zboot-riscv-obj-$(CONFIG_32BIT) := lib-ashldi3.o lib-lshrdi3.o
zboot-obj-$(CONFIG_RISCV) += lib-clz_ctz.o $(zboot-riscv-obj-y)
zboot-loongarch-obj-$(CONFIG_32BIT) := lib-ashldi3.o lib-lshrdi3.o
zboot-obj-$(CONFIG_LOONGARCH) += lib-clz_ctz.o $(zboot-loongarch-obj-y)
lib-$(CONFIG_EFI_ZBOOT) += zboot.o $(zboot-obj-y)
lib-$(CONFIG_UNACCEPTED_MEMORY) += unaccepted_memory.o bitmap.o find.o

View File

@@ -54,7 +54,7 @@
* &drm_crtc_state.degamma_lut.
*
* DEGAMMA_LUT_SIZE:
* Unsinged range property to give the size of the lookup table to be set
* Unsigned range property to give the size of the lookup table to be set
* on the DEGAMMA_LUT property (the size depends on the underlying
* hardware). If drivers support multiple LUT sizes then they should
* publish the largest size, and sub-sample smaller sized LUTs (e.g. for

View File

@@ -6958,7 +6958,7 @@ raid5_store_rmw_level(struct mddev *mddev, const char *page, size_t len)
if (kstrtoul(page, 10, &new))
return -EINVAL;
if (new != PARITY_DISABLE_RMW && !raid6_call.xor_syndrome)
if (new != PARITY_DISABLE_RMW && !raid6_can_xor_syndrome())
return -EINVAL;
if (new != PARITY_DISABLE_RMW &&
@@ -7649,7 +7649,7 @@ static struct r5conf *setup_conf(struct mddev *mddev)
conf->level = mddev->new_level;
if (conf->level == 6) {
conf->max_degraded = 2;
if (raid6_call.xor_syndrome)
if (raid6_can_xor_syndrome())
conf->rmw_level = PARITY_ENABLE_RMW;
else
conf->rmw_level = PARITY_DISABLE_RMW;

View File

@@ -394,7 +394,6 @@ static void tsi721_db_dpc(struct work_struct *work)
idb_work);
struct rio_mport *mport;
struct rio_dbell *dbell;
int found = 0;
u32 wr_ptr, rd_ptr;
u64 *idb_entry;
u32 regval;
@@ -412,6 +411,8 @@ static void tsi721_db_dpc(struct work_struct *work)
rd_ptr = ioread32(priv->regs + TSI721_IDQ_RP(IDB_QUEUE)) % IDB_QSIZE;
while (wr_ptr != rd_ptr) {
int found = 0;
idb_entry = (u64 *)(priv->idb_base +
(TSI721_IDB_ENTRY_SIZE * rd_ptr));
rd_ptr++;

View File

@@ -59,7 +59,7 @@
#define EFCT_HW_EQ_DEPTH 1024
/*
* A CQ will be assinged to each WQ
* A CQ will be assigned to each WQ
* (CQ must have 2X entries of the WQ for abort
* processing), plus a separate one for each RQ PAIR and one for MQ
*/

View File

@@ -2488,7 +2488,7 @@ struct isci_request *sci_request_by_tag(struct isci_host *ihost, u16 io_tag)
* free remote node ids
* @idev: This is the device object which is requesting the a remote node
* id
* @node_id: This is the remote node id that is assinged to the device if one
* @node_id: This is the remote node id that is assigned to the device if one
* is available
*
* enum sci_status SCI_FAILURE_OUT_OF_RESOURCES if there are no available remote

View File

@@ -464,7 +464,7 @@ static enum sci_status sci_port_set_phy(struct isci_port *iport, struct isci_phy
{
/* Check to see if we can add this phy to a port
* that means that the phy is not part of a port and that the port does
* not already have a phy assinged to the phy index.
* not already have a phy assigned to the phy index.
*/
if (!iport->phy_table[iphy->phy_index] &&
!phy_get_non_dummy_port(iphy) &&

View File

@@ -259,7 +259,7 @@ sci_mpc_agent_validate_phy_configuration(struct isci_host *ihost,
if (!phy_mask)
continue;
/*
* Make sure that one or more of the phys were not already assinged to
* Make sure that one or more of the phys were not already assigned to
* a different port. */
if ((phy_mask & ~assigned_phy_mask) == 0) {
return SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION;

View File

@@ -282,9 +282,7 @@ struct usbip_device {
void (*unusable)(struct usbip_device *);
} eh_ops;
#ifdef CONFIG_KCOV
u64 kcov_handle;
#endif
struct kcov_common_handle_id kcov_handle;
};
#define kthread_get_run(threadfn, data, namefmt, ...) \
@@ -339,29 +337,4 @@ static inline int interface_to_devnum(struct usb_interface *interface)
return udev->devnum;
}
#ifdef CONFIG_KCOV
static inline void usbip_kcov_handle_init(struct usbip_device *ud)
{
ud->kcov_handle = kcov_common_handle();
}
static inline void usbip_kcov_remote_start(struct usbip_device *ud)
{
kcov_remote_start_common(ud->kcov_handle);
}
static inline void usbip_kcov_remote_stop(void)
{
kcov_remote_stop();
}
#else /* CONFIG_KCOV */
static inline void usbip_kcov_handle_init(struct usbip_device *ud) { }
static inline void usbip_kcov_remote_start(struct usbip_device *ud) { }
static inline void usbip_kcov_remote_stop(void) { }
#endif /* CONFIG_KCOV */
#endif /* __USBIP_COMMON_H */

View File

@@ -261,9 +261,9 @@ int vhci_rx_loop(void *data)
if (usbip_event_happened(ud))
break;
usbip_kcov_remote_start(ud);
kcov_remote_start_common(ud->kcov_handle);
vhci_rx_pdu(ud);
usbip_kcov_remote_stop();
kcov_remote_stop();
}
return 0;

View File

@@ -425,7 +425,7 @@ static ssize_t attach_store(struct device *dev, struct device_attribute *attr,
vdev->ud.tcp_rx = tcp_rx;
vdev->ud.tcp_tx = tcp_tx;
vdev->ud.status = VDEV_ST_NOTASSIGNED;
usbip_kcov_handle_init(&vdev->ud);
vdev->ud.kcov_handle = kcov_common_handle();
spin_unlock(&vdev->ud.lock);
spin_unlock_irqrestore(&vhci->lock, flags);

View File

@@ -44,7 +44,7 @@ struct vhost_worker {
/* Used to serialize device wide flushing with worker swapping. */
struct mutex mutex;
struct llist_head work_list;
u64 kcov_handle;
struct kcov_common_handle_id kcov_handle;
u32 id;
int attachment_cnt;
bool killed;

View File

@@ -78,7 +78,7 @@ config FS_DAX
--map=mem:
https://docs.pmem.io/ndctl-user-guide/ndctl-man-pages/ndctl-create-namespace
For ndctl to work CONFIG_DEV_DAX needs to be enabled as well. For most
For ndctl to work CONFIG_DEV_DAX needs to be enabled as well. For most
file systems DAX support needs to be manually enabled globally or
per-inode using a mount option as well. See the file documentation in
Documentation/filesystems/dax.rst for details.
@@ -116,8 +116,8 @@ config FILE_LOCKING
default y
help
This option enables standard file locking support, required
for filesystems like NFS and for the flock() system
call. Disabling this option saves about 11k.
for filesystems like NFS and for the flock() system
call. Disabling this option saves about 11k.
source "fs/crypto/Kconfig"

View File

@@ -1410,7 +1410,7 @@ static void generate_pq_vertical_step(struct btrfs_raid_bio *rbio, unsigned int
rbio_qstripe_paddr(rbio, sector_nr, step_nr));
assert_rbio(rbio);
raid6_call.gen_syndrome(rbio->real_stripes, step, pointers);
raid6_gen_syndrome(rbio->real_stripes, step, pointers);
} else {
/* raid5 */
memcpy(pointers[rbio->nr_data], pointers[0], step);
@@ -1987,10 +1987,10 @@ static void recover_vertical_step(struct btrfs_raid_bio *rbio,
}
if (failb == rbio->real_stripes - 2) {
raid6_datap_recov(rbio->real_stripes, step,
raid6_recov_datap(rbio->real_stripes, step,
faila, pointers);
} else {
raid6_2data_recov(rbio->real_stripes, step,
raid6_recov_2data(rbio->real_stripes, step,
faila, failb, pointers);
}
} else {
@@ -2644,7 +2644,7 @@ static bool verify_one_parity_step(struct btrfs_raid_bio *rbio,
if (has_qstripe) {
assert_rbio(rbio);
/* RAID6, call the library function to fill in our P/Q. */
raid6_call.gen_syndrome(rbio->real_stripes, step, pointers);
raid6_gen_syndrome(rbio->real_stripes, step, pointers);
} else {
/* RAID5. */
memcpy(pointers[nr_data], pointers[0], step);

View File

@@ -18,16 +18,9 @@ int efs_get_block(struct inode *inode, sector_t iblock,
if (create)
return error;
if (iblock >= inode->i_blocks) {
#ifdef DEBUG
/*
* i have no idea why this happens as often as it does
*/
pr_warn("%s(): block %d >= %ld (filesize %ld)\n",
__func__, block, inode->i_blocks, inode->i_size);
#endif
if (iblock >= inode->i_blocks)
return 0;
}
phys = efs_map_block(inode, iblock);
if (phys)
map_bh(bh_result, inode->i_sb, phys);
@@ -42,16 +35,8 @@ int efs_bmap(struct inode *inode, efs_block_t block) {
}
/* are we about to read past the end of a file ? */
if (!(block < inode->i_blocks)) {
#ifdef DEBUG
/*
* i have no idea why this happens as often as it does
*/
pr_warn("%s(): block %d >= %ld (filesize %ld)\n",
__func__, block, inode->i_blocks, inode->i_size);
#endif
if (!(block < inode->i_blocks))
return 0;
}
return efs_map_block(inode, block);
}

View File

@@ -20,6 +20,37 @@ static void fat_checksum_test(struct kunit *test)
KUNIT_EXPECT_EQ(test, fat_checksum("ABCDEFGHA "), (u8)98);
}
static void fat_clus_to_blknr_test(struct kunit *test)
{
struct msdos_sb_info sbi = {
.sec_per_clus = 4,
.data_start = 100,
};
KUNIT_EXPECT_EQ(test, (sector_t)100,
fat_clus_to_blknr(&sbi, FAT_START_ENT));
KUNIT_EXPECT_EQ(test, (sector_t)112, fat_clus_to_blknr(&sbi, 5));
}
static void fat_get_blknr_offset_test(struct kunit *test)
{
struct msdos_sb_info sbi = {
.dir_per_block = 16,
.dir_per_block_bits = 4,
};
sector_t blknr;
int offset;
fat_get_blknr_offset(&sbi, 0, &blknr, &offset);
KUNIT_EXPECT_EQ(test, (sector_t)0, blknr);
KUNIT_EXPECT_EQ(test, 0, offset);
fat_get_blknr_offset(&sbi, (10 << 4) | 7, &blknr, &offset);
KUNIT_EXPECT_EQ(test, (sector_t)10, blknr);
KUNIT_EXPECT_EQ(test, 7, offset);
}
struct fat_timestamp_testcase {
const char *name;
struct timespec64 ts;
@@ -341,6 +372,8 @@ static void fat_truncate_atime_test(struct kunit *test)
static struct kunit_case fat_test_cases[] = {
KUNIT_CASE(fat_checksum_test),
KUNIT_CASE(fat_clus_to_blknr_test),
KUNIT_CASE(fat_get_blknr_offset_test),
KUNIT_CASE_PARAM(fat_time_fat2unix_test, fat_time_gen_params),
KUNIT_CASE_PARAM(fat_time_unix2fat_test, fat_time_gen_params),
KUNIT_CASE_PARAM(fat_time_unix2fat_clamp_test,

View File

@@ -1738,6 +1738,14 @@ int fat_fill_super(struct super_block *sb, struct fs_context *fc,
if (total_sectors == 0)
total_sectors = bpb.fat_total_sect;
if (total_sectors < sbi->data_start) {
if (!silent)
fat_msg(sb, KERN_ERR,
"data area starts beyond volume (%lu > %u)",
sbi->data_start, total_sectors);
goto out_invalid;
}
total_clusters = (total_sectors - sbi->data_start) / sbi->sec_per_clus;
if (!is_fat32(sbi))
@@ -1786,7 +1794,7 @@ int fat_fill_super(struct super_block *sb, struct fs_context *fc,
*/
error = -EINVAL;
sprintf(buf, "cp%d", sbi->options.codepage);
scnprintf(buf, sizeof(buf), "cp%d", sbi->options.codepage);
sbi->nls_disk = load_nls(buf);
if (!sbi->nls_disk) {
fat_msg(sb, KERN_ERR, "codepage %s not found", buf);

View File

@@ -7576,7 +7576,7 @@ int ocfs2_trim_mainbm(struct super_block *sb, struct fstrim_range *range)
len = range->len >> osb->s_clustersize_bits;
minlen = range->minlen >> osb->s_clustersize_bits;
if (minlen >= osb->bitmap_cpg || range->len < sb->s_blocksize)
if (minlen >= osb->bitmap_cpg || range->len < osb->s_clustersize)
return -EINVAL;
trace_ocfs2_trim_mainbm(start, len, minlen);

View File

@@ -2372,6 +2372,15 @@ static int ocfs2_dio_end_io_write(struct inode *inode,
unlock:
up_write(&oi->ip_alloc_sem);
if (data_ac) {
ocfs2_free_alloc_context(data_ac);
data_ac = NULL;
}
if (meta_ac) {
ocfs2_free_alloc_context(meta_ac);
meta_ac = NULL;
}
/* everything looks good, let's start the cleanup */
if (!ret && dwc->dw_orphaned) {
BUG_ON(dwc->dw_writer_pid != task_pid_nr(current));
@@ -2383,10 +2392,6 @@ static int ocfs2_dio_end_io_write(struct inode *inode,
ocfs2_inode_unlock(inode, 1);
brelse(di_bh);
out:
if (data_ac)
ocfs2_free_alloc_context(data_ac);
if (meta_ac)
ocfs2_free_alloc_context(meta_ac);
ocfs2_run_deallocs(osb, &dealloc);
ocfs2_dio_free_write_ctx(inode, dwc);

View File

@@ -344,8 +344,6 @@ int ocfs2_read_blocks(struct ocfs2_caching_info *ci, u64 block, int nr,
wait_on_buffer(bh);
put_bh(bh);
bhs[i] = NULL;
} else if (bh && buffer_uptodate(bh)) {
clear_buffer_uptodate(bh);
}
continue;
}
@@ -374,8 +372,11 @@ int ocfs2_read_blocks(struct ocfs2_caching_info *ci, u64 block, int nr,
BUG_ON(buffer_jbd(bh));
clear_buffer_needs_validate(bh);
status = validate(sb, bh);
if (status)
if (status) {
if (buffer_uptodate(bh))
clear_buffer_uptodate(bh);
goto read_failure;
}
}
}

View File

@@ -556,6 +556,7 @@ static int debug_lockres_open(struct inode *inode, struct file *file)
struct dlm_ctxt *dlm = inode->i_private;
struct debug_lockres *dl;
void *buf;
int status = -ENOMEM;
buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
if (!buf)
@@ -568,16 +569,23 @@ static int debug_lockres_open(struct inode *inode, struct file *file)
dl->dl_len = PAGE_SIZE;
dl->dl_buf = buf;
dlm_grab(dlm);
dl->dl_ctxt = dlm;
/* ->release uses dl_ctxt after open, so it needs a real pin. */
dl->dl_ctxt = dlm_grab(dlm);
if (!dl->dl_ctxt) {
status = -ENOENT;
goto bailseq;
}
return 0;
bailseq:
seq_release_private(inode, file);
bailfree:
kfree(buf);
bail:
mlog_errno(-ENOMEM);
return -ENOMEM;
if (status != -ENOENT)
mlog_errno(status);
return status;
}
static int debug_lockres_release(struct inode *inode, struct file *file)

View File

@@ -3134,6 +3134,22 @@ static void *ocfs2_dlm_seq_next(struct seq_file *m, void *v, loff_t *pos)
* - Add last pr/ex unlock times and first lock wait time in usecs
*/
#define OCFS2_DLM_DEBUG_STR_VERSION 4
/*
* The debug iterator snapshots lockres by value, so a userspace-stack LVB
* pointer copied from the original lockres must be rebased to the copied
* lksb before the dump walks the raw bytes.
*/
static void ocfs2_dlm_seq_rebase_lvb(struct ocfs2_lock_res *lockres)
{
if (!ocfs2_stack_supports_plocks())
return;
if (lockres->l_lksb.lksb_fsdlm.sb_lvbptr)
lockres->l_lksb.lksb_fsdlm.sb_lvbptr =
(char *)&lockres->l_lksb + sizeof(struct dlm_lksb);
}
static int ocfs2_dlm_seq_show(struct seq_file *m, void *v)
{
int i;
@@ -3191,6 +3207,7 @@ static int ocfs2_dlm_seq_show(struct seq_file *m, void *v)
lockres->l_blocking);
/* Dump the raw LVB */
ocfs2_dlm_seq_rebase_lvb(lockres);
lvb = ocfs2_dlm_lvb(&lockres->l_lksb);
for(i = 0; i < DLM_LVB_LEN; i++)
seq_printf(m, "0x%x\t", lvb[i]);

View File

@@ -444,21 +444,26 @@ int ocfs2_truncate_file(struct inode *inode,
struct ocfs2_dinode *fe = NULL;
struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
/* We trust di_bh because it comes from ocfs2_inode_lock(), which
* already validated it */
/*
* On local mounts ocfs2_inode_lock_update() skips the inode
* refresh path, so truncation still needs to reject an inode
* state that no longer matches di_bh.
*/
fe = (struct ocfs2_dinode *) di_bh->b_data;
trace_ocfs2_truncate_file((unsigned long long)OCFS2_I(inode)->ip_blkno,
(unsigned long long)le64_to_cpu(fe->i_size),
(unsigned long long)new_i_size);
mlog_bug_on_msg(le64_to_cpu(fe->i_size) != i_size_read(inode),
"Inode %llu, inode i_size = %lld != di "
"i_size = %llu, i_flags = 0x%x\n",
(unsigned long long)OCFS2_I(inode)->ip_blkno,
i_size_read(inode),
(unsigned long long)le64_to_cpu(fe->i_size),
le32_to_cpu(fe->i_flags));
if (unlikely(le64_to_cpu(fe->i_size) != i_size_read(inode))) {
status = ocfs2_error(inode->i_sb,
"Inode %llu has inconsistent i_size: inode = %lld, dinode = %llu, i_flags = 0x%x\n",
(unsigned long long)OCFS2_I(inode)->ip_blkno,
i_size_read(inode),
(unsigned long long)le64_to_cpu(fe->i_size),
le32_to_cpu(fe->i_flags));
goto bail;
}
if (new_i_size > le64_to_cpu(fe->i_size)) {
trace_ocfs2_truncate_file_error(

View File

@@ -13,6 +13,7 @@
#include <linux/pagemap.h>
#include <linux/quotaops.h>
#include <linux/iversion.h>
#include <linux/fs_dirent.h>
#include <asm/byteorder.h>
@@ -64,7 +65,40 @@ static int ocfs2_filecheck_read_inode_block_full(struct inode *inode,
static int ocfs2_filecheck_validate_inode_block(struct super_block *sb,
struct buffer_head *bh);
static int ocfs2_filecheck_repair_inode_block(struct super_block *sb,
struct buffer_head *bh);
struct buffer_head *bh);
static bool ocfs2_valid_inode_mode(umode_t mode)
{
return fs_umode_to_ftype(mode) != FT_UNKNOWN;
}
static bool ocfs2_dinode_has_unexpected_rdev(struct ocfs2_dinode *di)
{
umode_t mode = le16_to_cpu(di->i_mode);
if (le32_to_cpu(di->i_flags) & OCFS2_SYSTEM_FL)
return false;
return !S_ISCHR(mode) && !S_ISBLK(mode) && di->id1.dev1.i_rdev != 0;
}
static bool ocfs2_dinode_has_size_without_clusters(struct super_block *sb,
struct ocfs2_dinode *di)
{
umode_t mode = le16_to_cpu(di->i_mode);
if (le32_to_cpu(di->i_flags) & OCFS2_SYSTEM_FL)
return false;
if (le16_to_cpu(di->i_dyn_features) & OCFS2_INLINE_DATA_FL)
return false;
if (!le64_to_cpu(di->i_size) || le32_to_cpu(di->i_clusters))
return false;
if (S_ISDIR(mode))
return true;
return !ocfs2_sparse_alloc(OCFS2_SB(sb)) && S_ISREG(mode);
}
void ocfs2_set_inode_flags(struct inode *inode)
{
@@ -1494,6 +1528,86 @@ int ocfs2_validate_inode_block(struct super_block *sb,
goto bail;
}
/*
* Reject dinodes whose i_mode does not name one of the seven
* canonical POSIX file types. ocfs2_populate_inode() copies
* i_mode verbatim into inode->i_mode and then dispatches via
* switch (mode & S_IFMT) to file/dir/symlink/special_file iops;
* an unrecognised type falls into ocfs2_special_file_iops with
* init_special_inode(), which interprets i_rdev. Constrain the
* type here so the dispatch only ever sees a value mkfs.ocfs2 /
* VFS can produce.
*/
if (!ocfs2_valid_inode_mode(le16_to_cpu(di->i_mode))) {
rc = ocfs2_error(sb,
"Invalid dinode #%llu: mode 0%o has unknown file type\n",
(unsigned long long)bh->b_blocknr,
le16_to_cpu(di->i_mode));
goto bail;
}
/*
* id1.dev1.i_rdev is the device-number arm of the id1 union and
* is only meaningful for character and block device inodes. For
* any other regular user-visible file type the on-disk value
* must be zero. ocfs2_populate_inode() currently runs
*
* inode->i_rdev = huge_decode_dev(le64_to_cpu(fe->id1.dev1.i_rdev));
*
* unconditionally, before the S_IFMT switch decides whether the
* inode is a special file. As a result, an i_rdev value present
* on a non-device inode is silently published into the in-core
* inode; a subsequent forced re-read or in-core mode mutation
* (cluster peer with raw write access to the shared LUN,
* on-disk corruption, or a separately forged dinode) can then
* expose the attacker-controlled device number to
* init_special_inode() without ever showing an unusual i_mode
* at validation time.
*
* System inodes (OCFS2_SYSTEM_FL) legitimately use the bitmap1
* and journal1 arms of the same union (allocator i_used /
* i_total counters and the journal ij_flags /
* ij_recovery_generation pair); those bytes are not an i_rdev
* and must not be checked here. Restrict the cross-check to
* non-system inodes, which is the full attacker-controllable
* surface.
*/
if (ocfs2_dinode_has_unexpected_rdev(di)) {
rc = ocfs2_error(sb,
"Invalid dinode #%llu: non-device mode 0%o with i_rdev %llu\n",
(unsigned long long)bh->b_blocknr,
le16_to_cpu(di->i_mode),
(unsigned long long)le64_to_cpu(di->id1.dev1.i_rdev));
goto bail;
}
/*
* Non-inline directories must not have i_size without allocated
* clusters: directory growth adds storage before advancing i_size,
* and readdir walks i_size block-by-block. A forged directory
* with zero clusters and a huge i_size would repeatedly fault on
* holes while advancing through the claimed size.
*
* Non-inline regular files have the same invariant on non-sparse
* volumes. Sparse regular files are different: truncate can
* legitimately grow i_size without allocating clusters, so keep
* the sparse-alloc carveout for S_IFREG only. System inodes and
* inline-data dinodes have their own storage rules.
*/
if (ocfs2_dinode_has_size_without_clusters(sb, di)) {
if (S_ISDIR(le16_to_cpu(di->i_mode)))
rc = ocfs2_error(sb,
"Invalid dinode #%llu: directory i_size %llu with i_clusters 0 and no inline-data flag\n",
(unsigned long long)bh->b_blocknr,
(unsigned long long)le64_to_cpu(di->i_size));
else
rc = ocfs2_error(sb,
"Invalid dinode #%llu: regular file i_size %llu with i_clusters 0 and no inline-data flag on non-sparse volume\n",
(unsigned long long)bh->b_blocknr,
(unsigned long long)le64_to_cpu(di->i_size));
goto bail;
}
if (le16_to_cpu(di->i_dyn_features) & OCFS2_INLINE_DATA_FL) {
struct ocfs2_inline_data *data = &di->id2.i_data;
@@ -1525,6 +1639,29 @@ int ocfs2_validate_inode_block(struct super_block *sb,
}
}
if (S_ISLNK(le16_to_cpu(di->i_mode)) &&
!le32_to_cpu(di->i_clusters)) {
int max_inline = ocfs2_fast_symlink_chars(sb);
u64 i_size = le64_to_cpu(di->i_size);
if (i_size >= max_inline) {
rc = ocfs2_error(sb,
"Invalid dinode #%llu: fast symlink i_size %llu exceeds max %d\n",
(unsigned long long)bh->b_blocknr,
(unsigned long long)i_size,
max_inline - 1);
goto bail;
}
if (strnlen((char *)di->id2.i_symlink, i_size + 1) != i_size) {
rc = ocfs2_error(sb,
"Invalid dinode #%llu: fast symlink is not NUL-terminated at i_size %llu\n",
(unsigned long long)bh->b_blocknr,
(unsigned long long)i_size);
goto bail;
}
}
if (le32_to_cpu(di->i_flags) & OCFS2_CHAIN_FL) {
struct ocfs2_chain_list *cl = &di->id2.i_chain;
u16 bpc = 1 << (OCFS2_SB(sb)->s_clustersize_bits -
@@ -1559,6 +1696,38 @@ int ocfs2_validate_inode_block(struct super_block *sb,
goto bail;
}
if (ocfs2_dinode_has_extents(di)) {
struct ocfs2_extent_list *el = &di->id2.i_list;
u16 count = le16_to_cpu(el->l_count);
u16 next_free = le16_to_cpu(el->l_next_free_rec);
if (count == 0) {
rc = ocfs2_error(sb,
"Invalid dinode %llu: extent list l_count is zero\n",
(unsigned long long)bh->b_blocknr);
goto bail;
}
/*
* The exact capacity depends on i_xattr_inline_size, another
* unvalidated on-disk field. Inline xattrs only shrink the
* list, so the no-xattr maximum is a safe upper bound that a
* valid l_count never exceeds.
*/
if (count > ocfs2_extent_recs_per_inode(sb)) {
rc = ocfs2_error(sb,
"Invalid dinode %llu: extent list l_count %u exceeds max %u\n",
(unsigned long long)bh->b_blocknr, count,
ocfs2_extent_recs_per_inode(sb));
goto bail;
}
if (next_free > count) {
rc = ocfs2_error(sb,
"Invalid dinode %llu: extent list l_next_free_rec %u exceeds l_count %u\n",
(unsigned long long)bh->b_blocknr, next_free, count);
goto bail;
}
}
rc = 0;
bail:
@@ -1624,6 +1793,40 @@ static int ocfs2_filecheck_validate_inode_block(struct super_block *sb,
(unsigned long long)bh->b_blocknr,
le32_to_cpu(di->i_fs_generation));
rc = -OCFS2_FILECHECK_ERR_GENERATION;
goto bail;
}
if (!ocfs2_valid_inode_mode(le16_to_cpu(di->i_mode))) {
mlog(ML_ERROR,
"Filecheck: invalid dinode #%llu: mode 0%o has unknown file type\n",
(unsigned long long)bh->b_blocknr,
le16_to_cpu(di->i_mode));
rc = -OCFS2_FILECHECK_ERR_INVALIDINO;
goto bail;
}
if (ocfs2_dinode_has_unexpected_rdev(di)) {
mlog(ML_ERROR,
"Filecheck: invalid dinode #%llu: non-device mode 0%o with i_rdev %llu\n",
(unsigned long long)bh->b_blocknr,
le16_to_cpu(di->i_mode),
(unsigned long long)le64_to_cpu(di->id1.dev1.i_rdev));
rc = -OCFS2_FILECHECK_ERR_INVALIDINO;
goto bail;
}
if (ocfs2_dinode_has_size_without_clusters(sb, di)) {
if (S_ISDIR(le16_to_cpu(di->i_mode)))
mlog(ML_ERROR,
"Filecheck: invalid dinode #%llu: directory i_size %llu with i_clusters 0 and no inline-data flag\n",
(unsigned long long)bh->b_blocknr,
(unsigned long long)le64_to_cpu(di->i_size));
else
mlog(ML_ERROR,
"Filecheck: invalid dinode #%llu: regular file i_size %llu with i_clusters 0 and no inline-data flag on non-sparse volume\n",
(unsigned long long)bh->b_blocknr,
(unsigned long long)le64_to_cpu(di->i_size));
rc = -OCFS2_FILECHECK_ERR_INVALIDINO;
}
bail:
@@ -1812,4 +2015,3 @@ const struct ocfs2_caching_operations ocfs2_inode_caching_ops = {
.co_io_lock = ocfs2_inode_cache_io_lock,
.co_io_unlock = ocfs2_inode_cache_io_unlock,
};

View File

@@ -473,8 +473,12 @@ int ocfs2_extend_trans(handle_t *handle, int nblocks)
*/
int ocfs2_assure_trans_credits(handle_t *handle, int nblocks)
{
int old_nblks = jbd2_handle_buffer_credits(handle);
int old_nblks;
if (is_handle_aborted(handle))
return -EROFS;
old_nblks = jbd2_handle_buffer_credits(handle);
trace_ocfs2_assure_trans_credits(old_nblks);
if (old_nblks >= nblocks)
return 0;
@@ -1022,11 +1026,8 @@ static int ocfs2_journal_toggle_dirty(struct ocfs2_super *osb,
struct ocfs2_dinode *fe;
fe = (struct ocfs2_dinode *)bh->b_data;
/* The journal bh on the osb always comes from ocfs2_journal_init()
* and was validated there inside ocfs2_inode_lock_full(). It's a
* code bug if we mess it up. */
BUG_ON(!OCFS2_IS_VALID_DINODE(fe));
if (WARN_ON(!OCFS2_IS_VALID_DINODE(fe)))
return -EIO;
flags = le32_to_cpu(fe->id1.journal1.ij_flags);
if (dirty)

View File

@@ -196,6 +196,9 @@ static inline void ocfs2_checkpoint_inode(struct inode *inode)
if (ocfs2_mount_local(osb))
return;
if (!osb->journal)
return;
if (!ocfs2_ci_fully_checkpointed(INODE_CACHE(inode))) {
/* WARNING: This only kicks off a single
* checkpoint. If someone races you and adds more

View File

@@ -534,6 +534,8 @@ static void ocfs2_probe_alloc_group(struct inode *inode, struct buffer_head *bh,
u32 base_cpos = ocfs2_blocks_to_clusters(inode->i_sb,
le64_to_cpu(gd->bg_blkno));
*phys_cpos = 0;
for (i = base_bit; i < le16_to_cpu(gd->bg_bits); i++) {
used = ocfs2_test_bit(i, (unsigned long *)gd->bg_bitmap);
@@ -555,7 +557,7 @@ static void ocfs2_probe_alloc_group(struct inode *inode, struct buffer_head *bh,
last_free_bits++;
if (last_free_bits == move_len) {
i -= move_len;
i = i - move_len + 1;
*goal_bit = i;
*phys_cpos = base_cpos + i;
break;

View File

@@ -494,8 +494,6 @@ struct ocfs2_super
struct rb_root osb_rf_lock_tree;
struct ocfs2_refcount_tree *osb_ref_tree_lru;
struct mutex system_file_mutex;
/*
* OCFS2 needs to schedule several different types of work which
* require cluster locking, disk I/O, recovery waits, etc. Since these

View File

@@ -302,7 +302,7 @@ static int ocfs2_add_recovery_chunk(struct super_block *sb,
if (!rc)
return -ENOMEM;
rc->rc_chunk = chunk;
rc->rc_bitmap = kmalloc(sb->s_blocksize, GFP_NOFS);
rc->rc_bitmap = kzalloc(sb->s_blocksize, GFP_NOFS);
if (!rc->rc_bitmap) {
kfree(rc);
return -ENOMEM;

View File

@@ -2131,10 +2131,15 @@ static int ocfs2_remove_refcount_extent(handle_t *handle,
rb->rf_flags = 0;
rb->rf_parent = 0;
rb->rf_cpos = 0;
memset(&rb->rf_records, 0, sb->s_blocksize -
offsetof(struct ocfs2_refcount_block, rf_records));
rb->rf_records.rl_used = 0;
rb->rf_records.rl_reserved2 = 0;
rb->rf_records.rl_reserved1 = 0;
/* rl_count determines the memset size and fortify object size. */
rb->rf_records.rl_count =
cpu_to_le16(ocfs2_refcount_recs_per_rb(sb));
memset(rb->rf_records.rl_recs, 0,
le16_to_cpu(rb->rf_records.rl_count) *
sizeof(*rb->rf_records.rl_recs));
}
ocfs2_journal_dirty(handle, ref_root_bh);

View File

@@ -327,18 +327,14 @@ static int ocfs2_control_install_private(struct file *file)
ocfs2_control_this_node = p->op_this_node;
running_proto.pv_major = p->op_proto.pv_major;
running_proto.pv_minor = p->op_proto.pv_minor;
}
out_unlock:
mutex_unlock(&ocfs2_control_lock);
if (!rc && set_p) {
/* We set the global values successfully */
atomic_inc(&ocfs2_control_opened);
ocfs2_control_set_handshake_state(file,
OCFS2_CONTROL_HANDSHAKE_VALID);
}
out_unlock:
mutex_unlock(&ocfs2_control_lock);
return rc;
}

View File

@@ -231,8 +231,16 @@ static int ocfs2_validate_gd_parent(struct super_block *sb,
int resize)
{
unsigned int max_bits;
unsigned int max_bitmap_bits;
unsigned int max_bitmap_size;
int suballocator;
struct ocfs2_group_desc *gd = (struct ocfs2_group_desc *)bh->b_data;
suballocator = le64_to_cpu(di->i_blkno) != OCFS2_SB(sb)->bitmap_blkno;
max_bitmap_size = ocfs2_group_bitmap_size(sb, suballocator,
OCFS2_SB(sb)->s_feature_incompat);
max_bitmap_bits = max_bitmap_size * 8;
if (di->i_blkno != gd->bg_parent_dinode) {
do_error("Group descriptor #%llu has bad parent pointer (%llu, expected %llu)\n",
(unsigned long long)bh->b_blocknr,
@@ -240,6 +248,20 @@ static int ocfs2_validate_gd_parent(struct super_block *sb,
(unsigned long long)le64_to_cpu(di->i_blkno));
}
if (le16_to_cpu(gd->bg_size) > max_bitmap_size) {
do_error("Group descriptor #%llu has bitmap size %u but physical max of %u\n",
(unsigned long long)bh->b_blocknr,
le16_to_cpu(gd->bg_size),
max_bitmap_size);
}
if (le16_to_cpu(gd->bg_bits) > max_bitmap_bits) {
do_error("Group descriptor #%llu has bit count %u but physical max of %u\n",
(unsigned long long)bh->b_blocknr,
le16_to_cpu(gd->bg_bits),
max_bitmap_bits);
}
max_bits = le16_to_cpu(di->id2.i_chain.cl_cpg) * le16_to_cpu(di->id2.i_chain.cl_bpc);
if (le16_to_cpu(gd->bg_bits) > max_bits) {
do_error("Group descriptor #%llu has bit count of %u\n",

View File

@@ -1996,8 +1996,6 @@ static int ocfs2_initialize_super(struct super_block *sb,
spin_lock_init(&osb->osb_xattr_lock);
ocfs2_init_steal_slots(osb);
mutex_init(&osb->system_file_mutex);
atomic_set(&osb->alloc_stats.moves, 0);
atomic_set(&osb->alloc_stats.local_data, 0);
atomic_set(&osb->alloc_stats.bitmap_data, 0);

View File

@@ -98,11 +98,9 @@ struct inode *ocfs2_get_system_file_inode(struct ocfs2_super *osb,
} else
arr = get_local_system_inode(osb, type, slot);
mutex_lock(&osb->system_file_mutex);
if (arr && ((inode = *arr) != NULL)) {
/* get a ref in addition to the array ref */
inode = igrab(inode);
mutex_unlock(&osb->system_file_mutex);
BUG_ON(!inode);
return inode;
@@ -112,11 +110,10 @@ struct inode *ocfs2_get_system_file_inode(struct ocfs2_super *osb,
inode = _ocfs2_get_system_file_inode(osb, type, slot);
/* add one more if putting into array for first time */
if (arr && inode) {
*arr = igrab(inode);
BUG_ON(!*arr);
if (inode && arr && !*arr && !cmpxchg(&(*arr), NULL, inode)) {
inode = igrab(inode);
BUG_ON(!inode);
}
mutex_unlock(&osb->system_file_mutex);
return inode;
}

View File

@@ -950,15 +950,51 @@ static int ocfs2_xattr_list_entries(struct inode *inode,
return result;
}
static int ocfs2_xattr_ibody_lookup_header(struct inode *inode,
struct ocfs2_dinode *di,
struct ocfs2_xattr_header **header)
{
u16 xattr_count;
size_t max_entries;
u16 inline_size = le16_to_cpu(di->i_xattr_inline_size);
if (inline_size > inode->i_sb->s_blocksize ||
inline_size < sizeof(struct ocfs2_xattr_header)) {
ocfs2_error(inode->i_sb,
"Invalid xattr inline size %u in inode %llu\n",
inline_size,
(unsigned long long)OCFS2_I(inode)->ip_blkno);
return -EFSCORRUPTED;
}
*header = (struct ocfs2_xattr_header *)
((void *)di + inode->i_sb->s_blocksize - inline_size);
xattr_count = le16_to_cpu((*header)->xh_count);
max_entries = (inline_size - sizeof(struct ocfs2_xattr_header)) /
sizeof(struct ocfs2_xattr_entry);
if (xattr_count > max_entries) {
ocfs2_error(inode->i_sb,
"xattr entry count %u exceeds maximum %zu in inode %llu\n",
xattr_count, max_entries,
(unsigned long long)OCFS2_I(inode)->ip_blkno);
return -EFSCORRUPTED;
}
return 0;
}
int ocfs2_has_inline_xattr_value_outside(struct inode *inode,
struct ocfs2_dinode *di)
{
struct ocfs2_xattr_header *xh;
int ret;
int i;
xh = (struct ocfs2_xattr_header *)
((void *)di + inode->i_sb->s_blocksize -
le16_to_cpu(di->i_xattr_inline_size));
ret = ocfs2_xattr_ibody_lookup_header(inode, di, &xh);
if (ret)
return 1;
for (i = 0; i < le16_to_cpu(xh->xh_count); i++)
if (!ocfs2_xattr_is_local(&xh->xh_entries[i]))
@@ -975,39 +1011,13 @@ static int ocfs2_xattr_ibody_list(struct inode *inode,
struct ocfs2_xattr_header *header = NULL;
struct ocfs2_inode_info *oi = OCFS2_I(inode);
int ret = 0;
u16 xattr_count;
size_t max_entries;
u16 inline_size;
if (!(oi->ip_dyn_features & OCFS2_INLINE_XATTR_FL))
return ret;
inline_size = le16_to_cpu(di->i_xattr_inline_size);
/* Validate inline size is reasonable */
if (inline_size > inode->i_sb->s_blocksize ||
inline_size < sizeof(struct ocfs2_xattr_header)) {
ocfs2_error(inode->i_sb,
"Invalid xattr inline size %u in inode %llu\n",
inline_size,
(unsigned long long)OCFS2_I(inode)->ip_blkno);
return -EFSCORRUPTED;
}
header = (struct ocfs2_xattr_header *)
((void *)di + inode->i_sb->s_blocksize - inline_size);
xattr_count = le16_to_cpu(header->xh_count);
max_entries = (inline_size - sizeof(struct ocfs2_xattr_header)) /
sizeof(struct ocfs2_xattr_entry);
if (xattr_count > max_entries) {
ocfs2_error(inode->i_sb,
"xattr entry count %u exceeds maximum %zu in inode %llu\n",
xattr_count, max_entries,
(unsigned long long)OCFS2_I(inode)->ip_blkno);
return -EFSCORRUPTED;
}
ret = ocfs2_xattr_ibody_lookup_header(inode, di, &header);
if (ret)
return ret;
ret = ocfs2_xattr_list_entries(inode, header, buffer, buffer_size);
@@ -1200,8 +1210,9 @@ static int ocfs2_xattr_ibody_get(struct inode *inode,
return -ENODATA;
xs->end = (void *)di + inode->i_sb->s_blocksize;
xs->header = (struct ocfs2_xattr_header *)
(xs->end - le16_to_cpu(di->i_xattr_inline_size));
ret = ocfs2_xattr_ibody_lookup_header(inode, di, &xs->header);
if (ret)
return ret;
xs->base = (void *)xs->header;
xs->here = xs->header->xh_entries;
@@ -2465,9 +2476,9 @@ static int ocfs2_xattr_ibody_remove(struct inode *inode,
.vb_access = ocfs2_journal_access_di,
};
header = (struct ocfs2_xattr_header *)
((void *)di + inode->i_sb->s_blocksize -
le16_to_cpu(di->i_xattr_inline_size));
ret = ocfs2_xattr_ibody_lookup_header(inode, di, &header);
if (ret)
return ret;
ret = ocfs2_remove_value_outside(inode, &vb, header,
ref_ci, ref_root_bh);
@@ -2726,12 +2737,14 @@ static int ocfs2_xattr_ibody_find(struct inode *inode,
xs->xattr_bh = xs->inode_bh;
xs->end = (void *)di + inode->i_sb->s_blocksize;
if (oi->ip_dyn_features & OCFS2_INLINE_XATTR_FL)
xs->header = (struct ocfs2_xattr_header *)
(xs->end - le16_to_cpu(di->i_xattr_inline_size));
else
if (oi->ip_dyn_features & OCFS2_INLINE_XATTR_FL) {
ret = ocfs2_xattr_ibody_lookup_header(inode, di, &xs->header);
if (ret)
return ret;
} else {
xs->header = (struct ocfs2_xattr_header *)
(xs->end - OCFS2_SB(inode->i_sb)->s_xattr_inline_size);
}
xs->base = (void *)xs->header;
xs->here = xs->header->xh_entries;
@@ -6003,14 +6016,17 @@ static int ocfs2_xattr_inline_attach_refcount(struct inode *inode,
struct ocfs2_cached_dealloc_ctxt *dealloc)
{
struct ocfs2_dinode *di = (struct ocfs2_dinode *)fe_bh->b_data;
struct ocfs2_xattr_header *header = (struct ocfs2_xattr_header *)
(fe_bh->b_data + inode->i_sb->s_blocksize -
le16_to_cpu(di->i_xattr_inline_size));
struct ocfs2_xattr_header *header;
int ret;
struct ocfs2_xattr_value_buf vb = {
.vb_bh = fe_bh,
.vb_access = ocfs2_journal_access_di,
};
ret = ocfs2_xattr_ibody_lookup_header(inode, di, &header);
if (ret)
return ret;
return ocfs2_xattr_attach_refcount_normal(inode, &vb, header,
ref_ci, ref_root_bh, dealloc);
}
@@ -6495,12 +6511,10 @@ static int ocfs2_reflink_xattr_inline(struct ocfs2_xattr_reflink *args)
handle_t *handle;
struct ocfs2_super *osb = OCFS2_SB(args->old_inode->i_sb);
struct ocfs2_dinode *di = (struct ocfs2_dinode *)args->old_bh->b_data;
int inline_size = le16_to_cpu(di->i_xattr_inline_size);
int header_off = osb->sb->s_blocksize - inline_size;
struct ocfs2_xattr_header *xh = (struct ocfs2_xattr_header *)
(args->old_bh->b_data + header_off);
struct ocfs2_xattr_header *new_xh = (struct ocfs2_xattr_header *)
(args->new_bh->b_data + header_off);
int inline_size;
int header_off;
struct ocfs2_xattr_header *xh;
struct ocfs2_xattr_header *new_xh;
struct ocfs2_alloc_context *meta_ac = NULL;
struct ocfs2_inode_info *new_oi;
struct ocfs2_dinode *new_di;
@@ -6509,6 +6523,15 @@ static int ocfs2_reflink_xattr_inline(struct ocfs2_xattr_reflink *args)
.vb_access = ocfs2_journal_access_di,
};
ret = ocfs2_xattr_ibody_lookup_header(args->old_inode, di, &xh);
if (ret)
goto out;
inline_size = le16_to_cpu(di->i_xattr_inline_size);
header_off = osb->sb->s_blocksize - inline_size;
new_xh = (struct ocfs2_xattr_header *)
(args->new_bh->b_data + header_off);
ret = ocfs2_reflink_lock_xattr_allocators(osb, xh, args->ref_root_bh,
&credits, &meta_ac);
if (ret) {

View File

@@ -3513,28 +3513,42 @@ struct dentry *proc_pid_lookup(struct dentry *dentry, unsigned int flags)
struct tgid_iter {
unsigned int tgid;
struct task_struct *task;
struct pid_namespace *const pid_ns;
};
static struct tgid_iter next_tgid(struct pid_namespace *ns, struct tgid_iter iter)
{
struct pid *pid;
if (iter.task)
put_task_struct(iter.task);
rcu_read_lock();
retry:
iter.task = NULL;
pid = find_ge_pid(iter.tgid, ns);
if (pid) {
iter.tgid = pid_nr_ns(pid, ns);
iter.task = pid_task(pid, PIDTYPE_TGID);
if (!iter.task) {
iter.tgid += 1;
goto retry;
}
get_task_struct(iter.task);
static struct tgid_iter
make_tgid_iter(unsigned int init_tgid, struct pid_namespace *pid_ns)
{
return (struct tgid_iter){
.tgid = init_tgid - 1,
.pid_ns = pid_ns,
};
}
static bool next_tgid(struct tgid_iter *it)
{
if (it->task) {
put_task_struct(it->task);
it->task = NULL;
}
rcu_read_lock();
while (1) {
it->tgid += 1;
const auto pid = find_ge_pid(it->tgid, it->pid_ns);
if (pid) {
it->tgid = pid_nr_ns(pid, it->pid_ns);
it->task = pid_task(pid, PIDTYPE_TGID);
if (it->task) {
get_task_struct(it->task);
rcu_read_unlock();
return true;
}
} else {
rcu_read_unlock();
return false;
}
}
rcu_read_unlock();
return iter;
}
#define TGID_OFFSET (FIRST_PROCESS_ENTRY + 2)
@@ -3542,9 +3556,8 @@ static struct tgid_iter next_tgid(struct pid_namespace *ns, struct tgid_iter ite
/* for the /proc/ directory itself, after non-process stuff has been done */
int proc_pid_readdir(struct file *file, struct dir_context *ctx)
{
struct tgid_iter iter;
struct proc_fs_info *fs_info = proc_sb_info(file_inode(file)->i_sb);
struct pid_namespace *ns = proc_pid_ns(file_inode(file)->i_sb);
struct pid_namespace *pid_ns = proc_pid_ns(file_inode(file)->i_sb);
loff_t pos = ctx->pos;
if (pos >= PID_MAX_LIMIT + TGID_OFFSET)
@@ -3560,11 +3573,9 @@ int proc_pid_readdir(struct file *file, struct dir_context *ctx)
return 0;
ctx->pos = pos = pos + 1;
}
iter.tgid = pos - TGID_OFFSET;
iter.task = NULL;
for (iter = next_tgid(ns, iter);
iter.task;
iter.tgid += 1, iter = next_tgid(ns, iter)) {
auto iter = make_tgid_iter(pos - TGID_OFFSET, pid_ns);
while (next_tgid(&iter)) {
char name[10 + 1];
unsigned int len;

View File

@@ -427,9 +427,13 @@ static struct proc_dir_entry *__proc_create(struct proc_dir_entry **parent,
if (xlate_proc_name(name, parent, &fn) != 0)
goto out;
qstr.name = fn;
qstr.len = strlen(fn);
if (qstr.len == 0 || qstr.len >= 256) {
WARN(1, "name len %u\n", qstr.len);
qstr.len = strnlen(fn, NAME_MAX + 1);
if (qstr.len == 0) {
WARN(1, "empty name\n");
return NULL;
}
if (qstr.len > NAME_MAX) {
WARN(1, "name too long\n");
return NULL;
}
if (qstr.len == 1 && fn[0] == '.') {

View File

@@ -91,8 +91,7 @@ raw_copy_to_user(void __user *to, const void *from, unsigned long n)
memcpy((void __force *)to, from, n);
return 0;
}
#define INLINE_COPY_FROM_USER
#define INLINE_COPY_TO_USER
#define INLINE_COPY_USER
#endif /* CONFIG_UACCESS_MEMCPY */
/*

View File

@@ -1,104 +0,0 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Extend a 32-bit counter to 63 bits
*
* Author: Nicolas Pitre
* Created: December 3, 2006
* Copyright: MontaVista Software, Inc.
*/
#ifndef __LINUX_CNT32_TO_63_H__
#define __LINUX_CNT32_TO_63_H__
#include <linux/compiler.h>
#include <linux/types.h>
#include <asm/byteorder.h>
/* this is used only to give gcc a clue about good code generation */
union cnt32_to_63 {
struct {
#if defined(__LITTLE_ENDIAN)
u32 lo, hi;
#elif defined(__BIG_ENDIAN)
u32 hi, lo;
#endif
};
u64 val;
};
/**
* cnt32_to_63 - Expand a 32-bit counter to a 63-bit counter
* @cnt_lo: The low part of the counter
*
* Many hardware clock counters are only 32 bits wide and therefore have
* a relatively short period making wrap-arounds rather frequent. This
* is a problem when implementing sched_clock() for example, where a 64-bit
* non-wrapping monotonic value is expected to be returned.
*
* To overcome that limitation, let's extend a 32-bit counter to 63 bits
* in a completely lock free fashion. Bits 0 to 31 of the clock are provided
* by the hardware while bits 32 to 62 are stored in memory. The top bit in
* memory is used to synchronize with the hardware clock half-period. When
* the top bit of both counters (hardware and in memory) differ then the
* memory is updated with a new value, incrementing it when the hardware
* counter wraps around.
*
* Because a word store in memory is atomic then the incremented value will
* always be in synch with the top bit indicating to any potential concurrent
* reader if the value in memory is up to date or not with regards to the
* needed increment. And any race in updating the value in memory is harmless
* as the same value would simply be stored more than once.
*
* The restrictions for the algorithm to work properly are:
*
* 1) this code must be called at least once per each half period of the
* 32-bit counter;
*
* 2) this code must not be preempted for a duration longer than the
* 32-bit counter half period minus the longest period between two
* calls to this code;
*
* Those requirements ensure proper update to the state bit in memory.
* This is usually not a problem in practice, but if it is then a kernel
* timer should be scheduled to manage for this code to be executed often
* enough.
*
* And finally:
*
* 3) the cnt_lo argument must be seen as a globally incrementing value,
* meaning that it should be a direct reference to the counter data which
* can be evaluated according to a specific ordering within the macro,
* and not the result of a previous evaluation stored in a variable.
*
* For example, this is wrong:
*
* u32 partial = get_hw_count();
* u64 full = cnt32_to_63(partial);
* return full;
*
* This is fine:
*
* u64 full = cnt32_to_63(get_hw_count());
* return full;
*
* Note that the top bit (bit 63) in the returned value should be considered
* as garbage. It is not cleared here because callers are likely to use a
* multiplier on the returned value which can get rid of the top bit
* implicitly by making the multiplier even, therefore saving on a runtime
* clear-bit instruction. Otherwise caller must remember to clear the top
* bit explicitly.
*/
#define cnt32_to_63(cnt_lo) \
({ \
static u32 __m_cnt_hi; \
union cnt32_to_63 __x; \
__x.hi = __m_cnt_hi; \
smp_rmb(); \
__x.lo = (cnt_lo); \
if (unlikely((s32)(__x.hi ^ __x.lo) < 0)) \
__m_cnt_hi = __x.hi = (__x.hi ^ 0x80000000) + (__x.hi >> 31); \
__x.val; \
})
#endif

View File

@@ -36,7 +36,7 @@
*
* Return: A pointer with @error encoded within its value.
*/
static inline void * __must_check ERR_PTR(long error)
static __always_inline void * __must_check ERR_PTR(long error)
{
return (void *) error;
}
@@ -60,7 +60,7 @@ static inline void * __must_check ERR_PTR(long error)
* @ptr: An error pointer.
* Return: The error code within @ptr.
*/
static inline long __must_check PTR_ERR(__force const void *ptr)
static __always_inline long __must_check PTR_ERR(__force const void *ptr)
{
return (long) ptr;
}
@@ -73,7 +73,7 @@ static inline long __must_check PTR_ERR(__force const void *ptr)
* @ptr: The pointer to check.
* Return: true if @ptr is an error pointer, false otherwise.
*/
static inline bool __must_check IS_ERR(__force const void *ptr)
static __always_inline bool __must_check IS_ERR(__force const void *ptr)
{
return IS_ERR_VALUE((unsigned long)ptr);
}
@@ -87,7 +87,7 @@ static inline bool __must_check IS_ERR(__force const void *ptr)
*
* Like IS_ERR(), but also returns true for a null pointer.
*/
static inline bool __must_check IS_ERR_OR_NULL(__force const void *ptr)
static __always_inline bool __must_check IS_ERR_OR_NULL(__force const void *ptr)
{
return unlikely(!ptr) || IS_ERR_VALUE((unsigned long)ptr);
}
@@ -99,7 +99,7 @@ static inline bool __must_check IS_ERR_OR_NULL(__force const void *ptr)
* Explicitly cast an error-valued pointer to another pointer type in such a
* way as to make it clear that's what's going on.
*/
static inline void * __must_check ERR_CAST(__force const void *ptr)
static __always_inline void * __must_check ERR_CAST(__force const void *ptr)
{
/* cast away the const */
return (void *) ptr;
@@ -122,7 +122,7 @@ static inline void * __must_check ERR_CAST(__force const void *ptr)
*
* Return: The error code within @ptr if it is an error pointer; 0 otherwise.
*/
static inline int __must_check PTR_ERR_OR_ZERO(__force const void *ptr)
static __always_inline int __must_check PTR_ERR_OR_ZERO(__force const void *ptr)
{
if (IS_ERR(ptr))
return PTR_ERR(ptr);

View File

@@ -47,7 +47,7 @@
#define __initdata __section(".init.data")
#define __initconst __section(".init.rodata")
#define __exitdata __section(".exit.data")
#define __exit_call __used __section(".exitcall.exit")
#define __exit_call __maybe_unused __section(".exitcall.exit")
/*
* modpost check for section mismatches during the kernel build.

View File

@@ -21,8 +21,6 @@ enum kcov_mode {
KCOV_MODE_TRACE_PC = 2,
/* Collecting comparison operands mode. */
KCOV_MODE_TRACE_CMP = 3,
/* The process owns a KCOV remote reference. */
KCOV_MODE_REMOTE = 4,
};
#define KCOV_IN_CTXSW (1 << 30)
@@ -43,11 +41,11 @@ do { \
/* See Documentation/dev-tools/kcov.rst for usage details. */
void kcov_remote_start(u64 handle);
void kcov_remote_stop(void);
u64 kcov_common_handle(void);
struct kcov_common_handle_id kcov_common_handle(void);
static inline void kcov_remote_start_common(u64 id)
static inline void kcov_remote_start_common(struct kcov_common_handle_id id)
{
kcov_remote_start(kcov_remote_handle(KCOV_SUBSYSTEM_COMMON, id));
kcov_remote_start(kcov_remote_handle(KCOV_SUBSYSTEM_COMMON, id.val));
}
static inline void kcov_remote_start_usb(u64 id)
@@ -99,11 +97,11 @@ static inline void kcov_prepare_switch(struct task_struct *t) {}
static inline void kcov_finish_switch(struct task_struct *t) {}
static inline void kcov_remote_start(u64 handle) {}
static inline void kcov_remote_stop(void) {}
static inline u64 kcov_common_handle(void)
static inline struct kcov_common_handle_id kcov_common_handle(void)
{
return 0;
return (struct kcov_common_handle_id){};
}
static inline void kcov_remote_start_common(u64 id) {}
static inline void kcov_remote_start_common(struct kcov_common_handle_id id) {}
static inline void kcov_remote_start_usb(u64 id) {}
static inline void kcov_remote_start_usb_softirq(u64 id) {}
static inline void kcov_remote_stop_softirq(void) {}

View File

@@ -26,8 +26,8 @@
*
* | add | del_first | del_all
* add | - | - | -
* del_first | | L | L
* del_all | | | -
* del_first | - | L | L
* del_all | - | - | -
*
* Where, a particular row's operation can happen concurrently with a column's
* operation, with "-" being no lock needed, while "L" being lock is needed.

View File

@@ -1,206 +1,24 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
/* -*- linux-c -*- ------------------------------------------------------- *
/*
* Copyright 2003 H. Peter Anvin - All Rights Reserved
*
* Copyright 2003 H. Peter Anvin - All Rights Reserved
*
* ----------------------------------------------------------------------- */
* Public interface to the RAID6 P/Q calculation and recovery library.
*/
#ifndef LINUX_RAID_PQ_H
#define LINUX_RAID_PQ_H
#ifndef LINUX_RAID_RAID6_H
#define LINUX_RAID_RAID6_H
#include <linux/types.h>
#ifdef __KERNEL__
#define RAID6_MIN_DISKS 4
#include <linux/blkdev.h>
#include <linux/mm.h>
void raid6_gen_syndrome(int disks, size_t bytes, void **ptrs);
void raid6_xor_syndrome(int disks, int start, int stop, size_t bytes,
void **ptrs);
bool raid6_can_xor_syndrome(void);
/* This should be const but the raid6 code is too convoluted for that. */
static inline void *raid6_get_zero_page(void)
{
return page_address(ZERO_PAGE(0));
}
void raid6_recov_2data(int disks, size_t bytes, int faila, int failb,
void **ptrs);
void raid6_recov_datap(int disks, size_t bytes, int faila,
void **ptrs);
#else /* ! __KERNEL__ */
/* Used for testing in user space */
#include <errno.h>
#include <inttypes.h>
#include <stddef.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/time.h>
#include <sys/types.h>
/* Not standard, but glibc defines it */
#define BITS_PER_LONG __WORDSIZE
typedef uint8_t u8;
typedef uint16_t u16;
typedef uint32_t u32;
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
#define __exit
#ifndef __attribute_const__
# define __attribute_const__ __attribute__((const))
#endif
#define noinline __attribute__((noinline))
#define preempt_enable()
#define preempt_disable()
#define cpu_has_feature(x) 1
#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)
#define subsys_initcall(x)
#define module_exit(x)
#define IS_ENABLED(x) (x)
#define CONFIG_RAID6_PQ_BENCHMARK 1
#endif /* __KERNEL__ */
/* Routine choices */
struct raid6_calls {
void (*gen_syndrome)(int, size_t, void **);
void (*xor_syndrome)(int, int, int, size_t, void **);
int (*valid)(void); /* Returns 1 if this routine set is usable */
const char *name; /* Name of this routine set */
int priority; /* Relative priority ranking if non-zero */
};
/* Selected algorithm */
extern struct raid6_calls raid6_call;
/* Various routine sets */
extern const struct raid6_calls raid6_intx1;
extern const struct raid6_calls raid6_intx2;
extern const struct raid6_calls raid6_intx4;
extern const struct raid6_calls raid6_intx8;
extern const struct raid6_calls raid6_mmxx1;
extern const struct raid6_calls raid6_mmxx2;
extern const struct raid6_calls raid6_sse1x1;
extern const struct raid6_calls raid6_sse1x2;
extern const struct raid6_calls raid6_sse2x1;
extern const struct raid6_calls raid6_sse2x2;
extern const struct raid6_calls raid6_sse2x4;
extern const struct raid6_calls raid6_altivec1;
extern const struct raid6_calls raid6_altivec2;
extern const struct raid6_calls raid6_altivec4;
extern const struct raid6_calls raid6_altivec8;
extern const struct raid6_calls raid6_avx2x1;
extern const struct raid6_calls raid6_avx2x2;
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;
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;
extern const struct raid6_calls raid6_lsx;
extern const struct raid6_calls raid6_lasx;
extern const struct raid6_calls raid6_rvvx1;
extern const struct raid6_calls raid6_rvvx2;
extern const struct raid6_calls raid6_rvvx4;
extern const struct raid6_calls raid6_rvvx8;
struct raid6_recov_calls {
void (*data2)(int, size_t, int, int, void **);
void (*datap)(int, size_t, int, void **);
int (*valid)(void);
const char *name;
int priority;
};
extern const struct raid6_recov_calls raid6_recov_intx1;
extern const struct raid6_recov_calls raid6_recov_ssse3;
extern const struct raid6_recov_calls raid6_recov_avx2;
extern const struct raid6_recov_calls raid6_recov_avx512;
extern const struct raid6_recov_calls raid6_recov_s390xc;
extern const struct raid6_recov_calls raid6_recov_neon;
extern const struct raid6_recov_calls raid6_recov_lsx;
extern const struct raid6_recov_calls raid6_recov_lasx;
extern const struct raid6_recov_calls raid6_recov_rvv;
extern const struct raid6_calls raid6_neonx1;
extern const struct raid6_calls raid6_neonx2;
extern const struct raid6_calls raid6_neonx4;
extern const struct raid6_calls raid6_neonx8;
/* Algorithm list */
extern const struct raid6_calls * const raid6_algos[];
extern const struct raid6_recov_calls *const raid6_recov_algos[];
int raid6_select_algo(void);
/* Return values from chk_syndrome */
#define RAID6_OK 0
#define RAID6_P_BAD 1
#define RAID6_Q_BAD 2
#define RAID6_PQ_BAD 3
/* Galois field tables */
extern const u8 raid6_gfmul[256][256] __attribute__((aligned(256)));
extern const u8 raid6_vgfmul[256][32] __attribute__((aligned(256)));
extern const u8 raid6_gfexp[256] __attribute__((aligned(256)));
extern const u8 raid6_gflog[256] __attribute__((aligned(256)));
extern const u8 raid6_gfinv[256] __attribute__((aligned(256)));
extern const u8 raid6_gfexi[256] __attribute__((aligned(256)));
/* Recovery routines */
extern void (*raid6_2data_recov)(int disks, size_t bytes, int faila, int failb,
void **ptrs);
extern void (*raid6_datap_recov)(int disks, size_t bytes, int faila,
void **ptrs);
void raid6_dual_recov(int disks, size_t bytes, int faila, int failb,
void **ptrs);
/* Some definitions to allow code to be compiled for testing in userspace */
#ifndef __KERNEL__
# define jiffies raid6_jiffies()
# define printk printf
# define pr_err(format, ...) fprintf(stderr, format, ## __VA_ARGS__)
# define pr_info(format, ...) fprintf(stdout, format, ## __VA_ARGS__)
# define GFP_KERNEL 0
# define __get_free_pages(x, y) ((unsigned long)mmap(NULL, PAGE_SIZE << (y), \
PROT_READ|PROT_WRITE, \
MAP_PRIVATE|MAP_ANONYMOUS,\
0, 0))
# define free_pages(x, y) munmap((void *)(x), PAGE_SIZE << (y))
static inline void cpu_relax(void)
{
/* Nothing */
}
#undef HZ
#define HZ 1000
static inline uint32_t raid6_jiffies(void)
{
struct timeval tv;
gettimeofday(&tv, NULL);
return tv.tv_sec*1000 + tv.tv_usec/1000;
}
static inline void *raid6_get_zero_page(void)
{
return raid6_empty_zero_page;
}
#endif /* ! __KERNEL__ */
#endif /* LINUX_RAID_RAID6_H */
#endif /* LINUX_RAID_PQ_H */

View File

@@ -0,0 +1,19 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
* Copyright 2003 H. Peter Anvin - All Rights Reserved
*
* Galois field tables for the Linux RAID6 P/Q parity algorithm.
*/
#ifndef _LINUX_RAID_PQ_TABLES_H
#define _LINUX_RAID_PQ_TABLES_H
#include <linux/types.h>
extern const u8 raid6_gfmul[256][256] __attribute__((aligned(256)));
extern const u8 raid6_vgfmul[256][32] __attribute__((aligned(256)));
extern const u8 raid6_gfexp[256] __attribute__((aligned(256)));
extern const u8 raid6_gflog[256] __attribute__((aligned(256)));
extern const u8 raid6_gfinv[256] __attribute__((aligned(256)));
extern const u8 raid6_gfexi[256] __attribute__((aligned(256)));
#endif /* _LINUX_RAID_PQ_TABLES_H */

View File

@@ -1532,6 +1532,9 @@ struct task_struct {
/* KCOV descriptor wired with this task or NULL: */
struct kcov *kcov;
/* KCOV descriptor for remote coverage collection from other tasks: */
struct kcov *kcov_remote;
/* KCOV common handle for remote coverage collection: */
u64 kcov_handle;

View File

@@ -1084,9 +1084,7 @@ struct sk_buff {
__u16 network_header;
__u16 mac_header;
#ifdef CONFIG_KCOV
u64 kcov_handle;
#endif
struct kcov_common_handle_id kcov_handle;
); /* end headers group */
@@ -5440,20 +5438,14 @@ static inline void skb_reset_csum_not_inet(struct sk_buff *skb)
}
static inline void skb_set_kcov_handle(struct sk_buff *skb,
const u64 kcov_handle)
struct kcov_common_handle_id kcov_handle)
{
#ifdef CONFIG_KCOV
skb->kcov_handle = kcov_handle;
#endif
}
static inline u64 skb_get_kcov_handle(struct sk_buff *skb)
static inline struct kcov_common_handle_id skb_get_kcov_handle(struct sk_buff *skb)
{
#ifdef CONFIG_KCOV
return skb->kcov_handle;
#else
return 0;
#endif
}
static inline void skb_mark_for_recycle(struct sk_buff *skb)

View File

@@ -224,6 +224,12 @@ struct ustat {
char f_fpack[6];
};
struct kcov_common_handle_id {
#ifdef CONFIG_KCOV
u64 val;
#endif
};
/**
* struct callback_head - callback structure for use with RCU and task_work
* @next: next update requests in a list

View File

@@ -84,7 +84,7 @@
* the 6 functions (copy_{to,from}_user(), __copy_{to,from}_user_inatomic())
* that are used instead. Out of those, __... ones are inlined. Plain
* copy_{to,from}_user() might or might not be inlined. If you want them
* inlined, have asm/uaccess.h define INLINE_COPY_{TO,FROM}_USER.
* inlined, have asm/uaccess.h define INLINE_COPY_USER.
*
* NOTE: only copy_from_user() zero-pads the destination in case of short copy.
* Neither __copy_from_user() nor __copy_from_user_inatomic() zero anything
@@ -157,7 +157,7 @@ __copy_to_user(void __user *to, const void *from, unsigned long n)
}
/*
* Architectures that #define INLINE_COPY_TO_USER use this function
* Architectures that #define INLINE_COPY_USER use this function
* directly in the normal copy_to/from_user(), the other ones go
* through an extern _copy_to/from_user(), which expands the same code
* here.
@@ -190,10 +190,6 @@ _inline_copy_from_user(void *to, const void __user *from, unsigned long n)
memset(to + (n - res), 0, res);
return res;
}
#ifndef INLINE_COPY_FROM_USER
extern __must_check unsigned long
_copy_from_user(void *, const void __user *, unsigned long);
#endif
static inline __must_check unsigned long
_inline_copy_to_user(void __user *to, const void *from, unsigned long n)
@@ -207,7 +203,13 @@ _inline_copy_to_user(void __user *to, const void *from, unsigned long n)
}
return n;
}
#ifndef INLINE_COPY_TO_USER
#ifdef INLINE_COPY_USER
# define _copy_to_user _inline_copy_to_user
# define _copy_from_user _inline_copy_from_user
#else
extern __must_check unsigned long
_copy_from_user(void *, const void __user *, unsigned long);
extern __must_check unsigned long
_copy_to_user(void __user *, const void *, unsigned long);
#endif
@@ -217,11 +219,7 @@ copy_from_user(void *to, const void __user *from, unsigned long n)
{
if (!check_copy_size(to, n, false))
return n;
#ifdef INLINE_COPY_FROM_USER
return _inline_copy_from_user(to, from, n);
#else
return _copy_from_user(to, from, n);
#endif
}
static __always_inline unsigned long __must_check
@@ -229,12 +227,7 @@ copy_to_user(void __user *to, const void *from, unsigned long n)
{
if (!check_copy_size(from, n, true))
return n;
#ifdef INLINE_COPY_TO_USER
return _inline_copy_to_user(to, from, n);
#else
return _copy_to_user(to, from, n);
#endif
}
#ifndef copy_mc_to_kernel

View File

@@ -1061,14 +1061,14 @@ config PAGE_COUNTER
bool
config CGROUP_FAVOR_DYNMODS
bool "Favor dynamic modification latency reduction by default"
help
This option enables the "favordynmods" mount option by default
which reduces the latencies of dynamic cgroup modifications such
as task migrations and controller on/offs at the cost of making
hot path operations such as forks and exits more expensive.
bool "Favor dynamic modification latency reduction by default"
help
This option enables the "favordynmods" mount option by default
which reduces the latencies of dynamic cgroup modifications such
as task migrations and controller on/offs at the cost of making
hot path operations such as forks and exits more expensive.
Say N if unsure.
Say N if unsure.
config MEMCG
bool "Memory controller"
@@ -1150,7 +1150,7 @@ config GROUP_SCHED_WEIGHT
def_bool n
config GROUP_SCHED_BANDWIDTH
def_bool n
def_bool n
config FAIR_GROUP_SCHED
bool "Group scheduling for SCHED_OTHER"
@@ -1656,10 +1656,10 @@ config LD_ORPHAN_WARN
depends on $(ld-option,--orphan-handling=error)
config LD_ORPHAN_WARN_LEVEL
string
depends on LD_ORPHAN_WARN
default "error" if WERROR
default "warn"
string
depends on LD_ORPHAN_WARN
default "error" if WERROR
default "warn"
config SYSCTL
bool

View File

@@ -3700,7 +3700,7 @@ __bpf_kfunc int bpf_copy_from_user_task_str(void *dst, u32 dst__sz,
return ret + 1;
}
/* Keep unsinged long in prototype so that kfunc is usable when emitted to
/* Keep unsigned long in prototype so that kfunc is usable when emitted to
* vmlinux.h in BPF programs directly, but note that while in BPF prog, the
* unsigned long always points to 8-byte region on stack, the kernel may only
* read and write the 4-bytes on 32-bit.

View File

@@ -368,6 +368,7 @@ static void kcov_start(struct task_struct *t, struct kcov *kcov,
WRITE_ONCE(t->kcov_mode, mode);
}
/* operates on coverage-generator-owned fields */
static void kcov_stop(struct task_struct *t)
{
WRITE_ONCE(t->kcov_mode, KCOV_MODE_DISABLED);
@@ -377,16 +378,17 @@ static void kcov_stop(struct task_struct *t)
t->kcov_area = NULL;
}
/* operates on coverage-generator-owned fields */
static void kcov_task_reset(struct task_struct *t)
{
kcov_stop(t);
t->kcov_sequence = 0;
t->kcov_handle = 0;
}
void kcov_task_init(struct task_struct *t)
{
kcov_task_reset(t);
t->kcov_remote = NULL;
t->kcov_handle = current->kcov_handle;
}
@@ -423,11 +425,14 @@ static void kcov_remote_reset(struct kcov *kcov)
static void kcov_disable(struct task_struct *t, struct kcov *kcov)
__must_hold(&kcov->lock)
{
kcov_task_reset(t);
if (kcov->remote)
if (kcov->remote) {
t->kcov_handle = 0;
t->kcov_remote = NULL;
kcov_remote_reset(kcov);
else
} else {
kcov_task_reset(t);
kcov_reset(kcov);
}
}
static void kcov_get(struct kcov *kcov)
@@ -453,41 +458,47 @@ void kcov_task_exit(struct task_struct *t)
unsigned long flags;
kcov = t->kcov;
if (kcov == NULL)
return;
spin_lock_irqsave(&kcov->lock, flags);
kcov_debug("t = %px, kcov->t = %px\n", t, kcov->t);
/*
* For KCOV_ENABLE devices we want to make sure that t->kcov->t == t,
* which comes down to:
* WARN_ON(!kcov->remote && kcov->t != t);
*
* For KCOV_REMOTE_ENABLE devices, the exiting task is either:
*
* 1. A remote task between kcov_remote_start() and kcov_remote_stop().
* In this case we should print a warning right away, since a task
* shouldn't be exiting when it's in a kcov coverage collection
* section. Here t points to the task that is collecting remote
* coverage, and t->kcov->t points to the thread that created the
* kcov device. Which means that to detect this case we need to
* check that t != t->kcov->t, and this gives us the following:
* WARN_ON(kcov->remote && kcov->t != t);
*
* 2. The task that created kcov exiting without calling KCOV_DISABLE,
* and then again we make sure that t->kcov->t == t:
* WARN_ON(kcov->remote && kcov->t != t);
*
* By combining all three checks into one we get:
*/
if (WARN_ON(kcov->t != t)) {
if (kcov) {
spin_lock_irqsave(&kcov->lock, flags);
kcov_debug("t = %px, kcov->t = %px\n", t, kcov->t);
/*
* This could be a remote task between kcov_remote_start() and
* kcov_remote_stop().
* In this case we should print a warning right away, since a
* task shouldn't be exiting when it's in a kcov coverage
* collection section.
*
* Otherwise, this should be a task that created a local
* kcov instance and hasn't called KCOV_DISABLE.
* Make sure that t->kcov->t is consistent.
*/
if (WARN_ON(kcov->remote) || WARN_ON(kcov->t != t)) {
spin_unlock_irqrestore(&kcov->lock, flags);
return;
}
/* Just to not leave dangling references behind. */
kcov_disable(t, kcov);
spin_unlock_irqrestore(&kcov->lock, flags);
return;
kcov_put(kcov);
}
kcov = t->kcov_remote;
if (kcov) {
spin_lock_irqsave(&kcov->lock, flags);
kcov_debug("t = %px, kcov->t = %px\n", t, kcov->t);
/*
* This is a KCOV_REMOTE_ENABLE device, and the task is the
* user task which has requested remote coverage collection.
* Make sure that t->kcov->t is consistent.
*/
if (WARN_ON(!kcov->remote) || WARN_ON(kcov->t != t)) {
spin_unlock_irqrestore(&kcov->lock, flags);
return;
}
/* Just to not leave dangling references behind. */
kcov_disable(t, kcov);
spin_unlock_irqrestore(&kcov->lock, flags);
kcov_put(kcov);
}
/* Just to not leave dangling references behind. */
kcov_disable(t, kcov);
spin_unlock_irqrestore(&kcov->lock, flags);
kcov_put(kcov);
}
static int kcov_mmap(struct file *filep, struct vm_area_struct *vma)
@@ -629,9 +640,9 @@ static int kcov_ioctl_locked(struct kcov *kcov, unsigned int cmd,
case KCOV_DISABLE:
/* Disable coverage for the current task. */
unused = arg;
if (unused != 0 || current->kcov != kcov)
return -EINVAL;
t = current;
if (unused != 0 || (kcov != t->kcov && kcov != t->kcov_remote))
return -EINVAL;
if (WARN_ON(kcov->t != t))
return -EINVAL;
kcov_disable(t, kcov);
@@ -641,7 +652,7 @@ static int kcov_ioctl_locked(struct kcov *kcov, unsigned int cmd,
if (kcov->mode != KCOV_MODE_INIT || !kcov->area)
return -EINVAL;
t = current;
if (kcov->t != NULL || t->kcov != NULL)
if (kcov->t != NULL || t->kcov_remote != NULL)
return -EBUSY;
remote_arg = (struct kcov_remote_arg *)arg;
mode = kcov_get_mode(remote_arg->trace_mode);
@@ -651,8 +662,7 @@ static int kcov_ioctl_locked(struct kcov *kcov, unsigned int cmd,
LONG_MAX / sizeof(unsigned long))
return -EINVAL;
kcov->mode = mode;
t->kcov = kcov;
t->kcov_mode = KCOV_MODE_REMOTE;
t->kcov_remote = kcov;
kcov->t = t;
kcov->remote = true;
kcov->remote_size = remote_arg->area_size;
@@ -1083,11 +1093,11 @@ void kcov_remote_stop(void)
EXPORT_SYMBOL(kcov_remote_stop);
/* See the comment before kcov_remote_start() for usage details. */
u64 kcov_common_handle(void)
struct kcov_common_handle_id kcov_common_handle(void)
{
if (!in_task())
return 0;
return current->kcov_handle;
return (struct kcov_common_handle_id){ .val = 0 };
return (struct kcov_common_handle_id){ .val = current->kcov_handle };
}
EXPORT_SYMBOL(kcov_common_handle);
@@ -1109,10 +1119,10 @@ static void __init selftest(void)
* potentially traced functions in this region.
*/
start = jiffies;
current->kcov_mode = KCOV_MODE_TRACE_PC;
WRITE_ONCE(current->kcov_mode, KCOV_MODE_TRACE_PC);
while ((jiffies - start) * MSEC_PER_SEC / HZ < 300)
;
current->kcov_mode = 0;
WRITE_ONCE(current->kcov_mode, 0);
pr_err("done running self test\n");
}
#endif

View File

@@ -210,13 +210,39 @@ static int fill_stats_for_pid(pid_t pid, struct taskstats *stats)
return 0;
}
static void tgid_stats_add_task(struct taskstats *stats,
struct task_struct *tsk, u64 now_ns)
{
u64 delta, utime, stime;
/*
* Each accounting subsystem calls its functions here to
* accumulate its per-task stats for tsk, into the per-tgid structure
*
* per-task-foo(stats, tsk);
*/
delayacct_add_tsk(stats, tsk);
/* calculate task elapsed time in nsec */
delta = now_ns - tsk->start_time;
/* Convert to micro seconds */
do_div(delta, NSEC_PER_USEC);
stats->ac_etime += delta;
task_cputime(tsk, &utime, &stime);
stats->ac_utime += div_u64(utime, NSEC_PER_USEC);
stats->ac_stime += div_u64(stime, NSEC_PER_USEC);
stats->nvcsw += tsk->nvcsw;
stats->nivcsw += tsk->nivcsw;
}
static int fill_stats_for_tgid(pid_t tgid, struct taskstats *stats)
{
struct task_struct *tsk, *first;
unsigned long flags;
int rc = -ESRCH;
u64 delta, utime, stime;
u64 start_time;
u64 now_ns;
/*
* Add additional stats from live tasks except zombie thread group
@@ -233,30 +259,12 @@ static int fill_stats_for_tgid(pid_t tgid, struct taskstats *stats)
else
memset(stats, 0, sizeof(*stats));
start_time = ktime_get_ns();
now_ns = ktime_get_ns();
for_each_thread(first, tsk) {
if (tsk->exit_state)
continue;
/*
* Accounting subsystem can call its functions here to
* fill in relevant parts of struct taskstsats as follows
*
* per-task-foo(stats, tsk);
*/
delayacct_add_tsk(stats, tsk);
/* calculate task elapsed time in nsec */
delta = start_time - tsk->start_time;
/* Convert to micro seconds */
do_div(delta, NSEC_PER_USEC);
stats->ac_etime += delta;
task_cputime(tsk, &utime, &stime);
stats->ac_utime += div_u64(utime, NSEC_PER_USEC);
stats->ac_stime += div_u64(stime, NSEC_PER_USEC);
stats->nvcsw += tsk->nvcsw;
stats->nivcsw += tsk->nivcsw;
tgid_stats_add_task(stats, tsk, now_ns);
}
unlock_task_sighand(first, &flags);
@@ -275,18 +283,14 @@ static int fill_stats_for_tgid(pid_t tgid, struct taskstats *stats)
static void fill_tgid_exit(struct task_struct *tsk)
{
unsigned long flags;
u64 now_ns;
spin_lock_irqsave(&tsk->sighand->siglock, flags);
if (!tsk->signal->stats)
goto ret;
/*
* Each accounting subsystem calls its functions here to
* accumalate its per-task stats for tsk, into the per-tgid structure
*
* per-task-foo(tsk->signal->stats, tsk);
*/
delayacct_add_tsk(tsk->signal->stats, tsk);
now_ns = ktime_get_ns();
tgid_stats_add_task(tsk->signal->stats, tsk, now_ns);
ret:
spin_unlock_irqrestore(&tsk->sighand->siglock, flags);
return;

View File

@@ -8,17 +8,6 @@ config BINARY_PRINTF
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 LINEAR_RANGES
tristate
@@ -603,7 +592,7 @@ config OBJAGG
config LWQ_TEST
bool "Boot-time test for lwq queuing"
help
Run boot-time test of light-weight queuing.
Run boot-time test of light-weight queuing.
endmenu

View File

@@ -2976,6 +2976,16 @@ config BITS_TEST
If unsure, say N.
config SHDI3_KUNIT_TEST
tristate "KUnit test for __ashldi3(), __ashrdi3(), and __lshrdi3()"
depends on KUNIT
depends on ARM || XTENSA || MICROBLAZE || ((RISCV || SPARC) && !64BIT)
help
This builds the unit test for __ashldi3(), __ashrdi3(), and
__lshrdi3() helper functions used to implement 64-bit arithmetic
shift left, arithmetic shift right and logical shift right,
respectively, on a 32-bit CPUs.
config SLUB_KUNIT_TEST
tristate "KUnit test for SLUB cache error detection" if !KUNIT_ALL_TESTS
depends on SLUB_DEBUG && KUNIT

View File

@@ -167,7 +167,6 @@ obj-$(CONFIG_LZ4_DECOMPRESS) += lz4/
obj-$(CONFIG_ZSTD_COMPRESS) += zstd/
obj-$(CONFIG_ZSTD_DECOMPRESS) += zstd/
obj-$(CONFIG_XZ_DEC) += xz/
obj-$(CONFIG_RAID6_PQ) += raid6/
lib-$(CONFIG_DECOMPRESS_GZIP) += decompress_inflate.o
lib-$(CONFIG_DECOMPRESS_BZIP2) += decompress_bunzip2.o

View File

@@ -122,7 +122,7 @@ EXPORT_SYMBOL_GPL(base64_encode);
* @src: the string to decode. Doesn't need to be NUL-terminated.
* @srclen: the length of @src in bytes
* @dst: (output) the decoded binary data
* @padding: whether to append '=' padding characters
* @padding: whether the input is expected to include '=' padding characters
* @variant: which base64 variant to use
*
* Decodes a string using the selected Base64 variant.
@@ -168,15 +168,16 @@ int base64_decode(const char *src, int srclen, u8 *dst, bool padding, enum base6
return -1;
val = (base64_rev_tables[s[0]] << 12) | (base64_rev_tables[s[1]] << 6);
*bp++ = val >> 10;
if (srclen == 2) {
if (val & 0x800003ff)
return -1;
*bp++ = val >> 10;
} else {
val |= base64_rev_tables[s[2]];
if (val & 0x80000003)
return -1;
*bp++ = val >> 10;
*bp++ = val >> 2;
}
return bp - dst;

View File

@@ -1,41 +1,41 @@
// SPDX-License-Identifier: GPL-2.0
/*
Generic support for BUG()
This respects the following config options:
CONFIG_BUG - emit BUG traps. Nothing happens without this.
CONFIG_GENERIC_BUG - enable this code.
CONFIG_GENERIC_BUG_RELATIVE_POINTERS - use 32-bit relative pointers for bug_addr and file
CONFIG_DEBUG_BUGVERBOSE - emit full file+line information for each BUG
CONFIG_BUG and CONFIG_DEBUG_BUGVERBOSE are potentially user-settable
(though they're generally always on).
CONFIG_GENERIC_BUG is set by each architecture using this code.
To use this, your architecture must:
1. Set up the config options:
- Enable CONFIG_GENERIC_BUG if CONFIG_BUG
2. Implement BUG (and optionally BUG_ON, WARN, WARN_ON)
- Define HAVE_ARCH_BUG
- Implement BUG() to generate a faulting instruction
- NOTE: struct bug_entry does not have "file" or "line" entries
when CONFIG_DEBUG_BUGVERBOSE is not enabled, so you must generate
the values accordingly.
3. Implement the trap
- In the illegal instruction trap handler (typically), verify
that the fault was in kernel mode, and call report_bug()
- report_bug() will return whether it was a false alarm, a warning,
or an actual bug.
- You must implement the is_valid_bugaddr(bugaddr) callback which
returns true if the eip is a real kernel address, and it points
to the expected BUG trap instruction.
Jeremy Fitzhardinge <jeremy@goop.org> 2006
* Generic support for BUG()
*
* This respects the following config options:
*
* CONFIG_BUG - emit BUG traps. Nothing happens without this.
* CONFIG_GENERIC_BUG - enable this code.
* CONFIG_GENERIC_BUG_RELATIVE_POINTERS - use 32-bit relative pointers for bug_addr and file
* CONFIG_DEBUG_BUGVERBOSE - emit full file+line information for each BUG
*
* CONFIG_BUG and CONFIG_DEBUG_BUGVERBOSE are potentially user-settable
* (though they're generally always on).
*
* CONFIG_GENERIC_BUG is set by each architecture using this code.
*
* To use this, your architecture must:
*
* 1. Set up the config options:
* - Enable CONFIG_GENERIC_BUG if CONFIG_BUG
*
* 2. Implement BUG (and optionally BUG_ON, WARN, WARN_ON)
* - Define HAVE_ARCH_BUG
* - Implement BUG() to generate a faulting instruction
* - NOTE: struct bug_entry does not have "file" or "line" entries
* when CONFIG_DEBUG_BUGVERBOSE is not enabled, so you must generate
* the values accordingly.
*
* 3. Implement the trap
* - In the illegal instruction trap handler (typically), verify
* that the fault was in kernel mode, and call report_bug()
* - report_bug() will return whether it was a false alarm, a warning,
* or an actual bug.
* - You must implement the is_valid_bugaddr(bugaddr) callback which
* returns true if the eip is a real kernel address, and it points
* to the expected BUG trap instruction.
*
* Jeremy Fitzhardinge <jeremy@goop.org> 2006
*/
#define pr_fmt(fmt) fmt
@@ -72,7 +72,7 @@ static struct bug_entry *module_find_bug(unsigned long bugaddr)
guard(rcu)();
list_for_each_entry_rcu(mod, &module_bug_list, bug_list) {
unsigned i;
unsigned int i;
bug = mod->bug_table;
for (i = 0; i < mod->num_bugs; ++i, ++bug)
@@ -192,14 +192,14 @@ void __warn_printf(const char *fmt, struct pt_regs *regs)
}
#endif
printk("%s", fmt);
pr_warn("%s", fmt);
}
static enum bug_trap_type __report_bug(struct bug_entry *bug, unsigned long bugaddr, struct pt_regs *regs)
{
bool warning, once, done, no_cut, has_args;
const char *file, *fmt;
unsigned line;
unsigned int line;
if (!bug) {
if (!is_valid_bugaddr(bugaddr))
@@ -247,7 +247,7 @@ static enum bug_trap_type __report_bug(struct bug_entry *bug, unsigned long buga
* extra debugging message it writes before triggering the handler.
*/
if (!no_cut) {
printk(KERN_DEFAULT CUT_HERE);
pr_info(CUT_HERE);
__warn_printf(fmt, has_args ? regs : NULL);
}

View File

@@ -43,7 +43,7 @@ static int get_range(char **str, int *pint, int n)
* When @pint is NULL the function can be used as a validator of
* the current option in the string.
*
* Return values:
* Return:
* 0 - no int in string
* 1 - int found, no subsequent comma
* 2 - int found including a subsequent comma
@@ -145,44 +145,54 @@ EXPORT_SYMBOL(get_options);
*
* Parses a string into a number. The number stored at @ptr is
* potentially suffixed with K, M, G, T, P, E.
*
* Return: The value as recognized by simple_strtoull() multiplied
* by the value as specified by suffix, if any.
*/
unsigned long long memparse(const char *ptr, char **retptr)
{
char *endptr; /* local pointer to end of parsed string */
unsigned long long ret = simple_strtoull(ptr, &endptr, 0);
unsigned int shl = 0;
/* Consume valid suffix even in case of overflow. */
switch (*endptr) {
case 'E':
case 'e':
ret <<= 10;
shl += 10;
fallthrough;
case 'P':
case 'p':
ret <<= 10;
shl += 10;
fallthrough;
case 'T':
case 't':
ret <<= 10;
shl += 10;
fallthrough;
case 'G':
case 'g':
ret <<= 10;
shl += 10;
fallthrough;
case 'M':
case 'm':
ret <<= 10;
shl += 10;
fallthrough;
case 'K':
case 'k':
ret <<= 10;
endptr++;
shl += 10;
fallthrough;
default:
break;
}
if (shl && likely(ptr != endptr)) {
/* Have valid suffix with preceding number. */
if (unlikely(check_shl_overflow(ret, shl, &ret)))
ret = ULLONG_MAX;
endptr++;
}
if (retptr)
*retptr = endptr;
@@ -198,7 +208,7 @@ EXPORT_SYMBOL(memparse);
* This function parses a string containing a comma-separated list of
* strings like a=b,c.
*
* Return true if there's such option in the string, or return false.
* Return: True if there's such option in the string or false otherwise.
*/
bool parse_option_str(const char *str, const char *option)
{

View File

@@ -219,9 +219,9 @@ static int __init ei_debugfs_init(void)
dir = debugfs_create_dir("error_injection", NULL);
file = debugfs_create_file("list", 0444, dir, NULL, &ei_fops);
if (!file) {
if (IS_ERR(file)) {
debugfs_remove(dir);
return -ENOMEM;
return PTR_ERR(file);
}
return 0;

View File

@@ -4,6 +4,7 @@
#include <linux/interval_tree.h>
#include <linux/prandom.h>
#include <linux/slab.h>
#include <linux/printk.h>
#include <asm/timex.h>
#include <linux/bitmap.h>
#include <linux/maple_tree.h>
@@ -311,6 +312,27 @@ static inline int span_iteration_check(void) {return 0; }
static int interval_tree_test_init(void)
{
if (nnodes <= 0) {
pr_warn("nnodes must be positive\n");
return -EINVAL;
}
if (nsearches <= 0) {
pr_warn("nsearches must be positive\n");
return -EINVAL;
}
if (perf_loops <= 0) {
pr_warn("perf_loops must be positive\n");
return -EINVAL;
}
if (search_loops <= 0) {
pr_warn("search_loops must be positive\n");
return -EINVAL;
}
if (max_endpoint < 2) {
pr_warn("max_endpoint must be at least 2\n");
return -EINVAL;
}
nodes = kmalloc_objs(struct interval_tree_node, nnodes);
if (!nodes)
return -ENOMEM;

View File

@@ -39,25 +39,30 @@ const char *_parse_integer_fixup_radix(const char *s, unsigned int *base)
return s;
}
/*
* Convert non-negative integer string representation in explicitly given radix
* to an integer. A maximum of max_chars characters will be converted.
/**
* _parse_integer_limit - Convert integer string representation to an integer
* @s: Integer string representation
* @base: Radix
* @p: Where to store result
* @max_chars: Maximum amount of characters to convert
*
* Return number of characters consumed maybe or-ed with overflow bit.
* If overflow occurs, result integer (incorrect) is still returned.
* Convert non-negative integer string representation in explicitly given
* radix to an integer. If overflow occurs, value at @p is set to ULLONG_MAX.
*
* Don't you dare use this function.
* This function is the workhorse of other string conversion functions and it
* is discouraged to use it explicitly. Consider kstrto*() family instead.
*
* Return: Number of characters consumed, maybe ORed with overflow bit
*/
noinline
unsigned int _parse_integer_limit(const char *s, unsigned int base, unsigned long long *p,
size_t max_chars)
{
unsigned int rv, overflow = 0;
unsigned long long res;
unsigned int rv;
res = 0;
rv = 0;
while (max_chars--) {
for (rv = 0; rv < max_chars; rv++, s++) {
unsigned int c = *s;
unsigned int lc = _tolower(c);
unsigned int val;
@@ -76,15 +81,17 @@ unsigned int _parse_integer_limit(const char *s, unsigned int base, unsigned lon
* it in the max base we support (16)
*/
if (unlikely(res & (~0ull << 60))) {
if (res > div_u64(ULLONG_MAX - val, base))
rv |= KSTRTOX_OVERFLOW;
if (check_mul_overflow(res, base, &res) ||
check_add_overflow(res, val, &res)) {
res = ULLONG_MAX;
overflow = KSTRTOX_OVERFLOW;
}
} else {
res = res * base + val;
}
res = res * base + val;
rv++;
s++;
}
*p = res;
return rv;
return rv | overflow;
}
noinline

View File

@@ -16,6 +16,7 @@
#include <linux/cpumask.h>
#include <linux/delay.h>
#include <linux/kprobes.h>
#include <linux/stringify.h>
#include <linux/nmi.h>
#include <linux/cpu.h>
#include <linux/sched/debug.h>
@@ -27,6 +28,8 @@ static DECLARE_BITMAP(backtrace_mask, NR_CPUS) __read_mostly;
/* "in progress" flag of arch_trigger_cpumask_backtrace */
static unsigned long backtrace_flag;
#define NMI_BT_TIMEOUT_SEC 10
/*
* When raise() is called it will be passed a pointer to the
* backtrace_mask. Architectures that call nmi_cpu_backtrace()
@@ -68,14 +71,20 @@ void nmi_trigger_cpumask_backtrace(const cpumask_t *mask,
raise(to_cpumask(backtrace_mask));
}
/* Wait for up to 10 seconds for all CPUs to do the backtrace */
for (i = 0; i < 10 * 1000; i++) {
/* Wait for up to NMI_BT_TIMEOUT_SEC seconds for all CPUs to do the backtrace */
for (i = 0; i < NMI_BT_TIMEOUT_SEC * 1000; i++) {
if (cpumask_empty(to_cpumask(backtrace_mask)))
break;
mdelay(1);
touch_softlockup_watchdog();
}
nmi_backtrace_stall_check(to_cpumask(backtrace_mask));
if (!cpumask_empty(to_cpumask(backtrace_mask))) {
pr_warn("After " __stringify(NMI_BT_TIMEOUT_SEC) " seconds, these CPUS still haven't responded to the NMI: %*pbl\n",
cpumask_pr_args(to_cpumask(backtrace_mask)));
nmi_backtrace_stall_check(to_cpumask(backtrace_mask));
}
/*
* Force flush any remote buffers that might be stuck in IRQ context

Some files were not shown because too many files have changed in this diff Show More