diff options
Diffstat (limited to 'fs/xfs/xfs_log.c')
| -rw-r--r-- | fs/xfs/xfs_log.c | 281 |
1 files changed, 91 insertions, 190 deletions
diff --git a/fs/xfs/xfs_log.c b/fs/xfs/xfs_log.c index 54a6f1142403..29af51275ca9 100644 --- a/fs/xfs/xfs_log.c +++ b/fs/xfs/xfs_log.c | |||
| @@ -1,58 +1,47 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * Copyright (c) 2000-2004 Silicon Graphics, Inc. All Rights Reserved. | 2 | * Copyright (c) 2000-2005 Silicon Graphics, Inc. |
| 3 | * All Rights Reserved. | ||
| 3 | * | 4 | * |
| 4 | * This program is free software; you can redistribute it and/or modify it | 5 | * This program is free software; you can redistribute it and/or |
| 5 | * under the terms of version 2 of the GNU General Public License as | 6 | * modify it under the terms of the GNU General Public License as |
| 6 | * published by the Free Software Foundation. | 7 | * published by the Free Software Foundation. |
| 7 | * | 8 | * |
| 8 | * This program is distributed in the hope that it would be useful, but | 9 | * This program is distributed in the hope that it would be useful, |
| 9 | * WITHOUT ANY WARRANTY; without even the implied warranty of | 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 12 | * GNU General Public License for more details. | ||
| 11 | * | 13 | * |
| 12 | * Further, this software is distributed without any warranty that it is | 14 | * You should have received a copy of the GNU General Public License |
| 13 | * free of the rightful claim of any third person regarding infringement | 15 | * along with this program; if not, write the Free Software Foundation, |
| 14 | * or the like. Any license provided herein, whether implied or | 16 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
| 15 | * otherwise, applies only to this software file. Patent licenses, if | ||
| 16 | * any, provided herein do not apply to combinations of this program with | ||
| 17 | * other software, or any other product whatsoever. | ||
| 18 | * | ||
| 19 | * You should have received a copy of the GNU General Public License along | ||
| 20 | * with this program; if not, write the Free Software Foundation, Inc., 59 | ||
| 21 | * Temple Place - Suite 330, Boston MA 02111-1307, USA. | ||
| 22 | * | ||
| 23 | * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, | ||
| 24 | * Mountain View, CA 94043, or: | ||
| 25 | * | ||
| 26 | * http://www.sgi.com | ||
| 27 | * | ||
| 28 | * For further information regarding this notice, see: | ||
| 29 | * | ||
| 30 | * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/ | ||
| 31 | */ | 17 | */ |
| 32 | |||
| 33 | /* | ||
| 34 | * High level interface routines for log manager | ||
| 35 | */ | ||
| 36 | |||
| 37 | #include "xfs.h" | 18 | #include "xfs.h" |
| 38 | #include "xfs_macros.h" | 19 | #include "xfs_fs.h" |
| 39 | #include "xfs_types.h" | 20 | #include "xfs_types.h" |
| 40 | #include "xfs_inum.h" | 21 | #include "xfs_bit.h" |
| 41 | #include "xfs_ag.h" | ||
| 42 | #include "xfs_sb.h" | ||
| 43 | #include "xfs_log.h" | 22 | #include "xfs_log.h" |
| 23 | #include "xfs_inum.h" | ||
| 44 | #include "xfs_trans.h" | 24 | #include "xfs_trans.h" |
| 25 | #include "xfs_sb.h" | ||
| 26 | #include "xfs_ag.h" | ||
| 45 | #include "xfs_dir.h" | 27 | #include "xfs_dir.h" |
| 28 | #include "xfs_dir2.h" | ||
| 46 | #include "xfs_dmapi.h" | 29 | #include "xfs_dmapi.h" |
| 47 | #include "xfs_mount.h" | 30 | #include "xfs_mount.h" |
| 48 | #include "xfs_error.h" | 31 | #include "xfs_error.h" |
| 49 | #include "xfs_log_priv.h" | 32 | #include "xfs_log_priv.h" |
| 50 | #include "xfs_buf_item.h" | 33 | #include "xfs_buf_item.h" |
| 34 | #include "xfs_bmap_btree.h" | ||
| 51 | #include "xfs_alloc_btree.h" | 35 | #include "xfs_alloc_btree.h" |
| 36 | #include "xfs_ialloc_btree.h" | ||
| 52 | #include "xfs_log_recover.h" | 37 | #include "xfs_log_recover.h" |
| 53 | #include "xfs_bit.h" | ||
| 54 | #include "xfs_rw.h" | ||
| 55 | #include "xfs_trans_priv.h" | 38 | #include "xfs_trans_priv.h" |
| 39 | #include "xfs_dir_sf.h" | ||
| 40 | #include "xfs_dir2_sf.h" | ||
| 41 | #include "xfs_attr_sf.h" | ||
| 42 | #include "xfs_dinode.h" | ||
| 43 | #include "xfs_inode.h" | ||
| 44 | #include "xfs_rw.h" | ||
| 56 | 45 | ||
| 57 | 46 | ||
| 58 | #define xlog_write_adv_cnt(ptr, len, off, bytes) \ | 47 | #define xlog_write_adv_cnt(ptr, len, off, bytes) \ |
| @@ -93,8 +82,11 @@ STATIC int xlog_state_release_iclog(xlog_t *log, | |||
| 93 | STATIC void xlog_state_switch_iclogs(xlog_t *log, | 82 | STATIC void xlog_state_switch_iclogs(xlog_t *log, |
| 94 | xlog_in_core_t *iclog, | 83 | xlog_in_core_t *iclog, |
| 95 | int eventual_size); | 84 | int eventual_size); |
| 96 | STATIC int xlog_state_sync(xlog_t *log, xfs_lsn_t lsn, uint flags); | 85 | STATIC int xlog_state_sync(xlog_t *log, |
| 97 | STATIC int xlog_state_sync_all(xlog_t *log, uint flags); | 86 | xfs_lsn_t lsn, |
| 87 | uint flags, | ||
| 88 | int *log_flushed); | ||
| 89 | 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); | 90 | STATIC void xlog_state_want_sync(xlog_t *log, xlog_in_core_t *iclog); |
| 99 | 91 | ||
| 100 | /* local functions to manipulate grant head */ | 92 | /* local functions to manipulate grant head */ |
| @@ -119,8 +111,7 @@ STATIC xlog_ticket_t *xlog_ticket_get(xlog_t *log, | |||
| 119 | uint flags); | 111 | uint flags); |
| 120 | STATIC void xlog_ticket_put(xlog_t *log, xlog_ticket_t *ticket); | 112 | STATIC void xlog_ticket_put(xlog_t *log, xlog_ticket_t *ticket); |
| 121 | 113 | ||
| 122 | /* local debug functions */ | 114 | #if defined(DEBUG) |
| 123 | #if defined(DEBUG) && !defined(XLOG_NOLOG) | ||
| 124 | STATIC void xlog_verify_dest_ptr(xlog_t *log, __psint_t ptr); | 115 | STATIC void xlog_verify_dest_ptr(xlog_t *log, __psint_t ptr); |
| 125 | STATIC void xlog_verify_grant_head(xlog_t *log, int equals); | 116 | STATIC void xlog_verify_grant_head(xlog_t *log, int equals); |
| 126 | STATIC void xlog_verify_iclog(xlog_t *log, xlog_in_core_t *iclog, | 117 | STATIC void xlog_verify_iclog(xlog_t *log, xlog_in_core_t *iclog, |
| @@ -136,26 +127,7 @@ STATIC void xlog_verify_tail_lsn(xlog_t *log, xlog_in_core_t *iclog, | |||
| 136 | 127 | ||
| 137 | STATIC int xlog_iclogs_empty(xlog_t *log); | 128 | STATIC int xlog_iclogs_empty(xlog_t *log); |
| 138 | 129 | ||
| 139 | #ifdef DEBUG | ||
| 140 | int xlog_do_error = 0; | ||
| 141 | int xlog_req_num = 0; | ||
| 142 | int xlog_error_mod = 33; | ||
| 143 | #endif | ||
| 144 | |||
| 145 | #define XLOG_FORCED_SHUTDOWN(log) (log->l_flags & XLOG_IO_ERROR) | ||
| 146 | |||
| 147 | /* | ||
| 148 | * 0 => disable log manager | ||
| 149 | * 1 => enable log manager | ||
| 150 | * 2 => enable log manager and log debugging | ||
| 151 | */ | ||
| 152 | #if defined(XLOG_NOLOG) || defined(DEBUG) | ||
| 153 | int xlog_debug = 1; | ||
| 154 | xfs_buftarg_t *xlog_target; | ||
| 155 | #endif | ||
| 156 | |||
| 157 | #if defined(XFS_LOG_TRACE) | 130 | #if defined(XFS_LOG_TRACE) |
| 158 | |||
| 159 | void | 131 | void |
| 160 | xlog_trace_loggrant(xlog_t *log, xlog_ticket_t *tic, xfs_caddr_t string) | 132 | xlog_trace_loggrant(xlog_t *log, xlog_ticket_t *tic, xfs_caddr_t string) |
| 161 | { | 133 | { |
| @@ -191,31 +163,16 @@ xlog_trace_loggrant(xlog_t *log, xlog_ticket_t *tic, xfs_caddr_t string) | |||
| 191 | void | 163 | void |
| 192 | xlog_trace_iclog(xlog_in_core_t *iclog, uint state) | 164 | xlog_trace_iclog(xlog_in_core_t *iclog, uint state) |
| 193 | { | 165 | { |
| 194 | pid_t pid; | ||
| 195 | |||
| 196 | pid = current_pid(); | ||
| 197 | |||
| 198 | if (!iclog->ic_trace) | 166 | if (!iclog->ic_trace) |
| 199 | iclog->ic_trace = ktrace_alloc(256, KM_SLEEP); | 167 | iclog->ic_trace = ktrace_alloc(256, KM_SLEEP); |
| 200 | ktrace_enter(iclog->ic_trace, | 168 | ktrace_enter(iclog->ic_trace, |
| 201 | (void *)((unsigned long)state), | 169 | (void *)((unsigned long)state), |
| 202 | (void *)((unsigned long)pid), | 170 | (void *)((unsigned long)current_pid()), |
| 203 | (void *)0, | 171 | (void *)NULL, (void *)NULL, (void *)NULL, (void *)NULL, |
| 204 | (void *)0, | 172 | (void *)NULL, (void *)NULL, (void *)NULL, (void *)NULL, |
| 205 | (void *)0, | 173 | (void *)NULL, (void *)NULL, (void *)NULL, (void *)NULL, |
| 206 | (void *)0, | 174 | (void *)NULL, (void *)NULL); |
| 207 | (void *)0, | ||
| 208 | (void *)0, | ||
| 209 | (void *)0, | ||
| 210 | (void *)0, | ||
| 211 | (void *)0, | ||
| 212 | (void *)0, | ||
| 213 | (void *)0, | ||
| 214 | (void *)0, | ||
| 215 | (void *)0, | ||
| 216 | (void *)0); | ||
| 217 | } | 175 | } |
| 218 | |||
| 219 | #else | 176 | #else |
| 220 | #define xlog_trace_loggrant(log,tic,string) | 177 | #define xlog_trace_loggrant(log,tic,string) |
| 221 | #define xlog_trace_iclog(iclog,state) | 178 | #define xlog_trace_iclog(iclog,state) |
| @@ -252,11 +209,6 @@ xfs_log_done(xfs_mount_t *mp, | |||
| 252 | xlog_ticket_t *ticket = (xfs_log_ticket_t) xtic; | 209 | xlog_ticket_t *ticket = (xfs_log_ticket_t) xtic; |
| 253 | xfs_lsn_t lsn = 0; | 210 | xfs_lsn_t lsn = 0; |
| 254 | 211 | ||
| 255 | #if defined(DEBUG) || defined(XLOG_NOLOG) | ||
| 256 | if (!xlog_debug && xlog_target == log->l_targ) | ||
| 257 | return 0; | ||
| 258 | #endif | ||
| 259 | |||
| 260 | if (XLOG_FORCED_SHUTDOWN(log) || | 212 | if (XLOG_FORCED_SHUTDOWN(log) || |
| 261 | /* | 213 | /* |
| 262 | * If nothing was ever written, don't write out commit record. | 214 | * If nothing was ever written, don't write out commit record. |
| @@ -312,33 +264,28 @@ xfs_log_done(xfs_mount_t *mp, | |||
| 312 | * semaphore. | 264 | * semaphore. |
| 313 | */ | 265 | */ |
| 314 | int | 266 | int |
| 315 | xfs_log_force(xfs_mount_t *mp, | 267 | _xfs_log_force( |
| 316 | xfs_lsn_t lsn, | 268 | xfs_mount_t *mp, |
| 317 | uint flags) | 269 | xfs_lsn_t lsn, |
| 270 | uint flags, | ||
| 271 | int *log_flushed) | ||
| 318 | { | 272 | { |
| 319 | int rval; | 273 | xlog_t *log = mp->m_log; |
| 320 | xlog_t *log = mp->m_log; | 274 | int dummy; |
| 321 | 275 | ||
| 322 | #if defined(DEBUG) || defined(XLOG_NOLOG) | 276 | if (!log_flushed) |
| 323 | if (!xlog_debug && xlog_target == log->l_targ) | 277 | log_flushed = &dummy; |
| 324 | return 0; | ||
| 325 | #endif | ||
| 326 | 278 | ||
| 327 | ASSERT(flags & XFS_LOG_FORCE); | 279 | ASSERT(flags & XFS_LOG_FORCE); |
| 328 | 280 | ||
| 329 | XFS_STATS_INC(xs_log_force); | 281 | XFS_STATS_INC(xs_log_force); |
| 330 | 282 | ||
| 331 | if ((log->l_flags & XLOG_IO_ERROR) == 0) { | 283 | if (log->l_flags & XLOG_IO_ERROR) |
| 332 | if (lsn == 0) | 284 | return XFS_ERROR(EIO); |
| 333 | rval = xlog_state_sync_all(log, flags); | 285 | if (lsn == 0) |
| 334 | else | 286 | return xlog_state_sync_all(log, flags, log_flushed); |
| 335 | rval = xlog_state_sync(log, lsn, flags); | 287 | else |
| 336 | } else { | 288 | return xlog_state_sync(log, lsn, flags, log_flushed); |
| 337 | rval = XFS_ERROR(EIO); | ||
| 338 | } | ||
| 339 | |||
| 340 | return rval; | ||
| 341 | |||
| 342 | } /* xfs_log_force */ | 289 | } /* xfs_log_force */ |
| 343 | 290 | ||
| 344 | /* | 291 | /* |
| @@ -356,10 +303,6 @@ xfs_log_notify(xfs_mount_t *mp, /* mount of partition */ | |||
| 356 | xlog_in_core_t *iclog = (xlog_in_core_t *)iclog_hndl; | 303 | xlog_in_core_t *iclog = (xlog_in_core_t *)iclog_hndl; |
| 357 | int abortflg, spl; | 304 | int abortflg, spl; |
| 358 | 305 | ||
| 359 | #if defined(DEBUG) || defined(XLOG_NOLOG) | ||
| 360 | if (!xlog_debug && xlog_target == log->l_targ) | ||
| 361 | return 0; | ||
| 362 | #endif | ||
| 363 | cb->cb_next = NULL; | 306 | cb->cb_next = NULL; |
| 364 | spl = LOG_LOCK(log); | 307 | spl = LOG_LOCK(log); |
| 365 | abortflg = (iclog->ic_state & XLOG_STATE_IOERROR); | 308 | abortflg = (iclog->ic_state & XLOG_STATE_IOERROR); |
| @@ -410,13 +353,8 @@ xfs_log_reserve(xfs_mount_t *mp, | |||
| 410 | { | 353 | { |
| 411 | xlog_t *log = mp->m_log; | 354 | xlog_t *log = mp->m_log; |
| 412 | xlog_ticket_t *internal_ticket; | 355 | xlog_ticket_t *internal_ticket; |
| 413 | int retval; | 356 | int retval = 0; |
| 414 | 357 | ||
| 415 | #if defined(DEBUG) || defined(XLOG_NOLOG) | ||
| 416 | if (!xlog_debug && xlog_target == log->l_targ) | ||
| 417 | return 0; | ||
| 418 | #endif | ||
| 419 | retval = 0; | ||
| 420 | ASSERT(client == XFS_TRANSACTION || client == XFS_LOG); | 358 | ASSERT(client == XFS_TRANSACTION || client == XFS_LOG); |
| 421 | ASSERT((flags & XFS_LOG_NOSLEEP) == 0); | 359 | ASSERT((flags & XFS_LOG_NOSLEEP) == 0); |
| 422 | 360 | ||
| @@ -478,12 +416,6 @@ xfs_log_mount(xfs_mount_t *mp, | |||
| 478 | 416 | ||
| 479 | mp->m_log = xlog_alloc_log(mp, log_target, blk_offset, num_bblks); | 417 | mp->m_log = xlog_alloc_log(mp, log_target, blk_offset, num_bblks); |
| 480 | 418 | ||
| 481 | #if defined(DEBUG) || defined(XLOG_NOLOG) | ||
| 482 | if (!xlog_debug) { | ||
| 483 | cmn_err(CE_NOTE, "log dev: %s", XFS_BUFTARG_NAME(log_target)); | ||
| 484 | return 0; | ||
| 485 | } | ||
| 486 | #endif | ||
| 487 | /* | 419 | /* |
| 488 | * skip log recovery on a norecovery mount. pretend it all | 420 | * skip log recovery on a norecovery mount. pretend it all |
| 489 | * just worked. | 421 | * just worked. |
| @@ -587,11 +519,6 @@ xfs_log_unmount_write(xfs_mount_t *mp) | |||
| 587 | __uint32_t pad2; /* may as well make it 64 bits */ | 519 | __uint32_t pad2; /* may as well make it 64 bits */ |
| 588 | } magic = { XLOG_UNMOUNT_TYPE, 0, 0 }; | 520 | } magic = { XLOG_UNMOUNT_TYPE, 0, 0 }; |
| 589 | 521 | ||
| 590 | #if defined(DEBUG) || defined(XLOG_NOLOG) | ||
| 591 | if (!xlog_debug && xlog_target == log->l_targ) | ||
| 592 | return 0; | ||
| 593 | #endif | ||
| 594 | |||
| 595 | /* | 522 | /* |
| 596 | * Don't write out unmount record on read-only mounts. | 523 | * Don't write out unmount record on read-only mounts. |
| 597 | * Or, if we are doing a forced umount (typically because of IO errors). | 524 | * Or, if we are doing a forced umount (typically because of IO errors). |
| @@ -718,12 +645,6 @@ xfs_log_write(xfs_mount_t * mp, | |||
| 718 | int error; | 645 | int error; |
| 719 | xlog_t *log = mp->m_log; | 646 | xlog_t *log = mp->m_log; |
| 720 | 647 | ||
| 721 | #if defined(DEBUG) || defined(XLOG_NOLOG) | ||
| 722 | if (!xlog_debug && xlog_target == log->l_targ) { | ||
| 723 | *start_lsn = 0; | ||
| 724 | return 0; | ||
| 725 | } | ||
| 726 | #endif | ||
| 727 | if (XLOG_FORCED_SHUTDOWN(log)) | 648 | if (XLOG_FORCED_SHUTDOWN(log)) |
| 728 | return XFS_ERROR(EIO); | 649 | return XFS_ERROR(EIO); |
| 729 | 650 | ||
| @@ -743,11 +664,6 @@ xfs_log_move_tail(xfs_mount_t *mp, | |||
| 743 | int need_bytes, free_bytes, cycle, bytes; | 664 | int need_bytes, free_bytes, cycle, bytes; |
| 744 | SPLDECL(s); | 665 | SPLDECL(s); |
| 745 | 666 | ||
| 746 | #if defined(DEBUG) || defined(XLOG_NOLOG) | ||
| 747 | if (!xlog_debug && xlog_target == log->l_targ) | ||
| 748 | return; | ||
| 749 | #endif | ||
| 750 | /* XXXsup tmp */ | ||
| 751 | if (XLOG_FORCED_SHUTDOWN(log)) | 667 | if (XLOG_FORCED_SHUTDOWN(log)) |
| 752 | return; | 668 | return; |
| 753 | ASSERT(!XFS_FORCED_SHUTDOWN(mp)); | 669 | ASSERT(!XFS_FORCED_SHUTDOWN(mp)); |
| @@ -1034,51 +950,22 @@ xlog_get_iclog_buffer_size(xfs_mount_t *mp, | |||
| 1034 | int size; | 950 | int size; |
| 1035 | int xhdrs; | 951 | int xhdrs; |
| 1036 | 952 | ||
| 1037 | #if defined(DEBUG) || defined(XLOG_NOLOG) | 953 | if (mp->m_logbufs <= 0) { |
| 1038 | /* | 954 | if (xfs_physmem <= btoc(128*1024*1024)) { |
| 1039 | * When logbufs == 0, someone has disabled the log from the FSTAB | 955 | log->l_iclog_bufs = XLOG_MIN_ICLOGS; |
| 1040 | * file. This is not a documented feature. We need to set xlog_debug | 956 | } else if (xfs_physmem <= btoc(400*1024*1024)) { |
| 1041 | * to zero (this deactivates the log) and set xlog_target to the | 957 | log->l_iclog_bufs = XLOG_MED_ICLOGS; |
| 1042 | * appropriate device. Only one filesystem may be affected as such | 958 | } else { /* 256K with 32K bufs */ |
| 1043 | * since this is just a performance hack to test what we might be able | 959 | log->l_iclog_bufs = XLOG_MAX_ICLOGS; |
| 1044 | * to get if the log were not present. | ||
| 1045 | */ | ||
| 1046 | if (mp->m_logbufs == 0) { | ||
| 1047 | xlog_debug = 0; | ||
| 1048 | xlog_target = log->l_targ; | ||
| 1049 | log->l_iclog_bufs = XLOG_MIN_ICLOGS; | ||
| 1050 | } else | ||
| 1051 | #endif | ||
| 1052 | { | ||
| 1053 | /* | ||
| 1054 | * This is the normal path. If m_logbufs == -1, then the | ||
| 1055 | * admin has chosen to use the system defaults for logbuffers. | ||
| 1056 | */ | ||
| 1057 | if (mp->m_logbufs == -1) { | ||
| 1058 | if (xfs_physmem <= btoc(128*1024*1024)) { | ||
| 1059 | log->l_iclog_bufs = XLOG_MIN_ICLOGS; | ||
| 1060 | } else if (xfs_physmem <= btoc(400*1024*1024)) { | ||
| 1061 | log->l_iclog_bufs = XLOG_MED_ICLOGS; | ||
| 1062 | } else { | ||
| 1063 | /* 256K with 32K bufs */ | ||
| 1064 | log->l_iclog_bufs = XLOG_MAX_ICLOGS; | ||
| 1065 | } | ||
| 1066 | } else | ||
| 1067 | log->l_iclog_bufs = mp->m_logbufs; | ||
| 1068 | |||
| 1069 | #if defined(DEBUG) || defined(XLOG_NOLOG) | ||
| 1070 | /* We are reactivating a filesystem after it was inactive */ | ||
| 1071 | if (log->l_targ == xlog_target) { | ||
| 1072 | xlog_target = NULL; | ||
| 1073 | xlog_debug = 1; | ||
| 1074 | } | 960 | } |
| 1075 | #endif | 961 | } else { |
| 962 | log->l_iclog_bufs = mp->m_logbufs; | ||
| 1076 | } | 963 | } |
| 1077 | 964 | ||
| 1078 | /* | 965 | /* |
| 1079 | * Buffer size passed in from mount system call. | 966 | * Buffer size passed in from mount system call. |
| 1080 | */ | 967 | */ |
| 1081 | if (mp->m_logbsize != -1) { | 968 | if (mp->m_logbsize > 0) { |
| 1082 | size = log->l_iclog_size = mp->m_logbsize; | 969 | size = log->l_iclog_size = mp->m_logbsize; |
| 1083 | log->l_iclog_size_log = 0; | 970 | log->l_iclog_size_log = 0; |
| 1084 | while (size != 1) { | 971 | while (size != 1) { |
| @@ -1101,7 +988,7 @@ xlog_get_iclog_buffer_size(xfs_mount_t *mp, | |||
| 1101 | log->l_iclog_hsize = BBSIZE; | 988 | log->l_iclog_hsize = BBSIZE; |
| 1102 | log->l_iclog_heads = 1; | 989 | log->l_iclog_heads = 1; |
| 1103 | } | 990 | } |
| 1104 | return; | 991 | goto done; |
| 1105 | } | 992 | } |
| 1106 | 993 | ||
| 1107 | /* | 994 | /* |
| @@ -1128,7 +1015,7 @@ xlog_get_iclog_buffer_size(xfs_mount_t *mp, | |||
| 1128 | if (mp->m_sb.sb_blocksize >= 16*1024) { | 1015 | if (mp->m_sb.sb_blocksize >= 16*1024) { |
| 1129 | log->l_iclog_size = XLOG_BIG_RECORD_BSIZE; | 1016 | log->l_iclog_size = XLOG_BIG_RECORD_BSIZE; |
| 1130 | log->l_iclog_size_log = XLOG_BIG_RECORD_BSHIFT; | 1017 | log->l_iclog_size_log = XLOG_BIG_RECORD_BSHIFT; |
| 1131 | if (mp->m_logbufs == -1) { | 1018 | if (mp->m_logbufs <= 0) { |
| 1132 | switch (mp->m_sb.sb_blocksize) { | 1019 | switch (mp->m_sb.sb_blocksize) { |
| 1133 | case 16*1024: /* 16 KB */ | 1020 | case 16*1024: /* 16 KB */ |
| 1134 | log->l_iclog_bufs = 3; | 1021 | log->l_iclog_bufs = 3; |
| @@ -1145,6 +1032,12 @@ xlog_get_iclog_buffer_size(xfs_mount_t *mp, | |||
| 1145 | } | 1032 | } |
| 1146 | } | 1033 | } |
| 1147 | } | 1034 | } |
| 1035 | |||
| 1036 | done: /* are we being asked to make the sizes selected above visible? */ | ||
| 1037 | if (mp->m_logbufs == 0) | ||
| 1038 | mp->m_logbufs = log->l_iclog_bufs; | ||
| 1039 | if (mp->m_logbsize == 0) | ||
| 1040 | mp->m_logbsize = log->l_iclog_size; | ||
| 1148 | } /* xlog_get_iclog_buffer_size */ | 1041 | } /* xlog_get_iclog_buffer_size */ |
| 1149 | 1042 | ||
| 1150 | 1043 | ||
| @@ -1467,14 +1360,13 @@ xlog_sync(xlog_t *log, | |||
| 1467 | XFS_BUF_BUSY(bp); | 1360 | XFS_BUF_BUSY(bp); |
| 1468 | XFS_BUF_ASYNC(bp); | 1361 | XFS_BUF_ASYNC(bp); |
| 1469 | /* | 1362 | /* |
| 1470 | * Do a disk write cache flush for the log block. | 1363 | * Do an ordered write for the log block. |
| 1471 | * This is a bit of a sledgehammer, it would be better | 1364 | * |
| 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 | 1365 | * 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 | 1366 | * case, but do it anyways to be safe -AK |
| 1475 | */ | 1367 | */ |
| 1476 | if (!(log->l_mp->m_flags & XFS_MOUNT_NOLOGFLUSH)) | 1368 | if (log->l_mp->m_flags & XFS_MOUNT_BARRIER) |
| 1477 | XFS_BUF_FLUSH(bp); | 1369 | XFS_BUF_ORDERED(bp); |
| 1478 | 1370 | ||
| 1479 | ASSERT(XFS_BUF_ADDR(bp) <= log->l_logBBsize-1); | 1371 | ASSERT(XFS_BUF_ADDR(bp) <= log->l_logBBsize-1); |
| 1480 | ASSERT(XFS_BUF_ADDR(bp) + BTOBB(count) <= log->l_logBBsize); | 1372 | ASSERT(XFS_BUF_ADDR(bp) + BTOBB(count) <= log->l_logBBsize); |
| @@ -1505,8 +1397,8 @@ xlog_sync(xlog_t *log, | |||
| 1505 | XFS_BUF_SET_FSPRIVATE(bp, iclog); | 1397 | XFS_BUF_SET_FSPRIVATE(bp, iclog); |
| 1506 | XFS_BUF_BUSY(bp); | 1398 | XFS_BUF_BUSY(bp); |
| 1507 | XFS_BUF_ASYNC(bp); | 1399 | XFS_BUF_ASYNC(bp); |
| 1508 | if (!(log->l_mp->m_flags & XFS_MOUNT_NOLOGFLUSH)) | 1400 | if (log->l_mp->m_flags & XFS_MOUNT_BARRIER) |
| 1509 | XFS_BUF_FLUSH(bp); | 1401 | XFS_BUF_ORDERED(bp); |
| 1510 | dptr = XFS_BUF_PTR(bp); | 1402 | dptr = XFS_BUF_PTR(bp); |
| 1511 | /* | 1403 | /* |
| 1512 | * Bump the cycle numbers at the start of each block | 1404 | * Bump the cycle numbers at the start of each block |
| @@ -2951,7 +2843,7 @@ xlog_state_switch_iclogs(xlog_t *log, | |||
| 2951 | * not in the active nor dirty state. | 2843 | * not in the active nor dirty state. |
| 2952 | */ | 2844 | */ |
| 2953 | STATIC int | 2845 | STATIC int |
| 2954 | xlog_state_sync_all(xlog_t *log, uint flags) | 2846 | xlog_state_sync_all(xlog_t *log, uint flags, int *log_flushed) |
| 2955 | { | 2847 | { |
| 2956 | xlog_in_core_t *iclog; | 2848 | xlog_in_core_t *iclog; |
| 2957 | xfs_lsn_t lsn; | 2849 | xfs_lsn_t lsn; |
| @@ -3000,6 +2892,7 @@ xlog_state_sync_all(xlog_t *log, uint flags) | |||
| 3000 | 2892 | ||
| 3001 | if (xlog_state_release_iclog(log, iclog)) | 2893 | if (xlog_state_release_iclog(log, iclog)) |
| 3002 | return XFS_ERROR(EIO); | 2894 | return XFS_ERROR(EIO); |
| 2895 | *log_flushed = 1; | ||
| 3003 | s = LOG_LOCK(log); | 2896 | s = LOG_LOCK(log); |
| 3004 | if (INT_GET(iclog->ic_header.h_lsn, ARCH_CONVERT) == lsn && | 2897 | if (INT_GET(iclog->ic_header.h_lsn, ARCH_CONVERT) == lsn && |
| 3005 | iclog->ic_state != XLOG_STATE_DIRTY) | 2898 | iclog->ic_state != XLOG_STATE_DIRTY) |
| @@ -3043,6 +2936,7 @@ maybe_sleep: | |||
| 3043 | */ | 2936 | */ |
| 3044 | if (iclog->ic_state & XLOG_STATE_IOERROR) | 2937 | if (iclog->ic_state & XLOG_STATE_IOERROR) |
| 3045 | return XFS_ERROR(EIO); | 2938 | return XFS_ERROR(EIO); |
| 2939 | *log_flushed = 1; | ||
| 3046 | 2940 | ||
| 3047 | } else { | 2941 | } else { |
| 3048 | 2942 | ||
| @@ -3068,7 +2962,8 @@ no_sleep: | |||
| 3068 | int | 2962 | int |
| 3069 | xlog_state_sync(xlog_t *log, | 2963 | xlog_state_sync(xlog_t *log, |
| 3070 | xfs_lsn_t lsn, | 2964 | xfs_lsn_t lsn, |
| 3071 | uint flags) | 2965 | uint flags, |
| 2966 | int *log_flushed) | ||
| 3072 | { | 2967 | { |
| 3073 | xlog_in_core_t *iclog; | 2968 | xlog_in_core_t *iclog; |
| 3074 | int already_slept = 0; | 2969 | int already_slept = 0; |
| @@ -3120,6 +3015,7 @@ try_again: | |||
| 3120 | XFS_STATS_INC(xs_log_force_sleep); | 3015 | XFS_STATS_INC(xs_log_force_sleep); |
| 3121 | sv_wait(&iclog->ic_prev->ic_writesema, PSWP, | 3016 | sv_wait(&iclog->ic_prev->ic_writesema, PSWP, |
| 3122 | &log->l_icloglock, s); | 3017 | &log->l_icloglock, s); |
| 3018 | *log_flushed = 1; | ||
| 3123 | already_slept = 1; | 3019 | already_slept = 1; |
| 3124 | goto try_again; | 3020 | goto try_again; |
| 3125 | } else { | 3021 | } else { |
| @@ -3128,6 +3024,7 @@ try_again: | |||
| 3128 | LOG_UNLOCK(log, s); | 3024 | LOG_UNLOCK(log, s); |
| 3129 | if (xlog_state_release_iclog(log, iclog)) | 3025 | if (xlog_state_release_iclog(log, iclog)) |
| 3130 | return XFS_ERROR(EIO); | 3026 | return XFS_ERROR(EIO); |
| 3027 | *log_flushed = 1; | ||
| 3131 | s = LOG_LOCK(log); | 3028 | s = LOG_LOCK(log); |
| 3132 | } | 3029 | } |
| 3133 | } | 3030 | } |
| @@ -3152,6 +3049,7 @@ try_again: | |||
| 3152 | */ | 3049 | */ |
| 3153 | if (iclog->ic_state & XLOG_STATE_IOERROR) | 3050 | if (iclog->ic_state & XLOG_STATE_IOERROR) |
| 3154 | return XFS_ERROR(EIO); | 3051 | return XFS_ERROR(EIO); |
| 3052 | *log_flushed = 1; | ||
| 3155 | } else { /* just return */ | 3053 | } else { /* just return */ |
| 3156 | LOG_UNLOCK(log, s); | 3054 | LOG_UNLOCK(log, s); |
| 3157 | } | 3055 | } |
| @@ -3392,7 +3290,7 @@ xlog_ticket_get(xlog_t *log, | |||
| 3392 | * | 3290 | * |
| 3393 | ****************************************************************************** | 3291 | ****************************************************************************** |
| 3394 | */ | 3292 | */ |
| 3395 | #if defined(DEBUG) && !defined(XLOG_NOLOG) | 3293 | #if defined(DEBUG) |
| 3396 | /* | 3294 | /* |
| 3397 | * Make sure that the destination ptr is within the valid data region of | 3295 | * Make sure that the destination ptr is within the valid data region of |
| 3398 | * one of the iclogs. This uses backup pointers stored in a different | 3296 | * one of the iclogs. This uses backup pointers stored in a different |
| @@ -3533,7 +3431,9 @@ xlog_verify_iclog(xlog_t *log, | |||
| 3533 | } | 3431 | } |
| 3534 | } | 3432 | } |
| 3535 | if (clientid != XFS_TRANSACTION && clientid != XFS_LOG) | 3433 | if (clientid != XFS_TRANSACTION && clientid != XFS_LOG) |
| 3536 | cmn_err(CE_WARN, "xlog_verify_iclog: invalid clientid %d op 0x%p offset 0x%x", clientid, ophead, field_offset); | 3434 | cmn_err(CE_WARN, "xlog_verify_iclog: " |
| 3435 | "invalid clientid %d op 0x%p offset 0x%lx", | ||
| 3436 | clientid, ophead, (unsigned long)field_offset); | ||
| 3537 | 3437 | ||
| 3538 | /* check length */ | 3438 | /* check length */ |
| 3539 | field_offset = (__psint_t) | 3439 | field_offset = (__psint_t) |
| @@ -3554,7 +3454,7 @@ xlog_verify_iclog(xlog_t *log, | |||
| 3554 | ptr += sizeof(xlog_op_header_t) + op_len; | 3454 | ptr += sizeof(xlog_op_header_t) + op_len; |
| 3555 | } | 3455 | } |
| 3556 | } /* xlog_verify_iclog */ | 3456 | } /* xlog_verify_iclog */ |
| 3557 | #endif /* DEBUG && !XLOG_NOLOG */ | 3457 | #endif |
| 3558 | 3458 | ||
| 3559 | /* | 3459 | /* |
| 3560 | * Mark all iclogs IOERROR. LOG_LOCK is held by the caller. | 3460 | * Mark all iclogs IOERROR. LOG_LOCK is held by the caller. |
| @@ -3604,6 +3504,7 @@ xfs_log_force_umount( | |||
| 3604 | xlog_ticket_t *tic; | 3504 | xlog_ticket_t *tic; |
| 3605 | xlog_t *log; | 3505 | xlog_t *log; |
| 3606 | int retval; | 3506 | int retval; |
| 3507 | int dummy; | ||
| 3607 | SPLDECL(s); | 3508 | SPLDECL(s); |
| 3608 | SPLDECL(s2); | 3509 | SPLDECL(s2); |
| 3609 | 3510 | ||
| @@ -3682,7 +3583,7 @@ xfs_log_force_umount( | |||
| 3682 | * Force the incore logs to disk before shutting the | 3583 | * Force the incore logs to disk before shutting the |
| 3683 | * log down completely. | 3584 | * log down completely. |
| 3684 | */ | 3585 | */ |
| 3685 | xlog_state_sync_all(log, XFS_LOG_FORCE|XFS_LOG_SYNC); | 3586 | xlog_state_sync_all(log, XFS_LOG_FORCE|XFS_LOG_SYNC, &dummy); |
| 3686 | s2 = LOG_LOCK(log); | 3587 | s2 = LOG_LOCK(log); |
| 3687 | retval = xlog_state_ioerror(log); | 3588 | retval = xlog_state_ioerror(log); |
| 3688 | LOG_UNLOCK(log, s2); | 3589 | LOG_UNLOCK(log, s2); |
