core kernel fixes
Linus,
Please pull the latest core-urgent-for-linus git tree from:
git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip.git core-urgent-for-linus
Thanks,
Ingo
------------------>
Peter Zijlstra (4):
lockdep: Fix trace_hardirqs_on_caller()
lockdep: Fix up warning
slab, lockdep: Annotate slab -> rcu -> debug_object -> slab slab, lockdep: Annotate the locks before using them
Shawn Bohrer (1):
futex: Fix regression with read only mappings
Tejun Heo (1):
lockdep: Clear whole lockdep_map on initialization
kernel/futex.c | 54 ++++++++++++++++++++++++------- kernel/lockdep.c | 37 ++++++++++----------- mm/slab.c | 92 +++++++++++++++++++++++++++++++++++++++++------------ 3 files changed, 131 insertions(+), 52 deletions(-)
kernel/futex.c +42 -12
@@ -218,6 +218,8 @@ static void drop_futex_key_refs(union futex_key *key)* @uaddr: virtual address of the futex * @fshared: 0 for a PROCESS_PRIVATE futex, 1 for PROCESS_SHARED * @key: address where result is stored. +* @rw: mapping needs to be read/write (values: VERIFY_READ, +* VERIFY_WRITE) * * Returns a negative error code or 0 * The key words are stored in *key on success.
@@ -229,12 +231,12 @@ static void drop_futex_key_refs(union futex_key *key)* lock_page() might sleep, the caller should not hold a spinlock. */ static int -get_futex_key (u32 __user *uaddr,int fshared,union futex_key *key) +get_futex_key (u32 __user *uaddr,int fshared,union futex_key *key,int rw) {unsigned long address = (unsigned long )uaddr;struct mm_struct *mm = current->mm;struct page *page, *page_head; -int err; +int err, ro =0 ;/* * The futex address must be "naturally" aligned.
@@ -262,8 +264,18 @@ get_futex_key(u32 __user *uaddr, int fshared, union futex_key *key) again: err =get_user_pages_fast (address,1 ,1 , &page); +/* +* If write access is not required (eg. FUTEX_WAIT), try +* and get read-only access. +*/ +if (err == -EFAULT && rw ==VERIFY_READ ) { + err =get_user_pages_fast (address,1 ,0 , &page); + ro =1 ; + }if (err <0 )return err; +else + err =0 ;#ifdef CONFIG_TRANSPARENT_HUGEPAGE page_head = page;
@@ -305,6 +317,13 @@ again:if (!page_head->mapping) {unlock_page (page_head);put_page (page_head); +/* +* ZERO_PAGE pages don't have a mapping. Avoid a busy loop +* trying to find one. RW mapping would have COW'd (and thus +* have a mapping) so this page is RO and won't ever change. +*/ +if ((page_head ==ZERO_PAGE (address))) +return -EFAULT ; goto again; }
@@ -316,6 +335,15 @@ again:* the object not the particular process. */ if (PageAnon (page_head)) { +/* +* A RO anonymous page will never change and thus doesn't make +* sense for futex operations. +*/ +if (ro) { + err = -EFAULT ; + goto out; + } + key->both.offset |=FUT_OFF_MMSHARED ;/* ref taken on mm */ key->private.mm = mm; key->private.address = address;
@@ -327,9 +355,10 @@ again:get_futex_key_refs (key); +out:unlock_page (page_head);put_page (page_head); -return 0 ; +return err; }static inline void put_futex_key (union futex_key *key)
@@ -940,7 +969,7 @@ futex_wake(u32 __user *uaddr, unsigned int flags, int nr_wake, u32 bitset)if (!bitset)return -EINVAL ; - ret =get_futex_key (uaddr, flags &FLAGS_SHARED , &key); + ret =get_futex_key (uaddr, flags &FLAGS_SHARED , &key,VERIFY_READ );if (unlikely (ret !=0 )) goto out;
@@ -986,10 +1015,10 @@ futex_wake_op(u32 __user *uaddr1, unsigned int flags, u32 __user *uaddr2,int ret, op_ret; retry: - ret =get_futex_key (uaddr1, flags &FLAGS_SHARED , &key1); + ret =get_futex_key (uaddr1, flags &FLAGS_SHARED , &key1,VERIFY_READ );if (unlikely (ret !=0 )) goto out; - ret =get_futex_key (uaddr2, flags &FLAGS_SHARED , &key2); + ret =get_futex_key (uaddr2, flags &FLAGS_SHARED , &key2,VERIFY_WRITE );if (unlikely (ret !=0 )) goto out_put_key1;
@@ -1243,10 +1272,11 @@ retry: pi_state =NULL ; } - ret =get_futex_key (uaddr1, flags &FLAGS_SHARED , &key1); + ret =get_futex_key (uaddr1, flags &FLAGS_SHARED , &key1,VERIFY_READ );if (unlikely (ret !=0 )) goto out; - ret =get_futex_key (uaddr2, flags &FLAGS_SHARED , &key2); + ret =get_futex_key (uaddr2, flags &FLAGS_SHARED , &key2, + requeue_pi ?VERIFY_WRITE :VERIFY_READ );if (unlikely (ret !=0 )) goto out_put_key1;
@@ -1790,7 +1820,7 @@ static int futex_wait_setup(u32 __user *uaddr, u32 val, unsigned int flags,* while the syscall executes. */ retry: - ret =get_futex_key (uaddr, flags &FLAGS_SHARED , &q->key); + ret =get_futex_key (uaddr, flags &FLAGS_SHARED , &q->key,VERIFY_READ );if (unlikely (ret !=0 ))return ret;
@@ -1941,7 +1971,7 @@ static int futex_lock_pi(u32 __user *uaddr, unsigned int flags, int detect, } retry: - ret =get_futex_key (uaddr, flags &FLAGS_SHARED , &q.key); + ret =get_futex_key (uaddr, flags &FLAGS_SHARED , &q.key,VERIFY_WRITE );if (unlikely (ret !=0 )) goto out;
@@ -2060,7 +2090,7 @@ retry:if ((uval &FUTEX_TID_MASK ) != vpid)return -EPERM ; - ret =get_futex_key (uaddr, flags &FLAGS_SHARED , &key); + ret =get_futex_key (uaddr, flags &FLAGS_SHARED , &key,VERIFY_WRITE );if (unlikely (ret !=0 )) goto out;
@@ -2249,7 +2279,7 @@ static int futex_wait_requeue_pi(u32 __user *uaddr, unsigned int flags,debug_rt_mutex_init_waiter (&rt_waiter); rt_waiter.task =NULL ; - ret =get_futex_key (uaddr2, flags &FLAGS_SHARED , &key2); + ret =get_futex_key (uaddr2, flags &FLAGS_SHARED , &key2,VERIFY_WRITE );if (unlikely (ret !=0 )) goto out;
kernel/lockdep.c +18 -19
@@ -2468,7 +2468,7 @@ mark_held_locks(struct task_struct *curr, enum mark_type mark)BUG_ON (usage_bit >=LOCK_USAGE_STATES ); -if (hlock_class (hlock)->key == &__lockdep_no_validate__) +if (hlock_class (hlock)->key == __lockdep_no_validate__.subkeys)continue ;if (!mark_lock (curr, hlock, usage_bit))
@@ -2485,23 +2485,9 @@ static void __trace_hardirqs_on_caller(unsigned long ip) {struct task_struct *curr = current; -if (DEBUG_LOCKS_WARN_ON (unlikely (early_boot_irqs_disabled))) -return ; - -if (unlikely (curr->hardirqs_enabled)) { -/* -* Neither irq nor preemption are disabled here -* so this is racy by nature but losing one hit -* in a stat is not a big deal. -*/ -__debug_atomic_inc (redundant_hardirqs_on); -return ; - }/* we'll do an OFF -> ON transition: */ curr->hardirqs_enabled =1 ; -if (DEBUG_LOCKS_WARN_ON (current->hardirq_context)) -return ;/* * We are going to turn hardirqs on, so set the * usage bit for all held locks:
@@ -2529,9 +2515,25 @@ void trace_hardirqs_on_caller(unsigned long ip)if (unlikely (!debug_locks || current->lockdep_recursion))return ; +if (unlikely (current->hardirqs_enabled)) { +/* +* Neither irq nor preemption are disabled here +* so this is racy by nature but losing one hit +* in a stat is not a big deal. +*/ +__debug_atomic_inc (redundant_hardirqs_on); +return ; + } +if (DEBUG_LOCKS_WARN_ON (!irqs_disabled ()))return ; +if (DEBUG_LOCKS_WARN_ON (unlikely (early_boot_irqs_disabled))) +return ; + +if (DEBUG_LOCKS_WARN_ON (current->hardirq_context)) +return ; + current->lockdep_recursion =1 ;__trace_hardirqs_on_caller (ip); current->lockdep_recursion =0 ;
@@ -2872,10 +2874,7 @@ static int mark_lock(struct task_struct *curr, struct held_lock *this,void lockdep_init_map (struct lockdep_map *lock,const char *name,struct lock_class_key *key,int subclass) { -int i; - -for (i =0 ; i <NR_LOCKDEP_CACHING_CLASSES ; i++) - lock->class_cache[i] =NULL ; +memset (lock,0 ,sizeof (*lock));#ifdef CONFIG_LOCK_STAT lock->cpu =raw_smp_processor_id ();
mm/slab.c +71 -21
139 lines not on this page · raw message