Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

bootconfig: Support mixing a value and subkeys under a key

Support mixing a value and subkeys under a key. Since kernel cmdline
options will support "aaa.bbb=value1 aaa.bbb.ccc=value2", it is
better that the bootconfig supports such configuration too.

Note that this does not change syntax itself but just accepts
mixed value and subkeys e.g.

key = value1
key.subkey = value2

But this is not accepted;

key {
value1
subkey = value2
}

That will make value1 as a subkey.

Also, the order of the value node under a key is fixed. If there
are a value and subkeys, the value is always the first child node
of the key. Thus if user specifies subkeys first, e.g.

key.subkey = value1
key = value2

In the program (and /proc/bootconfig), it will be shown as below

key = value2
key.subkey = value1

Link: https://lkml.kernel.org/r/162262194685.264090.7738574774030567419.stgit@devnote2

Signed-off-by: Masami Hiramatsu <mhiramat@kernel.org>
Signed-off-by: Steven Rostedt (VMware) <rostedt@goodmis.org>

authored by

Masami Hiramatsu and committed by
Steven Rostedt (VMware)
e5efaeb8 ca24306d

+115 -29
+32
include/linux/bootconfig.h
··· 80 80 * 81 81 * Test the @node is a leaf key node which is a key node and has a value node 82 82 * or no child. Returns true if it is a leaf node, or false if not. 83 + * Note that the leaf node can have subkey nodes in addition to the 84 + * value node. 83 85 */ 84 86 static inline __init bool xbc_node_is_leaf(struct xbc_node *node) 85 87 { ··· 132 130 } 133 131 134 132 /** 133 + * xbc_node_get_subkey() - Return the first subkey node if exists 134 + * @node: Parent node 135 + * 136 + * Return the first subkey node of the @node. If the @node has no child 137 + * or only value node, this will return NULL. 138 + */ 139 + static inline struct xbc_node * __init xbc_node_get_subkey(struct xbc_node *node) 140 + { 141 + struct xbc_node *child = xbc_node_get_child(node); 142 + 143 + if (child && xbc_node_is_value(child)) 144 + return xbc_node_get_next(child); 145 + else 146 + return child; 147 + } 148 + 149 + /** 135 150 * xbc_array_for_each_value() - Iterate value nodes on an array 136 151 * @anode: An XBC arraied value node 137 152 * @value: A value ··· 168 149 * @child: Iterated XBC node. 169 150 * 170 151 * Iterate child nodes of @parent. Each child nodes are stored to @child. 152 + * The @child can be mixture of a value node and subkey nodes. 171 153 */ 172 154 #define xbc_node_for_each_child(parent, child) \ 173 155 for (child = xbc_node_get_child(parent); child != NULL ; \ 156 + child = xbc_node_get_next(child)) 157 + 158 + /** 159 + * xbc_node_for_each_subkey() - Iterate child subkey nodes 160 + * @parent: An XBC node. 161 + * @child: Iterated XBC node. 162 + * 163 + * Iterate subkey nodes of @parent. Each child nodes are stored to @child. 164 + * The @child is only the subkey node. 165 + */ 166 + #define xbc_node_for_each_subkey(parent, child) \ 167 + for (child = xbc_node_get_subkey(parent); child != NULL ; \ 174 168 child = xbc_node_get_next(child)) 175 169 176 170 /**
+46 -21
lib/bootconfig.c
··· 156 156 struct xbc_node *node; 157 157 158 158 if (parent) 159 - node = xbc_node_get_child(parent); 159 + node = xbc_node_get_subkey(parent); 160 160 else 161 161 node = xbc_root_node(); 162 162 ··· 164 164 if (!xbc_node_match_prefix(node, &key)) 165 165 node = xbc_node_get_next(node); 166 166 else if (*key != '\0') 167 - node = xbc_node_get_child(node); 167 + node = xbc_node_get_subkey(node); 168 168 else 169 169 break; 170 170 } ··· 274 274 struct xbc_node * __init xbc_node_find_next_leaf(struct xbc_node *root, 275 275 struct xbc_node *node) 276 276 { 277 + struct xbc_node *next; 278 + 277 279 if (unlikely(!xbc_data)) 278 280 return NULL; 279 281 ··· 284 282 if (!node) 285 283 node = xbc_nodes; 286 284 } else { 285 + /* Leaf node may have a subkey */ 286 + next = xbc_node_get_subkey(node); 287 + if (next) { 288 + node = next; 289 + goto found; 290 + } 291 + 287 292 if (node == root) /* @root was a leaf, no child node. */ 288 293 return NULL; 289 294 ··· 305 296 node = xbc_node_get_next(node); 306 297 } 307 298 299 + found: 308 300 while (node && !xbc_node_is_leaf(node)) 309 301 node = xbc_node_get_child(node); 310 302 ··· 385 375 return node; 386 376 } 387 377 388 - static struct xbc_node * __init xbc_add_sibling(char *data, u32 flag) 378 + static struct xbc_node * __init __xbc_add_sibling(char *data, u32 flag, bool head) 389 379 { 390 380 struct xbc_node *sib, *node = xbc_add_node(data, flag); 391 381 392 382 if (node) { 393 383 if (!last_parent) { 384 + /* Ignore @head in this case */ 394 385 node->parent = XBC_NODE_MAX; 395 386 sib = xbc_last_sibling(xbc_nodes); 396 387 sib->next = xbc_node_index(node); 397 388 } else { 398 389 node->parent = xbc_node_index(last_parent); 399 - if (!last_parent->child) { 390 + if (!last_parent->child || head) { 391 + node->next = last_parent->child; 400 392 last_parent->child = xbc_node_index(node); 401 393 } else { 402 394 sib = xbc_node_get_child(last_parent); ··· 410 398 xbc_parse_error("Too many nodes", data); 411 399 412 400 return node; 401 + } 402 + 403 + static inline struct xbc_node * __init xbc_add_sibling(char *data, u32 flag) 404 + { 405 + return __xbc_add_sibling(data, flag, false); 406 + } 407 + 408 + static inline struct xbc_node * __init xbc_add_head_sibling(char *data, u32 flag) 409 + { 410 + return __xbc_add_sibling(data, flag, true); 413 411 } 414 412 415 413 static inline __init struct xbc_node *xbc_add_child(char *data, u32 flag) ··· 590 568 node = find_match_node(xbc_nodes, k); 591 569 else { 592 570 child = xbc_node_get_child(last_parent); 571 + /* Since the value node is the first child, skip it. */ 593 572 if (child && xbc_node_is_value(child)) 594 - return xbc_parse_error("Subkey is mixed with value", k); 573 + child = xbc_node_get_next(child); 595 574 node = find_match_node(child, k); 596 575 } 597 576 ··· 635 612 if (ret) 636 613 return ret; 637 614 638 - child = xbc_node_get_child(last_parent); 639 - if (child) { 640 - if (xbc_node_is_key(child)) 641 - return xbc_parse_error("Value is mixed with subkey", v); 642 - else if (op == '=') 643 - return xbc_parse_error("Value is redefined", v); 644 - } 645 - 646 615 c = __xbc_parse_value(&v, &next); 647 616 if (c < 0) 648 617 return c; 649 618 650 - if (op == ':' && child) { 651 - xbc_init_node(child, v, XBC_VALUE); 652 - } else { 653 - if (op == '+' && child) 654 - last_parent = xbc_last_child(child); 655 - if (!xbc_add_sibling(v, XBC_VALUE)) 656 - return -ENOMEM; 657 - } 619 + child = xbc_node_get_child(last_parent); 620 + if (child && xbc_node_is_value(child)) { 621 + if (op == '=') 622 + return xbc_parse_error("Value is redefined", v); 623 + if (op == ':') { 624 + unsigned short nidx = child->next; 658 625 626 + xbc_init_node(child, v, XBC_VALUE); 627 + child->next = nidx; /* keep subkeys */ 628 + goto array; 629 + } 630 + /* op must be '+' */ 631 + last_parent = xbc_last_child(child); 632 + } 633 + /* The value node should always be the first child */ 634 + if (!xbc_add_head_sibling(v, XBC_VALUE)) 635 + return -ENOMEM; 636 + 637 + array: 659 638 if (c == ',') { /* Array */ 660 639 c = xbc_parse_array(&next); 661 640 if (c < 0)
+37 -8
tools/bootconfig/main.c
··· 35 35 36 36 static void xbc_show_compact_tree(void) 37 37 { 38 - struct xbc_node *node, *cnode; 38 + struct xbc_node *node, *cnode = NULL, *vnode; 39 39 int depth = 0, i; 40 40 41 41 node = xbc_root_node(); 42 42 while (node && xbc_node_is_key(node)) { 43 43 for (i = 0; i < depth; i++) 44 44 printf("\t"); 45 - cnode = xbc_node_get_child(node); 45 + if (!cnode) 46 + cnode = xbc_node_get_child(node); 46 47 while (cnode && xbc_node_is_key(cnode) && !cnode->next) { 48 + vnode = xbc_node_get_child(cnode); 49 + /* 50 + * If @cnode has value and subkeys, this 51 + * should show it as below. 52 + * 53 + * key(@node) { 54 + * key(@cnode) = value; 55 + * key(@cnode) { 56 + * subkeys; 57 + * } 58 + * } 59 + */ 60 + if (vnode && xbc_node_is_value(vnode) && vnode->next) 61 + break; 47 62 printf("%s.", xbc_node_get_data(node)); 48 63 node = cnode; 49 - cnode = xbc_node_get_child(node); 64 + cnode = vnode; 50 65 } 51 66 if (cnode && xbc_node_is_key(cnode)) { 52 67 printf("%s {\n", xbc_node_get_data(node)); 53 68 depth++; 54 69 node = cnode; 70 + cnode = NULL; 55 71 continue; 56 72 } else if (cnode && xbc_node_is_value(cnode)) { 57 73 printf("%s = ", xbc_node_get_data(node)); 58 74 xbc_show_value(cnode, true); 75 + /* 76 + * If @node has value and subkeys, continue 77 + * looping on subkeys with same node. 78 + */ 79 + if (cnode->next) { 80 + cnode = xbc_node_get_next(cnode); 81 + continue; 82 + } 59 83 } else { 60 84 printf("%s;\n", xbc_node_get_data(node)); 61 85 } 86 + cnode = NULL; 62 87 63 88 if (node->next) { 64 89 node = xbc_node_get_next(node); ··· 95 70 return; 96 71 if (!xbc_node_get_child(node)->next) 97 72 continue; 98 - depth--; 99 - for (i = 0; i < depth; i++) 100 - printf("\t"); 101 - printf("}\n"); 73 + if (depth) { 74 + depth--; 75 + for (i = 0; i < depth; i++) 76 + printf("\t"); 77 + printf("}\n"); 78 + } 102 79 } 103 80 node = xbc_node_get_next(node); 104 81 } ··· 113 86 const char *val; 114 87 115 88 xbc_for_each_key_value(leaf, val) { 116 - if (xbc_node_compose_key(leaf, key, XBC_KEYLEN_MAX) < 0) 89 + if (xbc_node_compose_key(leaf, key, XBC_KEYLEN_MAX) < 0) { 90 + fprintf(stderr, "Failed to compose key %d\n", ret); 117 91 break; 92 + } 118 93 printf("%s = ", key); 119 94 if (!val || val[0] == '\0') { 120 95 printf("\"\"\n");