Whamcloud - gitweb
- ext3_check_dir_entry shouldn't panic if inum in cross-node dentry
[fs/lustre-release.git] / lustre / kernel_patches / patches / ext3-mds-num-2.4.24.patch
1 Index: linux-2.4.24/fs/ext3/namei.c
2 ===================================================================
3 --- linux-2.4.24.orig/fs/ext3/namei.c   2004-07-19 11:11:29.000000000 +0400
4 +++ linux-2.4.24/fs/ext3/namei.c        2004-07-19 11:11:29.000000000 +0400
5 @@ -1099,6 +1099,23 @@
6         inode = NULL;
7         if (bh) {
8                 unsigned long ino = le32_to_cpu(de->inode);
9 +               unsigned type = de->file_type;
10 +               __u32 *mds;
11 +               mds = (__u32 *)((char *) de + EXT3_DIR_REC_LEN(de->name_len));
12 +                if ((type & 128) && EXT3_HAS_INCOMPAT_FEATURE(dir->i_sb,
13 +                               EXT3_FEATURE_INCOMPAT_MDSNUM) &&
14 +                               mds[0] != EXT3_SB(dir->i_sb)->s_mdsnum) {
15 +                       struct ext3_super_block *es;
16 +                       es = EXT3_SB(dir->i_sb)->s_es;
17 +                       ext3_unlock_htree(dir, lock);
18 +                       brelse (bh);
19 +                       dentry->d_flags |= DCACHE_CROSS_REF;
20 +                       dentry->d_generation = mds[1];
21 +                       dentry->d_mdsnum = mds[0];
22 +                       dentry->d_inum = ino;
23 +                       d_add(dentry, NULL);
24 +                       return NULL;
25 +               }
26                 ext3_unlock_htree(dir, lock);
27                 brelse (bh);
28                 inode = iget(dir->i_sb, ino);
29 @@ -1138,7 +1155,7 @@
30         while (count--) {
31                 struct ext3_dir_entry_2 *de =
32                         (struct ext3_dir_entry_2 *) (from + map->offs);
33 -               rec_len = EXT3_DIR_REC_LEN(de->name_len);
34 +               rec_len = EXT3_DIR_REC_LEN_DE(de);
35                 memcpy (to, de, rec_len);
36                 ((struct ext3_dir_entry_2 *)to)->rec_len = cpu_to_le16(rec_len);
37                 de->inode = 0;
38 @@ -1159,7 +1176,7 @@
39                 next = (struct ext3_dir_entry_2 *) ((char *) de +
40                                                     le16_to_cpu(de->rec_len));
41                 if (de->inode && de->name_len) {
42 -                       rec_len = EXT3_DIR_REC_LEN(de->name_len);
43 +                       rec_len = EXT3_DIR_REC_LEN_DE(de);
44                         if (de > to)
45                                 memmove(to, de, rec_len);
46                         to->rec_len = cpu_to_le16(rec_len);
47 @@ -1275,6 +1292,7 @@
48                              struct buffer_head * bh)
49  {
50         struct inode    *dir = dentry->d_parent->d_inode;
51 +       struct super_block *sb = dir->i_sb;
52         const char      *name = dentry->d_name.name;
53         int             namelen = dentry->d_name.len;
54         unsigned long   offset = 0;
55 @@ -1283,6 +1301,10 @@
56         char            *top;
57         
58         reclen = EXT3_DIR_REC_LEN(namelen);
59 +        if (EXT3_HAS_INCOMPAT_FEATURE(sb, EXT3_FEATURE_INCOMPAT_MDSNUM)
60 +                       && (dentry->d_flags & DCACHE_CROSS_REF)
61 +                       && (dentry->d_mdsnum != EXT3_SB(sb)->s_mdsnum))
62 +               reclen += 8; /* we need space to store mds num */
63         if (!de) {
64                 de = (struct ext3_dir_entry_2 *)bh->b_data;
65                 top = bh->b_data + dir->i_sb->s_blocksize - reclen;
66 @@ -1296,7 +1318,7 @@
67                                 brelse (bh);
68                                 return -EEXIST;
69                         }
70 -                       nlen = EXT3_DIR_REC_LEN(de->name_len);
71 +                       nlen = EXT3_DIR_REC_LEN_DE(de);
72                         rlen = le16_to_cpu(de->rec_len);
73                         if ((de->inode? rlen - nlen: rlen) >= reclen)
74                                 break;
75 @@ -1315,7 +1337,7 @@
76         }
77         
78         /* By now the buffer is marked for journaling */
79 -       nlen = EXT3_DIR_REC_LEN(de->name_len);
80 +       nlen = EXT3_DIR_REC_LEN_DE(de);
81         rlen = le16_to_cpu(de->rec_len);
82         if (de->inode) {
83                 struct ext3_dir_entry_2 *de1 =
84 @@ -1327,8 +1349,20 @@
85         de->file_type = EXT3_FT_UNKNOWN;
86         if (inode) {
87                 de->inode = cpu_to_le32(inode->i_ino);
88 -               ext3_set_de_type(dir->i_sb, de, inode->i_mode);
89 -       } else
90 +               ext3_set_de_type(sb, de, inode->i_mode);
91 +       } else if (EXT3_HAS_INCOMPAT_FEATURE(sb, EXT3_FEATURE_INCOMPAT_MDSNUM)
92 +                       && (dentry->d_flags & DCACHE_CROSS_REF)) {
93 +               if (dentry->d_mdsnum != EXT3_SB(sb)->s_mdsnum) {
94 +                       __u32 *mds;
95 +                       mds = (__u32 *)((char *)de + EXT3_DIR_REC_LEN(namelen));
96 +                       mds[0] = cpu_to_le32(dentry->d_mdsnum);
97 +                       mds[1] = cpu_to_le32(dentry->d_generation);
98 +                       de->inode = cpu_to_le32(dentry->d_inum);
99 +                       de->file_type = 128;
100 +               } else {
101 +                       de->inode = cpu_to_le32(dentry->d_inum);
102 +               }
103 +       } else 
104                 de->inode = 0;
105         de->name_len = namelen;
106         memcpy (de->name, name, namelen);
107 @@ -2662,6 +2696,79 @@
108  }
109  
110  /*
111 + * caller has to make sure directory is protected
112 + */
113 +int ext3_add_dir_entry(struct dentry *dentry)
114 +{
115 +       struct inode *dir = dentry->d_parent->d_inode;
116 +       handle_t *handle;
117 +       int err;
118 +
119 +       handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS +
120 +                                       EXT3_INDEX_EXTRA_TRANS_BLOCKS);
121 +       if (IS_ERR(handle)) {
122 +               return PTR_ERR(handle);
123 +       }
124 +
125 +       if (IS_SYNC(dir))
126 +               handle->h_sync = 1;
127 +
128 +       err = ext3_add_entry(handle, dentry, NULL);
129 +       ext3_journal_stop(handle, dir);
130 +       return err;
131 +}
132 +
133 +/*
134 + * caller has to make sure directory is protected
135 + */
136 +int ext3_del_dir_entry(struct dentry *dentry)
137 +{
138 +       struct inode * inode;
139 +       struct inode * dir = dentry->d_parent->d_inode;
140 +       struct buffer_head * bh;
141 +       struct ext3_dir_entry_2 * de;
142 +       handle_t *handle;
143 +       void *lock;
144 +       int retval;
145 +
146 +       handle = ext3_journal_start(dir, EXT3_DELETE_TRANS_BLOCKS);
147 +       if (IS_ERR(handle)) {
148 +               return PTR_ERR(handle);
149 +       }
150 +
151 +       if (IS_SYNC(dir))
152 +               handle->h_sync = 1;
153 +
154 +       retval = -ENOENT;
155 +       bh = ext3_find_entry (dentry, &de, 1, &lock);
156 +       if (!bh)
157 +               goto end_unlink;
158 +
159 +       inode = dentry->d_inode;
160 +       if (inode)
161 +               DQUOT_INIT(inode);
162 +
163 +       retval = ext3_delete_entry(handle, dir, de, bh);
164 +       ext3_unlock_htree(dir, lock);
165 +       if (retval)
166 +               goto end_unlink;
167 +       dir->i_ctime = dir->i_mtime = CURRENT_TIME;
168 +       ext3_update_dx_flag(dir);
169 +       if (inode) {
170 +               inode->i_ctime = dir->i_ctime;
171 +               ext3_mark_inode_dirty(handle, inode);
172 +               if (S_ISDIR(inode->i_mode))
173 +                       dir->i_nlink--;
174 +       }
175 +       ext3_mark_inode_dirty(handle, dir);
176 +       retval = 0;
177 +
178 +end_unlink:
179 +       ext3_journal_stop(handle, dir);
180 +       brelse (bh);
181 +       return retval;
182 +}
183 +/*
184   * directories can handle most operations...
185   */
186  struct inode_operations ext3_dir_inode_operations = {
187 Index: linux-2.4.24/fs/ext3/dir.c
188 ===================================================================
189 --- linux-2.4.24.orig/fs/ext3/dir.c     2004-07-19 11:11:16.000000000 +0400
190 +++ linux-2.4.24/fs/ext3/dir.c  2004-07-30 23:56:03.000000000 +0400
191 @@ -42,6 +42,9 @@
192  
193  static unsigned char get_dtype(struct super_block *sb, int filetype)
194  {
195 +       if (EXT3_HAS_INCOMPAT_FEATURE(sb, EXT3_FEATURE_INCOMPAT_MDSNUM))
196 +               return DT_UNKNOWN;
197 +
198         if (!EXT3_HAS_INCOMPAT_FEATURE(sb, EXT3_FEATURE_INCOMPAT_FILETYPE) ||
199             (filetype >= EXT3_FT_MAX))
200                 return DT_UNKNOWN;
201 @@ -67,8 +70,10 @@
202         else if (((char *) de - bh->b_data) + rlen > dir->i_sb->s_blocksize)
203                 error_msg = "directory entry across blocks";
204         else if (le32_to_cpu(de->inode) >
205 -                       le32_to_cpu(dir->i_sb->u.ext3_sb.s_es->s_inodes_count))
206 -               error_msg = "inode out of bounds";
207 +                       le32_to_cpu(dir->i_sb->u.ext3_sb.s_es->s_inodes_count)) {
208 +               if (de->file_type != 128)
209 +                       error_msg = "inode out of bounds";
210 +       }
211  
212         if (error_msg != NULL)
213                 ext3_error (dir->i_sb, function,
214 Index: linux-2.4.24/fs/ext3/ext3-exports.c
215 ===================================================================
216 --- linux-2.4.24.orig/fs/ext3/ext3-exports.c    2004-07-19 11:11:16.000000000 +0400
217 +++ linux-2.4.24/fs/ext3/ext3-exports.c 2004-07-19 11:11:29.000000000 +0400
218 @@ -26,3 +26,10 @@
219  EXPORT_SYMBOL(ext3_decode_error);
220  EXPORT_SYMBOL(__ext3_std_error);
221  
222 +int ext3_add_dir_entry (struct dentry *dentry);
223 +EXPORT_SYMBOL(ext3_add_dir_entry);
224 +int ext3_del_dir_entry(struct dentry *dentry);
225 +EXPORT_SYMBOL(ext3_del_dir_entry);
226 +
227 +
228 +
229 Index: linux-2.4.24/include/linux/ext3_fs.h
230 ===================================================================
231 --- linux-2.4.24.orig/include/linux/ext3_fs.h   2004-07-19 11:11:29.000000000 +0400
232 +++ linux-2.4.24/include/linux/ext3_fs.h        2004-07-19 11:13:53.000000000 +0400
233 @@ -446,7 +446,8 @@
234         __u8    s_def_hash_version;     /* Default hash version to use */
235         __u8    s_reserved_char_pad;
236         __u16   s_reserved_word_pad;
237 -       __u32   s_reserved[192];        /* Padding to the end of the block */
238 +       __u32   s_mdsnum;
239 +       __u32   s_reserved[191];        /* Padding to the end of the block */
240  };
241  
242  #ifdef __KERNEL__
243 @@ -519,10 +520,12 @@
244  #define EXT3_FEATURE_INCOMPAT_FILETYPE         0x0002
245  #define EXT3_FEATURE_INCOMPAT_RECOVER          0x0004 /* Needs recovery */
246  #define EXT3_FEATURE_INCOMPAT_JOURNAL_DEV      0x0008 /* Journal device */
247 +#define EXT3_FEATURE_INCOMPAT_MDSNUM           0x0020 /* direntry has mdsnum */
248  
249  #define EXT3_FEATURE_COMPAT_SUPP       EXT2_FEATURE_COMPAT_EXT_ATTR
250  #define EXT3_FEATURE_INCOMPAT_SUPP     (EXT3_FEATURE_INCOMPAT_FILETYPE| \
251 -                                        EXT3_FEATURE_INCOMPAT_RECOVER)
252 +                                        EXT3_FEATURE_INCOMPAT_RECOVER| \
253 +                                        EXT3_FEATURE_INCOMPAT_MDSNUM)
254  #define EXT3_FEATURE_RO_COMPAT_SUPP    (EXT3_FEATURE_RO_COMPAT_SPARSE_SUPER| \
255                                          EXT3_FEATURE_RO_COMPAT_LARGE_FILE| \
256                                          EXT3_FEATURE_RO_COMPAT_BTREE_DIR)
257 @@ -583,6 +586,9 @@
258  #define EXT3_DIR_ROUND                 (EXT3_DIR_PAD - 1)
259  #define EXT3_DIR_REC_LEN(name_len)     (((name_len) + 8 + EXT3_DIR_ROUND) & \
260                                          ~EXT3_DIR_ROUND)
261 +#define EXT3_DIR_REC_LEN_DE(de)        (EXT3_DIR_REC_LEN((de)->name_len) + \
262 +                                       (((de)->file_type & 128) ? 8 : 0))
263 +
264  /*
265   * Hash Tree Directory indexing
266   * (c) Daniel Phillips, 2001
267 Index: linux-2.4.24/include/linux/ext3_fs_sb.h
268 ===================================================================
269 --- linux-2.4.24.orig/include/linux/ext3_fs_sb.h        2004-07-19 11:11:16.000000000 +0400
270 +++ linux-2.4.24/include/linux/ext3_fs_sb.h     2004-07-19 11:12:54.000000000 +0400
271 @@ -86,6 +86,7 @@
272         wait_queue_head_t s_delete_thread_queue;
273         wait_queue_head_t s_delete_waiter_queue;
274  #endif
275 +       u32 s_mdsnum;
276  };
277  
278  #endif /* _LINUX_EXT3_FS_SB */
279 Index: linux-2.4.24/include/linux/dcache.h
280 ===================================================================
281 --- linux-2.4.24.orig/include/linux/dcache.h    2004-07-19 11:11:16.000000000 +0400
282 +++ linux-2.4.24/include/linux/dcache.h 2004-07-19 11:12:53.000000000 +0400
283 @@ -120,6 +120,9 @@
284         atomic_t d_count;
285         unsigned int d_flags;
286         struct inode  * d_inode;        /* Where the name belongs to - NULL is negative */
287 +       unsigned d_inum;                /* for cross-fs references (Lustre) */
288 +       unsigned d_mdsnum;              /* for cross-fs references (Lustre) */
289 +       unsigned d_generation;          /* for cross-fs references (Lustre) */
290         struct dentry * d_parent;       /* parent directory */
291         struct list_head d_hash;        /* lookup hash list */
292         struct list_head d_lru;         /* d_count = 0 LRU list */
293 @@ -193,6 +196,7 @@
294                                          */
295  #define DCACHE_REFERENCED      0x0008  /* Recently used, don't discard. */
296  #define DCACHE_LUSTRE_INVALID  0x0010  /* Lustre invalidated */
297 +#define DCACHE_CROSS_REF       0x0020  /* entry points to inode on another MDS */
298  
299  extern spinlock_t dcache_lock;
300