lfs_subr.c revision 1.13
1/* $NetBSD: lfs_subr.c,v 1.13 2000/03/30 12:41:13 augustss Exp $ */ 2 3/*- 4 * Copyright (c) 1999 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Konrad E. Schroder <perseant@hhhh.org>. 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 by the NetBSD 21 * Foundation, Inc. and its contributors. 22 * 4. Neither the name of The NetBSD Foundation nor the names of its 23 * contributors may be used to endorse or promote products derived 24 * from this software without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 27 * ``AS IS'' AND 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 THE FOUNDATION OR CONTRIBUTORS 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 * Copyright (c) 1991, 1993 40 * The Regents of the University of California. All rights reserved. 41 * 42 * Redistribution and use in source and binary forms, with or without 43 * modification, are permitted provided that the following conditions 44 * are met: 45 * 1. Redistributions of source code must retain the above copyright 46 * notice, this list of conditions and the following disclaimer. 47 * 2. Redistributions in binary form must reproduce the above copyright 48 * notice, this list of conditions and the following disclaimer in the 49 * documentation and/or other materials provided with the distribution. 50 * 3. All advertising materials mentioning features or use of this software 51 * must display the following acknowledgement: 52 * This product includes software developed by the University of 53 * California, Berkeley and its contributors. 54 * 4. Neither the name of the University nor the names of its contributors 55 * may be used to endorse or promote products derived from this software 56 * without specific prior written permission. 57 * 58 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 59 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 60 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 61 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 62 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 63 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 64 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 65 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 66 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 67 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 68 * SUCH DAMAGE. 69 * 70 * @(#)lfs_subr.c 8.4 (Berkeley) 5/8/95 71 */ 72 73#include <sys/param.h> 74#include <sys/systm.h> 75#include <sys/namei.h> 76#include <sys/vnode.h> 77#include <sys/buf.h> 78#include <sys/mount.h> 79#include <sys/malloc.h> 80#include <sys/proc.h> 81 82#include <ufs/ufs/quota.h> 83#include <ufs/ufs/inode.h> 84#include <ufs/lfs/lfs.h> 85#include <ufs/lfs/lfs_extern.h> 86 87/* 88 * Return buffer with the contents of block "offset" from the beginning of 89 * directory "ip". If "res" is non-zero, fill it in with a pointer to the 90 * remaining space in the directory. 91 */ 92int 93lfs_blkatoff(v) 94 void *v; 95{ 96 struct vop_blkatoff_args /* { 97 struct vnode *a_vp; 98 off_t a_offset; 99 char **a_res; 100 struct buf **a_bpp; 101 } */ *ap = v; 102 struct lfs *fs; 103 struct inode *ip; 104 struct buf *bp; 105 ufs_daddr_t lbn; 106 int bsize, error; 107 108 ip = VTOI(ap->a_vp); 109 fs = ip->i_lfs; 110 lbn = lblkno(fs, ap->a_offset); 111 bsize = blksize(fs, ip, lbn); 112 113 *ap->a_bpp = NULL; 114 if ((error = bread(ap->a_vp, lbn, bsize, NOCRED, &bp)) != 0) { 115 brelse(bp); 116 return (error); 117 } 118 if (ap->a_res) 119 *ap->a_res = (char *)bp->b_data + blkoff(fs, ap->a_offset); 120 *ap->a_bpp = bp; 121 return (0); 122} 123 124 125/* 126 * lfs_seglock -- 127 * Single thread the segment writer. 128 */ 129void 130lfs_seglock(fs, flags) 131 struct lfs *fs; 132 unsigned long flags; 133{ 134 struct segment *sp; 135 int s; 136 137 if (fs->lfs_seglock) { 138 if (fs->lfs_lockpid == curproc->p_pid) { 139 ++fs->lfs_seglock; 140 fs->lfs_sp->seg_flags |= flags; 141 return; 142 } else while (fs->lfs_seglock) 143 (void)tsleep(&fs->lfs_seglock, PRIBIO + 1, 144 "lfs seglock", 0); 145 } 146 147 fs->lfs_seglock = 1; 148 fs->lfs_lockpid = curproc->p_pid; 149 150 sp = fs->lfs_sp = malloc(sizeof(struct segment), M_SEGMENT, M_WAITOK); 151 sp->bpp = malloc(((LFS_SUMMARY_SIZE - sizeof(SEGSUM)) / 152 sizeof(ufs_daddr_t) + 1) * sizeof(struct buf *), 153 M_SEGMENT, M_WAITOK); 154 sp->seg_flags = flags; 155 sp->vp = NULL; 156 (void) lfs_initseg(fs); 157 158 /* 159 * Keep a cumulative count of the outstanding I/O operations. If the 160 * disk drive catches up with us it could go to zero before we finish, 161 * so we artificially increment it by one until we've scheduled all of 162 * the writes we intend to do. 163 */ 164 s = splbio(); 165 ++fs->lfs_iocount; 166 splx(s); 167} 168 169/* 170 * lfs_segunlock -- 171 * Single thread the segment writer. 172 */ 173void 174lfs_segunlock(fs) 175 struct lfs *fs; 176{ 177 struct segment *sp; 178 unsigned long sync, ckp; 179 int s; 180 struct vnode *vp; 181 struct mount *mp; 182 extern int lfs_dirvcount; 183 184 if (fs->lfs_seglock == 1) { 185 186 mp = fs->lfs_ivnode->v_mount; 187 /* 188 * Go through and unmark all DIROP vnodes, possibly 189 * calling VOP_INACTIVE (through vrele). This is 190 * delayed until now in order not to accidentally 191 * write a DIROP node through lfs_flush. 192 */ 193#ifndef LFS_NO_BACKVP_HACK 194 /* BEGIN HACK */ 195#define VN_OFFSET (((caddr_t)&vp->v_mntvnodes.le_next) - (caddr_t)vp) 196#define BACK_VP(VP) ((struct vnode *)(((caddr_t)VP->v_mntvnodes.le_prev) - VN_OFFSET)) 197#define BEG_OF_VLIST ((struct vnode *)(((caddr_t)&mp->mnt_vnodelist.lh_first) - VN_OFFSET)) 198 199 /* Find last vnode. */ 200 loop: for (vp = mp->mnt_vnodelist.lh_first; 201 vp && vp->v_mntvnodes.le_next != NULL; 202 vp = vp->v_mntvnodes.le_next); 203 for (; vp && vp != BEG_OF_VLIST; vp = BACK_VP(vp)) { 204#else 205 loop: 206 for (vp = mp->mnt_vnodelist.lh_first; 207 vp != NULL; 208 vp = vp->v_mntvnodes.le_next) { 209#endif 210 if (vp->v_mount != mp) 211 goto loop; 212 if (vp->v_type == VNON) 213 continue; 214 if(vp->v_flag & VDIROP) { 215 /* No vref, it has one from before */ 216 --lfs_dirvcount; 217 vp->v_flag &= ~VDIROP; 218 wakeup(&lfs_dirvcount); 219 if(vp->v_usecount == 1) { 220 /* vrele may call VOP_INACTIVE */ 221 vrele(vp); 222 } else 223 lfs_vunref(vp); 224 225 } 226 } 227 228 sp = fs->lfs_sp; 229 sync = sp->seg_flags & SEGM_SYNC; 230 ckp = sp->seg_flags & SEGM_CKP; 231 if (sp->bpp != sp->cbpp) { 232 /* Free allocated segment summary */ 233 fs->lfs_offset -= LFS_SUMMARY_SIZE / DEV_BSIZE; 234 lfs_freebuf(*sp->bpp); 235 } else 236 printf ("unlock to 0 with no summary"); 237 238 free(sp->bpp, M_SEGMENT); 239 free(sp, M_SEGMENT); 240 241 /* 242 * If the I/O count is non-zero, sleep until it reaches zero. 243 * At the moment, the user's process hangs around so we can 244 * sleep. 245 */ 246 s = splbio(); 247 --fs->lfs_iocount; 248 /* 249 * We let checkpoints happen asynchronously. That means 250 * that during recovery, we have to roll forward between 251 * the two segments described by the first and second 252 * superblocks to make sure that the checkpoint described 253 * by a superblock completed. 254 */ 255 while (sync && fs->lfs_iocount) 256 (void)tsleep(&fs->lfs_iocount, PRIBIO + 1, 257 "lfs vflush", 0); 258 splx(s); 259 if (ckp) { 260 fs->lfs_nactive = 0; 261 /* If we *know* everything's on disk, write both sbs */ 262 if(sync) 263 lfs_writesuper(fs,fs->lfs_sboffs[fs->lfs_activesb]); 264 fs->lfs_activesb = 1 - fs->lfs_activesb; 265 lfs_writesuper(fs,fs->lfs_sboffs[fs->lfs_activesb]); 266 } 267 --fs->lfs_seglock; 268 fs->lfs_lockpid = 0; 269 wakeup(&fs->lfs_seglock); 270 } else if (fs->lfs_seglock == 0) { 271 panic ("Seglock not held"); 272 } else { 273 --fs->lfs_seglock; 274 } 275} 276