@@ -475,24 +475,31 @@ static int ila_nl_cmd_get_mapping(struct sk_buff *skb, struct genl_info *info)
475475
476476struct ila_dump_iter {
477477 struct rhashtable_iter rhiter ;
478+ int skip ;
478479};
479480
480481static int ila_nl_dump_start (struct netlink_callback * cb )
481482{
482483 struct net * net = sock_net (cb -> skb -> sk );
483484 struct ila_net * ilan = net_generic (net , ila_net_id );
484- struct ila_dump_iter * iter = (struct ila_dump_iter * )cb -> args [0 ];
485+ struct ila_dump_iter * iter ;
486+ int ret ;
485487
486- if (!iter ) {
487- iter = kmalloc (sizeof (* iter ), GFP_KERNEL );
488- if (!iter )
489- return - ENOMEM ;
488+ iter = kmalloc (sizeof (* iter ), GFP_KERNEL );
489+ if (!iter )
490+ return - ENOMEM ;
490491
491- cb -> args [0 ] = (long )iter ;
492+ ret = rhashtable_walk_init (& ilan -> rhash_table , & iter -> rhiter ,
493+ GFP_KERNEL );
494+ if (ret ) {
495+ kfree (iter );
496+ return ret ;
492497 }
493498
494- return rhashtable_walk_init (& ilan -> rhash_table , & iter -> rhiter ,
495- GFP_KERNEL );
499+ iter -> skip = 0 ;
500+ cb -> args [0 ] = (long )iter ;
501+
502+ return ret ;
496503}
497504
498505static int ila_nl_dump_done (struct netlink_callback * cb )
@@ -510,20 +517,45 @@ static int ila_nl_dump(struct sk_buff *skb, struct netlink_callback *cb)
510517{
511518 struct ila_dump_iter * iter = (struct ila_dump_iter * )cb -> args [0 ];
512519 struct rhashtable_iter * rhiter = & iter -> rhiter ;
520+ int skip = iter -> skip ;
513521 struct ila_map * ila ;
514522 int ret ;
515523
516524 rhashtable_walk_start (rhiter );
517525
518- for (;;) {
519- ila = rhashtable_walk_next (rhiter );
526+ /* Get first entry */
527+ ila = rhashtable_walk_peek (rhiter );
528+
529+ if (ila && !IS_ERR (ila ) && skip ) {
530+ /* Skip over visited entries */
531+
532+ while (ila && skip ) {
533+ /* Skip over any ila entries in this list that we
534+ * have already dumped.
535+ */
536+ ila = rcu_access_pointer (ila -> next );
537+ skip -- ;
538+ }
539+ }
520540
541+ skip = 0 ;
542+
543+ for (;;) {
521544 if (IS_ERR (ila )) {
522- if (PTR_ERR (ila ) == - EAGAIN )
523- continue ;
524545 ret = PTR_ERR (ila );
525- goto done ;
546+ if (ret == - EAGAIN ) {
547+ /* Table has changed and iter has reset. Return
548+ * -EAGAIN to the application even if we have
549+ * written data to the skb. The application
550+ * needs to deal with this.
551+ */
552+
553+ goto out_ret ;
554+ } else {
555+ break ;
556+ }
526557 } else if (!ila ) {
558+ ret = 0 ;
527559 break ;
528560 }
529561
@@ -532,15 +564,21 @@ static int ila_nl_dump(struct sk_buff *skb, struct netlink_callback *cb)
532564 cb -> nlh -> nlmsg_seq , NLM_F_MULTI ,
533565 skb , ILA_CMD_GET );
534566 if (ret )
535- goto done ;
567+ goto out ;
536568
569+ skip ++ ;
537570 ila = rcu_access_pointer (ila -> next );
538571 }
572+
573+ skip = 0 ;
574+ ila = rhashtable_walk_next (rhiter );
539575 }
540576
541- ret = skb -> len ;
577+ out :
578+ iter -> skip = skip ;
579+ ret = (skb -> len ? : ret );
542580
543- done :
581+ out_ret :
544582 rhashtable_walk_stop (rhiter );
545583 return ret ;
546584}
0 commit comments