Gitweb:     
http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=fb46f341d9868fe993626536c7449c2a1aec62a3
Commit:     fb46f341d9868fe993626536c7449c2a1aec62a3
Parent:     b9ec0339d8e22cadf2d9d1b010b51dc53837dfb0
Author:     Lepton Wu <[EMAIL PROTECTED]>
AuthorDate: Tue Oct 16 23:30:04 2007 -0700
Committer:  Linus Torvalds <[EMAIL PROTECTED]>
CommitDate: Wed Oct 17 08:42:58 2007 -0700

    reiserfs: workaround for dead loop in finish_unfinished
    
    There is possible dead loop in finish_unfinished function.
    
    In most situation, the call chain iput -> ...  -> reiserfs_delete_inode ->
    remove_save_link will success.  But for some reason such as data
    corruption, reiserfs_delete_inode fails on reiserfs_do_truncate ->
    search_for_position_by_key.
    
    Then remove_save_link won't be called.  We always get the same
    "save_link_key" in the while loop in finish_unfinished function.  The
    following patch adds a check for the possible dead loop and just remove
    save link when deap loop.
    
    [EMAIL PROTECTED]: cleanups]
    Signed-off-by: Lepton Wu <[EMAIL PROTECTED]>
    Cc: Chris Mason <[EMAIL PROTECTED]>
    Cc: Jeff Mahoney <[EMAIL PROTECTED]>
    Cc: "Vladimir V. Saveliev" <[EMAIL PROTECTED]>
    Signed-off-by: Andrew Morton <[EMAIL PROTECTED]>
    Signed-off-by: Linus Torvalds <[EMAIL PROTECTED]>
---
 fs/reiserfs/super.c |   18 +++++++++++++++---
 1 files changed, 15 insertions(+), 3 deletions(-)

diff --git a/fs/reiserfs/super.c b/fs/reiserfs/super.c
index edfd74f..b82897a 100644
--- a/fs/reiserfs/super.c
+++ b/fs/reiserfs/super.c
@@ -145,7 +145,7 @@ static int finish_unfinished(struct super_block *s)
 {
        INITIALIZE_PATH(path);
        struct cpu_key max_cpu_key, obj_key;
-       struct reiserfs_key save_link_key;
+       struct reiserfs_key save_link_key, last_inode_key;
        int retval = 0;
        struct item_head *ih;
        struct buffer_head *bh;
@@ -166,6 +166,8 @@ static int finish_unfinished(struct super_block *s)
        set_cpu_key_k_offset(&max_cpu_key, ~0U);
        max_cpu_key.key_length = 3;
 
+       memset(&last_inode_key, 0, sizeof(last_inode_key));
+
 #ifdef CONFIG_QUOTA
        /* Needed for iput() to work correctly and not trash data */
        if (s->s_flags & MS_ACTIVE) {
@@ -278,8 +280,18 @@ static int finish_unfinished(struct super_block *s)
                        REISERFS_I(inode)->i_flags |= i_link_saved_unlink_mask;
                        /* not completed unlink (rmdir) found */
                        reiserfs_info(s, "Removing %k..", INODE_PKEY(inode));
-                       /* removal gets completed in iput */
-                       retval = 0;
+                       if (memcmp(&last_inode_key, INODE_PKEY(inode),
+                                       sizeof(last_inode_key))){
+                               last_inode_key = *INODE_PKEY(inode);
+                               /* removal gets completed in iput */
+                               retval = 0;
+                       } else {
+                               reiserfs_warning(s, "Dead loop in "
+                                               "finish_unfinished detected, "
+                                               "just remove save link\n");
+                               retval = remove_save_link_only(s,
+                                                       &save_link_key, 0);
+                       }
                }
 
                iput(inode);
-
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to