Changeset View
Changeset View
Standalone View
Standalone View
sys/fs/nfsclient/nfs_clbio.c
Show First 20 Lines • Show All 887 Lines • ▼ Show 20 Lines | ncl_write(struct vop_write_args *ap) | ||||
struct nfsnode *np = VTONFS(vp); | struct nfsnode *np = VTONFS(vp); | ||||
struct ucred *cred = ap->a_cred; | struct ucred *cred = ap->a_cred; | ||||
int ioflag = ap->a_ioflag; | int ioflag = ap->a_ioflag; | ||||
struct buf *bp; | struct buf *bp; | ||||
struct vattr vattr; | struct vattr vattr; | ||||
struct nfsmount *nmp = VFSTONFS(vp->v_mount); | struct nfsmount *nmp = VFSTONFS(vp->v_mount); | ||||
daddr_t lbn; | daddr_t lbn; | ||||
int bcount, noncontig_write, obcount; | int bcount, noncontig_write, obcount; | ||||
int bp_cached, n, on, error = 0, error1, wouldcommit; | int bp_cached, n, on, error = 0, error1, save2, wouldcommit; | ||||
size_t orig_resid, local_resid; | size_t orig_resid, local_resid; | ||||
off_t orig_size, tmp_off; | off_t orig_size, tmp_off; | ||||
KASSERT(uio->uio_rw == UIO_WRITE, ("ncl_write mode")); | KASSERT(uio->uio_rw == UIO_WRITE, ("ncl_write mode")); | ||||
KASSERT(uio->uio_segflg != UIO_USERSPACE || uio->uio_td == curthread, | KASSERT(uio->uio_segflg != UIO_USERSPACE || uio->uio_td == curthread, | ||||
("ncl_write proc")); | ("ncl_write proc")); | ||||
if (vp->v_type != VREG) | if (vp->v_type != VREG) | ||||
return (EIO); | return (EIO); | ||||
▲ Show 20 Lines • Show All 75 Lines • ▼ Show 20 Lines | #endif | ||||
/* | /* | ||||
* Maybe this should be above the vnode op call, but so long as | * Maybe this should be above the vnode op call, but so long as | ||||
* file servers have no limits, i don't think it matters | * file servers have no limits, i don't think it matters | ||||
*/ | */ | ||||
if (vn_rlimit_fsize(vp, uio, td)) | if (vn_rlimit_fsize(vp, uio, td)) | ||||
return (EFBIG); | return (EFBIG); | ||||
save2 = curthread_pflags2_set(TDP2_SBPAGES); | |||||
biosize = vp->v_bufobj.bo_bsize; | biosize = vp->v_bufobj.bo_bsize; | ||||
/* | /* | ||||
* Find all of this file's B_NEEDCOMMIT buffers. If our writes | * Find all of this file's B_NEEDCOMMIT buffers. If our writes | ||||
* would exceed the local maximum per-file write commit size when | * would exceed the local maximum per-file write commit size when | ||||
* combined with those, we must decide whether to flush, | * combined with those, we must decide whether to flush, | ||||
* go synchronous, or return error. We don't bother checking | * go synchronous, or return error. We don't bother checking | ||||
* IO_UNIT -- we just make all writes atomic anyway, as there's | * IO_UNIT -- we just make all writes atomic anyway, as there's | ||||
* no point optimizing for something that really won't ever happen. | * no point optimizing for something that really won't ever happen. | ||||
Show All 22 Lines | do { | ||||
if (!(ioflag & IO_SYNC)) { | if (!(ioflag & IO_SYNC)) { | ||||
wouldcommit += biosize; | wouldcommit += biosize; | ||||
if (wouldcommit > nmp->nm_wcommitsize) { | if (wouldcommit > nmp->nm_wcommitsize) { | ||||
np->n_attrstamp = 0; | np->n_attrstamp = 0; | ||||
KDTRACE_NFS_ATTRCACHE_FLUSH_DONE(vp); | KDTRACE_NFS_ATTRCACHE_FLUSH_DONE(vp); | ||||
error = ncl_vinvalbuf(vp, V_SAVE | ((ioflag & | error = ncl_vinvalbuf(vp, V_SAVE | ((ioflag & | ||||
IO_VMIO) != 0 ? V_VMIO : 0), td, 1); | IO_VMIO) != 0 ? V_VMIO : 0), td, 1); | ||||
if (error != 0) | if (error != 0) | ||||
return (error); | goto out; | ||||
wouldcommit = biosize; | wouldcommit = biosize; | ||||
} | } | ||||
} | } | ||||
NFSINCRGLOBAL(nfsstatsv1.biocache_writes); | NFSINCRGLOBAL(nfsstatsv1.biocache_writes); | ||||
lbn = uio->uio_offset / biosize; | lbn = uio->uio_offset / biosize; | ||||
on = uio->uio_offset - (lbn * biosize); | on = uio->uio_offset - (lbn * biosize); | ||||
n = MIN((unsigned)(biosize - on), uio->uio_resid); | n = MIN((unsigned)(biosize - on), uio->uio_resid); | ||||
Show All 23 Lines | if ((uio->uio_offset == np->n_size || | ||||
bp = nfs_getcacheblk(vp, lbn, obcount, td); | bp = nfs_getcacheblk(vp, lbn, obcount, td); | ||||
if (bp != NULL) { | if (bp != NULL) { | ||||
long save; | long save; | ||||
NFSLOCKNODE(np); | NFSLOCKNODE(np); | ||||
np->n_size = uio->uio_offset + n; | np->n_size = uio->uio_offset + n; | ||||
np->n_flag |= NMODIFIED; | np->n_flag |= NMODIFIED; | ||||
np->n_flag &= ~NVNSETSZSKIP; | |||||
vnode_pager_setsize(vp, np->n_size); | vnode_pager_setsize(vp, np->n_size); | ||||
NFSUNLOCKNODE(np); | NFSUNLOCKNODE(np); | ||||
save = bp->b_flags & B_CACHE; | save = bp->b_flags & B_CACHE; | ||||
bcount = on + n; | bcount = on + n; | ||||
allocbuf(bp, bcount); | allocbuf(bp, bcount); | ||||
bp->b_flags |= save; | bp->b_flags |= save; | ||||
if (noncontig_write != 0 && on > obcount) | if (noncontig_write != 0 && on > obcount) | ||||
Show All 13 Lines | if ((uio->uio_offset == np->n_size || | ||||
bcount = np->n_size - (off_t)lbn * biosize; | bcount = np->n_size - (off_t)lbn * biosize; | ||||
} | } | ||||
NFSUNLOCKNODE(np); | NFSUNLOCKNODE(np); | ||||
bp = nfs_getcacheblk(vp, lbn, bcount, td); | bp = nfs_getcacheblk(vp, lbn, bcount, td); | ||||
NFSLOCKNODE(np); | NFSLOCKNODE(np); | ||||
if (uio->uio_offset + n > np->n_size) { | if (uio->uio_offset + n > np->n_size) { | ||||
np->n_size = uio->uio_offset + n; | np->n_size = uio->uio_offset + n; | ||||
np->n_flag |= NMODIFIED; | np->n_flag |= NMODIFIED; | ||||
np->n_flag &= ~NVNSETSZSKIP; | |||||
vnode_pager_setsize(vp, np->n_size); | vnode_pager_setsize(vp, np->n_size); | ||||
} | } | ||||
NFSUNLOCKNODE(np); | NFSUNLOCKNODE(np); | ||||
} | } | ||||
if (!bp) { | if (!bp) { | ||||
error = newnfs_sigintr(nmp, td); | error = newnfs_sigintr(nmp, td); | ||||
if (!error) | if (!error) | ||||
▲ Show 20 Lines • Show All 171 Lines • ▼ Show 20 Lines | if (error != 0) { | ||||
if (ioflag & IO_UNIT) { | if (ioflag & IO_UNIT) { | ||||
VATTR_NULL(&vattr); | VATTR_NULL(&vattr); | ||||
vattr.va_size = orig_size; | vattr.va_size = orig_size; | ||||
/* IO_SYNC is handled implicitely */ | /* IO_SYNC is handled implicitely */ | ||||
(void)VOP_SETATTR(vp, &vattr, cred); | (void)VOP_SETATTR(vp, &vattr, cred); | ||||
uio->uio_offset -= orig_resid - uio->uio_resid; | uio->uio_offset -= orig_resid - uio->uio_resid; | ||||
uio->uio_resid = orig_resid; | uio->uio_resid = orig_resid; | ||||
} | } | ||||
} | |||||
out: | |||||
curthread_pflags2_restore(save2); | |||||
if ((curthread->td_pflags2 & TDP2_SBPAGES) == 0) { | |||||
NFSLOCKNODE(np); | |||||
ncl_pager_setsize(vp, NULL); | |||||
} | } | ||||
return (error); | return (error); | ||||
} | } | ||||
/* | /* | ||||
* Get an nfs cache block. | * Get an nfs cache block. | ||||
* | * | ||||
▲ Show 20 Lines • Show All 603 Lines • Show Last 20 Lines |