Print this page
2882 implement libzfs_core
2883 changing "canmount" property to "on" should not always remount dataset
2900 "zfs snapshot" should be able to create multiple, arbitrary snapshots at once
Reviewed by: George Wilson <george.wilson@delphix.com>
Reviewed by: Chris Siden <christopher.siden@delphix.com>
Reviewed by: Garrett D'Amore <garrett@damore.org>
Reviewed by: Bill Pijewski <wdp@joyent.com>
Reviewed by: Dan Kruchinin <dan.kruchinin@gmail.com>

Split Close
Expand all
Collapse all
          --- old/usr/src/cmd/zpool/zpool_main.c
          +++ new/usr/src/cmd/zpool/zpool_main.c
↓ open down ↓ 177 lines elided ↑ open up ↑
 178  178          { "upgrade",    zpool_do_upgrade,       HELP_UPGRADE            },
 179  179          { "reguid",     zpool_do_reguid,        HELP_REGUID             },
 180  180          { NULL },
 181  181          { "history",    zpool_do_history,       HELP_HISTORY            },
 182  182          { "get",        zpool_do_get,           HELP_GET                },
 183  183          { "set",        zpool_do_set,           HELP_SET                },
 184  184  };
 185  185  
 186  186  #define NCOMMAND        (sizeof (command_table) / sizeof (command_table[0]))
 187  187  
 188      -zpool_command_t *current_command;
      188 +static zpool_command_t *current_command;
 189  189  static char history_str[HIS_MAX_RECORD_LEN];
 190      -
      190 +static boolean_t log_history = B_TRUE;
 191  191  static uint_t timestamp_fmt = NODATE;
 192  192  
 193  193  static const char *
 194  194  get_usage(zpool_help_t idx) {
 195  195          switch (idx) {
 196  196          case HELP_ADD:
 197  197                  return (gettext("\tadd [-fn] <pool> <vdev> ...\n"));
 198  198          case HELP_ATTACH:
 199  199                  return (gettext("\tattach [-f] <pool> <device> "
 200  200                      "<new-device>\n"));
↓ open down ↓ 727 lines elided ↑ open up ↑
 928  928                              "destroy a dataset\n"));
 929  929                  return (1);
 930  930          }
 931  931  
 932  932          if (zpool_disable_datasets(zhp, force) != 0) {
 933  933                  (void) fprintf(stderr, gettext("could not destroy '%s': "
 934  934                      "could not unmount datasets\n"), zpool_get_name(zhp));
 935  935                  return (1);
 936  936          }
 937  937  
 938      -        ret = (zpool_destroy(zhp) != 0);
      938 +        /* The history must be logged as part of the export */
      939 +        log_history = B_FALSE;
      940 +
      941 +        ret = (zpool_destroy(zhp, history_str) != 0);
 939  942  
 940  943          zpool_close(zhp);
 941  944  
 942  945          return (ret);
 943  946  }
 944  947  
 945  948  /*
 946  949   * zpool export [-f] <pool> ...
 947  950   *
 948  951   *      -f      Forcefully unmount datasets
↓ open down ↓ 43 lines elided ↑ open up ↑
 992  995                          ret = 1;
 993  996                          continue;
 994  997                  }
 995  998  
 996  999                  if (zpool_disable_datasets(zhp, force) != 0) {
 997 1000                          ret = 1;
 998 1001                          zpool_close(zhp);
 999 1002                          continue;
1000 1003                  }
1001 1004  
     1005 +                /* The history must be logged as part of the export */
     1006 +                log_history = B_FALSE;
     1007 +
