diff options
Diffstat (limited to 'fs/aio.c')
-rw-r--r-- | fs/aio.c | 14 |
1 files changed, 12 insertions, 2 deletions
@@ -1241,6 +1241,7 @@ SYSCALL_DEFINE1(io_destroy, aio_context_t, ctx) | |||
1241 | 1241 | ||
1242 | typedef ssize_t (aio_rw_op)(struct kiocb *, const struct iovec *, | 1242 | typedef ssize_t (aio_rw_op)(struct kiocb *, const struct iovec *, |
1243 | unsigned long, loff_t); | 1243 | unsigned long, loff_t); |
1244 | typedef ssize_t (rw_iter_op)(struct kiocb *, struct iov_iter *); | ||
1244 | 1245 | ||
1245 | static ssize_t aio_setup_vectored_rw(struct kiocb *kiocb, | 1246 | static ssize_t aio_setup_vectored_rw(struct kiocb *kiocb, |
1246 | int rw, char __user *buf, | 1247 | int rw, char __user *buf, |
@@ -1298,7 +1299,9 @@ static ssize_t aio_run_iocb(struct kiocb *req, unsigned opcode, | |||
1298 | int rw; | 1299 | int rw; |
1299 | fmode_t mode; | 1300 | fmode_t mode; |
1300 | aio_rw_op *rw_op; | 1301 | aio_rw_op *rw_op; |
1302 | rw_iter_op *iter_op; | ||
1301 | struct iovec inline_vec, *iovec = &inline_vec; | 1303 | struct iovec inline_vec, *iovec = &inline_vec; |
1304 | struct iov_iter iter; | ||
1302 | 1305 | ||
1303 | switch (opcode) { | 1306 | switch (opcode) { |
1304 | case IOCB_CMD_PREAD: | 1307 | case IOCB_CMD_PREAD: |
@@ -1306,6 +1309,7 @@ static ssize_t aio_run_iocb(struct kiocb *req, unsigned opcode, | |||
1306 | mode = FMODE_READ; | 1309 | mode = FMODE_READ; |
1307 | rw = READ; | 1310 | rw = READ; |
1308 | rw_op = file->f_op->aio_read; | 1311 | rw_op = file->f_op->aio_read; |
1312 | iter_op = file->f_op->read_iter; | ||
1309 | goto rw_common; | 1313 | goto rw_common; |
1310 | 1314 | ||
1311 | case IOCB_CMD_PWRITE: | 1315 | case IOCB_CMD_PWRITE: |
@@ -1313,12 +1317,13 @@ static ssize_t aio_run_iocb(struct kiocb *req, unsigned opcode, | |||
1313 | mode = FMODE_WRITE; | 1317 | mode = FMODE_WRITE; |
1314 | rw = WRITE; | 1318 | rw = WRITE; |
1315 | rw_op = file->f_op->aio_write; | 1319 | rw_op = file->f_op->aio_write; |
1320 | iter_op = file->f_op->write_iter; | ||
1316 | goto rw_common; | 1321 | goto rw_common; |
1317 | rw_common: | 1322 | rw_common: |
1318 | if (unlikely(!(file->f_mode & mode))) | 1323 | if (unlikely(!(file->f_mode & mode))) |
1319 | return -EBADF; | 1324 | return -EBADF; |
1320 | 1325 | ||
1321 | if (!rw_op) | 1326 | if (!rw_op && !iter_op) |
1322 | return -EINVAL; | 1327 | return -EINVAL; |
1323 | 1328 | ||
1324 | ret = (opcode == IOCB_CMD_PREADV || | 1329 | ret = (opcode == IOCB_CMD_PREADV || |
@@ -1347,7 +1352,12 @@ rw_common: | |||
1347 | if (rw == WRITE) | 1352 | if (rw == WRITE) |
1348 | file_start_write(file); | 1353 | file_start_write(file); |
1349 | 1354 | ||
1350 | ret = rw_op(req, iovec, nr_segs, req->ki_pos); | 1355 | if (iter_op) { |
1356 | iov_iter_init(&iter, rw, iovec, nr_segs, req->ki_nbytes); | ||
1357 | ret = iter_op(req, &iter); | ||
1358 | } else { | ||
1359 | ret = rw_op(req, iovec, nr_segs, req->ki_pos); | ||
1360 | } | ||
1351 | 1361 | ||
1352 | if (rw == WRITE) | 1362 | if (rw == WRITE) |
1353 | file_end_write(file); | 1363 | file_end_write(file); |