ino->i_size = le64_to_cpu(l->size);
i->parent = le32_to_cpu(l->parent);
ino->i_nlink = le32_to_cpu(l->linkcount);
- if (ino->i_nlink == 0 && list_empty(&b->orphans)) {
+ if (ino->i_nlink == 0 && list_empty(&b->orphans) &&
+ fs_from_inode(ino)->rolled) {
/* This block should already be on the orphan
* list, otherwise there is a filesystem
* inconsistency.
* linkcount is wrong.
* It is safest to assume the later - either
* way an FS check would be needed to fix it.
+ * Note: while roll-forward is happening, this
+ * situation is perfectly possible and is handled
+ * correctly.
*/
/* FIXME set a superblock flag requesting
* directory linkage checking
{
struct inode *inode;
struct lafs_inode *li;
- struct datablock *db;
+ struct datablock *db = NULL;
int err = 0;
void *buf;
err = PTR_ERR(db);
break;
}
+ /* Should normally iolock the block, but we don't
+ * need that during roll-forward */
+ set_bit(B_PinPending, &db->b.flags);
+ lafs_pin_dblock(db, CleanSpace);
/* Make sure block is in-sync with inode */
lafs_inode_fillblock(inode);
buf = map_dblock(db);
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);
- lafs_igrab_fs(inode);
- getdref(db, MKREF(roll_orphan));
- }
- putdref(db, MKREF(roll));
+ lafs_dirty_dblock(db);
break;
case TypeDir:
BUG();
break;
}
+ /* 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
+ * don't get deleted early
+ */
+ if (inode->i_nlink == 0) {
+ if (!db)
+ db = lafs_inode_get_dblock(inode, MKREF(roll));
+ if (db &&
+ list_empty(&db->orphans)) {
+ list_add(&db->orphans, &fs->pending_orphans);
+ lafs_igrab_fs(inode);
+ getdref(db, MKREF(roll_orphan));
+ }
+ }
+ putdref(db, MKREF(roll));
lafs_iput_fs(inode);
return err;
}
}
if (blk)
putdref(blk, MKREF(roll));
+
+ if (inode->i_nlink == 0) {
+ struct datablock *db = lafs_inode_get_dblock(inode, MKREF(roll));
+ if (db &&
+ list_empty(&db->orphans)) {
+ list_add(&db->orphans, &fs->pending_orphans);
+ lafs_igrab_fs(inode);
+ getdref(db, MKREF(roll_orphan));
+ }
+ putdref(db, MKREF(roll));
+ }
lafs_iput_fs(inode);
dprintk("leaving with error %d\n", err);
return err;