Make common helpers for seq_files that work with list_head-s (v2)
Subsystems (14)
cover Make common helpers for seq_files that work with list_head-s (v2)
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 about 300 lines smaller:
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 --- fs/seq_file.c | 34 +++++++ include/linux/seq_file.h | 11 ++ 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 +--------- 18 files changed, 126 insertions(+), 423 deletions(-)
The first version of this patch made the helper functions static inline in the seq_file.h header. This patch moves them to the fs/seq_file.c as Andrew proposed. The vmlinux .text section sizes are as follows:
2.6.22-rc1-mm1: 0x001794d5 with the previous version: 0x00179505 with this patch: 0x00179135
The config file used was make allnoconfig with the "y" inclusion of all the possible options to make the files modified by the patch compile plus drivers I have on the test node.
PATCH 1/15 The helper functions itselves
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.
---
fs/seq_file.c +34 -0
@@ -447,3 +447,37 @@ int seq_puts(struct seq_file *m, const creturn -1 ; }EXPORT_SYMBOL (seq_puts); + +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 ; +} + +EXPORT_SYMBOL (seq_list_start); + +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 ); +} + +EXPORT_SYMBOL (seq_list_start_head); + +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; +} + +EXPORT_SYMBOL (seq_list_next);
include/linux/seq_file.h +11 -0
@@ -50,5 +50,16 @@ int seq_release_private(struct inode *,#define SEQ_START_TOKEN ((void *)1) +/* +* Helpers for iteration over list_head-s in seq_files +*/ + +extern struct list_head *seq_list_start (struct list_head *head, +loff_t pos); +extern struct list_head *seq_list_start_head (struct list_head *head, +loff_t pos); +extern struct list_head *seq_list_next (void *v,struct list_head *head, +loff_t *ppos); +#endif #endif
David Howells
maintainerRe: [PATCH 1/15] The helper functions itselves
Quoted 3 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.
And the documentation for this?
David
PATCH 2/15 Make AFS use seq_list_xxx helpers
In reply to Pavel EmelianovThese proc files show some header before dumping
the list, so the seq_list_start_head() is used.
---
fs/afs/proc.c +11 -70
@@ -200,23 +200,9 @@ static int afs_proc_cells_open(struct in*/ static void *afs_proc_cells_start (struct seq_file *m,loff_t *_pos) { -struct list_head *_p; -loff_t pos = *_pos; -/* lock the list against modification */ down_read (&afs_proc_cells_sem); - -/* allow for the header line */ -if (!pos) -return (void *)1 ; - pos--; - -/* find the n'th element in the list */ -list_for_each (_p, &afs_proc_cells) -if (!pos--) -break ; - -return _p != &afs_proc_cells ? _p :NULL ; +return seq_list_start_head (&afs_proc_cells, *_pos); }/*
@@ -224,14 +210,7 @@ static void *afs_proc_cells_start(struct*/ static void *afs_proc_cells_next (struct seq_file *p,void *v,loff_t *pos) { -struct list_head *_p; - - (*pos)++; - - _p = v; - _p = v == (void *)1 ? afs_proc_cells.next : _p->next; - -return _p != &afs_proc_cells ? _p :NULL ; +return seq_list_next (v, &afs_proc_cells, pos); }/*
@@ -249,7 +228,7 @@ static int afs_proc_cells_show(struct se { struct afs_cell *cell = list_entry(v, struct afs_cell, proc_link); -if (v == (void *)1 ) { +if (v == &afs_proc_cells) {/* display header on line 1 */ seq_puts (m,"USE NAME\n" );return 0 ;
@@ -502,26 +481,13 @@ static int afs_proc_cell_volumes_release*/ static void *afs_proc_cell_volumes_start (struct seq_file *m,loff_t *_pos) { -struct list_head *_p;struct afs_cell *cell = m->private; -loff_t pos = *_pos;_enter ("cell=%p pos=%Ld" , cell, *_pos);/* lock the list against modification */ down_read (&cell->vl_sem); - -/* allow for the header line */ -if (!pos) -return (void *)1 ; - pos--; - -/* find the n'th element in the list */ -list_for_each (_p, &cell->vl_list) -if (!pos--) -break ; - -return _p != &cell->vl_list ? _p :NULL ; +return seq_list_start_head (&cell->vl_list, *_pos); }/*
@@ -530,17 +496,10 @@ static void *afs_proc_cell_volumes_startstatic void *afs_proc_cell_volumes_next (struct seq_file *p,void *v,loff_t *_pos) { -struct list_head *_p;struct afs_cell *cell = p->private;_enter ("cell=%p pos=%Ld" , cell, *_pos); - - (*_pos)++; - - _p = v; - _p = (v == (void *)1 ) ? cell->vl_list.next : _p->next; - -return (_p != &cell->vl_list) ? _p :NULL ; +return seq_list_next (v, &cell->vl_list, _pos); }/*
@@ -568,11 +527,12 @@ const char afs_vlocation_states[][4] = {*/ static int afs_proc_cell_volumes_show (struct seq_file *m,void *v) { +struct afs_cell *cell = m->private;struct afs_vlocation *vlocation = list_entry(v, struct afs_vlocation, link);/* display header on line 1 */ -if (v == (void *)1 ) { +if (v == &cell->vl_list) {seq_puts (m,"USE STT VLID[0] VLID[1] VLID[2] NAME\n" );return 0 ; }
@@ -733,26 +693,13 @@ static int afs_proc_cell_servers_releasestatic void *afs_proc_cell_servers_start (struct seq_file *m,loff_t *_pos) __acquires(m->private->servers_lock) { -struct list_head *_p;struct afs_cell *cell = m->private; -loff_t pos = *_pos;_enter ("cell=%p pos=%Ld" , cell, *_pos);/* lock the list against modification */ read_lock (&cell->servers_lock); - -/* allow for the header line */ -if (!pos) -return (void *)1 ; - pos--; - -/* find the n'th element in the list */ -list_for_each (_p, &cell->servers) -if (!pos--) -break ; - -return _p != &cell->servers ? _p :NULL ; +return seq_list_start_head (&cell->servers, *_pos); }/*
@@ -761,17 +708,10 @@ static void *afs_proc_cell_servers_startstatic void *afs_proc_cell_servers_next (struct seq_file *p,void *v,loff_t *_pos) { -struct list_head *_p;struct afs_cell *cell = p->private;_enter ("cell=%p pos=%Ld" , cell, *_pos); - - (*_pos)++; - - _p = v; - _p = v == (void *)1 ? cell->servers.next : _p->next; - -return _p != &cell->servers ? _p :NULL ; +return seq_list_next (v, &cell->servers, _pos); }/*
@@ -790,11 +730,12 @@ static void afs_proc_cell_servers_stop(s*/ static int afs_proc_cell_servers_show (struct seq_file *m,void *v) { +struct afs_cell *cell = m->private; struct afs_server *server = list_entry(v, struct afs_server, link);char ipaddr[20 ];/* display header on line 1 */ -if (v == (void *)1 ) { +if (v == &cell->servers) {seq_puts (m,"USE ADDR STATE\n" );return 0 ; }
PATCH 3/15 Make ATM driver use seq_list_xxx helpers
In reply to Pavel EmelianovThe .show callback receives the list_head pointer now, not the struct br2684_dev one.
---
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;
PATCH 4/15 Make block layer /proc files use seq_list_xxx helpers
In reply to Pavel EmelianovThe /proc/partitions .show callback checked the *v to be the first element in list to show the header. Now *v is the struct list_head pointer and it is checked for the head of the list.
The comment in /proc/diskstats .show handler is also updated not to forget it in the future.
---
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 ();
PATCH 5/15 Make crypto API use seq_list_xxx helpers
In reply to Pavel EmelianovSimple and stupid - just use the same code from another place in the kernel.
---
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);
Herbert Xu
maintainerRe: [PATCH 5/15] Make crypto API use seq_list_xxx helpers
Quoted 4 lines · Pavel Emelianov
Simple and stupid - just use the same code from another place in the kernel.
Signed-off-by Pavel Emelianov <[email protected]>
Ack.
Signature · 4 lines
Visit Openswan at http://www.openswan.org/
Email: Herbert Xu ~{PmV>HI~} <[email protected]>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txtPATCH 6/15 Make input layer use seq_list_xxx helpers
In reply to Pavel EmelianovThis is essentially just a renaming of the existing functions as the seq_list_start() and seq_list_next() copies already exist in the input.c file. Now we have them in the generic place.
---
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)
PATCH 7/15 Make ISDN CAPI use seq_list_xxx helpers
In reply to Pavel EmelianovThe similar code exists here and is called capi_driver_get_idx(). Use generic helpers now and remember to convert list_head to struct capi_driver in .show callback.
---
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 ; }
PATCH 8/15 Make /proc/misc use seq_list_xxx helpers
In reply to Pavel EmelianovSimple and stupid - just use the helpers.
Sorry for no maintainer in Cc: - I haven't found any.
---
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 ;
PATCH 9/15 Make /proc/modules use seq_list_xxx helpers
In reply to Pavel EmelianovHere there is not need even in .show callback altering. The original code passes list_head in *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)
PATCH 10/15 Make some network-related proc files use seq_list_xxx helpers
In reply to Pavel EmelianovThis includes /proc/net/protocols, /proc/net/rxrpc_calls and /proc/net/rxrpc_connections files.
All three need seq_list_start_head to show some header.
---
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/rxrpc/ar-proc.c +6 -42
83 lines not on this page · raw message
Re: [PATCH 10/15] Make some network-related proc files use seq_list_xxx helpers
From: Pavel Emelianov <[email protected]>
Date: Fri, 18 May 2007 13:53:13 +0400
Quoted 6 lines
This includes
/proc/net/protocols,/proc/net/rxrpc_callsand/proc/net/rxrpc_connectionsfiles.All three need
seq_list_start_headto show some header.Signed-off-by Pavel Emelianov <[email protected]>
PATCH 11/15 Make some netfilter-related proc files use seq_list_xxx helpers
In reply to Pavel EmelianovThis includes /proc/net/ip_conntrack_expect file.
Although struct nf_conntrack_expect has list_head as the very first element I use list_entry in .show callback to emphasize the fact that *v is the list_head pointer.
---
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)
PATCH 12/15 Make NFS client use seq_list_xxx helpers
In reply to Pavel EmelianovThis includes /proc/fs/nfsfs/servers and /proc/fs/nfsfs/volumes entries.
Both need to show the header and use the list_head.
---
fs/nfs/client.c +6 -48
@@ -1232,23 +1232,9 @@ static int nfs_server_list_open(struct i*/ static void *nfs_server_list_start (struct seq_file *m,loff_t *_pos) { -struct list_head *_p; -loff_t pos = *_pos; -/* lock the list against modification */ spin_lock (&nfs_client_lock); - -/* allow for the header line */ -if (!pos) -return SEQ_START_TOKEN ; - pos--; - -/* find the n'th element in the list */ -list_for_each (_p, &nfs_client_list) -if (!pos--) -break ; - -return _p != &nfs_client_list ? _p :NULL ; +return seq_list_start_head (&nfs_client_list, *_pos); }/*
@@ -1256,14 +1242,7 @@ static void *nfs_server_list_start(struc*/ static void *nfs_server_list_next (struct seq_file *p,void *v,loff_t *pos) { -struct list_head *_p; - - (*pos)++; - - _p = v; - _p = (v ==SEQ_START_TOKEN ) ? nfs_client_list.next : _p->next; - -return _p != &nfs_client_list ? _p :NULL ; +return seq_list_next (v, &nfs_client_list, pos); }/*
@@ -1282,7 +1261,7 @@ static int nfs_server_list_show(struct sstruct nfs_client *clp;/* display header on line 1 */ -if (v ==SEQ_START_TOKEN ) { +if (v == &nfs_client_list) {seq_puts (m,"NV SERVER PORT USE HOSTNAME\n" );return 0 ; }
@@ -1323,23 +1302,9 @@ static int nfs_volume_list_open(struct i*/ static void *nfs_volume_list_start (struct seq_file *m,loff_t *_pos) { -struct list_head *_p; -loff_t pos = *_pos; -/* lock the list against modification */ spin_lock (&nfs_client_lock); - -/* allow for the header line */ -if (!pos) -return SEQ_START_TOKEN ; - pos--; - -/* find the n'th element in the list */ -list_for_each (_p, &nfs_volume_list) -if (!pos--) -break ; - -return _p != &nfs_volume_list ? _p :NULL ; +return seq_list_start_head (&nfs_volume_list, *_pos); }/*
@@ -1347,14 +1312,7 @@ static void *nfs_volume_list_start(struc*/ static void *nfs_volume_list_next (struct seq_file *p,void *v,loff_t *pos) { -struct list_head *_p; - - (*pos)++; - - _p = v; - _p = (v ==SEQ_START_TOKEN ) ? nfs_volume_list.next : _p->next; - -return _p != &nfs_volume_list ? _p :NULL ; +return seq_list_next (v, &nfs_volume_list, pos); }/*
@@ -1375,7 +1333,7 @@ static int nfs_volume_list_show(struct schar dev[8 ], fsid[17 ];/* display header on line 1 */ -if (v ==SEQ_START_TOKEN ) { +if (v == &nfs_volume_list) {seq_puts (m,"NV SERVER PORT DEV FSID\n" );return 0 ; }
Re: [PATCH 12/15] Make NFS client use seq_list_xxx helpers
Quoted 6 lines · Pavel Emelianov
This includes
/proc/fs/nfsfs/serversand/proc/fs/nfsfs/volumesentries.Both need to show the header and use the
list_head.Signed-off-by Pavel Emelianov <[email protected]>
Quoted 108 lines
---
fs/nfs/client.c +6
-48@@ -1232,23 +1232,9 @@ static int nfs_server_list_open(struct i*/ static void *nfs_server_list_start (struct seq_file *m,loff_t *_pos) { -struct list_head *_p; -loff_t pos = *_pos; -/* lock the list against modification */ spin_lock (&nfs_client_lock); - -/* allow for the header line */ -if (!pos) -return SEQ_START_TOKEN ; - pos--; - -/* find the n'th element in the list */ -list_for_each (_p, &nfs_client_list) -if (!pos--) -break ; - -return _p != &nfs_client_list ? _p :NULL ; +return seq_list_start_head (&nfs_client_list, *_pos); }/* @@ -1256,14 +1242,7 @@ static void *nfs_server_list_start(struc*/ static void *nfs_server_list_next (struct seq_file *p,void *v,loff_t *pos) { -struct list_head *_p; - - (*pos)++; - - _p = v; - _p = (v ==SEQ_START_TOKEN ) ? nfs_client_list.next : _p->next; - -return _p != &nfs_client_list ? _p :NULL ; +return seq_list_next (v, &nfs_client_list, pos); }/* @@ -1282,7 +1261,7 @@ static int nfs_server_list_show(struct sstruct nfs_client *clp;/* display header on line 1 */ -if (v ==SEQ_START_TOKEN ) { +if (v == &nfs_client_list) {seq_puts (m,"NV SERVER PORT USE HOSTNAME\n" );return 0 ; }@@ -1323,23 +1302,9 @@ static int nfs_volume_list_open(struct i*/ static void *nfs_volume_list_start (struct seq_file *m,loff_t *_pos) { -struct list_head *_p; -loff_t pos = *_pos; -/* lock the list against modification */ spin_lock (&nfs_client_lock); - -/* allow for the header line */ -if (!pos) -return SEQ_START_TOKEN ; - pos--; - -/* find the n'th element in the list */ -list_for_each (_p, &nfs_volume_list) -if (!pos--) -break ; - -return _p != &nfs_volume_list ? _p :NULL ; +return seq_list_start_head (&nfs_volume_list, *_pos); }/* @@ -1347,14 +1312,7 @@ static void *nfs_volume_list_start(struc*/ static void *nfs_volume_list_next (struct seq_file *p,void *v,loff_t *pos) { -struct list_head *_p; - - (*pos)++; - - _p = v; - _p = (v ==SEQ_START_TOKEN ) ? nfs_volume_list.next : _p->next; - -return _p != &nfs_volume_list ? _p :NULL ; +return seq_list_next (v, &nfs_volume_list, pos); }/* @@ -1375,7 +1333,7 @@ static int nfs_volume_list_show(struct schar dev[8 ], fsid[17 ];/* display header on line 1 */ -if (v ==SEQ_START_TOKEN ) { +if (v == &nfs_volume_list) {seq_puts (m,"NV SERVER PORT DEV FSID\n" );return 0 ; }
PATCH 13/15 Make /proc/tty/drivers use seq_list_xxx helpers
In reply to Pavel EmelianovSimple and stupid like some previous ones. Just use new API.
---
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)
PATCH 14/15 Make /proc/slabinfo use seq_list_xxx helpers
In reply to Pavel EmelianovThis entry prints a header in .start callback. This is OK, but the more elegant solution would be to move this into the .show callback and use seq_list_start_head() in .start one.
I have left it as is in order to make the patch just switch to new API and noting more.
---
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)
PATCH 15/15 Make /proc/self/mounts(tats) use seq_list_xxx helpers
In reply to Pavel EmelianovOne more simple and stupid switching to the new API.
---
fs/namespace.c +5 -11
@@ -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;
@@ -481,7 +475,7 @@ struct seq_operations mounts_op = {static int show_vfsstat (struct seq_file *m,void *v) { -struct vfsmount *mnt = v; + struct vfsmount *mnt = list_entry(v, struct vfsmount, mnt_list);int err =0 ;/* device */