Hello,

I found the patch on my harddisk. It was a patch against 2.0.21 which I am
using with a 2.0.30 kernel for half a year now. I tried to apply it to a
2.0.35-sparc kernel, which worked partly. I changed 2 hunks that where not
found in the new kernel (they just changed some indentation and things like
that). So here is the diff I got after that, I compiled it, and it runs on
my elc right now and uses a swapfile on nfs. I don't know where I found it
in the first place, the original filename was nfs-swap-2.0.21.dif. So I
cannot give any garanty for this patch, but I am pretty sure it works. I
will keep up the elc for a few ours and let it swap :-) I'll tell you
tomorrow if it shows any unusual behavior.

- Alexander

diff -u --recursive --new-file ./fs/Config.in.orig ./fs/Config.in
--- ./fs/Config.in.orig Fri Jul 26 14:59:47 1996
+++ ./fs/Config.in      Wed Aug  7 01:07:27 1996
@@ -21,6 +21,7 @@
 if [ "$CONFIG_INET" = "y" ]; then
   tristate 'NFS filesystem support' CONFIG_NFS_FS
   if [ "$CONFIG_NFS_FS" = "y" ]; then
+    bool '   Allow swap files to be on NFS filesystems' CONFIG_SWAP_NFS
     bool '   Root file system on NFS' CONFIG_ROOT_NFS
     if [ "$CONFIG_ROOT_NFS" = "y" ]; then
       bool '      BOOTP support' CONFIG_RNFS_BOOTP
