|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. ! 3: * ! 4: * @APPLE_LICENSE_HEADER_START@ ! 5: * ! 6: * The contents of this file constitute Original Code as defined in and ! 7: * are subject to the Apple Public Source License Version 1.1 (the ! 8: * "License"). You may not use this file except in compliance with the ! 9: * License. Please obtain a copy of the License at ! 10: * http://www.apple.com/publicsource and read it before using this file. ! 11: * ! 12: * This Original Code and all software distributed under the License are ! 13: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER ! 14: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, ! 15: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, ! 16: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the ! 17: * License for the specific language governing rights and limitations ! 18: * under the License. ! 19: * ! 20: * @APPLE_LICENSE_HEADER_END@ ! 21: */ ! 22: /* $NetBSD: lfs_syscalls.c,v 1.8 1995/03/21 13:34:08 mycroft Exp $ */ ! 23: ! 24: /*- ! 25: * Copyright (c) 1991, 1993, 1994 ! 26: * The Regents of the University of California. All rights reserved. ! 27: * ! 28: * Redistribution and use in source and binary forms, with or without ! 29: * modification, are permitted provided that the following conditions ! 30: * are met: ! 31: * 1. Redistributions of source code must retain the above copyright ! 32: * notice, this list of conditions and the following disclaimer. ! 33: * 2. Redistributions in binary form must reproduce the above copyright ! 34: * notice, this list of conditions and the following disclaimer in the ! 35: * documentation and/or other materials provided with the distribution. ! 36: * 3. All advertising materials mentioning features or use of this software ! 37: * must display the following acknowledgement: ! 38: * This product includes software developed by the University of ! 39: * California, Berkeley and its contributors. ! 40: * 4. Neither the name of the University nor the names of its contributors ! 41: * may be used to endorse or promote products derived from this software ! 42: * without specific prior written permission. ! 43: * ! 44: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ! 45: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ! 46: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ! 47: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE ! 48: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ! 49: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ! 50: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ! 51: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ! 52: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ! 53: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ! 54: * SUCH DAMAGE. ! 55: * ! 56: * @(#)lfs_syscalls.c 8.6 (Berkeley) 6/16/94 ! 57: */ ! 58: ! 59: #include <sys/param.h> ! 60: #include <sys/systm.h> ! 61: #include <sys/proc.h> ! 62: #include <sys/buf.h> ! 63: #include <sys/mount.h> ! 64: #include <sys/vnode.h> ! 65: #include <sys/malloc.h> ! 66: #include <sys/kernel.h> ! 67: ! 68: #include <sys/syscallargs.h> ! 69: ! 70: #include <ufs/ufs/quota.h> ! 71: #include <ufs/ufs/inode.h> ! 72: #include <ufs/ufs/ufsmount.h> ! 73: #include <ufs/ufs/ufs_extern.h> ! 74: ! 75: #include <ufs/lfs/lfs.h> ! 76: #include <ufs/lfs/lfs_extern.h> ! 77: #define BUMP_FIP(SP) \ ! 78: (SP)->fip = (FINFO *) (&(SP)->fip->fi_blocks[(SP)->fip->fi_nblocks]) ! 79: ! 80: #define INC_FINFO(SP) ++((SEGSUM *)((SP)->segsum))->ss_nfinfo ! 81: #define DEC_FINFO(SP) --((SEGSUM *)((SP)->segsum))->ss_nfinfo ! 82: ! 83: /* ! 84: * Before committing to add something to a segment summary, make sure there ! 85: * is enough room. S is the bytes added to the summary. ! 86: */ ! 87: #define CHECK_SEG(s) \ ! 88: if (sp->sum_bytes_left < (s)) { \ ! 89: (void) lfs_writeseg(fs, sp); \ ! 90: } ! 91: struct buf *lfs_fakebuf __P((struct vnode *, int, size_t, caddr_t)); ! 92: ! 93: /* ! 94: * lfs_markv: ! 95: * ! 96: * This will mark inodes and blocks dirty, so they are written into the log. ! 97: * It will block until all the blocks have been written. The segment create ! 98: * time passed in the block_info and inode_info structures is used to decide ! 99: * if the data is valid for each block (in case some process dirtied a block ! 100: * or inode that is being cleaned between the determination that a block is ! 101: * live and the lfs_markv call). ! 102: * ! 103: * 0 on success ! 104: * -1/errno is return on error. ! 105: */ ! 106: int ! 107: lfs_markv(p, uap, retval) ! 108: struct proc *p; ! 109: struct lfs_markv_args /* { ! 110: syscallarg(fsid_t *) fsidp; ! 111: syscallarg(struct block_info *) blkiov; ! 112: syscallarg(int) blkcnt; ! 113: } */ *uap; ! 114: register_t *retval; ! 115: { ! 116: struct segment *sp; ! 117: BLOCK_INFO *blkp; ! 118: IFILE *ifp; ! 119: struct buf *bp, **bpp; ! 120: struct inode *ip; ! 121: struct lfs *fs; ! 122: struct mount *mntp; ! 123: struct vnode *vp; ! 124: fsid_t fsid; ! 125: void *start; ! 126: ino_t lastino; ! 127: daddr_t b_daddr, v_daddr; ! 128: u_long bsize; ! 129: int cnt, error; ! 130: ! 131: if (error = suser(p->p_ucred, &p->p_acflag)) ! 132: return (error); ! 133: ! 134: if (error = copyin(SCARG(uap, fsidp), &fsid, sizeof(fsid_t))) ! 135: return (error); ! 136: if ((mntp = getvfs(&fsid)) == NULL) ! 137: return (EINVAL); ! 138: ! 139: cnt = SCARG(uap, blkcnt); ! 140: // start = malloc(cnt * sizeof(BLOCK_INFO), M_SEGMENT, M_WAITOK); ! 141: MALLOC(start, void *, cnt * sizeof(BLOCK_INFO), M_SEGMENT, M_WAITOK); ! 142: if (error = copyin(SCARG(uap, blkiov), start, cnt * sizeof(BLOCK_INFO))) ! 143: goto err1; ! 144: ! 145: /* Mark blocks/inodes dirty. */ ! 146: fs = VFSTOUFS(mntp)->um_lfs; ! 147: bsize = fs->lfs_bsize; ! 148: error = 0; ! 149: ! 150: lfs_seglock(fs, SEGM_SYNC | SEGM_CLEAN); ! 151: sp = fs->lfs_sp; ! 152: for (v_daddr = LFS_UNUSED_DADDR, lastino = LFS_UNUSED_INUM, ! 153: blkp = start; cnt--; ++blkp) { ! 154: /* ! 155: * Get the IFILE entry (only once) and see if the file still ! 156: * exists. ! 157: */ ! 158: if (lastino != blkp->bi_inode) { ! 159: if (lastino != LFS_UNUSED_INUM) { ! 160: /* Finish up last file */ ! 161: if (sp->fip->fi_nblocks == 0) { ! 162: DEC_FINFO(sp); ! 163: sp->sum_bytes_left += ! 164: sizeof(FINFO) - sizeof(daddr_t); ! 165: } else { ! 166: lfs_updatemeta(sp); ! 167: BUMP_FIP(sp); ! 168: } ! 169: ! 170: lfs_writeinode(fs, sp, ip); ! 171: lfs_vunref(vp); ! 172: } ! 173: ! 174: /* Start a new file */ ! 175: CHECK_SEG(sizeof(FINFO)); ! 176: sp->sum_bytes_left -= sizeof(FINFO) - sizeof(daddr_t); ! 177: INC_FINFO(sp); ! 178: sp->start_lbp = &sp->fip->fi_blocks[0]; ! 179: sp->vp = NULL; ! 180: sp->fip->fi_version = blkp->bi_version; ! 181: sp->fip->fi_nblocks = 0; ! 182: sp->fip->fi_ino = blkp->bi_inode; ! 183: lastino = blkp->bi_inode; ! 184: if (blkp->bi_inode == LFS_IFILE_INUM) ! 185: v_daddr = fs->lfs_idaddr; ! 186: else { ! 187: LFS_IENTRY(ifp, fs, blkp->bi_inode, bp); ! 188: v_daddr = ifp->if_daddr; ! 189: brelse(bp); ! 190: } ! 191: if (v_daddr == LFS_UNUSED_DADDR) ! 192: continue; ! 193: ! 194: /* Get the vnode/inode. */ ! 195: if (lfs_fastvget(mntp, blkp->bi_inode, v_daddr, &vp, ! 196: blkp->bi_lbn == LFS_UNUSED_LBN ? ! 197: blkp->bi_bp : NULL)) { ! 198: #if DIAGNOSTIC ! 199: printf("lfs_markv: VFS_VGET failed (%d)\n", ! 200: blkp->bi_inode); ! 201: #endif ! 202: lastino = LFS_UNUSED_INUM; ! 203: v_daddr = LFS_UNUSED_DADDR; ! 204: continue; ! 205: } ! 206: sp->vp = vp; ! 207: ip = VTOI(vp); ! 208: } else if (v_daddr == LFS_UNUSED_DADDR) ! 209: continue; ! 210: ! 211: /* If this BLOCK_INFO didn't contain a block, keep going. */ ! 212: if (blkp->bi_lbn == LFS_UNUSED_LBN) ! 213: continue; ! 214: if (VOP_BMAP(vp, blkp->bi_lbn, NULL, &b_daddr, NULL) || ! 215: b_daddr != blkp->bi_daddr) ! 216: continue; ! 217: /* ! 218: * If we got to here, then we are keeping the block. If it ! 219: * is an indirect block, we want to actually put it in the ! 220: * buffer cache so that it can be updated in the finish_meta ! 221: * section. If it's not, we need to allocate a fake buffer ! 222: * so that writeseg can perform the copyin and write the buffer. ! 223: */ ! 224: if (blkp->bi_lbn >= 0) /* Data Block */ ! 225: bp = lfs_fakebuf(vp, blkp->bi_lbn, bsize, ! 226: blkp->bi_bp); ! 227: else { ! 228: bp = getblk(vp, blkp->bi_lbn, bsize, 0, 0); ! 229: if (!(bp->b_flags & (B_DELWRI | B_DONE | B_CACHE)) && ! 230: (error = copyin(blkp->bi_bp, bp->b_data, ! 231: bsize))) ! 232: goto err2; ! 233: if (error = VOP_BWRITE(bp)) ! 234: goto err2; ! 235: } ! 236: while (lfs_gatherblock(sp, bp, NULL)); ! 237: } ! 238: if (sp->vp) { ! 239: if (sp->fip->fi_nblocks == 0) { ! 240: DEC_FINFO(sp); ! 241: sp->sum_bytes_left += ! 242: sizeof(FINFO) - sizeof(daddr_t); ! 243: } else ! 244: lfs_updatemeta(sp); ! 245: ! 246: lfs_writeinode(fs, sp, ip); ! 247: lfs_vunref(vp); ! 248: } ! 249: (void) lfs_writeseg(fs, sp); ! 250: lfs_segunlock(fs); ! 251: free(start, M_SEGMENT); ! 252: return (error); ! 253: ! 254: /* ! 255: * XXX ! 256: * If we come in to error 2, we might have indirect blocks that were ! 257: * updated and now have bad block pointers. I don't know what to do ! 258: * about this. ! 259: */ ! 260: ! 261: err2: lfs_vunref(vp); ! 262: /* Free up fakebuffers */ ! 263: for (bpp = --sp->cbpp; bpp >= sp->bpp; --bpp) ! 264: if ((*bpp)->b_flags & B_CALL) { ! 265: brelvp(*bpp); ! 266: free(*bpp, M_SEGMENT); ! 267: } else ! 268: brelse(*bpp); ! 269: lfs_segunlock(fs); ! 270: err1: ! 271: free(start, M_SEGMENT); ! 272: return (error); ! 273: } ! 274: ! 275: /* ! 276: * lfs_bmapv: ! 277: * ! 278: * This will fill in the current disk address for arrays of blocks. ! 279: * ! 280: * 0 on success ! 281: * -1/errno is return on error. ! 282: */ ! 283: int ! 284: lfs_bmapv(p, uap, retval) ! 285: struct proc *p; ! 286: struct lfs_bmapv_args /* { ! 287: syscallarg(fsid_t *) fsidp; ! 288: syscallarg(struct block_info *) blkiov; ! 289: syscallarg(int) blkcnt; ! 290: } */ *uap; ! 291: register_t *retval; ! 292: { ! 293: BLOCK_INFO *blkp; ! 294: struct mount *mntp; ! 295: struct vnode *vp; ! 296: fsid_t fsid; ! 297: void *start; ! 298: daddr_t daddr; ! 299: int cnt, error, step; ! 300: ! 301: if (error = suser(p->p_ucred, &p->p_acflag)) ! 302: return (error); ! 303: ! 304: if (error = copyin(SCARG(uap, fsidp), &fsid, sizeof(fsid_t))) ! 305: return (error); ! 306: if ((mntp = getvfs(&fsid)) == NULL) ! 307: return (EINVAL); ! 308: ! 309: cnt = SCARG(uap, blkcnt); ! 310: // start = blkp = malloc(cnt * sizeof(BLOCK_INFO), M_SEGMENT, M_WAITOK); ! 311: MALLOC(blkp, BLOCK_INFO *, cnt * sizeof(BLOCK_INFO), M_SEGMENT, M_WAITOK); ! 312: start = blkp; ! 313: if (error = copyin(SCARG(uap, blkiov), blkp, ! 314: cnt * sizeof(BLOCK_INFO))) { ! 315: free(blkp, M_SEGMENT); ! 316: return (error); ! 317: } ! 318: ! 319: for (step = cnt; step--; ++blkp) { ! 320: if (blkp->bi_lbn == LFS_UNUSED_LBN) ! 321: continue; ! 322: /* Could be a deadlock ? */ ! 323: if (VFS_VGET(mntp, blkp->bi_inode, &vp)) ! 324: daddr = LFS_UNUSED_DADDR; ! 325: else { ! 326: if (VOP_BMAP(vp, blkp->bi_lbn, NULL, &daddr, NULL)) ! 327: daddr = LFS_UNUSED_DADDR; ! 328: vput(vp); ! 329: } ! 330: blkp->bi_daddr = daddr; ! 331: } ! 332: copyout(start, SCARG(uap, blkiov), cnt * sizeof(BLOCK_INFO)); ! 333: free(start, M_SEGMENT); ! 334: return (0); ! 335: } ! 336: ! 337: /* ! 338: * lfs_segclean: ! 339: * ! 340: * Mark the segment clean. ! 341: * ! 342: * 0 on success ! 343: * -1/errno is return on error. ! 344: */ ! 345: int ! 346: lfs_segclean(p, uap, retval) ! 347: struct proc *p; ! 348: struct lfs_segclean_args /* { ! 349: syscallarg(fsid_t *) fsidp; ! 350: syscallarg(u_long) segment; ! 351: } */ *uap; ! 352: register_t *retval; ! 353: { ! 354: CLEANERINFO *cip; ! 355: SEGUSE *sup; ! 356: struct buf *bp; ! 357: struct mount *mntp; ! 358: struct lfs *fs; ! 359: fsid_t fsid; ! 360: int error; ! 361: ! 362: if (error = suser(p->p_ucred, &p->p_acflag)) ! 363: return (error); ! 364: ! 365: if (error = copyin(SCARG(uap, fsidp), &fsid, sizeof(fsid_t))) ! 366: return (error); ! 367: if ((mntp = getvfs(&fsid)) == NULL) ! 368: return (EINVAL); ! 369: ! 370: fs = VFSTOUFS(mntp)->um_lfs; ! 371: ! 372: if (datosn(fs, fs->lfs_curseg) == SCARG(uap, segment)) ! 373: return (EBUSY); ! 374: ! 375: LFS_SEGENTRY(sup, fs, SCARG(uap, segment), bp); ! 376: if (sup->su_flags & SEGUSE_ACTIVE) { ! 377: brelse(bp); ! 378: return (EBUSY); ! 379: } ! 380: fs->lfs_avail += fsbtodb(fs, fs->lfs_ssize) - 1; ! 381: fs->lfs_bfree += (sup->su_nsums * LFS_SUMMARY_SIZE / DEV_BSIZE) + ! 382: sup->su_ninos * btodb(fs->lfs_bsize); ! 383: sup->su_flags &= ~SEGUSE_DIRTY; ! 384: (void) VOP_BWRITE(bp); ! 385: ! 386: LFS_CLEANERINFO(cip, fs, bp); ! 387: ++cip->clean; ! 388: --cip->dirty; ! 389: (void) VOP_BWRITE(bp); ! 390: wakeup(&fs->lfs_avail); ! 391: return (0); ! 392: } ! 393: ! 394: /* ! 395: * lfs_segwait: ! 396: * ! 397: * This will block until a segment in file system fsid is written. A timeout ! 398: * in milliseconds may be specified which will awake the cleaner automatically. ! 399: * An fsid of -1 means any file system, and a timeout of 0 means forever. ! 400: * ! 401: * 0 on success ! 402: * 1 on timeout ! 403: * -1/errno is return on error. ! 404: */ ! 405: int ! 406: lfs_segwait(p, uap, retval) ! 407: struct proc *p; ! 408: struct lfs_segwait_args /* { ! 409: syscallarg(fsid_t *) fsidp; ! 410: syscallarg(struct timeval *) tv; ! 411: } */ *uap; ! 412: register_t *retval; ! 413: { ! 414: extern int lfs_allclean_wakeup; ! 415: struct mount *mntp; ! 416: struct timeval atv; ! 417: fsid_t fsid; ! 418: void *addr; ! 419: u_long timeout; ! 420: int error, s; ! 421: ! 422: if (error = suser(p->p_ucred, &p->p_acflag)) { ! 423: return (error); ! 424: } ! 425: #ifdef WHEN_QUADS_WORK ! 426: if (error = copyin(SCARG(uap, fsidp), &fsid, sizeof(fsid_t))) ! 427: return (error); ! 428: if (fsid == (fsid_t)-1) ! 429: addr = &lfs_allclean_wakeup; ! 430: else { ! 431: if ((mntp = getvfs(&fsid)) == NULL) ! 432: return (EINVAL); ! 433: addr = &VFSTOUFS(mntp)->um_lfs->lfs_nextseg; ! 434: } ! 435: #else ! 436: if (error = copyin(SCARG(uap, fsidp), &fsid, sizeof(fsid_t))) ! 437: return (error); ! 438: if ((mntp = getvfs(&fsid)) == NULL) ! 439: addr = &lfs_allclean_wakeup; ! 440: else ! 441: addr = &VFSTOUFS(mntp)->um_lfs->lfs_nextseg; ! 442: #endif ! 443: ! 444: if (SCARG(uap, tv)) { ! 445: if (error = ! 446: copyin(SCARG(uap, tv), &atv, sizeof(struct timeval))) ! 447: return (error); ! 448: if (itimerfix(&atv)) ! 449: return (EINVAL); ! 450: s = splclock(); ! 451: timeradd(&atv, &time, &atv); ! 452: timeout = hzto(&atv); ! 453: splx(s); ! 454: } else ! 455: timeout = 0; ! 456: ! 457: error = tsleep(addr, PCATCH | PUSER, "segment", timeout); ! 458: return (error == ERESTART ? EINTR : 0); ! 459: } ! 460: ! 461: /* ! 462: * VFS_VGET call specialized for the cleaner. The cleaner already knows the ! 463: * daddr from the ifile, so don't look it up again. If the cleaner is ! 464: * processing IINFO structures, it may have the ondisk inode already, so ! 465: * don't go retrieving it again. ! 466: */ ! 467: int ! 468: lfs_fastvget(mp, ino, daddr, vpp, dinp) ! 469: struct mount *mp; ! 470: ino_t ino; ! 471: daddr_t daddr; ! 472: struct vnode **vpp; ! 473: struct dinode *dinp; ! 474: { ! 475: register struct inode *ip; ! 476: struct vnode *vp; ! 477: struct ufsmount *ump; ! 478: struct buf *bp; ! 479: dev_t dev; ! 480: int error; ! 481: ! 482: ump = VFSTOUFS(mp); ! 483: dev = ump->um_dev; ! 484: /* ! 485: * This is playing fast and loose. Someone may have the inode ! 486: * locked, in which case they are going to be distinctly unhappy ! 487: * if we trash something. ! 488: */ ! 489: if ((*vpp = ufs_ihashlookup(dev, ino)) != NULL) { ! 490: lfs_vref(*vpp); ! 491: if ((*vpp)->v_flag & VXLOCK) ! 492: printf ("Cleaned vnode VXLOCKED\n"); ! 493: ip = VTOI(*vpp); ! 494: if (ip->i_flag & IN_LOCKED) ! 495: printf("cleaned vnode locked\n"); ! 496: if (!(ip->i_flag & IN_MODIFIED)) { ! 497: ++ump->um_lfs->lfs_uinodes; ! 498: ip->i_flag |= IN_MODIFIED; ! 499: } ! 500: ip->i_flag |= IN_MODIFIED; ! 501: return (0); ! 502: } ! 503: ! 504: /* Allocate new vnode/inode. */ ! 505: if (error = lfs_vcreate(mp, ino, &vp)) { ! 506: *vpp = NULL; ! 507: return (error); ! 508: } ! 509: ! 510: /* ! 511: * Put it onto its hash chain and lock it so that other requests for ! 512: * this inode will block if they arrive while we are sleeping waiting ! 513: * for old data structures to be purged or for the contents of the ! 514: * disk portion of this inode to be read. ! 515: */ ! 516: ip = VTOI(vp); ! 517: ufs_ihashins(ip); ! 518: ! 519: /* ! 520: * XXX ! 521: * This may not need to be here, logically it should go down with ! 522: * the i_devvp initialization. ! 523: * Ask Kirk. ! 524: */ ! 525: ip->i_lfs = ump->um_lfs; ! 526: ! 527: /* Read in the disk contents for the inode, copy into the inode. */ ! 528: if (dinp) ! 529: if (error = copyin(dinp, &ip->i_din, sizeof(struct dinode))) ! 530: return (error); ! 531: else { ! 532: if (error = bread(ump->um_devvp, daddr, ! 533: (int)ump->um_lfs->lfs_bsize, NOCRED, &bp)) { ! 534: /* ! 535: * The inode does not contain anything useful, so it ! 536: * would be misleading to leave it on its hash chain. ! 537: * Iput() will return it to the free list. ! 538: */ ! 539: ufs_ihashrem(ip); ! 540: ! 541: /* Unlock and discard unneeded inode. */ ! 542: lfs_vunref(vp); ! 543: brelse(bp); ! 544: *vpp = NULL; ! 545: return (error); ! 546: } ! 547: ip->i_din = ! 548: *lfs_ifind(ump->um_lfs, ino, (struct dinode *)bp->b_data); ! 549: brelse(bp); ! 550: } ! 551: ! 552: /* Inode was just read from user space or disk, make sure it's locked */ ! 553: ip->i_flag |= IN_LOCKED; ! 554: ! 555: /* ! 556: * Initialize the vnode from the inode, check for aliases. In all ! 557: * cases re-init ip, the underlying vnode/inode may have changed. ! 558: */ ! 559: if (error = ufs_vinit(mp, lfs_specop_p, LFS_FIFOOPS, &vp)) { ! 560: lfs_vunref(vp); ! 561: *vpp = NULL; ! 562: return (error); ! 563: } ! 564: /* ! 565: * Finish inode initialization now that aliasing has been resolved. ! 566: */ ! 567: ip->i_devvp = ump->um_devvp; ! 568: ip->i_flag |= IN_MODIFIED; ! 569: ++ump->um_lfs->lfs_uinodes; ! 570: VREF(ip->i_devvp); ! 571: *vpp = vp; ! 572: return (0); ! 573: } ! 574: struct buf * ! 575: lfs_fakebuf(vp, lbn, size, uaddr) ! 576: struct vnode *vp; ! 577: int lbn; ! 578: size_t size; ! 579: caddr_t uaddr; ! 580: { ! 581: struct buf *bp; ! 582: ! 583: bp = lfs_newbuf(vp, lbn, 0); ! 584: bp->b_saveaddr = uaddr; ! 585: bp->b_bufsize = size; ! 586: bp->b_bcount = size; ! 587: bp->b_flags |= B_INVAL; ! 588: return (bp); ! 589: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.