This patch adds a dm-netlink skeleton support to the Makefile, and the dm directory. This base dm-netlink file only contains the mempool support. Signed-off-by: Mike Anderson drivers/md/Kconfig | 5 + drivers/md/Makefile | 4 + drivers/md/dm-netlink.c | 181 ++++++++++++++++++++++++++++++++++++++++++++++++ drivers/md/dm-netlink.h | 31 ++++++++ drivers/md/dm.c | 2 include/linux/netlink.h | 1 6 files changed, 224 insertions(+) Index: linux-2.6.16-rc5/drivers/md/dm-netlink.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ linux-2.6.16-rc5/drivers/md/dm-netlink.c 2006-03-15 23:31:13.000000000 +0000 @@ -0,0 +1,181 @@ +/* + * Device Mapper Netlink Support (dm-netlink) + * + * Copyright (C) 2005 IBM Corporation + * Author: Mike Anderson + * skb mempool derived from drivers/scsi/scsi_transport_iscsi.c + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ +#include +#include +#include +#include +#include +#include +#include +#include "dm-netlink.h" + +#define MIN_EVENT_SKBS 16 +#define HIWAT_EVENT_SKBS 32 +#define EVENT_SKB_SIZE NLMSG_SPACE(128) + +struct mp_zone { + mempool_t *pool; + kmem_cache_t *cache; + int allocated; + int size; + int hiwat; + struct list_head freequeue; + spinlock_t freelock; +}; + +static struct mp_zone z_dm_event; + +static void* mp_zone_alloc_dm_event(gfp_t gfp_mask, + void *pool_data) +{ + struct dm_event *evt; + struct mp_zone *zone = pool_data; + + evt = kmem_cache_alloc(zone->cache, gfp_mask); + if (!evt) + goto out; + + evt->skb = alloc_skb(zone->size, gfp_mask); + if (!evt->skb) + goto cache_out; + return evt; + +cache_out: + kmem_cache_free(zone->cache, evt); +out: + return NULL; +} + +static void mp_zone_free_dm_event(void *element, void *pool_data) +{ + struct dm_event *evt = element; + struct mp_zone *zone = pool_data; + + kfree_skb(evt->skb); + kmem_cache_free(zone->cache, evt); +} + +static void +mp_zone_complete(struct mp_zone *zone, int release_pid) +{ + unsigned long flags; + struct dm_event *evt, *n; + struct sk_buff *skb; + struct nlmsghdr *nlh; + + spin_lock_irqsave(&zone->freelock, flags); + if (zone->allocated) { + list_for_each_entry_safe(evt, n, &zone->freequeue, zlist) { + skb = evt->skb; + + if (release_pid) { + nlh = (struct nlmsghdr *)skb->data; + if (nlh->nlmsg_pid == release_pid) { + if (skb->next && skb->sk) + skb_unlink(skb, + &skb->sk->sk_receive_queue); + atomic_set(&skb->users, 1); + } + } + + if (!skb_shared(skb)) { + list_del(&evt->zlist); + --zone->allocated; + skb_orphan(skb); + + /* Init in case sent to pool */ + skb->len = 0; + skb->tail = skb->head; + + mempool_free(evt, zone->pool); + } + } + } + spin_unlock_irqrestore(&zone->freelock, flags); +} + +static int mp_zone_init(struct mp_zone *zp, unsigned size, + int min_nr, unsigned hiwat) +{ + zp->size = size; + zp->hiwat = hiwat; + zp->allocated = 0; + INIT_LIST_HEAD(&zp->freequeue); + spin_lock_init(&zp->freelock); + + zp->pool = mempool_create(min_nr, mp_zone_alloc_dm_event, + mp_zone_free_dm_event, zp); + if (!zp->pool) + return -ENOMEM; + + return 0; +} + +static struct dm_event* mp_zone_get_dm_event(struct mp_zone *zone) +{ + struct dm_event *evt; + unsigned long flags; + + /* Check for ones we can complete before we alloc */ + mp_zone_complete(zone, 0); + + evt = mempool_alloc(zone->pool, GFP_ATOMIC); + if (evt) { + skb_get(evt->skb); + INIT_LIST_HEAD(&evt->zlist); + spin_lock_irqsave(&z_dm_event.freelock, flags); + list_add(&evt->zlist, &z_dm_event.freequeue); + ++zone->allocated; + spin_unlock_irqrestore(&z_dm_event.freelock, flags); + } + return evt; +} + +int __init dm_netlink_init(void) +{ + int err; + + z_dm_event.cache = kmem_cache_create("dm_events", + sizeof(struct dm_event), 0, 0, NULL, NULL); + if (!z_dm_event.cache) + goto out; + + err = mp_zone_init(&z_dm_event, EVENT_SKB_SIZE, + MIN_EVENT_SKBS, HIWAT_EVENT_SKBS); + if (err) + goto cache_out; + + printk(KERN_DEBUG "dm-netlink version 0.0.5 loaded\n"); + + return err; +cache_out: + kmem_cache_destroy(z_dm_event.cache); +out: + return err; +} + +void dm_netlink_exit(void) +{ + mempool_destroy(z_dm_event.pool); + kmem_cache_destroy(z_dm_event.cache); +} Index: linux-2.6.16-rc5/include/linux/netlink.h =================================================================== --- linux-2.6.16-rc5.orig/include/linux/netlink.h 2006-03-12 18:27:47.000000000 +0000 +++ linux-2.6.16-rc5/include/linux/netlink.h 2006-03-15 23:31:13.000000000 +0000 @@ -21,6 +21,7 @@ #define NETLINK_DNRTMSG 14 /* DECnet routing messages */ #define NETLINK_KOBJECT_UEVENT 15 /* Kernel messages to userspace */ #define NETLINK_GENERIC 16 +#define NETLINK_DM 17 /* Device Mapper */ #define MAX_LINKS 32 Index: linux-2.6.16-rc5/drivers/md/Makefile =================================================================== --- linux-2.6.16-rc5.orig/drivers/md/Makefile 2006-03-12 18:27:47.000000000 +0000 +++ linux-2.6.16-rc5/drivers/md/Makefile 2006-03-15 23:31:13.000000000 +0000 @@ -46,6 +46,10 @@ ifeq ($(CONFIG_ALTIVEC),y) altivec_flags := -maltivec -mabi=altivec endif +ifeq ($(CONFIG_DM_NETLINK_EVENT),y) +dm-mod-objs += dm-netlink.o +endif + targets += raid6int1.c $(obj)/raid6int1.c: UNROLL := 1 $(obj)/raid6int1.c: $(src)/raid6int.uc $(src)/unroll.pl FORCE Index: linux-2.6.16-rc5/drivers/md/Kconfig =================================================================== --- linux-2.6.16-rc5.orig/drivers/md/Kconfig 2006-03-12 18:27:47.000000000 +0000 +++ linux-2.6.16-rc5/drivers/md/Kconfig 2006-03-15 23:31:13.000000000 +0000 @@ -236,5 +236,10 @@ config DM_MULTIPATH_EMC ---help--- Multipath support for EMC CX/AX series hardware. +config DM_NETLINK_EVENT + bool "DM netlink events (EXPERIMENTAL)" + depends on BLK_DEV_DM && EXPERIMENTAL + ---help--- + Generate netlink events for DM events. endmenu Index: linux-2.6.16-rc5/drivers/md/dm-netlink.h =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ linux-2.6.16-rc5/drivers/md/dm-netlink.h 2006-03-15 23:31:13.000000000 +0000 @@ -0,0 +1,31 @@ +/* + * Device Mapper Netlink Support + * + * Copyright (C) 2005 IBM Corporation + * Author: Mike Anderson + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ +#ifndef DM_NETLINK_H +#define DM_NETLINK_H + +struct dm_event { + struct list_head zlist; + struct list_head elist; + struct sk_buff *skb; +}; + +#endif /* DM_NETLINK_H */ Index: linux-2.6.16-rc5/drivers/md/dm.c =================================================================== --- linux-2.6.16-rc5.orig/drivers/md/dm.c 2006-03-15 23:31:07.000000000 +0000 +++ linux-2.6.16-rc5/drivers/md/dm.c 2006-03-15 23:31:13.000000000 +0000 @@ -171,6 +171,7 @@ int (*_inits[])(void) __initdata = { dm_linear_init, dm_stripe_init, dm_interface_init, + dm_netlink_init, }; void (*_exits[])(void) = { @@ -179,6 +180,7 @@ void (*_exits[])(void) = { dm_linear_exit, dm_stripe_exit, dm_interface_exit, + dm_netlink_exit, }; static int __init dm_init(void)