buf.c revision 1.7
1/* $OpenBSD: buf.c,v 1.7 2021/10/06 00:40:41 deraadt Exp $ */ 2/* $NetBSD: buf.c,v 1.24 2016/06/24 19:24:11 christos Exp $ */ 3 4/* 5 * Copyright (c) 2001 Wasabi Systems, Inc. 6 * All rights reserved. 7 * 8 * Written by Luke Mewburn for Wasabi Systems, Inc. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed for the NetBSD Project by 21 * Wasabi Systems, Inc. 22 * 4. The name of Wasabi Systems, Inc. may not be used to endorse 23 * or promote products derived from this software without specific prior 24 * written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND 27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC 30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 36 * POSSIBILITY OF SUCH DAMAGE. 37 */ 38 39#include <sys/time.h> 40 41#include <assert.h> 42#include <errno.h> 43#include <stdio.h> 44#include <stdlib.h> 45#include <unistd.h> 46#include <util.h> 47 48#include "makefs.h" 49#include "buf.h" 50 51TAILQ_HEAD(buftailhead,mkfsbuf) buftail; 52 53int 54bread(struct mkfsvnode *vp, daddr_t blkno, int size, int u2 __unused, 55 struct mkfsbuf **bpp) 56{ 57 off_t offset; 58 ssize_t rv; 59 fsinfo_t *fs = vp->fs; 60 61 assert (bpp != NULL); 62 63 *bpp = getblk(vp, blkno, size, 0, 0); 64 offset = (*bpp)->b_blkno * fs->sectorsize + fs->offset; 65 if (lseek((*bpp)->b_fs->fd, offset, SEEK_SET) == -1) 66 err(1, "%s: lseek %lld (%lld)", __func__, 67 (long long)(*bpp)->b_blkno, (long long)offset); 68 rv = read((*bpp)->b_fs->fd, (*bpp)->b_data, (size_t)(*bpp)->b_bcount); 69 if (rv == -1) /* read error */ 70 err(1, "%s: read %ld (%lld) returned %zd", __func__, 71 (*bpp)->b_bcount, (long long)offset, rv); 72 else if (rv != (*bpp)->b_bcount) /* short read */ 73 errx(1, "%s: read %ld (%lld) returned %zd", __func__, 74 (*bpp)->b_bcount, (long long)offset, rv); 75 else 76 return (0); 77} 78 79void 80brelse(struct mkfsbuf *bp, int u1 __unused) 81{ 82 83 assert (bp != NULL); 84 assert (bp->b_data != NULL); 85 86 if (bp->b_lblkno < 0) { 87 /* 88 * XXX don't remove any buffers with negative logical block 89 * numbers (lblkno), so that we retain the mapping 90 * of negative lblkno -> real blkno that ffs_balloc() 91 * sets up. 92 * 93 * if we instead released these buffers, and implemented 94 * ufs_strategy() (and ufs_bmaparray()) and called those 95 * from bread() and bwrite() to convert the lblkno to 96 * a real blkno, we'd add a lot more code & complexity 97 * and reading off disk, for little gain, because this 98 * simple hack works for our purpose. 99 */ 100 bp->b_bcount = 0; 101 return; 102 } 103 104 TAILQ_REMOVE(&buftail, bp, b_tailq); 105 free(bp->b_data); 106 free(bp); 107} 108 109int 110bwrite(struct mkfsbuf *bp) 111{ 112 off_t offset; 113 ssize_t rv; 114 size_t bytes; 115 fsinfo_t *fs = bp->b_fs; 116 117 assert (bp != NULL); 118 offset = bp->b_blkno * fs->sectorsize + fs->offset; 119 bytes = (size_t)bp->b_bcount; 120 if (lseek(bp->b_fs->fd, offset, SEEK_SET) == -1) 121 return (errno); 122 rv = write(bp->b_fs->fd, bp->b_data, bytes); 123 brelse(bp, 0); 124 if (rv == (ssize_t)bytes) 125 return (0); 126 else if (rv == -1) /* write error */ 127 return (errno); 128 else /* short write ? */ 129 return (EAGAIN); 130} 131 132void 133bcleanup(void) 134{ 135#if DEBUG_BUFFERS 136 struct mkfsbuf *bp; 137 138 /* 139 * XXX this really shouldn't be necessary, but i'm curious to 140 * know why there's still some buffers lying around that 141 * aren't brelse()d 142 */ 143 144 if (TAILQ_EMPTY(&buftail)) 145 return; 146 147 printf("bcleanup: unflushed buffers:\n"); 148 TAILQ_FOREACH(bp, &buftail, b_tailq) { 149 printf("\tlblkno %10lld blkno %10lld count %6ld bufsize %6ld\n", 150 (long long)bp->b_lblkno, (long long)bp->b_blkno, 151 bp->b_bcount, bp->b_bufsize); 152 } 153 printf("bcleanup: done\n"); 154#endif 155} 156 157struct mkfsbuf * 158getblk(struct mkfsvnode *vp, daddr_t blkno, int size, int u1 __unused, 159 int u2 __unused) 160{ 161 static int buftailinitted; 162 struct mkfsbuf *bp; 163 void *n; 164 165 bp = NULL; 166 if (!buftailinitted) { 167 TAILQ_INIT(&buftail); 168 buftailinitted = 1; 169 } else { 170 TAILQ_FOREACH(bp, &buftail, b_tailq) { 171 if (bp->b_lblkno != blkno) 172 continue; 173 break; 174 } 175 } 176 if (bp == NULL) { 177 bp = ecalloc(1, sizeof(*bp)); 178 bp->b_bufsize = 0; 179 bp->b_blkno = bp->b_lblkno = blkno; 180 bp->b_fs = vp->fs; 181 bp->b_data = NULL; 182 TAILQ_INSERT_HEAD(&buftail, bp, b_tailq); 183 } 184 bp->b_bcount = size; 185 if (bp->b_data == NULL || bp->b_bcount > bp->b_bufsize) { 186 n = erealloc(bp->b_data, (size_t)size); 187 memset(n, 0, (size_t)size); 188 bp->b_data = n; 189 bp->b_bufsize = size; 190 } 191 192 return (bp); 193} 194