source: rtems/cpukit/libfs/src/imfs/imfs_memfile.c @ c6bb1c33

5
Last change on this file since c6bb1c33 was c6bb1c33, checked in by Kevin Kirspel <kevin-kirspel@…>, on 06/29/17 at 14:36:43

posix/mmap: Add support for file handler and MAP_ANON

Added a mmap file handler to struct _rtems_filesystem_file_handlers_r.
Updated each file handler object to support the default mmap handler.
Updated mmap() to call the mmap handler for MAP_SHARED.
Added a mmap file handler for shm

Added support for MAP_ANON in mmap().

Updates #2859

  • Property mode set to 100644
File size: 19.8 KB
Line 
1/**
2 * @file
3 *
4 * @brief IMFS Memory File Handlers
5 * @ingroup IMFS
6 */
7
8/*
9 *  COPYRIGHT (c) 1989-2010.
10 *  On-Line Applications Research Corporation (OAR).
11 *
12 *  The license and distribution terms for this file may be
13 *  found in the file LICENSE in this distribution or at
14 *  http://www.rtems.org/license/LICENSE.
15 */
16
17#if HAVE_CONFIG_H
18  #include "config.h"
19#endif
20
21#include "imfs.h"
22
23#include <stdlib.h>
24#include <string.h>
25
26/*
27 *  Prototypes of private routines
28 */
29static int IMFS_memfile_extend(
30   IMFS_memfile_t *memfile,
31   bool            zero_fill,
32   off_t           new_length
33);
34
35static int IMFS_memfile_addblock(
36   IMFS_memfile_t *memfile,
37   unsigned int    block
38);
39
40static void IMFS_memfile_remove_block(
41   IMFS_memfile_t *memfile,
42   unsigned int    block
43);
44
45static block_p *IMFS_memfile_get_block_pointer(
46   IMFS_memfile_t *memfile,
47   unsigned int    block,
48   int             malloc_it
49);
50
51static ssize_t IMFS_memfile_read(
52   IMFS_file_t     *file,
53   off_t            start,
54   unsigned char   *destination,
55   unsigned int     length
56);
57
58static void *memfile_alloc_block(void);
59
60static void memfile_free_block(
61  void *memory
62);
63
64static ssize_t memfile_read(
65  rtems_libio_t *iop,
66  void          *buffer,
67  size_t         count
68)
69{
70  IMFS_file_t *file = IMFS_iop_to_file( iop );
71  ssize_t      status;
72
73  status = IMFS_memfile_read( file, iop->offset, buffer, count );
74
75  if ( status > 0 )
76    iop->offset += status;
77
78  return status;
79}
80
81static ssize_t memfile_write(
82  rtems_libio_t *iop,
83  const void    *buffer,
84  size_t         count
85)
86{
87  IMFS_memfile_t *memfile = IMFS_iop_to_memfile( iop );
88  ssize_t         status;
89
90  if ((iop->flags & LIBIO_FLAGS_APPEND) != 0)
91    iop->offset = memfile->File.size;
92
93  status = IMFS_memfile_write( memfile, iop->offset, buffer, count );
94
95  if ( status > 0 )
96    iop->offset += status;
97
98  return status;
99}
100
101/*
102 *  memfile_stat
103 *
104 *  This IMFS_stat() can be used.
105 */
106
107static int memfile_ftruncate(
108  rtems_libio_t        *iop,
109  off_t                 length
110)
111{
112  IMFS_memfile_t *memfile = IMFS_iop_to_memfile( iop );
113
114  /*
115   *  POSIX 1003.1b does not specify what happens if you truncate a file
116   *  and the new length is greater than the current size.  We treat this
117   *  as an extend operation.
118   */
119
120  if ( length > memfile->File.size )
121    return IMFS_memfile_extend( memfile, true, length );
122
123  /*
124   *  The in-memory files do not currently reclaim memory until the file is
125   *  deleted.  So we leave the previously allocated blocks in place for
126   *  future use and just set the length.
127   */
128  memfile->File.size = length;
129
130  IMFS_mtime_ctime_update( &memfile->File.Node );
131
132  return 0;
133}
134
135/*
136 *  IMFS_memfile_extend
137 *
138 *  This routine insures that the in-memory file is of the length
139 *  specified.  If necessary, it will allocate memory blocks to
140 *  extend the file.
141 */
142static int IMFS_memfile_extend(
143   IMFS_memfile_t *memfile,
144   bool            zero_fill,
145   off_t           new_length
146)
147{
148  unsigned int   block;
149  unsigned int   new_blocks;
150  unsigned int   old_blocks;
151  unsigned int   offset;
152
153  /*
154   *  Perform internal consistency checks
155   */
156  IMFS_assert( memfile );
157
158  /*
159   *  Verify new file size is supported
160   */
161  if ( new_length >= IMFS_MEMFILE_MAXIMUM_SIZE )
162    rtems_set_errno_and_return_minus_one( EFBIG );
163
164  /*
165   *  Verify new file size is actually larger than current size
166   */
167  if ( new_length <= memfile->File.size )
168    return 0;
169
170  /*
171   *  Calculate the number of range of blocks to allocate
172   */
173  new_blocks = new_length / IMFS_MEMFILE_BYTES_PER_BLOCK;
174  old_blocks = memfile->File.size / IMFS_MEMFILE_BYTES_PER_BLOCK;
175  offset = memfile->File.size - old_blocks * IMFS_MEMFILE_BYTES_PER_BLOCK;
176
177  /*
178   *  Now allocate each of those blocks.
179   */
180  for ( block=old_blocks ; block<=new_blocks ; block++ ) {
181    if ( !IMFS_memfile_addblock( memfile, block ) ) {
182       if ( zero_fill ) {
183          size_t count = IMFS_MEMFILE_BYTES_PER_BLOCK - offset;
184          block_p *block_ptr =
185            IMFS_memfile_get_block_pointer( memfile, block, 0 );
186
187          memset( &(*block_ptr) [offset], 0, count);
188          offset = 0;
189       }
190    } else {
191       for ( ; block>=old_blocks ; block-- ) {
192         IMFS_memfile_remove_block( memfile, block );
193       }
194       rtems_set_errno_and_return_minus_one( ENOSPC );
195    }
196  }
197
198  /*
199   *  Set the new length of the file.
200   */
201  memfile->File.size = new_length;
202
203  IMFS_mtime_ctime_update( &memfile->File.Node );
204
205  return 0;
206}
207
208/*
209 *  IMFS_memfile_addblock
210 *
211 *  This routine adds a single block to the specified in-memory file.
212 */
213static int IMFS_memfile_addblock(
214   IMFS_memfile_t *memfile,
215   unsigned int    block
216)
217{
218  block_p  memory;
219  block_p *block_entry_ptr;
220
221  IMFS_assert( memfile );
222
223  /*
224   * Obtain the pointer for the specified block number
225   */
226  block_entry_ptr = IMFS_memfile_get_block_pointer( memfile, block, 1 );
227  if ( !block_entry_ptr )
228    return 1;
229
230  if ( *block_entry_ptr )
231    return 0;
232
233  /*
234   *  There is no memory for this block number so allocate it.
235   */
236  memory = memfile_alloc_block();
237  if ( !memory )
238    return 1;
239
240  *block_entry_ptr = memory;
241  return 0;
242}
243
244/*
245 *  IMFS_memfile_remove_block
246 *
247 *  This routine removes the specified block from the in-memory file.
248 *
249 *  NOTE:  This is a support routine and is called only to remove
250 *         the last block or set of blocks in a file.  Removing a
251 *         block from the middle of a file would be exceptionally
252 *         dangerous and the results unpredictable.
253 */
254static void IMFS_memfile_remove_block(
255   IMFS_memfile_t *memfile,
256   unsigned int    block
257)
258{
259  block_p *block_ptr;
260  block_p  ptr;
261
262  block_ptr = IMFS_memfile_get_block_pointer( memfile, block, 0 );
263  if ( block_ptr ) {
264    ptr = *block_ptr;
265    *block_ptr = 0;
266    memfile_free_block( ptr );
267  }
268}
269
270/*
271 *  memfile_free_blocks_in_table
272 *
273 *  This is a support routine for IMFS_memfile_remove.  It frees all the
274 *  blocks in one of the indirection tables.
275 */
276static void memfile_free_blocks_in_table(
277  block_p **block_table,
278  int       entries
279)
280{
281  int      i;
282  block_p *b;
283
284  /*
285   *  Perform internal consistency checks
286   */
287  IMFS_assert( block_table );
288
289  /*
290   *  Now go through all the slots in the table and free the memory.
291   */
292  b = *block_table;
293
294  for ( i=0 ; i<entries ; i++ ) {
295    if ( b[i] ) {
296      memfile_free_block( b[i] );
297      b[i] = 0;
298    }
299  }
300
301  /*
302   *  Now that all the blocks in the block table are free, we can
303   *  free the block table itself.
304   */
305  memfile_free_block( *block_table );
306  *block_table = 0;
307}
308
309/*
310 *  IMFS_memfile_destroy
311 *
312 *  This routine frees all memory associated with an in memory file.
313 *
314 *  NOTE:  This is an exceptionally conservative implementation.
315 *         It will check EVERY pointer which is non-NULL and insure
316 *         any child non-NULL pointers are freed.  Optimistically, all that
317 *         is necessary is to scan until a NULL pointer is found.  There
318 *         should be no allocated data past that point.
319 *
320 *         In experimentation on the powerpc simulator, it was noted
321 *         that using blocks which held 128 slots versus 16 slots made
322 *         a significant difference in the performance of this routine.
323 *
324 *         Regardless until the IMFS implementation is proven, it
325 *         is better to stick to simple, easy to understand algorithms.
326 */
327static void IMFS_memfile_destroy(
328 IMFS_jnode_t  *the_jnode
329)
330{
331  IMFS_memfile_t  *memfile;
332  int              i;
333  int              j;
334  unsigned int     to_free;
335  block_p         *p;
336
337  memfile = (IMFS_memfile_t *) the_jnode;
338
339  /*
340   *  Perform internal consistency checks
341   */
342  IMFS_assert( memfile );
343
344  /*
345   *  Eventually this could be set smarter at each call to
346   *  memfile_free_blocks_in_table to greatly speed this up.
347   */
348  to_free = IMFS_MEMFILE_BLOCK_SLOTS;
349
350  /*
351   *  Now start freeing blocks in this order:
352   *    + indirect
353   *    + doubly indirect
354   *    + triply indirect
355   */
356
357  if ( memfile->indirect ) {
358    memfile_free_blocks_in_table( &memfile->indirect, to_free );
359  }
360
361  if ( memfile->doubly_indirect ) {
362    for ( i=0 ; i<IMFS_MEMFILE_BLOCK_SLOTS ; i++ ) {
363      if ( memfile->doubly_indirect[i] ) {
364        memfile_free_blocks_in_table(
365         (block_p **)&memfile->doubly_indirect[i], to_free );
366      }
367    }
368    memfile_free_blocks_in_table( &memfile->doubly_indirect, to_free );
369
370  }
371
372  if ( memfile->triply_indirect ) {
373    for ( i=0 ; i<IMFS_MEMFILE_BLOCK_SLOTS ; i++ ) {
374      p = (block_p *) memfile->triply_indirect[i];
375      if ( !p )  /* ensure we have a valid pointer */
376         break;
377      for ( j=0 ; j<IMFS_MEMFILE_BLOCK_SLOTS ; j++ ) {
378        if ( p[j] ) {
379          memfile_free_blocks_in_table( (block_p **)&p[j], to_free);
380        }
381      }
382      memfile_free_blocks_in_table(
383        (block_p **)&memfile->triply_indirect[i], to_free );
384    }
385    memfile_free_blocks_in_table(
386        (block_p **)&memfile->triply_indirect, to_free );
387  }
388
389  IMFS_node_destroy_default( the_jnode );
390}
391
392/*
393 *  IMFS_memfile_read
394 *
395 *  This routine read from memory file pointed to by the_jnode into
396 *  the specified data buffer specified by destination.  The file
397 *  is NOT extended.  An offset greater than the length of the file
398 *  is considered an error.  Read from an offset for more bytes than
399 *  are between the offset and the end of the file will result in
400 *  reading the data between offset and the end of the file (truncated
401 *  read).
402 */
403static ssize_t IMFS_memfile_read(
404   IMFS_file_t     *file,
405   off_t            start,
406   unsigned char   *destination,
407   unsigned int     length
408)
409{
410  block_p             *block_ptr;
411  unsigned int         block;
412  unsigned int         my_length;
413  unsigned int         to_copy = 0;
414  unsigned int         last_byte;
415  unsigned int         copied;
416  unsigned int         start_offset;
417  unsigned char       *dest;
418
419  dest = destination;
420
421  /*
422   *  Perform internal consistency checks
423   */
424  IMFS_assert( file );
425  IMFS_assert( dest );
426
427  /*
428   *  Linear files (as created from a tar file are easier to handle
429   *  than block files).
430   */
431  my_length = length;
432
433  /*
434   *  If the last byte we are supposed to read is past the end of this
435   *  in memory file, then shorten the length to read.
436   */
437  last_byte = start + length;
438  if ( last_byte > file->Memfile.File.size )
439    my_length = file->Memfile.File.size - start;
440
441  copied = 0;
442
443  /*
444   *  Three phases to the read:
445   *    + possibly the last part of one block
446   *    + all of zero of more blocks
447   *    + possibly the first part of one block
448   */
449
450  /*
451   *  Phase 1: possibly the last part of one block
452   */
453  start_offset = start % IMFS_MEMFILE_BYTES_PER_BLOCK;
454  block = start / IMFS_MEMFILE_BYTES_PER_BLOCK;
455  if ( start_offset )  {
456    to_copy = IMFS_MEMFILE_BYTES_PER_BLOCK - start_offset;
457    if ( to_copy > my_length )
458      to_copy = my_length;
459    block_ptr = IMFS_memfile_get_block_pointer( &file->Memfile, block, 0 );
460    if ( !block_ptr )
461      return copied;
462    memcpy( dest, &(*block_ptr)[ start_offset ], to_copy );
463    dest += to_copy;
464    block++;
465    my_length -= to_copy;
466    copied += to_copy;
467  }
468
469  /*
470   *  Phase 2: all of zero of more blocks
471   */
472  to_copy = IMFS_MEMFILE_BYTES_PER_BLOCK;
473  while ( my_length >= IMFS_MEMFILE_BYTES_PER_BLOCK ) {
474    block_ptr = IMFS_memfile_get_block_pointer( &file->Memfile, block, 0 );
475    if ( !block_ptr )
476      return copied;
477    memcpy( dest, &(*block_ptr)[ 0 ], to_copy );
478    dest += to_copy;
479    block++;
480    my_length -= to_copy;
481    copied += to_copy;
482  }
483
484  /*
485   *  Phase 3: possibly the first part of one block
486   */
487  IMFS_assert( my_length < IMFS_MEMFILE_BYTES_PER_BLOCK );
488
489  if ( my_length ) {
490    block_ptr = IMFS_memfile_get_block_pointer( &file->Memfile, block, 0 );
491    if ( !block_ptr )
492      return copied;
493    memcpy( dest, &(*block_ptr)[ 0 ], my_length );
494    copied += my_length;
495  }
496
497  IMFS_update_atime( &file->Node );
498
499  return copied;
500}
501
502/*
503 *  IMFS_memfile_write
504 *
505 *  This routine writes the specified data buffer into the in memory
506 *  file pointed to by memfile.  The file is extended as needed.
507 */
508ssize_t IMFS_memfile_write(
509   IMFS_memfile_t        *memfile,
510   off_t                  start,
511   const unsigned char   *source,
512   unsigned int           length
513)
514{
515  block_p             *block_ptr;
516  unsigned int         block;
517  int                  status;
518  unsigned int         my_length;
519  unsigned int         to_copy = 0;
520  unsigned int         last_byte;
521  unsigned int         start_offset;
522  int                  copied;
523  const unsigned char *src;
524
525  src = source;
526
527  /*
528   *  Perform internal consistency checks
529   */
530  IMFS_assert( source );
531  IMFS_assert( memfile );
532
533  my_length = length;
534  /*
535   *  If the last byte we are supposed to write is past the end of this
536   *  in memory file, then extend the length.
537   */
538
539  last_byte = start + my_length;
540  if ( last_byte > memfile->File.size ) {
541    bool zero_fill = start > memfile->File.size;
542
543    status = IMFS_memfile_extend( memfile, zero_fill, last_byte );
544    if ( status )
545      return status;
546  }
547
548  copied = 0;
549
550  /*
551   *  Three phases to the write:
552   *    + possibly the last part of one block
553   *    + all of zero of more blocks
554   *    + possibly the first part of one block
555   */
556
557  /*
558   *  Phase 1: possibly the last part of one block
559   */
560  start_offset = start % IMFS_MEMFILE_BYTES_PER_BLOCK;
561  block = start / IMFS_MEMFILE_BYTES_PER_BLOCK;
562  if ( start_offset )  {
563    to_copy = IMFS_MEMFILE_BYTES_PER_BLOCK - start_offset;
564    if ( to_copy > my_length )
565      to_copy = my_length;
566    block_ptr = IMFS_memfile_get_block_pointer( memfile, block, 0 );
567    if ( !block_ptr )
568      return copied;
569    #if 0
570      fprintf(
571        stderr,
572        "write %d at %d in %d: %*s\n",
573        to_copy,
574        start_offset,
575        block,
576        to_copy,
577        src
578      );
579    #endif
580    memcpy( &(*block_ptr)[ start_offset ], src, to_copy );
581    src += to_copy;
582    block++;
583    my_length -= to_copy;
584    copied += to_copy;
585  }
586
587  /*
588   *  Phase 2: all of zero of more blocks
589   */
590
591  to_copy = IMFS_MEMFILE_BYTES_PER_BLOCK;
592  while ( my_length >= IMFS_MEMFILE_BYTES_PER_BLOCK ) {
593    block_ptr = IMFS_memfile_get_block_pointer( memfile, block, 0 );
594    if ( !block_ptr )
595      return copied;
596    #if 0
597      fprintf(stdout, "write %d in %d: %*s\n", to_copy, block, to_copy, src );
598    #endif
599    memcpy( &(*block_ptr)[ 0 ], src, to_copy );
600    src += to_copy;
601    block++;
602    my_length -= to_copy;
603    copied += to_copy;
604  }
605
606  /*
607   *  Phase 3: possibly the first part of one block
608   */
609  IMFS_assert( my_length < IMFS_MEMFILE_BYTES_PER_BLOCK );
610
611  to_copy = my_length;
612  if ( my_length ) {
613    block_ptr = IMFS_memfile_get_block_pointer( memfile, block, 0 );
614    if ( !block_ptr )
615      return copied;
616    #if 0
617    fprintf(stdout, "write %d in %d: %*s\n", to_copy, block, to_copy, src );
618    #endif
619    memcpy( &(*block_ptr)[ 0 ], src, my_length );
620    my_length = 0;
621    copied += to_copy;
622  }
623
624  IMFS_mtime_ctime_update( &memfile->File.Node );
625
626  return copied;
627}
628
629/*
630 *  IMFS_memfile_get_block_pointer
631 *
632 *  This routine looks up the block pointer associated with the given block
633 *  number.  If that block has not been allocated and "malloc_it" is
634 *  TRUE, then the block is allocated.  Otherwise, it is an error.
635 */
636#if 0
637block_p *IMFS_memfile_get_block_pointer_DEBUG(
638   IMFS_jnode_t   *the_jnode,
639   unsigned int    block,
640   int             malloc_it
641);
642
643block_p *IMFS_memfile_get_block_pointer(
644   IMFS_jnode_t   *the_jnode,
645   unsigned int    block,
646   int             malloc_it
647)
648{
649  block_p *p;
650
651  p = IMFS_memfile_get_block_pointer_DEBUG( the_jnode, block, malloc_it );
652  fprintf(stdout, "(%d -> %p) ", block, p );
653  return p;
654}
655
656block_p *IMFS_memfile_get_block_pointer_DEBUG(
657#else
658block_p *IMFS_memfile_get_block_pointer(
659#endif
660   IMFS_memfile_t *memfile,
661   unsigned int    block,
662   int             malloc_it
663)
664{
665  unsigned int    my_block;
666  unsigned int    singly;
667  unsigned int    doubly;
668  unsigned int    triply;
669  block_p        *p;
670  block_p        *p1;
671  block_p        *p2;
672
673  /*
674   *  Perform internal consistency checks
675   */
676  IMFS_assert( memfile );
677
678  my_block = block;
679
680  /*
681   *  Is the block number in the simple indirect portion?
682   */
683  if ( my_block <= LAST_INDIRECT ) {
684    p = memfile->indirect;
685
686    if ( malloc_it ) {
687
688      if ( !p ) {
689        p = memfile_alloc_block();
690        if ( !p )
691           return 0;
692        memfile->indirect = p;
693      }
694      return &memfile->indirect[ my_block ];
695    }
696
697    if ( !p )
698      return 0;
699
700    return &memfile->indirect[ my_block ];
701  }
702
703  /*
704   *  Is the block number in the doubly indirect portion?
705   */
706
707  if ( my_block <= LAST_DOUBLY_INDIRECT ) {
708    my_block -= FIRST_DOUBLY_INDIRECT;
709
710    singly = my_block % IMFS_MEMFILE_BLOCK_SLOTS;
711    doubly = my_block / IMFS_MEMFILE_BLOCK_SLOTS;
712
713    p = memfile->doubly_indirect;
714    if ( malloc_it ) {
715
716      if ( !p ) {
717        p = memfile_alloc_block();
718        if ( !p )
719           return 0;
720        memfile->doubly_indirect = p;
721      }
722
723      p1 = (block_p *)p[ doubly ];
724      if ( !p1 ) {
725        p1 = memfile_alloc_block();
726        if ( !p1 )
727           return 0;
728        p[ doubly ] = (block_p) p1;
729      }
730
731      return (block_p *)&p1[ singly ];
732    }
733
734    if ( !p )
735      return 0;
736
737    p = (block_p *)p[ doubly ];
738    if ( !p )
739      return 0;
740
741    return (block_p *)&p[ singly ];
742  }
743
744  /*
745   *  Is the block number in the triply indirect portion?
746   */
747  if ( my_block <= LAST_TRIPLY_INDIRECT ) {
748    my_block -= FIRST_TRIPLY_INDIRECT;
749
750    singly = my_block % IMFS_MEMFILE_BLOCK_SLOTS;
751    doubly = my_block / IMFS_MEMFILE_BLOCK_SLOTS;
752    triply = doubly / IMFS_MEMFILE_BLOCK_SLOTS;
753    doubly %= IMFS_MEMFILE_BLOCK_SLOTS;
754
755    p = memfile->triply_indirect;
756
757    if ( malloc_it ) {
758      if ( !p ) {
759        p = memfile_alloc_block();
760        if ( !p )
761           return 0;
762        memfile->triply_indirect = p;
763      }
764
765      p1 = (block_p *) p[ triply ];
766      if ( !p1 ) {
767        p1 = memfile_alloc_block();
768        if ( !p1 )
769           return 0;
770        p[ triply ] = (block_p) p1;
771      }
772
773      p2 = (block_p *)p1[ doubly ];
774      if ( !p2 ) {
775        p2 = memfile_alloc_block();
776        if ( !p2 )
777           return 0;
778        p1[ doubly ] = (block_p) p2;
779      }
780      return (block_p *)&p2[ singly ];
781    }
782
783    if ( !p )
784      return 0;
785
786    p1 = (block_p *) p[ triply ];
787    if ( !p1 )
788      return 0;
789
790    p2 = (block_p *)p1[ doubly ];
791    if ( !p2 )
792      return 0;
793
794    return (block_p *)&p2[ singly ];
795  }
796
797  /*
798   *  This means the requested block number is out of range.
799   */
800  return 0;
801}
802
803/*
804 *  memfile_alloc_block
805 *
806 *  Allocate a block for an in-memory file.
807 */
808int memfile_blocks_allocated = 0;
809
810void *memfile_alloc_block(void)
811{
812  void *memory;
813
814  memory = (void *)calloc(1, IMFS_MEMFILE_BYTES_PER_BLOCK);
815  if ( memory )
816    memfile_blocks_allocated++;
817
818  return memory;
819}
820
821/*
822 *  memfile_free_block
823 *
824 *  Free a block from an in-memory file.
825 */
826void memfile_free_block(
827  void *memory
828)
829{
830  free(memory);
831  memfile_blocks_allocated--;
832}
833
834static const rtems_filesystem_file_handlers_r IMFS_memfile_handlers = {
835  .open_h = rtems_filesystem_default_open,
836  .close_h = rtems_filesystem_default_close,
837  .read_h = memfile_read,
838  .write_h = memfile_write,
839  .ioctl_h = rtems_filesystem_default_ioctl,
840  .lseek_h = rtems_filesystem_default_lseek_file,
841  .fstat_h = IMFS_stat_file,
842  .ftruncate_h = memfile_ftruncate,
843  .fsync_h = rtems_filesystem_default_fsync_or_fdatasync_success,
844  .fdatasync_h = rtems_filesystem_default_fsync_or_fdatasync_success,
845  .fcntl_h = rtems_filesystem_default_fcntl,
846  .kqfilter_h = rtems_filesystem_default_kqfilter,
847  .mmap_h = rtems_filesystem_default_mmap,
848  .poll_h = rtems_filesystem_default_poll,
849  .readv_h = rtems_filesystem_default_readv,
850  .writev_h = rtems_filesystem_default_writev
851};
852
853const IMFS_mknod_control IMFS_mknod_control_memfile = {
854  {
855    .handlers = &IMFS_memfile_handlers,
856    .node_initialize = IMFS_node_initialize_default,
857    .node_remove = IMFS_node_remove_default,
858    .node_destroy = IMFS_memfile_destroy
859  },
860  .node_size = sizeof( IMFS_file_t )
861};
Note: See TracBrowser for help on using the repository browser.