]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
tasks/cephfs: add TestForwardScrub.test_backtrace_repair
authorJohn Spray <john.spray@redhat.com>
Thu, 20 Oct 2016 10:49:08 +0000 (11:49 +0100)
committerJohn Spray <john.spray@redhat.com>
Mon, 24 Oct 2016 10:37:47 +0000 (11:37 +0100)
Signed-off-by: John Spray <john.spray@redhat.com>
suites/fs/recovery/tasks/forward-scrub.yaml
tasks/cephfs/filesystem.py
tasks/cephfs/test_forward_scrub.py

index 0a6a09cd4325f90a9ef394caf39ba3fe85ace131..dbbed4bf718b2a8eec324d8c1722b0cbaca71956 100644 (file)
@@ -3,6 +3,7 @@ overrides:
   ceph:
     log-whitelist:
       - inode wrongly marked free
+      - bad backtrace on inode
       - inode table repaired for inode
       - Scrub error on inode
 
index 3f0687512a4f64cfacf85b8b92adbda19ab54cff..709ed1a1c10ffea8387af890576eb55fba1e1f87 100644 (file)
@@ -675,6 +675,30 @@ class Filesystem(MDSCluster):
 
         return json.loads(p.stdout.getvalue().strip())
 
+    def _write_data_xattr(self, ino_no, xattr_name, data, pool=None):
+        """
+        Write to an xattr of the 0th data object of an inode.  Will
+        succeed whether the object and/or xattr already exist or not.
+
+        :param ino_no: integer inode number
+        :param xattr_name: string name of the xattr
+        :param data: byte array data to write to the xattr
+        :param pool: name of data pool or None to use primary data pool
+        :return: None
+        """
+        remote = self.mds_daemons[self.mds_ids[0]].remote
+        if pool is None:
+            pool = self.get_data_pool_name()
+
+        obj_name = "{0:x}.00000000".format(ino_no)
+        args = [
+            os.path.join(self._prefix, "rados"), "-p", pool, "setxattr",
+            obj_name, xattr_name, data
+        ]
+        remote.run(
+            args=args,
+            stdout=StringIO())
+
     def read_backtrace(self, ino_no, pool=None):
         """
         Read the backtrace from the data pool, return a dict in the format
index 6df9b73e33cf1a82af975095bbd87cb313138e6a..a0dc3eb3dee1ee707e3ec02b4e5a13869d5f447a 100644 (file)
@@ -262,3 +262,33 @@ class TestForwardScrub(CephFSTestCase):
         self.assertGreater(
                 table['0']['data']['inotable']['free'][0]['start'],
                 inos['./file3_sixmegs'])
+
+    def test_backtrace_repair(self):
+        """
+        That the MDS can repair an inodes backtrace in the data pool
+        if it is found to be damaged.
+        """
+        # Create a file for subsequent checks
+        self.mount_a.run_shell(["mkdir", "parent_a"])
+        self.mount_a.run_shell(["touch", "parent_a/alpha"])
+        file_ino = self.mount_a.path_to_ino("parent_a/alpha")
+
+        # That backtrace and layout are written after initial flush
+        self.fs.mds_asok(["flush", "journal"])
+        backtrace = self.fs.read_backtrace(file_ino)
+        self.assertEqual(['alpha', 'parent_a'],
+                         [a['dname'] for a in backtrace['ancestors']])
+
+        with self.assert_cluster_log("bad backtrace on inode", invert_match=True):
+            self.fs.mds_asok(["scrub_path", "/", "repair", "recursive"])
+
+        # Go corrupt the backtrace
+        self.fs._write_data_xattr(file_ino, "inode_backtrace_t",
+                                  "oh i'm sorry did i overwrite your xattr?")
+
+        with self.assert_cluster_log("bad backtrace on inode"):
+            self.fs.mds_asok(["scrub_path", "/", "repair", "recursive"])
+        self.fs.mds_asok(["flush", "journal"])
+        backtrace = self.fs.read_backtrace(file_ino)
+        self.assertEqual(['alpha', 'parent_a'],
+                         [a['dname'] for a in backtrace['ancestors']])