Dear RT folks! I'm pleased to announce the v4.8.2-rt3 patch set. Changes since v4.8.2-rt2: - The connector subsystem could sleep in invalid context. Found and fixed by Mike Galbraith - zram / zcomp has shown new warnings. The warnings have been addressed and an old error fixed (Mike Galbraith) - The ftrace header was off slightly and the ascii arrow were point to the wrong direction (Mike Galbraith) - On CPU-down (CPU hotplug) we could attempt to sleep in wrong context. (Mike Galbraith) - Removed an unused static variable in RXPRC (noticed by kbuild test robot) - ifdefed a variable in APIC so we don't get this "unused variable" warning on certain configurations (noticed by kbuild test robot) - Added `-no-PIE' to the Makefile. This breaks gcc 3.2. Is someone here still using it? - Fixed docbook in two places (noticed by kbuild test robot) - Fixed compile on sparc which was broken after I moved RCU headers (noticed by kbuild test robot) - The kbuild test robot sent me a warning about sleeping in invalid context in the NFS4 code. I didn't manage to reproduce this myself but the warning is valid. I attempted to fix this and will wait for robot's feedback :) - Lazy preempt was broken on x86-32. Fixed by Paul Gortmaker. Known issues - CPU hotplug got a little better but can deadlock. The delta patch against 4.8.2-rt3 is appended below and can be found here: https://cdn.kernel.org/pub/linux/kernel/projects/rt/4.8/incr/patch-4.8.2-rt2-rt3.patch.xz You can get this release via the git tree at: git://git.kernel.org/pub/scm/linux/kernel/git/rt/linux-rt-devel.git v4.8.2-rt3 The RT patch against 4.6.5 can be found here: https://cdn.kernel.org/pub/linux/kernel/projects/rt/4.8/patch-4.8.2-rt3.patch.xz The split quilt queue is available at: https://cdn.kernel.org/pub/linux/kernel/projects/rt/4.8/patches-4.8.2-rt3.tar.xz Sebastian diff --git a/Makefile b/Makefile index bf6e44a421df..97296d66b586 100644 --- a/Makefile +++ b/Makefile @@ -398,7 +398,7 @@ KBUILD_CPPFLAGS := -D__KERNEL__ KBUILD_CFLAGS := -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs \ -fno-strict-aliasing -fno-common \ -Werror-implicit-function-declaration \ - -Wno-format-security \ + -Wno-format-security -fno-PIE \ -std=gnu89 KBUILD_AFLAGS_KERNEL := diff --git a/arch/x86/entry/entry_32.S b/arch/x86/entry/entry_32.S index aa149231b1ff..1d8ee026c9c5 100644 --- a/arch/x86/entry/entry_32.S +++ b/arch/x86/entry/entry_32.S @@ -282,6 +282,7 @@ ENTRY(resume_kernel) cmpl $_PREEMPT_ENABLED,PER_CPU_VAR(__preempt_count) jne restore_all + GET_THREAD_INFO(%ebp) cmpl $0,TI_preempt_lazy_count(%ebp) # non-zero preempt_lazy_count ? jnz restore_all diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c index fbd19444403f..e78f477a4ae3 100644 --- a/arch/x86/kernel/acpi/boot.c +++ b/arch/x86/kernel/acpi/boot.c @@ -87,7 +87,9 @@ static u64 acpi_lapic_addr __initdata = APIC_DEFAULT_PHYS_BASE; * ->ioapic_mutex * ->ioapic_lock */ +#ifdef CONFIG_X86_IO_APIC static DEFINE_MUTEX(acpi_ioapic_lock); +#endif /* -------------------------------------------------------------------------- Boot-time Configuration diff --git a/drivers/block/zram/zcomp.c b/drivers/block/zram/zcomp.c index 4b5cd3a7b2b6..fa8329ad79fd 100644 --- a/drivers/block/zram/zcomp.c +++ b/drivers/block/zram/zcomp.c @@ -118,12 +118,19 @@ ssize_t zcomp_available_show(const char *comp, char *buf) struct zcomp_strm *zcomp_stream_get(struct zcomp *comp) { - return *get_cpu_ptr(comp->stream); + struct zcomp_strm *zstrm; + + zstrm = *this_cpu_ptr(comp->stream); + spin_lock(&zstrm->zcomp_lock); + return zstrm; } void zcomp_stream_put(struct zcomp *comp) { - put_cpu_ptr(comp->stream); + struct zcomp_strm *zstrm; + + zstrm = *this_cpu_ptr(comp->stream); + spin_unlock(&zstrm->zcomp_lock); } int zcomp_compress(struct zcomp_strm *zstrm, @@ -174,6 +181,7 @@ static int __zcomp_cpu_notifier(struct zcomp *comp, pr_err("Can't allocate a compression stream\n"); return NOTIFY_BAD; } + spin_lock_init(&zstrm->zcomp_lock); *per_cpu_ptr(comp->stream, cpu) = zstrm; break; case CPU_DEAD: diff --git a/drivers/block/zram/zcomp.h b/drivers/block/zram/zcomp.h index 478cac2ed465..f7a6efdc3285 100644 --- a/drivers/block/zram/zcomp.h +++ b/drivers/block/zram/zcomp.h @@ -14,6 +14,7 @@ struct zcomp_strm { /* compression/decompression buffer */ void *buffer; struct crypto_comp *tfm; + spinlock_t zcomp_lock; }; /* dynamic per-device compression frontend */ diff --git a/drivers/block/zram/zram_drv.c b/drivers/block/zram/zram_drv.c index d16c876c2400..b4a0577a4dbc 100644 --- a/drivers/block/zram/zram_drv.c +++ b/drivers/block/zram/zram_drv.c @@ -568,6 +568,7 @@ static int zram_decompress_page(struct zram *zram, char *mem, u32 index) struct zram_meta *meta = zram->meta; unsigned long handle; unsigned int size; + struct zcomp_strm *zstrm; zram_lock_table(&meta->table[index]); handle = meta->table[index].handle; @@ -579,16 +580,15 @@ static int zram_decompress_page(struct zram *zram, char *mem, u32 index) return 0; } + zstrm = zcomp_stream_get(zram->comp); cmem = zs_map_object(meta->mem_pool, handle, ZS_MM_RO); if (size == PAGE_SIZE) { copy_page(mem, cmem); } else { - struct zcomp_strm *zstrm = zcomp_stream_get(zram->comp); - ret = zcomp_decompress(zstrm, cmem, size, mem); - zcomp_stream_put(zram->comp); } zs_unmap_object(meta->mem_pool, handle); + zcomp_stream_put(zram->comp); zram_unlock_table(&meta->table[index]); /* Should NEVER happen. Return bio error if it does. */ diff --git a/drivers/connector/cn_proc.c b/drivers/connector/cn_proc.c index a782ce87715c..19d265948526 100644 --- a/drivers/connector/cn_proc.c +++ b/drivers/connector/cn_proc.c @@ -32,6 +32,7 @@ #include <linux/pid_namespace.h> #include <linux/cn_proc.h> +#include <linux/locallock.h> /* * Size of a cn_msg followed by a proc_event structure. Since the @@ -54,10 +55,11 @@ static struct cb_id cn_proc_event_id = { CN_IDX_PROC, CN_VAL_PROC }; /* proc_event_counts is used as the sequence number of the netlink message */ static DEFINE_PER_CPU(__u32, proc_event_counts) = { 0 }; +static DEFINE_LOCAL_IRQ_LOCK(send_msg_lock); static inline void send_msg(struct cn_msg *msg) { - preempt_disable(); + local_lock(send_msg_lock); msg->seq = __this_cpu_inc_return(proc_event_counts) - 1; ((struct proc_event *)msg->data)->cpu = smp_processor_id(); @@ -70,7 +72,7 @@ static inline void send_msg(struct cn_msg *msg) */ cn_netlink_send(msg, 0, CN_IDX_PROC, GFP_NOWAIT); - preempt_enable(); + local_unlock(send_msg_lock); } void proc_fork_connector(struct task_struct *task) diff --git a/fs/nfs/delegation.c b/fs/nfs/delegation.c index 322c2585bc34..aff0448aa0f2 100644 --- a/fs/nfs/delegation.c +++ b/fs/nfs/delegation.c @@ -140,11 +140,11 @@ static int nfs_delegation_claim_opens(struct inode *inode, sp = state->owner; /* Block nfs4_proc_unlck */ mutex_lock(&sp->so_delegreturn_mutex); - seq = raw_seqcount_begin(&sp->so_reclaim_seqcount); + seq = read_seqbegin(&sp->so_reclaim_seqlock); err = nfs4_open_delegation_recall(ctx, state, stateid, type); if (!err) err = nfs_delegation_claim_locks(ctx, state, stateid); - if (!err && read_seqcount_retry(&sp->so_reclaim_seqcount, seq)) + if (!err && read_seqretry(&sp->so_reclaim_seqlock, seq)) err = -EAGAIN; mutex_unlock(&sp->so_delegreturn_mutex); put_nfs_open_context(ctx); diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h index 9bf64eacba5b..041da5cb80f5 100644 --- a/fs/nfs/nfs4_fs.h +++ b/fs/nfs/nfs4_fs.h @@ -107,7 +107,7 @@ struct nfs4_state_owner { unsigned long so_flags; struct list_head so_states; struct nfs_seqid_counter so_seqid; - seqcount_t so_reclaim_seqcount; + seqlock_t so_reclaim_seqlock; struct mutex so_delegreturn_mutex; }; diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index a9dec32ba9ba..49b64dfb307c 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c @@ -2525,7 +2525,7 @@ static int _nfs4_open_and_get_state(struct nfs4_opendata *opendata, unsigned int seq; int ret; - seq = raw_seqcount_begin(&sp->so_reclaim_seqcount); + seq = raw_seqcount_begin(&sp->so_reclaim_seqlock.seqcount); ret = _nfs4_proc_open(opendata); if (ret != 0) @@ -2561,7 +2561,7 @@ static int _nfs4_open_and_get_state(struct nfs4_opendata *opendata, ctx->state = state; if (d_inode(dentry) == state->inode) { nfs_inode_attach_open_context(ctx); - if (read_seqcount_retry(&sp->so_reclaim_seqcount, seq)) + if (read_seqretry(&sp->so_reclaim_seqlock, seq)) nfs4_schedule_stateid_recovery(server, state); } out: diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c index cada00aa5096..d8ad3d406523 100644 --- a/fs/nfs/nfs4state.c +++ b/fs/nfs/nfs4state.c @@ -488,7 +488,7 @@ nfs4_alloc_state_owner(struct nfs_server *server, nfs4_init_seqid_counter(&sp->so_seqid); atomic_set(&sp->so_count, 1); INIT_LIST_HEAD(&sp->so_lru); - seqcount_init(&sp->so_reclaim_seqcount); + seqlock_init(&sp->so_reclaim_seqlock); mutex_init(&sp->so_delegreturn_mutex); return sp; } @@ -1459,8 +1459,8 @@ static int nfs4_reclaim_open_state(struct nfs4_state_owner *sp, const struct nfs * recovering after a network partition or a reboot from a * server that doesn't support a grace period. */ + write_seqlock(&sp->so_reclaim_seqlock); spin_lock(&sp->so_lock); - raw_write_seqcount_begin(&sp->so_reclaim_seqcount); restart: list_for_each_entry(state, &sp->so_states, open_states) { if (!test_and_clear_bit(ops->state_flag_bit, &state->flags)) @@ -1525,14 +1525,12 @@ static int nfs4_reclaim_open_state(struct nfs4_state_owner *sp, const struct nfs spin_lock(&sp->so_lock); goto restart; } - raw_write_seqcount_end(&sp->so_reclaim_seqcount); spin_unlock(&sp->so_lock); + write_sequnlock(&sp->so_reclaim_seqlock); return 0; out_err: nfs4_put_open_state(state); - spin_lock(&sp->so_lock); - raw_write_seqcount_end(&sp->so_reclaim_seqcount); - spin_unlock(&sp->so_lock); + write_sequnlock(&sp->so_reclaim_seqlock); return status; } diff --git a/include/linux/interrupt.h b/include/linux/interrupt.h index c8f178549d7b..c0a351daf736 100644 --- a/include/linux/interrupt.h +++ b/include/linux/interrupt.h @@ -219,6 +219,7 @@ extern void resume_device_irqs(void); * struct irq_affinity_notify - context for notification of IRQ affinity changes * @irq: Interrupt to which notification applies * @kref: Reference count, for internal use + * @swork: Swork item, for internal use * @work: Work item, for internal use * @notify: Function to be called on change. This will be * called in process context. diff --git a/include/linux/rcu_assign_pointer.h b/include/linux/rcu_assign_pointer.h index 1f49a6dd1b67..7066962a4379 100644 --- a/include/linux/rcu_assign_pointer.h +++ b/include/linux/rcu_assign_pointer.h @@ -1,6 +1,7 @@ #ifndef __LINUX_RCU_ASSIGN_POINTER_H__ #define __LINUX_RCU_ASSIGN_POINTER_H__ #include <linux/compiler.h> +#include <asm/barrier.h> /** * RCU_INITIALIZER() - statically initialize an RCU-protected global variable diff --git a/kernel/sched/core.c b/kernel/sched/core.c index 75666215b8cd..55aafcff5810 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -7569,7 +7569,7 @@ int sched_cpu_dying(unsigned int cpu) nohz_balance_exit_idle(cpu); hrtick_clear(rq); if (per_cpu(idle_last_mm, cpu)) { - mmdrop(per_cpu(idle_last_mm, cpu)); + mmdrop_delayed(per_cpu(idle_last_mm, cpu)); per_cpu(idle_last_mm, cpu) = NULL; } return 0; diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index 8c0b960c60da..84ffcb813263 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c @@ -2896,17 +2896,17 @@ get_total_entries(struct trace_buffer *buf, static void print_lat_help_header(struct seq_file *m) { - seq_puts(m, "# _--------=> CPU# \n" - "# / _-------=> irqs-off \n" - "# | / _------=> need-resched \n" - "# || / _-----=> need-resched_lazy \n" - "# ||| / _----=> hardirq/softirq \n" - "# |||| / _---=> preempt-depth \n" - "# ||||| / _--=> preempt-lazy-depth\n" - "# |||||| / _-=> migrate-disable \n" - "# ||||||| / delay \n" - "# cmd pid |||||||| time | caller \n" - "# \\ / |||||||| \\ | / \n"); + seq_puts(m, "# _--------=> CPU# \n" + "# / _-------=> irqs-off \n" + "# | / _------=> need-resched \n" + "# || / _-----=> need-resched_lazy \n" + "# ||| / _----=> hardirq/softirq \n" + "# |||| / _---=> preempt-depth \n" + "# ||||| / _--=> preempt-lazy-depth\n" + "# |||||| / _-=> migrate-disable \n" + "# ||||||| / delay \n" + "# cmd pid |||||||| time | caller \n" + "# \\ / |||||||| \\ | / \n"); } static void print_event_info(struct trace_buffer *buf, struct seq_file *m) @@ -2935,11 +2935,11 @@ static void print_func_help_header_irq(struct trace_buffer *buf, struct seq_file "# |/ _-----=> need-resched_lazy\n" "# || / _---=> hardirq/softirq\n" "# ||| / _--=> preempt-depth\n" - "# |||| /_--=> preempt-lazy-depth\n" - "# ||||| _-=> migrate-disable \n" - "# ||||| / delay\n" - "# TASK-PID CPU# |||||| TIMESTAMP FUNCTION\n" - "# | | | |||||| | |\n"); + "# |||| / _-=> preempt-lazy-depth\n" + "# ||||| / _-=> migrate-disable \n" + "# |||||| / delay\n" + "# TASK-PID CPU# ||||||| TIMESTAMP FUNCTION\n" + "# | | | ||||||| | |\n"); } void diff --git a/kernel/workqueue.c b/kernel/workqueue.c index 479775f5d97d..c7a62d6adb00 100644 --- a/kernel/workqueue.c +++ b/kernel/workqueue.c @@ -878,7 +878,7 @@ static void wake_up_worker(struct worker_pool *pool) /** * wq_worker_running - a worker is running again - * @cpu: CPU @task is waking up to + * @task: task waking up * * This function is called when a worker returns from schedule() */ diff --git a/localversion-rt b/localversion-rt index c3054d08a112..1445cd65885c 100644 --- a/localversion-rt +++ b/localversion-rt @@ -1 +1 @@ --rt2 +-rt3 diff --git a/mm/zsmalloc.c b/mm/zsmalloc.c index f264d387a5ec..5af6426fbcbe 100644 --- a/mm/zsmalloc.c +++ b/mm/zsmalloc.c @@ -53,6 +53,7 @@ #include <linux/mount.h> #include <linux/migrate.h> #include <linux/pagemap.h> +#include <linux/locallock.h> #define ZSPAGE_MAGIC 0x58 @@ -70,19 +71,20 @@ */ #define ZS_MAX_ZSPAGE_ORDER 2 #define ZS_MAX_PAGES_PER_ZSPAGE (_AC(1, UL) << ZS_MAX_ZSPAGE_ORDER) +#define ZS_HANDLE_SIZE (sizeof(unsigned long)) -#ifdef CONFIG_PREEMPT_RT_BASE +#ifdef CONFIG_PREEMPT_RT_FULL struct zsmalloc_handle { unsigned long addr; struct mutex lock; }; -#define ZS_HANDLE_SIZE (sizeof(struct zsmalloc_handle)) +#define ZS_HANDLE_ALLOC_SIZE (sizeof(struct zsmalloc_handle)) #else -#define ZS_HANDLE_SIZE (sizeof(unsigned long)) +#define ZS_HANDLE_ALLOC_SIZE (sizeof(unsigned long)) #endif /* @@ -339,7 +341,7 @@ static void SetZsPageMovable(struct zs_pool *pool, struct zspage *zspage) {} static int create_cache(struct zs_pool *pool) { - pool->handle_cachep = kmem_cache_create("zs_handle", ZS_HANDLE_SIZE, + pool->handle_cachep = kmem_cache_create("zs_handle", ZS_HANDLE_ALLOC_SIZE, 0, 0, NULL); if (!pool->handle_cachep) return 1; @@ -367,7 +369,7 @@ static unsigned long cache_alloc_handle(struct zs_pool *pool, gfp_t gfp) p = kmem_cache_alloc(pool->handle_cachep, gfp & ~(__GFP_HIGHMEM|__GFP_MOVABLE)); -#ifdef CONFIG_PREEMPT_RT_BASE +#ifdef CONFIG_PREEMPT_RT_FULL if (p) { struct zsmalloc_handle *zh = p; @@ -377,7 +379,7 @@ static unsigned long cache_alloc_handle(struct zs_pool *pool, gfp_t gfp) return (unsigned long)p; } -#ifdef CONFIG_PREEMPT_RT_BASE +#ifdef CONFIG_PREEMPT_RT_FULL static struct zsmalloc_handle *zs_get_pure_handle(unsigned long handle) { return (void *)(handle &~((1 << OBJ_TAG_BITS) - 1)); @@ -402,7 +404,7 @@ static void cache_free_zspage(struct zs_pool *pool, struct zspage *zspage) static void record_obj(unsigned long handle, unsigned long obj) { -#ifdef CONFIG_PREEMPT_RT_BASE +#ifdef CONFIG_PREEMPT_RT_FULL struct zsmalloc_handle *zh = zs_get_pure_handle(handle); WRITE_ONCE(zh->addr, obj); @@ -502,6 +504,7 @@ MODULE_ALIAS("zpool-zsmalloc"); /* per-cpu VM mapping areas for zspage accesses that cross page boundaries */ static DEFINE_PER_CPU(struct mapping_area, zs_map_area); +static DEFINE_LOCAL_IRQ_LOCK(zs_map_area_lock); static bool is_zspage_isolated(struct zspage *zspage) { @@ -937,7 +940,7 @@ static unsigned long location_to_obj(struct page *page, unsigned int obj_idx) static unsigned long handle_to_obj(unsigned long handle) { -#ifdef CONFIG_PREEMPT_RT_BASE +#ifdef CONFIG_PREEMPT_RT_FULL struct zsmalloc_handle *zh = zs_get_pure_handle(handle); return zh->addr; @@ -957,7 +960,7 @@ static unsigned long obj_to_head(struct page *page, void *obj) static inline int testpin_tag(unsigned long handle) { -#ifdef CONFIG_PREEMPT_RT_BASE +#ifdef CONFIG_PREEMPT_RT_FULL struct zsmalloc_handle *zh = zs_get_pure_handle(handle); return mutex_is_locked(&zh->lock); @@ -968,7 +971,7 @@ static inline int testpin_tag(unsigned long handle) static inline int trypin_tag(unsigned long handle) { -#ifdef CONFIG_PREEMPT_RT_BASE +#ifdef CONFIG_PREEMPT_RT_FULL struct zsmalloc_handle *zh = zs_get_pure_handle(handle); return mutex_trylock(&zh->lock); @@ -979,7 +982,7 @@ static inline int trypin_tag(unsigned long handle) static void pin_tag(unsigned long handle) { -#ifdef CONFIG_PREEMPT_RT_BASE +#ifdef CONFIG_PREEMPT_RT_FULL struct zsmalloc_handle *zh = zs_get_pure_handle(handle); return mutex_lock(&zh->lock); @@ -990,7 +993,7 @@ static void pin_tag(unsigned long handle) static void unpin_tag(unsigned long handle) { -#ifdef CONFIG_PREEMPT_RT_BASE +#ifdef CONFIG_PREEMPT_RT_FULL struct zsmalloc_handle *zh = zs_get_pure_handle(handle); return mutex_unlock(&zh->lock); @@ -1488,7 +1491,7 @@ void *zs_map_object(struct zs_pool *pool, unsigned long handle, class = pool->size_class[class_idx]; off = (class->size * obj_idx) & ~PAGE_MASK; - area = per_cpu_ptr(&zs_map_area, get_cpu_light()); + area = &get_locked_var(zs_map_area_lock, zs_map_area); area->vm_mm = mm; if (off + class->size <= PAGE_SIZE) { /* this object is contained entirely within a page */ @@ -1542,7 +1545,7 @@ void zs_unmap_object(struct zs_pool *pool, unsigned long handle) __zs_unmap_object(area, pages, off, class->size); } - put_cpu_light(); + put_locked_var(zs_map_area_lock, zs_map_area); migrate_read_unlock(zspage); unpin_tag(handle); diff --git a/net/rxrpc/security.c b/net/rxrpc/security.c index 814d285ff802..d4d088e9be85 100644 --- a/net/rxrpc/security.c +++ b/net/rxrpc/security.c @@ -19,9 +19,6 @@ #include <keys/rxrpc-type.h> #include "ar-internal.h" -static LIST_HEAD(rxrpc_security_methods); -static DECLARE_RWSEM(rxrpc_security_sem); - static const struct rxrpc_security *rxrpc_security_types[] = { [RXRPC_SECURITY_NONE] = &rxrpc_no_security, #ifdef CONFIG_RXKAD -- To unsubscribe from this list: send the line "unsubscribe linux-rt-users" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html