1*0Sstevel@tonic-gate /* 2*0Sstevel@tonic-gate * CDDL HEADER START 3*0Sstevel@tonic-gate * 4*0Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*0Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*0Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*0Sstevel@tonic-gate * with the License. 8*0Sstevel@tonic-gate * 9*0Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*0Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*0Sstevel@tonic-gate * See the License for the specific language governing permissions 12*0Sstevel@tonic-gate * and limitations under the License. 13*0Sstevel@tonic-gate * 14*0Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*0Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*0Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*0Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*0Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*0Sstevel@tonic-gate * 20*0Sstevel@tonic-gate * CDDL HEADER END 21*0Sstevel@tonic-gate */ 22*0Sstevel@tonic-gate /* 23*0Sstevel@tonic-gate * Copyright (c) 1994-2000 by Sun Microsystems, Inc. 24*0Sstevel@tonic-gate * All rights reserved. 25*0Sstevel@tonic-gate */ 26*0Sstevel@tonic-gate 27*0Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 28*0Sstevel@tonic-gate 29*0Sstevel@tonic-gate #include <sys/types.h> 30*0Sstevel@tonic-gate #include <sys/param.h> 31*0Sstevel@tonic-gate #include <sys/systm.h> /* for bzero */ 32*0Sstevel@tonic-gate #include <sys/machlock.h> 33*0Sstevel@tonic-gate #include <sys/spl.h> 34*0Sstevel@tonic-gate #include <sys/promif.h> 35*0Sstevel@tonic-gate #include <sys/debug.h> 36*0Sstevel@tonic-gate 37*0Sstevel@tonic-gate #include "tnf_buf.h" 38*0Sstevel@tonic-gate 39*0Sstevel@tonic-gate /* 40*0Sstevel@tonic-gate * Defines 41*0Sstevel@tonic-gate */ 42*0Sstevel@tonic-gate 43*0Sstevel@tonic-gate #define TNFW_B_ALLOC_LO 0x1 44*0Sstevel@tonic-gate #define TNFW_B_MAXALLOCTRY 32 45*0Sstevel@tonic-gate 46*0Sstevel@tonic-gate #define TNF_MAXALLOC (TNF_BLOCK_SIZE - sizeof (tnf_block_header_t)) 47*0Sstevel@tonic-gate 48*0Sstevel@tonic-gate /* 49*0Sstevel@tonic-gate * Globals 50*0Sstevel@tonic-gate */ 51*0Sstevel@tonic-gate 52*0Sstevel@tonic-gate TNFW_B_STATE tnfw_b_state = TNFW_B_NOBUFFER | TNFW_B_STOPPED; 53*0Sstevel@tonic-gate 54*0Sstevel@tonic-gate /* 55*0Sstevel@tonic-gate * Locals 56*0Sstevel@tonic-gate */ 57*0Sstevel@tonic-gate 58*0Sstevel@tonic-gate static int spinlock_spl; 59*0Sstevel@tonic-gate 60*0Sstevel@tonic-gate /* 61*0Sstevel@tonic-gate * Declarations 62*0Sstevel@tonic-gate */ 63*0Sstevel@tonic-gate 64*0Sstevel@tonic-gate static tnf_block_header_t *tnfw_b_alloc_block(tnf_buf_file_header_t *, 65*0Sstevel@tonic-gate enum tnf_alloc_mode); 66*0Sstevel@tonic-gate 67*0Sstevel@tonic-gate /* 68*0Sstevel@tonic-gate * (Private) Allocate a new block. Return NULL on failure and mark 69*0Sstevel@tonic-gate * tracing as broken. 'istag' is non-zero if the block is to be 70*0Sstevel@tonic-gate * non-reclaimable. All blocks are returned A-locked. 71*0Sstevel@tonic-gate */ 72*0Sstevel@tonic-gate 73*0Sstevel@tonic-gate static tnf_block_header_t * 74*0Sstevel@tonic-gate tnfw_b_alloc_block(tnf_buf_file_header_t *fh, enum tnf_alloc_mode istag) 75*0Sstevel@tonic-gate { 76*0Sstevel@tonic-gate tnf_block_header_t *block; 77*0Sstevel@tonic-gate ulong_t bcount; 78*0Sstevel@tonic-gate ulong_t tmp_bn, bn, new_bn; 79*0Sstevel@tonic-gate ulong_t tmp_gen, gen, new_gen; 80*0Sstevel@tonic-gate ulong_t next; 81*0Sstevel@tonic-gate int i; 82*0Sstevel@tonic-gate lock_t *lp; 83*0Sstevel@tonic-gate ushort_t spl; 84*0Sstevel@tonic-gate 85*0Sstevel@tonic-gate if (tnfw_b_state != TNFW_B_RUNNING) 86*0Sstevel@tonic-gate return (NULL); 87*0Sstevel@tonic-gate 88*0Sstevel@tonic-gate lp = &fh->lock; 89*0Sstevel@tonic-gate 90*0Sstevel@tonic-gate /* 91*0Sstevel@tonic-gate * Check reserved area first for tag block allocations 92*0Sstevel@tonic-gate * Tag allocations are rare, so we move the code out of line 93*0Sstevel@tonic-gate */ 94*0Sstevel@tonic-gate if (istag) 95*0Sstevel@tonic-gate goto try_reserved; 96*0Sstevel@tonic-gate 97*0Sstevel@tonic-gate try_loop: 98*0Sstevel@tonic-gate /* 99*0Sstevel@tonic-gate * Search for a block, using hint as starting point. 100*0Sstevel@tonic-gate */ 101*0Sstevel@tonic-gate 102*0Sstevel@tonic-gate bcount = fh->com.block_count; /* total block count */ 103*0Sstevel@tonic-gate 104*0Sstevel@tonic-gate gen = fh->next_alloc.gen; 105*0Sstevel@tonic-gate bn = fh->next_alloc.block[gen & TNFW_B_ALLOC_LO]; 106*0Sstevel@tonic-gate 107*0Sstevel@tonic-gate for (i = 0; i < TNFW_B_MAXALLOCTRY; i++) { 108*0Sstevel@tonic-gate 109*0Sstevel@tonic-gate /* 110*0Sstevel@tonic-gate * Calculate next (not this) block to look for. 111*0Sstevel@tonic-gate * Needed for updating the hint. 112*0Sstevel@tonic-gate */ 113*0Sstevel@tonic-gate if ((new_bn = bn + 1) >= bcount) { 114*0Sstevel@tonic-gate new_bn = TNFW_B_DATA_BLOCK_BEGIN >> TNF_BLOCK_SHIFT; 115*0Sstevel@tonic-gate new_gen = gen + 1; 116*0Sstevel@tonic-gate } else 117*0Sstevel@tonic-gate new_gen = gen; 118*0Sstevel@tonic-gate 119*0Sstevel@tonic-gate /* 120*0Sstevel@tonic-gate * Try to reserve candidate block 121*0Sstevel@tonic-gate */ 122*0Sstevel@tonic-gate /* LINTED pointer cast may result in improper alignment */ 123*0Sstevel@tonic-gate block = (tnf_block_header_t *) 124*0Sstevel@tonic-gate ((char *)fh + (bn << TNF_BLOCK_SHIFT)); 125*0Sstevel@tonic-gate 126*0Sstevel@tonic-gate if (lock_try(&block->A_lock)) 127*0Sstevel@tonic-gate if (block->generation < gen && 128*0Sstevel@tonic-gate lock_try(&block->B_lock)) 129*0Sstevel@tonic-gate goto update_hint; 130*0Sstevel@tonic-gate else 131*0Sstevel@tonic-gate lock_clear(&block->A_lock); 132*0Sstevel@tonic-gate 133*0Sstevel@tonic-gate /* Reload hint values */ 134*0Sstevel@tonic-gate gen = fh->next_alloc.gen; 135*0Sstevel@tonic-gate bn = fh->next_alloc.block[gen & TNFW_B_ALLOC_LO]; 136*0Sstevel@tonic-gate 137*0Sstevel@tonic-gate /* adjust if we know a little better than the hint */ 138*0Sstevel@tonic-gate if ((new_bn > bn && new_gen == gen) || new_gen > gen) { 139*0Sstevel@tonic-gate gen = new_gen; 140*0Sstevel@tonic-gate bn = new_bn; 141*0Sstevel@tonic-gate } 142*0Sstevel@tonic-gate } 143*0Sstevel@tonic-gate 144*0Sstevel@tonic-gate goto loop_fail; 145*0Sstevel@tonic-gate 146*0Sstevel@tonic-gate update_hint: 147*0Sstevel@tonic-gate /* 148*0Sstevel@tonic-gate * Re-read the hint and update it only if we'll be increasing it. 149*0Sstevel@tonic-gate */ 150*0Sstevel@tonic-gate lock_set_spl(lp, spinlock_spl, &spl); 151*0Sstevel@tonic-gate tmp_gen = fh->next_alloc.gen; 152*0Sstevel@tonic-gate tmp_bn = fh->next_alloc.block[tmp_gen & TNFW_B_ALLOC_LO]; 153*0Sstevel@tonic-gate 154*0Sstevel@tonic-gate if ((new_gen == tmp_gen && new_bn > tmp_bn) || new_gen > tmp_gen) { 155*0Sstevel@tonic-gate /* 156*0Sstevel@tonic-gate * Order is important here! It is the write to 157*0Sstevel@tonic-gate * next_alloc.gen that atomically records the new 158*0Sstevel@tonic-gate * value. 159*0Sstevel@tonic-gate */ 160*0Sstevel@tonic-gate fh->next_alloc.block[new_gen & TNFW_B_ALLOC_LO] = new_bn; 161*0Sstevel@tonic-gate fh->next_alloc.gen = new_gen; 162*0Sstevel@tonic-gate } 163*0Sstevel@tonic-gate lock_clear_splx(lp, spl); 164*0Sstevel@tonic-gate 165*0Sstevel@tonic-gate got_block: 166*0Sstevel@tonic-gate /* 167*0Sstevel@tonic-gate * Initialize and return the block 168*0Sstevel@tonic-gate */ 169*0Sstevel@tonic-gate /* ASSERT(block->tag == TNF_BLOCK_HEADER_TAG); */ 170*0Sstevel@tonic-gate block->bytes_valid = sizeof (tnf_block_header_t); 171*0Sstevel@tonic-gate block->next_block = NULL; 172*0Sstevel@tonic-gate /* LINTED assignment of 64-bit integer to 32-bit integer */ 173*0Sstevel@tonic-gate block->generation = istag ? TNF_TAG_GENERATION_NUM : gen; 174*0Sstevel@tonic-gate /* ASSERT(LOCK_HELD(&block->A_lock); */ 175*0Sstevel@tonic-gate lock_clear(&block->B_lock); 176*0Sstevel@tonic-gate return (block); 177*0Sstevel@tonic-gate 178*0Sstevel@tonic-gate try_reserved: 179*0Sstevel@tonic-gate /* 180*0Sstevel@tonic-gate * Look for a free tag block in reserved area 181*0Sstevel@tonic-gate */ 182*0Sstevel@tonic-gate next = fh->next_tag_alloc; 183*0Sstevel@tonic-gate while (next < (TNFW_B_DATA_BLOCK_BEGIN >> TNF_BLOCK_SHIFT)) { 184*0Sstevel@tonic-gate /* LINTED pointer cast may result in improper alignment */ 185*0Sstevel@tonic-gate block = (tnf_block_header_t *) 186*0Sstevel@tonic-gate ((char *)fh + (next << TNF_BLOCK_SHIFT)); 187*0Sstevel@tonic-gate next++; 188*0Sstevel@tonic-gate /* 189*0Sstevel@tonic-gate * See if block is unclaimed. 190*0Sstevel@tonic-gate * Don't bother clearing the A-lock if the 191*0Sstevel@tonic-gate * block was claimed and released, since it 192*0Sstevel@tonic-gate * will never be reallocated anyway. 193*0Sstevel@tonic-gate */ 194*0Sstevel@tonic-gate if (lock_try(&block->A_lock) && 195*0Sstevel@tonic-gate block->generation == 0) { 196*0Sstevel@tonic-gate lock_set_spl(lp, spinlock_spl, &spl); 197*0Sstevel@tonic-gate if (next > fh->next_tag_alloc) 198*0Sstevel@tonic-gate fh->next_tag_alloc = next; 199*0Sstevel@tonic-gate lock_clear_splx(lp, spl); 200*0Sstevel@tonic-gate goto got_block; 201*0Sstevel@tonic-gate } 202*0Sstevel@tonic-gate } 203*0Sstevel@tonic-gate goto try_loop; 204*0Sstevel@tonic-gate 205*0Sstevel@tonic-gate loop_fail: 206*0Sstevel@tonic-gate /* 207*0Sstevel@tonic-gate * Only get here if we failed the for loop 208*0Sstevel@tonic-gate */ 209*0Sstevel@tonic-gate ASSERT(i == TNFW_B_MAXALLOCTRY); 210*0Sstevel@tonic-gate tnfw_b_state = TNFW_B_BROKEN; 211*0Sstevel@tonic-gate #ifdef DEBUG 212*0Sstevel@tonic-gate prom_printf("kernel probes: alloc_block failed\n"); 213*0Sstevel@tonic-gate #endif 214*0Sstevel@tonic-gate return (NULL); 215*0Sstevel@tonic-gate 216*0Sstevel@tonic-gate } 217*0Sstevel@tonic-gate 218*0Sstevel@tonic-gate /* 219*0Sstevel@tonic-gate * Allocate size bytes from the trace buffer. Return NULL on failure, 220*0Sstevel@tonic-gate * and mark tracing as broken. We're guaranteed that the buffer will 221*0Sstevel@tonic-gate * not be deallocated while we're in this routine. 222*0Sstevel@tonic-gate * Allocation requests must be word-sized and are word-aligned. 223*0Sstevel@tonic-gate */ 224*0Sstevel@tonic-gate 225*0Sstevel@tonic-gate void * 226*0Sstevel@tonic-gate tnfw_b_alloc(TNFW_B_WCB *wcb, size_t size, enum tnf_alloc_mode istag) 227*0Sstevel@tonic-gate { 228*0Sstevel@tonic-gate TNFW_B_POS *pos; 229*0Sstevel@tonic-gate ushort_t offset; 230*0Sstevel@tonic-gate void *destp; 231*0Sstevel@tonic-gate tnf_block_header_t *block, *new_block; 232*0Sstevel@tonic-gate 233*0Sstevel@tonic-gate pos = &wcb->tnfw_w_pos; /* common case */ 234*0Sstevel@tonic-gate if (istag) 235*0Sstevel@tonic-gate pos = &wcb->tnfw_w_tag_pos; 236*0Sstevel@tonic-gate block = pos->tnfw_w_block; 237*0Sstevel@tonic-gate offset = pos->tnfw_w_write_off; 238*0Sstevel@tonic-gate /* Round size up to a multiple of 8. */ 239*0Sstevel@tonic-gate size = (size + 7) & ~7; 240*0Sstevel@tonic-gate 241*0Sstevel@tonic-gate if (block == NULL || offset + size > TNF_BLOCK_SIZE) { 242*0Sstevel@tonic-gate 243*0Sstevel@tonic-gate /* Get a new block */ 244*0Sstevel@tonic-gate /* LINTED pointer cast may result in improper alignment */ 245*0Sstevel@tonic-gate new_block = tnfw_b_alloc_block(TNF_FILE_HEADER(), istag); 246*0Sstevel@tonic-gate if (new_block == NULL) 247*0Sstevel@tonic-gate /* tracing has been marked as broken at this point */ 248*0Sstevel@tonic-gate return (NULL); 249*0Sstevel@tonic-gate 250*0Sstevel@tonic-gate /* ASSERT(size <= TNF_MAXALLOC); */ 251*0Sstevel@tonic-gate 252*0Sstevel@tonic-gate /* 253*0Sstevel@tonic-gate * If the old block is clean (i.e., we're in a new 254*0Sstevel@tonic-gate * transaction), just release it. Else, pad it out 255*0Sstevel@tonic-gate * and attach it to the list of uncommitted blocks. 256*0Sstevel@tonic-gate */ 257*0Sstevel@tonic-gate if (block != NULL) { 258*0Sstevel@tonic-gate if (block->bytes_valid == offset && 259*0Sstevel@tonic-gate !pos->tnfw_w_dirty) { 260*0Sstevel@tonic-gate /* block is clean: release it */ 261*0Sstevel@tonic-gate lock_clear(&block->A_lock); 262*0Sstevel@tonic-gate } else { 263*0Sstevel@tonic-gate /* block is dirty */ 264*0Sstevel@tonic-gate ulong_t *p, *q; 265*0Sstevel@tonic-gate 266*0Sstevel@tonic-gate /* LINTED pointer cast */ 267*0Sstevel@tonic-gate p = (ulong_t *)((char *)block + offset); 268*0Sstevel@tonic-gate /* LINTED pointer cast */ 269*0Sstevel@tonic-gate q = (ulong_t *)((char *)block + TNF_BLOCK_SIZE); 270*0Sstevel@tonic-gate while (p < q) 271*0Sstevel@tonic-gate *p++ = TNF_NULL; 272*0Sstevel@tonic-gate 273*0Sstevel@tonic-gate /* append block to release list */ 274*0Sstevel@tonic-gate new_block->next_block = block; 275*0Sstevel@tonic-gate 276*0Sstevel@tonic-gate /* we have at least one dirty block */ 277*0Sstevel@tonic-gate pos->tnfw_w_dirty = 1; 278*0Sstevel@tonic-gate } 279*0Sstevel@tonic-gate } 280*0Sstevel@tonic-gate 281*0Sstevel@tonic-gate /* make new_block the current block */ 282*0Sstevel@tonic-gate pos->tnfw_w_block = block = new_block; 283*0Sstevel@tonic-gate /* write_off is updated below */ 284*0Sstevel@tonic-gate offset = sizeof (tnf_block_header_t); 285*0Sstevel@tonic-gate /* ASSERT(new_block->bytes_valid == offset); */ 286*0Sstevel@tonic-gate } 287*0Sstevel@tonic-gate 288*0Sstevel@tonic-gate destp = (char *)block + offset; 289*0Sstevel@tonic-gate /* update write_off */ 290*0Sstevel@tonic-gate pos->tnfw_w_write_off = offset + size; 291*0Sstevel@tonic-gate /* 292*0Sstevel@tonic-gate * Unconditionally write a 0 into the last word allocated, 293*0Sstevel@tonic-gate * in case we left an alignment gap. (Assume that doing an 294*0Sstevel@tonic-gate * unconditional write is cheaper than testing and branching 295*0Sstevel@tonic-gate * around the write half the time.) 296*0Sstevel@tonic-gate */ 297*0Sstevel@tonic-gate /* LINTED pointer cast may result in improper alignment */ 298*0Sstevel@tonic-gate *((int *)((char *)destp + size - sizeof (int))) = 0; 299*0Sstevel@tonic-gate return (destp); 300*0Sstevel@tonic-gate } 301*0Sstevel@tonic-gate 302*0Sstevel@tonic-gate /* 303*0Sstevel@tonic-gate * Allocate a directory entry. 304*0Sstevel@tonic-gate */ 305*0Sstevel@tonic-gate 306*0Sstevel@tonic-gate /*ARGSUSED0*/ 307*0Sstevel@tonic-gate void * 308*0Sstevel@tonic-gate tnfw_b_fw_alloc(TNFW_B_WCB *wcb) 309*0Sstevel@tonic-gate { 310*0Sstevel@tonic-gate tnf_buf_file_header_t *fh; 311*0Sstevel@tonic-gate lock_t *lp; 312*0Sstevel@tonic-gate ushort_t spl; 313*0Sstevel@tonic-gate caddr_t cell; 314*0Sstevel@tonic-gate ulong_t next; 315*0Sstevel@tonic-gate 316*0Sstevel@tonic-gate /* LINTED pointer cast may result in improper alignment */ 317*0Sstevel@tonic-gate fh = TNF_FILE_HEADER(); 318*0Sstevel@tonic-gate lp = &fh->lock; 319*0Sstevel@tonic-gate 320*0Sstevel@tonic-gate lock_set_spl(lp, spinlock_spl, &spl); 321*0Sstevel@tonic-gate next = fh->next_fw_alloc; 322*0Sstevel@tonic-gate if (next < TNFW_B_FW_ZONE) { 323*0Sstevel@tonic-gate cell = (caddr_t)fh + next; 324*0Sstevel@tonic-gate fh->next_fw_alloc = next + sizeof (tnf_ref32_t); 325*0Sstevel@tonic-gate } else 326*0Sstevel@tonic-gate cell = NULL; 327*0Sstevel@tonic-gate lock_clear_splx(lp, spl); 328*0Sstevel@tonic-gate 329*0Sstevel@tonic-gate return (cell); 330*0Sstevel@tonic-gate } 331*0Sstevel@tonic-gate 332*0Sstevel@tonic-gate /* 333*0Sstevel@tonic-gate * Initialize a buffer. 334*0Sstevel@tonic-gate */ 335*0Sstevel@tonic-gate 336*0Sstevel@tonic-gate void 337*0Sstevel@tonic-gate tnfw_b_init_buffer(caddr_t buf, size_t size) 338*0Sstevel@tonic-gate { 339*0Sstevel@tonic-gate int gen_shift; 340*0Sstevel@tonic-gate int i; 341*0Sstevel@tonic-gate ulong_t b; 342*0Sstevel@tonic-gate ulong_t blocks; 343*0Sstevel@tonic-gate tnf_block_header_t *block; 344*0Sstevel@tonic-gate tnf_buf_file_header_t *fh; 345*0Sstevel@tonic-gate 346*0Sstevel@tonic-gate /* Compute platform-specific spinlock_spl */ 347*0Sstevel@tonic-gate spinlock_spl = __ipltospl(LOCK_LEVEL + 1); 348*0Sstevel@tonic-gate 349*0Sstevel@tonic-gate /* LINTED pointer cast may result in improper alignment */ 350*0Sstevel@tonic-gate fh = (tnf_buf_file_header_t *)buf; 351*0Sstevel@tonic-gate 352*0Sstevel@tonic-gate /* LINTED logical expression always true: op "||" */ 353*0Sstevel@tonic-gate ASSERT(TNF_DIRECTORY_SIZE > TNF_BLOCK_SIZE); 354*0Sstevel@tonic-gate 355*0Sstevel@tonic-gate /* 356*0Sstevel@tonic-gate * This assertion is needed because we cannot change 357*0Sstevel@tonic-gate * sys/tnf_com.h this late in the release cycle, but we need the 358*0Sstevel@tonic-gate * interface in sys/machlock.h for locking operations. 359*0Sstevel@tonic-gate */ 360*0Sstevel@tonic-gate /* LINTED logical expression always true: op "||" */ 361*0Sstevel@tonic-gate ASSERT(sizeof (tnf_byte_lock_t) == sizeof (lock_t)); 362*0Sstevel@tonic-gate 363*0Sstevel@tonic-gate /* Calculate number of blocks */ 364*0Sstevel@tonic-gate blocks = size >> TNF_BLOCK_SHIFT; 365*0Sstevel@tonic-gate 366*0Sstevel@tonic-gate /* Calculate generation shift */ 367*0Sstevel@tonic-gate gen_shift = 0; 368*0Sstevel@tonic-gate b = 1; 369*0Sstevel@tonic-gate while (b < blocks) { 370*0Sstevel@tonic-gate b <<= 1; 371*0Sstevel@tonic-gate ++gen_shift; 372*0Sstevel@tonic-gate } 373*0Sstevel@tonic-gate ASSERT(gen_shift < 32); 374*0Sstevel@tonic-gate 375*0Sstevel@tonic-gate /* fill in file header */ 376*0Sstevel@tonic-gate /* magic number comes last */ 377*0Sstevel@tonic-gate /* LINTED constant truncated by assignment */ 378*0Sstevel@tonic-gate fh->com.tag = TNF_FILE_HEADER_TAG; 379*0Sstevel@tonic-gate fh->com.file_version = TNF_FILE_VERSION; 380*0Sstevel@tonic-gate fh->com.file_header_size = sizeof (tnf_file_header_t); 381*0Sstevel@tonic-gate fh->com.file_log_size = gen_shift + TNF_BLOCK_SHIFT; 382*0Sstevel@tonic-gate fh->com.block_header_size = sizeof (tnf_block_header_t); 383*0Sstevel@tonic-gate fh->com.block_size = TNF_BLOCK_SIZE; 384*0Sstevel@tonic-gate fh->com.directory_size = TNF_DIRECTORY_SIZE; 385*0Sstevel@tonic-gate /* LINTED assignment of 64-bit integer to 32-bit integer */ 386*0Sstevel@tonic-gate fh->com.block_count = blocks; 387*0Sstevel@tonic-gate /* com.blocks_valid is unused */ 388*0Sstevel@tonic-gate fh->next_alloc.gen = 1; 389*0Sstevel@tonic-gate fh->next_alloc.block[0] = 0; 390*0Sstevel@tonic-gate fh->next_alloc.block[1] = TNFW_B_DATA_BLOCK_BEGIN >> TNF_BLOCK_SHIFT; 391*0Sstevel@tonic-gate fh->next_tag_alloc = TNF_DIRECTORY_SIZE >> TNF_BLOCK_SHIFT; 392*0Sstevel@tonic-gate fh->next_fw_alloc = TNF_DIRENT_LAST + 4; 393*0Sstevel@tonic-gate LOCK_INIT_CLEAR(&fh->lock); 394*0Sstevel@tonic-gate 395*0Sstevel@tonic-gate (void) bzero(buf + sizeof (*fh), TNF_DIRECTORY_SIZE - sizeof (*fh)); 396*0Sstevel@tonic-gate i = TNF_DIRECTORY_SIZE >> TNF_BLOCK_SHIFT; 397*0Sstevel@tonic-gate for (; i < blocks; ++i) { 398*0Sstevel@tonic-gate /* LINTED pointer cast may result in improper alignment */ 399*0Sstevel@tonic-gate block = (tnf_block_header_t *)(buf + (i << TNF_BLOCK_SHIFT)); 400*0Sstevel@tonic-gate block->tag = (tnf_ref32_t)TNF_BLOCK_HEADER_TAG; 401*0Sstevel@tonic-gate block->generation = 0; 402*0Sstevel@tonic-gate block->bytes_valid = sizeof (tnf_block_header_t); 403*0Sstevel@tonic-gate LOCK_INIT_CLEAR(&block->A_lock); 404*0Sstevel@tonic-gate LOCK_INIT_CLEAR(&block->B_lock); 405*0Sstevel@tonic-gate } 406*0Sstevel@tonic-gate 407*0Sstevel@tonic-gate /* snap in magic number */ 408*0Sstevel@tonic-gate fh->magic = TNF_MAGIC; 409*0Sstevel@tonic-gate } 410