Annotation of src/sys/ufs/ufs/ufs_readwrite.c, Revision 1.74.2.2
1.74.2.2! yamt 1: /* $NetBSD: ufs_readwrite.c,v 1.74.2.1 2007/02/27 16:55:23 yamt 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.74.2.2! yamt 35: __KERNEL_RCSID(1, "$NetBSD: ufs_readwrite.c,v 1.74.2.1 2007/02/27 16:55:23 yamt Exp $");
1.15 mrg 36:
1.1 mycroft 37: #ifdef LFS_READWRITE
1.16 fvdl 38: #define BLKSIZE(a, b, c) blksize(a, b, c)
1.1 mycroft 39: #define FS struct lfs
40: #define I_FS i_lfs
41: #define READ lfs_read
42: #define READ_S "lfs_read"
43: #define WRITE lfs_write
44: #define WRITE_S "lfs_write"
45: #define fs_bsize lfs_bsize
1.57 mycroft 46: #define fs_bmask lfs_bmask
1.1 mycroft 47: #else
48: #define BLKSIZE(a, b, c) blksize(a, b, c)
49: #define FS struct fs
50: #define I_FS i_fs
51: #define READ ffs_read
52: #define READ_S "ffs_read"
53: #define WRITE ffs_write
54: #define WRITE_S "ffs_write"
55: #endif
56:
57: /*
58: * Vnode op for reading.
59: */
60: /* ARGSUSED */
1.8 christos 61: int
1.29 lukem 62: READ(void *v)
1.8 christos 63: {
1.1 mycroft 64: struct vop_read_args /* {
65: struct vnode *a_vp;
66: struct uio *a_uio;
67: int a_ioflag;
1.68 elad 68: kauth_cred_t a_cred;
1.8 christos 69: } */ *ap = v;
1.24 augustss 70: struct vnode *vp;
71: struct inode *ip;
72: struct uio *uio;
1.60 chs 73: struct ufsmount *ump;
74: struct buf *bp;
1.24 augustss 75: FS *fs;
1.28 chs 76: void *win;
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.70 chs 81: int error, flags, ioflag;
1.74.2.1 yamt 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.74 hannken 108: if ((error = fstrans_start(vp->v_mount, FSTRANS_SHARED)) != 0)
1.73 hannken 109: return error;
110:
1.56 mycroft 111: if (uio->uio_offset >= ip->i_size)
1.28 chs 112: goto out;
113:
1.48 perseant 114: #ifdef LFS_READWRITE
115: usepc = (vp->v_type == VREG && ip->i_number != LFS_IFILE_INUM);
116: #else /* !LFS_READWRITE */
1.34 chs 117: usepc = vp->v_type == VREG;
1.48 perseant 118: #endif /* !LFS_READWRITE */
1.34 chs 119: if (usepc) {
1.65 yamt 120: const int advice = IO_ADV_DECODE(ap->a_ioflag);
121:
1.28 chs 122: while (uio->uio_resid > 0) {
1.70 chs 123: if (ioflag & IO_DIRECT) {
124: genfs_directio(vp, uio, ioflag);
125: }
1.51 fvdl 126: bytelen = MIN(ip->i_size - uio->uio_offset,
1.28 chs 127: uio->uio_resid);
128: if (bytelen == 0)
129: break;
130:
1.33 chs 131: win = ubc_alloc(&vp->v_uobj, uio->uio_offset,
1.65 yamt 132: &bytelen, advice, UBC_READ);
1.28 chs 133: error = uiomove(win, bytelen, uio);
1.60 chs 134: flags = UBC_WANT_UNMAP(vp) ? UBC_UNMAP : 0;
135: ubc_release(win, flags);
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;
148: size = BLKSIZE(fs, ip, lbn);
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.1 mycroft 154: error = bread(vp, lbn, size, NOCRED, &bp);
1.33 chs 155: else {
1.1 mycroft 156: int nextsize = BLKSIZE(fs, ip, nextlbn);
157: error = breadn(vp, lbn,
158: size, &nextlbn, &nextsize, 1, NOCRED, &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;
179: brelse(bp);
180: }
181: if (bp != NULL)
182: brelse(bp);
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.20 mycroft 187: if ((ap->a_ioflag & IO_SYNC) == IO_SYNC)
1.64 yamt 188: error = UFS_UPDATE(vp, NULL, NULL, UPDATE_WAIT);
1.18 kleink 189: }
1.73 hannken 190:
191: fstrans_done(vp->v_mount);
1.1 mycroft 192: return (error);
193: }
194:
195: /*
196: * Vnode op for writing.
197: */
1.8 christos 198: int
1.29 lukem 199: WRITE(void *v)
1.8 christos 200: {
1.1 mycroft 201: struct vop_write_args /* {
202: struct vnode *a_vp;
203: struct uio *a_uio;
204: int a_ioflag;
1.68 elad 205: kauth_cred_t a_cred;
1.8 christos 206: } */ *ap = v;
1.24 augustss 207: struct vnode *vp;
208: struct uio *uio;
209: struct inode *ip;
210: FS *fs;
1.1 mycroft 211: struct buf *bp;
1.66 christos 212: struct lwp *l;
1.68 elad 213: kauth_cred_t cred;
1.47 fvdl 214: daddr_t lbn;
1.33 chs 215: off_t osize, origoff, oldoff, preallocoff, endallocoff, nsize;
1.1 mycroft 216: int blkoffset, error, flags, ioflag, resid, size, xfersize;
1.57 mycroft 217: int aflag;
1.60 chs 218: int ubc_alloc_flags, ubc_release_flags;
1.44 jdolecek 219: int extended=0;
1.28 chs 220: void *win;
221: vsize_t bytelen;
1.74.2.1 yamt 222: bool async;
223: bool usepc = false;
1.45 yamt 224: #ifdef LFS_READWRITE
1.74.2.1 yamt 225: bool need_unreserve = false;
1.45 yamt 226: #endif
1.56 mycroft 227: struct ufsmount *ump;
1.1 mycroft 228:
1.33 chs 229: cred = ap->a_cred;
1.1 mycroft 230: ioflag = ap->a_ioflag;
231: uio = ap->a_uio;
232: vp = ap->a_vp;
233: ip = VTOI(vp);
1.56 mycroft 234: ump = ip->i_ump;
1.1 mycroft 235:
1.51 fvdl 236: KASSERT(vp->v_size == ip->i_size);
1.1 mycroft 237: #ifdef DIAGNOSTIC
238: if (uio->uio_rw != UIO_WRITE)
239: panic("%s: mode", WRITE_S);
240: #endif
241:
242: switch (vp->v_type) {
243: case VREG:
244: if (ioflag & IO_APPEND)
1.51 fvdl 245: uio->uio_offset = ip->i_size;
246: if ((ip->i_flags & APPEND) && uio->uio_offset != ip->i_size)
1.1 mycroft 247: return (EPERM);
248: /* FALLTHROUGH */
249: case VLNK:
250: break;
251: case VDIR:
252: if ((ioflag & IO_SYNC) == 0)
253: panic("%s: nonsync dir write", WRITE_S);
254: break;
255: default:
256: panic("%s: type", WRITE_S);
257: }
258:
259: fs = ip->I_FS;
260: if (uio->uio_offset < 0 ||
1.56 mycroft 261: (u_int64_t)uio->uio_offset + uio->uio_resid > ump->um_maxfilesize)
1.1 mycroft 262: return (EFBIG);
1.26 perseant 263: #ifdef LFS_READWRITE
264: /* Disallow writes to the Ifile, even if noschg flag is removed */
265: /* XXX can this go away when the Ifile is no longer in the namespace? */
266: if (vp == fs->lfs_ivnode)
267: return (EPERM);
268: #endif
1.1 mycroft 269: /*
270: * Maybe this should be above the vnode op call, but so long as
271: * file servers have no limits, I don't think it matters.
272: */
1.67 yamt 273: l = curlwp;
1.66 christos 274: if (vp->v_type == VREG && l &&
1.1 mycroft 275: uio->uio_offset + uio->uio_resid >
1.66 christos 276: l->l_proc->p_rlimit[RLIMIT_FSIZE].rlim_cur) {
1.74.2.2! yamt 277: mutex_enter(&proclist_mutex);
1.66 christos 278: psignal(l->l_proc, SIGXFSZ);
1.74.2.2! yamt 279: mutex_exit(&proclist_mutex);
1.1 mycroft 280: return (EFBIG);
281: }
1.42 chs 282: if (uio->uio_resid == 0)
283: return (0);
1.1 mycroft 284:
1.74 hannken 285: if ((error = fstrans_start(vp->v_mount, FSTRANS_SHARED)) != 0)
1.73 hannken 286: return error;
287:
1.39 simonb 288: flags = ioflag & IO_SYNC ? B_SYNC : 0;
1.36 chs 289: async = vp->v_mount->mnt_flag & MNT_ASYNC;
1.41 chs 290: origoff = uio->uio_offset;
1.1 mycroft 291: resid = uio->uio_resid;
1.51 fvdl 292: osize = ip->i_size;
1.28 chs 293: error = 0;
294:
1.50 perseant 295: usepc = vp->v_type == VREG;
1.48 perseant 296: #ifdef LFS_READWRITE
1.74.2.1 yamt 297: async = true;
1.50 perseant 298: lfs_check(vp, LFS_UNUSED_LBN, 0);
1.49 perseant 299: #endif /* !LFS_READWRITE */
1.56 mycroft 300: if (!usepc)
1.28 chs 301: goto bcache;
302:
1.33 chs 303: preallocoff = round_page(blkroundup(fs, MAX(osize, uio->uio_offset)));
304: aflag = ioflag & IO_SYNC ? B_SYNC : 0;
305: nsize = MAX(osize, uio->uio_offset + uio->uio_resid);
306: endallocoff = nsize - blkoff(fs, nsize);
307:
308: /*
309: * if we're increasing the file size, deal with expanding
310: * the fragment if there is one.
311: */
312:
313: if (nsize > osize && lblkno(fs, osize) < NDADDR &&
314: lblkno(fs, osize) != lblkno(fs, nsize) &&
315: blkroundup(fs, osize) != osize) {
1.57 mycroft 316: off_t eob;
317:
318: eob = blkroundup(fs, osize);
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.57 mycroft 323: vp->v_size = eob;
1.38 chs 324: simple_lock(&vp->v_interlock);
1.57 mycroft 325: VOP_PUTPAGES(vp, trunc_page(osize & fs->fs_bmask),
326: round_page(eob), PGO_CLEANIT | PGO_SYNCIO);
1.38 chs 327: }
1.33 chs 328: }
329:
330: ubc_alloc_flags = UBC_WRITE;
1.28 chs 331: while (uio->uio_resid > 0) {
1.74.2.1 yamt 332: bool extending; /* if we're extending a whole block */
1.43 yamt 333: off_t newoff;
334:
1.70 chs 335: if (ioflag & IO_DIRECT) {
336: genfs_directio(vp, uio, ioflag);
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.43 yamt 353: extending = uio->uio_offset >= preallocoff &&
354: uio->uio_offset < endallocoff;
1.28 chs 355:
1.43 yamt 356: if (!extending) {
1.33 chs 357: error = ufs_balloc_range(vp, uio->uio_offset, bytelen,
358: cred, aflag);
1.58 mycroft 359: if (error)
1.33 chs 360: break;
361: ubc_alloc_flags &= ~UBC_FAULTBUSY;
1.35 chs 362: } else {
1.71 yamt 363: genfs_node_wrlock(vp);
1.35 chs 364: error = GOP_ALLOC(vp, uio->uio_offset, bytelen,
1.33 chs 365: aflag, cred);
1.71 yamt 366: genfs_node_unlock(vp);
1.58 mycroft 367: if (error)
1.33 chs 368: break;
369: ubc_alloc_flags |= UBC_FAULTBUSY;
1.28 chs 370: }
371:
1.33 chs 372: /*
373: * copy the data.
374: */
375:
376: win = ubc_alloc(&vp->v_uobj, uio->uio_offset, &bytelen,
1.65 yamt 377: UVM_ADV_NORMAL, ubc_alloc_flags);
1.28 chs 378: error = uiomove(win, bytelen, uio);
1.43 yamt 379: if (error && extending) {
380: /*
381: * if we haven't initialized the pages yet,
382: * do it now. it's safe to use memset here
383: * because we just mapped the pages above.
384: */
385: memset(win, 0, bytelen);
386: }
1.60 chs 387: ubc_release_flags = UBC_WANT_UNMAP(vp) ? UBC_UNMAP : 0;
388: ubc_release(win, ubc_release_flags);
1.33 chs 389:
390: /*
391: * update UVM's notion of the size now that we've
392: * copied the data into the vnode's pages.
1.43 yamt 393: *
394: * we should update the size even when uiomove failed.
395: * otherwise ffs_truncate can't flush soft update states.
1.33 chs 396: */
397:
1.43 yamt 398: newoff = oldoff + bytelen;
399: if (vp->v_size < newoff) {
400: uvm_vnp_setsize(vp, newoff);
1.44 jdolecek 401: extended = 1;
1.43 yamt 402: }
403:
1.56 mycroft 404: if (error)
1.43 yamt 405: break;
1.28 chs 406:
407: /*
408: * flush what we just wrote if necessary.
409: * XXXUBC simplistic async flushing.
410: */
411:
1.69 christos 412: #ifndef LFS_READWRITE
1.36 chs 413: if (!async && oldoff >> 16 != uio->uio_offset >> 16) {
1.38 chs 414: simple_lock(&vp->v_interlock);
415: error = VOP_PUTPAGES(vp, (oldoff >> 16) << 16,
416: (uio->uio_offset >> 16) << 16, PGO_CLEANIT);
1.56 mycroft 417: if (error)
1.33 chs 418: break;
1.28 chs 419: }
1.69 christos 420: #endif
1.33 chs 421: }
422: if (error == 0 && ioflag & IO_SYNC) {
1.38 chs 423: simple_lock(&vp->v_interlock);
1.57 mycroft 424: error = VOP_PUTPAGES(vp, trunc_page(origoff & fs->fs_bmask),
1.40 chs 425: round_page(blkroundup(fs, uio->uio_offset)),
426: PGO_CLEANIT | PGO_SYNCIO);
1.28 chs 427: }
428: goto out;
429:
1.29 lukem 430: bcache:
1.41 chs 431: simple_lock(&vp->v_interlock);
432: VOP_PUTPAGES(vp, trunc_page(origoff), round_page(origoff + resid),
433: PGO_CLEANIT | PGO_FREE | PGO_SYNCIO);
1.28 chs 434: while (uio->uio_resid > 0) {
1.1 mycroft 435: lbn = lblkno(fs, uio->uio_offset);
436: blkoffset = blkoff(fs, uio->uio_offset);
1.30 chs 437: xfersize = MIN(fs->fs_bsize - blkoffset, uio->uio_resid);
1.1 mycroft 438: if (fs->fs_bsize > xfersize)
439: flags |= B_CLRBUF;
440: else
441: flags &= ~B_CLRBUF;
442:
1.45 yamt 443: #ifdef LFS_READWRITE
1.46 yamt 444: error = lfs_reserve(fs, vp, NULL,
1.45 yamt 445: btofsb(fs, (NIADDR + 1) << fs->lfs_bshift));
446: if (error)
447: break;
1.74.2.1 yamt 448: need_unreserve = true;
1.45 yamt 449: #endif
1.64 yamt 450: error = UFS_BALLOC(vp, uio->uio_offset, xfersize,
1.23 fvdl 451: ap->a_cred, flags, &bp);
452:
1.1 mycroft 453: if (error)
454: break;
1.51 fvdl 455: if (uio->uio_offset + xfersize > ip->i_size) {
456: ip->i_size = uio->uio_offset + xfersize;
1.52 kristerw 457: DIP_ASSIGN(ip, size, ip->i_size);
1.51 fvdl 458: uvm_vnp_setsize(vp, ip->i_size);
1.44 jdolecek 459: extended = 1;
1.1 mycroft 460: }
461: size = BLKSIZE(fs, ip, lbn) - bp->b_resid;
1.28 chs 462: if (xfersize > size)
1.1 mycroft 463: xfersize = size;
464:
1.28 chs 465: error = uiomove((char *)bp->b_data + blkoffset, xfersize, uio);
466:
467: /*
468: * if we didn't clear the block and the uiomove failed,
469: * the buf will now contain part of some other file,
470: * so we need to invalidate it.
471: */
472: if (error && (flags & B_CLRBUF) == 0) {
473: bp->b_flags |= B_INVAL;
474: brelse(bp);
475: break;
476: }
1.1 mycroft 477: #ifdef LFS_READWRITE
478: (void)VOP_BWRITE(bp);
1.46 yamt 479: lfs_reserve(fs, vp, NULL,
1.45 yamt 480: -btofsb(fs, (NIADDR + 1) << fs->lfs_bshift));
1.74.2.1 yamt 481: need_unreserve = false;
1.1 mycroft 482: #else
483: if (ioflag & IO_SYNC)
484: (void)bwrite(bp);
485: else if (xfersize + blkoffset == fs->fs_bsize)
1.33 chs 486: bawrite(bp);
1.1 mycroft 487: else
488: bdwrite(bp);
489: #endif
490: if (error || xfersize == 0)
491: break;
492: }
1.45 yamt 493: #ifdef LFS_READWRITE
494: if (need_unreserve) {
1.46 yamt 495: lfs_reserve(fs, vp, NULL,
1.45 yamt 496: -btofsb(fs, (NIADDR + 1) << fs->lfs_bshift));
497: }
498: #endif
499:
1.1 mycroft 500: /*
501: * If we successfully wrote any data, and we are not the superuser
502: * we clear the setuid and setgid bits as a precaution against
503: * tampering.
504: */
1.33 chs 505: out:
1.28 chs 506: ip->i_flag |= IN_CHANGE | IN_UPDATE;
1.68 elad 507: if (resid > uio->uio_resid && ap->a_cred &&
1.72 elad 508: kauth_authorize_generic(ap->a_cred, KAUTH_GENERIC_ISSUSER, NULL)) {
1.51 fvdl 509: ip->i_mode &= ~(ISUID | ISGID);
1.52 kristerw 510: DIP_ASSIGN(ip, mode, ip->i_mode);
1.51 fvdl 511: }
1.44 jdolecek 512: if (resid > uio->uio_resid)
513: VN_KNOTE(vp, NOTE_WRITE | (extended ? NOTE_EXTEND : 0));
1.1 mycroft 514: if (error) {
1.64 yamt 515: (void) UFS_TRUNCATE(vp, osize, ioflag & IO_SYNC, ap->a_cred,
1.67 yamt 516: curlwp);
1.33 chs 517: uio->uio_offset -= resid - uio->uio_resid;
518: uio->uio_resid = resid;
1.20 mycroft 519: } else if (resid > uio->uio_resid && (ioflag & IO_SYNC) == IO_SYNC)
1.64 yamt 520: error = UFS_UPDATE(vp, NULL, NULL, UPDATE_WAIT);
1.51 fvdl 521: KASSERT(vp->v_size == ip->i_size);
1.73 hannken 522:
523: fstrans_done(vp->v_mount);
524:
1.1 mycroft 525: return (error);
526: }
CVSweb <webmaster@jp.NetBSD.org>