Print this page
NEX-17457 kernel share list fails to be updated after fs import
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Gordon Ross <gordon.ross@nexenta.com>
Reviewed by: Yuri Pankov <yuripv@yuripv.net>
NEX-16159 Time spent sharing SMB filesystems could be reduced by optimizing smb_getdataset for default mount points
Reviewed by: Sanjay Nadkarni <sanjay.nadkarni@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Reviewed by: Matt Barden <matt.barden@nexenta.com>
NEX-9808 SMB3 persistent handles
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
NEX-5665 SMB2 oplock leases
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Roman Strashkin <roman.strashkin@nexenta.com>
NEX-9808 SMB3 persistent handles
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
NEX-5665 SMB2 oplock leases
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Roman Strashkin <roman.strashkin@nexenta.com>
NEX-10098 Disabling SMB server service does not change the sharestate of a smb share to “offline”.(cstyle)
NEX-10098 Disabling SMB server service does not change the sharestate of a smb share to “offline”.
Reviewed by: Gordon Ross <gordon.ross@nexenta.com>
Reviewed by: Rob Gittins <rob.gittins@nexenta.com>
NEX-5273 SMB 3 Encryption
Reviewed by: Gordon Ross <gordon.ross@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Roman Strashkin <roman.strashkin@nexenta.com>
NEX-6949 SMB shares with no permission for root fail after restart
Reviewed by: Rick McNeal <rick.mcneal@nexenta.com>
Reviewed by: Sanjay Nadkarni <sanjay.nadkarni@nexent.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Matt Barden <matt.barden@nexenta.com>
NEX-6135 Pool cannot get exported while deletes is running
Reviewed by: Alek Pinchuk <alek@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Sanjay Nadkarni <sanjay.nadkarni@nexent.com>
Reviewed by: Saso Kiselkov <saso.kiselkov@nexenta.com>
NEX-4865 Still creating .$EXTEND directory with quotas disabled
Reviewed by: Kevin Crowe <kevin.crowe@nexenta.com>
Reviewed by: Matt Barden <Matt.Barden@nexenta.com>
NEX-3863 Would like an SMB share property to enable/disable quotas
Reviewed by: Bayard Bell <bayard.bell@nexenta.com>
Reviewed by: Kevin Crowe <kevin.crowe@nexenta.com>
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>
NEX-3673 CLONE NEX-2525 Customer cannot set Share Properties using MMC in Windows Server 2008 R2
Reviewed by: Alek Pinchuk <alek@nexenta.com>
NEX-1473 share unavailable after failover (copyright update)
NEX-1473 share unavailable after failover

Split Close
Expand all
Collapse all
          --- old/usr/src/lib/smbsrv/libmlsvc/common/smb_share.c
          +++ new/usr/src/lib/smbsrv/libmlsvc/common/smb_share.c
↓ open down ↓ 11 lines elided ↑ open up ↑
  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   * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
  22      - * Copyright 2015 Nexenta Systems, Inc. All rights reserved.
       22 + * Copyright 2018 Nexenta Systems, Inc. All rights reserved.
  23   23   */
  24   24  
  25   25  /*
  26   26   * SMB/CIFS share cache implementation.
  27   27   */
  28   28  
  29   29  #include <errno.h>
  30   30  #include <synch.h>
  31   31  #include <stdlib.h>
  32   32  #include <strings.h>
