SimpleOS

LXR

Navigation



Site hébergé par : enix

The LXR Cross Referencer for SOS

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

Diff markup

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

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