summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRich Ercolani <214141+rincebrain@users.noreply.github.com>2021-06-09 20:57:57 -0400
committerTony Hutter <hutter2@llnl.gov>2021-11-01 16:31:45 -0700
commit1b9f133028ba7a55ed247ea387d53a7fbde1b639 (patch)
treed46991448f0f7f4e4b53f1345d8028582435f0d0
parent5e6435e2f7625f6e512233dd1d38099f1e698459 (diff)
Added error for writing to /dev/ on Linuxzfs-2.0.7-staging
Starting in Linux 5.10, trying to write to /dev/{null,zero} errors out. Prefer to inform people when this happens rather than hoping they guess what's wrong. Reviewed-by: Antonio Russo <aerusso@aerusso.net> Reviewed-by: Ahelenia ZiemiaƄska <nabijaczleweli@nabijaczleweli.xyz> Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov> Reviewed-by: John Kennedy <john.kennedy@delphix.com> Signed-off-by: Rich Ercolani <rincebrain@gmail.com> Closes: #11991
-rw-r--r--cmd/zfs/zfs_main.c38
-rw-r--r--lib/libzfs/libzfs_sendrecv.c3
2 files changed, 38 insertions, 3 deletions
diff --git a/cmd/zfs/zfs_main.c b/cmd/zfs/zfs_main.c
index 92aafb091..52fd829e9 100644
--- a/cmd/zfs/zfs_main.c
+++ b/cmd/zfs/zfs_main.c
@@ -730,6 +730,32 @@ finish_progress(char *done)
pt_header = NULL;
}
+/* This function checks if the passed fd refers to /dev/null or /dev/zero */
+#ifdef __linux__
+static boolean_t
+is_dev_nullzero(int fd)
+{
+ struct stat st;
+ fstat(fd, &st);
+ return (major(st.st_rdev) == 1 && (minor(st.st_rdev) == 3 /* null */ ||
+ minor(st.st_rdev) == 5 /* zero */));
+}
+#endif
+
+static void
+note_dev_error(int err, int fd)
+{
+#ifdef __linux__
+ if (err == EINVAL && is_dev_nullzero(fd)) {
+ (void) fprintf(stderr,
+ gettext("Error: Writing directly to /dev/{null,zero} files"
+ " on certain kernels is not currently implemented.\n"
+ "(As a workaround, "
+ "try \"zfs send [...] | cat > /dev/null\")\n"));
+ }
+#endif
+}
+
static int
zfs_mount_and_share(libzfs_handle_t *hdl, const char *dataset, zfs_type_t type)
{
@@ -4448,11 +4474,16 @@ zfs_do_send(int argc, char **argv)
err = zfs_send_saved(zhp, &flags, STDOUT_FILENO,
resume_token);
+ if (err != 0)
+ note_dev_error(errno, STDOUT_FILENO);
zfs_close(zhp);
return (err != 0);
} else if (resume_token != NULL) {
- return (zfs_send_resume(g_zfs, &flags, STDOUT_FILENO,
- resume_token));
+ err = zfs_send_resume(g_zfs, &flags, STDOUT_FILENO,
+ resume_token);
+ if (err != 0)
+ note_dev_error(errno, STDOUT_FILENO);
+ return (err);
}
/*
@@ -4496,6 +4527,8 @@ zfs_do_send(int argc, char **argv)
err = zfs_send_one(zhp, fromname, STDOUT_FILENO, &flags,
redactbook);
zfs_close(zhp);
+ if (err != 0)
+ note_dev_error(errno, STDOUT_FILENO);
return (err != 0);
}
@@ -4572,6 +4605,7 @@ zfs_do_send(int argc, char **argv)
nvlist_free(dbgnv);
}
zfs_close(zhp);
+ note_dev_error(errno, STDOUT_FILENO);
return (err != 0);
}
diff --git a/lib/libzfs/libzfs_sendrecv.c b/lib/libzfs/libzfs_sendrecv.c
index 5410b8fae..3ea2d22bd 100644
--- a/lib/libzfs/libzfs_sendrecv.c
+++ b/lib/libzfs/libzfs_sendrecv.c
@@ -847,7 +847,8 @@ dump_ioctl(zfs_handle_t *zhp, const char *fromsnap, uint64_t fromsnap_obj,
case ERANGE:
case EFAULT:
case EROFS:
- zfs_error_aux(hdl, strerror(errno));
+ case EINVAL:
+ zfs_error_aux(hdl, "%s", strerror(errno));
return (zfs_error(hdl, EZFS_BADBACKUP, errbuf));
default: