source: rtems/c/src/libfs/src/imfs/memfile.c @ db501a3d

4.104.114.84.95
Last change on this file since db501a3d was d6b1d73, checked in by Joel Sherrill <joel.sherrill@…>, on 01/22/01 at 14:05:14

2001-01-22 Ralf Corsepius <corsepiu@…>

  • configure.in: Add src/imfs/config.h
  • src/imfs/Makefile.am: Add INCLUDES += -I. to pickup config.h
  • src/imfs/.cvsignore: Add config.h and stamp-h
  • src/imfs/*.c: Add config.h support.
  • Property mode set to 100644
File size: 24.1 KB
Line 
1/*
2 *  IMFS Device Node Handlers
3 *
4 *  This file contains the set of handlers used to process operations on
5 *  IMFS memory file nodes.  The memory files are created in memory using
6 *  malloc'ed memory.  Thus any data stored in one of these files is lost
7 *  at system shutdown unless special arrangements to copy the data to
8 *  some type of non-volailte storage are made by the application.
9 *
10 *  COPYRIGHT (c) 1989-1999.
11 *  On-Line Applications Research Corporation (OAR).
12 *
13 *  The license and distribution terms for this file may be
14 *  found in the file LICENSE in this distribution or at
15 *  http://www.OARcorp.com/rtems/license.html.
16 *
17 *  $Id$
18 */
19
20#if HAVE_CONFIG_H
21#include "config.h"
22#endif
23
24#include <stdlib.h>
25#include <assert.h>
26#include <errno.h>
27
28#include <rtems.h>
29#include <rtems/libio.h>
30#include "imfs.h"
31#include <rtems/libio_.h>
32
33#define MEMFILE_STATIC
34
35/*
36 *  Prototypes of private routines
37 */
38
39MEMFILE_STATIC int IMFS_memfile_extend(
40   IMFS_jnode_t  *the_jnode,
41   off_t          new_length
42);
43
44MEMFILE_STATIC int IMFS_memfile_addblock(
45   IMFS_jnode_t  *the_jnode,
46   unsigned int   block
47);
48
49MEMFILE_STATIC int IMFS_memfile_remove_block(
50   IMFS_jnode_t  *the_jnode,
51   unsigned int   block
52);
53
54MEMFILE_STATIC block_p *IMFS_memfile_get_block_pointer(
55   IMFS_jnode_t   *the_jnode,
56   unsigned int    block,
57   int             malloc_it
58);
59
60MEMFILE_STATIC int IMFS_memfile_read(
61   IMFS_jnode_t    *the_jnode,
62   off_t            start,
63   unsigned char   *destination,
64   unsigned int     length
65);
66
67MEMFILE_STATIC int IMFS_memfile_write(
68   IMFS_jnode_t          *the_jnode,
69   off_t                  start,
70   const unsigned char   *source,
71   unsigned int           length
72);
73
74void *memfile_alloc_block(void);
75
76void memfile_free_block(
77  void *memory
78);
79
80/*
81 *  memfile_open
82 *
83 *  This routine processes the open() system call.  Note that there is
84 *  nothing special to be done at open() time.
85 */
86
87int memfile_open(
88  rtems_libio_t *iop,
89  const char    *pathname,
90  unsigned32     flag,
91  unsigned32     mode
92)
93{
94  IMFS_jnode_t  *the_jnode;
95
96  the_jnode = iop->file_info;
97
98  if (iop->flags & LIBIO_FLAGS_APPEND)
99    iop->offset = the_jnode->info.file.size;
100
101  return 0;
102}
103
104/*
105 *  memfile_close
106 *
107 *  This routine processes the close() system call.  Note that there is
108 *  nothing to flush or memory to free at this point.
109 */
110
111int memfile_close(
112  rtems_libio_t *iop
113)
114{
115  IMFS_jnode_t   *the_jnode;
116
117  the_jnode = iop->file_info;
118
119  if (iop->flags & LIBIO_FLAGS_APPEND)
120    iop->offset = the_jnode->info.file.size;
121
122  return 0;
123}
124
125/*
126 *  memfile_read
127 *
128 *  This routine processes the read() system call.
129 */
130
131int memfile_read(
132  rtems_libio_t *iop,
133  void          *buffer,
134  unsigned32     count
135)
136{
137  IMFS_jnode_t   *the_jnode;
138
139  the_jnode = iop->file_info;
140
141  return IMFS_memfile_read( the_jnode, iop->offset, buffer, count );
142}
143
144/*
145 *  memfile_write
146 *
147 *  This routine processes the write() system call.
148 */
149
150int memfile_write(
151  rtems_libio_t *iop,
152  const void    *buffer,
153  unsigned32     count
154)
155{
156  IMFS_jnode_t   *the_jnode;
157  int             status;
158
159  the_jnode = iop->file_info;
160
161  status = IMFS_memfile_write( the_jnode, iop->offset, buffer, count );
162  iop->size = the_jnode->info.file.size;
163
164  return status;
165}
166
167/*
168 *  memfile_ioctl
169 *
170 *  This routine processes the ioctl() system call.
171 *
172 *  NOTE:  No ioctl()'s are supported for in-memory files.
173 */
174
175int memfile_ioctl(
176  rtems_libio_t *iop,
177  unsigned32     command,
178  void          *buffer
179)
180{
181  IMFS_jnode_t   *the_jnode;
182
183  the_jnode = iop->file_info;
184
185  return 0;
186}
187
188/*
189 *  memfile_lseek
190 *
191 *  This routine processes the lseek() system call.
192 */
193
194int memfile_lseek(
195  rtems_libio_t   *iop,
196  off_t            offset,
197  int              whence
198)
199{
200  IMFS_jnode_t   *the_jnode;
201
202  the_jnode = iop->file_info;
203
204  if (the_jnode->type == IMFS_LINEAR_FILE) {
205    if (iop->offset > the_jnode->info.linearfile.size)
206      iop->offset = the_jnode->info.linearfile.size;
207  }
208  else {  /* Must be a block file (IMFS_MEMORY_FILE). */
209    if (IMFS_memfile_extend( the_jnode, iop->offset ))
210      set_errno_and_return_minus_one( ENOSPC );
211
212    iop->size = the_jnode->info.file.size;
213  }
214  return iop->offset;
215}
216
217/*
218 *  memfile_stat
219 *
220 *  This IMFS_stat() can be used.
221 */
222
223/*
224 *  memfile_ftruncate
225 *
226 *  This routine processes the ftruncate() system call.
227 */
228
229int memfile_ftruncate(
230  rtems_libio_t        *iop,
231  off_t                 length
232)
233{
234  IMFS_jnode_t   *the_jnode;
235
236  the_jnode = iop->file_info;
237
238  /*
239   *  POSIX 1003.1b does not specify what happens if you truncate a file
240   *  and the new length is greater than the current size.  We treat this
241   *  as an extend operation.
242   */
243
244  if ( length > the_jnode->info.file.size )
245    return IMFS_memfile_extend( the_jnode, length );
246
247  /*
248   *  The in-memory files do not currently reclaim memory until the file is
249   *  deleted.  So we leave the previously allocated blocks in place for
250   *  future use and just set the length.
251   */
252
253  the_jnode->info.file.size = length;
254  iop->size = the_jnode->info.file.size;
255
256  IMFS_update_atime( the_jnode );
257
258  return 0;
259}
260
261/*
262 *  IMFS_memfile_extend
263 *
264 *  This routine insures that the in-memory file is of the length
265 *  specified.  If necessary, it will allocate memory blocks to
266 *  extend the file.
267 */
268
269MEMFILE_STATIC int IMFS_memfile_extend(
270   IMFS_jnode_t  *the_jnode,
271   off_t          new_length
272)
273{
274  unsigned int   block;
275  unsigned int   new_blocks;
276  unsigned int   old_blocks;
277
278  /*
279   *  Perform internal consistency checks
280   */
281
282  assert( the_jnode );
283  if ( !the_jnode )
284    set_errno_and_return_minus_one( EIO );
285
286  assert( the_jnode->type == IMFS_MEMORY_FILE );
287  if ( the_jnode->type != IMFS_MEMORY_FILE )
288    set_errno_and_return_minus_one( EIO );
289
290  if ( new_length >= IMFS_MEMFILE_MAXIMUM_SIZE )
291    set_errno_and_return_minus_one( EINVAL );
292
293  if ( new_length <= the_jnode->info.file.size )
294    return 0;
295
296  /*
297   *  Calculate the number of range of blocks to allocate
298   */
299
300  new_blocks = new_length / IMFS_MEMFILE_BYTES_PER_BLOCK;
301  old_blocks = the_jnode->info.file.size / IMFS_MEMFILE_BYTES_PER_BLOCK;
302
303  /*
304   *  Now allocate each of those blocks.
305   */
306
307  for ( block=old_blocks ; block<=new_blocks ; block++ ) {
308    if ( IMFS_memfile_addblock( the_jnode, block ) ) {
309       for ( ; block>=old_blocks ; block-- ) {
310          IMFS_memfile_remove_block( the_jnode, block );
311       }
312       set_errno_and_return_minus_one( ENOSPC );
313    }
314  }
315
316  /*
317   *  Set the new length of the file.
318   */
319
320  the_jnode->info.file.size = new_length;
321  return 0;
322}
323
324/*
325 *  IMFS_memfile_addblock
326 *
327 *  This routine adds a single block to the specified in-memory file.
328 */
329
330MEMFILE_STATIC int IMFS_memfile_addblock(
331   IMFS_jnode_t  *the_jnode,
332   unsigned int   block
333)
334{
335  block_p  memory;
336  block_p *block_entry_ptr;
337
338  assert( the_jnode );
339  if ( !the_jnode )
340    set_errno_and_return_minus_one( EIO );
341
342  assert( the_jnode->type == IMFS_MEMORY_FILE );
343  if ( the_jnode->type != IMFS_MEMORY_FILE )
344    set_errno_and_return_minus_one( EIO );
345
346  block_entry_ptr = IMFS_memfile_get_block_pointer( the_jnode, block, 1 );
347  if ( *block_entry_ptr )
348    return 0;
349
350#if 0
351  printf( "%d %p", block, block_entry_ptr );
352    fflush(stdout);
353#endif
354
355  memory = memfile_alloc_block();
356  if ( !memory )
357    return 1;
358  *block_entry_ptr = memory;
359
360  return 0;
361}
362
363/*
364 *  IMFS_memfile_remove_block
365 *
366 *  This routine removes the specified block from the in-memory file.
367 *
368 *  NOTE:  This is a support routine and is called only to remove
369 *         the last block or set of blocks in a file.  Removing a
370 *         block from the middle of a file would be exceptionally
371 *         dangerous and the results unpredictable.
372 */
373
374MEMFILE_STATIC int IMFS_memfile_remove_block(
375   IMFS_jnode_t  *the_jnode,
376   unsigned int   block
377)
378{
379  block_p *block_entry_ptr;
380  block_p  ptr;
381
382  block_entry_ptr = IMFS_memfile_get_block_pointer( the_jnode, block, 0 );
383  ptr = *block_entry_ptr;
384  *block_entry_ptr = 0;
385
386  memfile_free_block( ptr );
387
388  return 1;
389}
390
391/*
392 *  memfile_free_blocks_in_table
393 *
394 *  This is a support routine for IMFS_memfile_remove.  It frees all the
395 *  blocks in one of the indirection tables.
396 */
397
398void memfile_free_blocks_in_table(
399  block_p **block_table,
400  int       entries
401)
402{
403  int      i;
404  block_p *b;
405
406  /*
407   *  Perform internal consistency checks
408   */
409
410  assert( block_table );
411  if ( !block_table )
412    return;
413
414  /*
415   *  Now go through all the slots in the table and free the memory.
416   */
417
418  b = *block_table;
419
420  for ( i=0 ; i<entries ; i++ ) {
421    if ( b[i] ) {
422      memfile_free_block( b[i] );
423      b[i] = 0;
424    }
425  }
426
427  /*
428   *  Now that all the blocks in the block table are free, we can
429   *  free the block table itself.
430   */
431
432  memfile_free_block( *block_table );
433  *block_table = 0;
434}
435
436/*
437 *  IMFS_memfile_remove
438 *
439 *  This routine frees all memory associated with an in memory file.
440 *
441 *  NOTE:  This is an exceptionally conservative implementation. 
442 *         It will check EVERY pointer which is non-NULL and insure
443 *         any child non-NULL pointers are freed.  Optimistically, all that
444 *         is necessary is to scan until a NULL pointer is found.  There
445 *         should be no allocated data past that point.
446 *
447 *         In experimentation on the powerpc simulator, it was noted
448 *         that using blocks which held 128 slots versus 16 slots made
449 *         a significant difference in the performance of this routine.
450 *
451 *         Regardless until the IMFS implementation is proven, it
452 *         is better to stick to simple, easy to understand algorithms.
453 */
454
455int IMFS_memfile_remove(
456 IMFS_jnode_t  *the_jnode
457)
458{
459  IMFS_memfile_t  *info;
460  int              i;
461  int              j;
462  unsigned int     to_free;
463  block_p         *p;
464
465  /*
466   *  Perform internal consistency checks
467   */
468
469  assert( the_jnode );
470  if ( !the_jnode )
471    set_errno_and_return_minus_one( EIO );
472
473  assert( the_jnode->type == IMFS_MEMORY_FILE );
474  if ( the_jnode->type != IMFS_MEMORY_FILE )
475    set_errno_and_return_minus_one( EIO );
476
477  /*
478   *  Eventually this could be set smarter at each call to
479   *  memfile_free_blocks_in_table to greatly speed this up.
480   */
481
482  to_free = IMFS_MEMFILE_BLOCK_SLOTS;
483
484  /*
485   *  Now start freeing blocks in this order:
486   *    + indirect
487   *    + doubly indirect
488   *    + triply indirect
489   */
490
491  info = &the_jnode->info.file;
492
493  if ( info->indirect ) {
494    memfile_free_blocks_in_table( &info->indirect, to_free );
495  }
496
497  if ( info->doubly_indirect ) {
498
499    for ( i=0 ; i<IMFS_MEMFILE_BLOCK_SLOTS ; i++ ) {
500      if ( info->doubly_indirect[i] ) {
501        memfile_free_blocks_in_table(
502         (block_p **)&info->doubly_indirect[i], to_free );
503      }
504    }
505    memfile_free_blocks_in_table( &info->doubly_indirect, to_free );
506
507  }
508 
509  if ( info->triply_indirect ) {
510    for ( i=0 ; i<IMFS_MEMFILE_BLOCK_SLOTS ; i++ ) {
511      p = (block_p *) info->triply_indirect[i];
512      for ( j=0 ; j<IMFS_MEMFILE_BLOCK_SLOTS ; j++ ) {
513        if ( p[j] ) {
514          memfile_free_blocks_in_table( (block_p **)&p[j], to_free);
515        }
516      }
517      memfile_free_blocks_in_table(
518        (block_p **)&info->triply_indirect[i], to_free );
519    }
520    memfile_free_blocks_in_table(
521        (block_p **)&info->triply_indirect, to_free );
522  }
523
524  return 0;
525}
526
527/*
528 *  IMFS_memfile_read
529 *
530 *  This routine read from memory file pointed to by the_jnode into
531 *  the specified data buffer specified by destination.  The file
532 *  is NOT extended.  An offset greater than the length of the file
533 *  is considered an error.  Read from an offset for more bytes than
534 *  are between the offset and the end of the file will result in
535 *  reading the data between offset and the end of the file (truncated
536 *  read).
537 */
538
539MEMFILE_STATIC int IMFS_memfile_read(
540   IMFS_jnode_t    *the_jnode,
541   off_t            start,
542   unsigned char   *destination,
543   unsigned int     length
544)
545{
546  block_p             *block_ptr;
547  unsigned int         block;
548  unsigned int         my_length;
549  unsigned int         to_copy = 0;
550  unsigned int         last_byte;
551  unsigned int         copied;
552  unsigned int         start_offset;
553  unsigned char       *dest;
554
555  dest = destination;
556
557  /*
558   *  Perform internal consistency checks
559   */
560
561  assert( the_jnode );
562  if ( !the_jnode )
563    set_errno_and_return_minus_one( EIO );
564
565  assert( the_jnode->type == IMFS_MEMORY_FILE ||
566          the_jnode->type == IMFS_LINEAR_FILE );
567  if ( the_jnode->type != IMFS_MEMORY_FILE &&
568       the_jnode->type != IMFS_LINEAR_FILE )
569    set_errno_and_return_minus_one( EIO );
570
571  /*
572   *  Error checks on arguments
573   */
574
575  assert( dest );
576  if ( !dest )
577    set_errno_and_return_minus_one( EINVAL );
578
579  /*
580   *  If there is nothing to read, then quick exit.
581   */
582
583  my_length = length;
584  if ( !my_length )
585    set_errno_and_return_minus_one( EINVAL );
586
587  /*
588   *  Linear files (as created from a tar file are easier to handle
589   *  than block files).
590   */
591  if (the_jnode->type == IMFS_LINEAR_FILE) {
592    unsigned char  *file_ptr;
593
594    file_ptr = (unsigned char *)the_jnode->info.linearfile.direct;
595
596    if (my_length > (the_jnode->info.linearfile.size - start))
597      my_length = the_jnode->info.linearfile.size - start;
598
599    memcpy(dest, &file_ptr[start], my_length);
600
601    IMFS_update_atime( the_jnode );
602
603    return my_length;
604  }
605
606  /*
607   *  If the last byte we are supposed to read is past the end of this
608   *  in memory file, then shorten the length to read.
609   */
610
611  last_byte = start + length;
612  if ( last_byte > the_jnode->info.file.size )
613    my_length = the_jnode->info.file.size - start;
614
615  copied = 0;
616
617  /*
618   *  Three phases to the read:
619   *    + possibly the last part of one block
620   *    + all of zero of more blocks
621   *    + possibly the first part of one block
622   */
623
624  /*
625   *  Phase 1: possibly the last part of one block
626   */
627
628  start_offset = start % IMFS_MEMFILE_BYTES_PER_BLOCK;
629  block = start / IMFS_MEMFILE_BYTES_PER_BLOCK;
630  if ( start_offset )  {
631    to_copy = IMFS_MEMFILE_BYTES_PER_BLOCK - start_offset;
632    if ( to_copy > my_length )
633      to_copy = my_length;
634    block_ptr = IMFS_memfile_get_block_pointer( the_jnode, block, 0 );
635    assert( block_ptr );
636    if ( !block_ptr )
637      return copied;
638    memcpy( dest, &(*block_ptr)[ start_offset ], to_copy );
639    dest += to_copy;
640    block++;
641    my_length -= to_copy;
642    copied += to_copy;
643  }
644
645  /*
646   *  Phase 2: all of zero of more blocks
647   */
648
649  to_copy = IMFS_MEMFILE_BYTES_PER_BLOCK;
650  while ( my_length >= IMFS_MEMFILE_BYTES_PER_BLOCK ) {
651    block_ptr = IMFS_memfile_get_block_pointer( the_jnode, block, 0 );
652    assert( block_ptr );
653    if ( !block_ptr )
654      return copied;
655    memcpy( dest, &(*block_ptr)[ 0 ], to_copy );
656    dest += to_copy;
657    block++;
658    my_length -= to_copy;
659    copied += to_copy;
660  }
661
662  /*
663   *  Phase 3: possibly the first part of one block
664   */
665
666  assert( my_length < IMFS_MEMFILE_BYTES_PER_BLOCK );
667
668  if ( my_length ) {
669    block_ptr = IMFS_memfile_get_block_pointer( the_jnode, block, 0 );
670    assert( block_ptr );
671    if ( !block_ptr )
672      return copied;
673    memcpy( dest, &(*block_ptr)[ 0 ], my_length );
674    copied += my_length;
675  }
676
677  IMFS_update_atime( the_jnode );
678
679  return copied;
680}
681
682/*
683 *  IMFS_memfile_write
684 *
685 *  This routine writes the specified data buffer into the in memory
686 *  file pointed to by the_jnode.  The file is extended as needed.
687 */
688
689MEMFILE_STATIC int IMFS_memfile_write(
690   IMFS_jnode_t          *the_jnode,
691   off_t                  start,
692   const unsigned char   *source,
693   unsigned int           length
694)
695{
696  block_p             *block_ptr;
697  unsigned int         block;
698  int                  status;
699  unsigned int         my_length;
700  unsigned int         to_copy = 0;
701  unsigned int         last_byte;
702  unsigned int         start_offset;
703  int                  copied;
704  const unsigned char *src;
705
706  src = source;
707
708  /*
709   *  Perform internal consistency checks
710   */
711
712  assert( the_jnode );
713  if ( !the_jnode )
714    set_errno_and_return_minus_one( EIO );
715
716  assert( the_jnode->type == IMFS_MEMORY_FILE );
717  if ( the_jnode->type != IMFS_MEMORY_FILE )
718    set_errno_and_return_minus_one( EIO );
719
720  /*
721   *  Error check arguments
722   */
723
724  assert( source );
725  if ( !source )
726    set_errno_and_return_minus_one( EINVAL );
727
728
729  /*
730   *  If there is nothing to write, then quick exit.
731   */
732
733  my_length = length;
734  if ( !my_length )
735    set_errno_and_return_minus_one( EINVAL );
736
737  /*
738   *  If the last byte we are supposed to write is past the end of this
739   *  in memory file, then extend the length.
740   */
741
742  last_byte = start + length;
743  if ( last_byte > the_jnode->info.file.size ) {
744    status = IMFS_memfile_extend( the_jnode, last_byte );
745    if ( status )
746      set_errno_and_return_minus_one( ENOSPC );
747  }
748
749  copied = 0;
750
751  /*
752   *  Three phases to the write:
753   *    + possibly the last part of one block
754   *    + all of zero of more blocks
755   *    + possibly the first part of one block
756   */
757
758  /*
759   *  Phase 1: possibly the last part of one block
760   */
761
762  start_offset = start % IMFS_MEMFILE_BYTES_PER_BLOCK;
763  block = start / IMFS_MEMFILE_BYTES_PER_BLOCK;
764  if ( start_offset )  {
765    to_copy = IMFS_MEMFILE_BYTES_PER_BLOCK - start_offset;
766    if ( to_copy > my_length )
767      to_copy = my_length;
768    block_ptr = IMFS_memfile_get_block_pointer( the_jnode, block, 0 );
769    assert( block_ptr );
770    if ( !block_ptr )
771      return copied;
772#if 0
773printf( "write %d at %d in %d: %*s\n", to_copy, start_offset, block, to_copy, src );
774#endif
775    memcpy( &(*block_ptr)[ start_offset ], src, to_copy );
776    src += to_copy;
777    block++;
778    my_length -= to_copy;
779    copied += to_copy;
780  }
781
782  /*
783   *  Phase 2: all of zero of more blocks
784   */
785
786  to_copy = IMFS_MEMFILE_BYTES_PER_BLOCK;
787  while ( my_length >= IMFS_MEMFILE_BYTES_PER_BLOCK ) {
788    block_ptr = IMFS_memfile_get_block_pointer( the_jnode, block, 0 );
789    assert( block_ptr );
790    if ( !block_ptr )
791      return copied;
792#if 0
793printf( "write %d in %d: %*s\n", to_copy, block, to_copy, src );
794#endif
795    memcpy( &(*block_ptr)[ 0 ], src, to_copy );
796    src += to_copy;
797    block++;
798    my_length -= to_copy;
799    copied += to_copy;
800  }
801
802  /*
803   *  Phase 3: possibly the first part of one block
804   */
805
806  assert( my_length < IMFS_MEMFILE_BYTES_PER_BLOCK );
807
808  to_copy = my_length;
809  if ( my_length ) {
810    block_ptr = IMFS_memfile_get_block_pointer( the_jnode, block, 0 );
811    assert( block_ptr );
812    if ( !block_ptr )
813      return copied;
814#if 0
815printf( "write %d in %d: %*s\n", to_copy, block, to_copy, src );
816#endif
817    memcpy( &(*block_ptr)[ 0 ], src, my_length );
818    my_length = 0;
819    copied += to_copy;
820  }
821
822  IMFS_atime_mtime_update( the_jnode );
823
824  return copied;
825}
826
827/*
828 *  IMFS_memfile_get_block_pointer
829 *
830 *  This routine looks up the block pointer associated with the given block
831 *  number.  If that block has not been allocated and "malloc_it" is
832 *  TRUE, then the block is allocated.  Otherwise, it is an error.
833 */
834
835#if 0
836block_p *IMFS_memfile_get_block_pointer_DEBUG(
837   IMFS_jnode_t   *the_jnode,
838   unsigned int    block,
839   int             malloc_it
840);
841
842block_p *IMFS_memfile_get_block_pointer(
843   IMFS_jnode_t   *the_jnode,
844   unsigned int    block,
845   int             malloc_it
846)
847{
848  block_p *p;
849
850  p = IMFS_memfile_get_block_pointer_DEBUG( the_jnode, block, malloc_it );
851  printf( "(%d -> %p) ", block, p );
852  return p;
853}
854
855block_p *IMFS_memfile_get_block_pointer_DEBUG(
856#else
857block_p *IMFS_memfile_get_block_pointer(
858#endif
859   IMFS_jnode_t   *the_jnode,
860   unsigned int    block,
861   int             malloc_it
862)
863{
864  unsigned int    my_block;
865  IMFS_memfile_t *info;
866  unsigned int    singly;
867  unsigned int    doubly;
868  unsigned int    triply;
869  block_p        *p;
870  block_p        *p1;
871  block_p        *p2;
872
873  /*
874   *  Perform internal consistency checks
875   */
876
877  assert( the_jnode );
878  if ( !the_jnode )
879    return NULL;
880
881  assert( the_jnode->type == IMFS_MEMORY_FILE );
882  if ( the_jnode->type != IMFS_MEMORY_FILE )
883    return NULL;
884
885  info = &the_jnode->info.file;
886
887  my_block = block;
888
889  /*
890   *  Is the block number in the simple indirect portion?
891   */
892
893  if ( my_block <= LAST_INDIRECT ) {
894#if 0
895printf( "(s %d) ", block );
896fflush(stdout);
897#endif
898    p = info->indirect;
899
900    if ( malloc_it ) {
901
902      if ( !p ) {
903        p = memfile_alloc_block();
904        if ( !p )
905           return 0;
906        info->indirect = p;
907      }
908      return &info->indirect[ my_block ];
909    }
910
911    if ( !p )
912      return 0;
913
914    return &info->indirect[ my_block ];
915  }
916
917  /*
918   *  Is the block number in the doubly indirect portion?
919   */
920
921  if ( my_block <= LAST_DOUBLY_INDIRECT ) {
922#if 0
923printf( "(d %d) ", block );
924fflush(stdout);
925#endif
926
927    my_block -= FIRST_DOUBLY_INDIRECT;
928
929    singly = my_block % IMFS_MEMFILE_BLOCK_SLOTS;
930    doubly = my_block / IMFS_MEMFILE_BLOCK_SLOTS;
931
932    p = info->doubly_indirect;
933    if ( malloc_it ) {
934
935      if ( !p ) {
936        p = memfile_alloc_block();
937        if ( !p )
938           return 0;
939        info->doubly_indirect = p;
940      }
941
942      p1 = (block_p *)p[ doubly ];
943      if ( !p1 ) {
944        p1 = memfile_alloc_block();
945        if ( !p1 )
946           return 0;
947        p[ doubly ] = (block_p) p1;
948      }
949
950      return (block_p *)&p1[ singly ];
951    }
952
953    if ( !p )
954      return 0;
955
956    p = (block_p *)p[ doubly ];
957    if ( !p )
958      return 0;
959
960#if 0
961printf( "(d %d %d %d %d %p %p) ", block, my_block, doubly,
962                                       singly, p, &p[singly] );
963fflush(stdout);
964#endif
965    return (block_p *)&p[ singly ];
966  }
967
968#if 0
969printf( "(t %d) ", block );
970fflush(stdout);
971#endif
972  /*
973   *  Is the block number in the triply indirect portion?
974   */
975
976  if ( my_block <= LAST_TRIPLY_INDIRECT ) {
977    my_block -= FIRST_TRIPLY_INDIRECT;
978
979    singly = my_block % IMFS_MEMFILE_BLOCK_SLOTS;
980    doubly = my_block / IMFS_MEMFILE_BLOCK_SLOTS;
981    triply = doubly / IMFS_MEMFILE_BLOCK_SLOTS;
982    doubly %= IMFS_MEMFILE_BLOCK_SLOTS;
983
984    p = info->triply_indirect;
985
986    if ( malloc_it ) {
987      if ( !p ) {
988        p = memfile_alloc_block();
989        if ( !p )
990           return 0;
991        info->triply_indirect = p;
992      }
993
994      p1 = (block_p *) p[ triply ];
995      if ( !p1 ) {
996        p1 = memfile_alloc_block();
997        if ( !p1 )
998           return 0;
999        p[ triply ] = (block_p) p1;
1000      }
1001
1002      p2 = (block_p *)p1[ doubly ];
1003      if ( !p2 ) {
1004        p2 = memfile_alloc_block();
1005        if ( !p2 )
1006           return 0;
1007        p1[ doubly ] = (block_p) p2;
1008      }
1009      return (block_p *)&p2[ singly ];
1010    }
1011
1012    if ( !p )
1013      return 0;
1014
1015#if 0
1016printf( "(t %d %d %d %d %d) ", block, my_block, triply, doubly, singly );
1017fflush(stdout);
1018#endif
1019    p1 = (block_p *) p[ triply ];
1020    if ( !p1 )
1021      return 0;
1022
1023    p2 = (block_p *)p1[ doubly ];
1024    if ( !p )
1025      return 0;
1026
1027    return (block_p *)&p2[ singly ];
1028  }
1029
1030  /*
1031   *  This means the requested block number is out of range.
1032   */
1033
1034  return 0;
1035}
1036
1037/*
1038 *  memfile_alloc_block
1039 *
1040 *  Allocate a block for an in-memory file.
1041 */
1042
1043int memfile_blocks_allocated = 0;
1044
1045void *memfile_alloc_block(void)
1046{
1047  void *memory;
1048
1049  memory = (void *)calloc(1, IMFS_MEMFILE_BYTES_PER_BLOCK);
1050  if ( memory )
1051    memfile_blocks_allocated++;
1052
1053  return memory;
1054}
1055
1056/*
1057 *  memfile_free_block
1058 *
1059 *  Free a block from an in-memory file.
1060 */
1061
1062void memfile_free_block(
1063  void *memory
1064)
1065{
1066#if 0
1067printf( "(d %p) ", memory );
1068fflush(stdout);
1069#endif
1070  free(memory);
1071  memfile_blocks_allocated--;
1072}
1073
1074
1075/*
1076 *  memfile_rmnod
1077 *
1078 *  This routine is available from the optable to remove a node
1079 *  from the IMFS file system.
1080 */
1081
1082int memfile_rmnod(
1083  rtems_filesystem_location_info_t      *pathloc       /* IN */
1084)
1085{
1086  IMFS_jnode_t *the_jnode; 
1087
1088  the_jnode = (IMFS_jnode_t *) pathloc->node_access;
1089
1090  /*
1091   * Take the node out of the parent's chain that contains this node
1092   */
1093
1094  if ( the_jnode->Parent != NULL ) {
1095    Chain_Extract( (Chain_Node *) the_jnode );
1096    the_jnode->Parent = NULL;
1097  }
1098
1099  /*
1100   * Decrement the link counter and see if we can free the space.
1101   */
1102
1103  the_jnode->st_nlink--;
1104  IMFS_update_ctime( the_jnode );
1105
1106  /*
1107   * The file cannot be open and the link must be less than 1 to free.
1108   */
1109
1110  if ( !rtems_libio_is_file_open( the_jnode ) && (the_jnode->st_nlink < 1) ) {
1111
1112    /*
1113     * Is the rtems_filesystem_current is this node?
1114     */
1115
1116    if ( rtems_filesystem_current.node_access == pathloc->node_access )
1117       rtems_filesystem_current.node_access = NULL;
1118
1119    /*
1120     * Free memory associated with a memory file.
1121     */
1122    if (the_jnode->type != IMFS_LINEAR_FILE)
1123      IMFS_memfile_remove( the_jnode );
1124
1125    free( the_jnode );
1126  }
1127
1128  return 0;
1129
1130}
1131
1132
Note: See TracBrowser for help on using the repository browser.