Changeset View
Changeset View
Standalone View
Standalone View
sys/fs/nfsclient/nfs_clbio.c
Show First 20 Lines • Show All 64 Lines • ▼ Show 20 Lines | |||||
extern struct nfsstatsv1 nfsstatsv1; | 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 */ | uma_zone_t ncl_pbuf_zone; | ||||
static struct buf *nfs_getcacheblk(struct vnode *vp, daddr_t bn, int size, | static struct buf *nfs_getcacheblk(struct vnode *vp, daddr_t bn, int size, | ||||
struct thread *td); | struct thread *td); | ||||
static int nfs_directio_write(struct vnode *vp, struct uio *uiop, | static int nfs_directio_write(struct vnode *vp, struct uio *uiop, | ||||
struct ucred *cred, int ioflag); | struct ucred *cred, int ioflag); | ||||
/* | /* | ||||
* Vnode op for VM getpages. | * Vnode op for VM getpages. | ||||
▲ Show 20 Lines • Show All 95 Lines • ▼ Show 20 Lines | ncl_getpages(struct vop_getpages_args *ap) | ||||
if (pages[npages - 1]->valid != 0 && --npages == 0) | if (pages[npages - 1]->valid != 0 && --npages == 0) | ||||
goto out; | goto out; | ||||
VM_OBJECT_WUNLOCK(object); | VM_OBJECT_WUNLOCK(object); | ||||
/* | /* | ||||
* We use only the kva address for the buffer, but this is extremely | * We use only the kva address for the buffer, but this is extremely | ||||
* convenient and fast. | * convenient and fast. | ||||
*/ | */ | ||||
bp = getpbuf(&ncl_pbuf_freecnt); | bp = uma_zalloc(ncl_pbuf_zone, M_WAITOK); | ||||
kva = (vm_offset_t) bp->b_data; | kva = (vm_offset_t) bp->b_data; | ||||
pmap_qenter(kva, pages, npages); | pmap_qenter(kva, pages, npages); | ||||
VM_CNT_INC(v_vnodein); | VM_CNT_INC(v_vnodein); | ||||
VM_CNT_ADD(v_vnodepgsin, npages); | VM_CNT_ADD(v_vnodepgsin, npages); | ||||
count = npages << PAGE_SHIFT; | count = npages << PAGE_SHIFT; | ||||
iov.iov_base = (caddr_t) kva; | iov.iov_base = (caddr_t) kva; | ||||
iov.iov_len = count; | iov.iov_len = count; | ||||
uio.uio_iov = &iov; | uio.uio_iov = &iov; | ||||
uio.uio_iovcnt = 1; | uio.uio_iovcnt = 1; | ||||
uio.uio_offset = IDX_TO_OFF(pages[0]->pindex); | uio.uio_offset = IDX_TO_OFF(pages[0]->pindex); | ||||
uio.uio_resid = count; | uio.uio_resid = count; | ||||
uio.uio_segflg = UIO_SYSSPACE; | uio.uio_segflg = UIO_SYSSPACE; | ||||
uio.uio_rw = UIO_READ; | uio.uio_rw = UIO_READ; | ||||
uio.uio_td = td; | uio.uio_td = td; | ||||
error = ncl_readrpc(vp, &uio, cred); | error = ncl_readrpc(vp, &uio, cred); | ||||
pmap_qremove(kva, npages); | pmap_qremove(kva, npages); | ||||
relpbuf(bp, &ncl_pbuf_freecnt); | uma_zfree(ncl_pbuf_zone, bp); | ||||
if (error && (uio.uio_resid == count)) { | if (error && (uio.uio_resid == count)) { | ||||
printf("ncl_getpages: error %d\n", error); | printf("ncl_getpages: error %d\n", error); | ||||
return (VM_PAGER_ERROR); | return (VM_PAGER_ERROR); | ||||
} | } | ||||
/* | /* | ||||
* Calculate the number of bytes read and validate only that number | * Calculate the number of bytes read and validate only that number | ||||
▲ Show 20 Lines • Show All 573 Lines • ▼ Show 20 Lines | do_sync: | ||||
* data here directly into mbufs and passing the mbuf chain | * data here directly into mbufs and passing the mbuf chain | ||||
* down. But that will require a fair amount of re-working | * down. But that will require a fair amount of re-working | ||||
* of the code and can be done if there's enough interest | * of the code and can be done if there's enough interest | ||||
* in NFS directio access. | * in NFS directio access. | ||||
*/ | */ | ||||
while (uiop->uio_resid > 0) { | while (uiop->uio_resid > 0) { | ||||
size = MIN(uiop->uio_resid, wsize); | size = MIN(uiop->uio_resid, wsize); | ||||
size = MIN(uiop->uio_iov->iov_len, size); | size = MIN(uiop->uio_iov->iov_len, size); | ||||
bp = getpbuf(&ncl_pbuf_freecnt); | bp = uma_zalloc(ncl_pbuf_zone, M_WAITOK); | ||||
t_uio = malloc(sizeof(struct uio), M_NFSDIRECTIO, M_WAITOK); | t_uio = malloc(sizeof(struct uio), M_NFSDIRECTIO, M_WAITOK); | ||||
t_iov = malloc(sizeof(struct iovec), M_NFSDIRECTIO, M_WAITOK); | t_iov = malloc(sizeof(struct iovec), M_NFSDIRECTIO, M_WAITOK); | ||||
t_iov->iov_base = malloc(size, M_NFSDIRECTIO, M_WAITOK); | t_iov->iov_base = malloc(size, M_NFSDIRECTIO, M_WAITOK); | ||||
t_iov->iov_len = size; | t_iov->iov_len = size; | ||||
t_uio->uio_iov = t_iov; | t_uio->uio_iov = t_iov; | ||||
t_uio->uio_iovcnt = 1; | t_uio->uio_iovcnt = 1; | ||||
t_uio->uio_offset = uiop->uio_offset; | t_uio->uio_offset = uiop->uio_offset; | ||||
t_uio->uio_resid = size; | t_uio->uio_resid = size; | ||||
Show All 26 Lines | while (uiop->uio_resid > 0) { | ||||
bp->b_vp = vp; | bp->b_vp = vp; | ||||
error = ncl_asyncio(nmp, bp, NOCRED, td); | error = ncl_asyncio(nmp, bp, NOCRED, td); | ||||
err_free: | err_free: | ||||
if (error) { | if (error) { | ||||
free(t_iov->iov_base, M_NFSDIRECTIO); | free(t_iov->iov_base, M_NFSDIRECTIO); | ||||
free(t_iov, M_NFSDIRECTIO); | free(t_iov, M_NFSDIRECTIO); | ||||
free(t_uio, M_NFSDIRECTIO); | free(t_uio, M_NFSDIRECTIO); | ||||
bp->b_vp = NULL; | bp->b_vp = NULL; | ||||
relpbuf(bp, &ncl_pbuf_freecnt); | uma_zfree(ncl_pbuf_zone, bp); | ||||
if (error == EINTR) | if (error == EINTR) | ||||
return (error); | return (error); | ||||
goto do_sync; | goto do_sync; | ||||
} | } | ||||
uiop->uio_offset += size; | uiop->uio_offset += size; | ||||
uiop->uio_resid -= size; | uiop->uio_resid -= size; | ||||
if (uiop->uio_iov->iov_len <= size) { | if (uiop->uio_iov->iov_len <= size) { | ||||
uiop->uio_iovcnt--; | uiop->uio_iovcnt--; | ||||
▲ Show 20 Lines • Show All 718 Lines • ▼ Show 20 Lines | if (np->n_directio_asyncwr == 0) { | ||||
if ((np->n_flag & NFSYNCWAIT)) { | if ((np->n_flag & NFSYNCWAIT)) { | ||||
np->n_flag &= ~NFSYNCWAIT; | np->n_flag &= ~NFSYNCWAIT; | ||||
wakeup((caddr_t)&np->n_directio_asyncwr); | wakeup((caddr_t)&np->n_directio_asyncwr); | ||||
} | } | ||||
} | } | ||||
mtx_unlock(&np->n_mtx); | mtx_unlock(&np->n_mtx); | ||||
} | } | ||||
bp->b_vp = NULL; | bp->b_vp = NULL; | ||||
relpbuf(bp, &ncl_pbuf_freecnt); | uma_zfree(ncl_pbuf_zone, bp); | ||||
} | } | ||||
/* | /* | ||||
* Do an I/O operation to/from a cache block. This may be called | * Do an I/O operation to/from a cache block. This may be called | ||||
* synchronously or from an nfsiod. | * synchronously or from an nfsiod. | ||||
*/ | */ | ||||
int | int | ||||
ncl_doio(struct vnode *vp, struct buf *bp, struct ucred *cr, struct thread *td, | ncl_doio(struct vnode *vp, struct buf *bp, struct ucred *cr, struct thread *td, | ||||
▲ Show 20 Lines • Show All 292 Lines • Show Last 20 Lines |