Skip to contentSkip to conversation

exofs_file_fsync

PATCH In review Christoph Hellwig 2 participants 20 messages May 31, 2010 – Jun 1, 2010 VFS

lore
Share & tools
lore
#0 lore raw

Various odd things going on here:

- no checks for I_DIRTY and friends, so it will always write out data
- filemap_write_and_wait is superflous, as it's already done by the caller
- write_inode_now is overkill as it also writes out data, better use sync_inode in a similar way to generic_file_fsync

#1 lore raw
Quoted 7 lines · Christoph Hellwig

Various odd things going on here:

- no checks for I_DIRTY and friends, so it will always write out data
- filemap_write_and_wait is superflous, as it's already done by the caller
- write_inode_now is overkill as it also writes out data, better use sync_inode in a similar way to generic_file_fsync

I'll look into it, but I think what I did here was to effectively "data sync" because I wanted a data sync on close and that was the only vector I already had that's called on close.

I want "data sync on close" because I'm kind of close-2-open network semantics, cross a network. And this is my local access checkpoint.

But sure I'll re think the all thing.

Thanks
Boaz

#2 lore raw
Quoted 9 lines · Boaz Harrosh
Quoted 7 lines · Christoph Hellwig

Various odd things going on here:

- no checks for I_DIRTY and friends, so it will always write out data
- filemap_write_and_wait is superflous, as it's already done by the caller
- write_inode_now is overkill as it also writes out data, better use sync_inode in a similar way to generic_file_fsync

Quoted 3 lines

I'll look into it, but I think what I did here was to effectively "data sync" because I wanted a data sync on close and that was the only vector I already had that's called on close.

fsync won't get called at close time. ->release is called on last close and ->flush on every close.

#3 lore raw
Quoted 10 lines · Christoph Hellwig
Quoted 9 lines · Boaz Harrosh
Quoted 7 lines · Christoph Hellwig

Various odd things going on here:

- no checks for I_DIRTY and friends, so it will always write out data
- filemap_write_and_wait is superflous, as it's already done by the caller
- write_inode_now is overkill as it also writes out data, better use sync_inode in a similar way to generic_file_fsync

Quoted 7 lines
Quoted 3 lines

I'll look into it, but I think what I did here was to effectively "data sync" because I wanted a data sync on close and that was the only vector I already had that's called on close.

fsync won't get called at close time. ->release is called on last close and ->flush on every close.

OK, I was just looking at that. thanks you saved me some digging. should I just open-code the generic_file_fsync minus the blocks thing then?

I'm busy with the truncate stuff, but I'll do this next. Do you need this ASAP?

Thanks
Boaz

#4 lore raw
Quoted 3 lines · Boaz Harrosh

OK, I was just looking at that. thanks you saved me some digging. should I just open-code the generic_file_fsync minus the blocks thing then?

sync_mapping_buffers is a no-op for you so you can keep it. The other difference is that you sync out the superblock at the end of your fsync implementation. That is rather unusual, but I don't know enough about exofs if you really need to update data in the superblock to commit file data to disk.

Quoted 2 lines

I'm busy with the truncate stuff, but I'll do this next. Do you need this ASAP?

I just noticed it while walking through the fsync implementations.

#5 lore raw
Quoted 11 lines · Christoph Hellwig
Quoted 3 lines · Boaz Harrosh

OK, I was just looking at that. thanks you saved me some digging. should I just open-code the generic_file_fsync minus the blocks thing then?

sync_mapping_buffers is a no-op for you so you can keep it. The other difference is that you sync out the superblock at the end of your fsync implementation. That is rather unusual, but I don't know enough about exofs if you really need to update data in the superblock to commit file data to disk.

Quoted 5 lines
Quoted 2 lines

I'm busy with the truncate stuff, but I'll do this next. Do you need this ASAP?

I just noticed it while walking through the fsync implementations.

OK Chritoff I would need your help Please.

It looks like what I need exactly is:
write_inode_now(inode, sync)

But write_inode_now() has one extra hunk over generic_file_fsync:

	if (sync)
		inode_sync_wait(inode);

Do you think I can get in trouble calling it from ->fsync

I don't like generic_file_fsync because it does not write my data since I don't have buffer_heads.

OK, I'm totally lost what does ->fsync need to do? only write the inode or the pages as well?

