Re: [Myrinet] kernel panic initiated by gm driver version 1.5.2

Susan Blackford <[email protected]>
Newsgroups gmane.network.myrinet.general
Organization Myricom, Inc.
Message-ID <0206251205290A.00536@idefix>
Hi,

On Tuesday 25 June 2002 08:53 am, you wrote:
> When running a user program the system went into a kernel
> hung state after issuing the following messages:
>
> kernel: GM: PANIC:
> libgm/_gm_assertion_failed.c:27:_gm_assertion_failed():kernel
> kernel: GM: drivers/linux/gm/gm_arch_fork.c:126: failed assertion:
> "!pmd_none (*src_pmd) && !pmd_bad (*src_pmd)".
> kernel: Kernel panic: gm_arch_abort() called
>
> Our system is running Linux kernel version 2.4.17.

This is a bug related to the recently introduced fork() support 
in gm-1.5.2, and unfortunately passed through our tests.  This
bug affects only the driver, so you should apply the
patch, recompile the driver, and reload the gm module.

This patch will be available on the Linux Download page, and will 
be included in the next release of GM.

Attached is the patch and the analysis from the developer.

 (cd <gmsrcdir>;patch -p1 < .../fork4.diff)

When creating a new mapping that just perfectly fits the hole between two
previous mapping, Linux merge the two old areas and the new one into one
into just one chunk, and although the original right area is removed (its
range now being part of the big reunited chunk), Linux never calls the
->close method on it, which causes the GM driver to lose track of the areas
on which it has registered hooks.

The reason Linux does not care to call the close method is because areas
susceptible to be merged are anonymous and normally never have a "->close"
method anyway, but this is no longer the case with the GM driver where we
use the vm_area open and close method for fork() support, (and they are
actually generally called in all other creation/destruction cases), there is
just this weird corner case that I hadn't noticed before :-(.

The fix is to make any vm area with registered page "non-mergeable" (see
can_vma_merge in include/linux/mm.h), by attaching them to a pseudo file.
Using the vm_file attribute. We have the shmem_file_setup function starting
with 2.4.4 that can be used to creates the dumb file used for this purpose
(and there is no problem for earlier 2.4 kernels where no vm merge is ever
done, 2.2 kernels always call the vm_area->open/close method before
creating/destroying them). 

We increase the dependence on Linux internals when we have to
insert/deinsert the vm areas from the mapping list attached to the
pseudo-inode of the pseudo-file, but all 2.4 kernels(included redhat or
other variant) seems to use exactly the same simple linked list for this
purpose.

We apologize for the inconvenience.  Please confirm with us that this
patch solves your problem.

Susan

-- 

------------------------------------------
Susan Blackford
Member of Technical Staff
Myricom Inc.
------------------------------------------
fork4.diff (text/plain, 35.8 KB)
Index: gm/configure
diff -u gm/configure:1.279 gm/configure:1.279.14.1
--- gm/configure:1.279	Tue May 28 16:27:20 2002
+++ gm/configure	Fri Jun 21 05:57:14 2002
@@ -1914,8 +1914,48 @@
 fi
 done
 
+    for ac_hdr in asm/rmap.h
+do
+ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
+echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
+echo "configure:1922: checking for $ac_hdr" >&5
+if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftest.$ac_ext <<EOF
+#line 1927 "configure"
+#include "confdefs.h"
+#include <$ac_hdr>
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:1932: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+  rm -rf conftest*
+  eval "ac_cv_header_$ac_safe=yes"
+else
+  echo "$ac_err" >&5
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  eval "ac_cv_header_$ac_safe=no"
+fi
+rm -f conftest*
+fi
+if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
+  echo "$ac_t""yes" 1>&6
+    ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'`
+  cat >> confdefs.h <<EOF
+#define $ac_tr_hdr 1
+EOF
+ 
+else
+  echo "$ac_t""no" 1>&6
+fi
+done
+
     cat > conftest.$ac_ext <<EOF
-#line 1919 "configure"
+#line 1959 "configure"
 #include "confdefs.h"
 #include <linux/autoconf.h>
              #ifdef CONFIG_SMP
@@ -1930,7 +1970,7 @@
 rm -f conftest*
 
     cat > conftest.$ac_ext <<EOF
-#line 1934 "configure"
+#line 1974 "configure"
 #include "confdefs.h"
 #include <linux/autoconf.h>
              #ifdef CONFIG_MODVERSIONS
@@ -2893,7 +2933,7 @@
 
 
 echo $ac_n "checking whether ${MAKE-make} sets \${MAKE}""... $ac_c" 1>&6
-echo "configure:2897: checking whether ${MAKE-make} sets \${MAKE}" >&5
+echo "configure:2937: checking whether ${MAKE-make} sets \${MAKE}" >&5
 set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y%./+-%__p_%'`
 if eval "test \"`echo '$''{'ac_cv_prog_make_${ac_make}_set'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
@@ -2923,7 +2963,7 @@
 # Extract the first word of "ar", so it can be a program name with args.
 set dummy ar; ac_word=$2
 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:2927: checking for $ac_word" >&5
