uint64_t obj_name_offset) -> int {
int r = 0;
- dout(10) << "handling object "
- << std::hex << obj_name_ino << "." << obj_name_offset << std::dec
- << dendl;
+ dout(10) << "handling object " << std::hex << obj_name_ino << "."
+ << obj_name_offset << std::dec << dendl;
+
+ AccumulateResult accum_res;
+ inode_backtrace_t backtrace;
+ file_layout_t loaded_layout = file_layout_t::get_default();
+ std::string symlink;
+ inodeno_t remote_inode;
+ r = ClsCephFSClient::fetch_inode_accumulate_result(
+ data_io, oid, &backtrace, &loaded_layout, &symlink, &remote_inode,
+ &accum_res);
- AccumulateResult accum_res;
- inode_backtrace_t backtrace;
- file_layout_t loaded_layout = file_layout_t::get_default();
- std::string symlink;
- inodeno_t remote_inode;
- r = ClsCephFSClient::fetch_inode_accumulate_result(
- data_io, oid, &backtrace, &loaded_layout, &symlink, &remote_inode, &accum_res);
-
- if (r == -EINVAL) {
- dout(4) << "Accumulated metadata missing from '"
- << oid << ", did you run scan_extents?" << dendl;
- return r;
- } else if (r < 0) {
- dout(4) << "Unexpected error loading accumulated metadata from '"
- << oid << "': " << cpp_strerror(r) << dendl;
- // FIXME: this creates situation where if a client has a corrupt
- // backtrace/layout, we will fail to inject it. We should (optionally)
- // proceed if the backtrace/layout is corrupt but we have valid
- // accumulated metadata.
- return r;
- }
-
- const time_t file_mtime = accum_res.max_mtime;
- uint64_t file_size = 0;
- bool have_backtrace = !(backtrace.ancestors.empty());
+ if (r == -EINVAL) {
+ dout(4) << "Accumulated metadata missing from '" << oid
+ << ", did you run scan_extents?" << dendl;
+ return r;
+ } else if (r < 0) {
+ dout(4) << "Unexpected error loading accumulated metadata from '"
+ << oid << "': " << cpp_strerror(r) << dendl;
+ // FIXME: this creates situation where if a client has a corrupt
+ // backtrace/layout, we will fail to inject it. We should (optionally)
+ // proceed if the backtrace/layout is corrupt but we have valid
+ // accumulated metadata.
+ return r;
+ }
- // This is the layout we will use for injection, populated either
- // from loaded_layout or from best guesses
- file_layout_t guessed_layout;
- if (accum_res.obj_pool_id == -1) {
- guessed_layout.pool_id = data_pool_id;
- } else {
- guessed_layout.pool_id = accum_res.obj_pool_id;
+ const time_t file_mtime = accum_res.max_mtime;
+ uint64_t file_size = 0;
+ bool have_backtrace = !(backtrace.ancestors.empty());
- librados::IoCtx ioctx;
- r = librados::Rados(data_io).ioctx_create2(guessed_layout.pool_id, ioctx);
- if (r != 0) {
- derr << "Unexpected error opening file data pool id="
- << guessed_layout.pool_id << ": " << cpp_strerror(r) << dendl;
- return r;
- }
+ // This is the layout we will use for injection, populated either
+ // from loaded_layout or from best guesses
+ file_layout_t guessed_layout;
+ if (accum_res.obj_pool_id == -1) {
+ guessed_layout.pool_id = data_pool_id;
+ } else {
+ guessed_layout.pool_id = accum_res.obj_pool_id;
+
+ librados::IoCtx ioctx;
+ r = librados::Rados(data_io).ioctx_create2(
+ guessed_layout.pool_id, ioctx);
+ if (r != 0) {
+ derr << "Unexpected error opening file data pool id="
+ << guessed_layout.pool_id << ": " << cpp_strerror(r) << dendl;
+ return r;
+ }
- bufferlist bl;
- int r = ioctx.getxattr(oid, "layout", bl);
- if (r < 0) {
- if (r != -ENODATA) {
- derr << "Unexpected error reading layout for " << oid << ": "
- << cpp_strerror(r) << dendl;
- return r;
- }
- } else {
- try {
- auto q = bl.cbegin();
- decode(loaded_layout, q);
- } catch (ceph::buffer::error &e) {
- derr << "Unexpected error decoding layout for " << oid << dendl;
- return -EINVAL;
- }
- }
- }
+ bufferlist bl;
+ int r = ioctx.getxattr(oid, "layout", bl);
+ if (r < 0) {
+ if (r != -ENODATA) {
+ derr << "Unexpected error reading layout for " << oid << ": "
+ << cpp_strerror(r) << dendl;
+ return r;
+ }
+ } else {
+ try {
+ auto q = bl.cbegin();
+ decode(loaded_layout, q);
+ } catch (ceph::buffer::error& e) {
+ derr << "Unexpected error decoding layout for " << oid << dendl;
+ return -EINVAL;
+ }
+ }
+ }
- // Calculate file_size, guess the layout
- if (accum_res.ceiling_obj_index > 0) {
- uint32_t chunk_size = file_layout_t::get_default().object_size;
- // When there are multiple objects, the largest object probably
- // indicates the chunk size. But not necessarily, because files
- // can be sparse. Only make this assumption if size seen
- // is a power of two, as chunk sizes typically are.
- if ((accum_res.max_obj_size & (accum_res.max_obj_size - 1)) == 0) {
- chunk_size = accum_res.max_obj_size;
- }
+ // Calculate file_size, guess the layout
+ if (accum_res.ceiling_obj_index > 0) {
+ uint32_t chunk_size = file_layout_t::get_default().object_size;
+ // When there are multiple objects, the largest object probably
+ // indicates the chunk size. But not necessarily, because files
+ // can be sparse. Only make this assumption if size seen
+ // is a power of two, as chunk sizes typically are.
+ if ((accum_res.max_obj_size & (accum_res.max_obj_size - 1)) == 0) {
+ chunk_size = accum_res.max_obj_size;
+ }
- if (loaded_layout.pool_id == -1) {
- // If no stashed layout was found, guess it
- guessed_layout.object_size = chunk_size;
- guessed_layout.stripe_unit = chunk_size;
- guessed_layout.stripe_count = 1;
- } else if (!loaded_layout.is_valid() ||
- loaded_layout.object_size < accum_res.max_obj_size) {
- // If the max size seen exceeds what the stashed layout claims, then
- // disbelieve it. Guess instead. Same for invalid layouts on disk.
- dout(4) << "bogus xattr layout on 0x" << std::hex << obj_name_ino
- << std::dec << ", ignoring in favour of best guess" << dendl;
- guessed_layout.object_size = chunk_size;
- guessed_layout.stripe_unit = chunk_size;
- guessed_layout.stripe_count = 1;
- } else {
- // We have a stashed layout that we can't disprove, so apply it
- guessed_layout = loaded_layout;
- dout(20) << "loaded layout from xattr:"
- << " pi: " << guessed_layout.pool_id
- << " os: " << guessed_layout.object_size
- << " sc: " << guessed_layout.stripe_count
- << " su: " << guessed_layout.stripe_unit
- << dendl;
- // User might have transplanted files from a pool with a different
- // ID, so if the pool from loaded_layout is not found in the list of
- // the data pools, we'll force the injected layout to point to the
- // pool we read from.
- auto& fs = fsmap->get_filesystem(fscid);
- if (!fs.get_mds_map().is_data_pool(guessed_layout.pool_id)) {
- dout(20) << "overwriting layout pool_id " << data_pool_id << dendl;
- guessed_layout.pool_id = data_pool_id;
- }
- }
+ if (loaded_layout.pool_id == -1) {
+ // If no stashed layout was found, guess it
+ guessed_layout.object_size = chunk_size;
+ guessed_layout.stripe_unit = chunk_size;
+ guessed_layout.stripe_count = 1;
+ } else if (
+ !loaded_layout.is_valid() ||
+ loaded_layout.object_size < accum_res.max_obj_size) {
+ // If the max size seen exceeds what the stashed layout claims, then
+ // disbelieve it. Guess instead. Same for invalid layouts on disk.
+ dout(4) << "bogus xattr layout on 0x" << std::hex << obj_name_ino
+ << std::dec << ", ignoring in favour of best guess"
+ << dendl;
+ guessed_layout.object_size = chunk_size;
+ guessed_layout.stripe_unit = chunk_size;
+ guessed_layout.stripe_count = 1;
+ } else {
+ // We have a stashed layout that we can't disprove, so apply it
+ guessed_layout = loaded_layout;
+ dout(20) << "loaded layout from xattr:"
+ << " pi: " << guessed_layout.pool_id
+ << " os: " << guessed_layout.object_size
+ << " sc: " << guessed_layout.stripe_count
+ << " su: " << guessed_layout.stripe_unit << dendl;
+ // User might have transplanted files from a pool with a different
+ // ID, so if the pool from loaded_layout is not found in the list of
+ // the data pools, we'll force the injected layout to point to the
+ // pool we read from.
+ auto& fs = fsmap->get_filesystem(fscid);
+ if (!fs.get_mds_map().is_data_pool(guessed_layout.pool_id)) {
+ dout(20) << "overwriting layout pool_id " << data_pool_id
+ << dendl;
+ guessed_layout.pool_id = data_pool_id;
+ }
+ }
- if (guessed_layout.stripe_count == 1) {
- // Unstriped file: simple chunking
- file_size = guessed_layout.object_size * accum_res.ceiling_obj_index
- + accum_res.ceiling_obj_size;
- } else {
- // Striped file: need to examine the last stripe_count objects
- // in the file to determine the size.
-
- librados::IoCtx ioctx;
- if (guessed_layout.pool_id == data_io.get_id()) {
- ioctx.dup(data_io);
- } else {
- r = librados::Rados(data_io).ioctx_create2(guessed_layout.pool_id,
- ioctx);
- if (r != 0) {
- derr << "Unexpected error opening file data pool id="
- << guessed_layout.pool_id << ": " << cpp_strerror(r) << dendl;
- return r;
- }
- }
+ if (guessed_layout.stripe_count == 1) {
+ // Unstriped file: simple chunking
+ file_size = guessed_layout.object_size *
+ accum_res.ceiling_obj_index +
+ accum_res.ceiling_obj_size;
+ } else {
+ // Striped file: need to examine the last stripe_count objects
+ // in the file to determine the size.
+
+ librados::IoCtx ioctx;
+ if (guessed_layout.pool_id == data_io.get_id()) {
+ ioctx.dup(data_io);
+ } else {
+ r = librados::Rados(data_io).ioctx_create2(
+ guessed_layout.pool_id, ioctx);
+ if (r != 0) {
+ derr << "Unexpected error opening file data pool id="
+ << guessed_layout.pool_id << ": " << cpp_strerror(r)
+ << dendl;
+ return r;
+ }
+ }
- // How many complete (i.e. not last stripe) objects?
- uint64_t complete_objs = 0;
- if (accum_res.ceiling_obj_index > guessed_layout.stripe_count - 1) {
- complete_objs = (accum_res.ceiling_obj_index / guessed_layout.stripe_count) * guessed_layout.stripe_count;
- } else {
- complete_objs = 0;
- }
+ // How many complete (i.e. not last stripe) objects?
+ uint64_t complete_objs = 0;
+ if (accum_res.ceiling_obj_index > guessed_layout.stripe_count - 1) {
+ complete_objs = (accum_res.ceiling_obj_index /
+ guessed_layout.stripe_count) *
+ guessed_layout.stripe_count;
+ } else {
+ complete_objs = 0;
+ }
- // How many potentially-short objects (i.e. last stripe set) objects?
- uint64_t partial_objs = accum_res.ceiling_obj_index + 1 - complete_objs;
-
- dout(10) << "calculating striped size from complete objs: "
- << complete_objs << ", partial objs: " << partial_objs
- << dendl;
-
- // Maximum amount of data that may be in the incomplete objects
- uint64_t incomplete_size = 0;
-
- // For each short object, calculate the max file size within it
- // and accumulate the maximum
- for (uint64_t i = complete_objs; i < complete_objs + partial_objs; ++i) {
- char buf[60];
- snprintf(buf, sizeof(buf), "%llx.%08llx",
- (long long unsigned)obj_name_ino, (long long unsigned)i);
-
- uint64_t osize(0);
- time_t omtime(0);
- r = ioctx.stat(std::string(buf), &osize, &omtime);
- if (r == 0) {
- if (osize > 0) {
- // Upper bound within this object
- uint64_t upper_size = (osize - 1) / guessed_layout.stripe_unit
- * (guessed_layout.stripe_unit * guessed_layout.stripe_count)
- + (i % guessed_layout.stripe_count)
- * guessed_layout.stripe_unit + (osize - 1)
- % guessed_layout.stripe_unit + 1;
- incomplete_size = std::max(incomplete_size, upper_size);
+ // How many potentially-short objects (i.e. last stripe set) objects?
+ uint64_t partial_objs = accum_res.ceiling_obj_index + 1 -
+ complete_objs;
+
+ dout(10) << "calculating striped size from complete objs: "
+ << complete_objs << ", partial objs: " << partial_objs
+ << dendl;
+
+ // Maximum amount of data that may be in the incomplete objects
+ uint64_t incomplete_size = 0;
+
+ // For each short object, calculate the max file size within it
+ // and accumulate the maximum
+ for (uint64_t i = complete_objs; i < complete_objs + partial_objs;
+ ++i) {
+ char buf[60];
+ snprintf(
+ buf, sizeof(buf), "%llx.%08llx",
+ (long long unsigned)obj_name_ino, (long long unsigned)i);
+
+ uint64_t osize(0);
+ time_t omtime(0);
+ r = ioctx.stat(std::string(buf), &osize, &omtime);
+ if (r == 0) {
+ if (osize > 0) {
+ // Upper bound within this object
+ uint64_t upper_size =
+ (osize - 1) / guessed_layout.stripe_unit *
+ (guessed_layout.stripe_unit *
+ guessed_layout.stripe_count) +
+ (i % guessed_layout.stripe_count) *
+ guessed_layout.stripe_unit +
+ (osize - 1) % guessed_layout.stripe_unit + 1;
+ incomplete_size = std::max(incomplete_size, upper_size);
+ }
+ } else if (r == -ENOENT) {
+ // Absent object, treat as size 0 and ignore.
+ } else {
+ // Unexpected error, carry r to outer scope for handling.
+ break;
+ }
}
- } else if (r == -ENOENT) {
- // Absent object, treat as size 0 and ignore.
+ if (r != 0 && r != -ENOENT) {
+ derr << "Unexpected error checking size of ino 0x" << std::hex
+ << obj_name_ino << std::dec << ": " << cpp_strerror(r)
+ << dendl;
+ return r;
+ }
+ file_size = complete_objs * guessed_layout.object_size +
+ incomplete_size;
+ }
+ } else {
+ file_size = accum_res.ceiling_obj_size;
+ if (loaded_layout.pool_id < 0 ||
+ loaded_layout.object_size < accum_res.max_obj_size) {
+ // No layout loaded, or inconsistent layout, use default
+ guessed_layout = file_layout_t::get_default();
+ guessed_layout.pool_id = accum_res.obj_pool_id != -1
+ ? accum_res.obj_pool_id
+ : data_pool_id;
} else {
- // Unexpected error, carry r to outer scope for handling.
- break;
+ guessed_layout = loaded_layout;
}
}
- if (r != 0 && r != -ENOENT) {
- derr << "Unexpected error checking size of ino 0x" << std::hex
- << obj_name_ino << std::dec << ": " << cpp_strerror(r) << dendl;
- return r;
- }
- file_size = complete_objs * guessed_layout.object_size
- + incomplete_size;
- }
- } else {
- file_size = accum_res.ceiling_obj_size;
- if (loaded_layout.pool_id < 0
- || loaded_layout.object_size < accum_res.max_obj_size) {
- // No layout loaded, or inconsistent layout, use default
- guessed_layout = file_layout_t::get_default();
- guessed_layout.pool_id = accum_res.obj_pool_id != -1 ?
- accum_res.obj_pool_id : data_pool_id;
- } else {
- guessed_layout = loaded_layout;
- }
- }
- // Santity checking backtrace ino against object name
- if (have_backtrace && backtrace.ino != obj_name_ino) {
- dout(4) << "Backtrace ino 0x" << std::hex << backtrace.ino
- << " doesn't match object name ino 0x" << obj_name_ino
- << std::dec << dendl;
- have_backtrace = false;
- }
+ // Santity checking backtrace ino against object name
+ if (have_backtrace && backtrace.ino != obj_name_ino) {
+ dout(4) << "Backtrace ino 0x" << std::hex << backtrace.ino
+ << " doesn't match object name ino 0x" << obj_name_ino
+ << std::dec << dendl;
+ have_backtrace = false;
+ }
- InodeStore dentry;
- build_file_dentry(obj_name_ino, file_size, file_mtime, guessed_layout, symlink, remote_inode, &dentry);
+ InodeStore dentry;
+ build_file_dentry(
+ obj_name_ino, file_size, file_mtime, guessed_layout, symlink,
+ remote_inode, &dentry);
- // Inject inode to the metadata pool
- if (have_backtrace) {
- inode_backpointer_t root_bp = *(backtrace.ancestors.rbegin());
- if (MDS_INO_IS_MDSDIR(root_bp.dirino)) {
- /* Special case for strays: even if we have a good backtrace,
+ // Inject inode to the metadata pool
+ if (have_backtrace) {
+ inode_backpointer_t root_bp = *(backtrace.ancestors.rbegin());
+ if (MDS_INO_IS_MDSDIR(root_bp.dirino)) {
+ /* Special case for strays: even if we have a good backtrace,
* don't put it in the stray dir, because while that would technically
* give it linkage it would still be invisible to the user */
- r = driver->inject_lost_and_found(obj_name_ino, dentry);
- if (r < 0) {
- dout(4) << "Error injecting 0x" << std::hex << backtrace.ino
- << std::dec << " into lost+found: " << cpp_strerror(r) << dendl;
- if (r == -EINVAL) {
- dout(4) << "Use --force-corrupt to overwrite structures that "
- "appear to be corrupt" << dendl;
+ r = driver->inject_lost_and_found(obj_name_ino, dentry);
+ if (r < 0) {
+ dout(4) << "Error injecting 0x" << std::hex << backtrace.ino
+ << std::dec << " into lost+found: " << cpp_strerror(r)
+ << dendl;
+ if (r == -EINVAL) {
+ dout(4) << "Use --force-corrupt to overwrite structures that "
+ "appear to be corrupt"
+ << dendl;
+ }
+ }
+ } else {
+ /* Happy case: we will inject a named dentry for this inode */
+ r = driver->inject_with_backtrace(backtrace, dentry);
+ if (r < 0) {
+ dout(4) << "Error injecting 0x" << std::hex << backtrace.ino
+ << std::dec << " with backtrace: " << cpp_strerror(r)
+ << dendl;
+ if (r == -EINVAL) {
+ dout(4) << "Use --force-corrupt to overwrite structures that "
+ "appear to be corrupt"
+ << dendl;
+ }
+ }
}
- }
- } else {
- /* Happy case: we will inject a named dentry for this inode */
- r = driver->inject_with_backtrace(backtrace, dentry);
- if (r < 0) {
- dout(4) << "Error injecting 0x" << std::hex << backtrace.ino
- << std::dec << " with backtrace: " << cpp_strerror(r) << dendl;
- if (r == -EINVAL) {
- dout(4) << "Use --force-corrupt to overwrite structures that "
- "appear to be corrupt" << dendl;
+ } else {
+ /* Backtrace-less case: we will inject a lost+found dentry */
+ r = driver->inject_lost_and_found(obj_name_ino, dentry);
+ if (r < 0) {
+ dout(4) << "Error injecting 0x" << std::hex << obj_name_ino
+ << std::dec << " into lost+found: " << cpp_strerror(r)
+ << dendl;
+ if (r == -EINVAL) {
+ dout(4) << "Use --force-corrupt to overwrite structures that "
+ "appear to be corrupt"
+ << dendl;
+ }
}
}
- }
- } else {
- /* Backtrace-less case: we will inject a lost+found dentry */
- r = driver->inject_lost_and_found(
- obj_name_ino, dentry);
- if (r < 0) {
- dout(4) << "Error injecting 0x" << std::hex << obj_name_ino
- << std::dec << " into lost+found: " << cpp_strerror(r) << dendl;
- if (r == -EINVAL) {
- dout(4) << "Use --force-corrupt to overwrite structures that "
- "appear to be corrupt" << dendl;
- }
- }
- }
- progress_tracker->increment();
- progress_tracker->display_progress();
+ progress_tracker->increment();
+ progress_tracker->display_progress();
return r;
});
int DataScan::scan_links()
{
- MetadataDriver *metadata_driver = dynamic_cast<MetadataDriver*>(driver);
+ MetadataDriver* metadata_driver = dynamic_cast<MetadataDriver*>(driver);
if (!metadata_driver) {
derr << "Unexpected --output-dir option for scan_links" << dendl;
return -EINVAL;
interval_set<uint64_t> used_inos;
map<inodeno_t, int> remote_links;
- map<inodeno_t, vector<uint64_t>> referent_inodes; //referent inode list of primary inode
+ map<inodeno_t, vector<uint64_t>>
+ referent_inodes; //referent inode list of primary inode
map<snapid_t, SnapInfo> snaps;
snapid_t last_snap = 1;
snapid_t snaprealm_v2_since = 2;
bool is_dir;
map<snapid_t, SnapInfo> snaps;
vector<uint64_t> referent_inodes;
- link_info_t() : version(0), nlink(0), is_dir(false) {}
- link_info_t(inodeno_t di, frag_t df, const string& n, const CInode::inode_const_ptr& i) :
- dirino(di), frag(df), name(n),
- version(i->version), nlink(i->nlink), is_dir(S_IFDIR & i->mode), referent_inodes(i->referent_inodes) {}
- dirfrag_t dirfrag() const {
+
+ link_info_t() :
+ version(0), nlink(0), is_dir(false)
+ {}
+
+ link_info_t(
+ inodeno_t di,
+ frag_t df,
+ const string& n,
+ const CInode::inode_const_ptr& i) :
+ dirino(di),
+ frag(df),
+ name(n),
+ version(i->version),
+ nlink(i->nlink),
+ is_dir(S_IFDIR & i->mode),
+ referent_inodes(i->referent_inodes)
+ {}
+
+ dirfrag_t
+ dirfrag() const
+ {
return dirfrag_t(dirino, frag);
}
- void print(std::ostream& os) const {
- os << "link_info_t(diri=" << dirino << "." << frag << " name=" << name << " v=" << version << " l=" << nlink << ")";
+
+ void
+ print(std::ostream& os) const
+ {
+ os << "link_info_t(diri=" << dirino << "." << frag << " name=" << name
+ << " v=" << version << " l=" << nlink << ")";
}
- bool operator==(const link_info_t& o) const {
- return dirino == o.dirino
- && frag == o.frag
- && name == o.name;
+
+ bool
+ operator==(const link_info_t& o) const
+ {
+ return dirino == o.dirino && frag == o.frag && name == o.name;
}
};
- map<inodeno_t, list<link_info_t> > dup_primaries;
+
+ map<inodeno_t, list<link_info_t>> dup_primaries;
map<inodeno_t, link_info_t> bad_nlink_inos;
multimap<inodeno_t, link_info_t> injected_inos;
- map<dirfrag_t, set<string> > to_remove;
+ map<dirfrag_t, set<string>> to_remove;
enum {
SCAN_INOS = 1,
uint64_t frag_id = 0;
int r = parse_oid(oid, &dir_ino, &frag_id);
if (r == -EINVAL) {
- dout(10) << "Not a dirfrag: '" << oid << "'" << dendl;
- continue;
+ dout(10) << "Not a dirfrag: '" << oid << "'" << dendl;
+ continue;
} else {
- // parse_oid can only do 0 or -EINVAL
- ceph_assert(r == 0);
+ // parse_oid can only do 0 or -EINVAL
+ ceph_assert(r == 0);
}
if (!valid_ino(dir_ino)) {
- dout(10) << "Not a dirfrag (invalid ino): '" << oid << "'" << dendl;
- continue;
+ dout(10) << "Not a dirfrag (invalid ino): '" << oid << "'" << dendl;
+ continue;
}
std::map<std::string, bufferlist> items;
r = metadata_io.omap_get_vals(oid, "", (uint64_t)-1, &items);
if (r < 0) {
- derr << "Error getting omap from '" << oid << "': " << cpp_strerror(r) << dendl;
- return r;
+ derr << "Error getting omap from '" << oid << "': " << cpp_strerror(r)
+ << dendl;
+ return r;
}
for (auto& p : items) {
- auto q = p.second.cbegin();
- string dname;
- snapid_t last;
- dentry_key_t::decode_helper(p.first, dname, last);
-
- if (last != CEPH_NOSNAP) {
- if (last > last_snap)
- last_snap = last;
- continue;
- }
+ auto q = p.second.cbegin();
+ string dname;
+ snapid_t last;
+ dentry_key_t::decode_helper(p.first, dname, last);
+
+ if (last != CEPH_NOSNAP) {
+ if (last > last_snap)
+ last_snap = last;
+ continue;
+ }
- try {
- snapid_t dnfirst;
- decode(dnfirst, q);
+ try {
+ snapid_t dnfirst;
+ decode(dnfirst, q);
if (dnfirst == CEPH_NOSNAP) {
dout(20) << "injected ino detected" << dendl;
} else if (dnfirst <= CEPH_MAXSNAP) {
- if (dnfirst - 1 > last_snap)
- last_snap = dnfirst - 1;
- }
- char dentry_type;
- decode(dentry_type, q);
- mempool::mds_co::string alternate_name;
- if (dentry_type == 'I' || dentry_type == 'i') {
- InodeStore inode;
+ if (dnfirst - 1 > last_snap)
+ last_snap = dnfirst - 1;
+ }
+ char dentry_type;
+ decode(dentry_type, q);
+ mempool::mds_co::string alternate_name;
+ if (dentry_type == 'I' || dentry_type == 'i') {
+ InodeStore inode;
if (dentry_type == 'i') {
- DECODE_START(2, q);
+ DECODE_START(2, q);
if (struct_v >= 2)
decode(alternate_name, q);
- inode.decode(q);
- DECODE_FINISH(q);
- } else {
- inode.decode_bare(q);
- }
-
- inodeno_t ino = inode.inode->ino;
-
- if (step == SCAN_INOS) {
- if (used_inos.contains(ino, 1)) {
- dup_primaries.emplace(std::piecewise_construct,
- std::forward_as_tuple(ino),
- std::forward_as_tuple());
- } else {
- used_inos.insert(ino);
- }
- } else if (step == CHECK_LINK) {
- sr_t srnode;
- if (inode.snap_blob.length()) {
- auto p = inode.snap_blob.cbegin();
- decode(srnode, p);
- for (auto it = srnode.snaps.begin();
- it != srnode.snaps.end(); ) {
- if (it->second.ino != ino ||
- it->second.snapid != it->first) {
- srnode.snaps.erase(it++);
- } else {
- ++it;
- }
- }
- if (!srnode.past_parents.empty()) {
- snapid_t last = srnode.past_parents.rbegin()->first;
- if (last + 1 > snaprealm_v2_since)
- snaprealm_v2_since = last + 1;
- }
- }
- if (inode.old_inodes && !inode.old_inodes->empty()) {
- auto _last_snap = inode.old_inodes->rbegin()->first;
- if (_last_snap > last_snap)
- last_snap = _last_snap;
- }
- auto q = dup_primaries.find(ino);
- if (q != dup_primaries.end()) {
- q->second.push_back(link_info_t(dir_ino, frag_id, dname, inode.inode));
- q->second.back().snaps.swap(srnode.snaps);
- } else {
- int nlink = 0;
- auto r = remote_links.find(ino);
- if (r != remote_links.end())
- nlink = r->second;
- if (!MDS_INO_IS_STRAY(dir_ino))
- nlink++;
-
- if (inode.inode->nlink != nlink) {
- if (nlink > 1)
- ceph_assert(!referent_inodes[ino].empty());
- ceph_assert(static_cast<unsigned int>(nlink) == (referent_inodes[ino].size()+1));
- derr << "Bad nlink on " << ino << " expected " << nlink
- << " has " << inode.inode->nlink << dendl;
- bad_nlink_inos[ino] = link_info_t(dir_ino, frag_id, dname, inode.inode);
- bad_nlink_inos[ino].nlink = nlink;
- dout(1) << "Bad nlink, adding referent inode list " << referent_inodes[ino]
- << " to the primary inode " << ino << dendl;
- bad_nlink_inos[ino].referent_inodes = referent_inodes[ino];
- }
- snaps.insert(make_move_iterator(begin(srnode.snaps)),
- make_move_iterator(end(srnode.snaps)));
- }
- if (dnfirst == CEPH_NOSNAP) {
- injected_inos.insert({ino, link_info_t(dir_ino, frag_id, dname, inode.inode)});
- dout(20) << "adding " << ino << " for future processing to fix dnfirst" << dendl;
+ inode.decode(q);
+ DECODE_FINISH(q);
+ } else {
+ inode.decode_bare(q);
+ }
+
+ inodeno_t ino = inode.inode->ino;
+
+ if (step == SCAN_INOS) {
+ if (used_inos.contains(ino, 1)) {
+ dup_primaries.emplace(
+ std::piecewise_construct, std::forward_as_tuple(ino),
+ std::forward_as_tuple());
+ } else {
+ used_inos.insert(ino);
+ }
+ } else if (step == CHECK_LINK) {
+ sr_t srnode;
+ if (inode.snap_blob.length()) {
+ auto p = inode.snap_blob.cbegin();
+ decode(srnode, p);
+ for (auto it = srnode.snaps.begin(); it != srnode.snaps.end();) {
+ if (it->second.ino != ino || it->second.snapid != it->first) {
+ srnode.snaps.erase(it++);
+ } else {
+ ++it;
+ }
+ }
+ if (!srnode.past_parents.empty()) {
+ snapid_t last = srnode.past_parents.rbegin()->first;
+ if (last + 1 > snaprealm_v2_since)
+ snaprealm_v2_since = last + 1;
+ }
}
- }
- } else if (dentry_type == 'L' || dentry_type == 'l' || dentry_type == 'R' || dentry_type == 'r') {
- inodeno_t ino;
- inodeno_t referent_ino;
- InodeStore inode;
- unsigned char d_type;
-
- if (dentry_type == 'r') {
- DECODE_START(2, q);
+ if (inode.old_inodes && !inode.old_inodes->empty()) {
+ auto _last_snap = inode.old_inodes->rbegin()->first;
+ if (_last_snap > last_snap)
+ last_snap = _last_snap;
+ }
+ auto q = dup_primaries.find(ino);
+ if (q != dup_primaries.end()) {
+ q->second.push_back(
+ link_info_t(dir_ino, frag_id, dname, inode.inode));
+ q->second.back().snaps.swap(srnode.snaps);
+ } else {
+ int nlink = 0;
+ auto r = remote_links.find(ino);
+ if (r != remote_links.end())
+ nlink = r->second;
+ if (!MDS_INO_IS_STRAY(dir_ino))
+ nlink++;
+
+ if (inode.inode->nlink != nlink) {
+ if (nlink > 1)
+ ceph_assert(!referent_inodes[ino].empty());
+ ceph_assert(
+ static_cast<unsigned int>(nlink) ==
+ (referent_inodes[ino].size() + 1));
+ derr << "Bad nlink on " << ino << " expected " << nlink
+ << " has " << inode.inode->nlink << dendl;
+ bad_nlink_inos[ino] =
+ link_info_t(dir_ino, frag_id, dname, inode.inode);
+ bad_nlink_inos[ino].nlink = nlink;
+ dout(1) << "Bad nlink, adding referent inode list "
+ << referent_inodes[ino] << " to the primary inode "
+ << ino << dendl;
+ bad_nlink_inos[ino].referent_inodes = referent_inodes[ino];
+ }
+ snaps.insert(
+ make_move_iterator(begin(srnode.snaps)),
+ make_move_iterator(end(srnode.snaps)));
+ }
+ if (dnfirst == CEPH_NOSNAP) {
+ injected_inos.insert(
+ {ino, link_info_t(dir_ino, frag_id, dname, inode.inode)});
+ dout(20) << "adding " << ino
+ << " for future processing to fix dnfirst" << dendl;
+ }
+ }
+ } else if (
+ dentry_type == 'L' || dentry_type == 'l' || dentry_type == 'R' ||
+ dentry_type == 'r') {
+ inodeno_t ino;
+ inodeno_t referent_ino;
+ InodeStore inode;
+ unsigned char d_type;
+
+ if (dentry_type == 'r') {
+ DECODE_START(2, q);
if (struct_v >= 2)
decode(alternate_name, q);
- dout(20) << "decoding referent inode dentry type 'r' 0x" << std::hex << dir_ino << std::dec << "/" << dname << dendl;
- inode.decode(q);
- DECODE_FINISH(q);
- ino = inode.inode->remote_ino;
- referent_ino = inode.inode->ino;
- } else if (dentry_type == 'R') {
- dout(20) << "decoding referent inode dentry type 'R' 0x" << std::hex << dir_ino << std::dec << "/" << dname << dendl;
- inode.decode_bare(q);
- ino = inode.inode->remote_ino;
- referent_ino = inode.inode->ino;
- } else {
- CDentry::decode_remote(dentry_type, ino, d_type, alternate_name, q);
- }
-
- if (step == SCAN_INOS) {
- dout(20) << "Add referent inode dentry 0x" << std::hex << dir_ino << std::dec << "/" << dname << " to used_inos" << dendl;
+ dout(20) << "decoding referent inode dentry type 'r' 0x"
+ << std::hex << dir_ino << std::dec << "/" << dname
+ << dendl;
+ inode.decode(q);
+ DECODE_FINISH(q);
+ ino = inode.inode->remote_ino;
+ referent_ino = inode.inode->ino;
+ } else if (dentry_type == 'R') {
+ dout(20) << "decoding referent inode dentry type 'R' 0x"
+ << std::hex << dir_ino << std::dec << "/" << dname
+ << dendl;
+ inode.decode_bare(q);
+ ino = inode.inode->remote_ino;
+ referent_ino = inode.inode->ino;
+ } else {
+ CDentry::decode_remote(
+ dentry_type, ino, d_type, alternate_name, q);
+ }
+
+ if (step == SCAN_INOS) {
+ dout(20) << "Add referent inode dentry 0x" << std::hex << dir_ino
+ << std::dec << "/" << dname << " to used_inos" << dendl;
used_inos.insert(referent_ino);
- dout(20) << "Add referent inode dentry 0x" << std::hex << dir_ino << std::dec << "/" << dname << " to remote_links" << dendl;
+ dout(20) << "Add referent inode dentry 0x" << std::hex << dir_ino
+ << std::dec << "/" << dname << " to remote_links"
+ << dendl;
remote_links[ino]++;
referent_inodes[ino].push_back(referent_ino);
- dout(20) << "Added referent inode " << referent_ino << " of dentry 0x"
- << std::hex << dir_ino << std::dec << "/" << dname
+ dout(20) << "Added referent inode " << referent_ino
+ << " of dentry 0x" << std::hex << dir_ino << std::dec
+ << "/" << dname
<< " to referent_inodes list of primary inode " << ino
- << " referent_inode list after addition " << referent_inodes[ino]
- << dendl;
- } else if (step == CHECK_LINK) {
- if (dnfirst == CEPH_NOSNAP) {
- injected_inos.insert({referent_ino, link_info_t(dir_ino, frag_id, dname, inode.inode)});
- dout(20) << "Adding referent inode " << referent_ino << " for future processing to fix dnfirst" << dendl;
- }
- if (!used_inos.contains(ino, 1)) {
- derr << "Bad remote link dentry 0x" << std::hex << dir_ino
- << std::dec << "/" << dname
- << ", ino " << ino << " not found" << dendl;
- std::string key;
- dentry_key_t dn_key(CEPH_NOSNAP, dname.c_str());
- dn_key.encode(key);
- to_remove[dirfrag_t(dir_ino, frag_id)].insert(key);
- }
- }
- } else {
- derr << "Invalid tag char '" << dentry_type << "' dentry 0x" << dir_ino
- << std::dec << "/" << dname << dendl;
- return -EINVAL;
- }
- } catch (const buffer::error &err) {
- derr << "Error decoding dentry 0x" << std::hex << dir_ino
- << std::dec << "/" << dname << dendl;
- return -EINVAL;
- }
+ << " referent_inode list after addition "
+ << referent_inodes[ino] << dendl;
+ } else if (step == CHECK_LINK) {
+ if (dnfirst == CEPH_NOSNAP) {
+ injected_inos.insert(
+ {referent_ino,
+ link_info_t(dir_ino, frag_id, dname, inode.inode)});
+ dout(20) << "Adding referent inode " << referent_ino
+ << " for future processing to fix dnfirst" << dendl;
+ }
+ if (!used_inos.contains(ino, 1)) {
+ derr << "Bad remote link dentry 0x" << std::hex << dir_ino
+ << std::dec << "/" << dname << ", ino " << ino
+ << " not found" << dendl;
+ std::string key;
+ dentry_key_t dn_key(CEPH_NOSNAP, dname.c_str());
+ dn_key.encode(key);
+ to_remove[dirfrag_t(dir_ino, frag_id)].insert(key);
+ }
+ }
+ } else {
+ derr << "Invalid tag char '" << dentry_type << "' dentry 0x"
+ << dir_ino << std::dec << "/" << dname << dendl;
+ return -EINVAL;
+ }
+ } catch (const buffer::error& err) {
+ derr << "Error decoding dentry 0x" << std::hex << dir_ino << std::dec
+ << "/" << dname << dendl;
+ return -EINVAL;
+ }
progress_tracker->increment();
- progress_tracker->display_progress();
+ progress_tracker->display_progress();
}
}
}
for (auto p = used_inos.begin(); p != used_inos.end(); ++p) {
auto cur_max = p.get_start() + p.get_len() - 1;
if (cur_max < prev_max_ino)
- continue; // system inodes
+ continue; // system inodes
- if ((prev_max_ino >> 40) != (cur_max >> 40)) {
- unsigned rank = (prev_max_ino >> 40) - 1;
- max_ino_map[rank] = prev_max_ino;
+ if ((prev_max_ino >> 40) != (cur_max >> 40)) {
+ unsigned rank = (prev_max_ino >> 40) - 1;
+ max_ino_map[rank] = prev_max_ino;
} else if ((p.get_start() >> 40) != (cur_max >> 40)) {
- unsigned rank = (p.get_start() >> 40) - 1;
- max_ino_map[rank] = ((uint64_t)(rank + 2) << 40) - 1;
+ unsigned rank = (p.get_start() >> 40) - 1;
+ max_ino_map[rank] = ((uint64_t)(rank + 2) << 40) - 1;
}
prev_max_ino = cur_max;
}
used_inos.clear();
dout(10) << "processing " << dup_primaries.size() << " dup_primaries, "
- << remote_links.size() << " remote_links" << dendl;
+ << remote_links.size() << " remote_links" << dendl;
for (auto& p : dup_primaries) {
for (auto& q : p.second) {
dout(10) << " primary: " << q << dendl;
if (q.version > newest.version) {
- newest = q;
- } else if (q.version == newest.version &&
- !MDS_INO_IS_STRAY(q.dirino) &&
- MDS_INO_IS_STRAY(newest.dirino)) {
- newest = q;
+ newest = q;
+ } else if (
+ q.version == newest.version && !MDS_INO_IS_STRAY(q.dirino) &&
+ MDS_INO_IS_STRAY(newest.dirino)) {
+ newest = q;
}
}
dout(10) << "newest is: " << newest << dendl;
for (auto& q : p.second) {
// in the middle of dir fragmentation?
if (newest == q) {
- snaps.insert(make_move_iterator(begin(q.snaps)),
- make_move_iterator(end(q.snaps)));
- continue;
+ snaps.insert(
+ make_move_iterator(begin(q.snaps)),
+ make_move_iterator(end(q.snaps)));
+ continue;
}
std::string key;
dentry_key_t dn_key(CEPH_NOSNAP, q.name.c_str());
dn_key.encode(key);
to_remove[q.dirfrag()].insert(key);
- derr << "Remove duplicated ino 0x" << p.first << " from "
- << q.dirfrag() << "/" << q.name << dendl;
+ derr << "Remove duplicated ino 0x" << p.first << " from " << q.dirfrag()
+ << "/" << q.name << dendl;
{
/* we've removed the injected linkage: don't fix it later */
auto range = injected_inos.equal_range(p.first);
- for (auto it = range.first; it != range.second; ) {
+ for (auto it = range.first; it != range.second;) {
if (it->second == q) {
it = injected_inos.erase(it);
} else {
nlink++;
if (nlink != newest.nlink) {
- derr << "Dup primaries - Bad nlink on " << p.first << " expected " << nlink
- << " has " << newest.nlink << dendl;
+ derr << "Dup primaries - Bad nlink on " << p.first << " expected "
+ << nlink << " has " << newest.nlink << dendl;
if (nlink > 1)
ceph_assert(!referent_inodes[p.first].empty());
- ceph_assert(static_cast<unsigned int>(nlink) == (referent_inodes[p.first].size()+1));
+ ceph_assert(
+ static_cast<unsigned int>(nlink) ==
+ (referent_inodes[p.first].size() + 1));
bad_nlink_inos[p.first] = newest;
bad_nlink_inos[p.first].nlink = nlink;
- dout(1) << "Dup primaries - Bad nlink, adding referent inode list " << referent_inodes[p.first]
- << " to the primary inode " << p.first << dendl;
+ dout(1) << "Dup primaries - Bad nlink, adding referent inode list "
+ << referent_inodes[p.first] << " to the primary inode " << p.first
+ << dendl;
bad_nlink_inos[p.first].referent_inodes = referent_inodes[p.first];
} else {
bad_nlink_inos.erase(p.first);
{
objecter->with_osdmap([&](const OSDMap& o) {
for (auto p : data_pools) {
- const pg_pool_t *pi = o.get_pg_pool(p);
- if (!pi)
- continue;
- if (pi->snap_seq > last_snap)
- last_snap = pi->snap_seq;
+ const pg_pool_t* pi = o.get_pg_pool(p);
+ if (!pi)
+ continue;
+ if (pi->snap_seq > last_snap)
+ last_snap = pi->snap_seq;
}
});
if (!snaps.empty()) {
if (snaps.rbegin()->first > last_snap)
- last_snap = snaps.rbegin()->first;
+ last_snap = snaps.rbegin()->first;
}
}
dout(10) << "removing dup dentries from " << to_remove.size() << " objects"
- << dendl;
+ << dendl;
for (auto& p : to_remove) {
- object_t frag_oid = InodeStore::get_object_name(p.first.ino, p.first.frag, "");
+ object_t frag_oid =
+ InodeStore::get_object_name(p.first.ino, p.first.frag, "");
dout(10) << "removing dup dentries from " << p.first << dendl;
to_remove.clear();
dout(10) << "processing " << bad_nlink_inos.size() << " bad_nlink_inos"
- << dendl;
+ << dendl;
- for (auto &p : bad_nlink_inos) {
+ for (auto& p : bad_nlink_inos) {
dout(10) << "handling bad_nlink_ino " << p.first << dendl;
InodeStore inode;
snapid_t first;
- int r = read_dentry(p.second.dirino, p.second.frag, p.second.name, &inode, &first);
+ int r = read_dentry(
+ p.second.dirino, p.second.frag, p.second.name, &inode, &first);
if (r < 0) {
- derr << "Unexpected error reading dentry "
- << p.second.dirfrag() << "/" << p.second.name
- << ": " << cpp_strerror(r) << dendl;
+ derr << "Unexpected error reading dentry " << p.second.dirfrag() << "/"
+ << p.second.name << ": " << cpp_strerror(r) << dendl;
continue;
}
inode.get_inode()->nlink = p.second.nlink;
inode.get_inode()->referent_inodes = p.second.referent_inodes;
dout(10) << "bad_nlink_inos processing - Injecting referent_inodes "
- << p.second.referent_inodes << " to the primary inode " << inode.inode->ino << dendl;
- r = metadata_driver->inject_linkage(p.second.dirino, p.second.name, p.second.frag, inode, first);
+ << p.second.referent_inodes << " to the primary inode "
+ << inode.inode->ino << dendl;
+ r = metadata_driver->inject_linkage(
+ p.second.dirino, p.second.name, p.second.frag, inode, first);
if (r < 0)
return r;
}
dout(10) << "processing " << injected_inos.size() << " injected_inos"
- << dendl;
+ << dendl;
- for (auto &p : injected_inos) {
+ for (auto& p : injected_inos) {
dout(10) << "handling injected_ino " << p.first << dendl;
InodeStore inode;
snapid_t first;
- dout(20) << " fixing linkage (dnfirst) of " << p.second.dirino << ":" << p.second.name << dendl;
- int r = read_dentry(p.second.dirino, p.second.frag, p.second.name, &inode, &first);
+ dout(20) << " fixing linkage (dnfirst) of " << p.second.dirino << ":"
+ << p.second.name << dendl;
+ int r = read_dentry(
+ p.second.dirino, p.second.frag, p.second.name, &inode, &first);
if (r < 0) {
- derr << "Unexpected error reading dentry "
- << p.second.dirfrag() << "/" << p.second.name
- << ": " << cpp_strerror(r) << dendl;
+ derr << "Unexpected error reading dentry " << p.second.dirfrag() << "/"
+ << p.second.name << ": " << cpp_strerror(r) << dendl;
continue;
}
first = last_snap + 1;
dout(20) << " first is now " << first << dendl;
- r = metadata_driver->inject_linkage(p.second.dirino, p.second.name, p.second.frag, inode, first);
+ r = metadata_driver->inject_linkage(
+ p.second.dirino, p.second.name, p.second.frag, inode, first);
if (r < 0)
return r;
}
if (dirty) {
r = metadata_driver->save_table(&inotable);
if (r < 0)
- return r;
+ return r;
}
}
if (dirty) {
r = metadata_driver->save_table(&snaptable);
if (r < 0)
- return r;
+ return r;
}
}
return 0;