diff --git a/configure.in b/configure.in
index ed57fa0c72b9baea3fd806820258417a2cfd438e..a01d962e3eaa1bd5061e414b8e9ddd3ca2bf3682 100644
--- a/configure.in
+++ b/configure.in
@@ -1819,7 +1819,7 @@ AC_CHECK_FUNCS(alarm bcmp bfill bmove bzero chsize cuserid fchmod fcntl \
   getcwd gethostbyaddr_r gethostbyname_r getpass getpassphrase getpwnam \
   getpwuid getrlimit getrusage getwd gmtime_r index initgroups isnan \
   localtime_r locking longjmp lrand48 madvise mallinfo memcpy memmove \
-  mkstemp mlockall perror poll pread pthread_attr_create mmap getpagesize \
+  mkstemp mlockall perror poll pread pthread_attr_create mmap mmap64 getpagesize \
   pthread_attr_getstacksize pthread_attr_setprio pthread_attr_setschedparam \
   pthread_attr_setstacksize pthread_condattr_create pthread_getsequence_np \
   pthread_key_delete pthread_rwlock_rdlock pthread_setprio \
diff --git a/include/my_base.h b/include/my_base.h
index ebe1c6ab722e43e5827e23b6bfd5b51d24b75ab0..c688591e1d53a4a2a59b4800ece011e2eb7a5034 100644
--- a/include/my_base.h
+++ b/include/my_base.h
@@ -152,7 +152,8 @@ enum ha_extra_function {
     other fields intact. When this is off (by default) InnoDB will use memcpy
     to overwrite entire row.
   */
-  HA_EXTRA_KEYREAD_PRESERVE_FIELDS
+  HA_EXTRA_KEYREAD_PRESERVE_FIELDS,
+  HA_EXTRA_MMAP
 };
 
 	/* The following is parameter to ha_panic() */
diff --git a/include/my_sys.h b/include/my_sys.h
index 44fe383bf4f81f9e266353ae0c5bcd0b00f6d04e..cda308f222a1c41b2807092816a6b22b726bb55c 100644
--- a/include/my_sys.h
+++ b/include/my_sys.h
@@ -821,7 +821,11 @@ my_bool my_gethwaddr(uchar *to);
 #define MAP_NOSYNC      0
 #endif
 
+#ifdef HAVE_MMAP64
+#define my_mmap(a,b,c,d,e,f)    mmap64(a,b,c,d,e,f)
+#else
 #define my_mmap(a,b,c,d,e,f)    mmap(a,b,c,d,e,f)
+#endif
 #ifdef HAVE_GETPAGESIZE
 #define my_getpagesize()        getpagesize()
 #else
diff --git a/sql/ha_myisam.cc b/sql/ha_myisam.cc
index 02d814a94516877845d518bbd47e97937ec129c3..dfd8fb23cf4dec00c9b6eab803e167db1855f217 100644
--- a/sql/ha_myisam.cc
+++ b/sql/ha_myisam.cc
@@ -304,6 +304,10 @@ int ha_myisam::open(const char *name, int mode, uint test_if_locked)
   
   if (test_if_locked & (HA_OPEN_IGNORE_IF_LOCKED | HA_OPEN_TMP_TABLE))
     VOID(mi_extra(file, HA_EXTRA_NO_WAIT_LOCK, 0));
+
+  if (!(test_if_locked & HA_OPEN_TMP_TABLE) && opt_myisam_use_mmap)
+    VOID(mi_extra(file, HA_EXTRA_MMAP, 0));
+
   info(HA_STATUS_NO_LOCK | HA_STATUS_VARIABLE | HA_STATUS_CONST);
   if (!(test_if_locked & HA_OPEN_WAIT_IF_LOCKED))
     VOID(mi_extra(file, HA_EXTRA_WAIT_LOCK, 0));
diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h
index 4b7a1fc00a8b9bd08222c560bb0fca2372b55520..9c18fb1b8acc25525a2b95c522c42344d33bad0a 100644
--- a/sql/mysql_priv.h
+++ b/sql/mysql_priv.h
@@ -1215,7 +1215,7 @@ extern bool volatile abort_loop, shutdown_in_progress, grant_option;
 extern bool mysql_proc_table_exists;
 extern uint volatile thread_count, thread_running, global_read_lock;
 extern my_bool opt_sql_bin_update, opt_safe_user_create, opt_no_mix_types;
-extern my_bool opt_safe_show_db, opt_local_infile;
+extern my_bool opt_safe_show_db, opt_local_infile, opt_myisam_use_mmap;
 extern my_bool opt_slave_compressed_protocol, use_temp_pool;
 extern my_bool opt_readonly, lower_case_file_system;
 extern my_bool opt_enable_named_pipe, opt_sync_frm, opt_allow_suspicious_udfs;
diff --git a/sql/mysqld.cc b/sql/mysqld.cc
index f344becffdea179e688f01ad42a836d0f70d239a..a56082a6ad39e6fc7d21414a25d36ef07fb0ed9e 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@ -428,6 +428,7 @@ my_bool opt_secure_auth= 0;
 my_bool opt_log_slow_admin_statements= 0;
 my_bool lower_case_file_system= 0;
 my_bool opt_large_pages= 0;
+my_bool opt_myisam_use_mmap= 0;
 uint    opt_large_page_size= 0;
 my_bool opt_old_style_user_limits= 0, trust_function_creators= 0;
 /*
@@ -4558,6 +4559,7 @@ enum options_mysqld
   OPT_MAX_ERROR_COUNT, OPT_MULTI_RANGE_COUNT, OPT_MYISAM_DATA_POINTER_SIZE,
   OPT_MYISAM_BLOCK_SIZE, OPT_MYISAM_MAX_EXTRA_SORT_FILE_SIZE,
   OPT_MYISAM_MAX_SORT_FILE_SIZE, OPT_MYISAM_SORT_BUFFER_SIZE,
+  OPT_MYISAM_USE_MMAP,
   OPT_MYISAM_STATS_METHOD,
   OPT_NET_BUFFER_LENGTH, OPT_NET_RETRY_COUNT,
   OPT_NET_READ_TIMEOUT, OPT_NET_WRITE_TIMEOUT,
@@ -5767,6 +5769,11 @@ The minimum value for this variable is 4096.",
    (gptr*) &global_system_variables.myisam_sort_buff_size,
    (gptr*) &max_system_variables.myisam_sort_buff_size, 0,
    GET_ULONG, REQUIRED_ARG, 8192*1024, 4, ~0L, 0, 1, 0},
+  {"myisam_use_mmap", OPT_MYISAM_USE_MMAP,
+   "Use memory mapping for read/write MyISAM tables",
+   (gptr*) &opt_myisam_use_mmap,
+   (gptr*) &opt_myisam_use_mmap, 0, GET_BOOL, NO_ARG, 0, 
+    0, 0, 0, 0, 0},
   {"myisam_stats_method", OPT_MYISAM_STATS_METHOD,
    "Specifies how MyISAM index statistics collection code should threat NULLs. "
    "Possible values of name are \"nulls_unequal\" (default behavior for 4.1/5.0), "
diff --git a/sql/records.cc b/sql/records.cc
index ff0185195b08c82b62be3e91930bd730acc447c2..5cb9b1e5c478baad6f5ab7e7e8a20cb709ef8132 100644
--- a/sql/records.cc
+++ b/sql/records.cc
@@ -153,6 +153,10 @@ void init_read_record(READ_RECORD *info,THD *thd, TABLE *table,
   info->table=table;
   info->file= table->file;
   info->forms= &info->table;		/* Only one table */
+  
+  if (table->s->tmp_table == TMP_TABLE && !table->sort.addon_field)
+    VOID(table->file->extra(HA_EXTRA_MMAP));
+  
   if (table->sort.addon_field)
   {
     info->rec_buf= table->sort.addon_buf;
diff --git a/sql/set_var.cc b/sql/set_var.cc
index 19dc22653470f5848542350125e476af9cf01909..9d5fb2940cf1a3e53a1a81c6eaa16d340388ef42 100644
--- a/sql/set_var.cc
+++ b/sql/set_var.cc
@@ -314,6 +314,8 @@ sys_var_long_ptr	sys_myisam_data_pointer_size("myisam_data_pointer_size",
 sys_var_thd_ulonglong	sys_myisam_max_sort_file_size("myisam_max_sort_file_size", &SV::myisam_max_sort_file_size, fix_myisam_max_sort_file_size, 1);
 sys_var_thd_ulong       sys_myisam_repair_threads("myisam_repair_threads", &SV::myisam_repair_threads);
 sys_var_thd_ulong	sys_myisam_sort_buffer_size("myisam_sort_buffer_size", &SV::myisam_sort_buff_size);
+sys_var_bool_ptr	sys_myisam_use_mmap("myisam_use_mmap", 
+                                            &opt_myisam_use_mmap);
 
 sys_var_thd_enum        sys_myisam_stats_method("myisam_stats_method",
                                                 &SV::myisam_stats_method,
@@ -789,6 +791,7 @@ struct show_var_st init_vars[]= {
   {sys_myisam_repair_threads.name, (char*) &sys_myisam_repair_threads,
    SHOW_SYS},
   {sys_myisam_sort_buffer_size.name, (char*) &sys_myisam_sort_buffer_size, SHOW_SYS},
+  {sys_myisam_use_mmap.name, (char*) &sys_myisam_use_mmap, SHOW_SYS},
   
   {sys_myisam_stats_method.name, (char*) &sys_myisam_stats_method, SHOW_SYS},
   
diff --git a/storage/myisam/mi_close.c b/storage/myisam/mi_close.c
index 62f5617de1a60825c1921584e439cdb712ee166c..39a91371323db5a3dc9dc97b86e44bc01ed65c99 100644
--- a/storage/myisam/mi_close.c
+++ b/storage/myisam/mi_close.c
@@ -96,6 +96,7 @@ int mi_close(register MI_INFO *info)
     {
       int i,keys;
       keys = share->state.header.keys;
+      VOID(rwlock_destroy(&share->mmap_lock));
       for(i=0; i<keys; i++) {
 	VOID(rwlock_destroy(&share->key_root_lock[i]));
       }
diff --git a/storage/myisam/mi_delete_all.c b/storage/myisam/mi_delete_all.c
index a30abb95070382d1fd0cee3536f5822d2c6cc361..51f1e44d6d25646c3d4a59c2bc7dd4d2def8181e 100644
--- a/storage/myisam/mi_delete_all.c
+++ b/storage/myisam/mi_delete_all.c
@@ -22,6 +22,7 @@
 int mi_delete_all_rows(MI_INFO *info)
 {
   uint i;
+  char buf[22];
   MYISAM_SHARE *share=info->s;
   MI_STATE_INFO *state=&share->state;
   DBUG_ENTER("mi_delete_all_rows");
@@ -58,6 +59,12 @@ int mi_delete_all_rows(MI_INFO *info)
       my_chsize(share->kfile, share->base.keystart, 0, MYF(MY_WME))  )
     goto err;
   VOID(_mi_writeinfo(info,WRITEINFO_UPDATE_KEYFILE));
+#ifdef HAVE_MMAP
+  /* Resize mmaped area */
+  rw_wrlock(&info->s->mmap_lock);
+  mi_remap_file(info, (my_off_t)0);
+  rw_unlock(&info->s->mmap_lock);
+#endif
   allow_break();			/* Allow SIGHUP & SIGINT */
   DBUG_RETURN(0);
 
diff --git a/storage/myisam/mi_dynrec.c b/storage/myisam/mi_dynrec.c
index 8de500a73519896b4823d4bba364f73aa92b5744..cdcd7b95ce13e44aa9f7029b9f115c9771433445 100644
--- a/storage/myisam/mi_dynrec.c
+++ b/storage/myisam/mi_dynrec.c
@@ -50,6 +50,174 @@ static int _mi_cmp_buffer(File file, const byte *buff, my_off_t filepos,
 
 	/* Interface function from MI_INFO */
 
+#ifdef HAVE_MMAP
+
+/*
+  Create mmaped area for MyISAM handler
+
+  SYNOPSIS
+    mi_dynmap_file()
+    info		MyISAM handler
+
+  RETURN
+    0  ok
+    1  error.
+*/
+
+my_bool mi_dynmap_file(MI_INFO *info, my_off_t size)
+{
+  DBUG_ENTER("mi_dynmap_file");
+  info->s->file_map= (byte*)
+                  my_mmap(0, (size_t)(size + MEMMAP_EXTRA_MARGIN),
+                          info->s->mode==O_RDONLY ? PROT_READ :
+                          PROT_READ | PROT_WRITE,
+                          MAP_SHARED | MAP_NORESERVE,
+                          info->dfile, 0L);
+  if (info->s->file_map == (byte*) MAP_FAILED)
+  {
+    info->s->file_map= NULL;
+    DBUG_RETURN(1);
+  }
+#if defined(HAVE_MADVISE)
+  madvise(info->s->file_map, size, MADV_RANDOM);
+#endif
+  info->s->mmaped_length= size;
+  DBUG_RETURN(0);
+}
+
+
+/*
+  Resize mmaped area for MyISAM handler
+
+  SYNOPSIS
+    mi_remap_file()
+    info		MyISAM handler
+
+  RETURN
+*/
+
+void mi_remap_file(MI_INFO *info, my_off_t size)
+{
+  if (info->s->file_map)
+  {
+    VOID(my_munmap(info->s->file_map,
+                   (size_t) info->s->mmaped_length + MEMMAP_EXTRA_MARGIN));
+    mi_dynmap_file(info, size);
+  }
+}
+#endif
+
+
+/*
+  Read bytes from MySAM handler, using mmap or pread
+
+  SYNOPSIS
+    mi_mmap_pread()
+    info		MyISAM handler
+    Buffer              Input buffer
+    Count               Count of bytes for read
+    offset              Start position
+    MyFlags             
+
+  RETURN
+    0  ok
+*/
+
+uint mi_mmap_pread(MI_INFO *info, byte *Buffer,
+                    uint Count, my_off_t offset, myf MyFlags)
+{
+  DBUG_PRINT("info", ("mi_read with mmap %d\n", info->dfile));
+  if (info->s->concurrent_insert)
+    rw_rdlock(&info->s->mmap_lock);
+
+  /*
+    The following test may fail in the following cases:
+    - We failed to remap a memory area (fragmented memory?)
+    - This thread has done some writes, but not yet extended the
+    memory mapped area.
+  */
+
+  if (info->s->mmaped_length >= offset + Count)
+  {
+    memcpy(Buffer, info->s->file_map + offset, Count);
+    if (info->s->concurrent_insert)
+      rw_unlock(&info->s->mmap_lock);
+    return 0;
+  }
+  else
+  {
+    if (info->s->concurrent_insert)
+      rw_unlock(&info->s->mmap_lock);
+    return my_pread(info->dfile, Buffer, Count, offset, MyFlags);
+  }
+}
+
+
+        /* wrapper for my_pread in case if mmap isn't used */
+
+uint mi_nommap_pread(MI_INFO *info, byte *Buffer,
+                      uint Count, my_off_t offset, myf MyFlags)
+{
+  return my_pread(info->dfile, Buffer, Count, offset, MyFlags);
+}
+
+
+/*
+  Write bytes to MySAM handler, using mmap or pwrite
+
+  SYNOPSIS
+    mi_mmap_pwrite()
+    info		MyISAM handler
+    Buffer              Output buffer
+    Count               Count of bytes for write
+    offset              Start position
+    MyFlags             
+
+  RETURN
+    0  ok
+    !=0  error.  In this case return error from pwrite
+*/
+
+uint mi_mmap_pwrite(MI_INFO *info, byte *Buffer,
+                     uint Count, my_off_t offset, myf MyFlags)
+{
+  DBUG_PRINT("info", ("mi_write with mmap %d\n", info->dfile));
+  if (info->s->concurrent_insert)
+    rw_rdlock(&info->s->mmap_lock);
+
+  /*
+    The following test may fail in the following cases:
+    - We failed to remap a memory area (fragmented memory?)
+    - This thread has done some writes, but not yet extended the
+    memory mapped area.
+  */
+
+  if (info->s->mmaped_length >= offset + Count)
+  {
+    memcpy(info->s->file_map + offset, Buffer, Count); 
+    if (info->s->concurrent_insert)
+      rw_unlock(&info->s->mmap_lock);
+    return 0;
+  }
+  else
+  {
+    if (info->s->concurrent_insert)
+      rw_unlock(&info->s->mmap_lock);
+    return my_pwrite(info->dfile, Buffer, Count, offset, MyFlags);
+  }
+
+}
+
+
+        /* wrapper for my_pwrite in case if mmap isn't used */
+
+uint mi_nommap_pwrite(MI_INFO *info, byte *Buffer,
+                      uint Count, my_off_t offset, myf MyFlags)
+{
+  return my_pwrite(info->dfile, Buffer, Count, offset, MyFlags);
+}
+
+
 int _mi_write_dynamic_record(MI_INFO *info, const byte *record)
 {
   ulong reclength=_mi_rec_pack(info,info->rec_buff,record);
@@ -243,7 +411,7 @@ static bool unlink_deleted_block(MI_INFO *info, MI_BLOCK_INFO *block_info)
 	  & BLOCK_DELETED))
       DBUG_RETURN(1);				/* Something is wrong */
     mi_sizestore(tmp.header+4,block_info->next_filepos);
-    if (my_pwrite(info->dfile,(char*) tmp.header+4,8,
+    if (info->s->file_write(info,(char*) tmp.header+4,8,
 		  block_info->prev_filepos+4, MYF(MY_NABP)))
       DBUG_RETURN(1);
     /* Unlink block from next block */
@@ -253,7 +421,7 @@ static bool unlink_deleted_block(MI_INFO *info, MI_BLOCK_INFO *block_info)
 	    & BLOCK_DELETED))
 	DBUG_RETURN(1);				/* Something is wrong */
       mi_sizestore(tmp.header+12,block_info->prev_filepos);
-      if (my_pwrite(info->dfile,(char*) tmp.header+12,8,
+      if (info->s->file_write(info,(char*) tmp.header+12,8,
 		    block_info->next_filepos+12,
 		    MYF(MY_NABP)))
 	DBUG_RETURN(1);
@@ -304,7 +472,7 @@ static int update_backward_delete_link(MI_INFO *info, my_off_t delete_block,
     {
       char buff[8];
       mi_sizestore(buff,filepos);
-      if (my_pwrite(info->dfile,buff, 8, delete_block+12, MYF(MY_NABP)))
+      if (info->s->file_write(info,buff, 8, delete_block+12, MYF(MY_NABP)))
 	DBUG_RETURN(1);				/* Error on write */
     }
     else
@@ -362,7 +530,7 @@ static int delete_dynamic_record(MI_INFO *info, my_off_t filepos,
       bfill(block_info.header+12,8,255);
     else
       mi_sizestore(block_info.header+12,block_info.next_filepos);
-    if (my_pwrite(info->dfile,(byte*) block_info.header,20,filepos,
+    if (info->s->file_write(info,(byte*) block_info.header,20,filepos,
 		  MYF(MY_NABP)))
       DBUG_RETURN(1);
     info->s->state.dellink = filepos;
@@ -545,7 +713,7 @@ int _mi_write_part_record(MI_INFO *info,
   else
   {
     info->rec_cache.seek_not_done=1;
-    if (my_pwrite(info->dfile,(byte*) *record-head_length,length+extra_length+
+    if (info->s->file_write(info,(byte*) *record-head_length,length+extra_length+
 		  del_length,filepos,info->s->write_flag))
       goto err;
   }
@@ -655,7 +823,7 @@ static int update_dynamic_record(MI_INFO *info, my_off_t filepos, byte *record,
 	      mi_int3store(del_block.header+1, rest_length);
 	      mi_sizestore(del_block.header+4,info->s->state.dellink);
 	      bfill(del_block.header+12,8,255);
-	      if (my_pwrite(info->dfile,(byte*) del_block.header,20, next_pos,
+	      if (info->s->file_write(info,(byte*) del_block.header,20, next_pos,
 			    MYF(MY_NABP)))
 		DBUG_RETURN(1);
 	      info->s->state.dellink= next_pos;
@@ -1182,7 +1350,7 @@ int _mi_read_dynamic_record(MI_INFO *info, my_off_t filepos, byte *buf)
       }
       if (left_length < block_info.data_len || ! block_info.data_len)
 	goto panic;			/* Wrong linked record */
-      if (my_pread(file,(byte*) to,block_info.data_len,block_info.filepos,
+      if (info->s->file_read(info,(byte*) to,block_info.data_len,block_info.filepos,
 		   MYF(MY_NABP)))
 	goto panic;
       left_length-=block_info.data_len;
diff --git a/storage/myisam/mi_extra.c b/storage/myisam/mi_extra.c
index 7c0dd13b87085b498999d23630755da54f4e537f..04beb36bb4769417bd75a2173e3e60c67503426c 100644
--- a/storage/myisam/mi_extra.c
+++ b/storage/myisam/mi_extra.c
@@ -93,6 +93,8 @@ int mi_extra(MI_INFO *info, enum ha_extra_function function, void *extra_arg)
       my_errno=EACCES;
       break;
     }
+    if (info->s->file_map) /* Don't use cache if mmap */
+      break;
 #if defined(HAVE_MMAP) && defined(HAVE_MADVISE)
     if ((share->options & HA_OPTION_COMPRESS_RECORD))
     {
@@ -150,6 +152,7 @@ int mi_extra(MI_INFO *info, enum ha_extra_function function, void *extra_arg)
       error=1;			/* Not possibly if not locked */
       break;
     }
+
     cache_size= (extra_arg ? *(ulong*) extra_arg :
 		 my_default_record_cache_size);
     if (!(info->opt_flag &
@@ -367,6 +370,25 @@ int mi_extra(MI_INFO *info, enum ha_extra_function function, void *extra_arg)
   case HA_EXTRA_CHANGE_KEY_TO_DUP:
     mi_extra_keyflag(info, function);
     break;
+  case HA_EXTRA_MMAP:
+#ifdef HAVE_MMAP
+    pthread_mutex_lock(&share->intern_lock);
+    if (!share->file_map)
+    {
+      if (mi_dynmap_file(info, share->state.state.data_file_length))
+      {
+        DBUG_PRINT("warning",("mmap failed: errno: %d",errno));
+        error= my_errno= errno;
+      }
+      else
+      {
+        share->file_read= mi_mmap_pread;
+        share->file_write= mi_mmap_pwrite;
+      }
+    }
+    pthread_mutex_unlock(&share->intern_lock);
+#endif
+    break;
   case HA_EXTRA_KEY_CACHE:
   case HA_EXTRA_NO_KEY_CACHE:
   default:
diff --git a/storage/myisam/mi_locking.c b/storage/myisam/mi_locking.c
index 8d48c5242e5b33d8b4d6102e22cf75169e67f436..5d871aa1e38e5a845b6481b0cfff2dfc623f15a7 100644
--- a/storage/myisam/mi_locking.c
+++ b/storage/myisam/mi_locking.c
@@ -38,7 +38,6 @@ int mi_lock_database(MI_INFO *info, int lock_type)
                       share->w_locks,
                       share->global_changed, share->state.open_count,
                       share->index_file_name));
-
   if (share->options & HA_OPTION_READ_ONLY_DATA ||
       info->lock_type == lock_type)
     DBUG_RETURN(0);
@@ -84,6 +83,14 @@ int mi_lock_database(MI_INFO *info, int lock_type)
 			   (uint) share->changed, share->w_locks));
 	if (share->changed && !share->w_locks)
 	{
+          if (info->s->mmaped_length != info->s->state.state.data_file_length)
+          {
+            if (info->s->concurrent_insert)
+              rw_wrlock(&info->s->mmap_lock);
+            mi_remap_file(info, info->s->state.state.data_file_length);
+            if (info->s->concurrent_insert)
+              rw_unlock(&info->s->mmap_lock);
+          }
 	  share->state.process= share->last_process=share->this_process;
 	  share->state.unique=   info->last_unique=  info->this_unique;
 	  share->state.update_count= info->last_loop= ++info->this_loop;
@@ -215,6 +222,7 @@ int mi_lock_database(MI_INFO *info, int lock_type)
 	}
       }
       VOID(_mi_test_if_changed(info));
+        
       info->lock_type=lock_type;
       info->invalidator=info->s->invalidator;
       share->w_locks++;
diff --git a/storage/myisam/mi_open.c b/storage/myisam/mi_open.c
index 91136bbeef58fa3e22ac4faad8b3e8fa0b66e5be..a09e4514d63ac7441908b0a6271d5ff6881c746d 100644
--- a/storage/myisam/mi_open.c
+++ b/storage/myisam/mi_open.c
@@ -288,6 +288,7 @@ MI_INFO *mi_open(const char *name, int mode, uint open_flags)
 #ifdef THREAD
 			 &share->key_root_lock,sizeof(rw_lock_t)*keys,
 #endif
+			 &share->mmap_lock,sizeof(rw_lock_t),
 			 NullS))
       goto err;
     errpos=4;
@@ -459,7 +460,6 @@ MI_INFO *mi_open(const char *name, int mode, uint open_flags)
 					(keys ? MI_INDEX_BLOCK_MARGIN *
 					 share->blocksize * keys : 0));
     share->blocksize=min(IO_SIZE,myisam_block_size);
-
     share->data_file_type=STATIC_RECORD;
     if (share->options & HA_OPTION_COMPRESS_RECORD)
     {
@@ -482,6 +482,7 @@ MI_INFO *mi_open(const char *name, int mode, uint open_flags)
     VOID(pthread_mutex_init(&share->intern_lock,MY_MUTEX_INIT_FAST));
     for (i=0; i<keys; i++)
       VOID(my_rwlock_init(&share->key_root_lock[i], NULL));
+    VOID(my_rwlock_init(&share->mmap_lock, NULL));
     if (!thr_lock_inited)
     {
       /* Probably a single threaded program; Don't use concurrent inserts */
@@ -736,6 +737,8 @@ void mi_setup_functions(register MYISAM_SHARE *share)
     share->compare_unique=_mi_cmp_static_unique;
     share->calc_checksum= mi_static_checksum;
   }
+  share->file_read= mi_nommap_pread;
+  share->file_write= mi_nommap_pwrite;
   if (!(share->options & HA_OPTION_CHECKSUM))
     share->calc_checksum=0;
   return;
diff --git a/storage/myisam/mi_packrec.c b/storage/myisam/mi_packrec.c
index e242e9d506d943459024fe4ec04943dfc6f805e7..6a1fca9ede9706f9b58446fbc7be68446ecdf238 100644
--- a/storage/myisam/mi_packrec.c
+++ b/storage/myisam/mi_packrec.c
@@ -1192,34 +1192,25 @@ my_bool _mi_memmap_file(MI_INFO *info)
   if (!info->s->file_map)
   {
     if (my_seek(info->dfile,0L,MY_SEEK_END,MYF(0)) <
-	share->state.state.data_file_length+MEMMAP_EXTRA_MARGIN)
+        share->state.state.data_file_length+MEMMAP_EXTRA_MARGIN)
     {
       DBUG_PRINT("warning",("File isn't extended for memmap"));
       DBUG_RETURN(0);
     }
-    file_map=(byte*)
-      my_mmap(0,(size_t)(share->state.state.data_file_length+MEMMAP_EXTRA_MARGIN),PROT_READ,
-	   MAP_SHARED | MAP_NORESERVE,info->dfile,0L);
-    if (file_map == (byte*) MAP_FAILED)
-    {
-      DBUG_PRINT("warning",("mmap failed: errno: %d",errno));
-      my_errno=errno;
+    if (mi_dynmap_file(info, share->state.state.data_file_length))
       DBUG_RETURN(0);
-    }
-    info->s->file_map=file_map;
   }
   info->opt_flag|= MEMMAP_USED;
-  info->read_record=share->read_record=_mi_read_mempack_record;
-  share->read_rnd=_mi_read_rnd_mempack_record;
+  info->read_record= share->read_record= _mi_read_mempack_record;
+  share->read_rnd= _mi_read_rnd_mempack_record;
   DBUG_RETURN(1);
 }
 
 
 void _mi_unmap_file(MI_INFO *info)
 {
-  VOID(my_munmap(info->s->file_map,
-	      (size_t) info->s->state.state.data_file_length+
-	      MEMMAP_EXTRA_MARGIN));
+  VOID(my_munmap(info->s->file_map, 
+                 (size_t) info->s->mmaped_length + MEMMAP_EXTRA_MARGIN));
 }
 
 
diff --git a/storage/myisam/mi_statrec.c b/storage/myisam/mi_statrec.c
index 42352f63c6691aef593988da047ad991884e88fa..70e63ef8ce1040fff9f3f21c7cfb4598ae1ce93d 100644
--- a/storage/myisam/mi_statrec.c
+++ b/storage/myisam/mi_statrec.c
@@ -22,20 +22,19 @@
 int _mi_write_static_record(MI_INFO *info, const byte *record)
 {
   uchar temp[8];				/* max pointer length */
-
   if (info->s->state.dellink != HA_OFFSET_ERROR &&
       !info->append_insert_at_end)
   {
     my_off_t filepos=info->s->state.dellink;
     info->rec_cache.seek_not_done=1;		/* We have done a seek */
-    if (my_pread(info->dfile,(char*) &temp[0],info->s->base.rec_reflength,
+    if (info->s->file_read(info,(char*) &temp[0],info->s->base.rec_reflength,
 		info->s->state.dellink+1,
 		 MYF(MY_NABP)))
       goto err;
     info->s->state.dellink= _mi_rec_pos(info->s,temp);
     info->state->del--;
     info->state->empty-=info->s->base.pack_reclength;
-    if (my_pwrite(info->dfile, (char*) record, info->s->base.reclength,
+    if (info->s->file_write(info, (char*) record, info->s->base.reclength,
 		  filepos,
 		  MYF(MY_NABP)))
       goto err;
@@ -64,19 +63,19 @@ int _mi_write_static_record(MI_INFO *info, const byte *record)
     else
     {
       info->rec_cache.seek_not_done=1;		/* We have done a seek */
-      if (my_pwrite(info->dfile,(char*) record,info->s->base.reclength,
+      if (info->s->file_write(info,(char*) record,info->s->base.reclength,
 		    info->state->data_file_length,
 		    info->s->write_flag))
-	goto err;
+        goto err;
       if (info->s->base.pack_reclength != info->s->base.reclength)
       {
 	uint length=info->s->base.pack_reclength - info->s->base.reclength;
 	bzero((char*) temp,length);
-	if (my_pwrite(info->dfile, (byte*) temp,length,
+	if (info->s->file_write(info, (byte*) temp,length,
 		      info->state->data_file_length+
 		      info->s->base.reclength,
 		      info->s->write_flag))
-	  goto err;
+    goto err;
       }
     }
     info->state->data_file_length+=info->s->base.pack_reclength;
@@ -90,7 +89,7 @@ int _mi_write_static_record(MI_INFO *info, const byte *record)
 int _mi_update_static_record(MI_INFO *info, my_off_t pos, const byte *record)
 {
   info->rec_cache.seek_not_done=1;		/* We have done a seek */
-  return (my_pwrite(info->dfile,
+  return (info->s->file_write(info,
 		    (char*) record,info->s->base.reclength,
 		    pos,
 		    MYF(MY_NABP)) != 0);
@@ -107,7 +106,7 @@ int _mi_delete_static_record(MI_INFO *info)
   _mi_dpointer(info,temp+1,info->s->state.dellink);
   info->s->state.dellink = info->lastpos;
   info->rec_cache.seek_not_done=1;
-  return (my_pwrite(info->dfile,(byte*) temp, 1+info->s->rec_reflength,
+  return (info->s->file_write(info,(byte*) temp, 1+info->s->rec_reflength,
 		    info->lastpos, MYF(MY_NABP)) != 0);
 }
 
@@ -131,7 +130,7 @@ int _mi_cmp_static_record(register MI_INFO *info, register const byte *old)
   if ((info->opt_flag & READ_CHECK_USED))
   {						/* If check isn't disabled  */
     info->rec_cache.seek_not_done=1;		/* We have done a seek */
-    if (my_pread(info->dfile, (char*) info->rec_buff, info->s->base.reclength,
+    if (info->s->file_read(info, (char*) info->rec_buff, info->s->base.reclength,
 		 info->lastpos,
 		 MYF(MY_NABP)))
       DBUG_RETURN(-1);
@@ -154,7 +153,7 @@ int _mi_cmp_static_unique(MI_INFO *info, MI_UNIQUEDEF *def,
   DBUG_ENTER("_mi_cmp_static_unique");
 
   info->rec_cache.seek_not_done=1;		/* We have done a seek */
-  if (my_pread(info->dfile, (char*) info->rec_buff, info->s->base.reclength,
+  if (info->s->file_read(info, (char*) info->rec_buff, info->s->base.reclength,
 	       pos, MYF(MY_NABP)))
     DBUG_RETURN(-1);
   DBUG_RETURN(mi_unique_comp(def, record, info->rec_buff,
@@ -180,7 +179,7 @@ int _mi_read_static_record(register MI_INFO *info, register my_off_t pos,
       return(-1);
     info->rec_cache.seek_not_done=1;		/* We have done a seek */
 
-    error=my_pread(info->dfile,(char*) record,info->s->base.reclength,
+    error=info->s->file_read(info,(char*) record,info->s->base.reclength,
 		   pos,MYF(MY_NABP)) != 0;
     fast_mi_writeinfo(info);
     if (! error)
diff --git a/storage/myisam/myisamdef.h b/storage/myisam/myisamdef.h
index 6ccb52aff22b71230bfae0ab6dea9bcf7d877558..564acb82e69eca79acde0882e4fbbc081be7503d 100644
--- a/storage/myisam/myisamdef.h
+++ b/storage/myisam/myisamdef.h
@@ -179,6 +179,8 @@ typedef struct st_mi_isam_share {	/* Shared between opens */
   ha_checksum (*calc_checksum)(struct st_myisam_info*, const byte *);
   int (*compare_unique)(struct st_myisam_info*, MI_UNIQUEDEF *,
 			const byte *record, my_off_t pos);
+  uint (*file_read)(MI_INFO *, byte *, uint, my_off_t, myf);
+  uint (*file_write)(MI_INFO *, byte *, uint, my_off_t, myf);
   invalidator_by_filename invalidator;  /* query cache invalidator */
   ulong this_process;			/* processid */
   ulong last_process;			/* For table-change-check */
@@ -207,6 +209,8 @@ typedef struct st_mi_isam_share {	/* Shared between opens */
   pthread_mutex_t intern_lock;		/* Locking for use with _locking */
   rw_lock_t *key_root_lock;
 #endif
+  my_off_t mmaped_length;
+  rw_lock_t mmap_lock;
 } MYISAM_SHARE;
 
 
@@ -685,6 +689,14 @@ extern void _mi_unmap_file(MI_INFO *info);
 extern uint save_pack_length(uint version, byte *block_buff, ulong length);
 extern uint read_pack_length(uint version, const uchar *buf, ulong *length);
 extern uint calc_pack_length(uint version, ulong length);
+extern uint mi_mmap_pread(MI_INFO *info, byte *Buffer,
+                           uint Count, my_off_t offset, myf MyFlags);
+extern uint mi_mmap_pwrite(MI_INFO *info, byte *Buffer,
+                            uint Count, my_off_t offset, myf MyFlags);
+extern uint mi_nommap_pread(MI_INFO *info, byte *Buffer,
+                             uint Count, my_off_t offset, myf MyFlags);
+extern uint mi_nommap_pwrite(MI_INFO *info, byte *Buffer,
+                             uint Count, my_off_t offset, myf MyFlags);
 
 uint mi_state_info_write(File file, MI_STATE_INFO *state, uint pWrite);
 uchar *mi_state_info_read(uchar *ptr, MI_STATE_INFO *state);