27 #include <linux/slab.h>
28 #include <linux/rbtree.h>
31 static unsigned char ext4_filetype_table[] = {
35 static int ext4_dx_readdir(
struct file *filp,
38 static unsigned char get_dtype(
struct super_block *
sb,
int filetype)
44 return (ext4_filetype_table[filetype]);
73 struct inode *dir,
struct file *filp,
75 struct buffer_head *bh,
78 const char *error_msg =
NULL;
79 const int rlen = ext4_rec_len_from_disk(de->
rec_len,
80 dir->
i_sb->s_blocksize);
83 error_msg =
"rec_len is smaller than minimal";
85 error_msg =
"rec_len % 4 != 0";
87 error_msg =
"rec_len is too small for name_len";
88 else if (
unlikely(((
char *) de - bh->b_data) + rlen >
89 dir->
i_sb->s_blocksize))
90 error_msg =
"directory entry across blocks";
93 error_msg =
"inode out of bounds";
99 "bad entry in directory: %s - offset=%u(%u), "
100 "inode=%u, rec_len=%d, name_len=%d",
101 error_msg, (
unsigned) (offset % bh->b_size),
106 "bad entry in directory: %s - offset=%u(%u), "
107 "inode=%u, rec_len=%d, name_len=%d",
108 error_msg, (
unsigned) (offset % bh->b_size),
115 static int ext4_readdir(
struct file *filp,
123 struct inode *inode = filp->
f_path.dentry->d_inode;
126 int dir_has_error = 0;
128 if (is_dx_dir(inode)) {
129 err = ext4_dx_readdir(filp, dirent, filldir);
138 ext4_clear_inode_flag(filp->
f_path.dentry->d_inode,
144 while (!error && !stored && filp->
f_pos < inode->
i_size) {
146 struct buffer_head *bh =
NULL;
154 if (!ra_has_index(&filp->
f_ra, index))
156 sb->
s_bdev->bd_inode->i_mapping,
168 if (!dir_has_error) {
170 "directory contains a "
171 "hole at offset %llu",
172 (
unsigned long long) filp->
f_pos);
183 if (!buffer_verified(bh) &&
188 (
unsigned long long)filp->
f_pos);
192 set_buffer_verified(bh);
209 if (ext4_rec_len_from_disk(de->
rec_len,
212 i += ext4_rec_len_from_disk(de->
rec_len,
224 if (ext4_check_dir_entry(inode, filp, de,
235 offset += ext4_rec_len_from_disk(de->
rec_len,
247 error = filldir(dirent, de->
name,
268 static inline int is_32bit_api(
void)
286 static inline loff_t hash2pos(
struct file *filp,
__u32 major,
__u32 minor)
292 return ((
__u64)(major >> 1) << 32) | (
__u64)minor;
295 static inline __u32 pos2maj_hash(
struct file *filp, loff_t
pos)
299 return (pos << 1) & 0xffffffff;
301 return ((pos >> 32) << 1) & 0xffffffff;
304 static inline __u32 pos2min_hash(
struct file *filp, loff_t pos)
310 return pos & 0xffffffff;
316 static inline loff_t ext4_get_htree_eof(
struct file *filp)
320 return EXT4_HTREE_EOF_32BIT;
322 return EXT4_HTREE_EOF_64BIT;
339 struct inode *inode = file->
f_mapping->host;
340 int dx_dir = is_dx_dir(inode);
341 loff_t htree_max = ext4_get_htree_eof(file);
345 htree_max, htree_max);
369 static void free_rb_tree_fname(
struct rb_root *root)
394 struct fname *old =
fname;
424 free_rb_tree_fname(&p->
root);
436 struct fname *
fname, *new_fn;
441 p = &info->
root.rb_node;
444 len =
sizeof(
struct fname) + dirent->name_len + 1;
451 new_fn->name_len = dirent->
name_len;
464 if ((new_fn->hash == fname->
hash) &&
466 new_fn->next = fname->
next;
467 fname->
next = new_fn;
471 if (new_fn->hash < fname->
hash)
473 else if (new_fn->hash > fname->
hash)
475 else if (new_fn->minor_hash < fname->
minor_hash)
481 rb_link_node(&new_fn->rb_hash, parent, p);
493 static int call_filldir(
struct file *filp,
void *dirent,
498 struct inode *inode = filp->
f_path.dentry->d_inode;
506 "called with null fname?!?", __func__, __LINE__,
512 error = filldir(dirent, fname->
name,
517 filp->
f_pos = curr_pos;
526 static int ext4_dx_readdir(
struct file *filp,
530 struct inode *inode = filp->
f_path.dentry->d_inode;
535 info = ext4_htree_create_dir_info(filp, filp->
f_pos);
541 if (filp->
f_pos == ext4_get_htree_eof(filp))
546 free_rb_tree_fname(&info->
root);
558 if (call_filldir(filp, dirent, filldir, info->
extra_fname))
574 free_rb_tree_fname(&info->
root);
582 filp->
f_pos = ext4_get_htree_eof(filp);
591 if (call_filldir(filp, dirent, filldir, fname))
602 filp->
f_pos = ext4_get_htree_eof(filp);
614 static int ext4_release_dir(
struct inode *inode,
struct file *filp)
625 .readdir = ext4_readdir,
628 .compat_ioctl = ext4_compat_ioctl,
631 .release = ext4_release_dir,