Make common helpers for seq_files that work with list_head-s
Subsystems (14)
PATCH 1/1 Make common helpers for seq_files that work with list_head-s
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.
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(-)
---
include/linux/seq_file.h +35 -0
@@ -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
block/genhd.c +14 -26
@@ -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 *pstatic 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_fistatic 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 ();
crypto/proc.c +3 -14
@@ -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, vstatic 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);
drivers/char/misc.c +3 -15
@@ -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_filstatic 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 ;
drivers/input/input.c +4 -25
@@ -471,37 +471,16 @@ static unsigned int input_proc_devices_preturn 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)
drivers/isdn/capi/kcapi_proc.c +4 -24
@@ -243,36 +243,15 @@ create_seq_entry(char *name, mode_t mode// --------------------------------------------------------------------------- - -static __inline__struct capi_driver *capi_driver_get_idx (loff_t pos) -{ -struct capi_driver *drv =NULL ; -struct list_head *l; -loff_t i; - - i =0 ; -list_for_each (l, &capi_drivers) { - drv = list_entry(l, struct capi_driver, list); -if (i++ == pos) -return drv; - } -return NULL ; -} -static void *capi_driver_start (struct seq_file *seq,loff_t *pos) { -struct capi_driver *drv;read_lock (&capi_drivers_list_lock); - drv =capi_driver_get_idx (*pos); -return drv; +return seq_list_start (&capi_drivers, *pos); }static void *capi_driver_next (struct seq_file *seq,void *v,loff_t *pos) { -struct capi_driver *drv = (struct capi_driver *)v; - ++*pos; -if (drv->list.next == &capi_drivers)return NULL ; - return list_entry(drv->list.next, struct capi_driver, list); +return seq_list_next (v, &capi_drivers, pos); }static void capi_driver_stop (struct seq_file *seq,void *v)
@@ -282,7 +261,8 @@ static void capi_driver_stop(struct seq_static int capi_driver_show (struct seq_file *seq,void *v) { -struct capi_driver *drv = (struct capi_driver *)v; + struct capi_driver *drv = list_entry(v, struct capi_driver, list); +seq_printf (seq,"%-32s %s\n" , drv->name, drv->revision);return 0 ; }
fs/afs/proc.c +11 -70
163 lines not on this page · raw message
fs/namespace.c +4 -10
@@ -393,22 +393,16 @@ EXPORT_SYMBOL(mnt_unpin);static void *m_start (struct seq_file *m,loff_t *pos) {struct mnt_namespace *n = m->private; -struct list_head *p; -loff_t l = *pos;down_read (&namespace_sem); -list_for_each (p, &n->list) -if (!l--) - return list_entry(p, struct vfsmount, mnt_list); -return NULL ; +return seq_list_start (&n->list, *pos); }static void *m_next (struct seq_file *m,void *v,loff_t *pos) {struct mnt_namespace *n = m->private; -struct list_head *p = ((struct vfsmount *)v)->mnt_list.next; - (*pos)++; - return p == &n->list ? NULL : list_entry(p, struct vfsmount, mnt_list); + +return seq_list_next (v, &n->list, pos); }static void m_stop (struct seq_file *m,void *v)
@@ -423,7 +417,7 @@ static inline void mangle(struct seq_filstatic int show_vfsmnt (struct seq_file *m,void *v) { -struct vfsmount *mnt = v; + struct vfsmount *mnt = list_entry(v, struct vfsmount, mnt_list);int err =0 ; static struct proc_fs_info { int flag;
fs/nfs/client.c +6 -48
94 lines not on this page · raw message
fs/proc/proc_tty.c +3 -12
@@ -69,7 +69,7 @@ static void show_tty_range(struct seq_fistatic int show_tty_driver (struct seq_file *m,void *v) { -struct tty_driver *p = v; + struct tty_driver *p = list_entry(v, struct tty_driver, tty_drivers);dev_t from =MKDEV (p->major, p->minor_start);dev_t to = from + p->num;
@@ -106,22 +106,13 @@ static int show_tty_driver(struct seq_fi/* iterator */ static void *t_start (struct seq_file *m,loff_t *pos) { -struct list_head *p; -loff_t l = *pos; -mutex_lock (&tty_mutex); -list_for_each (p, &tty_drivers) -if (!l--) - return list_entry(p, struct tty_driver, tty_drivers); -return NULL ; +return seq_list_start (&tty_drivers, *pos); }static void *t_next (struct seq_file *m,void *v,loff_t *pos) { -struct list_head *p = ((struct tty_driver *)v)->tty_drivers.next; - (*pos)++; -return p==&tty_drivers ?NULL : - list_entry(p, struct tty_driver, tty_drivers); +return seq_list_next (v, &tty_drivers, pos); }static void t_stop (struct seq_file *m,void *v)
kernel/module.c +2 -15
@@ -2232,26 +2232,13 @@ unsigned long module_kallsyms_lookup_nam/* Called by the /proc file system to return a list of modules. */ static void *m_start (struct seq_file *m,loff_t *pos) { -struct list_head *i; -loff_t n =0 ; -mutex_lock (&module_mutex); -list_for_each (i, &modules) { -if (n++ == *pos) -break ; - } -if (i == &modules) -return NULL ; -return i; +return seq_list_start (&modules, *pos); }static void *m_next (struct seq_file *m,void *p,loff_t *pos) { -struct list_head *i = p; - (*pos)++; -if (i->next == &modules) -return NULL ; -return i->next; +return seq_list_next (p, &modules, pos); }static void m_stop (struct seq_file *m,void *p)
mm/slab.c +5 -23
@@ -4161,26 +4161,17 @@ static void print_slabinfo_header(structstatic void *s_start (struct seq_file *m,loff_t *pos) {loff_t n = *pos; -struct list_head *p;mutex_lock (&cache_chain_mutex);if (!n)print_slabinfo_header (m); - p = cache_chain.next; -while (n--) { - p = p->next; -if (p == &cache_chain) -return NULL ; - } - return list_entry(p, struct kmem_cache, next); + +return seq_list_start (&cache_chain, *pos); }static void *s_next (struct seq_file *m,void *p,loff_t *pos) { -struct kmem_cache *cachep = p; - ++*pos; -return cachep->next.next == &cache_chain ? - NULL : list_entry(cachep->next.next, struct kmem_cache, next); +return seq_list_next (p, &cache_chain, pos); }static void s_stop (struct seq_file *m,void *p)
@@ -4190,7 +4181,7 @@ static void s_stop(struct seq_file *m, vstatic int s_show (struct seq_file *m,void *p) { -struct kmem_cache *cachep = p; + struct kmem_cache *cachep = list_entry(p, struct kmem_cache, next);struct slab *slabp;unsigned long active_objs;unsigned long num_objs;
@@ -4359,17 +4350,8 @@ ssize_t slabinfo_write(struct file *filestatic void *leaks_start (struct seq_file *m,loff_t *pos) { -loff_t n = *pos; -struct list_head *p; -mutex_lock (&cache_chain_mutex); - p = cache_chain.next; -while (n--) { - p = p->next; -if (p == &cache_chain) -return NULL ; - } - return list_entry(p, struct kmem_cache, next); +return seq_list_start (&cache_chain, *pos); }static inline int add_caller (unsigned long *n,unsigned long v)
net/atm/br2684.c +4 -18
@@ -699,28 +699,13 @@ static struct atm_ioctl br2684_ioctl_ops#ifdef CONFIG_PROC_FS static void *br2684_seq_start (struct seq_file *seq,loff_t *pos) { -loff_t offs =0 ; -struct br2684_dev *brd; -read_lock (&devs_lock); - -list_for_each_entry (brd, &br2684_devs, br2684_devs) { -if (offs == *pos) -return brd; - ++offs; - } -return NULL ; +return seq_list_start (&br2684_devs, *pos); }static void *br2684_seq_next (struct seq_file *seq,void *v,loff_t *pos) { -struct br2684_dev *brd = v; - - ++*pos; - - brd =list_entry (brd->br2684_devs.next, - struct br2684_dev, br2684_devs); -return (&brd->br2684_devs != &br2684_devs) ? brd :NULL ; +return seq_list_next (v, &br2684_devs, pos); }static void br2684_seq_stop (struct seq_file *seq,void *v)
@@ -730,7 +715,8 @@ static void br2684_seq_stop(struct seq_fstatic int br2684_seq_show (struct seq_file *seq,void *v) { -const struct br2684_dev *brdev = v; + const struct br2684_dev *brdev = list_entry(v, struct br2684_dev, + br2684_devs);const struct net_device *net_dev = brdev->net_dev;const struct br2684_vcc *brvcc;
net/core/sock.c +4 -35
@@ -1839,46 +1839,15 @@ void proto_unregister(struct proto *protEXPORT_SYMBOL (proto_unregister);#ifdef CONFIG_PROC_FS -static inline struct proto *__proto_head (void ) -{ - return list_entry(proto_list.next, struct proto, node); -} - -static inline struct proto *proto_head (void ) -{ -return list_empty (&proto_list) ?NULL :__proto_head (); -} - -static inline struct proto *proto_next (struct proto *proto) -{ -return proto->node.next == &proto_list ?NULL : - list_entry(proto->node.next, struct proto, node); -} - -static inline struct proto *proto_get_idx (loff_t pos) -{ -struct proto *proto; -loff_t i =0 ; - -list_for_each_entry (proto, &proto_list, node) -if (i++ == pos) - goto out; - - proto =NULL ; -out: -return proto; -} -static void *proto_seq_start (struct seq_file *seq,loff_t *pos) {read_lock (&proto_list_lock); -return *pos ?proto_get_idx (*pos -1 ) :SEQ_START_TOKEN ; +return seq_list_start_head (&proto_list, *pos); }static void *proto_seq_next (struct seq_file *seq,void *v,loff_t *pos) { - ++*pos; -return v ==SEQ_START_TOKEN ?proto_head () :proto_next (v); +return seq_list_next (v, &proto_list, pos); }static void proto_seq_stop (struct seq_file *seq,void *v)
@@ -1926,7 +1895,7 @@ static void proto_seq_printf(struct seq_static int proto_seq_show (struct seq_file *seq,void *v) { -if (v ==SEQ_START_TOKEN ) +if (v == &proto_list) seq_printf(seq, "%-9s %-4s %-8s %-6s %-5s %-7s %-4s %-10s %s", "protocol", "size",
@@ -1938,7 +1907,7 @@ static int proto_seq_show(struct seq_fil"module" , "cl co di ac io in de sh ss gs se re sp bi br ha uh gp em\n"); else -proto_seq_printf (seq ,v ); +proto_seq_printf (seq ,list_entry (v ,struct proto ,node ));return 0 ; }
net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c +4 -23
@@ -208,35 +208,15 @@ static const struct file_operations ct_f/* expects */ static void *exp_seq_start (struct seq_file *s,loff_t *pos) { -struct list_head *e = &nf_conntrack_expect_list; -loff_t i; -/* strange seq_file api calls stop even if we fail, * thus we need to grab lock since stop unlocks */ read_lock_bh (&nf_conntrack_lock); - -if (list_empty (e)) -return NULL ; - -for (i =0 ; i <= *pos; i++) { - e = e->next; -if (e == &nf_conntrack_expect_list) -return NULL ; - } -return e; +return seq_list_start (&nf_conntrack_expect_list, *pos); }static void *exp_seq_next (struct seq_file *s,void *v,loff_t *pos) { -struct list_head *e = v; - - ++*pos; - e = e->next; - -if (e == &nf_conntrack_expect_list) -return NULL ; - -return e; +return seq_list_next (v, &nf_conntrack_expect_list, pos); }static void exp_seq_stop (struct seq_file *s,void *v)
@@ -246,7 +226,8 @@ static void exp_seq_stop(struct seq_filestatic int exp_seq_show (struct seq_file *s,void *v) { -struct nf_conntrack_expect *exp = v; +struct nf_conntrack_expect *exp =list_entry (v, + struct nf_conntrack_expect, list);if (exp->tuple.src.l3num !=AF_INET )return 0 ;
net/netfilter/nf_conntrack_expect.c +4 -23
@@ -366,35 +366,15 @@ EXPORT_SYMBOL_GPL(nf_conntrack_expect_re#ifdef CONFIG_PROC_FS static void *exp_seq_start (struct seq_file *s,loff_t *pos) { -struct list_head *e = &nf_conntrack_expect_list; -loff_t i; -/* strange seq_file api calls stop even if we fail, * thus we need to grab lock since stop unlocks */ read_lock_bh (&nf_conntrack_lock); - -if (list_empty (e)) -return NULL ; - -for (i =0 ; i <= *pos; i++) { - e = e->next; -if (e == &nf_conntrack_expect_list) -return NULL ; - } -return e; +return seq_list_start (&nf_conntrack_expect_list, *pos); }static void *exp_seq_next (struct seq_file *s,void *v,loff_t *pos) { -struct list_head *e = v; - - ++*pos; - e = e->next; - -if (e == &nf_conntrack_expect_list) -return NULL ; - -return e; +return seq_list_next (v, &nf_conntrack_expect_list, pos); }static void exp_seq_stop (struct seq_file *s,void *v)
@@ -404,7 +384,8 @@ static void exp_seq_stop(struct seq_filestatic int exp_seq_show (struct seq_file *s,void *v) { -struct nf_conntrack_expect *expect = v; +struct nf_conntrack_expect *expect =list_entry (v, + struct nf_conntrack_expect, list);if (expect->timeout.function) seq_printf(s, "%ld ", timer_pending(&expect->timeout)
net/rxrpc/ar-proc.c +6 -42
83 lines not on this page · raw message
Dmitry Torokhov
maintainerHi Pavel,
Quoted 4 lines · Pavel Emelianov
Many places in kernel use
seq_fileAPI to iterate over a regularlist_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!
Signature · 1 line
Dmitry
Andrew Morton
maintainerQuoted 20 lines · On Thu, 17 May 2007 19:19:40 +0400 Pavel Emelianov <[email protected]> wrote:
Many places in kernel use
seq_fileAPI to iterate over a regularlist_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 <[email protected]>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 +++++++
Quoted 8 lines
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.