gfapi: API/library for accessing gluster volumes

Change-Id: Ie4cbcf91b58218bebf23cf951c313aceeb29f311
BUG: 839950
Signed-off-by: Anand Avati <avati@redhat.com>
Reviewed-on: http://review.gluster.com/3664
Tested-by: Gluster Build System <jenkins@build.gluster.com>
Reviewed-by: Jeff Darcy <jdarcy@redhat.com>
Reviewed-by: Kaleb KEITHLEY <kkeithle@redhat.com>
Reviewed-by: Bharata B Rao <bharata.rao@gmail.com>
This commit is contained in:
Anand Avati 2012-07-12 15:37:38 -07:00
parent 162505c019
commit 2475e0193c
12 changed files with 2864 additions and 1 deletions

View File

@ -1,6 +1,7 @@
EXTRA_DIST = autogen.sh COPYING-GPLV2 COPYING-LGPLV3 INSTALL README AUTHORS THANKS NEWS glusterfs.spec
SUBDIRS = argp-standalone libglusterfs rpc xlators glusterfsd $(FUSERMOUNT_SUBDIR) doc extras cli
SUBDIRS = argp-standalone libglusterfs rpc api xlators glusterfsd \
$(FUSERMOUNT_SUBDIR) doc extras cli
CLEANFILES =

1
api/Makefile.am Normal file
View File

@ -0,0 +1 @@
SUBDIRS = src

30
api/src/Makefile.am Normal file
View File

@ -0,0 +1,30 @@
lib_LTLIBRARIES = libgfapi.la
noinst_HEADERS = glfs-mem-types.h glfs-internal.h
libgfapi_HEADERS = glfs.h
libgfapidir = $(includedir)/glusterfs/api
libgfapi_la_SOURCES = glfs.c glfs-mgmt.c glfs-fops.c glfs-resolve.c
libgfapi_la_CFLAGS = -fPIC -Wall
libgfapi_la_LIBADD = $(top_builddir)/libglusterfs/src/libglusterfs.la
$(top_builddir)/rpc/rpc-lib/src/libgfrpc.la \
$(top_builddir)/rpc/xdr/src/libgfxdr.la \
$(GF_LDADD)
libgfapi_la_CPPFLAGS = -D_FILE_OFFSET_BITS=64 -D__USE_FILE_OFFSET64 -D_GNU_SOURCE \
-D$(GF_HOST_OS) $(GF_CFLAGS) \
-I$(top_srcdir)/libglusterfs/src \
-I$(top_srcdir)/rpc/rpc-lib/src \
-I$(top_srcdir)/rpc/xdr/src
libgfapi_la_LDFLAGS = -shared -nostartfiles
xlator_LTLIBRARIES = api.la
xlatordir = $(libdir)/glusterfs/$(PACKAGE_VERSION)/xlator/mount
api_la_SOURCES = glfs-master.c
api_la_LDFLAGS = -module -avoidversion
api_la_LIBADD = $(top_builddir)/libglusterfs/src/libglusterfs.la
AM_CFLAGS = -fPIC -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE -D$(GF_HOST_OS) -Wall \
-I$(top_srcdir)/libglusterfs/src $(GF_CFLAGS)

829
api/src/glfs-fops.c Normal file
View File

