update and add new version of speedup-jbd2_journal_dirty_metadata
[ext4-patch-queue.git] / improve-warning-directory-handling-messages
blob090b67a802de4f1b6a1379dd1b1200147f07bd08
1 ext4: improve warning directory handling messages
3 From: Andreas Dilger <adilger@dilger.ca>
5 Several ext4_warning() messages in the directory handling code do not
6 report the inode number of the (potentially corrupt) directory where a
7 problem is seen, and others report this in an ad-hoc manner.  Add an
8 ext4_warning_inode() helper to print the inode number and command name
9 consistent with ext4_error_inode().
11 Consolidate the place in ext4.h that these macros are defined.
13 Clean up some other directory error and warning messages to print the
14 calling function name.
16 Minor code style fixes in nearby lines.
18 Signed-off-by: Andreas Dilger <adilger@dilger.ca>
19 Signed-off-by: Theodore Ts'o <tytso@mit.edu>
20 ---
21  fs/ext4/ext4.h  |   28 ++++++++----
22  fs/ext4/namei.c |  125 +++++++++++++++++++++++++++++-------------------------
23  fs/ext4/super.c |   25 ++++++++++-
24  3 files changed, 109 insertions(+), 69 deletions(-)
26 diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
27 index 009a059..7a49dd1 100644
28 --- a/fs/ext4/ext4.h
29 +++ b/fs/ext4/ext4.h
30 @@ -69,15 +69,6 @@
31  #define ext_debug(fmt, ...)    no_printk(fmt, ##__VA_ARGS__)
32  #endif
34 -#define EXT4_ERROR_INODE(inode, fmt, a...) \
35 -       ext4_error_inode((inode), __func__, __LINE__, 0, (fmt), ## a)
37 -#define EXT4_ERROR_INODE_BLOCK(inode, block, fmt, a...)                        \
38 -       ext4_error_inode((inode), __func__, __LINE__, (block), (fmt), ## a)
40 -#define EXT4_ERROR_FILE(file, block, fmt, a...)                                \
41 -       ext4_error_file((file), __func__, __LINE__, (block), (fmt), ## a)
43  /* data type for block offset of block group */
44  typedef int ext4_grpblk_t;
46 @@ -2368,6 +2359,9 @@ void __ext4_abort(struct super_block *, const char *, unsigned int,
47  extern __printf(4, 5)
48  void __ext4_warning(struct super_block *, const char *, unsigned int,
49                     const char *, ...);
50 +extern __printf(4, 5)
51 +void __ext4_warning_inode(const struct inode *inode, const char *function,
52 +                         unsigned int line, const char *fmt, ...);
53  extern __printf(3, 4)
54  void __ext4_msg(struct super_block *, const char *, const char *, ...);
55  extern void __dump_mmp_msg(struct super_block *, struct mmp_struct *mmp,
56 @@ -2378,6 +2372,15 @@ void __ext4_grp_locked_error(const char *, unsigned int,
57                              unsigned long, ext4_fsblk_t,
58                              const char *, ...);
60 +#define EXT4_ERROR_INODE(inode, fmt, a...) \
61 +       ext4_error_inode((inode), __func__, __LINE__, 0, (fmt), ## a)
63 +#define EXT4_ERROR_INODE_BLOCK(inode, block, fmt, a...)                        \
64 +       ext4_error_inode((inode), __func__, __LINE__, (block), (fmt), ## a)
66 +#define EXT4_ERROR_FILE(file, block, fmt, a...)                                \
67 +       ext4_error_file((file), __func__, __LINE__, (block), (fmt), ## a)
69  #ifdef CONFIG_PRINTK
71  #define ext4_error_inode(inode, func, line, block, fmt, ...)           \
72 @@ -2390,6 +2393,8 @@ void __ext4_grp_locked_error(const char *, unsigned int,
73         __ext4_abort(sb, __func__, __LINE__, fmt, ##__VA_ARGS__)
74  #define ext4_warning(sb, fmt, ...)                                     \
75         __ext4_warning(sb, __func__, __LINE__, fmt, ##__VA_ARGS__)
76 +#define ext4_warning_inode(inode, fmt, ...)                            \
77 +       __ext4_warning_inode(inode, __func__, __LINE__, fmt, ##__VA_ARGS__)
78  #define ext4_msg(sb, level, fmt, ...)                          \
79         __ext4_msg(sb, level, fmt, ##__VA_ARGS__)
80  #define dump_mmp_msg(sb, mmp, msg)                                     \
81 @@ -2425,6 +2430,11 @@ do {                                                                     \
82         no_printk(fmt, ##__VA_ARGS__);                                  \
83         __ext4_warning(sb, "", 0, " ");                                 \
84  } while (0)
85 +#define ext4_warning_inode(inode, fmt, ...)                            \
86 +do {                                                                   \
87 +       no_printk(fmt, ##__VA_ARGS__);                                  \
88 +       __ext4_warning_inode(inode, "", 0, " ");                        \
89 +} while (0)
90  #define ext4_msg(sb, level, fmt, ...)                                  \
91  do {                                                                   \
92         no_printk(fmt, ##__VA_ARGS__);                                  \
93 diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
94 index 814f3be..45539b6 100644
95 --- a/fs/ext4/namei.c
96 +++ b/fs/ext4/namei.c
97 @@ -84,12 +84,13 @@ typedef enum {
98  } dirblock_type_t;
100  #define ext4_read_dirblock(inode, block, type) \
101 -       __ext4_read_dirblock((inode), (block), (type), __LINE__)
102 +       __ext4_read_dirblock((inode), (block), (type), __func__, __LINE__)
104  static struct buffer_head *__ext4_read_dirblock(struct inode *inode,
105 -                                             ext4_lblk_t block,
106 -                                             dirblock_type_t type,
107 -                                             unsigned int line)
108 +                                               ext4_lblk_t block,
109 +                                               dirblock_type_t type,
110 +                                               const char *func,
111 +                                               unsigned int line)
113         struct buffer_head *bh;
114         struct ext4_dir_entry *dirent;
115 @@ -97,15 +98,17 @@ static struct buffer_head *__ext4_read_dirblock(struct inode *inode,
117         bh = ext4_bread(NULL, inode, block, 0);
118         if (IS_ERR(bh)) {
119 -               __ext4_warning(inode->i_sb, __func__, line,
120 -                              "error %ld reading directory block "
121 -                              "(ino %lu, block %lu)", PTR_ERR(bh), inode->i_ino,
122 -                              (unsigned long) block);
123 +               __ext4_warning(inode->i_sb, func, line,
124 +                              "inode #%lu: lblock %lu: comm %s: "
125 +                              "error %ld reading directory block",
126 +                              inode->i_ino, (unsigned long)block,
127 +                              current->comm, PTR_ERR(bh));
129                 return bh;
130         }
131         if (!bh) {
132 -               ext4_error_inode(inode, __func__, line, block, "Directory hole found");
133 +               ext4_error_inode(inode, func, line, block,
134 +                                "Directory hole found");
135                 return ERR_PTR(-EIO);
136         }
137         dirent = (struct ext4_dir_entry *) bh->b_data;
138 @@ -119,7 +122,7 @@ static struct buffer_head *__ext4_read_dirblock(struct inode *inode,
139                         is_dx_block = 1;
140         }
141         if (!is_dx_block && type == INDEX) {
142 -               ext4_error_inode(inode, __func__, line, block,
143 +               ext4_error_inode(inode, func, line, block,
144                        "directory leaf block found instead of index block");
145                 return ERR_PTR(-EIO);
146         }
147 @@ -136,8 +139,8 @@ static struct buffer_head *__ext4_read_dirblock(struct inode *inode,
148                 if (ext4_dx_csum_verify(inode, dirent))
149                         set_buffer_verified(bh);
150                 else {
151 -                       ext4_error_inode(inode, __func__, line, block,
152 -                               "Directory index failed checksum");
153 +                       ext4_error_inode(inode, func, line, block,
154 +                                        "Directory index failed checksum");
155                         brelse(bh);
156                         return ERR_PTR(-EIO);
157                 }
158 @@ -146,8 +149,8 @@ static struct buffer_head *__ext4_read_dirblock(struct inode *inode,
159                 if (ext4_dirent_csum_verify(inode, dirent))
160                         set_buffer_verified(bh);
161                 else {
162 -                       ext4_error_inode(inode, __func__, line, block,
163 -                               "Directory block failed checksum");
164 +                       ext4_error_inode(inode, func, line, block,
165 +                                        "Directory block failed checksum");
166                         brelse(bh);
167                         return ERR_PTR(-EIO);
168                 }
169 @@ -327,10 +330,14 @@ static __le32 ext4_dirent_csum(struct inode *inode,
170         return cpu_to_le32(csum);
173 -static void warn_no_space_for_csum(struct inode *inode)
174 +#define warn_no_space_for_csum(inode)                                  \
175 +       __warn_no_space_for_csum((inode), __func__, __LINE__)
177 +static void __warn_no_space_for_csum(struct inode *inode, const char *func,
178 +                                    unsigned int line)
180 -       ext4_warning(inode->i_sb, "no space in directory inode %lu leaf for "
181 -                    "checksum.  Please run e2fsck -D.", inode->i_ino);
182 +       __ext4_warning_inode(inode, func, line,
183 +               "No space for directory leaf checksum. Please run e2fsck -D.");
186  int ext4_dirent_csum_verify(struct inode *inode, struct ext4_dir_entry *dirent)
187 @@ -742,8 +749,8 @@ dx_probe(const struct qstr *d_name, struct inode *dir,
188         if (root->info.hash_version != DX_HASH_TEA &&
189             root->info.hash_version != DX_HASH_HALF_MD4 &&
190             root->info.hash_version != DX_HASH_LEGACY) {
191 -               ext4_warning(dir->i_sb, "Unrecognised inode hash code %d",
192 -                            root->info.hash_version);
193 +               ext4_warning_inode(dir, "Unrecognised inode hash code %u",
194 +                                  root->info.hash_version);
195                 goto fail;
196         }
197         hinfo->hash_version = root->info.hash_version;
198 @@ -775,23 +782,26 @@ dx_probe(const struct qstr *d_name, struct inode *dir,
199         hash = hinfo->hash;
201         if (root->info.unused_flags & 1) {
202 -               ext4_warning(dir->i_sb, "Unimplemented inode hash flags: %#06x",
203 -                            root->info.unused_flags);
204 +               ext4_warning_inode(dir, "Unimplemented hash flags: %#06x",
205 +                                  root->info.unused_flags);
206                 goto fail;
207         }
209 -       if ((indirect = root->info.indirect_levels) > 1) {
210 -               ext4_warning(dir->i_sb, "Unimplemented inode hash depth: %#06x",
211 -                            root->info.indirect_levels);
212 +       indirect = root->info.indirect_levels;
213 +       if (indirect > 1) {
214 +               ext4_warning_inode(dir, "Unimplemented hash depth: %#06x",
215 +                                  root->info.indirect_levels);
216                 goto fail;
217         }
219 -       entries = (struct dx_entry *) (((char *)&root->info) +
220 -                                      root->info.info_length);
221 +       entries = (struct dx_entry *)(((char *)&root->info) +
222 +                                     root->info.info_length);
224         if (dx_get_limit(entries) != dx_root_limit(dir,
225                                                    root->info.info_length)) {
226 -               ext4_warning(dir->i_sb, "dx entry: limit != root limit");
227 +               ext4_warning_inode(dir, "dx entry: limit %u != root limit %u",
228 +                                  dx_get_limit(entries),
229 +                                  dx_root_limit(dir, root->info.info_length));
230                 goto fail;
231         }
233 @@ -799,15 +809,16 @@ dx_probe(const struct qstr *d_name, struct inode *dir,
234         while (1) {
235                 count = dx_get_count(entries);
236                 if (!count || count > dx_get_limit(entries)) {
237 -                       ext4_warning(dir->i_sb,
238 -                                    "dx entry: no count or count > limit");
239 +                       ext4_warning_inode(dir,
240 +                                          "dx entry: count %u beyond limit %u",
241 +                                          count, dx_get_limit(entries));
242                         goto fail;
243                 }
245                 p = entries + 1;
246                 q = entries + count - 1;
247                 while (p <= q) {
248 -                       m = p + (q - p)/2;
249 +                       m = p + (q - p) / 2;
250                         dxtrace(printk("."));
251                         if (dx_get_hash(m) > hash)
252                                 q = m - 1;
253 @@ -831,7 +842,8 @@ dx_probe(const struct qstr *d_name, struct inode *dir,
254                 }
256                 at = p - 1;
257 -               dxtrace(printk(" %x->%u\n", at == entries? 0: dx_get_hash(at), dx_get_block(at)));
258 +               dxtrace(printk(" %x->%u\n", at == entries ? 0 : dx_get_hash(at),
259 +                              dx_get_block(at)));
260                 frame->entries = entries;
261                 frame->at = at;
262                 if (!indirect--)
263 @@ -845,9 +857,10 @@ dx_probe(const struct qstr *d_name, struct inode *dir,
264                 }
265                 entries = ((struct dx_node *) frame->bh->b_data)->entries;
267 -               if (dx_get_limit(entries) != dx_node_limit (dir)) {
268 -                       ext4_warning(dir->i_sb,
269 -                                    "dx entry: limit != node limit");
270 +               if (dx_get_limit(entries) != dx_node_limit(dir)) {
271 +                       ext4_warning_inode(dir,
272 +                               "dx entry: limit %u != node limit %u",
273 +                               dx_get_limit(entries), dx_node_limit(dir));
274                         goto fail;
275                 }
276         }
277 @@ -858,18 +871,17 @@ fail:
278         }
280         if (ret_err == ERR_PTR(ERR_BAD_DX_DIR))
281 -               ext4_warning(dir->i_sb,
282 -                            "Corrupt dir inode %lu, running e2fsck is "
283 -                            "recommended.", dir->i_ino);
284 +               ext4_warning_inode(dir,
285 +                       "Corrupt directory, running e2fsck is recommended");
286         return ret_err;
289 -static void dx_release (struct dx_frame *frames)
290 +static void dx_release(struct dx_frame *frames)
292         if (frames[0].bh == NULL)
293                 return;
295 -       if (((struct dx_root *) frames[0].bh->b_data)->info.indirect_levels)
296 +       if (((struct dx_root *)frames[0].bh->b_data)->info.indirect_levels)
297                 brelse(frames[1].bh);
298         brelse(frames[0].bh);
300 @@ -1540,9 +1552,9 @@ static struct buffer_head * ext4_dx_find_entry(struct inode *dir, const struct q
301                 retval = ext4_htree_next_block(dir, hinfo.hash, frame,
302                                                frames, NULL);
303                 if (retval < 0) {
304 -                       ext4_warning(sb,
305 -                            "error %d reading index page in directory #%lu",
306 -                            retval, dir->i_ino);
307 +                       ext4_warning_inode(dir,
308 +                               "error %d reading directory index block",
309 +                               retval);
310                         bh = ERR_PTR(retval);
311                         goto errout;
312                 }
313 @@ -2267,7 +2279,7 @@ static int ext4_dx_add_entry(handle_t *handle, struct dentry *dentry,
315                 if (levels && (dx_get_count(frames->entries) ==
316                                dx_get_limit(frames->entries))) {
317 -                       ext4_warning(sb, "Directory index full!");
318 +                       ext4_warning_inode(dir, "Directory index full!");
319                         err = -ENOSPC;
320                         goto cleanup;
321                 }
322 @@ -2779,12 +2791,9 @@ int ext4_empty_dir(struct inode *inode)
323         de = (struct ext4_dir_entry_2 *) bh->b_data;
324         de1 = ext4_next_entry(de, sb->s_blocksize);
325         if (le32_to_cpu(de->inode) != inode->i_ino ||
326 -                       !le32_to_cpu(de1->inode) ||
327 -                       strcmp(".", de->name) ||
328 -                       strcmp("..", de1->name)) {
329 -               ext4_warning(inode->i_sb,
330 -                            "bad directory (dir #%lu) - no `.' or `..'",
331 -                            inode->i_ino);
332 +                       le32_to_cpu(de1->inode) == 0 ||
333 +                       strcmp(".", de->name) || strcmp("..", de1->name)) {
334 +               ext4_warning_inode(inode, "directory missing '.' and/or '..'");
335                 brelse(bh);
336                 return 1;
337         }
338 @@ -3037,8 +3046,9 @@ static int ext4_rmdir(struct inode *dir, struct dentry *dentry)
339         if (retval)
340                 goto end_rmdir;
341         if (!EXT4_DIR_LINK_EMPTY(inode))
342 -               ext4_warning(inode->i_sb,
343 -                            "empty directory has too many links (%d)",
344 +               ext4_warning_inode(inode,
345 +                            "empty directory '%.*s' has too many links (%u)",
346 +                            dentry->d_name.len, dentry->d_name.name,
347                              inode->i_nlink);
348         inode->i_version++;
349         clear_nlink(inode);
350 @@ -3098,10 +3108,9 @@ static int ext4_unlink(struct inode *dir, struct dentry *dentry)
351         if (IS_DIRSYNC(dir))
352                 ext4_handle_sync(handle);
354 -       if (!inode->i_nlink) {
355 -               ext4_warning(inode->i_sb,
356 -                            "Deleting nonexistent file (%lu), %d",
357 -                            inode->i_ino, inode->i_nlink);
358 +       if (inode->i_nlink == 0) {
359 +               ext4_warning_inode(inode, "Deleting file '%.*s' with no links",
360 +                                  dentry->d_name.len, dentry->d_name.name);
361                 set_nlink(inode, 1);
362         }
363         retval = ext4_delete_entry(handle, dir, de, bh);
364 @@ -3487,9 +3496,9 @@ static void ext4_rename_delete(handle_t *handle, struct ext4_renament *ent,
365         }
367         if (retval) {
368 -               ext4_warning(ent->dir->i_sb,
369 -                               "Deleting old file (%lu), %d, error=%d",
370 -                               ent->dir->i_ino, ent->dir->i_nlink, retval);
371 +               ext4_warning_inode(ent->dir,
372 +                                  "Deleting old file: nlink %d, error=%d",
373 +                                  ent->dir->i_nlink, retval);
374         }
377 diff --git a/fs/ext4/super.c b/fs/ext4/super.c
378 index f06d058..efef80a 100644
379 --- a/fs/ext4/super.c
380 +++ b/fs/ext4/super.c
381 @@ -589,14 +589,17 @@ void __ext4_msg(struct super_block *sb,
382         va_end(args);
385 +#define ext4_warning_ratelimit(sb)                                     \
386 +               ___ratelimit(&(EXT4_SB(sb)->s_warning_ratelimit_state), \
387 +                            "EXT4-fs warning")
389  void __ext4_warning(struct super_block *sb, const char *function,
390                     unsigned int line, const char *fmt, ...)
392         struct va_format vaf;
393         va_list args;
395 -       if (!___ratelimit(&(EXT4_SB(sb)->s_warning_ratelimit_state),
396 -                         "EXT4-fs warning"))
397 +       if (!ext4_warning_ratelimit(sb))
398                 return;
400         va_start(args, fmt);
401 @@ -607,6 +610,24 @@ void __ext4_warning(struct super_block *sb, const char *function,
402         va_end(args);
405 +void __ext4_warning_inode(const struct inode *inode, const char *function,
406 +                         unsigned int line, const char *fmt, ...)
408 +       struct va_format vaf;
409 +       va_list args;
411 +       if (!ext4_warning_ratelimit(inode->i_sb))
412 +               return;
414 +       va_start(args, fmt);
415 +       vaf.fmt = fmt;
416 +       vaf.va = &args;
417 +       printk(KERN_WARNING "EXT4-fs warning (device %s): %s:%d: "
418 +              "inode #%lu: comm %s: %pV\n", inode->i_sb->s_id,
419 +              function, line, inode->i_ino, current->comm, &vaf);
420 +       va_end(args);
423  void __ext4_grp_locked_error(const char *function, unsigned int line,
424                              struct super_block *sb, ext4_group_t grp,
425                              unsigned long ino, ext4_fsblk_t block,
426 -- 
427 1.7.3.4