@@ -100,24 +100,23 @@ static int z_erofs_load_deflate_config(struct super_block *sb,
100100static int z_erofs_deflate_decompress (struct z_erofs_decompress_req * rq ,
101101 struct page * * pgpl )
102102{
103- const unsigned int nrpages_out =
104- PAGE_ALIGN (rq -> pageofs_out + rq -> outputsize ) >> PAGE_SHIFT ;
105- const unsigned int nrpages_in =
106- PAGE_ALIGN (rq -> inputsize ) >> PAGE_SHIFT ;
107103 struct super_block * sb = rq -> sb ;
108- unsigned int insz , outsz , pofs ;
104+ struct z_erofs_stream_dctx dctx = {
105+ .rq = rq ,
106+ .inpages = PAGE_ALIGN (rq -> inputsize ) >> PAGE_SHIFT ,
107+ .outpages = PAGE_ALIGN (rq -> pageofs_out + rq -> outputsize )
108+ >> PAGE_SHIFT ,
109+ .no = -1 , .ni = 0 ,
110+ };
109111 struct z_erofs_deflate * strm ;
110- u8 * kin , * kout = NULL ;
111- bool bounced = false;
112- int no = -1 , ni = 0 , j = 0 , zerr , err ;
112+ int zerr , err ;
113113
114114 /* 1. get the exact DEFLATE compressed size */
115- kin = kmap_local_page (* rq -> in );
116- err = z_erofs_fixup_insize (rq , kin + rq -> pageofs_in ,
117- min_t (unsigned int , rq -> inputsize ,
118- sb -> s_blocksize - rq -> pageofs_in ));
115+ dctx .kin = kmap_local_page (* rq -> in );
116+ err = z_erofs_fixup_insize (rq , dctx .kin + rq -> pageofs_in ,
117+ min (rq -> inputsize , sb -> s_blocksize - rq -> pageofs_in ));
119118 if (err ) {
120- kunmap_local (kin );
119+ kunmap_local (dctx . kin );
121120 return err ;
122121 }
123122
@@ -134,116 +133,48 @@ static int z_erofs_deflate_decompress(struct z_erofs_decompress_req *rq,
134133 spin_unlock (& z_erofs_deflate_lock );
135134
136135 /* 3. multi-call decompress */
137- insz = rq -> inputsize ;
138- outsz = rq -> outputsize ;
139136 zerr = zlib_inflateInit2 (& strm -> z , - MAX_WBITS );
140137 if (zerr != Z_OK ) {
141138 err = - EIO ;
142139 goto failed_zinit ;
143140 }
144141
145- pofs = rq -> pageofs_out ;
146- strm -> z .avail_in = min_t ( u32 , insz , PAGE_SIZE - rq -> pageofs_in );
147- insz -= strm -> z .avail_in ;
148- strm -> z .next_in = kin + rq -> pageofs_in ;
142+ rq -> fillgaps = true; /* DEFLATE doesn't support NULL output buffer */
143+ strm -> z .avail_in = min ( rq -> inputsize , PAGE_SIZE - rq -> pageofs_in );
144+ rq -> inputsize -= strm -> z .avail_in ;
145+ strm -> z .next_in = dctx . kin + rq -> pageofs_in ;
149146 strm -> z .avail_out = 0 ;
147+ dctx .bounce = strm -> bounce ;
150148
151149 while (1 ) {
152- if (!strm -> z .avail_out ) {
153- if (++ no >= nrpages_out || !outsz ) {
154- erofs_err (sb , "insufficient space for decompressed data" );
155- err = - EFSCORRUPTED ;
156- break ;
157- }
158-
159- if (kout )
160- kunmap_local (kout );
161- strm -> z .avail_out = min_t (u32 , outsz , PAGE_SIZE - pofs );
162- outsz -= strm -> z .avail_out ;
163- if (!rq -> out [no ]) {
164- rq -> out [no ] = erofs_allocpage (pgpl , rq -> gfp );
165- if (!rq -> out [no ]) {
166- kout = NULL ;
167- err = - ENOMEM ;
168- break ;
169- }
170- set_page_private (rq -> out [no ],
171- Z_EROFS_SHORTLIVED_PAGE );
172- }
173- kout = kmap_local_page (rq -> out [no ]);
174- strm -> z .next_out = kout + pofs ;
175- pofs = 0 ;
176- }
177-
178- if (!strm -> z .avail_in && insz ) {
179- if (++ ni >= nrpages_in ) {
180- erofs_err (sb , "invalid compressed data" );
181- err = - EFSCORRUPTED ;
182- break ;
183- }
184-
185- if (kout ) { /* unlike kmap(), take care of the orders */
186- j = strm -> z .next_out - kout ;
187- kunmap_local (kout );
188- }
189- kunmap_local (kin );
190- strm -> z .avail_in = min_t (u32 , insz , PAGE_SIZE );
191- insz -= strm -> z .avail_in ;
192- kin = kmap_local_page (rq -> in [ni ]);
193- strm -> z .next_in = kin ;
194- bounced = false;
195- if (kout ) {
196- kout = kmap_local_page (rq -> out [no ]);
197- strm -> z .next_out = kout + j ;
198- }
199- }
200-
201- /*
202- * Handle overlapping: Use bounced buffer if the compressed
203- * data is under processing; Or use short-lived pages from the
204- * on-stack pagepool where pages share among the same request
205- * and not _all_ inplace I/O pages are needed to be doubled.
206- */
207- if (!bounced && rq -> out [no ] == rq -> in [ni ]) {
208- memcpy (strm -> bounce , strm -> z .next_in , strm -> z .avail_in );
209- strm -> z .next_in = strm -> bounce ;
210- bounced = true;
211- }
212-
213- for (j = ni + 1 ; j < nrpages_in ; ++ j ) {
214- struct page * tmppage ;
215-
216- if (rq -> out [no ] != rq -> in [j ])
217- continue ;
218- tmppage = erofs_allocpage (pgpl , rq -> gfp );
219- if (!tmppage ) {
220- err = - ENOMEM ;
221- goto failed ;
222- }
223- set_page_private (tmppage , Z_EROFS_SHORTLIVED_PAGE );
224- copy_highpage (tmppage , rq -> in [j ]);
225- rq -> in [j ] = tmppage ;
226- }
150+ dctx .avail_out = strm -> z .avail_out ;
151+ dctx .inbuf_sz = strm -> z .avail_in ;
152+ err = z_erofs_stream_switch_bufs (& dctx ,
153+ (void * * )& strm -> z .next_out ,
154+ (void * * )& strm -> z .next_in , pgpl );
155+ if (err )
156+ break ;
157+ strm -> z .avail_out = dctx .avail_out ;
158+ strm -> z .avail_in = dctx .inbuf_sz ;
227159
228160 zerr = zlib_inflate (& strm -> z , Z_SYNC_FLUSH );
229- if (zerr != Z_OK || !(outsz + strm -> z .avail_out )) {
161+ if (zerr != Z_OK || !(rq -> outputsize + strm -> z .avail_out )) {
230162 if (zerr == Z_OK && rq -> partial_decoding )
231163 break ;
232- if (zerr == Z_STREAM_END && !outsz )
164+ if (zerr == Z_STREAM_END && !rq -> outputsize )
233165 break ;
234166 erofs_err (sb , "failed to decompress %d in[%u] out[%u]" ,
235167 zerr , rq -> inputsize , rq -> outputsize );
236168 err = - EFSCORRUPTED ;
237169 break ;
238170 }
239171 }
240- failed :
241172 if (zlib_inflateEnd (& strm -> z ) != Z_OK && !err )
242173 err = - EIO ;
243- if (kout )
244- kunmap_local (kout );
174+ if (dctx . kout )
175+ kunmap_local (dctx . kout );
245176failed_zinit :
246- kunmap_local (kin );
177+ kunmap_local (dctx . kin );
247178 /* 4. push back DEFLATE stream context to the global list */
248179 spin_lock (& z_erofs_deflate_lock );
249180 strm -> next = z_erofs_deflate_head ;
0 commit comments