/* * mapper.h - Map memory, file or device in process virtual address space. * * Authors Mohamed Lamine Karaoui (2015) * Alain Greiner (2016) * * Copyright (c) UPMC Sorbonne Universites * * This file is part of ALMOS-MKH. * * ALMOS-MKH is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2.0 of the License. * * ALMOS-MKH is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with ALMOS-MKH; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef _MAPPER_H_ #define _MAPPER_H_ #include #include #include #include #include /**** Forward declarations ****/ struct page_s; struct vfs_inode_s; /******************************************************************************************* * The mapper implements the kernel cache for a given 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/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 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 vfs_move_page_to_mapper() and vfs_move_page_from_mapper() define * the generic API used to move pages to or from the relevant file system on IOC device. * - the mapper_move() function is used to move data to or from a, possibly distributed * user buffer in user space. * - 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/inode is destroyed. ******************************************************************************************/ /******************************************************************************************* * This structure defines the mapper descriptor. ******************************************************************************************/ typedef struct mapper_s { struct vfs_inode_s * inode; /*! owner 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 */ xlist_entry_t wait_root; /*! root of list of threads waiting on mapper */ list_entry_t dirty_root; /*! root of list of dirty pages */ } mapper_t; /******************************************************************************************* * 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 */ void * buf_ptr; /*! local pointer on first byte in user buffer */ } fragment_t; /******************************************************************************************* * This function allocates physical memory for a mapper descriptor, and initializes 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 tree themselves 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 move data between a kernel mapper and an user buffer. * It must be called by a thread running in the cluster containing the mapper. * It split the data in fragments : one fragment is a set of contiguous bytes * stored in the same mapper page. * It uses "hal_uspace" accesses to move fragments to/from the user buffer. * In case of write, the dirty bit is set for all pages written in the mapper. * The offset in the file descriptor is not modified by this function. ******************************************************************************************* * @ mapper : extended pointer on local mapper. * @ to_buffer : move data from mapper to buffer if true. * @ file_offset : first byte to move in file. * @ buffer : buffer address in user space. * @ size : number of bytes to move. * returns O if success / returns EINVAL if error. ******************************************************************************************/ error_t mapper_move( mapper_t * mapper, bool_t to_buffer, uint32_t file_offset, void * buffer, uint32_t size ); /******************************************************************************************* * 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. * @ 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, struct page_s * page ); /******************************************************************************************* * This function searches 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 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 ); #endif /* _MAPPER_H_ */