diff options
Diffstat (limited to 'net/core')
-rw-r--r-- | net/core/dev.c | 38 | ||||
-rw-r--r-- | net/core/dev_addr_lists.c | 12 | ||||
-rw-r--r-- | net/core/drop_monitor.c | 12 | ||||
-rw-r--r-- | net/core/gen_estimator.c | 9 | ||||
-rw-r--r-- | net/core/net-sysfs.c | 34 | ||||
-rw-r--r-- | net/core/net_namespace.c | 10 |
6 files changed, 29 insertions, 86 deletions
diff --git a/net/core/dev.c b/net/core/dev.c index c2ac599fa0f6..b624fe4d9bd7 100644 --- a/net/core/dev.c +++ b/net/core/dev.c | |||
@@ -1284,11 +1284,13 @@ static int dev_close_many(struct list_head *head) | |||
1284 | */ | 1284 | */ |
1285 | int dev_close(struct net_device *dev) | 1285 | int dev_close(struct net_device *dev) |
1286 | { | 1286 | { |
1287 | LIST_HEAD(single); | 1287 | if (dev->flags & IFF_UP) { |
1288 | LIST_HEAD(single); | ||
1288 | 1289 | ||
1289 | list_add(&dev->unreg_list, &single); | 1290 | list_add(&dev->unreg_list, &single); |
1290 | dev_close_many(&single); | 1291 | dev_close_many(&single); |
1291 | list_del(&single); | 1292 | list_del(&single); |
1293 | } | ||
1292 | return 0; | 1294 | return 0; |
1293 | } | 1295 | } |
1294 | EXPORT_SYMBOL(dev_close); | 1296 | EXPORT_SYMBOL(dev_close); |
@@ -4773,7 +4775,7 @@ static int dev_ifsioc_locked(struct net *net, struct ifreq *ifr, unsigned int cm | |||
4773 | * is never reached | 4775 | * is never reached |
4774 | */ | 4776 | */ |
4775 | WARN_ON(1); | 4777 | WARN_ON(1); |
4776 | err = -EINVAL; | 4778 | err = -ENOTTY; |
4777 | break; | 4779 | break; |
4778 | 4780 | ||
4779 | } | 4781 | } |
@@ -5041,7 +5043,7 @@ int dev_ioctl(struct net *net, unsigned int cmd, void __user *arg) | |||
5041 | /* Set the per device memory buffer space. | 5043 | /* Set the per device memory buffer space. |
5042 | * Not applicable in our case */ | 5044 | * Not applicable in our case */ |
5043 | case SIOCSIFLINK: | 5045 | case SIOCSIFLINK: |
5044 | return -EINVAL; | 5046 | return -ENOTTY; |
5045 | 5047 | ||
5046 | /* | 5048 | /* |
5047 | * Unknown or private ioctl. | 5049 | * Unknown or private ioctl. |
@@ -5062,7 +5064,7 @@ int dev_ioctl(struct net *net, unsigned int cmd, void __user *arg) | |||
5062 | /* Take care of Wireless Extensions */ | 5064 | /* Take care of Wireless Extensions */ |
5063 | if (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST) | 5065 | if (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST) |
5064 | return wext_handle_ioctl(net, &ifr, cmd, arg); | 5066 | return wext_handle_ioctl(net, &ifr, cmd, arg); |
5065 | return -EINVAL; | 5067 | return -ENOTTY; |
5066 | } | 5068 | } |
5067 | } | 5069 | } |
5068 | 5070 | ||
@@ -5184,27 +5186,27 @@ u32 netdev_fix_features(struct net_device *dev, u32 features) | |||
5184 | /* Fix illegal checksum combinations */ | 5186 | /* Fix illegal checksum combinations */ |
5185 | if ((features & NETIF_F_HW_CSUM) && | 5187 | if ((features & NETIF_F_HW_CSUM) && |
5186 | (features & (NETIF_F_IP_CSUM|NETIF_F_IPV6_CSUM))) { | 5188 | (features & (NETIF_F_IP_CSUM|NETIF_F_IPV6_CSUM))) { |
5187 | netdev_info(dev, "mixed HW and IP checksum settings.\n"); | 5189 | netdev_warn(dev, "mixed HW and IP checksum settings.\n"); |
5188 | features &= ~(NETIF_F_IP_CSUM|NETIF_F_IPV6_CSUM); | 5190 | features &= ~(NETIF_F_IP_CSUM|NETIF_F_IPV6_CSUM); |
5189 | } | 5191 | } |
5190 | 5192 | ||
5191 | if ((features & NETIF_F_NO_CSUM) && | 5193 | if ((features & NETIF_F_NO_CSUM) && |
5192 | (features & (NETIF_F_HW_CSUM|NETIF_F_IP_CSUM|NETIF_F_IPV6_CSUM))) { | 5194 | (features & (NETIF_F_HW_CSUM|NETIF_F_IP_CSUM|NETIF_F_IPV6_CSUM))) { |
5193 | netdev_info(dev, "mixed no checksumming and other settings.\n"); | 5195 | netdev_warn(dev, "mixed no checksumming and other settings.\n"); |
5194 | features &= ~(NETIF_F_IP_CSUM|NETIF_F_IPV6_CSUM|NETIF_F_HW_CSUM); | 5196 | features &= ~(NETIF_F_IP_CSUM|NETIF_F_IPV6_CSUM|NETIF_F_HW_CSUM); |
5195 | } | 5197 | } |
5196 | 5198 | ||
5197 | /* Fix illegal SG+CSUM combinations. */ | 5199 | /* Fix illegal SG+CSUM combinations. */ |
5198 | if ((features & NETIF_F_SG) && | 5200 | if ((features & NETIF_F_SG) && |
5199 | !(features & NETIF_F_ALL_CSUM)) { | 5201 | !(features & NETIF_F_ALL_CSUM)) { |
5200 | netdev_info(dev, | 5202 | netdev_dbg(dev, |
5201 | "Dropping NETIF_F_SG since no checksum feature.\n"); | 5203 | "Dropping NETIF_F_SG since no checksum feature.\n"); |
5202 | features &= ~NETIF_F_SG; | 5204 | features &= ~NETIF_F_SG; |
5203 | } | 5205 | } |
5204 | 5206 | ||
5205 | /* TSO requires that SG is present as well. */ | 5207 | /* TSO requires that SG is present as well. */ |
5206 | if ((features & NETIF_F_ALL_TSO) && !(features & NETIF_F_SG)) { | 5208 | if ((features & NETIF_F_ALL_TSO) && !(features & NETIF_F_SG)) { |
5207 | netdev_info(dev, "Dropping TSO features since no SG feature.\n"); | 5209 | netdev_dbg(dev, "Dropping TSO features since no SG feature.\n"); |
5208 | features &= ~NETIF_F_ALL_TSO; | 5210 | features &= ~NETIF_F_ALL_TSO; |
5209 | } | 5211 | } |
5210 | 5212 | ||
@@ -5214,7 +5216,7 @@ u32 netdev_fix_features(struct net_device *dev, u32 features) | |||
5214 | 5216 | ||
5215 | /* Software GSO depends on SG. */ | 5217 | /* Software GSO depends on SG. */ |
5216 | if ((features & NETIF_F_GSO) && !(features & NETIF_F_SG)) { | 5218 | if ((features & NETIF_F_GSO) && !(features & NETIF_F_SG)) { |
5217 | netdev_info(dev, "Dropping NETIF_F_GSO since no SG feature.\n"); | 5219 | netdev_dbg(dev, "Dropping NETIF_F_GSO since no SG feature.\n"); |
5218 | features &= ~NETIF_F_GSO; | 5220 | features &= ~NETIF_F_GSO; |
5219 | } | 5221 | } |
5220 | 5222 | ||
@@ -5224,13 +5226,13 @@ u32 netdev_fix_features(struct net_device *dev, u32 features) | |||
5224 | if (!((features & NETIF_F_GEN_CSUM) || | 5226 | if (!((features & NETIF_F_GEN_CSUM) || |
5225 | (features & (NETIF_F_IP_CSUM|NETIF_F_IPV6_CSUM)) | 5227 | (features & (NETIF_F_IP_CSUM|NETIF_F_IPV6_CSUM)) |
5226 | == (NETIF_F_IP_CSUM|NETIF_F_IPV6_CSUM))) { | 5228 | == (NETIF_F_IP_CSUM|NETIF_F_IPV6_CSUM))) { |
5227 | netdev_info(dev, | 5229 | netdev_dbg(dev, |
5228 | "Dropping NETIF_F_UFO since no checksum offload features.\n"); | 5230 | "Dropping NETIF_F_UFO since no checksum offload features.\n"); |
5229 | features &= ~NETIF_F_UFO; | 5231 | features &= ~NETIF_F_UFO; |
5230 | } | 5232 | } |
5231 | 5233 | ||
5232 | if (!(features & NETIF_F_SG)) { | 5234 | if (!(features & NETIF_F_SG)) { |
5233 | netdev_info(dev, | 5235 | netdev_dbg(dev, |
5234 | "Dropping NETIF_F_UFO since no NETIF_F_SG feature.\n"); | 5236 | "Dropping NETIF_F_UFO since no NETIF_F_SG feature.\n"); |
5235 | features &= ~NETIF_F_UFO; | 5237 | features &= ~NETIF_F_UFO; |
5236 | } | 5238 | } |
@@ -5412,12 +5414,6 @@ int register_netdevice(struct net_device *dev) | |||
5412 | dev->features |= NETIF_F_SOFT_FEATURES; | 5414 | dev->features |= NETIF_F_SOFT_FEATURES; |
5413 | dev->wanted_features = dev->features & dev->hw_features; | 5415 | dev->wanted_features = dev->features & dev->hw_features; |
5414 | 5416 | ||
5415 | /* Avoid warning from netdev_fix_features() for GSO without SG */ | ||
5416 | if (!(dev->wanted_features & NETIF_F_SG)) { | ||
5417 | dev->wanted_features &= ~NETIF_F_GSO; | ||
5418 | dev->features &= ~NETIF_F_GSO; | ||
5419 | } | ||
5420 | |||
5421 | /* Enable GRO and NETIF_F_HIGHDMA for vlans by default, | 5417 | /* Enable GRO and NETIF_F_HIGHDMA for vlans by default, |
5422 | * vlan_dev_init() will do the dev->features check, so these features | 5418 | * vlan_dev_init() will do the dev->features check, so these features |
5423 | * are enabled only if supported by underlying device. | 5419 | * are enabled only if supported by underlying device. |
diff --git a/net/core/dev_addr_lists.c b/net/core/dev_addr_lists.c index 7b39f3ed2fda..e2e66939ed00 100644 --- a/net/core/dev_addr_lists.c +++ b/net/core/dev_addr_lists.c | |||
@@ -68,14 +68,6 @@ static int __hw_addr_add(struct netdev_hw_addr_list *list, unsigned char *addr, | |||
68 | return __hw_addr_add_ex(list, addr, addr_len, addr_type, false); | 68 | return __hw_addr_add_ex(list, addr, addr_len, addr_type, false); |
69 | } | 69 | } |
70 | 70 | ||
71 | static void ha_rcu_free(struct rcu_head *head) | ||
72 | { | ||
73 | struct netdev_hw_addr *ha; | ||
74 | |||
75 | ha = container_of(head, struct netdev_hw_addr, rcu_head); | ||
76 | kfree(ha); | ||
77 | } | ||
78 | |||
79 | static int __hw_addr_del_ex(struct netdev_hw_addr_list *list, | 71 | static int __hw_addr_del_ex(struct netdev_hw_addr_list *list, |
80 | unsigned char *addr, int addr_len, | 72 | unsigned char *addr, int addr_len, |
81 | unsigned char addr_type, bool global) | 73 | unsigned char addr_type, bool global) |
@@ -94,7 +86,7 @@ static int __hw_addr_del_ex(struct netdev_hw_addr_list *list, | |||
94 | if (--ha->refcount) | 86 | if (--ha->refcount) |
95 | return 0; | 87 | return 0; |
96 | list_del_rcu(&ha->list); | 88 | list_del_rcu(&ha->list); |
97 | call_rcu(&ha->rcu_head, ha_rcu_free); | 89 | kfree_rcu(ha, rcu_head); |
98 | list->count--; | 90 | list->count--; |
99 | return 0; | 91 | return 0; |
100 | } | 92 | } |
@@ -197,7 +189,7 @@ void __hw_addr_flush(struct netdev_hw_addr_list *list) | |||
197 | 189 | ||
198 | list_for_each_entry_safe(ha, tmp, &list->list, list) { | 190 | list_for_each_entry_safe(ha, tmp, &list->list, list) { |
199 | list_del_rcu(&ha->list); | 191 | list_del_rcu(&ha->list); |
200 | call_rcu(&ha->rcu_head, ha_rcu_free); | 192 | kfree_rcu(ha, rcu_head); |
201 | } | 193 | } |
202 | list->count = 0; | 194 | list->count = 0; |
203 | } | 195 | } |
diff --git a/net/core/drop_monitor.c b/net/core/drop_monitor.c index 706502ff64aa..7f36b38e060f 100644 --- a/net/core/drop_monitor.c +++ b/net/core/drop_monitor.c | |||
@@ -207,14 +207,6 @@ static void trace_napi_poll_hit(void *ignore, struct napi_struct *napi) | |||
207 | rcu_read_unlock(); | 207 | rcu_read_unlock(); |
208 | } | 208 | } |
209 | 209 | ||
210 | |||
211 | static void free_dm_hw_stat(struct rcu_head *head) | ||
212 | { | ||
213 | struct dm_hw_stat_delta *n; | ||
214 | n = container_of(head, struct dm_hw_stat_delta, rcu); | ||
215 | kfree(n); | ||
216 | } | ||
217 | |||
218 | static int set_all_monitor_traces(int state) | 210 | static int set_all_monitor_traces(int state) |
219 | { | 211 | { |
220 | int rc = 0; | 212 | int rc = 0; |
@@ -245,7 +237,7 @@ static int set_all_monitor_traces(int state) | |||
245 | list_for_each_entry_safe(new_stat, temp, &hw_stats_list, list) { | 237 | list_for_each_entry_safe(new_stat, temp, &hw_stats_list, list) { |
246 | if (new_stat->dev == NULL) { | 238 | if (new_stat->dev == NULL) { |
247 | list_del_rcu(&new_stat->list); | 239 | list_del_rcu(&new_stat->list); |
248 | call_rcu(&new_stat->rcu, free_dm_hw_stat); | 240 | kfree_rcu(new_stat, rcu); |
249 | } | 241 | } |
250 | } | 242 | } |
251 | break; | 243 | break; |
@@ -314,7 +306,7 @@ static int dropmon_net_event(struct notifier_block *ev_block, | |||
314 | new_stat->dev = NULL; | 306 | new_stat->dev = NULL; |
315 | if (trace_state == TRACE_OFF) { | 307 | if (trace_state == TRACE_OFF) { |
316 | list_del_rcu(&new_stat->list); | 308 | list_del_rcu(&new_stat->list); |
317 | call_rcu(&new_stat->rcu, free_dm_hw_stat); | 309 | kfree_rcu(new_stat, rcu); |
318 | break; | 310 | break; |
319 | } | 311 | } |
320 | } | 312 | } |
diff --git a/net/core/gen_estimator.c b/net/core/gen_estimator.c index 7c2373321b74..43b03dd71e85 100644 --- a/net/core/gen_estimator.c +++ b/net/core/gen_estimator.c | |||
@@ -249,13 +249,6 @@ int gen_new_estimator(struct gnet_stats_basic_packed *bstats, | |||
249 | } | 249 | } |
250 | EXPORT_SYMBOL(gen_new_estimator); | 250 | EXPORT_SYMBOL(gen_new_estimator); |
251 | 251 | ||
252 | static void __gen_kill_estimator(struct rcu_head *head) | ||
253 | { | ||
254 | struct gen_estimator *e = container_of(head, | ||
255 | struct gen_estimator, e_rcu); | ||
256 | kfree(e); | ||
257 | } | ||
258 | |||
259 | /** | 252 | /** |
260 | * gen_kill_estimator - remove a rate estimator | 253 | * gen_kill_estimator - remove a rate estimator |
261 | * @bstats: basic statistics | 254 | * @bstats: basic statistics |
@@ -279,7 +272,7 @@ void gen_kill_estimator(struct gnet_stats_basic_packed *bstats, | |||
279 | write_unlock(&est_lock); | 272 | write_unlock(&est_lock); |
280 | 273 | ||
281 | list_del_rcu(&e->list); | 274 | list_del_rcu(&e->list); |
282 | call_rcu(&e->e_rcu, __gen_kill_estimator); | 275 | kfree_rcu(e, e_rcu); |
283 | } | 276 | } |
284 | spin_unlock_bh(&est_tree_lock); | 277 | spin_unlock_bh(&est_tree_lock); |
285 | } | 278 | } |
diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c index 5ceb257e860c..80b2aad3b73d 100644 --- a/net/core/net-sysfs.c +++ b/net/core/net-sysfs.c | |||
@@ -565,13 +565,6 @@ static ssize_t show_rps_map(struct netdev_rx_queue *queue, | |||
565 | return len; | 565 | return len; |
566 | } | 566 | } |
567 | 567 | ||
568 | static void rps_map_release(struct rcu_head *rcu) | ||
569 | { | ||
570 | struct rps_map *map = container_of(rcu, struct rps_map, rcu); | ||
571 | |||
572 | kfree(map); | ||
573 | } | ||
574 | |||
575 | static ssize_t store_rps_map(struct netdev_rx_queue *queue, | 568 | static ssize_t store_rps_map(struct netdev_rx_queue *queue, |
576 | struct rx_queue_attribute *attribute, | 569 | struct rx_queue_attribute *attribute, |
577 | const char *buf, size_t len) | 570 | const char *buf, size_t len) |
@@ -619,7 +612,7 @@ static ssize_t store_rps_map(struct netdev_rx_queue *queue, | |||
619 | spin_unlock(&rps_map_lock); | 612 | spin_unlock(&rps_map_lock); |
620 | 613 | ||
621 | if (old_map) | 614 | if (old_map) |
622 | call_rcu(&old_map->rcu, rps_map_release); | 615 | kfree_rcu(old_map, rcu); |
623 | 616 | ||
624 | free_cpumask_var(mask); | 617 | free_cpumask_var(mask); |
625 | return len; | 618 | return len; |
@@ -728,7 +721,7 @@ static void rx_queue_release(struct kobject *kobj) | |||
728 | map = rcu_dereference_raw(queue->rps_map); | 721 | map = rcu_dereference_raw(queue->rps_map); |
729 | if (map) { | 722 | if (map) { |
730 | RCU_INIT_POINTER(queue->rps_map, NULL); | 723 | RCU_INIT_POINTER(queue->rps_map, NULL); |
731 | call_rcu(&map->rcu, rps_map_release); | 724 | kfree_rcu(map, rcu); |
732 | } | 725 | } |
733 | 726 | ||
734 | flow_table = rcu_dereference_raw(queue->rps_flow_table); | 727 | flow_table = rcu_dereference_raw(queue->rps_flow_table); |
@@ -898,21 +891,6 @@ static ssize_t show_xps_map(struct netdev_queue *queue, | |||
898 | return len; | 891 | return len; |
899 | } | 892 | } |
900 | 893 | ||
901 | static void xps_map_release(struct rcu_head *rcu) | ||
902 | { | ||
903 | struct xps_map *map = container_of(rcu, struct xps_map, rcu); | ||
904 | |||
905 | kfree(map); | ||
906 | } | ||
907 | |||
908 | static void xps_dev_maps_release(struct rcu_head *rcu) | ||
909 | { | ||
910 | struct xps_dev_maps *dev_maps = | ||
911 | container_of(rcu, struct xps_dev_maps, rcu); | ||
912 | |||
913 | kfree(dev_maps); | ||
914 | } | ||
915 | |||
916 | static DEFINE_MUTEX(xps_map_mutex); | 894 | static DEFINE_MUTEX(xps_map_mutex); |
917 | #define xmap_dereference(P) \ | 895 | #define xmap_dereference(P) \ |
918 | rcu_dereference_protected((P), lockdep_is_held(&xps_map_mutex)) | 896 | rcu_dereference_protected((P), lockdep_is_held(&xps_map_mutex)) |
@@ -1009,7 +987,7 @@ static ssize_t store_xps_map(struct netdev_queue *queue, | |||
1009 | map = dev_maps ? | 987 | map = dev_maps ? |
1010 | xmap_dereference(dev_maps->cpu_map[cpu]) : NULL; | 988 | xmap_dereference(dev_maps->cpu_map[cpu]) : NULL; |
1011 | if (map && xmap_dereference(new_dev_maps->cpu_map[cpu]) != map) | 989 | if (map && xmap_dereference(new_dev_maps->cpu_map[cpu]) != map) |
1012 | call_rcu(&map->rcu, xps_map_release); | 990 | kfree_rcu(map, rcu); |
1013 | if (new_dev_maps->cpu_map[cpu]) | 991 | if (new_dev_maps->cpu_map[cpu]) |
1014 | nonempty = 1; | 992 | nonempty = 1; |
1015 | } | 993 | } |
@@ -1022,7 +1000,7 @@ static ssize_t store_xps_map(struct netdev_queue *queue, | |||
1022 | } | 1000 | } |
1023 | 1001 | ||
1024 | if (dev_maps) | 1002 | if (dev_maps) |
1025 | call_rcu(&dev_maps->rcu, xps_dev_maps_release); | 1003 | kfree_rcu(dev_maps, rcu); |
1026 | 1004 | ||
1027 | netdev_queue_numa_node_write(queue, (numa_node >= 0) ? numa_node : | 1005 | netdev_queue_numa_node_write(queue, (numa_node >= 0) ? numa_node : |
1028 | NUMA_NO_NODE); | 1006 | NUMA_NO_NODE); |
@@ -1084,7 +1062,7 @@ static void netdev_queue_release(struct kobject *kobj) | |||
1084 | else { | 1062 | else { |
1085 | RCU_INIT_POINTER(dev_maps->cpu_map[i], | 1063 | RCU_INIT_POINTER(dev_maps->cpu_map[i], |
1086 | NULL); | 1064 | NULL); |
1087 | call_rcu(&map->rcu, xps_map_release); | 1065 | kfree_rcu(map, rcu); |
1088 | map = NULL; | 1066 | map = NULL; |
1089 | } | 1067 | } |
1090 | } | 1068 | } |
@@ -1094,7 +1072,7 @@ static void netdev_queue_release(struct kobject *kobj) | |||
1094 | 1072 | ||
1095 | if (!nonempty) { | 1073 | if (!nonempty) { |
1096 | RCU_INIT_POINTER(dev->xps_maps, NULL); | 1074 | RCU_INIT_POINTER(dev->xps_maps, NULL); |
1097 | call_rcu(&dev_maps->rcu, xps_dev_maps_release); | 1075 | kfree_rcu(dev_maps, rcu); |
1098 | } | 1076 | } |
1099 | } | 1077 | } |
1100 | 1078 | ||
diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c index 3f860261c5ee..297bb9272240 100644 --- a/net/core/net_namespace.c +++ b/net/core/net_namespace.c | |||
@@ -27,14 +27,6 @@ EXPORT_SYMBOL(init_net); | |||
27 | 27 | ||
28 | #define INITIAL_NET_GEN_PTRS 13 /* +1 for len +2 for rcu_head */ | 28 | #define INITIAL_NET_GEN_PTRS 13 /* +1 for len +2 for rcu_head */ |
29 | 29 | ||
30 | static void net_generic_release(struct rcu_head *rcu) | ||
31 | { | ||
32 | struct net_generic *ng; | ||
33 | |||
34 | ng = container_of(rcu, struct net_generic, rcu); | ||
35 | kfree(ng); | ||
36 | } | ||
37 | |||
38 | static int net_assign_generic(struct net *net, int id, void *data) | 30 | static int net_assign_generic(struct net *net, int id, void *data) |
39 | { | 31 | { |
40 | struct net_generic *ng, *old_ng; | 32 | struct net_generic *ng, *old_ng; |
@@ -68,7 +60,7 @@ static int net_assign_generic(struct net *net, int id, void *data) | |||
68 | memcpy(&ng->ptr, &old_ng->ptr, old_ng->len * sizeof(void*)); | 60 | memcpy(&ng->ptr, &old_ng->ptr, old_ng->len * sizeof(void*)); |
69 | 61 | ||
70 | rcu_assign_pointer(net->gen, ng); | 62 | rcu_assign_pointer(net->gen, ng); |
71 | call_rcu(&old_ng->rcu, net_generic_release); | 63 | kfree_rcu(old_ng, rcu); |
72 | assign: | 64 | assign: |
73 | ng->ptr[id - 1] = data; | 65 | ng->ptr[id - 1] = data; |
74 | return 0; | 66 | return 0; |