Support for NLM_F_INTR

Check if a dump was interrupted and needs to be redone
This commit is contained in:
Thomas Graf 2011-07-14 10:51:49 +02:00
parent dba0e91a09
commit 21d52eabba
6 changed files with 35 additions and 4 deletions

View File

@ -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 */

View File

@ -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 *);

View File

@ -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,
};

View File

@ -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;
}
/** @} */

View File

@ -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",
};
/**

View File

@ -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;
}