datapath: Eliminate vport_mutex by protecting vport table with RCU.
[sliver-openvswitch.git] / datapath / vport.c
1 /*
2  * Copyright (c) 2010, 2011 Nicira Networks.
3  * Distributed under the terms of the GNU GPL version 2.
4  *
5  * Significant portions of this file may be copied from parts of the Linux
6  * kernel, by Linus Torvalds and others.
7  */
8
9 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
10
11 #include <linux/dcache.h>
12 #include <linux/etherdevice.h>
13 #include <linux/if.h>
14 #include <linux/if_vlan.h>
15 #include <linux/kernel.h>
16 #include <linux/list.h>
17 #include <linux/mutex.h>
18 #include <linux/percpu.h>
19 #include <linux/rcupdate.h>
20 #include <linux/rtnetlink.h>
21 #include <linux/compat.h>
22 #include <linux/version.h>
23
24 #include "vport.h"
25 #include "vport-internal_dev.h"
26
27 /* List of statically compiled vport implementations.  Don't forget to also
28  * add yours to the list at the bottom of vport.h. */
29 static const struct vport_ops *base_vport_ops_list[] = {
30         &netdev_vport_ops,
31         &internal_vport_ops,
32         &patch_vport_ops,
33         &gre_vport_ops,
34 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26)
35         &capwap_vport_ops,
36 #endif
37 };
38
39 static const struct vport_ops **vport_ops_list;
40 static int n_vport_types;
41
42 /* Protected by RCU read lock for reading, RTNL lock for writing. */
43 static struct hlist_head *dev_table;
44 #define VPORT_HASH_BUCKETS 1024
45
46 /**
47  *      vport_init - initialize vport subsystem
48  *
49  * Called at module load time to initialize the vport subsystem and any
50  * compiled in vport types.
51  */
52 int vport_init(void)
53 {
54         int err;
55         int i;
56
57         dev_table = kzalloc(VPORT_HASH_BUCKETS * sizeof(struct hlist_head),
58                             GFP_KERNEL);
59         if (!dev_table) {
60                 err = -ENOMEM;
61                 goto error;
62         }
63
64         vport_ops_list = kmalloc(ARRAY_SIZE(base_vport_ops_list) *
65                                  sizeof(struct vport_ops *), GFP_KERNEL);
66         if (!vport_ops_list) {
67                 err = -ENOMEM;
68                 goto error_dev_table;
69         }
70
71         for (i = 0; i < ARRAY_SIZE(base_vport_ops_list); i++) {
72                 const struct vport_ops *new_ops = base_vport_ops_list[i];
73
74                 if (new_ops->init)
75                         err = new_ops->init();
76                 else
77                         err = 0;
78
79                 if (!err)
80                         vport_ops_list[n_vport_types++] = new_ops;
81                 else if (new_ops->flags & VPORT_F_REQUIRED) {
82                         vport_exit();
83                         goto error;
84                 }
85         }
86
87         return 0;
88
89 error_dev_table:
90         kfree(dev_table);
91 error:
92         return err;
93 }
94
95 /**
96  *      vport_exit - shutdown vport subsystem
97  *
98  * Called at module exit time to shutdown the vport subsystem and any
99  * initialized vport types.
100  */
101 void vport_exit(void)
102 {
103         int i;
104
105         for (i = 0; i < n_vport_types; i++) {
106                 if (vport_ops_list[i]->exit)
107                         vport_ops_list[i]->exit();
108         }
109
110         kfree(vport_ops_list);
111         kfree(dev_table);
112 }
113
114 static struct hlist_head *hash_bucket(const char *name)
115 {
116         unsigned int hash = full_name_hash(name, strlen(name));
117         return &dev_table[hash & (VPORT_HASH_BUCKETS - 1)];
118 }
119
120 /**
121  *      vport_locate - find a port that has already been created
122  *
123  * @name: name of port to find
124  *
125  * Must be called with RTNL or RCU read lock.
126  */
127 struct vport *vport_locate(const char *name)
128 {
129         struct hlist_head *bucket = hash_bucket(name);
130         struct vport *vport;
131         struct hlist_node *node;
132
133         hlist_for_each_entry_rcu(vport, node, bucket, hash_node)
134                 if (!strcmp(name, vport_get_name(vport)))
135                         return vport;
136
137         return NULL;
138 }
139
140 static void release_vport(struct kobject *kobj)
141 {
142         struct vport *p = container_of(kobj, struct vport, kobj);
143         kfree(p);
144 }
145
146 static struct kobj_type brport_ktype = {
147 #ifdef CONFIG_SYSFS
148         .sysfs_ops = &brport_sysfs_ops,
149 #endif
150         .release = release_vport
151 };
152
153 /**
154  *      vport_alloc - allocate and initialize new vport
155  *
156  * @priv_size: Size of private data area to allocate.
157  * @ops: vport device ops
158  *
159  * Allocate and initialize a new vport defined by @ops.  The vport will contain
160  * a private data area of size @priv_size that can be accessed using
161  * vport_priv().  vports that are no longer needed should be released with
162  * vport_free().
163  */
164 struct vport *vport_alloc(int priv_size, const struct vport_ops *ops, const struct vport_parms *parms)
165 {
166         struct vport *vport;
167         size_t alloc_size;
168
169         alloc_size = sizeof(struct vport);
170         if (priv_size) {
171                 alloc_size = ALIGN(alloc_size, VPORT_ALIGN);
172                 alloc_size += priv_size;
173         }
174
175         vport = kzalloc(alloc_size, GFP_KERNEL);
176         if (!vport)
177                 return ERR_PTR(-ENOMEM);
178
179         vport->dp = parms->dp;
180         vport->port_no = parms->port_no;
181         atomic_set(&vport->sflow_pool, 0);
182         vport->ops = ops;
183
184         /* Initialize kobject for bridge.  This will be added as
185          * /sys/class/net/<devname>/brport later, if sysfs is enabled. */
186         vport->kobj.kset = NULL;
187         kobject_init(&vport->kobj, &brport_ktype);
188
189         if (vport->ops->flags & VPORT_F_GEN_STATS) {
190                 vport->percpu_stats = alloc_percpu(struct vport_percpu_stats);
191                 if (!vport->percpu_stats)
192                         return ERR_PTR(-ENOMEM);
193
194                 spin_lock_init(&vport->stats_lock);
195         }
196
197         return vport;
198 }
199
200 /**
201  *      vport_free - uninitialize and free vport
202  *
203  * @vport: vport to free
204  *
205  * Frees a vport allocated with vport_alloc() when it is no longer needed.
206  *
207  * The caller must ensure that an RCU grace period has passed since the last
208  * time @vport was in a datapath.
209  */
210 void vport_free(struct vport *vport)
211 {
212         if (vport->ops->flags & VPORT_F_GEN_STATS)
213                 free_percpu(vport->percpu_stats);
214
215         kobject_put(&vport->kobj);
216 }
217
218 /**
219  *      vport_add - add vport device (for kernel callers)
220  *
221  * @parms: Information about new vport.
222  *
223  * Creates a new vport with the specified configuration (which is dependent on
224  * device type) and attaches it to a datapath.  RTNL lock must be held.
225  */
226 struct vport *vport_add(const struct vport_parms *parms)
227 {
228         struct vport *vport;
229         int err = 0;
230         int i;
231
232         ASSERT_RTNL();
233
234         for (i = 0; i < n_vport_types; i++) {
235                 if (vport_ops_list[i]->type == parms->type) {
236                         vport = vport_ops_list[i]->create(parms);
237                         if (IS_ERR(vport)) {
238                                 err = PTR_ERR(vport);
239                                 goto out;
240                         }
241
242                         hlist_add_head_rcu(&vport->hash_node,
243                                            hash_bucket(vport_get_name(vport)));
244                         return vport;
245                 }
246         }
247
248         err = -EAFNOSUPPORT;
249
250 out:
251         return ERR_PTR(err);
252 }
253
254 /**
255  *      vport_set_options - modify existing vport device (for kernel callers)
256  *
257  * @vport: vport to modify.
258  * @port: New configuration.
259  *
260  * Modifies an existing device with the specified configuration (which is
261  * dependent on device type).  RTNL lock must be held.
262  */
263 int vport_set_options(struct vport *vport, struct nlattr *options)
264 {
265         ASSERT_RTNL();
266
267         if (!vport->ops->set_options)
268                 return -EOPNOTSUPP;
269         return vport->ops->set_options(vport, options);
270 }
271
272 /**
273  *      vport_del - delete existing vport device (for kernel callers)
274  *
275  * @vport: vport to delete.
276  *
277  * Detaches @vport from its datapath and destroys it.  It is possible to fail
278  * for reasons such as lack of memory.  RTNL lock must be held.
279  */
280 int vport_del(struct vport *vport)
281 {
282         ASSERT_RTNL();
283
284         hlist_del_rcu(&vport->hash_node);
285
286         return vport->ops->destroy(vport);
287 }
288
289 /**
290  *      vport_set_mtu - set device MTU (for kernel callers)
291  *
292  * @vport: vport on which to set MTU.
293  * @mtu: New MTU.
294  *
295  * Sets the MTU of the given device.  Some devices may not support setting the
296  * MTU, in which case the result will always be -EOPNOTSUPP.  RTNL lock must
297  * be held.
298  */
299 int vport_set_mtu(struct vport *vport, int mtu)
300 {
301         ASSERT_RTNL();
302
303         if (mtu < 68)
304                 return -EINVAL;
305
306         if (vport->ops->set_mtu) {
307                 int ret;
308
309                 ret = vport->ops->set_mtu(vport, mtu);
310
311                 if (!ret && !is_internal_vport(vport))
312                         set_internal_devs_mtu(vport->dp);
313
314                 return ret;
315         } else
316                 return -EOPNOTSUPP;
317 }
318
319 /**
320  *      vport_set_addr - set device Ethernet address (for kernel callers)
321  *
322  * @vport: vport on which to set Ethernet address.
323  * @addr: New address.
324  *
325  * Sets the Ethernet address of the given device.  Some devices may not support
326  * setting the Ethernet address, in which case the result will always be
327  * -EOPNOTSUPP.  RTNL lock must be held.
328  */
329 int vport_set_addr(struct vport *vport, const unsigned char *addr)
330 {
331         ASSERT_RTNL();
332
333         if (!is_valid_ether_addr(addr))
334                 return -EADDRNOTAVAIL;
335
336         if (vport->ops->set_addr)
337                 return vport->ops->set_addr(vport, addr);
338         else
339                 return -EOPNOTSUPP;
340 }
341
342 /**
343  *      vport_set_stats - sets offset device stats (for kernel callers)
344  *
345  * @vport: vport on which to set stats
346  * @stats: stats to set
347  *
348  * Provides a set of transmit, receive, and error stats to be added as an
349  * offset to the collect data when stats are retreived.  Some devices may not
350  * support setting the stats, in which case the result will always be
351  * -EOPNOTSUPP.  RTNL lock must be held.
352  */
353 int vport_set_stats(struct vport *vport, struct rtnl_link_stats64 *stats)
354 {
355         ASSERT_RTNL();
356
357         if (vport->ops->flags & VPORT_F_GEN_STATS) {
358                 spin_lock_bh(&vport->stats_lock);
359                 vport->offset_stats = *stats;
360                 spin_unlock_bh(&vport->stats_lock);
361
362                 return 0;
363         } else
364                 return -EOPNOTSUPP;
365 }
366
367 /**
368  *      vport_get_name - retrieve device name
369  *
370  * @vport: vport from which to retrieve the name.
371  *
372  * Retrieves the name of the given device.  Either RTNL lock or rcu_read_lock
373  * must be held for the entire duration that the name is in use.
374  */
375 const char *vport_get_name(const struct vport *vport)
376 {
377         return vport->ops->get_name(vport);
378 }
379
380 /**
381  *      vport_get_type - retrieve device type
382  *
383  * @vport: vport from which to retrieve the type.
384  *
385  * Retrieves the type of the given device.  Either RTNL lock or rcu_read_lock
386  * must be held.
387  */
388 enum odp_vport_type vport_get_type(const struct vport *vport)
389 {
390         return vport->ops->type;
391 }
392
393 /**
394  *      vport_get_addr - retrieve device Ethernet address (for kernel callers)
395  *
396  * @vport: vport from which to retrieve the Ethernet address.
397  *
398  * Retrieves the Ethernet address of the given device.  Either RTNL lock or
399  * rcu_read_lock must be held for the entire duration that the Ethernet address
400  * is in use.
401  */
402 const unsigned char *vport_get_addr(const struct vport *vport)
403 {
404         return vport->ops->get_addr(vport);
405 }
406
407 /**
408  *      vport_get_kobj - retrieve associated kobj
409  *
410  * @vport: vport from which to retrieve the associated kobj
411  *
412  * Retrieves the associated kobj or null if no kobj.  The returned kobj is
413  * valid for as long as the vport exists.
414  */
415 struct kobject *vport_get_kobj(const struct vport *vport)
416 {
417         if (vport->ops->get_kobj)
418                 return vport->ops->get_kobj(vport);
419         else
420                 return NULL;
421 }
422
423 static int vport_call_get_stats(struct vport *vport, struct rtnl_link_stats64 *stats)
424 {
425         int err;
426
427         rcu_read_lock();
428         err = vport->ops->get_stats(vport, stats);
429         rcu_read_unlock();
430
431         return err;
432 }
433
434 /**
435  *      vport_get_stats - retrieve device stats (for kernel callers)
436  *
437  * @vport: vport from which to retrieve the stats
438  * @stats: location to store stats
439  *
440  * Retrieves transmit, receive, and error stats for the given device.
441  */
442 int vport_get_stats(struct vport *vport, struct rtnl_link_stats64 *stats)
443 {
444         int i;
445
446         if (!(vport->ops->flags & VPORT_F_GEN_STATS))
447                 return vport_call_get_stats(vport, stats);
448
449         /* We potentially have 3 sources of stats that need to be
450          * combined: those we have collected (split into err_stats and
451          * percpu_stats), offset_stats from set_stats(), and device
452          * error stats from get_stats() (for errors that happen
453          * downstream and therefore aren't reported through our
454          * vport_record_error() function). */
455
456         spin_lock_bh(&vport->stats_lock);
457
458         *stats = vport->offset_stats;
459
460         stats->rx_errors        += vport->err_stats.rx_errors;
461         stats->tx_errors        += vport->err_stats.tx_errors;
462         stats->tx_dropped       += vport->err_stats.tx_dropped;
463         stats->rx_dropped       += vport->err_stats.rx_dropped;
464
465         spin_unlock_bh(&vport->stats_lock);
466
467         if (vport->ops->get_stats) {
468                 struct rtnl_link_stats64 dev_stats;
469                 int err;
470
471                 err = vport_call_get_stats(vport, &dev_stats);
472                 if (err)
473                         return err;
474
475                 stats->rx_errors           += dev_stats.rx_errors;
476                 stats->tx_errors           += dev_stats.tx_errors;
477                 stats->rx_dropped          += dev_stats.rx_dropped;
478                 stats->tx_dropped          += dev_stats.tx_dropped;
479                 stats->multicast           += dev_stats.multicast;
480                 stats->collisions          += dev_stats.collisions;
481                 stats->rx_length_errors    += dev_stats.rx_length_errors;
482                 stats->rx_over_errors      += dev_stats.rx_over_errors;
483                 stats->rx_crc_errors       += dev_stats.rx_crc_errors;
484                 stats->rx_frame_errors     += dev_stats.rx_frame_errors;
485                 stats->rx_fifo_errors      += dev_stats.rx_fifo_errors;
486                 stats->rx_missed_errors    += dev_stats.rx_missed_errors;
487                 stats->tx_aborted_errors   += dev_stats.tx_aborted_errors;
488                 stats->tx_carrier_errors   += dev_stats.tx_carrier_errors;
489                 stats->tx_fifo_errors      += dev_stats.tx_fifo_errors;
490                 stats->tx_heartbeat_errors += dev_stats.tx_heartbeat_errors;
491                 stats->tx_window_errors    += dev_stats.tx_window_errors;
492                 stats->rx_compressed       += dev_stats.rx_compressed;
493                 stats->tx_compressed       += dev_stats.tx_compressed;
494         }
495
496         for_each_possible_cpu(i) {
497                 const struct vport_percpu_stats *percpu_stats;
498                 struct vport_percpu_stats local_stats;
499                 unsigned seqcount;
500
501                 percpu_stats = per_cpu_ptr(vport->percpu_stats, i);
502
503                 do {
504                         seqcount = read_seqcount_begin(&percpu_stats->seqlock);
505                         local_stats = *percpu_stats;
506                 } while (read_seqcount_retry(&percpu_stats->seqlock, seqcount));
507
508                 stats->rx_bytes         += local_stats.rx_bytes;
509                 stats->rx_packets       += local_stats.rx_packets;
510                 stats->tx_bytes         += local_stats.tx_bytes;
511                 stats->tx_packets       += local_stats.tx_packets;
512         }
513
514         return 0;
515 }
516
517 /**
518  *      vport_get_flags - retrieve device flags
519  *
520  * @vport: vport from which to retrieve the flags
521  *
522  * Retrieves the flags of the given device.  Either RTNL lock or rcu_read_lock
523  * must be held.
524  */
525 unsigned vport_get_flags(const struct vport *vport)
526 {
527         return vport->ops->get_dev_flags(vport);
528 }
529
530 /**
531  *      vport_get_flags - check whether device is running
532  *
533  * @vport: vport on which to check status.
534  *
535  * Checks whether the given device is running.  Either RTNL lock or
536  * rcu_read_lock must be held.
537  */
538 int vport_is_running(const struct vport *vport)
539 {
540         return vport->ops->is_running(vport);
541 }
542
543 /**
544  *      vport_get_flags - retrieve device operating state
545  *
546  * @vport: vport from which to check status
547  *
548  * Retrieves the RFC2863 operstate of the given device.  Either RTNL lock or
549  * rcu_read_lock must be held.
550  */
551 unsigned char vport_get_operstate(const struct vport *vport)
552 {
553         return vport->ops->get_operstate(vport);
554 }
555
556 /**
557  *      vport_get_ifindex - retrieve device system interface index
558  *
559  * @vport: vport from which to retrieve index
560  *
561  * Retrieves the system interface index of the given device or 0 if
562  * the device does not have one (in the case of virtual ports).
563  * Returns a negative index on error. Either RTNL lock or
564  * rcu_read_lock must be held.
565  */
566 int vport_get_ifindex(const struct vport *vport)
567 {
568         if (vport->ops->get_ifindex)
569                 return vport->ops->get_ifindex(vport);
570         else
571                 return 0;
572 }
573
574 /**
575  *      vport_get_iflink - retrieve device system link index
576  *
577  * @vport: vport from which to retrieve index
578  *
579  * Retrieves the system link index of the given device.  The link is the index
580  * of the interface on which the packet will actually be sent.  In most cases
581  * this is the same as the ifindex but may be different for tunnel devices.
582  * Returns a negative index on error.  Either RTNL lock or rcu_read_lock must
583  * be held.
584  */
585 int vport_get_iflink(const struct vport *vport)
586 {
587         if (vport->ops->get_iflink)
588                 return vport->ops->get_iflink(vport);
589
590         /* If we don't have an iflink, use the ifindex.  In most cases they
591          * are the same. */
592         return vport_get_ifindex(vport);
593 }
594
595 /**
596  *      vport_get_mtu - retrieve device MTU (for kernel callers)
597  *
598  * @vport: vport from which to retrieve MTU
599  *
600  * Retrieves the MTU of the given device.  Either RTNL lock or rcu_read_lock
601  * must be held.
602  */
603 int vport_get_mtu(const struct vport *vport)
604 {
605         return vport->ops->get_mtu(vport);
606 }
607
608 /**
609  *      vport_get_options - retrieve device options
610  *
611  * @vport: vport from which to retrieve the options.
612  * @skb: sk_buff where options should be appended.
613  *
614  * Retrieves the configuration of the given device, appending an
615  * %ODP_VPORT_ATTR_OPTIONS attribute that in turn contains nested
616  * vport-specific attributes to @skb.  Either RTNL lock or rcu_read_lock must
617  * be held.
618  *
619  * Returns 0 if successful, -EMSGSIZE if @skb has insufficient room, or another
620  * negative error code if a real error occurred.
621  */
622 int vport_get_options(const struct vport *vport, struct sk_buff *skb)
623 {
624         struct nlattr *nla;
625
626         nla = nla_nest_start(skb, ODP_VPORT_ATTR_OPTIONS);
627         if (!nla)
628                 return -EMSGSIZE;
629
630         if (vport->ops->get_options) {
631                 int err = vport->ops->get_options(vport, skb);
632                 if (err)
633                         return err;
634         }
635
636         nla_nest_end(skb, nla);
637         return 0;
638 }
639
640 /**
641  *      vport_receive - pass up received packet to the datapath for processing
642  *
643  * @vport: vport that received the packet
644  * @skb: skb that was received
645  *
646  * Must be called with rcu_read_lock.  The packet cannot be shared and
647  * skb->data should point to the Ethernet header.  The caller must have already
648  * called compute_ip_summed() to initialize the checksumming fields.
649  */
650 void vport_receive(struct vport *vport, struct sk_buff *skb)
651 {
652         if (vport->ops->flags & VPORT_F_GEN_STATS) {
653                 struct vport_percpu_stats *stats;
654
655                 local_bh_disable();
656                 stats = per_cpu_ptr(vport->percpu_stats, smp_processor_id());
657
658                 write_seqcount_begin(&stats->seqlock);
659                 stats->rx_packets++;
660                 stats->rx_bytes += skb->len;
661                 write_seqcount_end(&stats->seqlock);
662
663                 local_bh_enable();
664         }
665
666         if (!(vport->ops->flags & VPORT_F_FLOW))
667                 OVS_CB(skb)->flow = NULL;
668
669         if (!(vport->ops->flags & VPORT_F_TUN_ID))
670                 OVS_CB(skb)->tun_id = 0;
671
672         dp_process_received_packet(vport, skb);
673 }
674
675 static inline unsigned packet_length(const struct sk_buff *skb)
676 {
677         unsigned length = skb->len - ETH_HLEN;
678
679         if (skb->protocol == htons(ETH_P_8021Q))
680                 length -= VLAN_HLEN;
681
682         return length;
683 }
684
685 /**
686  *      vport_send - send a packet on a device
687  *
688  * @vport: vport on which to send the packet
689  * @skb: skb to send
690  *
691  * Sends the given packet and returns the length of data sent.  Either RTNL
692  * lock or rcu_read_lock must be held.
693  */
694 int vport_send(struct vport *vport, struct sk_buff *skb)
695 {
696         int mtu;
697         int sent;
698
699         mtu = vport_get_mtu(vport);
700         if (unlikely(packet_length(skb) > mtu && !skb_is_gso(skb))) {
701                 if (net_ratelimit())
702                         pr_warn("%s: dropped over-mtu packet: %d > %d\n",
703                                 dp_name(vport->dp), packet_length(skb), mtu);
704                 goto error;
705         }
706
707         sent = vport->ops->send(vport, skb);
708
709         if (vport->ops->flags & VPORT_F_GEN_STATS && sent > 0) {
710                 struct vport_percpu_stats *stats;
711
712                 local_bh_disable();
713                 stats = per_cpu_ptr(vport->percpu_stats, smp_processor_id());
714
715                 write_seqcount_begin(&stats->seqlock);
716                 stats->tx_packets++;
717                 stats->tx_bytes += sent;
718                 write_seqcount_end(&stats->seqlock);
719
720                 local_bh_enable();
721         }
722
723         return sent;
724
725 error:
726         kfree_skb(skb);
727         vport_record_error(vport, VPORT_E_TX_DROPPED);
728         return 0;
729 }
730
731 /**
732  *      vport_record_error - indicate device error to generic stats layer
733  *
734  * @vport: vport that encountered the error
735  * @err_type: one of enum vport_err_type types to indicate the error type
736  *
737  * If using the vport generic stats layer indicate that an error of the given
738  * type has occured.
739  */
740 void vport_record_error(struct vport *vport, enum vport_err_type err_type)
741 {
742         if (vport->ops->flags & VPORT_F_GEN_STATS) {
743
744                 spin_lock_bh(&vport->stats_lock);
745
746                 switch (err_type) {
747                 case VPORT_E_RX_DROPPED:
748                         vport->err_stats.rx_dropped++;
749                         break;
750
751                 case VPORT_E_RX_ERROR:
752                         vport->err_stats.rx_errors++;
753                         break;
754
755                 case VPORT_E_TX_DROPPED:
756                         vport->err_stats.tx_dropped++;
757                         break;
758
759                 case VPORT_E_TX_ERROR:
760                         vport->err_stats.tx_errors++;
761                         break;
762                 };
763
764                 spin_unlock_bh(&vport->stats_lock);
765         }
766 }