Whamcloud - gitweb
b=3244
[fs/lustre-release.git] / lustre / kernel_patches / patches / ext3-nlinks-2.4.20-hp_pnnl.patch
1 Index: linux/fs/ext3/namei.c
2 ===================================================================
3 --- linux.orig/fs/ext3/namei.c
4 +++ linux/fs/ext3/namei.c
5 @@ -1549,11 +1549,17 @@ static int ext3_delete_entry (handle_t *
6  static inline void ext3_inc_count(handle_t *handle, struct inode *inode)
7  {
8         inode->i_nlink++;
9 +       if (is_dx(inode) && inode->i_nlink > 1) {
10 +               /* limit is 16-bit i_links_count */
11 +               if (inode->i_nlink >= EXT3_LINK_MAX || inode->i_nlink == 2)
12 +                       inode->i_nlink = 1;
13 +       }
14  }
15  
16  static inline void ext3_dec_count(handle_t *handle, struct inode *inode)
17  {
18 -       inode->i_nlink--;
19 +       if (!S_ISDIR(inode->i_mode) || inode->i_nlink > 2)
20 +               inode->i_nlink--;
21  }
22  
23  static int ext3_add_nondir(handle_t *handle,
24 @@ -1654,7 +1660,7 @@ static int ext3_mkdir(struct inode * dir
25         struct ext3_dir_entry_2 * de;
26         int err;
27  
28 -       if (dir->i_nlink >= EXT3_LINK_MAX)
29 +       if (EXT3_DIR_LINK_MAX(dir))
30                 return -EMLINK;
31  
32         handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS +
33 @@ -1676,7 +1682,7 @@ static int ext3_mkdir(struct inode * dir
34         inode->i_size = EXT3_I(inode)->i_disksize = inode->i_sb->s_blocksize;
35         dir_block = ext3_bread (handle, inode, 0, 1, &err);
36         if (!dir_block) {
37 -               inode->i_nlink--; /* is this nlink == 0? */
38 +               ext3_dec_count(handle, inode); /* is this nlink == 0? */
39                 ext3_mark_inode_dirty(handle, inode);
40                 iput (inode);
41                 goto out_stop;
42 @@ -1708,7 +1714,7 @@ static int ext3_mkdir(struct inode * dir
43                 iput (inode);
44                 goto out_stop;
45         }
46 -       dir->i_nlink++;
47 +       ext3_inc_count(handle, dir);
48         ext3_update_dx_flag(dir);
49         ext3_mark_inode_dirty(handle, dir);
50         d_instantiate(dentry, inode);
51 @@ -1769,10 +1775,11 @@ static int empty_dir (struct inode * ino
52                         }
53                         de = (struct ext3_dir_entry_2 *) bh->b_data;
54                 }
55 -               if (!ext3_check_dir_entry ("empty_dir", inode, de, bh,
56 -                                          offset)) {
57 -                       brelse (bh);
58 -                       return 1;
59 +               if (!ext3_check_dir_entry("empty_dir", inode, de, bh, offset)) {
60 +                       /* On error skip the de and offset to the next block. */
61 +                       de = (void *)(bh->b_data + sb->s_blocksize);
62 +                       offset = (offset | (sb->s_blocksize - 1)) + 1;
63 +                       continue;
64                 }
65                 if (le32_to_cpu(de->inode)) {
66                         brelse (bh);
67 @@ -1965,14 +1972,14 @@ static int ext3_rmdir (struct inode * di
68         retval = ext3_delete_entry(handle, dir, de, bh);
69         if (retval)
70                 goto end_rmdir;
71 -       if (inode->i_nlink != 2)
72 -               ext3_warning (inode->i_sb, "ext3_rmdir",
73 -                             "empty directory has nlink!=2 (%d)",
74 -                             inode->i_nlink);
75 +       if (!EXT3_DIR_LINK_EMPTY(inode))
76 +               ext3_warning(inode->i_sb, __FUNCTION__,
77 +                            "empty directory has too many links (%d)",
78 +                            inode->i_nlink);
79         inode->i_version = ++event;
80         inode->i_nlink = 0;
81         ext3_orphan_add(handle, inode);
82 -       dir->i_nlink--;
83 +       ext3_dec_count(handle, dir);
84         inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
85         ext3_mark_inode_dirty(handle, inode);
86         ext3_update_dx_flag(dir);
87 @@ -2024,7 +2031,7 @@ static int ext3_unlink(struct inode * di
88         dir->i_ctime = dir->i_mtime = CURRENT_TIME;
89         ext3_update_dx_flag(dir);
90         ext3_mark_inode_dirty(handle, dir);
91 -       inode->i_nlink--;
92 +       ext3_dec_count(handle, inode);
93         if (!inode->i_nlink)
94                 ext3_orphan_add(handle, inode);
95         inode->i_ctime = dir->i_ctime;
96 @@ -2116,9 +2123,8 @@ static int ext3_link (struct dentry * ol
97         if (S_ISDIR(inode->i_mode))
98                 return -EPERM;
99  
100 -       if (inode->i_nlink >= EXT3_LINK_MAX) {
101 +       if (EXT3_DIR_LINK_MAX(inode))
102                 return -EMLINK;
103 -       }
104  
105         handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS +
106                                         EXT3_INDEX_EXTRA_TRANS_BLOCKS);
107 @@ -2202,8 +2208,8 @@ static int ext3_rename (struct inode * o
108                 if (le32_to_cpu(PARENT_INO(dir_bh->b_data)) != old_dir->i_ino)
109                         goto end_rename;
110                 retval = -EMLINK;
111 -               if (!new_inode && new_dir!=old_dir &&
112 -                               new_dir->i_nlink >= EXT3_LINK_MAX)
113 +               if (!new_inode && new_dir != old_dir &&
114 +                   EXT3_DIR_LINK_MAX(new_dir))
115                         goto end_rename;
116         }
117         if (!new_bh) {
118 @@ -2261,7 +2267,7 @@ static int ext3_rename (struct inode * o
119         }
120  
121         if (new_inode) {
122 -               new_inode->i_nlink--;
123 +               ext3_dec_count(handle, new_inode);
124                 new_inode->i_ctime = CURRENT_TIME;
125         }
126         old_dir->i_ctime = old_dir->i_mtime = CURRENT_TIME;
127 @@ -2272,11 +2278,13 @@ static int ext3_rename (struct inode * o
128                 PARENT_INO(dir_bh->b_data) = le32_to_cpu(new_dir->i_ino);
129                 BUFFER_TRACE(dir_bh, "call ext3_journal_dirty_metadata");
130                 ext3_journal_dirty_metadata(handle, dir_bh);
131 -               old_dir->i_nlink--;
132 +               ext3_dec_count(handle, old_dir);
133                 if (new_inode) {
134 -                       new_inode->i_nlink--;
135 +                       /* checked empty_dir above, can't have another parent,
136 +                        * ext3_dec_count() won't work for many-linked dirs */
137 +                       new_inode->i_nlink = 0;
138                 } else {
139 -                       new_dir->i_nlink++;
140 +                       ext3_inc_count(handle, new_dir);
141                         ext3_update_dx_flag(new_dir);
142                         ext3_mark_inode_dirty(handle, new_dir);
143                 }
144 Index: linux/include/linux/ext3_fs.h
145 ===================================================================
146 --- linux.orig/include/linux/ext3_fs.h
147 +++ linux/include/linux/ext3_fs.h
148 @@ -79,7 +79,7 @@
149  /*
150   * Maximal count of links to a file
151   */
152 -#define EXT3_LINK_MAX          32000
153 +#define EXT3_LINK_MAX          65000
154  
155  /*
156   * Macro-instructions used to manage several block sizes
157 @@ -503,6 +503,7 @@ struct ext3_super_block {
158  #define EXT3_FEATURE_RO_COMPAT_SPARSE_SUPER    0x0001
159  #define EXT3_FEATURE_RO_COMPAT_LARGE_FILE      0x0002
160  #define EXT3_FEATURE_RO_COMPAT_BTREE_DIR       0x0004
161 +#define EXT3_FEATURE_RO_COMPAT_DIR_NLINK       0x0020
162  
163  #define EXT3_FEATURE_INCOMPAT_COMPRESSION      0x0001
164  #define EXT3_FEATURE_INCOMPAT_FILETYPE         0x0002
165 @@ -516,6 +517,7 @@ struct ext3_super_block {
166                                          EXT3_FEATURE_INCOMPAT_EXTENTS)
167  #define EXT3_FEATURE_RO_COMPAT_SUPP    (EXT3_FEATURE_RO_COMPAT_SPARSE_SUPER| \
168                                          EXT3_FEATURE_RO_COMPAT_LARGE_FILE| \
169 +                                        EXT3_FEATURE_RO_COMPAT_DIR_NLINK| \
170                                          EXT3_FEATURE_RO_COMPAT_BTREE_DIR)
171  
172  /*