Print this page
7882 Add /dev/full , the always-full memory device
Reviewed by: Adam Stevko <adam.stevko@gmail.com>
Reviewed by: Toomas Soome <tsoome@me.com>

Split Close
Expand all
Collapse all
          --- old/usr/src/uts/common/io/mem.c
          +++ new/usr/src/uts/common/io/mem.c
↓ open down ↓ 17 lines elided ↑ open up ↑
  18   18   *
  19   19   * CDDL HEADER END
  20   20   */
  21   21  /*
  22   22   * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
  23   23   * Use is subject to license terms.
  24   24   */
  25   25  
  26   26  /*
  27   27   * Copyright (c) 2015, Joyent, Inc.  All rights reserved.
       28 + * Copyright 2017 James S Blachly, MD <james.blachly@gmail.com>
  28   29   */
  29   30  
  30   31  /*
  31   32   * Memory special file
  32   33   */
  33   34  
  34   35  #include <sys/types.h>
  35   36  #include <sys/param.h>
  36   37  #include <sys/user.h>
  37   38  #include <sys/buf.h>
↓ open down ↓ 115 lines elided ↑ open up ↑
 153  154                  int privonly;
 154  155                  const char *rdpriv;
 155  156                  const char *wrpriv;
 156  157                  mode_t priv_mode;
 157  158          } mm[] = {
 158  159                  { "mem",        M_MEM,          0,      NULL,   "all",  0640 },
 159  160                  { "kmem",       M_KMEM,         0,      NULL,   "all",  0640 },
 160  161                  { "allkmem",    M_ALLKMEM,      0,      "all",  "all",  0600 },
 161  162                  { "null",       M_NULL, PRIVONLY_DEV,   NULL,   NULL,   0666 },
 162  163                  { "zero",       M_ZERO, PRIVONLY_DEV,   NULL,   NULL,   0666 },
      164 +                { "full",       M_FULL, PRIVONLY_DEV,   NULL,   NULL,   0666 },
 163  165          };
 164  166          kstat_t *ksp;
 165  167  
 166  168          mutex_init(&mm_lock, NULL, MUTEX_DEFAULT, NULL);
 167  169          mm_map = vmem_alloc(heap_arena, PAGESIZE, VM_SLEEP);
 168  170  
 169  171          for (i = 0; i < (sizeof (mm) / sizeof (mm[0])); i++) {
 170  172                  if (ddi_create_priv_minor_node(devi, mm[i].name, S_IFCHR,
 171  173                      mm[i].minor, DDI_PSEUDO, mm[i].privonly,
 172  174                      mm[i].rdpriv, mm[i].wrpriv, mm[i].priv_mode) ==
↓ open down ↓ 41 lines elided ↑ open up ↑
 214  216          return (error);
 215  217  }
 216  218  
 217  219  /*ARGSUSED1*/
 218  220  static int
 219  221  mmopen(dev_t *devp, int flag, int typ, struct cred *cred)
 220  222  {
 221  223          switch (getminor(*devp)) {
 222  224          case M_NULL:
 223  225          case M_ZERO:
      226 +        case M_FULL:
 224  227          case M_MEM:
 225  228          case M_KMEM:
 226  229          case M_ALLKMEM:
 227  230                  /* standard devices */
 228  231                  break;
 229  232  
 230  233          default:
 231  234                  /* Unsupported or unknown type */
 232  235                  return (EINVAL);
 233  236          }
↓ open down ↓ 6 lines elided ↑ open up ↑
 240  243  struct pollhead mm_pollhd;
 241  244  
 242  245  /*ARGSUSED*/
 243  246  static int
 244  247  mmchpoll(dev_t dev, short events, int anyyet, short *reventsp,
 245  248      struct pollhead **phpp)
 246  249  {
 247  250          switch (getminor(dev)) {
 248  251          case M_NULL:
 249  252          case M_ZERO:
      253 +        case M_FULL:
 250  254          case M_MEM:
 251  255          case M_KMEM:
 252  256          case M_ALLKMEM:
 253  257                  *reventsp = events & (POLLIN | POLLOUT | POLLPRI | POLLRDNORM |
 254  258                      POLLWRNORM | POLLRDBAND | POLLWRBAND);
 255  259                  /*
 256  260                   * A non NULL pollhead pointer should be returned in case
 257  261                   * user polls for 0 events.
 258  262                   */
 259  263                  *phpp = !anyyet && !*reventsp ?
↓ open down ↓ 171 lines elided ↑ open up ↑
 431  435                          error = mmio(uio, rw, v, uio->uio_loffset & PAGEOFFSET,
 432  436                              minor == M_ALLKMEM || mm_kmem_io_access,
 433  437                              (locked && ppp) ? *ppp : NULL);
 434  438                          if (locked)
 435  439                                  as_pageunlock(&kas, ppp, vaddr, PAGESIZE,
 436  440                                      S_WRITE);
 437  441                          }
 438  442  
 439  443                          break;
 440  444  
      445 +                case M_FULL:
      446 +                        if (rw == UIO_WRITE) {
      447 +                                error = ENOSPC;
      448 +                                break;
      449 +                        }
      450 +                        /* else it's a read, fall through to zero case */
      451 +                        /*FALLTHROUGH*/
      452 +
 441  453                  case M_ZERO:
 442  454                          if (rw == UIO_READ) {
 443  455                                  label_t ljb;
 444  456  
 445  457                                  if (on_fault(&ljb)) {
 446  458                                          no_fault();
 447  459                                          error = EFAULT;
 448  460                                          break;
 449  461                                  }
 450  462                                  uzero(iov->iov_base, iov->iov_len);
↓ open down ↓ 369 lines elided ↑ open up ↑
 820  832                          }
 821  833                  }
 822  834                  memlist_read_unlock();
 823  835                  break;
 824  836  
 825  837          case M_KMEM:
 826  838          case M_ALLKMEM:
 827  839                  /* no longer supported with KPR */
 828  840                  return (-1);
 829  841  
      842 +        case M_FULL:
 830  843          case M_ZERO:
 831  844                  /*
 832  845                   * We shouldn't be mmap'ing to /dev/zero here as
 833  846                   * mmsegmap() should have already converted
 834  847                   * a mapping request for this device to a mapping
 835  848                   * using seg_vn for anonymous memory.
 836  849                   */
 837  850                  break;
 838  851  
 839  852          }
↓ open down ↓ 265 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX