/** * 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; }