OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [rtems/] [c/] [src/] [lib/] [libc/] [memfile.c] - Blame information for rev 846

Go to most recent revision | Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.