Small program that converts a dataset id and an object id to a path

Small program that converts a dataset id and an object id to a path

Reviewed-by: Prakash Surya <prakash.surya@delphix.com>
Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Reviewed-by: Matthew Ahrens <mahrens@delphix.com>
Signed-off-by: Paul Dagnelie <pcd@delphix.com>
Closes #10204
This commit is contained in:
Paul Dagnelie 2020-05-20 10:05:33 -07:00 committed by GitHub
parent 7b0e39030c
commit de4f06c275
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 349 additions and 7 deletions

View File

@ -1,5 +1,5 @@
SUBDIRS = zfs zpool zdb zhack zinject zstream zstreamdump ztest
SUBDIRS += fsck_zfs vdev_id raidz_test
SUBDIRS += fsck_zfs vdev_id raidz_test zfs_ids_to_path
if USING_PYTHON
SUBDIRS += arcstat arc_summary dbufstat

1
cmd/zfs_ids_to_path/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
zfs_ids_to_path

View File

@ -0,0 +1,9 @@
include $(top_srcdir)/config/Rules.am
sbin_PROGRAMS = zfs_ids_to_path
zfs_ids_to_path_SOURCES = \
zfs_ids_to_path.c
zfs_ids_to_path_LDADD = \
$(top_builddir)/lib/libzfs/libzfs.la

View File

@ -0,0 +1,96 @@
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright (c) 2019 by Delphix. All rights reserved.
*/
#include <libintl.h>
#include <unistd.h>
#include <sys/types.h>
#include <stdint.h>
#include <libzfs.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
libzfs_handle_t *g_zfs;
void
usage(int err)
{
fprintf(stderr, "Usage: [-v] zfs_ids_to_path <pool> <objset id> "
"<object id>\n");
exit(err);
}
int
main(int argc, char **argv)
{
boolean_t verbose = B_FALSE;
char c;
while ((c = getopt(argc, argv, "v")) != -1) {
switch (c) {
case 'v':
verbose = B_TRUE;
break;
}
}
argc -= optind;
argv += optind;
if (argc != 3) {
(void) fprintf(stderr, "Incorrect number of arguments: %d\n",
argc);
usage(1);
}
uint64_t objset, object;
if (sscanf(argv[1], "%llu", (u_longlong_t *)&objset) != 1) {
(void) fprintf(stderr, "Invalid objset id: %s\n", argv[2]);
usage(2);
}
if (sscanf(argv[2], "%llu", (u_longlong_t *)&object) != 1) {
(void) fprintf(stderr, "Invalid object id: %s\n", argv[3]);
usage(3);
}
if ((g_zfs = libzfs_init()) == NULL) {
(void) fprintf(stderr, "%s\n", libzfs_error_init(errno));
return (4);
}
zpool_handle_t *pool = zpool_open(g_zfs, argv[0]);
if (pool == NULL) {
fprintf(stderr, "Could not open pool %s\n", argv[1]);
libzfs_fini(g_zfs);
return (5);
}
char pathname[PATH_MAX * 2];
if (verbose) {
zpool_obj_to_path_ds(pool, objset, object, pathname,
sizeof (pathname));
} else {
zpool_obj_to_path(pool, objset, object, pathname,
sizeof (pathname));
}
printf("%s\n", pathname);
zpool_close(pool);
libzfs_fini(g_zfs);
return (0);
}

View File

