[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.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>