| [1] | 1 | /* | 
|---|
 | 2 |  * vfs.c - Virtual File System implementation. | 
|---|
 | 3 |  * | 
|---|
 | 4 |  * Author  Mohamed Lamine Karaoui (2015) | 
|---|
| [437] | 5 |  *         Alain Greiner (2016,2017,2018) | 
|---|
| [1] | 6 |  * | 
|---|
 | 7 |  * Copyright (c) UPMC Sorbonne Universites | 
|---|
 | 8 |  * | 
|---|
 | 9 |  * This file is part of ALMOS-MKH. | 
|---|
 | 10 |  * | 
|---|
 | 11 |  * ALMOS-MKH is free software; you can redistribute it and/or modify it | 
|---|
 | 12 |  * under the terms of the GNU General Public License as published by | 
|---|
 | 13 |  * the Free Software Foundation; version 2.0 of the License. | 
|---|
 | 14 |  * | 
|---|
 | 15 |  * ALMOS-MKH is distributed in the hope that it will be useful, but | 
|---|
 | 16 |  * WITHOUT ANY WARRANTY; without even the implied warranty of | 
|---|
 | 17 |  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | 
|---|
 | 18 |  * General Public License for more details. | 
|---|
 | 19 |  * | 
|---|
 | 20 |  * You should have received a copy of the GNU General Public License | 
|---|
 | 21 |  * along with ALMOS-MKH; if not, write to the Free Software Foundation, | 
|---|
 | 22 |  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | 
|---|
 | 23 |  */ | 
|---|
 | 24 |  | 
|---|
| [14] | 25 | #include <kernel_config.h> | 
|---|
| [457] | 26 | #include <hal_kernel_types.h> | 
|---|
| [1] | 27 | #include <hal_atomic.h> | 
|---|
 | 28 | #include <hal_special.h> | 
|---|
 | 29 | #include <printk.h> | 
|---|
 | 30 | #include <list.h> | 
|---|
 | 31 | #include <xlist.h> | 
|---|
 | 32 | #include <slist.h> | 
|---|
 | 33 | #include <xhtab.h> | 
|---|
| [430] | 34 | #include <string.h> | 
|---|
| [23] | 35 | #include <rpc.h> | 
|---|
| [1] | 36 | #include <errno.h> | 
|---|
 | 37 | #include <kmem.h> | 
|---|
 | 38 | #include <mapper.h> | 
|---|
 | 39 | #include <thread.h> | 
|---|
| [337] | 40 | #include <chdev.h> | 
|---|
| [1] | 41 | #include <process.h> | 
|---|
| [568] | 42 | #include <cluster.h> | 
|---|
| [23] | 43 | #include <vfs.h> | 
|---|
| [1] | 44 | #include <fatfs.h> | 
|---|
 | 45 | #include <ramfs.h> | 
|---|
| [23] | 46 | #include <devfs.h> | 
|---|
 | 47 | #include <syscalls.h> | 
|---|
| [1] | 48 |  | 
|---|
 | 49 | ////////////////////////////////////////////////////////////////////////////////////////// | 
|---|
| [50] | 50 | //           Extern variables          | 
|---|
| [1] | 51 | ////////////////////////////////////////////////////////////////////////////////////////// | 
|---|
 | 52 |  | 
|---|
| [337] | 53 | extern vfs_ctx_t          fs_context[FS_TYPES_NR];    // allocated in kernel_init.c | 
|---|
 | 54 | extern chdev_directory_t  chdev_dir;                  // allocated in kernel_init.c   | 
|---|
| [568] | 55 | extern char *             lock_type_str[];            // allocated in kernel_init.c | 
|---|
| [50] | 56 |    | 
|---|
| [602] | 57 | /////////////////////////////////////////////////////////////////////////////////////////// | 
|---|
 | 58 | //           VFS Context related functions | 
|---|
| [1] | 59 | ////////////////////////////////////////////////////////////////////////////////////////// | 
|---|
 | 60 |  | 
|---|
| [188] | 61 | //////////////////////////////////////// | 
|---|
 | 62 | void vfs_ctx_init( vfs_fs_type_t   type, | 
|---|
 | 63 |                    uint32_t        attr, | 
|---|
 | 64 |                        uint32_t        total_clusters, | 
|---|
 | 65 |                        uint32_t        cluster_size, | 
|---|
 | 66 |                        xptr_t          vfs_root_xp, | 
|---|
 | 67 |                    void          * extend ) | 
|---|
 | 68 | { | 
|---|
 | 69 |     vfs_ctx_t * vfs_ctx = &fs_context[type]; | 
|---|
 | 70 |  | 
|---|
 | 71 |     vfs_ctx->type           = type; | 
|---|
 | 72 |     vfs_ctx->attr           = attr; | 
|---|
 | 73 |     vfs_ctx->total_clusters = total_clusters; | 
|---|
 | 74 |     vfs_ctx->cluster_size   = cluster_size; | 
|---|
 | 75 |     vfs_ctx->vfs_root_xp    = vfs_root_xp; | 
|---|
 | 76 |     vfs_ctx->extend         = extend; | 
|---|
 | 77 |  | 
|---|
| [568] | 78 |     busylock_init( &vfs_ctx->lock , LOCK_VFS_CTX ); | 
|---|
| [188] | 79 |  | 
|---|
 | 80 |     bitmap_init( vfs_ctx->bitmap , BITMAP_SIZE(CONFIG_VFS_MAX_INODES) );  | 
|---|
 | 81 | } | 
|---|
 | 82 |  | 
|---|
| [23] | 83 | //////////////////////////////////////////// | 
|---|
| [1] | 84 | error_t vfs_ctx_inum_alloc( vfs_ctx_t * ctx, | 
|---|
 | 85 |                             uint32_t  * inum ) | 
|---|
 | 86 | { | 
|---|
 | 87 |     // get lock on inum allocator | 
|---|
| [568] | 88 |     busylock_acquire( &ctx->lock ); | 
|---|
| [1] | 89 |  | 
|---|
 | 90 |     // get lid from local inum allocator | 
|---|
| [23] | 91 |     uint32_t lid = bitmap_ffc( ctx->bitmap , CONFIG_VFS_MAX_INODES ); | 
|---|
| [1] | 92 |  | 
|---|
| [473] | 93 |     if( lid == 0xFFFFFFFF )   // no more free slot => error | 
|---|
| [1] | 94 |     { | 
|---|
 | 95 |         // release lock | 
|---|
| [568] | 96 |         busylock_release( &ctx->lock ); | 
|---|
| [1] | 97 |  | 
|---|
 | 98 |         // return error | 
|---|
 | 99 |         return 1; | 
|---|
 | 100 |     } | 
|---|
 | 101 |     else              // found => return inum | 
|---|
 | 102 |     { | 
|---|
 | 103 |         // set slot allocated | 
|---|
| [23] | 104 |         bitmap_set( ctx->bitmap , lid ); | 
|---|
| [1] | 105 |  | 
|---|
 | 106 |         // release lock | 
|---|
| [568] | 107 |         busylock_release( &ctx->lock ); | 
|---|
| [1] | 108 |  | 
|---|
 | 109 |         // return inum | 
|---|
 | 110 |         *inum = (((uint32_t)local_cxy) << 16) | (lid & 0xFFFF); | 
|---|
 | 111 |         return 0; | 
|---|
 | 112 |     } | 
|---|
 | 113 | } | 
|---|
 | 114 |  | 
|---|
 | 115 | //////////////////////////////////////////// | 
|---|
 | 116 | void vfs_ctx_inum_release( vfs_ctx_t * ctx, | 
|---|
 | 117 |                            uint32_t    inum ) | 
|---|
 | 118 | { | 
|---|
| [23] | 119 |     bitmap_clear( ctx->bitmap , inum & 0xFFFF );  | 
|---|
| [1] | 120 | } | 
|---|
 | 121 |  | 
|---|
 | 122 | ////////////////////////////////////////////////////////////////////////////////////////// | 
|---|
| [602] | 123 | //           VFS inode descriptor related functions | 
|---|
| [1] | 124 | ////////////////////////////////////////////////////////////////////////////////////////// | 
|---|
 | 125 |  | 
|---|
| [598] | 126 | const char * vfs_inode_type_str( vfs_inode_type_t type ) | 
|---|
| [188] | 127 | { | 
|---|
| [598] | 128 |     switch ( type )  | 
|---|
 | 129 |     { | 
|---|
 | 130 |         case INODE_TYPE_FILE: return "FILE"; | 
|---|
 | 131 |         case INODE_TYPE_DIR:  return "DIR "; | 
|---|
 | 132 |         case INODE_TYPE_FIFO: return "FIFO"; | 
|---|
 | 133 |         case INODE_TYPE_PIPE: return "PIPE"; | 
|---|
 | 134 |         case INODE_TYPE_SOCK: return "SOCK"; | 
|---|
 | 135 |         case INODE_TYPE_DEV:  return "DEV "; | 
|---|
| [611] | 136 |         case INODE_TYPE_BLK:  return "BLK "; | 
|---|
| [598] | 137 |         case INODE_TYPE_SYML: return "SYML"; | 
|---|
 | 138 |         default:              return "undefined"; | 
|---|
| [527] | 139 |     } | 
|---|
| [188] | 140 | } | 
|---|
 | 141 |  | 
|---|
| [610] | 142 | //////////////////////////////////////////////////// | 
|---|
 | 143 | error_t vfs_inode_create( vfs_fs_type_t     fs_type, | 
|---|
| [23] | 144 |                           vfs_inode_type_t  inode_type, | 
|---|
 | 145 |                           uint32_t          attr, | 
|---|
 | 146 |                           uint32_t          rights, | 
|---|
 | 147 |                           uid_t             uid, | 
|---|
 | 148 |                           gid_t             gid, | 
|---|
 | 149 |                           xptr_t          * inode_xp ) | 
|---|
| [1] | 150 | { | 
|---|
 | 151 |     mapper_t         * mapper;     // associated mapper( to be allocated) | 
|---|
 | 152 |     vfs_inode_t      * inode;      // inode descriptor (to be allocated) | 
|---|
 | 153 |     uint32_t           inum;       // inode identifier (to be allocated) | 
|---|
 | 154 |     vfs_ctx_t        * ctx;        // file system context  | 
|---|
 | 155 |         kmem_req_t         req;        // request to kernel memory allocator | 
|---|
 | 156 |     error_t            error; | 
|---|
 | 157 |  | 
|---|
| [438] | 158 | #if DEBUG_VFS_INODE_CREATE | 
|---|
| [568] | 159 | char           name[CONFIG_VFS_MAX_NAME_LENGTH]; | 
|---|
 | 160 | uint32_t       cycle      = (uint32_t)hal_get_cycles(); | 
|---|
 | 161 | cxy_t          dentry_cxy = GET_CXY( dentry_xp ); | 
|---|
 | 162 | vfs_dentry_t * dentry_ptr = GET_PTR( dentry_xp ); | 
|---|
 | 163 | thread_t *     this       = CURRENT_THREAD; | 
|---|
 | 164 | if( dentry_xp != XPTR_NULL ) hal_remote_strcpy( XPTR( local_cxy  , name ),  | 
|---|
 | 165 |                                                 XPTR( dentry_cxy , dentry_ptr->name ) ); | 
|---|
 | 166 | else                         strcpy( name , "/" ); | 
|---|
| [438] | 167 | if( DEBUG_VFS_INODE_CREATE < cycle ) | 
|---|
| [598] | 168 | printk("\n[%s] thread[%x,%x] enter for <%s> / cycle %d\n", | 
|---|
 | 169 | __FUNCTION__, this->process->pid, this->trdid, name, cycle ); | 
|---|
| [433] | 170 | #endif | 
|---|
| [279] | 171 |   | 
|---|
| [23] | 172 |     // check fs type and get pointer on context | 
|---|
 | 173 |     if     ( fs_type == FS_TYPE_FATFS ) ctx = &fs_context[FS_TYPE_FATFS]; | 
|---|
 | 174 |     else if( fs_type == FS_TYPE_RAMFS ) ctx = &fs_context[FS_TYPE_RAMFS]; | 
|---|
 | 175 |     else if( fs_type == FS_TYPE_DEVFS ) ctx = &fs_context[FS_TYPE_DEVFS]; | 
|---|
| [1] | 176 |     else | 
|---|
 | 177 |     { | 
|---|
 | 178 |         ctx = NULL; | 
|---|
| [492] | 179 |                 assert( false , "illegal file system type = %d\n" , fs_type ); | 
|---|
| [1] | 180 |     } | 
|---|
 | 181 |  | 
|---|
 | 182 |     // allocate inum | 
|---|
 | 183 |     error = vfs_ctx_inum_alloc( ctx , &inum ); | 
|---|
 | 184 |  | 
|---|
 | 185 |     if( error ) | 
|---|
 | 186 |     { | 
|---|
 | 187 |         printk("\n[ERROR] in %s : cannot allocate inum\n", __FUNCTION__ ); | 
|---|
 | 188 |         return ENOMEM; | 
|---|
 | 189 |     } | 
|---|
 | 190 |  | 
|---|
 | 191 |     // allocate memory for mapper | 
|---|
| [246] | 192 |     mapper = mapper_create( fs_type ); | 
|---|
| [1] | 193 |  | 
|---|
 | 194 |     if( mapper == NULL ) | 
|---|
 | 195 |     { | 
|---|
 | 196 |         printk("\n[ERROR] in %s : cannot allocate mapper\n", __FUNCTION__ ); | 
|---|
 | 197 |         vfs_ctx_inum_release( ctx , inum ); | 
|---|
 | 198 |         return ENOMEM; | 
|---|
 | 199 |     } | 
|---|
 | 200 |  | 
|---|
| [23] | 201 |     // allocate memory for VFS inode descriptor | 
|---|
| [1] | 202 |         req.type  = KMEM_VFS_INODE; | 
|---|
 | 203 |         req.size  = sizeof(vfs_inode_t); | 
|---|
 | 204 |     req.flags = AF_KERNEL | AF_ZERO; | 
|---|
 | 205 |         inode     = (vfs_inode_t *)kmem_alloc( &req ); | 
|---|
 | 206 |  | 
|---|
 | 207 |     if( inode == NULL ) | 
|---|
 | 208 |     { | 
|---|
 | 209 |         printk("\n[ERROR] in %s : cannot allocate inode descriptor\n", __FUNCTION__ ); | 
|---|
 | 210 |         vfs_ctx_inum_release( ctx , inum ); | 
|---|
 | 211 |         mapper_destroy( mapper ); | 
|---|
| [610] | 212 |         return -1; | 
|---|
| [1] | 213 |     } | 
|---|
 | 214 |  | 
|---|
 | 215 |     // initialize inode descriptor | 
|---|
| [23] | 216 |     inode->type       = inode_type; | 
|---|
| [1] | 217 |     inode->inum       = inum; | 
|---|
 | 218 |     inode->attr       = attr; | 
|---|
| [23] | 219 |     inode->rights     = rights; | 
|---|
| [1] | 220 |     inode->uid        = uid; | 
|---|
 | 221 |     inode->gid        = gid; | 
|---|
 | 222 |     inode->ctx        = ctx; | 
|---|
| [246] | 223 |     inode->mapper     = mapper; | 
|---|
| [602] | 224 |     inode->extend     = NULL; | 
|---|
| [610] | 225 |     inode->links      = 0; | 
|---|
| [1] | 226 |  | 
|---|
| [246] | 227 |     // initialise inode field in mapper | 
|---|
 | 228 |     mapper->inode     = inode; | 
|---|
 | 229 |   | 
|---|
| [1] | 230 |     // initialise threads waiting queue | 
|---|
| [610] | 231 |     // xlist_root_init( XPTR( local_cxy , &inode->wait_root ) ); | 
|---|
| [1] | 232 |  | 
|---|
| [610] | 233 |     // initialize chidren dentries xhtab | 
|---|
| [204] | 234 |     xhtab_init( &inode->children , XHTAB_DENTRY_TYPE ); | 
|---|
| [1] | 235 |  | 
|---|
| [610] | 236 |     // initialize parents dentries xlist | 
|---|
 | 237 |     xlist_root_init( XPTR( local_cxy , &inode->parents ) ); | 
|---|
 | 238 |   | 
|---|
 | 239 |     // initialize lock protecting size  | 
|---|
 | 240 |     remote_rwlock_init( XPTR( local_cxy , &inode->size_lock ), LOCK_VFS_SIZE ); | 
|---|
| [1] | 241 |  | 
|---|
| [610] | 242 |     // initialise lock protecting inode tree traversal | 
|---|
 | 243 |     remote_rwlock_init( XPTR( local_cxy , &inode->main_lock ), LOCK_VFS_MAIN ); | 
|---|
| [568] | 244 |  | 
|---|
| [610] | 245 |     // return extended pointer on inode | 
|---|
 | 246 |     *inode_xp = XPTR( local_cxy , inode ); | 
|---|
 | 247 |  | 
|---|
| [438] | 248 | #if DEBUG_VFS_INODE_CREATE | 
|---|
| [568] | 249 | cycle      = (uint32_t)hal_get_cycles(); | 
|---|
| [438] | 250 | if( DEBUG_VFS_INODE_CREATE < cycle ) | 
|---|
| [598] | 251 | printk("\n[%s] thread[%x,%x] exit for <%s> / inode [%x,%x] / cycle %d\n", | 
|---|
 | 252 | __FUNCTION__, this->process->pid, this->trdid, name, local_cxy, inode, cycle ); | 
|---|
| [433] | 253 | #endif | 
|---|
| [401] | 254 |   | 
|---|
| [1] | 255 |     return 0; | 
|---|
 | 256 |  | 
|---|
 | 257 | }  // end vfs_inode_create()   | 
|---|
 | 258 |  | 
|---|
| [602] | 259 | ///////////////////////////////////////////// | 
|---|
 | 260 | void vfs_inode_destroy( vfs_inode_t * inode ) | 
|---|
| [1] | 261 | { | 
|---|
 | 262 |     // release memory allocated for mapper | 
|---|
 | 263 |     mapper_destroy( inode->mapper ); | 
|---|
 | 264 |  | 
|---|
 | 265 |     // release memory allocate for inode descriptor | 
|---|
 | 266 |         kmem_req_t req; | 
|---|
 | 267 |         req.ptr   = inode; | 
|---|
 | 268 |         req.type  = KMEM_VFS_INODE; | 
|---|
 | 269 |         kmem_free( &req ); | 
|---|
 | 270 |  | 
|---|
 | 271 | }  // end vfs_inode_destroy() | 
|---|
 | 272 |  | 
|---|
 | 273 | ////////////////////////////////////////////// | 
|---|
 | 274 | uint32_t vfs_inode_get_size( xptr_t inode_xp ) | 
|---|
 | 275 | { | 
|---|
 | 276 |     // get inode cluster and local pointer | 
|---|
 | 277 |     cxy_t         cxy = GET_CXY( inode_xp ); | 
|---|
| [473] | 278 |     vfs_inode_t * ptr = GET_PTR( inode_xp ); | 
|---|
| [1] | 279 |  | 
|---|
 | 280 |     // get size | 
|---|
| [610] | 281 |     remote_rwlock_rd_acquire( XPTR( cxy , &ptr->size_lock ) ); | 
|---|
| [568] | 282 |     uint32_t size = hal_remote_l32( XPTR( cxy , &ptr->size ) ); | 
|---|
| [610] | 283 |     remote_rwlock_rd_release( XPTR( cxy , &ptr->size_lock ) ); | 
|---|
| [1] | 284 |     return size; | 
|---|
 | 285 | } | 
|---|
 | 286 |  | 
|---|
| [101] | 287 | //////////////////////////////////////////// | 
|---|
 | 288 | void vfs_inode_set_size( xptr_t    inode_xp, | 
|---|
| [409] | 289 |                          uint32_t  size ) | 
|---|
| [1] | 290 | { | 
|---|
 | 291 |     // get inode cluster and local pointer | 
|---|
 | 292 |     cxy_t         cxy = GET_CXY( inode_xp ); | 
|---|
| [473] | 293 |     vfs_inode_t * ptr = GET_PTR( inode_xp ); | 
|---|
| [1] | 294 |  | 
|---|
 | 295 |     // set size | 
|---|
| [610] | 296 |     remote_rwlock_wr_release( XPTR( cxy , &ptr->size_lock ) ); | 
|---|
| [568] | 297 |     hal_remote_s32( XPTR( cxy , &ptr->size ) , size ); | 
|---|
| [610] | 298 |     remote_rwlock_wr_release( XPTR( cxy , &ptr->size_lock ) ); | 
|---|
| [1] | 299 | } | 
|---|
 | 300 |  | 
|---|
| [101] | 301 | //////////////////////////////////////// | 
|---|
 | 302 | void vfs_inode_unlock( xptr_t inode_xp ) | 
|---|
| [1] | 303 | { | 
|---|
 | 304 |     // get inode cluster and local pointer | 
|---|
 | 305 |     cxy_t         cxy = GET_CXY( inode_xp ); | 
|---|
| [473] | 306 |     vfs_inode_t * ptr = GET_PTR( inode_xp ); | 
|---|
| [1] | 307 |  | 
|---|
 | 308 |     // release the main lock | 
|---|
| [568] | 309 |     remote_busylock_release( XPTR( cxy , &ptr->main_lock ) ); | 
|---|
| [1] | 310 | } | 
|---|
 | 311 |  | 
|---|
| [101] | 312 | ////////////////////////////////////// | 
|---|
 | 313 | void vfs_inode_lock( xptr_t inode_xp ) | 
|---|
| [1] | 314 | { | 
|---|
 | 315 |     // get inode cluster and local pointer | 
|---|
 | 316 |     cxy_t         cxy = GET_CXY( inode_xp ); | 
|---|
| [473] | 317 |     vfs_inode_t * ptr = GET_PTR( inode_xp ); | 
|---|
| [1] | 318 |  | 
|---|
 | 319 |     // get the main lock | 
|---|
| [568] | 320 |     remote_busylock_acquire( XPTR( cxy , &ptr->main_lock ) ); | 
|---|
| [1] | 321 | } | 
|---|
 | 322 |  | 
|---|
| [610] | 323 | /////////////////////////////////////////// | 
|---|
 | 324 | void vfs_inode_get_name( xptr_t   inode_xp, | 
|---|
 | 325 |                          char   * name ) | 
|---|
| [101] | 326 | { | 
|---|
| [610] | 327 |     cxy_t          inode_cxy;          // inode cluster identifier  | 
|---|
 | 328 |     vfs_inode_t  * inode_ptr;          // local pointer on inode | 
|---|
 | 329 |     xptr_t         parents_root_xp;    // extended pointer on inode parents root | 
|---|
| [204] | 330 |      | 
|---|
 | 331 |     // get inode cluster and local pointer | 
|---|
 | 332 |     inode_cxy = GET_CXY( inode_xp ); | 
|---|
| [473] | 333 |     inode_ptr = GET_PTR( inode_xp ); | 
|---|
| [204] | 334 |  | 
|---|
| [610] | 335 |     // build extended pointer on parents dentries root | 
|---|
 | 336 |     parents_root_xp  = XPTR( inode_cxy , &inode_ptr->parents ); | 
|---|
| [204] | 337 |  | 
|---|
| [610] | 338 |     // check VFS root  | 
|---|
 | 339 |     if( xlist_is_empty( parents_root_xp ) )  // inode is the VFS root | 
|---|
| [204] | 340 |     { | 
|---|
 | 341 |         strcpy( name , "/" ); | 
|---|
 | 342 |     } | 
|---|
| [610] | 343 |     else                                     // not the VFS root | 
|---|
| [204] | 344 |     { | 
|---|
| [610] | 345 |         xptr_t         dentry_xp; | 
|---|
 | 346 |         cxy_t          dentry_cxy; | 
|---|
 | 347 |         vfs_dentry_t * dentry_ptr; | 
|---|
 | 348 |  | 
|---|
 | 349 |         // get first name in list of parents | 
|---|
 | 350 |         dentry_xp  = XLIST_FIRST( parents_root_xp , vfs_dentry_t , parents ); | 
|---|
| [204] | 351 |         dentry_cxy = GET_CXY( dentry_xp ); | 
|---|
| [473] | 352 |         dentry_ptr = GET_PTR( dentry_xp ); | 
|---|
| [204] | 353 |  | 
|---|
 | 354 |         hal_remote_strcpy( XPTR( local_cxy  , name ) ,  | 
|---|
| [610] | 355 |                            XPTR( dentry_cxy , dentry_ptr->name ) ); | 
|---|
| [204] | 356 |     } | 
|---|
| [610] | 357 |  | 
|---|
| [409] | 358 | }  // end vfs_inode_get_name() | 
|---|
| [204] | 359 |  | 
|---|
| [602] | 360 | /////////////////////////////////////////////////////// | 
|---|
 | 361 | error_t vfs_inode_load_all_pages( vfs_inode_t * inode ) | 
|---|
 | 362 | { | 
|---|
 | 363 |  | 
|---|
 | 364 | assert( (inode != NULL) , "inode pointer is NULL\n" ); | 
|---|
 | 365 |  | 
|---|
 | 366 |     uint32_t   page_id; | 
|---|
 | 367 |     xptr_t     page_xp; | 
|---|
 | 368 |  | 
|---|
 | 369 |     mapper_t * mapper = inode->mapper; | 
|---|
 | 370 |     uint32_t   size   = inode->size; | 
|---|
 | 371 |  | 
|---|
 | 372 | assert( (mapper != NULL) , "mapper pointer is NULL\n" ); | 
|---|
 | 373 |  | 
|---|
 | 374 | #if DEBUG_VFS_INODE_LOAD_ALL | 
|---|
 | 375 | uint32_t   cycle = (uint32_t)hal_get_cycles(); | 
|---|
 | 376 | thread_t * this  = CURRENT_THREAD; | 
|---|
 | 377 | char       name[CONFIG_VFS_MAX_NAME_LENGTH]; | 
|---|
 | 378 | vfs_inode_get_name( XPTR( local_cxy , inode ) , name ); | 
|---|
 | 379 | if( DEBUG_VFS_INODE_LOAD_ALL < cycle ) | 
|---|
 | 380 | printk("\n[%s] thread[%x,%x] enter for <%s> in cluster %x / cycle %d\n", | 
|---|
 | 381 | __FUNCTION__, this->process->pid, this->trdid, name, local_cxy, cycle ); | 
|---|
 | 382 | #endif | 
|---|
 | 383 |  | 
|---|
 | 384 |     // compute number of pages | 
|---|
 | 385 |     uint32_t npages = size >> CONFIG_PPM_PAGE_SHIFT; | 
|---|
 | 386 |     if( (size & CONFIG_PPM_PAGE_MASK) || (size == 0) ) npages++; | 
|---|
 | 387 |  | 
|---|
 | 388 |     // loop on pages  | 
|---|
 | 389 |     for( page_id = 0 ; page_id < npages ; page_id ++ ) | 
|---|
 | 390 |     { | 
|---|
 | 391 |         // If the mage is missing, this function allocates the missing page, | 
|---|
 | 392 |         // and load the page from IOC device into mapper | 
|---|
 | 393 |         page_xp = mapper_remote_get_page( XPTR( local_cxy , mapper ), page_id ); | 
|---|
 | 394 |  | 
|---|
 | 395 |         if( page_xp == XPTR_NULL ) return -1; | 
|---|
 | 396 |     } | 
|---|
 | 397 |  | 
|---|
 | 398 | #if DEBUG_VFS_INODE_LOAD_ALL | 
|---|
 | 399 | cycle = (uint32_t)hal_get_cycles(); | 
|---|
 | 400 | if( DEBUG_VFS_INODE_LOAD_ALL < cycle ) | 
|---|
 | 401 | printk("\n[%s] thread[%x,%x] exit for <%x> in cluster %x / cycle %d\n", | 
|---|
 | 402 | __FUNCTION__, this->process->pid, this->trdid, name, local_cxy, cycle ); | 
|---|
 | 403 | #endif | 
|---|
 | 404 |  | 
|---|
 | 405 |     return 0; | 
|---|
 | 406 |  | 
|---|
 | 407 | }  // end vfs_inode_load_all_pages() | 
|---|
 | 408 |  | 
|---|
| [204] | 409 | //////////////////////////////////////////////////////////////////////////////////////////// | 
|---|
| [602] | 410 | //          VFS dentry descriptor related functions | 
|---|
| [1] | 411 | ////////////////////////////////////////////////////////////////////////////////////////// | 
|---|
 | 412 |  | 
|---|
| [23] | 413 | /////////////////////////////////////////////////// | 
|---|
 | 414 | error_t vfs_dentry_create( vfs_fs_type_t   fs_type, | 
|---|
 | 415 |                            char          * name, | 
|---|
 | 416 |                            xptr_t        * dentry_xp ) | 
|---|
| [1] | 417 | { | 
|---|
 | 418 |     vfs_ctx_t      * ctx;        // context descriptor | 
|---|
 | 419 |     vfs_dentry_t   * dentry;     // dentry descriptor (to be allocated) | 
|---|
 | 420 |         kmem_req_t       req;        // request to kernel memory allocator | 
|---|
 | 421 |  | 
|---|
| [438] | 422 | #if DEBUG_VFS_DENTRY_CREATE | 
|---|
| [598] | 423 | thread_t * this = CURRENT_THREAD; | 
|---|
| [433] | 424 | uint32_t cycle = (uint32_t)hal_get_cycles(); | 
|---|
| [438] | 425 | if( DEBUG_VFS_DENTRY_CREATE < cycle ) | 
|---|
| [614] | 426 | printk("\n[%s] thread[%x,%x] enter for <%s> / cycle %d\n", | 
|---|
 | 427 | __FUNCTION__, this->process->pid, this->trdid, name, cycle ); | 
|---|
| [433] | 428 | #endif | 
|---|
| [296] | 429 |  | 
|---|
| [188] | 430 |     // get pointer on context | 
|---|
| [23] | 431 |     if     ( fs_type == FS_TYPE_FATFS ) ctx = &fs_context[FS_TYPE_FATFS]; | 
|---|
 | 432 |     else if( fs_type == FS_TYPE_RAMFS ) ctx = &fs_context[FS_TYPE_RAMFS]; | 
|---|
 | 433 |     else if( fs_type == FS_TYPE_DEVFS ) ctx = &fs_context[FS_TYPE_DEVFS]; | 
|---|
| [459] | 434 |     else  | 
|---|
| [1] | 435 |     { | 
|---|
 | 436 |         ctx = NULL; | 
|---|
| [610] | 437 |         return -1; | 
|---|
| [1] | 438 |     } | 
|---|
 | 439 |  | 
|---|
 | 440 |     // get name length | 
|---|
 | 441 |     uint32_t length = strlen( name ); | 
|---|
 | 442 |  | 
|---|
| [459] | 443 |     if( length >= CONFIG_VFS_MAX_NAME_LENGTH ) return EINVAL; | 
|---|
| [437] | 444 |  | 
|---|
| [1] | 445 |     // allocate memory for dentry descriptor | 
|---|
 | 446 |         req.type  = KMEM_VFS_DENTRY; | 
|---|
 | 447 |         req.size  = sizeof(vfs_dentry_t); | 
|---|
 | 448 |     req.flags = AF_KERNEL | AF_ZERO; | 
|---|
 | 449 |         dentry     = (vfs_dentry_t *)kmem_alloc( &req ); | 
|---|
 | 450 |  | 
|---|
| [610] | 451 |     if( dentry == NULL )  | 
|---|
 | 452 |     { | 
|---|
 | 453 |         printk("\n[ERROR] in %s : cannot allocate dentry descriptor\n", | 
|---|
 | 454 |         __FUNCTION__ ); | 
|---|
 | 455 |         return -1; | 
|---|
 | 456 |     } | 
|---|
| [437] | 457 |  | 
|---|
| [1] | 458 |     // initialize dentry descriptor | 
|---|
 | 459 |     dentry->ctx     = ctx; | 
|---|
 | 460 |     dentry->length  = length; | 
|---|
| [602] | 461 |     dentry->extend  = NULL; | 
|---|
| [1] | 462 |     strcpy( dentry->name , name ); | 
|---|
 | 463 |  | 
|---|
| [23] | 464 |     // return extended pointer on dentry  | 
|---|
| [1] | 465 |     *dentry_xp = XPTR( local_cxy , dentry ); | 
|---|
 | 466 |  | 
|---|
| [438] | 467 | #if DEBUG_VFS_DENTRY_CREATE | 
|---|
| [433] | 468 | cycle = (uint32_t)hal_get_cycles(); | 
|---|
| [438] | 469 | if( DEBUG_VFS_DENTRY_CREATE < cycle ) | 
|---|
| [602] | 470 | printk("\n[%s] thread[%x,%x] exit for <%s> / dentry [%x,%x] / cycle %d\n", | 
|---|
 | 471 | __FUNCTION__, this->process->pid, this->trdid, name, local_cxy, dentry, cycle ); | 
|---|
| [433] | 472 | #endif | 
|---|
| [296] | 473 |  | 
|---|
| [1] | 474 |     return 0; | 
|---|
 | 475 |  | 
|---|
 | 476 | }  // end vfs_dentry_create() | 
