~n-muench/ubuntu/maverick/open-vm-tools/open-vm-tools.fix-632101

« back to all changes in this revision

Viewing changes to modules/solaris/vmmemctl/os.c

  • Committer: Nate Muench
  • Date: 2010-09-07 02:10:30 UTC
  • Revision ID: nowiwilldestroyabydos@gmail.com-20100907021030-msa3598ldopvwkye
* Merge from Debian testing (LP: #632101), remaining changes:
  - Recommend open-vm-toolbox in open-vm-tools.
  - Rediffing vsock.patch.
* Updating local Makefile to inject symvers files to fix vmhgfs and
  vsock modules, thanks to Joe Gooch <mrwizard@k12system.com> (Closes:
  #579721).
* Updating standards version to 3.9.1.
* Removing vmmemctl fom initscript (Closes: #588356).
* Merging upstream version 2010.06.16-268169.
* Updating standards version to 3.9.0.
* Updating README.source.
* Rediffing kvers.patch.
* Dropping procps.patch, not required anymore.
* Updating packaging for upstreams vmmemctl module removal.

Show diffs side-by-side

added added

removed removed

Lines of Context:
33
33
#include <sys/kstat.h>
34
34
#include <sys/id_space.h>
35
35
#include <sys/vnode.h>
36
 
#include <sys/taskq.h>
 
36
#include <sys/proc.h>
37
37
#include <sys/disp.h>
38
38
#include <sys/ksynch.h>
39
39
 
40
40
#include "os.h"
41
41
#include "vmballoon.h"
42
 
#include "vm_assert.h"
43
42
#include "balloon_def.h"
44
43
#include "vmballoon_kstats.h"
45
 
#include "vmmemctl.h"
46
44
#include "buildNumber.h"
47
45
 
48
 
#if defined(SOL9)
49
 
extern unsigned disable_memscrub;
50
 
#else
51
46
extern void memscrub_disable(void);
52
 
#endif
53
47
 
54
48
/*
55
49
 * Constants
64
58
typedef struct {
65
59
   timeout_id_t id;
66
60
 
 
61
   /* Worker thread ID */
 
62
   kt_did_t thread_id;
 
63
 
67
64
   /* termination flag */
68
65
   volatile int stop;
69
66
 
72
69
   kcondvar_t cv;
73
70
 
74
71
   /* registered state */
75
 
   OSTimerHandler *handler;
76
72
   void *data;
77
73
   int period;
78
74
} os_timer;
88
84
} os_page;
89
85
 
90
86
typedef struct {
91
 
   const char   *name;
92
 
   const char   *name_verbose;
93
87
   os_timer     timer;
94
88
   kstat_t      *kstats;
95
89
   id_space_t   *id_space;
101
95
 */
102
96
 
103
97
static os_state global_state;
104
 
static dev_info_t *vmmemctl_dip;        /* only one instance */
105
98
 
106
99
 
107
100
/*
204
197
/*
205
198
 *-----------------------------------------------------------------------------
206
199
 *
207
 
 * OS_Snprintf --
208
 
 *
209
 
 *      Print a string into a bounded memory location.
210
 
 *
211
 
 * Results:
212
 
 *      Number of character printed including trailing \0.
213
 
 *
214
 
 * Side effects:
215
 
 *      None
216
 
 *
217
 
 *-----------------------------------------------------------------------------
218
 
 */
219
 
 
220
 
int
221
 
OS_Snprintf(char *buf,          // OUT
222
 
            size_t size,        // IN
223
 
            const char *format, // IN
224
 
            ...)                // IN
225
 
{
226
 
   ASSERT(0);
227
 
   /*
228
 
    * XXX disabled because the varargs header file doesn't seem to
229
 
    * work in the current (gcc 2.95.3) cross-compiler environment.
230
 
    * Not used for Solaris anyway.
231
 
    */
232
 
   return 0;
233
 
}
234
 
 
235
 
 
236
 
/*
237
 
 *-----------------------------------------------------------------------------
238
 
 *
239
 
 * OS_Identity --
240
 
 *
241
 
 *      Returns an identifier for the guest OS family.
242
 
 *
243
 
 * Results:
244
 
 *      The identifier
245
 
 *
246
 
 * Side effects:
247
 
 *      None
248
 
 *
249
 
 *-----------------------------------------------------------------------------
250
 
 */
251
 
 
252
 
BalloonGuest
253
 
OS_Identity(void)
254
 
{
255
 
   return BALLOON_GUEST_SOLARIS;
256
 
}
257
 
 
258
 
 
259
 
/*
260
 
 *-----------------------------------------------------------------------------
261
 
 *
262
200
 * OS_ReservedPageGetLimit --
263
201
 *
264
202
 *      Predict the maximum achievable balloon size.
440
378
/*
441
379
 *-----------------------------------------------------------------------------
442
380
 *
443
 
 * os_worker --
 
381
 * vmememctl_poll_worker --
444
382
 *
445
383
 *      Worker thread that periodically calls the timer handler.  This is
446
384
 *      executed by a user context thread so that it can block waiting for
456
394
 *-----------------------------------------------------------------------------
457
395
 */
458
396
 
459
 
static int
460
 
os_worker(void)
 
397
static void
 
398
vmmemctl_poll_worker(os_timer *t) // IN
461
399
{
462
 
   os_timer *t = &global_state.timer;
463
400
   clock_t timeout;
464
401
 
465
402
   mutex_enter(&t->lock);
 
403
 
466
404
   while (!t->stop) {
467
 
      /* invoke registered handler */
468
405
      mutex_exit(&t->lock);
469
 
      (void) (*(t->handler))(t->data);
 
406
 
 
407
      Balloon_QueryAndExecute();
 
408
 
470
409
      mutex_enter(&t->lock);
471
 
 
472
410
      /* check again whether we should stop */
473
411
      if (t->stop)
474
 
         break;
 
412
         break;
475
413
 
476
414
      /* wait for timeout */
477
415
      (void) drv_getparm(LBOLT, &timeout);
478
416
      timeout += t->period;
479
 
      if (cv_timedwait_sig(&t->cv, &t->lock, timeout) == 0) {
480
 
         mutex_exit(&t->lock);
481
 
         return EINTR;          /* took a signal, return to user level */
482
 
      }
 
417
      cv_timedwait_sig(&t->cv, &t->lock, timeout);
483
418
   }
 
419
 
484
420
   mutex_exit(&t->lock);
485
 
   ASSERT(t->stop);
486
 
   return 0;                    /* normal termination */
 
421
 
 
422
   thread_exit();
487
423
}
488
424
 
489
425
 
503
439
 *-----------------------------------------------------------------------------
504
440
 */
505
441
 
506
 
Bool
507
 
OS_TimerStart(OSTimerHandler *handler, // IN
508
 
              void *clientData)        // IN
 
442
static int
 
443
vmmemctl_poll_start(void)
509
444
{
510
445
   os_timer *t = &global_state.timer;
 
446
   kthread_t *tp;
511
447
 
512
448
   /* setup the timer structure */
513
449
   t->id = 0;
514
 
   t->handler = handler;
515
 
   t->data = clientData;
516
 
   t->period = drv_usectohz(ONE_SECOND_IN_MICROSECONDS);
 
450
   t->stop = 0;
 
451
   t->period = drv_usectohz(BALLOON_POLL_PERIOD * ONE_SECOND_IN_MICROSECONDS);
517
452
 
518
453
   mutex_init(&t->lock, NULL, MUTEX_DRIVER, NULL);
519
454
   cv_init(&t->cv, NULL, CV_DRIVER, NULL);
520
455
 
521
 
   /* start the timer */
522
 
   t->stop = 0;
 
456
   /*
 
457
    * All Solaris drivers that I checked assume that thread_create() will
 
458
    * succeed, let's follow the suit.
 
459
    */
 
460
   tp = thread_create(NULL, 0, vmmemctl_poll_worker, (void *)t,
 
461
                      0, &p0, TS_RUN, minclsyspri);
 
462
   t->thread_id = tp->t_did;
523
463
 
524
 
   return TRUE;
 
464
   return 0;
525
465
}
526
466
 
527
467
 
528
468
/*
529
469
 *-----------------------------------------------------------------------------
530
470
 *
531
 
 * OS_TimerStop --
 
471
 * vmmemctl_poll_stop --
532
472
 *
533
 
 *      Stop the timer.
 
473
 *      Signal polling thread to stop and wait till it exists.
534
474
 *
535
475
 * Results:
536
476
 *      None
541
481
 *-----------------------------------------------------------------------------
542
482
 */
543
483
 
544
 
void
545
 
OS_TimerStop(void)
 
484
static void
 
485
vmmemctl_poll_stop(void)
546
486
{
547
487
   os_timer *t = &global_state.timer;
548
488
 
549
489
   mutex_enter(&t->lock);
550
490
 
551
 
   /* set termination flag */
 
491
   /* Set termination flag. */
552
492
   t->stop = 1;
553
493
 
554
 
   /* wake up worker thread so it can exit */
 
494
   /* Wake up worker thread so it can exit. */
555
495
   cv_signal(&t->cv);
556
496
 
557
497
   mutex_exit(&t->lock);
558
 
}
559
 
 
560
 
 
561
 
static void
562
 
os_timer_cleanup(void)
563
 
{
564
 
   os_timer *timer = &global_state.timer;
565
 
 
566
 
   mutex_destroy(&timer->lock);
567
 
   cv_destroy(&timer->cv);
 
498
 
 
499
   /* Wait for the worker thread to complete. */
 
500
   if (t->thread_id != 0) {
 
501
      thread_join(t->thread_id);
 
502
      t->thread_id = 0;
 
503
   }
 
504
 
 
505
   mutex_destroy(&t->lock);
 
506
   cv_destroy(&t->cv);
568
507
}
569
508
 
570
509
 
592
531
 
593
532
 
594
533
/*
595
 
 *-----------------------------------------------------------------------------
596
 
 *
597
 
 * OS_Init --
598
 
 *
599
 
 *      Called at driver startup, initializes the balloon state and structures.
600
 
 *
601
 
 * Results:
602
 
 *      On success: TRUE
603
 
 *      On failure: FALSE
604
 
 *
605
 
 * Side effects:
606
 
 *      None
607
 
 *
608
 
 *-----------------------------------------------------------------------------
609
 
 */
610
 
 
611
 
Bool
612
 
OS_Init(const char *name,         // IN
613
 
        const char *nameVerbose,  // IN
614
 
        OSStatusHandler *handler) // IN
615
 
{
616
 
   os_state *state = &global_state;
617
 
   static int initialized = 0;
618
 
 
619
 
   /* initialize only once */
620
 
   if (initialized++) {
621
 
      return FALSE;
622
 
   }
623
 
 
624
 
   /* zero global state */
625
 
   bzero(state, sizeof(global_state));
626
 
 
627
 
   state->kstats = BalloonKstatCreate();
628
 
   state->id_space = id_space_create("vmmemctl", 0, INT_MAX);
629
 
   state->name = name;
630
 
   state->name_verbose = nameVerbose;
631
 
 
632
 
   /* disable memscrubber */
633
 
#if defined(SOL9)
634
 
   disable_memscrub = 1;
635
 
#else
636
 
   memscrub_disable();
637
 
#endif
638
 
 
639
 
   /* log device load */
640
 
   cmn_err(CE_CONT, "!%s initialized\n", nameVerbose);
641
 
   return TRUE;
642
 
}
643
 
 
644
 
 
645
 
/*
646
 
 *-----------------------------------------------------------------------------
647
 
 *
648
 
 * OS_Cleanup --
649
 
 *
650
 
 *      Called when the driver is terminating, cleanup initialized structures.
651
 
 *
652
 
 * Results:
653
 
 *      None
654
 
 *
655
 
 * Side effects:
656
 
 *      None
657
 
 *
658
 
 *-----------------------------------------------------------------------------
659
 
 */
660
 
 
661
 
void
662
 
OS_Cleanup(void)
663
 
{
664
 
   os_state *state = &global_state;
665
 
 
666
 
   os_timer_cleanup();
667
 
   BalloonKstatDelete(state->kstats);
668
 
   id_space_destroy(state->id_space);
669
 
 
670
 
   /* log device unload */
671
 
   cmn_err(CE_CONT, "!%s unloaded\n", state->name_verbose);
672
 
}
673
 
 
674
 
 
675
 
/*
676
 
 * Device configuration entry points
677
 
 */
678
 
 
679
 
 
680
 
static int
681
 
vmmemctl_attach(dev_info_t *dip,      // IN
682
 
                ddi_attach_cmd_t cmd) // IN
683
 
{
684
 
   switch (cmd) {
685
 
   case DDI_ATTACH:
686
 
      vmmemctl_dip = dip;
687
 
      if (ddi_create_minor_node(dip, "0", S_IFCHR, ddi_get_instance(dip),
688
 
                                DDI_PSEUDO,0) != DDI_SUCCESS) {
689
 
         return DDI_FAILURE;
690
 
      } else {
691
 
         return DDI_SUCCESS;
692
 
      }
693
 
   default:
694
 
      return DDI_FAILURE;
695
 
   }
696
 
}
697
 
 
698
 
 
699
 
static int
700
 
vmmemctl_detach(dev_info_t *dip,      // IN
701
 
                ddi_detach_cmd_t cmd) // IN
702
 
{
703
 
   switch (cmd) {
704
 
   case DDI_DETACH:
705
 
      vmmemctl_dip = 0;
706
 
      ddi_remove_minor_node(dip, NULL);
707
 
      return DDI_SUCCESS;
708
 
   default:
709
 
      return DDI_FAILURE;
710
 
   }
711
 
}
712
 
 
713
 
 
714
 
/*
715
 
 *-----------------------------------------------------------------------------
716
 
 *
717
 
 * vmmemctl_ioctl --
718
 
 *
719
 
 *      Commands used by the user level daemon to control the driver.
720
 
 *      Since the daemon is single threaded, we use a simple monitor to
721
 
 *      make sure that only one thread is executing here at a time.
722
 
 *
723
 
 * Results:
724
 
 *      On success: 0
725
 
 *      On failure: error code
726
 
 *
727
 
 * Side effects:
728
 
 *      None
729
 
 *
730
 
 *-----------------------------------------------------------------------------
731
 
 */
732
 
 
733
 
static int
734
 
vmmemctl_ioctl(dev_t dev,    // IN: Unused
735
 
               int cmd,      // IN
736
 
               intptr_t arg, // IN: Unused
737
 
               int mode,     // IN: Unused
738
 
               cred_t *cred, // IN
739
 
               int *rvalp)   // IN: Unused
740
 
{
741
 
   int error = 0;
742
 
   static int busy = 0;         /* set when a thread is in this function */
743
 
   static kmutex_t lock;        /* lock to protect busy count */
744
 
 
745
 
   if (drv_priv(cred) != 0)
746
 
      return EPERM;
747
 
 
748
 
   mutex_enter(&lock);
749
 
   if (busy) {
750
 
      /*
751
 
       * Only one thread at a time.
752
 
       */
753
 
      mutex_exit(&lock);
754
 
      return EBUSY;
755
 
   }
756
 
   busy = 1;
757
 
   mutex_exit(&lock);
758
 
 
759
 
   switch (cmd) {
760
 
   case VMMIOCWORK:
761
 
      error = os_worker();
762
 
      break;
763
 
 
764
 
   default:
765
 
      error = ENXIO;
766
 
      break;
767
 
   }
768
 
 
769
 
   mutex_enter(&lock);
770
 
   ASSERT(busy);
771
 
   busy = 0;
772
 
   mutex_exit(&lock);
773
 
 
774
 
   return error;
775
 
}
776
 
 
777
 
/*
778
534
 * Module linkage
779
535
 */
780
536
 
781
 
static struct cb_ops vmmemctl_cb_ops = {
782
 
   nulldev,             /* open */
783
 
   nulldev,             /* close */
784
 
   nodev,               /* strategy */
785
 
   nodev,               /* print */
786
 
   nodev,               /* dump */
787
 
   nodev,               /* read */
788
 
   nodev,               /* write */
789
 
   vmmemctl_ioctl,
790
 
   nodev,               /* devmap */
791
 
   nodev,               /* mmap */
792
 
   nodev,               /* segmap */
793
 
   nochpoll,            /* poll */
794
 
   ddi_prop_op,         /* prop_op */
795
 
   0,                   /* streamtab */
796
 
   D_NEW | D_MP
797
 
};
798
 
 
799
 
static struct dev_ops vmmemctl_dev_ops = {
800
 
   DEVO_REV,
801
 
   0,
802
 
   ddi_no_info,         /* getinfo */
803
 
   nulldev,             /* identify */
804
 
   nulldev,             /* probe */
805
 
   vmmemctl_attach,
806
 
   vmmemctl_detach,
807
 
   nodev,               /* reset */
808
 
   &vmmemctl_cb_ops,    /* cb_ops */
809
 
   NULL,                /* bus_ops */
810
 
   nodev                /* power */
811
 
};
812
 
 
813
537
static struct modldrv vmmodldrv = {
814
 
   &mod_driverops,
 
538
   &mod_miscops,
815
539
   "VMware Memory Control b" BUILD_NUMBER_NUMERIC_STRING,
816
 
   &vmmemctl_dev_ops
817
540
};
818
541
 
819
542
static struct modlinkage vmmodlinkage = {
820
543
   MODREV_1,
821
 
   {&vmmodldrv, NULL}
 
544
   { &vmmodldrv, NULL }
822
545
};
823
546
 
824
547
 
825
548
int
826
549
_init(void)
827
550
{
 
551
   os_state *state = &global_state;
828
552
   int error;
829
553
 
830
 
   if (Balloon_ModuleInit() != BALLOON_SUCCESS) {
831
 
      return EAGAIN;
832
 
   }
 
554
   if (!Balloon_Init(BALLOON_GUEST_SOLARIS)) {
 
555
      return EIO;
 
556
   }
 
557
 
 
558
   state->kstats = BalloonKstatCreate();
 
559
   state->id_space = id_space_create(BALLOON_NAME, 0, INT_MAX);
 
560
 
 
561
   /* disable memscrubber */
 
562
   memscrub_disable();
 
563
 
 
564
   error = vmmemctl_poll_start();
 
565
   if (error) {
 
566
      goto err_do_cleanup;
 
567
   }
 
568
 
 
569
 
833
570
   error = mod_install(&vmmodlinkage);
834
 
   if (error != 0) {
835
 
      Balloon_ModuleCleanup();
 
571
   if (error) {
 
572
      goto err_stop_poll;
836
573
   }
 
574
 
 
575
   cmn_err(CE_CONT, "!%s initialized\n", BALLOON_NAME_VERBOSE);
 
576
   return 0;
 
577
 
 
578
err_stop_poll:
 
579
   vmmemctl_poll_stop();
 
580
 
 
581
err_do_cleanup:
 
582
   id_space_destroy(state->id_space);
 
583
   BalloonKstatDelete(state->kstats);
 
584
   Balloon_Cleanup();
 
585
 
837
586
   return error;
838
587
}
839
588
 
848
597
int
849
598
_fini(void)
850
599
{
 
600
   os_state *state = &global_state;
851
601
   int error;
852
602
 
853
603
   /*
854
 
    * Check if the module is busy (i.e., there's a worker thread active)
855
 
    * before cleaning up.
 
604
    * Check if the module is busy before cleaning up.
856
605
    */
857
606
   error = mod_remove(&vmmodlinkage);
858
 
   if (error == 0) {
859
 
      Balloon_ModuleCleanup();
 
607
   if (error) {
 
608
      return error;
860
609
   }
861
 
   return error;
 
610
 
 
611
   vmmemctl_poll_stop();
 
612
   BalloonKstatDelete(state->kstats);
 
613
   id_space_destroy(state->id_space);
 
614
   Balloon_Cleanup();
 
615
 
 
616
   cmn_err(CE_CONT, "!%s unloaded\n", BALLOON_NAME_VERBOSE);
 
617
 
 
618
   return 0;
862
619
}
863
620
 
864
621