public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
From: Andrew Morton <akpm@osdl.org>
To: Martin Schwidefsky <schwidefsky@de.ibm.com>
Cc: mpeschke@de.ibm.com, linux-kernel@vger.kernel.org
Subject: Re: [patch 1/14] s390: statistics infrastructure.
Date: Mon, 31 Oct 2005 00:40:46 -0800	[thread overview]
Message-ID: <20051031004046.730bc45f.akpm@osdl.org> (raw)
In-Reply-To: <20051028140617.GA7300@skybase.boeblingen.de.ibm.com>

Martin Schwidefsky <schwidefsky@de.ibm.com> wrote:
>
> From: Martin Peschke <mpeschke@de.ibm.com>
> 
> [patch 1/14] s390: statistics infrastructure.
> 
> Add the statistics facility. This features offers a simple way to
> gather statistical data and to display them via the debugfs.
> An example how this is used:
> 
> 	struct statistic_interface *stat_if;
> 	struct statistic *stat;
> 
> 	statistic_interface_create(&stat_if, "whatever");
> 	statistic_create(&stat, stat_if, "stat-name", "unit");
> 	statistic_define_value(stat, range_min, range_max, def_mode);
> 	...
> 	statistic_inc(stat, value);	/* repeat.. */
> 	...
> 	statistic_interface_remove(&stat_if);
> 

I agree with Christoph on this: please present it as a Kconfigurable
generic option and flesh out the changelog a bit.  If the documentation in
the source file isn't sufficient, consider a Documentation/ file too,
please.

> +static struct sgrb_seg *
> +sgrb_seg_alloc(struct list_head *lh, int size, unsigned int gfp)

Use gfp_t throughout.

> +EXPORT_SYMBOL(sgrb_seg_find);

Can we use EXPORT_SYMBOL_GPL throughout?

> +
> +/**
> + * sgrb_seg_release_all - releases scatter-gather buffer
> + * @lh: list_head that holds list of scattered buffer parts
> + */
> +void
> +sgrb_seg_release_all(struct list_head *lh)

Coding style nit: please do

void sgrb_seg_release_all(struct list_head *lh)

as per the rest of the core kernel.

(If we end up deciding to keep all this in arch/s390 then I guess
we can live with s390 peculiarities though)

