/* * netsniff-ng - the packet sniffing beast * Copyright 2009, 2010 Daniel Borkmann. * Subject to the GPL, version 2. */ #include #include "hash.h" #include "oui.h" #include "str.h" #include "protos.h" #include "pkt_buff.h" #include "dissector.h" #include "dissector_eth.h" #include "xmalloc.h" struct hash_table eth_lay2; struct hash_table eth_lay3; static struct hash_table eth_ether_types; static struct hash_table eth_ports_udp; static struct hash_table eth_ports_tcp; struct port { unsigned int id; char *port; struct port *next; }; #define __do_lookup_inline(id, struct_name, hash_ptr, struct_member) \ ({ \ struct struct_name *entry = lookup_hash(id, hash_ptr); \ \ while (entry && id != entry->id) \ entry = entry->next; \ \ (entry && id == entry->id ? entry->struct_member : NULL); \ }) char *lookup_port_udp(unsigned int id) { return __do_lookup_inline(id, port, ð_ports_udp, port); } char *lookup_port_tcp(unsigned int id) { return __do_lookup_inline(id, port, ð_ports_tcp, port); } char *lookup_ether_type(unsigned int id) { return __do_lookup_inline(id, port, ð_ether_types, port); } #ifdef HAVE_DISSECTOR_PROTOS static inline void dissector_init_entry(int type) { dissector_set_print_type(ðernet_ops, type); } static inline void dissector_init_exit(int type) { dissector_set_print_type(&none_ops, type); } static void dissector_init_layer_2(int type) { init_hash(ð_lay2); INSERT_HASH_PROTOS(arp_ops, eth_lay2); INSERT_HASH_PROTOS(lldp_ops, eth_lay2); INSERT_HASH_PROTOS(vlan_ops, eth_lay2); INSERT_HASH_PROTOS(ipv4_ops, eth_lay2); INSERT_HASH_PROTOS(ipv6_ops, eth_lay2); INSERT_HASH_PROTOS(QinQ_ops, eth_lay2); INSERT_HASH_PROTOS(mpls_uc_ops, eth_lay2); for_each_hash_int(ð_lay2, dissector_set_print_type, type); } static void dissector_init_layer_3(int type) { init_hash(ð_lay3); INSERT_HASH_PROTOS(icmpv4_ops, eth_lay3); INSERT_HASH_PROTOS(icmpv6_ops, eth_lay3); INSERT_HASH_PROTOS(igmp_ops, eth_lay3); INSERT_HASH_PROTOS(ip_auth_ops, eth_lay3); INSERT_HASH_PROTOS(ip_esp_ops, eth_lay3); INSERT_HASH_PROTOS(ipv6_dest_opts_ops, eth_lay3); INSERT_HASH_PROTOS(ipv6_fragm_ops, eth_lay3); INSERT_HASH_PROTOS(ipv6_hop_by_hop_ops, eth_lay3); INSERT_HASH_PROTOS(ipv6_in_ipv4_ops, eth_lay3); INSERT_HASH_PROTOS(ipv6_mobility_ops, eth_lay3); INSERT_HASH_PROTOS(ipv6_no_next_header_ops, eth_lay3); INSERT_HASH_PROTOS(ipv6_routing_ops, eth_lay3); INSERT_HASH_PROTOS(tcp_ops, eth_lay3); INSERT_HASH_PROTOS(udp_ops, eth_lay3); for_each_hash_int(ð_lay3, dissector_set_print_type, type); } #else static inline void dissector_init_entry(int type __maybe_unused) {} static inline void dissector_init_exit(int type __maybe_unused) {} static void dissector_init_layer_2(int type __maybe_unused) {} static void dissector_init_layer_3(int type __maybe_unused) {} #endif enum ports { PORTS_UDP, PORTS_TCP, PORTS_ETHER, }; static void dissector_init_ports(enum ports which) { FILE *fp; char buff[128], *ptr, *file, *end; struct hash_table *table; struct port *p; void **pos; switch (which) { case PORTS_UDP: file = PREFIX_STRING "/etc/netsniff-ng/udp.conf"; table = ð_ports_udp; break; case PORTS_TCP: file = PREFIX_STRING "/etc/netsniff-ng/tcp.conf"; table = ð_ports_tcp; break; case PORTS_ETHER: file = PREFIX_STRING "/etc/netsniff-ng/ether.conf"; table = ð_ether_types; break; default: bug(); } fp = fopen(file, "r"); if (!fp) panic("No %s found!\n", file); memset(buff, 0, sizeof(buff)); while (fgets(buff, sizeof(buff), fp) != NULL) { buff[sizeof(buff) - 1] = 0; ptr = buff; p = xmalloc(sizeof(*p)); p->id = strtol(ptr, &end, 0); /* not a valid line, skip */ if (p->id == 0 && end == ptr) { xfree(p); continue; } ptr = strstr(buff, ", "); /* likewise */ if (!ptr) { xfree(p); continue; } ptr += strlen(", "); ptr = strtrim_right(ptr, '\n'); ptr = strtrim_right(ptr, ' '); p->port = xstrdup(ptr); p->next = NULL; pos = insert_hash(p->id, p, table); if (pos) { p->next = *pos; *pos = p; } memset(buff, 0, sizeof(buff)); } fclose(fp); } static int dissector_cleanup_ports(void *ptr) { struct port *tmp, *p = ptr; if (!ptr) return 0; while ((tmp = p->next)) { xfree(p->port); xfree(p); p = tmp; } xfree(p->port); xfree(p); return 0; } void dissector_init_ethernet(int fnttype) { dissector_init_entry(fnttype); dissector_init_layer_2(fnttype); dissector_init_layer_3(fnttype); dissector_init_exit(fnttype); #ifdef __WITH_PROTOS dissector_init_oui(); #endif dissector_init_ports(PORTS_UDP); dissector_init_ports(PORTS_TCP); dissector_init_ports(PORTS_ETHER); } void dissector_cleanup_ethernet(void) { free_hash(ð_lay2); free_hash(ð_lay3); for_each_hash(ð_ether_types, dissector_cleanup_ports); for_each_hash(ð_ports_udp, dissector_cleanup_ports); for_each_hash(ð_ports_tcp, dissector_cleanup_ports); free_hash(ð_ether_types); free_hash(ð_ports_udp); free_hash(ð_ports_tcp); #ifdef __WITH_PROTOS dissector_cleanup_oui(); #endif } t-next.git/patch/Documentation/devicetree/bindings?id=8e018c21da3febb558586b48c8db0d6d66cb6593'>patch) tree70d8d62900570c7cade6a7554236f0014ee1e43e /Documentation/devicetree/bindings parent86a1679860babbacd61fc1e8c0c0f43641d5860d (diff)
raid5-cache: fix a deadlock in superblock write
There is a potential deadlock in superblock write. Discard could zero data, so before discard we must make sure superblock is updated to new log tail. Updating superblock (either directly call md_update_sb() or depend on md thread) must hold reconfig mutex. On the other hand, raid5_quiesce is called with reconfig_mutex hold. The first step of raid5_quiesce() is waitting for all IO finish, hence waitting for reclaim thread, while reclaim thread is calling this function and waitting for reconfig mutex. So there is a deadlock. We workaround this issue with a trylock. The downside of the solution is we could miss discard if we can't take reconfig mutex. But this should happen rarely (mainly in raid array stop), so miss discard shouldn't be a big problem. Cc: NeilBrown <neilb@suse.com> Signed-off-by: Shaohua Li <shli@fb.com>
Diffstat (limited to 'Documentation/devicetree/bindings')