SimpleOS

LXR

Navigation



Site hébergé par : enix

The LXR Cross Referencer for SOS

source navigation ]
diff markup ]
identifier search ]
general search ]
 
 
Article:1 ] [ 2 ] [ 3 ] [ 4 ] [ 5 ] [ 6 ] [ 6.5 ] [ 7 ] [ 7.5 ] [ 8 ] [ 9 ] [ 9.5 ]

Diff markup

Differences between /drivers/fs_virtfs.c (Article 9) and /drivers/fs_virtfs.c (Article 9.5)


001 /* Copyright (C) 2005 David Decotigny             001 /* Copyright (C) 2005 David Decotigny
002                                                   002 
003    This program is free software; you can redi    003    This program is free software; you can redistribute it and/or
004    modify it under the terms of the GNU Genera    004    modify it under the terms of the GNU General Public License
005    as published by the Free Software Foundatio    005    as published by the Free Software Foundation; either version 2
006    of the License, or (at your option) any lat    006    of the License, or (at your option) any later version.
007                                                   007    
008    This program is distributed in the hope tha    008    This program is distributed in the hope that it will be useful,
009    but WITHOUT ANY WARRANTY; without even the     009    but WITHOUT ANY WARRANTY; without even the implied warranty of
010    MERCHANTABILITY or FITNESS FOR A PARTICULAR    010    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
011    GNU General Public License for more details    011    GNU General Public License for more details.
012                                                   012    
013    You should have received a copy of the GNU     013    You should have received a copy of the GNU General Public License
014    along with this program; if not, write to t    014    along with this program; if not, write to the Free Software
015    Foundation, Inc., 59 Temple Place - Suite 3    015    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
016    USA.                                           016    USA. 
017 */                                                017 */
018                                                   018 
019 #include <sos/kmalloc.h>                          019 #include <sos/kmalloc.h>
020 #include <sos/klibc.h>                            020 #include <sos/klibc.h>
021 #include <sos/assert.h>                           021 #include <sos/assert.h>
022 #include <sos/list.h>                             022 #include <sos/list.h>
023 #include <sos/ksynch.h>                           023 #include <sos/ksynch.h>
024 #include <sos/uaccess.h>                          024 #include <sos/uaccess.h>
025 #include <sos/physmem.h>                          025 #include <sos/physmem.h>
026                                                   026 
027 #include <sos/fs.h>                               027 #include <sos/fs.h>
028 #include <sos/fs_nscache.h>                       028 #include <sos/fs_nscache.h>
029                                                   029 
030 #include "fs_virtfs.h"                            030 #include "fs_virtfs.h"
031                                                   031 
032 /**                                               032 /**
033  * @file fs_virtfs.c                              033  * @file fs_virtfs.c
034  *                                                034  *
035  * All the sos_fs_nodes and their contents are    035  * All the sos_fs_nodes and their contents are stored in kernel
036  * memory. Thus, with "virtfs", the "disk" is     036  * memory. Thus, with "virtfs", the "disk" is actually the kernel
037  * memory. In a sos_fs_node, the storage_locat    037  * memory. In a sos_fs_node, the storage_location field corresponds to
038  * the kernel address of the corresponding str    038  * the kernel address of the corresponding struct sos_fs_node.
039  *                                                039  *
040  * Basic kernel-memory virtual FS. Highly UNDE    040  * Basic kernel-memory virtual FS. Highly UNDER-optimized filesystem:
041  * each time we resize a file, a complete real    041  * each time we resize a file, a complete reallocation is done. This
042  * somehow complicates the file mapping, as we    042  * somehow complicates the file mapping, as we cannot do this anyhow
043  * as long as the file is mapped because the k    043  * as long as the file is mapped because the kernel address of the
044  * file contents must NOT change. For that rea    044  * file contents must NOT change. For that reason, we forbid to resize
045  * a file as soon as it is mapped and the file    045  * a file as soon as it is mapped and the file's contents are aligned
046  * on a page boundary in kernel memory (use of    046  * on a page boundary in kernel memory (use of sos_kmem_vmm_alloc
047  * instead of sos_kmalloc).                       047  * instead of sos_kmalloc).
048  */                                               048  */
049                                                   049 
050                                                   050 
051 /**                                               051 /**
052  * A directory entry, used in virtfs_node of t    052  * A directory entry, used in virtfs_node of type "directory". This is
053  * as simple as a sos_fs_node with a name.        053  * as simple as a sos_fs_node with a name.
054  */                                               054  */
055 struct virtfs_direntry                            055 struct virtfs_direntry
056 {                                                 056 {
057   char * name;                                    057   char * name;
058   struct sos_fs_node * fsnode;                    058   struct sos_fs_node * fsnode;
059                                                   059 
060   /**                                             060   /**
061    * Used by readdir to be resilient against c    061    * Used by readdir to be resilient against creat/mkdir/unlink/rmdir
062    * between 2 successive readdirs. Each time     062    * between 2 successive readdirs. Each time a new child to a node is
063    * allocated, a new "creation_order" is uniq    063    * allocated, a new "creation_order" is uniquely attributed. 64bits
064    * should be large enough.                      064    * should be large enough.
065    */                                             065    */
066   sos_lcount_t creation_order;                    066   sos_lcount_t creation_order;
067                                                   067 
068   struct virtfs_direntry * sibling_prev, * sib    068   struct virtfs_direntry * sibling_prev, * sibling_next;
069 };                                                069 };
070                                                   070 
071                                                   071 
072 /**                                               072 /**
073  * Structure of a FS file or dir for virtfs. V    073  * Structure of a FS file or dir for virtfs. Virtfs only supports
074  * regular files, directories or symbolic link    074  * regular files, directories or symbolic links:
075  *  - regular files correspond to an area in k    075  *  - regular files correspond to an area in kernel memory
076  *  - directories correspond to a list of virt    076  *  - directories correspond to a list of virtfs_direntry
077  *                                                077  *
078  * Structural inheritance of sos_fs_node: "sup    078  * Structural inheritance of sos_fs_node: "super" is the ancestor (in
079  * "OOP" terms). The "super" field might not b    079  * "OOP" terms). The "super" field might not be the first field: from
080  * a sos_fs_node, the corresponding virtfs_nod    080  * a sos_fs_node, the corresponding virtfs_node is given by the
081  * sos_fs_node::custom_data field                 081  * sos_fs_node::custom_data field
082  */                                               082  */
083 struct virtfs_node                                083 struct virtfs_node
084 {                                                 084 {
085   /** The ancestor */                             085   /** The ancestor */
086   struct sos_fs_node super;                       086   struct sos_fs_node super;
087                                                   087 
088   union                                           088   union
089   {                                               089   {
090     /* A file */                                  090     /* A file */
091     struct                                        091     struct
092     {                                             092     {
093       /* Contents of the file */                  093       /* Contents of the file */
094       sos_size_t size;                            094       sos_size_t size;
095       void * data;                                095       void * data;
096                                                   096 
097       /* Yes, the file can be mapped ! */         097       /* Yes, the file can be mapped ! */
098       struct sos_umem_vmm_mapped_resource mapr    098       struct sos_umem_vmm_mapped_resource mapres;
099       sos_count_t num_mappings; /**< Forbids t    099       sos_count_t num_mappings; /**< Forbids the region to be resized
100                                    while it's  !! 100                                    while it's being mapped, because
101                                    woould caus !! 101                                    this woould cause the underlying
102                                    to be moved !! 102                                    data area to be moved (because of
                                                   >> 103                                    the implementation we chose, a new
                                                   >> 104                                    allocation is made each time a file
                                                   >> 105                                    is resized) */
103     } file;                                       106     } file;
104                                                   107 
105     /* A directory */                             108     /* A directory */
106     struct                                        109     struct
107     {                                             110     {
108       /** the children nodes are inserted in F    111       /** the children nodes are inserted in FIFO order. This is
109           important for the readdir function t    112           important for the readdir function to be resilient against
110           mkdir/rmdir/creat/unlink */             113           mkdir/rmdir/creat/unlink */
111       struct virtfs_direntry * list_entries;      114       struct virtfs_direntry * list_entries;
112                                                   115 
113       /** Used by readdir to remember the last    116       /** Used by readdir to remember the last unique "creation order"
114           attributed */                           117           attributed */
115       sos_lcount_t top_creation_order;            118       sos_lcount_t top_creation_order;
116     } dir;                                        119     } dir;
117   }; /* Anonymous union (gcc extension) */        120   }; /* Anonymous union (gcc extension) */
118                                                   121 
119   /* The virtfs nodes are chained */              122   /* The virtfs nodes are chained */
120   struct virtfs_node * prev, * next;              123   struct virtfs_node * prev, * next;
121 };                                                124 };
122                                                   125 
123                                                   126 
124 /**                                               127 /**
125  * A virtfs FS instance                           128  * A virtfs FS instance
126  *                                                129  *
127  * Structural inheritance of sos_fs_manager_in    130  * Structural inheritance of sos_fs_manager_instance: "super" is the
128  * ancestor (in "OOP" terms). The "super" fiel    131  * ancestor (in "OOP" terms). The "super" field might not be the first
129  * field: from a sos_fs_manager_instance, the     132  * field: from a sos_fs_manager_instance, the corresponding
130  * virtfs_instance is given by the                133  * virtfs_instance is given by the
131  * sos_fs_manager_instance::custom_data field     134  * sos_fs_manager_instance::custom_data field
132  */                                               135  */
133 struct virtfs_instance                            136 struct virtfs_instance
134 {                                                 137 {
135   /** Ancestor */                                 138   /** Ancestor */
136   struct sos_fs_manager_instance super;           139   struct sos_fs_manager_instance super;
137                                                   140 
138   /** For the serialization of virtfs "disk" (    141   /** For the serialization of virtfs "disk" (ie kernel memory)
139       accesses */                                 142       accesses */
140   struct sos_kmutex lock;                         143   struct sos_kmutex lock;
141                                                   144 
142   /** The list of virtfs nodes "on disk" (ie i    145   /** The list of virtfs nodes "on disk" (ie in kernel memory) */
143   struct virtfs_node * list_fsnodes;              146   struct virtfs_node * list_fsnodes;
144 };                                                147 };
145                                                   148 
146                                                   149 
147 /** The description of the "Virtual FS" */        150 /** The description of the "Virtual FS" */
148 static struct sos_fs_manager_type virtfs_type;    151 static struct sos_fs_manager_type virtfs_type;
149                                                   152 
150                                                   153 
151 /* ********** Forward declarations */             154 /* ********** Forward declarations */
152 static sos_ret_t virtfs_mount(struct sos_fs_ma    155 static sos_ret_t virtfs_mount(struct sos_fs_manager_type * this,
153                               struct sos_fs_no    156                               struct sos_fs_node * device,
154                               const char * arg    157                               const char * args,
155                               struct sos_fs_ma    158                               struct sos_fs_manager_instance ** mounted_fs);
156                                                   159 
157                                                   160 
158 static sos_ret_t virtfs_umount(struct sos_fs_m    161 static sos_ret_t virtfs_umount(struct sos_fs_manager_type * this,
159                                struct sos_fs_m    162                                struct sos_fs_manager_instance * mounted_fs);
160                                                   163 
161                                                   164 
162 static sos_ret_t virtfs_new_mapping(struct sos    165 static sos_ret_t virtfs_new_mapping(struct sos_umem_vmm_vr *vr);
163                                                   166 
164                                                   167 
165 sos_ret_t sos_fs_virtfs_subsystem_setup()         168 sos_ret_t sos_fs_virtfs_subsystem_setup()
166 {                                                 169 {
167   strzcpy(virtfs_type.name, "virtfs", SOS_FS_M    170   strzcpy(virtfs_type.name, "virtfs", SOS_FS_MANAGER_NAME_MAXLEN);
168   virtfs_type.mount  = virtfs_mount;              171   virtfs_type.mount  = virtfs_mount;
169   virtfs_type.umount = virtfs_umount;             172   virtfs_type.umount = virtfs_umount;
170                                                   173 
171   return sos_fs_register_fs_type(& virtfs_type    174   return sos_fs_register_fs_type(& virtfs_type);
172 }                                                 175 }
173                                                   176 
174                                                   177 
175 /* *******************************************    178 /* ********************************************************
176  * Helper functions                               179  * Helper functions
177  */                                               180  */
178                                                   181 
179                                                   182 
180 /* Helper function to serialize "disk" accesse    183 /* Helper function to serialize "disk" accesses */
181 inline static void virtfs_lock(struct virtfs_n    184 inline static void virtfs_lock(struct virtfs_node *a_node)
182 {                                                 185 {
183   struct virtfs_instance * fs = (struct virtfs    186   struct virtfs_instance * fs = (struct virtfs_instance*)a_node->super.fs->custom_data;
184   sos_kmutex_lock(& fs->lock, NULL);              187   sos_kmutex_lock(& fs->lock, NULL);
185 }                                                 188 }
186                                                   189 
187                                                   190 
188 /* Helper function to serialize "disk" accesse    191 /* Helper function to serialize "disk" accesses */
189 inline static void virtfs_unlock(struct virtfs    192 inline static void virtfs_unlock(struct virtfs_node *a_node)
190 {                                                 193 {
191   struct virtfs_instance * fs = (struct virtfs    194   struct virtfs_instance * fs = (struct virtfs_instance*)a_node->super.fs->custom_data;
192   sos_kmutex_unlock(& fs->lock);                  195   sos_kmutex_unlock(& fs->lock);
193 }                                                 196 }
194                                                   197 
195                                                   198 
196 /* Helper function to resize the given virts n    199 /* Helper function to resize the given virts node (ie kernel memory
197    reallocation) */                               200    reallocation) */
198 static sos_ret_t virtfs_resize(struct virtfs_n    201 static sos_ret_t virtfs_resize(struct virtfs_node *this,
199                                sos_size_t new_    202                                sos_size_t new_size)
200 {                                                 203 {
201   void * new_data = NULL;                         204   void * new_data = NULL;
202                                                   205 
203   if (this->file.size == new_size)                206   if (this->file.size == new_size)
204     return SOS_OK;                                207     return SOS_OK;
205                                                   208 
206   /* Don't allow to resize the region when the    209   /* Don't allow to resize the region when the file is being mapped */
207   if (this->file.num_mappings > 0)                210   if (this->file.num_mappings > 0)
208     return -SOS_EBUSY;                            211     return -SOS_EBUSY;
209                                                   212 
210   if (new_size > 0)                               213   if (new_size > 0)
211     {                                             214     {
212       /* Use kmem_vmm_alloc instead of kmalloc    215       /* Use kmem_vmm_alloc instead of kmalloc to make sure the data
213          WILL be page-aligned (needed by file     216          WILL be page-aligned (needed by file mapping stuff) */
214       sos_ui32_t npages = SOS_PAGE_ALIGN_SUP(n    217       sos_ui32_t npages = SOS_PAGE_ALIGN_SUP(new_size) / SOS_PAGE_SIZE;
215       new_data = (void*)sos_kmem_vmm_alloc(npa    218       new_data = (void*)sos_kmem_vmm_alloc(npages,
216                                            SOS    219                                            SOS_KMEM_VMM_MAP);
217       if (! new_data)                             220       if (! new_data)
218         return -SOS_OK;                           221         return -SOS_OK;
219     }                                             222     }
220                                                   223 
221   /* Copy the data to its new location */         224   /* Copy the data to its new location */
222   if (this->file.size < new_size)                 225   if (this->file.size < new_size)
223     {                                             226     {
224       if (this->file.size > 0)                    227       if (this->file.size > 0)
225         memcpy(new_data, this->file.data, this    228         memcpy(new_data, this->file.data, this->file.size);
226       if (new_size > this->file.size)             229       if (new_size > this->file.size)
227         memset(new_data + this->file.size, 0x0    230         memset(new_data + this->file.size, 0x0,
228                new_size - this->file.size);       231                new_size - this->file.size);
229     }                                             232     }
230   else if (new_size > 0)                          233   else if (new_size > 0)
231     memcpy(new_data, this->file.data, new_size    234     memcpy(new_data, this->file.data, new_size);
232                                                   235 
233   if (this->file.data)                            236   if (this->file.data)
234     sos_kfree((sos_vaddr_t)this->file.data);      237     sos_kfree((sos_vaddr_t)this->file.data);
235   this->file.data = new_data;                     238   this->file.data = new_data;
236   this->file.size = new_size;                     239   this->file.size = new_size;
237                                                   240 
238   return SOS_OK;                                  241   return SOS_OK;
239 }                                                 242 }
240                                                   243 
241                                                   244 
242 /* *******************************************    245 /* ********************************************************
243  * Opened file operations                         246  * Opened file operations
244  */                                               247  */
245                                                   248 
246                                                   249 
247 static sos_ret_t                                  250 static sos_ret_t
248 virtfs_duplicate_opened_file(struct sos_fs_ope    251 virtfs_duplicate_opened_file(struct sos_fs_opened_file *this,
249                              const struct sos_    252                              const struct sos_process  * for_owner,
250                              struct sos_fs_ope    253                              struct sos_fs_opened_file **result)
251 {                                                 254 {
252   *result = (struct sos_fs_opened_file*)          255   *result = (struct sos_fs_opened_file*)
253     sos_kmalloc(sizeof(struct sos_fs_opened_fi    256     sos_kmalloc(sizeof(struct sos_fs_opened_file), 0);
254   if (! *result)                                  257   if (! *result)
255     return -SOS_ENOMEM;                           258     return -SOS_ENOMEM;
256                                                   259 
257   memcpy(*result, this, sizeof(*this));           260   memcpy(*result, this, sizeof(*this));
258   (*result)->owner = for_owner;                   261   (*result)->owner = for_owner;
259   return SOS_OK;                                  262   return SOS_OK;
260 }                                                 263 }
261                                                   264 
262                                                   265 
263 static sos_ret_t                                  266 static sos_ret_t
264 virtfs_seek(struct sos_fs_opened_file *this,      267 virtfs_seek(struct sos_fs_opened_file *this,
265             sos_lsoffset_t offset,                268             sos_lsoffset_t offset,
266             sos_seek_whence_t whence,             269             sos_seek_whence_t whence,
267             /* out */ sos_lsoffset_t * result_    270             /* out */ sos_lsoffset_t * result_position)
268 {                                                 271 {
269   sos_lsoffset_t ref_offs;                        272   sos_lsoffset_t ref_offs;
270   struct virtfs_node * virtfsnode;                273   struct virtfs_node * virtfsnode;
271                                                   274 
272   virtfsnode = (struct virtfs_node*)              275   virtfsnode = (struct virtfs_node*)
273     sos_fs_nscache_get_fs_node(this->direntry)    276     sos_fs_nscache_get_fs_node(this->direntry)->custom_data;
274                                                   277 
275   if ( (virtfsnode->super.type != SOS_FS_NODE_    278   if ( (virtfsnode->super.type != SOS_FS_NODE_REGULAR_FILE)
276        && (virtfsnode->super.type != SOS_FS_NO    279        && (virtfsnode->super.type != SOS_FS_NODE_SYMLINK))
277     return -SOS_ENOSUP;                           280     return -SOS_ENOSUP;
278                                                   281 
279   *result_position = this->position;              282   *result_position = this->position;
280   switch (whence)                                 283   switch (whence)
281     {                                             284     {
282     case SOS_SEEK_SET:                            285     case SOS_SEEK_SET:
283       ref_offs = 0;                               286       ref_offs = 0;
284       break;                                      287       break;
285                                                   288 
286     case SOS_SEEK_CUR:                            289     case SOS_SEEK_CUR:
287       ref_offs = this->position;                  290       ref_offs = this->position;
288       break;                                      291       break;
289                                                   292 
290     case SOS_SEEK_END:                            293     case SOS_SEEK_END:
291       ref_offs = virtfsnode->file.size;           294       ref_offs = virtfsnode->file.size;
292       break;                                      295       break;
293                                                   296 
294     default:                                      297     default:
295       return -SOS_EINVAL;                         298       return -SOS_EINVAL;
296     }                                             299     }
297                                                   300 
298   if (offset < -ref_offs)                         301   if (offset < -ref_offs)
299     return -SOS_EINVAL;                           302     return -SOS_EINVAL;
300                                                   303   
301   this->position = ref_offs + offset;             304   this->position = ref_offs + offset;
302   *result_position = this->position;              305   *result_position = this->position;
303   return SOS_OK;                                  306   return SOS_OK;
304 }                                                 307 }
305                                                   308 
306                                                   309 
307 static sos_ret_t virtfs_read(struct sos_fs_ope    310 static sos_ret_t virtfs_read(struct sos_fs_opened_file *this,
308                              sos_uaddr_t dest_    311                              sos_uaddr_t dest_buf,
309                              sos_size_t * /* i    312                              sos_size_t * /* in/out */len)
310 {                                                 313 {
311   sos_ret_t retval;                               314   sos_ret_t retval;
312   struct virtfs_node * virtfsnode;                315   struct virtfs_node * virtfsnode;
313                                                   316 
314   virtfsnode = (struct virtfs_node*)              317   virtfsnode = (struct virtfs_node*)
315     sos_fs_nscache_get_fs_node(this->direntry)    318     sos_fs_nscache_get_fs_node(this->direntry)->custom_data;
316                                                   319 
317   if ( (virtfsnode->super.type != SOS_FS_NODE_    320   if ( (virtfsnode->super.type != SOS_FS_NODE_REGULAR_FILE)
318        && (virtfsnode->super.type != SOS_FS_NO    321        && (virtfsnode->super.type != SOS_FS_NODE_SYMLINK))
319     return -SOS_ENOSUP;                           322     return -SOS_ENOSUP;
320                                                   323 
321   if (this->position >= virtfsnode->file.size)    324   if (this->position >= virtfsnode->file.size)
322     {                                             325     {
323       *len = 0;                                   326       *len = 0;
324       return SOS_OK;                              327       return SOS_OK;
325     }                                             328     }
326                                                   329 
327   virtfs_lock(virtfsnode);                        330   virtfs_lock(virtfsnode);
328                                                   331 
329   if (this->position + *len >= virtfsnode->fil    332   if (this->position + *len >= virtfsnode->file.size)
330     *len = virtfsnode->file.size - this->posit    333     *len = virtfsnode->file.size - this->position;
331                                                   334 
332   retval = sos_memcpy_to_user(dest_buf,           335   retval = sos_memcpy_to_user(dest_buf,
333                               ((sos_vaddr_t)vi    336                               ((sos_vaddr_t)virtfsnode->file.data)
334                               + this->position    337                               + this->position,
335                               *len);              338                               *len);
336   if (retval < 0)                                 339   if (retval < 0)
337     {                                             340     {
338       virtfs_unlock(virtfsnode);                  341       virtfs_unlock(virtfsnode);
339       return retval;                              342       return retval;
340     }                                             343     }
341                                                   344 
342   this->position += retval;                       345   this->position += retval;
343   *len = retval;                                  346   *len = retval;
344                                                   347 
345   virtfs_unlock(virtfsnode);                      348   virtfs_unlock(virtfsnode);
346                                                   349 
347   return SOS_OK;                                  350   return SOS_OK;
348 }                                                 351 }
349                                                   352 
350                                                   353 
351 static sos_ret_t virtfs_write(struct sos_fs_op    354 static sos_ret_t virtfs_write(struct sos_fs_opened_file *this,
352                              sos_uaddr_t src_b    355                              sos_uaddr_t src_buf,
353                              sos_size_t * /* i    356                              sos_size_t * /* in/out */len)
354 {                                                 357 {
355   sos_ret_t retval;                               358   sos_ret_t retval;
356   struct virtfs_node * virtfsnode;                359   struct virtfs_node * virtfsnode;
357                                                   360 
358   virtfsnode = (struct virtfs_node*)              361   virtfsnode = (struct virtfs_node*)
359     sos_fs_nscache_get_fs_node(this->direntry)    362     sos_fs_nscache_get_fs_node(this->direntry)->custom_data;
360                                                   363 
361   if ( (virtfsnode->super.type != SOS_FS_NODE_    364   if ( (virtfsnode->super.type != SOS_FS_NODE_REGULAR_FILE)
362        && (virtfsnode->super.type != SOS_FS_NO    365        && (virtfsnode->super.type != SOS_FS_NODE_SYMLINK))
363     return -SOS_ENOSUP;                           366     return -SOS_ENOSUP;
364                                                   367 
365   virtfs_lock(virtfsnode);                        368   virtfs_lock(virtfsnode);
366   if (this->position + *len >= virtfsnode->fil    369   if (this->position + *len >= virtfsnode->file.size)
367     {                                             370     {
368       /* Try to resize if needed */               371       /* Try to resize if needed */
369       if (SOS_OK != virtfs_resize(virtfsnode,     372       if (SOS_OK != virtfs_resize(virtfsnode, this->position + *len))
370         *len = virtfsnode->file.size - this->p    373         *len = virtfsnode->file.size - this->position;
371     }                                             374     }
372                                                   375 
373   retval = sos_memcpy_from_user(((sos_vaddr_t)    376   retval = sos_memcpy_from_user(((sos_vaddr_t)virtfsnode->file.data)
374                                   + this->posi    377                                   + this->position,
375                                 src_buf,          378                                 src_buf,
376                                 *len);            379                                 *len);
377   if (retval < 0)                                 380   if (retval < 0)
378     {                                             381     {
379       virtfs_unlock(virtfsnode);                  382       virtfs_unlock(virtfsnode);
380       return retval;                              383       return retval;
381     }                                             384     }
382                                                   385 
383   this->position += retval;                       386   this->position += retval;
384   *len = retval;                                  387   *len = retval;
385                                                   388 
386   virtfs_unlock(virtfsnode);                      389   virtfs_unlock(virtfsnode);
387                                                   390 
388   return SOS_OK;                                  391   return SOS_OK;
389 }                                                 392 }
390                                                   393 
391                                                   394 
392 static sos_ret_t virtfs_mmap(struct sos_fs_ope    395 static sos_ret_t virtfs_mmap(struct sos_fs_opened_file *this,
393                              sos_uaddr_t *uadd    396                              sos_uaddr_t *uaddr, sos_size_t size,
394                              sos_ui32_t access    397                              sos_ui32_t access_rights,
395                              sos_ui32_t flags,    398                              sos_ui32_t flags,
396                              sos_luoffset_t of    399                              sos_luoffset_t offset)
397 {                                                 400 {
398   struct virtfs_node * virtfsnode;                401   struct virtfs_node * virtfsnode;
399                                                   402 
400   virtfsnode = (struct virtfs_node*)              403   virtfsnode = (struct virtfs_node*)
401     sos_fs_nscache_get_fs_node(this->direntry)    404     sos_fs_nscache_get_fs_node(this->direntry)->custom_data;
402                                                   405 
403   if (virtfsnode->super.type != SOS_FS_NODE_RE    406   if (virtfsnode->super.type != SOS_FS_NODE_REGULAR_FILE)
404     return -SOS_ENOSUP;                           407     return -SOS_ENOSUP;
405                                                   408 
406   return sos_umem_vmm_map(sos_process_get_addr    409   return sos_umem_vmm_map(sos_process_get_address_space(this->owner),
407                           uaddr, size, access_    410                           uaddr, size, access_rights,
408                           flags, & virtfsnode-    411                           flags, & virtfsnode->file.mapres, offset);
409 }                                                 412 }
410                                                   413 
411                                                   414 
412 static sos_ret_t virtfs_readdir(struct sos_fs_    415 static sos_ret_t virtfs_readdir(struct sos_fs_opened_file *this,
413                                 struct sos_fs_    416                                 struct sos_fs_dirent * result)
414 {                                                 417 {
415   /* For directories, "position" indicates the    418   /* For directories, "position" indicates the "creation_order" of the
416      last readdir operation, and "custom_data"    419      last readdir operation, and "custom_data" indicates the address
417      of the last directory entry */               420      of the last directory entry */
418                                                   421 
419   struct virtfs_direntry * direntry, * next_di    422   struct virtfs_direntry * direntry, * next_direntry;
420   struct virtfs_node * virtfsnode;                423   struct virtfs_node * virtfsnode;
421   int nb;                                         424   int nb;
422                                                   425 
423   virtfsnode = (struct virtfs_node*)              426   virtfsnode = (struct virtfs_node*)
424     sos_fs_nscache_get_fs_node(this->direntry)    427     sos_fs_nscache_get_fs_node(this->direntry)->custom_data;
425   next_direntry = NULL;                           428   next_direntry = NULL;
426                                                   429 
427   /* If the "generation" of the node did not c    430   /* If the "generation" of the node did not change, the next direntry
428      is the next in the list. We can safely do    431      is the next in the list. We can safely do this because the list
429      of direntries is sorted in increasing cre    432      of direntries is sorted in increasing creation_order. */
430   if ((this->generation == virtfsnode->super.g    433   if ((this->generation == virtfsnode->super.generation)
431       && (this->custom_data != NULL))             434       && (this->custom_data != NULL))
432     {                                             435     {
433       direntry = (struct virtfs_direntry*)this    436       direntry = (struct virtfs_direntry*)this->custom_data;
434       next_direntry = direntry->sibling_next;     437       next_direntry = direntry->sibling_next;
435                                                   438 
436       /* Did we go past the end of the list ?     439       /* Did we go past the end of the list ? */
437       if (next_direntry == list_get_head_named    440       if (next_direntry == list_get_head_named(virtfsnode->dir.list_entries,
438                                                   441                                                sibling_prev, sibling_next))
439         next_direntry = NULL;                     442         next_direntry = NULL;
440     }                                             443     }
441   else                                            444   else
442     /* Otherwise we have to lookup the next en    445     /* Otherwise we have to lookup the next entry manually */
443     {                                             446     {
444       /* Lookup the entry that has next creati    447       /* Lookup the entry that has next creation_order */
445       next_direntry = NULL;                       448       next_direntry = NULL;
446       list_foreach_forward_named(virtfsnode->d    449       list_foreach_forward_named(virtfsnode->dir.list_entries,
447                                  direntry, nb,    450                                  direntry, nb,
448                                  sibling_prev,    451                                  sibling_prev, sibling_next)
449         {                                         452         {
450           if (direntry->creation_order <= this    453           if (direntry->creation_order <= this->position)
451             continue;                             454             continue;
452                                                   455 
453           if (! next_direntry)                    456           if (! next_direntry)
454             {                                     457             {
455               next_direntry = direntry;           458               next_direntry = direntry;
456               continue;                           459               continue;
457             }                                     460             }
458                                                   461           
459           if (direntry->creation_order < next_    462           if (direntry->creation_order < next_direntry->creation_order)
460             next_direntry = direntry;             463             next_direntry = direntry;
461         }                                         464         }
462     }                                             465     }
463                                                   466 
464   if (! next_direntry)                            467   if (! next_direntry)
465     {                                             468     {
466       this->custom_data = NULL;                   469       this->custom_data = NULL;
467       this->position    = 0;                      470       this->position    = 0;
468       return -SOS_ENOENT;                         471       return -SOS_ENOENT;
469     }                                             472     }
470                                                   473 
471   /* Update the result */                         474   /* Update the result */
472   result->storage_location  = ((sos_vaddr_t)ne    475   result->storage_location  = ((sos_vaddr_t)next_direntry->fsnode);
473   result->offset_in_dirfile = next_direntry->c    476   result->offset_in_dirfile = next_direntry->creation_order;
474   result->type              = next_direntry->f    477   result->type              = next_direntry->fsnode->type;
475   result->namelen           = strnlen(next_dir    478   result->namelen           = strnlen(next_direntry->name,
476                                       SOS_FS_D    479                                       SOS_FS_DIRENT_NAME_MAXLEN);
477   strzcpy(result->name, next_direntry->name, S    480   strzcpy(result->name, next_direntry->name, SOS_FS_DIRENT_NAME_MAXLEN);
478                                                   481 
479   /* Update the custom data */                    482   /* Update the custom data */
480   this->position    = next_direntry->creation_    483   this->position    = next_direntry->creation_order;
481   this->custom_data = next_direntry;              484   this->custom_data = next_direntry;
482                                                   485 
483   return SOS_OK;                                  486   return SOS_OK;
484 }                                                 487 }
485                                                   488 
486                                                   489 
487 static struct sos_fs_ops_opened_file virtfs_op    490 static struct sos_fs_ops_opened_file virtfs_ops_opened_file =
488   (struct sos_fs_ops_opened_file){                491   (struct sos_fs_ops_opened_file){
489     .seek     = virtfs_seek,                      492     .seek     = virtfs_seek,
490     .read     = virtfs_read,                      493     .read     = virtfs_read,
491     .write    = virtfs_write,                     494     .write    = virtfs_write,
492     .mmap     = virtfs_mmap                       495     .mmap     = virtfs_mmap
493   };                                              496   };
494                                                   497 
495                                                   498 
496 static struct sos_fs_ops_opened_dir virtfs_ops    499 static struct sos_fs_ops_opened_dir virtfs_ops_opened_dir =
497   (struct sos_fs_ops_opened_dir){                 500   (struct sos_fs_ops_opened_dir){
498     .readdir  = virtfs_readdir                    501     .readdir  = virtfs_readdir
499   };                                              502   };
500                                                   503 
501                                                   504 
502 /* *******************************************    505 /* ********************************************************
503  * FS node operations                             506  * FS node operations
504  */                                               507  */
505                                                   508 
506 static sos_ret_t virtfs_stat_node(struct sos_f    509 static sos_ret_t virtfs_stat_node(struct sos_fs_node * this,
507                                   struct sos_f    510                                   struct sos_fs_stat * result)
508 {                                                 511 {
509   struct virtfs_node * virtfsnode = (struct vi    512   struct virtfs_node * virtfsnode = (struct virtfs_node*)this->custom_data;
510                                                   513 
511   /* Establish the major/minor fields */          514   /* Establish the major/minor fields */
512   result->st_rdev.device_class    = 0;            515   result->st_rdev.device_class    = 0;
513   result->st_rdev.device_instance = 0;            516   result->st_rdev.device_instance = 0;
514   if (this->type == SOS_FS_NODE_DEVICE_CHAR)   !! 517   if ( (this->type == SOS_FS_NODE_DEVICE_CHAR)
                                                   >> 518        || (this->type == SOS_FS_NODE_DEVICE_BLOCK) )
515     {                                             519     {
516       /* If the current node is a special devi    520       /* If the current node is a special device: get the major/minor
517          directly from it */                      521          directly from it */
518       result->st_rdev.device_class    = this->    522       result->st_rdev.device_class    = this->dev_id.device_class;
519       result->st_rdev.device_instance = this->    523       result->st_rdev.device_instance = this->dev_id.device_instance;
520     }                                             524     }
521   else                                            525   else
522     {                                             526     {
523       /* Otherwise, retrieve it from the devic    527       /* Otherwise, retrieve it from the device that it is mounted
524          on (might not exist...) */               528          on (might not exist...) */
525       struct sos_fs_node * rootdev = this->fs-    529       struct sos_fs_node * rootdev = this->fs->device;
526       if (rootdev)                                530       if (rootdev)
527         {                                         531         {
528           result->st_rdev.device_class    = ro    532           result->st_rdev.device_class    = rootdev->dev_id.device_class;
529           result->st_rdev.device_instance = ro    533           result->st_rdev.device_instance = rootdev->dev_id.device_instance;
530         }                                         534         }
531     }                                             535     }
532                                                   536 
533   result->st_type                 = this->type    537   result->st_type                 = this->type;
534   result->st_storage_location     = this->stor    538   result->st_storage_location     = this->storage_location;
535   result->st_access_rights        = this->acce    539   result->st_access_rights        = this->access_rights;
536   result->st_nlink                = this->ondi    540   result->st_nlink                = this->ondisk_lnk_cnt;
537   if (this->type == SOS_FS_NODE_REGULAR_FILE)     541   if (this->type == SOS_FS_NODE_REGULAR_FILE)
538     result->st_size               = virtfsnode    542     result->st_size               = virtfsnode->file.size;
539   else                                            543   else
540     result->st_size               = 0;            544     result->st_size               = 0;
541   return SOS_OK;                                  545   return SOS_OK;
542 }                                                 546 }
543                                                   547 
544                                                   548 
545 static sos_ret_t virtfs_truncate(struct sos_fs    549 static sos_ret_t virtfs_truncate(struct sos_fs_node *this,
546                                  sos_lsoffset_    550                                  sos_lsoffset_t length)
547 {                                                 551 {
548   sos_ret_t retval;                               552   sos_ret_t retval;
549   struct virtfs_node * virtfsnode;                553   struct virtfs_node * virtfsnode;
550                                                   554 
551   virtfsnode = (struct virtfs_node*) this->cus    555   virtfsnode = (struct virtfs_node*) this->custom_data;
552                                                   556 
553   if ( (virtfsnode->super.type != SOS_FS_NODE_    557   if ( (virtfsnode->super.type != SOS_FS_NODE_REGULAR_FILE)
554        && (virtfsnode->super.type != SOS_FS_NO    558        && (virtfsnode->super.type != SOS_FS_NODE_SYMLINK))
555     return -SOS_ENOSUP;                           559     return -SOS_ENOSUP;
556                                                   560   
557   virtfs_lock(virtfsnode);                        561   virtfs_lock(virtfsnode);
558   retval = virtfs_resize(virtfsnode, length);     562   retval = virtfs_resize(virtfsnode, length);
559   virtfs_unlock(virtfsnode);                      563   virtfs_unlock(virtfsnode);
560                                                   564 
561   return retval;                                  565   return retval;
562 }                                                 566 }
563                                                   567 
564                                                   568 
565 static sos_ret_t virtfs_sync_node(struct sos_f    569 static sos_ret_t virtfs_sync_node(struct sos_fs_node *this)
566 {                                                 570 {
567   /* No backing store for virtfs */               571   /* No backing store for virtfs */
568   return SOS_OK;                                  572   return SOS_OK;
569 }                                                 573 }
570                                                   574 
571                                                   575 
572 static sos_ret_t virtfs_chmod_node(struct sos_    576 static sos_ret_t virtfs_chmod_node(struct sos_fs_node * this,
573                                    sos_ui32_t     577                                    sos_ui32_t access_rights)
574 {                                                 578 {
575   this->access_rights = access_rights;            579   this->access_rights = access_rights;
576   return SOS_OK;                                  580   return SOS_OK;
577 }                                                 581 }
578                                                   582 
579                                                   583 
580 /** Callback when nothing (in particular no so    584 /** Callback when nothing (in particular no sos_fs_nscache_node) make
581     reference to the node */                      585     reference to the node */
582 static sos_ret_t virtfs_node_destructor(struct    586 static sos_ret_t virtfs_node_destructor(struct sos_fs_node * this)
583 {                                                 587 {
584   /* This callback is called only when the fsn    588   /* This callback is called only when the fsnode is not needed
585      anymore by any process or by the kernel.     589      anymore by any process or by the kernel. But the node must remain
586      stored "on disk" as long as the FS is mou    590      stored "on disk" as long as the FS is mounted AND the node is
587      still "on disk" */                           591      still "on disk" */
588   if (this->ondisk_lnk_cnt <= 0)                  592   if (this->ondisk_lnk_cnt <= 0)
589     {                                             593     {
590       struct virtfs_instance * virtfs = (struc    594       struct virtfs_instance * virtfs = (struct virtfs_instance*)this->fs->custom_data;
591       struct virtfs_node * virtfsnode = (struc    595       struct virtfs_node * virtfsnode = (struct virtfs_node*)this->custom_data;
592                                                   596 
593       list_delete(virtfs->list_fsnodes, virtfs    597       list_delete(virtfs->list_fsnodes, virtfsnode);
594       sos_kfree((sos_vaddr_t) this->custom_dat    598       sos_kfree((sos_vaddr_t) this->custom_data);
595     }                                             599     }
596                                                   600 
597   return SOS_OK;                                  601   return SOS_OK;
598 }                                                 602 }
599                                                   603 
600                                                   604 
601 static struct sos_fs_node_ops_file virtfs_ops_    605 static struct sos_fs_node_ops_file virtfs_ops_file =
602   (struct sos_fs_node_ops_file){                  606   (struct sos_fs_node_ops_file){
603     .truncate = virtfs_truncate,                  607     .truncate = virtfs_truncate,
604     .stat     = virtfs_stat_node,                 608     .stat     = virtfs_stat_node,
605     .chmod    = virtfs_chmod_node              !! 609     .chmod    = virtfs_chmod_node,
                                                   >> 610     .sync     = virtfs_sync_node
606   };                                              611   };
607                                                   612 
608                                                   613 
609 static sos_ret_t virtfs_new_opened_file(struct    614 static sos_ret_t virtfs_new_opened_file(struct sos_fs_node * this,
610                                         const     615                                         const struct sos_process * owner,
611                                         sos_ui    616                                         sos_ui32_t open_flags,
612                                         struct    617                                         struct sos_fs_opened_file ** result_of)
613 {                                                 618 {
614   struct sos_fs_opened_file * of                  619   struct sos_fs_opened_file * of
615     = (struct sos_fs_opened_file*)sos_kmalloc(    620     = (struct sos_fs_opened_file*)sos_kmalloc(sizeof(*of), 0);
616   if (! of)                                       621   if (! of)
617     return -SOS_ENOMEM;                           622     return -SOS_ENOMEM;
618                                                   623 
619   memset(of, 0x0, sizeof(*of));                   624   memset(of, 0x0, sizeof(*of));
620   of->owner      = owner;                         625   of->owner      = owner;
621   of->duplicate  = virtfs_duplicate_opened_fil    626   of->duplicate  = virtfs_duplicate_opened_file;
622   of->open_flags = open_flags;                    627   of->open_flags = open_flags;
623   of->ops_file   = & virtfs_ops_opened_file;      628   of->ops_file   = & virtfs_ops_opened_file;
624   if (this->type == SOS_FS_NODE_DIRECTORY)        629   if (this->type == SOS_FS_NODE_DIRECTORY)
625     of->ops_dir  = & virtfs_ops_opened_dir;       630     of->ops_dir  = & virtfs_ops_opened_dir;
626                                                   631 
627   *result_of = of;                                632   *result_of = of;
628   return SOS_OK;                                  633   return SOS_OK;
629 }                                                 634 }
630                                                   635 
631                                                   636 
632 static sos_ret_t virtfs_close_opened_file(stru    637 static sos_ret_t virtfs_close_opened_file(struct sos_fs_node * this,
633                                           stru    638                                           struct sos_fs_opened_file * of)
634 {                                                 639 {
635   sos_kfree((sos_vaddr_t)of);                     640   sos_kfree((sos_vaddr_t)of);
636   return SOS_OK;                                  641   return SOS_OK;
637 }                                                 642 }
638                                                   643 
639                                                   644 
640 static sos_ret_t virtfs_symlink_expand(struct     645 static sos_ret_t virtfs_symlink_expand(struct sos_fs_node *this,
641                                        char co    646                                        char const  ** target,
642                                        sos_siz    647                                        sos_size_t * target_len)
643 {                                                 648 {
644   struct virtfs_node * virtfsnode = (struct vi    649   struct virtfs_node * virtfsnode = (struct virtfs_node*)this->custom_data;
645                                                   650   
646   *target = virtfsnode->file.data;                651   *target = virtfsnode->file.data;
647   *target_len = virtfsnode->file.size;            652   *target_len = virtfsnode->file.size;
648                                                   653 
649   return SOS_OK;                                  654   return SOS_OK;
650 }                                                 655 }
651                                                   656 
652                                                   657 
653 static struct sos_fs_node_ops_symlink virtfs_o    658 static struct sos_fs_node_ops_symlink virtfs_ops_symlink
654   = (struct sos_fs_node_ops_symlink){             659   = (struct sos_fs_node_ops_symlink){
655     .expand = virtfs_symlink_expand               660     .expand = virtfs_symlink_expand
656   };                                              661   };
657                                                   662 
658                                                   663 
659 static sos_ret_t virtfs_dir_lookup(struct sos_    664 static sos_ret_t virtfs_dir_lookup(struct sos_fs_node *this,
660                                    const char     665                                    const char * name, sos_ui16_t namelen,
661                                    sos_ui64_t     666                                    sos_ui64_t * result_storage_location)
662 {                                                 667 {
663   struct virtfs_node * virtfsnode = (struct vi    668   struct virtfs_node * virtfsnode = (struct virtfs_node*)this->custom_data;
664   struct virtfs_direntry * direntry;              669   struct virtfs_direntry * direntry;
665   int nbentries;                                  670   int nbentries;
666                                                   671   
667   list_foreach_forward_named(virtfsnode->dir.l    672   list_foreach_forward_named(virtfsnode->dir.list_entries,
668                              direntry, nbentri    673                              direntry, nbentries,
669                              sibling_prev, sib    674                              sibling_prev, sibling_next)
670     {                                             675     {
671       if (!memcmp(name, direntry->name, namele    676       if (!memcmp(name, direntry->name, namelen) && !direntry->name[namelen])
672         {                                         677         {
673           *result_storage_location = direntry-    678           *result_storage_location = direntry->fsnode->storage_location;
674           return SOS_OK;                          679           return SOS_OK;
675         }                                         680         }
676     }                                             681     }
677                                                   682 
678   return -SOS_ENOENT;                             683   return -SOS_ENOENT;
679 }                                                 684 }
680                                                   685 
681                                                   686 
682 static sos_ret_t virtfs_link(struct sos_fs_nod    687 static sos_ret_t virtfs_link(struct sos_fs_node *this,
683                              const struct sos_    688                              const struct sos_process *actor,
684                              const char * entr    689                              const char * entry_name, sos_ui16_t entry_namelen,
685                              struct sos_fs_nod    690                              struct sos_fs_node * node)
686 {                                                 691 {
687   struct virtfs_node * parent = (struct virtfs    692   struct virtfs_node * parent = (struct virtfs_node*)this->custom_data;
688   struct virtfs_direntry * direntry;              693   struct virtfs_direntry * direntry;
689                                                   694 
690   direntry = (struct virtfs_direntry*)sos_kmal    695   direntry = (struct virtfs_direntry*)sos_kmalloc(sizeof(*direntry), 0);
691   if (! direntry)                                 696   if (! direntry)
692     return -SOS_ENOMEM;                           697     return -SOS_ENOMEM;
693                                                   698 
694   direntry->name = (char*)sos_kmalloc(entry_na    699   direntry->name = (char*)sos_kmalloc(entry_namelen + 1, 0);
695   if (! direntry->name)                           700   if (! direntry->name)
696     {                                             701     {
697       sos_kfree((sos_vaddr_t)direntry->name);     702       sos_kfree((sos_vaddr_t)direntry->name);
698       return -SOS_ENOMEM;                         703       return -SOS_ENOMEM;
699     }                                             704     }
700                                                   705 
701   memcpy(direntry->name, entry_name, entry_nam    706   memcpy(direntry->name, entry_name, entry_namelen);
702   direntry->name[entry_namelen] = '\0';           707   direntry->name[entry_namelen] = '\0';
703                                                   708 
704   direntry->fsnode = node;                        709   direntry->fsnode = node;
705   node->ondisk_lnk_cnt ++;                        710   node->ondisk_lnk_cnt ++;
706   this->ondisk_lnk_cnt ++;                        711   this->ondisk_lnk_cnt ++;
707   list_add_tail_named(parent->dir.list_entries    712   list_add_tail_named(parent->dir.list_entries, direntry,
708                       sibling_prev, sibling_ne    713                       sibling_prev, sibling_next);
709                                                   714 
710   /* Update the index of the new entry in orde    715   /* Update the index of the new entry in order for the next readdirs
711      to fetch this new entry */                   716      to fetch this new entry */
712   parent->dir.top_creation_order ++;              717   parent->dir.top_creation_order ++;
713   direntry->creation_order = parent->dir.top_c    718   direntry->creation_order = parent->dir.top_creation_order;
714                                                   719 
715   return SOS_OK;                                  720   return SOS_OK;
716 }                                                 721 }
717                                                   722 
718                                                   723 
719 static sos_ret_t                                  724 static sos_ret_t
720 virtfs_unlink(struct sos_fs_node *this,           725 virtfs_unlink(struct sos_fs_node *this,
721               const struct sos_process *actor,    726               const struct sos_process *actor,
722               const char * entry_name, sos_ui1    727               const char * entry_name, sos_ui16_t entry_namelen)
723 {                                                 728 {
724   struct virtfs_node * parent = (struct virtfs    729   struct virtfs_node * parent = (struct virtfs_node*)this->custom_data;
725   struct virtfs_direntry * direntry;              730   struct virtfs_direntry * direntry;
726   int nbentries;                                  731   int nbentries;
727                                                   732   
728   list_foreach_forward_named(parent->dir.list_    733   list_foreach_forward_named(parent->dir.list_entries,
729                              direntry, nbentri    734                              direntry, nbentries,
730                              sibling_prev, sib    735                              sibling_prev, sibling_next)
731     {                                             736     {
732       if (!memcmp(entry_name, direntry->name,     737       if (!memcmp(entry_name, direntry->name, entry_namelen)
733           && !direntry->name[entry_namelen])      738           && !direntry->name[entry_namelen])
734         {                                         739         {
735           list_delete_named(parent->dir.list_e    740           list_delete_named(parent->dir.list_entries, direntry,
736                             sibling_prev, sibl    741                             sibling_prev, sibling_next);
737           direntry->fsnode->ondisk_lnk_cnt --;    742           direntry->fsnode->ondisk_lnk_cnt --;
738           this->ondisk_lnk_cnt --;                743           this->ondisk_lnk_cnt --;
739           sos_kfree((sos_vaddr_t)direntry);       744           sos_kfree((sos_vaddr_t)direntry);
740           return SOS_OK;                          745           return SOS_OK;
741         }                                         746         }
742     }                                             747     }
743                                                   748 
744   return -SOS_ENOENT;                             749   return -SOS_ENOENT;
745 }                                                 750 }
746                                                   751 
747                                                   752 
748 static struct sos_fs_node_ops_dir virtfs_ops_d    753 static struct sos_fs_node_ops_dir virtfs_ops_dir
749   = (struct sos_fs_node_ops_dir){                 754   = (struct sos_fs_node_ops_dir){
750     .lookup = virtfs_dir_lookup,                  755     .lookup = virtfs_dir_lookup,
751     .link   = virtfs_link,                        756     .link   = virtfs_link,
752     .unlink = virtfs_unlink                       757     .unlink = virtfs_unlink
753   };                                              758   };
754                                                   759 
755                                                   760 
756 /* *******************************************    761 /* ********************************************************
757  * FS instance operations                         762  * FS instance operations
758  */                                               763  */
759                                                   764 
760                                                   765 
761 /** Simulate the access to a node located on d    766 /** Simulate the access to a node located on disk. In virtfs, the
762     "disk" is directly the kernel memory, so t    767     "disk" is directly the kernel memory, so the
763     "sos_fs_node::storage_location field corre    768     "sos_fs_node::storage_location field corresponds to a kernel
764     address */                                    769     address */
765 static sos_ret_t                                  770 static sos_ret_t
766 virtfs_fetch_node_from_disk(struct sos_fs_mana    771 virtfs_fetch_node_from_disk(struct sos_fs_manager_instance * this,
767                             sos_ui64_t storage    772                             sos_ui64_t storage_location,
768                             struct sos_fs_node    773                             struct sos_fs_node ** result)
769 {                                                 774 {
770   /* The "disk" is simply the ram */              775   /* The "disk" is simply the ram */
771   struct virtfs_node * virtfsnode;                776   struct virtfs_node * virtfsnode;
772                                                   777 
773   virtfsnode = (struct virtfs_node *)((sos_vad    778   virtfsnode = (struct virtfs_node *)((sos_vaddr_t)storage_location);
774   *result = & virtfsnode->super;                  779   *result = & virtfsnode->super;
775                                                   780 
776   return SOS_OK;                                  781   return SOS_OK;
777 }                                                 782 }
778                                                   783 
779                                                   784 
780 static sos_ret_t                                  785 static sos_ret_t
781 virtfs_allocate_new_node(struct sos_fs_manager    786 virtfs_allocate_new_node(struct sos_fs_manager_instance * this,
782                          sos_fs_node_type_t ty    787                          sos_fs_node_type_t type,
783                          const struct sos_proc    788                          const struct sos_process * creator,
784                          sos_ui32_t access_rig    789                          sos_ui32_t access_rights,
785                          sos_ui32_t flags,        790                          sos_ui32_t flags,
786                          struct sos_fs_node **    791                          struct sos_fs_node ** result)
787 {                                                 792 {
788   struct virtfs_node * virtfsnode;                793   struct virtfs_node * virtfsnode;
789                                                   794 
790   /* Allow only DIRs, FILEs or special device     795   /* Allow only DIRs, FILEs or special device files */
791   if ((type != SOS_FS_NODE_REGULAR_FILE)          796   if ((type != SOS_FS_NODE_REGULAR_FILE)
792       && (type != SOS_FS_NODE_SYMLINK)            797       && (type != SOS_FS_NODE_SYMLINK)
793       && (type != SOS_FS_NODE_DIRECTORY)          798       && (type != SOS_FS_NODE_DIRECTORY)
794       && (type != SOS_FS_NODE_DEVICE_CHAR))    !! 799       && (type != SOS_FS_NODE_DEVICE_CHAR)
                                                   >> 800       && (type != SOS_FS_NODE_DEVICE_BLOCK))
795     return -SOS_ENOSUP;                           801     return -SOS_ENOSUP;
796                                                   802 
797   virtfsnode = (struct virtfs_node*) sos_kmall    803   virtfsnode = (struct virtfs_node*) sos_kmalloc(sizeof(*virtfsnode), 0);
798   if (! virtfsnode)                               804   if (! virtfsnode)
799     return -SOS_ENOMEM;                           805     return -SOS_ENOMEM;
800                                                   806 
801   memset(virtfsnode, 0x0, sizeof(*virtfsnode))    807   memset(virtfsnode, 0x0, sizeof(*virtfsnode));
802   *result = & virtfsnode->super;                  808   *result = & virtfsnode->super;
803                                                   809 
804   /* Initialize "file" */                         810   /* Initialize "file" */
805   (*result)->inmem_ref_cnt     = 1;               811   (*result)->inmem_ref_cnt     = 1;
806   (*result)->custom_data       = virtfsnode;      812   (*result)->custom_data       = virtfsnode;
807   (*result)->storage_location  = (sos_ui64_t)(    813   (*result)->storage_location  = (sos_ui64_t)((sos_vaddr_t)virtfsnode);
808   (*result)->type              = type;            814   (*result)->type              = type;
809   (*result)->access_rights     = access_rights    815   (*result)->access_rights     = access_rights;
810   (*result)->destructor        = virtfs_node_d    816   (*result)->destructor        = virtfs_node_destructor;
811   (*result)->ops_file          = & virtfs_ops_    817   (*result)->ops_file          = & virtfs_ops_file;
812                                                   818 
813   /* The "file" functions are defined by the F    819   /* The "file" functions are defined by the FS code only for
814      non-special device files */                  820      non-special device files */
815   if (type != SOS_FS_NODE_DEVICE_CHAR)         !! 821   if ((type != SOS_FS_NODE_DEVICE_CHAR)
                                                   >> 822       && (type != SOS_FS_NODE_DEVICE_BLOCK))
816     {                                             823     {
817       (*result)->sync              = virtfs_sy << 
818       (*result)->new_opened_file   = virtfs_ne    824       (*result)->new_opened_file   = virtfs_new_opened_file;
819       (*result)->close_opened_file = virtfs_cl    825       (*result)->close_opened_file = virtfs_close_opened_file;
820     }                                             826     }
821                                                   827 
822   if (type == SOS_FS_NODE_SYMLINK)                828   if (type == SOS_FS_NODE_SYMLINK)
823     (*result)->ops_symlink = & virtfs_ops_syml    829     (*result)->ops_symlink = & virtfs_ops_symlink;
824   else if (type == SOS_FS_NODE_DIRECTORY)         830   else if (type == SOS_FS_NODE_DIRECTORY)
825     (*result)->ops_dir = & virtfs_ops_dir;        831     (*result)->ops_dir = & virtfs_ops_dir;
826                                                   832 
827   /* Initialize mapping structure */              833   /* Initialize mapping structure */
828   if (type == SOS_FS_NODE_REGULAR_FILE)           834   if (type == SOS_FS_NODE_REGULAR_FILE)
829     {                                             835     {
830       virtfsnode->file.mapres.allowed_access_r    836       virtfsnode->file.mapres.allowed_access_rights 
831         = SOS_VM_MAP_PROT_READ                    837         = SOS_VM_MAP_PROT_READ
832         | SOS_VM_MAP_PROT_WRITE                   838         | SOS_VM_MAP_PROT_WRITE
833         | SOS_VM_MAP_PROT_EXEC;                   839         | SOS_VM_MAP_PROT_EXEC;
834       virtfsnode->file.mapres.custom_data    =    840       virtfsnode->file.mapres.custom_data    = virtfsnode;
835       virtfsnode->file.mapres.mmap           =    841       virtfsnode->file.mapres.mmap           = virtfs_new_mapping;
836     }                                             842     }
837                                                   843 
838   list_add_tail(((struct virtfs_instance*)this    844   list_add_tail(((struct virtfs_instance*)this->custom_data)->list_fsnodes,
839                 virtfsnode);                      845                 virtfsnode);
840                                                   846 
841   return SOS_OK;                                  847   return SOS_OK;
842 }                                                 848 }
843                                                   849 
844                                                   850 
845 /* *******************************************    851 /* ********************************************************
846  * FS type (mount/umount) operations              852  * FS type (mount/umount) operations
847  */                                               853  */
848                                                   854 
849 static sos_ret_t virtfs_mount(struct sos_fs_ma    855 static sos_ret_t virtfs_mount(struct sos_fs_manager_type * this,
850                               struct sos_fs_no    856                               struct sos_fs_node * device,
851                               const char * arg    857                               const char * args,
852                               struct sos_fs_ma    858                               struct sos_fs_manager_instance ** mounted_fs)
853 {                                                 859 {
854   sos_ret_t retval;                               860   sos_ret_t retval;
855   struct virtfs_instance * fs;                    861   struct virtfs_instance * fs;
856   struct sos_fs_node * fsnode_root;               862   struct sos_fs_node * fsnode_root;
857   struct sos_hash_table * hash;                   863   struct sos_hash_table * hash;
858                                                   864 
859   *mounted_fs = (struct sos_fs_manager_instanc    865   *mounted_fs = (struct sos_fs_manager_instance*)NULL;
860                                                   866 
861   /* Create FS node hash table */                 867   /* Create FS node hash table */
862   hash = sos_hash_create("virtfs H", struct so    868   hash = sos_hash_create("virtfs H", struct sos_fs_node,
863                          sos_hash_ui64,           869                          sos_hash_ui64,
864                          sos_hash_key_eq_ui64,    870                          sos_hash_key_eq_ui64, 17,
865                          storage_location, hli    871                          storage_location, hlink_nodecache);
866   if (! hash)                                     872   if (! hash)
867     return -SOS_ENOMEM;                           873     return -SOS_ENOMEM;
868                                                   874 
869   fs = (struct virtfs_instance*)                  875   fs = (struct virtfs_instance*)
870     sos_kmalloc(sizeof(struct virtfs_instance)    876     sos_kmalloc(sizeof(struct virtfs_instance), 0);
871   if (! fs)                                       877   if (! fs)
872     {                                             878     {
873       sos_hash_dispose(hash);                     879       sos_hash_dispose(hash);
874       return -SOS_ENOMEM;                         880       return -SOS_ENOMEM;
875     }                                             881     }
876                                                   882 
877   memset(fs, 0x0, sizeof(struct virtfs_instanc    883   memset(fs, 0x0, sizeof(struct virtfs_instance));
878   retval = sos_kmutex_init(& fs->lock, "virtfs    884   retval = sos_kmutex_init(& fs->lock, "virtfs", SOS_KWQ_ORDER_FIFO);
879   if (SOS_OK != retval)                           885   if (SOS_OK != retval)
880     {                                             886     {
881       sos_hash_dispose(hash);                     887       sos_hash_dispose(hash);
882       sos_kfree((sos_vaddr_t) fs);                888       sos_kfree((sos_vaddr_t) fs);
883       return retval;                              889       return retval;
884     }                                             890     }
885   fs->super.custom_data          = fs;            891   fs->super.custom_data          = fs;
886   fs->super.fs_type              = this;          892   fs->super.fs_type              = this;
887   fs->super.allocate_new_node    = virtfs_allo    893   fs->super.allocate_new_node    = virtfs_allocate_new_node;
888   fs->super.fetch_node_from_disk = virtfs_fetc    894   fs->super.fetch_node_from_disk = virtfs_fetch_node_from_disk;
889   fs->super.nodecache            = hash;          895   fs->super.nodecache            = hash;
890                                                   896 
891   retval = virtfs_allocate_new_node(& fs->supe    897   retval = virtfs_allocate_new_node(& fs->super, SOS_FS_NODE_DIRECTORY,
892                                     NULL,         898                                     NULL,
893                                     SOS_FS_REA    899                                     SOS_FS_READABLE | SOS_FS_WRITABLE
894                                     | SOS_FS_E    900                                     | SOS_FS_EXECUTABLE,
895                                     0,            901                                     0,
896                                     & fsnode_r    902                                     & fsnode_root);
897   if (SOS_OK != retval)                           903   if (SOS_OK != retval)
898     {                                             904     {
899       sos_hash_dispose(hash);                     905       sos_hash_dispose(hash);
900       sos_kmutex_dispose(& fs->lock);             906       sos_kmutex_dispose(& fs->lock);
901       sos_kfree((sos_vaddr_t) fs);                907       sos_kfree((sos_vaddr_t) fs);
902       return retval;                              908       return retval;
903     }                                             909     }
904                                                   910 
905   retval = sos_fs_register_fs_instance(& fs->s    911   retval = sos_fs_register_fs_instance(& fs->super, fsnode_root);
906   sos_fs_unref_fsnode(fsnode_root);               912   sos_fs_unref_fsnode(fsnode_root);
907   if (SOS_OK != retval)                           913   if (SOS_OK != retval)
908     {                                             914     {
909       sos_hash_dispose(hash);                     915       sos_hash_dispose(hash);
910       sos_kmutex_dispose(& fs->lock);             916       sos_kmutex_dispose(& fs->lock);
911       sos_kfree((sos_vaddr_t) fs);                917       sos_kfree((sos_vaddr_t) fs);
912       return retval;                              918       return retval;
913     }                                             919     }
914                                                   920 
915   *mounted_fs = & fs->super;                      921   *mounted_fs = & fs->super;
916   return SOS_OK;                                  922   return SOS_OK;
917 }                                                 923 }
918                                                   924 
919                                                   925 
920 static sos_ret_t virtfs_umount(struct sos_fs_m    926 static sos_ret_t virtfs_umount(struct sos_fs_manager_type * this,
921                                struct sos_fs_m    927                                struct sos_fs_manager_instance * mounted_fs)
922 {                                                 928 {
923   struct virtfs_instance * virtfs = (struct vi    929   struct virtfs_instance * virtfs = (struct virtfs_instance*)mounted_fs->custom_data;
924                                                   930 
925   sos_hash_dispose(virtfs->super.nodecache);      931   sos_hash_dispose(virtfs->super.nodecache);
926   while (! list_is_empty(virtfs->list_fsnodes)    932   while (! list_is_empty(virtfs->list_fsnodes))
927     {                                             933     {
928       struct virtfs_node * virtfsnode = list_p    934       struct virtfs_node * virtfsnode = list_pop_head(virtfs->list_fsnodes);
929                                                   935       
930       if (virtfsnode->super.type == SOS_FS_NOD    936       if (virtfsnode->super.type == SOS_FS_NODE_REGULAR_FILE)
931         {                                         937         {
932           if (virtfsnode->file.size > 0)          938           if (virtfsnode->file.size > 0)
933             sos_kfree((sos_vaddr_t) virtfsnode    939             sos_kfree((sos_vaddr_t) virtfsnode->file.data);
934         }                                         940         }
935       else if (virtfsnode->super.type == SOS_F    941       else if (virtfsnode->super.type == SOS_FS_NODE_DIRECTORY)
936         {                                         942         {
937           while (! list_is_empty_named(virtfsn    943           while (! list_is_empty_named(virtfsnode->dir.list_entries,
938                                        sibling    944                                        sibling_prev, sibling_next))
939             {                                     945             {
940               struct virtfs_direntry * direntr    946               struct virtfs_direntry * direntry
941                 = list_pop_head_named(virtfsno    947                 = list_pop_head_named(virtfsnode->dir.list_entries,
942                                       sibling_    948                                       sibling_prev, sibling_next);
943                                                   949               
944               sos_kfree((sos_vaddr_t)direntry-    950               sos_kfree((sos_vaddr_t)direntry->name);
945               sos_kfree((sos_vaddr_t)direntry)    951               sos_kfree((sos_vaddr_t)direntry);
946             }                                     952             }
947         }                                         953         }
948                                                   954 
949       sos_kfree((sos_vaddr_t)virtfsnode);         955       sos_kfree((sos_vaddr_t)virtfsnode);
950     }                                             956     }
951                                                   957 
952   sos_fs_unregister_fs_instance(& virtfs->supe    958   sos_fs_unregister_fs_instance(& virtfs->super);
953   sos_kmutex_dispose(& virtfs->lock);             959   sos_kmutex_dispose(& virtfs->lock);
954   sos_kfree((sos_vaddr_t)virtfs);                 960   sos_kfree((sos_vaddr_t)virtfs);
955   return SOS_OK;                                  961   return SOS_OK;
956 }                                                 962 }
957                                                   963 
958                                                   964 
959 /* *******************************************    965 /* ********************************************************
960  * File mapping stuff                             966  * File mapping stuff
961  */                                               967  */
962 inline static struct virtfs_node *                968 inline static struct virtfs_node *
963 get_virtfsnode_of_vr(struct sos_umem_vmm_vr *     969 get_virtfsnode_of_vr(struct sos_umem_vmm_vr * vr)
964 {                                                 970 {
965   struct sos_umem_vmm_mapped_resource *mr         971   struct sos_umem_vmm_mapped_resource *mr
966     = sos_umem_vmm_get_mapped_resource_of_vr(v    972     = sos_umem_vmm_get_mapped_resource_of_vr(vr);
967                                                   973 
968   return (struct virtfs_node *)mr->custom_data    974   return (struct virtfs_node *)mr->custom_data;
969 }                                                 975 }
970                                                   976 
971                                                   977 
972 static void virtfs_map_ref(struct sos_umem_vmm    978 static void virtfs_map_ref(struct sos_umem_vmm_vr * vr)
973 {                                                 979 {
974   struct virtfs_node * virtfsnode = get_virtfs    980   struct virtfs_node * virtfsnode = get_virtfsnode_of_vr(vr);
975   sos_fs_ref_fsnode(& virtfsnode->super);         981   sos_fs_ref_fsnode(& virtfsnode->super);
976   virtfsnode->file.num_mappings ++;               982   virtfsnode->file.num_mappings ++;
977 }                                                 983 }
978                                                   984 
979                                                   985 
980 static void virtfs_map_unref(struct sos_umem_v    986 static void virtfs_map_unref(struct sos_umem_vmm_vr * vr)
981 {                                                 987 {
982   struct virtfs_node * virtfsnode = get_virtfs    988   struct virtfs_node * virtfsnode = get_virtfsnode_of_vr(vr);
983                                                   989 
984   SOS_ASSERT_FATAL(virtfsnode->file.num_mappin    990   SOS_ASSERT_FATAL(virtfsnode->file.num_mappings > 0);
985   virtfsnode->file.num_mappings --;               991   virtfsnode->file.num_mappings --;
986                                                   992 
987   _sos_fs_unref_fsnode(& virtfsnode->super);      993   _sos_fs_unref_fsnode(& virtfsnode->super);
988 }                                                 994 }
989                                                   995 
990                                                   996 
991 static sos_ret_t virtfs_map_page_in(struct sos    997 static sos_ret_t virtfs_map_page_in(struct sos_umem_vmm_vr * vr,
992                                     sos_uaddr_    998                                     sos_uaddr_t uaddr,
993                                     sos_bool_t    999                                     sos_bool_t write_access)
994 {                                                 1000 {
995   struct virtfs_node * virtfsnode = get_virtfs    1001   struct virtfs_node * virtfsnode = get_virtfsnode_of_vr(vr);
996   sos_luoffset_t offset = uaddr - sos_umem_vmm    1002   sos_luoffset_t offset = uaddr - sos_umem_vmm_get_start_of_vr(vr);
997   sos_ret_t retval = SOS_OK;                      1003   sos_ret_t retval = SOS_OK;
998   sos_paddr_t ppage_paddr;                        1004   sos_paddr_t ppage_paddr;
999                                                   1005 
1000   /* The region is not allowed to be resized     1006   /* The region is not allowed to be resized */
1001   if (SOS_PAGE_ALIGN_SUP(offset) > virtfsnode    1007   if (SOS_PAGE_ALIGN_SUP(offset) > virtfsnode->file.size)
1002     return -SOS_EFAULT;                          1008     return -SOS_EFAULT;
1003                                                  1009 
1004   /* Lookup physical kernel page */              1010   /* Lookup physical kernel page */
1005   ppage_paddr = sos_paging_get_paddr(SOS_PAGE    1011   ppage_paddr = sos_paging_get_paddr(SOS_PAGE_ALIGN_INF(virtfsnode->file.data
1006                                                  1012                                                         + offset));
1007                                                  1013 
1008   /* Cannot access unmapped kernel pages */      1014   /* Cannot access unmapped kernel pages */
1009   if (! ppage_paddr)                             1015   if (! ppage_paddr)
1010     return -SOS_EFAULT;                          1016     return -SOS_EFAULT;
1011                                                  1017   
1012   /* Remap it in user space */                   1018   /* Remap it in user space */
1013   retval = sos_paging_map(ppage_paddr,           1019   retval = sos_paging_map(ppage_paddr,
1014                           SOS_PAGE_ALIGN_INF(    1020                           SOS_PAGE_ALIGN_INF(uaddr),
1015                           TRUE,                  1021                           TRUE,
1016                           sos_umem_vmm_get_pr    1022                           sos_umem_vmm_get_prot_of_vr(vr));
1017                                                  1023 
1018   return retval;                                 1024   return retval;
1019 }                                                1025 }
1020                                                  1026 
1021                                                  1027 
1022 static struct sos_umem_vmm_vr_ops virtfs_map_    1028 static struct sos_umem_vmm_vr_ops virtfs_map_ops
1023   = (struct sos_umem_vmm_vr_ops){                1029   = (struct sos_umem_vmm_vr_ops){
1024     .ref     = virtfs_map_ref,                   1030     .ref     = virtfs_map_ref,
1025     .unref   = virtfs_map_unref,                 1031     .unref   = virtfs_map_unref,
1026     .page_in = virtfs_map_page_in                1032     .page_in = virtfs_map_page_in
1027   };                                             1033   };
1028                                                  1034 
1029 static sos_ret_t virtfs_new_mapping(struct so    1035 static sos_ret_t virtfs_new_mapping(struct sos_umem_vmm_vr *vr)
1030 {                                                1036 {
1031   struct virtfs_node * virtfsnode = get_virtf    1037   struct virtfs_node * virtfsnode = get_virtfsnode_of_vr(vr);
1032   sos_size_t reqsize;                            1038   sos_size_t reqsize;
1033   sos_ret_t retval;                              1039   sos_ret_t retval;
1034                                                  1040 
1035   reqsize  = sos_umem_vmm_get_offset_in_resou    1041   reqsize  = sos_umem_vmm_get_offset_in_resource(vr);
1036   reqsize += sos_umem_vmm_get_size_of_vr(vr);    1042   reqsize += sos_umem_vmm_get_size_of_vr(vr);
1037                                                  1043 
1038   /* Resize the region NOW */                    1044   /* Resize the region NOW */
1039   if (reqsize > virtfsnode->file.size)           1045   if (reqsize > virtfsnode->file.size)
1040     {                                            1046     {
1041       retval = virtfs_resize(virtfsnode,         1047       retval = virtfs_resize(virtfsnode,
1042                              SOS_PAGE_ALIGN_S    1048                              SOS_PAGE_ALIGN_SUP(reqsize));
1043       if (SOS_OK != retval)                      1049       if (SOS_OK != retval)
1044         return retval;                           1050         return retval;
1045     }                                            1051     }
1046                                                  1052 
1047   return sos_umem_vmm_set_ops_of_vr(vr, &virt    1053   return sos_umem_vmm_set_ops_of_vr(vr, &virtfs_map_ops);
1048 }                                                1054 }
                                                      

source navigation ] diff markup ] identifier search ] general search ]