Skip to content

Commit 7ce4252

Browse files
committed
Merge PR ceph#61173 into main
* refs/pull/61173/head: Reviewed-by: Venky Shankar <[email protected]> Reviewed-by: Milind Changire <[email protected]> Reviewed-by: Anthony D Atri <[email protected]>
2 parents 0efafa3 + ed00c81 commit 7ce4252

File tree

5 files changed

+66
-5
lines changed

5 files changed

+66
-5
lines changed

doc/cephfs/scrub.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,8 @@ These above named MDS damages can be repaired by using the following command::
150150
If scrub is able to repair the damage, the corresponding entry is automatically
151151
removed from the damage table.
152152

153+
Note: A scrub invoked with the ``repair`` option can identify an damaged hard link but not repair it.
154+
153155

154156
Evaluate strays using recursive scrub
155157
=====================================

qa/suites/fs/functional/tasks/scrub.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ overrides:
88
- bad backtrace on inode
99
- overall HEALTH_
1010
- \(MDS_TRIM\)
11+
- object missing on disk
1112
conf:
1213
mds:
1314
mds log max segments: 1

qa/tasks/cephfs/test_scrub_checks.py

Lines changed: 43 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -477,6 +477,44 @@ def test_scrub_split_dirfrags(self):
477477
timeout=30
478478
)
479479

480+
def test_scrub_remote_link(self):
481+
"""
482+
test scrub remote link
483+
"""
484+
test_dir_path = "test_dir"
485+
self.mount_a.run_shell(["mkdir", test_dir_path])
486+
file_dir_path = os.path.join(test_dir_path, "file_dir")
487+
self.mount_a.run_shell(["mkdir", file_dir_path])
488+
file_path = os.path.join(file_dir_path, "test_file.txt")
489+
link_path = os.path.join(test_dir_path, "test_link")
490+
abs_link_path = "/" + link_path
491+
self.mount_a.run_shell(["touch", file_path])
492+
self.mount_a.run_shell(["ln", file_path, link_path])
493+
file_ino = self.mount_a.path_to_ino(file_path)
494+
dir_ino = self.mount_a.path_to_ino(file_dir_path)
495+
rados_obj_file = "{ino:x}.00000000".format(ino=file_ino)
496+
rados_obj_dir = "{ino:x}.00000000".format(ino=dir_ino)
497+
self.fs.flush()
498+
self.fs.rados(["rm", rados_obj_file], pool=self.fs.get_data_pool_name())
499+
self.fs.rados(["rm", rados_obj_dir], pool=self.fs.get_metadata_pool_name())
500+
self.fs.mds_fail_restart()
501+
self.fs.wait_for_daemons()
502+
status = self.fs.mds_asok(['status'])
503+
self.assertEqual("up:active", str(status['state']))
504+
mds_rank = self.fs.get_rank()['rank']
505+
success_validator = lambda j, r: self.json_validator(j, r, "return_code", 0)
506+
scrub_json = self.tell_command(mds_rank,
507+
"scrub start /{0} recursive force".format(test_dir_path),
508+
success_validator)
509+
self.assertEqual(
510+
self.fs.wait_until_scrub_complete(tag=scrub_json["scrub_tag"]), True)
511+
damage_json = self.tell_command(mds_rank, "damage ls")
512+
found_remote_link_damage = False
513+
for entry in damage_json:
514+
if entry["path"] == abs_link_path :
515+
found_remote_link_damage = True
516+
self.assertEqual(found_remote_link_damage, True)
517+
480518
def test_stray_evaluation_with_scrub(self):
481519
"""
482520
test that scrub can iterate over ~mdsdir and evaluate strays
@@ -501,7 +539,7 @@ def json_validator(json_out, rc, element, expected_value):
501539
jv=element_value, ev=expected_value)
502540
return True, "Succeeded"
503541

504-
def tell_command(self, mds_rank, command, validator):
542+
def tell_command(self, mds_rank, command, validator=None):
505543
log.info("Running command '{command}'".format(command=command))
506544

507545
command_list = command.split()
@@ -510,9 +548,10 @@ def tell_command(self, mds_rank, command, validator):
510548
log.info("command '{command}' returned '{jout}'".format(
511549
command=command, jout=jout))
512550

513-
success, errstring = validator(jout, 0)
514-
if not success:
515-
raise AsokCommandFailedError(command, 0, jout, errstring)
551+
if validator:
552+
success, errstring = validator(jout, 0)
553+
if not success:
554+
raise AsokCommandFailedError(command, 0, jout, errstring)
516555
return jout
517556

518557
@staticmethod

src/mds/ScrubStack.cc

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -487,6 +487,19 @@ void ScrubStack::scrub_dir_inode_final(CInode *in)
487487
return;
488488
}
489489

490+
void ScrubStack::identify_remote_link_damage(CDentry *dn) {
491+
492+
CDentry::linkage_t *dnl = dn->get_linkage();
493+
CInode *remote_inode = mdcache->get_inode(dnl->get_remote_ino());
494+
if (!remote_inode) {
495+
if (mdcache->mds->damage_table.is_remote_damaged(dnl->get_remote_ino())) {
496+
dout(4) << "scrub: remote dentry points to damaged ino " << *dn << dendl;
497+
return;
498+
}
499+
mdcache->open_remote_dentry(dn, true, new C_MDSInternalNoop());
500+
}
501+
}
502+
490503
void ScrubStack::scrub_dirfrag(CDir *dir, bool *done)
491504
{
492505
ceph_assert(dir != NULL);
@@ -530,7 +543,7 @@ void ScrubStack::scrub_dirfrag(CDir *dir, bool *done)
530543
if (dnl->is_primary()) {
531544
_enqueue(dnl->get_inode(), header, false);
532545
} else if (dnl->is_remote() || dnl->is_referent_remote()) {
533-
// TODO: check remote linkage
546+
identify_remote_link_damage(dn);
534547
}
535548
}
536549
}

src/mds/ScrubStack.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,12 @@ class ScrubStack {
212212
*/
213213
void scrub_file_inode(CInode *in);
214214

215+
/**
216+
* Scrub a file inode.
217+
* @param dn The remote dentry to identify
218+
*/
219+
void identify_remote_link_damage(CDentry *dn);
220+
215221
/**
216222
* Callback from completion of CInode::validate_disk_state
217223
* @param in The inode we were validating

0 commit comments

Comments
 (0)