goto abort_unlock;
ino->i_nlink = 1;
+ lafs_add_orphan(fs, db);
LAFSI(ino)->md.file.parent = dir->i_ino;
lafs_dirty_inode(ino);
lafs_inode_checkpin(ino);
ino->i_ino, DT_REG);
lafs_checkpoint_unlock(fs);
d_instantiate(de, ino); /* FIXME do I need to iput?? */
- lafs_orphan_release(fs, db);
clear_bit(B_PinPending, &db->b.flags);
putdref(db, MKREF(inode_new));
return 0;
ino->i_nlink = 1;
LAFSI(ino)->md.file.parent = dir->i_ino;
+ lafs_add_orphan(fs, inodb);
buf = map_dblock(b);
memcpy(buf, symlink, l);
ino->i_ino, DT_LNK);
lafs_checkpoint_unlock(fs);
d_instantiate(de, ino);
- lafs_orphan_release(fs, inodb);
putdref(inodb, MKREF(inode_new));
return 0;
abort_unlock:
lafs_dirty_inode(ino);
lafs_inode_checkpin(dir);
lafs_inode_checkpin(ino);
- lafs_orphan_release(fs, inodb);
+ lafs_add_orphan(fs, inodb);
dir_create_commit(&doh, fs, dir, de->d_name.name, de->d_name.len,
ino->i_ino, DT_DIR);
d_instantiate(de, ino);
LAFSI(ino)->md.file.parent = dir->i_ino;
ino->i_nlink = 1;
+ lafs_add_orphan(fs, inodb);
lafs_dirty_inode(ino);
lafs_inode_checkpin(ino);
ino->i_ino, type);
lafs_checkpoint_unlock(fs);
d_instantiate(de, ino);
- lafs_orphan_release(fs, inodb);
clear_bit(B_PinPending, &inodb->b.flags);
putdref(inodb, MKREF(inode_new));
return 0;
dprintk("DELETE INODE %d\n", (int)ino->i_ino);
spin_lock(&ino->i_data.private_lock);
b = LAFSI(ino)->dblock;
+ /* FIXME we use b unconditionally, so either we don't
+ * need the test, or we need to make the block if it
+ * doesn't exist.. */
if (b)
getdref_locked(b, MKREF(delete_inode));
spin_unlock(&ino->i_data.private_lock);
set_bit(I_Deleting, &LAFSI(ino)->iflags);
set_bit(B_Claimed, &b->b.flags);
+ lafs_add_orphan(fs, b);
inode_map_free(fs, LAFSI(ino)->filesys, ino->i_ino);
// FIXME what to do on error (-ENOMEM )
restart:
if (!test_bit(I_Trunc, &LAFSI(ino)->iflags)) {
- if (ino->i_nlink == 0) {
- LAFS_BUG(LAFSI(ino)->type != 0, &b->b);
+ if (test_bit(I_Deleting, &LAFSI(ino)->iflags)) {
+ LAFS_BUG(ino->i_nlink, &b->b);
lafs_erase_dblock(b);
clear_bit(I_Deleting, &LAFSI(ino)->iflags);
- }
- lafs_orphan_release(fs, b);
+ } else if (ino->i_nlink)
+ lafs_orphan_release(fs, b);
+ else
+ lafs_orphan_forget(fs, b);
return;
}
void lafs_orphan_release(struct fs *fs, struct datablock *b);
long lafs_run_orphans(struct fs *fs);
int lafs_drop_orphan(struct fs *fs, struct datablock *db);
+void lafs_add_orphan(struct fs *fs, struct datablock *db);
+void lafs_orphan_forget(struct fs *fs, struct datablock *db);
struct datablock *lafs_find_orphan(struct inode *ino);
/* Segment.c */
}
}
+void lafs_add_orphan(struct fs *fs, struct datablock *db)
+{
+ /* This block is an orphan block but might not be
+ * on the list any more.
+ * It now needs orphan processing (probably nlink
+ * has changed, or I_Deleting), so put it back
+ * on the list.
+ */
+ LAFS_BUG(!test_bit(B_Orphan, &db->b.flags), &db->b);
+ spin_lock(&fs->lock);
+ if (list_empty(&db->orphans)) {
+ list_add_tail(&db->orphans, &fs->pending_orphans);
+ getdref(db, MKREF(orphan_list));
+ }
+ spin_unlock(&fs->lock);
+}
+
+void lafs_orphan_forget(struct fs *fs, struct datablock *db)
+{
+ /* This is still and orphan, but we don't want to handle
+ * it just now. When we we, lafs_add_orphan will be called */
+ LAFS_BUG(!test_bit(B_Orphan, &db->b.flags), &db->b);
+ spin_lock(&fs->lock);
+ if (!list_empty(&db->orphans)) {
+ list_del_init(&db->orphans);
+ spin_unlock(&fs->lock);
+ putdref(db, MKREF(orphan_list));
+ } else
+ spin_unlock(&fs->lock);
+}
+
struct datablock *lafs_find_orphan(struct inode *ino)
{
/* I could walk the child tree of the inode, or