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, oa->cr));
 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);
      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 ↓ 82 lines elided ↑ open up ↑
 800  803                  /* dsl_dataset_destroy() closes the ds. */
 801  804          }
 802  805  
 803  806          return (error);
 804  807  }
 805  808  
 806  809  typedef struct snapallarg {
 807  810          dsl_sync_task_group_t *saa_dstg;
 808  811          boolean_t saa_needsuspend;
 809  812          nvlist_t *saa_props;
      813 +        cred_t *saa_cr;
 810  814  
 811  815          /* the following are used only if 'temporary' is set: */
 812  816          boolean_t saa_temporary;
 813  817          const char *saa_htag;
 814  818          struct dsl_ds_holdarg *saa_ha;
 815  819          dsl_dataset_t *saa_newds;
 816  820  } snapallarg_t;
 817  821  
 818  822  typedef struct snaponearg {
 819  823          const char *soa_longname; /* long snap name */
 820  824          const char *soa_snapname; /* short snap name */
      825 +        uint64_t soa_tot_cnt;
 821  826          snapallarg_t *soa_saa;
 822  827  } snaponearg_t;
 823  828  
 824  829  static int
 825  830  snapshot_check(void *arg1, void *arg2, dmu_tx_t *tx)
 826  831  {
 827  832          objset_t *os = arg1;
 828  833          snaponearg_t *soa = arg2;
 829  834          snapallarg_t *saa = soa->soa_saa;
 830  835          int error;
 831  836  
 832  837          /* The props have already been checked by zfs_check_userprops(). */
 833  838  
 834  839          error = dsl_dataset_snapshot_check(os->os_dsl_dataset,
 835      -            soa->soa_snapname, tx);
      840 +            soa->soa_snapname, soa->soa_tot_cnt, tx, saa->saa_cr);
 836  841          if (error)
 837  842                  return (error);
 838  843  
 839  844          if (saa->saa_temporary) {
 840  845                  /*
 841  846                   * Ideally we would just call
 842  847                   * dsl_dataset_user_hold_check() and
 843  848                   * dsl_dataset_destroy_check() here.  However the
 844  849                   * dataset we want to hold and destroy is the snapshot
 845  850                   * that we just confirmed we can create, but it won't
↓ open down ↓ 44 lines elided ↑ open up ↑
 890  895                  saa->saa_ha = NULL;
 891  896                  saa->saa_newds = ds->ds_prev;
 892  897  
 893  898                  da.ds = ds->ds_prev;
 894  899                  da.defer = B_TRUE;
 895  900                  dsl_dataset_destroy_sync(&da, FTAG, tx);
 896  901          }
 897  902  }
 898  903  
 899  904  static int
 900      -snapshot_one_impl(const char *snapname, void *arg)
      905 +snapshot_one_impl(const char *snapname, void *arg, uint64_t cnt)
 901  906  {
 902  907          char fsname[MAXPATHLEN];
 903  908          snapallarg_t *saa = arg;
 904  909          snaponearg_t *soa;
 905  910          objset_t *os;
 906  911          int err;
 907  912  
 908  913          (void) strlcpy(fsname, snapname, sizeof (fsname));
 909  914          strchr(fsname, '@')[0] = '\0';
 910  915  
↓ open down ↓ 15 lines elided ↑ open up ↑
 926  931                  if (err) {
 927  932                          dmu_objset_rele(os, saa);
 928  933                          return (err);
 929  934                  }
 930  935          }
 931  936  
 932  937          soa = kmem_zalloc(sizeof (*soa), KM_SLEEP);
 933  938          soa->soa_saa = saa;
 934  939          soa->soa_longname = snapname;
 935  940          soa->soa_snapname = strchr(snapname, '@') + 1;
      941 +        soa->soa_tot_cnt = cnt;
 936  942  
 937  943          dsl_sync_task_create(saa->saa_dstg, snapshot_check, snapshot_sync,
 938  944              os, soa, 3);
 939  945  
 940  946          return (0);
 941  947  }
 942  948  
 943  949  /*
 944  950   * The snapshots must all be in the same pool.
 945  951   */
 946  952  int
 947  953  dmu_objset_snapshot(nvlist_t *snaps, nvlist_t *props, nvlist_t *errors)
 948  954  {
 949  955          dsl_sync_task_t *dst;
 950  956          snapallarg_t saa = { 0 };
 951  957          spa_t *spa;
 952  958          int rv = 0;
 953  959          int err;
 954  960          nvpair_t *pair;
      961 +        nvlist_t *cnt_track = NULL;
      962 +        char *pdelim;
      963 +        uint64_t val;
      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);
      976 +        saa.saa_cr = CRED();
 966  977  
      978 +        /*
      979 +         * Pre-compute how many total new snapshots will be created for each
      980 +         * level in the tree and below. This is needed for validating the
      981 +         * snapshot limit when taking a recursive snapshot.
      982 +         *
      983 +         * The problem is that the counts are not actually adjusted when
      984 +         * we are checking, only when we finally sync. For a single snapshot,
      985 +         * this is easy, the count will increase by 1 at each node up the tree,
      986 +         * but its more complicated for recursive snapshots. Since we are
      987 +         * validating each snapshot independently we need to be sure that we
      988 +         * are validating the complete count for the entire set of snapshots.
      989 +         * We do this by rolling up the counts for each component of the name
      990 +         * into an nvlist then we'll use that count in the validation of each
      991 +         * individual snapshot.
      992 +         *
      993 +         * We validated the snapshot names in zfs_ioc_snapshot so we know they
      994 +         * have a '@'.
      995 +         */
      996 +        cnt_track = fnvlist_alloc();
      997 +
 967  998          for (pair = nvlist_next_nvpair(snaps, NULL); pair != NULL;
 968  999              pair = nvlist_next_nvpair(snaps, pair)) {
 969      -                err = snapshot_one_impl(nvpair_name(pair), &saa);
     1000 +                (void) strlcpy(nm, nvpair_name(pair), sizeof (nm));
     1001 +                pdelim = strchr(nm, '@');
     1002 +                *pdelim = '\0';
     1003 +
     1004 +                do {
     1005 +                        if (nvlist_lookup_uint64(cnt_track, nm, &val) == 0) {
     1006 +                                /* update existing entry */
     1007 +                                fnvlist_add_uint64(cnt_track, nm, val + 1);
     1008 +                        } else {
     1009 +                                /* add to list */
     1010 +                                fnvlist_add_uint64(cnt_track, nm, 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 +                val = fnvlist_lookup_uint64(cnt_track, nm);
     1029 +                err = snapshot_one_impl(nvpair_name(pair), &saa, val);
 970 1030                  if (err != 0) {
 971 1031                          if (errors != NULL) {
 972 1032                                  fnvlist_add_int32(errors,
 973 1033                                      nvpair_name(pair), err);
 974 1034                          }
 975 1035                          rv = err;
 976 1036                  }
 977 1037          }
 978 1038  
     1039 +        nvlist_free(cnt_track);
     1040 +
 979 1041          /*
 980 1042           * If any call to snapshot_one_impl() failed, don't execute the
 981 1043           * sync task.  The error handling code below will clean up the
 982 1044           * snaponearg_t from any successful calls to
 983 1045           * snapshot_one_impl().
 984 1046           */
 985 1047          if (rv == 0)
 986 1048                  err = dsl_sync_task_group_wait(saa.saa_dstg);
 987 1049          if (err != 0)
 988 1050                  rv = err;
↓ open down ↓ 54 lines elided ↑ open up ↑
1043 1105  
1044 1106          if (cleanup_fd < 0) {
1045 1107                  spa_close(spa, FTAG);
1046 1108                  return (EINVAL);
1047 1109          }
1048 1110          if ((err = zfs_onexit_fd_hold(cleanup_fd, &minor)) != 0) {
1049 1111                  spa_close(spa, FTAG);
1050 1112                  return (err);
1051 1113          }
1052 1114  
1053      -        err = snapshot_one_impl(snapname, &saa);
     1115 +        err = snapshot_one_impl(snapname, &saa, 1);
1054 1116  
1055 1117          if (err == 0)
1056 1118                  err = dsl_sync_task_group_wait(saa.saa_dstg);
1057 1119  
1058 1120          for (dst = list_head(&saa.saa_dstg->dstg_tasks); dst;
1059 1121              dst = list_next(&saa.saa_dstg->dstg_tasks, dst)) {
1060 1122                  objset_t *os = dst->dst_arg1;
1061 1123                  dsl_register_onexit_hold_cleanup(saa.saa_newds, tag, minor);
1062 1124                  if (saa.saa_needsuspend)
1063 1125                          zil_resume(dmu_objset_zil(os));
↓ open down ↓ 778 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX