From 111611dd025f086e9fd44eea619440a066a173c5 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Sun, 1 Aug 2010 13:01:10 +1000 Subject: [PATCH] hold ref to inode for directory orphans. When we directory block is an orphan, make sure we hold a reference on the inode so it cannot disappear on us. Signed-off-by: NeilBrown --- dir.c | 14 +++++++------- inode.c | 10 +++++----- lafs.h | 6 +++--- orphan.c | 19 +++++++++++++------ 4 files changed, 28 insertions(+), 21 deletions(-) diff --git a/dir.c b/dir.c index faf50ad..9a70280 100644 --- a/dir.c +++ b/dir.c @@ -411,7 +411,7 @@ dir_delete_prepare(struct fs *fs, struct inode *dir, /* FIXME should I check if the orphanage is needed * before committing this block to it? */ - err = lafs_make_orphan(fs, doh->dirent_block); + err = lafs_make_orphan(fs, doh->dirent_block, dir); return err; } @@ -746,7 +746,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); + err = lafs_make_orphan(fs, inodb, NULL); if (err) goto abort; lafs_iolock_block(&inodb->b); @@ -832,7 +832,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); + err = lafs_make_orphan(fs, inodb, NULL); if (err) goto abort; lafs_iolock_block(&inodb->b); @@ -1152,7 +1152,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); + err = lafs_make_orphan(fs, newdb, NULL); lafs_iolock_block(&newdb->b); set_bit(B_PinPending, &newdb->b.flags); lafs_iounlock_block(&newdb->b); @@ -1306,7 +1306,7 @@ int lafs_dir_handle_orphan(struct datablock *b) * space being tight. * just try again */ - lafs_orphan_release(fs, b); + lafs_orphan_release(fs, b, dir); err = 0; goto abort; } @@ -1387,7 +1387,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); + err = lafs_make_orphan_nb(fs, b2, dir); unmap_dblock(b2, buf2); putdref(b2, MKREF(dir_orphan)); b2 = NULL; @@ -1438,7 +1438,7 @@ int lafs_dir_handle_orphan(struct datablock *b) } else unmap_dblock(b, buf); - lafs_orphan_release(fs, b); + lafs_orphan_release(fs, b, dir); err = 0; abort: diff --git a/inode.c b/inode.c index b209ca2..fc978f1 100644 --- a/inode.c +++ b/inode.c @@ -752,9 +752,9 @@ int lafs_inode_handle_orphan(struct datablock *b) LAFSI(ino)->piblocks); lafs_erase_dblock(b); clear_bit(I_Deleting, &LAFSI(ino)->iflags); - lafs_orphan_release(fs, b); + lafs_orphan_release(fs, b, NULL); } else if (ino->i_nlink || LAFSI(ino)->type == 0) - lafs_orphan_release(fs, b); + lafs_orphan_release(fs, b, NULL); else lafs_orphan_forget(fs, b); return 0; @@ -1422,7 +1422,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); + imni->ib, NULL); } putdref(imni->ib, MKREF(cfi_ino)); if (imni->mb) @@ -1456,7 +1456,7 @@ lafs_new_inode(struct fs *fs, struct inode *dir, int type, int inum, int mode, err = lafs_cluster_update_prepare(&ui, fs, sizeof(struct la_inode)) ?: err; if (err == 0) - err = lafs_make_orphan(fs, imni.ib); + err = lafs_make_orphan(fs, imni.ib, NULL); if (err) goto abort; retry: @@ -1621,7 +1621,7 @@ void lafs_truncate(struct inode *ino) finish_wait(&fs->async_complete, &wq); /* FIXME there is nothing I can do with an error here */ - lafs_make_orphan(fs, db); + lafs_make_orphan(fs, db, NULL); if (!test_and_set_bit(I_Trunc, &LAFSI(ino)->iflags)) igrab(ino); diff --git a/lafs.h b/lafs.h index 1397325..675635b 100644 --- a/lafs.h +++ b/lafs.h @@ -609,9 +609,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); -int lafs_make_orphan_nb(struct fs *fs, struct datablock *db); -void lafs_orphan_release(struct fs *fs, struct datablock *b); +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); 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); diff --git a/orphan.c b/orphan.c index 8a562e9..cf30e13 100644 --- a/orphan.c +++ b/orphan.c @@ -232,7 +232,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) +int lafs_make_orphan(struct fs *fs, struct datablock *db, struct inode *ino) { int err; struct datablock *ob; @@ -255,15 +255,18 @@ 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) +int lafs_make_orphan_nb(struct fs *fs, struct datablock *db, struct inode *ino) { int err; struct datablock *ob; @@ -284,8 +287,11 @@ int lafs_make_orphan_nb(struct fs *fs, struct datablock *db) 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; @@ -303,7 +309,7 @@ int lafs_make_orphan_nb(struct fs *fs, struct datablock *db) * All IO requests here must be async as we run from the cleaner * thread. */ -void lafs_orphan_release(struct fs *fs, struct datablock *b) +void lafs_orphan_release(struct fs *fs, struct datablock *b, struct inode *ino) { struct datablock *ob1, *ob2; int shift = b->b.inode->i_blkbits - 4; @@ -426,6 +432,7 @@ void lafs_orphan_release(struct fs *fs, struct datablock *b) om->nextfree--; om->reserved++; clear_bit(B_Orphan, &b->b.flags); + iput(ino); lafs_drop_orphan(fs, b); /* Now drop the reservation we just synthesised */ @@ -499,7 +506,7 @@ long lafs_run_orphans(struct fs *fs) spin_unlock(&fs->lock); if (!ino) - lafs_orphan_release(fs, db); + lafs_orphan_release(fs, db, NULL); else { int err = -ERESTARTSYS; while (err == -ERESTARTSYS) { -- 2.39.5