Lines Matching +full:page +full:- +full:offset

1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Squashfs - a compressed read only filesystem for Linux
14 * compressed fragment block (tail-end packed block). The compressed size
23 * retaining a simple and space-efficient block list on disk. The cache
45 * Locate cache slot in range [offset, index] for specified inode. If
48 static struct meta_index *locate_meta_index(struct inode *inode, int offset, in locate_meta_index() argument
52 struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info; in locate_meta_index()
55 mutex_lock(&msblk->meta_index_mutex); in locate_meta_index()
57 TRACE("locate_meta_index: index %d, offset %d\n", index, offset); in locate_meta_index()
59 if (msblk->meta_index == NULL) in locate_meta_index()
63 if (msblk->meta_index[i].inode_number == inode->i_ino && in locate_meta_index()
64 msblk->meta_index[i].offset >= offset && in locate_meta_index()
65 msblk->meta_index[i].offset <= index && in locate_meta_index()
66 msblk->meta_index[i].locked == 0) { in locate_meta_index()
67 TRACE("locate_meta_index: entry %d, offset %d\n", i, in locate_meta_index()
68 msblk->meta_index[i].offset); in locate_meta_index()
69 meta = &msblk->meta_index[i]; in locate_meta_index()
70 offset = meta->offset; in locate_meta_index()
75 meta->locked = 1; in locate_meta_index()
78 mutex_unlock(&msblk->meta_index_mutex); in locate_meta_index()
85 * Find and initialise an empty cache slot for index offset.
87 static struct meta_index *empty_meta_index(struct inode *inode, int offset, in empty_meta_index() argument
90 struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info; in empty_meta_index()
94 mutex_lock(&msblk->meta_index_mutex); in empty_meta_index()
96 TRACE("empty_meta_index: offset %d, skip %d\n", offset, skip); in empty_meta_index()
98 if (msblk->meta_index == NULL) { in empty_meta_index()
105 msblk->meta_index = kcalloc(SQUASHFS_META_SLOTS, in empty_meta_index()
106 sizeof(*(msblk->meta_index)), GFP_KERNEL); in empty_meta_index()
107 if (msblk->meta_index == NULL) { in empty_meta_index()
112 msblk->meta_index[i].inode_number = 0; in empty_meta_index()
113 msblk->meta_index[i].locked = 0; in empty_meta_index()
115 msblk->next_meta_index = 0; in empty_meta_index()
119 msblk->meta_index[msblk->next_meta_index].locked; i--) in empty_meta_index()
120 msblk->next_meta_index = (msblk->next_meta_index + 1) % in empty_meta_index()
129 msblk->next_meta_index, in empty_meta_index()
130 &msblk->meta_index[msblk->next_meta_index]); in empty_meta_index()
132 meta = &msblk->meta_index[msblk->next_meta_index]; in empty_meta_index()
133 msblk->next_meta_index = (msblk->next_meta_index + 1) % in empty_meta_index()
136 meta->inode_number = inode->i_ino; in empty_meta_index()
137 meta->offset = offset; in empty_meta_index()
138 meta->skip = skip; in empty_meta_index()
139 meta->entries = 0; in empty_meta_index()
140 meta->locked = 1; in empty_meta_index()
143 mutex_unlock(&msblk->meta_index_mutex); in empty_meta_index()
150 struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info; in release_meta_index()
151 mutex_lock(&msblk->meta_index_mutex); in release_meta_index()
152 meta->locked = 0; in release_meta_index()
153 mutex_unlock(&msblk->meta_index_mutex); in release_meta_index()
159 * metadata block <start_block, offset>.
162 u64 *start_block, int *offset) in read_indexes() argument
170 return -ENOMEM; in read_indexes()
177 offset, blocks << 2); in read_indexes()
180 *start_block, *offset); in read_indexes()
192 n -= blocks; in read_indexes()
206 * can cache one index -> datablock/blocklist-block mapping. We wish
219 return min((u64) SQUASHFS_CACHED_BLKS - 1, skip + 1); in calculate_skip()
225 * on-disk locations of the datablock and block list metadata block
231 struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info; in fill_meta_index()
232 int skip = calculate_skip(i_size_read(inode) >> msblk->block_log); in fill_meta_index()
233 int offset = 0; in fill_meta_index() local
236 u64 cur_index_block = squashfs_i(inode)->block_list_start; in fill_meta_index()
237 int cur_offset = squashfs_i(inode)->offset; in fill_meta_index()
238 u64 cur_data_block = squashfs_i(inode)->start; in fill_meta_index()
246 while (offset < index) { in fill_meta_index()
247 meta = locate_meta_index(inode, offset + 1, index); in fill_meta_index()
250 meta = empty_meta_index(inode, offset + 1, skip); in fill_meta_index()
254 offset = index < meta->offset + meta->entries ? index : in fill_meta_index()
255 meta->offset + meta->entries - 1; in fill_meta_index()
256 meta_entry = &meta->meta_entry[offset - meta->offset]; in fill_meta_index()
257 cur_index_block = meta_entry->index_block + in fill_meta_index()
258 msblk->inode_table; in fill_meta_index()
259 cur_offset = meta_entry->offset; in fill_meta_index()
260 cur_data_block = meta_entry->data_block; in fill_meta_index()
261 TRACE("get_meta_index: offset %d, meta->offset %d, " in fill_meta_index()
262 "meta->entries %d\n", offset, meta->offset, in fill_meta_index()
263 meta->entries); in fill_meta_index()
264 TRACE("get_meta_index: index_block 0x%llx, offset 0x%x" in fill_meta_index()
274 for (i = meta->offset + meta->entries; i <= index && in fill_meta_index()
275 i < meta->offset + SQUASHFS_META_ENTRIES; i++) { in fill_meta_index()
277 long long res = read_indexes(inode->i_sb, blocks, in fill_meta_index()
281 if (meta->entries == 0) in fill_meta_index()
286 meta->inode_number = 0; in fill_meta_index()
292 meta_entry = &meta->meta_entry[i - meta->offset]; in fill_meta_index()
293 meta_entry->index_block = cur_index_block - in fill_meta_index()
294 msblk->inode_table; in fill_meta_index()
295 meta_entry->offset = cur_offset; in fill_meta_index()
296 meta_entry->data_block = cur_data_block; in fill_meta_index()
297 meta->entries++; in fill_meta_index()
298 offset++; in fill_meta_index()
301 TRACE("get_meta_index: meta->offset %d, meta->entries %d\n", in fill_meta_index()
302 meta->offset, meta->entries); in fill_meta_index()
315 return offset * SQUASHFS_META_INDEXES * skip; in fill_meta_index()
324 * Get the on-disk location and compressed size of the datablock
331 int offset; in read_blocklist() local
333 int res = fill_meta_index(inode, index, &start, &offset, block); in read_blocklist()
335 TRACE("read_blocklist: res %d, index %d, start 0x%llx, offset" in read_blocklist()
336 " 0x%x, block 0x%llx\n", res, index, start, offset, in read_blocklist()
349 blks = read_indexes(inode->i_sb, index - res, &start, &offset); in read_blocklist()
358 res = squashfs_read_metadata(inode->i_sb, &size, &start, &offset, in read_blocklist()
365 void squashfs_fill_page(struct page *page, struct squashfs_cache_entry *buffer, int offset, int ava… in squashfs_fill_page() argument
370 pageaddr = kmap_atomic(page); in squashfs_fill_page()
371 copied = squashfs_copy_data(pageaddr, buffer, offset, avail); in squashfs_fill_page()
372 memset(pageaddr + copied, 0, PAGE_SIZE - copied); in squashfs_fill_page()
375 flush_dcache_page(page); in squashfs_fill_page()
377 SetPageUptodate(page); in squashfs_fill_page()
380 /* Copy data into page cache */
381 void squashfs_copy_cache(struct page *page, struct squashfs_cache_entry *buffer, in squashfs_copy_cache() argument
382 int bytes, int offset) in squashfs_copy_cache() argument
384 struct inode *inode = page->mapping->host; in squashfs_copy_cache()
385 struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info; in squashfs_copy_cache()
386 int i, mask = (1 << (msblk->block_log - PAGE_SHIFT)) - 1; in squashfs_copy_cache()
387 int start_index = page->index & ~mask, end_index = start_index | mask; in squashfs_copy_cache()
392 * grab the pages from the page cache, except for the page that we've in squashfs_copy_cache()
396 bytes -= PAGE_SIZE, offset += PAGE_SIZE) { in squashfs_copy_cache()
397 struct page *push_page; in squashfs_copy_cache()
402 push_page = (i == page->index) ? page : in squashfs_copy_cache()
403 grab_cache_page_nowait(page->mapping, i); in squashfs_copy_cache()
411 squashfs_fill_page(push_page, buffer, offset, avail); in squashfs_copy_cache()
414 if (i != page->index) in squashfs_copy_cache()
419 /* Read datablock stored packed inside a fragment (tail-end packed block) */
420 static int squashfs_readpage_fragment(struct page *page, int expected) in squashfs_readpage_fragment() argument
422 struct inode *inode = page->mapping->host; in squashfs_readpage_fragment()
423 struct squashfs_cache_entry *buffer = squashfs_get_fragment(inode->i_sb, in squashfs_readpage_fragment()
424 squashfs_i(inode)->fragment_block, in squashfs_readpage_fragment()
425 squashfs_i(inode)->fragment_size); in squashfs_readpage_fragment()
426 int res = buffer->error; in squashfs_readpage_fragment()
429 ERROR("Unable to read page, block %llx, size %x\n", in squashfs_readpage_fragment()
430 squashfs_i(inode)->fragment_block, in squashfs_readpage_fragment()
431 squashfs_i(inode)->fragment_size); in squashfs_readpage_fragment()
433 squashfs_copy_cache(page, buffer, expected, in squashfs_readpage_fragment()
434 squashfs_i(inode)->fragment_offset); in squashfs_readpage_fragment()
440 static int squashfs_readpage_sparse(struct page *page, int expected) in squashfs_readpage_sparse() argument
442 squashfs_copy_cache(page, NULL, expected, 0); in squashfs_readpage_sparse()
448 struct page *page = &folio->page; in squashfs_read_folio() local
449 struct inode *inode = page->mapping->host; in squashfs_read_folio()
450 struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info; in squashfs_read_folio()
451 int index = page->index >> (msblk->block_log - PAGE_SHIFT); in squashfs_read_folio()
452 int file_end = i_size_read(inode) >> msblk->block_log; in squashfs_read_folio()
454 (i_size_read(inode) & (msblk->block_size - 1)) : in squashfs_read_folio()
455 msblk->block_size; in squashfs_read_folio()
459 TRACE("Entered squashfs_readpage, page index %lx, start block %llx\n", in squashfs_read_folio()
460 page->index, squashfs_i(inode)->start); in squashfs_read_folio()
462 if (page->index >= ((i_size_read(inode) + PAGE_SIZE - 1) >> in squashfs_read_folio()
466 if (index < file_end || squashfs_i(inode)->fragment_block == in squashfs_read_folio()
475 res = squashfs_readpage_sparse(page, expected); in squashfs_read_folio()
477 res = squashfs_readpage_block(page, block, res, expected); in squashfs_read_folio()
479 res = squashfs_readpage_fragment(page, expected); in squashfs_read_folio()
485 pageaddr = kmap_atomic(page); in squashfs_read_folio()
488 flush_dcache_page(page); in squashfs_read_folio()
490 SetPageUptodate(page); in squashfs_read_folio()
491 unlock_page(page); in squashfs_read_folio()
496 static int squashfs_readahead_fragment(struct page **page, in squashfs_readahead_fragment() argument
499 struct inode *inode = page[0]->mapping->host; in squashfs_readahead_fragment()
500 struct squashfs_cache_entry *buffer = squashfs_get_fragment(inode->i_sb, in squashfs_readahead_fragment()
501 squashfs_i(inode)->fragment_block, in squashfs_readahead_fragment()
502 squashfs_i(inode)->fragment_size); in squashfs_readahead_fragment()
503 struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info; in squashfs_readahead_fragment()
506 unsigned int offset; in squashfs_readahead_fragment() local
508 struct page *last_page; in squashfs_readahead_fragment()
510 if (buffer->error) in squashfs_readahead_fragment()
513 actor = squashfs_page_actor_init_special(msblk, page, pages, in squashfs_readahead_fragment()
521 for (copied = offset = 0; offset < expected; offset += PAGE_SIZE) { in squashfs_readahead_fragment()
522 int avail = min_t(int, expected - offset, PAGE_SIZE); in squashfs_readahead_fragment()
525 bytes = squashfs_copy_data(addr, buffer, offset + in squashfs_readahead_fragment()
526 squashfs_i(inode)->fragment_offset, avail); in squashfs_readahead_fragment()
539 /* Last page (if present) may have trailing bytes not filled */ in squashfs_readahead_fragment()
542 memzero_page(last_page, bytes, PAGE_SIZE - bytes); in squashfs_readahead_fragment()
545 flush_dcache_page(page[i]); in squashfs_readahead_fragment()
546 SetPageUptodate(page[i]); in squashfs_readahead_fragment()
551 unlock_page(page[i]); in squashfs_readahead_fragment()
552 put_page(page[i]); in squashfs_readahead_fragment()
568 struct inode *inode = ractl->mapping->host; in squashfs_readahead()
569 struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info; in squashfs_readahead()
570 size_t mask = (1UL << msblk->block_log) - 1; in squashfs_readahead()
571 unsigned short shift = msblk->block_log - PAGE_SHIFT; in squashfs_readahead()
573 size_t len = readahead_length(ractl) + readahead_pos(ractl) - start; in squashfs_readahead()
576 struct page **pages; in squashfs_readahead()
578 loff_t file_end = i_size_read(inode) >> msblk->block_log; in squashfs_readahead()
591 struct page *last_page; in squashfs_readahead()
593 expected = start >> msblk->block_log == file_end ? in squashfs_readahead()
594 (i_size_read(inode) & (msblk->block_size - 1)) : in squashfs_readahead()
595 msblk->block_size; in squashfs_readahead()
597 max_pages = (expected + PAGE_SIZE - 1) >> PAGE_SHIFT; in squashfs_readahead()
606 if (start >> msblk->block_log == file_end && in squashfs_readahead()
607 squashfs_i(inode)->fragment_block != SQUASHFS_INVALID_BLK) { in squashfs_readahead()
615 bsize = read_blocklist(inode, start >> msblk->block_log, &block); in squashfs_readahead()
624 res = squashfs_read_data(inode->i_sb, block, bsize, NULL, actor); in squashfs_readahead()
631 /* Last page (if present) may have trailing bytes not filled */ in squashfs_readahead()
633 if (start >> msblk->block_log == file_end && bytes && last_page) in squashfs_readahead()
635 PAGE_SIZE - bytes); in squashfs_readahead()