Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F144471866
D25968.id75591.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
6 KB
Referenced Files
None
Subscribers
None
D25968.id75591.diff
View Options
Index: sys/fs/nullfs/null_subr.c
===================================================================
--- sys/fs/nullfs/null_subr.c
+++ sys/fs/nullfs/null_subr.c
@@ -258,6 +258,26 @@
if (lowervp == MOUNTTONULLMOUNT(mp)->nullm_lowerrootvp)
vp->v_vflag |= VV_ROOT;
+ /*
+ * We might miss the case where lower vnode sets VIRF_PGREAD
+ * some time after construction, which is typical case.
+ * null_open rechecks.
+ */
+ if ((lowervp->v_irflag & VIRF_PGREAD) != 0) {
+ MPASS(lowervp->v_object != NULL);
+ if ((vp->v_irflag & VIRF_PGREAD) == 0) {
+ if (vp->v_object == NULL)
+ vp->v_object = lowervp->v_object;
+ else
+ MPASS(vp->v_object == lowervp->v_object);
+ VI_LOCK(vp);
+ vp->v_irflag |= VIRF_PGREAD;
+ VI_UNLOCK(vp);
+ } else {
+ MPASS(vp->v_object != NULL);
+ }
+ }
+
/*
* Atomically insert our new node into the hash or vget existing
* if someone else has beaten us to it.
Index: sys/fs/nullfs/null_vnops.c
===================================================================
--- sys/fs/nullfs/null_vnops.c
+++ sys/fs/nullfs/null_vnops.c
@@ -438,8 +438,17 @@
vp = ap->a_vp;
ldvp = NULLVPTOLOWERVP(vp);
retval = null_bypass(&ap->a_gen);
- if (retval == 0)
+ if (retval == 0) {
vp->v_object = ldvp->v_object;
+ if ((ldvp->v_irflag & VIRF_PGREAD) != 0) {
+ MPASS(vp->v_object != NULL);
+ if ((vp->v_irflag & VIRF_PGREAD) == 0) {
+ VI_LOCK(vp);
+ vp->v_irflag |= VIRF_PGREAD;
+ VI_UNLOCK(vp);
+ }
+ }
+ }
return (retval);
}
Index: sys/kern/vfs_vnops.c
===================================================================
--- sys/kern/vfs_vnops.c
+++ sys/kern/vfs_vnops.c
@@ -127,11 +127,15 @@
static const int io_hold_cnt = 16;
static int vn_io_fault_enable = 1;
-SYSCTL_INT(_debug, OID_AUTO, vn_io_fault_enable, CTLFLAG_RW,
+SYSCTL_INT(_debug, OID_AUTO, vn_io_fault_enable, CTLFLAG_RWTUN,
&vn_io_fault_enable, 0, "Enable vn_io_fault lock avoidance");
static int vn_io_fault_prefault = 0;
-SYSCTL_INT(_debug, OID_AUTO, vn_io_fault_prefault, CTLFLAG_RW,
+SYSCTL_INT(_debug, OID_AUTO, vn_io_fault_prefault, CTLFLAG_RWTUN,
&vn_io_fault_prefault, 0, "Enable vn_io_fault prefaulting");
+static int vn_io_pgcache_read_enable = 1;
+SYSCTL_INT(_debug, OID_AUTO, vn_io_pgcache_read_enable, CTLFLAG_RWTUN,
+ &vn_io_pgcache_read_enable, 0,
+ "Enable copying from page cache for reads, avoiding fs");
static u_long vn_io_faults_cnt;
SYSCTL_ULONG(_debug, OID_AUTO, vn_io_faults, CTLFLAG_RD,
&vn_io_faults_cnt, 0, "Count of vn_io_fault lock avoidance triggers");
@@ -844,6 +848,92 @@
return (ret);
}
+static int
+vn_read_from_obj(struct vnode *vp, struct uio *uio)
+{
+ vm_object_t obj;
+ vm_page_t ma[io_hold_cnt + 2];
+ off_t off, vsz;
+ ssize_t resid;
+ int error, i, j;
+
+ obj = vp->v_object;
+ MPASS(uio->uio_resid <= ptoa(io_hold_cnt + 2));
+ MPASS(obj != NULL);
+ MPASS(obj->type == VREG);
+
+ resid = uio->uio_resid;
+ off = uio->uio_offset;
+ for (i = 0; resid > 0; i++) {
+ MPASS(i < io_hold_cnt + 2);
+ ma[i] = vm_page_grab_unlocked(obj, atop(off),
+ VM_ALLOC_NOCREAT | VM_ALLOC_SBUSY | VM_ALLOC_IGN_SBUSY |
+ VM_ALLOC_NOWAIT);
+ if (ma[i] == NULL)
+ break;
+
+ /*
+ * Skip invalid pages. Valid mask can be partial only
+ * at EOF, and we clip later.
+ */
+ if (vm_page_none_valid(ma[i])) {
+ vm_page_sunbusy(ma[i]);
+ break;
+ }
+
+ resid -= PAGE_SIZE;
+ off += PAGE_SIZE;
+ }
+ if (i == 0)
+ return (EJUSTRETURN);
+
+ /*
+ * Check VIRF_DOOMED after we busied our pages. Since
+ * vgonel() terminates the vnode' vm_object, it cannot
+ * process past pages busied by us.
+ */
+ if (VN_IS_DOOMED(vp)) {
+ error = EJUSTRETURN;
+ goto out;
+ }
+
+ resid = PAGE_SIZE - (uio->uio_offset & PAGE_MASK) + ptoa(i - 1);
+ if (resid > uio->uio_resid)
+ resid = uio->uio_resid;
+
+ /*
+ * Unlocked read of vnp_size is safe because truncation cannot
+ * pass busied page. But we load vnp_size into a local
+ * variable so that possible concurrent extension does not
+ * break calculation.
+ */
+#if defined(__powerpc__) && !defined(__powerpc64__)
+ vsz = object->un_pager.vnp.vnp_size ;
+#else
+ vsz = atomic_load_64(&obj->un_pager.vnp.vnp_size);
+#endif
+ if (uio->uio_offset + resid > vsz)
+ resid = vsz - uio->uio_offset;
+
+ error = vn_io_fault_pgmove(ma, uio->uio_offset & PAGE_MASK, resid, uio);
+
+out:
+ for (j = 0; j < i; j++)
+ vm_page_sunbusy(ma[j]);
+ if (error != 0)
+ return (error);
+ return (uio->uio_resid == 0 ? 0 : EJUSTRETURN);
+}
+
+static bool
+do_vn_read_from_pgcache(struct vnode *vp, struct uio *uio, struct file *fp)
+{
+ return ((vp->v_irflag & VIRF_PGREAD) != 0 &&
+ !mac_vnode_check_read_enabled() &&
+ uio->uio_resid <= ptoa(io_hold_cnt) && uio->uio_offset >= 0 &&
+ (fp->f_flag & O_DIRECT) == 0 && vn_io_pgcache_read_enable);
+}
+
/*
* File table vnode read routine.
*/
@@ -860,6 +950,15 @@
uio->uio_td, td));
KASSERT(flags & FOF_OFFSET, ("No FOF_OFFSET"));
vp = fp->f_vnode;
+ if (do_vn_read_from_pgcache(vp, uio, fp)) {
+ error = vn_read_from_obj(vp, uio);
+ if (error == 0) {
+ fp->f_nextoff[UIO_READ] = uio->uio_offset;
+ return (0);
+ }
+ if (error != EJUSTRETURN)
+ return (error);
+ }
ioflag = 0;
if (fp->f_flag & FNONBLOCK)
ioflag |= IO_NDELAY;
@@ -1164,8 +1263,8 @@
uio_clone->uio_iovcnt--;
continue;
}
- if (len > io_hold_cnt * PAGE_SIZE)
- len = io_hold_cnt * PAGE_SIZE;
+ if (len > ptoa(io_hold_cnt))
+ len = ptoa(io_hold_cnt);
addr = (uintptr_t)uio_clone->uio_iov->iov_base;
end = round_page(addr + len);
if (end < addr) {
Index: sys/sys/vnode.h
===================================================================
--- sys/sys/vnode.h
+++ sys/sys/vnode.h
@@ -244,6 +244,8 @@
#define VHOLD_ALL_FLAGS (VHOLD_NO_SMR)
#define VIRF_DOOMED 0x0001 /* This vnode is being recycled */
+#define VIRF_PGREAD 0x0002 /* Read from page cache, never cleared
+ once set */
#define VI_TEXT_REF 0x0001 /* Text ref grabbed use ref */
#define VI_MOUNT 0x0002 /* Mount in progress */
Index: sys/ufs/ufs/ufs_vnops.c
===================================================================
--- sys/ufs/ufs/ufs_vnops.c
+++ sys/ufs/ufs/ufs_vnops.c
@@ -280,13 +280,20 @@
return (EOPNOTSUPP);
ip = VTOI(vp);
+ vnode_create_vobject(vp, DIP(ip, i_size), ap->a_td);
+ if (vp->v_type == VREG && (vp->v_irflag & VIRF_PGREAD) == 0) {
+ VI_LOCK(vp);
+ vp->v_irflag |= VIRF_PGREAD;
+ VI_UNLOCK(vp);
+ }
+
/*
* Files marked append-only must be opened for appending.
*/
if ((ip->i_flags & APPEND) &&
(ap->a_mode & (FWRITE | O_APPEND)) == FWRITE)
return (EPERM);
- vnode_create_vobject(vp, DIP(ip, i_size), ap->a_td);
+
return (0);
}
Index: sys/vm/vnode_pager.c
===================================================================
--- sys/vm/vnode_pager.c
+++ sys/vm/vnode_pager.c
@@ -520,7 +520,11 @@
vm_page_xunbusy(m);
}
out:
+#if defined(__powerpc__) && !defined(__powerpc64__)
object->un_pager.vnp.vnp_size = nsize;
+#else
+ atomic_store_64(&object->un_pager.vnp.vnp_size, nsize);
+#endif
object->size = nobjsize;
VM_OBJECT_WUNLOCK(object);
}
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Mon, Feb 9, 3:10 PM (13 h, 41 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
28592275
Default Alt Text
D25968.id75591.diff (6 KB)
Attached To
Mode
D25968: VMIO read
Attached
Detach File
Event Timeline
Log In to Comment