From 312de84d111ce55918f093cb14671b5a1c4e7ab4 Mon Sep 17 00:00:00 2001 From: Matthew Dillon Date: Mon, 30 Jun 2008 00:03:55 +0000 Subject: [PATCH] HAMMER 59D/Many: Stabilization pass * Fix a panic that occurs when the crash recovery undo space is larger then conveniently fits in the buffer cache. * Fix a bug in the truncation code (detected by fsx). The bug was related to moving an inode from one flush group to another (which itself was done to fix a bug related to blowing out the buffer cache). --- sys/vfs/hammer/hammer_inode.c | 33 +++++++++++++++++++++------------ sys/vfs/hammer/hammer_object.c | 8 ++++---- sys/vfs/hammer/hammer_prune.c | 7 ++++++- sys/vfs/hammer/hammer_recover.c | 13 +++++++++++-- 4 files changed, 42 insertions(+), 19 deletions(-) diff --git a/sys/vfs/hammer/hammer_inode.c b/sys/vfs/hammer/hammer_inode.c index 5452aa63e2..f5f06054a0 100644 --- a/sys/vfs/hammer/hammer_inode.c +++ b/sys/vfs/hammer/hammer_inode.c @@ -31,7 +31,7 @@ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $DragonFly: src/sys/vfs/hammer/hammer_inode.c,v 1.88 2008/06/29 07:50:40 dillon Exp $ + * $DragonFly: src/sys/vfs/hammer/hammer_inode.c,v 1.89 2008/06/30 00:03:55 dillon Exp $ */ #include "hammer.h" @@ -1278,9 +1278,14 @@ hammer_flush_inode_core(hammer_inode_t ip, int flags) /* * Figure out how many in-memory records we can actually flush * (not including inode meta-data, buffers, etc). + * + * Do not add new records to the flush if this is a recursion or + * if we must still complete a flush from the previous flush cycle. */ if (flags & HAMMER_FLUSH_RECURSION) { go_count = 1; + } else if (ip->flags & HAMMER_INODE_WOULDBLOCK) { + go_count = 1; } else { go_count = RB_SCAN(hammer_rec_rb_tree, &ip->rec_tree, NULL, hammer_setup_child_callback, NULL); @@ -1327,15 +1332,19 @@ hammer_flush_inode_core(hammer_inode_t ip, int flags) * * NOTE: If a truncation from a previous flush cycle had to be * continued into this one, the TRUNCATED flag will still be - * set in sync_flags. + * set in sync_flags as will WOULDBLOCK. When this occurs + * we CANNOT safely integrate a new truncation from the front-end + * because there may be data records in-memory assigned a flush + * state from the previous cycle that are supposed to be flushed + * before the next frontend truncation. */ - if (ip->flags & HAMMER_INODE_TRUNCATED) { - if (ip->sync_flags & HAMMER_INODE_TRUNCATED) { - if (ip->sync_trunc_off > ip->trunc_off) - ip->sync_trunc_off = ip->trunc_off; - } else { - ip->sync_trunc_off = ip->trunc_off; - } + if ((ip->flags & (HAMMER_INODE_TRUNCATED | HAMMER_INODE_WOULDBLOCK)) == + HAMMER_INODE_TRUNCATED) { + KKASSERT((ip->sync_flags & HAMMER_INODE_TRUNCATED) == 0); + ip->sync_trunc_off = ip->trunc_off; + ip->trunc_off = 0x7FFFFFFFFFFFFFFFLL; + ip->flags &= ~HAMMER_INODE_TRUNCATED; + ip->sync_flags |= HAMMER_INODE_TRUNCATED; /* * The save_trunc_off used to cache whether the B-Tree @@ -1346,11 +1355,11 @@ hammer_flush_inode_core(hammer_inode_t ip, int flags) if (ip->save_trunc_off > ip->sync_trunc_off) ip->save_trunc_off = ip->sync_trunc_off; } - ip->sync_flags |= (ip->flags & HAMMER_INODE_MODMASK); + ip->sync_flags |= (ip->flags & HAMMER_INODE_MODMASK & + ~HAMMER_INODE_TRUNCATED); ip->sync_ino_leaf = ip->ino_leaf; ip->sync_ino_data = ip->ino_data; - ip->trunc_off = 0x7FFFFFFFFFFFFFFFLL; - ip->flags &= ~HAMMER_INODE_MODMASK; + ip->flags &= ~HAMMER_INODE_MODMASK | HAMMER_INODE_TRUNCATED; #ifdef DEBUG_TRUNCATE if ((ip->sync_flags & HAMMER_INODE_TRUNCATED) && ip == HammerTruncIp) kprintf("truncateS %016llx\n", ip->sync_trunc_off); diff --git a/sys/vfs/hammer/hammer_object.c b/sys/vfs/hammer/hammer_object.c index 5670a1c28d..57dbe1539d 100644 --- a/sys/vfs/hammer/hammer_object.c +++ b/sys/vfs/hammer/hammer_object.c @@ -31,7 +31,7 @@ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $DragonFly: src/sys/vfs/hammer/hammer_object.c,v 1.78 2008/06/28 18:10:55 dillon Exp $ + * $DragonFly: src/sys/vfs/hammer/hammer_object.c,v 1.79 2008/06/30 00:03:55 dillon Exp $ */ #include "hammer.h" @@ -39,7 +39,7 @@ static int hammer_mem_add(hammer_record_t record); static int hammer_mem_lookup(hammer_cursor_t cursor); static int hammer_mem_first(hammer_cursor_t cursor); -static int hammer_rec_trunc_callback(hammer_record_t record, +static int hammer_frontend_trunc_callback(hammer_record_t record, void *data __unused); static int hammer_record_needs_overwrite_delete(hammer_record_t record); @@ -933,12 +933,12 @@ hammer_ip_frontend_trunc(struct hammer_inode *ip, off_t file_size) } info.trunc_off = file_size; hammer_rec_rb_tree_RB_SCAN(&ip->rec_tree, hammer_rec_trunc_cmp, - hammer_rec_trunc_callback, &info); + hammer_frontend_trunc_callback, &info); return(0); } static int -hammer_rec_trunc_callback(hammer_record_t record, void *data __unused) +hammer_frontend_trunc_callback(hammer_record_t record, void *data __unused) { if (record->flags & HAMMER_RECF_DELETED_FE) return(0); diff --git a/sys/vfs/hammer/hammer_prune.c b/sys/vfs/hammer/hammer_prune.c index 47f86dece4..f55fe79574 100644 --- a/sys/vfs/hammer/hammer_prune.c +++ b/sys/vfs/hammer/hammer_prune.c @@ -31,7 +31,7 @@ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $DragonFly: src/sys/vfs/hammer/hammer_prune.c,v 1.9 2008/06/27 20:56:59 dillon Exp $ + * $DragonFly: src/sys/vfs/hammer/hammer_prune.c,v 1.10 2008/06/30 00:03:55 dillon Exp $ */ #include "hammer.h" @@ -303,6 +303,11 @@ prune_check_nlinks(hammer_cursor_t cursor, hammer_btree_leaf_elm_t elm) * accesses from "now" to the first snapshot softlink continue to * be fine-grained. * + * NOTE: It also looks like there's a bug in the removed code. It is believed + * that create_tid can sometimes get set to 0xffffffffffffffff. Just as + * well we no longer try to do this fancy shit. Probably the attempt to + * correct the rhb is blowing up the cursor's indexing or addressing mapping. + * * Align the record to cover any gaps created through the deletion of * records within the pruning space. If we were to just delete the records * there would be gaps which in turn would cause a snapshot that is NOT on diff --git a/sys/vfs/hammer/hammer_recover.c b/sys/vfs/hammer/hammer_recover.c index 63efc7b0b9..3a14257119 100644 --- a/sys/vfs/hammer/hammer_recover.c +++ b/sys/vfs/hammer/hammer_recover.c @@ -31,7 +31,7 @@ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $DragonFly: src/sys/vfs/hammer/hammer_recover.c,v 1.27 2008/06/28 23:50:37 dillon Exp $ + * $DragonFly: src/sys/vfs/hammer/hammer_recover.c,v 1.28 2008/06/30 00:03:55 dillon Exp $ */ #include "hammer.h" @@ -158,9 +158,18 @@ hammer_recover(hammer_mount_t hmp, hammer_volume_t root_volume) bytes -= tail->tail_size; /* - * If too many dirty buffers have built up + * If too many dirty buffers have built up we have to flush'm + * out. As long as we do not flush out the volume header + * a crash here should not cause any problems. + * + * buffer must be released so the flush can assert that + * all buffers are idle. */ if (hammer_flusher_meta_limit(hmp)) { + if (buffer) { + hammer_rel_buffer(buffer, 0); + buffer = NULL; + } if (hmp->ronly == 0) { hammer_recover_flush_buffers(hmp, root_volume, 0); -- 2.11.4.GIT