OpenVZ Forum


Home » Mailing lists » Devel » [PATCH] Make common helpers for seq_files that work with list_head-s
[PATCH] Make common helpers for seq_files that work with list_head-s [message #13017] Thu, 17 May 2007 15:15 Go to next message
xemul is currently offline  xemul
Messages: 248
Registered: November 2005
Senior Member
Many places in kernel use seq_file API to iterate over a regular
list_head. The code for such iteration is identical in all the
places, so it's worth introducing a common helpers.

This makes code more than 300 lines smaller.

Cc-ed are people, who maintain the code altered by the patch.

Signed-off-by: Pavel Emelianov <xemul@openvz.org>

block/genhd.c | 40 +++-----
crypto/proc.c | 17 ---
drivers/char/misc.c | 18 ----
drivers/input/input.c | 29 ------
drivers/isdn/capi/kcapi_proc.c | 28 ------
fs/afs/proc.c | 81 ++----------------
fs/namespace.c | 14 ---
fs/nfs/client.c | 54 +-----------
fs/proc/proc_tty.c | 15 ---
include/linux/seq_file.h | 35 +++++++
kernel/module.c | 17 ---
mm/slab.c | 28 +-----
net/atm/br2684.c | 22 ----
net/core/sock.c | 39 --------
net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c | 27 ------
net/netfilter/nf_conntrack_expect.c | 27 ------
net/rxrpc/ar-proc.c | 48 +---------
17 files changed, 116 insertions(+), 423 deletions(-)

---

diff --git a/include/linux/seq_file.h b/include/linux/seq_file.h
index 3e3cccb..6f394a0 100644
--- a/include/linux/seq_file.h
+++ b/include/linux/seq_file.h
@@ -50,5 +50,40 @@ int seq_release_private(struct inode *,

#define SEQ_START_TOKEN ((void *)1)

+/*
+ * Helpers for iteration over list_head-s in seq_files
+ */
+
+static inline struct list_head *seq_list_start(struct list_head *head,
+ loff_t pos)
+{
+ struct list_head *lh;
+
+ list_for_each(lh, head)
+ if (pos-- == 0)
+ return lh;
+
+ return NULL;
+}
+
+static inline struct list_head *seq_list_start_head(struct list_head *head,
+ loff_t pos)
+{
+ if (!pos)
+ return head;
+
+ return seq_list_start(head, pos - 1);
+}
+
+static inline struct list_head *seq_list_next(void *v, struct list_head *head,
+ loff_t *ppos)
+{
+ struct list_head *lh;
+
+ lh = ((struct list_head *)v)->next;
+ ++*ppos;
+ return lh == head ? NULL : lh;
+}
+
#endif
#endif
diff --git a/block/genhd.c b/block/genhd.c
index 863a8c0..8813c14 100644
--- a/block/genhd.c
+++ b/block/genhd.c
@@ -270,22 +270,13 @@ void __init printk_all_partitions(void)
/* iterator */
static void *part_start(struct seq_file *part, loff_t *pos)
{
- struct list_head *p;
- loff_t l = *pos;
-
mutex_lock(&block_subsys_lock);
- list_for_each(p, &block_subsys.list)
- if (!l--)
- return list_entry(p, struct gendisk, kobj.entry);
- return NULL;
+ return seq_list_start_head(&block_subsys.list, *pos);
}

static void *part_next(struct seq_file *part, void *v, loff_t *pos)
{
- struct list_head *p = ((struct gendisk *)v)->kobj.entry.next;
- ++*pos;
- return p==&block_subsys.list ? NULL :
- list_entry(p, struct gendisk, kobj.entry);
+ return seq_list_next(v, &block_subsys.list, pos);
}

static void part_stop(struct seq_file *part, void *v)
@@ -295,13 +286,16 @@ static void part_stop(struct seq_file *p

static int show_partition(struct seq_file *part, void *v)
{
- struct gendisk *sgp = v;
+ struct gendisk *sgp;
int n;
char buf[BDEVNAME_SIZE];

- if (&sgp->kobj.entry == block_subsys.list.next)
+ if (v == &block_subsys.list) {
seq_puts(part, "major minor #blocks name\n\n");
+ return 0;
+ }

+ sgp = list_entry(v, struct gendisk, kobj.entry);
/* Don't show non-partitionable removeable devices or empty devices */
if (!get_capacity(sgp) ||
(sgp->minors == 1 && (sgp->flags & GENHD_FL_REMOVABLE)))
@@ -622,22 +616,13 @@ decl_subsys(block, &ktype_block, &block_
/* iterator */
static void *diskstats_start(struct seq_file *part, loff_t *pos)
{
- loff_t k = *pos;
- struct list_head *p;
-
mutex_lock(&block_subsys_lock);
- list_for_each(p, &block_subsys.list)
- if (!k--)
- return list_entry(p, struct gendisk, kobj.entry);
- return NULL;
+ return seq_list_start(&block_subsys.list, *pos);
}

static void *diskstats_next(struct seq_file *part, void *v, loff_t *pos)
{
- struct list_head *p = ((struct gendisk *)v)->kobj.entry.next;
- ++*pos;
- return p==&block_subsys.list ? NULL :
- list_entry(p, struct gendisk, kobj.entry);
+ return seq_list_next(v, &block_subsys.list, pos);
}

static void diskstats_stop(struct seq_file *part, void *v)
@@ -647,18 +632,21 @@ static void diskstats_stop(struct seq_fi

static int diskstats_show(struct seq_file *s, void *v)
{
- struct gendisk *gp = v;
+ struct gendisk *gp;
char buf[BDEVNAME_SIZE];
int n = 0;

/*
- if (&sgp->kobj.entry == block_subsys.kset.list.next)
+ if (v == &block_subsys.list) {
seq_puts(s, "major minor name"
" rio rmerge rsect ruse wio wmerge "
"wsect wuse running use aveq"
"\n\n");
+ return 0;
+ }
*/

+ gp = list_entry(v, struct gendisk, kobj.entry);
preempt_disable();
disk_round_stats(gp);
preempt_enable();
diff --git a/crypto/proc.c b/crypto/proc.c
index 102c751..3d73323 100644
--- a/crypto/proc.c
+++ b/crypto/proc.c
@@ -23,24 +23,13 @@

static void *c_start(struct seq_file *m, loff_t *pos)
{
- struct list_head *v;
- loff_t n = *pos;
-
down_read(&crypto_alg_sem);
- list_for_each(v, &crypto_alg_list)
- if (!n--)
- return list_entry(v, struct crypto_alg, cra_list);
- return NULL;
+ return seq_list_start(&crypto_alg_list, *pos);
}

static void *c_next(struct seq_file *m, void *p, loff_t *pos)
{
- struct list_head *v = p;
-
- (*pos)++;
- v = v->next;
- return (v == &crypto_alg_list) ?
- NULL : list_entry(v, struct crypto_alg, cra_list);
+ return seq_list_next(p, &crypto_alg_list, pos);
}

static void c_stop(struct seq_file *m, void *p)
@@ -50,7 +39,7 @@ static void c_stop(struct seq_file *m, v

static int c_show(struct seq_file *m, void *p)
{
- struct crypto_alg *alg = (struct crypto_alg *)p;
+ struct crypto_alg *alg = list_entry(p, struct crypto_alg, cra_list);

seq_printf(m, "name : %s\n", alg->cra_name);
seq_printf(m, "driver : %s\n", alg->cra_driver_name);
diff --git a/drivers/char/misc.c b/drivers/char/misc.c
index 4e6fb96..71c8cd7 100644
--- a/drivers/char/misc.c
+++ b/drivers/char/misc.c
@@ -67,25 +67,13 @@ extern int pmu_device_init(void);
#ifdef CONFIG_PROC_FS
static void *misc_seq_start(struct seq_file *seq, loff_t *pos)
{
- struct miscdevice *p;
- loff_t off = 0;
-
mutex_lock(&misc_mtx);
- list_for_each_entry(p, &misc_list, list) {
- if (*pos == off++)
- return p;
- }
- return NULL;
+ return seq_list_start(&misc_list, *pos);
}

static void *misc_seq_next(struct seq_file *seq, void *v, loff_t *pos)
{
- struct list_head *n = ((struct miscdevice *)v)->list.next;
-
- ++*pos;
-
- return (n != &misc_list) ? list_entry(n, struct miscdevice, list)
- : NULL;
+ return seq_list_next(v, &misc_list, pos);
}

static void misc_seq_stop(struct seq_file *seq, void *v)
@@ -95,7 +83,7 @@ static void misc_seq_stop(struct seq_fil

static int misc_seq_show(struct seq_file *seq, void *v)
{
- const struct miscdevice *p = v;
+ const struct miscdevice *p = list_entry(v, struct miscdevice, list);

seq_printf(seq, "%3i %s\n", p->minor, p->name ? p->name : "");
return 0;
diff --git a/drivers/input/input.c b/drivers/input/input.c
index ccd8aba..da83c17 100644
--- a/drivers/input/input.c
+++ b/drivers/input/input.c
@@ -471,37 +471,16 @@ static unsigned int input_proc_devices_p
return 0;
}

-static struct list_head *list_get_nth_element(struct list_head *list, loff_t *pos)
-{
- struct list_head *node;
- loff_t i = 0;
-
- list_for_each(node, list)
- if (i++ == *pos)
- return node;
-
- return NULL;
-}
-
-static struct list_head *list_get_next_element(struct list_head *list, struct list_head *element, loff_t *pos)
-{
- if (element->next == list)
- return NULL;
-
- ++(*pos);
- return element->next;
-}
-
static void *input_devices_seq_start(struct seq_file *seq, loff_t *pos)
{
/* acquire lock here ... Yes, we do need locking, I knowi, I know... */

- return list_get_nth_element(&input_dev_list, pos);
+ return seq_list_start(&input_dev_list, *pos);
}

static void *input_devices_seq_next(struct seq_file *seq, void *v, loff_t *pos)
{
- return list_get_next_element(&input_dev_list, v, pos);
+ return seq_list_next(v, &input_dev_list, pos);
}

static void input_devices_seq_stop(struct seq_file *seq, void *v)
@@ -592,13 +571,13 @@ static void *input_handlers_seq_start(st
{
/* acquire lock here ... Yes, we do need locking, I knowi, I know... */
seq->private = (void *)(unsigned long)*pos;
- return list_get_nth_element(&input_handler_list, pos);
+ return seq_list_start(&input_handler_list, *pos);
}

static void *input_handlers_seq_next(struct seq_file *seq, void *v, loff_t *pos)
{
seq->private = (void *)(unsigned long)(*pos + 1);
- return list_get_next_element(&input_handler_list, v, pos);
+ return seq_list_next(v, &input_handler_list, pos);
}

static void input_handlers_seq_stop(struct seq_file *seq, void *v)
diff --git a/drivers/isdn/capi/kcapi_proc.c b/drivers/isdn/capi/kcapi_proc.c
index 31f4fd8..845a797 100644
--- a/drivers/isdn/capi/kcapi_proc.c
+++ b/drivers/isdn/capi/kcapi_proc.c
@@ -243,36 +243,15 @@ create_seq_entry(char *name, mode_t mode

// ------------------------------------------------------------ ---------------

-
-static __inline__ struct capi_driver *ca
...

Re: [PATCH] Make common helpers for seq_files that work with list_head-s [message #13021 is a reply to message #13017] Thu, 17 May 2007 17:36 Go to previous message
Andrew Morton is currently offline  Andrew Morton
Messages: 127
Registered: December 2005
Senior Member
On Thu, 17 May 2007 19:19:40 +0400 Pavel Emelianov <xemul@sw.ru> wrote:

> Many places in kernel use seq_file API to iterate over a regular
> list_head. The code for such iteration is identical in all the
> places, so it's worth introducing a common helpers.
>
> This makes code more than 300 lines smaller.
>
> Cc-ed are people, who maintain the code altered by the patch.
>
> Signed-off-by: Pavel Emelianov <xemul@openvz.org>
>
> block/genhd.c | 40 +++-----
> crypto/proc.c | 17 ---
> drivers/char/misc.c | 18 ----
> drivers/input/input.c | 29 ------
> drivers/isdn/capi/kcapi_proc.c | 28 ------
> fs/afs/proc.c | 81 ++----------------
> fs/namespace.c | 14 ---
> fs/nfs/client.c | 54 +-----------
> fs/proc/proc_tty.c | 15 ---
> include/linux/seq_file.h | 35 +++++++
> kernel/module.c | 17 ---
> mm/slab.c | 28 +-----
> net/atm/br2684.c | 22 ----
> net/core/sock.c | 39 --------
> net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c | 27 ------
> net/netfilter/nf_conntrack_expect.c | 27 ------
> net/rxrpc/ar-proc.c | 48 +---------
> 17 files changed, 116 insertions(+), 423 deletions(-)

Can't complain about the diffstat. Please experiment with uninlining
seq_list_start(), see if that reduces overall text size.

And as Dmitry indicated, it would be less disruptive if we could have the
one core patch then a stream of per-subsystem patches, please.
Re: [PATCH] Make common helpers for seq_files that work with list_head-s [message #13080 is a reply to message #13017] Thu, 17 May 2007 15:35 Go to previous message
Dmitry Torokhov is currently offline  Dmitry Torokhov
Messages: 1
Registered: May 2007
Junior Member
Hi Pavel,

On 5/17/07, Pavel Emelianov <xemul@sw.ru> wrote:
> Many places in kernel use seq_file API to iterate over a regular
> list_head. The code for such iteration is identical in all the
> places, so it's worth introducing a common helpers.
>

Makes sense, however I am working on that part of the input code so if
you could split input out so I could apply it later that'd be grand.
Thanks!

--
Dmitry
Previous Topic: Remaining straight forward kthread API conversions...
Next Topic: [PATCH 0/15] Make common helpers for seq_files that work with list_head-s (v2)
Goto Forum:
  


Current Time: Fri Apr 19 15:49:55 GMT 2024

Total time taken to generate the page: 0.01802 seconds