Print this page
OS-1566 filesystem limits for ZFS datasets

Split Close
Expand all
Collapse all
          --- old/usr/src/uts/common/fs/zfs/dmu_objset.c
          +++ new/usr/src/uts/common/fs/zfs/dmu_objset.c
↓ open down ↓ 13 lines elided ↑ open up ↑
  14   14   * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15   15   * If applicable, add the following below this CDDL HEADER, with the
  16   16   * fields enclosed by brackets "[]" replaced with your own identifying
  17   17   * information: Portions Copyright [yyyy] [name of copyright owner]
  18   18   *
  19   19   * CDDL HEADER END
  20   20   */
  21   21  /*
  22   22   * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
  23   23   * Copyright (c) 2012 by Delphix. All rights reserved.
       24 + * Copyright (c) 2012, Joyent, Inc. All rights reserved.
  24   25   */
  25   26  
  26   27  /* Portions Copyright 2010 Robert Milkowski */
  27   28  
  28   29  #include <sys/cred.h>
  29   30  #include <sys/zfs_context.h>
  30   31  #include <sys/dmu_objset.h>
  31   32  #include <sys/dsl_dir.h>
  32   33  #include <sys/dsl_dataset.h>
  33   34  #include <sys/dsl_prop.h>
↓ open down ↓ 649 lines elided ↑ open up ↑
 683  684          if (oa->clone_origin != NULL) {
 684  685                  /* You can't clone across pools. */
 685  686                  if (oa->clone_origin->ds_dir->dd_pool != dd->dd_pool)
 686  687                          return (EXDEV);
 687  688  
 688  689                  /* You can only clone snapshots, not the head datasets. */
 689  690                  if (!dsl_dataset_is_snapshot(oa->clone_origin))
 690  691                          return (EINVAL);
 691  692          }
 692  693  
 693      -        return (0);
      694 +        return (dsl_dir_fscount_check(dd, 1, NULL));
 694  695  }
 695  696  
 696  697  static void
 697  698  dmu_objset_create_sync(void *arg1, void *arg2, dmu_tx_t *tx)
 698  699  {
 699  700          dsl_dir_t *dd = arg1;
 700  701          spa_t *spa = dd->dd_pool->dp_spa;
 701  702          struct oscarg *oa = arg2;
 702  703          uint64_t obj;
 703  704          dsl_dataset_t *ds;
 704  705          blkptr_t *bp;
 705  706  
 706  707          ASSERT(dmu_tx_is_syncing(tx));
 707  708  
      709 +        dsl_dir_fscount_adjust(dd, tx, 1, B_TRUE, B_TRUE);
      710 +
 708  711          obj = dsl_dataset_create_sync(dd, oa->lastname,
 709  712              oa->clone_origin, oa->flags, oa->cr, tx);
 710  713  
 711  714          VERIFY3U(0, ==, dsl_dataset_hold_obj(dd->dd_pool, obj, FTAG, &ds));
 712  715          bp = dsl_dataset_get_blkptr(ds);
 713  716          if (BP_IS_HOLE(bp)) {
 714  717                  objset_t *os =
 715  718                      dmu_objset_create_impl(spa, ds, bp, oa->type, tx);
 716  719  
 717  720                  if (oa->userfunc)
↓ open down ↓ 93 lines elided ↑ open up ↑
 811  814          /* the following are used only if 'temporary' is set: */
 812  815          boolean_t saa_temporary;
 813  816          const char *saa_htag;
 814  817          struct dsl_ds_holdarg *saa_ha;
 815  818          dsl_dataset_t *saa_newds;
 816  819  } snapallarg_t;
 817  820  
 818  821  typedef struct snaponearg {
 819  822          const char *soa_longname; /* long snap name */
 820  823          const char *soa_snapname; /* short snap name */
      824 +        uint64_t soa_tot_cnt;
 821  825          snapallarg_t *soa_saa;
 822  826  } snaponearg_t;
 823  827  
 824  828  static int
 825  829  snapshot_check(void *arg1, void *arg2, dmu_tx_t *tx)
 826  830  {
 827  831          objset_t *os = arg1;
 828  832          snaponearg_t *soa = arg2;
 829  833          snapallarg_t *saa = soa->soa_saa;
 830  834          int error;
 831  835  
 832  836          /* The props have already been checked by zfs_check_userprops(). */
 833  837  
 834  838          error = dsl_dataset_snapshot_check(os->os_dsl_dataset,
 835      -            soa->soa_snapname, tx);
      839 +            soa->soa_snapname, soa->soa_tot_cnt, tx);
 836  840          if (error)
 837  841                  return (error);
 838  842  
 839  843          if (saa->saa_temporary) {
 840  844                  /*
 841  845                   * Ideally we would just call
 842  846                   * dsl_dataset_user_hold_check() and
 843  847                   * dsl_dataset_destroy_check() here.  However the
 844  848                   * dataset we want to hold and destroy is the snapshot
 845  849                   * that we just confirmed we can create, but it won't
↓ open down ↓ 44 lines elided ↑ open up ↑
 890  894                  saa->saa_ha = NULL;
 891  895                  saa->saa_newds = ds->ds_prev;
 892  896  
 893  897                  da.ds = ds->ds_prev;
 894  898                  da.defer = B_TRUE;
 895  899                  dsl_dataset_destroy_sync(&da, FTAG, tx);
 896  900          }
 897  901  }
 898  902  
 899  903  static int
 900      -snapshot_one_impl(const char *snapname, void *arg)
      904 +snapshot_one_impl(const char *snapname, void *arg, uint64_t cnt)
 901  905  {
 902  906          char fsname[MAXPATHLEN];
 903  907          snapallarg_t *saa = arg;
 904  908          snaponearg_t *soa;
 905  909          objset_t *os;
 906  910          int err;
 907  911  
 908  912          (void) strlcpy(fsname, snapname, sizeof (fsname));
 909  913          strchr(fsname, '@')[0] = '\0';
 910  914  
↓ open down ↓ 15 lines elided ↑ open up ↑
 926  930                  if (err) {
 927  931                          dmu_objset_rele(os, saa);
 928  932                          return (err);
 929  933                  }
 930  934          }
 931  935  
 932  936          soa = kmem_zalloc(sizeof (*soa), KM_SLEEP);
 933  937          soa->soa_saa = saa;
 934  938          soa->soa_longname = snapname;
 935  939          soa->soa_snapname = strchr(snapname, '@') + 1;
      940 +        soa->soa_tot_cnt = cnt;
 936  941  
 937  942          dsl_sync_task_create(saa->saa_dstg, snapshot_check, snapshot_sync,
 938  943              os, soa, 3);
 939  944  
 940  945          return (0);
 941  946  }
 942  947  
 943  948  /*
 944  949   * The snapshots must all be in the same pool.
 945  950   */
 946  951  int
 947  952  dmu_objset_snapshot(nvlist_t *snaps, nvlist_t *props, nvlist_t *errors)
 948  953  {
 949  954          dsl_sync_task_t *dst;
 950  955          snapallarg_t saa = { 0 };
 951  956          spa_t *spa;
 952  957          int rv = 0;
 953  958          int err;
 954  959          nvpair_t *pair;
      960 +        nvlist_t *cnt_track = NULL;
      961 +        nvpair_t *pp;
      962 +        char *pdelim;
      963 +        uint64_t *pv;
      964 +        char nm[MAXPATHLEN];
 955  965  
 956  966          pair = nvlist_next_nvpair(snaps, NULL);
 957  967          if (pair == NULL)
 958  968                  return (0);
 959  969  
 960  970          err = spa_open(nvpair_name(pair), &spa, FTAG);
 961  971          if (err)
 962  972                  return (err);
 963  973          saa.saa_dstg = dsl_sync_task_group_create(spa_get_dsl(spa));
 964  974          saa.saa_props = props;
 965  975          saa.saa_needsuspend = (spa_version(spa) < SPA_VERSION_FAST_SNAP);
 966  976  
      977 +        /*
      978 +         * Pre-compute how many total new snapshots will be created for each
      979 +         * level in the tree and below. This is needed for validating the
      980 +         * snapshot limit when taking a recursive snapshot.
      981 +         *
      982 +         * The problem is that the counts are not actually adjusted when
      983 +         * we are checking, only when we finally sync. For a single snapshot,
      984 +         * this is easy, the count will increase by 1 at each node up the tree,
      985 +         * but its more complicated for recursive snapshots. Since we are
      986 +         * validating each snapshot independently we need to be sure that we
      987 +         * are validating the complete count for the entire set of snapshots.
      988 +         * We do this by rolling up the counts for each component of the name
      989 +         * into an nvlist then we'll use that count in the validation of each
      990 +         * individual snapshot.
      991 +         *
      992 +         * We validated the snapshot names in zfs_ioc_snapshot so we know they
      993 +         * have a '@'.
      994 +         */
      995 +        VERIFY(nvlist_alloc(&cnt_track, NV_UNIQUE_NAME, KM_SLEEP) == 0);
      996 +
 967  997          for (pair = nvlist_next_nvpair(snaps, NULL); pair != NULL;
 968  998              pair = nvlist_next_nvpair(snaps, pair)) {
 969      -                err = snapshot_one_impl(nvpair_name(pair), &saa);
      999 +                (void) strlcpy(nm, nvpair_name(pair), sizeof (nm));
     1000 +                pdelim = strchr(nm, '@');
     1001 +                *pdelim = '\0';
     1002 +
     1003 +                do {
     1004 +                        if (nvlist_lookup_nvpair(cnt_track, nm, &pp) != 0) {
     1005 +                                /* add to list */
     1006 +                                nvlist_add_uint64(cnt_track, nm, 1);
     1007 +                        } else {
     1008 +                                /* update existing entry */
     1009 +                                pv = (uint64_t *)NVP_VALUE(pp);
     1010 +                                *pv += 1;
     1011 +                        }
     1012 +
     1013 +                        pdelim = strrchr(nm, '/');
     1014 +                        if (pdelim != NULL)
     1015 +                                *pdelim = '\0';
     1016 +                } while (pdelim != NULL);
     1017 +        }
     1018 +
     1019 +        /*
     1020 +         * We've calculated the counts, now validate.
     1021 +         */
     1022 +        for (pair = nvlist_next_nvpair(snaps, NULL); pair != NULL;
     1023 +            pair = nvlist_next_nvpair(snaps, pair)) {
     1024 +                (void) strlcpy(nm, nvpair_name(pair), sizeof (nm));
     1025 +                pdelim = strchr(nm, '@');
     1026 +                *pdelim = '\0';
     1027 +
     1028 +                VERIFY(nvlist_lookup_nvpair(cnt_track, nm, &pp) == 0);
     1029 +
     1030 +                pv = (uint64_t *)NVP_VALUE(pp);
     1031 +                err = snapshot_one_impl(nvpair_name(pair), &saa, *pv);
 970 1032                  if (err != 0) {
 971 1033                          if (errors != NULL) {
 972 1034                                  fnvlist_add_int32(errors,
 973 1035                                      nvpair_name(pair), err);
 974 1036                          }
 975 1037                          rv = err;
 976 1038                  }
 977 1039          }
 978 1040  
     1041 +        nvlist_free(cnt_track);
     1042 +
 979 1043          /*
 980 1044           * If any call to snapshot_one_impl() failed, don't execute the
 981 1045           * sync task.  The error handling code below will clean up the
 982 1046           * snaponearg_t from any successful calls to
 983 1047           * snapshot_one_impl().
 984 1048           */
 985 1049          if (rv == 0)
 986 1050                  err = dsl_sync_task_group_wait(saa.saa_dstg);
 987 1051          if (err != 0)
 988 1052                  rv = err;
↓ open down ↓ 54 lines elided ↑ open up ↑
1043 1107  
1044 1108          if (cleanup_fd < 0) {
1045 1109                  spa_close(spa, FTAG);
1046 1110                  return (EINVAL);
1047 1111          }
1048 1112          if ((err = zfs_onexit_fd_hold(cleanup_fd, &minor)) != 0) {
1049 1113                  spa_close(spa, FTAG);
1050 1114                  return (err);
1051 1115          }
1052 1116  
1053      -        err = snapshot_one_impl(snapname, &saa);
     1117 +        err = snapshot_one_impl(snapname, &saa, 1);
1054 1118  
1055 1119          if (err == 0)
1056 1120                  err = dsl_sync_task_group_wait(saa.saa_dstg);
1057 1121  
1058 1122          for (dst = list_head(&saa.saa_dstg->dstg_tasks); dst;
1059 1123              dst = list_next(&saa.saa_dstg->dstg_tasks, dst)) {
1060 1124                  objset_t *os = dst->dst_arg1;
1061 1125                  dsl_register_onexit_hold_cleanup(saa.saa_newds, tag, minor);
1062 1126                  if (saa.saa_needsuspend)
1063 1127                          zil_resume(dmu_objset_zil(os));
↓ open down ↓ 778 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX