1313 * datablocks and metadata blocks.
1414 */
1515
16+ #include <linux/blkdev.h>
1617#include <linux/fs.h>
1718#include <linux/vfs.h>
1819#include <linux/slab.h>
2728#include "page_actor.h"
2829
2930/*
30- * Read the metadata block length, this is stored in the first two
31- * bytes of the metadata block.
31+ * Returns the amount of bytes copied to the page actor.
3232 */
33- static struct buffer_head * get_block_length (struct super_block * sb ,
34- u64 * cur_index , int * offset , int * length )
33+ static int copy_bio_to_actor (struct bio * bio ,
34+ struct squashfs_page_actor * actor ,
35+ int offset , int req_length )
36+ {
37+ void * actor_addr = squashfs_first_page (actor );
38+ struct bvec_iter_all iter_all = {};
39+ struct bio_vec * bvec = bvec_init_iter_all (& iter_all );
40+ int copied_bytes = 0 ;
41+ int actor_offset = 0 ;
42+
43+ if (WARN_ON_ONCE (!bio_next_segment (bio , & iter_all )))
44+ return 0 ;
45+
46+ while (copied_bytes < req_length ) {
47+ int bytes_to_copy = min_t (int , bvec -> bv_len - offset ,
48+ PAGE_SIZE - actor_offset );
49+
50+ bytes_to_copy = min_t (int , bytes_to_copy ,
51+ req_length - copied_bytes );
52+ memcpy (actor_addr + actor_offset ,
53+ page_address (bvec -> bv_page ) + bvec -> bv_offset + offset ,
54+ bytes_to_copy );
55+
56+ actor_offset += bytes_to_copy ;
57+ copied_bytes += bytes_to_copy ;
58+ offset += bytes_to_copy ;
59+
60+ if (actor_offset >= PAGE_SIZE ) {
61+ actor_addr = squashfs_next_page (actor );
62+ if (!actor_addr )
63+ break ;
64+ actor_offset = 0 ;
65+ }
66+ if (offset >= bvec -> bv_len ) {
67+ if (!bio_next_segment (bio , & iter_all ))
68+ break ;
69+ offset = 0 ;
70+ }
71+ }
72+ squashfs_finish_page (actor );
73+ return copied_bytes ;
74+ }
75+
76+ static int squashfs_bio_read (struct super_block * sb , u64 index , int length ,
77+ struct bio * * biop , int * block_offset )
3578{
3679 struct squashfs_sb_info * msblk = sb -> s_fs_info ;
37- struct buffer_head * bh ;
38-
39- bh = sb_bread (sb , * cur_index );
40- if (bh == NULL )
41- return NULL ;
42-
43- if (msblk -> devblksize - * offset == 1 ) {
44- * length = (unsigned char ) bh -> b_data [* offset ];
45- put_bh (bh );
46- bh = sb_bread (sb , ++ (* cur_index ));
47- if (bh == NULL )
48- return NULL ;
49- * length |= (unsigned char ) bh -> b_data [0 ] << 8 ;
50- * offset = 1 ;
51- } else {
52- * length = (unsigned char ) bh -> b_data [* offset ] |
53- (unsigned char ) bh -> b_data [* offset + 1 ] << 8 ;
54- * offset += 2 ;
55-
56- if (* offset == msblk -> devblksize ) {
57- put_bh (bh );
58- bh = sb_bread (sb , ++ (* cur_index ));
59- if (bh == NULL )
60- return NULL ;
61- * offset = 0 ;
80+ const u64 read_start = round_down (index , msblk -> devblksize );
81+ const sector_t block = read_start >> msblk -> devblksize_log2 ;
82+ const u64 read_end = round_up (index + length , msblk -> devblksize );
83+ const sector_t block_end = read_end >> msblk -> devblksize_log2 ;
84+ int offset = read_start - round_down (index , PAGE_SIZE );
85+ int total_len = (block_end - block ) << msblk -> devblksize_log2 ;
86+ const int page_count = DIV_ROUND_UP (total_len + offset , PAGE_SIZE );
87+ int error , i ;
88+ struct bio * bio ;
89+
90+ bio = bio_alloc (GFP_NOIO , page_count );
91+ if (!bio )
92+ return - ENOMEM ;
93+
94+ bio_set_dev (bio , sb -> s_bdev );
95+ bio -> bi_opf = READ ;
96+ bio -> bi_iter .bi_sector = block * (msblk -> devblksize >> SECTOR_SHIFT );
97+
98+ for (i = 0 ; i < page_count ; ++ i ) {
99+ unsigned int len =
100+ min_t (unsigned int , PAGE_SIZE - offset , total_len );
101+ struct page * page = alloc_page (GFP_NOIO );
102+
103+ if (!page ) {
104+ error = - ENOMEM ;
105+ goto out_free_bio ;
106+ }
107+ if (!bio_add_page (bio , page , len , offset )) {
108+ error = - EIO ;
109+ goto out_free_bio ;
62110 }
111+ offset = 0 ;
112+ total_len -= len ;
63113 }
64114
65- return bh ;
66- }
115+ error = submit_bio_wait (bio );
116+ if (error )
117+ goto out_free_bio ;
67118
119+ * biop = bio ;
120+ * block_offset = index & ((1 << msblk -> devblksize_log2 ) - 1 );
121+ return 0 ;
122+
123+ out_free_bio :
124+ bio_free_pages (bio );
125+ bio_put (bio );
126+ return error ;
127+ }
68128
69129/*
70130 * Read and decompress a metadata block or datablock. Length is non-zero
@@ -76,129 +136,88 @@ static struct buffer_head *get_block_length(struct super_block *sb,
76136 * algorithms).
77137 */
78138int squashfs_read_data (struct super_block * sb , u64 index , int length ,
79- u64 * next_index , struct squashfs_page_actor * output )
139+ u64 * next_index , struct squashfs_page_actor * output )
80140{
81141 struct squashfs_sb_info * msblk = sb -> s_fs_info ;
82- struct buffer_head * * bh ;
83- int offset = index & ((1 << msblk -> devblksize_log2 ) - 1 );
84- u64 cur_index = index >> msblk -> devblksize_log2 ;
85- int bytes , compressed , b = 0 , k = 0 , avail , i ;
86-
87- bh = kcalloc (((output -> length + msblk -> devblksize - 1 )
88- >> msblk -> devblksize_log2 ) + 1 , sizeof (* bh ), GFP_KERNEL );
89- if (bh == NULL )
90- return - ENOMEM ;
142+ struct bio * bio = NULL ;
143+ int compressed ;
144+ int res ;
145+ int offset ;
91146
92147 if (length ) {
93148 /*
94149 * Datablock.
95150 */
96- bytes = - offset ;
97151 compressed = SQUASHFS_COMPRESSED_BLOCK (length );
98152 length = SQUASHFS_COMPRESSED_SIZE_BLOCK (length );
99- if (next_index )
100- * next_index = index + length ;
101-
102153 TRACE ("Block @ 0x%llx, %scompressed size %d, src size %d\n" ,
103154 index , compressed ? "" : "un" , length , output -> length );
104-
105- if (length < 0 || length > output -> length ||
106- (index + length ) > msblk -> bytes_used )
107- goto read_failure ;
108-
109- for (b = 0 ; bytes < length ; b ++ , cur_index ++ ) {
110- bh [b ] = sb_getblk (sb , cur_index );
111- if (bh [b ] == NULL )
112- goto block_release ;
113- bytes += msblk -> devblksize ;
114- }
115- ll_rw_block (REQ_OP_READ , 0 , b , bh );
116155 } else {
117156 /*
118157 * Metadata block.
119158 */
120- if ((index + 2 ) > msblk -> bytes_used )
121- goto read_failure ;
159+ const u8 * data ;
160+ struct bvec_iter_all iter_all = {};
161+ struct bio_vec * bvec = bvec_init_iter_all (& iter_all );
122162
123- bh [0 ] = get_block_length (sb , & cur_index , & offset , & length );
124- if (bh [0 ] == NULL )
125- goto read_failure ;
126- b = 1 ;
163+ if (index + 2 > msblk -> bytes_used ) {
164+ res = - EIO ;
165+ goto out ;
166+ }
167+ res = squashfs_bio_read (sb , index , 2 , & bio , & offset );
168+ if (res )
169+ goto out ;
170+
171+ if (WARN_ON_ONCE (!bio_next_segment (bio , & iter_all ))) {
172+ res = - EIO ;
173+ goto out_free_bio ;
174+ }
175+ /* Extract the length of the metadata block */
176+ data = page_address (bvec -> bv_page ) + bvec -> bv_offset ;
177+ length = data [offset ];
178+ if (offset <= bvec -> bv_len - 1 ) {
179+ length |= data [offset + 1 ] << 8 ;
180+ } else {
181+ if (WARN_ON_ONCE (!bio_next_segment (bio , & iter_all ))) {
182+ res = - EIO ;
183+ goto out_free_bio ;
184+ }
185+ data = page_address (bvec -> bv_page ) + bvec -> bv_offset ;
186+ length |= data [0 ] << 8 ;
187+ }
188+ bio_free_pages (bio );
189+ bio_put (bio );
127190
128- bytes = msblk -> devblksize - offset ;
129191 compressed = SQUASHFS_COMPRESSED (length );
130192 length = SQUASHFS_COMPRESSED_SIZE (length );
131- if (next_index )
132- * next_index = index + length + 2 ;
193+ index += 2 ;
133194
134195 TRACE ("Block @ 0x%llx, %scompressed size %d\n" , index ,
135- compressed ? "" : "un" , length );
136-
137- if (length < 0 || length > output -> length ||
138- (index + length ) > msblk -> bytes_used )
139- goto block_release ;
140-
141- for (; bytes < length ; b ++ ) {
142- bh [b ] = sb_getblk (sb , ++ cur_index );
143- if (bh [b ] == NULL )
144- goto block_release ;
145- bytes += msblk -> devblksize ;
146- }
147- ll_rw_block (REQ_OP_READ , 0 , b - 1 , bh + 1 );
196+ compressed ? "" : "un" , length );
148197 }
198+ if (next_index )
199+ * next_index = index + length ;
149200
150- for (i = 0 ; i < b ; i ++ ) {
151- wait_on_buffer (bh [i ]);
152- if (!buffer_uptodate (bh [i ]))
153- goto block_release ;
154- }
201+ res = squashfs_bio_read (sb , index , length , & bio , & offset );
202+ if (res )
203+ goto out ;
155204
156205 if (compressed ) {
157- if (!msblk -> stream )
158- goto read_failure ;
159- length = squashfs_decompress (msblk , bh , b , offset , length ,
160- output );
161- if (length < 0 )
162- goto read_failure ;
163- } else {
164- /*
165- * Block is uncompressed.
166- */
167- int in , pg_offset = 0 ;
168- void * data = squashfs_first_page (output );
169-
170- for (bytes = length ; k < b ; k ++ ) {
171- in = min (bytes , msblk -> devblksize - offset );
172- bytes -= in ;
173- while (in ) {
174- if (pg_offset == PAGE_SIZE ) {
175- data = squashfs_next_page (output );
176- pg_offset = 0 ;
177- }
178- avail = min_t (int , in , PAGE_SIZE -
179- pg_offset );
180- memcpy (data + pg_offset , bh [k ]-> b_data + offset ,
181- avail );
182- in -= avail ;
183- pg_offset += avail ;
184- offset += avail ;
185- }
186- offset = 0 ;
187- put_bh (bh [k ]);
206+ if (!msblk -> stream ) {
207+ res = - EIO ;
208+ goto out_free_bio ;
188209 }
189- squashfs_finish_page (output );
210+ res = squashfs_decompress (msblk , bio , offset , length , output );
211+ } else {
212+ res = copy_bio_to_actor (bio , output , offset , length );
190213 }
191214
192- kfree ( bh );
193- return length ;
194-
195- block_release :
196- for (; k < b ; k ++ )
197- put_bh ( bh [ k ] );
215+ out_free_bio :
216+ bio_free_pages ( bio ) ;
217+ bio_put ( bio );
218+ out :
219+ if ( res < 0 )
220+ ERROR ( "Failed to read block 0x%llx: %d\n" , index , res );
198221
199- read_failure :
200- ERROR ("squashfs_read_data failed to read block 0x%llx\n" ,
201- (unsigned long long ) index );
202- kfree (bh );
203- return - EIO ;
222+ return res ;
204223}
0 commit comments