@@ -100,24 +100,23 @@ static int z_erofs_load_deflate_config(struct super_block *sb,
100
100
static int z_erofs_deflate_decompress (struct z_erofs_decompress_req * rq ,
101
101
struct page * * pgpl )
102
102
{
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 ;
107
103
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
+ };
109
111
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 ;
113
113
114
114
/* 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 ));
119
118
if (err ) {
120
- kunmap_local (kin );
119
+ kunmap_local (dctx . kin );
121
120
return err ;
122
121
}
123
122
@@ -134,116 +133,48 @@ static int z_erofs_deflate_decompress(struct z_erofs_decompress_req *rq,
134
133
spin_unlock (& z_erofs_deflate_lock );
135
134
136
135
/* 3. multi-call decompress */
137
- insz = rq -> inputsize ;
138
- outsz = rq -> outputsize ;
139
136
zerr = zlib_inflateInit2 (& strm -> z , - MAX_WBITS );
140
137
if (zerr != Z_OK ) {
141
138
err = - EIO ;
142
139
goto failed_zinit ;
143
140
}
144
141
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 ;
149
146
strm -> z .avail_out = 0 ;
147
+ dctx .bounce = strm -> bounce ;
150
148
151
149
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 ;
227
159
228
160
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 )) {
230
162
if (zerr == Z_OK && rq -> partial_decoding )
231
163
break ;
232
- if (zerr == Z_STREAM_END && !outsz )
164
+ if (zerr == Z_STREAM_END && !rq -> outputsize )
233
165
break ;
234
166
erofs_err (sb , "failed to decompress %d in[%u] out[%u]" ,
235
167
zerr , rq -> inputsize , rq -> outputsize );
236
168
err = - EFSCORRUPTED ;
237
169
break ;
238
170
}
239
171
}
240
- failed :
241
172
if (zlib_inflateEnd (& strm -> z ) != Z_OK && !err )
242
173
err = - EIO ;
243
- if (kout )
244
- kunmap_local (kout );
174
+ if (dctx . kout )
175
+ kunmap_local (dctx . kout );
245
176
failed_zinit :
246
- kunmap_local (kin );
177
+ kunmap_local (dctx . kin );
247
178
/* 4. push back DEFLATE stream context to the global list */
248
179
spin_lock (& z_erofs_deflate_lock );
249
180
strm -> next = z_erofs_deflate_head ;
0 commit comments