@ -0,0 +1,829 @@
/*
Copyright (c) 2012 Red Hat, Inc. <http://www.redhat.com>
This file is part of GlusterFS.
This file is licensed to you under your choice of the GNU Lesser
General Public License, version 3 or any later version (LGPLv3 or
later), or the GNU General Public License, version 2 (GPLv2), in all
cases as published by the Free Software Foundation.
*/
#include "glfs-internal.h"
#include "glfs-mem-types.h"
#include "syncop.h"
#include "glfs.h"
struct glfs_fd *
glfs_open (struct glfs *fs, const char *path, int flags)
{
int ret = -1;
struct glfs_fd *glfd = NULL;
xlator_t *subvol = NULL;
loc_t loc = {0, };
struct iatt iatt = {0, };
__glfs_entry_fs (fs);
subvol = glfs_active_subvol (fs);
if (!subvol) {
ret = -1;
errno = EIO;
goto out;
}
glfd = GF_CALLOC (1, sizeof (*glfd), glfs_mt_glfs_fd_t);
if (!glfd)
goto out;
ret = glfs_resolve (fs, subvol, path, &loc, &iatt);
if (ret)
goto out;
if (IA_ISDIR (iatt.ia_type)) {
ret = -1;
errno = EISDIR;
goto out;
}
if (!IA_ISREG (iatt.ia_type)) {
ret = -1;
errno = EINVAL;
goto out;
}
glfd->fd = fd_create (loc.inode, getpid());
if (!glfd->fd) {
ret = -1;
errno = ENOMEM;
goto out;
}
ret = syncop_open (subvol, &loc, flags, glfd->fd);
out:
loc_wipe (&loc);
if (ret && glfd) {
glfs_fd_destroy (glfd);
glfd = NULL;
}
return glfd;
}
int
glfs_close (struct glfs_fd *glfd)
{
xlator_t *subvol = NULL;
int ret = -1;
__glfs_entry_fd (glfd);
subvol = glfs_fd_subvol (glfd);
ret = syncop_flush (subvol, glfd->fd);
glfs_fd_destroy (glfd);
return ret;
}
int
glfs_lstat (struct glfs *fs, const char *path, struct stat *stat)
{
int ret = -1;
xlator_t *subvol = NULL;
loc_t loc = {0, };
struct iatt iatt = {0, };
__glfs_entry_fs (fs);
subvol = glfs_active_subvol (fs);
if (!subvol) {
ret = -1;
errno = EIO;
goto out;
}
ret = glfs_resolve (fs, subvol, path, &loc, &iatt);
if (ret == 0 && stat)
iatt_to_stat (&iatt, stat);
out:
loc_wipe (&loc);
return ret;
}
int
glfs_fstat (struct glfs_fd *glfd, struct stat *stat)
{
int ret = -1;
xlator_t *subvol = NULL;
struct iatt iatt = {0, };
__glfs_entry_fd (glfd);
subvol = glfs_fd_subvol (glfd);
if (!subvol) {
ret = -1;
errno = EIO;
goto out;
}
ret = syncop_fstat (subvol, glfd->fd, &iatt);
if (ret == 0 && stat)
iatt_to_stat (&iatt, stat);
out:
return ret;
}
struct glfs_fd *
glfs_creat (struct glfs *fs, const char *path, int flags, mode_t mode)
{
int ret = -1;
struct glfs_fd *glfd = NULL;
xlator_t *subvol = NULL;
loc_t loc = {0, };
struct iatt iatt = {0, };
uuid_t gfid;
dict_t *xattr_req = NULL;
__glfs_entry_fs (fs);
subvol = glfs_active_subvol (fs);
if (!subvol) {
ret = -1;
errno = EIO;
goto out;
}
xattr_req = dict_new ();
if (!xattr_req) {
ret = -1;
errno = ENOMEM;
goto out;
}
uuid_generate (gfid);
ret = dict_set_static_bin (xattr_req, "gfid-req", gfid, 16);
if (ret) {
ret = -1;
errno = ENOMEM;
goto out;
}
glfd = GF_CALLOC (1, sizeof (*glfd), glfs_mt_glfs_fd_t);
if (!glfd)
goto out;
ret = glfs_resolve (fs, subvol, path, &loc, &iatt);
if (ret == -1 && errno != ENOENT)
/* Any other type of error is fatal */
goto out;
if (ret == -1 && errno == ENOENT && !loc.parent)
/* The parent directory or an ancestor even
higher does not exist
*/
goto out;
if (loc.inode) {
if (flags & O_EXCL) {
ret = -1;
errno = EEXIST;
goto out;
}
if (IA_ISDIR (iatt.ia_type)) {
ret = -1;
errno = EISDIR;
goto out;
}
if (!IA_ISREG (iatt.ia_type)) {
ret = -1;
errno = EINVAL;
goto out;
}
}
if (ret == -1 && errno == ENOENT) {
loc.inode = inode_new (loc.parent->table);
if (!loc.inode) {
ret = -1;
errno = ENOMEM;
goto out;
}
}
glfd->fd = fd_create (loc.inode, getpid());
if (!glfd->fd) {
ret = -1;
errno = ENOMEM;
goto out;
}
ret = syncop_create (subvol, &loc, flags, mode, glfd->fd, xattr_req);
out:
loc_wipe (&loc);
if (xattr_req)
dict_destroy (xattr_req);
if (ret && glfd) {
glfs_fd_destroy (glfd);
glfd = NULL;
}
return glfd;
}
off_t
glfs_lseek (struct glfs_fd *glfd, off_t offset, int whence)
{
struct stat sb = {0, };
int ret = -1;
__glfs_entry_fd (glfd);
switch (whence) {
case SEEK_SET:
glfd->offset = offset;
break;
case SEEK_CUR:
glfd->offset += offset;
break;
case SEEK_END:
ret = glfs_fstat (glfd, &sb);
if (ret) {
/* seek cannot fail :O */
break;
}
glfd->offset = sb.st_size + offset;
break;
}
return glfd->offset;
}
//////////////
ssize_t
glfs_preadv (struct glfs_fd *glfd, const struct iovec *iovec, int iovcnt,
off_t offset, int flags)
{
xlator_t *subvol = NULL;
int ret = -1;
size_t size = -1;
struct iovec *iov = NULL;
int cnt = 0;
struct iobref *iobref = NULL;
__glfs_entry_fd (glfd);
subvol = glfs_fd_subvol (glfd);
size = iov_length (iovec, iovcnt);
ret = syncop_readv (subvol, glfd->fd, size, offset,
0, &iov, &cnt, &iobref);
if (ret <= 0)
return ret;
size = iov_copy (iovec, iovcnt, iov, cnt); /* FIXME!!! */
glfd->offset = (offset + size);
if (iov)
GF_FREE (iov);
if (iobref)
iobref_unref (iobref);
return size;
}
ssize_t
glfs_read (struct glfs_fd *glfd, void *buf, size_t count, int flags)
{
struct iovec iov = {0, };
ssize_t ret = 0;
iov.iov_base = buf;
iov.iov_len = count;
ret = glfs_preadv (glfd, &iov, 1, glfd->offset, flags);
return ret;
}
ssize_t
glfs_pread (struct glfs_fd *glfd, void *buf, size_t count, off_t offset,
int flags)
{
struct iovec iov = {0, };
ssize_t ret = 0;
iov.iov_base = buf;
iov.iov_len = count;
ret = glfs_preadv (glfd, &iov, 1, offset, flags);
return ret;
}
ssize_t
glfs_readv (struct glfs_fd *glfd, const struct iovec *iov, int count,
int flags)
{
ssize_t ret = 0;
ret = glfs_preadv (glfd, iov, count, glfd->offset, flags);
return ret;
}
struct glfs_io {
struct glfs_fd *glfd;
int op;
off_t offset;
struct iovec *iov;
int count;
int flags;
glfs_io_cbk fn;
void *data;
};
static int
glfs_io_async_cbk (int ret, call_frame_t *frame, void *data)
{
struct glfs_io *gio = data;
gio->fn (gio->glfd, ret, gio->data);
GF_FREE (gio->iov);
GF_FREE (gio);
return 0;
}
static int
glfs_io_async_task (void *data)
{
struct glfs_io *gio = data;
ssize_t ret = 0;
switch (gio->op) {
case GF_FOP_READ:
ret = glfs_preadv (gio->glfd, gio->iov, gio->count,
gio->offset, gio->flags);
break;
case GF_FOP_WRITE:
ret = glfs_pwritev (gio->glfd, gio->iov, gio->count,
gio->offset, gio->flags);
break;
case GF_FOP_FTRUNCATE:
ret = glfs_ftruncate (gio->glfd, gio->offset);
break;
case GF_FOP_FSYNC:
if (gio->flags)
ret = glfs_fdatasync (gio->glfd);
else
ret = glfs_fsync (gio->glfd);
break;
}
return (int) ret;
}
int
glfs_preadv_async (struct glfs_fd *glfd, const struct iovec *iovec, int count,
off_t offset, int flags, glfs_io_cbk fn, void *data)
{
struct glfs_io *gio = NULL;
int ret = 0;
gio = GF_CALLOC (1, sizeof (*gio), glfs_mt_glfs_io_t);
if (!gio) {
errno = ENOMEM;
return -1;
}
gio->iov = iov_dup (iovec, count);
if (!gio->iov) {
GF_FREE (gio);
errno = ENOMEM;
return -1;
}
gio->op = GF_FOP_READ;
gio->glfd = glfd;
gio->count = count;
gio->offset = offset;
gio->flags = flags;
gio->fn = fn;
gio->data = data;
ret = synctask_new (glfs_from_glfd (glfd)->ctx->env,
glfs_io_async_task, glfs_io_async_cbk,
NULL, gio);
if (ret) {
GF_FREE (gio->iov);
GF_FREE (gio);
}
return ret;
}
int
glfs_read_async (struct glfs_fd *glfd, void *buf, size_t count, int flags,
glfs_io_cbk fn, void *data)
{
struct iovec iov = {0, };
ssize_t ret = 0;
iov.iov_base = buf;
iov.iov_len = count;
ret = glfs_preadv_async (glfd, &iov, 1, glfd->offset, flags, fn, data);
return ret;
}
int
glfs_pread_async (struct glfs_fd *glfd, void *buf, size_t count, off_t offset,
int flags, glfs_io_cbk fn, void *data)
{
struct iovec iov = {0, };
ssize_t ret = 0;
iov.iov_base = buf;
iov.iov_len = count;
ret = glfs_preadv_async (glfd, &iov, 1, offset, flags, fn, data);
return ret;
}
int
glfs_readv_async (struct glfs_fd *glfd, const struct iovec *iov, int count,
int flags, glfs_io_cbk fn, void *data)
{
ssize_t ret = 0;
ret = glfs_preadv_async (glfd, iov, count, glfd->offset, flags,
fn, data);
return ret;
}
///// writev /////
ssize_t
glfs_pwritev (struct glfs_fd *glfd, const struct iovec *iovec, int iovcnt,
off_t offset, int flags)
{
xlator_t *subvol = NULL;
int ret = -1;
size_t size = -1;
struct iobref *iobref = NULL;
struct iobuf *iobuf = NULL;
struct iovec iov = {0, };
__glfs_entry_fd (glfd);
subvol = glfs_fd_subvol (glfd);
size = iov_length (iovec, iovcnt);
iobuf = iobuf_get2 (subvol->ctx->iobuf_pool, size);
if (!iobuf) {
errno = ENOMEM;
return -1;
}
iobref = iobref_new ();
if (!iobref) {
iobuf_unref (iobuf);
errno = ENOMEM;
return -1;
}
ret = iobref_add (iobref, iobuf);
if (ret) {
iobuf_unref (iobuf);
iobref_unref (iobref);
errno = ENOMEM;
return -1;
}
iov_unload (iobuf_ptr (iobuf), iovec, iovcnt); /* FIXME!!! */
iov.iov_base = iobuf_ptr (iobuf);
iov.iov_len = size;
ret = syncop_writev (subvol, glfd->fd, &iov, 1, offset,
iobref, flags);
iobuf_unref (iobuf);
iobref_unref (iobref);
if (ret <= 0)
return ret;
glfd->offset = (offset + size);
return ret;
}
ssize_t
glfs_write (struct glfs_fd *glfd, const void *buf, size_t count, int flags)
{
struct iovec iov = {0, };
ssize_t ret = 0;
iov.iov_base = (void *) buf;
iov.iov_len = count;
ret = glfs_pwritev (glfd, &iov, 1, glfd->offset, flags);
return ret;
}
ssize_t
glfs_writev (struct glfs_fd *glfd, const struct iovec *iov, int count,
int flags)
{
ssize_t ret = 0;
ret = glfs_pwritev (glfd, iov, count, glfd->offset, flags);
return ret;
}
ssize_t
glfs_pwrite (struct glfs_fd *glfd, const void *buf, size_t count, off_t offset,
int flags)
{
struct iovec iov = {0, };
ssize_t ret = 0;
iov.iov_base = (void *) buf;
iov.iov_len = count;
ret = glfs_pwritev (glfd, &iov, 1, offset, flags);
return ret;
}
int
glfs_pwritev_async (struct glfs_fd *glfd, const struct iovec *iovec, int count,
off_t offset, int flags, glfs_io_cbk fn, void *data)
{
struct glfs_io *gio = NULL;
int ret = 0;
gio = GF_CALLOC (1, sizeof (*gio), glfs_mt_glfs_io_t);
if (!gio) {
errno = ENOMEM;
return -1;
}
gio->iov = iov_dup (iovec, count);
if (!gio->iov) {
GF_FREE (gio);
errno = ENOMEM;
return -1;
}
gio->op = GF_FOP_WRITE;
gio->glfd = glfd;
gio->count = count;
gio->offset = offset;
gio->flags = flags;
gio->fn = fn;
gio->data = data;
ret = synctask_new (glfs_from_glfd (glfd)->ctx->env,
glfs_io_async_task, glfs_io_async_cbk,
NULL, gio);
if (ret) {
GF_FREE (gio->iov);
GF_FREE (gio);
}
return ret;
}
int
glfs_write_async (struct glfs_fd *glfd, const void *buf, size_t count, int flags,
glfs_io_cbk fn, void *data)
{
struct iovec iov = {0, };
ssize_t ret = 0;
iov.iov_base = (void *) buf;
iov.iov_len = count;
ret = glfs_pwritev_async (glfd, &iov, 1, glfd->offset, flags, fn, data);
return ret;
}
int
glfs_pwrite_async (struct glfs_fd *glfd, const void *buf, int count,
off_t offset, int flags, glfs_io_cbk fn, void *data)
{
struct iovec iov = {0, };
ssize_t ret = 0;
iov.iov_base = (void *) buf;
iov.iov_len = count;
ret = glfs_pwritev_async (glfd, &iov, 1, offset, flags, fn, data);
return ret;
}
int
glfs_writev_async (struct glfs_fd *glfd, const struct iovec *iov, int count,
int flags, glfs_io_cbk fn, void *data)
{
ssize_t ret = 0;
ret = glfs_pwritev_async (glfd, iov, count, glfd->offset, flags,
fn, data);
return ret;
}
int
glfs_fsync (struct glfs_fd *glfd)
{
int ret = -1;
xlator_t *subvol = NULL;
__glfs_entry_fd (glfd);
subvol = glfs_fd_subvol (glfd);
if (!subvol) {
ret = -1;
errno = EIO;
goto out;
}
ret = syncop_fsync (subvol, glfd->fd);
// ret = syncop_fsync (subvol, glfd->fd, 0);
out:
return ret;
}
static int
glfs_fsync_async_common (struct glfs_fd *glfd, glfs_io_cbk fn, void *data,
int dataonly)
{
struct glfs_io *gio = NULL;
int ret = 0;
gio = GF_CALLOC (1, sizeof (*gio), glfs_mt_glfs_io_t);
if (!gio) {
errno = ENOMEM;
return -1;
}
gio->op = GF_FOP_FSYNC;
gio->glfd = glfd;
gio->flags = dataonly;
gio->fn = fn;
gio->data = data;
ret = synctask_new (glfs_from_glfd (glfd)->ctx->env,
glfs_io_async_task, glfs_io_async_cbk,
NULL, gio);
if (ret) {
GF_FREE (gio->iov);
GF_FREE (gio);
}
return ret;
}
int
glfs_fsync_async (struct glfs_fd *glfd, glfs_io_cbk fn, void *data)
{
return glfs_fsync_async_common (glfd, fn, data, 0);
}
int
glfs_fdatasync (struct glfs_fd *glfd)
{
int ret = -1;
xlator_t *subvol = NULL;
__glfs_entry_fd (glfd);
subvol = glfs_fd_subvol (glfd);
if (!subvol) {
ret = -1;
errno = EIO;
goto out;
}
ret = syncop_fsync (subvol, glfd->fd);
// ret = syncop_fsync (subvol, glfd->fd, 1);
out:
return ret;
}
int
glfs_fdatasync_async (struct glfs_fd *glfd, glfs_io_cbk fn, void *data)
{
return glfs_fsync_async_common (glfd, fn, data, 1);
}
int
glfs_ftruncate (struct glfs_fd *glfd, off_t offset)
{
int ret = -1;
xlator_t *subvol = NULL;
__glfs_entry_fd (glfd);
subvol = glfs_fd_subvol (glfd);
if (!subvol) {
ret = -1;
errno = EIO;
goto out;
}
ret = syncop_ftruncate (subvol, glfd->fd, offset);
out:
return ret;
}
int
glfs_ftruncate_async (struct glfs_fd *glfd, off_t offset,
glfs_io_cbk fn, void *data)
{
struct glfs_io *gio = NULL;
int ret = 0;
gio = GF_CALLOC (1, sizeof (*gio), glfs_mt_glfs_io_t);
if (!gio) {
errno = ENOMEM;
return -1;
}
gio->op = GF_FOP_FTRUNCATE;
gio->glfd = glfd;
gio->offset = offset;
gio->fn = fn;
gio->data = data;
ret = synctask_new (glfs_from_glfd (glfd)->ctx->env,
glfs_io_async_task, glfs_io_async_cbk,
NULL, gio);
if (ret) {
GF_FREE (gio->iov);
GF_FREE (gio);
}
return ret;
}

