From owner-svn-src-head@freebsd.org Fri Sep 22 08:27:28 2017 Return-Path: Delivered-To: svn-src-head@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 91609E1E6C6; Fri, 22 Sep 2017 08:27:28 +0000 (UTC) (envelope-from avg@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 6E6C4ED9; Fri, 22 Sep 2017 08:27:28 +0000 (UTC) (envelope-from avg@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id v8M8RRfP026782; Fri, 22 Sep 2017 08:27:27 GMT (envelope-from avg@FreeBSD.org) Received: (from avg@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id v8M8RRxn026780; Fri, 22 Sep 2017 08:27:27 GMT (envelope-from avg@FreeBSD.org) Message-Id: <201709220827.v8M8RRxn026780@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: avg set sender to avg@FreeBSD.org using -f From: Andriy Gapon Date: Fri, 22 Sep 2017 08:27:27 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r323918 - head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs X-SVN-Group: head X-SVN-Commit-Author: avg X-SVN-Commit-Paths: head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs X-SVN-Commit-Revision: 323918 X-SVN-Commit-Repository: base MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 22 Sep 2017 08:27:28 -0000 Author: avg Date: Fri Sep 22 08:27:27 2017 New Revision: 323918 URL: https://svnweb.freebsd.org/changeset/base/323918 Log: MFV r323917: 8648 Fix range locking in ZIL commit codepath illumos/illumos-gate@42b14111721da2ebd5159e7b45012a3eb0e3384c https://github.com/illumos/illumos-gate/commit/42b14111721da2ebd5159e7b45012a3eb0e3384c https://www.illumos.org/issues/8648 I'm opening this bug to track integration of the following ZFS on Linux commit into illumos: commit f763c3d1df569a8d6b60bcb5e95cf07aa7a189e6 Author: LOLi Date: Mon Aug 21 17:59:48 2017 +0200 Fix range locking in ZIL commit codepath Since OpenZFS 7578 (1b7c1e5) if we have a ZVOL with logbias=throughput we will force WR_INDIRECT itxs in zvol_log_write() setting itx->itx_lr offset and length to the offset and length of the BIO from zvol_write()->zvol_log_write(): these offset and length are later used to take a range lock in zillog->zl_get_data function: zvol_get_data(). Now suppose we have a ZVOL with blocksize=8K and push 4K writes to offset 0: we will only be range-locking 0-4096. This means the ASSERTion we make in dbuf_unoverride() is no longer valid because now dmu_sync() is called from zilog's get_data functions holding a partial lock on the dbuf. Fix this by taking a range lock on the whole block in zvol_get_data(). Reviewed-by: Chunwei Chen Reviewed-by: Brian Behlendorf Signed-off-by: loli10K Reviewed by: Igor Kozhukhov Reviewed by: Matt Ahrens Reviewed by: Andriy Gapon Reviewed by: Alexander Motin Approved by: Robert Mustacchi Author: LOLi MFC after: 10 days Modified: head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zvol.c Directory Properties: head/sys/cddl/contrib/opensolaris/ (props changed) Modified: head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c ============================================================================== --- head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c Fri Sep 22 08:23:24 2017 (r323917) +++ head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c Fri Sep 22 08:27:27 2017 (r323918) @@ -1343,7 +1343,7 @@ zfs_get_data(void *arg, lr_write_t *lr, char *buf, zio } else { /* indirect write */ /* * Have to lock the whole block to ensure when it's - * written out and it's checksum is being calculated + * written out and its checksum is being calculated * that no one can change the data. We need to re-check * blocksize after we get the lock in case it's changed! */ Modified: head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zvol.c ============================================================================== --- head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zvol.c Fri Sep 22 08:23:24 2017 (r323917) +++ head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zvol.c Fri Sep 22 08:27:27 2017 (r323918) @@ -1349,7 +1349,6 @@ zvol_get_data(void *arg, lr_write_t *lr, char *buf, zi zgd = kmem_zalloc(sizeof (zgd_t), KM_SLEEP); zgd->zgd_zilog = zv->zv_zilog; - zgd->zgd_rl = zfs_range_lock(&zv->zv_znode, offset, size, RL_READER); /* * Write records come in two flavors: immediate and indirect. @@ -1358,12 +1357,22 @@ zvol_get_data(void *arg, lr_write_t *lr, char *buf, zi * sync the data and get a pointer to it (indirect) so that * we don't have to write the data twice. */ - if (buf != NULL) { /* immediate write */ + if (buf != NULL) { /* immediate write */ + zgd->zgd_rl = zfs_range_lock(&zv->zv_znode, offset, size, + RL_READER); error = dmu_read(os, object, offset, size, buf, DMU_READ_NO_PREFETCH); - } else { + } else { /* indirect write */ + /* + * Have to lock the whole block to ensure when it's written out + * and its checksum is being calculated that no one can change + * the data. Contrarily to zfs_get_data we need not re-check + * blocksize after we get the lock because it cannot be changed. + */ size = zv->zv_volblocksize; offset = P2ALIGN(offset, size); + zgd->zgd_rl = zfs_range_lock(&zv->zv_znode, offset, size, + RL_READER); error = dmu_buf_hold(os, object, offset, zgd, &db, DMU_READ_NO_PREFETCH); if (error == 0) {