↓ open down ↓ 349 lines elided ↑ open up ↑
 382  382   *
 383  383   * If the specified share is an autohome share which already
 384  384   * exists in the cache, just increments the reference count.
 385  385   */
 386  386  uint32_t
 387  387  smb_shr_add(smb_share_t *si)
 388  388  {
 389  389          struct stat st;
 390  390          smb_share_t *cached_si;
 391  391          nvlist_t *shrlist;
      392 +        boolean_t created_zfs = B_FALSE;
 392  393          uint32_t status;
 393  394          int rc;
 394  395  
 395  396          assert(si != NULL);
 396  397  
 397  398          if (smb_name_validate_share(si->shr_name) != ERROR_SUCCESS)
 398  399                  return (ERROR_INVALID_NAME);
 399  400  
 400  401          if (smb_shr_cache_lock(SMB_SHR_CACHE_WRLOCK) != NERR_Success)
 401  402                  return (NERR_InternalError);
↓ open down ↓ 7 lines elided ↑ open up ↑
 409  410                          status = NERR_DuplicateShare;
 410  411                  }
 411  412                  smb_shr_cache_unlock();
 412  413                  return (status);
 413  414          }
 414  415  
 415  416          if (STYPE_ISDSK(si->shr_type)) {
 416  417                  /*
 417  418                   * If share type is STYPE_DISKTREE then the path to the
 418  419                   * share should exist so that we can add the share to cache.
      420 +                 * If path is ZFS, add the .zfs/shares/<share> entry.
      421 +                 *
      422 +                 * Both actions may require privileges that main dropped,
      423 +                 * so we need to temporarily make those effective.
 419  424                   */
 420      -                rc = stat(si->shr_path, &st);
      425 +                if (smb_proc_takesem() == 0) {
      426 +
      427 +                        (void) priv_set(PRIV_ON, PRIV_EFFECTIVE,
      428 +                            PRIV_FILE_DAC_READ,
      429 +                            PRIV_FILE_DAC_SEARCH,
      430 +                            PRIV_FILE_DAC_WRITE,
      431 +                            NULL);
      432 +
      433 +                        rc = stat(si->shr_path, &st);
      434 +                        if (rc == 0) {
      435 +                                smb_shr_zfs_add(si);
      436 +                                created_zfs = B_TRUE;
      437 +                        }
      438 +
      439 +                        (void) priv_set(PRIV_OFF, PRIV_EFFECTIVE,
      440 +                            PRIV_FILE_DAC_READ,
      441 +                            PRIV_FILE_DAC_SEARCH,
      442 +                            PRIV_FILE_DAC_WRITE,
      443 +                            NULL);
      444 +                        smb_proc_givesem();
      445 +                } else {
      446 +                        rc = NERR_InternalError;
      447 +                }
 421  448                  if (rc != 0) {
 422  449                          smb_shr_cache_unlock();
 423  450                          return (NERR_ItemNotFound);
 424  451                  }
 425  452          }
 426  453  
 427  454          if ((status = smb_shr_cache_addent(si)) != NERR_Success) {
      455 +                /* This error should be impossible after findent above. */
 428  456                  smb_shr_cache_unlock();
 429  457                  return (status);
 430  458          }
 431  459  
 432  460          /* don't hold the lock across door call */
 433  461          smb_shr_cache_unlock();
 434  462  
 435  463          if ((rc = smb_shr_encode(si, &shrlist)) == 0) {
 436  464                  /* send the share to kernel */
 437  465                  rc = smb_kmod_share(shrlist);
 438  466                  nvlist_free(shrlist);
 439  467  
 440  468                  if (rc == 0) {
 441  469                          smb_shr_publish(si->shr_name, si->shr_container);
 442  470  
 443      -                        /* If path is ZFS, add the .zfs/shares/<share> entry. */
 444      -                        smb_shr_zfs_add(si);
 445      -
 446  471                          if ((si->shr_flags & SMB_SHRF_DFSROOT) != 0)
 447  472                                  dfs_namespace_load(si->shr_name);
 448  473  
 449  474                          return (NERR_Success);
 450  475                  }
 451  476          }
 452  477  
      478 +        /*
      479 +         * Error code path, i.e. when the kernel could not accept
      480 +         * the new share for some reason.
      481 +         */
 453  482          if (smb_shr_cache_lock(SMB_SHR_CACHE_WRLOCK) == NERR_Success) {
 454  483                  smb_shr_cache_delent(si->shr_name);
 455  484                  smb_shr_cache_unlock();
 456  485          }
 457  486  
      487 +        if (created_zfs && smb_proc_takesem() == 0) {
      488 +
      489 +                (void) priv_set(PRIV_ON, PRIV_EFFECTIVE,
      490 +                    PRIV_FILE_DAC_READ,
      491 +                    PRIV_FILE_DAC_SEARCH,
      492 +                    PRIV_FILE_DAC_WRITE,
      493 +                    NULL);
      494 +
      495 +                smb_shr_zfs_remove(si);
      496 +
      497 +                (void) priv_set(PRIV_OFF, PRIV_EFFECTIVE,
      498 +                    PRIV_FILE_DAC_READ,
      499 +                    PRIV_FILE_DAC_SEARCH,
      500 +                    PRIV_FILE_DAC_WRITE,
      501 +                    NULL);
      502 +
      503 +                smb_proc_givesem();
      504 +        }
      505 +
 458  506          /*
 459  507           * rc == ENOENT means the shared directory doesn't exist
 460  508           */
 461  509          return ((rc == ENOENT) ? NERR_UnknownDevDir : NERR_InternalError);
 462  510  }
 463  511  
 464  512  /*
 465  513   * Removes the specified share from cache, removes it from AD
 466  514   * if it has an AD container, and calls the kernel to release
 467  515   * the hold on the shared file system.
↓ open down ↓ 30 lines elided ↑ open up ↑
 498  546  
 499  547          if (si->shr_flags & SMB_SHRF_AUTOHOME) {
 500  548                  if ((--si->shr_refcnt) > 0) {
 501  549                          smb_shr_cache_unlock();
 502  550                          return (NERR_Success);
 503  551                  }
 504  552          }
 505  553  
 506  554          /*
 507  555           * If path is ZFS, remove the .zfs/shares/<share> entry.  Need
 508      -         * to remove before cleanup of cache occurs.
      556 +         * to remove before cleanup of cache occurs.  These actions
      557 +         * require temporary elevation of privileges.
 509  558           */
 510      -        smb_shr_zfs_remove(si);
      559 +        if (smb_proc_takesem() == 0) {
      560 +
      561 +                (void) priv_set(PRIV_ON, PRIV_EFFECTIVE,
      562 +                    PRIV_FILE_DAC_READ,
      563 +                    PRIV_FILE_DAC_SEARCH,
      564 +                    PRIV_FILE_DAC_WRITE,
      565 +                    NULL);
      566 +
      567 +                smb_shr_zfs_remove(si);
      568 +
      569 +                (void) priv_set(PRIV_OFF, PRIV_EFFECTIVE,
      570 +                    PRIV_FILE_DAC_READ,
      571 +                    PRIV_FILE_DAC_SEARCH,
      572 +                    PRIV_FILE_DAC_WRITE,
      573 +                    NULL);
      574 +
      575 +                smb_proc_givesem();
      576 +        }
      577 +
 511  578          (void) smb_shr_encode(si, &shrlist);
 512  579  
 513  580          (void) strlcpy(container, si->shr_container, sizeof (container));
 514  581          dfsroot = ((si->shr_flags & SMB_SHRF_DFSROOT) != 0);
 515  582          smb_shr_cache_delent(sharename);
 516  583          smb_shr_cache_unlock();
 517  584  
 518  585          smb_shr_unpublish(sharename, container);
 519  586  
 520  587          /* call kernel to release the hold on the shared file system */
