summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorhunt <hunt>2007-09-10 16:18:42 +0000
committerhunt <hunt>2007-09-10 16:18:42 +0000
commitf0d5b7785b8275fe4017b796e2fedcf7829f8db0 (patch)
tree08aa318a9e05d674370c5676c9188987be2f080b
parentc4def167a224cf416b1dc16ec82ae791422d568d (diff)
downloadsystemtap-steved-f0d5b7785b8275fe4017b796e2fedcf7829f8db0.tar.gz
systemtap-steved-f0d5b7785b8275fe4017b796e2fedcf7829f8db0.tar.xz
systemtap-steved-f0d5b7785b8275fe4017b796e2fedcf7829f8db0.zip
2007-09-10 Martin Hunt <hunt@redhat.com>
* procfs.c: New file. Common runtime procfs functions.
-rw-r--r--runtime/ChangeLog4
-rw-r--r--runtime/procfs.c177
-rw-r--r--runtime/runtime.h5
3 files changed, 185 insertions, 1 deletions
diff --git a/runtime/ChangeLog b/runtime/ChangeLog
index 0597007d..ac7cce35 100644
--- a/runtime/ChangeLog
+++ b/runtime/ChangeLog
@@ -1,3 +1,7 @@
+2007-09-10 Martin Hunt <hunt@redhat.com>
+
+ * procfs.c: New file. Common runtime procfs functions.
+
2007-08-20 Martin Hunt <hunt@redhat.com>
* stack.c (_stp_kta): Removed.
diff --git a/runtime/procfs.c b/runtime/procfs.c
new file mode 100644
index 00000000..f31766ca
--- /dev/null
+++ b/runtime/procfs.c
@@ -0,0 +1,177 @@
+/* -*- linux-c -*-
+ *
+ * /proc command channels
+ * Copyright (C) 2007 Red Hat Inc.
+ *
+ * This file is part of systemtap, and is free software. You can
+ * redistribute it and/or modify it under the terms of the GNU General
+ * Public License (GPL); either version 2, or (at your option) any
+ * later version.
+ */
+
+/* The maximum number of files AND directories that can be opened.
+ * It would be great if the translator would emit this based on the actual
+ * number of needed files.
+ */
+
+#define STP_MAX_PROCFS_FILES 16
+static int _stp_num_pde = 0;
+static int _stp_num_procfs_files = 0;
+static struct proc_dir_entry *_stp_pde[STP_MAX_PROCFS_FILES];
+static struct proc_dir_entry *_stp_procfs_files[STP_MAX_PROCFS_FILES];
+static struct proc_dir_entry *_stp_proc_stap = NULL;
+static struct proc_dir_entry *_stp_proc_root = NULL;
+
+void _stp_close_procfs(void);
+
+/*
+ * Removes /proc/systemtap/{module_name} and /proc/systemtap (if empty)
+ */
+void _stp_rmdir_proc_module(void)
+{
+ if (_stp_proc_root && _stp_proc_root->subdir == NULL) {
+ remove_proc_entry(THIS_MODULE->name, _stp_proc_stap);
+ _stp_proc_root = NULL;
+ }
+
+ if (_stp_proc_stap) {
+ if (!_stp_lock_debugfs()) {
+ errk("Unable to lock transport directory.\n");
+ return;
+ }
+
+ if (_stp_proc_stap->subdir == NULL) {
+ remove_proc_entry("systemtap", NULL);
+ _stp_proc_stap = NULL;
+ }
+
+ _stp_unlock_debugfs();
+ }
+}
+
+
+/*
+ * Safely creates /proc/systemtap (if necessary) and
+ * /proc/systemtap/{module_name}.
+ */
+int _stp_mkdir_proc_module(void)
+{
+ if (_stp_proc_root == NULL) {
+ struct nameidata nd;
+
+ if (!_stp_lock_debugfs()) {
+ errk("Unable to lock transport directory.\n");
+ goto done;
+ }
+
+ /* We use path_lookup() because there is no lookup */
+ /* function for procfs we can call directly. And */
+ /* proc_mkdir() will always succeed, creating multiple */
+ /* directory entries, all with the same name. */
+
+ if (path_lookup("/proc/systemtap", 0, &nd)) {
+ /* doesn't exist, so create it */
+ _stp_proc_stap = proc_mkdir ("systemtap", NULL);
+ if (_stp_proc_stap == NULL) {
+ _stp_unlock_debugfs();
+ goto done;
+ }
+ } else
+ _stp_proc_stap = PDE(nd.dentry->d_inode);
+
+ _stp_proc_root = proc_mkdir(THIS_MODULE->name, _stp_proc_stap);
+ _stp_unlock_debugfs();
+ }
+done:
+ return (_stp_proc_root) ? 1 : 0;
+}
+
+/*
+ * This checks our local cache to see if we already made the dir.
+ */
+static struct proc_dir_entry *_stp_procfs_dir_lookup(char *dir, struct proc_dir_entry *parent)
+{
+ int i;
+ for (i = 0; i <_stp_num_pde; i++) {
+ struct proc_dir_entry *pde = _stp_pde[i];
+ if (pde->parent == parent && !strcmp(dir, pde->name))
+ return pde;
+ }
+ return NULL;
+}
+
+int _stp_create_procfs(char *path, int num)
+{
+ char *p = path, *next;
+ struct proc_dir_entry *last_dir, *de;
+
+ if (num >= STP_MAX_PROCFS_FILES) {
+ _stp_error("Requested file number %d is larger than max (%d)\n",
+ num, STP_MAX_PROCFS_FILES);
+ return -1;
+ }
+
+ _stp_mkdir_proc_module();
+ last_dir = _stp_proc_root;
+
+ /* if no path, use default one */
+ if (strlen(p) == 0)
+ p = "command";
+ _dbug("path=/proc/systemtap/%s/%s\n", THIS_MODULE->name, p);
+
+ while ((next = strchr(p, '/'))) {
+ if (_stp_num_pde == STP_MAX_PROCFS_FILES)
+ goto too_many;
+ *next = 0;
+ de = _stp_procfs_dir_lookup(p, last_dir);
+ _dbug("lookup of %s %p returned %p\n", p, last_dir, de);
+ if (de == NULL) {
+ last_dir = proc_mkdir(p, last_dir);
+ if (!last_dir) {
+ _stp_error("Could not create directory \"%s\" " \
+ "in path \"%s\"\n", p, path);
+ goto err;
+ }
+ _dbug("mkdir %s returned %p\n", p, last_dir);
+ _stp_pde[_stp_num_pde++] = last_dir;
+ last_dir->uid = _stp_uid;
+ last_dir->gid = _stp_gid;
+ } else
+ last_dir = de;
+ p = next + 1;
+ }
+
+ if (_stp_num_pde == STP_MAX_PROCFS_FILES)
+ goto too_many;
+
+ _dbug("creating file %s\n", p);
+ de = create_proc_entry (p, 0600, last_dir);
+ if (de == NULL) {
+ _stp_error("Could not create file \"%s\" in path \"%s\"\n", p, path);
+ goto err;
+ }
+ _stp_pde[_stp_num_pde++] = de;
+ _stp_procfs_files[num] = de;
+ de->uid = _stp_uid;
+ de->gid = _stp_gid;
+ return 0;
+
+too_many:
+ _stp_error("Attempted to open too many procfs files. Maximum is %d\n", STP_MAX_PROCFS_FILES);
+err:
+ _stp_close_procfs();
+ return -1;
+}
+
+void _stp_close_procfs(void)
+{
+ int i;
+ _dbug("closing all procfs files\n");
+ for (i = _stp_num_pde-1; i >= 0; i--) {
+ struct proc_dir_entry *pde = _stp_pde[i];
+ _dbug("remove %s in %s\n", pde->name, pde->parent->name);
+ remove_proc_entry(pde->name, pde->parent);
+ }
+ _stp_num_pde = 0;
+ _stp_rmdir_proc_module();
+}
diff --git a/runtime/runtime.h b/runtime/runtime.h
index 756f8607..d951833d 100644
--- a/runtime/runtime.h
+++ b/runtime/runtime.h
@@ -43,6 +43,9 @@
#define for_each_cpu(cpu) for_each_cpu_mask((cpu), cpu_possible_map)
#endif
+static void _stp_dbug (const char *func, int line, const char *fmt, ...);
+void _stp_error (const char *fmt, ...);
+
#ifdef DEBUG
/** Prints debug line.
* This function prints a debug message immediately to staprun.
@@ -50,13 +53,13 @@
* @param args A variable number of args in a format like printf.
* @ingroup io
*/
-static void _stp_dbug (const char *func, int line, const char *fmt, ...);
#define dbug(args...) _stp_dbug(__FUNCTION__, __LINE__, args)
#define kbug(args...) {printk("%s:%d ",__FUNCTION__, __LINE__); printk(args); }
#else
#define dbug(args...) ;
#define kbug(args...) ;
#endif /* DEBUG */
+#define _dbug(args...) _stp_dbug(__FUNCTION__, __LINE__, args)
#define errk(args...) {printk("Systemtap Error at %s:%d ",__FUNCTION__, __LINE__); printk(args); }
/* atomic globals */