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 8) and /drivers/fs_virtfs.c (Article 9)


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

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