↓ open down ↓ 42 lines elided ↑ open up ↑
 563  630          }
 564  631  
 565  632          if (smb_shr_cache_findent(to_name) != NULL) {
 566  633                  smb_shr_cache_unlock();
 567  634                  return (NERR_DuplicateShare);
 568  635          }
 569  636  
 570  637          bcopy(from_si, &to_si, sizeof (smb_share_t));
 571  638          (void) strlcpy(to_si.shr_name, to_name, sizeof (to_si.shr_name));
 572  639  
 573      -
 574  640          /* If path is ZFS, rename the .zfs/shares/<share> entry. */
 575      -        smb_shr_zfs_rename(from_si, &to_si);
      641 +        if (smb_proc_takesem() == 0) {
 576  642  
      643 +                (void) priv_set(PRIV_ON, PRIV_EFFECTIVE,
      644 +                    PRIV_FILE_DAC_READ,
      645 +                    PRIV_FILE_DAC_SEARCH,
      646 +                    PRIV_FILE_DAC_WRITE,
      647 +                    NULL);
      648 +
      649 +                smb_shr_zfs_rename(from_si, &to_si);
      650 +
      651 +                (void) priv_set(PRIV_OFF, PRIV_EFFECTIVE,
      652 +                    PRIV_FILE_DAC_READ,
      653 +                    PRIV_FILE_DAC_SEARCH,
      654 +                    PRIV_FILE_DAC_WRITE,
      655 +                    NULL);
      656 +
      657 +                smb_proc_givesem();
      658 +        }
      659 +
 577  660          if ((status = smb_shr_cache_addent(&to_si)) != NERR_Success) {
 578  661                  smb_shr_cache_unlock();
 579  662                  return (status);
 580  663          }
 581  664  
 582  665          smb_shr_cache_delent(from_name);
 583  666          smb_shr_cache_unlock();
 584  667  
 585  668          if (smb_shr_encode(from_si, &shrlist) == 0) {
 586  669                  (void) smb_kmod_unshare(shrlist);
↓ open down ↓ 34 lines elided ↑ open up ↑
 621  704  
 622  705          return (status);
 623  706  }
 624  707  
 625  708  /*
 626  709   * Modifies an existing share. Properties that can be modified are:
 627  710   *
 628  711   *   o comment
 629  712   *   o AD container
 630  713   *   o host access
 631      - *   o abe
      714 + *   o flags
 632  715   */
 633  716  uint32_t
 634  717  smb_shr_modify(smb_share_t *new_si)
 635  718  {
      719 +        smb_share_t old_si;
 636  720          smb_share_t *si;
 637  721          boolean_t adc_changed = B_FALSE;
 638      -        char old_container[MAXPATHLEN];
      722 +        boolean_t quota_flag_changed = B_FALSE;
 639  723          uint32_t access, flag;
 640  724          nvlist_t *shrlist;
 641  725  
 642  726          assert(new_si != NULL);
 643  727  
 644  728          if (smb_shr_cache_lock(SMB_SHR_CACHE_WRLOCK) != NERR_Success)
 645  729                  return (NERR_InternalError);
 646  730  
 647  731          if ((si = smb_shr_cache_findent(new_si->shr_name)) == NULL) {
 648  732                  smb_shr_cache_unlock();
 649  733                  return (NERR_NetNameNotFound);
 650  734          }
 651  735  
 652  736          if (STYPE_ISIPC(si->shr_type)) {
 653  737                  /* IPC$ share cannot be modified */
 654  738                  smb_shr_cache_unlock();
 655  739                  return (ERROR_ACCESS_DENIED);
 656  740          }
 657  741  
      742 +        /*
      743 +         * Keep a copy of what the share entry looks like before we
      744 +         * modify it.  We need this for things like unpublishing
      745 +         * from the old share container, removing the quota dir.
      746 +         */
      747 +        bcopy(si, &old_si, sizeof (old_si));
      748 +
      749 +        /* Share comment */
 658  750          (void) strlcpy(si->shr_cmnt, new_si->shr_cmnt, sizeof (si->shr_cmnt));
 659  751  
 660      -        adc_changed = (strcmp(new_si->shr_container, si->shr_container) != 0);
 661      -        if (adc_changed) {
 662      -                /* save current container - needed for unpublishing */
 663      -                (void) strlcpy(old_container, si->shr_container,
 664      -                    sizeof (old_container));
 665      -                (void) strlcpy(si->shr_container, new_si->shr_container,
 666      -                    sizeof (si->shr_container));
 667      -        }
      752 +        /* Container */
      753 +        (void) strlcpy(si->shr_container, new_si->shr_container,
      754 +            sizeof (si->shr_container));
      755 +        adc_changed = (strcmp(old_si.shr_container, si->shr_container) != 0);
 668  756  
 669  757          flag = (new_si->shr_flags & SMB_SHRF_ABE);
 670  758          si->shr_flags &= ~SMB_SHRF_ABE;
 671  759          si->shr_flags |= flag;
 672  760  
 673  761          flag = (new_si->shr_flags & SMB_SHRF_CATIA);
 674  762          si->shr_flags &= ~SMB_SHRF_CATIA;
 675  763          si->shr_flags |= flag;
 676  764  
 677  765          flag = (new_si->shr_flags & SMB_SHRF_GUEST_OK);
 678  766          si->shr_flags &= ~SMB_SHRF_GUEST_OK;
 679  767          si->shr_flags |= flag;
 680  768  
 681  769          flag = (new_si->shr_flags & SMB_SHRF_DFSROOT);
 682  770          si->shr_flags &= ~SMB_SHRF_DFSROOT;
 683  771          si->shr_flags |= flag;
 684  772  
      773 +        flag = (new_si->shr_flags & SMB_SHRF_CA);
      774 +        si->shr_flags &= ~SMB_SHRF_CA;
      775 +        si->shr_flags |= flag;
      776 +
      777 +        flag = (new_si->shr_flags & SMB_SHRF_FSO);
      778 +        si->shr_flags &= ~SMB_SHRF_FSO;
      779 +        si->shr_flags |= flag;
      780 +
      781 +        flag = (new_si->shr_flags & SMB_SHRF_QUOTAS);
      782 +        si->shr_flags &= ~SMB_SHRF_QUOTAS;
      783 +        si->shr_flags |= flag;
      784 +        if ((old_si.shr_flags ^ si->shr_flags) & SMB_SHRF_QUOTAS)
      785 +                quota_flag_changed = B_TRUE;
      786 +
 685  787          flag = (new_si->shr_flags & SMB_SHRF_CSC_MASK);
 686  788          si->shr_flags &= ~SMB_SHRF_CSC_MASK;
 687  789          si->shr_flags |= flag;
 688  790  
 689  791          access = (new_si->shr_flags & SMB_SHRF_ACC_ALL);
 690  792          si->shr_flags &= ~SMB_SHRF_ACC_ALL;
 691  793          si->shr_flags |= access;
 692  794  
      795 +        si->shr_encrypt = new_si->shr_encrypt;
      796 +
 693  797          if (access & SMB_SHRF_ACC_NONE)
 694  798                  (void) strlcpy(si->shr_access_none, new_si->shr_access_none,
 695  799                      sizeof (si->shr_access_none));
 696  800  
 697  801          if (access & SMB_SHRF_ACC_RO)
 698  802                  (void) strlcpy(si->shr_access_ro, new_si->shr_access_ro,
 699  803                      sizeof (si->shr_access_ro));
 700  804  
 701  805          if (access & SMB_SHRF_ACC_RW)
 702  806                  (void) strlcpy(si->shr_access_rw, new_si->shr_access_rw,
↓ open down ↓ 5 lines elided ↑ open up ↑
 708  812                  (void) smb_kmod_unshare(shrlist);
 709  813                  nvlist_free(shrlist);
 710  814  
 711  815                  if (smb_shr_encode(new_si, &shrlist) == 0) {
 712  816                          (void) smb_kmod_share(shrlist);
 713  817                          nvlist_free(shrlist);
 714  818                  }
 715  819          }
 716  820  
 717  821          if (adc_changed) {
 718      -                smb_shr_unpublish(new_si->shr_name, old_container);
      822 +                smb_shr_unpublish(old_si.shr_name, old_si.shr_container);
 719  823                  smb_shr_publish(new_si->shr_name, new_si->shr_container);
 720  824          }
 721  825  
      826 +        /* The following required privileges we dropped. */
      827 +        if (quota_flag_changed && smb_proc_takesem() == 0) {
      828 +
      829 +                (void) priv_set(PRIV_ON, PRIV_EFFECTIVE,
      830 +                    PRIV_FILE_DAC_READ,
      831 +                    PRIV_FILE_DAC_SEARCH,
      832 +                    PRIV_FILE_DAC_WRITE,
      833 +                    NULL);
      834 +
      835 +                smb_shr_zfs_remove(&old_si);
      836 +                smb_shr_zfs_add(si);
      837 +
      838 +                (void) priv_set(PRIV_OFF, PRIV_EFFECTIVE,
      839 +                    PRIV_FILE_DAC_READ,
      840 +                    PRIV_FILE_DAC_SEARCH,
      841 +                    PRIV_FILE_DAC_WRITE,
      842 +                    NULL);
      843 +
      844 +                smb_proc_givesem();
      845 +        }
      846 +
 722  847          return (NERR_Success);
 723  848  }
 724  849  
 725  850  /*
 726  851   * smb_shr_exists
 727  852   *
 728  853   * Returns B_TRUE if the share exists. Otherwise returns B_FALSE
 729  854   */
 730  855  boolean_t
 731  856  smb_shr_exists(char *sharename)
↓ open down ↓ 697 lines elided ↑ open up ↑
1429 1554  
1430 1555  /*
1431 1556   * ============================================
1432 1557   * Interfaces to sharemgr
1433 1558   *
1434 1559   * All functions in this section are private
1435 1560   * ============================================
1436 1561   */
1437 1562  
1438 1563  /*
1439      - * Load shares from sharemgr
     1564 + * Loads the SMB shares, from sharemgr, then:
     1565 + *     - calls smb_shr_add which:
     1566 + *         - adds the share into the share cache
     1567 + *         - adds the share into in-kernel kshare table
     1568 + *         - publishes the share in ADS
     1569 + *     - updates the share list in sharefs/sharetab
1440 1570   */
1441 1571  /*ARGSUSED*/
1442 1572  void *
1443 1573  smb_shr_load(void *args)
1444 1574  {
1445 1575          sa_handle_t handle;
1446 1576          sa_group_t group, subgroup;
1447 1577          char *gstate;
1448 1578          boolean_t gdisabled;
1449 1579  
1450      -        (void) mutex_lock(&smb_shr_exec_mtx);
1451      -        (void) smb_config_get_execinfo(smb_shr_exec_map, smb_shr_exec_unmap,
1452      -            MAXPATHLEN);
1453      -        (void) mutex_unlock(&smb_shr_exec_mtx);
     1580 +        smb_shr_load_execinfo();
1454 1581  
1455 1582          if ((handle = smb_shr_sa_enter()) == NULL) {
1456 1583                  syslog(LOG_ERR, "smb_shr_load: load failed");
1457 1584                  return (NULL);
1458 1585          }
1459 1586  
1460 1587          for (group = sa_get_group(handle, NULL);
1461 1588              group != NULL; group = sa_get_next_group(group)) {
1462 1589                  gstate = sa_get_group_attr(group, "state");
1463 1590                  if (gstate == NULL)
↓ open down ↓ 10 lines elided ↑ open up ↑
1474 1601                      subgroup != NULL;
1475 1602                      subgroup = sa_get_next_group(subgroup)) {
1476 1603                          smb_shr_sa_loadgrp(subgroup);
1477 1604                  }
1478 1605  
1479 1606          }
1480 1607          smb_shr_sa_exit();
1481 1608          return (NULL);
1482 1609  }
1483 1610  
     1611 +void
     1612 +smb_shr_load_execinfo()
     1613 +{
     1614 +        (void) mutex_lock(&smb_shr_exec_mtx);
     1615 +        (void) smb_config_get_execinfo(smb_shr_exec_map, smb_shr_exec_unmap,
     1616 +            MAXPATHLEN);
     1617 +        (void) mutex_unlock(&smb_shr_exec_mtx);
     1618 +}
     1619 +