|---|
 | 477 |  | 
|---|
| [602] | 478 | //////////////////////////////////////////////// | 
|---|
 | 479 | void vfs_dentry_destroy( vfs_dentry_t * dentry ) | 
|---|
| [1] | 480 | { | 
|---|
| [459] | 481 |     // release memory allocated to dentry | 
|---|
| [1] | 482 |         kmem_req_t req; | 
|---|
 | 483 |         req.ptr   = dentry; | 
|---|
 | 484 |         req.type  = KMEM_VFS_DENTRY; | 
|---|
 | 485 |         kmem_free( &req ); | 
|---|
| [459] | 486 |  | 
|---|
| [602] | 487 | }  // end vfs_dentry_destroy() | 
|---|
 | 488 |  | 
|---|
 | 489 |  | 
|---|
| [1] | 490 | ////////////////////////////////////////////////////////////////////////////////////////// | 
|---|
| [602] | 491 | //       VFS file descriptor related functions | 
|---|
| [1] | 492 | ////////////////////////////////////////////////////////////////////////////////////////// | 
|---|
 | 493 |  | 
|---|
| [23] | 494 | ///////////////////////////////////////////// | 
|---|
 | 495 | error_t vfs_file_create( vfs_inode_t * inode, | 
|---|
 | 496 |                          uint32_t      attr, | 
|---|
 | 497 |                          xptr_t      * file_xp ) | 
|---|
 | 498 | { | 
|---|
 | 499 |     vfs_file_t  * file; | 
|---|
 | 500 |         kmem_req_t    req; | 
|---|
 | 501 |  | 
|---|
| [568] | 502 | #if DEBUG_VFS_FILE_CREATE | 
|---|
| [598] | 503 | thread_t * this = CURRENT_THREAD; | 
|---|
| [568] | 504 | uint32_t cycle = (uint32_t)hal_get_cycles(); | 
|---|
 | 505 | if( DEBUG_VFS_OPEN < cycle ) | 
|---|
| [598] | 506 | printk("\n[%s] thread[%x,%x] enter for inode %x in cluster %x / cycle %d\n", | 
|---|
 | 507 | __FUNCTION__, this->process->pid, this->trdid, inode, local_cxy, cycle ); | 
|---|
| [568] | 508 | #endif | 
|---|
 | 509 |  | 
|---|
| [23] | 510 |     // allocate memory for new file descriptor | 
|---|
 | 511 |         req.type  = KMEM_VFS_FILE; | 
|---|
 | 512 |         req.size  = sizeof(vfs_file_t); | 
|---|
 | 513 |     req.flags = AF_KERNEL | AF_ZERO; | 
|---|
 | 514 |         file      = (vfs_file_t *)kmem_alloc( &req ); | 
|---|
 | 515 |  | 
|---|
 | 516 |     if( file == NULL ) return ENOMEM; | 
|---|
 | 517 |  | 
|---|
 | 518 |     // initializes new file descriptor | 
|---|
 | 519 |     file->gc       = 0; | 
|---|
 | 520 |     file->type     = inode->type; | 
|---|
 | 521 |     file->attr     = attr; | 
|---|
 | 522 |     file->offset   = 0; | 
|---|
| [337] | 523 |     file->refcount = 1; | 
|---|
| [23] | 524 |     file->inode    = inode; | 
|---|
 | 525 |     file->ctx      = inode->ctx; | 
|---|
 | 526 |     file->mapper   = inode->mapper; | 
|---|
 | 527 |  | 
|---|
| [568] | 528 |     remote_rwlock_init( XPTR( local_cxy , &file->lock ), LOCK_VFS_FILE ); | 
|---|
| [23] | 529 |  | 
|---|
 | 530 |     *file_xp = XPTR( local_cxy , file ); | 
|---|
| [459] | 531 |  | 
|---|
| [568] | 532 | #if DEBUG_VFS_FILE_CREATE | 
|---|
 | 533 | cycle = (uint32_t)hal_get_cycles(); | 
|---|
| [459] | 534 | if( DEBUG_VFS_OPEN < cycle ) | 
|---|
| [598] | 535 | printk("\n[%s] thread[%x,%x] created file %x in cluster %x / cycle %d\n", | 
|---|
 | 536 | __FUNCTION__, this->process->pid, this->trdid, file, local_cxy, cycle ); | 
|---|
| [459] | 537 | #endif | 
|---|
 | 538 |  | 
|---|
| [23] | 539 |     return 0; | 
|---|
 | 540 |  | 
|---|
 | 541 | }  // end vfs_file_create() | 
|---|
 | 542 |  | 
|---|
 | 543 | /////////////////////////////////////////// | 
|---|
 | 544 | void vfs_file_destroy( vfs_file_t *  file ) | 
|---|
 | 545 | { | 
|---|
 | 546 |  | 
|---|
| [610] | 547 | // check refcount | 
|---|
 | 548 | assert( (file->refcount == 0) , "refcount non zero\n" ); | 
|---|
 | 549 |  | 
|---|
| [23] | 550 |         kmem_req_t req; | 
|---|
 | 551 |         req.ptr   = file; | 
|---|
 | 552 |         req.type  = KMEM_VFS_FILE; | 
|---|
 | 553 |         kmem_free( &req ); | 
|---|
 | 554 |  | 
|---|
| [459] | 555 | #if DEBUG_VFS_CLOSE | 
|---|
| [598] | 556 | thread_t * this = CURRENT_THREAD; | 
|---|
| [459] | 557 | uint32_t cycle = (uint32_t)hal_get_cycles(); | 
|---|
 | 558 | if( DEBUG_VFS_CLOSE < cycle ) | 
|---|
| [598] | 559 | printk("\n[%s] thread[%x,%x] deleted file %x in cluster %x / cycle %d\n", | 
|---|
 | 560 | __FUNCTION__, this->process->pid, this->trdid, file, local_cxy, cycle ); | 
|---|
| [459] | 561 | #endif | 
|---|
 | 562 |  | 
|---|
| [23] | 563 | }  // end vfs_file_destroy()  | 
|---|
 | 564 |  | 
|---|
 | 565 |  | 
|---|
| [1] | 566 | //////////////////////////////////////// | 
|---|
 | 567 | void vfs_file_count_up( xptr_t file_xp ) | 
|---|
 | 568 | { | 
|---|
 | 569 |     // get file cluster and local pointer | 
|---|
 | 570 |     cxy_t        file_cxy = GET_CXY( file_xp ); | 
|---|
| [459] | 571 |     vfs_file_t * file_ptr = GET_PTR( file_xp );  | 
|---|
| [1] | 572 |  | 
|---|
 | 573 |     // atomically increment count | 
|---|
 | 574 |     hal_remote_atomic_add( XPTR( file_cxy , &file_ptr->refcount ) , 1 );  | 
|---|
 | 575 | } | 
|---|
 | 576 |  | 
|---|
 | 577 | ////////////////////////////////////////// | 
|---|
 | 578 | void vfs_file_count_down( xptr_t file_xp ) | 
|---|
 | 579 | { | 
|---|
 | 580 |     // get file cluster and local pointer | 
|---|
 | 581 |     cxy_t        file_cxy = GET_CXY( file_xp ); | 
|---|
| [459] | 582 |     vfs_file_t * file_ptr = GET_PTR( file_xp );  | 
|---|
| [1] | 583 |  | 
|---|
 | 584 |     // atomically decrement count | 
|---|
 | 585 |     hal_remote_atomic_add( XPTR( file_cxy , &file_ptr->refcount ) , -1 );  | 
|---|
 | 586 | } | 
|---|
 | 587 |  | 
|---|
| [23] | 588 | ////////////////////////////////////////////////////////////////////////////////////////// | 
|---|
| [602] | 589 | //           "syscalls" API related functions | 
|---|
| [23] | 590 | ////////////////////////////////////////////////////////////////////////////////////////// | 
|---|
 | 591 |  | 
|---|
| [407] | 592 | ////////////////////////////////////// | 
|---|
| [610] | 593 | error_t vfs_open( xptr_t      root_xp, | 
|---|
| [407] | 594 |                           char      * path, | 
|---|
| [610] | 595 |                   xptr_t      process_xp, | 
|---|
| [407] | 596 |                           uint32_t    flags, | 
|---|
 | 597 |                   uint32_t    mode,  | 
|---|
 | 598 |                           xptr_t    * new_file_xp, | 
|---|
 | 599 |                   uint32_t  * new_file_id ) | 
|---|
| [1] | 600 | { | 
|---|
| [610] | 601 |     error_t        error; | 
|---|
 | 602 |     xptr_t         inode_xp;       // extended pointer on target inode | 
|---|
 | 603 |     cxy_t          inode_cxy;      // inode cluster identifier        | 
|---|
 | 604 |     vfs_inode_t  * inode_ptr;      // inode local pointer | 
|---|
 | 605 |     uint32_t       file_attr;      // file descriptor attributes | 
|---|
 | 606 |     uint32_t       lookup_mode;    // lookup working mode         | 
|---|
 | 607 |     xptr_t         file_xp;        // extended pointer on created file descriptor | 
|---|
 | 608 |     uint32_t       file_id;        // created file descriptor index in reference fd_array | 
|---|
 | 609 |     xptr_t         vfs_root_xp;    // extended pointer on VFS root inode | 
|---|
 | 610 |     vfs_inode_t  * vfs_root_ptr;   // local pointer on VFS root inode | 
|---|
 | 611 |     cxy_t          vfs_root_cxy;   // VFS root inode cluster identifier | 
|---|
 | 612 |     xptr_t         lock_xp;        // extended pointer on Inode Tree lock  | 
|---|
| [1] | 613 |  | 
|---|
| [602] | 614 |     if( mode != 0 ) | 
|---|
 | 615 |     { | 
|---|
 | 616 |         printk("\n[ERROR] in %s : the mode parameter is not supported yet\n" ); | 
|---|
 | 617 |         return -1; | 
|---|
 | 618 |     } | 
|---|
 | 619 |  | 
|---|
| [610] | 620 |     thread_t  * this    = CURRENT_THREAD; | 
|---|
 | 621 |     process_t * process = this->process; | 
|---|
 | 622 |  | 
|---|
| [438] | 623 | #if DEBUG_VFS_OPEN | 
|---|
| [433] | 624 | uint32_t cycle = (uint32_t)hal_get_cycles(); | 
|---|
| [438] | 625 | if( DEBUG_VFS_OPEN < cycle ) | 
|---|
| [610] | 626 | printk("\n[%s] thread[%x,%x] enter for <%s> / root_inode (%x,%x) / cycle %d\n", | 
|---|
 | 627 | __FUNCTION__, process->pid, this->trdid, path, GET_CXY(root_xp), GET_PTR(root_xp), cycle ); | 
|---|
| [433] | 628 | #endif | 
|---|
| [101] | 629 |  | 
|---|
| [23] | 630 |     // compute lookup working mode | 
|---|
 | 631 |     lookup_mode = VFS_LOOKUP_OPEN; | 
|---|
 | 632 |     if( (flags & O_DIR    )      )  lookup_mode |= VFS_LOOKUP_DIR; | 
|---|
 | 633 |     if( (flags & O_CREAT  )      )  lookup_mode |= VFS_LOOKUP_CREATE; | 
|---|
 | 634 |     if( (flags & O_EXCL   )      )  lookup_mode |= VFS_LOOKUP_EXCL; | 
|---|
 | 635 |   | 
|---|
 | 636 |     // compute attributes for the created file | 
|---|
 | 637 |     file_attr = 0; | 
|---|
| [407] | 638 |     if( (flags & O_RDONLY ) == 0 )  file_attr |= FD_ATTR_WRITE_ENABLE; | 
|---|
 | 639 |     if( (flags & O_WRONLY ) == 0 )  file_attr |= FD_ATTR_READ_ENABLE; | 
|---|
| [23] | 640 |     if( (flags & O_SYNC   )      )  file_attr |= FD_ATTR_SYNC; | 
|---|
 | 641 |     if( (flags & O_APPEND )      )  file_attr |= FD_ATTR_APPEND; | 
|---|
 | 642 |     if( (flags & O_CLOEXEC)      )  file_attr |= FD_ATTR_CLOSE_EXEC; | 
|---|
| [1] | 643 |  | 
|---|
| [610] | 644 |     // build extended pointer on lock protecting Inode Tree | 
|---|
 | 645 |     vfs_root_xp  = process->vfs_root_xp; | 
|---|
 | 646 |     vfs_root_ptr = GET_PTR( vfs_root_xp ); | 
|---|
 | 647 |     vfs_root_cxy = GET_CXY( vfs_root_xp ); | 
|---|
 | 648 |     lock_xp      = XPTR( vfs_root_cxy , &vfs_root_ptr->main_lock ); | 
|---|
 | 649 |  | 
|---|
 | 650 |     // take lock protecting Inode Tree in read mode | 
|---|
 | 651 |     remote_rwlock_rd_acquire( lock_xp ); | 
|---|
 | 652 |  | 
|---|
| [23] | 653 |     // get extended pointer on target inode | 
|---|
| [610] | 654 |     error = vfs_lookup( root_xp, | 
|---|
 | 655 |                         path, | 
|---|
 | 656 |                         lookup_mode, | 
|---|
 | 657 |                         &inode_xp, | 
|---|
 | 658 |                         NULL ); | 
|---|
| [23] | 659 |  | 
|---|
| [610] | 660 |     // release lock protecting Inode Tree | 
|---|
 | 661 |     remote_rwlock_rd_release( lock_xp ); | 
|---|
| [23] | 662 |  | 
|---|
| [610] | 663 |     if( error ) | 
|---|
 | 664 |     { | 
|---|
 | 665 |         printk("\n[ERROR] in %s : cannot get inode <%s>\n", | 
|---|
 | 666 |         __FUNCTION__ , path ); | 
|---|
 | 667 |         return -1; | 
|---|
 | 668 |     } | 
|---|
 | 669 |  | 
|---|
| [23] | 670 |     // get target inode cluster and local pointer | 
|---|
 | 671 |     inode_cxy = GET_CXY( inode_xp ); | 
|---|
| [473] | 672 |     inode_ptr = GET_PTR( inode_xp ); | 
|---|
| [23] | 673 |      | 
|---|
| [610] | 674 | #if (DEBUG_VFS_OPEN & 1) | 
|---|
 | 675 | cycle = (uint32_t)hal_get_cycles(); | 
|---|
 | 676 | if( DEBUG_VFS_OPEN < cycle ) | 
|---|
 | 677 | printk("\n[%s] thread[%x,%x] found inode(%x,%x) for <%s>\n", | 
|---|
 | 678 | __FUNCTION__, process->pid, this->trdid, inode_cxy, inode_ptr, path ); | 
|---|
 | 679 | #endif | 
|---|
 | 680 |  | 
|---|
| [23] | 681 |     // create a new file descriptor in cluster containing inode | 
|---|
 | 682 |     if( inode_cxy == local_cxy )      // target cluster is local | 
|---|
| [1] | 683 |     { | 
|---|
| [23] | 684 |         error = vfs_file_create( inode_ptr , file_attr , &file_xp ); | 
|---|
| [1] | 685 |     } | 
|---|
| [23] | 686 |     else                              // target cluster is remote | 
|---|
 | 687 |     { | 
|---|
 | 688 |         rpc_vfs_file_create_client( inode_cxy , inode_ptr , file_attr , &file_xp , &error ); | 
|---|
 | 689 |     } | 
|---|
| [1] | 690 |  | 
|---|
| [23] | 691 |     if( error )  return error; | 
|---|
| [1] | 692 |  | 
|---|
| [610] | 693 | #if (DEBUG_VFS_OPEN & 1) | 
|---|
 | 694 | cycle = (uint32_t)hal_get_cycles(); | 
|---|
 | 695 | if( DEBUG_VFS_OPEN < cycle ) | 
|---|
 | 696 | printk("\n[%s] thread[%x,%x] created file descriptor (%x,%x) for <%s>\n", | 
|---|
 | 697 | __FUNCTION__, process->pid, this->trdid, GET_CXY(file_xp), GET_PTR(file_xp), path ); | 
|---|
 | 698 | #endif | 
|---|
 | 699 |  | 
|---|
| [407] | 700 |     // allocate and register a new file descriptor index in reference process | 
|---|
| [610] | 701 |     error = process_fd_register( process_xp , file_xp , &file_id ); | 
|---|
| [1] | 702 |  | 
|---|
| [23] | 703 |     if( error ) return error; | 
|---|
| [1] | 704 |  | 
|---|
| [438] | 705 | #if DEBUG_VFS_OPEN | 
|---|
| [433] | 706 | cycle = (uint32_t)hal_get_cycles(); | 
|---|
| [438] | 707 | if( DEBUG_VFS_OPEN < cycle ) | 
|---|
| [610] | 708 | printk("\n[%s] thread[%x,%x] exit for <%s> / fdid %d / cluster %x / cycle %d\n", | 
|---|
 | 709 | __FUNCTION__, process->pid, this->trdid, path, file_id, GET_CXY( file_xp ), cycle ); | 
|---|
| [433] | 710 | #endif | 
|---|
| [238] | 711 |  | 
|---|
| [23] | 712 |     // success | 
|---|
 | 713 |     *new_file_xp = file_xp; | 
|---|
 | 714 |     *new_file_id = file_id; | 
|---|
 | 715 |     return 0; | 
|---|
| [1] | 716 |  | 
|---|
| [23] | 717 | }  // end vfs_open() | 
|---|
 | 718 |  | 
|---|
| [407] | 719 | ////////////////////////////////////// | 
|---|
 | 720 | int vfs_user_move( bool_t   to_buffer, | 
|---|
 | 721 |                    xptr_t   file_xp, | 
|---|
 | 722 |                    void   * buffer, | 
|---|
 | 723 |                    uint32_t size ) | 
|---|
| [23] | 724 | { | 
|---|
 | 725 |     cxy_t              file_cxy;     // remote file descriptor cluster  | 
|---|
 | 726 |     vfs_file_t       * file_ptr;     // remote file descriptor local pointer | 
|---|
 | 727 |     vfs_inode_type_t   inode_type; | 
|---|
 | 728 |     uint32_t           file_offset;  // current offset in file | 
|---|
 | 729 |     mapper_t         * mapper; | 
|---|
 | 730 |     error_t            error; | 
|---|
 | 731 |  | 
|---|
| [602] | 732 | // check argument | 
|---|
 | 733 | assert( (file_xp != XPTR_NULL), "file_xp == XPTR_NULL\n" ); | 
|---|
 | 734 |  | 
|---|
| [23] | 735 |     // get cluster and local pointer on remote file descriptor | 
|---|
 | 736 |     file_cxy  = GET_CXY( file_xp ); | 
|---|
| [473] | 737 |     file_ptr  = GET_PTR( file_xp ); | 
|---|
| [23] | 738 |  | 
|---|
 | 739 |     // get inode type from remote file descriptor | 
|---|
| [568] | 740 |     inode_type = hal_remote_l32( XPTR( file_cxy , &file_ptr->type   ) ); | 
|---|
| [23] | 741 |     | 
|---|
| [602] | 742 | // check inode type | 
|---|
 | 743 | assert( (inode_type == INODE_TYPE_FILE), "inode type is not INODE_TYPE_FILE" ); | 
|---|
| [23] | 744 |  | 
|---|
| [407] | 745 |     // get mapper pointer and file offset from file descriptor | 
|---|
| [568] | 746 |     file_offset = hal_remote_l32( XPTR( file_cxy , &file_ptr->offset ) ); | 
|---|
| [407] | 747 |     mapper = (mapper_t *)hal_remote_lpt( XPTR( file_cxy , &file_ptr->mapper ) ); | 
|---|
| [23] | 748 |  | 
|---|
| [407] | 749 |     // move data between mapper and buffer | 
|---|
| [610] | 750 |     error = mapper_move_user( XPTR( file_cxy , mapper ), | 
|---|
 | 751 |                               to_buffer, | 
|---|
 | 752 |                               file_offset, | 
|---|
 | 753 |                               buffer, | 
|---|
 | 754 |                               size ); | 
|---|
| [407] | 755 |  | 
|---|
| [602] | 756 |     // update file offset in file descriptor | 
|---|
 | 757 |     hal_remote_atomic_add( XPTR( file_cxy , &file_ptr->offset ) , size ); | 
|---|
| [407] | 758 |  | 
|---|
| [602] | 759 |     if( error )  | 
|---|
 | 760 |     { | 
|---|
 | 761 |         return -1; | 
|---|
 | 762 |     } | 
|---|
 | 763 |  | 
|---|
 | 764 |     return size; | 
|---|
 | 765 |  | 
|---|
| [313] | 766 | }  // end vfs_user_move() | 
|---|
| [23] | 767 |  | 
|---|
| [317] | 768 | //////////////////////////////////////////// | 
|---|
 | 769 | error_t vfs_kernel_move( bool_t   to_buffer, | 
|---|
 | 770 |                          xptr_t   file_xp, | 
|---|
 | 771 |                          xptr_t   buffer_xp, | 
|---|
 | 772 |                          uint32_t size ) | 
|---|
 | 773 | { | 
|---|
 | 774 |     cxy_t              file_cxy;     // remote file descriptor cluster  | 
|---|
 | 775 |     vfs_file_t       * file_ptr;     // remote file descriptor local pointer | 
|---|
| [602] | 776 |     vfs_inode_type_t   inode_type;   // remote file type | 
|---|
| [317] | 777 |     uint32_t           file_offset;  // current offset in file | 
|---|
| [602] | 778 |     mapper_t         * mapper_ptr;   // remote mapper local pointer | 
|---|
 | 779 |     xptr_t             mapper_xp;    // remote mapper extended pointer | 
|---|
| [317] | 780 |     error_t            error; | 
|---|
 | 781 |  | 
|---|
| [602] | 782 | // check argument | 
|---|
 | 783 | assert( (file_xp != XPTR_NULL) , "file_xp == XPTR_NULL\n" ); | 
|---|
 | 784 |  | 
|---|
| [317] | 785 |     // get cluster and local pointer on remote file descriptor | 
|---|
 | 786 |     file_cxy  = GET_CXY( file_xp ); | 
|---|
| [473] | 787 |     file_ptr  = GET_PTR( file_xp ); | 
|---|
| [317] | 788 |  | 
|---|
 | 789 |     // get inode type from remote file descriptor | 
|---|
| [568] | 790 |     inode_type = hal_remote_l32( XPTR( file_cxy , &file_ptr->type   ) ); | 
|---|
| [610] | 791 |  | 
|---|
| [317] | 792 |     // action depends on inode type | 
|---|
 | 793 |     if( inode_type == INODE_TYPE_FILE ) | 
|---|
 | 794 |     { | 
|---|
| [602] | 795 |         // get mapper pointers and file offset from file descriptor | 
|---|
| [568] | 796 |         file_offset = hal_remote_l32( XPTR( file_cxy , &file_ptr->offset ) ); | 
|---|
| [602] | 797 |         mapper_ptr  = hal_remote_lpt( XPTR( file_cxy , &file_ptr->mapper ) ); | 
|---|
 | 798 |         mapper_xp   = XPTR( file_cxy , mapper_ptr ); | 
|---|
| [317] | 799 |  | 
|---|
 | 800 |         // move data between mapper and buffer | 
|---|
| [602] | 801 |         error = mapper_move_kernel( mapper_xp, | 
|---|
 | 802 |                                     to_buffer, | 
|---|
 | 803 |                                     file_offset, | 
|---|
 | 804 |                                     buffer_xp, | 
|---|
 | 805 |                                     size ); | 
|---|
| [317] | 806 |         if( error ) return -1; | 
|---|
 | 807 |     } | 
|---|
 | 808 |     else  | 
|---|
 | 809 |     { | 
|---|
 | 810 |         printk("\n[ERROR] in %s : inode is not a file", __FUNCTION__ ); | 
|---|
 | 811 |         return -1; | 
|---|
 | 812 |     } | 
|---|
| [602] | 813 |  | 
|---|
 | 814 |     return 0; | 
|---|
 | 815 |  | 
|---|
| [317] | 816 | }  // end vfs_kernel_move() | 
|---|
 | 817 |  | 
|---|
| [23] | 818 | ////////////////////////////////////// | 
|---|
 | 819 | error_t vfs_lseek( xptr_t     file_xp, | 
|---|
 | 820 |                    uint32_t   offset, | 
|---|
 | 821 |                    uint32_t   whence,  | 
|---|
 | 822 |                    uint32_t * new_offset ) | 
|---|
 | 823 | { | 
|---|
| [266] | 824 |     xptr_t         offset_xp; | 
|---|
 | 825 |     xptr_t         lock_xp; | 
|---|
| [602] | 826 |     xptr_t         size_xp; | 
|---|
| [266] | 827 |     cxy_t          file_cxy; | 
|---|
 | 828 |     vfs_file_t  *  file_ptr; | 
|---|
 | 829 |     vfs_inode_t *  inode_ptr; | 
|---|
 | 830 |     uint32_t       new; | 
|---|
 | 831 |  | 
|---|
| [602] | 832 | // check argument | 
|---|
 | 833 | assert( (file_xp != XPTR_NULL) , "file_xp == XPTR_NULL\n" ); | 
|---|
| [266] | 834 |  | 
|---|
 | 835 |     // get cluster and local pointer on remote file descriptor | 
|---|
 | 836 |     file_cxy = GET_CXY( file_xp ); | 
|---|
| [473] | 837 |     file_ptr = GET_PTR( file_xp ); | 
|---|
| [266] | 838 |  | 
|---|
| [602] | 839 |     // get local pointer on remote inode | 
|---|
 | 840 |     inode_ptr = (vfs_inode_t *)hal_remote_lpt( XPTR( file_cxy , &file_ptr->inode ) ); | 
|---|
 | 841 |  | 
|---|
 | 842 |     // build extended pointers on lock, offset and size | 
|---|
| [266] | 843 |     offset_xp = XPTR( file_cxy , &file_ptr->offset ); | 
|---|
 | 844 |     lock_xp   = XPTR( file_cxy , &file_ptr->lock ); | 
|---|
| [602] | 845 |     size_xp   = XPTR( file_cxy , &inode_ptr->size ); | 
|---|
| [266] | 846 |  | 
|---|
 | 847 |     // take file descriptor lock | 
|---|
| [568] | 848 |     remote_rwlock_wr_acquire( lock_xp ); | 
|---|
| [266] | 849 |  | 
|---|
 | 850 |     if      ( whence == SEEK_CUR )   // new = current + offset | 
|---|
 | 851 |     { | 
|---|
| [568] | 852 |         new = hal_remote_l32( offset_xp ) + offset; | 
|---|
| [266] | 853 |     } | 
|---|
 | 854 |     else if ( whence == SEEK_SET )   // new = offset | 
|---|
 | 855 |     { | 
|---|
 | 856 |         new = offset; | 
|---|
 | 857 |     } | 
|---|
 | 858 |     else if ( whence == SEEK_END )   // new = size + offset | 
|---|
 | 859 |     {  | 
|---|
| [602] | 860 |         new = hal_remote_l32( size_xp ) + offset; | 
|---|
| [266] | 861 |     } | 
|---|
 | 862 |     else | 
|---|
 | 863 |     { | 
|---|
 | 864 |         printk("\n[ERROR] in %s : illegal whence value\n", __FUNCTION__ ); | 
|---|
| [568] | 865 |         remote_rwlock_wr_release( lock_xp ); | 
|---|
| [266] | 866 |         return -1; | 
|---|
 | 867 |     } | 
|---|
 | 868 |  | 
|---|
| [602] | 869 | #if DEBUG_VFS_LSEEK | 
|---|
 | 870 | uint32_t   cycle = (uint32_t)hal_get_cycles(); | 
|---|
 | 871 | thread_t * this  = CURRENT_THREAD; | 
|---|
 | 872 | char       name[CONFIG_VFS_MAX_NAME_LENGTH]; | 
|---|
 | 873 | vfs_inode_get_name( XPTR( file_cxy , inode_ptr ) , name ); | 
|---|
 | 874 | if( cycle > DEBUG_VFS_LSEEK ) | 
|---|
 | 875 | printk("\n[%s] thread[%x,%x] for <%s> / new offset %d / cycle %d\n", | 
|---|
 | 876 | __FUNCTION__ , this->process->pid, this->trdid, name, new, cycle ); | 
|---|
 | 877 | #endif | 
|---|
 | 878 |  | 
|---|
| [266] | 879 |     // set new offset | 
|---|
| [568] | 880 |     hal_remote_s32( offset_xp , new ); | 
|---|
| [266] | 881 |  | 
|---|
 | 882 |     // release file descriptor lock | 
|---|
| [568] | 883 |     remote_rwlock_wr_release( lock_xp ); | 
|---|
| [266] | 884 |  | 
|---|
 | 885 |     // success | 
|---|
| [602] | 886 |     if ( new_offset != NULL ) *new_offset = new; | 
|---|
| [1] | 887 |     return 0; | 
|---|
 | 888 |  | 
|---|
| [23] | 889 | }  // vfs_lseek() | 
|---|
 | 890 |  | 
|---|
 | 891 | /////////////////////////////////// | 
|---|
 | 892 | error_t vfs_close( xptr_t   file_xp, | 
|---|
 | 893 |                    uint32_t file_id ) | 
