Changeset View
Changeset View
Standalone View
Standalone View
head/sys/fs/nfsclient/nfs_clbio.c
Show First 20 Lines • Show All 54 Lines • ▼ Show 20 Lines | |||||
#include <fs/nfs/nfsport.h> | #include <fs/nfs/nfsport.h> | ||||
#include <fs/nfsclient/nfsmount.h> | #include <fs/nfsclient/nfsmount.h> | ||||
#include <fs/nfsclient/nfs.h> | #include <fs/nfsclient/nfs.h> | ||||
#include <fs/nfsclient/nfsnode.h> | #include <fs/nfsclient/nfsnode.h> | ||||
#include <fs/nfsclient/nfs_kdtrace.h> | #include <fs/nfsclient/nfs_kdtrace.h> | ||||
extern int newnfs_directio_allow_mmap; | extern int newnfs_directio_allow_mmap; | ||||
extern struct nfsstats newnfsstats; | extern struct nfsstatsv1 nfsstatsv1; | ||||
extern struct mtx ncl_iod_mutex; | extern struct mtx ncl_iod_mutex; | ||||
extern int ncl_numasync; | extern int ncl_numasync; | ||||
extern enum nfsiod_state ncl_iodwant[NFS_MAXASYNCDAEMON]; | extern enum nfsiod_state ncl_iodwant[NFS_MAXASYNCDAEMON]; | ||||
extern struct nfsmount *ncl_iodmount[NFS_MAXASYNCDAEMON]; | extern struct nfsmount *ncl_iodmount[NFS_MAXASYNCDAEMON]; | ||||
extern int newnfs_directio_enable; | extern int newnfs_directio_enable; | ||||
extern int nfs_keep_dirty_on_error; | extern int nfs_keep_dirty_on_error; | ||||
int ncl_pbuf_freecnt = -1; /* start out unlimited */ | int ncl_pbuf_freecnt = -1; /* start out unlimited */ | ||||
▲ Show 20 Lines • Show All 389 Lines • ▼ Show 20 Lines | do { | ||||
u_quad_t nsize; | u_quad_t nsize; | ||||
mtx_lock(&np->n_mtx); | mtx_lock(&np->n_mtx); | ||||
nsize = np->n_size; | nsize = np->n_size; | ||||
mtx_unlock(&np->n_mtx); | mtx_unlock(&np->n_mtx); | ||||
switch (vp->v_type) { | switch (vp->v_type) { | ||||
case VREG: | case VREG: | ||||
NFSINCRGLOBAL(newnfsstats.biocache_reads); | NFSINCRGLOBAL(nfsstatsv1.biocache_reads); | ||||
lbn = uio->uio_offset / biosize; | lbn = uio->uio_offset / biosize; | ||||
on = uio->uio_offset - (lbn * biosize); | on = uio->uio_offset - (lbn * biosize); | ||||
/* | /* | ||||
* Start the read ahead(s), as required. | * Start the read ahead(s), as required. | ||||
*/ | */ | ||||
if (nmp->nm_readahead > 0) { | if (nmp->nm_readahead > 0) { | ||||
for (nra = 0; nra < nmp->nm_readahead && nra < seqcount && | for (nra = 0; nra < nmp->nm_readahead && nra < seqcount && | ||||
▲ Show 20 Lines • Show All 60 Lines • ▼ Show 20 Lines | do { | ||||
* Then figure out how many bytes we can copy into the uio. | * Then figure out how many bytes we can copy into the uio. | ||||
*/ | */ | ||||
n = 0; | n = 0; | ||||
if (on < bcount) | if (on < bcount) | ||||
n = MIN((unsigned)(bcount - on), uio->uio_resid); | n = MIN((unsigned)(bcount - on), uio->uio_resid); | ||||
break; | break; | ||||
case VLNK: | case VLNK: | ||||
NFSINCRGLOBAL(newnfsstats.biocache_readlinks); | NFSINCRGLOBAL(nfsstatsv1.biocache_readlinks); | ||||
bp = nfs_getcacheblk(vp, (daddr_t)0, NFS_MAXPATHLEN, td); | bp = nfs_getcacheblk(vp, (daddr_t)0, NFS_MAXPATHLEN, td); | ||||
if (!bp) { | if (!bp) { | ||||
error = newnfs_sigintr(nmp, td); | error = newnfs_sigintr(nmp, td); | ||||
return (error ? error : EINTR); | return (error ? error : EINTR); | ||||
} | } | ||||
if ((bp->b_flags & B_CACHE) == 0) { | if ((bp->b_flags & B_CACHE) == 0) { | ||||
bp->b_iocmd = BIO_READ; | bp->b_iocmd = BIO_READ; | ||||
vfs_busy_pages(bp, 0); | vfs_busy_pages(bp, 0); | ||||
error = ncl_doio(vp, bp, cred, td, 0); | error = ncl_doio(vp, bp, cred, td, 0); | ||||
if (error) { | if (error) { | ||||
bp->b_ioflags |= BIO_ERROR; | bp->b_ioflags |= BIO_ERROR; | ||||
brelse(bp); | brelse(bp); | ||||
return (error); | return (error); | ||||
} | } | ||||
} | } | ||||
n = MIN(uio->uio_resid, NFS_MAXPATHLEN - bp->b_resid); | n = MIN(uio->uio_resid, NFS_MAXPATHLEN - bp->b_resid); | ||||
on = 0; | on = 0; | ||||
break; | break; | ||||
case VDIR: | case VDIR: | ||||
NFSINCRGLOBAL(newnfsstats.biocache_readdirs); | NFSINCRGLOBAL(nfsstatsv1.biocache_readdirs); | ||||
if (np->n_direofoffset | if (np->n_direofoffset | ||||
&& uio->uio_offset >= np->n_direofoffset) { | && uio->uio_offset >= np->n_direofoffset) { | ||||
return (0); | return (0); | ||||
} | } | ||||
lbn = (uoff_t)uio->uio_offset / NFS_DIRBLKSIZ; | lbn = (uoff_t)uio->uio_offset / NFS_DIRBLKSIZ; | ||||
on = uio->uio_offset & (NFS_DIRBLKSIZ - 1); | on = uio->uio_offset & (NFS_DIRBLKSIZ - 1); | ||||
bp = nfs_getcacheblk(vp, lbn, NFS_DIRBLKSIZ, td); | bp = nfs_getcacheblk(vp, lbn, NFS_DIRBLKSIZ, td); | ||||
if (!bp) { | if (!bp) { | ||||
▲ Show 20 Lines • Show All 412 Lines • ▼ Show 20 Lines | if (!(ioflag & IO_SYNC)) { | ||||
KDTRACE_NFS_ATTRCACHE_FLUSH_DONE(vp); | KDTRACE_NFS_ATTRCACHE_FLUSH_DONE(vp); | ||||
error = ncl_vinvalbuf(vp, V_SAVE, td, 1); | error = ncl_vinvalbuf(vp, V_SAVE, td, 1); | ||||
if (error) | if (error) | ||||
return (error); | return (error); | ||||
wouldcommit = biosize; | wouldcommit = biosize; | ||||
} | } | ||||
} | } | ||||
NFSINCRGLOBAL(newnfsstats.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); | ||||
again: | again: | ||||
/* | /* | ||||
* Handle direct append and file extension cases, calculate | * Handle direct append and file extension cases, calculate | ||||
* unaligned buffer size. | * unaligned buffer size. | ||||
*/ | */ | ||||
▲ Show 20 Lines • Show All 597 Lines • ▼ Show 20 Lines | ncl_doio(struct vnode *vp, struct buf *bp, struct ucred *cr, struct thread *td, | ||||
if (iocmd == BIO_READ) { | if (iocmd == BIO_READ) { | ||||
io.iov_len = uiop->uio_resid = bp->b_bcount; | io.iov_len = uiop->uio_resid = bp->b_bcount; | ||||
io.iov_base = bp->b_data; | io.iov_base = bp->b_data; | ||||
uiop->uio_rw = UIO_READ; | uiop->uio_rw = UIO_READ; | ||||
switch (vp->v_type) { | switch (vp->v_type) { | ||||
case VREG: | case VREG: | ||||
uiop->uio_offset = ((off_t)bp->b_blkno) * DEV_BSIZE; | uiop->uio_offset = ((off_t)bp->b_blkno) * DEV_BSIZE; | ||||
NFSINCRGLOBAL(newnfsstats.read_bios); | NFSINCRGLOBAL(nfsstatsv1.read_bios); | ||||
error = ncl_readrpc(vp, uiop, cr); | error = ncl_readrpc(vp, uiop, cr); | ||||
if (!error) { | if (!error) { | ||||
if (uiop->uio_resid) { | if (uiop->uio_resid) { | ||||
/* | /* | ||||
* If we had a short read with no error, we must have | * If we had a short read with no error, we must have | ||||
* hit a file hole. We should zero-fill the remainder. | * hit a file hole. We should zero-fill the remainder. | ||||
* This can also occur if the server hits the file EOF. | * This can also occur if the server hits the file EOF. | ||||
Show All 18 Lines | if (p && (vp->v_vflag & VV_TEXT)) { | ||||
killproc(p, "text file modification"); | killproc(p, "text file modification"); | ||||
PROC_UNLOCK(p); | PROC_UNLOCK(p); | ||||
} else | } else | ||||
mtx_unlock(&np->n_mtx); | mtx_unlock(&np->n_mtx); | ||||
} | } | ||||
break; | break; | ||||
case VLNK: | case VLNK: | ||||
uiop->uio_offset = (off_t)0; | uiop->uio_offset = (off_t)0; | ||||
NFSINCRGLOBAL(newnfsstats.readlink_bios); | NFSINCRGLOBAL(nfsstatsv1.readlink_bios); | ||||
error = ncl_readlinkrpc(vp, uiop, cr); | error = ncl_readlinkrpc(vp, uiop, cr); | ||||
break; | break; | ||||
case VDIR: | case VDIR: | ||||
NFSINCRGLOBAL(newnfsstats.readdir_bios); | NFSINCRGLOBAL(nfsstatsv1.readdir_bios); | ||||
uiop->uio_offset = ((u_quad_t)bp->b_lblkno) * NFS_DIRBLKSIZ; | uiop->uio_offset = ((u_quad_t)bp->b_lblkno) * NFS_DIRBLKSIZ; | ||||
if ((nmp->nm_flag & NFSMNT_RDIRPLUS) != 0) { | if ((nmp->nm_flag & NFSMNT_RDIRPLUS) != 0) { | ||||
error = ncl_readdirplusrpc(vp, uiop, cr, td); | error = ncl_readdirplusrpc(vp, uiop, cr, td); | ||||
if (error == NFSERR_NOTSUPP) | if (error == NFSERR_NOTSUPP) | ||||
nmp->nm_flag &= ~NFSMNT_RDIRPLUS; | nmp->nm_flag &= ~NFSMNT_RDIRPLUS; | ||||
} | } | ||||
if ((nmp->nm_flag & NFSMNT_RDIRPLUS) == 0) | if ((nmp->nm_flag & NFSMNT_RDIRPLUS) == 0) | ||||
error = ncl_readdirrpc(vp, uiop, cr, td); | error = ncl_readdirrpc(vp, uiop, cr, td); | ||||
▲ Show 20 Lines • Show All 45 Lines • ▼ Show 20 Lines | bp->b_dirtyend = np->n_size - (off_t)bp->b_blkno * DEV_BSIZE; | ||||
if (bp->b_dirtyend > bp->b_dirtyoff) { | if (bp->b_dirtyend > bp->b_dirtyoff) { | ||||
io.iov_len = uiop->uio_resid = bp->b_dirtyend | io.iov_len = uiop->uio_resid = bp->b_dirtyend | ||||
- bp->b_dirtyoff; | - bp->b_dirtyoff; | ||||
uiop->uio_offset = (off_t)bp->b_blkno * DEV_BSIZE | uiop->uio_offset = (off_t)bp->b_blkno * DEV_BSIZE | ||||
+ bp->b_dirtyoff; | + bp->b_dirtyoff; | ||||
io.iov_base = (char *)bp->b_data + bp->b_dirtyoff; | io.iov_base = (char *)bp->b_data + bp->b_dirtyoff; | ||||
uiop->uio_rw = UIO_WRITE; | uiop->uio_rw = UIO_WRITE; | ||||
NFSINCRGLOBAL(newnfsstats.write_bios); | NFSINCRGLOBAL(nfsstatsv1.write_bios); | ||||
if ((bp->b_flags & (B_ASYNC | B_NEEDCOMMIT | B_NOCACHE | B_CLUSTER)) == B_ASYNC) | if ((bp->b_flags & (B_ASYNC | B_NEEDCOMMIT | B_NOCACHE | B_CLUSTER)) == B_ASYNC) | ||||
iomode = NFSWRITE_UNSTABLE; | iomode = NFSWRITE_UNSTABLE; | ||||
else | else | ||||
iomode = NFSWRITE_FILESYNC; | iomode = NFSWRITE_FILESYNC; | ||||
error = ncl_writerpc(vp, uiop, cr, &iomode, &must_commit, | error = ncl_writerpc(vp, uiop, cr, &iomode, &must_commit, | ||||
called_from_strategy); | called_from_strategy); | ||||
▲ Show 20 Lines • Show All 149 Lines • Show Last 20 Lines |