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>
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
31 #define ext_debug(fmt, ...) no_printk(fmt, ##__VA_ARGS__)
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,
48 void __ext4_warning(struct super_block *, const char *, unsigned int,
50 +extern __printf(4, 5)
51 +void __ext4_warning_inode(const struct inode *inode, const char *function,
52 + unsigned int line, const char *fmt, ...);
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,
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)
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, " "); \
85 +#define ext4_warning_inode(inode, fmt, ...) \
87 + no_printk(fmt, ##__VA_ARGS__); \
88 + __ext4_warning_inode(inode, "", 0, " "); \
90 #define ext4_msg(sb, level, fmt, ...) \
92 no_printk(fmt, ##__VA_ARGS__); \
93 diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
94 index 814f3be..45539b6 100644
97 @@ -84,12 +84,13 @@ typedef enum {
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,
106 - dirblock_type_t type,
109 + dirblock_type_t type,
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);
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));
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);
137 dirent = (struct ext4_dir_entry *) bh->b_data;
138 @@ -119,7 +122,7 @@ static struct buffer_head *__ext4_read_dirblock(struct inode *inode,
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);
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);
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");
156 return ERR_PTR(-EIO);
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);
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");
167 return ERR_PTR(-EIO);
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,
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);
197 hinfo->hash_version = root->info.hash_version;
198 @@ -775,23 +782,26 @@ dx_probe(const struct qstr *d_name, struct inode *dir,
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);
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);
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));
233 @@ -799,15 +809,16 @@ dx_probe(const struct qstr *d_name, struct inode *dir,
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));
246 q = entries + count - 1;
249 + m = p + (q - p) / 2;
250 dxtrace(printk("."));
251 if (dx_get_hash(m) > hash)
253 @@ -831,7 +842,8 @@ dx_probe(const struct qstr *d_name, struct inode *dir,
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;
263 @@ -845,9 +857,10 @@ dx_probe(const struct qstr *d_name, struct inode *dir,
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));
277 @@ -858,18 +871,17 @@ fail:
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");
289 -static void dx_release (struct dx_frame *frames)
290 +static void dx_release(struct dx_frame *frames)
292 if (frames[0].bh == NULL)
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,
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",
310 bh = ERR_PTR(retval);
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!");
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 `..'",
332 + le32_to_cpu(de1->inode) == 0 ||
333 + strcmp(".", de->name) || strcmp("..", de1->name)) {
334 + ext4_warning_inode(inode, "directory missing '.' and/or '..'");
338 @@ -3037,8 +3046,9 @@ static int ext4_rmdir(struct inode *dir, struct dentry *dentry)
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,
350 @@ -3098,10 +3108,9 @@ static int ext4_unlink(struct inode *dir, struct dentry *dentry)
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);
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,
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);
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,
385 +#define ext4_warning_ratelimit(sb) \
386 + ___ratelimit(&(EXT4_SB(sb)->s_warning_ratelimit_state), \
389 void __ext4_warning(struct super_block *sb, const char *function,
390 unsigned int line, const char *fmt, ...)
392 struct va_format vaf;
395 - if (!___ratelimit(&(EXT4_SB(sb)->s_warning_ratelimit_state),
396 - "EXT4-fs warning"))
397 + if (!ext4_warning_ratelimit(sb))
401 @@ -607,6 +610,24 @@ void __ext4_warning(struct super_block *sb, const char *function,
405 +void __ext4_warning_inode(const struct inode *inode, const char *function,
406 + unsigned int line, const char *fmt, ...)
408 + struct va_format vaf;
411 + if (!ext4_warning_ratelimit(inode->i_sb))
414 + va_start(args, fmt);
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);
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,