From c01fd44591daf08f35b78ee488352da00396f90b Mon Sep 17 00:00:00 2001 From: Paul Zuchowski Date: Fri, 16 Apr 2021 13:51:48 -0400 Subject: [PATCH] Add zfs_refcount command --- sdb/commands/zfs/zfs_refcount.py | 59 +++++++++++++++++++ .../spa |member spa_refcount | zfs_refcount | 3 + tests/integration/test_zfs_generic.py | 3 + 3 files changed, 65 insertions(+) create mode 100644 sdb/commands/zfs/zfs_refcount.py create mode 100644 tests/integration/data/regression_output/zfs/spa |member spa_refcount | zfs_refcount diff --git a/sdb/commands/zfs/zfs_refcount.py b/sdb/commands/zfs/zfs_refcount.py new file mode 100644 index 00000000..48559772 --- /dev/null +++ b/sdb/commands/zfs/zfs_refcount.py @@ -0,0 +1,59 @@ +# +# Copyright 2020 Datto, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +# pylint: disable=missing-docstring + +from typing import Iterable +import drgn +import sdb +from sdb.commands.spl.spl_list import SPLList + + +class Zfs_Refcount(sdb.PrettyPrinter): + names = ["zfs_refcount"] + input_type = "zfs_refcount_t *" + output_type = "zfs_refcount_t *" + + @staticmethod + def print_ref(obj: drgn.Object) -> None: + ptr = int(obj.ref_holder) + c = sdb.create_object("char *", ptr) + try: + s = c.string_().decode("utf-8") + except UnicodeDecodeError: + s = "" + print(f"{hex(ptr)} {s} ") + + def pretty_print(self, objs: Iterable[drgn.Object]) -> None: + for zr in objs: + # handle the lack of rc_tracked in non-debug zfs build + tracked = 0 + try: + tracked = zr.rc_tracked + except AttributeError: + pass + print(f"zfs_recount_t at {hex(zr)} has {int(zr.rc_count)} " + f"current holds tracked={int(tracked)}") + if tracked: + ref_list = zr.rc_list + list_addr = ref_list.address_of_() + refs = sdb.execute_pipeline( + [list_addr], + [SPLList(), sdb.Cast(["reference_t *"])], + ) + + for ref in refs: + Zfs_Refcount.print_ref(ref) diff --git a/tests/integration/data/regression_output/zfs/spa |member spa_refcount | zfs_refcount b/tests/integration/data/regression_output/zfs/spa |member spa_refcount | zfs_refcount new file mode 100644 index 00000000..1465f561 --- /dev/null +++ b/tests/integration/data/regression_output/zfs/spa |member spa_refcount | zfs_refcount @@ -0,0 +1,3 @@ +zfs_recount_t at 0xffffa0894e7223c8 has 12 current holds tracked=0 +zfs_recount_t at 0xffffa089413ba3c8 has 15 current holds tracked=0 +zfs_recount_t at 0xffffa08955c463c8 has 39 current holds tracked=0 diff --git a/tests/integration/test_zfs_generic.py b/tests/integration/test_zfs_generic.py index 812c2ae7..b8c67246 100644 --- a/tests/integration/test_zfs_generic.py +++ b/tests/integration/test_zfs_generic.py @@ -61,6 +61,9 @@ "spa data | vdev | metaslab | filter 'obj.ms_loaded == 1' | head 1 | member ms_sm.sm_phys.smp_histogram | zhist", "spa data | vdev | metaslab | filter 'obj.ms_loaded == 1' | head 1 | member ms_sm.sm_phys.smp_histogram | zhist 9", "spa data | vdev | metaslab | filter 'obj.ms_loaded == 1' | head 1 | member ms_allocatable.rt_histogram | zhist", + + # refcount + "spa |member spa_refcount | zfs_refcount", ] # yapf: disable