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*68550Smckusick * @(#)lfs_bio.c 8.5 (Berkeley) 03/21/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; 5356865Smargo int 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; 7156865Smargo while (!LFS_FITS(fs, fsbtodb(fs, 1)) && !IS_IFILE(bp) && 7256155Smargo bp->b_lblkno > 0) { 7356865Smargo /* Out of space, need cleaner to run */ 7456052Sbostic wakeup(&lfs_allclean_wakeup); 7556865Smargo if (error = tsleep(&fs->lfs_avail, PCATCH | PUSER, 7656865Smargo "cleaner", NULL)) { 7756865Smargo brelse(bp); 7856865Smargo return (error); 7956865Smargo } 8055935Sbostic } 8155935Sbostic ip = VTOI((bp)->b_vp); 8264608Sbostic if (!(ip->i_flag & IN_MODIFIED)) 8355935Sbostic ++fs->lfs_uinodes; 8464608Sbostic ip->i_flag |= IN_CHANGE | IN_MODIFIED | IN_UPDATE; 8555935Sbostic fs->lfs_avail -= fsbtodb(fs, 1); 8652081Sbostic ++locked_queue_count; 8753867Sheideman bp->b_flags |= B_DELWRI | B_LOCKED; 8855935Sbostic bp->b_flags &= ~(B_READ | B_ERROR); 8953143Sstaelin s = splbio(); 9053867Sheideman reassignbuf(bp, bp->b_vp); 9153143Sstaelin splx(s); 9253143Sstaelin } 9353867Sheideman brelse(bp); 9451480Sbostic return (0); 9551184Sbostic } 9652081Sbostic 9752081Sbostic /* 9852081Sbostic * XXX 9952081Sbostic * This routine flushes buffers out of the B_LOCKED queue when LFS has too 10052081Sbostic * many locked down. Eventually the pageout daemon will simply call LFS 10152325Sbostic * when pages need to be reclaimed. Note, we have one static count of locked 10252325Sbostic * buffers, so we can't have more than a single file system. To make this 10352325Sbostic * work for multiple file systems, put the count into the mount structure. 10452081Sbostic */ 10552081Sbostic void 10652081Sbostic lfs_flush() 10752081Sbostic { 10852081Sbostic register struct mount *mp; 10952081Sbostic 11057066Smargo #ifdef DOSTATS 11157066Smargo ++lfs_stats.write_exceeded; 11257066Smargo #endif 11355935Sbostic if (lfs_writing) 11452081Sbostic return; 11555935Sbostic lfs_writing = 1; 11665238Smckusick for (mp = mountlist.tqh_first; mp != NULL; mp = mp->mnt_list.tqe_next) { 11755935Sbostic /* The lock check below is to avoid races with unmount. */ 11852081Sbostic if (mp->mnt_stat.f_type == MOUNT_LFS && 11955935Sbostic (mp->mnt_flag & (MNT_MLOCK|MNT_RDONLY|MNT_UNMOUNT)) == 0 && 12055935Sbostic !((((struct ufsmount *)mp->mnt_data))->ufsmount_u.lfs)->lfs_dirops ) { 12152347Sbostic /* 12252347Sbostic * We set the queue to 0 here because we are about to 12352347Sbostic * write all the dirty buffers we have. If more come 12452347Sbostic * in while we're writing the segment, they may not 12552347Sbostic * get written, so we want the count to reflect these 12652347Sbostic * new writes after the segwrite completes. 12752347Sbostic */ 12857066Smargo #ifdef DOSTATS 12957066Smargo ++lfs_stats.flush_invoked; 13057066Smargo #endif 13152081Sbostic lfs_segwrite(mp, 0); 13255935Sbostic } 13365238Smckusick } 13455935Sbostic lfs_writing = 0; 13552081Sbostic } 13655935Sbostic 13755935Sbostic int 13855935Sbostic lfs_check(vp, blkno) 13955935Sbostic struct vnode *vp; 140*68550Smckusick ufs_daddr_t blkno; 14155935Sbostic { 14255935Sbostic extern int lfs_allclean_wakeup; 14355935Sbostic int error; 14455935Sbostic 14556865Smargo error = 0; 14655935Sbostic if (incore(vp, blkno)) 14755935Sbostic return (0); 14855935Sbostic if (locked_queue_count > WRITE_THRESHHOLD) 14955935Sbostic lfs_flush(); 15056865Smargo 15156865Smargo /* If out of buffers, wait on writer */ 15257066Smargo while (locked_queue_count > WAIT_THRESHHOLD) { 15357066Smargo #ifdef DOSTATS 15457066Smargo ++lfs_stats.wait_exceeded; 15557066Smargo #endif 15656865Smargo error = tsleep(&locked_queue_count, PCATCH | PUSER, "buffers", 15756865Smargo hz * LFS_BUFWAIT); 15857066Smargo } 15956865Smargo 16055935Sbostic return (error); 16155935Sbostic } 162