Name: Automagic Proc Entry Creation Author: Rusty Russell Status: Tested on 2.5.71-bk2 Use the module_init_exit to write a "module_proc_net" macro, as an example. Index: linux-2.6.10-rc2-bk11-Module/net/ipv4/netfilter/ip_tables.c =================================================================== --- linux-2.6.10-rc2-bk11-Module.orig/net/ipv4/netfilter/ip_tables.c 2004-11-29 07:48:58.000000000 +1100 +++ linux-2.6.10-rc2-bk11-Module/net/ipv4/netfilter/ip_tables.c 2004-11-29 17:35:26.504257608 +1100 @@ -1740,7 +1740,6 @@ .checkentry = &icmp_checkentry, }; -#ifdef CONFIG_PROC_FS static inline int print_name(const char *i, off_t start_offset, char *buffer, int length, off_t *pos, unsigned int *count) @@ -1820,12 +1819,9 @@ return pos; } -static struct { char *name; get_info_t *get_info; } ipt_proc_entry[] = -{ { "ip_tables_names", ipt_get_tables }, - { "ip_tables_targets", ipt_get_targets }, - { "ip_tables_matches", ipt_get_matches }, - { NULL, NULL} }; -#endif /*CONFIG_PROC_FS*/ +module_proc_net("ip_tables_names", ipt_get_tables); +module_proc_net("ip_tables_targets", ipt_get_targets); +module_proc_net("ip_tables_matches", ipt_get_matches); static int __init init(void) { @@ -1847,25 +1843,6 @@ return ret; } -#ifdef CONFIG_PROC_FS - { - struct proc_dir_entry *proc; - int i; - - for (i = 0; ipt_proc_entry[i].name; i++) { - proc = proc_net_create(ipt_proc_entry[i].name, 0, - ipt_proc_entry[i].get_info); - if (!proc) { - while (--i >= 0) - proc_net_remove(ipt_proc_entry[i].name); - nf_unregister_sockopt(&ipt_sockopts); - return -ENOMEM; - } - proc->owner = THIS_MODULE; - } - } -#endif - printk("ip_tables: (C) 2000-2002 Netfilter core team\n"); return 0; } @@ -1873,13 +1850,6 @@ static void __exit fini(void) { nf_unregister_sockopt(&ipt_sockopts); -#ifdef CONFIG_PROC_FS - { - int i; - for (i = 0; ipt_proc_entry[i].name; i++) - proc_net_remove(ipt_proc_entry[i].name); - } -#endif } EXPORT_SYMBOL(ipt_register_table); Index: linux-2.6.10-rc2-bk11-Module/include/linux/proc_fs.h =================================================================== --- linux-2.6.10-rc2-bk11-Module.orig/include/linux/proc_fs.h 2004-11-16 15:30:07.000000000 +1100 +++ linux-2.6.10-rc2-bk11-Module/include/linux/proc_fs.h 2004-11-29 17:24:09.903116616 +1100 @@ -4,6 +4,7 @@ #include #include #include +#include #include /* @@ -189,6 +190,20 @@ remove_proc_entry(name,proc_net); } +#define module_proc_net(name, fn) \ +static int __cat(_proc_net_init,fn)(void) \ +{ \ + struct proc_dir_entry *proc = proc_net_create(name, 0, fn); \ + if (!proc) \ + return -EINVAL; \ + proc->owner = THIS_MODULE; \ + return 0; \ +} \ +static void __cat(_proc_net_exit,fn)(void) \ +{ \ + proc_net_remove(name); \ +} \ +module_init_exit(__cat(_proc_net_init,fn), __cat(_proc_net_exit,fn)) #else #define proc_root_driver NULL @@ -225,6 +240,10 @@ extern struct proc_dir_entry proc_root; +/* Check type and stop gcc from complaining about unused function, but + * allow gcc 3.3+ to discard it. */ +#define module_proc_net(name, fn) \ +static inline get_info_t *__unique_id(test_fntype)(void) { return fn; } #endif /* CONFIG_PROC_FS */ #if !defined(CONFIG_PROC_KCORE) Index: linux-2.6.10-rc2-bk11-Module/net/ipv4/netfilter/arp_tables.c =================================================================== --- linux-2.6.10-rc2-bk11-Module.orig/net/ipv4/netfilter/arp_tables.c 2004-11-16 15:30:12.000000000 +1100 +++ linux-2.6.10-rc2-bk11-Module/net/ipv4/netfilter/arp_tables.c 2004-11-29 17:24:09.904116464 +1100 @@ -1243,7 +1243,6 @@ .get = do_arpt_get_ctl, }; -#ifdef CONFIG_PROC_FS static inline int print_name(const struct arpt_table *t, off_t start_offset, char *buffer, int length, off_t *pos, unsigned int *count) @@ -1278,7 +1277,8 @@ *start=(char *)((unsigned long)count-offset); return pos; } -#endif /*CONFIG_PROC_FS*/ + +module_proc_net("arp_tables_names", arpt_get_tables); static int __init init(void) { @@ -1297,19 +1297,6 @@ return ret; } -#ifdef CONFIG_PROC_FS - { - struct proc_dir_entry *proc; - - proc = proc_net_create("arp_tables_names", 0, arpt_get_tables); - if (!proc) { - nf_unregister_sockopt(&arpt_sockopts); - return -ENOMEM; - } - proc->owner = THIS_MODULE; - } -#endif - printk("arp_tables: (C) 2002 David S. Miller\n"); return 0; }