]> pilppa.org Git - familiar-h63xx-build.git/blob - org.handhelds.familiar/packages/linux/linux-wrt-2.4.20/130-nfsswap.patch
OE tree imported from monotone branch org.openembedded.oz354fam083 at revision 8b12e3...
[familiar-h63xx-build.git] / org.handhelds.familiar / packages / linux / linux-wrt-2.4.20 / 130-nfsswap.patch
1
2 #
3 # Patch managed by http://www.mn-logistik.de/unsupported/pxa250/patcher
4 #
5
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
8 @@ -0,0 +1,51 @@
9 +                     Swapping over network
10 +
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).
14 +
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.
20 +
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.
24 +
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
31 +network.
32 +
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.
38 +
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'
42 +
43 +There are two other files:
44 +
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).
49 +
50 +`/proc/sys/net/swapping/sock_count':
51 +    How many network sockets have the `SO_SWAPPING' option set (read
52 +    only, of course).
53 +
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
56 +care about it.
57 +
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
62 @@ -0,0 +1,41 @@
63 +                   Swapping to files on NFS volumes
64 +
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
69 +
70 +alias swapfile-mod nfsswap
71 +
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
77 +
78 +mount -t nfs -o rsize=2048,wsize=2048 NFS_SERVER_IP:/server_volume /mount_point
79 +
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.
83 +
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.
87 +
88 +You may want to read `Documentation/netswap.txt' as well.
89 +
90 +Swapfiles on NFS volumes can be treated like any other swapfile,
91 +i.e.
92 +
93 +dd if=/dev/zero of=/swapfiles/SWAPFILE bs=1k count=20480
94 +mkswap /swapfiles/SWAPFILE
95 +swapon /swapfiles/SWAPFILE
96 +
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.
100 +
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.
103 +
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
106 @@ -34,7 +34,7 @@
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 */
113  
114  #include <asm/uaccess.h>
115 @@ -114,6 +114,29 @@
116         return 0;
117  }
118  
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",
121 + * otherwise "1".
122 + */
123 +static int is_swap_partition_hook(unsigned int flags, struct file *swap_file,
124 +                                 void *testdata)
125 +{
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);
129 +       
130 +       if (flags & SWP_USED && dev == swap_dev) {
131 +               return 1;
132 +       } else {
133 +               return 0;
134 +       }
135 +}
136 +
137 +static inline int is_swap_partition(kdev_t dev)
138 +{
139 +       return swap_run_test(is_swap_partition_hook, &dev);
140 +}
141 +
142  /*
143   * Delete a partition given by partition number
144   *
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
147 @@ -4,6 +4,12 @@
148  mainmenu_option next_comment
149  comment 'File systems'
150  
151 +if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
152 +   tristate 'Swapping to block devices' CONFIG_BLKDEV_SWAP
153 +else
154 +   define_bool CONFIG_BLKDEV_SWAP y
155 +fi
156 +
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
160 @@ -104,6 +110,12 @@
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
168 +      fi
169 +   fi
170  
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
175 @@ -8,7 +8,7 @@
176  O_TARGET := fs.o
177  
178  export-objs := filesystems.o open.o dcache.o buffer.o
179 -mod-subdirs := nls
180 +mod-subdirs := nls nfs
181  
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 \
184 @@ -70,6 +70,7 @@
185  subdir-$(CONFIG_JFS_FS)                += jfs
186  subdir-$(CONFIG_SQUASHFS)      += squashfs
187  
188 +obj-$(CONFIG_BLKDEV_SWAP)       += blkdev_swap.o
189  
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
194 @@ -0,0 +1,309 @@
195 +/*
196 + * Swapping to partitions or files located on partitions.
197 + */
198 +
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>
208 +
209 +#ifdef DEBUG_BLKDEV_SWAP
210 +# define dprintk(fmt...) printk(##fmt)
211 +#else
212 +# define dprintk(fmt...) do { /* */ } while (0)
213 +#endif
214 +
215 +#define BLKDEV_SWAP_ID      "blkdev"
216 +#define BLKDEV_FILE_SWAP_ID "blkdev file"
217 +
218 +/*
219 + * Helper function, copied here from buffer.c
220 + */
221 +
222 +/*
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.
227 + *
228 + * brw_page() is SMP-safe, although it's being called with the
229 + * kernel lock held - but the code is ready.
230 + *
231 + * FIXME: we need a swapper_inode->get_block function to remove
232 + *        some of the bmap kludges and interface ugliness here.
233 + */
234 +int brw_page(int rw, struct page *page, kdev_t dev, int b[], int size)
235 +{
236 +       struct buffer_head *head, *bh;
237 +
238 +       if (!PageLocked(page))
239 +               panic("brw_page: page not locked for I/O");
240 +
241 +       if (!page->buffers)
242 +               create_empty_buffers(page, dev, size);
243 +       head = bh = page->buffers;
244 +
245 +       /* Stage 1: lock all the buffers */
246 +       do {
247 +               lock_buffer(bh);
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);
253 +
254 +       /* Stage 2: start the IO */
255 +       do {
256 +               struct buffer_head *next = bh->b_this_page;
257 +               submit_bh(rw, bh);
258 +               bh = next;
259 +       } while (bh != head);
260 +       return 0;
261 +}
262 +
263 +/*
264 + * We implement to methods: swapping to partitions, and swapping to files
265 + * located on partitions.
266 + */
267 +
268 +struct blkdev_swap_data {
269 +       kdev_t dev;
270 +};
271 +
272 +struct test_data {
273 +       struct file * filp;
274 +       kdev_t dev;
275 +};
276 +
277 +static int is_blkdev_swapping(unsigned int flags,
278 +                             struct file * swapf,
279 +                             void *data)
280 +{
281 +       struct test_data *testdata = (struct test_data *) data;
282 +       struct file * filp = testdata->filp;
283 +       kdev_t dev = testdata->dev;
284 +
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
287 +        * busy swap file.
288 +        */
289 +
290 +       if (swapf != filp) {
291 +               if (dev == swapf->f_dentry->d_inode->i_rdev)
292 +                       return 1;
293 +       }
294 +       return 0;
295 +}
296 +
297 +static int blkdev_swap_open(struct file * filp, void **dptr)
298 +{
299 +       int swapfilesize;
300 +       kdev_t dev;
301 +       struct blkdev_swap_data *data;
302 +       int error;
303 +       struct test_data testdata;
304 +
305 +       MOD_INC_USE_COUNT;
306 +
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 */
311 +               goto bad_swap;
312 +       }
313 +       
314 +       dev = filp->f_dentry->d_inode->i_rdev;
315 +       set_blocksize(dev, PAGE_SIZE);
316 +       error = -ENODEV;
317 +       if (!dev ||
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);
321 +               goto bad_swap;
322 +       }
323 +               
324 +       /* Check to make sure that we aren't already swapping. */
325 +       error = -EBUSY;
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);
331 +               goto bad_swap;
332 +       }
333 +
334 +       swapfilesize = 0;
335 +       if (blk_size[MAJOR(dev)])
336 +               swapfilesize = blk_size[MAJOR(dev)][MINOR(dev)]
337 +                       >> (PAGE_SHIFT - 10);
338 +
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);
342 +               error = -ENOMEM;
343 +               goto bad_swap;
344 +       }
345 +       data->dev = dev;
346 +       *dptr = data;
347 +
348 +       dprintk("blkdev_swap_open: returning %d\n", swapfilesize);
349 +       return swapfilesize;
350 +
351 + bad_swap:
352 +       MOD_DEC_USE_COUNT;
353 +       return error; /* this swap thing is not for us */       
354 +}
355 +
356 +static int blkdev_swap_release(struct file * filp, void *data)
357 +{
358 +       dprintk("blkdev_swap_release: releasing swap device %s\n",
359 +               filp->f_dentry->d_name.name);
360 +       kfree(data);
361 +       MOD_DEC_USE_COUNT;
362 +       return 0;
363 +}
364 +
365 +static int blkdev_rw_page(int rw, struct page *page, unsigned long offset,
366 +                         void *ptr)
367 +{
368 +       struct blkdev_swap_data *data = (struct blkdev_swap_data *)ptr;
369 +       brw_page(rw, page, data->dev, (int *)&offset, PAGE_SIZE);
370 +       return 1;
371 +}
372 +
373 +static struct swap_ops blkdev_swap_ops = {
374 +       blkdev_swap_open,
375 +       blkdev_swap_release,
376 +       blkdev_rw_page
377 +};
378 +
379 +struct blkdevfile_swap_data {
380 +       struct inode *swapf;
381 +};
382 +
383 +static int is_blkdevfile_swapping(unsigned int flags,
384 +                                 struct file * swapf,
385 +                                 void * data)
386 +{
387 +       struct file * filp = (struct file *) data;
388 +
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
391 +        * busy swap file.
392 +        */
393 +
394 +       if (swapf != filp) {
395 +               if (filp->f_dentry->d_inode == swapf->f_dentry->d_inode)
396 +                       return 1;
397 +       }
398 +       return 0;
399 +}
400 +
401 +static int blkdevfile_swap_open(struct file *swapf, void **dptr)
402 +{
403 +       int error = 0;
404 +       int swapfilesize;
405 +       struct blkdevfile_swap_data *data;
406 +
407 +       MOD_INC_USE_COUNT;
408 +
409 +       /* first check whether this is a regular file located on a local 
410 +        * hard disk
411 +        */
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 */
417 +               goto bad_swap;
418 +       }
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 */
423 +               goto bad_swap;
424 +       }
425 +
426 +       if (swap_run_test(is_blkdevfile_swapping, swapf)) {
427 +               dprintk("blkdevfile_swap_open: already swapping to %s\n",
428 +                       swapf->d_name.name);
429 +               error = -EBUSY;
430 +               goto bad_swap;
431 +       }
432 +       swapfilesize = swapf->f_dentry->d_inode->i_size >> PAGE_SHIFT;
433 +       if ((data = kmalloc(sizeof(*data), GFP_KERNEL)) == NULL) {
434 +               error = -ENOMEM;
435 +               goto bad_swap;
436 +       }
437 +       data->swapf = swapf->f_dentry->d_inode;
438 +       *dptr = data;
439 +       return swapfilesize;
440 +
441 + bad_swap:
442 +       MOD_DEC_USE_COUNT;
443 +       return error;
444 +}
445 +
446 +static int blkdevfile_swap_release(struct file *swapf, void *data)
447 +{
448 +       kfree(data);
449 +       MOD_DEC_USE_COUNT;
450 +       return 0;
451 +}
452 +
453 +static int blkdevfile_rw_page(int rw, struct page *page, unsigned long offset,
454 +                             void *ptr)
455 +{
456 +       struct blkdevfile_swap_data *data = (struct blkdevfile_swap_data *)ptr;
457 +       struct inode * swapf = data->swapf;
458 +       int i, j;
459 +       unsigned int block = offset
460 +               << (PAGE_SHIFT - swapf->i_sb->s_blocksize_bits);
461 +       kdev_t dev = swapf->i_dev;
462 +       int block_size;
463 +       int zones[PAGE_SIZE/512];
464 +       int zones_used;
465 +
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");
470 +                       return 0;
471 +                       }
472 +       zones_used = i;
473 +       
474 +       /* block_size == PAGE_SIZE/zones_used */
475 +       brw_page(rw, page, dev, zones, block_size);
476 +       return 1;
477 +}
478 +
479 +static struct swap_ops blkdevfile_swap_ops = {
480 +       blkdevfile_swap_open,
481 +       blkdevfile_swap_release,
482 +       blkdevfile_rw_page
483 + };
484 +
485 +int __init blkdev_swap_init(void)
486 +{
487 +       (void)register_swap_method(BLKDEV_SWAP_ID, &blkdev_swap_ops);
488 +       (void)register_swap_method(BLKDEV_FILE_SWAP_ID, &blkdevfile_swap_ops);
489 +       return 0;
490 +}
491 +
492 +void __exit blkdev_swap_exit(void)
493 +{
494 +       unregister_swap_method(BLKDEV_SWAP_ID);
495 +       unregister_swap_method(BLKDEV_FILE_SWAP_ID);
496 +}
497 +
498 +module_init(blkdev_swap_init)
499 +module_exit(blkdev_swap_exit)
500 +
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
506 @@ -743,7 +743,7 @@
507         bh->b_private = private;
508  }
509  
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)
512  {
513         static spinlock_t page_uptodate_lock = SPIN_LOCK_UNLOCKED;
514         unsigned long flags;
515 @@ -2345,47 +2345,6 @@
516         return err;
517  }
518  
519 -/*
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.
524 - *
525 - * brw_page() is SMP-safe, although it's being called with the
526 - * kernel lock held - but the code is ready.
527 - *
528 - * FIXME: we need a swapper_inode->get_block function to remove
529 - *        some of the bmap kludges and interface ugliness here.
530 - */
531 -int brw_page(int rw, struct page *page, kdev_t dev, int b[], int size)
532 -{
533 -       struct buffer_head *head, *bh;
534 -
535 -       if (!PageLocked(page))
536 -               panic("brw_page: page not locked for I/O");
537 -
538 -       if (!page->buffers)
539 -               create_empty_buffers(page, dev, size);
540 -       head = bh = page->buffers;
541 -
542 -       /* Stage 1: lock all the buffers */
543 -       do {
544 -               lock_buffer(bh);
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);
550 -
551 -       /* Stage 2: start the IO */
552 -       do {
553 -               struct buffer_head *next = bh->b_this_page;
554 -               submit_bh(rw, bh);
555 -               bh = next;
556 -       } while (bh != head);
557 -       return 0;
558 -}
559 -
560  int block_symlink(struct inode *inode, const char *symname, int len)
561  {
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
565 @@ -15,6 +15,14 @@
566  obj-$(CONFIG_ROOT_NFS) += nfsroot.o mount_clnt.o      
567  obj-$(CONFIG_NFS_V3) += nfs3proc.o nfs3xdr.o
568  
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
573 +obj-y += nfs_syms.o
574 +endif
575 +
576 +ifeq ($(CONFIG_NFS_FS),m)
577 +obj-m   += $(O_TARGET)
578 +endif
579  
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
583 @@ -58,11 +58,6 @@
584         setattr:        nfs_notify_change,
585  };
586  
587 -/* Hack for future NFS swap support */
588 -#ifndef IS_SWAPFILE
589 -# define IS_SWAPFILE(inode)    (0)
590 -#endif
591 -
592  /*
593   * Flush all dirty pages, and check for write errors.
594   *
595 @@ -217,8 +212,6 @@
596                 inode->i_ino, (unsigned long) count, (unsigned long) *ppos);
597  
598         result = -EBUSY;
599 -       if (IS_SWAPFILE(inode))
600 -               goto out_swapfile;
601         result = nfs_revalidate_inode(NFS_SERVER(inode), inode);
602         if (result)
603                 goto out;
604 @@ -230,10 +223,6 @@
605         result = generic_file_write(file, buf, count, ppos);
606  out:
607         return result;
608 -
609 -out_swapfile:
610 -       printk(KERN_INFO "NFS: attempt to write to active swap file!\n");
611 -       goto out;
612  }
613  
614  /*
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
617 @@ -0,0 +1,10 @@
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>
624 +
625 +EXPORT_SYMBOL(__nfs_refresh_inode);
626 +EXPORT_SYMBOL(nfs_write_attributes);
627 +
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
630 @@ -0,0 +1,350 @@
631 +/*
632 + * Swapping to files located on NFS mounted volumes
633 + * Copyright (c) 2000 Claus-Justus Heine
634 + *
635 + */
636 +
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>
650 +
651 +#include <linux/sunrpc/clnt.h>
652 +#include <linux/nfs_fs.h>
653 +#include <linux/nfs_fs_sb.h>
654 +#include <asm/uaccess.h>
655 +
656 +#define NFSDBG_FACILITY                NFSDBG_SWAP
657 +
658 +#define NFS_SWAP_ID "nfs file"
659 +
660 +/* we cache some values here. In principle, we only need the file.
661 + */
662 +struct nfs_swap_data {
663 +       struct file       *file;
664 +       struct inode      *inode;
665 +       struct nfs_server *server;
666 +       struct socket     *socket;
667 +};
668 +
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.
671 + */
672 +static int nfs_read_swap_page(struct page *page,
673 +                             struct nfs_server *server,
674 +                             struct inode *inode,
675 +                             struct file  *file)
676 +{
677 +       unsigned int     rsize   = server->rsize;
678 +       unsigned int     count   = PAGE_SIZE;
679 +       unsigned int     offset  = 0; /* always at start of page */
680 +       int              result, eof;
681 +       struct rpc_cred  *cred;
682 +       struct nfs_fattr fattr;
683 +
684 +       cred = nfs_file_cred(file);
685 +
686 +       do {
687 +               if (count < rsize)
688 +                       rsize = count;
689 +
690 +               lock_kernel();
691 +               result = NFS_PROTO(inode)->read(inode, cred,
692 +                                               &fattr,
693 +                                               NFS_RPC_SWAPFLAGS,
694 +                                               offset, rsize, page, &eof);
695 +               nfs_refresh_inode(inode, &fattr);
696 +               unlock_kernel();
697 +
698 +               /*
699 +                * Even if we had a partial success we can't mark the page
700 +                * cache valid.
701 +                */
702 +               if (result < 0) {
703 +                       if (result == -EISDIR)
704 +                               result = -EINVAL;
705 +                       goto io_error;
706 +               }
707 +               count  -= result;
708 +               offset += result;
709 +               if (result < rsize)     /* NFSv2ism */
710 +                       break;
711 +       } while (count);
712 +
713 +       if (count) {
714 +               char *kaddr = kmap(page);
715 +               memset(kaddr + offset, 0, count);
716 +               kunmap(page);
717 +       }
718 +       flush_dcache_page(page);
719 +       result = 0;
720 +
721 +io_error:
722 +       return result;
723 +}
724 +
725 +/* Like nfs_writepage_sync(), but when swapping page->index does not encode
726 + * the offset in the swap file alone.
727 + *
728 + */
729 +static int nfs_write_swap_page(struct page *page,
730 +                              struct nfs_server *server,
731 +                              struct inode *inode,
732 +                              struct file *file)
733 +{
734 +       struct rpc_cred  *cred;
735 +       unsigned int     wsize   = server->wsize;
736 +       unsigned int     count   = PAGE_SIZE;
737 +       unsigned int     offset  = 0;
738 +       int              result;
739 +       struct nfs_writeverf verf;
740 +       struct nfs_fattr fattr;
741 +
742 +       cred = nfs_file_cred(file);
743 +
744 +       do {
745 +               if (count < wsize)
746 +                       wsize = count;
747 +               
748 +               lock_kernel();
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);
753 +               unlock_kernel();
754 +
755 +               if (result < 0) {
756 +                       goto io_error;
757 +               }
758 +               if (result != wsize)
759 +                       printk("NFS: short write, wsize=%u, result=%d\n",
760 +                       wsize, result);
761 +               offset  += wsize;
762 +               count   -= wsize;
763 +               /*
764 +                * If we've extended the file, update the inode
765 +                * now so we don't invalidate the cache.
766 +                */
767 +               if (offset > inode->i_size)
768 +                       inode->i_size = offset;
769 +       } while (count);
770 +
771 +       result = 0;
772 +
773 +io_error:
774 +
775 +       return result;
776 +}
777 +
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.
781 + * 
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
784 + * the index later.
785 + */
786 +static int nfs_rw_swap_page(int rw, struct page *page,
787 +                           unsigned long offset, void *dptr)
788 +{
789 +       int error;
790 +       struct nfs_swap_data *data = dptr;
791 +       unsigned long alloc_flag = current->flags & PF_MEMALLOC;
792 +       unsigned long page_index;
793 +
794 +       if (!PageLocked(page))
795 +               panic("nfs_rw_swap_page: page not locked for I/O");
796 +
797 +       /* prevent memory deadlocks */
798 +       if (!(current->flags & PF_MEMALLOC)) {
799 +               dprintk("nfs_rw_swap_page: Setting PF_MEMALLOC\n");
800 +       }
801 +       current->flags |= PF_MEMALLOC;
802 +
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;
806 +
807 +       if (rw == WRITE) {
808 +               error = nfs_write_swap_page(page,
809 +                                           data->server,
810 +                                           data->inode,
811 +                                           data->file);
812 +       } else {
813 +               error = nfs_read_swap_page(page,
814 +                                          data->server,
815 +                                          data->inode,
816 +                                          data->file);
817 +       }
818 +       
819 +       if (!alloc_flag) {
820 +               current->flags &= ~PF_MEMALLOC;
821 +       }
822 +
823 +       /* now restore the page->index field ... */
824 +       page->index = page_index;
825 +
826 +       if (error) {
827 +               /* Must mark the page invalid after I/O error */
828 +               SetPageError(page);
829 +               ClearPageUptodate(page);
830 +       } else {
831 +               ClearPageError(page);
832 +               SetPageUptodate(page);
833 +       }
834 +
835 +       if (!error) { /* in case of an error rw_swap_page() likes to unlock
836 +                      * itself.
837 +                      */
838 +               UnlockPage(page);
839 +       }
840 +
841 +       return error < 0 ? 0 : 1;
842 +}
843 +
844 +static int is_nfsfile_swapping(unsigned int flags,
845 +                              struct file * swapf,
846 +                              void * data)
847 +{
848 +       struct file * filp = (struct file *) data;
849 +
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
852 +        * busy swap file.
853 +        */
854 +
855 +       if (swapf != filp) {
856 +               if (filp->f_dentry->d_inode == swapf->f_dentry->d_inode)
857 +                       return 1;
858 +       }
859 +       return 0;
860 +}
861 +
862 +static int nfs_swap_open(struct file *swapf, void **dptr)
863 +{
864 +       int error = 0;
865 +       int swapfilesize;
866 +       struct nfs_swap_data *data;
867 +       int on = 1;
868 +       mm_segment_t fs;
869 +       struct inode *inode = swapf->f_dentry->d_inode;
870 +
871 +       MOD_INC_USE_COUNT;
872 +
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 */
877 +               goto bad_swap;
878 +       }
879 +       /* determine whether this file really is located on an NFS mounted
880 +        * volume
881 +        */
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 */
886 +               goto bad_swap;
887 +       }
888 +
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);
892 +               error = -EBUSY;
893 +               goto bad_swap;
894 +       }
895 +       swapfilesize = inode->i_size >> PAGE_SHIFT;
896 +       if ((data = kmalloc(sizeof(*data), GFP_KERNEL)) == NULL) {
897 +               error = -ENOMEM;
898 +               goto bad_swap;
899 +       }
900 +       data->file   = swapf;
901 +       data->inode  = inode;
902 +       data->server = NFS_SERVER(inode);
903 +       data->socket = data->server->client->cl_xprt->sock;
904 +       
905 +       /* set socket option SO_SWAPPING */
906 +       fs = get_fs();
907 +       set_fs(KERNEL_DS);
908 +       error = sock_setsockopt(data->socket, SOL_SOCKET, SO_SWAPPING,
909 +                               (char *)&on, sizeof(on));
910 +       set_fs(fs);
911 +       if (error) {
912 +               dprintk("nfs_swap_open: error setting SO_SWAPPING\n");
913 +               goto bad_swap_2;
914 +       }
915 +
916 +       *dptr = data;
917 +       return swapfilesize;
918 +
919 + bad_swap_2:
920 +       kfree(data);
921 + bad_swap:
922 +       MOD_DEC_USE_COUNT;
923 +       return error;
924 +}
925 +
926 +static int nfs_swap_release(struct file *swapf, void *dptr)
927 +{
928 +       struct nfs_swap_data *data = (struct nfs_swap_data *)dptr;
929 +       int off = 0;
930 +       mm_segment_t fs;
931 +       int error;
932 +
933 +#if 1
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");
941 +       }
942 +#endif
943 +
944 +       /* remove socket option SO_SWAPPING */
945 +       fs = get_fs();
946 +       set_fs(KERNEL_DS);
947 +       error = sock_setsockopt(data->socket, SOL_SOCKET, SO_SWAPPING,
948 +                               (char *)&off, sizeof(off));
949 +       set_fs(fs);
950 +       if (error) {
951 +               dprintk("nfs_swap_open: error clearing SO_SWAPPING\n");
952 +       }
953 +       kfree(data);
954 +       MOD_DEC_USE_COUNT;
955 +       return error;
956 +}
957 +
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
962 +};
963 +
964 +int __init nfs_swap_init(void)
965 +{
966 +       (void)register_swap_method(NFS_SWAP_ID, &nfs_swap_ops);
967 +       return 0;
968 +}
969 +
970 +void __exit nfs_swap_exit(void)
971 +{
972 +       unregister_swap_method(NFS_SWAP_ID);
973 +}
974 +
975 +module_init(nfs_swap_init)
976 +module_exit(nfs_swap_exit)
977 +
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
983 @@ -50,11 +50,6 @@
984   */
985  static void    nfs_readpage_result(struct rpc_task *task);
986  
987 -/* Hack for future NFS swap support */
988 -#ifndef IS_SWAPFILE
989 -# define IS_SWAPFILE(inode)    (0)
990 -#endif
991 -
992  static kmem_cache_t *nfs_rdata_cachep;
993  
994  static __inline__ struct nfs_read_data *nfs_readdata_alloc(void)
995 @@ -92,7 +87,6 @@
996         int             rsize = NFS_SERVER(inode)->rsize;
997         int             result;
998         int             count = PAGE_CACHE_SIZE;
999 -       int             flags = IS_SWAPFILE(inode)? NFS_RPC_SWAPFLAGS : 0;
1000         int             eof;
1001  
1002         dprintk("NFS: nfs_readpage_sync(%p)\n", page);
1003 @@ -114,7 +108,7 @@
1004                         offset, rsize, page);
1005  
1006                 lock_kernel();
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);
1011                 unlock_kernel();
1012 @@ -246,7 +240,7 @@
1013         task = &data->task;
1014  
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;
1018  
1019         nfs_read_rpcsetup(head, data);
1020  
1021 @@ -476,8 +470,6 @@
1022         }
1023  
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");
1027  out:
1028         return error;
1029  
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
1032 @@ -49,7 +49,6 @@
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>
1039  
1040 @@ -92,11 +91,6 @@
1041  static void    nfs_commit_done(struct rpc_task *);
1042  #endif
1043  
1044 -/* Hack for future NFS swap support */
1045 -#ifndef IS_SWAPFILE
1046 -# define IS_SWAPFILE(inode)    (0)
1047 -#endif
1048 -
1049  static kmem_cache_t *nfs_wdata_cachep;
1050  
1051  static __inline__ struct nfs_write_data *nfs_writedata_alloc(void)
1052 @@ -128,7 +122,7 @@
1053   * For the moment, we just call nfs_refresh_inode().
1054   */
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)
1058  {
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);
1063  }
1064  
1065 +int nfs_write_attributes(struct inode *inode, struct nfs_fattr *fattr)
1066 +{
1067 +       return __nfs_write_attributes(inode, fattr);
1068 +}
1069 +
1070  /*
1071   * Write a page synchronously.
1072   * Offset is the data offset within the page.
1073 @@ -150,8 +149,7 @@
1074         struct rpc_cred *cred = NULL;
1075         loff_t          base;
1076         unsigned int    wsize = NFS_SERVER(inode)->wsize;
1077 -       int             result, refresh = 0, written = 0, flags;
1078 -       u8              *buffer;
1079 +       int             result, refresh = 0, written = 0;
1080         struct nfs_fattr fattr;
1081         struct nfs_writeverf verf;
1082  
1083 @@ -167,15 +165,14 @@
1084  
1085         base = page_offset(page) + offset;
1086  
1087 -       flags = ((IS_SWAPFILE(inode)) ? NFS_RW_SWAP : 0) | NFS_RW_SYNC;
1088 -
1089         do {
1090 -               if (count < wsize && !IS_SWAPFILE(inode))
1091 +               if (count < wsize)
1092                         wsize = count;
1093  
1094 -               result = NFS_PROTO(inode)->write(inode, cred, &fattr, flags,
1095 +               result = NFS_PROTO(inode)->write(inode, cred, &fattr,
1096 +                                                NFS_RW_SYNC,
1097                                                  offset, wsize, page, &verf);
1098 -               nfs_write_attributes(inode, &fattr);
1099 +               __nfs_write_attributes(inode, &fattr);
1100  
1101                 if (result < 0) {
1102                         /* Must mark the page invalid after I/O error */
1103 @@ -186,7 +183,6 @@
1104                         printk("NFS: short write, wsize=%u, result=%d\n",
1105                         wsize, result);
1106                 refresh = 1;
1107 -               buffer  += wsize;
1108                 base    += wsize;
1109                 offset  += wsize;
1110                 written += wsize;
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.
1114          */
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))
1122                 return;
1123  
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 *);
1134  
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);
1138 +
1139  /*
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
1144 @@ -40,8 +40,8 @@
1145   */
1146  #define NFS_MAX_DIRCACHE               16
1147  
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
1152  
1153  /*
1154   * The upper limit on timeouts for the exponential backoff algorithm.
1155 @@ -205,6 +205,8 @@
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);
1160 +
1161  /*
1162   * Try to write back everything synchronously (but check the
1163   * return value!)
1164 @@ -375,6 +377,7 @@
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
1170  
1171  #ifdef __KERNEL__
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
1174 @@ -39,6 +39,7 @@
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 */
1179  
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
1184 @@ -58,15 +58,29 @@
1185  #define SWAP_MAP_MAX   0x7fff
1186  #define SWAP_MAP_BAD   0x8000
1187  
1188 +struct swap_ops {
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);
1193 +};
1194 +
1195 +struct swap_method {
1196 +       struct swap_method *next;
1197 +       char * name;
1198 +       struct swap_ops *ops;
1199 +       int use_count;
1200 +};
1201 +
1202  /*
1203   * The in-memory structure used to track swap areas.
1204   */
1205  struct swap_info_struct {
1206         unsigned int flags;
1207 -       kdev_t swap_device;
1208 +       struct file *swap_file;
1209 +       struct swap_method *method;
1210 +       void *data;
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 *, 
1230 -                                       struct inode **);
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
1238 @@ -0,0 +1,47 @@
1239 +#ifndef _LINUX_NETSWAPPING_H
1240 +#define _LINUX_NETSWAPPING_H
1241 +
1242 +#include <linux/swap.h>
1243 +#include <linux/init.h>
1244 +
1245 +/* It is a mess. Socket options are defined in asm-ARCH/socket.h */
1246 +
1247 +#define SO_SWAPPING 0x00100000 /* hopefully not used by anybody else */
1248 +
1249 +#ifdef __KERNEL__
1250 +
1251 +#define CTL_NETSWAP 0x00100000
1252 +
1253 +enum {
1254 +       NET_SWAP_DROPPED = 1,
1255 +       NET_SWAP_DROP_THRESHOLD = 2,
1256 +       NET_SWAP_SOCK_COUNT = 3
1257 +};
1258 +
1259 +extern unsigned int netswap_free_pages_min;
1260 +extern int netswap_sock_count;
1261 +extern unsigned int netswap_dropped;
1262 +
1263 +/* this is "#defined" and not inline because sock.h includes us, but we need
1264 + * the "struct sock" definition.
1265 + */
1266 +#define netswap_low_memory(sk, skb)                                       \
1267 +({                                                                        \
1268 +       int _ret = 0;                                                      \
1269 +                                                                          \
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 ++;                                        \
1276 +               _ret = 1;                                                  \
1277 +       }                                                                  \
1278 +       _ret;                                                              \
1279 +})
1280 +
1281 +extern int __init netswap_init(void);
1282 +
1283 +#endif
1284 +
1285 +#endif
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>
1290  #endif
1291  
1292 +#ifdef CONFIG_NETSWAP
1293 +#include <net/netswapping.h>
1294 +#endif
1295 +
1296  #include <asm/atomic.h>
1297  #include <net/dst.h>
1298  
1299 @@ -539,6 +543,12 @@
1300                                 no_check,
1301                                 broadcast,
1302                                 bsdism;
1303 +#ifdef CONFIG_NETSWAP
1304 +       /* Increased by SO_SWAPPING with arg != 0, decreased by
1305 +        * SO_SWAPPING with arg 0
1306 +        */
1307 +       int                     swapping;
1308 +#endif
1309         unsigned char           debug;
1310         unsigned char           rcvtstamp;
1311         unsigned char           use_write_queue;
1312 @@ -1168,6 +1178,11 @@
1313                         return err;     /* Toss packet */
1314         }
1315  #endif /* CONFIG_FILTER */
1316 +#ifdef CONFIG_NETSWAP
1317 +       /* an inline function defined in net/netswapping.h */
1318 +       if (netswap_low_memory(sk, skb))
1319 +               return -ENOMEM;
1320 +#endif /* CONFIG_NETSWAP */
1321  
1322         skb->dev = NULL;
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
1326 @@ -41,6 +41,7 @@
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);
1337  #endif
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);
1343  
1344  /* filesystem internal functions */
1345  EXPORT_SYMBOL(def_blk_fops);
1346 @@ -531,7 +537,7 @@
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);
1353  
1354  #ifdef CONFIG_UID16
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
1357 @@ -36,11 +36,8 @@
1358  static int rw_swap_page_base(int rw, swp_entry_t entry, struct page *page)
1359  {
1360         unsigned long offset;
1361 -       int zones[PAGE_SIZE/512];
1362 -       int zones_used;
1363 -       kdev_t dev = 0;
1364 -       int block_size;
1365 -       struct inode *swapf = 0;
1366 +       struct swap_method *method;
1367 +       void *data;
1368  
1369         if (rw == READ) {
1370                 ClearPageUptodate(page);
1371 @@ -48,30 +45,11 @@
1372         } else
1373                 kstat.pswpout++;
1374  
1375 -       get_swaphandle_info(entry, &offset, &dev, &swapf);
1376 -       if (dev) {
1377 -               zones[0] = offset;
1378 -               zones_used = 1;
1379 -               block_size = PAGE_SIZE;
1380 -       } else if (swapf) {
1381 -               int i, j;
1382 -               unsigned int block = offset
1383 -                       << (PAGE_SHIFT - swapf->i_sb->s_blocksize_bits);
1384 -
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");
1389 -                               return 0;
1390 -                       }
1391 -               zones_used = i;
1392 -               dev = swapf->i_dev;
1393 -       } else {
1394 +       method = get_swaphandle_info(entry, &offset, &data);
1395 +       if (!method || !method->ops->rw_page(rw, page, offset, data)) {
1396                 return 0;
1397         }
1398  
1399 -       /* block_size == PAGE_SIZE/zones_used */
1400 -       brw_page(rw, page, dev, zones, block_size);
1401         return 1;
1402  }
1403  
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)
1413  #else
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)
1418  #endif
1419  
1420  /*
1421 @@ -247,8 +249,13 @@
1422  };
1423  
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)
1430 +
1431 +#if (CFLGS_MASK & CREATE_MASK)
1432 +# error BUG: internal and external SLAB flags overlap
1433 +#endif
1434  
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))) {
1442 +                                         0,
1443 +#if CONFIG_NETSWAP
1444 +                                         SLAB_LOW_GFP_ORDER|  /* sorry */
1445 +#endif
1446 +                                         SLAB_HWCACHE_ALIGN,
1447 +                                         NULL, NULL))) {
1448                         BUG();
1449                 }
1450  
1451 @@ -732,6 +744,8 @@
1452                         break;
1453                 if (!cachep->num)
1454                         goto next;
1455 +               if (cachep->gfporder == 0 && (flags & SLAB_LOW_GFP_ORDER))
1456 +                       break;
1457                 if (flags & CFLGS_OFF_SLAB && cachep->num > offslab_limit) {
1458                         /* Oops, this num of objs will cause problems. */
1459                         cachep->gfporder--;
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
1462 @@ -11,12 +11,17 @@
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>
1470  
1471  #include <asm/pgtable.h>
1472  
1473 +#ifdef CONFIG_KMOD
1474 +#include <linux/kmod.h>
1475 +#endif
1476 +
1477  spinlock_t swaplock = SPIN_LOCK_UNLOCKED;
1478  unsigned int nr_swapfiles;
1479  int total_swap_pages;
1480 @@ -31,8 +36,78 @@
1481  
1482  struct swap_info_struct swap_info[MAX_SWAPFILES];
1483  
1484 +static struct swap_method *swap_methods = NULL;
1485 +
1486  #define SWAPFILE_CLUSTER 256
1487  
1488 +int register_swap_method(char *name, struct swap_ops *ops)
1489 +{
1490 +       struct swap_method *pos;
1491 +       struct swap_method *new;
1492 +       int result = 0;
1493 +
1494 +       lock_kernel();
1495 +
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);
1500 +                       result = -EBUSY;
1501 +                       goto out;
1502 +               }
1503 +       }
1504 +
1505 +       if (!(new = kmalloc(sizeof(*new), GFP_KERNEL))) {
1506 +               printk(KERN_ERR "register_swap_method: "
1507 +                      "no memory for new method \"%s\"\n", name);
1508 +               result = -ENOMEM;
1509 +               goto out;
1510 +       }
1511 +
1512 +       new->name      = name;
1513 +       new->ops       = ops;
1514 +       new->use_count = 0;
1515 +
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;
1520 + out:
1521 +       unlock_kernel();
1522 +       return result;
1523 +}
1524 +
1525 +int unregister_swap_method(char *name)
1526 +{
1527 +       struct swap_method **method, *next;
1528 +       int result = 0;
1529 +
1530 +       lock_kernel();
1531 +
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);
1537 +                               result = -EBUSY;
1538 +                               goto out;
1539 +                       }
1540 +
1541 +                       next = (*method)->next;
1542 +                       kfree(*method);
1543 +                       *method = next;                 
1544 +                       printk("unregister_swap_method: method %s\n", name);
1545 +                       goto out;
1546 +               }
1547 +       }
1548 +       /* not found */
1549 +       printk("unregister_swap_method: no such method %s\n", name);
1550 +       result = -ENOENT;
1551 + out:
1552 +       unlock_kernel();
1553 +       return result;
1554 +}
1555 +
1556  static inline int scan_swap_map(struct swap_info_struct *si)
1557  {
1558         unsigned long offset;
1559 @@ -711,13 +786,14 @@
1560         struct nameidata nd;
1561         int i, type, prev;
1562         int err;
1563 +       struct file *swap_file;
1564         
1565         if (!capable(CAP_SYS_ADMIN))
1566                 return -EPERM;
1567  
1568         err = user_path_walk(specialfile, &nd);
1569         if (err)
1570 -               goto out;
1571 +               return err;
1572  
1573         lock_kernel();
1574         prev = -1;
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)
1582                           break;
1583                 }
1584                 prev = type;
1585         }
1586         err = -EINVAL;
1587 +       /* p->swap_file contains all needed info, no need to keep nd, so
1588 +        * release it now.
1589 +        */
1590 +       path_release(&nd);
1591         if (type < 0) {
1592                 swap_list_unlock();
1593 -               goto out_dput;
1594 +               goto out;
1595         }
1596  
1597         if (prev < 0) {
1598 @@ -767,32 +848,30 @@
1599                 total_swap_pages += p->pages;
1600                 p->flags = SWP_WRITEOK;
1601                 swap_list_unlock();
1602 -               goto out_dput;
1603 +               goto out;
1604         }
1605 -       if (p->swap_device)
1606 -               blkdev_put(p->swap_file->d_inode->i_bdev, BDEV_SWAP);
1607 -       path_release(&nd);
1608  
1609 +       if (p->method->ops->release)
1610 +               p->method->ops->release(p->swap_file, p->data);
1611         swap_list_lock();
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 --;
1617 +       p->method = NULL;
1618 +       p->data   = NULL;
1619 +       swap_file = p->swap_file;
1620         p->swap_file = NULL;
1621 -       p->swap_device = 0;
1622         p->max = 0;
1623         swap_map = p->swap_map;
1624         p->swap_map = NULL;
1625         p->flags = 0;
1626         swap_device_unlock(p);
1627         swap_list_unlock();
1628 +       filp_close(swap_file, NULL);
1629         vfree(swap_map);
1630         err = 0;
1631  
1632 -out_dput:
1633 -       unlock_kernel();
1634 -       path_release(&nd);
1635  out:
1636 +       unlock_kernel();
1637         return err;
1638  }
1639  
1640 @@ -805,18 +884,17 @@
1641         if (!page)
1642                 return -ENOMEM;
1643  
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,
1652                                                 page, PAGE_SIZE);
1653  
1654                         len += sprintf(buf + len, "%-31s ", path);
1655  
1656 -                       if (!ptr->swap_device)
1657 -                               len += sprintf(buf + len, "file\t\t");
1658 -                       else
1659 -                               len += sprintf(buf + len, "partition\t");
1660 +                       len += sprintf(buf + len, "%-15s ", ptr->method->name);
1661  
1662                         usedswap = 0;
1663                         for (j = 0; j < ptr->max; ++j)
1664 @@ -827,7 +905,7 @@
1665                                         default:
1666                                                 usedswap++;
1667                                 }
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);
1671                 }
1672         }
1673 @@ -835,18 +913,55 @@
1674         return len;
1675  }
1676  
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
1680 + */
1681 +int swap_run_test(int (*test_fct)(unsigned int flags,
1682 +                                 struct file * swap_file,
1683 +                                 void *testdata), void *testdata)
1684 +{
1685         struct swap_info_struct *ptr = swap_info;
1686         int i;
1687  
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))
1693                                 return 1;
1694         }
1695         return 0;
1696  }
1697  
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.
1701 + *
1702 + * return value: < 0: error, 0: not found, > 0: swapfilesize
1703 + */
1704 +int find_swap_method(struct file *swap_file,
1705 +                    struct swap_info_struct *p)
1706 +{
1707 +       int swapfilesize = 0;
1708 +       struct swap_method *method;
1709 +
1710 +       p->method = NULL;
1711 +       for (method = swap_methods; method; method = method->next) {
1712 +               swapfilesize = method->ops->open(swap_file, &p->data);
1713 +               if (swapfilesize == 0) {
1714 +                       continue;
1715 +               }
1716 +               if (swapfilesize > 0) {
1717 +                       p->method = method;
1718 +                       p->method->use_count ++;
1719 +                       p->swap_file = swap_file;
1720 +                       break;
1721 +               }
1722 +               if (swapfilesize < 0) {
1723 +                       break;
1724 +               }
1725 +       }
1726 +       return swapfilesize;
1727 +}
1728 +
1729  /*
1730   * Written 01/25/92 by Simmule Turner, heavily changed by Linus.
1731   *
1732 @@ -855,8 +970,6 @@
1733  asmlinkage long sys_swapon(const char * specialfile, int swap_flags)
1734  {
1735         struct swap_info_struct * p;
1736 -       struct nameidata nd;
1737 -       struct inode * swap_inode;
1738         unsigned int type;
1739         int i, j, prev;
1740         int error;
1741 @@ -866,8 +979,9 @@
1742         int nr_good_pages = 0;
1743         unsigned long maxpages = 1;
1744         int swapfilesize;
1745 -       struct block_device *bdev = NULL;
1746         unsigned short *swap_map;
1747 +       char * tmp_specialfile;
1748 +       struct file *swap_file;
1749         
1750         if (!capable(CAP_SYS_ADMIN))
1751                 return -EPERM;
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;
1758 +       p->method = NULL;
1759         p->swap_map = NULL;
1760         p->lowest_bit = 0;
1761         p->highest_bit = 0;
1762 @@ -901,53 +1014,56 @@
1763                 p->prio = --least_priority;
1764         }
1765         swap_list_unlock();
1766 -       error = user_path_walk(specialfile, &nd);
1767 -       if (error)
1768 +
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);
1773                 goto bad_swap_2;
1774 +       }
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);
1779 +               goto bad_swap_1;
1780 +       }
1781  
1782 -       p->swap_file = nd.dentry;
1783 -       p->swap_vfsmnt = nd.mnt;
1784 -       swap_inode = nd.dentry->d_inode;
1785         error = -EINVAL;
1786  
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;
1791 -
1792 -               p->swap_device = dev;
1793 -               set_blocksize(dev, PAGE_SIZE);
1794 -               
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;
1803 +               goto bad_swap_1;
1804 +       }
1805 +#ifdef CONFIG_KMOD
1806 +       if (swapfilesize == 0) {
1807 +               (void)request_module("swapfile-mod");
1808  
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*/
1811 -               if (error)
1812 -                       goto bad_swap_2;
1813 -               set_blocksize(dev, PAGE_SIZE);
1814 -               error = -ENODEV;
1815 -               if (!dev || (blk_size[MAJOR(dev)] &&
1816 -                    !blk_size[MAJOR(dev)][MINOR(dev)]))
1817 -                       goto bad_swap;
1818 -               swapfilesize = 0;
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;
1824 -       else
1825 -               goto bad_swap;
1826 +               swapfilesize = find_swap_method(p->swap_file, p);
1827 +               if (swapfilesize < 0) {
1828 +                       error = swapfilesize;
1829 +                       goto bad_swap_1;
1830 +               }
1831 +       }
1832 +#endif         
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 */
1836 +       }
1837 +  
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
1840 +        * errors.
1841 +        */
1842  
1843         error = -EBUSY;
1844         for (i = 0 ; i < nr_swapfiles ; i++) {
1845                 struct swap_info_struct *q = &swap_info[i];
1846                 if (i == type || !q->swap_file)
1847                         continue;
1848 -               if (swap_inode->i_mapping == q->swap_file->d_inode->i_mapping)
1849 +               if (p->swap_file->f_dentry->d_inode->i_mapping
1850 +                   ==
1851 +                   q->swap_file->f_dentry->d_inode->i_mapping)
1852                         goto bad_swap;
1853         }
1854  
1855 @@ -1083,17 +1199,27 @@
1856         swap_list_unlock();
1857         error = 0;
1858         goto out;
1859 +
1860  bad_swap:
1861 -       if (bdev)
1862 -               blkdev_put(bdev, BDEV_SWAP);
1863 +       if (p->method->ops->release)
1864 +               p->method->ops->release(p->swap_file, p->data);
1865 +       swap_list_lock();
1866 +       p->method->use_count --;
1867 +       p->method = NULL;
1868 +       p->data = NULL;
1869 +       swap_list_unlock();
1870 +
1871 +bad_swap_1:
1872 +       swap_list_lock();
1873 +       swap_file = p->swap_file;
1874 +       p->swap_file = NULL;
1875 +       swap_list_unlock();
1876 +       filp_close(swap_file, NULL);
1877 +       
1878  bad_swap_2:
1879 +
1880         swap_list_lock();
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;
1887         p->swap_map = NULL;
1888         p->flags = 0;
1889         if (!(swap_flags & SWAP_FLAG_PREFER))
1890 @@ -1101,7 +1227,7 @@
1891         swap_list_unlock();
1892         if (swap_map)
1893                 vfree(swap_map);
1894 -       path_release(&nd);
1895 +
1896  out:
1897         if (swap_header)
1898                 free_page((long) swap_header);
1899 @@ -1217,8 +1343,8 @@
1900  /*
1901   * Prior swap_duplicate protects against swap device deletion.
1902   */
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)
1907  {
1908         unsigned long type;
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);
1914 -               return;
1915 +               return NULL;
1916         }
1917  
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);
1922 -               return;
1923 +               return NULL;
1924         }
1925         if (p->swap_map && !p->swap_map[*offset]) {
1926                 printk(KERN_ERR "rw_swap_page: %s%08lx\n", Unused_offset, entry.val);
1927 -               return;
1928 +               return NULL;
1929         }
1930         if (!(p->flags & SWP_USED)) {
1931                 printk(KERN_ERR "rw_swap_page: %s%08lx\n", Unused_file, entry.val);
1932 -               return;
1933 +               return NULL;
1934         }
1935  
1936 -       if (p->swap_device) {
1937 -               *dev = p->swap_device;
1938 -       } else if (p->swap_file) {
1939 -               *swapf = p->swap_file->d_inode;
1940 -       } else {
1941 -               printk(KERN_ERR "rw_swap_page: no swap file or device\n");
1942 -       }
1943 -       return;
1944 +       *data = p->data;
1945 +       return p->method;
1946  }
1947  
1948  /*
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
1951 @@ -16,6 +16,9 @@
1952  fi
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
1957 +fi
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
1963 @@ -51,6 +51,7 @@
1964  ifeq ($(CONFIG_NET),y)
1965  obj-$(CONFIG_MODULES)          += netsyms.o
1966  obj-$(CONFIG_SYSCTL)           += sysctl_net.o
1967 +obj-$(CONFIG_NETSWAP)           += netswapping.o
1968  endif
1969  
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 @@
1974                         ret = -ENONET;
1975                         break;
1976  #endif
1977 +#ifdef CONFIG_NETSWAP
1978 +               case SO_SWAPPING:
1979 +                       if (valbool) {
1980 +                               if (!sk->swapping) {
1981 +                                       netswap_sock_count ++;
1982 +                               }
1983 +                               sk->swapping ++;
1984 +                       } else if (sk->swapping > 0) {
1985 +                               sk->swapping --;
1986 +                               if (!sk->swapping) {
1987 +                                       netswap_sock_count --;
1988 +                               }
1989 +                       }
1990 +                       break;
1991 +#endif
1992                 /* We implement the SO_SNDLOWAT etc to
1993                    not be settable (1003.1g 5.3) */
1994                 default:
1995 @@ -553,6 +568,12 @@
1996                         goto lenout;
1997                 }
1998  
1999 +#ifdef CONFIG_NETSWAP
2000 +               case SO_SWAPPING:
2001 +                       v.val = sk->swapping;
2002 +                       break;
2003 +#endif
2004 +
2005                 /* Dubious BSD thing... Probably nobody even uses it, but
2006                  * the UNIX standard wants it for whatever reason... -DaveM
2007                  */
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))
2012                 goto discard;
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))
2018 +               goto discard;
2019 +#endif /* CONFIG_NETSWAP */
2020  
2021         IP_INC_STATS_BH(IpInDelivers);
2022  
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))
2027                 goto discard;
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))
2033 +               goto discard;
2034 +#endif /* CONFIG_NETSWAP */
2035  
2036         /*
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
2040 @@ -0,0 +1,76 @@
2041 +/*
2042 + * linux/net/swapping.c
2043 + *
2044 + * Support paging over network connections (inet only)
2045 + *
2046 + * (c) 2000 Claus-Justus Heine <heine@instmath.rwth-aachen.de>
2047 + */
2048 +
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>
2059 +
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 */
2063 +
2064 +#ifdef CONFIG_SYSCTL
2065 +
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 },
2073 +       {0},
2074 +};
2075 +
2076 +static struct ctl_table_header *netswap_sysctl_header;
2077 +
2078 +static ctl_table netswap_net_table[] = {
2079 +       {CTL_NETSWAP, "swapping", NULL, 0, 0555, netswap_table},
2080 +       {0}
2081 +};
2082 +
2083 +static ctl_table netswap_root_table[] = {
2084 +       {CTL_NET, "net", NULL, 0, 0555, netswap_net_table},
2085 +       {0}
2086 +};
2087 +
2088 +#endif
2089 +
2090 +int __init netswap_init(void)
2091 +{
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);
2096 +#endif
2097 +       return 0;
2098 +}
2099 +
2100 +void __exit netswap_exit(void)
2101 +{
2102 +#ifdef CONFIG_SYSCTL
2103 +       unregister_sysctl_table(netswap_sysctl_header);
2104 +#endif
2105 +}
2106 +
2107 +/* linux/init.h -- VERY nice :-)
2108 + *
2109 + * On the other hand, we have no control over the order the initcalls
2110 + * are performed ...
2111 + *
2112 + * Actually, we are not compiled as module ...
2113 + */
2114 +
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 */
2122  
2123 +#ifdef CONFIG_NETSWAP
2124 +EXPORT_SYMBOL(netswap_sock_count);
2125 +EXPORT_SYMBOL(netswap_free_pages_min);
2126 +EXPORT_SYMBOL(netswap_dropped);
2127 +#endif
2128 +
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 @@
2133                         snaplen = res;
2134         }
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 */
2142  
2143         if (atomic_read(&sk->rmem_alloc) + skb->truesize >= (unsigned)sk->rcvbuf)
2144                 goto drop_n_acct;
2145 @@ -500,7 +506,7 @@
2146         po->stats.tp_drops++;
2147         spin_unlock(&sk->receive_queue.lock);
2148  
2149 -#ifdef CONFIG_FILTER
2150 +#if defined(CONFIG_FILTER) || defined(CONFIG_NETSWAP)
2151  drop_n_restore:
2152  #endif
2153         if (skb_head != skb->data && skb_shared(skb)) {
2154 @@ -561,6 +567,12 @@
2155                         snaplen = res;
2156         }
2157  #endif
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 */
2164  
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
2169 @@ -79,10 +79,11 @@
2170   */
2171  static spinlock_t rpc_sched_lock = SPIN_LOCK_UNLOCKED;
2172  
2173 +#if CONFIG_SWAP_VIA_NFS || CONFIG_SWAP_VIA_NFS_MODULE
2174  /*
2175   * This is the last-ditch buffer for NFS swap requests
2176   */
2177 -static u32                     swap_buffer[PAGE_SIZE >> 2];
2178 +static u32                     swap_buffer[2*PAGE_SIZE >> 2];
2179  static long                    swap_buffer_used;
2180  
2181  /*
2182 @@ -96,6 +97,7 @@
2183  {
2184         clear_bit(1, &swap_buffer_used);
2185  }
2186 +#endif
2187  
2188  /*
2189   * Disable the timer for a given RPC task. Should be called with
2190 @@ -501,6 +503,7 @@
2191  __rpc_execute(struct rpc_task *task)
2192  {
2193         int             status = 0;
2194 +       unsigned long alloc_flag = current->flags & PF_MEMALLOC;
2195  
2196         dprintk("RPC: %4d rpc_execute flgs %x\n",
2197                                 task->tk_pid, task->tk_flags);
2198 @@ -510,6 +513,13 @@
2199                 return 0;
2200         }
2201  
2202 +       if (task->tk_flags & RPC_TASK_SWAPPER) {
2203 +               if (!current->flags & PF_MEMALLOC) {
2204 +                       dprintk("__rpc_execute: Setting PF_MEMALLOC\n");
2205 +               }
2206 +               current->flags |= PF_MEMALLOC;
2207 +       }
2208 +
2209   restarted:
2210         while (1) {
2211                 /*
2212 @@ -554,7 +564,8 @@
2213                         rpc_set_sleeping(task);
2214                         if (RPC_IS_ASYNC(task)) {
2215                                 spin_unlock_bh(&rpc_queue_lock);
2216 -                               return 0;
2217 +                               status = 0;
2218 +                               goto out;
2219                         }
2220                 }
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",
2225                                                         task->tk_pid);
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.
2230 +                        */
2231 +                       if (current->pid == rpciod_pid &&
2232 +                           !(task->tk_flags & RPC_TASK_SWAPPER))
2233                                 printk(KERN_ERR "RPC: rpciod waiting on sync task!\n");
2234  
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);
2239  
2240 + out:
2241 +       if (!alloc_flag) {
2242 +               current->flags &= ~PF_MEMALLOC;
2243 +       }       
2244         return status;
2245  }
2246  
2247 @@ -699,10 +719,16 @@
2248  {
2249         u32     *buffer;
2250         int     gfp;
2251 +       unsigned long alloc_flag = current->flags & PF_MEMALLOC;
2252 +       void    *ret = NULL;
2253  
2254 -       if (flags & RPC_TASK_SWAPPER)
2255 +       if (flags & RPC_TASK_SWAPPER) {
2256                 gfp = GFP_ATOMIC;
2257 -       else if (flags & RPC_TASK_ASYNC)
2258 +               if (!(current->flags & PF_MEMALLOC)) {
2259 +                       dprintk("rpc_allocate: Setting PF_MEMALLOC\n");
2260 +               }
2261 +               current->flags |= PF_MEMALLOC;
2262 +       } else if (flags & RPC_TASK_ASYNC)
2263                 gfp = GFP_RPC;
2264         else
2265                 gfp = GFP_KERNEL;
2266 @@ -710,29 +736,44 @@
2267         do {
2268                 if ((buffer = (u32 *) kmalloc(size, gfp)) != NULL) {
2269                         dprintk("RPC:      allocated buffer %p\n", buffer);
2270 -                       return buffer;
2271 +                       ret = buffer;
2272 +                       goto out;
2273                 }
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;
2280 +                       goto out;
2281 +#endif
2282 +               }
2283 +               if (flags & RPC_TASK_ASYNC) {
2284 +                       ret = NULL;
2285 +                       goto out;
2286                 }
2287 -               if (flags & RPC_TASK_ASYNC)
2288 -                       return NULL;
2289                 yield();
2290         } while (!signalled());
2291  
2292 -       return NULL;
2293 + out:
2294 +       if (!alloc_flag) {
2295 +               current->flags &= ~PF_MEMALLOC;
2296 +       }
2297 +       return ret;
2298  }
2299  
2300  void
2301  rpc_free(void *buffer)
2302  {
2303 +#if CONFIG_SWAP_VIA_NFS || CONFIG_SWAP_VIA_NFS_MODULE
2304         if (buffer != swap_buffer) {
2305 +#endif
2306                 kfree(buffer);
2307                 return;
2308 +#if CONFIG_SWAP_VIA_NFS || CONFIG_SWAP_VIA_NFS_MODULE
2309         }
2310         rpc_unlock_swapbuf();
2311 +       printk("RPC:      Released swap buffer\n");
2312 +#endif
2313  }
2314  
2315  /*
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
2318 @@ -139,7 +139,7 @@
2319  __xprt_lock_write(struct rpc_xprt *xprt, struct rpc_task *task)
2320  {
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;
2325         }
2326         if (xprt->snd_task != task) {
2327 @@ -179,7 +179,7 @@
2328                 if (!task)
2329                         return;
2330         }
2331 -       if (xprt->nocong || __xprt_get_cong(xprt, task))
2332 +       if (__xprt_get_cong(xprt, task))
2333                 xprt->snd_task = task;
2334  }
2335  
2336 @@ -276,6 +276,9 @@
2337  {
2338         struct rpc_rqst *req = task->tk_rqstp;
2339  
2340 +       if (xprt->nocong || RPC_IS_SWAPPER(task))
2341 +               return 1;
2342 +
2343         if (req->rq_cong)
2344                 return 1;
2345         dprintk("RPC: %4d xprt_cwnd_limited cong = %ld cwnd = %ld\n",