buf.c revision 1.5
1/* $OpenBSD: buf.c,v 1.5 2016/10/26 15:31:13 natano 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/param.h> 40#include <sys/time.h> 41 42#include <assert.h> 43#include <errno.h> 44#include <stdio.h> 45#include <stdlib.h> 46#include <unistd.h> 47#include <util.h> 48 49#include "makefs.h" 50#include "buf.h" 51 52TAILQ_HEAD(buftailhead,mkfsbuf) buftail; 53 54int 55bread(struct mkfsvnode *vp, daddr_t blkno, int size, int u2 __unused, 56 struct mkfsbuf **bpp) 57{ 58 off_t offset; 59 ssize_t rv; 60 fsinfo_t *fs = vp->fs; 61 62 assert (bpp != NULL); 63 64 *bpp = getblk(vp, blkno, size, 0, 0); 65 offset = (*bpp)->b_blkno * fs->sectorsize + fs->offset; 66 if (lseek((*bpp)->b_fs->fd, offset, SEEK_SET) == -1) 67 err(1, "%s: lseek %lld (%lld)", __func__, 68 (long long)(*bpp)->b_blkno, (long long)offset); 69 rv = read((*bpp)->b_fs->fd, (*bpp)->b_data, (size_t)(*bpp)->b_bcount); 70 if (rv == -1) /* read error */ 71 err(1, "%s: read %ld (%lld) returned %zd", __func__, 72 (*bpp)->b_bcount, (long long)offset, rv); 73 else if (rv != (*bpp)->b_bcount) /* short read */ 74 errx(1, "%s: read %ld (%lld) returned %zd", __func__, 75 (*bpp)->b_bcount, (long long)offset, rv); 76 else 77 return (0); 78} 79 80void 81brelse(struct mkfsbuf *bp, int u1 __unused) 82{ 83 84 assert (bp != NULL); 85 assert (bp->b_data != NULL); 86 87 if (bp->b_lblkno < 0) { 88 /* 89 * XXX don't remove any buffers with negative logical block 90 * numbers (lblkno), so that we retain the mapping 91 * of negative lblkno -> real blkno that ffs_balloc() 92 * sets up. 93 * 94 * if we instead released these buffers, and implemented 95 * ufs_strategy() (and ufs_bmaparray()) and called those 96 * from bread() and bwrite() to convert the lblkno to 97 * a real blkno, we'd add a lot more code & complexity 98 * and reading off disk, for little gain, because this 99 * simple hack works for our purpose. 100 */ 101 bp->b_bcount = 0; 102 return; 103 } 104 105 TAILQ_REMOVE(&buftail, bp, b_tailq); 106 free(bp->b_data); 107 free(bp); 108} 109 110int 111bwrite(struct mkfsbuf *bp) 112{ 113 off_t offset; 114 ssize_t rv; 115 size_t bytes; 116 fsinfo_t *fs = bp->b_fs; 117 118 assert (bp != NULL); 119 offset = bp->b_blkno * fs->sectorsize + fs->offset; 120 bytes = (size_t)bp->b_bcount; 121 if (lseek(bp->b_fs->fd, offset, SEEK_SET) == -1) 122 return (errno); 123 rv = write(bp->b_fs->fd, bp->b_data, bytes); 124 brelse(bp, 0); 125 if (rv == (ssize_t)bytes) 126 return (0); 127 else if (rv == -1) /* write error */ 128 return (errno); 129 else /* short write ? */ 130 return (EAGAIN); 131} 132 133void 134bcleanup(void) 135{ 136#if DEBUG_BUFFERS 137 struct mkfsbuf *bp; 138 139 /* 140 * XXX this really shouldn't be necessary, but i'm curious to 141 * know why there's still some buffers lying around that 142 * aren't brelse()d 143 */ 144 145 if (TAILQ_EMPTY(&buftail)) 146 return; 147 148 printf("bcleanup: unflushed buffers:\n"); 149 TAILQ_FOREACH(bp, &buftail, b_tailq) { 150 printf("\tlblkno %10lld blkno %10lld count %6ld bufsize %6ld\n", 151 (long long)bp->b_lblkno, (long long)bp->b_blkno, 152 bp->b_bcount, bp->b_bufsize); 153 } 154 printf("bcleanup: done\n"); 155#endif 156} 157 158struct mkfsbuf * 159getblk(struct mkfsvnode *vp, daddr_t blkno, int size, int u1 __unused, 160 int u2 __unused) 161{ 162 static int buftailinitted; 163 struct mkfsbuf *bp; 164 void *n; 165 166 bp = NULL; 167 if (!buftailinitted) { 168 TAILQ_INIT(&buftail); 169 buftailinitted = 1; 170 } else { 171 TAILQ_FOREACH(bp, &buftail, b_tailq) { 172 if (bp->b_lblkno != blkno) 173 continue; 174 break; 175 } 176 } 177 if (bp == NULL) { 178 bp = ecalloc(1, sizeof(*bp)); 179 bp->b_bufsize = 0; 180 bp->b_blkno = bp->b_lblkno = blkno; 181 bp->b_fs = vp->fs; 182 bp->b_data = NULL; 183 TAILQ_INSERT_HEAD(&buftail, bp, b_tailq); 184 } 185 bp->b_bcount = size; 186 if (bp->b_data == NULL || bp->b_bcount > bp->b_bufsize) { 187 n = erealloc(bp->b_data, (size_t)size); 188 memset(n, 0, (size_t)size); 189 bp->b_data = n; 190 bp->b_bufsize = size; 191 } 192 193 return (bp); 194} 195