+echo "configure:2967: checking for $ac_word" >&5
 if eval "test \"`echo '$''{'ac_cv_path_AR'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -2959,7 +2999,7 @@
 # Extract the first word of "basename", so it can be a program name with args.
 set dummy basename; ac_word=$2
 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:2963: checking for $ac_word" >&5
+echo "configure:3003: checking for $ac_word" >&5
 if eval "test \"`echo '$''{'ac_cv_path_BASENAME'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -2995,7 +3035,7 @@
 # Extract the first word of "cat", so it can be a program name with args.
 set dummy cat; ac_word=$2
 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:2999: checking for $ac_word" >&5
+echo "configure:3039: checking for $ac_word" >&5
 if eval "test \"`echo '$''{'ac_cv_path_CAT'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -3031,7 +3071,7 @@
 # Extract the first word of "chmod", so it can be a program name with args.
 set dummy chmod; ac_word=$2
 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:3035: checking for $ac_word" >&5
+echo "configure:3075: checking for $ac_word" >&5
 if eval "test \"`echo '$''{'ac_cv_path_CHMOD'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -3067,7 +3107,7 @@
 # Extract the first word of "ctags", so it can be a program name with args.
 set dummy ctags; ac_word=$2
 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:3071: checking for $ac_word" >&5
+echo "configure:3111: checking for $ac_word" >&5
 if eval "test \"`echo '$''{'ac_cv_path_CTAGS'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -3103,7 +3143,7 @@
 # Extract the first word of "distill", so it can be a program name with args.
 set dummy distill; ac_word=$2
 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:3107: checking for $ac_word" >&5
+echo "configure:3147: checking for $ac_word" >&5
 if eval "test \"`echo '$''{'ac_cv_path_DISTILL'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -3139,7 +3179,7 @@
 # Extract the first word of "dvips", so it can be a program name with args.
 set dummy dvips; ac_word=$2
 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:3143: checking for $ac_word" >&5
+echo "configure:3183: checking for $ac_word" >&5
 if eval "test \"`echo '$''{'ac_cv_path_DVIPS'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -3175,7 +3215,7 @@
 # Extract the first word of "echo", so it can be a program name with args.
 set dummy echo; ac_word=$2
 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:3179: checking for $ac_word" >&5
+echo "configure:3219: checking for $ac_word" >&5
 if eval "test \"`echo '$''{'ac_cv_path_ECHO'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -3211,7 +3251,7 @@
 # Extract the first word of "etags", so it can be a program name with args.
 set dummy etags; ac_word=$2
 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:3215: checking for $ac_word" >&5
+echo "configure:3255: checking for $ac_word" >&5
 if eval "test \"`echo '$''{'ac_cv_path_ETAGS'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -3247,7 +3287,7 @@
 # Extract the first word of "gendat", so it can be a program name with args.
 set dummy gendat; ac_word=$2
 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:3251: checking for $ac_word" >&5
+echo "configure:3291: checking for $ac_word" >&5
 if eval "test \"`echo '$''{'ac_cv_path_GENDAT'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -3283,7 +3323,7 @@
 # Extract the first word of "gs", so it can be a program name with args.
 set dummy gs; ac_word=$2
 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:3287: checking for $ac_word" >&5
+echo "configure:3327: checking for $ac_word" >&5
 if eval "test \"`echo '$''{'ac_cv_path_GS'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -3328,7 +3368,7 @@
 # SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
 # ./install, which can be erroneously created by make from ./install.sh.
 echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6
-echo "configure:3332: checking for a BSD compatible install" >&5
+echo "configure:3372: checking for a BSD compatible install" >&5
 if test -z "$INSTALL"; then
 if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
@@ -3383,7 +3423,7 @@
 # Extract the first word of "install-info", so it can be a program name with args.
 set dummy install-info; ac_word=$2
 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:3387: checking for $ac_word" >&5
+echo "configure:3427: checking for $ac_word" >&5
 if eval "test \"`echo '$''{'ac_cv_path_INSTALL_INFO'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -3419,7 +3459,7 @@
 # Extract the first word of "lanai-gcc", so it can be a program name with args.
 set dummy lanai-gcc; ac_word=$2
 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:3423: checking for $ac_word" >&5
+echo "configure:3463: checking for $ac_word" >&5
 if eval "test \"`echo '$''{'ac_cv_path_LANAI_GCC'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -3455,7 +3495,7 @@
 # Extract the first word of "lanai-ar", so it can be a program name with args.
 set dummy lanai-ar; ac_word=$2
 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:3459: checking for $ac_word" >&5
+echo "configure:3499: checking for $ac_word" >&5
 if eval "test \"`echo '$''{'ac_cv_path_LANAI_AR'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -3491,7 +3531,7 @@
 # Extract the first word of "ld", so it can be a program name with args.
 set dummy ld; ac_word=$2
 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:3495: checking for $ac_word" >&5
+echo "configure:3535: checking for $ac_word" >&5
 if eval "test \"`echo '$''{'ac_cv_path_LD'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -3525,7 +3565,7 @@
 fi
 
 echo $ac_n "checking whether ln -s works""... $ac_c" 1>&6
