hardlink fixes
authorEric Biggers <ebiggers3@gmail.com>
Sun, 19 Aug 2012 07:32:33 +0000 (02:32 -0500)
committerEric Biggers <ebiggers3@gmail.com>
Sun, 19 Aug 2012 07:32:33 +0000 (02:32 -0500)
src/dentry.h
src/hardlink.c

index f684a7a0340f25ff3887e127a5f429a589dbe7c2..251e86f6034c235a8323d5c0ce194114a95266dc 100644 (file)
@@ -215,12 +215,12 @@ static inline const u8 *dentry_hash(const struct dentry *dentry)
 
 static inline size_t dentry_link_group_size(const struct dentry *dentry)
 {
+       const struct list_head *cur = &dentry->link_group_list;
        size_t size = 0;
-       struct list_head *list;
-       list_for_each(list, &dentry->link_group_list)
+       do {
                size++;
-       if (size == 0)
-               size = 1;
+               cur = cur->next;
+       } while (cur != &dentry->link_group_list);
        return size;
 }
 
index a5d8b9fae05fae57f56dae0fab55262bcb9456ef..81eb10d4d54b529630cc6602e00083e41a16b71e 100644 (file)
@@ -6,7 +6,7 @@
 struct link_group {
        u64 link_group_id;
        struct link_group *next;
-       struct list_head dentry_list;
+       struct list_head *dentry_list;
 };
 
 struct link_group_table {
@@ -46,7 +46,7 @@ int link_group_table_insert(struct dentry *dentry, struct link_group_table *tabl
        group = table->array[pos];
        while (group) {
                if (group->link_group_id == dentry->hard_link) {
-                       list_add(&dentry->link_group_list, &group->dentry_list);
+                       list_add(&dentry->link_group_list, group->dentry_list);
                        return 0;
                }
                group = group->next;
@@ -59,8 +59,8 @@ int link_group_table_insert(struct dentry *dentry, struct link_group_table *tabl
                return WIMLIB_ERR_NOMEM;
        group->link_group_id   = dentry->hard_link;
        group->next            = table->array[pos];
-       INIT_LIST_HEAD(&group->dentry_list);
-       list_add(&dentry->link_group_list, &group->dentry_list);
+       INIT_LIST_HEAD(&dentry->link_group_list);
+       group->dentry_list = &dentry->link_group_list;
        table->array[pos]      = group;
 
        /* XXX Make the table grow when too many entries have been inserted. */
@@ -100,26 +100,30 @@ u64 assign_link_groups(struct link_group_table *table)
                struct dentry *dentry;
                while (group) {
                        next_group = group->next;
-                       if (list_is_singular(&group->dentry_list)) {
+                       u64 cur_id;
+                       struct list_head *dentry_list = group->dentry_list;
+                       if (dentry_list->next == dentry_list) {
                                /* Hard link group of size 1.  Change the hard
                                 * link ID to 0 and discard the link_group */
-                               dentry = container_of(group->dentry_list.next,
-                                                     struct dentry,
-                                                     link_group_list);
-                               dentry->hard_link = 0;
+                               cur_id = 0;
                                FREE(group);
                        } else {
                                /* Hard link group of size > 1.  Assign the
                                 * dentries in the group the next available hard
                                 * link IDs and queue the group to be
                                 * re-inserted into the table. */
-                               list_for_each_entry(dentry, &group->dentry_list,
-                                                   link_group_list)
-                                       dentry->hard_link = id;
+                               cur_id = id++;
                                group->next = remaining_groups;
                                remaining_groups = group;
-                               id++;
                        }
+                       struct list_head *cur = dentry_list;
+                       do {
+                               dentry = container_of(cur,
+                                                     struct dentry,
+                                                     link_group_list);
+                               dentry->hard_link = cur_id;
+                               cur = cur->next;
+                       } while (cur != dentry_list);
                        group = next_group;
                }
        }