3 # Patch managed by http://www.mn-logistik.de/unsupported/pxa250/patcher
6 --- /dev/null 2004-04-06 13:56:48.000000000 -0400
7 +++ linux-2.4.20/Documentation/netswap.txt 2005-01-07 02:55:48.022456424 -0500
9 + Swapping over network
11 +Support for this is enabled via the CONFIG_NETSWAP option, which is
12 +automatically enabled when enabling swap files located on NFS volumes
13 +(CONFIG_SWAP_VIA_NFS).
15 +When swapping to files located on a network file system like NFS or
16 +CODA or others or to nbd (network block device, see `nbd.txt')
17 +partitions there is the problem that this requires additional memory,
18 +besides the page which is currently swapped in or out, probably at
19 +least two more pages for each page in question.
21 +This means that not only there needs to be free space left in the swap
22 +file or the swap partition, but in addition there must be enough free
23 +memory left in the system to perform the swap out of pages.
25 +This is particularly painful as receiving data over the network itself
26 +consumes memory, and this memory is allocated from an interrupt
27 +context (i.e. in the interrupt handler of the network card). That
28 +means that on a congested network there are chances that the machine
29 +runs out of memory, simply because the network device's interrupt
30 +routines allocate memory faster that it is freed by swapping via
33 +To cope with this problem, there is a new socket option `SO_SWAPPING'
34 +which has to be set on the `SOL_SOCKET' level with setsockopt() (see
35 +setsockopt(2)). When this option is set on any network socket, then
36 +the system will start to drop network packets it receives on any other
37 +socket when the number of free pages falls below a certain threshold.
39 +This threshold initially is 4 pages less than `freepages.min' (see
40 +`Documentation/sysctl/vm.txt') but can be tuned using the sysctl
41 +interface by writing to the file `/proc/sys/net/swapping/threshold'
43 +There are two other files:
45 +`/proc/sys/net/swapping/dropped':
46 + how many network packets have been dropped so far. This file is
47 + writable, writing to it simply sets the counter to the given value
48 + (useful for resetting the counter).
50 +`/proc/sys/net/swapping/sock_count':
51 + How many network sockets have the `SO_SWAPPING' option set (read
54 +When using swap-files on NFS volumes, then the `SO_SWAPPING' option is
55 +set or cleared by swapon/swapoff system calls, so the user need not
58 +Swapping over the network is insecure unless the data would be
59 +encrypted, which is not the case with NFS. It is also very slow.
60 --- /dev/null 2004-04-06 13:56:48.000000000 -0400
61 +++ linux-2.4.20/Documentation/nfsswap.txt 2005-01-07 02:55:48.022456424 -0500
63 + Swapping to files on NFS volumes
65 +To do this you have to say `Y' or `M' to the CONFIG_SWAP_VIA_NFS
66 +configuration option. When compling support for this as a module you
67 +should read `Documentation/modules.txt'. For auto-loading of the
68 +module during the `swapon' system call you have to place a line like
70 +alias swapfile-mod nfsswap
72 +in `/etc/modules.conf' (or `/etc/conf.modules', depending on your
73 +setup). NFS volumes holding swapfile should be mounted with `rsize'
74 +and `wsize' set to something less than the size of a page, otherwise
75 +deadlocks caused by memory fragmentation can happen, i.e. mount the
76 +volume which is to hold the swapfiles with
78 +mount -t nfs -o rsize=2048,wsize=2048 NFS_SERVER_IP:/server_volume /mount_point
80 +or set the option in `/etc/fstab'. Read `Documentation/nfsroot.txt' to
81 +learn how to set mount options for the root file system, if your swap
82 +files are to be located on the root file system.
84 +Setting the `rsize' and `wsize' to anything less than PAGE_SIZE is a
85 +performance hit, so you probably want to have at least two volumes
86 +mounted, one for the swapfiles, one for the rest.
88 +You may want to read `Documentation/netswap.txt' as well.
90 +Swapfiles on NFS volumes can be treated like any other swapfile,
93 +dd if=/dev/zero of=/swapfiles/SWAPFILE bs=1k count=20480
94 +mkswap /swapfiles/SWAPFILE
95 +swapon /swapfiles/SWAPFILE
97 +will create a 20M swapfile and tell the system to use it. Actually,
98 +one could use lseek(2) to create an empty swapfile. This is different
99 +from swapfiles located on local harddisk.
101 +Swapping over the network is insecure unless the data would be
102 +encrypted, which is not the case with NFS. It is also very slow.
104 --- linux-2.4.20/drivers/block/blkpg.c~130-nfsswap 2002-08-02 20:39:43.000000000 -0400
105 +++ linux-2.4.20/drivers/block/blkpg.c 2005-01-07 02:55:48.022456424 -0500
107 #include <linux/blk.h> /* for set_device_ro() */
108 #include <linux/blkpg.h>
109 #include <linux/genhd.h>
110 -#include <linux/swap.h> /* for is_swap_partition() */
111 +#include <linux/swap.h> /* for swap_run_test() */
112 #include <linux/module.h> /* for EXPORT_SYMBOL */
114 #include <asm/uaccess.h>
119 +/* swap_run_test() applies this hook to all swapfiles until it returns
120 + * "1". If it never returns "1", the result of swap_run_test() is "0",
123 +static int is_swap_partition_hook(unsigned int flags, struct file *swap_file,
126 + kdev_t swap_dev = S_ISBLK(swap_file->f_dentry->d_inode->i_mode)
127 + ? swap_file->f_dentry->d_inode->i_rdev : 0;
128 + kdev_t dev = *((kdev_t *)testdata);
130 + if (flags & SWP_USED && dev == swap_dev) {
137 +static inline int is_swap_partition(kdev_t dev)
139 + return swap_run_test(is_swap_partition_hook, &dev);
143 * Delete a partition given by partition number
145 --- linux-2.4.20/fs/Config.in~130-nfsswap 2005-01-07 02:54:46.352831000 -0500
146 +++ linux-2.4.20/fs/Config.in 2005-01-07 02:55:48.023456272 -0500
148 mainmenu_option next_comment
149 comment 'File systems'
151 +if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
152 + tristate 'Swapping to block devices' CONFIG_BLKDEV_SWAP
154 + define_bool CONFIG_BLKDEV_SWAP y
157 bool 'Quota support' CONFIG_QUOTA
158 tristate 'Kernel automounter support' CONFIG_AUTOFS_FS
159 tristate 'Kernel automounter version 4 support (also supports v3)' CONFIG_AUTOFS4_FS
161 dep_tristate 'NFS file system support' CONFIG_NFS_FS $CONFIG_INET
162 dep_mbool ' Provide NFSv3 client support' CONFIG_NFS_V3 $CONFIG_NFS_FS
163 dep_bool ' Root file system on NFS' CONFIG_ROOT_NFS $CONFIG_NFS_FS $CONFIG_IP_PNP
164 + if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
165 + dep_tristate ' Swapping via NFS (EXPERIMENTAL)' CONFIG_SWAP_VIA_NFS $CONFIG_NFS_FS
166 + if [ "$CONFIG_SWAP_VIA_NFS" = "y" -o "$CONFIG_SWAP_VIA_NFS" = "m" ]; then
167 + define_bool CONFIG_NETSWAP y
171 dep_tristate 'NFS server support' CONFIG_NFSD $CONFIG_INET
172 dep_mbool ' Provide NFSv3 server support' CONFIG_NFSD_V3 $CONFIG_NFSD
173 --- linux-2.4.20/fs/Makefile~130-nfsswap 2005-01-07 02:54:46.353831000 -0500
174 +++ linux-2.4.20/fs/Makefile 2005-01-07 02:55:48.023456272 -0500
178 export-objs := filesystems.o open.o dcache.o buffer.o
180 +mod-subdirs := nls nfs
182 obj-y := open.o read_write.o devices.o file_table.o buffer.o \
183 super.o block_dev.o char_dev.o stat.o exec.o pipe.o namei.o \
185 subdir-$(CONFIG_JFS_FS) += jfs
186 subdir-$(CONFIG_SQUASHFS) += squashfs
188 +obj-$(CONFIG_BLKDEV_SWAP) += blkdev_swap.o
190 obj-$(CONFIG_BINFMT_AOUT) += binfmt_aout.o
191 obj-$(CONFIG_BINFMT_EM86) += binfmt_em86.o
192 --- /dev/null 2004-04-06 13:56:48.000000000 -0400
193 +++ linux-2.4.20/fs/blkdev_swap.c 2005-01-07 02:55:48.023456272 -0500
196 + * Swapping to partitions or files located on partitions.
199 +#include <linux/config.h>
200 +#include <linux/module.h>
201 +#include <linux/init.h>
202 +#include <linux/slab.h>
203 +#include <linux/locks.h>
204 +#include <linux/blkdev.h>
205 +#include <linux/pagemap.h>
206 +#include <linux/swap.h>
207 +#include <linux/fs.h>
209 +#ifdef DEBUG_BLKDEV_SWAP
210 +# define dprintk(fmt...) printk(##fmt)
212 +# define dprintk(fmt...) do { /* */ } while (0)
215 +#define BLKDEV_SWAP_ID "blkdev"
216 +#define BLKDEV_FILE_SWAP_ID "blkdev file"
219 + * Helper function, copied here from buffer.c
223 + * Start I/O on a page.
224 + * This function expects the page to be locked and may return
225 + * before I/O is complete. You then have to check page->locked
226 + * and page->uptodate.
228 + * brw_page() is SMP-safe, although it's being called with the
229 + * kernel lock held - but the code is ready.
231 + * FIXME: we need a swapper_inode->get_block function to remove
232 + * some of the bmap kludges and interface ugliness here.
234 +int brw_page(int rw, struct page *page, kdev_t dev, int b[], int size)
236 + struct buffer_head *head, *bh;
238 + if (!PageLocked(page))
239 + panic("brw_page: page not locked for I/O");
241 + if (!page->buffers)
242 + create_empty_buffers(page, dev, size);
243 + head = bh = page->buffers;
245 + /* Stage 1: lock all the buffers */
248 + bh->b_blocknr = *(b++);
249 + set_bit(BH_Mapped, &bh->b_state);
250 + set_buffer_async_io(bh);
251 + bh = bh->b_this_page;
252 + } while (bh != head);
254 + /* Stage 2: start the IO */
256 + struct buffer_head *next = bh->b_this_page;
259 + } while (bh != head);
264 + * We implement to methods: swapping to partitions, and swapping to files
265 + * located on partitions.
268 +struct blkdev_swap_data {
273 + struct file * filp;
277 +static int is_blkdev_swapping(unsigned int flags,
278 + struct file * swapf,
281 + struct test_data *testdata = (struct test_data *) data;
282 + struct file * filp = testdata->filp;
283 + kdev_t dev = testdata->dev;
285 + /* Only check filp's that don't match the one already opened
286 + * for us by sys_swapon(). Otherwise, we will always flag a
290 + if (swapf != filp) {
291 + if (dev == swapf->f_dentry->d_inode->i_rdev)
297 +static int blkdev_swap_open(struct file * filp, void **dptr)
301 + struct blkdev_swap_data *data;
303 + struct test_data testdata;
307 + if (!S_ISBLK(filp->f_dentry->d_inode->i_mode)) {
308 + dprintk(__FUNCTION__": can't handle this swap file: %s\n",
309 + swapf->d_name.name);
310 + error = 0; /* not for us */
314 + dev = filp->f_dentry->d_inode->i_rdev;
315 + set_blocksize(dev, PAGE_SIZE);
318 + (blk_size[MAJOR(dev)] && !blk_size[MAJOR(dev)][MINOR(dev)])) {
319 + printk("blkdev_swap_open: blkdev weirdness for %s\n",
320 + filp->f_dentry->d_name.name);
324 + /* Check to make sure that we aren't already swapping. */
326 + testdata.filp = filp;
327 + testdata.dev = dev;
328 + if (swap_run_test(is_blkdev_swapping, &testdata)) {
329 + printk("blkdev_swap_open: already swapping to %s\n",
330 + filp->f_dentry->d_name.name);
335 + if (blk_size[MAJOR(dev)])
336 + swapfilesize = blk_size[MAJOR(dev)][MINOR(dev)]
337 + >> (PAGE_SHIFT - 10);
339 + if ((data = kmalloc(sizeof(*data), GFP_KERNEL)) == NULL) {
340 + printk("blkdev_swap_open: can't allocate data for %s\n",
341 + filp->f_dentry->d_name.name);
348 + dprintk("blkdev_swap_open: returning %d\n", swapfilesize);
349 + return swapfilesize;
353 + return error; /* this swap thing is not for us */
356 +static int blkdev_swap_release(struct file * filp, void *data)
358 + dprintk("blkdev_swap_release: releasing swap device %s\n",
359 + filp->f_dentry->d_name.name);
365 +static int blkdev_rw_page(int rw, struct page *page, unsigned long offset,
368 + struct blkdev_swap_data *data = (struct blkdev_swap_data *)ptr;
369 + brw_page(rw, page, data->dev, (int *)&offset, PAGE_SIZE);
373 +static struct swap_ops blkdev_swap_ops = {
375 + blkdev_swap_release,
379 +struct blkdevfile_swap_data {
380 + struct inode *swapf;
383 +static int is_blkdevfile_swapping(unsigned int flags,
384 + struct file * swapf,
387 + struct file * filp = (struct file *) data;
389 + /* Only check filp's that don't match the one already opened
390 + * for us by sys_swapon(). Otherwise, we will always flag a
394 + if (swapf != filp) {
395 + if (filp->f_dentry->d_inode == swapf->f_dentry->d_inode)
401 +static int blkdevfile_swap_open(struct file *swapf, void **dptr)
405 + struct blkdevfile_swap_data *data;
409 + /* first check whether this is a regular file located on a local
412 + if (!S_ISREG(swapf->f_dentry->d_inode->i_mode)) {
413 + dprintk("blkdevfile_swap_open: "
414 + "can't handle this swap file: %s\n",
415 + swapf->d_name.name);
416 + error = 0; /* not for us */
419 + if (!swapf->f_dentry->d_inode->i_mapping->a_ops->bmap) {
420 + dprintk("blkdevfile_swap_open: no bmap for file: %s\n",
421 + swapf->d_name.name);
422 + error = 0; /* not for us */
426 + if (swap_run_test(is_blkdevfile_swapping, swapf)) {
427 + dprintk("blkdevfile_swap_open: already swapping to %s\n",
428 + swapf->d_name.name);
432 + swapfilesize = swapf->f_dentry->d_inode->i_size >> PAGE_SHIFT;
433 + if ((data = kmalloc(sizeof(*data), GFP_KERNEL)) == NULL) {
437 + data->swapf = swapf->f_dentry->d_inode;
439 + return swapfilesize;
446 +static int blkdevfile_swap_release(struct file *swapf, void *data)
453 +static int blkdevfile_rw_page(int rw, struct page *page, unsigned long offset,
456 + struct blkdevfile_swap_data *data = (struct blkdevfile_swap_data *)ptr;
457 + struct inode * swapf = data->swapf;
459 + unsigned int block = offset
460 + << (PAGE_SHIFT - swapf->i_sb->s_blocksize_bits);
461 + kdev_t dev = swapf->i_dev;
463 + int zones[PAGE_SIZE/512];
466 + block_size = swapf->i_sb->s_blocksize;
467 + for (i=0, j=0; j< PAGE_SIZE ; i++, j += block_size)
468 + if (!(zones[i] = bmap(swapf,block++))) {
469 + printk("blkdevfile_rw_page: bad swap file\n");
474 + /* block_size == PAGE_SIZE/zones_used */
475 + brw_page(rw, page, dev, zones, block_size);
479 +static struct swap_ops blkdevfile_swap_ops = {
480 + blkdevfile_swap_open,
481 + blkdevfile_swap_release,
485 +int __init blkdev_swap_init(void)
487 + (void)register_swap_method(BLKDEV_SWAP_ID, &blkdev_swap_ops);
488 + (void)register_swap_method(BLKDEV_FILE_SWAP_ID, &blkdevfile_swap_ops);
492 +void __exit blkdev_swap_exit(void)
494 + unregister_swap_method(BLKDEV_SWAP_ID);
495 + unregister_swap_method(BLKDEV_FILE_SWAP_ID);
498 +module_init(blkdev_swap_init)
499 +module_exit(blkdev_swap_exit)
501 +MODULE_LICENSE("GPL");
502 +MODULE_AUTHOR("Many. Stuffed into a module by cH (Claus-Justus Heine)");
503 +MODULE_DESCRIPTION("Swapping to partitions and files on local hard-disks");
504 --- linux-2.4.20/fs/buffer.c~130-nfsswap 2002-11-28 18:53:15.000000000 -0500
505 +++ linux-2.4.20/fs/buffer.c 2005-01-07 02:56:22.809168040 -0500
507 bh->b_private = private;
510 -static void end_buffer_io_async(struct buffer_head * bh, int uptodate)
511 +void end_buffer_io_async(struct buffer_head * bh, int uptodate)
513 static spinlock_t page_uptodate_lock = SPIN_LOCK_UNLOCKED;
515 @@ -2345,47 +2345,6 @@
520 - * Start I/O on a page.
521 - * This function expects the page to be locked and may return
522 - * before I/O is complete. You then have to check page->locked
523 - * and page->uptodate.
525 - * brw_page() is SMP-safe, although it's being called with the
526 - * kernel lock held - but the code is ready.
528 - * FIXME: we need a swapper_inode->get_block function to remove
529 - * some of the bmap kludges and interface ugliness here.
531 -int brw_page(int rw, struct page *page, kdev_t dev, int b[], int size)
533 - struct buffer_head *head, *bh;
535 - if (!PageLocked(page))
536 - panic("brw_page: page not locked for I/O");
538 - if (!page->buffers)
539 - create_empty_buffers(page, dev, size);
540 - head = bh = page->buffers;
542 - /* Stage 1: lock all the buffers */
545 - bh->b_blocknr = *(b++);
546 - set_bit(BH_Mapped, &bh->b_state);
547 - set_buffer_async_io(bh);
548 - bh = bh->b_this_page;
549 - } while (bh != head);
551 - /* Stage 2: start the IO */
553 - struct buffer_head *next = bh->b_this_page;
556 - } while (bh != head);
560 int block_symlink(struct inode *inode, const char *symname, int len)
562 struct address_space *mapping = inode->i_mapping;
563 --- linux-2.4.20/fs/nfs/Makefile~130-nfsswap 2001-11-09 17:28:15.000000000 -0500
564 +++ linux-2.4.20/fs/nfs/Makefile 2005-01-07 02:55:48.026455816 -0500
566 obj-$(CONFIG_ROOT_NFS) += nfsroot.o mount_clnt.o
567 obj-$(CONFIG_NFS_V3) += nfs3proc.o nfs3xdr.o
569 -obj-m := $(O_TARGET)
570 +obj-$(CONFIG_SWAP_VIA_NFS) += nfsswap.o
571 +ifeq ($(CONFIG_SWAP_VIA_NFS),m)
572 +export-objs := nfs_syms.o
576 +ifeq ($(CONFIG_NFS_FS),m)
577 +obj-m += $(O_TARGET)
580 include $(TOPDIR)/Rules.make
581 --- linux-2.4.20/fs/nfs/file.c~130-nfsswap 2002-02-25 14:38:09.000000000 -0500
582 +++ linux-2.4.20/fs/nfs/file.c 2005-01-07 02:55:48.026455816 -0500
584 setattr: nfs_notify_change,
587 -/* Hack for future NFS swap support */
589 -# define IS_SWAPFILE(inode) (0)
593 * Flush all dirty pages, and check for write errors.
596 inode->i_ino, (unsigned long) count, (unsigned long) *ppos);
599 - if (IS_SWAPFILE(inode))
601 result = nfs_revalidate_inode(NFS_SERVER(inode), inode);
605 result = generic_file_write(file, buf, count, ppos);
610 - printk(KERN_INFO "NFS: attempt to write to active swap file!\n");
615 --- /dev/null 2004-04-06 13:56:48.000000000 -0400
616 +++ linux-2.4.20/fs/nfs/nfs_syms.c 2005-01-07 02:55:48.026455816 -0500
618 +#include <linux/config.h>
619 +#define __NO_VERSION__
620 +#include <linux/module.h>
621 +#include <linux/types.h>
622 +#include <linux/sunrpc/clnt.h>
623 +#include <linux/nfs_fs.h>
625 +EXPORT_SYMBOL(__nfs_refresh_inode);
626 +EXPORT_SYMBOL(nfs_write_attributes);
628 --- /dev/null 2004-04-06 13:56:48.000000000 -0400
629 +++ linux-2.4.20/fs/nfs/nfsswap.c 2005-01-07 02:55:48.027455664 -0500
632 + * Swapping to files located on NFS mounted volumes
633 + * Copyright (c) 2000 Claus-Justus Heine
637 +#include <linux/config.h>
638 +#include <linux/module.h>
639 +#include <linux/init.h>
640 +#include <linux/types.h>
641 +#include <linux/slab.h>
642 +#include <linux/swap.h>
643 +#include <linux/pagemap.h>
644 +#include <linux/file.h>
645 +#include <linux/fs.h>
646 +#include <linux/socket.h>
647 +#include <linux/smp_lock.h>
648 +#include <net/netswapping.h>
649 +#include <net/sock.h>
651 +#include <linux/sunrpc/clnt.h>
652 +#include <linux/nfs_fs.h>
653 +#include <linux/nfs_fs_sb.h>
654 +#include <asm/uaccess.h>
656 +#define NFSDBG_FACILITY NFSDBG_SWAP
658 +#define NFS_SWAP_ID "nfs file"
660 +/* we cache some values here. In principle, we only need the file.
662 +struct nfs_swap_data {
664 + struct inode *inode;
665 + struct nfs_server *server;
666 + struct socket *socket;
669 +/* Nearly a clone of nfs_readpage_sync() in read.c, but "struct page" does not
670 + * contain information about the file offset when swapping. So.
672 +static int nfs_read_swap_page(struct page *page,
673 + struct nfs_server *server,
674 + struct inode *inode,
677 + unsigned int rsize = server->rsize;
678 + unsigned int count = PAGE_SIZE;
679 + unsigned int offset = 0; /* always at start of page */
681 + struct rpc_cred *cred;
682 + struct nfs_fattr fattr;
684 + cred = nfs_file_cred(file);
691 + result = NFS_PROTO(inode)->read(inode, cred,
694 + offset, rsize, page, &eof);
695 + nfs_refresh_inode(inode, &fattr);
699 + * Even if we had a partial success we can't mark the page
703 + if (result == -EISDIR)
709 + if (result < rsize) /* NFSv2ism */
714 + char *kaddr = kmap(page);
715 + memset(kaddr + offset, 0, count);
718 + flush_dcache_page(page);
725 +/* Like nfs_writepage_sync(), but when swapping page->index does not encode
726 + * the offset in the swap file alone.
729 +static int nfs_write_swap_page(struct page *page,
730 + struct nfs_server *server,
731 + struct inode *inode,
734 + struct rpc_cred *cred;
735 + unsigned int wsize = server->wsize;
736 + unsigned int count = PAGE_SIZE;
737 + unsigned int offset = 0;
739 + struct nfs_writeverf verf;
740 + struct nfs_fattr fattr;
742 + cred = nfs_file_cred(file);
749 + result = NFS_PROTO(inode)->write(inode, cred, &fattr,
750 + NFS_RW_SWAP|NFS_RW_SYNC,
751 + offset, wsize, page, &verf);
752 + nfs_write_attributes(inode, &fattr);
758 + if (result != wsize)
759 + printk("NFS: short write, wsize=%u, result=%d\n",
764 + * If we've extended the file, update the inode
765 + * now so we don't invalidate the cache.
767 + if (offset > inode->i_size)
768 + inode->i_size = offset;
778 +/* Unluckily (for us) form 2.4.19 -> 2.4.20 the nfs-proc's where
779 + * changed and expect now a proper file-mapping page, where index
780 + * encodes the offset alone.
782 + * What we do: we save the original value of page->index, initialize
783 + * page->index to what the NFS/sun-rpc subsystem expects and restore
786 +static int nfs_rw_swap_page(int rw, struct page *page,
787 + unsigned long offset, void *dptr)
790 + struct nfs_swap_data *data = dptr;
791 + unsigned long alloc_flag = current->flags & PF_MEMALLOC;
792 + unsigned long page_index;
794 + if (!PageLocked(page))
795 + panic("nfs_rw_swap_page: page not locked for I/O");
797 + /* prevent memory deadlocks */
798 + if (!(current->flags & PF_MEMALLOC)) {
799 + dprintk("nfs_rw_swap_page: Setting PF_MEMALLOC\n");
801 + current->flags |= PF_MEMALLOC;
803 + /* now tweak the page->index field ... */
804 + page_index = page->index;
805 + page->index = ((loff_t)offset*(loff_t)PAGE_SIZE) >> PAGE_CACHE_SHIFT;
808 + error = nfs_write_swap_page(page,
813 + error = nfs_read_swap_page(page,
820 + current->flags &= ~PF_MEMALLOC;
823 + /* now restore the page->index field ... */
824 + page->index = page_index;
827 + /* Must mark the page invalid after I/O error */
828 + SetPageError(page);
829 + ClearPageUptodate(page);
831 + ClearPageError(page);
832 + SetPageUptodate(page);
835 + if (!error) { /* in case of an error rw_swap_page() likes to unlock
841 + return error < 0 ? 0 : 1;
844 +static int is_nfsfile_swapping(unsigned int flags,
845 + struct file * swapf,
848 + struct file * filp = (struct file *) data;
850 + /* Only check filp's that don't match the one already opened
851 + * for us by sys_swapon(). Otherwise, we will always flag a
855 + if (swapf != filp) {
856 + if (filp->f_dentry->d_inode == swapf->f_dentry->d_inode)
862 +static int nfs_swap_open(struct file *swapf, void **dptr)
866 + struct nfs_swap_data *data;
869 + struct inode *inode = swapf->f_dentry->d_inode;
873 + if (!S_ISREG(inode->i_mode)) {
874 + dprintk("nfs_swap_open: can't handle this swap file: %s\n",
875 + swapf->f_dentry->d_name.name);
876 + error = 0; /* not for us */
879 + /* determine whether this file really is located on an NFS mounted
882 + if (!inode->i_sb || inode->i_sb->s_magic != NFS_SUPER_MAGIC) {
883 + dprintk("nfs_swap_open: %s is not an NFS file.\n",
884 + swapf->f_dentry->d_name.name);
885 + error = 0; /* not for us */
889 + if (swap_run_test(is_nfsfile_swapping, swapf)) {
890 + dprintk("nfs_swap_open: already swapping to %s\n",
891 + swapf->f_dentry->d_name.name);
895 + swapfilesize = inode->i_size >> PAGE_SHIFT;
896 + if ((data = kmalloc(sizeof(*data), GFP_KERNEL)) == NULL) {
900 + data->file = swapf;
901 + data->inode = inode;
902 + data->server = NFS_SERVER(inode);
903 + data->socket = data->server->client->cl_xprt->sock;
905 + /* set socket option SO_SWAPPING */
908 + error = sock_setsockopt(data->socket, SOL_SOCKET, SO_SWAPPING,
909 + (char *)&on, sizeof(on));
912 + dprintk("nfs_swap_open: error setting SO_SWAPPING\n");
917 + return swapfilesize;
926 +static int nfs_swap_release(struct file *swapf, void *dptr)
928 + struct nfs_swap_data *data = (struct nfs_swap_data *)dptr;
934 + if (swapf != data->file ||
935 + swapf->f_dentry->d_inode != data->inode ||
936 + !swapf->f_dentry->d_inode->i_sb ||
937 + swapf->f_dentry->d_inode->i_sb->s_magic != NFS_SUPER_MAGIC ||
938 + NFS_SERVER(swapf->f_dentry->d_inode) != data->server ||
939 + data->socket != data->server->client->cl_xprt->sock) {
940 + panic("nfs_swap_release: nfs swap data messed up");
944 + /* remove socket option SO_SWAPPING */
947 + error = sock_setsockopt(data->socket, SOL_SOCKET, SO_SWAPPING,
948 + (char *)&off, sizeof(off));
951 + dprintk("nfs_swap_open: error clearing SO_SWAPPING\n");
958 +static struct swap_ops nfs_swap_ops = {
959 + open: nfs_swap_open,
960 + release: nfs_swap_release,
961 + rw_page: nfs_rw_swap_page
964 +int __init nfs_swap_init(void)
966 + (void)register_swap_method(NFS_SWAP_ID, &nfs_swap_ops);
970 +void __exit nfs_swap_exit(void)
972 + unregister_swap_method(NFS_SWAP_ID);
975 +module_init(nfs_swap_init)
976 +module_exit(nfs_swap_exit)
978 +MODULE_LICENSE("GPL");
979 +MODULE_AUTHOR("(c) 1996-2002 cH (Claus-Justus Heine)");
980 +MODULE_DESCRIPTION("Swapping to files located on volumes mounted via NFS");
981 --- linux-2.4.20/fs/nfs/read.c~130-nfsswap 2002-11-28 18:53:15.000000000 -0500
982 +++ linux-2.4.20/fs/nfs/read.c 2005-01-07 02:55:48.027455664 -0500
985 static void nfs_readpage_result(struct rpc_task *task);
987 -/* Hack for future NFS swap support */
989 -# define IS_SWAPFILE(inode) (0)
992 static kmem_cache_t *nfs_rdata_cachep;
994 static __inline__ struct nfs_read_data *nfs_readdata_alloc(void)
996 int rsize = NFS_SERVER(inode)->rsize;
998 int count = PAGE_CACHE_SIZE;
999 - int flags = IS_SWAPFILE(inode)? NFS_RPC_SWAPFLAGS : 0;
1002 dprintk("NFS: nfs_readpage_sync(%p)\n", page);
1004 offset, rsize, page);
1007 - result = NFS_PROTO(inode)->read(inode, cred, &fattr, flags,
1008 + result = NFS_PROTO(inode)->read(inode, cred, &fattr, 0,
1009 offset, rsize, page, &eof);
1010 nfs_refresh_inode(inode, &fattr);
1015 /* N.B. Do we need to test? Never called for swapfile inode */
1016 - flags = RPC_TASK_ASYNC | (IS_SWAPFILE(inode)? NFS_RPC_SWAPFLAGS : 0);
1017 + flags = RPC_TASK_ASYNC;
1019 nfs_read_rpcsetup(head, data);
1024 error = nfs_readpage_sync(file, inode, page);
1025 - if (error < 0 && IS_SWAPFILE(inode))
1026 - printk("Aiee.. nfs swap-in of page failed!\n");
1030 --- linux-2.4.20/fs/nfs/write.c~130-nfsswap 2002-11-28 18:53:15.000000000 -0500
1031 +++ linux-2.4.20/fs/nfs/write.c 2005-01-07 02:57:10.476921440 -0500
1033 #include <linux/config.h>
1034 #include <linux/types.h>
1035 #include <linux/slab.h>
1036 -#include <linux/swap.h>
1037 #include <linux/pagemap.h>
1038 #include <linux/file.h>
1041 static void nfs_commit_done(struct rpc_task *);
1044 -/* Hack for future NFS swap support */
1045 -#ifndef IS_SWAPFILE
1046 -# define IS_SWAPFILE(inode) (0)
1049 static kmem_cache_t *nfs_wdata_cachep;
1051 static __inline__ struct nfs_write_data *nfs_writedata_alloc(void)
1053 * For the moment, we just call nfs_refresh_inode().
1055 static __inline__ int
1056 -nfs_write_attributes(struct inode *inode, struct nfs_fattr *fattr)
1057 +__nfs_write_attributes(struct inode *inode, struct nfs_fattr *fattr)
1059 if ((fattr->valid & NFS_ATTR_FATTR) && !(fattr->valid & NFS_ATTR_WCC)) {
1060 fattr->pre_size = NFS_CACHE_ISIZE(inode);
1061 @@ -139,6 +133,11 @@
1062 return nfs_refresh_inode(inode, fattr);
1065 +int nfs_write_attributes(struct inode *inode, struct nfs_fattr *fattr)
1067 + return __nfs_write_attributes(inode, fattr);
1071 * Write a page synchronously.
1072 * Offset is the data offset within the page.
1074 struct rpc_cred *cred = NULL;
1076 unsigned int wsize = NFS_SERVER(inode)->wsize;
1077 - int result, refresh = 0, written = 0, flags;
1079 + int result, refresh = 0, written = 0;
1080 struct nfs_fattr fattr;
1081 struct nfs_writeverf verf;
1083 @@ -167,15 +165,14 @@
1085 base = page_offset(page) + offset;
1087 - flags = ((IS_SWAPFILE(inode)) ? NFS_RW_SWAP : 0) | NFS_RW_SYNC;
1090 - if (count < wsize && !IS_SWAPFILE(inode))
1091 + if (count < wsize)
1094 - result = NFS_PROTO(inode)->write(inode, cred, &fattr, flags,
1095 + result = NFS_PROTO(inode)->write(inode, cred, &fattr,
1097 offset, wsize, page, &verf);
1098 - nfs_write_attributes(inode, &fattr);
1099 + __nfs_write_attributes(inode, &fattr);
1102 /* Must mark the page invalid after I/O error */
1104 printk("NFS: short write, wsize=%u, result=%d\n",
1111 @@ -1057,7 +1053,7 @@
1112 * writebacks since the page->count is kept > 1 for as long
1113 * as the page has a write request pending.
1115 - nfs_write_attributes(inode, resp->fattr);
1116 + __nfs_write_attributes(inode, resp->fattr);
1117 while (!list_empty(&data->pages)) {
1118 req = nfs_list_entry(data->pages.next);
1119 nfs_list_remove_request(req);
1120 @@ -1211,7 +1207,7 @@
1121 if (nfs_async_handle_jukebox(task))
1124 - nfs_write_attributes(inode, resp->fattr);
1125 + __nfs_write_attributes(inode, resp->fattr);
1126 while (!list_empty(&data->pages)) {
1127 req = nfs_list_entry(data->pages.next);
1128 nfs_list_remove_request(req);
1129 --- linux-2.4.20/include/linux/fs.h~130-nfsswap 2005-01-07 02:54:46.357830000 -0500
1130 +++ linux-2.4.20/include/linux/fs.h 2005-01-07 02:55:48.030455208 -0500
1131 @@ -1507,6 +1507,10 @@
1132 extern int inode_change_ok(struct inode *, struct iattr *);
1133 extern int inode_setattr(struct inode *, struct iattr *);
1135 +/* for swapping to block devices */
1136 +void create_empty_buffers(struct page *page, kdev_t dev, unsigned long blocksize);
1137 +void end_buffer_io_async(struct buffer_head * bh, int uptodate);
1140 * Common dentry functions for inclusion in the VFS
1141 * or in other stackable file systems. Some of these
1142 --- linux-2.4.20/include/linux/nfs_fs.h~130-nfsswap 2002-11-28 18:53:15.000000000 -0500
1143 +++ linux-2.4.20/include/linux/nfs_fs.h 2005-01-07 02:55:48.030455208 -0500
1146 #define NFS_MAX_DIRCACHE 16
1148 -#define NFS_MAX_FILE_IO_BUFFER_SIZE 32768
1149 -#define NFS_DEF_FILE_IO_BUFFER_SIZE 4096
1150 +#define NFS_MAX_FILE_IO_BUFFER_SIZE (8*PAGE_SIZE)
1151 +#define NFS_DEF_FILE_IO_BUFFER_SIZE PAGE_SIZE
1154 * The upper limit on timeouts for the exponential backoff algorithm.
1156 extern int nfs_writepage(struct page *);
1157 extern int nfs_flush_incompatible(struct file *file, struct page *page);
1158 extern int nfs_updatepage(struct file *, struct page *, unsigned int, unsigned int);
1159 +extern int nfs_write_attributes(struct inode *inode, struct nfs_fattr *fattr);
1162 * Try to write back everything synchronously (but check the
1165 #define NFSDBG_XDR 0x0020
1166 #define NFSDBG_FILE 0x0040
1167 #define NFSDBG_ROOT 0x0080
1168 +#define NFSDBG_SWAP 0x0100
1169 #define NFSDBG_ALL 0xFFFF
1172 --- linux-2.4.20/include/linux/slab.h~130-nfsswap 2002-11-28 18:53:15.000000000 -0500
1173 +++ linux-2.4.20/include/linux/slab.h 2005-01-07 02:55:48.030455208 -0500
1175 #define SLAB_HWCACHE_ALIGN 0x00002000UL /* align objs on a h/w cache lines */
1176 #define SLAB_CACHE_DMA 0x00004000UL /* use GFP_DMA memory */
1177 #define SLAB_MUST_HWCACHE_ALIGN 0x00008000UL /* force alignment */
1178 +#define SLAB_LOW_GFP_ORDER 0x00010000UL /* use as low a gfp order as possible */
1180 /* flags passed to a constructor func */
1181 #define SLAB_CTOR_CONSTRUCTOR 0x001UL /* if not set, then deconstructor */
1182 --- linux-2.4.20/include/linux/swap.h~130-nfsswap 2002-11-28 18:53:15.000000000 -0500
1183 +++ linux-2.4.20/include/linux/swap.h 2005-01-07 02:55:48.031455056 -0500
1185 #define SWAP_MAP_MAX 0x7fff
1186 #define SWAP_MAP_BAD 0x8000
1189 + int (*open)(struct file *swapf, void **data);
1190 + int (*release)(struct file *swapf, void *data);
1191 + int (*rw_page)(int rw,
1192 + struct page *page, unsigned long offset, void *data);
1195 +struct swap_method {
1196 + struct swap_method *next;
1198 + struct swap_ops *ops;
1203 * The in-memory structure used to track swap areas.
1205 struct swap_info_struct {
1207 - kdev_t swap_device;
1208 + struct file *swap_file;
1209 + struct swap_method *method;
1211 spinlock_t sdev_lock;
1212 - struct dentry * swap_file;
1213 - struct vfsmount *swap_vfsmnt;
1214 unsigned short * swap_map;
1215 unsigned int lowest_bit;
1216 unsigned int highest_bit;
1217 @@ -141,11 +155,15 @@
1218 extern int total_swap_pages;
1219 extern unsigned int nr_swapfiles;
1220 extern struct swap_info_struct swap_info[];
1221 -extern int is_swap_partition(kdev_t);
1222 +extern int register_swap_method(char *name, struct swap_ops *ops);
1223 +extern int unregister_swap_method(char *name);
1224 +extern int swap_run_test(int (*test_fct)(unsigned int flags,
1225 + struct file *swap_file,
1226 + void *testdata), void *testdata);
1227 extern void si_swapinfo(struct sysinfo *);
1228 extern swp_entry_t get_swap_page(void);
1229 -extern void get_swaphandle_info(swp_entry_t, unsigned long *, kdev_t *,
1231 +struct swap_method *get_swaphandle_info(swp_entry_t entry,
1232 + unsigned long *offset, void **data);
1233 extern int swap_duplicate(swp_entry_t);
1234 extern int swap_count(struct page *);
1235 extern int valid_swaphandles(swp_entry_t, unsigned long *);
1236 --- /dev/null 2004-04-06 13:56:48.000000000 -0400
1237 +++ linux-2.4.20/include/net/netswapping.h 2005-01-07 02:55:48.031455056 -0500
1239 +#ifndef _LINUX_NETSWAPPING_H
1240 +#define _LINUX_NETSWAPPING_H
1242 +#include <linux/swap.h>
1243 +#include <linux/init.h>
1245 +/* It is a mess. Socket options are defined in asm-ARCH/socket.h */
1247 +#define SO_SWAPPING 0x00100000 /* hopefully not used by anybody else */
1251 +#define CTL_NETSWAP 0x00100000
1254 + NET_SWAP_DROPPED = 1,
1255 + NET_SWAP_DROP_THRESHOLD = 2,
1256 + NET_SWAP_SOCK_COUNT = 3
1259 +extern unsigned int netswap_free_pages_min;
1260 +extern int netswap_sock_count;
1261 +extern unsigned int netswap_dropped;
1263 +/* this is "#defined" and not inline because sock.h includes us, but we need
1264 + * the "struct sock" definition.
1266 +#define netswap_low_memory(sk, skb) \
1270 + if (netswap_sock_count > 0 && /* anybody swapping via network? */ \
1271 + !(sk)->swapping && /* but we are not needed for swapping */ \
1272 + nr_free_pages() < netswap_free_pages_min) { /* so drop us */ \
1273 + printk("netswap_low_memory: " \
1274 + "dropping skb 0x%p@0x%p\n", skb, sk); \
1275 + netswap_dropped ++; \
1281 +extern int __init netswap_init(void);
1286 --- linux-2.4.20/include/net/sock.h~130-nfsswap 2002-08-02 20:39:46.000000000 -0400
1287 +++ linux-2.4.20/include/net/sock.h 2005-01-07 02:55:48.032454904 -0500
1288 @@ -103,6 +103,10 @@
1289 #include <linux/filter.h>
1292 +#ifdef CONFIG_NETSWAP
1293 +#include <net/netswapping.h>
1296 #include <asm/atomic.h>
1297 #include <net/dst.h>
1299 @@ -539,6 +543,12 @@
1303 +#ifdef CONFIG_NETSWAP
1304 + /* Increased by SO_SWAPPING with arg != 0, decreased by
1305 + * SO_SWAPPING with arg 0
1309 unsigned char debug;
1310 unsigned char rcvtstamp;
1311 unsigned char use_write_queue;
1312 @@ -1168,6 +1178,11 @@
1313 return err; /* Toss packet */
1315 #endif /* CONFIG_FILTER */
1316 +#ifdef CONFIG_NETSWAP
1317 + /* an inline function defined in net/netswapping.h */
1318 + if (netswap_low_memory(sk, skb))
1320 +#endif /* CONFIG_NETSWAP */
1323 skb_set_owner_r(skb, sk);
1324 --- linux-2.4.20/kernel/ksyms.c~130-nfsswap 2005-01-07 02:54:46.362830000 -0500
1325 +++ linux-2.4.20/kernel/ksyms.c 2005-01-07 02:55:48.032454904 -0500
1327 #include <linux/mm.h>
1328 #include <linux/capability.h>
1329 #include <linux/highuid.h>
1330 +#include <linux/swapctl.h>
1331 #include <linux/brlock.h>
1332 #include <linux/fs.h>
1333 #include <linux/tty.h>
1334 @@ -127,6 +128,11 @@
1335 EXPORT_SYMBOL(kmap_prot);
1336 EXPORT_SYMBOL(kmap_pte);
1338 +EXPORT_SYMBOL(nr_free_pages);
1339 +/* EXPORT_SYMBOL(freepages); */
1340 +EXPORT_SYMBOL(register_swap_method);
1341 +EXPORT_SYMBOL(unregister_swap_method);
1342 +EXPORT_SYMBOL(swap_run_test);
1344 /* filesystem internal functions */
1345 EXPORT_SYMBOL(def_blk_fops);
1347 EXPORT_SYMBOL(make_bad_inode);
1348 EXPORT_SYMBOL(is_bad_inode);
1349 EXPORT_SYMBOL(event);
1350 -EXPORT_SYMBOL(brw_page);
1351 +EXPORT_SYMBOL(end_buffer_io_async);
1352 EXPORT_SYMBOL(__inode_dir_notify);
1355 --- linux-2.4.20/mm/page_io.c~130-nfsswap 2002-11-28 18:53:15.000000000 -0500
1356 +++ linux-2.4.20/mm/page_io.c 2005-01-07 02:55:48.033454752 -0500
1358 static int rw_swap_page_base(int rw, swp_entry_t entry, struct page *page)
1360 unsigned long offset;
1361 - int zones[PAGE_SIZE/512];
1365 - struct inode *swapf = 0;
1366 + struct swap_method *method;
1370 ClearPageUptodate(page);
1375 - get_swaphandle_info(entry, &offset, &dev, &swapf);
1377 - zones[0] = offset;
1379 - block_size = PAGE_SIZE;
1380 - } else if (swapf) {
1382 - unsigned int block = offset
1383 - << (PAGE_SHIFT - swapf->i_sb->s_blocksize_bits);
1385 - block_size = swapf->i_sb->s_blocksize;
1386 - for (i=0, j=0; j< PAGE_SIZE ; i++, j += block_size)
1387 - if (!(zones[i] = bmap(swapf,block++))) {
1388 - printk("rw_swap_page: bad swap file\n");
1392 - dev = swapf->i_dev;
1394 + method = get_swaphandle_info(entry, &offset, &data);
1395 + if (!method || !method->ops->rw_page(rw, page, offset, data)) {
1399 - /* block_size == PAGE_SIZE/zones_used */
1400 - brw_page(rw, page, dev, zones, block_size);
1404 --- linux-2.4.20/mm/slab.c~130-nfsswap 2002-11-28 18:53:15.000000000 -0500
1405 +++ linux-2.4.20/mm/slab.c 2005-01-07 02:55:48.034454600 -0500
1406 @@ -111,10 +111,12 @@
1407 # define CREATE_MASK (SLAB_DEBUG_INITIAL | SLAB_RED_ZONE | \
1408 SLAB_POISON | SLAB_HWCACHE_ALIGN | \
1409 SLAB_NO_REAP | SLAB_CACHE_DMA | \
1410 - SLAB_MUST_HWCACHE_ALIGN)
1411 + SLAB_MUST_HWCACHE_ALIGN | \
1412 + SLAB_LOW_GFP_ORDER)
1414 # define CREATE_MASK (SLAB_HWCACHE_ALIGN | SLAB_NO_REAP | \
1415 - SLAB_CACHE_DMA | SLAB_MUST_HWCACHE_ALIGN)
1416 + SLAB_CACHE_DMA | SLAB_MUST_HWCACHE_ALIGN | \
1417 + SLAB_LOW_GFP_ORDER)
1421 @@ -247,8 +249,13 @@
1424 /* internal c_flags */
1425 -#define CFLGS_OFF_SLAB 0x010000UL /* slab management in own cache */
1426 -#define CFLGS_OPTIMIZE 0x020000UL /* optimized slab lookup */
1427 +#define CFLGS_OFF_SLAB 0x020000UL /* slab management in own cache */
1428 +#define CFLGS_OPTIMIZE 0x040000UL /* optimized slab lookup */
1429 +#define CFLGS_MASK (CFLGS_OFF_SLAB | CFLGS_OPTIMIZE)
1431 +#if (CFLGS_MASK & CREATE_MASK)
1432 +# error BUG: internal and external SLAB flags overlap
1435 /* c_dflags (dynamic flags). Need to hold the spinlock to access this member */
1436 #define DFLGS_GROWN 0x000001UL /* don't reap a recently grown */
1437 @@ -452,7 +459,12 @@
1438 snprintf(name, sizeof(name), "size-%Zd",sizes->cs_size);
1439 if (!(sizes->cs_cachep =
1440 kmem_cache_create(name, sizes->cs_size,
1441 - 0, SLAB_HWCACHE_ALIGN, NULL, NULL))) {
1444 + SLAB_LOW_GFP_ORDER| /* sorry */
1446 + SLAB_HWCACHE_ALIGN,
1455 + if (cachep->gfporder == 0 && (flags & SLAB_LOW_GFP_ORDER))
1457 if (flags & CFLGS_OFF_SLAB && cachep->num > offslab_limit) {
1458 /* Oops, this num of objs will cause problems. */
1460 --- linux-2.4.20/mm/swapfile.c~130-nfsswap 2002-08-02 20:39:46.000000000 -0400
1461 +++ linux-2.4.20/mm/swapfile.c 2005-01-07 02:55:48.037454144 -0500
1463 #include <linux/swap.h>
1464 #include <linux/swapctl.h>
1465 #include <linux/blkdev.h> /* for blk_size */
1466 +#include <linux/file.h>
1467 #include <linux/vmalloc.h>
1468 #include <linux/pagemap.h>
1469 #include <linux/shm.h>
1471 #include <asm/pgtable.h>
1474 +#include <linux/kmod.h>
1477 spinlock_t swaplock = SPIN_LOCK_UNLOCKED;
1478 unsigned int nr_swapfiles;
1479 int total_swap_pages;
1482 struct swap_info_struct swap_info[MAX_SWAPFILES];
1484 +static struct swap_method *swap_methods = NULL;
1486 #define SWAPFILE_CLUSTER 256
1488 +int register_swap_method(char *name, struct swap_ops *ops)
1490 + struct swap_method *pos;
1491 + struct swap_method *new;
1496 + for (pos = swap_methods; pos; pos = pos->next) {
1497 + if (strcmp(pos->name, name) == 0) {
1498 + printk(KERN_ERR "register_swap_method: "
1499 + "method %s already registered\n", name);
1505 + if (!(new = kmalloc(sizeof(*new), GFP_KERNEL))) {
1506 + printk(KERN_ERR "register_swap_method: "
1507 + "no memory for new method \"%s\"\n", name);
1514 + new->use_count = 0;
1516 + /* ok, insert at top of list */
1517 + printk("register_swap_method: method %s\n", name);
1518 + new->next = swap_methods;
1519 + swap_methods = new;
1525 +int unregister_swap_method(char *name)
1527 + struct swap_method **method, *next;
1532 + for (method = &swap_methods; *method; method = &(*method)->next) {
1533 + if (strcmp((*method)->name, name) == 0) {
1534 + if ((*method)->use_count > 0) {
1535 + printk(KERN_ERR "unregister_swap_method: "
1536 + "method \"%s\" is in use\n", name);
1541 + next = (*method)->next;
1544 + printk("unregister_swap_method: method %s\n", name);
1549 + printk("unregister_swap_method: no such method %s\n", name);
1556 static inline int scan_swap_map(struct swap_info_struct *si)
1558 unsigned long offset;
1559 @@ -711,13 +786,14 @@
1560 struct nameidata nd;
1563 + struct file *swap_file;
1565 if (!capable(CAP_SYS_ADMIN))
1568 err = user_path_walk(specialfile, &nd);
1575 @@ -725,15 +801,20 @@
1576 for (type = swap_list.head; type >= 0; type = swap_info[type].next) {
1577 p = swap_info + type;
1578 if ((p->flags & SWP_WRITEOK) == SWP_WRITEOK) {
1579 - if (p->swap_file == nd.dentry)
1580 + if (p->swap_file &&
1581 + p->swap_file->f_dentry == nd.dentry)
1587 + /* p->swap_file contains all needed info, no need to keep nd, so
1590 + path_release(&nd);
1598 @@ -767,32 +848,30 @@
1599 total_swap_pages += p->pages;
1600 p->flags = SWP_WRITEOK;
1605 - if (p->swap_device)
1606 - blkdev_put(p->swap_file->d_inode->i_bdev, BDEV_SWAP);
1607 - path_release(&nd);
1609 + if (p->method->ops->release)
1610 + p->method->ops->release(p->swap_file, p->data);
1612 swap_device_lock(p);
1613 - nd.mnt = p->swap_vfsmnt;
1614 - nd.dentry = p->swap_file;
1615 - p->swap_vfsmnt = NULL;
1616 + p->method->use_count --;
1619 + swap_file = p->swap_file;
1620 p->swap_file = NULL;
1621 - p->swap_device = 0;
1623 swap_map = p->swap_map;
1626 swap_device_unlock(p);
1628 + filp_close(swap_file, NULL);
1634 - path_release(&nd);
1640 @@ -805,18 +884,17 @@
1644 - len += sprintf(buf, "Filename\t\t\tType\t\tSize\tUsed\tPriority\n");
1645 + len += sprintf(buf, "%-32s%-16s%-8s%-8sPriority\n",
1646 + "Filename", "Type", "Size", "Used");
1647 for (i = 0 ; i < nr_swapfiles ; i++, ptr++) {
1648 if ((ptr->flags & SWP_USED) && ptr->swap_map) {
1649 - char * path = d_path(ptr->swap_file, ptr->swap_vfsmnt,
1650 + char * path = d_path(ptr->swap_file->f_dentry,
1651 + ptr->swap_file->f_vfsmnt,
1654 len += sprintf(buf + len, "%-31s ", path);
1656 - if (!ptr->swap_device)
1657 - len += sprintf(buf + len, "file\t\t");
1659 - len += sprintf(buf + len, "partition\t");
1660 + len += sprintf(buf + len, "%-15s ", ptr->method->name);
1663 for (j = 0; j < ptr->max; ++j)
1668 - len += sprintf(buf + len, "%d\t%d\t%d\n", ptr->pages << (PAGE_SHIFT - 10),
1669 + len += sprintf(buf + len, "%-8d%-8d%d\n", ptr->pages << (PAGE_SHIFT - 10),
1670 usedswap << (PAGE_SHIFT - 10), ptr->prio);
1673 @@ -835,18 +913,55 @@
1677 -int is_swap_partition(kdev_t dev) {
1678 +/* apply a test function to all active swap objects. E.g. for checking
1679 + * whether a partition is used for swapping
1681 +int swap_run_test(int (*test_fct)(unsigned int flags,
1682 + struct file * swap_file,
1683 + void *testdata), void *testdata)
1685 struct swap_info_struct *ptr = swap_info;
1688 for (i = 0 ; i < nr_swapfiles ; i++, ptr++) {
1689 - if (ptr->flags & SWP_USED)
1690 - if (ptr->swap_device == dev)
1691 + if (ptr->swap_file &&
1692 + test_fct(ptr->flags, ptr->swap_file, testdata))
1698 +/* Walk through the list of known swap method until somebody wants to
1699 + * handle this file. Pick the first one which claims to be able to
1700 + * swap to this kind of file.
1702 + * return value: < 0: error, 0: not found, > 0: swapfilesize
1704 +int find_swap_method(struct file *swap_file,
1705 + struct swap_info_struct *p)
1707 + int swapfilesize = 0;
1708 + struct swap_method *method;
1711 + for (method = swap_methods; method; method = method->next) {
1712 + swapfilesize = method->ops->open(swap_file, &p->data);
1713 + if (swapfilesize == 0) {
1716 + if (swapfilesize > 0) {
1717 + p->method = method;
1718 + p->method->use_count ++;
1719 + p->swap_file = swap_file;
1722 + if (swapfilesize < 0) {
1726 + return swapfilesize;
1730 * Written 01/25/92 by Simmule Turner, heavily changed by Linus.
1733 asmlinkage long sys_swapon(const char * specialfile, int swap_flags)
1735 struct swap_info_struct * p;
1736 - struct nameidata nd;
1737 - struct inode * swap_inode;
1742 int nr_good_pages = 0;
1743 unsigned long maxpages = 1;
1745 - struct block_device *bdev = NULL;
1746 unsigned short *swap_map;
1747 + char * tmp_specialfile;
1748 + struct file *swap_file;
1750 if (!capable(CAP_SYS_ADMIN))
1752 @@ -886,8 +1000,7 @@
1753 nr_swapfiles = type+1;
1754 p->flags = SWP_USED;
1755 p->swap_file = NULL;
1756 - p->swap_vfsmnt = NULL;
1757 - p->swap_device = 0;
1762 @@ -901,53 +1014,56 @@
1763 p->prio = --least_priority;
1766 - error = user_path_walk(specialfile, &nd);
1769 + /* Open the swap using filp_open. Bail out on any errors. */
1770 + tmp_specialfile = getname(specialfile);
1771 + if (IS_ERR(tmp_specialfile)) {
1772 + error = PTR_ERR(tmp_specialfile);
1775 + p->swap_file = filp_open(tmp_specialfile, O_RDWR, 0600);
1776 + putname(tmp_specialfile);
1777 + if (IS_ERR(p->swap_file)) {
1778 + error = PTR_ERR(p->swap_file);
1782 - p->swap_file = nd.dentry;
1783 - p->swap_vfsmnt = nd.mnt;
1784 - swap_inode = nd.dentry->d_inode;
1787 - if (S_ISBLK(swap_inode->i_mode)) {
1788 - kdev_t dev = swap_inode->i_rdev;
1789 - struct block_device_operations *bdops;
1790 - devfs_handle_t de;
1792 - p->swap_device = dev;
1793 - set_blocksize(dev, PAGE_SIZE);
1795 - bd_acquire(swap_inode);
1796 - bdev = swap_inode->i_bdev;
1797 - de = devfs_get_handle_from_inode(swap_inode);
1798 - bdops = devfs_get_ops(de); /* Increments module use count */
1799 - if (bdops) bdev->bd_op = bdops;
1800 + swapfilesize = find_swap_method(p->swap_file, p);
1801 + if (swapfilesize < 0) {
1802 + error = swapfilesize;
1806 + if (swapfilesize == 0) {
1807 + (void)request_module("swapfile-mod");
1809 - error = blkdev_get(bdev, FMODE_READ|FMODE_WRITE, 0, BDEV_SWAP);
1810 - devfs_put_ops(de);/*Decrement module use count now we're safe*/
1813 - set_blocksize(dev, PAGE_SIZE);
1815 - if (!dev || (blk_size[MAJOR(dev)] &&
1816 - !blk_size[MAJOR(dev)][MINOR(dev)]))
1819 - if (blk_size[MAJOR(dev)])
1820 - swapfilesize = blk_size[MAJOR(dev)][MINOR(dev)]
1821 - >> (PAGE_SHIFT - 10);
1822 - } else if (S_ISREG(swap_inode->i_mode))
1823 - swapfilesize = swap_inode->i_size >> PAGE_SHIFT;
1826 + swapfilesize = find_swap_method(p->swap_file, p);
1827 + if (swapfilesize < 0) {
1828 + error = swapfilesize;
1833 + if (swapfilesize == 0) {
1834 + printk("Don't know how to swap to this kind of file\n");
1835 + goto bad_swap_1; /* free swap map */
1838 + /* After this point, the swap-file has been opened by the swap
1839 + * method. We must make sure to use the bad_swap label for any
1844 for (i = 0 ; i < nr_swapfiles ; i++) {
1845 struct swap_info_struct *q = &swap_info[i];
1846 if (i == type || !q->swap_file)
1848 - if (swap_inode->i_mapping == q->swap_file->d_inode->i_mapping)
1849 + if (p->swap_file->f_dentry->d_inode->i_mapping
1851 + q->swap_file->f_dentry->d_inode->i_mapping)
1855 @@ -1083,17 +1199,27 @@
1862 - blkdev_put(bdev, BDEV_SWAP);
1863 + if (p->method->ops->release)
1864 + p->method->ops->release(p->swap_file, p->data);
1866 + p->method->use_count --;
1869 + swap_list_unlock();
1873 + swap_file = p->swap_file;
1874 + p->swap_file = NULL;
1875 + swap_list_unlock();
1876 + filp_close(swap_file, NULL);
1881 swap_map = p->swap_map;
1882 - nd.mnt = p->swap_vfsmnt;
1883 - nd.dentry = p->swap_file;
1884 - p->swap_device = 0;
1885 - p->swap_file = NULL;
1886 - p->swap_vfsmnt = NULL;
1889 if (!(swap_flags & SWAP_FLAG_PREFER))
1890 @@ -1101,7 +1227,7 @@
1894 - path_release(&nd);
1898 free_page((long) swap_header);
1899 @@ -1217,8 +1343,8 @@
1901 * Prior swap_duplicate protects against swap device deletion.
1903 -void get_swaphandle_info(swp_entry_t entry, unsigned long *offset,
1904 - kdev_t *dev, struct inode **swapf)
1905 +struct swap_method *get_swaphandle_info(swp_entry_t entry,
1906 + unsigned long *offset, void **data)
1909 struct swap_info_struct *p;
1910 @@ -1226,32 +1352,26 @@
1911 type = SWP_TYPE(entry);
1912 if (type >= nr_swapfiles) {
1913 printk(KERN_ERR "rw_swap_page: %s%08lx\n", Bad_file, entry.val);
1918 p = &swap_info[type];
1919 *offset = SWP_OFFSET(entry);
1920 if (*offset >= p->max && *offset != 0) {
1921 printk(KERN_ERR "rw_swap_page: %s%08lx\n", Bad_offset, entry.val);
1925 if (p->swap_map && !p->swap_map[*offset]) {
1926 printk(KERN_ERR "rw_swap_page: %s%08lx\n", Unused_offset, entry.val);
1930 if (!(p->flags & SWP_USED)) {
1931 printk(KERN_ERR "rw_swap_page: %s%08lx\n", Unused_file, entry.val);
1936 - if (p->swap_device) {
1937 - *dev = p->swap_device;
1938 - } else if (p->swap_file) {
1939 - *swapf = p->swap_file->d_inode;
1941 - printk(KERN_ERR "rw_swap_page: no swap file or device\n");
1949 --- linux-2.4.20/net/Config.in~130-nfsswap 2002-08-02 20:39:46.000000000 -0400
1950 +++ linux-2.4.20/net/Config.in 2005-01-07 02:55:48.037454144 -0500
1953 bool 'Socket Filtering' CONFIG_FILTER
1954 tristate 'Unix domain sockets' CONFIG_UNIX
1955 +if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
1956 + bool 'Swapping via network sockets (EXPERIMENTAL)' CONFIG_NETSWAP
1958 bool 'TCP/IP networking' CONFIG_INET
1959 if [ "$CONFIG_INET" = "y" ]; then
1960 source net/ipv4/Config.in
1961 --- linux-2.4.20/net/Makefile~130-nfsswap 2002-08-02 20:39:46.000000000 -0400
1962 +++ linux-2.4.20/net/Makefile 2005-01-07 02:55:48.037454144 -0500
1964 ifeq ($(CONFIG_NET),y)
1965 obj-$(CONFIG_MODULES) += netsyms.o
1966 obj-$(CONFIG_SYSCTL) += sysctl_net.o
1967 +obj-$(CONFIG_NETSWAP) += netswapping.o
1970 include $(TOPDIR)/Rules.make
1971 --- linux-2.4.20/net/core/sock.c~130-nfsswap 2002-08-02 20:39:46.000000000 -0400
1972 +++ linux-2.4.20/net/core/sock.c 2005-01-07 02:55:48.038453992 -0500
1973 @@ -403,6 +403,21 @@
1977 +#ifdef CONFIG_NETSWAP
1980 + if (!sk->swapping) {
1981 + netswap_sock_count ++;
1984 + } else if (sk->swapping > 0) {
1986 + if (!sk->swapping) {
1987 + netswap_sock_count --;
1992 /* We implement the SO_SNDLOWAT etc to
1993 not be settable (1003.1g 5.3) */
1995 @@ -553,6 +568,12 @@
1999 +#ifdef CONFIG_NETSWAP
2001 + v.val = sk->swapping;
2005 /* Dubious BSD thing... Probably nobody even uses it, but
2006 * the UNIX standard wants it for whatever reason... -DaveM
2008 --- linux-2.4.20/net/ipv4/tcp_ipv4.c~130-nfsswap 2002-11-28 18:53:15.000000000 -0500
2009 +++ linux-2.4.20/net/ipv4/tcp_ipv4.c 2005-01-07 02:55:48.039453840 -0500
2010 @@ -1657,6 +1657,12 @@
2011 if (filter && sk_filter(skb, filter))
2013 #endif /* CONFIG_FILTER */
2014 +#ifdef CONFIG_NETSWAP
2015 + /* tcp doesn't use sock_queue_rcv_skb() ... */
2016 + /* an inline function defined in net/netswapping.h */
2017 + if (netswap_low_memory(sk, skb))
2019 +#endif /* CONFIG_NETSWAP */
2021 IP_INC_STATS_BH(IpInDelivers);
2023 --- linux-2.4.20/net/ipv6/tcp_ipv6.c~130-nfsswap 2002-11-28 18:53:15.000000000 -0500
2024 +++ linux-2.4.20/net/ipv6/tcp_ipv6.c 2005-01-07 02:55:48.042453384 -0500
2025 @@ -1433,6 +1433,12 @@
2026 if (filter && sk_filter(skb, filter))
2028 #endif /* CONFIG_FILTER */
2029 +#ifdef CONFIG_NETSWAP
2030 + /* tcp doesn't use sock_queue_rcv_skb() ... */
2031 + /* an inline function defined in net/netswapping.h */
2032 + if (netswap_low_memory(sk, skb))
2034 +#endif /* CONFIG_NETSWAP */
2037 * socket locking is here for SMP purposes as backlog rcv
2038 --- /dev/null 2004-04-06 13:56:48.000000000 -0400
2039 +++ linux-2.4.20/net/netswapping.c 2005-01-07 02:55:48.042453384 -0500
2042 + * linux/net/swapping.c
2044 + * Support paging over network connections (inet only)
2046 + * (c) 2000 Claus-Justus Heine <heine@instmath.rwth-aachen.de>
2049 +#include <linux/slab.h>
2050 +#include <linux/swap.h>
2051 +#include <linux/swapctl.h>
2052 +#include <linux/skbuff.h>
2053 +#include <linux/module.h>
2054 +#include <linux/sysctl.h>
2055 +#include <linux/init.h>
2056 +#include <net/netswapping.h>
2057 +#include <net/sock.h>
2058 +#include <asm/uaccess.h>
2060 +unsigned int netswap_dropped; /* statistics */
2061 +unsigned int netswap_free_pages_min;
2062 +int netswap_sock_count; /* how many sockets have swapping option set */
2064 +#ifdef CONFIG_SYSCTL
2066 +static ctl_table netswap_table[] = {
2067 + {NET_SWAP_DROPPED, "dropped",
2068 + &netswap_dropped, sizeof(int), 0644, NULL, &proc_dointvec },
2069 + {NET_SWAP_DROP_THRESHOLD, "threshold",
2070 + &netswap_free_pages_min, sizeof(int), 0644, NULL, &proc_dointvec },
2071 + {NET_SWAP_SOCK_COUNT, "sock_count",
2072 + &netswap_sock_count, sizeof(int), 0444, NULL, &proc_dointvec },
2076 +static struct ctl_table_header *netswap_sysctl_header;
2078 +static ctl_table netswap_net_table[] = {
2079 + {CTL_NETSWAP, "swapping", NULL, 0, 0555, netswap_table},
2083 +static ctl_table netswap_root_table[] = {
2084 + {CTL_NET, "net", NULL, 0, 0555, netswap_net_table},
2090 +int __init netswap_init(void)
2092 + /* drop packets when below this threshold */
2093 + netswap_free_pages_min = 32 /* freepages.min */;
2094 +#ifdef CONFIG_SYSCTL
2095 + netswap_sysctl_header = register_sysctl_table(netswap_root_table, 0);
2100 +void __exit netswap_exit(void)
2102 +#ifdef CONFIG_SYSCTL
2103 + unregister_sysctl_table(netswap_sysctl_header);
2107 +/* linux/init.h -- VERY nice :-)
2109 + * On the other hand, we have no control over the order the initcalls
2110 + * are performed ...
2112 + * Actually, we are not compiled as module ...
2115 +module_init(netswap_init)
2116 +module_exit(netswap_exit)
2117 --- linux-2.4.20/net/netsyms.c~130-nfsswap 2005-01-07 02:52:47.208944000 -0500
2118 +++ linux-2.4.20/net/netsyms.c 2005-01-07 02:55:48.043453232 -0500
2119 @@ -596,4 +596,10 @@
2120 EXPORT_SYMBOL(wireless_send_event);
2121 #endif /* CONFIG_NET_RADIO || CONFIG_NET_PCMCIA_RADIO */
2123 +#ifdef CONFIG_NETSWAP
2124 +EXPORT_SYMBOL(netswap_sock_count);
2125 +EXPORT_SYMBOL(netswap_free_pages_min);
2126 +EXPORT_SYMBOL(netswap_dropped);
2129 #endif /* CONFIG_NET */
2130 --- linux-2.4.20/net/packet/af_packet.c~130-nfsswap 2002-08-02 20:39:46.000000000 -0400
2131 +++ linux-2.4.20/net/packet/af_packet.c 2005-01-07 02:55:48.045452928 -0500
2132 @@ -453,6 +453,12 @@
2135 #endif /* CONFIG_FILTER */
2136 +#ifdef CONFIG_NETSWAP
2137 + /* packet doesn't use sock_queue_rcv_skb() ... */
2138 + /* an inline function defined in net/netswapping.h */
2139 + if (netswap_low_memory(sk, skb))
2140 + goto drop_n_restore;
2141 +#endif /* CONFIG_NETSWAP */
2143 if (atomic_read(&sk->rmem_alloc) + skb->truesize >= (unsigned)sk->rcvbuf)
2146 po->stats.tp_drops++;
2147 spin_unlock(&sk->receive_queue.lock);
2149 -#ifdef CONFIG_FILTER
2150 +#if defined(CONFIG_FILTER) || defined(CONFIG_NETSWAP)
2153 if (skb_head != skb->data && skb_shared(skb)) {
2154 @@ -561,6 +567,12 @@
2158 +#ifdef CONFIG_NETSWAP
2159 + /* packet doesn't use sock_queue_rcv_skb() ... */
2160 + /* an inline function defined in net/netswapping.h */
2161 + if (netswap_low_memory(sk, skb))
2162 + goto drop_n_restore;
2163 +#endif /* CONFIG_NETSWAP */
2165 if (sk->type == SOCK_DGRAM) {
2166 macoff = netoff = TPACKET_ALIGN(TPACKET_HDRLEN) + 16;
2167 --- linux-2.4.20/net/sunrpc/sched.c~130-nfsswap 2002-11-28 18:53:16.000000000 -0500
2168 +++ linux-2.4.20/net/sunrpc/sched.c 2005-01-07 02:55:48.046452776 -0500
2171 static spinlock_t rpc_sched_lock = SPIN_LOCK_UNLOCKED;
2173 +#if CONFIG_SWAP_VIA_NFS || CONFIG_SWAP_VIA_NFS_MODULE
2175 * This is the last-ditch buffer for NFS swap requests
2177 -static u32 swap_buffer[PAGE_SIZE >> 2];
2178 +static u32 swap_buffer[2*PAGE_SIZE >> 2];
2179 static long swap_buffer_used;
2184 clear_bit(1, &swap_buffer_used);
2189 * Disable the timer for a given RPC task. Should be called with
2191 __rpc_execute(struct rpc_task *task)
2194 + unsigned long alloc_flag = current->flags & PF_MEMALLOC;
2196 dprintk("RPC: %4d rpc_execute flgs %x\n",
2197 task->tk_pid, task->tk_flags);
2198 @@ -510,6 +513,13 @@
2202 + if (task->tk_flags & RPC_TASK_SWAPPER) {
2203 + if (!current->flags & PF_MEMALLOC) {
2204 + dprintk("__rpc_execute: Setting PF_MEMALLOC\n");
2206 + current->flags |= PF_MEMALLOC;
2213 rpc_set_sleeping(task);
2214 if (RPC_IS_ASYNC(task)) {
2215 spin_unlock_bh(&rpc_queue_lock);
2221 spin_unlock_bh(&rpc_queue_lock);
2222 @@ -563,7 +574,12 @@
2223 /* sync task: sleep here */
2224 dprintk("RPC: %4d sync task going to sleep\n",
2226 - if (current->pid == rpciod_pid)
2227 + /* it's ok to wait for rpciod when swapping,
2228 + * because this means it needed memory and is
2229 + * doing the swap-out itself.
2231 + if (current->pid == rpciod_pid &&
2232 + !(task->tk_flags & RPC_TASK_SWAPPER))
2233 printk(KERN_ERR "RPC: rpciod waiting on sync task!\n");
2235 __wait_event(task->tk_wait, !RPC_IS_SLEEPING(task));
2236 @@ -608,6 +624,10 @@
2237 /* Release all resources associated with the task */
2238 rpc_release_task(task);
2241 + if (!alloc_flag) {
2242 + current->flags &= ~PF_MEMALLOC;
2247 @@ -699,10 +719,16 @@
2251 + unsigned long alloc_flag = current->flags & PF_MEMALLOC;
2254 - if (flags & RPC_TASK_SWAPPER)
2255 + if (flags & RPC_TASK_SWAPPER) {
2257 - else if (flags & RPC_TASK_ASYNC)
2258 + if (!(current->flags & PF_MEMALLOC)) {
2259 + dprintk("rpc_allocate: Setting PF_MEMALLOC\n");
2261 + current->flags |= PF_MEMALLOC;
2262 + } else if (flags & RPC_TASK_ASYNC)
2266 @@ -710,29 +736,44 @@
2268 if ((buffer = (u32 *) kmalloc(size, gfp)) != NULL) {
2269 dprintk("RPC: allocated buffer %p\n", buffer);
2274 +#if CONFIG_SWAP_VIA_NFS || CONFIG_SWAP_VIA_NFS_MODULE
2275 if ((flags & RPC_TASK_SWAPPER) && size <= sizeof(swap_buffer)
2276 && rpc_lock_swapbuf()) {
2277 dprintk("RPC: used last-ditch swap buffer\n");
2278 - return swap_buffer;
2279 + ret = swap_buffer;
2283 + if (flags & RPC_TASK_ASYNC) {
2287 - if (flags & RPC_TASK_ASYNC)
2290 } while (!signalled());
2294 + if (!alloc_flag) {
2295 + current->flags &= ~PF_MEMALLOC;
2301 rpc_free(void *buffer)
2303 +#if CONFIG_SWAP_VIA_NFS || CONFIG_SWAP_VIA_NFS_MODULE
2304 if (buffer != swap_buffer) {
2308 +#if CONFIG_SWAP_VIA_NFS || CONFIG_SWAP_VIA_NFS_MODULE
2310 rpc_unlock_swapbuf();
2311 + printk("RPC: Released swap buffer\n");
2316 --- linux-2.4.20/net/sunrpc/xprt.c~130-nfsswap 2002-11-28 18:53:16.000000000 -0500
2317 +++ linux-2.4.20/net/sunrpc/xprt.c 2005-01-07 02:55:48.047452624 -0500
2319 __xprt_lock_write(struct rpc_xprt *xprt, struct rpc_task *task)
2321 if (!xprt->snd_task) {
2322 - if (xprt->nocong || __xprt_get_cong(xprt, task))
2323 + if (__xprt_get_cong(xprt, task))
2324 xprt->snd_task = task;
2326 if (xprt->snd_task != task) {
2331 - if (xprt->nocong || __xprt_get_cong(xprt, task))
2332 + if (__xprt_get_cong(xprt, task))
2333 xprt->snd_task = task;
2338 struct rpc_rqst *req = task->tk_rqstp;
2340 + if (xprt->nocong || RPC_IS_SWAPPER(task))
2345 dprintk("RPC: %4d xprt_cwnd_limited cong = %ld cwnd = %ld\n",