3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright 2015 Nexenta Systems, Inc. All rights reserved.
24 * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
25 */
26
27 #include <assert.h>
28 #include <stddef.h>
29 #include <strings.h>
30 #include <libuutil.h>
31 #include <libzfs.h>
32 #include <fm/fmd_api.h>
33 #include <fm/libtopo.h>
34 #include <sys/types.h>
35 #include <sys/time.h>
36 #include <sys/fs/zfs.h>
37 #include <sys/fm/protocol.h>
38 #include <sys/fm/fs/zfs.h>
39
40 /*
41 * Our serd engines are named 'zfs_<pool_guid>_<vdev_guid>_{checksum,io}'. This
42 * #define reserves enough space for two 64-bit hex values plus the length of
43 * the longest string.
44 */
45 #define MAX_SERDLEN (16 * 2 + sizeof ("zfs___checksum"))
915 }
916 }
917
918 /*
919 * The timeout is fired when we diagnosed an I/O error, and it was not due to
920 * device removal (which would cause the timeout to be cancelled).
921 */
922 /* ARGSUSED */
923 static void
924 zfs_fm_timeout(fmd_hdl_t *hdl, id_t id, void *data)
925 {
926 zfs_case_t *zcp = data;
927
928 if (id == zcp->zc_remove_timer)
929 zfs_case_solve(hdl, zcp, "fault.fs.zfs.vdev.io", B_FALSE);
930 }
931
932 static void
933 zfs_fm_close(fmd_hdl_t *hdl, fmd_case_t *cs)
934 {
935 zfs_case_t *zcp = fmd_case_getspecific(hdl, cs);
936
937 if (zcp->zc_data.zc_serd_checksum[0] != '\0')
938 fmd_serd_destroy(hdl, zcp->zc_data.zc_serd_checksum);
939 if (zcp->zc_data.zc_serd_io[0] != '\0')
940 fmd_serd_destroy(hdl, zcp->zc_data.zc_serd_io);
941 if (zcp->zc_data.zc_has_remove_timer)
942 fmd_timer_remove(hdl, zcp->zc_remove_timer);
943 uu_list_remove(zfs_cases, zcp);
944 fmd_hdl_free(hdl, zcp, sizeof (zfs_case_t));
945 }
946
947 /*
948 * We use the fmd gc entry point to look for old cases that no longer apply.
949 * This allows us to keep our set of case data small in a long running system.
950 */
951 static void
952 zfs_fm_gc(fmd_hdl_t *hdl)
953 {
954 zfs_purge_cases(hdl);
955 }
956
957 static const fmd_hdl_ops_t fmd_ops = {
958 zfs_fm_recv, /* fmdo_recv */
959 zfs_fm_timeout, /* fmdo_timeout */
960 zfs_fm_close, /* fmdo_close */
961 NULL, /* fmdo_stats */
962 zfs_fm_gc, /* fmdo_gc */
963 };
964
965 static const fmd_prop_t fmd_props[] = {
966 { "checksum_N", FMD_TYPE_UINT32, "10" },
967 { "checksum_T", FMD_TYPE_TIME, "10min" },
968 { "io_N", FMD_TYPE_UINT32, "10" },
969 { "io_T", FMD_TYPE_TIME, "10min" },
970 { "remove_timeout", FMD_TYPE_TIME, "15sec" },
971 { NULL, 0, NULL }
972 };
973
974 static const fmd_hdl_info_t fmd_info = {
975 "ZFS Diagnosis Engine", "1.0", &fmd_ops, fmd_props
976 };
977
978 void
979 _fmd_init(fmd_hdl_t *hdl)
980 {
981 fmd_case_t *cp;
982 libzfs_handle_t *zhdl;
983
984 if ((zhdl = libzfs_init()) == NULL)
985 return;
986
987 if ((zfs_case_pool = uu_list_pool_create("zfs_case_pool",
988 sizeof (zfs_case_t), offsetof(zfs_case_t, zc_node),
989 NULL, 0)) == NULL) {
990 libzfs_fini(zhdl);
991 return;
992 }
993
994 if ((zfs_cases = uu_list_create(zfs_case_pool, NULL, 0)) == NULL) {
995 uu_list_pool_destroy(zfs_case_pool);
|
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
24 */
25 /*
26 * Copyright 2015 Nexenta Systems, Inc. All rights reserved.
27 */
28
29 #include <assert.h>
30 #include <stddef.h>
31 #include <strings.h>
32 #include <libuutil.h>
33 #include <libzfs.h>
34 #include <fm/fmd_api.h>
35 #include <fm/libtopo.h>
36 #include <sys/types.h>
37 #include <sys/time.h>
38 #include <sys/fs/zfs.h>
39 #include <sys/fm/protocol.h>
40 #include <sys/fm/fs/zfs.h>
41
42 /*
43 * Our serd engines are named 'zfs_<pool_guid>_<vdev_guid>_{checksum,io}'. This
44 * #define reserves enough space for two 64-bit hex values plus the length of
45 * the longest string.
46 */
47 #define MAX_SERDLEN (16 * 2 + sizeof ("zfs___checksum"))
917 }
918 }
919
920 /*
921 * The timeout is fired when we diagnosed an I/O error, and it was not due to
922 * device removal (which would cause the timeout to be cancelled).
923 */
924 /* ARGSUSED */
925 static void
926 zfs_fm_timeout(fmd_hdl_t *hdl, id_t id, void *data)
927 {
928 zfs_case_t *zcp = data;
929
930 if (id == zcp->zc_remove_timer)
931 zfs_case_solve(hdl, zcp, "fault.fs.zfs.vdev.io", B_FALSE);
932 }
933
934 static void
935 zfs_fm_close(fmd_hdl_t *hdl, fmd_case_t *cs)
936 {
937 zfs_case_t *zcp;
938
939 if ((zcp = fmd_case_getspecific(hdl, cs)) == NULL)
940 return;
941
942 if (zcp->zc_data.zc_serd_checksum[0] != '\0')
943 fmd_serd_destroy(hdl, zcp->zc_data.zc_serd_checksum);
944 if (zcp->zc_data.zc_serd_io[0] != '\0')
945 fmd_serd_destroy(hdl, zcp->zc_data.zc_serd_io);
946 if (zcp->zc_data.zc_has_remove_timer)
947 fmd_timer_remove(hdl, zcp->zc_remove_timer);
948 uu_list_remove(zfs_cases, zcp);
949 fmd_hdl_free(hdl, zcp, sizeof (zfs_case_t));
950 }
951
952 /*
953 * We use the fmd gc entry point to look for old cases that no longer apply.
954 * This allows us to keep our set of case data small in a long running system.
955 */
956 static void
957 zfs_fm_gc(fmd_hdl_t *hdl)
958 {
959 zfs_purge_cases(hdl);
960 }
961
962 static const fmd_hdl_ops_t fmd_ops = {
963 zfs_fm_recv, /* fmdo_recv */
964 zfs_fm_timeout, /* fmdo_timeout */
965 zfs_fm_close, /* fmdo_close */
966 NULL, /* fmdo_stats */
967 zfs_fm_gc, /* fmdo_gc */
968 };
969
970 static const fmd_prop_t fmd_props[] = {
971 { "checksum_N", FMD_TYPE_UINT32, "10" },
972 { "checksum_T", FMD_TYPE_TIME, "10min" },
973 { "io_N", FMD_TYPE_UINT32, "10" },
974 { "io_T", FMD_TYPE_TIME, "10min" },
975 { "remove_timeout", FMD_TYPE_TIME, "15sec" },
976 { NULL, 0, NULL }
977 };
978
979 static const fmd_hdl_info_t fmd_info = {
980 "ZFS Diagnosis Engine", "1.1", &fmd_ops, fmd_props
981 };
982
983 void
984 _fmd_init(fmd_hdl_t *hdl)
985 {
986 fmd_case_t *cp;
987 libzfs_handle_t *zhdl;
988
989 if ((zhdl = libzfs_init()) == NULL)
990 return;
991
992 if ((zfs_case_pool = uu_list_pool_create("zfs_case_pool",
993 sizeof (zfs_case_t), offsetof(zfs_case_t, zc_node),
994 NULL, 0)) == NULL) {
995 libzfs_fini(zhdl);
996 return;
997 }
998
999 if ((zfs_cases = uu_list_create(zfs_case_pool, NULL, 0)) == NULL) {
1000 uu_list_pool_destroy(zfs_case_pool);
|