source: rtems/cpukit/libfs/src/imfs/memfile.c @ a02224e

4.104.114.84.95
Last change on this file since a02224e was eb22ebe, checked in by Joel Sherrill <joel.sherrill@…>, on 04/24/01 at 23:06:50

2001-04-24 Joel Sherrill <joel@…>

  • src/imfs/memfile.c (memfile_open): Did not set iop->size

and thus the value was incorrect. Before this field was cleared,
this resulted in the value from the last time that IOP was used
being still in place. Discovered by Andrew Bythell
<abythell@…>.

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