xref: /onnv-gate/usr/src/common/fs/ufsops.c (revision 7563:84ec90ffc3f7)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
51544Seschrock  * Common Development and Distribution License (the "License").
61544Seschrock  * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate  * See the License for the specific language governing permissions
110Sstevel@tonic-gate  * and limitations under the License.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * CDDL HEADER END
200Sstevel@tonic-gate  */
21*7563SPrasad.Singamsetty@Sun.COM 
220Sstevel@tonic-gate /*
23*7563SPrasad.Singamsetty@Sun.COM  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
240Sstevel@tonic-gate  * Use is subject to license terms.
250Sstevel@tonic-gate  */
260Sstevel@tonic-gate 
270Sstevel@tonic-gate #include <sys/types.h>
280Sstevel@tonic-gate #include <sys/param.h>
290Sstevel@tonic-gate #include <sys/vnode.h>
300Sstevel@tonic-gate #include <sys/fs/ufs_fsdir.h>
310Sstevel@tonic-gate #include <sys/fs/ufs_fs.h>
320Sstevel@tonic-gate #include <sys/fs/ufs_inode.h>
330Sstevel@tonic-gate #include <sys/sysmacros.h>
340Sstevel@tonic-gate #include <sys/bootvfs.h>
350Sstevel@tonic-gate #include <sys/filep.h>
360Sstevel@tonic-gate 
370Sstevel@tonic-gate #ifdef	_BOOT
380Sstevel@tonic-gate #include "../common/util.h"
390Sstevel@tonic-gate #else
400Sstevel@tonic-gate #include <sys/sunddi.h>
410Sstevel@tonic-gate #endif
420Sstevel@tonic-gate 
430Sstevel@tonic-gate extern void *bkmem_alloc(size_t);
440Sstevel@tonic-gate extern void bkmem_free(void *, size_t);
453446Smrj extern int cf_check_compressed(fileid_t *);
463446Smrj extern void cf_close(fileid_t *);
473446Smrj extern void cf_seek(fileid_t *, off_t, int);
483446Smrj extern int cf_read(fileid_t *, caddr_t, size_t);
490Sstevel@tonic-gate 
500Sstevel@tonic-gate int bootrd_debug;
510Sstevel@tonic-gate #ifdef _BOOT
520Sstevel@tonic-gate #define	dprintf	if (bootrd_debug) printf
530Sstevel@tonic-gate #else
540Sstevel@tonic-gate #define	printf	kobj_printf
550Sstevel@tonic-gate #define	dprintf	if (bootrd_debug) kobj_printf
560Sstevel@tonic-gate 
570Sstevel@tonic-gate /* PRINTLIKE */
580Sstevel@tonic-gate extern void kobj_printf(char *, ...);
590Sstevel@tonic-gate #endif
600Sstevel@tonic-gate 
610Sstevel@tonic-gate /*
620Sstevel@tonic-gate  * This fd is used when talking to the device file itself.
630Sstevel@tonic-gate  */
640Sstevel@tonic-gate static fileid_t *head;
650Sstevel@tonic-gate 
660Sstevel@tonic-gate /* Only got one of these...ergo, only 1 fs open at once */
670Sstevel@tonic-gate /* static */
680Sstevel@tonic-gate devid_t		*ufs_devp;
690Sstevel@tonic-gate 
700Sstevel@tonic-gate struct dirinfo {
710Sstevel@tonic-gate 	int 	loc;
720Sstevel@tonic-gate 	fileid_t *fi;
730Sstevel@tonic-gate };
740Sstevel@tonic-gate 
750Sstevel@tonic-gate static	int	bufs_close(int);
760Sstevel@tonic-gate static	void	bufs_closeall(int);
770Sstevel@tonic-gate static 	ino_t	find(fileid_t *filep, char *path);
780Sstevel@tonic-gate static	ino_t	dlook(fileid_t *filep, char *path);
790Sstevel@tonic-gate static 	daddr32_t	sbmap(fileid_t *filep, daddr32_t bn);
800Sstevel@tonic-gate static  struct direct *readdir(struct dirinfo *dstuff);
810Sstevel@tonic-gate static	void set_cache(int, void *, uint_t);
820Sstevel@tonic-gate static	void *get_cache(int);
830Sstevel@tonic-gate static	void free_cache();
840Sstevel@tonic-gate 
850Sstevel@tonic-gate 
860Sstevel@tonic-gate /*
870Sstevel@tonic-gate  *	There is only 1 open (mounted) device at any given time.
880Sstevel@tonic-gate  *	So we can keep a single, global devp file descriptor to
890Sstevel@tonic-gate  *	use to index into the di[] array.  This is not true for the
900Sstevel@tonic-gate  *	fi[] array.  We can have more than one file open at once,
910Sstevel@tonic-gate  *	so there is no global fd for the fi[].
920Sstevel@tonic-gate  *	The user program must save the fd passed back from open()
930Sstevel@tonic-gate  *	and use it to do subsequent read()'s.
940Sstevel@tonic-gate  */
950Sstevel@tonic-gate 
960Sstevel@tonic-gate static int
openi(fileid_t * filep,ino_t inode)970Sstevel@tonic-gate openi(fileid_t *filep, ino_t inode)
980Sstevel@tonic-gate {
990Sstevel@tonic-gate 	struct dinode *dp;
1000Sstevel@tonic-gate 	devid_t *devp = filep->fi_devp;
1010Sstevel@tonic-gate 
1020Sstevel@tonic-gate 	filep->fi_inode = get_cache((int)inode);
1030Sstevel@tonic-gate 	if (filep->fi_inode != 0)
1040Sstevel@tonic-gate 		return (0);
1050Sstevel@tonic-gate 
1060Sstevel@tonic-gate 	filep->fi_offset = 0;
1070Sstevel@tonic-gate 	filep->fi_blocknum = fsbtodb(&devp->un_fs.di_fs,
108*7563SPrasad.Singamsetty@Sun.COM 	    itod(&devp->un_fs.di_fs, inode));
1090Sstevel@tonic-gate 
1100Sstevel@tonic-gate 	/* never more than 1 disk block */
1110Sstevel@tonic-gate 	filep->fi_count = devp->un_fs.di_fs.fs_bsize;
1120Sstevel@tonic-gate 	filep->fi_memp = 0;		/* cached read */
1130Sstevel@tonic-gate 	if (diskread(filep) != 0) {
1140Sstevel@tonic-gate 		return (0);
1150Sstevel@tonic-gate 	}
1160Sstevel@tonic-gate 
1170Sstevel@tonic-gate 	dp = (struct dinode *)filep->fi_memp;
1180Sstevel@tonic-gate 	filep->fi_inode = (struct inode *)
1190Sstevel@tonic-gate 	    bkmem_alloc(sizeof (struct inode));
1200Sstevel@tonic-gate 	bzero((char *)filep->fi_inode, sizeof (struct inode));
1210Sstevel@tonic-gate 	filep->fi_inode->i_ic =
1220Sstevel@tonic-gate 	    dp[itoo(&devp->un_fs.di_fs, inode)].di_un.di_icom;
1230Sstevel@tonic-gate 	filep->fi_inode->i_number = inode;
1240Sstevel@tonic-gate 	set_cache((int)inode, (void *)filep->fi_inode, sizeof (struct inode));
1250Sstevel@tonic-gate 	return (0);
1260Sstevel@tonic-gate }
1270Sstevel@tonic-gate 
1280Sstevel@tonic-gate static fileid_t *
find_fp(int fd)1290Sstevel@tonic-gate find_fp(int fd)
1300Sstevel@tonic-gate {
1310Sstevel@tonic-gate 	fileid_t *filep = head;
1320Sstevel@tonic-gate 
1330Sstevel@tonic-gate 	if (fd >= 0) {
1340Sstevel@tonic-gate 		while ((filep = filep->fi_forw) != head)
1350Sstevel@tonic-gate 			if (fd == filep->fi_filedes)
1360Sstevel@tonic-gate 				return (filep->fi_taken ? filep : 0);
1370Sstevel@tonic-gate 	}
1380Sstevel@tonic-gate 
1390Sstevel@tonic-gate 	return (0);
1400Sstevel@tonic-gate }
1410Sstevel@tonic-gate 
1420Sstevel@tonic-gate static ino_t
find(fileid_t * filep,char * path)1430Sstevel@tonic-gate find(fileid_t *filep, char *path)
1440Sstevel@tonic-gate {
1450Sstevel@tonic-gate 	char *q;
1460Sstevel@tonic-gate 	char c;
1470Sstevel@tonic-gate 	ino_t inode;
1480Sstevel@tonic-gate 	char lpath[MAXPATHLEN];
1490Sstevel@tonic-gate 	char *lpathp = lpath;
1500Sstevel@tonic-gate 	int len, r;
1510Sstevel@tonic-gate 	devid_t	*devp;
1520Sstevel@tonic-gate 
1530Sstevel@tonic-gate 	if (path == NULL || *path == '\0') {
1540Sstevel@tonic-gate 		printf("null path\n");
1550Sstevel@tonic-gate 		return ((ino_t)0);
1560Sstevel@tonic-gate 	}
1570Sstevel@tonic-gate 
1580Sstevel@tonic-gate 	dprintf("openi: %s\n", path);
1590Sstevel@tonic-gate 
1600Sstevel@tonic-gate 	bzero(lpath, sizeof (lpath));
1610Sstevel@tonic-gate 	bcopy(path, lpath, strlen(path));
1620Sstevel@tonic-gate 	devp = filep->fi_devp;
1630Sstevel@tonic-gate 	while (*lpathp) {
1640Sstevel@tonic-gate 		/* if at the beginning of pathname get root inode */
1650Sstevel@tonic-gate 		r = (lpathp == lpath);
1660Sstevel@tonic-gate 		if (r && openi(filep, (ino_t)UFSROOTINO))
1670Sstevel@tonic-gate 			return ((ino_t)0);
1680Sstevel@tonic-gate 		while (*lpathp == '/')
1690Sstevel@tonic-gate 			lpathp++;	/* skip leading slashes */
1700Sstevel@tonic-gate 		q = lpathp;
1710Sstevel@tonic-gate 		while (*q != '/' && *q != '\0')
1720Sstevel@tonic-gate 			q++;		/* find end of component */
1730Sstevel@tonic-gate 		c = *q;
1740Sstevel@tonic-gate 		*q = '\0';		/* terminate component */
1750Sstevel@tonic-gate 
1760Sstevel@tonic-gate 		/* Bail out early if opening root */
1770Sstevel@tonic-gate 		if (r && (*lpathp == '\0'))
1780Sstevel@tonic-gate 			return ((ino_t)UFSROOTINO);
1790Sstevel@tonic-gate 		if ((inode = dlook(filep, lpathp)) != 0) {
1800Sstevel@tonic-gate 			if (openi(filep, inode))
1810Sstevel@tonic-gate 				return ((ino_t)0);
1820Sstevel@tonic-gate 			if ((filep->fi_inode->i_smode & IFMT) == IFLNK) {
1830Sstevel@tonic-gate 				filep->fi_blocknum =
1840Sstevel@tonic-gate 				    fsbtodb(&devp->un_fs.di_fs,
1850Sstevel@tonic-gate 				    filep->fi_inode->i_db[0]);
1860Sstevel@tonic-gate 				filep->fi_count = DEV_BSIZE;
1870Sstevel@tonic-gate 				filep->fi_memp = 0;
1880Sstevel@tonic-gate 				if (diskread(filep) != 0)
1890Sstevel@tonic-gate 					return ((ino_t)0);
1900Sstevel@tonic-gate 				len = strlen(filep->fi_memp);
1910Sstevel@tonic-gate 				if (filep->fi_memp[0] == '/')
1920Sstevel@tonic-gate 					/* absolute link */
1930Sstevel@tonic-gate 					lpathp = lpath;
1940Sstevel@tonic-gate 				/* copy rest of unprocessed path up */
1950Sstevel@tonic-gate 				bcopy(q, lpathp + len, strlen(q + 1) + 2);
1960Sstevel@tonic-gate 				/* point to unprocessed path */
1970Sstevel@tonic-gate 				*(lpathp + len) = c;
1980Sstevel@tonic-gate 				/* prepend link in before unprocessed path */
1990Sstevel@tonic-gate 				bcopy(filep->fi_memp, lpathp, len);
2000Sstevel@tonic-gate 				lpathp = lpath;
2010Sstevel@tonic-gate 				continue;
2020Sstevel@tonic-gate 			} else
2030Sstevel@tonic-gate 				*q = c;
2040Sstevel@tonic-gate 			if (c == '\0')
2050Sstevel@tonic-gate 				break;
2060Sstevel@tonic-gate 			lpathp = q;
2070Sstevel@tonic-gate 			continue;
2080Sstevel@tonic-gate 		} else {
2090Sstevel@tonic-gate 			return ((ino_t)0);
2100Sstevel@tonic-gate 		}
2110Sstevel@tonic-gate 	}
2120Sstevel@tonic-gate 	return (inode);
2130Sstevel@tonic-gate }
2140Sstevel@tonic-gate 
2150Sstevel@tonic-gate static daddr32_t
sbmap(fileid_t * filep,daddr32_t bn)2160Sstevel@tonic-gate sbmap(fileid_t *filep, daddr32_t bn)
2170Sstevel@tonic-gate {
2180Sstevel@tonic-gate 	struct inode *inodep;
2190Sstevel@tonic-gate 	int i, j, sh;
2200Sstevel@tonic-gate 	daddr32_t nb, *bap;
2210Sstevel@tonic-gate 	daddr32_t *db;
2220Sstevel@tonic-gate 	devid_t	*devp;
2230Sstevel@tonic-gate 
2240Sstevel@tonic-gate 	devp = filep->fi_devp;
2250Sstevel@tonic-gate 	inodep = filep->fi_inode;
2260Sstevel@tonic-gate 	db = inodep->i_db;
2270Sstevel@tonic-gate 
2280Sstevel@tonic-gate 	/*
2290Sstevel@tonic-gate 	 * blocks 0..NDADDR are direct blocks
2300Sstevel@tonic-gate 	 */
2310Sstevel@tonic-gate 	if (bn < NDADDR) {
2320Sstevel@tonic-gate 		nb = db[bn];
2330Sstevel@tonic-gate 		return (nb);
2340Sstevel@tonic-gate 	}
2350Sstevel@tonic-gate 
2360Sstevel@tonic-gate 	/*
2370Sstevel@tonic-gate 	 * addresses NIADDR have single and double indirect blocks.
2380Sstevel@tonic-gate 	 * the first step is to determine how many levels of indirection.
2390Sstevel@tonic-gate 	 */
2400Sstevel@tonic-gate 	sh = 1;
2410Sstevel@tonic-gate 	bn -= NDADDR;
2420Sstevel@tonic-gate 	for (j = NIADDR; j > 0; j--) {
2430Sstevel@tonic-gate 		sh *= NINDIR(&devp->un_fs.di_fs);
2440Sstevel@tonic-gate 		if (bn < sh)
2450Sstevel@tonic-gate 			break;
2460Sstevel@tonic-gate 		bn -= sh;
2470Sstevel@tonic-gate 	}
2480Sstevel@tonic-gate 	if (j == 0) {
2490Sstevel@tonic-gate 		return ((daddr32_t)0);
2500Sstevel@tonic-gate 	}
2510Sstevel@tonic-gate 
2520Sstevel@tonic-gate 	/*
2530Sstevel@tonic-gate 	 * fetch the first indirect block address from the inode
2540Sstevel@tonic-gate 	 */
2550Sstevel@tonic-gate 	nb = inodep->i_ib[NIADDR - j];
2560Sstevel@tonic-gate 	if (nb == 0) {
2570Sstevel@tonic-gate 		return ((daddr32_t)0);
2580Sstevel@tonic-gate 	}
2590Sstevel@tonic-gate 
2600Sstevel@tonic-gate 	/*
2610Sstevel@tonic-gate 	 * fetch through the indirect blocks
2620Sstevel@tonic-gate 	 */
2630Sstevel@tonic-gate 	for (; j <= NIADDR; j++) {
2643128Saf 		filep->fi_blocknum = fsbtodb(&devp->un_fs.di_fs, nb);
2653128Saf 		filep->fi_count = devp->un_fs.di_fs.fs_bsize;
2663128Saf 		filep->fi_memp = 0;
2673128Saf 		if (diskread(filep) != 0)
2683128Saf 			return (0);
2693128Saf 		bap = (daddr32_t *)filep->fi_memp;
2700Sstevel@tonic-gate 		sh /= NINDIR(&devp->un_fs.di_fs);
2710Sstevel@tonic-gate 		i = (bn / sh) % NINDIR(&devp->un_fs.di_fs);
2720Sstevel@tonic-gate 		nb = bap[i];
2730Sstevel@tonic-gate 		if (nb == 0) {
2740Sstevel@tonic-gate 			return ((daddr32_t)0);
2750Sstevel@tonic-gate 		}
2760Sstevel@tonic-gate 	}
2770Sstevel@tonic-gate 	return (nb);
2780Sstevel@tonic-gate }
2790Sstevel@tonic-gate 
2800Sstevel@tonic-gate static ino_t
dlook(fileid_t * filep,char * path)2810Sstevel@tonic-gate dlook(fileid_t *filep, char *path)
2820Sstevel@tonic-gate {
2830Sstevel@tonic-gate 	struct direct *dp;
2840Sstevel@tonic-gate 	struct inode *ip;
2850Sstevel@tonic-gate 	struct dirinfo dirp;
2860Sstevel@tonic-gate 	int len;
2870Sstevel@tonic-gate 
2880Sstevel@tonic-gate 	ip = filep->fi_inode;
2890Sstevel@tonic-gate 	if (path == NULL || *path == '\0')
2900Sstevel@tonic-gate 		return (0);
2910Sstevel@tonic-gate 
2920Sstevel@tonic-gate 	dprintf("dlook: %s\n", path);
2930Sstevel@tonic-gate 
2940Sstevel@tonic-gate 	if ((ip->i_smode & IFMT) != IFDIR) {
2950Sstevel@tonic-gate 		return (0);
2960Sstevel@tonic-gate 	}
2970Sstevel@tonic-gate 	if (ip->i_size == 0) {
2980Sstevel@tonic-gate 		return (0);
2990Sstevel@tonic-gate 	}
3000Sstevel@tonic-gate 	len = strlen(path);
3010Sstevel@tonic-gate 	dirp.loc = 0;
3020Sstevel@tonic-gate 	dirp.fi = filep;
3030Sstevel@tonic-gate 	for (dp = readdir(&dirp); dp != NULL; dp = readdir(&dirp)) {
3040Sstevel@tonic-gate 		if (dp->d_ino == 0)
3050Sstevel@tonic-gate 			continue;
3060Sstevel@tonic-gate 		if (dp->d_namlen == len && strcmp(path, dp->d_name) == 0) {
3070Sstevel@tonic-gate 			return (dp->d_ino);
3080Sstevel@tonic-gate 		}
3090Sstevel@tonic-gate 		/* Allow "*" to print all names at that level, w/out match */
3100Sstevel@tonic-gate 		if (strcmp(path, "*") == 0)
3110Sstevel@tonic-gate 			dprintf("%s\n", dp->d_name);
3120Sstevel@tonic-gate 	}
3130Sstevel@tonic-gate 	return (0);
3140Sstevel@tonic-gate }
3150Sstevel@tonic-gate 
3160Sstevel@tonic-gate /*
3170Sstevel@tonic-gate  * get next entry in a directory.
3180Sstevel@tonic-gate  */
3190Sstevel@tonic-gate struct direct *
readdir(struct dirinfo * dstuff)3200Sstevel@tonic-gate readdir(struct dirinfo *dstuff)
3210Sstevel@tonic-gate {
3220Sstevel@tonic-gate 	struct direct *dp;
3230Sstevel@tonic-gate 	fileid_t *filep;
3240Sstevel@tonic-gate 	daddr32_t lbn, d;
3250Sstevel@tonic-gate 	int off;
3260Sstevel@tonic-gate 	devid_t	*devp;
3270Sstevel@tonic-gate 
3280Sstevel@tonic-gate 	filep = dstuff->fi;
3290Sstevel@tonic-gate 	devp = filep->fi_devp;
3300Sstevel@tonic-gate 	for (;;) {
3310Sstevel@tonic-gate 		if (dstuff->loc >= filep->fi_inode->i_size) {
3320Sstevel@tonic-gate 			return (NULL);
3330Sstevel@tonic-gate 		}
3340Sstevel@tonic-gate 		off = blkoff(&devp->un_fs.di_fs, dstuff->loc);
3350Sstevel@tonic-gate 		dprintf("readdir: off = 0x%x\n", off);
3360Sstevel@tonic-gate 		if (off == 0) {
3370Sstevel@tonic-gate 			lbn = lblkno(&devp->un_fs.di_fs, dstuff->loc);
3380Sstevel@tonic-gate 			d = sbmap(filep, lbn);
3390Sstevel@tonic-gate 
3400Sstevel@tonic-gate 			if (d == 0)
3410Sstevel@tonic-gate 				return (NULL);
3420Sstevel@tonic-gate 
3430Sstevel@tonic-gate 			filep->fi_blocknum = fsbtodb(&devp->un_fs.di_fs, d);
3440Sstevel@tonic-gate 			filep->fi_count =
3450Sstevel@tonic-gate 			    blksize(&devp->un_fs.di_fs, filep->fi_inode, lbn);
3460Sstevel@tonic-gate 			filep->fi_memp = 0;
3470Sstevel@tonic-gate 			if (diskread(filep) != 0) {
3480Sstevel@tonic-gate 				return (NULL);
3490Sstevel@tonic-gate 			}
3500Sstevel@tonic-gate 		}
3510Sstevel@tonic-gate 		dp = (struct direct *)(filep->fi_memp + off);
3520Sstevel@tonic-gate 		dstuff->loc += dp->d_reclen;
3530Sstevel@tonic-gate 		if (dp->d_ino == 0)
3540Sstevel@tonic-gate 			continue;
3550Sstevel@tonic-gate 		dprintf("readdir: name = %s\n", dp->d_name);
3560Sstevel@tonic-gate 		return (dp);
3570Sstevel@tonic-gate 	}
3580Sstevel@tonic-gate }
3590Sstevel@tonic-gate 
3600Sstevel@tonic-gate /*
3610Sstevel@tonic-gate  * Get the next block of data from the file.  If possible, dma right into
3620Sstevel@tonic-gate  * user's buffer
3630Sstevel@tonic-gate  */
3640Sstevel@tonic-gate static int
getblock(fileid_t * filep,caddr_t buf,int count,int * rcount)3650Sstevel@tonic-gate getblock(fileid_t *filep, caddr_t buf, int count, int *rcount)
3660Sstevel@tonic-gate {
3670Sstevel@tonic-gate 	struct fs *fs;
3680Sstevel@tonic-gate 	caddr_t p;
3690Sstevel@tonic-gate 	int off, size, diff;
3700Sstevel@tonic-gate 	daddr32_t lbn;
3710Sstevel@tonic-gate 	devid_t	*devp;
3720Sstevel@tonic-gate 
3730Sstevel@tonic-gate 	dprintf("getblock: buf 0x%p, count 0x%x\n", (void *)buf, count);
3740Sstevel@tonic-gate 
3750Sstevel@tonic-gate 	devp = filep->fi_devp;
3760Sstevel@tonic-gate 	p = filep->fi_memp;
3770Sstevel@tonic-gate 	if ((signed)filep->fi_count <= 0) {
3780Sstevel@tonic-gate 
3790Sstevel@tonic-gate 		/* find the amt left to be read in the file */
3800Sstevel@tonic-gate 		diff = filep->fi_inode->i_size - filep->fi_offset;
3810Sstevel@tonic-gate 		if (diff <= 0) {
3820Sstevel@tonic-gate 			printf("Short read\n");
3830Sstevel@tonic-gate 			return (-1);
3840Sstevel@tonic-gate 		}
3850Sstevel@tonic-gate 
3860Sstevel@tonic-gate 		fs = &devp->un_fs.di_fs;
3870Sstevel@tonic-gate 		/* which block (or frag) in the file do we read? */
3880Sstevel@tonic-gate 		lbn = lblkno(fs, filep->fi_offset);
3890Sstevel@tonic-gate 
3900Sstevel@tonic-gate 		/* which physical block on the device do we read? */
3910Sstevel@tonic-gate 		filep->fi_blocknum = fsbtodb(fs, sbmap(filep, lbn));
3920Sstevel@tonic-gate 
3930Sstevel@tonic-gate 		off = blkoff(fs, filep->fi_offset);
3940Sstevel@tonic-gate 
3950Sstevel@tonic-gate 		/* either blksize or fragsize */
3960Sstevel@tonic-gate 		size = blksize(fs, filep->fi_inode, lbn);
3970Sstevel@tonic-gate 		filep->fi_count = size;
3980Sstevel@tonic-gate 		filep->fi_memp = filep->fi_buf;
3990Sstevel@tonic-gate 
4000Sstevel@tonic-gate 		/*
4010Sstevel@tonic-gate 		 * optimization if we are reading large blocks of data then
4020Sstevel@tonic-gate 		 * we can go directly to user's buffer
4030Sstevel@tonic-gate 		 */
4040Sstevel@tonic-gate 		*rcount = 0;
4050Sstevel@tonic-gate 		if (off == 0 && count >= size) {
4060Sstevel@tonic-gate 			filep->fi_memp = buf;
4070Sstevel@tonic-gate 			if (diskread(filep)) {
4080Sstevel@tonic-gate 				return (-1);
4090Sstevel@tonic-gate 			}
4100Sstevel@tonic-gate 			*rcount = size;
4110Sstevel@tonic-gate 			filep->fi_count = 0;
4120Sstevel@tonic-gate 			return (0);
4130Sstevel@tonic-gate 		} else if (diskread(filep))
4140Sstevel@tonic-gate 			return (-1);
4150Sstevel@tonic-gate 
4160Sstevel@tonic-gate 		if (filep->fi_offset - off + size >= filep->fi_inode->i_size)
4170Sstevel@tonic-gate 			filep->fi_count = diff + off;
4180Sstevel@tonic-gate 		filep->fi_count -= off;
4190Sstevel@tonic-gate 		p = &filep->fi_memp[off];
4200Sstevel@tonic-gate 	}
4210Sstevel@tonic-gate 	filep->fi_memp = p;
4220Sstevel@tonic-gate 	return (0);
4230Sstevel@tonic-gate }
4240Sstevel@tonic-gate 
4253446Smrj /*
4263446Smrj  * Get the next block of data from the file.  Don't attempt to go directly
4273446Smrj  * to user's buffer.
4283446Smrj  */
4293446Smrj static int
getblock_noopt(fileid_t * filep)4303446Smrj getblock_noopt(fileid_t *filep)
4313446Smrj {
4323446Smrj 	struct fs *fs;
4333446Smrj 	caddr_t p;
4343446Smrj 	int off, size, diff;
4353446Smrj 	daddr32_t lbn;
4363446Smrj 	devid_t	*devp;
4373446Smrj 
4383446Smrj 	dprintf("getblock_noopt: start\n");
4393446Smrj 
4403446Smrj 	devp = filep->fi_devp;
4413446Smrj 	p = filep->fi_memp;
4423446Smrj 	if ((signed)filep->fi_count <= 0) {
4433446Smrj 
4443446Smrj 		/* find the amt left to be read in the file */
4453446Smrj 		diff = filep->fi_inode->i_size - filep->fi_offset;
4463446Smrj 		if (diff <= 0) {
4473446Smrj 			printf("Short read\n");
4483446Smrj 			return (-1);
4493446Smrj 		}
4503446Smrj 
4513446Smrj 		fs = &devp->un_fs.di_fs;
4523446Smrj 		/* which block (or frag) in the file do we read? */
4533446Smrj 		lbn = lblkno(fs, filep->fi_offset);
4543446Smrj 
4553446Smrj 		/* which physical block on the device do we read? */
4563446Smrj 		filep->fi_blocknum = fsbtodb(fs, sbmap(filep, lbn));
4573446Smrj 
4583446Smrj 		off = blkoff(fs, filep->fi_offset);
4593446Smrj 
4603446Smrj 		/* either blksize or fragsize */
4613446Smrj 		size = blksize(fs, filep->fi_inode, lbn);
4623446Smrj 		filep->fi_count = size;
4633446Smrj 		/* reading on a ramdisk, just get a pointer to the data */
4643446Smrj 		filep->fi_memp = NULL;
4653446Smrj 
4663446Smrj 		if (diskread(filep))
4673446Smrj 			return (-1);
4683446Smrj 
4693446Smrj 		if (filep->fi_offset - off + size >= filep->fi_inode->i_size)
4703446Smrj 			filep->fi_count = diff + off;
4713446Smrj 		filep->fi_count -= off;
4723446Smrj 		p = &filep->fi_memp[off];
4733446Smrj 	}
4743446Smrj 	filep->fi_memp = p;
4753446Smrj 	return (0);
4763446Smrj }
4773446Smrj 
4780Sstevel@tonic-gate 
4790Sstevel@tonic-gate /*
4800Sstevel@tonic-gate  *  This is the high-level read function.  It works like this.
4810Sstevel@tonic-gate  *  We assume that our IO device buffers up some amount of
4820Sstevel@tonic-gate  *  data and that we can get a ptr to it.  Thus we need
4830Sstevel@tonic-gate  *  to actually call the device func about filesize/blocksize times
4840Sstevel@tonic-gate  *  and this greatly increases our IO speed.  When we already
4850Sstevel@tonic-gate  *  have data in the buffer, we just return that data (with bcopy() ).
4860Sstevel@tonic-gate  */
4870Sstevel@tonic-gate 
4880Sstevel@tonic-gate static ssize_t
bufs_read(int fd,caddr_t buf,size_t count)4890Sstevel@tonic-gate bufs_read(int fd, caddr_t buf, size_t count)
4900Sstevel@tonic-gate {
4910Sstevel@tonic-gate 	size_t i, j;
4920Sstevel@tonic-gate 	caddr_t	n;
4930Sstevel@tonic-gate 	int rcount;
4940Sstevel@tonic-gate 	fileid_t *filep;
4950Sstevel@tonic-gate 
4960Sstevel@tonic-gate 	if (!(filep = find_fp(fd))) {
4970Sstevel@tonic-gate 		return (-1);
4980Sstevel@tonic-gate 	}
4990Sstevel@tonic-gate 
5003446Smrj 	if ((filep->fi_flags & FI_COMPRESSED) == 0 &&
5013446Smrj 	    filep->fi_offset + count > filep->fi_inode->i_size)
5020Sstevel@tonic-gate 		count = filep->fi_inode->i_size - filep->fi_offset;
5030Sstevel@tonic-gate 
5040Sstevel@tonic-gate 	/* that was easy */
5050Sstevel@tonic-gate 	if ((i = count) == 0)
5060Sstevel@tonic-gate 		return (0);
5070Sstevel@tonic-gate 
5080Sstevel@tonic-gate 	n = buf;
5090Sstevel@tonic-gate 	while (i > 0) {
5103446Smrj 		if (filep->fi_flags & FI_COMPRESSED) {
5113446Smrj 			if ((j = cf_read(filep, buf, count)) < 0)
5123446Smrj 				return (0); /* encountered an error */
5133446Smrj 			if (j < i)
5143446Smrj 				i = j; /* short read, must have hit EOF */
5150Sstevel@tonic-gate 		} else {
5163446Smrj 			/* If we need to reload the buffer, do so */
5173446Smrj 			if ((j = filep->fi_count) == 0) {
5183446Smrj 				(void) getblock(filep, buf, i, &rcount);
5193446Smrj 				i -= rcount;
5203446Smrj 				buf += rcount;
5213446Smrj 				filep->fi_offset += rcount;
5223446Smrj 				continue;
5233446Smrj 			} else {
5243446Smrj 				/* else just bcopy from our buffer */
5253446Smrj 				j = MIN(i, j);
5263446Smrj 				bcopy(filep->fi_memp, buf, (unsigned)j);
5273446Smrj 			}
5280Sstevel@tonic-gate 		}
5293446Smrj 		buf += j;
5303446Smrj 		filep->fi_memp += j;
5313446Smrj 		filep->fi_offset += j;
5323446Smrj 		filep->fi_count -= j;
5333446Smrj 		i -= j;
5340Sstevel@tonic-gate 	}
5350Sstevel@tonic-gate 	return (buf - n);
5360Sstevel@tonic-gate }
5370Sstevel@tonic-gate 
5380Sstevel@tonic-gate /*
5390Sstevel@tonic-gate  *	This routine will open a device as it is known by the V2 OBP.
5400Sstevel@tonic-gate  *	Interface Defn:
5410Sstevel@tonic-gate  *	err = mountroot(string);
5420Sstevel@tonic-gate  *		err = 0 on success
5430Sstevel@tonic-gate  *		err = -1 on failure
5440Sstevel@tonic-gate  *	string:	char string describing the properties of the device.
5450Sstevel@tonic-gate  *	We must not dork with any fi[]'s here.  Save that for later.
5460Sstevel@tonic-gate  */
5470Sstevel@tonic-gate 
5480Sstevel@tonic-gate static int
bufs_mountroot(char * str)5490Sstevel@tonic-gate bufs_mountroot(char *str)
5500Sstevel@tonic-gate {
5510Sstevel@tonic-gate 	if (ufs_devp)		/* already mounted */
5520Sstevel@tonic-gate 		return (0);
5530Sstevel@tonic-gate 
5540Sstevel@tonic-gate 	ufs_devp = (devid_t *)bkmem_alloc(sizeof (devid_t));
5550Sstevel@tonic-gate 	ufs_devp->di_taken = 1;
5560Sstevel@tonic-gate 	ufs_devp->di_dcookie = 0;
5570Sstevel@tonic-gate 	ufs_devp->di_desc = (char *)bkmem_alloc(strlen(str) + 1);
5580Sstevel@tonic-gate 	(void) strcpy(ufs_devp->di_desc, str);
5590Sstevel@tonic-gate 	bzero(ufs_devp->un_fs.dummy, SBSIZE);
5600Sstevel@tonic-gate 	head = (fileid_t *)bkmem_alloc(sizeof (fileid_t));
5610Sstevel@tonic-gate 	head->fi_back = head->fi_forw = head;
5620Sstevel@tonic-gate 	head->fi_filedes = 0;
5630Sstevel@tonic-gate 	head->fi_taken = 0;
5640Sstevel@tonic-gate 
5650Sstevel@tonic-gate 	/* Setup read of the superblock */
5660Sstevel@tonic-gate 	head->fi_devp = ufs_devp;
5670Sstevel@tonic-gate 	head->fi_blocknum = SBLOCK;
5680Sstevel@tonic-gate 	head->fi_count = (uint_t)SBSIZE;
5690Sstevel@tonic-gate 	head->fi_memp = (caddr_t)&(ufs_devp->un_fs.di_fs);
5700Sstevel@tonic-gate 	head->fi_offset = 0;
5710Sstevel@tonic-gate 
5720Sstevel@tonic-gate 	if (diskread(head)) {
5730Sstevel@tonic-gate 		printf("failed to read superblock\n");
5740Sstevel@tonic-gate 		(void) bufs_closeall(1);
5750Sstevel@tonic-gate 		return (-1);
5760Sstevel@tonic-gate 	}
5770Sstevel@tonic-gate 
5780Sstevel@tonic-gate 	if (ufs_devp->un_fs.di_fs.fs_magic != FS_MAGIC) {
5790Sstevel@tonic-gate 		dprintf("fs magic = 0x%x\n", ufs_devp->un_fs.di_fs.fs_magic);
5800Sstevel@tonic-gate 		(void) bufs_closeall(1);
5810Sstevel@tonic-gate 		return (-1);
5820Sstevel@tonic-gate 	}
5830Sstevel@tonic-gate 	dprintf("mountroot succeeded\n");
5840Sstevel@tonic-gate 	return (0);
5850Sstevel@tonic-gate }
5860Sstevel@tonic-gate 
5870Sstevel@tonic-gate /*
5880Sstevel@tonic-gate  * Unmount the currently mounted root fs.  In practice, this means
5890Sstevel@tonic-gate  * closing all open files and releasing resources.  All of this
5900Sstevel@tonic-gate  * is done by closeall().
5910Sstevel@tonic-gate  */
5920Sstevel@tonic-gate 
5930Sstevel@tonic-gate static int
bufs_unmountroot(void)5940Sstevel@tonic-gate bufs_unmountroot(void)
5950Sstevel@tonic-gate {
5960Sstevel@tonic-gate 	if (ufs_devp == NULL)
5970Sstevel@tonic-gate 		return (-1);
5980Sstevel@tonic-gate 
5990Sstevel@tonic-gate 	(void) bufs_closeall(1);
6000Sstevel@tonic-gate 
6010Sstevel@tonic-gate 	return (0);
6020Sstevel@tonic-gate }
6030Sstevel@tonic-gate 
6040Sstevel@tonic-gate /*
6050Sstevel@tonic-gate  *	We allocate an fd here for use when talking
6060Sstevel@tonic-gate  *	to the file itself.
6070Sstevel@tonic-gate  */
6080Sstevel@tonic-gate 
6090Sstevel@tonic-gate /*ARGSUSED*/
6100Sstevel@tonic-gate static int
bufs_open(char * filename,int flags)6110Sstevel@tonic-gate bufs_open(char *filename, int flags)
6120Sstevel@tonic-gate {
6130Sstevel@tonic-gate 	fileid_t	*filep;
6140Sstevel@tonic-gate 	ino_t	inode;
6150Sstevel@tonic-gate 	static int	filedes = 1;
6160Sstevel@tonic-gate 
6170Sstevel@tonic-gate 	dprintf("open: %s\n", filename);
6180Sstevel@tonic-gate 
6190Sstevel@tonic-gate 	/* build and link a new file descriptor */
6200Sstevel@tonic-gate 	filep = (fileid_t *)bkmem_alloc(sizeof (fileid_t));
6210Sstevel@tonic-gate 	filep->fi_back = head->fi_back;
6220Sstevel@tonic-gate 	filep->fi_forw = head;
6230Sstevel@tonic-gate 	head->fi_back->fi_forw = filep;
6240Sstevel@tonic-gate 	head->fi_back = filep;
6250Sstevel@tonic-gate 	filep->fi_filedes = filedes++;
6260Sstevel@tonic-gate 	filep->fi_taken = 1;
6270Sstevel@tonic-gate 	filep->fi_path = (char *)bkmem_alloc(strlen(filename) + 1);
6280Sstevel@tonic-gate 	(void) strcpy(filep->fi_path, filename);
6290Sstevel@tonic-gate 	filep->fi_devp = ufs_devp; /* dev is already "mounted" */
6300Sstevel@tonic-gate 	filep->fi_inode = NULL;
6310Sstevel@tonic-gate 	bzero(filep->fi_buf, MAXBSIZE);
6323446Smrj 	filep->fi_getblock = getblock_noopt;
6333446Smrj 	filep->fi_flags = 0;
6340Sstevel@tonic-gate 
6350Sstevel@tonic-gate 	inode = find(filep, (char *)filename);
6360Sstevel@tonic-gate 	if (inode == (ino_t)0) {
6370Sstevel@tonic-gate 		dprintf("open: cannot find %s\n", filename);
6380Sstevel@tonic-gate 		(void) bufs_close(filep->fi_filedes);
6390Sstevel@tonic-gate 		return (-1);
6400Sstevel@tonic-gate 	}
6410Sstevel@tonic-gate 	if (openi(filep, inode)) {
6420Sstevel@tonic-gate 		printf("open: cannot open %s\n", filename);
6430Sstevel@tonic-gate 		(void) bufs_close(filep->fi_filedes);
6440Sstevel@tonic-gate 		return (-1);
6450Sstevel@tonic-gate 	}
6460Sstevel@tonic-gate 
6470Sstevel@tonic-gate 	filep->fi_offset = filep->fi_count = 0;
6480Sstevel@tonic-gate 
6493446Smrj 	if (cf_check_compressed(filep) != 0)
6503446Smrj 		return (-1);
6510Sstevel@tonic-gate 	return (filep->fi_filedes);
6520Sstevel@tonic-gate }
6530Sstevel@tonic-gate 
6540Sstevel@tonic-gate /*
6550Sstevel@tonic-gate  *  We don't do any IO here.
6560Sstevel@tonic-gate  *  We just play games with the device pointers.
6570Sstevel@tonic-gate  */
6580Sstevel@tonic-gate 
6590Sstevel@tonic-gate static off_t
bufs_lseek(int fd,off_t addr,int whence)6600Sstevel@tonic-gate bufs_lseek(int fd, off_t addr, int whence)
6610Sstevel@tonic-gate {
6620Sstevel@tonic-gate 	fileid_t *filep;
6630Sstevel@tonic-gate 
6640Sstevel@tonic-gate 	/* Make sure user knows what file he is talking to */
6650Sstevel@tonic-gate 	if (!(filep = find_fp(fd)))
6660Sstevel@tonic-gate 		return (-1);
6670Sstevel@tonic-gate 
6683446Smrj 	if (filep->fi_flags & FI_COMPRESSED) {
6693446Smrj 		cf_seek(filep, addr, whence);
6703446Smrj 	} else {
6713446Smrj 		switch (whence) {
6723446Smrj 		case SEEK_CUR:
6733446Smrj 			filep->fi_offset += addr;
6743446Smrj 			break;
6753446Smrj 		case SEEK_SET:
6763446Smrj 			filep->fi_offset = addr;
6773446Smrj 			break;
6783446Smrj 		default:
6793446Smrj 		case SEEK_END:
6803446Smrj 			printf("lseek(): invalid whence value %d\n", whence);
6813446Smrj 			break;
6823446Smrj 		}
6833446Smrj 		filep->fi_blocknum = addr / DEV_BSIZE;
6840Sstevel@tonic-gate 	}
6850Sstevel@tonic-gate 
6860Sstevel@tonic-gate 	filep->fi_count = 0;
6870Sstevel@tonic-gate 
6880Sstevel@tonic-gate 	return (0);
6890Sstevel@tonic-gate }
6900Sstevel@tonic-gate 
6911544Seschrock 
6921544Seschrock int
bufs_fstat(int fd,struct bootstat * stp)6931544Seschrock bufs_fstat(int fd, struct bootstat *stp)
6941544Seschrock {
6951544Seschrock 	fileid_t	*filep;
6961544Seschrock 	struct inode	*ip;
6971544Seschrock 
6981544Seschrock 	if (!(filep = find_fp(fd)))
6991544Seschrock 		return (-1);
7001544Seschrock 
7011544Seschrock 	ip = filep->fi_inode;
7021544Seschrock 
7031544Seschrock 	stp->st_mode = 0;
7041544Seschrock 	stp->st_size = 0;
7051544Seschrock 
7061544Seschrock 	if (ip == NULL)
7071544Seschrock 		return (0);
7081544Seschrock 
7091544Seschrock 	switch (ip->i_smode & IFMT) {
7101544Seschrock 	case IFLNK:
7111544Seschrock 		stp->st_mode = S_IFLNK;
7121544Seschrock 		break;
7131544Seschrock 	case IFREG:
7141544Seschrock 		stp->st_mode = S_IFREG;
7151544Seschrock 		break;
7161544Seschrock 	default:
7171544Seschrock 		break;
7181544Seschrock 	}
7193446Smrj 	/*
7203446Smrj 	 * NOTE: this size will be the compressed size for a compressed file
7213446Smrj 	 * This could confuse the caller since we decompress the file behind
7223446Smrj 	 * the scenes when the file is read.
7233446Smrj 	 */
7241544Seschrock 	stp->st_size = ip->i_size;
7251544Seschrock 	stp->st_atim.tv_sec = ip->i_atime.tv_sec;
7261544Seschrock 	stp->st_atim.tv_nsec = ip->i_atime.tv_usec * 1000;
7271544Seschrock 	stp->st_mtim.tv_sec = ip->i_mtime.tv_sec;
7281544Seschrock 	stp->st_mtim.tv_nsec = ip->i_mtime.tv_usec * 1000;
7291544Seschrock 	stp->st_ctim.tv_sec = ip->i_ctime.tv_sec;
7301544Seschrock 	stp->st_ctim.tv_nsec = ip->i_ctime.tv_usec * 1000;
7311544Seschrock 
7321544Seschrock 	return (0);
7331544Seschrock }
7341544Seschrock 
7351544Seschrock 
7360Sstevel@tonic-gate static int
bufs_close(int fd)7370Sstevel@tonic-gate bufs_close(int fd)
7380Sstevel@tonic-gate {
7390Sstevel@tonic-gate 	fileid_t *filep;
7400Sstevel@tonic-gate 
7410Sstevel@tonic-gate 	/* Make sure user knows what file he is talking to */
7420Sstevel@tonic-gate 	if (!(filep = find_fp(fd)))
7430Sstevel@tonic-gate 		return (-1);
7440Sstevel@tonic-gate 
7450Sstevel@tonic-gate 	if (filep->fi_taken && (filep != head)) {
7460Sstevel@tonic-gate 		/* Clear the ranks */
7470Sstevel@tonic-gate 		bkmem_free(filep->fi_path, strlen(filep->fi_path)+1);
7480Sstevel@tonic-gate 		filep->fi_blocknum = filep->fi_count = filep->fi_offset = 0;
7490Sstevel@tonic-gate 		filep->fi_memp = (caddr_t)0;
7500Sstevel@tonic-gate 		filep->fi_devp = 0;
7510Sstevel@tonic-gate 		filep->fi_taken = 0;
7520Sstevel@tonic-gate 
7530Sstevel@tonic-gate 		/* unlink and deallocate node */
7540Sstevel@tonic-gate 		filep->fi_forw->fi_back = filep->fi_back;
7550Sstevel@tonic-gate 		filep->fi_back->fi_forw = filep->fi_forw;
7563446Smrj 		cf_close(filep);
7570Sstevel@tonic-gate 		bkmem_free((char *)filep, sizeof (fileid_t));
7580Sstevel@tonic-gate 
7590Sstevel@tonic-gate 		return (0);
7600Sstevel@tonic-gate 	} else {
7610Sstevel@tonic-gate 		/* Big problem */
7620Sstevel@tonic-gate 		printf("\nFile descrip %d not allocated!", fd);
7630Sstevel@tonic-gate 		return (-1);
7640Sstevel@tonic-gate 	}
7650Sstevel@tonic-gate }
7660Sstevel@tonic-gate 
7670Sstevel@tonic-gate /*ARGSUSED*/
7680Sstevel@tonic-gate static void
bufs_closeall(int flag)7690Sstevel@tonic-gate bufs_closeall(int flag)
7700Sstevel@tonic-gate {
7710Sstevel@tonic-gate 	fileid_t *filep = head;
7720Sstevel@tonic-gate 
7730Sstevel@tonic-gate 	while ((filep = filep->fi_forw) != head)
7740Sstevel@tonic-gate 		if (filep->fi_taken)
7750Sstevel@tonic-gate 			if (bufs_close(filep->fi_filedes))
7760Sstevel@tonic-gate 				printf("Filesystem may be inconsistent.\n");
7770Sstevel@tonic-gate 
7780Sstevel@tonic-gate 	ufs_devp->di_taken = 0;
7790Sstevel@tonic-gate 	bkmem_free((char *)ufs_devp, sizeof (devid_t));
7800Sstevel@tonic-gate 	bkmem_free((char *)head, sizeof (fileid_t));
7810Sstevel@tonic-gate 	ufs_devp = (devid_t *)NULL;
7820Sstevel@tonic-gate 	head = (fileid_t *)NULL;
7830Sstevel@tonic-gate 	free_cache();
7840Sstevel@tonic-gate }
7850Sstevel@tonic-gate 
7860Sstevel@tonic-gate static struct cache {
7870Sstevel@tonic-gate 	struct cache *next;
7880Sstevel@tonic-gate 	void *data;
7890Sstevel@tonic-gate 	int key;
7900Sstevel@tonic-gate 	uint_t size;
7910Sstevel@tonic-gate } *icache;
7920Sstevel@tonic-gate 
7930Sstevel@tonic-gate void
set_cache(int key,void * data,uint_t size)7940Sstevel@tonic-gate set_cache(int key, void *data, uint_t size)
7950Sstevel@tonic-gate {
7960Sstevel@tonic-gate 	struct cache *entry = bkmem_alloc(sizeof (*entry));
7970Sstevel@tonic-gate 	entry->key = key;
7980Sstevel@tonic-gate 	entry->data = data;
7990Sstevel@tonic-gate 	entry->size = size;
8000Sstevel@tonic-gate 	if (icache) {
8010Sstevel@tonic-gate 		entry->next = icache;
8020Sstevel@tonic-gate 		icache = entry;
8030Sstevel@tonic-gate 	} else {
8040Sstevel@tonic-gate 		icache = entry;
8050Sstevel@tonic-gate 		entry->next = 0;
8060Sstevel@tonic-gate 	}
8070Sstevel@tonic-gate }
8080Sstevel@tonic-gate 
8090Sstevel@tonic-gate void *
get_cache(int key)8100Sstevel@tonic-gate get_cache(int key)
8110Sstevel@tonic-gate {
8120Sstevel@tonic-gate 	struct cache *entry = icache;
8130Sstevel@tonic-gate 	while (entry) {
8140Sstevel@tonic-gate 		if (entry->key == key)
8150Sstevel@tonic-gate 			return (entry->data);
8160Sstevel@tonic-gate 		entry = entry->next;
8170Sstevel@tonic-gate 	}
8180Sstevel@tonic-gate 	return (NULL);
8190Sstevel@tonic-gate }
8200Sstevel@tonic-gate 
8210Sstevel@tonic-gate void
free_cache()8220Sstevel@tonic-gate free_cache()
8230Sstevel@tonic-gate {
8240Sstevel@tonic-gate 	struct cache *next, *entry = icache;
8250Sstevel@tonic-gate 	while (entry) {
8260Sstevel@tonic-gate 		next = entry->next;
8270Sstevel@tonic-gate 		bkmem_free(entry->data, entry->size);
8280Sstevel@tonic-gate 		bkmem_free(entry, sizeof (*entry));
8290Sstevel@tonic-gate 		entry = next;
8300Sstevel@tonic-gate 	}
8310Sstevel@tonic-gate 	icache = 0;
8320Sstevel@tonic-gate }
8330Sstevel@tonic-gate 
8340Sstevel@tonic-gate struct boot_fs_ops bufs_ops = {
8350Sstevel@tonic-gate 	"boot_ufs",
8360Sstevel@tonic-gate 	bufs_mountroot,
8370Sstevel@tonic-gate 	bufs_unmountroot,
8380Sstevel@tonic-gate 	bufs_open,
8390Sstevel@tonic-gate 	bufs_close,
8400Sstevel@tonic-gate 	bufs_read,
8410Sstevel@tonic-gate 	bufs_lseek,
8421544Seschrock 	bufs_fstat,
8430Sstevel@tonic-gate 	NULL
8440Sstevel@tonic-gate };
845