summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKent Overstreet <kent.overstreet@gmail.com>2015-04-10 18:50:50 -0700
committerKent Overstreet <kent.overstreet@gmail.com>2016-08-28 19:15:14 -0800
commit52e8659d75c93399ac99cf079ab602676824cf19 (patch)
tree9203ce889c1f1c574ea44f11d6c70470b7d9f2e3
parent5db6cab6185caf43b4ba6ed4078a9db2ea38710a (diff)
bcachefs: async fsync
Signed-off-by: Kent Overstreet <kent.overstreet@gmail.com>
-rw-r--r--drivers/md/bcache/fs-io.c52
-rw-r--r--drivers/md/bcache/fs-io.h1
-rw-r--r--drivers/md/bcache/fs.c1
3 files changed, 54 insertions, 0 deletions
diff --git a/drivers/md/bcache/fs-io.c b/drivers/md/bcache/fs-io.c
index 651f39dd9e96..b0079b2e6740 100644
--- a/drivers/md/bcache/fs-io.c
+++ b/drivers/md/bcache/fs-io.c
@@ -1626,6 +1626,58 @@ int bch_fsync(struct file *file, loff_t start, loff_t end, int datasync)
return bch_journal_flush_seq(&c->journal, ei->journal_seq);
}
+struct bch_aio_fsync_op {
+ struct closure cl;
+ struct kiocb *req;
+};
+
+static void bch_aio_fsync_done(struct closure *cl)
+{
+ struct bch_aio_fsync_op *op =
+ container_of(cl, struct bch_aio_fsync_op, cl);
+ struct kiocb *req = op->req;
+ struct cache_set *c = req->ki_filp->f_inode->i_sb->s_fs_info;
+
+ req->ki_complete(req, bch_journal_error(&c->journal), 0);
+ kfree(op);
+}
+
+int bch_aio_fsync(struct kiocb *req, int datasync)
+{
+ struct file *file = req->ki_filp;
+ struct inode *inode = file->f_inode;
+ struct bch_inode_info *ei = to_bch_ei(inode);
+ struct cache_set *c = inode->i_sb->s_fs_info;
+ struct bch_aio_fsync_op *op;
+ int ret;
+
+ ret = filemap_write_and_wait_range(inode->i_mapping, 0, LLONG_MAX);
+ if (ret)
+ return ret;
+
+ mutex_lock(&inode->i_mutex);
+ if (!(inode->i_state & I_DIRTY))
+ goto out;
+ if (datasync && !(inode->i_state & I_DIRTY_DATASYNC))
+ goto out;
+
+ ret = sync_inode_metadata(inode, 1);
+out:
+ mutex_unlock(&inode->i_mutex);
+
+ op = kmalloc(sizeof(*op), GFP_NOIO);
+ if (!op)
+ return bch_fsync(file, 0, LLONG_MAX, datasync);
+
+ closure_init(&op->cl, NULL);
+ op->req = req;
+
+ bch_journal_flush_seq_async(&c->journal, ei->journal_seq, &op->cl);
+ closure_return_with_destructor_noreturn(&op->cl, bch_aio_fsync_done);
+
+ return -EIOCBQUEUED;
+}
+
static int __bch_truncate_page(struct address_space *mapping,
pgoff_t index, loff_t start, loff_t end)
{
diff --git a/drivers/md/bcache/fs-io.h b/drivers/md/bcache/fs-io.h
index d598bc8431be..3cf76b2f9d8f 100644
--- a/drivers/md/bcache/fs-io.h
+++ b/drivers/md/bcache/fs-io.h
@@ -23,6 +23,7 @@ ssize_t bch_direct_IO(struct kiocb *, struct iov_iter *);
ssize_t bch_write_iter(struct kiocb *, struct iov_iter *);
int bch_fsync(struct file *, loff_t, loff_t, int);
+int bch_aio_fsync(struct kiocb *, int);
int bch_truncate(struct inode *, struct iattr *);
long bch_fallocate_dispatch(struct file *, int, loff_t, loff_t);
diff --git a/drivers/md/bcache/fs.c b/drivers/md/bcache/fs.c
index 3ce40da5e84e..2493f5ff9884 100644
--- a/drivers/md/bcache/fs.c
+++ b/drivers/md/bcache/fs.c
@@ -903,6 +903,7 @@ static const struct file_operations bch_file_operations = {
.mmap = bch_mmap,
.open = generic_file_open,
.fsync = bch_fsync,
+ .aio_fsync = bch_aio_fsync,
.splice_read = generic_file_splice_read,
.splice_write = iter_file_splice_write,
.fallocate = bch_fallocate_dispatch,