diff options
| author | Amar Tumballi <amarts@redhat.com> | 2017-12-22 13:12:42 +0530 |
|---|---|---|
| committer | Amar Tumballi <amarts@redhat.com> | 2018-01-19 22:48:39 +0530 |
| commit | 303cc2b54797bc5371be742543ccb289010c92f2 (patch) | |
| tree | cf383488d0edff81b012b5e908f8ebca7affaea3 /xlators/protocol/server/src/server-common.c | |
| parent | 9eefff096fd9b54120e4347b6b00f10a6c502cf4 (diff) | |
protocol: make on-wire-change of protocol using new XDR definition.
With this patchset, some major things are changed in XDR, mainly:
* Naming: Instead of gfs3/gfs4 settle for gfx_ for xdr structures
* add iattx as a separate structure, and add conversion methods
* the *_rsp structure is now changed, and is also reduced in number
(ie, no need for different strucutes if it is similar to other response).
* use proper XDR methods for sending dict on wire.
Also, with the change of xdr structure, there are changes needed
outside of xlator protocol layer to handle these properly. Mainly
because the abstraction was broken to support 0-copy RDMA with payload
for write and read FOP. This made transport layer know about the xdr
payload, hence with the change of xdr payload structure, transport layer
needed to know about the change.
Updates #384
Change-Id: I1448fbe9deab0a1b06cb8351f2f37488cefe461f
Signed-off-by: Amar Tumballi <amarts@redhat.com>
Diffstat (limited to 'xlators/protocol/server/src/server-common.c')
| -rw-r--r-- | xlators/protocol/server/src/server-common.c | 374 |
1 files changed, 370 insertions, 4 deletions
diff --git a/xlators/protocol/server/src/server-common.c b/xlators/protocol/server/src/server-common.c index 9c38706dbcb..17660ef475e 100644 --- a/xlators/protocol/server/src/server-common.c +++ b/xlators/protocol/server/src/server-common.c @@ -5,6 +5,7 @@ #include "glusterfs3.h" #include "compat-errno.h" #include "server-messages.h" +#include "server-helpers.h" #include "defaults.h" #include "fd.h" #include "xdr-nfs3.h" @@ -229,9 +230,9 @@ server_post_lk (xlator_t *this, gfs3_lk_rsp *rsp, struct gf_flock *lock) int server_post_readdir (gfs3_readdir_rsp *rsp, gf_dirent_t *entries) { - int ret = 0; + int ret = 0; - ret = serialize_rsp_dirent (entries, rsp); + ret = serialize_rsp_dirent (entries, rsp); return ret; } @@ -268,9 +269,9 @@ server_post_seek (gfs3_seek_rsp *rsp, off_t offset) int server_post_readdirp (gfs3_readdirp_rsp *rsp, gf_dirent_t *entries) { - int ret = 0; + int ret = 0; - ret = serialize_rsp_direntp (entries, rsp); + ret = serialize_rsp_direntp (entries, rsp); return ret; } @@ -512,3 +513,368 @@ server_post_lease (gfs3_lease_rsp *rsp, struct gf_lease *lease) { gf_proto_lease_from_lease (&rsp->lease, lease); } + + +/* Version 4 helpers */ + +void +server4_post_readlink (gfx_readlink_rsp *rsp, struct iatt *stbuf, + const char *buf) +{ + gfx_stat_from_iattx (&rsp->buf, stbuf); + rsp->path = (char *)buf; +} + +void +server4_post_common_3iatt (server_state_t *state, gfx_common_3iatt_rsp *rsp, + inode_t *inode, struct iatt *stbuf, + struct iatt *preparent, struct iatt *postparent) +{ + inode_t *link_inode = NULL; + + gfx_stat_from_iattx (&rsp->stat, stbuf); + if (state->client->subdir_mount && + !gf_uuid_compare (preparent->ia_gfid, + state->client->subdir_gfid)) { + /* This is very important as when we send iatt of + root-inode, fuse/client expect the gfid to be 1, + along with inode number. As for subdirectory mount, + we use inode table which is shared by everyone, but + make sure we send fops only from subdir and below, + we have to alter inode gfid and send it to client */ + uuid_t gfid = {0,}; + + gfid[15] = 1; + preparent->ia_ino = 1; + postparent->ia_ino = 1; + gf_uuid_copy (preparent->ia_gfid, gfid); + gf_uuid_copy (postparent->ia_gfid, gfid); + } + + gfx_stat_from_iattx (&rsp->preparent, preparent); + gfx_stat_from_iattx (&rsp->postparent, postparent); + + link_inode = inode_link (inode, state->loc.parent, + state->loc.name, stbuf); + inode_lookup (link_inode); + inode_unref (link_inode); +} + +void +server4_post_common_2iatt (gfx_common_2iatt_rsp *rsp, struct iatt *prebuf, + struct iatt *postbuf) +{ + gfx_stat_from_iattx (&rsp->prestat, prebuf); + gfx_stat_from_iattx (&rsp->poststat, postbuf); +} + +void +server4_post_entry_remove (server_state_t *state, gfx_common_2iatt_rsp *rsp, + struct iatt *prebuf, struct iatt *postbuf) +{ + inode_unlink (state->loc.inode, state->loc.parent, + state->loc.name); + /* parent should not be found for directories after + * inode_unlink, since directories cannot have + * hardlinks. + */ + forget_inode_if_no_dentry (state->loc.inode); + + gfx_stat_from_iattx (&rsp->prestat, prebuf); + gfx_stat_from_iattx (&rsp->poststat, postbuf); +} + + +void +server4_post_statfs (gfx_statfs_rsp *rsp, struct statvfs *stbuf) +{ + gf_statfs_from_statfs (&rsp->statfs, stbuf); +} + +void +server4_post_common_iatt (server_state_t *state, gfx_common_iatt_rsp *rsp, + struct iatt *stbuf) +{ + if (state->client->subdir_mount && + !gf_uuid_compare (stbuf->ia_gfid, + state->client->subdir_gfid)) { + /* This is very important as when we send iatt of + root-inode, fuse/client expect the gfid to be 1, + along with inode number. As for subdirectory mount, + we use inode table which is shared by everyone, but + make sure we send fops only from subdir and below, + we have to alter inode gfid and send it to client */ + uuid_t gfid = {0,}; + + gfid[15] = 1; + stbuf->ia_ino = 1; + gf_uuid_copy (stbuf->ia_gfid, gfid); + } + + gfx_stat_from_iattx (&rsp->stat, stbuf); +} + +void +server4_post_lk (xlator_t *this, gfx_lk_rsp *rsp, struct gf_flock *lock) +{ + switch (lock->l_type) { + case F_RDLCK: + lock->l_type = GF_LK_F_RDLCK; + break; + case F_WRLCK: + lock->l_type = GF_LK_F_WRLCK; + break; + case F_UNLCK: + lock->l_type = GF_LK_F_UNLCK; + break; + default: + gf_msg (this->name, GF_LOG_ERROR, 0, PS_MSG_LOCK_ERROR, + "Unknown lock type: %"PRId32"!", lock->l_type); + break; + } + + gf_proto_flock_from_flock (&rsp->flock, lock); +} + +int +server4_post_readdir (gfx_readdir_rsp *rsp, gf_dirent_t *entries) +{ + int ret = 0; + + ret = serialize_rsp_dirent_v2 (entries, rsp); + + return ret; +} + +void +server4_post_seek (gfx_seek_rsp *rsp, off_t offset) +{ + rsp->offset = offset; +} + +int +server4_post_readdirp (gfx_readdirp_rsp *rsp, gf_dirent_t *entries) +{ + int ret = 0; + + ret = serialize_rsp_direntp_v2 (entries, rsp); + + return ret; +} + +void +server4_post_rchecksum (gfx_rchecksum_rsp *rsp, uint32_t weak_checksum, + uint8_t *strong_checksum) +{ + rsp->weak_checksum = weak_checksum; + + rsp->strong_checksum.strong_checksum_val = (char *)strong_checksum; + rsp->strong_checksum.strong_checksum_len = SHA256_DIGEST_LENGTH; + +} + +void +server4_post_rename (call_frame_t *frame, + server_state_t *state, gfx_rename_rsp *rsp, + struct iatt *stbuf, + struct iatt *preoldparent, + struct iatt *postoldparent, + struct iatt *prenewparent, + struct iatt *postnewparent) +{ + inode_t *tmp_inode = NULL; + + stbuf->ia_type = state->loc.inode->ia_type; + + /* TODO: log gfid of the inodes */ + gf_msg_trace (frame->root->client->bound_xl->name, 0, "%"PRId64": " + "RENAME_CBK %s ==> %s", frame->root->unique, + state->loc.name, state->loc2.name); + + /* Before renaming the inode, we have to get the inode for the + * destination entry (i.e. inode with state->loc2.parent as + * parent and state->loc2.name as name). If it exists, then + * unlink that inode, and send forget on that inode if the + * unlinked entry is the last entry. In case of fuse client + * the fuse kernel module itself sends the forget on the + * unlinked inode. + */ + tmp_inode = inode_grep (state->loc.inode->table, + state->loc2.parent, state->loc2.name); + if (tmp_inode) { + inode_unlink (tmp_inode, state->loc2.parent, + state->loc2.name); + forget_inode_if_no_dentry (tmp_inode); + inode_unref (tmp_inode); + } + + inode_rename (state->itable, + state->loc.parent, state->loc.name, + state->loc2.parent, state->loc2.name, + state->loc.inode, stbuf); + gfx_stat_from_iattx (&rsp->stat, stbuf); + + gfx_stat_from_iattx (&rsp->preoldparent, preoldparent); + gfx_stat_from_iattx (&rsp->postoldparent, postoldparent); + + gfx_stat_from_iattx (&rsp->prenewparent, prenewparent); + gfx_stat_from_iattx (&rsp->postnewparent, postnewparent); + +} + +int +server4_post_open (call_frame_t *frame, xlator_t *this, + gfx_open_rsp *rsp, fd_t *fd) +{ + server_ctx_t *serv_ctx = NULL; + uint64_t fd_no = 0; + + serv_ctx = server_ctx_get (frame->root->client, this); + if (serv_ctx == NULL) { + gf_msg (this->name, GF_LOG_INFO, 0, + PS_MSG_SERVER_CTX_GET_FAILED, "server_ctx_get() " + "failed"); + return -1; + } + + fd_bind (fd); + fd_ref (fd); + fd_no = gf_fd_unused_get (serv_ctx->fdtable, fd); + rsp->fd = fd_no; + + return 0; +} + +void +server4_post_readv (gfx_read_rsp *rsp, struct iatt *stbuf, int op_ret) +{ + gfx_stat_from_iattx (&rsp->stat, stbuf); + rsp->size = op_ret; +} + +int +server4_post_create (call_frame_t *frame, gfx_create_rsp *rsp, + server_state_t *state, + xlator_t *this, fd_t *fd, inode_t *inode, + struct iatt *stbuf, struct iatt *preparent, + struct iatt *postparent) +{ + server_ctx_t *serv_ctx = NULL; + inode_t *link_inode = NULL; + uint64_t fd_no = 0; + int op_errno = 0; + + link_inode = inode_link (inode, state->loc.parent, + state->loc.name, stbuf); + + if (!link_inode) { + op_errno = ENOENT; + goto out; + } + + if (link_inode != inode) { + /* + VERY racy code (if used anywhere else) + -- don't do this without understanding + */ + + inode_ctx_merge (fd, fd->inode, link_inode); + inode_unref (fd->inode); + fd->inode = inode_ref (link_inode); + } + + inode_lookup (link_inode); + inode_unref (link_inode); + + serv_ctx = server_ctx_get (frame->root->client, this); + if (serv_ctx == NULL) { + gf_msg (this->name, GF_LOG_INFO, 0, + PS_MSG_SERVER_CTX_GET_FAILED, "server_ctx_get() " + "failed"); + goto out; + } + + fd_bind (fd); + fd_ref (fd); + fd_no = gf_fd_unused_get (serv_ctx->fdtable, fd); + + if ((fd_no > UINT64_MAX) || (fd == 0)) { + op_errno = errno; + } + + rsp->fd = fd_no; + gfx_stat_from_iattx (&rsp->stat, stbuf); + gfx_stat_from_iattx (&rsp->preparent, preparent); + gfx_stat_from_iattx (&rsp->postparent, postparent); + + return 0; +out: + return -op_errno; +} + +/*TODO: Handle revalidate path */ +void +server4_post_lookup (gfx_common_2iatt_rsp *rsp, call_frame_t *frame, + server_state_t *state, + inode_t *inode, struct iatt *stbuf) +{ + inode_t *root_inode = NULL; + inode_t *link_inode = NULL; + uuid_t rootgfid = {0,}; + + root_inode = frame->root->client->bound_xl->itable->root; + + if (!__is_root_gfid (inode->gfid)) { + link_inode = inode_link (inode, state->loc.parent, + state->loc.name, stbuf); + if (link_inode) { + inode_lookup (link_inode); + inode_unref (link_inode); + } + } + + if ((inode == root_inode) || + (state->client->subdir_mount && + (inode == state->client->subdir_inode))) { + /* we just looked up root ("/") OR + subdir mount directory, which is root ('/') in client */ + /* This is very important as when we send iatt of + root-inode, fuse/client expect the gfid to be 1, + along with inode number. As for subdirectory mount, + we use inode table which is shared by everyone, but + make sure we send fops only from subdir and below, + we have to alter inode gfid and send it to client */ + stbuf->ia_ino = 1; + rootgfid[15] = 1; + gf_uuid_copy (stbuf->ia_gfid, rootgfid); + if (inode->ia_type == 0) + inode->ia_type = stbuf->ia_type; + } + + gfx_stat_from_iattx (&rsp->prestat, stbuf); +} + +void +server4_post_lease (gfx_lease_rsp *rsp, struct gf_lease *lease) +{ + gf_proto_lease_from_lease (&rsp->lease, lease); +} + +void +server4_post_link (server_state_t *state, gfx_common_3iatt_rsp *rsp, + inode_t *inode, + struct iatt *stbuf, struct iatt *preparent, + struct iatt *postparent, dict_t *xdata) +{ + inode_t *link_inode = NULL; + + gfx_stat_from_iattx (&rsp->stat, stbuf); + gfx_stat_from_iattx (&rsp->preparent, preparent); + gfx_stat_from_iattx (&rsp->postparent, postparent); + + link_inode = inode_link (inode, state->loc2.parent, + state->loc2.name, stbuf); + inode_lookup (link_inode); + inode_unref (link_inode); + +} |