> +static inline int
> +sgrb_ptr_identical(
> +	struct sgrb_ptr *a,
> +	struct sgrb_ptr *b)
> +{

Here too.

> +
> +/**
> + * sgrb_alloc - prepare a new ringbuffer for use
> + *
> + * @rb: a ringbuffer struct provided by the exploiter
> + * @entry_size: size of entries in ringbuffer
> + * @entry_num: total number of entries in ringbuffer
> + * @seg_size: size of individual, scatter-gathered segments used to build up
> + *            ringbuffer
> + * @gfp: kmalloc flags
> + *
> + * Returns 0 on success.
> + * Returns -ENOMEM if some memory allocation failed.
> + **/
> +int
> +sgrb_alloc(
> +	struct sgrb *rb,
> +	int entry_size, int entry_num, int seg_size, int gfp)
> +{
> +	int i;
> +	struct sgrb_seg *seg;
> +	int entries_per_seg = (seg_size / entry_size);
> +	int seg_num = entry_num / entries_per_seg;
> +	int residual = (entry_num % entries_per_seg) * entry_size;
> +
> +	rb->entry_size = entry_size;
> +	INIT_LIST_HEAD(&rb->seg_lh);
> +	for (i = 0; i < seg_num; i++)
> +		if (!sgrb_seg_alloc(&rb->seg_lh, seg_size, gfp))
> +			return -ENOMEM;
> +	if (residual)
> +		if (!sgrb_seg_alloc(&rb->seg_lh, residual, gfp))
> +			return -ENOMEM;
> +	list_for_each_entry(seg, &rb->seg_lh, list)
> +		break;

eh?   Something's gone rather wrong here.

> +	rb->first.seg = seg;
> +	rb->last.seg = seg;
> +	sgrb_init(rb);
> +	return 0;
> +}
> +EXPORT_SYMBOL(sgrb_alloc);
> +
> ...
> +static void
> +sgrb_next_entry(
> +	struct sgrb *rb,
> +	struct sgrb_ptr *pos,
> +	struct sgrb_ptr *next)
> +{
> +	sgrb_ptr_copy(next, pos);
> +	next->offset += rb->entry_size;
> +	if ((next->offset + rb->entry_size) - 1 > next->seg->size) {
> +		if (rb->seg_lh.prev == &next->seg->list) {
> +			next->seg = NULL;
> +			next->seg = list_prepare_entry(next->seg, &rb->seg_lh, list);
> +		}
> +		list_for_each_entry_continue(next->seg, &rb->seg_lh, list)
> +			break;

You did it again.   I guess it's deliberate.  Isn't there a simpler way?

> +/**
> + * sgrb_produce_nooverwrite - put an entry into the ringbuffer
> + *     if there is room whithout the need to overwrite the oldest

spello

> +/**
> + * sgrb_consume_delete - get an entry from the ringbuffer and
> + *     delete the entry from the ringbuffer so that it can't
> + *     be consumed twice, and in order to free up its slot for
> + *     another entry
> + *
> + * @rb: the ringbuffer to use
> + *
> + * Returns address of the entry read, if there is an entry available.
> + * Returns NULL otherwise.
> + **/
> +void *
> +sgrb_consume_delete(struct sgrb *rb)
> +{
> +	struct sgrb_ptr prev;
> +
> +	if (!sgrb_ptr_valid(&rb->first))
> +		return NULL;
> +	sgrb_ptr_copy(&prev, &rb->first);
> +	if (sgrb_ptr_identical(&rb->last, &rb->first))
> +		sgrb_init(rb);
> +	else
> +		sgrb_next_entry(rb, &rb->first, &rb->first);
> +	rb->entries--;
> +	return sgrb_entry(&prev);
> +}
> +EXPORT_SYMBOL(sgrb_consume_delete);

I guess all of these functions require caller-provided locking, and that's
documented somewhere?

> +
> +extern void tod_to_timeval(__u64, struct timespec *);

Please don't put extern decls in .c files - put them in a header file.

> +static inline void
> +statistic_nsec_to_timespec(u64 nsec, struct timespec *xtime)
> +{
> +	unsigned long long sec;
> +
> +        sec = nsec;
> +        do_div(sec, 1000000000);
> +        xtime->tv_sec = sec;
> +        xtime->tv_nsec = nsec - sec * 1000000000;
> +}
> +
> +static inline u64
> +statistic_timespec_to_nsec(struct timespec *xtime)
> +{
> +	return (xtime->tv_sec * 1000000000 + xtime->tv_nsec);
> +}

Maybe these should be put in jiffies.h.

> +/**
> + * statistic_create - create a statistic and attach it to a given interface
> + * @stat_ptr: reference to struct statistic pointer
> + * @interface_ptr: reference to struct statistic_interface pointer
> + * @name: name of statistic to be created and as seen in "data" and
> + *        "definition" files
> + *
> + * Create a statistic, which - after being defined and enabled - is ready
> + * to capture and compute data provided by the exploiter. A line in the
> + * interface's "definition" file will hold specifics about the named statistic.
> + *
> + * On success, 0 is returned, the struct statistic pointer
> + * provided by the caller points to a newly alloacted struct,
> + * and the statistic is defined as type "value" by default.
> + *
> + * If the struct statistic pointer provided by the caller
> + * is not NULL (used), this routine fails, the struct statistic
> + * pointer is not changed, and -EINVAL is returned.
> + *
> + * If some required memory could not be allocated this routine fails,
> + * the struct statistic pointer is not changed, and -ENOMEM is returned.
> + **/
> +int
> +statistic_create(
> +	struct statistic **stat_ptr,
> +	struct statistic_interface *interface,
> +	const char *name,
> +	const char *units)
> +{
> +	struct statistic *stat;
> +
> +	if (*stat_ptr || !interface)
> +		return -EINVAL;
> +
> +	stat = kmalloc(sizeof(struct statistic), GFP_KERNEL);
> +	if (!stat)
> +		return -ENOMEM;
> +	memset(stat, 0, sizeof(struct statistic));
> +
> +	stat->interface = interface;
> +	strlcpy(stat->name, name, sizeof(stat->name));
> +	strlcpy(stat->units, units, sizeof(stat->units));
> +	statistic_define_value(stat, STATISTIC_RANGE_MIN, STATISTIC_RANGE_MAX,
> +				STATISTIC_DEF_MODE_INC);
> +	statistic_stop_nolock(stat);
> +	stat->started = stat->stopped;
> +	stat->stat_ptr = stat_ptr;
> +
> +	list_add_tail(&stat->list, &interface->statistic_lh);
> +
> +	*stat_ptr = stat;
> +
> +	return 0;
> +}

A lot of this looks pretty generic as well.




It's a lot of code, and it'll be some work to make it generic.

Can you help us decide whether there's actually any point in making it
generic?  What problems was it designed to solve, and what additional
problems might it all be useful for?

Thanks.

  parent reply	other threads:[~2005-10-31  7:41 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2005-10-28 14:06 [patch 1/14] s390: statistics infrastructure Martin Schwidefsky
2005-10-28 18:08 ` Christoph Hellwig
2005-10-31  8:40 ` Andrew Morton [this message]
  -- strict thread matches above, loose matches on Subject: below --
2005-10-31  9:36 Martin Peschke3
2005-10-31 14:15 Martin Peschke3
2005-10-31 19:16 ` Andrew Morton
2005-10-31 20:44 Martin Peschke3

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=20051031004046.730bc45f.akpm@osdl.org \
    --to=akpm@osdl.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mpeschke@de.ibm.com \
    --cc=schwidefsky@de.ibm.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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox