Annotation of src/sys/ufs/ufs/ufs_readwrite.c, Revision 1.98
1.98 ! rmind 1: /* $NetBSD: ufs_readwrite.c,v 1.97 2011/06/12 03:36:02 rmind Exp $ */
1.3 cgd 2:
1.1 mycroft 3: /*-
4: * Copyright (c) 1993
5: * The Regents of the University of California. All rights reserved.
6: *
7: * Redistribution and use in source and binary forms, with or without
8: * modification, are permitted provided that the following conditions
9: * are met:
10: * 1. Redistributions of source code must retain the above copyright
11: * notice, this list of conditions and the following disclaimer.
12: * 2. Redistributions in binary form must reproduce the above copyright
13: * notice, this list of conditions and the following disclaimer in the
14: * documentation and/or other materials provided with the distribution.
1.55 agc 15: * 3. Neither the name of the University nor the names of its contributors
1.1 mycroft 16: * may be used to endorse or promote products derived from this software
17: * without specific prior written permission.
18: *
19: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29: * SUCH DAMAGE.
30: *
1.16 fvdl 31: * @(#)ufs_readwrite.c 8.11 (Berkeley) 5/8/95
1.1 mycroft 32: */
1.37 lukem 33:
34: #include <sys/cdefs.h>
1.98 ! rmind 35: __KERNEL_RCSID(1, "$NetBSD: ufs_readwrite.c,v 1.97 2011/06/12 03:36:02 rmind Exp $");
1.15 mrg 36:
1.1 mycroft 37: #ifdef LFS_READWRITE
38: #define FS struct lfs
39: #define I_FS i_lfs
40: #define READ lfs_read
41: #define READ_S "lfs_read"
42: #define WRITE lfs_write
43: #define WRITE_S "lfs_write"
44: #define fs_bsize lfs_bsize
1.57 mycroft 45: #define fs_bmask lfs_bmask
1.89 simonb 46: #define UFS_WAPBL_BEGIN(mp) 0
47: #define UFS_WAPBL_END(mp) do { } while (0)
48: #define UFS_WAPBL_UPDATE(vp, access, modify, flags) do { } while (0)
1.1 mycroft 49: #else
50: #define FS struct fs
51: #define I_FS i_fs
52: #define READ ffs_read
53: #define READ_S "ffs_read"
54: #define WRITE ffs_write
55: #define WRITE_S "ffs_write"
56: #endif
57:
58: /*
59: * Vnode op for reading.
60: */
61: /* ARGSUSED */
1.8 christos 62: int
1.29 lukem 63: READ(void *v)
1.8 christos 64: {
1.1 mycroft 65: struct vop_read_args /* {
66: struct vnode *a_vp;
67: struct uio *a_uio;
68: int a_ioflag;
1.68 elad 69: kauth_cred_t a_cred;
1.8 christos 70: } */ *ap = v;
1.24 augustss 71: struct vnode *vp;
72: struct inode *ip;
73: struct uio *uio;
1.60 chs 74: struct ufsmount *ump;
75: struct buf *bp;
1.24 augustss 76: FS *fs;
1.28 chs 77: vsize_t bytelen;
1.47 fvdl 78: daddr_t lbn, nextlbn;
1.1 mycroft 79: off_t bytesinfile;
80: long size, xfersize, blkoffset;
1.81 yamt 81: int error, ioflag;
1.76 thorpej 82: bool usepc = false;
1.1 mycroft 83:
84: vp = ap->a_vp;
85: ip = VTOI(vp);
1.56 mycroft 86: ump = ip->i_ump;
1.1 mycroft 87: uio = ap->a_uio;
1.70 chs 88: ioflag = ap->a_ioflag;
1.28 chs 89: error = 0;
1.1 mycroft 90:
91: #ifdef DIAGNOSTIC
92: if (uio->uio_rw != UIO_READ)
93: panic("%s: mode", READ_S);
94:
95: if (vp->v_type == VLNK) {
1.56 mycroft 96: if (ip->i_size < ump->um_maxsymlinklen ||
97: (ump->um_maxsymlinklen == 0 && DIP(ip, blocks) == 0))
1.1 mycroft 98: panic("%s: short symlink", READ_S);
99: } else if (vp->v_type != VREG && vp->v_type != VDIR)
100: panic("%s: type %d", READ_S, vp->v_type);
101: #endif
102: fs = ip->I_FS;
1.56 mycroft 103: if ((u_int64_t)uio->uio_offset > ump->um_maxfilesize)
1.1 mycroft 104: return (EFBIG);
1.11 kleink 105: if (uio->uio_resid == 0)
106: return (0);
1.73 hannken 107:
1.90 hannken 108: #ifndef LFS_READWRITE
1.96 bouyer 109: if ((ip->i_flags & (SF_SNAPSHOT | SF_SNAPINVAL)) == SF_SNAPSHOT)
1.90 hannken 110: return ffs_snapshot_read(vp, uio, ioflag);
111: #endif /* !LFS_READWRITE */
112:
1.78 hannken 113: fstrans_start(vp->v_mount, FSTRANS_SHARED);
1.73 hannken 114:
1.56 mycroft 115: if (uio->uio_offset >= ip->i_size)
1.28 chs 116: goto out;
117:
1.48 perseant 118: #ifdef LFS_READWRITE
119: usepc = (vp->v_type == VREG && ip->i_number != LFS_IFILE_INUM);
120: #else /* !LFS_READWRITE */
1.34 chs 121: usepc = vp->v_type == VREG;
1.48 perseant 122: #endif /* !LFS_READWRITE */
1.34 chs 123: if (usepc) {
1.65 yamt 124: const int advice = IO_ADV_DECODE(ap->a_ioflag);
125:
1.28 chs 126: while (uio->uio_resid > 0) {
1.70 chs 127: if (ioflag & IO_DIRECT) {
128: genfs_directio(vp, uio, ioflag);
129: }
1.51 fvdl 130: bytelen = MIN(ip->i_size - uio->uio_offset,
1.28 chs 131: uio->uio_resid);
132: if (bytelen == 0)
133: break;
1.81 yamt 134: error = ubc_uiomove(&vp->v_uobj, uio, bytelen, advice,
1.98 ! rmind 135: UBC_READ | UBC_PARTIALOK | UBC_UNMAP_FLAG(vp));
1.28 chs 136: if (error)
137: break;
138: }
139: goto out;
140: }
1.1 mycroft 141:
142: for (error = 0, bp = NULL; uio->uio_resid > 0; bp = NULL) {
1.51 fvdl 143: bytesinfile = ip->i_size - uio->uio_offset;
1.28 chs 144: if (bytesinfile <= 0)
1.1 mycroft 145: break;
146: lbn = lblkno(fs, uio->uio_offset);
147: nextlbn = lbn + 1;
1.82 pooka 148: size = blksize(fs, ip, lbn);
1.1 mycroft 149: blkoffset = blkoff(fs, uio->uio_offset);
1.30 chs 150: xfersize = MIN(MIN(fs->fs_bsize - blkoffset, uio->uio_resid),
1.28 chs 151: bytesinfile);
1.1 mycroft 152:
1.51 fvdl 153: if (lblktosize(fs, nextlbn) >= ip->i_size)
1.88 hannken 154: error = bread(vp, lbn, size, NOCRED, 0, &bp);
1.33 chs 155: else {
1.82 pooka 156: int nextsize = blksize(fs, ip, nextlbn);
1.1 mycroft 157: error = breadn(vp, lbn,
1.88 hannken 158: size, &nextlbn, &nextsize, 1, NOCRED, 0, &bp);
1.33 chs 159: }
1.1 mycroft 160: if (error)
161: break;
162:
163: /*
164: * We should only get non-zero b_resid when an I/O error
165: * has occurred, which should cause us to break above.
166: * However, if the short read did not cause an error,
167: * then we want to ensure that we do not uiomove bad
168: * or uninitialized data.
169: */
170: size -= bp->b_resid;
171: if (size < xfersize) {
172: if (size == 0)
173: break;
174: xfersize = size;
175: }
1.28 chs 176: error = uiomove((char *)bp->b_data + blkoffset, xfersize, uio);
1.8 christos 177: if (error)
1.1 mycroft 178: break;
1.83 ad 179: brelse(bp, 0);
1.1 mycroft 180: }
181: if (bp != NULL)
1.83 ad 182: brelse(bp, 0);
1.28 chs 183:
1.29 lukem 184: out:
1.18 kleink 185: if (!(vp->v_mount->mnt_flag & MNT_NOATIME)) {
1.10 tls 186: ip->i_flag |= IN_ACCESS;
1.89 simonb 187: if ((ap->a_ioflag & IO_SYNC) == IO_SYNC) {
188: error = UFS_WAPBL_BEGIN(vp->v_mount);
189: if (error) {
190: fstrans_done(vp->v_mount);
191: return error;
192: }
1.64 yamt 193: error = UFS_UPDATE(vp, NULL, NULL, UPDATE_WAIT);
1.89 simonb 194: UFS_WAPBL_END(vp->v_mount);
195: }
1.18 kleink 196: }
1.73 hannken 197:
198: fstrans_done(vp->v_mount);
1.1 mycroft 199: return (error);
200: }
201:
202: /*
203: * Vnode op for writing.
204: */
1.8 christos 205: int
1.29 lukem 206: WRITE(void *v)
1.8 christos 207: {
1.1 mycroft 208: struct vop_write_args /* {
209: struct vnode *a_vp;
210: struct uio *a_uio;
211: int a_ioflag;
1.68 elad 212: kauth_cred_t a_cred;
1.8 christos 213: } */ *ap = v;
1.24 augustss 214: struct vnode *vp;
215: struct uio *uio;
216: struct inode *ip;
217: FS *fs;
1.1 mycroft 218: struct buf *bp;
1.68 elad 219: kauth_cred_t cred;
1.47 fvdl 220: daddr_t lbn;
1.33 chs 221: off_t osize, origoff, oldoff, preallocoff, endallocoff, nsize;
1.1 mycroft 222: int blkoffset, error, flags, ioflag, resid, size, xfersize;
1.57 mycroft 223: int aflag;
1.44 jdolecek 224: int extended=0;
1.28 chs 225: vsize_t bytelen;
1.75 thorpej 226: bool async;
1.76 thorpej 227: bool usepc = false;
1.45 yamt 228: #ifdef LFS_READWRITE
1.76 thorpej 229: bool need_unreserve = false;
1.45 yamt 230: #endif
1.56 mycroft 231: struct ufsmount *ump;
1.1 mycroft 232:
1.33 chs 233: cred = ap->a_cred;
1.1 mycroft 234: ioflag = ap->a_ioflag;
235: uio = ap->a_uio;
236: vp = ap->a_vp;
237: ip = VTOI(vp);
1.56 mycroft 238: ump = ip->i_ump;
1.1 mycroft 239:
1.51 fvdl 240: KASSERT(vp->v_size == ip->i_size);
1.1 mycroft 241: #ifdef DIAGNOSTIC
242: if (uio->uio_rw != UIO_WRITE)
243: panic("%s: mode", WRITE_S);
244: #endif
245:
246: switch (vp->v_type) {
247: case VREG:
248: if (ioflag & IO_APPEND)
1.51 fvdl 249: uio->uio_offset = ip->i_size;
250: if ((ip->i_flags & APPEND) && uio->uio_offset != ip->i_size)
1.1 mycroft 251: return (EPERM);
252: /* FALLTHROUGH */
253: case VLNK:
254: break;
255: case VDIR:
256: if ((ioflag & IO_SYNC) == 0)
257: panic("%s: nonsync dir write", WRITE_S);
258: break;
259: default:
260: panic("%s: type", WRITE_S);
261: }
262:
263: fs = ip->I_FS;
264: if (uio->uio_offset < 0 ||
1.56 mycroft 265: (u_int64_t)uio->uio_offset + uio->uio_resid > ump->um_maxfilesize)
1.1 mycroft 266: return (EFBIG);
1.26 perseant 267: #ifdef LFS_READWRITE
268: /* Disallow writes to the Ifile, even if noschg flag is removed */
269: /* XXX can this go away when the Ifile is no longer in the namespace? */
270: if (vp == fs->lfs_ivnode)
271: return (EPERM);
272: #endif
1.42 chs 273: if (uio->uio_resid == 0)
274: return (0);
1.1 mycroft 275:
1.78 hannken 276: fstrans_start(vp->v_mount, FSTRANS_SHARED);
1.73 hannken 277:
1.39 simonb 278: flags = ioflag & IO_SYNC ? B_SYNC : 0;
1.36 chs 279: async = vp->v_mount->mnt_flag & MNT_ASYNC;
1.41 chs 280: origoff = uio->uio_offset;
1.1 mycroft 281: resid = uio->uio_resid;
1.51 fvdl 282: osize = ip->i_size;
1.28 chs 283: error = 0;
284:
1.50 perseant 285: usepc = vp->v_type == VREG;
1.89 simonb 286:
287: if ((ioflag & IO_JOURNALLOCKED) == 0) {
288: error = UFS_WAPBL_BEGIN(vp->v_mount);
289: if (error) {
290: fstrans_done(vp->v_mount);
291: return error;
292: }
293: }
294:
1.48 perseant 295: #ifdef LFS_READWRITE
1.76 thorpej 296: async = true;
1.50 perseant 297: lfs_check(vp, LFS_UNUSED_LBN, 0);
1.49 perseant 298: #endif /* !LFS_READWRITE */
1.56 mycroft 299: if (!usepc)
1.28 chs 300: goto bcache;
301:
1.33 chs 302: preallocoff = round_page(blkroundup(fs, MAX(osize, uio->uio_offset)));
303: aflag = ioflag & IO_SYNC ? B_SYNC : 0;
304: nsize = MAX(osize, uio->uio_offset + uio->uio_resid);
305: endallocoff = nsize - blkoff(fs, nsize);
306:
307: /*
308: * if we're increasing the file size, deal with expanding
309: * the fragment if there is one.
310: */
311:
312: if (nsize > osize && lblkno(fs, osize) < NDADDR &&
313: lblkno(fs, osize) != lblkno(fs, nsize) &&
314: blkroundup(fs, osize) != osize) {
1.57 mycroft 315: off_t eob;
316:
317: eob = blkroundup(fs, osize);
1.79 yamt 318: uvm_vnp_setwritesize(vp, eob);
1.57 mycroft 319: error = ufs_balloc_range(vp, osize, eob - osize, cred, aflag);
320: if (error)
1.33 chs 321: goto out;
1.38 chs 322: if (flags & B_SYNC) {
1.97 rmind 323: mutex_enter(vp->v_interlock);
1.57 mycroft 324: VOP_PUTPAGES(vp, trunc_page(osize & fs->fs_bmask),
1.91 hannken 325: round_page(eob),
326: PGO_CLEANIT | PGO_SYNCIO | PGO_JOURNALLOCKED);
1.38 chs 327: }
1.33 chs 328: }
329:
1.28 chs 330: while (uio->uio_resid > 0) {
1.79 yamt 331: int ubc_flags = UBC_WRITE;
332: bool overwrite; /* if we're overwrite a whole block */
1.43 yamt 333: off_t newoff;
334:
1.70 chs 335: if (ioflag & IO_DIRECT) {
1.92 hannken 336: genfs_directio(vp, uio, ioflag | IO_JOURNALLOCKED);
1.70 chs 337: }
338:
1.28 chs 339: oldoff = uio->uio_offset;
340: blkoffset = blkoff(fs, uio->uio_offset);
1.30 chs 341: bytelen = MIN(fs->fs_bsize - blkoffset, uio->uio_resid);
1.70 chs 342: if (bytelen == 0) {
343: break;
344: }
1.28 chs 345:
346: /*
1.33 chs 347: * if we're filling in a hole, allocate the blocks now and
348: * initialize the pages first. if we're extending the file,
349: * we can safely allocate blocks without initializing pages
350: * since the new blocks will be inaccessible until the write
351: * is complete.
1.28 chs 352: */
1.79 yamt 353: overwrite = uio->uio_offset >= preallocoff &&
1.43 yamt 354: uio->uio_offset < endallocoff;
1.84 ad 355: if (!overwrite && (vp->v_vflag & VV_MAPPED) == 0 &&
1.79 yamt 356: blkoff(fs, uio->uio_offset) == 0 &&
357: (uio->uio_offset & PAGE_MASK) == 0) {
358: vsize_t len;
359:
360: len = trunc_page(bytelen);
361: len -= blkoff(fs, len);
362: if (len > 0) {
363: overwrite = true;
364: bytelen = len;
365: }
366: }
1.28 chs 367:
1.79 yamt 368: newoff = oldoff + bytelen;
369: if (vp->v_size < newoff) {
370: uvm_vnp_setwritesize(vp, newoff);
371: }
372:
373: if (!overwrite) {
1.33 chs 374: error = ufs_balloc_range(vp, uio->uio_offset, bytelen,
375: cred, aflag);
1.58 mycroft 376: if (error)
1.33 chs 377: break;
1.35 chs 378: } else {
1.71 yamt 379: genfs_node_wrlock(vp);
1.35 chs 380: error = GOP_ALLOC(vp, uio->uio_offset, bytelen,
1.33 chs 381: aflag, cred);
1.71 yamt 382: genfs_node_unlock(vp);
1.58 mycroft 383: if (error)
1.33 chs 384: break;
1.79 yamt 385: ubc_flags |= UBC_FAULTBUSY;
1.28 chs 386: }
387:
1.33 chs 388: /*
389: * copy the data.
390: */
391:
1.93 pooka 392: error = ubc_uiomove(&vp->v_uobj, uio, bytelen,
1.98 ! rmind 393: IO_ADV_DECODE(ioflag), ubc_flags | UBC_UNMAP_FLAG(vp));
1.33 chs 394:
395: /*
396: * update UVM's notion of the size now that we've
397: * copied the data into the vnode's pages.
1.43 yamt 398: *
399: * we should update the size even when uiomove failed.
1.33 chs 400: */
401:
1.43 yamt 402: if (vp->v_size < newoff) {
403: uvm_vnp_setsize(vp, newoff);
1.44 jdolecek 404: extended = 1;
1.43 yamt 405: }
406:
1.56 mycroft 407: if (error)
1.43 yamt 408: break;
1.28 chs 409:
410: /*
411: * flush what we just wrote if necessary.
412: * XXXUBC simplistic async flushing.
413: */
414:
1.69 christos 415: #ifndef LFS_READWRITE
1.36 chs 416: if (!async && oldoff >> 16 != uio->uio_offset >> 16) {
1.97 rmind 417: mutex_enter(vp->v_interlock);
1.38 chs 418: error = VOP_PUTPAGES(vp, (oldoff >> 16) << 16,
1.91 hannken 419: (uio->uio_offset >> 16) << 16,
420: PGO_CLEANIT | PGO_JOURNALLOCKED);
1.56 mycroft 421: if (error)
1.33 chs 422: break;
1.28 chs 423: }
1.69 christos 424: #endif
1.33 chs 425: }
426: if (error == 0 && ioflag & IO_SYNC) {
1.97 rmind 427: mutex_enter(vp->v_interlock);
1.57 mycroft 428: error = VOP_PUTPAGES(vp, trunc_page(origoff & fs->fs_bmask),
1.40 chs 429: round_page(blkroundup(fs, uio->uio_offset)),
1.91 hannken 430: PGO_CLEANIT | PGO_SYNCIO | PGO_JOURNALLOCKED);
1.28 chs 431: }
432: goto out;
433:
1.29 lukem 434: bcache:
1.97 rmind 435: mutex_enter(vp->v_interlock);
1.41 chs 436: VOP_PUTPAGES(vp, trunc_page(origoff), round_page(origoff + resid),
1.91 hannken 437: PGO_CLEANIT | PGO_FREE | PGO_SYNCIO | PGO_JOURNALLOCKED);
1.28 chs 438: while (uio->uio_resid > 0) {
1.1 mycroft 439: lbn = lblkno(fs, uio->uio_offset);
440: blkoffset = blkoff(fs, uio->uio_offset);
1.30 chs 441: xfersize = MIN(fs->fs_bsize - blkoffset, uio->uio_resid);
1.1 mycroft 442: if (fs->fs_bsize > xfersize)
443: flags |= B_CLRBUF;
444: else
445: flags &= ~B_CLRBUF;
446:
1.45 yamt 447: #ifdef LFS_READWRITE
1.46 yamt 448: error = lfs_reserve(fs, vp, NULL,
1.45 yamt 449: btofsb(fs, (NIADDR + 1) << fs->lfs_bshift));
450: if (error)
451: break;
1.76 thorpej 452: need_unreserve = true;
1.45 yamt 453: #endif
1.64 yamt 454: error = UFS_BALLOC(vp, uio->uio_offset, xfersize,
1.23 fvdl 455: ap->a_cred, flags, &bp);
456:
1.1 mycroft 457: if (error)
458: break;
1.51 fvdl 459: if (uio->uio_offset + xfersize > ip->i_size) {
460: ip->i_size = uio->uio_offset + xfersize;
1.52 kristerw 461: DIP_ASSIGN(ip, size, ip->i_size);
1.51 fvdl 462: uvm_vnp_setsize(vp, ip->i_size);
1.44 jdolecek 463: extended = 1;
1.1 mycroft 464: }
1.82 pooka 465: size = blksize(fs, ip, lbn) - bp->b_resid;
1.28 chs 466: if (xfersize > size)
1.1 mycroft 467: xfersize = size;
468:
1.28 chs 469: error = uiomove((char *)bp->b_data + blkoffset, xfersize, uio);
470:
471: /*
472: * if we didn't clear the block and the uiomove failed,
473: * the buf will now contain part of some other file,
474: * so we need to invalidate it.
475: */
476: if (error && (flags & B_CLRBUF) == 0) {
1.83 ad 477: brelse(bp, BC_INVAL);
1.28 chs 478: break;
479: }
1.1 mycroft 480: #ifdef LFS_READWRITE
481: (void)VOP_BWRITE(bp);
1.46 yamt 482: lfs_reserve(fs, vp, NULL,
1.45 yamt 483: -btofsb(fs, (NIADDR + 1) << fs->lfs_bshift));
1.76 thorpej 484: need_unreserve = false;
1.1 mycroft 485: #else
486: if (ioflag & IO_SYNC)
487: (void)bwrite(bp);
488: else if (xfersize + blkoffset == fs->fs_bsize)
1.33 chs 489: bawrite(bp);
1.1 mycroft 490: else
491: bdwrite(bp);
492: #endif
493: if (error || xfersize == 0)
494: break;
495: }
1.45 yamt 496: #ifdef LFS_READWRITE
497: if (need_unreserve) {
1.46 yamt 498: lfs_reserve(fs, vp, NULL,
1.45 yamt 499: -btofsb(fs, (NIADDR + 1) << fs->lfs_bshift));
500: }
501: #endif
502:
1.1 mycroft 503: /*
504: * If we successfully wrote any data, and we are not the superuser
505: * we clear the setuid and setgid bits as a precaution against
506: * tampering.
507: */
1.33 chs 508: out:
1.28 chs 509: ip->i_flag |= IN_CHANGE | IN_UPDATE;
1.68 elad 510: if (resid > uio->uio_resid && ap->a_cred &&
1.72 elad 511: kauth_authorize_generic(ap->a_cred, KAUTH_GENERIC_ISSUSER, NULL)) {
1.51 fvdl 512: ip->i_mode &= ~(ISUID | ISGID);
1.52 kristerw 513: DIP_ASSIGN(ip, mode, ip->i_mode);
1.51 fvdl 514: }
1.44 jdolecek 515: if (resid > uio->uio_resid)
516: VN_KNOTE(vp, NOTE_WRITE | (extended ? NOTE_EXTEND : 0));
1.1 mycroft 517: if (error) {
1.85 pooka 518: (void) UFS_TRUNCATE(vp, osize, ioflag & IO_SYNC, ap->a_cred);
1.33 chs 519: uio->uio_offset -= resid - uio->uio_resid;
520: uio->uio_resid = resid;
1.20 mycroft 521: } else if (resid > uio->uio_resid && (ioflag & IO_SYNC) == IO_SYNC)
1.64 yamt 522: error = UFS_UPDATE(vp, NULL, NULL, UPDATE_WAIT);
1.89 simonb 523: else
524: UFS_WAPBL_UPDATE(vp, NULL, NULL, 0);
1.51 fvdl 525: KASSERT(vp->v_size == ip->i_size);
1.89 simonb 526: if ((ioflag & IO_JOURNALLOCKED) == 0)
527: UFS_WAPBL_END(vp->v_mount);
1.73 hannken 528: fstrans_done(vp->v_mount);
529:
1.1 mycroft 530: return (error);
531: }
CVSweb <webmaster@jp.NetBSD.org>