@@ -183,79 +183,41 @@ ssize_t splice_to_pipe(struct pipe_inode_info *pipe,
183
183
struct splice_pipe_desc * spd )
184
184
{
185
185
unsigned int spd_pages = spd -> nr_pages ;
186
- int ret , do_wakeup , page_nr ;
186
+ int ret = 0 , page_nr = 0 ;
187
187
188
188
if (!spd_pages )
189
189
return 0 ;
190
190
191
- ret = 0 ;
192
- do_wakeup = 0 ;
193
- page_nr = 0 ;
194
-
195
- pipe_lock (pipe );
196
-
197
- for (;;) {
198
- if (!pipe -> readers ) {
199
- send_sig (SIGPIPE , current , 0 );
200
- if (!ret )
201
- ret = - EPIPE ;
202
- break ;
203
- }
204
-
205
- if (pipe -> nrbufs < pipe -> buffers ) {
206
- int newbuf = (pipe -> curbuf + pipe -> nrbufs ) & (pipe -> buffers - 1 );
207
- struct pipe_buffer * buf = pipe -> bufs + newbuf ;
208
-
209
- buf -> page = spd -> pages [page_nr ];
210
- buf -> offset = spd -> partial [page_nr ].offset ;
211
- buf -> len = spd -> partial [page_nr ].len ;
212
- buf -> private = spd -> partial [page_nr ].private ;
213
- buf -> ops = spd -> ops ;
214
- if (spd -> flags & SPLICE_F_GIFT )
215
- buf -> flags |= PIPE_BUF_FLAG_GIFT ;
216
-
217
- pipe -> nrbufs ++ ;
218
- page_nr ++ ;
219
- ret += buf -> len ;
220
-
221
- if (pipe -> files )
222
- do_wakeup = 1 ;
191
+ if (unlikely (!pipe -> readers )) {
192
+ send_sig (SIGPIPE , current , 0 );
193
+ ret = - EPIPE ;
194
+ goto out ;
195
+ }
223
196
224
- if (!-- spd -> nr_pages )
225
- break ;
226
- if (pipe -> nrbufs < pipe -> buffers )
227
- continue ;
197
+ while (pipe -> nrbufs < pipe -> buffers ) {
198
+ int newbuf = (pipe -> curbuf + pipe -> nrbufs ) & (pipe -> buffers - 1 );
199
+ struct pipe_buffer * buf = pipe -> bufs + newbuf ;
228
200
229
- break ;
230
- }
201
+ buf -> page = spd -> pages [page_nr ];
202
+ buf -> offset = spd -> partial [page_nr ].offset ;
203
+ buf -> len = spd -> partial [page_nr ].len ;
204
+ buf -> private = spd -> partial [page_nr ].private ;
205
+ buf -> ops = spd -> ops ;
206
+ if (spd -> flags & SPLICE_F_GIFT )
207
+ buf -> flags |= PIPE_BUF_FLAG_GIFT ;
231
208
232
- if (spd -> flags & SPLICE_F_NONBLOCK ) {
233
- if (!ret )
234
- ret = - EAGAIN ;
235
- break ;
236
- }
209
+ pipe -> nrbufs ++ ;
210
+ page_nr ++ ;
211
+ ret += buf -> len ;
237
212
238
- if (signal_pending (current )) {
239
- if (!ret )
240
- ret = - ERESTARTSYS ;
213
+ if (!-- spd -> nr_pages )
241
214
break ;
242
- }
243
-
244
- if (do_wakeup ) {
245
- wakeup_pipe_readers (pipe );
246
- do_wakeup = 0 ;
247
- }
248
-
249
- pipe -> waiting_writers ++ ;
250
- pipe_wait (pipe );
251
- pipe -> waiting_writers -- ;
252
215
}
253
216
254
- pipe_unlock (pipe );
255
-
256
- if (do_wakeup )
257
- wakeup_pipe_readers (pipe );
217
+ if (!ret )
218
+ ret = - EAGAIN ;
258
219
220
+ out :
259
221
while (page_nr < spd_pages )
260
222
spd -> spd_release (spd , page_nr ++ );
261
223
@@ -1339,6 +1301,20 @@ long do_splice_direct(struct file *in, loff_t *ppos, struct file *out,
1339
1301
}
1340
1302
EXPORT_SYMBOL (do_splice_direct );
1341
1303
1304
+ static int wait_for_space (struct pipe_inode_info * pipe , unsigned flags )
1305
+ {
1306
+ while (pipe -> nrbufs == pipe -> buffers ) {
1307
+ if (flags & SPLICE_F_NONBLOCK )
1308
+ return - EAGAIN ;
1309
+ if (signal_pending (current ))
1310
+ return - ERESTARTSYS ;
1311
+ pipe -> waiting_writers ++ ;
1312
+ pipe_wait (pipe );
1313
+ pipe -> waiting_writers -- ;
1314
+ }
1315
+ return 0 ;
1316
+ }
1317
+
1342
1318
static int splice_pipe_to_pipe (struct pipe_inode_info * ipipe ,
1343
1319
struct pipe_inode_info * opipe ,
1344
1320
size_t len , unsigned int flags );
@@ -1421,8 +1397,13 @@ static long do_splice(struct file *in, loff_t __user *off_in,
1421
1397
offset = in -> f_pos ;
1422
1398
}
1423
1399
1424
- ret = do_splice_to (in , & offset , opipe , len , flags );
1425
-
1400
+ pipe_lock (opipe );
1401
+ ret = wait_for_space (opipe , flags );
1402
+ if (!ret )
1403
+ ret = do_splice_to (in , & offset , opipe , len , flags );
1404
+ pipe_unlock (opipe );
1405
+ if (ret > 0 )
1406
+ wakeup_pipe_readers (opipe );
1426
1407
if (!off_in )
1427
1408
in -> f_pos = offset ;
1428
1409
else if (copy_to_user (off_in , & offset , sizeof (loff_t )))
@@ -1546,14 +1527,20 @@ static long vmsplice_to_pipe(struct file *file, const struct iovec __user *uiov,
1546
1527
return - ENOMEM ;
1547
1528
}
1548
1529
1549
- spd .nr_pages = get_iovec_page_array (& from , spd .pages ,
1550
- spd .partial ,
1551
- spd .nr_pages_max );
1552
- if (spd .nr_pages <= 0 )
1553
- ret = spd .nr_pages ;
1554
- else
1555
- ret = splice_to_pipe (pipe , & spd );
1556
-
1530
+ pipe_lock (pipe );
1531
+ ret = wait_for_space (pipe , flags );
1532
+ if (!ret ) {
1533
+ spd .nr_pages = get_iovec_page_array (& from , spd .pages ,
1534
+ spd .partial ,
1535
+ spd .nr_pages_max );
1536
+ if (spd .nr_pages <= 0 )
1537
+ ret = spd .nr_pages ;
1538
+ else
1539
+ ret = splice_to_pipe (pipe , & spd );
1540
+ }
1541
+ pipe_unlock (pipe );
1542
+ if (ret > 0 )
1543
+ wakeup_pipe_readers (pipe );
1557
1544
splice_shrink_spd (& spd );
1558
1545
kfree (iov );
1559
1546
return ret ;
0 commit comments