1*d65f6f70SBen Gras /* $NetBSD: ext2fs_readwrite.c,v 1.58 2011/11/18 21:18:51 christos Exp $ */ 2*d65f6f70SBen Gras 3*d65f6f70SBen Gras /*- 4*d65f6f70SBen Gras * Copyright (c) 1993 5*d65f6f70SBen Gras * The Regents of the University of California. All rights reserved. 6*d65f6f70SBen Gras * 7*d65f6f70SBen Gras * Redistribution and use in source and binary forms, with or without 8*d65f6f70SBen Gras * modification, are permitted provided that the following conditions 9*d65f6f70SBen Gras * are met: 10*d65f6f70SBen Gras * 1. Redistributions of source code must retain the above copyright 11*d65f6f70SBen Gras * notice, this list of conditions and the following disclaimer. 12*d65f6f70SBen Gras * 2. Redistributions in binary form must reproduce the above copyright 13*d65f6f70SBen Gras * notice, this list of conditions and the following disclaimer in the 14*d65f6f70SBen Gras * documentation and/or other materials provided with the distribution. 15*d65f6f70SBen Gras * 3. Neither the name of the University nor the names of its contributors 16*d65f6f70SBen Gras * may be used to endorse or promote products derived from this software 17*d65f6f70SBen Gras * without specific prior written permission. 18*d65f6f70SBen Gras * 19*d65f6f70SBen Gras * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 20*d65f6f70SBen Gras * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21*d65f6f70SBen Gras * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22*d65f6f70SBen Gras * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 23*d65f6f70SBen Gras * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24*d65f6f70SBen Gras * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25*d65f6f70SBen Gras * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26*d65f6f70SBen Gras * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27*d65f6f70SBen Gras * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28*d65f6f70SBen Gras * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29*d65f6f70SBen Gras * SUCH DAMAGE. 30*d65f6f70SBen Gras * 31*d65f6f70SBen Gras * @(#)ufs_readwrite.c 8.8 (Berkeley) 8/4/94 32*d65f6f70SBen Gras * Modified for ext2fs by Manuel Bouyer. 33*d65f6f70SBen Gras */ 34*d65f6f70SBen Gras 35*d65f6f70SBen Gras /*- 36*d65f6f70SBen Gras * Copyright (c) 1997 Manuel Bouyer. 37*d65f6f70SBen Gras * 38*d65f6f70SBen Gras * Redistribution and use in source and binary forms, with or without 39*d65f6f70SBen Gras * modification, are permitted provided that the following conditions 40*d65f6f70SBen Gras * are met: 41*d65f6f70SBen Gras * 1. Redistributions of source code must retain the above copyright 42*d65f6f70SBen Gras * notice, this list of conditions and the following disclaimer. 43*d65f6f70SBen Gras * 2. Redistributions in binary form must reproduce the above copyright 44*d65f6f70SBen Gras * notice, this list of conditions and the following disclaimer in the 45*d65f6f70SBen Gras * documentation and/or other materials provided with the distribution. 46*d65f6f70SBen Gras * 47*d65f6f70SBen Gras * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 48*d65f6f70SBen Gras * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 49*d65f6f70SBen Gras * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 50*d65f6f70SBen Gras * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 51*d65f6f70SBen Gras * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 52*d65f6f70SBen Gras * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 53*d65f6f70SBen Gras * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 54*d65f6f70SBen Gras * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 55*d65f6f70SBen Gras * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 56*d65f6f70SBen Gras * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 57*d65f6f70SBen Gras * 58*d65f6f70SBen Gras * @(#)ufs_readwrite.c 8.8 (Berkeley) 8/4/94 59*d65f6f70SBen Gras * Modified for ext2fs by Manuel Bouyer. 60*d65f6f70SBen Gras */ 61*d65f6f70SBen Gras 62*d65f6f70SBen Gras #include <sys/cdefs.h> 63*d65f6f70SBen Gras __KERNEL_RCSID(0, "$NetBSD: ext2fs_readwrite.c,v 1.58 2011/11/18 21:18:51 christos Exp $"); 64*d65f6f70SBen Gras 65*d65f6f70SBen Gras #include <sys/param.h> 66*d65f6f70SBen Gras #include <sys/systm.h> 67*d65f6f70SBen Gras #include <sys/resourcevar.h> 68*d65f6f70SBen Gras #include <sys/kernel.h> 69*d65f6f70SBen Gras #include <sys/file.h> 70*d65f6f70SBen Gras #include <sys/stat.h> 71*d65f6f70SBen Gras #include <sys/buf.h> 72*d65f6f70SBen Gras #include <sys/proc.h> 73*d65f6f70SBen Gras #include <sys/mount.h> 74*d65f6f70SBen Gras #include <sys/vnode.h> 75*d65f6f70SBen Gras #include <sys/malloc.h> 76*d65f6f70SBen Gras #include <sys/signalvar.h> 77*d65f6f70SBen Gras #include <sys/kauth.h> 78*d65f6f70SBen Gras 79*d65f6f70SBen Gras #include <ufs/ufs/inode.h> 80*d65f6f70SBen Gras #include <ufs/ufs/ufsmount.h> 81*d65f6f70SBen Gras #include <ufs/ufs/ufs_extern.h> 82*d65f6f70SBen Gras #include <ufs/ext2fs/ext2fs.h> 83*d65f6f70SBen Gras #include <ufs/ext2fs/ext2fs_extern.h> 84*d65f6f70SBen Gras 85*d65f6f70SBen Gras 86*d65f6f70SBen Gras #define doclusterread 0 /* XXX underway */ 87*d65f6f70SBen Gras #define doclusterwrite 0 88*d65f6f70SBen Gras 89*d65f6f70SBen Gras /* 90*d65f6f70SBen Gras * Vnode op for reading. 91*d65f6f70SBen Gras */ 92*d65f6f70SBen Gras /* ARGSUSED */ 93*d65f6f70SBen Gras int 94*d65f6f70SBen Gras ext2fs_read(void *v) 95*d65f6f70SBen Gras { 96*d65f6f70SBen Gras struct vop_read_args /* { 97*d65f6f70SBen Gras struct vnode *a_vp; 98*d65f6f70SBen Gras struct uio *a_uio; 99*d65f6f70SBen Gras int a_ioflag; 100*d65f6f70SBen Gras kauth_cred_t a_cred; 101*d65f6f70SBen Gras } */ *ap = v; 102*d65f6f70SBen Gras struct vnode *vp; 103*d65f6f70SBen Gras struct inode *ip; 104*d65f6f70SBen Gras struct uio *uio; 105*d65f6f70SBen Gras struct m_ext2fs *fs; 106*d65f6f70SBen Gras struct buf *bp; 107*d65f6f70SBen Gras struct ufsmount *ump; 108*d65f6f70SBen Gras vsize_t bytelen; 109*d65f6f70SBen Gras daddr_t lbn, nextlbn; 110*d65f6f70SBen Gras off_t bytesinfile; 111*d65f6f70SBen Gras long size, xfersize, blkoffset; 112*d65f6f70SBen Gras int error; 113*d65f6f70SBen Gras 114*d65f6f70SBen Gras vp = ap->a_vp; 115*d65f6f70SBen Gras ip = VTOI(vp); 116*d65f6f70SBen Gras ump = ip->i_ump; 117*d65f6f70SBen Gras uio = ap->a_uio; 118*d65f6f70SBen Gras error = 0; 119*d65f6f70SBen Gras 120*d65f6f70SBen Gras #ifdef DIAGNOSTIC 121*d65f6f70SBen Gras if (uio->uio_rw != UIO_READ) 122*d65f6f70SBen Gras panic("%s: mode", "ext2fs_read"); 123*d65f6f70SBen Gras 124*d65f6f70SBen Gras if (vp->v_type == VLNK) { 125*d65f6f70SBen Gras if (ext2fs_size(ip) < ump->um_maxsymlinklen || 126*d65f6f70SBen Gras (ump->um_maxsymlinklen == 0 && ip->i_e2fs_nblock == 0)) 127*d65f6f70SBen Gras panic("%s: short symlink", "ext2fs_read"); 128*d65f6f70SBen Gras } else if (vp->v_type != VREG && vp->v_type != VDIR) 129*d65f6f70SBen Gras panic("%s: type %d", "ext2fs_read", vp->v_type); 130*d65f6f70SBen Gras #endif 131*d65f6f70SBen Gras fs = ip->i_e2fs; 132*d65f6f70SBen Gras if ((uint64_t)uio->uio_offset > ump->um_maxfilesize) 133*d65f6f70SBen Gras return (EFBIG); 134*d65f6f70SBen Gras if (uio->uio_resid == 0) 135*d65f6f70SBen Gras return (0); 136*d65f6f70SBen Gras if (uio->uio_offset >= ext2fs_size(ip)) 137*d65f6f70SBen Gras goto out; 138*d65f6f70SBen Gras 139*d65f6f70SBen Gras if (vp->v_type == VREG) { 140*d65f6f70SBen Gras const int advice = IO_ADV_DECODE(ap->a_ioflag); 141*d65f6f70SBen Gras 142*d65f6f70SBen Gras while (uio->uio_resid > 0) { 143*d65f6f70SBen Gras bytelen = MIN(ext2fs_size(ip) - uio->uio_offset, 144*d65f6f70SBen Gras uio->uio_resid); 145*d65f6f70SBen Gras if (bytelen == 0) 146*d65f6f70SBen Gras break; 147*d65f6f70SBen Gras 148*d65f6f70SBen Gras error = ubc_uiomove(&vp->v_uobj, uio, bytelen, advice, 149*d65f6f70SBen Gras UBC_READ | UBC_PARTIALOK | UBC_UNMAP_FLAG(vp)); 150*d65f6f70SBen Gras if (error) 151*d65f6f70SBen Gras break; 152*d65f6f70SBen Gras } 153*d65f6f70SBen Gras goto out; 154*d65f6f70SBen Gras } 155*d65f6f70SBen Gras 156*d65f6f70SBen Gras for (error = 0, bp = NULL; uio->uio_resid > 0; bp = NULL) { 157*d65f6f70SBen Gras bytesinfile = ext2fs_size(ip) - uio->uio_offset; 158*d65f6f70SBen Gras if (bytesinfile <= 0) 159*d65f6f70SBen Gras break; 160*d65f6f70SBen Gras lbn = lblkno(fs, uio->uio_offset); 161*d65f6f70SBen Gras nextlbn = lbn + 1; 162*d65f6f70SBen Gras size = fs->e2fs_bsize; 163*d65f6f70SBen Gras blkoffset = blkoff(fs, uio->uio_offset); 164*d65f6f70SBen Gras xfersize = fs->e2fs_bsize - blkoffset; 165*d65f6f70SBen Gras if (uio->uio_resid < xfersize) 166*d65f6f70SBen Gras xfersize = uio->uio_resid; 167*d65f6f70SBen Gras if (bytesinfile < xfersize) 168*d65f6f70SBen Gras xfersize = bytesinfile; 169*d65f6f70SBen Gras 170*d65f6f70SBen Gras if (lblktosize(fs, nextlbn) >= ext2fs_size(ip)) 171*d65f6f70SBen Gras error = bread(vp, lbn, size, NOCRED, 0, &bp); 172*d65f6f70SBen Gras else { 173*d65f6f70SBen Gras int nextsize = fs->e2fs_bsize; 174*d65f6f70SBen Gras error = breadn(vp, lbn, 175*d65f6f70SBen Gras size, &nextlbn, &nextsize, 1, NOCRED, 0, &bp); 176*d65f6f70SBen Gras } 177*d65f6f70SBen Gras if (error) 178*d65f6f70SBen Gras break; 179*d65f6f70SBen Gras 180*d65f6f70SBen Gras /* 181*d65f6f70SBen Gras * We should only get non-zero b_resid when an I/O error 182*d65f6f70SBen Gras * has occurred, which should cause us to break above. 183*d65f6f70SBen Gras * However, if the short read did not cause an error, 184*d65f6f70SBen Gras * then we want to ensure that we do not uiomove bad 185*d65f6f70SBen Gras * or uninitialized data. 186*d65f6f70SBen Gras */ 187*d65f6f70SBen Gras size -= bp->b_resid; 188*d65f6f70SBen Gras if (size < xfersize) { 189*d65f6f70SBen Gras if (size == 0) 190*d65f6f70SBen Gras break; 191*d65f6f70SBen Gras xfersize = size; 192*d65f6f70SBen Gras } 193*d65f6f70SBen Gras error = uiomove((char *)bp->b_data + blkoffset, xfersize, uio); 194*d65f6f70SBen Gras if (error) 195*d65f6f70SBen Gras break; 196*d65f6f70SBen Gras brelse(bp, 0); 197*d65f6f70SBen Gras } 198*d65f6f70SBen Gras if (bp != NULL) 199*d65f6f70SBen Gras brelse(bp, 0); 200*d65f6f70SBen Gras 201*d65f6f70SBen Gras out: 202*d65f6f70SBen Gras if (!(vp->v_mount->mnt_flag & MNT_NOATIME)) { 203*d65f6f70SBen Gras ip->i_flag |= IN_ACCESS; 204*d65f6f70SBen Gras if ((ap->a_ioflag & IO_SYNC) == IO_SYNC) 205*d65f6f70SBen Gras error = ext2fs_update(vp, NULL, NULL, UPDATE_WAIT); 206*d65f6f70SBen Gras } 207*d65f6f70SBen Gras return (error); 208*d65f6f70SBen Gras } 209*d65f6f70SBen Gras 210*d65f6f70SBen Gras /* 211*d65f6f70SBen Gras * Vnode op for writing. 212*d65f6f70SBen Gras */ 213*d65f6f70SBen Gras int 214*d65f6f70SBen Gras ext2fs_write(void *v) 215*d65f6f70SBen Gras { 216*d65f6f70SBen Gras struct vop_write_args /* { 217*d65f6f70SBen Gras struct vnode *a_vp; 218*d65f6f70SBen Gras struct uio *a_uio; 219*d65f6f70SBen Gras int a_ioflag; 220*d65f6f70SBen Gras kauth_cred_t a_cred; 221*d65f6f70SBen Gras } */ *ap = v; 222*d65f6f70SBen Gras struct vnode *vp; 223*d65f6f70SBen Gras struct uio *uio; 224*d65f6f70SBen Gras struct inode *ip; 225*d65f6f70SBen Gras struct m_ext2fs *fs; 226*d65f6f70SBen Gras struct buf *bp; 227*d65f6f70SBen Gras struct ufsmount *ump; 228*d65f6f70SBen Gras daddr_t lbn; 229*d65f6f70SBen Gras off_t osize; 230*d65f6f70SBen Gras int blkoffset, error, flags, ioflag, resid, xfersize; 231*d65f6f70SBen Gras vsize_t bytelen; 232*d65f6f70SBen Gras off_t oldoff = 0; /* XXX */ 233*d65f6f70SBen Gras bool async; 234*d65f6f70SBen Gras int extended = 0; 235*d65f6f70SBen Gras int advice; 236*d65f6f70SBen Gras 237*d65f6f70SBen Gras ioflag = ap->a_ioflag; 238*d65f6f70SBen Gras advice = IO_ADV_DECODE(ioflag); 239*d65f6f70SBen Gras uio = ap->a_uio; 240*d65f6f70SBen Gras vp = ap->a_vp; 241*d65f6f70SBen Gras ip = VTOI(vp); 242*d65f6f70SBen Gras ump = ip->i_ump; 243*d65f6f70SBen Gras error = 0; 244*d65f6f70SBen Gras 245*d65f6f70SBen Gras #ifdef DIAGNOSTIC 246*d65f6f70SBen Gras if (uio->uio_rw != UIO_WRITE) 247*d65f6f70SBen Gras panic("%s: mode", "ext2fs_write"); 248*d65f6f70SBen Gras #endif 249*d65f6f70SBen Gras 250*d65f6f70SBen Gras switch (vp->v_type) { 251*d65f6f70SBen Gras case VREG: 252*d65f6f70SBen Gras if (ioflag & IO_APPEND) 253*d65f6f70SBen Gras uio->uio_offset = ext2fs_size(ip); 254*d65f6f70SBen Gras if ((ip->i_e2fs_flags & EXT2_APPEND) && 255*d65f6f70SBen Gras uio->uio_offset != ext2fs_size(ip)) 256*d65f6f70SBen Gras return (EPERM); 257*d65f6f70SBen Gras /* FALLTHROUGH */ 258*d65f6f70SBen Gras case VLNK: 259*d65f6f70SBen Gras break; 260*d65f6f70SBen Gras case VDIR: 261*d65f6f70SBen Gras if ((ioflag & IO_SYNC) == 0) 262*d65f6f70SBen Gras panic("%s: nonsync dir write", "ext2fs_write"); 263*d65f6f70SBen Gras break; 264*d65f6f70SBen Gras default: 265*d65f6f70SBen Gras panic("%s: type", "ext2fs_write"); 266*d65f6f70SBen Gras } 267*d65f6f70SBen Gras 268*d65f6f70SBen Gras fs = ip->i_e2fs; 269*d65f6f70SBen Gras if (uio->uio_offset < 0 || 270*d65f6f70SBen Gras (uint64_t)uio->uio_offset + uio->uio_resid > ump->um_maxfilesize) 271*d65f6f70SBen Gras return (EFBIG); 272*d65f6f70SBen Gras if (uio->uio_resid == 0) 273*d65f6f70SBen Gras return (0); 274*d65f6f70SBen Gras 275*d65f6f70SBen Gras async = vp->v_mount->mnt_flag & MNT_ASYNC; 276*d65f6f70SBen Gras resid = uio->uio_resid; 277*d65f6f70SBen Gras osize = ext2fs_size(ip); 278*d65f6f70SBen Gras 279*d65f6f70SBen Gras if (vp->v_type == VREG) { 280*d65f6f70SBen Gras while (uio->uio_resid > 0) { 281*d65f6f70SBen Gras oldoff = uio->uio_offset; 282*d65f6f70SBen Gras blkoffset = blkoff(fs, uio->uio_offset); 283*d65f6f70SBen Gras bytelen = MIN(fs->e2fs_bsize - blkoffset, 284*d65f6f70SBen Gras uio->uio_resid); 285*d65f6f70SBen Gras 286*d65f6f70SBen Gras if (vp->v_size < oldoff + bytelen) { 287*d65f6f70SBen Gras uvm_vnp_setwritesize(vp, oldoff + bytelen); 288*d65f6f70SBen Gras } 289*d65f6f70SBen Gras error = ufs_balloc_range(vp, uio->uio_offset, 290*d65f6f70SBen Gras bytelen, ap->a_cred, 0); 291*d65f6f70SBen Gras if (error) 292*d65f6f70SBen Gras break; 293*d65f6f70SBen Gras error = ubc_uiomove(&vp->v_uobj, uio, bytelen, advice, 294*d65f6f70SBen Gras UBC_WRITE | UBC_UNMAP_FLAG(vp)); 295*d65f6f70SBen Gras if (error) 296*d65f6f70SBen Gras break; 297*d65f6f70SBen Gras 298*d65f6f70SBen Gras /* 299*d65f6f70SBen Gras * update UVM's notion of the size now that we've 300*d65f6f70SBen Gras * copied the data into the vnode's pages. 301*d65f6f70SBen Gras */ 302*d65f6f70SBen Gras 303*d65f6f70SBen Gras if (vp->v_size < uio->uio_offset) { 304*d65f6f70SBen Gras uvm_vnp_setsize(vp, uio->uio_offset); 305*d65f6f70SBen Gras extended = 1; 306*d65f6f70SBen Gras } 307*d65f6f70SBen Gras 308*d65f6f70SBen Gras /* 309*d65f6f70SBen Gras * flush what we just wrote if necessary. 310*d65f6f70SBen Gras * XXXUBC simplistic async flushing. 311*d65f6f70SBen Gras */ 312*d65f6f70SBen Gras 313*d65f6f70SBen Gras if (!async && oldoff >> 16 != uio->uio_offset >> 16) { 314*d65f6f70SBen Gras mutex_enter(vp->v_interlock); 315*d65f6f70SBen Gras error = VOP_PUTPAGES(vp, (oldoff >> 16) << 16, 316*d65f6f70SBen Gras (uio->uio_offset >> 16) << 16, PGO_CLEANIT); 317*d65f6f70SBen Gras } 318*d65f6f70SBen Gras } 319*d65f6f70SBen Gras if (error == 0 && ioflag & IO_SYNC) { 320*d65f6f70SBen Gras mutex_enter(vp->v_interlock); 321*d65f6f70SBen Gras error = VOP_PUTPAGES(vp, trunc_page(oldoff), 322*d65f6f70SBen Gras round_page(blkroundup(fs, uio->uio_offset)), 323*d65f6f70SBen Gras PGO_CLEANIT | PGO_SYNCIO); 324*d65f6f70SBen Gras } 325*d65f6f70SBen Gras 326*d65f6f70SBen Gras goto out; 327*d65f6f70SBen Gras } 328*d65f6f70SBen Gras 329*d65f6f70SBen Gras flags = ioflag & IO_SYNC ? B_SYNC : 0; 330*d65f6f70SBen Gras for (error = 0; uio->uio_resid > 0;) { 331*d65f6f70SBen Gras lbn = lblkno(fs, uio->uio_offset); 332*d65f6f70SBen Gras blkoffset = blkoff(fs, uio->uio_offset); 333*d65f6f70SBen Gras xfersize = MIN(fs->e2fs_bsize - blkoffset, uio->uio_resid); 334*d65f6f70SBen Gras if (xfersize < fs->e2fs_bsize) 335*d65f6f70SBen Gras flags |= B_CLRBUF; 336*d65f6f70SBen Gras else 337*d65f6f70SBen Gras flags &= ~B_CLRBUF; 338*d65f6f70SBen Gras error = ext2fs_balloc(ip, 339*d65f6f70SBen Gras lbn, blkoffset + xfersize, ap->a_cred, &bp, flags); 340*d65f6f70SBen Gras if (error) 341*d65f6f70SBen Gras break; 342*d65f6f70SBen Gras if (ext2fs_size(ip) < uio->uio_offset + xfersize) { 343*d65f6f70SBen Gras error = ext2fs_setsize(ip, uio->uio_offset + xfersize); 344*d65f6f70SBen Gras if (error) 345*d65f6f70SBen Gras break; 346*d65f6f70SBen Gras } 347*d65f6f70SBen Gras error = uiomove((char *)bp->b_data + blkoffset, xfersize, uio); 348*d65f6f70SBen Gras 349*d65f6f70SBen Gras /* 350*d65f6f70SBen Gras * update UVM's notion of the size now that we've 351*d65f6f70SBen Gras * copied the data into the vnode's pages. 352*d65f6f70SBen Gras */ 353*d65f6f70SBen Gras 354*d65f6f70SBen Gras if (vp->v_size < uio->uio_offset) { 355*d65f6f70SBen Gras uvm_vnp_setsize(vp, uio->uio_offset); 356*d65f6f70SBen Gras extended = 1; 357*d65f6f70SBen Gras } 358*d65f6f70SBen Gras 359*d65f6f70SBen Gras if (ioflag & IO_SYNC) 360*d65f6f70SBen Gras (void)bwrite(bp); 361*d65f6f70SBen Gras else if (xfersize + blkoffset == fs->e2fs_bsize) 362*d65f6f70SBen Gras bawrite(bp); 363*d65f6f70SBen Gras else 364*d65f6f70SBen Gras bdwrite(bp); 365*d65f6f70SBen Gras if (error || xfersize == 0) 366*d65f6f70SBen Gras break; 367*d65f6f70SBen Gras } 368*d65f6f70SBen Gras 369*d65f6f70SBen Gras /* 370*d65f6f70SBen Gras * If we successfully wrote any data, and we are not the superuser 371*d65f6f70SBen Gras * we clear the setuid and setgid bits as a precaution against 372*d65f6f70SBen Gras * tampering. 373*d65f6f70SBen Gras */ 374*d65f6f70SBen Gras 375*d65f6f70SBen Gras out: 376*d65f6f70SBen Gras ip->i_flag |= IN_CHANGE | IN_UPDATE; 377*d65f6f70SBen Gras if (vp->v_mount->mnt_flag & MNT_RELATIME) 378*d65f6f70SBen Gras ip->i_flag |= IN_ACCESS; 379*d65f6f70SBen Gras if (resid > uio->uio_resid && ap->a_cred && 380*d65f6f70SBen Gras kauth_authorize_generic(ap->a_cred, KAUTH_GENERIC_ISSUSER, NULL)) 381*d65f6f70SBen Gras ip->i_e2fs_mode &= ~(ISUID | ISGID); 382*d65f6f70SBen Gras if (resid > uio->uio_resid) 383*d65f6f70SBen Gras VN_KNOTE(vp, NOTE_WRITE | (extended ? NOTE_EXTEND : 0)); 384*d65f6f70SBen Gras if (error) { 385*d65f6f70SBen Gras (void) ext2fs_truncate(vp, osize, ioflag & IO_SYNC, ap->a_cred); 386*d65f6f70SBen Gras uio->uio_offset -= resid - uio->uio_resid; 387*d65f6f70SBen Gras uio->uio_resid = resid; 388*d65f6f70SBen Gras } else if (resid > uio->uio_resid && (ioflag & IO_SYNC) == IO_SYNC) 389*d65f6f70SBen Gras error = ext2fs_update(vp, NULL, NULL, UPDATE_WAIT); 390*d65f6f70SBen Gras KASSERT(vp->v_size == ext2fs_size(ip)); 391*d65f6f70SBen Gras return (error); 392*d65f6f70SBen Gras } 393