LVS
lvs-users
Google
 
Web LinuxVirtualServer.org

Re: [PATCH] (3/6) ipvs -- use list_for_each_entry macro's

To: Julian Anastasov <ja@xxxxxx>
Subject: Re: [PATCH] (3/6) ipvs -- use list_for_each_entry macro's
Cc: lvs-users@xxxxxxxxxxxxxxxxxxxxxx
Cc: Wensong Zhang <wensong@xxxxxxxxxxxx>
Cc: netdev@xxxxxxxxxxx
From: Stephen Hemminger <shemminger@xxxxxxxx>
Date: Mon, 22 Sep 2003 11:03:46 -0700
Thank you for your observations. Here are my comments.
Followup message is a patch to restore the missing pieces.

Why don't you make up a patch with your changes to gcd and 
list_for_each_entry_continue?


>       It seems some places become inefficient. May be we have
> to introduce list_for_each_entry_continue?:
> 
>  * list_for_each_entry_continue       -       iterate over list of given type
>  *                    continuing after existing point
>  * @pos:      the type * to use as a loop counter.
>  * @head:     the head for your list.
>  * @member:   the name of the list_struct within the struct.
>  */
> #define list_for_each_entry_continue(pos, head, member)                       
> \
>       for (pos = list_entry(pos->member.next, typeof(*pos), member),  \
>                    prefetch(pos->member.next);                        \
>            &pos->member != (head);                                    \
>            pos = list_entry(pos->member.next, typeof(*pos), member),  \
>                    prefetch(pos->member.next))
> 

That looks good.
 
