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
*** 17,27 ****
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*
* Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
! * Copyright 2015 Nexenta Systems, Inc. All rights reserved.
*/
/*
* SMB/CIFS share cache implementation.
*/
--- 17,27 ----
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*
* Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
! * Copyright 2018 Nexenta Systems, Inc. All rights reserved.
*/
/*
* SMB/CIFS share cache implementation.
*/
*** 387,396 ****
--- 387,397 ----
smb_shr_add(smb_share_t *si)
{
struct stat st;
smb_share_t *cached_si;
nvlist_t *shrlist;
+ boolean_t created_zfs = B_FALSE;
uint32_t status;
int rc;
assert(si != NULL);
*** 414,432 ****
--- 415,460 ----
if (STYPE_ISDSK(si->shr_type)) {
/*
* If share type is STYPE_DISKTREE then the path to the
* share should exist so that we can add the share to cache.
+ * If path is ZFS, add the .zfs/shares/<share> entry.
+ *
+ * Both actions may require privileges that main dropped,
+ * so we need to temporarily make those effective.
*/
+ if (smb_proc_takesem() == 0) {
+
+ (void) priv_set(PRIV_ON, PRIV_EFFECTIVE,
+ PRIV_FILE_DAC_READ,
+ PRIV_FILE_DAC_SEARCH,
+ PRIV_FILE_DAC_WRITE,
+ NULL);
+
rc = stat(si->shr_path, &st);
+ if (rc == 0) {
+ smb_shr_zfs_add(si);
+ created_zfs = B_TRUE;
+ }
+
+ (void) priv_set(PRIV_OFF, PRIV_EFFECTIVE,
+ PRIV_FILE_DAC_READ,
+ PRIV_FILE_DAC_SEARCH,
+ PRIV_FILE_DAC_WRITE,
+ NULL);
+ smb_proc_givesem();
+ } else {
+ rc = NERR_InternalError;
+ }
if (rc != 0) {
smb_shr_cache_unlock();
return (NERR_ItemNotFound);
}
}
if ((status = smb_shr_cache_addent(si)) != NERR_Success) {
+ /* This error should be impossible after findent above. */
smb_shr_cache_unlock();
return (status);
}
/* don't hold the lock across door call */
*** 438,462 ****
nvlist_free(shrlist);
if (rc == 0) {
smb_shr_publish(si->shr_name, si->shr_container);
- /* If path is ZFS, add the .zfs/shares/<share> entry. */
- smb_shr_zfs_add(si);
-
if ((si->shr_flags & SMB_SHRF_DFSROOT) != 0)
dfs_namespace_load(si->shr_name);
return (NERR_Success);
}
}
if (smb_shr_cache_lock(SMB_SHR_CACHE_WRLOCK) == NERR_Success) {
smb_shr_cache_delent(si->shr_name);
smb_shr_cache_unlock();
}
/*
* rc == ENOENT means the shared directory doesn't exist
*/
return ((rc == ENOENT) ? NERR_UnknownDevDir : NERR_InternalError);
}
--- 466,510 ----
nvlist_free(shrlist);
if (rc == 0) {
smb_shr_publish(si->shr_name, si->shr_container);
if ((si->shr_flags & SMB_SHRF_DFSROOT) != 0)
dfs_namespace_load(si->shr_name);
return (NERR_Success);
}
}
+ /*
+ * Error code path, i.e. when the kernel could not accept
+ * the new share for some reason.
+ */
if (smb_shr_cache_lock(SMB_SHR_CACHE_WRLOCK) == NERR_Success) {
smb_shr_cache_delent(si->shr_name);
smb_shr_cache_unlock();
}
+ if (created_zfs && smb_proc_takesem() == 0) {
+
+ (void) priv_set(PRIV_ON, PRIV_EFFECTIVE,
+ PRIV_FILE_DAC_READ,
+ PRIV_FILE_DAC_SEARCH,
+ PRIV_FILE_DAC_WRITE,
+ NULL);
+
+ smb_shr_zfs_remove(si);
+
+ (void) priv_set(PRIV_OFF, PRIV_EFFECTIVE,
+ PRIV_FILE_DAC_READ,
+ PRIV_FILE_DAC_SEARCH,
+ PRIV_FILE_DAC_WRITE,
+ NULL);
+
+ smb_proc_givesem();
+ }
+
/*
* rc == ENOENT means the shared directory doesn't exist
*/
return ((rc == ENOENT) ? NERR_UnknownDevDir : NERR_InternalError);
}
*** 503,515 ****
}
}
/*
* If path is ZFS, remove the .zfs/shares/<share> entry. Need
! * to remove before cleanup of cache occurs.
*/
smb_shr_zfs_remove(si);
(void) smb_shr_encode(si, &shrlist);
(void) strlcpy(container, si->shr_container, sizeof (container));
dfsroot = ((si->shr_flags & SMB_SHRF_DFSROOT) != 0);
smb_shr_cache_delent(sharename);
--- 551,582 ----
}
}
/*
* If path is ZFS, remove the .zfs/shares/<share> entry. Need
! * to remove before cleanup of cache occurs. These actions
! * require temporary elevation of privileges.
*/
+ if (smb_proc_takesem() == 0) {
+
+ (void) priv_set(PRIV_ON, PRIV_EFFECTIVE,
+ PRIV_FILE_DAC_READ,
+ PRIV_FILE_DAC_SEARCH,
+ PRIV_FILE_DAC_WRITE,
+ NULL);
+
smb_shr_zfs_remove(si);
+
+ (void) priv_set(PRIV_OFF, PRIV_EFFECTIVE,
+ PRIV_FILE_DAC_READ,
+ PRIV_FILE_DAC_SEARCH,
+ PRIV_FILE_DAC_WRITE,
+ NULL);
+
+ smb_proc_givesem();
+ }
+
(void) smb_shr_encode(si, &shrlist);
(void) strlcpy(container, si->shr_container, sizeof (container));
dfsroot = ((si->shr_flags & SMB_SHRF_DFSROOT) != 0);
smb_shr_cache_delent(sharename);
*** 568,581 ****
}
bcopy(from_si, &to_si, sizeof (smb_share_t));
(void) strlcpy(to_si.shr_name, to_name, sizeof (to_si.shr_name));
-
/* If path is ZFS, rename the .zfs/shares/<share> entry. */
smb_shr_zfs_rename(from_si, &to_si);
if ((status = smb_shr_cache_addent(&to_si)) != NERR_Success) {
smb_shr_cache_unlock();
return (status);
}
--- 635,664 ----
}
bcopy(from_si, &to_si, sizeof (smb_share_t));
(void) strlcpy(to_si.shr_name, to_name, sizeof (to_si.shr_name));
/* If path is ZFS, rename the .zfs/shares/<share> entry. */
+ if (smb_proc_takesem() == 0) {
+
+ (void) priv_set(PRIV_ON, PRIV_EFFECTIVE,
+ PRIV_FILE_DAC_READ,
+ PRIV_FILE_DAC_SEARCH,
+ PRIV_FILE_DAC_WRITE,
+ NULL);
+
smb_shr_zfs_rename(from_si, &to_si);
+ (void) priv_set(PRIV_OFF, PRIV_EFFECTIVE,
+ PRIV_FILE_DAC_READ,
+ PRIV_FILE_DAC_SEARCH,
+ PRIV_FILE_DAC_WRITE,
+ NULL);
+
+ smb_proc_givesem();
+ }
+
if ((status = smb_shr_cache_addent(&to_si)) != NERR_Success) {
smb_shr_cache_unlock();
return (status);
}
*** 626,643 ****
* Modifies an existing share. Properties that can be modified are:
*
* o comment
* o AD container
* o host access
! * o abe
*/
uint32_t
smb_shr_modify(smb_share_t *new_si)
{
smb_share_t *si;
boolean_t adc_changed = B_FALSE;
! char old_container[MAXPATHLEN];
uint32_t access, flag;
nvlist_t *shrlist;
assert(new_si != NULL);
--- 709,727 ----
* Modifies an existing share. Properties that can be modified are:
*
* o comment
* o AD container
* o host access
! * o flags
*/
uint32_t
smb_shr_modify(smb_share_t *new_si)
{
+ smb_share_t old_si;
smb_share_t *si;
boolean_t adc_changed = B_FALSE;
! boolean_t quota_flag_changed = B_FALSE;
uint32_t access, flag;
nvlist_t *shrlist;
assert(new_si != NULL);
*** 653,672 ****
/* IPC$ share cannot be modified */
smb_shr_cache_unlock();
return (ERROR_ACCESS_DENIED);
}
(void) strlcpy(si->shr_cmnt, new_si->shr_cmnt, sizeof (si->shr_cmnt));
! adc_changed = (strcmp(new_si->shr_container, si->shr_container) != 0);
! if (adc_changed) {
! /* save current container - needed for unpublishing */
! (void) strlcpy(old_container, si->shr_container,
! sizeof (old_container));
(void) strlcpy(si->shr_container, new_si->shr_container,
sizeof (si->shr_container));
! }
flag = (new_si->shr_flags & SMB_SHRF_ABE);
si->shr_flags &= ~SMB_SHRF_ABE;
si->shr_flags |= flag;
--- 737,760 ----
/* IPC$ share cannot be modified */
smb_shr_cache_unlock();
return (ERROR_ACCESS_DENIED);
}
+ /*
+ * Keep a copy of what the share entry looks like before we
+ * modify it. We need this for things like unpublishing
+ * from the old share container, removing the quota dir.
+ */
+ bcopy(si, &old_si, sizeof (old_si));
+
+ /* Share comment */
(void) strlcpy(si->shr_cmnt, new_si->shr_cmnt, sizeof (si->shr_cmnt));
! /* Container */
(void) strlcpy(si->shr_container, new_si->shr_container,
sizeof (si->shr_container));
! adc_changed = (strcmp(old_si.shr_container, si->shr_container) != 0);
flag = (new_si->shr_flags & SMB_SHRF_ABE);
si->shr_flags &= ~SMB_SHRF_ABE;
si->shr_flags |= flag;
*** 680,697 ****
--- 768,801 ----
flag = (new_si->shr_flags & SMB_SHRF_DFSROOT);
si->shr_flags &= ~SMB_SHRF_DFSROOT;
si->shr_flags |= flag;
+ flag = (new_si->shr_flags & SMB_SHRF_CA);
+ si->shr_flags &= ~SMB_SHRF_CA;
+ si->shr_flags |= flag;
+
+ flag = (new_si->shr_flags & SMB_SHRF_FSO);
+ si->shr_flags &= ~SMB_SHRF_FSO;
+ si->shr_flags |= flag;
+
+ flag = (new_si->shr_flags & SMB_SHRF_QUOTAS);
+ si->shr_flags &= ~SMB_SHRF_QUOTAS;
+ si->shr_flags |= flag;
+ if ((old_si.shr_flags ^ si->shr_flags) & SMB_SHRF_QUOTAS)
+ quota_flag_changed = B_TRUE;
+
flag = (new_si->shr_flags & SMB_SHRF_CSC_MASK);
si->shr_flags &= ~SMB_SHRF_CSC_MASK;
si->shr_flags |= flag;
access = (new_si->shr_flags & SMB_SHRF_ACC_ALL);
si->shr_flags &= ~SMB_SHRF_ACC_ALL;
si->shr_flags |= access;
+ si->shr_encrypt = new_si->shr_encrypt;
+
if (access & SMB_SHRF_ACC_NONE)
(void) strlcpy(si->shr_access_none, new_si->shr_access_none,
sizeof (si->shr_access_none));
if (access & SMB_SHRF_ACC_RO)
*** 713,726 ****
nvlist_free(shrlist);
}
}
if (adc_changed) {
! smb_shr_unpublish(new_si->shr_name, old_container);
smb_shr_publish(new_si->shr_name, new_si->shr_container);
}
return (NERR_Success);
}
/*
* smb_shr_exists
--- 817,851 ----
nvlist_free(shrlist);
}
}
if (adc_changed) {
! smb_shr_unpublish(old_si.shr_name, old_si.shr_container);
smb_shr_publish(new_si->shr_name, new_si->shr_container);
}
+ /* The following required privileges we dropped. */
+ if (quota_flag_changed && smb_proc_takesem() == 0) {
+
+ (void) priv_set(PRIV_ON, PRIV_EFFECTIVE,
+ PRIV_FILE_DAC_READ,
+ PRIV_FILE_DAC_SEARCH,
+ PRIV_FILE_DAC_WRITE,
+ NULL);
+
+ smb_shr_zfs_remove(&old_si);
+ smb_shr_zfs_add(si);
+
+ (void) priv_set(PRIV_OFF, PRIV_EFFECTIVE,
+ PRIV_FILE_DAC_READ,
+ PRIV_FILE_DAC_SEARCH,
+ PRIV_FILE_DAC_WRITE,
+ NULL);
+
+ smb_proc_givesem();
+ }
+
return (NERR_Success);
}
/*
* smb_shr_exists
*** 1434,1444 ****
* All functions in this section are private
* ============================================
*/
/*
! * Load shares from sharemgr
*/
/*ARGSUSED*/
void *
smb_shr_load(void *args)
{
--- 1559,1574 ----
* All functions in this section are private
* ============================================
*/
/*
! * Loads the SMB shares, from sharemgr, then:
! * - calls smb_shr_add which:
! * - adds the share into the share cache
! * - adds the share into in-kernel kshare table
! * - publishes the share in ADS
! * - updates the share list in sharefs/sharetab
*/
/*ARGSUSED*/
void *
smb_shr_load(void *args)
{
*** 1445,1458 ****
sa_handle_t handle;
sa_group_t group, subgroup;
char *gstate;
boolean_t gdisabled;
! (void) mutex_lock(&smb_shr_exec_mtx);
! (void) smb_config_get_execinfo(smb_shr_exec_map, smb_shr_exec_unmap,
! MAXPATHLEN);
! (void) mutex_unlock(&smb_shr_exec_mtx);
if ((handle = smb_shr_sa_enter()) == NULL) {
syslog(LOG_ERR, "smb_shr_load: load failed");
return (NULL);
}
--- 1575,1585 ----
sa_handle_t handle;
sa_group_t group, subgroup;
char *gstate;
boolean_t gdisabled;
! smb_shr_load_execinfo();
if ((handle = smb_shr_sa_enter()) == NULL) {
syslog(LOG_ERR, "smb_shr_load: load failed");
return (NULL);
}
*** 1479,1489 ****
--- 1606,1660 ----
}
smb_shr_sa_exit();
return (NULL);
}
+ void
+ smb_shr_load_execinfo()
+ {
+ (void) mutex_lock(&smb_shr_exec_mtx);
+ (void) smb_config_get_execinfo(smb_shr_exec_map, smb_shr_exec_unmap,
+ MAXPATHLEN);
+ (void) mutex_unlock(&smb_shr_exec_mtx);
+ }
+
/*
+ * Handles disabling shares in sharefs when stoping smbd
+ */
+ void
+ smb_shr_unload()
+ {
+ smb_shriter_t iterator;
+ smb_share_t *si;
+ sa_handle_t handle;
+ int rc;
+
+ if ((handle = smb_shr_sa_enter()) == NULL) {
+ syslog(LOG_ERR, "smb_shr_unload: failed");
+ return;
+ }
+
+ smb_shr_iterinit(&iterator);
+
+ while ((si = smb_shr_iterate(&iterator)) != NULL) {
+
+ /* Skip transient shares, IPC$, ... */
+ if ((si->shr_flags & SMB_SHRF_TRANS) ||
+ STYPE_ISIPC(si->shr_type))
+ continue;
+
+ rc = sa_delete_sharetab(handle, si->shr_path, "smb");
+ if (rc) {
+ syslog(LOG_ERR,
+ "sharefs remove %s failed, rc=%d, err=%d",
+ si->shr_path, rc, errno);
+ }
+ }
+ smb_shr_sa_exit();
+ }
+
+ /*
* Load the shares contained in the specified group.
*
* Don't process groups on which the smb protocol is disabled.
* The top level ZFS group won't have the smb protocol enabled
* but sub-groups will.
*** 1533,1542 ****
--- 1704,1714 ----
{
smb_share_t si;
char *sharename;
uint32_t status;
boolean_t loaded;
+ int rc;
if ((sharename = sa_get_resource_attr(resource, "name")) == NULL)
return (NERR_InternalError);
loaded = smb_shr_exists(sharename);
*** 1556,1565 ****
--- 1728,1743 ----
syslog(LOG_DEBUG, "share: failed to cache %s (%d)",
si.shr_name, status);
return (status);
}
+ rc = sa_update_sharetab(share, "smb");
+ if (rc) {
+ syslog(LOG_ERR, "sharefs add %s failed, rc=%d, err=%d",
+ sharename, rc, errno);
+ }
+
return (NERR_Success);
}
static char *
smb_shr_sa_getprop(sa_optionset_t opts, char *propname)
*** 1646,1655 ****
--- 1824,1861 ----
if (val != NULL) {
smb_shr_sa_setflag(val, si, SMB_SHRF_DFSROOT);
free(val);
}
+ val = smb_shr_sa_getprop(opts, SHOPT_CA);
+ if (val != NULL) {
+ smb_shr_sa_setflag(val, si, SMB_SHRF_CA);
+ free(val);
+ }
+
+ val = smb_shr_sa_getprop(opts, SHOPT_FSO);
+ if (val != NULL) {
+ smb_shr_sa_setflag(val, si, SMB_SHRF_FSO);
+ free(val);
+ }
+
+ val = smb_shr_sa_getprop(opts, SHOPT_QUOTAS);
+ if (val != NULL) {
+ /* Turn the flag on or off */
+ smb_shr_sa_setflag(val, si, SMB_SHRF_QUOTAS);
+ free(val);
+ } else {
+ /* Default for this is enabled. */
+ si->shr_flags |= SMB_SHRF_QUOTAS;
+ }
+
+ val = smb_shr_sa_getprop(opts, SHOPT_ENCRYPT);
+ if (val != NULL) {
+ smb_cfg_set_require(val, &si->shr_encrypt);
+ free(val);
+ }
+
val = smb_shr_sa_getprop(opts, SHOPT_CSC);
if (val != NULL) {
smb_shr_sa_csc_option(val, si);
free(val);
}
*** 2021,2046 ****
}
}
/*
* If the share path refers to a ZFS file system, add the
! * .zfs/shares/<share> object and call smb_quota_add_fs()
! * to initialize quota support for the share.
*/
static void
smb_shr_zfs_add(smb_share_t *si)
{
libzfs_handle_t *libhd;
zfs_handle_t *zfshd;
int ret;
char buf[MAXPATHLEN]; /* dataset or mountpoint */
! if (smb_getdataset(si->shr_path, buf, MAXPATHLEN) != 0)
return;
! if ((libhd = libzfs_init()) == NULL)
return;
if ((zfshd = zfs_open(libhd, buf, ZFS_TYPE_FILESYSTEM)) == NULL) {
libzfs_fini(libhd);
return;
}
--- 2227,2254 ----
}
}
/*
* If the share path refers to a ZFS file system, add the
! * .zfs/shares/<share> object and add or remove the special
! * directory and file telling clients about quota support.
*/
static void
smb_shr_zfs_add(smb_share_t *si)
{
libzfs_handle_t *libhd;
zfs_handle_t *zfshd;
int ret;
char buf[MAXPATHLEN]; /* dataset or mountpoint */
! if ((libhd = libzfs_init()) == NULL)
return;
! if (smb_getdataset(libhd, si->shr_path, buf, MAXPATHLEN) != 0) {
! libzfs_fini(libhd);
return;
+ }
if ((zfshd = zfs_open(libhd, buf, ZFS_TYPE_FILESYSTEM)) == NULL) {
libzfs_fini(libhd);
return;
}
*** 2049,2088 ****
ret = zfs_smb_acl_add(libhd, buf, si->shr_path, si->shr_name);
if (ret != 0 && errno != EAGAIN && errno != EEXIST)
syslog(LOG_INFO, "share: failed to add ACL object: %s: %s\n",
si->shr_name, strerror(errno));
! if (zfs_prop_get(zfshd, ZFS_PROP_MOUNTPOINT, buf, MAXPATHLEN,
! NULL, NULL, 0, B_FALSE) == 0) {
smb_quota_add_fs(buf);
}
-
zfs_close(zfshd);
libzfs_fini(libhd);
}
/*
* If the share path refers to a ZFS file system, remove the
! * .zfs/shares/<share> object, and call smb_quota_remove_fs()
! * to end quota support for the share.
*/
static void
smb_shr_zfs_remove(smb_share_t *si)
{
libzfs_handle_t *libhd;
- zfs_handle_t *zfshd;
int ret;
char buf[MAXPATHLEN]; /* dataset or mountpoint */
- if (smb_getdataset(si->shr_path, buf, MAXPATHLEN) != 0)
- return;
-
if ((libhd = libzfs_init()) == NULL)
return;
! if ((zfshd = zfs_open(libhd, buf, ZFS_TYPE_FILESYSTEM)) == NULL) {
libzfs_fini(libhd);
return;
}
errno = 0;
--- 2257,2298 ----
ret = zfs_smb_acl_add(libhd, buf, si->shr_path, si->shr_name);
if (ret != 0 && errno != EAGAIN && errno != EEXIST)
syslog(LOG_INFO, "share: failed to add ACL object: %s: %s\n",
si->shr_name, strerror(errno));
! ret = zfs_prop_get(zfshd, ZFS_PROP_MOUNTPOINT,
! buf, MAXPATHLEN, NULL, NULL, 0, B_FALSE);
! if (ret != 0) {
! syslog(LOG_INFO, "share: failed to get mountpoint: "
! "%s\n", si->shr_name);
! } else {
! if ((si->shr_flags & SMB_SHRF_QUOTAS) != 0) {
smb_quota_add_fs(buf);
+ } else {
+ smb_quota_remove_fs(buf);
}
+ }
zfs_close(zfshd);
libzfs_fini(libhd);
}
/*
* If the share path refers to a ZFS file system, remove the
! * .zfs/shares/<share> object.
*/
static void
smb_shr_zfs_remove(smb_share_t *si)
{
libzfs_handle_t *libhd;
int ret;
char buf[MAXPATHLEN]; /* dataset or mountpoint */
if ((libhd = libzfs_init()) == NULL)
return;
! if (smb_getdataset(libhd, si->shr_path, buf, MAXPATHLEN) != 0) {
libzfs_fini(libhd);
return;
}
errno = 0;
*** 2089,2104 ****
ret = zfs_smb_acl_remove(libhd, buf, si->shr_path, si->shr_name);
if (ret != 0 && errno != EAGAIN)
syslog(LOG_INFO, "share: failed to remove ACL object: %s: %s\n",
si->shr_name, strerror(errno));
! if (zfs_prop_get(zfshd, ZFS_PROP_MOUNTPOINT, buf, MAXPATHLEN,
! NULL, NULL, 0, B_FALSE) == 0) {
! smb_quota_remove_fs(buf);
! }
- zfs_close(zfshd);
libzfs_fini(libhd);
}
/*
* If the share path refers to a ZFS file system, rename the
--- 2299,2314 ----
ret = zfs_smb_acl_remove(libhd, buf, si->shr_path, si->shr_name);
if (ret != 0 && errno != EAGAIN)
syslog(LOG_INFO, "share: failed to remove ACL object: %s: %s\n",
si->shr_name, strerror(errno));
! /*
! * We could remove the quotas directory here, but that adds
! * significantly to the time required for a zpool export,
! * so just leave it here and fixup when we share next.
! */
libzfs_fini(libhd);
}
/*
* If the share path refers to a ZFS file system, rename the
*** 2110,2124 ****
libzfs_handle_t *libhd;
zfs_handle_t *zfshd;
int ret;
char dataset[MAXPATHLEN];
! if (smb_getdataset(from->shr_path, dataset, MAXPATHLEN) != 0)
return;
! if ((libhd = libzfs_init()) == NULL)
return;
if ((zfshd = zfs_open(libhd, dataset, ZFS_TYPE_FILESYSTEM)) == NULL) {
libzfs_fini(libhd);
return;
}
--- 2320,2336 ----
libzfs_handle_t *libhd;
zfs_handle_t *zfshd;
int ret;
char dataset[MAXPATHLEN];
! if ((libhd = libzfs_init()) == NULL)
return;
! if (smb_getdataset(libhd, from->shr_path, dataset, MAXPATHLEN) != 0) {
! libzfs_fini(libhd);
return;
+ }
if ((zfshd = zfs_open(libhd, dataset, ZFS_TYPE_FILESYSTEM)) == NULL) {
libzfs_fini(libhd);
return;
}
*** 2413,2425 ****
rc |= nvlist_add_string(smb, SHOPT_CATIA, "true");
if ((si->shr_flags & SMB_SHRF_GUEST_OK) != 0)
rc |= nvlist_add_string(smb, SHOPT_GUEST, "true");
if ((si->shr_flags & SMB_SHRF_DFSROOT) != 0)
rc |= nvlist_add_string(smb, SHOPT_DFSROOT, "true");
if ((si->shr_flags & SMB_SHRF_AUTOHOME) != 0) {
! rc |= nvlist_add_string(smb, "Autohome", "true");
rc |= nvlist_add_uint32(smb, "uid", si->shr_uid);
rc |= nvlist_add_uint32(smb, "gid", si->shr_gid);
}
if ((csc = smb_shr_sa_csc_name(si)) != NULL)
--- 2625,2650 ----
rc |= nvlist_add_string(smb, SHOPT_CATIA, "true");
if ((si->shr_flags & SMB_SHRF_GUEST_OK) != 0)
rc |= nvlist_add_string(smb, SHOPT_GUEST, "true");
if ((si->shr_flags & SMB_SHRF_DFSROOT) != 0)
rc |= nvlist_add_string(smb, SHOPT_DFSROOT, "true");
+ if ((si->shr_flags & SMB_SHRF_CA) != 0)
+ rc |= nvlist_add_string(smb, SHOPT_CA, "true");
+ if ((si->shr_flags & SMB_SHRF_FSO) != 0)
+ rc |= nvlist_add_string(smb, SHOPT_FSO, "true");
+ if ((si->shr_flags & SMB_SHRF_QUOTAS) != 0)
+ rc |= nvlist_add_string(smb, SHOPT_QUOTAS, "true");
+ if (si->shr_encrypt == SMB_CONFIG_REQUIRED)
+ rc |= nvlist_add_string(smb, SHOPT_ENCRYPT, "required");
+ else if (si->shr_encrypt == SMB_CONFIG_ENABLED)
+ rc |= nvlist_add_string(smb, SHOPT_ENCRYPT, "enabled");
+ else
+ rc |= nvlist_add_string(smb, SHOPT_ENCRYPT, "disabled");
+
if ((si->shr_flags & SMB_SHRF_AUTOHOME) != 0) {
! rc |= nvlist_add_string(smb, SHOPT_AUTOHOME, "true");
rc |= nvlist_add_uint32(smb, "uid", si->shr_uid);
rc |= nvlist_add_uint32(smb, "gid", si->shr_gid);
}
if ((csc = smb_shr_sa_csc_name(si)) != NULL)