[BACK]Return to ufs_readwrite.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / ufs / ufs

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>