#include "server.h" #include #include "rpc-common-xdr.h" #include "glusterfs3-xdr.h" #include "glusterfs3.h" #include #include "server-messages.h" #include "server-helpers.h" #include #include #include "xdr-nfs3.h" void server_post_stat(server_state_t *state, gfs3_stat_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); } gf_stat_from_iatt(&rsp->stat, stbuf); } void server_post_readlink(gfs3_readlink_rsp *rsp, struct iatt *stbuf, const char *buf) { gf_stat_from_iatt(&rsp->buf, stbuf); rsp->path = (char *)buf; } void server_post_mknod(server_state_t *state, gfs3_mknod_rsp *rsp, struct iatt *stbuf, struct iatt *preparent, struct iatt *postparent, inode_t *inode) { inode_t *link_inode = NULL; gf_stat_from_iatt(&rsp->stat, stbuf); gf_stat_from_iatt(&rsp->preparent, preparent); gf_stat_from_iatt(&rsp->postparent, postparent); link_inode = inode_link(inode, state->loc.parent, state->loc.name, stbuf); inode_lookup(link_inode); inode_unref(link_inode); } void server_post_mkdir(server_state_t *state, gfs3_mkdir_rsp *rsp, inode_t *inode, struct iatt *stbuf, struct iatt *preparent, struct iatt *postparent, dict_t *xdata) { inode_t *link_inode = NULL; gf_stat_from_iatt(&rsp->stat, stbuf); gf_stat_from_iatt(&rsp->preparent, preparent); gf_stat_from_iatt(&rsp->postparent, postparent); link_inode = inode_link(inode, state->loc.parent, state->loc.name, stbuf); inode_lookup(link_inode); inode_unref(link_inode); } void server_post_unlink(server_state_t *state, gfs3_unlink_rsp *rsp, struct iatt *preparent, struct iatt *postparent) { inode_unlink(state->loc.inode, state->loc.parent, state->loc.name); forget_inode_if_no_dentry(state->loc.inode); gf_stat_from_iatt(&rsp->preparent, preparent); gf_stat_from_iatt(&rsp->postparent, postparent); } void server_post_rmdir(server_state_t *state, gfs3_rmdir_rsp *rsp, struct iatt *preparent, struct iatt *postparent) { 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); gf_stat_from_iatt(&rsp->preparent, preparent); gf_stat_from_iatt(&rsp->postparent, postparent); } void server_post_symlink(server_state_t *state, gfs3_symlink_rsp *rsp, inode_t *inode, struct iatt *stbuf, struct iatt *preparent, struct iatt *postparent, dict_t *xdata) { inode_t *link_inode = NULL; gf_stat_from_iatt(&rsp->stat, stbuf); gf_stat_from_iatt(&rsp->preparent, preparent); gf_stat_from_iatt(&rsp->postparent, postparent); link_inode = inode_link(inode, state->loc.parent, state->loc.name, stbuf); inode_lookup(link_inode); inode_unref(link_inode); } void server_post_link(server_state_t *state, gfs3_link_rsp *rsp, inode_t *inode, struct iatt *stbuf, struct iatt *preparent, struct iatt *postparent, dict_t *xdata) { inode_t *link_inode = NULL; gf_stat_from_iatt(&rsp->stat, stbuf); gf_stat_from_iatt(&rsp->preparent, preparent); gf_stat_from_iatt(&rsp->postparent, postparent); link_inode = inode_link(inode, state->loc2.parent, state->loc2.name, stbuf); inode_lookup(link_inode); inode_unref(link_inode); } void server_post_truncate(gfs3_truncate_rsp *rsp, struct iatt *prebuf, struct iatt *postbuf) { gf_stat_from_iatt(&rsp->prestat, prebuf); gf_stat_from_iatt(&rsp->poststat, postbuf); } void server_post_writev(gfs3_write_rsp *rsp, struct iatt *prebuf, struct iatt *postbuf) { gf_stat_from_iatt(&rsp->prestat, prebuf); gf_stat_from_iatt(&rsp->poststat, postbuf); } void server_post_statfs(gfs3_statfs_rsp *rsp, struct statvfs *stbuf) { gf_statfs_from_statfs(&rsp->statfs, stbuf); } void server_post_fsync(gfs3_fsync_rsp *rsp, struct iatt *prebuf, struct iatt *postbuf) { gf_stat_from_iatt(&rsp->prestat, prebuf); gf_stat_from_iatt(&rsp->poststat, postbuf); } void server_post_ftruncate(gfs3_ftruncate_rsp *rsp, struct iatt *prebuf, struct iatt *postbuf) { gf_stat_from_iatt(&rsp->prestat, prebuf); gf_stat_from_iatt(&rsp->poststat, postbuf); } void server_post_fstat(server_state_t *state, gfs3_fstat_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); } gf_stat_from_iatt(&rsp->stat, stbuf); } void server_post_lk(xlator_t *this, gfs3_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 server_post_readdir(gfs3_readdir_rsp *rsp, gf_dirent_t *entries) { int ret = 0; ret = serialize_rsp_dirent(entries, rsp); return ret; } void server_post_zerofill(gfs3_zerofill_rsp *rsp, struct iatt *statpre, struct iatt *statpost) { gf_stat_from_iatt(&rsp->statpre, statpre); gf_stat_from_iatt(&rsp->statpost, statpost); } void server_post_discard(gfs3_discard_rsp *rsp, struct iatt *statpre, struct iatt *statpost) { gf_stat_from_iatt(&rsp->statpre, statpre); gf_stat_from_iatt(&rsp->statpost, statpost); } void server_post_fallocate(gfs3_fallocate_rsp *rsp, struct iatt *statpre, struct iatt *statpost) { gf_stat_from_iatt(&rsp->statpre, statpre); gf_stat_from_iatt(&rsp->statpost, statpost); } void server_post_seek(gfs3_seek_rsp *rsp, off_t offset) { rsp->offset = offset; } int server_post_readdirp(gfs3_readdirp_rsp *rsp, gf_dirent_t *entries) { int ret = 0; ret = serialize_rsp_direntp(entries, rsp); return ret; } void server_post_fsetattr(gfs3_fsetattr_rsp *rsp, struct iatt *statpre, struct iatt *statpost) { gf_stat_from_iatt(&rsp->statpre, statpre); gf_stat_from_iatt(&rsp->statpost, statpost); } void server_post_setattr(gfs3_setattr_rsp *rsp, struct iatt *statpre, struct iatt *statpost) { gf_stat_from_iatt(&rsp->statpre, statpre); gf_stat_from_iatt(&rsp->statpost, statpost); } void server_post_rchecksum(gfs3_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 = MD5_DIGEST_LENGTH; } void server_post_rename(call_frame_t *frame, server_state_t *state, gfs3_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); gf_stat_from_iatt(&rsp->stat, stbuf); gf_stat_from_iatt(&rsp->preoldparent, preoldparent); gf_stat_from_iatt(&rsp->postoldparent, postoldparent); gf_stat_from_iatt(&rsp->prenewparent, prenewparent); gf_stat_from_iatt(&rsp->postnewparent, postnewparent); } int server_post_open(call_frame_t *frame, xlator_t *this, gfs3_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 server_post_readv(gfs3_read_rsp *rsp, struct iatt *stbuf, int op_ret) { gf_stat_from_iatt(&rsp->stat, stbuf); rsp->size = op_ret; } int server_post_opendir(call_frame_t *frame, xlator_t *this, gfs3_opendir_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; } int server_post_create(call_frame_t *frame, gfs3_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; gf_stat_from_iatt(&rsp->stat, stbuf); gf_stat_from_iatt(&rsp->preparent, preparent); gf_stat_from_iatt(&rsp->postparent, postparent); return 0; out: return -op_errno; } /*TODO: Handle revalidate path */ void server_post_lookup(gfs3_lookup_rsp *rsp, call_frame_t *frame, server_state_t *state, inode_t *inode, struct iatt *stbuf, struct iatt *postparent) { 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; } gf_stat_from_iatt(&rsp->stat, stbuf); } void 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_3iatt_noinode(gfx_common_3iatt_rsp *rsp, struct iatt *stbuf, struct iatt *prebuf_dst, struct iatt *postbuf_dst) { gfx_stat_from_iattx(&rsp->stat, stbuf); gfx_stat_from_iattx(&rsp->preparent, prebuf_dst); gfx_stat_from_iattx(&rsp->postparent, postbuf_dst); } 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; /* When the length encoding changes, update the change in posix code also. */ rsp->strong_checksum.strong_checksum_val = (char *)strong_checksum; rsp->strong_checksum.strong_checksum_len = SHA256_DIGEST_LENGTH; rsp->flags = 1; /* Indicates SHA256 TYPE */ } 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); }