@@ -1242,38 +1242,26 @@ static int pipe_to_user(struct pipe_inode_info *pipe, struct pipe_buffer *buf,
1242
1242
* For lack of a better implementation, implement vmsplice() to userspace
1243
1243
* as a simple copy of the pipes pages to the user iov.
1244
1244
*/
1245
- static long vmsplice_to_user (struct file * file , const struct iovec __user * uiov ,
1246
- unsigned long nr_segs , unsigned int flags )
1245
+ static long vmsplice_to_user (struct file * file , struct iov_iter * iter ,
1246
+ unsigned int flags )
1247
1247
{
1248
- struct pipe_inode_info * pipe ;
1249
- struct splice_desc sd ;
1250
- long ret ;
1251
- struct iovec iovstack [UIO_FASTIOV ];
1252
- struct iovec * iov = iovstack ;
1253
- struct iov_iter iter ;
1248
+ struct pipe_inode_info * pipe = get_pipe_info (file );
1249
+ struct splice_desc sd = {
1250
+ .total_len = iov_iter_count (iter ),
1251
+ .flags = flags ,
1252
+ .u .data = iter
1253
+ };
1254
+ long ret = 0 ;
1254
1255
1255
- pipe = get_pipe_info (file );
1256
1256
if (!pipe )
1257
1257
return - EBADF ;
1258
1258
1259
- ret = import_iovec (READ , uiov , nr_segs ,
1260
- ARRAY_SIZE (iovstack ), & iov , & iter );
1261
- if (ret < 0 )
1262
- return ret ;
1263
-
1264
- sd .total_len = iov_iter_count (& iter );
1265
- sd .len = 0 ;
1266
- sd .flags = flags ;
1267
- sd .u .data = & iter ;
1268
- sd .pos = 0 ;
1269
-
1270
1259
if (sd .total_len ) {
1271
1260
pipe_lock (pipe );
1272
1261
ret = __splice_from_pipe (pipe , & sd , pipe_to_user );
1273
1262
pipe_unlock (pipe );
1274
1263
}
1275
1264
1276
- kfree (iov );
1277
1265
return ret ;
1278
1266
}
1279
1267
@@ -1282,14 +1270,11 @@ static long vmsplice_to_user(struct file *file, const struct iovec __user *uiov,
1282
1270
* as splice-from-memory, where the regular splice is splice-from-file (or
1283
1271
* to file). In both cases the output is a pipe, naturally.
1284
1272
*/
1285
- static long vmsplice_to_pipe (struct file * file , const struct iovec __user * uiov ,
1286
- unsigned long nr_segs , unsigned int flags )
1273
+ static long vmsplice_to_pipe (struct file * file , struct iov_iter * iter ,
1274
+ unsigned int flags )
1287
1275
{
1288
1276
struct pipe_inode_info * pipe ;
1289
- struct iovec iovstack [UIO_FASTIOV ];
1290
- struct iovec * iov = iovstack ;
1291
- struct iov_iter from ;
1292
- long ret ;
1277
+ long ret = 0 ;
1293
1278
unsigned buf_flag = 0 ;
1294
1279
1295
1280
if (flags & SPLICE_F_GIFT )
@@ -1299,22 +1284,31 @@ static long vmsplice_to_pipe(struct file *file, const struct iovec __user *uiov,
1299
1284
if (!pipe )
1300
1285
return - EBADF ;
1301
1286
1302
- ret = import_iovec (WRITE , uiov , nr_segs ,
1303
- ARRAY_SIZE (iovstack ), & iov , & from );
1304
- if (ret < 0 )
1305
- return ret ;
1306
-
1307
1287
pipe_lock (pipe );
1308
1288
ret = wait_for_space (pipe , flags );
1309
1289
if (!ret )
1310
- ret = iter_to_pipe (& from , pipe , buf_flag );
1290
+ ret = iter_to_pipe (iter , pipe , buf_flag );
1311
1291
pipe_unlock (pipe );
1312
1292
if (ret > 0 )
1313
1293
wakeup_pipe_readers (pipe );
1314
- kfree (iov );
1315
1294
return ret ;
1316
1295
}
1317
1296
1297
+ static int vmsplice_type (struct fd f , int * type )
1298
+ {
1299
+ if (!f .file )
1300
+ return - EBADF ;
1301
+ if (f .file -> f_mode & FMODE_WRITE ) {
1302
+ * type = WRITE ;
1303
+ } else if (f .file -> f_mode & FMODE_READ ) {
1304
+ * type = READ ;
1305
+ } else {
1306
+ fdput (f );
1307
+ return - EBADF ;
1308
+ }
1309
+ return 0 ;
1310
+ }
1311
+
1318
1312
/*
1319
1313
* Note that vmsplice only really supports true splicing _from_ user memory
1320
1314
* to a pipe, not the other way around. Splicing from user memory is a simple
@@ -1331,57 +1325,69 @@ static long vmsplice_to_pipe(struct file *file, const struct iovec __user *uiov,
1331
1325
* Currently we punt and implement it as a normal copy, see pipe_to_user().
1332
1326
*
1333
1327
*/
1334
- static long do_vmsplice (int fd , const struct iovec __user * iov ,
1335
- unsigned long nr_segs , unsigned int flags )
1328
+ static long do_vmsplice (struct file * f , struct iov_iter * iter , unsigned int flags )
1336
1329
{
1337
- struct fd f ;
1338
- long error ;
1339
-
1340
1330
if (unlikely (flags & ~SPLICE_F_ALL ))
1341
1331
return - EINVAL ;
1342
- if (unlikely (nr_segs > UIO_MAXIOV ))
1343
- return - EINVAL ;
1344
- else if (unlikely (!nr_segs ))
1345
- return 0 ;
1346
1332
1347
- error = - EBADF ;
1348
- f = fdget (fd );
1349
- if (f .file ) {
1350
- if (f .file -> f_mode & FMODE_WRITE )
1351
- error = vmsplice_to_pipe (f .file , iov , nr_segs , flags );
1352
- else if (f .file -> f_mode & FMODE_READ )
1353
- error = vmsplice_to_user (f .file , iov , nr_segs , flags );
1354
-
1355
- fdput (f );
1356
- }
1333
+ if (!iov_iter_count (iter ))
1334
+ return 0 ;
1357
1335
1358
- return error ;
1336
+ if (iov_iter_rw (iter ) == WRITE )
1337
+ return vmsplice_to_pipe (f , iter , flags );
1338
+ else
1339
+ return vmsplice_to_user (f , iter , flags );
1359
1340
}
1360
1341
1361
- SYSCALL_DEFINE4 (vmsplice , int , fd , const struct iovec __user * , iov ,
1342
+ SYSCALL_DEFINE4 (vmsplice , int , fd , const struct iovec __user * , uiov ,
1362
1343
unsigned long , nr_segs , unsigned int , flags )
1363
1344
{
1364
- return do_vmsplice (fd , iov , nr_segs , flags );
1345
+ struct iovec iovstack [UIO_FASTIOV ];
1346
+ struct iovec * iov = iovstack ;
1347
+ struct iov_iter iter ;
1348
+ long error ;
1349
+ struct fd f ;
1350
+ int type ;
1351
+
1352
+ f = fdget (fd );
1353
+ error = vmsplice_type (f , & type );
1354
+ if (error )
1355
+ return error ;
1356
+
1357
+ error = import_iovec (type , uiov , nr_segs ,
1358
+ ARRAY_SIZE (iovstack ), & iov , & iter );
1359
+ if (!error ) {
1360
+ error = do_vmsplice (f .file , & iter , flags );
1361
+ kfree (iov );
1362
+ }
1363
+ fdput (f );
1364
+ return error ;
1365
1365
}
1366
1366
1367
1367
#ifdef CONFIG_COMPAT
1368
1368
COMPAT_SYSCALL_DEFINE4 (vmsplice , int , fd , const struct compat_iovec __user * , iov32 ,
1369
1369
unsigned int , nr_segs , unsigned int , flags )
1370
1370
{
1371
- unsigned i ;
1372
- struct iovec __user * iov ;
1373
- if (nr_segs > UIO_MAXIOV )
1374
- return - EINVAL ;
1375
- iov = compat_alloc_user_space (nr_segs * sizeof (struct iovec ));
1376
- for (i = 0 ; i < nr_segs ; i ++ ) {
1377
- struct compat_iovec v ;
1378
- if (get_user (v .iov_base , & iov32 [i ].iov_base ) ||
1379
- get_user (v .iov_len , & iov32 [i ].iov_len ) ||
1380
- put_user (compat_ptr (v .iov_base ), & iov [i ].iov_base ) ||
1381
- put_user (v .iov_len , & iov [i ].iov_len ))
1382
- return - EFAULT ;
1371
+ struct iovec iovstack [UIO_FASTIOV ];
1372
+ struct iovec * iov = iovstack ;
1373
+ struct iov_iter iter ;
1374
+ long error ;
1375
+ struct fd f ;
1376
+ int type ;
1377
+
1378
+ f = fdget (fd );
1379
+ error = vmsplice_type (f , & type );
1380
+ if (error )
1381
+ return error ;
1382
+
1383
+ error = compat_import_iovec (type , iov32 , nr_segs ,
1384
+ ARRAY_SIZE (iovstack ), & iov , & iter );
1385
+ if (!error ) {
1386
+ error = do_vmsplice (f .file , & iter , flags );
1387
+ kfree (iov );
1383
1388
}
1384
- return do_vmsplice (fd , iov , nr_segs , flags );
1389
+ fdput (f );
1390
+ return error ;
1385
1391
}
1386
1392
#endif
1387
1393
0 commit comments