Esempio n. 1
0
int
nffs_dir_open(const char *path, struct nffs_dir **out_dir)
{
    struct nffs_inode_entry *parent_inode_entry;
    struct nffs_dir *dir;
    int rc;

    rc = nffs_path_find_inode_entry(path, &parent_inode_entry);
    if (rc != 0) {
        return rc;
    }

    if (!nffs_hash_id_is_dir(parent_inode_entry->nie_hash_entry.nhe_id)) {
        return FS_EINVAL;
    }

    dir = nffs_dir_alloc();
    if (dir == NULL) {
        return FS_ENOMEM;
    }

    dir->nd_parent_inode_entry = parent_inode_entry;
    nffs_inode_inc_refcnt(dir->nd_parent_inode_entry);
    memset(&dir->nd_dirent, 0, sizeof dir->nd_dirent);

    *out_dir = dir;

    return 0;
}
Esempio n. 2
0
int
nffs_dir_read(struct nffs_dir *dir, struct nffs_dirent **out_dirent)
{
    struct nffs_inode_entry *child;
    int rc;

    if (dir->nd_dirent.nde_inode_entry == NULL) {
        child = SLIST_FIRST(&dir->nd_parent_inode_entry->nie_child_list);
    } else {
        child = SLIST_NEXT(dir->nd_dirent.nde_inode_entry, nie_sibling_next);
        rc = nffs_inode_dec_refcnt(dir->nd_dirent.nde_inode_entry);
        if (rc != 0) {
            /* XXX: Need to clean up anything? */
            return rc;
        }
    }
    dir->nd_dirent.nde_inode_entry = child;

    if (child == NULL) {
        *out_dirent = NULL;
        return FS_ENOENT;
    }

    nffs_inode_inc_refcnt(child);
    *out_dirent = &dir->nd_dirent;

    return 0;
}
static int
nffs_restore_should_sweep_inode_entry(struct nffs_inode_entry *inode_entry,
                                      int *out_should_sweep)
{
    struct nffs_inode inode;
    int rc;


    /*
     * if this inode was tagged to have a dummy block entry and the
     * flag is still set, that means we didn't find the block and so
     * should remove this inode and all associated blocks.
     */
    if (nffs_inode_getflags(inode_entry, NFFS_INODE_FLAG_DUMMYLSTBLK)) {
        *out_should_sweep = 1;
        /*nffs_inode_inc_refcnt(inode_entry);*/
        inode_entry->nie_refcnt = 1;
        assert(inode_entry->nie_refcnt >= 1);
        return 0;
    }

    /*
     * This inode was originally created to hold a block that was restored
     * before the owning inode. If the flag is still set, it means we never
     * restored the inode from disk and so this entry should be deleted.
     */
    if (nffs_inode_getflags(inode_entry, NFFS_INODE_FLAG_DUMMYINOBLK)) {
        *out_should_sweep = 2;
        inode_entry->nie_refcnt = 1;
        assert(inode_entry->nie_refcnt >= 1);
        return 0;
    }

    /*
     * Determine if the inode is a dummy. Dummy inodes have a flash
     * location set to LOC_NONE and should have a flag set for the reason.
     * The presence of a dummy inode during the final sweep step indicates
     * file system corruption.  It's assumed that directories have
     * previously migrated all children to /lost+found.
     */
    if (nffs_inode_is_dummy(inode_entry)) {
        *out_should_sweep = 3;
        nffs_inode_inc_refcnt(inode_entry);
        assert(inode_entry->nie_refcnt >= 1);
        return 0;
    }

    /* Determine if the inode has been deleted.  If an inode has no parent (and
     * it isn't the root directory), it has been deleted from the disk and
     * should be swept from the RAM representation.
     */
    if (inode_entry->nie_hash_entry.nhe_id != NFFS_ID_ROOT_DIR) {
        rc = nffs_inode_from_entry(&inode, inode_entry);
        if (rc != 0 && rc != FS_ENOENT) {
            *out_should_sweep = 0;
            return rc;
        }
        if (inode.ni_parent == NULL) {
            *out_should_sweep = 4;
            return 0;
        }
    }

    /*
     * If this inode has been marked as deleted, we can unlink it here.
     *
     * XXX Note that the record of a deletion could be lost if garbage
     * collection erases the delete but leaves inode updates on other
     * partitions which can then be restored.
     */
    if (nffs_inode_getflags(inode_entry, NFFS_INODE_FLAG_DELETED)) {
        rc = nffs_inode_from_entry(&inode, inode_entry);
        if (rc != 0) {
            *out_should_sweep = 0;
            return rc;
        }
        *out_should_sweep = 5;
    }

    /* If this is a file inode, verify that all of its constituent blocks are
     * present.
     */
    if (nffs_hash_id_is_file(inode_entry->nie_hash_entry.nhe_id)) {
        rc = nffs_restore_validate_block_chain(
                inode_entry->nie_last_block_entry);
        if (rc == FS_ECORRUPT) {
            *out_should_sweep = 6;
            return 0;
        } else if (rc == FS_ENOENT) {
            *out_should_sweep = 7;
            return 0;
        } else if (rc != 0) {
            *out_should_sweep = 0;
            return rc;
        }
    }

    /* This is a valid inode; don't sweep it. */
    *out_should_sweep = 0;
    return 0;
}