From: NeilBrown Date: Sat, 31 Jul 2010 00:00:22 +0000 (+1000) Subject: Break linkage between inode and dblock at earliest opportunity. X-Git-Url: http://git.neil.brown.name/?a=commitdiff_plain;h=b858851d50fc1b79008f956deb8c9d22057239d7;p=LaFS.git Break linkage between inode and dblock at earliest opportunity. clear_inode is the first chance to break this linkage, so do it there. It is still possible for lafs_iget to get a new inode before clear_inode has completed, so we need to do the same test/clear in lafs_iget if b->my_inode is found to be non-NULL; Signed-off-by: NeilBrown --- diff --git a/index.c b/index.c index 4c86d6a..ceda443 100644 --- a/index.c +++ b/index.c @@ -1053,6 +1053,7 @@ void lafs_refile(struct block *b, int dec) test_bit(I_Destroyed, &LAFSI(in)->iflags))) { dblk(b)->my_inode = NULL; LAFSI(in)->dblock = NULL; + LAFSI(in)->iblock = NULL; spin_unlock(&lafs_hash_lock); if (test_bit(I_Destroyed, &LAFSI(in)->iflags)) lafs_destroy_inode(in); diff --git a/inode.c b/inode.c index 0db0b49..52f5d99 100644 --- a/inode.c +++ b/inode.c @@ -65,6 +65,7 @@ lafs_iget(struct super_block *sb, ino_t inum, int async) { /* find, and load if needed, this inum */ struct inode *ino = NULL; + struct inode *oldino; struct datablock *b = NULL; struct inode *inodefile; struct sb_key *k; @@ -155,15 +156,25 @@ lafs_iget(struct super_block *sb, ino_t inum, int async) if (err) goto err; - if (b->my_inode) { + oldino = b->my_inode; + if (oldino) { /* The inode is new, but the block thinks it has an * old inode, so we must be in the process of destroying * the old one. * So fail the lookup without even looking at the content * of the block (Which might not be clear yet). */ - err = -ENOENT; - goto err; + spin_lock(&oldino->i_data.private_lock); + if (!test_bit(I_Deleting, &LAFSI(oldino)->iflags)) { + b->my_inode = NULL; + LAFSI(oldino)->dblock = NULL; + LAFSI(oldino)->iblock = NULL; + } + spin_unlock(&oldino->i_data.private_lock); + if (b->my_inode) { + err = -ENOENT; + goto err; + } } err = lafs_import_inode(ino, b); @@ -578,6 +589,24 @@ void lafs_clear_inode(struct inode *ino) li->type = 0; + /* Now is a good time to break the linkage between + * inode and dblock - but node if the file is + * being deleted + */ + if (!test_bit(I_Deleting, &LAFSI(ino)->iflags)) { + struct datablock *db; + spin_lock(&ino->i_data.private_lock); + db = LAFSI(ino)->dblock; + if (db) { + struct indexblock *ib = LAFSI(ino)->iblock; + LAFS_BUG(ib && atomic_read(&ib->b.refcnt), &db->b); + db->my_inode = NULL; + LAFSI(ino)->dblock = NULL; + LAFSI(ino)->iblock = NULL; + } + spin_unlock(&ino->i_data.private_lock); + } + /* FIXME release quota inodes if filesystem */ }