提交 676cb495 编写于 作者: L Linus Torvalds

Merge tag 'mm-nonmm-stable-2022-10-11' of git://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm

Pull non-MM updates from Andrew Morton:

 - hfs and hfsplus kmap API modernization (Fabio Francesco)

 - make crash-kexec work properly when invoked from an NMI-time panic
   (Valentin Schneider)

 - ntfs bugfixes (Hawkins Jiawei)

 - improve IPC msg scalability by replacing atomic_t's with percpu
   counters (Jiebin Sun)

 - nilfs2 cleanups (Minghao Chi)

 - lots of other single patches all over the tree!

* tag 'mm-nonmm-stable-2022-10-11' of git://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm: (71 commits)
  include/linux/entry-common.h: remove has_signal comment of arch_do_signal_or_restart() prototype
  proc: test how it holds up with mapping'less process
  mailmap: update Frank Rowand email address
  ia64: mca: use strscpy() is more robust and safer
  init/Kconfig: fix unmet direct dependencies
  ia64: update config files
  nilfs2: replace WARN_ONs by nilfs_error for checkpoint acquisition failure
  fork: remove duplicate included header files
  init/main.c: remove unnecessary (void*) conversions
  proc: mark more files as permanent
  nilfs2: remove the unneeded result variable
  nilfs2: delete unnecessary checks before brelse()
  checkpatch: warn for non-standard fixes tag style
  usr/gen_init_cpio.c: remove unnecessary -1 values from int file
  ipc/msg: mitigate the lock contention with percpu counter
  percpu: add percpu_counter_add_local and percpu_counter_sub_local
  fs/ocfs2: fix repeated words in comments
  relay: use kvcalloc to alloc page array in relay_alloc_page_array
  proc: make config PROC_CHILDREN depend on PROC_FS
  fs: uninline inode_maybe_inc_iversion()
  ...
