dm-netlink events
Subsystems (4)
cover dm-netlink events
This is an update of my previous patch to add netlink event support to dm multipath. I have moved the dm netlink support out of a hardware handler and into a dm-netlink support file. I have changed the event messages to use netlink attributes which should allow for more flexibility in event message content over time.
This patch series adds a file called dm-netlink to the drivers/md directory to provide netlink support for dm events.
The skb mempool in this patch is derived / copied from drivers/scsi/scsi_transport_iscsi.c.
This patch series contains:
1 Core dm netlink support (dm-netlink).
2 Calls to dm-netlink for path failure / reinstate events. 3 A sample user space program to receive / display events (dm_nld).
I have ran path failure testing on a small config.
I ran the sample program as a 32 bit and 64 bit app against a 64 bit kernel.
Currently on path failures the blkerr is hard coded until that error support is complete.
Example out:
1.) Path failure.
Msg Type: 17 Recevied
Event Type: 1 Version: 6
[Event]: SEQNUM: 7, Time: Tue Nov 29 21:50:47 2005, DMNAME: 8:160, BLKERR:0x5a5a5a5a
2.) Path reinstate
Msg Type: 17 Recevied
Event Type: 2 Version: 6
[Event]: SEQNUM: 12, Time: Tue Nov 29 21:51:57 2005, DMNAME: 8:48
-andmike
--
Michael Anderson
[email protected]
RFC PATCH 1/4 dm-netlink skeleton support
This patch adds a dm-netlink skeleton support to the Makefile, Kconfig, and the dm directory. This base dm-netlink file only contains the mempool support.
drivers/md/Kconfig | 6 ++ drivers/md/Makefile | 3 + drivers/md/dm-netlink.c | 144 ++++++++++++++++++++++++++++++++++++++++++++++++ include/linux/netlink.h | 1 4 files changed, 154 insertions(+)
drivers/md/dm-netlink.c new file +144 -0
@@ -0,0 +1,144 @@ +/* +* Device Mapper Netlink Support (dm-netlink) +* +* Copyright (C) 2005 IBM Corporation +* Author: Mike Anderson <[email protected]> +* 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 <linux/module.h> +#include <linux/mempool.h> +#include <linux/time.h> +#include <linux/jiffies.h> +#include <linux/security.h> +#include <net/sock.h> +#include <net/netlink.h> + +#define MIN_EVT_SKBS 16 +#define HIWAT_EVT_SKBS 32 +#define EVT_SKB_SIZE NLMSG_SPACE(128) + +struct mempool_zone { +mempool_t *pool; +int allocated; +int size; +int hiwat; +struct list_head freequeue; +spinlock_t freelock; +}; + +static struct mempool_zone z_dm_evt; + +static inline struct list_head *skb_to_lh (struct sk_buff *skb) +{ +return (struct list_head *)&skb->cb; +} + +static void *mempool_zone_alloc_skb (unsigned int gfp_mask, +void *pool_data) +{ +struct mempool_zone *zone = pool_data; + +return alloc_skb (zone->size, gfp_mask); +} + +static void mempool_zone_free_skb (void *element,void *pool_data) +{ +kfree_skb (element); +} + +static void +mempool_zone_complete (struct mempool_zone *zone,int release_all) +{ +unsigned long flags; +struct list_head *lh, *n; + +spin_lock_irqsave (&zone->freelock, flags); +if (zone->allocated) { +list_for_each_safe (lh, n, &zone->freequeue) { +struct sk_buff *skb = + (struct sk_buff *)((char *)lh - + offsetof(struct sk_buff , cb)); +if (skb_shared (skb)) { +if (release_all) +kfree_skb (skb); +else +continue ; + } + +list_del (skb_to_lh (skb)); +mempool_free (skb, zone->pool); + --zone->allocated; + + } + } +spin_unlock_irqrestore (&zone->freelock, flags); +} + +static int mempool_zone_init (struct mempool_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, mempool_zone_alloc_skb, + mempool_zone_free_skb, zp); +if (!zp->pool) +return -ENOMEM ; + +return 0 ; +} + +static struct sk_buff *mempool_zone_get_skb (struct mempool_zone *zone) +{ +struct sk_buff *skb; +unsigned long flags; + +/* Check for ones we can complete before we alloc */ +mempool_zone_complete (zone,0 ); + + skb =mempool_alloc (zone->pool,GFP_ATOMIC ); +if (skb) { +skb_get (skb); +spin_lock_irqsave (&z_dm_evt.freelock, flags); +list_add (skb_to_lh (skb), &z_dm_evt.freequeue); + ++zone->allocated; +spin_unlock_irqrestore (&z_dm_evt.freelock, flags); + } +return skb; +} + +int __init dm_nl_init (void ) +{ +int err; + + err =mempool_zone_init (&z_dm_evt,EVT_SKB_SIZE , +MIN_EVT_SKBS ,HIWAT_EVT_SKBS ); +if (!err) +printk (KERN_DEBUG "dm-netlink version 0.0.1 loaded\n" ); + +return err; + +} + +void dm_nl_exit (void ) +{ +mempool_destroy (z_dm_evt.pool); +}
include/linux/netlink.h +1 -0
@@ -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
drivers/md/Makefile +3 -0
@@ -37,6 +37,9 @@ obj-$(CONFIG_DM_MULTIPATH_EMC) += dm-emc obj-$(CONFIG_DM_SNAPSHOT) += dm-snapshot.o obj-$(CONFIG_DM_MIRROR) += dm-mirror.o obj-$(CONFIG_DM_ZERO) += dm-zero.o +ifeq ($(CONFIG_DM_NL_SUPPORT),y) + dm-mod-objs += dm-netlink.o +endif quiet_cmd_unroll = UNROLL $@ cmd_unroll = $(PERL) $(srctree)/$(src)/unroll.pl $(UNROLL) \
drivers/md/Kconfig +6 -0
@@ -236,5 +236,11 @@ config DM_MULTIPATH_EMC ---help--- Multipath support for EMC CX/AX series hardware. +config DM_NL_SUPPORT + bool "DM Netlink Support (EXPERIMENTAL)" + depends on BLK_DEV_DM && EXPERIMENTAL + ---help--- + Netlink events for dm devices. + endmenu
Re: [PATCH RFC 2/4] dm-netlink netlink support
In reply to Mike AndersonThis patch adds netlink support to dm-netlink. It also adds support for using netlink attributes for the event messages.
drivers/md/dm-netlink.c | 188 ++++++++++++++++++++++++++++++++++++++++++++- drivers/md/dm-netlink.h | 40 +++++++++ include/linux/dm-netlink.h | 46 +++++++++++ 3 files changed, 272 insertions(+), 2 deletions(-)
drivers/md/dm-netlink.c +186 -2
@@ -27,6 +27,7 @@#include <linux/security.h> #include <net/sock.h> #include <net/netlink.h> +#include <linux/dm-netlink.h> #define MIN_EVT_SKBS 16#define HIWAT_EVT_SKBS 32
@@ -125,20 +126,203 @@ static struct sk_buff* mempool_zone_get_return skb; } +static struct sock *dm_nl_sock; +static int dm_nl_daemon_pid; + +static u64 dm_evt_seqnum; +static DEFINE_SPINLOCK (sequence_lock); + +static struct sk_buff *dm_nl_build_path_msg (char * dm_name,int type, +int blk_err) +{ +struct sk_buff *skb; +struct nlmsghdr *nlh; +struct dm_nl_msghdr *dm_nlh; +u64 seq; +struct timeval tv; +int err = -ENOBUFS ; + + skb =mempool_zone_get_skb (&z_dm_evt); +if (!skb) { +printk (KERN_ERR "%s: mempool_zone_get_skb %d\n" , + __FUNCTION__, err); + err = -ENOMEM ; + goto out; + } + + nlh =nlmsg_put (skb, dm_nl_daemon_pid,0 ,DM_EVT , +NLMSG_ALIGN (sizeof (*dm_nlh)),0 ); +if (!nlh) + goto nla_put_failure; + + dm_nlh =nlmsg_data (nlh); + dm_nlh->type = type; + dm_nlh->version =DM_E_ATTR_MAX ; + +spin_lock (&sequence_lock); + seq = ++dm_evt_seqnum; +spin_unlock (&sequence_lock); +do_gettimeofday (&tv); + +NLA_PUT_U64 (skb,DM_E_ATTR_SEQNUM , seq); +NLA_PUT_U64 (skb,DM_E_ATTR_TSSEC , tv.tv_sec); +NLA_PUT_U64 (skb,DM_E_ATTR_TSUSEC , tv.tv_usec); +NLA_PUT_STRING (skb,DM_E_ATTR_DMNAME , dm_name); + +if (blk_err) +NLA_PUT_U32 (skb,DM_E_ATTR_BLKERR , blk_err); + +nlmsg_end (skb, nlh); + +return skb; + +nla_put_failure: +printk (KERN_ERR "%s: nla_put_failure\n" , + __FUNCTION__); +/* reduce skb users so zone_complete can free */ +kfree_skb (skb); +mempool_zone_complete (&z_dm_evt,0 ); +out: +return ERR_PTR (err); + +} + +static inline void dm_nl_unicast (struct sk_buff *skb) +{ +int err; + +if (!dm_nl_sock || !dm_nl_daemon_pid) +return ; + + err =nlmsg_unicast (dm_nl_sock, skb, dm_nl_daemon_pid); +if (err <0 ) +printk (KERN_ERR "%s: nlmsg_unicast %d\n" , __FUNCTION__, + err); +} + +void dm_nl_path_fail (char * dm_name,int blk_err) +{ +struct sk_buff *msg; + msg =dm_nl_build_path_msg (dm_name,DM_EVT_FAIL_PATH , blk_err); + +if (!IS_ERR (msg)) +dm_nl_unicast (msg); +} + +EXPORT_SYMBOL (dm_nl_path_fail); + +void dm_nl_path_reinstate (char * dm_name) +{ +struct sk_buff *msg; + msg =dm_nl_build_path_msg (dm_name,DM_EVT_REINSTATE_PATH ,0 ); + +if (!IS_ERR (msg)) +dm_nl_unicast (msg); +} + +EXPORT_SYMBOL (dm_nl_path_reinstate); + +#define RCV_SKB_FAIL (err) do { netlink_ack(skb, nlh, (err)); return; } while (0) + +static void dm_nl_rcv_msg (struct sk_buff *skb) +{ +int pid, flags; +struct nlmsghdr *nlh = (struct nlmsghdr *) skb->data; + +if (skb->len >=NLMSG_SPACE (0 )) { + +if (nlh->nlmsg_len <sizeof (*nlh) || + skb->len < nlh->nlmsg_len) { +return ; + } + pid = nlh->nlmsg_pid; + flags = nlh->nlmsg_flags; + +if (security_netlink_recv (skb)) +RCV_SKB_FAIL (-EPERM ); + +if (dm_nl_daemon_pid) { +if (dm_nl_daemon_pid != pid) { +RCV_SKB_FAIL (-EBUSY ); + } + }else { + dm_nl_daemon_pid = pid; + } + +if (flags &NLM_F_ACK ) +netlink_ack (skb, nlh,0 ); + } +} + +static void dm_nl_rcv (struct sock *sk,int len) +{ +struct sk_buff *skb; +unsigned int qlen; + +for (qlen =skb_queue_len (&sk->sk_receive_queue); qlen; qlen--) { + skb =skb_dequeue (&sk->sk_receive_queue); +dm_nl_rcv_msg (skb); +kfree_skb (skb); + } +} + +static int dm_nl_rcv_nl_event (struct notifier_block *this,unsigned long event,void *ptr) +{ +struct netlink_notify *n = ptr; + +if (event ==NETLINK_URELEASE && + n->protocol ==NETLINK_DM && n->pid) { +if ( n->pid == dm_nl_daemon_pid ) { + dm_nl_daemon_pid =0 ; + } +mempool_zone_complete (&z_dm_evt,1 ); + } + +return NOTIFY_DONE ; +} + +static struct notifier_block dm_nl_nl_notifier = { + .notifier_call = dm_nl_rcv_nl_event, +}; + +static struct sock *dm_nl_sock; +static int dm_nl_daemon_pid; +int __init dm_nl_init (void ) {int err; + err =netlink_register_notifier (&dm_nl_nl_notifier); +if (err) +return err; + + dm_nl_sock =netlink_kernel_create (NETLINK_DM ,0 , + dm_nl_rcv,THIS_MODULE ); +if (!dm_nl_sock) { + err = -ENOBUFS ; + goto unregister_notifier; + } + err =mempool_zone_init (&z_dm_evt,EVT_SKB_SIZE ,MIN_EVT_SKBS ,HIWAT_EVT_SKBS ); -if (!err) -printk (KERN_DEBUG "dm-netlink version 0.0.1 loaded\n" ); +if (err) + goto release_socket; + +printk (KERN_DEBUG "dm-netlink version 0.0.1 loaded\n" );return err; +release_socket: +sock_release (dm_nl_sock->sk_socket); +unregister_notifier: +netlink_unregister_notifier (&dm_nl_nl_notifier); +printk (KERN_ERR "%s: failed %d\n" , __FUNCTION__, err); +return err; }void dm_nl_exit (void ) {mempool_destroy (z_dm_evt.pool); +sock_release (dm_nl_sock->sk_socket); +netlink_unregister_notifier (&dm_nl_nl_notifier); }
include/linux/dm-netlink.h new file +46 -0
46 lines not on this page · raw message
drivers/md/dm-netlink.h new file +40 -0
@@ -0,0 +1,40 @@ +/* +* Device Mapper Netlink Support +* +* Copyright (C) 2005 IBM Corporation +* Author: Mike Anderson <[email protected]> +* +* 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 + +#ifdef CONFIG_DM_NL_SUPPORT +void dm_nl_path_fail (char *,int ); +void dm_nl_path_reinstate (char *); +#else +static inline void dm_nl_path_fail (char * dm_name,int blk_err) +{ +return ; +} + +static inline void dm_nl_path_reinstate (char * dm_name) +{ +return ; +} +#endif + +#endif /* DM_NETLINK_H */
RFC PATCH 3/4 dm-mpath calls to dm-netlink
In reply to Mike AndersonThis patch adds a call to init dm_nl during dm init, and calls to dm_nl functions for path failure / reinstate events.
drivers/md/dm-mpath.c | 9 ++++++--- drivers/md/dm.c | 2 ++ drivers/md/dm.h | 3 +++ 3 files changed, 11 insertions(+), 3 deletions(-)
drivers/md/dm.h +3 -0
@@ -192,4 +192,7 @@ void dm_stripe_exit(void);void *dm_vcalloc (unsigned long nmemb,unsigned long elem_size);union map_info *dm_get_mapinfo (struct bio *bio); +int dm_nl_init (void ); +void dm_nl_exit (void ); +#endif
drivers/md/dm.c +2 -0
@@ -163,6 +163,7 @@ int (*_inits[])(void) __initdata = { dm_linear_init, dm_stripe_init, dm_interface_init, + dm_nl_init, }; void (*_exits[])(void) = {
@@ -171,6 +172,7 @@ void (*_exits[])(void) = { dm_linear_exit, dm_stripe_exit, dm_interface_exit, + dm_nl_exit, };static int __init dm_init (void )
drivers/md/dm-mpath.c +6 -3
@@ -10,6 +10,7 @@#include "dm-hw-handler.h" #include "dm-bio-list.h" #include "dm-bio-record.h" +#include "dm-netlink.h" #include <linux/ctype.h> #include <linux/init.h>
@@ -798,7 +799,7 @@ static int multipath_map(struct dm_targe/* * Take a path out of use. */ -static int fail_path (struct pgpath *pgpath) +static int fail_path (struct pgpath *pgpath,struct bio *bio) {unsigned long flags;struct multipath *m = pgpath->pg->m;
@@ -819,6 +820,7 @@ static int fail_path(struct pgpath *pgpaif (pgpath == m->current_pgpath) m->current_pgpath =NULL ; +dm_nl_path_fail (pgpath->path.dev->name,0x5A5A5A5A );queue_work (kmultipathd, &m->trigger_event); out:
@@ -858,6 +860,7 @@ static int reinstate_path(struct pgpathif (!m->nr_valid_paths++ && m->queue_size)queue_work (kmultipathd, &m->process_queued_ios); +dm_nl_path_reinstate (pgpath->path.dev->name);queue_work (kmultipathd, &m->trigger_event); out:
@@ -975,7 +978,7 @@ void dm_pg_init_complete(struct path *pa err_flags |=MP_FAIL_PATH ;if (err_flags &MP_FAIL_PATH ) -fail_path (pgpath); +fail_path (pgpath,NULL );if (err_flags &MP_BYPASS_PG )bypass_pg (m, pg,1 );
@@ -1027,7 +1030,7 @@ static int do_end_io(struct multipath *mif (mpio->pgpath) {if (err_flags &MP_FAIL_PATH ) -fail_path (mpio->pgpath); +fail_path (mpio->pgpath, bio);if (err_flags &MP_BYPASS_PG )bypass_pg (m, mpio->pgpath->pg,1 );
RFC PATCH 4/4 Sample user space program (dm_nld)
In reply to Mike Anderson Sample program that receives dm netlink events and prints them out. This program uses the netlink library (libnl)
http://people.suug.ch/~tgr/libnl/
Makefile | 31 ++++++++++++ dm_nld.c | 159 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ dm_nld.h | 53 +++++++++++++++++++++ 3 files changed, 243 insertions(+)
dm_nld.c new file +159 -0
@@ -0,0 +1,159 @@ +/* +* Device Mapper Netlink User Space Daemon (dm-nld) +* +* Copyright (C) 2005 IBM Corporation +* Author: Mike Anderson <[email protected]> +* +* 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. +* +*/ +/* +* This program is a proto example of using the dm netlink interface +*/ + +#include <unistd.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <fcntl.h> +#include <errno.h> +#include <inttypes.h> +#include <sys/socket.h> +#include <sys/user.h> +#include <asm/types.h> +#include <linux/netlink.h> +#include <time.h> +#include "dm_nld.h" + +static struct nla_policy dm_e_attr_policy[DM_E_ATTR_MAX ] = { + [DM_E_ATTR_SEQNUM ] = { .type =NLA_U64 }, + [DM_E_ATTR_TSSEC ] = { .type =NLA_U64 }, + [DM_E_ATTR_TSUSEC ] = { .type =NLA_U64 }, + [DM_E_ATTR_DMNAME ] = { .type =NLA_STRING }, + [DM_E_ATTR_BLKERR ] = { .type =NLA_U32 }, +}; + +char *build_evt_msg (struct nlattr *dm_attr[]) +{ +int n, size =1024 ; +char *bmark, *str =NULL ; + + str =calloc (1 , size); +if (!str) + goto out; + bmark = str; + + n =snprintf (bmark, size,"[Event]:" ); + size -= n; + bmark += n; + +if (dm_attr[DM_E_ATTR_SEQNUM ] && size) { + n =snprintf (bmark, size," SEQNUM: %" PRIu64, +nla_get_u64 (dm_attr[DM_E_ATTR_SEQNUM ])); + size -= n; + bmark += n; + } + +if (dm_attr[DM_E_ATTR_TSSEC ] && size) { +const time_t t =nla_get_u64 (dm_attr[DM_E_ATTR_TSSEC ]), + n =snprintf (bmark, size,", Time: %s" ,ctime (&t)); + size -= n; + bmark += n -1 ; + } + +if (dm_attr[DM_E_ATTR_DMNAME ] && size) { + n =snprintf (bmark, size,", DMNAME: %s" , (char *) +nla_data (dm_attr[DM_E_ATTR_DMNAME ])); + size -= n; + bmark += n; + } + +if (dm_attr[DM_E_ATTR_BLKERR ] && size) { + n =snprintf (bmark, size,", BLKERR: 0x%x" , +nla_get_u32 (dm_attr[DM_E_ATTR_BLKERR ])); + } + +out: +return str; +} + +int main (int argc,char *argv[]) +{ +int err =-1 ; +struct sockaddr_nl addr; +struct nlmsghdr *nlh; +struct dm_nl_msghdr *dm_nlh; +unsigned char *msg; +char *evt_str =NULL ; +struct nlattr *dm_attr[DM_E_ATTR_MAX ]; + +struct nl_handle *handle; + + handle =nl_handle_alloc (); +if (!handle) + goto handle_out; + +nl_disable_sequence_check (handle); + + err =nl_connect (handle,NETLINK_DM ); +if (err <0 ) + goto connect_out; + + err =nl_send_simple (handle,NLMSG_NOOP ,0 ,NULL ,0 ); +if (err <0 ) + goto simple_out; + +memset (&addr,0 ,sizeof (addr)); + addr.nl_family =AF_NETLINK ; + addr.nl_pid =0 ; + addr.nl_groups =0 ; + +do { + err =nl_recv (handle, &addr, &msg); +if (err <=0 ) +break ; + nlh = (struct nlmsghdr *) msg; +fprintf (stdout,"Msg Type: %d Recevied\n" , + nlh->nlmsg_type); +if (nlh->nlmsg_type ==DM_EVT ) { + dm_nlh =nlmsg_data (nlh); +fprintf (stdout,"Event Type: %d Version: %d\n" , + dm_nlh->type, dm_nlh->version); + + err =nla_parse (dm_attr,DM_E_ATTR_MAX -1 , +nlmsg_attrdata (nlh, +sizeof (struct dm_nl_msghdr )), +nlmsg_attrlen (nlh, +sizeof (struct dm_nl_msghdr )), + dm_e_attr_policy); +if (err <0 ) +break ; + + evt_str =build_evt_msg (dm_attr); +if (evt_str) +fprintf (stdout,"%s\n" , evt_str); + } + +free (evt_str); +free (msg); + }while (1 ); + +simple_out: +nl_close (handle); +connect_out: +nl_handle_destroy (handle); +handle_out: +exit (err ==0 ?0 :1 ); +}
dm_nld.h new file +53 -0
53 lines not on this page · raw message
Makefile new file +31 -0
@@ -0,0 +1,31 @@ +# Make variables (CC, etc...) +AS = $(CROSS_COMPILE)as +LD = $(CROSS_COMPILE)ld +CC = $(CROSS_COMPILE)gcc +CPP = $(CC) -E +AR = $(CROSS_COMPILE)ar +NM = $(CROSS_COMPILE)nm +STRIP = $(CROSS_COMPILE)strip +OBJCOPY = $(CROSS_COMPILE)objcopy +OBJDUMP = $(CROSS_COMPILE)objdump + +CFLAGS += -fno-builtin -Wall -Wchar-subscripts -Wundef \ + -Wstrict-prototypes -Wpointer-arith -Wsign-compare +CFLAGS += -DNETLINK_DM=17 + +LDFLAGS = -lnl +ifeq ($(strip $(DEBUG)),true) +CFLAGS += -O1 -g +else +CFLAGS += -Os +endif + +PROGRAM = dm_nld + +all: $(PROGRAM) + +dm_evtd: dm_nld.o + $(CC) $^ -o $@ + +clean: + rm -f *.o $(PROGRAM)