data.c (60261442c1b91d9e0cdc611222034286aeb18946) data.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) 2021, Alibaba Cloud
6 */
7#include "internal.h"
8#include <linux/prefetch.h>

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

22{
23 if (!buf->page)
24 return;
25 erofs_unmap_metabuf(buf);
26 put_page(buf->page);
27 buf->page = NULL;
28}
29
1// SPDX-License-Identifier: GPL-2.0-only
2/*
3 * Copyright (C) 2017-2018 HUAWEI, Inc.
4 * https://www.huawei.com/
5 * Copyright (C) 2021, Alibaba Cloud
6 */
7#include "internal.h"
8#include <linux/prefetch.h>

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

22{
23 if (!buf->page)
24 return;
25 erofs_unmap_metabuf(buf);
26 put_page(buf->page);
27 buf->page = NULL;
28}
29
30/*
31 * Derive the block size from inode->i_blkbits to make compatible with
32 * anonymous inode in fscache mode.
33 */
30void *erofs_bread(struct erofs_buf *buf, struct inode *inode,
31 erofs_blk_t blkaddr, enum erofs_kmap_type type)
32{
34void *erofs_bread(struct erofs_buf *buf, struct inode *inode,
35 erofs_blk_t blkaddr, enum erofs_kmap_type type)
36{
37 erofs_off_t offset = (erofs_off_t)blkaddr << inode->i_blkbits;
33 struct address_space *const mapping = inode->i_mapping;
38 struct address_space *const mapping = inode->i_mapping;
34 erofs_off_t offset = blknr_to_addr(blkaddr);
35 pgoff_t index = offset >> PAGE_SHIFT;
36 struct page *page = buf->page;
37 struct folio *folio;
38 unsigned int nofs_flag;
39
40 if (!page || page->index != index) {
41 erofs_put_metabuf(buf);
42

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

74}
75
76static int erofs_map_blocks_flatmode(struct inode *inode,
77 struct erofs_map_blocks *map)
78{
79 erofs_blk_t nblocks, lastblk;
80 u64 offset = map->m_la;
81 struct erofs_inode *vi = EROFS_I(inode);
39 pgoff_t index = offset >> PAGE_SHIFT;
40 struct page *page = buf->page;
41 struct folio *folio;
42 unsigned int nofs_flag;
43
44 if (!page || page->index != index) {
45 erofs_put_metabuf(buf);
46

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

78}
79
80static int erofs_map_blocks_flatmode(struct inode *inode,
81 struct erofs_map_blocks *map)
82{
83 erofs_blk_t nblocks, lastblk;
84 u64 offset = map->m_la;
85 struct erofs_inode *vi = EROFS_I(inode);
86 struct super_block *sb = inode->i_sb;
82 bool tailendpacking = (vi->datalayout == EROFS_INODE_FLAT_INLINE);
83
87 bool tailendpacking = (vi->datalayout == EROFS_INODE_FLAT_INLINE);
88
84 nblocks = DIV_ROUND_UP(inode->i_size, EROFS_BLKSIZ);
89 nblocks = erofs_iblks(inode);
85 lastblk = nblocks - tailendpacking;
86
87 /* there is no hole in flatmode */
88 map->m_flags = EROFS_MAP_MAPPED;
90 lastblk = nblocks - tailendpacking;
91
92 /* there is no hole in flatmode */
93 map->m_flags = EROFS_MAP_MAPPED;
89 if (offset < blknr_to_addr(lastblk)) {
90 map->m_pa = blknr_to_addr(vi->raw_blkaddr) + map->m_la;
91 map->m_plen = blknr_to_addr(lastblk) - offset;
94 if (offset < erofs_pos(sb, lastblk)) {
95 map->m_pa = erofs_pos(sb, vi->raw_blkaddr) + map->m_la;
96 map->m_plen = erofs_pos(sb, lastblk) - offset;
92 } else if (tailendpacking) {
93 map->m_pa = erofs_iloc(inode) + vi->inode_isize +
97 } else if (tailendpacking) {
98 map->m_pa = erofs_iloc(inode) + vi->inode_isize +
94 vi->xattr_isize + erofs_blkoff(offset);
99 vi->xattr_isize + erofs_blkoff(sb, offset);
95 map->m_plen = inode->i_size - offset;
96
97 /* inline data should be located in the same meta block */
100 map->m_plen = inode->i_size - offset;
101
102 /* inline data should be located in the same meta block */
98 if (erofs_blkoff(map->m_pa) + map->m_plen > EROFS_BLKSIZ) {
99 erofs_err(inode->i_sb,
100 "inline data cross block boundary @ nid %llu",
103 if (erofs_blkoff(sb, map->m_pa) + map->m_plen > sb->s_blocksize) {
104 erofs_err(sb, "inline data cross block boundary @ nid %llu",
101 vi->nid);
102 DBG_BUGON(1);
103 return -EFSCORRUPTED;
104 }
105 map->m_flags |= EROFS_MAP_META;
106 } else {
105 vi->nid);
106 DBG_BUGON(1);
107 return -EFSCORRUPTED;
108 }
109 map->m_flags |= EROFS_MAP_META;
110 } else {
107 erofs_err(inode->i_sb,
108 "internal error @ nid: %llu (size %llu), m_la 0x%llx",
111 erofs_err(sb, "internal error @ nid: %llu (size %llu), m_la 0x%llx",
109 vi->nid, inode->i_size, map->m_la);
110 DBG_BUGON(1);
111 return -EIO;
112 }
113 return 0;
114}
115
116int erofs_map_blocks(struct inode *inode, struct erofs_map_blocks *map)

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

143 unit = sizeof(*idx); /* chunk index */
144 else
145 unit = EROFS_BLOCK_MAP_ENTRY_SIZE; /* block map */
146
147 chunknr = map->m_la >> vi->chunkbits;
148 pos = ALIGN(erofs_iloc(inode) + vi->inode_isize +
149 vi->xattr_isize, unit) + unit * chunknr;
150
112 vi->nid, inode->i_size, map->m_la);
113 DBG_BUGON(1);
114 return -EIO;
115 }
116 return 0;
117}
118
119int erofs_map_blocks(struct inode *inode, struct erofs_map_blocks *map)

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

146 unit = sizeof(*idx); /* chunk index */
147 else
148 unit = EROFS_BLOCK_MAP_ENTRY_SIZE; /* block map */
149
150 chunknr = map->m_la >> vi->chunkbits;
151 pos = ALIGN(erofs_iloc(inode) + vi->inode_isize +
152 vi->xattr_isize, unit) + unit * chunknr;
153
151 kaddr = erofs_read_metabuf(&buf, sb, erofs_blknr(pos), EROFS_KMAP);
154 kaddr = erofs_read_metabuf(&buf, sb, erofs_blknr(sb, pos), EROFS_KMAP);
152 if (IS_ERR(kaddr)) {
153 err = PTR_ERR(kaddr);
154 goto out;
155 }
156 map->m_la = chunknr << vi->chunkbits;
157 map->m_plen = min_t(erofs_off_t, 1UL << vi->chunkbits,
155 if (IS_ERR(kaddr)) {
156 err = PTR_ERR(kaddr);
157 goto out;
158 }
159 map->m_la = chunknr << vi->chunkbits;
160 map->m_plen = min_t(erofs_off_t, 1UL << vi->chunkbits,
158 roundup(inode->i_size - map->m_la, EROFS_BLKSIZ));
161 round_up(inode->i_size - map->m_la, sb->s_blocksize));
159
160 /* handle block map */
161 if (!(vi->chunkformat & EROFS_CHUNK_FORMAT_INDEXES)) {
162
163 /* handle block map */
164 if (!(vi->chunkformat & EROFS_CHUNK_FORMAT_INDEXES)) {
162 __le32 *blkaddr = kaddr + erofs_blkoff(pos);
165 __le32 *blkaddr = kaddr + erofs_blkoff(sb, pos);
163
164 if (le32_to_cpu(*blkaddr) == EROFS_NULL_ADDR) {
165 map->m_flags = 0;
166 } else {
166
167 if (le32_to_cpu(*blkaddr) == EROFS_NULL_ADDR) {
168 map->m_flags = 0;
169 } else {
167 map->m_pa = blknr_to_addr(le32_to_cpu(*blkaddr));
170 map->m_pa = erofs_pos(sb, le32_to_cpu(*blkaddr));
168 map->m_flags = EROFS_MAP_MAPPED;
169 }
170 goto out_unlock;
171 }
172 /* parse chunk indexes */
171 map->m_flags = EROFS_MAP_MAPPED;
172 }
173 goto out_unlock;
174 }
175 /* parse chunk indexes */
173 idx = kaddr + erofs_blkoff(pos);
176 idx = kaddr + erofs_blkoff(sb, pos);
174 switch (le32_to_cpu(idx->blkaddr)) {
175 case EROFS_NULL_ADDR:
176 map->m_flags = 0;
177 break;
178 default:
179 map->m_deviceid = le16_to_cpu(idx->device_id) &
180 EROFS_SB(sb)->device_id_mask;
177 switch (le32_to_cpu(idx->blkaddr)) {
178 case EROFS_NULL_ADDR:
179 map->m_flags = 0;
180 break;
181 default:
182 map->m_deviceid = le16_to_cpu(idx->device_id) &
183 EROFS_SB(sb)->device_id_mask;
181 map->m_pa = blknr_to_addr(le32_to_cpu(idx->blkaddr));
184 map->m_pa = erofs_pos(sb, le32_to_cpu(idx->blkaddr));
182 map->m_flags = EROFS_MAP_MAPPED;
183 break;
184 }
185out_unlock:
186 erofs_put_metabuf(&buf);
187out:
188 if (!err)
189 map->m_llen = map->m_plen;

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

217 up_read(&devs->rwsem);
218 } else if (devs->extra_devices) {
219 down_read(&devs->rwsem);
220 idr_for_each_entry(&devs->tree, dif, id) {
221 erofs_off_t startoff, length;
222
223 if (!dif->mapped_blkaddr)
224 continue;
185 map->m_flags = EROFS_MAP_MAPPED;
186 break;
187 }
188out_unlock:
189 erofs_put_metabuf(&buf);
190out:
191 if (!err)
192 map->m_llen = map->m_plen;

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

220 up_read(&devs->rwsem);
221 } else if (devs->extra_devices) {
222 down_read(&devs->rwsem);
223 idr_for_each_entry(&devs->tree, dif, id) {
224 erofs_off_t startoff, length;
225
226 if (!dif->mapped_blkaddr)
227 continue;
225 startoff = blknr_to_addr(dif->mapped_blkaddr);
226 length = blknr_to_addr(dif->blocks);
228 startoff = erofs_pos(sb, dif->mapped_blkaddr);
229 length = erofs_pos(sb, dif->blocks);
227
228 if (map->m_pa >= startoff &&
229 map->m_pa < startoff + length) {
230 map->m_pa -= startoff;
231 map->m_bdev = dif->bdev;
232 map->m_daxdev = dif->dax_dev;
233 map->m_dax_part_off = dif->dax_part_off;
234 map->m_fscache = dif->fscache;

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

239 }
240 return 0;
241}
242
243static int erofs_iomap_begin(struct inode *inode, loff_t offset, loff_t length,
244 unsigned int flags, struct iomap *iomap, struct iomap *srcmap)
245{
246 int ret;
230
231 if (map->m_pa >= startoff &&
232 map->m_pa < startoff + length) {
233 map->m_pa -= startoff;
234 map->m_bdev = dif->bdev;
235 map->m_daxdev = dif->dax_dev;
236 map->m_dax_part_off = dif->dax_part_off;
237 map->m_fscache = dif->fscache;

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

242 }
243 return 0;
244}
245
246static int erofs_iomap_begin(struct inode *inode, loff_t offset, loff_t length,
247 unsigned int flags, struct iomap *iomap, struct iomap *srcmap)
248{
249 int ret;
250 struct super_block *sb = inode->i_sb;
247 struct erofs_map_blocks map;
248 struct erofs_map_dev mdev;
249
250 map.m_la = offset;
251 map.m_llen = length;
252
253 ret = erofs_map_blocks(inode, &map);
254 if (ret < 0)
255 return ret;
256
257 mdev = (struct erofs_map_dev) {
258 .m_deviceid = map.m_deviceid,
259 .m_pa = map.m_pa,
260 };
251 struct erofs_map_blocks map;
252 struct erofs_map_dev mdev;
253
254 map.m_la = offset;
255 map.m_llen = length;
256
257 ret = erofs_map_blocks(inode, &map);
258 if (ret < 0)
259 return ret;
260
261 mdev = (struct erofs_map_dev) {
262 .m_deviceid = map.m_deviceid,
263 .m_pa = map.m_pa,
264 };
261 ret = erofs_map_dev(inode->i_sb, &mdev);
265 ret = erofs_map_dev(sb, &mdev);
262 if (ret)
263 return ret;
264
265 iomap->offset = map.m_la;
266 if (flags & IOMAP_DAX)
267 iomap->dax_dev = mdev.m_daxdev;
268 else
269 iomap->bdev = mdev.m_bdev;

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

279 return 0;
280 }
281
282 if (map.m_flags & EROFS_MAP_META) {
283 void *ptr;
284 struct erofs_buf buf = __EROFS_BUF_INITIALIZER;
285
286 iomap->type = IOMAP_INLINE;
266 if (ret)
267 return ret;
268
269 iomap->offset = map.m_la;
270 if (flags & IOMAP_DAX)
271 iomap->dax_dev = mdev.m_daxdev;
272 else
273 iomap->bdev = mdev.m_bdev;

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

283 return 0;
284 }
285
286 if (map.m_flags & EROFS_MAP_META) {
287 void *ptr;
288 struct erofs_buf buf = __EROFS_BUF_INITIALIZER;
289
290 iomap->type = IOMAP_INLINE;
287 ptr = erofs_read_metabuf(&buf, inode->i_sb,
288 erofs_blknr(mdev.m_pa), EROFS_KMAP);
291 ptr = erofs_read_metabuf(&buf, sb,
292 erofs_blknr(sb, mdev.m_pa), EROFS_KMAP);
289 if (IS_ERR(ptr))
290 return PTR_ERR(ptr);
293 if (IS_ERR(ptr))
294 return PTR_ERR(ptr);
291 iomap->inline_data = ptr + erofs_blkoff(mdev.m_pa);
295 iomap->inline_data = ptr + erofs_blkoff(sb, mdev.m_pa);
292 iomap->private = buf.base;
293 } else {
294 iomap->type = IOMAP_MAPPED;
295 iomap->addr = mdev.m_pa;
296 if (flags & IOMAP_DAX)
297 iomap->addr += mdev.m_dax_part_off;
298 }
299 return 0;

--- 140 unchanged lines hidden ---
296 iomap->private = buf.base;
297 } else {
298 iomap->type = IOMAP_MAPPED;
299 iomap->addr = mdev.m_pa;
300 if (flags & IOMAP_DAX)
301 iomap->addr += mdev.m_dax_part_off;
302 }
303 return 0;

--- 140 unchanged lines hidden ---