[PATCH 27/28] nfs: enable swap on NFS

2008-02-20 Thread Peter Zijlstra
Implement all the new swapfile a_ops for NFS. This will set the NFS socket to
SOCK_MEMALLOC and run socket reconnect under PF_MEMALLOC as well as reset
SOCK_MEMALLOC before engaging the protocol ->connect() method.

PF_MEMALLOC should allow the allocation of struct socket and related objects
and the early (re)setting of SOCK_MEMALLOC should allow us to receive the
packets required for the TCP connection buildup.

(swapping continues over a server reset during heavy network traffic)

Signed-off-by: Peter Zijlstra <[EMAIL PROTECTED]>
---
 fs/Kconfig  |   17 +++
 fs/nfs/file.c   |   12 
 fs/nfs/write.c  |   19 +
 include/linux/nfs_fs.h  |2 +
 include/linux/sunrpc/xprt.h |5 ++-
 net/sunrpc/sched.c  |9 --
 net/sunrpc/xprtsock.c   |   63 
 7 files changed, 124 insertions(+), 3 deletions(-)

Index: linux-2.6/fs/nfs/file.c
===
--- linux-2.6.orig/fs/nfs/file.c
+++ linux-2.6/fs/nfs/file.c
@@ -373,6 +373,13 @@ static int nfs_launder_page(struct page 
return nfs_wb_page(page_file_mapping(page)->host, page);
 }
 
+#ifdef CONFIG_NFS_SWAP
+static int nfs_swapfile(struct address_space *mapping, int enable)
+{
+   return xs_swapper(NFS_CLIENT(mapping->host)->cl_xprt, enable);
+}
+#endif
+
 const struct address_space_operations nfs_file_aops = {
.readpage = nfs_readpage,
.readpages = nfs_readpages,
@@ -387,6 +394,11 @@ const struct address_space_operations nf
.direct_IO = nfs_direct_IO,
 #endif
.launder_page = nfs_launder_page,
+#ifdef CONFIG_NFS_SWAP
+   .swapfile = nfs_swapfile,
+   .swap_out = nfs_swap_out,
+   .swap_in = nfs_readpage,
+#endif
 };
 
 static int nfs_vm_page_mkwrite(struct vm_area_struct *vma, struct page *page)
Index: linux-2.6/fs/nfs/write.c
===
--- linux-2.6.orig/fs/nfs/write.c
+++ linux-2.6/fs/nfs/write.c
@@ -362,6 +362,25 @@ int nfs_writepage(struct page *page, str
return ret;
 }
 
