summaryrefslogtreecommitdiffstats
path: root/module/zfs
diff options
context:
space:
mode:
authorAndriy Gapon <[email protected]>2017-09-12 16:35:48 +0300
committerBrian Behlendorf <[email protected]>2018-01-11 13:50:08 -0800
commit6a2185660d000c99b14556c7eb1108c5609faf41 (patch)
tree92b3eb8b84cfe8d91f201b79ea642d444ac7e629 /module/zfs
parentfed90353d799acbc5e81b0dfadc6d649b0f2e8b5 (diff)
OpenZFS 8930 - zfs_zinactive: do not remove the node if the filesystem is readonly
Authored by: Andriy Gapon <[email protected]> Reviewed by: Matthew Ahrens <[email protected]> Reviewed-by: George Melikov <[email protected]> Approved by: Gordon Ross <[email protected]> Ported-by: Brian Behlendorf <[email protected]> OpenZFS-issue: https://www.illumos.org/issues/8930 OpenZFS-commit: https://github.com/openzfs/openzfs/commit/93c618e0f4 Closes #7029
Diffstat (limited to 'module/zfs')
-rw-r--r--module/zfs/zfs_znode.c33
1 files changed, 26 insertions, 7 deletions
diff --git a/module/zfs/zfs_znode.c b/module/zfs/zfs_znode.c
index 3caf1bdc1..d3b68403b 100644
--- a/module/zfs/zfs_znode.c
+++ b/module/zfs/zfs_znode.c
@@ -1255,7 +1255,6 @@ zfs_rezget(znode_t *zp)
return (SET_ERROR(EIO));
}
- zp->z_unlinked = (ZTOI(zp)->i_nlink == 0);
set_nlink(ZTOI(zp), (uint32_t)links);
zfs_set_inode_flags(zp, ZTOI(zp));
@@ -1263,6 +1262,19 @@ zfs_rezget(znode_t *zp)
zp->z_atime_dirty = 0;
zfs_inode_update(zp);
+ /*
+ * 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 = (ZTOI(zp)->i_nlink == 0);
+ if (zp->z_unlinked)
+ zfs_znode_dmu_fini(zp);
+
zfs_znode_hold_exit(zfsvfs, zh);
return (0);
@@ -1304,14 +1316,21 @@ zfs_zinactive(znode_t *zp)
mutex_enter(&zp->z_lock);
/*
- * 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) {
- mutex_exit(&zp->z_lock);
- zfs_znode_hold_exit(zfsvfs, zh);
- zfs_rmnode(zp);
- return;
+ ASSERT(!zfsvfs->z_issnap);
+ if (!zfs_is_readonly(zfsvfs)) {
+ mutex_exit(&zp->z_lock);
+ zfs_znode_hold_exit(zfsvfs, zh);
+ zfs_rmnode(zp);
+ return;
+ }
}
mutex_exit(&zp->z_lock);