~n-muench/ubuntu/quantal/open-vm-tools/open-vm-tools.may2.sid-sync

« back to all changes in this revision

Viewing changes to modules/linux/vsock/linux/notify.c

  • Committer: Bazaar Package Importer
  • Author(s): Daniel Baumann
  • Date: 2009-05-30 09:48:43 UTC
  • mfrom: (1.1.5 upstream) (2.4.4 squeeze)
  • Revision ID: james.westby@ubuntu.com-20090530094843-gdpza57r5iqsf124
Tags: 2009.05.22-167859-1
MergingĀ upstreamĀ versionĀ 2009.05.22-167859.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*********************************************************
 
2
 * Copyright (C) 2009 VMware, Inc. All rights reserved.
 
3
 *
 
4
 * This program is free software; you can redistribute it and/or modify it
 
5
 * under the terms of the GNU General Public License as published by the
 
6
 * Free Software Foundation version 2 and no later version.
 
7
 *
 
8
 * This program is distributed in the hope that it will be useful, but
 
9
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 
10
 * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 
11
 * for more details.
 
12
 *
 
13
 * You should have received a copy of the GNU General Public License along
 
14
 * with this program; if not, write to the Free Software Foundation, Inc.,
 
15
 * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
 
16
 *
 
17
 *********************************************************/
 
18
 
 
19
/*
 
20
 * notify.c --
 
21
 *
 
22
 *      Linux control notifications for the VMCI Stream Sockets protocol.
 
23
 */
 
24
 
 
25
 
 
26
#include "driver-config.h"
 
27
 
 
28
#include <linux/socket.h>
 
29
 
 
30
#include "compat_sock.h"
 
31
 
 
32
#include "notify.h"
 
33
#include "af_vsock.h"
 
34
 
 
35
#define PKT_FIELD(vsk, fieldName) \
 
36
   (vsk)->notify.fieldName
 
37
 
 
38
#define VSOCK_MAX_DGRAM_RESENDS       10
 
39
 
 
40
 
 
41
/*
 
42
 *----------------------------------------------------------------------------
 
43
 *
 
44
 * VSockVmciNotifyWaitingWrite --
 
45
 *
 
46
 *      Determines if the conditions have been met to notify a waiting writer.
 
47
 *
 
48
 * Results:
 
49
 *      TRUE if a notification should be sent, FALSE otherwise.
 
50
 *
 
51
 * Side effects:
 
52
 *      None.
 
53
 *
 
54
 *----------------------------------------------------------------------------
 
55
 */
 
56
 
 
57
static Bool
 
58
VSockVmciNotifyWaitingWrite(VSockVmciSock *vsk)    // IN
 
59
{
 
60
#if defined(VSOCK_OPTIMIZATION_WAITING_NOTIFY)
 
61
   Bool retval;
 
62
   uint64 notifyLimit;
 
63
 
 
64
   if (!PKT_FIELD(vsk, peerWaitingWrite)) {
 
65
      return FALSE;
 
66
   }
 
67
 
 
68
#ifdef VSOCK_OPTIMIZATION_FLOW_CONTROL
 
69
   /*
 
70
    * When the sender blocks, we take that as a sign that the sender
 
71
    * is faster than the receiver. To reduce the transmit rate of the
 
72
    * sender, we delay the sending of the read notification by
 
73
    * decreasing the writeNotifyWindow. The notification is delayed
 
74
    * until the number of bytes used in the queue drops below the
 
75
    * writeNotifyWindow.
 
76
    */
 
77
 
 
78
   if (!PKT_FIELD(vsk, peerWaitingWriteDetected)) {
 
79
      PKT_FIELD(vsk, peerWaitingWriteDetected) = TRUE;
 
80
      PKT_FIELD(vsk, writeNotifyWindow) -= PAGE_SIZE;
 
81
      if (PKT_FIELD(vsk, writeNotifyWindow) <
 
82
                    PKT_FIELD(vsk, writeNotifyMinWindow)) {
 
83
         PKT_FIELD(vsk, writeNotifyWindow) =
 
84
            PKT_FIELD(vsk, writeNotifyMinWindow);
 
85
      }
 
86
   }
 
87
   notifyLimit = vsk->consumeSize - PKT_FIELD(vsk, writeNotifyWindow);
 
88
#else
 
89
   notifyLimit = 0;
 
90
#endif // VSOCK_OPTIMIZATION_FLOW_CONTROL
 
91
 
 
92
   /*
 
93
    * For now we ignore the wait information and just see if the free
 
94
    * space exceeds the notify limit.  Note that improving this
 
95
    * function to be more intelligent will not require a protocol
 
96
    * change and will retain compatibility between endpoints with
 
97
    * mixed versions of this function.
 
98
    *
 
99
    * The notifyLimit is used to delay notifications in the case where
 
100
    * flow control is enabled. Below the test is expressed in terms of
 
101
    * free space in the queue:
 
102
    *   if freeSpace > ConsumeSize - writeNotifyWindow then notify
 
103
    * An alternate way of expressing this is to rewrite the expression
 
104
    * to use the data ready in the receive queue:
 
105
    *   if writeNotifyWindow > bufferReady then notify
 
106
    * as freeSpace == ConsumeSize - bufferReady.
 
107
    */
 
108
   retval = VMCIQueue_FreeSpace(vsk->consumeQ, vsk->produceQ, vsk->consumeSize) >
 
109
            notifyLimit;
 
110
#ifdef VSOCK_OPTIMIZATION_FLOW_CONTROL
 
111
   if (retval) {
 
112
      /*
 
113
       * Once we notify the peer, we reset the detected flag so the
 
114
       * next wait will again cause a decrease in the window size.
 
115
       */
 
116
 
 
117
      PKT_FIELD(vsk, peerWaitingWriteDetected) = FALSE;
 
118
   }
 
119
#endif // VSOCK_OPTIMIZATION_FLOW_CONTROL
 
120
   return retval;
 
121
#else
 
122
   return TRUE;
 
123
#endif
 
124
}
 
