Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Create a znode command for sdb #279

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
162 changes: 162 additions & 0 deletions sdb/commands/zfs/znode.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
#
# Copyright 2019 Delphix
# Copyright 2021 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 os
import drgn
from drgn.helpers.linux.fs import inode_path
import sdb
from sdb.target import type_canonicalize, get_prog
from sdb.command import Command


class Inode2znode(Command):
"""
Convert an inode to a znode and display it.

sdb> echo 0xffff9ca45647f588 | cast struct inode * | itoz
ADDR OBJ UNLINKED BLKSZ SIZE ...
0xffff9ca45647f398 2 0 29184 28772 ...
"""

names = ["inode2znode", "i2z", "itoz"]

def _call(self, objs: Iterable[drgn.Object]) -> None:
for obj in objs:
obj_type = type_canonicalize(obj.type_)
if obj_type.kind != drgn.TypeKind.POINTER:
raise sdb.CommandError(
self.name,
f"'{obj.type_.type_name()}' is not a valid pointer type")
obj = drgn.Object(get_prog(),
type=obj.type_.type,
address=obj.value_())
znode = drgn.container_of(obj.address_of_(), 'struct znode',
'z_inode')
znodes = sdb.execute_pipeline([znode], [Znode()])
Znode.pretty_print(znode, znodes)


class Znode2inode(Command):
"""
Convert a znode to an inode and display it.

sdb> echo 0xffff9ca45647f398 | znode | ztoi
ADDR INO MODE LINKS BLOCKS SB
0xffff9ca45647f588 2 33184 1 1 0xffff9ca464ae8800

sdb> znode | znode2inode
ADDR INO MODE LINKS BLOCKS SB
0xffff9ca456478638 2 16877 2 1 0xffff9ca486819800
0xffff9ca456478a80 34 16877 2 1 0xffff9ca464ae8800
0xffff9ca456478ec8 -1 16895 1 0 0xffff9ca464ae8800
0xffff9ca45647b108 3 33184 1 1 0xffff9ca464ae8800
0xffff9ca45647b998 -1 16895 1 0 0xffff9ca486819800
0xffff9ca45647c228 3 16877 2 1 0xffff9ca486819800
0xffff9ca45647dbd8 34 16877 4 1 0xffff9ca486819800
0xffff9ca45647e8b0 34 16877 2 1 0xffff9ca464aeb000
0xffff9ca45647f588 2 33184 1 1 0xffff9ca464ae8800
0xffff9ca45647f9d0 -1 16895 1 0 0xffff9ca464aeb000
"""

names = ["znode2inode", "z2i", "ztoi"]

@staticmethod
def inode_print(znode: drgn.Object) -> None:
inode = znode.z_inode
i = drgn.cast('int', znode.z_id)
print("{:18} {:>8} {:>8} {:>8} {:>8} {:18}".format(
hex(inode.address_), int(i), int(inode.i_mode), int(inode.i_nlink),
int(inode.i_blocks), hex(int(inode.i_sb))))

def _call(self, objs: Iterable[drgn.Object]) -> None:
print("{:18} {:>8} {:>8} {:>8} {:>8} {:18}".format(
"ADDR", "INO", "MODE", "LINKS", "BLOCKS", "SB"))
for obj in objs:
obj_type = type_canonicalize(obj.type_)
if obj_type.kind != drgn.TypeKind.POINTER:
raise sdb.CommandError(
self.name,
f"'{obj.type_.type_name()}' is not a valid pointer type")
obj = drgn.Object(get_prog(),
type=obj.type_.type,
address=obj.value_())
self.inode_print(obj)


class Znode(sdb.Locator, sdb.PrettyPrinter):
"""
Iterate and pretty-print znodes

DESCRIPTION

Iterate znodes or convert an address to a znode
and display it.

sdb> znode
ADDR OBJ UNLINKED BLKSZ SIZE ...
0xffff9ca456478448 2 0 512 2 ...
0xffff9ca456478890 34 0 512 6 ...
0xffff9ca456478cd8 -1 0 0 0 ...
0xffff9ca45647af18 3 0 29696 29257 ...
0xffff9ca45647b7a8 -1 0 0 0 ...
0xffff9ca45647c038 3 0 512 2 ...
0xffff9ca45647d9e8 34 0 512 4 ...
0xffff9ca45647e6c0 34 0 512 4 ...
0xffff9ca45647f398 2 0 29184 28772 ...
0xffff9ca45647f7e0 -1 0 0 0 ...

sdb> echo 0xffff9ca45647f398 | znode
ADDR OBJ UNLINKED BLKSZ SIZE ...
0xffff9ca45647f398 2 0 29184 28772 ...
"""

