diff options
author | Theodore Ts'o <tytso@mit.edu> | 2011-01-10 12:10:55 -0500 |
---|---|---|
committer | Theodore Ts'o <tytso@mit.edu> | 2011-01-10 12:10:55 -0500 |
commit | f7c21177af0b32a2cd9ee36189637f0c1f0e1e17 (patch) | |
tree | ba83d4ddcd4b7e15ff575f0b75013ba9ed62f249 | |
parent | f9a62d090cf47fae2fe6f6bd8eb9f24482573fd8 (diff) |
ext4: Use ext4_error_file() to print the pathname to the corrupted inode
Where the file pointer is available, use ext4_error_file() instead of
ext4_error_inode().
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
-rw-r--r-- | fs/ext4/dir.c | 30 | ||||
-rw-r--r-- | fs/ext4/ext4.h | 15 | ||||
-rw-r--r-- | fs/ext4/namei.c | 10 | ||||
-rw-r--r-- | fs/ext4/super.c | 28 |
4 files changed, 49 insertions, 34 deletions
diff --git a/fs/ext4/dir.c b/fs/ext4/dir.c index bd5d74d06399..164c56092e58 100644 --- a/fs/ext4/dir.c +++ b/fs/ext4/dir.c | |||
@@ -66,7 +66,7 @@ static unsigned char get_dtype(struct super_block *sb, int filetype) | |||
66 | * Note: this is the opposite of what ext2 and ext3 historically returned... | 66 | * Note: this is the opposite of what ext2 and ext3 historically returned... |
67 | */ | 67 | */ |
68 | int __ext4_check_dir_entry(const char *function, unsigned int line, | 68 | int __ext4_check_dir_entry(const char *function, unsigned int line, |
69 | struct inode *dir, | 69 | struct inode *dir, struct file *filp, |
70 | struct ext4_dir_entry_2 *de, | 70 | struct ext4_dir_entry_2 *de, |
71 | struct buffer_head *bh, | 71 | struct buffer_head *bh, |
72 | unsigned int offset) | 72 | unsigned int offset) |
@@ -90,12 +90,21 @@ int __ext4_check_dir_entry(const char *function, unsigned int line, | |||
90 | else | 90 | else |
91 | return 0; | 91 | return 0; |
92 | 92 | ||
93 | ext4_error_inode(dir, function, line, bh->b_blocknr, | 93 | if (filp) |
94 | "bad entry in directory: %s - " | 94 | ext4_error_file(filp, function, line, bh ? bh->b_blocknr : 0, |
95 | "offset=%u(%u), inode=%u, rec_len=%d, name_len=%d", | 95 | "bad entry in directory: %s - offset=%u(%u), " |
96 | error_msg, (unsigned) (offset%bh->b_size), offset, | 96 | "inode=%u, rec_len=%d, name_len=%d", |
97 | le32_to_cpu(de->inode), | 97 | error_msg, (unsigned) (offset%bh->b_size), |
98 | rlen, de->name_len); | 98 | offset, le32_to_cpu(de->inode), |
99 | rlen, de->name_len); | ||
100 | else | ||
101 | ext4_error_inode(dir, function, line, bh ? bh->b_blocknr : 0, | ||
102 | "bad entry in directory: %s - offset=%u(%u), " | ||
103 | "inode=%u, rec_len=%d, name_len=%d", | ||
104 | error_msg, (unsigned) (offset%bh->b_size), | ||
105 | offset, le32_to_cpu(de->inode), | ||
106 | rlen, de->name_len); | ||
107 | |||
99 | return 1; | 108 | return 1; |
100 | } | 109 | } |
101 | 110 | ||
@@ -158,8 +167,9 @@ static int ext4_readdir(struct file *filp, | |||
158 | */ | 167 | */ |
159 | if (!bh) { | 168 | if (!bh) { |
160 | if (!dir_has_error) { | 169 | if (!dir_has_error) { |
161 | EXT4_ERROR_INODE(inode, "directory " | 170 | EXT4_ERROR_FILE(filp, 0, |
162 | "contains a hole at offset %Lu", | 171 | "directory contains a " |
172 | "hole at offset %llu", | ||
163 | (unsigned long long) filp->f_pos); | 173 | (unsigned long long) filp->f_pos); |
164 | dir_has_error = 1; | 174 | dir_has_error = 1; |
165 | } | 175 | } |
@@ -200,7 +210,7 @@ revalidate: | |||
200 | while (!error && filp->f_pos < inode->i_size | 210 | while (!error && filp->f_pos < inode->i_size |
201 | && offset < sb->s_blocksize) { | 211 | && offset < sb->s_blocksize) { |
202 | de = (struct ext4_dir_entry_2 *) (bh->b_data + offset); | 212 | de = (struct ext4_dir_entry_2 *) (bh->b_data + offset); |
203 | if (ext4_check_dir_entry(inode, de, | 213 | if (ext4_check_dir_entry(inode, filp, de, |
204 | bh, offset)) { | 214 | bh, offset)) { |
205 | /* | 215 | /* |
206 | * On error, skip the f_pos to the next block | 216 | * On error, skip the f_pos to the next block |
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h index 8104ab7eb7d4..2a739255ee05 100644 --- a/fs/ext4/ext4.h +++ b/fs/ext4/ext4.h | |||
@@ -62,8 +62,8 @@ | |||
62 | #define EXT4_ERROR_INODE_BLOCK(inode, block, fmt, a...) \ | 62 | #define EXT4_ERROR_INODE_BLOCK(inode, block, fmt, a...) \ |
63 | ext4_error_inode((inode), __func__, __LINE__, (block), (fmt), ## a) | 63 | ext4_error_inode((inode), __func__, __LINE__, (block), (fmt), ## a) |
64 | 64 | ||
65 | #define EXT4_ERROR_FILE(file, fmt, a...) \ | 65 | #define EXT4_ERROR_FILE(file, block, fmt, a...) \ |
66 | ext4_error_file(__func__, __LINE__, (file), (fmt), ## a) | 66 | ext4_error_file((file), __func__, __LINE__, (block), (fmt), ## a) |
67 | 67 | ||
68 | /* data type for block offset of block group */ | 68 | /* data type for block offset of block group */ |
69 | typedef int ext4_grpblk_t; | 69 | typedef int ext4_grpblk_t; |
@@ -1640,11 +1640,12 @@ extern unsigned ext4_init_block_bitmap(struct super_block *sb, | |||
1640 | 1640 | ||
1641 | /* dir.c */ | 1641 | /* dir.c */ |
1642 | extern int __ext4_check_dir_entry(const char *, unsigned int, struct inode *, | 1642 | extern int __ext4_check_dir_entry(const char *, unsigned int, struct inode *, |
1643 | struct file *, | ||
1643 | struct ext4_dir_entry_2 *, | 1644 | struct ext4_dir_entry_2 *, |
1644 | struct buffer_head *, unsigned int); | 1645 | struct buffer_head *, unsigned int); |
1645 | #define ext4_check_dir_entry(dir, de, bh, offset) \ | 1646 | #define ext4_check_dir_entry(dir, filp, de, bh, offset) \ |
1646 | unlikely(__ext4_check_dir_entry(__func__, __LINE__, (dir), (de), \ | 1647 | unlikely(__ext4_check_dir_entry(__func__, __LINE__, (dir), (filp), \ |
1647 | (bh), (offset))) | 1648 | (de), (bh), (offset))) |
1648 | extern int ext4_htree_store_dirent(struct file *dir_file, __u32 hash, | 1649 | extern int ext4_htree_store_dirent(struct file *dir_file, __u32 hash, |
1649 | __u32 minor_hash, | 1650 | __u32 minor_hash, |
1650 | struct ext4_dir_entry_2 *dirent); | 1651 | struct ext4_dir_entry_2 *dirent); |
@@ -1751,8 +1752,8 @@ extern void ext4_error_inode(struct inode *, const char *, unsigned int, | |||
1751 | ext4_fsblk_t, const char *, ...) | 1752 | ext4_fsblk_t, const char *, ...) |
1752 | __attribute__ ((format (printf, 5, 6))); | 1753 | __attribute__ ((format (printf, 5, 6))); |
1753 | extern void ext4_error_file(struct file *, const char *, unsigned int, | 1754 | extern void ext4_error_file(struct file *, const char *, unsigned int, |
1754 | const char *, ...) | 1755 | ext4_fsblk_t, const char *, ...) |
1755 | __attribute__ ((format (printf, 4, 5))); | 1756 | __attribute__ ((format (printf, 5, 6))); |
1756 | extern void __ext4_std_error(struct super_block *, const char *, | 1757 | extern void __ext4_std_error(struct super_block *, const char *, |
1757 | unsigned int, int); | 1758 | unsigned int, int); |
1758 | extern void __ext4_abort(struct super_block *, const char *, unsigned int, | 1759 | extern void __ext4_abort(struct super_block *, const char *, unsigned int, |
diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c index e275464f7754..96a594d86a19 100644 --- a/fs/ext4/namei.c +++ b/fs/ext4/namei.c | |||
@@ -581,7 +581,7 @@ static int htree_dirblock_to_tree(struct file *dir_file, | |||
581 | dir->i_sb->s_blocksize - | 581 | dir->i_sb->s_blocksize - |
582 | EXT4_DIR_REC_LEN(0)); | 582 | EXT4_DIR_REC_LEN(0)); |
583 | for (; de < top; de = ext4_next_entry(de, dir->i_sb->s_blocksize)) { | 583 | for (; de < top; de = ext4_next_entry(de, dir->i_sb->s_blocksize)) { |
584 | if (ext4_check_dir_entry(dir, de, bh, | 584 | if (ext4_check_dir_entry(dir, NULL, de, bh, |
585 | (block<<EXT4_BLOCK_SIZE_BITS(dir->i_sb)) | 585 | (block<<EXT4_BLOCK_SIZE_BITS(dir->i_sb)) |
586 | + ((char *)de - bh->b_data))) { | 586 | + ((char *)de - bh->b_data))) { |
587 | /* On error, skip the f_pos to the next block. */ | 587 | /* On error, skip the f_pos to the next block. */ |
@@ -820,7 +820,7 @@ static inline int search_dirblock(struct buffer_head *bh, | |||
820 | if ((char *) de + namelen <= dlimit && | 820 | if ((char *) de + namelen <= dlimit && |
821 | ext4_match (namelen, name, de)) { | 821 | ext4_match (namelen, name, de)) { |
822 | /* found a match - just to be sure, do a full check */ | 822 | /* found a match - just to be sure, do a full check */ |
823 | if (ext4_check_dir_entry(dir, de, bh, offset)) | 823 | if (ext4_check_dir_entry(dir, NULL, de, bh, offset)) |
824 | return -1; | 824 | return -1; |
825 | *res_dir = de; | 825 | *res_dir = de; |
826 | return 1; | 826 | return 1; |
@@ -1269,7 +1269,7 @@ static int add_dirent_to_buf(handle_t *handle, struct dentry *dentry, | |||
1269 | de = (struct ext4_dir_entry_2 *)bh->b_data; | 1269 | de = (struct ext4_dir_entry_2 *)bh->b_data; |
1270 | top = bh->b_data + blocksize - reclen; | 1270 | top = bh->b_data + blocksize - reclen; |
1271 | while ((char *) de <= top) { | 1271 | while ((char *) de <= top) { |
1272 | if (ext4_check_dir_entry(dir, de, bh, offset)) | 1272 | if (ext4_check_dir_entry(dir, NULL, de, bh, offset)) |
1273 | return -EIO; | 1273 | return -EIO; |
1274 | if (ext4_match(namelen, name, de)) | 1274 | if (ext4_match(namelen, name, de)) |
1275 | return -EEXIST; | 1275 | return -EEXIST; |
@@ -1636,7 +1636,7 @@ static int ext4_delete_entry(handle_t *handle, | |||
1636 | pde = NULL; | 1636 | pde = NULL; |
1637 | de = (struct ext4_dir_entry_2 *) bh->b_data; | 1637 | de = (struct ext4_dir_entry_2 *) bh->b_data; |
1638 | while (i < bh->b_size) { | 1638 | while (i < bh->b_size) { |
1639 | if (ext4_check_dir_entry(dir, de, bh, i)) | 1639 | if (ext4_check_dir_entry(dir, NULL, de, bh, i)) |
1640 | return -EIO; | 1640 | return -EIO; |
1641 | if (de == de_del) { | 1641 | if (de == de_del) { |
1642 | BUFFER_TRACE(bh, "get_write_access"); | 1642 | BUFFER_TRACE(bh, "get_write_access"); |
@@ -1919,7 +1919,7 @@ static int empty_dir(struct inode *inode) | |||
1919 | } | 1919 | } |
1920 | de = (struct ext4_dir_entry_2 *) bh->b_data; | 1920 | de = (struct ext4_dir_entry_2 *) bh->b_data; |
1921 | } | 1921 | } |
1922 | if (ext4_check_dir_entry(inode, de, bh, offset)) { | 1922 | if (ext4_check_dir_entry(inode, NULL, de, bh, offset)) { |
1923 | de = (struct ext4_dir_entry_2 *)(bh->b_data + | 1923 | de = (struct ext4_dir_entry_2 *)(bh->b_data + |
1924 | sb->s_blocksize); | 1924 | sb->s_blocksize); |
1925 | offset = (offset | (sb->s_blocksize - 1)) + 1; | 1925 | offset = (offset | (sb->s_blocksize - 1)) + 1; |
diff --git a/fs/ext4/super.c b/fs/ext4/super.c index d49e3b1ec41e..7728a4ca3d6c 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c | |||
@@ -406,28 +406,31 @@ void ext4_error_inode(struct inode *inode, const char *function, | |||
406 | const char *fmt, ...) | 406 | const char *fmt, ...) |
407 | { | 407 | { |
408 | va_list args; | 408 | va_list args; |
409 | struct va_format vaf; | ||
409 | struct ext4_super_block *es = EXT4_SB(inode->i_sb)->s_es; | 410 | struct ext4_super_block *es = EXT4_SB(inode->i_sb)->s_es; |
410 | 411 | ||
411 | es->s_last_error_ino = cpu_to_le32(inode->i_ino); | 412 | es->s_last_error_ino = cpu_to_le32(inode->i_ino); |
412 | es->s_last_error_block = cpu_to_le64(block); | 413 | es->s_last_error_block = cpu_to_le64(block); |
413 | save_error_info(inode->i_sb, function, line); | 414 | save_error_info(inode->i_sb, function, line); |
414 | va_start(args, fmt); | 415 | va_start(args, fmt); |
416 | vaf.fmt = fmt; | ||
417 | vaf.va = &args; | ||
415 | printk(KERN_CRIT "EXT4-fs error (device %s): %s:%d: inode #%lu: ", | 418 | printk(KERN_CRIT "EXT4-fs error (device %s): %s:%d: inode #%lu: ", |
416 | inode->i_sb->s_id, function, line, inode->i_ino); | 419 | inode->i_sb->s_id, function, line, inode->i_ino); |
417 | if (block) | 420 | if (block) |
418 | printk("block %llu: ", block); | 421 | printk(KERN_CONT "block %llu: ", block); |
419 | printk("comm %s: ", current->comm); | 422 | printk(KERN_CONT "comm %s: %pV\n", current->comm, &vaf); |
420 | vprintk(fmt, args); | ||
421 | printk("\n"); | ||
422 | va_end(args); | 423 | va_end(args); |
423 | 424 | ||
424 | ext4_handle_error(inode->i_sb); | 425 | ext4_handle_error(inode->i_sb); |
425 | } | 426 | } |
426 | 427 | ||
427 | void ext4_error_file(struct file *file, const char *function, | 428 | void ext4_error_file(struct file *file, const char *function, |
428 | unsigned int line, const char *fmt, ...) | 429 | unsigned int line, ext4_fsblk_t block, |
430 | const char *fmt, ...) | ||
429 | { | 431 | { |
430 | va_list args; | 432 | va_list args; |
433 | struct va_format vaf; | ||
431 | struct ext4_super_block *es; | 434 | struct ext4_super_block *es; |
432 | struct inode *inode = file->f_dentry->d_inode; | 435 | struct inode *inode = file->f_dentry->d_inode; |
433 | char pathname[80], *path; | 436 | char pathname[80], *path; |
@@ -435,17 +438,18 @@ void ext4_error_file(struct file *file, const char *function, | |||
435 | es = EXT4_SB(inode->i_sb)->s_es; | 438 | es = EXT4_SB(inode->i_sb)->s_es; |
436 | es->s_last_error_ino = cpu_to_le32(inode->i_ino); | 439 | es->s_last_error_ino = cpu_to_le32(inode->i_ino); |
437 | save_error_info(inode->i_sb, function, line); | 440 | save_error_info(inode->i_sb, function, line); |
438 | va_start(args, fmt); | ||
439 | path = d_path(&(file->f_path), pathname, sizeof(pathname)); | 441 | path = d_path(&(file->f_path), pathname, sizeof(pathname)); |
440 | if (IS_ERR(path)) | 442 | if (IS_ERR(path)) |
441 | path = "(unknown)"; | 443 | path = "(unknown)"; |
442 | printk(KERN_CRIT | 444 | printk(KERN_CRIT |
443 | "EXT4-fs error (device %s): %s:%d: inode #%lu " | 445 | "EXT4-fs error (device %s): %s:%d: inode #%lu: ", |
444 | "(comm %s path %s): ", | 446 | inode->i_sb->s_id, function, line, inode->i_ino); |
445 | inode->i_sb->s_id, function, line, inode->i_ino, | 447 | if (block) |
446 | current->comm, path); | 448 | printk(KERN_CONT "block %llu: ", block); |
447 | vprintk(fmt, args); | 449 | va_start(args, fmt); |
448 | printk("\n"); | 450 | vaf.fmt = fmt; |
451 | vaf.va = &args; | ||
452 | printk(KERN_CONT "comm %s: path %s: %pV\n", current->comm, path, &vaf); | ||
449 | va_end(args); | 453 | va_end(args); |
450 | 454 | ||
451 | ext4_handle_error(inode->i_sb); | 455 | ext4_handle_error(inode->i_sb); |