From 21d52eabba00089e3319575616a429fb75309cb7 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Thu, 14 Jul 2011 10:51:49 +0200 Subject: Support for NLM_F_INTR Check if a dump was interrupted and needs to be redone --- include/linux/netlink.h | 1 + include/netlink/errno.h | 3 ++- include/netlink/handlers.h | 2 ++ lib/cache.c | 14 ++++++++++++-- lib/error.c | 1 + lib/nl.c | 18 +++++++++++++++++- 6 files changed, 35 insertions(+), 4 deletions(-) diff --git a/include/linux/netlink.h b/include/linux/netlink.h index 0abcdaf..3925254 100644 --- a/include/linux/netlink.h +++ b/include/linux/netlink.h @@ -49,6 +49,7 @@ struct nlmsghdr { #define NLM_F_MULTI 2 /* Multipart message, terminated by NLMSG_DONE */ #define NLM_F_ACK 4 /* Reply with ack, with zero or error code */ #define NLM_F_ECHO 8 /* Echo this request */ +#define NLM_F_DUMP_INTR 16 /* Dump was inconsistent due to sequence change */ /* Modifiers to GET request */ #define NLM_F_ROOT 0x100 /* specify tree root */ diff --git a/include/netlink/errno.h b/include/netlink/errno.h index 267a745..f8b5130 100644 --- a/include/netlink/errno.h +++ b/include/netlink/errno.h @@ -49,8 +49,9 @@ extern "C" { #define NLE_PARSE_ERR 30 #define NLE_NODEV 31 #define NLE_IMMUTABLE 32 +#define NLE_DUMP_INTR 33 -#define NLE_MAX NLE_IMMUTABLE +#define NLE_MAX NLE_DUMP_INTR extern const char * nl_geterror(int); extern void nl_perror(int, const char *); diff --git a/include/netlink/handlers.h b/include/netlink/handlers.h index f373f58..dfa2809 100644 --- a/include/netlink/handlers.h +++ b/include/netlink/handlers.h @@ -108,6 +108,8 @@ enum nl_cb_type { NL_CB_SEQ_CHECK, /** Sending of an acknowledge message has been requested */ NL_CB_SEND_ACK, + /** Flag NLM_F_DUMP_INTR is set in message */ + NL_CB_DUMP_INTR, __NL_CB_TYPE_MAX, }; diff --git a/lib/cache.c b/lib/cache.c index 7afa42e..3b453a9 100644 --- a/lib/cache.c +++ b/lib/cache.c @@ -677,6 +677,7 @@ int nl_cache_resync(struct nl_sock *sk, struct nl_cache *cache, NL_DBG(1, "Resyncing cache %p <%s>...\n", cache, nl_cache_name(cache)); +restart: /* Mark all objects so we can see if some of them are obsolete */ nl_cache_mark_all(cache); @@ -685,7 +686,9 @@ int nl_cache_resync(struct nl_sock *sk, struct nl_cache *cache, goto errout; err = __cache_pickup(sk, cache, &p); - if (err < 0) + if (err == -NLE_DUMP_INTR) + goto restart; + else if (err < 0) goto errout; nl_list_for_each_entry_safe(obj, next, &cache->c_items, ce_list) { @@ -770,6 +773,7 @@ int nl_cache_refill(struct nl_sock *sk, struct nl_cache *cache) { int err; +restart: err = nl_cache_request_full_dump(sk, cache); if (err < 0) return err; @@ -778,7 +782,13 @@ int nl_cache_refill(struct nl_sock *sk, struct nl_cache *cache) cache, nl_cache_name(cache)); nl_cache_clear(cache); - return nl_cache_pickup(sk, cache); + err = nl_cache_pickup(sk, cache); + if (err == -NLE_DUMP_INTR) { + fprintf(stderr, "dump interrupted, restarting!\n"); + goto restart; + } + + return err; } /** @} */ diff --git a/lib/error.c b/lib/error.c index 8934020..e8ee474 100644 --- a/lib/error.c +++ b/lib/error.c @@ -46,6 +46,7 @@ static const char *errmsg[NLE_MAX+1] = { [NLE_PARSE_ERR] = "Unable to parse object", [NLE_NODEV] = "No such device", [NLE_IMMUTABLE] = "Immutable attribute", +[NLE_DUMP_INTR] = "Dump inconsistency detected, interrupted", }; /** diff --git a/lib/nl.c b/lib/nl.c index fc70374..cc450c7 100644 --- a/lib/nl.c +++ b/lib/nl.c @@ -559,7 +559,7 @@ do { \ static int recvmsgs(struct nl_sock *sk, struct nl_cb *cb) { - int n, err = 0, multipart = 0; + int n, err = 0, multipart = 0, interrupted = 0; unsigned char *buf = NULL; struct nlmsghdr *hdr; struct sockaddr_nl nla = {0}; @@ -631,6 +631,19 @@ continue_reading: if (hdr->nlmsg_flags & NLM_F_MULTI) multipart = 1; + + if (hdr->nlmsg_flags & NLM_F_DUMP_INTR) { + if (cb->cb_set[NL_CB_DUMP_INTR]) + NL_CB_CALL(cb, NL_CB_DUMP_INTR, msg); + else { + /* + * We have to continue reading to clear + * all messages until a NLMSG_DONE is + * received and report the inconsistency. + */ + interrupted = 1; + } + } /* Other side wishes to see an ack for this message */ if (hdr->nlmsg_flags & NLM_F_ACK) { @@ -738,6 +751,9 @@ out: free(buf); free(creds); + if (interrupted) + err = -NLE_DUMP_INTR; + return err; } -- cgit v1.2.1