Whamcloud - gitweb
Branch HEAD
[fs/lustre-release.git] / lustre / kernel_patches / patches / qsnet-suse-2.6.patch
1 Index: LINUX-SRC-TREE/arch/i386/defconfig
2 ===================================================================
3 --- LINUX-SRC-TREE.orig/arch/i386/defconfig
4 +++ LINUX-SRC-TREE/arch/i386/defconfig
5 @@ -2932,3 +2932,5 @@ CONFIG_CFGNAME="default"
6  CONFIG_RELEASE="7.283"
7  CONFIG_X86_BIOS_REBOOT=y
8  CONFIG_PC=y
9 +CONFIG_IOPROC=y
10 +CONFIG_PTRACK=y
11 Index: LINUX-SRC-TREE/arch/i386/Kconfig
12 ===================================================================
13 --- LINUX-SRC-TREE.orig/arch/i386/Kconfig
14 +++ LINUX-SRC-TREE/arch/i386/Kconfig
15 @@ -1022,6 +1022,9 @@ config APM_REAL_MODE_POWER_OFF
16           a work-around for a number of buggy BIOSes. Switch this option on if
17           your computer crashes instead of powering off properly.
18  
19 +source "mm/Kconfig"
20 +source "kernel/Kconfig"
21 +       
22  endmenu
23  
24  source "arch/i386/kernel/cpu/cpufreq/Kconfig"
25 Index: LINUX-SRC-TREE/arch/i386/mm/hugetlbpage.c
26 ===================================================================
27 --- LINUX-SRC-TREE.orig/arch/i386/mm/hugetlbpage.c
28 +++ LINUX-SRC-TREE/arch/i386/mm/hugetlbpage.c
29 @@ -16,6 +16,7 @@
30  #include <linux/err.h>
31  #include <linux/sysctl.h>
32  #include <linux/mempolicy.h>
33 +#include <linux/ioproc.h>
34  #include <asm/mman.h>
35  #include <asm/pgalloc.h>
36  #include <asm/tlb.h>
37 @@ -393,6 +394,7 @@ zap_hugepage_range(struct vm_area_struct
38  {
39         struct mm_struct *mm = vma->vm_mm;
40         spin_lock(&mm->page_table_lock);
41 +       ioproc_invalidate_range(vma, start, start + length);
42         unmap_hugepage_range(vma, start, start + length);
43         spin_unlock(&mm->page_table_lock);
44  }
45 Index: LINUX-SRC-TREE/arch/ia64/defconfig
46 ===================================================================
47 --- LINUX-SRC-TREE.orig/arch/ia64/defconfig
48 +++ LINUX-SRC-TREE/arch/ia64/defconfig
49 @@ -104,6 +104,8 @@ CONFIG_IA64_PALINFO=y
50  CONFIG_EFI_VARS=y
51  CONFIG_BINFMT_ELF=y
52  CONFIG_BINFMT_MISC=m
53 +CONFIG_IOPROC=y
54 +CONFIG_PTRACK=y
55  
56  #
57  # Power management and ACPI
58 Index: LINUX-SRC-TREE/arch/ia64/Kconfig
59 ===================================================================
60 --- LINUX-SRC-TREE.orig/arch/ia64/Kconfig
61 +++ LINUX-SRC-TREE/arch/ia64/Kconfig
62 @@ -334,6 +334,8 @@ config EFI_VARS
63           To use this option, you have to check that the "/proc file system
64           support" (CONFIG_PROC_FS) is enabled, too.
65  
66 +source "mm/Kconfig"
67 +source "kernel/Kconfig"
68  source "fs/Kconfig.binfmt"
69  
70  endmenu
71 Index: LINUX-SRC-TREE/arch/ia64/mm/hugetlbpage.c
72 ===================================================================
73 --- LINUX-SRC-TREE.orig/arch/ia64/mm/hugetlbpage.c
74 +++ LINUX-SRC-TREE/arch/ia64/mm/hugetlbpage.c
75 @@ -19,6 +19,7 @@
76  #include <linux/slab.h>
77  #include <linux/sysctl.h>
78  #include <linux/mempolicy.h>
79 +#include <linux/ioproc.h>
80  #include <asm/mman.h>
81  #include <asm/pgalloc.h>
82  #include <asm/tlb.h>
83 @@ -378,6 +379,7 @@ void zap_hugepage_range(struct vm_area_s
84  {
85         struct mm_struct *mm = vma->vm_mm;
86         spin_lock(&mm->page_table_lock);
87 +       ioproc_invalidate_range(vma, start, start + length);
88         unmap_hugepage_range(vma, start, start + length);
89         spin_unlock(&mm->page_table_lock);
90  }
91 Index: LINUX-SRC-TREE/arch/x86_64/defconfig
92 ===================================================================
93 --- LINUX-SRC-TREE.orig/arch/x86_64/defconfig
94 +++ LINUX-SRC-TREE/arch/x86_64/defconfig
95 @@ -98,6 +98,8 @@ CONFIG_MTRR=y
96  CONFIG_GART_IOMMU=y
97  CONFIG_SWIOTLB=y
98  CONFIG_X86_MCE=y
99 +CONFIG_IOPROC=y
100 +CONFIG_PTRACK=y
101  
102  #
103  # Power management options
104 Index: LINUX-SRC-TREE/arch/x86_64/Kconfig
105 ===================================================================
106 --- LINUX-SRC-TREE.orig/arch/x86_64/Kconfig
107 +++ LINUX-SRC-TREE/arch/x86_64/Kconfig
108 @@ -343,6 +343,9 @@ source "drivers/acpi/Kconfig"
109  
110  source "arch/x86_64/kernel/cpufreq/Kconfig"
111  
112 +source "mm/Kconfig"
113 +source "kernel/Kconfig"
114 +
115  endmenu
116  
117  menu "Bus options (PCI etc.)"
118 Index: LINUX-SRC-TREE/Documentation/vm/ioproc.txt
119 ===================================================================
120 --- /dev/null
121 +++ LINUX-SRC-TREE/Documentation/vm/ioproc.txt
122 @@ -0,0 +1,468 @@
123 +Linux IOPROC patch overview
124 +===========================
125 +
126 +The network interface for an HPC network differs significantly from
127 +network interfaces for traditional IP networks. HPC networks tend to
128 +be used directly from user processes and perform large RDMA transfers
129 +between theses processes address space. They also have a requirement
130 +for low latency communication, and typically achieve this by OS bypass
131 +techniques.  This then requires a different model to traditional
132 +interconnects, in that a process may need to expose a large amount of
133 +it's address space to the network RDMA.
134 +
135 +Locking down of memory has been a common mechanism for performing
136 +this, together with a pin-down cache implemented in user
137 +libraries. The disadvantage of this method is that large portions of
138 +the physical memory can be locked down for a single process, even if
139 +it's working set changes over the different phases of it's
140 +execution. This leads to inefficient memory utilisation - akin to the
141 +disadvantage of swapping compared to paging.
142 +
143 +This model also has problems where memory is being dynamically
144 +allocated and freed, since the pin down cache is unaware that memory
145 +may have been released by a call to munmap() and so it will still be
146 +locking down the now unused pages.
147 +
148 +Some modern HPC network interfaces implement their own MMU and are
149 +able to handle a translation fault during a network access. The
150 +Quadrics (http://www.quadrics.com) devices (Elan3 and Elan4) have done
151 +this for some time and we expect others to follow the same route in
152 +the relatively near future. These NICs are able to operate in an
153 +environment where paging occurs and do not require memory to be locked
154 +down. The advantage of this is that the user process can expose large
155 +portions of it's address space without having to worry about physical
156 +memory constraints.
157 +
158 +However should the operating system decide to swap a page to disk,
159 +then the NIC must be made aware that it should no longer read/write
160 +from this memory, but should generate a translation fault instead.
161 +
162 +The ioproc patch has been developed to provide a mechanism whereby the
163 +device driver for a NIC can be aware of when a user process's address
164 +translations change, either by paging or by explicitly mapping or
165 +unmapping memory.
166 +
167 +The patch involves inserting callbacks where translations are being
168 +invalidated to notify the NIC that the memory behind those
169 +translations is no longer visible to the application (and so should
170 +not be visible to the NIC). This callback is then responsible for
171 +ensuring that the NIC will not access the physical memory that was
172 +being mapped.
173 +
174 +An ioproc invalidate callback in the kswapd code could be utilised to
175 +prevent memory from being paged out if the NIC is unable to support
176 +network page faulting.
177 +
178 +For NICs which support network page faulting, there is no requirement
179 +for a user level pin down cache, since they are able to page-in their
180 +translations on the first communication using a buffer. However this
181 +is likely to be inefficient, resulting in slow first use of the
182 +buffer. If the communication buffers were continually allocated and
183 +freed using mmap based malloc() calls then this would lead to all
184 +communications being slower than desirable.
185 +
186 +To optimise these warm-up cases the ioproc patch adds calls to
187 +ioproc_update wherever the kernel is creating translations for a user
188 +process. These then allows the device driver to preload translations
189 +so that they are already present for the first network communication
190 +from a buffer.
191 +
192 +Linux 2.6 IOPROC implementation details
193 +=======================================
194 +
195 +The Linux IOPROC patch adds hooks to the Linux VM code whenever page
196 +table entries are being created and/or invalidated. IOPROC device
197 +drivers can register their interest in being informed of such changes
198 +by registering an ioproc_ops structure which is defined as follows;
199 +
200 +extern int ioproc_register_ops(struct mm_struct *mm, struct ioproc_ops *ip);
201 +extern int ioproc_unregister_ops(struct mm_struct *mm, struct ioproc_ops *ip);
202 +
203 +typedef struct ioproc_ops {
204 +       struct ioproc_ops *next;
205 +       void *arg;
206 +
207 +       void (*release)(void *arg, struct mm_struct *mm);
208 +       void (*sync_range)(void *arg, struct vm_area_struct *vma, unsigned long start, unsigned long end);
209 +       void (*invalidate_range)(void *arg, struct vm_area_struct *vma, unsigned long start, unsigned long end);
210 +       void (*update_range)(void *arg, struct vm_area_struct *vma, unsigned long start, unsigned long end);
211 +
212 +       void (*change_protection)(void *arg, struct vm_area_struct *vma, unsigned long start, unsigned long end, pgprot_t newprot);
213 +
214 +       void (*sync_page)(void *arg, struct vm_area_struct *vma, unsigned long address);
215 +       void (*invalidate_page)(void *arg, struct vm_area_struct *vma, unsigned long address);
216 +       void (*update_page)(void *arg, struct vm_area_struct *vma, unsigned long address);
217 +
218 +} ioproc_ops_t;
219 +
220 +ioproc_register_ops
221 +===================
222 +This function should be called by the IOPROC device driver to register
223 +its interest in PTE changes for the process associated with the passed
224 +in mm_struct.
225 +
226 +The ioproc registration is not inherited across fork() and should be
227 +called once for each process that IOPROC is interested in.
228 +
229 +This function must be called whilst holding the mm->page_table_lock.
230 +
231 +ioproc_unregister_ops
232 +=====================
233 +This function should be called by the IOPROC device driver when it no
234 +longer requires informing of PTE changes in the process associated
235 +with the supplied mm_struct.
236 +
237 +This function is not normally needed to be called as the ioproc_ops
238 +struct is unlinked from the associated mm_struct during the
239 +ioproc_release() call.
240 +
241 +This function must be called whilst holding the mm->page_table_lock.
242 +
243 +ioproc_ops struct
244 +=================
245 +A linked list ioproc_ops structures is hung off the user process
246 +mm_struct (linux/sched.h). At each hook point in the patched kernel
247 +the ioproc patch will call the associated ioproc_ops callback function
248 +pointer in turn for each registered structure.
249 +
250 +The intention of the callbacks is to allow the IOPROC device driver to
251 +inspect the new or modified PTE entry via the Linux kernel
252 +(e.g. find_pte_map()). These callbacks should not modify the Linux
253 +kernel VM state or PTE entries.
254 +
255 +The ioproc_ops callback function pointers are defined as follows;
256 +
257 +ioproc_release
258 +==============
259 +The release hook is called when a program exits and all its vma areas
260 +are torn down and unmapped. i.e. during exit_mmap(). Before each
261 +release hook is called the ioproc_ops structure is unlinked from the
262 +mm_struct.
263 +
264 +No locks are required as the process has the only reference to the mm
265 +at this point.
266 +
267 +ioproc_sync_[range|page]
268 +========================
269 +The sync hooks are called when a memory map is synchronised with its
270 +disk image i.e. when the msync() syscall is invoked. Any future read
271 +or write by the IOPROC device to the associated pages should cause the
272 +page to be marked as referenced or modified.
273 +
274 +Called holding the mm->page_table_lock
275 +
276 +ioproc_invalidate_[range|page]
277 +==============================
278 +The invalidate hooks are called whenever a valid PTE is unloaded
279 +e.g. when a page is unmapped by the user or paged out by the
280 +kernel. After this call the IOPROC must not access the physical memory
281 +again unless a new translation is loaded.
282 +
283 +Called holding the mm->page_table_lock
284 +
285 +ioproc_update_[range|page]
286 +==========================
287 +The update hooks are called whenever a valid PTE is loaded
288 +e.g. mmaping memory, moving the brk up, when breaking COW or faulting
289 +in an anonymous page of memory. These give the IOPROC device the
290 +opportunity to load translations speculatively, which can improve
291 +performance by avoiding device translation faults.
292 +
293 +Called holding the mm->page_table_lock
294 +
295 +ioproc_change_protection
296 +========================
297 +This hook is called when the protection on a region of memory is
298 +changed i.e. when the mprotect() syscall is invoked.
299 +
300 +The IOPROC must not be able to write to a read-only page, so if the
301 +permissions are downgraded then it must honour them. If they are
302 +upgraded it can treat this in the same way as the
303 +ioproc_update_[range|page]() calls
304 +
305 +Called holding the mm->page_table_lock
306 +
307 +
308 +Linux 2.6 IOPROC patch details
309 +==============================
310 +
311 +Here are the specific details of each ioproc hook added to the Linux
312 +2.6 VM system and the reasons for doing so;
313 +
314 +++++ FILE
315 +       mm/fremap.c
316 +
317 +==== FUNCTION
318 +       zap_pte
319 +
320 +CALLED FROM
321 +       install_page
322 +       install_file_pte
323 +
324 +PTE MODIFICATION
325 +       ptep_clear_flush
326 +
327 +ADDED HOOKS
328 +       ioproc_invalidate_page
329 +
330 +==== FUNCTION
331 +       install_page
332 +
333 +CALLED FROM
334 +       filemap_populate, shmem_populate
335 +
336 +PTE MODIFICATION
337 +       set_pte
338 +
339 +ADDED HOOKS
340 +       ioproc_update_page
341 +
342 +==== FUNCTION
343 +       install_file_pte
344 +
345 +CALLED FROM
346 +       filemap_populate, shmem_populate
347 +
348 +PTE MODIFICATION
349 +       set_pte
350 +
351 +ADDED HOOKS
352 +       ioproc_update_page
353 +
354 +
355 +++++ FILE
356 +       mm/memory.c
357 +
358 +==== FUNCTION
359 +       zap_page_range
360 +
361 +CALLED FROM
362 +       read_zero_pagealigned, madvise_dontneed, unmap_mapping_range,
363 +       unmap_mapping_range_list, do_mmap_pgoff
364 +
365 +PTE MODIFICATION
366 +       set_pte (unmap_vmas)
367 +
368 +ADDED HOOKS
369 +       ioproc_invalidate_range
370 +
371 +
372 +==== FUNCTION
373 +       zeromap_page_range
374 +
375 +CALLED FROM
376 +       read_zero_pagealigned, mmap_zero
377 +
378 +PTE MODIFICATION
379 +       set_pte (zeromap_pte_range)
380 +
381 +ADDED HOOKS
382 +       ioproc_invalidate_range
383 +       ioproc_update_range
384 +
385 +
386 +==== FUNCTION
387 +       remap_page_range
388 +
389 +CALLED FROM
390 +       many device drivers
391 +
392 +PTE MODIFICATION
393 +       set_pte (remap_pte_range)
394 +
395 +ADDED HOOKS
396 +       ioproc_invalidate_range
397 +       ioproc_update_range
398 +
399 +
400 +==== FUNCTION
401 +       break_cow
402 +
403 +CALLED FROM
404 +       do_wp_page
405 +
406 +PTE MODIFICATION
407 +       ptep_establish
408 +
409 +ADDED HOOKS
410 +       ioproc_invalidate_page
411 +       ioproc_update_page
412 +
413 +
414 +==== FUNCTION
415 +       do_wp_page
416 +
417 +CALLED FROM
418 +       do_swap_page, handle_pte_fault
419 +
420 +PTE MODIFICATION
421 +       ptep_set_access_flags
422 +
423 +ADDED HOOKS
424 +       ioproc_update_page
425 +
426 +
427 +==== FUNCTION
428 +       do_swap_page
429 +
430 +CALLED FROM
431 +       handle_pte_fault
432 +
433 +PTE MODIFICATION
434 +       set_pte
435 +
436 +ADDED HOOKS
437 +       ioproc_update_page
438 +
439 +
440 +==== FUNCTION
441 +       do_anonymous_page
442 +
443 +CALLED FROM
444 +       do_no_page
445 +
446 +PTE MODIFICATION
447 +       set_pte
448 +
449 +ADDED HOOKS
450 +       ioproc_update_page
451 +
452 +
453 +==== FUNCTION
454 +       do_no_page
455 +
456 +CALLED FROM
457 +       do_file_page, handle_pte_fault
458 +
459 +PTE MODIFICATION
460 +       set_pte
461 +
462 +ADDED HOOKS
463 +       ioproc_update_page
464 +
465 +
466 +++++ FILE
467 +       mm/mmap.c
468 +
469 +==== FUNCTION
470 +       unmap_region
471 +
472 +CALLED FROM
473 +       do_munmap
474 +
475 +PTE MODIFICATION
476 +       set_pte (unmap_vmas)
477 +
478 +ADDED HOOKS
479 +       ioproc_invalidate_range
480 +
481 +
482 +==== FUNCTION
483 +       exit_mmap
484 +
485 +CALLED FROM
486 +       mmput
487 +
488 +PTE MODIFICATION
489 +       set_pte (unmap_vmas)
490 +
491 +ADDED HOOKS
492 +       ioproc_release
493 +
494 +
495 +++++ FILE
496 +       mm/mprotect.c
497 +
498 +==== FUNCTION
499 +       change_protection
500 +
501 +CALLED FROM
502 +       mprotect_fixup
503 +
504 +PTE MODIFICATION
505 +       set_pte (change_pte_range)
506 +
507 +ADDED HOOKS
508 +       ioproc_change_protection
509 +
510 +
511 +++++ FILE
512 +       mm/mremap.c
513 +
514 +==== FUNCTION
515 +       move_page_tables
516 +
517 +CALLED FROM
518 +       move_vma
519 +
520 +PTE MODIFICATION
521 +       ptep_clear_flush (move_one_page)
522 +
523 +ADDED HOOKS
524 +       ioproc_invalidate_range
525 +       ioproc_invalidate_range
526 +
527 +
528 +++++ FILE
529 +       mm/rmap.c
530 +
531 +==== FUNCTION
532 +       try_to_unmap_one
533 +
534 +CALLED FROM
535 +       try_to_unmap_anon, try_to_unmap_file
536 +
537 +PTE MODIFICATION
538 +       ptep_clear_flush
539 +
540 +ADDED HOOKS
541 +       ioproc_invalidate_page
542 +
543 +
544 +==== FUNCTION
545 +       try_to_unmap_cluster
546 +
547 +CALLED FROM
548 +       try_to_unmap_file
549 +
550 +PTE MODIFICATION
551 +       ptep_clear_flush
552 +
553 +ADDED HOOKS
554 +       ioproc_invalidate_page
555 +
556 +
557 +
558 +++++ FILE 
559 +       mm/msync.c
560 +
561 +==== FUNCTION
562 +       filemap_sync
563 +
564 +CALLED FROM
565 +       msync_interval
566 +
567 +PTE MODIFICATION
568 +       ptep_clear_flush_dirty (filemap_sync_pte)
569 +
570 +ADDED HOOKS
571 +       ioproc_sync_range
572 +
573 +
574 +++++ FILE
575 +       mm/hugetlb.c
576 +
577 +==== FUNCTION
578 +       zap_hugepage_range
579 +
580 +CALLED FROM
581 +       hugetlb_vmtruncate_list
582 +
583 +PTE MODIFICATION
584 +       ptep_get_and_clear (unmap_hugepage_range)
585 +
586 +ADDED HOOK
587 +       ioproc_invalidate_range
588 +
589 +
590 +-- Last update DavidAddison - 17 Aug 2004
591 Index: LINUX-SRC-TREE/fs/exec.c
592 ===================================================================
593 --- LINUX-SRC-TREE.orig/fs/exec.c
594 +++ LINUX-SRC-TREE/fs/exec.c
595 @@ -65,6 +65,8 @@ EXPORT_SYMBOL(coredump_notifier_list);
596  #include <linux/kmod.h>
597  #endif
598  
599 +#include <linux/ptrack.h>
600 +
601  int core_uses_pid;
602  char core_pattern[65] = "core";
603  int suid_dumpable = 0;
604 @@ -1213,6 +1215,9 @@ int do_execve(char * filename,
605         if (retval < 0)
606                 goto out;
607  
608 +       /* notify any ptrack callbacks of the process exec */
609 +       ptrack_call_callbacks(PTRACK_PHASE_EXEC, NULL);
610 +
611         retval = search_binary_handler(&bprm,regs);
612         if (retval >= 0) {
613                 TRIG_EVENT(exec_hook, file->f_dentry->d_name.len,
614 Index: LINUX-SRC-TREE/fs/read_write.c
615 ===================================================================
616 --- LINUX-SRC-TREE.orig/fs/read_write.c
617 +++ LINUX-SRC-TREE/fs/read_write.c
618 @@ -339,6 +339,7 @@ asmlinkage ssize_t sys_write(unsigned in
619  
620         return ret;
621  }
622 +EXPORT_SYMBOL_GPL(sys_write);
623  
624  asmlinkage ssize_t sys_pread64(unsigned int fd, char __user *buf,
625                              size_t count, loff_t pos)
626 Index: LINUX-SRC-TREE/fs/select.c
627 ===================================================================
628 --- LINUX-SRC-TREE.orig/fs/select.c
629 +++ LINUX-SRC-TREE/fs/select.c
630 @@ -649,3 +649,4 @@ ssize_t generic_aio_poll(struct kiocb *i
631         }
632         return -EIOCBRETRY;
633  }
634 +EXPORT_SYMBOL_GPL(sys_poll);
635 Index: LINUX-SRC-TREE/include/linux/init_task.h
636 ===================================================================
637 --- LINUX-SRC-TREE.orig/include/linux/init_task.h
638 +++ LINUX-SRC-TREE/include/linux/init_task.h
639 @@ -3,6 +3,7 @@
640  
641  #include <linux/file.h>
642  #include <linux/pagg.h>
643 +#include <linux/ptrack.h>
644  
645  #define INIT_FILES \
646  {                                                      \
647 @@ -116,6 +117,7 @@ extern struct group_info init_groups;
648         .map_base       = __TASK_UNMAPPED_BASE,                         \
649         .io_wait        = NULL,                                         \
650         INIT_TASK_PAGG(tsk)                                             \
651 +       INIT_TASK_PTRACK(tsk)                                           \
652  }
653  
654  
655 Index: LINUX-SRC-TREE/include/linux/ioproc.h
656 ===================================================================
657 --- /dev/null
658 +++ LINUX-SRC-TREE/include/linux/ioproc.h
659 @@ -0,0 +1,271 @@
660 +/* -*- linux-c -*-
661 + *
662 + *    Copyright (C) 2002-2004 Quadrics Ltd.
663 + *
664 + *    This program is free software; you can redistribute it and/or modify
665 + *    it under the terms of the GNU General Public License as published by
666 + *    the Free Software Foundation; either version 2 of the License, or
667 + *    (at your option) any later version.
668 + *
669 + *    This program is distributed in the hope that it will be useful,
670 + *    but WITHOUT ANY WARRANTY; without even the implied warranty of
671 + *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
672 + *    GNU General Public License for more details.
673 + *
674 + *    You should have received a copy of the GNU General Public License
675 + *    along with this program; if not, write to the Free Software
676 + *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
677 + *
678 + *
679 + */
680 +
681 +/*
682 + * Callbacks for IO processor page table updates.
683 + */
684 +
685 +#ifndef __LINUX_IOPROC_H__
686 +#define __LINUX_IOPROC_H__
687 +
688 +#include <linux/sched.h>
689 +#include <linux/mm.h>
690 +
691 +typedef struct ioproc_ops {
692 +       struct ioproc_ops *next;
693 +       void *arg;
694 +
695 +       void (*release)(void *arg, struct mm_struct *mm);
696 +       void (*sync_range)(void *arg, struct vm_area_struct *vma, unsigned long start, unsigned long end);
697 +       void (*invalidate_range)(void *arg, struct vm_area_struct *vma, unsigned long start, unsigned long end);
698 +       void (*update_range)(void *arg, struct vm_area_struct *vma, unsigned long start, unsigned long end);
699 +
700 +       void (*change_protection)(void *arg, struct vm_area_struct *vma, unsigned long start, unsigned long end, pgprot_t newprot);
701 +
702 +       void (*sync_page)(void *arg, struct vm_area_struct *vma, unsigned long address);
703 +       void (*invalidate_page)(void *arg, struct vm_area_struct *vma, unsigned long address);
704 +       void (*update_page)(void *arg, struct vm_area_struct *vma, unsigned long address);
705 +
706 +} ioproc_ops_t;
707 +
708 +/* IOPROC Registration
709 + * 
710 + * Called by the IOPROC device driver to register its interest in page table
711 + * changes for the process associated with the supplied mm_struct
712 + *
713 + * The caller should first allocate and fill out an ioproc_ops structure with 
714 + * the function pointers initialised to the device driver specific code for
715 + * each callback. If the device driver doesn't have code for a particular 
716 + * callback then it should set the function pointer to be NULL.
717 + * The ioproc_ops arg parameter will be passed unchanged as the first argument
718 + * to each callback function invocation.
719 + *
720 + * The ioproc registration is not inherited across fork() and should be called
721 + * once for each process that the IOPROC device driver is interested in.
722 + *
723 + * Must be called holding the mm->page_table_lock
724 + */
725 +extern int ioproc_register_ops(struct mm_struct *mm, struct ioproc_ops *ip);
726 +
727 +
728 +/* IOPROC De-registration
729 + * 
730 + * Called by the IOPROC device driver when it is no longer interested in page 
731 + * table changes for the process associated with the supplied mm_struct
732 + *
733 + * Normally this is not needed to be called as the ioproc_release() code will
734 + * automatically unlink the ioproc_ops struct from the mm_struct as the
735 + * process exits
736 + *
737 + * Must be called holding the mm->page_table_lock
738 + */
739 +extern int ioproc_unregister_ops(struct mm_struct *mm, struct ioproc_ops *ip);
740 +
741 +#ifdef CONFIG_IOPROC
742 +
743 +/* IOPROC Release
744 + *
745 + * Called during exit_mmap() as all vmas are torn down and unmapped.
746 + *
747 + * Also unlinks the ioproc_ops structure from the mm list as it goes.
748 + *
749 + * No need for locks as the mm can no longer be accessed at this point
750 + *
751 + */
752 +static inline void 
753 +ioproc_release(struct mm_struct *mm)
754 +{
755 +       struct ioproc_ops *cp;
756 +
757 +       while ((cp = mm->ioproc_ops) != NULL) {
758 +               mm->ioproc_ops = cp->next;
759 +        
760 +               if (cp->release)
761 +                       cp->release(cp->arg, mm);
762 +       }
763 +}
764 +
765 +/* IOPROC SYNC RANGE
766 + *
767 + * Called when a memory map is synchronised with its disk image i.e. when the 
768 + * msync() syscall is invoked. Any future read or write to the associated 
769 + * pages by the IOPROC should cause the page to be marked as referenced or 
770 + * modified.
771 + *
772 + * Called holding the mm->page_table_lock
773 + */
774 +static inline void 
775 +ioproc_sync_range(struct vm_area_struct *vma, unsigned long start, unsigned long end)
776 +{
777 +       struct ioproc_ops *cp;
778 +
779 +       for (cp = vma->vm_mm->ioproc_ops; cp; cp = cp->next)
780 +               if (cp->sync_range)
781 +                       cp->sync_range(cp->arg, vma, start, end);
782 +}
783 +
784 +/* IOPROC INVALIDATE RANGE
785 + *
786 + * Called whenever a valid PTE is unloaded e.g. when a page is unmapped by the
787 + * user or paged out by the kernel. 
788 + *
789 + * After this call the IOPROC must not access the physical memory again unless
790 + * a new translation is loaded.
791 + *
792 + * Called holding the mm->page_table_lock
793 + */
794 +static inline void 
795 +ioproc_invalidate_range(struct vm_area_struct *vma, unsigned long start, unsigned long end)
796 +{
797 +       struct ioproc_ops *cp;
798 +       
799 +       for (cp = vma->vm_mm->ioproc_ops; cp; cp = cp->next)
800 +               if (cp->invalidate_range)
801 +                       cp->invalidate_range(cp->arg, vma, start, end);
802 +}
803 +
804 +/* IOPROC UPDATE RANGE
805 + *
806 + * Called whenever a valid PTE is loaded e.g. mmaping memory, moving the brk 
807 + * up, when breaking COW or faulting in an anonymous page of memory.
808 + *
809 + * These give the IOPROC device driver the opportunity to load translations 
810 + * speculatively, which can improve performance by avoiding device translation
811 + * faults.
812 + *
813 + * Called holding the mm->page_table_lock
814 + */
815 +static inline void 
816 +ioproc_update_range(struct vm_area_struct *vma, unsigned long start, unsigned long end)
817 +{
818 +       struct ioproc_ops *cp;
819 +
820 +       for (cp = vma->vm_mm->ioproc_ops; cp; cp = cp->next)
821 +               if (cp->update_range)
822 +                       cp->update_range(cp->arg, vma, start, end);
823 +}
824 +
825 +
826 +/* IOPROC CHANGE PROTECTION
827 + *
828 + * Called when the protection on a region of memory is changed i.e. when the 
829 + * mprotect() syscall is invoked.
830 + *
831 + * The IOPROC must not be able to write to a read-only page, so if the 
832 + * permissions are downgraded then it must honour them. If they are upgraded 
833 + * it can treat this in the same way as the ioproc_update_[range|sync]() calls
834 + *
835 + * Called holding the mm->page_table_lock
836 + */
837 +static inline void 
838 +ioproc_change_protection(struct vm_area_struct *vma, unsigned long start, unsigned long end, pgprot_t newprot)
839 +{
840 +       struct ioproc_ops *cp;
841 +
842 +       for (cp = vma->vm_mm->ioproc_ops; cp; cp = cp->next)
843 +               if (cp->change_protection)
844 +                       cp->change_protection(cp->arg, vma, start, end, newprot);
845 +}
846 +
847 +/* IOPROC SYNC PAGE
848 + *
849 + * Called when a memory map is synchronised with its disk image i.e. when the 
850 + * msync() syscall is invoked. Any future read or write to the associated page
851 + * by the IOPROC should cause the page to be marked as referenced or modified.
852 + *
853 + * Not currently called as msync() calls ioproc_sync_range() instead
854 + *
855 + * Called holding the mm->page_table_lock
856 + */
857 +static inline void 
858 +ioproc_sync_page(struct vm_area_struct *vma, unsigned long addr)
859 +{
860 +       struct ioproc_ops *cp;
861 +
862 +       for (cp = vma->vm_mm->ioproc_ops; cp; cp = cp->next)
863 +               if (cp->sync_page)
864 +                       cp->sync_page(cp->arg, vma, addr);
865 +}
866 +
867 +/* IOPROC INVALIDATE PAGE
868 + *
869 + * Called whenever a valid PTE is unloaded e.g. when a page is unmapped by the
870 + * user or paged out by the kernel. 
871 + *
872 + * After this call the IOPROC must not access the physical memory again unless
873 + * a new translation is loaded.
874 + *
875 + * Called holding the mm->page_table_lock
876 + */
877 +static inline void 
878 +ioproc_invalidate_page(struct vm_area_struct *vma, unsigned long addr)
879 +{
880 +       struct ioproc_ops *cp;
881 +
882 +       for (cp = vma->vm_mm->ioproc_ops; cp; cp = cp->next)
883 +               if (cp->invalidate_page)
884 +                       cp->invalidate_page(cp->arg, vma, addr);
885 +}
886 +
887 +/* IOPROC UPDATE PAGE
888 + *
889 + * Called whenever a valid PTE is loaded e.g. mmaping memory, moving the brk 
890 + * up, when breaking COW or faulting in an anoymous page of memory.
891 + *
892 + * These give the IOPROC device the opportunity to load translations 
893 + * speculatively, which can improve performance by avoiding device translation
894 + * faults.
895 + *
896 + * Called holding the mm->page_table_lock
897 + */
898 +static inline void 
899 +ioproc_update_page(struct vm_area_struct *vma, unsigned long addr)
900 +{
901 +       struct ioproc_ops *cp;
902 +
903 +       for (cp = vma->vm_mm->ioproc_ops; cp; cp = cp->next)
904 +               if (cp->update_page)
905 +                       cp->update_page(cp->arg, vma, addr);
906 +}
907 +
908 +#else
909 +
910 +/* ! CONFIG_IOPROC so make all hooks empty */
911 +
912 +#define ioproc_release(mm)                     do { } while (0)
913 +
914 +#define ioproc_sync_range(vma,start,end)               do { } while (0)
915 +
916 +#define ioproc_invalidate_range(vma, start,end)        do { } while (0)
917 +
918 +#define ioproc_update_range(vma, start, end)   do { } while (0)
919 +
920 +#define ioproc_change_protection(vma, start, end, prot)        do { } while (0)
921 +
922 +#define ioproc_sync_page(vma, addr)            do { } while (0)
923 +
924 +#define ioproc_invalidate_page(vma, addr)      do { } while (0)
925 +
926 +#define ioproc_update_page(vma, addr)          do { } while (0)
927 +
928 +#endif /* CONFIG_IOPROC */
929 +
930 +#endif /* __LINUX_IOPROC_H__ */
931 Index: LINUX-SRC-TREE/include/linux/ptrack.h
932 ===================================================================
933 --- /dev/null
934 +++ LINUX-SRC-TREE/include/linux/ptrack.h
935 @@ -0,0 +1,65 @@
936 +/*
937 + *    Copyright (C) 2000  Regents of the University of California
938 + *
939 + *    This program is free software; you can redistribute it and/or modify
940 + *    it under the terms of the GNU General Public License as published by
941 + *    the Free Software Foundation; either version 2 of the License, or
942 + *    (at your option) any later version.
943 + *
944 + *    This program is distributed in the hope that it will be useful,
945 + *    but WITHOUT ANY WARRANTY; without even the implied warranty of
946 + *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
947 + *    GNU General Public License for more details.
948 + *
949 + *    You should have received a copy of the GNU General Public License
950 + *    along with this program; if not, write to the Free Software
951 + *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
952 + *
953 + * Derived from exit_actn.c by
954 + *    Copyright (C) 2003 Quadrics Ltd.
955 + *
956 + */
957 +#ifndef __LINUX_PTRACK_H
958 +#define __LINUX_PTRACK_H
959 +
960 +/* 
961 + * Process tracking - this allows a module to keep track of processes
962 + * in order that it can manage all tasks derived from a single process.
963 + */
964 +
965 +#define PTRACK_PHASE_CLONE     1
966 +#define PTRACK_PHASE_CLONE_FAIL        2
967 +#define PTRACK_PHASE_EXEC      3
968 +#define PTRACK_PHASE_EXIT              4
969 +
970 +#define PTRACK_FINISHED                0
971 +#define PTRACK_INNHERIT                1
972 +#define PTRACK_DENIED          2
973 +
974 +#ifdef CONFIG_PTRACK
975 +
976 +typedef int (*ptrack_callback_t)(void *arg, int phase, struct task_struct *child);
977 +
978 +struct ptrack_desc {
979 +       struct list_head        link;
980 +       ptrack_callback_t       callback;
981 +       void                   *arg;
982 +};
983 +
984 +extern int     ptrack_register (ptrack_callback_t callback, void *arg);
985 +extern void    ptrack_deregister (ptrack_callback_t callback, void *arg);
986 +extern int     ptrack_registered (ptrack_callback_t callback, void *arg);
987 +
988 +extern int     ptrack_call_callbacks (int phase, struct task_struct *child);
989 +
990 +#define INIT_TASK_PTRACK(tsk) \
991 +       .ptrack_list = LIST_HEAD_INIT(tsk.ptrack_list)
992 +
993 +#else
994 +#define ptrack_call_callbacks (phase, child) (0)
995 +
996 +#define INIT_TASK_PTRACK(tsk)
997 +
998 +#endif
999 +
1000 +#endif /* __LINUX_PTRACK_H */
1001 Index: LINUX-SRC-TREE/include/linux/sched.h
1002 ===================================================================
1003 --- LINUX-SRC-TREE.orig/include/linux/sched.h
1004 +++ LINUX-SRC-TREE/include/linux/sched.h
1005 @@ -188,6 +188,9 @@ asmlinkage void schedule(void);
1006  extern int max_timeslice, min_timeslice;
1007  
1008  struct namespace;
1009 +#ifdef CONFIG_IOPROC
1010 +struct ioproc_ops;
1011 +#endif
1012  
1013  /* Maximum number of active map areas.. This is a random (large) number */
1014  #define DEFAULT_MAX_MAP_COUNT  65536
1015 @@ -241,6 +244,11 @@ struct mm_struct {
1016         struct kioctx           default_kioctx;
1017  
1018         unsigned long hiwater_rss, hiwater_vm;
1019 +
1020 +#ifdef CONFIG_IOPROC
1021 +       /* hooks for io devices with advanced RDMA capabilities */
1022 +       struct ioproc_ops       *ioproc_ops;
1023 +#endif
1024  };
1025  
1026  extern int mmlist_nr;
1027 @@ -603,6 +611,10 @@ struct task_struct {
1028         struct rw_semaphore pagg_sem;
1029  #endif
1030  
1031 +#ifdef CONFIG_PTRACK
1032 +/* process tracking callback */
1033 +       struct list_head ptrack_list;
1034 +#endif
1035  };
1036  
1037  static inline pid_t process_group(struct task_struct *tsk)
1038 Index: LINUX-SRC-TREE/ipc/shm.c
1039 ===================================================================
1040 --- LINUX-SRC-TREE.orig/ipc/shm.c
1041 +++ LINUX-SRC-TREE/ipc/shm.c
1042 @@ -27,6 +27,7 @@
1043  #include <linux/shmem_fs.h>
1044  #include <linux/security.h>
1045  #include <linux/audit.h>
1046 +#include <linux/module.h>
1047  #include <linux/trigevent_hooks.h>
1048  #include <asm/uaccess.h>
1049  
1050 @@ -879,6 +880,44 @@ asmlinkage long sys_shmdt(char __user *s
1051         return audit_result(retval);
1052  }
1053  
1054 +/*
1055 + * Mark all segments created by this process for destruction
1056 + */
1057 +int shm_cleanup (void)
1058 +{
1059 +       int i;
1060 +
1061 +       down(&shm_ids.sem);
1062 +
1063 +       for (i = 0; i <= shm_ids.max_id; i++) {
1064 +               struct shmid_kernel *shp;
1065 +
1066 +               shp = shm_lock(i);
1067 +               if (shp != NULL) {
1068 +                       /* mark this segment for destruction if we created it */
1069 +                       if (current->pid == shp->shm_cprid)
1070 +                       {
1071 +                               /* copy of IPC_RMID code */
1072 +                               if (shp->shm_nattch) {
1073 +                                       shp->shm_flags |= SHM_DEST;
1074 +                                       /* do not find it any more */
1075 +                                       shp->shm_perm.key = IPC_PRIVATE;
1076 +                               } else {
1077 +                                       shm_destroy(shp);
1078 +                                       continue;
1079 +                               }
1080 +                       }
1081 +
1082 +                       shm_unlock(shp);
1083 +               }
1084 +       }
1085 +
1086 +       up(&shm_ids.sem);
1087 +
1088 +       return 0;
1089 +}
1090 +EXPORT_SYMBOL_GPL(shm_cleanup);
1091 +
1092  #ifdef CONFIG_PROC_FS
1093  static int sysvipc_shm_read_proc(char *buffer, char **start, off_t offset, int length, int *eof, void *data)
1094  {
1095 Index: LINUX-SRC-TREE/kernel/exit.c
1096 ===================================================================
1097 --- LINUX-SRC-TREE.orig/kernel/exit.c
1098 +++ LINUX-SRC-TREE/kernel/exit.c
1099 @@ -40,6 +40,8 @@
1100  /* tng related changes */
1101  int (*tng_exitfunc)(int) = NULL;
1102  
1103 +#include <linux/ptrack.h>
1104 +
1105  extern void sem_exit (void);
1106  extern struct task_struct *child_reaper;
1107  void (*do_eop_acct) (int, struct task_struct *);
1108 @@ -848,6 +850,8 @@ asmlinkage NORET_TYPE void do_exit(long 
1109                 audit_exit(tsk, code);
1110         audit_free(tsk->audit);
1111  #endif
1112 +       /* Notify any ptrack callbacks of the process exit */
1113 +       ptrack_call_callbacks (PTRACK_PHASE_EXIT, NULL);
1114         __exit_mm(tsk);
1115  
1116         if (unlikely(tng_exitfunc))
1117 Index: LINUX-SRC-TREE/kernel/fork.c
1118 ===================================================================
1119 --- LINUX-SRC-TREE.orig/kernel/fork.c
1120 +++ LINUX-SRC-TREE/kernel/fork.c
1121 @@ -14,6 +14,7 @@
1122  #include <linux/config.h>
1123  #include <linux/slab.h>
1124  #include <linux/init.h>
1125 +#include <linux/ptrack.h>
1126  #include <linux/unistd.h>
1127  #include <linux/smp_lock.h>
1128  #include <linux/module.h>
1129 @@ -432,6 +433,9 @@ static struct mm_struct * mm_init(struct
1130         mm->page_table_lock = SPIN_LOCK_UNLOCKED;
1131         mm->ioctx_list_lock = RW_LOCK_UNLOCKED;
1132         mm->ioctx_list = NULL;
1133 +#ifdef CONFIG_IOPROC
1134 +       mm->ioproc_ops = NULL;
1135 +#endif
1136         mm->default_kioctx = (struct kioctx)INIT_KIOCTX(mm->default_kioctx, *mm);
1137         mm->free_area_cache = TASK_UNMAPPED_BASE;
1138  
1139 @@ -1276,6 +1280,11 @@ long do_fork(unsigned long clone_flags,
1140                       audit_fork(current, p);
1141  #endif
1142  
1143 +               if (ptrack_call_callbacks(PTRACK_PHASE_CLONE, p)) {
1144 +                       sigaddset(&p->pending.signal, SIGKILL);
1145 +                       set_tsk_thread_flag(p, TIF_SIGPENDING);
1146 +               }
1147 +
1148                 /* Trace the event  */
1149                 TRIG_EVENT(fork_hook, clone_flags, p, pid);
1150                 if (!(clone_flags & CLONE_STOPPED)) {
1151 Index: LINUX-SRC-TREE/kernel/Kconfig
1152 ===================================================================
1153 --- /dev/null
1154 +++ LINUX-SRC-TREE/kernel/Kconfig
1155 @@ -0,0 +1,14 @@
1156 +#
1157 +# Kernel subsystem specific config
1158 +# 
1159 +
1160 +# Support for Process Tracking callbacks
1161 +#
1162 +config PTRACK
1163 +       bool "Enable PTRACK process tracking hooks"
1164 +       default y
1165 +       help
1166 +       This option enables hooks to be called when processes are
1167 +       created and destoryed in order for a resource management 
1168 +       system to know which processes are a member of a "job" and 
1169 +       to be able to clean up when the job is terminated.
1170 Index: LINUX-SRC-TREE/kernel/Makefile
1171 ===================================================================
1172 --- LINUX-SRC-TREE.orig/kernel/Makefile
1173 +++ LINUX-SRC-TREE/kernel/Makefile
1174 @@ -29,6 +29,7 @@ obj-$(CONFIG_LTT) += ltt/
1175  obj-$(CONFIG_KPROBES) += kprobes.o
1176  obj-$(CONFIG_CPUSETS) += cpuset.o
1177  obj-$(CONFIG_CKRM_CPU_SCHEDULE) += ckrm_classqueue.o ckrm_sched.o
1178 +obj-$(CONFIG_PTRACK) += ptrack.o
1179  
1180  ifneq ($(CONFIG_IA64),y)
1181  # According to Alan Modra <alan@linuxcare.com.au>, the -fno-omit-frame-pointer is
1182 Index: LINUX-SRC-TREE/kernel/ptrack.c
1183 ===================================================================
1184 --- /dev/null
1185 +++ LINUX-SRC-TREE/kernel/ptrack.c
1186 @@ -0,0 +1,145 @@
1187 +/*
1188 + *    Copyright (C) 2000  Regents of the University of California
1189 + *
1190 + *    This program is free software; you can redistribute it and/or modify
1191 + *    it under the terms of the GNU General Public License as published by
1192 + *    the Free Software Foundation; either version 2 of the License, or
1193 + *    (at your option) any later version.
1194 + *
1195 + *    This program is distributed in the hope that it will be useful,
1196 + *    but WITHOUT ANY WARRANTY; without even the implied warranty of
1197 + *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1198 + *    GNU General Public License for more details.
1199 + *
1200 + *    You should have received a copy of the GNU General Public License
1201 + *    along with this program; if not, write to the Free Software
1202 + *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
1203 + *
1204 + * Derived from exit_actn.c by
1205 + *    Copyright (C) 2003 Quadrics Ltd.
1206 + */
1207 +
1208 +
1209 +#include <linux/module.h>
1210 +#include <linux/spinlock.h>
1211 +#include <linux/sched.h>
1212 +#include <linux/ptrack.h>
1213 +#include <linux/slab.h>
1214 +#include <linux/list.h>
1215 +
1216 +#include <asm/errno.h>
1217 +
1218 +int
1219 +ptrack_register (ptrack_callback_t callback, void *arg)
1220 +{
1221 +       struct ptrack_desc *desc = kmalloc (sizeof (struct ptrack_desc), GFP_KERNEL);
1222 +       
1223 +       if (desc == NULL)
1224 +               return -ENOMEM;
1225 +
1226 +       desc->callback = callback;
1227 +       desc->arg      = arg;
1228 +       
1229 +       list_add_tail (&desc->link, &current->ptrack_list);
1230 +       
1231 +       return 0;
1232 +}
1233 +
1234 +void
1235 +ptrack_deregister (ptrack_callback_t callback, void *arg)
1236 +{      
1237 +       struct list_head *el, *nel;
1238 +       
1239 +       list_for_each_safe (el, nel, &current->ptrack_list) {
1240 +               struct ptrack_desc *desc = list_entry (el, struct ptrack_desc, link);
1241 +               
1242 +               if (desc->callback == callback && desc->arg == arg) {
1243 +                       list_del (&desc->link);
1244 +                       kfree (desc);
1245 +               }
1246 +       }
1247 +}
1248 +
1249 +int
1250 +ptrack_registered (ptrack_callback_t callback, void *arg)
1251 +{
1252 +       struct list_head *el;
1253 +       
1254 +       list_for_each (el, &current->ptrack_list) {
1255 +               struct ptrack_desc *desc = list_entry (el, struct ptrack_desc, link);
1256 +               
1257 +               if (desc->callback == callback && desc->arg == arg)
1258 +                       return 1;
1259 +       }
1260 +       return 0;
1261 +}      
1262 +        
1263 +int
1264 +ptrack_call_callbacks (int phase, struct task_struct *child)
1265 +{
1266 +       struct list_head *el, *nel;
1267 +       struct ptrack_desc *new;
1268 +       int res;
1269 +
1270 +       if (phase == PTRACK_PHASE_CLONE)
1271 +               INIT_LIST_HEAD (&child->ptrack_list);
1272 +
1273 +       list_for_each_safe (el, nel, &current->ptrack_list) {
1274 +               struct ptrack_desc *desc = list_entry (el, struct ptrack_desc, link);
1275 +               
1276 +              res = desc->callback (desc->arg, phase, child);
1277 +               
1278 +               switch (phase)
1279 +               {
1280 +               case PTRACK_PHASE_EXIT:
1281 +                       list_del (&desc->link);
1282 +                       kfree (desc);
1283 +                       break;
1284 +                       
1285 +               case PTRACK_PHASE_CLONE:
1286 +                      switch (res)
1287 +                      {
1288 +                      case PTRACK_FINISHED:
1289 +                              break;
1290 +
1291 +                      case PTRACK_INNHERIT:
1292 +                              if ((new = kmalloc (sizeof (struct ptrack_desc), GFP_ATOMIC)) == NULL)
1293 +                              {
1294 +                                      /* allocation failed - notify that this process is not going
1295 +                                       * to be started by signalling clone failure.
1296 +                                       */
1297 +                                      desc->callback (desc->arg, PTRACK_PHASE_CLONE_FAIL, child);
1298 +                                      
1299 +                                      goto failed;
1300 +                              }
1301 +
1302 +                               new->callback = desc->callback;
1303 +                               new->arg      = desc->arg;
1304 +                               
1305 +                               list_add_tail (&new->link, &child->ptrack_list);
1306 +                              break;
1307 +
1308 +                      case PTRACK_DENIED:
1309 +                              goto failed;
1310 +                       }
1311 +                      break;
1312 +               }
1313 +       }
1314 +
1315 +       return 0;
1316 +
1317 + failed:
1318 +       while (! list_empty (&child->ptrack_list))
1319 +       {
1320 +              struct ptrack_desc *desc = list_entry (child->ptrack_list.next, struct ptrack_desc, link);
1321 +              
1322 +              desc->callback (desc->arg, PTRACK_PHASE_CLONE_FAIL, child);
1323 +
1324 +              list_del (&desc->link);
1325 +              kfree (desc);
1326 +       }
1327 +       return 1;
1328 +}
1329 +EXPORT_SYMBOL(ptrack_register);
1330 +EXPORT_SYMBOL(ptrack_deregister);
1331 +EXPORT_SYMBOL(ptrack_registered);
1332 Index: LINUX-SRC-TREE/kernel/signal.c
1333 ===================================================================
1334 --- LINUX-SRC-TREE.orig/kernel/signal.c
1335 +++ LINUX-SRC-TREE/kernel/signal.c
1336 @@ -2315,6 +2315,7 @@ sys_tkill(int pid, int sig)
1337         read_unlock(&tasklist_lock);
1338         return audit_lresult(error);
1339  }
1340 +EXPORT_SYMBOL_GPL(sys_kill);
1341  
1342  asmlinkage long
1343  sys_rt_sigqueueinfo(int pid, int sig, siginfo_t __user *uinfo)
1344 Index: LINUX-SRC-TREE/mm/fremap.c
1345 ===================================================================
1346 --- LINUX-SRC-TREE.orig/mm/fremap.c
1347 +++ LINUX-SRC-TREE/mm/fremap.c
1348 @@ -14,6 +14,7 @@
1349  #include <linux/swapops.h>
1350  #include <linux/objrmap.h>
1351  #include <linux/module.h>
1352 +#include <linux/ioproc.h>
1353  
1354  #include <asm/mmu_context.h>
1355  #include <asm/cacheflush.h>
1356 @@ -29,6 +30,7 @@ static inline void zap_pte(struct mm_str
1357         if (pte_present(pte)) {
1358                 unsigned long pfn = pte_pfn(pte);
1359  
1360 +               ioproc_invalidate_page(vma, addr);
1361                 flush_cache_page(vma, addr);
1362                 pte = ptep_clear_flush(vma, addr, ptep);
1363                 if (pfn_valid(pfn)) {
1364 @@ -80,6 +82,7 @@ int install_page(struct mm_struct *mm, s
1365         pte_val = *pte;
1366         pte_unmap(pte);
1367         update_mmu_cache(vma, addr, pte_val);
1368 +       ioproc_update_page(vma, addr);
1369  
1370         err = 0;
1371  err_unlock:
1372 @@ -118,6 +121,7 @@ int install_file_pte(struct mm_struct *m
1373         pte_val = *pte;
1374         pte_unmap(pte);
1375         update_mmu_cache(vma, addr, pte_val);
1376 +       ioproc_update_page(vma, addr);
1377         spin_unlock(&mm->page_table_lock);
1378         return 0;
1379  
1380 Index: LINUX-SRC-TREE/mm/ioproc.c
1381 ===================================================================
1382 --- /dev/null
1383 +++ LINUX-SRC-TREE/mm/ioproc.c
1384 @@ -0,0 +1,58 @@
1385 +/* -*- linux-c -*-
1386 + *
1387 + *    Copyright (C) 2002-2004 Quadrics Ltd.
1388 + *
1389 + *    This program is free software; you can redistribute it and/or modify
1390 + *    it under the terms of the GNU General Public License as published by
1391 + *    the Free Software Foundation; either version 2 of the License, or
1392 + *    (at your option) any later version.
1393 + *
1394 + *    This program is distributed in the hope that it will be useful,
1395 + *    but WITHOUT ANY WARRANTY; without even the implied warranty of
1396 + *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1397 + *    GNU General Public License for more details.
1398 + *
1399 + *    You should have received a copy of the GNU General Public License
1400 + *    along with this program; if not, write to the Free Software
1401 + *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
1402 + *
1403 + *
1404 + */
1405 +
1406 +/*
1407 + * Registration for IO processor page table updates.
1408 + */
1409 +
1410 +#include <linux/kernel.h>
1411 +#include <linux/module.h>
1412 +
1413 +#include <linux/mm.h>
1414 +#include <linux/ioproc.h>
1415 +
1416 +int
1417 +ioproc_register_ops(struct mm_struct *mm, struct ioproc_ops *ip)
1418 +{
1419 +       ip->next = mm->ioproc_ops;
1420 +       mm->ioproc_ops = ip;
1421 +
1422 +       return 0;
1423 +}
1424 +
1425 +EXPORT_SYMBOL_GPL(ioproc_register_ops);
1426 +
1427 +int
1428 +ioproc_unregister_ops(struct mm_struct *mm, struct ioproc_ops *ip)
1429 +{
1430 +       struct ioproc_ops **tmp;
1431 +
1432 +       for (tmp = &mm->ioproc_ops; *tmp && *tmp != ip; tmp= &(*tmp)->next)
1433 +               ;
1434 +       if (*tmp) {
1435 +               *tmp = ip->next;
1436 +               return 0;
1437 +       }
1438 +
1439 +       return -EINVAL;
1440 +}
1441 +
1442 +EXPORT_SYMBOL_GPL(ioproc_unregister_ops);
1443 Index: LINUX-SRC-TREE/mm/Kconfig
1444 ===================================================================
1445 --- /dev/null
1446 +++ LINUX-SRC-TREE/mm/Kconfig
1447 @@ -0,0 +1,15 @@
1448 +#
1449 +# VM subsystem specific config
1450 +# 
1451 +
1452 +# Support for IO processors which have advanced RDMA capabilities
1453 +#
1454 +config IOPROC
1455 +       bool "Enable IOPROC VM hooks"
1456 +       depends on MMU
1457 +       default y
1458 +       help
1459 +       This option enables hooks in the VM subsystem so that IO devices which
1460 +       incorporate advanced RDMA capabilities can be kept in sync with CPU 
1461 +       page table changes.
1462 +       See Documentation/vm/ioproc.txt for more details.
1463 Index: LINUX-SRC-TREE/mm/Makefile
1464 ===================================================================
1465 --- LINUX-SRC-TREE.orig/mm/Makefile
1466 +++ LINUX-SRC-TREE/mm/Makefile
1467 @@ -15,4 +15,5 @@ obj-y                 := bootmem.o filemap.o mempool.o
1468  obj-$(CONFIG_SWAP)     += page_io.o swap_state.o swapfile.o
1469  obj-$(CONFIG_PROC_MM)  += proc_mm.o
1470  obj-$(CONFIG_NUMA)     += policy.o
1471 +obj-$(CONFIG_IOPROC)    += ioproc.o
1472  
1473 Index: LINUX-SRC-TREE/mm/memory.c
1474 ===================================================================
1475 --- LINUX-SRC-TREE.orig/mm/memory.c
1476 +++ LINUX-SRC-TREE/mm/memory.c
1477 @@ -43,6 +43,7 @@
1478  #include <linux/swap.h>
1479  #include <linux/highmem.h>
1480  #include <linux/pagemap.h>
1481 +#include <linux/ioproc.h>
1482  #include <linux/objrmap.h>
1483  #include <linux/module.h>
1484  #include <linux/acct.h>
1485 @@ -627,6 +628,7 @@ void zap_page_range(struct vm_area_struc
1486  
1487         lru_add_drain();
1488         spin_lock(&mm->page_table_lock);
1489 +       ioproc_invalidate_range(vma, address, end);
1490         tlb = tlb_gather_mmu(mm, 0);
1491         unmap_vmas(&tlb, mm, vma, address, end, &nr_accounted, details);
1492         tlb_finish_mmu(tlb, address, end);
1493 @@ -927,6 +929,7 @@ int zeromap_page_range(struct vm_area_st
1494                 BUG();
1495  
1496         spin_lock(&mm->page_table_lock);
1497 +       ioproc_invalidate_range(vma, beg, end);
1498         do {
1499                 pmd_t *pmd = pmd_alloc(mm, dir, address);
1500                 error = -ENOMEM;
1501 @@ -941,6 +944,7 @@ int zeromap_page_range(struct vm_area_st
1502         /*
1503          * Why flush? zeromap_pte_range has a BUG_ON for !pte_none()
1504          */
1505 +       ioproc_update_range(vma, beg, end);
1506         flush_tlb_range(vma, beg, end);
1507         spin_unlock(&mm->page_table_lock);
1508         return error;
1509 @@ -1011,6 +1015,7 @@ int remap_page_range(struct vm_area_stru
1510                 BUG();
1511  
1512         spin_lock(&mm->page_table_lock);
1513 +       ioproc_invalidate_range(vma, beg, end);
1514         do {
1515                 pmd_t *pmd = pmd_alloc(mm, dir, from);
1516                 error = -ENOMEM;
1517 @@ -1025,6 +1030,7 @@ int remap_page_range(struct vm_area_stru
1518         /*
1519          * Why flush? remap_pte_range has a BUG_ON for !pte_none()
1520          */
1521 +       ioproc_update_range(vma, beg, end);
1522         flush_tlb_range(vma, beg, end);
1523         spin_unlock(&mm->page_table_lock);
1524         return error;
1525 @@ -1098,6 +1104,7 @@ static int do_wp_page(struct mm_struct *
1526                         update_mmu_cache(vma, address, entry);
1527                         lazy_mmu_prot_update(entry);
1528                         pte_unmap(page_table);
1529 +                       ioproc_update_page(vma, address);
1530                         spin_unlock(&mm->page_table_lock);
1531                         return VM_FAULT_MINOR;
1532                 }
1533 @@ -1133,6 +1140,7 @@ static int do_wp_page(struct mm_struct *
1534                 }
1535  
1536                 page_remove_rmap(old_page);
1537 +               ioproc_invalidate_page(vma, address);
1538                 break_cow(vma, new_page, address, page_table);
1539                 page_add_rmap(new_page, vma, address, 1);
1540                 lru_cache_add_active(new_page);
1541 @@ -1141,6 +1149,7 @@ static int do_wp_page(struct mm_struct *
1542                 new_page = old_page;
1543         }
1544         pte_unmap(page_table);
1545 +       ioproc_update_page(vma, address);
1546         page_cache_release(new_page);
1547         page_cache_release(old_page);
1548         spin_unlock(&mm->page_table_lock);
1549 @@ -1376,6 +1385,7 @@ static int do_swap_page(struct mm_struct
1550         int ret;
1551  
1552         pte_unmap(page_table);
1553 +       ioproc_update_page(vma, address);
1554         spin_unlock(&mm->page_table_lock);
1555  
1556         BUG_ON(!vma->anon_vma);
1557 @@ -1508,6 +1518,7 @@ do_anonymous_page(struct mm_struct *mm, 
1558  
1559         /* No need to invalidate - it was non-present before */
1560         update_mmu_cache(vma, addr, entry);
1561 +       ioproc_update_page(vma, addr);
1562         lazy_mmu_prot_update(entry);
1563         spin_unlock(&mm->page_table_lock);
1564         ret = VM_FAULT_MINOR;
1565 @@ -1658,6 +1669,7 @@ retry:
1566  
1567         /* no need to invalidate: a not-present page shouldn't be cached */
1568         update_mmu_cache(vma, address, entry);
1569 +       ioproc_update_page(vma, address);
1570         lazy_mmu_prot_update(entry);
1571         spin_unlock(&mm->page_table_lock);
1572   out:
1573 @@ -1771,6 +1783,7 @@ static inline int handle_pte_fault(struc
1574         spin_unlock(&mm->page_table_lock);
1575         return VM_FAULT_MINOR;
1576  }
1577 +EXPORT_SYMBOL_GPL(make_pages_present);
1578  
1579  
1580  /* Can be overwritten by the architecture */
1581 Index: LINUX-SRC-TREE/mm/mmap.c
1582 ===================================================================
1583 --- LINUX-SRC-TREE.orig/mm/mmap.c
1584 +++ LINUX-SRC-TREE/mm/mmap.c
1585 @@ -25,6 +25,7 @@
1586  #include <linux/init.h>
1587  #include <linux/file.h>
1588  #include <linux/fs.h>
1589 +#include <linux/ioproc.h>
1590  #include <linux/personality.h>
1591  #include <linux/security.h>
1592  #include <linux/hugetlb.h>
1593 @@ -1389,6 +1390,7 @@ static void unmap_region(struct mm_struc
1594         unsigned long nr_accounted = 0;
1595  
1596         lru_add_drain();
1597 +       ioproc_invalidate_range(vma, start, end);
1598         tlb = tlb_gather_mmu(mm, 0);
1599         unmap_vmas(&tlb, mm, vma, start, end, &nr_accounted, NULL);
1600         vm_unacct_memory(nr_accounted);
1601 @@ -1713,6 +1715,7 @@ void exit_mmap(struct mm_struct *mm)
1602  
1603         spin_lock(&mm->page_table_lock);
1604  
1605 +       ioproc_release(mm);
1606         tlb = tlb_gather_mmu(mm, 1);
1607         flush_cache_mm(mm);
1608         /* Use ~0UL here to ensure all VMAs in the mm are unmapped */
1609 Index: LINUX-SRC-TREE/mm/mprotect.c
1610 ===================================================================
1611 --- LINUX-SRC-TREE.orig/mm/mprotect.c
1612 +++ LINUX-SRC-TREE/mm/mprotect.c
1613 @@ -10,6 +10,7 @@
1614  
1615  #include <linux/mm.h>
1616  #include <linux/hugetlb.h>
1617 +#include <linux/ioproc.h>
1618  #include <linux/slab.h>
1619  #include <linux/shm.h>
1620  #include <linux/mman.h>
1621 @@ -101,6 +102,7 @@ change_protection(struct vm_area_struct 
1622         if (start >= end)
1623                 BUG();
1624         spin_lock(&current->mm->page_table_lock);
1625 +       ioproc_change_protection(vma, start, end, newprot);
1626         do {
1627                 change_pmd_range(dir, start, end - start, newprot);
1628                 start = (start + PGDIR_SIZE) & PGDIR_MASK;
1629 Index: LINUX-SRC-TREE/mm/mremap.c
1630 ===================================================================
1631 --- LINUX-SRC-TREE.orig/mm/mremap.c
1632 +++ LINUX-SRC-TREE/mm/mremap.c
1633 @@ -9,6 +9,7 @@
1634  
1635  #include <linux/mm.h>
1636  #include <linux/hugetlb.h>
1637 +#include <linux/ioproc.h>
1638  #include <linux/slab.h>
1639  #include <linux/shm.h>
1640  #include <linux/mman.h>
1641 @@ -144,6 +145,8 @@ static int move_page_tables(struct vm_ar
1642  {
1643         unsigned long offset = len;
1644  
1645 +       ioproc_invalidate_range(vma, old_addr, old_addr + len);
1646 +       ioproc_invalidate_range(vma, new_addr, new_addr + len);
1647         flush_cache_range(vma, old_addr, old_addr + len);
1648  
1649         /*
1650 Index: LINUX-SRC-TREE/mm/msync.c
1651 ===================================================================
1652 --- LINUX-SRC-TREE.orig/mm/msync.c
1653 +++ LINUX-SRC-TREE/mm/msync.c
1654 @@ -12,6 +12,7 @@
1655  #include <linux/mm.h>
1656  #include <linux/mman.h>
1657  #include <linux/hugetlb.h>
1658 +#include <linux/ioproc.h>
1659  
1660  #include <asm/pgtable.h>
1661  #include <asm/pgalloc.h>
1662 @@ -116,6 +117,7 @@ static int filemap_sync(struct vm_area_s
1663  
1664         if (address >= end)
1665                 BUG();
1666 +       ioproc_sync_range(vma, address, end);
1667         do {
1668                 error |= filemap_sync_pmd_range(dir, address, end, vma, flags);
1669                 address = (address + PGDIR_SIZE) & PGDIR_MASK;
1670 Index: LINUX-SRC-TREE/mm/objrmap.c
1671 ===================================================================
1672 --- LINUX-SRC-TREE.orig/mm/objrmap.c
1673 +++ LINUX-SRC-TREE/mm/objrmap.c
1674 @@ -29,6 +29,7 @@
1675  #include <linux/swapops.h>
1676  #include <linux/objrmap.h>
1677  #include <linux/init.h>
1678 +#include <linux/ioproc.h>
1679  #include <asm/tlbflush.h>
1680  
1681  kmem_cache_t * anon_vma_cachep;
1682 @@ -393,6 +394,8 @@ unmap_pte_page(struct page * page, struc
1683  {
1684         pte_t pteval;
1685  
1686 +       ioproc_invalidate_page(vma, address);
1687 +
1688         flush_cache_page(vma, address);
1689         pteval = ptep_clear_flush(vma, address, pte);
1690