125
 
 
126
 
 
127
/*
 
128
 *----------------------------------------------------------------------------
 
129
 *
 
130
 * VSockVmciNotifyWaitingRead --
 
131
 *
 
132
v *      Determines if the conditions have been met to notify a waiting reader.
 
133
 *
 
134
 * Results:
 
135
 *      TRUE if a notification should be sent, FALSE otherwise.
 
136
 *
 
137
 * Side effects:
 
138
 *      None.
 
139
 *
 
140
 *----------------------------------------------------------------------------
 
141
 */
 
142
 
 
143
static Bool
 
144
VSockVmciNotifyWaitingRead(VSockVmciSock *vsk)  // IN
 
145
{
 
146
#if defined(VSOCK_OPTIMIZATION_WAITING_NOTIFY)
 
147
   if (!PKT_FIELD(vsk, peerWaitingRead)) {
 
148
      return FALSE;
 
149
   }
 
150
 
 
151
   /*
 
152
    * For now we ignore the wait information and just see if there is any data
 
153
    * for our peer to read.  Note that improving this function to be more intelligent will
 
154
    * not require a protocol change and will retain compatibility between
 
155
    * endpoints with mixed versions of this function.
 
156
    */
 
157
   return VMCIQueue_BufReady(vsk->produceQ,
 
158
                             vsk->consumeQ, vsk->produceSize) > 0;
 
159
#else
 
160
   return TRUE;
 
161
#endif
 
162
}
 
163
 
 
164
 
 
165
/*
 
166
 *----------------------------------------------------------------------------
 
167
 *
 
168
 * VSockVmciHandleWaitingRead --
 
169
 *
 
170
 *      Handles an incoming waiting read message.
 
171
 *
 
172
 * Results:
 
173
 *      None.
 
174
 *
 
175
 * Side effects:
 
176
 *      May send a notification to the peer, may update socket's wait info
 
177
 *      structure.
 
178
 *
 
179
 *----------------------------------------------------------------------------
 
180
 */
 
181
 
 
182
static void
 
183
VSockVmciHandleWaitingRead(struct sock *sk,             // IN
 
184
                           VSockPacket *pkt,            // IN
 
185
                           Bool bottomHalf,             // IN
 
186
                           struct sockaddr_vm *dst,     // IN
 
187
                           struct sockaddr_vm *src)     // IN
 
188
{
 
189
#if defined(VSOCK_OPTIMIZATION_WAITING_NOTIFY)
 
190
   VSockVmciSock *vsk;
 
191
 
 
192
   vsk = vsock_sk(sk);
 
193
 
 
194
   PKT_FIELD(vsk, peerWaitingRead) = TRUE;
 
195
   memcpy(&PKT_FIELD(vsk, peerWaitingReadInfo), &pkt->u.wait,
 
196
          sizeof PKT_FIELD(vsk, peerWaitingReadInfo));
 
197
 
 
198
   if (VSockVmciNotifyWaitingRead(vsk)) {
 
199
      Bool sent;
 
200
 
 
201
      if (bottomHalf) {
 
202
         sent = VSOCK_SEND_WROTE_BH(dst, src) > 0;
 
203
      } else {
 
204
         sent = VSOCK_SEND_WROTE(sk) > 0;
 
205
      }
 
206
 
 
207
      if (sent) {
 
208
         PKT_FIELD(vsk, peerWaitingRead) = FALSE;
 
209
      }
 
210
   }
 
211
#endif
 
212
}
 
213
 
 
214
 
 
215
/*
 
216
 *----------------------------------------------------------------------------
 
217
 *
 
218
 * VSockVmciHandleWaitingWrite --
 
219
 *
 
220
 *      Handles an incoming waiting write message.
 
221
 *
 
222
 * Results:
 
223
 *      None.
 
224
 *
 
225
 * Side effects:
 
226
 *      May send a notification to the peer, may update socket's wait info
 
227
 *      structure.
 
228
 *
 
229
 *----------------------------------------------------------------------------
 
230
 */
 
231
 
 
232
static void
 
233
VSockVmciHandleWaitingWrite(struct sock *sk,            // IN
 
234
                            VSockPacket *pkt,           // IN
 
235
                            Bool bottomHalf,            // IN
 
236
                            struct sockaddr_vm *dst,    // IN
 
237
                            struct sockaddr_vm *src)    // IN
 
238
{
 
239
#if defined(VSOCK_OPTIMIZATION_WAITING_NOTIFY)
 
240
   VSockVmciSock *vsk;
 
241
 
 
242
   vsk = vsock_sk(sk);
 
243
 
 
244
   PKT_FIELD(vsk, peerWaitingWrite) = TRUE;
 
245
   memcpy(&PKT_FIELD(vsk, peerWaitingWriteInfo), &pkt->u.wait,
 
246
          sizeof PKT_FIELD(vsk,peerWaitingWriteInfo));
 
247
 
 
248
   if (VSockVmciNotifyWaitingWrite(vsk)) {
 
249
      Bool sent;
 
250
 
 
251
      if (bottomHalf) {
 
252
         sent = VSOCK_SEND_READ_BH(dst, src) > 0;
 
253
      } else {
 
254
         sent = VSOCK_SEND_READ(sk) > 0;
 
255
      }
 
256
 
 
257
      if (sent) {
 
258
         PKT_FIELD(vsk, peerWaitingWrite) = FALSE;
 
259
      }
 
260
   }
 
261
#endif
 
262
}
 