74
api/src/glfs-internal.h Normal file
View File

@ -0,0 +1,74 @@
/*
Copyright (c) 2012 Red Hat, Inc. <http://www.redhat.com>
This file is part of GlusterFS.
This file is licensed to you under your choice of the GNU Lesser
General Public License, version 3 or any later version (LGPLv3 or
later), or the GNU General Public License, version 2 (GPLv2), in all
cases as published by the Free Software Foundation.
*/
#ifndef _GLFS_INTERNAL_H
#define _GLFS_INTERNAL_H
#include "xlator.h"
struct glfs;
typedef int (*glfs_init_cbk) (struct glfs *fs, int ret);
struct glfs {
char *volname;
glusterfs_ctx_t *ctx;
pthread_t poller;
glfs_init_cbk init_cbk;
pthread_mutex_t mutex;
pthread_cond_t cond;
int init;
int ret;
xlator_t *active_subvol;
};
struct glfs_fd {
off_t offset;
fd_t *fd;
};
#define DEFAULT_EVENT_POOL_SIZE 16384
#define GF_MEMPOOL_COUNT_OF_DICT_T 4096
#define GF_MEMPOOL_COUNT_OF_DATA_T (GF_MEMPOOL_COUNT_OF_DICT_T * 4)
#define GF_MEMPOOL_COUNT_OF_DATA_PAIR_T (GF_MEMPOOL_COUNT_OF_DICT_T * 4)
int glfs_mgmt_init (struct glfs *fs);
void glfs_init_done (struct glfs *fs, int ret);
int glfs_process_volfp (struct glfs *fs, FILE *fp);
int glfs_resolve (struct glfs *fs, xlator_t *subvol, const char *path, loc_t *loc,
struct iatt *iatt);
void glfs_first_lookup (xlator_t *subvol);
static inline void
__glfs_entry_fs (struct glfs *fs)
{
THIS = fs->ctx->master;
}
static inline void
__glfs_entry_fd (struct glfs_fd *fd)
{
THIS = fd->fd->inode->table->xl->ctx->master;
}
void glfs_fd_destroy (struct glfs_fd *glfd);
xlator_t * glfs_fd_subvol (struct glfs_fd *glfd);
xlator_t * glfs_active_subvol (struct glfs *fs);
#endif /* !_GLFS_INTERNAL_H */

113
api/src/glfs-master.c Normal file
View File

@ -0,0 +1,113 @@
/*
Copyright (c) 2012 Red Hat, Inc. <http://www.redhat.com>
This file is part of GlusterFS.
This file is licensed to you under your choice of the GNU Lesser
General Public License, version 3 or any later version (LGPLv3 or
later), or the GNU General Public License, version 2 (GPLv2), in all
cases as published by the Free Software Foundation.
*/
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <inttypes.h>
#include <limits.h>
#ifndef _CONFIG_H
#define _CONFIG_H
#include "config.h"
#endif
#include "xlator.h"
#include "glusterfs.h"
#include "glfs-internal.h"
int
glfs_graph_setup (struct glfs *fs, glusterfs_graph_t *graph)
{
if (fs->active_subvol == graph->top)
return 0;
pthread_mutex_lock (&fs->mutex);
{
fs->active_subvol = graph->top;
pthread_cond_broadcast (&fs->cond);
}
pthread_mutex_unlock (&fs->mutex);
gf_log ("glfs-master", GF_LOG_INFO, "switched to graph %s (%d)",
uuid_utoa ((unsigned char *)graph->graph_uuid), graph->id);
return 0;
}
int
notify (xlator_t *this, int event, void *data, ...)
{
glusterfs_graph_t *graph = NULL;
struct glfs *fs = NULL;
graph = data;
fs = this->private;
switch (event) {
case GF_EVENT_GRAPH_NEW:
gf_log (this->name, GF_LOG_INFO, "New graph %s (%d) coming up",
uuid_utoa ((unsigned char *)graph->graph_uuid),
graph->id);
break;
case GF_EVENT_CHILD_UP:
glfs_graph_setup (fs, graph);
glfs_init_done (fs, 0);
break;
case GF_EVENT_CHILD_DOWN:
glfs_graph_setup (fs, graph);
glfs_init_done (fs, 1);
break;
case GF_EVENT_CHILD_CONNECTING:
break;
default:
gf_log (this->name, GF_LOG_DEBUG,
"got notify event %d", event);
break;
}
return 0;
}
int
mem_acct_init (xlator_t *this)
{
return 0;
}
int
init (xlator_t *this)
{
return 0;
}
void
fini (xlator_t *this)
{
}
struct xlator_dumpops dumpops = {
};
struct xlator_fops fops = {
};
struct xlator_cbks cbks = {
};

28
api/src/glfs-mem-types.h Normal file
View File

