mirror_zfs/lib/libshare/libshare.c
Don Brady ede037cda7
Make zfs-share service resilient to stale exports
The are a few cases where stale entries in /etc/exports.d/zfs.exports 
will cause the nfs-server service to fail when starting up.

Since the nfs-server startup consumes /etc/exports.d/zfs.exports, the 
zfs-share service (which rebuilds the list of zfs exports) should run 
before the nfs-server service.

To make the zfs-share service resilient to stale exports, this change 
truncates the zfs config file as part of the zfs share -a operation.

Reviewed-by: Allan Jude <allan@klarasystems.com>
Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Signed-off-by: Don Brady <don.brady@delphix.com>
Closes #13775
2022-09-09 10:54:16 -07:00

204 lines
5.9 KiB
C

/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or https://opensource.org/licenses/CDDL-1.0.
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2011 Gunnar Beutner
* Copyright (c) 2018, 2022 by Delphix. All rights reserved.
*/
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <string.h>
#include <errno.h>
#include <libintl.h>
#include <sys/file.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <libzfs.h>
#include <libshare.h>
#include "libshare_impl.h"
#define init_share(zfsname, path, shareopts) \
{ \
.sa_zfsname = zfsname, \
.sa_mountpoint = path, \
.sa_shareopts = shareopts, \
}
#define VALIDATE_PROTOCOL(proto, ...) \
if ((proto) < 0 || (proto) >= SA_PROTOCOL_COUNT) \
return __VA_ARGS__
const char *const sa_protocol_names[SA_PROTOCOL_COUNT] = {
[SA_PROTOCOL_NFS] = "nfs",
[SA_PROTOCOL_SMB] = "smb",
};
static const sa_fstype_t *fstypes[SA_PROTOCOL_COUNT] =
{&libshare_nfs_type, &libshare_smb_type};
int
sa_enable_share(const char *zfsname, const char *mountpoint,
const char *shareopts, enum sa_protocol protocol)
{
VALIDATE_PROTOCOL(protocol, SA_INVALID_PROTOCOL);
const struct sa_share_impl args =
init_share(zfsname, mountpoint, shareopts);
return (fstypes[protocol]->enable_share(&args));
}
int
sa_disable_share(const char *mountpoint, enum sa_protocol protocol)
{
VALIDATE_PROTOCOL(protocol, SA_INVALID_PROTOCOL);
const struct sa_share_impl args = init_share(NULL, mountpoint, NULL);
return (fstypes[protocol]->disable_share(&args));
}
boolean_t
sa_is_shared(const char *mountpoint, enum sa_protocol protocol)
{
VALIDATE_PROTOCOL(protocol, B_FALSE);
const struct sa_share_impl args = init_share(NULL, mountpoint, NULL);
return (fstypes[protocol]->is_shared(&args));
}
void
sa_commit_shares(enum sa_protocol protocol)
{
/* CSTYLED */
VALIDATE_PROTOCOL(protocol, );
fstypes[protocol]->commit_shares();
}
void
sa_truncate_shares(enum sa_protocol protocol)
{
/* CSTYLED */
VALIDATE_PROTOCOL(protocol, );
if (fstypes[protocol]->truncate_shares != NULL)
fstypes[protocol]->truncate_shares();
}
int
sa_validate_shareopts(const char *options, enum sa_protocol protocol)
{
VALIDATE_PROTOCOL(protocol, SA_INVALID_PROTOCOL);
return (fstypes[protocol]->validate_shareopts(options));
}
/*
* sa_errorstr(err)
*
* convert an error value to an error string
*/
const char *
sa_errorstr(int err)
{
static char errstr[32];
switch (err) {
case SA_OK:
return (dgettext(TEXT_DOMAIN, "ok"));
case SA_NO_SUCH_PATH:
return (dgettext(TEXT_DOMAIN, "path doesn't exist"));
case SA_NO_MEMORY:
return (dgettext(TEXT_DOMAIN, "no memory"));
case SA_DUPLICATE_NAME:
return (dgettext(TEXT_DOMAIN, "name in use"));
case SA_BAD_PATH:
return (dgettext(TEXT_DOMAIN, "bad path"));
case SA_NO_SUCH_GROUP:
return (dgettext(TEXT_DOMAIN, "no such group"));
case SA_CONFIG_ERR:
return (dgettext(TEXT_DOMAIN, "configuration error"));
case SA_SYSTEM_ERR:
return (dgettext(TEXT_DOMAIN, "system error"));
case SA_SYNTAX_ERR:
return (dgettext(TEXT_DOMAIN, "syntax error"));
case SA_NO_PERMISSION:
return (dgettext(TEXT_DOMAIN, "no permission"));
case SA_BUSY:
return (dgettext(TEXT_DOMAIN, "busy"));
case SA_NO_SUCH_PROP:
return (dgettext(TEXT_DOMAIN, "no such property"));
case SA_INVALID_NAME:
return (dgettext(TEXT_DOMAIN, "invalid name"));
case SA_INVALID_PROTOCOL:
return (dgettext(TEXT_DOMAIN, "invalid protocol"));
case SA_NOT_ALLOWED:
return (dgettext(TEXT_DOMAIN, "operation not allowed"));
case SA_BAD_VALUE:
return (dgettext(TEXT_DOMAIN, "bad property value"));
case SA_INVALID_SECURITY:
return (dgettext(TEXT_DOMAIN, "invalid security type"));
case SA_NO_SUCH_SECURITY:
return (dgettext(TEXT_DOMAIN, "security type not found"));
case SA_VALUE_CONFLICT:
return (dgettext(TEXT_DOMAIN, "property value conflict"));
case SA_NOT_IMPLEMENTED:
return (dgettext(TEXT_DOMAIN, "not implemented"));
case SA_INVALID_PATH:
return (dgettext(TEXT_DOMAIN, "invalid path"));
case SA_NOT_SUPPORTED:
return (dgettext(TEXT_DOMAIN, "operation not supported"));
case SA_PROP_SHARE_ONLY:
return (dgettext(TEXT_DOMAIN, "property not valid for group"));
case SA_NOT_SHARED:
return (dgettext(TEXT_DOMAIN, "not shared"));
case SA_NO_SUCH_RESOURCE:
return (dgettext(TEXT_DOMAIN, "no such resource"));
case SA_RESOURCE_REQUIRED:
return (dgettext(TEXT_DOMAIN, "resource name required"));
case SA_MULTIPLE_ERROR:
return (dgettext(TEXT_DOMAIN,
"errors from multiple protocols"));
case SA_PATH_IS_SUBDIR:
return (dgettext(TEXT_DOMAIN, "path is a subpath of share"));
case SA_PATH_IS_PARENTDIR:
return (dgettext(TEXT_DOMAIN, "path is parent of a share"));
case SA_NO_SECTION:
return (dgettext(TEXT_DOMAIN, "protocol requires a section"));
case SA_NO_PROPERTIES:
return (dgettext(TEXT_DOMAIN, "properties not found"));
case SA_NO_SUCH_SECTION:
return (dgettext(TEXT_DOMAIN, "section not found"));
case SA_PASSWORD_ENC:
return (dgettext(TEXT_DOMAIN, "passwords must be encrypted"));
case SA_SHARE_EXISTS:
return (dgettext(TEXT_DOMAIN,
"path or file is already shared"));
default:
(void) snprintf(errstr, sizeof (errstr),
dgettext(TEXT_DOMAIN, "unknown %d"), err);
return (errstr);
}
}