Переглянути джерело

[settings] Make "netX" settings block function as a symbolic link

Add a facility for settings blocks to act as symbolic links to other
settings blocks, and reimplement the "netX" virtual settings block
using this facility.

The primary advantage of this approach is that unscoped settings such
as ${mac} and ${filename} will now reflect the settings obtained from
the most recently opened network device: in most cases, this will mean
the settings obtained from the most recent DHCP attempt.  This should
improve conformance to the principle of least astonishment.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
tags/v1.20.1
Michael Brown 11 роки тому
джерело
коміт
66ea458125

+ 50
- 23
src/core/settings.c Переглянути файл

@@ -271,6 +271,9 @@ struct settings * find_child_settings ( struct settings *parent,
271 271
 					const char *name ) {
272 272
 	struct settings *settings;
273 273
 
274
+	/* Find target parent settings block */
275
+	parent = settings_target ( parent );
276
+
274 277
 	/* Treat empty name as meaning "this block" */
275 278
 	if ( ! *name )
276 279
 		return parent;
@@ -278,7 +281,7 @@ struct settings * find_child_settings ( struct settings *parent,
278 281
 	/* Look for child with matching name */
279 282
 	list_for_each_entry ( settings, &parent->children, siblings ) {
280 283
 		if ( strcmp ( settings->name, name ) == 0 )
281
-			return settings;
284
+			return settings_target ( settings );
282 285
 	}
283 286
 
284 287
 	return NULL;
@@ -299,6 +302,9 @@ static struct settings * autovivify_child_settings ( struct settings *parent,
299 302
 	} *new_child;
300 303
 	struct settings *settings;
301 304
 
305
+	/* Find target parent settings block */
306
+	parent = settings_target ( parent );
307
+
302 308
 	/* Return existing settings, if existent */
303 309
 	if ( ( settings = find_child_settings ( parent, name ) ) != NULL )
304 310
 		return settings;
@@ -330,6 +336,10 @@ const char * settings_name ( struct settings *settings ) {
330 336
 	static char buf[16];
331 337
 	char tmp[ sizeof ( buf ) ];
332 338
 
339
+	/* Find target settings block */
340
+	settings = settings_target ( settings );
341
+
342
+	/* Construct name */
333 343
 	for ( buf[2] = buf[0] = 0 ; settings ; settings = settings->parent ) {
334 344
 		memcpy ( tmp, buf, sizeof ( tmp ) );
335 345
 		snprintf ( buf, sizeof ( buf ), ".%s%s", settings->name, tmp );
@@ -359,20 +369,11 @@ parse_settings_name ( const char *name,
359 369
 
360 370
 	/* Parse each name component in turn */
361 371
 	while ( remainder ) {
362
-		struct net_device *netdev;
363
-
364 372
 		subname = remainder;
365 373
 		remainder = strchr ( subname, '.' );
366 374
 		if ( remainder )
367 375
 			*(remainder++) = '\0';
368
-
369
-		/* Special case "netX" root settings block */
370
-		if ( ( subname == name_copy ) && ! strcmp ( subname, "netX" ) &&
371
-		     ( ( netdev = last_opened_netdev() ) != NULL ) )
372
-			settings = get_child ( settings, netdev->name );
373
-		else
374
-			settings = get_child ( settings, subname );
375
-
376
+		settings = get_child ( settings, subname );
376 377
 		if ( ! settings )
377 378
 			break;
378 379
 	}
@@ -460,10 +461,11 @@ int register_settings ( struct settings *settings, struct settings *parent,
460 461
 			const char *name ) {
461 462
 	struct settings *old_settings;
462 463
 
463
-	/* NULL parent => add to settings root */
464
+	/* Sanity check */
464 465
 	assert ( settings != NULL );
465
-	if ( parent == NULL )
466
-		parent = &settings_root;
466
+
467
+	/* Find target parent settings block */
468
+	parent = settings_target ( parent );
467 469
 
468 470
 	/* Apply settings block name */
469 471
 	settings->name = name;
@@ -523,6 +525,26 @@ void unregister_settings ( struct settings *settings ) {
523 525
  ******************************************************************************
524 526
  */
525 527
 
528
+/**
529
+ * Redirect to target settings block
530
+ *
531
+ * @v settings		Settings block, or NULL
532
+ * @ret settings	Underlying settings block
533
+ */
534
+struct settings * settings_target ( struct settings *settings ) {
535
+
536
+	/* NULL settings implies the global settings root */
537
+	if ( ! settings )
538
+		settings = &settings_root;
539
+
540
+	/* Redirect to underlying settings block, if applicable */
541
+	if ( settings->op->redirect )
542
+		return settings->op->redirect ( settings );
543
+
544
+	/* Otherwise, return this settings block */
545
+	return settings;
546
+}
547
+
526 548
 /**
527 549
  * Check applicability of setting
528 550
  *
@@ -532,6 +554,10 @@ void unregister_settings ( struct settings *settings ) {
532 554
  */
533 555
 int setting_applies ( struct settings *settings, struct setting *setting ) {
534 556
 
557
+	/* Find target settings block */
558
+	settings = settings_target ( settings );
559
+
560
+	/* Check applicability of setting */
535 561
 	return ( settings->op->applies ?
536 562
 		 settings->op->applies ( settings, setting ) : 1 );
537 563
 }
@@ -549,9 +575,8 @@ int store_setting ( struct settings *settings, struct setting *setting,
549 575
 		    const void *data, size_t len ) {
550 576
 	int rc;
551 577
 
552
-	/* NULL settings implies storing into the global settings root */
553
-	if ( ! settings )
554
-		settings = &settings_root;
578
+	/* Find target settings block */
579
+	settings = settings_target ( settings );
555 580
 
556 581
 	/* Fail if tag does not apply to this settings block */
557 582
 	if ( ! setting_applies ( settings, setting ) )
@@ -609,9 +634,8 @@ static int fetch_setting_and_origin ( struct settings *settings,
609 634
 	if ( origin )
610 635
 		*origin = NULL;
611 636
 
612
-	/* NULL settings implies starting at the global settings root */
613
-	if ( ! settings )
614
-		settings = &settings_root;
637
+	/* Find target settings block */
638
+	settings = settings_target ( settings );
615 639
 
616 640
 	/* Sanity check */
617 641
 	if ( ! settings->op->fetch )
@@ -971,6 +995,11 @@ int fetch_uuid_setting ( struct settings *settings, struct setting *setting,
971 995
  * @v settings		Settings block
972 996
  */
973 997
 void clear_settings ( struct settings *settings ) {
998
+
999
+	/* Find target settings block */
1000
+	settings = settings_target ( settings );
1001
+
1002
+	/* Clear settings, if applicable */
974 1003
 	if ( settings->op->clear )
975 1004
 		settings->op->clear ( settings );
976 1005
 }
@@ -1230,9 +1259,7 @@ int setting_name ( struct settings *settings, struct setting *setting,
1230 1259
 		   char *buf, size_t len ) {
1231 1260
 	const char *name;
1232 1261
 
1233
-	if ( ! settings )
1234
-		settings = &settings_root;
1235
-
1262
+	settings = settings_target ( settings );
1236 1263
 	name = settings_name ( settings );
1237 1264
 	return snprintf ( buf, len, "%s%s%s:%s", name, ( name[0] ? "/" : "" ),
1238 1265
 			  setting->name, setting->type->name );

+ 1
- 1
src/hci/tui/settings_ui.c Переглянути файл

@@ -441,7 +441,7 @@ static void reveal_setting_row ( struct setting_widget *widget,
441 441
 static void init_widget ( struct setting_widget *widget,
442 442
 			  struct settings *settings ) {
443 443
 
444
-	widget->settings = settings;
444
+	widget->settings = settings_target ( settings );
445 445
 	widget->num_rows = select_setting_row ( widget, 0 );
446 446
 	widget->first_visible = SETTINGS_LIST_ROWS;
447 447
 	draw_title_row ( widget );

+ 7
- 0
src/include/ipxe/settings.h Переглянути файл

@@ -77,6 +77,12 @@ struct setting {
77 77
 
78 78
 /** Settings block operations */
79 79
 struct settings_operations {
80
+	/** Redirect to underlying settings block (if applicable)
81
+	 *
82
+	 * @v settings		Settings block
83
+	 * @ret settings	Underlying settings block
84
+	 */
85
+	struct settings * ( * redirect ) ( struct settings *settings );
80 86
 	/** Check applicability of setting
81 87
 	 *
82 88
 	 * @v settings		Settings block
@@ -248,6 +254,7 @@ extern int register_settings ( struct settings *settings,
248 254
 			       struct settings *parent, const char *name );
249 255
 extern void unregister_settings ( struct settings *settings );
250 256
 
257
+extern struct settings * settings_target ( struct settings *settings );
251 258
 extern int setting_applies ( struct settings *settings,
252 259
 			     struct setting *setting );
253 260
 extern int store_setting ( struct settings *settings, struct setting *setting,

+ 49
- 0
src/net/netdev_settings.c Переглянути файл

@@ -27,6 +27,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
27 27
 #include <ipxe/settings.h>
28 28
 #include <ipxe/device.h>
29 29
 #include <ipxe/netdevice.h>
30
+#include <ipxe/init.h>
30 31
 
31 32
 /** @file
32 33
  *
@@ -295,3 +296,51 @@ struct settings_operations netdev_settings_operations = {
295 296
 	.fetch = netdev_fetch,
296 297
 	.clear = netdev_clear,
297 298
 };
299
+
300
+/**
301
+ * Redirect "netX" settings block
302
+ *
303
+ * @v settings		Settings block
304
+ * @ret settings	Underlying settings block
305
+ */
306
+static struct settings * netdev_redirect ( struct settings *settings ) {
307
+	struct net_device *netdev;
308
+
309
+	/* Redirect to most recently opened network device */
310
+	netdev = last_opened_netdev();
311
+	if ( netdev ) {
312
+		return netdev_settings ( netdev );
313
+	} else {
314
+		return settings;
315
+	}
316
+}
317
+
318
+/** "netX" settings operations */
319
+static struct settings_operations netdev_redirect_settings_operations = {
320
+	.redirect = netdev_redirect,
321
+};
322
+
323
+/** "netX" settings */
324
+static struct settings netdev_redirect_settings = {
325
+	.refcnt = NULL,
326
+	.siblings = LIST_HEAD_INIT ( netdev_redirect_settings.siblings ),
327
+	.children = LIST_HEAD_INIT ( netdev_redirect_settings.children ),
328
+	.op = &netdev_redirect_settings_operations,
329
+};
330
+
331
+/** Initialise "netX" settings */
332
+static void netdev_redirect_settings_init ( void ) {
333
+	int rc;
334
+
335
+	if ( ( rc = register_settings ( &netdev_redirect_settings, NULL,
336
+					"netX" ) ) != 0 ) {
337
+		DBG ( "Could not register netX settings: %s\n",
338
+		      strerror ( rc ) );
339
+		return;
340
+	}
341
+}
342
+
343
+/** "netX" settings initialiser */
344
+struct init_fn netdev_redirect_settings_init_fn __init_fn ( INIT_LATE ) = {
345
+	.initialise = netdev_redirect_settings_init,
346
+};

Завантаження…
Відмінити
Зберегти