Let zfs diff be more permissive
In the current world, `zfs diff` will die on certain kinds of errors that come up on ordinary, not-mangled filesystems - like EINVAL, which can come from a file with multiple hardlinks having the one whose name is referenced deleted. Since it should always be safe to continue, let's relax about all error codes - still print something for most, but don't immediately abort when we encounter them. Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov> Reviewed-by: Tony Nguyen <tony.nguyen@delphix.com> Signed-off-by: Rich Ercolani <rincebrain@gmail.com> Closes #12072
This commit is contained in:
parent
8dddb25d2c
commit
50353dbd05
|
@ -243,6 +243,7 @@ write_inuse_diffs_one(FILE *fp, differ_info_t *di, uint64_t dobj)
|
|||
struct zfs_stat fsb, tsb;
|
||||
mode_t fmode, tmode;
|
||||
char fobjname[MAXPATHLEN], tobjname[MAXPATHLEN];
|
||||
boolean_t already_logged = B_FALSE;
|
||||
int fobjerr, tobjerr;
|
||||
int change;
|
||||
|
||||
|
@ -254,22 +255,35 @@ write_inuse_diffs_one(FILE *fp, differ_info_t *di, uint64_t dobj)
|
|||
* we get ENOENT, then the object just didn't exist in that
|
||||
* snapshot. If we get ENOTSUP, then we tried to get
|
||||
* info on a non-ZPL object, which we don't care about anyway.
|
||||
* For any other error we print a warning which includes the
|
||||
* errno and continue.
|
||||
*/
|
||||
|
||||
fobjerr = get_stats_for_obj(di, di->fromsnap, dobj, fobjname,
|
||||
MAXPATHLEN, &fsb);
|
||||
if (fobjerr && di->zerr != ENOENT && di->zerr != ENOTSUP)
|
||||
return (-1);
|
||||
if (fobjerr && di->zerr != ENOTSUP && di->zerr != ENOENT) {
|
||||
zfs_error_aux(di->zhp->zfs_hdl, strerror(di->zerr));
|
||||
zfs_error(di->zhp->zfs_hdl, di->zerr, di->errbuf);
|
||||
/*
|
||||
* Let's not print an error for the same object more than
|
||||
* once if it happens in both snapshots
|
||||
*/
|
||||
already_logged = B_TRUE;
|
||||
}
|
||||
|
||||
tobjerr = get_stats_for_obj(di, di->tosnap, dobj, tobjname,
|
||||
MAXPATHLEN, &tsb);
|
||||
if (tobjerr && di->zerr != ENOENT && di->zerr != ENOTSUP)
|
||||
return (-1);
|
||||
|
||||
if (tobjerr && di->zerr != ENOTSUP && di->zerr != ENOENT) {
|
||||
if (!already_logged) {
|
||||
zfs_error_aux(di->zhp->zfs_hdl, strerror(di->zerr));
|
||||
zfs_error(di->zhp->zfs_hdl, di->zerr, di->errbuf);
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Unallocated object sharing the same meta dnode block
|
||||
*/
|
||||
if (fobjerr && tobjerr) {
|
||||
ASSERT(di->zerr == ENOENT || di->zerr == ENOTSUP);
|
||||
di->zerr = 0;
|
||||
return (0);
|
||||
}
|
||||
|
@ -344,12 +358,11 @@ describe_free(FILE *fp, differ_info_t *di, uint64_t object, char *namebuf,
|
|||
{
|
||||
struct zfs_stat sb;
|
||||
|
||||
if (get_stats_for_obj(di, di->fromsnap, object, namebuf,
|
||||
maxlen, &sb) != 0) {
|
||||
return (-1);
|
||||
}
|
||||
(void) get_stats_for_obj(di, di->fromsnap, object, namebuf,
|
||||
maxlen, &sb);
|
||||
|
||||
/* Don't print if in the delete queue on from side */
|
||||
if (di->zerr == ESTALE) {
|
||||
if (di->zerr == ESTALE || di->zerr == ENOENT) {
|
||||
di->zerr = 0;
|
||||
return (0);
|
||||
}
|
||||
|
@ -384,8 +397,6 @@ write_free_diffs(FILE *fp, differ_info_t *di, dmu_diff_record_t *dr)
|
|||
}
|
||||
err = describe_free(fp, di, zc.zc_obj, fobjname,
|
||||
MAXPATHLEN);
|
||||
if (err)
|
||||
break;
|
||||
} else if (errno == ESRCH) {
|
||||
break;
|
||||
} else {
|
||||
|
|
Loading…
Reference in New Issue