From owner-p4-projects@FreeBSD.ORG Wed Aug 26 19:15:10 2009 Return-Path: Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id 162051065695; Wed, 26 Aug 2009 19:15:10 +0000 (UTC) Delivered-To: perforce@FreeBSD.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id CE6BA106568E for ; Wed, 26 Aug 2009 19:15:09 +0000 (UTC) (envelope-from truncs@FreeBSD.org) Received: from repoman.freebsd.org (repoman.freebsd.org [IPv6:2001:4f8:fff6::29]) by mx1.freebsd.org (Postfix) with ESMTP id BCE4D8FC30 for ; Wed, 26 Aug 2009 19:15:09 +0000 (UTC) Received: from repoman.freebsd.org (localhost [127.0.0.1]) by repoman.freebsd.org (8.14.3/8.14.3) with ESMTP id n7QJF9s2092479 for ; Wed, 26 Aug 2009 19:15:09 GMT (envelope-from truncs@FreeBSD.org) Received: (from perforce@localhost) by repoman.freebsd.org (8.14.3/8.14.3/Submit) id n7QJF9nh092477 for perforce@freebsd.org; Wed, 26 Aug 2009 19:15:09 GMT (envelope-from truncs@FreeBSD.org) Date: Wed, 26 Aug 2009 19:15:09 GMT Message-Id: <200908261915.n7QJF9nh092477@repoman.freebsd.org> X-Authentication-Warning: repoman.freebsd.org: perforce set sender to truncs@FreeBSD.org using -f From: Aditya Sarawgi To: Perforce Change Reviews Cc: Subject: PERFORCE change 167854 for review X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: p4 projects tree changes List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 26 Aug 2009 19:15:10 -0000 http://perforce.freebsd.org/chv.cgi?CH=167854 Change 167854 by truncs@aditya on 2009/08/26 19:14:43 Fixes provided by bde@ Affected files ... .. //depot/projects/soc2009/soc_ext2fs/src/sys/fs/ext2fs/ext2_readwrite.c#2 edit Differences ... ==== //depot/projects/soc2009/soc_ext2fs/src/sys/fs/ext2fs/ext2_readwrite.c#2 (text+ko) ==== @@ -35,7 +35,7 @@ * @(#)ufs_readwrite.c 8.7 (Berkeley) 1/21/94 * $FreeBSD: src/sys/gnu/fs/ext2fs/ext2_readwrite.c,v 1.31 2005/01/06 18:27:30 imp Exp $ */ - +/* XXX TODO: remove these obfuscations (as in ffs_vnops.c). */ #define BLKSIZE(a, b, c) blksize(a, b, c) #define FS struct m_ext2fs #define I_FS i_e2fs @@ -47,7 +47,6 @@ /* * Vnode op for reading. */ -/* ARGSUSED */ static int READ(ap) struct vop_read_args /* { @@ -65,8 +64,8 @@ daddr_t lbn, nextlbn; off_t bytesinfile; long size, xfersize, blkoffset; - int error, orig_resid; - int seqcount = ap->a_ioflag >> IO_SEQSHIFT; + int error, orig_resid, seqcount; + seqcount = ap->a_ioflag >> IO_SEQSHIFT; u_short mode; vp = ap->a_vp; @@ -84,11 +83,14 @@ } else if (vp->v_type != VREG && vp->v_type != VDIR) panic("%s: type %d", READ_S, vp->v_type); #endif + orig_resid = uio->uio_resid; + KASSERT(orig_resid >= 0, ("ext2_read: uio->uio_resid < 0")); + if (orig_resid == 0) + return (0); + KASSERT(uio->uio_offset >= 0, ("ext2_read: uio->uio_offset < 0")); fs = ip->I_FS; - if ((uoff_t)uio->uio_offset > fs->e2fs_maxfilesize) - return (EFBIG); - - orig_resid = uio->uio_resid; + if (uio->uio_offset < ip->i_size && uio->uio_offset >= fs->e2fs_maxfilesize) + return (EOVERFLOW); for (error = 0, bp = NULL; uio->uio_resid > 0; bp = NULL) { if ((bytesinfile = ip->i_size - uio->uio_offset) <= 0) break; @@ -106,9 +108,8 @@ if (lblktosize(fs, nextlbn) >= ip->i_size) error = bread(vp, lbn, size, NOCRED, &bp); else if ((vp->v_mount->mnt_flag & MNT_NOCLUSTERR) == 0) - error = cluster_read(vp, - ip->i_size, lbn, size, NOCRED, - uio->uio_resid, (ap->a_ioflag >> IO_SEQSHIFT), &bp); + error = cluster_read(vp, ip->i_size, lbn, size, + NOCRED, blkoffset + uio->uio_resid, seqcount, &bp); else if (seqcount > 1) { int nextsize = BLKSIZE(fs, ip, nextlbn); error = breadn(vp, lbn, @@ -134,8 +135,8 @@ break; xfersize = size; } - error = - uiomove((char *)bp->b_data + blkoffset, (int)xfersize, uio); + error = uiomove((char *)bp->b_data + blkoffset, + (int)xfersize, uio); if (error) break; @@ -143,7 +144,7 @@ } if (bp != NULL) bqrelse(bp); - if (orig_resid > 0 && (error == 0 || uio->uio_resid != orig_resid) && + if ((error == 0 || uio->uio_resid != orig_resid) && (vp->v_mount->mnt_flag & MNT_NOATIME) == 0) ip->i_flag |= IN_ACCESS; return (error); @@ -169,11 +170,10 @@ struct thread *td; daddr_t lbn; off_t osize; - int seqcount; - int blkoffset, error, flags, ioflag, resid, size, xfersize; + int blkoffset, error, flags, ioflag, resid, size, seqcount, xfersize; ioflag = ap->a_ioflag; - seqcount = ap->a_ioflag >> IO_SEQSHIFT; + seqcount = ioflag >> IO_SEQSHIFT; uio = ap->a_uio; vp = ap->a_vp; ip = VTOI(vp); @@ -193,16 +193,19 @@ case VLNK: break; case VDIR: + /* XXX differs from ffs -- this is called from ext2_mkdir(). */ if ((ioflag & IO_SYNC) == 0) - panic("%s: nonsync dir write", WRITE_S); + panic("ext2_write: nonsync dir write"); break; default: - panic("%s: type", WRITE_S); + panic("ext2_write: type %p %d (%jd,%d)", (void *)vp, vp->v_type, + (intmax_t)uio->uio_offset, uio->uio_resid); } + KASSERT(uio->uio_resid >= 0, ("ext2_write: uio->uio_resid < 0")); + KASSERT(uio->uio_offset >= 0, ("ext2_write: uio->uio_offset < 0")); fs = ip->I_FS; - if (uio->uio_offset < 0 || - (uoff_t)uio->uio_offset + uio->uio_resid > fs->e2fs_maxfilesize) + if ((uoff_t)uio->uio_offset + uio->uio_resid > fs->e2fs_maxfilesize) return (EFBIG); /* * Maybe this should be above the vnode op call, but so long as @@ -230,33 +233,22 @@ xfersize = fs->e2fs_fsize - blkoffset; if (uio->uio_resid < xfersize) xfersize = uio->uio_resid; - if (uio->uio_offset + xfersize > ip->i_size) vnode_pager_setsize(vp, uio->uio_offset + xfersize); /* * Avoid a data-consistency race between write() and mmap() - * by ensuring that newly allocated blocks are zerod. The + * by ensuring that newly allocated blocks are zeroed. The * race can occur even in the case where the write covers * the entire block. */ flags |= B_CLRBUF; -#if 0 - if (fs->e2fs_fsize > xfersize) - flags |= B_CLRBUF; - else - flags &= ~B_CLRBUF; -#endif - - error = ext2_balloc(ip, - lbn, blkoffset + xfersize, ap->a_cred, &bp, flags); - if (error) + error = ext2_balloc(ip, lbn, blkoffset + xfersize, + ap->a_cred, &bp, flags); + if (error != 0) break; - - if (uio->uio_offset + xfersize > ip->i_size) { + if (uio->uio_offset + xfersize > ip->i_size) ip->i_size = uio->uio_offset + xfersize; - } - size = BLKSIZE(fs, ip, lbn) - bp->b_resid; if (size < xfersize) xfersize = size; @@ -264,7 +256,7 @@ error = uiomove((char *)bp->b_data + blkoffset, (int)xfersize, uio); if ((ioflag & IO_VMIO) && - (LIST_FIRST(&bp->b_dep) == NULL)) /* in ext2fs? */ + LIST_FIRST(&bp->b_dep) == NULL) /* in ext2fs? */ bp->b_flags |= B_RELBUF; if (ioflag & IO_SYNC) { @@ -282,23 +274,34 @@ } if (error || xfersize == 0) break; - ip->i_flag |= IN_CHANGE | IN_UPDATE; } /* * If we successfully wrote any data, and we are not the superuser * we clear the setuid and setgid bits as a precaution against * tampering. + * XXX too late, the tamperer may have opened the file while we + * were writing the data (or before). + * XXX too early, if (error && ioflag & IO_UNIT) then we will + * unwrite the data. */ if (resid > uio->uio_resid && ap->a_cred && ap->a_cred->cr_uid != 0) ip->i_mode &= ~(ISUID | ISGID); if (error) { + /* + * XXX should truncate to the last successfully written + * data if the uiomove() failed. + */ if (ioflag & IO_UNIT) { (void)ext2_truncate(vp, osize, ioflag & IO_SYNC, ap->a_cred, uio->uio_td); uio->uio_offset -= resid - uio->uio_resid; uio->uio_resid = resid; } - } else if (resid > uio->uio_resid && (ioflag & IO_SYNC)) - error = ext2_update(vp, 1); + } + if (uio->uio_resid != resid) { + ip->i_flag |= IN_CHANGE | IN_UPDATE; + if (ioflag & IO_SYNC) + error = ext2_update(vp, 1); + } return (error); }