powerpc: Honor O_NONBLOCK flag when reading RTAS log
authorVitaly Mayatskikh <v.mayatskih@gmail.com>
Sun, 28 Sep 2008 23:24:33 +0000 (23:24 +0000)
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>
Tue, 7 Oct 2008 03:26:21 +0000 (14:26 +1100)
rtas_log_read() doesn't check file flags for O_NONBLOCK and blocks
non-blocking readers of /proc/ppc64/rtas/error_log when there is
no data available. This fixes it.

Also rtas_log_read() returns now with ENODATA to prevent suspending of
process in wait_event_interruptible() when logging facility was
switched off and log is already empty.

Signed-off-by: Vitaly Mayatskikh <v.mayatskih@gmail.com>
Acked-by: David Howells <dhowells@redhat.com>
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
arch/powerpc/platforms/pseries/rtasd.c

index c9ffd8c225f1a7b1b2e852bf86899bd8d785e3b4..f4e55be2eea948548837177f432e893175960391 100644 (file)
@@ -295,19 +295,29 @@ static ssize_t rtas_log_read(struct file * file, char __user * buf,
        if (!tmp)
                return -ENOMEM;
 
-
        spin_lock_irqsave(&rtasd_log_lock, s);
        /* if it's 0, then we know we got the last one (the one in NVRAM) */
-       if (rtas_log_size == 0 && logging_enabled)
-               nvram_clear_error_log();
-       spin_unlock_irqrestore(&rtasd_log_lock, s);
+       while (rtas_log_size == 0) {
+               if (file->f_flags & O_NONBLOCK) {
+                       spin_unlock_irqrestore(&rtasd_log_lock, s);
+                       error = -EAGAIN;
+                       goto out;
+               }
 
+               if (!logging_enabled) {
+                       spin_unlock_irqrestore(&rtasd_log_lock, s);
+                       error = -ENODATA;
+                       goto out;
+               }
+               nvram_clear_error_log();
 
-       error = wait_event_interruptible(rtas_log_wait, rtas_log_size);
-       if (error)
-               goto out;
+               spin_unlock_irqrestore(&rtasd_log_lock, s);
+               error = wait_event_interruptible(rtas_log_wait, rtas_log_size);
+               if (error)
+                       goto out;
+               spin_lock_irqsave(&rtasd_log_lock, s);
+       }
 
-       spin_lock_irqsave(&rtasd_log_lock, s);
        offset = rtas_error_log_buffer_max * (rtas_log_start & LOG_NUMBER_MASK);
        memcpy(tmp, &rtas_log_buf[offset], count);