[BACK]Return to ext2fs_readwrite.c CVS log [TXT][DIR] Up to [local] / sys / ufs / ext2fs

Annotation of sys/ufs/ext2fs/ext2fs_readwrite.c, Revision 1.1

1.1     ! nbrk        1: /*     $OpenBSD: ext2fs_readwrite.c,v 1.22 2007/06/17 20:15:25 jasper Exp $    */
        !             2: /*     $NetBSD: ext2fs_readwrite.c,v 1.16 2001/02/27 04:37:47 chs Exp $        */
        !             3:
        !             4: /*-
        !             5:  * Copyright (c) 1997 Manuel Bouyer.
        !             6:  * Copyright (c) 1993
        !             7:  *     The Regents of the University of California.  All rights reserved.
        !             8:  *
        !             9:  * Redistribution and use in source and binary forms, with or without
        !            10:  * modification, are permitted provided that the following conditions
        !            11:  * are met:
        !            12:  * 1. Redistributions of source code must retain the above copyright
        !            13:  *    notice, this list of conditions and the following disclaimer.
        !            14:  * 2. Redistributions in binary form must reproduce the above copyright
        !            15:  *    notice, this list of conditions and the following disclaimer in the
        !            16:  *    documentation and/or other materials provided with the distribution.
        !            17:  * 3. Neither the name of the University nor the names of its contributors
        !            18:  *    may be used to endorse or promote products derived from this software
        !            19:  *    without specific prior written permission.
        !            20:  *
        !            21:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
        !            22:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
        !            23:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
        !            24:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
        !            25:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
        !            26:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
        !            27:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
        !            28:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
        !            29:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
        !            30:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
        !            31:  * SUCH DAMAGE.
        !            32:  *
        !            33:  *     @(#)ufs_readwrite.c     8.8 (Berkeley) 8/4/94
        !            34:  * Modified for ext2fs by Manuel Bouyer.
        !            35:  */
        !            36:
        !            37: #include <sys/param.h>
        !            38: #include <sys/systm.h>
        !            39: #include <sys/resourcevar.h>
        !            40: #include <sys/kernel.h>
        !            41: #include <sys/file.h>
        !            42: #include <sys/stat.h>
        !            43: #include <sys/buf.h>
        !            44: #include <sys/proc.h>
        !            45: #include <sys/conf.h>
        !            46: #include <sys/mount.h>
        !            47: #include <sys/vnode.h>
        !            48: #include <sys/malloc.h>
        !            49: #include <sys/signalvar.h>
        !            50:
        !            51: #include <ufs/ufs/quota.h>
        !            52: #include <ufs/ufs/inode.h>
        !            53: #include <ufs/ext2fs/ext2fs.h>
        !            54: #include <ufs/ext2fs/ext2fs_extern.h>
        !            55:
        !            56:
        !            57: #define doclusterread 0 /* XXX underway */
        !            58: #define doclusterwrite 0
        !            59:
        !            60: /*
        !            61:  * Vnode op for reading.
        !            62:  */
        !            63: /* ARGSUSED */
        !            64: int
        !            65: ext2fs_read(void *v)
        !            66: {
        !            67:        struct vop_read_args *ap = v;
        !            68:        struct vnode *vp;
        !            69:        struct inode *ip;
        !            70:        struct uio *uio;
        !            71:        struct m_ext2fs *fs;
        !            72:        struct buf *bp;
        !            73:        daddr64_t lbn, nextlbn;
        !            74:        off_t bytesinfile;
        !            75:        long size, xfersize, blkoffset;
        !            76:        int error;
        !            77:
        !            78:        vp = ap->a_vp;
        !            79:        ip = VTOI(vp);
        !            80:        uio = ap->a_uio;
        !            81:
        !            82: #ifdef DIAGNOSTIC
        !            83:        if (uio->uio_rw != UIO_READ)
        !            84:                panic("%s: mode", "ext2fs_read");
        !            85:
        !            86:        if (vp->v_type == VLNK) {
        !            87:                if ((int)ext2fs_size(ip) < vp->v_mount->mnt_maxsymlinklen ||
        !            88:                        (vp->v_mount->mnt_maxsymlinklen == 0 &&
        !            89:                         ip->i_e2fs_nblock == 0))
        !            90:                        panic("%s: short symlink", "ext2fs_read");
        !            91:        } else if (vp->v_type != VREG && vp->v_type != VDIR)
        !            92:                panic("%s: type %d", "ext2fs_read", vp->v_type);
        !            93: #endif
        !            94:        fs = ip->i_e2fs;
        !            95:        if ((u_int64_t)uio->uio_offset >
        !            96:                ((u_int64_t)0x80000000 * fs->e2fs_bsize - 1))
        !            97:                return (EFBIG);
        !            98:        if (uio->uio_resid == 0)
        !            99:                return (0);
        !           100:
        !           101:        for (error = 0, bp = NULL; uio->uio_resid > 0; bp = NULL) {
        !           102:                if ((bytesinfile = ext2fs_size(ip) - uio->uio_offset) <= 0)
        !           103:                        break;
        !           104:                lbn = lblkno(fs, uio->uio_offset);
        !           105:                nextlbn = lbn + 1;
        !           106:                size = fs->e2fs_bsize;
        !           107:                blkoffset = blkoff(fs, uio->uio_offset);
        !           108:                xfersize = fs->e2fs_bsize - blkoffset;
        !           109:                if (uio->uio_resid < xfersize)
        !           110:                        xfersize = uio->uio_resid;
        !           111:                if (bytesinfile < xfersize)
        !           112:                        xfersize = bytesinfile;
        !           113:
        !           114:                if (lblktosize(fs, nextlbn) >= ext2fs_size(ip))
        !           115:                        error = bread(vp, lbn, size, NOCRED, &bp);
        !           116:                else if (lbn - 1 == ip->i_ci.ci_lastr) {
        !           117:                        int nextsize = fs->e2fs_bsize;
        !           118:                        error = breadn(vp, lbn,
        !           119:                                size, &nextlbn, &nextsize, 1, NOCRED, &bp);
        !           120:                } else
        !           121:                        error = bread(vp, lbn, size, NOCRED, &bp);
        !           122:                if (error)
        !           123:                        break;
        !           124:                ip->i_ci.ci_lastr = lbn;
        !           125:
        !           126:                /*
        !           127:                 * We should only get non-zero b_resid when an I/O error
        !           128:                 * has occurred, which should cause us to break above.
        !           129:                 * However, if the short read did not cause an error,
        !           130:                 * then we want to ensure that we do not uiomove bad
        !           131:                 * or uninitialized data.
        !           132:                 */
        !           133:                size -= bp->b_resid;
        !           134:                if (size < xfersize) {
        !           135:                        if (size == 0)
        !           136:                                break;
        !           137:                        xfersize = size;
        !           138:                }
        !           139:                error = uiomove((char *)bp->b_data + blkoffset, xfersize, uio);
        !           140:                if (error)
        !           141:                        break;
        !           142:                brelse(bp);
        !           143:        }
        !           144:        if (bp != NULL)
        !           145:                brelse(bp);
        !           146:
        !           147:        if (!(vp->v_mount->mnt_flag & MNT_NOATIME)) {
        !           148:                ip->i_flag |= IN_ACCESS;
        !           149:        }
        !           150:        return (error);
        !           151: }
        !           152:
        !           153: /*
        !           154:  * Vnode op for writing.
        !           155:  */
        !           156: int
        !           157: ext2fs_write(void *v)
        !           158: {
        !           159:        struct vop_write_args *ap = v;
        !           160:        struct vnode *vp;
        !           161:        struct uio *uio;
        !           162:        struct inode *ip;
        !           163:        struct m_ext2fs *fs;
        !           164:        struct buf *bp;
        !           165:        struct proc *p;
        !           166:        int32_t lbn;
        !           167:        off_t osize;
        !           168:        int blkoffset, error, flags, ioflag, resid, size, xfersize;
        !           169:
        !           170:        ioflag = ap->a_ioflag;
        !           171:        uio = ap->a_uio;
        !           172:        vp = ap->a_vp;
        !           173:        ip = VTOI(vp);
        !           174:
        !           175: #ifdef DIAGNOSTIC
        !           176:        if (uio->uio_rw != UIO_WRITE)
        !           177:                panic("%s: mode", "ext2fs_write");
        !           178: #endif
        !           179:
        !           180:        /*
        !           181:         * If writing 0 bytes, succeed and do not change
        !           182:         * update time or file offset (standards compliance)
        !           183:         */
        !           184:        if (uio->uio_resid == 0)
        !           185:                return (0);
        !           186:
        !           187:        switch (vp->v_type) {
        !           188:        case VREG:
        !           189:                if (ioflag & IO_APPEND)
        !           190:                        uio->uio_offset = ext2fs_size(ip);
        !           191:                if ((ip->i_e2fs_flags & EXT2_APPEND) &&
        !           192:                        uio->uio_offset != ext2fs_size(ip))
        !           193:                        return (EPERM);
        !           194:                /* FALLTHROUGH */
        !           195:        case VLNK:
        !           196:                break;
        !           197:        case VDIR:
        !           198:                if ((ioflag & IO_SYNC) == 0)
        !           199:                        panic("%s: nonsync dir write", "ext2fs_write");
        !           200:                break;
        !           201:        default:
        !           202:                panic("%s: type", "ext2fs_write");
        !           203:        }
        !           204:
        !           205:        fs = ip->i_e2fs;
        !           206:        if (uio->uio_offset < 0 ||
        !           207:                (u_int64_t)uio->uio_offset + uio->uio_resid >
        !           208:                ((u_int64_t)0x80000000 * fs->e2fs_bsize - 1))
        !           209:                return (EFBIG);
        !           210:        /*
        !           211:         * Maybe this should be above the vnode op call, but so long as
        !           212:         * file servers have no limits, I don't think it matters.
        !           213:         */
        !           214:        p = uio->uio_procp;
        !           215:        if (vp->v_type == VREG && p &&
        !           216:                uio->uio_offset + uio->uio_resid >
        !           217:                p->p_rlimit[RLIMIT_FSIZE].rlim_cur) {
        !           218:                psignal(p, SIGXFSZ);
        !           219:                return (EFBIG);
        !           220:        }
        !           221:
        !           222:        resid = uio->uio_resid;
        !           223:        osize = ext2fs_size(ip);
        !           224:        flags = ioflag & IO_SYNC ? B_SYNC : 0;
        !           225:
        !           226:        for (error = 0; uio->uio_resid > 0;) {
        !           227:                lbn = lblkno(fs, uio->uio_offset);
        !           228:                blkoffset = blkoff(fs, uio->uio_offset);
        !           229:                xfersize = fs->e2fs_bsize - blkoffset;
        !           230:                if (uio->uio_resid < xfersize)
        !           231:                        xfersize = uio->uio_resid;
        !           232:                if (fs->e2fs_bsize > xfersize)
        !           233:                        flags |= B_CLRBUF;
        !           234:                else
        !           235:                        flags &= ~B_CLRBUF;
        !           236:
        !           237:                error = ext2fs_buf_alloc(ip,
        !           238:                        lbn, blkoffset + xfersize, ap->a_cred, &bp, flags);
        !           239:                if (error)
        !           240:                        break;
        !           241:                if (uio->uio_offset + xfersize > ext2fs_size(ip)) {
        !           242:                        error = ext2fs_setsize(ip, uio->uio_offset + xfersize);
        !           243:                        if (error)
        !           244:                                break;
        !           245:                        uvm_vnp_setsize(vp, ip->i_e2fs_size);
        !           246:                }
        !           247:                uvm_vnp_uncache(vp);
        !           248:
        !           249:                size = fs->e2fs_bsize - bp->b_resid;
        !           250:                if (size < xfersize)
        !           251:                        xfersize = size;
        !           252:
        !           253:                error =
        !           254:                        uiomove((char *)bp->b_data + blkoffset, (int)xfersize, uio);
        !           255:                if (ioflag & IO_SYNC)
        !           256:                        (void)bwrite(bp);
        !           257:                else if (xfersize + blkoffset == fs->e2fs_bsize) {
        !           258:                        if (doclusterwrite)
        !           259:                                cluster_write(bp, &ip->i_ci, ext2fs_size(ip));
        !           260:                        else
        !           261:                                bawrite(bp);
        !           262:                } else
        !           263:                        bdwrite(bp);
        !           264:                if (error || xfersize == 0)
        !           265:                        break;
        !           266:                ip->i_flag |= IN_CHANGE | IN_UPDATE;
        !           267:        }
        !           268:        /*
        !           269:         * If we successfully wrote any data, and we are not the superuser
        !           270:         * we clear the setuid and setgid bits as a precaution against
        !           271:         * tampering.
        !           272:         */
        !           273:        if (resid > uio->uio_resid && ap->a_cred && ap->a_cred->cr_uid != 0)
        !           274:                ip->i_e2fs_mode &= ~(ISUID | ISGID);
        !           275:        if (error) {
        !           276:                if (ioflag & IO_UNIT) {
        !           277:                        (void)ext2fs_truncate(ip, osize,
        !           278:                                ioflag & IO_SYNC, ap->a_cred);
        !           279:                        uio->uio_offset -= resid - uio->uio_resid;
        !           280:                        uio->uio_resid = resid;
        !           281:                }
        !           282:        } else if (resid > uio->uio_resid && (ioflag & IO_SYNC)) {
        !           283:                error = ext2fs_update(ip, NULL, NULL, 1);
        !           284:        }
        !           285:        return (error);
        !           286: }

CVSweb