1*0a6a1f1dSLionel Sambuc /* $NetBSD: buf.c,v 1.22 2015/03/29 05:52:59 agc Exp $ */
29f988b79SJean-Baptiste Boric
39f988b79SJean-Baptiste Boric /*
49f988b79SJean-Baptiste Boric * Copyright (c) 2001 Wasabi Systems, Inc.
59f988b79SJean-Baptiste Boric * All rights reserved.
69f988b79SJean-Baptiste Boric *
79f988b79SJean-Baptiste Boric * Written by Luke Mewburn for Wasabi Systems, Inc.
89f988b79SJean-Baptiste Boric *
99f988b79SJean-Baptiste Boric * Redistribution and use in source and binary forms, with or without
109f988b79SJean-Baptiste Boric * modification, are permitted provided that the following conditions
119f988b79SJean-Baptiste Boric * are met:
129f988b79SJean-Baptiste Boric * 1. Redistributions of source code must retain the above copyright
139f988b79SJean-Baptiste Boric * notice, this list of conditions and the following disclaimer.
149f988b79SJean-Baptiste Boric * 2. Redistributions in binary form must reproduce the above copyright
159f988b79SJean-Baptiste Boric * notice, this list of conditions and the following disclaimer in the
169f988b79SJean-Baptiste Boric * documentation and/or other materials provided with the distribution.
179f988b79SJean-Baptiste Boric * 3. All advertising materials mentioning features or use of this software
189f988b79SJean-Baptiste Boric * must display the following acknowledgement:
199f988b79SJean-Baptiste Boric * This product includes software developed for the NetBSD Project by
209f988b79SJean-Baptiste Boric * Wasabi Systems, Inc.
219f988b79SJean-Baptiste Boric * 4. The name of Wasabi Systems, Inc. may not be used to endorse
229f988b79SJean-Baptiste Boric * or promote products derived from this software without specific prior
239f988b79SJean-Baptiste Boric * written permission.
249f988b79SJean-Baptiste Boric *
259f988b79SJean-Baptiste Boric * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
269f988b79SJean-Baptiste Boric * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
279f988b79SJean-Baptiste Boric * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
289f988b79SJean-Baptiste Boric * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC
299f988b79SJean-Baptiste Boric * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
309f988b79SJean-Baptiste Boric * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
319f988b79SJean-Baptiste Boric * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
329f988b79SJean-Baptiste Boric * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
339f988b79SJean-Baptiste Boric * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
349f988b79SJean-Baptiste Boric * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
359f988b79SJean-Baptiste Boric * POSSIBILITY OF SUCH DAMAGE.
369f988b79SJean-Baptiste Boric */
379f988b79SJean-Baptiste Boric
389f988b79SJean-Baptiste Boric #if HAVE_NBTOOL_CONFIG_H
399f988b79SJean-Baptiste Boric #include "nbtool_config.h"
409f988b79SJean-Baptiste Boric #endif
419f988b79SJean-Baptiste Boric
429f988b79SJean-Baptiste Boric #include <sys/cdefs.h>
439f988b79SJean-Baptiste Boric #if defined(__RCSID) && !defined(__lint)
44*0a6a1f1dSLionel Sambuc __RCSID("$NetBSD: buf.c,v 1.22 2015/03/29 05:52:59 agc Exp $");
459f988b79SJean-Baptiste Boric #endif /* !__lint */
469f988b79SJean-Baptiste Boric
479f988b79SJean-Baptiste Boric #include <sys/param.h>
489f988b79SJean-Baptiste Boric #include <sys/time.h>
499f988b79SJean-Baptiste Boric
509f988b79SJean-Baptiste Boric #include <assert.h>
519f988b79SJean-Baptiste Boric #include <errno.h>
529f988b79SJean-Baptiste Boric #include <stdio.h>
539f988b79SJean-Baptiste Boric #include <stdlib.h>
549f988b79SJean-Baptiste Boric #include <unistd.h>
559f988b79SJean-Baptiste Boric #include <util.h>
569f988b79SJean-Baptiste Boric
579f988b79SJean-Baptiste Boric #include "makefs.h"
589f988b79SJean-Baptiste Boric #include "buf.h"
599f988b79SJean-Baptiste Boric
609f988b79SJean-Baptiste Boric TAILQ_HEAD(buftailhead,buf) buftail;
619f988b79SJean-Baptiste Boric
629f988b79SJean-Baptiste Boric int
bread(struct vnode * vp,daddr_t blkno,int size,int u2 __unused,struct buf ** bpp)63*0a6a1f1dSLionel Sambuc bread(struct vnode *vp, daddr_t blkno, int size, int u2 __unused,
64*0a6a1f1dSLionel Sambuc struct buf **bpp)
659f988b79SJean-Baptiste Boric {
669f988b79SJean-Baptiste Boric off_t offset;
679f988b79SJean-Baptiste Boric ssize_t rv;
689f988b79SJean-Baptiste Boric fsinfo_t *fs = vp->fs;
699f988b79SJean-Baptiste Boric
709f988b79SJean-Baptiste Boric assert (bpp != NULL);
719f988b79SJean-Baptiste Boric
729f988b79SJean-Baptiste Boric if (debug & DEBUG_BUF_BREAD)
739f988b79SJean-Baptiste Boric printf("bread: blkno %lld size %d\n", (long long)blkno, size);
749f988b79SJean-Baptiste Boric *bpp = getblk(vp, blkno, size, 0, 0);
759f988b79SJean-Baptiste Boric offset = (*bpp)->b_blkno * fs->sectorsize + fs->offset;
769f988b79SJean-Baptiste Boric if (debug & DEBUG_BUF_BREAD)
779f988b79SJean-Baptiste Boric printf("bread: blkno %lld offset %lld bcount %ld\n",
789f988b79SJean-Baptiste Boric (long long)(*bpp)->b_blkno, (long long) offset,
799f988b79SJean-Baptiste Boric (*bpp)->b_bcount);
809f988b79SJean-Baptiste Boric if (lseek((*bpp)->b_fs->fd, offset, SEEK_SET) == -1)
819f988b79SJean-Baptiste Boric err(1, "%s: lseek %lld (%lld)", __func__,
829f988b79SJean-Baptiste Boric (long long)(*bpp)->b_blkno, (long long)offset);
839f988b79SJean-Baptiste Boric rv = read((*bpp)->b_fs->fd, (*bpp)->b_data, (*bpp)->b_bcount);
849f988b79SJean-Baptiste Boric if (debug & DEBUG_BUF_BREAD)
859f988b79SJean-Baptiste Boric printf("bread: read %ld (%lld) returned %zd\n",
869f988b79SJean-Baptiste Boric (*bpp)->b_bcount, (long long)offset, rv);
879f988b79SJean-Baptiste Boric if (rv == -1) /* read error */
889f988b79SJean-Baptiste Boric err(1, "%s: read %ld (%lld) returned %zd", __func__,
899f988b79SJean-Baptiste Boric (*bpp)->b_bcount, (long long)offset, rv);
909f988b79SJean-Baptiste Boric else if (rv != (*bpp)->b_bcount) /* short read */
919f988b79SJean-Baptiste Boric err(1, "%s: read %ld (%lld) returned %zd", __func__,
929f988b79SJean-Baptiste Boric (*bpp)->b_bcount, (long long)offset, rv);
939f988b79SJean-Baptiste Boric else
949f988b79SJean-Baptiste Boric return (0);
959f988b79SJean-Baptiste Boric }
969f988b79SJean-Baptiste Boric
979f988b79SJean-Baptiste Boric void
brelse(struct buf * bp,int u1 __unused)989f988b79SJean-Baptiste Boric brelse(struct buf *bp, int u1 __unused)
999f988b79SJean-Baptiste Boric {
1009f988b79SJean-Baptiste Boric
1019f988b79SJean-Baptiste Boric assert (bp != NULL);
1029f988b79SJean-Baptiste Boric assert (bp->b_data != NULL);
1039f988b79SJean-Baptiste Boric
1049f988b79SJean-Baptiste Boric if (bp->b_lblkno < 0) {
1059f988b79SJean-Baptiste Boric /*
1069f988b79SJean-Baptiste Boric * XXX don't remove any buffers with negative logical block
1079f988b79SJean-Baptiste Boric * numbers (lblkno), so that we retain the mapping
1089f988b79SJean-Baptiste Boric * of negative lblkno -> real blkno that ffs_balloc()
1099f988b79SJean-Baptiste Boric * sets up.
1109f988b79SJean-Baptiste Boric *
1119f988b79SJean-Baptiste Boric * if we instead released these buffers, and implemented
1129f988b79SJean-Baptiste Boric * ufs_strategy() (and ufs_bmaparray()) and called those
1139f988b79SJean-Baptiste Boric * from bread() and bwrite() to convert the lblkno to
1149f988b79SJean-Baptiste Boric * a real blkno, we'd add a lot more code & complexity
1159f988b79SJean-Baptiste Boric * and reading off disk, for little gain, because this
1169f988b79SJean-Baptiste Boric * simple hack works for our purpose.
1179f988b79SJean-Baptiste Boric */
1189f988b79SJean-Baptiste Boric bp->b_bcount = 0;
1199f988b79SJean-Baptiste Boric return;
1209f988b79SJean-Baptiste Boric }
1219f988b79SJean-Baptiste Boric
1229f988b79SJean-Baptiste Boric TAILQ_REMOVE(&buftail, bp, b_tailq);
1239f988b79SJean-Baptiste Boric free(bp->b_data);
1249f988b79SJean-Baptiste Boric free(bp);
1259f988b79SJean-Baptiste Boric }
1269f988b79SJean-Baptiste Boric
1279f988b79SJean-Baptiste Boric int
bwrite(struct buf * bp)1289f988b79SJean-Baptiste Boric bwrite(struct buf *bp)
1299f988b79SJean-Baptiste Boric {
1309f988b79SJean-Baptiste Boric off_t offset;
1319f988b79SJean-Baptiste Boric ssize_t rv;
1329f988b79SJean-Baptiste Boric int bytes;
1339f988b79SJean-Baptiste Boric fsinfo_t *fs = bp->b_fs;
1349f988b79SJean-Baptiste Boric
1359f988b79SJean-Baptiste Boric assert (bp != NULL);
1369f988b79SJean-Baptiste Boric offset = bp->b_blkno * fs->sectorsize + fs->offset;
1379f988b79SJean-Baptiste Boric bytes = bp->b_bcount;
1389f988b79SJean-Baptiste Boric if (debug & DEBUG_BUF_BWRITE)
1399f988b79SJean-Baptiste Boric printf("bwrite: blkno %lld offset %lld bcount %d\n",
1409f988b79SJean-Baptiste Boric (long long)bp->b_blkno, (long long) offset, bytes);
1419f988b79SJean-Baptiste Boric if (lseek(bp->b_fs->fd, offset, SEEK_SET) == -1)
1429f988b79SJean-Baptiste Boric return (errno);
1439f988b79SJean-Baptiste Boric rv = write(bp->b_fs->fd, bp->b_data, bytes);
1449f988b79SJean-Baptiste Boric if (debug & DEBUG_BUF_BWRITE)
1459f988b79SJean-Baptiste Boric printf("bwrite: write %ld (offset %lld) returned %lld\n",
1469f988b79SJean-Baptiste Boric bp->b_bcount, (long long)offset, (long long)rv);
1479f988b79SJean-Baptiste Boric brelse(bp, 0);
1489f988b79SJean-Baptiste Boric if (rv == bytes)
1499f988b79SJean-Baptiste Boric return (0);
1509f988b79SJean-Baptiste Boric else if (rv == -1) /* write error */
1519f988b79SJean-Baptiste Boric return (errno);
1529f988b79SJean-Baptiste Boric else /* short write ? */
1539f988b79SJean-Baptiste Boric return (EAGAIN);
1549f988b79SJean-Baptiste Boric }
1559f988b79SJean-Baptiste Boric
1569f988b79SJean-Baptiste Boric void
bcleanup(void)1579f988b79SJean-Baptiste Boric bcleanup(void)
1589f988b79SJean-Baptiste Boric {
1599f988b79SJean-Baptiste Boric struct buf *bp;
1609f988b79SJean-Baptiste Boric
1619f988b79SJean-Baptiste Boric /*
1629f988b79SJean-Baptiste Boric * XXX this really shouldn't be necessary, but i'm curious to
1639f988b79SJean-Baptiste Boric * know why there's still some buffers lying around that
1649f988b79SJean-Baptiste Boric * aren't brelse()d
1659f988b79SJean-Baptiste Boric */
1669f988b79SJean-Baptiste Boric
1679f988b79SJean-Baptiste Boric if (TAILQ_EMPTY(&buftail))
1689f988b79SJean-Baptiste Boric return;
1699f988b79SJean-Baptiste Boric
1709f988b79SJean-Baptiste Boric printf("bcleanup: unflushed buffers:\n");
1719f988b79SJean-Baptiste Boric TAILQ_FOREACH(bp, &buftail, b_tailq) {
1729f988b79SJean-Baptiste Boric printf("\tlblkno %10lld blkno %10lld count %6ld bufsize %6ld\n",
1739f988b79SJean-Baptiste Boric (long long)bp->b_lblkno, (long long)bp->b_blkno,
1749f988b79SJean-Baptiste Boric bp->b_bcount, bp->b_bufsize);
1759f988b79SJean-Baptiste Boric }
1769f988b79SJean-Baptiste Boric printf("bcleanup: done\n");
1779f988b79SJean-Baptiste Boric }
1789f988b79SJean-Baptiste Boric
1799f988b79SJean-Baptiste Boric struct buf *
getblk(struct vnode * vp,daddr_t blkno,int size,int u1 __unused,int u2 __unused)1809f988b79SJean-Baptiste Boric getblk(struct vnode *vp, daddr_t blkno, int size, int u1 __unused,
1819f988b79SJean-Baptiste Boric int u2 __unused)
1829f988b79SJean-Baptiste Boric {
1839f988b79SJean-Baptiste Boric static int buftailinitted;
1849f988b79SJean-Baptiste Boric struct buf *bp;
1859f988b79SJean-Baptiste Boric void *n;
1869f988b79SJean-Baptiste Boric
1879f988b79SJean-Baptiste Boric if (debug & DEBUG_BUF_GETBLK)
1889f988b79SJean-Baptiste Boric printf("getblk: blkno %lld size %d\n", (long long)blkno, size);
1899f988b79SJean-Baptiste Boric
1909f988b79SJean-Baptiste Boric bp = NULL;
1919f988b79SJean-Baptiste Boric if (!buftailinitted) {
1929f988b79SJean-Baptiste Boric if (debug & DEBUG_BUF_GETBLK)
1939f988b79SJean-Baptiste Boric printf("getblk: initialising tailq\n");
1949f988b79SJean-Baptiste Boric TAILQ_INIT(&buftail);
1959f988b79SJean-Baptiste Boric buftailinitted = 1;
1969f988b79SJean-Baptiste Boric } else {
1979f988b79SJean-Baptiste Boric TAILQ_FOREACH(bp, &buftail, b_tailq) {
1989f988b79SJean-Baptiste Boric if (bp->b_lblkno != blkno)
1999f988b79SJean-Baptiste Boric continue;
2009f988b79SJean-Baptiste Boric break;
2019f988b79SJean-Baptiste Boric }
2029f988b79SJean-Baptiste Boric }
2039f988b79SJean-Baptiste Boric if (bp == NULL) {
2049f988b79SJean-Baptiste Boric bp = ecalloc(1, sizeof(*bp));
2059f988b79SJean-Baptiste Boric bp->b_bufsize = 0;
2069f988b79SJean-Baptiste Boric bp->b_blkno = bp->b_lblkno = blkno;
2079f988b79SJean-Baptiste Boric bp->b_fs = vp->fs;
2089f988b79SJean-Baptiste Boric bp->b_data = NULL;
2099f988b79SJean-Baptiste Boric TAILQ_INSERT_HEAD(&buftail, bp, b_tailq);
2109f988b79SJean-Baptiste Boric }
2119f988b79SJean-Baptiste Boric bp->b_bcount = size;
2129f988b79SJean-Baptiste Boric if (bp->b_data == NULL || bp->b_bcount > bp->b_bufsize) {
2139f988b79SJean-Baptiste Boric n = erealloc(bp->b_data, size);
2149f988b79SJean-Baptiste Boric memset(n, 0, size);
2159f988b79SJean-Baptiste Boric bp->b_data = n;
2169f988b79SJean-Baptiste Boric bp->b_bufsize = size;
2179f988b79SJean-Baptiste Boric }
2189f988b79SJean-Baptiste Boric
2199f988b79SJean-Baptiste Boric return (bp);
2209f988b79SJean-Baptiste Boric }
221