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

📄 core.c

📁 MMI层OBJ不能完全编译
💻 C
📖 第 1 页 / 共 5 页
字号:
void block_free(bref_t b)
{
    tw(tr(TR_BEGIN, TrBlock, "block_free(%d) {\n", b));

    // mark block as invalid and schedule erasure
    block_flags_write(b, BF_LOST);
    block_reclaim(b);

    tw(tr(TR_END, TrBlock, "}\n"));
}

void block_flags_write(uint8 block, uint16 flags)
{
    struct block_header_s *bhp =
        (struct block_header_s *) offset2addr(dev.binfo[block].offset);

    tw(tr(TR_BEGIN, TrBlock, "block_flags_write(%d, 0x%x)\n", block, flags));

    POWERFAIL_DOMAIN_BEGIN(PFM_BLOCKHEADER);
    POWERFAIL_SET_ADDR((int)bhp);

    bstat[block].flags = BIT_SET(bstat[block].flags, flags);
    ffsdrv.write_halfword((uint16 *) &bhp->flags, bstat[block].flags );

    POWERFAIL_DOMAIN_END();

    tw(tr(TR_END, TrBlock, ""));
}

// Allocate an inode for a new object. We use bstat[fs.inodes].objects to
// start our scan for a free inode instead of starting from the first time
// each time.
iref_t inode_alloc(void)
{
    iref_t i;

    tw(tr(TR_BEGIN, TrInode, "inode_alloc() {\n"));
    ttw(ttr(TTrInode, "i_a() {" NL));

    if ((i = inode_alloc_try()) == 0) {
		// NOTEME we are not always out of inodes, maybe there exist to many
		// objects! It will not help to reclaim the inodes in that case!
        tw(tr(TR_FUNC, TrInode, "NOTE: Out of free inodes...\n"));
        inodes_reclaim();
        i = inode_alloc_try();
    }

    tw(tr(TR_END, TrInode, "} %d\n", i));
    ttw(ttr(TTrInode, "} %d" NL, i));

    return i;
}

iref_t inode_alloc_try(void)
{
    iref_t i = fs.inodes_max;
    struct inode_s *ip;

    // If we have not yet reached the maximum allowed number of objects,
    // search for next free inode...
    if (bstat[fs.inodes].used - bstat[fs.inodes].lost < fs.objects_max)
    {
        ip = inode_addr(bstat[fs.inodes].objects);
        for (i = bstat[fs.inodes].objects;
             i < fs.inodes_max - FFS_INODES_MARGIN; i++, ip++) {
            if (ip->location == FLASH_NULL32) {
                bstat[fs.inodes].objects = i;
                bstat[fs.inodes].used++;
                break;
            }
        }
    }
    if (i >= fs.inodes_max - FFS_INODES_MARGIN)
        i = 0;
        
    tw(tr(TR_FUNC, TrInode, "inode_alloc_try() %d\n", i));
    ttw(ttr(TTrInode, "i_a_t() %d" NL, i));

    return i;
}

// NOTEME: Should file data be word aligned to enable faster reads and
// writes in word quantities AND to be more compatible with the inherent
// 16-bit access width of flash memories?
offset_t data_alloc(int size)
{
    offset_t offset = 0;
    bref_t b;
  
    tw(tr(TR_BEGIN, TrData, "data_alloc(%d) {\n", size));
    ttw(ttr(TTrData, "da(%d) {" NL, size));

    offset = data_prealloc(size);

	// If we did allocate the space, we update bstat[]
	if (offset > 0) {
		b = offset2block(offset);
		bstat[b].used += size;
		stats.data_allocated += size; // STATS
	}
	
    tw(tr(TR_END, TrData, "} 0x%04x\n", offset));
    ttw(ttr(TTrData, "} %x" NL, offset));

    return offset;
}

offset_t data_prealloc(int realsize)
{
    int result, i, bytes_free;
    offset_t offset;

	// Is it possible to get this amount of free space and still have enough
	// reserved space?
    ffs_query(Q_BYTES_FREE_RAW, &bytes_free);
	if (realsize > (bytes_free + FFS_FILENAME_MAX + dev.atomsize))
        return 0;    // Not enough unused space

    for (i = 0; i < dev.numblocks; i++) {
        if ((offset = data_alloc_try(realsize)) > 0)
            return offset;  // Space found

        if ((result = data_reclaim()) < 0)
            return 0;  // Data reclaim failed!
    }
    
    return 0;  // No space found
}