@ -0,0 +1,28 @@
/*
Copyright (c) 2012 Red Hat, Inc. <http://www.redhat.com>
This file is part of GlusterFS.
This file is licensed to you under your choice of the GNU Lesser
General Public License, version 3 or any later version (LGPLv3 or
later), or the GNU General Public License, version 2 (GPLv2), in all
cases as published by the Free Software Foundation.
*/
#ifndef _GLFS_MEM_TYPES_H
#define _GLFS_MEM_TYPES_H
#include "mem-types.h"
#define GF_MEM_TYPE_START (gf_common_mt_end + 1)
enum glfs_mem_types_ {
glfs_mt_glfs_t,
glfs_mt_call_pool_t,
glfs_mt_xlator_t,
glfs_mt_glfs_fd_t,
glfs_mt_glfs_io_t,
glfs_mt_end
};
#endif

629
api/src/glfs-mgmt.c Normal file
View File

@ -0,0 +1,629 @@
/*
Copyright (c) 2012 Red Hat, Inc. <http://www.redhat.com>
This file is part of GlusterFS.
This file is licensed to you under your choice of the GNU Lesser
General Public License, version 3 or any later version (LGPLv3 or
later), or the GNU General Public License, version 2 (GPLv2), in all
cases as published by the Free Software Foundation.
*/
#include <stdio.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <signal.h>
#include <pthread.h>
#ifndef _CONFIG_H
#define _CONFIG_H
#include "config.h"
#endif /* _CONFIG_H */
#include "glusterfs.h"
#include "stack.h"
#include "dict.h"
#include "event.h"
#include "defaults.h"
#include "rpc-clnt.h"
#include "protocol-common.h"
#include "glusterfs3.h"
#include "portmap-xdr.h"
#include "xdr-generic.h"
#include "syncop.h"
#include "xlator.h"
#include "glfs-internal.h"
int glfs_volfile_fetch (struct glfs *fs);
int
glfs_process_volfp (struct glfs *fs, FILE *fp)
{
glusterfs_graph_t *graph = NULL;
int ret = -1;
xlator_t *trav = NULL;
glusterfs_ctx_t *ctx = NULL;
ctx = fs->ctx;
graph = glusterfs_graph_construct (fp);
if (!graph) {
gf_log ("glfs", GF_LOG_ERROR, "failed to construct the graph");
goto out;
}
for (trav = graph->first; trav; trav = trav->next) {
if (strcmp (trav->type, "mount/fuse") == 0) {
gf_log ("glfs", GF_LOG_ERROR,
"fuse xlator cannot be specified "
"in volume file");
goto out;
}
}
ret = glusterfs_graph_prepare (graph, ctx);
if (ret) {
glusterfs_graph_destroy (graph);
goto out;
}
ret = glusterfs_graph_activate (graph, ctx);
if (ret) {
glusterfs_graph_destroy (graph);
goto out;
}
ret = 0;
out:
if (fp)
fclose (fp);
if (!ctx->active) {
ret = -1;
}
return ret;
}
int
mgmt_cbk_spec (struct rpc_clnt *rpc, void *mydata, void *data)
{
struct glfs *fs = NULL;
xlator_t *this = NULL;
this = mydata;
fs = this->private;
glfs_volfile_fetch (fs);
return 0;
}
int
mgmt_cbk_event (struct rpc_clnt *rpc, void *mydata, void *data)
{
return 0;
}
rpcclnt_cb_actor_t gluster_cbk_actors[] = {
[GF_CBK_FETCHSPEC] = {"FETCHSPEC", GF_CBK_FETCHSPEC, mgmt_cbk_spec },
[GF_CBK_EVENT_NOTIFY] = {"EVENTNOTIFY", GF_CBK_EVENT_NOTIFY,
mgmt_cbk_event},
};
struct rpcclnt_cb_program mgmt_cbk_prog = {
.progname = "GlusterFS Callback",
.prognum = GLUSTER_CBK_PROGRAM,
.progver = GLUSTER_CBK_VERSION,
.actors = gluster_cbk_actors,
.numactors = GF_CBK_MAXVALUE,
};
char *clnt_handshake_procs[GF_HNDSK_MAXVALUE] = {
[GF_HNDSK_NULL] = "NULL",
[GF_HNDSK_SETVOLUME] = "SETVOLUME",
[GF_HNDSK_GETSPEC] = "GETSPEC",
[GF_HNDSK_PING] = "PING",
[GF_HNDSK_EVENT_NOTIFY] = "EVENTNOTIFY",
};
rpc_clnt_prog_t clnt_handshake_prog = {
.progname = "GlusterFS Handshake",
.prognum = GLUSTER_HNDSK_PROGRAM,
.progver = GLUSTER_HNDSK_VERSION,
.procnames = clnt_handshake_procs,
};
int
mgmt_submit_request (void *req, call_frame_t *frame,
glusterfs_ctx_t *ctx,
rpc_clnt_prog_t *prog, int procnum,
fop_cbk_fn_t cbkfn, xdrproc_t xdrproc)
{
int ret = -1;
int count = 0;
struct iovec iov = {0, };
struct iobuf *iobuf = NULL;
struct iobref *iobref = NULL;
ssize_t xdr_size = 0;
iobref = iobref_new ();
if (!iobref) {
goto out;
}
if (req) {
xdr_size = xdr_sizeof (xdrproc, req);
iobuf = iobuf_get2 (ctx->iobuf_pool, xdr_size);
if (!iobuf) {
goto out;
};
iobref_add (iobref, iobuf);
iov.iov_base = iobuf->ptr;
iov.iov_len = iobuf_pagesize (iobuf);
/* Create the xdr payload */
ret = xdr_serialize_generic (iov, req, xdrproc);
if (ret == -1) {
gf_log (THIS->name, GF_LOG_WARNING,
"failed to create XDR payload");
goto out;
}
iov.iov_len = ret;
count = 1;
}
/* Send the msg */
ret = rpc_clnt_submit (ctx->mgmt, prog, procnum, cbkfn,
&iov, count,
NULL, 0, iobref, frame, NULL, 0, NULL, 0, NULL);
out:
if (iobref)
iobref_unref (iobref);
if (iobuf)
iobuf_unref (iobuf);
return ret;
}
/* XXX: move these into @ctx */
static char oldvolfile[131072];
static int oldvollen = 0;
static int
xlator_equal_rec (xlator_t *xl1, xlator_t *xl2)
{
xlator_list_t *trav1 = NULL;
xlator_list_t *trav2 = NULL;
int ret = 0;
if (xl1 == NULL || xl2 == NULL) {
gf_log ("xlator", GF_LOG_DEBUG, "invalid argument");
return -1;
}
trav1 = xl1->children;
trav2 = xl2->children;
while (trav1 && trav2) {
ret = xlator_equal_rec (trav1->xlator, trav2->xlator);
if (ret) {
gf_log ("glfs-mgmt", GF_LOG_DEBUG,
"xlators children not equal");
goto out;
}
trav1 = trav1->next;
trav2 = trav2->next;
}
if (trav1 || trav2) {
ret = -1;
goto out;
}
if (strcmp (xl1->name, xl2->name)) {
ret = -1;
goto out;
}
out :
return ret;
}
static gf_boolean_t
is_graph_topology_equal (glusterfs_graph_t *graph1,
glusterfs_graph_t *graph2)
{
xlator_t *trav1 = NULL;
xlator_t *trav2 = NULL;
gf_boolean_t ret = _gf_true;
trav1 = graph1->first;
trav2 = graph2->first;
ret = xlator_equal_rec (trav1, trav2);
if (ret) {
gf_log ("glfs-mgmt", GF_LOG_DEBUG,
"graphs are not equal");
ret = _gf_false;
goto out;
}
ret = _gf_true;
gf_log ("glfs-mgmt", GF_LOG_DEBUG,
"graphs are equal");
out:
return ret;
}
/* Function has 3types of return value 0, -ve , 1
* return 0 =======> reconfiguration of options has succeeded
* return 1 =======> the graph has to be reconstructed and all the xlators should be inited
* return -1(or -ve) =======> Some Internal Error occurred during the operation
*/
static int
glusterfs_volfile_reconfigure (struct glfs *fs, FILE *newvolfile_fp)
{
glusterfs_graph_t *oldvolfile_graph = NULL;
glusterfs_graph_t *newvolfile_graph = NULL;
FILE *oldvolfile_fp = NULL;
glusterfs_ctx_t *ctx = NULL;
int ret = -1;
oldvolfile_fp = tmpfile ();
if (!oldvolfile_fp)
goto out;
if (!oldvollen) {
ret = 1; // Has to call INIT for the whole graph
goto out;
}
fwrite (oldvolfile, oldvollen, 1, oldvolfile_fp);
fflush (oldvolfile_fp);
if (ferror (oldvolfile_fp)) {
goto out;
}
oldvolfile_graph = glusterfs_graph_construct (oldvolfile_fp);
if (!oldvolfile_graph) {
goto out;
}
newvolfile_graph = glusterfs_graph_construct (newvolfile_fp);
if (!newvolfile_graph) {
goto out;
}
if (!is_graph_topology_equal (oldvolfile_graph,
newvolfile_graph)) {
ret = 1;
gf_log ("glfs-mgmt", GF_LOG_DEBUG,
"Graph topology not equal(should call INIT)");
goto out;
}
gf_log ("glfs-mgmt", GF_LOG_DEBUG,
"Only options have changed in the new "
"graph");
ctx = fs->ctx;
if (!ctx) {
gf_log ("glfs-mgmt", GF_LOG_ERROR,
"glusterfs_ctx_get() returned NULL");
goto out;
}
oldvolfile_graph = ctx->active;
if (!oldvolfile_graph) {
gf_log ("glfs-mgmt", GF_LOG_ERROR,
"glusterfs_ctx->active is NULL");
goto out;
}
/* */
ret = glusterfs_graph_reconfigure (oldvolfile_graph,
newvolfile_graph);
if (ret) {
gf_log ("glfs-mgmt", GF_LOG_DEBUG,
"Could not reconfigure new options in old graph");
goto out;
}
ret = 0;
out:
if (oldvolfile_fp)
fclose (oldvolfile_fp);
return ret;
}
int
mgmt_getspec_cbk (struct rpc_req *req, struct iovec *iov, int count,
void *myframe)
{
gf_getspec_rsp rsp = {0,};
call_frame_t *frame = NULL;
glusterfs_ctx_t *ctx = NULL;
int ret = 0;
ssize_t size = 0;
FILE *tmpfp = NULL;
struct glfs *fs = NULL;
frame = myframe;
ctx = frame->this->ctx;
fs = ((xlator_t *)ctx->master)->private;
if (-1 == req->rpc_status) {
ret = -1;
goto out;
}
ret = xdr_to_generic (*iov, &rsp, (xdrproc_t)xdr_gf_getspec_rsp);
if (ret < 0) {
gf_log (frame->this->name, GF_LOG_ERROR, "XDR decoding error");
ret = -1;
goto out;
}
if (-1 == rsp.op_ret) {
gf_log (frame->this->name, GF_LOG_ERROR,
"failed to get the 'volume file' from server");
ret = -1;
goto out;
}
ret = 0;
size = rsp.op_ret;
if (size == oldvollen && (memcmp (oldvolfile, rsp.spec, size) == 0)) {
gf_log (frame->this->name, GF_LOG_INFO,
"No change in volfile, continuing");
goto out;
}
tmpfp = tmpfile ();
if (!tmpfp) {
ret = -1;
goto out;
}
fwrite (rsp.spec, size, 1, tmpfp);
fflush (tmpfp);
if (ferror (tmpfp)) {
ret = -1;
goto out;
}
/* Check if only options have changed. No need to reload the
* volfile if topology hasn't changed.
* glusterfs_volfile_reconfigure returns 3 possible return states
* return 0 =======> reconfiguration of options has succeeded
* return 1 =======> the graph has to be reconstructed and all the xlators should be inited
* return -1(or -ve) =======> Some Internal Error occurred during the operation
*/
ret = glusterfs_volfile_reconfigure (fs, tmpfp);
if (ret == 0) {
gf_log ("glusterfsd-mgmt", GF_LOG_DEBUG,
"No need to re-load volfile, reconfigure done");
oldvollen = size;
memcpy (oldvolfile, rsp.spec, size);
goto out;
}
if (ret < 0) {
gf_log ("glusterfsd-mgmt", GF_LOG_DEBUG,
"Reconfigure failed !!");
goto out;
}
ret = glfs_process_volfp (fs, tmpfp);
/* tmpfp closed */
tmpfp = NULL;
if (ret)
goto out;
oldvollen = size;
memcpy (oldvolfile, rsp.spec, size);
out:
STACK_DESTROY (frame->root);
if (rsp.spec)
free (rsp.spec);
if (ret && ctx && !ctx->active) {
/* Do it only for the first time */
/* Failed to get the volume file, something wrong,
restart the process */
gf_log ("glfs-mgmt", GF_LOG_ERROR,
"failed to fetch volume file (key:%s)",
ctx->cmd_args.volfile_id);
}
if (tmpfp)
fclose (tmpfp);
return 0;
}
int
glfs_volfile_fetch (struct glfs *fs)
{
cmd_args_t *cmd_args = NULL;
gf_getspec_req req = {0, };
int ret = 0;
call_frame_t *frame = NULL;
glusterfs_ctx_t *ctx = NULL;
ctx = fs->ctx;
cmd_args = &ctx->cmd_args;
frame = create_frame (THIS, ctx->pool);
req.key = cmd_args->volfile_id;
req.flags = 0;
ret = mgmt_submit_request (&req, frame, ctx, &clnt_handshake_prog,
GF_HNDSK_GETSPEC, mgmt_getspec_cbk,
(xdrproc_t)xdr_gf_getspec_req);
return ret;
}
static int
mgmt_rpc_notify (struct rpc_clnt *rpc, void *mydata, rpc_clnt_event_t event,
void *data)
{
xlator_t *this = NULL;
cmd_args_t *cmd_args = NULL;
glusterfs_ctx_t *ctx = NULL;
struct glfs *fs = NULL;
int ret = 0;
this = mydata;
ctx = this->ctx;
fs = ((xlator_t *)ctx->master)->private;
cmd_args = &ctx->cmd_args;
switch (event) {
case RPC_CLNT_DISCONNECT:
if (!ctx->active) {
cmd_args->max_connect_attempts--;
gf_log ("glfs-mgmt", GF_LOG_ERROR,
"failed to connect with remote-host: %s",
strerror (errno));
gf_log ("glfs-mgmt", GF_LOG_INFO,
"%d connect attempts left",
cmd_args->max_connect_attempts);
if (0 >= cmd_args->max_connect_attempts)
glfs_init_done (fs, -1);
break;
}
break;
case RPC_CLNT_CONNECT:
rpc_clnt_set_connected (&((struct rpc_clnt*)ctx->mgmt)->conn);
ret = glfs_volfile_fetch (fs);
if (ret && ctx && (ctx->active == NULL)) {
/* Do it only for the first time */
/* Exit the process.. there is some wrong options */
gf_log ("glfs-mgmt", GF_LOG_ERROR,
"failed to fetch volume file (key:%s)",
ctx->cmd_args.volfile_id);
glfs_init_done (fs, -1);
}
break;
default:
break;
}
return 0;
}
int
glusterfs_mgmt_notify (int32_t op, void *data, ...)
{
int ret = 0;
switch (op)
{
case GF_EN_DEFRAG_STATUS:
break;
default:
break;
}
return ret;
}
int
glfs_mgmt_init (struct glfs *fs)
{
cmd_args_t *cmd_args = NULL;
struct rpc_clnt *rpc = NULL;
dict_t *options = NULL;
int ret = -1;
int port = GF_DEFAULT_BASE_PORT;
char *host = NULL;
glusterfs_ctx_t *ctx = NULL;
ctx = fs->ctx;
cmd_args = &ctx->cmd_args;
if (ctx->mgmt)
return 0;
if (cmd_args->volfile_server_port)
port = cmd_args->volfile_server_port;
host = "localhost";
if (cmd_args->volfile_server)
host = cmd_args->volfile_server;
ret = rpc_transport_inet_options_build (&options, host, port);
if (ret)
goto out;
rpc = rpc_clnt_new (options, THIS->ctx, THIS->name, 8);
if (!rpc) {
ret = -1;
gf_log (THIS->name, GF_LOG_WARNING,
"failed to create rpc clnt");
goto out;
}
ret = rpc_clnt_register_notify (rpc, mgmt_rpc_notify, THIS);
if (ret) {
gf_log (THIS->name, GF_LOG_WARNING,
"failed to register notify function");
goto out;
}
ret = rpcclnt_cbk_program_register (rpc, &mgmt_cbk_prog, THIS);
if (ret) {
gf_log (THIS->name, GF_LOG_WARNING,
"failed to register callback function");
goto out;
}
ctx->notify = glusterfs_mgmt_notify;
/* This value should be set before doing the 'rpc_clnt_start()' as
the notify function uses this variable */
ctx->mgmt = rpc;
ret = rpc_clnt_start (rpc);
out:
return ret;
}

