/* * Resize the cluster's physical storage allocation in-place. This may * replace the cluster's chains. */ void hammer2_cluster_resize(hammer2_trans_t *trans, hammer2_inode_t *ip, hammer2_cluster_t *cparent, hammer2_cluster_t *cluster, int nradix, int flags) { int i; KKASSERT(cparent->pmp == cluster->pmp); /* can be NULL */ KKASSERT(cparent->nchains == cluster->nchains); cluster->focus = NULL; for (i = 0; i < cluster->nchains; ++i) { if (cluster->array[i]) { KKASSERT(cparent->array[i]); hammer2_chain_resize(trans, ip, cparent->array[i], &cluster->array[i], nradix, flags); if (cluster->focus == NULL) cluster->focus = cluster->array[i]; } } }
/* * cparent is locked exclusively, with an extra ref, cluster is not locked. * Replace element [i] in the cluster. */ static int hammer2_sync_replace(hammer2_thread_t *thr, hammer2_chain_t *parent, hammer2_chain_t *chain, hammer2_tid_t mtid, int idx, hammer2_chain_t *focus) { int nradix; uint8_t otype; #if HAMMER2_THREAD_DEBUG if (hammer2_debug & 1) kprintf("replace rec %p slave %d %d.%016jx mod=%016jx\n", chain, idx, focus->bref.type, focus->bref.key, mtid); #endif hammer2_chain_unlock(chain); hammer2_chain_lock(chain, HAMMER2_RESOLVE_ALWAYS); if (chain->bytes != focus->bytes) { /* XXX what if compressed? */ nradix = hammer2_getradix(chain->bytes); hammer2_chain_resize(NULL, parent, chain, mtid, nradix, 0); } hammer2_chain_modify(chain, mtid, 0); otype = chain->bref.type; chain->bref.type = focus->bref.type; chain->bref.methods = focus->bref.methods; chain->bref.keybits = focus->bref.keybits; chain->bref.vradix = focus->bref.vradix; /* mirror_tid updated by flush */ KKASSERT(chain->bref.modify_tid == mtid); chain->bref.flags = focus->bref.flags; /* key already present */ /* check code will be recalculated */ chain->error = 0; /* * Copy data body. */ switch(chain->bref.type) { case HAMMER2_BREF_TYPE_INODE: if ((focus->data->ipdata.meta.op_flags & HAMMER2_OPFLAG_DIRECTDATA) == 0) { /* * If DIRECTDATA is transitioning to 0 or the old * chain is not an inode we have to initialize * the block table. */ if (otype != HAMMER2_BREF_TYPE_INODE || (chain->data->ipdata.meta.op_flags & HAMMER2_OPFLAG_DIRECTDATA)) { kprintf("chain inode trans away from dd\n"); bzero(&chain->data->ipdata.u, sizeof(chain->data->ipdata.u)); } bcopy(focus->data, chain->data, offsetof(hammer2_inode_data_t, u)); /* XXX setcheck on inode should not be needed */ hammer2_chain_setcheck(chain, chain->data); break; } /* fall through */ case HAMMER2_BREF_TYPE_DATA: bcopy(focus->data, chain->data, chain->bytes); hammer2_chain_setcheck(chain, chain->data); break; default: KKASSERT(0); break; } hammer2_chain_unlock(chain); hammer2_chain_lock(chain, HAMMER2_RESOLVE_SHARED | HAMMER2_RESOLVE_MAYBE); return 0; }