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