1 // SPDX-License-Identifier: GPL-2.0-only
4 * Phillip Lougher <phillip@squashfs.org.uk>
9 #include <linux/kernel.h>
10 #include <linux/slab.h>
11 #include <linux/string.h>
12 #include <linux/pagemap.h>
13 #include <linux/mutex.h>
15 #include "squashfs_fs.h"
16 #include "squashfs_fs_sb.h"
17 #include "squashfs_fs_i.h"
19 #include "page_actor.h"
21 /* Read separately compressed datablock directly into page cache */
22 int squashfs_readpage_block(struct folio
*folio
, u64 block
, int bsize
,
25 struct page
*target_page
= &folio
->page
;
26 struct inode
*inode
= folio
->mapping
->host
;
27 struct squashfs_sb_info
*msblk
= inode
->i_sb
->s_fs_info
;
28 loff_t file_end
= (i_size_read(inode
) - 1) >> PAGE_SHIFT
;
29 int mask
= (1 << (msblk
->block_log
- PAGE_SHIFT
)) - 1;
30 loff_t start_index
= folio
->index
& ~mask
;
31 loff_t end_index
= start_index
| mask
;
33 int i
, pages
, bytes
, res
= -ENOMEM
;
34 struct page
**page
, *last_page
;
35 struct squashfs_page_actor
*actor
;
38 if (end_index
> file_end
)
41 pages
= end_index
- start_index
+ 1;
43 page
= kmalloc_array(pages
, sizeof(void *), GFP_KERNEL
);
47 /* Try to grab all the pages covered by the Squashfs block */
48 for (i
= 0, index
= start_index
; index
<= end_index
; index
++) {
49 page
[i
] = (index
== folio
->index
) ? target_page
:
50 grab_cache_page_nowait(folio
->mapping
, index
);
55 if (PageUptodate(page
[i
])) {
67 * Create a "page actor" which will kmap and kunmap the
68 * page cache pages appropriately within the decompressor
70 actor
= squashfs_page_actor_init_special(msblk
, page
, pages
, expected
,
71 start_index
<< PAGE_SHIFT
);
75 /* Decompress directly into the page cache buffers */
76 res
= squashfs_read_data(inode
->i_sb
, block
, bsize
, NULL
, actor
);
78 last_page
= squashfs_page_actor_free(actor
);
83 if (res
!= expected
|| IS_ERR(last_page
)) {
88 /* Last page (if present) may have trailing bytes not filled */
89 bytes
= res
% PAGE_SIZE
;
90 if (end_index
== file_end
&& last_page
&& bytes
) {
91 pageaddr
= kmap_local_page(last_page
);
92 memset(pageaddr
+ bytes
, 0, PAGE_SIZE
- bytes
);
93 kunmap_local(pageaddr
);
96 /* Mark pages as uptodate, unlock and release */
97 for (i
= 0; i
< pages
; i
++) {
98 flush_dcache_page(page
[i
]);
99 SetPageUptodate(page
[i
]);
100 unlock_page(page
[i
]);
101 if (page
[i
] != target_page
)
110 /* Decompression failed. Target_page is
111 * dealt with by the caller
113 for (i
= 0; i
< pages
; i
++) {
114 if (page
[i
] == NULL
|| page
[i
] == target_page
)
116 flush_dcache_page(page
[i
]);
117 unlock_page(page
[i
]);