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