diff options
Diffstat (limited to 'fs/ext4/dir.c')
| -rw-r--r-- | fs/ext4/dir.c | 64 |
1 files changed, 35 insertions, 29 deletions
diff --git a/fs/ext4/dir.c b/fs/ext4/dir.c index ec8e33b45219..3ca6a2b7632d 100644 --- a/fs/ext4/dir.c +++ b/fs/ext4/dir.c | |||
| @@ -33,10 +33,10 @@ static unsigned char ext4_filetype_table[] = { | |||
| 33 | }; | 33 | }; |
| 34 | 34 | ||
| 35 | static int ext4_readdir(struct file *, void *, filldir_t); | 35 | static int ext4_readdir(struct file *, void *, filldir_t); |
| 36 | static int ext4_dx_readdir(struct file * filp, | 36 | static int ext4_dx_readdir(struct file *filp, |
| 37 | void * dirent, filldir_t filldir); | 37 | void *dirent, filldir_t filldir); |
| 38 | static int ext4_release_dir (struct inode * inode, | 38 | static int ext4_release_dir(struct inode *inode, |
| 39 | struct file * filp); | 39 | struct file *filp); |
| 40 | 40 | ||
| 41 | const struct file_operations ext4_dir_operations = { | 41 | const struct file_operations ext4_dir_operations = { |
| 42 | .llseek = generic_file_llseek, | 42 | .llseek = generic_file_llseek, |
| @@ -61,12 +61,12 @@ static unsigned char get_dtype(struct super_block *sb, int filetype) | |||
| 61 | } | 61 | } |
| 62 | 62 | ||
| 63 | 63 | ||
| 64 | int ext4_check_dir_entry (const char * function, struct inode * dir, | 64 | int ext4_check_dir_entry(const char *function, struct inode *dir, |
| 65 | struct ext4_dir_entry_2 * de, | 65 | struct ext4_dir_entry_2 *de, |
| 66 | struct buffer_head * bh, | 66 | struct buffer_head *bh, |
| 67 | unsigned long offset) | 67 | unsigned long offset) |
| 68 | { | 68 | { |
| 69 | const char * error_msg = NULL; | 69 | const char *error_msg = NULL; |
| 70 | const int rlen = ext4_rec_len_from_disk(de->rec_len); | 70 | const int rlen = ext4_rec_len_from_disk(de->rec_len); |
| 71 | 71 | ||
| 72 | if (rlen < EXT4_DIR_REC_LEN(1)) | 72 | if (rlen < EXT4_DIR_REC_LEN(1)) |
| @@ -82,7 +82,7 @@ int ext4_check_dir_entry (const char * function, struct inode * dir, | |||
| 82 | error_msg = "inode out of bounds"; | 82 | error_msg = "inode out of bounds"; |
| 83 | 83 | ||
| 84 | if (error_msg != NULL) | 84 | if (error_msg != NULL) |
| 85 | ext4_error (dir->i_sb, function, | 85 | ext4_error(dir->i_sb, function, |
| 86 | "bad entry in directory #%lu: %s - " | 86 | "bad entry in directory #%lu: %s - " |
| 87 | "offset=%lu, inode=%lu, rec_len=%d, name_len=%d", | 87 | "offset=%lu, inode=%lu, rec_len=%d, name_len=%d", |
| 88 | dir->i_ino, error_msg, offset, | 88 | dir->i_ino, error_msg, offset, |
| @@ -91,8 +91,8 @@ int ext4_check_dir_entry (const char * function, struct inode * dir, | |||
| 91 | return error_msg == NULL ? 1 : 0; | 91 | return error_msg == NULL ? 1 : 0; |
| 92 | } | 92 | } |
| 93 | 93 | ||
| 94 | static int ext4_readdir(struct file * filp, | 94 | static int ext4_readdir(struct file *filp, |
| 95 | void * dirent, filldir_t filldir) | 95 | void *dirent, filldir_t filldir) |
| 96 | { | 96 | { |
| 97 | int error = 0; | 97 | int error = 0; |
| 98 | unsigned long offset; | 98 | unsigned long offset; |
| @@ -102,6 +102,7 @@ static int ext4_readdir(struct file * filp, | |||
| 102 | int err; | 102 | int err; |
| 103 | struct inode *inode = filp->f_path.dentry->d_inode; | 103 | struct inode *inode = filp->f_path.dentry->d_inode; |
| 104 | int ret = 0; | 104 | int ret = 0; |
| 105 | int dir_has_error = 0; | ||
| 105 | 106 | ||
| 106 | sb = inode->i_sb; | 107 | sb = inode->i_sb; |
| 107 | 108 | ||
| @@ -148,9 +149,13 @@ static int ext4_readdir(struct file * filp, | |||
| 148 | * of recovering data when there's a bad sector | 149 | * of recovering data when there's a bad sector |
| 149 | */ | 150 | */ |
| 150 | if (!bh) { | 151 | if (!bh) { |
| 151 | ext4_error (sb, "ext4_readdir", | 152 | if (!dir_has_error) { |
| 152 | "directory #%lu contains a hole at offset %lu", | 153 | ext4_error(sb, __func__, "directory #%lu " |
| 153 | inode->i_ino, (unsigned long)filp->f_pos); | 154 | "contains a hole at offset %Lu", |
| 155 | inode->i_ino, | ||
| 156 | (unsigned long long) filp->f_pos); | ||
| 157 | dir_has_error = 1; | ||
| 158 | } | ||
| 154 | /* corrupt size? Maybe no more blocks to read */ | 159 | /* corrupt size? Maybe no more blocks to read */ |
| 155 | if (filp->f_pos > inode->i_blocks << 9) | 160 | if (filp->f_pos > inode->i_blocks << 9) |
| 156 | break; | 161 | break; |
| @@ -187,14 +192,14 @@ revalidate: | |||
| 187 | while (!error && filp->f_pos < inode->i_size | 192 | while (!error && filp->f_pos < inode->i_size |
| 188 | && offset < sb->s_blocksize) { | 193 | && offset < sb->s_blocksize) { |
| 189 | de = (struct ext4_dir_entry_2 *) (bh->b_data + offset); | 194 | de = (struct ext4_dir_entry_2 *) (bh->b_data + offset); |
| 190 | if (!ext4_check_dir_entry ("ext4_readdir", inode, de, | 195 | if (!ext4_check_dir_entry("ext4_readdir", inode, de, |
| 191 | bh, offset)) { | 196 | bh, offset)) { |
| 192 | /* | 197 | /* |
| 193 | * On error, skip the f_pos to the next block | 198 | * On error, skip the f_pos to the next block |
| 194 | */ | 199 | */ |
| 195 | filp->f_pos = (filp->f_pos | | 200 | filp->f_pos = (filp->f_pos | |
| 196 | (sb->s_blocksize - 1)) + 1; | 201 | (sb->s_blocksize - 1)) + 1; |
| 197 | brelse (bh); | 202 | brelse(bh); |
| 198 | ret = stored; | 203 | ret = stored; |
| 199 | goto out; | 204 | goto out; |
| 200 | } | 205 | } |
| @@ -218,12 +223,12 @@ revalidate: | |||
| 218 | break; | 223 | break; |
| 219 | if (version != filp->f_version) | 224 | if (version != filp->f_version) |
| 220 | goto revalidate; | 225 | goto revalidate; |
| 221 | stored ++; | 226 | stored++; |
| 222 | } | 227 | } |
| 223 | filp->f_pos += ext4_rec_len_from_disk(de->rec_len); | 228 | filp->f_pos += ext4_rec_len_from_disk(de->rec_len); |
| 224 | } | 229 | } |
| 225 | offset = 0; | 230 | offset = 0; |
| 226 | brelse (bh); | 231 | brelse(bh); |
| 227 | } | 232 | } |
| 228 | out: | 233 | out: |
| 229 | return ret; | 234 | return ret; |
| @@ -290,9 +295,9 @@ static void free_rb_tree_fname(struct rb_root *root) | |||
| 290 | parent = rb_parent(n); | 295 | parent = rb_parent(n); |
| 291 | fname = rb_entry(n, struct fname, rb_hash); | 296 | fname = rb_entry(n, struct fname, rb_hash); |
| 292 | while (fname) { | 297 | while (fname) { |
| 293 | struct fname * old = fname; | 298 | struct fname *old = fname; |
| 294 | fname = fname->next; | 299 | fname = fname->next; |
| 295 | kfree (old); | 300 | kfree(old); |
| 296 | } | 301 | } |
| 297 | if (!parent) | 302 | if (!parent) |
| 298 | root->rb_node = NULL; | 303 | root->rb_node = NULL; |
| @@ -331,7 +336,7 @@ int ext4_htree_store_dirent(struct file *dir_file, __u32 hash, | |||
| 331 | struct ext4_dir_entry_2 *dirent) | 336 | struct ext4_dir_entry_2 *dirent) |
| 332 | { | 337 | { |
| 333 | struct rb_node **p, *parent = NULL; | 338 | struct rb_node **p, *parent = NULL; |
| 334 | struct fname * fname, *new_fn; | 339 | struct fname *fname, *new_fn; |
| 335 | struct dir_private_info *info; | 340 | struct dir_private_info *info; |
| 336 | int len; | 341 | int len; |
| 337 | 342 | ||
| @@ -388,19 +393,20 @@ int ext4_htree_store_dirent(struct file *dir_file, __u32 hash, | |||
| 388 | * for all entres on the fname linked list. (Normally there is only | 393 | * for all entres on the fname linked list. (Normally there is only |
| 389 | * one entry on the linked list, unless there are 62 bit hash collisions.) | 394 | * one entry on the linked list, unless there are 62 bit hash collisions.) |
| 390 | */ | 395 | */ |
| 391 | static int call_filldir(struct file * filp, void * dirent, | 396 | static int call_filldir(struct file *filp, void *dirent, |
| 392 | filldir_t filldir, struct fname *fname) | 397 | filldir_t filldir, struct fname *fname) |
| 393 | { | 398 | { |
| 394 | struct dir_private_info *info = filp->private_data; | 399 | struct dir_private_info *info = filp->private_data; |
| 395 | loff_t curr_pos; | 400 | loff_t curr_pos; |
| 396 | struct inode *inode = filp->f_path.dentry->d_inode; | 401 | struct inode *inode = filp->f_path.dentry->d_inode; |
| 397 | struct super_block * sb; | 402 | struct super_block *sb; |
| 398 | int error; | 403 | int error; |
| 399 | 404 | ||
| 400 | sb = inode->i_sb; | 405 | sb = inode->i_sb; |
| 401 | 406 | ||
| 402 | if (!fname) { | 407 | if (!fname) { |
| 403 | printk("call_filldir: called with null fname?!?\n"); | 408 | printk(KERN_ERR "ext4: call_filldir: called with " |
| 409 | "null fname?!?\n"); | ||
| 404 | return 0; | 410 | return 0; |
| 405 | } | 411 | } |
| 406 | curr_pos = hash2pos(fname->hash, fname->minor_hash); | 412 | curr_pos = hash2pos(fname->hash, fname->minor_hash); |
| @@ -419,8 +425,8 @@ static int call_filldir(struct file * filp, void * dirent, | |||
| 419 | return 0; | 425 | return 0; |
| 420 | } | 426 | } |
| 421 | 427 | ||
| 422 | static int ext4_dx_readdir(struct file * filp, | 428 | static int ext4_dx_readdir(struct file *filp, |
| 423 | void * dirent, filldir_t filldir) | 429 | void *dirent, filldir_t filldir) |
| 424 | { | 430 | { |
| 425 | struct dir_private_info *info = filp->private_data; | 431 | struct dir_private_info *info = filp->private_data; |
| 426 | struct inode *inode = filp->f_path.dentry->d_inode; | 432 | struct inode *inode = filp->f_path.dentry->d_inode; |
| @@ -511,7 +517,7 @@ finished: | |||
| 511 | return 0; | 517 | return 0; |
| 512 | } | 518 | } |
| 513 | 519 | ||
| 514 | static int ext4_release_dir (struct inode * inode, struct file * filp) | 520 | static int ext4_release_dir(struct inode *inode, struct file *filp) |
| 515 | { | 521 | { |
| 516 | if (filp->private_data) | 522 | if (filp->private_data) |
| 517 | ext4_htree_free_dir_info(filp->private_data); | 523 | ext4_htree_free_dir_info(filp->private_data); |
