1 /* 2 * Copyright (c) 1991 Regents of the University of California. 3 * All rights reserved. 4 * 5 * %sccs.include.redist.c% 6 * 7 * @(#)lfs_bio.c 7.17 (Berkeley) 09/02/92 8 */ 9 10 #include <sys/param.h> 11 #include <sys/proc.h> 12 #include <sys/buf.h> 13 #include <sys/vnode.h> 14 #include <sys/resourcevar.h> 15 #include <sys/mount.h> 16 17 #include <ufs/ufs/quota.h> 18 #include <ufs/ufs/inode.h> 19 #include <ufs/ufs/ufsmount.h> 20 21 #include <ufs/lfs/lfs.h> 22 #include <ufs/lfs/lfs_extern.h> 23 24 /* 25 * LFS block write function. 26 * 27 * XXX 28 * No write cost accounting is done. 29 * This is almost certainly wrong for synchronous operations and NFS. 30 */ 31 int lfs_allclean_wakeup; /* Cleaner wakeup address. */ 32 int locked_queue_count; /* XXX Count of locked-down buffers. */ 33 int lfs_writing; /* Set if already kicked off a writer 34 because of buffer space */ 35 #define WRITE_THRESHHOLD ((nbuf >> 2) - 10) 36 #define WAIT_THRESHHOLD ((nbuf >> 1) - 10) 37 38 int 39 lfs_bwrite(ap) 40 struct vop_bwrite_args /* { 41 struct buf *a_bp; 42 } */ *ap; 43 { 44 register struct buf *bp = ap->a_bp; 45 struct lfs *fs; 46 struct inode *ip; 47 int s; 48 49 /* 50 * Set the delayed write flag and use reassignbuf to move the buffer 51 * from the clean list to the dirty one. 52 * 53 * Set the B_LOCKED flag and unlock the buffer, causing brelse to move 54 * the buffer onto the LOCKED free list. This is necessary, otherwise 55 * getnewbuf() would try to reclaim the buffers using bawrite, which 56 * isn't going to work. 57 * 58 * XXX we don't let meta-data writes run out of space because they can 59 * come from the segment writer. We need to make sure that there is 60 * enough space reserved so that there's room to write meta-data 61 * blocks. 62 */ 63 if (!(bp->b_flags & B_LOCKED)) { 64 fs = VFSTOUFS(bp->b_vp->v_mount)->um_lfs; 65 if (!LFS_FITS(fs, fsbtodb(fs, 1)) && !IS_IFILE(bp) && 66 bp->b_lblkno > 0) { 67 brelse(bp); 68 wakeup(&lfs_allclean_wakeup); 69 return (ENOSPC); 70 } 71 ip = VTOI((bp)->b_vp); 72 if (!(ip->i_flag & IMOD)) 73 ++fs->lfs_uinodes; 74 ip->i_flag |= IMOD | ICHG | IUPD; \ 75 fs->lfs_avail -= fsbtodb(fs, 1); 76 ++locked_queue_count; 77 bp->b_flags |= B_DELWRI | B_LOCKED; 78 bp->b_flags &= ~(B_READ | B_ERROR); 79 s = splbio(); 80 reassignbuf(bp, bp->b_vp); 81 splx(s); 82 } 83 brelse(bp); 84 return (0); 85 } 86 87 /* 88 * XXX 89 * This routine flushes buffers out of the B_LOCKED queue when LFS has too 90 * many locked down. Eventually the pageout daemon will simply call LFS 91 * when pages need to be reclaimed. Note, we have one static count of locked 92 * buffers, so we can't have more than a single file system. To make this 93 * work for multiple file systems, put the count into the mount structure. 94 */ 95 void 96 lfs_flush() 97 { 98 register struct mount *mp; 99 100 if (lfs_writing) 101 return; 102 lfs_writing = 1; 103 mp = rootfs; 104 do { 105 /* The lock check below is to avoid races with unmount. */ 106 if (mp->mnt_stat.f_type == MOUNT_LFS && 107 (mp->mnt_flag & (MNT_MLOCK|MNT_RDONLY|MNT_UNMOUNT)) == 0 && 108 !((((struct ufsmount *)mp->mnt_data))->ufsmount_u.lfs)->lfs_dirops ) { 109 /* 110 * We set the queue to 0 here because we are about to 111 * write all the dirty buffers we have. If more come 112 * in while we're writing the segment, they may not 113 * get written, so we want the count to reflect these 114 * new writes after the segwrite completes. 115 */ 116 lfs_segwrite(mp, 0); 117 } 118 mp = mp->mnt_next; 119 } while (mp != rootfs); 120 lfs_writing = 0; 121 } 122 123 int 124 lfs_check(vp, blkno) 125 struct vnode *vp; 126 daddr_t blkno; 127 { 128 extern int lfs_allclean_wakeup; 129 int error; 130 131 if (incore(vp, blkno)) 132 return (0); 133 if (locked_queue_count > WRITE_THRESHHOLD) 134 lfs_flush(); 135 if (locked_queue_count > WAIT_THRESHHOLD) 136 error = tsleep(&lfs_allclean_wakeup, PCATCH | PUSER, 137 "buffers", NULL); 138 return (error); 139 } 140