Boaz
---
git diff --stat -p -M fs/exofs/file.c

 fs/exofs/file.c |    8 ++------
 1 files changed, 2 insertions(+), 6 deletions(-)
fs/exofs/file.c +2 -6
index f9bfe2b..9b3555e 100644
@@ -47,18 +47,14 @@ static int exofs_file_fsync(struct file *filp, int datasync)
 	struct inode *inode = mapping->host;
 	struct super_block *sb;
 
-	ret = filemap_write_and_wait(mapping);
-	if (ret)
-		return ret;
-
 	/* sync the inode attributes */
-	ret = write_inode_now(inode, 1);
+	ret = write_inode_now(inode, datasync);
 
 	/* This is a good place to write the sb */
 	/* TODO: Sechedule an sb-sync on create */
 	sb = inode->i_sb;
 	if (sb->s_dirt)
-		exofs_sync_fs(sb, 1);
+		exofs_sync_fs(sb, datasync);
 
 	return ret;
 }
#6 lore raw
Quoted 46 lines · Boaz Harrosh
Quoted 11 lines · Christoph Hellwig
Quoted 3 lines · Boaz Harrosh

OK, I was just looking at that. thanks you saved me some digging. should I just open-code the generic_file_fsync minus the blocks thing then?

sync_mapping_buffers is a no-op for you so you can keep it. The other difference is that you sync out the superblock at the end of your fsync implementation. That is rather unusual, but I don't know enough about exofs if you really need to update data in the superblock to commit file data to disk.

Quoted 5 lines
Quoted 2 lines

I'm busy with the truncate stuff, but I'll do this next. Do you need this ASAP?

I just noticed it while walking through the fsync implementations.

OK Chritoff I would need your help Please.

It looks like what I need exactly is:
write_inode_now(inode, sync)

But write_inode_now() has one extra hunk over generic_file_fsync:

	if (sync)
		inode_sync_wait(inode);

Do you think I can get in trouble calling it from ->fsync

I don't like generic_file_fsync because it does not write my data since I don't have buffer_heads.

OK, I'm totally lost what does ->fsync need to do? only write the inode or the pages as well?

Boaz
---
git diff --stat -p -M fs/exofs/file.c

 fs/exofs/file.c |    8 ++------
 1 files changed, 2 insertions(+), 6 deletions(-)
fs/exofs/file.c +0 -0
index f9bfe2b..9b3555e 100644

fs/exofs/file.c static int exofs_file_fsync(struct file *filp, int datasync) · line 53

Quoted 7 lines
fs/exofs/file.c +0 -4
@@ -47,18 +47,14 @@ static int exofs_file_fsync(struct file *filp, int datasync)
 	struct inode *inode = mapping->host;
 	struct super_block *sb;
 
-	ret = filemap_write_and_wait(mapping);
-	if (ret)
-		return ret;
-

You think I also need a:

	if (!(inode->i_state & I_DIRTY))
		return ret;
	if (datasync && !(inode->i_state & I_DIRTY_DATASYNC))
		return ret;

before the write_inode_now call ?

Quoted 13 lines
fs/exofs/file.c +2 -2
 	/* sync the inode attributes */
-	ret = write_inode_now(inode, 1);
+	ret = write_inode_now(inode, datasync);
 
 	/* This is a good place to write the sb */
 	/* TODO: Sechedule an sb-sync on create */
 	sb = inode->i_sb;
 	if (sb->s_dirt)
-		exofs_sync_fs(sb, 1);
+		exofs_sync_fs(sb, datasync);
 
 	return ret;
 }
#7 lore raw
Quoted 6 lines · Boaz Harrosh

You think I also need a:

	if (!(inode->i_state & I_DIRTY))
		return ret;
	if (datasync && !(inode->i_state & I_DIRTY_DATASYNC))
		return ret;

before the write_inode_now call ?

You don't strictly need it, but without it you will perform a lot of work for no gain if the inode is not actually dirty.

#8 lore raw
In reply to Boaz Harrosh
Quoted 8 lines · Boaz Harrosh

OK Chritoff I would need your help Please.

It looks like what I need exactly is:
write_inode_now(inode, sync)

But write_inode_now() has one extra hunk over generic_file_fsync:

	if (sync)
		inode_sync_wait(inode);

It waits for I_SYNC beeing cleared, which is entirely superflous for ->fsync purposes. In fact I don't have the slightest idea what it is useful for, given that we already clear I_SYNC inside writeback_single_inode ourselves. So the only thing it causes is to wait for another code racing to step into this code just after us.