|---|
| [1] | 894 | { | 
|---|
| [459] | 895 |     cluster_t  * cluster;          // local pointer on local cluster | 
|---|
 | 896 |     cxy_t        file_cxy;         // cluster containing the file descriptor. | 
|---|
 | 897 |     vfs_file_t * file_ptr;         // local ponter on file descriptor | 
|---|
 | 898 |     cxy_t        owner_cxy;        // process owner cluster | 
|---|
 | 899 |     lpid_t       lpid;             // process local index | 
|---|
 | 900 |     xptr_t       root_xp;          // root of list of process copies | 
|---|
 | 901 |     xptr_t       lock_xp;          // lock protecting the list of copies | 
|---|
 | 902 |     xptr_t       iter_xp;          // iterator on list of process copies | 
|---|
 | 903 |     xptr_t       process_xp;       // extended pointer on one process copy | 
|---|
 | 904 |     cxy_t        process_cxy;      // process copy cluster | 
|---|
 | 905 |     process_t  * process_ptr;      // process copy local pointer | 
|---|
 | 906 |  | 
|---|
| [602] | 907 | // check arguments | 
|---|
 | 908 | assert( (file_xp != XPTR_NULL) , "file_xp == XPTR_NULL\n" ); | 
|---|
 | 909 | assert( (file_id < CONFIG_PROCESS_FILE_MAX_NR) , "illegal file_id\n" ); | 
|---|
| [23] | 910 |  | 
|---|
 | 911 |     thread_t  * this    = CURRENT_THREAD; | 
|---|
 | 912 |     process_t * process = this->process; | 
|---|
 | 913 |  | 
|---|
| [459] | 914 | #if DEBUG_VFS_CLOSE | 
|---|
 | 915 | uint32_t cycle = (uint32_t)hal_get_cycles(); | 
|---|
 | 916 | if( DEBUG_VFS_CLOSE < cycle ) | 
|---|
| [598] | 917 | printk("\n[%s] thread[%x,%x] enter / fdid %d / cycle %d\n", | 
|---|
 | 918 | __FUNCTION__, process->pid, this->trdid, file_id, cycle ); | 
|---|
| [459] | 919 | #endif | 
|---|
| [1] | 920 |  | 
|---|
| [23] | 921 |     // get local pointer on local cluster manager | 
|---|
| [459] | 922 |     cluster = LOCAL_CLUSTER; | 
|---|
| [23] | 923 |  | 
|---|
 | 924 |     // get owner process cluster and lpid | 
|---|
| [459] | 925 |     owner_cxy  = CXY_FROM_PID( process->pid ); | 
|---|
 | 926 |     lpid       = LPID_FROM_PID( process->pid ); | 
|---|
| [23] | 927 |  | 
|---|
 | 928 |     // get extended pointers on copies root and lock | 
|---|
| [459] | 929 |     root_xp = XPTR( owner_cxy , &cluster->pmgr.copies_root[lpid] ); | 
|---|
 | 930 |     lock_xp = XPTR( owner_cxy , &cluster->pmgr.copies_lock[lpid] ); | 
|---|
| [23] | 931 |  | 
|---|
| [459] | 932 |     // 1) loop on the process descriptor copies to reset all fd_array[file_id] entries | 
|---|
 | 933 |  | 
|---|
 | 934 |     // take the lock protecting the list of copies | 
|---|
| [568] | 935 |     remote_queuelock_acquire( lock_xp ); | 
|---|
| [23] | 936 |  | 
|---|
 | 937 |     XLIST_FOREACH( root_xp , iter_xp ) | 
|---|
| [1] | 938 |     { | 
|---|
| [459] | 939 |         process_xp  = XLIST_ELEMENT( iter_xp , process_t , copies_list ); | 
|---|
 | 940 |         process_cxy = GET_CXY( process_xp ); | 
|---|
 | 941 |         process_ptr = GET_PTR( process_xp ); | 
|---|
| [1] | 942 |  | 
|---|
| [459] | 943 | #if (DEBUG_VFS_CLOSE & 1 ) | 
|---|
 | 944 | if( DEBUG_VFS_CLOSE < cycle ) | 
|---|
| [598] | 945 | printk("\n[%s]  reset fd_array[%d] for process %x in cluster %x\n", | 
|---|
| [459] | 946 | __FUNCTION__, file_id, process_ptr, process_cxy ); | 
|---|
 | 947 | #endif | 
|---|
| [23] | 948 |  | 
|---|
| [459] | 949 | // fd_array lock is required for atomic write of a 64 bits word | 
|---|
 | 950 | // xptr_t fd_array_lock_xp = XPTR( process_cxy , &process_ptr->fd_array.lock ); | 
|---|
 | 951 |  | 
|---|
 | 952 |         xptr_t entry_xp         = XPTR( process_cxy , &process_ptr->fd_array.array[file_id] ); | 
|---|
 | 953 |  | 
|---|
| [568] | 954 | // remote_rwlock_wr_acquire( fd_array_lock_xp ); | 
|---|
| [459] | 955 |  | 
|---|
| [568] | 956 |         hal_remote_s64( entry_xp , XPTR_NULL ); | 
|---|
| [459] | 957 |          | 
|---|
| [568] | 958 | // remote_rwlock_wr_release( fd_array_lock_xp ); | 
|---|
| [23] | 959 |  | 
|---|
| [459] | 960 |         vfs_file_count_down( file_xp ); | 
|---|
 | 961 |  | 
|---|
| [124] | 962 |         hal_fence(); | 
|---|
| [23] | 963 |     }     | 
|---|
 | 964 |  | 
|---|
| [459] | 965 |     // release the lock protecting the list of copies | 
|---|
| [568] | 966 |     remote_queuelock_release( lock_xp ); | 
|---|
| [459] | 967 |  | 
|---|
 | 968 | #if (DEBUG_VFS_CLOSE & 1)  | 
|---|
 | 969 | if( DEBUG_VFS_CLOSE < cycle ) | 
|---|
| [598] | 970 | printk("\n[%s] thread[%x,%x] reset all fd-array copies\n", | 
|---|
 | 971 | __FUNCTION__, process->pid, this->trdid ); | 
|---|
| [459] | 972 | #endif | 
|---|
 | 973 |  | 
|---|
| [23] | 974 |     // 2) release memory allocated to file descriptor in remote cluster | 
|---|
| [459] | 975 |  | 
|---|
 | 976 |     // get cluster and local pointer on remote file descriptor | 
|---|
 | 977 |     file_cxy = GET_CXY( file_xp ); | 
|---|
 | 978 |     file_ptr = GET_PTR( file_xp ); | 
|---|
 | 979 |  | 
|---|
| [23] | 980 |     if( file_cxy == local_cxy )             // file cluster is local | 
|---|
| [1] | 981 |     { | 
|---|
| [23] | 982 |         vfs_file_destroy( file_ptr ); | 
|---|
 | 983 |     } | 
|---|
 | 984 |     else                                    // file cluster is local | 
|---|
 | 985 |     { | 
|---|
 | 986 |         rpc_vfs_file_destroy_client( file_cxy , file_ptr ); | 
|---|
 | 987 |     } | 
|---|
| [1] | 988 |  | 
|---|
| [459] | 989 | #if DEBUG_VFS_CLOSE | 
|---|
 | 990 | cycle = (uint32_t)hal_get_cycles(); | 
|---|
 | 991 | if( DEBUG_VFS_CLOSE < cycle ) | 
|---|
| [598] | 992 | printk("\n[%s] thread[%x,%x] exit / fdid %d closed / cycle %d\n", | 
|---|
 | 993 | __FUNCTION__, process->pid, this->trdid, file_id, cycle ); | 
|---|
| [459] | 994 | #endif | 
|---|
 | 995 |  | 
|---|
| [23] | 996 |     return 0; | 
|---|
| [1] | 997 |  | 
|---|
| [23] | 998 | }  // end vfs_close() | 
|---|
| [1] | 999 |  | 
|---|
 | 1000 | //////////////////////////////////// | 
|---|
| [610] | 1001 | error_t vfs_mkdir( xptr_t   root_xp, | 
|---|
 | 1002 |                    char   * path, | 
|---|
 | 1003 |                    uint32_t rights ) | 
|---|
 | 1004 | { | 
|---|
 | 1005 |     error_t        error; | 
|---|
 | 1006 |     xptr_t         vfs_root_xp;        // extended pointer on VFS root inode | 
|---|
 | 1007 |     vfs_inode_t  * vfs_root_ptr;       // local pointer on VFS root inode | 
|---|
 | 1008 |     cxy_t          vfs_root_cxy;       // VFS root inode cluster identifier | 
|---|
 | 1009 |     xptr_t         lock_xp;            // extended pointer on lock protecting Inode Tree | 
|---|
| [611] | 1010 |     xptr_t         inode_xp;           // extended pointer on new directory inode | 
|---|
 | 1011 |     vfs_inode_t  * inode_ptr;          // local pointer on new directory inode | 
|---|
 | 1012 |     cxy_t          inode_cxy;          // new directory inode cluster identifier | 
|---|
| [610] | 1013 |     xptr_t         dentry_xp;          // extended pointer on new dentry | 
|---|
| [611] | 1014 |     vfs_dentry_t * dentry_ptr;         // new dentry local pointer | 
|---|
 | 1015 |     xptr_t         parent_xp;          // extended pointer on parent inode | 
|---|
 | 1016 |     vfs_inode_t  * parent_ptr;         // local pointer on parent inode   | 
|---|
 | 1017 |     cxy_t          parent_cxy;         // parent inode cluster identifier | 
|---|
 | 1018 |     vfs_ctx_t    * parent_ctx_ptr;     // local pointer on parent inode context | 
|---|
 | 1019 |     uint32_t       parent_fs_type;     // parent inode file system type | 
|---|
| [610] | 1020 |  | 
|---|
 | 1021 |     xptr_t         parents_root_xp;    // extended pointer on parents field in inode (root) | 
|---|
 | 1022 |     xptr_t         parents_entry_xp;   // extended pointer on parents field in dentry | 
|---|
 | 1023 |     xptr_t         children_xhtab_xp;  // extended pointer on children field in inode (root) | 
|---|
 | 1024 |     xptr_t         children_entry_xp;  // extended pointer on children field in dentry | 
|---|
 | 1025 |  | 
|---|
 | 1026 |     char           last_name[CONFIG_VFS_MAX_NAME_LENGTH]; | 
|---|
 | 1027 |  | 
|---|
 | 1028 |     thread_t  * this    = CURRENT_THREAD; | 
|---|
 | 1029 |     process_t * process = this->process; | 
|---|
 | 1030 |  | 
|---|
 | 1031 | #if DEBUG_VFS_MKDIR | 
|---|
 | 1032 | char root_name[CONFIG_VFS_MAX_NAME_LENGTH]; | 
|---|
 | 1033 | vfs_inode_get_name( root_xp , root_name ); | 
|---|
 | 1034 | uint32_t   cycle = (uint32_t)hal_get_cycles(); | 
|---|
 | 1035 | if( DEBUG_VFS_MKDIR < cycle ) | 
|---|
 | 1036 | printk("\n[%s] thread[%x,%x] enter / root <%s> / path <%s> / cycle %d\n", | 
|---|
 | 1037 | __FUNCTION__, process->pid, this->trdid, root_name, path, cycle ); | 
|---|
 | 1038 | #endif | 
|---|
 | 1039 |  | 
|---|
 | 1040 |     // build extended pointer on lock protecting Inode Tree (in VFS root inode) | 
|---|
 | 1041 |     vfs_root_xp  = process->vfs_root_xp; | 
|---|
 | 1042 |     vfs_root_ptr = GET_PTR( vfs_root_xp ); | 
|---|
 | 1043 |     vfs_root_cxy = GET_CXY( vfs_root_xp ); | 
|---|
 | 1044 |     lock_xp      = XPTR( vfs_root_cxy , &vfs_root_ptr->main_lock ); | 
|---|
 | 1045 |  | 
|---|
 | 1046 |     // take the lock protecting Inode Tree in write mode | 
|---|
 | 1047 |     remote_rwlock_wr_acquire( lock_xp ); | 
|---|
 | 1048 |  | 
|---|
 | 1049 |     // 1. get pointers on parent inode | 
|---|
 | 1050 |     error = vfs_lookup( root_xp, | 
|---|
 | 1051 |                         path, | 
|---|
 | 1052 |                         VFS_LOOKUP_DIR | VFS_LOOKUP_PARENT, | 
|---|
 | 1053 |                         &parent_xp, | 
|---|
 | 1054 |                         last_name ); | 
|---|
 | 1055 |     if( error ) | 
|---|
 | 1056 |     { | 
|---|
 | 1057 |         remote_rwlock_wr_release( lock_xp ); | 
|---|
 | 1058 |         printk("\n[ERROR] in %s : cannot get parent inode for <%s>\n", | 
|---|
 | 1059 |         __FUNCTION__, path ); | 
|---|
 | 1060 |         return -1; | 
|---|
 | 1061 |     } | 
|---|
 | 1062 |  | 
|---|
 | 1063 |     // get parent inode cluster and local pointer | 
|---|
 | 1064 |     parent_cxy = GET_CXY( parent_xp ); | 
|---|
 | 1065 |     parent_ptr = GET_PTR( parent_xp ); | 
|---|
 | 1066 |  | 
|---|
 | 1067 | #if( DEBUG_VFS_MKDIR & 1 ) | 
|---|
 | 1068 | if( DEBUG_VFS_MKDIR < cycle ) | 
|---|
 | 1069 | printk("\n[%s] thread[%x,%x] get parent inode (%x,%x) for <%s>\n", | 
|---|
 | 1070 | __FUNCTION__, process->pid, this->trdid, parent_cxy, parent_ptr, path ); | 
|---|
 | 1071 | #endif | 
|---|
 | 1072 |  | 
|---|
 | 1073 |     // get parent inode context, and FS type | 
|---|
 | 1074 |     parent_ctx_ptr = hal_remote_lpt( XPTR( parent_cxy , &parent_ptr->ctx ) ); | 
|---|
 | 1075 |     parent_fs_type = hal_remote_l32( XPTR( parent_cxy , &parent_ctx_ptr->type ) ); | 
|---|
 | 1076 |  | 
|---|
 | 1077 |     // 2. create one new dentry in parent cluster | 
|---|
 | 1078 |     if( parent_cxy == local_cxy )   | 
|---|
 | 1079 |     { | 
|---|
 | 1080 |         error = vfs_dentry_create( parent_fs_type, | 
|---|
 | 1081 |                                    last_name, | 
|---|
 | 1082 |                                    &dentry_xp ); | 
|---|
 | 1083 |     } | 
|---|
 | 1084 |     else | 
|---|
 | 1085 |     { | 
|---|
 | 1086 |         rpc_vfs_dentry_create_client( parent_cxy, | 
|---|
 | 1087 |                                       parent_fs_type, | 
|---|
 | 1088 |                                       last_name, | 
|---|
 | 1089 |                                       &dentry_xp, | 
|---|
 | 1090 |                                       &error ); | 
|---|
 | 1091 |     } | 
|---|
 | 1092 |  | 
|---|
 | 1093 |     if( error ) | 
|---|
 | 1094 |     { | 
|---|
 | 1095 |         remote_rwlock_wr_release( lock_xp ); | 
|---|
 | 1096 |         printk("\n[ERROR] in %s : cannot create new dentry in cluster %x for <%s>\n", | 
|---|
 | 1097 |         __FUNCTION__, parent_cxy, path ); | 
|---|
 | 1098 |         return -1; | 
|---|
 | 1099 |     } | 
|---|
 | 1100 |  | 
|---|
 | 1101 |     // get local pointer on dentry  | 
|---|
 | 1102 |     dentry_ptr = GET_PTR( dentry_xp ); | 
|---|
 | 1103 |  | 
|---|
 | 1104 | #if( DEBUG_VFS_MKDIR & 1 ) | 
|---|
 | 1105 | if( DEBUG_VFS_MKDIR < cycle ) | 
|---|
 | 1106 | printk("\n[%s] thread[%x,%x] created new dentry (%x,%x) for <%s>\n", | 
|---|
 | 1107 | __FUNCTION__, process->pid, this->trdid, parent_cxy, dentry_ptr, path ); | 
|---|
 | 1108 | #endif | 
|---|
 | 1109 |  | 
|---|
| [611] | 1110 |     // 3. create new directory inode | 
|---|
| [610] | 1111 |     // TODO : define attr / uid / gid | 
|---|
 | 1112 |     uint32_t attr = 0; | 
|---|
 | 1113 |     uint32_t uid  = 0; | 
|---|
 | 1114 |     uint32_t gid  = 0; | 
|---|
 | 1115 |  | 
|---|
 | 1116 |     // select a target cluster for new inode | 
|---|
 | 1117 |     inode_cxy = cluster_random_select(); | 
|---|
 | 1118 |      | 
|---|
| [611] | 1119 |     if( inode_cxy == local_cxy )      // target cluster is local  | 
|---|
| [610] | 1120 |     { | 
|---|
 | 1121 |         error = vfs_inode_create( parent_fs_type, | 
|---|
 | 1122 |                                   INODE_TYPE_DIR, | 
|---|
 | 1123 |                                   attr, | 
|---|
 | 1124 |                                   rights, | 
|---|
 | 1125 |                                   uid, | 
|---|
 | 1126 |                                   gid, | 
|---|
 | 1127 |                                   &inode_xp ); | 
|---|
 | 1128 |     } | 
|---|
| [611] | 1129 |     else                              // target cluster is remote | 
|---|
| [610] | 1130 |     { | 
|---|
 | 1131 |         rpc_vfs_inode_create_client( inode_cxy, | 
|---|
 | 1132 |                                      parent_fs_type, | 
|---|
 | 1133 |                                      INODE_TYPE_DIR, | 
|---|
 | 1134 |                                      attr, | 
|---|
 | 1135 |                                      rights, | 
|---|
 | 1136 |                                      uid, | 
|---|
 | 1137 |                                      gid, | 
|---|
 | 1138 |                                      &inode_xp, | 
|---|
 | 1139 |                                      &error ); | 
|---|
 | 1140 |     } | 
|---|
 | 1141 |                                       | 
|---|
 | 1142 |     if( error ) | 
|---|
 | 1143 |     { | 
|---|
| [611] | 1144 |         remote_rwlock_wr_release( lock_xp ); | 
|---|
| [610] | 1145 |         printk("\n[ERROR] in %s : cannot create new inode in cluster %x for <%s>\n", | 
|---|
 | 1146 |                __FUNCTION__ , inode_cxy , path ); | 
|---|
 | 1147 |         if( parent_cxy == local_cxy ) vfs_dentry_destroy( dentry_ptr ); | 
|---|
 | 1148 |         else rpc_vfs_dentry_destroy_client( parent_cxy , dentry_ptr ); | 
|---|
 | 1149 |         return -1; | 
|---|
 | 1150 |     } | 
|---|
 | 1151 |  | 
|---|
 | 1152 |     // get new inode local pointer | 
|---|
 | 1153 |     inode_ptr = GET_PTR( inode_xp ); | 
|---|
 | 1154 |      | 
|---|
 | 1155 | #if(DEBUG_VFS_MKDIR & 1) | 
|---|
 | 1156 | if( DEBUG_VFS_MKDIR < cycle ) | 
|---|
 | 1157 | printk("\n[%s] thread[%x,%x] created new inode (%x,%x) for <%s>\n", | 
|---|
 | 1158 | __FUNCTION__ , process->pid, this->trdid, inode_cxy, inode_ptr, path ); | 
|---|
 | 1159 | #endif | 
|---|
 | 1160 |  | 
|---|
 | 1161 |     // 4. register dentry in new inode list of parents | 
|---|
 | 1162 |     parents_root_xp  = XPTR( inode_cxy  , &inode_ptr->parents ); | 
|---|
 | 1163 |     parents_entry_xp = XPTR( parent_cxy , &dentry_ptr->parents ); | 
|---|
 | 1164 |     xlist_add_first( parents_root_xp , parents_entry_xp ); | 
|---|
 | 1165 |     hal_remote_atomic_add( XPTR( inode_cxy , &inode_ptr->links ) , 1 ); | 
|---|
 | 1166 |  | 
|---|
 | 1167 |     // 5. register dentry in parent inode  | 
|---|
 | 1168 |     children_xhtab_xp = XPTR( parent_cxy , &parent_ptr->children ); | 
|---|
 | 1169 |     children_entry_xp = XPTR( parent_cxy , &dentry_ptr->children ); | 
|---|
 | 1170 |     xhtab_insert( children_xhtab_xp , last_name , children_entry_xp ); | 
|---|
 | 1171 |  | 
|---|
 | 1172 |     // 6. update "parent" and "child_xp" fields in dentry | 
|---|
 | 1173 |     hal_remote_s64( XPTR( parent_cxy , &dentry_ptr->child_xp ) , inode_xp ); | 
|---|
 | 1174 |     hal_remote_spt( XPTR( parent_cxy , &dentry_ptr->parent ) , parent_ptr ); | 
|---|
 | 1175 |  | 
|---|
 | 1176 | #if(DEBUG_VFS_MKDIR & 1) | 
|---|
 | 1177 | if( DEBUG_VFS_MKDIR < cycle ) | 
|---|
 | 1178 | printk("\n[%s] thread[%x,%x] updated Inode Tree for <%s>\n", | 
|---|
 | 1179 | __FUNCTION__, process->pid, this->trdid, path ); | 
|---|
 | 1180 | #endif | 
|---|
 | 1181 |  | 
|---|
| [611] | 1182 |     // 7. create the two special dentries <.> and <..> in new directory | 
|---|
 | 1183 |     // both the new directory mapper, and the Inode Tree are updated | 
|---|
 | 1184 |     error = vfs_add_special_dentries( inode_xp, | 
|---|
 | 1185 |                                       parent_xp ); | 
|---|
 | 1186 |  | 
|---|
 | 1187 |     if( error ) | 
|---|
 | 1188 |     { | 
|---|
 | 1189 |         remote_rwlock_wr_release( lock_xp ); | 
|---|
 | 1190 |         printk("\n[ERROR] in %s : cannot create new inode in cluster %x for <%s>\n", | 
|---|
 | 1191 |                __FUNCTION__ , inode_cxy , path ); | 
|---|
 | 1192 |         if( parent_cxy == local_cxy ) vfs_dentry_destroy( dentry_ptr ); | 
|---|
 | 1193 |         else rpc_vfs_dentry_destroy_client( parent_cxy , dentry_ptr ); | 
|---|
 | 1194 |         return -1; | 
|---|
 | 1195 |     } | 
|---|
 | 1196 |  | 
|---|
| [610] | 1197 |     // release the lock protecting Inode Tree | 
|---|
 | 1198 |     remote_rwlock_wr_release( lock_xp ); | 
|---|
 | 1199 |  | 
|---|
| [611] | 1200 |     // 8. update parent directory mapper  | 
|---|
| [610] | 1201 |     //    and synchronize the parent directory on IOC device | 
|---|
 | 1202 |     if (parent_cxy == local_cxy) | 
|---|
 | 1203 |     { | 
|---|
 | 1204 |         error = vfs_fs_add_dentry( parent_ptr, | 
|---|
 | 1205 |                                    dentry_ptr ); | 
|---|
 | 1206 |     } | 
|---|
 | 1207 |     else | 
|---|
 | 1208 |     { | 
|---|
 | 1209 |         rpc_vfs_fs_add_dentry_client( parent_cxy, | 
|---|
 | 1210 |                                       parent_ptr, | 
|---|
 | 1211 |                                       dentry_ptr, | 
|---|
 | 1212 |                                       &error ); | 
|---|
 | 1213 |     } | 
|---|
 | 1214 |  | 
|---|
 | 1215 |     if( error ) | 
|---|
 | 1216 |     { | 
|---|
 | 1217 |         printk("\n[ERROR] in %s : cannot update parent directory for <%s>\n", | 
|---|
 | 1218 |         __FUNCTION__, path ); | 
|---|
 | 1219 |         return -1; | 
|---|
 | 1220 |     } | 
|---|
 | 1221 |  | 
|---|
 | 1222 | #if(DEBUG_VFS_MKDIR & 1) | 
|---|
 | 1223 | if( DEBUG_VFS_MKDIR < cycle ) | 
|---|
 | 1224 | printk("\n[%s] thread[%x,%x] updated parent dir (mapper and IOC) for <%s>\n", | 
|---|
 | 1225 | __FUNCTION__, process->pid, this->trdid, path ); | 
|---|
 | 1226 | #endif | 
|---|
 | 1227 |  | 
|---|
 | 1228 |     return 0; | 
|---|
 | 1229 |  | 
|---|
 | 1230 | }  // end vfs_mkdir() | 
|---|
 | 1231 |  | 
|---|
 | 1232 | /////////////////////////////////////// | 
|---|
 | 1233 | error_t vfs_link( xptr_t   old_root_xp, | 
|---|
 | 1234 |                   char   * old_path, | 
|---|
 | 1235 |                   xptr_t   new_root_xp, | 
|---|
 | 1236 |                   char   * new_path ) | 
|---|
 | 1237 | { | 
|---|
 | 1238 |     error_t        error; | 
|---|
 | 1239 |     xptr_t         vfs_root_xp;        // extended pointer on VFS root inode | 
|---|
 | 1240 |     vfs_inode_t  * vfs_root_ptr;       // local pointer on VFS root inode | 
|---|
 | 1241 |     cxy_t          vfs_root_cxy;       // VFS root inode cluster identifier | 
|---|
 | 1242 |     xptr_t         lock_xp;            // extended pointer on lock protecting Inode Tree | 
|---|
 | 1243 |     xptr_t         inode_xp;           // extended pointer on target inode | 
|---|
 | 1244 |     vfs_inode_t  * inode_ptr;          // local pointer on target inode | 
|---|
 | 1245 |     cxy_t          inode_cxy;          // target inode cluster identifier | 
|---|
 | 1246 |     uint32_t       inode_type;         // target inode type | 
|---|
 | 1247 |     vfs_ctx_t    * inode_ctx_ptr;      // local pointer on target inode context | 
|---|
 | 1248 |     uint32_t       inode_fs_type;      // target inode file system type | 
|---|
 | 1249 |     xptr_t         dentry_xp;          // extended pointer on new dentry | 
|---|
 | 1250 |     vfs_dentry_t * dentry_ptr;         // target dentry local pointer | 
|---|
 | 1251 |     xptr_t         new_parent_xp;      // extended pointer on new parent inode | 
|---|
 | 1252 |     vfs_inode_t  * new_parent_ptr;     // local pointer on new parent inode   | 
|---|
 | 1253 |     cxy_t          new_parent_cxy;     // new parent inode cluster identifier | 
|---|
 | 1254 |  | 
|---|
 | 1255 |     xptr_t         parents_root_xp;    // extended pointer on parents field in inode (root) | 
|---|
 | 1256 |     xptr_t         parents_entry_xp;   // extended pointer on parents field in dentry | 
|---|
 | 1257 |     xptr_t         children_xhtab_xp;  // extended pointer on children field in inode (root) | 
|---|
 | 1258 |     xptr_t         children_entry_xp;  // extended pointer on children field in dentry | 
|---|
 | 1259 |  | 
|---|
 | 1260 |     char           new_name[CONFIG_VFS_MAX_NAME_LENGTH]; | 
|---|
 | 1261 |  | 
|---|
 | 1262 |     thread_t  * this    = CURRENT_THREAD; | 
|---|
 | 1263 |     process_t * process = this->process; | 
|---|
 | 1264 |  | 
|---|
 | 1265 | #if DEBUG_VFS_LINK | 
|---|
 | 1266 | char old_root_name[CONFIG_VFS_MAX_NAME_LENGTH]; | 
|---|
 | 1267 | char new_root_name[CONFIG_VFS_MAX_NAME_LENGTH]; | 
|---|
 | 1268 | vfs_inode_get_name( old_root_xp , old_root_name ); | 
|---|
 | 1269 | vfs_inode_get_name( new_root_xp , new_root_name ); | 
|---|
 | 1270 | uint32_t   cycle = (uint32_t)hal_get_cycles(); | 
|---|
 | 1271 | if( DEBUG_VFS_LINK < cycle ) | 
|---|
 | 1272 | printk("\n[%s] thread[%x,%x] enter / old_root <%s> / old_path <%s> / " | 
|---|
 | 1273 | "new_root <%s> / new_path <%s> / cycle %d\n", | 
|---|
 | 1274 | __FUNCTION__, process->pid, this->trdid, | 
|---|
 | 1275 | old_root_name, old_path, new_root_name, new_path, cycle ); | 
|---|
 | 1276 | #endif | 
|---|
 | 1277 |  | 
|---|
 | 1278 |     // build extended pointer on lock protecting Inode Tree (in VFS root inode) | 
|---|
 | 1279 |     vfs_root_xp  = process->vfs_root_xp; | 
|---|
 | 1280 |     vfs_root_ptr = GET_PTR( vfs_root_xp ); | 
|---|
 | 1281 |     vfs_root_cxy = GET_CXY( vfs_root_xp ); | 
|---|
 | 1282 |     lock_xp      = XPTR( vfs_root_cxy , &vfs_root_ptr->main_lock ); | 
|---|
 | 1283 |  | 
|---|
 | 1284 |     // take the lock protecting Inode Tree in write mode | 
|---|
 | 1285 |     remote_rwlock_wr_acquire( lock_xp ); | 
|---|
 | 1286 |  | 
|---|
 | 1287 |     // get extended pointer on target inode | 
|---|
 | 1288 |     error = vfs_lookup( old_root_xp, | 
|---|
 | 1289 |                         old_path, | 
|---|
 | 1290 |                         0, | 
|---|
 | 1291 |                         &inode_xp, | 
|---|
 | 1292 |                         NULL ); | 
|---|
 | 1293 |     if( error ) | 
|---|
 | 1294 |     { | 
|---|
 | 1295 |         remote_rwlock_wr_release( lock_xp ); | 
|---|
 | 1296 |         printk("\n[ERROR] in %s : cannot get target inode for <%s>\n", | 
|---|
 | 1297 |         __FUNCTION__, old_path ); | 
|---|
 | 1298 |         return -1; | 
|---|
 | 1299 |     } | 
|---|
 | 1300 |  | 
|---|
 | 1301 | #if( DEBUG_VFS_LINK & 1 ) | 
|---|
 | 1302 | if( DEBUG_VFS_LINK < cycle ) | 
|---|
 | 1303 | printk("\n[%s] thread[%x,%x] get child inode (%x,%x) for <%s>\n", | 
|---|
 | 1304 | __FUNCTION__, process->pid, this->trdid, | 
|---|
 | 1305 | GET_CXY(inode_xp), GET_PTR(inode_xp), old_path, cycle ); | 
|---|
 | 1306 | #endif | 
|---|
 | 1307 |  | 
|---|
 | 1308 |     // get extended pointer on parent inode in new path | 
|---|
 | 1309 |     error = vfs_lookup( new_root_xp, | 
|---|
 | 1310 |                         new_path, | 
|---|
 | 1311 |                         VFS_LOOKUP_PARENT, | 
|---|
 | 1312 |                         &new_parent_xp, | 
|---|
 | 1313 |                         new_name ); | 
|---|
 | 1314 |     if( error ) | 
|---|
 | 1315 |     { | 
|---|
 | 1316 |         remote_rwlock_wr_release( lock_xp ); | 
|---|
 | 1317 |         printk("\n[ERROR] in %s : cannot get parent inode for <%s>\n", | 
|---|
 | 1318 |         __FUNCTION__, new_path ); | 
|---|
 | 1319 |         return -1; | 
|---|
 | 1320 |     } | 
|---|
 | 1321 |  | 
|---|
 | 1322 | #if( DEBUG_VFS_LINK & 1 ) | 
|---|
 | 1323 | if( DEBUG_VFS_LINK < cycle ) | 
|---|
 | 1324 | printk("\n[%s] thread[%x,%x] get parent inode (%x,%x) for <%s>\n", | 
|---|
 | 1325 | __FUNCTION__, process->pid, this->trdid, | 
|---|
 | 1326 | GET_CXY(new_parent_xp), GET_PTR(new_parent_xp), new_path ); | 
|---|
 | 1327 | #endif | 
|---|
 | 1328 |  | 
|---|
 | 1329 |     // get target inode cluster and local pointer | 
|---|
 | 1330 |     inode_cxy = GET_CXY( inode_xp ); | 
|---|
 | 1331 |     inode_ptr = GET_PTR( inode_xp ); | 
|---|
 | 1332 |  | 
|---|
 | 1333 |     // get target inode type, context, and FS type | 
|---|
 | 1334 |     inode_type        = hal_remote_l32( XPTR( inode_cxy , &inode_ptr->type ) ); | 
|---|
 | 1335 |     inode_ctx_ptr     = hal_remote_lpt( XPTR( inode_cxy , &inode_ptr->ctx ) ); | 
|---|
 | 1336 |     inode_fs_type     = hal_remote_l32( XPTR( inode_cxy , &inode_ctx_ptr->type ) ); | 
|---|
 | 1337 |  | 
|---|
 | 1338 |     // get new parent inode cluster an local pointer | 
|---|
 | 1339 |     new_parent_ptr = GET_PTR( new_parent_xp ); | 
|---|
 | 1340 |     new_parent_cxy = GET_CXY( new_parent_xp ); | 
|---|
 | 1341 |  | 
|---|
 | 1342 |     /////////////////////////////////////////////////////////////////////// | 
|---|
 | 1343 |     if( (inode_type == INODE_TYPE_FILE) || (inode_type == INODE_TYPE_DIR) ) | 
|---|
 | 1344 |     { | 
|---|
 | 1345 |         // 1. create one new dentry | 
|---|
 | 1346 |         if( new_parent_cxy == local_cxy )   | 
|---|
 | 1347 |         { | 
|---|
 | 1348 |             error = vfs_dentry_create( inode_fs_type, | 
|---|
 | 1349 |                                        new_name, | 
|---|
 | 1350 |                                        &dentry_xp ); | 
|---|
 | 1351 |         } | 
|---|
 | 1352 |         else | 
|---|
 | 1353 |         { | 
|---|
 | 1354 |             rpc_vfs_dentry_create_client( new_parent_cxy, | 
|---|
 | 1355 |                                           inode_fs_type, | 
|---|
 | 1356 |                                           new_name, | 
|---|
 | 1357 |                                           &dentry_xp, | 
|---|
 | 1358 |                                           &error ); | 
|---|
 | 1359 |         } | 
|---|
 | 1360 |  | 
|---|
 | 1361 |         if( error ) | 
|---|
 | 1362 |         { | 
|---|
 | 1363 |             remote_rwlock_wr_release( lock_xp ); | 
|---|
 | 1364 |             printk("\n[ERROR] in %s : cannot create new dentry for <%s>\n", | 
|---|
 | 1365 |             __FUNCTION__, new_path ); | 
|---|
 | 1366 |             return -1; | 
|---|
 | 1367 |         } | 
|---|
 | 1368 |  | 
|---|
 | 1369 |         // get local pointer on dentry  | 
|---|
 | 1370 |         dentry_ptr = GET_PTR( dentry_xp ); | 
|---|
 | 1371 |  | 
|---|
 | 1372 |         // 2. register dentry in target inode  | 
|---|
 | 1373 |         parents_root_xp  = XPTR( inode_cxy      , &inode_ptr->parents ); | 
|---|
 | 1374 |         parents_entry_xp = XPTR( new_parent_cxy , &dentry_ptr->parents ); | 
|---|
 | 1375 |         xlist_add_first( parents_root_xp , parents_entry_xp ); | 
|---|
 | 1376 |         hal_remote_atomic_add( XPTR( inode_cxy , &inode_ptr->links ) , 1 ); | 
|---|
 | 1377 |  | 
|---|
 | 1378 |         // 3. register dentry in parent inode  | 
|---|
 | 1379 |         children_xhtab_xp = XPTR( new_parent_cxy , &new_parent_ptr->children ); | 
|---|
 | 1380 |         children_entry_xp = XPTR( new_parent_cxy , &dentry_ptr->children ); | 
|---|
 | 1381 |         xhtab_insert( children_xhtab_xp , new_name , children_entry_xp ); | 
|---|
 | 1382 |  | 
|---|
 | 1383 |         // 4. update "parent" and "child_xp" fields in dentry | 
|---|
 | 1384 |         hal_remote_s64( XPTR( new_parent_cxy , &dentry_ptr->child_xp ) , inode_xp ); | 
|---|
 | 1385 |         hal_remote_spt( XPTR( new_parent_cxy , &dentry_ptr->parent ) , new_parent_ptr ); | 
|---|
 | 1386 |  | 
|---|
 | 1387 | #if(DEBUG_VFS_LINK & 1) | 
|---|
 | 1388 | if( DEBUG_VFS_LINK < cycle ) | 
|---|
 | 1389 | printk("\n[%s] thread[%x,%x] updated Inode Tree / old <%s> / new <%s>\n", | 
|---|
 | 1390 | __FUNCTION__, process->pid, this->trdid, old_path, new_path ); | 
|---|
 | 1391 | vfs_display( new_parent_xp );  | 
|---|
 | 1392 | #endif | 
|---|
 | 1393 |  | 
|---|
 | 1394 |         // release the lock protecting Inode Tree | 
|---|
 | 1395 |         remote_rwlock_wr_release( lock_xp ); | 
|---|
 | 1396 |  | 
|---|
 | 1397 |         // 5. update new parent directory mapper in Inode Tree | 
|---|
 | 1398 |         //    and synchronize the parent directory on IOC device | 
|---|
 | 1399 |         if (new_parent_cxy == local_cxy) | 
|---|
 | 1400 |         { | 
|---|
 | 1401 |             error = vfs_fs_add_dentry( new_parent_ptr, | 
|---|
 | 1402 |                                        dentry_ptr ); | 
|---|
 | 1403 |         } | 
|---|
 | 1404 |         else | 
|---|
 | 1405 |         { | 
|---|
 | 1406 |             rpc_vfs_fs_add_dentry_client( new_parent_cxy, | 
|---|
 | 1407 |                                           new_parent_ptr, | 
|---|
 | 1408 |                                           dentry_ptr, | 
|---|
 | 1409 |                                           &error ); | 
|---|
 | 1410 |         } | 
|---|
 | 1411 |         if( error ) | 
|---|
 | 1412 |         { | 
|---|
 | 1413 |             printk("\n[ERROR] in %s : cannot update new parent directory for <%s>\n", | 
|---|
 | 1414 |             __FUNCTION__, new_path ); | 
|---|
 | 1415 |             return -1; | 
|---|
 | 1416 |         } | 
|---|
 | 1417 |  | 
|---|
 | 1418 | #if(DEBUG_VFS_LINK & 1) | 
|---|
 | 1419 | if( DEBUG_VFS_LINK < cycle ) | 
|---|
 | 1420 | printk("\n[%s] thread[%x,%x] updated new parent dir (mapper and IOC) / old <%s> / new <%s>\n", | 
|---|
 | 1421 | __FUNCTION__, process->pid, this->trdid, old_path, new_path ); | 
|---|
 | 1422 | #endif | 
|---|
 | 1423 |         return 0; | 
|---|
 | 1424 |     } | 
|---|
 | 1425 |     else | 
|---|
 | 1426 |     { | 
|---|
 | 1427 |         // release the lock protecting Inode Tree | 
|---|
 | 1428 |         remote_rwlock_wr_release( lock_xp ); | 
|---|
 | 1429 |  | 
|---|
 | 1430 |         printk("\n[ERROR] in %s : unsupported inode type %s\n", | 
|---|
 | 1431 |         __FUNCTION__ , vfs_inode_type_str( inode_type ) ); | 
|---|
 | 1432 |         return -1; | 
|---|
 | 1433 |     } | 
|---|
 | 1434 |  | 
|---|
 | 1435 | }  // end vfs_link() | 