diff -u --recursive --new-file ./fs/nfs/bio.c.orig ./fs/nfs/bio.c
--- ./fs/nfs/bio.c.orig Fri Jul 26 15:01:25 1996
+++ ./fs/nfs/bio.c      Sun Aug 11 20:23:22 1996
@@ -61,7 +61,7 @@
                if (count < rsize)
                        rsize = count;
                result = nfs_proc_read(NFS_SERVER(inode), NFS_FH(inode), 
-                       pos, rsize, buf, &fattr);
+                       pos, rsize, buf, &fattr, 0);
                dprintk("nfs_proc_read(%s, (%x,%lx), %ld, %d, %p) = %d\n",
                                NFS_SERVER(inode)->hostname,
                                inode->i_dev, inode->i_ino,
@@ -213,7 +213,7 @@
        dprintk("NFS: nfs_readpage %08lx\n", page_address(page));
        address = page_address(page);
        page->count++;
-       if (!PageError(page) && NFS_SERVER(inode)->rsize >= PAGE_SIZE)
+       if ( !NFS_SERVER(inode)->no_async && !PageError(page) && 
NFS_SERVER(inode)->rsize >= PAGE_SIZE)
                error = do_read_nfs_async(inode, page);
        if (error < 0)          /* couldn't enqueue */
                error = do_read_nfs_sync(inode, page);
diff -u --recursive --new-file ./fs/nfs/file.c.orig ./fs/nfs/file.c
--- ./fs/nfs/file.c.orig        Fri Jul 26 15:03:14 1996
+++ ./fs/nfs/file.c     Thu Aug  8 13:53:17 1996
@@ -134,8 +134,7 @@
                int hunk = count - written;
                if (hunk >= wsize)
                        hunk = wsize;
-               result = nfs_proc_write(inode,
-                       pos, hunk, buf, &fattr);
+               result = nfs_proc_write(inode, pos, hunk, buf, &fattr, 0);
                if (result < 0)
                        break;
                pos += hunk;
diff -u --recursive --new-file ./fs/nfs/inode.c.orig ./fs/nfs/inode.c
--- ./fs/nfs/inode.c.orig       Fri Jul 26 14:47:51 1996
+++ ./fs/nfs/inode.c    Mon Aug 12 01:25:27 1996
@@ -143,7 +143,7 @@
        sb->s_op = &nfs_sops;
        server = &sb->u.nfs_sb.s_server;
        server->file = filp;
-       server->lock = 0;
+       server->no_async = 0;
        server->wait = NULL;
        server->flags = data->flags;
        server->rsize = data->rsize;
@@ -343,6 +343,9 @@
        exit_mm(current);
        current->session = 1;
        current->pgrp = 1;
+#ifndef MODULE
+       current->blocked = ~0UL;
+#endif
        sprintf(current->comm, "nfsiod");
        ret = nfsiod();
        MOD_DEC_USE_COUNT;
diff -u --recursive --new-file ./fs/nfs/nfsiod.c.orig ./fs/nfs/nfsiod.c
--- ./fs/nfs/nfsiod.c.orig      Fri Jul 26 15:01:25 1996
+++ ./fs/nfs/nfsiod.c   Mon Aug 12 00:27:40 1996
@@ -90,6 +90,9 @@
        int                     result;
 
        dprintk("BIO: nfsiod %d starting\n", current->pid);
+#ifndef MODULE
+       current->blocked = ~0UL;
+#endif
        while (1) {
                /* Insert request into free list */
                memset(req, 0, sizeof(*req));
diff -u --recursive --new-file  ./fs/nfs/proc.c.orig ./fs/nfs/proc.c
--- ./fs/nfs/proc.c.orig        Fri Jul 26 15:01:25 1996
+++ ./fs/nfs/proc.c     Sun Aug 11 16:52:05 1996
@@ -43,6 +43,7 @@
 #include <linux/string.h>
 #include <linux/in.h>
 #include <linux/pagemap.h>
+#include <asm/pgtable.h>
 
 #include <asm/segment.h>
 
@@ -80,7 +81,7 @@
 {
        int *i;
 
-       while (!(i = (int *)kmalloc(size+NFS_SLACK_SPACE,GFP_NFS))) {
+       while (!(i = (int *)kmalloc(size/*+NFS_SLACK_SPACE*/,GFP_NFS))) {
                schedule();
        }
        return i;
@@ -142,13 +143,16 @@
 }
 
 
-static inline int *xdr_encode_data(int *p, const char *data, int len)
+static inline int *xdr_encode_data(int *p, const char *data, int len, int swap)
 {
        int quadlen = QUADLEN(len);
        
        p[quadlen] = 0;
        *p++ = htonl(len);
-       memcpy_fromfs(p, data, len);
+       if (!swap)
+               memcpy_fromfs(p, data, len);
+       else
+               memcpy(p, data, len);
        return p + quadlen;
 }
 
@@ -371,7 +375,8 @@
 }
 
 int nfs_proc_read(struct nfs_server *server, struct nfs_fh *fhandle,
-         int offset, int count, char *data, struct nfs_fattr *fattr)
+                 int offset, int count, char *data, struct nfs_fattr *fattr,
+                 int swap)
 {
        int *p, *p0;
        int status;
@@ -382,7 +387,11 @@
        if (!(p0 = nfs_rpc_alloc(server->rsize)))
                return -EIO;
 retry:
-       p = nfs_rpc_header(p0, NFSPROC_READ, ruid);
+       if (swap)
+               p= rpc_header(p0, NFSPROC_READ, NFS_PROGRAM, NFS_VERSION,
+                             init_task.uid, init_task.egid, init_task.groups);
+       else
+               p = nfs_rpc_header(p0, NFSPROC_READ, ruid);
        p = xdr_encode_fhandle(p, fhandle);
        *p++ = htonl(offset);
        *p++ = htonl(count);
@@ -492,7 +501,8 @@
 }
 
 int nfs_proc_write(struct inode * inode, int offset,
-                  int count, const char *data, struct nfs_fattr *fattr)
+                  int count, const char *data, struct nfs_fattr *fattr,
+                  int swap)
 {
        int *p, *p0;
        int status;
@@ -505,15 +515,20 @@
        if (!(p0 = nfs_rpc_alloc(server->wsize)))
                return -EIO;
 retry:
-       p = nfs_rpc_header(p0, NFSPROC_WRITE, ruid);
+       if (swap)
+               p= rpc_header(p0, NFSPROC_WRITE, NFS_PROGRAM, NFS_VERSION,
+                             init_task.uid, init_task.egid, init_task.groups);
+       else
+               p = nfs_rpc_header(p0, NFSPROC_WRITE, ruid);
        p = xdr_encode_fhandle(p, fhandle);
        *p++ = htonl(offset); /* traditional, could be any value */
        *p++ = htonl(offset);
        *p++ = htonl(count); /* traditional, could be any value */
        kdata = (void *) (p+1); /* start of data in RPC buffer */
-       p = xdr_encode_data(p, data, count);
+       p = xdr_encode_data(p, data, count, swap );
        if ((status = nfs_rpc_call(server, p0, p, server->wsize)) < 0) {
                nfs_rpc_free(p0);
+               printk("nfs_proc_write: status: %d\n", status );
                return status;
        }
        if (!(p = nfs_rpc_verify(p0)))
diff -u --recursive --new-file ./fs/nfs/rpcsock.c.orig ./fs/nfs/rpcsock.c
--- ./fs/nfs/rpcsock.c.orig     Thu Oct  3 01:30:11 1996
+++ ./fs/nfs/rpcsock.c  Thu Oct  3 13:15:49 1996
@@ -66,7 +66,11 @@
 static inline void
 rpc_insque(struct rpc_sock *rsock, struct rpc_wait *slot)
 {
-       struct rpc_wait *next = rsock->pending;
+       unsigned long   oldflags;
+       struct rpc_wait *next;
+
+       save_flags(oldflags); cli();
+       next = rsock->pending;
 
        slot->w_next = next;
        slot->w_prev = NULL;
@@ -75,6 +79,7 @@
        rsock->pending = slot;
        slot->w_queued = 1;
 
+       restore_flags(oldflags);
        dprintk("RPC: inserted %p into queue\n", slot);
 }
 
@@ -84,9 +89,12 @@
 static inline void
 rpc_remque(struct rpc_sock *rsock, struct rpc_wait *slot)
 {
-       struct rpc_wait *prev = slot->w_prev,
-                       *next = slot->w_next;
+       unsigned long   oldflags;
+       struct rpc_wait *prev, *next; 
 
+       save_flags(oldflags); cli();
+       prev = slot->w_prev,
+       next = slot->w_next;
        if (prev != NULL)
                prev->w_next = next;
        else
@@ -95,6 +103,8 @@
                next->w_prev = prev;
 
        slot->w_queued = 0;
+       restore_flags(oldflags);
+
        dprintk("RPC: removed %p from queue, head now %p.\n",
                        slot, rsock->pending);
 }
@@ -191,11 +201,14 @@
 int
 rpc_reserve(struct rpc_sock *rsock, struct rpc_ioreq *req, int nocwait)
 {
+       unsigned long oldflags;
        struct rpc_wait *slot;
 
        req->rq_slot = NULL;
 
-       while (!(slot = rsock->free) || rsock->cong >= rsock->cwnd) {
+       save_flags(oldflags); cli();
+       while (!(slot = rsock->free) || rsock->cong >= rsock->cwnd ) {
+               restore_flags(oldflags);
                if (nocwait) {
                        current->timeout = 0;
                        return -ENOBUFS;
@@ -208,6 +221,7 @@
                        return -ERESTARTSYS;
                if (rsock->shutdown)
                        return -EIO;
+               save_flags(oldflags); cli();
        }
 
        rsock->free = slot->w_next;
@@ -219,6 +233,7 @@
 
        dprintk("RPC: reserved slot %p\n", slot);
        req->rq_slot = slot;
+       restore_flags(oldflags);
        return 0;
 }
 
@@ -228,6 +243,7 @@
 void
 rpc_release(struct rpc_sock *rsock, struct rpc_ioreq *req)
 {
+       unsigned long oldflags;
        struct rpc_wait *slot = req->rq_slot;
 
        if (slot != NULL) {
@@ -237,6 +253,7 @@
                if (slot == rsock->pending && slot->w_next != NULL)
                        wake_up(&slot->w_next->w_wait);
 
+               save_flags(oldflags); cli();
                /* remove slot from queue of pending */
                if (slot->w_queued)
                        rpc_remque(rsock, slot);
@@ -245,7 +262,9 @@
 
                /* decrease congestion value */
                rsock->cong -= RPC_CWNDSCALE;
-               if (rsock->cong < rsock->cwnd && rsock->backlog)
+               restore_flags(oldflags); 
+               
+               if (rsock->cong < rsock->cwnd && 
waitqueue_active(&rsock->backlog))
                        wake_up(&rsock->backlog);
                if (rsock->shutdown)
                        wake_up(&rsock->shutwait);
diff -u --recursive --new-file ./fs/nfs/sock.c.orig ./fs/nfs/sock.c
--- ./fs/nfs/sock.c.orig        Fri Jul 26 14:40:24 1996
+++ ./fs/nfs/sock.c     Sun Aug 11 16:45:46 1996
@@ -87,8 +87,21 @@
        maxtimeo = timeout.to_maxval;
 
        do {
+#ifdef CONFIG_SWAP_NFS
+#ifdef DEBUG_SWAP_NFS
+               if ( current->doing_nfs ) {
+                       printk( LOG_WARN"Dangerous: current %s already "
+                               "doing nfs. This may lock your system!\n",
+                               current->comm );
+               }
+#endif
+               current->doing_nfs = 1;
+#endif
                result = rpc_doio(server->rsock, req, &timeout, async);
                rpc_release(server->rsock, req);        /* Release slot */
+#ifdef CONFIG_SWAP_NFS
+               current->doing_nfs = 0;
+#endif
 
                if (current->signal & ~current->blocked)
                        result = -ERESTARTSYS;
diff -u --recursive --new-file ./include/linux/nfs_fs.h.orig 
./include/linux/nfs_fs.h
--- ./include/linux/nfs_fs.h.orig       Fri Jul 26 15:03:14 1996
+++ ./include/linux/nfs_fs.h    Thu Oct  3 01:54:01 1996
@@ -73,9 +73,10 @@
                        unsigned int maxlen);
 extern int nfs_proc_read(struct nfs_server *server, struct nfs_fh *fhandle,
                         int offset, int count, char *data,
-                        struct nfs_fattr *fattr);
+                        struct nfs_fattr *fattr, int swap);
 extern int nfs_proc_write(struct inode * inode, int offset,
-                         int count, const char *data, struct nfs_fattr *fattr);
+                         int count, const char *data, struct nfs_fattr *fattr,
+                         int swap);
 extern int nfs_proc_create(struct nfs_server *server, struct nfs_fh *dir,
                           const char *name, struct nfs_sattr *sattr,
                           struct nfs_fh *fhandle, struct nfs_fattr *fattr);
diff -u --recursive --new-file ./include/linux/nfs_fs_sb.h.orig 
./include/linux/nfs_fs_sb.h
--- ./include/linux/nfs_fs_sb.h.orig    Fri Jul 26 14:22:14 1996
+++ ./include/linux/nfs_fs_sb.h Sun Aug 11 19:19:38 1996
@@ -8,7 +8,7 @@
        struct file *file;
        struct rpc_sock *rsock;
        struct sockaddr toaddr ;  /* Added for change to NFS code to use 
sendto()  1995-06-02  JSP */
-       int lock;
+       int no_async;
        struct wait_queue *wait;
        int flags;
        int rsize;
diff -u --recursive --new-file ./include/linux/rpcsock.h.orig 
./include/linux/rpcsock.h
--- ./include/linux/rpcsock.h.orig      Fri Jul 26 14:59:48 1996
+++ ./include/linux/rpcsock.h   Sun Aug 11 16:51:33 1996
@@ -23,11 +23,11 @@
  * MAXREQS value: At 32 outstanding reqs with 8 megs of RAM, fragment
  * reassembly will frequently run out of memory.
  */
-#define RPC_MAXREQS            32
+#define RPC_MAXREQS            32
 #define RPC_CWNDSCALE          256
 #define RPC_MAXCWND            (RPC_MAXREQS * RPC_CWNDSCALE)
 /* #define RPC_INITCWND                (RPC_MAXCWND / 2) */
-#define RPC_INITCWND           RPC_CWNDSCALE
+#define RPC_INITCWND           RPC_CWNDSCALE 
 #define RPC_CONGESTED(rsock)   ((rsock)->cong >= (rsock)->cwnd)
 
 /* RPC reply header size: xid, direction, status, accept_status (verifier
@@ -83,6 +83,7 @@
        char                    w_queued;
        char                    w_gotit;
        __u32                   w_xid;
+       struct task_struct      *w_task;
 };
 
 struct rpc_sock {
diff -u --recursive --new-file ./include/linux/sched.h.orig 
./include/linux/sched.h
--- ./include/linux/sched.h.orig        Thu Oct  3 01:30:36 1996
+++ ./include/linux/sched.h     Thu Oct  3 01:48:54 1996
@@ -218,6 +218,10 @@
 /* mm fault and swap info: this can arguably be seen as either mm-specific or 
thread-specific */
        unsigned long min_flt, maj_flt, nswap, cmin_flt, cmaj_flt, cnswap;
        int swappable:1;
+       int doing_nfs:1; /* this is set whenever the task does nfs, 
+                         * let's it allocate more memory to prevent deadlocks
+                         * when swapping to nfs. 
+                         */
        unsigned long swap_address;
        unsigned long old_maj_flt;      /* old value of maj_flt */
        unsigned long dec_flt;          /* page fault count of the last time */
@@ -297,7 +301,7 @@
 /* timer */    { NULL, NULL, 0, 0, it_real_fn }, \
 /* utime */    0,0,0,0,0, \
 /* flt */      0,0,0,0,0,0, \
-/* swp */      0,0,0,0,0, \
+/* swp */      0,0,0,0,0,0, \
 /* rlimits */   INIT_RLIMITS, \
 /* math */     0, \
 /* comm */     "swapper", \
diff -u --recursive --new-file ./include/linux/swap.h.orig 
./include/linux/swap.h
--- ./include/linux/swap.h.orig Fri Jul 26 14:59:15 1996
+++ ./include/linux/swap.h      Wed Aug  7 00:50:36 1996
@@ -11,8 +11,10 @@
 
 #include <asm/atomic.h>
 
-#define SWP_USED       1
-#define SWP_WRITEOK    3
+#define SWP_USED       0x01
+#define SWP_WRITEOK    0x03
+#define SWP_ISNFS      0x04
+#define SWP_NFSLOCK    0x08
 
 #define SWAP_CLUSTER_MAX 32
 
diff -u --recursive --new-file ./mm/page_io.c.orig ./mm/page_io.c
--- ./mm/page_io.c.orig Thu Oct  3 01:30:12 1996
+++ ./mm/page_io.c      Wed Oct  2 23:42:24 1996
@@ -8,6 +8,7 @@
  *  Removed race in async swapping. 14.4.1996. Bruno Haible
  */
 
+#include <linux/config.h>
 #include <linux/mm.h>
 #include <linux/sched.h>
 #include <linux/head.h>
@@ -20,6 +21,12 @@
 #include <linux/fs.h>
 #include <linux/locks.h>
 #include <linux/swapctl.h>
+#ifdef CONFIG_SWAP_NFS
+#include <linux/nfs.h>
+#include <linux/nfs_fs.h>
+#include <linux/nfs_fs_i.h>
+#include <linux/nfs_fs_sb.h>
+#endif
 
 #include <asm/dma.h>
 #include <asm/system.h> /* for cli()/sti() */
@@ -27,8 +34,15 @@
 #include <asm/bitops.h>
 #include <asm/pgtable.h>
 
+#ifdef CONFIG_SWAP_NFS
+/* This is incremented each swapping via nfs is attempted, and decremented
+ * after having finished the nfs swap. It overrides (together with 
+ * current->doing_nfs the priority field in __get_free_pages() to prevent
+ * deadlocks when swapping via nfs.
+ */
+int nfs_swap_active = 0;
+#endif
 static struct wait_queue * lock_queue = NULL;
-
 /*
  * Reads or writes a swap page.
  * wait=1: start I/O and wait for completion. wait=0: start asynchronous I/O.
@@ -99,6 +113,47 @@
                struct inode *swapf = p->swap_file;
                unsigned int zones[PAGE_SIZE/512];
                int i;
+#ifdef CONFIG_SWAP_NFS
+               if ((p->flags & SWP_ISNFS) == SWP_ISNFS) {
+                       int j;
+                       struct nfs_fattr fattr;
+                       unsigned int block = offset * PAGE_SIZE;
+
+                       nfs_swap_active++;
+
+                       if (rw == READ) {
+                               int n = NFS_SERVER(swapf)->rsize;
+                               if (n > PAGE_SIZE)
+                                       n = PAGE_SIZE;
+                               for (i = 0; i < PAGE_SIZE; i += n) {
+                                       j = nfs_proc_read(NFS_SERVER(swapf),
+                                               NFS_FH(swapf), block, n, buf,
+                                               &fattr, 1);
+                                       if (j < n) break;
+                                       block += n;
+                                       buf   += n;
+                               }
+                       } else {
+                               int n = NFS_SERVER(swapf)->wsize;
+                               if (n > PAGE_SIZE)
+                                       n = PAGE_SIZE;
+                               for (i = 0; i < PAGE_SIZE; i += n) {
+                                       j = nfs_proc_write(swapf, block, n, buf,
+                                                          &fattr, 1);
+                                       if (j < 0) break;
+                                       block += n;
+                                       buf   += n;
+                               }
+                       }
+                       nfs_refresh_inode(swapf, &fattr);
+                       
+                       nfs_swap_active--;
+                       
+                       if (i < PAGE_SIZE || j < 0)
+                               printk("rw_swap_page: NFS swap file error %d, 
offset %u (%s)\n", 
+                                      j, block, (rw == READ) ? "reading" : 
"writing");
+               } else
+#endif
                if (swapf->i_op->bmap == NULL
                        && swapf->i_op->smap != NULL){
                        /*
@@ -122,6 +177,7 @@
                                        return;
                                }
                        }
+                       ll_rw_swap_file(rw,swapf->i_dev, zones, i,buf);
                }else{
                        int j;
                        unsigned int block = offset
@@ -131,8 +187,8 @@
                                if (!(zones[i] = bmap(swapf,block++))) {
                                        printk("rw_swap_page: bad swap file\n");
                                }
+                       ll_rw_swap_file(rw,swapf->i_dev, zones, i,buf);
                }
-               ll_rw_swap_file(rw,swapf->i_dev, zones, i,buf);
        } else
                printk("rw_swap_page: no swap file or device\n");
        atomic_dec(&page->count);
diff -u --recursive --new-file ./mm/swapfile.c.orig ./mm/swapfile.c
--- ./mm/swapfile.c.orig        Fri Jul 26 15:01:32 1996
+++ ./mm/swapfile.c     Sun Aug 11 19:50:41 1996
@@ -17,6 +17,12 @@
 #include <linux/fs.h>
 #include <linux/swapctl.h>
 #include <linux/blkdev.h> /* for blk_size */
+#ifdef CONFIG_SWAP_NFS
+#include <linux/nfs.h>
+#include <linux/nfs_fs.h>
+#include <linux/nfs_fs_i.h>
+#include <linux/nfs_fs_sb.h>
+#endif
 
 #include <asm/dma.h>
 #include <asm/system.h> /* for cli()/sti() */
@@ -354,7 +360,8 @@
                /* just pick something that's safe... */
                swap_list.next = swap_list.head;
        }
-       p->flags = SWP_USED;
+       p->flags &= ~SWP_WRITEOK;
+       p->flags |= SWP_USED;
        err = try_to_unuse(type);
        if (err) {
                iput(inode);
@@ -367,7 +374,7 @@
                        swap_list.head = swap_list.next = p - swap_info;
                else
                        swap_info[prev].next = p - swap_info;
-               p->flags = SWP_WRITEOK;
+               p->flags |= SWP_WRITEOK;
                return err;
        }
        if(p->swap_device){
@@ -381,6 +388,12 @@
                        filp.f_op->release(inode,&filp);
                }
        }
+#ifdef CONFIG_SWAP_NFS
+       else if ((p->flags & SWP_ISNFS) == SWP_ISNFS) {
+               NFS_SERVER(p->swap_file)->no_async--; /* re-enable async reads
+                                                      */
+       }
+#endif
        iput(inode);
 
        nr_swap_pages -= p->pages;
@@ -471,12 +484,25 @@
                }
        } else if (!S_ISREG(swap_inode->i_mode))
                goto bad_swap;