1484 1620  /*
     1621 + * Handles disabling shares in sharefs when stoping smbd
     1622 + */
     1623 +void
     1624 +smb_shr_unload()
     1625 +{
     1626 +        smb_shriter_t iterator;
     1627 +        smb_share_t *si;
     1628 +        sa_handle_t handle;
     1629 +        int rc;
     1630 +
     1631 +        if ((handle = smb_shr_sa_enter()) == NULL) {
     1632 +                syslog(LOG_ERR, "smb_shr_unload: failed");
     1633 +                return;
     1634 +        }
     1635 +
     1636 +        smb_shr_iterinit(&iterator);
     1637 +
     1638 +        while ((si = smb_shr_iterate(&iterator)) != NULL) {
     1639 +
     1640 +                /* Skip transient shares, IPC$, ... */
     1641 +                if ((si->shr_flags & SMB_SHRF_TRANS) ||
     1642 +                    STYPE_ISIPC(si->shr_type))
     1643 +                        continue;
     1644 +
     1645 +                rc = sa_delete_sharetab(handle, si->shr_path, "smb");
     1646 +                if (rc) {
     1647 +                        syslog(LOG_ERR,
     1648 +                            "sharefs remove %s failed, rc=%d, err=%d",
     1649 +                            si->shr_path, rc, errno);
     1650 +                }
     1651 +        }
     1652 +        smb_shr_sa_exit();
     1653 +}
     1654 +
     1655 +/*
1485 1656   * Load the shares contained in the specified group.
1486 1657   *
1487 1658   * Don't process groups on which the smb protocol is disabled.
1488 1659   * The top level ZFS group won't have the smb protocol enabled
1489 1660   * but sub-groups will.
1490 1661   *
1491 1662   * We will tolerate a limited number of errors and then give
1492 1663   * up on the current group.  A typical error might be that the
1493 1664   * shared directory no longer exists.
1494 1665   */
↓ open down ↓ 33 lines elided ↑ open up ↑
1528 1699   * a share might have been added by smb_shr_get() while load is
1529 1700   * in progress.
1530 1701   */
1531 1702  static uint32_t
1532 1703  smb_shr_sa_load(sa_share_t share, sa_resource_t resource)
1533 1704  {
1534 1705          smb_share_t si;
1535 1706          char *sharename;
1536 1707          uint32_t status;
1537 1708          boolean_t loaded;
     1709 +        int rc;
1538 1710  
1539 1711          if ((sharename = sa_get_resource_attr(resource, "name")) == NULL)
1540 1712                  return (NERR_InternalError);
1541 1713  
1542 1714          loaded = smb_shr_exists(sharename);
1543 1715          sa_free_attr_string(sharename);
1544 1716  
1545 1717          if (loaded)
1546 1718                  return (NERR_Success);
1547 1719  
↓ open down ↓ 3 lines elided ↑ open up ↑
1551 1723                  return (status);
1552 1724          }
1553 1725  
1554 1726          status = smb_shr_add(&si);
1555 1727          if ((status != NERR_Success) && (status != NERR_DuplicateShare)) {
1556 1728                  syslog(LOG_DEBUG, "share: failed to cache %s (%d)",
1557 1729                      si.shr_name, status);
1558 1730                  return (status);
1559 1731          }
1560 1732  
     1733 +        rc = sa_update_sharetab(share, "smb");
     1734 +        if (rc) {
     1735 +                syslog(LOG_ERR, "sharefs add %s failed, rc=%d, err=%d",
     1736 +                    sharename, rc, errno);
     1737 +        }
     1738 +
