]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
tasks/cephfs: add TestDataScan.test_scan_links
authorYan, Zheng <zyan@redhat.com>
Mon, 24 Oct 2016 08:24:24 +0000 (16:24 +0800)
committerYan, Zheng <zyan@redhat.com>
Tue, 25 Oct 2016 13:37:08 +0000 (21:37 +0800)
Signed-off-by: Yan, Zheng <zyan@redhat.com>
tasks/cephfs/mount.py
tasks/cephfs/test_data_scan.py

index 873c3edfddd35887531956f285e5f646a18df0fd..7b9c22342b994ce5b793e79ecbf0f84a75d755e6 100644 (file)
@@ -550,6 +550,20 @@ class CephFSMount(object):
         proc.wait()
         return int(proc.stdout.getvalue().strip())
 
+    def path_to_nlink(self, fs_path):
+        abs_path = os.path.join(self.mountpoint, fs_path)
+
+        pyscript = dedent("""
+            import os
+            import stat
+
+            print os.stat("{path}").st_nlink
+            """).format(path=abs_path)
+
+        proc = self._run_python(pyscript)
+        proc.wait()
+        return int(proc.stdout.getvalue().strip())
+
     def ls(self, path=None):
         """
         Wrap ls: return a list of strings
index 2a0d05abc7b593f433303268bfdc50b5d5778f65..cf84b023cd0e672b4010a52e8e95439c482d5fd4 100644 (file)
@@ -544,4 +544,60 @@ class TestDataScan(CephFSTestCase):
             out = self.fs.data_scan(["pg_files", "mydir", pg_str])
             lines = [l for l in out.split("\n") if l]
             log.info("{0}: {1}".format(pg_str, lines))
-            self.assertSetEqual(set(lines), set(pgs_to_files[pg_str]))
\ No newline at end of file
+            self.assertSetEqual(set(lines), set(pgs_to_files[pg_str]))
+
+    def test_scan_links(self):
+        """
+        The scan_links command fixes linkage errors
+        """
+        self.mount_a.run_shell(["mkdir", "testdir1"])
+        self.mount_a.run_shell(["mkdir", "testdir2"])
+        dir1_ino = self.mount_a.path_to_ino("testdir1")
+        dir2_ino = self.mount_a.path_to_ino("testdir2")
+        dirfrag1_oid = "{0:x}.00000000".format(dir1_ino)
+        dirfrag2_oid = "{0:x}.00000000".format(dir2_ino)
+
+        self.mount_a.run_shell(["touch", "testdir1/file1"])
+        self.mount_a.run_shell(["ln", "testdir1/file1", "testdir1/link1"])
+        self.mount_a.run_shell(["ln", "testdir1/file1", "testdir2/link2"])
+
+        mds_id = self.fs.get_active_names()[0]
+        self.fs.mds_asok(["flush", "journal"], mds_id)
+
+        dirfrag1_keys = self._dirfrag_keys(dirfrag1_oid)
+
+        # introduce duplicated primary link
+        file1_key = "file1_head"
+        self.assertIn(file1_key, dirfrag1_keys)
+        file1_omap_data = self.fs.rados(["getomapval", dirfrag1_oid, file1_key, '-'])
+        self.fs.rados(["setomapval", dirfrag2_oid, file1_key], stdin_data=file1_omap_data)
+        self.assertIn(file1_key, self._dirfrag_keys(dirfrag2_oid))
+
+        # remove a remote link, make inode link count incorrect
+        link1_key = 'link1_head'
+        self.assertIn(link1_key, dirfrag1_keys)
+        self.fs.rados(["rmomapkey", dirfrag1_oid, link1_key])
+
+        # increase good primary link's version
+        self.mount_a.run_shell(["touch", "testdir1/file1"])
+        self.mount_a.umount_wait()
+
+        self.fs.mds_asok(["flush", "journal"], mds_id)
+        self.fs.mds_stop()
+        self.fs.mds_fail()
+
+        # repair linkage errors
+        self.fs.data_scan(["scan_links"])
+
+        # primary link in testdir2 was deleted?
+        self.assertNotIn(file1_key, self._dirfrag_keys(dirfrag2_oid))
+
+        self.fs.mds_restart()
+        self.fs.wait_for_daemons()
+
+        self.mount_a.mount()
+        self.mount_a.wait_until_mounted()
+
+        # link count was adjusted?
+        file1_nlink = self.mount_a.path_to_nlink("testdir1/file1")
+        self.assertEqual(file1_nlink, 2)