244
api/src/glfs-resolve.c Normal file
View File

@ -0,0 +1,244 @@
/*
Copyright (c) 2012 Red Hat, Inc. <http://www.redhat.com>
This file is part of GlusterFS.
This file is licensed to you under your choice of the GNU Lesser
General Public License, version 3 or any later version (LGPLv3 or
later), or the GNU General Public License, version 2 (GPLv2), in all
cases as published by the Free Software Foundation.
*/
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <inttypes.h>
#include <limits.h>
#ifndef _CONFIG_H
#define _CONFIG_H
#include "config.h"
#endif
#include "glusterfs.h"
#include "logging.h"
#include "stack.h"
#include "event.h"
#include "glfs-mem-types.h"
#include "common-utils.h"
#include "syncop.h"
#include "call-stub.h"
#include "glfs-internal.h"
void
glfs_first_lookup (xlator_t *subvol)
{
loc_t loc = {0, };
int ret = -1;
loc.inode = subvol->itable->root;
memset (loc.gfid, 0, 16);
loc.gfid[15] = 1;
loc.path = "/";
loc.name = "";
ret = syncop_lookup (subvol, &loc, 0, 0, 0, 0);
gf_log (subvol->name, GF_LOG_DEBUG, "first lookup complete %d", ret);
return;
}
int
glfs_loc_touchup (loc_t *loc)
{
char *path = NULL;
int ret = -1;
char *bn = NULL;
ret = inode_path (loc->parent, loc->name, &path);
loc->path = path;
if (ret < 0 || !path) {
ret = -1;
errno = ENOMEM;
goto out;
}
bn = strrchr (path, '/');
if (bn)
bn++;
loc->name = bn;
ret = 0;
out:
return ret;
}
inode_t *
glfs_resolve_component (struct glfs *fs, xlator_t *subvol, inode_t *parent,
const char *component, struct iatt *iatt)
{
loc_t loc = {0, };
inode_t *inode = NULL;
int reval = 0;
int ret = -1;
int glret = -1;
struct iatt ciatt = {0, };
uuid_t gfid;
dict_t *xattr_req = NULL;
loc.name = component;
loc.parent = inode_ref (parent);
uuid_copy (loc.pargfid, parent->gfid);
xattr_req = dict_new ();
if (!xattr_req) {
errno = ENOMEM;
goto out;
}
ret = dict_set_static_bin (xattr_req, "gfid-req", gfid, 16);
if (ret) {
errno = ENOMEM;
goto out;
}
loc.inode = inode_grep (parent->table, parent, component);
if (loc.inode) {
uuid_copy (loc.gfid, loc.inode->gfid);
reval = 1;
} else {
uuid_generate (gfid);
loc.inode = inode_new (parent->table);
}
if (!loc.inode)
goto out;
glret = glfs_loc_touchup (&loc);
if (glret < 0) {
ret = -1;
goto out;
}
ret = syncop_lookup (subvol, &loc, xattr_req, &ciatt, NULL, NULL);
if (ret && reval) {
inode_unref (loc.inode);
loc.inode = inode_new (parent->table);
if (!loc.inode)
goto out;
uuid_generate (gfid);
ret = syncop_lookup (subvol, &loc, xattr_req, &ciatt,
NULL, NULL);
}
if (ret)
goto out;
inode = inode_link (loc.inode, loc.parent, component, &ciatt);
if (inode)
inode_lookup (inode);
if (iatt)
*iatt = ciatt;
out:
if (xattr_req)
dict_destroy (xattr_req);
loc_wipe (&loc);
return inode;
}
int
glfs_resolve (struct glfs *fs, xlator_t *subvol, const char *origpath,
loc_t *loc, struct iatt *iatt)
{
inode_t *inode = NULL;
inode_t *parent = NULL;
char *saveptr = NULL;
char *path = NULL;
char *component = NULL;
char *next_component = NULL;
int ret = -1;
struct iatt ciatt = {0, };
path = gf_strdup (origpath);
if (!path) {
errno = ENOMEM;
return -1;
}
parent = NULL;
inode = inode_ref (subvol->itable->root);
for (component = strtok_r (path, "/", &saveptr);
component; component = next_component) {
next_component = strtok_r (NULL, "/", &saveptr);
if (parent)
inode_unref (parent);
parent = inode;
inode = glfs_resolve_component (fs, subvol, parent,
component, &ciatt);
if (!inode)
break;
if (!next_component)
break;
if (!IA_ISDIR (ciatt.ia_type)) {
/* next_component exists and this component is
not a directory
*/
inode_unref (inode);
inode = NULL;
ret = -1;
errno = ENOTDIR;
break;
}
}
if (parent && next_component)
/* resolution failed mid-way */
goto out;
/* At this point, all components up to the last parent directory
have been resolved successfully (@parent). Resolution of basename
might have failed (@inode) if at all.
*/
loc->parent = parent;
if (parent) {
uuid_copy (loc->pargfid, parent->gfid);
loc->name = component;
}
loc->inode = inode;
if (inode) {
uuid_copy (loc->gfid, inode->gfid);
if (iatt)
*iatt = ciatt;
ret = 0;
}
glfs_loc_touchup (loc);
out:
GF_FREE (path);
/* do NOT loc_wipe here as only last component might be missing */
return ret;
}