|---|
 | 1436 |  | 
|---|
 | 1437 | ///////////////////////////////////// | 
|---|
 | 1438 | error_t vfs_unlink( xptr_t   root_xp, | 
|---|
| [23] | 1439 |                     char   * path ) | 
|---|
| [1] | 1440 | { | 
|---|
| [602] | 1441 |     error_t           error; | 
|---|
| [610] | 1442 |     xptr_t            vfs_root_xp;        // extended pointer on VFS root inode | 
|---|
 | 1443 |     vfs_inode_t     * vfs_root_ptr;       // local_pointer on VFS root inode | 
|---|
 | 1444 |     cxy_t             vfs_root_cxy;       // VFS root inode cluster identifier | 
|---|
 | 1445 |     xptr_t            lock_xp;            // extended pointer on lock protecting Inode Tree | 
|---|
 | 1446 |     xptr_t            parent_xp;          // extended pointer on target inode | 
|---|
 | 1447 |     cxy_t             parent_cxy;         // target inode cluster identifier        | 
|---|
 | 1448 |     vfs_inode_t     * parent_ptr;         // target inode local pointer | 
|---|
| [602] | 1449 |     xptr_t            inode_xp;           // extended pointer on target inode | 
|---|
 | 1450 |     cxy_t             inode_cxy;          // target inode cluster identifier        | 
|---|
 | 1451 |     vfs_inode_t     * inode_ptr;          // target inode local pointer | 
|---|
| [610] | 1452 |     uint32_t          inode_links;        // target inode links count | 
|---|
 | 1453 |     vfs_inode_type_t  inode_type;         // target inode type | 
|---|
 | 1454 |     uint32_t          inode_children;     // target inode number of children | 
|---|
 | 1455 |     xptr_t            dentry_xp;          // extended pointer on dentry to unlink | 
|---|
 | 1456 |     vfs_dentry_t    * dentry_ptr;         // local pointer on dentry to unlink | 
|---|
| [1] | 1457 |  | 
|---|
| [610] | 1458 |     char              name[CONFIG_VFS_MAX_NAME_LENGTH];  // name of link to remove | 
|---|
 | 1459 |  | 
|---|
 | 1460 |     thread_t  * this    = CURRENT_THREAD; | 
|---|
 | 1461 |     process_t * process = this->process; | 
|---|
 | 1462 |  | 
|---|
| [602] | 1463 | #if DEBUG_VFS_UNLINK | 
|---|
 | 1464 | uint32_t   cycle = (uint32_t)hal_get_cycles(); | 
|---|
| [610] | 1465 | char root_name[CONFIG_VFS_MAX_NAME_LENGTH]; | 
|---|
 | 1466 | vfs_inode_get_name( root_xp , root_name ); | 
|---|
| [602] | 1467 | if( DEBUG_VFS_UNLINK < cycle ) | 
|---|
| [610] | 1468 | printk("\n[%s] thread[%x,%x] enter / root <%s> / path <%s> / cycle %d\n", | 
|---|
 | 1469 | __FUNCTION__, process->pid, this->trdid, root_name, path, cycle ); | 
|---|
| [602] | 1470 | #endif | 
|---|
 | 1471 |  | 
|---|
| [610] | 1472 |     // build extended pointer on lock protecting Inode Tree (in VFS root inode) | 
|---|
 | 1473 |     vfs_root_xp  = process->vfs_root_xp; | 
|---|
 | 1474 |     vfs_root_ptr = GET_PTR( root_xp ); | 
|---|
 | 1475 |     vfs_root_cxy = GET_CXY( root_xp ); | 
|---|
 | 1476 |     lock_xp      = XPTR( vfs_root_cxy , &vfs_root_ptr->main_lock ); | 
|---|
| [602] | 1477 |  | 
|---|
| [610] | 1478 |     // take the lock protecting Inode Tree | 
|---|
 | 1479 |     remote_rwlock_wr_acquire( lock_xp ); | 
|---|
| [602] | 1480 |  | 
|---|
| [610] | 1481 |     // get extended pointer on parent inode | 
|---|
 | 1482 |     error = vfs_lookup( root_xp, | 
|---|
 | 1483 |                         path, | 
|---|
 | 1484 |                         VFS_LOOKUP_PARENT, | 
|---|
 | 1485 |                         &parent_xp, | 
|---|
 | 1486 |                         name ); | 
|---|
 | 1487 |     if( error )  | 
|---|
 | 1488 |     { | 
|---|
 | 1489 |         remote_rwlock_wr_release( lock_xp ); | 
|---|
 | 1490 |         printk("\n[ERROR] in %s : cannot get parent inode for <%s> in <%s>\n", | 
|---|
 | 1491 |         __FUNCTION__, name, path ); | 
|---|
 | 1492 |         return -1; | 
|---|
 | 1493 |     } | 
|---|
 | 1494 |  | 
|---|
 | 1495 |     // get parent inode cluster and local pointer | 
|---|
 | 1496 |     parent_cxy = GET_CXY( parent_xp ); | 
|---|
 | 1497 |     parent_ptr = GET_PTR( parent_xp ); | 
|---|
 | 1498 |   | 
|---|
 | 1499 | #if( DEBUG_VFS_UNLINK & 1 ) | 
|---|
 | 1500 | char parent_name[CONFIG_VFS_MAX_NAME_LENGTH]; | 
|---|
 | 1501 | vfs_inode_get_name( parent_xp , parent_name ); | 
|---|
 | 1502 | if( DEBUG_VFS_UNLINK < cycle ) | 
|---|
 | 1503 | printk("\n[%s] thread[%x,%x] parent inode <%s> is (%x,%x)\n", | 
|---|
 | 1504 | __FUNCTION__, process->pid, this->trdid, parent_name, parent_cxy, parent_ptr ); | 
|---|
 | 1505 | #endif | 
|---|
 | 1506 |  | 
|---|
 | 1507 |     // build extended pointer on parent inode "children" xhtab | 
|---|
 | 1508 |     xptr_t children_xp = XPTR( parent_cxy , &parent_ptr->children ); | 
|---|
 | 1509 |  | 
|---|
 | 1510 |     // get extended pointer on dentry to unlink | 
|---|
 | 1511 |     dentry_xp = xhtab_lookup( children_xp , name ); | 
|---|
 | 1512 |      | 
|---|
 | 1513 |     if( dentry_xp == XPTR_NULL ) | 
|---|
 | 1514 |     { | 
|---|
 | 1515 |         remote_rwlock_wr_release( lock_xp ); | 
|---|
 | 1516 |         printk("\n[ERROR] in %s : cannot get target dentry <%s> in <%s>\n", | 
|---|
 | 1517 |         __FUNCTION__, name, path ); | 
|---|
 | 1518 |         return -1; | 
|---|
 | 1519 |     } | 
|---|
 | 1520 |      | 
|---|
 | 1521 |     // get local pointer on dentry to unlink | 
|---|
 | 1522 |     dentry_ptr = GET_PTR( dentry_xp ); | 
|---|
 | 1523 |  | 
|---|
 | 1524 | #if( DEBUG_VFS_UNLINK & 1 ) | 
|---|
 | 1525 | if( DEBUG_VFS_UNLINK < cycle ) | 
|---|
 | 1526 | printk("\n[%s] thread[%x,%x] dentry <%s> to unlink is (%x,%x)\n", | 
|---|
 | 1527 | __FUNCTION__, process->pid, this->trdid, name, parent_cxy, dentry_ptr ); | 
|---|
 | 1528 | #endif | 
|---|
 | 1529 |  | 
|---|
 | 1530 |     // get pointer on target inode | 
|---|
 | 1531 |     inode_xp  = hal_remote_l64( XPTR( parent_cxy , &dentry_ptr->child_xp ) ); | 
|---|
| [602] | 1532 |     inode_cxy = GET_CXY( inode_xp ); | 
|---|
 | 1533 |     inode_ptr = GET_PTR( inode_xp ); | 
|---|
| [610] | 1534 |   | 
|---|
 | 1535 | #if( DEBUG_VFS_UNLINK & 1 ) | 
|---|
 | 1536 | char inode_name[CONFIG_VFS_MAX_NAME_LENGTH]; | 
|---|
 | 1537 | vfs_inode_get_name( inode_xp , inode_name ); | 
|---|
 | 1538 | if( DEBUG_VFS_UNLINK < cycle ) | 
|---|
 | 1539 | printk("\n[%s] thread[%x,%x] target inode <%s> is (%x,%x) / cycle %d\n", | 
|---|
 | 1540 | __FUNCTION__, process->pid, this->trdid, inode_name, inode_cxy, inode_ptr, cycle ); | 
|---|
 | 1541 | #endif | 
|---|
| [602] | 1542 |  | 
|---|
| [610] | 1543 |     // get target inode "type" and "links" | 
|---|
 | 1544 |     inode_type   = hal_remote_l32( XPTR( inode_cxy , &inode_ptr->type ) ); | 
|---|
 | 1545 |     inode_links  = hal_remote_l32( XPTR( inode_cxy , &inode_ptr->links ) ); | 
|---|
| [602] | 1546 |  | 
|---|
| [610] | 1547 | // check target inode links counter | 
|---|
 | 1548 | assert( (inode_links >= 1), "illegal inode links count %d for <%s>\n", inode_links, path ); | 
|---|
| [602] | 1549 |  | 
|---|
| [610] | 1550 |     /////////////////////////////////////////////////////////////////////// | 
|---|
 | 1551 |     if( (inode_type == INODE_TYPE_FILE) || (inode_type == INODE_TYPE_DIR) ) | 
|---|
| [602] | 1552 |     { | 
|---|
| [610] | 1553 |         // 1. Release clusters allocated to target inode  | 
|---|
 | 1554 |         //    and synchronize the FAT on IOC device if last link. | 
|---|
 | 1555 |         if( inode_links == 1 )  | 
|---|
| [602] | 1556 |         { | 
|---|
| [610] | 1557 |             // build extended pointer on target inode "children" number | 
|---|
 | 1558 |             xptr_t inode_children_xp = XPTR( inode_cxy , &inode_ptr->children.items ); | 
|---|
| [602] | 1559 |  | 
|---|
| [610] | 1560 |             // get target inode number of children  | 
|---|
 | 1561 |             inode_children = hal_remote_l32( inode_children_xp ); | 
|---|
 | 1562 |  | 
|---|
 | 1563 |             // check no children | 
|---|
 | 1564 |             if( inode_children != 0 ) | 
|---|
 | 1565 |             { | 
|---|
 | 1566 |                 remote_rwlock_wr_release( lock_xp ); | 
|---|
 | 1567 |                 printk("\n[ERROR] in %s : cannot remove <%s> inode that has children\n", | 
|---|
 | 1568 |                 __FUNCTION__, path ); | 
|---|
 | 1569 |                 return -1; | 
|---|
 | 1570 |             } | 
|---|
 | 1571 |  | 
|---|
 | 1572 |             // release clusters on IOC device | 
|---|
 | 1573 |             error = vfs_fs_release_inode( inode_xp );  | 
|---|
 | 1574 |  | 
|---|
 | 1575 |             if( error ) | 
|---|
 | 1576 |             { | 
|---|
 | 1577 |                 remote_rwlock_wr_release( lock_xp ); | 
|---|
 | 1578 |                 printk("\n[ERROR] in %s : cannot update FAT mapper to remove <%s> inode\n", | 
|---|
 | 1579 |                 __FUNCTION__ , path ); | 
|---|
 | 1580 |                 return -1; | 
|---|
 | 1581 |             } | 
|---|
 | 1582 |  | 
|---|
| [602] | 1583 | #if(DEBUG_VFS_UNLINK & 1) | 
|---|
 | 1584 | if( DEBUG_VFS_UNLINK < cycle ) | 
|---|
 | 1585 | printk("\n[%s] thread[%x,%x] removed <%s> inode from FAT (mapper and IOC device)\n", | 
|---|
| [610] | 1586 | __FUNCTION__, process->pid, this->trdid, path ); | 
|---|
| [602] | 1587 | #endif | 
|---|
| [610] | 1588 |         } | 
|---|
| [602] | 1589 |  | 
|---|
| [610] | 1590 |         // 2. update parent directory mapper | 
|---|
 | 1591 |         //    and synchronize the parent directory on IOC device | 
|---|
 | 1592 |         if (parent_cxy == local_cxy) | 
|---|
| [602] | 1593 |         { | 
|---|
| [610] | 1594 |             error = vfs_fs_remove_dentry( parent_ptr, | 
|---|
| [602] | 1595 |                                           dentry_ptr ); | 
|---|
 | 1596 |         } | 
|---|
| [610] | 1597 |         else             | 
|---|
| [602] | 1598 |         { | 
|---|
| [610] | 1599 |             rpc_vfs_fs_remove_dentry_client( parent_cxy, | 
|---|
 | 1600 |                                              parent_ptr, | 
|---|
| [602] | 1601 |                                              dentry_ptr, | 
|---|
 | 1602 |                                              &error ); | 
|---|
 | 1603 |         } | 
|---|
| [610] | 1604 |  | 
|---|
| [602] | 1605 |         if( error ) | 
|---|
 | 1606 |         { | 
|---|
| [610] | 1607 |             remote_rwlock_wr_release( lock_xp ); | 
|---|
 | 1608 |             printk("\n[ERROR] in %s : cannot update dentry on device for <%s>\n", | 
|---|
 | 1609 |             __FUNCTION__ , path ); | 
|---|
| [602] | 1610 |             return -1; | 
|---|
 | 1611 |         } | 
|---|
 | 1612 |  | 
|---|
 | 1613 | #if(DEBUG_VFS_UNLINK & 1) | 
|---|
 | 1614 | if( DEBUG_VFS_UNLINK < cycle ) | 
|---|
 | 1615 | printk("\n[%s] thread[%x,%x] removed <%s> inode from parent dir (mapper and IOC device)\n", | 
|---|
| [610] | 1616 | __FUNCTION__, process->pid, this->trdid, path ); | 
|---|
| [602] | 1617 | #endif | 
|---|
| [610] | 1618 |         // 3. remove dentry from Inode Tree (and associated chils inode when last link) | 
|---|
 | 1619 |         vfs_remove_child_from_parent( dentry_xp ); | 
|---|
| [602] | 1620 |  | 
|---|
| [610] | 1621 |         // release the lock protecting Inode Tree | 
|---|
 | 1622 |         remote_rwlock_wr_release( lock_xp ); | 
|---|
 | 1623 |  | 
|---|
| [602] | 1624 | #if DEBUG_VFS_UNLINK | 
|---|
 | 1625 | if( DEBUG_VFS_UNLINK < cycle ) | 
|---|
 | 1626 | printk("\n[%s] thread[%x,%x] exit / removed <%s> inode from Inode Tree / cycle %d\n", | 
|---|
| [610] | 1627 | __FUNCTION__, process->pid, this->trdid, path, cycle ); | 
|---|
| [602] | 1628 | #endif | 
|---|
 | 1629 |         return 0; | 
|---|
 | 1630 |     } | 
|---|
 | 1631 |     else | 
|---|
 | 1632 |     { | 
|---|
| [610] | 1633 |         remote_rwlock_wr_release( lock_xp ); | 
|---|
 | 1634 |         printk("\n[ERROR] in %s : unsupported inode type %s\n", | 
|---|
 | 1635 |         __FUNCTION__ , vfs_inode_type_str( inode_type ) ); | 
|---|
| [602] | 1636 |         return -1; | 
|---|
 | 1637 |     } | 
|---|
 | 1638 |  | 
|---|
 | 1639 | }  // end vfs_unlink()  | 
|---|
 | 1640 |  | 
|---|
| [611] | 1641 | //////////////////////////////////////////////// | 
|---|
 | 1642 | error_t vfs_stat( xptr_t         root_inode_xp, | 
|---|
 | 1643 |                   char         * path, | 
|---|
 | 1644 |                   struct stat  * st ) | 
|---|
| [1] | 1645 | { | 
|---|
| [610] | 1646 |     error_t       error; | 
|---|
 | 1647 |     xptr_t        inode_xp;           // extended pointer on target inode | 
|---|
 | 1648 |     vfs_inode_t * inode_ptr;          // local pointer on target inode | 
|---|
 | 1649 |     cxy_t         inode_cxy;          // target inode cluster identifier | 
|---|
 | 1650 |     xptr_t        vfs_root_xp;        // extended pointer on VFS root inode | 
|---|
 | 1651 |     vfs_inode_t * vfs_root_ptr;       // local_pointer on VFS root inode | 
|---|
 | 1652 |     cxy_t         vfs_root_cxy;       // VFS root inode cluster identifier | 
|---|
 | 1653 |     xptr_t        lock_xp;            // extended pointer on lock protecting Inode Tree | 
|---|
 | 1654 |  | 
|---|
 | 1655 |     thread_t  * this    = CURRENT_THREAD; | 
|---|
 | 1656 |     process_t * process = this->process; | 
|---|
 | 1657 |  | 
|---|
 | 1658 |     // build extended pointer on lock protecting Inode Tree (in VFS root inode) | 
|---|
 | 1659 |     vfs_root_xp  = process->vfs_root_xp; | 
|---|
 | 1660 |     vfs_root_ptr = GET_PTR( vfs_root_xp ); | 
|---|
 | 1661 |     vfs_root_cxy = GET_CXY( vfs_root_xp ); | 
|---|
 | 1662 |     lock_xp      = XPTR( vfs_root_cxy , &vfs_root_ptr->main_lock ); | 
|---|
 | 1663 |  | 
|---|
 | 1664 |     // get the lock protecting Inode Tree in read mode | 
|---|
 | 1665 |     remote_rwlock_rd_acquire( lock_xp ); | 
|---|
 | 1666 |  | 
|---|
 | 1667 |     // get extended pointer on target inode | 
|---|
 | 1668 |     error = vfs_lookup( root_inode_xp, | 
|---|
 | 1669 |                         path, | 
|---|
 | 1670 |                         0, | 
|---|
 | 1671 |                         &inode_xp, | 
|---|
 | 1672 |                         NULL ); | 
|---|
 | 1673 |  | 
|---|
 | 1674 |     // release the lock protecting Inode Tree | 
|---|
 | 1675 |     remote_rwlock_rd_release( lock_xp ); | 
|---|
 | 1676 |  | 
|---|
 | 1677 |     if( error ) | 
|---|
 | 1678 |     { | 
|---|
 | 1679 |         printk("\n[ERROR] in %s : cannot found inode <%s>\n", | 
|---|
 | 1680 |         __FUNCTION__ , path ); | 
|---|
 | 1681 |         return -1; | 
|---|
 | 1682 |     } | 
|---|
 | 1683 |  | 
|---|
| [598] | 1684 |     // get cluster and local pointer on inode descriptor | 
|---|
| [610] | 1685 |     inode_ptr = GET_PTR( inode_xp ); | 
|---|
 | 1686 |     inode_cxy = GET_CXY( inode_xp ); | 
|---|
| [598] | 1687 |  | 
|---|
 | 1688 |     // get relevant infos from inode descriptor | 
|---|
 | 1689 |     uint32_t inum   = hal_remote_l32( XPTR( inode_cxy , &inode_ptr->inum   ) ); | 
|---|
 | 1690 |     uint32_t size   = hal_remote_l32( XPTR( inode_cxy , &inode_ptr->size   ) ); | 
|---|
 | 1691 |     uint32_t uid    = hal_remote_l32( XPTR( inode_cxy , &inode_ptr->uid    ) ); | 
|---|
 | 1692 |     uint32_t gid    = hal_remote_l32( XPTR( inode_cxy , &inode_ptr->gid    ) ); | 
|---|
 | 1693 |     uint32_t type   = hal_remote_l32( XPTR( inode_cxy , &inode_ptr->type   ) ); | 
|---|
 | 1694 |     uint32_t rights = hal_remote_l32( XPTR( inode_cxy , &inode_ptr->rights ) ); | 
|---|
 | 1695 |  | 
|---|
 | 1696 |     // set stat structure fields  | 
|---|
 | 1697 |     st->st_ino  = inum; | 
|---|
 | 1698 |     st->st_gid  = gid; | 
|---|
 | 1699 |     st->st_uid  = uid; | 
|---|
 | 1700 |     st->st_size = size; | 
|---|
 | 1701 |     st->st_mode = (type << 16) | rights; | 
|---|
 | 1702 |  | 
|---|
 | 1703 | #if DEBUG_VFS_STAT | 
|---|
 | 1704 | uint32_t cycle  = (uint32_t)hal_get_cycles(); | 
|---|
 | 1705 | if( DEBUG_VFS_STAT < cycle ) | 
|---|
 | 1706 | printk("\n[%s] thread[%x,%x] set stat %x for inode %x in cluster %x / cycle %d\n" | 
|---|
 | 1707 |        " %s / inum %d / size %d\n", | 
|---|
| [610] | 1708 | __FUNCTION__, process->pid, this->trdid, st, inode_ptr, inode_cxy, cycle, | 
|---|
| [598] | 1709 | vfs_inode_type_str( type ), inum, size ); | 
|---|
 | 1710 | #endif | 
|---|
 | 1711 |  | 
|---|
| [1] | 1712 |     return 0; | 
|---|
 | 1713 |  | 
|---|
| [602] | 1714 | }  // end vfs_stat() | 
|---|
 | 1715 |  | 
|---|
| [407] | 1716 | ///////////////////////////////////////////// | 
|---|
 | 1717 | error_t vfs_readdir( xptr_t          file_xp, | 
|---|
 | 1718 |                      struct dirent * k_dirent ) | 
|---|
| [1] | 1719 | { | 
|---|
| [492] | 1720 |     assert( false , "not implemented file_xp: %x, k_dirent ptr %x\n", | 
|---|
 | 1721 |       file_xp, k_dirent ); | 
|---|
| [1] | 1722 |     return 0; | 
|---|
 | 1723 | } | 
|---|
 | 1724 |  | 
|---|
| [23] | 1725 | //////////////////////////////////// | 
|---|
 | 1726 | error_t vfs_rmdir( xptr_t   file_xp, | 
|---|
 | 1727 |                    char   * path ) | 
|---|
| [1] | 1728 | { | 
|---|
| [492] | 1729 |     assert( false , "not implemented file_xp: %x, path <%s>\n", | 
|---|
 | 1730 |       file_xp, path ); | 
|---|
| [1] | 1731 |     return 0; | 
|---|
 | 1732 | } | 
|---|
 | 1733 |  | 
