Print this page
    
7127  remove -Wno-missing-braces from Makefile.uts
    
      
        | Split | 
	Close | 
      
      | Expand all | 
      | Collapse all | 
    
    
          --- old/usr/src/uts/common/syscall/pset.c
          +++ new/usr/src/uts/common/syscall/pset.c
   1    1  /*
   2    2   * CDDL HEADER START
   3    3   *
   4    4   * The contents of this file are subject to the terms of the
   5    5   * Common Development and Distribution License (the "License").
   6    6   * You may not use this file except in compliance with the License.
   7    7   *
   8    8   * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9    9   * or http://www.opensolaris.org/os/licensing.
  10   10   * See the License for the specific language governing permissions
  11   11   * and limitations under the License.
  12   12   *
  13   13   * When distributing Covered Code, include this CDDL HEADER in each
  14   14   * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15   15   * If applicable, add the following below this CDDL HEADER, with the
  16   16   * fields enclosed by brackets "[]" replaced with your own identifying
  17   17   * information: Portions Copyright [yyyy] [name of copyright owner]
  18   18   *
  19   19   * CDDL HEADER END
  20   20   */
  21   21  /*
  22   22   * Copyright (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved.
  23   23   */
  24   24  
  25   25  #include <sys/types.h>
  26   26  #include <sys/systm.h>
  27   27  #include <sys/cmn_err.h>
  28   28  #include <sys/cpuvar.h>
  29   29  #include <sys/thread.h>
  30   30  #include <sys/disp.h>
  31   31  #include <sys/kmem.h>
  32   32  #include <sys/debug.h>
  33   33  #include <sys/sysmacros.h>
  34   34  #include <sys/cpupart.h>
  35   35  #include <sys/pset.h>
  36   36  #include <sys/modctl.h>
  37   37  #include <sys/syscall.h>
  38   38  #include <sys/task.h>
  39   39  #include <sys/loadavg.h>
  40   40  #include <sys/fss.h>
  41   41  #include <sys/pool.h>
  42   42  #include <sys/pool_pset.h>
  43   43  #include <sys/policy.h>
  44   44  #include <sys/zone.h>
  45   45  #include <sys/contract/process_impl.h>
  46   46  
  47   47  static int      pset(int, long, long, long, long);
  48   48  
  49   49  static struct sysent pset_sysent = {
  50   50          5,
  51   51          SE_ARGC | SE_NOUNLOAD,
  52   52          (int (*)())pset,
  53   53  };
  54   54  
  55   55  static struct modlsys modlsys = {
  56   56          &mod_syscallops, "processor sets", &pset_sysent
  
    | 
      ↓ open down ↓ | 
    56 lines elided | 
    
      ↑ open up ↑ | 
  
  57   57  };
  58   58  
  59   59  #ifdef _SYSCALL32_IMPL
  60   60  static struct modlsys modlsys32 = {
  61   61          &mod_syscallops32, "32-bit pset(2) syscall", &pset_sysent
  62   62  };
  63   63  #endif
  64   64  
  65   65  static struct modlinkage modlinkage = {
  66   66          MODREV_1,
  67      -        &modlsys,
       67 +        {   &modlsys,
  68   68  #ifdef _SYSCALL32_IMPL
  69      -        &modlsys32,
       69 +            &modlsys32,
  70   70  #endif
  71      -        NULL
       71 +            NULL
       72 +        }
  72   73  };
  73   74  
  74   75  #define PSET_BADATTR(attr)      ((~PSET_NOESCAPE) & (attr))
  75   76  
  76   77  int
  77   78  _init(void)
  78   79  {
  79   80          return (mod_install(&modlinkage));
  80   81  }
  81   82  
  82   83  int
  83   84  _info(struct modinfo *modinfop)
  84   85  {
  85   86          return (mod_info(&modlinkage, modinfop));
  86   87  }
  87   88  
  88   89  static int
  89   90  pset_create(psetid_t *psetp)
  90   91  {
  91   92          psetid_t newpset;
  92   93          int error;
  93   94  
  94   95          if (secpolicy_pset(CRED()) != 0)
  95   96                  return (set_errno(EPERM));
  96   97  
  97   98          pool_lock();
  98   99          if (pool_state == POOL_ENABLED) {
  99  100                  pool_unlock();
 100  101                  return (set_errno(ENOTSUP));
 101  102          }
 102  103          error = cpupart_create(&newpset);
 103  104          if (error) {
 104  105                  pool_unlock();
 105  106                  return (set_errno(error));
 106  107          }
 107  108          if (copyout(&newpset, psetp, sizeof (psetid_t)) != 0) {
 108  109                  (void) cpupart_destroy(newpset);
 109  110                  pool_unlock();
 110  111                  return (set_errno(EFAULT));
 111  112          }
 112  113          pool_unlock();
 113  114          return (error);
 114  115  }
 115  116  
 116  117  static int
 117  118  pset_destroy(psetid_t pset)
 118  119  {
 119  120          int error;
 120  121  
 121  122          if (secpolicy_pset(CRED()) != 0)
 122  123                  return (set_errno(EPERM));
 123  124  
 124  125          pool_lock();
 125  126          if (pool_state == POOL_ENABLED) {
 126  127                  pool_unlock();
 127  128                  return (set_errno(ENOTSUP));
 128  129          }
 129  130          error = cpupart_destroy(pset);
 130  131          pool_unlock();
 131  132          if (error)
 132  133                  return (set_errno(error));
 133  134          else
 134  135                  return (0);
 135  136  }
 136  137  
 137  138  static int
 138  139  pset_assign(psetid_t pset, processorid_t cpuid, psetid_t *opset, int forced)
 139  140  {
 140  141          psetid_t oldpset;
 141  142          int     error = 0;
 142  143          cpu_t   *cp;
 143  144  
 144  145          if (pset != PS_QUERY && secpolicy_pset(CRED()) != 0)
 145  146                  return (set_errno(EPERM));
 146  147  
 147  148          pool_lock();
 148  149          if (pset != PS_QUERY && pool_state == POOL_ENABLED) {
 149  150                  pool_unlock();
 150  151                  return (set_errno(ENOTSUP));
 151  152          }
 152  153  
 153  154          mutex_enter(&cpu_lock);
 154  155          if ((cp = cpu_get(cpuid)) == NULL) {
 155  156                  mutex_exit(&cpu_lock);
 156  157                  pool_unlock();
 157  158                  return (set_errno(EINVAL));
 158  159          }
 159  160  
 160  161          oldpset = cpupart_query_cpu(cp);
 161  162  
 162  163          if (pset != PS_QUERY)
 163  164                  error = cpupart_attach_cpu(pset, cp, forced);
 164  165          mutex_exit(&cpu_lock);
 165  166          pool_unlock();
 166  167  
 167  168          if (error)
 168  169                  return (set_errno(error));
 169  170  
 170  171          if (opset != NULL)
 171  172                  if (copyout(&oldpset, opset, sizeof (psetid_t)) != 0)
 172  173                          return (set_errno(EFAULT));
 173  174  
 174  175          return (0);
 175  176  }
 176  177  
 177  178  static int
 178  179  pset_info(psetid_t pset, int *typep, uint_t *numcpusp,
 179  180      processorid_t *cpulistp)
 180  181  {
 181  182          int pset_type;
 182  183          uint_t user_ncpus = 0, real_ncpus, copy_ncpus;
 183  184          processorid_t *pset_cpus = NULL;
 184  185          int error = 0;
 185  186  
 186  187          if (numcpusp != NULL) {
 187  188                  if (copyin(numcpusp, &user_ncpus, sizeof (uint_t)) != 0)
 188  189                          return (set_errno(EFAULT));
 189  190          }
 190  191  
 191  192          if (user_ncpus > max_ncpus)     /* sanity check */
 192  193                  user_ncpus = max_ncpus;
 193  194          if (user_ncpus != 0 && cpulistp != NULL)
 194  195                  pset_cpus = kmem_alloc(sizeof (processorid_t) * user_ncpus,
 195  196                      KM_SLEEP);
 196  197  
 197  198          real_ncpus = user_ncpus;
 198  199          if ((error = cpupart_get_cpus(&pset, pset_cpus, &real_ncpus)) != 0)
 199  200                  goto out;
 200  201  
 201  202          /*
 202  203           * Now copyout the information about this processor set.
 203  204           */
 204  205  
 205  206          /*
 206  207           * Get number of cpus to copy back.  If the user didn't pass in
 207  208           * a big enough buffer, only copy back as many cpus as fits in
 208  209           * the buffer but copy back the real number of cpus.
 209  210           */
 210  211  
 211  212          if (user_ncpus != 0 && cpulistp != NULL) {
 212  213                  copy_ncpus = MIN(real_ncpus, user_ncpus);
 213  214                  if (copyout(pset_cpus, cpulistp,
 214  215                      sizeof (processorid_t) * copy_ncpus) != 0) {
 215  216                          error = EFAULT;
 216  217                          goto out;
 217  218                  }
 218  219          }
 219  220          if (pset_cpus != NULL)
 220  221                  kmem_free(pset_cpus, sizeof (processorid_t) * user_ncpus);
 221  222          if (typep != NULL) {
 222  223                  if (pset == PS_NONE)
 223  224                          pset_type = PS_NONE;
 224  225                  else
 225  226                          pset_type = PS_PRIVATE;
 226  227                  if (copyout(&pset_type, typep, sizeof (int)) != 0)
 227  228                          return (set_errno(EFAULT));
 228  229          }
 229  230          if (numcpusp != NULL)
 230  231                  if (copyout(&real_ncpus, numcpusp, sizeof (uint_t)) != 0)
 231  232                          return (set_errno(EFAULT));
 232  233          return (0);
 233  234  
 234  235  out:
 235  236          if (pset_cpus != NULL)
 236  237                  kmem_free(pset_cpus, sizeof (processorid_t) * user_ncpus);
 237  238          return (set_errno(error));
 238  239  }
 239  240  
 240  241  static int
 241  242  pset_bind_thread(kthread_t *tp, psetid_t pset, psetid_t *oldpset, void *projbuf,
 242  243      void *zonebuf)
 243  244  {
 244  245          int error = 0;
 245  246  
 246  247          ASSERT(pool_lock_held());
 247  248          ASSERT(MUTEX_HELD(&cpu_lock));
 248  249          ASSERT(MUTEX_HELD(&ttoproc(tp)->p_lock));
 249  250  
 250  251          *oldpset = tp->t_bind_pset;
 251  252  
 252  253          switch (pset) {
 253  254          case PS_SOFT:
 254  255                  TB_PSET_SOFT_SET(tp);
 255  256                  break;
 256  257  
 257  258          case PS_HARD:
 258  259                  TB_PSET_HARD_SET(tp);
 259  260                  break;
 260  261  
 261  262          case PS_QUERY:
 262  263                  break;
 263  264  
 264  265          case PS_QUERY_TYPE:
 265  266                  *oldpset = TB_PSET_IS_SOFT(tp) ? PS_SOFT : PS_HARD;
 266  267                  break;
 267  268  
 268  269          default:
 269  270                  /*
 270  271                   * Must have the same UID as the target process or
 271  272                   * have PRIV_PROC_OWNER privilege.
 272  273                   */
 273  274                  if (!hasprocperm(tp->t_cred, CRED()))
 274  275                          return (EPERM);
 275  276                  /*
 276  277                   * Unbinding of an unbound thread should always succeed.
 277  278                   */
 278  279                  if (*oldpset == PS_NONE && pset == PS_NONE)
 279  280                          return (0);
 280  281                  /*
 281  282                   * Only privileged processes can move threads from psets with
 282  283                   * PSET_NOESCAPE attribute.
 283  284                   */
 284  285                  if ((tp->t_cpupart->cp_attr & PSET_NOESCAPE) &&
 285  286                      secpolicy_pbind(CRED()) != 0)
 286  287                          return (EPERM);
 287  288                  if ((error = cpupart_bind_thread(tp, pset, 0,
 288  289                      projbuf, zonebuf)) == 0)
 289  290                          tp->t_bind_pset = pset;
 290  291  
 291  292                  break;
 292  293          }
 293  294  
 294  295          return (error);
 295  296  }
 296  297  
 297  298  static int
 298  299  pset_bind_process(proc_t *pp, psetid_t pset, psetid_t *oldpset, void *projbuf,
 299  300      void *zonebuf)
 300  301  {
 301  302          int error = 0;
 302  303          kthread_t *tp;
 303  304  
 304  305          /* skip kernel processes */
 305  306          if ((pset != PS_QUERY) && pp->p_flag & SSYS) {
 306  307                  *oldpset = PS_NONE;
 307  308                  return (ENOTSUP);
 308  309          }
 309  310  
 310  311          mutex_enter(&pp->p_lock);
 311  312          tp = pp->p_tlist;
 312  313          if (tp != NULL) {
 313  314                  do {
 314  315                          int rval;
 315  316  
 316  317                          rval = pset_bind_thread(tp, pset, oldpset, projbuf,
 317  318                              zonebuf);
 318  319                          if (error == 0)
 319  320                                  error = rval;
 320  321                  } while ((tp = tp->t_forw) != pp->p_tlist);
 321  322          } else
 322  323                  error = ESRCH;
 323  324          mutex_exit(&pp->p_lock);
 324  325  
 325  326          return (error);
 326  327  }
 327  328  
 328  329  static int
 329  330  pset_bind_task(task_t *tk, psetid_t pset, psetid_t *oldpset, void *projbuf,
 330  331      void *zonebuf)
 331  332  {
 332  333          int error = 0;
 333  334          proc_t *pp;
 334  335  
 335  336          ASSERT(MUTEX_HELD(&pidlock));
 336  337  
 337  338          if ((pp = tk->tk_memb_list) == NULL) {
 338  339                  return (ESRCH);
 339  340          }
 340  341  
 341  342          do {
 342  343                  int rval;
 343  344  
 344  345                  if (!(pp->p_flag & SSYS)) {
 345  346                          rval = pset_bind_process(pp, pset, oldpset, projbuf,
 346  347                              zonebuf);
 347  348                          if (error == 0)
 348  349                                  error = rval;
 349  350                  }
 350  351          } while ((pp = pp->p_tasknext) != tk->tk_memb_list);
 351  352  
 352  353          return (error);
 353  354  }
 354  355  
 355  356  static int
 356  357  pset_bind_project(kproject_t *kpj, psetid_t pset, psetid_t *oldpset,
 357  358      void *projbuf, void *zonebuf)
 358  359  {
 359  360          int error = 0;
 360  361          proc_t *pp;
 361  362  
 362  363          ASSERT(MUTEX_HELD(&pidlock));
 363  364  
 364  365          for (pp = practive; pp != NULL; pp = pp->p_next) {
 365  366                  if (pp->p_tlist == NULL)
 366  367                          continue;
 367  368                  if (pp->p_task->tk_proj == kpj && !(pp->p_flag & SSYS)) {
 368  369                          int rval;
 369  370  
 370  371                          rval = pset_bind_process(pp, pset, oldpset, projbuf,
 371  372                              zonebuf);
 372  373                          if (error == 0)
 373  374                                  error = rval;
 374  375                  }
 375  376          }
 376  377  
 377  378          return (error);
 378  379  }
 379  380  
 380  381  static int
 381  382  pset_bind_zone(zone_t *zptr, psetid_t pset, psetid_t *oldpset, void *projbuf,
 382  383      void *zonebuf)
 383  384  {
 384  385          int error = 0;
 385  386          proc_t *pp;
 386  387  
 387  388          ASSERT(MUTEX_HELD(&pidlock));
 388  389  
 389  390          for (pp = practive; pp != NULL; pp = pp->p_next) {
 390  391                  if (pp->p_zone == zptr && !(pp->p_flag & SSYS)) {
 391  392                          int rval;
 392  393  
 393  394                          rval = pset_bind_process(pp, pset, oldpset, projbuf,
 394  395                              zonebuf);
 395  396                          if (error == 0)
 396  397                                  error = rval;
 397  398                  }
 398  399          }
 399  400  
 400  401          return (error);
 401  402  }
 402  403  
 403  404  /*
 404  405   * Unbind all threads from the specified processor set, or from all
 405  406   * processor sets.
 406  407   */
 407  408  static int
 408  409  pset_unbind(psetid_t pset, void *projbuf, void *zonebuf, idtype_t idtype)
 409  410  {
 410  411          psetid_t olbind;
 411  412          kthread_t *tp;
 412  413          int error = 0;
 413  414          int rval;
 414  415          proc_t *pp;
 415  416  
 416  417          ASSERT(MUTEX_HELD(&cpu_lock));
 417  418  
 418  419          if (idtype == P_PSETID && cpupart_find(pset) == NULL)
 419  420                  return (EINVAL);
 420  421  
 421  422          mutex_enter(&pidlock);
 422  423          for (pp = practive; pp != NULL; pp = pp->p_next) {
 423  424                  mutex_enter(&pp->p_lock);
 424  425                  tp = pp->p_tlist;
 425  426                  /*
 426  427                   * Skip zombies and kernel processes, and processes in
 427  428                   * other zones, if called from a non-global zone.
 428  429                   */
 429  430                  if (tp == NULL || (pp->p_flag & SSYS) ||
 430  431                      !HASZONEACCESS(curproc, pp->p_zone->zone_id)) {
 431  432                          mutex_exit(&pp->p_lock);
 432  433                          continue;
 433  434                  }
 434  435                  do {
 435  436                          if ((idtype == P_PSETID && tp->t_bind_pset != pset) ||
 436  437                              (idtype == P_ALL && tp->t_bind_pset == PS_NONE))
 437  438                                  continue;
 438  439                          rval = pset_bind_thread(tp, PS_NONE, &olbind,
 439  440                              projbuf, zonebuf);
 440  441                          if (error == 0)
 441  442                                  error = rval;
 442  443                  } while ((tp = tp->t_forw) != pp->p_tlist);
 443  444                  mutex_exit(&pp->p_lock);
 444  445          }
 445  446          mutex_exit(&pidlock);
 446  447          return (error);
 447  448  }
 448  449  
 449  450  static int
 450  451  pset_bind_contract(cont_process_t *ctp, psetid_t pset, psetid_t *oldpset,
 451  452      void *projbuf, void *zonebuf)
 452  453  {
 453  454          int error = 0;
 454  455          proc_t *pp;
 455  456  
 456  457          ASSERT(MUTEX_HELD(&pidlock));
 457  458  
 458  459          for (pp = practive; pp != NULL; pp = pp->p_next) {
 459  460                  if (pp->p_ct_process == ctp) {
 460  461                          int rval;
 461  462  
 462  463                          rval = pset_bind_process(pp, pset, oldpset, projbuf,
 463  464                              zonebuf);
 464  465                          if (error == 0)
 465  466                                  error = rval;
 466  467                  }
 467  468          }
 468  469  
 469  470          return (error);
 470  471  }
 471  472  
 472  473  /*
 473  474   * Bind the lwp:id of process:pid to processor set: pset
 474  475   */
 475  476  static int
 476  477  pset_bind_lwp(psetid_t pset, id_t id, pid_t pid, psetid_t *opset)
 477  478  {
 478  479          kthread_t       *tp;
 479  480          proc_t          *pp;
 480  481          psetid_t        oldpset;
 481  482          void            *projbuf, *zonebuf;
 482  483          int             error = 0;
 483  484  
 484  485          pool_lock();
 485  486          mutex_enter(&cpu_lock);
 486  487          projbuf = fss_allocbuf(FSS_NPROJ_BUF, FSS_ALLOC_PROJ);
 487  488          zonebuf = fss_allocbuf(FSS_NPROJ_BUF, FSS_ALLOC_ZONE);
 488  489  
 489  490          mutex_enter(&pidlock);
 490  491          if ((pid == P_MYID && id == P_MYID) ||
 491  492              (pid == curproc->p_pid && id == P_MYID)) {
 492  493                  pp = curproc;
 493  494                  tp = curthread;
 494  495                  mutex_enter(&pp->p_lock);
 495  496          } else {
 496  497                  if (pid == P_MYID) {
 497  498                          pp = curproc;
 498  499                  } else if ((pp = prfind(pid)) == NULL) {
 499  500                          error = ESRCH;
 500  501                          goto err;
 501  502                  }
 502  503                  if (pp != curproc && id == P_MYID) {
 503  504                          error = EINVAL;
 504  505                          goto err;
 505  506                  }
 506  507                  mutex_enter(&pp->p_lock);
 507  508                  if ((tp = idtot(pp, id)) == NULL) {
 508  509                          mutex_exit(&pp->p_lock);
 509  510                          error = ESRCH;
 510  511                          goto err;
 511  512                  }
 512  513          }
 513  514  
 514  515          error = pset_bind_thread(tp, pset, &oldpset, projbuf, zonebuf);
 515  516          mutex_exit(&pp->p_lock);
 516  517  err:
 517  518          mutex_exit(&pidlock);
 518  519  
 519  520          fss_freebuf(projbuf, FSS_ALLOC_PROJ);
 520  521          fss_freebuf(zonebuf, FSS_ALLOC_ZONE);
 521  522          mutex_exit(&cpu_lock);
 522  523          pool_unlock();
 523  524          if (opset != NULL) {
 524  525                  if (copyout(&oldpset, opset, sizeof (psetid_t)) != 0)
 525  526                          return (set_errno(EFAULT));
 526  527          }
 527  528          if (error != 0)
 528  529                  return (set_errno(error));
 529  530          return (0);
 530  531  }
 531  532  
 532  533  static int
 533  534  pset_bind(psetid_t pset, idtype_t idtype, id_t id, psetid_t *opset)
 534  535  {
 535  536          kthread_t       *tp;
 536  537          proc_t          *pp;
 537  538          task_t          *tk;
 538  539          kproject_t      *kpj;
 539  540          contract_t      *ct;
 540  541          zone_t          *zptr;
 541  542          psetid_t        oldpset;
 542  543          int             error = 0;
 543  544          void            *projbuf, *zonebuf;
 544  545  
 545  546          pool_lock();
 546  547          if ((pset != PS_QUERY) && (pset != PS_SOFT) &&
 547  548              (pset != PS_HARD) && (pset != PS_QUERY_TYPE)) {
 548  549                  /*
 549  550                   * Check if the set actually exists before checking
 550  551                   * permissions.  This is the historical error
 551  552                   * precedence.  Note that if pset was PS_MYID, the
 552  553                   * cpupart_get_cpus call will change it to the
 553  554                   * processor set id of the caller (or PS_NONE if the
 554  555                   * caller is not bound to a processor set).
 555  556                   */
 556  557                  if (pool_state == POOL_ENABLED) {
 557  558                          pool_unlock();
 558  559                          return (set_errno(ENOTSUP));
 559  560                  }
 560  561                  if (cpupart_get_cpus(&pset, NULL, NULL) != 0) {
 561  562                          pool_unlock();
 562  563                          return (set_errno(EINVAL));
 563  564                  } else if (pset != PS_NONE && secpolicy_pbind(CRED()) != 0) {
 564  565                          pool_unlock();
 565  566                          return (set_errno(EPERM));
 566  567                  }
 567  568          }
 568  569  
 569  570          /*
 570  571           * Pre-allocate enough buffers for FSS for all active projects
 571  572           * and for all active zones on the system.  Unused buffers will
 572  573           * be freed later by fss_freebuf().
 573  574           */
 574  575          mutex_enter(&cpu_lock);
 575  576          projbuf = fss_allocbuf(FSS_NPROJ_BUF, FSS_ALLOC_PROJ);
 576  577          zonebuf = fss_allocbuf(FSS_NPROJ_BUF, FSS_ALLOC_ZONE);
 577  578  
 578  579          switch (idtype) {
 579  580          case P_LWPID:
 580  581                  pp = curproc;
 581  582                  mutex_enter(&pidlock);
 582  583                  mutex_enter(&pp->p_lock);
 583  584                  if (id == P_MYID) {
 584  585                          tp = curthread;
 585  586                  } else {
 586  587                          if ((tp = idtot(pp, id)) == NULL) {
 587  588                                  mutex_exit(&pp->p_lock);
 588  589                                  mutex_exit(&pidlock);
 589  590                                  error = ESRCH;
 590  591                                  break;
 591  592                          }
 592  593                  }
 593  594                  error = pset_bind_thread(tp, pset, &oldpset, projbuf, zonebuf);
 594  595                  mutex_exit(&pp->p_lock);
 595  596                  mutex_exit(&pidlock);
 596  597                  break;
 597  598  
 598  599          case P_PID:
 599  600                  mutex_enter(&pidlock);
 600  601                  if (id == P_MYID) {
 601  602                          pp = curproc;
 602  603                  } else if ((pp = prfind(id)) == NULL) {
 603  604                          mutex_exit(&pidlock);
 604  605                          error = ESRCH;
 605  606                          break;
 606  607                  }
 607  608                  error = pset_bind_process(pp, pset, &oldpset, projbuf, zonebuf);
 608  609                  mutex_exit(&pidlock);
 609  610                  break;
 610  611  
 611  612          case P_TASKID:
 612  613                  mutex_enter(&pidlock);
 613  614                  if (id == P_MYID)
 614  615                          id = curproc->p_task->tk_tkid;
 615  616                  if ((tk = task_hold_by_id(id)) == NULL) {
 616  617                          mutex_exit(&pidlock);
 617  618                          error = ESRCH;
 618  619                          break;
 619  620                  }
 620  621                  error = pset_bind_task(tk, pset, &oldpset, projbuf, zonebuf);
 621  622                  mutex_exit(&pidlock);
 622  623                  task_rele(tk);
 623  624                  break;
 624  625  
 625  626          case P_PROJID:
 626  627                  pp = curproc;
 627  628                  if (id == P_MYID)
 628  629                          id = curprojid();
 629  630                  if ((kpj = project_hold_by_id(id, pp->p_zone,
 630  631                      PROJECT_HOLD_FIND)) == NULL) {
 631  632                          error = ESRCH;
 632  633                          break;
 633  634                  }
 634  635                  mutex_enter(&pidlock);
 635  636                  error = pset_bind_project(kpj, pset, &oldpset, projbuf,
 636  637                      zonebuf);
 637  638                  mutex_exit(&pidlock);
 638  639                  project_rele(kpj);
 639  640                  break;
 640  641  
 641  642          case P_ZONEID:
 642  643                  if (id == P_MYID)
 643  644                          id = getzoneid();
 644  645                  if ((zptr = zone_find_by_id(id)) == NULL) {
 645  646                          error = ESRCH;
 646  647                          break;
 647  648                  }
 648  649                  mutex_enter(&pidlock);
 649  650                  error = pset_bind_zone(zptr, pset, &oldpset, projbuf, zonebuf);
 650  651                  mutex_exit(&pidlock);
 651  652                  zone_rele(zptr);
 652  653                  break;
 653  654  
 654  655          case P_CTID:
 655  656                  if (id == P_MYID)
 656  657                          id = PRCTID(curproc);
 657  658                  if ((ct = contract_type_ptr(process_type, id,
 658  659                      curproc->p_zone->zone_uniqid)) == NULL) {
 659  660                          error = ESRCH;
 660  661                          break;
 661  662                  }
 662  663                  mutex_enter(&pidlock);
 663  664                  error = pset_bind_contract(ct->ct_data, pset, &oldpset, projbuf,
 664  665                      zonebuf);
 665  666                  mutex_exit(&pidlock);
 666  667                  contract_rele(ct);
 667  668                  break;
 668  669  
 669  670          case P_PSETID:
 670  671                  if (id == P_MYID || pset != PS_NONE || !INGLOBALZONE(curproc)) {
 671  672                          error = EINVAL;
 672  673                          break;
 673  674                  }
 674  675                  error = pset_unbind(id, projbuf, zonebuf, idtype);
 675  676                  break;
 676  677  
 677  678          case P_ALL:
 678  679                  if (id == P_MYID || pset != PS_NONE || !INGLOBALZONE(curproc)) {
 679  680                          error = EINVAL;
 680  681                          break;
 681  682                  }
 682  683                  error = pset_unbind(PS_NONE, projbuf, zonebuf, idtype);
 683  684                  break;
 684  685  
 685  686          default:
 686  687                  error = EINVAL;
 687  688                  break;
 688  689          }
 689  690  
 690  691          fss_freebuf(projbuf, FSS_ALLOC_PROJ);
 691  692          fss_freebuf(zonebuf, FSS_ALLOC_ZONE);
 692  693          mutex_exit(&cpu_lock);
 693  694          pool_unlock();
 694  695  
 695  696          if (error != 0)
 696  697                  return (set_errno(error));
 697  698          if (opset != NULL) {
 698  699                  if (copyout(&oldpset, opset, sizeof (psetid_t)) != 0)
 699  700                          return (set_errno(EFAULT));
 700  701          }
 701  702          return (0);
 702  703  }
 703  704  
 704  705  /*
 705  706   * Report load average statistics for the specified processor set.
 706  707   */
 707  708  static int
 708  709  pset_getloadavg(psetid_t pset, int *buf, int nelem)
 709  710  {
 710  711          int loadbuf[LOADAVG_NSTATS];
 711  712          int error = 0;
 712  713  
 713  714          if (nelem < 0)
 714  715                  return (set_errno(EINVAL));
 715  716  
 716  717          /*
 717  718           * We keep the same number of load average statistics for processor
 718  719           * sets as we do for the system as a whole.
 719  720           */
 720  721          if (nelem > LOADAVG_NSTATS)
 721  722                  nelem = LOADAVG_NSTATS;
 722  723  
 723  724          mutex_enter(&cpu_lock);
 724  725          error = cpupart_get_loadavg(pset, loadbuf, nelem);
 725  726          mutex_exit(&cpu_lock);
 726  727          if (!error && nelem && copyout(loadbuf, buf, nelem * sizeof (int)) != 0)
 727  728                  error = EFAULT;
 728  729  
 729  730          if (error)
 730  731                  return (set_errno(error));
 731  732          else
 732  733                  return (0);
 733  734  }
 734  735  
 735  736  
 736  737  /*
 737  738   * Return list of active processor sets, up to a maximum indicated by
 738  739   * numpsets.  The total number of processor sets is stored in the
 739  740   * location pointed to by numpsets.
 740  741   */
 741  742  static int
 742  743  pset_list(psetid_t *psetlist, uint_t *numpsets)
 743  744  {
 744  745          uint_t user_npsets = 0;
 745  746          uint_t real_npsets;
 746  747          psetid_t *psets = NULL;
 747  748          int error = 0;
 748  749  
 749  750          if (numpsets != NULL) {
 750  751                  if (copyin(numpsets, &user_npsets, sizeof (uint_t)) != 0)
 751  752                          return (set_errno(EFAULT));
 752  753          }
 753  754  
 754  755          /*
 755  756           * Get the list of all processor sets.  First we need to find
 756  757           * out how many there are, so we can allocate a large enough
 757  758           * buffer.
 758  759           */
 759  760          mutex_enter(&cpu_lock);
 760  761          if (!INGLOBALZONE(curproc) && pool_pset_enabled()) {
 761  762                  psetid_t psetid = zone_pset_get(curproc->p_zone);
 762  763  
 763  764                  if (psetid == PS_NONE) {
 764  765                          real_npsets = 0;
 765  766                  } else {
 766  767                          real_npsets = 1;
 767  768                          psets = kmem_alloc(real_npsets * sizeof (psetid_t),
 768  769                              KM_SLEEP);
 769  770                          psets[0] = psetid;
 770  771                  }
 771  772          } else {
 772  773                  real_npsets = cpupart_list(0, NULL, CP_ALL);
 773  774                  if (real_npsets) {
 774  775                          psets = kmem_alloc(real_npsets * sizeof (psetid_t),
 775  776                              KM_SLEEP);
 776  777                          (void) cpupart_list(psets, real_npsets, CP_ALL);
 777  778                  }
 778  779          }
 779  780          mutex_exit(&cpu_lock);
 780  781  
 781  782          if (user_npsets > real_npsets)
 782  783                  user_npsets = real_npsets;
 783  784  
 784  785          if (numpsets != NULL) {
 785  786                  if (copyout(&real_npsets, numpsets, sizeof (uint_t)) != 0)
 786  787                          error = EFAULT;
 787  788                  else if (psetlist != NULL && user_npsets != 0) {
 788  789                          if (copyout(psets, psetlist,
 789  790                              user_npsets * sizeof (psetid_t)) != 0)
 790  791                                  error = EFAULT;
 791  792                  }
 792  793          }
 793  794  
 794  795          if (real_npsets)
 795  796                  kmem_free(psets, real_npsets * sizeof (psetid_t));
 796  797  
 797  798          if (error)
 798  799                  return (set_errno(error));
 799  800          else
 800  801                  return (0);
 801  802  }
 802  803  
 803  804  static int
 804  805  pset_setattr(psetid_t pset, uint_t attr)
 805  806  {
 806  807          int error;
 807  808  
 808  809          if (secpolicy_pset(CRED()) != 0)
 809  810                  return (set_errno(EPERM));
 810  811          pool_lock();
 811  812          if (pool_state == POOL_ENABLED) {
 812  813                  pool_unlock();
 813  814                  return (set_errno(ENOTSUP));
 814  815          }
 815  816          if (pset == PS_QUERY || PSET_BADATTR(attr)) {
 816  817                  pool_unlock();
 817  818                  return (set_errno(EINVAL));
 818  819          }
 819  820          if ((error = cpupart_setattr(pset, attr)) != 0) {
 820  821                  pool_unlock();
 821  822                  return (set_errno(error));
 822  823          }
 823  824          pool_unlock();
 824  825          return (0);
 825  826  }
 826  827  
 827  828  static int
 828  829  pset_getattr(psetid_t pset, uint_t *attrp)
 829  830  {
 830  831          int error = 0;
 831  832          uint_t attr;
 832  833  
 833  834          if (pset == PS_QUERY)
 834  835                  return (set_errno(EINVAL));
 835  836          if ((error = cpupart_getattr(pset, &attr)) != 0)
 836  837                  return (set_errno(error));
 837  838          if (copyout(&attr, attrp, sizeof (uint_t)) != 0)
 838  839                  return (set_errno(EFAULT));
 839  840          return (0);
 840  841  }
 841  842  
 842  843  static int
 843  844  pset(int subcode, long arg1, long arg2, long arg3, long arg4)
 844  845  {
 845  846          switch (subcode) {
 846  847          case PSET_CREATE:
 847  848                  return (pset_create((psetid_t *)arg1));
 848  849          case PSET_DESTROY:
 849  850                  return (pset_destroy((psetid_t)arg1));
 850  851          case PSET_ASSIGN:
 851  852                  return (pset_assign((psetid_t)arg1,
 852  853                      (processorid_t)arg2, (psetid_t *)arg3, 0));
 853  854          case PSET_INFO:
 854  855                  return (pset_info((psetid_t)arg1, (int *)arg2,
 855  856                      (uint_t *)arg3, (processorid_t *)arg4));
 856  857          case PSET_BIND:
 857  858                  return (pset_bind((psetid_t)arg1, (idtype_t)arg2,
 858  859                      (id_t)arg3, (psetid_t *)arg4));
 859  860          case PSET_BIND_LWP:
 860  861                  return (pset_bind_lwp((psetid_t)arg1, (id_t)arg2,
 861  862                      (pid_t)arg3, (psetid_t *)arg4));
 862  863          case PSET_GETLOADAVG:
 863  864                  return (pset_getloadavg((psetid_t)arg1, (int *)arg2,
 864  865                      (int)arg3));
 865  866          case PSET_LIST:
 866  867                  return (pset_list((psetid_t *)arg1, (uint_t *)arg2));
 867  868          case PSET_SETATTR:
 868  869                  return (pset_setattr((psetid_t)arg1, (uint_t)arg2));
 869  870          case PSET_GETATTR:
 870  871                  return (pset_getattr((psetid_t)arg1, (uint_t *)arg2));
 871  872          case PSET_ASSIGN_FORCED:
 872  873                  return (pset_assign((psetid_t)arg1,
 873  874                      (processorid_t)arg2, (psetid_t *)arg3, 1));
 874  875          default:
 875  876                  return (set_errno(EINVAL));
 876  877          }
 877  878  }
  
    | 
      ↓ open down ↓ | 
    796 lines elided | 
    
      ↑ open up ↑ | 
  
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX