server/fs_log: merge labels using 'label_prefix'

Policies are no longer partially matched against 'label' attributes.
New test at run/fs_log.

Issue #1766
This commit is contained in:
Emery Hemingway 2015-11-27 16:13:14 +01:00 committed by Christian Helmuth
parent 627ecc44d2
commit d0ebdfba4b
3 changed files with 107 additions and 58 deletions

72
repos/os/run/fs_log.run Normal file
View File

@ -0,0 +1,72 @@
#
# Test logging to file system
#
build {
core init drivers/timer
server/vfs server/fs_log
test/bomb
}
set timeout 240
set rounds 20
set config {
<config prio_levels="2">
<parent-provides>
<service name="CAP"/>
<service name="CPU"/>
<service name="LOG"/>
<service name="PD"/>
<service name="RAM"/>
<service name="RM"/>
<service name="ROM"/>
<service name="SIGNAL"/>
</parent-provides>
<default-route>
<any-service> <parent/> <any-child/> </any-service>
</default-route>
<start name="timer">
<resource name="CPU" quantum="10"/>
<resource name="RAM" quantum="1M"/>
<provides><service name="Timer"/></provides>
</start>
<start name="vfs">
<resource name="RAM" quantum="2M"/>
<provides><service name="File_system"/></provides>
<config>
<vfs>
<log name="bomb-master.log"/>
<dir name="bomb-master"> <log name="bomb_g5.log"/> </dir>
</vfs>
<policy label="fs_log" writeable="yes"/>
</config>
</start>
<start name="fs_log">
<resource name="RAM" quantum="2M"/>
<provides><service name="LOG"/></provides>
<config>
<policy label="bomb-master"/>
<policy label_prefix="bomb-master" merge="true"/>
</config>
</start>
<start name="bomb-master" priority="-1">
<binary name="bomb"/>
<resource name="CPU" quantum="90"/>
<resource name="RAM" quantum="2G"/>
<route>
<any-service> <any-child/> <parent/> </any-service>
</route>
<config rounds="1" generations="1" sleep="500"/>
</start>
</config>}
create_boot_directory
install_config $config
build_boot_image "core init ld.lib.so bomb timer vfs fs_log"
append qemu_args " -nographic"
run_genode_until "Done\. Going to sleep\." $timeout

View File

@ -15,8 +15,8 @@ trailing "->", the log filename takes the name of the next label element.
! <provides><service name="LOG"/></provides>
! <config>
! <policy label="nic_drv" truncate="no"/>
! <policy label="cli_monitor -> " merge="yes"/>
! <policy label="" truncate="yes"/>
! <policy label_prefix="cli_monitor -> " merge="yes"/>
! <policy truncate="yes"/>
! </config>
! </start>

View File

@ -12,6 +12,7 @@
*/
/* Genode includes */
#include <os/path.h>
#include <file_system_session/connection.h>
#include <file_system/util.h>
#include <root/component.h>
@ -37,6 +38,8 @@ namespace Fs_log {
TX_BUF_SIZE = BLOCK_SIZE * (QUEUE_SIZE*2 + 1)
};
typedef Genode::Path<File_system::MAX_PATH_LEN> Path;
}
class Fs_log::Root_component :
@ -71,61 +74,38 @@ class Fs_log::Root_component :
bool truncate = false;
Session_label session_label(args);
char const *label_str = session_label.string();
char const *label_prefix = nullptr;
char const *label_prefix = "";
strncpy(dir_path+1, label_str, MAX_PATH_LEN-1);
try {
Session_policy policy(session_label);
try {
truncate = policy.attribute("truncate").has_value("yes");
} catch (Xml_node::Nonexistent_attribute) { }
truncate = policy.attribute_value("truncate", truncate);
if (policy.attribute_value("merge", false)
&& policy.has_attribute("label_prefix")) {
bool merge = false;
try {
merge = policy.attribute("merge").has_value("yes");
} catch (Xml_node::Nonexistent_attribute) { }
if (merge) {
/*
* Use the policy label that was matched rather than
* full session label for the path of the log file.
*/
policy.attribute("label").value(dir_path+1, sizeof(dir_path)-1);
if (!dir_path[1]) {
PERR("cannot merge an empty policy label");
throw Root::Unavailable();
}
/*
* If the policy has a trailing '->', move first element
* from the log prefix to the end of the log path.
* split the label between what will be the log file
* and what will be prepended to messages in the file
*/
size_t label_len = strlen(dir_path);
label_prefix = label_str+(label_len-1);
size_t offset = policy.attribute("label_prefix").value_size();
for (size_t i = offset; i < session_label.length()-4; ++i) {
if (strcmp(label_str+i, " -> ", 4))
continue;
if ((strcmp((dir_path+label_len)-3, " ->", 4) == 0) ||
(strcmp((dir_path+label_len)-4, " -> ", 5) == 0)) {
for (size_t i = 0;; ++i) {
if (label_prefix[i] == '\0') {
strncpy(dir_path+1, label_str, MAX_PATH_LEN-1);
label_prefix = nullptr;
break;
}
if (strcmp(label_prefix+i, " -> ", 4))
continue;
strncpy(dir_path+label_len, label_prefix, i+1);
label_prefix += i+4;
break;
}
dir_path[i+1] = '\0';
label_prefix = label_str+i+4;
break;
}
}
} catch (Session_policy::No_policy_defined) { }
} else
strncpy(dir_path+1, label_str, MAX_PATH_LEN-1);
} catch (Session_policy::No_policy_defined) {
strncpy(dir_path+1, label_str, MAX_PATH_LEN-1);
}
{
/* Parse out a directory and file name. */
@ -171,6 +151,7 @@ class Fs_log::Root_component :
offset = _fs.status(handle).size;
} catch (File_system::Lookup_failed) {
PDBG("create");
handle = _fs.file(dir_handle, file_name,
File_system::WRITE_ONLY, true);
}
@ -181,33 +162,29 @@ class Fs_log::Root_component :
_log_files.insert(file);
} catch (Permission_denied) {
PERR("%s:%s: permission denied", dir_path, file_name);
} catch (Name_too_long) {
PERR("%s:%s: name too long", dir_path, file_name);
PERR("%s: permission denied", Path(file_name, dir_path).base());
} catch (No_space) {
PERR("%s:%s: no space", dir_path, file_name);
PERR("file system out of space");
} catch (Out_of_node_handles) {
PERR("%s:%s: out of node handles", dir_path, file_name);
PERR("too many open file handles");
} catch (Invalid_name) {
PERR("%s:%s: invalid_name", dir_path, file_name);
PERR("%s: invalid path", Path(file_name, dir_path).base());
} catch (Size_limit_reached) {
PERR("%s:%s: size limit reached", dir_path, file_name);
} catch (Name_too_long) {
PERR("%s: name too long", Path(file_name, dir_path).base());
} catch (...) {
PERR("%s:%s: unknown error", dir_path, file_name);
PERR("cannot open log file %s", Path(file_name, dir_path).base());
throw;
}
if (!file) {
PERR("file was null");
throw Root::Unavailable();
}
if (label_prefix && *label_prefix)
if (!file)
throw Root::Unavailable();
if (*label_prefix)
return new (md_alloc()) Labeled_session_component(label_prefix, *file);
return new (md_alloc()) Unlabeled_session_component(*file);
}