[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

swap-nfs patch



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 to: