Annotation of kernel/bsd/ufs/lfs/lfs_bio.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
                      3:  *
                      4:  * @APPLE_LICENSE_HEADER_START@
                      5:  * 
                      6:  * Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
                      7:  * Reserved.  This file contains Original Code and/or Modifications of
                      8:  * Original Code as defined in and that are subject to the Apple Public
                      9:  * Source License Version 1.1 (the "License").  You may not use this file
                     10:  * except in compliance with the License.  Please obtain a copy of the
                     11:  * License at http://www.apple.com/publicsource and read it before using
                     12:  * this file.
                     13:  * 
                     14:  * The Original Code and all software distributed under the License are
                     15:  * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
                     16:  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
                     17:  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
                     18:  * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
                     19:  * License for the specific language governing rights and limitations
                     20:  * under the License.
                     21:  * 
                     22:  * @APPLE_LICENSE_HEADER_END@
                     23:  */
                     24: 
                     25: /*     $NetBSD: lfs_bio.c,v 1.3 1995/01/18 06:19:52 mycroft Exp $      */
                     26: 
                     27: /*
                     28:  * Copyright (c) 1991, 1993
                     29:  *     The Regents of the University of California.  All rights reserved.
                     30:  *
                     31:  * Redistribution and use in source and binary forms, with or without
                     32:  * modification, are permitted provided that the following conditions
                     33:  * are met:
                     34:  * 1. Redistributions of source code must retain the above copyright
                     35:  *    notice, this list of conditions and the following disclaimer.
                     36:  * 2. Redistributions in binary form must reproduce the above copyright
                     37:  *    notice, this list of conditions and the following disclaimer in the
                     38:  *    documentation and/or other materials provided with the distribution.
                     39:  * 3. All advertising materials mentioning features or use of this software
                     40:  *    must display the following acknowledgement:
                     41:  *     This product includes software developed by the University of
                     42:  *     California, Berkeley and its contributors.
                     43:  * 4. Neither the name of the University nor the names of its contributors
                     44:  *    may be used to endorse or promote products derived from this software
                     45:  *    without specific prior written permission.
                     46:  *
                     47:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     48:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     49:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     50:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     51:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     52:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     53:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     54:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     55:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     56:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     57:  * SUCH DAMAGE.
                     58:  *
                     59:  *     @(#)lfs_bio.c   8.4 (Berkeley) 12/30/93
                     60:  */
                     61: 
                     62: #include <sys/param.h>
                     63: #include <sys/proc.h>
                     64: #include <sys/buf.h>
                     65: #include <sys/vnode.h>
                     66: #include <sys/resourcevar.h>
                     67: #include <sys/mount.h>
                     68: #include <sys/kernel.h>
                     69: 
                     70: #include <ufs/ufs/quota.h>
                     71: #include <ufs/ufs/inode.h>
                     72: #include <ufs/ufs/ufsmount.h>
                     73: 
                     74: #include <ufs/lfs/lfs.h>
                     75: #include <ufs/lfs/lfs_extern.h>
                     76: 
                     77: /*
                     78:  * LFS block write function.
                     79:  *
                     80:  * XXX
                     81:  * No write cost accounting is done.
                     82:  * This is almost certainly wrong for synchronous operations and NFS.
                     83:  */
                     84: int    lfs_allclean_wakeup;            /* Cleaner wakeup address. */
                     85: int    locked_queue_count;             /* XXX Count of locked-down buffers. */
                     86: int    lfs_writing;                    /* Set if already kicked off a writer
                     87:                                           because of buffer space */
                     88: /*
                     89: #define WRITE_THRESHHOLD       ((nbuf >> 2) - 10)
                     90: #define WAIT_THRESHHOLD                ((nbuf >> 1) - 10)
                     91: */
                     92: #define WAIT_THRESHHOLD         (nbuf - (nbuf >> 2) - 10)
                     93: #define WRITE_THRESHHOLD        ((nbuf >> 1) - 10)
                     94: #define LFS_BUFWAIT    2
                     95: 
                     96: int
                     97: lfs_bwrite(ap)
                     98:        struct vop_bwrite_args /* {
                     99:                struct buf *a_bp;
                    100:        } */ *ap;
                    101: {
                    102:        register struct buf *bp = ap->a_bp;
                    103:        struct lfs *fs;
                    104:        struct inode *ip;
                    105:        int error, s;
                    106: 
                    107:        /*
                    108:         * Set the delayed write flag and use reassignbuf to move the buffer
                    109:         * from the clean list to the dirty one.
                    110:         *
                    111:         * Set the B_LOCKED flag and unlock the buffer, causing brelse to move
                    112:         * the buffer onto the LOCKED free list.  This is necessary, otherwise
                    113:         * getnewbuf() would try to reclaim the buffers using bawrite, which
                    114:         * isn't going to work.
                    115:         *
                    116:         * XXX we don't let meta-data writes run out of space because they can
                    117:         * come from the segment writer.  We need to make sure that there is
                    118:         * enough space reserved so that there's room to write meta-data
                    119:         * blocks.
                    120:         */
                    121:        if (!(bp->b_flags & B_LOCKED)) {
                    122:                fs = VFSTOUFS(bp->b_vp->v_mount)->um_lfs;
                    123:                while (!LFS_FITS(fs, fsbtodb(fs, 1)) && !IS_IFILE(bp) &&
                    124:                    bp->b_lblkno > 0) {
                    125:                        /* Out of space, need cleaner to run */
                    126:                        wakeup(&lfs_allclean_wakeup);
                    127:                        if (error = tsleep(&fs->lfs_avail, PCATCH | PUSER,
                    128:                            "cleaner", NULL)) {
                    129:                                brelse(bp);
                    130:                                return (error);
                    131:                        }
                    132:                }
                    133:                ip = VTOI((bp)->b_vp);
                    134:                if (!(ip->i_flag & IN_MODIFIED))
                    135:                        ++fs->lfs_uinodes;
                    136:                ip->i_flag |= IN_CHANGE | IN_MODIFIED | IN_UPDATE;
                    137:                fs->lfs_avail -= fsbtodb(fs, 1);
                    138:                ++locked_queue_count;
                    139:                bp->b_flags |= B_DELWRI | B_LOCKED;
                    140:                bp->b_flags &= ~(B_READ | B_ERROR);
                    141:                s = splbio();
                    142:                reassignbuf(bp, bp->b_vp);
                    143:                splx(s);
                    144:        }
                    145:        brelse(bp);
                    146:        return (0);
                    147: }
                    148: 
                    149: /*
                    150:  * XXX
                    151:  * This routine flushes buffers out of the B_LOCKED queue when LFS has too
                    152:  * many locked down.  Eventually the pageout daemon will simply call LFS
                    153:  * when pages need to be reclaimed.  Note, we have one static count of locked
                    154:  * buffers, so we can't have more than a single file system.  To make this
                    155:  * work for multiple file systems, put the count into the mount structure.
                    156:  */
                    157: void
                    158: lfs_flush()
                    159: {
                    160:        register struct mount *mp;
                    161: 
                    162: #ifdef DOSTATS
                    163:        ++lfs_stats.write_exceeded;
                    164: #endif
                    165:        if (lfs_writing)
                    166:                return;
                    167:        lfs_writing = 1;
                    168:        for (mp = mountlist.cqh_first; mp != (void *)&mountlist;
                    169:             mp = mp->mnt_list.cqe_next) {
                    170:                /* The lock check below is to avoid races with unmount. */
                    171:                if (!strcmp(&mp->mnt_stat.f_fstypename[0], MOUNT_LFS) &&
                    172:                    (mp->mnt_flag & (MNT_MLOCK|MNT_RDONLY|MNT_UNMOUNT)) == 0 &&
                    173:                    !((((struct ufsmount *)mp->mnt_data))->ufsmount_u.lfs)->lfs_dirops ) {
                    174:                        /*
                    175:                         * We set the queue to 0 here because we are about to
                    176:                         * write all the dirty buffers we have.  If more come
                    177:                         * in while we're writing the segment, they may not
                    178:                         * get written, so we want the count to reflect these
                    179:                         * new writes after the segwrite completes.
                    180:                         */
                    181: #ifdef DOSTATS
                    182:                        ++lfs_stats.flush_invoked;
                    183: #endif
                    184:                        lfs_segwrite(mp, 0);
                    185:                }
                    186:        }
                    187:        lfs_writing = 0;
                    188: }
                    189: 
                    190: int
                    191: lfs_check(vp, blkno)
                    192:        struct vnode *vp;
                    193:        daddr_t blkno;
                    194: {
                    195:        extern int lfs_allclean_wakeup;
                    196:        int error;
                    197: 
                    198:        error = 0;
                    199:        if (incore(vp, blkno))
                    200:                return (0);
                    201:        if (locked_queue_count > WRITE_THRESHHOLD)
                    202:                lfs_flush();
                    203: 
                    204:        /* If out of buffers, wait on writer */
                    205:        while (locked_queue_count > WAIT_THRESHHOLD) {
                    206: #ifdef DOSTATS
                    207:            ++lfs_stats.wait_exceeded;
                    208: #endif
                    209:            error = tsleep(&locked_queue_count, PCATCH | PUSER, "buffers",
                    210:                hz * LFS_BUFWAIT);
                    211:        }
                    212: 
                    213:        return (error);
                    214: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.