Index: trunk/kernel/mm/mapper.h
===================================================================
--- trunk/kernel/mm/mapper.h	(revision 690)
+++ trunk/kernel/mm/mapper.h	(revision 1)
@@ -1,7 +1,7 @@
 /*
- * mapper.h - Kernel cache for VFS files/directories definition.
+ * mapper.h - Map memory, file or device in process virtual address space.
  *
  * Authors   Mohamed Lamine Karaoui (2015)
- *           Alain Greiner (2016,2017,2018,2019)
+ *           Alain Greiner (2016)
  *
  * Copyright (c)  UPMC Sorbonne Universites
@@ -26,5 +26,5 @@
 #define _MAPPER_H_
 
-#include <hal_kernel_types.h>
+#include <hal_types.h>
 #include <hal_atomic.h>
 #include <xlist.h>
@@ -38,32 +38,23 @@
 
 /*******************************************************************************************
- * This mapper_t object implements the kernel cache for a given VFS file or directory.
- * There is one mapper per file/dir.
- * - It is implemented as a three levels radix tree, entirely stored in the same cluster
- *   as the inode representing the file/directory.
- * - The fast retrieval key is the page index in the file.
+ * The mapper implement the kernel cache for a given file or directory.
+ * There is one mapper per file. It is implemented as a three levels radix tree,
+ * entirely stored in the same cluster as the inode representing the file/dir.
+ * - The fast retrieval key is the page index in the file. 
  *   The ix1_width, ix2_width, ix3_width sub-indexes are configuration parameters.
  * - The leaves are pointers on physical page descriptors, dynamically allocated
- *   in the same cluster as the radix tree.
- * - The mapper is protected by a "remote_rwlock", to support several simultaneous 
- *   "readers", and only one "writer".
- * - A "reader" thread, calling the mapper_remote_get_page() function to get a page 
- *   descriptor pointer from the page index in file, can be running in any cluster. 
- * - A "writer" thread, calling the mapper_handle_miss() function to handle a page miss
- *   must be local (running in the mapper cluster).
- * - The vfs_fs_move_page() function access the file system to handle a mapper miss,
- *   or update a dirty page on device.
- * - The vfs_mapper_load_all() functions is used to load all pages of a directory 
- *   into the mapper (prefetch).
- * - the mapper_move_user() function is used to move data to or from an user buffer.
- *   This user space buffer can be physically distributed in several clusters.
- * - the mapper_move_kernel() function is used to move data to or from a remote kernel
- *   buffer, that can be physically located in any cluster.
- * - In the present implementation the cache size for a given file increases on demand,
- *   and the  allocated memory is only released when the inode is destroyed.
- *
- * WARNING : This mapper implementation makes the assumption that the PPM page size
- *           is 4 Kbytes. This code should be modified to support a generic page size,
- *           defined by the CONFIG_PPM_PAGE_SIZE parameter. 
+ *   in the local cluster.
+ * - In a given cluster, a mapper is a "private" structure: a thread accessing the mapper
+ *   must be running in the cluster containing it (can be a local thread or a RPC thread).
+ * - The mapper is protected by a blocking "rwlock", to support several simultaneous
+ *   readers, and only one writer. This lock implement a busy waiting policy.
+ * - The two functions mapper_sync_page() and mapper_updt_page() define the generic API
+ *   used to move pages to or from the relevant file system on IOC device.
+ * - the mapper_move fragments() function is used to move data to or from a distributed
+ *   user buffer. 
+ * - The mapper_get_page() function that return a page descriptor pointer from a page
+ *   index in file is in charge of handling the miss on the mapper cache.
+ * - In the present implementation the cache size increases on demand, and the
+ *   allocated memory is only released when the mapper is destroyed.
  ******************************************************************************************/
 
