xref: /onnv-gate/usr/src/cmd/fs.d/preenlib.c (revision 821:ef17b74dd690)
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
50Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
60Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
70Sstevel@tonic-gate  * with the License.
80Sstevel@tonic-gate  *
90Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
100Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
110Sstevel@tonic-gate  * See the License for the specific language governing permissions
120Sstevel@tonic-gate  * and limitations under the License.
130Sstevel@tonic-gate  *
140Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
150Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
160Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
170Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
180Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
190Sstevel@tonic-gate  *
200Sstevel@tonic-gate  * CDDL HEADER END
210Sstevel@tonic-gate  */
220Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
230Sstevel@tonic-gate /*
24*821Sdh145677  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
25*821Sdh145677  * Use is subject to license terms.
260Sstevel@tonic-gate  */
270Sstevel@tonic-gate 
280Sstevel@tonic-gate /*
290Sstevel@tonic-gate  * common routines for parallelization (used by both fsck and quotacheck)
300Sstevel@tonic-gate  */
310Sstevel@tonic-gate #include <stdio.h>
320Sstevel@tonic-gate #include <fcntl.h>
330Sstevel@tonic-gate #include <dlfcn.h>
340Sstevel@tonic-gate #include <macros.h>
350Sstevel@tonic-gate #include <sys/types.h>
360Sstevel@tonic-gate #include <sys/wait.h>
370Sstevel@tonic-gate #include <sys/mntent.h>
380Sstevel@tonic-gate #include <sys/dkio.h>
390Sstevel@tonic-gate 
400Sstevel@tonic-gate /*
410Sstevel@tonic-gate  * data structures for parallelization
420Sstevel@tonic-gate  */
43*821Sdh145677 struct driver {
440Sstevel@tonic-gate 	char 	*name;			/* driver name (from DKIOCINFO) */
450Sstevel@tonic-gate 	uint_t	mapsize;		/* size of `busymap' */
460Sstevel@tonic-gate 	uint_t	*busymap;		/* bitmask of active units */
470Sstevel@tonic-gate 	int	(*choosefunc)();	/* driver specific chooser */
480Sstevel@tonic-gate 	void	*data;			/* driver private data */
490Sstevel@tonic-gate };
500Sstevel@tonic-gate 
51*821Sdh145677 struct onedev {
520Sstevel@tonic-gate 	int	drvid;			/* index in driver array */
530Sstevel@tonic-gate 	uint_t	mapsize;		/* size of `unitmap' */
540Sstevel@tonic-gate 	uint_t	*unitmap;		/* unit #'s (from DKIOCINFO) */
550Sstevel@tonic-gate 	struct onedev *nxtdev;
560Sstevel@tonic-gate };
570Sstevel@tonic-gate 
58*821Sdh145677 struct rawdev {
590Sstevel@tonic-gate 	char	*devname;		/* name passed to preen_addev */
600Sstevel@tonic-gate 	struct	onedev *alldevs;	/* info about each component device */
610Sstevel@tonic-gate 	struct rawdev *nxtrd;		/* next entry in list */
620Sstevel@tonic-gate };
630Sstevel@tonic-gate 
640Sstevel@tonic-gate static int debug = 0;
650Sstevel@tonic-gate 
660Sstevel@tonic-gate /*
670Sstevel@tonic-gate  * defines used in building shared object names
680Sstevel@tonic-gate  */
690Sstevel@tonic-gate 
700Sstevel@tonic-gate /* the directory where we find shared objects */
710Sstevel@tonic-gate #define	OBJECT_DIRECTORY	"/usr/lib/drv"
720Sstevel@tonic-gate 
730Sstevel@tonic-gate /* a shared object name is OBJECT_PREFIX || driver_name */
740Sstevel@tonic-gate #define	OBJECT_PREFIX		"preen_"
750Sstevel@tonic-gate 
760Sstevel@tonic-gate /* the version of the driver interface we support */
770Sstevel@tonic-gate #define	OBJECT_VERSION		1
780Sstevel@tonic-gate 
790Sstevel@tonic-gate /* the "build" entry point for a driver specific object is named this */
800Sstevel@tonic-gate #define	BUILD_ENTRY		preen_build_devs
810Sstevel@tonic-gate #define	BUILD_NAME		"preen_build_devs"
820Sstevel@tonic-gate 
830Sstevel@tonic-gate #define	DRIVER_ALLOC	10
840Sstevel@tonic-gate static int ndrivers, ndalloc;
850Sstevel@tonic-gate static struct driver *dlist;
860Sstevel@tonic-gate 
870Sstevel@tonic-gate static struct rawdev *unchecked, *active, *get_runnable();
880Sstevel@tonic-gate static struct onedev *alloc_dev();
890Sstevel@tonic-gate static int chooseone();
900Sstevel@tonic-gate 
910Sstevel@tonic-gate #define	WORDSIZE	(NBBY * sizeof (uint_t))
920Sstevel@tonic-gate 
930Sstevel@tonic-gate void 	preen_addunit(void *, char *, int (*)(), void *, uint_t);
940Sstevel@tonic-gate int 	preen_subdev(char *, struct dk_cinfo *, void *);
950Sstevel@tonic-gate 
960Sstevel@tonic-gate static int 	alloc_driver(char *, int (*)(), void *);
970Sstevel@tonic-gate static void 	addunit(struct onedev *, uint_t);
980Sstevel@tonic-gate static void	makebusy(struct onedev *);
990Sstevel@tonic-gate static void	notbusy(struct rawdev *);
1000Sstevel@tonic-gate 
1010Sstevel@tonic-gate /*
1020Sstevel@tonic-gate  * add the given device to the list of devices to be checked
1030Sstevel@tonic-gate  */
104*821Sdh145677 int
preen_addev(char * devnm)1050Sstevel@tonic-gate preen_addev(char *devnm)
1060Sstevel@tonic-gate {
1070Sstevel@tonic-gate 	struct rawdev *rdp;
1080Sstevel@tonic-gate 	int fd;
1090Sstevel@tonic-gate 	struct dk_cinfo dki;
1100Sstevel@tonic-gate 	extern char *strdup();
1110Sstevel@tonic-gate 
1120Sstevel@tonic-gate 	if ((fd = open64(devnm, O_RDONLY)) == -1) {
1130Sstevel@tonic-gate 		perror(devnm);
1140Sstevel@tonic-gate 		return (-1);
1150Sstevel@tonic-gate 	}
1160Sstevel@tonic-gate 	if (ioctl(fd, DKIOCINFO, &dki) == -1) {
1170Sstevel@tonic-gate 		perror("DKIOCINFO");
1180Sstevel@tonic-gate 		fprintf(stderr, "device: `%s'\n", devnm);
1190Sstevel@tonic-gate 		(void) close(fd);
1200Sstevel@tonic-gate 		return (-1);
1210Sstevel@tonic-gate 	}
1220Sstevel@tonic-gate 	(void) close(fd);
1230Sstevel@tonic-gate 	if ((rdp = (struct rawdev *)malloc(sizeof (struct rawdev))) == NULL) {
1240Sstevel@tonic-gate 		(void) fprintf(stderr, "out of memory in preenlib\n");
1250Sstevel@tonic-gate 		return (-1);
1260Sstevel@tonic-gate 	}
1270Sstevel@tonic-gate 	if ((rdp->devname = strdup(devnm)) == NULL) {
1280Sstevel@tonic-gate 		(void) fprintf(stderr, "out of memory in preenlib\n");
1290Sstevel@tonic-gate 		return (-1);
1300Sstevel@tonic-gate 	}
1310Sstevel@tonic-gate 	rdp->alldevs = NULL;
1320Sstevel@tonic-gate 	rdp->nxtrd = NULL;
1330Sstevel@tonic-gate 
1340Sstevel@tonic-gate 	if (preen_subdev(devnm, &dki, (void *)rdp)) {
1350Sstevel@tonic-gate 		preen_addunit(rdp, dki.dki_dname, NULL, NULL, dki.dki_unit);
1360Sstevel@tonic-gate 	}
1370Sstevel@tonic-gate 
1380Sstevel@tonic-gate 	rdp->nxtrd = unchecked;
1390Sstevel@tonic-gate 	unchecked = rdp;
1400Sstevel@tonic-gate 	return (0);
1410Sstevel@tonic-gate }
1420Sstevel@tonic-gate 
143*821Sdh145677 int
preen_subdev(char * name,struct dk_cinfo * dkiop,void * dp)1440Sstevel@tonic-gate preen_subdev(char *name, struct dk_cinfo *dkiop, void *dp)
1450Sstevel@tonic-gate {
1460Sstevel@tonic-gate 	char modname[255];
1470Sstevel@tonic-gate 	void *dlhandle;
1480Sstevel@tonic-gate 	int (*fptr)();
1490Sstevel@tonic-gate 
1500Sstevel@tonic-gate 	(void) sprintf(modname, "%s/%s%s.so.%d",
1510Sstevel@tonic-gate 	    OBJECT_DIRECTORY, OBJECT_PREFIX, dkiop->dki_dname, OBJECT_VERSION);
1520Sstevel@tonic-gate 	dlhandle = dlopen(modname, RTLD_LAZY);
1530Sstevel@tonic-gate 	if (dlhandle == NULL) {
1540Sstevel@tonic-gate 		if (debug)
1550Sstevel@tonic-gate 			(void) fprintf(stderr, "preen_subdev: %s\n", dlerror());
1560Sstevel@tonic-gate 		return (1);
1570Sstevel@tonic-gate 	}
1580Sstevel@tonic-gate 	fptr = (int (*)())dlsym(dlhandle, BUILD_NAME);
1590Sstevel@tonic-gate 	if (fptr == NULL) {
1600Sstevel@tonic-gate 		if (debug)
1610Sstevel@tonic-gate 			(void) fprintf(stderr, "preen_subdev: %s\n", dlerror());
1620Sstevel@tonic-gate 		return (1);
1630Sstevel@tonic-gate 	}
1640Sstevel@tonic-gate 	(*fptr)(name, dkiop, dp);
1650Sstevel@tonic-gate 	return (0);
1660Sstevel@tonic-gate }
1670Sstevel@tonic-gate 
1680Sstevel@tonic-gate /*
1690Sstevel@tonic-gate  * select a device from the "unchecked" list, and add it to the
1700Sstevel@tonic-gate  * active list.
1710Sstevel@tonic-gate  */
172*821Sdh145677 int
preen_getdev(char * devnm)1730Sstevel@tonic-gate preen_getdev(char *devnm)
1740Sstevel@tonic-gate {
1750Sstevel@tonic-gate 	struct rawdev *rdp;
176*821Sdh145677 	struct onedev *dp;
1770Sstevel@tonic-gate 
1780Sstevel@tonic-gate 	if (unchecked == NULL)
1790Sstevel@tonic-gate 		return (0);
1800Sstevel@tonic-gate 
1810Sstevel@tonic-gate 	rdp = get_runnable(&unchecked);
1820Sstevel@tonic-gate 
1830Sstevel@tonic-gate 	if (rdp) {
1840Sstevel@tonic-gate 		for (dp = rdp->alldevs; dp; dp = dp->nxtdev) {
1850Sstevel@tonic-gate 			makebusy(dp);
1860Sstevel@tonic-gate 		}
1870Sstevel@tonic-gate 		rdp->nxtrd = active;
1880Sstevel@tonic-gate 		active = rdp;
1890Sstevel@tonic-gate 		(void) strcpy(devnm, rdp->devname);
1900Sstevel@tonic-gate 		return (1);
1910Sstevel@tonic-gate 	} else {
1920Sstevel@tonic-gate 		return (2);
1930Sstevel@tonic-gate 	}
1940Sstevel@tonic-gate }
1950Sstevel@tonic-gate 
196*821Sdh145677 int
preen_releasedev(char * name)1970Sstevel@tonic-gate preen_releasedev(char *name)
1980Sstevel@tonic-gate {
199*821Sdh145677 	struct rawdev *dp, *ldp;
2000Sstevel@tonic-gate 
2010Sstevel@tonic-gate 	for (ldp = NULL, dp = active; dp != NULL; ldp = dp, dp = dp->nxtrd) {
2020Sstevel@tonic-gate 		if (strcmp(dp->devname, name) == 0)
2030Sstevel@tonic-gate 			break;
2040Sstevel@tonic-gate 	}
2050Sstevel@tonic-gate 
2060Sstevel@tonic-gate 	if (dp == NULL)
2070Sstevel@tonic-gate 		return (-1);
2080Sstevel@tonic-gate 	if (ldp != NULL) {
2090Sstevel@tonic-gate 		ldp->nxtrd = dp->nxtrd;
2100Sstevel@tonic-gate 	} else {
2110Sstevel@tonic-gate 		active = dp->nxtrd;
2120Sstevel@tonic-gate 	}
2130Sstevel@tonic-gate 
2140Sstevel@tonic-gate 	notbusy(dp);
2150Sstevel@tonic-gate 	/*
2160Sstevel@tonic-gate 	 * free(dp->devname);
2170Sstevel@tonic-gate 	 * free(dp);
2180Sstevel@tonic-gate 	 */
2190Sstevel@tonic-gate 	return (0);
2200Sstevel@tonic-gate }
2210Sstevel@tonic-gate 
2220Sstevel@tonic-gate static
2230Sstevel@tonic-gate struct rawdev *
get_runnable(struct rawdev ** devlist)2240Sstevel@tonic-gate get_runnable(struct rawdev **devlist)
2250Sstevel@tonic-gate {
226*821Sdh145677 	struct rawdev *last, *rdp;
227*821Sdh145677 	struct onedev *devp;
228*821Sdh145677 	struct driver *drvp;
2290Sstevel@tonic-gate 	int rc = 1;
2300Sstevel@tonic-gate 
2310Sstevel@tonic-gate 	for (last = NULL, rdp = *devlist; rdp; last = rdp, rdp = rdp->nxtrd) {
2320Sstevel@tonic-gate 		for (devp = rdp->alldevs; devp != NULL; devp = devp->nxtdev) {
2330Sstevel@tonic-gate 			drvp = &dlist[devp->drvid];
2340Sstevel@tonic-gate 			rc = (*drvp->choosefunc)(devp->mapsize, devp->unitmap,
2350Sstevel@tonic-gate 			    drvp->mapsize, drvp->busymap);
2360Sstevel@tonic-gate 			if (rc != 0)
2370Sstevel@tonic-gate 				break;
2380Sstevel@tonic-gate 		}
2390Sstevel@tonic-gate 		if (rc == 0)
2400Sstevel@tonic-gate 			break;
2410Sstevel@tonic-gate 	}
2420Sstevel@tonic-gate 
2430Sstevel@tonic-gate 	/*
2440Sstevel@tonic-gate 	 * remove from list...
2450Sstevel@tonic-gate 	 */
2460Sstevel@tonic-gate 	if (rdp) {
2470Sstevel@tonic-gate 		if (last) {
2480Sstevel@tonic-gate 			last->nxtrd = rdp->nxtrd;
2490Sstevel@tonic-gate 		} else {
2500Sstevel@tonic-gate 			*devlist = rdp->nxtrd;
2510Sstevel@tonic-gate 		}
2520Sstevel@tonic-gate 	}
2530Sstevel@tonic-gate 
2540Sstevel@tonic-gate 	return (rdp);
2550Sstevel@tonic-gate }
2560Sstevel@tonic-gate 
2570Sstevel@tonic-gate /*
2580Sstevel@tonic-gate  * add the given driver/unit reference to the `rawdev' structure identified
2590Sstevel@tonic-gate  * by `cookie'
2600Sstevel@tonic-gate  * If a new `driver' structure needs to be created, associate the given
2610Sstevel@tonic-gate  * choosing function and driver private data with it.
2620Sstevel@tonic-gate  */
2630Sstevel@tonic-gate void
preen_addunit(void * cookie,char * dname,int (* cf)(),void * datap,uint_t unit)2640Sstevel@tonic-gate preen_addunit(
2650Sstevel@tonic-gate 	void    *cookie,
2660Sstevel@tonic-gate 	char	*dname,		/* driver name */
2670Sstevel@tonic-gate 	int	(*cf)(),	/* candidate choosing function */
2680Sstevel@tonic-gate 	void	*datap,		/* driver private data */
2690Sstevel@tonic-gate 	uint_t	unit)		/* unit number */
2700Sstevel@tonic-gate {
271*821Sdh145677 	int drvid;
272*821Sdh145677 	struct driver *dp;
273*821Sdh145677 	struct onedev *devp;
2740Sstevel@tonic-gate 	struct rawdev *rdp = (struct rawdev *)cookie;
2750Sstevel@tonic-gate 
2760Sstevel@tonic-gate 	/*
2770Sstevel@tonic-gate 	 * locate the driver struct
2780Sstevel@tonic-gate 	 */
2790Sstevel@tonic-gate 	dp = NULL;
2800Sstevel@tonic-gate 	for (drvid = 0; drvid < ndrivers; drvid++) {
2810Sstevel@tonic-gate 		if (strcmp(dlist[drvid].name, dname) == 0) {
2820Sstevel@tonic-gate 			dp = &dlist[drvid];
2830Sstevel@tonic-gate 			break;
2840Sstevel@tonic-gate 		}
2850Sstevel@tonic-gate 	}
2860Sstevel@tonic-gate 
2870Sstevel@tonic-gate 	if (dp == NULL) {
2880Sstevel@tonic-gate 		/*
2890Sstevel@tonic-gate 		 * driver struct doesn't exist yet -- create one
2900Sstevel@tonic-gate 		 */
2910Sstevel@tonic-gate 		if (cf == NULL)
2920Sstevel@tonic-gate 			cf = chooseone;
2930Sstevel@tonic-gate 		drvid = alloc_driver(dname, cf, datap);
2940Sstevel@tonic-gate 		dp = &dlist[drvid];
2950Sstevel@tonic-gate 	}
2960Sstevel@tonic-gate 
2970Sstevel@tonic-gate 	for (devp = rdp->alldevs; devp != NULL; devp = devp->nxtdev) {
2980Sstevel@tonic-gate 		/*
2990Sstevel@tonic-gate 		 * see if this device already references the given driver
3000Sstevel@tonic-gate 		 */
3010Sstevel@tonic-gate 		if (devp->drvid == drvid)
3020Sstevel@tonic-gate 			break;
3030Sstevel@tonic-gate 	}
3040Sstevel@tonic-gate 
3050Sstevel@tonic-gate 	if (devp == NULL) {
3060Sstevel@tonic-gate 		/*
3070Sstevel@tonic-gate 		 * allocate a new `struct onedev' and chain it in
3080Sstevel@tonic-gate 		 * rdp->alldevs...
3090Sstevel@tonic-gate 		 */
3100Sstevel@tonic-gate 		devp = alloc_dev(drvid);
3110Sstevel@tonic-gate 		devp->nxtdev = rdp->alldevs;
3120Sstevel@tonic-gate 		rdp->alldevs = devp;
3130Sstevel@tonic-gate 	}
3140Sstevel@tonic-gate 
3150Sstevel@tonic-gate 	/*
3160Sstevel@tonic-gate 	 * add `unit' to the unitmap in devp
3170Sstevel@tonic-gate 	 */
3180Sstevel@tonic-gate 	addunit(devp, unit);
3190Sstevel@tonic-gate }
3200Sstevel@tonic-gate 
3210Sstevel@tonic-gate static
3220Sstevel@tonic-gate int
alloc_driver(char * name,int (* cf)(),void * datap)3230Sstevel@tonic-gate alloc_driver(char *name, int (*cf)(), void *datap)
3240Sstevel@tonic-gate {
325*821Sdh145677 	struct driver *dp;
3260Sstevel@tonic-gate 	extern char *strdup();
3270Sstevel@tonic-gate 
3280Sstevel@tonic-gate 	if (ndrivers == ndalloc) {
3290Sstevel@tonic-gate 		dlist = ndalloc ?
3300Sstevel@tonic-gate 		    (struct driver *)
3310Sstevel@tonic-gate 		    realloc(dlist, sizeof (struct driver) * DRIVER_ALLOC) :
3320Sstevel@tonic-gate 		    (struct driver *)
3330Sstevel@tonic-gate 		    malloc(sizeof (struct driver) * DRIVER_ALLOC);
3340Sstevel@tonic-gate 		if (dlist == NULL) {
3350Sstevel@tonic-gate 			(void) fprintf(stderr, "out of memory in preenlib\n");
3360Sstevel@tonic-gate 			exit(1);
3370Sstevel@tonic-gate 		}
3380Sstevel@tonic-gate 		ndalloc += DRIVER_ALLOC;
3390Sstevel@tonic-gate 	}
3400Sstevel@tonic-gate 
3410Sstevel@tonic-gate 	dp = &dlist[ndrivers];
3420Sstevel@tonic-gate 	dp->name = strdup(name);
3430Sstevel@tonic-gate 	if (dp->name == NULL) {
3440Sstevel@tonic-gate 		(void) fprintf(stderr, "out of memory in preenlib\n");
3450Sstevel@tonic-gate 		exit(1);
3460Sstevel@tonic-gate 	}
3470Sstevel@tonic-gate 	dp->choosefunc = cf;
3480Sstevel@tonic-gate 	dp->data = datap;
3490Sstevel@tonic-gate 	dp->mapsize = 0;
3500Sstevel@tonic-gate 	dp->busymap = NULL;
3510Sstevel@tonic-gate 	return (ndrivers++);
3520Sstevel@tonic-gate }
3530Sstevel@tonic-gate 
3540Sstevel@tonic-gate static
3550Sstevel@tonic-gate struct onedev *
alloc_dev(int did)3560Sstevel@tonic-gate alloc_dev(int did)
3570Sstevel@tonic-gate {
358*821Sdh145677 	struct onedev *devp;
3590Sstevel@tonic-gate 
3600Sstevel@tonic-gate 	devp = (struct onedev *)malloc(sizeof (struct onedev));
3610Sstevel@tonic-gate 	if (devp == NULL) {
3620Sstevel@tonic-gate 		(void) fprintf(stderr, "out of memory in preenlib\n");
3630Sstevel@tonic-gate 		exit(1);
3640Sstevel@tonic-gate 	}
3650Sstevel@tonic-gate 	devp->drvid = did;
3660Sstevel@tonic-gate 	devp->mapsize = 0;
3670Sstevel@tonic-gate 	devp->unitmap = NULL;
3680Sstevel@tonic-gate 	devp->nxtdev = NULL;
3690Sstevel@tonic-gate 	return (devp);
3700Sstevel@tonic-gate }
3710Sstevel@tonic-gate 
3720Sstevel@tonic-gate static
3730Sstevel@tonic-gate void
addunit(struct onedev * devp,uint_t unit)3740Sstevel@tonic-gate addunit(struct onedev *devp, uint_t unit)
3750Sstevel@tonic-gate {
3760Sstevel@tonic-gate 	uint_t newsize;
3770Sstevel@tonic-gate 
3780Sstevel@tonic-gate 	newsize = howmany(unit+1, WORDSIZE);
3790Sstevel@tonic-gate 	if (devp->mapsize < newsize) {
3800Sstevel@tonic-gate 		devp->unitmap = devp->mapsize ?
3810Sstevel@tonic-gate 		    (uint_t *)realloc(devp->unitmap,
3820Sstevel@tonic-gate 		    newsize * sizeof (uint_t)) :
3830Sstevel@tonic-gate 		    (uint_t *)malloc(newsize * sizeof (uint_t));
3840Sstevel@tonic-gate 		if (devp->unitmap == NULL) {
3850Sstevel@tonic-gate 			(void) fprintf(stderr, "out of memory in preenlib\n");
3860Sstevel@tonic-gate 			exit(1);
3870Sstevel@tonic-gate 		}
3880Sstevel@tonic-gate 		(void) memset((char *)&devp->unitmap[devp->mapsize], 0,
3890Sstevel@tonic-gate 		    (uint_t)((newsize - devp->mapsize) * sizeof (uint_t)));
3900Sstevel@tonic-gate 		devp->mapsize = newsize;
3910Sstevel@tonic-gate 	}
3920Sstevel@tonic-gate 	devp->unitmap[unit / WORDSIZE] |= (1 << (unit % WORDSIZE));
3930Sstevel@tonic-gate }
3940Sstevel@tonic-gate 
395*821Sdh145677 static int
chooseone(int devmapsize,ulong_t * devmap,int drvmapsize,ulong_t * drvmap)3960Sstevel@tonic-gate chooseone(int devmapsize, ulong_t *devmap, int drvmapsize, ulong_t *drvmap)
3970Sstevel@tonic-gate {
398*821Sdh145677 	int i;
3990Sstevel@tonic-gate 
4000Sstevel@tonic-gate 	for (i = 0; i < min(devmapsize, drvmapsize); i++) {
4010Sstevel@tonic-gate 		if (devmap[i] & drvmap[i])
4020Sstevel@tonic-gate 			return (1);
4030Sstevel@tonic-gate 	}
4040Sstevel@tonic-gate 	return (0);
4050Sstevel@tonic-gate }
4060Sstevel@tonic-gate 
4070Sstevel@tonic-gate /*
4080Sstevel@tonic-gate  * mark the given driver/unit pair as busy.  This is called from
4090Sstevel@tonic-gate  * preen_getdev.
4100Sstevel@tonic-gate  */
4110Sstevel@tonic-gate static
4120Sstevel@tonic-gate void
makebusy(struct onedev * dev)4130Sstevel@tonic-gate makebusy(struct onedev *dev)
4140Sstevel@tonic-gate {
4150Sstevel@tonic-gate 	struct driver *drvp = &dlist[dev->drvid];
4160Sstevel@tonic-gate 	int newsize = dev->mapsize;
417*821Sdh145677 	int i;
4180Sstevel@tonic-gate 
4190Sstevel@tonic-gate 	if (drvp->mapsize < newsize) {
4200Sstevel@tonic-gate 		drvp->busymap = drvp->mapsize ?
4210Sstevel@tonic-gate 		    (uint_t *)realloc(drvp->busymap,
4220Sstevel@tonic-gate 		    newsize * sizeof (uint_t)) :
4230Sstevel@tonic-gate 		    (uint_t *)malloc(newsize * sizeof (uint_t));
4240Sstevel@tonic-gate 		if (drvp->busymap == NULL) {
4250Sstevel@tonic-gate 			(void) fprintf(stderr, "out of memory in preenlib\n");
4260Sstevel@tonic-gate 			exit(1);
4270Sstevel@tonic-gate 		}
4280Sstevel@tonic-gate 		(void) memset((char *)&drvp->busymap[drvp->mapsize], 0,
4290Sstevel@tonic-gate 		    (uint_t)((newsize - drvp->mapsize) * sizeof (uint_t)));
4300Sstevel@tonic-gate 		drvp->mapsize = newsize;
4310Sstevel@tonic-gate 	}
4320Sstevel@tonic-gate 
4330Sstevel@tonic-gate 	for (i = 0; i < newsize; i++)
4340Sstevel@tonic-gate 		drvp->busymap[i] |= dev->unitmap[i];
4350Sstevel@tonic-gate }
4360Sstevel@tonic-gate 
4370Sstevel@tonic-gate /*
4380Sstevel@tonic-gate  * make each device in the given `rawdev' un-busy.
4390Sstevel@tonic-gate  * Called from preen_releasedev
4400Sstevel@tonic-gate  */
4410Sstevel@tonic-gate static
4420Sstevel@tonic-gate void
notbusy(struct rawdev * rd)4430Sstevel@tonic-gate notbusy(struct rawdev *rd)
4440Sstevel@tonic-gate {
4450Sstevel@tonic-gate 	struct onedev *devp;
4460Sstevel@tonic-gate 	struct driver *drvp;
447*821Sdh145677 	int i;
4480Sstevel@tonic-gate 
4490Sstevel@tonic-gate 	for (devp = rd->alldevs; devp; devp = devp->nxtdev) {
4500Sstevel@tonic-gate 		drvp = &dlist[devp->drvid];
4510Sstevel@tonic-gate 		for (i = 0; i < devp->mapsize; i++)
4520Sstevel@tonic-gate 			drvp->busymap[i] &= ~(devp->unitmap[i]);
4530Sstevel@tonic-gate 	}
4540Sstevel@tonic-gate }
455