263
 
 
264
 
 
265
/*
 
266
 *----------------------------------------------------------------------------
 
267
 *
 
268
 * VSockVmciHandleRead --
 
269
 *
 
270
 *      Handles an incoming read message.
 
271
 *
 
272
 * Results:
 
273
 *      None.
 
274
 *
 
275
 * Side effects:
 
276
 *      None.
 
277
 *
 
278
 *----------------------------------------------------------------------------
 
279
 */
 
280
 
 
281
static void
 
282
VSockVmciHandleRead(struct sock *sk,            // IN
 
283
                    VSockPacket *pkt,           // IN: unused
 
284
                    Bool bottomHalf,            // IN: unused
 
285
                    struct sockaddr_vm *dst,    // IN: unused
 
286
                    struct sockaddr_vm *src)    // IN: unused
 
287
{
 
288
#if defined(VSOCK_OPTIMIZATION_WAITING_NOTIFY)
 
289
   VSockVmciSock *vsk;
 
290
 
 
291
   vsk = vsock_sk(sk);
 
292
   PKT_FIELD(vsk, sentWaitingWrite) = FALSE;
 
293
#endif
 
294
 
 
295
   sk->compat_sk_write_space(sk);
 
296
}
 
297
 
 
298
 
 
299
/*
 
300
 *----------------------------------------------------------------------------
 
301
 *
 
302
 * VSockVmciSendWaitingRead --
 
303
 *
 
304
 *      Sends a waiting read notification to this socket's peer.
 
305
 *
 
306
 * Results:
 
307
 *      TRUE if the datagram is sent successfully, FALSE otherwise.
 
308
 *
 
309
 * Side effects:
 
310
 *      Our peer will notify us when there is data to read from our consume
 
311
 *      queue.
 
312
 *
 
313
 *----------------------------------------------------------------------------
 
314
 */
 
315
 
 
316
static Bool
 
317
VSockVmciSendWaitingRead(struct sock *sk,    // IN
 
318
                         uint64 roomNeeded)  // IN
 
319
{
 
320
#if defined(VSOCK_OPTIMIZATION_WAITING_NOTIFY)
 
321
   VSockVmciSock *vsk;
 
322
   VSockWaitingInfo waitingInfo;
 
323
   uint64 tail;
 
324
   uint64 head;
 
325
   uint64 roomLeft;
 
326
   Bool ret;
 
327
 
 
328
   ASSERT(sk);
 
329
 
 
330
   vsk = vsock_sk(sk);
 
331
 
 
332
   if (PKT_FIELD(vsk, sentWaitingRead)) {
 
333
      return TRUE;
 
334
   }
 
335
 
 
336
   if (PKT_FIELD(vsk, writeNotifyWindow) < vsk->consumeSize) {
 
337
      PKT_FIELD(vsk, writeNotifyWindow) =
 
338
         MIN(PKT_FIELD(vsk, writeNotifyWindow) + PAGE_SIZE,
 
339
             vsk->consumeSize);
 
340
   }
 
341
 
 
342
   VMCIQueue_GetPointers(vsk->consumeQ, vsk->produceQ, &tail, &head);
 
343
   roomLeft = vsk->consumeSize - head;
 
344
   if (roomNeeded >= roomLeft) {
 
345
      waitingInfo.offset = roomNeeded - roomLeft;
 
346
      waitingInfo.generation = PKT_FIELD(vsk, consumeQGeneration) + 1;
 
347
   } else {
 
348
      waitingInfo.offset = head + roomNeeded;
 
349
      waitingInfo.generation = PKT_FIELD(vsk, consumeQGeneration);
 
350
   }
 
351
 
 
352
   ret = VSOCK_SEND_WAITING_READ(sk, &waitingInfo) > 0;
 
353
   if (ret) {
 
354
      PKT_FIELD(vsk, sentWaitingRead) = TRUE;
 
355
   }
 
356
   return ret;
 
357
#else
 
358
   return TRUE;
 
359
#endif
 
360
}
 
361
 
 
362
 
 
363
/*
 
364
 *----------------------------------------------------------------------------
 
365
 *
 
366
 * VSockVmciSendWaitingWrite --
 
367
 *
 
368
 *      Sends a waiting write notification to this socket's peer.
 
369
 *
 
370
 * Results:
 
371
 *      TRUE if the datagram is sent successfully or does not need to be sent.
 
372
 *      FALSE otherwise.
 
373
 *
 
374
 * Side effects:
 
375
 *      Our peer will notify us when there is room to write in to our produce
 
376
 *      queue.
 
377
 *
 
378
 *----------------------------------------------------------------------------
 
379
 */
 
380
 
 
381
static Bool
 
382
VSockVmciSendWaitingWrite(struct sock *sk,   // IN
 
383
                          uint64 roomNeeded) // IN
 
384
{
 
385
#if defined(VSOCK_OPTIMIZATION_WAITING_NOTIFY)
 
386
   VSockVmciSock *vsk;
 
387
   VSockWaitingInfo waitingInfo;
 
388
   uint64 tail;
 
389
   uint64 head;
 
390
   uint64 roomLeft;
 
391
   Bool ret;
 
392
 
 
393
   ASSERT(sk);
 
394
 
 
395
   vsk = vsock_sk(sk);
 
396
 
 
397
   if (PKT_FIELD(vsk, sentWaitingWrite)) {
 
398
      return TRUE;
 
399
   }
 
400
 
 
401
   VMCIQueue_GetPointers(vsk->produceQ, vsk->consumeQ, &tail, &head);
 
402
   roomLeft = vsk->produceSize - tail;
 
403
   if (roomNeeded + 1 >= roomLeft) {
 
404
      /* Wraps around to current generation. */
 
405
      waitingInfo.offset = roomNeeded + 1 - roomLeft;
 
406
      waitingInfo.generation = PKT_FIELD(vsk, produceQGeneration);
 
407
   } else {
 
408
      waitingInfo.offset = tail + roomNeeded + 1;
 
409
      waitingInfo.generation = PKT_FIELD(vsk, produceQGeneration) - 1;
 
410
   }
 
411
 
 
412
   ret = VSOCK_SEND_WAITING_WRITE(sk, &waitingInfo) > 0;
 
413
   if (ret) {
 
414
      PKT_FIELD(vsk, sentWaitingWrite) = TRUE;
 
415
   }
 
416
   return ret;
 
417
#else
 
418
   return TRUE;
 
419
#endif
 
420
}
 
