Print this page
    
2619 asynchronous destruction of ZFS file systems
2747 SPA versioning with zfs feature flags
Reviewed by: Matt Ahrens <mahrens@delphix.com>
Reviewed by: George Wilson <gwilson@delphix.com>
Reviewed by: Richard Lowe <richlowe@richlowe.net>
Reviewed by: Dan Kruchinin <dan.kruchinin@gmail.com>
Approved by: Dan McDonald <danmcd@nexenta.com>
    
      
        | Split | 
	Close | 
      
      | Expand all | 
      | Collapse all | 
    
    
          --- old/usr/src/lib/libzfs/common/libzfs_util.c
          +++ new/usr/src/lib/libzfs/common/libzfs_util.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
  
    | 
      ↓ open down ↓ | 
    10 lines elided | 
    
      ↑ open up ↑ | 
  
  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   23   * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
  23      - * Copyright (c) 2011 by Delphix. All rights reserved.
       24 + * Copyright (c) 2012 by Delphix. All rights reserved.
  24   25   */
  25   26  
  26   27  /*
  27   28   * Internal utility routines for the ZFS library.
  28   29   */
  29   30  
  30   31  #include <errno.h>
  31   32  #include <fcntl.h>
  32   33  #include <libintl.h>
  33   34  #include <stdarg.h>
  34   35  #include <stdio.h>
  35   36  #include <stdlib.h>
  36   37  #include <strings.h>
  37   38  #include <unistd.h>
  
    | 
      ↓ open down ↓ | 
    4 lines elided | 
    
      ↑ open up ↑ | 
  
  38   39  #include <ctype.h>
  39   40  #include <math.h>
  40   41  #include <sys/mnttab.h>
  41   42  #include <sys/mntent.h>
  42   43  #include <sys/types.h>
  43   44  
  44   45  #include <libzfs.h>
  45   46  
  46   47  #include "libzfs_impl.h"
  47   48  #include "zfs_prop.h"
       49 +#include "zfeature_common.h"
  48   50  
  49   51  int
  50   52  libzfs_errno(libzfs_handle_t *hdl)
  51   53  {
  52   54          return (hdl->libzfs_error);
  53   55  }
  54   56  
  55   57  const char *
  56   58  libzfs_error_action(libzfs_handle_t *hdl)
  57   59  {
  58   60          return (hdl->libzfs_action);
  59   61  }
  60   62  
  61   63  const char *
  62   64  libzfs_error_description(libzfs_handle_t *hdl)
  63   65  {
  64   66          if (hdl->libzfs_desc[0] != '\0')
  65   67                  return (hdl->libzfs_desc);
  66   68  
  67   69          switch (hdl->libzfs_error) {
  68   70          case EZFS_NOMEM:
  69   71                  return (dgettext(TEXT_DOMAIN, "out of memory"));
  70   72          case EZFS_BADPROP:
  71   73                  return (dgettext(TEXT_DOMAIN, "invalid property value"));
  72   74          case EZFS_PROPREADONLY:
  73   75                  return (dgettext(TEXT_DOMAIN, "read-only property"));
  74   76          case EZFS_PROPTYPE:
  75   77                  return (dgettext(TEXT_DOMAIN, "property doesn't apply to "
  76   78                      "datasets of this type"));
  77   79          case EZFS_PROPNONINHERIT:
  78   80                  return (dgettext(TEXT_DOMAIN, "property cannot be inherited"));
  79   81          case EZFS_PROPSPACE:
  80   82                  return (dgettext(TEXT_DOMAIN, "invalid quota or reservation"));
  81   83          case EZFS_BADTYPE:
  82   84                  return (dgettext(TEXT_DOMAIN, "operation not applicable to "
  83   85                      "datasets of this type"));
  84   86          case EZFS_BUSY:
  85   87                  return (dgettext(TEXT_DOMAIN, "pool or dataset is busy"));
  86   88          case EZFS_EXISTS:
  87   89                  return (dgettext(TEXT_DOMAIN, "pool or dataset exists"));
  88   90          case EZFS_NOENT:
  89   91                  return (dgettext(TEXT_DOMAIN, "no such pool or dataset"));
  90   92          case EZFS_BADSTREAM:
  91   93                  return (dgettext(TEXT_DOMAIN, "invalid backup stream"));
  92   94          case EZFS_DSREADONLY:
  93   95                  return (dgettext(TEXT_DOMAIN, "dataset is read-only"));
  94   96          case EZFS_VOLTOOBIG:
  95   97                  return (dgettext(TEXT_DOMAIN, "volume size exceeds limit for "
  96   98                      "this system"));
  97   99          case EZFS_INVALIDNAME:
  98  100                  return (dgettext(TEXT_DOMAIN, "invalid name"));
  99  101          case EZFS_BADRESTORE:
 100  102                  return (dgettext(TEXT_DOMAIN, "unable to restore to "
 101  103                      "destination"));
 102  104          case EZFS_BADBACKUP:
 103  105                  return (dgettext(TEXT_DOMAIN, "backup failed"));
 104  106          case EZFS_BADTARGET:
  
    | 
      ↓ open down ↓ | 
    47 lines elided | 
    
      ↑ open up ↑ | 
  
 105  107                  return (dgettext(TEXT_DOMAIN, "invalid target vdev"));
 106  108          case EZFS_NODEVICE:
 107  109                  return (dgettext(TEXT_DOMAIN, "no such device in pool"));
 108  110          case EZFS_BADDEV:
 109  111                  return (dgettext(TEXT_DOMAIN, "invalid device"));
 110  112          case EZFS_NOREPLICAS:
 111  113                  return (dgettext(TEXT_DOMAIN, "no valid replicas"));
 112  114          case EZFS_RESILVERING:
 113  115                  return (dgettext(TEXT_DOMAIN, "currently resilvering"));
 114  116          case EZFS_BADVERSION:
 115      -                return (dgettext(TEXT_DOMAIN, "unsupported version"));
      117 +                return (dgettext(TEXT_DOMAIN, "unsupported version or "
      118 +                    "feature"));
 116  119          case EZFS_POOLUNAVAIL:
 117  120                  return (dgettext(TEXT_DOMAIN, "pool is unavailable"));
 118  121          case EZFS_DEVOVERFLOW:
 119  122                  return (dgettext(TEXT_DOMAIN, "too many devices in one vdev"));
 120  123          case EZFS_BADPATH:
 121  124                  return (dgettext(TEXT_DOMAIN, "must be an absolute path"));
 122  125          case EZFS_CROSSTARGET:
 123  126                  return (dgettext(TEXT_DOMAIN, "operation crosses datasets or "
 124  127                      "pools"));
 125  128          case EZFS_ZONED:
 126  129                  return (dgettext(TEXT_DOMAIN, "dataset in use by local zone"));
 127  130          case EZFS_MOUNTFAILED:
 128  131                  return (dgettext(TEXT_DOMAIN, "mount failed"));
 129  132          case EZFS_UMOUNTFAILED:
 130  133                  return (dgettext(TEXT_DOMAIN, "umount failed"));
 131  134          case EZFS_UNSHARENFSFAILED:
 132  135                  return (dgettext(TEXT_DOMAIN, "unshare(1M) failed"));
 133  136          case EZFS_SHARENFSFAILED:
 134  137                  return (dgettext(TEXT_DOMAIN, "share(1M) failed"));
 135  138          case EZFS_UNSHARESMBFAILED:
 136  139                  return (dgettext(TEXT_DOMAIN, "smb remove share failed"));
 137  140          case EZFS_SHARESMBFAILED:
 138  141                  return (dgettext(TEXT_DOMAIN, "smb add share failed"));
 139  142          case EZFS_PERM:
 140  143                  return (dgettext(TEXT_DOMAIN, "permission denied"));
 141  144          case EZFS_NOSPC:
 142  145                  return (dgettext(TEXT_DOMAIN, "out of space"));
 143  146          case EZFS_FAULT:
 144  147                  return (dgettext(TEXT_DOMAIN, "bad address"));
 145  148          case EZFS_IO:
 146  149                  return (dgettext(TEXT_DOMAIN, "I/O error"));
 147  150          case EZFS_INTR:
 148  151                  return (dgettext(TEXT_DOMAIN, "signal received"));
 149  152          case EZFS_ISSPARE:
 150  153                  return (dgettext(TEXT_DOMAIN, "device is reserved as a hot "
 151  154                      "spare"));
 152  155          case EZFS_INVALCONFIG:
 153  156                  return (dgettext(TEXT_DOMAIN, "invalid vdev configuration"));
 154  157          case EZFS_RECURSIVE:
 155  158                  return (dgettext(TEXT_DOMAIN, "recursive dataset dependency"));
 156  159          case EZFS_NOHISTORY:
 157  160                  return (dgettext(TEXT_DOMAIN, "no history available"));
 158  161          case EZFS_POOLPROPS:
 159  162                  return (dgettext(TEXT_DOMAIN, "failed to retrieve "
 160  163                      "pool properties"));
 161  164          case EZFS_POOL_NOTSUP:
 162  165                  return (dgettext(TEXT_DOMAIN, "operation not supported "
 163  166                      "on this type of pool"));
 164  167          case EZFS_POOL_INVALARG:
 165  168                  return (dgettext(TEXT_DOMAIN, "invalid argument for "
 166  169                      "this pool operation"));
 167  170          case EZFS_NAMETOOLONG:
 168  171                  return (dgettext(TEXT_DOMAIN, "dataset name is too long"));
 169  172          case EZFS_OPENFAILED:
 170  173                  return (dgettext(TEXT_DOMAIN, "open failed"));
 171  174          case EZFS_NOCAP:
 172  175                  return (dgettext(TEXT_DOMAIN,
 173  176                      "disk capacity information could not be retrieved"));
 174  177          case EZFS_LABELFAILED:
 175  178                  return (dgettext(TEXT_DOMAIN, "write of label failed"));
 176  179          case EZFS_BADWHO:
 177  180                  return (dgettext(TEXT_DOMAIN, "invalid user/group"));
 178  181          case EZFS_BADPERM:
 179  182                  return (dgettext(TEXT_DOMAIN, "invalid permission"));
 180  183          case EZFS_BADPERMSET:
 181  184                  return (dgettext(TEXT_DOMAIN, "invalid permission set name"));
 182  185          case EZFS_NODELEGATION:
 183  186                  return (dgettext(TEXT_DOMAIN, "delegated administration is "
 184  187                      "disabled on pool"));
 185  188          case EZFS_BADCACHE:
 186  189                  return (dgettext(TEXT_DOMAIN, "invalid or missing cache file"));
 187  190          case EZFS_ISL2CACHE:
 188  191                  return (dgettext(TEXT_DOMAIN, "device is in use as a cache"));
 189  192          case EZFS_VDEVNOTSUP:
 190  193                  return (dgettext(TEXT_DOMAIN, "vdev specification is not "
 191  194                      "supported"));
 192  195          case EZFS_NOTSUP:
 193  196                  return (dgettext(TEXT_DOMAIN, "operation not supported "
 194  197                      "on this dataset"));
 195  198          case EZFS_ACTIVE_SPARE:
 196  199                  return (dgettext(TEXT_DOMAIN, "pool has active shared spare "
 197  200                      "device"));
 198  201          case EZFS_UNPLAYED_LOGS:
 199  202                  return (dgettext(TEXT_DOMAIN, "log device has unplayed intent "
 200  203                      "logs"));
 201  204          case EZFS_REFTAG_RELE:
 202  205                  return (dgettext(TEXT_DOMAIN, "no such tag on this dataset"));
 203  206          case EZFS_REFTAG_HOLD:
 204  207                  return (dgettext(TEXT_DOMAIN, "tag already exists on this "
 205  208                      "dataset"));
 206  209          case EZFS_TAGTOOLONG:
 207  210                  return (dgettext(TEXT_DOMAIN, "tag too long"));
 208  211          case EZFS_PIPEFAILED:
 209  212                  return (dgettext(TEXT_DOMAIN, "pipe create failed"));
 210  213          case EZFS_THREADCREATEFAILED:
 211  214                  return (dgettext(TEXT_DOMAIN, "thread create failed"));
 212  215          case EZFS_POSTSPLIT_ONLINE:
 213  216                  return (dgettext(TEXT_DOMAIN, "disk was split from this pool "
 214  217                      "into a new one"));
 215  218          case EZFS_SCRUBBING:
 216  219                  return (dgettext(TEXT_DOMAIN, "currently scrubbing; "
 217  220                      "use 'zpool scrub -s' to cancel current scrub"));
 218  221          case EZFS_NO_SCRUB:
 219  222                  return (dgettext(TEXT_DOMAIN, "there is no active scrub"));
 220  223          case EZFS_DIFF:
 221  224                  return (dgettext(TEXT_DOMAIN, "unable to generate diffs"));
 222  225          case EZFS_DIFFDATA:
 223  226                  return (dgettext(TEXT_DOMAIN, "invalid diff data"));
 224  227          case EZFS_POOLREADONLY:
 225  228                  return (dgettext(TEXT_DOMAIN, "pool is read-only"));
 226  229          case EZFS_UNKNOWN:
 227  230                  return (dgettext(TEXT_DOMAIN, "unknown error"));
 228  231          default:
 229  232                  assert(hdl->libzfs_error == 0);
 230  233                  return (dgettext(TEXT_DOMAIN, "no error"));
 231  234          }
 232  235  }
 233  236  
 234  237  /*PRINTFLIKE2*/
 235  238  void
 236  239  zfs_error_aux(libzfs_handle_t *hdl, const char *fmt, ...)
 237  240  {
 238  241          va_list ap;
 239  242  
 240  243          va_start(ap, fmt);
 241  244  
 242  245          (void) vsnprintf(hdl->libzfs_desc, sizeof (hdl->libzfs_desc),
 243  246              fmt, ap);
 244  247          hdl->libzfs_desc_active = 1;
 245  248  
 246  249          va_end(ap);
 247  250  }
 248  251  
 249  252  static void
 250  253  zfs_verror(libzfs_handle_t *hdl, int error, const char *fmt, va_list ap)
 251  254  {
 252  255          (void) vsnprintf(hdl->libzfs_action, sizeof (hdl->libzfs_action),
 253  256              fmt, ap);
 254  257          hdl->libzfs_error = error;
 255  258  
 256  259          if (hdl->libzfs_desc_active)
 257  260                  hdl->libzfs_desc_active = 0;
 258  261          else
 259  262                  hdl->libzfs_desc[0] = '\0';
 260  263  
 261  264          if (hdl->libzfs_printerr) {
 262  265                  if (error == EZFS_UNKNOWN) {
 263  266                          (void) fprintf(stderr, dgettext(TEXT_DOMAIN, "internal "
 264  267                              "error: %s\n"), libzfs_error_description(hdl));
 265  268                          abort();
 266  269                  }
 267  270  
 268  271                  (void) fprintf(stderr, "%s: %s\n", hdl->libzfs_action,
 269  272                      libzfs_error_description(hdl));
 270  273                  if (error == EZFS_NOMEM)
 271  274                          exit(1);
 272  275          }
 273  276  }
 274  277  
 275  278  int
 276  279  zfs_error(libzfs_handle_t *hdl, int error, const char *msg)
 277  280  {
 278  281          return (zfs_error_fmt(hdl, error, "%s", msg));
 279  282  }
 280  283  
 281  284  /*PRINTFLIKE3*/
 282  285  int
 283  286  zfs_error_fmt(libzfs_handle_t *hdl, int error, const char *fmt, ...)
 284  287  {
 285  288          va_list ap;
 286  289  
 287  290          va_start(ap, fmt);
 288  291  
 289  292          zfs_verror(hdl, error, fmt, ap);
 290  293  
 291  294          va_end(ap);
 292  295  
 293  296          return (-1);
 294  297  }
 295  298  
 296  299  static int
 297  300  zfs_common_error(libzfs_handle_t *hdl, int error, const char *fmt,
 298  301      va_list ap)
 299  302  {
 300  303          switch (error) {
 301  304          case EPERM:
 302  305          case EACCES:
 303  306                  zfs_verror(hdl, EZFS_PERM, fmt, ap);
 304  307                  return (-1);
 305  308  
 306  309          case ECANCELED:
 307  310                  zfs_verror(hdl, EZFS_NODELEGATION, fmt, ap);
 308  311                  return (-1);
 309  312  
 310  313          case EIO:
 311  314                  zfs_verror(hdl, EZFS_IO, fmt, ap);
 312  315                  return (-1);
 313  316  
 314  317          case EFAULT:
 315  318                  zfs_verror(hdl, EZFS_FAULT, fmt, ap);
 316  319                  return (-1);
 317  320  
 318  321          case EINTR:
 319  322                  zfs_verror(hdl, EZFS_INTR, fmt, ap);
 320  323                  return (-1);
 321  324          }
 322  325  
 323  326          return (0);
 324  327  }
 325  328  
 326  329  int
 327  330  zfs_standard_error(libzfs_handle_t *hdl, int error, const char *msg)
 328  331  {
 329  332          return (zfs_standard_error_fmt(hdl, error, "%s", msg));
 330  333  }
 331  334  
 332  335  /*PRINTFLIKE3*/
 333  336  int
 334  337  zfs_standard_error_fmt(libzfs_handle_t *hdl, int error, const char *fmt, ...)
 335  338  {
 336  339          va_list ap;
 337  340  
 338  341          va_start(ap, fmt);
 339  342  
 340  343          if (zfs_common_error(hdl, error, fmt, ap) != 0) {
 341  344                  va_end(ap);
 342  345                  return (-1);
 343  346          }
 344  347  
 345  348          switch (error) {
 346  349          case ENXIO:
 347  350          case ENODEV:
 348  351          case EPIPE:
 349  352                  zfs_verror(hdl, EZFS_IO, fmt, ap);
 350  353                  break;
 351  354  
 352  355          case ENOENT:
 353  356                  zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
 354  357                      "dataset does not exist"));
 355  358                  zfs_verror(hdl, EZFS_NOENT, fmt, ap);
 356  359                  break;
 357  360  
 358  361          case ENOSPC:
 359  362          case EDQUOT:
 360  363                  zfs_verror(hdl, EZFS_NOSPC, fmt, ap);
 361  364                  return (-1);
 362  365  
 363  366          case EEXIST:
 364  367                  zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
 365  368                      "dataset already exists"));
 366  369                  zfs_verror(hdl, EZFS_EXISTS, fmt, ap);
 367  370                  break;
 368  371  
 369  372          case EBUSY:
 370  373                  zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
 371  374                      "dataset is busy"));
 372  375                  zfs_verror(hdl, EZFS_BUSY, fmt, ap);
 373  376                  break;
 374  377          case EROFS:
 375  378                  zfs_verror(hdl, EZFS_POOLREADONLY, fmt, ap);
 376  379                  break;
 377  380          case ENAMETOOLONG:
 378  381                  zfs_verror(hdl, EZFS_NAMETOOLONG, fmt, ap);
 379  382                  break;
 380  383          case ENOTSUP:
 381  384                  zfs_verror(hdl, EZFS_BADVERSION, fmt, ap);
 382  385                  break;
 383  386          case EAGAIN:
 384  387                  zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
 385  388                      "pool I/O is currently suspended"));
 386  389                  zfs_verror(hdl, EZFS_POOLUNAVAIL, fmt, ap);
 387  390                  break;
 388  391          default:
 389  392                  zfs_error_aux(hdl, strerror(error));
 390  393                  zfs_verror(hdl, EZFS_UNKNOWN, fmt, ap);
 391  394                  break;
 392  395          }
 393  396  
 394  397          va_end(ap);
 395  398          return (-1);
 396  399  }
 397  400  
 398  401  int
 399  402  zpool_standard_error(libzfs_handle_t *hdl, int error, const char *msg)
 400  403  {
 401  404          return (zpool_standard_error_fmt(hdl, error, "%s", msg));
 402  405  }
 403  406  
 404  407  /*PRINTFLIKE3*/
 405  408  int
 406  409  zpool_standard_error_fmt(libzfs_handle_t *hdl, int error, const char *fmt, ...)
 407  410  {
 408  411          va_list ap;
 409  412  
 410  413          va_start(ap, fmt);
 411  414  
 412  415          if (zfs_common_error(hdl, error, fmt, ap) != 0) {
 413  416                  va_end(ap);
 414  417                  return (-1);
 415  418          }
 416  419  
 417  420          switch (error) {
 418  421          case ENODEV:
 419  422                  zfs_verror(hdl, EZFS_NODEVICE, fmt, ap);
 420  423                  break;
 421  424  
 422  425          case ENOENT:
 423  426                  zfs_error_aux(hdl,
 424  427                      dgettext(TEXT_DOMAIN, "no such pool or dataset"));
 425  428                  zfs_verror(hdl, EZFS_NOENT, fmt, ap);
 426  429                  break;
 427  430  
 428  431          case EEXIST:
 429  432                  zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
 430  433                      "pool already exists"));
 431  434                  zfs_verror(hdl, EZFS_EXISTS, fmt, ap);
 432  435                  break;
 433  436  
 434  437          case EBUSY:
 435  438                  zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "pool is busy"));
 436  439                  zfs_verror(hdl, EZFS_BUSY, fmt, ap);
 437  440                  break;
 438  441  
 439  442          case ENXIO:
 440  443                  zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
 441  444                      "one or more devices is currently unavailable"));
 442  445                  zfs_verror(hdl, EZFS_BADDEV, fmt, ap);
 443  446                  break;
 444  447  
 445  448          case ENAMETOOLONG:
 446  449                  zfs_verror(hdl, EZFS_DEVOVERFLOW, fmt, ap);
 447  450                  break;
 448  451  
 449  452          case ENOTSUP:
 450  453                  zfs_verror(hdl, EZFS_POOL_NOTSUP, fmt, ap);
 451  454                  break;
 452  455  
 453  456          case EINVAL:
 454  457                  zfs_verror(hdl, EZFS_POOL_INVALARG, fmt, ap);
 455  458                  break;
 456  459  
 457  460          case ENOSPC:
 458  461          case EDQUOT:
 459  462                  zfs_verror(hdl, EZFS_NOSPC, fmt, ap);
 460  463                  return (-1);
 461  464  
 462  465          case EAGAIN:
 463  466                  zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
 464  467                      "pool I/O is currently suspended"));
 465  468                  zfs_verror(hdl, EZFS_POOLUNAVAIL, fmt, ap);
 466  469                  break;
 467  470  
 468  471          case EROFS:
 469  472                  zfs_verror(hdl, EZFS_POOLREADONLY, fmt, ap);
 470  473                  break;
 471  474  
 472  475          default:
 473  476                  zfs_error_aux(hdl, strerror(error));
 474  477                  zfs_verror(hdl, EZFS_UNKNOWN, fmt, ap);
 475  478          }
 476  479  
 477  480          va_end(ap);
 478  481          return (-1);
 479  482  }
 480  483  
 481  484  /*
 482  485   * Display an out of memory error message and abort the current program.
 483  486   */
 484  487  int
 485  488  no_memory(libzfs_handle_t *hdl)
 486  489  {
 487  490          return (zfs_error(hdl, EZFS_NOMEM, "internal error"));
 488  491  }
 489  492  
 490  493  /*
 491  494   * A safe form of malloc() which will die if the allocation fails.
 492  495   */
 493  496  void *
 494  497  zfs_alloc(libzfs_handle_t *hdl, size_t size)
 495  498  {
 496  499          void *data;
 497  500  
 498  501          if ((data = calloc(1, size)) == NULL)
 499  502                  (void) no_memory(hdl);
 500  503  
 501  504          return (data);
 502  505  }
 503  506  
 504  507  /*
 505  508   * A safe form of asprintf() which will die if the allocation fails.
 506  509   */
 507  510  /*PRINTFLIKE2*/
 508  511  char *
 509  512  zfs_asprintf(libzfs_handle_t *hdl, const char *fmt, ...)
 510  513  {
 511  514          va_list ap;
 512  515          char *ret;
 513  516          int err;
 514  517  
 515  518          va_start(ap, fmt);
 516  519  
 517  520          err = vasprintf(&ret, fmt, ap);
 518  521  
 519  522          va_end(ap);
 520  523  
 521  524          if (err < 0)
 522  525                  (void) no_memory(hdl);
 523  526  
 524  527          return (ret);
 525  528  }
 526  529  
 527  530  /*
 528  531   * A safe form of realloc(), which also zeroes newly allocated space.
 529  532   */
 530  533  void *
 531  534  zfs_realloc(libzfs_handle_t *hdl, void *ptr, size_t oldsize, size_t newsize)
 532  535  {
 533  536          void *ret;
 534  537  
 535  538          if ((ret = realloc(ptr, newsize)) == NULL) {
 536  539                  (void) no_memory(hdl);
 537  540                  return (NULL);
 538  541          }
 539  542  
 540  543          bzero((char *)ret + oldsize, (newsize - oldsize));
 541  544          return (ret);
 542  545  }
 543  546  
 544  547  /*
 545  548   * A safe form of strdup() which will die if the allocation fails.
 546  549   */
 547  550  char *
 548  551  zfs_strdup(libzfs_handle_t *hdl, const char *str)
 549  552  {
 550  553          char *ret;
 551  554  
 552  555          if ((ret = strdup(str)) == NULL)
 553  556                  (void) no_memory(hdl);
 554  557  
 555  558          return (ret);
 556  559  }
 557  560  
 558  561  /*
 559  562   * Convert a number to an appropriately human-readable output.
 560  563   */
 561  564  void
 562  565  zfs_nicenum(uint64_t num, char *buf, size_t buflen)
 563  566  {
 564  567          uint64_t n = num;
 565  568          int index = 0;
 566  569          char u;
 567  570  
 568  571          while (n >= 1024) {
 569  572                  n /= 1024;
 570  573                  index++;
 571  574          }
 572  575  
 573  576          u = " KMGTPE"[index];
 574  577  
 575  578          if (index == 0) {
 576  579                  (void) snprintf(buf, buflen, "%llu", n);
 577  580          } else if ((num & ((1ULL << 10 * index) - 1)) == 0) {
 578  581                  /*
 579  582                   * If this is an even multiple of the base, always display
 580  583                   * without any decimal precision.
 581  584                   */
 582  585                  (void) snprintf(buf, buflen, "%llu%c", n, u);
 583  586          } else {
 584  587                  /*
 585  588                   * We want to choose a precision that reflects the best choice
 586  589                   * for fitting in 5 characters.  This can get rather tricky when
 587  590                   * we have numbers that are very close to an order of magnitude.
 588  591                   * For example, when displaying 10239 (which is really 9.999K),
 589  592                   * we want only a single place of precision for 10.0K.  We could
 590  593                   * develop some complex heuristics for this, but it's much
 591  594                   * easier just to try each combination in turn.
 592  595                   */
 593  596                  int i;
 594  597                  for (i = 2; i >= 0; i--) {
 595  598                          if (snprintf(buf, buflen, "%.*f%c", i,
 596  599                              (double)num / (1ULL << 10 * index), u) <= 5)
 597  600                                  break;
 598  601                  }
 599  602          }
 600  603  }
 601  604  
 602  605  void
 603  606  libzfs_print_on_error(libzfs_handle_t *hdl, boolean_t printerr)
 604  607  {
 605  608          hdl->libzfs_printerr = printerr;
 606  609  }
 607  610  
 608  611  libzfs_handle_t *
 609  612  libzfs_init(void)
 610  613  {
 611  614          libzfs_handle_t *hdl;
 612  615  
 613  616          if ((hdl = calloc(1, sizeof (libzfs_handle_t))) == NULL) {
 614  617                  return (NULL);
 615  618          }
 616  619  
 617  620          if ((hdl->libzfs_fd = open(ZFS_DEV, O_RDWR)) < 0) {
 618  621                  free(hdl);
 619  622                  return (NULL);
 620  623          }
 621  624  
  
    | 
      ↓ open down ↓ | 
    496 lines elided | 
    
      ↑ open up ↑ | 
  
 622  625          if ((hdl->libzfs_mnttab = fopen(MNTTAB, "r")) == NULL) {
 623  626                  (void) close(hdl->libzfs_fd);
 624  627                  free(hdl);
 625  628                  return (NULL);
 626  629          }
 627  630  
 628  631          hdl->libzfs_sharetab = fopen("/etc/dfs/sharetab", "r");
 629  632  
 630  633          zfs_prop_init();
 631  634          zpool_prop_init();
      635 +        zpool_feature_init();
 632  636          libzfs_mnttab_init(hdl);
 633  637  
 634  638          return (hdl);
 635  639  }
 636  640  
 637  641  void
 638  642  libzfs_fini(libzfs_handle_t *hdl)
 639  643  {
 640  644          (void) close(hdl->libzfs_fd);
 641  645          if (hdl->libzfs_mnttab)
 642  646                  (void) fclose(hdl->libzfs_mnttab);
 643  647          if (hdl->libzfs_sharetab)
 644  648                  (void) fclose(hdl->libzfs_sharetab);
 645  649          zfs_uninit_libshare(hdl);
 646  650          if (hdl->libzfs_log_str)
 647  651                  (void) free(hdl->libzfs_log_str);
 648  652          zpool_free_handles(hdl);
 649  653          libzfs_fru_clear(hdl, B_TRUE);
 650  654          namespace_clear(hdl);
 651  655          libzfs_mnttab_fini(hdl);
 652  656          free(hdl);
 653  657  }
 654  658  
 655  659  libzfs_handle_t *
 656  660  zpool_get_handle(zpool_handle_t *zhp)
 657  661  {
 658  662          return (zhp->zpool_hdl);
 659  663  }
 660  664  
 661  665  libzfs_handle_t *
 662  666  zfs_get_handle(zfs_handle_t *zhp)
 663  667  {
 664  668          return (zhp->zfs_hdl);
 665  669  }
 666  670  
 667  671  zpool_handle_t *
 668  672  zfs_get_pool_handle(const zfs_handle_t *zhp)
 669  673  {
 670  674          return (zhp->zpool_hdl);
 671  675  }
 672  676  
 673  677  /*
 674  678   * Given a name, determine whether or not it's a valid path
 675  679   * (starts with '/' or "./").  If so, walk the mnttab trying
 676  680   * to match the device number.  If not, treat the path as an
 677  681   * fs/vol/snap name.
 678  682   */
 679  683  zfs_handle_t *
 680  684  zfs_path_to_zhandle(libzfs_handle_t *hdl, char *path, zfs_type_t argtype)
 681  685  {
 682  686          struct stat64 statbuf;
 683  687          struct extmnttab entry;
 684  688          int ret;
 685  689  
 686  690          if (path[0] != '/' && strncmp(path, "./", strlen("./")) != 0) {
 687  691                  /*
 688  692                   * It's not a valid path, assume it's a name of type 'argtype'.
 689  693                   */
 690  694                  return (zfs_open(hdl, path, argtype));
 691  695          }
 692  696  
 693  697          if (stat64(path, &statbuf) != 0) {
 694  698                  (void) fprintf(stderr, "%s: %s\n", path, strerror(errno));
 695  699                  return (NULL);
 696  700          }
 697  701  
 698  702          rewind(hdl->libzfs_mnttab);
 699  703          while ((ret = getextmntent(hdl->libzfs_mnttab, &entry, 0)) == 0) {
 700  704                  if (makedevice(entry.mnt_major, entry.mnt_minor) ==
 701  705                      statbuf.st_dev) {
 702  706                          break;
 703  707                  }
 704  708          }
 705  709          if (ret != 0) {
 706  710                  return (NULL);
 707  711          }
 708  712  
 709  713          if (strcmp(entry.mnt_fstype, MNTTYPE_ZFS) != 0) {
 710  714                  (void) fprintf(stderr, gettext("'%s': not a ZFS filesystem\n"),
 711  715                      path);
 712  716                  return (NULL);
 713  717          }
 714  718  
 715  719          return (zfs_open(hdl, entry.mnt_special, ZFS_TYPE_FILESYSTEM));
 716  720  }
 717  721  
 718  722  /*
 719  723   * Initialize the zc_nvlist_dst member to prepare for receiving an nvlist from
 720  724   * an ioctl().
 721  725   */
 722  726  int
 723  727  zcmd_alloc_dst_nvlist(libzfs_handle_t *hdl, zfs_cmd_t *zc, size_t len)
 724  728  {
 725  729          if (len == 0)
 726  730                  len = 16 * 1024;
 727  731          zc->zc_nvlist_dst_size = len;
 728  732          if ((zc->zc_nvlist_dst = (uint64_t)(uintptr_t)
 729  733              zfs_alloc(hdl, zc->zc_nvlist_dst_size)) == NULL)
 730  734                  return (-1);
 731  735  
 732  736          return (0);
 733  737  }
 734  738  
 735  739  /*
 736  740   * Called when an ioctl() which returns an nvlist fails with ENOMEM.  This will
 737  741   * expand the nvlist to the size specified in 'zc_nvlist_dst_size', which was
 738  742   * filled in by the kernel to indicate the actual required size.
 739  743   */
 740  744  int
 741  745  zcmd_expand_dst_nvlist(libzfs_handle_t *hdl, zfs_cmd_t *zc)
 742  746  {
 743  747          free((void *)(uintptr_t)zc->zc_nvlist_dst);
 744  748          if ((zc->zc_nvlist_dst = (uint64_t)(uintptr_t)
 745  749              zfs_alloc(hdl, zc->zc_nvlist_dst_size))
 746  750              == NULL)
 747  751                  return (-1);
 748  752  
 749  753          return (0);
 750  754  }
 751  755  
 752  756  /*
 753  757   * Called to free the src and dst nvlists stored in the command structure.
 754  758   */
 755  759  void
 756  760  zcmd_free_nvlists(zfs_cmd_t *zc)
 757  761  {
 758  762          free((void *)(uintptr_t)zc->zc_nvlist_conf);
 759  763          free((void *)(uintptr_t)zc->zc_nvlist_src);
 760  764          free((void *)(uintptr_t)zc->zc_nvlist_dst);
 761  765  }
 762  766  
 763  767  static int
 764  768  zcmd_write_nvlist_com(libzfs_handle_t *hdl, uint64_t *outnv, uint64_t *outlen,
 765  769      nvlist_t *nvl)
 766  770  {
 767  771          char *packed;
 768  772          size_t len;
 769  773  
 770  774          verify(nvlist_size(nvl, &len, NV_ENCODE_NATIVE) == 0);
 771  775  
 772  776          if ((packed = zfs_alloc(hdl, len)) == NULL)
 773  777                  return (-1);
 774  778  
 775  779          verify(nvlist_pack(nvl, &packed, &len, NV_ENCODE_NATIVE, 0) == 0);
 776  780  
 777  781          *outnv = (uint64_t)(uintptr_t)packed;
 778  782          *outlen = len;
 779  783  
 780  784          return (0);
 781  785  }
 782  786  
 783  787  int
 784  788  zcmd_write_conf_nvlist(libzfs_handle_t *hdl, zfs_cmd_t *zc, nvlist_t *nvl)
 785  789  {
 786  790          return (zcmd_write_nvlist_com(hdl, &zc->zc_nvlist_conf,
 787  791              &zc->zc_nvlist_conf_size, nvl));
 788  792  }
 789  793  
 790  794  int
 791  795  zcmd_write_src_nvlist(libzfs_handle_t *hdl, zfs_cmd_t *zc, nvlist_t *nvl)
 792  796  {
 793  797          return (zcmd_write_nvlist_com(hdl, &zc->zc_nvlist_src,
 794  798              &zc->zc_nvlist_src_size, nvl));
 795  799  }
 796  800  
 797  801  /*
 798  802   * Unpacks an nvlist from the ZFS ioctl command structure.
 799  803   */
 800  804  int
 801  805  zcmd_read_dst_nvlist(libzfs_handle_t *hdl, zfs_cmd_t *zc, nvlist_t **nvlp)
 802  806  {
 803  807          if (nvlist_unpack((void *)(uintptr_t)zc->zc_nvlist_dst,
 804  808              zc->zc_nvlist_dst_size, nvlp, 0) != 0)
 805  809                  return (no_memory(hdl));
 806  810  
 807  811          return (0);
 808  812  }
 809  813  
 810  814  int
 811  815  zfs_ioctl(libzfs_handle_t *hdl, int request, zfs_cmd_t *zc)
 812  816  {
 813  817          int error;
 814  818  
 815  819          zc->zc_history = (uint64_t)(uintptr_t)hdl->libzfs_log_str;
 816  820          error = ioctl(hdl->libzfs_fd, request, zc);
 817  821          if (hdl->libzfs_log_str) {
 818  822                  free(hdl->libzfs_log_str);
 819  823                  hdl->libzfs_log_str = NULL;
 820  824          }
 821  825          zc->zc_history = 0;
 822  826  
 823  827          return (error);
 824  828  }
 825  829  
 826  830  /*
 827  831   * ================================================================
 828  832   * API shared by zfs and zpool property management
 829  833   * ================================================================
 830  834   */
 831  835  
 832  836  static void
 833  837  zprop_print_headers(zprop_get_cbdata_t *cbp, zfs_type_t type)
 834  838  {
 835  839          zprop_list_t *pl = cbp->cb_proplist;
 836  840          int i;
 837  841          char *title;
 838  842          size_t len;
 839  843  
 840  844          cbp->cb_first = B_FALSE;
 841  845          if (cbp->cb_scripted)
 842  846                  return;
 843  847  
 844  848          /*
 845  849           * Start with the length of the column headers.
 846  850           */
 847  851          cbp->cb_colwidths[GET_COL_NAME] = strlen(dgettext(TEXT_DOMAIN, "NAME"));
 848  852          cbp->cb_colwidths[GET_COL_PROPERTY] = strlen(dgettext(TEXT_DOMAIN,
 849  853              "PROPERTY"));
 850  854          cbp->cb_colwidths[GET_COL_VALUE] = strlen(dgettext(TEXT_DOMAIN,
 851  855              "VALUE"));
 852  856          cbp->cb_colwidths[GET_COL_RECVD] = strlen(dgettext(TEXT_DOMAIN,
 853  857              "RECEIVED"));
 854  858          cbp->cb_colwidths[GET_COL_SOURCE] = strlen(dgettext(TEXT_DOMAIN,
 855  859              "SOURCE"));
 856  860  
 857  861          /* first property is always NAME */
 858  862          assert(cbp->cb_proplist->pl_prop ==
 859  863              ((type == ZFS_TYPE_POOL) ?  ZPOOL_PROP_NAME : ZFS_PROP_NAME));
 860  864  
 861  865          /*
 862  866           * Go through and calculate the widths for each column.  For the
 863  867           * 'source' column, we kludge it up by taking the worst-case scenario of
 864  868           * inheriting from the longest name.  This is acceptable because in the
 865  869           * majority of cases 'SOURCE' is the last column displayed, and we don't
 866  870           * use the width anyway.  Note that the 'VALUE' column can be oversized,
 867  871           * if the name of the property is much longer than any values we find.
 868  872           */
 869  873          for (pl = cbp->cb_proplist; pl != NULL; pl = pl->pl_next) {
 870  874                  /*
 871  875                   * 'PROPERTY' column
 872  876                   */
 873  877                  if (pl->pl_prop != ZPROP_INVAL) {
 874  878                          const char *propname = (type == ZFS_TYPE_POOL) ?
 875  879                              zpool_prop_to_name(pl->pl_prop) :
 876  880                              zfs_prop_to_name(pl->pl_prop);
 877  881  
 878  882                          len = strlen(propname);
 879  883                          if (len > cbp->cb_colwidths[GET_COL_PROPERTY])
 880  884                                  cbp->cb_colwidths[GET_COL_PROPERTY] = len;
 881  885                  } else {
 882  886                          len = strlen(pl->pl_user_prop);
 883  887                          if (len > cbp->cb_colwidths[GET_COL_PROPERTY])
 884  888                                  cbp->cb_colwidths[GET_COL_PROPERTY] = len;
 885  889                  }
 886  890  
 887  891                  /*
 888  892                   * 'VALUE' column.  The first property is always the 'name'
 889  893                   * property that was tacked on either by /sbin/zfs's
 890  894                   * zfs_do_get() or when calling zprop_expand_list(), so we
 891  895                   * ignore its width.  If the user specified the name property
 892  896                   * to display, then it will be later in the list in any case.
 893  897                   */
 894  898                  if (pl != cbp->cb_proplist &&
 895  899                      pl->pl_width > cbp->cb_colwidths[GET_COL_VALUE])
 896  900                          cbp->cb_colwidths[GET_COL_VALUE] = pl->pl_width;
 897  901  
 898  902                  /* 'RECEIVED' column. */
 899  903                  if (pl != cbp->cb_proplist &&
 900  904                      pl->pl_recvd_width > cbp->cb_colwidths[GET_COL_RECVD])
 901  905                          cbp->cb_colwidths[GET_COL_RECVD] = pl->pl_recvd_width;
 902  906  
 903  907                  /*
 904  908                   * 'NAME' and 'SOURCE' columns
 905  909                   */
 906  910                  if (pl->pl_prop == (type == ZFS_TYPE_POOL ? ZPOOL_PROP_NAME :
 907  911                      ZFS_PROP_NAME) &&
 908  912                      pl->pl_width > cbp->cb_colwidths[GET_COL_NAME]) {
 909  913                          cbp->cb_colwidths[GET_COL_NAME] = pl->pl_width;
 910  914                          cbp->cb_colwidths[GET_COL_SOURCE] = pl->pl_width +
 911  915                              strlen(dgettext(TEXT_DOMAIN, "inherited from"));
 912  916                  }
 913  917          }
 914  918  
 915  919          /*
 916  920           * Now go through and print the headers.
 917  921           */
 918  922          for (i = 0; i < ZFS_GET_NCOLS; i++) {
 919  923                  switch (cbp->cb_columns[i]) {
 920  924                  case GET_COL_NAME:
 921  925                          title = dgettext(TEXT_DOMAIN, "NAME");
 922  926                          break;
 923  927                  case GET_COL_PROPERTY:
 924  928                          title = dgettext(TEXT_DOMAIN, "PROPERTY");
 925  929                          break;
 926  930                  case GET_COL_VALUE:
 927  931                          title = dgettext(TEXT_DOMAIN, "VALUE");
 928  932                          break;
 929  933                  case GET_COL_RECVD:
 930  934                          title = dgettext(TEXT_DOMAIN, "RECEIVED");
 931  935                          break;
 932  936                  case GET_COL_SOURCE:
 933  937                          title = dgettext(TEXT_DOMAIN, "SOURCE");
 934  938                          break;
 935  939                  default:
 936  940                          title = NULL;
 937  941                  }
 938  942  
 939  943                  if (title != NULL) {
 940  944                          if (i == (ZFS_GET_NCOLS - 1) ||
 941  945                              cbp->cb_columns[i + 1] == GET_COL_NONE)
 942  946                                  (void) printf("%s", title);
 943  947                          else
 944  948                                  (void) printf("%-*s  ",
 945  949                                      cbp->cb_colwidths[cbp->cb_columns[i]],
 946  950                                      title);
 947  951                  }
 948  952          }
 949  953          (void) printf("\n");
 950  954  }
 951  955  
 952  956  /*
 953  957   * Display a single line of output, according to the settings in the callback
 954  958   * structure.
 955  959   */
 956  960  void
 957  961  zprop_print_one_property(const char *name, zprop_get_cbdata_t *cbp,
 958  962      const char *propname, const char *value, zprop_source_t sourcetype,
 959  963      const char *source, const char *recvd_value)
 960  964  {
 961  965          int i;
 962  966          const char *str;
 963  967          char buf[128];
 964  968  
 965  969          /*
 966  970           * Ignore those source types that the user has chosen to ignore.
 967  971           */
 968  972          if ((sourcetype & cbp->cb_sources) == 0)
 969  973                  return;
 970  974  
 971  975          if (cbp->cb_first)
 972  976                  zprop_print_headers(cbp, cbp->cb_type);
 973  977  
 974  978          for (i = 0; i < ZFS_GET_NCOLS; i++) {
 975  979                  switch (cbp->cb_columns[i]) {
 976  980                  case GET_COL_NAME:
 977  981                          str = name;
 978  982                          break;
 979  983  
 980  984                  case GET_COL_PROPERTY:
 981  985                          str = propname;
 982  986                          break;
 983  987  
 984  988                  case GET_COL_VALUE:
 985  989                          str = value;
 986  990                          break;
 987  991  
 988  992                  case GET_COL_SOURCE:
 989  993                          switch (sourcetype) {
 990  994                          case ZPROP_SRC_NONE:
 991  995                                  str = "-";
 992  996                                  break;
 993  997  
 994  998                          case ZPROP_SRC_DEFAULT:
 995  999                                  str = "default";
 996 1000                                  break;
 997 1001  
 998 1002                          case ZPROP_SRC_LOCAL:
 999 1003                                  str = "local";
1000 1004                                  break;
1001 1005  
1002 1006                          case ZPROP_SRC_TEMPORARY:
1003 1007                                  str = "temporary";
1004 1008                                  break;
1005 1009  
1006 1010                          case ZPROP_SRC_INHERITED:
1007 1011                                  (void) snprintf(buf, sizeof (buf),
1008 1012                                      "inherited from %s", source);
1009 1013                                  str = buf;
1010 1014                                  break;
1011 1015                          case ZPROP_SRC_RECEIVED:
1012 1016                                  str = "received";
1013 1017                                  break;
1014 1018                          }
1015 1019                          break;
1016 1020  
1017 1021                  case GET_COL_RECVD:
1018 1022                          str = (recvd_value == NULL ? "-" : recvd_value);
1019 1023                          break;
1020 1024  
1021 1025                  default:
1022 1026                          continue;
1023 1027                  }
1024 1028  
1025 1029                  if (cbp->cb_columns[i + 1] == GET_COL_NONE)
1026 1030                          (void) printf("%s", str);
1027 1031                  else if (cbp->cb_scripted)
1028 1032                          (void) printf("%s\t", str);
1029 1033                  else
1030 1034                          (void) printf("%-*s  ",
1031 1035                              cbp->cb_colwidths[cbp->cb_columns[i]],
1032 1036                              str);
1033 1037          }
1034 1038  
1035 1039          (void) printf("\n");
1036 1040  }
1037 1041  
1038 1042  /*
1039 1043   * Given a numeric suffix, convert the value into a number of bits that the
1040 1044   * resulting value must be shifted.
1041 1045   */
1042 1046  static int
1043 1047  str2shift(libzfs_handle_t *hdl, const char *buf)
1044 1048  {
1045 1049          const char *ends = "BKMGTPEZ";
1046 1050          int i;
1047 1051  
1048 1052          if (buf[0] == '\0')
1049 1053                  return (0);
1050 1054          for (i = 0; i < strlen(ends); i++) {
1051 1055                  if (toupper(buf[0]) == ends[i])
1052 1056                          break;
1053 1057          }
1054 1058          if (i == strlen(ends)) {
1055 1059                  zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1056 1060                      "invalid numeric suffix '%s'"), buf);
1057 1061                  return (-1);
1058 1062          }
1059 1063  
1060 1064          /*
1061 1065           * We want to allow trailing 'b' characters for 'GB' or 'Mb'.  But don't
1062 1066           * allow 'BB' - that's just weird.
1063 1067           */
1064 1068          if (buf[1] == '\0' || (toupper(buf[1]) == 'B' && buf[2] == '\0' &&
1065 1069              toupper(buf[0]) != 'B'))
1066 1070                  return (10*i);
1067 1071  
1068 1072          zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1069 1073              "invalid numeric suffix '%s'"), buf);
1070 1074          return (-1);
1071 1075  }
1072 1076  
1073 1077  /*
1074 1078   * Convert a string of the form '100G' into a real number.  Used when setting
1075 1079   * properties or creating a volume.  'buf' is used to place an extended error
1076 1080   * message for the caller to use.
1077 1081   */
1078 1082  int
1079 1083  zfs_nicestrtonum(libzfs_handle_t *hdl, const char *value, uint64_t *num)
1080 1084  {
1081 1085          char *end;
1082 1086          int shift;
1083 1087  
1084 1088          *num = 0;
1085 1089  
1086 1090          /* Check to see if this looks like a number.  */
1087 1091          if ((value[0] < '0' || value[0] > '9') && value[0] != '.') {
1088 1092                  if (hdl)
1089 1093                          zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1090 1094                              "bad numeric value '%s'"), value);
1091 1095                  return (-1);
1092 1096          }
1093 1097  
1094 1098          /* Rely on strtoull() to process the numeric portion.  */
1095 1099          errno = 0;
1096 1100          *num = strtoull(value, &end, 10);
1097 1101  
1098 1102          /*
1099 1103           * Check for ERANGE, which indicates that the value is too large to fit
1100 1104           * in a 64-bit value.
1101 1105           */
1102 1106          if (errno == ERANGE) {
1103 1107                  if (hdl)
1104 1108                          zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1105 1109                              "numeric value is too large"));
1106 1110                  return (-1);
1107 1111          }
1108 1112  
1109 1113          /*
1110 1114           * If we have a decimal value, then do the computation with floating
1111 1115           * point arithmetic.  Otherwise, use standard arithmetic.
1112 1116           */
1113 1117          if (*end == '.') {
1114 1118                  double fval = strtod(value, &end);
1115 1119  
1116 1120                  if ((shift = str2shift(hdl, end)) == -1)
1117 1121                          return (-1);
1118 1122  
1119 1123                  fval *= pow(2, shift);
1120 1124  
1121 1125                  if (fval > UINT64_MAX) {
1122 1126                          if (hdl)
1123 1127                                  zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1124 1128                                      "numeric value is too large"));
1125 1129                          return (-1);
1126 1130                  }
1127 1131  
1128 1132                  *num = (uint64_t)fval;
1129 1133          } else {
1130 1134                  if ((shift = str2shift(hdl, end)) == -1)
1131 1135                          return (-1);
1132 1136  
1133 1137                  /* Check for overflow */
1134 1138                  if (shift >= 64 || (*num << shift) >> shift != *num) {
1135 1139                          if (hdl)
1136 1140                                  zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1137 1141                                      "numeric value is too large"));
1138 1142                          return (-1);
1139 1143                  }
1140 1144  
1141 1145                  *num <<= shift;
1142 1146          }
1143 1147  
1144 1148          return (0);
1145 1149  }
1146 1150  
1147 1151  /*
1148 1152   * Given a propname=value nvpair to set, parse any numeric properties
1149 1153   * (index, boolean, etc) if they are specified as strings and add the
1150 1154   * resulting nvpair to the returned nvlist.
1151 1155   *
1152 1156   * At the DSL layer, all properties are either 64-bit numbers or strings.
1153 1157   * We want the user to be able to ignore this fact and specify properties
1154 1158   * as native values (numbers, for example) or as strings (to simplify
1155 1159   * command line utilities).  This also handles converting index types
1156 1160   * (compression, checksum, etc) from strings to their on-disk index.
1157 1161   */
1158 1162  int
1159 1163  zprop_parse_value(libzfs_handle_t *hdl, nvpair_t *elem, int prop,
1160 1164      zfs_type_t type, nvlist_t *ret, char **svalp, uint64_t *ivalp,
1161 1165      const char *errbuf)
1162 1166  {
1163 1167          data_type_t datatype = nvpair_type(elem);
1164 1168          zprop_type_t proptype;
1165 1169          const char *propname;
1166 1170          char *value;
1167 1171          boolean_t isnone = B_FALSE;
1168 1172  
1169 1173          if (type == ZFS_TYPE_POOL) {
1170 1174                  proptype = zpool_prop_get_type(prop);
1171 1175                  propname = zpool_prop_to_name(prop);
1172 1176          } else {
1173 1177                  proptype = zfs_prop_get_type(prop);
1174 1178                  propname = zfs_prop_to_name(prop);
1175 1179          }
1176 1180  
1177 1181          /*
1178 1182           * Convert any properties to the internal DSL value types.
1179 1183           */
1180 1184          *svalp = NULL;
1181 1185          *ivalp = 0;
1182 1186  
1183 1187          switch (proptype) {
1184 1188          case PROP_TYPE_STRING:
1185 1189                  if (datatype != DATA_TYPE_STRING) {
1186 1190                          zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1187 1191                              "'%s' must be a string"), nvpair_name(elem));
1188 1192                          goto error;
1189 1193                  }
1190 1194                  (void) nvpair_value_string(elem, svalp);
1191 1195                  if (strlen(*svalp) >= ZFS_MAXPROPLEN) {
1192 1196                          zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1193 1197                              "'%s' is too long"), nvpair_name(elem));
1194 1198                          goto error;
1195 1199                  }
1196 1200                  break;
1197 1201  
1198 1202          case PROP_TYPE_NUMBER:
1199 1203                  if (datatype == DATA_TYPE_STRING) {
1200 1204                          (void) nvpair_value_string(elem, &value);
1201 1205                          if (strcmp(value, "none") == 0) {
1202 1206                                  isnone = B_TRUE;
1203 1207                          } else if (zfs_nicestrtonum(hdl, value, ivalp)
1204 1208                              != 0) {
1205 1209                                  goto error;
1206 1210                          }
1207 1211                  } else if (datatype == DATA_TYPE_UINT64) {
1208 1212                          (void) nvpair_value_uint64(elem, ivalp);
1209 1213                  } else {
1210 1214                          zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1211 1215                              "'%s' must be a number"), nvpair_name(elem));
1212 1216                          goto error;
1213 1217                  }
1214 1218  
1215 1219                  /*
1216 1220                   * Quota special: force 'none' and don't allow 0.
1217 1221                   */
1218 1222                  if ((type & ZFS_TYPE_DATASET) && *ivalp == 0 && !isnone &&
1219 1223                      (prop == ZFS_PROP_QUOTA || prop == ZFS_PROP_REFQUOTA)) {
1220 1224                          zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1221 1225                              "use 'none' to disable quota/refquota"));
1222 1226                          goto error;
1223 1227                  }
1224 1228                  break;
1225 1229  
1226 1230          case PROP_TYPE_INDEX:
1227 1231                  if (datatype != DATA_TYPE_STRING) {
1228 1232                          zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1229 1233                              "'%s' must be a string"), nvpair_name(elem));
1230 1234                          goto error;
1231 1235                  }
1232 1236  
1233 1237                  (void) nvpair_value_string(elem, &value);
1234 1238  
1235 1239                  if (zprop_string_to_index(prop, value, ivalp, type) != 0) {
1236 1240                          zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1237 1241                              "'%s' must be one of '%s'"), propname,
1238 1242                              zprop_values(prop, type));
1239 1243                          goto error;
1240 1244                  }
1241 1245                  break;
1242 1246  
1243 1247          default:
1244 1248                  abort();
1245 1249          }
1246 1250  
1247 1251          /*
1248 1252           * Add the result to our return set of properties.
1249 1253           */
1250 1254          if (*svalp != NULL) {
1251 1255                  if (nvlist_add_string(ret, propname, *svalp) != 0) {
1252 1256                          (void) no_memory(hdl);
1253 1257                          return (-1);
1254 1258                  }
1255 1259          } else {
1256 1260                  if (nvlist_add_uint64(ret, propname, *ivalp) != 0) {
1257 1261                          (void) no_memory(hdl);
1258 1262                          return (-1);
1259 1263                  }
1260 1264          }
1261 1265  
1262 1266          return (0);
1263 1267  error:
1264 1268          (void) zfs_error(hdl, EZFS_BADPROP, errbuf);
1265 1269          return (-1);
1266 1270  }
1267 1271  
1268 1272  static int
1269 1273  addlist(libzfs_handle_t *hdl, char *propname, zprop_list_t **listp,
1270 1274      zfs_type_t type)
1271 1275  {
1272 1276          int prop;
1273 1277          zprop_list_t *entry;
1274 1278  
  
    | 
      ↓ open down ↓ | 
    633 lines elided | 
    
      ↑ open up ↑ | 
  
1275 1279          prop = zprop_name_to_prop(propname, type);
1276 1280  
1277 1281          if (prop != ZPROP_INVAL && !zprop_valid_for_type(prop, type))
1278 1282                  prop = ZPROP_INVAL;
1279 1283  
1280 1284          /*
1281 1285           * When no property table entry can be found, return failure if
1282 1286           * this is a pool property or if this isn't a user-defined
1283 1287           * dataset property,
1284 1288           */
1285      -        if (prop == ZPROP_INVAL && (type == ZFS_TYPE_POOL ||
1286      -            (!zfs_prop_user(propname) && !zfs_prop_userquota(propname) &&
1287      -            !zfs_prop_written(propname)))) {
     1289 +        if (prop == ZPROP_INVAL && ((type == ZFS_TYPE_POOL &&
     1290 +            !zpool_prop_feature(propname) &&
     1291 +            !zpool_prop_unsupported(propname)) ||
     1292 +            (type == ZFS_TYPE_DATASET && !zfs_prop_user(propname) &&
     1293 +            !zfs_prop_userquota(propname) && !zfs_prop_written(propname)))) {
1288 1294                  zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1289 1295                      "invalid property '%s'"), propname);
1290 1296                  return (zfs_error(hdl, EZFS_BADPROP,
1291 1297                      dgettext(TEXT_DOMAIN, "bad property list")));
1292 1298          }
1293 1299  
1294 1300          if ((entry = zfs_alloc(hdl, sizeof (zprop_list_t))) == NULL)
1295 1301                  return (-1);
1296 1302  
1297 1303          entry->pl_prop = prop;
1298 1304          if (prop == ZPROP_INVAL) {
1299      -                if ((entry->pl_user_prop = zfs_strdup(hdl, propname)) == NULL) {
     1305 +                if ((entry->pl_user_prop = zfs_strdup(hdl, propname)) ==
     1306 +                    NULL) {
1300 1307                          free(entry);
1301 1308                          return (-1);
1302 1309                  }
1303 1310                  entry->pl_width = strlen(propname);
1304 1311          } else {
1305 1312                  entry->pl_width = zprop_width(prop, &entry->pl_fixed,
1306 1313                      type);
1307 1314          }
1308 1315  
1309 1316          *listp = entry;
1310 1317  
1311 1318          return (0);
1312 1319  }
1313 1320  
1314 1321  /*
1315 1322   * Given a comma-separated list of properties, construct a property list
1316 1323   * containing both user-defined and native properties.  This function will
1317 1324   * return a NULL list if 'all' is specified, which can later be expanded
1318 1325   * by zprop_expand_list().
1319 1326   */
1320 1327  int
1321 1328  zprop_get_list(libzfs_handle_t *hdl, char *props, zprop_list_t **listp,
1322 1329      zfs_type_t type)
1323 1330  {
1324 1331          *listp = NULL;
1325 1332  
1326 1333          /*
1327 1334           * If 'all' is specified, return a NULL list.
1328 1335           */
1329 1336          if (strcmp(props, "all") == 0)
1330 1337                  return (0);
1331 1338  
1332 1339          /*
1333 1340           * If no props were specified, return an error.
1334 1341           */
1335 1342          if (props[0] == '\0') {
1336 1343                  zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1337 1344                      "no properties specified"));
1338 1345                  return (zfs_error(hdl, EZFS_BADPROP, dgettext(TEXT_DOMAIN,
1339 1346                      "bad property list")));
1340 1347          }
1341 1348  
1342 1349          /*
1343 1350           * It would be nice to use getsubopt() here, but the inclusion of column
1344 1351           * aliases makes this more effort than it's worth.
1345 1352           */
1346 1353          while (*props != '\0') {
1347 1354                  size_t len;
1348 1355                  char *p;
1349 1356                  char c;
1350 1357  
1351 1358                  if ((p = strchr(props, ',')) == NULL) {
1352 1359                          len = strlen(props);
1353 1360                          p = props + len;
1354 1361                  } else {
1355 1362                          len = p - props;
1356 1363                  }
1357 1364  
1358 1365                  /*
1359 1366                   * Check for empty options.
1360 1367                   */
1361 1368                  if (len == 0) {
1362 1369                          zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1363 1370                              "empty property name"));
1364 1371                          return (zfs_error(hdl, EZFS_BADPROP,
1365 1372                              dgettext(TEXT_DOMAIN, "bad property list")));
1366 1373                  }
1367 1374  
1368 1375                  /*
1369 1376                   * Check all regular property names.
1370 1377                   */
1371 1378                  c = props[len];
1372 1379                  props[len] = '\0';
1373 1380  
1374 1381                  if (strcmp(props, "space") == 0) {
1375 1382                          static char *spaceprops[] = {
1376 1383                                  "name", "avail", "used", "usedbysnapshots",
1377 1384                                  "usedbydataset", "usedbyrefreservation",
1378 1385                                  "usedbychildren", NULL
1379 1386                          };
1380 1387                          int i;
1381 1388  
1382 1389                          for (i = 0; spaceprops[i]; i++) {
1383 1390                                  if (addlist(hdl, spaceprops[i], listp, type))
1384 1391                                          return (-1);
1385 1392                                  listp = &(*listp)->pl_next;
1386 1393                          }
1387 1394                  } else {
1388 1395                          if (addlist(hdl, props, listp, type))
1389 1396                                  return (-1);
1390 1397                          listp = &(*listp)->pl_next;
1391 1398                  }
1392 1399  
1393 1400                  props = p;
1394 1401                  if (c == ',')
1395 1402                          props++;
1396 1403          }
1397 1404  
1398 1405          return (0);
1399 1406  }
1400 1407  
1401 1408  void
1402 1409  zprop_free_list(zprop_list_t *pl)
1403 1410  {
1404 1411          zprop_list_t *next;
1405 1412  
1406 1413          while (pl != NULL) {
1407 1414                  next = pl->pl_next;
1408 1415                  free(pl->pl_user_prop);
1409 1416                  free(pl);
1410 1417                  pl = next;
1411 1418          }
1412 1419  }
1413 1420  
1414 1421  typedef struct expand_data {
1415 1422          zprop_list_t    **last;
1416 1423          libzfs_handle_t *hdl;
1417 1424          zfs_type_t type;
1418 1425  } expand_data_t;
1419 1426  
1420 1427  int
1421 1428  zprop_expand_list_cb(int prop, void *cb)
1422 1429  {
1423 1430          zprop_list_t *entry;
1424 1431          expand_data_t *edp = cb;
1425 1432  
1426 1433          if ((entry = zfs_alloc(edp->hdl, sizeof (zprop_list_t))) == NULL)
1427 1434                  return (ZPROP_INVAL);
1428 1435  
1429 1436          entry->pl_prop = prop;
1430 1437          entry->pl_width = zprop_width(prop, &entry->pl_fixed, edp->type);
1431 1438          entry->pl_all = B_TRUE;
1432 1439  
1433 1440          *(edp->last) = entry;
1434 1441          edp->last = &entry->pl_next;
1435 1442  
1436 1443          return (ZPROP_CONT);
1437 1444  }
1438 1445  
1439 1446  int
1440 1447  zprop_expand_list(libzfs_handle_t *hdl, zprop_list_t **plp, zfs_type_t type)
1441 1448  {
1442 1449          zprop_list_t *entry;
1443 1450          zprop_list_t **last;
1444 1451          expand_data_t exp;
1445 1452  
1446 1453          if (*plp == NULL) {
1447 1454                  /*
1448 1455                   * If this is the very first time we've been called for an 'all'
1449 1456                   * specification, expand the list to include all native
1450 1457                   * properties.
1451 1458                   */
1452 1459                  last = plp;
1453 1460  
1454 1461                  exp.last = last;
1455 1462                  exp.hdl = hdl;
1456 1463                  exp.type = type;
1457 1464  
1458 1465                  if (zprop_iter_common(zprop_expand_list_cb, &exp, B_FALSE,
1459 1466                      B_FALSE, type) == ZPROP_INVAL)
1460 1467                          return (-1);
1461 1468  
1462 1469                  /*
1463 1470                   * Add 'name' to the beginning of the list, which is handled
1464 1471                   * specially.
1465 1472                   */
1466 1473                  if ((entry = zfs_alloc(hdl, sizeof (zprop_list_t))) == NULL)
1467 1474                          return (-1);
1468 1475  
1469 1476                  entry->pl_prop = (type == ZFS_TYPE_POOL) ?  ZPOOL_PROP_NAME :
1470 1477                      ZFS_PROP_NAME;
1471 1478                  entry->pl_width = zprop_width(entry->pl_prop,
1472 1479                      &entry->pl_fixed, type);
1473 1480                  entry->pl_all = B_TRUE;
1474 1481                  entry->pl_next = *plp;
1475 1482                  *plp = entry;
1476 1483          }
1477 1484          return (0);
1478 1485  }
1479 1486  
1480 1487  int
1481 1488  zprop_iter(zprop_func func, void *cb, boolean_t show_all, boolean_t ordered,
1482 1489      zfs_type_t type)
1483 1490  {
1484 1491          return (zprop_iter_common(func, cb, show_all, ordered, type));
1485 1492  }
  
    | 
      ↓ open down ↓ | 
    176 lines elided | 
    
      ↑ open up ↑ | 
  
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX