diff options
author | Neil Perrin <Neil.Perrin@Sun.COM> | 2009-03-06 10:47:00 -0700 |
---|---|---|
committer | Neil Perrin <Neil.Perrin@Sun.COM> | 2009-03-06 10:47:00 -0700 |
commit | 3589c4f01c20349ca65899d209cdc0c17a641433 (patch) | |
tree | faa56e5ffd2d8a7405aef968bf4822b2248cf647 /usr/src | |
parent | 13651adbc76509937e310f6a6a515b59ff7bbafd (diff) | |
download | illumos-gate-3589c4f01c20349ca65899d209cdc0c17a641433.tar.gz |
6462803 zfs snapshot -r failed because filesystem was busy
Diffstat (limited to 'usr/src')
-rw-r--r-- | usr/src/cmd/zdb/zdb_il.c | 10 | ||||
-rw-r--r-- | usr/src/grub/grub-0.97/stage2/zfs-include/zil.h | 12 | ||||
-rw-r--r-- | usr/src/uts/common/fs/zfs/sys/zil.h | 10 | ||||
-rw-r--r-- | usr/src/uts/common/fs/zfs/zil.c | 57 |
4 files changed, 57 insertions, 32 deletions
diff --git a/usr/src/cmd/zdb/zdb_il.c b/usr/src/cmd/zdb/zdb_il.c index 02d35a0503..cc08ef5148 100644 --- a/usr/src/cmd/zdb/zdb_il.c +++ b/usr/src/cmd/zdb/zdb_il.c @@ -19,12 +19,10 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ -#pragma ident "%Z%%M% %I% %E% SMI" - /* * Print intent log header and statistics. */ @@ -345,8 +343,10 @@ dump_intent_log(zilog_t *zilog) if (zh->zh_log.blk_birth == 0 || verbose < 2) return; - (void) printf("\n ZIL header: claim_txg %llu, seq %llu\n", - (u_longlong_t)zh->zh_claim_txg, (u_longlong_t)zh->zh_replay_seq); + (void) printf("\n ZIL header: claim_txg %llu, claim_seq %llu", + (u_longlong_t)zh->zh_claim_txg, (u_longlong_t)zh->zh_claim_seq); + (void) printf(" replay_seq %llu, flags 0x%llx\n", + (u_longlong_t)zh->zh_replay_seq, (u_longlong_t)zh->zh_flags); if (verbose >= 4) print_log_bp(&zh->zh_log, "\n\tfirst block: "); diff --git a/usr/src/grub/grub-0.97/stage2/zfs-include/zil.h b/usr/src/grub/grub-0.97/stage2/zfs-include/zil.h index 11ab4b5a3a..87c1dc57f1 100644 --- a/usr/src/grub/grub-0.97/stage2/zfs-include/zil.h +++ b/usr/src/grub/grub-0.97/stage2/zfs-include/zil.h @@ -17,15 +17,13 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #ifndef _SYS_ZIL_H #define _SYS_ZIL_H -#pragma ident "%Z%%M% %I% %E% SMI" - /* * Intent log format: * @@ -47,7 +45,13 @@ typedef struct zil_header { uint64_t zh_replay_seq; /* highest replayed sequence number */ blkptr_t zh_log; /* log chain */ uint64_t zh_claim_seq; /* highest claimed sequence number */ - uint64_t zh_pad[5]; + uint64_t zh_flags; /* header flags */ + uint64_t zh_pad[4]; } zil_header_t; +/* + * zh_flags bit settings + */ +#define ZIL_REPLAY_NEEDED 0x1 /* replay needed - internal only */ + #endif /* _SYS_ZIL_H */ diff --git a/usr/src/uts/common/fs/zfs/sys/zil.h b/usr/src/uts/common/fs/zfs/sys/zil.h index b69323cfaf..d85345d86d 100644 --- a/usr/src/uts/common/fs/zfs/sys/zil.h +++ b/usr/src/uts/common/fs/zfs/sys/zil.h @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -56,10 +56,16 @@ typedef struct zil_header { uint64_t zh_replay_seq; /* highest replayed sequence number */ blkptr_t zh_log; /* log chain */ uint64_t zh_claim_seq; /* highest claimed sequence number */ - uint64_t zh_pad[5]; + uint64_t zh_flags; /* header flags */ + uint64_t zh_pad[4]; } zil_header_t; /* + * zh_flags bit settings + */ +#define ZIL_REPLAY_NEEDED 0x1 /* replay needed - internal only */ + +/* * Log block trailer - structure at the end of the header and each log block * * The zit_bt contains a zbt_cksum which for the intent log is diff --git a/usr/src/uts/common/fs/zfs/zil.c b/usr/src/uts/common/fs/zfs/zil.c index b9a373139b..2a1f82a1be 100644 --- a/usr/src/uts/common/fs/zfs/zil.c +++ b/usr/src/uts/common/fs/zfs/zil.c @@ -470,6 +470,25 @@ zil_destroy(zilog_t *zilog, boolean_t keep_first) dmu_tx_commit(tx); } +/* + * return true if the initial log block is not valid + */ +static boolean_t +zil_empty(zilog_t *zilog) +{ + const zil_header_t *zh = zilog->zl_header; + arc_buf_t *abuf = NULL; + + if (BP_IS_HOLE(&zh->zh_log)) + return (B_TRUE); + + if (zil_read_log_block(zilog, &zh->zh_log, &abuf) != 0) + return (B_TRUE); + + VERIFY(arc_buf_remove_ref(abuf, &abuf) == 1); + return (B_FALSE); +} + int zil_claim(char *osname, void *txarg) { @@ -490,6 +509,21 @@ zil_claim(char *osname, void *txarg) zh = zil_header_in_syncing_context(zilog); /* + * Record here whether the zil has any records to replay. + * If the header block pointer is null or the block points + * to the stubby then we know there are no valid log records. + * We use the header to store this state as the the zilog gets + * freed later in dmu_objset_close(). + * The flags (and the rest of the header fields) are cleared in + * zil_sync() as a result of a zil_destroy(), after replaying the log. + * + * Note, the intent log can be empty but still need the + * stubby to be claimed. + */ + if (!zil_empty(zilog)) + zh->zh_flags |= ZIL_REPLAY_NEEDED; + + /* * Claim all log blocks if we haven't already done so, and remember * the highest claimed sequence number. This ensures that if we can * read only part of the log now (e.g. due to a missing device), @@ -1313,25 +1347,6 @@ zil_free(zilog_t *zilog) } /* - * return true if the initial log block is not valid - */ -static boolean_t -zil_empty(zilog_t *zilog) -{ - const zil_header_t *zh = zilog->zl_header; - arc_buf_t *abuf = NULL; - - if (BP_IS_HOLE(&zh->zh_log)) - return (B_TRUE); - - if (zil_read_log_block(zilog, &zh->zh_log, &abuf) != 0) - return (B_TRUE); - - VERIFY(arc_buf_remove_ref(abuf, &abuf) == 1); - return (B_FALSE); -} - -/* * Open an intent log. */ zilog_t * @@ -1386,7 +1401,7 @@ zil_suspend(zilog_t *zilog) const zil_header_t *zh = zilog->zl_header; mutex_enter(&zilog->zl_lock); - if (zh->zh_claim_txg != 0) { /* unplayed log */ + if (zh->zh_flags & ZIL_REPLAY_NEEDED) { /* unplayed log */ mutex_exit(&zilog->zl_lock); return (EBUSY); } @@ -1570,7 +1585,7 @@ zil_replay(objset_t *os, void *arg, zil_replay_func_t *replay_func[TX_MAX_TYPE]) const zil_header_t *zh = zilog->zl_header; zil_replay_arg_t zr; - if (zil_empty(zilog)) { + if ((zh->zh_flags & ZIL_REPLAY_NEEDED) == 0) { zil_destroy(zilog, B_TRUE); return; } |