Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > by-pkgid > fc11cd6e1c513a17304da94a5390f3cd > files > 3001

kernel-2.6.18-194.11.1.el5.src.rpm

From: Vitaly Mayatskikh <vmayatsk@redhat.com>
Date: Thu, 25 Sep 2008 15:39:36 +0200
Subject: [ppc64] support O_NONBLOCK in /proc/ppc64/rtas/error_log
Message-id: m3ljxge44n.wl%vmayatsk@redhat.com
O-Subject: Re: [RHEL-5.3 PATCH] BZ376831 Read from /proc/ppc64/rtas/error_log does not honor O_NONBLOCK
Bugzilla: 376831
RH-Acked-by: David Howells <dhowells@redhat.com>

Bugzilla: 376831
https://bugzilla.redhat.com/show_bug.cgi?id=376831

Description:
============
rtas_log_read() currently doesn't count O_NONBLOCK flag. This sample
code will block on read:

fd = open ("/proc/ppc64/rtas/error_log", O_RDONLY | O_NONBLOCK);
while (1) {
    err =read (fd, buf, 4096);
    printf("err = %d, errno = %d (%s)\n", err, errno, strerror(errno));
    sleep(1);
}

Upstream status:
================
Posted upstream:
http://lkml.org/lkml/2008/7/4/112

However, no reaction from maintainers.

Test status of the patch:
=========================
Tested by me. With patched kernel it produces such (correct) output:

err = 2052, errno = 0 (Success)
err = -1, errno = 11 (Resource temporarily unavailable)
err = -1, errno = 11 (Resource temporarily unavailable)
err = -1, errno = 11 (Resource temporarily unavailable)
err = -1, errno = 11 (Resource temporarily unavailable)

diff --git a/arch/powerpc/platforms/pseries/rtasd.c b/arch/powerpc/platforms/pseries/rtasd.c
index 2e4e040..83db911 100644
--- a/arch/powerpc/platforms/pseries/rtasd.c
+++ b/arch/powerpc/platforms/pseries/rtasd.c
@@ -297,19 +297,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 && !no_logging)
-		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 (no_logging) {
+			spin_unlock_irqrestore(&rtasd_log_lock, s);
+			error = -ENODATA;
+			goto out;
+		} else
+			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);