]> git.kernelconcepts.de Git - karo-tx-linux.git/commitdiff
Merge branch 'nf' of git://1984.lsi.us.es/net
authorDavid S. Miller <davem@davemloft.net>
Mon, 17 Oct 2011 23:38:03 +0000 (19:38 -0400)
committerDavid S. Miller <davem@davemloft.net>
Mon, 17 Oct 2011 23:38:03 +0000 (19:38 -0400)
1  2 
net/netfilter/ipvs/ip_vs_ctl.c

index 5290ac353a5ec70de401918b09566f3209db9049,3e5e08b78bfcfd53daf7adc85606db8e7d5e03cc..e3be48bf4dcdb0779c0a20072e43839b8e01d9fc
@@@ -2283,6 -2283,7 +2283,7 @@@ do_ip_vs_set_ctl(struct sock *sk, int c
        struct ip_vs_service *svc;
        struct ip_vs_dest_user *udest_compat;
        struct ip_vs_dest_user_kern udest;
+       struct netns_ipvs *ipvs = net_ipvs(net);
  
        if (!capable(CAP_NET_ADMIN))
                return -EPERM;
        /* increase the module use count */
        ip_vs_use_count_inc();
  
+       /* Handle daemons since they have another lock */
+       if (cmd == IP_VS_SO_SET_STARTDAEMON ||
+           cmd == IP_VS_SO_SET_STOPDAEMON) {
+               struct ip_vs_daemon_user *dm = (struct ip_vs_daemon_user *)arg;
+               if (mutex_lock_interruptible(&ipvs->sync_mutex)) {
+                       ret = -ERESTARTSYS;
+                       goto out_dec;
+               }
+               if (cmd == IP_VS_SO_SET_STARTDAEMON)
+                       ret = start_sync_thread(net, dm->state, dm->mcast_ifn,
+                                               dm->syncid);
+               else
+                       ret = stop_sync_thread(net, dm->state);
+               mutex_unlock(&ipvs->sync_mutex);
+               goto out_dec;
+       }
        if (mutex_lock_interruptible(&__ip_vs_mutex)) {
                ret = -ERESTARTSYS;
                goto out_dec;
                /* Set timeout values for (tcp tcpfin udp) */
                ret = ip_vs_set_timeout(net, (struct ip_vs_timeout_user *)arg);
                goto out_unlock;
-       } else if (cmd == IP_VS_SO_SET_STARTDAEMON) {
-               struct ip_vs_daemon_user *dm = (struct ip_vs_daemon_user *)arg;
-               ret = start_sync_thread(net, dm->state, dm->mcast_ifn,
-                                       dm->syncid);
-               goto out_unlock;
-       } else if (cmd == IP_VS_SO_SET_STOPDAEMON) {
-               struct ip_vs_daemon_user *dm = (struct ip_vs_daemon_user *)arg;
-               ret = stop_sync_thread(net, dm->state);
-               goto out_unlock;
        }
  
        usvc_compat = (struct ip_vs_service_user *)arg;
@@@ -2584,6 -2594,33 +2594,33 @@@ do_ip_vs_get_ctl(struct sock *sk, int c
  
        if (copy_from_user(arg, user, copylen) != 0)
                return -EFAULT;
+       /*
+        * Handle daemons first since it has its own locking
+        */
+       if (cmd == IP_VS_SO_GET_DAEMON) {
+               struct ip_vs_daemon_user d[2];
+               memset(&d, 0, sizeof(d));
+               if (mutex_lock_interruptible(&ipvs->sync_mutex))
+                       return -ERESTARTSYS;
+               if (ipvs->sync_state & IP_VS_STATE_MASTER) {
+                       d[0].state = IP_VS_STATE_MASTER;
+                       strlcpy(d[0].mcast_ifn, ipvs->master_mcast_ifn,
+                               sizeof(d[0].mcast_ifn));
+                       d[0].syncid = ipvs->master_syncid;
+               }
+               if (ipvs->sync_state & IP_VS_STATE_BACKUP) {
+                       d[1].state = IP_VS_STATE_BACKUP;
+                       strlcpy(d[1].mcast_ifn, ipvs->backup_mcast_ifn,
+                               sizeof(d[1].mcast_ifn));
+                       d[1].syncid = ipvs->backup_syncid;
+               }
+               if (copy_to_user(user, &d, sizeof(d)) != 0)
+                       ret = -EFAULT;
+               mutex_unlock(&ipvs->sync_mutex);
+               return ret;
+       }
  
        if (mutex_lock_interruptible(&__ip_vs_mutex))
                return -ERESTARTSYS;
        }
        break;
  
-       case IP_VS_SO_GET_DAEMON:
-       {
-               struct ip_vs_daemon_user d[2];
-               memset(&d, 0, sizeof(d));
-               if (ipvs->sync_state & IP_VS_STATE_MASTER) {
-                       d[0].state = IP_VS_STATE_MASTER;
-                       strlcpy(d[0].mcast_ifn, ipvs->master_mcast_ifn,
-                               sizeof(d[0].mcast_ifn));
-                       d[0].syncid = ipvs->master_syncid;
-               }
-               if (ipvs->sync_state & IP_VS_STATE_BACKUP) {
-                       d[1].state = IP_VS_STATE_BACKUP;
-                       strlcpy(d[1].mcast_ifn, ipvs->backup_mcast_ifn,
-                               sizeof(d[1].mcast_ifn));
-                       d[1].syncid = ipvs->backup_syncid;
-               }
-               if (copy_to_user(user, &d, sizeof(d)) != 0)
-                       ret = -EFAULT;
-       }
-       break;
        default:
                ret = -EINVAL;
        }
@@@ -3205,7 -3220,7 +3220,7 @@@ static int ip_vs_genl_dump_daemons(stru
        struct net *net = skb_sknet(skb);
        struct netns_ipvs *ipvs = net_ipvs(net);
  
-       mutex_lock(&__ip_vs_mutex);
+       mutex_lock(&ipvs->sync_mutex);
        if ((ipvs->sync_state & IP_VS_STATE_MASTER) && !cb->args[0]) {
                if (ip_vs_genl_dump_daemon(skb, IP_VS_STATE_MASTER,
                                           ipvs->master_mcast_ifn,
        }
  
  nla_put_failure:
-       mutex_unlock(&__ip_vs_mutex);
+       mutex_unlock(&ipvs->sync_mutex);
  
        return skb->len;
  }
@@@ -3271,13 -3286,9 +3286,9 @@@ static int ip_vs_genl_set_config(struc
        return ip_vs_set_timeout(net, &t);
  }
  
- static int ip_vs_genl_set_cmd(struct sk_buff *skb, struct genl_info *info)
+ static int ip_vs_genl_set_daemon(struct sk_buff *skb, struct genl_info *info)
  {
-       struct ip_vs_service *svc = NULL;
-       struct ip_vs_service_user_kern usvc;
-       struct ip_vs_dest_user_kern udest;
        int ret = 0, cmd;
-       int need_full_svc = 0, need_full_dest = 0;
        struct net *net;
        struct netns_ipvs *ipvs;
  
        ipvs = net_ipvs(net);
        cmd = info->genlhdr->cmd;
  
-       mutex_lock(&__ip_vs_mutex);
-       if (cmd == IPVS_CMD_FLUSH) {
-               ret = ip_vs_flush(net);
-               goto out;
-       } else if (cmd == IPVS_CMD_SET_CONFIG) {
-               ret = ip_vs_genl_set_config(net, info->attrs);
-               goto out;
-       } else if (cmd == IPVS_CMD_NEW_DAEMON ||
-                  cmd == IPVS_CMD_DEL_DAEMON) {
+       if (cmd == IPVS_CMD_NEW_DAEMON || cmd == IPVS_CMD_DEL_DAEMON) {
                struct nlattr *daemon_attrs[IPVS_DAEMON_ATTR_MAX + 1];
  
+               mutex_lock(&ipvs->sync_mutex);
                if (!info->attrs[IPVS_CMD_ATTR_DAEMON] ||
                    nla_parse_nested(daemon_attrs, IPVS_DAEMON_ATTR_MAX,
                                     info->attrs[IPVS_CMD_ATTR_DAEMON],
                        ret = ip_vs_genl_new_daemon(net, daemon_attrs);
                else
                        ret = ip_vs_genl_del_daemon(net, daemon_attrs);
+ out:
+               mutex_unlock(&ipvs->sync_mutex);
+       }
+       return ret;
+ }
+ static int ip_vs_genl_set_cmd(struct sk_buff *skb, struct genl_info *info)
+ {
+       struct ip_vs_service *svc = NULL;
+       struct ip_vs_service_user_kern usvc;
+       struct ip_vs_dest_user_kern udest;
+       int ret = 0, cmd;
+       int need_full_svc = 0, need_full_dest = 0;
+       struct net *net;
+       struct netns_ipvs *ipvs;
+       net = skb_sknet(skb);
+       ipvs = net_ipvs(net);
+       cmd = info->genlhdr->cmd;
+       mutex_lock(&__ip_vs_mutex);
+       if (cmd == IPVS_CMD_FLUSH) {
+               ret = ip_vs_flush(net);
+               goto out;
+       } else if (cmd == IPVS_CMD_SET_CONFIG) {
+               ret = ip_vs_genl_set_config(net, info->attrs);
                goto out;
        } else if (cmd == IPVS_CMD_ZERO &&
                   !info->attrs[IPVS_CMD_ATTR_SERVICE]) {
@@@ -3536,13 -3565,13 +3565,13 @@@ static struct genl_ops ip_vs_genl_ops[
                .cmd    = IPVS_CMD_NEW_DAEMON,
                .flags  = GENL_ADMIN_PERM,
                .policy = ip_vs_cmd_policy,
-               .doit   = ip_vs_genl_set_cmd,
+               .doit   = ip_vs_genl_set_daemon,
        },
        {
                .cmd    = IPVS_CMD_DEL_DAEMON,
                .flags  = GENL_ADMIN_PERM,
                .policy = ip_vs_cmd_policy,
-               .doit   = ip_vs_genl_set_cmd,
+               .doit   = ip_vs_genl_set_daemon,
        },
        {
                .cmd    = IPVS_CMD_GET_DAEMON,
@@@ -3679,7 -3708,7 +3708,7 @@@ int __net_init ip_vs_control_net_init(s
        int idx;
        struct netns_ipvs *ipvs = net_ipvs(net);
  
 -      ipvs->rs_lock = __RW_LOCK_UNLOCKED(ipvs->rs_lock);
 +      rwlock_init(&ipvs->rs_lock);
  
        /* Initialize rs_table */
        for (idx = 0; idx < IP_VS_RTAB_SIZE; idx++)