diff --git a/module/zfs/spa_config.c b/module/zfs/spa_config.c index 8459e7362813..6658d4167237 100644 --- a/module/zfs/spa_config.c +++ b/module/zfs/spa_config.c @@ -161,12 +161,21 @@ spa_config_write(spa_config_dirent_t *dp, nvlist_t *nvl) * If the nvlist is empty (NULL), then remove the old cachefile. */ if (nvl == NULL) { +#if defined(__linux__) && defined(_KERNEL) + if ((err = vn_open(dp->scd_path, UIO_SYSSPACE, FWRITE | FTRUNC, + 0644, &vp, 0, 0)) == 0) { + (void) VOP_FSYNC(vp, FSYNC, kcred, NULL); + (void) VOP_CLOSE(vp, 0, 1, 0, kcred, NULL); + } +#else err = vn_remove(dp->scd_path, UIO_SYSSPACE, RMFILE); +#endif /* * Don't report an error when the cache file is already removed */ if (err == ENOENT) err = 0; + return (err); } @@ -179,9 +188,9 @@ spa_config_write(spa_config_dirent_t *dp, nvlist_t *nvl) #if defined(__linux__) && defined(_KERNEL) /* * Write the configuration to disk. Due to the complexity involved - * in performing a rename from within the kernel the file is truncated - * and overwritten in place. In the event of an error the file is - * unlinked to make sure we always have a consistent view of the data. + * in performing a rename and remove from within the kernel the file + * is instead truncated and overwritten in place. This way we always + * always have a consistent view of the data or a zero length file. */ err = vn_open(dp->scd_path, UIO_SYSSPACE, oflags, 0644, &vp, 0, 0); if (err == 0) { @@ -191,9 +200,6 @@ spa_config_write(spa_config_dirent_t *dp, nvlist_t *nvl) err = VOP_FSYNC(vp, FSYNC, kcred, NULL); (void) VOP_CLOSE(vp, oflags, 1, 0, kcred, NULL); - - if (err) - (void) vn_remove(dp->scd_path, UIO_SYSSPACE, RMFILE); } #else /* diff --git a/tests/zfs-tests/tests/functional/cachefile/cachefile_004_pos.ksh b/tests/zfs-tests/tests/functional/cachefile/cachefile_004_pos.ksh index ae54a9365f54..e0b81e166279 100755 --- a/tests/zfs-tests/tests/functional/cachefile/cachefile_004_pos.ksh +++ b/tests/zfs-tests/tests/functional/cachefile/cachefile_004_pos.ksh @@ -98,13 +98,13 @@ log_must zpool set cachefile=$CPATH2 $TESTPOOL1 log_must pool_in_cache $TESTPOOL1 $CPATH2 log_must zpool set cachefile=$CPATH2 $TESTPOOL2 log_must pool_in_cache $TESTPOOL2 $CPATH2 -if [[ -f $CPATH1 ]]; then +if [[ -s $CPATH1 ]]; then log_fail "Verify set when cachefile is set on pool." fi log_must zpool export $TESTPOOL1 log_must zpool export $TESTPOOL2 -if [[ -f $CPATH2 ]]; then +if [[ -s $CPATH2 ]]; then log_fail "Verify export when cachefile is set on pool." fi @@ -117,7 +117,7 @@ log_must pool_in_cache $TESTPOOL2 $CPATH2 log_must zpool destroy $TESTPOOL1 log_must zpool destroy $TESTPOOL2 -if [[ -f $CPATH2 ]]; then +if [[ -s $CPATH2 ]]; then log_fail "Verify destroy when cachefile is set on pool." fi