diff options
-rw-r--r-- | fs/xfs/linux-2.6/xfs_buf.c | 5 | ||||
-rw-r--r-- | fs/xfs/linux-2.6/xfs_buf.h | 8 | ||||
-rw-r--r-- | fs/xfs/linux-2.6/xfs_super.c | 66 | ||||
-rw-r--r-- | fs/xfs/linux-2.6/xfs_super.h | 1 | ||||
-rw-r--r-- | fs/xfs/xfs_clnt.h | 2 | ||||
-rw-r--r-- | fs/xfs/xfs_log.c | 65 | ||||
-rw-r--r-- | fs/xfs/xfs_log.h | 9 | ||||
-rw-r--r-- | fs/xfs/xfs_mount.h | 3 | ||||
-rw-r--r-- | fs/xfs/xfs_trans.c | 13 | ||||
-rw-r--r-- | fs/xfs/xfs_trans.h | 7 | ||||
-rw-r--r-- | fs/xfs/xfs_vfsops.c | 38 | ||||
-rw-r--r-- | fs/xfs/xfs_vnodeops.c | 32 |
12 files changed, 190 insertions, 59 deletions
diff --git a/fs/xfs/linux-2.6/xfs_buf.c b/fs/xfs/linux-2.6/xfs_buf.c index 188cbbd5b74a..4663f7dbff1c 100644 --- a/fs/xfs/linux-2.6/xfs_buf.c +++ b/fs/xfs/linux-2.6/xfs_buf.c | |||
@@ -1295,6 +1295,11 @@ _pagebuf_ioapply( | |||
1295 | rw = (pb->pb_flags & PBF_READ) ? READ : WRITE; | 1295 | rw = (pb->pb_flags & PBF_READ) ? READ : WRITE; |
1296 | } | 1296 | } |
1297 | 1297 | ||
1298 | if (pb->pb_flags & PBF_ORDERED) { | ||
1299 | ASSERT(!(pb->pb_flags & PBF_READ)); | ||
1300 | rw = WRITE_BARRIER; | ||
1301 | } | ||
1302 | |||
1298 | /* Special code path for reading a sub page size pagebuf in -- | 1303 | /* Special code path for reading a sub page size pagebuf in -- |
1299 | * we populate up the whole page, and hence the other metadata | 1304 | * we populate up the whole page, and hence the other metadata |
1300 | * in the same page. This optimization is only valid when the | 1305 | * in the same page. This optimization is only valid when the |
diff --git a/fs/xfs/linux-2.6/xfs_buf.h b/fs/xfs/linux-2.6/xfs_buf.h index 39c8ca122534..fa21d1f9cb0b 100644 --- a/fs/xfs/linux-2.6/xfs_buf.h +++ b/fs/xfs/linux-2.6/xfs_buf.h | |||
@@ -74,7 +74,7 @@ typedef enum page_buf_flags_e { /* pb_flags values */ | |||
74 | PBF_DELWRI = (1 << 6), /* buffer has dirty pages */ | 74 | PBF_DELWRI = (1 << 6), /* buffer has dirty pages */ |
75 | PBF_STALE = (1 << 7), /* buffer has been staled, do not find it */ | 75 | PBF_STALE = (1 << 7), /* buffer has been staled, do not find it */ |
76 | PBF_FS_MANAGED = (1 << 8), /* filesystem controls freeing memory */ | 76 | PBF_FS_MANAGED = (1 << 8), /* filesystem controls freeing memory */ |
77 | PBF_FLUSH = (1 << 11), /* flush disk write cache */ | 77 | PBF_ORDERED = (1 << 11), /* use ordered writes */ |
78 | PBF_READ_AHEAD = (1 << 12), /* asynchronous read-ahead */ | 78 | PBF_READ_AHEAD = (1 << 12), /* asynchronous read-ahead */ |
79 | 79 | ||
80 | /* flags used only as arguments to access routines */ | 80 | /* flags used only as arguments to access routines */ |
@@ -383,9 +383,9 @@ extern void pagebuf_trace( | |||
383 | #define XFS_BUF_UNASYNC(x) ((x)->pb_flags &= ~PBF_ASYNC) | 383 | #define XFS_BUF_UNASYNC(x) ((x)->pb_flags &= ~PBF_ASYNC) |
384 | #define XFS_BUF_ISASYNC(x) ((x)->pb_flags & PBF_ASYNC) | 384 | #define XFS_BUF_ISASYNC(x) ((x)->pb_flags & PBF_ASYNC) |
385 | 385 | ||
386 | #define XFS_BUF_FLUSH(x) ((x)->pb_flags |= PBF_FLUSH) | 386 | #define XFS_BUF_ORDERED(x) ((x)->pb_flags |= PBF_ORDERED) |
387 | #define XFS_BUF_UNFLUSH(x) ((x)->pb_flags &= ~PBF_FLUSH) | 387 | #define XFS_BUF_UNORDERED(x) ((x)->pb_flags &= ~PBF_ORDERED) |
388 | #define XFS_BUF_ISFLUSH(x) ((x)->pb_flags & PBF_FLUSH) | 388 | #define XFS_BUF_ISORDERED(x) ((x)->pb_flags & PBF_ORDERED) |
389 | 389 | ||
390 | #define XFS_BUF_SHUT(x) printk("XFS_BUF_SHUT not implemented yet\n") | 390 | #define XFS_BUF_SHUT(x) printk("XFS_BUF_SHUT not implemented yet\n") |
391 | #define XFS_BUF_UNSHUT(x) printk("XFS_BUF_UNSHUT not implemented yet\n") | 391 | #define XFS_BUF_UNSHUT(x) printk("XFS_BUF_UNSHUT not implemented yet\n") |
diff --git a/fs/xfs/linux-2.6/xfs_super.c b/fs/xfs/linux-2.6/xfs_super.c index 2302454d8d47..d2701cc624b9 100644 --- a/fs/xfs/linux-2.6/xfs_super.c +++ b/fs/xfs/linux-2.6/xfs_super.c | |||
@@ -278,6 +278,72 @@ xfs_blkdev_put( | |||
278 | close_bdev_excl(bdev); | 278 | close_bdev_excl(bdev); |
279 | } | 279 | } |
280 | 280 | ||
281 | /* | ||
282 | * Try to write out the superblock using barriers. | ||
283 | */ | ||
284 | STATIC int | ||
285 | xfs_barrier_test( | ||
286 | xfs_mount_t *mp) | ||
287 | { | ||
288 | xfs_buf_t *sbp = xfs_getsb(mp, 0); | ||
289 | int error; | ||
290 | |||
291 | XFS_BUF_UNDONE(sbp); | ||
292 | XFS_BUF_UNREAD(sbp); | ||
293 | XFS_BUF_UNDELAYWRITE(sbp); | ||
294 | XFS_BUF_WRITE(sbp); | ||
295 | XFS_BUF_UNASYNC(sbp); | ||
296 | XFS_BUF_ORDERED(sbp); | ||
297 | |||
298 | xfsbdstrat(mp, sbp); | ||
299 | error = xfs_iowait(sbp); | ||
300 | |||
301 | /* | ||
302 | * Clear all the flags we set and possible error state in the | ||
303 | * buffer. We only did the write to try out whether barriers | ||
304 | * worked and shouldn't leave any traces in the superblock | ||
305 | * buffer. | ||
306 | */ | ||
307 | XFS_BUF_DONE(sbp); | ||
308 | XFS_BUF_ERROR(sbp, 0); | ||
309 | XFS_BUF_UNORDERED(sbp); | ||
310 | |||
311 | xfs_buf_relse(sbp); | ||
312 | return error; | ||
313 | } | ||
314 | |||
315 | void | ||
316 | xfs_mountfs_check_barriers(xfs_mount_t *mp) | ||
317 | { | ||
318 | int error; | ||
319 | |||
320 | if (mp->m_logdev_targp != mp->m_ddev_targp) { | ||
321 | xfs_fs_cmn_err(CE_NOTE, mp, | ||
322 | "Disabling barriers, not supported with external log device"); | ||
323 | mp->m_flags &= ~XFS_MOUNT_BARRIER; | ||
324 | } | ||
325 | |||
326 | if (mp->m_ddev_targp->pbr_bdev->bd_disk->queue->ordered == | ||
327 | QUEUE_ORDERED_NONE) { | ||
328 | xfs_fs_cmn_err(CE_NOTE, mp, | ||
329 | "Disabling barriers, not supported by the underlying device"); | ||
330 | mp->m_flags &= ~XFS_MOUNT_BARRIER; | ||
331 | } | ||
332 | |||
333 | error = xfs_barrier_test(mp); | ||
334 | if (error) { | ||
335 | xfs_fs_cmn_err(CE_NOTE, mp, | ||
336 | "Disabling barriers, trial barrier write failed"); | ||
337 | mp->m_flags &= ~XFS_MOUNT_BARRIER; | ||
338 | } | ||
339 | } | ||
340 | |||
341 | void | ||
342 | xfs_blkdev_issue_flush( | ||
343 | xfs_buftarg_t *buftarg) | ||
344 | { | ||
345 | blkdev_issue_flush(buftarg->pbr_bdev, NULL); | ||
346 | } | ||
281 | 347 | ||
282 | STATIC struct inode * | 348 | STATIC struct inode * |
283 | linvfs_alloc_inode( | 349 | linvfs_alloc_inode( |
diff --git a/fs/xfs/linux-2.6/xfs_super.h b/fs/xfs/linux-2.6/xfs_super.h index ec7e0035c731..ad77e3743e04 100644 --- a/fs/xfs/linux-2.6/xfs_super.h +++ b/fs/xfs/linux-2.6/xfs_super.h | |||
@@ -132,6 +132,7 @@ extern void xfs_flush_device(struct xfs_inode *); | |||
132 | extern int xfs_blkdev_get(struct xfs_mount *, const char *, | 132 | extern int xfs_blkdev_get(struct xfs_mount *, const char *, |
133 | struct block_device **); | 133 | struct block_device **); |
134 | extern void xfs_blkdev_put(struct block_device *); | 134 | extern void xfs_blkdev_put(struct block_device *); |
135 | extern void xfs_blkdev_issue_flush(struct xfs_buftarg *); | ||
135 | 136 | ||
136 | extern struct export_operations linvfs_export_ops; | 137 | extern struct export_operations linvfs_export_ops; |
137 | 138 | ||
diff --git a/fs/xfs/xfs_clnt.h b/fs/xfs/xfs_clnt.h index b3215ffe0be8..c93cb282f3d8 100644 --- a/fs/xfs/xfs_clnt.h +++ b/fs/xfs/xfs_clnt.h | |||
@@ -99,7 +99,7 @@ struct xfs_mount_args { | |||
99 | * enforcement */ | 99 | * enforcement */ |
100 | #define XFSMNT_NOUUID 0x01000000 /* Ignore fs uuid */ | 100 | #define XFSMNT_NOUUID 0x01000000 /* Ignore fs uuid */ |
101 | #define XFSMNT_DMAPI 0x02000000 /* enable dmapi/xdsm */ | 101 | #define XFSMNT_DMAPI 0x02000000 /* enable dmapi/xdsm */ |
102 | #define XFSMNT_NOLOGFLUSH 0x04000000 /* Don't flush for log blocks */ | 102 | #define XFSMNT_BARRIER 0x04000000 /* use write barriers */ |
103 | #define XFSMNT_IDELETE 0x08000000 /* inode cluster delete */ | 103 | #define XFSMNT_IDELETE 0x08000000 /* inode cluster delete */ |
104 | #define XFSMNT_SWALLOC 0x10000000 /* turn on stripe width | 104 | #define XFSMNT_SWALLOC 0x10000000 /* turn on stripe width |
105 | * allocation */ | 105 | * allocation */ |
diff --git a/fs/xfs/xfs_log.c b/fs/xfs/xfs_log.c index 51814c32eddf..b9d3ad35240e 100644 --- a/fs/xfs/xfs_log.c +++ b/fs/xfs/xfs_log.c | |||
@@ -93,8 +93,11 @@ STATIC int xlog_state_release_iclog(xlog_t *log, | |||
93 | STATIC void xlog_state_switch_iclogs(xlog_t *log, | 93 | STATIC void xlog_state_switch_iclogs(xlog_t *log, |
94 | xlog_in_core_t *iclog, | 94 | xlog_in_core_t *iclog, |
95 | int eventual_size); | 95 | int eventual_size); |
96 | STATIC int xlog_state_sync(xlog_t *log, xfs_lsn_t lsn, uint flags); | 96 | STATIC int xlog_state_sync(xlog_t *log, |
97 | STATIC int xlog_state_sync_all(xlog_t *log, uint flags); | 97 | xfs_lsn_t lsn, |
98 | uint flags, | ||
99 | int *log_flushed); | ||
100 | STATIC int xlog_state_sync_all(xlog_t *log, uint flags, int *log_flushed); | ||
98 | STATIC void xlog_state_want_sync(xlog_t *log, xlog_in_core_t *iclog); | 101 | STATIC void xlog_state_want_sync(xlog_t *log, xlog_in_core_t *iclog); |
99 | 102 | ||
100 | /* local functions to manipulate grant head */ | 103 | /* local functions to manipulate grant head */ |
@@ -312,12 +315,17 @@ xfs_log_done(xfs_mount_t *mp, | |||
312 | * semaphore. | 315 | * semaphore. |
313 | */ | 316 | */ |
314 | int | 317 | int |
315 | xfs_log_force(xfs_mount_t *mp, | 318 | _xfs_log_force( |
316 | xfs_lsn_t lsn, | 319 | xfs_mount_t *mp, |
317 | uint flags) | 320 | xfs_lsn_t lsn, |
321 | uint flags, | ||
322 | int *log_flushed) | ||
318 | { | 323 | { |
319 | int rval; | 324 | xlog_t *log = mp->m_log; |
320 | xlog_t *log = mp->m_log; | 325 | int dummy; |
326 | |||
327 | if (!log_flushed) | ||
328 | log_flushed = &dummy; | ||
321 | 329 | ||
322 | #if defined(DEBUG) || defined(XLOG_NOLOG) | 330 | #if defined(DEBUG) || defined(XLOG_NOLOG) |
323 | if (!xlog_debug && xlog_target == log->l_targ) | 331 | if (!xlog_debug && xlog_target == log->l_targ) |
@@ -328,17 +336,12 @@ xfs_log_force(xfs_mount_t *mp, | |||
328 | 336 | ||
329 | XFS_STATS_INC(xs_log_force); | 337 | XFS_STATS_INC(xs_log_force); |
330 | 338 | ||
331 | if ((log->l_flags & XLOG_IO_ERROR) == 0) { | 339 | if (log->l_flags & XLOG_IO_ERROR) |
332 | if (lsn == 0) | 340 | return XFS_ERROR(EIO); |
333 | rval = xlog_state_sync_all(log, flags); | 341 | if (lsn == 0) |
334 | else | 342 | return xlog_state_sync_all(log, flags, log_flushed); |
335 | rval = xlog_state_sync(log, lsn, flags); | 343 | else |
336 | } else { | 344 | return xlog_state_sync(log, lsn, flags, log_flushed); |
337 | rval = XFS_ERROR(EIO); | ||
338 | } | ||
339 | |||
340 | return rval; | ||
341 | |||
342 | } /* xfs_log_force */ | 345 | } /* xfs_log_force */ |
343 | 346 | ||
344 | /* | 347 | /* |
@@ -1467,14 +1470,13 @@ xlog_sync(xlog_t *log, | |||
1467 | XFS_BUF_BUSY(bp); | 1470 | XFS_BUF_BUSY(bp); |
1468 | XFS_BUF_ASYNC(bp); | 1471 | XFS_BUF_ASYNC(bp); |
1469 | /* | 1472 | /* |
1470 | * Do a disk write cache flush for the log block. | 1473 | * Do an ordered write for the log block. |
1471 | * This is a bit of a sledgehammer, it would be better | 1474 | * |
1472 | * to use a tag barrier here that just prevents reordering. | ||
1473 | * It may not be needed to flush the first split block in the log wrap | 1475 | * It may not be needed to flush the first split block in the log wrap |
1474 | * case, but do it anyways to be safe -AK | 1476 | * case, but do it anyways to be safe -AK |
1475 | */ | 1477 | */ |
1476 | if (!(log->l_mp->m_flags & XFS_MOUNT_NOLOGFLUSH)) | 1478 | if (log->l_mp->m_flags & XFS_MOUNT_BARRIER) |
1477 | XFS_BUF_FLUSH(bp); | 1479 | XFS_BUF_ORDERED(bp); |
1478 | 1480 | ||
1479 | ASSERT(XFS_BUF_ADDR(bp) <= log->l_logBBsize-1); | 1481 | ASSERT(XFS_BUF_ADDR(bp) <= log->l_logBBsize-1); |
1480 | ASSERT(XFS_BUF_ADDR(bp) + BTOBB(count) <= log->l_logBBsize); | 1482 | ASSERT(XFS_BUF_ADDR(bp) + BTOBB(count) <= log->l_logBBsize); |
@@ -1505,8 +1507,8 @@ xlog_sync(xlog_t *log, | |||
1505 | XFS_BUF_SET_FSPRIVATE(bp, iclog); | 1507 | XFS_BUF_SET_FSPRIVATE(bp, iclog); |
1506 | XFS_BUF_BUSY(bp); | 1508 | XFS_BUF_BUSY(bp); |
1507 | XFS_BUF_ASYNC(bp); | 1509 | XFS_BUF_ASYNC(bp); |
1508 | if (!(log->l_mp->m_flags & XFS_MOUNT_NOLOGFLUSH)) | 1510 | if (log->l_mp->m_flags & XFS_MOUNT_BARRIER) |
1509 | XFS_BUF_FLUSH(bp); | 1511 | XFS_BUF_ORDERED(bp); |
1510 | dptr = XFS_BUF_PTR(bp); | 1512 | dptr = XFS_BUF_PTR(bp); |
1511 | /* | 1513 | /* |
1512 | * Bump the cycle numbers at the start of each block | 1514 | * Bump the cycle numbers at the start of each block |
@@ -2951,7 +2953,7 @@ xlog_state_switch_iclogs(xlog_t *log, | |||
2951 | * not in the active nor dirty state. | 2953 | * not in the active nor dirty state. |
2952 | */ | 2954 | */ |
2953 | STATIC int | 2955 | STATIC int |
2954 | xlog_state_sync_all(xlog_t *log, uint flags) | 2956 | xlog_state_sync_all(xlog_t *log, uint flags, int *log_flushed) |
2955 | { | 2957 | { |
2956 | xlog_in_core_t *iclog; | 2958 | xlog_in_core_t *iclog; |
2957 | xfs_lsn_t lsn; | 2959 | xfs_lsn_t lsn; |
@@ -3000,6 +3002,7 @@ xlog_state_sync_all(xlog_t *log, uint flags) | |||
3000 | 3002 | ||
3001 | if (xlog_state_release_iclog(log, iclog)) | 3003 | if (xlog_state_release_iclog(log, iclog)) |
3002 | return XFS_ERROR(EIO); | 3004 | return XFS_ERROR(EIO); |
3005 | *log_flushed = 1; | ||
3003 | s = LOG_LOCK(log); | 3006 | s = LOG_LOCK(log); |
3004 | if (INT_GET(iclog->ic_header.h_lsn, ARCH_CONVERT) == lsn && | 3007 | if (INT_GET(iclog->ic_header.h_lsn, ARCH_CONVERT) == lsn && |
3005 | iclog->ic_state != XLOG_STATE_DIRTY) | 3008 | iclog->ic_state != XLOG_STATE_DIRTY) |
@@ -3043,6 +3046,7 @@ maybe_sleep: | |||
3043 | */ | 3046 | */ |
3044 | if (iclog->ic_state & XLOG_STATE_IOERROR) | 3047 | if (iclog->ic_state & XLOG_STATE_IOERROR) |
3045 | return XFS_ERROR(EIO); | 3048 | return XFS_ERROR(EIO); |
3049 | *log_flushed = 1; | ||
3046 | 3050 | ||
3047 | } else { | 3051 | } else { |
3048 | 3052 | ||
@@ -3068,7 +3072,8 @@ no_sleep: | |||
3068 | int | 3072 | int |
3069 | xlog_state_sync(xlog_t *log, | 3073 | xlog_state_sync(xlog_t *log, |
3070 | xfs_lsn_t lsn, | 3074 | xfs_lsn_t lsn, |
3071 | uint flags) | 3075 | uint flags, |
3076 | int *log_flushed) | ||
3072 | { | 3077 | { |
3073 | xlog_in_core_t *iclog; | 3078 | xlog_in_core_t *iclog; |
3074 | int already_slept = 0; | 3079 | int already_slept = 0; |
@@ -3120,6 +3125,7 @@ try_again: | |||
3120 | XFS_STATS_INC(xs_log_force_sleep); | 3125 | XFS_STATS_INC(xs_log_force_sleep); |
3121 | sv_wait(&iclog->ic_prev->ic_writesema, PSWP, | 3126 | sv_wait(&iclog->ic_prev->ic_writesema, PSWP, |
3122 | &log->l_icloglock, s); | 3127 | &log->l_icloglock, s); |
3128 | *log_flushed = 1; | ||
3123 | already_slept = 1; | 3129 | already_slept = 1; |
3124 | goto try_again; | 3130 | goto try_again; |
3125 | } else { | 3131 | } else { |
@@ -3128,6 +3134,7 @@ try_again: | |||
3128 | LOG_UNLOCK(log, s); | 3134 | LOG_UNLOCK(log, s); |
3129 | if (xlog_state_release_iclog(log, iclog)) | 3135 | if (xlog_state_release_iclog(log, iclog)) |
3130 | return XFS_ERROR(EIO); | 3136 | return XFS_ERROR(EIO); |
3137 | *log_flushed = 1; | ||
3131 | s = LOG_LOCK(log); | 3138 | s = LOG_LOCK(log); |
3132 | } | 3139 | } |
3133 | } | 3140 | } |
@@ -3152,6 +3159,7 @@ try_again: | |||
3152 | */ | 3159 | */ |
3153 | if (iclog->ic_state & XLOG_STATE_IOERROR) | 3160 | if (iclog->ic_state & XLOG_STATE_IOERROR) |
3154 | return XFS_ERROR(EIO); | 3161 | return XFS_ERROR(EIO); |
3162 | *log_flushed = 1; | ||
3155 | } else { /* just return */ | 3163 | } else { /* just return */ |
3156 | LOG_UNLOCK(log, s); | 3164 | LOG_UNLOCK(log, s); |
3157 | } | 3165 | } |
@@ -3606,6 +3614,7 @@ xfs_log_force_umount( | |||
3606 | xlog_ticket_t *tic; | 3614 | xlog_ticket_t *tic; |
3607 | xlog_t *log; | 3615 | xlog_t *log; |
3608 | int retval; | 3616 | int retval; |
3617 | int dummy; | ||
3609 | SPLDECL(s); | 3618 | SPLDECL(s); |
3610 | SPLDECL(s2); | 3619 | SPLDECL(s2); |
3611 | 3620 | ||
@@ -3684,7 +3693,7 @@ xfs_log_force_umount( | |||
3684 | * Force the incore logs to disk before shutting the | 3693 | * Force the incore logs to disk before shutting the |
3685 | * log down completely. | 3694 | * log down completely. |
3686 | */ | 3695 | */ |
3687 | xlog_state_sync_all(log, XFS_LOG_FORCE|XFS_LOG_SYNC); | 3696 | xlog_state_sync_all(log, XFS_LOG_FORCE|XFS_LOG_SYNC, &dummy); |
3688 | s2 = LOG_LOCK(log); | 3697 | s2 = LOG_LOCK(log); |
3689 | retval = xlog_state_ioerror(log); | 3698 | retval = xlog_state_ioerror(log); |
3690 | LOG_UNLOCK(log, s2); | 3699 | LOG_UNLOCK(log, s2); |
diff --git a/fs/xfs/xfs_log.h b/fs/xfs/xfs_log.h index 18961119fc65..dc920f83412d 100644 --- a/fs/xfs/xfs_log.h +++ b/fs/xfs/xfs_log.h | |||
@@ -174,9 +174,12 @@ xfs_lsn_t xfs_log_done(struct xfs_mount *mp, | |||
174 | xfs_log_ticket_t ticket, | 174 | xfs_log_ticket_t ticket, |
175 | void **iclog, | 175 | void **iclog, |
176 | uint flags); | 176 | uint flags); |
177 | int xfs_log_force(struct xfs_mount *mp, | 177 | int _xfs_log_force(struct xfs_mount *mp, |
178 | xfs_lsn_t lsn, | 178 | xfs_lsn_t lsn, |
179 | uint flags); | 179 | uint flags, |
180 | int *log_forced); | ||
181 | #define xfs_log_force(mp, lsn, flags) \ | ||
182 | _xfs_log_force(mp, lsn, flags, NULL); | ||
180 | int xfs_log_mount(struct xfs_mount *mp, | 183 | int xfs_log_mount(struct xfs_mount *mp, |
181 | struct xfs_buftarg *log_target, | 184 | struct xfs_buftarg *log_target, |
182 | xfs_daddr_t start_block, | 185 | xfs_daddr_t start_block, |
diff --git a/fs/xfs/xfs_mount.h b/fs/xfs/xfs_mount.h index 5affba38a577..bc55931ac74e 100644 --- a/fs/xfs/xfs_mount.h +++ b/fs/xfs/xfs_mount.h | |||
@@ -415,7 +415,7 @@ typedef struct xfs_mount { | |||
415 | * 32 bits in size */ | 415 | * 32 bits in size */ |
416 | #define XFS_MOUNT_32BITINOOPT 0x00008000 /* saved mount option state */ | 416 | #define XFS_MOUNT_32BITINOOPT 0x00008000 /* saved mount option state */ |
417 | #define XFS_MOUNT_NOUUID 0x00010000 /* ignore uuid during mount */ | 417 | #define XFS_MOUNT_NOUUID 0x00010000 /* ignore uuid during mount */ |
418 | #define XFS_MOUNT_NOLOGFLUSH 0x00020000 | 418 | #define XFS_MOUNT_BARRIER 0x00020000 |
419 | #define XFS_MOUNT_IDELETE 0x00040000 /* delete empty inode clusters*/ | 419 | #define XFS_MOUNT_IDELETE 0x00040000 /* delete empty inode clusters*/ |
420 | #define XFS_MOUNT_SWALLOC 0x00080000 /* turn on stripe width | 420 | #define XFS_MOUNT_SWALLOC 0x00080000 /* turn on stripe width |
421 | * allocation */ | 421 | * allocation */ |
@@ -542,6 +542,7 @@ extern xfs_mount_t *xfs_mount_init(void); | |||
542 | extern void xfs_mod_sb(xfs_trans_t *, __int64_t); | 542 | extern void xfs_mod_sb(xfs_trans_t *, __int64_t); |
543 | extern void xfs_mount_free(xfs_mount_t *mp, int remove_bhv); | 543 | extern void xfs_mount_free(xfs_mount_t *mp, int remove_bhv); |
544 | extern int xfs_mountfs(struct vfs *, xfs_mount_t *mp, int); | 544 | extern int xfs_mountfs(struct vfs *, xfs_mount_t *mp, int); |
545 | extern void xfs_mountfs_check_barriers(xfs_mount_t *mp); | ||
545 | 546 | ||
546 | extern int xfs_unmountfs(xfs_mount_t *, struct cred *); | 547 | extern int xfs_unmountfs(xfs_mount_t *, struct cred *); |
547 | extern void xfs_unmountfs_close(xfs_mount_t *, struct cred *); | 548 | extern void xfs_unmountfs_close(xfs_mount_t *, struct cred *); |
diff --git a/fs/xfs/xfs_trans.c b/fs/xfs/xfs_trans.c index 92efe272b83d..5e33891b8049 100644 --- a/fs/xfs/xfs_trans.c +++ b/fs/xfs/xfs_trans.c | |||
@@ -661,10 +661,11 @@ xfs_trans_unreserve_and_mod_sb( | |||
661 | */ | 661 | */ |
662 | /*ARGSUSED*/ | 662 | /*ARGSUSED*/ |
663 | int | 663 | int |
664 | xfs_trans_commit( | 664 | _xfs_trans_commit( |
665 | xfs_trans_t *tp, | 665 | xfs_trans_t *tp, |
666 | uint flags, | 666 | uint flags, |
667 | xfs_lsn_t *commit_lsn_p) | 667 | xfs_lsn_t *commit_lsn_p, |
668 | int *log_flushed) | ||
668 | { | 669 | { |
669 | xfs_log_iovec_t *log_vector; | 670 | xfs_log_iovec_t *log_vector; |
670 | int nvec; | 671 | int nvec; |
@@ -893,9 +894,11 @@ shut_us_down: | |||
893 | * log out now and wait for it. | 894 | * log out now and wait for it. |
894 | */ | 895 | */ |
895 | if (sync) { | 896 | if (sync) { |
896 | if (!error) | 897 | if (!error) { |
897 | error = xfs_log_force(mp, commit_lsn, | 898 | error = _xfs_log_force(mp, commit_lsn, |
898 | XFS_LOG_FORCE | XFS_LOG_SYNC); | 899 | XFS_LOG_FORCE | XFS_LOG_SYNC, |
900 | log_flushed); | ||
901 | } | ||
899 | XFS_STATS_INC(xs_trans_sync); | 902 | XFS_STATS_INC(xs_trans_sync); |
900 | } else { | 903 | } else { |
901 | XFS_STATS_INC(xs_trans_async); | 904 | XFS_STATS_INC(xs_trans_async); |
diff --git a/fs/xfs/xfs_trans.h b/fs/xfs/xfs_trans.h index a263aec8b3a6..0cc7af5c1f00 100644 --- a/fs/xfs/xfs_trans.h +++ b/fs/xfs/xfs_trans.h | |||
@@ -1025,7 +1025,12 @@ void xfs_trans_log_efd_extent(xfs_trans_t *, | |||
1025 | struct xfs_efd_log_item *, | 1025 | struct xfs_efd_log_item *, |
1026 | xfs_fsblock_t, | 1026 | xfs_fsblock_t, |
1027 | xfs_extlen_t); | 1027 | xfs_extlen_t); |
1028 | int xfs_trans_commit(xfs_trans_t *, uint flags, xfs_lsn_t *); | 1028 | int _xfs_trans_commit(xfs_trans_t *, |
1029 | uint flags, | ||
1030 | xfs_lsn_t *, | ||
1031 | int *); | ||
1032 | #define xfs_trans_commit(tp, flags, lsn) \ | ||
1033 | _xfs_trans_commit(tp, flags, lsn, NULL) | ||
1029 | void xfs_trans_cancel(xfs_trans_t *, int); | 1034 | void xfs_trans_cancel(xfs_trans_t *, int); |
1030 | void xfs_trans_ail_init(struct xfs_mount *); | 1035 | void xfs_trans_ail_init(struct xfs_mount *); |
1031 | xfs_lsn_t xfs_trans_push_ail(struct xfs_mount *, xfs_lsn_t); | 1036 | xfs_lsn_t xfs_trans_push_ail(struct xfs_mount *, xfs_lsn_t); |
diff --git a/fs/xfs/xfs_vfsops.c b/fs/xfs/xfs_vfsops.c index f1a904e23ade..8238c7517822 100644 --- a/fs/xfs/xfs_vfsops.c +++ b/fs/xfs/xfs_vfsops.c | |||
@@ -321,8 +321,8 @@ xfs_start_flags( | |||
321 | 321 | ||
322 | if (ap->flags & XFSMNT_NOUUID) | 322 | if (ap->flags & XFSMNT_NOUUID) |
323 | mp->m_flags |= XFS_MOUNT_NOUUID; | 323 | mp->m_flags |= XFS_MOUNT_NOUUID; |
324 | if (ap->flags & XFSMNT_NOLOGFLUSH) | 324 | if (ap->flags & XFSMNT_BARRIER) |
325 | mp->m_flags |= XFS_MOUNT_NOLOGFLUSH; | 325 | mp->m_flags |= XFS_MOUNT_BARRIER; |
326 | 326 | ||
327 | return 0; | 327 | return 0; |
328 | } | 328 | } |
@@ -512,8 +512,14 @@ xfs_mount( | |||
512 | goto error2; | 512 | goto error2; |
513 | 513 | ||
514 | error = XFS_IOINIT(vfsp, args, flags); | 514 | error = XFS_IOINIT(vfsp, args, flags); |
515 | if (!error) | 515 | if (error) |
516 | return 0; | 516 | goto error2; |
517 | |||
518 | if ((args->flags & XFSMNT_BARRIER) && | ||
519 | !(XFS_MTOVFS(mp)->vfs_flag & VFS_RDONLY)) | ||
520 | xfs_mountfs_check_barriers(mp); | ||
521 | return 0; | ||
522 | |||
517 | error2: | 523 | error2: |
518 | if (mp->m_sb_bp) | 524 | if (mp->m_sb_bp) |
519 | xfs_freesb(mp); | 525 | xfs_freesb(mp); |
@@ -656,19 +662,24 @@ xfs_mntupdate( | |||
656 | else | 662 | else |
657 | mp->m_flags &= ~XFS_MOUNT_NOATIME; | 663 | mp->m_flags &= ~XFS_MOUNT_NOATIME; |
658 | 664 | ||
659 | if (!(vfsp->vfs_flag & VFS_RDONLY)) { | 665 | if ((vfsp->vfs_flag & VFS_RDONLY) && |
660 | VFS_SYNC(vfsp, SYNC_FSDATA|SYNC_BDFLUSH|SYNC_ATTR, NULL, error); | 666 | !(*flags & MS_RDONLY)) { |
667 | vfsp->vfs_flag &= ~VFS_RDONLY; | ||
668 | |||
669 | if (args->flags & XFSMNT_BARRIER) | ||
670 | xfs_mountfs_check_barriers(mp); | ||
661 | } | 671 | } |
662 | 672 | ||
663 | if (*flags & MS_RDONLY) { | 673 | if (!(vfsp->vfs_flag & VFS_RDONLY) && |
674 | (*flags & MS_RDONLY)) { | ||
675 | VFS_SYNC(vfsp, SYNC_FSDATA|SYNC_BDFLUSH|SYNC_ATTR, NULL, error); | ||
676 | |||
664 | xfs_quiesce_fs(mp); | 677 | xfs_quiesce_fs(mp); |
665 | 678 | ||
666 | /* Ok now write out an unmount record */ | 679 | /* Ok now write out an unmount record */ |
667 | xfs_log_unmount_write(mp); | 680 | xfs_log_unmount_write(mp); |
668 | xfs_unmountfs_writesb(mp); | 681 | xfs_unmountfs_writesb(mp); |
669 | vfsp->vfs_flag |= VFS_RDONLY; | 682 | vfsp->vfs_flag |= VFS_RDONLY; |
670 | } else { | ||
671 | vfsp->vfs_flag &= ~VFS_RDONLY; | ||
672 | } | 683 | } |
673 | 684 | ||
674 | return 0; | 685 | return 0; |
@@ -1628,7 +1639,8 @@ xfs_vget( | |||
1628 | #define MNTOPT_ALLOCSIZE "allocsize" /* preferred allocation size */ | 1639 | #define MNTOPT_ALLOCSIZE "allocsize" /* preferred allocation size */ |
1629 | #define MNTOPT_IHASHSIZE "ihashsize" /* size of inode hash table */ | 1640 | #define MNTOPT_IHASHSIZE "ihashsize" /* size of inode hash table */ |
1630 | #define MNTOPT_NORECOVERY "norecovery" /* don't run XFS recovery */ | 1641 | #define MNTOPT_NORECOVERY "norecovery" /* don't run XFS recovery */ |
1631 | #define MNTOPT_NOLOGFLUSH "nologflush" /* don't hard flush on log writes */ | 1642 | #define MNTOPT_BARRIER "barrier" /* use writer barriers for log write and |
1643 | unwritten extent conversion */ | ||
1632 | #define MNTOPT_OSYNCISOSYNC "osyncisosync" /* o_sync is REALLY o_sync */ | 1644 | #define MNTOPT_OSYNCISOSYNC "osyncisosync" /* o_sync is REALLY o_sync */ |
1633 | #define MNTOPT_64BITINODE "inode64" /* inodes can be allocated anywhere */ | 1645 | #define MNTOPT_64BITINODE "inode64" /* inodes can be allocated anywhere */ |
1634 | #define MNTOPT_IKEEP "ikeep" /* do not free empty inode clusters */ | 1646 | #define MNTOPT_IKEEP "ikeep" /* do not free empty inode clusters */ |
@@ -1791,8 +1803,8 @@ xfs_parseargs( | |||
1791 | #endif | 1803 | #endif |
1792 | } else if (!strcmp(this_char, MNTOPT_NOUUID)) { | 1804 | } else if (!strcmp(this_char, MNTOPT_NOUUID)) { |
1793 | args->flags |= XFSMNT_NOUUID; | 1805 | args->flags |= XFSMNT_NOUUID; |
1794 | } else if (!strcmp(this_char, MNTOPT_NOLOGFLUSH)) { | 1806 | } else if (!strcmp(this_char, MNTOPT_BARRIER)) { |
1795 | args->flags |= XFSMNT_NOLOGFLUSH; | 1807 | args->flags |= XFSMNT_BARRIER; |
1796 | } else if (!strcmp(this_char, MNTOPT_IKEEP)) { | 1808 | } else if (!strcmp(this_char, MNTOPT_IKEEP)) { |
1797 | args->flags &= ~XFSMNT_IDELETE; | 1809 | args->flags &= ~XFSMNT_IDELETE; |
1798 | } else if (!strcmp(this_char, MNTOPT_NOIKEEP)) { | 1810 | } else if (!strcmp(this_char, MNTOPT_NOIKEEP)) { |
@@ -1866,7 +1878,7 @@ xfs_showargs( | |||
1866 | { XFS_MOUNT_NOUUID, "," MNTOPT_NOUUID }, | 1878 | { XFS_MOUNT_NOUUID, "," MNTOPT_NOUUID }, |
1867 | { XFS_MOUNT_NORECOVERY, "," MNTOPT_NORECOVERY }, | 1879 | { XFS_MOUNT_NORECOVERY, "," MNTOPT_NORECOVERY }, |
1868 | { XFS_MOUNT_OSYNCISOSYNC, "," MNTOPT_OSYNCISOSYNC }, | 1880 | { XFS_MOUNT_OSYNCISOSYNC, "," MNTOPT_OSYNCISOSYNC }, |
1869 | { XFS_MOUNT_NOLOGFLUSH, "," MNTOPT_NOLOGFLUSH }, | 1881 | { XFS_MOUNT_BARRIER, "," MNTOPT_BARRIER }, |
1870 | { XFS_MOUNT_IDELETE, "," MNTOPT_NOIKEEP }, | 1882 | { XFS_MOUNT_IDELETE, "," MNTOPT_NOIKEEP }, |
1871 | { 0, NULL } | 1883 | { 0, NULL } |
1872 | }; | 1884 | }; |
diff --git a/fs/xfs/xfs_vnodeops.c b/fs/xfs/xfs_vnodeops.c index 58bfe629b933..e2bf2ef58b66 100644 --- a/fs/xfs/xfs_vnodeops.c +++ b/fs/xfs/xfs_vnodeops.c | |||
@@ -1118,6 +1118,7 @@ xfs_fsync( | |||
1118 | xfs_inode_t *ip; | 1118 | xfs_inode_t *ip; |
1119 | xfs_trans_t *tp; | 1119 | xfs_trans_t *tp; |
1120 | int error; | 1120 | int error; |
1121 | int log_flushed = 0, changed = 1; | ||
1121 | 1122 | ||
1122 | vn_trace_entry(BHV_TO_VNODE(bdp), | 1123 | vn_trace_entry(BHV_TO_VNODE(bdp), |
1123 | __FUNCTION__, (inst_t *)__return_address); | 1124 | __FUNCTION__, (inst_t *)__return_address); |
@@ -1171,10 +1172,18 @@ xfs_fsync( | |||
1171 | xfs_iunlock(ip, XFS_ILOCK_SHARED); | 1172 | xfs_iunlock(ip, XFS_ILOCK_SHARED); |
1172 | 1173 | ||
1173 | if (xfs_ipincount(ip)) { | 1174 | if (xfs_ipincount(ip)) { |
1174 | xfs_log_force(ip->i_mount, (xfs_lsn_t)0, | 1175 | _xfs_log_force(ip->i_mount, (xfs_lsn_t)0, |
1175 | XFS_LOG_FORCE | | 1176 | XFS_LOG_FORCE | |
1176 | ((flag & FSYNC_WAIT) | 1177 | ((flag & FSYNC_WAIT) |
1177 | ? XFS_LOG_SYNC : 0)); | 1178 | ? XFS_LOG_SYNC : 0), |
1179 | &log_flushed); | ||
1180 | } else { | ||
1181 | /* | ||
1182 | * If the inode is not pinned and nothing | ||
1183 | * has changed we don't need to flush the | ||
1184 | * cache. | ||
1185 | */ | ||
1186 | changed = 0; | ||
1178 | } | 1187 | } |
1179 | error = 0; | 1188 | error = 0; |
1180 | } else { | 1189 | } else { |
@@ -1210,10 +1219,27 @@ xfs_fsync( | |||
1210 | xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); | 1219 | xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); |
1211 | if (flag & FSYNC_WAIT) | 1220 | if (flag & FSYNC_WAIT) |
1212 | xfs_trans_set_sync(tp); | 1221 | xfs_trans_set_sync(tp); |
1213 | error = xfs_trans_commit(tp, 0, NULL); | 1222 | error = _xfs_trans_commit(tp, 0, NULL, &log_flushed); |
1214 | 1223 | ||
1215 | xfs_iunlock(ip, XFS_ILOCK_EXCL); | 1224 | xfs_iunlock(ip, XFS_ILOCK_EXCL); |
1216 | } | 1225 | } |
1226 | |||
1227 | if ((ip->i_mount->m_flags & XFS_MOUNT_BARRIER) && changed) { | ||
1228 | /* | ||
1229 | * If the log write didn't issue an ordered tag we need | ||
1230 | * to flush the disk cache for the data device now. | ||
1231 | */ | ||
1232 | if (!log_flushed) | ||
1233 | xfs_blkdev_issue_flush(ip->i_mount->m_ddev_targp); | ||
1234 | |||
1235 | /* | ||
1236 | * If this inode is on the RT dev we need to flush that | ||
1237 | * cache aswell. | ||
1238 | */ | ||
1239 | if (ip->i_d.di_flags & XFS_DIFLAG_REALTIME) | ||
1240 | xfs_blkdev_issue_flush(ip->i_mount->m_rtdev_targp); | ||
1241 | } | ||
1242 | |||
1217 | return error; | 1243 | return error; |
1218 | } | 1244 | } |
1219 | 1245 | ||