names = ["znode"]
input_type = "znode_t *"
output_type = "znode_t *"

def pretty_print(self, objs: Iterable[drgn.Object]) -> None:
print("{:18} {:>8} {:8} {:>8} {:>18} {:>18} {:>18} {:<18}".format(
"ADDR", "OBJ", "UNLINKED", "BLKSZ", "SIZE", "INODE", "ZFSVFS",
"FILENAME"))
for znode in objs:
i = drgn.cast('int', znode.z_id)
inode = znode.z_inode
ipath = inode_path(inode)
fn = ""
if ipath is not None:
fn = os.fsdecode(ipath)
print(
"{:18} {:>8d} {:>8d} {:>8d} {:>18} {:>18} {:>18} {:<18}".format(
hex(znode), int(i), int(znode.z_unlinked),
int(znode.z_blksz), int(znode.z_size),
hex(znode.z_inode.address_of_()),
hex(znode.z_inode.i_sb.s_fs_info), str(fn)))

def no_input(self) -> drgn.Object:
znode_cache = drgn.cast("spl_kmem_cache_t *",
sdb.get_object("znode_cache"))
znode_kmem = znode_cache.skc_linux_cache
znodes = sdb.execute_pipeline(
[znode_kmem],
[sdb.Walk(), sdb.Cast(["znode_t *"])],
)
for znode in znodes:
if znode.z_id != 0:
yield znode
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
ADDR OBJ UNLINKED BLKSZ SIZE INODE ZFSVFS FILENAME
0xffffa08884646ec0 1032 0 1024 581 0xffffa088846470b8 0xffffa08953ea8000 etc/profile
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
ADDR INO MODE LINKS BLOCKS SB
0xffffa088846470b8 1032 33188 1 2 0xffffa08955983800
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
ADDR OBJ UNLINKED BLKSZ SIZE INODE ZFSVFS FILENAME
0xffffa08884646ec0 1032 0 1024 581 0xffffa088846470b8 0xffffa08953ea8000 etc/profile
11 changes: 11 additions & 0 deletions tests/integration/data/regression_output/zfs/znode |head 10 |znode
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
ADDR OBJ UNLINKED BLKSZ SIZE INODE ZFSVFS FILENAME
0xffffa08884644000 123 0 512 7 0xffffa088846441f8 0xffffa08953ea8000 etc/profile.d
0xffffa08884644440 68902 0 512 298 0xffffa08884644638 0xffffa08953ea8000 usr/lib/systemd/user/gpg-agent-browser.socket
0xffffa08884644880 68905 0 512 223 0xffffa08884644a78 0xffffa08953ea8000 usr/lib/systemd/user/gpg-agent.service
0xffffa08884644cc0 68898 0 512 231 0xffffa08884644eb8 0xffffa08953ea8000 usr/lib/systemd/user/dirmngr.service
0xffffa08884645100 1900 0 4096 3635 0xffffa088846452f8 0xffffa08953ea8000 etc/security/group.conf
0xffffa08884645540 68904 0 512 308 0xffffa08884645738 0xffffa08953ea8000 usr/lib/systemd/user/gpg-agent-ssh.socket
0xffffa08884645980 2037 0 512 96 0xffffa08884645b78 0xffffa08953ea8000 etc/profile.d/01-locale-fix.sh
0xffffa08884645dc0 67553 0 512 27 0xffffa08884645fb8 0xffffa08953ea8000 usr/lib/systemd/user/sockets.target.wants/gpg-agent-browser.socket
0xffffa08884646200 68899 0 512 204 0xffffa088846463f8 0xffffa08953ea8000 usr/lib/systemd/user/dirmngr.socket
0xffffa08884646640 67554 0 512 25 0xffffa08884646838 0xffffa08953ea8000 usr/lib/systemd/user/sockets.target.wants/gpg-agent-extra.socket
6 changes: 6 additions & 0 deletions tests/integration/test_zfs_generic.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,12 @@
"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",

# znode
"znode |head 10 |znode",
"echo 0xffffa08884646ec0 | znode",
"echo 0xffffa08884646ec0 | znode | znode2inode",
"echo 0xffffa088846470b8 | cast struct inode * | inode2znode",
] # yapf: disable


Expand Down