diff --git a/src/mds/mdstypes.cc b/src/mds/mdstypes.cc index eb1ae77d655..ecdbc4f3bad 100644 --- a/src/mds/mdstypes.cc +++ b/src/mds/mdstypes.cc @@ -390,6 +390,70 @@ void inode_t::generate_test_instances(list& ls) // i am lazy. } +int inode_t::compare(const inode_t &other, bool *divergent) const +{ + assert(ino == other.ino); + if (version == other.version) { + if (rdev != other.rdev || + ctime != other.ctime || + mode != other.mode || + uid != other.uid || + gid != other.gid || + nlink != other.nlink || + memcmp(&dir_layout, &other.dir_layout, sizeof(dir_layout)) || + memcmp(&layout, &other.layout, sizeof(layout)) || + old_pools != other.old_pools || + size != other.size || + max_size_ever != other.max_size_ever || + truncate_seq != other.truncate_seq || + truncate_size != other.truncate_size || + truncate_from != other.truncate_from || + truncate_pending != other.truncate_pending || + mtime != other.mtime || + atime != other.atime || + time_warp_seq != other.time_warp_seq || + !(*const_cast(&inline_data) == + *const_cast(&other.inline_data)) || + inline_version != other.inline_version || + client_ranges != other.client_ranges || + !(dirstat == other.dirstat) || + !(rstat == other.rstat) || + !(accounted_rstat == other.accounted_rstat) || + file_data_version != other.file_data_version || + xattr_version != other.xattr_version || + backtrace_version != other.backtrace_version) { + *divergent = true; + } + return 0; + } else if (version > other.version) { + *divergent = !older_is_consistent(other); + return 1; + } else { + assert(version < other.version); + *divergent = !other.older_is_consistent(*this); + return -1; + } + assert(0 == "can't have reached this point"); + *divergent = true; + return 0; +} + +bool inode_t::older_is_consistent(const inode_t &other) const +{ + if (max_size_ever < other.max_size_ever || + truncate_seq < other.truncate_seq || + time_warp_seq < other.time_warp_seq || + inline_version < other.inline_version || + dirstat.version < other.dirstat.version || + rstat.version < other.rstat.version || + accounted_rstat.version < other.accounted_rstat.version || + file_data_version < other.file_data_version || + xattr_version < other.xattr_version || + backtrace_version < other.backtrace_version) { + return false; + } + return true; +} /* * old_inode_t diff --git a/src/mds/mdstypes.h b/src/mds/mdstypes.h index d7c2665058b..59d79cf0b31 100644 --- a/src/mds/mdstypes.h +++ b/src/mds/mdstypes.h @@ -308,6 +308,11 @@ inline bool operator==(const client_writeable_range_t& l, * inode_t */ struct inode_t { + /** + * *************** + * Do not forget to add any new fields to the compare() function. + * *************** + */ // base (immutable) inodeno_t ino; uint32_t rdev; // if special file @@ -447,6 +452,21 @@ struct inode_t { void decode(bufferlist::iterator& bl); void dump(Formatter *f) const; static void generate_test_instances(list& ls); + /** + * Compare this inode_t with another that represent *the same inode* + * at different points in time. + * @pre The inodes are the same ino + * + * @param other The inode_t to compare ourselves with + * @param divergent A bool pointer which will be set to true + * if the values are different in a way that can't be explained + * by one being a newer version than the other. + * + * @returns 1 if we are newer than the other, 0 if equal, -1 if older. + */ + int compare(const inode_t &other, bool *divergent) const; +private: + bool older_is_consistent(const inode_t &other) const; }; WRITE_CLASS_ENCODER(inode_t)