]> git.neil.brown.name Git - LaFS.git/commitdiff
Remove special handling for i_nlink when reading inodes.
authorNeilBrown <neilb@suse.de>
Wed, 2 Sep 2009 00:09:52 +0000 (10:09 +1000)
committerNeilBrown <neilb@suse.de>
Wed, 2 Sep 2009 00:09:52 +0000 (10:09 +1000)
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.

dir.c
inode.c
roll.c

diff --git a/dir.c b/dir.c
index 7ee11b5dc2ce188bbefcf8fc5acdd85b721d1103..e336ef8c6aec4fba72806a2c008799d3b8786021 100644 (file)
--- 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 d6e916d4090283040c2dcc89c84c25c536446f58..4bf4fda44f5f12360f46da752720ef5b945c4a42 100644 (file)
--- 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 934f9d7a37fd28ed07420919c0f3bfff246b12b3..f2bea8fc7a9f7aea70796541eb22ebbc1a8580cc 100644 (file)
--- 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;
 }