lfs_syscalls.c revision 1.77 1 /* $NetBSD: lfs_syscalls.c,v 1.77 2002/12/26 13:04:39 yamt Exp $ */
2
3 /*-
4 * Copyright (c) 1999, 2000 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Konrad E. Schroder <perseant (at) hhhh.org>.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. All advertising materials mentioning features or use of this software
19 * must display the following acknowledgement:
20 * This product includes software developed by the NetBSD
21 * Foundation, Inc. and its contributors.
22 * 4. Neither the name of The NetBSD Foundation nor the names of its
23 * contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36 * POSSIBILITY OF SUCH DAMAGE.
37 */
38 /*-
39 * Copyright (c) 1991, 1993, 1994
40 * The Regents of the University of California. All rights reserved.
41 *
42 * Redistribution and use in source and binary forms, with or without
43 * modification, are permitted provided that the following conditions
44 * are met:
45 * 1. Redistributions of source code must retain the above copyright
46 * notice, this list of conditions and the following disclaimer.
47 * 2. Redistributions in binary form must reproduce the above copyright
48 * notice, this list of conditions and the following disclaimer in the
49 * documentation and/or other materials provided with the distribution.
50 * 3. All advertising materials mentioning features or use of this software
51 * must display the following acknowledgement:
52 * This product includes software developed by the University of
53 * California, Berkeley and its contributors.
54 * 4. Neither the name of the University nor the names of its contributors
55 * may be used to endorse or promote products derived from this software
56 * without specific prior written permission.
57 *
58 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
59 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
60 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
61 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
62 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
63 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
64 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
65 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
66 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
67 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
68 * SUCH DAMAGE.
69 *
70 * @(#)lfs_syscalls.c 8.10 (Berkeley) 5/14/95
71 */
72
73 #include <sys/cdefs.h>
74 __KERNEL_RCSID(0, "$NetBSD: lfs_syscalls.c,v 1.77 2002/12/26 13:04:39 yamt Exp $");
75
76 #define LFS /* for prototypes in syscallargs.h */
77
78 #include <sys/param.h>
79 #include <sys/systm.h>
80 #include <sys/proc.h>
81 #include <sys/buf.h>
82 #include <sys/mount.h>
83 #include <sys/vnode.h>
84 #include <sys/malloc.h>
85 #include <sys/kernel.h>
86
87 #include <sys/syscallargs.h>
88
89 #include <ufs/ufs/inode.h>
90 #include <ufs/ufs/ufsmount.h>
91 #include <ufs/ufs/ufs_extern.h>
92
93 #include <ufs/lfs/lfs.h>
94 #include <ufs/lfs/lfs_extern.h>
95
96 /* Max block count for lfs_markv() */
97 #define MARKV_MAXBLKCNT 65536
98
99 struct buf *lfs_fakebuf(struct lfs *, struct vnode *, int, size_t, caddr_t);
100 int lfs_fasthashget(dev_t, ino_t, struct vnode **);
101
102 int debug_cleaner = 0;
103 int clean_vnlocked = 0;
104 int clean_inlocked = 0;
105 int verbose_debug = 0;
106
107 pid_t lfs_cleaner_pid = 0;
108
109 /*
110 * Definitions for the buffer free lists.
111 */
112 #define BQUEUES 4 /* number of free buffer queues */
113
114 #define BQ_LOCKED 0 /* super-blocks &c */
115 #define BQ_LRU 1 /* lru, useful buffers */
116 #define BQ_AGE 2 /* rubbish */
117 #define BQ_EMPTY 3 /* buffer headers with no memory */
118
119 extern TAILQ_HEAD(bqueues, buf) bufqueues[BQUEUES];
120
121 #define LFS_FORCE_WRITE UNASSIGNED
122
123 #define LFS_VREF_THRESHOLD 128
124
125 static int lfs_bmapv(struct proc *, fsid_t *, BLOCK_INFO *, int);
126 static int lfs_markv(struct proc *, fsid_t *, BLOCK_INFO *, int);
127 static void lfs_fakebuf_iodone(struct buf *);
128
129 /*
130 * sys_lfs_markv:
131 *
132 * This will mark inodes and blocks dirty, so they are written into the log.
133 * It will block until all the blocks have been written. The segment create
134 * time passed in the block_info and inode_info structures is used to decide
135 * if the data is valid for each block (in case some process dirtied a block
136 * or inode that is being cleaned between the determination that a block is
137 * live and the lfs_markv call).
138 *
139 * 0 on success
140 * -1/errno is return on error.
141 */
142 #ifdef USE_64BIT_SYSCALLS
143 int
144 sys_lfs_markv(struct proc *p, void *v, register_t *retval)
145 {
146 struct sys_lfs_markv_args /* {
147 syscallarg(fsid_t *) fsidp;
148 syscallarg(struct block_info *) blkiov;
149 syscallarg(int) blkcnt;
150 } */ *uap = v;
151 BLOCK_INFO *blkiov;
152 int blkcnt, error;
153 fsid_t fsid;
154
155 if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
156 return (error);
157
158 if ((error = copyin(SCARG(uap, fsidp), &fsid, sizeof(fsid_t))) != 0)
159 return (error);
160
161 blkcnt = SCARG(uap, blkcnt);
162 if ((u_int) blkcnt > MARKV_MAXBLKCNT)
163 return (EINVAL);
164
165 blkiov = malloc(blkcnt * sizeof(BLOCK_INFO), M_SEGMENT, M_WAITOK);
166 if ((error = copyin(SCARG(uap, blkiov), blkiov,
167 blkcnt * sizeof(BLOCK_INFO))) != 0)
168 goto out;
169
170 if ((error = lfs_markv(p, &fsid, blkiov, blkcnt)) == 0)
171 copyout(blkiov, SCARG(uap, blkiov),
172 blkcnt * sizeof(BLOCK_INFO));
173 out:
174 free(blkiov, M_SEGMENT);
175 return error;
176 }
177 #else
178 int
179 sys_lfs_markv(struct proc *p, void *v, register_t *retval)
180 {
181 struct sys_lfs_markv_args /* {
182 syscallarg(fsid_t *) fsidp;
183 syscallarg(struct block_info *) blkiov;
184 syscallarg(int) blkcnt;
185 } */ *uap = v;
186 BLOCK_INFO *blkiov;
187 BLOCK_INFO_15 *blkiov15;
188 int i, blkcnt, error;
189 fsid_t fsid;
190
191 if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
192 return (error);
193
194 if ((error = copyin(SCARG(uap, fsidp), &fsid, sizeof(fsid_t))) != 0)
195 return (error);
196
197 blkcnt = SCARG(uap, blkcnt);
198 if ((u_int) blkcnt > MARKV_MAXBLKCNT)
199 return (EINVAL);
200
201 blkiov = malloc(blkcnt * sizeof(BLOCK_INFO), M_SEGMENT, M_WAITOK);
202 blkiov15 = malloc(blkcnt * sizeof(BLOCK_INFO_15), M_SEGMENT, M_WAITOK);
203 if ((error = copyin(SCARG(uap, blkiov), blkiov15,
204 blkcnt * sizeof(BLOCK_INFO_15))) != 0)
205 goto out;
206
207 for (i = 0; i < blkcnt; i++) {
208 blkiov[i].bi_inode = blkiov15[i].bi_inode;
209 blkiov[i].bi_lbn = blkiov15[i].bi_lbn;
210 blkiov[i].bi_daddr = blkiov15[i].bi_daddr;
211 blkiov[i].bi_segcreate = blkiov15[i].bi_segcreate;
212 blkiov[i].bi_version = blkiov15[i].bi_version;
213 blkiov[i].bi_bp = blkiov15[i].bi_bp;
214 blkiov[i].bi_size = blkiov15[i].bi_size;
215 }
216
217 if ((error = lfs_markv(p, &fsid, blkiov, blkcnt)) == 0) {
218 for (i = 0; i < blkcnt; i++) {
219 blkiov15[i].bi_inode = blkiov[i].bi_inode;
220 blkiov15[i].bi_lbn = blkiov[i].bi_lbn;
221 blkiov15[i].bi_daddr = blkiov[i].bi_daddr;
222 blkiov15[i].bi_segcreate = blkiov[i].bi_segcreate;
223 blkiov15[i].bi_version = blkiov[i].bi_version;
224 blkiov15[i].bi_bp = blkiov[i].bi_bp;
225 blkiov15[i].bi_size = blkiov[i].bi_size;
226 }
227 copyout(blkiov15, SCARG(uap, blkiov),
228 blkcnt * sizeof(BLOCK_INFO_15));
229 }
230 out:
231 free(blkiov, M_SEGMENT);
232 free(blkiov15, M_SEGMENT);
233 return error;
234 }
235 #endif
236
237 #define LFS_MARKV_MAX_BLOCKS (LFS_MAX_BUFS)
238
239 static int
240 lfs_markv(struct proc *p, fsid_t *fsidp, BLOCK_INFO *blkiov, int blkcnt)
241 {
242 BLOCK_INFO *blkp;
243 IFILE *ifp;
244 struct buf *bp, *nbp;
245 struct inode *ip = NULL;
246 struct lfs *fs;
247 struct mount *mntp;
248 struct vnode *vp;
249 #ifdef DEBUG_LFS
250 int vputc = 0, iwritten = 0;
251 #endif
252 ino_t lastino;
253 ufs_daddr_t b_daddr, v_daddr;
254 int cnt, error;
255 int do_again = 0;
256 int s;
257 #ifdef CHECK_COPYIN
258 int i;
259 #endif /* CHECK_COPYIN */
260 int numrefed = 0;
261 ino_t maxino;
262 size_t obsize;
263
264 /* number of blocks/inodes that we have already bwrite'ed */
265 int nblkwritten, ninowritten;
266
267 if ((mntp = vfs_getvfs(fsidp)) == NULL)
268 return (ENOENT);
269
270 fs = VFSTOUFS(mntp)->um_lfs;
271 maxino = (fragstoblks(fs, fsbtofrags(fs, VTOI(fs->lfs_ivnode)->i_ffs_blocks)) -
272 fs->lfs_cleansz - fs->lfs_segtabsz) * fs->lfs_ifpb;
273
274 cnt = blkcnt;
275
276 if ((error = vfs_busy(mntp, LK_NOWAIT, NULL)) != 0)
277 return (error);
278
279 /*
280 * This seglock is just to prevent the fact that we might have to sleep
281 * from allowing the possibility that our blocks might become
282 * invalid.
283 *
284 * It is also important to note here that unless we specify SEGM_CKP,
285 * any Ifile blocks that we might be asked to clean will never get
286 * to the disk.
287 */
288 lfs_seglock(fs, SEGM_CLEAN | SEGM_CKP | SEGM_SYNC);
289
290 /* Mark blocks/inodes dirty. */
291 error = 0;
292
293 #ifdef DEBUG_LFS
294 /* Run through and count the inodes */
295 lastino = LFS_UNUSED_INUM;
296 for (blkp = blkiov; cnt--; ++blkp) {
297 if (lastino != blkp->bi_inode) {
298 lastino = blkp->bi_inode;
299 vputc++;
300 }
301 }
302 cnt = blkcnt;
303 printf("[%d/",vputc);
304 iwritten = 0;
305 #endif /* DEBUG_LFS */
306 /* these were inside the initialization for the for loop */
307 v_daddr = LFS_UNUSED_DADDR;
308 lastino = LFS_UNUSED_INUM;
309 nblkwritten = ninowritten = 0;
310 for (blkp = blkiov; cnt--; ++blkp)
311 {
312 if (blkp->bi_daddr == LFS_FORCE_WRITE)
313 printf("lfs_markv: warning: force-writing ino %d lbn %d\n",
314 blkp->bi_inode, blkp->bi_lbn);
315 /* Bounds-check incoming data, avoid panic for failed VGET */
316 if (blkp->bi_inode <= 0 || blkp->bi_inode >= maxino) {
317 error = EINVAL;
318 goto again;
319 }
320 /*
321 * Get the IFILE entry (only once) and see if the file still
322 * exists.
323 */
324 if (lastino != blkp->bi_inode) {
325 /*
326 * Finish the old file, if there was one. The presence
327 * of a usable vnode in vp is signaled by a valid v_daddr.
328 */
329 if (v_daddr != LFS_UNUSED_DADDR) {
330 #ifdef DEBUG_LFS
331 if (ip->i_flag & (IN_MODIFIED|IN_CLEANING))
332 iwritten++;
333 #endif
334 lfs_vunref(vp);
335 numrefed--;
336 }
337
338 /*
339 * Start a new file
340 */
341 lastino = blkp->bi_inode;
342 if (blkp->bi_inode == LFS_IFILE_INUM)
343 v_daddr = fs->lfs_idaddr;
344 else {
345 LFS_IENTRY(ifp, fs, blkp->bi_inode, bp);
346 /* XXX fix for force write */
347 v_daddr = ifp->if_daddr;
348 brelse(bp);
349 }
350 /* Don't force-write the ifile */
351 if (blkp->bi_inode == LFS_IFILE_INUM
352 && blkp->bi_daddr == LFS_FORCE_WRITE)
353 {
354 continue;
355 }
356 if (v_daddr == LFS_UNUSED_DADDR
357 && blkp->bi_daddr != LFS_FORCE_WRITE)
358 {
359 continue;
360 }
361
362 /* Get the vnode/inode. */
363 error = lfs_fastvget(mntp, blkp->bi_inode, v_daddr,
364 &vp,
365 (blkp->bi_lbn == LFS_UNUSED_LBN
366 ? blkp->bi_bp
367 : NULL));
368
369 if (!error) {
370 numrefed++;
371 }
372 if (error) {
373 #ifdef DEBUG_LFS
374 printf("lfs_markv: lfs_fastvget failed with %d (ino %d, segment %d)\n",
375 error, blkp->bi_inode,
376 dtosn(fs, blkp->bi_daddr));
377 #endif /* DEBUG_LFS */
378 /*
379 * If we got EAGAIN, that means that the
380 * Inode was locked. This is
381 * recoverable: just clean the rest of
382 * this segment, and let the cleaner try
383 * again with another. (When the
384 * cleaner runs again, this segment will
385 * sort high on the list, since it is
386 * now almost entirely empty.) But, we
387 * still set v_daddr = LFS_UNUSED_ADDR
388 * so as not to test this over and over
389 * again.
390 */
391 if (error == EAGAIN) {
392 error = 0;
393 do_again++;
394 }
395 #ifdef DIAGNOSTIC
396 else if (error != ENOENT)
397 panic("lfs_markv VFS_VGET FAILED");
398 #endif
399 /* lastino = LFS_UNUSED_INUM; */
400 v_daddr = LFS_UNUSED_DADDR;
401 vp = NULL;
402 ip = NULL;
403 continue;
404 }
405 ip = VTOI(vp);
406 ninowritten++;
407 } else if (v_daddr == LFS_UNUSED_DADDR) {
408 /*
409 * This can only happen if the vnode is dead (or
410 * in any case we can't get it...e.g., it is
411 * inlocked). Keep going.
412 */
413 continue;
414 }
415
416 /* Past this point we are guaranteed that vp, ip are valid. */
417
418 /* If this BLOCK_INFO didn't contain a block, keep going. */
419 if (blkp->bi_lbn == LFS_UNUSED_LBN) {
420 /* XXX need to make sure that the inode gets written in this case */
421 /* XXX but only write the inode if it's the right one */
422 if (blkp->bi_inode != LFS_IFILE_INUM) {
423 LFS_IENTRY(ifp, fs, blkp->bi_inode, bp);
424 if (ifp->if_daddr == blkp->bi_daddr
425 || blkp->bi_daddr == LFS_FORCE_WRITE)
426 {
427 LFS_SET_UINO(ip, IN_CLEANING);
428 }
429 brelse(bp);
430 }
431 continue;
432 }
433
434 b_daddr = 0;
435 if (blkp->bi_daddr != LFS_FORCE_WRITE) {
436 if (VOP_BMAP(vp, blkp->bi_lbn, NULL, &b_daddr, NULL) ||
437 dbtofsb(fs, b_daddr) != blkp->bi_daddr)
438 {
439 if (dtosn(fs,dbtofsb(fs, b_daddr))
440 == dtosn(fs,blkp->bi_daddr))
441 {
442 printf("lfs_markv: wrong da same seg: %x vs %x\n",
443 blkp->bi_daddr, dbtofsb(fs, b_daddr));
444 }
445 do_again++;
446 continue;
447 }
448 }
449
450 /*
451 * Check block sizes. The blocks being cleaned come from
452 * disk, so they should have the same size as their on-disk
453 * counterparts.
454 */
455 if (blkp->bi_lbn >= 0)
456 obsize = blksize(fs, ip, blkp->bi_lbn);
457 else
458 obsize = fs->lfs_bsize;
459 /* Check for fragment size change */
460 if (blkp->bi_lbn >= 0 && blkp->bi_lbn < NDADDR) {
461 obsize = ip->i_lfs_fragsize[blkp->bi_lbn];
462 }
463 if (obsize != blkp->bi_size) {
464 printf("lfs_markv: ino %d lbn %d wrong size (%ld != %d), try again\n",
465 blkp->bi_inode, blkp->bi_lbn,
466 (long) obsize, blkp->bi_size);
467 do_again++;
468 continue;
469 }
470
471 /*
472 * If we get to here, then we are keeping the block. If
473 * it is an indirect block, we want to actually put it
474 * in the buffer cache so that it can be updated in the
475 * finish_meta section. If it's not, we need to
476 * allocate a fake buffer so that writeseg can perform
477 * the copyin and write the buffer.
478 */
479 if (ip->i_number != LFS_IFILE_INUM && blkp->bi_lbn >= 0) {
480 /* Data Block */
481 bp = lfs_fakebuf(fs, vp, blkp->bi_lbn,
482 blkp->bi_size, blkp->bi_bp);
483 /* Pretend we used bread() to get it */
484 bp->b_blkno = fsbtodb(fs, blkp->bi_daddr);
485 } else {
486 /* Indirect block or ifile */
487 if (blkp->bi_size != fs->lfs_bsize &&
488 ip->i_number != LFS_IFILE_INUM)
489 panic("lfs_markv: partial indirect block?"
490 " size=%d\n", blkp->bi_size);
491 bp = getblk(vp, blkp->bi_lbn, blkp->bi_size, 0, 0);
492 if (!(bp->b_flags & (B_DONE|B_DELWRI))) { /* B_CACHE */
493 /*
494 * The block in question was not found
495 * in the cache; i.e., the block that
496 * getblk() returned is empty. So, we
497 * can (and should) copy in the
498 * contents, because we've already
499 * determined that this was the right
500 * version of this block on disk.
501 *
502 * And, it can't have changed underneath
503 * us, because we have the segment lock.
504 */
505 error = copyin(blkp->bi_bp, bp->b_data, blkp->bi_size);
506 if (error)
507 goto err2;
508 }
509 }
510 if ((error = lfs_bwrite_ext(bp,BW_CLEAN)) != 0)
511 goto err2;
512
513 nblkwritten++;
514 /*
515 * XXX should account indirect blocks and ifile pages as well
516 */
517 if (nblkwritten + lblkno(fs, ninowritten * DINODE_SIZE)
518 > LFS_MARKV_MAX_BLOCKS) {
519 #ifdef DEBUG_LFS
520 printf("lfs_markv: writing %d blks %d inos\n",
521 nblkwritten, ninowritten);
522 #endif
523 lfs_segwrite(mntp, SEGM_CLEAN);
524 nblkwritten = ninowritten = 0;
525 }
526 }
527
528 /*
529 * Finish the old file, if there was one
530 */
531 if (v_daddr != LFS_UNUSED_DADDR) {
532 #ifdef DEBUG_LFS
533 if (ip->i_flag & (IN_MODIFIED|IN_CLEANING))
534 iwritten++;
535 #endif
536 lfs_vunref(vp);
537 numrefed--;
538 }
539
540 #ifdef DEBUG_LFS
541 printf("%d]",iwritten);
542 if (numrefed != 0) {
543 panic("lfs_markv: numrefed=%d", numrefed);
544 }
545 #endif
546
547 #ifdef DEBUG_LFS
548 printf("lfs_markv: writing %d blks %d inos (check point)\n",
549 nblkwritten, ninowritten);
550 #endif
551 /*
552 * The last write has to be SEGM_SYNC, because of calling semantics.
553 * It also has to be SEGM_CKP, because otherwise we could write
554 * over the newly cleaned data contained in a checkpoint, and then
555 * we'd be unhappy at recovery time.
556 */
557 lfs_segwrite(mntp, SEGM_CLEAN | SEGM_CKP | SEGM_SYNC);
558
559 lfs_segunlock(fs);
560
561 vfs_unbusy(mntp);
562 if (error)
563 return (error);
564 else if (do_again)
565 return EAGAIN;
566
567 return 0;
568
569 err2:
570 printf("lfs_markv err2\n");
571 lfs_vunref(vp);
572 --numrefed;
573
574 /* Free up fakebuffers -- have to take these from the LOCKED list */
575 again:
576 s = splbio();
577 for (bp = bufqueues[BQ_LOCKED].tqh_first; bp; bp = nbp) {
578 nbp = bp->b_freelist.tqe_next;
579 if (bp->b_flags & B_CALL) {
580 if (bp->b_flags & B_BUSY) { /* not bloody likely */
581 bp->b_flags |= B_WANTED;
582 tsleep(bp, PRIBIO+1, "markv", 0);
583 splx(s);
584 goto again;
585 }
586 if (bp->b_flags & B_DELWRI)
587 fs->lfs_avail += btofsb(fs, bp->b_bcount);
588 bremfree(bp);
589 splx(s);
590 brelse(bp);
591 s = splbio();
592 }
593 }
594 splx(s);
595 lfs_segunlock(fs);
596 vfs_unbusy(mntp);
597 #ifdef DEBUG_LFS
598 if (numrefed != 0) {
599 panic("lfs_markv: numrefed=%d", numrefed);
600 }
601 #endif
602
603 return (error);
604 }
605
606 /*
607 * sys_lfs_bmapv:
608 *
609 * This will fill in the current disk address for arrays of blocks.
610 *
611 * 0 on success
612 * -1/errno is return on error.
613 */
614 #ifdef USE_64BIT_SYSCALLS
615 int
616 sys_lfs_bmapv(struct proc *p, void *v, register_t *retval)
617 {
618 struct sys_lfs_bmapv_args /* {
619 syscallarg(fsid_t *) fsidp;
620 syscallarg(struct block_info *) blkiov;
621 syscallarg(int) blkcnt;
622 } */ *uap = v;
623 BLOCK_INFO *blkiov;
624 int blkcnt, error;
625 fsid_t fsid;
626
627 if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
628 return (error);
629
630 if ((error = copyin(SCARG(uap, fsidp), &fsid, sizeof(fsid_t))) != 0)
631 return (error);
632
633 blkcnt = SCARG(uap, blkcnt);
634 if ((u_int) blkcnt > SIZE_T_MAX / sizeof(BLOCK_INFO))
635 return (EINVAL);
636 blkiov = malloc(blkcnt * sizeof(BLOCK_INFO), M_SEGMENT, M_WAITOK);
637 if ((error = copyin(SCARG(uap, blkiov), blkiov,
638 blkcnt * sizeof(BLOCK_INFO))) != 0)
639 goto out;
640
641 if ((error = lfs_bmapv(p, &fsid, blkiov, blkcnt)) == 0)
642 copyout(blkiov, SCARG(uap, blkiov),
643 blkcnt * sizeof(BLOCK_INFO));
644 out:
645 free(blkiov, M_SEGMENT);
646 return error;
647 }
648 #else
649 int
650 sys_lfs_bmapv(struct proc *p, void *v, register_t *retval)
651 {
652 struct sys_lfs_bmapv_args /* {
653 syscallarg(fsid_t *) fsidp;
654 syscallarg(struct block_info *) blkiov;
655 syscallarg(int) blkcnt;
656 } */ *uap = v;
657 BLOCK_INFO *blkiov;
658 BLOCK_INFO_15 *blkiov15;
659 int i, blkcnt, error;
660 fsid_t fsid;
661
662 if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
663 return (error);
664
665 if ((error = copyin(SCARG(uap, fsidp), &fsid, sizeof(fsid_t))) != 0)
666 return (error);
667
668 blkcnt = SCARG(uap, blkcnt);
669 if ((u_int) blkcnt > SIZE_T_MAX / sizeof(BLOCK_INFO))
670 return (EINVAL);
671 blkiov = malloc(blkcnt * sizeof(BLOCK_INFO), M_SEGMENT, M_WAITOK);
672 blkiov15 = malloc(blkcnt * sizeof(BLOCK_INFO_15), M_SEGMENT, M_WAITOK);
673 if ((error = copyin(SCARG(uap, blkiov), blkiov15,
674 blkcnt * sizeof(BLOCK_INFO_15))) != 0)
675 goto out;
676
677 for (i = 0; i < blkcnt; i++) {
678 blkiov[i].bi_inode = blkiov15[i].bi_inode;
679 blkiov[i].bi_lbn = blkiov15[i].bi_lbn;
680 blkiov[i].bi_daddr = blkiov15[i].bi_daddr;
681 blkiov[i].bi_segcreate = blkiov15[i].bi_segcreate;
682 blkiov[i].bi_version = blkiov15[i].bi_version;
683 blkiov[i].bi_bp = blkiov15[i].bi_bp;
684 blkiov[i].bi_size = blkiov15[i].bi_size;
685 }
686
687 if ((error = lfs_bmapv(p, &fsid, blkiov, blkcnt)) == 0) {
688 for (i = 0; i < blkcnt; i++) {
689 blkiov15[i].bi_inode = blkiov[i].bi_inode;
690 blkiov15[i].bi_lbn = blkiov[i].bi_lbn;
691 blkiov15[i].bi_daddr = blkiov[i].bi_daddr;
692 blkiov15[i].bi_segcreate = blkiov[i].bi_segcreate;
693 blkiov15[i].bi_version = blkiov[i].bi_version;
694 blkiov15[i].bi_bp = blkiov[i].bi_bp;
695 blkiov15[i].bi_size = blkiov[i].bi_size;
696 }
697 copyout(blkiov15, SCARG(uap, blkiov),
698 blkcnt * sizeof(BLOCK_INFO_15));
699 }
700 out:
701 free(blkiov, M_SEGMENT);
702 free(blkiov15, M_SEGMENT);
703 return error;
704 }
705 #endif
706
707 static int
708 lfs_bmapv(struct proc *p, fsid_t *fsidp, BLOCK_INFO *blkiov, int blkcnt)
709 {
710 BLOCK_INFO *blkp;
711 IFILE *ifp;
712 struct buf *bp;
713 struct inode *ip = NULL;
714 struct lfs *fs;
715 struct mount *mntp;
716 struct ufsmount *ump;
717 struct vnode *vp;
718 ino_t lastino;
719 ufs_daddr_t v_daddr;
720 int cnt, error;
721 int numrefed = 0;
722
723 lfs_cleaner_pid = p->p_pid;
724
725 if ((mntp = vfs_getvfs(fsidp)) == NULL)
726 return (ENOENT);
727
728 ump = VFSTOUFS(mntp);
729 if ((error = vfs_busy(mntp, LK_NOWAIT, NULL)) != 0)
730 return (error);
731
732 cnt = blkcnt;
733
734 fs = VFSTOUFS(mntp)->um_lfs;
735
736 error = 0;
737
738 /* these were inside the initialization for the for loop */
739 v_daddr = LFS_UNUSED_DADDR;
740 lastino = LFS_UNUSED_INUM;
741 for (blkp = blkiov; cnt--; ++blkp)
742 {
743 /*
744 * Get the IFILE entry (only once) and see if the file still
745 * exists.
746 */
747 if (lastino != blkp->bi_inode) {
748 /*
749 * Finish the old file, if there was one. The presence
750 * of a usable vnode in vp is signaled by a valid
751 * v_daddr.
752 */
753 if (v_daddr != LFS_UNUSED_DADDR) {
754 lfs_vunref(vp);
755 numrefed--;
756 }
757
758 /*
759 * Start a new file
760 */
761 lastino = blkp->bi_inode;
762 if (blkp->bi_inode == LFS_IFILE_INUM)
763 v_daddr = fs->lfs_idaddr;
764 else {
765 LFS_IENTRY(ifp, fs, blkp->bi_inode, bp);
766 v_daddr = ifp->if_daddr;
767 brelse(bp);
768 }
769 if (v_daddr == LFS_UNUSED_DADDR) {
770 blkp->bi_daddr = LFS_UNUSED_DADDR;
771 continue;
772 }
773 /*
774 * A regular call to VFS_VGET could deadlock
775 * here. Instead, we try an unlocked access.
776 */
777 vp = ufs_ihashlookup(ump->um_dev, blkp->bi_inode);
778 if (vp != NULL && !(vp->v_flag & VXLOCK)) {
779 ip = VTOI(vp);
780 if (lfs_vref(vp)) {
781 v_daddr = LFS_UNUSED_DADDR;
782 continue;
783 }
784 numrefed++;
785 } else {
786 error = VFS_VGET(mntp, blkp->bi_inode, &vp);
787 if (error) {
788 #ifdef DEBUG_LFS
789 printf("lfs_bmapv: vget of ino %d failed with %d",blkp->bi_inode,error);
790 #endif
791 v_daddr = LFS_UNUSED_DADDR;
792 continue;
793 } else {
794 KASSERT(VOP_ISLOCKED(vp));
795 VOP_UNLOCK(vp, 0);
796 numrefed++;
797 }
798 }
799 ip = VTOI(vp);
800 } else if (v_daddr == LFS_UNUSED_DADDR) {
801 /*
802 * This can only happen if the vnode is dead.
803 * Keep going. Note that we DO NOT set the
804 * bi_addr to anything -- if we failed to get
805 * the vnode, for example, we want to assume
806 * conservatively that all of its blocks *are*
807 * located in the segment in question.
808 * lfs_markv will throw them out if we are
809 * wrong.
810 */
811 /* blkp->bi_daddr = LFS_UNUSED_DADDR; */
812 continue;
813 }
814
815 /* Past this point we are guaranteed that vp, ip are valid. */
816
817 if (blkp->bi_lbn == LFS_UNUSED_LBN) {
818 /*
819 * We just want the inode address, which is
820 * conveniently in v_daddr.
821 */
822 blkp->bi_daddr = v_daddr;
823 } else {
824 error = VOP_BMAP(vp, blkp->bi_lbn, NULL,
825 &(blkp->bi_daddr), NULL);
826 if (error)
827 {
828 blkp->bi_daddr = LFS_UNUSED_DADDR;
829 continue;
830 }
831 blkp->bi_daddr = dbtofsb(fs, blkp->bi_daddr);
832 /* Fill in the block size, too */
833 if (blkp->bi_lbn >= 0)
834 blkp->bi_size = blksize(fs, ip, blkp->bi_lbn);
835 else
836 blkp->bi_size = fs->lfs_bsize;
837 }
838 }
839
840 /*
841 * Finish the old file, if there was one. The presence
842 * of a usable vnode in vp is signaled by a valid v_daddr.
843 */
844 if (v_daddr != LFS_UNUSED_DADDR) {
845 lfs_vunref(vp);
846 numrefed--;
847 }
848
849 #ifdef DEBUG_LFS
850 if (numrefed != 0) {
851 panic("lfs_bmapv: numrefed=%d", numrefed);
852 }
853 #endif
854
855 vfs_unbusy(mntp);
856
857 return 0;
858 }
859
860 /*
861 * sys_lfs_segclean:
862 *
863 * Mark the segment clean.
864 *
865 * 0 on success
866 * -1/errno is return on error.
867 */
868 int
869 sys_lfs_segclean(struct proc *p, void *v, register_t *retval)
870 {
871 struct sys_lfs_segclean_args /* {
872 syscallarg(fsid_t *) fsidp;
873 syscallarg(u_long) segment;
874 } */ *uap = v;
875 CLEANERINFO *cip;
876 SEGUSE *sup;
877 struct buf *bp;
878 struct mount *mntp;
879 struct lfs *fs;
880 fsid_t fsid;
881 int error;
882 unsigned long segnum;
883
884 if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
885 return (error);
886
887 if ((error = copyin(SCARG(uap, fsidp), &fsid, sizeof(fsid_t))) != 0)
888 return (error);
889 if ((mntp = vfs_getvfs(&fsid)) == NULL)
890 return (ENOENT);
891
892 fs = VFSTOUFS(mntp)->um_lfs;
893 segnum = SCARG(uap, segment);
894
895 if (dtosn(fs, fs->lfs_curseg) == segnum)
896 return (EBUSY);
897
898 if ((error = vfs_busy(mntp, LK_NOWAIT, NULL)) != 0)
899 return (error);
900 #ifdef LFS_AGGRESSIVE_SEGLOCK
901 lfs_seglock(fs, SEGM_PROT);
902 #endif
903 LFS_SEGENTRY(sup, fs, segnum, bp);
904 if (sup->su_nbytes) {
905 printf("lfs_segclean: not cleaning segment %lu: %d live bytes\n",
906 segnum, sup->su_nbytes);
907 brelse(bp);
908 #ifdef LFS_AGGRESSIVE_SEGLOCK
909 lfs_segunlock(fs);
910 #endif
911 vfs_unbusy(mntp);
912 return (EBUSY);
913 }
914 if (sup->su_flags & SEGUSE_ACTIVE) {
915 brelse(bp);
916 #ifdef LFS_AGGRESSIVE_SEGLOCK
917 lfs_segunlock(fs);
918 #endif
919 vfs_unbusy(mntp);
920 return (EBUSY);
921 }
922 if (!(sup->su_flags & SEGUSE_DIRTY)) {
923 brelse(bp);
924 #ifdef LFS_AGGRESSIVE_SEGLOCK
925 lfs_segunlock(fs);
926 #endif
927 vfs_unbusy(mntp);
928 return (EALREADY);
929 }
930
931 fs->lfs_avail += segtod(fs, 1);
932 if (sup->su_flags & SEGUSE_SUPERBLOCK)
933 fs->lfs_avail -= btofsb(fs, LFS_SBPAD);
934 if (fs->lfs_version > 1 && segnum == 0 &&
935 fs->lfs_start < btofsb(fs, LFS_LABELPAD))
936 fs->lfs_avail -= btofsb(fs, LFS_LABELPAD) - fs->lfs_start;
937 fs->lfs_bfree += sup->su_nsums * btofsb(fs, fs->lfs_sumsize) +
938 btofsb(fs, sup->su_ninos * fs->lfs_ibsize);
939 fs->lfs_dmeta -= sup->su_nsums * btofsb(fs, fs->lfs_sumsize) +
940 btofsb(fs, sup->su_ninos * fs->lfs_ibsize);
941 if (fs->lfs_dmeta < 0)
942 fs->lfs_dmeta = 0;
943 sup->su_flags &= ~SEGUSE_DIRTY;
944 (void) LFS_BWRITE_LOG(bp);
945
946 LFS_CLEANERINFO(cip, fs, bp);
947 ++cip->clean;
948 --cip->dirty;
949 fs->lfs_nclean = cip->clean;
950 cip->bfree = fs->lfs_bfree;
951 cip->avail = fs->lfs_avail - fs->lfs_ravail;
952 (void) LFS_BWRITE_LOG(bp);
953 wakeup(&fs->lfs_avail);
954 #ifdef LFS_AGGRESSIVE_SEGLOCK
955 lfs_segunlock(fs);
956 #endif
957 vfs_unbusy(mntp);
958
959 return (0);
960 }
961
962 /*
963 * sys_lfs_segwait:
964 *
965 * This will block until a segment in file system fsid is written. A timeout
966 * in milliseconds may be specified which will awake the cleaner automatically.
967 * An fsid of -1 means any file system, and a timeout of 0 means forever.
968 *
969 * 0 on success
970 * 1 on timeout
971 * -1/errno is return on error.
972 */
973 int
974 sys_lfs_segwait(struct proc *p, void *v, register_t *retval)
975 {
976 struct sys_lfs_segwait_args /* {
977 syscallarg(fsid_t *) fsidp;
978 syscallarg(struct timeval *) tv;
979 } */ *uap = v;
980 struct mount *mntp;
981 struct timeval atv;
982 fsid_t fsid;
983 void *addr;
984 u_long timeout;
985 int error, s;
986
987 if ((error = suser(p->p_ucred, &p->p_acflag)) != 0) {
988 return (error);
989 }
990 if ((error = copyin(SCARG(uap, fsidp), &fsid, sizeof(fsid_t))) != 0)
991 return (error);
992 if ((mntp = vfs_getvfs(&fsid)) == NULL)
993 addr = &lfs_allclean_wakeup;
994 else
995 addr = &VFSTOUFS(mntp)->um_lfs->lfs_nextseg;
996
997 if (SCARG(uap, tv)) {
998 error = copyin(SCARG(uap, tv), &atv, sizeof(struct timeval));
999 if (error)
1000 return (error);
1001 if (itimerfix(&atv))
1002 return (EINVAL);
1003 /*
1004 * XXX THIS COULD SLEEP FOREVER IF TIMEOUT IS {0,0}!
1005 * XXX IS THAT WHAT IS INTENDED?
1006 */
1007 s = splclock();
1008 timeradd(&atv, &time, &atv);
1009 timeout = hzto(&atv);
1010 splx(s);
1011 } else
1012 timeout = 0;
1013
1014 error = tsleep(addr, PCATCH | PUSER, "segment", timeout);
1015 return (error == ERESTART ? EINTR : 0);
1016 }
1017
1018 /*
1019 * VFS_VGET call specialized for the cleaner. The cleaner already knows the
1020 * daddr from the ifile, so don't look it up again. If the cleaner is
1021 * processing IINFO structures, it may have the ondisk inode already, so
1022 * don't go retrieving it again.
1023 *
1024 * we lfs_vref, and it is the caller's responsibility to lfs_vunref
1025 * when finished.
1026 */
1027 extern struct lock ufs_hashlock;
1028
1029 int
1030 lfs_fasthashget(dev_t dev, ino_t ino, struct vnode **vpp)
1031 {
1032 struct inode *ip;
1033
1034 /*
1035 * This is playing fast and loose. Someone may have the inode
1036 * locked, in which case they are going to be distinctly unhappy
1037 * if we trash something.
1038 */
1039 if ((*vpp = ufs_ihashlookup(dev, ino)) != NULL) {
1040 if ((*vpp)->v_flag & VXLOCK) {
1041 printf("lfs_fastvget: vnode VXLOCKed for ino %d\n",
1042 ino);
1043 clean_vnlocked++;
1044 #ifdef LFS_EAGAIN_FAIL
1045 return EAGAIN;
1046 #endif
1047 }
1048 ip = VTOI(*vpp);
1049 if (lfs_vref(*vpp)) {
1050 clean_inlocked++;
1051 return EAGAIN;
1052 }
1053 } else
1054 *vpp = NULL;
1055
1056 return (0);
1057 }
1058
1059 int
1060 lfs_fastvget(struct mount *mp, ino_t ino, ufs_daddr_t daddr, struct vnode **vpp, struct dinode *dinp)
1061 {
1062 struct inode *ip;
1063 struct dinode *dip;
1064 struct vnode *vp;
1065 struct ufsmount *ump;
1066 dev_t dev;
1067 int i, error, retries;
1068 struct buf *bp;
1069 struct lfs *fs;
1070
1071 ump = VFSTOUFS(mp);
1072 dev = ump->um_dev;
1073 fs = ump->um_lfs;
1074
1075 /*
1076 * Wait until the filesystem is fully mounted before allowing vget
1077 * to complete. This prevents possible problems with roll-forward.
1078 */
1079 while (fs->lfs_flags & LFS_NOTYET) {
1080 tsleep(&fs->lfs_flags, PRIBIO+1, "lfs_fnotyet", 0);
1081 }
1082 /*
1083 * This is playing fast and loose. Someone may have the inode
1084 * locked, in which case they are going to be distinctly unhappy
1085 * if we trash something.
1086 */
1087
1088 error = lfs_fasthashget(dev, ino, vpp);
1089 if (error != 0 || *vpp != NULL)
1090 return (error);
1091
1092 if ((error = getnewvnode(VT_LFS, mp, lfs_vnodeop_p, &vp)) != 0) {
1093 *vpp = NULL;
1094 return (error);
1095 }
1096
1097 do {
1098 error = lfs_fasthashget(dev, ino, vpp);
1099 if (error != 0 || *vpp != NULL) {
1100 ungetnewvnode(vp);
1101 return (error);
1102 }
1103 } while (lockmgr(&ufs_hashlock, LK_EXCLUSIVE|LK_SLEEPFAIL, 0));
1104
1105 /* Allocate new vnode/inode. */
1106 lfs_vcreate(mp, ino, vp);
1107
1108 /*
1109 * Put it onto its hash chain and lock it so that other requests for
1110 * this inode will block if they arrive while we are sleeping waiting
1111 * for old data structures to be purged or for the contents of the
1112 * disk portion of this inode to be read.
1113 */
1114 ip = VTOI(vp);
1115 ufs_ihashins(ip);
1116 lockmgr(&ufs_hashlock, LK_RELEASE, 0);
1117
1118 /*
1119 * XXX
1120 * This may not need to be here, logically it should go down with
1121 * the i_devvp initialization.
1122 * Ask Kirk.
1123 */
1124 ip->i_lfs = fs;
1125
1126 /* Read in the disk contents for the inode, copy into the inode. */
1127 if (dinp) {
1128 error = copyin(dinp, &ip->i_din.ffs_din, DINODE_SIZE);
1129 if (error) {
1130 printf("lfs_fastvget: dinode copyin failed for ino %d\n", ino);
1131 ufs_ihashrem(ip);
1132
1133 /* Unlock and discard unneeded inode. */
1134 lockmgr(&vp->v_lock, LK_RELEASE, &vp->v_interlock);
1135 lfs_vunref(vp);
1136 *vpp = NULL;
1137 return (error);
1138 }
1139 if (ip->i_number != ino)
1140 panic("lfs_fastvget: I was fed the wrong inode!");
1141 } else {
1142 retries = 0;
1143 again:
1144 error = bread(ump->um_devvp, fsbtodb(fs, daddr), fs->lfs_ibsize,
1145 NOCRED, &bp);
1146 if (error) {
1147 printf("lfs_fastvget: bread failed with %d\n",error);
1148 /*
1149 * The inode does not contain anything useful, so it
1150 * would be misleading to leave it on its hash chain.
1151 * Iput() will return it to the free list.
1152 */
1153 ufs_ihashrem(ip);
1154
1155 /* Unlock and discard unneeded inode. */
1156 lockmgr(&vp->v_lock, LK_RELEASE, &vp->v_interlock);
1157 lfs_vunref(vp);
1158 brelse(bp);
1159 *vpp = NULL;
1160 return (error);
1161 }
1162 dip = lfs_ifind(ump->um_lfs, ino, bp);
1163 if (dip == NULL) {
1164 /* Assume write has not completed yet; try again */
1165 bp->b_flags |= B_INVAL;
1166 brelse(bp);
1167 ++retries;
1168 if (retries > LFS_IFIND_RETRIES)
1169 panic("lfs_fastvget: dinode not found");
1170 printf("lfs_fastvget: dinode not found, retrying...\n");
1171 goto again;
1172 }
1173 ip->i_din.ffs_din = *dip;
1174 brelse(bp);
1175 }
1176 ip->i_ffs_effnlink = ip->i_ffs_nlink;
1177 ip->i_lfs_effnblks = ip->i_ffs_blocks;
1178 ip->i_lfs_osize = ip->i_ffs_size;
1179
1180 memset(ip->i_lfs_fragsize, 0, NDADDR * sizeof(*ip->i_lfs_fragsize));
1181 for (i = 0; i < NDADDR; i++)
1182 if (ip->i_ffs_db[i] != 0)
1183 ip->i_lfs_fragsize[i] = blksize(fs, ip, i);
1184
1185 /*
1186 * Initialize the vnode from the inode, check for aliases. In all
1187 * cases re-init ip, the underlying vnode/inode may have changed.
1188 */
1189 ufs_vinit(mp, lfs_specop_p, lfs_fifoop_p, &vp);
1190 #ifdef DEBUG_LFS
1191 if (vp->v_type == VNON) {
1192 printf("lfs_fastvget: ino %d is type VNON! (ifmt=%o, dinp=%p)\n",
1193 ip->i_number, (ip->i_ffs_mode & IFMT) >> 12, dinp);
1194 lfs_dump_dinode(&ip->i_din.ffs_din);
1195 #ifdef DDB
1196 Debugger();
1197 #endif
1198 }
1199 #endif /* DEBUG_LFS */
1200 /*
1201 * Finish inode initialization now that aliasing has been resolved.
1202 */
1203
1204 genfs_node_init(vp, &lfs_genfsops);
1205 ip->i_devvp = ump->um_devvp;
1206 VREF(ip->i_devvp);
1207 *vpp = vp;
1208 KASSERT(VOP_ISLOCKED(vp));
1209 VOP_UNLOCK(vp, 0);
1210
1211 uvm_vnp_setsize(vp, ip->i_ffs_size);
1212
1213 return (0);
1214 }
1215
1216 static void
1217 lfs_fakebuf_iodone(struct buf *bp)
1218 {
1219 struct buf *obp = bp->b_saveaddr;
1220
1221 if (!(obp->b_flags & (B_DELWRI | B_DONE)))
1222 obp->b_flags |= B_INVAL;
1223 brelse(obp);
1224 lfs_callback(bp);
1225 }
1226
1227 struct buf *
1228 lfs_fakebuf(struct lfs *fs, struct vnode *vp, int lbn, size_t size, caddr_t uaddr)
1229 {
1230 struct buf *bp;
1231 int error;
1232
1233 struct buf *obp;
1234
1235 KASSERT(VTOI(vp)->i_number != LFS_IFILE_INUM);
1236
1237 /*
1238 * make corresponding buffer busy to avoid
1239 * reading blocks that isn't written yet.
1240 * it's needed because we'll update metadatas in lfs_updatemeta
1241 * before data pointed by them is actually written to disk.
1242 *
1243 * XXX no need to allocbuf.
1244 *
1245 * XXX this can cause buf starvation.
1246 */
1247 obp = getblk(vp, lbn, size, 0, 0);
1248 if (obp == NULL)
1249 panic("lfs_fakebuf: getblk failed");
1250
1251 #ifndef ALLOW_VFLUSH_CORRUPTION
1252 bp = lfs_newbuf(VTOI(vp)->i_lfs, vp, lbn, size);
1253 error = copyin(uaddr, bp->b_data, size);
1254 if (error) {
1255 lfs_freebuf(bp);
1256 return NULL;
1257 }
1258 bp->b_saveaddr = obp;
1259 KDASSERT(bp->b_iodone == lfs_callback);
1260 bp->b_iodone = lfs_fakebuf_iodone;
1261
1262 #ifdef DIAGNOSTIC
1263 if (obp->b_flags & B_GATHERED)
1264 panic("lfs_fakebuf: gathered bp: %p, ino=%u, lbn=%d",
1265 bp, VTOI(vp)->i_number, lbn);
1266 #endif
1267 #else
1268 bp = lfs_newbuf(VTOI(vp)->i_lfs, vp, lbn, 0);
1269 bp->b_flags |= B_INVAL;
1270 bp->b_saveaddr = uaddr;
1271 #endif
1272 #if 0
1273 bp->b_saveaddr = (caddr_t)fs;
1274 ++fs->lfs_iocount;
1275 #endif
1276 bp->b_bufsize = size;
1277 bp->b_bcount = size;
1278 return (bp);
1279 }
1280