diff options
Diffstat (limited to 'fs/xfs')
| -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 | ||
