MFV r316931: 6268 zfs diff confused by moving a file to another directory

illumos/illumos-gate@aab04418a7
aab04418a7

https://www.illumos.org/issues/6268
  The zfs diff command presents a description of the changes that have occurred
  to files within a filesystem between two snapshots. If a file is renamed, the
  tool is capable of reporting this, e.g.:
  cd /some/zfs/dataset/subdir
  mv file0 file1
  Will result in a diff record like:
  R        /some/zfs/dataset/subdir/file0  ->  /some/zfs/dataset/subdir/file1
  Unfortunately, it seems that rename detection only uses the base filename to
  determine if a file has been renamed or simply modified. This leads to
  misreporting only the original filename, omitting the more relevant destination
  filename entirely. For example:
  cd /some/zfs/dataset/subdir
  mv file0 ../otherdir/file0
  Will result in a diff entry:
  M        /some/zfs/dataset/subdir/file0
  But it should really emit:
  R        /some/zfs/dataset/subdir/file0  ->  /some/zfs/dataset/otherdir/file0

Reviewed by: Matthew Ahrens <mahrens@delphix.com>
Reviewed by: Justin Gibbs <gibbs@scsiguy.com>
Approved by: Dan McDonald <danmcd@omniti.com>
Author: Joshua M. Clulow <josh@sysmgr.org>

MFC after:	3 weeks
This commit is contained in:
Andriy Gapon 2017-10-06 08:12:13 +00:00
commit 6a880de6e0

View File

@ -55,15 +55,6 @@
#define ZDIFF_REMOVED '-'
#define ZDIFF_RENAMED 'R'
static boolean_t
do_name_cmp(const char *fpath, const char *tpath)
{
char *fname, *tname;
fname = strrchr(fpath, '/') + 1;
tname = strrchr(tpath, '/') + 1;
return (strcmp(fname, tname) == 0);
}
typedef struct differ_info {
zfs_handle_t *zhp;
char *fromsnap;
@ -262,7 +253,6 @@ static int
write_inuse_diffs_one(FILE *fp, differ_info_t *di, uint64_t dobj)
{
struct zfs_stat fsb, tsb;
boolean_t same_name;
mode_t fmode, tmode;
char fobjname[MAXPATHLEN], tobjname[MAXPATHLEN];
int fobjerr, tobjerr;
@ -323,7 +313,6 @@ write_inuse_diffs_one(FILE *fp, differ_info_t *di, uint64_t dobj)
if (fmode != tmode && fsb.zs_gen == tsb.zs_gen)
tsb.zs_gen++; /* Force a generational difference */
same_name = do_name_cmp(fobjname, tobjname);
/* Simple modification or no change */
if (fsb.zs_gen == tsb.zs_gen) {
@ -334,7 +323,7 @@ write_inuse_diffs_one(FILE *fp, differ_info_t *di, uint64_t dobj)
if (change) {
print_link_change(fp, di, change,
change > 0 ? fobjname : tobjname, &tsb);
} else if (same_name) {
} else if (strcmp(fobjname, tobjname) == 0) {
print_file(fp, di, ZDIFF_MODIFIED, fobjname, &tsb);
} else {
print_rename(fp, di, fobjname, tobjname, &tsb);