421
 
 
422
 
 
423
/*
 
424
 *----------------------------------------------------------------------------
 
425
 *
 
426
 * VSockVmciSendReadNotification --
 
427
 *
 
428
 *      Sends a read notification to this socket's peer.
 
429
 *
 
430
 * Results:
 
431
 *      >= 0 if the datagram is sent successfully, negative error value
 
432
 *      otherwise.
 
433
 *
 
434
 * Side effects:
 
435
 *      None.
 
436
 *
 
437
 *----------------------------------------------------------------------------
 
438
 */
 
439
 
 
440
static int
 
441
VSockVmciSendReadNotification(struct sock *sk)  // IN
 
442
{
 
443
   VSockVmciSock *vsk;
 
444
   Bool sentRead;
 
445
   unsigned int retries;
 
446
   int err;
 
447
 
 
448
   ASSERT(sk);
 
449
 
 
450
   vsk = vsock_sk(sk);
 
451
   sentRead = FALSE;
 
452
   retries = 0;
 
453
   err = 0;
 
454
 
 
455
   if (VSockVmciNotifyWaitingWrite(vsk)) {
 
456
      /*
 
457
       * Notify the peer that we have read, retrying the send on failure up to our
 
458
       * maximum value.  XXX For now we just log the failure, but later we should
 
459
       * schedule a work item to handle the resend until it succeeds.  That would
 
460
       * require keeping track of work items in the vsk and cleaning them up upon
 
461
       * socket close.
 
462
       */
 
463
      while (!(vsk->peerShutdown & RCV_SHUTDOWN) &&
 
464
             !sentRead &&
 
465
             retries < VSOCK_MAX_DGRAM_RESENDS) {
 
466
         err = VSOCK_SEND_READ(sk);
 
467
         if (err >= 0) {
 
468
            sentRead = TRUE;
 
469
         }
 
470
 
 
471
         retries++;
 
472
      }
 
473
 
 
474
      if (retries >= VSOCK_MAX_DGRAM_RESENDS) {
 
475
         Warning("unable to send read notification to peer for socket %p.\n", sk);
 
476
      } else {
 
477
#if defined(VSOCK_OPTIMIZATION_WAITING_NOTIFY)
 
478
         PKT_FIELD(vsk, peerWaitingWrite) = FALSE;
 
479
#endif
 
480
      }
 
481
   }
 
482
   return err;
 
483
}
 
484
 
 
485
 
 
486
/*
 
487
 *----------------------------------------------------------------------------
 
488
 *
 
489
 * VSockVmciHandleWrote --
 
490
 *
 
491
 *      Handles an incoming wrote message.
 
492
 *
 
493
 * Results:
 
494
 *      None.
 
495
 *
 
496
 * Side effects:
 
497
 *      None.
 
498
 *
 
499
 *----------------------------------------------------------------------------
 
500
 */
 
501
 
 
502
static void
 
503
VSockVmciHandleWrote(struct sock *sk,            // IN
 
504
                     VSockPacket *pkt,           // IN: unused
 
505
                     Bool bottomHalf,            // IN: unused
 
506
                     struct sockaddr_vm *dst,    // IN: unused
 
507
                     struct sockaddr_vm *src)    // IN: unused
 
508
{
 
509
#if defined(VSOCK_OPTIMIZATION_WAITING_NOTIFY)
 
510
   VSockVmciSock *vsk;
 
511
 
 
512
   vsk = vsock_sk(sk);
 
513
   PKT_FIELD(vsk, sentWaitingRead) = FALSE;
 
514
#endif
 
515
 
 
516
   sk->compat_sk_data_ready(sk, 0);
 
517
}
 
518
 
 
519
 
 
520
/*
 
521
 *----------------------------------------------------------------------------
 
522
 *
 
523
 * VSockVmciNotifyPktSocketInit --
 
524
 *
 
525
 *      Function that is called after a socket is created and before any
 
526
 *      notify ops are used.
 
527
 *
 
528
 * Results:
 
529
 *      None.
 
530
 *
 
531
 * Side effects:
 
532
 *      None.
 
533
 *
 
534
 *----------------------------------------------------------------------------
 
535
 */
 
536
 
 
537
static void
 
538
VSockVmciNotifyPktSocketInit(struct sock *sk) // IN
 
