summaryrefslogtreecommitdiffstats
path: root/fs/aio.c
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@lst.de>2018-03-27 13:18:57 -0400
committerChristoph Hellwig <hch@lst.de>2018-05-02 13:57:24 -0400
commita3c0d439e4d92411c2b4b21a526a4de720d0806b (patch)
tree6acf05c9788bc140f2687d04a2d8c4f70800cdd9 /fs/aio.c
parent54843f875f7a9f802bbb0d9895c3266b4a0b2f37 (diff)
aio: implement IOCB_CMD_FSYNC and IOCB_CMD_FDSYNC
Simple workqueue offload for now, but prepared for adding a real aio_fsync method if the need arises. Based on an earlier patch from Dave Chinner. Signed-off-by: Christoph Hellwig <hch@lst.de> Reviewed-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Reviewed-by: Darrick J. Wong <darrick.wong@oracle.com>
Diffstat (limited to 'fs/aio.c')
-rw-r--r--fs/aio.c43
1 files changed, 43 insertions, 0 deletions
diff --git a/fs/aio.c b/fs/aio.c
index d07c27b3fe88..61d2e6942951 100644
--- a/fs/aio.c
+++ b/fs/aio.c
@@ -156,6 +156,12 @@ struct kioctx {
156 unsigned id; 156 unsigned id;
157}; 157};
158 158
159struct fsync_iocb {
160 struct work_struct work;
161 struct file *file;
162 bool datasync;
163};
164
159/* 165/*
160 * We use ki_cancel == KIOCB_CANCELLED to indicate that a kiocb has been either 166 * We use ki_cancel == KIOCB_CANCELLED to indicate that a kiocb has been either
161 * cancelled or completed (this makes a certain amount of sense because 167 * cancelled or completed (this makes a certain amount of sense because
@@ -172,6 +178,7 @@ struct kioctx {
172struct aio_kiocb { 178struct aio_kiocb {
173 union { 179 union {
174 struct kiocb rw; 180 struct kiocb rw;
181 struct fsync_iocb fsync;
175 }; 182 };
176 183
177 struct kioctx *ki_ctx; 184 struct kioctx *ki_ctx;
@@ -1573,6 +1580,36 @@ out_fput:
1573 return ret; 1580 return ret;
1574} 1581}
1575 1582
1583static void aio_fsync_work(struct work_struct *work)
1584{
1585 struct fsync_iocb *req = container_of(work, struct fsync_iocb, work);
1586 int ret;
1587
1588 ret = vfs_fsync(req->file, req->datasync);
1589 fput(req->file);
1590 aio_complete(container_of(req, struct aio_kiocb, fsync), ret, 0);
1591}
1592
1593static int aio_fsync(struct fsync_iocb *req, struct iocb *iocb, bool datasync)
1594{
1595 if (unlikely(iocb->aio_buf || iocb->aio_offset || iocb->aio_nbytes ||
1596 iocb->aio_rw_flags))
1597 return -EINVAL;
1598
1599 req->file = fget(iocb->aio_fildes);
1600 if (unlikely(!req->file))
1601 return -EBADF;
1602 if (unlikely(!req->file->f_op->fsync)) {
1603 fput(req->file);
1604 return -EINVAL;
1605 }
1606
1607 req->datasync = datasync;
1608 INIT_WORK(&req->work, aio_fsync_work);
1609 schedule_work(&req->work);
1610 return -EIOCBQUEUED;
1611}
1612
1576static int io_submit_one(struct kioctx *ctx, struct iocb __user *user_iocb, 1613static int io_submit_one(struct kioctx *ctx, struct iocb __user *user_iocb,
1577 struct iocb *iocb, bool compat) 1614 struct iocb *iocb, bool compat)
1578{ 1615{
@@ -1636,6 +1673,12 @@ static int io_submit_one(struct kioctx *ctx, struct iocb __user *user_iocb,
1636 case IOCB_CMD_PWRITEV: 1673 case IOCB_CMD_PWRITEV:
1637 ret = aio_write(&req->rw, iocb, true, compat); 1674 ret = aio_write(&req->rw, iocb, true, compat);
1638 break; 1675 break;
1676 case IOCB_CMD_FSYNC:
1677 ret = aio_fsync(&req->fsync, iocb, false);
1678 break;
1679 case IOCB_CMD_FDSYNC:
1680 ret = aio_fsync(&req->fsync, iocb, true);
1681 break;
1639 default: 1682 default:
1640 pr_debug("invalid aio operation %d\n", iocb->aio_lio_opcode); 1683 pr_debug("invalid aio operation %d\n", iocb->aio_lio_opcode);
1641 ret = -EINVAL; 1684 ret = -EINVAL;