/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 1994-2003 Sun Microsytems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#ifdef _KERNEL
#else /* _KERNEL */
#include <string.h> /* for memset */
#endif /* _KERNEL */
#include "tnf_buf.h"
#ifdef TNFWB_DEBUG
#ifdef _KERNEL
#else /* _KERNEL */
#include <stdio.h>
#include <thread.h>
#endif /* _KERNEL */
#endif /* TNFW_DEBUG */
/*
* Defines
*/
#ifdef TNF_BLOCK_STATS
static struct {
int tnf_block_allocs;
int tnf_block_tries;
int tnf_max_block_tries;
int tnf_tag_blocks;
int tnf_generation_laps;
int tnf_a_locks;
int tnf_b_locks;
#endif
/*
* Regular record tag pointer - CAUTION - has to be in sync with tnf_tag
* macro in writer.h
*/
/*
* Exported interface by buffering layer to indicate where fowarding ptrs
* for file header and block header are.
*/
#ifdef _KERNEL
#endif
/*
* (Private) Allocate a new block. Return NULL on failure. 'istag'
* is true if the block is to be non-reclaimable.
*/
static tnf_block_header_t *
{
uint_t i, b;
#ifdef TNF_BLOCK_STATS
b_locks = 0;
#endif
#ifdef _TNF_VERBOSE
#endif
#ifndef _KERNEL
if (_tnfw_b_control->tnf_init_callback() == 0)
return (NULL);
#endif /* _KERNEL */
return (NULL);
return (NULL);
}
/* LINTED pointer cast may result in improper alignment */
if (!wcb->tnfw_w_initialized) {
/* Get the block shift and generation shift values. */
b = 1;
b <<= 1;
}
b = 1;
b <<= 1;
++wcb->tnfw_w_gen_shift;
}
}
/*
* If we need a tag block, check the reserved tag block space
* first. fh->next_tag_alloc is only a hint; it is updated
* without concurrency control.
*/
i = fh->next_tag_alloc;
do {
/* LINTED pointer cast */
block->generation == 0)
break;
} while (i < TNFW_B_DATA_BLOCK_BEGIN);
if (i < TNFW_B_DATA_BLOCK_BEGIN) {
if (i > fh->next_tag_alloc)
fh->next_tag_alloc = i;
/* LINTED pointer subtraction casted to 32 bits */
/* LINTED constant truncated by assignment */
return (block);
}
}
for (i = 0; !gotit && i != TNFW_B_MAXALLOCTRY; ++i) {
#ifdef TNFWB_DEBUG
#endif
prev_gen > generation) {
}
#ifdef TNFWB_DEBUG
"alloc_block (%d): trying blocknum = %d, gen %d\n",
#endif
block = (tnf_block_header_t *)
/* LINTED pointer cast may result in improper alignment */
#ifdef TNF_BLOCK_STATS
++tag_blocks;
++a_locks;
++tag_blocks;
++b_locks;
} else
#else
} else {
}
}
#endif
++prev_gen;
}
}
}
if (i == TNFW_B_MAXALLOCTRY) {
return (NULL);
}
#ifdef TNFWB_DEBUG
"alloc_block (%d): got blocknum = %d, gen %d, block at 0x%x\n",
#endif
/* LINTED pointer subtraction casted to 32 bits */
if (istag) {
}
/*
* Read the hint one more time, only update it if we'll be increasing
* it
*/
#ifdef _KERNEL
#endif
new_hint_hi > hint_hi) {
/*
* Order is important here! It is the write to next_alloc.hi
* that atomically records the new value.
*/
else
#ifdef TNFWB_DEBUG
#endif
}
#ifdef _KERNEL
#endif
#ifdef TNF_BLOCK_STATS
if (i > tnf_block_stats.tnf_max_block_tries) {
}
#endif
return (block);
}
{
return;
return;
}
void
{
return;
}
/*
* Initialize a buffer. NOT RE-ENTRANT! Block sizes other than 512
* are currently rejected. The code "ought to work" with any block
* size that is an integral power of 2. 'zfod' states whether we
* can assume that the buffer is zero-filled (or paged-in zero-fill-on-demand).
*/
{
int i;
int file_size;
unsigned b;
/* LINTED pointer cast may result in improper alignment */
#ifdef _TNF_VERBOSE
#endif
/* Check for 512 could go away. */
return (TNFW_B_BAD_BLOCK_SIZE);
/*
* Check to see if block size is a power of 2, and get
* log2(block size).
*/
++block_shift;
if (b != 1)
return (TNFW_B_BAD_BLOCK_SIZE);
gen_shift = 0;
while (b < blocks) {
b <<= 1;
++gen_shift;
}
/* reserve first two words for file header tag and block header tag */
sizeof (tnf_ref32_t);
(2 * sizeof (tnf_ref32_t));
/* LINTED size of tnf_ref_32_t known to be 32 */
/* fill in rest of file header */
/* Self relative pointer to tag */
/* LINTED pointer subtraction casted to 32 bits */
/* fill in fh->com.file_log_size */
b = 1;
while (b < file_size) {
b <<= 1;
}
#ifdef TNFWB_DEBUG
#endif
if (!zfod) {
#ifdef _KERNEL
#else
#endif
}
for (; i != blocks; ++i) {
block = (tnf_block_header_t *)
/* LINTED pointer cast */
(buf + (i << block_shift));
block->generation = 0;
}
}
#ifdef _KERNEL
(void *) ipltospl(LOCK_LEVEL));
#endif
return (TNFW_B_OK);
}
/*
*
*/
void *
{
int offset;
void *destp;
#ifdef _TNF_VERBOSE
#endif
return (NULL);
}
}
/* Round size up to a multiple of 8. */
/* LINTED pointer cast may result in improper alignment */
/* Check size within range. */
#ifdef TNFWB_SAFER
/* TNFW_B_RECORD_TOO_BIG */
return (NULL);
#endif
#ifdef TNFWB_MAY_RELEASE_A_LOCK
/* re-acquire the A-lock for the current block */
}
} else {
}
}
#endif
/* TNFW_B_ACKPHT */
return (NULL);
}
#ifdef TNFWB_DEBUG
"wcb 0x%x: new block at 0x%x, old block is 0x%x, "
"uncommitted is 0x%x\n",
#endif
/* XXXX is this what we want for padding? */
#ifdef _KERNEL
#else
#endif
#ifdef TNFWB_MAY_RELEASE_A_LOCK
/* Could still be holding the A-lock on block */
if (!wcb->tnfw_w_a_lock_released)
#else
/* Definitely still holding the A-lock */
#endif /* TNFWB_MAY_RELEASE_A_LOCK */
}
}
/* Add new_block to the list of uncommitted blocks. */
} else {
/* Assert(block != NULL); */
}
}
/*
* Unconditionally write a 0 into the last word allocated,
* in case we left an alignment gap. (Assume that doing an
* unconditional write is cheaper than testing and branching
* around the write half the time.)
*/
/* LINTED pointer cast may result in improper alignment */
#ifdef _TNF_VERBOSE
#endif
return (destp);
}
/*
*
*/
{
/* LINTED pointer cast may result in improper alignment */
#ifdef TNFWB_DEBUG
#endif
/*
* cope with the normal record block(s) first
*/
#ifdef TNFWB_DEBUG
#endif
}
#ifdef TNFWB_DEBUG
#endif
}
#ifdef TNFWB_MAY_RELEASE_A_LOCK
if (0) { /* XXXX Do we or don't we clear this lock? */
}
#endif
/*
* cope with the tag block(s)
*/
#ifdef TNFWB_DEBUG
#endif
}
return (TNFW_B_OK);
}
/*
*
*/
{
/* LINTED pointer cast may result in improper alignment */
#ifdef TNFWB_MAY_RELEASE_A_LOCK
if (0) { /* XXXX */
}
#endif
}
}
}
return (TNFW_B_OK);
}
/*
* The kernel version is different because we can use a spin mutex
* in the kernel, and not all SPARC systems support the SWAP instruction.
*/
#ifdef _KERNEL
/*ARGSUSED0*/
{
/* LINTED pointer cast may result in improper alignment */
}
#else
/*ARGSUSED0*/
{
/* LINTED pointer cast may result in improper alignment */
/* LINTED pointer cast may result in improper alignment */
/* LINTED pointer cast may result in improper alignment */
#ifdef VERYVERBOSE
#endif
#ifdef VERYVERBOSE
#endif
#ifdef VERYVERBOSE
#endif
#ifdef VERYVERBOSE
#endif
if (*hint == 0) {
if (swapin != 0) {
if (swapin != (unsigned)TNFW_B_FW_INVALID) {
/* restore */
}
} else {
break;
}
}
++hint;
#ifdef VERYVERBOSE
#endif
}
/* LINTED pointer subtraction casted to 32 bits */
#ifdef VERYVERBOSE
#endif
return (retval);
}
#endif /* _KERNEL */