From 2cc1fbf020798edee97d9f626a767ecec5deca69 Mon Sep 17 00:00:00 2001 From: "M. Mohan Kumar" Date: Thu, 29 Nov 2012 21:46:05 +0530 Subject: BD Backend: Open,read and related calls support for LV BUG: 805138 Change-Id: I811c179d4244342537dbedb8a24fd2ec628942ed Signed-off-by: M. Mohan Kumar Reviewed-on: http://review.gluster.org/3552 Tested-by: Gluster Build System Reviewed-by: Vijay Bellur --- xlators/storage/bd_map/src/bd_map.c | 271 +++++++++++++++++++++++++++++++ xlators/storage/bd_map/src/bd_map.h | 1 + xlators/storage/bd_map/src/bd_map_help.c | 19 +++ xlators/storage/bd_map/src/bd_map_help.h | 5 + 4 files changed, 296 insertions(+) (limited to 'xlators') diff --git a/xlators/storage/bd_map/src/bd_map.c b/xlators/storage/bd_map/src/bd_map.c index e7a684c5..29de9fc1 100644 --- a/xlators/storage/bd_map/src/bd_map.c +++ b/xlators/storage/bd_map/src/bd_map.c @@ -34,6 +34,183 @@ /* Regular fops */ +int +bd_access (call_frame_t *frame, xlator_t *this, + loc_t *loc, int32_t mask, dict_t *xdict) +{ + int32_t op_ret = -1; + int32_t op_errno = 0; + char path[PATH_MAX] = {0, }; + + VALIDATE_OR_GOTO (frame, out); + VALIDATE_OR_GOTO (this, out); + VALIDATE_OR_GOTO (loc, out); + + sprintf (path, "/dev/mapper/%s", loc->path); + op_ret = access (path, mask & 07); + if (op_ret == -1) { + op_errno = errno; + gf_log (this->name, GF_LOG_ERROR, "access failed on %s: %s", + loc->path, strerror (op_errno)); + goto out; + } + op_ret = 0; +out: + STACK_UNWIND_STRICT (access, frame, op_ret, op_errno, NULL); + + return 0; +} + +int32_t +bd_open (call_frame_t *frame, xlator_t *this, + loc_t *loc, int32_t flags, fd_t *fd, dict_t *xdata) +{ + int32_t op_ret = -1; + int32_t op_errno = 0; + int32_t _fd = -1; + bd_fd_t *bd_fd = NULL; + bd_entry_t *lventry = NULL; + bd_priv_t *priv = NULL; + char *devpath = NULL; + + VALIDATE_OR_GOTO (frame, out); + VALIDATE_OR_GOTO (this, out); + VALIDATE_OR_GOTO (this->private, out); + VALIDATE_OR_GOTO (loc, out); + VALIDATE_OR_GOTO (fd, out); + + priv = this->private; + VALIDATE_OR_GOTO (priv, out); + + BD_ENTRY (priv, lventry, loc->path); + if (!lventry) { + op_errno = ENOENT; + goto out; + } + + gf_asprintf (&devpath, "/dev/%s/%s", lventry->parent->name, + lventry->name); + _fd = open (devpath, flags, 0); + if (_fd == -1) { + op_errno = errno; + gf_log (this->name, GF_LOG_ERROR, + "open on %s: %s", devpath, strerror (op_errno)); + goto out; + } + + bd_fd = GF_CALLOC (1, sizeof(*bd_fd), gf_bd_fd); + if (!bd_fd) { + op_errno = errno; + goto out; + } + bd_fd->entry = lventry; + bd_fd->fd = _fd; + + op_ret = fd_ctx_set (fd, this, (uint64_t)(long)bd_fd); + if (op_ret) { + gf_log (this->name, GF_LOG_WARNING, + "failed to set the fd context path=%s fd=%p", + loc->name, fd); + goto out; + } + + op_ret = 0; +out: + if (op_ret == -1) { + if (_fd != -1) + close (_fd); + /* FIXME: Should we call fd_ctx_set with NULL? */ + if (bd_fd) + GF_FREE (bd_fd); + if (lventry) + BD_PUT_ENTRY (priv, lventry); + } + if (devpath) + GF_FREE (devpath); + + STACK_UNWIND_STRICT (open, frame, op_ret, op_errno, fd, NULL); + + return 0; +} + +int +bd_readv (call_frame_t *frame, xlator_t *this, fd_t *fd, size_t size, + off_t offset, uint32_t flags, dict_t *xdata) +{ + uint64_t tmp_bd_fd = 0; + int32_t op_ret = -1; + int32_t op_errno = 0; + int _fd = -1; + bd_priv_t *priv = NULL; + struct iobuf *iobuf = NULL; + struct iobref *iobref = NULL; + struct iovec vec = {0, }; + bd_fd_t *bd_fd = NULL; + int ret = -1; + struct iatt stbuf = {0, }; + + VALIDATE_OR_GOTO (frame, out); + VALIDATE_OR_GOTO (this, out); + VALIDATE_OR_GOTO (fd, out); + VALIDATE_OR_GOTO (this->private, out); + + priv = this->private; + VALIDATE_OR_GOTO (priv, out); + + ret = fd_ctx_get (fd, this, &tmp_bd_fd); + if (ret < 0) { + op_errno = -EINVAL; + gf_log (this->name, GF_LOG_WARNING, + "bd_fd is NULL from fd=%p", fd); + goto out; + } + bd_fd = (bd_fd_t *)(long)tmp_bd_fd; + if (!size) { + op_errno = EINVAL; + gf_log (this->name, GF_LOG_WARNING, "size=%"GF_PRI_SIZET, size); + goto out; + } + iobuf = iobuf_get2 (this->ctx->iobuf_pool, size); + if (!iobuf) { + op_errno = ENOMEM; + goto out; + } + _fd = bd_fd->fd; + op_ret = pread (_fd, iobuf->ptr, size, offset); + if (op_ret == -1) { + op_errno = errno; + gf_log (this->name, GF_LOG_ERROR, + "read failed on fd=%p: %s", fd, + strerror (op_errno)); + goto out; + } + + vec.iov_base = iobuf->ptr; + vec.iov_len = op_ret; + + iobref = iobref_new (); + iobref_add (iobref, iobuf); + BD_ENTRY_UPDATE_ATIME (bd_fd->entry); + + memcpy (&stbuf, bd_fd->entry->attr, sizeof(stbuf)); + + /* Hack to notify higher layers of EOF. */ + if (bd_fd->entry->size == 0) + op_errno = ENOENT; + else if ((offset + vec.iov_len) >= bd_fd->entry->size) + op_errno = ENOENT; + op_ret = vec.iov_len; +out: + STACK_UNWIND_STRICT (readv, frame, op_ret, op_errno, + &vec, 1, &stbuf, iobref, NULL); + + if (iobref) + iobref_unref (iobref); + if (iobuf) + iobuf_unref (iobuf); + return 0; +} + int32_t bd_lookup (call_frame_t *frame, xlator_t *this, loc_t *loc, dict_t *xattr_req) { @@ -134,6 +311,39 @@ out: return 0; } +int32_t +bd_fstat (call_frame_t *frame, xlator_t *this, fd_t *fd, dict_t *xdata) +{ + int ret = -1; + int32_t op_ret = -1; + int32_t op_errno = 0; + uint64_t tmp_bd_fd = 0; + struct iatt buf = {0, }; + bd_fd_t *bd_fd = NULL; + int _fd = -1; + + VALIDATE_OR_GOTO (frame, out); + VALIDATE_OR_GOTO (this, out); + VALIDATE_OR_GOTO (fd, out); + + ret = fd_ctx_get (fd, this, &tmp_bd_fd); + if (ret < 0) { + gf_log (this->name, GF_LOG_WARNING, + "bd_fd is NULL, fd=%p", fd); + op_errno = -EINVAL; + goto out; + } + bd_fd = (bd_fd_t *)(long)tmp_bd_fd; + _fd = bd_fd->fd; + + memcpy (&buf, bd_fd->entry->attr, sizeof(buf)); + op_ret = 0; + +out: + STACK_UNWIND_STRICT (stat, frame, op_ret, op_errno, &buf, NULL); + return 0; +} + int32_t bd_opendir (call_frame_t *frame, xlator_t *this, loc_t *loc, fd_t *fd, dict_t *xdata) @@ -290,6 +500,61 @@ out: return 0; } +int32_t +bd_release (xlator_t *this, fd_t *fd) +{ + bd_fd_t *bd_fd = NULL; + int ret = -1; + uint64_t tmp_bd_fd = 0; + bd_priv_t *priv = NULL; + + VALIDATE_OR_GOTO (this, out); + VALIDATE_OR_GOTO (fd, out); + + priv = this->private; + VALIDATE_OR_GOTO (priv, out); + + ret = fd_ctx_get (fd, this, &tmp_bd_fd); + if (ret < 0) { + gf_log (this->name, GF_LOG_WARNING, "bd_fd is NULL from fd=%p", + fd); + goto out; + } + bd_fd = (bd_fd_t *) (long)tmp_bd_fd; + close (bd_fd->fd); + BD_PUT_ENTRY (priv, bd_fd->entry); + + GF_FREE (bd_fd); +out: + return 0; +} + +int32_t +bd_flush (call_frame_t *frame, xlator_t *this, fd_t *fd, dict_t *xdict) +{ + int32_t op_ret = -1; + int32_t op_errno = 0; + int ret = -1; + uint64_t tmp_bd_fd = 0; + + VALIDATE_OR_GOTO (frame, out); + VALIDATE_OR_GOTO (this, out); + VALIDATE_OR_GOTO (fd, out); + + ret = fd_ctx_get (fd, this, &tmp_bd_fd); + if (ret < 0) { + op_errno = -EINVAL; + gf_log (this->name, GF_LOG_WARNING, + "bd_fd is NULL on fd=%p", fd); + goto out; + } + op_ret = 0; +out: + STACK_UNWIND_STRICT (flush, frame, op_ret, op_errno, NULL); + + return 0; +} + int __bd_fill_readdir (pthread_rwlock_t *bd_lock, bd_fd_t *bd_fd, off_t off, size_t size, gf_dirent_t *entries) @@ -881,10 +1146,16 @@ struct xlator_fops fops = { .readdirp = bd_readdirp, .stat = bd_stat, .statfs = bd_statfs, + .open = bd_open, + .access = bd_access, + .flush = bd_flush, + .readv = bd_readv, + .fstat = bd_fstat, }; struct xlator_cbks cbks = { .releasedir = bd_releasedir, + .release = bd_release, }; struct volume_options options[] = { diff --git a/xlators/storage/bd_map/src/bd_map.h b/xlators/storage/bd_map/src/bd_map.h index 974ec928..936defbb 100644 --- a/xlators/storage/bd_map/src/bd_map.h +++ b/xlators/storage/bd_map/src/bd_map.h @@ -64,6 +64,7 @@ typedef struct bd_entry { typedef struct bd_fd { bd_entry_t *entry; bd_entry_t *p_entry; /* Parent entry */ + int fd; } bd_fd_t; typedef struct bd_priv { diff --git a/xlators/storage/bd_map/src/bd_map_help.c b/xlators/storage/bd_map/src/bd_map_help.c index 2b5c321f..3576d705 100644 --- a/xlators/storage/bd_map/src/bd_map_help.c +++ b/xlators/storage/bd_map/src/bd_map_help.c @@ -47,6 +47,25 @@ static void bd_entry_get_ino (uint64_t *inode) UNLOCK (&inode_lk); } +void bd_update_time (bd_entry_t *entry, int type) +{ + struct timespec ts; + + clock_gettime (CLOCK_REALTIME, &ts); + if (type == 0) { + entry->attr->ia_mtime = ts.tv_sec; + entry->attr->ia_mtime_nsec = ts.tv_nsec; + entry->attr->ia_atime = ts.tv_sec; + entry->attr->ia_atime_nsec = ts.tv_nsec; + } else if (type == 1) { + entry->attr->ia_mtime = ts.tv_sec; + entry->attr->ia_mtime_nsec = ts.tv_nsec; + } else { + entry->attr->ia_atime = ts.tv_sec; + entry->attr->ia_atime_nsec = ts.tv_nsec; + } +} + static bd_entry_t *bd_entry_init (const char *name) { bd_entry_t *bdentry; diff --git a/xlators/storage/bd_map/src/bd_map_help.h b/xlators/storage/bd_map/src/bd_map_help.h index 997b8b71..46862f32 100644 --- a/xlators/storage/bd_map/src/bd_map_help.h +++ b/xlators/storage/bd_map/src/bd_map_help.h @@ -47,6 +47,10 @@ BD_UNLOCK (&priv->lock); \ } while (0) +#define BD_ENTRY_UPDATE_TIME(bdentry) bd_update_time (bdentry, 0) +#define BD_ENTRY_UPDATE_ATIME(bdentry) bd_update_time (bdentry, 2) +#define BD_ENTRY_UPDATE_MTIME(bdentry) bd_update_time (bdentry, 1) + extern bd_entry_t *bd_rootp; extern gf_lock_t inode_lk; @@ -59,5 +63,6 @@ bd_entry_t *bd_entry_get (const char *name); void bd_entry_put (bd_entry_t *entry); int bd_build_lv_list (bd_priv_t *priv, char *vg); int bd_entry_cleanup (void); +void bd_update_time (bd_entry_t *entry, int type); #endif -- cgit