OpenZFS 8930 - zfs_zinactive: do not remove the node if the filesystem is readonly

Authored by: Andriy Gapon <avg@FreeBSD.org>
Reviewed by: Matthew Ahrens <mahrens@delphix.com>
Reviewed-by: George Melikov <mail@gmelikov.ru>
Approved by: Gordon Ross <gwr@nexenta.com>
Ported-by: Brian Behlendorf <behlendorf1@llnl.gov>

OpenZFS-issue: https://www.illumos.org/issues/8930
OpenZFS-commit: https://github.com/openzfs/openzfs/commit/93c618e0f4
Closes #7029
This commit is contained in:
Andriy Gapon 2017-09-12 16:35:48 +03:00 committed by Brian Behlendorf
parent fed90353d7
commit 6a2185660d
1 changed files with 26 additions and 7 deletions

View File

@ -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);