This was never "right" and is confusing orphan handling.
We should not lose those blocks anymore but if we do we need a better
fix.
abort:
lafs_cluster_update_abort(&uh);
dir_create_abort(&doh);
- /* This is needed because import_inode sets it to 1
- * to avoid something silly. Needs FIXME */
- ino->i_nlink = 0;
iput(ino);
clear_bit(B_PinPending, &db->b.flags);
putdref(db, MKREF(inode_new));
clear_bit(B_PinPending, &b->b.flags);
putdref(b, MKREF(symlink));
dir_create_abort(&doh);
- /* This is needed because import_inode sets it to 1
- * to avoid something silly. Needs FIXME */
- ino->i_nlink = 0;
lafs_cluster_update_abort(&uh);
iput(ino);
return err;
abort:
dir_create_abort(&doh);
lafs_cluster_update_abort(&uh);
- /* This is needed because import_inode sets it to 1
- * to avoid something silly. Needs FIXME */
- ino->i_nlink = 0;
- iput(ino);
+ iput(ino);
clear_bit(B_PinPending, &inodb->b.flags);
putdref(inodb, MKREF(inode_new));
return err;
abort:
dir_create_abort(&doh);
lafs_cluster_update_abort(&uh);
- /* This is needed because import_inode sets it to 1
- * to avoid something silly. Needs FIXME */
- ino->i_nlink = 0;
iput(ino);
clear_bit(B_PinPending, &inodb->b.flags);
putdref(inodb, MKREF(inode_new));
ino->i_size = le64_to_cpu(l->size);
i->parent = le32_to_cpu(l->parent);
ino->i_nlink = le32_to_cpu(l->linkcount);
-/*FIXME when rollforward finds nlink=0 inode,
- it keeps losing them... */
-if (!ino->i_nlink) ino->i_nlink = 1;
+ if (ino->i_nlink == 0 && list_empty(&b->orphans)) {
+ /* Pop this block on the orphan list just in case */
+ struct fs *fs = fs_from_inode(ino);
+ spin_lock(&fs->lock);
+ if (list_empty(&b->orphans)) {
+ list_add_tail(&b->orphans, &fs->pending_orphans);
+ getdref(b, MKREF(orphan_list));
+ }
+ spin_unlock(&fs->lock);
+ }
dprintk(" mode = 0%o uid %d size %lld\n",
ino->i_mode, ino->i_uid, ino->i_size);
memcpy(buf+offset, data, len);
unmap_dblock(db, buf);
err = lafs_import_inode(inode, db);
+ /* WE borrow the orphan list to keep a reference on
+ * this inode until all processing is finished
+ * to make sure inodes that are about to get linked
+ * to get deleted early
+ */
+ if (list_empty(&db->orphans)) {
+ list_add(&db->orphans, &fs->pending_orphans);
+ igrab(inode);
+ getdref(db, MKREF(roll_orphan));
+ }
putdref(db, MKREF(roll));
break;
}
put_page(p);
put_page(pg);
kfree(buf);
+
+ /* Now we release all the nlink==0 inode that we found */
+ while (!list_empty(&fs->pending_orphans)) {
+ struct datablock *db = list_entry(fs->pending_orphans.next,
+ struct datablock,
+ orphans);
+ list_del_init(&db->orphans);
+ iput(db->my_inode);
+ putdref(db, MKREF(roll_orphan));
+ }
fs->rolled = 1;
return err;
}