Print this page
OS-1566 filesystem limits for ZFS datasets


   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 /*
  22  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
  23  * Copyright (c) 2012 by Delphix. All rights reserved.

  24  */
  25 
  26 /*
  27  * DSL permissions are stored in a two level zap attribute
  28  * mechanism.   The first level identifies the "class" of
  29  * entry.  The class is identified by the first 2 letters of
  30  * the attribute.  The second letter "l" or "d" identifies whether
  31  * it is a local or descendent permission.  The first letter
  32  * identifies the type of entry.
  33  *
  34  * ul$<id>    identifies permissions granted locally for this userid.
  35  * ud$<id>    identifies permissions granted on descendent datasets for
  36  *            this userid.
  37  * Ul$<id>    identifies permission sets granted locally for this userid.
  38  * Ud$<id>    identifies permission sets granted on descendent datasets for
  39  *            this userid.
  40  * gl$<id>    identifies permissions granted locally for this groupid.
  41  * gd$<id>    identifies permissions granted on descendent datasets for
  42  *            this groupid.
  43  * Gl$<id>    identifies permission sets granted locally for this groupid.


 504         id = crgetgid(cr);
 505         (void) dsl_load_sets(mos, zapobj,
 506             ZFS_DELEG_GROUP_SETS, checkflag, &id, avl);
 507 
 508         (void) dsl_load_sets(mos, zapobj,
 509             ZFS_DELEG_EVERYONE_SETS, checkflag, NULL, avl);
 510 
 511         ngids = crgetngroups(cr);
 512         gids = crgetgroups(cr);
 513         for (i = 0; i != ngids; i++) {
 514                 id = gids[i];
 515                 (void) dsl_load_sets(mos, zapobj,
 516                     ZFS_DELEG_GROUP_SETS, checkflag, &id, avl);
 517         }
 518 }
 519 
 520 /*
 521  * Check if user has requested permission.
 522  */
 523 int
 524 dsl_deleg_access_impl(dsl_dataset_t *ds, const char *perm, cred_t *cr)

 525 {
 526         dsl_dir_t *dd;
 527         dsl_pool_t *dp;
 528         void *cookie;
 529         int     error;
 530         char    checkflag;
 531         objset_t *mos;
 532         avl_tree_t permsets;
 533         perm_set_t *setnode;
 534 
 535         dp = ds->ds_dir->dd_pool;
 536         mos = dp->dp_meta_objset;
 537 
 538         if (dsl_delegation_on(mos) == B_FALSE)
 539                 return (ECANCELED);
 540 
 541         if (spa_version(dmu_objset_spa(dp->dp_meta_objset)) <
 542             SPA_VERSION_DELEGATED_PERMS)
 543                 return (EPERM);
 544 
 545         if (dsl_dataset_is_snapshot(ds)) {
 546                 /*
 547                  * Snapshots are treated as descendents only,
 548                  * local permissions do not apply.
 549                  */
 550                 checkflag = ZFS_DELEG_DESCENDENT;
 551         } else {
 552                 checkflag = ZFS_DELEG_LOCAL;
 553         }
 554 
 555         avl_create(&permsets, perm_set_compare, sizeof (perm_set_t),
 556             offsetof(perm_set_t, p_node));
 557 

 558         rw_enter(&dp->dp_config_rwlock, RW_READER);
 559         for (dd = ds->ds_dir; dd != NULL; dd = dd->dd_parent,
 560             checkflag = ZFS_DELEG_DESCENDENT) {
 561                 uint64_t zapobj;
 562                 boolean_t expanded;
 563 
 564                 /*
 565                  * If not in global zone then make sure
 566                  * the zoned property is set
 567                  */
 568                 if (!INGLOBALZONE(curproc)) {
 569                         uint64_t zoned;
 570 
 571                         if (dsl_prop_get_dd(dd,
 572                             zfs_prop_to_name(ZFS_PROP_ZONED),
 573                             8, 1, &zoned, NULL, B_FALSE) != 0)
 574                                 break;
 575                         if (!zoned)
 576                                 break;
 577                 }


 599                         /* See if this set includes other sets */
 600                         error = dsl_load_sets(mos, zapobj,
 601                             ZFS_DELEG_NAMED_SET_SETS, 0,
 602                             setnode->p_setname, &permsets);
 603                         if (error == 0)
 604                                 setnode->p_matched = expanded = B_TRUE;
 605                 }
 606                 /*
 607                  * If we expanded any sets, that will define more sets,
 608                  * which we need to check.
 609                  */
 610                 if (expanded)
 611                         goto again;
 612 
 613                 error = dsl_check_user_access(mos, zapobj, perm, checkflag, cr);
 614                 if (error == 0)
 615                         goto success;
 616         }
 617         error = EPERM;
 618 success:

 619         rw_exit(&dp->dp_config_rwlock);
 620 
 621         cookie = NULL;
 622         while ((setnode = avl_destroy_nodes(&permsets, &cookie)) != NULL)
 623                 kmem_free(setnode, sizeof (perm_set_t));
 624 
 625         return (error);
 626 }
 627 
 628 int
 629 dsl_deleg_access(const char *dsname, const char *perm, cred_t *cr)
 630 {
 631         dsl_dataset_t *ds;
 632         int error;
 633 
 634         error = dsl_dataset_hold(dsname, FTAG, &ds);
 635         if (error)
 636                 return (error);
 637 
 638         error = dsl_deleg_access_impl(ds, perm, cr);
 639         dsl_dataset_rele(ds, FTAG);
 640 
 641         return (error);
 642 }
 643 
 644 /*
 645  * Other routines.
 646  */
 647 
 648 static void
 649 copy_create_perms(dsl_dir_t *dd, uint64_t pzapobj,
 650     boolean_t dosets, uint64_t uid, dmu_tx_t *tx)
 651 {
 652         objset_t *mos = dd->dd_pool->dp_meta_objset;
 653         uint64_t jumpobj, pjumpobj;
 654         uint64_t zapobj = dd->dd_phys->dd_deleg_zapobj;
 655         zap_cursor_t zc;
 656         zap_attribute_t za;
 657         char whokey[ZFS_MAX_DELEG_NAME];
 658 




   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 /*
  22  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
  23  * Copyright (c) 2012 by Delphix. All rights reserved.
  24  * Copyright (c) 2012 Joyent, Inc. All rights reserved.
  25  */
  26 
  27 /*
  28  * DSL permissions are stored in a two level zap attribute
  29  * mechanism.   The first level identifies the "class" of
  30  * entry.  The class is identified by the first 2 letters of
  31  * the attribute.  The second letter "l" or "d" identifies whether
  32  * it is a local or descendent permission.  The first letter
  33  * identifies the type of entry.
  34  *
  35  * ul$<id>    identifies permissions granted locally for this userid.
  36  * ud$<id>    identifies permissions granted on descendent datasets for
  37  *            this userid.
  38  * Ul$<id>    identifies permission sets granted locally for this userid.
  39  * Ud$<id>    identifies permission sets granted on descendent datasets for
  40  *            this userid.
  41  * gl$<id>    identifies permissions granted locally for this groupid.
  42  * gd$<id>    identifies permissions granted on descendent datasets for
  43  *            this groupid.
  44  * Gl$<id>    identifies permission sets granted locally for this groupid.


 505         id = crgetgid(cr);
 506         (void) dsl_load_sets(mos, zapobj,
 507             ZFS_DELEG_GROUP_SETS, checkflag, &id, avl);
 508 
 509         (void) dsl_load_sets(mos, zapobj,
 510             ZFS_DELEG_EVERYONE_SETS, checkflag, NULL, avl);
 511 
 512         ngids = crgetngroups(cr);
 513         gids = crgetgroups(cr);
 514         for (i = 0; i != ngids; i++) {
 515                 id = gids[i];
 516                 (void) dsl_load_sets(mos, zapobj,
 517                     ZFS_DELEG_GROUP_SETS, checkflag, &id, avl);
 518         }
 519 }
 520 
 521 /*
 522  * Check if user has requested permission.
 523  */
 524 int
 525 dsl_deleg_access_impl(dsl_dataset_t *ds, const char *perm, cred_t *cr,
 526     boolean_t do_lock)
 527 {
 528         dsl_dir_t *dd;
 529         dsl_pool_t *dp;
 530         void *cookie;
 531         int     error;
 532         char    checkflag;
 533         objset_t *mos;
 534         avl_tree_t permsets;
 535         perm_set_t *setnode;
 536 
 537         dp = ds->ds_dir->dd_pool;
 538         mos = dp->dp_meta_objset;
 539 
 540         if (dsl_delegation_on(mos) == B_FALSE)
 541                 return (ECANCELED);
 542 
 543         if (spa_version(dmu_objset_spa(dp->dp_meta_objset)) <
 544             SPA_VERSION_DELEGATED_PERMS)
 545                 return (EPERM);
 546 
 547         if (dsl_dataset_is_snapshot(ds)) {
 548                 /*
 549                  * Snapshots are treated as descendents only,
 550                  * local permissions do not apply.
 551                  */
 552                 checkflag = ZFS_DELEG_DESCENDENT;
 553         } else {
 554                 checkflag = ZFS_DELEG_LOCAL;
 555         }
 556 
 557         avl_create(&permsets, perm_set_compare, sizeof (perm_set_t),
 558             offsetof(perm_set_t, p_node));
 559 
 560         if (do_lock)
 561                 rw_enter(&dp->dp_config_rwlock, RW_READER);
 562         for (dd = ds->ds_dir; dd != NULL; dd = dd->dd_parent,
 563             checkflag = ZFS_DELEG_DESCENDENT) {
 564                 uint64_t zapobj;
 565                 boolean_t expanded;
 566 
 567                 /*
 568                  * If not in global zone then make sure
 569                  * the zoned property is set
 570                  */
 571                 if (!INGLOBALZONE(curproc)) {
 572                         uint64_t zoned;
 573 
 574                         if (dsl_prop_get_dd(dd,
 575                             zfs_prop_to_name(ZFS_PROP_ZONED),
 576                             8, 1, &zoned, NULL, B_FALSE) != 0)
 577                                 break;
 578                         if (!zoned)
 579                                 break;
 580                 }


 602                         /* See if this set includes other sets */
 603                         error = dsl_load_sets(mos, zapobj,
 604                             ZFS_DELEG_NAMED_SET_SETS, 0,
 605                             setnode->p_setname, &permsets);
 606                         if (error == 0)
 607                                 setnode->p_matched = expanded = B_TRUE;
 608                 }
 609                 /*
 610                  * If we expanded any sets, that will define more sets,
 611                  * which we need to check.
 612                  */
 613                 if (expanded)
 614                         goto again;
 615 
 616                 error = dsl_check_user_access(mos, zapobj, perm, checkflag, cr);
 617                 if (error == 0)
 618                         goto success;
 619         }
 620         error = EPERM;
 621 success:
 622         if (do_lock)
 623                 rw_exit(&dp->dp_config_rwlock);
 624 
 625         cookie = NULL;
 626         while ((setnode = avl_destroy_nodes(&permsets, &cookie)) != NULL)
 627                 kmem_free(setnode, sizeof (perm_set_t));
 628 
 629         return (error);
 630 }
 631 
 632 int
 633 dsl_deleg_access(const char *dsname, const char *perm, cred_t *cr)
 634 {
 635         dsl_dataset_t *ds;
 636         int error;
 637 
 638         error = dsl_dataset_hold(dsname, FTAG, &ds);
 639         if (error)
 640                 return (error);
 641 
 642         error = dsl_deleg_access_impl(ds, perm, cr, B_TRUE);
 643         dsl_dataset_rele(ds, FTAG);
 644 
 645         return (error);
 646 }
 647 
 648 /*
 649  * Other routines.
 650  */
 651 
 652 static void
 653 copy_create_perms(dsl_dir_t *dd, uint64_t pzapobj,
 654     boolean_t dosets, uint64_t uid, dmu_tx_t *tx)
 655 {
 656         objset_t *mos = dd->dd_pool->dp_meta_objset;
 657         uint64_t jumpobj, pjumpobj;
 658         uint64_t zapobj = dd->dd_phys->dd_deleg_zapobj;
 659         zap_cursor_t zc;
 660         zap_attribute_t za;
 661         char whokey[ZFS_MAX_DELEG_NAME];
 662