/**
 * Performs a sweep of the RAM representation at the end of a successful
 * restore.  The sweep phase performs the following actions of each inode in
 * the file system:
 *     1. If the inode is a dummy directory, its children are migrated to the
 *        lost+found directory.
 *     2. Else if the inode is a dummy file, it is fully deleted from RAM.
 *     3. Else, a CRC check is performed on each of the inode's constituent
 *        blocks.  If corruption is detected, the inode is fully deleted from
 *        RAM.
 *
 * @return                      0 on success; nonzero on failure.
 */
int
nffs_restore_sweep(void)
{
    struct nffs_inode_entry *inode_entry;
    struct nffs_hash_entry *entry;
    struct nffs_hash_entry *next;
    struct nffs_hash_list *list;
    struct nffs_inode inode;
    int del;
    int rc;
    int i;

    /* Iterate through every object in the hash table, deleting all inodes that
     * should be removed.
     */
    for (i = 0; i < NFFS_HASH_SIZE; i++) {
        list = nffs_hash + i;

        entry = SLIST_FIRST(list);
        while (entry != NULL) {
            next = SLIST_NEXT(entry, nhe_next);
            if (nffs_hash_id_is_inode(entry->nhe_id)) {
                inode_entry = (struct nffs_inode_entry *)entry;

                /* If this is a dummy inode directory, the file system is
                 * corrupted.  Move the directory's children inodes to the
                 * lost+found directory.
                 */
                rc = nffs_restore_migrate_orphan_children(inode_entry);
                if (rc != 0) {
                    return rc;
                }

                /* Determine if this inode needs to be deleted. */
                rc = nffs_restore_should_sweep_inode_entry(inode_entry, &del);
                if (rc != 0) {
                    return rc;
                }

                if (del) {
                    if (inode_entry->nie_hash_entry.nhe_flash_loc ==
                        NFFS_FLASH_LOC_NONE) {

                        nffs_restore_inode_from_dummy_entry(&inode,
                                                           inode_entry);
                    } else {
                        rc = nffs_inode_from_entry(&inode, inode_entry);
                        if (rc != 0) {
                            return rc;
                        }
                    }

                    /* Remove the inode and all its children from RAM. */
                    rc = nffs_inode_unlink_from_ram(&inode, &next);
                    if (rc != 0) {
                        return rc;
                    }
                    next = SLIST_FIRST(list);
                }
            }

            entry = next;
        }
    }

    return 0;
}
/**
 * Performs a sweep of the RAM representation at the end of a successful
 * restore.  The sweep phase performs the following actions of each inode in
 * the file system:
 *     1. If the inode is a dummy directory, its children are migrated to the
 *        lost+found directory.
 *     2. Else if the inode is a dummy file, it is fully deleted from RAM.
 *     3. Else, a CRC check is performed on each of the inode's constituent
 *        blocks.  If corruption is detected, the inode is fully deleted from
 *        RAM.
 *
 * @return                      0 on success; nonzero on failure.
 */
int
nffs_restore_sweep(void)
{
    struct nffs_inode_entry *inode_entry;
    struct nffs_hash_entry *entry;
    struct nffs_hash_entry *next;
    struct nffs_hash_list *list;
    struct nffs_inode inode;
    struct nffs_block block;
    int del = 0;
    int rc;
    int i;

    /* Iterate through every object in the hash table, deleting all inodes that
     * should be removed.
     */
    for (i = 0; i < NFFS_HASH_SIZE; i++) {
        list = nffs_hash + i;

        entry = SLIST_FIRST(list);
        while (entry != NULL) {
            next = SLIST_NEXT(entry, nhe_next);
            if (nffs_hash_id_is_inode(entry->nhe_id)) {
                inode_entry = (struct nffs_inode_entry *)entry;

                /*
                 * If this is a dummy inode directory, the file system
                 * is corrupt.  Move the directory's children inodes to
                 * the lost+found directory.
                 */
                rc = nffs_restore_migrate_orphan_children(inode_entry);
                if (rc != 0) {
                    return rc;
                }

                /* Determine if this inode needs to be deleted. */
                rc = nffs_restore_should_sweep_inode_entry(inode_entry, &del);
                if (rc != 0) {
                    return rc;
                }

                rc = nffs_inode_from_entry(&inode, inode_entry);
                if (rc != 0 && rc != FS_ENOENT) {
                    return rc;
                }

                if (del) {

                    /* Remove the inode and all its children from RAM.  We
                     * expect some file system corruption; the children are
                     * subject to garbage collection and may not exist in the
                     * hash.  Remove what is actually present and ignore
                     * corruption errors.
                     */
                    rc = nffs_inode_unlink_from_ram_corrupt_ok(&inode, &next);
                    if (rc != 0) {
                        return rc;
                    }
                    next = SLIST_FIRST(list);
                }
            } else if (nffs_hash_id_is_block(entry->nhe_id)) {
                if (nffs_hash_id_is_dummy(entry->nhe_id)) {
                    del = 1;
                    nffs_block_delete_from_ram(entry);
                } else {
                    rc = nffs_block_from_hash_entry(&block, entry);
                    if (rc != 0 && rc != FS_ENOENT) {
                        del = 1;
                        nffs_block_delete_from_ram(entry);
                    }
                }
                if (del) {
                    del = 0;
                    next = SLIST_FIRST(list);
                }
            }

            entry = next;
        }
    }

    return 0;
}