⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fsck.c

📁 MMI层OBJ不能完全编译
💻 C
📖 第 1 页 / 共 5 页
字号:
/******************************************************************************
 * Flash File System (ffs)
 * Idea, design and coding by Mads Meisner-Jensen, mmj@ti.com
 *
 * FFS file system integrity checking, journalling, init and exit
 *
 * $Id: fsck.c 1.3.1.1.1.33 Thu, 08 Jan 2004 15:05:23 +0100 tsj $
 *
 ******************************************************************************/


#ifndef TARGET
#include "ffs.cfg"
#endif

#include <string.h>
#include <assert.h>

#include "ffs/ffs.h"
#include "ffs/board/core.h"
#include "ffs/board/drv.h"
#include "ffs/board/ffstrace.h"

#if (TARGET == 0 || WITH_TFFS == 1)
#include "ffs/board/tffs.h"
#endif

#include "swconfig.cfg"

/******************************************************************************
 * Functions
 ******************************************************************************/

bref_t blocks_fsck(void);
iref_t inodes_fsck(void);

/******************************************************************************
 * Init and Exit
 ******************************************************************************/
char 	ffs_initerror[5];
effs_t ffs_initialize(void)
{
    bref_t b;
    struct inode_s *ip;
    int i;
    
    tlw(led_set(0));
    tlw(led_on(LED_INIT));
    ttw(str(TTrInit, "initialize {" NL));
    tw(tr(TR_BEGIN, TrFsck, "ffs_initialize() {\n"));

    // default to non-initialized ffs
    fs.root = 0;
    fs.debug[0] = fs.debug[1] = fs.debug[2] = fs.debug[3] = 0;
    fs.testflags = 0;

    tlw(led_on(LED_DRV_INIT));
    fs.initerror = ffsdrv_init();  // read manufacturer and device ID
    ffs_initerror[0]  = fs.initerror;//fangcjdebug
    tlw(led_off(LED_DRV_INIT));
    if (fs.initerror < 0) {
        tlw(led_off(0));
        tw(tr(TR_END, TrFsck, "} %d\n", fs.initerror));
        ttw(ttr(TTrInit, "} %d" NL, fs.initerror));
        return fs.initerror;
    }

    for (i = 0; i < 3; i++)
    {
        tlw(led_on(LED_BLOCKS_FSCK));
        fs.initerror = EFFS_INVALID;
        fs.initerror = b = blocks_fsck();
		ttr(TTrFatal, "xxx:   blocks_fsck() return: %d,for(%d)" NL, fs.initerror, i);
	ffs_initerror[1] = fs.initerror;//fangcjdebug
        tlw(led_off(LED_BLOCKS_FSCK));
        if (fs.initerror < 0) {
            tlw(led_off(0));
            tw(tr(TR_END, TrFsck, "} %d\n", fs.initerror));
            ttw(ttr(TTrInit, "} %d" NL, fs.initerror));
            return fs.initerror;
        }
        
        tlw(led_on(LED_INODES_FSCK));
        fs.initerror = EFFS_INVALID;
        fs.initerror = inodes_fsck();
	ffs_initerror[2] = fs.initerror;
        tlw(led_off(LED_INODES_FSCK));
        if (fs.initerror < 0) {
            tlw(led_off(0));
            tw(tr(TR_END, TrFsck, "} %d\n", fs.initerror));
            ttw(ttr(TTrInit, "} %d" NL, fs.initerror));
            return fs.initerror;
        }

        // parse the fs options in the root inode's name
        ip = inode_addr(fs.root);
        fs_params_init(addr2name(offset2addr(location2offset(ip->location))));

        if ((fs.initerror = journal_init(fs.ijournal)) == 0)
        	{
        	ffs_initerror[3] = fs.initerror;
            break;    
        	}
    }

	// Init all file_descriptors to zero
	memset(fs.fd, 0, sizeof(struct file_descriptor_s) * fs.fd_max);

    // If blocks_fsck() found a block that needs cleaning, we do it, now
    // that all the file system has been initialized.
    if (b > 0) {
        block_clean(b - 1);
		block_free(b - 1);
    }

    statistics_init();

    // In target, we do this before entering the task event loop...
    // Otherwise we would in some cases impose a long reboot delay if we did
    // it here. If we test in target it is nessesary to call
    // blocks_reclaim() anyway because we re-init ffs.
#if (TARGET == 1)         
#if (WITH_TFFS == 1)
    blocks_reclaim();  // target and test
    if (fs.repi_table[0] != 0) 
        inodes_reclaim();
#endif
#else
    blocks_reclaim();  // not target
    if (fs.repi_table[0] != 0) 
        inodes_reclaim();
#endif

    tlw(led_off(LED_INIT));
    tw(tr(TR_END, TrFsck, "} %d\n", EFFS_OK));
    ttw(str(TTrInit, "} 0" NL));

    return EFFS_OK;
}

