4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
22 #pragma ident "%Z%%M% %I% %E% SMI"
24 * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
25 * Use is subject to license terms.
29 * common routines for parallelization (used by both fsck and quotacheck)
35 #include <sys/types.h>
37 #include <sys/mntent.h>
41 * data structures for parallelization
44 char *name
; /* driver name (from DKIOCINFO) */
45 uint_t mapsize
; /* size of `busymap' */
46 uint_t
*busymap
; /* bitmask of active units */
47 int (*choosefunc
)(); /* driver specific chooser */
48 void *data
; /* driver private data */
52 int drvid
; /* index in driver array */
53 uint_t mapsize
; /* size of `unitmap' */
54 uint_t
*unitmap
; /* unit #'s (from DKIOCINFO) */
55 struct onedev
*nxtdev
;
59 char *devname
; /* name passed to preen_addev */
60 struct onedev
*alldevs
; /* info about each component device */
61 struct rawdev
*nxtrd
; /* next entry in list */
67 * defines used in building shared object names
70 /* the directory where we find shared objects */
71 #define OBJECT_DIRECTORY "/usr/lib/drv"
73 /* a shared object name is OBJECT_PREFIX || driver_name */
74 #define OBJECT_PREFIX "preen_"
76 /* the version of the driver interface we support */
77 #define OBJECT_VERSION 1
79 /* the "build" entry point for a driver specific object is named this */
80 #define BUILD_ENTRY preen_build_devs
81 #define BUILD_NAME "preen_build_devs"
83 #define DRIVER_ALLOC 10
84 static int ndrivers
, ndalloc
;
85 static struct driver
*dlist
;
87 static struct rawdev
*unchecked
, *active
, *get_runnable();
88 static struct onedev
*alloc_dev();
89 static int chooseone();
91 #define WORDSIZE (NBBY * sizeof (uint_t))
93 void preen_addunit(void *, char *, int (*)(), void *, uint_t
);
94 int preen_subdev(char *, struct dk_cinfo
*, void *);
96 static int alloc_driver(char *, int (*)(), void *);
97 static void addunit(struct onedev
*, uint_t
);
98 static void makebusy(struct onedev
*);
99 static void notbusy(struct rawdev
*);
102 * add the given device to the list of devices to be checked
105 preen_addev(char *devnm
)
110 extern char *strdup();
112 if ((fd
= open64(devnm
, O_RDONLY
)) == -1) {
116 if (ioctl(fd
, DKIOCINFO
, &dki
) == -1) {
118 fprintf(stderr
, "device: `%s'\n", devnm
);
123 if ((rdp
= (struct rawdev
*)malloc(sizeof (struct rawdev
))) == NULL
) {
124 (void) fprintf(stderr
, "out of memory in preenlib\n");
127 if ((rdp
->devname
= strdup(devnm
)) == NULL
) {
128 (void) fprintf(stderr
, "out of memory in preenlib\n");
134 if (preen_subdev(devnm
, &dki
, (void *)rdp
)) {
135 preen_addunit(rdp
, dki
.dki_dname
, NULL
, NULL
, dki
.dki_unit
);
138 rdp
->nxtrd
= unchecked
;
144 preen_subdev(char *name
, struct dk_cinfo
*dkiop
, void *dp
)
150 (void) sprintf(modname
, "%s/%s%s.so.%d",
151 OBJECT_DIRECTORY
, OBJECT_PREFIX
, dkiop
->dki_dname
, OBJECT_VERSION
);
152 dlhandle
= dlopen(modname
, RTLD_LAZY
);
153 if (dlhandle
== NULL
) {
155 (void) fprintf(stderr
, "preen_subdev: %s\n", dlerror());
158 fptr
= (int (*)())dlsym(dlhandle
, BUILD_NAME
);
161 (void) fprintf(stderr
, "preen_subdev: %s\n", dlerror());
164 (*fptr
)(name
, dkiop
, dp
);
169 * select a device from the "unchecked" list, and add it to the
173 preen_getdev(char *devnm
)
178 if (unchecked
== NULL
)
181 rdp
= get_runnable(&unchecked
);
184 for (dp
= rdp
->alldevs
; dp
; dp
= dp
->nxtdev
) {
189 (void) strcpy(devnm
, rdp
->devname
);
197 preen_releasedev(char *name
)
199 struct rawdev
*dp
, *ldp
;
201 for (ldp
= NULL
, dp
= active
; dp
!= NULL
; ldp
= dp
, dp
= dp
->nxtrd
) {
202 if (strcmp(dp
->devname
, name
) == 0)
209 ldp
->nxtrd
= dp
->nxtrd
;
224 get_runnable(struct rawdev
**devlist
)
226 struct rawdev
*last
, *rdp
;
231 for (last
= NULL
, rdp
= *devlist
; rdp
; last
= rdp
, rdp
= rdp
->nxtrd
) {
232 for (devp
= rdp
->alldevs
; devp
!= NULL
; devp
= devp
->nxtdev
) {
233 drvp
= &dlist
[devp
->drvid
];
234 rc
= (*drvp
->choosefunc
)(devp
->mapsize
, devp
->unitmap
,
235 drvp
->mapsize
, drvp
->busymap
);
244 * remove from list...
248 last
->nxtrd
= rdp
->nxtrd
;
250 *devlist
= rdp
->nxtrd
;
258 * add the given driver/unit reference to the `rawdev' structure identified
260 * If a new `driver' structure needs to be created, associate the given
261 * choosing function and driver private data with it.
266 char *dname
, /* driver name */
267 int (*cf
)(), /* candidate choosing function */
268 void *datap
, /* driver private data */
269 uint_t unit
) /* unit number */
274 struct rawdev
*rdp
= (struct rawdev
*)cookie
;
277 * locate the driver struct
280 for (drvid
= 0; drvid
< ndrivers
; drvid
++) {
281 if (strcmp(dlist
[drvid
].name
, dname
) == 0) {
289 * driver struct doesn't exist yet -- create one
293 drvid
= alloc_driver(dname
, cf
, datap
);
297 for (devp
= rdp
->alldevs
; devp
!= NULL
; devp
= devp
->nxtdev
) {
299 * see if this device already references the given driver
301 if (devp
->drvid
== drvid
)
307 * allocate a new `struct onedev' and chain it in
310 devp
= alloc_dev(drvid
);
311 devp
->nxtdev
= rdp
->alldevs
;
316 * add `unit' to the unitmap in devp
323 alloc_driver(char *name
, int (*cf
)(), void *datap
)
326 extern char *strdup();
328 if (ndrivers
== ndalloc
) {
331 realloc(dlist
, sizeof (struct driver
) * DRIVER_ALLOC
) :
333 malloc(sizeof (struct driver
) * DRIVER_ALLOC
);
335 (void) fprintf(stderr
, "out of memory in preenlib\n");
338 ndalloc
+= DRIVER_ALLOC
;
341 dp
= &dlist
[ndrivers
];
342 dp
->name
= strdup(name
);
343 if (dp
->name
== NULL
) {
344 (void) fprintf(stderr
, "out of memory in preenlib\n");
360 devp
= (struct onedev
*)malloc(sizeof (struct onedev
));
362 (void) fprintf(stderr
, "out of memory in preenlib\n");
367 devp
->unitmap
= NULL
;
374 addunit(struct onedev
*devp
, uint_t unit
)
378 newsize
= howmany(unit
+1, WORDSIZE
);
379 if (devp
->mapsize
< newsize
) {
380 devp
->unitmap
= devp
->mapsize
?
381 (uint_t
*)realloc(devp
->unitmap
,
382 newsize
* sizeof (uint_t
)) :
383 (uint_t
*)malloc(newsize
* sizeof (uint_t
));
384 if (devp
->unitmap
== NULL
) {
385 (void) fprintf(stderr
, "out of memory in preenlib\n");
388 (void) memset((char *)&devp
->unitmap
[devp
->mapsize
], 0,
389 (uint_t
)((newsize
- devp
->mapsize
) * sizeof (uint_t
)));
390 devp
->mapsize
= newsize
;
392 devp
->unitmap
[unit
/ WORDSIZE
] |= (1 << (unit
% WORDSIZE
));
396 chooseone(int devmapsize
, ulong_t
*devmap
, int drvmapsize
, ulong_t
*drvmap
)
400 for (i
= 0; i
< min(devmapsize
, drvmapsize
); i
++) {
401 if (devmap
[i
] & drvmap
[i
])
408 * mark the given driver/unit pair as busy. This is called from
413 makebusy(struct onedev
*dev
)
415 struct driver
*drvp
= &dlist
[dev
->drvid
];
416 int newsize
= dev
->mapsize
;
419 if (drvp
->mapsize
< newsize
) {
420 drvp
->busymap
= drvp
->mapsize
?
421 (uint_t
*)realloc(drvp
->busymap
,
422 newsize
* sizeof (uint_t
)) :
423 (uint_t
*)malloc(newsize
* sizeof (uint_t
));
424 if (drvp
->busymap
== NULL
) {
425 (void) fprintf(stderr
, "out of memory in preenlib\n");
428 (void) memset((char *)&drvp
->busymap
[drvp
->mapsize
], 0,
429 (uint_t
)((newsize
- drvp
->mapsize
) * sizeof (uint_t
)));
430 drvp
->mapsize
= newsize
;
433 for (i
= 0; i
< newsize
; i
++)
434 drvp
->busymap
[i
] |= dev
->unitmap
[i
];
438 * make each device in the given `rawdev' un-busy.
439 * Called from preen_releasedev
443 notbusy(struct rawdev
*rd
)
449 for (devp
= rd
->alldevs
; devp
; devp
= devp
->nxtdev
) {
450 drvp
= &dlist
[devp
->drvid
];
451 for (i
= 0; i
< devp
->mapsize
; i
++)
452 drvp
->busymap
[i
] &= ~(devp
->unitmap
[i
]);