diff options
Diffstat (limited to 'fs/ext4/fsync.c')
-rw-r--r-- | fs/ext4/fsync.c | 47 |
1 files changed, 11 insertions, 36 deletions
diff --git a/fs/ext4/fsync.c b/fs/ext4/fsync.c index dcc881b30849..6019bd449576 100644 --- a/fs/ext4/fsync.c +++ b/fs/ext4/fsync.c | |||
@@ -73,32 +73,6 @@ static int ext4_sync_parent(struct inode *inode) | |||
73 | return ret; | 73 | return ret; |
74 | } | 74 | } |
75 | 75 | ||
76 | /** | ||
77 | * __sync_file - generic_file_fsync without the locking and filemap_write | ||
78 | * @inode: inode to sync | ||
79 | * @datasync: only sync essential metadata if true | ||
80 | * | ||
81 | * This is just generic_file_fsync without the locking. This is needed for | ||
82 | * nojournal mode to make sure this inodes data/metadata makes it to disk | ||
83 | * properly. The i_mutex should be held already. | ||
84 | */ | ||
85 | static int __sync_inode(struct inode *inode, int datasync) | ||
86 | { | ||
87 | int err; | ||
88 | int ret; | ||
89 | |||
90 | ret = sync_mapping_buffers(inode->i_mapping); | ||
91 | if (!(inode->i_state & I_DIRTY)) | ||
92 | return ret; | ||
93 | if (datasync && !(inode->i_state & I_DIRTY_DATASYNC)) | ||
94 | return ret; | ||
95 | |||
96 | err = sync_inode_metadata(inode, 1); | ||
97 | if (ret == 0) | ||
98 | ret = err; | ||
99 | return ret; | ||
100 | } | ||
101 | |||
102 | /* | 76 | /* |
103 | * akpm: A new design for ext4_sync_file(). | 77 | * akpm: A new design for ext4_sync_file(). |
104 | * | 78 | * |
@@ -116,7 +90,7 @@ int ext4_sync_file(struct file *file, loff_t start, loff_t end, int datasync) | |||
116 | struct inode *inode = file->f_mapping->host; | 90 | struct inode *inode = file->f_mapping->host; |
117 | struct ext4_inode_info *ei = EXT4_I(inode); | 91 | struct ext4_inode_info *ei = EXT4_I(inode); |
118 | journal_t *journal = EXT4_SB(inode->i_sb)->s_journal; | 92 | journal_t *journal = EXT4_SB(inode->i_sb)->s_journal; |
119 | int ret, err; | 93 | int ret = 0, err; |
120 | tid_t commit_tid; | 94 | tid_t commit_tid; |
121 | bool needs_barrier = false; | 95 | bool needs_barrier = false; |
122 | 96 | ||
@@ -124,21 +98,21 @@ int ext4_sync_file(struct file *file, loff_t start, loff_t end, int datasync) | |||
124 | 98 | ||
125 | trace_ext4_sync_file_enter(file, datasync); | 99 | trace_ext4_sync_file_enter(file, datasync); |
126 | 100 | ||
127 | ret = filemap_write_and_wait_range(inode->i_mapping, start, end); | ||
128 | if (ret) | ||
129 | return ret; | ||
130 | mutex_lock(&inode->i_mutex); | ||
131 | |||
132 | if (inode->i_sb->s_flags & MS_RDONLY) | 101 | if (inode->i_sb->s_flags & MS_RDONLY) |
133 | goto out; | 102 | goto out_trace; |
134 | 103 | ||
135 | if (!journal) { | 104 | if (!journal) { |
136 | ret = __sync_inode(inode, datasync); | 105 | ret = generic_file_fsync(file, start, end, datasync); |
137 | if (!ret && !hlist_empty(&inode->i_dentry)) | 106 | if (!ret && !hlist_empty(&inode->i_dentry)) |
138 | ret = ext4_sync_parent(inode); | 107 | ret = ext4_sync_parent(inode); |
139 | goto out; | 108 | goto out_trace; |
140 | } | 109 | } |
141 | 110 | ||
111 | ret = filemap_write_and_wait_range(inode->i_mapping, start, end); | ||
112 | if (ret) | ||
113 | return ret; | ||
114 | mutex_lock(&inode->i_mutex); | ||
115 | |||
142 | /* | 116 | /* |
143 | * data=writeback,ordered: | 117 | * data=writeback,ordered: |
144 | * The caller's filemap_fdatawrite()/wait will sync the data. | 118 | * The caller's filemap_fdatawrite()/wait will sync the data. |
@@ -168,8 +142,9 @@ int ext4_sync_file(struct file *file, loff_t start, loff_t end, int datasync) | |||
168 | if (!ret) | 142 | if (!ret) |
169 | ret = err; | 143 | ret = err; |
170 | } | 144 | } |
171 | out: | 145 | out: |
172 | mutex_unlock(&inode->i_mutex); | 146 | mutex_unlock(&inode->i_mutex); |
147 | out_trace: | ||
173 | trace_ext4_sync_file_exit(inode, ret); | 148 | trace_ext4_sync_file_exit(inode, ret); |
174 | return ret; | 149 | return ret; |
175 | } | 150 | } |