Line data Source code
1 : // SPDX-License-Identifier: GPL-2.0
2 : /*
3 : * linux/fs/ext4/dir.c
4 : *
5 : * Copyright (C) 1992, 1993, 1994, 1995
6 : * Remy Card (card@masi.ibp.fr)
7 : * Laboratoire MASI - Institut Blaise Pascal
8 : * Universite Pierre et Marie Curie (Paris VI)
9 : *
10 : * from
11 : *
12 : * linux/fs/minix/dir.c
13 : *
14 : * Copyright (C) 1991, 1992 Linus Torvalds
15 : *
16 : * ext4 directory handling functions
17 : *
18 : * Big-endian to little-endian byte-swapping/bitmaps by
19 : * David S. Miller (davem@caip.rutgers.edu), 1995
20 : *
21 : * Hash Tree Directory indexing (c) 2001 Daniel Phillips
22 : *
23 : */
24 :
25 : #include <linux/fs.h>
26 : #include <linux/buffer_head.h>
27 : #include <linux/slab.h>
28 : #include <linux/iversion.h>
29 : #include <linux/unicode.h>
30 : #include "ext4.h"
31 : #include "xattr.h"
32 :
33 : static int ext4_dx_readdir(struct file *, struct dir_context *);
34 :
35 : /**
36 : * is_dx_dir() - check if a directory is using htree indexing
37 : * @inode: directory inode
38 : *
39 : * Check if the given dir-inode refers to an htree-indexed directory
40 : * (or a directory which could potentially get converted to use htree
41 : * indexing).
42 : *
43 : * Return 1 if it is a dx dir, 0 if not
44 : */
45 10465683 : static int is_dx_dir(struct inode *inode)
46 : {
47 10465683 : struct super_block *sb = inode->i_sb;
48 :
49 10465683 : if (ext4_has_feature_dir_index(inode->i_sb) &&
50 425436 : ((ext4_test_inode_flag(inode, EXT4_INODE_INDEX)) ||
51 212718 : ((inode->i_size >> sb->s_blocksize_bits) == 1) ||
52 : ext4_has_inline_data(inode)))
53 10465466 : return 1;
54 :
55 : return 0;
56 : }
57 :
58 503490818 : static bool is_fake_dir_entry(struct ext4_dir_entry_2 *de)
59 : {
60 : /* Check if . or .. , or skip if namelen is 0 */
61 503490818 : if ((de->name_len > 0) && (de->name_len <= 2) && (de->name[0] == '.') &&
62 4647863 : (de->name[1] == '.' || de->name[1] == '\0'))
63 : return true;
64 : /* Check if this is a csum entry */
65 498842731 : if (de->file_type == EXT4_FT_DIR_CSUM)
66 1030688 : return true;
67 : return false;
68 : }
69 :
70 : /*
71 : * Return 0 if the directory entry is OK, and 1 if there is a problem
72 : *
73 : * Note: this is the opposite of what ext2 and ext3 historically returned...
74 : *
75 : * bh passed here can be an inode block or a dir data block, depending
76 : * on the inode inline data flag.
77 : */
78 503470743 : int __ext4_check_dir_entry(const char *function, unsigned int line,
79 : struct inode *dir, struct file *filp,
80 : struct ext4_dir_entry_2 *de,
81 : struct buffer_head *bh, char *buf, int size,
82 : unsigned int offset)
83 : {
84 503470743 : const char *error_msg = NULL;
85 503470743 : const int rlen = ext4_rec_len_from_disk(de->rec_len,
86 503470743 : dir->i_sb->s_blocksize);
87 503470743 : const int next_offset = ((char *) de - buf) + rlen;
88 503470743 : bool fake = is_fake_dir_entry(de);
89 503470743 : bool has_csum = ext4_has_metadata_csum(dir->i_sb);
90 :
91 1001245310 : if (unlikely(rlen < ext4_dir_rec_len(1, fake ? NULL : dir)))
92 : error_msg = "rec_len is smaller than minimal";
93 503582754 : else if (unlikely(rlen % 4 != 0))
94 : error_msg = "rec_len % 4 != 0";
95 1499170032 : else if (unlikely(rlen < ext4_dir_rec_len(de->name_len,
96 : fake ? NULL : dir)))
97 : error_msg = "rec_len is too small for name_len";
98 503582754 : else if (unlikely(next_offset > size))
99 : error_msg = "directory entry overrun";
100 503588551 : else if (unlikely(next_offset > size - ext4_dir_rec_len(1,
101 : has_csum ? NULL : dir) &&
102 : next_offset != size))
103 : error_msg = "directory entry too close to block end";
104 503582754 : else if (unlikely(le32_to_cpu(de->inode) >
105 : le32_to_cpu(EXT4_SB(dir->i_sb)->s_es->s_inodes_count)))
106 : error_msg = "inode out of bounds";
107 : else
108 : return 0;
109 :
110 0 : if (filp)
111 0 : ext4_error_file(filp, function, line, bh->b_blocknr,
112 : "bad entry in directory: %s - offset=%u, "
113 : "inode=%u, rec_len=%d, size=%d fake=%d",
114 : error_msg, offset, le32_to_cpu(de->inode),
115 : rlen, size, fake);
116 : else
117 0 : ext4_error_inode(dir, function, line, bh->b_blocknr,
118 : "bad entry in directory: %s - offset=%u, "
119 : "inode=%u, rec_len=%d, size=%d fake=%d",
120 : error_msg, offset, le32_to_cpu(de->inode),
121 : rlen, size, fake);
122 :
123 : return 1;
124 : }
125 :
126 376377 : static int ext4_readdir(struct file *file, struct dir_context *ctx)
127 : {
128 376377 : unsigned int offset;
129 376377 : int i;
130 376377 : struct ext4_dir_entry_2 *de;
131 376377 : int err;
132 376377 : struct inode *inode = file_inode(file);
133 376377 : struct super_block *sb = inode->i_sb;
134 376377 : struct buffer_head *bh = NULL;
135 376377 : struct fscrypt_str fstr = FSTR_INIT(NULL, 0);
136 :
137 376377 : err = fscrypt_prepare_readdir(inode);
138 376377 : if (err)
139 : return err;
140 :
141 376377 : if (is_dx_dir(inode)) {
142 376143 : err = ext4_dx_readdir(file, ctx);
143 376147 : if (err != ERR_BAD_DX_DIR)
144 : return err;
145 :
146 : /* Can we just clear INDEX flag to ignore htree information? */
147 0 : if (!ext4_has_metadata_csum(sb)) {
148 : /*
149 : * We don't set the inode dirty flag since it's not
150 : * critical that it gets flushed back to the disk.
151 : */
152 0 : ext4_clear_inode_flag(inode, EXT4_INODE_INDEX);
153 : }
154 : }
155 :
156 232 : if (ext4_has_inline_data(inode)) {
157 0 : int has_inline_data = 1;
158 0 : err = ext4_read_inline_dir(file, ctx,
159 : &has_inline_data);
160 0 : if (has_inline_data)
161 0 : return err;
162 : }
163 :
164 232 : if (IS_ENCRYPTED(inode)) {
165 : err = fscrypt_fname_alloc_buffer(EXT4_NAME_LEN, &fstr);
166 : if (err < 0)
167 : return err;
168 : }
169 :
170 696 : while (ctx->pos < inode->i_size) {
171 464 : struct ext4_map_blocks map;
172 :
173 464 : if (fatal_signal_pending(current)) {
174 0 : err = -ERESTARTSYS;
175 0 : goto errout;
176 : }
177 464 : cond_resched();
178 464 : offset = ctx->pos & (sb->s_blocksize - 1);
179 464 : map.m_lblk = ctx->pos >> EXT4_BLOCK_SIZE_BITS(sb);
180 464 : map.m_len = 1;
181 464 : err = ext4_map_blocks(NULL, inode, &map, 0);
182 464 : if (err == 0) {
183 : /* m_len should never be zero but let's avoid
184 : * an infinite loop if it somehow is */
185 0 : if (map.m_len == 0)
186 0 : map.m_len = 1;
187 0 : ctx->pos += map.m_len * sb->s_blocksize;
188 0 : continue;
189 : }
190 464 : if (err > 0) {
191 0 : pgoff_t index = map.m_pblk >>
192 464 : (PAGE_SHIFT - inode->i_blkbits);
193 464 : if (!ra_has_index(&file->f_ra, index))
194 232 : page_cache_sync_readahead(
195 232 : sb->s_bdev->bd_inode->i_mapping,
196 : &file->f_ra, file,
197 : index, 1);
198 464 : file->f_ra.prev_pos = (loff_t)index << PAGE_SHIFT;
199 464 : bh = ext4_bread(NULL, inode, map.m_lblk, 0);
200 464 : if (IS_ERR(bh)) {
201 0 : err = PTR_ERR(bh);
202 0 : bh = NULL;
203 0 : goto errout;
204 : }
205 : }
206 :
207 464 : if (!bh) {
208 : /* corrupt size? Maybe no more blocks to read */
209 0 : if (ctx->pos > inode->i_blocks << 9)
210 : break;
211 0 : ctx->pos += sb->s_blocksize - offset;
212 0 : continue;
213 : }
214 :
215 : /* Check the checksum */
216 1352 : if (!buffer_verified(bh) &&
217 424 : !ext4_dirblock_csum_verify(inode, bh)) {
218 0 : EXT4_ERROR_FILE(file, 0, "directory fails checksum "
219 : "at offset %llu",
220 : (unsigned long long)ctx->pos);
221 0 : ctx->pos += sb->s_blocksize - offset;
222 0 : brelse(bh);
223 0 : bh = NULL;
224 0 : continue;
225 : }
226 464 : set_buffer_verified(bh);
227 :
228 : /* If the dir block has changed since the last call to
229 : * readdir(2), then we might be pointing to an invalid
230 : * dirent right now. Scan from the start of the block
231 : * to make sure. */
232 464 : if (!inode_eq_iversion(inode, file->f_version)) {
233 2 : for (i = 0; i < sb->s_blocksize && i < offset; ) {
234 0 : de = (struct ext4_dir_entry_2 *)
235 0 : (bh->b_data + i);
236 : /* It's too expensive to do a full
237 : * dirent test each time round this
238 : * loop, but we do have to test at
239 : * least that it is non-zero. A
240 : * failure will be detected in the
241 : * dirent test below. */
242 0 : if (ext4_rec_len_from_disk(de->rec_len,
243 : sb->s_blocksize) < ext4_dir_rec_len(1,
244 : inode))
245 : break;
246 0 : i += ext4_rec_len_from_disk(de->rec_len,
247 : sb->s_blocksize);
248 : }
249 2 : offset = i;
250 2 : ctx->pos = (ctx->pos & ~(sb->s_blocksize - 1))
251 2 : | offset;
252 2 : file->f_version = inode_query_iversion(inode);
253 : }
254 :
255 1502 : while (ctx->pos < inode->i_size
256 1502 : && offset < sb->s_blocksize) {
257 1038 : de = (struct ext4_dir_entry_2 *) (bh->b_data + offset);
258 1038 : if (ext4_check_dir_entry(inode, file, de, bh,
259 : bh->b_data, bh->b_size,
260 : offset)) {
261 : /*
262 : * On error, skip to the next block
263 : */
264 0 : ctx->pos = (ctx->pos |
265 0 : (sb->s_blocksize - 1)) + 1;
266 0 : break;
267 : }
268 1038 : offset += ext4_rec_len_from_disk(de->rec_len,
269 : sb->s_blocksize);
270 1038 : if (le32_to_cpu(de->inode)) {
271 234 : if (!IS_ENCRYPTED(inode)) {
272 234 : if (!dir_emit(ctx, de->name,
273 234 : de->name_len,
274 : le32_to_cpu(de->inode),
275 234 : get_dtype(sb, de->file_type)))
276 0 : goto done;
277 : } else {
278 0 : int save_len = fstr.len;
279 0 : struct fscrypt_str de_name =
280 : FSTR_INIT(de->name,
281 : de->name_len);
282 :
283 : /* Directory is encrypted */
284 0 : err = fscrypt_fname_disk_to_usr(inode,
285 : EXT4_DIRENT_HASH(de),
286 : EXT4_DIRENT_MINOR_HASH(de),
287 : &de_name, &fstr);
288 0 : de_name = fstr;
289 0 : fstr.len = save_len;
290 0 : if (err)
291 0 : goto errout;
292 : if (!dir_emit(ctx,
293 : de_name.name, de_name.len,
294 : le32_to_cpu(de->inode),
295 : get_dtype(sb, de->file_type)))
296 : goto done;
297 : }
298 : }
299 1038 : ctx->pos += ext4_rec_len_from_disk(de->rec_len,
300 : sb->s_blocksize);
301 : }
302 464 : if ((ctx->pos < inode->i_size) && !dir_relax_shared(inode))
303 0 : goto done;
304 464 : brelse(bh);
305 464 : bh = NULL;
306 : }
307 232 : done:
308 : err = 0;
309 232 : errout:
310 232 : fscrypt_fname_free_buffer(&fstr);
311 232 : brelse(bh);
312 : return err;
313 : }
314 :
315 : static inline int is_32bit_api(void)
316 : {
317 : #ifdef CONFIG_COMPAT
318 157314633 : return in_compat_syscall();
319 : #else
320 : return (BITS_PER_LONG == 32);
321 : #endif
322 : }
323 :
324 : /*
325 : * These functions convert from the major/minor hash to an f_pos
326 : * value for dx directories
327 : *
328 : * Upper layer (for example NFS) should specify FMODE_32BITHASH or
329 : * FMODE_64BITHASH explicitly. On the other hand, we allow ext4 to be mounted
330 : * directly on both 32-bit and 64-bit nodes, under such case, neither
331 : * FMODE_32BITHASH nor FMODE_64BITHASH is specified.
332 : */
333 146291791 : static inline loff_t hash2pos(struct file *filp, __u32 major, __u32 minor)
334 : {
335 146291791 : if ((filp->f_mode & FMODE_32BITHASH) ||
336 146291791 : (!(filp->f_mode & FMODE_64BITHASH) && is_32bit_api()))
337 0 : return major >> 1;
338 : else
339 146291791 : return ((__u64)(major >> 1) << 32) | (__u64)minor;
340 : }
341 :
342 209853 : static inline __u32 pos2maj_hash(struct file *filp, loff_t pos)
343 : {
344 209853 : if ((filp->f_mode & FMODE_32BITHASH) ||
345 209853 : (!(filp->f_mode & FMODE_64BITHASH) && is_32bit_api()))
346 0 : return (pos << 1) & 0xffffffff;
347 : else
348 209853 : return ((pos >> 32) << 1) & 0xffffffff;
349 : }
350 :
351 209853 : static inline __u32 pos2min_hash(struct file *filp, loff_t pos)
352 : {
353 209853 : if ((filp->f_mode & FMODE_32BITHASH) ||
354 209853 : (!(filp->f_mode & FMODE_64BITHASH) && is_32bit_api()))
355 : return 0;
356 : else
357 209855 : return pos & 0xffffffff;
358 : }
359 :
360 : /*
361 : * Return 32- or 64-bit end-of-file for dx directories
362 : */
363 10603112 : static inline loff_t ext4_get_htree_eof(struct file *filp)
364 : {
365 10603112 : if ((filp->f_mode & FMODE_32BITHASH) ||
366 10603112 : (!(filp->f_mode & FMODE_64BITHASH) && is_32bit_api()))
367 : return EXT4_HTREE_EOF_32BIT;
368 : else
369 10603119 : return EXT4_HTREE_EOF_64BIT;
370 : }
371 :
372 :
373 : /*
374 : * ext4_dir_llseek() calls generic_file_llseek_size to handle htree
375 : * directories, where the "offset" is in terms of the filename hash
376 : * value instead of the byte offset.
377 : *
378 : * Because we may return a 64-bit hash that is well beyond offset limits,
379 : * we need to pass the max hash as the maximum allowable offset in
380 : * the htree directory case.
381 : *
382 : * For non-htree, ext4_llseek already chooses the proper max offset.
383 : */
384 10089320 : static loff_t ext4_dir_llseek(struct file *file, loff_t offset, int whence)
385 : {
386 10089320 : struct inode *inode = file->f_mapping->host;
387 10089320 : int dx_dir = is_dx_dir(inode);
388 10089320 : loff_t ret, htree_max = ext4_get_htree_eof(file);
389 :
390 10089320 : if (likely(dx_dir))
391 10089320 : ret = generic_file_llseek_size(file, offset, whence,
392 : htree_max, htree_max);
393 : else
394 0 : ret = ext4_llseek(file, offset, whence);
395 10089320 : file->f_version = inode_peek_iversion(inode) - 1;
396 10089320 : return ret;
397 : }
398 :
399 : /*
400 : * This structure holds the nodes of the red-black tree used to store
401 : * the directory entry in hash order.
402 : */
403 : struct fname {
404 : __u32 hash;
405 : __u32 minor_hash;
406 : struct rb_node rb_hash;
407 : struct fname *next;
408 : __u32 inode;
409 : __u8 name_len;
410 : __u8 file_type;
411 : char name[];
412 : };
413 :
414 : /*
415 : * This function implements a non-recursive way of freeing all of the
416 : * nodes in the red-black tree.
417 : */
418 1046193 : static void free_rb_tree_fname(struct rb_root *root)
419 : {
420 1046193 : struct fname *fname, *next;
421 :
422 158032016 : rbtree_postorder_for_each_entry_safe(fname, next, root, rb_hash)
423 311879394 : while (fname) {
424 155939742 : struct fname *old = fname;
425 155939742 : fname = fname->next;
426 155939742 : kfree(old);
427 : }
428 :
429 1046170 : *root = RB_ROOT;
430 1046170 : }
431 :
432 :
433 119449 : static struct dir_private_info *ext4_htree_create_dir_info(struct file *filp,
434 : loff_t pos)
435 : {
436 119449 : struct dir_private_info *p;
437 :
438 119449 : p = kzalloc(sizeof(*p), GFP_KERNEL);
439 119441 : if (!p)
440 : return NULL;
441 119441 : p->curr_hash = pos2maj_hash(filp, pos);
442 119441 : p->curr_minor_hash = pos2min_hash(filp, pos);
443 119441 : return p;
444 : }
445 :
446 0 : void ext4_htree_free_dir_info(struct dir_private_info *p)
447 : {
448 0 : free_rb_tree_fname(&p->root);
449 119457 : kfree(p);
450 119455 : }
451 :
452 : /*
453 : * Given a directory entry, enter it into the fname rb tree.
454 : *
455 : * When filename encryption is enabled, the dirent will hold the
456 : * encrypted filename, while the htree will hold decrypted filename.
457 : * The decrypted filename is passed in via ent_name. parameter.
458 : */
459 155939955 : int ext4_htree_store_dirent(struct file *dir_file, __u32 hash,
460 : __u32 minor_hash,
461 : struct ext4_dir_entry_2 *dirent,
462 : struct fscrypt_str *ent_name)
463 : {
464 155939955 : struct rb_node **p, *parent = NULL;
465 155939955 : struct fname *fname, *new_fn;
466 155939955 : struct dir_private_info *info;
467 155939955 : int len;
468 :
469 155939955 : info = dir_file->private_data;
470 155939955 : p = &info->root.rb_node;
471 :
472 : /* Create and allocate the fname structure */
473 155939955 : len = sizeof(struct fname) + ent_name->len + 1;
474 155939955 : new_fn = kzalloc(len, GFP_KERNEL);
475 155940178 : if (!new_fn)
476 : return -ENOMEM;
477 155940178 : new_fn->hash = hash;
478 155940178 : new_fn->minor_hash = minor_hash;
479 155940178 : new_fn->inode = le32_to_cpu(dirent->inode);
480 155940178 : new_fn->name_len = ent_name->len;
481 155940178 : new_fn->file_type = dirent->file_type;
482 311880356 : memcpy(new_fn->name, ent_name->name, ent_name->len);
483 :
484 1403507723 : while (*p) {
485 1247567545 : parent = *p;
486 1247567545 : fname = rb_entry(parent, struct fname, rb_hash);
487 :
488 : /*
489 : * If the hash and minor hash match up, then we put
490 : * them on a linked list. This rarely happens...
491 : */
492 1247567545 : if ((new_fn->hash == fname->hash) &&
493 : (new_fn->minor_hash == fname->minor_hash)) {
494 0 : new_fn->next = fname->next;
495 0 : fname->next = new_fn;
496 0 : return 0;
497 : }
498 :
499 1247567545 : if (new_fn->hash < fname->hash)
500 304930547 : p = &(*p)->rb_left;
501 942636998 : else if (new_fn->hash > fname->hash)
502 942636997 : p = &(*p)->rb_right;
503 1 : else if (new_fn->minor_hash < fname->minor_hash)
504 0 : p = &(*p)->rb_left;
505 : else /* if (new_fn->minor_hash > fname->minor_hash) */
506 1 : p = &(*p)->rb_right;
507 : }
508 :
509 155940178 : rb_link_node(&new_fn->rb_hash, parent, p);
510 155940178 : rb_insert_color(&new_fn->rb_hash, &info->root);
511 155940178 : return 0;
512 : }
513 :
514 :
515 :
516 : /*
517 : * This is a helper function for ext4_dx_readdir. It calls filldir
518 : * for all entries on the fname linked list. (Normally there is only
519 : * one entry on the linked list, unless there are 62 bit hash collisions.)
520 : */
521 146291819 : static int call_filldir(struct file *file, struct dir_context *ctx,
522 : struct fname *fname)
523 : {
524 146291819 : struct dir_private_info *info = file->private_data;
525 146291819 : struct inode *inode = file_inode(file);
526 146291819 : struct super_block *sb = inode->i_sb;
527 :
528 146291819 : if (!fname) {
529 0 : ext4_msg(sb, KERN_ERR, "%s:%d: inode #%lu: comm %s: "
530 : "called with null fname?!?", __func__, __LINE__,
531 : inode->i_ino, current->comm);
532 0 : return 0;
533 : }
534 146291819 : ctx->pos = hash2pos(file, fname->hash, fname->minor_hash);
535 292458518 : while (fname) {
536 146292359 : if (!dir_emit(ctx, fname->name,
537 146291698 : fname->name_len,
538 146291698 : fname->inode,
539 146291720 : get_dtype(sb, fname->file_type))) {
540 125660 : info->extra_fname = fname;
541 125660 : return 1;
542 : }
543 146166699 : fname = fname->next;
544 : }
545 : return 0;
546 : }
547 :
548 376151 : static int ext4_dx_readdir(struct file *file, struct dir_context *ctx)
549 : {
550 376151 : struct dir_private_info *info = file->private_data;
551 376151 : struct inode *inode = file_inode(file);
552 376151 : struct fname *fname;
553 376151 : int ret = 0;
554 :
555 376151 : if (!info) {
556 119476 : info = ext4_htree_create_dir_info(file, ctx->pos);
557 119441 : if (!info)
558 : return -ENOMEM;
559 119441 : file->private_data = info;
560 : }
561 :
562 376116 : if (ctx->pos == ext4_get_htree_eof(file))
563 : return 0; /* EOF */
564 :
565 : /* Some one has messed with f_pos; reset the world */
566 263315 : if (info->last_pos != ctx->pos) {
567 90412 : free_rb_tree_fname(&info->root);
568 90412 : info->curr_node = NULL;
569 90412 : info->extra_fname = NULL;
570 90412 : info->curr_hash = pos2maj_hash(file, ctx->pos);
571 90412 : info->curr_minor_hash = pos2min_hash(file, ctx->pos);
572 : }
573 :
574 : /*
575 : * If there are any leftover names on the hash collision
576 : * chain, return them first.
577 : */
578 263315 : if (info->extra_fname) {
579 53465 : if (call_filldir(file, ctx, info->extra_fname))
580 0 : goto finished;
581 53465 : info->extra_fname = NULL;
582 53465 : goto next_node;
583 209850 : } else if (!info->curr_node)
584 209853 : info->curr_node = rb_first(&info->root);
585 :
586 146238390 : while (1) {
587 : /*
588 : * Fill the rbtree if we have no more entries,
589 : * or the inode has changed since we last read in the
590 : * cached entries.
591 : */
592 146238390 : if ((!info->curr_node) ||
593 145402096 : !inode_eq_iversion(inode, file->f_version)) {
594 836349 : info->curr_node = NULL;
595 836349 : free_rb_tree_fname(&info->root);
596 836303 : file->f_version = inode_query_iversion(inode);
597 836346 : ret = ext4_htree_fill_tree(file, info->curr_hash,
598 : info->curr_minor_hash,
599 : &info->next_hash);
600 836358 : if (ret < 0)
601 1 : goto finished;
602 836357 : if (ret == 0) {
603 1 : ctx->pos = ext4_get_htree_eof(file);
604 1 : break;
605 : }
606 836356 : info->curr_node = rb_first(&info->root);
607 : }
608 :
609 146238370 : fname = rb_entry(info->curr_node, struct fname, rb_hash);
610 146238370 : info->curr_hash = fname->hash;
611 146238370 : info->curr_minor_hash = fname->minor_hash;
612 146238370 : if (call_filldir(file, ctx, fname))
613 : break;
614 146113138 : next_node:
615 146166603 : info->curr_node = rb_next(info->curr_node);
616 146166221 : if (info->curr_node) {
617 145402120 : fname = rb_entry(info->curr_node, struct fname,
618 : rb_hash);
619 145402120 : info->curr_hash = fname->hash;
620 145402120 : info->curr_minor_hash = fname->minor_hash;
621 : } else {
622 764101 : if (info->next_hash == ~0) {
623 137670 : ctx->pos = ext4_get_htree_eof(file);
624 137670 : break;
625 : }
626 626431 : info->curr_hash = info->next_hash;
627 626431 : info->curr_minor_hash = 0;
628 : }
629 : }
630 125660 : finished:
631 263332 : info->last_pos = ctx->pos;
632 263332 : return ret < 0 ? ret : 0;
633 : }
634 :
635 167737 : static int ext4_release_dir(struct inode *inode, struct file *filp)
636 : {
637 167737 : if (filp->private_data)
638 119468 : ext4_htree_free_dir_info(filp->private_data);
639 :
640 167724 : return 0;
641 : }
642 :
643 0 : int ext4_check_all_de(struct inode *dir, struct buffer_head *bh, void *buf,
644 : int buf_size)
645 : {
646 0 : struct ext4_dir_entry_2 *de;
647 0 : int rlen;
648 0 : unsigned int offset = 0;
649 0 : char *top;
650 :
651 0 : de = buf;
652 0 : top = buf + buf_size;
653 0 : while ((char *) de < top) {
654 0 : if (ext4_check_dir_entry(dir, NULL, de, bh,
655 : buf, buf_size, offset))
656 : return -EFSCORRUPTED;
657 0 : rlen = ext4_rec_len_from_disk(de->rec_len, buf_size);
658 0 : de = (struct ext4_dir_entry_2 *)((char *)de + rlen);
659 0 : offset += rlen;
660 : }
661 0 : if ((char *) de > top)
662 0 : return -EFSCORRUPTED;
663 :
664 : return 0;
665 : }
666 :
667 : const struct file_operations ext4_dir_operations = {
668 : .llseek = ext4_dir_llseek,
669 : .read = generic_read_dir,
670 : .iterate_shared = ext4_readdir,
671 : .unlocked_ioctl = ext4_ioctl,
672 : #ifdef CONFIG_COMPAT
673 : .compat_ioctl = ext4_compat_ioctl,
674 : #endif
675 : .fsync = ext4_sync_file,
676 : .release = ext4_release_dir,
677 : };
|