Quoted 4 lines

Do you think I can get in trouble calling it from ->fsync

I don't like generic_file_fsync because it does not write my data since I don't have buffer_heads.

Then copy it.

Quoted 2 lines

OK, I'm totally lost what does ->fsync need to do? only write the inode or the pages as well?

The pages are written by vfs_fsync_range. You need to make sure that the inode back, or if the datasync flag is set only changes to the inode require to find that data are written back. That's basically a messy wording for you can skip dirtiness of timestamp updates if the datasync flag is set.

Note that your patch below is very wrong for this, as it does a lot of asynchronous activity if the datasync flag is not set.

#9 lore raw
Quoted 10 lines · Christoph Hellwig

The pages are written by vfs_fsync_range. You need to make sure that the inode back, or if the datasync flag is set only changes to the inode require to find that data are written back. That's basically a messy wording for you can skip dirtiness of timestamp updates if the datasync flag is set.

Note that your patch below is very wrong for this, as it does a lot of asynchronous activity if the datasync flag is not set.

Thank you Christoph. Me smack me on the head. Got two unrelated flags totally confused.

I'll be posting a fix. For the best of my knowledge all I need is a synchronous call to sync_inode() which will in turn call exofs_write_inode. The later takes care of all metadata an exofs inode has. (No allocation bitmaps, no data nodes lists, etc...)

In a next patch I'll also fix the super-block shit. Testing ...

Boaz

#10 lore raw

PATCH 1/1 exofs: exofs_file_fsync correctness

In reply to Christoph Hellwig

As per Christoph advise: no need to call filemap_write_and_wait(). In exofs all metadata is at the inode so just writing the pages and inode is all is needed. fsync implies this must be done synchronously.

FIXME: remove the sb_sync and fix that sb_update better.

---
 fs/exofs/file.c |   21 ++++++++++++---------
 1 files changed, 12 insertions(+), 9 deletions(-)
fs/exofs/file.c +12 -9
index f9bfe2b..54bb17d 100644
@@ -30,9 +30,6 @@
  * along with exofs; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  */
-
-#include <linux/buffer_head.h>
-
 #include "exofs.h"
 
 static int exofs_release_file(struct inode *inode, struct file *filp)
@@ -40,19 +37,25 @@ static int exofs_release_file(struct inode *inode, struct file *filp)
 	return 0;
 }
 
+/* exofs_file_fsync - flush the inode to disk
+ *
+ *   @datasync is not used. All metadata is written in one place regardless.
+ *   the writeout is synchronous
+ */
 static int exofs_file_fsync(struct file *filp, int datasync)
 {
 	int ret;
 	struct address_space *mapping = filp->f_mapping;
 	struct inode *inode = mapping->host;
 	struct super_block *sb;
+	struct writeback_control wbc = {
+		.sync_mode = WB_SYNC_ALL,
+		.nr_to_write = LONG_MAX,
+		.range_start = 0,
+		.range_end = LLONG_MAX,
+	};
 
-	ret = filemap_write_and_wait(mapping);
-	if (ret)
-		return ret;
-
-	/* sync the inode attributes */
-	ret = write_inode_now(inode, 1);
+	ret = sync_inode(inode, &wbc);
 
 	/* This is a good place to write the sb */
 	/* TODO: Sechedule an sb-sync on create */
Signature · 1 line
1.6.6.1
#11 lore raw

Re: [osd-dev] [PATCH] exofs: exofs_file_fsync correctness

Quoted 37 lines · Boaz Harrosh

As per Christoph advise: no need to call filemap_write_and_wait(). In exofs all metadata is at the inode so just writing the pages and inode is all is needed. fsync implies this must be done synchronously.

FIXME: remove the sb_sync and fix that sb_update better.

---
 fs/exofs/file.c |   21 ++++++++++++---------
 1 files changed, 12 insertions(+), 9 deletions(-)
fs/exofs/file.c +5 -3
index f9bfe2b..54bb17d 100644
@@ -30,9 +30,6 @@
  * along with exofs; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  */
-
-#include <linux/buffer_head.h>
-
 #include "exofs.h"
 
 static int exofs_release_file(struct inode *inode, struct file *filp)
@@ -40,19 +37,25 @@ static int exofs_release_file(struct inode *inode, struct file *filp)
 	return 0;
 }
 
+/* exofs_file_fsync - flush the inode to disk
+ *
+ *   @datasync is not used. All metadata is written in one place regardless.
+ *   the writeout is synchronous
+ */
 static int exofs_file_fsync(struct file *filp, int datasync)

fs/exofs/file.c static int exofs_release_file(struct inode *inode, struct file *filp) · line 55

Quoted 10 lines
fs/exofs/file.c +5 -0
 {
 	int ret;
 	struct address_space *mapping = filp->f_mapping;
 	struct inode *inode = mapping->host;
 	struct super_block *sb;
+	struct writeback_control wbc = {
+		.sync_mode = WB_SYNC_ALL,
+		.nr_to_write = LONG_MAX,
+		.range_start = 0,
+		.range_end = LLONG_MAX,

Christoph what do you say should I do

+ .range_end = i_size_read(inode);
here to cap the sync up to current size?

Boaz

Quoted 12 lines
fs/exofs/file.c +2 -6
+	};
 
-	ret = filemap_write_and_wait(mapping);
-	if (ret)
-		return ret;
-
-	/* sync the inode attributes */
-	ret = write_inode_now(inode, 1);
+	ret = sync_inode(inode, &wbc);
 
 	/* This is a good place to write the sb */
 	/* TODO: Sechedule an sb-sync on create */
#12 lore raw

Re: [PATCH] exofs: exofs_file_fsync correctness

In reply to Boaz Harrosh
Quoted 5 lines · Boaz Harrosh

+/* exofs_file_fsync - flush the inode to disk
+ *
+ * @datasync is not used. All metadata is written in one place regardless.
+ * the writeout is synchronous
+ */

You still want to check it. It's really only need for checking the various dirty flags in the inode, which you're still missing.

fs/exofs/file.c static int exofs_release_file(struct inode *inode, struct file *filp) · line 53

Quoted 3 lines
fs/exofs/file.c +3 -0
+	struct writeback_control wbc = {
+		.sync_mode = WB_SYNC_ALL,
+		.nr_to_write = LONG_MAX,

By setting a nr_to_write you still write out data (at least in theory).

I'd recommend just copying the code from generic_file_fsync..

#13 lore raw

Re: [PATCH] exofs: exofs_file_fsync correctness

Quoted 10 lines · Christoph Hellwig
Quoted 5 lines · Boaz Harrosh

+/* exofs_file_fsync - flush the inode to disk
+ *
+ * @datasync is not used. All metadata is written in one place regardless.
+ * the writeout is synchronous
+ */

You still want to check it. It's really only need for checking the various dirty flags in the inode, which you're still missing.

will do

Quoted 6 lines

fs/exofs/file.c static int exofs_release_file(struct inode *inode, struct file *filp) · line 53

Quoted 3 lines
fs/exofs/file.c +3 -0
+	struct writeback_control wbc = {
+		.sync_mode = WB_SYNC_ALL,
+		.nr_to_write = LONG_MAX,

By setting a nr_to_write you still write out data (at least in theory).

So when do I also sync the data? is that done for me at the VFS layer?

Quoted 2 lines

I'd recommend just copying the code from generic_file_fsync..

I was actually mimicking the code from nfs/write.c which has similar semantics as mine.

And if so then I'll need to not reuse the above in .flush

Boaz

#14 lore raw

Re: [PATCH] exofs: exofs_file_fsync correctness

Quoted 8 lines · Boaz Harrosh
Quoted 6 lines

fs/exofs/file.c static int exofs_release_file(struct inode *inode, struct file *filp) · line 53

Quoted 3 lines
fs/exofs/file.c +3 -0
+	struct writeback_control wbc = {
+		.sync_mode = WB_SYNC_ALL,
+		.nr_to_write = LONG_MAX,

By setting a nr_to_write you still write out data (at least in theory).

So when do I also sync the data? is that done for me at the VFS layer?

You never have to. vfs_fsync_range does the data writeout for you.

Quoted 5 lines
Quoted 2 lines

I'd recommend just copying the code from generic_file_fsync..

I was actually mimicking the code from nfs/write.c which has similar semantics as mine.

nfs code has no good reason to do that, at least when called from ->fsync.

Quoted 1 line

And if so then I'll need to not reuse the above in .flush

I would recommend keeping the ->flush code separate.

#15 lore raw

Re: [PATCH] exofs: exofs_file_fsync correctness

Quoted 18 lines · Christoph Hellwig
Quoted 8 lines · Boaz Harrosh
Quoted 6 lines

fs/exofs/file.c static int exofs_release_file(struct inode *inode, struct file *filp) · line 53

Quoted 3 lines
fs/exofs/file.c +3 -0
+	struct writeback_control wbc = {
+		.sync_mode = WB_SYNC_ALL,
+		.nr_to_write = LONG_MAX,

By setting a nr_to_write you still write out data (at least in theory).

So when do I also sync the data? is that done for me at the VFS layer?

You never have to. vfs_fsync_range does the data writeout for you.

Quoted 5 lines
Quoted 2 lines

I'd recommend just copying the code from generic_file_fsync..

I was actually mimicking the code from nfs/write.c which has similar semantics as mine.

Quoted 6 lines

nfs code has no good reason to do that, at least when called from ->fsync.

Quoted 1 line

And if so then I'll need to not reuse the above in .flush

I would recommend keeping the ->flush code separate.

OK, ... I think I got it this time. (I hope)

And you are totally right. The ->flush code is called without any locks and the ->fsync is called with i_mutex held. So the previous code was totally racy for ->flush.

Boaz

#16 lore raw

PATCH 1/1 exofs: exofs_file_fsync and exofs_file_flush correctness

In reply to Boaz Harrosh

As per Christoph advise: no need to call filemap_write_and_wait(). In exofs all metadata is at the inode so just writing the inode is all is needed. fsync implies this must be done synchronously.

But now exofs_file_fsync can not be used by exofs_file_flush. vfs_fsync_range should do that job.

FIXME: remove the sb_sync and fix that sb_update better.

---
 fs/exofs/file.c |   29 +++++++++++++++++------------
 1 files changed, 17 insertions(+), 12 deletions(-)
fs/exofs/file.c +17 -12
index f9bfe2b..e0eb219 100644
@@ -30,9 +30,6 @@
  * along with exofs; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  */
-
-#include <linux/buffer_head.h>
-
 #include "exofs.h"
 
 static int exofs_release_file(struct inode *inode, struct file *filp)
@@ -40,19 +37,27 @@ static int exofs_release_file(struct inode *inode, struct file *filp)
 	return 0;
 }
 
+/* exofs_file_fsync - flush the inode to disk
+ *
+ *   @datasync is not used. All metadata is written in one place regardless.
+ *   the writeout is synchronous
+ */
 static int exofs_file_fsync(struct file *filp, int datasync)
 {
 	int ret;
-	struct address_space *mapping = filp->f_mapping;
-	struct inode *inode = mapping->host;
+	struct writeback_control wbc = {
+		.sync_mode = WB_SYNC_ALL,
+		.nr_to_write = 0, /* metadata-only; caller takes care of data */
+	};
+	struct inode *inode = filp->f_mapping->host;
 	struct super_block *sb;
 
-	ret = filemap_write_and_wait(mapping);
-	if (ret)
-		return ret;
+	if (!(inode->i_state & I_DIRTY))
+		return 0;
+	if (datasync && !(inode->i_state & I_DIRTY_DATASYNC))
+		return 0;
 
-	/* sync the inode attributes */
-	ret = write_inode_now(inode, 1);
+	ret = sync_inode(inode, &wbc);
 
 	/* This is a good place to write the sb */
 	/* TODO: Sechedule an sb-sync on create */
@@ -65,9 +70,9 @@ static int exofs_file_fsync(struct file *filp, int datasync)
 
 static int exofs_flush(struct file *file, fl_owner_t id)
 {
-	exofs_file_fsync(file, 1);
+	int ret = vfs_fsync_range(file, 0, LLONG_MAX, 0);
 	/* TODO: Flush the OSD target */
-	return 0;
+	return ret;
 }
 
 const struct file_operations exofs_file_operations = {
Signature · 1 line
1.6.6.1
#17 lore raw

Re: [PATCH ver2] exofs: exofs_file_fsync and exofs_file_flush correctness

Quoted 5 lines · Boaz Harrosh

+/* exofs_file_fsync - flush the inode to disk
+ *
+ * @datasync is not used. All metadata is written in one place regardless.
+ * the writeout is synchronous
+ */

It actually is used now :)

fs/exofs/file.c static int exofs_file_fsync(struct file *filp, int datasync) · line 75

Quoted 7 lines

static int exofs_flush(struct file *file, fl_owner_t id) {

fs/exofs/file.c +2 -2
-	exofs_file_fsync(file, 1);
+	int ret = vfs_fsync_range(file, 0, LLONG_MAX, 0);
 	/* TODO: Flush the OSD target */
-	return 0;
+	return ret;

why not just:

	return vfs_fsync(file, 0);
#18 lore raw

Re: [PATCH ver2] exofs: exofs_file_fsync and exofs_file_flush correctness

Quoted 9 lines · Christoph Hellwig
Quoted 5 lines · Boaz Harrosh

+/* exofs_file_fsync - flush the inode to disk
+ *
+ * @datasync is not used. All metadata is written in one place regardless.
+ * the writeout is synchronous
+ */

It actually is used now :)

Right ;-) fixing

Quoted 10 lines

fs/exofs/file.c static int exofs_file_fsync(struct file *filp, int datasync) · line 75

Quoted 7 lines

static int exofs_flush(struct file *file, fl_owner_t id) {

fs/exofs/file.c +2 -2
-	exofs_file_fsync(file, 1);
+	int ret = vfs_fsync_range(file, 0, LLONG_MAX, 0);
 	/* TODO: Flush the OSD target */
-	return 0;
+	return ret;

why not just:

Quoted 2 lines
	return vfs_fsync(file, 0);

Why, because I don't look passed my nose that's why.

Thank you Christoph. This is an area I was feeling bad about from the get go. You can't imagine how happy I'm to have you help me on this. (Things You Always Wanted to Know But Were Afraid to Ask)

Will post
Boaz

#19 lore raw

PATCH 1/1 exofs: exofs_file_fsync and exofs_file_flush correctness

In reply to Boaz Harrosh

As per Christoph advise: no need to call filemap_write_and_wait(). In exofs all metadata is at the inode so just writing the inode is all is needed. ->fsync implies this must be done synchronously.

But now exofs_file_fsync can not be used by exofs_file_flush. vfs_fsync() should do that job correctly.

FIXME: remove the sb_sync and fix that sb_update better.

---
 fs/exofs/file.c |   29 +++++++++++++++++------------
 1 files changed, 17 insertions(+), 12 deletions(-)
fs/exofs/file.c +17 -12
index f9bfe2b..68cb23e 100644
@@ -30,9 +30,6 @@
  * along with exofs; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  */
-
-#include <linux/buffer_head.h>
-
 #include "exofs.h"
 
 static int exofs_release_file(struct inode *inode, struct file *filp)
@@ -40,19 +37,27 @@ static int exofs_release_file(struct inode *inode, struct file *filp)
 	return 0;
 }
 
+/* exofs_file_fsync - flush the inode to disk
+ *
+ *   Note, in exofs all metadata is written as part of inode, regardless.
+ *   The writeout is synchronous
+ */
 static int exofs_file_fsync(struct file *filp, int datasync)
 {
 	int ret;
-	struct address_space *mapping = filp->f_mapping;
-	struct inode *inode = mapping->host;
+	struct inode *inode = filp->f_mapping->host;
+	struct writeback_control wbc = {
+		.sync_mode = WB_SYNC_ALL,
+		.nr_to_write = 0, /* metadata-only; caller takes care of data */
+	};
 	struct super_block *sb;
 
-	ret = filemap_write_and_wait(mapping);
-	if (ret)
-		return ret;
+	if (!(inode->i_state & I_DIRTY))
+		return 0;
+	if (datasync && !(inode->i_state & I_DIRTY_DATASYNC))
+		return 0;
 
-	/* sync the inode attributes */
-	ret = write_inode_now(inode, 1);
+	ret = sync_inode(inode, &wbc);
 
 	/* This is a good place to write the sb */
 	/* TODO: Sechedule an sb-sync on create */
@@ -65,9 +70,9 @@ static int exofs_file_fsync(struct file *filp, int datasync)
 
 static int exofs_flush(struct file *file, fl_owner_t id)
 {
-	exofs_file_fsync(file, 1);
+	int ret = vfs_fsync(file, 0);
 	/* TODO: Flush the OSD target */
-	return 0;
+	return ret;
 }
 
 const struct file_operations exofs_file_operations = {
Signature · 1 line
1.6.6.1