void fs_params_init(const char *p)
{
    uint8 opt, digit;
    uint32 n;
	int numdatablocks;

    tw(tr(TR_BEGIN, TrFsck, "fsparams_init('%s') {\n", p));

	// Compiled default values
    fs.filename_max   = FFS_FILENAME_MAX;
	fs.path_depth_max = FFS_PATH_DEPTH_MAX;
    fs.fd_max         = FFS_FD_MAX;
	fs.journal_size   = FFS_JOURNAL_SIZE_IN256THS;
	fs.flags          = 0;
    fs.testflags      = 0;
    fs.is_reclaim_running = 0;
	
    // Flag that it not has been changed by an input arg.
	fs.block_files_max = 0;

    // If we only have two blocks, we cannot make any reclaims and thus we
    // have a write-once FFS system.
    fs.blocks_free_min = (dev.numblocks > 2 ? 1 : 0);

    // Don't count free and inodes blocks
	numdatablocks = dev.numblocks - fs.blocks_free_min - 1;

	// Abselute max number of inodes.
    fs.inodes_max = dev.blocksize / sizeof(struct inode_s);
    if (fs.inodes_max > FFS_INODES_MAX)
		fs.inodes_max = FFS_INODES_MAX;

   	// MUST be true: objects_max <= inodes_max - block_files_max, this is do
   	// to the fact that we always need to have block_files_max number of
   	// inodes left when we run a data reclaim.
    fs.objects_max = fs.inodes_max / 2;

	// Find a suitable chunk_size
//#if	(LOCOSTO_LITE)
//    	fs.chunk_size_max = 2048;
//#else
	// The buffer size is optimized to 8k, since not much performance improvement seen with 16 k.
//	fs.chunk_size_max = 8192;
//#endif	
    if (dev.numblocks*dev.blocksize > 1024*1024)
        fs.chunk_size_max = 8192;
    else
        fs.chunk_size_max = (2048 > (dev.blocksize / 8) 
                             ? (dev.blocksize / 8)
                             : 2048);
    
    fs.fd_buf_size = fs.chunk_size_max;    
    
    fs.journal_size = fs.journal_size * dev.blocksize / 256;
    if (fs.journal_size < FFS_JOURNAL_SIZE_MIN)
        fs.journal_size = FFS_JOURNAL_SIZE_MIN;

    // Set it just below the same amount as entries in one journal file
    fs.block_files_max = (fs.journal_size / sizeof(struct journal_s) 
                          - FFS_JOURNAL_MARGIN - 2);

    // MUST be true: block_files_max < objects_max / 2. But if we want
    // to reach objects_max must block_files_max >= objects_max / number
    // of datablocks, however a big block_files_max require higher
    // reserved_space.
    if (fs.block_files_max > fs.objects_max / 2)
        fs.block_files_max = fs.objects_max / 2 - 4;
		
    // Are we able to reach objects_max? If not then lower the number
    if (fs.objects_max > numdatablocks * fs.block_files_max)
        fs.objects_max = numdatablocks * fs.block_files_max + 10;

    // Absolute minimum is RESERVED_LOW the rest is 'workspace' which is
    // needed to have a reasonable performance.
    fs.reserved_space = dev.blocksize / 2 + 
        numdatablocks * dev.blocksize / 16 + RESERVED_LOW; 
    
    // skip to first char following second slash in name
    n = 0;
    while (*p) {
        if (*p++ == '/') {
            n++;
            if (n == 2)
                break;
        }
    }
    if (n == 2) {
        // while still options to process...
        while (*p) {
            opt = *p++; // save option letter for later
            // collect option value...
            n = 0;
            while ((digit = *p)) {
                if (digit >= '0' && digit <= '9') {
                    n = 10 * n + digit - '0';
                    p++;
                }
                else
                    break;
            }
            switch (opt) {
            case 'b': dev.numblocks = n;       break;
            case 'm': fs.blocks_free_min = n;  break;
            case 'i': fs.inodes_max = n;       break;
            case 'o': fs.objects_max = n;      break;
            case 'n': fs.filename_max = n;     break;
            case 'f': fs.block_files_max = n;  break;
            case 'd': fs.fd_max = n;           break;
            case 's': fs.fd_buf_size = n;      break;
            case 'z': fs.flags = n;            break;
            case 'j': fs.journal_size = n;     break;
            case 'c': fs.chunk_size_max = n;   break;
            case 'r': fs.reserved_space = n;   break;
                // d = &fs.path_depth_max;  // really necessary?
            default:
                break;
            }
        }
    }

    // Now recompute a few parameters based on adjusted values.

	// No journal file thuse no reserved space.
	if (fs.journal_size == 0) {   
		fs.block_files_max = fs.objects_max / 2;
		fs.reserved_space = 0;
		fs.block_files_reserved = 0;
	}

	else {
        // If journal size is less than minimum must it have been changed by an
        // input arg, recalculate.
        if (fs.journal_size < FFS_JOURNAL_SIZE_MIN)
            fs.journal_size = fs.journal_size * dev.blocksize / 256;

        if (fs.reserved_space < RESERVED_LOW)
            fs.reserved_space = fs.reserved_space * dev.blocksize / 256;

		// Only one reserved is needed however we want a margin and set it to two 
		fs.block_files_reserved = 2;
    }
	
	// Don't count free blocks, inode block, reserved space, block headers
	// and the size of one filename.
	fs.filesize_max = numdatablocks * dev.blocksize - fs.reserved_space - 
		numdatablocks * BHEADER_SIZE - FFS_FILENAME_MAX;
	
	// Furthermore don't count the overhead from each chunk (alignment) 
	fs.filesize_max -= ((fs.filesize_max / fs.chunk_size_max) * dev.atomsize 
                        + dev.atomsize);
	
    // NOTEME: chunk_size_min is never used
	fs.chunk_size_min = numdatablocks / fs.objects_max;
    
    tw(tr(TR_FUNC, TrFsck, "dev.numblocks      = %d\n", dev.numblocks));
    tw(tr(TR_FUNC, TrFsck, "fs.blocks_free_min = %d\n", fs.blocks_free_min));
    tw(tr(TR_FUNC, TrFsck, "fs.inodes_max      = %d\n", fs.inodes_max));
    tw(tr(TR_FUNC, TrFsck, "fs.objects_max     = %d\n", fs.objects_max));
    tw(tr(TR_FUNC, TrFsck, "fs.block_files_max = %d\n", fs.block_files_max));
	tw(tr(TR_FUNC, TrFsck, "fs.block_files_reserved    = %d\n", fs.block_files_reserved));
    tw(tr(TR_FUNC, TrFsck, "fs.chunk_size_max  = %d\n", fs.chunk_size_max));
    tw(tr(TR_FUNC, TrFsck, "fs.filename_max    = %d\n", fs.filename_max));
    tw(tr(TR_FUNC, TrFsck, "fs.path_depth_max  = %d\n", fs.path_depth_max));
    tw(tr(TR_FUNC, TrFsck, "fs.journal_size    = %d\n", fs.journal_size));
    tw(tr(TR_FUNC, TrFsck, "fs.reserved_space  = %d\n", fs.reserved_space));
    tw(tr(TR_FUNC, TrFsck, "fs.fd_max          = %d\n", fs.fd_max));
    tw(tr(TR_FUNC, TrFsck, "fs.fd_buf_size     = 0x%02x\n", fs.fd_buf_size));
    tw(tr(TR_FUNC, TrFsck, "fs.flags           = 0x%02x\n", fs.flags));
    tw(tr(TR_END,  TrFsck, "}\n"));
}

// TODO: Finish pending commits/writes. 
effs_t ffs_exit(void)
{
#if (OP_WCP == 1)
    // Make FFS inaccessible.
    fs.initerror = EFFS_AGAIN;

    // Finish pending commits/writes.
    if (ffs_remove("dummy") != EFFS_AGAIN)
      return EFFS_CORRUPTED;
#else
    tw(tr(TR_FUNC, TrFsck, "exit() 0\n"));

#endif

    return EFFS_OK;
}


/******************************************************************************
 * blocks_fsck()
 ******************************************************************************/

blocksize_t block_used(bref_t b)
{
    blocksize_t used;
    uint32 *p, *q;

    tlw(led_toggle(LED_BLOCKS_FSCK));
        
    // We search backwards through block to find the last used byte and
    // thus the total number of used bytes. Note that this code depends
    // on the fact that an erased flash location is 0xFF!
    p = (uint32 *) offset2addr(dev.binfo[b].offset);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -