LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Linux - Kernel (https://www.linuxquestions.org/questions/linux-kernel-70/)
-   -   how rcu list entry be protected in ip_vs_add_dest() & ip_vs_del_dest() [centos 7.2 kernel 3.10.327] (https://www.linuxquestions.org/questions/linux-kernel-70/how-rcu-list-entry-be-protected-in-ip_vs_add_dest-and-ip_vs_del_dest-%5Bcentos-7-2-kernel-3-10-327%5D-4175616019/)

newcent 10-20-2017 01:53 AM

how rcu list entry be protected in ip_vs_add_dest() & ip_vs_del_dest() [centos 7.2 kernel 3.10.327]
 
I was trying to learn ip_vs and linux rcu mechanism these days!and some codes related to rcu list confused me! How can svc list been protected if there is two task trying to del dest in the same svc list?
About __ip_vs_unlink_dest(), it doesn't protect svc destinations when it del dest from svc destination list

Code:

static void __ip_vs_unlink_dest(struct ip_vs_service *svc,
                                struct ip_vs_dest *dest,
                                int svcupd)
{
        dest->flags &= ~IP_VS_DEST_F_AVAILABLE;

        /*
        *  Remove it from the d-linked destination list.
        */
        list_del_rcu(&dest->n_list);
        svc->num_dests--;

        if (svcupd) {
                struct ip_vs_scheduler *sched;

                sched = rcu_dereference_protected(svc->scheduler, 1);
                if (sched->del_dest)
                        sched->del_dest(svc, dest);
        }
}

when add dest in ip_vs_update_dest
Code:

tatic void
__ip_vs_update_dest(struct ip_vs_service *svc, struct ip_vs_dest *dest,
                    struct ip_vs_dest_user_kern *udest, int add)
{
        struct netns_ipvs *ipvs = net_ipvs(svc->net);
        struct ip_vs_scheduler *sched;
        int conn_flags;

        /* set the weight and the flags */
        atomic_set(&dest->weight, udest->weight);
        conn_flags = udest->conn_flags & IP_VS_CONN_F_DEST_MASK;
        conn_flags |= IP_VS_CONN_F_INACTIVE;

        /* set the IP_VS_CONN_F_NOOUTPUT flag if not masquerading/NAT */
        if ((conn_flags & IP_VS_CONN_F_FWD_MASK) != IP_VS_CONN_F_MASQ) {
                conn_flags |= IP_VS_CONN_F_NOOUTPUT;
        } else {
                /*
                *    Put the real service in rs_table if not present.
                *    For now only for NAT!
                */
                ip_vs_rs_hash(ipvs, dest);
        }
        atomic_set(&dest->conn_flags, conn_flags);

        /* bind the service */
        if (!dest->svc) {
                __ip_vs_bind_svc(dest, svc);
        } else {
                if (dest->svc != svc) {
                        __ip_vs_unbind_svc(dest);
                        ip_vs_zero_stats(&dest->stats);
                        __ip_vs_bind_svc(dest, svc);
                }
        }

        /* set the dest status flags */
        dest->flags |= IP_VS_DEST_F_AVAILABLE;

        if (udest->u_threshold == 0 || udest->u_threshold > dest->u_threshold)
                dest->flags &= ~IP_VS_DEST_F_OVERLOAD;
        dest->u_threshold = udest->u_threshold;
        dest->l_threshold = udest->l_threshold;

        spin_lock_bh(&dest->dst_lock);
        __ip_vs_dst_cache_reset(dest);
        spin_unlock_bh(&dest->dst_lock);

        sched = rcu_dereference_protected(svc->scheduler, 1);
        if (add) {
                ip_vs_start_estimator(svc->net, &dest->stats);
                list_add_rcu(&dest->n_list, &svc->destinations);
                svc->num_dests++;
                if (sched->add_dest)
                        sched->add_dest(svc, dest);
        } else {
                if (sched->upd_dest)
                        sched->upd_dest(svc, dest);
        }
}



All times are GMT -5. The time now is 11:28 AM.