dir.c (ea68a3e9d14e9e0bf017d178fb4bd53b6deb1482) dir.c (3acea5fc335420ba7ef53947cf2d98d07fac39f7)
1// SPDX-License-Identifier: GPL-2.0-only
2/*
3 * Copyright (C) 2017-2018 HUAWEI, Inc.
4 * https://www.huawei.com/
5 * Copyright (C) 2022, Alibaba Cloud
6 */
7#include "internal.h"
8

--- 36 unchanged lines hidden (view full) ---

45 }
46 return 0;
47}
48
49static int erofs_readdir(struct file *f, struct dir_context *ctx)
50{
51 struct inode *dir = file_inode(f);
52 struct erofs_buf buf = __EROFS_BUF_INITIALIZER;
1// SPDX-License-Identifier: GPL-2.0-only
2/*
3 * Copyright (C) 2017-2018 HUAWEI, Inc.
4 * https://www.huawei.com/
5 * Copyright (C) 2022, Alibaba Cloud
6 */
7#include "internal.h"
8

--- 36 unchanged lines hidden (view full) ---

45 }
46 return 0;
47}
48
49static int erofs_readdir(struct file *f, struct dir_context *ctx)
50{
51 struct inode *dir = file_inode(f);
52 struct erofs_buf buf = __EROFS_BUF_INITIALIZER;
53 struct super_block *sb = dir->i_sb;
54 unsigned long bsz = sb->s_blocksize;
53 const size_t dirsize = i_size_read(dir);
55 const size_t dirsize = i_size_read(dir);
54 unsigned int i = ctx->pos / EROFS_BLKSIZ;
55 unsigned int ofs = ctx->pos % EROFS_BLKSIZ;
56 unsigned int i = erofs_blknr(sb, ctx->pos);
57 unsigned int ofs = erofs_blkoff(sb, ctx->pos);
56 int err = 0;
57 bool initial = true;
58
59 while (ctx->pos < dirsize) {
60 struct erofs_dirent *de;
61 unsigned int nameoff, maxsize;
62
63 de = erofs_bread(&buf, dir, i, EROFS_KMAP);
64 if (IS_ERR(de)) {
58 int err = 0;
59 bool initial = true;
60
61 while (ctx->pos < dirsize) {
62 struct erofs_dirent *de;
63 unsigned int nameoff, maxsize;
64
65 de = erofs_bread(&buf, dir, i, EROFS_KMAP);
66 if (IS_ERR(de)) {
65 erofs_err(dir->i_sb,
66 "fail to readdir of logical block %u of nid %llu",
67 erofs_err(sb, "fail to readdir of logical block %u of nid %llu",
67 i, EROFS_I(dir)->nid);
68 err = PTR_ERR(de);
69 break;
70 }
71
72 nameoff = le16_to_cpu(de->nameoff);
68 i, EROFS_I(dir)->nid);
69 err = PTR_ERR(de);
70 break;
71 }
72
73 nameoff = le16_to_cpu(de->nameoff);
73 if (nameoff < sizeof(struct erofs_dirent) ||
74 nameoff >= EROFS_BLKSIZ) {
75 erofs_err(dir->i_sb,
76 "invalid de[0].nameoff %u @ nid %llu",
74 if (nameoff < sizeof(struct erofs_dirent) || nameoff >= bsz) {
75 erofs_err(sb, "invalid de[0].nameoff %u @ nid %llu",
77 nameoff, EROFS_I(dir)->nid);
78 err = -EFSCORRUPTED;
79 break;
80 }
81
76 nameoff, EROFS_I(dir)->nid);
77 err = -EFSCORRUPTED;
78 break;
79 }
80
82 maxsize = min_t(unsigned int,
83 dirsize - ctx->pos + ofs, EROFS_BLKSIZ);
81 maxsize = min_t(unsigned int, dirsize - ctx->pos + ofs, bsz);
84
85 /* search dirents at the arbitrary position */
86 if (initial) {
87 initial = false;
88
89 ofs = roundup(ofs, sizeof(struct erofs_dirent));
82
83 /* search dirents at the arbitrary position */
84 if (initial) {
85 initial = false;
86
87 ofs = roundup(ofs, sizeof(struct erofs_dirent));
90 ctx->pos = blknr_to_addr(i) + ofs;
88 ctx->pos = erofs_pos(sb, i) + ofs;
91 if (ofs >= nameoff)
92 goto skip_this;
93 }
94
95 err = erofs_fill_dentries(dir, ctx, de, (void *)de + ofs,
96 nameoff, maxsize);
97 if (err)
98 break;
99skip_this:
89 if (ofs >= nameoff)
90 goto skip_this;
91 }
92
93 err = erofs_fill_dentries(dir, ctx, de, (void *)de + ofs,
94 nameoff, maxsize);
95 if (err)
96 break;
97skip_this:
100 ctx->pos = blknr_to_addr(i) + maxsize;
98 ctx->pos = erofs_pos(sb, i) + maxsize;
101 ++i;
102 ofs = 0;
103 }
104 erofs_put_metabuf(&buf);
105 return err < 0 ? err : 0;
106}
107
108const struct file_operations erofs_dir_fops = {
109 .llseek = generic_file_llseek,
110 .read = generic_read_dir,
111 .iterate_shared = erofs_readdir,
112};
99 ++i;
100 ofs = 0;
101 }
102 erofs_put_metabuf(&buf);
103 return err < 0 ? err : 0;
104}
105
106const struct file_operations erofs_dir_fops = {
107 .llseek = generic_file_llseek,
108 .read = generic_read_dir,
109 .iterate_shared = erofs_readdir,
110};