/* Copyright (c) 2008-2012 Red Hat, Inc. 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 "client.h" #include #include "client-messages.h" #include "client-common.h" #include #include int client_fd_lk_list_empty(fd_lk_ctx_t *lk_ctx, gf_boolean_t try_lock) { int ret = 1; if (!lk_ctx) { ret = -1; goto out; } if (try_lock) { ret = TRY_LOCK(&lk_ctx->lock); if (ret != 0) { ret = -1; goto out; } } else { LOCK(&lk_ctx->lock); } ret = list_empty(&lk_ctx->lk_list); UNLOCK(&lk_ctx->lock); out: return ret; } clnt_fd_ctx_t * this_fd_del_ctx(fd_t *file, xlator_t *this) { int dict_ret = -1; uint64_t ctxaddr = 0; GF_VALIDATE_OR_GOTO("client", this, out); GF_VALIDATE_OR_GOTO(this->name, file, out); dict_ret = fd_ctx_del(file, this, &ctxaddr); if (dict_ret < 0) { ctxaddr = 0; } out: return (clnt_fd_ctx_t *)(unsigned long)ctxaddr; } clnt_fd_ctx_t * this_fd_get_ctx(fd_t *file, xlator_t *this) { int dict_ret = -1; uint64_t ctxaddr = 0; GF_VALIDATE_OR_GOTO("client", this, out); GF_VALIDATE_OR_GOTO(this->name, file, out); dict_ret = fd_ctx_get(file, this, &ctxaddr); if (dict_ret < 0) { ctxaddr = 0; } out: return (clnt_fd_ctx_t *)(unsigned long)ctxaddr; } void this_fd_set_ctx(fd_t *file, xlator_t *this, loc_t *loc, clnt_fd_ctx_t *ctx) { uint64_t oldaddr = 0; int32_t ret = -1; GF_VALIDATE_OR_GOTO("client", this, out); GF_VALIDATE_OR_GOTO(this->name, file, out); ret = fd_ctx_get(file, this, &oldaddr); if (ret >= 0) { if (loc) gf_msg(this->name, GF_LOG_INFO, 0, PC_MSG_FD_DUPLICATE_TRY, "%s (%s): trying duplicate remote fd set. ", loc->path, uuid_utoa(loc->inode->gfid)); else gf_msg(this->name, GF_LOG_INFO, 0, PC_MSG_FD_DUPLICATE_TRY, "%p: trying duplicate remote fd set. ", file); } ret = fd_ctx_set(file, this, (uint64_t)(unsigned long)ctx); if (ret < 0) { if (loc) gf_msg(this->name, GF_LOG_WARNING, 0, PC_MSG_FD_SET_FAIL, "%s (%s): failed to set remote fd", loc->path, uuid_utoa(loc->inode->gfid)); else gf_msg(this->name, GF_LOG_WARNING, 0, PC_MSG_FD_SET_FAIL, "%p: failed to set remote fd", file); } out: return; } int client_local_wipe(clnt_local_t *local) { if (local) { loc_wipe(&local->loc); loc_wipe(&local->loc2); if (local->fd) { fd_unref(local->fd); } if (local->iobref) { iobref_unref(local->iobref); } GF_FREE(local->name); local->compound_args = NULL; mem_put(local); } return 0; } int unserialize_rsp_dirent(xlator_t *this, struct gfs3_readdir_rsp *rsp, gf_dirent_t *entries) { struct gfs3_dirlist *trav = NULL; gf_dirent_t *entry = NULL; int entry_len = 0; int ret = -1; clnt_conf_t *conf = NULL; conf = this->private; trav = rsp->reply; while (trav) { entry_len = gf_dirent_size(trav->name); entry = GF_CALLOC(1, entry_len, gf_common_mt_gf_dirent_t); if (!entry) goto out; entry->d_ino = trav->d_ino; gf_itransform(this, trav->d_off, &entry->d_off, conf->client_id); entry->d_len = trav->d_len; entry->d_type = trav->d_type; strcpy(entry->d_name, trav->name); list_add_tail(&entry->list, &entries->list); trav = trav->nextentry; } ret = 0; out: return ret; } int unserialize_rsp_direntp(xlator_t *this, fd_t *fd, struct gfs3_readdirp_rsp *rsp, gf_dirent_t *entries) { struct gfs3_dirplist *trav = NULL; char *buf = NULL; gf_dirent_t *entry = NULL; inode_table_t *itable = NULL; int entry_len = 0; int ret = -1; clnt_conf_t *conf = NULL; trav = rsp->reply; if (fd) itable = fd->inode->table; conf = this->private; if (!conf) goto out; while (trav) { entry_len = gf_dirent_size(trav->name); entry = GF_CALLOC(1, entry_len, gf_common_mt_gf_dirent_t); if (!entry) goto out; entry->d_ino = trav->d_ino; gf_itransform(this, trav->d_off, &entry->d_off, conf->client_id); entry->d_len = trav->d_len; entry->d_type = trav->d_type; gf_stat_to_iatt(&trav->stat, &entry->d_stat); strcpy(entry->d_name, trav->name); if (trav->dict.dict_val) { /* Dictionary is sent along with response */ buf = memdup(trav->dict.dict_val, trav->dict.dict_len); if (!buf) goto out; entry->dict = dict_new(); ret = dict_unserialize(buf, trav->dict.dict_len, &entry->dict); if (ret < 0) { gf_msg(THIS->name, GF_LOG_WARNING, EINVAL, PC_MSG_DICT_UNSERIALIZE_FAIL, "failed to unserialize xattr dict"); goto out; } GF_FREE(buf); buf = NULL; } entry->inode = inode_find(itable, entry->d_stat.ia_gfid); if (!entry->inode) entry->inode = inode_new(itable); list_add_tail(&entry->list, &entries->list); trav = trav->nextentry; } ret = 0; out: if (buf) GF_FREE(buf); return ret; } int clnt_readdirp_rsp_cleanup(gfs3_readdirp_rsp *rsp) { gfs3_dirplist *prev = NULL; gfs3_dirplist *trav = NULL; trav = rsp->reply; prev = trav; while (trav) { trav = trav->nextentry; /* on client, the rpc lib allocates this */ free(prev->dict.dict_val); free(prev->name); free(prev); prev = trav; } return 0; } int unserialize_rsp_dirent_v2(xlator_t *this, struct gfx_readdir_rsp *rsp, gf_dirent_t *entries) { struct gfx_dirlist *trav = NULL; gf_dirent_t *entry = NULL; int entry_len = 0; int ret = -1; clnt_conf_t *conf = NULL; conf = this->private; trav = rsp->reply; while (trav) { entry_len = gf_dirent_size(trav->name); entry = GF_CALLOC(1, entry_len, gf_common_mt_gf_dirent_t); if (!entry) goto out; entry->d_ino = trav->d_ino; gf_itransform(this, trav->d_off, &entry->d_off, conf->client_id); entry->d_len = trav->d_len; entry->d_type = trav->d_type; strcpy(entry->d_name, trav->name); list_add_tail(&entry->list, &entries->list); trav = trav->nextentry; } ret = 0; out: return ret; } int unserialize_rsp_direntp_v2(xlator_t *this, fd_t *fd, struct gfx_readdirp_rsp *rsp, gf_dirent_t *entries) { struct gfx_dirplist *trav = NULL; gf_dirent_t *entry = NULL; inode_table_t *itable = NULL; int entry_len = 0; int ret = -1; clnt_conf_t *conf = NULL; trav = rsp->reply; if (fd) itable = fd->inode->table; conf = this->private; if (!conf) goto out; while (trav) { entry_len = gf_dirent_size(trav->name); entry = GF_CALLOC(1, entry_len, gf_common_mt_gf_dirent_t); if (!entry) goto out; entry->d_ino = trav->d_ino; gf_itransform(this, trav->d_off, &entry->d_off, conf->client_id); entry->d_len = trav->d_len; entry->d_type = trav->d_type; gfx_stat_to_iattx(&trav->stat, &entry->d_stat); strcpy(entry->d_name, trav->name); xdr_to_dict(&trav->dict, &entry->dict); entry->inode = inode_find(itable, entry->d_stat.ia_gfid); if (!entry->inode) entry->inode = inode_new(itable); list_add_tail(&entry->list, &entries->list); trav = trav->nextentry; } ret = 0; out: return ret; } int clnt_readdirp_rsp_cleanup_v2(gfx_readdirp_rsp *rsp) { gfx_dirplist *prev = NULL; gfx_dirplist *trav = NULL; trav = rsp->reply; prev = trav; while (trav) { trav = trav->nextentry; free(prev->name); free(prev); prev = trav; } return 0; } int clnt_readdir_rsp_cleanup(gfs3_readdir_rsp *rsp) { gfs3_dirlist *prev = NULL; gfs3_dirlist *trav = NULL; trav = rsp->reply; prev = trav; while (trav) { trav = trav->nextentry; /* on client, the rpc lib allocates this */ free(prev->name); free(prev); prev = trav; } return 0; } int clnt_readdir_rsp_cleanup_v2(gfx_readdir_rsp *rsp) { gfx_dirlist *prev = NULL; gfx_dirlist *trav = NULL; trav = rsp->reply; prev = trav; while (trav) { trav = trav->nextentry; /* on client, the rpc lib allocates this */ free(prev->name); free(prev); prev = trav; } return 0; } int client_get_remote_fd(xlator_t *this, fd_t *fd, int flags, int64_t *remote_fd) { clnt_fd_ctx_t *fdctx = NULL; clnt_conf_t *conf = NULL; GF_VALIDATE_OR_GOTO(this->name, fd, out); GF_VALIDATE_OR_GOTO(this->name, remote_fd, out); conf = this->private; pthread_spin_lock(&conf->fd_lock); { fdctx = this_fd_get_ctx(fd, this); if (!fdctx) { *remote_fd = GF_ANON_FD_NO; } else { if (__is_fd_reopen_in_progress(fdctx)) *remote_fd = -1; else *remote_fd = fdctx->remote_fd; } } pthread_spin_unlock(&conf->fd_lock); if ((flags & FALLBACK_TO_ANON_FD) && (*remote_fd == -1)) *remote_fd = GF_ANON_FD_NO; return 0; out: return -1; } gf_boolean_t client_is_reopen_needed(fd_t *fd, xlator_t *this, int64_t remote_fd) { clnt_conf_t *conf = NULL; clnt_fd_ctx_t *fdctx = NULL; gf_boolean_t res = _gf_false; conf = this->private; pthread_spin_lock(&conf->fd_lock); { fdctx = this_fd_get_ctx(fd, this); if (fdctx && (fdctx->remote_fd == -1) && (remote_fd == GF_ANON_FD_NO)) res = _gf_true; } pthread_spin_unlock(&conf->fd_lock); return res; } int client_fd_fop_prepare_local(call_frame_t *frame, fd_t *fd, int64_t remote_fd) { xlator_t *this = NULL; clnt_local_t *local = NULL; int ret = 0; if (!frame || !fd) { ret = -EINVAL; goto out; } this = frame->this; frame->local = mem_get0(this->local_pool); if (frame->local == NULL) { ret = -ENOMEM; goto out; } local = frame->local; local->fd = fd_ref(fd); local->attempt_reopen = client_is_reopen_needed(fd, this, remote_fd); return 0; out: return ret; } int client_process_response(call_frame_t *frame, xlator_t *this, struct rpc_req *req, gfs3_compound_rsp *rsp, compound_args_cbk_t *args_cbk, int index) { int ret = 0; dict_t *xdata = NULL; dict_t *xattr = NULL; struct iovec vector[MAX_IOVEC] = { {0}, }; gf_dirent_t entries; default_args_cbk_t *this_args_cbk = &args_cbk->rsp_list[index]; clnt_local_t *local = frame->local; compound_rsp *this_rsp = NULL; compound_args_t *args = local->compound_args; this_rsp = &rsp->compound_rsp_array.compound_rsp_array_val[index]; args_cbk->enum_list[index] = this_rsp->fop_enum; INIT_LIST_HEAD(&entries.list); switch (args_cbk->enum_list[index]) { case GF_FOP_STAT: { gfs3_stat_rsp *tmp_rsp = NULL; tmp_rsp = &this_rsp->compound_rsp_u.compound_stat_rsp; client_post_stat(this, tmp_rsp, &this_args_cbk->stat, &xdata); CLIENT_POST_FOP_TYPE(stat, this_rsp, this_args_cbk, &this_args_cbk->stat, xdata); break; } case GF_FOP_READLINK: { gfs3_readlink_rsp *tmp_rsp = NULL; tmp_rsp = &this_rsp->compound_rsp_u.compound_readlink_rsp; client_post_readlink(this, tmp_rsp, &this_args_cbk->stat, &xdata); CLIENT_POST_FOP_TYPE(readlink, this_rsp, this_args_cbk, tmp_rsp->path, &this_args_cbk->stat, xdata); break; } case GF_FOP_MKNOD: { gfs3_mknod_rsp *tmp_rsp = NULL; tmp_rsp = &this_rsp->compound_rsp_u.compound_mknod_rsp; client_post_mknod(this, tmp_rsp, &this_args_cbk->stat, &this_args_cbk->preparent, &this_args_cbk->postparent, &xdata); CLIENT_POST_FOP_TYPE(mknod, this_rsp, this_args_cbk, local->loc.inode, &this_args_cbk->stat, &this_args_cbk->preparent, &this_args_cbk->postparent, xdata); break; } case GF_FOP_MKDIR: { gfs3_mkdir_rsp *tmp_rsp = NULL; tmp_rsp = &this_rsp->compound_rsp_u.compound_mkdir_rsp; client_post_mkdir(this, tmp_rsp, &this_args_cbk->stat, &this_args_cbk->preparent, &this_args_cbk->postparent, &xdata); CLIENT_POST_FOP_TYPE(mkdir, this_rsp, this_args_cbk, local->loc.inode, &this_args_cbk->stat, &this_args_cbk->preparent, &this_args_cbk->postparent, xdata); break; } case GF_FOP_UNLINK: { gfs3_unlink_rsp *tmp_rsp = NULL; tmp_rsp = &this_rsp->compound_rsp_u.compound_unlink_rsp; client_post_unlink(this, tmp_rsp, &this_args_cbk->preparent, &this_args_cbk->postparent, &xdata); CLIENT_POST_FOP_TYPE(unlink, this_rsp, this_args_cbk, &this_args_cbk->preparent, &this_args_cbk->postparent, xdata); break; } case GF_FOP_RMDIR: { gfs3_rmdir_rsp *tmp_rsp = NULL; tmp_rsp = &this_rsp->compound_rsp_u.compound_rmdir_rsp; client_post_rmdir(this, tmp_rsp, &this_args_cbk->preparent, &this_args_cbk->postparent, &xdata); CLIENT_POST_FOP_TYPE(rmdir, this_rsp, this_args_cbk, &this_args_cbk->preparent, &this_args_cbk->postparent, xdata); break; } case GF_FOP_SYMLINK: { gfs3_symlink_rsp *tmp_rsp = NULL; tmp_rsp = &this_rsp->compound_rsp_u.compound_symlink_rsp; client_post_symlink(this, tmp_rsp, &this_args_cbk->stat, &this_args_cbk->preparent, &this_args_cbk->postparent, &xdata); CLIENT_POST_FOP_TYPE( symlink, this_rsp, this_args_cbk, NULL, &this_args_cbk->stat, &this_args_cbk->preparent, &this_args_cbk->postparent, xdata); break; } case GF_FOP_RENAME: { gfs3_rename_rsp *tmp_rsp = NULL; tmp_rsp = &this_rsp->compound_rsp_u.compound_rename_rsp; client_post_rename( this, tmp_rsp, &this_args_cbk->stat, &this_args_cbk->preparent, &this_args_cbk->postparent, &this_args_cbk->preparent2, &this_args_cbk->postparent2, &xdata); CLIENT_POST_FOP_TYPE( rename, this_rsp, this_args_cbk, &this_args_cbk->stat, &this_args_cbk->preparent, &this_args_cbk->postparent, &this_args_cbk->preparent2, &this_args_cbk->postparent2, xdata); break; } case GF_FOP_LINK: { gfs3_link_rsp *tmp_rsp = NULL; tmp_rsp = &this_rsp->compound_rsp_u.compound_link_rsp; client_post_link(this, tmp_rsp, &this_args_cbk->stat, &this_args_cbk->preparent, &this_args_cbk->postparent, &xdata); CLIENT_POST_FOP_TYPE( link, this_rsp, this_args_cbk, NULL, &this_args_cbk->stat, &this_args_cbk->preparent, &this_args_cbk->postparent, xdata); break; } case GF_FOP_TRUNCATE: { gfs3_truncate_rsp *tmp_rsp = NULL; tmp_rsp = &this_rsp->compound_rsp_u.compound_truncate_rsp; client_post_truncate(this, tmp_rsp, &this_args_cbk->prestat, &this_args_cbk->poststat, &xdata); CLIENT_POST_FOP_TYPE(truncate, this_rsp, this_args_cbk, &this_args_cbk->prestat, &this_args_cbk->poststat, xdata); break; } case GF_FOP_OPEN: { gfs3_open_rsp *tmp_rsp = NULL; tmp_rsp = &this_rsp->compound_rsp_u.compound_open_rsp; client_post_open(this, tmp_rsp, &xdata); CLIENT_POST_FOP_TYPE(open, this_rsp, this_args_cbk, local->fd, xdata); if (-1 != this_args_cbk->op_ret) ret = client_add_fd_to_saved_fds(this, local->fd, &local->loc, args->req_list[index].flags, tmp_rsp->fd, 0); break; } case GF_FOP_READ: { gfs3_read_rsp *tmp_rsp = NULL; tmp_rsp = &this_rsp->compound_rsp_u.compound_read_rsp; client_post_readv(this, tmp_rsp, &this_args_cbk->iobref, req->rsp_iobref, &this_args_cbk->stat, vector, &req->rsp[1], &this_args_cbk->count, &xdata); /* Each read should be given read response that only * corresponds to its request. * Modify the iovecs accordingly. * After each read, store the length of data already read * so that the next ones can continue from there. */ if (local->read_length) { vector[0].iov_base += local->read_length; local->read_length += tmp_rsp->op_ret; } else { local->read_length = tmp_rsp->op_ret; } args_readv_cbk_store(this_args_cbk, tmp_rsp->op_ret, gf_error_to_errno(tmp_rsp->op_errno), vector, this_args_cbk->count, &this_args_cbk->stat, this_args_cbk->iobref, xdata); if (tmp_rsp->op_ret >= 0) if (local->attempt_reopen) client_attempt_reopen(local->fd, this); break; } case GF_FOP_WRITE: { gfs3_write_rsp *tmp_rsp = NULL; tmp_rsp = &this_rsp->compound_rsp_u.compound_write_rsp; client_post_writev(this, tmp_rsp, &this_args_cbk->prestat, &this_args_cbk->poststat, &xdata); args_writev_cbk_store(this_args_cbk, tmp_rsp->op_ret, gf_error_to_errno(tmp_rsp->op_errno), &this_args_cbk->prestat, &this_args_cbk->poststat, xdata); if (tmp_rsp->op_ret == 0) if (local->attempt_reopen) client_attempt_reopen(local->fd, this); break; } case GF_FOP_STATFS: { gfs3_statfs_rsp *tmp_rsp = NULL; tmp_rsp = &this_rsp->compound_rsp_u.compound_statfs_rsp; client_post_statfs(this, tmp_rsp, &this_args_cbk->statvfs, &xdata); CLIENT_POST_FOP_TYPE(statfs, this_rsp, this_args_cbk, &this_args_cbk->statvfs, xdata); break; } case GF_FOP_FLUSH: { gf_common_rsp *tmp_rsp = NULL; tmp_rsp = &this_rsp->compound_rsp_u.compound_flush_rsp; client_post_flush(this, tmp_rsp, &xdata); CLIENT_POST_FOP(flush, this_rsp, this_args_cbk, xdata); if (this_args_cbk->op_ret >= 0 && !fd_is_anonymous(local->fd)) { /* Delete all saved locks of the owner issuing flush */ ret = delete_granted_locks_owner(local->fd, &local->owner); gf_msg_trace(this->name, 0, "deleting locks of owner (%s) returned %d", lkowner_utoa(&local->owner), ret); } break; } case GF_FOP_FSYNC: { gfs3_fsync_rsp *tmp_rsp = NULL; tmp_rsp = &this_rsp->compound_rsp_u.compound_fsync_rsp; client_post_fsync(this, tmp_rsp, &this_args_cbk->prestat, &this_args_cbk->poststat, &xdata); CLIENT_POST_FOP_TYPE(fsync, this_rsp, this_args_cbk, &this_args_cbk->prestat, &this_args_cbk->poststat, xdata); break; } case GF_FOP_SETXATTR: { gf_common_rsp *tmp_rsp = NULL; tmp_rsp = &this_rsp->compound_rsp_u.compound_setxattr_rsp; client_post_setxattr(this, tmp_rsp, &xdata); CLIENT_POST_FOP(setxattr, this_rsp, this_args_cbk, xdata); break; } case GF_FOP_GETXATTR: { gfs3_getxattr_rsp *tmp_rsp = NULL; tmp_rsp = &this_rsp->compound_rsp_u.compound_getxattr_rsp; client_post_getxattr(this, tmp_rsp, &xattr, &xdata); CLIENT_POST_FOP_TYPE(getxattr, this_rsp, this_args_cbk, xattr, xdata); break; } case GF_FOP_REMOVEXATTR: { gf_common_rsp *tmp_rsp = NULL; tmp_rsp = &this_rsp->compound_rsp_u.compound_removexattr_rsp; client_post_removexattr(this, tmp_rsp, &xdata); CLIENT_POST_FOP(removexattr, this_rsp, this_args_cbk, xdata); break; } case GF_FOP_OPENDIR: { gfs3_opendir_rsp *tmp_rsp = NULL; tmp_rsp = &this_rsp->compound_rsp_u.compound_opendir_rsp; client_post_opendir(this, tmp_rsp, &xdata); CLIENT_POST_FOP_TYPE(opendir, this_rsp, this_args_cbk, local->fd, xdata); if (-1 != this_args_cbk->op_ret) ret = client_add_fd_to_saved_fds(this, local->fd, &local->loc, args->req_list[index].flags, tmp_rsp->fd, 0); break; } case GF_FOP_FSYNCDIR: { gf_common_rsp *tmp_rsp = NULL; tmp_rsp = &this_rsp->compound_rsp_u.compound_fsyncdir_rsp; client_post_fsyncdir(this, tmp_rsp, &xdata); CLIENT_POST_FOP(fsyncdir, this_rsp, this_args_cbk, xdata); break; } case GF_FOP_ACCESS: { gf_common_rsp *tmp_rsp = NULL; tmp_rsp = &this_rsp->compound_rsp_u.compound_access_rsp; client_post_access(this, tmp_rsp, &xdata); CLIENT_POST_FOP(access, this_rsp, this_args_cbk, xdata); break; } case GF_FOP_CREATE: { gfs3_create_rsp *tmp_rsp = NULL; tmp_rsp = &this_rsp->compound_rsp_u.compound_create_rsp; client_post_create(this, tmp_rsp, &this_args_cbk->stat, &this_args_cbk->preparent, &this_args_cbk->postparent, local, &xdata); CLIENT_POST_FOP_TYPE(create, this_rsp, this_args_cbk, local->fd, local->loc.inode, &this_args_cbk->stat, &this_args_cbk->preparent, &this_args_cbk->postparent, xdata); if (-1 != this_args_cbk->op_ret) ret = client_add_fd_to_saved_fds(this, local->fd, &local->loc, args->req_list[index].flags, tmp_rsp->fd, 0); break; } case GF_FOP_FTRUNCATE: { gfs3_ftruncate_rsp *tmp_rsp = NULL; tmp_rsp = &this_rsp->compound_rsp_u.compound_ftruncate_rsp; client_post_ftruncate(this, tmp_rsp, &this_args_cbk->prestat, &this_args_cbk->poststat, &xdata); CLIENT_POST_FOP_TYPE(ftruncate, this_rsp, this_args_cbk, &this_args_cbk->prestat, &this_args_cbk->poststat, xdata); break; } case GF_FOP_FSTAT: { gfs3_fstat_rsp *tmp_rsp = NULL; tmp_rsp = &this_rsp->compound_rsp_u.compound_fstat_rsp; client_post_fstat(this, tmp_rsp, &this_args_cbk->stat, &xdata); CLIENT_POST_FOP_TYPE(fstat, this_rsp, this_args_cbk, &this_args_cbk->stat, xdata); break; } case GF_FOP_LK: { gfs3_lk_rsp *tmp_rsp = NULL; tmp_rsp = &this_rsp->compound_rsp_u.compound_lk_rsp; client_post_lk(this, tmp_rsp, &this_args_cbk->lock, &xdata); CLIENT_POST_FOP_TYPE(lk, this_rsp, this_args_cbk, &this_args_cbk->lock, xdata); break; } case GF_FOP_LOOKUP: { gfs3_lookup_rsp *tmp_rsp = NULL; tmp_rsp = &this_rsp->compound_rsp_u.compound_lookup_rsp; client_post_lookup(this, tmp_rsp, &this_args_cbk->stat, &this_args_cbk->postparent, &xdata); CLIENT_POST_FOP_TYPE(lookup, this_rsp, this_args_cbk, local->loc.inode, &this_args_cbk->stat, xdata, &this_args_cbk->postparent); break; } case GF_FOP_READDIR: { gfs3_readdir_rsp *tmp_rsp = NULL; tmp_rsp = &this_rsp->compound_rsp_u.compound_readdir_rsp; client_post_readdir(this, tmp_rsp, &entries, &xdata); CLIENT_POST_FOP_TYPE(readdir, this_rsp, this_args_cbk, &entries, xdata); break; } case GF_FOP_INODELK: { gf_common_rsp *tmp_rsp = NULL; tmp_rsp = &this_rsp->compound_rsp_u.compound_inodelk_rsp; client_post_inodelk(this, tmp_rsp, &xdata); CLIENT_POST_FOP(inodelk, this_rsp, this_args_cbk, xdata); break; } case GF_FOP_FINODELK: { gf_common_rsp *tmp_rsp = NULL; tmp_rsp = &this_rsp->compound_rsp_u.compound_finodelk_rsp; client_post_finodelk(this, tmp_rsp, &xdata); CLIENT_POST_FOP(finodelk, this_rsp, this_args_cbk, xdata); if (tmp_rsp->op_ret == 0) if (local->attempt_reopen) client_attempt_reopen(local->fd, this); break; } case GF_FOP_ENTRYLK: { gf_common_rsp *tmp_rsp = NULL; tmp_rsp = &this_rsp->compound_rsp_u.compound_entrylk_rsp; client_post_entrylk(this, tmp_rsp, &xdata); CLIENT_POST_FOP(entrylk, this_rsp, this_args_cbk, xdata); break; } case GF_FOP_FENTRYLK: { gf_common_rsp *tmp_rsp = NULL; tmp_rsp = &this_rsp->compound_rsp_u.compound_fentrylk_rsp; client_post_fentrylk(this, tmp_rsp, &xdata); CLIENT_POST_FOP(fentrylk, this_rsp, this_args_cbk, xdata); break; } case GF_FOP_XATTROP: { gfs3_xattrop_rsp *tmp_rsp = NULL; tmp_rsp = &this_rsp->compound_rsp_u.compound_xattrop_rsp; client_post_xattrop(this, tmp_rsp, &xattr, &xdata); CLIENT_POST_FOP_TYPE(xattrop, this_rsp, this_args_cbk, xattr, xdata); break; } case GF_FOP_FXATTROP: { gfs3_fxattrop_rsp *tmp_rsp = NULL; tmp_rsp = &this_rsp->compound_rsp_u.compound_fxattrop_rsp; client_post_fxattrop(this, tmp_rsp, &xattr, &xdata); CLIENT_POST_FOP_TYPE(fxattrop, this_rsp, this_args_cbk, xattr, xdata); if (rsp->op_ret == 0) if (local->attempt_reopen) client_attempt_reopen(local->fd, this); break; } case GF_FOP_FGETXATTR: { gfs3_fgetxattr_rsp *tmp_rsp = NULL; tmp_rsp = &this_rsp->compound_rsp_u.compound_fgetxattr_rsp; client_post_fgetxattr(this, tmp_rsp, &xattr, &xdata); CLIENT_POST_FOP_TYPE(fgetxattr, this_rsp, this_args_cbk, xattr, xdata); break; } case GF_FOP_FSETXATTR: { gf_common_rsp *tmp_rsp = NULL; tmp_rsp = &this_rsp->compound_rsp_u.compound_fsetxattr_rsp; client_post_fsetxattr(this, tmp_rsp, &xdata); CLIENT_POST_FOP(fsetxattr, this_rsp, this_args_cbk, xdata); break; } case GF_FOP_RCHECKSUM: { gfs3_rchecksum_rsp *tmp_rsp = NULL; tmp_rsp = &this_rsp->compound_rsp_u.compound_rchecksum_rsp; client_post_rchecksum(this, tmp_rsp, &xdata); break; CLIENT_POST_FOP_TYPE( rchecksum, this_rsp, this_args_cbk, tmp_rsp->weak_checksum, (uint8_t *)tmp_rsp->strong_checksum.strong_checksum_val, xdata); break; } case GF_FOP_SETATTR: { gfs3_setattr_rsp *tmp_rsp = NULL; tmp_rsp = &this_rsp->compound_rsp_u.compound_setattr_rsp; client_post_setattr(this, tmp_rsp, &this_args_cbk->prestat, &this_args_cbk->poststat, &xdata); CLIENT_POST_FOP_TYPE(setattr, this_rsp, this_args_cbk, &this_args_cbk->prestat, &this_args_cbk->poststat, xdata); break; } case GF_FOP_FSETATTR: { gfs3_fsetattr_rsp *tmp_rsp = NULL; tmp_rsp = &this_rsp->compound_rsp_u.compound_fsetattr_rsp; client_post_fsetattr(this, tmp_rsp, &this_args_cbk->prestat, &this_args_cbk->poststat, &xdata); CLIENT_POST_FOP_TYPE(fsetattr, this_rsp, this_args_cbk, &this_args_cbk->prestat, &this_args_cbk->poststat, xdata); break; } case GF_FOP_READDIRP: { gfs3_readdirp_rsp *tmp_rsp = NULL; tmp_rsp = &this_rsp->compound_rsp_u.compound_readdirp_rsp; client_post_readdirp(this, tmp_rsp, local->fd, &entries, &xdata); CLIENT_POST_FOP_TYPE(readdirp, this_rsp, this_args_cbk, &entries, xdata); break; } case GF_FOP_FREMOVEXATTR: { gf_common_rsp *tmp_rsp = NULL; tmp_rsp = &this_rsp->compound_rsp_u.compound_fremovexattr_rsp; client_post_fremovexattr(this, tmp_rsp, &xdata); CLIENT_POST_FOP(fremovexattr, this_rsp, this_args_cbk, xdata); break; } case GF_FOP_FALLOCATE: { gfs3_fallocate_rsp *tmp_rsp = NULL; tmp_rsp = &this_rsp->compound_rsp_u.compound_fallocate_rsp; client_post_fallocate(this, tmp_rsp, &this_args_cbk->prestat, &this_args_cbk->poststat, &xdata); CLIENT_POST_FOP_TYPE(fallocate, this_rsp, this_args_cbk, &this_args_cbk->prestat, &this_args_cbk->poststat, xdata); break; } case GF_FOP_DISCARD: { gfs3_discard_rsp *tmp_rsp = NULL; tmp_rsp = &this_rsp->compound_rsp_u.compound_discard_rsp; client_post_discard(this, tmp_rsp, &this_args_cbk->prestat, &this_args_cbk->poststat, &xdata); CLIENT_POST_FOP_TYPE(discard, this_rsp, this_args_cbk, &this_args_cbk->prestat, &this_args_cbk->poststat, xdata); break; } case GF_FOP_ZEROFILL: { gfs3_zerofill_rsp *tmp_rsp = NULL; tmp_rsp = &this_rsp->compound_rsp_u.compound_zerofill_rsp; client_post_zerofill(this, tmp_rsp, &this_args_cbk->prestat, &this_args_cbk->poststat, &xdata); CLIENT_POST_FOP_TYPE(zerofill, this_rsp, this_args_cbk, &this_args_cbk->prestat, &this_args_cbk->poststat, xdata); break; } case GF_FOP_IPC: { gfs3_ipc_rsp *tmp_rsp = NULL; tmp_rsp = &this_rsp->compound_rsp_u.compound_ipc_rsp; client_post_ipc(this, tmp_rsp, &xdata); CLIENT_POST_FOP_TYPE(ipc, this_rsp, this_args_cbk, xdata); break; } case GF_FOP_SEEK: { gfs3_seek_rsp *tmp_rsp = NULL; tmp_rsp = &this_rsp->compound_rsp_u.compound_seek_rsp; client_post_seek(this, tmp_rsp, &xdata); CLIENT_POST_FOP_TYPE(seek, this_rsp, this_args_cbk, tmp_rsp->offset, xdata); break; } case GF_FOP_LEASE: { gfs3_lease_rsp *tmp_rsp = NULL; tmp_rsp = &this_rsp->compound_rsp_u.compound_lease_rsp; client_post_lease(this, tmp_rsp, &this_args_cbk->lease, &xdata); CLIENT_POST_FOP_TYPE(lease, this_rsp, this_args_cbk, &this_args_cbk->lease, xdata); break; } default: return -ENOTSUP; } if (xdata) dict_unref(xdata); if (xattr) dict_unref(xattr); gf_dirent_free(&entries); return 0; } int client_handle_fop_requirements( xlator_t *this, call_frame_t *frame, gfs3_compound_req *req, clnt_local_t *local, struct iobref **req_iobref, struct iobref **rsp_iobref, struct iovec *req_vector, struct iovec *rsp_vector, int *req_count, int *rsp_count, default_args_t *args, int fop_enum, int index) { int ret = 0; int op_errno = ENOMEM; struct iobuf *rsp_iobuf = NULL; int64_t remote_fd = -1; compound_req *this_req = &req->compound_req_array .compound_req_array_val[index]; this_req->fop_enum = fop_enum; switch (fop_enum) { case GF_FOP_STAT: CLIENT_PRE_FOP(stat, this, &this_req->compound_req_u.compound_stat_req, op_errno, out, &args->loc, args->xdata); break; case GF_FOP_READLINK: CLIENT_PRE_FOP(readlink, this, &this_req->compound_req_u.compound_readlink_req, op_errno, out, &args->loc, args->size, args->xdata); break; case GF_FOP_MKNOD: CLIENT_PRE_FOP(mknod, this, &this_req->compound_req_u.compound_mknod_req, op_errno, out, &args->loc, args->mode, args->rdev, args->umask, args->xdata); loc_copy(&local->loc, &args->loc); loc_path(&local->loc, NULL); break; case GF_FOP_MKDIR: CLIENT_PRE_FOP(mkdir, this, &this_req->compound_req_u.compound_mkdir_req, op_errno, out, &args->loc, args->mode, args->umask, args->xdata); loc_copy(&local->loc, &args->loc); loc_path(&local->loc, NULL); break; case GF_FOP_UNLINK: CLIENT_PRE_FOP(unlink, this, &this_req->compound_req_u.compound_unlink_req, op_errno, out, &args->loc, args->xflag, args->xdata); break; case GF_FOP_RMDIR: CLIENT_PRE_FOP(rmdir, this, &this_req->compound_req_u.compound_rmdir_req, op_errno, out, &args->loc, args->flags, args->xdata); break; case GF_FOP_SYMLINK: CLIENT_PRE_FOP(symlink, this, &this_req->compound_req_u.compound_symlink_req, op_errno, out, &args->loc, args->linkname, args->umask, args->xdata); loc_copy(&local->loc, &args->loc); loc_path(&local->loc, NULL); break; case GF_FOP_RENAME: CLIENT_PRE_FOP(rename, this, &this_req->compound_req_u.compound_rename_req, op_errno, out, &args->loc, &args->loc2, args->xdata); break; case GF_FOP_LINK: CLIENT_PRE_FOP(link, this, &this_req->compound_req_u.compound_link_req, op_errno, out, &args->loc, &args->loc2, args->xdata); break; case GF_FOP_TRUNCATE: CLIENT_PRE_FOP( truncate, this, &this_req->compound_req_u.compound_truncate_req, op_errno, out, &args->loc, args->offset, args->xdata); break; case GF_FOP_OPEN: CLIENT_PRE_FOP( open, this, &this_req->compound_req_u.compound_open_req, op_errno, out, &args->loc, args->fd, args->flags, args->xdata); if (!local->fd) local->fd = fd_ref(args->fd); break; case GF_FOP_READ: op_errno = client_pre_readv( this, &this_req->compound_req_u.compound_read_req, args->fd, args->size, args->offset, args->flags, args->xdata); if (op_errno) { op_errno = -op_errno; goto out; } if (!local->fd) local->fd = fd_ref(args->fd); local->attempt_reopen = client_is_reopen_needed(args->fd, this, remote_fd); rsp_iobuf = iobuf_get2(this->ctx->iobuf_pool, args->size); if (rsp_iobuf == NULL) { op_errno = ENOMEM; goto out; } if (!*rsp_iobref) { *rsp_iobref = iobref_new(); if (*rsp_iobref == NULL) { op_errno = ENOMEM; goto out; } } if (*rsp_count + 1 >= MAX_IOVEC) { op_errno = ENOMEM; goto out; } rsp_vector[*rsp_count].iov_base = iobuf_ptr(rsp_iobuf); rsp_vector[*rsp_count].iov_len = iobuf_pagesize(rsp_iobuf); iobref_add(*rsp_iobref, rsp_iobuf); iobuf_unref(rsp_iobuf); rsp_iobuf = NULL; if (args->size > rsp_vector[*rsp_count].iov_len) { gf_msg(this->name, GF_LOG_WARNING, ENOMEM, PC_MSG_NO_MEMORY, "read-size (%lu) is bigger than iobuf size " "(%lu)", (unsigned long)args->size, (unsigned long)rsp_vector[*rsp_count].iov_len); op_errno = EINVAL; goto out; } *rsp_count += 1; break; case GF_FOP_WRITE: op_errno = client_pre_writev( this, &this_req->compound_req_u.compound_write_req, args->fd, iov_length(args->vector, args->count), args->offset, args->flags, &args->xdata); if (op_errno) { op_errno = -op_errno; goto out; } if (!local->fd) local->fd = fd_ref(args->fd); local->attempt_reopen = client_is_reopen_needed(args->fd, this, remote_fd); if (*req_count + args->count >= MAX_IOVEC) { op_errno = ENOMEM; goto out; } memcpy(&req_vector[*req_count], args->vector, (args->count * sizeof(req_vector[0]))); *req_count += args->count; if (!*req_iobref) *req_iobref = args->iobref; else if (iobref_merge(*req_iobref, args->iobref)) goto out; break; case GF_FOP_STATFS: CLIENT_PRE_FOP(statfs, this, &this_req->compound_req_u.compound_statfs_req, op_errno, out, &args->loc, args->xdata); break; case GF_FOP_FLUSH: CLIENT_PRE_FOP(flush, this, &this_req->compound_req_u.compound_flush_req, op_errno, out, args->fd, args->xdata); if (!local->fd) local->fd = fd_ref(args->fd); local->owner = frame->root->lk_owner; break; case GF_FOP_FSYNC: CLIENT_PRE_FOP( fsync, this, &this_req->compound_req_u.compound_fsync_req, op_errno, out, args->fd, args->datasync, args->xdata); break; case GF_FOP_SETXATTR: CLIENT_PRE_FOP(setxattr, this, &this_req->compound_req_u.compound_setxattr_req, op_errno, out, &args->loc, args->xattr, args->flags, args->xdata); break; case GF_FOP_GETXATTR: CLIENT_PRE_FOP(getxattr, this, &this_req->compound_req_u.compound_getxattr_req, op_errno, out, &args->loc, args->name, args->xdata); loc_copy(&local->loc, &args->loc); loc_path(&local->loc, NULL); break; case GF_FOP_REMOVEXATTR: CLIENT_PRE_FOP(removexattr, this, &this_req->compound_req_u.compound_removexattr_req, op_errno, out, &args->loc, args->name, args->xdata); break; case GF_FOP_OPENDIR: CLIENT_PRE_FOP(opendir, this, &this_req->compound_req_u.compound_opendir_req, op_errno, out, &args->loc, args->fd, args->xdata); if (!local->fd) local->fd = fd_ref(args->fd); loc_copy(&local->loc, &args->loc); loc_path(&local->loc, NULL); break; case GF_FOP_FSYNCDIR: CLIENT_PRE_FOP( fsyncdir, this, &this_req->compound_req_u.compound_fsyncdir_req, op_errno, out, args->fd, args->datasync, args->xdata); break; case GF_FOP_ACCESS: CLIENT_PRE_FOP(access, this, &this_req->compound_req_u.compound_access_req, op_errno, out, &args->loc, args->mask, args->xdata); break; case GF_FOP_CREATE: CLIENT_PRE_FOP(create, this, &this_req->compound_req_u.compound_create_req, op_errno, out, &args->loc, args->fd, args->mode, args->flags, args->umask, args->xdata); if (!local->fd) local->fd = fd_ref(args->fd); loc_copy(&local->loc, &args->loc); loc_path(&local->loc, NULL); break; case GF_FOP_FTRUNCATE: CLIENT_PRE_FOP(ftruncate, this, &this_req->compound_req_u.compound_ftruncate_req, op_errno, out, args->fd, args->offset, args->xdata); break; case GF_FOP_FSTAT: CLIENT_PRE_FOP(fstat, this, &this_req->compound_req_u.compound_fstat_req, op_errno, out, args->fd, args->xdata); break; case GF_FOP_LK: CLIENT_PRE_FOP(lk, this, &this_req->compound_req_u.compound_lk_req, op_errno, out, args->cmd, &args->lock, args->fd, args->xdata); if (!local->fd) local->fd = fd_ref(args->fd); local->owner = frame->root->lk_owner; break; case GF_FOP_LOOKUP: CLIENT_PRE_FOP(lookup, this, &this_req->compound_req_u.compound_lookup_req, op_errno, out, &args->loc, args->xdata); loc_copy(&local->loc, &args->loc); loc_path(&local->loc, NULL); break; case GF_FOP_READDIR: CLIENT_PRE_FOP( readdir, this, &this_req->compound_req_u.compound_readdir_req, op_errno, out, args->fd, args->size, args->offset, args->xdata); break; case GF_FOP_INODELK: CLIENT_PRE_FOP(inodelk, this, &this_req->compound_req_u.compound_inodelk_req, op_errno, out, &args->loc, args->cmd, &args->lock, args->volume, args->xdata); break; case GF_FOP_FINODELK: CLIENT_PRE_FOP(finodelk, this, &this_req->compound_req_u.compound_finodelk_req, op_errno, out, args->fd, args->cmd, &args->lock, args->volume, args->xdata); if (!local->fd) local->fd = fd_ref(args->fd); local->attempt_reopen = client_is_reopen_needed(args->fd, this, remote_fd); break; case GF_FOP_ENTRYLK: CLIENT_PRE_FOP( entrylk, this, &this_req->compound_req_u.compound_entrylk_req, op_errno, out, &args->loc, args->entrylkcmd, args->entrylktype, args->volume, args->name, args->xdata); break; case GF_FOP_FENTRYLK: CLIENT_PRE_FOP( fentrylk, this, &this_req->compound_req_u.compound_fentrylk_req, op_errno, out, args->fd, args->entrylkcmd, args->entrylktype, args->volume, args->name, args->xdata); break; case GF_FOP_XATTROP: CLIENT_PRE_FOP(xattrop, this, &this_req->compound_req_u.compound_xattrop_req, op_errno, out, &args->loc, args->xattr, args->optype, args->xdata); break; case GF_FOP_FXATTROP: CLIENT_PRE_FOP(fxattrop, this, &this_req->compound_req_u.compound_fxattrop_req, op_errno, out, args->fd, args->xattr, args->optype, args->xdata); if (!local->fd) local->fd = fd_ref(args->fd); local->attempt_reopen = client_is_reopen_needed(args->fd, this, remote_fd); break; case GF_FOP_FGETXATTR: CLIENT_PRE_FOP(fgetxattr, this, &this_req->compound_req_u.compound_fgetxattr_req, op_errno, out, args->fd, args->name, args->xdata); break; case GF_FOP_FSETXATTR: CLIENT_PRE_FOP(fsetxattr, this, &this_req->compound_req_u.compound_fsetxattr_req, op_errno, out, args->fd, args->flags, args->xattr, args->xdata); break; case GF_FOP_RCHECKSUM: CLIENT_PRE_FOP(rchecksum, this, &this_req->compound_req_u.compound_rchecksum_req, op_errno, out, args->fd, args->size, args->offset, args->xdata); break; case GF_FOP_SETATTR: CLIENT_PRE_FOP(setattr, this, &this_req->compound_req_u.compound_setattr_req, op_errno, out, &args->loc, args->valid, &args->stat, args->xdata); break; case GF_FOP_FSETATTR: CLIENT_PRE_FOP( fsetattr, this, &this_req->compound_req_u.compound_fsetattr_req, op_errno, out, args->fd, args->valid, &args->stat, args->xdata); break; case GF_FOP_READDIRP: CLIENT_PRE_FOP( readdirp, this, &this_req->compound_req_u.compound_readdirp_req, op_errno, out, args->fd, args->size, args->offset, args->xdata); if (!local->fd) local->fd = fd_ref(args->fd); break; case GF_FOP_FREMOVEXATTR: CLIENT_PRE_FOP(fremovexattr, this, &this_req->compound_req_u.compound_fremovexattr_req, op_errno, out, args->fd, args->name, args->xdata); break; case GF_FOP_FALLOCATE: CLIENT_PRE_FOP(fallocate, this, &this_req->compound_req_u.compound_fallocate_req, op_errno, out, args->fd, args->flags, args->offset, args->size, args->xdata); break; case GF_FOP_DISCARD: CLIENT_PRE_FOP( discard, this, &this_req->compound_req_u.compound_discard_req, op_errno, out, args->fd, args->offset, args->size, args->xdata); break; case GF_FOP_ZEROFILL: CLIENT_PRE_FOP( zerofill, this, &this_req->compound_req_u.compound_zerofill_req, op_errno, out, args->fd, args->offset, args->size, args->xdata); break; case GF_FOP_IPC: CLIENT_PRE_FOP(ipc, this, &this_req->compound_req_u.compound_ipc_req, op_errno, out, args->cmd, args->xdata); break; case GF_FOP_SEEK: CLIENT_PRE_FOP( seek, this, &this_req->compound_req_u.compound_seek_req, op_errno, out, args->fd, args->offset, args->what, args->xdata); break; case GF_FOP_LEASE: CLIENT_PRE_FOP( lease, this, &this_req->compound_req_u.compound_lease_req, op_errno, out, &args->loc, &args->lease, args->xdata); break; default: return ENOTSUP; } return 0; out: return op_errno; } void compound_request_cleanup(gfs3_compound_req *req) { int i = 0; int length = req->compound_req_array.compound_req_array_len; compound_req *curr_req = NULL; if (!req->compound_req_array.compound_req_array_val) return; for (i = 0; i < length; i++) { curr_req = &req->compound_req_array.compound_req_array_val[i]; switch (curr_req->fop_enum) { case GF_FOP_STAT: CLIENT_COMPOUND_FOP_CLEANUP(curr_req, stat); break; case GF_FOP_READLINK: CLIENT_COMPOUND_FOP_CLEANUP(curr_req, readlink); break; case GF_FOP_MKNOD: CLIENT_COMPOUND_FOP_CLEANUP(curr_req, mknod); break; case GF_FOP_MKDIR: CLIENT_COMPOUND_FOP_CLEANUP(curr_req, mkdir); break; case GF_FOP_UNLINK: CLIENT_COMPOUND_FOP_CLEANUP(curr_req, unlink); break; case GF_FOP_RMDIR: CLIENT_COMPOUND_FOP_CLEANUP(curr_req, rmdir); break; case GF_FOP_SYMLINK: CLIENT_COMPOUND_FOP_CLEANUP(curr_req, symlink); break; case GF_FOP_RENAME: CLIENT_COMPOUND_FOP_CLEANUP(curr_req, rename); break; case GF_FOP_LINK: CLIENT_COMPOUND_FOP_CLEANUP(curr_req, link); break; case GF_FOP_TRUNCATE: CLIENT_COMPOUND_FOP_CLEANUP(curr_req, truncate); break; case GF_FOP_OPEN: CLIENT_COMPOUND_FOP_CLEANUP(curr_req, open); break; case GF_FOP_READ: CLIENT_COMPOUND_FOP_CLEANUP(curr_req, read); break; case GF_FOP_WRITE: CLIENT_COMPOUND_FOP_CLEANUP(curr_req, write); break; case GF_FOP_STATFS: CLIENT_COMPOUND_FOP_CLEANUP(curr_req, statfs); break; case GF_FOP_FLUSH: CLIENT_COMPOUND_FOP_CLEANUP(curr_req, flush); break; case GF_FOP_FSYNC: CLIENT_COMPOUND_FOP_CLEANUP(curr_req, fsync); break; case GF_FOP_SETXATTR: { gfs3_setxattr_req *args = &CPD_REQ_FIELD(curr_req, setxattr); GF_FREE(args->dict.dict_val); CLIENT_COMPOUND_FOP_CLEANUP(curr_req, setxattr); break; } case GF_FOP_GETXATTR: CLIENT_COMPOUND_FOP_CLEANUP(curr_req, getxattr); break; case GF_FOP_REMOVEXATTR: CLIENT_COMPOUND_FOP_CLEANUP(curr_req, removexattr); break; case GF_FOP_OPENDIR: CLIENT_COMPOUND_FOP_CLEANUP(curr_req, opendir); break; case GF_FOP_FSYNCDIR: CLIENT_COMPOUND_FOP_CLEANUP(curr_req, fsyncdir); break; case GF_FOP_ACCESS: CLIENT_COMPOUND_FOP_CLEANUP(curr_req, access); break; case GF_FOP_CREATE: CLIENT_COMPOUND_FOP_CLEANUP(curr_req, create); break; case GF_FOP_FTRUNCATE: CLIENT_COMPOUND_FOP_CLEANUP(curr_req, ftruncate); break; case GF_FOP_FSTAT: CLIENT_COMPOUND_FOP_CLEANUP(curr_req, fstat); break; case GF_FOP_LK: CLIENT_COMPOUND_FOP_CLEANUP(curr_req, lk); break; case GF_FOP_LOOKUP: CLIENT_COMPOUND_FOP_CLEANUP(curr_req, lookup); break; case GF_FOP_READDIR: CLIENT_COMPOUND_FOP_CLEANUP(curr_req, readdir); break; case GF_FOP_INODELK: CLIENT_COMPOUND_FOP_CLEANUP(curr_req, inodelk); break; case GF_FOP_FINODELK: CLIENT_COMPOUND_FOP_CLEANUP(curr_req, finodelk); break; case GF_FOP_ENTRYLK: CLIENT_COMPOUND_FOP_CLEANUP(curr_req, entrylk); break; case GF_FOP_FENTRYLK: CLIENT_COMPOUND_FOP_CLEANUP(curr_req, fentrylk); break; case GF_FOP_XATTROP: { gfs3_xattrop_req *args = &CPD_REQ_FIELD(curr_req, xattrop); GF_FREE(args->dict.dict_val); CLIENT_COMPOUND_FOP_CLEANUP(curr_req, xattrop); break; } case GF_FOP_FXATTROP: { gfs3_fxattrop_req *args = &CPD_REQ_FIELD(curr_req, fxattrop); GF_FREE(args->dict.dict_val); CLIENT_COMPOUND_FOP_CLEANUP(curr_req, fxattrop); break; } case GF_FOP_FGETXATTR: CLIENT_COMPOUND_FOP_CLEANUP(curr_req, fgetxattr); break; case GF_FOP_FSETXATTR: { gfs3_fsetxattr_req *args = &CPD_REQ_FIELD(curr_req, fsetxattr); GF_FREE(args->dict.dict_val); CLIENT_COMPOUND_FOP_CLEANUP(curr_req, fsetxattr); break; } case GF_FOP_RCHECKSUM: CLIENT_COMPOUND_FOP_CLEANUP(curr_req, rchecksum); break; case GF_FOP_SETATTR: CLIENT_COMPOUND_FOP_CLEANUP(curr_req, setattr); break; case GF_FOP_FSETATTR: CLIENT_COMPOUND_FOP_CLEANUP(curr_req, fsetattr); break; case GF_FOP_READDIRP: { gfs3_readdirp_req *args = &CPD_REQ_FIELD(curr_req, readdirp); GF_FREE(args->dict.dict_val); break; } case GF_FOP_FREMOVEXATTR: CLIENT_COMPOUND_FOP_CLEANUP(curr_req, fremovexattr); break; case GF_FOP_FALLOCATE: CLIENT_COMPOUND_FOP_CLEANUP(curr_req, fallocate); break; case GF_FOP_DISCARD: CLIENT_COMPOUND_FOP_CLEANUP(curr_req, discard); break; case GF_FOP_ZEROFILL: CLIENT_COMPOUND_FOP_CLEANUP(curr_req, zerofill); break; case GF_FOP_IPC: CLIENT_COMPOUND_FOP_CLEANUP(curr_req, ipc); break; case GF_FOP_SEEK: CLIENT_COMPOUND_FOP_CLEANUP(curr_req, seek); break; default: break; } } GF_FREE(req->compound_req_array.compound_req_array_val); return; } void clnt_getactivelk_rsp_cleanup(gfs3_getactivelk_rsp *rsp) { gfs3_locklist *trav = NULL; gfs3_locklist *next = NULL; trav = rsp->reply; while (trav) { next = trav->nextentry; free(trav->client_uid); free(trav); trav = next; } } void clnt_getactivelk_rsp_cleanup_v2(gfx_getactivelk_rsp *rsp) { gfs3_locklist *trav = NULL; gfs3_locklist *next = NULL; trav = rsp->reply; while (trav) { next = trav->nextentry; free(trav->client_uid); free(trav); trav = next; } } int clnt_unserialize_rsp_locklist(xlator_t *this, struct gfs3_getactivelk_rsp *rsp, lock_migration_info_t *lmi) { struct gfs3_locklist *trav = NULL; lock_migration_info_t *temp = NULL; int ret = -1; clnt_conf_t *conf = NULL; trav = rsp->reply; conf = this->private; if (!conf) goto out; while (trav) { temp = GF_CALLOC(1, sizeof(*lmi), gf_common_mt_lock_mig); if (temp == NULL) { gf_msg(this->name, GF_LOG_ERROR, 0, 0, "No memory"); goto out; } INIT_LIST_HEAD(&temp->list); gf_proto_flock_to_flock(&trav->flock, &temp->flock); temp->lk_flags = trav->lk_flags; temp->client_uid = gf_strdup(trav->client_uid); list_add_tail(&temp->list, &lmi->list); trav = trav->nextentry; } ret = 0; out: return ret; } int clnt_unserialize_rsp_locklist_v2(xlator_t *this, struct gfx_getactivelk_rsp *rsp, lock_migration_info_t *lmi) { struct gfs3_locklist *trav = NULL; lock_migration_info_t *temp = NULL; int ret = -1; clnt_conf_t *conf = NULL; trav = rsp->reply; conf = this->private; if (!conf) goto out; while (trav) { temp = GF_CALLOC(1, sizeof(*lmi), gf_common_mt_lock_mig); if (temp == NULL) { gf_msg(this->name, GF_LOG_ERROR, 0, 0, "No memory"); goto out; } INIT_LIST_HEAD(&temp->list); gf_proto_flock_to_flock(&trav->flock, &temp->flock); temp->lk_flags = trav->lk_flags; temp->client_uid = gf_strdup(trav->client_uid); list_add_tail(&temp->list, &lmi->list); trav = trav->nextentry; } ret = 0; out: return ret; } void clnt_setactivelk_req_cleanup(gfs3_setactivelk_req *req) { gfs3_locklist *trav = NULL; gfs3_locklist *next = NULL; trav = req->request; while (trav) { next = trav->nextentry; GF_FREE(trav->client_uid); GF_FREE(trav); trav = next; } } void clnt_setactivelk_req_cleanup_v2(gfx_setactivelk_req *req) { gfs3_locklist *trav = NULL; gfs3_locklist *next = NULL; trav = req->request; while (trav) { next = trav->nextentry; GF_FREE(trav->client_uid); GF_FREE(trav); trav = next; } } int serialize_req_locklist(lock_migration_info_t *locklist, gfs3_setactivelk_req *req) { lock_migration_info_t *tmp = NULL; gfs3_locklist *trav = NULL; gfs3_locklist *prev = NULL; int ret = -1; GF_VALIDATE_OR_GOTO("server", locklist, out); GF_VALIDATE_OR_GOTO("server", req, out); list_for_each_entry(tmp, &locklist->list, list) { trav = GF_CALLOC(1, sizeof(*trav), gf_client_mt_clnt_lock_request_t); if (!trav) goto out; switch (tmp->flock.l_type) { case F_RDLCK: tmp->flock.l_type = GF_LK_F_RDLCK; break; case F_WRLCK: tmp->flock.l_type = GF_LK_F_WRLCK; break; case F_UNLCK: tmp->flock.l_type = GF_LK_F_UNLCK; break; default: gf_msg(THIS->name, GF_LOG_ERROR, 0, 0, "Unknown lock type: %" PRId32 "!", tmp->flock.l_type); break; } gf_proto_flock_from_flock(&trav->flock, &tmp->flock); trav->lk_flags = tmp->lk_flags; trav->client_uid = gf_strdup(tmp->client_uid); if (!trav->client_uid) { gf_msg(THIS->name, GF_LOG_ERROR, 0, 0, "client_uid could not be allocated"); ret = -1; goto out; } if (prev) prev->nextentry = trav; else req->request = trav; prev = trav; trav = NULL; } ret = 0; out: GF_FREE(trav); return ret; } int serialize_req_locklist_v2(lock_migration_info_t *locklist, gfx_setactivelk_req *req) { lock_migration_info_t *tmp = NULL; gfs3_locklist *trav = NULL; gfs3_locklist *prev = NULL; int ret = -1; GF_VALIDATE_OR_GOTO("server", locklist, out); GF_VALIDATE_OR_GOTO("server", req, out); list_for_each_entry(tmp, &locklist->list, list) { trav = GF_CALLOC(1, sizeof(*trav), gf_client_mt_clnt_lock_request_t); if (!trav) goto out; switch (tmp->flock.l_type) { case F_RDLCK: tmp->flock.l_type = GF_LK_F_RDLCK; break; case F_WRLCK: tmp->flock.l_type = GF_LK_F_WRLCK; break; case F_UNLCK: tmp->flock.l_type = GF_LK_F_UNLCK; break; default: gf_msg(THIS->name, GF_LOG_ERROR, 0, 0, "Unknown lock type: %" PRId32 "!", tmp->flock.l_type); break; } gf_proto_flock_from_flock(&trav->flock, &tmp->flock); trav->lk_flags = tmp->lk_flags; trav->client_uid = gf_strdup(tmp->client_uid); if (!trav->client_uid) { gf_msg(THIS->name, GF_LOG_ERROR, 0, 0, "client_uid could not be allocated"); ret = -1; goto out; } if (prev) prev->nextentry = trav; else req->request = trav; prev = trav; trav = NULL; } ret = 0; out: GF_FREE(trav); return ret; } void client_compound_rsp_cleanup(gfs3_compound_rsp *rsp, int len) { int i = 0; compound_rsp *this_rsp = NULL; for (i = 0; i < len; i++) { this_rsp = &rsp->compound_rsp_array.compound_rsp_array_val[i]; switch (this_rsp->fop_enum) { case GF_FOP_STAT: CLIENT_FOP_RSP_CLEANUP(rsp, stat, i); break; case GF_FOP_MKNOD: CLIENT_FOP_RSP_CLEANUP(rsp, mknod, i); break; case GF_FOP_MKDIR: CLIENT_FOP_RSP_CLEANUP(rsp, mkdir, i); break; case GF_FOP_UNLINK: CLIENT_FOP_RSP_CLEANUP(rsp, unlink, i); break; case GF_FOP_RMDIR: CLIENT_FOP_RSP_CLEANUP(rsp, rmdir, i); break; case GF_FOP_SYMLINK: CLIENT_FOP_RSP_CLEANUP(rsp, symlink, i); break; case GF_FOP_RENAME: CLIENT_FOP_RSP_CLEANUP(rsp, rename, i); break; case GF_FOP_LINK: CLIENT_FOP_RSP_CLEANUP(rsp, link, i); break; case GF_FOP_TRUNCATE: CLIENT_FOP_RSP_CLEANUP(rsp, truncate, i); break; case GF_FOP_OPEN: CLIENT_FOP_RSP_CLEANUP(rsp, open, i); break; case GF_FOP_READ: CLIENT_FOP_RSP_CLEANUP(rsp, read, i); break; case GF_FOP_WRITE: CLIENT_FOP_RSP_CLEANUP(rsp, write, i); break; case GF_FOP_STATFS: CLIENT_FOP_RSP_CLEANUP(rsp, statfs, i); break; case GF_FOP_FSYNC: CLIENT_FOP_RSP_CLEANUP(rsp, fsync, i); break; case GF_FOP_OPENDIR: CLIENT_FOP_RSP_CLEANUP(rsp, opendir, i); break; case GF_FOP_CREATE: CLIENT_FOP_RSP_CLEANUP(rsp, create, i); break; case GF_FOP_FTRUNCATE: CLIENT_FOP_RSP_CLEANUP(rsp, ftruncate, i); break; case GF_FOP_FSTAT: CLIENT_FOP_RSP_CLEANUP(rsp, fstat, i); break; case GF_FOP_LOOKUP: CLIENT_FOP_RSP_CLEANUP(rsp, lookup, i); break; case GF_FOP_SETATTR: CLIENT_FOP_RSP_CLEANUP(rsp, setattr, i); break; case GF_FOP_FSETATTR: CLIENT_FOP_RSP_CLEANUP(rsp, fsetattr, i); break; case GF_FOP_FALLOCATE: CLIENT_FOP_RSP_CLEANUP(rsp, fallocate, i); break; case GF_FOP_DISCARD: CLIENT_FOP_RSP_CLEANUP(rsp, discard, i); break; case GF_FOP_ZEROFILL: CLIENT_FOP_RSP_CLEANUP(rsp, zerofill, i); break; case GF_FOP_IPC: CLIENT_FOP_RSP_CLEANUP(rsp, ipc, i); break; case GF_FOP_SEEK: CLIENT_FOP_RSP_CLEANUP(rsp, seek, i); break; case GF_FOP_LEASE: CLIENT_FOP_RSP_CLEANUP(rsp, lease, i); break; /* fops that use gf_common_rsp */ case GF_FOP_FLUSH: CLIENT_COMMON_RSP_CLEANUP(rsp, flush, i); break; case GF_FOP_SETXATTR: CLIENT_COMMON_RSP_CLEANUP(rsp, setxattr, i); break; case GF_FOP_REMOVEXATTR: CLIENT_COMMON_RSP_CLEANUP(rsp, removexattr, i); break; case GF_FOP_FSETXATTR: CLIENT_COMMON_RSP_CLEANUP(rsp, fsetxattr, i); break; case GF_FOP_FREMOVEXATTR: CLIENT_COMMON_RSP_CLEANUP(rsp, fremovexattr, i); break; case GF_FOP_FSYNCDIR: CLIENT_COMMON_RSP_CLEANUP(rsp, fsyncdir, i); break; case GF_FOP_ACCESS: CLIENT_COMMON_RSP_CLEANUP(rsp, access, i); break; case GF_FOP_INODELK: CLIENT_COMMON_RSP_CLEANUP(rsp, inodelk, i); break; case GF_FOP_FINODELK: CLIENT_COMMON_RSP_CLEANUP(rsp, finodelk, i); break; case GF_FOP_ENTRYLK: CLIENT_COMMON_RSP_CLEANUP(rsp, entrylk, i); break; case GF_FOP_FENTRYLK: CLIENT_COMMON_RSP_CLEANUP(rsp, fentrylk, i); break; /* fops that need extra cleanup */ case GF_FOP_LK: { CLIENT_FOP_RSP_CLEANUP(rsp, lk, i); gfs3_lk_rsp *tmp_rsp = &CPD_RSP_FIELD(this_rsp, lk); free(tmp_rsp->flock.lk_owner.lk_owner_val); break; } case GF_FOP_READLINK: { CLIENT_FOP_RSP_CLEANUP(rsp, readlink, i); gfs3_readlink_rsp *tmp_rsp = &CPD_RSP_FIELD(this_rsp, readlink); free(tmp_rsp->path); break; } case GF_FOP_XATTROP: { CLIENT_FOP_RSP_CLEANUP(rsp, xattrop, i); gfs3_xattrop_rsp *tmp_rsp = &CPD_RSP_FIELD(this_rsp, xattrop); free(tmp_rsp->dict.dict_val); break; } case GF_FOP_FXATTROP: { CLIENT_FOP_RSP_CLEANUP(rsp, fxattrop, i); gfs3_fxattrop_rsp *tmp_rsp = &CPD_RSP_FIELD(this_rsp, fxattrop); free(tmp_rsp->dict.dict_val); break; } case GF_FOP_READDIR: { CLIENT_FOP_RSP_CLEANUP(rsp, readdir, i); gfs3_readdir_rsp *tmp_rsp = &CPD_RSP_FIELD(this_rsp, readdir); clnt_readdir_rsp_cleanup(tmp_rsp); break; } case GF_FOP_READDIRP: { CLIENT_FOP_RSP_CLEANUP(rsp, readdirp, i); gfs3_readdirp_rsp *tmp_rsp = &CPD_RSP_FIELD(this_rsp, readdirp); clnt_readdirp_rsp_cleanup(tmp_rsp); break; } case GF_FOP_GETXATTR: { CLIENT_FOP_RSP_CLEANUP(rsp, getxattr, i); gfs3_getxattr_rsp *tmp_rsp = &CPD_RSP_FIELD(this_rsp, getxattr); free(tmp_rsp->dict.dict_val); break; } case GF_FOP_FGETXATTR: { CLIENT_FOP_RSP_CLEANUP(rsp, fgetxattr, i); gfs3_fgetxattr_rsp *tmp_rsp = &CPD_RSP_FIELD(this_rsp, fgetxattr); free(tmp_rsp->dict.dict_val); break; } case GF_FOP_RCHECKSUM: { CLIENT_FOP_RSP_CLEANUP(rsp, rchecksum, i); gfs3_rchecksum_rsp *rck = &CPD_RSP_FIELD(this_rsp, rchecksum); if (rck->strong_checksum.strong_checksum_val) { free(rck->strong_checksum.strong_checksum_val); } break; } default: break; } } return; } /* compound v2 */ int client_handle_fop_requirements_v2( xlator_t *this, call_frame_t *frame, gfx_compound_req *req, clnt_local_t *local, struct iobref **req_iobref, struct iobref **rsp_iobref, struct iovec *req_vector, struct iovec *rsp_vector, int *req_count, int *rsp_count, default_args_t *args, int fop_enum, int index) { int ret = 0; int op_errno = ENOMEM; struct iobuf *rsp_iobuf = NULL; int64_t remote_fd = -1; compound_req_v2 *this_req = &req->compound_req_array .compound_req_array_val[index]; this_req->fop_enum = fop_enum; switch (fop_enum) { case GF_FOP_STAT: CLIENT4_PRE_FOP(stat, this, &this_req->compound_req_v2_u.compound_stat_req, op_errno, out, &args->loc, args->xdata); break; case GF_FOP_READLINK: CLIENT4_PRE_FOP(readlink, this, &this_req->compound_req_v2_u.compound_readlink_req, op_errno, out, &args->loc, args->size, args->xdata); break; case GF_FOP_MKNOD: CLIENT4_PRE_FOP(mknod, this, &this_req->compound_req_v2_u.compound_mknod_req, op_errno, out, &args->loc, args->mode, args->rdev, args->umask, args->xdata); loc_copy(&local->loc, &args->loc); loc_path(&local->loc, NULL); break; case GF_FOP_MKDIR: CLIENT4_PRE_FOP(mkdir, this, &this_req->compound_req_v2_u.compound_mkdir_req, op_errno, out, &args->loc, args->mode, args->umask, args->xdata); loc_copy(&local->loc, &args->loc); loc_path(&local->loc, NULL); break; case GF_FOP_UNLINK: CLIENT4_PRE_FOP( unlink, this, &this_req->compound_req_v2_u.compound_unlink_req, op_errno, out, &args->loc, args->xflag, args->xdata); break; case GF_FOP_RMDIR: CLIENT4_PRE_FOP( rmdir, this, &this_req->compound_req_v2_u.compound_rmdir_req, op_errno, out, &args->loc, args->flags, args->xdata); break; case GF_FOP_SYMLINK: CLIENT4_PRE_FOP(symlink, this, &this_req->compound_req_v2_u.compound_symlink_req, op_errno, out, &args->loc, args->linkname, args->umask, args->xdata); loc_copy(&local->loc, &args->loc); loc_path(&local->loc, NULL); break; case GF_FOP_RENAME: CLIENT4_PRE_FOP( rename, this, &this_req->compound_req_v2_u.compound_rename_req, op_errno, out, &args->loc, &args->loc2, args->xdata); break; case GF_FOP_LINK: CLIENT4_PRE_FOP( link, this, &this_req->compound_req_v2_u.compound_link_req, op_errno, out, &args->loc, &args->loc2, args->xdata); break; case GF_FOP_TRUNCATE: CLIENT4_PRE_FOP(truncate, this, &this_req->compound_req_v2_u.compound_truncate_req, op_errno, out, &args->loc, args->offset, args->xdata); break; case GF_FOP_OPEN: CLIENT4_PRE_FOP( open, this, &this_req->compound_req_v2_u.compound_open_req, op_errno, out, &args->loc, args->fd, args->flags, args->xdata); if (!local->fd) local->fd = fd_ref(args->fd); break; case GF_FOP_READ: op_errno = client_pre_readv_v2( this, &this_req->compound_req_v2_u.compound_read_req, args->fd, args->size, args->offset, args->flags, args->xdata); if (op_errno) { op_errno = -op_errno; goto out; } if (!local->fd) local->fd = fd_ref(args->fd); local->attempt_reopen = client_is_reopen_needed(args->fd, this, remote_fd); rsp_iobuf = iobuf_get2(this->ctx->iobuf_pool, args->size); if (rsp_iobuf == NULL) { op_errno = ENOMEM; goto out; } if (!*rsp_iobref) { *rsp_iobref = iobref_new(); if (*rsp_iobref == NULL) { op_errno = ENOMEM; goto out; } } if (*rsp_count + 1 >= MAX_IOVEC) { op_errno = ENOMEM; goto out; } rsp_vector[*rsp_count].iov_base = iobuf_ptr(rsp_iobuf); rsp_vector[*rsp_count].iov_len = iobuf_pagesize(rsp_iobuf); iobref_add(*rsp_iobref, rsp_iobuf); iobuf_unref(rsp_iobuf); rsp_iobuf = NULL; if (args->size > rsp_vector[*rsp_count].iov_len) { gf_msg(this->name, GF_LOG_WARNING, ENOMEM, PC_MSG_NO_MEMORY, "read-size (%lu) is bigger than iobuf size " "(%lu)", (unsigned long)args->size, (unsigned long)rsp_vector[*rsp_count].iov_len); op_errno = EINVAL; goto out; } *rsp_count += 1; break; case GF_FOP_WRITE: op_errno = client_pre_writev_v2( this, &this_req->compound_req_v2_u.compound_write_req, args->fd, iov_length(args->vector, args->count), args->offset, args->flags, &args->xdata); if (op_errno) { op_errno = -op_errno; goto out; } if (!local->fd) local->fd = fd_ref(args->fd); local->attempt_reopen = client_is_reopen_needed(args->fd, this, remote_fd); if (*req_count + args->count >= MAX_IOVEC) { op_errno = ENOMEM; goto out; } memcpy(&req_vector[*req_count], args->vector, (args->count * sizeof(req_vector[0]))); *req_count += args->count; if (!*req_iobref) *req_iobref = args->iobref; else if (iobref_merge(*req_iobref, args->iobref)) goto out; break; case GF_FOP_STATFS: CLIENT4_PRE_FOP(statfs, this, &this_req->compound_req_v2_u.compound_statfs_req, op_errno, out, &args->loc, args->xdata); break; case GF_FOP_FLUSH: CLIENT4_PRE_FOP(flush, this, &this_req->compound_req_v2_u.compound_flush_req, op_errno, out, args->fd, args->xdata); if (!local->fd) local->fd = fd_ref(args->fd); local->owner = frame->root->lk_owner; break; case GF_FOP_FSYNC: CLIENT4_PRE_FOP( fsync, this, &this_req->compound_req_v2_u.compound_fsync_req, op_errno, out, args->fd, args->datasync, args->xdata); break; case GF_FOP_SETXATTR: CLIENT4_PRE_FOP(setxattr, this, &this_req->compound_req_v2_u.compound_setxattr_req, op_errno, out, &args->loc, args->xattr, args->flags, args->xdata); break; case GF_FOP_GETXATTR: CLIENT4_PRE_FOP(getxattr, this, &this_req->compound_req_v2_u.compound_getxattr_req, op_errno, out, &args->loc, args->name, args->xdata); loc_copy(&local->loc, &args->loc); loc_path(&local->loc, NULL); break; case GF_FOP_REMOVEXATTR: CLIENT4_PRE_FOP( removexattr, this, &this_req->compound_req_v2_u.compound_removexattr_req, op_errno, out, &args->loc, args->name, args->xdata); break; case GF_FOP_OPENDIR: CLIENT4_PRE_FOP(opendir, this, &this_req->compound_req_v2_u.compound_opendir_req, op_errno, out, &args->loc, args->fd, args->xdata); if (!local->fd) local->fd = fd_ref(args->fd); loc_copy(&local->loc, &args->loc); loc_path(&local->loc, NULL); break; case GF_FOP_FSYNCDIR: CLIENT4_PRE_FOP(fsyncdir, this, &this_req->compound_req_v2_u.compound_fsyncdir_req, op_errno, out, args->fd, args->datasync, args->xdata); break; case GF_FOP_ACCESS: CLIENT4_PRE_FOP(access, this, &this_req->compound_req_v2_u.compound_access_req, op_errno, out, &args->loc, args->mask, args->xdata); break; case GF_FOP_CREATE: CLIENT4_PRE_FOP(create, this, &this_req->compound_req_v2_u.compound_create_req, op_errno, out, &args->loc, args->fd, args->mode, args->flags, args->umask, args->xdata); if (!local->fd) local->fd = fd_ref(args->fd); loc_copy(&local->loc, &args->loc); loc_path(&local->loc, NULL); break; case GF_FOP_FTRUNCATE: CLIENT4_PRE_FOP(ftruncate, this, &this_req->compound_req_v2_u.compound_ftruncate_req, op_errno, out, args->fd, args->offset, args->xdata); break; case GF_FOP_FSTAT: CLIENT4_PRE_FOP(fstat, this, &this_req->compound_req_v2_u.compound_fstat_req, op_errno, out, args->fd, args->xdata); break; case GF_FOP_LK: CLIENT4_PRE_FOP( lk, this, &this_req->compound_req_v2_u.compound_lk_req, op_errno, out, args->cmd, &args->lock, args->fd, args->xdata); if (!local->fd) local->fd = fd_ref(args->fd); local->owner = frame->root->lk_owner; break; case GF_FOP_LOOKUP: CLIENT4_PRE_FOP(lookup, this, &this_req->compound_req_v2_u.compound_lookup_req, op_errno, out, &args->loc, args->xdata); loc_copy(&local->loc, &args->loc); loc_path(&local->loc, NULL); break; case GF_FOP_READDIR: CLIENT4_PRE_FOP(readdir, this, &this_req->compound_req_v2_u.compound_readdir_req, op_errno, out, args->fd, args->size, args->offset, args->xdata); break; case GF_FOP_INODELK: CLIENT4_PRE_FOP(inodelk, this, &this_req->compound_req_v2_u.compound_inodelk_req, op_errno, out, &args->loc, args->cmd, &args->lock, args->volume, args->xdata); break; case GF_FOP_FINODELK: CLIENT4_PRE_FOP(finodelk, this, &this_req->compound_req_v2_u.compound_finodelk_req, op_errno, out, args->fd, args->cmd, &args->lock, args->volume, args->xdata); if (!local->fd) local->fd = fd_ref(args->fd); local->attempt_reopen = client_is_reopen_needed(args->fd, this, remote_fd); break; case GF_FOP_ENTRYLK: CLIENT4_PRE_FOP(entrylk, this, &this_req->compound_req_v2_u.compound_entrylk_req, op_errno, out, &args->loc, args->entrylkcmd, args->entrylktype, args->volume, args->name, args->xdata); break; case GF_FOP_FENTRYLK: CLIENT4_PRE_FOP(fentrylk, this, &this_req->compound_req_v2_u.compound_fentrylk_req, op_errno, out, args->fd, args->entrylkcmd, args->entrylktype, args->volume, args->name, args->xdata); break; case GF_FOP_XATTROP: CLIENT4_PRE_FOP(xattrop, this, &this_req->compound_req_v2_u.compound_xattrop_req, op_errno, out, &args->loc, args->xattr, args->optype, args->xdata); break; case GF_FOP_FXATTROP: CLIENT4_PRE_FOP(fxattrop, this, &this_req->compound_req_v2_u.compound_fxattrop_req, op_errno, out, args->fd, args->xattr, args->optype, args->xdata); if (!local->fd) local->fd = fd_ref(args->fd); local->attempt_reopen = client_is_reopen_needed(args->fd, this, remote_fd); break; case GF_FOP_FGETXATTR: CLIENT4_PRE_FOP(fgetxattr, this, &this_req->compound_req_v2_u.compound_fgetxattr_req, op_errno, out, args->fd, args->name, args->xdata); break; case GF_FOP_FSETXATTR: CLIENT4_PRE_FOP(fsetxattr, this, &this_req->compound_req_v2_u.compound_fsetxattr_req, op_errno, out, args->fd, args->flags, args->xattr, args->xdata); break; case GF_FOP_RCHECKSUM: CLIENT4_PRE_FOP(rchecksum, this, &this_req->compound_req_v2_u.compound_rchecksum_req, op_errno, out, args->fd, args->size, args->offset, args->xdata); break; case GF_FOP_SETATTR: CLIENT4_PRE_FOP(setattr, this, &this_req->compound_req_v2_u.compound_setattr_req, op_errno, out, &args->loc, args->valid, &args->stat, args->xdata); break; case GF_FOP_FSETATTR: CLIENT4_PRE_FOP(fsetattr, this, &this_req->compound_req_v2_u.compound_fsetattr_req, op_errno, out, args->fd, args->valid, &args->stat, args->xdata); break; case GF_FOP_READDIRP: CLIENT4_PRE_FOP(readdirp, this, &this_req->compound_req_v2_u.compound_readdirp_req, op_errno, out, args->fd, args->size, args->offset, args->xdata); if (!local->fd) local->fd = fd_ref(args->fd); break; case GF_FOP_FREMOVEXATTR: CLIENT4_PRE_FOP( fremovexattr, this, &this_req->compound_req_v2_u.compound_fremovexattr_req, op_errno, out, args->fd, args->name, args->xdata); break; case GF_FOP_FALLOCATE: CLIENT4_PRE_FOP(fallocate, this, &this_req->compound_req_v2_u.compound_fallocate_req, op_errno, out, args->fd, args->flags, args->offset, args->size, args->xdata); break; case GF_FOP_DISCARD: CLIENT4_PRE_FOP(discard, this, &this_req->compound_req_v2_u.compound_discard_req, op_errno, out, args->fd, args->offset, args->size, args->xdata); break; case GF_FOP_ZEROFILL: CLIENT4_PRE_FOP(zerofill, this, &this_req->compound_req_v2_u.compound_zerofill_req, op_errno, out, args->fd, args->offset, args->size, args->xdata); break; case GF_FOP_IPC: CLIENT4_PRE_FOP(ipc, this, &this_req->compound_req_v2_u.compound_ipc_req, op_errno, out, args->cmd, args->xdata); break; case GF_FOP_SEEK: CLIENT4_PRE_FOP( seek, this, &this_req->compound_req_v2_u.compound_seek_req, op_errno, out, args->fd, args->offset, args->what, args->xdata); break; case GF_FOP_LEASE: CLIENT4_PRE_FOP( lease, this, &this_req->compound_req_v2_u.compound_lease_req, op_errno, out, &args->loc, &args->lease, args->xdata); break; case GF_FOP_COPY_FILE_RANGE: /* * Not going to handle the copy_file_range fop in compound * operation. This is because, compound operation is going * to be removed. In fact, AFR one of the heavy consumer of * compound operations has stopped using that. * https://github.com/gluster/glusterfs/issues/414 * Therefore, sending ENOTSUP error for this fop coming as * comound request. Though, there was no need of handling * "case GF_FOP_COPY_FILE_RANGE" technically, this comment * under the label of GF_FOP_COPY_FILE_RANGE will help in * understanding that this fop does not handle the compund * request and why. */ default: return ENOTSUP; } return 0; out: return op_errno; } void compound_request_cleanup_v2(gfx_compound_req *req) { int i = 0; int length = req->compound_req_array.compound_req_array_len; compound_req_v2 *curr_req = NULL; if (!req->compound_req_array.compound_req_array_val) return; for (i = 0; i < length; i++) { curr_req = &req->compound_req_array.compound_req_array_val[i]; switch (curr_req->fop_enum) { case GF_FOP_STAT: CLIENT4_COMPOUND_FOP_CLEANUP(curr_req, stat); break; case GF_FOP_READLINK: CLIENT4_COMPOUND_FOP_CLEANUP(curr_req, readlink); break; case GF_FOP_MKNOD: CLIENT4_COMPOUND_FOP_CLEANUP(curr_req, mknod); break; case GF_FOP_MKDIR: CLIENT4_COMPOUND_FOP_CLEANUP(curr_req, mkdir); break; case GF_FOP_UNLINK: CLIENT4_COMPOUND_FOP_CLEANUP(curr_req, unlink); break; case GF_FOP_RMDIR: CLIENT4_COMPOUND_FOP_CLEANUP(curr_req, rmdir); break; case GF_FOP_SYMLINK: CLIENT4_COMPOUND_FOP_CLEANUP(curr_req, symlink); break; case GF_FOP_RENAME: CLIENT4_COMPOUND_FOP_CLEANUP(curr_req, rename); break; case GF_FOP_LINK: CLIENT4_COMPOUND_FOP_CLEANUP(curr_req, link); break; case GF_FOP_TRUNCATE: CLIENT4_COMPOUND_FOP_CLEANUP(curr_req, truncate); break; case GF_FOP_OPEN: CLIENT4_COMPOUND_FOP_CLEANUP(curr_req, open); break; case GF_FOP_READ: CLIENT4_COMPOUND_FOP_CLEANUP(curr_req, read); break; case GF_FOP_WRITE: CLIENT4_COMPOUND_FOP_CLEANUP(curr_req, write); break; case GF_FOP_STATFS: CLIENT4_COMPOUND_FOP_CLEANUP(curr_req, statfs); break; case GF_FOP_FLUSH: CLIENT4_COMPOUND_FOP_CLEANUP(curr_req, flush); break; case GF_FOP_FSYNC: CLIENT4_COMPOUND_FOP_CLEANUP(curr_req, fsync); break; case GF_FOP_SETXATTR: { gfx_setxattr_req *args = &CPD4_REQ_FIELD(curr_req, setxattr); GF_FREE(args->dict.pairs.pairs_val); CLIENT4_COMPOUND_FOP_CLEANUP(curr_req, setxattr); break; } case GF_FOP_GETXATTR: CLIENT4_COMPOUND_FOP_CLEANUP(curr_req, getxattr); break; case GF_FOP_REMOVEXATTR: CLIENT4_COMPOUND_FOP_CLEANUP(curr_req, removexattr); break; case GF_FOP_OPENDIR: CLIENT4_COMPOUND_FOP_CLEANUP(curr_req, opendir); break; case GF_FOP_FSYNCDIR: CLIENT4_COMPOUND_FOP_CLEANUP(curr_req, fsyncdir); break; case GF_FOP_ACCESS: CLIENT4_COMPOUND_FOP_CLEANUP(curr_req, access); break; case GF_FOP_CREATE: CLIENT4_COMPOUND_FOP_CLEANUP(curr_req, create); break; case GF_FOP_FTRUNCATE: CLIENT4_COMPOUND_FOP_CLEANUP(curr_req, ftruncate); break; case GF_FOP_FSTAT: CLIENT4_COMPOUND_FOP_CLEANUP(curr_req, fstat); break; case GF_FOP_LK: CLIENT4_COMPOUND_FOP_CLEANUP(curr_req, lk); break; case GF_FOP_LOOKUP: CLIENT4_COMPOUND_FOP_CLEANUP(curr_req, lookup); break; case GF_FOP_READDIR: CLIENT4_COMPOUND_FOP_CLEANUP(curr_req, readdir); break; case GF_FOP_INODELK: CLIENT4_COMPOUND_FOP_CLEANUP(curr_req, inodelk); break; case GF_FOP_FINODELK: CLIENT4_COMPOUND_FOP_CLEANUP(curr_req, finodelk); break; case GF_FOP_ENTRYLK: CLIENT4_COMPOUND_FOP_CLEANUP(curr_req, entrylk); break; case GF_FOP_FENTRYLK: CLIENT4_COMPOUND_FOP_CLEANUP(curr_req, fentrylk); break; case GF_FOP_XATTROP: { gfx_xattrop_req *args = &CPD4_REQ_FIELD(curr_req, xattrop); GF_FREE(args->dict.pairs.pairs_val); CLIENT4_COMPOUND_FOP_CLEANUP(curr_req, xattrop); break; } case GF_FOP_FXATTROP: { gfx_fxattrop_req *args = &CPD4_REQ_FIELD(curr_req, fxattrop); GF_FREE(args->dict.pairs.pairs_val); CLIENT4_COMPOUND_FOP_CLEANUP(curr_req, fxattrop); break; } case GF_FOP_FGETXATTR: CLIENT4_COMPOUND_FOP_CLEANUP(curr_req, fgetxattr); break; case GF_FOP_FSETXATTR: { gfx_fsetxattr_req *args = &CPD4_REQ_FIELD(curr_req, fsetxattr); GF_FREE(args->dict.pairs.pairs_val); CLIENT4_COMPOUND_FOP_CLEANUP(curr_req, fsetxattr); break; } case GF_FOP_RCHECKSUM: CLIENT4_COMPOUND_FOP_CLEANUP(curr_req, rchecksum); break; case GF_FOP_SETATTR: CLIENT4_COMPOUND_FOP_CLEANUP(curr_req, setattr); break; case GF_FOP_FSETATTR: CLIENT4_COMPOUND_FOP_CLEANUP(curr_req, fsetattr); break; case GF_FOP_READDIRP: CLIENT4_COMPOUND_FOP_CLEANUP(curr_req, readdirp); break; case GF_FOP_FREMOVEXATTR: CLIENT4_COMPOUND_FOP_CLEANUP(curr_req, fremovexattr); break; case GF_FOP_FALLOCATE: CLIENT4_COMPOUND_FOP_CLEANUP(curr_req, fallocate); break; case GF_FOP_DISCARD: CLIENT4_COMPOUND_FOP_CLEANUP(curr_req, discard); break; case GF_FOP_ZEROFILL: CLIENT4_COMPOUND_FOP_CLEANUP(curr_req, zerofill); break; case GF_FOP_IPC: CLIENT4_COMPOUND_FOP_CLEANUP(curr_req, ipc); break; case GF_FOP_SEEK: CLIENT4_COMPOUND_FOP_CLEANUP(curr_req, seek); break; case GF_FOP_COPY_FILE_RANGE: /* * This fop is not handled in compund operations. * Check the comment added under this fop's section * in the compound_request_cleanup_v2. Therefore * keeping this label only as a placeholder with * a message that, this fop is not handled. */ default: break; } } GF_FREE(req->compound_req_array.compound_req_array_val); return; } void client_compound_rsp_cleanup_v2(gfx_compound_rsp *rsp, int len) { int i = 0; compound_rsp_v2 *this_rsp = NULL; for (i = 0; i < len; i++) { this_rsp = &rsp->compound_rsp_array.compound_rsp_array_val[i]; switch (this_rsp->fop_enum) { /* fops that need extra cleanup */ case GF_FOP_LK: { gfx_lk_rsp *tmp_rsp = &CPD4_RSP_FIELD(this_rsp, lk); free(tmp_rsp->flock.lk_owner.lk_owner_val); break; } case GF_FOP_READLINK: { gfx_readlink_rsp *tmp_rsp = &CPD4_RSP_FIELD(this_rsp, readlink); free(tmp_rsp->path); break; } case GF_FOP_READDIR: { gfx_readdir_rsp *tmp_rsp = &CPD4_RSP_FIELD(this_rsp, readdir); clnt_readdir_rsp_cleanup_v2(tmp_rsp); break; } case GF_FOP_READDIRP: { gfx_readdirp_rsp *tmp_rsp = &CPD4_RSP_FIELD(this_rsp, readdirp); clnt_readdirp_rsp_cleanup_v2(tmp_rsp); break; } case GF_FOP_RCHECKSUM: { gfx_rchecksum_rsp *rck = &CPD4_RSP_FIELD(this_rsp, rchecksum); if (rck->strong_checksum.strong_checksum_val) { free(rck->strong_checksum.strong_checksum_val); } break; } default: break; } } return; } int client_process_response_v2(call_frame_t *frame, xlator_t *this, struct rpc_req *req, gfx_compound_rsp *rsp, compound_args_cbk_t *args_cbk, int index) { int ret = 0; dict_t *xdata = NULL; dict_t *xattr = NULL; struct iovec vector[MAX_IOVEC] = { {0}, }; gf_dirent_t entries; default_args_cbk_t *this_args_cbk = &args_cbk->rsp_list[index]; clnt_local_t *local = frame->local; compound_rsp_v2 *this_rsp = NULL; compound_args_t *args = local->compound_args; this_rsp = &rsp->compound_rsp_array.compound_rsp_array_val[index]; args_cbk->enum_list[index] = this_rsp->fop_enum; INIT_LIST_HEAD(&entries.list); switch (args_cbk->enum_list[index]) { case GF_FOP_STAT: case GF_FOP_FSTAT: { gfx_common_iatt_rsp *tmp_rsp = NULL; tmp_rsp = &this_rsp->compound_rsp_v2_u.compound_stat_rsp; client_post_common_iatt(this, tmp_rsp, &this_args_cbk->stat, &xdata); CLIENT4_POST_FOP_TYPE(stat, common_iatt, this_rsp, this_args_cbk, &this_args_cbk->stat, xdata); break; } case GF_FOP_READLINK: { gfx_readlink_rsp *tmp_rsp = NULL; tmp_rsp = &this_rsp->compound_rsp_v2_u.compound_readlink_rsp; gfx_stat_to_iattx(&tmp_rsp->buf, &this_args_cbk->stat); xdr_to_dict(&tmp_rsp->xdata, &xdata); CLIENT4_POST_FOP_TYPE(readlink, readlink, this_rsp, this_args_cbk, tmp_rsp->path, &this_args_cbk->stat, xdata); break; } case GF_FOP_MKDIR: case GF_FOP_MKNOD: case GF_FOP_SYMLINK: case GF_FOP_LINK: { gfx_common_3iatt_rsp *tmp_rsp = NULL; tmp_rsp = &this_rsp->compound_rsp_v2_u.compound_mknod_rsp; client_post_common_3iatt(this, tmp_rsp, &this_args_cbk->stat, &this_args_cbk->preparent, &this_args_cbk->postparent, &xdata); CLIENT4_POST_FOP_TYPE(mknod, common_3iatt, this_rsp, this_args_cbk, local->loc.inode, &this_args_cbk->stat, &this_args_cbk->preparent, &this_args_cbk->postparent, xdata); break; } case GF_FOP_UNLINK: case GF_FOP_RMDIR: { gfx_common_2iatt_rsp *tmp_rsp = NULL; tmp_rsp = &this_rsp->compound_rsp_v2_u.compound_unlink_rsp; client_post_common_2iatt(this, tmp_rsp, &this_args_cbk->preparent, &this_args_cbk->postparent, &xdata); CLIENT4_POST_FOP_TYPE(unlink, common_2iatt, this_rsp, this_args_cbk, &this_args_cbk->preparent, &this_args_cbk->postparent, xdata); break; } case GF_FOP_RENAME: { gfx_rename_rsp *tmp_rsp = NULL; tmp_rsp = &this_rsp->compound_rsp_v2_u.compound_rename_rsp; client_post_rename_v2( this, tmp_rsp, &this_args_cbk->stat, &this_args_cbk->preparent, &this_args_cbk->postparent, &this_args_cbk->preparent2, &this_args_cbk->postparent2, &xdata); CLIENT4_POST_FOP_TYPE( rename, rename, this_rsp, this_args_cbk, &this_args_cbk->stat, &this_args_cbk->preparent, &this_args_cbk->postparent, &this_args_cbk->preparent2, &this_args_cbk->postparent2, xdata); break; } case GF_FOP_WRITE: case GF_FOP_TRUNCATE: case GF_FOP_FTRUNCATE: case GF_FOP_FSYNC: case GF_FOP_ZEROFILL: case GF_FOP_DISCARD: case GF_FOP_FALLOCATE: case GF_FOP_FSETATTR: case GF_FOP_SETATTR: { gfx_common_2iatt_rsp *tmp_rsp = NULL; tmp_rsp = &this_rsp->compound_rsp_v2_u.compound_truncate_rsp; client_post_common_2iatt(this, tmp_rsp, &this_args_cbk->prestat, &this_args_cbk->poststat, &xdata); CLIENT4_POST_FOP_TYPE(truncate, common_2iatt, this_rsp, this_args_cbk, &this_args_cbk->prestat, &this_args_cbk->poststat, xdata); break; } case GF_FOP_OPEN: { gfx_open_rsp *tmp_rsp = NULL; tmp_rsp = &this_rsp->compound_rsp_v2_u.compound_open_rsp; xdr_to_dict(&tmp_rsp->xdata, &xdata); CLIENT4_POST_FOP_TYPE(open, open, this_rsp, this_args_cbk, local->fd, xdata); if (-1 != this_args_cbk->op_ret) ret = client_add_fd_to_saved_fds(this, local->fd, &local->loc, args->req_list[index].flags, tmp_rsp->fd, 0); break; } case GF_FOP_READ: { gfx_read_rsp *tmp_rsp = NULL; tmp_rsp = &this_rsp->compound_rsp_v2_u.compound_read_rsp; client_post_readv_v2(this, tmp_rsp, &this_args_cbk->iobref, req->rsp_iobref, &this_args_cbk->stat, vector, &req->rsp[1], &this_args_cbk->count, &xdata); /* Each read should be given read response that only * corresponds to its request. * Modify the iovecs accordingly. * After each read, store the length of data already read * so that the next ones can continue from there. */ if (local->read_length) { vector[0].iov_base += local->read_length; local->read_length += tmp_rsp->op_ret; } else { local->read_length = tmp_rsp->op_ret; } args_readv_cbk_store(this_args_cbk, tmp_rsp->op_ret, gf_error_to_errno(tmp_rsp->op_errno), vector, this_args_cbk->count, &this_args_cbk->stat, this_args_cbk->iobref, xdata); if (tmp_rsp->op_ret >= 0) if (local->attempt_reopen) client_attempt_reopen(local->fd, this); break; } case GF_FOP_STATFS: { gfx_statfs_rsp *tmp_rsp = NULL; tmp_rsp = &this_rsp->compound_rsp_v2_u.compound_statfs_rsp; gf_statfs_to_statfs(&tmp_rsp->statfs, &this_args_cbk->statvfs); xdr_to_dict(&tmp_rsp->xdata, &xdata); CLIENT4_POST_FOP_TYPE(statfs, statfs, this_rsp, this_args_cbk, &this_args_cbk->statvfs, xdata); break; } case GF_FOP_FLUSH: { gfx_common_rsp *tmp_rsp = NULL; tmp_rsp = &this_rsp->compound_rsp_v2_u.compound_flush_rsp; xdr_to_dict(&tmp_rsp->xdata, &xdata); CLIENT4_POST_FOP(flush, this_rsp, this_args_cbk, xdata); if (this_args_cbk->op_ret >= 0 && !fd_is_anonymous(local->fd)) { /* Delete all saved locks of the owner issuing flush */ ret = delete_granted_locks_owner(local->fd, &local->owner); gf_msg_trace(this->name, 0, "deleting locks of owner (%s) returned %d", lkowner_utoa(&local->owner), ret); } break; } case GF_FOP_FSYNCDIR: case GF_FOP_ACCESS: case GF_FOP_REMOVEXATTR: case GF_FOP_FREMOVEXATTR: case GF_FOP_FSETXATTR: case GF_FOP_SETXATTR: case GF_FOP_INODELK: case GF_FOP_FINODELK: case GF_FOP_ENTRYLK: case GF_FOP_FENTRYLK: case GF_FOP_IPC: { gfx_common_rsp *tmp_rsp = NULL; tmp_rsp = &this_rsp->compound_rsp_v2_u.compound_setxattr_rsp; xdr_to_dict(&tmp_rsp->xdata, &xdata); CLIENT4_POST_FOP(setxattr, this_rsp, this_args_cbk, xdata); break; } case GF_FOP_GETXATTR: case GF_FOP_FGETXATTR: case GF_FOP_XATTROP: case GF_FOP_FXATTROP: { gfx_common_dict_rsp *tmp_rsp = NULL; tmp_rsp = &this_rsp->compound_rsp_v2_u.compound_getxattr_rsp; ret = client_post_common_dict(this, tmp_rsp, &xattr, &xdata); if (ret) { tmp_rsp->op_errno = -ret; goto out; } CLIENT4_POST_FOP_TYPE(getxattr, common_dict, this_rsp, this_args_cbk, xattr, xdata); break; } case GF_FOP_OPENDIR: { gfx_open_rsp *tmp_rsp = NULL; tmp_rsp = &this_rsp->compound_rsp_v2_u.compound_opendir_rsp; xdr_to_dict(&tmp_rsp->xdata, &xdata); CLIENT4_POST_FOP_TYPE(opendir, open, this_rsp, this_args_cbk, local->fd, xdata); if (-1 != this_args_cbk->op_ret) ret = client_add_fd_to_saved_fds(this, local->fd, &local->loc, args->req_list[index].flags, tmp_rsp->fd, 0); break; } case GF_FOP_CREATE: { gfx_create_rsp *tmp_rsp = NULL; tmp_rsp = &this_rsp->compound_rsp_v2_u.compound_create_rsp; client_post_create_v2(this, tmp_rsp, &this_args_cbk->stat, &this_args_cbk->preparent, &this_args_cbk->postparent, local, &xdata); CLIENT4_POST_FOP_TYPE( create, create, this_rsp, this_args_cbk, local->fd, local->loc.inode, &this_args_cbk->stat, &this_args_cbk->preparent, &this_args_cbk->postparent, xdata); if (-1 != this_args_cbk->op_ret) ret = client_add_fd_to_saved_fds(this, local->fd, &local->loc, args->req_list[index].flags, tmp_rsp->fd, 0); break; } case GF_FOP_LK: { gfx_lk_rsp *tmp_rsp = NULL; tmp_rsp = &this_rsp->compound_rsp_v2_u.compound_lk_rsp; client_post_lk_v2(this, tmp_rsp, &this_args_cbk->lock, &xdata); CLIENT4_POST_FOP_TYPE(lk, lk, this_rsp, this_args_cbk, &this_args_cbk->lock, xdata); break; } case GF_FOP_LOOKUP: { gfx_common_2iatt_rsp *tmp_rsp = NULL; tmp_rsp = &this_rsp->compound_rsp_v2_u.compound_lookup_rsp; client_post_common_2iatt(this, tmp_rsp, &this_args_cbk->stat, &this_args_cbk->postparent, &xdata); CLIENT4_POST_FOP_TYPE(lookup, common_2iatt, this_rsp, this_args_cbk, local->loc.inode, &this_args_cbk->stat, xdata, &this_args_cbk->postparent); break; } case GF_FOP_READDIR: { gfx_readdir_rsp *tmp_rsp = NULL; tmp_rsp = &this_rsp->compound_rsp_v2_u.compound_readdir_rsp; client_post_readdir_v2(this, tmp_rsp, &entries, &xdata); CLIENT4_POST_FOP_TYPE(readdir, readdir, this_rsp, this_args_cbk, &entries, xdata); break; } case GF_FOP_RCHECKSUM: { gfx_rchecksum_rsp *tmp_rsp = NULL; tmp_rsp = &this_rsp->compound_rsp_v2_u.compound_rchecksum_rsp; xdr_to_dict(&tmp_rsp->xdata, &xdata); CLIENT4_POST_FOP_TYPE( rchecksum, rchecksum, this_rsp, this_args_cbk, tmp_rsp->weak_checksum, (uint8_t *)tmp_rsp->strong_checksum.strong_checksum_val, xdata); break; } case GF_FOP_READDIRP: { gfx_readdirp_rsp *tmp_rsp = NULL; tmp_rsp = &this_rsp->compound_rsp_v2_u.compound_readdirp_rsp; client_post_readdirp_v2(this, tmp_rsp, local->fd, &entries, &xdata); CLIENT4_POST_FOP_TYPE(readdirp, readdirp, this_rsp, this_args_cbk, &entries, xdata); break; } case GF_FOP_SEEK: { gfx_seek_rsp *tmp_rsp = NULL; tmp_rsp = &this_rsp->compound_rsp_v2_u.compound_seek_rsp; xdr_to_dict(&tmp_rsp->xdata, &xdata); CLIENT4_POST_FOP_TYPE(seek, seek, this_rsp, this_args_cbk, tmp_rsp->offset, xdata); break; } case GF_FOP_LEASE: { gfx_lease_rsp *tmp_rsp = NULL; tmp_rsp = &this_rsp->compound_rsp_v2_u.compound_lease_rsp; client_post_lease_v2(this, tmp_rsp, &this_args_cbk->lease, &xdata); CLIENT4_POST_FOP_TYPE(lease, lease, this_rsp, this_args_cbk, &this_args_cbk->lease, xdata); break; } case GF_FOP_COPY_FILE_RANGE: /* * Not handling this fop. Returning ENOTSUP. Check * the comment added for this fop in the function * client_handle_fop_requirements_v2. */ default: return -ENOTSUP; } out: if (xdata) dict_unref(xdata); if (xattr) dict_unref(xattr); gf_dirent_free(&entries); return 0; } extern int client3_3_releasedir_cbk(struct rpc_req *req, struct iovec *iov, int count, void *myframe); extern int client3_3_release_cbk(struct rpc_req *req, struct iovec *iov, int count, void *myframe); extern int client4_0_releasedir_cbk(struct rpc_req *req, struct iovec *iov, int count, void *myframe); extern int client4_0_release_cbk(struct rpc_req *req, struct iovec *iov, int count, void *myframe); static int send_release4_0_over_wire(xlator_t *this, clnt_fd_ctx_t *fdctx, call_frame_t *fr) { clnt_conf_t *conf = NULL; conf = (clnt_conf_t *)this->private; if (fdctx->is_dir) { gfx_releasedir_req req = { { 0, }, }; memcpy(req.gfid, fdctx->gfid, 16); req.fd = fdctx->remote_fd; gf_msg_trace(this->name, 0, "sending releasedir on fd"); (void)client_submit_request( this, &req, fr, conf->fops, GFS3_OP_RELEASEDIR, client4_0_releasedir_cbk, NULL, (xdrproc_t)xdr_gfx_releasedir_req); } else { gfx_release_req req = { { 0, }, }; memcpy(req.gfid, fdctx->gfid, 16); req.fd = fdctx->remote_fd; gf_msg_trace(this->name, 0, "sending release on fd"); (void)client_submit_request(this, &req, fr, conf->fops, GFS3_OP_RELEASE, client4_0_release_cbk, NULL, (xdrproc_t)xdr_gfx_release_req); } return 0; } static int send_release3_3_over_wire(xlator_t *this, clnt_fd_ctx_t *fdctx, call_frame_t *fr) { clnt_conf_t *conf = NULL; conf = (clnt_conf_t *)this->private; if (fdctx->is_dir) { gfs3_releasedir_req req = { { 0, }, }; memcpy(req.gfid, fdctx->gfid, 16); req.fd = fdctx->remote_fd; gf_msg_trace(this->name, 0, "sending releasedir on fd"); (void)client_submit_request( this, &req, fr, conf->fops, GFS3_OP_RELEASEDIR, client3_3_releasedir_cbk, NULL, (xdrproc_t)xdr_gfs3_releasedir_req); } else { gfs3_release_req req = { { 0, }, }; memcpy(req.gfid, fdctx->gfid, 16); req.fd = fdctx->remote_fd; gf_msg_trace(this->name, 0, "sending release on fd"); (void)client_submit_request(this, &req, fr, conf->fops, GFS3_OP_RELEASE, client3_3_release_cbk, NULL, (xdrproc_t)xdr_gfs3_release_req); } return 0; } int client_fdctx_destroy(xlator_t *this, clnt_fd_ctx_t *fdctx) { clnt_conf_t *conf = NULL; call_frame_t *fr = NULL; int32_t ret = -1; char parent_down = 0; fd_lk_ctx_t *lk_ctx = NULL; GF_VALIDATE_OR_GOTO("client", this, out); GF_VALIDATE_OR_GOTO(this->name, fdctx, out); conf = (clnt_conf_t *)this->private; if (fdctx->remote_fd == -1) { gf_msg_debug(this->name, 0, "not a valid fd"); goto out; } pthread_mutex_lock(&conf->lock); { parent_down = conf->parent_down; } pthread_mutex_unlock(&conf->lock); lk_ctx = fdctx->lk_ctx; fdctx->lk_ctx = NULL; if (lk_ctx) fd_lk_ctx_unref(lk_ctx); if (!parent_down) rpc_clnt_ref(conf->rpc); else goto out; fr = create_frame(this, this->ctx->pool); if (fr == NULL) { goto out; } ret = 0; if (conf->fops->progver == GLUSTER_FOP_VERSION) send_release3_3_over_wire(this, fdctx, fr); else send_release4_0_over_wire(this, fdctx, fr); rpc_clnt_unref(conf->rpc); out: if (fdctx) { fdctx->remote_fd = -1; GF_FREE(fdctx); } return ret; }