The number of inodes examined is limited by MAX_OPEN_FILES, and we can
make it faster in the common case by checking i_num_streams.
/* Number of dentries that are aliases for this inode. */
u32 i_nlink : 30;
/* Number of dentries that are aliases for this inode. */
u32 i_nlink : 30;
- /* Flag used to mark this inode as visited; this is used when visiting
- * all the inodes in a dentry tree exactly once. It will be 0 by
- * default and must be cleared following the tree traversal, even in
- * error paths. */
+ /* Flag used by some code to mark this inode as visited. It will be 0
+ * by default, and it always must be cleared after use. */
u32 i_visited : 1;
/* Cached value */
u32 i_visited : 1;
/* Cached value */
static ntfs_inode *
ntfs_3g_open_inode(struct wim_inode *inode, struct ntfs_3g_apply_ctx *ctx)
{
static ntfs_inode *
ntfs_3g_open_inode(struct wim_inode *inode, struct ntfs_3g_apply_ctx *ctx)
{
- if (inode->i_visited) {
- for (u32 i = 0; i < ctx->num_open_inodes; i++) {
+ /* If the same blob is being extracted to multiple streams of the same
+ * inode, then we must only open the inode once. */
+ if (unlikely(inode->i_num_streams > 1)) {
+ for (unsigned i = 0; i < ctx->num_open_inodes; i++) {
if (ctx->open_inodes[i]->mft_no == inode->i_mft_no) {
ni = ctx->open_inodes[i];
if (ctx->open_inodes[i]->mft_no == inode->i_mft_no) {
ni = ctx->open_inodes[i];
- if (!ni) {
- ni = ntfs_inode_open(ctx->vol, inode->i_mft_no);
- ctx->open_inodes[ctx->num_open_inodes++] = ni;
- inode->i_visited = 1;
- }
+ ni = ntfs_inode_open(ctx->vol, inode->i_mft_no);
+ if (unlikely(!ni)) {
ERROR_WITH_ERRNO("Can't open \"%s\" in NTFS volume",
dentry_full_path(
inode_first_extraction_dentry(inode)));
return NULL;
}
ERROR_WITH_ERRNO("Can't open \"%s\" in NTFS volume",
dentry_full_path(
inode_first_extraction_dentry(inode)));
return NULL;
}
+
+have_inode:
+ ctx->open_inodes[ctx->num_open_inodes++] = ni;
out_cleanup:
ntfs_3g_cleanup_blob_extract(ctx);
out:
out_cleanup:
ntfs_3g_cleanup_blob_extract(ctx);
out:
- for (u32 i = 0; i < blob->out_refcnt; i++)
- targets[i].inode->i_visited = 0;