aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ext4/dir.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/ext4/dir.c')
-rw-r--r--fs/ext4/dir.c41
1 files changed, 20 insertions, 21 deletions
diff --git a/fs/ext4/dir.c b/fs/ext4/dir.c
index 86cb6d86a048..374510f72baa 100644
--- a/fs/ext4/dir.c
+++ b/fs/ext4/dir.c
@@ -61,10 +61,11 @@ static unsigned char get_dtype(struct super_block *sb, int filetype)
61} 61}
62 62
63 63
64int ext4_check_dir_entry(const char *function, struct inode *dir, 64int __ext4_check_dir_entry(const char *function, unsigned int line,
65 struct ext4_dir_entry_2 *de, 65 struct inode *dir,
66 struct buffer_head *bh, 66 struct ext4_dir_entry_2 *de,
67 unsigned int offset) 67 struct buffer_head *bh,
68 unsigned int offset)
68{ 69{
69 const char *error_msg = NULL; 70 const char *error_msg = NULL;
70 const int rlen = ext4_rec_len_from_disk(de->rec_len, 71 const int rlen = ext4_rec_len_from_disk(de->rec_len,
@@ -83,12 +84,10 @@ int ext4_check_dir_entry(const char *function, struct inode *dir,
83 error_msg = "inode out of bounds"; 84 error_msg = "inode out of bounds";
84 85
85 if (error_msg != NULL) 86 if (error_msg != NULL)
86 __ext4_error(dir->i_sb, function, 87 ext4_error_inode(dir, function, line, bh->b_blocknr,
87 "bad entry in directory #%lu: %s - block=%llu" 88 "bad entry in directory: %s - "
88 "offset=%u(%u), inode=%u, rec_len=%d, name_len=%d", 89 "offset=%u(%u), inode=%u, rec_len=%d, name_len=%d",
89 dir->i_ino, error_msg, 90 error_msg, (unsigned) (offset%bh->b_size), offset,
90 (unsigned long long) bh->b_blocknr,
91 (unsigned) (offset%bh->b_size), offset,
92 le32_to_cpu(de->inode), 91 le32_to_cpu(de->inode),
93 rlen, de->name_len); 92 rlen, de->name_len);
94 return error_msg == NULL ? 1 : 0; 93 return error_msg == NULL ? 1 : 0;
@@ -111,7 +110,7 @@ static int ext4_readdir(struct file *filp,
111 110
112 if (EXT4_HAS_COMPAT_FEATURE(inode->i_sb, 111 if (EXT4_HAS_COMPAT_FEATURE(inode->i_sb,
113 EXT4_FEATURE_COMPAT_DIR_INDEX) && 112 EXT4_FEATURE_COMPAT_DIR_INDEX) &&
114 ((EXT4_I(inode)->i_flags & EXT4_INDEX_FL) || 113 ((ext4_test_inode_flag(inode, EXT4_INODE_INDEX)) ||
115 ((inode->i_size >> sb->s_blocksize_bits) == 1))) { 114 ((inode->i_size >> sb->s_blocksize_bits) == 1))) {
116 err = ext4_dx_readdir(filp, dirent, filldir); 115 err = ext4_dx_readdir(filp, dirent, filldir);
117 if (err != ERR_BAD_DX_DIR) { 116 if (err != ERR_BAD_DX_DIR) {
@@ -122,20 +121,21 @@ static int ext4_readdir(struct file *filp,
122 * We don't set the inode dirty flag since it's not 121 * We don't set the inode dirty flag since it's not
123 * critical that it get flushed back to the disk. 122 * critical that it get flushed back to the disk.
124 */ 123 */
125 EXT4_I(filp->f_path.dentry->d_inode)->i_flags &= ~EXT4_INDEX_FL; 124 ext4_clear_inode_flag(filp->f_path.dentry->d_inode,
125 EXT4_INODE_INDEX);
126 } 126 }
127 stored = 0; 127 stored = 0;
128 offset = filp->f_pos & (sb->s_blocksize - 1); 128 offset = filp->f_pos & (sb->s_blocksize - 1);
129 129
130 while (!error && !stored && filp->f_pos < inode->i_size) { 130 while (!error && !stored && filp->f_pos < inode->i_size) {
131 ext4_lblk_t blk = filp->f_pos >> EXT4_BLOCK_SIZE_BITS(sb); 131 struct ext4_map_blocks map;
132 struct buffer_head map_bh;
133 struct buffer_head *bh = NULL; 132 struct buffer_head *bh = NULL;
134 133
135 map_bh.b_state = 0; 134 map.m_lblk = filp->f_pos >> EXT4_BLOCK_SIZE_BITS(sb);
136 err = ext4_get_blocks(NULL, inode, blk, 1, &map_bh, 0); 135 map.m_len = 1;
136 err = ext4_map_blocks(NULL, inode, &map, 0);
137 if (err > 0) { 137 if (err > 0) {
138 pgoff_t index = map_bh.b_blocknr >> 138 pgoff_t index = map.m_pblk >>
139 (PAGE_CACHE_SHIFT - inode->i_blkbits); 139 (PAGE_CACHE_SHIFT - inode->i_blkbits);
140 if (!ra_has_index(&filp->f_ra, index)) 140 if (!ra_has_index(&filp->f_ra, index))
141 page_cache_sync_readahead( 141 page_cache_sync_readahead(
@@ -143,7 +143,7 @@ static int ext4_readdir(struct file *filp,
143 &filp->f_ra, filp, 143 &filp->f_ra, filp,
144 index, 1); 144 index, 1);
145 filp->f_ra.prev_pos = (loff_t)index << PAGE_CACHE_SHIFT; 145 filp->f_ra.prev_pos = (loff_t)index << PAGE_CACHE_SHIFT;
146 bh = ext4_bread(NULL, inode, blk, 0, &err); 146 bh = ext4_bread(NULL, inode, map.m_lblk, 0, &err);
147 } 147 }
148 148
149 /* 149 /*
@@ -152,9 +152,8 @@ static int ext4_readdir(struct file *filp,
152 */ 152 */
153 if (!bh) { 153 if (!bh) {
154 if (!dir_has_error) { 154 if (!dir_has_error) {
155 ext4_error(sb, "directory #%lu " 155 EXT4_ERROR_INODE(inode, "directory "
156 "contains a hole at offset %Lu", 156 "contains a hole at offset %Lu",
157 inode->i_ino,
158 (unsigned long long) filp->f_pos); 157 (unsigned long long) filp->f_pos);
159 dir_has_error = 1; 158 dir_has_error = 1;
160 } 159 }
@@ -195,7 +194,7 @@ revalidate:
195 while (!error && filp->f_pos < inode->i_size 194 while (!error && filp->f_pos < inode->i_size
196 && offset < sb->s_blocksize) { 195 && offset < sb->s_blocksize) {
197 de = (struct ext4_dir_entry_2 *) (bh->b_data + offset); 196 de = (struct ext4_dir_entry_2 *) (bh->b_data + offset);
198 if (!ext4_check_dir_entry("ext4_readdir", inode, de, 197 if (!ext4_check_dir_entry(inode, de,
199 bh, offset)) { 198 bh, offset)) {
200 /* 199 /*
201 * On error, skip the f_pos to the next block 200 * On error, skip the f_pos to the next block
@@ -345,7 +344,7 @@ int ext4_htree_store_dirent(struct file *dir_file, __u32 hash,
345 struct dir_private_info *info; 344 struct dir_private_info *info;
346 int len; 345 int len;
347 346
348 info = (struct dir_private_info *) dir_file->private_data; 347 info = dir_file->private_data;
349 p = &info->root.rb_node; 348 p = &info->root.rb_node;
350 349
351 /* Create and allocate the fname structure */ 350 /* Create and allocate the fname structure */