Skip to content

Commit 50353db

Browse files
authored
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 <[email protected]> Reviewed-by: Tony Nguyen <[email protected]> Signed-off-by: Rich Ercolani <[email protected]> Closes #12072
1 parent 8dddb25 commit 50353db

File tree

1 file changed

+23
-12
lines changed

1 file changed

+23
-12
lines changed

lib/libzfs/libzfs_diff.c

Lines changed: 23 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -243,6 +243,7 @@ write_inuse_diffs_one(FILE *fp, differ_info_t *di, uint64_t dobj)
243243
struct zfs_stat fsb, tsb;
244244
mode_t fmode, tmode;
245245
char fobjname[MAXPATHLEN], tobjname[MAXPATHLEN];
246+
boolean_t already_logged = B_FALSE;
246247
int fobjerr, tobjerr;
247248
int change;
248249

@@ -254,22 +255,35 @@ write_inuse_diffs_one(FILE *fp, differ_info_t *di, uint64_t dobj)
254255
* we get ENOENT, then the object just didn't exist in that
255256
* snapshot. If we get ENOTSUP, then we tried to get
256257
* info on a non-ZPL object, which we don't care about anyway.
258+
* For any other error we print a warning which includes the
259+
* errno and continue.
257260
*/
261+
258262
fobjerr = get_stats_for_obj(di, di->fromsnap, dobj, fobjname,
259263
MAXPATHLEN, &fsb);
260-
if (fobjerr && di->zerr != ENOENT && di->zerr != ENOTSUP)
261-
return (-1);
264+
if (fobjerr && di->zerr != ENOTSUP && di->zerr != ENOENT) {
265+
zfs_error_aux(di->zhp->zfs_hdl, strerror(di->zerr));
266+
zfs_error(di->zhp->zfs_hdl, di->zerr, di->errbuf);
267+
/*
268+
* Let's not print an error for the same object more than
269+
* once if it happens in both snapshots
270+
*/
271+
already_logged = B_TRUE;
272+
}
262273

263274
tobjerr = get_stats_for_obj(di, di->tosnap, dobj, tobjname,
264275
MAXPATHLEN, &tsb);
265-
if (tobjerr && di->zerr != ENOENT && di->zerr != ENOTSUP)
266-
return (-1);
267276

277+
if (tobjerr && di->zerr != ENOTSUP && di->zerr != ENOENT) {
278+
if (!already_logged) {
279+
zfs_error_aux(di->zhp->zfs_hdl, strerror(di->zerr));
280+
zfs_error(di->zhp->zfs_hdl, di->zerr, di->errbuf);
281+
}
282+
}
268283
/*
269284
* Unallocated object sharing the same meta dnode block
270285
*/
271286
if (fobjerr && tobjerr) {
272-
ASSERT(di->zerr == ENOENT || di->zerr == ENOTSUP);
273287
di->zerr = 0;
274288
return (0);
275289
}
@@ -344,12 +358,11 @@ describe_free(FILE *fp, differ_info_t *di, uint64_t object, char *namebuf,
344358
{
345359
struct zfs_stat sb;
346360

347-
if (get_stats_for_obj(di, di->fromsnap, object, namebuf,
348-
maxlen, &sb) != 0) {
349-
return (-1);
350-
}
361+
(void) get_stats_for_obj(di, di->fromsnap, object, namebuf,
362+
maxlen, &sb);
363+
351364
/* Don't print if in the delete queue on from side */
352-
if (di->zerr == ESTALE) {
365+
if (di->zerr == ESTALE || di->zerr == ENOENT) {
353366
di->zerr = 0;
354367
return (0);
355368
}
@@ -384,8 +397,6 @@ write_free_diffs(FILE *fp, differ_info_t *di, dmu_diff_record_t *dr)
384397
}
385398
err = describe_free(fp, di, zc.zc_obj, fobjname,
386399
MAXPATHLEN);
387-
if (err)
388-
break;
389400
} else if (errno == ESRCH) {
390401
break;
391402
} else {

0 commit comments

Comments
 (0)