From: Andrew Morton <akpm@linux-foundation.org>
To: David Wilder <dwilder@us.ibm.com>
Cc: linux-kernel@vger.kernel.org, SystemTAP <systemtap@sources.redhat.com>
Subject: Re: [PATCH 1/2] Trace code and documentation
Date: Fri, 14 Sep 2007 18:08:40 -0700 [thread overview]
Message-ID: <20070914180840.579627ab.akpm@linux-foundation.org> (raw)
In-Reply-To: <46E9CB14.7060000@us.ibm.com>
> Trace - Provides tracing primitives
>
> ...
>
> +config TRACE
> + bool "Trace setup and control"
> + select RELAY
> + select DEBUG_FS
> + help
> + This option provides support for the setup, teardown and control
> + of tracing channels from kernel code. It also provides trace
> + information and control to userspace via a set of debugfs control
> + files. If unsure, say N.
> +
select is evil - you really want to avoid using it.
The problem is where you select a symbol whose dependencies aren't met.
Kconfig resolves this incompatibility by just not selecting the thing you
wanted, iirc. So your CONFIG_SYSFS=n, CONFIG_TRACE=y kernel won't build.
> +/*
> + * Based on blktrace code, Copyright (C) 2006 Jens Axboe <axboe@suse.de>
So can we migrate blktrace to using this?
> +static ssize_t state_write(struct file *filp, const char __user *buffer,
> + size_t count, loff_t *ppos)
> +{
> + struct trace_info *trace = filp->private_data;
> + char buf[16] = { '\0' };
this initialisation isn't needed and will waste cycles.
> + int ret;
> +
> + if (trace->flags & TRACE_DISABLE_STATE)
> + return -EINVAL;
> +
> + if (count > sizeof(buf) - 1)
> + return -EINVAL;
> +
> + if (copy_from_user(buf, buffer, count))
> + return -EFAULT;
> +
> + buf[count] = '\0';
> +
> + if (strncmp(buf, "start", strlen("start")) == 0 ) {
> + ret = trace_start(trace);
> + if (ret)
> + return ret;
> + } else if (strncmp(buffer, "stop", strlen("stop")) == 0)
> + trace_stop(trace);
> + else
> + return -EINVAL;
What's the above code doing? Trying to cope with trailing chars after
"start" or "stop"? Is that actually needed? It's the \n, I assume?
> + return count;
> +}
> +
> +
> +static struct file_operations state_fops = {
> + .owner = THIS_MODULE,
> + .open = state_open,
> + .read = state_read,
> + .write = state_write,
> +};
> +
> +
> +static void remove_root(struct trace_info *trace)
> +{
> + if (trace->root->root && simple_empty(trace->root->root)) {
> + debugfs_remove(trace->root->root);
> + list_del(&trace->root->list);
> + kfree(trace->root);
> + trace->root = NULL;
> + }
> +}
> +
> +
> +static void remove_tree(struct trace_info *trace)
> +{
> + mutex_lock(&trace_mutex);
> +
> + debugfs_remove(trace->dir);
> +
> + if (--trace->root->users == 0)
> + remove_root(trace);
> +
> + mutex_unlock(&trace_mutex);
> +}
We usually only put a single blank line between functions. Two is just a
waste of screen space.
> +
> +
> +/*
> + * Creates the trace_root if it's not found.
> + */
>
> ...
>
> +static ssize_t sub_size_read(struct file *filp, char __user *buffer,
> + size_t count, loff_t *ppos)
> +{
> + struct trace_info *trace = filp->private_data;
> + char buf[32];
> +
> + snprintf(buf, sizeof(buf), "%u\n",
> + (unsigned int)trace->rchan->subbuf_size);
Use %tu to print a size_t, rather than the typecast.
> + return simple_read_from_buffer(buffer, count, ppos, buf, strlen(buf));
> +}
> +
>
> ...
>
> +static ssize_t nr_sub_read(struct file *filp, char __user *buffer,
> + size_t count, loff_t *ppos)
> +{
> + struct trace_info *trace = filp->private_data;
> + char buf[32];
> +
> + snprintf(buf, sizeof(buf), "%u\n",
> + (unsigned int)trace->rchan->n_subbufs);
Ditto. (It's unobvious why n_subbufs is a size_t)
> + return simple_read_from_buffer(buffer, count, ppos, buf, strlen(buf));
> +}
> +
>
> ...
>
> +static void remove_controls(struct trace_info *trace)
> +{
> + if (trace->state_file)
> + debugfs_remove(trace->state_file);
> + if (trace->dropped_file)
> + debugfs_remove(trace->dropped_file);
> + if (trace->reset_consumed_file)
> + debugfs_remove(trace->reset_consumed_file);
> + if (trace->nr_sub_file)
> + debugfs_remove(trace->nr_sub_file);
> + if (trace->sub_size_file)
> + debugfs_remove(trace->sub_size_file);
debugfs_remove(NULL) is legal: all the above tests can be removed.
> + if (trace->dir)
> + remove_tree(trace);
> +}
> +
>
> ...
>
> + * trace_setup: create a new trace trace handle
> + *
> + * @root: The root directory name in the root of the debugfs
> + * to place trace directories. Created as needed.
> + * @name: Trace directory name, created in @root
> + * @buf_size: size of the relay sub-buffers
> + * @buf_nr: number of relay sub-buffers
> + * @flags: Option selection (see GTSC channel flags definitions)
> + * default values when flags=0 are: use per-CPU buffering,
> + * use non-overwrite mode. See Documentation/trace.txt for details.
> + *
> + * returns a trace_info handle or NULL, if setup failed.
> + */
> +struct trace_info *trace_setup(const char *root, const char *name,
> + u32 buf_size, u32 buf_nr, u32 flags)
> +{
> + struct trace_info *trace = NULL;
> +
> + trace = setup_controls(root, name, flags);
> + if (!trace)
> + return NULL;
> +
> + trace->buf_size = buf_size;
> + trace->buf_nr = buf_nr;
> + trace->flags = flags;
> + mutex_init(&trace->state_mutex);
> + trace->state = TRACE_SETUP;
> +
> + return trace;
> +}
> +EXPORT_SYMBOL_GPL(trace_setup);
It's better for a pointer-returning function to return an ERR_PTR on error,
rather than NULL. That way the caller doesn't have to make guesses about
why the callee failed when propagating back an error. (See how your
init_module gives up and returns -1?)
> ...
>
> +
> +/**
> + * trace_cleanup_channel: destroys the trace channel only
> + *
> + * @trace: trace handle to cleanup
> + */
> +static void trace_cleanup_channel(struct trace_info *trace)
> +{
> + trace_stop(trace);
> + if (trace->rchan)
> + relay_close(trace->rchan);
relay_close(NULL) is legal. Please check the whole patch for this.
> + trace->rchan = NULL;
> +}
> +
> +/**
> + * trace_cleanup: destroys the trace channel, control files and dir
> + *
> + * @trace: trace handle to cleanup
> + */
> +void trace_cleanup(struct trace_info *trace)
> +{
> + trace_cleanup_channel(trace);
> + remove_controls(trace);
> + kfree(trace);
> +}
> +EXPORT_SYMBOL_GPL(trace_cleanup);
>
>
>
next prev parent reply other threads:[~2007-09-15 1:09 UTC|newest]
Thread overview: 9+ messages / expand[flat|nested] mbox.gz Atom feed top
2007-09-13 23:43 [PATCH 1/2] Trace code and documentation David Wilder
2007-09-14 4:12 ` Randy Dunlap
2007-09-14 17:50 ` Sam Ravnborg
2007-09-15 4:49 ` David Wilder
2007-09-15 5:18 ` Sam Ravnborg
2007-09-15 1:08 ` Andrew Morton [this message]
2007-09-15 1:40 ` Randy Dunlap
2007-09-15 4:47 ` David Wilder
2007-09-15 16:01 ` Mathieu Desnoyers
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20070914180840.579627ab.akpm@linux-foundation.org \
--to=akpm@linux-foundation.org \
--cc=dwilder@us.ibm.com \
--cc=linux-kernel@vger.kernel.org \
--cc=systemtap@sources.redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.