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

1.31.2.1! perseant    1: /*     $NetBSD: ufs_readwrite.c,v 1.31 2001/03/26 06:47:34 chs 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.
                     15:  * 3. All advertising materials mentioning features or use of this software
                     16:  *    must display the following acknowledgement:
                     17:  *     This product includes software developed by the University of
                     18:  *     California, Berkeley and its contributors.
                     19:  * 4. Neither the name of the University nor the names of its contributors
                     20:  *    may be used to endorse or promote products derived from this software
                     21:  *    without specific prior written permission.
                     22:  *
                     23:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     24:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     25:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     26:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     27:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     28:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     29:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     30:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     31:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     32:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     33:  * SUCH DAMAGE.
                     34:  *
1.16      fvdl       35:  *     @(#)ufs_readwrite.c     8.11 (Berkeley) 5/8/95
1.1       mycroft    36:  */
1.15      mrg        37:
1.1       mycroft    38: #ifdef LFS_READWRITE
1.16      fvdl       39: #define        BLKSIZE(a, b, c)        blksize(a, b, c)
1.1       mycroft    40: #define        FS                      struct lfs
                     41: #define        I_FS                    i_lfs
                     42: #define        READ                    lfs_read
                     43: #define        READ_S                  "lfs_read"
                     44: #define        WRITE                   lfs_write
                     45: #define        WRITE_S                 "lfs_write"
                     46: #define        fs_bsize                lfs_bsize
                     47: #define        fs_maxfilesize          lfs_maxfilesize
                     48: #else
                     49: #define        BLKSIZE(a, b, c)        blksize(a, b, c)
                     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;
                     69:                struct ucred *a_cred;
1.8       christos   70:        } */ *ap = v;
1.24      augustss   71:        struct vnode *vp;
                     72:        struct inode *ip;
                     73:        struct uio *uio;
                     74:        FS *fs;
1.28      chs        75: #ifndef LFS_READWRITE
                     76:        void *win;
                     77:        vsize_t bytelen;
                     78: #endif
1.1       mycroft    79:        struct buf *bp;
1.16      fvdl       80:        ufs_daddr_t lbn, nextlbn;
1.1       mycroft    81:        off_t bytesinfile;
                     82:        long size, xfersize, blkoffset;
                     83:        int error;
                     84:
                     85:        vp = ap->a_vp;
                     86:        ip = VTOI(vp);
                     87:        uio = ap->a_uio;