+int nfs_swap_out(struct file *file, struct page *page,
+struct writeback_control *wbc)
+{
+   struct nfs_open_context *ctx = nfs_file_open_context(file);
+   int status;
+
+   status = nfs_writepage_setup(ctx, page, 0, nfs_page_length(page));
+   if (status < 0) {
+   nfs_set_pageerror(page);
+   goto out;
+   }
+
+   status = nfs_writepage_locked(page, wbc);
+
+out:
+   unlock_page(page);
+   return status;
+}
+
 static int nfs_writepages_callback(struct page *page, struct writeback_control 
*wbc, void *data)
 {
int ret;
Index: linux-2.6/include/linux/nfs_fs.h
===
--- linux-2.6.orig/include/linux/nfs_fs.h
+++ linux-2.6/include/linux/nfs_fs.h
@@ -453,6 +453,8 @@ extern int  nfs_flush_incompatible(struc
 extern int  nfs_updatepage(struct file *, struct page *, unsigned int, 
unsigned int);
 extern int nfs_writeback_done(struct rpc_task *, struct nfs_write_data *);
 extern void nfs_writedata_release(void *);
+extern int  nfs_swap_out(struct file *file, struct page *page,
+struct writeback_control *wbc);
 
 /*
  * Try to write back everything synchronously (but check the
Index: linux-2.6/fs/Kconfig
===
--- linux-2.6.orig/fs/Kconfig
+++ linux-2.6/fs/Kconfig
@@ -1661,6 +1661,18 @@ config NFS_DIRECTIO
  causes open() to return EINVAL if a file residing in NFS is
  opened with the O_DIRECT flag.
 
+config NFS_SWAP
+   bool "Provide swap over NFS support"
+   default n
+   depends on NFS_FS
+   select SUNRPC_SWAP
+   help
+ This option enables swapon to work on files located on NFS mounts.
+
+ For more details, see Documentation/vm_deadlock.txt
+
+ If unsure, say N.
+
 config NFSD
tristate "NFS server support"
depends on INET
@@ -1794,6 +1806,11 @@ config SUNRPC_BIND34
  If unsure, say N to get traditional behavior (version 2 rpcbind
  requests only).
 
+config SUNRPC_SWAP
+   def_bool n
+   depends on SUNRPC
+   select NETVM
+
 config RPCSEC_GSS_KRB5
tristate "Secure RPC: Kerberos V mechanism (EXPERIMENTAL)"
depends on SUNRPC && EXPERIMENTAL
Index: linux-2.6/include/linux/sunrpc/xprt.h
===
--- linux-2.6.orig/include/linux/sunrpc/xprt.h
+++ linux-2.6/include/linux/sunrpc/xprt.h
@@ -143,7 +143,9 @@ struct rpc_xprt {
unsigned intmax_reqs;   /* total slots */
unsigned long   state;  /* transport state */
unsigned char   shutdown   : 1, /* being shut down */
-   resvport   : 1; /* use a reserved port */
+  

[PATCH 27/28] nfs: enable swap on NFS

2008-02-20 Thread Peter Zijlstra
Implement all the new swapfile a_ops for NFS. This will set the NFS socket to
SOCK_MEMALLOC and run socket reconnect under PF_MEMALLOC as well as reset
SOCK_MEMALLOC before engaging the protocol -connect() method.

PF_MEMALLOC should allow the allocation of struct socket and related objects
and the early (re)setting of SOCK_MEMALLOC should allow us to receive the
packets required for the TCP connection buildup.

(swapping continues over a server reset during heavy network traffic)

Signed-off-by: Peter Zijlstra [EMAIL PROTECTED]
---
 fs/Kconfig  |   17 +++
 fs/nfs/file.c   |   12 
 fs/nfs/write.c  |   19 +
 include/linux/nfs_fs.h  |2 +
 include/linux/sunrpc/xprt.h |5 ++-
 net/sunrpc/sched.c  |9 --
 net/sunrpc/xprtsock.c   |   63 
 7 files changed, 124 insertions(+), 3 deletions(-)

Index: linux-2.6/fs/nfs/file.c
===
--- linux-2.6.orig/fs/nfs/file.c
+++ linux-2.6/fs/nfs/file.c
@@ -373,6 +373,13 @@ static int nfs_launder_page(struct page 
return nfs_wb_page(page_file_mapping(page)-host, page);
 }
 
+#ifdef CONFIG_NFS_SWAP
+static int nfs_swapfile(struct address_space *mapping, int enable)
+{
+   return xs_swapper(NFS_CLIENT(mapping-host)-cl_xprt, enable);
+}
+#endif
+
 const struct address_space_operations nfs_file_aops = {
.readpage = nfs_readpage,
.readpages = nfs_readpages,
@@ -387,6 +394,11 @@ const struct address_space_operations nf
.direct_IO = nfs_direct_IO,
 #endif
.launder_page = nfs_launder_page,
+#ifdef CONFIG_NFS_SWAP
+   .swapfile = nfs_swapfile,
+   .swap_out = nfs_swap_out,
+   .swap_in = nfs_readpage,
+#endif
 };
 
 static int nfs_vm_page_mkwrite(struct vm_area_struct *vma, struct page *page)
Index: linux-2.6/fs/nfs/write.c
===
--- linux-2.6.orig/fs/nfs/write.c
+++ linux-2.6/fs/nfs/write.c
@@ -362,6 +362,25 @@ int nfs_writepage(struct page *page, str
return ret;
 }
 
+int nfs_swap_out(struct file *file, struct page *page,
+struct writeback_control *wbc)
+{
+   struct nfs_open_context *ctx = nfs_file_open_context(file);
+   int status;
+
+   status = nfs_writepage_setup(ctx, page, 0, nfs_page_length(page));
+   if (status  0) {
+   nfs_set_pageerror(page);
+   goto out;
+   }
+
+   status = nfs_writepage_locked(page, wbc);
+
+out:
+   unlock_page(page);
+   return status;
+}
+
 static int nfs_writepages_callback(struct page *page, struct writeback_control 
*wbc, void *data)
 {
int ret;
Index: linux-2.6/include/linux/nfs_fs.h
===
--- linux-2.6.orig/include/linux/nfs_fs.h
+++ linux-2.6/include/linux/nfs_fs.h
@@ -453,6 +453,8 @@ extern int  nfs_flush_incompatible(struc
 extern int  nfs_updatepage(struct file *, struct page *, unsigned int, 
unsigned int);
 extern int nfs_writeback_done(struct rpc_task *, struct nfs_write_data *);
 extern void nfs_writedata_release(void *);
+extern int  nfs_swap_out(struct file *file, struct page *page,
+struct writeback_control *wbc);
 
 /*
  * Try to write back everything synchronously (but check the
Index: linux-2.6/fs/Kconfig
===
--- linux-2.6.orig/fs/Kconfig
+++ linux-2.6/fs/Kconfig
@@ -1661,6 +1661,18 @@ config NFS_DIRECTIO
  causes open() to return EINVAL if a file residing in NFS is
  opened with the O_DIRECT flag.
 
+config NFS_SWAP
+   bool Provide swap over NFS support
+   default n
+   depends on NFS_FS
+   select SUNRPC_SWAP
+   help
+ This option enables swapon to work on files located on NFS mounts.
+
+ For more details, see Documentation/vm_deadlock.txt
+
+ If unsure, say N.
+
 config NFSD
tristate NFS server support
depends on INET
@@ -1794,6 +1806,11 @@ config SUNRPC_BIND34
  If unsure, say N to get traditional behavior (version 2 rpcbind
  requests only).
 
+config SUNRPC_SWAP
+   def_bool n
+   depends on SUNRPC
+   select NETVM
+
 config RPCSEC_GSS_KRB5
tristate Secure RPC: Kerberos V mechanism (EXPERIMENTAL)
depends on SUNRPC  EXPERIMENTAL
Index: linux-2.6/include/linux/sunrpc/xprt.h
===
--- linux-2.6.orig/include/linux/sunrpc/xprt.h
+++ linux-2.6/include/linux/sunrpc/xprt.h
@@ -143,7 +143,9 @@ struct rpc_xprt {
unsigned intmax_reqs;   /* total slots */
unsigned long   state;  /* transport state */
unsigned char   shutdown   : 1, /* being shut down */
-   resvport   : 1; /* use a reserved port */
+