Loading Documentation/connector/connector.txt +44 −0 Original line number Diff line number Diff line Loading @@ -131,3 +131,47 @@ Netlink itself is not reliable protocol, that means that messages can be lost due to memory pressure or process' receiving queue overflowed, so caller is warned must be prepared. That is why struct cn_msg [main connector's message header] contains u32 seq and u32 ack fields. /*****************************************/ Userspace usage. /*****************************************/ 2.6.14 has a new netlink socket implementation, which by default does not allow to send data to netlink groups other than 1. So, if to use netlink socket (for example using connector) with different group number userspace application must subscribe to that group. It can be achieved by following pseudocode: s = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_CONNECTOR); l_local.nl_family = AF_NETLINK; l_local.nl_groups = 12345; l_local.nl_pid = 0; if (bind(s, (struct sockaddr *)&l_local, sizeof(struct sockaddr_nl)) == -1) { perror("bind"); close(s); return -1; } { int on = l_local.nl_groups; setsockopt(s, 270, 1, &on, sizeof(on)); } Where 270 above is SOL_NETLINK, and 1 is a NETLINK_ADD_MEMBERSHIP socket option. To drop multicast subscription one should call above socket option with NETLINK_DROP_MEMBERSHIP parameter which is defined as 0. 2.6.14 netlink code only allows to select a group which is less or equal to the maximum group number, which is used at netlink_kernel_create() time. In case of connector it is CN_NETLINK_USERS + 0xf, so if you want to use group number 12345, you must increment CN_NETLINK_USERS to that number. Additional 0xf numbers are allocated to be used by non-in-kernel users. Due to this limitation, group 0xffffffff does not work now, so one can not use add/remove connector's group notifications, but as far as I know, only cn_test.c test module used it. Some work in netlink area is still being done, so things can be changed in 2.6.15 timeframe, if it will happen, documentation will be updated for that kernel. arch/cris/arch-v32/kernel/smp.c +2 −0 Original line number Diff line number Diff line Loading @@ -15,6 +15,7 @@ #include <linux/kernel.h> #include <linux/cpumask.h> #include <linux/interrupt.h> #include <linux/module.h> #define IPI_SCHEDULE 1 #define IPI_CALL 2 Loading @@ -28,6 +29,7 @@ spinlock_t cris_atomic_locks[] = { [0 ... LOCK_COUNT - 1] = SPIN_LOCK_UNLOCKED}; /* CPU masks */ cpumask_t cpu_online_map = CPU_MASK_NONE; cpumask_t phys_cpu_present_map = CPU_MASK_NONE; EXPORT_SYMBOL(phys_cpu_present_map); /* Variables used during SMP boot */ volatile int cpu_now_booting = 0; Loading arch/sh/kernel/smp.c +3 −0 Original line number Diff line number Diff line Loading @@ -22,6 +22,7 @@ #include <linux/time.h> #include <linux/timex.h> #include <linux/sched.h> #include <linux/module.h> #include <asm/atomic.h> #include <asm/processor.h> Loading @@ -39,6 +40,8 @@ struct sh_cpuinfo cpu_data[NR_CPUS]; extern void per_cpu_trap_init(void); cpumask_t cpu_possible_map; EXPORT_SYMBOL(cpu_possible_map); cpumask_t cpu_online_map; static atomic_t cpus_booted = ATOMIC_INIT(0); Loading include/linux/cpumask.h +12 −0 Original line number Diff line number Diff line Loading @@ -392,4 +392,16 @@ extern cpumask_t cpu_present_map; #define for_each_online_cpu(cpu) for_each_cpu_mask((cpu), cpu_online_map) #define for_each_present_cpu(cpu) for_each_cpu_mask((cpu), cpu_present_map) /* Find the highest possible smp_processor_id() */ static inline unsigned int highest_possible_processor_id(void) { unsigned int cpu, highest = 0; for_each_cpu_mask(cpu, cpu_possible_map) highest = cpu; return highest; } #endif /* __LINUX_CPUMASK_H */ net/bridge/netfilter/ebtables.c +17 −10 Original line number Diff line number Diff line Loading @@ -26,6 +26,7 @@ #include <linux/spinlock.h> #include <asm/uaccess.h> #include <linux/smp.h> #include <linux/cpumask.h> #include <net/sock.h> /* needed for logical [in,out]-dev filtering */ #include "../br_private.h" Loading Loading @@ -823,10 +824,11 @@ static int translate_table(struct ebt_replace *repl, /* this will get free'd in do_replace()/ebt_register_table() if an error occurs */ newinfo->chainstack = (struct ebt_chainstack **) vmalloc(num_possible_cpus() * sizeof(struct ebt_chainstack)); vmalloc((highest_possible_processor_id()+1) * sizeof(struct ebt_chainstack)); if (!newinfo->chainstack) return -ENOMEM; for (i = 0; i < num_possible_cpus(); i++) { for_each_cpu(i) { newinfo->chainstack[i] = vmalloc(udc_cnt * sizeof(struct ebt_chainstack)); if (!newinfo->chainstack[i]) { Loading Loading @@ -896,8 +898,11 @@ static void get_counters(struct ebt_counter *oldcounters, /* counters of cpu 0 */ memcpy(counters, oldcounters, sizeof(struct ebt_counter) * nentries); /* add other counters to those of cpu 0 */ for (cpu = 1; cpu < num_possible_cpus(); cpu++) { for_each_cpu(cpu) { if (cpu == 0) continue; counter_base = COUNTER_BASE(oldcounters, nentries, cpu); for (i = 0; i < nentries; i++) { counters[i].pcnt += counter_base[i].pcnt; Loading Loading @@ -929,7 +934,8 @@ static int do_replace(void __user *user, unsigned int len) BUGPRINT("Entries_size never zero\n"); return -EINVAL; } countersize = COUNTER_OFFSET(tmp.nentries) * num_possible_cpus(); countersize = COUNTER_OFFSET(tmp.nentries) * (highest_possible_processor_id()+1); newinfo = (struct ebt_table_info *) vmalloc(sizeof(struct ebt_table_info) + countersize); if (!newinfo) Loading Loading @@ -1022,7 +1028,7 @@ static int do_replace(void __user *user, unsigned int len) vfree(table->entries); if (table->chainstack) { for (i = 0; i < num_possible_cpus(); i++) for_each_cpu(i) vfree(table->chainstack[i]); vfree(table->chainstack); } Loading @@ -1040,7 +1046,7 @@ static int do_replace(void __user *user, unsigned int len) vfree(counterstmp); /* can be initialized in translate_table() */ if (newinfo->chainstack) { for (i = 0; i < num_possible_cpus(); i++) for_each_cpu(i) vfree(newinfo->chainstack[i]); vfree(newinfo->chainstack); } Loading Loading @@ -1132,7 +1138,8 @@ int ebt_register_table(struct ebt_table *table) return -EINVAL; } countersize = COUNTER_OFFSET(table->table->nentries) * num_possible_cpus(); countersize = COUNTER_OFFSET(table->table->nentries) * (highest_possible_processor_id()+1); newinfo = (struct ebt_table_info *) vmalloc(sizeof(struct ebt_table_info) + countersize); ret = -ENOMEM; Loading Loading @@ -1186,7 +1193,7 @@ int ebt_register_table(struct ebt_table *table) up(&ebt_mutex); free_chainstack: if (newinfo->chainstack) { for (i = 0; i < num_possible_cpus(); i++) for_each_cpu(i) vfree(newinfo->chainstack[i]); vfree(newinfo->chainstack); } Loading @@ -1209,7 +1216,7 @@ void ebt_unregister_table(struct ebt_table *table) up(&ebt_mutex); vfree(table->private->entries); if (table->private->chainstack) { for (i = 0; i < num_possible_cpus(); i++) for_each_cpu(i) vfree(table->private->chainstack[i]); vfree(table->private->chainstack); } Loading Loading
Documentation/connector/connector.txt +44 −0 Original line number Diff line number Diff line Loading @@ -131,3 +131,47 @@ Netlink itself is not reliable protocol, that means that messages can be lost due to memory pressure or process' receiving queue overflowed, so caller is warned must be prepared. That is why struct cn_msg [main connector's message header] contains u32 seq and u32 ack fields. /*****************************************/ Userspace usage. /*****************************************/ 2.6.14 has a new netlink socket implementation, which by default does not allow to send data to netlink groups other than 1. So, if to use netlink socket (for example using connector) with different group number userspace application must subscribe to that group. It can be achieved by following pseudocode: s = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_CONNECTOR); l_local.nl_family = AF_NETLINK; l_local.nl_groups = 12345; l_local.nl_pid = 0; if (bind(s, (struct sockaddr *)&l_local, sizeof(struct sockaddr_nl)) == -1) { perror("bind"); close(s); return -1; } { int on = l_local.nl_groups; setsockopt(s, 270, 1, &on, sizeof(on)); } Where 270 above is SOL_NETLINK, and 1 is a NETLINK_ADD_MEMBERSHIP socket option. To drop multicast subscription one should call above socket option with NETLINK_DROP_MEMBERSHIP parameter which is defined as 0. 2.6.14 netlink code only allows to select a group which is less or equal to the maximum group number, which is used at netlink_kernel_create() time. In case of connector it is CN_NETLINK_USERS + 0xf, so if you want to use group number 12345, you must increment CN_NETLINK_USERS to that number. Additional 0xf numbers are allocated to be used by non-in-kernel users. Due to this limitation, group 0xffffffff does not work now, so one can not use add/remove connector's group notifications, but as far as I know, only cn_test.c test module used it. Some work in netlink area is still being done, so things can be changed in 2.6.15 timeframe, if it will happen, documentation will be updated for that kernel.
arch/cris/arch-v32/kernel/smp.c +2 −0 Original line number Diff line number Diff line Loading @@ -15,6 +15,7 @@ #include <linux/kernel.h> #include <linux/cpumask.h> #include <linux/interrupt.h> #include <linux/module.h> #define IPI_SCHEDULE 1 #define IPI_CALL 2 Loading @@ -28,6 +29,7 @@ spinlock_t cris_atomic_locks[] = { [0 ... LOCK_COUNT - 1] = SPIN_LOCK_UNLOCKED}; /* CPU masks */ cpumask_t cpu_online_map = CPU_MASK_NONE; cpumask_t phys_cpu_present_map = CPU_MASK_NONE; EXPORT_SYMBOL(phys_cpu_present_map); /* Variables used during SMP boot */ volatile int cpu_now_booting = 0; Loading
arch/sh/kernel/smp.c +3 −0 Original line number Diff line number Diff line Loading @@ -22,6 +22,7 @@ #include <linux/time.h> #include <linux/timex.h> #include <linux/sched.h> #include <linux/module.h> #include <asm/atomic.h> #include <asm/processor.h> Loading @@ -39,6 +40,8 @@ struct sh_cpuinfo cpu_data[NR_CPUS]; extern void per_cpu_trap_init(void); cpumask_t cpu_possible_map; EXPORT_SYMBOL(cpu_possible_map); cpumask_t cpu_online_map; static atomic_t cpus_booted = ATOMIC_INIT(0); Loading
include/linux/cpumask.h +12 −0 Original line number Diff line number Diff line Loading @@ -392,4 +392,16 @@ extern cpumask_t cpu_present_map; #define for_each_online_cpu(cpu) for_each_cpu_mask((cpu), cpu_online_map) #define for_each_present_cpu(cpu) for_each_cpu_mask((cpu), cpu_present_map) /* Find the highest possible smp_processor_id() */ static inline unsigned int highest_possible_processor_id(void) { unsigned int cpu, highest = 0; for_each_cpu_mask(cpu, cpu_possible_map) highest = cpu; return highest; } #endif /* __LINUX_CPUMASK_H */
net/bridge/netfilter/ebtables.c +17 −10 Original line number Diff line number Diff line Loading @@ -26,6 +26,7 @@ #include <linux/spinlock.h> #include <asm/uaccess.h> #include <linux/smp.h> #include <linux/cpumask.h> #include <net/sock.h> /* needed for logical [in,out]-dev filtering */ #include "../br_private.h" Loading Loading @@ -823,10 +824,11 @@ static int translate_table(struct ebt_replace *repl, /* this will get free'd in do_replace()/ebt_register_table() if an error occurs */ newinfo->chainstack = (struct ebt_chainstack **) vmalloc(num_possible_cpus() * sizeof(struct ebt_chainstack)); vmalloc((highest_possible_processor_id()+1) * sizeof(struct ebt_chainstack)); if (!newinfo->chainstack) return -ENOMEM; for (i = 0; i < num_possible_cpus(); i++) { for_each_cpu(i) { newinfo->chainstack[i] = vmalloc(udc_cnt * sizeof(struct ebt_chainstack)); if (!newinfo->chainstack[i]) { Loading Loading @@ -896,8 +898,11 @@ static void get_counters(struct ebt_counter *oldcounters, /* counters of cpu 0 */ memcpy(counters, oldcounters, sizeof(struct ebt_counter) * nentries); /* add other counters to those of cpu 0 */ for (cpu = 1; cpu < num_possible_cpus(); cpu++) { for_each_cpu(cpu) { if (cpu == 0) continue; counter_base = COUNTER_BASE(oldcounters, nentries, cpu); for (i = 0; i < nentries; i++) { counters[i].pcnt += counter_base[i].pcnt; Loading Loading @@ -929,7 +934,8 @@ static int do_replace(void __user *user, unsigned int len) BUGPRINT("Entries_size never zero\n"); return -EINVAL; } countersize = COUNTER_OFFSET(tmp.nentries) * num_possible_cpus(); countersize = COUNTER_OFFSET(tmp.nentries) * (highest_possible_processor_id()+1); newinfo = (struct ebt_table_info *) vmalloc(sizeof(struct ebt_table_info) + countersize); if (!newinfo) Loading Loading @@ -1022,7 +1028,7 @@ static int do_replace(void __user *user, unsigned int len) vfree(table->entries); if (table->chainstack) { for (i = 0; i < num_possible_cpus(); i++) for_each_cpu(i) vfree(table->chainstack[i]); vfree(table->chainstack); } Loading @@ -1040,7 +1046,7 @@ static int do_replace(void __user *user, unsigned int len) vfree(counterstmp); /* can be initialized in translate_table() */ if (newinfo->chainstack) { for (i = 0; i < num_possible_cpus(); i++) for_each_cpu(i) vfree(newinfo->chainstack[i]); vfree(newinfo->chainstack); } Loading Loading @@ -1132,7 +1138,8 @@ int ebt_register_table(struct ebt_table *table) return -EINVAL; } countersize = COUNTER_OFFSET(table->table->nentries) * num_possible_cpus(); countersize = COUNTER_OFFSET(table->table->nentries) * (highest_possible_processor_id()+1); newinfo = (struct ebt_table_info *) vmalloc(sizeof(struct ebt_table_info) + countersize); ret = -ENOMEM; Loading Loading @@ -1186,7 +1193,7 @@ int ebt_register_table(struct ebt_table *table) up(&ebt_mutex); free_chainstack: if (newinfo->chainstack) { for (i = 0; i < num_possible_cpus(); i++) for_each_cpu(i) vfree(newinfo->chainstack[i]); vfree(newinfo->chainstack); } Loading @@ -1209,7 +1216,7 @@ void ebt_unregister_table(struct ebt_table *table) up(&ebt_mutex); vfree(table->private->entries); if (table->private->chainstack) { for (i = 0; i < num_possible_cpus(); i++) for_each_cpu(i) vfree(table->private->chainstack[i]); vfree(table->private->chainstack); } Loading