patch for 2.0.31 fs/nfs/nfsiod.c

Bill Hawes (whawes@star.net)
Mon, 11 Aug 1997 21:23:51 -0400


This is a multi-part message in MIME format.
--------------FA3A0CDE71116C7D3AE96600
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit

I've found a problem in the 2.0.31 nfsiod code that might explain some
of the posted problems with NFS. If one of the nfsiod tasks is awakened
by a signal, it fails to unlink its request structure and could possibly
corrupt the free list of requests.

Similarly, if the task is somehow awakened before its req has been
removed, nfsiod clears the request when it loops back to requeue the
request, which would corrupt the free list. The present code seems to
allow for the possibility of such a wakeup by testing whether slot is
non-NULL and doing a continue.

The attached patch checks the free_list immediately upon awakening, and
if it finds the request still queued prints a warning and unqueues it.
The nfsiod tasks can then continue safely.

If you're using NFS under 2.0.31 (and especially if you've had crash
problems), please test this and let me know if the warning message
appears.

Regards,
Bill
--------------FA3A0CDE71116C7D3AE96600
Content-Type: text/plain; charset=us-ascii; name="nfsiod_31-patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline; filename="nfsiod_31-patch"

--- fs/nfs/nfsiod.c.old Sat Jun 29 05:00:46 1996
+++ fs/nfs/nfsiod.c Mon Aug 11 17:58:58 1997
@@ -87,6 +87,7 @@
nfsiod(void)
{
struct nfsiod_req request, *req = &request;
+ struct nfsiod_req *next, **prev;
int result;

dprintk("BIO: nfsiod %d starting\n", current->pid);
@@ -101,10 +102,26 @@
dprintk("BIO: nfsiod %d waiting\n", current->pid);
interruptible_sleep_on(&req->rq_wait);

+ /*
+ * Make sure our request isn't still in the free list ...
+ * we might have been awakened by a signal.
+ */
+ prev = &free_list;
+ while ((next = *prev) != NULL) {
+ if (next == &request) {
+ printk("nfsiod: request still in free list!\n");
+ *prev = next->rq_next;
+ break;
+ }
+ prev = &next->rq_next;
+ }
+
if (current->signal & ~current->blocked)
break;
- if (!req->rq_rpcreq.rq_slot)
+ if (!req->rq_rpcreq.rq_slot) {
+ printk("nfsiod: no slot specified, sleeping again\n");
continue;
+ }
dprintk("BIO: nfsiod %d woken up; calling nfs_rpc_doio.\n",
current->pid);
active++;

--------------FA3A0CDE71116C7D3AE96600--