diff options
Diffstat (limited to 'fs/xfs/linux-2.6/xfs_file.c')
-rw-r--r-- | fs/xfs/linux-2.6/xfs_file.c | 50 |
1 files changed, 31 insertions, 19 deletions
diff --git a/fs/xfs/linux-2.6/xfs_file.c b/fs/xfs/linux-2.6/xfs_file.c index f4213ba1ff85..7f782af286bf 100644 --- a/fs/xfs/linux-2.6/xfs_file.c +++ b/fs/xfs/linux-2.6/xfs_file.c | |||
@@ -131,19 +131,34 @@ xfs_file_fsync( | |||
131 | { | 131 | { |
132 | struct inode *inode = file->f_mapping->host; | 132 | struct inode *inode = file->f_mapping->host; |
133 | struct xfs_inode *ip = XFS_I(inode); | 133 | struct xfs_inode *ip = XFS_I(inode); |
134 | struct xfs_mount *mp = ip->i_mount; | ||
134 | struct xfs_trans *tp; | 135 | struct xfs_trans *tp; |
135 | int error = 0; | 136 | int error = 0; |
136 | int log_flushed = 0; | 137 | int log_flushed = 0; |
137 | 138 | ||
138 | trace_xfs_file_fsync(ip); | 139 | trace_xfs_file_fsync(ip); |
139 | 140 | ||
140 | if (XFS_FORCED_SHUTDOWN(ip->i_mount)) | 141 | if (XFS_FORCED_SHUTDOWN(mp)) |
141 | return -XFS_ERROR(EIO); | 142 | return -XFS_ERROR(EIO); |
142 | 143 | ||
143 | xfs_iflags_clear(ip, XFS_ITRUNCATED); | 144 | xfs_iflags_clear(ip, XFS_ITRUNCATED); |
144 | 145 | ||
145 | xfs_ioend_wait(ip); | 146 | xfs_ioend_wait(ip); |
146 | 147 | ||
148 | if (mp->m_flags & XFS_MOUNT_BARRIER) { | ||
149 | /* | ||
150 | * If we have an RT and/or log subvolume we need to make sure | ||
151 | * to flush the write cache the device used for file data | ||
152 | * first. This is to ensure newly written file data make | ||
153 | * it to disk before logging the new inode size in case of | ||
154 | * an extending write. | ||
155 | */ | ||
156 | if (XFS_IS_REALTIME_INODE(ip)) | ||
157 | xfs_blkdev_issue_flush(mp->m_rtdev_targp); | ||
158 | else if (mp->m_logdev_targp != mp->m_ddev_targp) | ||
159 | xfs_blkdev_issue_flush(mp->m_ddev_targp); | ||
160 | } | ||
161 | |||
147 | /* | 162 | /* |
148 | * We always need to make sure that the required inode state is safe on | 163 | * We always need to make sure that the required inode state is safe on |
149 | * disk. The inode might be clean but we still might need to force the | 164 | * disk. The inode might be clean but we still might need to force the |
@@ -175,9 +190,9 @@ xfs_file_fsync( | |||
175 | * updates. The sync transaction will also force the log. | 190 | * updates. The sync transaction will also force the log. |
176 | */ | 191 | */ |
177 | xfs_iunlock(ip, XFS_ILOCK_SHARED); | 192 | xfs_iunlock(ip, XFS_ILOCK_SHARED); |
178 | tp = xfs_trans_alloc(ip->i_mount, XFS_TRANS_FSYNC_TS); | 193 | tp = xfs_trans_alloc(mp, XFS_TRANS_FSYNC_TS); |
179 | error = xfs_trans_reserve(tp, 0, | 194 | error = xfs_trans_reserve(tp, 0, |
180 | XFS_FSYNC_TS_LOG_RES(ip->i_mount), 0, 0, 0); | 195 | XFS_FSYNC_TS_LOG_RES(mp), 0, 0, 0); |
181 | if (error) { | 196 | if (error) { |
182 | xfs_trans_cancel(tp, 0); | 197 | xfs_trans_cancel(tp, 0); |
183 | return -error; | 198 | return -error; |
@@ -209,28 +224,25 @@ xfs_file_fsync( | |||
209 | * force the log. | 224 | * force the log. |
210 | */ | 225 | */ |
211 | if (xfs_ipincount(ip)) { | 226 | if (xfs_ipincount(ip)) { |
212 | error = _xfs_log_force_lsn(ip->i_mount, | 227 | error = _xfs_log_force_lsn(mp, |
213 | ip->i_itemp->ili_last_lsn, | 228 | ip->i_itemp->ili_last_lsn, |
214 | XFS_LOG_SYNC, &log_flushed); | 229 | XFS_LOG_SYNC, &log_flushed); |
215 | } | 230 | } |
216 | xfs_iunlock(ip, XFS_ILOCK_SHARED); | 231 | xfs_iunlock(ip, XFS_ILOCK_SHARED); |
217 | } | 232 | } |
218 | 233 | ||
219 | if (ip->i_mount->m_flags & XFS_MOUNT_BARRIER) { | 234 | /* |
220 | /* | 235 | * If we only have a single device, and the log force about was |
221 | * If the log write didn't issue an ordered tag we need | 236 | * a no-op we might have to flush the data device cache here. |
222 | * to flush the disk cache for the data device now. | 237 | * This can only happen for fdatasync/O_DSYNC if we were overwriting |
223 | */ | 238 | * an already allocated file and thus do not have any metadata to |
224 | if (!log_flushed) | 239 | * commit. |
225 | xfs_blkdev_issue_flush(ip->i_mount->m_ddev_targp); | 240 | */ |
226 | 241 | if ((mp->m_flags & XFS_MOUNT_BARRIER) && | |
227 | /* | 242 | mp->m_logdev_targp == mp->m_ddev_targp && |
228 | * If this inode is on the RT dev we need to flush that | 243 | !XFS_IS_REALTIME_INODE(ip) && |
229 | * cache as well. | 244 | !log_flushed) |
230 | */ | 245 | xfs_blkdev_issue_flush(mp->m_ddev_targp); |
231 | if (XFS_IS_REALTIME_INODE(ip)) | ||
232 | xfs_blkdev_issue_flush(ip->i_mount->m_rtdev_targp); | ||
233 | } | ||
234 | 246 | ||
235 | return -error; | 247 | return -error; |
236 | } | 248 | } |