From: NeilBrown Date: Wed, 2 Sep 2009 00:09:52 +0000 (+1000) Subject: Remove special handling for i_nlink when reading inodes. X-Git-Url: http://git.neil.brown.name/?a=commitdiff_plain;h=f0ddcc2c1d2c8c49942bddac0781d4c8d57c482e;p=LaFS.git Remove special handling for i_nlink when reading inodes. 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. --- diff --git a/dir.c b/dir.c index 7ee11b5..e336ef8 100644 --- a/dir.c +++ b/dir.c @@ -620,9 +620,6 @@ lafs_create(struct inode *dir, struct dentry *de, int mode, 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)); @@ -907,9 +904,6 @@ lafs_symlink(struct inode *dir, struct dentry *de, 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; @@ -972,10 +966,7 @@ lafs_mkdir(struct inode *dir, struct dentry *de, int mode) 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; @@ -1051,9 +1042,6 @@ lafs_mknod(struct inode *dir, struct dentry *de, int mode, 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)); diff --git a/inode.c b/inode.c index d6e916d..4bf4fda 100644 --- a/inode.c +++ b/inode.c @@ -203,9 +203,16 @@ lafs_import_inode(struct inode *ino, struct datablock *b) 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); diff --git a/roll.c b/roll.c index 934f9d7..f2bea8f 100644 --- a/roll.c +++ b/roll.c @@ -219,6 +219,16 @@ roll_mini(struct fs *fs, int fsnum, int inum, int trunc, int flg, 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; } @@ -507,6 +517,16 @@ static int roll_forward(struct fs *fs) 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; }