]> git.karo-electronics.de Git - mv-sheeva.git/blobdiff - kernel/printk.c
thp: split_huge_page paging
[mv-sheeva.git] / kernel / printk.c
index 4642a5c439eb324b8d3e79872e589439c705cd20..53d9a9ec88e6952cde88769ce6cd124c57f541d4 100644 (file)
@@ -39,6 +39,7 @@
 #include <linux/syslog.h>
 #include <linux/cpu.h>
 #include <linux/notifier.h>
+#include <linux/rculist.h>
 
 #include <asm/uaccess.h>
 
@@ -273,12 +274,12 @@ int do_syslog(int type, char __user *buf, int len, bool from_file)
         * at open time.
         */
        if (type == SYSLOG_ACTION_OPEN || !from_file) {
-               if (dmesg_restrict && !capable(CAP_SYS_ADMIN))
-                       return -EPERM;
+               if (dmesg_restrict && !capable(CAP_SYSLOG))
+                       goto warn; /* switch to return -EPERM after 2.6.39 */
                if ((type != SYSLOG_ACTION_READ_ALL &&
                     type != SYSLOG_ACTION_SIZE_BUFFER) &&
-                   !capable(CAP_SYS_ADMIN))
-                       return -EPERM;
+                   !capable(CAP_SYSLOG))
+                       goto warn; /* switch to return -EPERM after 2.6.39 */
        }
 
        error = security_syslog(type);
@@ -422,6 +423,12 @@ int do_syslog(int type, char __user *buf, int len, bool from_file)
        }
 out:
        return error;
+warn:
+       /* remove after 2.6.39 */
+       if (capable(CAP_SYS_ADMIN))
+               WARN_ONCE(1, "Attempt to access syslog with CAP_SYS_ADMIN "
+                 "but no CAP_SYSLOG (deprecated and denied).\n");
+       return -EPERM;
 }
 
 SYSCALL_DEFINE3(syslog, int, type, char __user *, buf, int, len)
@@ -1496,7 +1503,7 @@ int kmsg_dump_register(struct kmsg_dumper *dumper)
        /* Don't allow registering multiple times */
        if (!dumper->registered) {
                dumper->registered = 1;
-               list_add_tail(&dumper->list, &dump_list);
+               list_add_tail_rcu(&dumper->list, &dump_list);
                err = 0;
        }
        spin_unlock_irqrestore(&dump_list_lock, flags);
@@ -1520,29 +1527,16 @@ int kmsg_dump_unregister(struct kmsg_dumper *dumper)
        spin_lock_irqsave(&dump_list_lock, flags);
        if (dumper->registered) {
                dumper->registered = 0;
-               list_del(&dumper->list);
+               list_del_rcu(&dumper->list);
                err = 0;
        }
        spin_unlock_irqrestore(&dump_list_lock, flags);
+       synchronize_rcu();
 
        return err;
 }
 EXPORT_SYMBOL_GPL(kmsg_dump_unregister);
 
-static const char * const kmsg_reasons[] = {
-       [KMSG_DUMP_OOPS]        = "oops",
-       [KMSG_DUMP_PANIC]       = "panic",
-       [KMSG_DUMP_KEXEC]       = "kexec",
-};
-
-static const char *kmsg_to_str(enum kmsg_dump_reason reason)
-{
-       if (reason >= ARRAY_SIZE(kmsg_reasons) || reason < 0)
-               return "unknown";
-
-       return kmsg_reasons[reason];
-}
-
 /**
  * kmsg_dump - dump kernel log to kernel message dumpers.
  * @reason: the reason (oops, panic etc) for dumping
@@ -1581,13 +1575,9 @@ void kmsg_dump(enum kmsg_dump_reason reason)
                l2 = chars;
        }
 
-       if (!spin_trylock_irqsave(&dump_list_lock, flags)) {
-               printk(KERN_ERR "dump_kmsg: dump list lock is held during %s, skipping dump\n",
-                               kmsg_to_str(reason));
-               return;
-       }
-       list_for_each_entry(dumper, &dump_list, list)
+       rcu_read_lock();
+       list_for_each_entry_rcu(dumper, &dump_list, list)
                dumper->dump(dumper, reason, s1, l1, s2, l2);
-       spin_unlock_irqrestore(&dump_list_lock, flags);
+       rcu_read_unlock();
 }
 #endif