|---|
| [610] | 1734 | //////////////////////////////////// | 
|---|
 | 1735 | error_t vfs_chdir( xptr_t   root_xp, | 
|---|
| [23] | 1736 |                    char   * path ) | 
|---|
| [1] | 1737 | { | 
|---|
| [23] | 1738 |     error_t           error; | 
|---|
| [610] | 1739 |     xptr_t            inode_xp;           // extended pointer on target inode | 
|---|
 | 1740 |     cxy_t             inode_cxy;          // target inode cluster identifier        | 
|---|
 | 1741 |     vfs_inode_t     * inode_ptr;          // target inode local pointer | 
|---|
 | 1742 |     vfs_inode_type_t  inode_type;         // target inode type | 
|---|
 | 1743 |     xptr_t            vfs_root_xp;        // extended pointer on VFS root inode | 
|---|
 | 1744 |     vfs_inode_t     * vfs_root_ptr;       // local_pointer on VFS root inode | 
|---|
 | 1745 |     cxy_t             vfs_root_cxy;       // VFS root inode cluster identifier | 
|---|
 | 1746 |     xptr_t            main_lock_xp;       // extended pointer on lock protecting Inode Tree | 
|---|
 | 1747 |     xptr_t            ref_xp;             // extended pointer on reference process | 
|---|
 | 1748 |     process_t       * ref_ptr;            // local pointer on reference process | 
|---|
 | 1749 |     cxy_t             ref_cxy;            // reference process cluster | 
|---|
 | 1750 |     xptr_t            cwd_lock_xp;        // extended pointer on lock protecting CWD change | 
|---|
 | 1751 |     xptr_t            cwd_xp_xp;          // extended pointer on cwd_xp in reference process | 
|---|
| [23] | 1752 |  | 
|---|
| [610] | 1753 |     thread_t  * this    = CURRENT_THREAD; | 
|---|
 | 1754 |     process_t * process = this->process; | 
|---|
| [23] | 1755 |  | 
|---|
| [610] | 1756 | #if DEBUG_VFS_CHDIR | 
|---|
 | 1757 | uint32_t cycle = (uint32_t)hal_get_cycles(); | 
|---|
 | 1758 | if( DEBUG_VFS_CHDIR < cycle ) | 
|---|
 | 1759 | printk("\n[%s] thread[%x,%x] enter for path <%s> / cycle %d\n", | 
|---|
 | 1760 | __FUNCTION__, process->pid, this->trdid, path, cycle ); | 
|---|
 | 1761 | #endif | 
|---|
 | 1762 |  | 
|---|
 | 1763 |     // build extended pointer on lock protecting Inode Tree (in VFS root inode) | 
|---|
 | 1764 |     vfs_root_xp  = process->vfs_root_xp; | 
|---|
 | 1765 |     vfs_root_ptr = GET_PTR( vfs_root_xp ); | 
|---|
 | 1766 |     vfs_root_cxy = GET_CXY( vfs_root_xp ); | 
|---|
 | 1767 |     main_lock_xp = XPTR( vfs_root_cxy , &vfs_root_ptr->main_lock ); | 
|---|
 | 1768 |  | 
|---|
 | 1769 |     // take lock protecting Inode Tree in read mode | 
|---|
 | 1770 |     remote_rwlock_rd_acquire( main_lock_xp ); | 
|---|
 | 1771 |  | 
|---|
| [23] | 1772 |     // get extended pointer on target inode | 
|---|
| [610] | 1773 |     error = vfs_lookup( root_xp, | 
|---|
 | 1774 |                         path, | 
|---|
 | 1775 |                         VFS_LOOKUP_DIR, | 
|---|
 | 1776 |                         &inode_xp, | 
|---|
 | 1777 |                         NULL ); | 
|---|
| [23] | 1778 |  | 
|---|
| [610] | 1779 |     // release lock protecting Inode Tree in read mode | 
|---|
 | 1780 |     remote_rwlock_rd_release( main_lock_xp ); | 
|---|
| [23] | 1781 |  | 
|---|
| [610] | 1782 |     if( error )  | 
|---|
 | 1783 |     { | 
|---|
 | 1784 |         printk("\n[ERROR] in %s : <%s> not found\n", | 
|---|
 | 1785 |         __FUNCTION__, path ); | 
|---|
 | 1786 |         return -1; | 
|---|
 | 1787 |     } | 
|---|
 | 1788 |  | 
|---|
 | 1789 |     // get inode type from remote file | 
|---|
| [23] | 1790 |     inode_cxy = GET_CXY( inode_xp ); | 
|---|
| [473] | 1791 |     inode_ptr = GET_PTR( inode_xp ); | 
|---|
| [568] | 1792 |     inode_type = hal_remote_l32( XPTR( inode_cxy , &inode_ptr->type ) ); | 
|---|
| [23] | 1793 |  | 
|---|
 | 1794 |     if( inode_type != INODE_TYPE_DIR ) | 
|---|
 | 1795 |     { | 
|---|
| [610] | 1796 |         printk("\n[ERROR] in %s : <%s> is not a directory\n", | 
|---|
 | 1797 |         __FUNCTION__, path ); | 
|---|
| [23] | 1798 |         return -1; | 
|---|
 | 1799 |     } | 
|---|
 | 1800 |  | 
|---|
| [610] | 1801 |     // build extended pointer on cwd_lock and cwd_xp  | 
|---|
 | 1802 |     ref_xp       = process->ref_xp; | 
|---|
 | 1803 |     ref_ptr      = GET_PTR( ref_xp ); | 
|---|
 | 1804 |     ref_cxy      = GET_CXY( ref_xp ); | 
|---|
 | 1805 |     cwd_lock_xp  = XPTR( ref_cxy , &ref_ptr->cwd_lock ); | 
|---|
 | 1806 |     cwd_xp_xp    = XPTR( ref_cxy , &ref_ptr->cwd_xp ); | 
|---|
| [568] | 1807 |  | 
|---|
| [610] | 1808 |     // take lock protecting CWD changes | 
|---|
 | 1809 |     remote_busylock_acquire( cwd_lock_xp ); | 
|---|
| [568] | 1810 |  | 
|---|
| [610] | 1811 |     // update cwd_xp field in reference process descriptor | 
|---|
 | 1812 |     hal_remote_s64( cwd_xp_xp , inode_xp ); | 
|---|
 | 1813 |  | 
|---|
 | 1814 |     // release lock protecting CWD changes | 
|---|
 | 1815 |     remote_busylock_release( cwd_lock_xp ); | 
|---|
 | 1816 |  | 
|---|
 | 1817 | #if DEBUG_VFS_CHDIR | 
|---|
 | 1818 | cycle = (uint32_t)hal_get_cycles(); | 
|---|
 | 1819 | if( DEBUG_VFS_CHDIR < cycle ) | 
|---|
 | 1820 | printk("\n[%s] thread[%x,%x] exit : inode (%x,%x) / &cwd_xp (%x,%x) / cycle %d\n", | 
|---|
 | 1821 | __FUNCTION__, process->pid, this->trdid, inode_cxy, inode_ptr,  | 
|---|
 | 1822 | GET_CXY(cwd_xp_xp), GET_PTR(cwd_xp_xp), cycle ); | 
|---|
 | 1823 | #endif | 
|---|
 | 1824 |  | 
|---|
| [1] | 1825 |     return 0; | 
|---|
 | 1826 |  | 
|---|
| [610] | 1827 | }  // end vfs_chdir() | 
|---|
 | 1828 |  | 
|---|
| [23] | 1829 | /////////////////////////////////// | 
|---|
 | 1830 | error_t vfs_chmod( xptr_t   cwd_xp, | 
|---|
 | 1831 |                    char   * path, | 
|---|
 | 1832 |                    uint32_t rights ) | 
|---|
| [1] | 1833 | { | 
|---|
| [23] | 1834 |     error_t           error; | 
|---|
 | 1835 |     xptr_t            inode_xp;     // extended pointer on target inode | 
|---|
 | 1836 |     cxy_t             inode_cxy;    // inode cluster identifier        | 
|---|
 | 1837 |     vfs_inode_t     * inode_ptr;    // inode local pointer | 
|---|
 | 1838 |     vfs_inode_type_t  inode_type;   // target inode type | 
|---|
 | 1839 |  | 
|---|
 | 1840 |     // set lookup working mode | 
|---|
| [473] | 1841 |     assert( (rights == 0), __FUNCTION__, | 
|---|
 | 1842 |     "access rights non implemented yet\n" ); | 
|---|
| [23] | 1843 |   | 
|---|
 | 1844 |     // get extended pointer on target inode | 
|---|
| [610] | 1845 |     error = vfs_lookup( cwd_xp, | 
|---|
 | 1846 |                         path, | 
|---|
 | 1847 |                         0, | 
|---|
 | 1848 |                         &inode_xp, | 
|---|
 | 1849 |                         NULL ); | 
|---|
| [23] | 1850 |  | 
|---|
 | 1851 |     if( error ) return error; | 
|---|
 | 1852 |  | 
|---|
 | 1853 |     // get inode cluster and local pointer | 
|---|
 | 1854 |     inode_cxy = GET_CXY( inode_xp ); | 
|---|
| [473] | 1855 |     inode_ptr = GET_PTR( inode_xp ); | 
|---|
| [23] | 1856 |      | 
|---|
 | 1857 |     // get inode type from remote inode | 
|---|
| [568] | 1858 |     inode_type = hal_remote_l32( XPTR( inode_cxy , &inode_ptr->type ) ); | 
|---|
| [23] | 1859 |  | 
|---|
| [610] | 1860 |     // TODO implement this function | 
|---|
 | 1861 |  | 
|---|
 | 1862 | assert( false , "not implemented\n" ); | 
|---|
 | 1863 |  | 
|---|
| [1] | 1864 |     return 0; | 
|---|
 | 1865 | } | 
|---|
 | 1866 |  | 
|---|
| [23] | 1867 | /////////////////////////////////// | 
|---|
 | 1868 | error_t vfs_mkfifo( xptr_t   cwd_xp, | 
|---|
 | 1869 |                     char   * path, | 
|---|
 | 1870 |                     uint32_t rights ) | 
|---|
 | 1871 | { | 
|---|
| [492] | 1872 |     assert( false , "not implemented cwd_xp: %x, path <%s>, rights %x\n", | 
|---|
 | 1873 |       cwd_xp, path, rights ); | 
|---|
| [23] | 1874 |     return 0; | 
|---|
 | 1875 | } | 
|---|
| [1] | 1876 |  | 
|---|
 | 1877 |  | 
|---|
 | 1878 |  | 
|---|
| [188] | 1879 | ////////////////////////////////////////////////////////////////////////////////////////// | 
|---|
| [602] | 1880 | //       Distributed Inode Tree access related functions | 
|---|
| [1] | 1881 | ////////////////////////////////////////////////////////////////////////////////////////// | 
|---|
 | 1882 |  | 
|---|
| [188] | 1883 | ////////////////////////////////////////////////////////////////////////// | 
|---|
 | 1884 | // This static function is called by the vfs_display() function. | 
|---|
| [337] | 1885 | // that is supposed to take the TXT0 lock. | 
|---|
| [188] | 1886 | ////////////////////////////////////////////////////////////////////////// | 
|---|
 | 1887 | static void vfs_recursive_display( xptr_t   inode_xp, | 
|---|
 | 1888 |                                    xptr_t   name_xp, | 
|---|
 | 1889 |                                    uint32_t indent ) | 
|---|
 | 1890 | { | 
|---|
 | 1891 |     cxy_t              inode_cxy; | 
|---|
 | 1892 |     vfs_inode_t      * inode_ptr; | 
|---|
 | 1893 |     vfs_inode_type_t   inode_type; | 
|---|
| [598] | 1894 |     uint32_t           inode_size; | 
|---|
 | 1895 |     uint32_t           inode_inum; | 
|---|
 | 1896 |     uint32_t           inode_attr; | 
|---|
 | 1897 |     uint32_t           inode_dirty; | 
|---|
| [204] | 1898 |     xptr_t             children_xp;    // extended pointer on children xhtab | 
|---|
| [188] | 1899 |  | 
|---|
| [204] | 1900 |     xptr_t             child_dentry_xp; | 
|---|
 | 1901 |     cxy_t              child_dentry_cxy; | 
|---|
 | 1902 |     vfs_dentry_t     * child_dentry_ptr; | 
|---|
 | 1903 |     xptr_t             child_inode_xp; | 
|---|
 | 1904 |     xptr_t             child_dentry_name_xp; | 
|---|
| [598] | 1905 |     mapper_t         * mapper_ptr; | 
|---|
| [188] | 1906 |  | 
|---|
 | 1907 |     char               name[CONFIG_VFS_MAX_NAME_LENGTH]; | 
|---|
 | 1908 |  | 
|---|
 | 1909 |     char *             indent_str[] = { "",                                  // level 0 | 
|---|
 | 1910 |                                         "  ",                                // level 1 | 
|---|
 | 1911 |                                         "    ",                              // level 2 | 
|---|
 | 1912 |                                         "      ",                            // level 3 | 
|---|
 | 1913 |                                         "        ",                          // level 4 | 
|---|
 | 1914 |                                         "          ",                        // level 5 | 
|---|
 | 1915 |                                         "            ",                      // level 6 | 
|---|
 | 1916 |                                         "              ",                    // level 7 | 
|---|
 | 1917 |                                         "                ",                  // level 8 | 
|---|
 | 1918 |                                         "                  ",                // level 9 | 
|---|
 | 1919 |                                         "                    ",              // level 10 | 
|---|
 | 1920 |                                         "                      ",            // level 11 | 
|---|
 | 1921 |                                         "                        ",          // level 12 | 
|---|
 | 1922 |                                         "                          ",        // level 13 | 
|---|
 | 1923 |                                         "                            ",      // level 14 | 
|---|
 | 1924 |                                         "                              " };  // level 15 | 
|---|
 | 1925 |  | 
|---|
| [598] | 1926 | assert( (inode_xp != XPTR_NULL) , "inode_xp cannot be NULL\n" ); | 
|---|
 | 1927 | assert( (name_xp  != XPTR_NULL) , "name_xp cannot be NULL\n" ); | 
|---|
 | 1928 | assert( (indent < 16)           , "depth cannot be larger than 15\n" ); | 
|---|
| [188] | 1929 |      | 
|---|
| [610] | 1930 |     // get current inode cluster and local pointer | 
|---|
| [188] | 1931 |     inode_cxy = GET_CXY( inode_xp ); | 
|---|
| [473] | 1932 |     inode_ptr = GET_PTR( inode_xp ); | 
|---|
| [188] | 1933 |  | 
|---|
| [598] | 1934 |     // get inode type, size, attr, mapper, and inum | 
|---|
 | 1935 |     inode_type = hal_remote_l32( XPTR( inode_cxy , &inode_ptr->type   ) ); | 
|---|
 | 1936 |     inode_size = hal_remote_l32( XPTR( inode_cxy , &inode_ptr->size   ) ); | 
|---|
 | 1937 |     inode_inum = hal_remote_l32( XPTR( inode_cxy , &inode_ptr->inum   ) ); | 
|---|
 | 1938 |     inode_attr = hal_remote_l32( XPTR( inode_cxy , &inode_ptr->attr   ) ); | 
|---|
 | 1939 |     mapper_ptr = hal_remote_lpt( XPTR( inode_cxy , &inode_ptr->mapper ) ); | 
|---|
| [188] | 1940 |  | 
|---|
 | 1941 |     // make a local copy of node name | 
|---|
 | 1942 |     hal_remote_strcpy( XPTR( local_cxy , name ) , name_xp ); | 
|---|
 | 1943 |  | 
|---|
| [598] | 1944 |     // compute dirty | 
|---|
 | 1945 |     inode_dirty = ((inode_attr & INODE_ATTR_DIRTY) != 0); | 
|---|
 | 1946 |  | 
|---|
| [188] | 1947 |     // display inode | 
|---|
| [614] | 1948 |     nolock_printk("%s<%s> : %s / inum %d / %d bytes / dirty %d / cxy %x / inode %x / mapper %x\n", | 
|---|
 | 1949 |                   indent_str[indent], name, vfs_inode_type_str( inode_type ), | 
|---|
| [598] | 1950 |                   inode_inum, inode_size, inode_dirty, inode_cxy, inode_ptr, mapper_ptr ); | 
|---|
| [188] | 1951 |  | 
|---|
| [611] | 1952 |     // scan directory entries when current inode is a directory | 
|---|
 | 1953 |     // don't scan the the "." and ".." directories to break loops  | 
|---|
 | 1954 |     if( (inode_type == INODE_TYPE_DIR) &&  | 
|---|
 | 1955 |         (strcmp( name , "." ) != 0)    && | 
|---|
 | 1956 |         (strcmp( name , ".." ) != 0) ) | 
|---|
| [188] | 1957 |     { | 
|---|
 | 1958 |         // get extended pointer on directory entries xhtab | 
|---|
| [204] | 1959 |         children_xp =  XPTR( inode_cxy , &inode_ptr->children ); | 
|---|
| [188] | 1960 |  | 
|---|
 | 1961 |         // get xhtab lock | 
|---|
| [568] | 1962 |         xhtab_lock( children_xp ); | 
|---|
| [188] | 1963 |  | 
|---|
 | 1964 |         // get first dentry from xhtab | 
|---|
| [204] | 1965 |         child_dentry_xp = xhtab_get_first( children_xp ); | 
|---|
| [188] | 1966 |  | 
|---|
| [204] | 1967 |         while( child_dentry_xp != XPTR_NULL ) | 
|---|
| [188] | 1968 |         { | 
|---|
 | 1969 |             // get dentry cluster and local pointer | 
|---|
| [204] | 1970 |             child_dentry_cxy = GET_CXY( child_dentry_xp ); | 
|---|
| [473] | 1971 |             child_dentry_ptr = GET_PTR( child_dentry_xp ); | 
|---|
| [188] | 1972 |  | 
|---|
 | 1973 |             // get extended pointer on child inode | 
|---|
| [568] | 1974 |             child_inode_xp = hal_remote_l64( XPTR( child_dentry_cxy, | 
|---|
| [204] | 1975 |                                                    &child_dentry_ptr->child_xp ) ); | 
|---|
| [188] | 1976 |  | 
|---|
 | 1977 |             // get extended pointer on dentry name | 
|---|
| [204] | 1978 |             child_dentry_name_xp = XPTR( child_dentry_cxy , &child_dentry_ptr->name ); | 
|---|
| [188] | 1979 |  | 
|---|
| [568] | 1980 |             // recursive call on inode display | 
|---|
| [204] | 1981 |             vfs_recursive_display( child_inode_xp, | 
|---|
 | 1982 |                                    child_dentry_name_xp, | 
|---|
 | 1983 |                                    indent+1 ); | 
|---|
| [188] | 1984 |  | 
|---|
 | 1985 |             // get next dentry | 
|---|
| [204] | 1986 |             child_dentry_xp = xhtab_get_next( children_xp ); | 
|---|
| [188] | 1987 |         } | 
|---|
 | 1988 |  | 
|---|
 | 1989 |         // release xhtab lock | 
|---|
| [568] | 1990 |         xhtab_unlock( children_xp ); | 
|---|
| [188] | 1991 |     } | 
|---|
 | 1992 | }  // end vfs_recursive_display() | 
|---|
 | 1993 |  | 
|---|
 | 1994 | /////////////////////////////////// | 
|---|
 | 1995 | void vfs_display( xptr_t inode_xp ) | 
|---|
 | 1996 | { | 
|---|
| [204] | 1997 |     xptr_t         name_xp; | 
|---|
| [188] | 1998 |     xptr_t         dentry_xp;  | 
|---|
 | 1999 |     cxy_t          dentry_cxy; | 
|---|
 | 2000 |     vfs_dentry_t * dentry_ptr; | 
|---|
| [610] | 2001 |     xptr_t         parents_root_xp;   // root of parent dentries xlist | 
|---|
| [188] | 2002 |  | 
|---|
 | 2003 |     // get target inode cluster and local pointer  | 
|---|
 | 2004 |     cxy_t         inode_cxy = GET_CXY( inode_xp ); | 
|---|
| [473] | 2005 |     vfs_inode_t * inode_ptr = GET_PTR( inode_xp ); | 
|---|
| [188] | 2006 |  | 
|---|
| [610] | 2007 |     // build extended pointer on parents dentries root | 
|---|
 | 2008 |     parents_root_xp = XPTR( inode_cxy , &inode_ptr->parents ); | 
|---|
| [188] | 2009 |  | 
|---|
| [610] | 2010 |     // check VFS root      | 
|---|
 | 2011 |     if( xlist_is_empty( parents_root_xp ) )  // inode is the VFS root | 
|---|
| [188] | 2012 |     { | 
|---|
 | 2013 |         // build extended pointer on root name | 
|---|
 | 2014 |         name_xp = XPTR( local_cxy , "/" ); | 
|---|
 | 2015 |     } | 
|---|
 | 2016 |     else | 
|---|
 | 2017 |     { | 
|---|
| [610] | 2018 |         // get first parent dentry cluster and pointers | 
|---|
 | 2019 |         dentry_xp  = XLIST_FIRST( parents_root_xp , vfs_dentry_t , parents ); | 
|---|
| [188] | 2020 |         dentry_cxy = GET_CXY( dentry_xp ); | 
|---|
| [473] | 2021 |         dentry_ptr = GET_PTR( dentry_xp ); | 
|---|
| [188] | 2022 |  | 
|---|
 | 2023 |         // get extended pointer on dentry name | 
|---|
 | 2024 |         name_xp = XPTR( dentry_cxy , &dentry_ptr->name ); | 
|---|
 | 2025 |     } | 
|---|
 | 2026 |  | 
|---|
| [337] | 2027 |     // get pointers on TXT0 chdev | 
|---|
| [407] | 2028 |     xptr_t    txt0_xp  = chdev_dir.txt_tx[0]; | 
|---|
| [337] | 2029 |     cxy_t     txt0_cxy = GET_CXY( txt0_xp ); | 
|---|
 | 2030 |     chdev_t * txt0_ptr = GET_PTR( txt0_xp ); | 
|---|
 | 2031 |  | 
|---|
 | 2032 |     // get extended pointer on remote TXT0 chdev lock | 
|---|
 | 2033 |     xptr_t  lock_xp = XPTR( txt0_cxy , &txt0_ptr->wait_lock ); | 
|---|
 | 2034 |  | 
|---|
 | 2035 |     // get TXT0 lock in busy waiting mode | 
|---|
| [568] | 2036 |     remote_busylock_acquire( lock_xp ); | 
|---|
| [337] | 2037 |  | 
|---|
| [188] | 2038 |     // print header | 
|---|
| [401] | 2039 |     nolock_printk("\n***** file system state\n\n"); | 
|---|
| [188] | 2040 |  | 
|---|
 | 2041 |     // call recursive function | 
|---|
| [473] | 2042 |     vfs_recursive_display( inode_xp , name_xp , 0 ); | 
|---|
| [188] | 2043 |  | 
|---|
| [337] | 2044 |     // release lock | 
|---|
| [568] | 2045 |     remote_busylock_release( lock_xp ); | 
|---|
| [337] | 2046 |  | 
|---|
| [204] | 2047 | }  // end vfs_display() | 
|---|
| [188] | 2048 |  | 
|---|
| [602] | 2049 | /* | 
|---|
| [1] | 2050 | ////////////////////////////////////////////////////////////////////////////////////////// | 
|---|
| [602] | 2051 | // This static function is used by the vfs_lookup() function. | 
|---|
| [1] | 2052 | // It takes an extended pointer on a remote inode (parent directory inode), | 
|---|
 | 2053 | // and check access_rights violation for the calling thread. | 
|---|
 | 2054 | // It can be used by any thread running in any cluster. | 
|---|
 | 2055 | ////////////////////////////////////////////////////////////////////////////////////////// | 
|---|
 | 2056 | // @ inode_xp    : extended pointer on inode. | 
|---|
 | 2057 | // @ client_uid  : client thread user ID | 
|---|
 | 2058 | // @ client_gid  : client thread group ID | 
|---|
 | 2059 | // @ return true if access rights are violated. | 
|---|
 | 2060 | ////////////////////////////////////////////////////////////////////////////////////////// | 
|---|
| [602] | 2061 | static bool_t vfs_access_denied( xptr_t   inode_xp, | 
|---|
| [1] | 2062 |                           uint32_t client_uid, | 
|---|
 | 2063 |                           uint32_t client_gid ) | 
|---|
 | 2064 | { | 
|---|
 | 2065 |     // get found inode cluster and local pointer | 
|---|
 | 2066 |     cxy_t         inode_cxy = GET_CXY( inode_xp ); | 
|---|
| [473] | 2067 |     vfs_inode_t * inode_ptr = GET_PTR( inode_xp ); | 
|---|
| [1] | 2068 |  | 
|---|
 | 2069 |     // get inode access mode, UID, and GID | 
|---|
| [568] | 2070 |     // TODO uint32_t  mode = hal_remote_l32( XPTR( inode_cxy , &inode_ptr->mode ) ); | 
|---|
 | 2071 |     uid_t     uid  = hal_remote_l32( XPTR( inode_cxy , &inode_ptr->uid  ) ); | 
|---|
 | 2072 |     gid_t     gid  = hal_remote_l32( XPTR( inode_cxy , &inode_ptr->gid  ) ); | 
|---|
| [1] | 2073 |  | 
|---|
 | 2074 |     // FIXME : me must use mode | 
|---|
 | 2075 |     if( (uid == client_uid) || (gid == client_gid) ) return false; | 
|---|
 | 2076 |     else                                             return true; | 
|---|
 | 2077 | } | 
|---|
| [602] | 2078 | */ | 
|---|
| [1] | 2079 |  | 
|---|
 | 2080 | ////////////////////////////////////////////////////////////////////////////////////////// | 
|---|
 | 2081 | // This static function is used by the vfs_lookup() function. | 
|---|
| [204] | 2082 | // It takes an extended pointer on a remote parent directory inode, a directory  | 
|---|
| [1] | 2083 | // entry name, and returns an extended pointer on the child inode.  | 
|---|
 | 2084 | // It can be used by any thread running in any cluster. | 
|---|
 | 2085 | ////////////////////////////////////////////////////////////////////////////////////////// | 
|---|
 | 2086 | // @ parent_xp   : extended pointer on parent inode in remote cluster. | 
|---|
 | 2087 | // @ name        : dentry name | 
|---|
 | 2088 | // @ child_xp    : [out] buffer for extended pointer on child inode. | 
|---|
 | 2089 | // @ return true if success / return false if not found. | 
|---|
 | 2090 | ////////////////////////////////////////////////////////////////////////////////////////// | 
|---|
 | 2091 | static bool_t vfs_get_child( xptr_t   parent_xp, | 
|---|
 | 2092 |                              char   * name, | 
|---|
 | 2093 |                              xptr_t * child_xp ) | 
|---|
 | 2094 | { | 
|---|
| [610] | 2095 |     xptr_t         xhtab_xp;    // extended pointer on hash table for children dentries | 
|---|
 | 2096 |     xptr_t         dentry_xp;   // extended pointer on children dentry | 
|---|
 | 2097 |     cxy_t          dentry_cxy; | 
|---|
 | 2098 |     vfs_dentry_t * dentry_ptr; | 
|---|
| [1] | 2099 |  | 
|---|
 | 2100 |     // get parent inode cluster and local pointer | 
|---|
 | 2101 |     cxy_t         parent_cxy = GET_CXY( parent_xp ); | 
|---|
| [473] | 2102 |     vfs_inode_t * parent_ptr = GET_PTR( parent_xp ); | 
|---|
| [1] | 2103 |  | 
|---|
 | 2104 |     // get extended pointer on hash table of children directory entries | 
|---|
 | 2105 |     xhtab_xp = XPTR( parent_cxy , &parent_ptr->children ); | 
|---|
 | 2106 |  | 
|---|
| [610] | 2107 |     // get pointers on matching dentry | 
|---|
 | 2108 |     dentry_xp  = xhtab_lookup( xhtab_xp , name ); | 
|---|
 | 2109 |     dentry_cxy = GET_CXY( dentry_xp ); | 
|---|
 | 2110 |     dentry_ptr = GET_PTR( dentry_xp ); | 
|---|
| [1] | 2111 |  | 
|---|
| [610] | 2112 |     if( dentry_xp == XPTR_NULL )  | 
|---|
 | 2113 |     { | 
|---|
 | 2114 |         return false; | 
|---|
 | 2115 |     } | 
|---|
 | 2116 |     else | 
|---|
 | 2117 |     { | 
|---|
 | 2118 |         *child_xp = (xptr_t)hal_remote_l64( XPTR( dentry_cxy , &dentry_ptr->child_xp ) ); | 
|---|
 | 2119 |         return true; | 
|---|
 | 2120 |     } | 
|---|
| [1] | 2121 |  | 
|---|
| [204] | 2122 | }  // end vfs_get_child() | 
|---|
 | 2123 |  | 
|---|
| [1] | 2124 | ////////////////////////////////////////////////////////////////////////////////////////// | 
|---|
 | 2125 | // This static function is used by the vfs_lookup() function. | 
|---|
 | 2126 | // It takes the <current> pointer on a buffer containing a complete pathname, and return | 
|---|
 | 2127 | // in the <name> buffer, allocated by the caller, a single name in the path. | 
|---|
 | 2128 | // It return also in the <next> pointer the next character to analyse in the path. | 
|---|
 | 2129 | // Finally it returns a <last> boolean, that is true when the returned <name> is the | 
|---|
 | 2130 | // last name in the path. The names are supposed to be separated by one or several '/' | 
|---|
 | 2131 | // characters, that are not written in  the <name> buffer. | 
|---|
| [610] | 2132 | //  | 
|---|
 | 2133 | // WARNING: the leading characters '/' in the path are skiped before analysis. | 
|---|
 | 2134 | //          The path "/" identifies the VFS root, and is therefore anaysed as an empty | 
|---|
 | 2135 | //          string. This empty string is dignaled by the (-1) return value.   | 
|---|
| [1] | 2136 | ////////////////////////////////////////////////////////////////////////////////////////// | 
|---|
 | 2137 | // @ current   : pointer on first character to analyse in buffer containing the path. | 
|---|
 | 2138 | // @ name      : [out] pointer on buffer allocated by the caller for the returned name. | 
|---|
 | 2139 | // @ next      : [out] pointer on next character to analyse in buffer containing the path. | 
|---|
 | 2140 | // @ last      : [out] true if the returned name is the last (NUL character found). | 
|---|
| [610] | 2141 | // @ return 0 if success / return -1 if string empty (first chracter is NUL). | 
|---|
| [1] | 2142 | ////////////////////////////////////////////////////////////////////////////////////////// | 
|---|
 | 2143 | static error_t vfs_get_name_from_path( char     * current, | 
|---|
 | 2144 |                                        char     * name, | 
|---|
 | 2145 |                                        char    ** next, | 
|---|
 | 2146 |                                        bool_t   * last ) | 
|---|
 | 2147 | { | 
|---|
 | 2148 |     char * ptr = current; | 
|---|
 | 2149 |  | 
|---|
 | 2150 |     // skip leading '/' characters | 
|---|
 | 2151 |     while( *ptr == '/' ) ptr++; | 
|---|
 | 2152 |  | 
|---|
| [610] | 2153 |     // signal empty string | 
|---|
 | 2154 |     if( *ptr == 0 ) | 
|---|
 | 2155 |     { | 
|---|
 | 2156 |         *last = true; | 
|---|
 | 2157 |         return -1; | 
|---|
 | 2158 |     } | 
|---|
| [1] | 2159 |  | 
|---|
 | 2160 |     // copy all characters in name until NUL or '/' | 
|---|
 | 2161 |     while( (*ptr != 0) && (*ptr !='/') )  *(name++) = *(ptr++); | 
|---|
 | 2162 |  | 
|---|
| [204] | 2163 |     // set NUL terminating character in name buffer | 
|---|
 | 2164 |     *(name++) = 0; | 
|---|
 | 2165 |  | 
|---|
| [1] | 2166 |     // return last an next | 
|---|
 | 2167 |     if( *ptr == 0 )             // last found character is NUL => last name in path | 
|---|
 | 2168 |     { | 
|---|
 | 2169 |         *last = true; | 
|---|
 | 2170 |     } | 
|---|
 | 2171 |     else                        // last found character is '/' => skip it  | 
|---|
 | 2172 |     { | 
|---|
 | 2173 |         *last = false; | 
|---|
 | 2174 |         *next = ptr + 1; | 
|---|
 | 2175 |     } | 
|---|
 | 2176 |  | 
|---|
 | 2177 |     return 0; | 
|---|
| [204] | 2178 |  | 
|---|
 | 2179 | }  // end vfs_get name_from_path() | 
|---|
| [188] | 2180 |     | 
|---|
| [610] | 2181 | /////////////////////////////////////////////// | 
|---|
 | 2182 | error_t vfs_lookup( xptr_t             root_xp, | 
|---|
| [23] | 2183 |                     char             * pathname, | 
|---|
| [610] | 2184 |                     uint32_t           lookup_mode, | 
|---|
 | 2185 |                                         xptr_t           * inode_xp, | 
|---|
 | 2186 |                                         char             * last_name ) | 