1561 1739          return (NERR_Success);
1562 1740  }
1563 1741  
1564 1742  static char *
1565 1743  smb_shr_sa_getprop(sa_optionset_t opts, char *propname)
1566 1744  {
1567 1745          sa_property_t prop;
1568 1746          char *val = NULL;
1569 1747  
1570 1748          prop = sa_get_property(opts, propname);
↓ open down ↓ 70 lines elided ↑ open up ↑
1641 1819                  smb_shr_sa_setflag(val, si, SMB_SHRF_GUEST_OK);
1642 1820                  free(val);
1643 1821          }
1644 1822  
1645 1823          val = smb_shr_sa_getprop(opts, SHOPT_DFSROOT);
1646 1824          if (val != NULL) {
1647 1825                  smb_shr_sa_setflag(val, si, SMB_SHRF_DFSROOT);
1648 1826                  free(val);
1649 1827          }
1650 1828  
     1829 +        val = smb_shr_sa_getprop(opts, SHOPT_CA);
     1830 +        if (val != NULL) {
     1831 +                smb_shr_sa_setflag(val, si, SMB_SHRF_CA);
     1832 +                free(val);
     1833 +        }
     1834 +
     1835 +        val = smb_shr_sa_getprop(opts, SHOPT_FSO);
     1836 +        if (val != NULL) {
     1837 +                smb_shr_sa_setflag(val, si, SMB_SHRF_FSO);
     1838 +                free(val);
     1839 +        }
     1840 +
     1841 +        val = smb_shr_sa_getprop(opts, SHOPT_QUOTAS);
     1842 +        if (val != NULL) {
     1843 +                /* Turn the flag on or off */
     1844 +                smb_shr_sa_setflag(val, si, SMB_SHRF_QUOTAS);
     1845 +                free(val);
     1846 +        } else {
     1847 +                /* Default for this is enabled. */
     1848 +                si->shr_flags |= SMB_SHRF_QUOTAS;
     1849 +        }
     1850 +
     1851 +        val = smb_shr_sa_getprop(opts, SHOPT_ENCRYPT);
     1852 +        if (val != NULL) {
     1853 +                smb_cfg_set_require(val, &si->shr_encrypt);
     1854 +                free(val);
     1855 +        }
     1856 +
