/*
Copyright (c) 2007-2011 Gluster, Inc. <http://www.gluster.com>
This file is part of GlusterFS.
GlusterFS is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published
by the Free Software Foundation; either version 3 of the License,
or (at your option) any later version.
GlusterFS is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see
<http://www.gnu.org/licenses/>.
*/
#ifndef _CONFIG_H
#define _CONFIG_H
#include "config.h"
#endif
#include "glusterd-op-sm.h"
#include <inttypes.h>
#include "globals.h"
#include "glusterfs.h"
#include "compat.h"
#include "dict.h"
#include "protocol-common.h"
#include "xlator.h"
#include "logging.h"
#include "timer.h"
#include "defaults.h"
#include "compat.h"
#include "compat-errno.h"
#include "statedump.h"
#include "glusterd-mem-types.h"
#include "glusterd.h"
#include "glusterd-sm.h"
#include "glusterd-op-sm.h"
#include "glusterd-utils.h"
#include "glusterd-store.h"
#include "rpc-clnt.h"
#include "common-utils.h"
#include <sys/resource.h>
#include <inttypes.h>
#include <dirent.h>
static int32_t
glusterd_store_mkdir (char *path)
{
int32_t ret = -1;
ret = mkdir (path, 0777);
if ((-1 == ret) && (EEXIST != errno)) {
gf_log ("", GF_LOG_ERROR, "mkdir() failed on path %s,"
"errno: %s", path, strerror (errno));
} else {
ret = 0;
}
return ret;
}
int32_t
glusterd_store_handle_create_on_absence (glusterd_store_handle_t **shandle,
char *path)
{
GF_ASSERT (shandle);
int32_t ret = 0;
if (*shandle == NULL) {
ret = glusterd_store_handle_new (path, shandle);
if (ret) {
gf_log ("", GF_LOG_ERROR, "Unable to create store"
" handle for path: %s", path);
}
}
return ret;
}
int32_t
glusterd_store_mkstemp (glusterd_store_handle_t *shandle)
{
int fd = -1;
char tmppath[PATH_MAX] = {0,};
GF_ASSERT (shandle);
GF_ASSERT (shandle->path);
snprintf (tmppath, sizeof (tmppath), "%s.tmp", shandle->path);
fd = open (tmppath, O_RDWR | O_CREAT | O_TRUNC, 0600);
if (fd <= 0) {
gf_log ("glusterd", GF_LOG_ERROR, "Failed to open %s, "
"error: %s", tmppath, strerror (errno));
}
return fd;
}
int32_t
glusterd_store_rename_tmppath (glusterd_store_handle_t *shandle)
{
int32_t ret = -1;
char tmppath[PATH_MAX] = {0,};
GF_ASSERT (shandle);
GF_ASSERT (shandle->path);
snprintf (tmppath, sizeof (tmppath), "%s.tmp", shandle->path);
ret = rename (tmppath, shandle->path);
if (ret) {
gf_log ("glusterd", GF_LOG_ERROR, "Failed to mv %s to %s, "
"error: %s", tmppath, shandle->path, strerror (errno));
}
return ret;
}
int32_t
glusterd_store_unlink_tmppath (glusterd_store_handle_t *shandle)
{
int32_t ret = -1;
char tmppath[PATH_MAX] = {0,};
GF_ASSERT (shandle);
GF_ASSERT (shandle->path);
snprintf (tmppath, sizeof (tmppath), "%s.tmp", shandle->path);
ret = unlink (tmppath);
if (ret && (errno != ENOENT)) {
gf_log ("glusterd", GF_LOG_ERROR, "Failed to mv %s to %s, "
"error: %s", tmppath, shandle->path, strerror (errno));
} else {
ret = 0;
}
return ret;
}
static void
glusterd_replace_slash_with_hipen (char *str)
{
char *ptr = NULL;
ptr = strchr (str, '/');
while (ptr) {
*ptr = '-';
ptr = strchr (str, '/');
}
}
int32_t
glusterd_store_create_brick_dir (glusterd_volinfo_t *volinfo)
{
int32_t ret = -1;
char brickdirpath[PATH_MAX] = {0,};
glusterd_conf_t *priv = NULL;
GF_ASSERT (volinfo);
priv = THIS->private;
GF_ASSERT (priv);
GLUSTERD_GET_BRICK_DIR (brickdirpath, volinfo, priv);
ret = glusterd_store_mkdir (brickdirpath);
return ret;
}
static void
glusterd_store_key_vol_brick_set (glusterd_brickinfo_t *brickinfo,
char *key_vol_brick, size_t len)
{
GF_ASSERT (brickinfo);
GF_ASSERT (key_vol_brick);
GF_ASSERT (len >= PATH_MAX);
snprintf (key_vol_brick, len, "%s", brickinfo->path);
glusterd_replace_slash_with_hipen (key_vol_brick);
}
static void
glusterd_store_brickinfofname_set (glusterd_brickinfo_t *brickinfo,
char *brickfname, size_t len)
{
char key_vol_brick[PATH_MAX] = {0};
GF_ASSERT (brickfname);
GF_ASSERT (brickinfo);
GF_ASSERT (len >= PATH_MAX);
glusterd_store_key_vol_brick_set (brickinfo, key_vol_brick,
sizeof (key_vol_brick));
snprintf (brickfname, len, "%s:%s", brickinfo->hostname, key_vol_brick);
}
static void
glusterd_store_brickinfopath_set (glusterd_volinfo_t *volinfo,
glusterd_brickinfo_t *brickinfo,
char *brickpath, size_t len)
{
char brickfname[PATH_MAX] = {0};
char brickdirpath[PATH_MAX] = {0,};
glusterd_conf_t *priv = NULL;
GF_ASSERT (brickpath);
GF_ASSERT (brickinfo);
GF_ASSERT (len >= PATH_MAX);
priv = THIS->private;
GF_ASSERT (priv);
GLUSTERD_GET_BRICK_DIR (brickdirpath, volinfo, priv);
glusterd_store_brickinfofname_set (brickinfo, brickfname,
sizeof (brickfname));
snprintf (brickpath, len, "%s/%s", brickdirpath, brickfname);
}
gf_boolean_t
glusterd_store_is_valid_brickpath (char *volname, char *brick)
{
char brickpath[PATH_MAX] = {0};
glusterd_brickinfo_t *brickinfo = NULL;
glusterd_volinfo_t *volinfo = NULL;
int32_t ret = 0;
ret = glusterd_brickinfo_from_brick (brick, &brickinfo);
if (ret) {
gf_log ("", GF_LOG_WARNING, "brick path validation failed");
ret = 0;
goto out;
}
ret = glusterd_volinfo_new (&volinfo);
if (ret) {
gf_log ("", GF_LOG_WARNING, "brick path validation failed");
ret = 0;
goto out;
}
strncpy (volinfo->volname, volname, sizeof (volinfo->volname));
glusterd_store_brickinfopath_set (volinfo, brickinfo, brickpath,
sizeof (brickpath));
ret = (strlen (brickpath) < _POSIX_PATH_MAX);
out:
if (brickinfo)
glusterd_brickinfo_delete (brickinfo);
if (volinfo)
glusterd_volinfo_delete (volinfo);
return ret;
}
int32_t
glusterd_store_volinfo_brick_fname_write (int vol_fd,
glusterd_brickinfo_t *brickinfo,
int32_t brick_count)
{
char key[PATH_MAX] = {0,};
char brickfname[PATH_MAX] = {0,};
int32_t ret = -1;
snprintf (key, sizeof (key), "%s-%d", GLUSTERD_STORE_KEY_VOL_BRICK,
brick_count);
glusterd_store_brickinfofname_set (brickinfo, brickfname,
sizeof (brickfname));
ret = glusterd_store_save_value (vol_fd, key, brickfname);
return ret;
}
int32_t
glusterd_store_create_brick_shandle_on_absence (glusterd_volinfo_t *volinfo,
glusterd_brickinfo_t *brickinfo)
{
char brickpath[PATH_MAX] = {0,};
int32_t ret = 0;
GF_ASSERT (volinfo);
GF_ASSERT (brickinfo);
glusterd_store_brickinfopath_set (volinfo, brickinfo, brickpath,
sizeof (brickpath));
ret = glusterd_store_handle_create_on_absence (&brickinfo->shandle,
brickpath);
return ret;
}
int32_t
glusterd_store_brickinfo_write (int fd, glusterd_brickinfo_t *brickinfo)
{
char value[256] = {0,};
int32_t ret = 0;
GF_ASSERT (brickinfo);
GF_ASSERT (fd > 0);
ret = glusterd_store_save_value (fd, GLUSTERD_STORE_KEY_BRICK_HOSTNAME,
brickinfo->hostname);
if (ret)
goto out;
ret = glusterd_store_save_value (fd, GLUSTERD_STORE_KEY_BRICK_PATH,
brickinfo->path);
if (ret)
goto out;
snprintf (value, sizeof(value), "%d", brickinfo->port);
ret = glusterd_store_save_value (fd, GLUSTERD_STORE_KEY_BRICK_PORT,
value);
snprintf (value, sizeof(value), "%d", brickinfo->rdma_port);
ret = glusterd_store_save_value (fd, GLUSTERD_STORE_KEY_BRICK_RDMA_PORT,
value);
snprintf (value, sizeof(value), "%d", brickinfo->decommissioned);
ret = glusterd_store_save_value (fd, GLUSTERD_STORE_KEY_BRICK_DECOMMISSIONED,
value);
out:
gf_log ("", GF_LOG_DEBUG, "Returning %d", ret);
return ret;
}
int32_t
glusterd_store_perform_brick_store (glusterd_brickinfo_t *brickinfo)
{
int fd = -1;
int32_t ret = -1;
GF_ASSERT (brickinfo);
fd = glusterd_store_mkstemp (brickinfo->shandle);
if (fd <= 0) {
ret = -1;
goto out;
}
ret = glusterd_store_brickinfo_write (fd, brickinfo);
if (ret)
goto out;
ret = glusterd_store_rename_tmppath (brickinfo->shandle);
out:
if (ret && (fd > 0))
glusterd_store_unlink_tmppath (brickinfo->shandle);
if (fd > 0)
close (fd);
gf_log ("", GF_LOG_DEBUG, "Returning %d", ret);
return ret;
}
int32_t
glusterd_store_brickinfo (glusterd_volinfo_t *volinfo,
glusterd_brickinfo_t *brickinfo, int32_t brick_count,
int vol_fd)
{
int32_t ret = -1;
GF_ASSERT (volinfo);
GF_ASSERT (brickinfo);
ret = glusterd_store_volinfo_brick_fname_write (vol_fd, brickinfo,
brick_count);
if (ret)
goto out;
ret = glusterd_store_create_brick_dir (volinfo);
if (ret)
goto out;
ret = glusterd_store_create_brick_shandle_on_absence (volinfo,
brickinfo);
if (ret)
goto out;
ret = glusterd_store_perform_brick_store (brickinfo);
out:
|