Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F157591341
D10241.id27010.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
13 KB
Referenced Files
None
Subscribers
None
D10241.id27010.diff
View Options
Index: sys/fs/nfsclient/nfs_clbio.c
===================================================================
--- sys/fs/nfsclient/nfs_clbio.c
+++ sys/fs/nfsclient/nfs_clbio.c
@@ -266,9 +266,7 @@
{
struct uio uio;
struct iovec iov;
- vm_offset_t kva;
- struct buf *bp;
- int iomode, must_commit, i, error, npages, count;
+ int i, error, npages, count;
off_t offset;
int *rtvals;
struct vnode *vp;
@@ -322,44 +320,26 @@
}
mtx_unlock(&np->n_mtx);
- /*
- * We use only the kva address for the buffer, but this is extremely
- * convenient and fast.
- */
- bp = getpbuf(&ncl_pbuf_freecnt);
-
- kva = (vm_offset_t) bp->b_data;
- pmap_qenter(kva, pages, npages);
PCPU_INC(cnt.v_vnodeout);
PCPU_ADD(cnt.v_vnodepgsout, count);
- iov.iov_base = (caddr_t) kva;
+ iov.iov_base = unmapped_buf;
iov.iov_len = count;
uio.uio_iov = &iov;
uio.uio_iovcnt = 1;
uio.uio_offset = offset;
uio.uio_resid = count;
- uio.uio_segflg = UIO_SYSSPACE;
+ uio.uio_segflg = UIO_NOCOPY;
uio.uio_rw = UIO_WRITE;
uio.uio_td = td;
- if ((ap->a_sync & VM_PAGER_PUT_SYNC) == 0)
- iomode = NFSWRITE_UNSTABLE;
- else
- iomode = NFSWRITE_FILESYNC;
-
- error = ncl_writerpc(vp, &uio, cred, &iomode, &must_commit, 0);
+ error = VOP_WRITE(vp, &uio, vnode_pager_putpages_ioflags(ap->a_sync),
+ cred);
crfree(cred);
- pmap_qremove(kva, npages);
- relpbuf(bp, &ncl_pbuf_freecnt);
-
- if (error == 0 || !nfs_keep_dirty_on_error) {
+ if (error == 0 || !nfs_keep_dirty_on_error)
vnode_pager_undirty_pages(pages, rtvals, count - uio.uio_resid);
- if (must_commit)
- ncl_clearcommit(vp->v_mount);
- }
- return rtvals[0];
+ return (rtvals[0]);
}
/*
@@ -394,8 +374,8 @@
*/
old_lock = ncl_upgrade_vnlock(vp);
if (vp->v_iflag & VI_DOOMED) {
- ncl_downgrade_vnlock(vp, old_lock);
- return (EBADF);
+ error = EBADF;
+ goto out;
}
mtx_lock(&np->n_mtx);
@@ -406,7 +386,9 @@
panic("nfs: bioread, not dir");
ncl_invaldir(vp);
error = ncl_vinvalbuf(vp, V_SAVE, td, 1);
- if (error)
+ if (error == 0 && (vp->v_iflag & VI_DOOMED) != 0)
+ error = EBADF;
+ if (error != 0)
goto out;
}
np->n_attrstamp = 0;
@@ -429,7 +411,9 @@
if (vp->v_type == VDIR)
ncl_invaldir(vp);
error = ncl_vinvalbuf(vp, V_SAVE, td, 1);
- if (error)
+ if (error == 0 && (vp->v_iflag & VI_DOOMED) != 0)
+ error = EBADF;
+ if (error != 0)
goto out;
mtx_lock(&np->n_mtx);
np->n_mtime = vattr.va_mtime;
@@ -439,7 +423,7 @@
}
out:
ncl_downgrade_vnlock(vp, old_lock);
- return error;
+ return (error);
}
/*
@@ -623,6 +607,9 @@
while (error == NFSERR_BAD_COOKIE) {
ncl_invaldir(vp);
error = ncl_vinvalbuf(vp, 0, td, 1);
+ if (error == 0 && (vp->v_iflag & VI_DOOMED) != 0)
+ return (EBADF);
+
/*
* Yuck! The directory has been modified on the
* server. The only way to get the block is by
@@ -943,8 +930,11 @@
#endif
np->n_attrstamp = 0;
KDTRACE_NFS_ATTRCACHE_FLUSH_DONE(vp);
- error = ncl_vinvalbuf(vp, V_SAVE, td, 1);
- if (error)
+ error = ncl_vinvalbuf(vp, V_SAVE | ((ioflag &
+ IO_VMIO) != 0 ? V_VMIO : 0), td, 1);
+ if (error == 0 && (vp->v_iflag & VI_DOOMED) != 0)
+ error = EBADF;
+ if (error != 0)
return (error);
} else
mtx_unlock(&np->n_mtx);
@@ -1023,8 +1013,12 @@
if (wouldcommit > nmp->nm_wcommitsize) {
np->n_attrstamp = 0;
KDTRACE_NFS_ATTRCACHE_FLUSH_DONE(vp);
- error = ncl_vinvalbuf(vp, V_SAVE, td, 1);
- if (error)
+ error = ncl_vinvalbuf(vp, V_SAVE | ((ioflag &
+ IO_VMIO) != 0 ? V_VMIO : 0), td, 1);
+ if (error == 0 &&
+ (vp->v_iflag & VI_DOOMED) != 0)
+ error = EBADF;
+ if (error != 0)
return (error);
wouldcommit = biosize;
}
@@ -1261,7 +1255,7 @@
error = error1;
break;
}
- } else if ((n + on) == biosize) {
+ } else if ((n + on) == biosize || (ioflag & IO_ASYNC) != 0) {
bp->b_flags |= B_ASYNC;
(void) ncl_writebp(bp, 0, NULL);
} else {
@@ -1371,7 +1365,8 @@
/*
* Now, flush as required.
*/
- if ((flags & V_SAVE) && (vp->v_bufobj.bo_object != NULL)) {
+ if ((flags & (V_SAVE | V_VMIO)) == V_SAVE &&
+ vp->v_bufobj.bo_object != NULL) {
VM_OBJECT_WLOCK(vp->v_bufobj.bo_object);
vm_object_page_clean(vp->v_bufobj.bo_object, 0, 0, OBJPC_SYNC);
VM_OBJECT_WUNLOCK(vp->v_bufobj.bo_object);
Index: sys/fs/nfsclient/nfs_clvnops.c
===================================================================
--- sys/fs/nfsclient/nfs_clvnops.c
+++ sys/fs/nfsclient/nfs_clvnops.c
@@ -520,6 +520,8 @@
if (np->n_flag & NMODIFIED) {
mtx_unlock(&np->n_mtx);
error = ncl_vinvalbuf(vp, V_SAVE, ap->a_td, 1);
+ if (error == 0 && (vp->v_iflag & VI_DOOMED) != 0)
+ return (EBADF);
if (error == EINTR || error == EIO) {
if (NFS_ISV4(vp))
(void) nfsrpc_close(vp, 0, ap->a_td);
@@ -556,6 +558,8 @@
np->n_direofoffset = 0;
mtx_unlock(&np->n_mtx);
error = ncl_vinvalbuf(vp, V_SAVE, ap->a_td, 1);
+ if (error == 0 && (vp->v_iflag & VI_DOOMED) != 0)
+ return (EBADF);
if (error == EINTR || error == EIO) {
if (NFS_ISV4(vp))
(void) nfsrpc_close(vp, 0, ap->a_td);
@@ -576,6 +580,8 @@
if (np->n_directio_opens == 0) {
mtx_unlock(&np->n_mtx);
error = ncl_vinvalbuf(vp, V_SAVE, ap->a_td, 1);
+ if (error == 0 && (vp->v_iflag & VI_DOOMED) != 0)
+ return (EBADF);
if (error) {
if (NFS_ISV4(vp))
(void) nfsrpc_close(vp, 0, ap->a_td);
@@ -714,8 +720,16 @@
* np->n_flag &= ~NMODIFIED;
*/
}
- } else
- error = ncl_vinvalbuf(vp, V_SAVE, ap->a_td, 1);
+ } else {
+ error = ncl_vinvalbuf(vp, V_SAVE, ap->a_td, 1);
+ if (error == 0 && (vp->v_vflag & VI_DOOMED) != 0) {
+ if (VTONFS(vp) != NULL) {
+ MPASS(np == VTONFS(vp));
+ goto directio_out;
+ }
+ return (error);
+ }
+ }
mtx_lock(&np->n_mtx);
}
/*
@@ -774,6 +788,7 @@
KASSERT((np->n_directio_asyncwr == 0),
("nfs_close: dirty unflushed (%d) directio buffers\n",
np->n_directio_asyncwr));
+directio_out:
if (newnfs_directio_enable && (fmode & O_DIRECT) && (vp->v_type == VREG)) {
mtx_lock(&np->n_mtx);
KASSERT((np->n_directio_opens > 0),
@@ -931,13 +946,13 @@
if (np->n_flag & NMODIFIED) {
tsize = np->n_size;
mtx_unlock(&np->n_mtx);
- if (vap->va_size == 0)
- error = ncl_vinvalbuf(vp, 0, td, 1);
- else
- error = ncl_vinvalbuf(vp, V_SAVE, td, 1);
- if (error) {
- vnode_pager_setsize(vp, tsize);
- return (error);
+ error = ncl_vinvalbuf(vp, vap->va_size == 0 ?
+ 0 : V_SAVE, td, 1);
+ if (error == 0 && (vp->v_iflag & VI_DOOMED) != 0)
+ error = EBADF;
+ if (error != 0) {
+ vnode_pager_setsize(vp, tsize);
+ return (error);
}
/*
* Call nfscl_delegmodtime() to set the modify time
@@ -961,8 +976,10 @@
if ((vap->va_mtime.tv_sec != VNOVAL || vap->va_atime.tv_sec != VNOVAL) &&
(np->n_flag & NMODIFIED) && vp->v_type == VREG) {
mtx_unlock(&np->n_mtx);
- if ((error = ncl_vinvalbuf(vp, V_SAVE, td, 1)) != 0 &&
- (error == EINTR || error == EIO))
+ error = ncl_vinvalbuf(vp, V_SAVE, td, 1);
+ if (error == 0 && (vp->v_iflag & VI_DOOMED) != 0)
+ return (EBADF);
+ if (error == EINTR || error == EIO)
return (error);
} else
mtx_unlock(&np->n_mtx);
@@ -1665,8 +1682,10 @@
* unnecessary delayed writes later.
*/
error = ncl_vinvalbuf(vp, 0, cnp->cn_thread, 1);
- /* Do the rpc */
- if (error != EINTR && error != EIO)
+ if (error == 0 && (vp->v_iflag & VI_DOOMED) != 0)
+ error = EBADF;
+ else if (error != EINTR && error != EIO)
+ /* Do the rpc */
error = nfs_removerpc(dvp, vp, cnp->cn_nameptr,
cnp->cn_namelen, cnp->cn_cred, cnp->cn_thread);
/*
@@ -3055,6 +3074,10 @@
if ((np->n_flag & NMODIFIED) || ret ||
np->n_change != va.va_filerev) {
(void) ncl_vinvalbuf(vp, V_SAVE, td, 1);
+ if ((vp->v_iflag & VI_DOOMED) != 0) {
+ NFSVOPUNLOCK(vp, 0);
+ return (EBADF);
+ }
np->n_attrstamp = 0;
KDTRACE_NFS_ATTRCACHE_FLUSH_DONE(vp);
ret = VOP_GETATTR(vp, &va, cred);
Index: sys/kern/vfs_subr.c
===================================================================
--- sys/kern/vfs_subr.c
+++ sys/kern/vfs_subr.c
@@ -1673,13 +1673,15 @@
*/
do {
bufobj_wwait(bo, 0, 0);
- BO_UNLOCK(bo);
- if (bo->bo_object != NULL) {
- VM_OBJECT_WLOCK(bo->bo_object);
- vm_object_pip_wait(bo->bo_object, "bovlbx");
- VM_OBJECT_WUNLOCK(bo->bo_object);
+ if ((flags & V_VMIO) == 0) {
+ BO_UNLOCK(bo);
+ if (bo->bo_object != NULL) {
+ VM_OBJECT_WLOCK(bo->bo_object);
+ vm_object_pip_wait(bo->bo_object, "bovlbx");
+ VM_OBJECT_WUNLOCK(bo->bo_object);
+ }
+ BO_LOCK(bo);
}
- BO_LOCK(bo);
} while (bo->bo_numoutput > 0);
BO_UNLOCK(bo);
@@ -1687,7 +1689,7 @@
* Destroy the copy in the VM cache, too.
*/
if (bo->bo_object != NULL &&
- (flags & (V_ALT | V_NORMAL | V_CLEANONLY)) == 0) {
+ (flags & (V_ALT | V_NORMAL | V_CLEANONLY | V_VMIO)) == 0) {
VM_OBJECT_WLOCK(bo->bo_object);
vm_object_page_remove(bo->bo_object, 0, 0, (flags & V_SAVE) ?
OBJPR_CLEANONLY : 0);
@@ -1696,7 +1698,7 @@
#ifdef INVARIANTS
BO_LOCK(bo);
- if ((flags & (V_ALT | V_NORMAL | V_CLEANONLY)) == 0 &&
+ if ((flags & (V_ALT | V_NORMAL | V_CLEANONLY | V_VMIO)) == 0 &&
(bo->bo_dirty.bv_cnt > 0 || bo->bo_clean.bv_cnt > 0))
panic("vinvalbuf: flush failed");
BO_UNLOCK(bo);
Index: sys/sys/vnode.h
===================================================================
--- sys/sys/vnode.h
+++ sys/sys/vnode.h
@@ -402,6 +402,7 @@
#define V_ALT 0x0002 /* vinvalbuf: invalidate only alternate bufs */
#define V_NORMAL 0x0004 /* vinvalbuf: invalidate only regular bufs */
#define V_CLEANONLY 0x0008 /* vinvalbuf: invalidate only clean bufs */
+#define V_VMIO 0x0010 /* vinvalbuf: called during pageout */
#define REVOKEALL 0x0001 /* vop_revoke: revoke all aliases */
#define V_WAIT 0x0001 /* vn_start_write: sleep for suspend */
#define V_NOWAIT 0x0002 /* vn_start_write: don't sleep for suspend */
Index: sys/vm/vnode_pager.h
===================================================================
--- sys/vm/vnode_pager.h
+++ sys/vm/vnode_pager.h
@@ -44,11 +44,10 @@
int count, int *rbehind, int *rahead, vop_getpages_iodone_t iodone,
void *arg);
int vnode_pager_generic_putpages(struct vnode *vp, vm_page_t *m,
- int count, boolean_t sync,
- int *rtvals);
+ int count, int flags, int *rtvals);
int vnode_pager_local_getpages(struct vop_getpages_args *ap);
int vnode_pager_local_getpages_async(struct vop_getpages_async_args *ap);
-
+int vnode_pager_putpages_ioflags(int pager_flags);
void vnode_pager_release_writecount(vm_object_t object, vm_offset_t start,
vm_offset_t end);
void vnode_pager_undirty_pages(vm_page_t *ma, int *rtvals, int written);
Index: sys/vm/vnode_pager.c
===================================================================
--- sys/vm/vnode_pager.c
+++ sys/vm/vnode_pager.c
@@ -1193,18 +1193,12 @@
vnode_pager_generic_putpages(struct vnode *vp, vm_page_t *ma, int bytecount,
int flags, int *rtvals)
{
- int i;
vm_object_t object;
vm_page_t m;
- int count;
-
- int maxsize, ncount;
vm_ooffset_t poffset;
struct uio auio;
struct iovec aiov;
- int error;
- int ioflags;
- int ppscheck = 0;
+ int count, error, i, maxsize, ncount, ppscheck;
static struct timeval lastfail;
static int curfail;
@@ -1271,22 +1265,6 @@
}
VM_OBJECT_WUNLOCK(object);
- /*
- * pageouts are already clustered, use IO_ASYNC to force a bawrite()
- * rather then a bdwrite() to prevent paging I/O from saturating
- * the buffer cache. Dummy-up the sequential heuristic to cause
- * large ranges to cluster. If neither IO_SYNC or IO_ASYNC is set,
- * the system decides how to cluster.
- */
- ioflags = IO_VMIO;
- if (flags & (VM_PAGER_PUT_SYNC | VM_PAGER_PUT_INVAL))
- ioflags |= IO_SYNC;
- else if ((flags & VM_PAGER_CLUSTER_OK) == 0)
- ioflags |= IO_ASYNC;
- ioflags |= (flags & VM_PAGER_PUT_INVAL) ? IO_INVAL: 0;
- ioflags |= (flags & VM_PAGER_PUT_NOREUSE) ? IO_NOREUSE : 0;
- ioflags |= IO_SEQMAX << IO_SEQSHIFT;
-
aiov.iov_base = (caddr_t) 0;
aiov.iov_len = maxsize;
auio.uio_iov = &aiov;
@@ -1296,10 +1274,12 @@
auio.uio_rw = UIO_WRITE;
auio.uio_resid = maxsize;
auio.uio_td = (struct thread *) 0;
- error = VOP_WRITE(vp, &auio, ioflags, curthread->td_ucred);
+ error = VOP_WRITE(vp, &auio, vnode_pager_putpages_ioflags(flags),
+ curthread->td_ucred);
PCPU_INC(cnt.v_vnodeout);
PCPU_ADD(cnt.v_vnodepgsout, ncount);
+ ppscheck = 0;
if (error) {
if ((ppscheck = ppsratecheck(&lastfail, &curfail, 1)))
printf("vnode_pager_putpages: I/O error %d\n", error);
@@ -1315,6 +1295,30 @@
return rtvals[0];
}
+int
+vnode_pager_putpages_ioflags(int pager_flags)
+{
+ int ioflags;
+
+ /*
+ * Pageouts are already clustered, use IO_ASYNC to force a
+ * bawrite() rather then a bdwrite() to prevent paging I/O
+ * from saturating the buffer cache. Dummy-up the sequential
+ * heuristic to cause large ranges to cluster. If neither
+ * IO_SYNC or IO_ASYNC is set, the system decides how to
+ * cluster.
+ */
+ ioflags = IO_VMIO;
+ if ((pager_flags & (VM_PAGER_PUT_SYNC | VM_PAGER_PUT_INVAL)) != 0)
+ ioflags |= IO_SYNC;
+ else if ((pager_flags & VM_PAGER_CLUSTER_OK) == 0)
+ ioflags |= IO_ASYNC;
+ ioflags |= (pager_flags & VM_PAGER_PUT_INVAL) != 0 ? IO_INVAL: 0;
+ ioflags |= (pager_flags & VM_PAGER_PUT_NOREUSE) != 0 ? IO_NOREUSE : 0;
+ ioflags |= IO_SEQMAX << IO_SEQSHIFT;
+ return (ioflags);
+}
+
void
vnode_pager_undirty_pages(vm_page_t *ma, int *rtvals, int written)
{
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sun, May 24, 4:01 AM (21 m, 52 s)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
33463851
Default Alt Text
D10241.id27010.diff (13 KB)
Attached To
Mode
D10241: Make nfs pageout coherent with the buffer cache.
Attached
Detach File
Event Timeline
Log In to Comment