PERFORCE change 167854 for review

Aditya Sarawgi truncs at FreeBSD.org
Wed Aug 26 19:15:10 UTC 2009


http://perforce.freebsd.org/chv.cgi?CH=167854

Change 167854 by truncs at 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);
 }


More information about the p4-projects mailing list