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