From c889053bcc7cf1f782c47038a073a2101beecaff Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Sat, 14 Aug 2010 21:50:14 +1000 Subject: [PATCH] flush orphans when renaming to empty directory just like rmdir Signed-off-by: NeilBrown --- dir.c | 49 +++++++++++++++++++++++++++++-------------------- 1 file changed, 29 insertions(+), 20 deletions(-) diff --git a/dir.c b/dir.c index 0985428..b2df67a 100644 --- a/dir.c +++ b/dir.c @@ -787,6 +787,29 @@ abort: return err; } +static void dir_flush_orphans(struct fs *fs, struct inode *inode) +{ + /* + * Orphans cannot clear while we hold i_mutex, so + * we have to run them ourselves. + */ + struct datablock *db; + DEFINE_WAIT(wq); + while ((db = lafs_find_orphan(inode))) { + int still_orphan; + prepare_to_wait(&fs->async_complete, &wq, + TASK_UNINTERRUPTIBLE); + getdref(db, MKREF(rmdir_orphan)); + lafs_dir_handle_orphan(db); + still_orphan = test_bit(B_Orphan, &db->b.flags); + putdref(db, MKREF(rmdir_orphan)); + if (still_orphan) + /* still an orphan, need to wait */ + schedule(); + } + finish_wait(&fs->async_complete, &wq); +} + static int lafs_rmdir(struct inode *dir, struct dentry *de) { @@ -802,24 +825,8 @@ lafs_rmdir(struct inode *dir, struct dentry *de) if (inode->i_size) { /* Probably not empty, but it could be that we * just need to wait for orphans the clear. - * They cannot clear while we hold i_mutex, so - * we have to run it ourselves. */ - struct datablock *db; - DEFINE_WAIT(wq); - while ((db = lafs_find_orphan(inode))) { - int still_orphan; - prepare_to_wait(&fs->async_complete, &wq, - TASK_UNINTERRUPTIBLE); - getdref(db, MKREF(rmdir_orphan)); - lafs_dir_handle_orphan(db); - still_orphan = test_bit(B_Orphan, &db->b.flags); - putdref(db, MKREF(rmdir_orphan)); - if (still_orphan) - /* still an orphan, need to wait */ - schedule(); - } - finish_wait(&fs->async_complete, &wq); + dir_flush_orphans(fs, inode); if (inode->i_size) return -ENOTEMPTY; } @@ -1123,9 +1130,11 @@ lafs_rename(struct inode *old_dir, struct dentry *old_dentry, if (S_ISDIR(old_inode->i_mode)) { if (new_inode) { - /* FIXME flush orphans in new_inode */ - if (new_inode->i_size) - return -ENOTEMPTY; + if (new_inode->i_size) { + dir_flush_orphans(fs, new_inode); + if (new_inode->i_size) + return -ENOTEMPTY; + } } else if (new_dir != old_dir) { /* New dir is getting a new link */ if (new_dir->i_nlink >= LAFS_MAX_LINKS) -- 2.39.5