Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 18 Feb 2018 00:20:46 +0000 (UTC)
From:      Alexander Motin <mav@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-11@freebsd.org
Subject:   svn commit: r329487 - stable/11/sys/cddl/contrib/opensolaris/uts/common/fs/zfs
Message-ID:  <201802180020.w1I0Kknk056615@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: mav
Date: Sun Feb 18 00:20:46 2018
New Revision: 329487
URL: https://svnweb.freebsd.org/changeset/base/329487

Log:
  MFC r328230: MFV r328229:
  8930 zfs_zinactive: do not remove the node if the filesystem is readonly
  
  illumos/illumos-gate@93c618e0f4932dc0bb9a9c90d8c4a5d029de5797
  
  https://www.illumos.org/issues/8930:
  We normally remove an unlinked node when its last user goes away and the
  node becomes inactive. However, we should not do that if the filesystem
  is mounted read-only including the case where it has its readonly
  property set. The node will remain on the unlinked queue, so it will
  not be leaked.
  
  One particular scenario is when we receive an incremental stream into a
  mounted read-only filesystem and that stream contains an unlinked file
  (still on the unlinked queue). If that file is opened before the
  receive and some time later after the receive it becomes inactive we
  would remove it and, thus, modify the read-only filesystem. As a
  result, the filesystem would diverge from its source and further
  incremental receives would not be possible (without forcing a rollback).
  
  Another related scenario, that may or may not be possible depending on an
  OS / VFS policy, is when an open file is unlinked, then the filesystem is
  remounted read-only, and then the file is closed.
  
  Reviewed by: Matthew Ahrens <mahrens@delphix.com>
  Approved by: Gordon Ross <gwr@nexenta.com>
  Author: Andriy Gapon <avg@FreeBSD.org>

Modified:
  stable/11/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_znode.c
Directory Properties:
  stable/11/   (props changed)

Modified: stable/11/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_znode.c
==============================================================================
--- stable/11/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_znode.c	Sun Feb 18 00:20:06 2018	(r329486)
+++ stable/11/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_znode.c	Sun Feb 18 00:20:46 2018	(r329487)
@@ -1336,12 +1336,24 @@ zfs_rezget(znode_t *zp)
 		return (EIO);
 	}
 
-	zp->z_unlinked = (zp->z_links == 0);
 	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.
+	 * We call zfs_znode_dmu_fini() now to prevent any accesses to the
+	 * stale data and to prevent automatical removal of the file in
+	 * zfs_zinactive().  The file will be removed either when it is removed
+	 * on the send side and the next incremental stream is received or
+	 * when the unlinked set gets processed.
+	 */
+	zp->z_unlinked = (zp->z_links == 0);
+	if (zp->z_unlinked)
+		zfs_znode_dmu_fini(zp);
+
 	ZFS_OBJ_HOLD_EXIT(zfsvfs, obj_num);
 
 	return (0);
@@ -1380,13 +1392,20 @@ zfs_zinactive(znode_t *zp)
 	ZFS_OBJ_HOLD_ENTER(zfsvfs, z_id);
 
 	/*
-	 * If this was the last reference to a file with no links,
-	 * remove the file from the file system.
+	 * If this was the last reference to a file with no links, remove
+	 * the file from the file system unless the file system is mounted
+	 * read-only.  That can happen, for example, if the file system was
+	 * originally read-write, the file was opened, then unlinked and
+	 * the file system was made read-only before the file was finally
+	 * closed.  The file will remain in the unlinked set.
 	 */
 	if (zp->z_unlinked) {
-		ZFS_OBJ_HOLD_EXIT(zfsvfs, z_id);
-		zfs_rmnode(zp);
-		return;
+		ASSERT(!zfsvfs->z_issnap);
+		if ((zfsvfs->z_vfs->vfs_flag & VFS_RDONLY) == 0) {
+			ZFS_OBJ_HOLD_EXIT(zfsvfs, z_id);
+			zfs_rmnode(zp);
+			return;
+		}
 	}
 
 	zfs_znode_dmu_fini(zp);



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201802180020.w1I0Kknk056615>