File: | ufs/ffs/ffs_vnops.c |
Warning: | line 200, column 2 Value stored to 'mode' is never read |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* $OpenBSD: ffs_vnops.c,v 1.99 2021/10/02 08:51:41 semarie Exp $ */ |
2 | /* $NetBSD: ffs_vnops.c,v 1.7 1996/05/11 18:27:24 mycroft Exp $ */ |
3 | |
4 | /* |
5 | * Copyright (c) 1982, 1986, 1989, 1993 |
6 | * The Regents of the University of California. All rights reserved. |
7 | * |
8 | * Redistribution and use in source and binary forms, with or without |
9 | * modification, are permitted provided that the following conditions |
10 | * are met: |
11 | * 1. Redistributions of source code must retain the above copyright |
12 | * notice, this list of conditions and the following disclaimer. |
13 | * 2. Redistributions in binary form must reproduce the above copyright |
14 | * notice, this list of conditions and the following disclaimer in the |
15 | * documentation and/or other materials provided with the distribution. |
16 | * 3. Neither the name of the University nor the names of its contributors |
17 | * may be used to endorse or promote products derived from this software |
18 | * without specific prior written permission. |
19 | * |
20 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND |
21 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
22 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
23 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE |
24 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
25 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
26 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
27 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
28 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
29 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
30 | * SUCH DAMAGE. |
31 | * |
32 | * @(#)ffs_vnops.c 8.10 (Berkeley) 8/10/94 |
33 | */ |
34 | |
35 | #include <sys/param.h> |
36 | #include <sys/systm.h> |
37 | #include <sys/resourcevar.h> |
38 | #include <sys/kernel.h> |
39 | #include <sys/stat.h> |
40 | #include <sys/buf.h> |
41 | #include <sys/mount.h> |
42 | #include <sys/vnode.h> |
43 | #include <sys/malloc.h> |
44 | #include <sys/signalvar.h> |
45 | #include <sys/pool.h> |
46 | #include <sys/event.h> |
47 | #include <sys/specdev.h> |
48 | |
49 | #include <miscfs/fifofs/fifo.h> |
50 | |
51 | #include <ufs/ufs/quota.h> |
52 | #include <ufs/ufs/inode.h> |
53 | #include <ufs/ufs/dir.h> |
54 | #include <ufs/ufs/ufs_extern.h> |
55 | #include <ufs/ufs/ufsmount.h> |
56 | |
57 | #include <ufs/ffs/fs.h> |
58 | #include <ufs/ffs/ffs_extern.h> |
59 | |
60 | const struct vops ffs_vops = { |
61 | .vop_lookup = ufs_lookup, |
62 | .vop_create = ufs_create, |
63 | .vop_mknod = ufs_mknod, |
64 | .vop_open = ufs_open, |
65 | .vop_close = ufs_close, |
66 | .vop_access = ufs_access, |
67 | .vop_getattr = ufs_getattr, |
68 | .vop_setattr = ufs_setattr, |
69 | .vop_read = ffs_read, |
70 | .vop_write = ffs_write, |
71 | .vop_ioctl = ufs_ioctl, |
72 | .vop_poll = ufs_poll, |
73 | .vop_kqfilter = ufs_kqfilter, |
74 | .vop_revoke = vop_generic_revoke, |
75 | .vop_fsync = ffs_fsync, |
76 | .vop_remove = ufs_remove, |
77 | .vop_link = ufs_link, |
78 | .vop_rename = ufs_rename, |
79 | .vop_mkdir = ufs_mkdir, |
80 | .vop_rmdir = ufs_rmdir, |
81 | .vop_symlink = ufs_symlink, |
82 | .vop_readdir = ufs_readdir, |
83 | .vop_readlink = ufs_readlink, |
84 | .vop_abortop = vop_generic_abortop, |
85 | .vop_inactive = ufs_inactive, |
86 | .vop_reclaim = ffs_reclaim, |
87 | .vop_lock = ufs_lock, |
88 | .vop_unlock = ufs_unlock, |
89 | .vop_bmap = ufs_bmap, |
90 | .vop_strategy = ufs_strategy, |
91 | .vop_print = ufs_print, |
92 | .vop_islocked = ufs_islocked, |
93 | .vop_pathconf = ufs_pathconf, |
94 | .vop_advlock = ufs_advlock, |
95 | .vop_bwrite = vop_generic_bwrite |
96 | }; |
97 | |
98 | const struct vops ffs_specvops = { |
99 | .vop_close = ufsspec_close, |
100 | .vop_access = ufs_access, |
101 | .vop_getattr = ufs_getattr, |
102 | .vop_setattr = ufs_setattr, |
103 | .vop_read = ufsspec_read, |
104 | .vop_write = ufsspec_write, |
105 | .vop_fsync = ffs_fsync, |
106 | .vop_inactive = ufs_inactive, |
107 | .vop_reclaim = ffs_reclaim, |
108 | .vop_lock = ufs_lock, |
109 | .vop_unlock = ufs_unlock, |
110 | .vop_print = ufs_print, |
111 | .vop_islocked = ufs_islocked, |
112 | |
113 | /* XXX: Keep in sync with spec_vops */ |
114 | .vop_lookup = vop_generic_lookup, |
115 | .vop_create = vop_generic_badop, |
116 | .vop_mknod = vop_generic_badop, |
117 | .vop_open = spec_open, |
118 | .vop_ioctl = spec_ioctl, |
119 | .vop_poll = spec_poll, |
120 | .vop_kqfilter = spec_kqfilter, |
121 | .vop_revoke = vop_generic_revoke, |
122 | .vop_remove = vop_generic_badop, |
123 | .vop_link = vop_generic_badop, |
124 | .vop_rename = vop_generic_badop, |
125 | .vop_mkdir = vop_generic_badop, |
126 | .vop_rmdir = vop_generic_badop, |
127 | .vop_symlink = vop_generic_badop, |
128 | .vop_readdir = vop_generic_badop, |
129 | .vop_readlink = vop_generic_badop, |
130 | .vop_abortop = vop_generic_badop, |
131 | .vop_bmap = vop_generic_bmap, |
132 | .vop_strategy = spec_strategy, |
133 | .vop_pathconf = spec_pathconf, |
134 | .vop_advlock = spec_advlock, |
135 | .vop_bwrite = vop_generic_bwrite, |
136 | }; |
137 | |
138 | #ifdef FIFO1 |
139 | const struct vops ffs_fifovops = { |
140 | .vop_close = ufsfifo_close, |
141 | .vop_access = ufs_access, |
142 | .vop_getattr = ufs_getattr, |
143 | .vop_setattr = ufs_setattr, |
144 | .vop_read = ufsfifo_read, |
145 | .vop_write = ufsfifo_write, |
146 | .vop_fsync = ffs_fsync, |
147 | .vop_inactive = ufs_inactive, |
148 | .vop_reclaim = ffsfifo_reclaim, |
149 | .vop_lock = ufs_lock, |
150 | .vop_unlock = ufs_unlock, |
151 | .vop_print = ufs_print, |
152 | .vop_islocked = ufs_islocked, |
153 | .vop_bwrite = vop_generic_bwrite, |
154 | |
155 | /* XXX: Keep in sync with fifo_vops */ |
156 | .vop_lookup = vop_generic_lookup, |
157 | .vop_create = vop_generic_badop, |
158 | .vop_mknod = vop_generic_badop, |
159 | .vop_open = fifo_open, |
160 | .vop_ioctl = fifo_ioctl, |
161 | .vop_poll = fifo_poll, |
162 | .vop_kqfilter = fifo_kqfilter, |
163 | .vop_revoke = vop_generic_revoke, |
164 | .vop_remove = vop_generic_badop, |
165 | .vop_link = vop_generic_badop, |
166 | .vop_rename = vop_generic_badop, |
167 | .vop_mkdir = vop_generic_badop, |
168 | .vop_rmdir = vop_generic_badop, |
169 | .vop_symlink = vop_generic_badop, |
170 | .vop_readdir = vop_generic_badop, |
171 | .vop_readlink = vop_generic_badop, |
172 | .vop_abortop = vop_generic_badop, |
173 | .vop_bmap = vop_generic_bmap, |
174 | .vop_strategy = vop_generic_badop, |
175 | .vop_pathconf = fifo_pathconf, |
176 | .vop_advlock = fifo_advlock |
177 | }; |
178 | #endif /* FIFO */ |
179 | |
180 | /* |
181 | * Vnode op for reading. |
182 | */ |
183 | int |
184 | ffs_read(void *v) |
185 | { |
186 | struct vop_read_args *ap = v; |
187 | struct vnode *vp; |
188 | struct inode *ip; |
189 | struct uio *uio; |
190 | struct fs *fs; |
191 | struct buf *bp; |
192 | daddr_t lbn, nextlbn; |
193 | off_t bytesinfile; |
194 | int size, xfersize, blkoffset; |
195 | mode_t mode; |
196 | int error; |
197 | |
198 | vp = ap->a_vp; |
199 | ip = VTOI(vp)((struct inode *)(vp)->v_data); |
200 | mode = DIP(ip, mode)(((ip)->i_ump->um_fstype == 1) ? (ip)->dinode_u.ffs1_din ->di_mode : (ip)->dinode_u.ffs2_din->di_mode); |
Value stored to 'mode' is never read | |
201 | uio = ap->a_uio; |
202 | |
203 | #ifdef DIAGNOSTIC1 |
204 | if (uio->uio_rw != UIO_READ) |
205 | panic("ffs_read: mode"); |
206 | |
207 | if (vp->v_type == VLNK) { |
208 | if (DIP(ip, size)(((ip)->i_ump->um_fstype == 1) ? (ip)->dinode_u.ffs1_din ->di_size : (ip)->dinode_u.ffs2_din->di_size) < ip->i_ump->um_maxsymlinklen || |
209 | (ip->i_ump->um_maxsymlinklen == 0 && DIP(ip, blocks)(((ip)->i_ump->um_fstype == 1) ? (ip)->dinode_u.ffs1_din ->di_blocks : (ip)->dinode_u.ffs2_din->di_blocks) == 0)) |
210 | panic("ffs_read: short symlink"); |
211 | } else if (vp->v_type != VREG && vp->v_type != VDIR) |
212 | panic("ffs_read: type %d", vp->v_type); |
213 | #endif |
214 | fs = ip->i_fsinode_u.fs; |
215 | if (uio->uio_offset < 0) |
216 | return (EINVAL22); |
217 | if (uio->uio_resid == 0) |
218 | return (0); |
219 | |
220 | for (error = 0, bp = NULL((void *)0); uio->uio_resid > 0; bp = NULL((void *)0)) { |
221 | if ((bytesinfile = DIP(ip, size)(((ip)->i_ump->um_fstype == 1) ? (ip)->dinode_u.ffs1_din ->di_size : (ip)->dinode_u.ffs2_din->di_size) - uio->uio_offset) <= 0) |
222 | break; |
223 | lbn = lblkno(fs, uio->uio_offset)((uio->uio_offset) >> (fs)->fs_bshift); |
224 | nextlbn = lbn + 1; |
225 | size = fs->fs_bsize; /* WAS blksize(fs, ip, lbn); */ |
226 | blkoffset = blkoff(fs, uio->uio_offset)((uio->uio_offset) & (fs)->fs_qbmask); |
227 | xfersize = fs->fs_bsize - blkoffset; |
228 | if (uio->uio_resid < xfersize) |
229 | xfersize = uio->uio_resid; |
230 | if (bytesinfile < xfersize) |
231 | xfersize = bytesinfile; |
232 | |
233 | if (lblktosize(fs, nextlbn)((off_t)(nextlbn) << (fs)->fs_bshift) >= DIP(ip, size)(((ip)->i_ump->um_fstype == 1) ? (ip)->dinode_u.ffs1_din ->di_size : (ip)->dinode_u.ffs2_din->di_size)) |
234 | error = bread(vp, lbn, size, &bp); |
235 | else if (lbn - 1 == ip->i_ci.ci_lastr || |
236 | uio->uio_resid > xfersize) { |
237 | error = bread_cluster(vp, lbn, size, &bp); |
238 | } else |
239 | error = bread(vp, lbn, size, &bp); |
240 | |
241 | if (error) |
242 | break; |
243 | ip->i_ci.ci_lastr = lbn; |
244 | |
245 | /* |
246 | * We should only get non-zero b_resid when an I/O error |
247 | * has occurred, which should cause us to break above. |
248 | * However, if the short read did not cause an error, |
249 | * then we want to ensure that we do not uiomove bad |
250 | * or uninitialized data. |
251 | */ |
252 | size -= bp->b_resid; |
253 | if (size < xfersize) { |
254 | if (size == 0) |
255 | break; |
256 | xfersize = size; |
257 | } |
258 | error = uiomove(bp->b_data + blkoffset, xfersize, uio); |
259 | if (error) |
260 | break; |
261 | brelse(bp); |
262 | } |
263 | if (bp != NULL((void *)0)) |
264 | brelse(bp); |
265 | if (!(vp->v_mount->mnt_flag & MNT_NOATIME0x00008000) || |
266 | (ip->i_flag & (IN_CHANGE0x0002 | IN_UPDATE0x0004))) { |
267 | ip->i_flag |= IN_ACCESS0x0001; |
268 | } |
269 | return (error); |
270 | } |
271 | |
272 | /* |
273 | * Vnode op for writing. |
274 | */ |
275 | int |
276 | ffs_write(void *v) |
277 | { |
278 | struct vop_write_args *ap = v; |
279 | struct vnode *vp; |
280 | struct uio *uio; |
281 | struct inode *ip; |
282 | struct fs *fs; |
283 | struct buf *bp; |
284 | daddr_t lbn; |
285 | off_t osize; |
286 | int blkoffset, error, extended, flags, ioflag, size, xfersize; |
287 | size_t resid; |
288 | ssize_t overrun; |
289 | |
290 | extended = 0; |
291 | ioflag = ap->a_ioflag; |
292 | uio = ap->a_uio; |
293 | vp = ap->a_vp; |
294 | ip = VTOI(vp)((struct inode *)(vp)->v_data); |
295 | |
296 | #ifdef DIAGNOSTIC1 |
297 | if (uio->uio_rw != UIO_WRITE) |
298 | panic("ffs_write: mode"); |
299 | #endif |
300 | |
301 | /* |
302 | * If writing 0 bytes, succeed and do not change |
303 | * update time or file offset (standards compliance) |
304 | */ |
305 | if (uio->uio_resid == 0) |
306 | return (0); |
307 | |
308 | switch (vp->v_type) { |
309 | case VREG: |
310 | if (ioflag & IO_APPEND0x02) |
311 | uio->uio_offset = DIP(ip, size)(((ip)->i_ump->um_fstype == 1) ? (ip)->dinode_u.ffs1_din ->di_size : (ip)->dinode_u.ffs2_din->di_size); |
312 | if ((DIP(ip, flags)(((ip)->i_ump->um_fstype == 1) ? (ip)->dinode_u.ffs1_din ->di_flags : (ip)->dinode_u.ffs2_din->di_flags) & APPEND(0x00000004 | 0x00040000)) && uio->uio_offset != DIP(ip, size)(((ip)->i_ump->um_fstype == 1) ? (ip)->dinode_u.ffs1_din ->di_size : (ip)->dinode_u.ffs2_din->di_size)) |
313 | return (EPERM1); |
314 | /* FALLTHROUGH */ |
315 | case VLNK: |
316 | break; |
317 | case VDIR: |
318 | if ((ioflag & IO_SYNC0x04) == 0) |
319 | panic("ffs_write: nonsync dir write"); |
320 | break; |
321 | default: |
322 | panic("ffs_write: type %d", vp->v_type); |
323 | } |
324 | |
325 | fs = ip->i_fsinode_u.fs; |
326 | if (uio->uio_offset < 0 || |
327 | (u_int64_t)uio->uio_offset + uio->uio_resid > fs->fs_maxfilesize) |
328 | return (EFBIG27); |
329 | |
330 | /* do the filesize rlimit check */ |
331 | if ((error = vn_fsizechk(vp, uio, ioflag, &overrun))) |
332 | return (error); |
333 | |
334 | resid = uio->uio_resid; |
335 | osize = DIP(ip, size)(((ip)->i_ump->um_fstype == 1) ? (ip)->dinode_u.ffs1_din ->di_size : (ip)->dinode_u.ffs2_din->di_size); |
336 | flags = ioflag & IO_SYNC0x04 ? B_SYNC0x02 : 0; |
337 | |
338 | for (error = 0; uio->uio_resid > 0;) { |
339 | lbn = lblkno(fs, uio->uio_offset)((uio->uio_offset) >> (fs)->fs_bshift); |
340 | blkoffset = blkoff(fs, uio->uio_offset)((uio->uio_offset) & (fs)->fs_qbmask); |
341 | xfersize = fs->fs_bsize - blkoffset; |
342 | if (uio->uio_resid < xfersize) |
343 | xfersize = uio->uio_resid; |
344 | if (fs->fs_bsize > xfersize) |
345 | flags |= B_CLRBUF0x01; |
346 | else |
347 | flags &= ~B_CLRBUF0x01; |
348 | |
349 | if ((error = UFS_BUF_ALLOC(ip, uio->uio_offset, xfersize,((ip)->i_vtbl->iv_buf_alloc)((ip), (uio->uio_offset) , (xfersize), (ap->a_cred), (flags), (&bp)) |
350 | ap->a_cred, flags, &bp)((ip)->i_vtbl->iv_buf_alloc)((ip), (uio->uio_offset) , (xfersize), (ap->a_cred), (flags), (&bp))) != 0) |
351 | break; |
352 | if (uio->uio_offset + xfersize > DIP(ip, size)(((ip)->i_ump->um_fstype == 1) ? (ip)->dinode_u.ffs1_din ->di_size : (ip)->dinode_u.ffs2_din->di_size)) { |
353 | DIP_ASSIGN(ip, size, uio->uio_offset + xfersize)do { if ((ip)->i_ump->um_fstype == 1) (ip)->dinode_u .ffs1_din->di_size = (uio->uio_offset + xfersize); else (ip)->dinode_u.ffs2_din->di_size = (uio->uio_offset + xfersize); } while (0); |
354 | uvm_vnp_setsize(vp, DIP(ip, size)(((ip)->i_ump->um_fstype == 1) ? (ip)->dinode_u.ffs1_din ->di_size : (ip)->dinode_u.ffs2_din->di_size)); |
355 | extended = 1; |
356 | } |
357 | (void)uvm_vnp_uncache(vp); |
358 | |
359 | size = blksize(fs, ip, lbn)(((lbn) >= 12 || ((((ip))->i_ump->um_fstype == 1) ? ( (ip))->dinode_u.ffs1_din->di_size : ((ip))->dinode_u .ffs2_din->di_size) >= ((lbn) + 1) << (fs)->fs_bshift ) ? (u_int64_t)(fs)->fs_bsize : ((((((((((ip))->i_ump-> um_fstype == 1) ? ((ip))->dinode_u.ffs1_din->di_size : ( (ip))->dinode_u.ffs2_din->di_size)) & (fs)->fs_qbmask )) + (fs)->fs_qfmask) & (fs)->fs_fmask))) - bp->b_resid; |
360 | if (size < xfersize) |
361 | xfersize = size; |
362 | |
363 | error = uiomove(bp->b_data + blkoffset, xfersize, uio); |
364 | /* |
365 | * If the buffer is not already filled and we encounter an |
366 | * error while trying to fill it, we have to clear out any |
367 | * garbage data from the pages instantiated for the buffer. |
368 | * If we do not, a failed uiomove() during a write can leave |
369 | * the prior contents of the pages exposed to a userland mmap. |
370 | * |
371 | * Note that we don't need to clear buffers that were |
372 | * allocated with the B_CLRBUF flag set. |
373 | */ |
374 | if (error != 0 && !(flags & B_CLRBUF0x01)) |
375 | memset(bp->b_data + blkoffset, 0, xfersize)__builtin_memset((bp->b_data + blkoffset), (0), (xfersize) ); |
376 | |
377 | if (ioflag & IO_NOCACHE0x40) |
378 | bp->b_flags |= B_NOCACHE0x00001000; |
379 | |
380 | if (ioflag & IO_SYNC0x04) |
381 | (void)bwrite(bp); |
382 | else if (xfersize + blkoffset == fs->fs_bsize) { |
383 | bawrite(bp); |
384 | } else |
385 | bdwrite(bp); |
386 | |
387 | if (error || xfersize == 0) |
388 | break; |
389 | ip->i_flag |= IN_CHANGE0x0002 | IN_UPDATE0x0004; |
390 | } |
391 | /* |
392 | * If we successfully wrote any data, and we are not the superuser |
393 | * we clear the setuid and setgid bits as a precaution against |
394 | * tampering. |
395 | */ |
396 | if (resid > uio->uio_resid && ap->a_cred && ap->a_cred->cr_uid != 0 && |
397 | !vnoperm(vp)) |
398 | DIP_ASSIGN(ip, mode, DIP(ip, mode) & ~(ISUID | ISGID))do { if ((ip)->i_ump->um_fstype == 1) (ip)->dinode_u .ffs1_din->di_mode = ((((ip)->i_ump->um_fstype == 1) ? (ip)->dinode_u.ffs1_din->di_mode : (ip)->dinode_u .ffs2_din->di_mode) & ~(0004000 | 0002000)); else (ip) ->dinode_u.ffs2_din->di_mode = ((((ip)->i_ump->um_fstype == 1) ? (ip)->dinode_u.ffs1_din->di_mode : (ip)->dinode_u .ffs2_din->di_mode) & ~(0004000 | 0002000)); } while ( 0); |
399 | if (resid > uio->uio_resid) |
400 | VN_KNOTE(vp, NOTE_WRITE | (extended ? NOTE_EXTEND : 0))do { struct klist *__list = (&vp->v_selectinfo.si_note ); if (__list != ((void *)0)) knote(__list, (0x0002 | (extended ? 0x0004 : 0))); } while (0); |
401 | if (error) { |
402 | if (ioflag & IO_UNIT0x01) { |
403 | (void)UFS_TRUNCATE(ip, osize,((ip)->i_vtbl->iv_truncate)((ip), (osize), (ioflag & 0x04), (ap->a_cred)) |
404 | ioflag & IO_SYNC, ap->a_cred)((ip)->i_vtbl->iv_truncate)((ip), (osize), (ioflag & 0x04), (ap->a_cred)); |
405 | uio->uio_offset -= resid - uio->uio_resid; |
406 | uio->uio_resid = resid; |
407 | } |
408 | } else if (resid > uio->uio_resid && (ioflag & IO_SYNC0x04)) { |
409 | error = UFS_UPDATE(ip, 1)((ip)->i_vtbl->iv_update)((ip), (1)); |
410 | } |
411 | /* correct the result for writes clamped by vn_fsizechk() */ |
412 | uio->uio_resid += overrun; |
413 | return (error); |
414 | } |
415 | |
416 | /* |
417 | * Synch an open file. |
418 | */ |
419 | int |
420 | ffs_fsync(void *v) |
421 | { |
422 | struct vop_fsync_args *ap = v; |
423 | struct vnode *vp = ap->a_vp; |
424 | struct buf *bp, *nbp; |
425 | int s, error, passes, skipmeta; |
426 | |
427 | if (vp->v_type == VBLK && |
428 | vp->v_specmountpointv_un.vu_specinfo->si_mountpoint != NULL((void *)0) && |
429 | (vp->v_specmountpointv_un.vu_specinfo->si_mountpoint->mnt_flag & MNT_SOFTDEP0x04000000)) |
430 | softdep_fsync_mountdev(vp, ap->a_waitfor); |
431 | |
432 | /* |
433 | * Flush all dirty buffers associated with a vnode. |
434 | */ |
435 | passes = NIADDR3 + 1; |
436 | skipmeta = 0; |
437 | if (ap->a_waitfor == MNT_WAIT1) |
438 | skipmeta = 1; |
439 | s = splbio()splraise(0x6); |
440 | loop: |
441 | LIST_FOREACH(bp, &vp->v_dirtyblkhd, b_vnbufs)for((bp) = ((&vp->v_dirtyblkhd)->lh_first); (bp)!= ( (void *)0); (bp) = ((bp)->b_vnbufs.le_next)) { |
442 | bp->b_flags &= ~B_SCANNED0x00100000; |
443 | } |
444 | LIST_FOREACH_SAFE(bp, &vp->v_dirtyblkhd, b_vnbufs, nbp)for ((bp) = ((&vp->v_dirtyblkhd)->lh_first); (bp) && ((nbp) = ((bp)->b_vnbufs.le_next), 1); (bp) = (nbp)) { |
445 | /* |
446 | * Reasons to skip this buffer: it has already been considered |
447 | * on this pass, this pass is the first time through on a |
448 | * synchronous flush request and the buffer being considered |
449 | * is metadata, the buffer has dependencies that will cause |
450 | * it to be redirtied and it has not already been deferred, |
451 | * or it is already being written. |
452 | */ |
453 | if (bp->b_flags & (B_BUSY0x00000010 | B_SCANNED0x00100000)) |
454 | continue; |
455 | if ((bp->b_flags & B_DELWRI0x00000080) == 0) |
456 | panic("ffs_fsync: not dirty"); |
457 | if (skipmeta && bp->b_lblkno < 0) |
458 | continue; |
459 | if (ap->a_waitfor != MNT_WAIT1 && |
460 | LIST_FIRST(&bp->b_dep)((&bp->b_dep)->lh_first) != NULL((void *)0) && |
461 | (bp->b_flags & B_DEFERRED0x00080000) == 0 && |
462 | buf_countdeps(bp, 0, 1)) { |
463 | bp->b_flags |= B_DEFERRED0x00080000; |
464 | continue; |
465 | } |
466 | |
467 | bremfreebufcache_take(bp); |
468 | buf_acquire(bp); |
469 | bp->b_flags |= B_SCANNED0x00100000; |
470 | splx(s)spllower(s); |
471 | /* |
472 | * On our final pass through, do all I/O synchronously |
473 | * so that we can find out if our flush is failing |
474 | * because of write errors. |
475 | */ |
476 | if (passes > 0 || ap->a_waitfor != MNT_WAIT1) |
477 | (void) bawrite(bp); |
478 | else if ((error = bwrite(bp)) != 0) |
479 | return (error); |
480 | s = splbio()splraise(0x6); |
481 | /* |
482 | * Since we may have slept during the I/O, we need |
483 | * to start from a known point. |
484 | */ |
485 | nbp = LIST_FIRST(&vp->v_dirtyblkhd)((&vp->v_dirtyblkhd)->lh_first); |
486 | } |
487 | if (skipmeta) { |
488 | skipmeta = 0; |
489 | goto loop; |
490 | } |
491 | if (ap->a_waitfor == MNT_WAIT1) { |
492 | vwaitforio(vp, 0, "ffs_fsync", INFSLP0xffffffffffffffffULL); |
493 | |
494 | /* |
495 | * Ensure that any filesystem metadata associated |
496 | * with the vnode has been written. |
497 | */ |
498 | splx(s)spllower(s); |
499 | if ((error = softdep_sync_metadata(ap)) != 0) |
500 | return (error); |
501 | s = splbio()splraise(0x6); |
502 | if (!LIST_EMPTY(&vp->v_dirtyblkhd)(((&vp->v_dirtyblkhd)->lh_first) == ((void *)0))) { |
503 | /* |
504 | * Block devices associated with filesystems may |
505 | * have new I/O requests posted for them even if |
506 | * the vnode is locked, so no amount of trying will |
507 | * get them clean. Thus we give block devices a |
508 | * good effort, then just give up. For all other file |
509 | * types, go around and try again until it is clean. |
510 | */ |
511 | if (passes > 0) { |
512 | passes -= 1; |
513 | goto loop; |
514 | } |
515 | #ifdef DIAGNOSTIC1 |
516 | if (vp->v_type != VBLK) |
517 | vprint("ffs_fsync: dirty", vp); |
518 | #endif |
519 | } |
520 | } |
521 | splx(s)spllower(s); |
522 | return (UFS_UPDATE(VTOI(vp), ap->a_waitfor == MNT_WAIT)((((struct inode *)(vp)->v_data))->i_vtbl->iv_update )((((struct inode *)(vp)->v_data)), (ap->a_waitfor == 1 ))); |
523 | } |
524 | |
525 | /* |
526 | * Reclaim an inode so that it can be used for other purposes. |
527 | */ |
528 | int |
529 | ffs_reclaim(void *v) |
530 | { |
531 | struct vop_reclaim_args *ap = v; |
532 | struct vnode *vp = ap->a_vp; |
533 | struct inode *ip = VTOI(vp)((struct inode *)(vp)->v_data); |
534 | int error; |
535 | |
536 | if ((error = ufs_reclaim(vp)) != 0) |
537 | return (error); |
538 | |
539 | if (ip->i_din1dinode_u.ffs1_din != NULL((void *)0)) { |
540 | #ifdef FFS21 |
541 | if (ip->i_ump->um_fstype == UM_UFS22) |
542 | pool_put(&ffs_dinode2_pool, ip->i_din2dinode_u.ffs2_din); |
543 | else |
544 | #endif |
545 | pool_put(&ffs_dinode1_pool, ip->i_din1dinode_u.ffs1_din); |
546 | } |
547 | |
548 | pool_put(&ffs_ino_pool, ip); |
549 | |
550 | vp->v_data = NULL((void *)0); |
551 | |
552 | return (0); |
553 | } |
554 | |
555 | #ifdef FIFO1 |
556 | int |
557 | ffsfifo_reclaim(void *v) |
558 | { |
559 | fifo_reclaim(v); |
560 | return (ffs_reclaim(v)); |
561 | } |
562 | #endif |