diff options
author | Anand Avati <avati@redhat.com> | 2012-07-12 15:37:38 -0700 |
---|---|---|
committer | Anand Avati <avati@redhat.com> | 2012-07-18 12:10:44 -0700 |
commit | 2475e0193c4b4a37028bd8168113d6cd6949fe0e (patch) | |
tree | cc11b8a64601a94ac9c0603e3bc12eee9c796b56 /api/src/glfs-fops.c | |
parent | 162505c019934c13aadf63ed82d4532d5cf5ca82 (diff) |
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>
Diffstat (limited to 'api/src/glfs-fops.c')
-rw-r--r-- | api/src/glfs-fops.c | 829 |
1 files changed, 829 insertions, 0 deletions
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; +} + |