151184Sbostic /* 263375Sbostic * Copyright (c) 1991, 1993 363375Sbostic * The Regents of the University of California. All rights reserved. 451184Sbostic * 551184Sbostic * %sccs.include.redist.c% 651184Sbostic * 7*69287Smckusick * @(#)lfs_bio.c 8.7 (Berkeley) 05/08/95 851184Sbostic */ 951184Sbostic 1051480Sbostic #include <sys/param.h> 1151480Sbostic #include <sys/proc.h> 1251480Sbostic #include <sys/buf.h> 1352081Sbostic #include <sys/vnode.h> 1451480Sbostic #include <sys/resourcevar.h> 1552081Sbostic #include <sys/mount.h> 1656865Smargo #include <sys/kernel.h> 1751184Sbostic 1852081Sbostic #include <ufs/ufs/quota.h> 1952081Sbostic #include <ufs/ufs/inode.h> 2052081Sbostic #include <ufs/ufs/ufsmount.h> 2152081Sbostic 2251493Sbostic #include <ufs/lfs/lfs.h> 2351493Sbostic #include <ufs/lfs/lfs_extern.h> 2451480Sbostic 2552081Sbostic /* 2652081Sbostic * LFS block write function. 2752081Sbostic * 2852081Sbostic * XXX 2952081Sbostic * No write cost accounting is done. 3052081Sbostic * This is almost certainly wrong for synchronous operations and NFS. 3152081Sbostic */ 3256052Sbostic int lfs_allclean_wakeup; /* Cleaner wakeup address. */ 3352081Sbostic int locked_queue_count; /* XXX Count of locked-down buffers. */ 3455935Sbostic int lfs_writing; /* Set if already kicked off a writer 3555935Sbostic because of buffer space */ 3657066Smargo /* 3755935Sbostic #define WRITE_THRESHHOLD ((nbuf >> 2) - 10) 3855935Sbostic #define WAIT_THRESHHOLD ((nbuf >> 1) - 10) 3957066Smargo */ 4057066Smargo #define WAIT_THRESHHOLD (nbuf - (nbuf >> 2) - 10) 4157066Smargo #define WRITE_THRESHHOLD ((nbuf >> 1) - 10) 4256865Smargo #define LFS_BUFWAIT 2 4352081Sbostic 4451480Sbostic int 4554621Smckusick lfs_bwrite(ap) 4654621Smckusick struct vop_bwrite_args /* { 4754621Smckusick struct buf *a_bp; 4854621Smckusick } */ *ap; 4951184Sbostic { 5053867Sheideman register struct buf *bp = ap->a_bp; 5155935Sbostic struct lfs *fs; 5255935Sbostic struct inode *ip; 53*69287Smckusick int db, error, s; 5455807Sbostic 5551851Sbostic /* 5652081Sbostic * Set the delayed write flag and use reassignbuf to move the buffer 5752081Sbostic * from the clean list to the dirty one. 5851851Sbostic * 5952081Sbostic * Set the B_LOCKED flag and unlock the buffer, causing brelse to move 6052081Sbostic * the buffer onto the LOCKED free list. This is necessary, otherwise 6152081Sbostic * getnewbuf() would try to reclaim the buffers using bawrite, which 6252081Sbostic * isn't going to work. 6356155Smargo * 6456155Smargo * XXX we don't let meta-data writes run out of space because they can 6556155Smargo * come from the segment writer. We need to make sure that there is 6656155Smargo * enough space reserved so that there's room to write meta-data 6756155Smargo * blocks. 6851851Sbostic */ 6953867Sheideman if (!(bp->b_flags & B_LOCKED)) { 7055935Sbostic fs = VFSTOUFS(bp->b_vp->v_mount)->um_lfs; 71*69287Smckusick db = fragstodb(fs, numfrags(fs, bp->b_bcount)); 72*69287Smckusick while (!LFS_FITS(fs, db) && !IS_IFILE(bp) && 7356155Smargo bp->b_lblkno > 0) { 7456865Smargo /* Out of space, need cleaner to run */ 7556052Sbostic wakeup(&lfs_allclean_wakeup); 7656865Smargo if (error = tsleep(&fs->lfs_avail, PCATCH | PUSER, 7756865Smargo "cleaner", NULL)) { 7856865Smargo brelse(bp); 7956865Smargo return (error); 8056865Smargo } 8155935Sbostic } 8255935Sbostic ip = VTOI((bp)->b_vp); 8364608Sbostic if (!(ip->i_flag & IN_MODIFIED)) 8455935Sbostic ++fs->lfs_uinodes; 8564608Sbostic ip->i_flag |= IN_CHANGE | IN_MODIFIED | IN_UPDATE; 86*69287Smckusick fs->lfs_avail -= db; 8752081Sbostic ++locked_queue_count; 8853867Sheideman bp->b_flags |= B_DELWRI | B_LOCKED; 8955935Sbostic bp->b_flags &= ~(B_READ | B_ERROR); 9053143Sstaelin s = splbio(); 9153867Sheideman reassignbuf(bp, bp->b_vp); 9253143Sstaelin splx(s); 9353143Sstaelin } 9453867Sheideman brelse(bp); 9551480Sbostic return (0); 9651184Sbostic } 9752081Sbostic 9852081Sbostic /* 9952081Sbostic * XXX 10052081Sbostic * This routine flushes buffers out of the B_LOCKED queue when LFS has too 10152081Sbostic * many locked down. Eventually the pageout daemon will simply call LFS 10252325Sbostic * when pages need to be reclaimed. Note, we have one static count of locked 10352325Sbostic * buffers, so we can't have more than a single file system. To make this 10452325Sbostic * work for multiple file systems, put the count into the mount structure. 10552081Sbostic */ 10652081Sbostic void 10752081Sbostic lfs_flush() 10852081Sbostic { 10952081Sbostic register struct mount *mp; 11052081Sbostic 11157066Smargo #ifdef DOSTATS 11257066Smargo ++lfs_stats.write_exceeded; 11357066Smargo #endif 11455935Sbostic if (lfs_writing) 11552081Sbostic return; 11655935Sbostic lfs_writing = 1; 11765238Smckusick for (mp = mountlist.tqh_first; mp != NULL; mp = mp->mnt_list.tqe_next) { 11855935Sbostic /* The lock check below is to avoid races with unmount. */ 11968675Smckusick if (mp->mnt_stat.f_type == lfs_mount_type && 12055935Sbostic (mp->mnt_flag & (MNT_MLOCK|MNT_RDONLY|MNT_UNMOUNT)) == 0 && 12155935Sbostic !((((struct ufsmount *)mp->mnt_data))->ufsmount_u.lfs)->lfs_dirops ) { 12252347Sbostic /* 12352347Sbostic * We set the queue to 0 here because we are about to 12452347Sbostic * write all the dirty buffers we have. If more come 12552347Sbostic * in while we're writing the segment, they may not 12652347Sbostic * get written, so we want the count to reflect these 12752347Sbostic * new writes after the segwrite completes. 12852347Sbostic */ 12957066Smargo #ifdef DOSTATS 13057066Smargo ++lfs_stats.flush_invoked; 13157066Smargo #endif 13252081Sbostic lfs_segwrite(mp, 0); 13355935Sbostic } 13465238Smckusick } 13555935Sbostic lfs_writing = 0; 13652081Sbostic } 13755935Sbostic 13855935Sbostic int 13955935Sbostic lfs_check(vp, blkno) 14055935Sbostic struct vnode *vp; 14168550Smckusick ufs_daddr_t blkno; 14255935Sbostic { 14355935Sbostic extern int lfs_allclean_wakeup; 14455935Sbostic int error; 14555935Sbostic 14656865Smargo error = 0; 14755935Sbostic if (incore(vp, blkno)) 14855935Sbostic return (0); 14955935Sbostic if (locked_queue_count > WRITE_THRESHHOLD) 15055935Sbostic lfs_flush(); 15156865Smargo 15256865Smargo /* If out of buffers, wait on writer */ 15357066Smargo while (locked_queue_count > WAIT_THRESHHOLD) { 15457066Smargo #ifdef DOSTATS 15557066Smargo ++lfs_stats.wait_exceeded; 15657066Smargo #endif 15756865Smargo error = tsleep(&locked_queue_count, PCATCH | PUSER, "buffers", 15856865Smargo hz * LFS_BUFWAIT); 15957066Smargo } 16056865Smargo 16155935Sbostic return (error); 16255935Sbostic } 163