@@ -75,8 +66,7 @@
 typedef struct mapper_s
 {
-	struct vfs_inode_s * inode;	      /*! owner inode                                     */
-    uint32_t             fs_type;     /*! file system type                                */
-	grdxt_t	             rt; 	      /*! embedded pages cache descriptor (radix tree)    */
-	remote_rwlock_t      lock;        /*! several readers / only one writer               */
+	struct vfs_inode_s * inode;	      /*! owner file inode                                */
+	grdxt_t	             radix;	      /*! pages cache implemented as a radix tree         */
+	rwlock_t             lock;        /*! several readers / only one writer               */
 	uint32_t	         refcount;    /*! several vsegs can refer the same file           */
 	xlist_entry_t        vsegs_root;  /*! root of list of vsegs refering this mapper      */
@@ -87,198 +77,124 @@
 
 /*******************************************************************************************
- * This function allocates physical memory for a mapper descriptor, in cluster
- * identified by the <cxy> argument. It initializes it (refcount <= 0) / inode <= NULL).
- * It can be executed by any thread running in any cluster.
- *******************************************************************************************
- * @ cxy    : target cluster identifier.
- * @ type   : FS type.
- * @ return an extended pointer on created mapper if success / return NULL if no memory
- ******************************************************************************************/
-xptr_t  mapper_create( cxy_t     cxy,
-                       uint32_t  type );
-
-/*******************************************************************************************
- * This function releases all physical memory allocated for a mapper, identified
- * by the <mapper_xp> argument. Both the mapper descriptor and the radix tree are released.
- * It does NOT synchronize dirty pages. Use the vfs_sync_inode() function if required.
- * It can be executed by any thread running in any cluster.
- *******************************************************************************************
- * @ mapper_xp	 : extended pointer on target mapper.
- ******************************************************************************************/
-void mapper_destroy( xptr_t  mapper_xp );
-
-/*******************************************************************************************
- * This function load from the IOC device a missing page identified by the <page_id> 
- * argument into a - possibly remote - mapper identified by the <mapper_xp> argument.
- * It can be executed by a thread running in any cluster.
- * It allocates a physical page from the remote cluster PPM, initialises it by accessing
- * the IOC device, and registers the page in the remote mapper radix tree.
- * WARNING : the calling function mapper_remote_get_page() is supposed to take and release
- * the lock protecting the mapper in WRITE_MODE.
- *******************************************************************************************
- * @ mapper_xp	 : [in]  extended pointer on remote mapper.
- * @ page_id     : [in]  missing page index in file.
- * @ page_xp     : [out] buffer for extended pointer on missing page descriptor.
- * @ return 0 if success / return -1 if IOC cannot be accessed.
- ******************************************************************************************/
-error_t mapper_handle_miss( xptr_t     mapper_xp,
-                            uint32_t   page_id,
-                            xptr_t   * page_xp );
-
-/*******************************************************************************************
- * This function removes a physical page from a - possibly remote - mapper,
- * and releases the page to the remote PPM. 
- * It can be executed by any thread running in any cluster. 
- * It takes the mapper lock in WRITE_MODE to update the mapper.
- *******************************************************************************************
- * @ mapper	: extended pointer on the remote mapper.
- * @ page	: local pointer on the page in remote mapper.
- ******************************************************************************************/
-void mapper_remote_release_page( xptr_t          mapper_xp,
-                                 struct page_s * page );
-
-/*******************************************************************************************
- * This function move data between a remote mapper, identified by the <mapper_xp> argument,
- * and a distributed user buffer. It can be called by a thread running in any cluster.
- * It is called by the vfs_user_move() to implement sys_read() and sys_write() syscalls.
- * If required, the data transfer is split in "fragments", where one fragment contains 
- * contiguous bytes in the same mapper page.
- * It uses "hal_uspace" accesses to move a fragment to/from the user buffer.
+ * This structure defines a "fragment". It is used to move data between the kernel mapper,
+ * and an user buffer, that can be split in several distributed physical pages located
+ * in different clusters. A fragment is a set of contiguous bytes in the file.
+ * - It can be stored in one single physical page in the user buffer. 
+ * - It can spread two successive physical pages in the kernel mapper.
+ ******************************************************************************************/
+
+typedef struct fragment_s
+{
+    uint32_t    file_offset;         /*! offset of fragment in file (i.e. in mapper)      */
+    uint32_t    size;                /*! number of bytes in fragment                      */
+    cxy_t       buf_cxy;             /*! user buffer cluster identifier                   */
+    uint8_t   * buf_ptr;             /*! local pointer on first byte in user buffer       */
+}
+fragment_t;
+
+/*******************************************************************************************
+ * This function allocates physical memory for a mapper descriptor, and inititalizes it
+ * (refcount <= 0) / inode <= NULL).
+ * It must be executed by a thread running in the cluster containing the mapper.
+ *******************************************************************************************
+ * @ return pointer on created mapper if success / return NULL if no memory
+ ******************************************************************************************/
+mapper_t * mapper_create();
+
+/*******************************************************************************************
+ * This function releases all physical pages allocated for the mapper.
+ * It synchronizes all dirty pages (i.e. update the file on disk) if required.
+ * The mapper descriptor and the radix three themselve are released.
+ * It must be executed by a thread running in the cluster containing the mapper.
+ *******************************************************************************************
+ * @ mapper	 : target mapper.
+ * @ return 0 if success / return EIO if a dirty page cannot be updated on device.
+ ******************************************************************************************/
+error_t mapper_destroy( mapper_t * mapper );
+
+/*******************************************************************************************
+ * This function moves all fragments covering a distributed user buffer between 
+ * a mapper (associated to a local inode), and the user buffer.
+ * [See the fragment definition in the mapper.h file] 
+ * It must be executed by a thread running in the cluster containing the mapper.
+ * The lock protecting the mapper must have been taken in WRITE_MODE or READ_MODE
+ * by the caller thread, depending on the transfer direction.
  * In case of write, the dirty bit is set for all pages written in the mapper.
- * The mapper being an extendable cache, it is automatically extended when required.
- * The "offset" field in the file descriptor, and the "size" field in inode descriptor
- * are not modified by this function.
- *******************************************************************************************
- * @ mapper_xp    : extended pointer on mapper.
- * @ to_buffer    : mapper -> buffer if true / buffer -> mapper if false.
- * @ file_offset  : first byte to move in file.
- * @ u_buf        : user space pointer on user buffer.
- * @ size         : number of bytes to move.
- * returns O if success / returns -1 if error.
- ******************************************************************************************/
-error_t mapper_move_user( xptr_t     mapper_xp,
-                          bool_t     to_buffer,
-                          uint32_t   file_offset,
-                          void     * u_buf,
-                          uint32_t   size );
-
-/********************************************************************************************
- * This function move <size> bytes from/to a remote mapper, identified by the <mapper_xp>
- * argument, to/from a remote kernel buffer, identified by the <buffer_xp> argument.
- * It can be called by a thread running in any cluster. 
- * If required, the data transfer is split in "fragments", where one fragment contains 
- * contiguous bytes in the same mapper page. Each fragment uses a "remote_memcpy".
- * In case of write to mapper, the dirty bit is set for all pages written in the mapper.
- *******************************************************************************************
- * @ mapper_xp    : extended pointer on mapper.
- * @ to_buffer    : mapper -> buffer if true / buffer -> mapper if false.
- * @ file_offset  : first byte to move in file.
- * @ buffer_xp    : extended pointer on kernel buffer.
- * @ size         : number of bytes to move.
- * returns O if success / returns -1 if error.
- ******************************************************************************************/
-error_t mapper_move_kernel( xptr_t     mapper_xp,
-                            bool_t     to_buffer,
-                            uint32_t   file_offset,
-                            xptr_t     buffer_xp,
-                            uint32_t   size );
-
-/*******************************************************************************************
- * This function returns an extended pointer on a page descriptor for a regular mapper
- * (i.e. this mapper is NOT the FAT mapper), identified by the <mapper_xp> argument.
- * The page is identified by <page_id> argument (page index in the file).
- * It can be executed by a thread running in any cluster, as it uses remote
- * access primitives to scan the mapper.
- * In case of miss, this function takes the mapper lock in WRITE_MODE, and call the 
- * mapper_handle_miss() to load the missing page from device to mapper, using an RPC 
- * when the mapper is remote.
- *******************************************************************************************
- * @ mapper_xp	: extended pointer on the mapper.
- * @ page_id	: page index in file
- * @ returns extended pointer on page descriptor if success / return XPTR_NULL if error.
- ******************************************************************************************/
-xptr_t mapper_get_page( xptr_t    mapper_xp,
-                        uint32_t  page_id );
-
-/*******************************************************************************************
- * This function returns an extended pointer on a page descriptor for the FAT mapper.
- * The page is identified by <page_id> argument (page index in the FAT mapper).
- * It can be executed by a thread running in any cluster, as it uses remote
- * access primitives to scan the mapper.
- * In case of miss, this function takes the mapper lock in WRITE_MODE, and call the 
- * mapper_handle_miss() to load the missing page from device to mapper, using an RPC 
- * when the mapper is remote.
- *******************************************************************************************
- * @ mapper_xp	: extended pointer on the mapper.
- * @ page_id	: page index in file
- * @ returns extended pointer on page descriptor if success / return XPTR_NULL if error.
- ******************************************************************************************/
-xptr_t mapper_get_fat_page( xptr_t    mapper_xp,
-                            uint32_t  page_id );
-
-/*******************************************************************************************
- * This function allows to read a single word in a mapper seen as and array of uint32_t.
- * It has bee designed to support remote access to the FAT mapper of the FATFS. 
- * It can be called by any thread running in any cluster.
+ * The offset in the file descriptor is not modified by this function. 
+ * Implementation note:
+ * For each fragment, this function makes ONE hal_remote_memcpy() when the fragment is
+ * fully contained in one single page of the mapper. It makes TWO hal_remote_memcpy()
+ * if the fragment spread on two contiguous pages in the mapper.
+ *******************************************************************************************
+ * @ mapper    : local pointer on the local mapper.
+ * @ to_buffer : mapper to buffer if true / buffer to mapper if false.
+ * @ nb_frags  : number of fragments covering the user buffer (one per page).
+ * @ frags_xp  : extended pointer on array of fragments.
+FAT * returns O if success / returns EINVAL if error.
+ ******************************************************************************************/
+error_t mapper_move_fragments( mapper_t * mapper,
+                               bool_t     to_buffer,
+                               uint32_t   nb_frags,
+                               xptr_t     frags_xp );
+
+
+/*******************************************************************************************
+ * This function removes a physical page from the mapper, update the FS if the page
+ * is dirty, and releases the page to PPM. It is called by the mapper_destroy() function.
+ * It must be executed by a thread running in the cluster containing the mapper.
+ * It takes both the page lock and the mapper lock in WRITE_MODE to release the page.
+ *******************************************************************************************
+ * @ mapper	: local pointer on the mapper.
+ * @ index	: page index in file
+ * @ page	: pointer on page to remove.
+ * @ return 0 if success / return EIO if a dirty page cannot be copied to FS.
+ ******************************************************************************************/
+error_t mapper_release_page( mapper_t      * mapper,
+                             uint32_t        index,
+                             struct page_s * page );
+
+/*******************************************************************************************
+ * This function search a physical page descriptor from its index in mapper.
+ * It must be executed by a thread running in the cluster containing the mapper.
  * In case of miss, it takes the mapper lock in WRITE_MODE, load the missing
- * page from device to mapper, and release the mapper lock.
- *******************************************************************************************
- * @ mapper_xp	: [in]  extended pointer on the mapper.
- * @ page_id    : [in]  page index in mapper.
- * @ word_id    : [in]  32 bits word index in page.
- * @ value      : [out] local pointer on destination buffer.
- * @ returns 0 if success / return -1 if error.
- ******************************************************************************************/
-error_t mapper_remote_get_32( xptr_t     mapper_xp,
-                              uint32_t   page_id,
-                              uint32_t   word_id,
-                              uint32_t * value );
-
-/*******************************************************************************************
- * This function allows to write a single word to a mapper seen as and array of uint32_t.
- * It has been designed to support remote access to the FAT mapper of the FATFS. 
- * It can be called by any thread running in any cluster.
- * In case of miss, it takes the mapper lock in WRITE_MODE, load the missing
- * page from device to mapper, and release the mapper lock.
- * It does not update the FAT on IOC device.
- *******************************************************************************************
- * @ mapper_xp	: [in]  extended pointer on the mapper.
- * @ page_id    : [in]  page index in mapper.
- * @ word_id    : [in]  32 bits word index in page.
- * @ value      : [in]  value to be written.
- * @ returns 0 if success / return -1 if error.
- ******************************************************************************************/
-error_t mapper_remote_set_32( xptr_t     mapper_xp,
-                              uint32_t   page_id,
-                              uint32_t   word_id,
-                              uint32_t   value );
-
-/*******************************************************************************************
- * This function scan all pages present in the mapper identified by the <mapper_xp>
- * argument, and synchronize all pages marked as "dirty" on disk. 
- * These pages are unmarked and removed from the local PPM dirty_list. 
- * It can be called by any thread running in any cluster.
- *******************************************************************************************
- * @ mapper_xp	: [in]  extended pointer on local mapper.
- * @ returns 0 if success / return -1 if error.
- ******************************************************************************************/
-error_t mapper_sync( xptr_t  mapper_xp );
-
-/*******************************************************************************************
- * This debug function displays the content of a given page of a given mapper, identified
- * by the <mapper_xp> and <page_id> arguments.
- * The number of bytes to display in page is defined by the <nbytes> argument.
- * The format is eigth (32 bits) words per line in hexadecimal.
- * It can be called by any thread running in any cluster.
- *******************************************************************************************
- * @ mapper_xp	: [in]  extended pointer on the mapper.
- * @ page_id	: [in]  page_index in mapper.
- * @ nbytes     : [in]  number of bytes in page.
- * @ returns 0 if success / return -1 if error.
- ******************************************************************************************/
-void mapper_display_page( xptr_t     mapper_xp,
-                          uint32_t   page_id,
-                          uint32_t   nbytes );
-
+ * page from device to the mapper, and release the mapper lock. 
+ *******************************************************************************************
+ * @ mapper	: local pointer on the mapper.
+ * @ index	: page index in file
+ * @ returns pointer on page descriptor if success / return NULL if error.
+ ******************************************************************************************/
+struct page_s * mapper_get_page( mapper_t * mapper,
+                                 uint32_t   index );
+
+/*******************************************************************************************
+ * This function makes an I/O operation to move one page from FS to mapper.
+ * Depending on the file system type, it calls the proper, FS specific function.
+ * It must be executed by a thread running in the cluster containing the mapper.
+ *******************************************************************************************
+ * @ mapper	: local pointer on the mapper.
+ * @ index	: page index in file.
+ * @ page   : local pointer on the page descriptor in mapper. 
+ * @ returns 0 if success / return EINVAL if it cannot access the device.
+ ******************************************************************************************/
+error_t mapper_updt_page( mapper_t      * mapper,
+                          uint32_t        index,
+                          struct page_s * page );        
+              
+/*******************************************************************************************
+ * This function makes an I/0 operation to move one page from mapper to FS.
+ * Depending on the file system type, it calls the proper, FS specific function.
+ * It must be executed by a thread running in the cluster containing the mapper.
+ * It does nothing if the page is not dirty. If the page is dirty, it takes
+ * the page lock before launching the IO operation, clear the page dirty bit,
+ * and remove the page from the PPM dirty list. It does nothing if the page is not dirty.
+ *******************************************************************************************
+ * @ mapper	: local pointer on the mapper.
+ * @ index	: page index in file.
+ * @ page   : local pointer on the page descriptor in mapper. 
+ * @ returns 0 if success / return EINVAL if it cannot access the device.
+ ******************************************************************************************/
+error_t mapper_sync_page( mapper_t      * mapper,
+                          uint32_t        index,
+                          struct page_s * page );        
 
 #endif /* _MAPPER_H_ */
