diff options
author | Michael Brown | 2008-03-21 00:15:48 +0100 |
---|---|---|
committer | Michael Brown | 2008-03-21 00:15:48 +0100 |
commit | cf033046206aede5064c798bfa887fbb888b9217 (patch) | |
tree | 9836e9742cda7fd923a75eeb100b467817bd31b6 /src/core/settings.c | |
parent | [Settings] Add per-netdevice settings block (diff) | |
download | ipxe-cf033046206aede5064c798bfa887fbb888b9217.tar.gz ipxe-cf033046206aede5064c798bfa887fbb888b9217.tar.xz ipxe-cf033046206aede5064c798bfa887fbb888b9217.zip |
[Settings] Introduce settings applicators.
Convert DHCP option applicators in dns.c and iscsi.c to settings
applicators.
Kill off DHCP option applicators.
Diffstat (limited to 'src/core/settings.c')
-rw-r--r-- | src/core/settings.c | 111 |
1 files changed, 102 insertions, 9 deletions
diff --git a/src/core/settings.c b/src/core/settings.c index 49a7410d..458ba111 100644 --- a/src/core/settings.c +++ b/src/core/settings.c @@ -37,15 +37,21 @@ /** Registered setting types */ static struct setting_type setting_types[0] -__table_start ( struct setting_type, setting_types ); + __table_start ( struct setting_type, setting_types ); static struct setting_type setting_types_end[0] -__table_end ( struct setting_type, setting_types ); + __table_end ( struct setting_type, setting_types ); /** Registered named settings */ static struct named_setting named_settings[0] -__table_start ( struct named_setting, named_settings ); + __table_start ( struct named_setting, named_settings ); static struct named_setting named_settings_end[0] -__table_end ( struct named_setting, named_settings ); + __table_end ( struct named_setting, named_settings ); + +/** Registered settings applicators */ +static struct settings_applicator settings_applicators[0] + __table_start ( struct settings_applicator, settings_applicators ); +static struct settings_applicator settings_applicators_end[0] + __table_end ( struct settings_applicator, settings_applicators ); /** * Obtain printable version of a settings tag number @@ -94,10 +100,6 @@ int simple_settings_fetch ( struct settings *settings, unsigned int tag, return ( len ? len : 8 ); } -// Dummy routine just for testing -static void apply_settings ( void ) { -} - /** Simple settings operations */ struct settings_operations simple_settings_operations = { .store = simple_settings_store, @@ -114,6 +116,66 @@ struct settings settings_root = { }; /** + * Apply all settings + * + * @ret rc Return status code + */ +static int apply_settings ( void ) { + struct settings_applicator *applicator; + int rc; + + /* Call all settings applicators */ + for ( applicator = settings_applicators ; + applicator < settings_applicators_end ; applicator++ ) { + if ( ( rc = applicator->apply() ) != 0 ) { + DBG ( "Could not apply settings using applicator " + "%p: %s\n", applicator, strerror ( rc ) ); + return rc; + } + } + + return 0; +} + +/** + * Reprioritise settings + * + * @v settings Settings block + * + * Reorders the settings block amongst its siblings according to its + * priority. + */ +static void reprioritise_settings ( struct settings *settings ) { + struct settings *parent = settings->parent; + long priority; + struct settings *tmp; + long tmp_priority; + + /* Stop when we reach the top of the tree */ + if ( ! parent ) + return; + + /* Read priority, if present */ + priority = 0; + fetch_int_setting ( settings, DHCP_EB_PRIORITY, &priority ); + + /* Remove from siblings list */ + list_del ( &settings->siblings ); + + /* Reinsert after any existing blocks which have a higher priority */ + list_for_each_entry ( tmp, &parent->children, siblings ) { + tmp_priority = 0; + fetch_int_setting ( tmp, DHCP_EB_PRIORITY, &tmp_priority ); + if ( priority > tmp_priority ) + break; + } + list_add_tail ( &settings->siblings, &tmp->siblings ); + + /* Recurse up the tree */ + reprioritise_settings ( parent ); +} + +/** * Register settings block * * @v settings Settings block @@ -134,6 +196,9 @@ int register_settings ( struct settings *settings, struct settings *parent ) { list_add_tail ( &settings->siblings, &parent->children ); DBGC ( settings, "Settings %p registered\n", settings ); + /* Fix up settings priority */ + reprioritise_settings ( settings ); + /* Apply potentially-updated settings */ apply_settings(); @@ -207,6 +272,34 @@ struct settings * find_settings ( const char *name ) { */ /** + * Store value of setting + * + * @v settings Settings block + * @v tag Setting tag number + * @v data Setting data, or NULL to clear setting + * @v len Length of setting data + * @ret rc Return status code + */ +int store_setting ( struct settings *settings, unsigned int tag, + const void *data, size_t len ) { + int rc; + + /* Store setting */ + if ( ( rc = settings->op->store ( settings, tag, data, len ) ) != 0 ) + return rc; + + /* Reprioritise settings if necessary */ + if ( tag == DHCP_EB_PRIORITY ) + reprioritise_settings ( settings ); + + /* Apply potentially-updated setting */ + if ( ( rc = apply_settings() ) != 0 ) + return rc; + + return 0; +} + +/** * Fetch value of setting * * @v settings Settings block, or NULL to search all blocks @@ -288,7 +381,7 @@ int fetch_ipv4_setting ( struct settings *settings, unsigned int tag, len = fetch_setting ( settings, tag, inp, sizeof ( *inp ) ); if ( len < 0 ) return len; - if ( len != sizeof ( *inp ) ) + if ( len < ( int ) sizeof ( *inp ) ) return -ERANGE; return len; } |