1002 1008                  if (hardforce) {
1003      -                        if (zpool_export_force(zhp) != 0)
     1009 +                        if (zpool_export_force(zhp, history_str) != 0)
1004 1010                                  ret = 1;
1005      -                } else if (zpool_export(zhp, force) != 0) {
     1011 +                } else if (zpool_export(zhp, force, history_str) != 0) {
1006 1012                          ret = 1;
1007 1013                  }
1008 1014  
1009 1015                  zpool_close(zhp);
1010 1016          }
1011 1017  
1012 1018          return (ret);
1013 1019  }
1014 1020  
1015 1021  /*
↓ open down ↓ 3246 lines elided ↑ open up ↑
4262 4268  
4263 4269                          (void) printf("%2llu   %s\n", (u_longlong_t)version,
4264 4270                              zpool_get_name(zhp));
4265 4271                  } else {
4266 4272                          cbp->cb_first = B_FALSE;
4267 4273                          ret = zpool_upgrade(zhp, cbp->cb_version);
4268 4274                          if (!ret) {
4269 4275                                  (void) printf(gettext("Successfully upgraded "
4270 4276                                      "'%s'\n\n"), zpool_get_name(zhp));
4271 4277                          }
     4278 +                        /*
     4279 +                         * If they did "zpool upgrade -a", then we could
     4280 +                         * be doing ioctls to different pools.  We need
     4281 +                         * to log this history once to each pool, and bypass
     4282 +                         * the normal history logging that happens in main().
     4283 +                         */
     4284 +                        (void) zpool_log_history(g_zfs, history_str);
     4285 +                        log_history = B_FALSE;
4272 4286                  }
4273 4287          } else if (cbp->cb_newer && !SPA_VERSION_IS_SUPPORTED(version)) {
4274 4288                  assert(!cbp->cb_all);
4275 4289  
4276 4290                  if (cbp->cb_first) {
4277 4291                          (void) printf(gettext("The following pools are "
4278 4292                              "formatted using an unsupported software version "
4279 4293                              "and\ncannot be accessed on the current "
4280 4294                              "system.\n\n"));
4281 4295                          (void) printf(gettext("VER  POOL\n"));
↓ open down ↓ 202 lines elided ↑ open up ↑
4484 4498          } else {
4485 4499                  ret = for_each_pool(argc, argv, B_FALSE, NULL,
4486 4500                      upgrade_one, &cb);
4487 4501          }
4488 4502  
4489 4503          return (ret);
4490 4504  }
4491 4505  
4492 4506  typedef struct hist_cbdata {
4493 4507          boolean_t first;
4494      -        int longfmt;
4495      -        int internal;
     4508 +        boolean_t longfmt;
     4509 +        boolean_t internal;
4496 4510  } hist_cbdata_t;
4497 4511  
4498 4512  /*
4499 4513   * Print out the command history for a specific pool.
4500 4514   */
4501 4515  static int
4502 4516  get_history_one(zpool_handle_t *zhp, void *data)
4503 4517  {
4504 4518          nvlist_t *nvhis;
4505 4519          nvlist_t **records;
4506 4520          uint_t numrecords;
4507      -        char *cmdstr;
4508      -        char *pathstr;
4509      -        uint64_t dst_time;
4510      -        time_t tsec;
4511      -        struct tm t;
4512      -        char tbuf[30];
4513 4521          int ret, i;
4514      -        uint64_t who;
4515      -        struct passwd *pwd;
4516      -        char *hostname;
4517      -        char *zonename;
4518      -        char internalstr[MAXPATHLEN];
4519 4522          hist_cbdata_t *cb = (hist_cbdata_t *)data;
4520      -        uint64_t txg;
4521      -        uint64_t ievent;
4522 4523  
4523 4524          cb->first = B_FALSE;
4524 4525  
4525 4526          (void) printf(gettext("History for '%s':\n"), zpool_get_name(zhp));
4526 4527  
4527 4528          if ((ret = zpool_get_history(zhp, &nvhis)) != 0)
4528 4529                  return (ret);
4529 4530  
4530 4531          verify(nvlist_lookup_nvlist_array(nvhis, ZPOOL_HIST_RECORD,
4531 4532              &records, &numrecords) == 0);
4532 4533          for (i = 0; i < numrecords; i++) {
4533      -                if (nvlist_lookup_uint64(records[i], ZPOOL_HIST_TIME,
4534      -                    &dst_time) != 0)
4535      -                        continue;
     4534 +                nvlist_t *rec = records[i];
     4535 +                char tbuf[30] = "";
4536 4536  
4537      -                /* is it an internal event or a standard event? */
4538      -                if (nvlist_lookup_string(records[i], ZPOOL_HIST_CMD,
4539      -                    &cmdstr) != 0) {
4540      -                        if (cb->internal == 0)
     4537 +                if (nvlist_exists(rec, ZPOOL_HIST_TIME)) {
     4538 +                        time_t tsec;
     4539 +                        struct tm t;
     4540 +
     4541 +                        tsec = fnvlist_lookup_uint64(records[i],
     4542 +                            ZPOOL_HIST_TIME);
     4543 +                        (void) localtime_r(&tsec, &t);
     4544 +                        (void) strftime(tbuf, sizeof (tbuf), "%F.%T", &t);
     4545 +                }
     4546 +
     4547 +                if (nvlist_exists(rec, ZPOOL_HIST_CMD)) {
     4548 +                        (void) printf("%s %s", tbuf,
     4549 +                            fnvlist_lookup_string(rec, ZPOOL_HIST_CMD));
     4550 +                } else if (nvlist_exists(rec, ZPOOL_HIST_INT_EVENT)) {
     4551 +                        int ievent =
     4552 +                            fnvlist_lookup_uint64(rec, ZPOOL_HIST_INT_EVENT);
     4553 +                        if (!cb->internal)
4541 4554                                  continue;
4542      -
4543      -                        if (nvlist_lookup_uint64(records[i],
4544      -                            ZPOOL_HIST_INT_EVENT, &ievent) != 0)
     4555 +                        if (ievent >= ZFS_NUM_LEGACY_HISTORY_EVENTS) {
     4556 +                                (void) printf("%s unrecognized record:\n",
     4557 +                                    tbuf);
     4558 +                                dump_nvlist(rec, 4);
     4559 +                                continue;
     4560 +                        }
     4561 +                        (void) printf("%s [internal %s txg:%lld] %s", tbuf,
     4562 +                            zfs_history_event_names[ievent],
     4563 +                            fnvlist_lookup_uint64(rec, ZPOOL_HIST_TXG),
     4564 +                            fnvlist_lookup_string(rec, ZPOOL_HIST_INT_STR));
     4565 +                } else if (nvlist_exists(rec, ZPOOL_HIST_INT_NAME)) {
     4566 +                        if (!cb->internal)
4545 4567                                  continue;
4546      -                        verify(nvlist_lookup_uint64(records[i],
4547      -                            ZPOOL_HIST_TXG, &txg) == 0);
4548      -                        verify(nvlist_lookup_string(records[i],
4549      -                            ZPOOL_HIST_INT_STR, &pathstr) == 0);
4550      -                        if (ievent >= LOG_END)
     4568 +                        (void) printf("%s [txg:%lld] %s", tbuf,
     4569 +                            fnvlist_lookup_uint64(rec, ZPOOL_HIST_TXG),
     4570 +                            fnvlist_lookup_string(rec, ZPOOL_HIST_INT_NAME));
     4571 +                        if (nvlist_exists(rec, ZPOOL_HIST_DSNAME)) {
     4572 +                                (void) printf(" %s (%llu)",
     4573 +                                    fnvlist_lookup_string(rec,
     4574 +                                    ZPOOL_HIST_DSNAME),
     4575 +                                    fnvlist_lookup_uint64(rec,
     4576 +                                    ZPOOL_HIST_DSID));
     4577 +                        }
     4578 +                        (void) printf(" %s", fnvlist_lookup_string(rec,
     4579 +                            ZPOOL_HIST_INT_STR));
     4580 +                } else if (nvlist_exists(rec, ZPOOL_HIST_IOCTL)) {
     4581 +                        if (!cb->internal)
4551 4582                                  continue;
4552      -                        (void) snprintf(internalstr,
4553      -                            sizeof (internalstr),
4554      -                            "[internal %s txg:%lld] %s",
4555      -                            zfs_history_event_names[ievent], txg,
4556      -                            pathstr);
4557      -                        cmdstr = internalstr;
4558      -                }
4559      -                tsec = dst_time;
4560      -                (void) localtime_r(&tsec, &t);
4561      -                (void) strftime(tbuf, sizeof (tbuf), "%F.%T", &t);
4562      -                (void) printf("%s %s", tbuf, cmdstr);
     4583 +                        (void) printf("%s ioctl %s\n", tbuf,
     4584 +                            fnvlist_lookup_string(rec, ZPOOL_HIST_IOCTL));
     4585 +                        if (nvlist_exists(rec, ZPOOL_HIST_INPUT_NVL)) {
     4586 +                                (void) printf("    input:\n");
     4587 +                                dump_nvlist(fnvlist_lookup_nvlist(rec,
     4588 +                                    ZPOOL_HIST_INPUT_NVL), 8);
     4589 +                        }
     4590 +                        if (nvlist_exists(rec, ZPOOL_HIST_OUTPUT_NVL)) {
     4591 +                                (void) printf("    output:\n");
     4592 +                                dump_nvlist(fnvlist_lookup_nvlist(rec,
     4593 +                                    ZPOOL_HIST_OUTPUT_NVL), 8);
     4594 +                        }
     4595 +                } else {
     4596 +                        if (!cb->internal)
     4597 +                                continue;
     4598 +                        (void) printf("%s unrecognized record:\n", tbuf);
     4599 +                        dump_nvlist(rec, 4);
     4600 +                }
4563 4601  
4564 4602                  if (!cb->longfmt) {
4565 4603                          (void) printf("\n");
4566 4604                          continue;
4567 4605                  }
4568 4606                  (void) printf(" [");
4569      -                if (nvlist_lookup_uint64(records[i],
4570      -                    ZPOOL_HIST_WHO, &who) == 0) {
4571      -                        pwd = getpwuid((uid_t)who);
4572      -                        if (pwd)
4573      -                                (void) printf("user %s on",
4574      -                                    pwd->pw_name);
4575      -                        else
4576      -                                (void) printf("user %d on",
4577      -                                    (int)who);
4578      -                } else {
4579      -                        (void) printf(gettext("no info]\n"));
4580      -                        continue;
     4607 +                if (nvlist_exists(rec, ZPOOL_HIST_WHO)) {
     4608 +                        uid_t who = fnvlist_lookup_uint64(rec, ZPOOL_HIST_WHO);
     4609 +                        struct passwd *pwd = getpwuid(who);
     4610 +                        (void) printf("user %d ", (int)who);
     4611 +                        if (pwd != NULL)
     4612 +                                (void) printf("(%s) ", pwd->pw_name);
     4613 +                }
     4614 +                if (nvlist_exists(rec, ZPOOL_HIST_HOST)) {
     4615 +                        (void) printf("on %s",
     4616 +                            fnvlist_lookup_string(rec, ZPOOL_HIST_HOST));
     4617 +                }
     4618 +                if (nvlist_exists(rec, ZPOOL_HIST_ZONE)) {
     4619 +                        (void) printf(":%s",
     4620 +                            fnvlist_lookup_string(rec, ZPOOL_HIST_ZONE));
4581 4621                  }
4582      -                if (nvlist_lookup_string(records[i],
4583      -                    ZPOOL_HIST_HOST, &hostname) == 0) {
4584      -                        (void) printf(" %s", hostname);
4585      -                }
4586      -                if (nvlist_lookup_string(records[i],
4587      -                    ZPOOL_HIST_ZONE, &zonename) == 0) {
4588      -                        (void) printf(":%s", zonename);
4589      -                }
4590      -
4591 4622                  (void) printf("]");
4592 4623                  (void) printf("\n");
4593 4624          }
4594 4625          (void) printf("\n");
4595 4626          nvlist_free(nvhis);
4596 4627  
4597 4628          return (ret);
4598 4629  }
4599 4630  
4600 4631  /*
4601 4632   * zpool history <pool>
4602 4633   *
4603 4634   * Displays the history of commands that modified pools.
4604 4635   */
4605      -
4606      -
4607 4636  int
4608 4637  zpool_do_history(int argc, char **argv)
4609 4638  {
4610 4639          hist_cbdata_t cbdata = { 0 };
4611 4640          int ret;
4612 4641          int c;
4613 4642  
4614 4643          cbdata.first = B_TRUE;
4615 4644          /* check options */
4616 4645          while ((c = getopt(argc, argv, "li")) != -1) {
4617 4646                  switch (c) {
4618 4647                  case 'l':
4619      -                        cbdata.longfmt = 1;
     4648 +                        cbdata.longfmt = B_TRUE;
4620 4649                          break;
4621 4650                  case 'i':
4622      -                        cbdata.internal = 1;
     4651 +                        cbdata.internal = B_TRUE;
4623 4652                          break;
4624 4653                  case '?':
4625 4654                          (void) fprintf(stderr, gettext("invalid option '%c'\n"),
4626 4655                              optopt);
4627 4656                          usage(B_FALSE);
4628 4657                  }
4629 4658          }
4630 4659          argc -= optind;
4631 4660          argv += optind;
4632 4661  
↓ open down ↓ 204 lines elided ↑ open up ↑
4837 4866          }
4838 4867  
4839 4868          cmdname = argv[1];
4840 4869  
4841 4870          /*
4842 4871           * Special case '-?'
4843 4872           */
4844 4873          if (strcmp(cmdname, "-?") == 0)
4845 4874                  usage(B_TRUE);
4846 4875  
4847      -        zpool_set_history_str("zpool", argc, argv, history_str);
4848      -        verify(zpool_stage_history(g_zfs, history_str) == 0);
     4876 +        zfs_save_arguments(argc, argv, history_str, sizeof (history_str));
4849 4877  
4850 4878          /*
4851 4879           * Run the appropriate command.
4852 4880           */
4853 4881          if (find_command_idx(cmdname, &i) == 0) {
4854 4882                  current_command = &command_table[i];
4855 4883                  ret = command_table[i].func(argc - 1, argv + 1);
4856 4884          } else if (strchr(cmdname, '=')) {
4857 4885                  verify(find_command_idx("set", &i) == 0);
4858 4886                  current_command = &command_table[i];
↓ open down ↓ 6 lines elided ↑ open up ↑
4865 4893                  char buf[16384];
4866 4894                  int fd = open(ZFS_DEV, O_RDWR);
4867 4895                  (void) strcpy((void *)buf, argv[2]);
4868 4896                  return (!!ioctl(fd, ZFS_IOC_POOL_FREEZE, buf));
4869 4897          } else {
4870 4898                  (void) fprintf(stderr, gettext("unrecognized "
4871 4899                      "command '%s'\n"), cmdname);
4872 4900                  usage(B_FALSE);
4873 4901          }
4874 4902  
     4903 +        if (ret == 0 && log_history)
     4904 +                (void) zpool_log_history(g_zfs, history_str);
     4905 +
4875 4906          libzfs_fini(g_zfs);
4876 4907  
4877 4908          /*
4878 4909           * The 'ZFS_ABORT' environment variable causes us to dump core on exit
4879 4910           * for the purposes of running ::findleaks.
4880 4911           */
4881 4912          if (getenv("ZFS_ABORT") != NULL) {
4882 4913                  (void) printf("dumping core by request\n");
4883 4914                  abort();
4884 4915          }
4885 4916  
4886 4917          return (ret);
4887 4918  }
    
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX