Date: Wed, 31 Jan 2018 14:44:52 +0000 (UTC) From: Andriy Gapon <avg@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r328626 - head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs Message-ID: <201801311444.w0VEiqTV036127@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: avg Date: Wed Jan 31 14:44:51 2018 New Revision: 328626 URL: https://svnweb.freebsd.org/changeset/base/328626 Log: zfs_rezget: drop cached pages before doing anything else We did that in the case of success to prevent the use of stale cached data, but it makes even less sense to keep the cached data when we fail. Ideally, we should call vgone() on the vnode in the case of zfs_rezget failure, but the current lock order prevents us from doing that. The change also rearranges the order of unlinked check and the size change check. While there, add missing SET_ERROR in one of the error paths. MFC after: 2 weeks Modified: head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_znode.c Modified: head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_znode.c ============================================================================== --- head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_znode.c Wed Jan 31 14:36:27 2018 (r328625) +++ head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_znode.c Wed Jan 31 14:44:51 2018 (r328626) @@ -1250,6 +1250,16 @@ zfs_rezget(znode_t *zp) int count = 0; uint64_t gen; + /* + * Remove cached pages before reloading the znode, so that they are not + * lingering after we run into any error. Ideally, we should vgone() + * the vnode in case of error, but currently we cannot do that + * because of the LOR between the vnode lock and z_teardown_lock. + * So, instead, we have to "doom" the znode in the illumos style. + */ + vp = ZTOV(zp); + vn_pages_remove(vp, 0, 0); + ZFS_OBJ_HOLD_ENTER(zfsvfs, obj_num); mutex_enter(&zp->z_acl_lock); @@ -1329,18 +1339,12 @@ zfs_rezget(znode_t *zp) * (e.g. via a look-up). The old vnode and znode will be * recycled when the last vnode reference is dropped. */ - vp = ZTOV(zp); if (vp->v_type != IFTOVT((mode_t)zp->z_mode)) { zfs_znode_dmu_fini(zp); ZFS_OBJ_HOLD_EXIT(zfsvfs, obj_num); - return (EIO); + return (SET_ERROR(EIO)); } - zp->z_blksz = doi.doi_data_block_size; - vn_pages_remove(vp, 0, 0); - if (zp->z_size != size) - vnode_pager_setsize(vp, zp->z_size); - /* * If the file has zero links, then it has been unlinked on the send * side and it must be in the received unlinked set. @@ -1351,8 +1355,15 @@ zfs_rezget(znode_t *zp) * when the unlinked set gets processed. */ zp->z_unlinked = (zp->z_links == 0); - if (zp->z_unlinked) + if (zp->z_unlinked) { zfs_znode_dmu_fini(zp); + ZFS_OBJ_HOLD_EXIT(zfsvfs, obj_num); + return (0); + } + + zp->z_blksz = doi.doi_data_block_size; + if (zp->z_size != size) + vnode_pager_setsize(vp, zp->z_size); ZFS_OBJ_HOLD_EXIT(zfsvfs, obj_num);
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201801311444.w0VEiqTV036127>