1651 1857          val = smb_shr_sa_getprop(opts, SHOPT_CSC);
1652 1858          if (val != NULL) {
1653 1859                  smb_shr_sa_csc_option(val, si);
1654 1860                  free(val);
1655 1861          }
1656 1862  
1657 1863          val = smb_shr_sa_getprop(opts, SHOPT_NONE);
1658 1864          if (val != NULL) {
1659 1865                  (void) strlcpy(si->shr_access_none, val,
1660 1866                      sizeof (si->shr_access_none));
↓ open down ↓ 355 lines elided ↑ open up ↑
2016 2222          smb_shr_pitem_t *shr;
2017 2223  
2018 2224          while ((shr = list_head(lst)) != NULL) {
2019 2225                  list_remove(lst, shr);
2020 2226                  free(shr);
2021 2227          }
2022 2228  }
2023 2229  
2024 2230  /*
2025 2231   * If the share path refers to a ZFS file system, add the
2026      - * .zfs/shares/<share> object and call smb_quota_add_fs()
2027      - * to initialize quota support for the share.
     2232 + * .zfs/shares/<share> object and add or remove the special
     2233 + * directory and file telling clients about quota support.
2028 2234   */
2029 2235  static void
2030 2236  smb_shr_zfs_add(smb_share_t *si)
2031 2237  {
2032 2238          libzfs_handle_t *libhd;
2033 2239          zfs_handle_t *zfshd;
2034 2240          int ret;
2035 2241          char buf[MAXPATHLEN];   /* dataset or mountpoint */
2036 2242  
2037      -        if (smb_getdataset(si->shr_path, buf, MAXPATHLEN) != 0)
     2243 +        if ((libhd = libzfs_init()) == NULL)
2038 2244                  return;
2039 2245  
2040      -        if ((libhd = libzfs_init()) == NULL)
     2246 +        if (smb_getdataset(libhd, si->shr_path, buf, MAXPATHLEN) != 0) {
     2247 +                libzfs_fini(libhd);
2041 2248                  return;
     2249 +        }
2042 2250  
2043 2251          if ((zfshd = zfs_open(libhd, buf, ZFS_TYPE_FILESYSTEM)) == NULL) {
2044 2252                  libzfs_fini(libhd);
2045 2253                  return;
2046 2254          }
2047 2255  
2048 2256          errno = 0;
2049 2257          ret = zfs_smb_acl_add(libhd, buf, si->shr_path, si->shr_name);
2050 2258          if (ret != 0 && errno != EAGAIN && errno != EEXIST)
2051 2259                  syslog(LOG_INFO, "share: failed to add ACL object: %s: %s\n",
2052 2260                      si->shr_name, strerror(errno));
2053 2261  
2054      -        if (zfs_prop_get(zfshd, ZFS_PROP_MOUNTPOINT, buf, MAXPATHLEN,
2055      -            NULL, NULL, 0, B_FALSE) == 0) {
2056      -                smb_quota_add_fs(buf);
     2262 +        ret = zfs_prop_get(zfshd, ZFS_PROP_MOUNTPOINT,
     2263 +            buf, MAXPATHLEN, NULL, NULL, 0, B_FALSE);
     2264 +        if (ret != 0) {
     2265 +                syslog(LOG_INFO, "share: failed to get mountpoint: "
     2266 +                    "%s\n", si->shr_name);
     2267 +        } else {
     2268 +                if ((si->shr_flags & SMB_SHRF_QUOTAS) != 0) {
     2269 +                        smb_quota_add_fs(buf);
     2270 +                } else {
     2271 +                        smb_quota_remove_fs(buf);
     2272 +                }
2057 2273          }
2058 2274  
2059      -
2060 2275          zfs_close(zfshd);
2061 2276          libzfs_fini(libhd);
2062 2277  }
2063 2278  
2064 2279  /*
2065 2280   * If the share path refers to a ZFS file system, remove the
2066      - * .zfs/shares/<share> object, and call smb_quota_remove_fs()
2067      - * to end quota support for the share.
     2281 + * .zfs/shares/<share> object.
2068 2282   */
2069 2283  static void
2070 2284  smb_shr_zfs_remove(smb_share_t *si)
2071 2285  {
2072 2286          libzfs_handle_t *libhd;
2073      -        zfs_handle_t *zfshd;
2074 2287          int ret;
2075 2288          char buf[MAXPATHLEN];   /* dataset or mountpoint */
2076 2289  
2077      -        if (smb_getdataset(si->shr_path, buf, MAXPATHLEN) != 0)
2078      -                return;
2079      -
2080 2290          if ((libhd = libzfs_init()) == NULL)
2081 2291                  return;
2082 2292  
2083      -        if ((zfshd = zfs_open(libhd, buf, ZFS_TYPE_FILESYSTEM)) == NULL) {
     2293 +        if (smb_getdataset(libhd, si->shr_path, buf, MAXPATHLEN) != 0) {
2084 2294                  libzfs_fini(libhd);
2085 2295                  return;
2086 2296          }
2087 2297  
2088 2298          errno = 0;
2089 2299          ret = zfs_smb_acl_remove(libhd, buf, si->shr_path, si->shr_name);
2090 2300          if (ret != 0 && errno != EAGAIN)
2091 2301                  syslog(LOG_INFO, "share: failed to remove ACL object: %s: %s\n",
2092 2302                      si->shr_name, strerror(errno));
2093 2303  
2094      -        if (zfs_prop_get(zfshd, ZFS_PROP_MOUNTPOINT, buf, MAXPATHLEN,
2095      -            NULL, NULL, 0, B_FALSE) == 0) {
2096      -                smb_quota_remove_fs(buf);
2097      -        }
     2304 +        /*
     2305 +         * We could remove the quotas directory here, but that adds
     2306 +         * significantly to the time required for a zpool export,
     2307 +         * so just leave it here and fixup when we share next.
     2308 +         */
2098 2309  
2099      -        zfs_close(zfshd);
2100 2310          libzfs_fini(libhd);
2101 2311  }
2102 2312  
2103 2313  /*
2104 2314   * If the share path refers to a ZFS file system, rename the
2105 2315   * .zfs/shares/<share> object.
2106 2316   */
2107 2317  static void
2108 2318  smb_shr_zfs_rename(smb_share_t *from, smb_share_t *to)
2109 2319  {
2110 2320          libzfs_handle_t *libhd;
2111 2321          zfs_handle_t *zfshd;
2112 2322          int ret;
2113 2323          char dataset[MAXPATHLEN];
2114 2324  
2115      -        if (smb_getdataset(from->shr_path, dataset, MAXPATHLEN) != 0)
     2325 +        if ((libhd = libzfs_init()) == NULL)
2116 2326                  return;
2117 2327  
2118      -        if ((libhd = libzfs_init()) == NULL)
     2328 +        if (smb_getdataset(libhd, from->shr_path, dataset, MAXPATHLEN) != 0) {
     2329 +                libzfs_fini(libhd);
2119 2330                  return;
     2331 +        }
2120 2332  
2121 2333          if ((zfshd = zfs_open(libhd, dataset, ZFS_TYPE_FILESYSTEM)) == NULL) {
2122 2334                  libzfs_fini(libhd);
2123 2335                  return;
2124 2336          }
2125 2337  
2126 2338          errno = 0;
2127 2339          ret = zfs_smb_acl_rename(libhd, dataset, from->shr_path,
2128 2340              from->shr_name, to->shr_name);
2129 2341          if (ret != 0 && errno != EAGAIN)
↓ open down ↓ 278 lines elided ↑ open up ↑
2408 2620                  rc |= nvlist_add_string(smb, SHOPT_RW, si->shr_access_rw);
2409 2621  
2410 2622          if ((si->shr_flags & SMB_SHRF_ABE) != 0)
2411 2623                  rc |= nvlist_add_string(smb, SHOPT_ABE, "true");
2412 2624          if ((si->shr_flags & SMB_SHRF_CATIA) != 0)
2413 2625                  rc |= nvlist_add_string(smb, SHOPT_CATIA, "true");
2414 2626          if ((si->shr_flags & SMB_SHRF_GUEST_OK) != 0)
2415 2627                  rc |= nvlist_add_string(smb, SHOPT_GUEST, "true");
2416 2628          if ((si->shr_flags & SMB_SHRF_DFSROOT) != 0)
2417 2629                  rc |= nvlist_add_string(smb, SHOPT_DFSROOT, "true");
     2630 +        if ((si->shr_flags & SMB_SHRF_CA) != 0)
     2631 +                rc |= nvlist_add_string(smb, SHOPT_CA, "true");
     2632 +        if ((si->shr_flags & SMB_SHRF_FSO) != 0)
     2633 +                rc |= nvlist_add_string(smb, SHOPT_FSO, "true");
     2634 +        if ((si->shr_flags & SMB_SHRF_QUOTAS) != 0)
     2635 +                rc |= nvlist_add_string(smb, SHOPT_QUOTAS, "true");
2418 2636  
     2637 +        if (si->shr_encrypt == SMB_CONFIG_REQUIRED)
     2638 +                rc |= nvlist_add_string(smb, SHOPT_ENCRYPT, "required");
     2639 +        else if (si->shr_encrypt == SMB_CONFIG_ENABLED)
     2640 +                rc |= nvlist_add_string(smb, SHOPT_ENCRYPT, "enabled");
     2641 +        else
     2642 +                rc |= nvlist_add_string(smb, SHOPT_ENCRYPT, "disabled");
     2643 +
2419 2644          if ((si->shr_flags & SMB_SHRF_AUTOHOME) != 0) {
2420      -                rc |= nvlist_add_string(smb, "Autohome", "true");
     2645 +                rc |= nvlist_add_string(smb, SHOPT_AUTOHOME, "true");
2421 2646                  rc |= nvlist_add_uint32(smb, "uid", si->shr_uid);
2422 2647                  rc |= nvlist_add_uint32(smb, "gid", si->shr_gid);
2423 2648          }
2424 2649  
2425 2650          if ((csc = smb_shr_sa_csc_name(si)) != NULL)
2426 2651                  rc |= nvlist_add_string(smb, SHOPT_CSC, csc);
2427 2652  
2428 2653          rc |= nvlist_add_uint32(smb, "type", si->shr_type);
2429 2654  
2430 2655          rc |= nvlist_add_nvlist(share, "smb", smb);
↓ open down ↓ 12 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX