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

4.104.114.84.95
Last change on this file since a5305f6b was a5305f6b, checked in by Ralf Corsepius <ralf.corsepius@…>, on 04/17/04 at 08:34:41

Remove stray white spaces.

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