539
{
 
540
   VSockVmciSock *vsk;
 
541
   vsk = vsock_sk(sk);
 
542
 
 
543
   PKT_FIELD(vsk, writeNotifyWindow) = 0;
 
544
   PKT_FIELD(vsk, writeNotifyMinWindow) = PAGE_SIZE;
 
545
   PKT_FIELD(vsk, peerWaitingRead) = FALSE;
 
546
   PKT_FIELD(vsk, peerWaitingWrite) = FALSE;
 
547
   PKT_FIELD(vsk, peerWaitingWriteDetected) = FALSE;
 
548
   PKT_FIELD(vsk, sentWaitingRead) = FALSE;
 
549
   PKT_FIELD(vsk, sentWaitingWrite) = FALSE;
 
550
   PKT_FIELD(vsk, produceQGeneration) = 0;
 
551
   PKT_FIELD(vsk, consumeQGeneration) = 0;
 
552
 
 
553
   memset(&PKT_FIELD(vsk, peerWaitingReadInfo), 0,
 
554
          sizeof PKT_FIELD(vsk, peerWaitingReadInfo));
 
555
   memset(&PKT_FIELD(vsk, peerWaitingWriteInfo), 0,
 
556
          sizeof PKT_FIELD(vsk, peerWaitingWriteInfo));
 
557
}
 
558
 
 
559
 
 
560
/*
 
561
 *----------------------------------------------------------------------------
 
562
 *
 
563
 * VSockVmciNotifyPktSocketDestruct --
 
564
 *
 
565
 *      Function that is called when the socket is being released.
 
566
 *
 
567
 * Results:
 
568
 *      None.
 
569
 *
 
570
 * Side effects:
 
571
 *      None.
 
572
 *
 
573
 *----------------------------------------------------------------------------
 
574
 */
 
575
 
 
576
static void
 
577
VSockVmciNotifyPktSocketDestruct(struct sock *sk) // IN
 
578
{
 
579
   return;
 
580
}
 
581
 
 
582
 
 
583
/*
 
584
 *----------------------------------------------------------------------------
 
585
 *
 
586
 * VSockVmciNotifyPktPollIn --
 
587
 *
 
588
 *      Called by the poll function to figure out if there is data to read
 
589
 *      and to setup future notifications if needed. Only called on sockets
 
590
 *      that aren't shutdown for recv.
 
591
 *
 
592
 * Results:
 
593
 *      0 on success. Negative error on failure.
 
594
 *
 
595
 * Side effects:
 
596
 *      None.
 
597
 *
 
598
 *----------------------------------------------------------------------------
 
599
 */
 
600
 
 
601
static int32
 
602
VSockVmciNotifyPktPollIn(struct sock *sk,    // IN
 
603
                         int target,         // IN
 
604
                         Bool *dataReadyNow) // IN
 
605
{
 
606
   VSockVmciSock *vsk;
 
607
 
 
608
   ASSERT(sk);
 
609
   ASSERT(dataReadyNow);
 
610
 
 
611
   vsk = vsock_sk(sk);
 
612
 
 
613
   if (VSockVmciStreamHasData(vsk)) {
 
614
      *dataReadyNow = TRUE;
 
615
   } else {
 
616
      /*
 
617
       * We can't read right now because there is nothing in the queue.
 
618
       * Ask for notifications when there is something to read.
 
619
       */
 
620
      if (sk->compat_sk_state == SS_CONNECTED) {
 
621
         if (!VSockVmciSendWaitingRead(sk, 1)) {
 
622
            return -1;
 
623
         }
 
624
      }
 
625
      *dataReadyNow = FALSE;
 
626
   }
 
627
 
 
628
   return 0;
 
629
}
 
630
 
 
631
 
 
632
/*
 
633
 *----------------------------------------------------------------------------
 
634
 *
 
635
 * VSockVmciNotifyPktPollOut
 
636
 *
 
637
 *      Called by the poll function to figure out if there is space to write
 
638
 *      and to setup future notifications if needed. Only called on a
 
639
 *      connected socket that isn't shutdown for send.
 
640
 *
 
641
 * Results:
 
642
 *      0 on success. Negative error on failure.
 
643
 *
 
644
 * Side effects:
 
645
 *      None.
 
646
 *
 
647
 *----------------------------------------------------------------------------
 
648
 */
 
649
 
 
650
static int32
 
651
VSockVmciNotifyPktPollOut(struct sock *sk,     // IN
 
652
                          int target,          // IN
 
653
                          Bool *spaceAvailNow) // IN
 
654
{
 
655
   int64 produceQFreeSpace;
 
656
   VSockVmciSock *vsk;
 
657
 
 
658
   ASSERT(sk);
 
659
   ASSERT(spaceAvailNow);
 
660
 
 
661
   vsk = vsock_sk(sk);
 
662
 
 
663
   produceQFreeSpace =
 
664
      VSockVmciStreamHasSpace(vsk);
 
665
   if (produceQFreeSpace > 0) {
 
666
      *spaceAvailNow = TRUE;
 
667
      return 0;
 
668
   } else if (produceQFreeSpace == 0) {
 
669
      /*
 
670
       * This is a connected socket but we can't currently send data. Notify
 
671
       * the peer that we are waiting if the queue is full.
 
672
       * We only send a waiting write if the queue is full because otherwise
 
673
       * we end up in an infinite WAITING_WRITE, READ, WAITING_WRITE, READ, etc.
 
674
       * loop. Treat failing to send the notification as a socket error, passing
 
675
       * that back through the mask.
 
676
       */
 
677
      if (!VSockVmciSendWaitingWrite(sk, 1)) {
 
678
         return -1;
 
679
      }
 
680
      *spaceAvailNow = FALSE;
 
681
   }
 
682
 
 
683
   return 0;
 
684
}
 
685
 
 
686
 
 
687
/*
 
688
 *----------------------------------------------------------------------------
 
689
 *
 
690
 * VSockVmciNotifyPktRecvInit --
 
691
 *
 
692
 *      Called at the start of a stream recv call with the socket lock held.
 
693
 *
 
694
 * Results:
 
695
 *      0 on success. Negative error on failure.
 
696
 *
 
697
 * Side effects:
 
698
 *      None.
 
699
 *
 
700
 *----------------------------------------------------------------------------
 
701
 */
 
702
 
 
703
static int32
 
