(一)利用 mdb 调试获取 nvlist_t 中 nvpair_t(name/value) 对
服务器:192.168.2.122
root@2236:~# mdb -k
> ::spa
ADDR STATE NAME
ffffff02dfaea000 ACTIVE p3way
ffffff02e38c0000 ACTIVE p98 //选取存储池 p98 作为调试对象
ffffff02e7fb3000 ACTIVE p99
ffffff02d55b0000 ACTIVE rpool
> ffffff02e38c0000::print -at spa_t
ffffff02e38c0000 spa_t {
ffffff02e38c0000 char [256] spa_name = [ "p98" ]
ffffff02e38c0100 char *spa_comment = 0
ffffff02e38c0108 avl_node_t spa_avl = {
ffffff02e38c0108 struct avl_node *[2] avl_child = [ 0xffffff02dfaea108,
0xffffff02d55b0108 ]
ffffff02e38c0118 uintptr_t avl_pcb = 0x2
}
ffffff02e38c0120 nvlist_t *spa_config = 0xffffff02dfaae820
ffffff02e38c0128 nvlist_t *spa_config_syncing = 0
ffffff02e38c0130 nvlist_t *spa_config_splitting = 0
ffffff02e38c0138 nvlist_t *spa_load_info = 0xffffff02dfaae7f0
//spa_t 结构体中元素 nvlist_t *spa_config 的所有信息
> 0xffffff02dfaae820::print -at nvlist_t
ffffff02dfaae820 nvlist_t {
ffffff02dfaae820 int32_t nvl_version = 0
ffffff02dfaae824 uint32_t nvl_nvflag = 0x1
ffffff02dfaae828 uint64_t nvl_priv = 0xffffff02e1f78b18
ffffff02dfaae830 uint32_t nvl_flag = 0
ffffff02dfaae834 int32_t nvl_pad = 0
}
> 0xffffff02e1f78b18::print -at nvpriv_t
ffffff02e1f78b18 nvpriv_t {
ffffff02e1f78b18 i_nvp_t *nvp_list = 0xffffff02dfa99398
ffffff02e1f78b20 i_nvp_t *nvp_last = 0xffffff02dfa305a8
ffffff02e1f78b28 i_nvp_t *nvp_curr = 0
ffffff02e1f78b30 nv_alloc_t *nvp_nva = nv_alloc_sleep_def
ffffff02e1f78b38 uint32_t nvp_stat = 0
}
> 0xffffff02dfa99398::print -at i_nvp_t
ffffff02dfa99398 i_nvp_t {
ffffff02dfa99398 union _nvi_un = {
ffffff02dfa99398 uint64_t _nvi_align = 0xffffff02e12eea78
ffffff02dfa99398 struct _nvi = {
ffffff02dfa99398 i_nvp_t *_nvi_next = 0xffffff02e12eea78
ffffff02dfa993a0 i_nvp_t *_nvi_prev = 0
}
}
ffffff02dfa993a8 nvpair_t nvi_nvp = {
ffffff02dfa993a8 int32_t nvp_size = 0x20
ffffff02dfa993ac int16_t nvp_name_sz = 0x8
ffffff02dfa993ae int16_t nvp_reserve = 0
ffffff02dfa993b0 int32_t nvp_value_elem = 0x1
ffffff02dfa993b4 data_type_t nvp_type = 8 (DATA_TYPE_UINT64)
}
}
//nvpair_t 类型的大小
> ::sizeof nvpair_t
sizeof (nvpair_t) = 0x10
//nvpair_t 地址为 ffffff02dfa993a8 的属性名称为 version
> ffffff02dfa993b8::print -at char
ffffff02dfa993b8 char 'v'
> ffffff02dfa993b9::print -at char
ffffff02dfa993b9 char 'e'
> ffffff02dfa993ba::print -at char
ffffff02dfa993ba char 'r'
> ffffff02dfa993bb::print -at char
ffffff02dfa993bb char 's'
> ffffff02dfa993bc::print -at char
ffffff02dfa993bc char 'i'
> ffffff02dfa993bd::print -at char
ffffff02dfa993bd char 'o'
> ffffff02dfa993be::print -at char
ffffff02dfa993be char 'n'
> ffffff02dfa993bf::print -at char
ffffff02dfa993bf char '\0'
//地址为 ffffff02dfa993a8 的 nvpair_t 指向的下一个 nvpair_t 地址
> 0xffffff02e12eea78::print -at i_nvp_t
ffffff02e12eea78 i_nvp_t {
ffffff02e12eea78 union _nvi_un = {
ffffff02e12eea78 uint64_t _nvi_align = 0xffffff02e1454d80
ffffff02e12eea78 struct _nvi = {
ffffff02e12eea78 i_nvp_t *_nvi_next = 0xffffff02e1454d80
ffffff02e12eea80 i_nvp_t *_nvi_prev = 0xffffff02dfa99398
}
}
ffffff02e12eea88 nvpair_t nvi_nvp = {
ffffff02e12eea88 int32_t nvp_size = 0x20
ffffff02e12eea8c int16_t nvp_name_sz = 0x5
ffffff02e12eea8e int16_t nvp_reserve = 0
ffffff02e12eea90 int32_t nvp_value_elem = 0x1
ffffff02e12eea94 data_type_t nvp_type = 9 (DATA_TYPE_STRING)
}
}
//nvpair_t 地址为 ffffff02e12eea88 的属性名称为 name
> ffffff02e12eea98::print -at char //计算得来
ffffff02e12eea98 char 'n'
> ffffff02e12eea99::print -at char
ffffff02e12eea99 char 'a'
> ffffff02e12eea9a::print -at char
ffffff02e12eea9a char 'm'
> ffffff02e12eea9b::print -at char
ffffff02e12eea9b char 'e'
> ffffff02e12eea9c::print -at char
ffffff02e12eea9c char '\0'
//nvpair_t 地址为 ffffff02e12eea88 的属性名称对应的属性值为 p98
> ffffff02e12eeaa0::print -at char //计算得来
ffffff02e12eeaa0 char 'p'
> ffffff02e12eeaa1::print -at char
ffffff02e12eeaa1 char '9'
> ffffff02e12eeaa2::print -at char
ffffff02e12eeaa2 char '8'
> ffffff02e12eeaa3::print -at char
ffffff02e12eeaa3 char '\0'
//地址为 0xffffff02dfa305a8 的 nvpair_t 结构(spa_config的最后一个nvpair_t结构==>i_nvp_t *nvp_last = 0xffffff02dfa305a8)
> 0xffffff02dfa305a8::print -at i_nvp_t
ffffff02dfa305a8 i_nvp_t {
ffffff02dfa305a8 union _nvi_un = {
ffffff02dfa305a8 uint64_t _nvi_align = 0
ffffff02dfa305a8 struct _nvi = {
ffffff02dfa305a8 i_nvp_t *_nvi_next = 0
ffffff02dfa305b0 i_nvp_t *_nvi_prev = 0xffffff02e3e72780
}
}
ffffff02dfa305b8 nvpair_t nvi_nvp = {
ffffff02dfa305b8 int32_t nvp_size = 0x40
ffffff02dfa305bc int16_t nvp_name_sz = 0x12
ffffff02dfa305be int16_t nvp_reserve = 0
ffffff02dfa305c0 int32_t nvp_value_elem = 0x1
ffffff02dfa305c4 data_type_t nvp_type = 0t19 (DATA_TYPE_NVLIST)
}
}
> ffffff02dfa305c8::print -at char
ffffff02dfa305c8 char 'f'
> ffffff02dfa305c9::print -at char
ffffff02dfa305c9 char 'e'
> ffffff02dfa305ca::print -at char
ffffff02dfa305ca char 'a'
> ffffff02dfa305cb::print -at char
ffffff02dfa305cb char 't'
> ffffff02dfa305cc::print -at char
ffffff02dfa305cc char 'u'
> ffffff02dfa305cd::print -at char
ffffff02dfa305cd char 'r'
> ffffff02dfa305ce::print -at char
ffffff02dfa305ce char 'e'
> ffffff02dfa305cf::print -at char
ffffff02dfa305cf char 's'
> ffffff02dfa305d0::print -at char
ffffff02dfa305d0 char '_'
> ffffff02dfa305d1::print -at char
ffffff02dfa305d1 char 'f'
> ffffff02dfa305d2::print -at char
ffffff02dfa305d2 char 'o'
> ffffff02dfa305d3::print -at char
ffffff02dfa305d3 char 'r'
> ffffff02dfa305d4::print -at char
ffffff02dfa305d4 char '_'
> ffffff02dfa305d5::print -at char
ffffff02dfa305d5 char 'r'
> ffffff02dfa305d6::print -at char
ffffff02dfa305d6 char 'e'
> ffffff02dfa305d7::print -at char
ffffff02dfa305d7 char 'a'
> ffffff02dfa305d8::print -at char
ffffff02dfa305d8 char 'd'
> ffffff02dfa305d9::print -at char
ffffff02dfa305d9 char '\0'
==> 属性名称:features_for_read
//计算出属性值存放的地址为: ffffff02dfa305e0 -- DATA_TYPE_NVLIST类型
> ffffff02dfa305e0::print -at nvlist_t
ffffff02dfa305e0 nvlist_t {
ffffff02dfa305e0 int32_t nvl_version = 0
ffffff02dfa305e4 uint32_t nvl_nvflag = 0x1
ffffff02dfa305e8 uint64_t nvl_priv = 0xffffff02e1b0cb08
ffffff02dfa305f0 uint32_t nvl_flag = 0
ffffff02dfa305f4 int32_t nvl_pad = 0
}
> 0xffffff02e1b0cb08::print -at nvpriv_t
ffffff02e1b0cb08 nvpriv_t {
ffffff02e1b0cb08 i_nvp_t *nvp_list = 0
ffffff02e1b0cb10 i_nvp_t *nvp_last = 0
ffffff02e1b0cb18 i_nvp_t *nvp_curr = 0
ffffff02e1b0cb20 nv_alloc_t *nvp_nva = nv_alloc_sleep_def
ffffff02e1b0cb28 uint32_t nvp_stat = 0x1
}
//源代码中如何从 nvlist_t 获取 nvpair_t (name/value) 对
usr/src/lib/smbsrv/libmlsvc/common/dfs.c 1332 rc = nvlist_lookup_string(nvl, "comment", &cmnt); 1333 rc |= nvlist_lookup_string(nvl, "guid", &guid); 1423 int 1424 nvlist_lookup_string(nvlist_t *nvl, const char *name, char **val) 1425 { 1426 return (nvlist_lookup_common(nvl, name, DATA_TYPE_STRING, NULL, val)); 1427 } 1323 static int 1324 nvlist_lookup_common(nvlist_t *nvl, const char *name, data_type_t type, 1325 uint_t *nelem, void *data) 1326 { 1327 nvpriv_t *priv; 1328 nvpair_t *nvp; 1329 i_nvp_t *curr; 1330 1331 if (name == NULL || nvl == NULL || 1332 (priv = (nvpriv_t *)(uintptr_t)nvl->nvl_priv) == NULL) 1333 return (EINVAL); 1334 1335 if (!(nvl->nvl_nvflag & (NV_UNIQUE_NAME | NV_UNIQUE_NAME_TYPE))) 1336 return (ENOTSUP); 1337 1338 for (curr = priv->nvp_list; curr != NULL; curr = curr->nvi_next) { 1339 nvp = &curr->nvi_nvp; 1340 1341 if (strcmp(name, NVP_NAME(nvp)) == 0 && NVP_TYPE(nvp) == type) //116 #define NVP_NAME(nvp) ((char *)(nvp) + sizeof (nvpair_t)) 1342 return (nvpair_value_common(nvp, type, nelem, data)); 1343 } 1344 1345 return (ENOENT); 1346 } 1249 static int 1250 nvpair_value_common(nvpair_t *nvp, data_type_t type, uint_t *nelem, void *data) 1251 { 1252 if (nvp == NULL || nvpair_type(nvp) != type) 1253 return (EINVAL); 1254 1255 /* 1256 * For non-array types, we copy the data. 1257 * For array types (including string), we set a pointer. 1258 */ 1259 switch (type) { 1260 case DATA_TYPE_BOOLEAN: 1261 if (nelem != NULL) 1262 *nelem = 0; 1263 break; 1264 1265 case DATA_TYPE_BOOLEAN_VALUE: 1266 case DATA_TYPE_BYTE: 1267 case DATA_TYPE_INT8: 1268 case DATA_TYPE_UINT8: 1269 case DATA_TYPE_INT16: 1270 case DATA_TYPE_UINT16: 1271 case DATA_TYPE_INT32: 1272 case DATA_TYPE_UINT32: 1273 case DATA_TYPE_INT64: 1274 case DATA_TYPE_UINT64: 1275 case DATA_TYPE_HRTIME: 1276 #if !defined(_KERNEL) 1277 case DATA_TYPE_DOUBLE: 1278 #endif 1279 if (data == NULL) 1280 return (EINVAL); 1281 bcopy(NVP_VALUE(nvp), data, 1282 (size_t)i_get_value_size(type, NULL, 1)); /* 112 #define NV_ALIGN(x) (((ulong_t)(x) + 7ul) & ~7ul) 119 #define NVP_VALUE(nvp) ((char *)(nvp) + NV_ALIGN(sizeof (nvpair_t) \ 120 + (nvp)->nvp_name_sz)) */ 1283 if (nelem != NULL) 1284 *nelem = 1; 1285 break; 1286 1287 case DATA_TYPE_NVLIST: 1288 case DATA_TYPE_STRING: 1289 if (data == NULL) 1290 return (EINVAL); 1291 *(void **)data = (void *)NVP_VALUE(nvp); 1292 if (nelem != NULL) 1293 *nelem = 1; 1294 break; 1295 1296 case DATA_TYPE_BOOLEAN_ARRAY: 1297 case DATA_TYPE_BYTE_ARRAY: 1298 case DATA_TYPE_INT8_ARRAY: 1299 case DATA_TYPE_UINT8_ARRAY: 1300 case DATA_TYPE_INT16_ARRAY: 1301 case DATA_TYPE_UINT16_ARRAY: 1302 case DATA_TYPE_INT32_ARRAY: 1303 case DATA_TYPE_UINT32_ARRAY: 1304 case DATA_TYPE_INT64_ARRAY: 1305 case DATA_TYPE_UINT64_ARRAY: 1306 case DATA_TYPE_STRING_ARRAY: 1307 case DATA_TYPE_NVLIST_ARRAY: 1308 if (nelem == NULL || data == NULL) 1309 return (EINVAL); 1310 if ((*nelem = NVP_NELEM(nvp)) != 0) 1311 *(void **)data = (void *)NVP_VALUE(nvp); 1312 else 1313 *(void **)data = NULL; 1314 break; 1315 1316 default: 1317 return (ENOTSUP); 1318 } 1319 1320 return (0); 1321 }
//相关数据结构如下 88 /* nvlist header */ 89 typedef struct nvlist { 90 int32_t nvl_version; 91 uint32_t nvl_nvflag; /* persistent flags */ 92 uint64_t nvl_priv; /* ptr to private data if not packed */ 93 uint32_t nvl_flag; 94 int32_t nvl_pad; /* currently not used, for alignment */ 95 } nvlist_t; 61 typedef struct { 62 i_nvp_t *nvp_list; /* linked list of nvpairs */ 63 i_nvp_t *nvp_last; /* last nvpair */ 64 i_nvp_t *nvp_curr; /* current walker nvpair */ 65 nv_alloc_t *nvp_nva; /* pluggable allocator */ 66 uint32_t nvp_stat; /* internal state */ 67 } nvpriv_t; 43 /* 44 * implementation linked list for pre-packed data 45 */ 46 typedef struct i_nvp i_nvp_t; 47 48 struct i_nvp { 49 union { 50 uint64_t _nvi_align; /* ensure alignment */ 51 struct { 52 i_nvp_t *_nvi_next; /* pointer to next nvpair */ 53 i_nvp_t *_nvi_prev; /* pointer to prev nvpair */ 54 } _nvi; 55 } _nvi_un; 56 nvpair_t nvi_nvp; /* nvpair */ 57 }; 77 typedef struct nvpair { 78 int32_t nvp_size; /* size of this nvpair */ 79 int16_t nvp_name_sz; /* length of name string */ 80 int16_t nvp_reserve; /* not used */ 81 int32_t nvp_value_elem; /* number of elements for array types */ 82 data_type_t nvp_type; /* type of value */ 83 /* name string */ 84 /* aligned ptr array for string arrays */ 85 /* aligned array of data for value */ 86 } nvpair_t;