-echo "configure:3529: checking whether ln -s works" >&5
+echo "configure:3569: checking whether ln -s works" >&5
 if eval "test \"`echo '$''{'ac_cv_prog_LN_S'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -3548,7 +3588,7 @@
 # Extract the first word of "makeinfo", so it can be a program name with args.
 set dummy makeinfo; ac_word=$2
 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:3552: checking for $ac_word" >&5
+echo "configure:3592: checking for $ac_word" >&5
 if eval "test \"`echo '$''{'ac_cv_path_MAKEINFO'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -3584,7 +3624,7 @@
 # Extract the first word of "psrev", so it can be a program name with args.
 set dummy psrev; ac_word=$2
 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:3588: checking for $ac_word" >&5
+echo "configure:3628: checking for $ac_word" >&5
 if eval "test \"`echo '$''{'ac_cv_path_PSREV'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -3620,7 +3660,7 @@
 # Extract the first word of "ranlib", so it can be a program name with args.
 set dummy ranlib; ac_word=$2
 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:3624: checking for $ac_word" >&5
+echo "configure:3664: checking for $ac_word" >&5
 if eval "test \"`echo '$''{'ac_cv_prog_RANLIB'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -3650,7 +3690,7 @@
 # Extract the first word of "strip", so it can be a program name with args.
 set dummy strip; ac_word=$2
 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:3654: checking for $ac_word" >&5
+echo "configure:3694: checking for $ac_word" >&5
 if eval "test \"`echo '$''{'ac_cv_path_STRIP'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -3686,7 +3726,7 @@
 # Extract the first word of "texi2dvi", so it can be a program name with args.
 set dummy texi2dvi; ac_word=$2
 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:3690: checking for $ac_word" >&5
+echo "configure:3730: checking for $ac_word" >&5
 if eval "test \"`echo '$''{'ac_cv_path_TEXI2DVI'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -3722,7 +3762,7 @@
 # Extract the first word of "texi2html", so it can be a program name with args.
 set dummy texi2html; ac_word=$2
 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:3726: checking for $ac_word" >&5
+echo "configure:3766: checking for $ac_word" >&5
 if eval "test \"`echo '$''{'ac_cv_path_TEXI2HTML'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -3786,12 +3826,12 @@
 
 
 echo $ac_n "checking for ANSI C header files""... $ac_c" 1>&6
-echo "configure:3790: checking for ANSI C header files" >&5
+echo "configure:3830: checking for ANSI C header files" >&5
 if eval "test \"`echo '$''{'ac_cv_header_stdc'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 3795 "configure"
+#line 3835 "configure"
 #include "confdefs.h"
 #include <stdlib.h>
 #include <stdarg.h>
@@ -3799,7 +3839,7 @@
 #include <float.h>
 EOF
 ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:3803: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:3843: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
 ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
 if test -z "$ac_err"; then
   rm -rf conftest*
@@ -3816,7 +3856,7 @@
 if test $ac_cv_header_stdc = yes; then
   # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
 cat > conftest.$ac_ext <<EOF
-#line 3820 "configure"
+#line 3860 "configure"
 #include "confdefs.h"
 #include <string.h>
 EOF
@@ -3834,7 +3874,7 @@
 if test $ac_cv_header_stdc = yes; then
   # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
 cat > conftest.$ac_ext <<EOF
-#line 3838 "configure"
+#line 3878 "configure"
 #include "confdefs.h"
 #include <stdlib.h>
 EOF
@@ -3855,7 +3895,7 @@
   :
 else
   cat > conftest.$ac_ext <<EOF
-#line 3859 "configure"
+#line 3899 "configure"
 #include "confdefs.h"
 #include <ctype.h>
 #define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
@@ -3866,7 +3906,7 @@
 exit (0); }
 
 EOF