704
VSockVmciNotifyPktRecvInit(struct sock *sk,               // IN
 
705
                           int target,                    // IN
 
706
                           VSockVmciRecvNotifyData *data) // IN
 
707
{
 
708
   VSockVmciSock *vsk;
 
709
 
 
710
   ASSERT(sk);
 
711
   ASSERT(data);
 
712
 
 
713
   vsk = vsock_sk(sk);
 
714
 
 
715
#ifdef VSOCK_OPTIMIZATION_WAITING_NOTIFY
 
716
   data->consumeHead = 0;
 
717
   data->produceTail = 0;
 
718
#ifdef VSOCK_OPTIMIZATION_FLOW_CONTROL
 
719
   data->notifyOnBlock = FALSE;
 
720
 
 
721
   if (PKT_FIELD(vsk, writeNotifyMinWindow) < target + 1) {
 
722
      ASSERT(target < vsk->consumeSize);
 
723
      PKT_FIELD(vsk, writeNotifyMinWindow) = target + 1;
 
724
      if (PKT_FIELD(vsk, writeNotifyWindow) <
 
725
          PKT_FIELD(vsk, writeNotifyMinWindow)) {
 
726
         /*
 
727
          * If the current window is smaller than the new minimal
 
728
          * window size, we need to reevaluate whether we need to
 
729
          * notify the sender. If the number of ready bytes are
 
730
          * smaller than the new window, we need to send a
 
731
          * notification to the sender before we block.
 
732
          */
 
733
 
 
734
         PKT_FIELD(vsk, writeNotifyWindow) =
 
735
            PKT_FIELD(vsk, writeNotifyMinWindow);
 
736
         data->notifyOnBlock = TRUE;
 
737
      }
 
738
   }
 
739
#endif
 
740
#endif
 
741
 
 
742
   return 0;
 
743
}
 
744
 
 
745
 
 
746
/*
 
747
 *----------------------------------------------------------------------------
 
748
 *
 
749
 * VSockVmciNotifyPktRecvPreBlock --
 
750
 *
 
751
 *      Called right before a socket is about to block with the socket lock
 
752
 *      held. The socket lock may have been released between the entry
 
753
 *      function and the preblock call.
 
754
 *
 
755
 *      Note: This function may be called multiple times before the post
 
756
 *      block function is called.
 
757
 *
 
758
 * Results:
 
759
 *      0 on success. Negative error on failure.
 
760
 *
 
761
 * Side effects:
 
762
 *      None.
 
763
 *
 
764
 *----------------------------------------------------------------------------
 
765
 */
 
766
 
 
767
static int32
 
768
VSockVmciNotifyPktRecvPreBlock(struct sock *sk,               // IN
 
769
                               int target,                    // IN
 
770
                               VSockVmciRecvNotifyData *data) // IN
 
771
{
 
772
   VSockVmciSock *vsk;
 
773
   int err;
 
774
 
 
775
   ASSERT(sk);
 
776
   ASSERT(data);
 
777
 
 
778
   vsk = vsock_sk(sk);
 
779
   err = 0;
 
780
 
 
781
   /* Notify our peer that we are waiting for data to read. */
 
782
   if (!VSockVmciSendWaitingRead(sk, target)) {
 
783
      err = -EHOSTUNREACH;
 
784
      return err;
 
785
   }
 
786
 
 
787
#ifdef VSOCK_OPTIMIZATION_FLOW_CONTROL
 
788
   if (data->notifyOnBlock) {
 
789
      err = VSockVmciSendReadNotification(sk);
 
790
      if (err < 0) {
 
791
         return err;
 
792
      }
 
793
      data->notifyOnBlock = FALSE;
 
794
   }
 
795
#endif
 
796
 
 
797
   return err;
 
798
}
 
799
 
 
800
 
 
801
/*
 
802
 *----------------------------------------------------------------------------
 
803
 *
 
804
 * VSockVmciNotifyPktRecvPreDequeue --
 
805
 *
 
806
 *      Called right before we dequeue / peek data from a socket.
 
807
 *
 
808
 * Results:
 
809
 *      0 on success. Negative error on failure.
 
810
 *
 
811
 * Side effects:
 
812
 *      None.
 
813
 *
 
814
 *----------------------------------------------------------------------------
 
815
 */
 
816
 
 
817
static int32
 
818
VSockVmciNotifyPktRecvPreDequeue(struct sock *sk,               // IN
 
819
                                 int target,                    // IN
 
820
                                 VSockVmciRecvNotifyData *data) // IN
 
821
{
 
822
   VSockVmciSock *vsk;
 
823
 
 
824
   ASSERT(sk);
 
825
   ASSERT(data);
 
826
 
 
827
   vsk = vsock_sk(sk);
 
828
 
 
829
   /*
 
830
    * Now consume up to len bytes from the queue.  Note that since we have the
 
831
    * socket locked we should copy at least ready bytes.
 
832
    */
 
833
#if defined(VSOCK_OPTIMIZATION_WAITING_NOTIFY)
 
834
   VMCIQueue_GetPointers(vsk->consumeQ, vsk->produceQ,
 
835
                         &data->produceTail, &data->consumeHead);
 
836
#endif
 
837
 
 
838
   return 0;
 
839
}
 
840
 
 
841
 
 
842
/*
 
843
 *----------------------------------------------------------------------------
 
844
 *
 
845
 * VSockVmciNotifyPktRecvPostDequeue --
 
846
 *
 
847
 *      Called right after we dequeue / peek data from a socket.
 
848
 *
 
849
 * Results:
 
850
 *      0 on success. Negative error on failure.
 
851
 *
 
852
 * Side effects:
 
853
 *      None.
 
854
 *
 
855
 *----------------------------------------------------------------------------
 
856
 */
 