546
api/src/glfs.c Normal file
View File

@ -0,0 +1,546 @@
/*
Copyright (c) 2012 Red Hat, Inc. <http://www.redhat.com>
This file is part of GlusterFS.
This file is licensed to you under your choice of the GNU Lesser
General Public License, version 3 or any later version (LGPLv3 or
later), or the GNU General Public License, version 2 (GPLv2), in all
cases as published by the Free Software Foundation.
*/
/*
TODO:
- set proper pid/lk_owner to call frames (currently buried in syncop)
- fix logging.c/h to store logfp and loglevel in glusterfs_ctx_t and
reach it via THIS.
- fd migration on graph switch.
- update syncop functions to accept/return xdata. ???
- syncop_readv to not touch params if args.op_ret < 0.
- protocol/client to reconnect immediately after portmap disconnect.
- handle SEEK_END failure in _lseek()
- handle umask (per filesystem?)
- implement glfs_set_xlator_option(), like --xlator-option
- make itables LRU based
- implement glfs_fini()
- modify syncop_fsync() to accept 'dataonly' flag
- 0-copy for readv/writev
*/
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <inttypes.h>
#include <sys/types.h>
#include <unistd.h>
#include <limits.h>
#ifndef _CONFIG_H
#define _CONFIG_H
#include "config.h"
#endif
#include "glusterfs.h"
#include "logging.h"
#include "stack.h"
#include "event.h"
#include "glfs-mem-types.h"
#include "common-utils.h"
#include "syncop.h"
#include "call-stub.h"
#include "glfs.h"
#include "glfs-internal.h"
static gf_boolean_t
vol_assigned (cmd_args_t *args)
{
return args->volfile || args->volfile_server;
}
static int
glusterfs_ctx_defaults_init (glusterfs_ctx_t *ctx)
{
call_pool_t *pool = NULL;
int ret = -1;
cmd_args_t *cmd_args = NULL;
xlator_mem_acct_init (THIS, glfs_mt_end);
cmd_args = &ctx->cmd_args;
ctx->process_uuid = generate_glusterfs_ctx_id ();
if (!ctx->process_uuid) {
goto err;
}
ctx->page_size = 128 * GF_UNIT_KB;
ctx->iobuf_pool = iobuf_pool_new ();
if (!ctx->iobuf_pool) {
goto err;
}
ctx->event_pool = event_pool_new (DEFAULT_EVENT_POOL_SIZE);
if (!ctx->event_pool) {
goto err;
}
ctx->env = syncenv_new (0);
if (!ctx->env) {
goto err;
}
pool = GF_CALLOC (1, sizeof (call_pool_t),
glfs_mt_call_pool_t);
if (!pool) {
goto err;
}
/* frame_mem_pool size 112 * 4k */
pool->frame_mem_pool = mem_pool_new (call_frame_t, 4096);
if (!pool->frame_mem_pool) {
goto err;
}
/* stack_mem_pool size 256 * 1024 */
pool->stack_mem_pool = mem_pool_new (call_stack_t, 1024);
if (!pool->stack_mem_pool) {
goto err;
}
ctx->stub_mem_pool = mem_pool_new (call_stub_t, 1024);
if (!ctx->stub_mem_pool) {
goto err;
}
ctx->dict_pool = mem_pool_new (dict_t, GF_MEMPOOL_COUNT_OF_DICT_T);
if (!ctx->dict_pool)
goto err;
ctx->dict_pair_pool = mem_pool_new (data_pair_t,
GF_MEMPOOL_COUNT_OF_DATA_PAIR_T);
if (!ctx->dict_pair_pool)
goto err;
ctx->dict_data_pool = mem_pool_new (data_t, GF_MEMPOOL_COUNT_OF_DATA_T);
if (!ctx->dict_data_pool)
goto err;
INIT_LIST_HEAD (&pool->all_frames);
INIT_LIST_HEAD (&ctx->cmd_args.xlator_options);
LOCK_INIT (&pool->lock);
ctx->pool = pool;
pthread_mutex_init (&(ctx->lock), NULL);
ret = 0;
err:
if (ret && pool) {
if (pool->frame_mem_pool)
mem_pool_destroy (pool->frame_mem_pool);
if (pool->stack_mem_pool)
mem_pool_destroy (pool->stack_mem_pool);
GF_FREE (pool);
}
if (ret && ctx) {
if (ctx->stub_mem_pool)
mem_pool_destroy (ctx->stub_mem_pool);
if (ctx->dict_pool)
mem_pool_destroy (ctx->dict_pool);
if (ctx->dict_data_pool)
mem_pool_destroy (ctx->dict_data_pool);
if (ctx->dict_pair_pool)
mem_pool_destroy (ctx->dict_pair_pool);
}
return ret;
}
static int
create_master (struct glfs *fs)
{
int ret = 0;
xlator_t *master = NULL;
master = GF_CALLOC (1, sizeof (*master),
glfs_mt_xlator_t);
if (!master)
goto err;
master->name = gf_strdup ("gfapi");
if (!master->name)
goto err;
if (xlator_set_type (master, "mount/api") == -1) {
gf_log ("glfs", GF_LOG_ERROR,
"master xlator for %s initialization failed",
fs->volname);
goto err;
}
master->ctx = fs->ctx;
master->private = fs;
master->options = get_new_dict ();
if (!master->options)
goto err;
ret = xlator_init (master);
if (ret) {
gf_log ("glfs", GF_LOG_ERROR,
"failed to initialize gfapi translator");
goto err;
}
fs->ctx->master = master;
THIS = master;
return 0;
err:
if (master) {
xlator_destroy (master);
}
return -1;
}
static FILE *
get_volfp (struct glfs *fs)
{
int ret = 0;
cmd_args_t *cmd_args = NULL;
FILE *specfp = NULL;
struct stat statbuf;
cmd_args = &fs->ctx->cmd_args;
ret = lstat (cmd_args->volfile, &statbuf);
if (ret == -1) {
gf_log ("glfs", GF_LOG_ERROR,
"%s: %s", cmd_args->volfile, strerror (errno));
return NULL;
}
if ((specfp = fopen (cmd_args->volfile, "r")) == NULL) {
gf_log ("glfs", GF_LOG_ERROR,
"volume file %s: %s",
cmd_args->volfile,
strerror (errno));
return NULL;
}
gf_log ("glfs", GF_LOG_DEBUG,
"loading volume file %s", cmd_args->volfile);
return specfp;
}
int
glfs_volumes_init (struct glfs *fs)
{
FILE *fp = NULL;
cmd_args_t *cmd_args = NULL;
int ret = 0;
cmd_args = &fs->ctx->cmd_args;
if (!vol_assigned (cmd_args))
return -1;
if (cmd_args->volfile_server) {
ret = glfs_mgmt_init (fs);
goto out;
}
fp = get_volfp (fs);
if (!fp) {
gf_log ("glfs", GF_LOG_ERROR,
"Cannot reach volume specification file");
ret = -1;
goto out;
}
ret = glfs_process_volfp (fs, fp);
if (ret)
goto out;
out:
return ret;
}
///////////////////////////////////////////////////////////////////////////////
struct glfs *
glfs_from_glfd (struct glfs_fd *glfd)
{
return ((xlator_t *)glfd->fd->inode->table->xl->ctx->master)->private;
}
void
glfs_fd_destroy (struct glfs_fd *glfd)
{
if (!glfd)
return;
if (glfd->fd)
fd_unref (glfd->fd);
GF_FREE (glfd);
}
xlator_t *
glfs_fd_subvol (struct glfs_fd *glfd)
{
xlator_t *subvol = NULL;
if (!glfd)
return NULL;
subvol = glfd->fd->inode->table->xl;
return subvol;
}
xlator_t *
glfs_active_subvol (struct glfs *fs)
{
xlator_t *subvol = NULL;
inode_table_t *itable = NULL;
pthread_mutex_lock (&fs->mutex);
{
while (!fs->init)
pthread_cond_wait (&fs->cond, &fs->mutex);
subvol = fs->active_subvol;
}
pthread_mutex_unlock (&fs->mutex);
if (!subvol)
return NULL;
if (!subvol->itable) {
itable = inode_table_new (0, subvol);
if (!itable) {
errno = ENOMEM;
return NULL;
}
subvol->itable = itable;
glfs_first_lookup (subvol);
}
return subvol;
}
static void *
glfs_poller (void *data)
{
struct glfs *fs = NULL;
fs = data;
event_dispatch (fs->ctx->event_pool);
return NULL;
}
struct glfs *
glfs_new (const char *volname)
{
struct glfs *fs = NULL;
int ret = -1;
glusterfs_ctx_t *ctx = NULL;
/* first globals init, for gf_mem_acct_enable_set () */
ret = glusterfs_globals_init ();
if (ret)
return NULL;
ctx = glusterfs_ctx_new ();
if (!ctx) {
return NULL;
}
THIS->ctx = ctx;
/* then ctx_defaults_init, for xlator_mem_acct_init(THIS) */
ret = glusterfs_ctx_defaults_init (ctx);
if (ret)
return NULL;
fs = GF_CALLOC (1, sizeof (*fs), glfs_mt_glfs_t);
if (!fs)
return NULL;
fs->ctx = ctx;
glfs_set_logging (fs, "/dev/null", 0);
fs->ctx->cmd_args.volfile_id = gf_strdup (volname);
fs->volname = gf_strdup (volname);
pthread_mutex_init (&fs->mutex, NULL);
pthread_cond_init (&fs->cond, NULL);
return fs;
}
int
glfs_set_volfile (struct glfs *fs, const char *volfile)
{
cmd_args_t *cmd_args = NULL;
cmd_args = &fs->ctx->cmd_args;
if (vol_assigned (cmd_args))
return -1;
cmd_args->volfile = gf_strdup (volfile);
return 0;
}
int
glfs_set_volfile_server (struct glfs *fs, const char *transport,
const char *host, int port)
{
cmd_args_t *cmd_args = NULL;
cmd_args = &fs->ctx->cmd_args;
if (vol_assigned (cmd_args))
return -1;
cmd_args->volfile_server = gf_strdup (host);
cmd_args->volfile_server_transport = gf_strdup (transport);
cmd_args->max_connect_attempts = 2;
return 0;
}
int
glfs_set_logging (struct glfs *fs, const char *logfile, int loglevel)
{
int ret = -1;
ret = gf_log_init (logfile);
if (ret)
return ret;
gf_log_set_loglevel (loglevel);
return ret;
}
int
glfs_init_wait (struct glfs *fs)
{
int ret = -1;
pthread_mutex_lock (&fs->mutex);
{
while (!fs->init)
pthread_cond_wait (&fs->cond,
&fs->mutex);
ret = fs->ret;
}
pthread_mutex_unlock (&fs->mutex);
return ret;
}
void
glfs_init_done (struct glfs *fs, int ret)
{
if (fs->init_cbk) {
fs->init_cbk (fs, ret);
return;
}
pthread_mutex_lock (&fs->mutex);
{
fs->init = 1;
fs->ret = ret;
pthread_cond_broadcast (&fs->cond);
}
pthread_mutex_unlock (&fs->mutex);
}
int
glfs_init_common (struct glfs *fs)
{
int ret = -1;
ret = create_master (fs);
if (ret)
return ret;
ret = pthread_create (&fs->poller, NULL, glfs_poller, fs);
if (ret)
return ret;
ret = glfs_volumes_init (fs);
if (ret)
return ret;
return ret;
}
int
glfs_init_async (struct glfs *fs, glfs_init_cbk cbk)
{
int ret = -1;
fs->init_cbk = cbk;
ret = glfs_init_common (fs);
return ret;
}
int
glfs_init (struct glfs *fs)
{
int ret = -1;
ret = glfs_init_common (fs);
if (ret)
return ret;
ret = glfs_init_wait (fs);
return ret;
}
int
glfs_fini (struct glfs *fs)
{
int ret = -1;
return ret;
}

