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 --- |