source: rtems/c/src/exec/libfs/src/imfs/memfile.c @ d79ef17

4.104.114.84.95
Last change on this file since d79ef17 was d79ef17, checked in by Joel Sherrill <joel.sherrill@…>, on 03/23/01 at 14:02:02

2001-03-23 Joel Sherrill <joel@…>

  • src/imfs/memfile.c: Reapply fix from bug report from Jose Sturniolo <jsturnio@…> where NULL pointer was dereferenced when freeing a triply indirect file. The fix was applied to the 4.5 release branch and not the development branch.
  • Property mode set to 100644
File size: 24.2 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      if ( !p )  /* ensure we have a valid pointer */
513         break;
514      for ( j=0 ; j<IMFS_MEMFILE_BLOCK_SLOTS ; j++ ) {
515        if ( p[j] ) {
516          memfile_free_blocks_in_table( (block_p **)&p[j], to_free);
517        }
518      }
519      memfile_free_blocks_in_table(
520        (block_p **)&info->triply_indirect[i], to_free );
521    }
522    memfile_free_blocks_in_table(
523        (block_p **)&info->triply_indirect, to_free );
524  }
525
526  return 0;
527}
528
529/*
530 *  IMFS_memfile_read
531 *
532 *  This routine read from memory file pointed to by the_jnode into
533 *  the specified data buffer specified by destination.  The file
534 *  is NOT extended.  An offset greater than the length of the file
535 *  is considered an error.  Read from an offset for more bytes than
536 *  are between the offset and the end of the file will result in
537 *  reading the data between offset and the end of the file (truncated
538 *  read).
539 */
540
541MEMFILE_STATIC int IMFS_memfile_read(
542   IMFS_jnode_t    *the_jnode,
543   off_t            start,
544   unsigned char   *destination,
545   unsigned int     length
546)
547{
548  block_p             *block_ptr;
549  unsigned int         block;
550  unsigned int         my_length;
551  unsigned int         to_copy = 0;
552  unsigned int         last_byte;
553  unsigned int         copied;
554  unsigned int         start_offset;
555  unsigned char       *dest;
556
557  dest = destination;
558
559  /*
560   *  Perform internal consistency checks
561   */
562
563  assert( the_jnode );
564  if ( !the_jnode )
565    set_errno_and_return_minus_one( EIO );
566
567  assert( the_jnode->type == IMFS_MEMORY_FILE ||
568          the_jnode->type == IMFS_LINEAR_FILE );
569  if ( the_jnode->type != IMFS_MEMORY_FILE &&
570       the_jnode->type != IMFS_LINEAR_FILE )
571    set_errno_and_return_minus_one( EIO );
572
573  /*
574   *  Error checks on arguments
575   */
576
577  assert( dest );
578  if ( !dest )
579    set_errno_and_return_minus_one( EINVAL );
580
581  /*
582   *  If there is nothing to read, then quick exit.
583   */
584
585  my_length = length;
586  if ( !my_length )
587    set_errno_and_return_minus_one( EINVAL );
588
589  /*
590   *  Linear files (as created from a tar file are easier to handle
591   *  than block files).
592   */
593  if (the_jnode->type == IMFS_LINEAR_FILE) {
594    unsigned char  *file_ptr;
595
596    file_ptr = (unsigned char *)the_jnode->info.linearfile.direct;
597
598    if (my_length > (the_jnode->info.linearfile.size - start))
599      my_length = the_jnode->info.linearfile.size - start;
600
601    memcpy(dest, &file_ptr[start], my_length);
602
603    IMFS_update_atime( the_jnode );
604
605    return my_length;
606  }
607
608  /*
609   *  If the last byte we are supposed to read is past the end of this
610   *  in memory file, then shorten the length to read.
611   */
612
613  last_byte = start + length;
614  if ( last_byte > the_jnode->info.file.size )
615    my_length = the_jnode->info.file.size - start;
616
617  copied = 0;
618
619  /*
620   *  Three phases to the read:
621   *    + possibly the last part of one block
622   *    + all of zero of more blocks
623   *    + possibly the first part of one block
624   */
625
626  /*
627   *  Phase 1: possibly the last part of one block
628   */
629
630  start_offset = start % IMFS_MEMFILE_BYTES_PER_BLOCK;
631  block = start / IMFS_MEMFILE_BYTES_PER_BLOCK;
632  if ( start_offset )  {
633    to_copy = IMFS_MEMFILE_BYTES_PER_BLOCK - start_offset;
634    if ( to_copy > my_length )
635      to_copy = my_length;
636    block_ptr = IMFS_memfile_get_block_pointer( the_jnode, block, 0 );
637    assert( block_ptr );
638    if ( !block_ptr )
639      return copied;
640    memcpy( dest, &(*block_ptr)[ start_offset ], to_copy );
641    dest += to_copy;
642    block++;
643    my_length -= to_copy;
644    copied += to_copy;
645  }
646
647  /*
648   *  Phase 2: all of zero of more blocks
649   */
650
651  to_copy = IMFS_MEMFILE_BYTES_PER_BLOCK;
652  while ( my_length >= IMFS_MEMFILE_BYTES_PER_BLOCK ) {
653    block_ptr = IMFS_memfile_get_block_pointer( the_jnode, block, 0 );
654    assert( block_ptr );
655    if ( !block_ptr )
656      return copied;
657    memcpy( dest, &(*block_ptr)[ 0 ], to_copy );
658    dest += to_copy;
659    block++;
660    my_length -= to_copy;
661    copied += to_copy;
662  }
663
664  /*
665   *  Phase 3: possibly the first part of one block
666   */
667
668  assert( my_length < IMFS_MEMFILE_BYTES_PER_BLOCK );
669
670  if ( my_length ) {
671    block_ptr = IMFS_memfile_get_block_pointer( the_jnode, block, 0 );
672    assert( block_ptr );
673    if ( !block_ptr )
674      return copied;
675    memcpy( dest, &(*block_ptr)[ 0 ], my_length );
676    copied += my_length;
677  }
678
679  IMFS_update_atime( the_jnode );
680
681  return copied;
682}
683
684/*
685 *  IMFS_memfile_write
686 *
687 *  This routine writes the specified data buffer into the in memory
688 *  file pointed to by the_jnode.  The file is extended as needed.
689 */
690
691MEMFILE_STATIC int IMFS_memfile_write(
692   IMFS_jnode_t          *the_jnode,
693   off_t                  start,
694   const unsigned char   *source,
695   unsigned int           length
696)
697{
698  block_p             *block_ptr;
699  unsigned int         block;
700  int                  status;
701  unsigned int         my_length;
702  unsigned int         to_copy = 0;
703  unsigned int         last_byte;
704  unsigned int         start_offset;
705  int                  copied;
706  const unsigned char *src;
707
708  src = source;
709
710  /*
711   *  Perform internal consistency checks
712   */
713
714  assert( the_jnode );
715  if ( !the_jnode )
716    set_errno_and_return_minus_one( EIO );
717
718  assert( the_jnode->type == IMFS_MEMORY_FILE );
719  if ( the_jnode->type != IMFS_MEMORY_FILE )
720    set_errno_and_return_minus_one( EIO );
721
722  /*
723   *  Error check arguments
724   */
725
726  assert( source );
727  if ( !source )
728    set_errno_and_return_minus_one( EINVAL );
729
730
731  /*
732   *  If there is nothing to write, then quick exit.
733   */
734
735  my_length = length;
736  if ( !my_length )
737    set_errno_and_return_minus_one( EINVAL );
738
739  /*
740   *  If the last byte we are supposed to write is past the end of this
741   *  in memory file, then extend the length.
742   */
743
744  last_byte = start + length;
745  if ( last_byte > the_jnode->info.file.size ) {
746    status = IMFS_memfile_extend( the_jnode, last_byte );
747    if ( status )
748      set_errno_and_return_minus_one( ENOSPC );
749  }
750
751  copied = 0;
752
753  /*
754   *  Three phases to the write:
755   *    + possibly the last part of one block
756   *    + all of zero of more blocks
757   *    + possibly the first part of one block
758   */
759
760  /*
761   *  Phase 1: possibly the last part of one block
762   */
763
764  start_offset = start % IMFS_MEMFILE_BYTES_PER_BLOCK;
765  block = start / IMFS_MEMFILE_BYTES_PER_BLOCK;
766  if ( start_offset )  {
767    to_copy = IMFS_MEMFILE_BYTES_PER_BLOCK - start_offset;
768    if ( to_copy > my_length )
769      to_copy = my_length;
770    block_ptr = IMFS_memfile_get_block_pointer( the_jnode, block, 0 );
771    assert( block_ptr );
772    if ( !block_ptr )
773      return copied;
774#if 0
775printf( "write %d at %d in %d: %*s\n", to_copy, start_offset, block, to_copy, src );
776#endif
777    memcpy( &(*block_ptr)[ start_offset ], src, to_copy );
778    src += to_copy;
779    block++;
780    my_length -= to_copy;
781    copied += to_copy;
782  }
783
784  /*
785   *  Phase 2: all of zero of more blocks
786   */
787
788  to_copy = IMFS_MEMFILE_BYTES_PER_BLOCK;
789  while ( my_length >= IMFS_MEMFILE_BYTES_PER_BLOCK ) {
790    block_ptr = IMFS_memfile_get_block_pointer( the_jnode, block, 0 );
791    assert( block_ptr );
792    if ( !block_ptr )
793      return copied;
794#if 0
795printf( "write %d in %d: %*s\n", to_copy, block, to_copy, src );
796#endif
797    memcpy( &(*block_ptr)[ 0 ], src, to_copy );
798    src += to_copy;
799    block++;
800    my_length -= to_copy;
801    copied += to_copy;
802  }
803
804  /*
805   *  Phase 3: possibly the first part of one block
806   */
807
808  assert( my_length < IMFS_MEMFILE_BYTES_PER_BLOCK );
809
810  to_copy = my_length;
811  if ( my_length ) {
812    block_ptr = IMFS_memfile_get_block_pointer( the_jnode, block, 0 );
813    assert( block_ptr );
814    if ( !block_ptr )
815      return copied;
816#if 0
817printf( "write %d in %d: %*s\n", to_copy, block, to_copy, src );
818#endif
819    memcpy( &(*block_ptr)[ 0 ], src, my_length );
820    my_length = 0;
821    copied += to_copy;
822  }
823
824  IMFS_atime_mtime_update( the_jnode );
825
826  return copied;
827}
828
829/*
830 *  IMFS_memfile_get_block_pointer
831 *
832 *  This routine looks up the block pointer associated with the given block
833 *  number.  If that block has not been allocated and "malloc_it" is
834 *  TRUE, then the block is allocated.  Otherwise, it is an error.
835 */
836
837#if 0
838block_p *IMFS_memfile_get_block_pointer_DEBUG(
839   IMFS_jnode_t   *the_jnode,
840   unsigned int    block,
841   int             malloc_it
842);
843
844block_p *IMFS_memfile_get_block_pointer(
845   IMFS_jnode_t   *the_jnode,
846   unsigned int    block,
847   int             malloc_it
848)
849{
850  block_p *p;
851
852  p = IMFS_memfile_get_block_pointer_DEBUG( the_jnode, block, malloc_it );
853  printf( "(%d -> %p) ", block, p );
854  return p;
855}
856
857block_p *IMFS_memfile_get_block_pointer_DEBUG(
858#else
859block_p *IMFS_memfile_get_block_pointer(
860#endif
861   IMFS_jnode_t   *the_jnode,
862   unsigned int    block,
863   int             malloc_it
864)
865{
866  unsigned int    my_block;
867  IMFS_memfile_t *info;
868  unsigned int    singly;
869  unsigned int    doubly;
870  unsigned int    triply;
871  block_p        *p;
872  block_p        *p1;
873  block_p        *p2;
874
875  /*
876   *  Perform internal consistency checks
877   */
878
879  assert( the_jnode );
880  if ( !the_jnode )
881    return NULL;
882
883  assert( the_jnode->type == IMFS_MEMORY_FILE );
884  if ( the_jnode->type != IMFS_MEMORY_FILE )
885    return NULL;
886
887  info = &the_jnode->info.file;
888
889  my_block = block;
890
891  /*
892   *  Is the block number in the simple indirect portion?
893   */
894
895  if ( my_block <= LAST_INDIRECT ) {
896#if 0
897printf( "(s %d) ", block );
898fflush(stdout);
899#endif
900    p = info->indirect;
901
902    if ( malloc_it ) {
903
904      if ( !p ) {
905        p = memfile_alloc_block();
906        if ( !p )
907           return 0;
908        info->indirect = p;
909      }
910      return &info->indirect[ my_block ];
911    }
912
913    if ( !p )
914      return 0;
915
916    return &info->indirect[ my_block ];
917  }
918
919  /*
920   *  Is the block number in the doubly indirect portion?
921   */
922
923  if ( my_block <= LAST_DOUBLY_INDIRECT ) {
924#if 0
925printf( "(d %d) ", block );
926fflush(stdout);
927#endif
928
929    my_block -= FIRST_DOUBLY_INDIRECT;
930
931    singly = my_block % IMFS_MEMFILE_BLOCK_SLOTS;
932    doubly = my_block / IMFS_MEMFILE_BLOCK_SLOTS;
933
934    p = info->doubly_indirect;
935    if ( malloc_it ) {
936
937      if ( !p ) {
938        p = memfile_alloc_block();
939        if ( !p )
940           return 0;
941        info->doubly_indirect = p;
942      }
943
944      p1 = (block_p *)p[ doubly ];
945      if ( !p1 ) {
946        p1 = memfile_alloc_block();
947        if ( !p1 )
948           return 0;
949        p[ doubly ] = (block_p) p1;
950      }
951
952      return (block_p *)&p1[ singly ];
953    }
954
955    if ( !p )
956      return 0;
957
958    p = (block_p *)p[ doubly ];
959    if ( !p )
960      return 0;
961
962#if 0
963printf( "(d %d %d %d %d %p %p) ", block, my_block, doubly,
964                                       singly, p, &p[singly] );
965fflush(stdout);
966#endif
967    return (block_p *)&p[ singly ];
968  }
969
970#if 0
971printf( "(t %d) ", block );
972fflush(stdout);
973#endif
974  /*
975   *  Is the block number in the triply indirect portion?
976   */
977
978  if ( my_block <= LAST_TRIPLY_INDIRECT ) {
979    my_block -= FIRST_TRIPLY_INDIRECT;
980
981    singly = my_block % IMFS_MEMFILE_BLOCK_SLOTS;
982    doubly = my_block / IMFS_MEMFILE_BLOCK_SLOTS;
983    triply = doubly / IMFS_MEMFILE_BLOCK_SLOTS;
984    doubly %= IMFS_MEMFILE_BLOCK_SLOTS;
985
986    p = info->triply_indirect;
987
988    if ( malloc_it ) {
989      if ( !p ) {
990        p = memfile_alloc_block();
991        if ( !p )
992           return 0;
993        info->triply_indirect = p;
994      }
995
996      p1 = (block_p *) p[ triply ];
997      if ( !p1 ) {
998        p1 = memfile_alloc_block();
999        if ( !p1 )
1000           return 0;
1001        p[ triply ] = (block_p) p1;
1002      }
1003
1004      p2 = (block_p *)p1[ doubly ];
1005      if ( !p2 ) {
1006        p2 = memfile_alloc_block();
1007        if ( !p2 )
1008           return 0;
1009        p1[ doubly ] = (block_p) p2;
1010      }
1011      return (block_p *)&p2[ singly ];
1012    }
1013
1014    if ( !p )
1015      return 0;
1016
1017#if 0
1018printf( "(t %d %d %d %d %d) ", block, my_block, triply, doubly, singly );
1019fflush(stdout);
1020#endif
1021    p1 = (block_p *) p[ triply ];
1022    if ( !p1 )
1023      return 0;
1024
1025    p2 = (block_p *)p1[ doubly ];
1026    if ( !p )
1027      return 0;
1028
1029    return (block_p *)&p2[ singly ];
1030  }
1031
1032  /*
1033   *  This means the requested block number is out of range.
1034   */
1035
1036  return 0;
1037}
1038
1039/*
1040 *  memfile_alloc_block
1041 *
1042 *  Allocate a block for an in-memory file.
1043 */
1044
1045int memfile_blocks_allocated = 0;
1046
1047void *memfile_alloc_block(void)
1048{
1049  void *memory;
1050
1051  memory = (void *)calloc(1, IMFS_MEMFILE_BYTES_PER_BLOCK);
1052  if ( memory )
1053    memfile_blocks_allocated++;
1054
1055  return memory;
1056}
1057
1058/*
1059 *  memfile_free_block
1060 *
1061 *  Free a block from an in-memory file.
1062 */
1063
1064void memfile_free_block(
1065  void *memory
1066)
1067{
1068#if 0
1069printf( "(d %p) ", memory );
1070fflush(stdout);
1071#endif
1072  free(memory);
1073  memfile_blocks_allocated--;
1074}
1075
1076
1077/*
1078 *  memfile_rmnod
1079 *
1080 *  This routine is available from the optable to remove a node
1081 *  from the IMFS file system.
1082 */
1083
1084int memfile_rmnod(
1085  rtems_filesystem_location_info_t      *pathloc       /* IN */
1086)
1087{
1088  IMFS_jnode_t *the_jnode; 
1089
1090  the_jnode = (IMFS_jnode_t *) pathloc->node_access;
1091
1092  /*
1093   * Take the node out of the parent's chain that contains this node
1094   */
1095
1096  if ( the_jnode->Parent != NULL ) {
1097    Chain_Extract( (Chain_Node *) the_jnode );
1098    the_jnode->Parent = NULL;
1099  }
1100
1101  /*
1102   * Decrement the link counter and see if we can free the space.
1103   */
1104
1105  the_jnode->st_nlink--;
1106  IMFS_update_ctime( the_jnode );
1107
1108  /*
1109   * The file cannot be open and the link must be less than 1 to free.
1110   */
1111
1112  if ( !rtems_libio_is_file_open( the_jnode ) && (the_jnode->st_nlink < 1) ) {
1113
1114    /*
1115     * Is the rtems_filesystem_current is this node?
1116     */
1117
1118    if ( rtems_filesystem_current.node_access == pathloc->node_access )
1119       rtems_filesystem_current.node_access = NULL;
1120
1121    /*
1122     * Free memory associated with a memory file.
1123     */
1124    if (the_jnode->type != IMFS_LINEAR_FILE)
1125      IMFS_memfile_remove( the_jnode );
1126
1127    free( the_jnode );
1128  }
1129
1130  return 0;
1131
1132}
1133
1134
Note: See TracBrowser for help on using the repository browser.