diff options
| -rw-r--r-- | Makefile.am | 3 | ||||
| -rw-r--r-- | api/Makefile.am | 1 | ||||
| -rw-r--r-- | api/src/Makefile.am | 30 | ||||
| -rw-r--r-- | api/src/glfs-fops.c | 829 | ||||
| -rw-r--r-- | api/src/glfs-internal.h | 74 | ||||
| -rw-r--r-- | api/src/glfs-master.c | 113 | ||||
| -rw-r--r-- | api/src/glfs-mem-types.h | 28 | ||||
| -rw-r--r-- | api/src/glfs-mgmt.c | 629 | ||||
| -rw-r--r-- | api/src/glfs-resolve.c | 244 | ||||
| -rw-r--r-- | api/src/glfs.c | 546 | ||||
| -rw-r--r-- | api/src/glfs.h | 366 | ||||
| -rw-r--r-- | configure.ac | 2 | 
12 files changed, 2864 insertions, 1 deletions
diff --git a/Makefile.am b/Makefile.am index 6693bb8767a..3cdd4dfb3b3 100644 --- a/Makefile.am +++ b/Makefile.am @@ -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 =  diff --git a/api/Makefile.am b/api/Makefile.am new file mode 100644 index 00000000000..af437a64d6d --- /dev/null +++ b/api/Makefile.am @@ -0,0 +1 @@ +SUBDIRS = src diff --git a/api/src/Makefile.am b/api/src/Makefile.am new file mode 100644 index 00000000000..f5fb9e70b44 --- /dev/null +++ b/api/src/Makefile.am @@ -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) diff --git a/api/src/glfs-fops.c b/api/src/glfs-fops.c new file mode 100644 index 00000000000..f3fba84e4e7 --- /dev/null +++ b/api/src/glfs-fops.c @@ -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; +} + diff --git a/api/src/glfs-internal.h b/api/src/glfs-internal.h new file mode 100644 index 00000000000..967be475cce --- /dev/null +++ b/api/src/glfs-internal.h @@ -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 */ diff --git a/api/src/glfs-master.c b/api/src/glfs-master.c new file mode 100644 index 00000000000..0806c3077b7 --- /dev/null +++ b/api/src/glfs-master.c @@ -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 = { +}; diff --git a/api/src/glfs-mem-types.h b/api/src/glfs-mem-types.h new file mode 100644 index 00000000000..dc5da30557a --- /dev/null +++ b/api/src/glfs-mem-types.h @@ -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 + diff --git a/api/src/glfs-mgmt.c b/api/src/glfs-mgmt.c new file mode 100644 index 00000000000..526d1ae4d7d --- /dev/null +++ b/api/src/glfs-mgmt.c @@ -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; +} + diff --git a/api/src/glfs-resolve.c b/api/src/glfs-resolve.c new file mode 100644 index 00000000000..c03c4154db0 --- /dev/null +++ b/api/src/glfs-resolve.c @@ -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; +} + diff --git a/api/src/glfs.c b/api/src/glfs.c new file mode 100644 index 00000000000..830efb23d65 --- /dev/null +++ b/api/src/glfs.c @@ -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; +} diff --git a/api/src/glfs.h b/api/src/glfs.h new file mode 100644 index 00000000000..14d41356a02 --- /dev/null +++ b/api/src/glfs.h @@ -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 */ diff --git a/configure.ac b/configure.ac index 4214a0787f8..0b07c6c1f36 100644 --- a/configure.ac +++ b/configure.ac @@ -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  | 
