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