// Find free data space of size <size>. Return zero if no space available.
// Note that we ensure that we always have space immediately available for a
// privileged data_alloc(), e.g. a data_alloc() that allocates data space
// without performing a data_reclaim(). This is important when
// re-creating/re-locating the journal file.
offset_t data_alloc_try(int size)
{
    bref_t b;
    int free;
    offset_t offset_big = 0, offset_small = 0;
    int size_big_ok = 0, size_small_ok = 0;
    int size_big, size_small;
    int reserved;

    tw(tr(TR_FUNC, TrData, "data_alloc_try(%d) { ", size));
    ttw(ttr(TTrData, "dat(%d) {" NL, size));

	// NOTE when we alloc do we only need to have reserved space for X
	// number of journal files, where X is the max number of used journals
	// per data reclaim. The only exception is when an object_relocate has
	// failed thus we set reserved_space to zero.
	reserved = RESERVED_LOW;

	if (fs.reserved_space < reserved)
		reserved = fs.reserved_space;

    // Set size_big to the grater of the sizes and size_small to the lesser.
    size_big   = (size > reserved ? size : reserved);
    size_small = (size > reserved ? reserved : size);
    tw(tr(TR_NULL, TrData, "(size_big, small = %d, %d) ", size_big, size_small));

    // First search for free space in data blocks
    tw(tr(TR_NULL, TrData, "block:free,objects: "));

    for (b = 0; b < dev.numblocks; b++) {
        if (is_block(b, BF_IS_DATA)) {
            free = dev.blocksize - bstat[b].used;
            tw(tr(TR_NULL, TrData, "%d:%d,%d ", b, free, bstat[b].objects));
            if (bstat[b].objects < fs.block_files_max - fs.block_files_reserved) {
                if (!size_big_ok && !size_small_ok && 
                    (free >= size_big + size_small)) {
                    size_big_ok = size_small_ok = 1;
                    offset_big = offset_small =
                        dev.binfo[b].offset + bstat[b].used;
                    tw(tr(TR_NULL, TrData, "big/small_ok "));
                    break;
                }
                else if (!size_big_ok && free >= size_big) {
                    size_big_ok = 1;
                    offset_big = dev.binfo[b].offset + bstat[b].used;
                    tw(tr(TR_NULL, TrData, "big_ok "));
                }
                else if (!size_small_ok && free >= size_small) {
                    size_small_ok = 1;
                    offset_small = dev.binfo[b].offset + bstat[b].used;
                    tw(tr(TR_NULL, TrData, "small_ok "));
                }
            }
        } 
        if (size_small_ok && size_big_ok)
            break;
    }

    if (size_big_ok && size_small_ok)
        offset_big = (size > reserved ? offset_big : offset_small);
    else
        offset_big = 0;

    tw(tr(TR_NULL, TrData, "} 0x%x\n", offset_big));
    ttw(ttr(TTrData, "} %x " NL, offset_big));

    return offset_big;
}

offset_t data_reserved_alloc(int size)
{
    bref_t b;
    offset_t offset = 0;
    int free;

    tw(tr(TR_BEGIN, TrData, "data_reserved_alloc(%d) {\n", size));
    ttw(ttr(TTrData, "dra(%d) {" NL, size));

    tw(tr(TR_NULL, TrData, "block:free,objects: "));
    for (b = 0; b < dev.numblocks; b++) {
        if (is_block(b, BF_IS_DATA)) {
            free = dev.blocksize - bstat[b].used;
            tw(tr(TR_NULL, TrData, "%d:%d,%d ", b, free, bstat[b].objects));
            if (free >= size) {
                offset = dev.binfo[b].offset + bstat[b].used;
                break;
            }
        } 
    }

    // If we did allocate the space, we update bstat[]
    if (offset != 0) {
        b = offset2block(offset);
        bstat[b].used += size;
        stats.data_allocated += size; // STATS
    }

    tw(tr(TR_END, TrData, "} 0x%04x\n", offset));
    ttw(ttr(TTrData, "} %x" NL, offset));

    return offset;
}


iref_t chunk_alloc(int realsize, int is_journal, offset_t *offset) 
{
    iref_t i;

    if (realsize < 0)
        return EFFS_INVALID;

	// Have we reached objects_max? We make a similar test in
	// inode_alloc_try(), however we need to do it here or else we risk to start
	// a data_reclaim we not can finish.
	if (bstat[fs.inodes].used - bstat[fs.inodes].lost >= fs.objects_max) {
		tw(tr(TR_END, TrObject, "} %d\n", EFFS_FSFULL));
        ttw(ttr(TTrObj, "} %d" NL, EFFS_FSFULL));
        return EFFS_FSFULL;
	}

    // Allocate space for the object name (and object data)
    if (is_journal)
        *offset = data_reserved_alloc(realsize);
    else
        *offset = data_alloc(realsize);

    if (*offset == 0) {
        tw(tr(TR_END, TrObject, "} %d\n", EFFS_NOSPACE));
        ttw(ttr(TTrObj, "} %d" NL, EFFS_NOSPACE));
        return EFFS_NOSPACE;
    }
    fs.journal_ram.location = offset2location(*offset);

    // Allocate an inode for the object
    i = fs.journal.i = inode_alloc();
    if (i == 0) {
        tw(tr(TR_END, TrObject, "} %d\n", EFFS_FSFULL));
        ttw(ttr(TTrObj, "} %d" NL, EFFS_FSFULL));
        return EFFS_FSFULL;
    }

    return i;
}

/******************************************************************************
 * query and fcontrol
 ******************************************************************************/

extern uint16 ffs_flash_device;
extern uint16 ffs_flash_manufact;

