From: Matthew Dillon Date: Mon, 13 May 2013 03:44:32 +0000 (-0700) Subject: hammer2 - flush sequencing part 8 - stabilization pass X-Git-Tag: v3.7.0~1116 X-Git-Url: https://gitweb.dragonflybsd.org/dragonfly.git/commitdiff_plain/09dd2dfe967a49429e51b8648e17be601a369908 hammer2 - flush sequencing part 8 - stabilization pass * On this commit it appears that the cpdup / test is fully validating on remount and chain memory leaks are gone. * Remove a hack when creating a hardlink. The original directory entry is duplicated to create the invisible hardlink target in the common parent directory, but the original directory entry is then not deleted. Instead I was modifying it (which generally did not cause a delete/duplicate sequence) and then changing the inode type to HARDLINK and setting the OPFLAG_DIRECTDATA flag. The problem with this is that the inode's core RBTREE was left intact, but as a DIRECTDATA inode the flusher ignores it. This prevented the flusher from clearing the MOVED but on the children and resulted in the memory leak. What I do now is delete/duplicate the original inode, give the duplicate a fresh core, and then modify the duplicate instead of the original to be the special HARDLINK type w/OPFLAG_DIRECTDATA. This removes the special case. --- diff --git a/sys/vfs/hammer2/hammer2.h b/sys/vfs/hammer2/hammer2.h index 4d65d5db11..52e68158ae 100644 --- a/sys/vfs/hammer2/hammer2.h +++ b/sys/vfs/hammer2/hammer2.h @@ -211,6 +211,11 @@ RB_PROTOTYPE(hammer2_chain_tree, hammer2_chain, rbnode, hammer2_chain_cmp); #define HAMMER2_RESOLVE_SHARED 0x10 #define HAMMER2_RESOLVE_NOREF 0x20 +/* + * Flags passed to hammer2_chain_delete_duplicate() + */ +#define HAMMER2_DELDUP_RECORE 0x0001 + /* * Cluster different types of storage together for allocations */ @@ -602,7 +607,7 @@ int hammer2_chain_snapshot(hammer2_trans_t *trans, hammer2_inode_t *ip, hammer2_ioc_pfs_t *pfs); void hammer2_chain_delete(hammer2_trans_t *trans, hammer2_chain_t *chain); void hammer2_chain_delete_duplicate(hammer2_trans_t *trans, - hammer2_chain_t **chainp); + hammer2_chain_t **chainp, int flags); void hammer2_chain_flush(hammer2_trans_t *trans, hammer2_chain_t *chain); void hammer2_chain_commit(hammer2_trans_t *trans, hammer2_chain_t *chain); void hammer2_chain_setsubmod(hammer2_trans_t *trans, hammer2_chain_t *chain); diff --git a/sys/vfs/hammer2/hammer2_chain.c b/sys/vfs/hammer2/hammer2_chain.c index 92331a2ae2..1b419f9b35 100644 --- a/sys/vfs/hammer2/hammer2_chain.c +++ b/sys/vfs/hammer2/hammer2_chain.c @@ -899,7 +899,7 @@ hammer2_chain_resize(hammer2_trans_t *trans, hammer2_inode_t *ip, * duplication code will simply reuse the existing chain * structure. */ - hammer2_chain_delete_duplicate(trans, &chain); + hammer2_chain_delete_duplicate(trans, &chain, 0); /* * Set MODIFIED and add a chain ref to prevent destruction. Both @@ -1015,7 +1015,7 @@ hammer2_chain_modify(hammer2_trans_t *trans, hammer2_chain_t **chainp, * requires delete-duplicate. */ KKASSERT((flags & HAMMER2_MODIFY_ASSERTNOCOPY) == 0); - hammer2_chain_delete_duplicate(trans, chainp); + hammer2_chain_delete_duplicate(trans, chainp, 0); chain = *chainp; /* fall through using duplicate */ } else { @@ -2370,14 +2370,13 @@ hammer2_chain_duplicate(hammer2_trans_t *trans, hammer2_chain_t *parent, int i, * order to ensure that lookups do not race us. */ void -hammer2_chain_delete_duplicate(hammer2_trans_t *trans, - hammer2_chain_t **chainp) +hammer2_chain_delete_duplicate(hammer2_trans_t *trans, hammer2_chain_t **chainp, + int flags) { hammer2_mount_t *hmp = trans->hmp; hammer2_chain_t *ochain; hammer2_chain_t *nchain; hammer2_chain_core_t *above; - hammer2_chain_core_t *core; size_t bytes; /* @@ -2388,13 +2387,12 @@ hammer2_chain_delete_duplicate(hammer2_trans_t *trans, */ ochain = *chainp; nchain = hammer2_chain_alloc(hmp, trans, &ochain->bref); /* 1 ref */ - hammer2_chain_core_alloc(nchain, ochain->core); - core = ochain->core; + if (flags & HAMMER2_DELDUP_RECORE) + hammer2_chain_core_alloc(nchain, NULL); + else + hammer2_chain_core_alloc(nchain, ochain->core); above = ochain->above; - kprintf("delete_duplicate %p.%d(%d)\n", - ochain, ochain->bref.type, ochain->refs); - bytes = (hammer2_off_t)1 << (int)(ochain->bref.data_off & HAMMER2_OFF_MASK_RADIX); nchain->bytes = bytes; @@ -2511,9 +2509,6 @@ hammer2_chain_delete_duplicate(hammer2_trans_t *trans, nchain->index = ochain->index; - kprintf("duplicate ochain %p(%d) nchain %p(%d) %08x\n", - ochain, ochain->refs, nchain, nchain->refs, nchain->flags); - spin_lock(&above->cst.spin); atomic_set_int(&nchain->flags, HAMMER2_CHAIN_ONRBTREE); ochain->delete_tid = trans->sync_tid; diff --git a/sys/vfs/hammer2/hammer2_flush.c b/sys/vfs/hammer2/hammer2_flush.c index 751b71e2b0..4741596f8c 100644 --- a/sys/vfs/hammer2/hammer2_flush.c +++ b/sys/vfs/hammer2/hammer2_flush.c @@ -888,6 +888,7 @@ hammer2_chain_flush_scan2(hammer2_chain_t *child, void *data) * skipped right now before we start messing with a non-existant * block table. */ +#if 0 if (parent->bref.type == HAMMER2_BREF_TYPE_INODE && (parent->data->ipdata.op_flags & HAMMER2_OPFLAG_DIRECTDATA)) { #if FLUSH_DEBUG @@ -895,6 +896,7 @@ hammer2_chain_flush_scan2(hammer2_chain_t *child, void *data) #endif goto finalize; } +#endif /* * Ignore children created after our flush point, treating them as @@ -981,10 +983,13 @@ hammer2_chain_flush_scan2(hammer2_chain_t *child, void *data) KKASSERT((parent->data->ipdata.op_flags & HAMMER2_OPFLAG_DIRECTDATA) == 0); #endif +#if 0 if (parent->data->ipdata.op_flags & HAMMER2_OPFLAG_DIRECTDATA) { base = NULL; - } else { + } else +#endif + { base = &parent->data->ipdata.u.blockset.blockref[0]; count = HAMMER2_SET_COUNT; } @@ -1061,6 +1066,18 @@ hammer2_chain_flush_scan2(hammer2_chain_t *child, void *data) for (scan = above->first_parent; scan; scan = scan->next_parent) { + /* + * XXX weird code also checked at the top of scan2, + * I would like to fix this by detaching the core + * on initial hardlink consolidation (1->2 nlinks). + */ +#if 0 + if (scan->bref.type == HAMMER2_BREF_TYPE_INODE && + (scan->data->ipdata.op_flags & + HAMMER2_OPFLAG_DIRECTDATA)) { + continue; + } +#endif if (scan->flags & HAMMER2_CHAIN_SUBMODIFIED) { ok = 0; break; diff --git a/sys/vfs/hammer2/hammer2_inode.c b/sys/vfs/hammer2/hammer2_inode.c index a4eff73b37..1f022f4ea2 100644 --- a/sys/vfs/hammer2/hammer2_inode.c +++ b/sys/vfs/hammer2/hammer2_inode.c @@ -1329,6 +1329,8 @@ hammer2_hardlink_consolidate(hammer2_trans_t *trans, hammer2_inode_t *ip, * file is extended afterwords. */ hammer2_chain_modify(trans, &chain, 0); + hammer2_chain_delete_duplicate(trans, &chain, + HAMMER2_DELDUP_RECORE); ipdata = &chain->data->ipdata; ipdata->target_type = ipdata->type; ipdata->type = HAMMER2_OBJTYPE_HARDLINK; @@ -1360,7 +1362,6 @@ hammer2_hardlink_consolidate(hammer2_trans_t *trans, hammer2_inode_t *ip, bzero(&ipdata->u, sizeof(ipdata->u)); /* XXX transaction ids */ } else { - kprintf("DELETE INVISIBLE %p\n", chain); hammer2_chain_delete(trans, chain); }