summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--runtime/procfs.c15
-rw-r--r--tapset-procfs.cxx71
2 files changed, 52 insertions, 34 deletions
diff --git a/runtime/procfs.c b/runtime/procfs.c
index d6b75336..1d2ad837 100644
--- a/runtime/procfs.c
+++ b/runtime/procfs.c
@@ -38,6 +38,11 @@ static void _stp_close_procfs(void);
*/
static void _stp_rmdir_proc_module(void)
{
+ if (!_stp_lock_transport_dir()) {
+ errk("Unable to lock transport directory.\n");
+ return;
+ }
+
if (_stp_proc_root && _stp_proc_root->subdir == NULL) {
if (atomic_read(&_stp_proc_root->count) != LAST_ENTRY_COUNT)
_stp_warn("Removal of /proc/systemtap/%s\nis deferred until it is no longer in use.\n"
@@ -46,12 +51,7 @@ static void _stp_rmdir_proc_module(void)
_stp_proc_root = NULL;
}
- if (_stp_proc_stap) {
- if (!_stp_lock_transport_dir()) {
- errk("Unable to lock transport directory.\n");
- return;
- }
-
+ if (_stp_proc_stap && _stp_proc_stap->subdir == NULL) {
/* Important! Do not attempt removal of /proc/systemtap */
/* if in use. This will put the PDE in deleted state */
/* pending usage count dropping to 0. During this time, */
@@ -63,9 +63,8 @@ static void _stp_rmdir_proc_module(void)
remove_proc_entry("systemtap", NULL);
_stp_proc_stap = NULL;
}
-
- _stp_unlock_transport_dir();
}
+ _stp_unlock_transport_dir();
}
diff --git a/tapset-procfs.cxx b/tapset-procfs.cxx
index 63a59afb..0c33857b 100644
--- a/tapset-procfs.cxx
+++ b/tapset-procfs.cxx
@@ -103,7 +103,19 @@ void
procfs_derived_probe::join_group (systemtap_session& s)
{
if (! s.procfs_derived_probes)
- s.procfs_derived_probes = new procfs_derived_probe_group ();
+ {
+ s.procfs_derived_probes = new procfs_derived_probe_group ();
+
+ // Make sure 'struct _stp_procfs_data' is defined early.
+ embeddedcode *ec = new embeddedcode;
+ ec->tok = NULL;
+ ec->code = string("struct _stp_procfs_data {\n")
+ + string(" const char *buffer;\n")
+ + string(" off_t off;\n")
+ + string(" unsigned long count;\n")
+ + string("};\n");
+ s.embeds.push_back(ec);
+ }
s.procfs_derived_probes->enroll (this);
}
@@ -208,13 +220,15 @@ procfs_derived_probe_group::emit_module_decls (systemtap_session& s)
s.op->newline() << "static int _stp_procfs_read(char *page, char **start, off_t off, int count, int *eof, void *data) {";
s.op->newline(1) << "struct stap_procfs_probe *spp = (struct stap_procfs_probe *)data;";
- s.op->newline() << "int bytes = 0;";
- s.op->newline() << "string_t strdata = {'\\0'};";
+ s.op->newline() << "struct _stp_procfs_data pdata;";
common_probe_entryfn_prologue (s.op, "STAP_SESSION_RUNNING", "spp->read_pp");
+ s.op->newline() << "pdata.buffer = page;";
+ s.op->newline() << "pdata.off = off;";
+ s.op->newline() << "pdata.count = count;";
s.op->newline() << "if (c->data == NULL)";
- s.op->newline(1) << "c->data = &strdata;";
+ s.op->newline(1) << "c->data = &pdata;";
s.op->newline(-1) << "else {";
s.op->newline(1) << "if (unlikely (atomic_inc_return (& skipped_count) > MAXSKIPPED)) {";
@@ -225,24 +239,16 @@ procfs_derived_probe_group::emit_module_decls (systemtap_session& s)
s.op->newline() << "goto probe_epilogue;";
s.op->newline(-1) << "}";
- // call probe function (which copies data into strdata)
+ // call probe function
s.op->newline() << "(*spp->read_ph) (c);";
- // copy string data into 'page'
+ // Note that _procfs_value_set copied string data into 'page'
s.op->newline() << "c->data = NULL;";
- s.op->newline() << "bytes = strnlen(strdata, MAXSTRINGLEN - 1);";
- s.op->newline() << "if (off >= bytes)";
- s.op->newline(1) << "*eof = 1;";
- s.op->newline(-1) << "else {";
- s.op->newline(1) << "bytes -= off;";
- s.op->newline() << "if (bytes > count)";
- s.op->newline(1) << "bytes = count;";
- s.op->newline(-1) << "memcpy(page, strdata + off, bytes);";
- s.op->newline() << "*start = page;";
- s.op->newline(-1) << "}";
-
common_probe_entryfn_epilogue (s.op);
- s.op->newline() << "return bytes;";
+ s.op->newline() << "if (pdata.count == 0)";
+ s.op->newline(1) << "*eof = 1;";
+ s.op->indent(-1);
+ s.op->newline() << "return pdata.count;";
s.op->newline(-1) << "}";
}
@@ -251,16 +257,18 @@ procfs_derived_probe_group::emit_module_decls (systemtap_session& s)
s.op->newline() << "static int _stp_procfs_write(struct file *file, const char *buffer, unsigned long count, void *data) {";
s.op->newline(1) << "struct stap_procfs_probe *spp = (struct stap_procfs_probe *)data;";
- s.op->newline() << "string_t strdata = {'\\0'};";
+ s.op->newline() << "struct _stp_procfs_data pdata;";
common_probe_entryfn_prologue (s.op, "STAP_SESSION_RUNNING", "spp->write_pp");
s.op->newline() << "if (count > (MAXSTRINGLEN - 1))";
s.op->newline(1) << "count = MAXSTRINGLEN - 1;";
- s.op->newline(-1) << "_stp_copy_from_user(strdata, buffer, count);";
+ s.op->indent(-1);
+ s.op->newline() << "pdata.buffer = buffer;";
+ s.op->newline() << "pdata.count = count;";
s.op->newline() << "if (c->data == NULL)";
- s.op->newline(1) << "c->data = &strdata;";
+ s.op->newline(1) << "c->data = &pdata;";
s.op->newline(-1) << "else {";
s.op->newline(1) << "if (unlikely (atomic_inc_return (& skipped_count) > MAXSKIPPED)) {";
@@ -271,7 +279,7 @@ procfs_derived_probe_group::emit_module_decls (systemtap_session& s)
s.op->newline() << "goto probe_epilogue;";
s.op->newline(-1) << "}";
- // call probe function (which copies data out of strdata)
+ // call probe function
s.op->newline() << "(*spp->write_ph) (c);";
s.op->newline() << "c->data = NULL;";
@@ -389,11 +397,22 @@ procfs_var_expanding_visitor::visit_target_symbol (target_symbol* e)
string locvalue = "CONTEXT->data";
if (! lvalue)
- ec->code = string("strlcpy (THIS->__retvalue, ") + locvalue
- + string(", MAXSTRINGLEN); /* pure */");
+ ec->code = string("_stp_copy_from_user(THIS->__retvalue, ((struct _stp_procfs_data *)(")
+ + locvalue + string("))->buffer, ((struct _stp_procfs_data *)(") + locvalue
+ + string("))->count); /* pure */");
else
- ec->code = string("strlcpy (") + locvalue
- + string(", THIS->value, MAXSTRINGLEN);");
+ ec->code = string("int bytes = 0;\n")
+ + string(" struct _stp_procfs_data *data = (struct _stp_procfs_data *)(") + locvalue + string(");\n")
+ + string(" bytes = strnlen(THIS->value, MAXSTRINGLEN - 1);\n")
+ + string(" if (data->off >= bytes)\n")
+ + string(" bytes = 0;\n")
+ + string(" else {\n")
+ + string(" bytes -= data->off;\n")
+ + string(" if (bytes > data->count)\n")
+ + string(" bytes = data->count;\n")
+ + string(" memcpy((void *)data->buffer, THIS->value + data->off, bytes);\n")
+ + string(" }\n")
+ + string(" data->count = bytes;\n");
fdecl->name = fname;
fdecl->body = ec;