* i_nlink dentries in this list. */
struct list_head i_dentry;
- /* Field to place this inode into a list. */
- union {
- /* Hash list node- used in inode_fixup.c when the inodes are
- * placed into a hash table keyed by inode number and optionally
- * device number, in order to detect dentries that are aliases
- * for the same inode. */
- struct hlist_node i_hlist;
-
- /* Normal list node- used to connect all the inodes of a WIM
- * image into a single linked list referenced from the `struct
- * wim_image_metadata' for that image. */
- struct list_head i_list;
- };
+ /* Field to place this inode into a list. While reading a WIM image or
+ * adding files to a WIM image this is owned by the inode table;
+ * otherwise this links the inodes for the WIM image. */
+ struct hlist_node i_hlist;
/* Number of dentries that are aliases for this inode. */
u32 i_nlink;
/* inode_fixup.c */
extern int
-dentry_tree_fix_inodes(struct wim_dentry *root, struct list_head *inode_list);
+dentry_tree_fix_inodes(struct wim_dentry *root, struct hlist_head *inode_list);
#endif /* _WIMLIB_INODE_H */
struct wim_dentry;
-/* Hash table to find inodes, given an inode number (in the case of reading
- * a WIM images), or both an inode number and a device number (in the case of
- * capturing a WIM image). */
+/* Hash table to find inodes for hard link detection, given an inode number (in
+ * the case of reading a WIM image), or both an inode number and a device number
+ * (in the case of adding files to a WIM image). Also contains an extra list to
+ * hold inodes for which no additional hard link detection is desired. In both
+ * cases the inodes are linked by i_hlist. */
struct wim_inode_table {
- /* Fields for the hash table */
struct hlist_head *array;
size_t num_entries;
size_t capacity;
-
- /*
- * Linked list of "extra" inodes. These may be:
- *
- * - inodes with link count 1, which are all allowed to have 0 for their
- * inode number, meaning we cannot insert them into the hash table.
- *
- * - Groups we create ourselves by splitting a nominal inode due to
- * inconsistencies in the dentries. These inodes will share an inode
- * number with some other inode until assign_inode_numbers() is
- * called.
- */
- struct list_head extra_inodes;
+ struct hlist_head extra_inodes;
};
extern void
inode_table_prepare_inode_list(struct wim_inode_table *table,
- struct list_head *head);
+ struct hlist_head *head);
extern void
destroy_inode_table(struct wim_inode_table *table);
struct blob_descriptor *metadata_blob;
/* Linked list of 'struct wim_inode's for this image. */
- struct list_head inode_list;
+ struct hlist_head inode_list;
/* Linked list of 'struct blob_descriptor's for blobs that are
* referenced by this image's dentry tree, but have not had their SHA-1
/* Iterate over each inode in a WIM image */
#define image_for_each_inode(inode, imd) \
- list_for_each_entry(inode, &(imd)->inode_list, i_list)
+ hlist_for_each_entry(inode, &(imd)->inode_list, i_hlist)
+
+/* Iterate over each inode in a WIM image (safe against inode removal) */
+#define image_for_each_inode_safe(inode, tmp, imd) \
+ hlist_for_each_entry_safe(inode, tmp, &(imd)->inode_list, i_hlist)
/* Iterate over each blob in a WIM image that has not yet been hashed */
#define image_for_each_unhashed_blob(blob, imd) \
inode->i_security_id = -1;
/*inode->i_nlink = 0;*/
inode->i_not_rpfixed = 1;
- INIT_LIST_HEAD(&inode->i_list);
INIT_LIST_HEAD(&inode->i_dentry);
inode->i_streams = inode->i_embedded_streams;
if (set_timestamps) {
FREE(inode->i_streams);
if (inode->i_extra)
FREE(inode->i_extra);
- /* HACK: This may instead delete the inode from i_list, but hlist_del()
- * behaves the same as list_del(). */
if (!hlist_unhashed(&inode->i_hlist))
hlist_del(&inode->i_hlist);
FREE(inode);
struct wim_inode *inode;
if (d_inode->i_ino == 0) {
- list_add_tail(&d_inode->i_list, &table->extra_inodes);
+ hlist_add_head(&d_inode->i_hlist, &table->extra_inodes);
return 0;
}
return 0;
}
+static void
+hlist_move_all(struct hlist_head *src, struct hlist_head *dest)
+{
+ struct hlist_node *node;
+
+ while ((node = src->first) != NULL) {
+ hlist_del(node);
+ hlist_add_head(node, dest);
+ }
+}
+
/* Move the inodes from the 'struct wim_inode_table' to the 'inode_list'. */
static void
build_inode_list(struct wim_inode_table *inode_table,
- struct list_head *inode_list)
+ struct hlist_head *inode_list)
{
- list_splice(&inode_table->extra_inodes, inode_list);
- for (size_t i = 0; i < inode_table->capacity; i++) {
- while (!hlist_empty(&inode_table->array[i])) {
- struct wim_inode *inode;
-
- inode = hlist_entry(inode_table->array[i].first,
- struct wim_inode, i_hlist);
- hlist_del(&inode->i_hlist);
- list_add(&inode->i_list, inode_list);
- }
- }
+ hlist_move_all(&inode_table->extra_inodes, inode_list);
+ for (size_t i = 0; i < inode_table->capacity; i++)
+ hlist_move_all(&inode_table->array[i], inode_list);
}
/* Re-assign inode numbers to the inodes in the list. */
static void
-reassign_inode_numbers(struct list_head *inode_list)
+reassign_inode_numbers(struct hlist_head *inode_list)
{
struct wim_inode *inode;
u64 cur_ino = 1;
- list_for_each_entry(inode, inode_list, i_list)
+ hlist_for_each_entry(inode, inode_list, i_hlist)
inode->i_ino = cur_ino++;
}
* i_ino fields.
*/
int
-dentry_tree_fix_inodes(struct wim_dentry *root, struct list_head *inode_list)
+dentry_tree_fix_inodes(struct wim_dentry *root, struct hlist_head *inode_list)
{
struct inode_fixup_params params;
int ret;
return WIMLIB_ERR_NOMEM;
table->num_entries = 0;
table->capacity = capacity;
- INIT_LIST_HEAD(&table->extra_inodes);
+ INIT_HLIST_HEAD(&table->extra_inodes);
return 0;
}
ret = new_dentry_with_new_inode(name, false, &dentry);
if (ret)
return ret;
- list_add_tail(&dentry->d_inode->i_list, &table->extra_inodes);
+ hlist_add_head(&dentry->d_inode->i_hlist, &table->extra_inodes);
} else {
size_t pos;
*/
void
inode_table_prepare_inode_list(struct wim_inode_table *table,
- struct list_head *head)
+ struct hlist_head *head)
{
- struct wim_inode *inode, *tmp_inode;
+ struct wim_inode *inode;
struct hlist_node *tmp;
u64 cur_ino = 1;
/* Re-assign inode numbers in the existing list to avoid duplicates. */
- list_for_each_entry(inode, head, i_list)
+ hlist_for_each_entry(inode, head, i_hlist)
inode->i_ino = cur_ino++;
/* Assign inode numbers to the new inodes and move them to the image's
hlist_for_each_entry_safe(inode, tmp, &table->array[i], i_hlist) {
inode->i_ino = cur_ino++;
inode->i_devno = 0;
- list_add_tail(&inode->i_list, head);
+ hlist_add_head(&inode->i_hlist, head);
}
INIT_HLIST_HEAD(&table->array[i]);
}
- list_for_each_entry_safe(inode, tmp_inode, &table->extra_inodes, i_list)
- {
+ hlist_for_each_entry_safe(inode, tmp, &table->extra_inodes, i_hlist) {
inode->i_ino = cur_ino++;
inode->i_devno = 0;
- list_add_tail(&inode->i_list, head);
+ hlist_add_head(&inode->i_hlist, head);
}
- INIT_LIST_HEAD(&table->extra_inodes);
+ INIT_HLIST_HEAD(&table->extra_inodes);
table->num_entries = 0;
}
}
}
- list_add_tail(&new_inode->i_list,
- &wim_get_current_image_metadata(wimfs_ctx->wim)->inode_list);
+ hlist_add_head(&new_inode->i_hlist,
+ &wim_get_current_image_metadata(wimfs_ctx->wim)->inode_list);
dentry_add_child(parent, new_dentry);
static void
close_all_fds(struct wimfs_context *ctx)
{
- struct wim_inode *inode, *tmp;
+ struct wim_inode *inode;
+ struct hlist_node *tmp;
struct wim_image_metadata *imd;
imd = wim_get_current_image_metadata(ctx->wim);
- list_for_each_entry_safe(inode, tmp, &imd->inode_list, i_list)
+ image_for_each_inode_safe(inode, tmp, imd)
inode_close_fds(inode);
}
free_blob_descriptor(blob);
}
INIT_LIST_HEAD(&imd->unhashed_blobs);
- INIT_LIST_HEAD(&imd->inode_list);
+ INIT_HLIST_HEAD(&imd->inode_list);
#ifdef WITH_NTFS_3G
if (imd->ntfs_vol) {
do_ntfs_umount(imd->ntfs_vol);
imd = CALLOC(1, sizeof(*imd));
if (imd) {
imd->refcnt = 1;
- INIT_LIST_HEAD(&imd->inode_list);
+ INIT_HLIST_HEAD(&imd->inode_list);
INIT_LIST_HEAD(&imd->unhashed_blobs);
}
return imd;