+#ifdef CONFIG_SWAP_NFS
+       else if (swap_inode->i_sb &&
+                swap_inode->i_sb->s_type &&
+                swap_inode->i_sb->s_type->name &&
+                !strcmp(swap_inode->i_sb->s_type->name, "nfs")) {
+               p->flags |= SWP_ISNFS;
+               NFS_SERVER(swap_inode)->no_async++; /* async reads really 
+                                                    * doesn't  work
+                                                    */
+       }
+#endif
        p->swap_lockmap = (unsigned char *) get_free_page(GFP_USER);
        if (!p->swap_lockmap) {
                printk("Unable to start swapping: out of memory :-)\n");
                error = -ENOMEM;
                goto bad_swap;
        }
+
+
        read_swap_page(SWP_ENTRY(type,0), (char *) p->swap_lockmap);
        if (memcmp("SWAP-SPACE",p->swap_lockmap+PAGE_SIZE-10,10)) {
                printk("Unable to find swap-space signature\n");
@@ -514,7 +540,7 @@
        }
        p->swap_map[0] = 0x80;
        memset(p->swap_lockmap,0,PAGE_SIZE);
-       p->flags = SWP_WRITEOK;
+       p->flags |= SWP_WRITEOK;
        p->pages = j;
        nr_swap_pages += j;
        printk("Adding Swap: %dk swap-space\n",j<<(PAGE_SHIFT-10));
