Skip to content

Commit

Permalink
Workaround for 'zfs diff' shares error
Browse files Browse the repository at this point in the history
For some reason which is not yet fully explained it's possible for
stat64() to fail with EIO on the .zfs/shares directory.  This then
causes the entire 'zfs diff' command to fail even though the shares
directory is not needed.

Until the root cause of the stat64() failure can be determined a
viable work around is to explicitly set the di->shares inode
number.  The Linux .zfs directory implementation will always use
the same well known inode numbers for the top level directories.
Obtaining the number through stat64() is cleaner, but in case that
fails it can be safely assigned based on the known constant.

Signed-off-by: Brian Behlendorf <[email protected]>
Issue openzfs#1426
Issue openzfs#481
  • Loading branch information
behlendorf committed Dec 3, 2013
1 parent 2e40f09 commit 195ab0b
Showing 1 changed file with 11 additions and 6 deletions.
17 changes: 11 additions & 6 deletions lib/libzfs/libzfs_diff.c
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,12 @@
#include "libzfs_impl.h"

#define ZDIFF_SNAPDIR "/.zfs/snapshot/"
#define ZDIFF_SHARESDIR "/.zfs/shares/"
#define ZDIFF_SHARESDIR "/.zfs/shares/"
#define ZDIFF_PREFIX "zfs-diff-%d"

/* Must match ZFSCTL_INO_SHARES value as defined in sys/zfs_ctldir.h */
#define ZDIFF_SHARESINO 0x0000FFFFFFFFFFFEULL

#define ZDIFF_ADDED '+'
#define ZDIFF_MODIFIED 'M'
#define ZDIFF_REMOVED '-'
Expand Down Expand Up @@ -493,11 +496,13 @@ find_shares_object(differ_info_t *di)
(void) strlcpy(fullpath, di->dsmnt, MAXPATHLEN);
(void) strlcat(fullpath, ZDIFF_SHARESDIR, MAXPATHLEN);

if (stat64(fullpath, &sb) != 0) {
(void) snprintf(di->errbuf, sizeof (di->errbuf),
dgettext(TEXT_DOMAIN, "Cannot stat %s"), fullpath);
return (zfs_error(di->zhp->zfs_hdl, EZFS_DIFF, di->errbuf));
}
/*
* Attempt to determine the shares directory inode number. But if
* that fails it is safe to fall back to the known reserved value.
* See #1426.
*/
if (stat64(fullpath, &sb) != 0)
sb.st_ino = ZDIFF_SHARESINO;

di->shares = (uint64_t)sb.st_ino;
return (0);
Expand Down

0 comments on commit 195ab0b

Please sign in to comment.