summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Brandenburg <martin@omnibond.com>2018-03-26 21:58:11 +0300
committerMike Marshall <hubcap@omnibond.com>2019-05-03 21:32:38 +0300
commit90fc07065a3505e5a874c5854fd6176beb545e08 (patch)
tree00cede9b9344af70e09ba43235598cced47027dd
parent8a88bbce6f83430a737a97bb72d0912a6a103945 (diff)
downloadlinux-90fc07065a3505e5a874c5854fd6176beb545e08.tar.xz
orangefs: avoid fsync service operation on flush
Without this, an fsync call is sent to the server even if no data changed. This resulted in a rather severe (50%) performance regression under certain metadata-heavy workloads. In the past, everything was direct IO. Nothing happend on a close call. An explicit fsync call would send an fsync request to the server which in turn fsynced the underlying file. Now there are cached writes. Then fsync began writing out dirty pages in addition to making an fsync request to the server, and close began calling fsync. With this commit, close only writes out dirty pages, and does not make the fsync request. Signed-off-by: Martin Brandenburg <martin@omnibond.com> Signed-off-by: Mike Marshall <hubcap@omnibond.com>
-rw-r--r--fs/orangefs/file.c24
1 files changed, 23 insertions, 1 deletions
diff --git a/fs/orangefs/file.c b/fs/orangefs/file.c
index f4e20d5ed207..26d8ff410b0a 100644
--- a/fs/orangefs/file.c
+++ b/fs/orangefs/file.c
@@ -487,7 +487,29 @@ static int orangefs_lock(struct file *filp, int cmd, struct file_lock *fl)
static int orangefs_flush(struct file *file, fl_owner_t id)
{
- return vfs_fsync(file, 0);
+ /*
+ * This is vfs_fsync_range(file, 0, LLONG_MAX, 0) without the
+ * service_operation in orangefs_fsync.
+ *
+ * Do not send fsync to OrangeFS server on a close. Do send fsync
+ * on an explicit fsync call. This duplicates historical OrangeFS
+ * behavior.
+ */
+ struct inode *inode = file->f_mapping->host;
+ int r;
+
+ if (inode->i_state & I_DIRTY_TIME) {
+ spin_lock(&inode->i_lock);
+ inode->i_state &= ~I_DIRTY_TIME;
+ spin_unlock(&inode->i_lock);
+ mark_inode_dirty_sync(inode);
+ }
+
+ r = filemap_write_and_wait_range(file->f_mapping, 0, LLONG_MAX);
+ if (r > 0)
+ return 0;
+ else
+ return r;
}
/** ORANGEFS implementation of VFS file operations */