*** ./mm/vmscan.c.orig  Mon Jul 13 22:47:40 1998
--- ./mm/vmscan.c       Mon Nov 30 19:56:32 1998
***************
*** 138,143 ****
--- 138,154 ----
                        printk("Aiee.. duplicated cached swap-cache entry\n");
                        return 0;
                }
+ #ifdef CONFIG_SWAP_NFS
+                 /* This must be checked. kmalloc calls sometimes try_to_
+                  * and kmalloc is called from inside the nfs code.
+                  */
+                 if ( current->doing_nfs &&
+                    (swap_info[SWP_TYPE(entry)].flags & SWP_ISNFS) == 
SWP_ISNFS ) {
+                       /* avoid loops when using kmalloc during nfs swapping
+                        */
+                       return 0;
+               }
+ #endif
                vma->vm_mm->rss--;
                flush_cache_page(vma, address);
                set_pte(page_table, __pte(entry));
*** ./mm/page_alloc.c.orig      Mon Jul 13 22:47:40 1998
--- ./mm/page_alloc.c   Mon Nov 30 19:49:51 1998
***************
*** 29,34 ****
--- 29,44 ----
  
  extern struct wait_queue *buffer_wait;
  
+ /* 
+  * This is set in linux/mm/page_io.c and is necessary to avoid dead locks
+  * when using a NFS filesystem. It overrides the priority field of kmalloc
+  * when requesting memory through any of the network modules during NFS
+  * operations.
+  */
+ #ifdef CONFIG_SWAP_NFS
+ extern int nfs_swap_active;
+ #endif
+ 
  /*
   * Free area management
   *
***************
*** 207,215 ****
                        priority = GFP_ATOMIC;
                }
        }
!       reserved_pages = 5;
!       if (priority != GFP_NFS)
!               reserved_pages = min_free_pages;
        if ((priority == GFP_BUFFER || priority == GFP_IO) && reserved_pages >= 
48)
                reserved_pages -= (12 + (reserved_pages>>3));
        save_flags(flags);
--- 217,234 ----
                        priority = GFP_ATOMIC;
                }
        }
!         reserved_pages = min_free_pages;
! #ifdef CONFIG_SWAP_NFS
! #undef DEBUG_SWAP_NFS_RESERVED_PAGES_HACK
! #ifdef DEBUG_SWAP_NFS_RESERVED_PAGES_HACK
!         if ( (priority != GFP_NFS) && (current->doing_nfs && nfs_swap_active 
&& (nr_free_pages < reserved_pages)) )
!                 printk("nfs_pid effective, reserved: %d, free: %d!\n", 
reservedpages, nr_free_pages);
! #endif
!         if ( (priority == GFP_NFS) || (current->doing_nfs && nfs_swap_active) 
)
! #else
!         if (priority == GFP_NFS)
! #endif
!                 reserved_pages = 5;
        if ((priority == GFP_BUFFER || priority == GFP_IO) && reserved_pages >= 
48)
                reserved_pages -= (12 + (reserved_pages>>3));
        save_flags(flags);

Reply via email to