diff options
author | Andriy Gapon <[email protected]> | 2017-09-12 16:35:48 +0300 |
---|---|---|
committer | Brian Behlendorf <[email protected]> | 2018-01-11 13:50:08 -0800 |
commit | 6a2185660d000c99b14556c7eb1108c5609faf41 (patch) | |
tree | 92b3eb8b84cfe8d91f201b79ea642d444ac7e629 /module/zfs | |
parent | fed90353d799acbc5e81b0dfadc6d649b0f2e8b5 (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.c | 33 |
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); |