366
api/src/glfs.h Normal file
View File

@ -0,0 +1,366 @@
/*
Copyright (c) 2012 Red Hat, Inc. <http://www.redhat.com>
This file is part of GlusterFS.
This file is licensed to you under your choice of the GNU Lesser
General Public License, version 3 or any later version (LGPLv3 or
later), or the GNU General Public License, version 2 (GPLv2), in all
cases as published by the Free Software Foundation.
*/
#ifndef _GLFS_H
#define _GLFS_H
/*
Enforce the following flags as libgfapi is built
with them, and we want programs linking against them to also
be built with these flags. This is necessary as it affects
some of the structures defined in libc headers (like struct stat)
and those definitions need to be consistently compiled in
both the library and the application.
*/
#ifndef _FILE_OFFSET_BITS
#define _FILE_OFFSET_BITS 64
#endif
#ifndef __USE_FILE_OFFSET64
#define __USE_FILE_OFFSET64
#endif
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/uio.h>
#include <unistd.h>
#include <sys/cdefs.h>
__BEGIN_DECLS
/* The filesystem object. One object per 'virtual mount' */
struct glfs;
typedef struct glfs glfs_t;
/*
SYNOPSIS
glfs_new: Create a new 'virtual mount' object.
DESCRIPTION
This is most likely the very first function you will use. This function
will create a new glfs_t (virtual mount) object in memory.
On this newly created glfs_t, you need to be either set a volfile path
(glfs_set_volfile) or a volfile server (glfs_set_volfile_server).
The glfs_t object needs to be initialized with glfs_init() before you
can start issuing file operations on it.
PARAMETERS
@volname: Name of the volume. This identifies the server-side volume and
the fetched volfile (equivalent of --volfile-id command line
parameter to glusterfsd). When used with glfs_set_volfile() the
@volname has no effect (except for appearing in log messages).
RETURN VALUES
NULL : Out of memory condition.
Others : Pointer to the newly created glfs_t virtual mount object.
*/
glfs_t *glfs_new (const char *volname);
/*
SYNOPSIS
glfs_set_volfile: Specify the path to the volume specification file.
DESCRIPTION
If you are using a static volume specification file (without dynamic
volume management abilities from the CLI), then specify the path to
the volume specification file.
This is incompatible with glfs_set_volfile_server().
PARAMETERS
@fs: The 'virtual mount' object to be configured with the volume
specification file.
@volfile: Path to the locally available volume specification file.
RETURN VALUES
0 : Success.
-1 : Failure. @errno will be set with the type of failure.
*/
int glfs_set_volfile (glfs_t *fs, const char *volfile);
/*
SYNOPSIS
glfs_set_volfile_server: Specify the address of management server.
DESCRIPTION
This function specifies the address of the management server (glusterd)
to connect, and establish the volume configuration. The @volname
parameter passed to glfs_new() is the volume which will be virtually
mounted as the glfs_t object. All operations performed by the CLI at
the management server will automatically be reflected in the 'virtual
mount' object as it maintains a connection to glusterd and polls on
configuration change notifications.
This is incompatible with glfs_set_volfile().
PARAMETERS
@fs: The 'virtual mount' object to be configured with the volume
specification file.
@transport: String specifying the transport used to connect to the
management daemon. Specifying NULL will result in the usage
of the default (socket) transport type. Permitted values
are those what you specify as transport-type in a volume
specification file (e.g "socket", "rdma", "unix".)
@host: String specifying the address of where to find the management
daemon. Depending on the transport type this would either be
an FQDN (e.g: "storage01.company.com"), ASCII encoded IP
address "192.168.22.1", or a UNIX domain socket path (e.g
"/tmp/glusterd.socket".)
@port: The TCP port number where gluster management daemon is listening.
Specifying 0 uses the default port number GF_DEFAULT_BASE_PORT.
This parameter is unused if you are using a UNIX domain socket.
RETURN VALUES
0 : Success.
-1 : Failure. @errno will be set with the type of failure.
*/
int glfs_set_volfile_server (glfs_t *fs, const char *transport,
const char *host, int port);
/*
SYNOPSIS
glfs_set_logging: Specify logging parameters.
DESCRIPTION
This function specifies logging parameters for the virtual mount.
Default log file is /dev/null.
PARAMETERS
@fs: The 'virtual mount' object to be configured with the logging parameters.
@logfile: The logfile to be used for logging. Will be created if it does not
already exist (provided system permissions allow.)
@loglevel: Numerical value specifying the degree of verbosity. Higher the
value, more verbose the logging.
RETURN VALUES
0 : Success.
-1 : Failure. @errno will be set with the type of failure.
*/
int glfs_set_logging (glfs_t *fs, const char *logfile, int loglevel);
/*
SYNOPSIS
glfs_init: Initialize the 'virtual mount'
DESCRIPTION
This function initializes the glfs_t object. This consists of many steps:
- Spawn a poll-loop thread.
- Establish connection to management daemon and receive volume specification.
- Construct translator graph and initialize graph.
- Wait for initialization (connecting to all bricks) to complete.
PARAMETERS
@fs: The 'virtual mount' object to be initialized.
RETURN VALUES
0 : Success.
-1 : Failure. @errno will be set with the type of failure.
*/
int glfs_init (glfs_t *fs);
int glfs_fini (glfs_t *fs);
/*
* FILE OPERATION
*
* What follows are filesystem operations performed on the
* 'virtual mount'. The calls here are kept as close to
* the POSIX system calls as possible.
*
* Notes:
*
* - All paths specified, even if absolute, are relative to the
* root of the virtual mount and not the system root (/).
*
*/
/* The file descriptor object. One per open file/directory. */
struct glfs_fd;
typedef struct glfs_fd glfs_fd_t;
/*
SYNOPSIS
glfs_open: Open a file.
DESCRIPTION
This function opens a file on a virtual mount.
PARAMETERS
@fs: The 'virtual mount' object to be initialized.
@path: Path of the file within the virtual mount.
@flags: Open flags. See open(2). O_CREAT is not supported.
Use glfs_creat() for creating files.
RETURN VALUES
NULL : Failure. @errno will be set with the type of failure.
Others : Pointer to the opened glfs_fd_t.
*/
glfs_fd_t *glfs_open (glfs_t *fs, const char *path, int flags);
/*
SYNOPSIS
glfs_creat: Create a file.
DESCRIPTION
This function opens a file on a virtual mount.
PARAMETERS
@fs: The 'virtual mount' object to be initialized.
@path: Path of the file within the virtual mount.
@mode: Permission of the file to be created.
@flags: Create flags. See open(2). O_EXCL is supported.
RETURN VALUES
NULL : Failure. @errno will be set with the type of failure.
Others : Pointer to the opened glfs_fd_t.
*/
glfs_fd_t *glfs_creat (glfs_t *fs, const char *path, int flags,
mode_t mode);
int glfs_close (glfs_fd_t *fd);
glfs_t *glfs_from_glfd (glfs_fd_t *fd);
typedef void (*glfs_io_cbk) (glfs_fd_t *fd, ssize_t ret, void *data);
// glfs_{read,write}[_async]
ssize_t glfs_read (glfs_fd_t *fd, void *buf, size_t count, int flags);
ssize_t glfs_write (glfs_fd_t *fd, const void *buf, size_t count, int flags);
int glfs_read_async (glfs_fd_t *fd, void *buf, size_t count, int flags,
glfs_io_cbk fn, void *data);
int glfs_write_async (glfs_fd_t *fd, const void *buf, size_t count, int flags,
glfs_io_cbk fn, void *data);
// glfs_{read,write}v[_async]
ssize_t glfs_readv (glfs_fd_t *fd, const struct iovec *iov, int iovcnt,
int flags);
ssize_t glfs_writev (glfs_fd_t *fd, const struct iovec *iov, int iovcnt,
int flags);
int glfs_readv_async (glfs_fd_t *fd, const struct iovec *iov, int count,
int flags, glfs_io_cbk fn, void *data);
int glfs_writev_async (glfs_fd_t *fd, const struct iovec *iov, int count,
int flags, glfs_io_cbk fn, void *data);
// glfs_p{read,write}[_async]
ssize_t glfs_pread (glfs_fd_t *fd, void *buf, size_t count, off_t offset,
int flags);
ssize_t glfs_pwrite (glfs_fd_t *fd, const void *buf, size_t count,
off_t offset, int flags);
int glfs_pread_async (glfs_fd_t *fd, void *buf, size_t count, off_t offset,
int flags, glfs_io_cbk fn, void *data);
int glfs_pwrite_async (glfs_fd_t *fd, const void *buf, int count, off_t offset,
int flags, glfs_io_cbk fn, void *data);
// glfs_p{read,write}v[_async]
ssize_t glfs_preadv (glfs_fd_t *fd, const struct iovec *iov, int iovcnt,
off_t offset, int flags);
ssize_t glfs_pwritev (glfs_fd_t *fd, const struct iovec *iov, int iovcnt,
off_t offset, int flags);
int glfs_preadv_async (glfs_fd_t *fd, const struct iovec *iov, int count,
off_t offset, int flags, glfs_io_cbk fn, void *data);
int glfs_pwritev_async (glfs_fd_t *fd, const struct iovec *iov, int count,
off_t offset, int flags, glfs_io_cbk fn, void *data);
off_t glfs_lseek (glfs_fd_t *fd, off_t offset, int whence);
int glfs_truncate (glfs_t *fs, const char *path, off_t length);
int glfs_ftruncate (glfs_fd_t *fd, off_t length);
int glfs_ftruncate_async (glfs_fd_t *fd, off_t length, glfs_io_cbk fn,
void *data);
int glfs_lstat (glfs_t *fs, const char *path, struct stat *buf);
int glfs_fstat (glfs_fd_t *fd, struct stat *buf);
int glfs_fsync (glfs_fd_t *fd);
int glfs_fsync_async (glfs_fd_t *fd, glfs_io_cbk fn, void *data);
int glfs_fdatasync (glfs_fd_t *fd);
int glfs_fdatasync_async (glfs_fd_t *fd, glfs_io_cbk fn, void *data);
__END_DECLS
#endif /* !_GLFS_H */

View File

@ -142,6 +142,8 @@ AC_CONFIG_FILES([Makefile
xlators/mgmt/Makefile
xlators/mgmt/glusterd/Makefile
xlators/mgmt/glusterd/src/Makefile
api/Makefile
api/src/Makefile
glusterfs.spec])
AC_CANONICAL_HOST