summaryrefslogtreecommitdiffstats
path: root/module/zfs
diff options
context:
space:
mode:
authorBrian Behlendorf <[email protected]>2017-10-19 10:06:55 -0700
committerGitHub <[email protected]>2017-10-19 10:06:55 -0700
commitbbf1ad67cd0d6f3bc1e22a8a0c7448c15409d007 (patch)
treeef5884b1fc85f6355f0bee4d089321cdcf929e78 /module/zfs
parent35df0bb5565c81ba52de430108b37eced9de0606 (diff)
Remove vn_rename and vn_remove dependency
The only place vn_rename and vn_remove are used is when writing out an updated pool configuration file. By truncating the file instead of renaming and removing it we can avoid having to implement these interfaces entirely. Functionally an empty cache file is treated the same as a missing cache file. This is particularly advantageous because the Linux kernel has never provided a way to reliably implement vn_rename and vn_remove. The cachefile_004_pos.ksh test case was updated to understand that an empty cache file is the same as a missing one. The zfs-import-* systemd service files were not updated to use ConditionFileNotEmpty in place of ConditionPathExists. This means that after exporting all pools and rebooting new pools will not the scanned for on the next boot. This small change should not impact normal usage since pools are not exported as part of a normal shutdown. Documentation was updated accordingly. Reviewed-by: George Melikov <[email protected]> Reviewed-by: Arkadiusz BubaƂa <[email protected]> Signed-off-by: Brian Behlendorf <[email protected]> Closes zfsonlinux/spl#648 Closes #6753
Diffstat (limited to 'module/zfs')
-rw-r--r--module/zfs/spa_config.c35
1 files changed, 26 insertions, 9 deletions
diff --git a/module/zfs/spa_config.c b/module/zfs/spa_config.c
index 8459e7362..0ee46c2f2 100644
--- a/module/zfs/spa_config.c
+++ b/module/zfs/spa_config.c
@@ -148,6 +148,26 @@ out:
}
static int
+spa_config_remove(spa_config_dirent_t *dp)
+{
+#if defined(__linux__) && defined(_KERNEL)
+ int error, flags = FWRITE | FTRUNC;
+ uio_seg_t seg = UIO_SYSSPACE;
+ vnode_t *vp;
+
+ error = vn_open(dp->scd_path, seg, flags, 0644, &vp, 0, 0);
+ if (error == 0) {
+ (void) VOP_FSYNC(vp, FSYNC, kcred, NULL);
+ (void) VOP_CLOSE(vp, 0, 1, 0, kcred, NULL);
+ }
+
+ return (error);
+#else
+ return (vn_remove(dp->scd_path, UIO_SYSSPACE, RMFILE));
+#endif
+}
+
+static int
spa_config_write(spa_config_dirent_t *dp, nvlist_t *nvl)
{
size_t buflen;
@@ -161,12 +181,10 @@ 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) {
- err = vn_remove(dp->scd_path, UIO_SYSSPACE, RMFILE);
- /*
- * Don't report an error when the cache file is already removed
- */
+ err = spa_config_remove(dp);
if (err == ENOENT)
err = 0;
+
return (err);
}
@@ -179,9 +197,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
+ * 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 +209,8 @@ 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);
+ (void) spa_config_remove(dp);
}
#else
/*