From: NeilBrown Date: Sun, 10 Oct 2010 22:58:36 +0000 (+1100) Subject: Use igrab_fs to hod refcounts on the inodes of orphans. X-Git-Url: http://git.neil.brown.name/?a=commitdiff_plain;h=b6a897fa60c5a8542af83ae6ec6c3c1132375e63;p=LaFS.git Use igrab_fs to hod refcounts on the inodes of orphans. We currently hold a refcount on the inodes of dir orphans. We need the filesystem (super_block) as well. Also, while we don't really need a similar refcount for inode orphans, it doesn't hurt. So simplify the tracking of whether we need to take such a refcount, use iget_fs to grab the super_block as well, and also take a ref in lafs_add_orphans, which was missing. Signed-off-by: NeilBrown --- diff --git a/dir.c b/dir.c index e1555f6..bb8b3d1 100644 --- a/dir.c +++ b/dir.c @@ -432,7 +432,7 @@ dir_delete_prepare(struct fs *fs, struct inode *dir, unmap_dblock(dirblk, buf); } if (orphan) - return lafs_make_orphan(fs, doh->dirent_block, dir); + return lafs_make_orphan(fs, doh->dirent_block); return 0; } @@ -768,7 +768,7 @@ lafs_unlink(struct inode *dir, struct dentry *de) if (IS_ERR(inodb)) err = PTR_ERR(inodb); if (last && !err) - err = lafs_make_orphan(fs, inodb, NULL); + err = lafs_make_orphan(fs, inodb); if (err) goto abort; lafs_iolock_block(&inodb->b); @@ -861,7 +861,7 @@ lafs_rmdir(struct inode *dir, struct dentry *de) if (IS_ERR(inodb)) err = PTR_ERR(inodb); if (!err) - err = lafs_make_orphan(fs, inodb, NULL); + err = lafs_make_orphan(fs, inodb); if (err) goto abort; lafs_iolock_block(&inodb->b); @@ -1188,7 +1188,7 @@ lafs_rename(struct inode *old_dir, struct dentry *old_dentry, if (IS_ERR(newdb)) err = PTR_ERR(newdb); if (last && !err) - err = lafs_make_orphan(fs, newdb, NULL); + err = lafs_make_orphan(fs, newdb); lafs_iolock_block(&newdb->b); set_bit(B_PinPending, &newdb->b.flags); lafs_iounlock_block(&newdb->b); @@ -1342,7 +1342,7 @@ int lafs_dir_handle_orphan(struct datablock *b) * space being tight. * just try again */ - lafs_orphan_release(fs, b, dir); + lafs_orphan_release(fs, b); err = 0; goto abort; } @@ -1423,7 +1423,7 @@ int lafs_dir_handle_orphan(struct datablock *b) if (lafs_dir_find(buf2, bits, seed, (hash-1) & MaxDirHash, &piece) && lafs_dir_extract(buf2, bits, &de, piece, NULL)->target == 0) - err = lafs_make_orphan_nb(fs, b2, dir); + err = lafs_make_orphan_nb(fs, b2); unmap_dblock(b2, buf2); putdref(b2, MKREF(dir_orphan)); b2 = NULL; @@ -1474,7 +1474,7 @@ int lafs_dir_handle_orphan(struct datablock *b) } else unmap_dblock(b, buf); - lafs_orphan_release(fs, b, dir); + lafs_orphan_release(fs, b); err = 0; abort: diff --git a/inode.c b/inode.c index 857ea60..8b13b4a 100644 --- a/inode.c +++ b/inode.c @@ -815,9 +815,9 @@ int lafs_inode_handle_orphan(struct datablock *b) LAFSI(ino)->ciblocks + LAFSI(ino)->piblocks); if (lafs_erase_dblock_async(b)) - lafs_orphan_release(fs, b, NULL); + lafs_orphan_release(fs, b); } else if (ino->i_nlink || LAFSI(ino)->type == 0) - lafs_orphan_release(fs, b, NULL); + lafs_orphan_release(fs, b); else lafs_orphan_forget(fs, b); return 0; @@ -1535,7 +1535,7 @@ inode_map_new_abort(struct inode_map_new_info *imni) clear_bit(B_Claimed, &imni->ib->b.flags); clear_bit(B_PinPending, &imni->ib->b.flags); lafs_orphan_release(fs_from_inode(imni->ib->b.inode), - imni->ib, NULL); + imni->ib); } putdref(imni->ib, MKREF(cfi_ino)); if (imni->mb) { @@ -1568,7 +1568,7 @@ lafs_new_inode(struct fs *fs, struct super_block *sb, struct inode *dir, err = lafs_cluster_update_prepare(&ui, fs, sizeof(struct la_inode)) ?: err; if (err == 0) - err = lafs_make_orphan(fs, imni.ib, NULL); + err = lafs_make_orphan(fs, imni.ib); if (err) goto abort; retry: @@ -1745,7 +1745,7 @@ void lafs_truncate(struct inode *ino) * If this doesn't get registered as an orphan .... maybe * it will have to wait until something else truncates it. */ - lafs_make_orphan(fs, db, NULL); + lafs_make_orphan(fs, db); if (!test_and_set_bit(I_Trunc, &LAFSI(ino)->iflags)) igrab(ino); diff --git a/lafs.h b/lafs.h index e52a168..c6c0bb2 100644 --- a/lafs.h +++ b/lafs.h @@ -706,9 +706,9 @@ unsigned long long lafs_checkpoint_start(struct fs *fs); unsigned long lafs_do_checkpoint(struct fs *fs); struct block *lafs_get_flushable(struct fs *fs, int phase); -int lafs_make_orphan(struct fs *fs, struct datablock *db, struct inode *ino); -int lafs_make_orphan_nb(struct fs *fs, struct datablock *db, struct inode *ino); -void lafs_orphan_release(struct fs *fs, struct datablock *b, struct inode *ino); +int lafs_make_orphan(struct fs *fs, struct datablock *db); +int lafs_make_orphan_nb(struct fs *fs, struct datablock *db); +void lafs_orphan_release(struct fs *fs, struct datablock *db); long lafs_run_orphans(struct fs *fs); void lafs_add_orphan(struct fs *fs, struct datablock *db); void lafs_orphan_forget(struct fs *fs, struct datablock *db); diff --git a/orphan.c b/orphan.c index 9e93676..8a09b09 100644 --- a/orphan.c +++ b/orphan.c @@ -170,6 +170,7 @@ static void orphan_commit(struct fs *fs, struct datablock *b, struct datablock * b->orphan_slot = om->nextfree++; set_bit(B_Orphan, &b->b.flags); getdref(b, MKREF(orphan_flag)); + lafs_igrab_fs(b->b.inode); lafs_add_orphan(fs, b); dprintk("%p->orphan_slot=%d (%lu,%lu,%lu) %s\n", b, b->orphan_slot, @@ -238,7 +239,7 @@ static void orphan_abort(struct fs *fs) * For directories, i_mutex is used for this. * For inodes, B_IOLock is used. */ -int lafs_make_orphan(struct fs *fs, struct datablock *db, struct inode *ino) +int lafs_make_orphan(struct fs *fs, struct datablock *db) { int err; struct datablock *ob; @@ -261,18 +262,16 @@ retry: if (IS_ERR(ob)) { orphan_abort(fs); err = PTR_ERR(ob); - } else { + } else orphan_commit(fs, db, ob); - if (ino) - igrab(ino); - } + mutex_unlock(&fs->orphans->i_mutex); lafs_checkpoint_unlock(fs); return err; } /* non-blocking version of make_orphan */ -int lafs_make_orphan_nb(struct fs *fs, struct datablock *db, struct inode *ino) +int lafs_make_orphan_nb(struct fs *fs, struct datablock *db) { int err; struct datablock *ob; @@ -293,11 +292,9 @@ int lafs_make_orphan_nb(struct fs *fs, struct datablock *db, struct inode *ino) if (IS_ERR(ob)) { orphan_abort(fs); err = PTR_ERR(ob); - } else { + } else orphan_commit(fs, db, ob); - if (ino) - igrab(ino); - } + mutex_unlock(&fs->orphans->i_mutex); lafs_checkpoint_unlock(fs); return err; @@ -320,7 +317,7 @@ static void lafs_drop_orphan(struct fs *fs, struct datablock *db); * like a spinlock, and erase_dblock should not block as the block * should be PinPending; */ -void lafs_orphan_release(struct fs *fs, struct datablock *b, struct inode *ino) +void lafs_orphan_release(struct fs *fs, struct datablock *b) { struct datablock *ob1, *ob2; int shift = b->b.inode->i_blkbits - 4; @@ -434,7 +431,7 @@ again: om->nextfree--; om->reserved++; clear_bit(B_Orphan, &b->b.flags); - iput(ino); + lafs_iput_fs(b->b.inode); lafs_drop_orphan(fs, b); putdref(b, MKREF(orphan_flag)); @@ -713,6 +710,7 @@ void lafs_add_orphans(struct fs *fs, struct inode *ino, int count) getdref(ob, MKREF(orphan_flag)); getdref(db, MKREF(orphan)); ob->orphan_slot = bslot + slot; + lafs_igrab_fs(ob->b.inode); lafs_add_orphan(fs, ob); } else or[slot].type = 0;