--- old/usr/src/uts/common/avs/ns/dsw/ii_tree.c	Fri Jul 27 15:35:54 2018
+++ /dev/null	Fri Jul 27 15:07:21 2018
@@ -1,599 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (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
- * or http://www.opensolaris.org/os/licensing.
- * 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 2009 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
- */
-
-#include <sys/types.h>
-#include <sys/ksynch.h>
-#include <sys/kmem.h>
-#include <sys/errno.h>
-#include <sys/cmn_err.h>
-#include <sys/debug.h>
-#include <sys/cred.h>
-#include <sys/file.h>
-#include <sys/ddi.h>
-#include <sys/nsctl/nsctl.h>
-#include <sys/unistat/spcs_s.h>
-#include <sys/unistat/spcs_errors.h>
-
-#include <sys/unistat/spcs_s_k.h>
-#include "dsw.h"
-#include "dsw_dev.h"
-
-#ifdef DS_DDICT
-#include "../contract.h"
-#endif
-
-#include <sys/sdt.h>		/* dtrace is S10 or later */
-
-/*
- * Instant Image.
- *
- * This file contains the chunk map lookup functions of II.
- *
- */
-#define	CHUNK_FBA(chunk) DSW_CHK2FBA(chunk)
-
-extern int ii_debug;	/* debug level switch */
-int ii_map_debug = 0;
-
-#ifdef II_MULTIMULTI_TERABYTE
-typedef	int64_t	nodeid_t;
-typedef	int32_t	nodeid32_t;
-#else
-typedef	int32_t	nodeid_t;
-#endif
-
-typedef struct	ii_node {
-	chunkid_t	vchunk_id;		/* virtual chunk id */
-} NODE;
-
-typedef struct ii_nodelink_s {
-	chunkid_t	next_chunk;
-} ii_nodelink_t;
-
-static	int	nodes_per_fba = FBA_SIZE(1) / sizeof (NODE);
-
-ii_header_t *_ii_bm_header_get(_ii_info_t *ip, nsc_buf_t **tmp);
-int _ii_bm_header_put(ii_header_t *hdr, _ii_info_t *ip,
-    nsc_buf_t *tmp);
-void _ii_rlse_devs(_ii_info_t *, int);
-int _ii_rsrv_devs(_ii_info_t *, int, int);
-void _ii_error(_ii_info_t *, int);
-/*
- * Private functions for use in this file.
- */
-static void free_node(_ii_info_t *ip, NODE *np, nodeid_t ni);
-static chunkid_t ii_alloc_overflow(_ii_info_t *ip);
-void ii_free_overflow(_ii_info_t *, chunkid_t);
-extern int _ii_nsc_io(_ii_info_t *, int, nsc_fd_t *, int, nsc_off_t,
-    unsigned char *, nsc_size_t);
-
-static int
-update_tree_header(_ii_info_t *ip)
-{
-	ii_header_t *header;
-	nsc_buf_t	*tmp = NULL;
-
-	mutex_enter(&ip->bi_mutex);
-	header = _ii_bm_header_get(ip, &tmp);
-	if (header == NULL) {
-		/* bitmap is probably offline */
-		mutex_exit(&ip->bi_mutex);
-		DTRACE_PROBE(_iit_update_tree_header_end);
-		return (1);
-	}
-	header->ii_mstchks = ip->bi_mstchks;
-	header->ii_shdchks = ip->bi_shdchks;
-	header->ii_shdchkused = ip->bi_shdchkused;
-	header->ii_shdfchk = ip->bi_shdfchk;
-	(void) _ii_bm_header_put(header, ip, tmp);
-	mutex_exit(&ip->bi_mutex);
-
-	return (0);
-}
-
-static int
-update_overflow_header(_ii_info_t *ip, _ii_overflow_t *op)
-{
-	(void) _ii_nsc_io(ip, KS_OVR, op->ii_dev->bi_fd, NSC_WRBUF,
-	    II_OHEADER_FBA, (unsigned char *)&(op->ii_do),
-	    sizeof (_ii_doverflow_t));
-
-	return (0);
-}
-
-static int
-node_io(_ii_info_t *ip, NODE *np, nodeid_t node, int flag)
-{
-	int	rc;
-	int	node_fba;
-	int	tree_fba = ip->bi_copyfba + (ip->bi_copyfba-ip->bi_shdfba);
-	int	offset;
-	nsc_buf_t *tmp = NULL;
-
-	/*
-	 * Don't use _ii_nsc_io() as _ii_nsc_io() requires io to start at
-	 * an fba boundary.
-	 */
-
-	/* calculate location of node on bitmap file */
-	offset = (node % nodes_per_fba) * sizeof (NODE);
-	node_fba = tree_fba + node / nodes_per_fba;
-
-	/* read disk block containing node */
-	rc = nsc_alloc_buf(ip->bi_bmpfd, node_fba, 1, NSC_RDBUF|flag, &tmp);
-	if (!II_SUCCESS(rc)) {
-		_ii_error(ip, DSW_BMPOFFLINE);
-		if (tmp)
-			(void) nsc_free_buf(tmp);
-
-		DTRACE_PROBE(_iit_node_io_end);
-		return (1);
-	}
-
-	/* copy node and update bitmap file if needed */
-	rc = 0;
-	if (flag == NSC_RDBUF)
-		bcopy(tmp->sb_vec->sv_addr+offset, np, sizeof (NODE));
-	else {
-		bcopy(np, tmp->sb_vec->sv_addr+offset, sizeof (NODE));
-		II_NSC_WRITE(ip, bitmap, rc, tmp, node_fba, 1, 0);
-		if (!II_SUCCESS(rc)) {
-			_ii_error(ip, DSW_BMPOFFLINE);
-			rc = EIO;
-		}
-	}
-	if (tmp)
-		(void) nsc_free_buf(tmp);
-
-	return (0);
-}
-
-static int
-node_fba_fill(_ii_info_t *ip, nsc_size_t nchunks, chunkid_t vchunk_id)
-{
-	int	rc;
-	nsc_off_t	fba;
-	nsc_size_t	fbas;
-	nsc_size_t	maxfbas;
-	nsc_buf_t *bp;
-	nsc_vec_t *vp;
-
-	/* Determine maximum number of FBAs to allocate */
-	rc =  nsc_maxfbas(ip->bi_bmpfd, 0, &maxfbas);
-	if (!II_SUCCESS(rc))
-		maxfbas = DSW_CBLK_FBA;
-
-	/* Write out blocks of initialied NODEs */
-	fba = ip->bi_copyfba + (ip->bi_copyfba-ip->bi_shdfba);
-	fbas = FBA_LEN(nchunks * sizeof (NODE));
-	while (fbas > 0) {
-
-		/* Determine number of FBA to allocate this time */
-		if (fbas < maxfbas) maxfbas = fbas;
-
-		/* Allocate buffer which map to FBAs containing NODEs */
-		bp = NULL;
-		rc = nsc_alloc_buf(ip->bi_bmpfd, fba, maxfbas, NSC_WRBUF, &bp);
-		if (!II_SUCCESS(rc)) {
-			_ii_error(ip, DSW_BMPOFFLINE);
-			DTRACE_PROBE(alloc_buf_failed);
-			return (EIO);
-		}
-
-		/* traverse vector list, filling wth initialized NODEs */
-		for (vp = bp->sb_vec; vp->sv_addr && vp->sv_len; vp++) {
-			NODE *pnode = (NODE *)vp->sv_addr;
-			NODE *enode = (NODE *)(vp->sv_addr +  vp->sv_len);
-			while (pnode < enode) {
-				pnode->vchunk_id = vchunk_id;
-				pnode++;
-			}
-		}
-
-		/* write FBAs containing initialized NODEs */
-		II_NSC_WRITE(ip, bitmap, rc, bp, fba, maxfbas, 0);
-		if (!II_SUCCESS(rc)) {
-			_ii_error(ip, DSW_BMPOFFLINE);
-			(void) nsc_free_buf(bp);
-			DTRACE_PROBE(write_failed);
-			return (EIO);
-		}
-
-		/* free the buffer */
-		(void) nsc_free_buf(bp);
-
-		/* Adjust nsc buffer values */
-		fba += maxfbas;
-		fbas -= maxfbas;
-	}
-
-	return (0);
-}
-
-/*
- * Reads the node into core and returns a pointer to it.
- */
-
-static NODE *
-read_node(_ii_info_t *ip, nodeid_t node)
-{
-	NODE *new;
-
-	new = (NODE *)kmem_alloc(sizeof (NODE), KM_SLEEP);
-
-	if (node_io(ip, new, node, NSC_RDBUF)) {
-		kmem_free(new, sizeof (NODE));
-		new = NULL;
-	}
-
-	return (new);
-}
-
-
-static chunkid_t
-alloc_chunk(_ii_info_t *ip)
-{
-	ii_nodelink_t nl;
-	int fba;
-	chunkid_t rc = II_NULLCHUNK;
-
-	mutex_enter(&ip->bi_chksmutex);
-	if (ip->bi_shdchkused < ip->bi_shdchks) {
-		rc = ip->bi_shdchkused++;
-	} else if (ip->bi_shdfchk != II_NULLCHUNK) {
-		ASSERT(ip->bi_shdfchk >= 0 && ip->bi_shdfchk < ip->bi_shdchks);
-		rc = ip->bi_shdfchk;
-		fba = CHUNK_FBA(rc);
-		(void) _ii_rsrv_devs(ip, SHDR, II_INTERNAL);
-		(void) _ii_nsc_io(ip, KS_SHD, SHDFD(ip), NSC_RDBUF, fba,
-		    (unsigned char *)&nl, sizeof (nl));
-		_ii_rlse_devs(ip, SHDR);
-		ip->bi_shdfchk = nl.next_chunk;
-		ASSERT(ip->bi_shdfchk == II_NULLCHUNK ||
-		    (ip->bi_shdfchk >= 0 && ip->bi_shdfchk < ip->bi_shdchks));
-	} else {
-
-		/* into overflow */
-		rc = ii_alloc_overflow(ip);
-	}
-	mutex_exit(&ip->bi_chksmutex);
-	(void) update_tree_header(ip);
-
-	return (rc);
-}
-
-/*
- * releases memory for node
- */
-static void	/*ARGSUSED*/
-release_node(_ii_info_t *ip, NODE *np, nodeid_t ni)
-{
-	kmem_free(np, sizeof (NODE));
-
-}
-
-static void
-write_node(_ii_info_t *ip, NODE *np, nodeid_t ni)
-{
-	(void) node_io(ip, np, ni, NSC_WRBUF);
-	release_node(ip, np, ni);
-
-}
-
-static void
-free_node(_ii_info_t *ip, NODE *np, nodeid_t ni)
-{
-	ii_nodelink_t nl;
-	int	fba;
-
-	if (np == NULL) {
-		DTRACE_PROBE(_iit_free_node_end);
-		return;
-	}
-
-	mutex_enter(&ip->bi_chksmutex);
-	if (II_ISOVERFLOW(np->vchunk_id)) {
-		/* link chunk onto overflow free list */
-		ii_free_overflow(ip, np->vchunk_id);
-	} else {
-		/* write old free list head into chunk */
-		nl.next_chunk = ip->bi_shdfchk;
-		ip->bi_shdfchk = np->vchunk_id;
-		ASSERT(ip->bi_shdfchk == II_NULLCHUNK ||
-		    (ip->bi_shdfchk >= 0 && ip->bi_shdfchk < ip->bi_shdchks));
-		fba = CHUNK_FBA(np->vchunk_id);
-		(void) _ii_rsrv_devs(ip, SHDR, II_INTERNAL);
-		(void) _ii_nsc_io(ip, KS_SHD, SHDFD(ip), NSC_WRBUF, fba,
-		    (unsigned char *)&nl, sizeof (nl));
-		_ii_rlse_devs(ip, SHDR);
-		/* update free counts */
-		/* ip->bi_unused++; */
-	}
-	np->vchunk_id = II_NULLCHUNK;
-	(void) node_io(ip, np, ni, NSC_WRBUF);
-	(void) update_tree_header(ip);
-	mutex_exit(&ip->bi_chksmutex);
-
-}
-
-/*
- * Public functions for dsw_dev to use.
- */
-
-/*
- * Overflow volume functions.
- */
-
-/* put overflow chunk on the overflow volume free list */
-void
-ii_free_overflow(_ii_info_t *ip, chunkid_t chunk)
-{
-	ii_nodelink_t nl;
-	_ii_overflow_t *op;
-	int fba;
-
-	if (!II_ISOVERFLOW(chunk)) {
-		DTRACE_PROBE(_iit_free_overflow_end_1);
-		return;
-	}
-	chunk = II_2OVERFLOW(chunk);
-
-	op = ip->bi_overflow;
-	if (op == NULL) {
-#ifdef DEBUG
-		cmn_err(CE_PANIC, "overflow used, but not attached ip %p",
-		    (void *) ip);
-#endif
-		DTRACE_PROBE(_iit_free_overflow_end_2);
-		return;
-	}
-	mutex_enter(&(op->ii_mutex));
-
-	DTRACE_PROBE(_iit_free_overflow);
-
-	/* write old free list head into chunk */
-	nl.next_chunk = op->ii_freehead;
-	fba = CHUNK_FBA(chunk);
-	(void) nsc_reserve(op->ii_dev->bi_fd, NSC_MULTI);
-	(void) _ii_nsc_io(ip, KS_OVR, op->ii_dev->bi_fd, NSC_WRBUF, fba,
-	    (unsigned char *)&nl, sizeof (nl));
-	/* update free counts */
-	op->ii_unused++;
-	ASSERT(op->ii_used > 0);		/* always use 1 for header */
-
-	/* write chunk id into header freelist start */
-	op->ii_freehead =  chunk;
-
-	(void) update_overflow_header(ip, op);
-	nsc_release(op->ii_dev->bi_fd);
-	mutex_exit(&(op->ii_mutex));
-
-}
-
-/* reclaim any overflow storage used by the volume */
-void
-ii_reclaim_overflow(_ii_info_t *ip)
-{
-	NODE	*node;
-	nodeid_t node_id;
-	_ii_overflow_t *op;
-
-	if ((ip->bi_flags & (DSW_VOVERFLOW | DSW_FRECLAIM)) == 0) {
-		DTRACE_PROBE(_iit_reclaim_overflow_end);
-		return;
-	}
-
-	/*
-	 * Determine whether overflow should be reclaimed:
-	 * 1/ If we're not doing a group volume update
-	 * OR
-	 * 2/ If the number of detaches != number of attached vols
-	 */
-	op = ip->bi_overflow;
-	if (op && (((op->ii_flags & IIO_VOL_UPDATE) == 0) ||
-	    (op->ii_detachcnt != op->ii_drefcnt))) {
-#ifndef II_MULTIMULTI_TERABYTE
-		/* assert volume size fits into node_id */
-		ASSERT(ip->bi_mstchks <= INT32_MAX);
-#endif
-		for (node_id = 0; node_id < ip->bi_mstchks; node_id++) {
-			if ((node = read_node(ip, node_id)) == NULL) {
-				DTRACE_PROBE(_iit_reclaim_overflow_end);
-				return;
-			}
-			ii_free_overflow(ip, node->vchunk_id);
-			release_node(ip, node, node_id);
-		}
-	} else {
-		/* need to reset the overflow volume header */
-		op->ii_freehead = II_NULLNODE;
-		op->ii_used = 1;		/* we have used the header */
-		op->ii_unused = op->ii_nchunks - op->ii_used;
-		(void) update_overflow_header(ip, op);
-	}
-
-	DTRACE_PROBE(_iit_reclaim_overflow);
-
-	if ((ip->bi_flags & DSW_VOVERFLOW) == DSW_VOVERFLOW) {
-		mutex_enter(&ip->bi_mutex);
-		II_FLAG_CLR(DSW_VOVERFLOW, ip);
-		mutex_exit(&ip->bi_mutex);
-	}
-	--iigkstat.spilled_over.value.ul;
-
-}
-
-static chunkid_t
-ii_alloc_overflow(_ii_info_t *ip)
-{
-	chunkid_t chunk;
-	ii_nodelink_t nl;
-	_ii_overflow_t *op;
-	int fba;
-
-	if ((op = ip->bi_overflow) == NULL) {
-		DTRACE_PROBE(_iit_alloc_overflow_end);
-		return (II_NULLCHUNK);	/* no overflow volume attached */
-	}
-
-	mutex_enter(&(op->ii_mutex));
-
-	DTRACE_PROBE(_iit_alloc_overflow);
-
-	if (op->ii_unused < 1) {
-		mutex_exit(&(op->ii_mutex));
-		DTRACE_PROBE(_iit_alloc_overflow_end);
-		return (II_NULLCHUNK);
-	}
-	(void) nsc_reserve(op->ii_dev->bi_fd, NSC_MULTI);
-	if (op->ii_freehead != II_NULLCHUNK) {
-		/* pick first from free list */
-		chunk = op->ii_freehead;
-		fba = CHUNK_FBA(chunk);
-		(void) _ii_nsc_io(ip, KS_OVR, op->ii_dev->bi_fd, NSC_RDBUF, fba,
-		    (unsigned char *)&nl, sizeof (nl));
-		op->ii_freehead = nl.next_chunk;
-		/* decrease unused count, fix bug 4419956 */
-		op->ii_unused--;
-	} else {
-		/* otherwise pick first unused */
-		if (op->ii_used > op->ii_nchunks)
-			chunk = II_NULLCHUNK;
-		else {
-			chunk = op->ii_used++;
-			op->ii_unused--;
-		}
-	}
-	if (chunk != II_NULLCHUNK) {
-		chunk = II_2OVERFLOW(chunk);
-		if ((ip->bi_flags&DSW_VOVERFLOW) == 0) {
-			mutex_enter(&ip->bi_mutex);
-			II_FLAG_SET(DSW_VOVERFLOW, ip);
-			mutex_exit(&ip->bi_mutex);
-			++iigkstat.spilled_over.value.ul;
-		}
-	}
-	(void) update_overflow_header(ip, op);
-	nsc_release(op->ii_dev->bi_fd);
-	mutex_exit(&(op->ii_mutex));
-
-	return (chunk);
-}
-/*
- * Find or insert key into search tree.
- */
-
-chunkid_t
-ii_tsearch(_ii_info_t *ip, chunkid_t chunk_id)
-			/* Address of the root of the tree */
-{
-	NODE	*rootp = NULL;
-	chunkid_t n;	/* New node id if key not found */
-
-	if ((rootp = read_node(ip, chunk_id)) == NULL) {
-		DTRACE_PROBE(_iit_tsearch_end);
-		return (II_NULLNODE);
-	}
-	n = rootp->vchunk_id;
-	if (n != II_NULLCHUNK) { /* chunk allocated, return location */
-		release_node(ip, rootp, 0);
-		DTRACE_PROBE(_iit_tsearch_end);
-		return (n);
-	}
-	n = alloc_chunk(ip);
-	if (n != II_NULLCHUNK) {
-		rootp->vchunk_id = n;
-		write_node(ip, rootp, chunk_id);
-	} else
-		release_node(ip, rootp, 0);
-
-	return (n);
-}
-
-/* Delete node with key chunkid */
-void
-ii_tdelete(_ii_info_t *ip,
-	chunkid_t chunkid)	/* Key to be deleted */
-{
-	NODE *np = NULL;
-
-	if ((np = read_node(ip, chunkid)) == NULL) {
-		DTRACE_PROBE(_iit_tdelete_end);
-		return;
-	}
-
-	ASSERT(np->vchunk_id != II_NULLCHUNK);
-	free_node(ip, np, chunkid);
-	np->vchunk_id = II_NULLCHUNK;
-	write_node(ip, np, chunkid);
-
-}
-
-/*
- * initialise an empty map for ip
- */
-
-int
-ii_tinit(_ii_info_t *ip)
-{
-	int rc = 0;
-
-	/* overflow can't be attached before first call to this function */
-	if (ip->bi_overflow)
-		ii_reclaim_overflow(ip);
-
-	mutex_enter(&ip->bi_chksmutex);
-	ip->bi_shdfchk = II_NULLCHUNK;	/* set freelist to empty chain */
-	ip->bi_shdchkused = 0;
-
-	/* fill index (bi_mstchks size) with II_NULLCHUNK */
-	rc = node_fba_fill(ip, ip->bi_mstchks, II_NULLCHUNK);
-	if (rc == 0)
-		rc = update_tree_header(ip);
-	mutex_exit(&ip->bi_chksmutex);
-
-	return (rc);
-}
-
-/*
- * Calculate the size of map space provided by a bitmap volume with
- * tree_len fba's spare for the tree.
- */
-
-nsc_size_t
-ii_btsize(nsc_size_t tree_len)
-{
-	nsc_size_t nchunks;
-
-	nchunks = tree_len * nodes_per_fba;
-
-	if (ii_debug > 1)
-		cmn_err(CE_NOTE,
-		    "!ii_btsize: bitmap with %" NSC_SZFMT
-		    " spare fba's will map %" NSC_SZFMT " chunks",
-		    tree_len, nchunks);
-
-	return (nchunks);
-}
