Home | History | Annotate | Line # | Download | only in kern
subr_bufq.c revision 1.15.8.1
      1  1.15.8.1    skrll /*	$NetBSD: subr_bufq.c,v 1.15.8.1 2009/01/19 13:19:39 skrll Exp $	*/
      2       1.3     yamt /*	NetBSD: subr_disk.c,v 1.70 2005/08/20 12:00:01 yamt Exp $	*/
      3       1.1     yamt 
      4       1.1     yamt /*-
      5       1.1     yamt  * Copyright (c) 1996, 1997, 1999, 2000 The NetBSD Foundation, Inc.
      6       1.1     yamt  * All rights reserved.
      7       1.1     yamt  *
      8       1.1     yamt  * This code is derived from software contributed to The NetBSD Foundation
      9       1.1     yamt  * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
     10       1.1     yamt  * NASA Ames Research Center.
     11       1.1     yamt  *
     12       1.1     yamt  * Redistribution and use in source and binary forms, with or without
     13       1.1     yamt  * modification, are permitted provided that the following conditions
     14       1.1     yamt  * are met:
     15       1.1     yamt  * 1. Redistributions of source code must retain the above copyright
     16       1.1     yamt  *    notice, this list of conditions and the following disclaimer.
     17       1.1     yamt  * 2. Redistributions in binary form must reproduce the above copyright
     18       1.1     yamt  *    notice, this list of conditions and the following disclaimer in the
     19       1.1     yamt  *    documentation and/or other materials provided with the distribution.
     20       1.1     yamt  *
     21       1.1     yamt  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     22       1.1     yamt  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     23       1.1     yamt  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     24       1.1     yamt  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     25       1.1     yamt  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     26       1.1     yamt  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     27       1.1     yamt  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     28       1.1     yamt  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     29       1.1     yamt  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     30       1.1     yamt  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     31       1.1     yamt  * POSSIBILITY OF SUCH DAMAGE.
     32       1.1     yamt  */
     33       1.1     yamt 
     34       1.1     yamt /*
     35       1.1     yamt  * Copyright (c) 1982, 1986, 1988, 1993
     36       1.1     yamt  *	The Regents of the University of California.  All rights reserved.
     37       1.1     yamt  * (c) UNIX System Laboratories, Inc.
     38       1.1     yamt  * All or some portions of this file are derived from material licensed
     39       1.1     yamt  * to the University of California by American Telephone and Telegraph
     40       1.1     yamt  * Co. or Unix System Laboratories, Inc. and are reproduced herein with
     41       1.1     yamt  * the permission of UNIX System Laboratories, Inc.
     42       1.1     yamt  *
     43       1.1     yamt  * Redistribution and use in source and binary forms, with or without
     44       1.1     yamt  * modification, are permitted provided that the following conditions
     45       1.1     yamt  * are met:
     46       1.1     yamt  * 1. Redistributions of source code must retain the above copyright
     47       1.1     yamt  *    notice, this list of conditions and the following disclaimer.
     48       1.1     yamt  * 2. Redistributions in binary form must reproduce the above copyright
     49       1.1     yamt  *    notice, this list of conditions and the following disclaimer in the
     50       1.1     yamt  *    documentation and/or other materials provided with the distribution.
     51       1.1     yamt  * 3. Neither the name of the University nor the names of its contributors
     52       1.1     yamt  *    may be used to endorse or promote products derived from this software
     53       1.1     yamt  *    without specific prior written permission.
     54       1.1     yamt  *
     55       1.1     yamt  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     56       1.1     yamt  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     57       1.1     yamt  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     58       1.1     yamt  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     59       1.1     yamt  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     60       1.1     yamt  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     61       1.1     yamt  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     62       1.1     yamt  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     63       1.1     yamt  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     64       1.1     yamt  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     65       1.1     yamt  * SUCH DAMAGE.
     66       1.1     yamt  *
     67       1.1     yamt  *	@(#)ufs_disksubr.c	8.5 (Berkeley) 1/21/94
     68       1.1     yamt  */
     69       1.1     yamt 
     70       1.1     yamt #include <sys/cdefs.h>
     71  1.15.8.1    skrll __KERNEL_RCSID(0, "$NetBSD: subr_bufq.c,v 1.15.8.1 2009/01/19 13:19:39 skrll Exp $");
     72       1.1     yamt 
     73       1.1     yamt #include <sys/param.h>
     74       1.1     yamt #include <sys/systm.h>
     75       1.1     yamt #include <sys/buf.h>
     76       1.1     yamt #include <sys/bufq.h>
     77       1.1     yamt #include <sys/bufq_impl.h>
     78       1.1     yamt #include <sys/malloc.h>
     79       1.2  xtraeme #include <sys/sysctl.h>
     80       1.1     yamt 
     81       1.1     yamt BUFQ_DEFINE(dummy, 0, NULL); /* so that bufq_strats won't be empty */
     82       1.1     yamt 
     83       1.9     yamt #define	STRAT_MATCH(id, bs)	(strcmp((id), (bs)->bs_name) == 0)
     84       1.1     yamt 
     85       1.1     yamt /*
     86       1.1     yamt  * Create a device buffer queue.
     87       1.1     yamt  */
     88       1.1     yamt int
     89       1.1     yamt bufq_alloc(struct bufq_state **bufqp, const char *strategy, int flags)
     90       1.1     yamt {
     91       1.1     yamt 	__link_set_decl(bufq_strats, const struct bufq_strat);
     92       1.1     yamt 	const struct bufq_strat *bsp;
     93       1.1     yamt 	const struct bufq_strat * const *it;
     94       1.1     yamt 	struct bufq_state *bufq;
     95       1.1     yamt 	int error = 0;
     96       1.1     yamt 
     97       1.1     yamt 	KASSERT((flags & BUFQ_EXACT) == 0 || strategy != BUFQ_STRAT_ANY);
     98       1.1     yamt 
     99       1.1     yamt 	switch (flags & BUFQ_SORT_MASK) {
    100       1.1     yamt 	case BUFQ_SORT_RAWBLOCK:
    101       1.1     yamt 	case BUFQ_SORT_CYLINDER:
    102       1.1     yamt 		break;
    103       1.1     yamt 	case 0:
    104       1.1     yamt 		/*
    105       1.1     yamt 		 * for strategies which don't care about block numbers.
    106       1.1     yamt 		 * eg. fcfs
    107       1.1     yamt 		 */
    108       1.1     yamt 		flags |= BUFQ_SORT_RAWBLOCK;
    109       1.1     yamt 		break;
    110       1.1     yamt 	default:
    111       1.1     yamt 		panic("bufq_alloc: sort out of range");
    112       1.1     yamt 	}
    113       1.1     yamt 
    114       1.1     yamt 	/*
    115       1.1     yamt 	 * select strategy.
    116       1.1     yamt 	 * if a strategy specified by flags is found, use it.
    117       1.1     yamt 	 * otherwise, select one with the largest bs_prio.
    118       1.1     yamt 	 */
    119       1.1     yamt 	bsp = NULL;
    120       1.1     yamt 	__link_set_foreach(it, bufq_strats) {
    121       1.1     yamt 		if ((*it) == &bufq_strat_dummy)
    122       1.1     yamt 			continue;
    123       1.9     yamt 		if (strategy != BUFQ_STRAT_ANY &&
    124       1.9     yamt 		    STRAT_MATCH(strategy, (*it))) {
    125       1.1     yamt 			bsp = *it;
    126       1.1     yamt 			break;
    127       1.1     yamt 		}
    128       1.1     yamt 		if (bsp == NULL || (*it)->bs_prio > bsp->bs_prio)
    129       1.1     yamt 			bsp = *it;
    130       1.1     yamt 	}
    131       1.1     yamt 
    132       1.1     yamt 	if (bsp == NULL) {
    133       1.1     yamt 		panic("bufq_alloc: no strategy");
    134       1.1     yamt 	}
    135       1.9     yamt 	if (strategy != BUFQ_STRAT_ANY && !STRAT_MATCH(strategy, bsp)) {
    136       1.1     yamt 		if ((flags & BUFQ_EXACT)) {
    137       1.1     yamt 			error = ENOENT;
    138       1.1     yamt 			goto out;
    139       1.1     yamt 		}
    140       1.1     yamt #if defined(DEBUG)
    141       1.1     yamt 		printf("bufq_alloc: '%s' is not available. using '%s'.\n",
    142       1.1     yamt 		    strategy, bsp->bs_name);
    143       1.1     yamt #endif
    144       1.1     yamt 	}
    145       1.1     yamt #if defined(BUFQ_DEBUG)
    146       1.1     yamt 	/* XXX aprint? */
    147       1.1     yamt 	printf("bufq_alloc: using '%s'\n", bsp->bs_name);
    148       1.1     yamt #endif
    149       1.1     yamt 
    150       1.1     yamt 	*bufqp = bufq = malloc(sizeof(*bufq), M_DEVBUF, M_WAITOK | M_ZERO);
    151       1.1     yamt 	bufq->bq_flags = flags;
    152       1.5     yamt 	bufq->bq_strat = bsp;
    153       1.1     yamt 	(*bsp->bs_initfn)(bufq);
    154       1.1     yamt 
    155       1.1     yamt out:
    156      1.11     yamt 	return error;
    157       1.1     yamt }
    158       1.1     yamt 
    159       1.1     yamt void
    160       1.1     yamt bufq_put(struct bufq_state *bufq, struct buf *bp)
    161       1.1     yamt {
    162       1.1     yamt 
    163       1.1     yamt 	(*bufq->bq_put)(bufq, bp);
    164       1.1     yamt }
    165       1.1     yamt 
    166       1.1     yamt struct buf *
    167       1.1     yamt bufq_get(struct bufq_state *bufq)
    168       1.1     yamt {
    169       1.1     yamt 
    170       1.1     yamt 	return (*bufq->bq_get)(bufq, 1);
    171       1.1     yamt }
    172       1.1     yamt 
    173       1.1     yamt struct buf *
    174       1.1     yamt bufq_peek(struct bufq_state *bufq)
    175       1.1     yamt {
    176       1.1     yamt 
    177       1.1     yamt 	return (*bufq->bq_get)(bufq, 0);
    178       1.1     yamt }
    179       1.1     yamt 
    180      1.15  reinoud struct buf *
    181      1.15  reinoud bufq_cancel(struct bufq_state *bufq, struct buf *bp)
    182      1.15  reinoud {
    183  1.15.8.1    skrll 
    184      1.15  reinoud 	return (*bufq->bq_cancel)(bufq, bp);
    185      1.15  reinoud }
    186      1.15  reinoud 
    187       1.1     yamt /*
    188       1.1     yamt  * Drain a device buffer queue.
    189       1.1     yamt  */
    190       1.1     yamt void
    191       1.1     yamt bufq_drain(struct bufq_state *bufq)
    192       1.1     yamt {
    193       1.1     yamt 	struct buf *bp;
    194       1.1     yamt 
    195  1.15.8.1    skrll 	while ((bp = bufq_get(bufq)) != NULL) {
    196       1.1     yamt 		bp->b_error = EIO;
    197       1.1     yamt 		bp->b_resid = bp->b_bcount;
    198       1.1     yamt 		biodone(bp);
    199       1.1     yamt 	}
    200       1.1     yamt }
    201       1.1     yamt 
    202       1.1     yamt /*
    203       1.1     yamt  * Destroy a device buffer queue.
    204       1.1     yamt  */
    205       1.1     yamt void
    206       1.1     yamt bufq_free(struct bufq_state *bufq)
    207       1.1     yamt {
    208       1.1     yamt 
    209       1.1     yamt 	KASSERT(bufq->bq_private != NULL);
    210  1.15.8.1    skrll 	KASSERT(bufq_peek(bufq) == NULL);
    211       1.1     yamt 
    212       1.1     yamt 	free(bufq->bq_private, M_DEVBUF);
    213       1.1     yamt 	free(bufq, M_DEVBUF);
    214       1.1     yamt }
    215       1.2  xtraeme 
    216       1.5     yamt /*
    217       1.5     yamt  * get a strategy identifier of a buffer queue.
    218       1.5     yamt  */
    219       1.5     yamt const char *
    220       1.5     yamt bufq_getstrategyname(struct bufq_state *bufq)
    221       1.5     yamt {
    222       1.5     yamt 
    223       1.5     yamt 	return bufq->bq_strat->bs_name;
    224       1.5     yamt }
    225       1.5     yamt 
    226       1.5     yamt /*
    227       1.5     yamt  * move all requests on a buffer queue to another.
    228       1.5     yamt  */
    229       1.5     yamt void
    230       1.5     yamt bufq_move(struct bufq_state *dst, struct bufq_state *src)
    231       1.5     yamt {
    232       1.5     yamt 	struct buf *bp;
    233       1.5     yamt 
    234  1.15.8.1    skrll 	while ((bp = bufq_get(src)) != NULL) {
    235  1.15.8.1    skrll 		bufq_put(dst, bp);
    236       1.5     yamt 	}
    237       1.5     yamt }
    238       1.5     yamt 
    239       1.8     yamt static int
    240       1.8     yamt docopy(char *buf, size_t *bufoffp, size_t buflen,
    241       1.8     yamt     const char *datap, size_t datalen)
    242       1.8     yamt {
    243       1.8     yamt 	int error = 0;
    244       1.8     yamt 
    245       1.8     yamt 	if (buf != NULL && datalen > 0) {
    246       1.8     yamt 
    247       1.8     yamt 		if (*bufoffp + datalen > buflen) {
    248       1.8     yamt 			goto out;
    249       1.8     yamt 		}
    250       1.8     yamt 		error = copyout(datap, buf + *bufoffp, datalen);
    251       1.8     yamt 		if (error) {
    252       1.8     yamt 			goto out;
    253       1.8     yamt 		}
    254       1.8     yamt 	}
    255       1.8     yamt out:
    256       1.8     yamt 	if (error == 0) {
    257       1.8     yamt 		*bufoffp += datalen;
    258       1.8     yamt 	}
    259       1.8     yamt 
    260       1.8     yamt 	return error;
    261       1.8     yamt }
    262       1.8     yamt 
    263       1.8     yamt static int
    264       1.8     yamt docopystr(char *buf, size_t *bufoffp, size_t buflen, const char *datap)
    265       1.8     yamt {
    266       1.8     yamt 
    267       1.8     yamt 	return docopy(buf, bufoffp, buflen, datap, strlen(datap));
    268       1.8     yamt }
    269       1.8     yamt 
    270       1.8     yamt static int
    271       1.8     yamt docopynul(char *buf, size_t *bufoffp, size_t buflen)
    272       1.8     yamt {
    273       1.8     yamt 
    274       1.8     yamt 	return docopy(buf, bufoffp, buflen, "", 1);
    275       1.8     yamt }
    276       1.8     yamt 
    277       1.2  xtraeme /*
    278       1.2  xtraeme  * sysctl function that will print all bufq strategies
    279       1.2  xtraeme  * built in the kernel.
    280       1.2  xtraeme  */
    281       1.2  xtraeme static int
    282       1.2  xtraeme sysctl_kern_bufq_strategies(SYSCTLFN_ARGS)
    283       1.2  xtraeme {
    284       1.4     yamt 	__link_set_decl(bufq_strats, const struct bufq_strat);
    285       1.2  xtraeme 	const struct bufq_strat * const *bq_strat;
    286       1.8     yamt 	const char *delim = "";
    287       1.8     yamt 	size_t off = 0;
    288       1.8     yamt 	size_t buflen = *oldlenp;
    289       1.8     yamt 	int error;
    290       1.2  xtraeme 
    291       1.2  xtraeme 	__link_set_foreach(bq_strat, bufq_strats) {
    292       1.8     yamt 		if ((*bq_strat) == &bufq_strat_dummy) {
    293       1.6     yamt 			continue;
    294       1.2  xtraeme 		}
    295       1.8     yamt 		error = docopystr(oldp, &off, buflen, delim);
    296       1.8     yamt 		if (error) {
    297       1.8     yamt 			goto out;
    298       1.8     yamt 		}
    299       1.8     yamt 		error = docopystr(oldp, &off, buflen, (*bq_strat)->bs_name);
    300       1.8     yamt 		if (error) {
    301       1.8     yamt 			goto out;
    302       1.8     yamt 		}
    303       1.8     yamt 		delim = " ";
    304       1.2  xtraeme 	}
    305       1.8     yamt 
    306       1.8     yamt 	/* NUL terminate */
    307       1.8     yamt 	error = docopynul(oldp, &off, buflen);
    308       1.8     yamt out:
    309       1.8     yamt 	*oldlenp = off;
    310       1.2  xtraeme 	return error;
    311       1.2  xtraeme }
    312       1.2  xtraeme 
    313       1.2  xtraeme SYSCTL_SETUP(sysctl_kern_bufq_strategies_setup, "sysctl kern.bufq tree setup")
    314       1.2  xtraeme {
    315       1.2  xtraeme 	const struct sysctlnode *node;
    316       1.2  xtraeme 
    317       1.2  xtraeme 	sysctl_createv(clog, 0, NULL, NULL,
    318       1.2  xtraeme 			CTLFLAG_PERMANENT,
    319       1.2  xtraeme 			CTLTYPE_NODE, "kern", NULL,
    320       1.2  xtraeme 			NULL, 0, NULL, 0,
    321       1.2  xtraeme 			CTL_KERN, CTL_EOL);
    322       1.2  xtraeme 	node = NULL;
    323       1.2  xtraeme 	sysctl_createv(clog, 0, NULL, &node,
    324       1.2  xtraeme 			CTLFLAG_PERMANENT,
    325       1.2  xtraeme 			CTLTYPE_NODE, "bufq",
    326       1.2  xtraeme 			SYSCTL_DESCR("buffer queue subtree"),
    327       1.2  xtraeme 			NULL, 0, NULL, 0,
    328       1.2  xtraeme 			CTL_KERN, CTL_CREATE, CTL_EOL);
    329       1.2  xtraeme 	if (node != NULL) {
    330       1.2  xtraeme 		sysctl_createv(clog, 0, NULL, NULL,
    331       1.2  xtraeme 			CTLFLAG_PERMANENT,
    332       1.2  xtraeme 			CTLTYPE_STRING, "strategies",
    333       1.2  xtraeme 			SYSCTL_DESCR("List of bufq strategies present"),
    334       1.2  xtraeme 			sysctl_kern_bufq_strategies, 0, NULL, 0,
    335       1.2  xtraeme 			CTL_KERN, node->sysctl_num, CTL_CREATE, CTL_EOL);
    336       1.2  xtraeme 	}
    337       1.2  xtraeme }
    338