|---|
| [1] | 2187 | { | 
|---|
| [101] | 2188 |     char               name[CONFIG_VFS_MAX_NAME_LENGTH];   // one name in path  | 
|---|
| [1] | 2189 |  | 
|---|
| [23] | 2190 |     xptr_t             parent_xp;    // extended pointer on parent inode | 
|---|
 | 2191 |     cxy_t              parent_cxy;   // cluster for parent inode | 
|---|
 | 2192 |     vfs_inode_t      * parent_ptr;   // local pointer on parent inode   | 
|---|
| [602] | 2193 |     xptr_t             dentry_xp;    // extended pointer on dentry        | 
|---|
| [23] | 2194 |     xptr_t             child_xp;     // extended pointer on child inode | 
|---|
 | 2195 |     cxy_t              child_cxy;    // cluster for child inode | 
|---|
| [602] | 2196 |     vfs_inode_t      * child_ptr;    // local pointer on child inode | 
|---|
 | 2197 |     vfs_inode_type_t   child_type;   // child inode type | 
|---|
| [23] | 2198 |     vfs_fs_type_t      fs_type;      // File system type | 
|---|
 | 2199 |     vfs_ctx_t        * ctx_ptr;      // local pointer on FS context | 
|---|
 | 2200 |     char             * current;      // current pointer on path | 
|---|
 | 2201 |     char             * next;         // next value for current pointer    | 
|---|
 | 2202 |     bool_t             last;         // true when the name is the last in path | 
|---|
 | 2203 |     bool_t             found;        // true when a child has been found | 
|---|
| [459] | 2204 |     bool_t             dir;          // searched inode is a directory | 
|---|
 | 2205 |     bool_t             create;       // searched inode must be created if not found | 
|---|
 | 2206 |     bool_t             excl;         // searched inode must not exist | 
|---|
| [610] | 2207 |     bool_t             par;          // searched inode is the parent | 
|---|
| [23] | 2208 |     thread_t         * this;         // pointer on calling thread descriptor | 
|---|
 | 2209 |     process_t        * process;      // pointer on calling process descriptor | 
|---|
 | 2210 |     error_t            error; | 
|---|
| [1] | 2211 |  | 
|---|
 | 2212 |     this    = CURRENT_THREAD; | 
|---|
 | 2213 |     process = this->process; | 
|---|
 | 2214 |  | 
|---|
| [610] | 2215 | // check pathname / root_xp consistency | 
|---|
 | 2216 | assert( ((pathname[0] != '/') || (root_xp == process->vfs_root_xp)),  | 
|---|
 | 2217 | "root inode must be VFS root for path <%s>\n", pathname ); | 
|---|
 | 2218 |  | 
|---|
| [438] | 2219 | #if DEBUG_VFS_LOOKUP | 
|---|
| [433] | 2220 | uint32_t cycle = (uint32_t)hal_get_cycles(); | 
|---|
| [610] | 2221 | char     root_name[CONFIG_VFS_MAX_NAME_LENGTH]; | 
|---|
 | 2222 | vfs_inode_get_name( root_xp , root_name ); | 
|---|
| [438] | 2223 | if( DEBUG_VFS_LOOKUP < cycle ) | 
|---|
| [610] | 2224 | printk("\n[%s] thread[%x,%x] enter / root <%s> / path <%s> / mode %x / cycle %d\n", | 
|---|
 | 2225 | __FUNCTION__, process->pid, this->trdid, root_name, pathname, lookup_mode, cycle ); | 
|---|
| [433] | 2226 | #endif | 
|---|
| [380] | 2227 |  | 
|---|
| [459] | 2228 |     // compute lookup flags | 
|---|
| [610] | 2229 |     dir    = (lookup_mode & VFS_LOOKUP_DIR)    == VFS_LOOKUP_DIR; | 
|---|
 | 2230 |     create = (lookup_mode & VFS_LOOKUP_CREATE) == VFS_LOOKUP_CREATE; | 
|---|
 | 2231 |     excl   = (lookup_mode & VFS_LOOKUP_EXCL)   == VFS_LOOKUP_EXCL; | 
|---|
 | 2232 |     par    = (lookup_mode & VFS_LOOKUP_PARENT) == VFS_LOOKUP_PARENT; | 
|---|
| [1] | 2233 |  | 
|---|
| [610] | 2234 |     // initialise loop variables | 
|---|
 | 2235 |     parent_xp = root_xp; | 
|---|
 | 2236 |     current   = pathname; | 
|---|
 | 2237 |     next      = NULL; | 
|---|
 | 2238 |     last      = false; | 
|---|
 | 2239 |     child_xp  = XPTR_NULL; | 
|---|
| [1] | 2240 |  | 
|---|
| [610] | 2241 |     // loop on nodes in pathname | 
|---|
 | 2242 |     // load from device if one node in path not found in Inode Tree | 
|---|
| [401] | 2243 |     // exit loop when last name found (i.e. last == true) | 
|---|
| [610] | 2244 |     while( 1 ) | 
|---|
| [1] | 2245 |     { | 
|---|
| [610] | 2246 |         // get parent inode cluster and local pointer | 
|---|
 | 2247 |         parent_cxy = GET_CXY( parent_xp ); | 
|---|
 | 2248 |         parent_ptr = GET_PTR( parent_xp ); | 
|---|
| [1] | 2249 |  | 
|---|
| [610] | 2250 |         // get one "name" from path, and "last" flag | 
|---|
 | 2251 |         error = vfs_get_name_from_path( current , name , &next , &last ); | 
|---|
 | 2252 |  | 
|---|
| [611] | 2253 |         // handle VFS root case | 
|---|
| [610] | 2254 |         if ( error ) | 
|---|
 | 2255 |         { | 
|---|
 | 2256 |  | 
|---|
 | 2257 | #if DEBUG_VFS_LOOKUP | 
|---|
 | 2258 | cycle = (uint32_t)hal_get_cycles(); | 
|---|
 | 2259 | if( DEBUG_VFS_LOOKUP < cycle ) | 
|---|
 | 2260 | printk("\n[%s] thread[%x,%x] exit / parent inode(%x,%x) / <%s> / cycle %d\n", | 
|---|
 | 2261 | __FUNCTION__ , process->pid, this->trdid, parent_cxy, parent_ptr, pathname, cycle ); | 
|---|
 | 2262 | #endif | 
|---|
 | 2263 |             *inode_xp = process->vfs_root_xp; | 
|---|
 | 2264 |             break; | 
|---|
 | 2265 |         } | 
|---|
 | 2266 |  | 
|---|
| [438] | 2267 | #if (DEBUG_VFS_LOOKUP & 1) | 
|---|
 | 2268 | if( DEBUG_VFS_LOOKUP < cycle ) | 
|---|
| [602] | 2269 | printk("\n[%s] thread[%x,%x] look for <%s> in <%s> / last = %d\n", | 
|---|
 | 2270 | __FUNCTION__, process->pid, this->trdid, name, pathname, last ); | 
|---|
| [433] | 2271 | #endif | 
|---|
| [101] | 2272 |  | 
|---|
| [610] | 2273 |         // search the child dentry matching name in parent inode | 
|---|
| [1] | 2274 |         found = vfs_get_child( parent_xp, | 
|---|
 | 2275 |                                name, | 
|---|
 | 2276 |                                &child_xp ); | 
|---|
 | 2277 |  | 
|---|
| [611] | 2278 |         // get child inode local pointer and cluster | 
|---|
 | 2279 |         child_ptr  = GET_PTR( child_xp ); | 
|---|
 | 2280 |         child_cxy  = GET_CXY( child_xp ); | 
|---|
 | 2281 |  | 
|---|
| [610] | 2282 |         // analyse found & last, depending on lookup_mode | 
|---|
 | 2283 |         if( found == false )                              // not found in Inode Tree  | 
|---|
| [1] | 2284 |         { | 
|---|
| [610] | 2285 |             // when a inode is not found in the Inode Tree: | 
|---|
 | 2286 |             // - if (last and par) the Inode Tree is not modified | 
|---|
 | 2287 |             // - else we speculatively introduce a new (dentry/inode) in inode tree, | 
|---|
 | 2288 |             //        and scan the parent directory mapper to initialise it. | 
|---|
 | 2289 |             //     . if it is not found in the parent mapper: | 
|---|
 | 2290 |             //         - if(last and create), a brand new file or directory is created | 
|---|
 | 2291 |             //         - else, an error is reported | 
|---|
 | 2292 |             //     . if it is found in parent mapper: | 
|---|
 | 2293 |             //         - if( last and excl ), an error is reported | 
|---|
 | 2294 |             //         - else the new child (inode & dentry) is initialised in Inode Tree | 
|---|
 | 2295 |             //         - if the child is a directory, the child mapper is loaded from device | 
|---|
| [101] | 2296 |  | 
|---|
| [610] | 2297 |             if( last && par )   //  does nothing | 
|---|
 | 2298 |             { | 
|---|
 | 2299 |  | 
|---|
| [438] | 2300 | #if (DEBUG_VFS_LOOKUP & 1) | 
|---|
 | 2301 | if( DEBUG_VFS_LOOKUP < cycle ) | 
|---|
| [610] | 2302 | printk("\n[%s] thread[%x,%x] child not found but only parent requested in <%s>\n", | 
|---|
 | 2303 | __FUNCTION__, process->pid, this->trdid, pathname ); | 
|---|
 | 2304 | #endif | 
|---|
 | 2305 |             } | 
|---|
 | 2306 |             else                                    // try to get it from parent mapper | 
|---|
 | 2307 |             { | 
|---|
 | 2308 |  | 
|---|
 | 2309 | #if (DEBUG_VFS_LOOKUP & 1) | 
|---|
 | 2310 | if( DEBUG_VFS_LOOKUP < cycle ) | 
|---|
 | 2311 | printk("\n[%s] thread[%x,%x] miss <%s> inode in Inode Tree => build from parent mapper\n", | 
|---|
| [602] | 2312 | __FUNCTION__, process->pid, this->trdid, name ); | 
|---|
| [433] | 2313 | #endif | 
|---|
| [610] | 2314 |                 // get parent inode FS type | 
|---|
 | 2315 |                 ctx_ptr    = hal_remote_lpt( XPTR( parent_cxy,&parent_ptr->ctx ) ); | 
|---|
 | 2316 |                 fs_type    = hal_remote_l32( XPTR( parent_cxy , &ctx_ptr->type ) ); | 
|---|
| [407] | 2317 |  | 
|---|
| [610] | 2318 |                 // select a cluster for new inode | 
|---|
 | 2319 |                 child_cxy = cluster_random_select(); | 
|---|
| [602] | 2320 |  | 
|---|
| [610] | 2321 |                 // define child inode type | 
|---|
 | 2322 |                 if( dir ) child_type = INODE_TYPE_DIR; | 
|---|
 | 2323 |                 else      child_type = INODE_TYPE_FILE; | 
|---|
| [401] | 2324 |   | 
|---|
| [611] | 2325 |                 // insert a new child dentry/inode couple in inode tree | 
|---|
| [610] | 2326 |                 error = vfs_add_child_in_parent( child_cxy, | 
|---|
 | 2327 |                                                  child_type,  | 
|---|
 | 2328 |                                                  fs_type,  | 
|---|
 | 2329 |                                                  parent_xp,  | 
|---|
 | 2330 |                                                  name,  | 
|---|
 | 2331 |                                                  &dentry_xp, | 
|---|
 | 2332 |                                                  &child_xp ); | 
|---|
 | 2333 |                 if( error ) | 
|---|
 | 2334 |                 { | 
|---|
 | 2335 |                     printk("\n[ERROR] in %s : cannot create inode <%s> in path <%s>\n", | 
|---|
 | 2336 |                     __FUNCTION__ , name, pathname ); | 
|---|
 | 2337 |                     return -1; | 
|---|
 | 2338 |                 } | 
|---|
| [238] | 2339 |  | 
|---|
| [610] | 2340 |                 // get child inode local pointer | 
|---|
 | 2341 |                 child_ptr = GET_PTR( child_xp ); | 
|---|
| [459] | 2342 |  | 
|---|
 | 2343 | #if (DEBUG_VFS_LOOKUP & 1) | 
|---|
 | 2344 | if( DEBUG_VFS_LOOKUP < cycle ) | 
|---|
| [602] | 2345 | printk("\n[%s] thread[%x,%x] created missing inode <%s> in cluster %x\n", | 
|---|
 | 2346 | __FUNCTION__, process->pid, this->trdid, name, child_cxy ); | 
|---|
| [459] | 2347 | #endif | 
|---|
| [610] | 2348 |                 // scan parent mapper to find the missing dentry, and complete  | 
|---|
| [611] | 2349 |                 // the initialisation of dentry and child inode descriptors | 
|---|
| [610] | 2350 |                 if( parent_cxy == local_cxy ) | 
|---|
 | 2351 |                 { | 
|---|
| [612] | 2352 |                     error = vfs_fs_get_dentry( parent_ptr, | 
|---|
| [610] | 2353 |                                                name, | 
|---|
 | 2354 |                                                child_xp ); | 
|---|
 | 2355 |                 } | 
|---|
 | 2356 |                 else | 
|---|
 | 2357 |                 { | 
|---|
| [612] | 2358 |                     rpc_vfs_fs_get_dentry_client( parent_cxy, | 
|---|
| [610] | 2359 |                                                   parent_ptr, | 
|---|
 | 2360 |                                                   name, | 
|---|
 | 2361 |                                                   child_xp, | 
|---|
 | 2362 |                                                   &error ); | 
|---|
 | 2363 |                 } | 
|---|
| [238] | 2364 |  | 
|---|
| [610] | 2365 |                 if ( error )   // child not found in parent mapper | 
|---|
| [459] | 2366 |                 { | 
|---|
| [610] | 2367 |                     if ( last && create )  // add a brand new dentry in parent | 
|---|
| [602] | 2368 |                     { | 
|---|
| [612] | 2369 |                         error = vfs_new_dentry_init( parent_xp,                 | 
|---|
 | 2370 |                                                      dentry_xp, | 
|---|
 | 2371 |                                                      child_xp ); | 
|---|
| [610] | 2372 |                         if ( error ) | 
|---|
 | 2373 |                         { | 
|---|
 | 2374 |                             printk("\n[ERROR] in %s : cannot init inode <%s> in path <%s>\n", | 
|---|
 | 2375 |                             __FUNCTION__, name, pathname ); | 
|---|
 | 2376 |                             vfs_remove_child_from_parent( dentry_xp ); | 
|---|
 | 2377 |                             return -1; | 
|---|
 | 2378 |                         } | 
|---|
| [1] | 2379 |  | 
|---|
| [459] | 2380 | #if (DEBUG_VFS_LOOKUP & 1) | 
|---|
 | 2381 | if( DEBUG_VFS_LOOKUP < cycle ) | 
|---|
| [610] | 2382 | printk("\n[%s] thread[%x,%x] child <%s> not found in parent mapper => create it\n", | 
|---|
| [602] | 2383 | __FUNCTION__, process->pid, this->trdid, name ); | 
|---|
| [459] | 2384 | #endif | 
|---|
| [610] | 2385 |                     } | 
|---|
 | 2386 |                     else                   // not last or not create => error | 
|---|
 | 2387 |                     {                        | 
|---|
 | 2388 |                         printk("\n[ERROR] in %s : <%s> node not found in parent for <%s>\n", | 
|---|
 | 2389 |                         __FUNCTION__ , name , pathname ); | 
|---|
 | 2390 |                         vfs_remove_child_from_parent( dentry_xp ); | 
|---|
 | 2391 |                         return -1; | 
|---|
 | 2392 |                     } | 
|---|
| [238] | 2393 |                 } | 
|---|
| [610] | 2394 |                 else          // child has been found in parent mapper | 
|---|
| [459] | 2395 |                 { | 
|---|
| [610] | 2396 |                     // check the excl | 
|---|
 | 2397 |                     if( last && create && excl ) | 
|---|
| [459] | 2398 |                     { | 
|---|
| [610] | 2399 |                         printk("\n[ERROR] in %s : node already exist <%s>\n", | 
|---|
 | 2400 |                         __FUNCTION__, name ); | 
|---|
 | 2401 |                        return -1; | 
|---|
| [459] | 2402 |                     } | 
|---|
| [610] | 2403 |  | 
|---|
 | 2404 | #if (DEBUG_VFS_LOOKUP & 1) | 
|---|
 | 2405 | if( DEBUG_VFS_LOOKUP < cycle ) | 
|---|
 | 2406 | printk("\n[%s] thread[%x,%x] initialised inode <%s> from parent mapper\n", | 
|---|
 | 2407 | __FUNCTION__, process->pid, this->trdid, name ); | 
|---|
 | 2408 | #endif | 
|---|
 | 2409 |                     // load child mapper from device if child is a directory (prefetch) | 
|---|
 | 2410 |                     uint32_t type = hal_remote_l32( XPTR( child_cxy , &child_ptr->type ) ); | 
|---|
 | 2411 |                     if( type == INODE_TYPE_DIR )  | 
|---|
| [459] | 2412 |                     { | 
|---|
| [610] | 2413 |                         if( child_cxy == local_cxy ) | 
|---|
 | 2414 |                         { | 
|---|
 | 2415 |                             error = vfs_inode_load_all_pages( child_ptr ); | 
|---|
 | 2416 |                         } | 
|---|
 | 2417 |                         else | 
|---|
 | 2418 |                         { | 
|---|
 | 2419 |                             rpc_vfs_inode_load_all_pages_client( child_cxy, | 
|---|
 | 2420 |                                                                  child_ptr, | 
|---|
 | 2421 |                                                                  &error ); | 
|---|
 | 2422 |                         } | 
|---|
 | 2423 |                         if ( error ) | 
|---|
 | 2424 |                         { | 
|---|
 | 2425 |                             printk("\n[ERROR] in %s : cannot load <%s> from device\n", | 
|---|
 | 2426 |                             __FUNCTION__ , name ); | 
|---|
 | 2427 |                             vfs_remove_child_from_parent( dentry_xp ); | 
|---|
 | 2428 |                             return -1; | 
|---|
 | 2429 |                         } | 
|---|
| [238] | 2430 |  | 
|---|
| [438] | 2431 | #if (DEBUG_VFS_LOOKUP & 1) | 
|---|
 | 2432 | if( DEBUG_VFS_LOOKUP < cycle ) | 
|---|
| [610] | 2433 | printk("\n[%s] thread[%x,%x] loaded directory mapper for <%s> from IOC\n", | 
|---|
 | 2434 | __FUNCTION__ , process->pid, this->trdid, name ); | 
|---|
| [433] | 2435 | #endif | 
|---|
| [610] | 2436 |                     } | 
|---|
| [459] | 2437 |                 } | 
|---|
 | 2438 |             } | 
|---|
| [1] | 2439 |         } | 
|---|
| [610] | 2440 |         else                                    // child directly found in inode tree | 
|---|
| [459] | 2441 |         { | 
|---|
 | 2442 |          | 
|---|
| [438] | 2443 | #if (DEBUG_VFS_LOOKUP & 1) | 
|---|
 | 2444 | if( DEBUG_VFS_LOOKUP < cycle ) | 
|---|
| [610] | 2445 | printk("\n[%s] thread[%x,%x] found <%s> in Inode Tree / inode (%x,%x)\n", | 
|---|
| [611] | 2446 | __FUNCTION__, process->pid, this->trdid, name, child_cxy, child_ptr ); | 
|---|
| [433] | 2447 | #endif | 
|---|
| [610] | 2448 |             // check the excl flag | 
|---|
 | 2449 |             if( last && create && excl ) | 
|---|
| [459] | 2450 |             { | 
|---|
| [610] | 2451 |                 printk("\n[ERROR] in %s : node <%s> already exist\n", | 
|---|
 | 2452 |                 __FUNCTION__, name ); | 
|---|
 | 2453 |                 return -1; | 
|---|
| [459] | 2454 |             } | 
|---|
 | 2455 |         } | 
|---|
 | 2456 |  | 
|---|
| [380] | 2457 |         // TODO check access rights here [AG] | 
|---|
| [23] | 2458 |         // error = vfs_access_denied( child_xp, | 
|---|
 | 2459 |         //                            client_uid, | 
|---|
 | 2460 |         //                            client_gid ); | 
|---|
 | 2461 |         // if( error )  | 
|---|
 | 2462 |         // { | 
|---|
| [441] | 2463 |         //     printk("\n[ERROR] in %s : thread %x / permission denied for %s\n", | 
|---|
 | 2464 |         //     __FUNCTION__ , this , name ); | 
|---|
| [23] | 2465 |         //     return EACCES; | 
|---|
 | 2466 |         // } | 
|---|
| [1] | 2467 |  | 
|---|
| [238] | 2468 |         // take lock on child inode and release lock on parent | 
|---|
| [610] | 2469 |         // vfs_inode_lock( child_xp ); | 
|---|
 | 2470 |         // vfs_inode_unlock( parent_xp ); | 
|---|
| [1] | 2471 |  | 
|---|
| [610] | 2472 |         // exit when last | 
|---|
 | 2473 |         if ( last )           // last inode in path  => return relevant info | 
|---|
 | 2474 |         { | 
|---|
 | 2475 |             if ( par )  // return parent inode and child name | 
|---|
 | 2476 |             { | 
|---|
| [1] | 2477 |  | 
|---|
| [610] | 2478 | #if DEBUG_VFS_LOOKUP | 
|---|
 | 2479 | cycle = (uint32_t)hal_get_cycles(); | 
|---|
 | 2480 | if( DEBUG_VFS_LOOKUP < cycle ) | 
|---|
 | 2481 | printk("\n[%s] thread[%x,%x] exit / parent inode(%x,%x) / <%s> / cycle %d\n", | 
|---|
 | 2482 | __FUNCTION__ , process->pid, this->trdid, parent_cxy, parent_ptr, pathname, cycle ); | 
|---|
 | 2483 | #endif | 
|---|
 | 2484 |                 *inode_xp = parent_xp; | 
|---|
 | 2485 |                 strcpy( last_name , name ); | 
|---|
 | 2486 |                 break;  | 
|---|
 | 2487 |             } | 
|---|
 | 2488 |             else        // return child inode name      | 
|---|
 | 2489 |             { | 
|---|
| [1] | 2490 |  | 
|---|
| [438] | 2491 | #if DEBUG_VFS_LOOKUP | 
|---|
| [433] | 2492 | cycle = (uint32_t)hal_get_cycles(); | 
|---|
| [438] | 2493 | if( DEBUG_VFS_LOOKUP < cycle ) | 
|---|
| [610] | 2494 | printk("\n[%s] thread[%x,%x] exit / child inode (%x,%x) / <%s> / cycle %d\n", | 
|---|
 | 2495 | __FUNCTION__ , process->pid, this->trdid, child_cxy, child_ptr, pathname, cycle ); | 
|---|
| [433] | 2496 | #endif | 
|---|
| [610] | 2497 |                 *inode_xp = child_xp; | 
|---|
 | 2498 |                 break; | 
|---|
 | 2499 |             } | 
|---|
 | 2500 |         } | 
|---|
 | 2501 |         else                     // not the last inode in path => update loop variables | 
|---|
 | 2502 |         { | 
|---|
 | 2503 |             parent_xp = child_xp; | 
|---|
 | 2504 |             current   = next; | 
|---|
 | 2505 |         } | 
|---|
 | 2506 |     } | 
|---|
| [1] | 2507 |  | 
|---|
 | 2508 |     return 0; | 
|---|
 | 2509 |  | 
|---|
 | 2510 | }  // end vfs_lookup() | 
|---|
 | 2511 |  | 
|---|
| [612] | 2512 | //////////////////////////////////////////////// | 
|---|
 | 2513 | error_t vfs_new_dentry_init( xptr_t   parent_xp, | 
|---|
 | 2514 |                              xptr_t   dentry_xp, | 
|---|
 | 2515 |                              xptr_t   child_xp ) | 
|---|
| [602] | 2516 | { | 
|---|
 | 2517 |     error_t     error; | 
|---|
 | 2518 |     uint32_t    cluster; | 
|---|
 | 2519 |     uint32_t    child_type; | 
|---|
 | 2520 |     uint32_t    child_size; | 
|---|
 | 2521 |  | 
|---|
 | 2522 | #if DEBUG_VFS_NEW_CHILD_INIT | 
|---|
 | 2523 | char parent_name[CONFIG_VFS_MAX_NAME_LENGTH]; | 
|---|
 | 2524 | char child_name[CONFIG_VFS_MAX_NAME_LENGTH]; | 
|---|
 | 2525 | vfs_inode_get_name( parent_xp , parent_name ); | 
|---|
 | 2526 | vfs_inode_get_name( child_xp  , child_name ); | 
|---|
 | 2527 | uint32_t   cycle = (uint32_t)hal_get_cycles(); | 
|---|
 | 2528 | thread_t * this  = CURRENT_THREAD; | 
|---|
 | 2529 | if( DEBUG_VFS_NEW_CHILD_INIT < cycle ) | 
|---|
 | 2530 | printk("\n[%s] thread[%x,%x] enter / parent <%s> / child <%s> / cycle %d\n", | 
|---|
 | 2531 | __FUNCTION__ , this->process->pid, this->trdid, parent_name, child_name, cycle ); | 
|---|
 | 2532 | #endif | 
|---|
 | 2533 |  | 
|---|
 | 2534 |     // get parent inode cluster and local pointer | 
|---|
 | 2535 |     cxy_t          parent_cxy = GET_CXY( parent_xp ); | 
|---|
 | 2536 |     vfs_inode_t  * parent_ptr = GET_PTR( parent_xp ); | 
|---|
 | 2537 |  | 
|---|
 | 2538 |     // get dentry local pointer | 
|---|
 | 2539 |     vfs_dentry_t * dentry_ptr = GET_PTR( dentry_xp ); | 
|---|
 | 2540 |  | 
|---|
 | 2541 |     // get child inode cluster and local pointer | 
|---|
 | 2542 |     cxy_t          child_cxy  = GET_CXY( child_xp ); | 
|---|
 | 2543 |     vfs_inode_t  * child_ptr  = GET_PTR( child_xp ); | 
|---|
 | 2544 |  | 
|---|
 | 2545 |     // 1. allocate one free cluster to child inode | 
|---|
 | 2546 |     // depending on the child inode FS type | 
|---|
 | 2547 |     vfs_ctx_t * ctx = hal_remote_lpt( XPTR( child_cxy , &child_ptr->ctx ) ); | 
|---|
 | 2548 |  | 
|---|
 | 2549 |     error = vfs_fs_cluster_alloc( ctx->type, | 
|---|
 | 2550 |                                   &cluster ); | 
|---|
 | 2551 |     if ( error ) | 
|---|
 | 2552 |     { | 
|---|
 | 2553 |         printk("\n[ERROR] in %s : cannot find a free VFS cluster\n", | 
|---|
 | 2554 |         __FUNCTION__ ); | 
|---|
 | 2555 |         return -1; | 
|---|
 | 2556 |     } | 
|---|
 | 2557 |  | 
|---|
 | 2558 | #if( DEBUG_VFS_NEW_CHILD_INIT & 1) | 
|---|
 | 2559 | if( DEBUG_VFS_NEW_CHILD_INIT < cycle ) | 
|---|
 | 2560 | printk("\n[%s] thread[%x,%x] allocated one FAT cluster to <%s>\n", | 
|---|
 | 2561 | __FUNCTION__ , this->process->pid, this->trdid, child_name ); | 
|---|
 | 2562 | #endif | 
|---|
 | 2563 |  | 
|---|
 | 2564 |     // 2. update the child inode descriptor | 
|---|
 | 2565 |     child_type = hal_remote_l32( XPTR( child_cxy , &child_ptr->type ) ); | 
|---|
 | 2566 |     child_size = (child_type == INODE_TYPE_DIR) ? 4096 : 0; | 
|---|
 | 2567 |      | 
|---|
 | 2568 |     hal_remote_s32( XPTR( child_cxy , &child_ptr->size )   , child_size ); | 
|---|
 | 2569 |     hal_remote_spt( XPTR( child_cxy , &child_ptr->extend ) , (void*)(intptr_t)cluster ); | 
|---|
 | 2570 |  | 
|---|
 | 2571 |     // 3. update the parent inode mapper, and  | 
|---|
 | 2572 |     // update the dentry extension if required | 
|---|
 | 2573 |     if( local_cxy == parent_cxy ) | 
|---|
 | 2574 |     { | 
|---|
 | 2575 |         error = vfs_fs_add_dentry( parent_ptr, | 
|---|
 | 2576 |                                    dentry_ptr ); | 
|---|
 | 2577 |     } | 
|---|
 | 2578 |     else | 
|---|
 | 2579 |     { | 
|---|
 | 2580 |         rpc_vfs_fs_add_dentry_client( parent_cxy, | 
|---|
 | 2581 |                                       parent_ptr, | 
|---|
 | 2582 |                                       dentry_ptr, | 
|---|
 | 2583 |                                       &error ); | 
|---|
 | 2584 |     } | 
|---|
 | 2585 |     if ( error ) | 
|---|
 | 2586 |     { | 
|---|
 | 2587 |         printk("\n[ERROR] in %s : cannot register child in parent directory\n", | 
|---|
 | 2588 |         __FUNCTION__ ); | 
|---|
 | 2589 |         return -1; | 
|---|
 | 2590 |     } | 
|---|
 | 2591 |  | 
|---|
 | 2592 | #if DEBUG_VFS_NEW_CHILD_INIT | 
|---|
 | 2593 | cycle = (uint32_t)hal_get_cycles(); | 
|---|
 | 2594 | if( DEBUG_VFS_NEW_CHILD_INIT < cycle ) | 
|---|
| [610] | 2595 | printk("\n[%s] thread[%x,%x] exit / parent <%s> / child <%s> / cycle %d\n", | 
|---|
| [602] | 2596 | __FUNCTION__ , this->process->pid, this->trdid, parent_name, child_name, cycle ); | 
|---|
 | 2597 | #endif | 
|---|
 | 2598 |  | 
|---|
 | 2599 |     return 0; | 
|---|
 | 2600 |  | 
|---|
| [612] | 2601 | }  // end vfs_new_dentry_init() | 
|---|
| [602] | 2602 |  | 
|---|
| [611] | 2603 | /////////////////////////////////////////////////// | 
|---|
 | 2604 | error_t vfs_add_special_dentries( xptr_t  child_xp, | 
|---|
 | 2605 |                                   xptr_t  parent_xp ) | 
