Answer assumes Linux kernel version 3.11 or 4.2, probably valid for many others. Answer current as of September 2015.
Whether callbacks may be concurrent or not is a configurable property of the struct genl_family at registration time, but if not explicitly specified, is probably defaulted to off. This is due to 1) The presence of a bool parallel_ops member in struct genl_family, and 2) Uninitialized members of a static-duration struct being defaulted to 0 in C.
On reception of a Netlink message, eventually the function genl_rcv_msg() is called, which determines the message's GeNetlink family and conditions on parallel_ops to decide whether or not to lock down the global genl_mutex.
static int genl_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh) { struct genl_family *family; int err; family = genl_family_find_byid(nlh->nlmsg_type); if (family == NULL) return -ENOENT; if (!family->parallel_ops) genl_lock(); err = genl_family_rcv_msg(family, skb, nlh); if (!family->parallel_ops) genl_unlock(); return err; }
Once genl_family_rcv_msg() is invoked (protected or unprotected by the mutex), the actual callback is invoked here.
struct genl_familycontains abool parallel_ops. Inlinux-3.11.10-21/net/netlink/genetlink.c:674or nearabouts, ingenl_rcv_msg(), if that flag is not set, then a global mutex is locked, the request is processed, and the global mutex unlocked. If it is set then this locking doesn't happen.genetlink.h, too. That should cover both multiple callbacks and single callback concurrency. Implementation you are referring seems to be proving that. You should make that an answer.