diff options
-rw-r--r-- | net/ipv4/fib_trie.c | 34 |
1 files changed, 21 insertions, 13 deletions
diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c index 441c4eafb9e0..f1005fe17898 100644 --- a/net/ipv4/fib_trie.c +++ b/net/ipv4/fib_trie.c | |||
@@ -1917,35 +1917,43 @@ static int fn_trie_dump_leaf(struct leaf *l, struct fib_table *tb, | |||
1917 | return skb->len; | 1917 | return skb->len; |
1918 | } | 1918 | } |
1919 | 1919 | ||
1920 | |||
1921 | |||
1922 | static int fn_trie_dump(struct fib_table *tb, struct sk_buff *skb, | 1920 | static int fn_trie_dump(struct fib_table *tb, struct sk_buff *skb, |
1923 | struct netlink_callback *cb) | 1921 | struct netlink_callback *cb) |
1924 | { | 1922 | { |
1925 | struct leaf *l; | 1923 | struct leaf *l; |
1926 | struct trie *t = (struct trie *) tb->tb_data; | 1924 | struct trie *t = (struct trie *) tb->tb_data; |
1927 | int h = 0; | 1925 | t_key key = cb->args[2]; |
1928 | int s_h = cb->args[2]; | ||
1929 | 1926 | ||
1930 | rcu_read_lock(); | 1927 | rcu_read_lock(); |
1931 | for (h = 0, l = trie_firstleaf(t); l != NULL; h++, l = trie_nextleaf(l)) { | 1928 | /* Dump starting at last key. |
1932 | if (h < s_h) | 1929 | * Note: 0.0.0.0/0 (ie default) is first key. |
1933 | continue; | 1930 | */ |
1934 | 1931 | if (!key) | |
1935 | if (h > s_h) { | 1932 | l = trie_firstleaf(t); |
1936 | cb->args[3] = 0; | 1933 | else { |
1937 | cb->args[4] = 0; | 1934 | l = fib_find_node(t, key); |
1935 | if (!l) { | ||
1936 | /* The table changed during the dump, rather than | ||
1937 | * giving partial data, just make application retry. | ||
1938 | */ | ||
1939 | rcu_read_unlock(); | ||
1940 | return -EBUSY; | ||
1938 | } | 1941 | } |
1942 | } | ||
1939 | 1943 | ||
1944 | while (l) { | ||
1945 | cb->args[2] = l->key; | ||
1940 | if (fn_trie_dump_leaf(l, tb, skb, cb) < 0) { | 1946 | if (fn_trie_dump_leaf(l, tb, skb, cb) < 0) { |
1941 | rcu_read_unlock(); | 1947 | rcu_read_unlock(); |
1942 | cb->args[2] = h; | ||
1943 | return -1; | 1948 | return -1; |
1944 | } | 1949 | } |
1950 | |||
1951 | l = trie_nextleaf(l); | ||
1952 | memset(&cb->args[3], 0, | ||
1953 | sizeof(cb->args) - 3*sizeof(cb->args[0])); | ||
1945 | } | 1954 | } |
1946 | rcu_read_unlock(); | 1955 | rcu_read_unlock(); |
1947 | 1956 | ||
1948 | cb->args[2] = h; | ||
1949 | return skb->len; | 1957 | return skb->len; |
1950 | } | 1958 | } |
1951 | 1959 | ||