source: rtems/cpukit/libfs/src/rfs/rtems-rfs-format.c @ 2c0450cb

4.104.115
Last change on this file since 2c0450cb was 1d539c0, checked in by Chris Johns <chrisj@…>, on 04/12/10 at 05:29:25

2010-04-12 Chris Johns <chrisj@…>

libfs/src/rfs/rtems-rfs-buffer-bdbuf.c,
libfs/src/rfs/rtems-rfs-buffer.c, libfs/src/rfs/rtems-rfs-data.h,
libfs/src/rfs/rtems-rfs-dir.c,
libfs/src/rfs/rtems-rfs-file-system.c,
libfs/src/rfs/rtems-rfs-format.c, libfs/src/rfs/rtems-rfs-inode.h,
libfs/src/rfs/rtems-rfs-rtems.c, libfs/src/rfs/rtems-rfs-rtems.h,
libfs/src/rfs/rtems-rfs-shell.c: Fix for PR1502. Clean up problems
on 16bit targets.

  • Property mode set to 100644
File size: 17.6 KB
Line 
1/*
2 *  COPYRIGHT (c) 2010 Chris Johns <chrisj@rtems.org>
3 *
4 *  The license and distribution terms for this file may be
5 *  found in the file LICENSE in this distribution or at
6 *  http://www.rtems.com/license/LICENSE.
7 *
8 *  $Id$
9 */
10/**
11 * @file
12 *
13 * @ingroup rtems-rfs
14 *
15 * RTEMS File Systems Format
16 *
17 * Format the file system ready for use.
18 */
19
20#if HAVE_CONFIG_H
21#include "config.h"
22#endif
23
24#include <stdlib.h>
25#include <stdio.h>
26
27#include <rtems/rfs/rtems-rfs-data.h>
28#include <rtems/rfs/rtems-rfs-file-system.h>
29#include <rtems/rfs/rtems-rfs-inode.h>
30#include <rtems/rtems-rfs-format.h>
31#include <rtems/rfs/rtems-rfs-dir.h>
32
33/**
34 * Return the number of gigabytes.
35 */
36#define GIGS(_g) (((uint64_t)(_g)) * 1024 * 1024)
37
38/**
39 * Return the number of bits that fit in the block size.
40 */
41static int
42rtems_rfs_bits_per_block (rtems_rfs_file_system* fs)
43{
44  return rtems_rfs_bitmap_numof_bits (rtems_rfs_fs_block_size (fs));
45}
46
47/**
48 * Return a rounded up integer quotient given a dividend and divisor. That is:
49 * "quotient = dividend / divisor"
50 */
51int
52rtems_rfs_rup_quotient (uint32_t dividend, uint32_t divisor)
53{
54  if (dividend == 0)
55    return 1;
56  return ((dividend - 1) / divisor) + 1;
57}
58
59/**
60 * Return the number of inodes as a percentage of the total number that can fit
61 * in a blocl.
62 */
63static int
64rtems_rfs_inodes_from_percent (rtems_rfs_file_system* fs,
65                               int                    percentage)
66{
67  int blocks;
68  blocks = ((rtems_rfs_fs_blocks (fs) -
69             RTEMS_RFS_SUPERBLOCK_SIZE) * percentage) / 100;
70  blocks = rtems_rfs_rup_quotient (blocks, fs->group_count);
71  return blocks * (rtems_rfs_fs_block_size (fs) / RTEMS_RFS_INODE_SIZE);
72}
73
74/**
75 * Return the inode overhead given a number of inodes.
76 */
77static int
78rtems_rfs_inode_overhead (rtems_rfs_file_system* fs)
79{
80  int blocks;
81  int bits_per_block;
82  blocks = rtems_rfs_rup_quotient(fs->group_inodes * RTEMS_RFS_INODE_SIZE,
83                                  rtems_rfs_fs_block_size (fs));
84  bits_per_block = rtems_rfs_bits_per_block (fs);
85  /*
86   * There could be more bits that there are blocks, eg 512K disk with 512
87   * blocks.
88   */
89  if (bits_per_block > (rtems_rfs_fs_blocks (fs) - RTEMS_RFS_SUPERBLOCK_SIZE))
90    bits_per_block = rtems_rfs_fs_blocks (fs) - RTEMS_RFS_SUPERBLOCK_SIZE;
91  return ((blocks + 1) * 100 * 10) / bits_per_block;
92}
93
94static bool
95rtems_rfs_check_config (rtems_rfs_file_system*         fs,
96                        const rtems_rfs_format_config* config)
97{
98  fs->block_size = config->block_size;
99  if (!fs->block_size)
100  {
101    uint64_t total_size = rtems_rfs_fs_media_size (fs);
102
103    if (total_size >= GIGS (1))
104    {
105      uint32_t gigs = (total_size + GIGS (1)) / GIGS (1);
106      int      b;
107      for (b = 31; b > 0; b--)
108        if ((gigs & (1 << b)) != 0)
109          break;
110      fs->block_size = 1 << b;
111    }
112
113    if (fs->block_size < 512)
114      fs->block_size = 512;
115   
116    if (fs->block_size > (4 * 1024))
117      fs->block_size = (4 * 1024);
118  }
119 
120  if ((fs->block_size % rtems_rfs_fs_media_block_size (fs)) != 0)
121  {
122    printf ("block size (%zd) is not a multiple of media block size (%ld)\n",
123            fs->block_size, rtems_rfs_fs_media_block_size (fs));
124    return false;
125  }
126
127  fs->group_blocks = config->group_blocks;
128  if (!fs->group_blocks)
129  {
130    /*
131     * The number of blocks per group is defined by the number of bits in a
132     * block.
133     */
134    fs->group_blocks = rtems_rfs_bitmap_numof_bits (fs->block_size);
135  }
136
137  if (fs->group_blocks > rtems_rfs_bitmap_numof_bits (fs->block_size))
138  {
139    printf ("group block count is higher than bits in block\n");
140    return false;
141  }
142 
143  fs->blocks = rtems_rfs_fs_media_size (fs) / fs->block_size;
144
145  /*
146   * The bits per block sets the upper limit for the number of blocks in a
147   * group. The disk will be divided into groups which are the number of bits
148   * per block.
149   */ 
150  fs->group_count = rtems_rfs_rup_quotient (rtems_rfs_fs_blocks (fs),
151                                            rtems_rfs_bits_per_block (fs));
152
153  fs->group_inodes = config->group_inodes;
154  if (!fs->group_inodes)
155  {
156    int inode_overhead = RTEMS_RFS_INODE_OVERHEAD_PERCENTAGE;
157   
158    /*
159     * The number of inodes per group is set as a percentage.
160     */
161    if (config->inode_overhead)
162      inode_overhead = config->inode_overhead;
163     
164    fs->group_inodes = rtems_rfs_inodes_from_percent (fs, inode_overhead);
165  }
166
167  /*
168   * Round up to fill a block because the minimum allocation unit is a block.
169   */
170  fs->inodes_per_block = rtems_rfs_fs_block_size (fs) / RTEMS_RFS_INODE_SIZE;
171  fs->group_inodes =
172    rtems_rfs_rup_quotient (fs->group_inodes,
173                            fs->inodes_per_block) * fs->inodes_per_block;
174 
175  if (fs->group_inodes > rtems_rfs_bitmap_numof_bits (fs->block_size))
176    fs->group_inodes = rtems_rfs_bitmap_numof_bits (fs->block_size);
177
178  fs->max_name_length = config->max_name_length;
179  if (!fs->max_name_length)
180  {
181    fs->max_name_length = 512;
182  }
183 
184  return true;
185}
186
187static bool
188rtems_rfs_write_group (rtems_rfs_file_system* fs,
189                       int                    group,
190                       bool                   initialise_inodes,
191                       bool                   verbose)
192{
193  rtems_rfs_buffer_handle  handle;
194  rtems_rfs_bitmap_control bitmap;
195  rtems_rfs_buffer_block   group_base;
196  size_t                   group_size;
197  int                      blocks;
198  int                      b;
199  int                      rc;
200 
201  group_base = rtems_rfs_fs_block (fs, group, 0);
202
203  if (group_base > rtems_rfs_fs_blocks (fs))
204  {
205    printf ("rtems-rfs: write-group: group %d base beyond disk limit\n",
206            group);
207    return false;
208  }
209
210  group_size = fs->group_blocks;
211
212  /*
213   * Be nice to strange sizes of disks. These are embedded systems after all
214   * and nice numbers do not always work out. Let the last block pick up the
215   * remainder of the blocks.
216   */
217  if ((group_base + group_size) > rtems_rfs_fs_blocks (fs))
218    group_size = rtems_rfs_fs_blocks (fs) - group_base;
219
220  if (verbose)
221    printf ("\rrtems-rfs: format: group %3d: base = %ld, size = %zd",
222            group, group_base, group_size);
223
224  /*
225   * Open a handle and request an empty buffer.
226   */
227  rc = rtems_rfs_buffer_handle_open (fs, &handle);
228  if (rc > 0)
229  {
230    printf ("\nrtems-rfs: write-group: handle open failed: %d: %s\n",
231            rc, strerror (rc));
232    return false;
233  }
234
235  if (verbose)
236    printf (", blocks");
237 
238  /*
239   * Open the block bitmap using the new buffer.
240   */
241  rc = rtems_rfs_bitmap_open (&bitmap, fs, &handle, group_size,
242                              group_base + RTEMS_RFS_GROUP_BLOCK_BITMAP_BLOCK);
243  if (rc > 0)
244  {
245    rtems_rfs_buffer_handle_close (fs, &handle);
246    printf ("\nrtems-rfs: write-group: group %3d: open block bitmap failed: %d: %s\n",
247            group, rc, strerror (rc));
248    return false;
249  }
250
251  /*
252   * Force the whole buffer to a known state. The bit map may not occupy the
253   * whole block.
254   */
255  memset (rtems_rfs_buffer_data (&handle), 0xff, rtems_rfs_fs_block_size (fs));
256 
257  /*
258   * Clear the bitmap.
259   */
260  rc = rtems_rfs_bitmap_map_clear_all (&bitmap);
261  if (rc > 0)
262  {
263    rtems_rfs_bitmap_close (&bitmap);
264    rtems_rfs_buffer_handle_close (fs, &handle);
265    printf ("\nrtems-rfs: write-group: group %3d: block bitmap clear all failed: %d: %s\n",
266            group, rc, strerror (rc));
267    return false;
268  }
269 
270  /*
271   * Forced allocation of the block bitmap.
272   */
273  rtems_rfs_bitmap_map_set (&bitmap, RTEMS_RFS_GROUP_BLOCK_BITMAP_BLOCK);
274
275  /*
276   * Forced allocation of the inode bitmap.
277   */
278  rtems_rfs_bitmap_map_set (&bitmap, RTEMS_RFS_GROUP_INODE_BITMAP_BLOCK);
279
280  /*
281   * Determine the number of inodes blocks in the group.
282   */
283  blocks = rtems_rfs_rup_quotient (fs->group_inodes, fs->inodes_per_block);
284
285  /*
286   * Forced allocation of the inode blocks which follow the block bitmap.
287   */
288  for (b = 0; b < blocks; b++)
289    rtems_rfs_bitmap_map_set (&bitmap, b + RTEMS_RFS_GROUP_INODE_BLOCK);
290
291  /*
292   * Close the block bitmap.
293   */
294  rc = rtems_rfs_bitmap_close (&bitmap);
295  if (rc > 0)
296  {
297    rtems_rfs_buffer_handle_close (fs, &handle);
298    printf ("\nrtems-rfs: write-group: group %3d: close block bitmap failed: %d: %s\n",
299            group, rc, strerror (rc));
300    return false;
301  }
302
303  rtems_rfs_buffer_mark_dirty (&handle);
304
305  if (verbose)
306    printf (", inodes");
307 
308  /*
309   * Open the inode bitmap using the old buffer. Should release any changes.
310   */
311  rc = rtems_rfs_bitmap_open (&bitmap, fs, &handle, group_size,
312                              group_base + RTEMS_RFS_GROUP_INODE_BITMAP_BLOCK);
313  if (rc > 0)
314  {
315    rtems_rfs_buffer_handle_close (fs, &handle);
316    printf ("\nrtems-rfs: write-group: group %3d: open inode bitmap failed: %d: %s\n",
317            group, rc, strerror (rc));
318    return false;
319  }
320
321  /*
322   * Force the whole buffer to a known state. The bit map may not occupy the
323   * whole block.
324   */
325  memset (rtems_rfs_buffer_data (&handle), 0x00, rtems_rfs_fs_block_size (fs));
326 
327  /*
328   * Clear the inode bitmap.
329   */
330  rc = rtems_rfs_bitmap_map_clear_all (&bitmap);
331  if (rc > 0)
332  {
333    rtems_rfs_bitmap_close (&bitmap);
334    rtems_rfs_buffer_handle_close (fs, &handle);
335    printf ("\nrtems-rfs: write-group: group %3d: inode bitmap" \
336            " clear all failed: %d: %s\n", group, rc, strerror (rc));
337    return false;
338  }
339 
340  /*
341   * Close the inode bitmap.
342   */
343  rc = rtems_rfs_bitmap_close (&bitmap);
344  if (rc > 0)
345  {
346    rtems_rfs_buffer_handle_close (fs, &handle);
347    printf ("\nrtems-rfs: write-group: group %3d: close inode" \
348            " bitmap failed: %d: %s\n", group, rc, strerror (rc));
349    return false;
350  }
351
352  rtems_rfs_buffer_mark_dirty (&handle);
353
354  /*
355   * Initialise the inode tables if rerquired to do so.
356   */
357  if (initialise_inodes)
358  {
359    for (b = 0; b < blocks; b++)
360    {
361      rc = rtems_rfs_buffer_handle_request (fs, &handle,
362                                            group_base + b + RTEMS_RFS_GROUP_INODE_BLOCK,
363                                            false);
364      if (rc > 0)
365      {
366        rtems_rfs_buffer_handle_close (fs, &handle);
367        printf ("\nrtems-rfs: write-group: group %3d: block %ld request failed: %d: %s\n",
368                group, group_base + b + RTEMS_RFS_GROUP_INODE_BLOCK,
369                rc, strerror (rc));
370        return false;
371      }
372   
373      /*
374       * Force the whole buffer to a known state. The bit map may not occupy the
375       * whole block.
376       */
377      memset (rtems_rfs_buffer_data (&handle), 0xff, rtems_rfs_fs_block_size (fs));
378 
379      rtems_rfs_buffer_mark_dirty (&handle);
380    }
381  }
382 
383  rc = rtems_rfs_buffer_handle_close (fs, &handle);
384  if (rc > 0)
385  {
386    printf ("\nrtems-rfs: write-group: buffer handle close failed: %d: %s\n",
387            rc, strerror (rc));
388    return false;
389  }
390 
391  return true;
392}
393
394static bool
395rtems_rfs_write_superblock (rtems_rfs_file_system* fs)
396{
397  rtems_rfs_buffer_handle handle;
398  uint8_t*                sb;
399  int                     rc;
400
401  rc = rtems_rfs_buffer_handle_open (fs, &handle);
402  if (rc > 0)
403  {
404    printf ("rtems-rfs: write-superblock: handle open failed: %d: %s\n",
405            rc, strerror (rc));
406    return false;
407  }
408
409  rc = rtems_rfs_buffer_handle_request (fs, &handle, 0, false);
410  if (rc > 0)
411  {
412    rtems_rfs_buffer_handle_close (fs, &handle);
413    printf ("rtems-rfs: write-superblock: request failed: %d: %s\n",
414            rc, strerror (rc));
415    return false;
416  }
417
418  sb = rtems_rfs_buffer_data (&handle);
419 
420#define write_sb(_o, _d) rtems_rfs_write_u32(sb + (_o), _d)
421 
422  memset (sb, 0xff, rtems_rfs_fs_block_size (fs));
423
424  write_sb (RTEMS_RFS_SB_OFFSET_MAGIC, RTEMS_RFS_SB_MAGIC);
425  write_sb (RTEMS_RFS_SB_OFFSET_VERSION, RTEMS_RFS_VERSION);
426  write_sb (RTEMS_RFS_SB_OFFSET_BLOCKS, rtems_rfs_fs_blocks (fs));
427  write_sb (RTEMS_RFS_SB_OFFSET_BLOCK_SIZE, rtems_rfs_fs_block_size (fs));
428  write_sb (RTEMS_RFS_SB_OFFSET_BAD_BLOCKS, fs->bad_blocks);
429  write_sb (RTEMS_RFS_SB_OFFSET_MAX_NAME_LENGTH, fs->max_name_length);
430  write_sb (RTEMS_RFS_SB_OFFSET_GROUPS, fs->group_count);
431  write_sb (RTEMS_RFS_SB_OFFSET_GROUP_BLOCKS, fs->group_blocks);
432  write_sb (RTEMS_RFS_SB_OFFSET_GROUP_INODES, fs->group_inodes);
433  write_sb (RTEMS_RFS_SB_OFFSET_INODE_SIZE, RTEMS_RFS_INODE_SIZE);
434
435  rtems_rfs_buffer_mark_dirty (&handle);
436
437  rc = rtems_rfs_buffer_handle_release (fs, &handle);
438  if (rc > 0)
439  {
440    rtems_rfs_buffer_handle_close (fs, &handle);
441    printf ("rtems-rfs: write-superblock: buffer release failed: %d: %s\n",
442            rc, strerror (rc));
443    return false;
444  }
445
446  rc = rtems_rfs_buffer_handle_close (fs, &handle);
447  if (rc > 0)
448  {
449    printf ("rtems-rfs: write-superblock: buffer handle close failed: %d: %s\n",
450            rc, strerror (rc));
451    return false;
452  }
453 
454  return true;
455}
456
457static int
458rtems_rfs_write_root_dir (const char* name)
459{
460  rtems_rfs_file_system* fs;
461  rtems_rfs_inode_handle inode;
462  rtems_rfs_ino          ino;
463  int                    rc;
464
465  /*
466   * External API so returns -1.
467   */
468  rc = rtems_rfs_fs_open (name, NULL, RTEMS_RFS_FS_FORCE_OPEN, &fs);
469  if (rc < 0)
470  {
471    printf ("rtems-rfs: format: file system open failed: %d: %s\n",
472            errno, strerror (errno));
473    return -1;
474  }
475 
476  rc = rtems_rfs_inode_alloc (fs, RTEMS_RFS_ROOT_INO, &ino);
477  if (rc > 0)
478  {
479    printf ("rtems-rfs: format: inode allocation failed: %d: %s\n",
480            rc, strerror (rc));
481    rtems_rfs_fs_close (fs);
482    return rc;
483  }
484
485  if (ino != RTEMS_RFS_ROOT_INO)
486  {
487    printf ("rtems-rfs: format: allocated inode not root ino: %ld\n", ino);
488    rtems_rfs_fs_close (fs);
489    return rc;
490  }
491 
492  rc = rtems_rfs_inode_open (fs, ino, &inode, true);
493  if (rc > 0)
494  {
495    printf ("rtems-rfs: format: inode open failed: %d: %s\n",
496            rc, strerror (rc));
497    rtems_rfs_group_bitmap_free (fs, true, ino);
498    rtems_rfs_fs_close (fs);
499    return rc;
500  }
501
502  rc = rtems_rfs_inode_initialise (&inode, 0,
503                                   (RTEMS_RFS_S_IFDIR | RTEMS_RFS_S_IRWXU |
504                                    RTEMS_RFS_S_IXGRP | RTEMS_RFS_S_IXOTH),
505                                   0, 0);
506  if (rc > 0)
507    printf ("rtems-rfs: format: inode initialise failed: %d: %s\n",
508            rc, strerror (rc));
509 
510  rc = rtems_rfs_dir_add_entry (fs, &inode, ".", 1, ino);
511  if (rc > 0)
512    printf ("rtems-rfs: format: directory add failed: %d: %s\n",
513            rc, strerror (rc));
514 
515  rc = rtems_rfs_inode_close (fs, &inode);
516  if (rc > 0)
517    printf ("rtems-rfs: format: inode close failed: %d: %s\n",
518            rc, strerror (rc));
519 
520  rc = rtems_rfs_fs_close (fs);
521  if (rc < 0)
522    printf ("rtems-rfs: format: file system close failed: %d: %s\n",
523            errno, strerror (errno));
524 
525  return rc;
526}
527
528int
529rtems_rfs_format (const char* name, const rtems_rfs_format_config* config)
530{
531  rtems_rfs_file_system fs;
532  int                   group;
533  int                   rc;
534
535  if (config->verbose)
536    printf ("rtems-rfs: format: %s\n", name);
537 
538  memset (&fs, 0, sizeof (rtems_rfs_file_system));
539
540  rtems_chain_initialize_empty (&fs.release);
541  rtems_chain_initialize_empty (&fs.release_modified);
542  rtems_chain_initialize_empty (&fs.file_shares);
543
544  fs.max_held_buffers = RTEMS_RFS_FS_MAX_HELD_BUFFERS;
545
546  fs.release_count = 0;
547  fs.release_modified_count = 0;
548
549  fs.flags = RTEMS_RFS_FS_NO_LOCAL_CACHE;
550 
551  /*
552   * Open the buffer interface.
553   */
554  rc = rtems_rfs_buffer_open (name, &fs);
555  if (rc > 0)
556  {
557    printf ("rtems-rfs: format: buffer open failed: %d: %s\n",
558            rc, strerror (rc));
559    return -1;
560  }
561
562  /*
563   * Check the media.
564   */
565  if (rtems_rfs_fs_media_block_size (&fs) == 0)
566  {
567    printf ("rtems-rfs: media block is invalid: %lu\n",
568            rtems_rfs_fs_media_block_size (&fs));
569    return -1;
570  }
571 
572  /*
573   * Check the configuration data.
574   */
575  if (!rtems_rfs_check_config (&fs, config))
576    return -1;
577
578  if (config->verbose)
579  {
580    printf ("rtems-rfs: format: media size = %llu\n",
581            rtems_rfs_fs_media_size (&fs));
582    printf ("rtems-rfs: format: media blocks = %ld\n",
583            rtems_rfs_fs_media_blocks (&fs));
584    printf ("rtems-rfs: format: media block size = %lu\n",
585            rtems_rfs_fs_media_block_size (&fs));
586    printf ("rtems-rfs: format: size = %llu\n",
587            rtems_rfs_fs_size (&fs));
588    printf ("rtems-rfs: format: blocks = %zu\n",
589            rtems_rfs_fs_blocks (&fs));
590    printf ("rtems-rfs: format: block size = %zu\n",
591            rtems_rfs_fs_block_size (&fs));
592    printf ("rtems-rfs: format: bits per block = %u\n",
593            rtems_rfs_bits_per_block (&fs));
594    printf ("rtems-rfs: format: inode size = %zu\n", RTEMS_RFS_INODE_SIZE);
595    printf ("rtems-rfs: format: inodes = %zu (%d.%d%%)\n",
596            fs.group_inodes * fs.group_count,
597            rtems_rfs_inode_overhead (&fs) / 10,
598            rtems_rfs_inode_overhead (&fs) % 10);
599    printf ("rtems-rfs: format: groups = %u\n", fs.group_count);
600    printf ("rtems-rfs: format: group blocks = %zu\n", fs.group_blocks);
601    printf ("rtems-rfs: format: group inodes = %zu\n", fs.group_inodes);
602  }
603
604  rc = rtems_rfs_buffer_setblksize (&fs, rtems_rfs_fs_block_size (&fs));
605  if (rc > 0)
606  {
607    printf ("rtems-rfs: format: setting block size failed: %d: %s\n",
608            rc, strerror (rc));
609    return -1;
610  }
611 
612  if (!rtems_rfs_write_superblock (&fs))
613  {
614    printf ("rtems-rfs: format: superblock write failed\n");
615    return -1;
616  }
617
618  for (group = 0; group < fs.group_count; group++)
619    if (!rtems_rfs_write_group (&fs, group,
620                                config->initialise_inodes, config->verbose))
621      return -1;
622
623  if (config->verbose)
624    printf ("\n");
625 
626  rc = rtems_rfs_buffer_close (&fs);
627  if (rc > 0)
628  {
629    printf ("rtems-rfs: format: buffer close failed: %d: %s\n",
630            rc, strerror (rc));
631    return -1;
632  }
633
634  rc = rtems_rfs_write_root_dir (name);
635  if (rc > 0)
636  {
637    printf ("rtems-rfs: format: writing root dir failed: %d: %s\n",
638            rc, strerror (rc));
639    return -1;
640  }
641 
642  return 0;
643}
Note: See TracBrowser for help on using the repository browser.