1.28      chs        88:        error = 0;
1.1       mycroft    89:
                     90: #ifdef DIAGNOSTIC
                     91:        if (uio->uio_rw != UIO_READ)
                     92:                panic("%s: mode", READ_S);
                     93:
                     94:        if (vp->v_type == VLNK) {
1.12      bouyer     95:                if ((int)ip->i_ffs_size < vp->v_mount->mnt_maxsymlinklen ||
1.2       mycroft    96:                    (vp->v_mount->mnt_maxsymlinklen == 0 &&
1.12      bouyer     97:                     ip->i_ffs_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.4       cgd       103:        if ((u_int64_t)uio->uio_offset > fs->fs_maxfilesize)
1.1       mycroft   104:                return (EFBIG);
1.11      kleink    105:        if (uio->uio_resid == 0)
                    106:                return (0);
1.28      chs       107:        if (uio->uio_offset >= ip->i_ffs_size) {
                    108:                goto out;
                    109:        }
                    110:
                    111: #ifndef LFS_READWRITE
                    112:        if (vp->v_type == VREG) {
                    113:                while (uio->uio_resid > 0) {
1.30      chs       114:                        bytelen = MIN(ip->i_ffs_size - uio->uio_offset,
1.28      chs       115:                            uio->uio_resid);
                    116:                        if (bytelen == 0)
                    117:                                break;
                    118:
                    119:                        win = ubc_alloc(&vp->v_uvm.u_obj, uio->uio_offset,
                    120:                                        &bytelen, UBC_READ);
                    121:                        error = uiomove(win, bytelen, uio);
                    122:                        ubc_release(win, 0);
                    123:                        if (error)
                    124:                                break;
                    125:                }
                    126:                goto out;
                    127:        }
                    128: #endif
1.1       mycroft   129:
                    130:        for (error = 0, bp = NULL; uio->uio_resid > 0; bp = NULL) {
1.28      chs       131:                bytesinfile = ip->i_ffs_size - uio->uio_offset;
                    132:                if (bytesinfile <= 0)
1.1       mycroft   133:                        break;
                    134:                lbn = lblkno(fs, uio->uio_offset);
                    135:                nextlbn = lbn + 1;
                    136:                size = BLKSIZE(fs, ip, lbn);
                    137:                blkoffset = blkoff(fs, uio->uio_offset);
1.30      chs       138:                xfersize = MIN(MIN(fs->fs_bsize - blkoffset, uio->uio_resid),
1.28      chs       139:                    bytesinfile);
1.1       mycroft   140:
                    141: #ifdef LFS_READWRITE
1.21      perseant  142:                (void)lfs_check(vp, lbn, 0);
1.12      bouyer    143:                error = cluster_read(vp, ip->i_ffs_size, lbn, size, NOCRED, &bp);
1.1       mycroft   144: #else
1.19      bouyer    145:                if (lblktosize(fs, nextlbn) >= ip->i_ffs_size)
1.1       mycroft   146:                        error = bread(vp, lbn, size, NOCRED, &bp);
                    147:                else if (lbn - 1 == vp->v_lastr) {
                    148:                        int nextsize = BLKSIZE(fs, ip, nextlbn);
                    149:                        error = breadn(vp, lbn,
                    150:                            size, &nextlbn, &nextsize, 1, NOCRED, &bp);
                    151:                } else
                    152:                        error = bread(vp, lbn, size, NOCRED, &bp);
                    153: #endif
                    154:                if (error)
                    155:                        break;
                    156:                vp->v_lastr = lbn;
                    157:
                    158:                /*
                    159:                 * We should only get non-zero b_resid when an I/O error
                    160:                 * has occurred, which should cause us to break above.
                    161:                 * However, if the short read did not cause an error,
                    162:                 * then we want to ensure that we do not uiomove bad
                    163:                 * or uninitialized data.
                    164:                 */
                    165:                size -= bp->b_resid;
                    166:                if (size < xfersize) {
                    167:                        if (size == 0)
                    168:                                break;
                    169:                        xfersize = size;
                    170:                }
1.28      chs       171:                error = uiomove((char *)bp->b_data + blkoffset, xfersize, uio);
1.8       christos  172:                if (error)
1.1       mycroft   173:                        break;
                    174:                brelse(bp);
                    175:        }
                    176:        if (bp != NULL)
                    177:                brelse(bp);
1.28      chs       178:
1.29      lukem     179:  out:
1.18      kleink    180:        if (!(vp->v_mount->mnt_flag & MNT_NOATIME)) {
1.10      tls       181:                ip->i_flag |= IN_ACCESS;
1.20      mycroft   182:                if ((ap->a_ioflag & IO_SYNC) == IO_SYNC)
1.25      perseant  183:                        error = VOP_UPDATE(vp, NULL, NULL, UPDATE_WAIT);
1.18      kleink    184:        }
1.1       mycroft   185:        return (error);
                    186: }
                    187:
                    188: /*
                    189:  * Vnode op for writing.
                    190:  */
1.8       christos  191: int
1.29      lukem     192: WRITE(void *v)
1.8       christos  193: {
1.1       mycroft   194:        struct vop_write_args /* {
                    195:                struct vnode *a_vp;
                    196:                struct uio *a_uio;
                    197:                int a_ioflag;
                    198:                struct ucred *a_cred;
1.8       christos  199:        } */ *ap = v;
1.24      augustss  200:        struct vnode *vp;
                    201:        struct uio *uio;
                    202:        struct inode *ip;
                    203:        FS *fs;
1.1       mycroft   204:        struct buf *bp;
                    205:        struct proc *p;
1.16      fvdl      206:        ufs_daddr_t lbn;
1.1       mycroft   207:        off_t osize;
                    208:        int blkoffset, error, flags, ioflag, resid, size, xfersize;
1.28      chs       209: #ifndef LFS_READWRITE
                    210:        void *win;
                    211:        vsize_t bytelen;
                    212:        off_t oldoff;
                    213:        boolean_t rv;
                    214: #endif
1.1       mycroft   215:
                    216:        ioflag = ap->a_ioflag;
                    217:        uio = ap->a_uio;
                    218:        vp = ap->a_vp;
                    219:        ip = VTOI(vp);
                    220:
                    221: #ifdef DIAGNOSTIC
                    222:        if (uio->uio_rw != UIO_WRITE)
                    223:                panic("%s: mode", WRITE_S);
                    224: #endif
                    225:
                    226:        switch (vp->v_type) {
                    227:        case VREG:
                    228:                if (ioflag & IO_APPEND)
1.12      bouyer    229:                        uio->uio_offset = ip->i_ffs_size;
                    230:                if ((ip->i_ffs_flags & APPEND) && uio->uio_offset != ip->i_ffs_size)
1.1       mycroft   231:                        return (EPERM);
                    232:                /* FALLTHROUGH */
                    233:        case VLNK:
                    234:                break;
                    235:        case VDIR:
                    236:                if ((ioflag & IO_SYNC) == 0)
                    237:                        panic("%s: nonsync dir write", WRITE_S);
                    238:                break;
                    239:        default:
                    240:                panic("%s: type", WRITE_S);
                    241:        }
                    242:
                    243:        fs = ip->I_FS;
                    244:        if (uio->uio_offset < 0 ||
1.4       cgd       245:            (u_int64_t)uio->uio_offset + uio->uio_resid > fs->fs_maxfilesize)
1.1       mycroft   246:                return (EFBIG);
1.26      perseant  247: #ifdef LFS_READWRITE
                    248:        /* Disallow writes to the Ifile, even if noschg flag is removed */
                    249:        /* XXX can this go away when the Ifile is no longer in the namespace? */
                    250:        if (vp == fs->lfs_ivnode)
                    251:                return (EPERM);
                    252: #endif
                    253:
1.1       mycroft   254:        /*
                    255:         * Maybe this should be above the vnode op call, but so long as
                    256:         * file servers have no limits, I don't think it matters.
                    257:         */
                    258:        p = uio->uio_procp;
                    259:        if (vp->v_type == VREG && p &&
                    260:            uio->uio_offset + uio->uio_resid >
                    261:            p->p_rlimit[RLIMIT_FSIZE].rlim_cur) {
                    262:                psignal(p, SIGXFSZ);
                    263:                return (EFBIG);
                    264:        }
                    265:
                    266:        resid = uio->uio_resid;
1.12      bouyer    267:        osize = ip->i_ffs_size;
1.28      chs       268:        error = 0;
                    269:
                    270: #ifndef LFS_READWRITE
                    271:        if (vp->v_type != VREG) {
                    272:                goto bcache;
                    273:        }
                    274:
                    275:        while (uio->uio_resid > 0) {
                    276:                oldoff = uio->uio_offset;
                    277:                blkoffset = blkoff(fs, uio->uio_offset);
1.30      chs       278:                bytelen = MIN(fs->fs_bsize - blkoffset, uio->uio_resid);
1.28      chs       279:
                    280:                /*
                    281:                 * XXXUBC if file is mapped and this is the last block,
                    282:                 * process one page at a time.
                    283:                 */
                    284:
                    285:                error = ufs_balloc_range(vp, uio->uio_offset, bytelen,
                    286:                    ap->a_cred, ioflag & IO_SYNC ? B_SYNC : 0);
                    287:                if (error) {
                    288:                        return error;
                    289:                }
                    290:
                    291:                win = ubc_alloc(&vp->v_uvm.u_obj, uio->uio_offset, &bytelen,
                    292:                                UBC_WRITE);
                    293:                error = uiomove(win, bytelen, uio);
                    294:                ubc_release(win, 0);
                    295:
                    296:                /*
                    297:                 * flush what we just wrote if necessary.
                    298:                 * XXXUBC simplistic async flushing.
                    299:                 */
                    300:
                    301:                if (ioflag & IO_SYNC) {
                    302:                        simple_lock(&vp->v_uvm.u_obj.vmobjlock);
1.31      chs       303: #if 1
                    304:                        /*
                    305:                         * XXX
                    306:                         * flush whole blocks in case there are deps.
                    307:                         * otherwise we can dirty and flush part of
                    308:                         * a block multiple times and the softdep code
                    309:                         * will get confused.  fixing this the right way
                    310:                         * is complicated so we'll work around it for now.
                    311:                         */
                    312:
                    313:                        rv = vp->v_uvm.u_obj.pgops->pgo_flush(
                    314:                            &vp->v_uvm.u_obj,
                    315:                            oldoff & ~(fs->fs_bsize - 1),
                    316:                            (oldoff + bytelen + fs->fs_bsize - 1) &
                    317:                            ~(fs->fs_bsize - 1),
                    318:                            PGO_CLEANIT|PGO_SYNCIO);
                    319: #else
1.28      chs       320:                        rv = vp->v_uvm.u_obj.pgops->pgo_flush(
                    321:                            &vp->v_uvm.u_obj, oldoff, oldoff + bytelen,
                    322:                            PGO_CLEANIT|PGO_SYNCIO);
1.31      chs       323: #endif
1.28      chs       324:                        simple_unlock(&vp->v_uvm.u_obj.vmobjlock);
                    325:                } else if (oldoff >> 16 != uio->uio_offset >> 16) {
                    326:                        simple_lock(&vp->v_uvm.u_obj.vmobjlock);
                    327:                        rv = vp->v_uvm.u_obj.pgops->pgo_flush(
                    328:                            &vp->v_uvm.u_obj, (oldoff >> 16) << 16,
                    329:                            (uio->uio_offset >> 16) << 16, PGO_CLEANIT);
                    330:                        simple_unlock(&vp->v_uvm.u_obj.vmobjlock);
                    331:                }
                    332:                if (error) {
                    333:                        break;
                    334:                }
                    335:        }
                    336:        goto out;
                    337:
1.29      lukem     338:  bcache:
1.28      chs       339: #endif
1.1       mycroft   340:        flags = ioflag & IO_SYNC ? B_SYNC : 0;
1.28      chs       341:        while (uio->uio_resid > 0) {
1.1       mycroft   342:                lbn = lblkno(fs, uio->uio_offset);
                    343:                blkoffset = blkoff(fs, uio->uio_offset);
1.30      chs       344:                xfersize = MIN(fs->fs_bsize - blkoffset, uio->uio_resid);
1.1       mycroft   345:                if (fs->fs_bsize > xfersize)
                    346:                        flags |= B_CLRBUF;
                    347:                else
                    348:                        flags &= ~B_CLRBUF;
                    349:
1.23      fvdl      350:                error = VOP_BALLOC(vp, uio->uio_offset, xfersize,
                    351:                    ap->a_cred, flags, &bp);
                    352:
1.1       mycroft   353:                if (error)
                    354:                        break;
1.12      bouyer    355:                if (uio->uio_offset + xfersize > ip->i_ffs_size) {
                    356:                        ip->i_ffs_size = uio->uio_offset + xfersize;
1.14      mrg       357:                        uvm_vnp_setsize(vp, ip->i_ffs_size);
1.1       mycroft   358:                }
                    359:                size = BLKSIZE(fs, ip, lbn) - bp->b_resid;
1.28      chs       360:                if (xfersize > size)
1.1       mycroft   361:                        xfersize = size;
                    362:
1.28      chs       363:                error = uiomove((char *)bp->b_data + blkoffset, xfersize, uio);
                    364:
                    365:                /*
                    366:                 * if we didn't clear the block and the uiomove failed,
                    367:                 * the buf will now contain part of some other file,
                    368:                 * so we need to invalidate it.
                    369:                 */
                    370:                if (error && (flags & B_CLRBUF) == 0) {
                    371:                        bp->b_flags |= B_INVAL;
                    372:                        brelse(bp);
                    373:                        break;
                    374:                }
1.1       mycroft   375: #ifdef LFS_READWRITE
1.27      perseant  376:                if (!error)
1.31.2.1! perseant  377:                        error = lfs_reserve(fs, vp, btofsb(fs, (NIADDR + 1) << fs->lfs_bshift));
1.1       mycroft   378:                (void)VOP_BWRITE(bp);
1.27      perseant  379:                if (!error)
1.31.2.1! perseant  380:                        lfs_reserve(fs, vp, -btofsb(fs, (NIADDR + 1) << fs->lfs_bshift));
1.1       mycroft   381: #else
                    382:                if (ioflag & IO_SYNC)
                    383:                        (void)bwrite(bp);
                    384:                else if (xfersize + blkoffset == fs->fs_bsize)
                    385:                        if (doclusterwrite)
1.12      bouyer    386:                                cluster_write(bp, ip->i_ffs_size);
1.7       cgd       387:                        else
1.1       mycroft   388:                                bawrite(bp);
                    389:                else
                    390:                        bdwrite(bp);
                    391: #endif
                    392:                if (error || xfersize == 0)
                    393:                        break;
                    394:        }
                    395:        /*
                    396:         * If we successfully wrote any data, and we are not the superuser
                    397:         * we clear the setuid and setgid bits as a precaution against
                    398:         * tampering.
                    399:         */
1.28      chs       400: #ifndef LFS_READWRITE
1.29      lukem     401:  out:
1.28      chs       402: #endif
                    403:        ip->i_flag |= IN_CHANGE | IN_UPDATE;
1.1       mycroft   404:        if (resid > uio->uio_resid && ap->a_cred && ap->a_cred->cr_uid != 0)
1.12      bouyer    405:                ip->i_ffs_mode &= ~(ISUID | ISGID);
1.1       mycroft   406:        if (error) {
                    407:                if (ioflag & IO_UNIT) {
                    408:                        (void)VOP_TRUNCATE(vp, osize,
                    409:                            ioflag & IO_SYNC, ap->a_cred, uio->uio_procp);
                    410:                        uio->uio_offset -= resid - uio->uio_resid;
                    411:                        uio->uio_resid = resid;
                    412:                }
1.20      mycroft   413:        } else if (resid > uio->uio_resid && (ioflag & IO_SYNC) == IO_SYNC)
1.25      perseant  414:                error = VOP_UPDATE(vp, NULL, NULL, UPDATE_WAIT);
1.1       mycroft   415:        return (error);
                    416: }

CVSweb <webmaster@jp.NetBSD.org>