diff options
Diffstat (limited to 'xlators/features/snapview-server/src/snapview-server.c')
-rw-r--r-- | xlators/features/snapview-server/src/snapview-server.c | 1155 |
1 files changed, 67 insertions, 1088 deletions
diff --git a/xlators/features/snapview-server/src/snapview-server.c b/xlators/features/snapview-server/src/snapview-server.c index b90ad24d7d0..21f3dbee563 100644 --- a/xlators/features/snapview-server/src/snapview-server.c +++ b/xlators/features/snapview-server/src/snapview-server.c @@ -22,1026 +22,6 @@ #include "syscall.h" #include <pthread.h> -static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; -static pthread_cond_t condvar = PTHREAD_COND_INITIALIZER; -static gf_boolean_t snap_worker_resume; - -void -snaplist_refresh (void *data) -{ - xlator_t *this = NULL; - int ret = 0; - svs_private_t *priv = NULL; - - this = data; - priv = this->private; - - ret = svs_get_snapshot_list (this); - if (ret) { - gf_log ("snapview-server", GF_LOG_WARNING, - "Error retrieving refreshed snapshot list"); - } - - return; -} - -void * -snaplist_worker (void *data) -{ - xlator_t *this = NULL; - int ret = 0; - struct timespec timeout = {0, }; - svs_private_t *priv = NULL; - glusterfs_ctx_t *ctx = NULL; - - this = data; - priv = this->private; - ctx = this->ctx; - GF_ASSERT (ctx); - - ret = pthread_mutex_lock (&priv->snaplist_lock); - if (ret != 0) { - goto out; - } - - priv->is_snaplist_done = 1; - - ret = pthread_mutex_unlock (&priv->snaplist_lock); - if (ret != 0) { - goto out; - } - - while (1) { - timeout.tv_sec = 300; - timeout.tv_nsec = 0; - priv->snap_timer = gf_timer_call_after (ctx, timeout, - snaplist_refresh, - data); - ret = pthread_mutex_lock (&mutex); - if (ret != 0) { - goto out; - } - /* - * We typically expect this mutex lock to succeed - * A corner case might be when snaplist_worker is - * scheduled and it tries to acquire this lock - * but we are in the middle of xlator _fini() - * when the mutex is itself being destroyed. - * To prevent any undefined behavior or segfault - * at that point, we check the ret here. - * If mutex is destroyed we expect a EINVAL for a - * mutex which is not initialized properly. - * Bail then. - * Same for the unlock case. - */ - while (!snap_worker_resume) { - pthread_cond_wait (&condvar, &mutex); - } - - snap_worker_resume = _gf_false; - - ret = pthread_mutex_unlock (&mutex); - if (ret != 0) { - goto out; - } - } - -out: - return NULL; -} - -int -svs_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; - - GF_VALIDATE_OR_GOTO ("snapview-server", frame, out); - GF_VALIDATE_OR_GOTO ("snapview-server", req, out); - GF_VALIDATE_OR_GOTO ("snapview-server", ctx, out); - GF_VALIDATE_OR_GOTO ("snapview-server", prog, out); - - GF_ASSERT (frame->this); - - 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 (frame->this->name, GF_LOG_WARNING, - "Failed to create XDR payload"); - goto out; - } - iov.iov_len = ret; - count = 1; - } - - 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; -} - - -int mgmt_get_snapinfo_cbk (struct rpc_req *req, struct iovec *iov, - int count, void *myframe) -{ - gf_getsnap_name_uuid_rsp rsp = {0,}; - call_frame_t *frame = NULL; - glusterfs_ctx_t *ctx = NULL; - int ret = 0; - dict_t *dict = NULL; - char key[1024] = {0}; - int snapcount = 0; - svs_private_t *priv = NULL; - xlator_t *this = NULL; - int i = 0; - int j = 0; - char *value = NULL; - snap_dirent_t *dirents = NULL; - snap_dirent_t *old_dirents = NULL; - - GF_VALIDATE_OR_GOTO ("snapview-server", req, error_out); - GF_VALIDATE_OR_GOTO ("snapview-server", myframe, error_out); - GF_VALIDATE_OR_GOTO ("snapview-server", iov, error_out); - - frame = myframe; - this = frame->this; - ctx = frame->this->ctx; - priv = this->private; - old_dirents = priv->dirents; - - if (!ctx) { - gf_log (frame->this->name, GF_LOG_ERROR, "NULL context"); - errno = EINVAL; - ret = -1; - goto out; - } - - if (-1 == req->rpc_status) { - gf_log (frame->this->name, GF_LOG_ERROR, - "RPC call is not successful"); - errno = EINVAL; - ret = -1; - goto out; - } - - ret = xdr_to_generic (*iov, &rsp, - (xdrproc_t)xdr_gf_getsnap_name_uuid_rsp); - if (ret < 0) { - gf_log (frame->this->name, GF_LOG_ERROR, - "Failed to decode xdr response, rsp.op_ret = %d", - rsp.op_ret); - goto out; - } - - if (rsp.op_ret == -1) { - errno = rsp.op_errno; - ret = -1; - goto out; - } - - if (!rsp.dict.dict_len) { - gf_log (frame->this->name, GF_LOG_ERROR, - "Response dict is not populated"); - ret = -1; - errno = EINVAL; - goto out; - } - - dict = dict_new (); - if (!dict) { - ret = -1; - errno = ENOMEM; - goto out; - } - - ret = dict_unserialize (rsp.dict.dict_val, rsp.dict.dict_len, &dict); - if (ret) { - gf_log (frame->this->name, GF_LOG_ERROR, - "Failed to unserialize dictionary"); - errno = EINVAL; - goto out; - } - - ret = dict_get_int32 (dict, "snap-count", (int32_t*)&snapcount); - if (ret) { - gf_log (this->name, GF_LOG_ERROR, - "Error retrieving snapcount"); - errno = EINVAL; - ret = -1; - goto out; - } - - pthread_mutex_lock (&priv->snaplist_lock); - - if ((priv->num_snaps == 0) && - (snapcount != 0)) { - /* first time we are fetching snap list */ - dirents = GF_CALLOC (snapcount, sizeof (snap_dirent_t), - gf_svs_mt_dirents_t); - if (!dirents) { - gf_log (frame->this->name, GF_LOG_ERROR, - "Unable to allocate memory"); - errno = ENOMEM; - ret = -1; - goto unlock; - } - } else { - /* fetch snaplist dynamically at run-time */ - dirents = GF_CALLOC (snapcount, sizeof (snap_dirent_t), - gf_svs_mt_dirents_t); - if (!dirents) { - gf_log (frame->this->name, GF_LOG_ERROR, - "Unable to allocate memory"); - errno = ENOMEM; - ret = -1; - goto unlock; - } - } - - for (i = 0; i < snapcount; i++) { - snprintf (key, sizeof (key), "snap-volname.%d", i+1); - ret = dict_get_str (dict, key, &value); - if (ret) { - gf_log (this->name, GF_LOG_ERROR, - "Error retrieving snap volname %d", i+1); - errno = EINVAL; - ret = -1; - goto unlock; - } - strncpy (dirents[i].snap_volname, value, - sizeof (dirents[i].snap_volname)); - - snprintf (key, sizeof (key), "snap-id.%d", i+1); - ret = dict_get_str (dict, key, &value); - if (ret) { - gf_log (this->name, GF_LOG_ERROR, - "Error retrieving snap uuid %d", i+1); - errno = EINVAL; - ret = -1; - goto unlock; - } - strncpy (dirents[i].uuid, value, sizeof (dirents[i].uuid)); - - snprintf (key, sizeof (key), "snapname.%d", i+1); - ret = dict_get_str (dict, key, &value); - if (ret) { - gf_log (this->name, GF_LOG_ERROR, - "Error retrieving snap name %d", i+1); - errno = EINVAL; - ret = -1; - goto unlock; - } - strncpy (dirents[i].name, value, sizeof (dirents[i].name)); - } - - /* - * Got the new snap list populated in dirents - * The new snap list is either a subset or a superset of - * the existing snaplist old_dirents which has priv->num_snaps - * number of entries. - * - * If subset, then clean up the fs for entries which are - * no longer relevant. - * - * For other overlapping entries set the fs for new dirents - * entries which have a fs assigned already in old_dirents - * - * We do this as we don't want to do new glfs_init()s repeatedly - * as the dirents entries for snapshot volumes get repatedly - * cleaned up and allocated. And if we don't then that will lead - * to memleaks - */ - for (i = 0; i < priv->num_snaps; i++) { - for (j = 0; j < snapcount; j++) { - if ((!strcmp (old_dirents[i].name, - dirents[j].name)) && - (!strcmp (old_dirents[i].uuid, - dirents[j].uuid))) { - dirents[j].fs = old_dirents[i].fs; - old_dirents[i].fs = NULL; - break; - } - } - } - - if (old_dirents) { - for (i=0; i < priv->num_snaps; i++) { - if (old_dirents[i].fs) - glfs_fini (old_dirents[i].fs); - } - } - - priv->dirents = dirents; - priv->num_snaps = snapcount; - - GF_FREE (old_dirents); - - ret = 0; - -unlock: - /* - * - * We will unlock the snaplist_lock here for two reasons: - * 1. We ideally would like to avoid nested locks - * 2. The snaplist_lock and the mutex protecting the condvar - * are independent of each other and don't need to be - * mixed together - */ - pthread_mutex_unlock (&priv->snaplist_lock); - -out: - pthread_mutex_lock (&mutex); - snap_worker_resume = _gf_true; - if (priv->is_snaplist_done) { - /* - * No need to signal if it is the first time - * refresh of the snaplist as no thread is - * waiting on this. It is only when the snaplist_worker - * is started that we have a thread waiting on this - */ - pthread_cond_signal (&condvar); - } - pthread_mutex_unlock (&mutex); - - if (dict) { - dict_unref (dict); - } - free (rsp.dict.dict_val); - free (rsp.op_errstr); - - if (ret && dirents) { - gf_log (this->name, GF_LOG_WARNING, - "Could not update dirents with refreshed snap list"); - GF_FREE (dirents); - } - - if (myframe) - SVS_STACK_DESTROY (myframe); - -error_out: - return ret; -} - -int -svs_get_snapshot_list (xlator_t *this) -{ - gf_getsnap_name_uuid_req req = {{0,}}; - int ret = 0; - dict_t *dict = NULL; - glusterfs_ctx_t *ctx = NULL; - call_frame_t *frame = NULL; - svs_private_t *priv = NULL; - gf_boolean_t frame_cleanup = _gf_false; - - ctx = this->ctx; - if (!ctx) { - gf_log (this->name, GF_LOG_ERROR, - "ctx is NULL"); - ret = -1; - goto out; - } - - frame = create_frame (this, ctx->pool); - if (!frame) { - gf_log (this->name, GF_LOG_ERROR, - "Error allocating frame"); - ret = -1; - goto out; - } - - priv = this->private; - - dict = dict_new (); - if (!dict) { - ret = -1; - gf_log (this->name, GF_LOG_ERROR, - "Error allocating dictionary"); - frame_cleanup = _gf_true; - goto out; - } - - ret = dict_set_str (dict, "volname", priv->volname); - if (ret) { - gf_log (this->name, GF_LOG_ERROR, - "Error setting volname in dict"); - frame_cleanup = _gf_true; - goto out; - } - - ret = dict_allocate_and_serialize (dict, &req.dict.dict_val, - &req.dict.dict_len); - if (ret) { - gf_log (this->name, GF_LOG_ERROR, - "Failed to serialize dictionary"); - ret = -1; - frame_cleanup = _gf_true; - goto out; - } - - ret = svs_mgmt_submit_request (&req, frame, ctx, - &svs_clnt_handshake_prog, - GF_HNDSK_GET_SNAPSHOT_INFO, - mgmt_get_snapinfo_cbk, - (xdrproc_t)xdr_gf_getsnap_name_uuid_req); - - if (ret) { - gf_log (this->name, GF_LOG_ERROR, - "Error sending snapshot names RPC request"); - } - -out: - if (dict) { - dict_unref (dict); - } - GF_FREE (req.dict.dict_val); - - if (frame_cleanup) { - /* - * Destroy the frame if we encountered an error - * Else we need to clean it up in - * mgmt_get_snapinfo_cbk - */ - SVS_STACK_DESTROY (frame); - } - - return ret; -} - -int -__svs_inode_ctx_set (xlator_t *this, inode_t *inode, svs_inode_t *svs_inode) -{ - uint64_t value = 0; - int ret = -1; - - GF_VALIDATE_OR_GOTO ("snapview-server", this, out); - GF_VALIDATE_OR_GOTO (this->name, inode, out); - GF_VALIDATE_OR_GOTO (this->name, svs_inode, out); - - value = (uint64_t)(long) svs_inode; - - ret = __inode_ctx_set (inode, this, &value); - -out: - return ret; -} - - -svs_inode_t * -__svs_inode_ctx_get (xlator_t *this, inode_t *inode) -{ - svs_inode_t *svs_inode = NULL; - uint64_t value = 0; - int ret = -1; - - GF_VALIDATE_OR_GOTO ("snapview-server", this, out); - GF_VALIDATE_OR_GOTO (this->name, inode, out); - - ret = __inode_ctx_get (inode, this, &value); - if (ret) - goto out; - - svs_inode = (svs_inode_t *) ((long) value); - -out: - return svs_inode; -} - - -svs_inode_t * -svs_inode_ctx_get (xlator_t *this, inode_t *inode) -{ - svs_inode_t *svs_inode = NULL; - - GF_VALIDATE_OR_GOTO ("snapview-server", this, out); - GF_VALIDATE_OR_GOTO (this->name, inode, out); - - LOCK (&inode->lock); - { - svs_inode = __svs_inode_ctx_get (this, inode); - } - UNLOCK (&inode->lock); - -out: - return svs_inode; -} - -int32_t -svs_inode_ctx_set (xlator_t *this, inode_t *inode, svs_inode_t *svs_inode) -{ - int32_t ret = -1; - - GF_VALIDATE_OR_GOTO ("snapview-server", this, out); - GF_VALIDATE_OR_GOTO (this->name, inode, out); - GF_VALIDATE_OR_GOTO (this->name, svs_inode, out); - - LOCK (&inode->lock); - { - ret = __svs_inode_ctx_set (this, inode, svs_inode); - } - UNLOCK (&inode->lock); - -out: - return ret; -} - -svs_inode_t * -svs_inode_new () -{ - svs_inode_t *svs_inode = NULL; - - svs_inode = GF_CALLOC (1, sizeof (*svs_inode), gf_svs_mt_svs_inode_t); - - return svs_inode; -} - -svs_inode_t * -svs_inode_ctx_get_or_new (xlator_t *this, inode_t *inode) -{ - svs_inode_t *svs_inode = NULL; - int ret = -1; - - GF_VALIDATE_OR_GOTO ("snapview-server", this, out); - GF_VALIDATE_OR_GOTO (this->name, inode, out); - - LOCK (&inode->lock); - { - svs_inode = __svs_inode_ctx_get (this, inode); - if (!svs_inode) { - svs_inode = svs_inode_new (); - if (svs_inode) { - ret = __svs_inode_ctx_set (this, inode, - svs_inode); - if (ret) { - GF_FREE (svs_inode); - svs_inode = NULL; - } - } - } - } - UNLOCK (&inode->lock); - -out: - return svs_inode; -} - -svs_fd_t * -svs_fd_new () -{ - svs_fd_t *svs_fd = NULL; - - svs_fd = GF_CALLOC (1, sizeof (*svs_fd), gf_svs_mt_svs_fd_t); - - return svs_fd; -} - -int -__svs_fd_ctx_set (xlator_t *this, fd_t *fd, svs_fd_t *svs_fd) -{ - uint64_t value = 0; - int ret = -1; - - GF_VALIDATE_OR_GOTO ("snapview-server", this, out); - GF_VALIDATE_OR_GOTO (this->name, fd, out); - GF_VALIDATE_OR_GOTO (this->name, svs_fd, out); - - value = (uint64_t)(long) svs_fd; - - ret = __fd_ctx_set (fd, this, value); - -out: - return ret; -} - - -svs_fd_t * -__svs_fd_ctx_get (xlator_t *this, fd_t *fd) -{ - svs_fd_t *svs_fd = NULL; - uint64_t value = 0; - int ret = -1; - - GF_VALIDATE_OR_GOTO ("snapview-server", this, out); - GF_VALIDATE_OR_GOTO (this->name, fd, out); - - ret = __fd_ctx_get (fd, this, &value); - if (ret) - return NULL; - - svs_fd = (svs_fd_t *) ((long) value); - -out: - return svs_fd; -} - - -svs_fd_t * -svs_fd_ctx_get (xlator_t *this, fd_t *fd) -{ - svs_fd_t *svs_fd = NULL; - - GF_VALIDATE_OR_GOTO ("snapview-server", this, out); - GF_VALIDATE_OR_GOTO (this->name, fd, out); - - LOCK (&fd->lock); - { - svs_fd = __svs_fd_ctx_get (this, fd); - } - UNLOCK (&fd->lock); - -out: - return svs_fd; -} - -int32_t -svs_fd_ctx_set (xlator_t *this, fd_t *fd, svs_fd_t *svs_fd) -{ - int32_t ret = -1; - - GF_VALIDATE_OR_GOTO ("snapview-server", this, out); - GF_VALIDATE_OR_GOTO (this->name, fd, out); - GF_VALIDATE_OR_GOTO (this->name, svs_fd, out); - - LOCK (&fd->lock); - { - ret = __svs_fd_ctx_set (this, fd, svs_fd); - } - UNLOCK (&fd->lock); - -out: - return ret; -} - -svs_fd_t * -__svs_fd_ctx_get_or_new (xlator_t *this, fd_t *fd) -{ - svs_fd_t *svs_fd = NULL; - int ret = -1; - glfs_t *fs = NULL; - glfs_object_t *object = NULL; - svs_inode_t *inode_ctx = NULL; - glfs_fd_t *glfd = NULL; - inode_t *inode = NULL; - - GF_VALIDATE_OR_GOTO ("snapview-server", this, out); - GF_VALIDATE_OR_GOTO (this->name, fd, out); - - inode = fd->inode; - svs_fd = __svs_fd_ctx_get (this, fd); - if (svs_fd) { - ret = 0; - goto out; - } - - svs_fd = svs_fd_new (); - if (!svs_fd) { - gf_log (this->name, GF_LOG_ERROR, "failed to allocate new fd " - "context for gfid %s", uuid_utoa (inode->gfid)); - goto out; - } - - if (fd_is_anonymous (fd)) { - inode_ctx = svs_inode_ctx_get (this, inode); - if (!inode_ctx) { - gf_log (this->name, GF_LOG_ERROR, "failed to get inode " - "context for %s", uuid_utoa (inode->gfid)); - goto out; - } - - fs = inode_ctx->fs; - object = inode_ctx->object; - - if (inode->ia_type == IA_IFDIR) { - glfd = glfs_h_opendir (fs, object); - if (!glfd) { - gf_log (this->name, GF_LOG_ERROR, "failed to " - "open the directory %s", - uuid_utoa (inode->gfid)); - goto out; - } - } - - if (inode->ia_type == IA_IFREG) { - glfd = glfs_h_open (fs, object, O_RDONLY|O_LARGEFILE); - if (!glfd) { - gf_log (this->name, GF_LOG_ERROR, "failed to " - "open the file %s", - uuid_utoa (inode->gfid)); - goto out; - } - } - - svs_fd->fd = glfd; - } - - ret = __svs_fd_ctx_set (this, fd, svs_fd); - if (ret) { - gf_log (this->name, GF_LOG_ERROR, "failed to set fd context " - "for gfid %s", uuid_utoa (inode->gfid)); - if (svs_fd->fd) { - if (inode->ia_type == IA_IFDIR) { - ret = glfs_closedir (svs_fd->fd); - if (ret) - gf_log (this->name, GF_LOG_ERROR, - "failed to close the fd for %s", - uuid_utoa (inode->gfid)); - } - if (inode->ia_type == IA_IFREG) { - ret = glfs_close (svs_fd->fd); - if (ret) - gf_log (this->name, GF_LOG_ERROR, - "failed to close the fd for %s", - uuid_utoa (inode->gfid)); - } - } - ret = -1; - } - -out: - if (ret) { - GF_FREE (svs_fd); - svs_fd = NULL; - } - - return svs_fd; -} - -svs_fd_t * -svs_fd_ctx_get_or_new (xlator_t *this, fd_t *fd) -{ - svs_fd_t *svs_fd = NULL; - - GF_VALIDATE_OR_GOTO ("snapview-server", this, out); - GF_VALIDATE_OR_GOTO (this->name, fd, out); - - LOCK (&fd->lock); - { - svs_fd = __svs_fd_ctx_get_or_new (this, fd); - } - UNLOCK (&fd->lock); - -out: - return svs_fd; -} - -void -svs_fill_ino_from_gfid (struct iatt *buf) -{ - uint64_t temp_ino = 0; - int j = 0; - int i = 0; - xlator_t *this = NULL; - - this = THIS; - - GF_VALIDATE_OR_GOTO ("snapview-server", this, out); - GF_VALIDATE_OR_GOTO (this->name, buf, out); - - /* consider least significant 8 bytes of value out of gfid */ - if (uuid_is_null (buf->ia_gfid)) { - buf->ia_ino = -1; - goto out; - } - for (i = 15; i > (15 - 8); i--) { - temp_ino += (uint64_t)(buf->ia_gfid[i]) << j; - j += 8; - } - buf->ia_ino = temp_ino; -out: - return; -} - -void -svs_iatt_fill (uuid_t gfid, struct iatt *buf) -{ - struct timeval tv = {0, }; - xlator_t *this = NULL; - - this = THIS; - - GF_VALIDATE_OR_GOTO ("snapview-server", this, out); - GF_VALIDATE_OR_GOTO (this->name, buf, out); - - buf->ia_type = IA_IFDIR; - buf->ia_uid = 0; - buf->ia_gid = 0; - buf->ia_size = 0; - buf->ia_nlink = 2; - buf->ia_blocks = 8; - buf->ia_size = 4096; - - uuid_copy (buf->ia_gfid, gfid); - svs_fill_ino_from_gfid (buf); - - buf->ia_prot = ia_prot_from_st_mode (0755); - - gettimeofday (&tv, 0); - - buf->ia_mtime = buf->ia_atime = buf->ia_ctime = tv.tv_sec; - buf->ia_mtime_nsec = buf->ia_atime_nsec = buf->ia_ctime_nsec = - (tv.tv_usec * 1000); - -out: - return; -} - -snap_dirent_t * -svs_get_snap_dirent (xlator_t *this, const char *name) -{ - svs_private_t *private = NULL; - int i = 0; - snap_dirent_t *dirents = NULL; - snap_dirent_t *tmp_dirent = NULL; - snap_dirent_t *dirent = NULL; - - GF_VALIDATE_OR_GOTO ("snapview-server", this, out); - GF_VALIDATE_OR_GOTO (this->name, this->private, out); - GF_VALIDATE_OR_GOTO (this->name, name, out); - - private = this->private; - - pthread_mutex_lock (&private->snaplist_lock); - - dirents = private->dirents; - if (!dirents) { - pthread_mutex_unlock (&private->snaplist_lock); - goto out; - } - - tmp_dirent = dirents; - for (i = 0; i < private->num_snaps; i++) { - if (!strcmp (tmp_dirent->name, name)) { - dirent = tmp_dirent; - break; - } - tmp_dirent++; - } - - pthread_mutex_unlock (&private->snaplist_lock); - -out: - return dirent; -} - -glfs_t * -svs_initialise_snapshot_volume (xlator_t *this, const char *name) -{ - svs_private_t *priv = NULL; - int32_t ret = -1; - snap_dirent_t *dirent = NULL; - char volname[PATH_MAX] = {0, }; - glfs_t *fs = NULL; - int loglevel = GF_LOG_INFO; - char logfile[PATH_MAX] = {0, }; - - GF_VALIDATE_OR_GOTO ("snapview-server", this, out); - GF_VALIDATE_OR_GOTO (this->name, this->private, out); - GF_VALIDATE_OR_GOTO (this->name, name, out); - - priv = this->private; - - dirent = svs_get_snap_dirent (this, name); - if (!dirent) { - gf_log (this->name, GF_LOG_ERROR, "snap entry for name %s " - "not found", name); - goto out; - } - - if (dirent->fs) { - ret = 0; - fs = dirent->fs; - goto out; - } - - snprintf (volname, sizeof (volname), "/snaps/%s/%s", - dirent->name, dirent->snap_volname); - - fs = glfs_new (volname); - if (!fs) { - gf_log (this->name, GF_LOG_ERROR, - "glfs instance for snap volume %s " - "failed", dirent->name); - goto out; - } - - ret = glfs_set_volfile_server (fs, "tcp", "localhost", - 24007); - if (ret) { - gf_log (this->name, GF_LOG_ERROR, "setting the " - "volfile srever for snap volume %s " - "failed", dirent->name); - goto out; - } - - ret = glfs_init (fs); - if (ret) { - gf_log (this->name, GF_LOG_ERROR, "initing the " - "fs for %s failed", dirent->name); - goto out; - } - - snprintf (logfile, sizeof (logfile), - DEFAULT_SVD_LOG_FILE_DIRECTORY "/%s-%s.log", - name, dirent->uuid); - - ret = glfs_set_logging(fs, logfile, loglevel); - if (ret) { - gf_log (this->name, GF_LOG_ERROR, "failed to set the " - "log file path"); - goto out; - } - - ret = 0; - -out: - if (ret && fs) { - glfs_fini (fs); - fs = NULL; - } - - if (fs) - dirent->fs = fs; - - return fs; -} - -snap_dirent_t * -svs_get_latest_snap_entry (xlator_t *this) -{ - svs_private_t *priv = NULL; - snap_dirent_t *dirents = NULL; - snap_dirent_t *dirent = NULL; - - GF_VALIDATE_OR_GOTO ("svs", this, out); - - priv = this->private; - - pthread_mutex_lock (&priv->snaplist_lock); - dirents = priv->dirents; - if (!dirents) { - pthread_mutex_unlock (&priv->snaplist_lock); - goto out; - } - if (priv->num_snaps) - dirent = &dirents[priv->num_snaps - 1]; - - pthread_mutex_unlock (&priv->snaplist_lock); -out: - return dirent; -} - -glfs_t * -svs_get_latest_snapshot (xlator_t *this) -{ - glfs_t *fs = NULL; - snap_dirent_t *dirent = NULL; - svs_private_t *priv = NULL; - - GF_VALIDATE_OR_GOTO ("svs", this, out); - priv = this->private; - - dirent = svs_get_latest_snap_entry (this); - - if (dirent) { - pthread_mutex_lock (&priv->snaplist_lock); - fs = dirent->fs; - pthread_mutex_unlock (&priv->snaplist_lock); - } - -out: - return fs; -} int32_t svs_lookup_entry_point (xlator_t *this, loc_t *loc, inode_t *parent, @@ -2096,33 +1076,43 @@ svs_fill_readdir (xlator_t *this, gf_dirent_t *entries, size_t size, off_t off) GF_ASSERT (priv); /* create the dir entries */ - pthread_mutex_lock (&priv->snaplist_lock); - dirents = priv->dirents; + LOCK (&priv->snaplist_lock); + { + dirents = priv->dirents; - for (i = off; i < priv->num_snaps; ) { - this_size = sizeof (gf_dirent_t) + - strlen (dirents[i].name) + 1; - if (this_size + filled_size > size ) - goto unlock; + for (i = off; i < priv->num_snaps; ) { + this_size = sizeof (gf_dirent_t) + + strlen (dirents[i].name) + 1; + if (this_size + filled_size > size ) + goto unlock; - entry = gf_dirent_for_name (dirents[i].name); - if (!entry) { - gf_log (this->name, GF_LOG_ERROR, "failed to allocate " - "dentry for %s", dirents[i].name); - goto unlock; - } + entry = gf_dirent_for_name (dirents[i].name); + if (!entry) { + gf_log (this->name, GF_LOG_ERROR, + "failed to allocate dentry for %s", + dirents[i].name); + goto unlock; + } - entry->d_off = i + 1; - entry->d_ino = i + 2*42; - entry->d_type = DT_DIR; - list_add_tail (&entry->list, &entries->list); - ++i; - count++; - filled_size += this_size; + entry->d_off = i + 1; + /* + * readdir on the entry-point directory to the snapshot + * world, will return elements in the list of the + * snapshots as the directory entries. Since the entries + * returned are virtual entries which does not exist + * physically on the disk, pseudo inode numbers are + * generated. + */ + entry->d_ino = i + 2*42; + entry->d_type = DT_DIR; + list_add_tail (&entry->list, &entries->list); + ++i; + count++; + filled_size += this_size; + } } - unlock: - pthread_mutex_unlock (&priv->snaplist_lock); + UNLOCK (&priv->snaplist_lock); out: return count; @@ -2843,6 +1833,10 @@ svs_access (call_frame_t *frame, xlator_t *this, loc_t *loc, int mask, is_fuse_call = __is_fuse_call (frame); + /* + * For entry-point directory, set read and execute bits. But not write + * permissions. + */ if (inode_ctx->type == SNAP_VIEW_ENTRY_POINT_INODE) { if (is_fuse_call) { op_ret = 0; @@ -2859,6 +1853,10 @@ svs_access (call_frame_t *frame, xlator_t *this, loc_t *loc, int mask, fs = inode_ctx->fs; object = inode_ctx->object; + /* The actual posix_acl xlator does acl checks differently for + fuse and nfs. So set frame->root->pid as fspid of the syncop + if the call came from nfs + */ if (!is_fuse_call) syncopctx_setfspid (&frame->root->pid); @@ -2871,12 +1869,6 @@ svs_access (call_frame_t *frame, xlator_t *this, loc_t *loc, int mask, goto out; } - /* The actual posix_acl xlator does acl checks differently for - fuse and nfs. In this case how to send the information of - whether the call came from fuse or nfs to the snapshot volume - via gfapi? - */ - op_ret = 0; op_errno = ret; @@ -2926,35 +1918,31 @@ init (xlator_t *this) this->private = priv; GF_OPTION_INIT ("volname", priv->volname, str, out); - pthread_mutex_init (&(priv->snaplist_lock), NULL); - - pthread_mutex_lock (&priv->snaplist_lock); - priv->is_snaplist_done = 0; - priv->num_snaps = 0; - snap_worker_resume = _gf_false; - pthread_mutex_unlock (&priv->snaplist_lock); + LOCK_INIT (&priv->snaplist_lock); - /* get the list of snaps first to return to client xlator */ - ret = svs_get_snapshot_list (this); - if (ret) { - gf_log (this->name, GF_LOG_ERROR, - "Error initializing snaplist infrastructure"); - ret = -1; - goto out; + LOCK (&priv->snaplist_lock); + { + priv->num_snaps = 0; } + UNLOCK (&priv->snaplist_lock); - if ((ret = pthread_attr_init (&priv->thr_attr)) != 0) { - gf_log (this->name, GF_LOG_ERROR, "pthread attr init failed"); + /* What to do here upon failure? should init be failed or succeed? */ + /* If succeeded, then dynamic management of snapshots will not */ + /* happen.*/ + ret = svs_mgmt_init (this); + if (ret) { + gf_log (this->name, GF_LOG_WARNING, "failed to initiate the " + "mgmt rpc callback for svs. Dymamic management of the" + "snapshots will not happen"); goto out; } - ret = gf_thread_create (&snap_thread, - &priv->thr_attr, - snaplist_worker, - this); + /* get the list of snaps first to return to client xlator */ + ret = svs_get_snapshot_list (this); if (ret) { gf_log (this->name, GF_LOG_ERROR, - "Failed to create snaplist worker thread"); + "Error initializing snaplist infrastructure"); + ret = -1; goto out; } @@ -2962,6 +1950,7 @@ init (xlator_t *this) out: if (ret && priv) { + LOCK_DESTROY (&priv->snaplist_lock); GF_FREE (priv->dirents); GF_FREE (priv); } @@ -2985,33 +1974,23 @@ fini (xlator_t *this) "Invalid ctx found"); if (priv) { - gf_timer_call_cancel (ctx, priv->snap_timer); - priv->snap_timer = NULL; - ret = pthread_mutex_destroy (&priv->snaplist_lock); + ret = LOCK_DESTROY (&priv->snaplist_lock); if (ret != 0) { gf_log (this->name, GF_LOG_WARNING, "Could not destroy mutex snaplist_lock"); } - ret = pthread_attr_destroy (&priv->thr_attr); - if (ret != 0) { - gf_log (this->name, GF_LOG_WARNING, - "Could not destroy pthread attr"); - } + if (priv->dirents) { GF_FREE (priv->dirents); } - GF_FREE (priv); - } - ret = pthread_mutex_destroy (&mutex); - if (ret != 0) { - gf_log (this->name, GF_LOG_WARNING, - "Could not destroy mutex"); - } - pthread_cond_destroy (&condvar); - if (ret != 0) { - gf_log (this->name, GF_LOG_WARNING, - "Could not destroy condition variable"); + if (priv->rpc) { + /* cleanup the saved-frames before last unref */ + rpc_clnt_connection_cleanup (&priv->rpc->conn); + rpc_clnt_unref (priv->rpc); + } + + GF_FREE (priv); } return; |