diff --git a/sys/fs/nfsclient/nfs_clbio.c.append2 b/sys/fs/nfsclient/nfs_clbio.c --- a/sys/fs/nfsclient/nfs_clbio.c.append2 +++ b/sys/fs/nfsclient/nfs_clbio.c @@ -1001,12 +1001,24 @@ if (uio->uio_resid == 0) return (0); + /* + * If the file in not mmap()'d, do IO_APPEND writing via a + * synchronous direct write. This can result in a significant + * performance improvement. + * If the file is mmap()'d, this cannot be done, since there + * is no way to maintain consistency between the file on the + * NFS server and the file's mmap()'d pages. + */ + NFSLOCKNODE(np); if (vp->v_type == VREG && ((newnfs_directio_enable && (ioflag & - IO_DIRECT)) || (ioflag & IO_APPEND))) { + IO_DIRECT)) || ((ioflag & IO_APPEND) && + (vp->v_object == NULL || !vm_object_is_active(vp->v_object))))) { + NFSUNLOCKNODE(np); if ((ioflag & IO_APPEND) != 0) ioflag |= IO_SYNC; return nfs_directio_write(vp, uio, cred, ioflag); } + NFSUNLOCKNODE(np); /* * Maybe this should be above the vnode op call, but so long as diff --git a/sys/vm/vm_meter.c.append2 b/sys/vm/vm_meter.c --- a/sys/vm/vm_meter.c.append2 +++ b/sys/vm/vm_meter.c @@ -142,21 +142,6 @@ CTLFLAG_MPSAFE, NULL, 0, sysctl_vm_loadavg, "S,loadavg", "Machine loadaverage history"); -/* - * This function aims to determine if the object is mapped, - * specifically, if it is referenced by a vm_map_entry. Because - * objects occasionally acquire transient references that do not - * represent a mapping, the method used here is inexact. However, it - * has very low overhead and is good enough for the advisory - * vm.vmtotal sysctl. - */ -static bool -is_object_active(vm_object_t obj) -{ - - return (obj->ref_count > obj->shadow_count); -} - #if defined(COMPAT_FREEBSD11) struct vmtotal11 { int16_t t_rq; @@ -268,7 +253,7 @@ } total.t_vm += object->size; total.t_rm += object->resident_page_count; - if (is_object_active(object)) { + if (vm_object_is_active(object)) { total.t_avm += object->size; total.t_arm += object->resident_page_count; } @@ -276,7 +261,7 @@ /* shared object */ total.t_vmshr += object->size; total.t_rmshr += object->resident_page_count; - if (is_object_active(object)) { + if (vm_object_is_active(object)) { total.t_avmshr += object->size; total.t_armshr += object->resident_page_count; } diff --git a/sys/vm/vm_object.h.append2 b/sys/vm/vm_object.h --- a/sys/vm/vm_object.h.append2 +++ b/sys/vm/vm_object.h @@ -391,6 +391,7 @@ void vm_object_unwire(vm_object_t object, vm_ooffset_t offset, vm_size_t length, uint8_t queue); struct vnode *vm_object_vnode(vm_object_t object); +bool vm_object_is_active(vm_object_t obj); #endif /* _KERNEL */ #endif /* _VM_OBJECT_ */ diff --git a/sys/vm/vm_object.c.append2 b/sys/vm/vm_object.c --- a/sys/vm/vm_object.c.append2 +++ b/sys/vm/vm_object.c @@ -2498,6 +2498,21 @@ (void)blockcount_sleep(&obj->busy, NULL, wmesg, PVM); } +/* + * This function aims to determine if the object is mapped, + * specifically, if it is referenced by a vm_map_entry. Because + * objects occasionally acquire transient references that do not + * represent a mapping, the method used here is inexact. However, it + * has very low overhead and is good enough for the advisory + * vm.vmtotal sysctl. + */ +bool +vm_object_is_active(vm_object_t obj) +{ + + return (obj->ref_count > obj->shadow_count); +} + static int vm_object_list_handler(struct sysctl_req *req, bool swap_only) {