daddr_t => ufs_daddr_t
[unix-history] / usr / src / sys / ufs / lfs / lfs_bio.c
CommitLineData
8c6ec179 1/*
ad0f93d2
KB
2 * Copyright (c) 1991, 1993
3 * The Regents of the University of California. All rights reserved.
8c6ec179
KB
4 *
5 * %sccs.include.redist.c%
6 *
89e2bb79 7 * @(#)lfs_bio.c 8.5 (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 */
f5e3f593 36/*
edc34597
KB
37#define WRITE_THRESHHOLD ((nbuf >> 2) - 10)
38#define WAIT_THRESHHOLD ((nbuf >> 1) - 10)
f5e3f593
MS
39*/
40#define WAIT_THRESHHOLD (nbuf - (nbuf >> 2) - 10)
41#define WRITE_THRESHHOLD ((nbuf >> 1) - 10)
1e0be126 42#define LFS_BUFWAIT 2
5c5f0f67 43
a5219e6e 44int
9e673f96
KM
45lfs_bwrite(ap)
46 struct vop_bwrite_args /* {
47 struct buf *a_bp;
48 } */ *ap;
8c6ec179 49{
406c9a0d 50 register struct buf *bp = ap->a_bp;
edc34597
KB
51 struct lfs *fs;
52 struct inode *ip;
1e0be126 53 int error, s;
fa870596 54
9a1dcf8a 55 /*
5c5f0f67
KB
56 * Set the delayed write flag and use reassignbuf to move the buffer
57 * from the clean list to the dirty one.
9a1dcf8a 58 *
5c5f0f67
KB
59 * Set the B_LOCKED flag and unlock the buffer, causing brelse to move
60 * the buffer onto the LOCKED free list. This is necessary, otherwise
61 * getnewbuf() would try to reclaim the buffers using bawrite, which
62 * isn't going to work.
41ba8073
MS
63 *
64 * XXX we don't let meta-data writes run out of space because they can
65 * come from the segment writer. We need to make sure that there is
66 * enough space reserved so that there's room to write meta-data
67 * blocks.
9a1dcf8a 68 */
406c9a0d 69 if (!(bp->b_flags & B_LOCKED)) {
edc34597 70 fs = VFSTOUFS(bp->b_vp->v_mount)->um_lfs;
1e0be126 71 while (!LFS_FITS(fs, fsbtodb(fs, 1)) && !IS_IFILE(bp) &&
41ba8073 72 bp->b_lblkno > 0) {
1e0be126 73 /* Out of space, need cleaner to run */
9e867303 74 wakeup(&lfs_allclean_wakeup);
1e0be126
MS
75 if (error = tsleep(&fs->lfs_avail, PCATCH | PUSER,
76 "cleaner", NULL)) {
77 brelse(bp);
78 return (error);
79 }
edc34597
KB
80 }
81 ip = VTOI((bp)->b_vp);
cf5ef508 82 if (!(ip->i_flag & IN_MODIFIED))
edc34597 83 ++fs->lfs_uinodes;
cf5ef508 84 ip->i_flag |= IN_CHANGE | IN_MODIFIED | IN_UPDATE;
edc34597 85 fs->lfs_avail -= fsbtodb(fs, 1);
5c5f0f67 86 ++locked_queue_count;
406c9a0d 87 bp->b_flags |= B_DELWRI | B_LOCKED;
edc34597 88 bp->b_flags &= ~(B_READ | B_ERROR);
9f1a72f3 89 s = splbio();
406c9a0d 90 reassignbuf(bp, bp->b_vp);
9f1a72f3
CS
91 splx(s);
92 }
406c9a0d 93 brelse(bp);
a5219e6e 94 return (0);
8c6ec179 95}
5c5f0f67
KB
96
97/*
98 * XXX
99 * This routine flushes buffers out of the B_LOCKED queue when LFS has too
100 * many locked down. Eventually the pageout daemon will simply call LFS
b9258e30
KB
101 * when pages need to be reclaimed. Note, we have one static count of locked
102 * buffers, so we can't have more than a single file system. To make this
103 * work for multiple file systems, put the count into the mount structure.
5c5f0f67
KB
104 */
105void
106lfs_flush()
107{
108 register struct mount *mp;
5c5f0f67 109
f5e3f593
MS
110#ifdef DOSTATS
111 ++lfs_stats.write_exceeded;
112#endif
edc34597 113 if (lfs_writing)
5c5f0f67 114 return;
edc34597 115 lfs_writing = 1;
b740ac27 116 for (mp = mountlist.tqh_first; mp != NULL; mp = mp->mnt_list.tqe_next) {
edc34597 117 /* The lock check below is to avoid races with unmount. */
5c5f0f67 118 if (mp->mnt_stat.f_type == MOUNT_LFS &&
edc34597
KB
119 (mp->mnt_flag & (MNT_MLOCK|MNT_RDONLY|MNT_UNMOUNT)) == 0 &&
120 !((((struct ufsmount *)mp->mnt_data))->ufsmount_u.lfs)->lfs_dirops ) {
b3cee2e6
KB
121 /*
122 * We set the queue to 0 here because we are about to
123 * write all the dirty buffers we have. If more come
124 * in while we're writing the segment, they may not
125 * get written, so we want the count to reflect these
126 * new writes after the segwrite completes.
127 */
f5e3f593
MS
128#ifdef DOSTATS
129 ++lfs_stats.flush_invoked;
130#endif
5c5f0f67 131 lfs_segwrite(mp, 0);
edc34597 132 }
b740ac27 133 }
edc34597
KB
134 lfs_writing = 0;
135}
136
137int
138lfs_check(vp, blkno)
139 struct vnode *vp;
89e2bb79 140 ufs_daddr_t blkno;
edc34597
KB
141{
142 extern int lfs_allclean_wakeup;
143 int error;
144
1e0be126 145 error = 0;
edc34597
KB
146 if (incore(vp, blkno))
147 return (0);
148 if (locked_queue_count > WRITE_THRESHHOLD)
149 lfs_flush();
1e0be126
MS
150
151 /* If out of buffers, wait on writer */
f5e3f593
MS
152 while (locked_queue_count > WAIT_THRESHHOLD) {
153#ifdef DOSTATS
154 ++lfs_stats.wait_exceeded;
155#endif
1e0be126
MS
156 error = tsleep(&locked_queue_count, PCATCH | PUSER, "buffers",
157 hz * LFS_BUFWAIT);
f5e3f593 158 }
1e0be126 159
edc34597 160 return (error);
5c5f0f67 161}