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