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

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

unix.superglobalmegacorp.com

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