Whamcloud - gitweb
b=20581 MDS returns full hash for readdir to decrease hash collision
[fs/lustre-release.git] / ldiskfs / kernel_patches / patches / ext3-corrupted-orphans-2.6.patch
1 --- linux-2.6.18-128.7.1.orig/include/linux/ext3_fs.h   2006-09-19 23:42:06.000000000 -0400
2 +++ linux-2.6.18-128.7.1/include/linux/ext3_fs.h        2009-10-12 19:37:54.000000000 -0400
3 @@ -809,6 +809,7 @@ extern void ext3_discard_reservation (st
4  extern void ext3_dirty_inode(struct inode *);
5  extern int ext3_change_inode_journal_flag(struct inode *, int);
6  extern int ext3_get_inode_loc(struct inode *, struct ext3_iloc *);
7 +extern int ext3_can_truncate(struct inode *inode);
8  extern void ext3_truncate (struct inode *);
9  extern void ext3_set_inode_flags(struct inode *);
10  extern void ext3_set_aops(struct inode *inode);
11 --- linux-2.6.18-128.7.1.orig/fs/ext3/inode.c   2009-09-15 10:38:31.000000000 -0400
12 +++ linux-2.6.18-128.7.1/fs/ext3/inode.c        2009-10-12 18:49:01.000000000 -0400
13 @@ -2194,6 +2194,19 @@ static void ext3_free_branches(handle_t 
14         }
15  }
16  
17 +int ext3_can_truncate(struct inode *inode)
18 +{
19 +       if (IS_APPEND(inode) || IS_IMMUTABLE(inode))
20 +               return 0;
21 +       if (S_ISREG(inode->i_mode))
22 +               return 1;
23 +       if (S_ISDIR(inode->i_mode))
24 +               return 1;
25 +       if (S_ISLNK(inode->i_mode))
26 +               return !ext3_inode_is_fast_symlink(inode);
27 +       return 0;
28 +}
29 +
30  /*
31   * ext3_truncate()
32   *
33 @@ -2238,12 +2251,7 @@ void ext3_truncate(struct inode *inode)
34         unsigned blocksize = inode->i_sb->s_blocksize;
35         struct page *page;
36  
37 -       if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
38 -           S_ISLNK(inode->i_mode)))
39 -               return;
40 -       if (ext3_inode_is_fast_symlink(inode))
41 -               return;
42 -       if (IS_APPEND(inode) || IS_IMMUTABLE(inode))
43 +       if (!ext3_can_truncate(inode))
44                 return;
45  
46         /*
47 --- linux-2.6.18-128.7.1.orig/fs/ext3/ialloc.c  2009-09-15 10:24:17.000000000 -0400
48 +++ linux-2.6.18-128.7.1/fs/ext3/ialloc.c       2009-10-14 15:36:27.000000000 -0400
49 @@ -645,54 +645,71 @@ struct inode *ext3_orphan_get(struct sup
50         unsigned long max_ino = le32_to_cpu(EXT3_SB(sb)->s_es->s_inodes_count);
51         unsigned long block_group;
52         int bit;
53 -       struct buffer_head *bitmap_bh = NULL;
54 +       struct buffer_head *bitmap_bh;
55         struct inode *inode = NULL;
56  
57         /* Error cases - e2fsck has already cleaned up for us */
58         if (ino > max_ino) {
59 -               ext3_warning(sb, __FUNCTION__,
60 +               ext3_warning(sb, __func__,
61                              "bad orphan ino %lu!  e2fsck was run?", ino);
62 -               goto out;
63 +               goto error;
64         }
65  
66         block_group = (ino - 1) / EXT3_INODES_PER_GROUP(sb);
67         bit = (ino - 1) % EXT3_INODES_PER_GROUP(sb);
68         bitmap_bh = read_inode_bitmap(sb, block_group);
69         if (!bitmap_bh) {
70 -               ext3_warning(sb, __FUNCTION__,
71 +               ext3_warning(sb, __func__,
72                              "inode bitmap error for orphan %lu", ino);
73 -               goto out;
74 +               goto error;
75         }
76  
77         /* Having the inode bit set should be a 100% indicator that this
78          * is a valid orphan (no e2fsck run on fs).  Orphans also include
79          * inodes that were being truncated, so we can't check i_nlink==0.
80          */
81 -       if (!ext3_test_bit(bit, bitmap_bh->b_data) ||
82 -                       !(inode = iget(sb, ino)) || is_bad_inode(inode) ||
83 -                       NEXT_ORPHAN(inode) > max_ino) {
84 -               ext3_warning(sb, __FUNCTION__,
85 -                            "bad orphan inode %lu!  e2fsck was run?", ino);
86 -               printk(KERN_NOTICE "ext3_test_bit(bit=%d, block=%llu) = %d\n",
87 -                      bit, (unsigned long long)bitmap_bh->b_blocknr,
88 -                      ext3_test_bit(bit, bitmap_bh->b_data));
89 -               printk(KERN_NOTICE "inode=%p\n", inode);
90 -               if (inode) {
91 -                       printk(KERN_NOTICE "is_bad_inode(inode)=%d\n",
92 -                              is_bad_inode(inode));
93 -                       printk(KERN_NOTICE "NEXT_ORPHAN(inode)=%u\n",
94 -                              NEXT_ORPHAN(inode));
95 -                       printk(KERN_NOTICE "max_ino=%lu\n", max_ino);
96 -               }
97 +       if (!ext3_test_bit(bit, bitmap_bh->b_data))
98 +               goto bad_orphan;
99 +
100 +       inode = iget(sb, ino);
101 +       if ((inode == NULL) || is_bad_inode(inode))
102 +               goto bad_orphan;
103 +
104 +       /*
105 +        * If the orphan has i_nlinks > 0 then it should be able to be
106 +        * truncated, otherwise it won't be removed from the orphan list
107 +        * during processing and an infinite loop will result.
108 +        */
109 +       if (inode->i_nlink && !ext3_can_truncate(inode))
110 +               goto bad_orphan;
111 +
112 +       if (NEXT_ORPHAN(inode) > max_ino)
113 +               goto bad_orphan;
114 +       brelse(bitmap_bh);
115 +       return inode;
116 +
117 +bad_orphan:
118 +       ext3_warning(sb, __func__,
119 +                    "bad orphan inode %lu!  e2fsck was run?", ino);
120 +       printk(KERN_NOTICE "ext3_test_bit(bit=%d, block=%llu) = %d\n",
121 +              bit, (unsigned long long)bitmap_bh->b_blocknr,
122 +              ext3_test_bit(bit, bitmap_bh->b_data));
123 +       printk(KERN_NOTICE "inode=%p\n", inode);
124 +       if (inode) {
125 +               printk(KERN_NOTICE "is_bad_inode(inode)=%d\n",
126 +                      is_bad_inode(inode));
127 +               printk(KERN_NOTICE "NEXT_ORPHAN(inode)=%u\n",
128 +                      NEXT_ORPHAN(inode));
129 +               printk(KERN_NOTICE "max_ino=%lu\n", max_ino);
130 +               printk(KERN_NOTICE "i_nlink=%u\n", inode->i_nlink);
131                 /* Avoid freeing blocks if we got a bad deleted inode */
132 -               if (inode && inode->i_nlink == 0)
133 +               if (inode->i_nlink == 0)
134                         inode->i_blocks = 0;
135                 iput(inode);
136 -               inode = NULL;
137         }
138 -out:
139         brelse(bitmap_bh);
140 -       return inode;
141 +error:
142 +       return NULL;
143  }
144  
145  unsigned long ext3_count_free_inodes (struct super_block * sb)