857
 
 
858
static int32
 
859
VSockVmciNotifyPktRecvPostDequeue(struct sock *sk,               // IN
 
860
                                  int target,                    // IN
 
861
                                  ssize_t copied,                // IN
 
862
                                  Bool dataRead,                 // IN
 
863
                                  VSockVmciRecvNotifyData *data) // IN
 
864
{
 
865
   VSockVmciSock *vsk;
 
866
   int err;
 
867
 
 
868
   ASSERT(sk);
 
869
   ASSERT(data);
 
870
 
 
871
   vsk = vsock_sk(sk);
 
872
   err = 0;
 
873
 
 
874
   if (dataRead) {
 
875
#if defined(VSOCK_OPTIMIZATION_WAITING_NOTIFY)
 
876
      /*
 
877
       * Detect a wrap-around to maintain queue generation.  Note that this is
 
878
       * safe since we hold the socket lock across the two queue pair
 
879
       * operations.
 
880
       */
 
881
      if (copied >= vsk->consumeSize - data->consumeHead) {
 
882
         PKT_FIELD(vsk, consumeQGeneration)++;
 
883
      }
 
884
#endif
 
885
 
 
886
      err = VSockVmciSendReadNotification(sk);
 
887
      if (err < 0) {
 
888
         return err;
 
889
      }
 
890
 
 
891
   }
 
892
   return err;
 
893
}
 
894
 
 
895
 
 
896
/*
 
897
 *----------------------------------------------------------------------------
 
898
 *
 
899
 * VSockVmciNotifyPktSendInit --
 
900
 *
 
901
 *      Called at the start of a stream send call with the socket lock held.
 
902
 *
 
903
 * Results:
 
904
 *      0 on success. A negative error code on failure.
 
905
 *
 
906
 * Side effects:
 
907
 *
 
908
 *----------------------------------------------------------------------------
 
909
 */
 
910
 
 
911
static int32
 
912
VSockVmciNotifyPktSendInit(struct sock *sk,               // IN
 
913
                           VSockVmciSendNotifyData *data) // IN
 
914
{
 
915
   ASSERT(sk);
 
916
   ASSERT(data);
 
917
 
 
918
#ifdef VSOCK_OPTIMIZATION_WAITING_NOTIFY
 
919
   data->consumeHead = 0;
 
920
   data->produceTail = 0;
 
921
#endif
 
922
 
 
923
   return 0;
 
924
}
 
925
 
 
926
 
 
927
/*
 
928
 *----------------------------------------------------------------------------
 
929
 *
 
930
 * VSockVmciNotifyPktSendPreBlock --
 
931
 *
 
932
 *      Called right before a socket is about to block with the socket lock
 
933
 *      held. The socket lock may have been released between the entry
 
934
 *      function and the preblock call.
 
935
 *
 
936
 *      Note: This function may be called multiple times before the post
 
937
 *      block function is called.
 
938
 *
 
939
 * Results.
 
940
 *      0 on success. A negative error code on failure.
 
941
 *
 
942
 * Side effects:
 
943
 *      None.
 
944
 *
 
945
 *----------------------------------------------------------------------------
 
946
 */
 
947
 
 
948
static int32
 
949
VSockVmciNotifyPktSendPreBlock(struct sock *sk,               // IN
 
950
                               VSockVmciSendNotifyData *data) // IN
 
951
{
 
952
   ASSERT(sk);
 
953
   ASSERT(data);
 
954
 
 
955
   /* Notify our peer that we are waiting for room to write. */
 
956
   if (!VSockVmciSendWaitingWrite(sk, 1)) {
 
957
      return -EHOSTUNREACH;
 
958
   }
 
959
 
 
960
   return 0;
 
961
}
 
962
 
 
963
 
 
964
/*
 
965
 *----------------------------------------------------------------------------
 
966
 *
 
967
 * VSockVmciNotifySendPreEnqueue --
 
968
 *
 
969
 *      Called right before we Enqueue to a socket.
 
970
 *
 
971
 * Results:
 
972
 *      0 on success. Negative error on failure.
 
973
 *
 
974
 * Side effects:
 
975
 *      None.
 
976
 *
 
977
 *----------------------------------------------------------------------------
 
978
 */
 
979
 
 
980
static int32
 
981
VSockVmciNotifyPktSendPreEnqueue(struct sock *sk,               // IN
 
982
                                 VSockVmciSendNotifyData *data) // IN
 
983
{
 
984
   VSockVmciSock *vsk;
 
985
 
 
986
   ASSERT(sk);
 
987
   ASSERT(data);
 
988
 
 
989
   vsk = vsock_sk(sk);
 
990
 
 
991
#if defined(VSOCK_OPTIMIZATION_WAITING_NOTIFY)
 
992
      VMCIQueue_GetPointers(vsk->produceQ, vsk->consumeQ,
 
993
                            &data->produceTail, &data->consumeHead);
 
994
#endif
 
995
 
 
996
   return 0;;
 
997
}
 
998
 
 
999
 
 
1000
/*
 
1001
 *----------------------------------------------------------------------------
 
1002
 *
 
1003
 * VSockVmciNotifySendPostEnqueue --
 
1004
 *
 
1005
 *      Called right after we enqueue data to a socket.
 
1006
 *
 
1007
 * Results:
 
1008
 *      0 on success. Negative error on failure.
 
1009
 *
 
1010
 * Side effects:
 
1011
 *      None.
 
1012
 *
 
1013
 *----------------------------------------------------------------------------
 
1014
 */
 
1015
 
 
1016
static int32
 
1017
VSockVmciNotifyPktSendPostEnqueue(struct sock *sk,               // IN
 
1018
                                  ssize_t written,               // IN
 
1019
                                  VSockVmciSendNotifyData *data) // IN
 
