Merge commit 'v2.6.28-rc7' into core/locking
authorIngo Molnar <mingo@elte.hu>
Thu, 4 Dec 2008 07:52:14 +0000 (08:52 +0100)
committerIngo Molnar <mingo@elte.hu>
Thu, 4 Dec 2008 07:52:14 +0000 (08:52 +0100)
1  2 
arch/x86/include/asm/uaccess_64.h
include/linux/kernel.h
kernel/irq/manage.c
kernel/lockdep.c
kernel/sched.c

index 543ba883cc66200ff0e2206aec36b434b63d3695,f8cfd00db450f2e0f948ce7128a2d44867aebf59..84210c479fca83524c6cef4c6bc069bcff76e272
@@@ -29,8 -29,6 +29,8 @@@ static __always_inline __must_chec
  int __copy_from_user(void *dst, const void __user *src, unsigned size)
  {
        int ret = 0;
 +
 +      might_fault();
        if (!__builtin_constant_p(size))
                return copy_user_generic(dst, (__force void *)src, size);
        switch (size) {
@@@ -48,7 -46,7 +48,7 @@@
                return ret;
        case 10:
                __get_user_asm(*(u64 *)dst, (u64 __user *)src,
-                              ret, "q", "", "=r", 16);
+                              ret, "q", "", "=r", 10);
                if (unlikely(ret))
                        return ret;
                __get_user_asm(*(u16 *)(8 + (char *)dst),
@@@ -73,8 -71,6 +73,8 @@@ static __always_inline __must_chec
  int __copy_to_user(void __user *dst, const void *src, unsigned size)
  {
        int ret = 0;
 +
 +      might_fault();
        if (!__builtin_constant_p(size))
                return copy_user_generic((__force void *)dst, src, size);
        switch (size) {
@@@ -117,8 -113,6 +117,8 @@@ static __always_inline __must_chec
  int __copy_in_user(void __user *dst, const void __user *src, unsigned size)
  {
        int ret = 0;
 +
 +      might_fault();
        if (!__builtin_constant_p(size))
                return copy_user_generic((__force void *)dst,
                                         (__force void *)src, size);
diff --combined include/linux/kernel.h
index 69a9bfdf9c86d9de03919277d108fe242a4d1e4f,dc7e0d0a6474448aba71b4c32d2045afc44e240e..6a5c75cee5bcf9f3085d92373852387894727c79
@@@ -141,15 -141,6 +141,15 @@@ extern int _cond_resched(void)
                (__x < 0) ? -__x : __x;         \
        })
  
 +#ifdef CONFIG_PROVE_LOCKING
 +void might_fault(void);
 +#else
 +static inline void might_fault(void)
 +{
 +      might_sleep();
 +}
 +#endif
 +
  extern struct atomic_notifier_head panic_notifier_list;
  extern long (*panic_blink)(long time);
  NORET_TYPE void panic(const char * fmt, ...)
@@@ -327,32 -318,36 +327,36 @@@ static inline char *pack_hex_byte(char 
        return buf;
  }
  
- #define pr_emerg(fmt, arg...) \
-       printk(KERN_EMERG fmt, ##arg)
- #define pr_alert(fmt, arg...) \
-       printk(KERN_ALERT fmt, ##arg)
- #define pr_crit(fmt, arg...) \
-       printk(KERN_CRIT fmt, ##arg)
- #define pr_err(fmt, arg...) \
-       printk(KERN_ERR fmt, ##arg)
- #define pr_warning(fmt, arg...) \
-       printk(KERN_WARNING fmt, ##arg)
- #define pr_notice(fmt, arg...) \
-       printk(KERN_NOTICE fmt, ##arg)
- #define pr_info(fmt, arg...) \
-       printk(KERN_INFO fmt, ##arg)
+ #ifndef pr_fmt
+ #define pr_fmt(fmt) fmt
+ #endif
+ #define pr_emerg(fmt, ...) \
+         printk(KERN_EMERG pr_fmt(fmt), ##__VA_ARGS__)
+ #define pr_alert(fmt, ...) \
+         printk(KERN_ALERT pr_fmt(fmt), ##__VA_ARGS__)
+ #define pr_crit(fmt, ...) \
+         printk(KERN_CRIT pr_fmt(fmt), ##__VA_ARGS__)
+ #define pr_err(fmt, ...) \
+         printk(KERN_ERR pr_fmt(fmt), ##__VA_ARGS__)
+ #define pr_warning(fmt, ...) \
+         printk(KERN_WARNING pr_fmt(fmt), ##__VA_ARGS__)
+ #define pr_notice(fmt, ...) \
+         printk(KERN_NOTICE pr_fmt(fmt), ##__VA_ARGS__)
+ #define pr_info(fmt, ...) \
+         printk(KERN_INFO pr_fmt(fmt), ##__VA_ARGS__)
  
  /* If you are writing a driver, please use dev_dbg instead */
  #if defined(CONFIG_DYNAMIC_PRINTK_DEBUG)
  #define pr_debug(fmt, ...) do { \
-       dynamic_pr_debug(fmt, ##__VA_ARGS__); \
+       dynamic_pr_debug(pr_fmt(fmt), ##__VA_ARGS__); \
        } while (0)
  #elif defined(DEBUG)
- #define pr_debug(fmt, arg...) \
-       printk(KERN_DEBUG fmt, ##arg)
+ #define pr_debug(fmt, ...) \
+       printk(KERN_DEBUG pr_fmt(fmt), ##__VA_ARGS__)
  #else
- #define pr_debug(fmt, arg...) \
-       ({ if (0) printk(KERN_DEBUG fmt, ##arg); 0; })
+ #define pr_debug(fmt, ...) \
+       ({ if (0) printk(KERN_DEBUG pr_fmt(fmt), ##__VA_ARGS__); 0; })
  #endif
  
  /*
diff --combined kernel/irq/manage.c
index 7fd891c3a33d5091bbcf87ed3df607000d12cda0,801addda3c43d4a7a767b27468fee05232cb6f89..e9d1c8205a3b0998d6e0a4c37b407a196bdcdab1
@@@ -82,24 -82,27 +82,27 @@@ int irq_can_set_affinity(unsigned int i
  int irq_set_affinity(unsigned int irq, cpumask_t cpumask)
  {
        struct irq_desc *desc = irq_to_desc(irq);
+       unsigned long flags;
  
        if (!desc->chip->set_affinity)
                return -EINVAL;
  
+       spin_lock_irqsave(&desc->lock, flags);
  #ifdef CONFIG_GENERIC_PENDING_IRQ
        if (desc->status & IRQ_MOVE_PCNTXT || desc->status & IRQ_DISABLED) {
-               unsigned long flags;
-               spin_lock_irqsave(&desc->lock, flags);
                desc->affinity = cpumask;
                desc->chip->set_affinity(irq, cpumask);
-               spin_unlock_irqrestore(&desc->lock, flags);
-       } else
-               set_pending_irq(irq, cpumask);
+       } else {
+               desc->status |= IRQ_MOVE_PENDING;
+               desc->pending_mask = cpumask;
+       }
  #else
        desc->affinity = cpumask;
        desc->chip->set_affinity(irq, cpumask);
  #endif
+       desc->status |= IRQ_AFFINITY_SET;
+       spin_unlock_irqrestore(&desc->lock, flags);
        return 0;
  }
  
  /*
   * Generic version of the affinity autoselector.
   */
- int irq_select_affinity(unsigned int irq)
+ int do_irq_select_affinity(unsigned int irq, struct irq_desc *desc)
  {
        cpumask_t mask;
-       struct irq_desc *desc;
  
        if (!irq_can_set_affinity(irq))
                return 0;
  
        cpus_and(mask, cpu_online_map, irq_default_affinity);
  
-       desc = irq_to_desc(irq);
+       /*
+        * Preserve an userspace affinity setup, but make sure that
+        * one of the targets is online.
+        */
+       if (desc->status & (IRQ_AFFINITY_SET | IRQ_NO_BALANCING)) {
+               if (cpus_intersects(desc->affinity, cpu_online_map))
+                       mask = desc->affinity;
+               else
+                       desc->status &= ~IRQ_AFFINITY_SET;
+       }
        desc->affinity = mask;
        desc->chip->set_affinity(irq, mask);
  
        return 0;
  }
+ #else
+ static inline int do_irq_select_affinity(unsigned int irq, struct irq_desc *d)
+ {
+       return irq_select_affinity(irq);
+ }
  #endif
  
+ /*
+  * Called when affinity is set via /proc/irq
+  */
+ int irq_select_affinity_usr(unsigned int irq)
+ {
+       struct irq_desc *desc = irq_to_desc(irq);
+       unsigned long flags;
+       int ret;
+       spin_lock_irqsave(&desc->lock, flags);
+       ret = do_irq_select_affinity(irq, desc);
+       spin_unlock_irqrestore(&desc->lock, flags);
+       return ret;
+ }
+ #else
+ static inline int do_irq_select_affinity(int irq, struct irq_desc *desc)
+ {
+       return 0;
+ }
  #endif
  
  /**
@@@ -327,7 -365,7 +365,7 @@@ int __irq_set_trigger(struct irq_desc *
                 * IRQF_TRIGGER_* but the PIC does not support multiple
                 * flow-types?
                 */
-               pr_warning("No set_type function for IRQ %d (%s)\n", irq,
+               pr_debug("No set_type function for IRQ %d (%s)\n", irq,
                                chip ? (chip->name ? : "unknown") : "unknown");
                return 0;
        }
@@@ -445,8 -483,12 +483,12 @@@ __setup_irq(unsigned int irq, struct ir
                        /* Undo nested disables: */
                        desc->depth = 1;
  
+               /* Exclude IRQ from balancing if requested */
+               if (new->flags & IRQF_NOBALANCING)
+                       desc->status |= IRQ_NO_BALANCING;
                /* Set default affinity mask once everything is setup */
-               irq_select_affinity(irq);
+               do_irq_select_affinity(irq, desc);
  
        } else if ((new->flags & IRQF_TRIGGER_MASK)
                        && (new->flags & IRQF_TRIGGER_MASK)
  
        *p = new;
  
-       /* Exclude IRQ from balancing */
-       if (new->flags & IRQF_NOBALANCING)
-               desc->status |= IRQ_NO_BALANCING;
        /* Reset broken irq detection when installing new handler */
        desc->irq_count = 0;
        desc->irqs_unhandled = 0;
@@@ -635,18 -673,6 +673,18 @@@ int request_irq(unsigned int irq, irq_h
        struct irq_desc *desc;
        int retval;
  
 +      /*
 +       * handle_IRQ_event() always ignores IRQF_DISABLED except for
 +       * the _first_ irqaction (sigh).  That can cause oopsing, but
 +       * the behavior is classified as "will not fix" so we need to
 +       * start nudging drivers away from using that idiom.
 +       */
 +      if ((irqflags & (IRQF_SHARED|IRQF_DISABLED))
 +                      == (IRQF_SHARED|IRQF_DISABLED))
 +              pr_warning("IRQ %d/%s: IRQF_DISABLED is not "
 +                              "guaranteed on shared IRQs\n",
 +                              irq, devname);
 +
  #ifdef CONFIG_LOCKDEP
        /*
         * Lockdep wants atomic interrupt handlers:
diff --combined kernel/lockdep.c
index c137953420e07946d6169e359d985bb9eeb343ba,46a404173db231a982baf3941c72e96911003906..90f3fb64dbce81d83b7bc56ee8c7f6112a0cc44d
@@@ -136,16 -136,16 +136,16 @@@ static inline struct lock_class *hlock_
  #ifdef CONFIG_LOCK_STAT
  static DEFINE_PER_CPU(struct lock_class_stats[MAX_LOCKDEP_KEYS], lock_stats);
  
 -static int lock_contention_point(struct lock_class *class, unsigned long ip)
 +static int lock_point(unsigned long points[], unsigned long ip)
  {
        int i;
  
 -      for (i = 0; i < ARRAY_SIZE(class->contention_point); i++) {
 -              if (class->contention_point[i] == 0) {
 -                      class->contention_point[i] = ip;
 +      for (i = 0; i < LOCKSTAT_POINTS; i++) {
 +              if (points[i] == 0) {
 +                      points[i] = ip;
                        break;
                }
 -              if (class->contention_point[i] == ip)
 +              if (points[i] == ip)
                        break;
        }
  
@@@ -185,9 -185,6 +185,9 @@@ struct lock_class_stats lock_stats(stru
                for (i = 0; i < ARRAY_SIZE(stats.contention_point); i++)
                        stats.contention_point[i] += pcs->contention_point[i];
  
 +              for (i = 0; i < ARRAY_SIZE(stats.contending_point); i++)
 +                      stats.contending_point[i] += pcs->contending_point[i];
 +
                lock_time_add(&pcs->read_waittime, &stats.read_waittime);
                lock_time_add(&pcs->write_waittime, &stats.write_waittime);
  
@@@ -212,7 -209,6 +212,7 @@@ void clear_lock_stats(struct lock_clas
                memset(cpu_stats, 0, sizeof(struct lock_class_stats));
        }
        memset(class->contention_point, 0, sizeof(class->contention_point));
 +      memset(class->contending_point, 0, sizeof(class->contending_point));
  }
  
  static struct lock_class_stats *get_lock_stats(struct lock_class *class)
@@@ -580,8 -576,7 +580,8 @@@ static void print_lock_class_header(str
  /*
   * printk all lock dependencies starting at <entry>:
   */
 -static void print_lock_dependencies(struct lock_class *class, int depth)
 +static void __used
 +print_lock_dependencies(struct lock_class *class, int depth)
  {
        struct lock_list *entry;
  
@@@ -3004,7 -2999,7 +3004,7 @@@ __lock_contended(struct lockdep_map *lo
        struct held_lock *hlock, *prev_hlock;
        struct lock_class_stats *stats;
        unsigned int depth;
 -      int i, point;
 +      int i, contention_point, contending_point;
  
        depth = curr->lockdep_depth;
        if (DEBUG_LOCKS_WARN_ON(!depth))
  found_it:
        hlock->waittime_stamp = sched_clock();
  
 -      point = lock_contention_point(hlock_class(hlock), ip);
 +      contention_point = lock_point(hlock_class(hlock)->contention_point, ip);
 +      contending_point = lock_point(hlock_class(hlock)->contending_point,
 +                                    lock->ip);
  
        stats = get_lock_stats(hlock_class(hlock));
 -      if (point < ARRAY_SIZE(stats->contention_point))
 -              stats->contention_point[point]++;
 +      if (contention_point < LOCKSTAT_POINTS)
 +              stats->contention_point[contention_point]++;
 +      if (contending_point < LOCKSTAT_POINTS)
 +              stats->contending_point[contending_point]++;
        if (lock->cpu != smp_processor_id())
                stats->bounces[bounce_contended + !!hlock->read]++;
        put_lock_stats(stats);
  }
  
  static void
 -__lock_acquired(struct lockdep_map *lock)
 +__lock_acquired(struct lockdep_map *lock, unsigned long ip)
  {
        struct task_struct *curr = current;
        struct held_lock *hlock, *prev_hlock;
@@@ -3092,7 -3083,6 +3092,7 @@@ found_it
        put_lock_stats(stats);
  
        lock->cpu = cpu;
 +      lock->ip = ip;
  }
  
  void lock_contended(struct lockdep_map *lock, unsigned long ip)
  }
  EXPORT_SYMBOL_GPL(lock_contended);
  
 -void lock_acquired(struct lockdep_map *lock)
 +void lock_acquired(struct lockdep_map *lock, unsigned long ip)
  {
        unsigned long flags;
  
        raw_local_irq_save(flags);
        check_flags(flags);
        current->lockdep_recursion = 1;
 -      __lock_acquired(lock);
 +      __lock_acquired(lock, ip);
        current->lockdep_recursion = 0;
        raw_local_irq_restore(flags);
  }
@@@ -3286,10 -3276,10 +3286,10 @@@ void __init lockdep_info(void
  {
        printk("Lock dependency validator: Copyright (c) 2006 Red Hat, Inc., Ingo Molnar\n");
  
-       printk("... MAX_LOCKDEP_SUBCLASSES:    %lu\n", MAX_LOCKDEP_SUBCLASSES);
+       printk("... MAX_LOCKDEP_SUBCLASSES:  %lu\n", MAX_LOCKDEP_SUBCLASSES);
        printk("... MAX_LOCK_DEPTH:          %lu\n", MAX_LOCK_DEPTH);
        printk("... MAX_LOCKDEP_KEYS:        %lu\n", MAX_LOCKDEP_KEYS);
-       printk("... CLASSHASH_SIZE:           %lu\n", CLASSHASH_SIZE);
+       printk("... CLASSHASH_SIZE:          %lu\n", CLASSHASH_SIZE);
        printk("... MAX_LOCKDEP_ENTRIES:     %lu\n", MAX_LOCKDEP_ENTRIES);
        printk("... MAX_LOCKDEP_CHAINS:      %lu\n", MAX_LOCKDEP_CHAINS);
        printk("... CHAINHASH_SIZE:          %lu\n", CHAINHASH_SIZE);
diff --combined kernel/sched.c
index 2a106b6b78b09006f75274defb2057b6e7a428e7,b7480fb5c3dc21a7bf6513a978cf0ed2e8c19a8f..1b8f8c3aecc435f9aeb30ab0c1412743491b75a1
@@@ -1453,9 -1453,12 +1453,12 @@@ static int task_hot(struct task_struct 
  static unsigned long cpu_avg_load_per_task(int cpu)
  {
        struct rq *rq = cpu_rq(cpu);
+       unsigned long nr_running = ACCESS_ONCE(rq->nr_running);
  
-       if (rq->nr_running)
-               rq->avg_load_per_task = rq->load.weight / rq->nr_running;
+       if (nr_running)
+               rq->avg_load_per_task = rq->load.weight / nr_running;
+       else
+               rq->avg_load_per_task = 0;
  
        return rq->avg_load_per_task;
  }
@@@ -4336,7 -4339,7 +4339,7 @@@ void __kprobes sub_preempt_count(int va
        /*
         * Underflow?
         */
 -      if (DEBUG_LOCKS_WARN_ON(val > preempt_count()))
 +       if (DEBUG_LOCKS_WARN_ON(val > preempt_count() - (!!kernel_locked())))
                return;
        /*
         * Is the spinlock portion underflowing?
@@@ -5868,6 -5871,8 +5871,8 @@@ void __cpuinit init_idle(struct task_st
        struct rq *rq = cpu_rq(cpu);
        unsigned long flags;
  
+       spin_lock_irqsave(&rq->lock, flags);
        __sched_fork(idle);
        idle->se.exec_start = sched_clock();
  
        idle->cpus_allowed = cpumask_of_cpu(cpu);
        __set_task_cpu(idle, cpu);
  
-       spin_lock_irqsave(&rq->lock, flags);
        rq->curr = rq->idle = idle;
  #if defined(CONFIG_SMP) && defined(__ARCH_WANT_UNLOCKED_CTXSW)
        idle->oncpu = 1;
@@@ -7786,13 -7790,14 +7790,14 @@@ static int dattrs_equal(struct sched_do
   *
   * The passed in 'doms_new' should be kmalloc'd. This routine takes
   * ownership of it and will kfree it when done with it. If the caller
-  * failed the kmalloc call, then it can pass in doms_new == NULL,
-  * and partition_sched_domains() will fallback to the single partition
-  * 'fallback_doms', it also forces the domains to be rebuilt.
+  * failed the kmalloc call, then it can pass in doms_new == NULL &&
+  * ndoms_new == 1, and partition_sched_domains() will fallback to
+  * the single partition 'fallback_doms', it also forces the domains
+  * to be rebuilt.
   *
-  * If doms_new==NULL it will be replaced with cpu_online_map.
-  * ndoms_new==0 is a special case for destroying existing domains.
-  * It will not create the default domain.
+  * If doms_new == NULL it will be replaced with cpu_online_map.
+  * ndoms_new == 0 is a special case for destroying existing domains,
+  * and it will not create the default domain.
   *
   * Call with hotplug lock held
   */