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);