Added error for writing to /dev/ on Linux

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
This commit is contained in:
Rich Ercolani 2021-06-09 20:57:57 -04:00 committed by Tony Hutter
parent c4a5e56abc
commit 47ada9e5ed
2 changed files with 38 additions and 3 deletions

View File

@ -730,6 +730,32 @@ finish_progress(char *done)
pt_header = NULL; 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 static int
zfs_mount_and_share(libzfs_handle_t *hdl, const char *dataset, zfs_type_t type) 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, err = zfs_send_saved(zhp, &flags, STDOUT_FILENO,
resume_token); resume_token);
if (err != 0)
note_dev_error(errno, STDOUT_FILENO);
zfs_close(zhp); zfs_close(zhp);
return (err != 0); return (err != 0);
} else if (resume_token != NULL) { } else if (resume_token != NULL) {
return (zfs_send_resume(g_zfs, &flags, STDOUT_FILENO, err = zfs_send_resume(g_zfs, &flags, STDOUT_FILENO,
resume_token)); 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, err = zfs_send_one(zhp, fromname, STDOUT_FILENO, &flags,
redactbook); redactbook);
zfs_close(zhp); zfs_close(zhp);
if (err != 0)
note_dev_error(errno, STDOUT_FILENO);
return (err != 0); return (err != 0);
} }
@ -4572,6 +4605,7 @@ zfs_do_send(int argc, char **argv)
nvlist_free(dbgnv); nvlist_free(dbgnv);
} }
zfs_close(zhp); zfs_close(zhp);
note_dev_error(errno, STDOUT_FILENO);
return (err != 0); return (err != 0);
} }

View File

@ -847,7 +847,8 @@ dump_ioctl(zfs_handle_t *zhp, const char *fromsnap, uint64_t fromsnap_obj,
case ERANGE: case ERANGE:
case EFAULT: case EFAULT:
case EROFS: case EROFS:
zfs_error_aux(hdl, strerror(errno)); case EINVAL:
zfs_error_aux(hdl, "%s", strerror(errno));
return (zfs_error(hdl, EZFS_BADBACKUP, errbuf)); return (zfs_error(hdl, EZFS_BADBACKUP, errbuf));
default: default: