This source file includes following definitions.
- vn_initialize_syncerd
- vn_syncer_add_to_worklist
- sched_sync
- speedup_syncer
- vfs_allocate_syncvnode
- sync_fsync
- sync_inactive
- sync_print
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43 #include <sys/queue.h>
44 #include <sys/param.h>
45 #include <sys/systm.h>
46 #include <sys/proc.h>
47 #include <sys/mount.h>
48 #include <sys/vnode.h>
49 #include <sys/buf.h>
50 #include <sys/malloc.h>
51
52 #include <sys/kernel.h>
53 #include <sys/sched.h>
54
55 #ifdef FFS_SOFTUPDATES
56 int softdep_process_worklist(struct mount *);
57 #endif
58
59
60
61
62 #define SYNCER_MAXDELAY 32
63 #define SYNCER_DEFAULT 30
64 int syncer_maxdelay = SYNCER_MAXDELAY;
65 time_t syncdelay = SYNCER_DEFAULT;
66
67 int rushjob = 0;
68 int stat_rush_requests = 0;
69
70 static int syncer_delayno = 0;
71 static long syncer_mask;
72 LIST_HEAD(synclist, vnode);
73 static struct synclist *syncer_workitem_pending;
74
75 struct proc *syncerproc;
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103 void
104 vn_initialize_syncerd(void)
105 {
106 syncer_workitem_pending = hashinit(syncer_maxdelay, M_VNODE, M_WAITOK,
107 &syncer_mask);
108 syncer_maxdelay = syncer_mask + 1;
109 }
110
111
112
113
114 void
115 vn_syncer_add_to_worklist(struct vnode *vp, int delay)
116 {
117 int s, slot;
118
119 if (delay > syncer_maxdelay - 2)
120 delay = syncer_maxdelay - 2;
121 slot = (syncer_delayno + delay) & syncer_mask;
122
123 s = splbio();
124 if (vp->v_bioflag & VBIOONSYNCLIST)
125 LIST_REMOVE(vp, v_synclist);
126
127 vp->v_bioflag |= VBIOONSYNCLIST;
128 LIST_INSERT_HEAD(&syncer_workitem_pending[slot], vp, v_synclist);
129 splx(s);
130 }
131
132
133
134
135 void
136 sched_sync(struct proc *p)
137 {
138 struct synclist *slp;
139 struct vnode *vp;
140 long starttime;
141 int s;
142
143 syncerproc = curproc;
144
145 for (;;) {
146 starttime = time_second;
147
148
149
150
151 s = splbio();
152 slp = &syncer_workitem_pending[syncer_delayno];
153
154 syncer_delayno += 1;
155 if (syncer_delayno == syncer_maxdelay)
156 syncer_delayno = 0;
157
158 while ((vp = LIST_FIRST(slp)) != NULL) {
159 if (vget(vp, LK_EXCLUSIVE | LK_NOWAIT, p)) {
160
161
162
163
164
165 vn_syncer_add_to_worklist(vp, 1);
166 continue;
167 }
168 splx(s);
169 (void) VOP_FSYNC(vp, p->p_ucred, MNT_LAZY, p);
170 vput(vp);
171 s = splbio();
172 if (LIST_FIRST(slp) == vp) {
173
174
175
176
177
178
179 #ifdef DIAGNOSTIC
180 if (LIST_FIRST(&vp->v_dirtyblkhd) == NULL &&
181 vp->v_type != VBLK) {
182 vprint("fsync failed", vp);
183 if (vp->v_mount != NULL)
184 printf("mounted on: %s\n",
185 vp->v_mount->mnt_stat.f_mntonname);
186 panic("sched_sync: fsync failed");
187 }
188 #endif
189
190
191
192
193
194
195 vn_syncer_add_to_worklist(vp, syncdelay);
196 }
197 }
198
199 splx(s);
200
201 #ifdef FFS_SOFTUPDATES
202
203
204
205 softdep_process_worklist(NULL);
206 #endif
207
208
209
210
211
212
213
214
215
216
217
218 if (rushjob > 0) {
219 rushjob -= 1;
220 continue;
221 }
222
223
224
225
226
227
228
229
230 if (time_second == starttime)
231 tsleep(&lbolt, PPAUSE, "syncer", 0);
232 }
233 }
234
235
236
237
238
239
240 int
241 speedup_syncer(void)
242 {
243 int s;
244
245 SCHED_LOCK(s);
246 if (syncerproc && syncerproc->p_wchan == &lbolt)
247 setrunnable(syncerproc);
248 SCHED_UNLOCK(s);
249 if (rushjob < syncdelay / 2) {
250 rushjob += 1;
251 stat_rush_requests += 1;
252 return 1;
253 }
254 return 0;
255 }
256
257
258
259
260 #define sync_close nullop
261 int sync_fsync(void *);
262 int sync_inactive(void *);
263 #define sync_reclaim nullop
264 #define sync_lock vop_generic_lock
265 #define sync_unlock vop_generic_unlock
266 int sync_print(void *);
267 #define sync_islocked vop_generic_islocked
268
269 int (**sync_vnodeop_p)(void *);
270 struct vnodeopv_entry_desc sync_vnodeop_entries[] = {
271 { &vop_default_desc, vn_default_error },
272 { &vop_close_desc, sync_close },
273 { &vop_fsync_desc, sync_fsync },
274 { &vop_inactive_desc, sync_inactive },
275 { &vop_reclaim_desc, sync_reclaim },
276 { &vop_lock_desc, sync_lock },
277 { &vop_unlock_desc, sync_unlock },
278 { &vop_print_desc, sync_print },
279 { &vop_islocked_desc, sync_islocked },
280 { (struct vnodeop_desc*)NULL, (int(*)(void *))NULL }
281 };
282 struct vnodeopv_desc sync_vnodeop_opv_desc = {
283 &sync_vnodeop_p, sync_vnodeop_entries
284 };
285
286
287
288
289 int
290 vfs_allocate_syncvnode(struct mount *mp)
291 {
292 struct vnode *vp;
293 static long start, incr, next;
294 int error;
295
296
297 if ((error = getnewvnode(VT_VFS, mp, sync_vnodeop_p, &vp)) != 0) {
298 mp->mnt_syncer = NULL;
299 return (error);
300 }
301 vp->v_writecount = 1;
302 vp->v_type = VNON;
303
304
305
306
307
308
309 next += incr;
310 if (next == 0 || next > syncer_maxdelay) {
311 start /= 2;
312 incr /= 2;
313 if (start == 0) {
314 start = syncer_maxdelay / 2;
315 incr = syncer_maxdelay;
316 }
317 next = start;
318 }
319 vn_syncer_add_to_worklist(vp, next);
320 mp->mnt_syncer = vp;
321 return (0);
322 }
323
324
325
326
327 int
328 sync_fsync(void *v)
329 {
330 struct vop_fsync_args *ap = v;
331 struct vnode *syncvp = ap->a_vp;
332 struct mount *mp = syncvp->v_mount;
333 int asyncflag;
334
335
336
337
338 if (ap->a_waitfor != MNT_LAZY)
339 return (0);
340
341
342
343
344 vn_syncer_add_to_worklist(syncvp, syncdelay);
345
346
347
348
349
350 if (vfs_busy(mp, VB_READ|VB_NOWAIT) == 0) {
351 asyncflag = mp->mnt_flag & MNT_ASYNC;
352 mp->mnt_flag &= ~MNT_ASYNC;
353 VFS_SYNC(mp, MNT_LAZY, ap->a_cred, ap->a_p);
354 if (asyncflag)
355 mp->mnt_flag |= MNT_ASYNC;
356 vfs_unbusy(mp);
357 }
358
359 return (0);
360 }
361
362
363
364
365 int
366 sync_inactive(void *v)
367 {
368 struct vop_inactive_args *ap = v;
369
370 struct vnode *vp = ap->a_vp;
371 int s;
372
373 if (vp->v_usecount == 0) {
374 VOP_UNLOCK(vp, 0, ap->a_p);
375 return (0);
376 }
377
378 vp->v_mount->mnt_syncer = NULL;
379
380 s = splbio();
381
382 LIST_REMOVE(vp, v_synclist);
383 vp->v_bioflag &= ~VBIOONSYNCLIST;
384
385 splx(s);
386
387 vp->v_writecount = 0;
388 vput(vp);
389
390 return (0);
391 }
392
393
394
395
396 int
397 sync_print(void *v)
398 {
399 printf("syncer vnode\n");
400
401 return (0);
402 }