From owner-freebsd-fs@freebsd.org Sun Oct 2 19:14:03 2016 Return-Path: Delivered-To: freebsd-fs@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id B6994AF1947 for ; Sun, 2 Oct 2016 19:14:03 +0000 (UTC) (envelope-from kostikbel@gmail.com) Received: from kib.kiev.ua (kib.kiev.ua [IPv6:2001:470:d5e7:1::1]) (using TLSv1 with cipher DHE-RSA-CAMELLIA256-SHA (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 46F90811 for ; Sun, 2 Oct 2016 19:14:03 +0000 (UTC) (envelope-from kostikbel@gmail.com) Received: from tom.home (kib@localhost [127.0.0.1]) by kib.kiev.ua (8.15.2/8.15.2) with ESMTPS id u92JDnRS057963 (version=TLSv1 cipher=DHE-RSA-CAMELLIA256-SHA bits=256 verify=NO); Sun, 2 Oct 2016 22:13:49 +0300 (EEST) (envelope-from kostikbel@gmail.com) DKIM-Filter: OpenDKIM Filter v2.10.3 kib.kiev.ua u92JDnRS057963 Received: (from kostik@localhost) by tom.home (8.15.2/8.15.2/Submit) id u92JDn5g057962; Sun, 2 Oct 2016 22:13:49 +0300 (EEST) (envelope-from kostikbel@gmail.com) X-Authentication-Warning: tom.home: kostik set sender to kostikbel@gmail.com using -f Date: Sun, 2 Oct 2016 22:13:49 +0300 From: Konstantin Belousov To: Anton Yuzhaninov Cc: "freebsd-fs@freebsd.org" Subject: Re: UFS: unaligned read from GELI with 8k sectorsize Message-ID: <20161002191349.GH38409@kib.kiev.ua> References: <20161001114536.GX38409@kib.kiev.ua> <20161001115439.GY38409@kib.kiev.ua> <68a8ed6d-e302-799c-3d2c-1d85c48d07bf@citrin.ru> <20161001211025.GD38409@kib.kiev.ua> <999638f9-3fee-82e3-d67f-cffef53b74e8@citrin.ru> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <999638f9-3fee-82e3-d67f-cffef53b74e8@citrin.ru> User-Agent: Mutt/1.6.1 (2016-04-27) X-Spam-Status: No, score=-2.0 required=5.0 tests=ALL_TRUSTED,BAYES_00, DKIM_ADSP_CUSTOM_MED,FREEMAIL_FROM,NML_ADSP_CUSTOM_MED autolearn=no autolearn_force=no version=3.4.1 X-Spam-Checker-Version: SpamAssassin 3.4.1 (2015-04-28) on tom.home X-BeenThere: freebsd-fs@freebsd.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: Filesystems List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 02 Oct 2016 19:14:03 -0000 On Sat, Oct 01, 2016 at 06:02:14PM -0400, Anton Yuzhaninov wrote: > DDB backtrace for shell: > https://imgur.com/a/JDLry I see. I was able to reproduce it with gnop -S 8k over swap-backed md. The following patch worked for me. diff --git a/sys/ufs/ffs/ffs_vnops.c b/sys/ufs/ffs/ffs_vnops.c index 2af5383..c9cd4dc 100644 --- a/sys/ufs/ffs/ffs_vnops.c +++ b/sys/ufs/ffs/ffs_vnops.c @@ -118,14 +118,14 @@ static vop_listextattr_t ffs_listextattr; static vop_openextattr_t ffs_openextattr; static vop_setextattr_t ffs_setextattr; static vop_vptofh_t ffs_vptofh; - +static vop_getpages_t ffs_getpages; /* Global vfs data structures for ufs. */ struct vop_vector ffs_vnodeops1 = { .vop_default = &ufs_vnodeops, .vop_fsync = ffs_fsync, .vop_fdatasync = ffs_fdatasync, - .vop_getpages = vnode_pager_local_getpages, + .vop_getpages = ffs_getpages, .vop_getpages_async = vnode_pager_local_getpages_async, .vop_lock1 = ffs_lock, .vop_read = ffs_read, @@ -147,7 +147,7 @@ struct vop_vector ffs_vnodeops2 = { .vop_default = &ufs_vnodeops, .vop_fsync = ffs_fsync, .vop_fdatasync = ffs_fdatasync, - .vop_getpages = vnode_pager_local_getpages, + .vop_getpages = ffs_getpages, .vop_getpages_async = vnode_pager_local_getpages_async, .vop_lock1 = ffs_lock, .vop_read = ffs_read, @@ -1784,3 +1787,95 @@ vop_vptofh { ufhp->ufid_gen = ip->i_gen; return (0); } + +static int +ffs_getpages(struct vop_getpages_args *ap) +{ + struct vnode *vp; + vm_page_t *mm, m, m1; + vm_object_t object; + struct bufobj *bo; + struct buf *bp; + struct fs *fs; + vm_pindex_t pi; + ufs_lbn_t lbn, lbnp; + long bsize; + int count, error, i; + bool redo; + + vp = ap->a_vp; + mm = ap->a_m; + count = ap->a_count; + + bo = &VFSTOUFS(ap->a_vp->v_mount)->um_devvp->v_bufobj; + if (bo->bo_bsize <= PAGE_SIZE) + return (vnode_pager_generic_getpages(vp, mm, count, + ap->a_rbehind, ap->a_rahead, NULL, NULL)); + + object = vp->v_object; + VM_OBJECT_WLOCK(object); + if (IDX_TO_OFF(mm[count - 1]->pindex) >= object->un_pager.vnp.vnp_size) + return (VM_PAGER_BAD); +again: + for (i = 0; i < count; i++) { + vm_page_xunbusy(mm[i]); + vm_page_sbusy(mm[i]); + } + VM_OBJECT_WUNLOCK(object); + + fs = VFSTOUFS(vp->v_mount)->um_fs; + lbnp = -1; + for (i = 0; i < count; i++) { + lbn = lblkno(fs, OFF_TO_IDX(mm[i]->pindex)); + if (lbn != lbnp) { + bsize = blksize(fs, VTOI(vp), lbn); + error = bread_gb(vp, lbn, bsize, NOCRED, GB_UNMAPPED, + &bp); + if (error == 0) { + if (LIST_EMPTY(&bp->b_dep)) { + bp->b_flags |= B_RELBUF; + brelse(bp); + } else { + /* XXX */ + bqrelse(bp); + } + lbnp = lbn; + } else { + break; + } + } + } + + VM_OBJECT_WLOCK(object); + if (error == 0) + vm_page_zero_invalid(mm[count - 1], TRUE); + redo = false; + for (i = 0; i < count; i++) { + KASSERT(mm[i]->valid == VM_PAGE_BITS_ALL, + ("run %d %p invalid", i, mm[i])); + vm_page_sunbusy(mm[i]); +wait: + while (vm_page_busied(mm[i])) { + pi = mm[i]->pindex; + vm_page_lock(mm[i]); + VM_OBJECT_WUNLOCK(object); + vm_page_busy_sleep(mm[i], "ffspgl"); + VM_OBJECT_WLOCK(object); + m1 = vm_page_lookup(object, pi); + if (m1 != mm[i]) + mm[i] = m1; + if (vm_page_busied(m1)) { + m = m1; + goto wait; + } + vm_page_xbusy(m1); + if (m1->valid != VM_PAGE_BITS_ALL) + redo = true; + } + vm_page_xbusy(mm[i]); + } + if (redo && error == 0) + goto again; + VM_OBJECT_WUNLOCK(object); + return (error != 0 ? VM_PAGER_ERROR : VM_PAGER_OK); +}