@ -76,6 +76,7 @@ AC_CONFIG_FILES([
cmd/zed/Makefile
cmd/zed/zed.d/Makefile
cmd/zfs/Makefile
cmd/zfs_ids_to_path/Makefile
cmd/zgenhostid/Makefile
cmd/zhack/Makefile
cmd/zinject/Makefile
@ -258,6 +259,7 @@ AC_CONFIG_FILES([
tests/zfs-tests/tests/functional/cli_root/zfs_destroy/Makefile
tests/zfs-tests/tests/functional/cli_root/zfs_diff/Makefile
tests/zfs-tests/tests/functional/cli_root/zfs_get/Makefile
tests/zfs-tests/tests/functional/cli_root/zfs_ids_to_path/Makefile
tests/zfs-tests/tests/functional/cli_root/zfs_inherit/Makefile
tests/zfs-tests/tests/functional/cli_root/zfs_load-key/Makefile
tests/zfs-tests/tests/functional/cli_root/zfs_mount/Makefile

View File

@ -441,8 +441,10 @@ extern int zpool_events_next(libzfs_handle_t *, nvlist_t **, int *, unsigned,
int);
extern int zpool_events_clear(libzfs_handle_t *, int *);
extern int zpool_events_seek(libzfs_handle_t *, uint64_t, int);
extern void zpool_obj_to_path_ds(zpool_handle_t *, uint64_t, uint64_t, char *,
size_t);
extern void zpool_obj_to_path(zpool_handle_t *, uint64_t, uint64_t, char *,
size_t len);
size_t);
extern int zfs_ioctl(libzfs_handle_t *, int, struct zfs_cmd *);
extern int zpool_get_physpath(zpool_handle_t *, char *, size_t);
extern void zpool_explain_recover(libzfs_handle_t *, const char *, int,

View File

@ -4362,9 +4362,9 @@ zpool_events_seek(libzfs_handle_t *hdl, uint64_t eid, int zevent_fd)
return (error);
}
void
zpool_obj_to_path(zpool_handle_t *zhp, uint64_t dsobj, uint64_t obj,
char *pathname, size_t len)
static void
zpool_obj_to_path_impl(zpool_handle_t *zhp, uint64_t dsobj, uint64_t obj,
char *pathname, size_t len, boolean_t always_unmounted)
{
zfs_cmd_t zc = {"\0"};
boolean_t mounted = B_FALSE;
@ -4391,7 +4391,8 @@ zpool_obj_to_path(zpool_handle_t *zhp, uint64_t dsobj, uint64_t obj,
(void) strlcpy(dsname, zc.zc_value, sizeof (dsname));
/* find out if the dataset is mounted */
mounted = is_mounted(zhp->zpool_hdl, dsname, &mntpnt);
mounted = !always_unmounted && is_mounted(zhp->zpool_hdl, dsname,
&mntpnt);
/* get the corrupted object's path */
(void) strlcpy(zc.zc_name, dsname, sizeof (zc.zc_name));
@ -4412,6 +4413,19 @@ zpool_obj_to_path(zpool_handle_t *zhp, uint64_t dsobj, uint64_t obj,
free(mntpnt);
}
void
zpool_obj_to_path(zpool_handle_t *zhp, uint64_t dsobj, uint64_t obj,
char *pathname, size_t len)
{
zpool_obj_to_path_impl(zhp, dsobj, obj, pathname, len, B_FALSE);
}
void
zpool_obj_to_path_ds(zpool_handle_t *zhp, uint64_t dsobj, uint64_t obj,
char *pathname, size_t len)
{
zpool_obj_to_path_impl(zhp, dsobj, obj, pathname, len, B_TRUE);
}
/*
* Wait while the specified activity is in progress in the pool.
*/

View File

@ -42,6 +42,7 @@ dist_man_MANS = \
zfs-upgrade.8 \
zfs-userspace.8 \
zfs-wait.8 \
zfs_ids_to_path.8 \
zgenhostid.8 \
zinject.8 \
zpool.8 \

View File

@ -0,0 +1,50 @@
.\"
.\" CDDL HEADER START
.\"
.\" The contents of this file are subject to the terms of the
.\" Common Development and Distribution License (the "License").
.\" You may not use this file except in compliance with the License.
.\"
.\" You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
.\" or http://www.opensolaris.org/os/licensing.
.\" See the License for the specific language governing permissions
.\" and limitations under the License.
.\"
.\" When distributing Covered Code, include this CDDL HEADER in each
.\" file and include the License file at usr/src/OPENSOLARIS.LICENSE.
.\" If applicable, add the following below this CDDL HEADER, with the
.\" fields enclosed by brackets "[]" replaced with your own identifying
.\" information: Portions Copyright [yyyy] [name of copyright owner]
.\"
.\" CDDL HEADER END
.\"
.\"
.\" Copyright (c) 2020 by Delphix. All rights reserved.
.Dd April 17, 2020
.Dt ZFS_IDS_TO_PATH 8
.Os Linux
.Sh NAME
.Nm zfs_ids_to_path
.Nd convert objset and object ids to names and paths
.Sh SYNOPSIS
.Nm
.Op Fl v
.Ar pool
.Ar objset id
.Ar object id
.Nm
.Sh DESCRIPTION
.Pp
.LP
The
.Sy zfs_ids_to_path
utility converts a provided objset and object id into a path to the file that
those ids refer to.
.Bl -tag -width "-D"
.It Fl v
Verbose.
Print the dataset name and the file path within the dataset separately. This
will work correctly even if the dataset is not mounted.
.Sh SEE ALSO
.Xr zfs 8 ,
.Xr zdb 8

View File

@ -169,6 +169,10 @@ tests = ['zfs_get_001_pos', 'zfs_get_002_pos', 'zfs_get_003_pos',
'zfs_get_008_pos', 'zfs_get_009_pos', 'zfs_get_010_neg']
tags = ['functional', 'cli_root', 'zfs_get']
[tests/functional/cli_root/zfs_ids_to_path]
tests = ['zfs_ids_to_path_001_pos']
tags = ['functional', 'cli_root', 'zfs_ids_to_path']
[tests/functional/cli_root/zfs_inherit]
tests = ['zfs_inherit_001_neg', 'zfs_inherit_002_neg', 'zfs_inherit_003_pos',
'zfs_inherit_mountpoint']

View File

@ -183,7 +183,8 @@ export ZFS_FILES='zdb
zed
zgenhostid
zstream
zstreamdump'
zstreamdump
zfs_ids_to_path'
export ZFSTEST_FILES='btree_test
chg_usr_exec

View File

@ -13,6 +13,7 @@ SUBDIRS = \
zfs_destroy \
zfs_diff \
zfs_get \
zfs_ids_to_path \
zfs_inherit \
zfs_load-key \
zfs_mount \

View File

@ -0,0 +1,5 @@
pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/cli_root/zfs_ids_to_path
dist_pkgdata_SCRIPTS = \
setup.ksh \
cleanup.ksh \
zfs_ids_to_path_001_pos.ksh

View File

@ -0,0 +1,29 @@
#!/bin/ksh -p
#
# CDDL HEADER START
#
# The contents of this file are subject to the terms of the
# Common Development and Distribution License (the "License").
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
# or http://www.opensolaris.org/os/licensing.
# See the License for the specific language governing permissions
# and limitations under the License.
#
# When distributing Covered Code, include this CDDL HEADER in each
# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
# If applicable, add the following below this CDDL HEADER, with the
# fields enclosed by brackets "[]" replaced with your own identifying
# information: Portions Copyright [yyyy] [name of copyright owner]
#
# CDDL HEADER END
#
#
# Copyright (c) 2020 by Delphix. All rights reserved.
#
. $STF_SUITE/include/libtest.shlib
default_cleanup

View File

@ -0,0 +1,31 @@
#!/bin/ksh -p
#
# CDDL HEADER START
#
# The contents of this file are subject to the terms of the
# Common Development and Distribution License (the "License").
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
# or http://www.opensolaris.org/os/licensing.
# See the License for the specific language governing permissions
# and limitations under the License.
#
# When distributing Covered Code, include this CDDL HEADER in each
# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
# If applicable, add the following below this CDDL HEADER, with the
# fields enclosed by brackets "[]" replaced with your own identifying
# information: Portions Copyright [yyyy] [name of copyright owner]
#
# CDDL HEADER END
#
#
# Copyright (c) 2020 by Delphix. All rights reserved.
#
. $STF_SUITE/include/libtest.shlib
verify_runnable "global"
default_setup $DISKS

View File

@ -0,0 +1,96 @@
#!/bin/ksh -p
#
# CDDL HEADER START
#
# The contents of this file are subject to the terms of the
# Common Development and Distribution License (the "License").
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
# or http://www.opensolaris.org/os/licensing.
# See the License for the specific language governing permissions
# and limitations under the License.
#
# When distributing Covered Code, include this CDDL HEADER in each
# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
# If applicable, add the following below this CDDL HEADER, with the
# fields enclosed by brackets "[]" replaced with your own identifying
# information: Portions Copyright [yyyy] [name of copyright owner]
#
# CDDL HEADER END
#
#
# Copyright (c) 2020 by Delphix. All rights reserved.
#
. $STF_SUITE/include/libtest.shlib
#
# DESCRIPTION: Identify the objset id and the object id of a file in a
# filesystem, and verify that zfs_ids_to_path behaves correctly with them.
#
# STRATEGY:
# 1. Create a dateset
# 2. Makes files in the dataset
# 3. Verify that zfs_ids_to_path outputs the correct format for each one
#
verify_runnable "both"
function cleanup
{
destroy_dataset $TESTPOOL/$TESTFS
zfs create -o mountpoint=$TESTDIR $TESTPOOL/$TESTFS
}
function test_one
{
typeset ds_id="$1"
typeset ds_path="$2"
typeset file_path="$3"
typeset mntpnt=$(get_prop mountpoint $ds_path)
typeset file_id=$(ls -i /$mntpnt/$file_path | sed 's/ .*//')
typeset output=$(zfs_ids_to_path $TESTPOOL $ds_id $file_id)
[[ "$output" == "$mntpnt/$file_path" ]] || \
log_fail "Incorrect output for non-verbose while mounted: $output"
output=$(zfs_ids_to_path -v $TESTPOOL $ds_id $file_id)
[[ "$output" == "$ds_path:/$file_path" ]] || \
log_fail "Incorrect output for verbose while mounted: $output"
log_must zfs unmount $ds_path
output=$(zfs_ids_to_path $TESTPOOL $ds_id $file_id)
[[ "$output" == "$ds_path:/$file_path" ]] || \
log_fail "Incorrect output for non-verbose while unmounted: $output"
output=$(zfs_ids_to_path -v $TESTPOOL $ds_id $file_id)
[[ "$output" == "$ds_path:/$file_path" ]] || \
log_fail "Incorrect output for verbose while unmounted: $output"
log_must zfs mount $ds_path
}
log_onexit cleanup
typeset BASE=$TESTPOOL/$TESTFS
typeset TESTFILE1=f1
typeset TESTDIR1=d1
typeset TESTFILE2=d1/f2
typeset TESTDIR2=d1/d2
typeset TESTFILE3=d1/d2/f3
typeset TESTFILE4=d1/d2/f4
typeset mntpnt=$(get_prop mountpoint $BASE)
log_must touch /$mntpnt/$TESTFILE1
log_must mkdir /$mntpnt/$TESTDIR1
log_must touch /$mntpnt/$TESTFILE2
log_must mkdir /$mntpnt/$TESTDIR2
log_must touch /$mntpnt/$TESTFILE3
log_must touch /$mntpnt/$TESTFILE4
typeset ds_id=$(zdb $BASE | grep "^Dataset" | sed 's/.* ID \([0-9]*\).*/\1/')
test_one $ds_id $BASE $TESTFILE1
test_one $ds_id $BASE $TESTFILE2
test_one $ds_id $BASE $TESTFILE3
test_one $ds_id $BASE $TESTFILE4
log_pass "zfs_ids_to_path displayed correctly"