|---|
 | 2606 | { | 
|---|
 | 2607 |     error_t         error; | 
|---|
 | 2608 |     vfs_inode_t   * child_ptr;         // local pointer on child inode directory | 
|---|
 | 2609 |     cxy_t           child_cxy;         // child inode directory cluster identifier | 
|---|
 | 2610 |     vfs_inode_t   * parent_ptr;        // local pointer on parent inode directory | 
|---|
 | 2611 |     cxy_t           parent_cxy;        // parent inode directory cluster identifier | 
|---|
 | 2612 |     vfs_ctx_t     * ctx_ptr;           // local pointer on child inode FS context | 
|---|
 | 2613 |     vfs_fs_type_t   fs_type;           // FS type of child inode | 
|---|
 | 2614 |     xptr_t          dentry_xp;         // extended pointer on dentry (used for . and ..) | 
|---|
 | 2615 |     vfs_dentry_t  * dentry_ptr;        // local pointer on dentry (used for . and ..)  | 
|---|
 | 2616 |  | 
|---|
| [612] | 2617 |     // xptr_t          parents_root_xp;   // extended pointer on inode "parents" field | 
|---|
 | 2618 |     // xptr_t          parents_entry_xp;  // extended pointer on dentry "parents" field | 
|---|
| [611] | 2619 |     xptr_t          children_xhtab_xp; // extended pointer on inode "children" field | 
|---|
 | 2620 |     xptr_t          children_entry_xp; // extended pointer on dentry "children" field | 
|---|
 | 2621 |  | 
|---|
 | 2622 | #if DEBUG_VFS_ADD_SPECIAL | 
|---|
 | 2623 | uint32_t   cycle = (uint32_t)hal_get_cycles(); | 
|---|
 | 2624 | thread_t * this  = CURRENT_THREAD; | 
|---|
 | 2625 | char child_name[CONFIG_VFS_MAX_NAME_LENGTH]; | 
|---|
 | 2626 | char parent_name[CONFIG_VFS_MAX_NAME_LENGTH]; | 
|---|
 | 2627 | vfs_inode_get_name( child_xp  , child_name ); | 
|---|
 | 2628 | vfs_inode_get_name( parent_xp , parent_name ); | 
|---|
 | 2629 | if( DEBUG_VFS_ADD_SPECIAL < cycle ) | 
|---|
| [612] | 2630 | printk("\n[%s] thread[%x,%x] enter for child <%s> in parent <%s> / cycle %d\n", | 
|---|
| [611] | 2631 | __FUNCTION__, this->process->pid, this->trdid, child_name, parent_name, cycle ); | 
|---|
 | 2632 | #endif | 
|---|
 | 2633 |  | 
|---|
 | 2634 |     // get new directory cluster and local pointer | 
|---|
 | 2635 |     child_cxy  = GET_CXY( child_xp ); | 
|---|
 | 2636 |     child_ptr  = GET_PTR( child_xp ); | 
|---|
 | 2637 |  | 
|---|
 | 2638 |     // get parent directory cluster and local pointer | 
|---|
 | 2639 |     parent_cxy = GET_CXY( parent_xp ); | 
|---|
 | 2640 |     parent_ptr = GET_PTR( parent_xp ); | 
|---|
 | 2641 |  | 
|---|
 | 2642 |     // get child inode FS type | 
|---|
 | 2643 |     ctx_ptr    = hal_remote_lpt( XPTR( child_cxy , &child_ptr->ctx ) ); | 
|---|
 | 2644 |     fs_type    = hal_remote_l32( XPTR( child_cxy , &ctx_ptr->type ) ); | 
|---|
 | 2645 |  | 
|---|
 | 2646 |     //////////////////////////// create <.>  | 
|---|
 | 2647 |     if( child_cxy == local_cxy )      | 
|---|
 | 2648 |     { | 
|---|
 | 2649 |         error = vfs_dentry_create( fs_type, | 
|---|
 | 2650 |                                    ".", | 
|---|
 | 2651 |                                    &dentry_xp ); | 
|---|
 | 2652 |     } | 
|---|
 | 2653 |     else | 
|---|
 | 2654 |     { | 
|---|
 | 2655 |         rpc_vfs_dentry_create_client( child_cxy, | 
|---|
 | 2656 |                                       fs_type, | 
|---|
 | 2657 |                                       ".", | 
|---|
 | 2658 |                                       &dentry_xp, | 
|---|
 | 2659 |                                       &error ); | 
|---|
 | 2660 |     } | 
|---|
 | 2661 |     if( error ) | 
|---|
 | 2662 |     { | 
|---|
 | 2663 |         printk("\n[ERROR] in %s : cannot create dentry <.> in cluster %x\n", | 
|---|
 | 2664 |         __FUNCTION__ , child_cxy ); | 
|---|
 | 2665 |         return -1; | 
|---|
 | 2666 |     } | 
|---|
 | 2667 |  | 
|---|
 | 2668 |     // get <.> dentry local pointer | 
|---|
 | 2669 |     dentry_ptr = GET_PTR( dentry_xp ); | 
|---|
 | 2670 |  | 
|---|
 | 2671 | #if(DEBUG_VFS_ADD_SPECIAL & 1) | 
|---|
 | 2672 | if( DEBUG_VFS_ADD_SPECIAL < cycle ) | 
|---|
 | 2673 | printk("\n[%s] thread[%x,%x] created dentry <.> (%x,%x)\n", | 
|---|
 | 2674 | __FUNCTION__, this->process->pid, this->trdid, child_cxy, dentry_ptr ); | 
|---|
 | 2675 | #endif | 
|---|
 | 2676 |  | 
|---|
 | 2677 |     // register <.> dentry in child inode xhtab of children | 
|---|
 | 2678 |     children_xhtab_xp = XPTR( child_cxy , &child_ptr->children ); | 
|---|
 | 2679 |     children_entry_xp = XPTR( child_cxy , &dentry_ptr->children ); | 
|---|
 | 2680 |     error = xhtab_insert( children_xhtab_xp , "." , children_entry_xp ); | 
|---|
 | 2681 |     if( error ) | 
|---|
 | 2682 |     { | 
|---|
 | 2683 |         printk("\n[ERROR] in %s : cannot register dentry <.> in xhtab\n", | 
|---|
 | 2684 |         __FUNCTION__ ); | 
|---|
 | 2685 |         return -1; | 
|---|
 | 2686 |     } | 
|---|
 | 2687 |  | 
|---|
| [612] | 2688 |      | 
|---|
 | 2689 |     // don't register <.> dentry in child_inode xlist of parents  | 
|---|
 | 2690 |     // parents_root_xp  = XPTR( child_cxy , &child_ptr->parents ); | 
|---|
 | 2691 |     // parents_entry_xp = XPTR( child_cxy , &dentry_ptr->parents ); | 
|---|
 | 2692 |     // xlist_add_first( parents_root_xp , parents_entry_xp ); | 
|---|
 | 2693 |     // hal_remote_atomic_add( XPTR( child_cxy , &child_ptr->links ) , 1 ); | 
|---|
| [611] | 2694 |  | 
|---|
 | 2695 |     // update "parent" and "child_xp" fields in <.> dentry | 
|---|
 | 2696 |     hal_remote_s64( XPTR( child_cxy , &dentry_ptr->child_xp ) , child_xp ); | 
|---|
 | 2697 |     hal_remote_spt( XPTR( child_cxy , &dentry_ptr->parent ) , child_ptr ); | 
|---|
 | 2698 |  | 
|---|
 | 2699 | #if(DEBUG_VFS_ADD_SPECIAL & 1) | 
|---|
 | 2700 | if( DEBUG_VFS_ADD_SPECIAL < cycle ) | 
|---|
 | 2701 | printk("\n[%s] thread[%x,%x] linked dentry <.> to parent and child inodes\n",  | 
|---|
 | 2702 | __FUNCTION__, this->process->pid, this->trdid );  | 
|---|
 | 2703 | #endif | 
|---|
 | 2704 |  | 
|---|
 | 2705 |     // introduce <.> dentry into child directory mapper | 
|---|
 | 2706 |     if( child_cxy == local_cxy ) | 
|---|
 | 2707 |     {  | 
|---|
 | 2708 |         error = vfs_fs_add_dentry( child_ptr, | 
|---|
 | 2709 |                                    dentry_ptr ); | 
|---|
 | 2710 |     } | 
|---|
 | 2711 |     else | 
|---|
 | 2712 |     { | 
|---|
 | 2713 |         rpc_vfs_fs_add_dentry_client( child_cxy, | 
|---|
 | 2714 |                                       child_ptr, | 
|---|
 | 2715 |                                       dentry_ptr, | 
|---|
 | 2716 |                                       &error ); | 
|---|
 | 2717 |     } | 
|---|
 | 2718 |     if( error ) | 
|---|
 | 2719 |     { | 
|---|
 | 2720 |         printk("\n[ERROR] in %s : cannot introduce dentry <..> in mapper %x\n", | 
|---|
 | 2721 |         __FUNCTION__ ); | 
|---|
 | 2722 |         return -1; | 
|---|
 | 2723 |     } | 
|---|
 | 2724 |  | 
|---|
 | 2725 | #if(DEBUG_VFS_ADD_SPECIAL & 1) | 
|---|
 | 2726 | if( DEBUG_VFS_ADD_SPECIAL < cycle ) | 
|---|
 | 2727 | printk("\n[%s] thread[%x,%x] registered dentry <.> in child mapper\n",  | 
|---|
 | 2728 | __FUNCTION__, this->process->pid, this->trdid );  | 
|---|
 | 2729 | #endif | 
|---|
 | 2730 |  | 
|---|
 | 2731 |     ///////////////////////////// create <..> dentry  | 
|---|
 | 2732 |     if( child_cxy == local_cxy )      | 
|---|
 | 2733 |     { | 
|---|
 | 2734 |         error = vfs_dentry_create( fs_type, | 
|---|
 | 2735 |                                    "..", | 
|---|
 | 2736 |                                    &dentry_xp ); | 
|---|
 | 2737 |     } | 
|---|
 | 2738 |     else | 
|---|
 | 2739 |     { | 
|---|
 | 2740 |         rpc_vfs_dentry_create_client( child_cxy, | 
|---|
 | 2741 |                                       fs_type, | 
|---|
 | 2742 |                                       "..", | 
|---|
 | 2743 |                                       &dentry_xp, | 
|---|
 | 2744 |                                       &error ); | 
|---|
 | 2745 |     } | 
|---|
 | 2746 |     if( error ) | 
|---|
 | 2747 |     { | 
|---|
 | 2748 |         printk("\n[ERROR] in %s : cannot create dentry <..> in cluster %x\n", | 
|---|
 | 2749 |         __FUNCTION__ , child_cxy ); | 
|---|
 | 2750 |         return -1; | 
|---|
 | 2751 |     } | 
|---|
 | 2752 |  | 
|---|
 | 2753 |     // get <..> dentry local pointer | 
|---|
 | 2754 |     dentry_ptr = GET_PTR( dentry_xp ); | 
|---|
 | 2755 |  | 
|---|
 | 2756 | #if(DEBUG_VFS_ADD_SPECIAL & 1) | 
|---|
 | 2757 | if( DEBUG_VFS_ADD_SPECIAL < cycle ) | 
|---|
 | 2758 | printk("\n[%s] thread[%x,%x] created dentry <..> (%x,%x)\n", | 
|---|
 | 2759 | __FUNCTION__, this->process->pid, this->trdid, child_cxy, dentry_ptr ); | 
|---|
 | 2760 | #endif | 
|---|
 | 2761 |  | 
|---|
 | 2762 |     // register <..> dentry in child_inode xhtab of children | 
|---|
 | 2763 |     children_xhtab_xp = XPTR( child_cxy , &child_ptr->children ); | 
|---|
 | 2764 |     children_entry_xp = XPTR( child_cxy , &dentry_ptr->children ); | 
|---|
 | 2765 |     error = xhtab_insert( children_xhtab_xp , ".." , children_entry_xp ); | 
|---|
 | 2766 |     if( error ) | 
|---|
 | 2767 |     { | 
|---|
 | 2768 |         printk("\n[ERROR] in %s : cannot register dentry <..> in xhtab\n", | 
|---|
 | 2769 |         __FUNCTION__ ); | 
|---|
 | 2770 |         return -1; | 
|---|
 | 2771 |     } | 
|---|
 | 2772 |  | 
|---|
| [612] | 2773 |     // don't register <..> dentry in parent_inode xlist of parents  | 
|---|
 | 2774 |     // parents_root_xp  = XPTR( parent_cxy , &parent_ptr->parents ); | 
|---|
 | 2775 |     // parents_entry_xp = XPTR( child_cxy  , &dentry_ptr->parents ); | 
|---|
 | 2776 |     // xlist_add_first( parents_root_xp , parents_entry_xp ); | 
|---|
 | 2777 |     // hal_remote_atomic_add( XPTR( parent_cxy , &parent_ptr->links ) , 1 ); | 
|---|
| [611] | 2778 |  | 
|---|
 | 2779 |     // update "parent" and "child_xp" fields in <..> dentry | 
|---|
 | 2780 |     hal_remote_s64( XPTR( child_cxy , &dentry_ptr->child_xp ) , parent_xp ); | 
|---|
 | 2781 |     hal_remote_spt( XPTR( child_cxy , &dentry_ptr->parent ) , child_ptr ); | 
|---|
 | 2782 |  | 
|---|
 | 2783 | #if(DEBUG_VFS_ADD_SPECIAL & 1) | 
|---|
 | 2784 | if( DEBUG_VFS_ADD_SPECIAL < cycle ) | 
|---|
 | 2785 | printk("\n[%s] thread[%x,%x] linked dentry <..> to parent and child inodes\n",  | 
|---|
 | 2786 | __FUNCTION__, this->process->pid, this->trdid );  | 
|---|
 | 2787 | #endif | 
|---|
 | 2788 |  | 
|---|
 | 2789 |     // introduce <..> dentry into child directory mapper | 
|---|
 | 2790 |     if( child_cxy == local_cxy ) | 
|---|
 | 2791 |     {  | 
|---|
 | 2792 |         error = vfs_fs_add_dentry( child_ptr, | 
|---|
 | 2793 |                                    dentry_ptr ); | 
|---|
 | 2794 |     } | 
|---|
 | 2795 |     else | 
|---|
 | 2796 |     { | 
|---|
 | 2797 |         rpc_vfs_fs_add_dentry_client( child_cxy, | 
|---|
 | 2798 |                                       child_ptr, | 
|---|
 | 2799 |                                       dentry_ptr, | 
|---|
 | 2800 |                                       &error ); | 
|---|
 | 2801 |     } | 
|---|
 | 2802 |     if( error ) | 
|---|
 | 2803 |     { | 
|---|
 | 2804 |         printk("\n[ERROR] in %s : cannot introduce dentry <..> in mapper %x\n", | 
|---|
 | 2805 |         __FUNCTION__ ); | 
|---|
 | 2806 |         return -1; | 
|---|
 | 2807 |     } | 
|---|
 | 2808 |  | 
|---|
 | 2809 | #if(DEBUG_VFS_ADD_SPECIAL & 1) | 
|---|
 | 2810 | if( DEBUG_VFS_ADD_SPECIAL < cycle ) | 
|---|
 | 2811 | printk("\n[%s] thread[%x,%x] registered dentry <..> in child mapper\n",  | 
|---|
 | 2812 | __FUNCTION__, this->process->pid, this->trdid );  | 
|---|
 | 2813 | #endif | 
|---|
 | 2814 |  | 
|---|
 | 2815 | #if DEBUG_VFS_ADD_SPECIAL | 
|---|
 | 2816 | cycle = (uint32_t)hal_get_cycles(); | 
|---|
 | 2817 | if( DEBUG_VFS_ADD_SPECIAL < cycle ) | 
|---|
| [612] | 2818 | printk("\n[%s] thread[%x,%x] exit for child <%s> in parent <%s> / cycle %d\n", | 
|---|
 | 2819 | __FUNCTION__, this->process->pid, this->trdid, child_name, parent_name, cycle ); | 
|---|
| [611] | 2820 | #endif | 
|---|
 | 2821 |  | 
|---|
 | 2822 |     return 0; | 
|---|
 | 2823 |  | 
|---|
 | 2824 | }  // end vfs_add_special_dentries() | 
|---|
 | 2825 |  | 
|---|
| [610] | 2826 | ////////////////////////////////////////// | 
|---|
 | 2827 | error_t vfs_get_path( xptr_t     inode_xp, | 
|---|
 | 2828 |                       char     * buffer, | 
|---|
 | 2829 |                       char    ** first, | 
|---|
 | 2830 |                       uint32_t   max_size ) | 
|---|
| [1] | 2831 | { | 
|---|
| [610] | 2832 |         xptr_t         dentry_xp;        // extended pointer on current dentry | 
|---|
 | 2833 |     vfs_dentry_t * dentry_ptr;       // local pointer on current dentry | 
|---|
 | 2834 |     cxy_t          dentry_cxy;       // current dentry cluster identifier | 
|---|
 | 2835 |     xptr_t         name_xp;          // extended pointer on current dentry name | 
|---|
 | 2836 |         uint32_t       length;           // length of current dentry name | 
|---|
 | 2837 |         int32_t        index;            // slot index in buffer | 
|---|
 | 2838 |     xptr_t         current_xp;       // extended pointer on current inode | 
|---|
 | 2839 |     vfs_inode_t  * current_ptr;      // local pointer on current inode | 
|---|
 | 2840 |     cxy_t          current_cxy;      // current inode cluster identifier | 
|---|
 | 2841 |     xptr_t         vfs_root_xp;      // extended pointer on VFS root inode | 
|---|
 | 2842 |     vfs_inode_t  * vfs_root_ptr;     // local pointer on VFS root inode | 
|---|
 | 2843 |     cxy_t          vfs_root_cxy;     // VFS root inode cluster identifier | 
|---|
 | 2844 |     xptr_t         lock_xp;          // extended pointer on Inode Tree lock  | 
|---|
 | 2845 |     xptr_t         parents_root_xp;  // extended pointer on current inode parents root | 
|---|
 | 2846 |     bool_t         found;            // condition to exit the while loop | 
|---|
| [1] | 2847 |  | 
|---|
| [610] | 2848 |     thread_t  * this    = CURRENT_THREAD; | 
|---|
 | 2849 |     process_t * process = this->process; | 
|---|
| [1] | 2850 |  | 
|---|
| [610] | 2851 | #if DEBUG_VFS_GET_PATH | 
|---|
 | 2852 | uint32_t cycle = (uint32_t)hal_get_cycles(); | 
|---|
 | 2853 | if( DEBUG_VFS_GET_PATH < cycle ) | 
|---|
 | 2854 | printk("\n[%s] thread[%x,%x] enter : inode (%x,%x) / cycle %d\n", | 
|---|
 | 2855 | __FUNCTION__ , process->pid, this->trdid, | 
|---|
 | 2856 | GET_CXY( inode_xp ), GET_PTR( inode_xp ), cycle ); | 
|---|
 | 2857 | #endif | 
|---|
 | 2858 |  | 
|---|
 | 2859 |         // set the NUL character in buffer / initialise buffer index | 
|---|
| [1] | 2860 |         buffer[max_size - 1] = 0; | 
|---|
| [610] | 2861 |     index    = (int32_t)(max_size - 1); | 
|---|
| [1] | 2862 |  | 
|---|
 | 2863 |     // initialize current inode | 
|---|
| [610] | 2864 |     current_xp  = inode_xp; | 
|---|
| [1] | 2865 |  | 
|---|
| [610] | 2866 |     // build extended pointer on lock protecting Inode Tree | 
|---|
 | 2867 |     vfs_root_xp  = process->vfs_root_xp; | 
|---|
 | 2868 |     vfs_root_ptr = GET_PTR( vfs_root_xp ); | 
|---|
 | 2869 |     vfs_root_cxy = GET_CXY( vfs_root_xp ); | 
|---|
 | 2870 |     lock_xp      = XPTR( vfs_root_cxy , &vfs_root_ptr->main_lock ); | 
|---|
 | 2871 |  | 
|---|
 | 2872 |     // take lock protecting Inode Tree in read mode | 
|---|
 | 2873 |     remote_rwlock_rd_acquire( lock_xp ); | 
|---|
 | 2874 |  | 
|---|
 | 2875 |     // traverse Inode Tree from target inode to VFS root | 
|---|
 | 2876 |     // selecting always the first parent dentry | 
|---|
 | 2877 |     // the buffer is written in "reverse order" (from target inode to root)  | 
|---|
 | 2878 |     // exit the while loop when the VFS root has been found | 
|---|
| [1] | 2879 |         do | 
|---|
 | 2880 |     { | 
|---|
| [610] | 2881 |         // get current inode cluster and local pointer | 
|---|
 | 2882 |         current_cxy = GET_CXY( current_xp ); | 
|---|
 | 2883 |         current_ptr = GET_PTR( current_xp ); | 
|---|
| [1] | 2884 |  | 
|---|
| [610] | 2885 |         // build extended pointer on parents dentries root | 
|---|
 | 2886 |         parents_root_xp = XPTR( current_cxy , ¤t_ptr->parents ); | 
|---|
| [1] | 2887 |  | 
|---|
| [610] | 2888 |         // compute exit condition <=> current inode is VFS root     | 
|---|
 | 2889 |         found = xlist_is_empty( parents_root_xp ); | 
|---|
| [1] | 2890 |  | 
|---|
| [610] | 2891 |         if( found )                              // parent is the VFS root | 
|---|
 | 2892 |         { | 
|---|
 | 2893 |             if( index == (int32_t)(max_size - 1) ) | 
|---|
 | 2894 |             { | 
|---|
 | 2895 |                 // update index | 
|---|
 | 2896 |                 index--; | 
|---|
 | 2897 |                   | 
|---|
 | 2898 |                 // set separator   | 
|---|
 | 2899 |                         buffer[index] = '/'; | 
|---|
| [1] | 2900 |  | 
|---|
| [610] | 2901 | // check buffer overflow | 
|---|
 | 2902 | assert( (index >= 0) , "kernel buffer too small\n" ); | 
|---|
| [1] | 2903 |  | 
|---|
| [610] | 2904 |             } | 
|---|
 | 2905 |         } | 
|---|
 | 2906 |         else                                     // not the VFS root | 
|---|
| [1] | 2907 |         { | 
|---|
| [610] | 2908 |             // get first parent dentry cluster and pointers | 
|---|
 | 2909 |             dentry_xp  = XLIST_FIRST( parents_root_xp , vfs_dentry_t , parents ); | 
|---|
 | 2910 |             dentry_cxy = GET_CXY( dentry_xp ); | 
|---|
 | 2911 |             dentry_ptr = GET_PTR( dentry_xp ); | 
|---|
| [1] | 2912 |  | 
|---|
| [610] | 2913 |             // get extended pointer on dentry name and name length | 
|---|
 | 2914 |             name_xp = XPTR( dentry_cxy , dentry_ptr->name ); | 
|---|
 | 2915 |             length  = hal_remote_l32( XPTR( dentry_cxy , &dentry_ptr->length ) ); | 
|---|
| [1] | 2916 |  | 
|---|
| [610] | 2917 | #if (DEBUG_VFS_GET_PATH & 1) | 
|---|
 | 2918 | char debug_name[CONFIG_VFS_MAX_NAME_LENGTH]; | 
|---|
 | 2919 | hal_remote_strcpy( XPTR( local_cxy , debug_name ) , name_xp ); | 
|---|
 | 2920 | if( DEBUG_VFS_GET_PATH < cycle ) | 
|---|
 | 2921 | printk("\n[%s] thread(%x,%s) get current dentry <%s> in cluster %x\n", | 
|---|
 | 2922 | __FUNCTION__ , process->pid, this->trdid, debug_name, current_cxy ); | 
|---|
 | 2923 | #endif | 
|---|
 | 2924 |             // update index  | 
|---|
 | 2925 |             index -= (length + 1);  | 
|---|
 | 2926 |  | 
|---|
 | 2927 | // check buffer overflow | 
|---|
 | 2928 | assert( (index >= 0) , "kernel buffer too small\n" ); | 
|---|
 | 2929 |  | 
|---|
 | 2930 |             // update pathname | 
|---|
 | 2931 |             hal_remote_memcpy( XPTR( local_cxy , &buffer[index + 1] ) , | 
|---|
 | 2932 |                                name_xp , length ); | 
|---|
 | 2933 |  | 
|---|
 | 2934 |             // set separator   | 
|---|
 | 2935 |                     buffer[index] = '/'; | 
|---|
 | 2936 |  | 
|---|
 | 2937 |             // get extended pointer on parent inode | 
|---|
 | 2938 |             current_xp = XPTR( dentry_cxy ,  | 
|---|
 | 2939 |                                hal_remote_lpt( XPTR( dentry_cxy , &dentry_ptr->parent ) ) ); | 
|---|
 | 2940 |         } | 
|---|
| [1] | 2941 |     } | 
|---|
| [610] | 2942 |     while( found == false ); | 
|---|
| [1] | 2943 |  | 
|---|
| [610] | 2944 |     // release lock protecting Inode Tree in read mode | 
|---|
 | 2945 |     remote_rwlock_rd_release( lock_xp ); | 
|---|
 | 2946 |  | 
|---|
 | 2947 | #if DEBUG_VFS_GET_PATH | 
|---|
 | 2948 | cycle = (uint32_t)hal_get_cycles(); | 
|---|
 | 2949 | if( DEBUG_VFS_GET_PATH < cycle ) | 
|---|
 | 2950 | printk("\n[%s] thread[%x,%x] exit : path <%s> / cycle %d\n", | 
|---|
 | 2951 | __FUNCTION__ , process->pid, this->trdid, &buffer[index], cycle ); | 
|---|
 | 2952 | #endif | 
|---|
 | 2953 |  | 
|---|
 | 2954 |     // return pointer on first character in buffer | 
|---|
 | 2955 |     *first = &buffer[index]; | 
|---|
| [1] | 2956 |         return 0; | 
|---|
 | 2957 |  | 
|---|
 | 2958 | }  // end vfs_get_path() | 
|---|
 | 2959 |  | 
|---|
| [188] | 2960 |        | 
|---|
| [602] | 2961 | //////////////////////////////////////////////////////////////////// | 
|---|
| [610] | 2962 | error_t vfs_add_child_in_parent( cxy_t              child_cxy, | 
|---|
 | 2963 |                                  vfs_inode_type_t   child_type, | 
|---|
| [23] | 2964 |                                  vfs_fs_type_t      fs_type, | 
|---|
| [602] | 2965 |                                  xptr_t             parent_inode_xp, | 
|---|
| [23] | 2966 |                                  char             * name, | 
|---|
| [610] | 2967 |                                  xptr_t           * child_dentry_xp, | 
|---|
| [602] | 2968 |                                  xptr_t           * child_inode_xp ) | 
|---|
| [1] | 2969 | { | 
|---|
| [610] | 2970 |     error_t        error; | 
|---|
 | 2971 |     cxy_t          parent_cxy;          // parent inode cluster identifier | 
|---|
 | 2972 |     vfs_inode_t  * parent_inode_ptr;    // parent inode local pointer | 
|---|
 | 2973 |     xptr_t         new_dentry_xp;       // extended pointer on created dentry | 
|---|
 | 2974 |     vfs_dentry_t * new_dentry_ptr;      // created dentry local pointer | 
|---|
 | 2975 |     xptr_t         new_inode_xp;        // extended pointer on created child inode | 
|---|
 | 2976 |     vfs_inode_t  * new_inode_ptr;       // local pointer on created child inode | 
|---|
| [1] | 2977 |  | 
|---|
| [610] | 2978 |     xptr_t         parents_root_xp;     // extended pointer on child inode  "parents" field | 
|---|
 | 2979 |     xptr_t         parents_entry_xp;    // extended pointer on child dentry "parents" field | 
|---|
 | 2980 |     xptr_t         children_xhtab_xp;   // extended pointer on parent inode "children" field | 
|---|
 | 2981 |     xptr_t         children_entry_xp;   // extended pointer on child dentry "children" field | 
|---|
 | 2982 |      | 
|---|
 | 2983 |     // get parent inode cluster and pointer | 
|---|
 | 2984 |     parent_cxy       = GET_CXY( parent_inode_xp ); | 
|---|
| [602] | 2985 |     parent_inode_ptr = GET_PTR( parent_inode_xp ); | 
|---|
| [1] | 2986 |  | 
|---|
| [438] | 2987 | #if DEBUG_VFS_ADD_CHILD | 
|---|
| [602] | 2988 | char parent_name[CONFIG_VFS_MAX_NAME_LENGTH]; | 
|---|
 | 2989 | vfs_inode_get_name( parent_inode_xp , parent_name ); | 
|---|
| [433] | 2990 | uint32_t cycle = (uint32_t)hal_get_cycles(); | 
|---|
| [568] | 2991 | thread_t * this = CURRENT_THREAD;  | 
|---|
| [438] | 2992 | if( DEBUG_VFS_ADD_CHILD < cycle ) | 
|---|
| [610] | 2993 | printk("\n[%s] thread[%x,%x] enter / child <%s> / parent <%s> / cycle %d\n", | 
|---|
 | 2994 | __FUNCTION__, this->process->pid, this->trdid, name, | 
|---|
 | 2995 | parent_name, (uint32_t)hal_get_cycles() ); | 
|---|
| [433] | 2996 | #endif | 
|---|
| [279] | 2997 |  | 
|---|
| [610] | 2998 |     // 1. create dentry in parent cluster | 
|---|
 | 2999 |     if( parent_cxy == local_cxy )           // parent cluster is local | 
|---|
| [1] | 3000 |     { | 
|---|
| [23] | 3001 |         error = vfs_dentry_create( fs_type, | 
|---|
| [1] | 3002 |                                    name, | 
|---|
| [602] | 3003 |                                    &new_dentry_xp ); | 
|---|
| [1] | 3004 |     } | 
|---|
| [610] | 3005 |     else                                    // parent cluster is remote | 
|---|
| [1] | 3006 |     { | 
|---|
| [610] | 3007 |         rpc_vfs_dentry_create_client( parent_cxy, | 
|---|
| [23] | 3008 |                                       fs_type, | 
|---|
| [1] | 3009 |                                       name, | 
|---|
| [602] | 3010 |                                       &new_dentry_xp, | 
|---|
| [1] | 3011 |                                       &error ); | 
|---|
 | 3012 |     } | 
|---|
 | 3013 |                                        | 
|---|
 | 3014 |     if( error ) | 
|---|
 | 3015 |     { | 
|---|
| [437] | 3016 |         printk("\n[ERROR] in %s : cannot create dentry <%s> in cluster %x\n", | 
|---|
| [610] | 3017 |         __FUNCTION__ , name , parent_cxy ); | 
|---|
| [602] | 3018 |         return -1; | 
|---|
| [1] | 3019 |     } | 
|---|
 | 3020 |  | 
|---|
| [602] | 3021 |     // get dentry local pointer | 
|---|
 | 3022 |     new_dentry_ptr = GET_PTR( new_dentry_xp ); | 
|---|
 | 3023 |  | 
|---|
| [568] | 3024 | #if(DEBUG_VFS_ADD_CHILD & 1) | 
|---|
 | 3025 | if( DEBUG_VFS_ADD_CHILD < cycle ) | 
|---|
| [610] | 3026 | printk("\n[%s] thread[%x,%x] / dentry <%s> created (%x,%x)\n", | 
|---|
 | 3027 | __FUNCTION__, this->process->pid, this->trdid, name, parent_cxy, new_dentry_ptr ); | 
|---|
| [568] | 3028 | #endif | 
|---|
 | 3029 |  | 
|---|
| [610] | 3030 |     // 2. create child inode in child cluster | 
|---|
 | 3031 |     // TODO : define attr / mode / uid / gid | 
|---|
| [1] | 3032 |     uint32_t attr = 0; | 
|---|
 | 3033 |     uint32_t mode = 0; | 
|---|
 | 3034 |     uint32_t uid  = 0; | 
|---|
 | 3035 |     uint32_t gid  = 0; | 
|---|
 | 3036 |      | 
|---|
| [610] | 3037 |     if( child_cxy == local_cxy )      // child cluster is local  | 
|---|
| [1] | 3038 |     { | 
|---|
| [610] | 3039 |         error = vfs_inode_create( fs_type, | 
|---|
 | 3040 |                                   child_type, | 
|---|
| [1] | 3041 |                                   attr, | 
|---|
 | 3042 |                                   mode, | 
|---|
 | 3043 |                                   uid, | 
|---|
 | 3044 |                                   gid, | 
|---|
| [602] | 3045 |                                   &new_inode_xp ); | 
|---|
| [1] | 3046 |     } | 
|---|
 | 3047 |     else                              // child cluster is remote | 
|---|
 | 3048 |     { | 
|---|
| [610] | 3049 |         rpc_vfs_inode_create_client( child_cxy, | 
|---|
| [23] | 3050 |                                      fs_type, | 
|---|
| [610] | 3051 |                                      child_type, | 
|---|
| [1] | 3052 |                                      attr, | 
|---|
 | 3053 |                                      mode, | 
|---|
 | 3054 |                                      uid, | 
|---|
 | 3055 |                                      gid, | 
|---|
| [602] | 3056 |                                      &new_inode_xp, | 
|---|
| [1] | 3057 |                                      &error ); | 
|---|
 | 3058 |     } | 
|---|
 | 3059 |                                       | 
|---|
 | 3060 |     if( error ) | 
|---|
 | 3061 |     { | 
|---|
 | 3062 |         printk("\n[ERROR] in %s : cannot create inode in cluster %x\n", | 
|---|
| [610] | 3063 |                __FUNCTION__ , child_cxy ); | 
|---|
| [1] | 3064 |   | 
|---|
| [610] | 3065 |         if( parent_cxy == local_cxy ) vfs_dentry_destroy( new_dentry_ptr ); | 
|---|
 | 3066 |         else rpc_vfs_dentry_destroy_client( parent_cxy , new_dentry_ptr ); | 
|---|
| [602] | 3067 |         return -1; | 
|---|
| [1] | 3068 |     } | 
|---|
 | 3069 |  | 
|---|
| [610] | 3070 |     // get new inode local pointer | 
|---|
 | 3071 |     new_inode_ptr = GET_PTR( new_inode_xp ); | 
|---|
 | 3072 |      | 
|---|
| [568] | 3073 | #if(DEBUG_VFS_ADD_CHILD & 1) | 
|---|
 | 3074 | if( DEBUG_VFS_ADD_CHILD < cycle ) | 
|---|
| [610] | 3075 | printk("\n[%s] thread[%x,%x] / inode <%s> created (%x,%x)\n", | 
|---|
 | 3076 | __FUNCTION__ , this->process->pid, this->trdid, name , child_cxy, new_inode_ptr ); | 
|---|
| [568] | 3077 | #endif | 
|---|
 | 3078 |  | 
|---|
| [610] | 3079 |     // 3. register new_dentry in new_inode xlist of parents  | 
|---|
 | 3080 |     parents_root_xp  = XPTR( child_cxy , &new_inode_ptr->parents ); | 
|---|
 | 3081 |     parents_entry_xp = XPTR( parent_cxy, &new_dentry_ptr->parents ); | 
|---|
 | 3082 |     xlist_add_first( parents_root_xp , parents_entry_xp ); | 
|---|
 | 3083 |     hal_remote_atomic_add( XPTR( child_cxy , &new_inode_ptr->links ) , 1 ); | 
|---|
| [204] | 3084 |  | 
|---|
| [610] | 3085 | #if(DEBUG_VFS_ADD_CHILD & 1) | 
|---|
| [611] | 3086 | if( DEBUG_VFS_ADD_CHILD < cycle ) | 
|---|
| [610] | 3087 | printk("\n[%s] thread[%x,%x] / dentry (%x,%x) registered in child inode (%x,%x)\n", | 
|---|
 | 3088 | __FUNCTION__, this->process->pid, this->trdid,  | 
|---|
 | 3089 | parent_cxy, new_dentry_ptr, child_cxy, new_inode_ptr ); | 
|---|
 | 3090 | #endif | 
|---|
 | 3091 |  | 
|---|
| [611] | 3092 |     // register new_dentry in parent_inode xhtab of children | 
|---|
| [610] | 3093 |     children_xhtab_xp = XPTR( parent_cxy , &parent_inode_ptr->children ); | 
|---|
 | 3094 |     children_entry_xp = XPTR( parent_cxy , &new_dentry_ptr->children ); | 
|---|
 | 3095 |     xhtab_insert( children_xhtab_xp , name , children_entry_xp ); | 
|---|
 | 3096 |  | 
|---|
 | 3097 | #if(DEBUG_VFS_ADD_CHILD & 1) | 
|---|
 | 3098 | if( DEBUG_VFS_ADD_CHILD < cycle ) | 
|---|
 | 3099 | printk("\n[%s] thread[%x,%x] / dentry (%x,%x) registered in parent inode (%x,%x)\n", | 
|---|
 | 3100 | __FUNCTION__, this->process->pid, this->trdid,  | 
|---|
 | 3101 | parent_cxy, new_dentry_ptr, parent_cxy, parent_inode_ptr ); | 
|---|
 | 3102 | #endif | 
|---|
 | 3103 |  | 
|---|
| [611] | 3104 |     // update "parent" and "child_xp" fields in new_dentry | 
|---|
| [610] | 3105 |     hal_remote_s64( XPTR( parent_cxy , &new_dentry_ptr->child_xp ) , new_inode_xp ); | 
|---|
 | 3106 |     hal_remote_spt( XPTR( parent_cxy , &new_dentry_ptr->parent ) , parent_inode_ptr ); | 
|---|
 | 3107 |  | 
|---|
| [438] | 3108 | #if DEBUG_VFS_ADD_CHILD | 
|---|
| [433] | 3109 | cycle = (uint32_t)hal_get_cycles(); | 
|---|
| [438] | 3110 | if( DEBUG_VFS_ADD_CHILD < cycle ) | 
|---|
| [598] | 3111 | printk("\n[%s] thread[%x,%x] exit for <%s> / cycle %d\n", | 
|---|
 | 3112 | __FUNCTION__, this->process->pid, this->trdid, name, (uint32_t)hal_get_cycles() ); | 
|---|
| [433] | 3113 | #endif | 
|---|
| [296] | 3114 |  | 
|---|
| [602] | 3115 |     // return extended pointer on dentry & child inode | 
|---|
| [610] | 3116 |     *child_dentry_xp = new_dentry_xp; | 
|---|
 | 3117 |     *child_inode_xp  = new_inode_xp; | 
|---|
| [1] | 3118 |     return 0; | 
|---|
 | 3119 |  | 
|---|
 | 3120 | }  // end vfs_add_child_in_parent() | 
