Date: Wed, 21 Aug 2013 17:23:24 +0000 (UTC) From: Konstantin Belousov <kib@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r254601 - in head/sys: fs/tmpfs kern sys Message-ID: <201308211723.r7LHNO2n072366@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: kib Date: Wed Aug 21 17:23:24 2013 New Revision: 254601 URL: http://svnweb.freebsd.org/changeset/base/254601 Log: Extract the general-purpose code from tmpfs to perform uiomove from the page queue of some vm object. Discussed with: alc Tested by: pho Sponsored by: The FreeBSD Foundation Modified: head/sys/fs/tmpfs/tmpfs_vnops.c head/sys/kern/uipc_shm.c head/sys/sys/uio.h Modified: head/sys/fs/tmpfs/tmpfs_vnops.c ============================================================================== --- head/sys/fs/tmpfs/tmpfs_vnops.c Wed Aug 21 16:46:06 2013 (r254600) +++ head/sys/fs/tmpfs/tmpfs_vnops.c Wed Aug 21 17:23:24 2013 (r254601) @@ -439,225 +439,51 @@ tmpfs_setattr(struct vop_setattr_args *v } static int -tmpfs_nocacheread(vm_object_t tobj, vm_pindex_t idx, - vm_offset_t offset, size_t tlen, struct uio *uio) -{ - vm_page_t m; - int error, rv; - - VM_OBJECT_WLOCK(tobj); - - /* - * Parallel reads of the page content from disk are prevented - * by exclusive busy. - * - * Although the tmpfs vnode lock is held here, it is - * nonetheless safe to sleep waiting for a free page. The - * pageout daemon does not need to acquire the tmpfs vnode - * lock to page out tobj's pages because tobj is a OBJT_SWAP - * type object. - */ - m = vm_page_grab(tobj, idx, VM_ALLOC_NORMAL | VM_ALLOC_RETRY); - if (m->valid != VM_PAGE_BITS_ALL) { - if (vm_pager_has_page(tobj, idx, NULL, NULL)) { - rv = vm_pager_get_pages(tobj, &m, 1, 0); - m = vm_page_lookup(tobj, idx); - if (m == NULL) { - printf( - "tmpfs: vm_obj %p idx %jd null lookup rv %d\n", - tobj, idx, rv); - VM_OBJECT_WUNLOCK(tobj); - return (EIO); - } - if (rv != VM_PAGER_OK) { - printf( - "tmpfs: vm_obj %p idx %jd valid %x pager error %d\n", - tobj, idx, m->valid, rv); - vm_page_lock(m); - vm_page_free(m); - vm_page_unlock(m); - VM_OBJECT_WUNLOCK(tobj); - return (EIO); - } - } else - vm_page_zero_invalid(m, TRUE); - } - vm_page_xunbusy(m); - vm_page_lock(m); - vm_page_hold(m); - vm_page_unlock(m); - VM_OBJECT_WUNLOCK(tobj); - error = uiomove_fromphys(&m, offset, tlen, uio); - vm_page_lock(m); - vm_page_unhold(m); - if (m->queue == PQ_NONE) { - vm_page_deactivate(m); - } else { - /* Requeue to maintain LRU ordering. */ - vm_page_requeue(m); - } - vm_page_unlock(m); - - return (error); -} - -static int tmpfs_read(struct vop_read_args *v) { - struct vnode *vp = v->a_vp; - struct uio *uio = v->a_uio; + struct vnode *vp; + struct uio *uio; struct tmpfs_node *node; - vm_object_t uobj; - size_t len; - int resid; - int error = 0; - vm_pindex_t idx; - vm_offset_t offset; - off_t addr; - size_t tlen; + vp = v->a_vp; + if (vp->v_type != VREG) + return (EISDIR); + uio = v->a_uio; + if (uio->uio_offset < 0) + return (EINVAL); node = VP_TO_TMPFS_NODE(vp); - - if (vp->v_type != VREG) { - error = EISDIR; - goto out; - } - - if (uio->uio_offset < 0) { - error = EINVAL; - goto out; - } - node->tn_status |= TMPFS_NODE_ACCESSED; - - uobj = node->tn_reg.tn_aobj; - while ((resid = uio->uio_resid) > 0) { - error = 0; - if (node->tn_size <= uio->uio_offset) - break; - len = MIN(node->tn_size - uio->uio_offset, resid); - if (len == 0) - break; - addr = uio->uio_offset; - idx = OFF_TO_IDX(addr); - offset = addr & PAGE_MASK; - tlen = MIN(PAGE_SIZE - offset, len); - error = tmpfs_nocacheread(uobj, idx, offset, tlen, uio); - if ((error != 0) || (resid == uio->uio_resid)) - break; - } - -out: - - return error; -} - -/* --------------------------------------------------------------------- */ - -static int -tmpfs_mappedwrite(vm_object_t tobj, size_t len, struct uio *uio) -{ - vm_pindex_t idx; - vm_page_t tpg; - vm_offset_t offset; - off_t addr; - size_t tlen; - int error, rv; - - error = 0; - - addr = uio->uio_offset; - idx = OFF_TO_IDX(addr); - offset = addr & PAGE_MASK; - tlen = MIN(PAGE_SIZE - offset, len); - - VM_OBJECT_WLOCK(tobj); - tpg = vm_page_grab(tobj, idx, VM_ALLOC_NORMAL | VM_ALLOC_RETRY); - if (tpg->valid != VM_PAGE_BITS_ALL) { - if (vm_pager_has_page(tobj, idx, NULL, NULL)) { - rv = vm_pager_get_pages(tobj, &tpg, 1, 0); - tpg = vm_page_lookup(tobj, idx); - if (tpg == NULL) { - printf( - "tmpfs: vm_obj %p idx %jd null lookup rv %d\n", - tobj, idx, rv); - VM_OBJECT_WUNLOCK(tobj); - return (EIO); - } - if (rv != VM_PAGER_OK) { - printf( - "tmpfs: vm_obj %p idx %jd valid %x pager error %d\n", - tobj, idx, tpg->valid, rv); - vm_page_lock(tpg); - vm_page_free(tpg); - vm_page_unlock(tpg); - VM_OBJECT_WUNLOCK(tobj); - return (EIO); - } - } else - vm_page_zero_invalid(tpg, TRUE); - } - vm_page_xunbusy(tpg); - vm_page_lock(tpg); - vm_page_hold(tpg); - vm_page_unlock(tpg); - VM_OBJECT_WUNLOCK(tobj); - error = uiomove_fromphys(&tpg, offset, tlen, uio); - VM_OBJECT_WLOCK(tobj); - if (error == 0) - vm_page_dirty(tpg); - vm_page_lock(tpg); - vm_page_unhold(tpg); - if (tpg->queue == PQ_NONE) { - vm_page_deactivate(tpg); - } else { - /* Requeue to maintain LRU ordering. */ - vm_page_requeue(tpg); - } - vm_page_unlock(tpg); - VM_OBJECT_WUNLOCK(tobj); - - return (error); + return (uiomove_object(node->tn_reg.tn_aobj, node->tn_size, uio)); } static int tmpfs_write(struct vop_write_args *v) { - struct vnode *vp = v->a_vp; - struct uio *uio = v->a_uio; - int ioflag = v->a_ioflag; - - boolean_t extended; - int error = 0; - off_t oldsize; + struct vnode *vp; + struct uio *uio; struct tmpfs_node *node; - vm_object_t uobj; - size_t len; - int resid; + off_t oldsize; + int error, ioflag; + boolean_t extended; + vp = v->a_vp; + uio = v->a_uio; + ioflag = v->a_ioflag; + error = 0; node = VP_TO_TMPFS_NODE(vp); oldsize = node->tn_size; - if (uio->uio_offset < 0 || vp->v_type != VREG) { - error = EINVAL; - goto out; - } - - if (uio->uio_resid == 0) { - error = 0; - goto out; - } - + if (uio->uio_offset < 0 || vp->v_type != VREG) + return (EINVAL); + if (uio->uio_resid == 0) + return (0); if (ioflag & IO_APPEND) uio->uio_offset = node->tn_size; - if (uio->uio_offset + uio->uio_resid > VFS_TO_TMPFS(vp->v_mount)->tm_maxfilesize) return (EFBIG); - if (vn_rlimit_fsize(vp, uio, uio->uio_td)) return (EFBIG); - extended = uio->uio_offset + uio->uio_resid > node->tn_size; if (extended) { error = tmpfs_reg_resize(vp, uio->uio_offset + uio->uio_resid, @@ -666,26 +492,13 @@ tmpfs_write(struct vop_write_args *v) goto out; } - uobj = node->tn_reg.tn_aobj; - while ((resid = uio->uio_resid) > 0) { - if (node->tn_size <= uio->uio_offset) - break; - len = MIN(node->tn_size - uio->uio_offset, resid); - if (len == 0) - break; - error = tmpfs_mappedwrite(uobj, len, uio); - if ((error != 0) || (resid == uio->uio_resid)) - break; - } - + error = uiomove_object(node->tn_reg.tn_aobj, node->tn_size, uio); node->tn_status |= TMPFS_NODE_ACCESSED | TMPFS_NODE_MODIFIED | (extended ? TMPFS_NODE_CHANGED : 0); - if (node->tn_mode & (S_ISUID | S_ISGID)) { if (priv_check_cred(v->a_cred, PRIV_VFS_RETAINSUGID, 0)) node->tn_mode &= ~(S_ISUID | S_ISGID); } - if (error != 0) (void)tmpfs_reg_resize(vp, oldsize, TRUE); @@ -693,7 +506,7 @@ out: MPASS(IMPLIES(error == 0, uio->uio_resid == 0)); MPASS(IMPLIES(error != 0, oldsize == node->tn_size)); - return error; + return (error); } /* --------------------------------------------------------------------- */ Modified: head/sys/kern/uipc_shm.c ============================================================================== --- head/sys/kern/uipc_shm.c Wed Aug 21 16:46:06 2013 (r254600) +++ head/sys/kern/uipc_shm.c Wed Aug 21 17:23:24 2013 (r254601) @@ -139,6 +139,100 @@ static struct fileops shm_ops = { FEATURE(posix_shm, "POSIX shared memory"); static int +uiomove_object_page(vm_object_t obj, size_t len, struct uio *uio) +{ + vm_page_t m; + vm_pindex_t idx; + size_t tlen; + int error, offset, rv; + + idx = OFF_TO_IDX(uio->uio_offset); + offset = uio->uio_offset & PAGE_MASK; + tlen = MIN(PAGE_SIZE - offset, len); + + VM_OBJECT_WLOCK(obj); + + /* + * Parallel reads of the page content from disk are prevented + * by exclusive busy. + * + * Although the tmpfs vnode lock is held here, it is + * nonetheless safe to sleep waiting for a free page. The + * pageout daemon does not need to acquire the tmpfs vnode + * lock to page out tobj's pages because tobj is a OBJT_SWAP + * type object. + */ + m = vm_page_grab(obj, idx, VM_ALLOC_NORMAL | VM_ALLOC_RETRY); + if (m->valid != VM_PAGE_BITS_ALL) { + if (vm_pager_has_page(obj, idx, NULL, NULL)) { + rv = vm_pager_get_pages(obj, &m, 1, 0); + m = vm_page_lookup(obj, idx); + if (m == NULL) { + printf( + "uiomove_object: vm_obj %p idx %jd null lookup rv %d\n", + obj, idx, rv); + VM_OBJECT_WUNLOCK(obj); + return (EIO); + } + if (rv != VM_PAGER_OK) { + printf( + "uiomove_object: vm_obj %p idx %jd valid %x pager error %d\n", + obj, idx, m->valid, rv); + vm_page_lock(m); + vm_page_free(m); + vm_page_unlock(m); + VM_OBJECT_WUNLOCK(obj); + return (EIO); + } + } else + vm_page_zero_invalid(m, TRUE); + } + vm_page_xunbusy(m); + vm_page_lock(m); + vm_page_hold(m); + vm_page_unlock(m); + VM_OBJECT_WUNLOCK(obj); + error = uiomove_fromphys(&m, offset, tlen, uio); + if (uio->uio_rw == UIO_WRITE && error == 0) { + VM_OBJECT_WLOCK(obj); + vm_page_dirty(m); + VM_OBJECT_WUNLOCK(obj); + } + vm_page_lock(m); + vm_page_unhold(m); + if (m->queue == PQ_NONE) { + vm_page_deactivate(m); + } else { + /* Requeue to maintain LRU ordering. */ + vm_page_requeue(m); + } + vm_page_unlock(m); + + return (error); +} + +int +uiomove_object(vm_object_t obj, off_t obj_size, struct uio *uio) +{ + ssize_t resid; + size_t len; + int error; + + error = 0; + while ((resid = uio->uio_resid) > 0) { + if (obj_size <= uio->uio_offset) + break; + len = MIN(obj_size - uio->uio_offset, resid); + if (len == 0) + break; + error = uiomove_object_page(obj, len, uio); + if (error != 0 || resid == uio->uio_resid) + break; + } + return (error); +} + +static int shm_read(struct file *fp, struct uio *uio, struct ucred *active_cred, int flags, struct thread *td) { Modified: head/sys/sys/uio.h ============================================================================== --- head/sys/sys/uio.h Wed Aug 21 16:46:06 2013 (r254600) +++ head/sys/sys/uio.h Wed Aug 21 17:23:24 2013 (r254601) @@ -103,6 +103,7 @@ int uiomove_frombuf(void *buf, int bufle int uiomove_fromphys(struct vm_page *ma[], vm_offset_t offset, int n, struct uio *uio); int uiomove_nofault(void *cp, int n, struct uio *uio); +int uiomove_object(struct vm_object *obj, off_t obj_size, struct uio *uio); int uiomoveco(void *cp, int n, struct uio *uio, int disposable); #else /* !_KERNEL */
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201308211723.r7LHNO2n072366>