effs_t object_control(iref_t i, int8 action, int value)
{
    effs_t error = EFFS_OK;

    tw(tr(TR_BEGIN, TrOther, "object_control(%d, %d, 0x%x) {\n",
          i, action, value));
    ttw(ttr(TTrApi, "obj_control(%d,%d,0x%x)" NL, i, action, value));

    // Convert the flag from 'API' flag to internal flag
    switch (value) {
    case OF_READONLY: value = OFE_READONLY;
    }

    switch (action) {
    case OC_FLAGS:
        // Set/clear object flags. Attempting to modify the "/dev/ffs"
        // object (i = 0) or any non-defined flags is an invalid operation.
        if (i <= 0 || value & ~OF_ALL) {
            error = EFFS_INVALID;
        }
        else {
            // there are two cases; either we only set bits in the flags.
            // This is simple, as we just have to update the flags byte. The
            // other case is harder because we have to clear bits and for
            // this we have to copy the old inode to a new inode, setting
            // the flags appropriately. For now we always just allocate a
            // new inode and set the flags according to the <value>
            // argument.
            journal_begin(i);
            fs.journal_ram.flags |= OF_MASK; // reset all flags
            fs.journal_ram.flags = BIT_SET(fs.journal_ram.flags, value);
            if ((fs.journal.i = inode_alloc()) == 0)
                error = EFFS_FSFULL;
            else {
                fs.journal.diri = dir_traverse(fs.journal.diri, 0);
                journal_end(0);
            }
        }
        break;

    case OC_FS_FLAGS:      fs.flags           = value; break;
    case OC_DEV_MANUFACT:  ffs_flash_manufact = value; break;
    case OC_DEV_DEVICE:    ffs_flash_device   = value; break;
    case OC_FS_TESTFLAGS:  fs.testflags       = value; break;
    case OC_DEBUG_0:
    case OC_DEBUG_1:
    case OC_DEBUG_2:
    case OC_DEBUG_3:       fs.debug[action - OC_DEBUG_FIRST] = value; break;
    case OC_TRACE_INIT:
#if (TARGET == 1)
        ttr_init(value);
#endif
        break;
    default:
        error = EFFS_INVALID;
    }

    tw(tr(TR_END, TrOther, "} %d\n", error));

    return error;
}

extern int tmffs_bufsize(void); // used by ffs_query()
extern unsigned char *tmffs_bufaddr(void); // used by ffs_query()

#if (TARGET == 1)
// request_id_last is only used in TARGET not to any use on the PC side
extern req_id_t request_id_last;   // from task.c
#else
req_id_t request_id_last;
#endif

// If tmffs not is represented we define a dummy tm version
#ifndef FFS_TM_VERSION 
#define FFS_TM_VERSION   ((uint16) 0x0BAD)
#endif

effs_t ffs_query(int8 query, void *p)
{
    tw(tr(TR_FUNC, TrOther, "query(%d) (?)\n", query));

    if (p == NULL)
        return EFFS_INVALID;

    switch (query)
    {
    case Q_BYTES_FREE:
    case Q_BYTES_USED:
    case Q_BYTES_LOST:
    case Q_BYTES_MAX:
    case Q_OBJECTS_TOTAL:
    case Q_BLOCKS_FREE:
    case Q_BYTES_FREE_RAW:
    {
        bref_t b;
        bref_t blocks_free = 0;
        iref_t objects = 0;
        offset_t max, used = 0, lost = 0;
        struct block_stat_s *bp;

		// Don't count free blocks, inode block, block header and reserved space.
		max = (dev.numblocks - fs.blocks_free_min - 1) * 
            (dev.blocksize - BHEADER_SIZE) - fs.reserved_space;

        // Furthermore don't count the ovewrhead from each chunk (alignment)
        // NOTE: If we call query while FFS not is formatted there is a risk
        // of deviding with zero!
        if (fs.chunk_size_max > 0)
            max -= ((max / fs.chunk_size_max + 1) * dev.atomsize);

        for (b = 0, bp = &bstat[0]; b < dev.numblocks; b++, bp++) {
            if (is_block(b, BF_IS_FREE))
                blocks_free++;
            if (is_block(b, BF_IS_DATA)) {
                objects += bp->objects;
                used    += bp->used;
                lost    += bp->lost;
            }
        }
		
        switch (query) {
        case Q_BYTES_FREE:    *(uint32*)p = max - (used - lost) - FFS_FILENAME_MAX; 
            break;
        case Q_BYTES_FREE_RAW:*(uint32*)p = max - (used - lost); break;
        case Q_BYTES_USED:    *(uint32*)p = used; break;
        case Q_BYTES_LOST:    *(uint32*)p = lost; break;
        case Q_BYTES_MAX:     *(uint32*)p = max; break;
        case Q_OBJECTS_TOTAL: *(uint16*)p = objects; break;
        case Q_BLOCKS_FREE:   *(uint16*)p = blocks_free; break;
        }
        break;
    }

    case Q_TM_BUFADDR:       *(uint32*)p = (uint32) tmffs_bufaddr(); break;
    case Q_TM_BUFSIZE:       *(uint32*)p = tmffs_bufsize(); break;

⌨️ 快捷键说明

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