|---|
 | 3121 |  | 
|---|
| [610] | 3122 | ///////////////////////////////////////////////////// | 
|---|
 | 3123 | void vfs_remove_child_from_parent( xptr_t dentry_xp ) | 
|---|
| [459] | 3124 | { | 
|---|
| [610] | 3125 |     cxy_t          parent_cxy;         // parent inode cluster identifier | 
|---|
 | 3126 |     cxy_t          child_cxy;          // child inode cluster identifier | 
|---|
 | 3127 |     vfs_dentry_t * dentry_ptr;         // local pointer on dentry | 
|---|
 | 3128 |     xptr_t         child_inode_xp;     // extended pointer on child inode | 
|---|
 | 3129 |     vfs_inode_t  * child_inode_ptr;    // local pointer on child inode | 
|---|
 | 3130 |     vfs_inode_t  * parent_inode_ptr;   // local pointer on parent inode | 
|---|
 | 3131 |     uint32_t       links;              // number of child inode parents | 
|---|
 | 3132 |  | 
|---|
 | 3133 |     char dentry_name[CONFIG_VFS_MAX_NAME_LENGTH]; | 
|---|
| [459] | 3134 |     | 
|---|
| [610] | 3135 |     // get parent cluster and dentry local pointer | 
|---|
 | 3136 |     parent_cxy = GET_CXY( dentry_xp ); | 
|---|
| [459] | 3137 |     dentry_ptr = GET_PTR( dentry_xp ); | 
|---|
 | 3138 |  | 
|---|
| [610] | 3139 |     // get a local copy of dentry name | 
|---|
 | 3140 |     hal_remote_strcpy( XPTR( local_cxy  , dentry_name ), | 
|---|
 | 3141 |                        XPTR( parent_cxy , &dentry_ptr->name ) ); | 
|---|
| [459] | 3142 |  | 
|---|
| [610] | 3143 |     // get parent_inode local pointer | 
|---|
 | 3144 |     parent_inode_ptr = hal_remote_lpt( XPTR( parent_cxy , &dentry_ptr->parent ) ); | 
|---|
 | 3145 |    | 
|---|
 | 3146 |     // get child cluster and child_inode pointers  | 
|---|
 | 3147 |     child_inode_xp   = hal_remote_l64( XPTR( parent_cxy , &dentry_ptr->child_xp ) ); | 
|---|
 | 3148 |     child_cxy        = GET_CXY( child_inode_xp );  | 
|---|
 | 3149 |     child_inode_ptr  = GET_PTR( child_inode_xp ); | 
|---|
| [602] | 3150 |  | 
|---|
| [610] | 3151 |     // remove dentry from parent_inode | 
|---|
 | 3152 |     xhtab_remove( XPTR( parent_cxy , &parent_inode_ptr->children ), | 
|---|
 | 3153 |                   dentry_name, | 
|---|
 | 3154 |                   XPTR( parent_cxy , &dentry_ptr->children ) ); | 
|---|
| [602] | 3155 |  | 
|---|
| [610] | 3156 |     // remove dentry from child_inode | 
|---|
 | 3157 |     xlist_unlink( XPTR( parent_cxy , &dentry_ptr->parents ) ); | 
|---|
 | 3158 |     links = hal_remote_atomic_add( XPTR( child_cxy , &child_inode_ptr->links ) , -1 ); | 
|---|
 | 3159 |  | 
|---|
 | 3160 |     // delete dentry descriptor | 
|---|
 | 3161 |     if( parent_cxy == local_cxy ) | 
|---|
| [459] | 3162 |     { | 
|---|
| [602] | 3163 |          vfs_dentry_destroy( dentry_ptr ); | 
|---|
| [459] | 3164 |     } | 
|---|
 | 3165 |     else | 
|---|
 | 3166 |     { | 
|---|
| [610] | 3167 |          rpc_vfs_dentry_destroy_client( parent_cxy, | 
|---|
| [602] | 3168 |                                         dentry_ptr ); | 
|---|
| [459] | 3169 |     } | 
|---|
 | 3170 |  | 
|---|
| [610] | 3171 |     // delete child_inode descriptor if last link | 
|---|
 | 3172 |     if( links == 1 ) | 
|---|
| [459] | 3173 |     { | 
|---|
| [610] | 3174 |         if( child_cxy == local_cxy ) | 
|---|
 | 3175 |         { | 
|---|
 | 3176 |             vfs_inode_destroy( child_inode_ptr ); | 
|---|
 | 3177 |         } | 
|---|
 | 3178 |         else | 
|---|
 | 3179 |         { | 
|---|
 | 3180 |             rpc_vfs_inode_destroy_client( child_cxy , child_inode_ptr ); | 
|---|
 | 3181 |         } | 
|---|
| [459] | 3182 |     } | 
|---|
 | 3183 |  | 
|---|
 | 3184 | }  // end vfs_remove_child_from_parent() | 
|---|
 | 3185 |  | 
|---|
| [612] | 3186 |  | 
|---|
 | 3187 |  | 
|---|
 | 3188 |  | 
|---|
| [23] | 3189 | ////////////////////////////////////////////////////////////////////////////////////////// | 
|---|
| [602] | 3190 | //    API used by VFS to access a specific FS   | 
|---|
| [23] | 3191 | ////////////////////////////////////////////////////////////////////////////////////////// | 
|---|
 | 3192 |  | 
|---|
| [614] | 3193 | ////////////////////////////////////////////// | 
|---|
 | 3194 | error_t vfs_fs_move_page( xptr_t      page_xp, | 
|---|
 | 3195 |                           cmd_type_t  cmd_type ) | 
|---|
| [23] | 3196 | { | 
|---|
| [204] | 3197 |     error_t error = 0; | 
|---|
| [23] | 3198 |  | 
|---|
| [602] | 3199 | assert( (page_xp != XPTR_NULL) , "page pointer is NULL\n" ); | 
|---|
| [23] | 3200 |  | 
|---|
| [602] | 3201 |     page_t * page_ptr = GET_PTR( page_xp ); | 
|---|
 | 3202 |     cxy_t    page_cxy = GET_CXY( page_xp ); | 
|---|
| [23] | 3203 |  | 
|---|
| [602] | 3204 |     // get local pointer on page mapper | 
|---|
 | 3205 |     mapper_t * mapper = hal_remote_lpt( XPTR( page_cxy , &page_ptr->mapper ) ); | 
|---|
| [23] | 3206 |  | 
|---|
| [602] | 3207 | assert( (mapper != NULL) , "no mapper for page\n" ); | 
|---|
| [246] | 3208 |  | 
|---|
| [23] | 3209 |     // get FS type | 
|---|
| [602] | 3210 |     vfs_fs_type_t fs_type = hal_remote_l32( XPTR( page_cxy , &mapper->type ) ); | 
|---|
| [23] | 3211 |  | 
|---|
| [238] | 3212 |     // call relevant FS function | 
|---|
| [23] | 3213 |     if( fs_type == FS_TYPE_FATFS ) | 
|---|
 | 3214 |     { | 
|---|
| [614] | 3215 |         error = fatfs_move_page( page_xp , cmd_type );  | 
|---|
| [602] | 3216 |     } | 
|---|
 | 3217 |     else if( fs_type == FS_TYPE_RAMFS ) | 
|---|
 | 3218 |     { | 
|---|
 | 3219 |         assert( false , "should not be called for RAMFS\n" ); | 
|---|
 | 3220 |     } | 
|---|
 | 3221 |     else if( fs_type == FS_TYPE_DEVFS ) | 
|---|
 | 3222 |     { | 
|---|
 | 3223 |         assert( false , "should not be called for DEVFS\n" ); | 
|---|
 | 3224 |     } | 
|---|
 | 3225 |     else | 
|---|
 | 3226 |     { | 
|---|
 | 3227 |         assert( false , "undefined file system type\n" ); | 
|---|
 | 3228 |     } | 
|---|
| [568] | 3229 |  | 
|---|
| [602] | 3230 |     return error; | 
|---|
| [568] | 3231 |  | 
|---|
| [602] | 3232 | }  // end vfs_fs_move_page() | 
|---|
 | 3233 |  | 
|---|
 | 3234 | //////////////////////////////////////////////// | 
|---|
 | 3235 | error_t vfs_fs_add_dentry( vfs_inode_t  * inode, | 
|---|
 | 3236 |                            vfs_dentry_t * dentry ) | 
|---|
 | 3237 | { | 
|---|
 | 3238 |     error_t error = 0; | 
|---|
 | 3239 |  | 
|---|
 | 3240 | assert( (inode  != NULL) , "inode  pointer is NULL\n" ); | 
|---|
 | 3241 | assert( (dentry != NULL) , "dentry pointer is NULL\n" ); | 
|---|
 | 3242 |  | 
|---|
 | 3243 |     mapper_t * mapper = inode->mapper; | 
|---|
 | 3244 |  | 
|---|
 | 3245 | assert( (mapper != NULL) , "mapper pointer is NULL\n" ); | 
|---|
 | 3246 |  | 
|---|
 | 3247 |     // get FS type | 
|---|
 | 3248 |     vfs_fs_type_t fs_type = mapper->type; | 
|---|
 | 3249 |  | 
|---|
 | 3250 |     // call relevant FS function | 
|---|
 | 3251 |     if( fs_type == FS_TYPE_FATFS ) | 
|---|
 | 3252 |     { | 
|---|
 | 3253 |         error = fatfs_add_dentry( inode , dentry );  | 
|---|
| [23] | 3254 |     } | 
|---|
 | 3255 |     else if( fs_type == FS_TYPE_RAMFS ) | 
|---|
 | 3256 |     { | 
|---|
| [612] | 3257 |         error = 0;     // does nothing for RAMFS | 
|---|
| [23] | 3258 |     } | 
|---|
 | 3259 |     else if( fs_type == FS_TYPE_DEVFS ) | 
|---|
 | 3260 |     { | 
|---|
| [612] | 3261 |         error = 0;     // does nothing for DEVFS | 
|---|
| [23] | 3262 |     } | 
|---|
 | 3263 |     else | 
|---|
 | 3264 |     { | 
|---|
| [492] | 3265 |         assert( false , "undefined file system type\n" ); | 
|---|
| [23] | 3266 |     } | 
|---|
 | 3267 |  | 
|---|
 | 3268 |     return error; | 
|---|
 | 3269 |  | 
|---|
| [602] | 3270 | }  // end vfs_fs_add_dentry() | 
|---|
| [23] | 3271 |  | 
|---|
| [602] | 3272 | /////////////////////////////////////////////////// | 
|---|
 | 3273 | error_t vfs_fs_remove_dentry( vfs_inode_t  * inode, | 
|---|
 | 3274 |                               vfs_dentry_t * dentry ) | 
|---|
| [23] | 3275 | { | 
|---|
| [602] | 3276 |     error_t error = 0; | 
|---|
| [23] | 3277 |  | 
|---|
| [602] | 3278 | assert( (inode  != NULL) , "inode  pointer is NULL\n" ); | 
|---|
 | 3279 | assert( (dentry != NULL) , "dentry pointer is NULL\n" ); | 
|---|
| [23] | 3280 |  | 
|---|
| [238] | 3281 |     mapper_t * mapper = inode->mapper; | 
|---|
| [23] | 3282 |  | 
|---|
| [598] | 3283 | assert( (mapper != NULL) , "mapper pointer is NULL\n" ); | 
|---|
| [23] | 3284 |  | 
|---|
| [602] | 3285 |     // get FS type | 
|---|
 | 3286 |     vfs_fs_type_t fs_type = mapper->type; | 
|---|
| [401] | 3287 |  | 
|---|
| [602] | 3288 |     // call relevant FS function | 
|---|
 | 3289 |     if( fs_type == FS_TYPE_FATFS ) | 
|---|
 | 3290 |     { | 
|---|
 | 3291 |         error = fatfs_remove_dentry( inode , dentry );  | 
|---|
 | 3292 |     } | 
|---|
 | 3293 |     else if( fs_type == FS_TYPE_RAMFS ) | 
|---|
 | 3294 |     { | 
|---|
| [612] | 3295 |         error = 0;     // does nothing for RAMFS | 
|---|
| [602] | 3296 |     } | 
|---|
 | 3297 |     else if( fs_type == FS_TYPE_DEVFS ) | 
|---|
 | 3298 |     { | 
|---|
| [612] | 3299 |         error = 0;     // does nothing for DEVFS | 
|---|
| [602] | 3300 |     } | 
|---|
 | 3301 |     else | 
|---|
 | 3302 |     { | 
|---|
 | 3303 |         assert( false , "undefined file system type\n" ); | 
|---|
 | 3304 |     } | 
|---|
| [238] | 3305 |  | 
|---|
| [602] | 3306 |     return error; | 
|---|
 | 3307 |  | 
|---|
 | 3308 | }  // end vfs_fs_remove_dentry() | 
|---|
 | 3309 |  | 
|---|
 | 3310 | //////////////////////////////////////////////// | 
|---|
| [612] | 3311 | error_t vfs_fs_get_dentry( vfs_inode_t * parent, | 
|---|
| [602] | 3312 |                            char        * name, | 
|---|
 | 3313 |                            xptr_t        child_xp ) | 
|---|
 | 3314 | { | 
|---|
 | 3315 |     error_t error = 0; | 
|---|
 | 3316 |  | 
|---|
 | 3317 | // check arguments | 
|---|
 | 3318 | assert( (parent != NULL) , "parent pointer is NULL\n"); | 
|---|
 | 3319 | assert( (child_xp != XPTR_NULL) , "child pointer is NULL\n"); | 
|---|
 | 3320 |  | 
|---|
 | 3321 |     // get parent inode FS type | 
|---|
 | 3322 |     vfs_fs_type_t fs_type = parent->ctx->type; | 
|---|
 | 3323 |  | 
|---|
 | 3324 |     // call relevant FS function | 
|---|
 | 3325 |     if( fs_type == FS_TYPE_FATFS ) | 
|---|
| [23] | 3326 |     { | 
|---|
| [612] | 3327 |         error = fatfs_get_dentry( parent , name , child_xp ); | 
|---|
| [602] | 3328 |     } | 
|---|
 | 3329 |     else if( fs_type == FS_TYPE_RAMFS ) | 
|---|
 | 3330 |     { | 
|---|
 | 3331 |         assert( false , "should not be called for RAMFS\n" ); | 
|---|
 | 3332 |     } | 
|---|
 | 3333 |     else if( fs_type == FS_TYPE_DEVFS ) | 
|---|
 | 3334 |     { | 
|---|
 | 3335 |         assert( false , "should not be called for DEVFS\n" ); | 
|---|
 | 3336 |     } | 
|---|
 | 3337 |     else | 
|---|
 | 3338 |     { | 
|---|
 | 3339 |         assert( false , "undefined file system type\n" ); | 
|---|
 | 3340 |     } | 
|---|
| [23] | 3341 |  | 
|---|
| [602] | 3342 |     return error; | 
|---|
 | 3343 |  | 
|---|
| [612] | 3344 | } // end vfs_fs_get_dentry() | 
|---|
| [602] | 3345 |  | 
|---|
| [612] | 3346 | /////////////////////////////////////////////////// | 
|---|
 | 3347 | error_t vfs_fs_get_user_dir( vfs_inode_t   * inode, | 
|---|
 | 3348 |                              struct dirent * array, | 
|---|
 | 3349 |                              uint32_t        max_dirent, | 
|---|
 | 3350 |                              uint32_t        min_dentry, | 
|---|
 | 3351 |                              bool_t          detailed, | 
|---|
 | 3352 |                              uint32_t      * entries, | 
|---|
 | 3353 |                              bool_t        * done ) | 
|---|
 | 3354 | { | 
|---|
 | 3355 |     error_t error = 0; | 
|---|
 | 3356 |  | 
|---|
 | 3357 | // check arguments | 
|---|
 | 3358 | assert( (inode != NULL) , "parent pointer is NULL\n"); | 
|---|
 | 3359 | assert( (array != NULL) , "child pointer is NULL\n"); | 
|---|
 | 3360 | assert( (detailed == false) , "detailed argument not supported\n"); | 
|---|
 | 3361 |  | 
|---|
 | 3362 |     // check inode type | 
|---|
 | 3363 |     if( inode->type != INODE_TYPE_DIR ) | 
|---|
 | 3364 |     { | 
|---|
 | 3365 |         printk("\n[ERROR] in %s : target inode is not a directory\n", | 
|---|
 | 3366 |         __FUNCTION__ ); | 
|---|
 | 3367 |         return -1; | 
|---|
 | 3368 |     } | 
|---|
 | 3369 |  | 
|---|
 | 3370 |     // get parent inode FS type | 
|---|
 | 3371 |     vfs_fs_type_t fs_type = inode->ctx->type; | 
|---|
 | 3372 |  | 
|---|
 | 3373 |     // call relevant FS function | 
|---|
 | 3374 |     if( fs_type == FS_TYPE_FATFS ) | 
|---|
 | 3375 |     { | 
|---|
 | 3376 |         error = fatfs_get_user_dir( inode,  | 
|---|
 | 3377 |                                     array, | 
|---|
 | 3378 |                                     max_dirent, | 
|---|
 | 3379 |                                     min_dentry, | 
|---|
 | 3380 |                                     detailed, | 
|---|
 | 3381 |                                     entries, | 
|---|
 | 3382 |                                     done ); | 
|---|
 | 3383 |     } | 
|---|
 | 3384 |     else if( fs_type == FS_TYPE_RAMFS ) | 
|---|
 | 3385 |     { | 
|---|
 | 3386 |         assert( false , "should not be called for RAMFS\n" ); | 
|---|
 | 3387 |     } | 
|---|
 | 3388 |     else if( fs_type == FS_TYPE_DEVFS ) | 
|---|
 | 3389 |     { | 
|---|
 | 3390 |         error = devfs_get_user_dir( inode, | 
|---|
 | 3391 |                                     array, | 
|---|
 | 3392 |                                     max_dirent, | 
|---|
 | 3393 |                                     min_dentry, | 
|---|
 | 3394 |                                     detailed, | 
|---|
 | 3395 |                                     entries, | 
|---|
 | 3396 |                                     done ); | 
|---|
 | 3397 |     } | 
|---|
 | 3398 |     else | 
|---|
 | 3399 |     { | 
|---|
 | 3400 |         assert( false , "undefined file system type\n" ); | 
|---|
 | 3401 |     } | 
|---|
 | 3402 |  | 
|---|
 | 3403 |     return error; | 
|---|
 | 3404 |  | 
|---|
 | 3405 | }  // end vfs_fs_get_user_dir() | 
|---|
 | 3406 |   | 
|---|
| [610] | 3407 | //////////////////////////////////////////////// | 
|---|
 | 3408 | error_t vfs_fs_sync_inode( vfs_inode_t * inode ) | 
|---|
 | 3409 | { | 
|---|
 | 3410 |     error_t error = 0; | 
|---|
 | 3411 |  | 
|---|
 | 3412 | // check arguments | 
|---|
 | 3413 | assert( (inode != NULL) , "inode pointer is NULL\n"); | 
|---|
 | 3414 |  | 
|---|
 | 3415 |     // get inode FS type | 
|---|
 | 3416 |     vfs_fs_type_t fs_type = inode->ctx->type; | 
|---|
 | 3417 |  | 
|---|
 | 3418 |     // call relevant FS function | 
|---|
 | 3419 |     if( fs_type == FS_TYPE_FATFS ) | 
|---|
 | 3420 |     { | 
|---|
 | 3421 |         error = fatfs_sync_inode( inode ); | 
|---|
 | 3422 |     } | 
|---|
 | 3423 |     else if( fs_type == FS_TYPE_RAMFS ) | 
|---|
 | 3424 |     { | 
|---|
 | 3425 |         assert( false , "should not be called for RAMFS\n" ); | 
|---|
 | 3426 |     } | 
|---|
 | 3427 |     else if( fs_type == FS_TYPE_DEVFS ) | 
|---|
 | 3428 |     { | 
|---|
 | 3429 |         assert( false , "should not be called for DEVFS\n" ); | 
|---|
 | 3430 |     } | 
|---|
 | 3431 |     else | 
|---|
 | 3432 |     { | 
|---|
 | 3433 |         assert( false , "undefined file system type\n" ); | 
|---|
 | 3434 |     } | 
|---|
 | 3435 |  | 
|---|
 | 3436 |     return error; | 
|---|
 | 3437 |  | 
|---|
 | 3438 | }  // end vfs_fs_sync_inode() | 
|---|
 | 3439 |  | 
|---|
 | 3440 | //////////////////////////////////////////////// | 
|---|
 | 3441 | error_t vfs_fs_sync_fat( vfs_fs_type_t fs_type ) | 
|---|
 | 3442 | { | 
|---|
 | 3443 |     error_t error = 0; | 
|---|
 | 3444 |  | 
|---|
 | 3445 |     // call relevant FS function | 
|---|
 | 3446 |     if( fs_type == FS_TYPE_FATFS ) | 
|---|
 | 3447 |     { | 
|---|
 | 3448 |         error = fatfs_sync_fat(); | 
|---|
 | 3449 |     } | 
|---|
 | 3450 |     else if( fs_type == FS_TYPE_RAMFS ) | 
|---|
 | 3451 |     { | 
|---|
 | 3452 |         assert( false , "should not be called for RAMFS\n" ); | 
|---|
 | 3453 |     } | 
|---|
 | 3454 |     else if( fs_type == FS_TYPE_DEVFS ) | 
|---|
 | 3455 |     { | 
|---|
 | 3456 |         assert( false , "should not be called for DEVFS\n" ); | 
|---|
 | 3457 |     } | 
|---|
 | 3458 |     else | 
|---|
 | 3459 |     { | 
|---|
 | 3460 |         assert( false , "undefined file system type\n" ); | 
|---|
 | 3461 |     } | 
|---|
 | 3462 |  | 
|---|
 | 3463 |     return error; | 
|---|
 | 3464 |  | 
|---|
 | 3465 | }  // end vfs_fs_sync_fat() | 
|---|
 | 3466 |  | 
|---|
 | 3467 | ////////////////////////////////////////////////////// | 
|---|
 | 3468 | error_t vfs_fs_sync_free_info( vfs_fs_type_t fs_type ) | 
|---|
 | 3469 | { | 
|---|
 | 3470 |     error_t error = 0; | 
|---|
 | 3471 |  | 
|---|
 | 3472 |     // call relevant FS function | 
|---|
 | 3473 |     if( fs_type == FS_TYPE_FATFS ) | 
|---|
 | 3474 |     { | 
|---|
 | 3475 |         error = fatfs_sync_free_info(); | 
|---|
 | 3476 |     } | 
|---|
 | 3477 |     else if( fs_type == FS_TYPE_RAMFS ) | 
|---|
 | 3478 |     { | 
|---|
 | 3479 |         assert( false , "should not be called for RAMFS\n" ); | 
|---|
 | 3480 |     } | 
|---|
 | 3481 |     else if( fs_type == FS_TYPE_DEVFS ) | 
|---|
 | 3482 |     { | 
|---|
 | 3483 |         assert( false , "should not be called for DEVFS\n" ); | 
|---|
 | 3484 |     } | 
|---|
 | 3485 |     else | 
|---|
 | 3486 |     { | 
|---|
 | 3487 |         assert( false , "undefined file system type\n" ); | 
|---|
 | 3488 |     } | 
|---|
 | 3489 |  | 
|---|
 | 3490 |     return error; | 
|---|
 | 3491 |  | 
|---|
 | 3492 | }  // end vfs_fs_sync_fat() | 
|---|
 | 3493 |  | 
|---|
| [602] | 3494 | ///////////////////////////////////////////////// | 
|---|
 | 3495 | error_t vfs_fs_cluster_alloc( uint32_t   fs_type, | 
|---|
 | 3496 |                               uint32_t * cluster ) | 
|---|
 | 3497 | { | 
|---|
 | 3498 |     error_t error = 0; | 
|---|
 | 3499 |  | 
|---|
 | 3500 |     // call relevant FS function | 
|---|
 | 3501 |     if( fs_type == FS_TYPE_FATFS ) | 
|---|
 | 3502 |     { | 
|---|
 | 3503 |         error = fatfs_cluster_alloc( cluster ); | 
|---|
| [23] | 3504 |     } | 
|---|
| [602] | 3505 |     else if( fs_type == FS_TYPE_RAMFS ) | 
|---|
 | 3506 |     { | 
|---|
 | 3507 |         assert( false , "should not be called for RAMFS\n" ); | 
|---|
 | 3508 |     } | 
|---|
 | 3509 |     else if( fs_type == FS_TYPE_DEVFS ) | 
|---|
 | 3510 |     { | 
|---|
 | 3511 |         assert( false , "should not be called for DEVFS\n" ); | 
|---|
 | 3512 |     } | 
|---|
 | 3513 |     else | 
|---|
 | 3514 |     { | 
|---|
 | 3515 |         assert( false , "undefined file system type\n" ); | 
|---|
 | 3516 |     } | 
|---|
| [23] | 3517 |  | 
|---|
| [602] | 3518 |     return error; | 
|---|
| [401] | 3519 |  | 
|---|
| [602] | 3520 | } // end vfs_fs_alloc_cluster() | 
|---|
| [23] | 3521 |  | 
|---|
| [602] | 3522 | //////////////////////////////////////////////// | 
|---|
 | 3523 | error_t vfs_fs_release_inode( xptr_t  inode_xp ) | 
|---|
 | 3524 | { | 
|---|
 | 3525 |     error_t error = 0; | 
|---|
| [23] | 3526 |  | 
|---|
| [602] | 3527 | assert( (inode_xp  != XPTR_NULL) , "inode pointer is NULL\n")         | 
|---|
 | 3528 |  | 
|---|
 | 3529 |     vfs_inode_t * inode_ptr = GET_PTR( inode_xp ); | 
|---|
 | 3530 |     cxy_t         inode_cxy = GET_CXY( inode_xp ); | 
|---|
 | 3531 |  | 
|---|
 | 3532 |     // get local pointer on page mapper  | 
|---|
 | 3533 |     mapper_t * mapper = hal_remote_lpt( XPTR( inode_cxy , &inode_ptr->mapper ) ); | 
|---|
 | 3534 |  | 
|---|
 | 3535 | assert( (mapper != NULL) , "mapper pointer is NULL\n")         | 
|---|
 | 3536 |  | 
|---|
 | 3537 |     // get FS type from mapper | 
|---|
 | 3538 |     vfs_fs_type_t fs_type = hal_remote_l32( XPTR( inode_cxy , &mapper->type ) ); | 
|---|
 | 3539 |  | 
|---|
 | 3540 |     // call relevant FS function | 
|---|
 | 3541 |     if( fs_type == FS_TYPE_FATFS ) | 
|---|
 | 3542 |     { | 
|---|
 | 3543 |         error = fatfs_release_inode( inode_xp );  | 
|---|
 | 3544 |     } | 
|---|
 | 3545 |     else if( fs_type == FS_TYPE_RAMFS ) | 
|---|
 | 3546 |     { | 
|---|
 | 3547 |         assert( false , "should not be called for RAMFS\n" ); | 
|---|
 | 3548 |     } | 
|---|
 | 3549 |     else if( fs_type == FS_TYPE_DEVFS ) | 
|---|
 | 3550 |     { | 
|---|
 | 3551 |         assert( false , "should not be called for DEVFS\n" ); | 
|---|
 | 3552 |     } | 
|---|
 | 3553 |     else | 
|---|
 | 3554 |     { | 
|---|
 | 3555 |         assert( false , "undefined file system type\n" ); | 
|---|
 | 3556 |     } | 
|---|
 | 3557 |  | 
|---|
 | 3558 |     return error; | 
|---|
 | 3559 |      | 
|---|
 | 3560 | }  // end vfs_fs_release_inode() | 
|---|
 | 3561 |  | 
|---|
 | 3562 |  | 
|---|