1020
{
 
1021
   int err = 0;
 
1022
   VSockVmciSock *vsk;
 
1023
   Bool sentWrote = FALSE;
 
1024
   int retries = 0;
 
1025
 
 
1026
   ASSERT(sk);
 
1027
   ASSERT(data);
 
1028
 
 
1029
   vsk = vsock_sk(sk);
 
1030
 
 
1031
#if defined(VSOCK_OPTIMIZATION_WAITING_NOTIFY)
 
1032
      /*
 
1033
       * Detect a wrap-around to maintain queue generation.  Note that this is
 
1034
       * safe since we hold the socket lock across the two queue pair
 
1035
       * operations.
 
1036
       */
 
1037
   if (written >= vsk->produceSize - data->produceTail) {
 
1038
      PKT_FIELD(vsk, produceQGeneration)++;
 
1039
   }
 
1040
#endif
 
1041
 
 
1042
   if (VSockVmciNotifyWaitingRead(vsk)) {
 
1043
      /*
 
1044
       * Notify the peer that we have written, retrying the send on failure up to
 
1045
       * our maximum value. See the XXX comment for the corresponding piece of
 
1046
       * code in StreamRecvmsg() for potential improvements.
 
1047
       */
 
1048
      while (!(vsk->peerShutdown & RCV_SHUTDOWN) &&
 
1049
             !sentWrote &&
 
1050
             retries < VSOCK_MAX_DGRAM_RESENDS) {
 
1051
         err = VSOCK_SEND_WROTE(sk);
 
1052
         if (err >= 0) {
 
1053
            sentWrote = TRUE;
 
1054
         }
 
1055
 
 
1056
         retries++;
 
1057
      }
 
1058
 
 
1059
      if (retries >= VSOCK_MAX_DGRAM_RESENDS) {
 
1060
         Warning("unable to send wrote notification to peer for socket %p.\n", sk);
 
1061
         return err;
 
1062
      } else {
 
1063
#if defined(VSOCK_OPTIMIZATION_WAITING_NOTIFY)
 
1064
         PKT_FIELD(vsk, peerWaitingRead) = FALSE;
 
1065
#endif
 
1066
      }
 
1067
   }
 
1068
   return err;
 
1069
}
 
1070
 
 
1071
 
 
1072
/*
 
1073
 *----------------------------------------------------------------------------
 
1074
 *
 
1075
 * VSockVmciNotifyPktHandlePkt
 
1076
 *
 
1077
 *      Called when a notify packet is recieved for a socket in the connected
 
1078
 *      state. Note this might be called from a bottom half.
 
1079
 *
 
1080
 * Results:
 
1081
 *      None.
 
1082
 *
 
1083
 * Side effects:
 
1084
 *      None.
 
1085
 *
 
1086
 *----------------------------------------------------------------------------
 
1087
 */
 
1088
 
 
1089
static void
 
1090
VSockVmciNotifyPktHandlePkt(struct sock *sk,         // IN
 
1091
                            VSockPacket *pkt,        // IN
 
1092
                            Bool bottomHalf,         // IN
 
1093
                            struct sockaddr_vm *dst, // IN
 
1094
                            struct sockaddr_vm *src, // IN
 
1095
                            Bool *pktProcessed)      // In
 
1096
{
 
1097
   Bool processed = FALSE;
 
1098
 
 
1099
   ASSERT(sk);
 
1100
   ASSERT(pkt);
 
1101
 
 
1102
   switch (pkt->type) {
 
1103
   case VSOCK_PACKET_TYPE_WROTE:
 
1104
      VSockVmciHandleWrote(sk, pkt, bottomHalf, dst, src);
 
1105
      processed = TRUE;
 
1106
      break;
 
1107
   case VSOCK_PACKET_TYPE_READ:
 
1108
      VSockVmciHandleRead(sk, pkt, bottomHalf, dst, src);
 
1109
      processed = TRUE;
 
1110
      break;
 
1111
   case VSOCK_PACKET_TYPE_WAITING_WRITE:
 
1112
      VSockVmciHandleWaitingWrite(sk, pkt, bottomHalf, dst, src);
 
1113
      processed = TRUE;
 
1114
      break;
 
1115
 
 
1116
   case VSOCK_PACKET_TYPE_WAITING_READ:
 
1117
      VSockVmciHandleWaitingRead(sk, pkt, bottomHalf, dst, src);
 
1118
      processed = TRUE;
 
1119
      break;
 
1120
   }
 
1121
 
 
1122
   if (pktProcessed) {
 
1123
      *pktProcessed = processed;
 
1124
   }
 
1125
}
 
1126
 
 
1127
/* Socket control packet based operations. */
 
1128
VSockVmciNotifyOps vSockVmciNotifyPktOps = {
 
1129
   VSockVmciNotifyPktSocketInit,
 
1130
   VSockVmciNotifyPktSocketDestruct,
 
1131
   VSockVmciNotifyPktPollIn,
 
1132
   VSockVmciNotifyPktPollOut,
 
1133
   VSockVmciNotifyPktHandlePkt,
 
1134
   VSockVmciNotifyPktRecvInit,
 
1135
   VSockVmciNotifyPktRecvPreBlock,
 
1136
   VSockVmciNotifyPktRecvPreDequeue,
 
1137
   VSockVmciNotifyPktRecvPostDequeue,
 
1138
   VSockVmciNotifyPktSendInit,
 
1139
   VSockVmciNotifyPktSendPreBlock,
 
1140
   VSockVmciNotifyPktSendPreEnqueue,
 
1141
   VSockVmciNotifyPktSendPostEnqueue
 
1142
};