-if { (eval echo configure:3870: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:3910: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
 then
   :
 else
@@ -3893,17 +3933,17 @@
 do
 ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
 echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
-echo "configure:3897: checking for $ac_hdr" >&5
+echo "configure:3937: checking for $ac_hdr" >&5
 if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 3902 "configure"
+#line 3942 "configure"
 #include "confdefs.h"
 #include <$ac_hdr>
 EOF
 ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:3907: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:3947: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
 ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
 if test -z "$ac_err"; then
   rm -rf conftest*
@@ -3931,12 +3971,12 @@
 
 
 echo $ac_n "checking for working const""... $ac_c" 1>&6
-echo "configure:3935: checking for working const" >&5
+echo "configure:3975: checking for working const" >&5
 if eval "test \"`echo '$''{'ac_cv_c_const'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 3940 "configure"
+#line 3980 "configure"
 #include "confdefs.h"
 
 int main() {
@@ -3985,7 +4025,7 @@
 
 ; return 0; }
 EOF
-if { (eval echo configure:3989: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:4029: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   ac_cv_c_const=yes
 else
@@ -4006,21 +4046,21 @@
 fi
 
 echo $ac_n "checking for inline""... $ac_c" 1>&6
-echo "configure:4010: checking for inline" >&5
+echo "configure:4050: checking for inline" >&5
 if eval "test \"`echo '$''{'ac_cv_c_inline'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   ac_cv_c_inline=no
 for ac_kw in inline __inline__ __inline; do
   cat > conftest.$ac_ext <<EOF
-#line 4017 "configure"
+#line 4057 "configure"
 #include "confdefs.h"
 
 int main() {
 } int $ac_kw foo() {
 ; return 0; }
 EOF
-if { (eval echo configure:4024: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:4064: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   ac_cv_c_inline=$ac_kw; break
 else
@@ -4046,12 +4086,12 @@
 esac
 
 echo $ac_n "checking for off_t""... $ac_c" 1>&6
-echo "configure:4050: checking for off_t" >&5
+echo "configure:4090: checking for off_t" >&5
 if eval "test \"`echo '$''{'ac_cv_type_off_t'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 4055 "configure"
+#line 4095 "configure"
 #include "confdefs.h"
 #include <sys/types.h>
 #if STDC_HEADERS
@@ -4079,12 +4119,12 @@
 fi
 
 echo $ac_n "checking for size_t""... $ac_c" 1>&6
-echo "configure:4083: checking for size_t" >&5
+echo "configure:4123: checking for size_t" >&5
 if eval "test \"`echo '$''{'ac_cv_type_size_t'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 4088 "configure"
+#line 4128 "configure"
 #include "confdefs.h"
 #include <sys/types.h>
 #if STDC_HEADERS
@@ -4112,12 +4152,12 @@
 fi
 
 echo $ac_n "checking for uid_t in sys/types.h""... $ac_c" 1>&6
-echo "configure:4116: checking for uid_t in sys/types.h" >&5
+echo "configure:4156: checking for uid_t in sys/types.h" >&5
 if eval "test \"`echo '$''{'ac_cv_type_uid_t'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 4121 "configure"
+#line 4161 "configure"
 #include "confdefs.h"
 #include <sys/types.h>
 EOF
@@ -4148,13 +4188,13 @@
 
 if test $ac_cv_prog_gcc = yes; then
     echo $ac_n "checking whether ${CC-cc} needs -traditional""... $ac_c" 1>&6
-echo "configure:4152: checking whether ${CC-cc} needs -traditional" >&5
+echo "configure:4192: checking whether ${CC-cc} needs -traditional" >&5
 if eval "test \"`echo '$''{'ac_cv_prog_gcc_traditional'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
     ac_pattern="Autoconf.*'x'"
   cat > conftest.$ac_ext <<EOF
-#line 4158 "configure"
+#line 4198 "configure"
 #include "confdefs.h"
 #include <sgtty.h>
 Autoconf TIOCGETP
@@ -4172,7 +4212,7 @@
 
   if test $ac_cv_prog_gcc_traditional = no; then
     cat > conftest.$ac_ext <<EOF
-#line 4176 "configure"
+#line 4216 "configure"
 #include "confdefs.h"
 #include <termio.h>
 Autoconf TCGETA
@@ -4197,17 +4237,17 @@
 do
 ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
 echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
-echo "configure:4201: checking for $ac_hdr" >&5
+echo "configure:4241: checking for $ac_hdr" >&5
 if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 4206 "configure"
+#line 4246 "configure"
 #include "confdefs.h"
 #include <$ac_hdr>
 EOF
 ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:4211: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:4251: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
 ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
 if test -z "$ac_err"; then
   rm -rf conftest*
@@ -4236,12 +4276,12 @@
 for ac_func in getpagesize
 do
 echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
-echo "configure:4240: checking for $ac_func" >&5
+echo "configure:4280: checking for $ac_func" >&5
 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 4245 "configure"
+#line 4285 "configure"
 #include "confdefs.h"
 /* System header to define __stub macros and hopefully few prototypes,
     which can conflict with char $ac_func(); below.  */
@@ -4264,7 +4304,7 @@
 
 ; return 0; }
 EOF
-if { (eval echo configure:4268: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:4308: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_func_$ac_func=yes"
 else
@@ -4289,7 +4329,7 @@
 done
 
 echo $ac_n "checking for working mmap""... $ac_c" 1>&6
-echo "configure:4293: checking for working mmap" >&5
+echo "configure:4333: checking for working mmap" >&5
 if eval "test \"`echo '$''{'ac_cv_func_mmap_fixed_mapped'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -4297,7 +4337,7 @@
   ac_cv_func_mmap_fixed_mapped=no
 else
   cat > conftest.$ac_ext <<EOF
-#line 4301 "configure"
+#line 4341 "configure"
 #include "confdefs.h"
 
 /* Thanks to Mike Haertel and Jim Avera for this test.
@@ -4440,7 +4480,7 @@
 }
 
 EOF
-if { (eval echo configure:4444: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:4484: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
 then
   ac_cv_func_mmap_fixed_mapped=yes
 else
@@ -4463,12 +4503,12 @@
 fi
 
 echo $ac_n "checking return type of signal handlers""... $ac_c" 1>&6
-echo "configure:4467: checking return type of signal handlers" >&5
+echo "configure:4507: checking return type of signal handlers" >&5
 if eval "test \"`echo '$''{'ac_cv_type_signal'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 4472 "configure"
+#line 4512 "configure"
 #include "confdefs.h"
 #include <sys/types.h>
 #include <signal.h>
@@ -4485,7 +4525,7 @@
 int i;
 ; return 0; }
 EOF
-if { (eval echo configure:4489: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:4529: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   ac_cv_type_signal=void
 else
@@ -4506,12 +4546,12 @@
 for ac_func in memalign atexit on_exit
 do
 echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
-echo "configure:4510: checking for $ac_func" >&5
+echo "configure:4550: checking for $ac_func" >&5
 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 4515 "configure"
+#line 4555 "configure"
 #include "confdefs.h"
 /* System header to define __stub macros and hopefully few prototypes,
     which can conflict with char $ac_func(); below.  */
@@ -4534,7 +4574,7 @@
 
 ; return 0; }
 EOF
-if { (eval echo configure:4538: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:4578: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_func_$ac_func=yes"
 else
@@ -4564,7 +4604,7 @@
 	# Checks for libraries.
 	# Replace `main' with a function in -lgcc:
 	echo $ac_n "checking for main in -lgcc""... $ac_c" 1>&6
-echo "configure:4568: checking for main in -lgcc" >&5
+echo "configure:4608: checking for main in -lgcc" >&5
 ac_lib_var=`echo gcc'_'main | sed 'y%./+-%__p_%'`
 if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
@@ -4572,14 +4612,14 @@
   ac_save_LIBS="$LIBS"
 LIBS="-lgcc  $LIBS"
 cat > conftest.$ac_ext <<EOF
-#line 4576 "configure"
+#line 4616 "configure"
 #include "confdefs.h"
 
 int main() {
 main()
 ; return 0; }
 EOF
-if { (eval echo configure:4583: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:4623: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_lib_$ac_lib_var=yes"
 else
@@ -4607,14 +4647,14 @@
 fi
 
 	echo $ac_n "checking whether byte ordering is bigendian""... $ac_c" 1>&6
-echo "configure:4611: checking whether byte ordering is bigendian" >&5
+echo "configure:4651: checking whether byte ordering is bigendian" >&5
 if eval "test \"`echo '$''{'ac_cv_c_bigendian'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   ac_cv_c_bigendian=unknown
 # See if sys/param.h defines the BYTE_ORDER macro.
 cat > conftest.$ac_ext <<EOF
-#line 4618 "configure"
+#line 4658 "configure"
 #include "confdefs.h"
 #include <sys/types.h>
 #include <sys/param.h>
@@ -4625,11 +4665,11 @@
 #endif
 ; return 0; }
 EOF
-if { (eval echo configure:4629: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:4669: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   # It does; now see whether it defined to BIG_ENDIAN or not.
 cat > conftest.$ac_ext <<EOF
-#line 4633 "configure"
+#line 4673 "configure"
 #include "confdefs.h"
 #include <sys/types.h>
 #include <sys/param.h>
@@ -4640,7 +4680,7 @@
 #endif
 ; return 0; }
 EOF
-if { (eval echo configure:4644: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:4684: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   ac_cv_c_bigendian=yes
 else
@@ -4660,7 +4700,7 @@
     { echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; }
 else
   cat > conftest.$ac_ext <<EOF
-#line 4664 "configure"
+#line 4704 "configure"
 #include "confdefs.h"
 main () {
   /* Are we little or big endian?  From Harbison&Steele.  */
@@ -4673,7 +4713,7 @@
   exit (u.c[sizeof (long) - 1] == 1);
 }
 EOF
-if { (eval echo configure:4677: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:4717: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
 then
   ac_cv_c_bigendian=no
 else
Index: gm/configure.in
diff -u gm/configure.in:1.271 gm/configure.in:1.271.32.1
--- gm/configure.in:1.271	Tue Apr  9 08:18:24 2002
+++ gm/configure.in	Fri Jun 21 05:57:18 2002
@@ -441,6 +441,7 @@
     oldflags="$CPPFLAGS"
     CPPFLAGS="-nostdinc -I$LINUX_KERSRC/include"
     AC_CHECK_HEADERS(linux/compile.h)
+    AC_CHECK_HEADERS(asm/rmap.h)
     AC_EGREP_CPP(config_smp, 
 	    [#include <linux/autoconf.h>
              #ifdef CONFIG_SMP
Index: gm/drivers/linux/gm/gm_arch.c
diff -u gm/drivers/linux/gm/gm_arch.c:1.291 gm/drivers/linux/gm/gm_arch.c:1.291.8.3
--- gm/drivers/linux/gm/gm_arch.c:1.291	Tue Jun  4 06:41:27 2002
+++ gm/drivers/linux/gm/gm_arch.c	Tue Jun 25 05:35:09 2002
@@ -57,6 +57,7 @@
 #include <linux/interrupt.h>
 #include <linux/slab.h>
 #include <linux/module.h>
+#include <linux/file.h>
 
 #if GM_SUPPORT_PCI
 #include <linux/pci.h>
@@ -258,6 +259,12 @@
 				      gm_hash_hash_ptr,
 				      0, 0,
 				      3, 0);
+#if LINUX_VERSION_CODE >= VERSION_CODE(2,4,4)
+  /* shmem_file_setup is only available after 2.4.4
+     as vm merging is not done between 2.4.0 and 2.4.9
+     that is not a problem */
+  ps->arch.file = shmem_file_setup ("gm-reg-file", 0);
+#endif
   return ps->arch.ops_hash ? GM_SUCCESS : GM_FAILURE;
 }
 
@@ -271,6 +278,13 @@
   GM_PARAMETER_MAY_BE_UNUSED (ps);
   gm_assert(ps->arch.ops_count == 0);
   gm_destroy_hash(ps->arch.ops_hash);
+#if LINUX_XX >= 24
+  if (ps->arch.file)
+    {
+      gm_assert (atomic_read (&ps->arch.file->f_count) == 1);
+      fput (ps->arch.file);
+    }
+#endif
   return;
 }
 
@@ -3150,6 +3164,11 @@
   init_MUTEX (&gm_linux_open_mutex);
   spin_lock_init (&gm_linux_intr_lock);
 
+  gm_linux_get_user_pages = (int (*)())gm_linux_symbol("get_user_pages");
+  if (!gm_linux_get_user_pages)
+    {
+      GM_INFO (("kernel does not export get_user_pages\n"));
+    }
 #if GM_SUPPORT_PCI
   if (pci_module_init (&gm_driver) != 0)
     {
Index: gm/drivers/linux/gm/gm_arch_def.h
diff -u gm/drivers/linux/gm/gm_arch_def.h:1.34 gm/drivers/linux/gm/gm_arch_def.h:1.34.18.1
--- gm/drivers/linux/gm/gm_arch_def.h:1.34	Thu May 23 10:22:31 2002
+++ gm/drivers/linux/gm/gm_arch_def.h	Fri Jun 21 05:57:20 2002
@@ -239,4 +239,8 @@
 
 extern spinlock_t gm_linux_intr_lock;
 extern struct gm_hash *gm_linux_pfn_hash;
+int (*gm_linux_get_user_pages)(struct task_struct *tsk, struct mm_struct *mm,
+			       unsigned long start, int len, int write, int force,
+			       struct page **pages, struct vm_area_struct **vmas);
+
 #endif /* _gm_arch_def_h_ */
Index: gm/drivers/linux/gm/gm_arch_fork.c
diff -u gm/drivers/linux/gm/gm_arch_fork.c:1.6 gm/drivers/linux/gm/gm_arch_fork.c:1.6.8.2
--- gm/drivers/linux/gm/gm_arch_fork.c:1.6	Tue Jun  4 06:41:28 2002
+++ gm/drivers/linux/gm/gm_arch_fork.c	Fri Jun 21 05:57:20 2002
@@ -59,35 +59,61 @@
 		 atomic_read (&old_page->count)));
       return;
     }
-  new_page = alloc_page (GFP_HIGHUSER);
-
-  /* copy new_page */
-  new = kmap (new_page);
-  old = kmap (old_page);
+  if (!gm_linux_get_user_pages)
+    {
+#ifdef HAVE_ASM_RMAP_H
+      GM_WARN (("fork() not supported on this kernel when GM ports are open"));
+      return;
+#endif
+      new_page = alloc_page (GFP_HIGHUSER);
+      
+      /* copy new_page */
+      new = kmap (new_page);
+      old = kmap (old_page);
 #if GM_CPU_ia64 || GM_CPU_powerpc
-  memcpy(new,old,PAGE_SIZE);
+      memcpy(new,old,PAGE_SIZE);
 #else
-  copy_user_page (new, old, addr_base);
+      copy_user_page (new, old, addr_base);
 #endif
-  kunmap (old_page);
-  kunmap (new_page);
+      kunmap (old_page);
+      kunmap (new_page);
 #if !GM_CPU_powerpc
-  flush_page_to_ram (old_page);
-  flush_page_to_ram (new_page);
+      flush_page_to_ram (old_page);
+      flush_page_to_ram (new_page);
 #endif
-  flush_cache_page (vma, addr_base);
-  set_pte (dst_pte,
-	   pte_mkwrite (pte_mkdirty (mk_pte (new_page, vma->vm_page_prot))));
-  page_cache_release (old_page);	/* remove child reference */
-  /* put again original page in rw mode */
-  set_pte (src_pte, pte_mkwrite (*src_pte));
+      flush_cache_page (vma, addr_base);
+      set_pte (dst_pte,
+	       pte_mkwrite (pte_mkdirty (mk_pte (new_page, vma->vm_page_prot))));
+      page_cache_release (old_page);	/* remove child reference */
+      /* put again original page in rw mode */
+      set_pte (src_pte, pte_mkwrite (*src_pte));
 #if LINUX_XX >= 24 && !GM_CPU_ia64 && !GM_CPU_powerpc
-  /* we do not need this as we are in fork, we only modified the child tlb which has never
-     been active and there will be a flush_tlb_page before that happens,
-     we are in dup_mmap in the parent and there is a flush_tlb_mm at the end 
-     of this function */
-  flush_tlb_page (vma, addr_base);
+      /* we do not need this as we are in fork, we only modified the
+	 child tlb which has never been active and there will be a
+	 flush_tlb_page before that happens, we are in dup_mmap in the
+	 parent and there is a flush_tlb_mm at the end of this
+	 function */
+      flush_tlb_page (vma, addr_base);
 #endif
+    }
+  else /* fonction get_user_pages available */
+    {
+      int res;
+      vma->vm_mm->mmap_cache = vma;
+      res = (*gm_linux_get_user_pages) (current,vma->vm_mm, addr_base, 1, 
+					1, 0, &new_page, NULL);
+      gm_always_assert (res == 1);
+      gm_always_assert (new_page != old_page);
+      gm_always_assert (pte_present (*src_pte) && pte_present (*dst_pte) &&
+			!pte_write (*src_pte) && pte_write (*dst_pte) &&
+			l24_pte_page (*dst_pte) == new_page &&
+			l24_pte_page (*src_pte) == old_page);
+      /* page count should be: 1 in parent, 1 in child, 1 in page_hash */
+      gm_always_assert (atomic_read (&old_page->count) == 2);
+      gm_always_assert (atomic_read (&new_page->count) == 2);
+      page_cache_release (new_page);
+      set_pte (src_pte, pte_mkwrite (*src_pte));
+    }
 }
 
 void
@@ -109,8 +135,11 @@
       unsigned long pmd_end = pmd_off + vma->vm_end - addr;
       pmd_t *src_pmd, *dst_pmd;
       /* check  valid pgd entries */
-      gm_always_assert (!pgd_none (*src_pgd) && !pgd_bad (*src_pgd));
-      gm_always_assert (!pgd_none (*dst_pgd) && !pgd_bad (*dst_pgd));
+      if (pgd_none (*src_pgd) || pgd_bad (*src_pgd) ||
+          pgd_none (*dst_pgd) || pgd_bad (*dst_pgd))
+        {
+          goto continue_pgd_loop;
+        }
       src_pmd = pmd_offset (src_pgd, pmd_off);
       dst_pmd = pmd_offset (dst_pgd, pmd_off);
       if (pmd_end > PGDIR_SIZE)
@@ -123,8 +152,11 @@
 	  unsigned long pte_end = pte_off + pmd_end - pmd_off;
 	  pte_t *src_pte, *dst_pte;
 	  /* check valid pmd entries */
-	  gm_always_assert (!pmd_none (*src_pmd) && !pmd_bad (*src_pmd));
-	  gm_always_assert (!pmd_none (*dst_pmd) && !pmd_bad (*dst_pmd));
+	  if (pmd_none (*src_pmd) || pmd_bad (*src_pmd) ||
+              pmd_none (*dst_pmd) || pmd_bad (*dst_pmd))
+            {
+              goto continue_pmd_loop;
+            }
 	  src_pte = pte_offset (src_pmd, pte_off);
 	  dst_pte = pte_offset (dst_pmd, pte_off);
 	  if (pte_end > PMD_SIZE)
@@ -150,10 +182,12 @@
 		    }
 		}
 	    }			/* end pte loop */
+        continue_pmd_loop:
 	  pmd_off = (pmd_off + PMD_SIZE) & PMD_MASK;
 	  src_pmd++;
 	  dst_pmd++;
 	}			/* end pmd loop */
+    continue_pgd_loop:
       addr = (addr + PGDIR_SIZE) & PGDIR_MASK;
       src_pgd++;
       dst_pgd++;
Index: gm/drivers/linux/gm/gm_arch_linux.h
diff -u gm/drivers/linux/gm/gm_arch_linux.h:1.11 gm/drivers/linux/gm/gm_arch_linux.h:1.11.16.1
--- gm/drivers/linux/gm/gm_arch_linux.h:1.11	Fri May 31 16:34:56 2002
+++ gm/drivers/linux/gm/gm_arch_linux.h	Tue Jun 25 05:05:49 2002
@@ -137,8 +137,8 @@
   return 1;
 }
 
-
-
+#define up_mmap_sem(a)
+#define down_mmap_sem(a)
 
 #elif LINUX_24
 
Index: gm/drivers/linux/gm/gm_arch_types.h
diff -u gm/drivers/linux/gm/gm_arch_types.h:1.49 gm/drivers/linux/gm/gm_arch_types.h:1.49.8.1
--- gm/drivers/linux/gm/gm_arch_types.h:1.49	Tue Jun  4 06:41:28 2002
+++ gm/drivers/linux/gm/gm_arch_types.h	Tue Jun 25 05:05:49 2002
@@ -113,6 +113,7 @@
   struct gm_hash *ops_hash;
   int ops_count;
   struct mm_struct *mm;
+  struct file * file;
 }
 gm_arch_port_info_t;
 
Index: gm/drivers/linux/gm/gm_arch_vmops.c
diff -u gm/drivers/linux/gm/gm_arch_vmops.c:1.4 gm/drivers/linux/gm/gm_arch_vmops.c:1.4.8.1
--- gm/drivers/linux/gm/gm_arch_vmops.c:1.4	Tue Jun  4 06:41:28 2002
+++ gm/drivers/linux/gm/gm_arch_vmops.c	Tue Jun 25 05:05:49 2002
@@ -7,8 +7,27 @@
 #include "gm_internal.h"
 
 #include <linux/mm.h>
+#include <linux/file.h>
 
 static void
+gm_linux_detach_file (struct vm_area_struct *vma)
+{
+#if LINUX_XX >= 24
+  gm_linux_vm_ops_t *ops = (gm_linux_vm_ops_t *) vma->vm_ops;
+  struct gm_port_state * ps = ops->gm.ps;
+  if (vma->vm_file && vma->vm_file == ps->arch.file)
+    {
+      vma->vm_file = 0;
+      gm_assert (atomic_read (&ps->arch.file->f_count) > 1);
+      if (vma->vm_next_share)
+	vma->vm_next_share->vm_pprev_share = vma->vm_pprev_share;
+      *vma->vm_pprev_share = vma->vm_next_share;
+      fput(ps->arch.file);
+    }
+#endif
+}
+
+static void
 gm_linux_vm_open (struct vm_area_struct *vma)
 {
   gm_linux_vm_ops_t *ops = (gm_linux_vm_ops_t *) vma->vm_ops;
@@ -19,6 +38,9 @@
     {
       /* ok we are doing a fork, I do believe this is the only case
          where the equality does not hold in open */
+      /* the kernel has duplicated the vma
+	 and increased the reference of vm_file before calling us */
+      gm_linux_detach_file (vma);
       vma->vm_ops = ops->gm.ori;
       gm_linux_fork (vma);
     }
@@ -37,6 +59,7 @@
   gm_assert (ops->gm.refcount > 0);
 
   ops->gm.refcount -= 1;
+  gm_linux_detach_file (vma);
   vma->vm_ops = ops->gm.ori;
   if (!ops->gm.refcount)
     {
@@ -145,6 +168,27 @@
     return GM_OUT_OF_MEMORY;
   vma->vm_ops = &ops->wrap;
   ops->gm.refcount += 1;
+#if  LINUX_XX >= 24
+  /* prevent Linux anonymous vma merge operations (see can_vma_merge
+     in linux/mm.h)which unfortunately do not guarantee to call open
+     and close method on the object, to do that we transform the
+     anonymous vm_area into a file object */
+  if (!vma->vm_file && ps->arch.file)
+    {
+      struct inode * inode = ps->arch.file->f_dentry->d_inode;
+      struct address_space * mapping = inode->i_mapping;
+      struct vm_area_struct **head = &mapping->i_mmap;
+      
+      get_file (ps->arch.file);
+      vma->vm_file = ps->arch.file;
+      /* insert into the special inode mapping list */
+      vma->vm_next_share = *head;
+      if (*head)
+	(*head)->vm_pprev_share = &vma->vm_next_share;
+      *head = vma;
+      vma->vm_pprev_share = head;
+    }
+#endif
   return GM_SUCCESS;
 }
 
@@ -155,6 +199,7 @@
   if (ps->arch.ops_count == 0 || current->mm != ps->arch.mm)
     return;
   gm_always_assert (current->mm);
+  down_mmap_sem (&current->mm->mmap_sem);
   vma = current->mm->mmap;
   while (vma)
     {
@@ -175,4 +220,5 @@
       gm_assert (gm_hash_find (ps->arch.ops_hash, vma->vm_ops) == NULL);
       vma = vma->vm_next;
     }
+  up_mmap_sem (&current->mm->mmap_sem);
 }
Index: gm/include/gm_auto_config.h.in
diff -u gm/include/gm_auto_config.h.in:1.64 gm/include/gm_auto_config.h.in:1.64.34.1
--- gm/include/gm_auto_config.h.in:1.64	Tue Apr  9 08:18:30 2002
+++ gm/include/gm_auto_config.h.in	Fri Jun 21 05:57:21 2002
@@ -52,6 +52,9 @@
 /* Define if you have the on_exit function.  */
 #undef HAVE_ON_EXIT
 
+/* Define if you have the <asm/rmap.h> header file.  */
+#undef HAVE_ASM_RMAP_H
+
 /* Define if you have the <fcntl.h> header file.  */
 #undef HAVE_FCNTL_H
 
Index: gm/libgm/gm_fork_system.c
diff -u gm/libgm/gm_fork_system.c:1.21 gm/libgm/gm_fork_system.c:1.21.156.1
--- gm/libgm/gm_fork_system.c:1.21	Wed Oct  3 05:29:58 2001
+++ gm/libgm/gm_fork_system.c	Thu Jun 20 09:02:45 2002
@@ -83,7 +83,8 @@
 
 
 
-#if (GM_ENABLE_FORK_SYSTEM == 0)
+/* always use our custom system() for Linux to minimize fork() use */
+#if (GM_ENABLE_FORK_SYSTEM == 0) || GM_OS_LINUX
 int
 system (const char *cmd)
 {
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.