> below are some comments, there are some strange changes:
> 
> On Tue, 16 Sep 2003, Stephen Hemminger wrote:
> 
> > diff -Nru a/net/ipv4/ipvs/ip_vs_app.c b/net/ipv4/ipvs/ip_vs_app.c
> > --- a/net/ipv4/ipvs/ip_vs_app.c     Tue Sep 16 14:08:39 2003
> > +++ b/net/ipv4/ipvs/ip_vs_app.c     Tue Sep 16 14:08:39 2003
> > @@ -214,18 +214,14 @@
> >   */
> >  void unregister_ip_vs_app(struct ip_vs_app *app)
> >  {
> > -   struct ip_vs_app *inc;
> > -   struct list_head *l = &app->incs_list;
> > +   struct ip_vs_app *inc, *nxt;
> >
> >     down(&__ip_vs_app_mutex);
> >
> > -   while (l->next != l) {
> > -           inc = list_entry(l->next, struct ip_vs_app, a_list);
> > +   list_for_each_entry_safe(inc, nxt, &app->incs_list, a_list) {
> >             ip_vs_app_inc_release(inc);
> >     }
> 
>       What happens with this list_del?:


That got accidentally dropped. Will send patch out to restore.



> >
> > -   list_del(&app->a_list);
> > -
> >     up(&__ip_vs_app_mutex);
> >
> >     /* decrease the module use count */
> 
> > diff -Nru a/net/ipv4/ipvs/ip_vs_rr.c b/net/ipv4/ipvs/ip_vs_rr.c
> > --- a/net/ipv4/ipvs/ip_vs_rr.c      Tue Sep 16 14:08:39 2003
> > +++ b/net/ipv4/ipvs/ip_vs_rr.c      Tue Sep 16 14:08:39 2003
> > @@ -57,7 +57,7 @@
> >  static struct ip_vs_dest *
> >  ip_vs_rr_schedule(struct ip_vs_service *svc, struct iphdr *iph)
> >  {
> > -   register struct list_head *p, *q;
> > +   struct list_head *p, *q;
> >     struct ip_vs_dest *dest;
> >
> >     IP_VS_DBG(6, "ip_vs_rr_schedule(): Scheduling...\n");
> > @@ -73,12 +73,12 @@
> >                     continue;
> >             }
> 
>       new empty line, may be your changes to ip_vs_rr.c are
> not completed/actual? :) :


Another accidental screw-up... I tried to use list_for_each somehow
in the RR code, but it got too messy and backed out back to the
original, and lost some stuff.


> >
> > +
> >             dest = list_entry(q, struct ip_vs_dest, n_list);
> >             if (!(dest->flags & IP_VS_DEST_F_OVERLOAD) &&
> >                 atomic_read(&dest->weight) > 0)
> >                     /* HIT */
> >                     goto out;
> 
>       Why this line is deleted?:
> 
> > -           q = q->next;
> >     } while (q != p);
> >     write_unlock(&svc->sched_lock);
> >     return NULL;
> 
> 
> > diff -Nru a/net/ipv4/ipvs/ip_vs_sed.c b/net/ipv4/ipvs/ip_vs_sed.c
> > --- a/net/ipv4/ipvs/ip_vs_sed.c     Tue Sep 16 14:08:39 2003
> > +++ b/net/ipv4/ipvs/ip_vs_sed.c     Tue Sep 16 14:08:39 2003
> > @@ -85,7 +85,6 @@
> >  static struct ip_vs_dest *
> >  ip_vs_sed_schedule(struct ip_vs_service *svc, struct iphdr *iph)
> >  {
> > -   register struct list_head *l, *e;
> >     struct ip_vs_dest *dest, *least;
> >     unsigned int loh, doh;
> >
> > @@ -104,9 +103,7 @@
> >      * new connections.
> >      */
> >
> > -   l = &svc->destinations;
> > -   for (e=l->next; e!=l; e=e->next) {
> > -           least = list_entry(e, struct ip_vs_dest, n_list);
> > +   list_for_each_entry(least, &svc->destinations, n_list) {
> >             if (!(least->flags & IP_VS_DEST_F_OVERLOAD) &&
> >                 atomic_read(&least->weight) > 0) {
> >                     loh = ip_vs_sed_dest_overhead(least);
> > @@ -119,9 +116,7 @@
> >      *    Find the destination with the least load.
> >      */
> 
>       Inefficient, list_for_each_entry_continue?:

As inefficient as the original though.


> >    nextstage:
> > -   for (e=e->next; e!=l; e=e->next) {
> > -           dest = list_entry(e, struct ip_vs_dest, n_list);
> > -
> > +   list_for_each_entry(dest, &svc->destinations, n_list) {
> >             if (dest->flags & IP_VS_DEST_F_OVERLOAD)
> >                     continue;
> >             doh = ip_vs_sed_dest_overhead(dest);
> 
> 
> > diff -Nru a/net/ipv4/ipvs/ip_vs_wlc.c b/net/ipv4/ipvs/ip_vs_wlc.c
> > --- a/net/ipv4/ipvs/ip_vs_wlc.c     Tue Sep 16 14:08:39 2003
> > +++ b/net/ipv4/ipvs/ip_vs_wlc.c     Tue Sep 16 14:08:39 2003
> > @@ -73,7 +73,6 @@
> >  static struct ip_vs_dest *
> >  ip_vs_wlc_schedule(struct ip_vs_service *svc, struct iphdr *iph)
> >  {
> > -   register struct list_head *l, *e;
> >     struct ip_vs_dest *dest, *least;
> >     unsigned int loh, doh;
> >
> > @@ -92,9 +91,7 @@
> >      * new connections.
> >      */
> >
> > -   l = &svc->destinations;
> > -   for (e=l->next; e!=l; e=e->next) {
> > -           least = list_entry(e, struct ip_vs_dest, n_list);
> > +   list_for_each_entry(least, &svc->destinations, n_list) {
> >             if (!(least->flags & IP_VS_DEST_F_OVERLOAD) &&
> >                 atomic_read(&least->weight) > 0) {
> >                     loh = ip_vs_wlc_dest_overhead(least);
> > @@ -107,9 +104,7 @@
> >      *    Find the destination with the least load.
> >      */
> 
>       Shorter, not broken but inefficient, list_for_each_entry_continue?:
> 
> >    nextstage:
> > -   for (e=e->next; e!=l; e=e->next) {
> > -           dest = list_entry(e, struct ip_vs_dest, n_list);
> > -
> > +   list_for_each_entry(dest, &svc->destinations, n_list) {
> >             if (dest->flags & IP_VS_DEST_F_OVERLOAD)
> >                     continue;
> >             doh = ip_vs_wlc_dest_overhead(dest);
> 
> > diff -Nru a/net/ipv4/ipvs/ip_vs_wrr.c b/net/ipv4/ipvs/ip_vs_wrr.c
> > --- a/net/ipv4/ipvs/ip_vs_wrr.c     Tue Sep 16 14:08:39 2003
> > +++ b/net/ipv4/ipvs/ip_vs_wrr.c     Tue Sep 16 14:08:39 2003
> > @@ -56,25 +56,22 @@
> >
> >  static int ip_vs_wrr_gcd_weight(struct ip_vs_service *svc)
> >  {
> > -   register struct list_head *l, *e;
> >     struct ip_vs_dest *dest;
> >     int weight;
> >     int g = 1;
> >
> > -   l = &svc->destinations;
> > -   for (e=l->next; e!=l; e=e->next) {
> > -           dest = list_entry(e, struct ip_vs_dest, n_list);
> > +   list_for_each_entry(dest, &svc->destinations, n_list) {
> >             weight = atomic_read(&dest->weight);
> >             if (weight > 0) {
> >                     g = weight;
> > -                   break;
> > +                   goto search_gcd;
> >             }
> >     }
> > -   if (e == l)
> > -           return g;
> >
> > -   for (e=e->next; e!=l; e=e->next) {
> > -           dest = list_entry(e, struct ip_vs_dest, n_list);
> > +   return g;
> > +
> 
>       It still does not look good:
> 
> > + search_gcd:
> > +   list_for_each_entry(dest, &svc->destinations, n_list) {
> >             weight = atomic_read(&dest->weight);
> >             if (weight > 0)
> >                     g = gcd(weight, g);
> > @@ -89,13 +86,10 @@
> 
>       What about such version?:
> 
> static int ip_vs_wrr_gcd_weight(struct ip_vs_service *svc)
> {
>       struct ip_vs_dest *dest;
>       int weight;
>       int g = 0;
> 
>       list_for_each_entry(dest, &svc->destinations, n_list) {
>               weight = atomic_read(&dest->weight);
>               if (weight > 0) {
>                       if (g > 0)
>                               g = gcd(weight, g);
>                       else
>                               g = weight;
>               }
>       }
> 
>       return g?: 1;

The null ?: is a gcc extension that confuses people.
<Prev in Thread] Current Thread [Next in Thread>