......@@ -137,6 +137,7 @@ Filipe Lautert <filipe@icewall.org>
Finn Thain <fthain@linux-m68k.org> <fthain@telegraphics.com.au>
Franck Bui-Huu <vagabon.xyz@gmail.com>
Frank Rowand <frowand.list@gmail.com> <frank.rowand@am.sony.com>
Frank Rowand <frowand.list@gmail.com> <frank.rowand@sony.com>
Frank Rowand <frowand.list@gmail.com> <frank.rowand@sonymobile.com>
Frank Rowand <frowand.list@gmail.com> <frowand@mvista.com>
Frank Zago <fzago@systemfabricworks.com>
......
......@@ -65,6 +65,11 @@ combining the following values:
4 s3_beep
= =======
arch
====
The machine hardware name, the same output as ``uname -m``
(e.g. ``x86_64`` or ``aarch64``).
auto_msgmni
===========
......
......@@ -612,6 +612,13 @@ Commit message
See: https://www.kernel.org/doc/html/latest/process/submitting-patches.html#describe-your-changes
**BAD_FIXES_TAG**
The Fixes: tag is malformed or does not follow the community conventions.
This can occur if the tag have been split into multiple lines (e.g., when
pasted in an email program with word wrapping enabled).
See: https://www.kernel.org/doc/html/latest/process/submitting-patches.html#describe-your-changes
Comparison style
----------------
......
......@@ -65,7 +65,7 @@ CONFIG_NFSD=m
CONFIG_NLS_CODEPAGE_437=y
CONFIG_MAGIC_SYSRQ=y
CONFIG_DEBUG_KERNEL=y
CONFIG_DEBUG_INFO=y
CONFIG_DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT=y
CONFIG_ALPHA_LEGACY_START_ADDRESS=y
CONFIG_MATHEMU=y
CONFIG_CRYPTO_HMAC=y
......
......@@ -36,8 +36,6 @@ extern void start_thread(struct pt_regs *, unsigned long, unsigned long);
/* Free all resources held by a thread. */
struct task_struct;
extern void release_thread(struct task_struct *);
unsigned long __get_wchan(struct task_struct *p);
#define KSTK_EIP(tsk) (task_pt_regs(tsk)->pc)
......
......@@ -225,11 +225,6 @@ flush_thread(void)
current_thread_info()->pcb.unique = 0;
}
void
release_thread(struct task_struct *dead_task)
{
}
/*
* Copy architecture-specific thread state
*/
......
......@@ -491,9 +491,9 @@ setup_arch(char **cmdline_p)
boot flags depending on the boot mode, we need some shorthand.
This should do for installation. */
if (strcmp(COMMAND_LINE, "INSTALL") == 0) {
strlcpy(command_line, "root=/dev/fd0 load_ramdisk=1", sizeof command_line);
strscpy(command_line, "root=/dev/fd0 load_ramdisk=1", sizeof(command_line));
} else {
strlcpy(command_line, COMMAND_LINE, sizeof command_line);
strscpy(command_line, COMMAND_LINE, sizeof(command_line));
}
strcpy(boot_command_line, command_line);
*cmdline_p = command_line;
......
......@@ -90,7 +90,7 @@ CONFIG_TMPFS=y
CONFIG_CONFIGFS_FS=y
# CONFIG_MISC_FILESYSTEMS is not set
# CONFIG_NETWORK_FILESYSTEMS is not set
CONFIG_DEBUG_INFO=y
CONFIG_DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT=y
CONFIG_STRIP_ASM_SYMS=y
CONFIG_DEBUG_FS=y
CONFIG_HEADERS_INSTALL=y
......
......@@ -43,9 +43,6 @@ struct task_struct;
#define task_pt_regs(p) \
((struct pt_regs *)(THREAD_SIZE + (void *)task_stack_page(p)) - 1)
/* Free all resources held by a thread */
#define release_thread(thread) do { } while (0)
/*
* A lot of busy-wait loops in SMP are based off of non-volatile data otherwise
* get optimised away by gcc
......
......@@ -81,9 +81,6 @@ static inline void arch_thread_struct_whitelist(unsigned long *offset,
/* Forward declaration, a strange C thing */
struct task_struct;
/* Free all resources held by a thread. */
extern void release_thread(struct task_struct *);
unsigned long __get_wchan(struct task_struct *p);
#define task_pt_regs(p) \
......
......@@ -232,10 +232,6 @@ void flush_thread(void)
thread_notify(THREAD_NOTIFY_FLUSH, thread);
}
void release_thread(struct task_struct *dead_task)
{
}
asmlinkage void ret_from_fork(void) __asm__("ret_from_fork");
int copy_thread(struct task_struct *p, const struct kernel_clone_args *args)
......
......@@ -323,9 +323,6 @@ static inline bool is_ttbr1_addr(unsigned long addr)
/* Forward declaration, a strange C thing */
struct task_struct;
/* Free all resources held by a thread. */
extern void release_thread(struct task_struct *);
unsigned long __get_wchan(struct task_struct *p);
void update_sctlr_el1(u64 sctlr);
......
......@@ -279,10 +279,6 @@ void flush_thread(void)
flush_tagged_addr_state();
}
void release_thread(struct task_struct *dead_task)
{
}
void arch_release_task_struct(struct task_struct *tsk)
{
fpsimd_release_task(tsk);
......
......@@ -69,11 +69,6 @@ do { \
/* Forward declaration, a strange C thing */
struct task_struct;
/* Free all resources held by a thread. */
static inline void release_thread(struct task_struct *dead_task)
{
}
/* Prepare to copy thread state - unlazy all lazy status */
#define prepare_to_copy(tsk) do { } while (0)
......
......@@ -60,10 +60,6 @@ struct thread_struct {
#define KSTK_EIP(tsk) (pt_elr(task_pt_regs(tsk)))
#define KSTK_ESP(tsk) (pt_psp(task_pt_regs(tsk)))
/* Free all resources held by a thread; defined in process.c */
extern void release_thread(struct task_struct *dead_task);
/* Get wait channel for task P. */
extern unsigned long __get_wchan(struct task_struct *p);
/* The following stuff is pretty HEXAGON specific. */
......
......@@ -112,13 +112,6 @@ int copy_thread(struct task_struct *p, const struct kernel_clone_args *args)
return 0;
}
/*
* Release any architecture-specific resources locked by thread
*/
void release_thread(struct task_struct *dead_task)
{
}
/*
* Some archs flush debug and FPU info here
*/
......
......@@ -20,7 +20,6 @@ CONFIG_UNIX=y
CONFIG_INET=y
# CONFIG_IPV6 is not set
CONFIG_BLK_DEV_LOOP=m
CONFIG_BLK_DEV_CRYPTOLOOP=m
CONFIG_BLK_DEV_NBD=m
CONFIG_BLK_DEV_RAM=m
CONFIG_ATA=m
......@@ -91,7 +90,6 @@ CONFIG_NFS_V4=m
CONFIG_NFSD=m
CONFIG_NFSD_V4=y
CONFIG_CIFS=m
CONFIG_CIFS_STATS=y
CONFIG_CIFS_XATTR=y
CONFIG_CIFS_POSIX=y
CONFIG_NLS_CODEPAGE_437=y
......
......@@ -39,7 +39,6 @@ CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
CONFIG_CONNECTOR=y
# CONFIG_PNP_DEBUG_MESSAGES is not set
CONFIG_BLK_DEV_LOOP=m
CONFIG_BLK_DEV_CRYPTOLOOP=m
CONFIG_BLK_DEV_NBD=m
CONFIG_BLK_DEV_RAM=y
CONFIG_SGI_XP=m
......@@ -91,7 +90,6 @@ CONFIG_SERIAL_8250_SHARE_IRQ=y
# CONFIG_HW_RANDOM is not set
CONFIG_RTC_CLASS=y
CONFIG_RTC_DRV_EFI=y
CONFIG_RAW_DRIVER=m
CONFIG_HPET=y
CONFIG_AGP=m
CONFIG_AGP_I460=m
......
......@@ -31,11 +31,9 @@ CONFIG_IP_MULTICAST=y
CONFIG_SYN_COOKIES=y
# CONFIG_IPV6 is not set
CONFIG_BLK_DEV_LOOP=m
CONFIG_BLK_DEV_CRYPTOLOOP=m
CONFIG_BLK_DEV_NBD=m
CONFIG_BLK_DEV_RAM=y
CONFIG_ATA=y
CONFIG_BLK_DEV_IDECD=y
CONFIG_ATA_GENERIC=y
CONFIG_PATA_CMD64X=y
CONFIG_ATA_PIIX=y
......@@ -81,7 +79,6 @@ CONFIG_SERIAL_8250_SHARE_IRQ=y
# CONFIG_HW_RANDOM is not set
CONFIG_RTC_CLASS=y
CONFIG_RTC_DRV_EFI=y
CONFIG_RAW_DRIVER=m
CONFIG_HPET=y
CONFIG_AGP=m
CONFIG_AGP_I460=m
......
......@@ -36,7 +36,6 @@ CONFIG_IP_MULTICAST=y
CONFIG_SYN_COOKIES=y
# CONFIG_IPV6 is not set
CONFIG_BLK_DEV_LOOP=m
CONFIG_BLK_DEV_CRYPTOLOOP=m
CONFIG_BLK_DEV_NBD=m
CONFIG_BLK_DEV_RAM=y
CONFIG_ATA=y
......@@ -85,7 +84,6 @@ CONFIG_SERIAL_8250_SHARE_IRQ=y
# CONFIG_HW_RANDOM is not set
CONFIG_RTC_CLASS=y
CONFIG_RTC_DRV_EFI=y
CONFIG_RAW_DRIVER=m
CONFIG_HPET=y
CONFIG_AGP=m
CONFIG_AGP_I460=m
......
......@@ -30,7 +30,6 @@ CONFIG_PATA_CMD64X=y
CONFIG_SCSI=y
CONFIG_BLK_DEV_SD=y
CONFIG_CHR_DEV_ST=y
CONFIG_CHR_DEV_OSST=y
CONFIG_BLK_DEV_SR=y
CONFIG_CHR_DEV_SG=y
CONFIG_SCSI_CONSTANTS=y
......
......@@ -318,13 +318,6 @@ struct thread_struct {
struct mm_struct;
struct task_struct;
/*
* Free all resources held by a thread. This is called after the
* parent of DEAD_TASK has collected the exit status of the task via
* wait().
*/
#define release_thread(dead_task)
/* Get wait channel for task P. */
extern unsigned long __get_wchan (struct task_struct *p);
......
......@@ -1793,7 +1793,7 @@ format_mca_init_stack(void *mca_data, unsigned long offset,
p->parent = p->real_parent = p->group_leader = p;
INIT_LIST_HEAD(&p->children);
INIT_LIST_HEAD(&p->sibling);
strncpy(p->comm, type, sizeof(p->comm)-1);
strscpy(p->comm, type, sizeof(p->comm)-1);
}
/* Caller prevents this from being called after init */
......
......@@ -552,7 +552,7 @@ setup_arch (char **cmdline_p)
ia64_patch_vtop((u64) __start___vtop_patchlist, (u64) __end___vtop_patchlist);
*cmdline_p = __va(ia64_boot_param->command_line);
strlcpy(boot_command_line, *cmdline_p, COMMAND_LINE_SIZE);
strscpy(boot_command_line, *cmdline_p, COMMAND_LINE_SIZE);
efi_init();
io_port_init();
......
......@@ -166,3 +166,29 @@ ia64_mremap (unsigned long addr, unsigned long old_len, unsigned long new_len, u
force_successful_syscall_return();
return addr;
}
asmlinkage long
ia64_clock_getres(const clockid_t which_clock, struct __kernel_timespec __user *tp)
{
/*
* ia64's clock_gettime() syscall is implemented as a vdso call
* fsys_clock_gettime(). Currently it handles only
* CLOCK_REALTIME and CLOCK_MONOTONIC. Both are based on
* 'ar.itc' counter which gets incremented at a constant
* frequency. It's usually 400MHz, ~2.5x times slower than CPU
* clock frequency. Which is almost a 1ns hrtimer, but not quite.
*
* Let's special-case these timers to report correct precision
* based on ITC frequency and not HZ frequency for supported
* clocks.
*/
switch (which_clock) {
case CLOCK_REALTIME:
case CLOCK_MONOTONIC:
s64 tick_ns = DIV_ROUND_UP(NSEC_PER_SEC, local_cpu_data->itc_freq);
struct timespec64 rtn_tp = ns_to_timespec64(tick_ns);
return put_timespec64(&rtn_tp, tp);
}
return sys_clock_getres(which_clock, tp);
}
......@@ -240,7 +240,7 @@
228 common timer_delete sys_timer_delete
229 common clock_settime sys_clock_settime
230 common clock_gettime sys_clock_gettime
231 common clock_getres sys_clock_getres
231 common clock_getres ia64_clock_getres
232 common clock_nanosleep sys_clock_nanosleep
233 common fstatfs64 sys_fstatfs64
234 common statfs64 sys_statfs64
......
......@@ -176,9 +176,6 @@ struct thread_struct {
struct task_struct;
/* Free all resources held by a thread. */
#define release_thread(thread) do { } while (0)
enum idle_boot_override {IDLE_NO_OVERRIDE = 0, IDLE_HALT, IDLE_NOMWAIT, IDLE_POLL};
extern unsigned long boot_option_idle_override;
......
......@@ -145,11 +145,6 @@ static inline void start_thread(struct pt_regs * regs, unsigned long pc,
/* Forward declaration, a strange C thing */
struct task_struct;
/* Free all resources held by a thread. */
static inline void release_thread(struct task_struct *dead_task)
{
}
unsigned long __get_wchan(struct task_struct *p);
void show_registers(struct pt_regs *regs);
......
......@@ -83,7 +83,7 @@ CONFIG_CIFS=y
CONFIG_CIFS_STATS2=y
CONFIG_ENCRYPTED_KEYS=y
CONFIG_DMA_CMA=y
CONFIG_DEBUG_INFO=y
CONFIG_DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT=y
CONFIG_KGDB=y
CONFIG_KGDB_TESTS=y
CONFIG_KGDB_KDB=y
......
......@@ -63,11 +63,6 @@ struct thread_struct {
.pgdir = swapper_pg_dir, \
}
/* Free all resources held by a thread. */
static inline void release_thread(struct task_struct *dead_task)
{
}
unsigned long __get_wchan(struct task_struct *p);
/* The size allocated for kernel stacks. This _must_ be a power of two! */
......
......@@ -72,7 +72,7 @@ CONFIG_LEDS_TRIGGER_TIMER=y
CONFIG_LEDS_TRIGGER_DEFAULT_ON=y
CONFIG_CRC32_SARWATE=y
CONFIG_PRINTK_TIME=y
CONFIG_DEBUG_INFO=y
CONFIG_DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT=y
CONFIG_DEBUG_INFO_REDUCED=y
CONFIG_STRIP_ASM_SYMS=y
CONFIG_DEBUG_FS=y
......
......@@ -161,7 +161,7 @@ CONFIG_CRYPTO_SHA1_OCTEON=m
CONFIG_CRYPTO_SHA256_OCTEON=m
CONFIG_CRYPTO_SHA512_OCTEON=m
CONFIG_CRYPTO_DES=y
CONFIG_DEBUG_INFO=y
CONFIG_DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT=y
CONFIG_DEBUG_FS=y
CONFIG_MAGIC_SYSRQ=y
# CONFIG_SCHED_DEBUG is not set
......@@ -199,7 +199,7 @@ CONFIG_NLS_UTF8=y
CONFIG_DMA_CMA=y
CONFIG_CMA_SIZE_MBYTES=32
CONFIG_PRINTK_TIME=y
CONFIG_DEBUG_INFO=y
CONFIG_DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT=y
CONFIG_STRIP_ASM_SYMS=y
CONFIG_MAGIC_SYSRQ=y
CONFIG_DEBUG_FS=y
......
......@@ -113,7 +113,7 @@ CONFIG_PRINTK_TIME=y
CONFIG_CONSOLE_LOGLEVEL_DEFAULT=15
CONFIG_CONSOLE_LOGLEVEL_QUIET=15
CONFIG_MESSAGE_LOGLEVEL_DEFAULT=7
CONFIG_DEBUG_INFO=y
CONFIG_DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT=y
CONFIG_STRIP_ASM_SYMS=y
CONFIG_MAGIC_SYSRQ=y
CONFIG_DEBUG_FS=y
......
......@@ -116,7 +116,7 @@ CONFIG_PRINTK_TIME=y
CONFIG_CONSOLE_LOGLEVEL_DEFAULT=15
CONFIG_CONSOLE_LOGLEVEL_QUIET=15
CONFIG_MESSAGE_LOGLEVEL_DEFAULT=7
CONFIG_DEBUG_INFO=y
CONFIG_DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT=y
CONFIG_STRIP_ASM_SYMS=y
CONFIG_MAGIC_SYSRQ=y
CONFIG_DEBUG_FS=y
......
......@@ -82,7 +82,7 @@ CONFIG_ROOT_NFS=y
# CONFIG_XZ_DEC_ARMTHUMB is not set
# CONFIG_XZ_DEC_SPARC is not set
CONFIG_PRINTK_TIME=y
CONFIG_DEBUG_INFO=y
CONFIG_DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT=y
CONFIG_DEBUG_INFO_REDUCED=y
CONFIG_DEBUG_FS=y
# CONFIG_SCHED_DEBUG is not set
......
......@@ -113,7 +113,7 @@ CONFIG_CRYPTO_LZO=y
CONFIG_CRC16=y
CONFIG_XZ_DEC=y
CONFIG_PRINTK_TIME=y
CONFIG_DEBUG_INFO=y
CONFIG_DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT=y
CONFIG_STRIP_ASM_SYMS=y
CONFIG_DEBUG_FS=y
CONFIG_MAGIC_SYSRQ=y
......
......@@ -166,7 +166,7 @@ CONFIG_NLS_UTF8=y
CONFIG_FONTS=y
CONFIG_FONT_SUN8x16=y
CONFIG_PRINTK_TIME=y
CONFIG_DEBUG_INFO=y
CONFIG_DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT=y
CONFIG_STRIP_ASM_SYMS=y
CONFIG_READABLE_ASM=y
CONFIG_KGDB=y
......
......@@ -113,7 +113,7 @@ CONFIG_CRYPTO_LZO=y
CONFIG_CRC16=y
CONFIG_XZ_DEC=y
CONFIG_PRINTK_TIME=y
CONFIG_DEBUG_INFO=y
CONFIG_DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT=y
CONFIG_STRIP_ASM_SYMS=y
CONFIG_DEBUG_FS=y
CONFIG_MAGIC_SYSRQ=y
......
......@@ -344,9 +344,6 @@ struct thread_struct {
struct task_struct;
/* Free all resources held by a thread. */
#define release_thread(thread) do { } while(0)
/*
* Do necessary setup to start up a newly executed thread.
*/
......
......@@ -74,4 +74,4 @@ CONFIG_NFS_FS=y
CONFIG_NFS_V3_ACL=y
CONFIG_ROOT_NFS=y
CONFIG_SUNRPC_DEBUG=y
CONFIG_DEBUG_INFO=y
CONFIG_DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT=y
......@@ -71,4 +71,4 @@ CONFIG_NFS_FS=y
CONFIG_NFS_V3_ACL=y
CONFIG_ROOT_NFS=y
CONFIG_SUNRPC_DEBUG=y
CONFIG_DEBUG_INFO=y
CONFIG_DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT=y
......@@ -64,11 +64,6 @@ extern void start_thread(struct pt_regs *regs, unsigned long pc,
struct task_struct;
/* Free all resources held by a thread. */
static inline void release_thread(struct task_struct *dead_task)
{
}
extern unsigned long __get_wchan(struct task_struct *p);
#define task_pt_regs(p) \
......
......@@ -72,7 +72,6 @@ struct thread_struct {
void start_thread(struct pt_regs *regs, unsigned long nip, unsigned long sp);
void release_thread(struct task_struct *);
unsigned long __get_wchan(struct task_struct *p);
#define cpu_relax() barrier()
......
......@@ -125,10 +125,6 @@ void show_regs(struct pt_regs *regs)
show_registers(regs);
}
void release_thread(struct task_struct *dead_task)
{
}
/*
* Copy the thread-specific (arch specific) info from the current
* process to the new one p
......
......@@ -266,9 +266,6 @@ on downward growing arches, it looks like this:
struct mm_struct;
/* Free all resources held by a thread. */
extern void release_thread(struct task_struct *);
extern unsigned long __get_wchan(struct task_struct *p);
#define KSTK_EIP(tsk) ((tsk)->thread.regs.iaoq[0])
......
......@@ -146,10 +146,6 @@ void flush_thread(void)
*/
}
void release_thread(struct task_struct *dead_task)
{
}
/*
* Idle thread support
*
......
......@@ -75,7 +75,6 @@ extern int _chrp_type;
struct task_struct;
void start_thread(struct pt_regs *regs, unsigned long fdptr, unsigned long sp);
void release_thread(struct task_struct *);
#define TS_FPR(i) fp_state.fpr[i][TS_FPROFFSET]
#define TS_CKFPR(i) ckfp_state.fpr[i][TS_FPROFFSET]
......
......@@ -1655,11 +1655,6 @@ EXPORT_SYMBOL_GPL(set_thread_tidr);
#endif /* CONFIG_PPC64 */
void
release_thread(struct task_struct *t)
{
}
/*
* this gets called so that we can store coprocessor state into memory and
* copy the current task into the new thread.
......
......@@ -65,11 +65,6 @@ static inline void arch_thread_struct_whitelist(unsigned long *offset,
extern void start_thread(struct pt_regs *regs,
unsigned long pc, unsigned long sp);
/* Free all resources held by a thread. */
static inline void release_thread(struct task_struct *dead_task)
{
}
extern unsigned long __get_wchan(struct task_struct *p);
......
......@@ -186,9 +186,6 @@ struct pt_regs;
void show_registers(struct pt_regs *regs);
void show_cacheinfo(struct seq_file *m);
/* Free all resources held by a thread. */
static inline void release_thread(struct task_struct *tsk) { }
/* Free guarded storage control block */
void guarded_storage_release(struct task_struct *tsk);
void gs_load_bc_cb(struct pt_regs *regs);
......
......@@ -85,7 +85,7 @@ CONFIG_DEBUG_FS=y
CONFIG_DEBUG_KERNEL=y
# CONFIG_DEBUG_PREEMPT is not set
# CONFIG_DEBUG_BUGVERBOSE is not set
CONFIG_DEBUG_INFO=y
CONFIG_DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT=y
# CONFIG_FTRACE is not set
# CONFIG_CRYPTO_ANSI_CPRNG is not set
# CONFIG_CRYPTO_HW is not set
......@@ -116,7 +116,7 @@ CONFIG_MAGIC_SYSRQ=y
CONFIG_DEBUG_KERNEL=y
CONFIG_DEBUG_SHIRQ=y
CONFIG_DETECT_HUNG_TASK=y
CONFIG_DEBUG_INFO=y
CONFIG_DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT=y
CONFIG_DEBUG_VM=y
CONFIG_DWARF_UNWINDER=y
# CONFIG_CRYPTO_ANSI_CPRNG is not set
......@@ -107,7 +107,7 @@ CONFIG_DEBUG_SHIRQ=y
CONFIG_DETECT_HUNG_TASK=y
# CONFIG_SCHED_DEBUG is not set
CONFIG_TIMER_STATS=y
CONFIG_DEBUG_INFO=y
CONFIG_DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT=y
CONFIG_CRYPTO=y
CONFIG_CRYPTO_MD5=y
CONFIG_CRYPTO_DES=y
......
......@@ -84,7 +84,7 @@ CONFIG_MAGIC_SYSRQ=y
CONFIG_DEBUG_KERNEL=y
# CONFIG_SCHED_DEBUG is not set
CONFIG_DEBUG_KOBJECT=y
CONFIG_DEBUG_INFO=y
CONFIG_DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT=y
CONFIG_FRAME_POINTER=y
CONFIG_CRC_CCITT=m
CONFIG_CRC16=m
......@@ -79,5 +79,5 @@ CONFIG_DETECT_HUNG_TASK=y
CONFIG_DEBUG_RT_MUTEXES=y
CONFIG_DEBUG_LOCK_ALLOC=y
CONFIG_DEBUG_SPINLOCK_SLEEP=y
CONFIG_DEBUG_INFO=y
CONFIG_DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT=y
CONFIG_DEBUG_SG=y
......@@ -101,7 +101,7 @@ CONFIG_DEBUG_FS=y
CONFIG_DEBUG_KERNEL=y
CONFIG_DETECT_HUNG_TASK=y
# CONFIG_DEBUG_PREEMPT is not set
CONFIG_DEBUG_INFO=y
CONFIG_DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT=y
CONFIG_CRYPTO_ECB=m
CONFIG_CRYPTO_PCBC=m
CONFIG_CRYPTO_HMAC=y
......
......@@ -96,7 +96,7 @@ CONFIG_DEBUG_KERNEL=y
# CONFIG_DEBUG_PREEMPT is not set
CONFIG_DEBUG_LOCK_ALLOC=y
CONFIG_DEBUG_LOCKING_API_SELFTESTS=y
CONFIG_DEBUG_INFO=y
CONFIG_DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT=y
CONFIG_SH_STANDARD_BIOS=y
CONFIG_DEBUG_STACK_USAGE=y
CONFIG_4KSTACKS=y
......
......@@ -112,7 +112,7 @@ CONFIG_DETECT_HUNG_TASK=y
CONFIG_DEBUG_OBJECTS=y
CONFIG_DEBUG_MUTEXES=y
CONFIG_DEBUG_SPINLOCK_SLEEP=y
CONFIG_DEBUG_INFO=y
CONFIG_DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT=y
CONFIG_DEBUG_VM=y
CONFIG_DEBUG_LIST=y
CONFIG_DEBUG_SG=y
......
......@@ -131,7 +131,7 @@ CONFIG_DEBUG_KERNEL=y
CONFIG_DETECT_HUNG_TASK=y
# CONFIG_SCHED_DEBUG is not set
CONFIG_TIMER_STATS=y
CONFIG_DEBUG_INFO=y
CONFIG_DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT=y
CONFIG_SH_STANDARD_BIOS=y
CONFIG_CRYPTO_MD5=y
CONFIG_CRYPTO_DES=y
......
......@@ -93,7 +93,7 @@ CONFIG_CRAMFS=y
CONFIG_NFS_FS=y
CONFIG_ROOT_NFS=y
CONFIG_DEBUG_KERNEL=y
CONFIG_DEBUG_INFO=y
CONFIG_DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT=y
CONFIG_FRAME_POINTER=y
CONFIG_CRYPTO_ECB=m
CONFIG_CRYPTO_PCBC=m
......
......@@ -121,7 +121,7 @@ CONFIG_NLS_CODEPAGE_437=y
CONFIG_NLS_CODEPAGE_932=y
CONFIG_NLS_ISO8859_1=y
CONFIG_DEBUG_KERNEL=y
CONFIG_DEBUG_INFO=y
CONFIG_DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT=y
CONFIG_FRAME_POINTER=y
# CONFIG_CRYPTO_ANSI_CPRNG is not set
CONFIG_CRC_CCITT=y
......@@ -159,7 +159,7 @@ CONFIG_DEBUG_FS=y
CONFIG_DEBUG_KERNEL=y
# CONFIG_DETECT_SOFTLOCKUP is not set
# CONFIG_SCHED_DEBUG is not set
CONFIG_DEBUG_INFO=y
CONFIG_DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT=y
CONFIG_FRAME_POINTER=y
CONFIG_SH_STANDARD_BIOS=y
CONFIG_CRYPTO_NULL=y
......
......@@ -80,6 +80,6 @@ CONFIG_NLS_ISO8859_1=y
CONFIG_DEBUG_KERNEL=y
# CONFIG_SCHED_DEBUG is not set
# CONFIG_DEBUG_BUGVERBOSE is not set
CONFIG_DEBUG_INFO=y
CONFIG_DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT=y
# CONFIG_FTRACE is not set
# CONFIG_CRYPTO_ANSI_CPRNG is not set
......@@ -141,7 +141,7 @@ CONFIG_DEBUG_KMEMLEAK=y
CONFIG_DEBUG_SPINLOCK=y
CONFIG_DEBUG_MUTEXES=y
CONFIG_DEBUG_SPINLOCK_SLEEP=y
CONFIG_DEBUG_INFO=y
CONFIG_DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT=y
CONFIG_LATENCYTOP=y
# CONFIG_FTRACE is not set
CONFIG_CRYPTO_HMAC=y
......
......@@ -138,7 +138,7 @@ CONFIG_PRINTK_TIME=y
CONFIG_DEBUG_FS=y
CONFIG_DEBUG_KERNEL=y
CONFIG_DETECT_HUNG_TASK=y
CONFIG_DEBUG_INFO=y
CONFIG_DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT=y
CONFIG_FRAME_POINTER=y
# CONFIG_FTRACE is not set
# CONFIG_DUMP_CODE is not set
......
......@@ -127,9 +127,6 @@ struct task_struct;
extern void start_thread(struct pt_regs *regs, unsigned long new_pc, unsigned long new_sp);
/* Free all resources held by a thread. */
extern void release_thread(struct task_struct *);
/*
* FPU lazy state save handling.
*/
......
......@@ -84,11 +84,6 @@ void flush_thread(void)
#endif
}
void release_thread(struct task_struct *dead_task)
{
/* do nothing */
}
asmlinkage void ret_from_fork(void);
asmlinkage void ret_from_kernel_thread(void);
......
......@@ -80,9 +80,6 @@ static inline void start_thread(struct pt_regs * regs, unsigned long pc,
: "memory");
}
/* Free all resources held by a thread. */
#define release_thread(tsk) do { } while(0)
unsigned long __get_wchan(struct task_struct *);
#define task_pt_regs(tsk) ((tsk)->thread.kregs)
......
......@@ -176,9 +176,6 @@ do { \
regs->tstate &= ~TSTATE_PEF; \
} while (0)
/* Free all resources held by a thread. */
#define release_thread(tsk) do { } while (0)
unsigned long __get_wchan(struct task_struct *task);
#define task_pt_regs(tsk) (task_thread_info(tsk)->kregs)
......
......@@ -69,5 +69,5 @@ CONFIG_JOLIET=y
CONFIG_PROC_KCORE=y
CONFIG_TMPFS=y
CONFIG_NLS=y
CONFIG_DEBUG_INFO=y
CONFIG_DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT=y
CONFIG_DEBUG_KERNEL=y
......@@ -67,6 +67,6 @@ CONFIG_JOLIET=y
CONFIG_PROC_KCORE=y
CONFIG_TMPFS=y
CONFIG_NLS=y
CONFIG_DEBUG_INFO=y
CONFIG_DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT=y
CONFIG_FRAME_WARN=1024
CONFIG_DEBUG_KERNEL=y
......@@ -55,10 +55,6 @@ struct thread_struct {
.request = { 0 } \
}
static inline void release_thread(struct task_struct *task)
{
}
/*
* User space process size: 3GB (default).
*/
......
......@@ -587,9 +587,6 @@ static inline void load_sp0(unsigned long sp0)
#endif /* CONFIG_PARAVIRT_XXL */
/* Free all resources held by a thread. */
extern void release_thread(struct task_struct *);
unsigned long __get_wchan(struct task_struct *p);
/*
......
......@@ -120,7 +120,7 @@ CONFIG_NLS_CODEPAGE_437=y
CONFIG_NLS_ISO8859_1=y
CONFIG_PRINTK_TIME=y
CONFIG_DYNAMIC_DEBUG=y
CONFIG_DEBUG_INFO=y
CONFIG_DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT=y
CONFIG_MAGIC_SYSRQ=y
CONFIG_LOCKUP_DETECTOR=y
# CONFIG_SCHED_DEBUG is not set
......
......@@ -100,7 +100,7 @@ CONFIG_NLS_CODEPAGE_437=y
CONFIG_NLS_ISO8859_1=y
CONFIG_PRINTK_TIME=y
CONFIG_DYNAMIC_DEBUG=y
CONFIG_DEBUG_INFO=y
CONFIG_DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT=y
CONFIG_MAGIC_SYSRQ=y
CONFIG_LOCKUP_DETECTOR=y
# CONFIG_SCHED_DEBUG is not set
......
......@@ -107,7 +107,7 @@ CONFIG_NLS_CODEPAGE_437=y
CONFIG_NLS_ISO8859_1=y
CONFIG_PRINTK_TIME=y
CONFIG_DYNAMIC_DEBUG=y
CONFIG_DEBUG_INFO=y
CONFIG_DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT=y
CONFIG_MAGIC_SYSRQ=y
CONFIG_LOCKUP_DETECTOR=y
# CONFIG_SCHED_DEBUG is not set
......
......@@ -105,7 +105,7 @@ CONFIG_NLS_CODEPAGE_437=y
CONFIG_NLS_ISO8859_1=y
CONFIG_PRINTK_TIME=y
CONFIG_DYNAMIC_DEBUG=y
CONFIG_DEBUG_INFO=y
CONFIG_DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT=y
# CONFIG_FRAME_POINTER is not set
CONFIG_MAGIC_SYSRQ=y
CONFIG_DEBUG_VM=y
......
......@@ -111,7 +111,7 @@ CONFIG_NLS_CODEPAGE_437=y
CONFIG_NLS_ISO8859_1=y
CONFIG_PRINTK_TIME=y
CONFIG_DYNAMIC_DEBUG=y
CONFIG_DEBUG_INFO=y
CONFIG_DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT=y
CONFIG_MAGIC_SYSRQ=y
CONFIG_DEBUG_VM=y
CONFIG_LOCKUP_DETECTOR=y
......
......@@ -97,7 +97,7 @@ CONFIG_CRYPTO_DEV_VIRTIO=y
CONFIG_FONTS=y
CONFIG_PRINTK_TIME=y
CONFIG_DYNAMIC_DEBUG=y
CONFIG_DEBUG_INFO=y
CONFIG_DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT=y
CONFIG_MAGIC_SYSRQ=y
# CONFIG_SCHED_DEBUG is not set
CONFIG_SCHEDSTATS=y
......
......@@ -102,7 +102,7 @@ CONFIG_CRYPTO_LZO=y
CONFIG_CRYPTO_ANSI_CPRNG=y
CONFIG_PRINTK_TIME=y
CONFIG_DYNAMIC_DEBUG=y
CONFIG_DEBUG_INFO=y
CONFIG_DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT=y
CONFIG_MAGIC_SYSRQ=y
CONFIG_DETECT_HUNG_TASK=y
# CONFIG_SCHED_DEBUG is not set
......
......@@ -224,9 +224,6 @@ struct thread_struct {
struct task_struct;
struct mm_struct;
/* Free all resources held by a thread. */
#define release_thread(thread) do { } while(0)
extern unsigned long __get_wchan(struct task_struct *p);
#define KSTK_EIP(tsk) (task_pt_regs(tsk)->pc)
......
......@@ -951,16 +951,13 @@ static bool __get_reqs_available(struct kioctx *ctx)
local_irq_save(flags);
kcpu = this_cpu_ptr(ctx->cpu);
if (!kcpu->reqs_available) {
int old, avail = atomic_read(&ctx->reqs_available);
int avail = atomic_read(&ctx->reqs_available);
do {
if (avail < ctx->req_batch)
goto out;
old = avail;
avail = atomic_cmpxchg(&ctx->reqs_available,
avail, avail - ctx->req_batch);
} while (avail != old);
} while (!atomic_try_cmpxchg(&ctx->reqs_available,
&avail, avail - ctx->req_batch));
kcpu->reqs_available += ctx->req_batch;
}
......
......@@ -1453,19 +1453,15 @@ EXPORT_SYMBOL(set_bh_page);
static void discard_buffer(struct buffer_head * bh)
{
unsigned long b_state, b_state_old;
unsigned long b_state;
lock_buffer(bh);
clear_buffer_dirty(bh);
bh->b_bdev = NULL;
b_state = bh->b_state;
for (;;) {
b_state_old = cmpxchg(&bh->b_state, b_state,
(b_state & ~BUFFER_FLAGS_DISCARD));
if (b_state_old == b_state)
break;
b_state = b_state_old;
}
b_state = READ_ONCE(bh->b_state);
do {
} while (!try_cmpxchg(&bh->b_state, &b_state,
b_state & ~BUFFER_FLAGS_DISCARD));
unlock_buffer(bh);
}
......
......@@ -1065,7 +1065,7 @@ static inline bool list_add_tail_lockless(struct list_head *new,
* added to the list from another CPU: the winner observes
* new->next == new.
*/
if (cmpxchg(&new->next, new, head) != new)
if (!try_cmpxchg(&new->next, &new, head))
return false;
/*
......
......@@ -21,7 +21,6 @@ void hfs_bnode_read(struct hfs_bnode *node, void *buf, int off, int len)
int pagenum;
int bytes_read;
int bytes_to_read;
void *vaddr;
off += node->page_offset;
pagenum = off >> PAGE_SHIFT;
......@@ -33,9 +32,7 @@ void hfs_bnode_read(struct hfs_bnode *node, void *buf, int off, int len)
page = node->page[pagenum];
bytes_to_read = min_t(int, len - bytes_read, PAGE_SIZE - off);
vaddr = kmap_atomic(page);
memcpy(buf + bytes_read, vaddr + off, bytes_to_read);
kunmap_atomic(vaddr);
memcpy_from_page(buf + bytes_read, page, off, bytes_to_read);
pagenum++;
off = 0; /* page offset only applies to the first page */
......@@ -80,8 +77,7 @@ void hfs_bnode_write(struct hfs_bnode *node, void *buf, int off, int len)
off += node->page_offset;
page = node->page[0];
memcpy(kmap(page) + off, buf, len);
kunmap(page);
memcpy_to_page(page, off, buf, len);
set_page_dirty(page);
}
......@@ -105,8 +101,7 @@ void hfs_bnode_clear(struct hfs_bnode *node, int off, int len)
off += node->page_offset;
page = node->page[0];
memset(kmap(page) + off, 0, len);
kunmap(page);
memzero_page(page, off, len);
set_page_dirty(page);
}
......@@ -123,9 +118,7 @@ void hfs_bnode_copy(struct hfs_bnode *dst_node, int dst,
src_page = src_node->page[0];
dst_page = dst_node->page[0];
memcpy(kmap(dst_page) + dst, kmap(src_page) + src, len);
kunmap(src_page);
kunmap(dst_page);
memcpy_page(dst_page, dst, src_page, src, len);
set_page_dirty(dst_page);
}
......@@ -140,9 +133,9 @@ void hfs_bnode_move(struct hfs_bnode *node, int dst, int src, int len)
src += node->page_offset;
dst += node->page_offset;
page = node->page[0];
ptr = kmap(page);
ptr = kmap_local_page(page);
memmove(ptr + dst, ptr + src, len);
kunmap(page);
kunmap_local(ptr);
set_page_dirty(page);
}
......@@ -346,13 +339,14 @@ struct hfs_bnode *hfs_bnode_find(struct hfs_btree *tree, u32 num)
if (!test_bit(HFS_BNODE_NEW, &node->flags))
return node;
desc = (struct hfs_bnode_desc *)(kmap(node->page[0]) + node->page_offset);
desc = (struct hfs_bnode_desc *)(kmap_local_page(node->page[0]) +
node->page_offset);
node->prev = be32_to_cpu(desc->prev);
node->next = be32_to_cpu(desc->next);
node->num_recs = be16_to_cpu(desc->num_recs);
node->type = desc->type;
node->height = desc->height;
kunmap(node->page[0]);
kunmap_local(desc);
switch (node->type) {
case HFS_NODE_HEADER:
......@@ -436,14 +430,12 @@ struct hfs_bnode *hfs_bnode_create(struct hfs_btree *tree, u32 num)
}
pagep = node->page;
memset(kmap(*pagep) + node->page_offset, 0,
min((int)PAGE_SIZE, (int)tree->node_size));
memzero_page(*pagep, node->page_offset,
min((int)PAGE_SIZE, (int)tree->node_size));
set_page_dirty(*pagep);
kunmap(*pagep);
for (i = 1; i < tree->pages_per_bnode; i++) {
memset(kmap(*++pagep), 0, PAGE_SIZE);
memzero_page(*++pagep, 0, PAGE_SIZE);
set_page_dirty(*pagep);
kunmap(*pagep);
}
clear_bit(HFS_BNODE_NEW, &node->flags);
wake_up(&node->lock_wq);
......
......@@ -80,7 +80,8 @@ struct hfs_btree *hfs_btree_open(struct super_block *sb, u32 id, btree_keycmp ke
goto free_inode;
/* Load the header */
head = (struct hfs_btree_header_rec *)(kmap(page) + sizeof(struct hfs_bnode_desc));
head = (struct hfs_btree_header_rec *)(kmap_local_page(page) +
sizeof(struct hfs_bnode_desc));
tree->root = be32_to_cpu(head->root);
tree->leaf_count = be32_to_cpu(head->leaf_count);
tree->leaf_head = be32_to_cpu(head->leaf_head);
......@@ -119,11 +120,12 @@ struct hfs_btree *hfs_btree_open(struct super_block *sb, u32 id, btree_keycmp ke
tree->node_size_shift = ffs(size) - 1;
tree->pages_per_bnode = (tree->node_size + PAGE_SIZE - 1) >> PAGE_SHIFT;
kunmap(page);
kunmap_local(head);
put_page(page);
return tree;
fail_page:
kunmap_local(head);
put_page(page);
free_inode:
tree->inode->i_mapping->a_ops = &hfs_aops;
......@@ -169,7 +171,8 @@ void hfs_btree_write(struct hfs_btree *tree)
return;
/* Load the header */
page = node->page[0];
head = (struct hfs_btree_header_rec *)(kmap(page) + sizeof(struct hfs_bnode_desc));
head = (struct hfs_btree_header_rec *)(kmap_local_page(page) +
sizeof(struct hfs_bnode_desc));
head->root = cpu_to_be32(tree->root);
head->leaf_count = cpu_to_be32(tree->leaf_count);
......@@ -180,7 +183,7 @@ void hfs_btree_write(struct hfs_btree *tree)
head->attributes = cpu_to_be32(tree->attributes);
head->depth = cpu_to_be16(tree->depth);
kunmap(page);
kunmap_local(head);
set_page_dirty(page);
hfs_bnode_put(node);
}
......@@ -268,7 +271,7 @@ struct hfs_bnode *hfs_bmap_alloc(struct hfs_btree *tree)
off += node->page_offset;
pagep = node->page + (off >> PAGE_SHIFT);
data = kmap(*pagep);
data = kmap_local_page(*pagep);
off &= ~PAGE_MASK;
idx = 0;
......@@ -281,7 +284,7 @@ struct hfs_bnode *hfs_bmap_alloc(struct hfs_btree *tree)
idx += i;
data[off] |= m;
set_page_dirty(*pagep);
kunmap(*pagep);
kunmap_local(data);
tree->free_nodes--;
mark_inode_dirty(tree->inode);
hfs_bnode_put(node);
......@@ -290,14 +293,14 @@ struct hfs_bnode *hfs_bmap_alloc(struct hfs_btree *tree)
}
}
if (++off >= PAGE_SIZE) {
kunmap(*pagep);
data = kmap(*++pagep);
kunmap_local(data);
data = kmap_local_page(*++pagep);
off = 0;
}
idx += 8;
len--;
}
kunmap(*pagep);
kunmap_local(data);
nidx = node->next;
if (!nidx) {
printk(KERN_DEBUG "create new bmap node...\n");
......@@ -313,7 +316,7 @@ struct hfs_bnode *hfs_bmap_alloc(struct hfs_btree *tree)
off = off16;
off += node->page_offset;
pagep = node->page + (off >> PAGE_SHIFT);
data = kmap(*pagep);
data = kmap_local_page(*pagep);
off &= ~PAGE_MASK;
}
}
......@@ -360,20 +363,20 @@ void hfs_bmap_free(struct hfs_bnode *node)
}
off += node->page_offset + nidx / 8;
page = node->page[off >> PAGE_SHIFT];
data = kmap(page);
data = kmap_local_page(page);
off &= ~PAGE_MASK;
m = 1 << (~nidx & 7);
byte = data[off];
if (!(byte & m)) {
pr_crit("trying to free free bnode %u(%d)\n",
node->this, node->type);
kunmap(page);
kunmap_local(data);
hfs_bnode_put(node);
return;
}
data[off] = byte & ~m;
set_page_dirty(page);
kunmap(page);
kunmap_local(data);
hfs_bnode_put(node);
tree->free_nodes++;
mark_inode_dirty(tree->inode);
......
......@@ -39,7 +39,7 @@ int hfsplus_block_allocate(struct super_block *sb, u32 size,
start = size;
goto out;
}
pptr = kmap(page);
pptr = kmap_local_page(page);
curr = pptr + (offset & (PAGE_CACHE_BITS - 1)) / 32;
i = offset % 32;
offset &= ~(PAGE_CACHE_BITS - 1);
......@@ -74,7 +74,7 @@ int hfsplus_block_allocate(struct super_block *sb, u32 size,
}
curr++;
}
kunmap(page);
kunmap_local(pptr);
offset += PAGE_CACHE_BITS;
if (offset >= size)
break;
......@@ -84,7 +84,7 @@ int hfsplus_block_allocate(struct super_block *sb, u32 size,
start = size;
goto out;
}
curr = pptr = kmap(page);
curr = pptr = kmap_local_page(page);
if ((size ^ offset) / PAGE_CACHE_BITS)
end = pptr + PAGE_CACHE_BITS / 32;
else
......@@ -127,7 +127,7 @@ int hfsplus_block_allocate(struct super_block *sb, u32 size,
len -= 32;
}
set_page_dirty(page);
kunmap(page);
kunmap_local(pptr);
offset += PAGE_CACHE_BITS;
page = read_mapping_page(mapping, offset / PAGE_CACHE_BITS,
NULL);
......@@ -135,7 +135,7 @@ int hfsplus_block_allocate(struct super_block *sb, u32 size,
start = size;
goto out;
}
pptr = kmap(page);
pptr = kmap_local_page(page);
curr = pptr;
end = pptr + PAGE_CACHE_BITS / 32;
}
......@@ -151,7 +151,7 @@ int hfsplus_block_allocate(struct super_block *sb, u32 size,
done:
*curr = cpu_to_be32(n);
set_page_dirty(page);
kunmap(page);
kunmap_local(pptr);
*max = offset + (curr - pptr) * 32 + i - start;
sbi->free_blocks -= *max;
hfsplus_mark_mdb_dirty(sb);
......@@ -185,7 +185,7 @@ int hfsplus_block_free(struct super_block *sb, u32 offset, u32 count)
page = read_mapping_page(mapping, pnr, NULL);
if (IS_ERR(page))
goto kaboom;
pptr = kmap(page);
pptr = kmap_local_page(page);
curr = pptr + (offset & (PAGE_CACHE_BITS - 1)) / 32;
end = pptr + PAGE_CACHE_BITS / 32;
len = count;
......@@ -215,11 +215,11 @@ int hfsplus_block_free(struct super_block *sb, u32 offset, u32 count)
if (!count)
break;
set_page_dirty(page);
kunmap(page);
kunmap_local(pptr);
page = read_mapping_page(mapping, ++pnr, NULL);
if (IS_ERR(page))
goto kaboom;
pptr = kmap(page);
pptr = kmap_local_page(page);
curr = pptr;
end = pptr + PAGE_CACHE_BITS / 32;
}
......@@ -231,7 +231,7 @@ int hfsplus_block_free(struct super_block *sb, u32 offset, u32 count)
}
out:
set_page_dirty(page);
kunmap(page);
kunmap_local(pptr);
sbi->free_blocks += len;
hfsplus_mark_mdb_dirty(sb);
mutex_unlock(&sbi->alloc_mutex);
......
......@@ -29,14 +29,12 @@ void hfs_bnode_read(struct hfs_bnode *node, void *buf, int off, int len)
off &= ~PAGE_MASK;
l = min_t(int, len, PAGE_SIZE - off);
memcpy(buf, kmap(*pagep) + off, l);
kunmap(*pagep);
memcpy_from_page(buf, *pagep, off, l);
while ((len -= l) != 0) {
buf += l;
l = min_t(int, len, PAGE_SIZE);
memcpy(buf, kmap(*++pagep), l);
kunmap(*pagep);
memcpy_from_page(buf, *++pagep, 0, l);
}
}
......@@ -82,16 +80,14 @@ void hfs_bnode_write(struct hfs_bnode *node, void *buf, int off, int len)
off &= ~PAGE_MASK;
l = min_t(int, len, PAGE_SIZE - off);
memcpy(kmap(*pagep) + off, buf, l);
memcpy_to_page(*pagep, off, buf, l);
set_page_dirty(*pagep);
kunmap(*pagep);
while ((len -= l) != 0) {
buf += l;
l = min_t(int, len, PAGE_SIZE);
memcpy(kmap(*++pagep), buf, l);
memcpy_to_page(*++pagep, 0, buf, l);
set_page_dirty(*pagep);
kunmap(*pagep);
}
}
......@@ -112,15 +108,13 @@ void hfs_bnode_clear(struct hfs_bnode *node, int off, int len)
off &= ~PAGE_MASK;
l = min_t(int, len, PAGE_SIZE - off);
memset(kmap(*pagep) + off, 0, l);
memzero_page(*pagep, off, l);
set_page_dirty(*pagep);
kunmap(*pagep);
while ((len -= l) != 0) {
l = min_t(int, len, PAGE_SIZE);
memset(kmap(*++pagep), 0, l);
memzero_page(*++pagep, 0, l);
set_page_dirty(*pagep);
kunmap(*pagep);
}
}
......@@ -142,24 +136,20 @@ void hfs_bnode_copy(struct hfs_bnode *dst_node, int dst,
if (src == dst) {
l = min_t(int, len, PAGE_SIZE - src);
memcpy(kmap(*dst_page) + src, kmap(*src_page) + src, l);
kunmap(*src_page);
memcpy_page(*dst_page, src, *src_page, src, l);
set_page_dirty(*dst_page);
kunmap(*dst_page);
while ((len -= l) != 0) {
l = min_t(int, len, PAGE_SIZE);
memcpy(kmap(*++dst_page), kmap(*++src_page), l);
kunmap(*src_page);
memcpy_page(*++dst_page, 0, *++src_page, 0, l);
set_page_dirty(*dst_page);
kunmap(*dst_page);
}
} else {
void *src_ptr, *dst_ptr;
do {
src_ptr = kmap(*src_page) + src;
dst_ptr = kmap(*dst_page) + dst;
dst_ptr = kmap_local_page(*dst_page) + dst;
src_ptr = kmap_local_page(*src_page) + src;
if (PAGE_SIZE - src < PAGE_SIZE - dst) {
l = PAGE_SIZE - src;
src = 0;
......@@ -171,9 +161,9 @@ void hfs_bnode_copy(struct hfs_bnode *dst_node, int dst,
}
l = min(len, l);
memcpy(dst_ptr, src_ptr, l);
kunmap(*src_page);
kunmap_local(src_ptr);
set_page_dirty(*dst_page);
kunmap(*dst_page);
kunmap_local(dst_ptr);
if (!dst)
dst_page++;
else
......@@ -185,6 +175,7 @@ void hfs_bnode_copy(struct hfs_bnode *dst_node, int dst,
void hfs_bnode_move(struct hfs_bnode *node, int dst, int src, int len)
{
struct page **src_page, **dst_page;
void *src_ptr, *dst_ptr;
int l;
hfs_dbg(BNODE_MOD, "movebytes: %u,%u,%u\n", dst, src, len);
......@@ -202,27 +193,28 @@ void hfs_bnode_move(struct hfs_bnode *node, int dst, int src, int len)
if (src == dst) {
while (src < len) {
memmove(kmap(*dst_page), kmap(*src_page), src);
kunmap(*src_page);
dst_ptr = kmap_local_page(*dst_page);
src_ptr = kmap_local_page(*src_page);
memmove(dst_ptr, src_ptr, src);
kunmap_local(src_ptr);
set_page_dirty(*dst_page);
kunmap(*dst_page);
kunmap_local(dst_ptr);
len -= src;
src = PAGE_SIZE;
src_page--;
dst_page--;
}
src -= len;
memmove(kmap(*dst_page) + src,
kmap(*src_page) + src, len);
kunmap(*src_page);
dst_ptr = kmap_local_page(*dst_page);
src_ptr = kmap_local_page(*src_page);
memmove(dst_ptr + src, src_ptr + src, len);
kunmap_local(src_ptr);
set_page_dirty(*dst_page);
kunmap(*dst_page);
kunmap_local(dst_ptr);
} else {
void *src_ptr, *dst_ptr;
do {
src_ptr = kmap(*src_page) + src;
dst_ptr = kmap(*dst_page) + dst;
dst_ptr = kmap_local_page(*dst_page) + dst;
src_ptr = kmap_local_page(*src_page) + src;
if (src < dst) {
l = src;
src = PAGE_SIZE;
......@@ -234,9 +226,9 @@ void hfs_bnode_move(struct hfs_bnode *node, int dst, int src, int len)
}
l = min(len, l);
memmove(dst_ptr - l, src_ptr - l, l);
kunmap(*src_page);
kunmap_local(src_ptr);
set_page_dirty(*dst_page);
kunmap(*dst_page);
kunmap_local(dst_ptr);
if (dst == PAGE_SIZE)
dst_page--;
else
......@@ -251,26 +243,27 @@ void hfs_bnode_move(struct hfs_bnode *node, int dst, int src, int len)
if (src == dst) {
l = min_t(int, len, PAGE_SIZE - src);
memmove(kmap(*dst_page) + src,
kmap(*src_page) + src, l);
kunmap(*src_page);
dst_ptr = kmap_local_page(*dst_page) + src;
src_ptr = kmap_local_page(*src_page) + src;
memmove(dst_ptr, src_ptr, l);
kunmap_local(src_ptr);
set_page_dirty(*dst_page);
kunmap(*dst_page);
kunmap_local(dst_ptr);
while ((len -= l) != 0) {
l = min_t(int, len, PAGE_SIZE);
memmove(kmap(*++dst_page),
kmap(*++src_page), l);
kunmap(*src_page);
dst_ptr = kmap_local_page(*++dst_page);
src_ptr = kmap_local_page(*++src_page);
memmove(dst_ptr, src_ptr, l);
kunmap_local(src_ptr);
set_page_dirty(*dst_page);
kunmap(*dst_page);
kunmap_local(dst_ptr);
}
} else {
void *src_ptr, *dst_ptr;
do {
src_ptr = kmap(*src_page) + src;
dst_ptr = kmap(*dst_page) + dst;
dst_ptr = kmap_local_page(*dst_page) + dst;
src_ptr = kmap_local_page(*src_page) + src;
if (PAGE_SIZE - src <
PAGE_SIZE - dst) {
l = PAGE_SIZE - src;
......@@ -283,9 +276,9 @@ void hfs_bnode_move(struct hfs_bnode *node, int dst, int src, int len)
}
l = min(len, l);
memmove(dst_ptr, src_ptr, l);
kunmap(*src_page);
kunmap_local(src_ptr);
set_page_dirty(*dst_page);
kunmap(*dst_page);
kunmap_local(dst_ptr);
if (!dst)
dst_page++;
else
......@@ -498,14 +491,14 @@ struct hfs_bnode *hfs_bnode_find(struct hfs_btree *tree, u32 num)
if (!test_bit(HFS_BNODE_NEW, &node->flags))
return node;
desc = (struct hfs_bnode_desc *)(kmap(node->page[0]) +
node->page_offset);
desc = (struct hfs_bnode_desc *)(kmap_local_page(node->page[0]) +
node->page_offset);
node->prev = be32_to_cpu(desc->prev);
node->next = be32_to_cpu(desc->next);
node->num_recs = be16_to_cpu(desc->num_recs);
node->type = desc->type;
node->height = desc->height;
kunmap(node->page[0]);
kunmap_local(desc);
switch (node->type) {
case HFS_NODE_HEADER:
......@@ -589,14 +582,12 @@ struct hfs_bnode *hfs_bnode_create(struct hfs_btree *tree, u32 num)
}
pagep = node->page;
memset(kmap(*pagep) + node->page_offset, 0,
min_t(int, PAGE_SIZE, tree->node_size));
memzero_page(*pagep, node->page_offset,
min_t(int, PAGE_SIZE, tree->node_size));
set_page_dirty(*pagep);
kunmap(*pagep);
for (i = 1; i < tree->pages_per_bnode; i++) {
memset(kmap(*++pagep), 0, PAGE_SIZE);
memzero_page(*++pagep, 0, PAGE_SIZE);
set_page_dirty(*pagep);
kunmap(*pagep);
}
clear_bit(HFS_BNODE_NEW, &node->flags);
wake_up(&node->lock_wq);
......
......@@ -163,7 +163,7 @@ struct hfs_btree *hfs_btree_open(struct super_block *sb, u32 id)
goto free_inode;
/* Load the header */
head = (struct hfs_btree_header_rec *)(kmap(page) +
head = (struct hfs_btree_header_rec *)(kmap_local_page(page) +
sizeof(struct hfs_bnode_desc));
tree->root = be32_to_cpu(head->root);
tree->leaf_count = be32_to_cpu(head->leaf_count);
......@@ -240,11 +240,12 @@ struct hfs_btree *hfs_btree_open(struct super_block *sb, u32 id)
(tree->node_size + PAGE_SIZE - 1) >>
PAGE_SHIFT;
kunmap(page);
kunmap_local(head);
put_page(page);
return tree;
fail_page:
kunmap_local(head);
put_page(page);
free_inode:
tree->inode->i_mapping->a_ops = &hfsplus_aops;
......@@ -291,7 +292,7 @@ int hfs_btree_write(struct hfs_btree *tree)
return -EIO;
/* Load the header */
page = node->page[0];
head = (struct hfs_btree_header_rec *)(kmap(page) +
head = (struct hfs_btree_header_rec *)(kmap_local_page(page) +
sizeof(struct hfs_bnode_desc));
head->root = cpu_to_be32(tree->root);
......@@ -303,7 +304,7 @@ int hfs_btree_write(struct hfs_btree *tree)
head->attributes = cpu_to_be32(tree->attributes);
head->depth = cpu_to_be16(tree->depth);
kunmap(page);
kunmap_local(head);
set_page_dirty(page);
hfs_bnode_put(node);
return 0;
......@@ -394,7 +395,7 @@ struct hfs_bnode *hfs_bmap_alloc(struct hfs_btree *tree)
off += node->page_offset;
pagep = node->page + (off >> PAGE_SHIFT);
data = kmap(*pagep);
data = kmap_local_page(*pagep);
off &= ~PAGE_MASK;
idx = 0;
......@@ -407,7 +408,7 @@ struct hfs_bnode *hfs_bmap_alloc(struct hfs_btree *tree)
idx += i;
data[off] |= m;
set_page_dirty(*pagep);
kunmap(*pagep);
kunmap_local(data);
tree->free_nodes--;
mark_inode_dirty(tree->inode);
hfs_bnode_put(node);
......@@ -417,14 +418,14 @@ struct hfs_bnode *hfs_bmap_alloc(struct hfs_btree *tree)
}
}
if (++off >= PAGE_SIZE) {
kunmap(*pagep);
data = kmap(*++pagep);
kunmap_local(data);
data = kmap_local_page(*++pagep);
off = 0;
}
idx += 8;
len--;
}
kunmap(*pagep);
kunmap_local(data);
nidx = node->next;
if (!nidx) {
hfs_dbg(BNODE_MOD, "create new bmap node\n");
......@@ -440,7 +441,7 @@ struct hfs_bnode *hfs_bmap_alloc(struct hfs_btree *tree)
off = off16;
off += node->page_offset;
pagep = node->page + (off >> PAGE_SHIFT);
data = kmap(*pagep);
data = kmap_local_page(*pagep);
off &= ~PAGE_MASK;
}
}
......@@ -490,7 +491,7 @@ void hfs_bmap_free(struct hfs_bnode *node)
}
off += node->page_offset + nidx / 8;
page = node->page[off >> PAGE_SHIFT];
data = kmap(page);
data = kmap_local_page(page);
off &= ~PAGE_MASK;
m = 1 << (~nidx & 7);
byte = data[off];
......@@ -498,13 +499,13 @@ void hfs_bmap_free(struct hfs_bnode *node)
pr_crit("trying to free free bnode "
"%u(%d)\n",
node->this, node->type);
kunmap(page);
kunmap_local(data);
hfs_bnode_put(node);
return;
}
data[off] = byte & ~m;
set_page_dirty(page);
kunmap(page);
kunmap_local(data);
hfs_bnode_put(node);
tree->free_nodes++;
mark_inode_dirty(tree->inode);
......
......@@ -67,8 +67,7 @@ static loff_t zisofs_uncompress_block(struct inode *inode, loff_t block_start,
for ( i = 0 ; i < pcount ; i++ ) {
if (!pages[i])
continue;
memset(page_address(pages[i]), 0, PAGE_SIZE);
flush_dcache_page(pages[i]);
memzero_page(pages[i], 0, PAGE_SIZE);
SetPageUptodate(pages[i]);
}
return ((loff_t)pcount) << PAGE_SHIFT;
......@@ -120,7 +119,7 @@ static loff_t zisofs_uncompress_block(struct inode *inode, loff_t block_start,
zerr != Z_STREAM_END) {
if (!stream.avail_out) {
if (pages[curpage]) {
stream.next_out = page_address(pages[curpage])
stream.next_out = kmap_local_page(pages[curpage])
+ poffset;
stream.avail_out = PAGE_SIZE - poffset;
poffset = 0;
......@@ -176,6 +175,10 @@ static loff_t zisofs_uncompress_block(struct inode *inode, loff_t block_start,
flush_dcache_page(pages[curpage]);
SetPageUptodate(pages[curpage]);
}
if (stream.next_out != (unsigned char *)zisofs_sink_page) {
kunmap_local(stream.next_out);
stream.next_out = NULL;
}
curpage++;
}
if (!stream.avail_in)
......@@ -183,6 +186,8 @@ static loff_t zisofs_uncompress_block(struct inode *inode, loff_t block_start,
}
inflate_out:
zlib_inflateEnd(&stream);
if (stream.next_out && stream.next_out != (unsigned char *)zisofs_sink_page)
kunmap_local(stream.next_out);
z_eio:
mutex_unlock(&zisofs_zlib_lock);
......@@ -283,9 +288,7 @@ static int zisofs_fill_pages(struct inode *inode, int full_page, int pcount,
}
if (poffset && *pages) {
memset(page_address(*pages) + poffset, 0,
PAGE_SIZE - poffset);
flush_dcache_page(*pages);
memzero_page(*pages, poffset, PAGE_SIZE - poffset);
SetPageUptodate(*pages);
}
return 0;
......@@ -343,10 +346,8 @@ static int zisofs_read_folio(struct file *file, struct folio *folio)
for (i = 0; i < pcount; i++, index++) {
if (i != full_page)
pages[i] = grab_cache_page_nowait(mapping, index);
if (pages[i]) {
if (pages[i])
ClearPageError(pages[i]);
kmap(pages[i]);
}
}
err = zisofs_fill_pages(inode, full_page, pcount, pages);
......@@ -357,7 +358,6 @@ static int zisofs_read_folio(struct file *file, struct folio *folio)
flush_dcache_page(pages[i]);
if (i == full_page && err)
SetPageError(pages[i]);
kunmap(pages[i]);
unlock_page(pages[i]);
if (i != full_page)
put_page(pages[i]);
......
......@@ -15,6 +15,7 @@
#include <linux/mutex.h>
#include <linux/namei.h>
#include <linux/exportfs.h>
#include <linux/iversion.h>
#include <linux/writeback.h>
#include <linux/buffer_head.h> /* sync_mapping_buffers */
#include <linux/fs_context.h>
......@@ -1520,3 +1521,48 @@ void generic_set_encrypted_ci_d_ops(struct dentry *dentry)
#endif
}
EXPORT_SYMBOL(generic_set_encrypted_ci_d_ops);
/**
* inode_maybe_inc_iversion - increments i_version
* @inode: inode with the i_version that should be updated
* @force: increment the counter even if it's not necessary?
*
* Every time the inode is modified, the i_version field must be seen to have
* changed by any observer.
*
* If "force" is set or the QUERIED flag is set, then ensure that we increment
* the value, and clear the queried flag.
*
* In the common case where neither is set, then we can return "false" without
* updating i_version.
*
* If this function returns false, and no other metadata has changed, then we
* can avoid logging the metadata.
*/
bool inode_maybe_inc_iversion(struct inode *inode, bool force)
{
u64 cur, new;
/*
* The i_version field is not strictly ordered with any other inode
* information, but the legacy inode_inc_iversion code used a spinlock
* to serialize increments.
*
* Here, we add full memory barriers to ensure that any de-facto
* ordering with other info is preserved.
*
* This barrier pairs with the barrier in inode_query_iversion()
*/
smp_mb();
cur = inode_peek_iversion_raw(inode);
do {
/* If flag is clear then we needn't do anything */
if (!force && !(cur & I_VERSION_QUERIED))
return false;
/* Since lowest bit is flag, add 2 to avoid it */
new = (cur & ~I_VERSION_QUERIED) + I_VERSION_INCREMENT;
} while (!atomic64_try_cmpxchg(&inode->i_version, &cur, new));
return true;
}
EXPORT_SYMBOL(inode_maybe_inc_iversion);
......@@ -1668,8 +1668,7 @@ static int nilfs_btree_check_delete(struct nilfs_bmap *btree, __u64 key)
maxkey = nilfs_btree_node_get_key(node, nchildren - 1);
nextmaxkey = (nchildren > 1) ?
nilfs_btree_node_get_key(node, nchildren - 2) : 0;
if (bh != NULL)
brelse(bh);
brelse(bh);
return (maxkey == key) && (nextmaxkey < NILFS_BMAP_LARGE_LOW);
}
......@@ -1717,8 +1716,7 @@ static int nilfs_btree_gather_data(struct nilfs_bmap *btree,
ptrs[i] = le64_to_cpu(dptrs[i]);
}
if (bh != NULL)
brelse(bh);
brelse(bh);
return nitems;
}
......
......@@ -875,9 +875,11 @@ static int nilfs_segctor_create_checkpoint(struct nilfs_sc_info *sci)
nilfs_mdt_mark_dirty(nilfs->ns_cpfile);
nilfs_cpfile_put_checkpoint(
nilfs->ns_cpfile, nilfs->ns_cno, bh_cp);
} else
WARN_ON(err == -EINVAL || err == -ENOENT);
} else if (err == -EINVAL || err == -ENOENT) {
nilfs_error(sci->sc_super,
"checkpoint creation failed due to metadata corruption.");
err = -EIO;
}
return err;
}
......@@ -891,7 +893,11 @@ static int nilfs_segctor_fill_in_checkpoint(struct nilfs_sc_info *sci)
err = nilfs_cpfile_get_checkpoint(nilfs->ns_cpfile, nilfs->ns_cno, 0,
&raw_cp, &bh_cp);
if (unlikely(err)) {
WARN_ON(err == -EINVAL || err == -ENOENT);
if (err == -EINVAL || err == -ENOENT) {
nilfs_error(sci->sc_super,
"checkpoint finalization failed due to metadata corruption.");
err = -EIO;
}
goto failed_ibh;
}
raw_cp->cp_snapshot_list.ssl_next = 0;
......@@ -2235,7 +2241,6 @@ int nilfs_construct_segment(struct super_block *sb)
struct the_nilfs *nilfs = sb->s_fs_info;
struct nilfs_sc_info *sci = nilfs->ns_writer;
struct nilfs_transaction_info *ti;
int err;
if (!sci)
return -EROFS;
......@@ -2243,8 +2248,7 @@ int nilfs_construct_segment(struct super_block *sb)
/* A call inside transactions causes a deadlock. */
BUG_ON((ti = current->journal_info) && ti->ti_magic == NILFS_TI_MAGIC);
err = nilfs_segctor_sync(sci);
return err;
return nilfs_segctor_sync(sci);
}
/**
......
......@@ -594,17 +594,37 @@ static int ntfs_attr_find(const ATTR_TYPE type, const ntfschar *name,
for (;; a = (ATTR_RECORD*)((u8*)a + le32_to_cpu(a->length))) {
u8 *mrec_end = (u8 *)ctx->mrec +
le32_to_cpu(ctx->mrec->bytes_allocated);
u8 *name_end = (u8 *)a + le16_to_cpu(a->name_offset) +
a->name_length * sizeof(ntfschar);
if ((u8*)a < (u8*)ctx->mrec || (u8*)a > mrec_end ||
name_end > mrec_end)
u8 *name_end;
/* check whether ATTR_RECORD wrap */
if ((u8 *)a < (u8 *)ctx->mrec)
break;
/* check whether Attribute Record Header is within bounds */
if ((u8 *)a > mrec_end ||
(u8 *)a + sizeof(ATTR_RECORD) > mrec_end)
break;
/* check whether ATTR_RECORD's name is within bounds */
name_end = (u8 *)a + le16_to_cpu(a->name_offset) +
a->name_length * sizeof(ntfschar);
if (name_end > mrec_end)
break;
ctx->attr = a;
if (unlikely(le32_to_cpu(a->type) > le32_to_cpu(type) ||
a->type == AT_END))
return -ENOENT;
if (unlikely(!a->length))
break;
/* check whether ATTR_RECORD's length wrap */
if ((u8 *)a + le32_to_cpu(a->length) < (u8 *)a)
break;
/* check whether ATTR_RECORD's length is within bounds */
if ((u8 *)a + le32_to_cpu(a->length) > mrec_end)
break;
if (a->type != type)
continue;
/*
......
......@@ -1829,6 +1829,13 @@ int ntfs_read_inode_mount(struct inode *vi)
goto err_out;
}
/* Sanity check offset to the first attribute */
if (le16_to_cpu(m->attrs_offset) >= le32_to_cpu(m->bytes_allocated)) {
ntfs_error(sb, "Incorrect mft offset to the first attribute %u in superblock.",
le16_to_cpu(m->attrs_offset));
goto err_out;
}
/* Need this to sanity check attribute list references to $MFT. */
vi->i_generation = ni->seq_no = le16_to_cpu(m->sequence_number);
......
......@@ -527,7 +527,7 @@ struct ocfs2_extent_block
* value -1 (0xFFFF) is OCFS2_INVALID_SLOT. This marks a slot empty.
*/
struct ocfs2_slot_map {
/*00*/ __le16 sm_slots[0];
/*00*/ DECLARE_FLEX_ARRAY(__le16, sm_slots);
/*
* Actual on-disk size is one block. OCFS2_MAX_SLOTS is 255,
* 255 * sizeof(__le16) == 512B, within the 512B block minimum blocksize.
......@@ -548,7 +548,7 @@ struct ocfs2_extended_slot {
* i_size.
*/
struct ocfs2_slot_map_extended {
/*00*/ struct ocfs2_extended_slot se_slots[0];
/*00*/ DECLARE_FLEX_ARRAY(struct ocfs2_extended_slot, se_slots);
/*
* Actual size is i_size of the slot_map system file. It should
* match s_max_slots * sizeof(struct ocfs2_extended_slot)
......@@ -727,7 +727,7 @@ struct ocfs2_dinode {
struct ocfs2_extent_list i_list;
struct ocfs2_truncate_log i_dealloc;
struct ocfs2_inline_data i_data;
__u8 i_symlink[0];
DECLARE_FLEX_ARRAY(__u8, i_symlink);
} id2;
/* Actual on-disk size is one block */
};
......@@ -892,7 +892,7 @@ struct ocfs2_group_desc
/*30*/ struct ocfs2_block_check bg_check; /* Error checking */
__le64 bg_reserved2;
/*40*/ union {
__u8 bg_bitmap[0];
DECLARE_FLEX_ARRAY(__u8, bg_bitmap);
struct {
/*
* Block groups may be discontiguous when
......
......@@ -2614,7 +2614,7 @@ static inline unsigned int ocfs2_cow_align_length(struct super_block *sb,
}
/*
* Calculate out the start and number of virtual clusters we need to to CoW.
* Calculate out the start and number of virtual clusters we need to CoW.
*
* cpos is vitual start cluster position we want to do CoW in a
* file and write_len is the cluster length.
......
......@@ -334,10 +334,10 @@ int ocfs2_cluster_connect(const char *stack_name,
goto out;
}
strlcpy(new_conn->cc_name, group, GROUP_NAME_MAX + 1);
strscpy(new_conn->cc_name, group, GROUP_NAME_MAX + 1);
new_conn->cc_namelen = grouplen;
if (cluster_name_len)
strlcpy(new_conn->cc_cluster_name, cluster_name,
strscpy(new_conn->cc_cluster_name, cluster_name,
CLUSTER_NAME_MAX + 1);
new_conn->cc_cluster_name_len = cluster_name_len;
new_conn->cc_recovery_handler = recovery_handler;
......
......@@ -106,7 +106,7 @@ int ocfs2_claim_clusters(handle_t *handle,
u32 *cluster_start,
u32 *num_clusters);
/*
* Use this variant of ocfs2_claim_clusters to specify a maxiumum
* Use this variant of ocfs2_claim_clusters to specify a maximum
* number of clusters smaller than the allocation reserved.
*/
int __ocfs2_claim_clusters(handle_t *handle,
......
......@@ -2219,7 +2219,7 @@ static int ocfs2_initialize_super(struct super_block *sb,
goto out_journal;
}
strlcpy(osb->vol_label, di->id2.i_super.s_label,
strscpy(osb->vol_label, di->id2.i_super.s_label,
OCFS2_MAX_VOL_LABEL_LEN);
osb->root_blkno = le64_to_cpu(di->id2.i_super.s_root_blkno);
osb->system_dir_blkno = le64_to_cpu(di->id2.i_super.s_system_dir_blkno);
......
......@@ -92,6 +92,7 @@ config PROC_PAGE_MONITOR
config PROC_CHILDREN
bool "Include /proc/<pid>/task/<tid>/children file"
depends on PROC_FS
default n
help
Provides a fast way to retrieve first level children pids of a task. See
......
......@@ -4,6 +4,7 @@
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <linux/blkdev.h>
#include "internal.h"
static int devinfo_show(struct seq_file *f, void *v)
{
......@@ -54,7 +55,10 @@ static const struct seq_operations devinfo_ops = {
static int __init proc_devices_init(void)
{
proc_create_seq("devices", 0, NULL, &devinfo_ops);
struct proc_dir_entry *pde;
pde = proc_create_seq("devices", 0, NULL, &devinfo_ops);
pde_make_permanent(pde);
return 0;
}
fs_initcall(proc_devices_init);
......@@ -79,6 +79,11 @@ static inline bool pde_is_permanent(const struct proc_dir_entry *pde)
return pde->flags & PROC_ENTRY_PERMANENT;
}
static inline void pde_make_permanent(struct proc_dir_entry *pde)
{
pde->flags |= PROC_ENTRY_PERMANENT;
}
extern struct kmem_cache *proc_dir_entry_cache;
void pde_free(struct proc_dir_entry *pde);
......
......@@ -9,6 +9,7 @@
#include <linux/seq_file.h>
#include <linux/seqlock.h>
#include <linux/time.h>
#include "internal.h"
static int loadavg_proc_show(struct seq_file *m, void *v)
{
......@@ -27,7 +28,10 @@ static int loadavg_proc_show(struct seq_file *m, void *v)
static int __init proc_loadavg_init(void)
{
proc_create_single("loadavg", 0, NULL, loadavg_proc_show);
struct proc_dir_entry *pde;
pde = proc_create_single("loadavg", 0, NULL, loadavg_proc_show);
pde_make_permanent(pde);
return 0;
}
fs_initcall(proc_loadavg_init);
......@@ -164,7 +164,10 @@ static int meminfo_proc_show(struct seq_file *m, void *v)
static int __init proc_meminfo_init(void)
{
proc_create_single("meminfo", 0, NULL, meminfo_proc_show);
struct proc_dir_entry *pde;
pde = proc_create_single("meminfo", 0, NULL, meminfo_proc_show);
pde_make_permanent(pde);
return 0;
}
fs_initcall(proc_meminfo_init);
......@@ -91,6 +91,7 @@ static ssize_t kpagecount_read(struct file *file, char __user *buf,
}
static const struct proc_ops kpagecount_proc_ops = {
.proc_flags = PROC_ENTRY_PERMANENT,
.proc_lseek = mem_lseek,
.proc_read = kpagecount_read,
};
......@@ -268,6 +269,7 @@ static ssize_t kpageflags_read(struct file *file, char __user *buf,
}
static const struct proc_ops kpageflags_proc_ops = {
.proc_flags = PROC_ENTRY_PERMANENT,
.proc_lseek = mem_lseek,
.proc_read = kpageflags_read,
};
......@@ -322,6 +324,7 @@ static ssize_t kpagecgroup_read(struct file *file, char __user *buf,
}
static const struct proc_ops kpagecgroup_proc_ops = {
.proc_flags = PROC_ENTRY_PERMANENT,
.proc_lseek = mem_lseek,
.proc_read = kpagecgroup_read,
};
......
......@@ -3,6 +3,7 @@
#include <linux/kernel_stat.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include "internal.h"
/*
* /proc/softirqs ... display the number of softirqs
......@@ -27,7 +28,10 @@ static int show_softirqs(struct seq_file *p, void *v)
static int __init proc_softirqs_init(void)
{
proc_create_single("softirqs", 0, NULL, show_softirqs);
struct proc_dir_entry *pde;
pde = proc_create_single("softirqs", 0, NULL, show_softirqs);
pde_make_permanent(pde);
return 0;
}
fs_initcall(proc_softirqs_init);
......@@ -7,6 +7,7 @@
#include <linux/time.h>
#include <linux/time_namespace.h>
#include <linux/kernel_stat.h>
#include "internal.h"
static int uptime_proc_show(struct seq_file *m, void *v)
{
......@@ -39,7 +40,10 @@ static int uptime_proc_show(struct seq_file *m, void *v)
static int __init proc_uptime_init(void)
{
proc_create_single("uptime", 0, NULL, uptime_proc_show);
struct proc_dir_entry *pde;
pde = proc_create_single("uptime", 0, NULL, uptime_proc_show);
pde_make_permanent(pde);
return 0;
}
fs_initcall(proc_uptime_init);
......@@ -5,6 +5,7 @@
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <linux/utsname.h>
#include "internal.h"
static int version_proc_show(struct seq_file *m, void *v)
{
......@@ -17,7 +18,10 @@ static int version_proc_show(struct seq_file *m, void *v)
static int __init proc_version_init(void)
{
proc_create_single("version", 0, NULL, version_proc_show);
struct proc_dir_entry *pde;
pde = proc_create_single("version", 0, NULL, version_proc_show);
pde_make_permanent(pde);
return 0;
}
fs_initcall(proc_version_init);
......@@ -470,10 +470,8 @@ static int qnx6_fill_super(struct super_block *s, void *data, int silent)
out1:
iput(sbi->inodes);
out:
if (bh1)
brelse(bh1);
if (bh2)
brelse(bh2);
brelse(bh1);
brelse(bh2);
outnobh:
kfree(qs);
s->s_fs_info = NULL;
......
......@@ -411,7 +411,7 @@ int reiserfs_proc_info_init(struct super_block *sb)
char *s;
/* Some block devices use /'s */
strlcpy(b, sb->s_id, BDEVNAME_SIZE);
strscpy(b, sb->s_id, BDEVNAME_SIZE);
s = strchr(b, '/');
if (s)
*s = '!';
......@@ -441,7 +441,7 @@ int reiserfs_proc_info_done(struct super_block *sb)
char *s;
/* Some block devices use /'s */
strlcpy(b, sb->s_id, BDEVNAME_SIZE);
strscpy(b, sb->s_id, BDEVNAME_SIZE);
s = strchr(b, '/');
if (s)
*s = '!';
......
......@@ -126,7 +126,7 @@ static inline void put_unaligned_le24(const u32 val, void *p)
__put_unaligned_le24(val, p);
}
static inline void __put_unaligned_be48(const u64 val, __u8 *p)
static inline void __put_unaligned_be48(const u64 val, u8 *p)
{
*p++ = val >> 40;
*p++ = val >> 32;
......
......@@ -347,10 +347,10 @@ static __always_inline void __assign_bit(long nr, volatile unsigned long *addr,
const typeof(*(ptr)) mask__ = (mask), bits__ = (bits); \
typeof(*(ptr)) old__, new__; \
\
old__ = READ_ONCE(*(ptr)); \
do { \
old__ = READ_ONCE(*(ptr)); \
new__ = (old__ & ~mask__) | bits__; \
} while (cmpxchg(ptr, old__, new__) != old__); \
} while (!try_cmpxchg(ptr, &old__, new__)); \
\
old__; \
})
......@@ -362,11 +362,12 @@ static __always_inline void __assign_bit(long nr, volatile unsigned long *addr,
const typeof(*(ptr)) clear__ = (clear), test__ = (test);\
typeof(*(ptr)) old__, new__; \
\
old__ = READ_ONCE(*(ptr)); \
do { \
old__ = READ_ONCE(*(ptr)); \
if (old__ & test__) \
break; \
new__ = old__ & ~clear__; \
} while (!(old__ & test__) && \
cmpxchg(ptr, old__, new__) != old__); \
} while (!try_cmpxchg(ptr, &old__, new__)); \
\
!(old__ & test__); \
})
......
......@@ -253,7 +253,6 @@ static __always_inline void arch_exit_to_user_mode(void) { }
/**
* arch_do_signal_or_restart - Architecture specific signal delivery function
* @regs: Pointer to currents pt_regs
* @has_signal: actual signal to handle
*
* Invoked from exit_to_user_mode_loop().
*/
......
......@@ -134,7 +134,7 @@ static inline initcall_t initcall_from_entry(initcall_entry_t *entry)
extern initcall_entry_t __con_initcall_start[], __con_initcall_end[];
/* Used for contructor calls. */
/* Used for constructor calls. */
typedef void (*ctor_fn_t)(void);
struct file_system_type;
......
......@@ -11,6 +11,7 @@
#include <linux/refcount.h>
#include <linux/rhashtable-types.h>
#include <linux/sysctl.h>
#include <linux/percpu_counter.h>
struct user_namespace;
......@@ -36,8 +37,8 @@ struct ipc_namespace {
unsigned int msg_ctlmax;
unsigned int msg_ctlmnb;
unsigned int msg_ctlmni;
atomic_t msg_bytes;
atomic_t msg_hdrs;
struct percpu_counter percpu_msg_bytes;
struct percpu_counter percpu_msg_hdrs;
size_t shm_ctlmax;
size_t shm_ctlall;
......
......@@ -123,17 +123,12 @@ inode_peek_iversion_raw(const struct inode *inode)
static inline void
inode_set_max_iversion_raw(struct inode *inode, u64 val)
{
u64 cur, old;
u64 cur = inode_peek_iversion_raw(inode);
cur = inode_peek_iversion_raw(inode);
for (;;) {
do {
if (cur > val)
break;
old = atomic64_cmpxchg(&inode->i_version, cur, val);
if (likely(old == cur))
break;
cur = old;
}
} while (!atomic64_try_cmpxchg(&inode->i_version, &cur, val));
}
/**
......@@ -177,56 +172,7 @@ inode_set_iversion_queried(struct inode *inode, u64 val)
I_VERSION_QUERIED);
}
/**
* inode_maybe_inc_iversion - increments i_version
* @inode: inode with the i_version that should be updated
* @force: increment the counter even if it's not necessary?
*
* Every time the inode is modified, the i_version field must be seen to have
* changed by any observer.
*
* If "force" is set or the QUERIED flag is set, then ensure that we increment
* the value, and clear the queried flag.
*
* In the common case where neither is set, then we can return "false" without
* updating i_version.
*
* If this function returns false, and no other metadata has changed, then we
* can avoid logging the metadata.
*/
static inline bool
inode_maybe_inc_iversion(struct inode *inode, bool force)
{
u64 cur, old, new;
/*
* The i_version field is not strictly ordered with any other inode
* information, but the legacy inode_inc_iversion code used a spinlock
* to serialize increments.
*
* Here, we add full memory barriers to ensure that any de-facto
* ordering with other info is preserved.
*
* This barrier pairs with the barrier in inode_query_iversion()
*/
smp_mb();
cur = inode_peek_iversion_raw(inode);
for (;;) {
/* If flag is clear then we needn't do anything */
if (!force && !(cur & I_VERSION_QUERIED))
return false;
/* Since lowest bit is flag, add 2 to avoid it */
new = (cur & ~I_VERSION_QUERIED) + I_VERSION_INCREMENT;
old = atomic64_cmpxchg(&inode->i_version, cur, new);
if (likely(old == cur))
break;
cur = old;
}
return true;
}
bool inode_maybe_inc_iversion(struct inode *inode, bool force);
/**
* inode_inc_iversion - forcibly increment i_version
......@@ -304,10 +250,10 @@ inode_peek_iversion(const struct inode *inode)
static inline u64
inode_query_iversion(struct inode *inode)
{
u64 cur, old, new;
u64 cur, new;
cur = inode_peek_iversion_raw(inode);
for (;;) {
do {
/* If flag is already set, then no need to swap */
if (cur & I_VERSION_QUERIED) {
/*
......@@ -320,11 +266,7 @@ inode_query_iversion(struct inode *inode)
}
new = cur | I_VERSION_QUERIED;
old = atomic64_cmpxchg(&inode->i_version, cur, new);
if (likely(old == cur))
break;
cur = old;
}
} while (!atomic64_try_cmpxchg(&inode->i_version, &cur, new));
return cur >> I_VERSION_QUERIED_SHIFT;
}
......
......@@ -427,7 +427,7 @@ extern int kexec_load_disabled;
extern bool kexec_in_progress;
int crash_shrink_memory(unsigned long new_size);
size_t crash_get_memory_size(void);
ssize_t crash_get_memory_size(void);
#ifndef arch_kexec_protect_crashkres
/*
......
......@@ -15,6 +15,9 @@
#include <linux/types.h>
#include <linux/gfp.h>
/* percpu_counter batch for local add or sub */
#define PERCPU_COUNTER_LOCAL_BATCH INT_MAX
#ifdef CONFIG_SMP
struct percpu_counter {
......@@ -56,6 +59,22 @@ static inline void percpu_counter_add(struct percpu_counter *fbc, s64 amount)
percpu_counter_add_batch(fbc, amount, percpu_counter_batch);
}
/*
* With percpu_counter_add_local() and percpu_counter_sub_local(), counts
* are accumulated in local per cpu counter and not in fbc->count until
* local count overflows PERCPU_COUNTER_LOCAL_BATCH. This makes counter
* write efficient.
* But percpu_counter_sum(), instead of percpu_counter_read(), needs to be
* used to add up the counts from each CPU to account for all the local
* counts. So percpu_counter_add_local() and percpu_counter_sub_local()
* should be used when a counter is updated frequently and read rarely.
*/
static inline void
percpu_counter_add_local(struct percpu_counter *fbc, s64 amount)
{
percpu_counter_add_batch(fbc, amount, PERCPU_COUNTER_LOCAL_BATCH);
}
static inline s64 percpu_counter_sum_positive(struct percpu_counter *fbc)
{
s64 ret = __percpu_counter_sum(fbc);
......@@ -138,6 +157,13 @@ percpu_counter_add(struct percpu_counter *fbc, s64 amount)
preempt_enable();
}
/* non-SMP percpu_counter_add_local is the same with percpu_counter_add */
static inline void
percpu_counter_add_local(struct percpu_counter *fbc, s64 amount)
{
percpu_counter_add(fbc, amount);
}
static inline void
percpu_counter_add_batch(struct percpu_counter *fbc, s64 amount, s32 batch)
{
......@@ -193,4 +219,10 @@ static inline void percpu_counter_sub(struct percpu_counter *fbc, s64 amount)
percpu_counter_add(fbc, -amount);
}
static inline void
percpu_counter_sub_local(struct percpu_counter *fbc, s64 amount)
{
percpu_counter_add_local(fbc, -amount);
}
#endif /* _LINUX_PERCPU_COUNTER_H */
......@@ -127,6 +127,9 @@ static inline void put_task_struct_many(struct task_struct *t, int nr)
void put_task_struct_rcu_user(struct task_struct *task);
/* Free all architecture-specific resources held by a thread. */
void release_thread(struct task_struct *dead_task);
#ifdef CONFIG_ARCH_WANTS_DYNAMIC_TASK_STRUCT
extern int arch_task_struct_size __read_mostly;
#else
......
......@@ -1267,6 +1267,7 @@ endif # NAMESPACES
config CHECKPOINT_RESTORE
bool "Checkpoint/restore support"
depends on PROC_FS
select PROC_CHILDREN
select KCMP
default n
......
......@@ -296,7 +296,7 @@ EXPORT_SYMBOL_GPL(name_to_dev_t);
static int __init root_dev_setup(char *line)
{
strlcpy(saved_root_name, line, sizeof(saved_root_name));
strscpy(saved_root_name, line, sizeof(saved_root_name));
return 1;
}
......@@ -343,7 +343,7 @@ static int __init split_fs_names(char *page, size_t size, char *names)
int count = 1;
char *p = page;
strlcpy(p, root_fs_names, size);
strscpy(p, root_fs_names, size);
while (*p++) {
if (p[-1] == ',') {
p[-1] = '\0';
......
......@@ -482,7 +482,7 @@ static long __init flush_buffer(void *bufv, unsigned long len)
return origLen;
}
static unsigned long my_inptr; /* index of next byte to be processed in inbuf */
static unsigned long my_inptr __initdata; /* index of next byte to be processed in inbuf */
#include <linux/decompress/generic.h>
......
......@@ -424,7 +424,7 @@ static void __init setup_boot_config(void)
if (!data)
data = xbc_get_embedded_bootconfig(&size);
strlcpy(tmp_cmdline, boot_command_line, COMMAND_LINE_SIZE);
strscpy(tmp_cmdline, boot_command_line, COMMAND_LINE_SIZE);
err = parse_args("bootconfig", tmp_cmdline, NULL, 0, 0, 0, NULL,
bootconfig_params);
......@@ -764,7 +764,7 @@ void __init parse_early_param(void)
return;
/* All fall through to do_early_param. */
strlcpy(tmp_cmdline, boot_command_line, COMMAND_LINE_SIZE);
strscpy(tmp_cmdline, boot_command_line, COMMAND_LINE_SIZE);
parse_early_options(tmp_cmdline);
done = 1;
}
......@@ -1244,7 +1244,7 @@ __setup("initcall_blacklist=", initcall_blacklist);
static __init_or_module void
trace_initcall_start_cb(void *data, initcall_t fn)
{
ktime_t *calltime = (ktime_t *)data;
ktime_t *calltime = data;
printk(KERN_DEBUG "calling %pS @ %i\n", fn, task_pid_nr(current));
*calltime = ktime_get();
......@@ -1253,7 +1253,7 @@ trace_initcall_start_cb(void *data, initcall_t fn)
static __init_or_module void
trace_initcall_finish_cb(void *data, initcall_t fn, int ret)
{
ktime_t rettime, *calltime = (ktime_t *)data;
ktime_t rettime, *calltime = data;
rettime = ktime_get();
printk(KERN_DEBUG "initcall %pS returned %d after %lld usecs\n",
......
......@@ -986,8 +986,7 @@ SYSCALL_DEFINE1(mq_unlink, const char __user *, u_name)
out_unlock:
inode_unlock(d_inode(mnt->mnt_root));
if (inode)
iput(inode);
iput(inode);
mnt_drop_write(mnt);
out_name:
putname(name);
......
......@@ -39,6 +39,7 @@
#include <linux/nsproxy.h>
#include <linux/ipc_namespace.h>
#include <linux/rhashtable.h>
#include <linux/percpu_counter.h>
#include <asm/current.h>
#include <linux/uaccess.h>
......@@ -285,10 +286,10 @@ static void freeque(struct ipc_namespace *ns, struct kern_ipc_perm *ipcp)
rcu_read_unlock();
list_for_each_entry_safe(msg, t, &msq->q_messages, m_list) {
atomic_dec(&ns->msg_hdrs);
percpu_counter_sub_local(&ns->percpu_msg_hdrs, 1);
free_msg(msg);
}
atomic_sub(msq->q_cbytes, &ns->msg_bytes);
percpu_counter_sub_local(&ns->percpu_msg_bytes, msq->q_cbytes);
ipc_update_pid(&msq->q_lspid, NULL);
ipc_update_pid(&msq->q_lrpid, NULL);
ipc_rcu_putref(&msq->q_perm, msg_rcu_free);
......@@ -495,17 +496,22 @@ static int msgctl_info(struct ipc_namespace *ns, int msqid,
msginfo->msgssz = MSGSSZ;
msginfo->msgseg = MSGSEG;
down_read(&msg_ids(ns).rwsem);
if (cmd == MSG_INFO) {
if (cmd == MSG_INFO)
msginfo->msgpool = msg_ids(ns).in_use;
msginfo->msgmap = atomic_read(&ns->msg_hdrs);
msginfo->msgtql = atomic_read(&ns->msg_bytes);
max_idx = ipc_get_maxidx(&msg_ids(ns));
up_read(&msg_ids(ns).rwsem);
if (cmd == MSG_INFO) {
msginfo->msgmap = min_t(int,
percpu_counter_sum(&ns->percpu_msg_hdrs),
INT_MAX);
msginfo->msgtql = min_t(int,
percpu_counter_sum(&ns->percpu_msg_bytes),
INT_MAX);
} else {
msginfo->msgmap = MSGMAP;
msginfo->msgpool = MSGPOOL;
msginfo->msgtql = MSGTQL;
}
max_idx = ipc_get_maxidx(&msg_ids(ns));
up_read(&msg_ids(ns).rwsem);
return (max_idx < 0) ? 0 : max_idx;
}
......@@ -935,8 +941,8 @@ static long do_msgsnd(int msqid, long mtype, void __user *mtext,
list_add_tail(&msg->m_list, &msq->q_messages);
msq->q_cbytes += msgsz;
msq->q_qnum++;
atomic_add(msgsz, &ns->msg_bytes);
atomic_inc(&ns->msg_hdrs);
percpu_counter_add_local(&ns->percpu_msg_bytes, msgsz);
percpu_counter_add_local(&ns->percpu_msg_hdrs, 1);
}
err = 0;
......@@ -1159,8 +1165,8 @@ static long do_msgrcv(int msqid, void __user *buf, size_t bufsz, long msgtyp, in
msq->q_rtime = ktime_get_real_seconds();
ipc_update_pid(&msq->q_lrpid, task_tgid(current));
msq->q_cbytes -= msg->m_ts;
atomic_sub(msg->m_ts, &ns->msg_bytes);
atomic_dec(&ns->msg_hdrs);
percpu_counter_sub_local(&ns->percpu_msg_bytes, msg->m_ts);
percpu_counter_sub_local(&ns->percpu_msg_hdrs, 1);
ss_wakeup(msq, &wake_q, false);
goto out_unlock0;
......@@ -1297,20 +1303,34 @@ COMPAT_SYSCALL_DEFINE5(msgrcv, int, msqid, compat_uptr_t, msgp,
}
#endif
void msg_init_ns(struct ipc_namespace *ns)
int msg_init_ns(struct ipc_namespace *ns)
{
int ret;
ns->msg_ctlmax = MSGMAX;
ns->msg_ctlmnb = MSGMNB;
ns->msg_ctlmni = MSGMNI;
atomic_set(&ns->msg_bytes, 0);
atomic_set(&ns->msg_hdrs, 0);
ret = percpu_counter_init(&ns->percpu_msg_bytes, 0, GFP_KERNEL);
if (ret)
goto fail_msg_bytes;
ret = percpu_counter_init(&ns->percpu_msg_hdrs, 0, GFP_KERNEL);
if (ret)
goto fail_msg_hdrs;
ipc_init_ids(&ns->ids[IPC_MSG_IDS]);
return 0;
fail_msg_hdrs:
percpu_counter_destroy(&ns->percpu_msg_bytes);
fail_msg_bytes:
return ret;
}
#ifdef CONFIG_IPC_NS
void msg_exit_ns(struct ipc_namespace *ns)
{
percpu_counter_destroy(&ns->percpu_msg_bytes);
percpu_counter_destroy(&ns->percpu_msg_hdrs);
free_ipcs(ns, &msg_ids(ns), freeque);
idr_destroy(&ns->ids[IPC_MSG_IDS].ipcs_idr);
rhashtable_destroy(&ns->ids[IPC_MSG_IDS].key_ht);
......
......@@ -66,8 +66,11 @@ static struct ipc_namespace *create_ipc_ns(struct user_namespace *user_ns,
if (!setup_ipc_sysctls(ns))
goto fail_mq;
err = msg_init_ns(ns);
if (err)
goto fail_put;
sem_init_ns(ns);
msg_init_ns(ns);
shm_init_ns(ns);
return ns;
......
......@@ -782,28 +782,37 @@ struct pid_namespace *ipc_seq_pid_ns(struct seq_file *s)
return iter->pid_ns;
}
/*
* This routine locks the ipc structure found at least at position pos.
/**
* sysvipc_find_ipc - Find and lock the ipc structure based on seq pos
* @ids: ipc identifier set
* @pos: expected position
*
* The function finds an ipc structure, based on the sequence file
* position @pos. If there is no ipc structure at position @pos, then
* the successor is selected.
* If a structure is found, then it is locked (both rcu_read_lock() and
* ipc_lock_object()) and @pos is set to the position needed to locate
* the found ipc structure.
* If nothing is found (i.e. EOF), @pos is not modified.
*
* The function returns the found ipc structure, or NULL at EOF.
*/
static struct kern_ipc_perm *sysvipc_find_ipc(struct ipc_ids *ids, loff_t pos,
loff_t *new_pos)
static struct kern_ipc_perm *sysvipc_find_ipc(struct ipc_ids *ids, loff_t *pos)
{
struct kern_ipc_perm *ipc = NULL;
int max_idx = ipc_get_maxidx(ids);
int tmpidx;
struct kern_ipc_perm *ipc;
if (max_idx == -1 || pos > max_idx)
goto out;
/* convert from position to idr index -> "-1" */
tmpidx = *pos - 1;
for (; pos <= max_idx; pos++) {
ipc = idr_find(&ids->ipcs_idr, pos);
if (ipc != NULL) {
rcu_read_lock();
ipc_lock_object(ipc);
break;
}
ipc = idr_get_next(&ids->ipcs_idr, &tmpidx);
if (ipc != NULL) {
rcu_read_lock();
ipc_lock_object(ipc);
/* convert from idr index to position -> "+1" */
*pos = tmpidx + 1;
}
out:
*new_pos = pos + 1;
return ipc;
}
......@@ -817,11 +826,13 @@ static void *sysvipc_proc_next(struct seq_file *s, void *it, loff_t *pos)
if (ipc && ipc != SEQ_START_TOKEN)
ipc_unlock(ipc);
return sysvipc_find_ipc(&iter->ns->ids[iface->ids], *pos, pos);
/* Next -> search for *pos+1 */
(*pos)++;
return sysvipc_find_ipc(&iter->ns->ids[iface->ids], pos);
}
/*
* File positions: pos 0 -> header, pos n -> ipc id = n - 1.
* File positions: pos 0 -> header, pos n -> ipc idx = n - 1.
* SeqFile iterator: iterator value locked ipc pointer or SEQ_TOKEN_START.
*/
static void *sysvipc_proc_start(struct seq_file *s, loff_t *pos)
......@@ -846,8 +857,8 @@ static void *sysvipc_proc_start(struct seq_file *s, loff_t *pos)
if (*pos == 0)
return SEQ_START_TOKEN;
/* Find the (pos-1)th ipc */
return sysvipc_find_ipc(ids, *pos - 1, pos);
/* Otherwise return the correct ipc structure */
return sysvipc_find_ipc(ids, pos);
}
static void sysvipc_proc_stop(struct seq_file *s, void *it)
......
......@@ -64,7 +64,7 @@ static inline void mq_put_mnt(struct ipc_namespace *ns) { }
#ifdef CONFIG_SYSVIPC
void sem_init_ns(struct ipc_namespace *ns);
void msg_init_ns(struct ipc_namespace *ns);
int msg_init_ns(struct ipc_namespace *ns);
void shm_init_ns(struct ipc_namespace *ns);
void sem_exit_ns(struct ipc_namespace *ns);
......@@ -72,7 +72,7 @@ void msg_exit_ns(struct ipc_namespace *ns);
void shm_exit_ns(struct ipc_namespace *ns);
#else
static inline void sem_init_ns(struct ipc_namespace *ns) { }
static inline void msg_init_ns(struct ipc_namespace *ns) { }
static inline int msg_init_ns(struct ipc_namespace *ns) { return 0; }
static inline void shm_init_ns(struct ipc_namespace *ns) { }
static inline void sem_exit_ns(struct ipc_namespace *ns) { }
......
......@@ -184,6 +184,10 @@ void put_task_struct_rcu_user(struct task_struct *task)
call_rcu(&task->rcu, delayed_put_task_struct);
}
void __weak release_thread(struct task_struct *dead_task)
{
}
void release_task(struct task_struct *p)
{
struct task_struct *leader;
......
......@@ -247,15 +247,11 @@ static ssize_t fei_write(struct file *file, const char __user *buffer,
/* cut off if it is too long */
if (count > KSYM_NAME_LEN)
count = KSYM_NAME_LEN;
buf = kmalloc(count + 1, GFP_KERNEL);
if (!buf)
return -ENOMEM;
if (copy_from_user(buf, buffer, count)) {
ret = -EFAULT;
goto out_free;
}
buf[count] = '\0';
buf = memdup_user_nul(buffer, count);
if (IS_ERR(buf))
return PTR_ERR(buf);
sym = strstrip(buf);
mutex_lock(&fei_lock);
......@@ -298,17 +294,15 @@ static ssize_t fei_write(struct file *file, const char __user *buffer,
}
ret = register_kprobe(&attr->kp);
if (!ret)
fei_debugfs_add_attr(attr);
if (ret < 0)
fei_attr_remove(attr);
else {
list_add_tail(&attr->list, &fei_attr_list);
ret = count;
if (ret) {
fei_attr_free(attr);
goto out;
}
fei_debugfs_add_attr(attr);
list_add_tail(&attr->list, &fei_attr_list);
ret = count;
out:
mutex_unlock(&fei_lock);
out_free:
kfree(buf);
return ret;
}
......
......@@ -97,7 +97,6 @@
#include <linux/scs.h>
#include <linux/io_uring.h>
#include <linux/bpf.h>
#include <linux/sched/mm.h>
#include <asm/pgalloc.h>
#include <linux/uaccess.h>
......
......@@ -93,13 +93,10 @@ static int do_kexec_load(unsigned long entry, unsigned long nr_segments,
/*
* Because we write directly to the reserved memory region when loading
* crash kernels we need a mutex here to prevent multiple crash kernels
* from attempting to load simultaneously, and to prevent a crash kernel
* from loading over the top of a in use crash kernel.
*
* KISS: always take the mutex.
* crash kernels we need a serialization here to prevent multiple crash
* kernels from attempting to load simultaneously.
*/
if (!mutex_trylock(&kexec_mutex))
if (!kexec_trylock())
return -EBUSY;
if (flags & KEXEC_ON_CRASH) {
......@@ -165,7 +162,7 @@ static int do_kexec_load(unsigned long entry, unsigned long nr_segments,
kimage_free(image);
out_unlock:
mutex_unlock(&kexec_mutex);
kexec_unlock();
return ret;
}
......
......@@ -46,7 +46,7 @@
#include <crypto/hash.h>
#include "kexec_internal.h"
DEFINE_MUTEX(kexec_mutex);
atomic_t __kexec_lock = ATOMIC_INIT(0);
/* Per cpu memory for storing cpu states in case of system crash. */
note_buf_t __percpu *crash_notes;
......@@ -809,7 +809,7 @@ static int kimage_load_normal_segment(struct kimage *image,
if (result < 0)
goto out;
ptr = kmap(page);
ptr = kmap_local_page(page);
/* Start with a clear page */
clear_page(ptr);
ptr += maddr & ~PAGE_MASK;
......@@ -822,7 +822,7 @@ static int kimage_load_normal_segment(struct kimage *image,
memcpy(ptr, kbuf, uchunk);
else
result = copy_from_user(ptr, buf, uchunk);
kunmap(page);
kunmap_local(ptr);
if (result) {
result = -EFAULT;
goto out;
......@@ -873,7 +873,7 @@ static int kimage_load_crash_segment(struct kimage *image,
goto out;
}
arch_kexec_post_alloc_pages(page_address(page), 1, 0);
ptr = kmap(page);
ptr = kmap_local_page(page);
ptr += maddr & ~PAGE_MASK;
mchunk = min_t(size_t, mbytes,
PAGE_SIZE - (maddr & ~PAGE_MASK));
......@@ -889,7 +889,7 @@ static int kimage_load_crash_segment(struct kimage *image,
else
result = copy_from_user(ptr, buf, uchunk);
kexec_flush_icache_page(page);
kunmap(page);
kunmap_local(ptr);
arch_kexec_pre_free_pages(page_address(page), 1);
if (result) {
result = -EFAULT;
......@@ -959,7 +959,7 @@ late_initcall(kexec_core_sysctl_init);
*/
void __noclone __crash_kexec(struct pt_regs *regs)
{
/* Take the kexec_mutex here to prevent sys_kexec_load
/* Take the kexec_lock here to prevent sys_kexec_load
* running on one cpu from replacing the crash kernel
* we are using after a panic on a different cpu.
*
......@@ -967,7 +967,7 @@ void __noclone __crash_kexec(struct pt_regs *regs)
* of memory the xchg(&kexec_crash_image) would be
* sufficient. But since I reuse the memory...
*/
if (mutex_trylock(&kexec_mutex)) {
if (kexec_trylock()) {
if (kexec_crash_image) {
struct pt_regs fixed_regs;
......@@ -976,7 +976,7 @@ void __noclone __crash_kexec(struct pt_regs *regs)
machine_crash_shutdown(&fixed_regs);
machine_kexec(kexec_crash_image);
}
mutex_unlock(&kexec_mutex);
kexec_unlock();
}
}
STACK_FRAME_NON_STANDARD(__crash_kexec);
......@@ -1004,14 +1004,17 @@ void crash_kexec(struct pt_regs *regs)
}
}
size_t crash_get_memory_size(void)
ssize_t crash_get_memory_size(void)
{
size_t size = 0;
ssize_t size = 0;
if (!kexec_trylock())
return -EBUSY;
mutex_lock(&kexec_mutex);
if (crashk_res.end != crashk_res.start)
size = resource_size(&crashk_res);
mutex_unlock(&kexec_mutex);
kexec_unlock();
return size;
}
......@@ -1022,7 +1025,8 @@ int crash_shrink_memory(unsigned long new_size)
unsigned long old_size;
struct resource *ram_res;
mutex_lock(&kexec_mutex);
if (!kexec_trylock())
return -EBUSY;
if (kexec_crash_image) {
ret = -ENOENT;
......@@ -1060,7 +1064,7 @@ int crash_shrink_memory(unsigned long new_size)
insert_resource(&iomem_resource, ram_res);
unlock:
mutex_unlock(&kexec_mutex);
kexec_unlock();
return ret;
}
......@@ -1132,7 +1136,7 @@ int kernel_kexec(void)
{
int error = 0;
if (!mutex_trylock(&kexec_mutex))
if (!kexec_trylock())
return -EBUSY;
if (!kexec_image) {
error = -EINVAL;
......@@ -1208,6 +1212,6 @@ int kernel_kexec(void)
#endif
Unlock:
mutex_unlock(&kexec_mutex);
kexec_unlock();
return error;
}
......@@ -339,7 +339,7 @@ SYSCALL_DEFINE5(kexec_file_load, int, kernel_fd, int, initrd_fd,
image = NULL;
if (!mutex_trylock(&kexec_mutex))
if (!kexec_trylock())
return -EBUSY;
dest_image = &kexec_image;
......@@ -411,7 +411,7 @@ SYSCALL_DEFINE5(kexec_file_load, int, kernel_fd, int, initrd_fd,
if ((flags & KEXEC_FILE_ON_CRASH) && kexec_crash_image)
arch_kexec_protect_crashkres();
mutex_unlock(&kexec_mutex);
kexec_unlock();
kimage_free(image);
return ret;
}
......
......@@ -13,7 +13,20 @@ void kimage_terminate(struct kimage *image);
int kimage_is_destination_range(struct kimage *image,
unsigned long start, unsigned long end);
extern struct mutex kexec_mutex;
/*
* Whatever is used to serialize accesses to the kexec_crash_image needs to be
* NMI safe, as __crash_kexec() can happen during nmi_panic(), so here we use a
* "simple" atomic variable that is acquired with a cmpxchg().
*/
extern atomic_t __kexec_lock;
static inline bool kexec_trylock(void)
{
return atomic_cmpxchg_acquire(&__kexec_lock, 0, 1) == 0;
}
static inline void kexec_unlock(void)
{
atomic_set_release(&__kexec_lock, 0);
}
#ifdef CONFIG_KEXEC_FILE
#include <linux/purgatory.h>
......
......@@ -105,7 +105,12 @@ KERNEL_ATTR_RO(kexec_crash_loaded);
static ssize_t kexec_crash_size_show(struct kobject *kobj,
struct kobj_attribute *attr, char *buf)
{
return sprintf(buf, "%zu\n", crash_get_memory_size());
ssize_t size = crash_get_memory_size();
if (size < 0)
return size;
return sprintf(buf, "%zd\n", size);
}
static ssize_t kexec_crash_size_store(struct kobject *kobj,
struct kobj_attribute *attr,
......
......@@ -112,7 +112,7 @@ static void __sched
account_global_scheduler_latency(struct task_struct *tsk,
struct latency_record *lat)
{
int firstnonnull = MAXLR + 1;
int firstnonnull = MAXLR;
int i;
/* skip kernel threads for now */
......@@ -150,7 +150,7 @@ account_global_scheduler_latency(struct task_struct *tsk,
}
i = firstnonnull;
if (i >= MAXLR - 1)
if (i >= MAXLR)
return;
/* Allocted a new one: */
......
......@@ -59,43 +59,39 @@ int profile_setup(char *str)
static const char schedstr[] = "schedule";
static const char sleepstr[] = "sleep";
static const char kvmstr[] = "kvm";
const char *select = NULL;
int par;
if (!strncmp(str, sleepstr, strlen(sleepstr))) {
#ifdef CONFIG_SCHEDSTATS
force_schedstat_enabled();
prof_on = SLEEP_PROFILING;
if (str[strlen(sleepstr)] == ',')
str += strlen(sleepstr) + 1;
if (get_option(&str, &par))
prof_shift = clamp(par, 0, BITS_PER_LONG - 1);
pr_info("kernel sleep profiling enabled (shift: %u)\n",
prof_shift);
select = sleepstr;
#else
pr_warn("kernel sleep profiling requires CONFIG_SCHEDSTATS\n");
#endif /* CONFIG_SCHEDSTATS */
} else if (!strncmp(str, schedstr, strlen(schedstr))) {
prof_on = SCHED_PROFILING;
if (str[strlen(schedstr)] == ',')
str += strlen(schedstr) + 1;
if (get_option(&str, &par))
prof_shift = clamp(par, 0, BITS_PER_LONG - 1);
pr_info("kernel schedule profiling enabled (shift: %u)\n",
prof_shift);
select = schedstr;
} else if (!strncmp(str, kvmstr, strlen(kvmstr))) {
prof_on = KVM_PROFILING;
if (str[strlen(kvmstr)] == ',')
str += strlen(kvmstr) + 1;
if (get_option(&str, &par))
prof_shift = clamp(par, 0, BITS_PER_LONG - 1);
pr_info("kernel KVM profiling enabled (shift: %u)\n",
prof_shift);
select = kvmstr;
} else if (get_option(&str, &par)) {
prof_shift = clamp(par, 0, BITS_PER_LONG - 1);
prof_on = CPU_PROFILING;
pr_info("kernel profiling enabled (shift: %u)\n",
prof_shift);
}
if (select) {
if (str[strlen(select)] == ',')
str += strlen(select) + 1;
if (get_option(&str, &par))
prof_shift = clamp(par, 0, BITS_PER_LONG - 1);
pr_info("kernel %s profiling enabled (shift: %u)\n",
select, prof_shift);
}
return 1;
}
__setup("profile=", profile_setup);
......
......@@ -60,10 +60,7 @@ static const struct vm_operations_struct relay_file_mmap_ops = {
*/
static struct page **relay_alloc_page_array(unsigned int n_pages)
{
const size_t pa_size = n_pages * sizeof(struct page *);
if (pa_size > PAGE_SIZE)
return vzalloc(pa_size);
return kzalloc(pa_size, GFP_KERNEL);
return kvcalloc(n_pages, sizeof(struct page *), GFP_KERNEL);
}
/*
......
......@@ -433,7 +433,7 @@ bool cpu_wait_death(unsigned int cpu, int seconds)
/* The outgoing CPU will normally get done quite quickly. */
if (atomic_read(&per_cpu(cpu_hotplug_state, cpu)) == CPU_DEAD)
goto update_state;
goto update_state_early;
udelay(5);
/* But if the outgoing CPU dawdles, wait increasingly long times. */
......@@ -444,16 +444,17 @@ bool cpu_wait_death(unsigned int cpu, int seconds)
break;
sleep_jf = DIV_ROUND_UP(sleep_jf * 11, 10);
}
update_state:
update_state_early:
oldstate = atomic_read(&per_cpu(cpu_hotplug_state, cpu));
update_state:
if (oldstate == CPU_DEAD) {
/* Outgoing CPU died normally, update state. */
smp_mb(); /* atomic_read() before update. */
atomic_set(&per_cpu(cpu_hotplug_state, cpu), CPU_POST_DEAD);
} else {
/* Outgoing CPU still hasn't died, set state accordingly. */
if (atomic_cmpxchg(&per_cpu(cpu_hotplug_state, cpu),
oldstate, CPU_BROKEN) != oldstate)
if (!atomic_try_cmpxchg(&per_cpu(cpu_hotplug_state, cpu),
&oldstate, CPU_BROKEN))
goto update_state;
ret = false;
}
......@@ -475,14 +476,14 @@ bool cpu_report_death(void)
int newstate;
int cpu = smp_processor_id();
oldstate = atomic_read(&per_cpu(cpu_hotplug_state, cpu));
do {
oldstate = atomic_read(&per_cpu(cpu_hotplug_state, cpu));
if (oldstate != CPU_BROKEN)
newstate = CPU_DEAD;
else
newstate = CPU_DEAD_FROZEN;
} while (atomic_cmpxchg(&per_cpu(cpu_hotplug_state, cpu),
oldstate, newstate) != oldstate);
} while (!atomic_try_cmpxchg(&per_cpu(cpu_hotplug_state, cpu),
&oldstate, newstate));
return newstate == CPU_DEAD;
}
......
......@@ -47,12 +47,12 @@ int task_work_add(struct task_struct *task, struct callback_head *work,
/* record the work call stack in order to print it in KASAN reports */
kasan_record_aux_stack(work);
head = READ_ONCE(task->task_works);
do {
head = READ_ONCE(task->task_works);
if (unlikely(head == &work_exited))
return -ESRCH;
work->next = head;
} while (cmpxchg(&task->task_works, head, work) != head);
} while (!try_cmpxchg(&task->task_works, &head, work));
switch (notify) {
case TWA_NONE:
......@@ -100,10 +100,12 @@ task_work_cancel_match(struct task_struct *task,
* we raced with task_work_run(), *pprev == NULL/exited.
*/
raw_spin_lock_irqsave(&task->pi_lock, flags);
while ((work = READ_ONCE(*pprev))) {
if (!match(work, data))
work = READ_ONCE(*pprev);
while (work) {
if (!match(work, data)) {
pprev = &work->next;
else if (cmpxchg(pprev, work, work->next) == work)
work = READ_ONCE(*pprev);
} else if (try_cmpxchg(pprev, &work, work->next))
break;
}
raw_spin_unlock_irqrestore(&task->pi_lock, flags);
......@@ -151,16 +153,16 @@ void task_work_run(void)
* work->func() can do task_work_add(), do not set
* work_exited unless the list is empty.
*/
work = READ_ONCE(task->task_works);
do {
head = NULL;
work = READ_ONCE(task->task_works);
if (!work) {
if (task->flags & PF_EXITING)
head = &work_exited;
else
break;
}
} while (cmpxchg(&task->task_works, work, head) != work);
} while (!try_cmpxchg(&task->task_works, &work, head));
if (!work)
break;
......
......@@ -75,6 +75,13 @@ static DEFINE_CTL_TABLE_POLL(hostname_poll);
static DEFINE_CTL_TABLE_POLL(domainname_poll);
static struct ctl_table uts_kern_table[] = {
{
.procname = "arch",
.data = init_uts_ns.name.machine,
.maxlen = sizeof(init_uts_ns.name.machine),
.mode = 0444,
.proc_handler = proc_do_uts_string,
},
{
.procname = "ostype",
.data = init_uts_ns.name.sysname,
......
......@@ -260,7 +260,7 @@ char *next_arg(char *args, char **param, char **val)
args[i-1] = '\0';
}
}
if (quoted && args[i-1] == '"')
if (quoted && i > 0 && args[i-1] == '"')
args[i-1] = '\0';
if (args[i]) {
......
......@@ -126,7 +126,7 @@ struct cpio_data find_cpio_data(const char *path, void *data,
"File %s exceeding MAX_CPIO_FILE_NAME [%d]\n",
p, MAX_CPIO_FILE_NAME);
}
strlcpy(cd.name, p + mypathsize, MAX_CPIO_FILE_NAME);
strscpy(cd.name, p + mypathsize, MAX_CPIO_FILE_NAME);
cd.data = (void *)dptr;
cd.size = ch[C_FILESIZE];
......
......@@ -30,7 +30,7 @@ bool llist_add_batch(struct llist_node *new_first, struct llist_node *new_last,
do {
new_last->next = first = READ_ONCE(head->first);
} while (cmpxchg(&head->first, first, new_first) != first);
} while (!try_cmpxchg(&head->first, &first, new_first));
return !first;
}
......@@ -52,18 +52,14 @@ EXPORT_SYMBOL_GPL(llist_add_batch);
*/
struct llist_node *llist_del_first(struct llist_head *head)
{
struct llist_node *entry, *old_entry, *next;
struct llist_node *entry, *next;
entry = smp_load_acquire(&head->first);
for (;;) {
do {
if (entry == NULL)
return NULL;
old_entry = entry;
next = READ_ONCE(entry->next);
entry = cmpxchg(&head->first, old_entry, next);
if (entry == old_entry)
break;
}
} while (!try_cmpxchg(&head->first, &entry, next));
return entry;
}
......
......@@ -576,10 +576,14 @@ our $typeKernelTypedefs = qr{(?x:
(?:__)?(?:u|s|be|le)(?:8|16|32|64)|
atomic_t
)};
our $typeStdioTypedefs = qr{(?x:
FILE
)};
our $typeTypedefs = qr{(?x:
$typeC99Typedefs\b|
$typeOtherOSTypedefs\b|
$typeKernelTypedefs\b
$typeKernelTypedefs\b|
$typeStdioTypedefs\b
)};
our $zero_initializer = qr{(?:(?:0[xX])?0+$Int_type?|NULL|false)\b};
......@@ -807,6 +811,8 @@ our %deprecated_apis = (
"rcu_barrier_sched" => "rcu_barrier",
"get_state_synchronize_sched" => "get_state_synchronize_rcu",
"cond_synchronize_sched" => "cond_synchronize_rcu",
"kmap" => "kmap_local_page",
"kmap_atomic" => "kmap_local_page",
);
#Create a search pattern for all these strings to speed up a loop below
......@@ -3140,6 +3146,50 @@ sub process {
}
}
# Check Fixes: styles is correct
if (!$in_header_lines &&
$line =~ /^\s*fixes:?\s*(?:commit\s*)?[0-9a-f]{5,}\b/i) {
my $orig_commit = "";
my $id = "0123456789ab";
my $title = "commit title";
my $tag_case = 1;
my $tag_space = 1;
my $id_length = 1;
my $id_case = 1;
my $title_has_quotes = 0;
if ($line =~ /(\s*fixes:?)\s+([0-9a-f]{5,})\s+($balanced_parens)/i) {
my $tag = $1;
$orig_commit = $2;
$title = $3;
$tag_case = 0 if $tag eq "Fixes:";
$tag_space = 0 if ($line =~ /^fixes:? [0-9a-f]{5,} ($balanced_parens)/i);
$id_length = 0 if ($orig_commit =~ /^[0-9a-f]{12}$/i);
$id_case = 0 if ($orig_commit !~ /[A-F]/);
# Always strip leading/trailing parens then double quotes if existing
$title = substr($title, 1, -1);
if ($title =~ /^".*"$/) {
$title = substr($title, 1, -1);
$title_has_quotes = 1;
}
}
my ($cid, $ctitle) = git_commit_info($orig_commit, $id,
$title);
if ($ctitle ne $title || $tag_case || $tag_space ||
$id_length || $id_case || !$title_has_quotes) {
if (WARN("BAD_FIXES_TAG",
"Please use correct Fixes: style 'Fixes: <12 chars of sha1> (\"<title line>\")' - ie: 'Fixes: $cid (\"$ctitle\")'\n" . $herecurr) &&
$fix) {
$fixed[$fixlinenr] = "Fixes: $cid (\"$ctitle\")";
}
}
}
# Check email subject for common tools that don't need to be mentioned
if ($in_header_lines &&
$line =~ /^Subject:.*\b(?:checkpatch|sparse|smatch)\b[^:]/i) {
......
#!/bin/sh
#!/bin/bash
# SPDX-License-Identifier: GPL-2.0
# Disassemble the Code: line in Linux oopses
# usage: decodecode < oops.file
......@@ -8,6 +8,8 @@
# AFLAGS=--32 decodecode < 386.oops
# PC=hex - the PC (program counter) the oops points to
faultlinenum=1
cleanup() {
rm -f $T $T.s $T.o $T.oo $T.aa $T.dis
exit 1
......@@ -102,28 +104,125 @@ disas() {
grep -v "/tmp\|Disassembly\|\.text\|^$" > $t.dis 2>&1
}
# Match the maximum number of opcode bytes from @op_bytes contained within
# @opline
#
# Params:
# @op_bytes: The string of bytes from the Code: line
# @opline: The disassembled line coming from objdump
#
# Returns:
# The max number of opcode bytes from the beginning of @op_bytes which match
# the opcode bytes in the objdump line.
get_substr_opcode_bytes_num()
{
local op_bytes=$1
local opline=$2
local retval=0
substr=""
for opc in $op_bytes;
do
substr+="$opc"
# return if opcode bytes do not match @opline anymore
if ! echo $opline | grep -q "$substr";
then
break
fi
# add trailing space
substr+=" "
retval=$((retval+1))
done
return $retval
}
# Return the line number in objdump output to where the IP marker in the Code:
# line points to
#
# Params:
# @all_code: code in bytes without the marker
# @dis_file: disassembled file
# @ip_byte: The byte to which the IP points to
get_faultlinenum()
{
local all_code="$1"
local dis_file="$2"
# num bytes including IP byte
local num_bytes_ip=$(( $3 + 1 * $width ))
# Add the two header lines (we're counting from 1).
local retval=3
# remove marker
all_code=$(echo $all_code | sed -e 's/[<>()]//g')
while read line
do
get_substr_opcode_bytes_num "$all_code" "$line"
ate_opcodes=$?
if ! (( $ate_opcodes )); then
continue
fi
num_bytes_ip=$((num_bytes_ip - ($ate_opcodes * $width) ))
if (( $num_bytes_ip <= 0 )); then
break
fi
# Delete matched opcode bytes from all_code. For that, compute
# how many chars those opcodes are represented by and include
# trailing space.
#
# a byte is 2 chars, ate_opcodes is also the number of trailing
# spaces
del_chars=$(( ($ate_opcodes * $width * 2) + $ate_opcodes ))
all_code=$(echo $all_code | sed -e "s!^.\{$del_chars\}!!")
let "retval+=1"
done < $dis_file
return $retval
}
marker=`expr index "$code" "\<"`
if [ $marker -eq 0 ]; then
marker=`expr index "$code" "\("`
fi
touch $T.oo
if [ $marker -ne 0 ]; then
# 2 opcode bytes and a single space
pc_sub=$(( $marker / 3 ))
# How many bytes to subtract from the program counter
# in order to get to the beginning virtual address of the
# Code:
pc_sub=$(( (($marker - 1) / (2 * $width + 1)) * $width ))
echo All code >> $T.oo
echo ======== >> $T.oo
beforemark=`echo "$code"`
echo -n " .$type 0x" > $T.s
echo $beforemark | sed -e 's/ /,0x/g; s/[<>()]//g' >> $T.s
disas $T $pc_sub
cat $T.dis >> $T.oo
rm -f $T.o $T.s $T.dis
# and fix code at-and-after marker
get_faultlinenum "$code" "$T.dis" $pc_sub
faultlinenum=$?
# and fix code at-and-after marker
code=`echo "$code" | cut -c$((${marker} + 1))-`
rm -f $T.o $T.s $T.dis
fi
echo Code starting with the faulting instruction > $T.aa
echo =========================================== >> $T.aa
code=`echo $code | sed -e 's/\r//;s/ [<(]/ /;s/[>)] / /;s/ /,0x/g; s/[>)]$//'`
......@@ -132,15 +231,6 @@ echo $code >> $T.s
disas $T 0
cat $T.dis >> $T.aa
# (lines of whole $T.oo) - (lines of $T.aa, i.e. "Code starting") + 3,
# i.e. the title + the "===..=" line (sed is counting from 1, 0 address is
# special)
faultlinenum=$(( $(wc -l $T.oo | cut -d" " -f1) - \
$(wc -l $T.aa | cut -d" " -f1) + 3))
faultline=`cat $T.dis | head -1 | cut -d":" -f2-`
faultline=`echo "$faultline" | sed -e 's/\[/\\\[/g; s/\]/\\\]/g'`
cat $T.oo | sed -e "${faultlinenum}s/^\([^:]*:\)\(.*\)/\1\*\2\t\t<-- trapping instruction/"
echo
cat $T.aa
......
......@@ -5,6 +5,7 @@
/proc-fsconfig-hidepid
/proc-loadavg-001
/proc-multiple-procfs
/proc-empty-vm
/proc-pid-vm
/proc-self-map-files-001
/proc-self-map-files-002
......
......@@ -8,6 +8,7 @@ TEST_GEN_PROGS += fd-001-lookup
TEST_GEN_PROGS += fd-002-posix-eq
TEST_GEN_PROGS += fd-003-kthread
TEST_GEN_PROGS += proc-loadavg-001
TEST_GEN_PROGS += proc-empty-vm
TEST_GEN_PROGS += proc-pid-vm
TEST_GEN_PROGS += proc-self-map-files-001
TEST_GEN_PROGS += proc-self-map-files-002
......
/*
* Copyright (c) 2022 Alexey Dobriyan <adobriyan@gmail.com>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*
* Create a process without mappings by unmapping everything at once and
* holding it with ptrace(2). See what happens to
*
* /proc/${pid}/maps
* /proc/${pid}/numa_maps
* /proc/${pid}/smaps
* /proc/${pid}/smaps_rollup
*/
#undef NDEBUG
#include <assert.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/ptrace.h>
#include <sys/resource.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
/*
* 0: vsyscall VMA doesn't exist vsyscall=none
* 1: vsyscall VMA is --xp vsyscall=xonly
* 2: vsyscall VMA is r-xp vsyscall=emulate
*/
static int g_vsyscall;
static const char *g_proc_pid_maps_vsyscall;
static const char *g_proc_pid_smaps_vsyscall;
static const char proc_pid_maps_vsyscall_0[] = "";
static const char proc_pid_maps_vsyscall_1[] =
"ffffffffff600000-ffffffffff601000 --xp 00000000 00:00 0 [vsyscall]\n";
static const char proc_pid_maps_vsyscall_2[] =
"ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall]\n";
static const char proc_pid_smaps_vsyscall_0[] = "";
static const char proc_pid_smaps_vsyscall_1[] =
"ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall]\n"
"Size: 4 kB\n"
"KernelPageSize: 4 kB\n"
"MMUPageSize: 4 kB\n"
"Rss: 0 kB\n"
"Pss: 0 kB\n"
"Pss_Dirty: 0 kB\n"
"Shared_Clean: 0 kB\n"
"Shared_Dirty: 0 kB\n"
"Private_Clean: 0 kB\n"
"Private_Dirty: 0 kB\n"
"Referenced: 0 kB\n"
"Anonymous: 0 kB\n"
"LazyFree: 0 kB\n"
"AnonHugePages: 0 kB\n"
"ShmemPmdMapped: 0 kB\n"
"FilePmdMapped: 0 kB\n"
"Shared_Hugetlb: 0 kB\n"
"Private_Hugetlb: 0 kB\n"
"Swap: 0 kB\n"
"SwapPss: 0 kB\n"
"Locked: 0 kB\n"
"THPeligible: 0\n"
/*
* "ProtectionKey:" field is conditional. It is possible to check it as well,
* but I don't have such machine.
*/
;
static const char proc_pid_smaps_vsyscall_2[] =
"ffffffffff600000-ffffffffff601000 --xp 00000000 00:00 0 [vsyscall]\n"
"Size: 4 kB\n"
"KernelPageSize: 4 kB\n"
"MMUPageSize: 4 kB\n"
"Rss: 0 kB\n"
"Pss: 0 kB\n"
"Pss_Dirty: 0 kB\n"
"Shared_Clean: 0 kB\n"
"Shared_Dirty: 0 kB\n"
"Private_Clean: 0 kB\n"
"Private_Dirty: 0 kB\n"
"Referenced: 0 kB\n"
"Anonymous: 0 kB\n"
"LazyFree: 0 kB\n"
"AnonHugePages: 0 kB\n"
"ShmemPmdMapped: 0 kB\n"
"FilePmdMapped: 0 kB\n"
"Shared_Hugetlb: 0 kB\n"
"Private_Hugetlb: 0 kB\n"
"Swap: 0 kB\n"
"SwapPss: 0 kB\n"
"Locked: 0 kB\n"
"THPeligible: 0\n"
/*
* "ProtectionKey:" field is conditional. It is possible to check it as well,
* but I'm too tired.
*/
;
static void sigaction_SIGSEGV(int _, siginfo_t *__, void *___)
{
_exit(EXIT_FAILURE);
}
static void sigaction_SIGSEGV_vsyscall(int _, siginfo_t *__, void *___)
{
_exit(g_vsyscall);
}
/*
* vsyscall page can't be unmapped, probe it directly.
*/
static void vsyscall(void)
{
pid_t pid;
int wstatus;
pid = fork();
if (pid < 0) {
fprintf(stderr, "fork, errno %d\n", errno);
exit(1);
}
if (pid == 0) {
setrlimit(RLIMIT_CORE, &(struct rlimit){});
/* Hide "segfault at ffffffffff600000" messages. */
struct sigaction act = {};
act.sa_flags = SA_SIGINFO;
act.sa_sigaction = sigaction_SIGSEGV_vsyscall;
sigaction(SIGSEGV, &act, NULL);
g_vsyscall = 0;
/* gettimeofday(NULL, NULL); */
asm volatile (
"call %P0"
:
: "i" (0xffffffffff600000), "D" (NULL), "S" (NULL)
: "rax", "rcx", "r11"
);
g_vsyscall = 1;
*(volatile int *)0xffffffffff600000UL;
g_vsyscall = 2;
exit(g_vsyscall);
}
waitpid(pid, &wstatus, 0);
if (WIFEXITED(wstatus)) {
g_vsyscall = WEXITSTATUS(wstatus);
} else {
fprintf(stderr, "error: vsyscall wstatus %08x\n", wstatus);
exit(1);
}
}
static int test_proc_pid_maps(pid_t pid)
{
char buf[4096];
snprintf(buf, sizeof(buf), "/proc/%u/maps", pid);
int fd = open(buf, O_RDONLY);
if (fd == -1) {
perror("open /proc/${pid}/maps");
return EXIT_FAILURE;
} else {
ssize_t rv = read(fd, buf, sizeof(buf));
close(fd);
if (g_vsyscall == 0) {
assert(rv == 0);
} else {
size_t len = strlen(g_proc_pid_maps_vsyscall);
assert(rv == len);
assert(memcmp(buf, g_proc_pid_maps_vsyscall, len) == 0);
}
return EXIT_SUCCESS;
}
}
static int test_proc_pid_numa_maps(pid_t pid)
{
char buf[4096];
snprintf(buf, sizeof(buf), "/proc/%u/numa_maps", pid);
int fd = open(buf, O_RDONLY);
if (fd == -1) {
if (errno == ENOENT) {
/*
* /proc/${pid}/numa_maps is under CONFIG_NUMA,
* it doesn't necessarily exist.
*/
return EXIT_SUCCESS;
}
perror("open /proc/${pid}/numa_maps");
return EXIT_FAILURE;
} else {
ssize_t rv = read(fd, buf, sizeof(buf));
close(fd);
assert(rv == 0);
return EXIT_SUCCESS;
}
}
static int test_proc_pid_smaps(pid_t pid)
{
char buf[4096];
snprintf(buf, sizeof(buf), "/proc/%u/smaps", pid);
int fd = open(buf, O_RDONLY);
if (fd == -1) {
if (errno == ENOENT) {
/*
* /proc/${pid}/smaps is under CONFIG_PROC_PAGE_MONITOR,
* it doesn't necessarily exist.
*/
return EXIT_SUCCESS;
}
perror("open /proc/${pid}/smaps");
return EXIT_FAILURE;
} else {
ssize_t rv = read(fd, buf, sizeof(buf));
close(fd);
if (g_vsyscall == 0) {
assert(rv == 0);
} else {
size_t len = strlen(g_proc_pid_maps_vsyscall);
/* TODO "ProtectionKey:" */
assert(rv > len);
assert(memcmp(buf, g_proc_pid_maps_vsyscall, len) == 0);
}
return EXIT_SUCCESS;
}
}
static const char g_smaps_rollup[] =
"00000000-00000000 ---p 00000000 00:00 0 [rollup]\n"
"Rss: 0 kB\n"
"Pss: 0 kB\n"
"Pss_Dirty: 0 kB\n"
"Pss_Anon: 0 kB\n"
"Pss_File: 0 kB\n"
"Pss_Shmem: 0 kB\n"
"Shared_Clean: 0 kB\n"
"Shared_Dirty: 0 kB\n"
"Private_Clean: 0 kB\n"
"Private_Dirty: 0 kB\n"
"Referenced: 0 kB\n"
"Anonymous: 0 kB\n"
"LazyFree: 0 kB\n"
"AnonHugePages: 0 kB\n"
"ShmemPmdMapped: 0 kB\n"
"FilePmdMapped: 0 kB\n"
"Shared_Hugetlb: 0 kB\n"
"Private_Hugetlb: 0 kB\n"
"Swap: 0 kB\n"
"SwapPss: 0 kB\n"
"Locked: 0 kB\n"
;
static int test_proc_pid_smaps_rollup(pid_t pid)
{
char buf[4096];
snprintf(buf, sizeof(buf), "/proc/%u/smaps_rollup", pid);
int fd = open(buf, O_RDONLY);
if (fd == -1) {
if (errno == ENOENT) {
/*
* /proc/${pid}/smaps_rollup is under CONFIG_PROC_PAGE_MONITOR,
* it doesn't necessarily exist.
*/
return EXIT_SUCCESS;
}
perror("open /proc/${pid}/smaps_rollup");
return EXIT_FAILURE;
} else {
ssize_t rv = read(fd, buf, sizeof(buf));
close(fd);
assert(rv == sizeof(g_smaps_rollup) - 1);
assert(memcmp(buf, g_smaps_rollup, sizeof(g_smaps_rollup) - 1) == 0);
return EXIT_SUCCESS;
}
}
int main(void)
{
int rv = EXIT_SUCCESS;
vsyscall();
switch (g_vsyscall) {
case 0:
g_proc_pid_maps_vsyscall = proc_pid_maps_vsyscall_0;
g_proc_pid_smaps_vsyscall = proc_pid_smaps_vsyscall_0;
break;
case 1:
g_proc_pid_maps_vsyscall = proc_pid_maps_vsyscall_1;
g_proc_pid_smaps_vsyscall = proc_pid_smaps_vsyscall_1;
break;
case 2:
g_proc_pid_maps_vsyscall = proc_pid_maps_vsyscall_2;
g_proc_pid_smaps_vsyscall = proc_pid_smaps_vsyscall_2;
break;
default:
abort();
}
pid_t pid = fork();
if (pid == -1) {
perror("fork");
return EXIT_FAILURE;
} else if (pid == 0) {
rv = ptrace(PTRACE_TRACEME, 0, NULL, NULL);
if (rv != 0) {
if (errno == EPERM) {
fprintf(stderr,
"Did you know? ptrace(PTRACE_TRACEME) doesn't work under strace.\n"
);
kill(getppid(), SIGTERM);
return EXIT_FAILURE;
}
perror("ptrace PTRACE_TRACEME");
return EXIT_FAILURE;
}
/*
* Hide "segfault at ..." messages. Signal handler won't run.
*/
struct sigaction act = {};
act.sa_flags = SA_SIGINFO;
act.sa_sigaction = sigaction_SIGSEGV;
sigaction(SIGSEGV, &act, NULL);
#ifdef __amd64__
munmap(NULL, ((size_t)1 << 47) - 4096);
#else
#error "implement 'unmap everything'"
#endif
return EXIT_FAILURE;
} else {
/*
* TODO find reliable way to signal parent that munmap(2) completed.
* Child can't do it directly because it effectively doesn't exist
* anymore. Looking at child's VM files isn't 100% reliable either:
* due to a bug they may not become empty or empty-like.
*/
sleep(1);
if (rv == EXIT_SUCCESS) {
rv = test_proc_pid_maps(pid);
}
if (rv == EXIT_SUCCESS) {
rv = test_proc_pid_numa_maps(pid);
}
if (rv == EXIT_SUCCESS) {
rv = test_proc_pid_smaps(pid);
}
if (rv == EXIT_SUCCESS) {
rv = test_proc_pid_smaps_rollup(pid);
}
/*
* TODO test /proc/${pid}/statm, task_statm()
* ->start_code, ->end_code aren't updated by munmap().
* Output can be "0 0 0 2 0 0 0\n" where "2" can be anything.
*/
/* Cut the rope. */
int wstatus;
waitpid(pid, &wstatus, 0);
assert(WIFSTOPPED(wstatus));
assert(WSTOPSIG(wstatus) == SIGSEGV);
}
return rv;
}
......@@ -213,22 +213,22 @@ static int make_exe(const uint8_t *payload, size_t len)
/*
* 0: vsyscall VMA doesn't exist vsyscall=none
* 1: vsyscall VMA is r-xp vsyscall=emulate
* 2: vsyscall VMA is --xp vsyscall=xonly
* 1: vsyscall VMA is --xp vsyscall=xonly
* 2: vsyscall VMA is r-xp vsyscall=emulate
*/
static int g_vsyscall;
static volatile int g_vsyscall;
static const char *str_vsyscall;
static const char str_vsyscall_0[] = "";
static const char str_vsyscall_1[] =
"ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall]\n";
static const char str_vsyscall_2[] =
"ffffffffff600000-ffffffffff601000 --xp 00000000 00:00 0 [vsyscall]\n";
static const char str_vsyscall_2[] =
"ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall]\n";
#ifdef __x86_64__
static void sigaction_SIGSEGV(int _, siginfo_t *__, void *___)
{
_exit(1);
_exit(g_vsyscall);
}
/*
......@@ -255,6 +255,7 @@ static void vsyscall(void)
act.sa_sigaction = sigaction_SIGSEGV;
(void)sigaction(SIGSEGV, &act, NULL);
g_vsyscall = 0;
/* gettimeofday(NULL, NULL); */
asm volatile (
"call %P0"
......@@ -262,45 +263,20 @@ static void vsyscall(void)
: "i" (0xffffffffff600000), "D" (NULL), "S" (NULL)
: "rax", "rcx", "r11"
);
exit(0);
}
waitpid(pid, &wstatus, 0);
if (WIFEXITED(wstatus) && WEXITSTATUS(wstatus) == 0) {
/* vsyscall page exists and is executable. */
} else {
/* vsyscall page doesn't exist. */
g_vsyscall = 0;
return;
}
pid = fork();
if (pid < 0) {
fprintf(stderr, "fork, errno %d\n", errno);
exit(1);
}
if (pid == 0) {
struct rlimit rlim = {0, 0};
(void)setrlimit(RLIMIT_CORE, &rlim);
/* Hide "segfault at ffffffffff600000" messages. */
struct sigaction act;
memset(&act, 0, sizeof(struct sigaction));
act.sa_flags = SA_SIGINFO;
act.sa_sigaction = sigaction_SIGSEGV;
(void)sigaction(SIGSEGV, &act, NULL);
g_vsyscall = 1;
*(volatile int *)0xffffffffff600000UL;
exit(0);
g_vsyscall = 2;
exit(g_vsyscall);
}
waitpid(pid, &wstatus, 0);
if (WIFEXITED(wstatus) && WEXITSTATUS(wstatus) == 0) {
/* vsyscall page is readable and executable. */
g_vsyscall = 1;
return;
if (WIFEXITED(wstatus)) {
g_vsyscall = WEXITSTATUS(wstatus);
} else {
fprintf(stderr, "error: wstatus %08x\n", wstatus);
exit(1);
}
/* vsyscall page is executable but unreadable. */
g_vsyscall = 2;
}
int main(void)
......
......@@ -326,7 +326,7 @@ static int cpio_mkfile(const char *name, const char *location,
char s[256];
struct stat buf;
unsigned long size;
int file = -1;
int file;
int retval;
int rc = -1;
int namesize;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册