diff options
Diffstat (limited to 'xlators/nfs/server/src/nfs-fops.c')
| -rw-r--r-- | xlators/nfs/server/src/nfs-fops.c | 1632 |
1 files changed, 1632 insertions, 0 deletions
diff --git a/xlators/nfs/server/src/nfs-fops.c b/xlators/nfs/server/src/nfs-fops.c new file mode 100644 index 00000000000..4d8540c2c3e --- /dev/null +++ b/xlators/nfs/server/src/nfs-fops.c @@ -0,0 +1,1632 @@ +/* + Copyright (c) 2010-2011 Gluster, Inc. <http://www.gluster.com> + 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 <pwd.h> + +#include <glusterfs/dict.h> +#include <glusterfs/xlator.h> +#include <glusterfs/iobuf.h> +#include <glusterfs/call-stub.h> +#include "nfs.h" +#include "nfs-fops.h" +#include "nfs-common.h" +#include "nfs3-helpers.h" +#include "nfs-mem-types.h" +#include "nfs-messages.h" +#include <libgen.h> +#include <semaphore.h> + +static int gf_auth_max_groups_nfs_log = 0; + +void +nfs_fix_groups(xlator_t *this, call_stack_t *root) +{ + struct passwd mypw; + char mystrs[1024]; + struct passwd *result; + gid_t *mygroups; + int ngroups; + int i; + int max_groups; + struct nfs_state *priv = this->private; + const gid_list_t *agl; + gid_list_t gl; + + if (!priv->server_aux_gids) { + return; + } + + /* RPC enforces the GF_AUTH_GLUSTERFS_MAX_GROUPS limit */ + max_groups = GF_AUTH_GLUSTERFS_MAX_GROUPS(root->lk_owner.len, + AUTH_GLUSTERFS_v2); + + agl = gid_cache_lookup(&priv->gid_cache, root->uid, 0, 0); + if (agl) { + if (agl->gl_count > max_groups) { + GF_LOG_OCCASIONALLY(gf_auth_max_groups_nfs_log, this->name, + GF_LOG_WARNING, + "too many groups, reducing %d -> %d", + agl->gl_count, max_groups); + } + + for (ngroups = 0; ngroups < agl->gl_count && ngroups <= max_groups; + ngroups++) { + root->groups[ngroups] = agl->gl_list[ngroups]; + } + root->ngrps = ngroups; + gid_cache_release(&priv->gid_cache, agl); + return; + } + + /* No cached list found. */ + if (getpwuid_r(root->uid, &mypw, mystrs, sizeof(mystrs), &result) != 0) { + gf_msg(this->name, GF_LOG_ERROR, 0, NFS_MSG_GETPWUID_FAIL, + "getpwuid_r(%u) failed", root->uid); + return; + } + + if (!result) { + gf_msg(this->name, GF_LOG_ERROR, 0, NFS_MSG_GETPWUID_FAIL, + "getpwuid_r(%u) found nothing", root->uid); + return; + } + + gf_msg_trace(this->name, 0, "mapped %u => %s", root->uid, result->pw_name); + + ngroups = gf_getgrouplist(result->pw_name, root->gid, &mygroups); + if (ngroups == -1) { + gf_msg(this->name, GF_LOG_ERROR, 0, NFS_MSG_MAP_GRP_LIST_FAIL, + "could not map %s to group list", result->pw_name); + return; + } + + /* RPC enforces the GF_AUTH_GLUSTERFS_MAX_GROUPS limit */ + if (ngroups > max_groups) { + GF_LOG_OCCASIONALLY( + gf_auth_max_groups_nfs_log, this->name, GF_LOG_WARNING, + "too many groups, reducing %d -> %d", ngroups, max_groups); + } + + /* Copy data to the frame. */ + for (i = 0; i < ngroups && i < max_groups; ++i) { + gf_msg_trace(this->name, 0, "%s is in group %u", result->pw_name, + mygroups[i]); + root->groups[i] = mygroups[i]; + } + root->ngrps = ngroups; + + /* Add the group data to the cache. */ + gl.gl_list = mygroups; + gl.gl_id = root->uid; + gl.gl_uid = 0; + gl.gl_gid = 0; + gl.gl_count = ngroups; + if (gid_cache_add(&priv->gid_cache, &gl) != 1) + GF_FREE(mygroups); +} + +struct nfs_fop_local * +nfs_fop_local_init(xlator_t *nfsx) +{ + struct nfs_fop_local *l = NULL; + + if (!nfsx) + return NULL; + + l = mem_get(nfs_fop_mempool(nfsx)); + if (!l) { + gf_msg_nomem(GF_NFS, GF_LOG_ERROR, 4096); + return NULL; + } + + memset(l, 0, sizeof(*l)); + return l; +} + +void +nfs_fop_local_wipe(xlator_t *nfsx, struct nfs_fop_local *l) +{ + if ((!nfsx) || (!l)) + return; + + if (l->iobref) + iobref_unref(l->iobref); + + if (l->parent) + inode_unref(l->parent); + + if (l->inode) + inode_unref(l->inode); + + if (l->newparent) + inode_unref(l->newparent); + + if (l->dictgfid) + dict_unref(l->dictgfid); + + mem_put(l); + + return; +} + +#define nfs_stack_destroy(nfl, fram) \ + do { \ + nfs_fop_local_wipe((nfl)->nfsx, nfl); \ + (fram)->local = NULL; \ + STACK_DESTROY((fram)->root); \ + } while (0) + +pthread_mutex_t ctr = PTHREAD_MUTEX_INITIALIZER; +unsigned int cval = 1; + +int +nfs_frame_getctr() +{ + uint64_t val = 0; + + pthread_mutex_lock(&ctr); + { + if (cval == 0) + cval = 1; + val = cval; + cval++; + } + pthread_mutex_unlock(&ctr); + + return val; +} + +call_frame_t * +nfs_create_frame(xlator_t *xl, nfs_user_t *nfu) +{ + call_frame_t *frame = NULL; + int x = 0; + int y = 0; + + if ((!xl) || (!nfu) || (nfu->ngrps > NFS_NGROUPS)) + return NULL; + + frame = create_frame(xl, (call_pool_t *)xl->ctx->pool); + if (!frame) + goto err; + if (call_stack_alloc_groups(frame->root, nfu->ngrps) != 0) { + STACK_DESTROY(frame->root); + frame = NULL; + goto err; + } + + frame->root->pid = NFS_PID; + frame->root->uid = nfu->uid; + frame->root->gid = nfu->gids[NFS_PRIMGID_IDX]; + memcpy(&frame->root->identifier, &nfu->identifier, UNIX_PATH_MAX); + frame->root->lk_owner = nfu->lk_owner; + + if (nfu->ngrps != 1) { + frame->root->ngrps = nfu->ngrps - 1; + + gf_msg_trace(GF_NFS, 0, "uid: %d, gid %d, gids: %d", frame->root->uid, + frame->root->gid, frame->root->ngrps); + for (y = 0, x = 1; y < frame->root->ngrps; x++, y++) { + gf_msg_trace(GF_NFS, 0, "gid: %d", nfu->gids[x]); + frame->root->groups[y] = nfu->gids[x]; + } + } + + /* + * It's tempting to do this *instead* of using nfu above, but we need + * to have those values in case nfs_fix_groups doesn't do anything. + */ + nfs_fix_groups(xl, frame->root); + +err: + return frame; +} + +#define nfs_fop_handle_frame_create(fram, xla, nfuser, retval, errlabel) \ + do { \ + fram = nfs_create_frame(xla, (nfuser)); \ + if (!fram) { \ + retval = (-ENOMEM); \ + gf_msg(GF_NFS, GF_LOG_ERROR, ENOMEM, NFS_MSG_NO_MEMORY, \ + "Frame creation failed"); \ + goto errlabel; \ + } \ + } while (0) + +/* Look into the inode and parent inode of a loc and save enough state + * for us to determine in the callback whether to funge the ino in the stat buf + * with 1 for the parent. + */ +#define nfs_fop_save_root_ino(locl, loc) \ + do { \ + if (((loc)->inode) && __is_root_gfid((loc)->inode->gfid)) \ + (locl)->rootinode = 1; \ + else if (((loc)->parent) && __is_root_gfid((loc)->parent->gfid)) \ + (locl)->rootparentinode = 1; \ + } while (0) + +/* Do the same for an fd */ +#define nfs_fop_save_root_fd_ino(locl, fdesc) \ + do { \ + if (__is_root_gfid((fdesc)->inode->gfid)) \ + (locl)->rootinode = 1; \ + } while (0) + +/* Use the state saved by the previous macro to funge the ino in the appropriate + * structure. + */ +#define nfs_fop_restore_root_ino(locl, fopret, preattr, postattr, prepar, \ + postpar) \ + do { \ + if (fopret == -1) \ + break; \ + if ((locl)->rootinode) { \ + if ((preattr)) { \ + ((struct iatt *)(preattr))->ia_ino = 1; \ + ((struct iatt *)(preattr))->ia_dev = 0; \ + } \ + if ((postattr)) { \ + ((struct iatt *)(postattr))->ia_ino = 1; \ + ((struct iatt *)(postattr))->ia_dev = 0; \ + } \ + } else if ((locl)->rootparentinode) { \ + if ((prepar)) { \ + ((struct iatt *)(prepar))->ia_ino = 1; \ + ((struct iatt *)(prepar))->ia_dev = 0; \ + } \ + if ((postpar)) { \ + ((struct iatt *)(postpar))->ia_ino = 1; \ + ((struct iatt *)(postpar))->ia_dev = 0; \ + } \ + } \ + } while (0) + +/* If the newly created, inode's parent is root, we'll need to funge the ino + * in the parent attr when we receive them in the callback. + */ +#define nfs_fop_newloc_save_root_ino(locl, newloc) \ + do { \ + if (((newloc)->inode) && __is_root_gfid((newloc)->inode->gfid)) \ + (locl)->newrootinode = 1; \ + else if (((newloc)->parent) && __is_root_gfid((newloc)->parent->gfid)) \ + (locl)->newrootparentinode = 1; \ + } while (0) + +#define nfs_fop_newloc_restore_root_ino(locl, fopret, preattr, postattr, \ + prepar, postpar) \ + do { \ + if (fopret == -1) \ + break; \ + \ + if ((locl)->newrootinode) { \ + if ((preattr)) \ + ((struct iatt *)(preattr))->ia_ino = 1; \ + if ((postattr)) \ + ((struct iatt *)(postattr))->ia_ino = 1; \ + } else if ((locl)->newrootparentinode) { \ + if ((prepar)) \ + ((struct iatt *)(prepar))->ia_ino = 1; \ + if ((postpar)) \ + ((struct iatt *)(postpar))->ia_ino = 1; \ + } \ + } while (0) + +dict_t * +nfs_gfid_dict(inode_t *inode) +{ + uuid_t newgfid = { + 0, + }; + unsigned char *dyngfid = NULL; + dict_t *dictgfid = NULL; + int ret = -1; + static uuid_t rootgfid = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}; + + dyngfid = GF_MALLOC(sizeof(uuid_t), gf_common_mt_char); + if (dyngfid == NULL) + return (NULL); + + gf_uuid_generate(newgfid); + + if (gf_uuid_compare(inode->gfid, rootgfid) == 0) + memcpy(dyngfid, rootgfid, sizeof(uuid_t)); + else + memcpy(dyngfid, newgfid, sizeof(uuid_t)); + + dictgfid = dict_new(); + if (!dictgfid) { + gf_msg(GF_NFS, GF_LOG_ERROR, errno, NFS_MSG_GFID_DICT_CREATE_FAIL, + "Failed to create gfid dict"); + GF_FREE(dyngfid); + return (NULL); + } + + ret = dict_set_gfuuid(dictgfid, "gfid-req", dyngfid, false); + if (ret < 0) { + GF_FREE(dyngfid); + dict_unref(dictgfid); + return (NULL); + } + + return dictgfid; +} + +#define nfs_fop_gfid_setup(nflcl, inode, retval, erlbl) \ + do { \ + if (nflcl) { \ + (nflcl)->dictgfid = nfs_gfid_dict(inode); \ + \ + if (!((nflcl)->dictgfid)) { \ + retval = -EFAULT; \ + goto erlbl; \ + } \ + } \ + } while (0) + +/* Fops Layer Explained + * The fops layer has three types of functions. They can all be identified by + * their names. Here are the three patterns: + * + * nfs_fop_<fopname> + * This is the lowest level function that knows nothing about states and + * callbacks. At most this is required to create a frame and call the + * fop. The idea here is to provide a convenient way to call fops than + * directly use STACK_WINDs. If this type of interface is used, the caller's + * callback is responsible for doing the relevant GlusterFS state + * maintenance operations on the data returned in the callbacks. + * + * nfs_<fopname> + * Unlike the nfs_fop_<fopname> variety, this is the stateful type of fop, in + * that it silently performs all the relevant GlusterFS state maintenance + * operations on the data returned to the callbacks, leaving the caller's + * callback to just use the data returned for whatever it needs to do with that + * data, for eg. the nfs_lookup, will take care of looking up the inodes, + * revalidating them if needed and linking new inodes into the table, while + * the caller's callback, for eg, the NFSv3 LOOKUP callback can just use + * the stat bufs returned to create file handle, map the file handle into the + * fh cache and finally encode the fh and the stat bufs into a NFS reply. + * + */ + +int32_t +nfs_fop_lookup_cbk(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, inode_t *inode, + struct iatt *buf, dict_t *xattr, struct iatt *postparent) +{ + struct nfs_fop_local *local = NULL; + fop_lookup_cbk_t progcbk; + + if (op_ret == 0) { + nfs_fix_generation(this, inode); + } + + nfl_to_prog_data(local, progcbk, frame); + nfs_fop_restore_root_ino(local, op_ret, buf, NULL, NULL, postparent); + if (progcbk) + progcbk(frame, cookie, this, op_ret, op_errno, inode, buf, xattr, + postparent); + + nfs_stack_destroy(local, frame); + return 0; +} + +int +nfs_fop_lookup(xlator_t *nfsx, xlator_t *xl, nfs_user_t *nfu, loc_t *loc, + fop_lookup_cbk_t cbk, void *local) +{ + call_frame_t *frame = NULL; + int ret = -EFAULT; + struct nfs_fop_local *nfl = NULL; + + if ((!xl) || (!loc) || (!nfu)) + return ret; + + gf_msg_trace(GF_NFS, 0, "Lookup: %s", loc->path); + nfs_fop_handle_frame_create(frame, nfsx, nfu, ret, err); + nfs_fop_handle_local_init(frame, nfsx, nfl, cbk, local, ret, err); + nfs_fop_save_root_ino(nfl, loc); + nfs_fop_gfid_setup(nfl, loc->inode, ret, err); + + STACK_WIND_COOKIE(frame, nfs_fop_lookup_cbk, xl, xl, xl->fops->lookup, loc, + nfl->dictgfid); + + ret = 0; +err: + if (ret < 0) { + if (frame) + nfs_stack_destroy(nfl, frame); + } + + return ret; +} + +int32_t +nfs_fop_access_cbk(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, dict_t *xdata) +{ + struct nfs_fop_local *nfl = NULL; + fop_access_cbk_t progcbk = NULL; + + nfl_to_prog_data(nfl, progcbk, frame); + if (progcbk) + progcbk(frame, cookie, this, op_ret, op_errno, xdata); + + nfs_stack_destroy(nfl, frame); + return 0; +} + +int +nfs_fop_access(xlator_t *nfsx, xlator_t *xl, nfs_user_t *nfu, loc_t *loc, + int32_t accesstest, fop_access_cbk_t cbk, void *local) +{ + call_frame_t *frame = NULL; + int ret = -EFAULT; + struct nfs_fop_local *nfl = NULL; + uint32_t accessbits = 0; + + if ((!xl) || (!loc) || (!nfu)) + return ret; + + gf_msg_trace(GF_NFS, 0, "Access: %s", loc->path); + nfs_fop_handle_frame_create(frame, nfsx, nfu, ret, err); + nfs_fop_handle_local_init(frame, nfsx, nfl, cbk, local, ret, err); + nfs_fop_save_root_ino(nfl, loc); + + accessbits = nfs3_request_to_accessbits(accesstest); + STACK_WIND_COOKIE(frame, nfs_fop_access_cbk, xl, xl, xl->fops->access, loc, + accessbits, NULL); + ret = 0; +err: + if (ret < 0) { + if (frame) + nfs_stack_destroy(nfl, frame); + } + + return ret; +} + +int32_t +nfs_fop_stat_cbk(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, struct iatt *buf, + dict_t *xdata) +{ + struct nfs_fop_local *nfl = NULL; + fop_stat_cbk_t progcbk = NULL; + + nfl_to_prog_data(nfl, progcbk, frame); + nfs_fop_restore_root_ino(nfl, op_ret, buf, NULL, NULL, NULL); + if (progcbk) + progcbk(frame, cookie, this, op_ret, op_errno, buf, xdata); + + nfs_stack_destroy(nfl, frame); + return 0; +} + +int +nfs_fop_stat(xlator_t *nfsx, xlator_t *xl, nfs_user_t *nfu, loc_t *loc, + fop_stat_cbk_t cbk, void *local) +{ + call_frame_t *frame = NULL; + int ret = -EFAULT; + struct nfs_fop_local *nfl = NULL; + + if ((!xl) || (!loc) || (!nfu)) + return ret; + + gf_msg_trace(GF_NFS, 0, "Stat: %s", loc->path); + nfs_fop_handle_frame_create(frame, nfsx, nfu, ret, err); + nfs_fop_handle_local_init(frame, nfsx, nfl, cbk, local, ret, err); + nfs_fop_save_root_ino(nfl, loc); + + STACK_WIND_COOKIE(frame, nfs_fop_stat_cbk, xl, xl, xl->fops->stat, loc, + NULL); + ret = 0; +err: + if (ret < 0) { + if (frame) + nfs_stack_destroy(nfl, frame); + } + + return ret; +} + +int32_t +nfs_fop_fstat_cbk(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, struct iatt *buf, + dict_t *xdata) +{ + struct nfs_fop_local *nfl = NULL; + fop_fstat_cbk_t progcbk = NULL; + + nfl_to_prog_data(nfl, progcbk, frame); + nfs_fop_restore_root_ino(nfl, op_ret, buf, NULL, NULL, NULL); + if (progcbk) + progcbk(frame, cookie, this, op_ret, op_errno, buf, xdata); + + nfs_stack_destroy(nfl, frame); + return 0; +} + +int +nfs_fop_fstat(xlator_t *nfsx, xlator_t *xl, nfs_user_t *nfu, fd_t *fd, + fop_fstat_cbk_t cbk, void *local) +{ + call_frame_t *frame = NULL; + int ret = -EFAULT; + struct nfs_fop_local *nfl = NULL; + + if ((!nfsx) || (!xl) || (!fd) || (!nfu)) + return ret; + + gf_msg_trace(GF_NFS, 0, "FStat"); + nfs_fop_handle_frame_create(frame, nfsx, nfu, ret, err); + nfs_fop_handle_local_init(frame, nfsx, nfl, cbk, local, ret, err); + nfs_fop_save_root_fd_ino(nfl, fd); + + STACK_WIND_COOKIE(frame, nfs_fop_fstat_cbk, xl, xl, xl->fops->fstat, fd, + NULL); + + ret = 0; +err: + if (ret < 0) { + if (frame) + nfs_stack_destroy(nfl, frame); + } + + return ret; +} + +int32_t +nfs_fop_opendir_cbk(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, fd_t *fd, dict_t *xdata) +{ + struct nfs_fop_local *nfl = NULL; + fop_opendir_cbk_t progcbk = NULL; + + nfl_to_prog_data(nfl, progcbk, frame); + if (progcbk) + progcbk(frame, cookie, this, op_ret, op_errno, fd, xdata); + nfs_stack_destroy(nfl, frame); + return 0; +} + +int +nfs_fop_opendir(xlator_t *nfsx, xlator_t *xl, nfs_user_t *nfu, loc_t *pathloc, + fd_t *dirfd, fop_opendir_cbk_t cbk, void *local) +{ + call_frame_t *frame = NULL; + int ret = -EFAULT; + struct nfs_fop_local *nfl = NULL; + + if ((!nfsx) || (!xl) || (!pathloc) || (!dirfd) || (!nfu)) + return ret; + + gf_msg_trace(GF_NFS, 0, "Opendir: %s", pathloc->path); + nfs_fop_handle_frame_create(frame, nfsx, nfu, ret, err); + nfs_fop_handle_local_init(frame, nfsx, nfl, cbk, local, ret, err); + + STACK_WIND_COOKIE(frame, nfs_fop_opendir_cbk, xl, xl, xl->fops->opendir, + pathloc, dirfd, NULL); + ret = 0; + +err: + if (ret < 0) { + if (frame) + nfs_stack_destroy(nfl, frame); + } + + return ret; +} + +int +nfs_fop_flush_cbk(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, dict_t *xdata) +{ + struct nfs_fop_local *nfl = NULL; + fop_flush_cbk_t progcbk = NULL; + + nfl_to_prog_data(nfl, progcbk, frame); + if (progcbk) + progcbk(frame, cookie, this, op_ret, op_errno, xdata); + + nfs_stack_destroy(nfl, frame); + return 0; +} + +int +nfs_fop_flush(xlator_t *nfsx, xlator_t *xl, nfs_user_t *nfu, fd_t *fd, + fop_flush_cbk_t cbk, void *local) +{ + call_frame_t *frame = NULL; + int ret = -EFAULT; + struct nfs_fop_local *nfl = NULL; + + if ((!nfsx) || (!xl) || (!fd) || (!nfu)) + return ret; + + nfs_fop_handle_frame_create(frame, nfsx, nfu, ret, err); + nfs_fop_handle_local_init(frame, nfsx, nfl, cbk, local, ret, err); + + STACK_WIND_COOKIE(frame, nfs_fop_flush_cbk, xl, xl, xl->fops->flush, fd, + NULL); + ret = 0; +err: + if (ret < 0) { + if (frame) + nfs_stack_destroy(nfl, frame); + } + + return ret; +} + +int32_t +nfs_fop_readdirp_cbk(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, gf_dirent_t *entries, + dict_t *xdata) +{ + struct nfs_fop_local *nfl = NULL; + fop_readdirp_cbk_t progcbk = NULL; + + nfl_to_prog_data(nfl, progcbk, frame); + if (progcbk) + progcbk(frame, cookie, this, op_ret, op_errno, entries, xdata); + + nfs_stack_destroy(nfl, frame); + + return 0; +} + +int +nfs_fop_readdirp(xlator_t *nfsx, xlator_t *xl, nfs_user_t *nfu, fd_t *dirfd, + size_t bufsize, off_t offset, fop_readdirp_cbk_t cbk, + void *local) +{ + call_frame_t *frame = NULL; + int ret = -EFAULT; + struct nfs_fop_local *nfl = NULL; + + if ((!nfsx) || (!xl) || (!dirfd) || (!nfu)) + return ret; + + gf_msg_trace(GF_NFS, 0, "readdir"); + nfs_fop_handle_frame_create(frame, nfsx, nfu, ret, err); + nfs_fop_handle_local_init(frame, nfsx, nfl, cbk, local, ret, err); + + STACK_WIND_COOKIE(frame, nfs_fop_readdirp_cbk, xl, xl, xl->fops->readdirp, + dirfd, bufsize, offset, 0); + + ret = 0; +err: + if (ret < 0) { + if (frame) + nfs_stack_destroy(nfl, frame); + } + + return ret; +} + +int32_t +nfs_fop_statfs_cbk(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, struct statvfs *buf, + dict_t *xdata) +{ + struct nfs_fop_local *nfl = NULL; + fop_statfs_cbk_t progcbk = NULL; + + nfl_to_prog_data(nfl, progcbk, frame); + if (progcbk) + progcbk(frame, cookie, this, op_ret, op_errno, buf, xdata); + + nfs_stack_destroy(nfl, frame); + return 0; +} + +int +nfs_fop_statfs(xlator_t *nfsx, xlator_t *xl, nfs_user_t *nfu, loc_t *pathloc, + fop_statfs_cbk_t cbk, void *local) +{ + call_frame_t *frame = NULL; + int ret = -EFAULT; + struct nfs_fop_local *nfl = NULL; + + if ((!nfsx) || (!xl) || (!pathloc) || (!nfu)) + return ret; + + gf_msg_trace(GF_NFS, 0, "Statfs: %s", pathloc->path); + nfs_fop_handle_frame_create(frame, nfsx, nfu, ret, err); + nfs_fop_handle_local_init(frame, nfsx, nfl, cbk, local, ret, err); + + STACK_WIND_COOKIE(frame, nfs_fop_statfs_cbk, xl, xl, xl->fops->statfs, + pathloc, NULL); + ret = 0; +err: + if (ret < 0) { + if (frame) + nfs_stack_destroy(nfl, frame); + } + + return ret; +} + +int32_t +nfs_fop_create_cbk(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, fd_t *fd, inode_t *inode, + struct iatt *buf, struct iatt *preparent, + struct iatt *postparent, dict_t *xdata) +{ + struct nfs_fop_local *nfl = NULL; + fop_create_cbk_t progcbk = NULL; + + if (op_ret == 0) { + nfs_fix_generation(this, inode); + } + + nfl_to_prog_data(nfl, progcbk, frame); + nfs_fop_restore_root_ino(nfl, op_ret, buf, NULL, preparent, postparent); + if (progcbk) + progcbk(frame, cookie, this, op_ret, op_errno, fd, inode, buf, + preparent, postparent, NULL); + + nfs_stack_destroy(nfl, frame); + return 0; +} + +int +nfs_fop_create(xlator_t *nfsx, xlator_t *xl, nfs_user_t *nfu, loc_t *pathloc, + int flags, mode_t mode, fd_t *fd, fop_create_cbk_t cbk, + void *local) +{ + call_frame_t *frame = NULL; + int ret = -EFAULT; + struct nfs_fop_local *nfl = NULL; + + if ((!nfsx) || (!xl) || (!pathloc) || (!nfu)) + return ret; + + gf_msg_trace(GF_NFS, 0, "Create: %s", pathloc->path); + nfs_fop_handle_frame_create(frame, nfsx, nfu, ret, err); + nfs_fop_handle_local_init(frame, nfsx, nfl, cbk, local, ret, err); + nfs_fop_save_root_ino(nfl, pathloc); + nfs_fop_gfid_setup(nfl, pathloc->inode, ret, err); + + STACK_WIND_COOKIE(frame, nfs_fop_create_cbk, xl, xl, xl->fops->create, + pathloc, flags, mode, 0, fd, nfl->dictgfid); + + ret = 0; +err: + if (ret < 0) { + if (frame) + nfs_stack_destroy(nfl, frame); + } + + return ret; +} + +int32_t +nfs_fop_setattr_cbk(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, struct iatt *pre, + struct iatt *post, dict_t *xdata) +{ + struct nfs_fop_local *nfl = NULL; + fop_setattr_cbk_t progcbk = NULL; + + nfl_to_prog_data(nfl, progcbk, frame); + nfs_fop_restore_root_ino(nfl, op_ret, pre, post, NULL, NULL); + if (progcbk) + progcbk(frame, cookie, this, op_ret, op_errno, pre, post, xdata); + nfs_stack_destroy(nfl, frame); + return 0; +} + +int +nfs_fop_setattr(xlator_t *nfsx, xlator_t *xl, nfs_user_t *nfu, loc_t *pathloc, + struct iatt *buf, int32_t valid, fop_setattr_cbk_t cbk, + void *local) +{ + call_frame_t *frame = NULL; + int ret = -EFAULT; + struct nfs_fop_local *nfl = NULL; + + if ((!nfsx) || (!xl) || (!pathloc) || (!nfu)) + return ret; + + gf_msg_trace(GF_NFS, 0, "Setattr: %s", pathloc->path); + nfs_fop_handle_frame_create(frame, nfsx, nfu, ret, err); + nfs_fop_handle_local_init(frame, nfsx, nfl, cbk, local, ret, err); + nfs_fop_save_root_ino(nfl, pathloc); + + STACK_WIND_COOKIE(frame, nfs_fop_setattr_cbk, xl, xl, xl->fops->setattr, + pathloc, buf, valid, NULL); + ret = 0; +err: + if (ret < 0) { + if (frame) + nfs_stack_destroy(nfl, frame); + } + + return ret; +} + +int32_t +nfs_fop_mkdir_cbk(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, inode_t *inode, + struct iatt *buf, struct iatt *preparent, + struct iatt *postparent, dict_t *xdata) +{ + struct nfs_fop_local *nfl = NULL; + fop_mkdir_cbk_t progcbk = NULL; + + if (op_ret == 0) { + nfs_fix_generation(this, inode); + } + + nfl_to_prog_data(nfl, progcbk, frame); + nfs_fop_restore_root_ino(nfl, op_ret, buf, NULL, preparent, postparent); + if (progcbk) + progcbk(frame, cookie, this, op_ret, op_errno, inode, buf, preparent, + postparent, xdata); + nfs_stack_destroy(nfl, frame); + return 0; +} + +int +nfs_fop_mkdir(xlator_t *nfsx, xlator_t *xl, nfs_user_t *nfu, loc_t *pathloc, + mode_t mode, fop_mkdir_cbk_t cbk, void *local) +{ + call_frame_t *frame = NULL; + int ret = -EFAULT; + struct nfs_fop_local *nfl = NULL; + + if ((!nfsx) || (!xl) || (!pathloc) || (!nfu)) + return ret; + + gf_msg_trace(GF_NFS, 0, "Mkdir: %s", pathloc->path); + nfs_fop_handle_frame_create(frame, nfsx, nfu, ret, err); + nfs_fop_handle_local_init(frame, nfsx, nfl, cbk, local, ret, err); + nfs_fop_save_root_ino(nfl, pathloc); + nfs_fop_gfid_setup(nfl, pathloc->inode, ret, err); + + STACK_WIND_COOKIE(frame, nfs_fop_mkdir_cbk, xl, xl, xl->fops->mkdir, + pathloc, mode, 0, nfl->dictgfid); + ret = 0; +err: + if (ret < 0) { + if (frame) + nfs_stack_destroy(nfl, frame); + } + + return ret; +} + +int32_t +nfs_fop_symlink_cbk(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, inode_t *inode, + struct iatt *buf, struct iatt *preparent, + struct iatt *postparent, dict_t *xdata) +{ + struct nfs_fop_local *nfl = NULL; + fop_symlink_cbk_t progcbk = NULL; + + if (op_ret == 0) { + nfs_fix_generation(this, inode); + } + + nfl_to_prog_data(nfl, progcbk, frame); + nfs_fop_restore_root_ino(nfl, op_ret, buf, NULL, preparent, postparent); + if (progcbk) + progcbk(frame, cookie, this, op_ret, op_errno, inode, buf, preparent, + postparent, xdata); + nfs_stack_destroy(nfl, frame); + return 0; +} + +int +nfs_fop_symlink(xlator_t *nfsx, xlator_t *xl, nfs_user_t *nfu, char *target, + loc_t *pathloc, fop_symlink_cbk_t cbk, void *local) +{ + call_frame_t *frame = NULL; + int ret = -EFAULT; + struct nfs_fop_local *nfl = NULL; + + if ((!nfsx) || (!xl) || (!pathloc) || (!target) || (!nfu)) + return ret; + + gf_msg_trace(GF_NFS, 0, "Symlink: %s", pathloc->path); + nfs_fop_handle_frame_create(frame, nfsx, nfu, ret, err); + nfs_fop_handle_local_init(frame, nfsx, nfl, cbk, local, ret, err); + nfs_fop_save_root_ino(nfl, pathloc); + nfs_fop_gfid_setup(nfl, pathloc->inode, ret, err); + + STACK_WIND_COOKIE(frame, nfs_fop_symlink_cbk, xl, xl, xl->fops->symlink, + target, pathloc, 0, nfl->dictgfid); + ret = 0; +err: + if (ret < 0) { + if (frame) + nfs_stack_destroy(nfl, frame); + } + + return ret; +} + +int32_t +nfs_fop_readlink_cbk(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, const char *path, + struct iatt *buf, dict_t *xdata) +{ + struct nfs_fop_local *nfl = NULL; + fop_readlink_cbk_t progcbk = NULL; + + nfl_to_prog_data(nfl, progcbk, frame); + nfs_fop_restore_root_ino(nfl, op_ret, buf, NULL, NULL, NULL); + if (progcbk) + progcbk(frame, cookie, this, op_ret, op_errno, path, buf, xdata); + nfs_stack_destroy(nfl, frame); + return 0; +} + +int +nfs_fop_readlink(xlator_t *nfsx, xlator_t *xl, nfs_user_t *nfu, loc_t *pathloc, + size_t size, fop_readlink_cbk_t cbk, void *local) +{ + call_frame_t *frame = NULL; + int ret = -EFAULT; + struct nfs_fop_local *nfl = NULL; + + if ((!nfsx) || (!xl) || (!pathloc) || (!nfu)) + return ret; + + gf_msg_trace(GF_NFS, 0, "Readlink: %s", pathloc->path); + nfs_fop_handle_frame_create(frame, nfsx, nfu, ret, err); + nfs_fop_handle_local_init(frame, nfsx, nfl, cbk, local, ret, err); + nfs_fop_save_root_ino(nfl, pathloc); + + STACK_WIND_COOKIE(frame, nfs_fop_readlink_cbk, xl, xl, xl->fops->readlink, + pathloc, size, NULL); + ret = 0; +err: + if (ret < 0) { + if (frame) + nfs_stack_destroy(nfl, frame); + } + + return ret; +} + +int32_t +nfs_fop_mknod_cbk(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, inode_t *inode, + struct iatt *buf, struct iatt *preparent, + struct iatt *postparent, dict_t *xdata) +{ + struct nfs_fop_local *nfl = NULL; + fop_mknod_cbk_t progcbk = NULL; + + if (op_ret == 0) { + nfs_fix_generation(this, inode); + } + + nfl_to_prog_data(nfl, progcbk, frame); + nfs_fop_restore_root_ino(nfl, op_ret, buf, NULL, preparent, postparent); + if (progcbk) + progcbk(frame, cookie, this, op_ret, op_errno, inode, buf, preparent, + postparent, xdata); + nfs_stack_destroy(nfl, frame); + return 0; +} + +int +nfs_fop_mknod(xlator_t *nfsx, xlator_t *xl, nfs_user_t *nfu, loc_t *pathloc, + mode_t mode, dev_t dev, fop_mknod_cbk_t cbk, void *local) +{ + call_frame_t *frame = NULL; + int ret = -EFAULT; + struct nfs_fop_local *nfl = NULL; + + if ((!nfsx) || (!xl) || (!pathloc) || (!nfu)) + return ret; + + gf_msg_trace(GF_NFS, 0, "Mknod: %s", pathloc->path); + nfs_fop_handle_frame_create(frame, nfsx, nfu, ret, err); + nfs_fop_handle_local_init(frame, nfsx, nfl, cbk, local, ret, err); + nfs_fop_save_root_ino(nfl, pathloc); + nfs_fop_gfid_setup(nfl, pathloc->inode, ret, err); + + STACK_WIND_COOKIE(frame, nfs_fop_mknod_cbk, xl, xl, xl->fops->mknod, + pathloc, mode, dev, 0, nfl->dictgfid); + ret = 0; +err: + if (ret < 0) { + if (frame) + nfs_stack_destroy(nfl, frame); + } + + return ret; +} + +int32_t +nfs_fop_rmdir_cbk(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, struct iatt *preparent, + struct iatt *postparent, dict_t *xdata) +{ + struct nfs_fop_local *nfl = frame->local; + fop_rmdir_cbk_t progcbk = NULL; + + nfl_to_prog_data(nfl, progcbk, frame); + nfs_fop_restore_root_ino(nfl, op_ret, NULL, NULL, preparent, postparent); + if (progcbk) + progcbk(frame, cookie, this, op_ret, op_errno, preparent, postparent, + NULL); + nfs_stack_destroy(nfl, frame); + return 0; +} + +int +nfs_fop_rmdir(xlator_t *nfsx, xlator_t *xl, nfs_user_t *nfu, loc_t *pathloc, + fop_rmdir_cbk_t cbk, void *local) +{ + call_frame_t *frame = NULL; + int ret = -EFAULT; + struct nfs_fop_local *nfl = NULL; + + if ((!nfsx) || (!xl) || (!pathloc) || (!nfu)) + return ret; + + gf_msg_trace(GF_NFS, 0, "Rmdir: %s", pathloc->path); + nfs_fop_handle_frame_create(frame, nfsx, nfu, ret, err); + nfs_fop_handle_local_init(frame, nfsx, nfl, cbk, local, ret, err); + nfs_fop_save_root_ino(nfl, pathloc); + + STACK_WIND_COOKIE(frame, nfs_fop_rmdir_cbk, xl, xl, xl->fops->rmdir, + pathloc, 0, NULL); + ret = 0; +err: + if (ret < 0) { + if (frame) + nfs_stack_destroy(nfl, frame); + } + + return ret; +} + +int32_t +nfs_fop_unlink_cbk(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, struct iatt *preparent, + struct iatt *postparent, dict_t *xdata) +{ + struct nfs_fop_local *nfl = frame->local; + fop_unlink_cbk_t progcbk = NULL; + + nfl_to_prog_data(nfl, progcbk, frame); + nfs_fop_restore_root_ino(nfl, op_ret, NULL, NULL, preparent, postparent); + if (progcbk) + progcbk(frame, cookie, this, op_ret, op_errno, preparent, postparent, + xdata); + nfs_stack_destroy(nfl, frame); + return 0; +} + +int +nfs_fop_unlink(xlator_t *nfsx, xlator_t *xl, nfs_user_t *nfu, loc_t *pathloc, + fop_unlink_cbk_t cbk, void *local) +{ + call_frame_t *frame = NULL; + int ret = -EFAULT; + struct nfs_fop_local *nfl = NULL; + + if ((!nfsx) || (!xl) || (!pathloc) || (!nfu)) + return ret; + + gf_msg_trace(GF_NFS, 0, "Unlink: %s", pathloc->path); + nfs_fop_handle_frame_create(frame, nfsx, nfu, ret, err); + nfs_fop_handle_local_init(frame, nfsx, nfl, cbk, local, ret, err); + nfs_fop_save_root_ino(nfl, pathloc); + + STACK_WIND_COOKIE(frame, nfs_fop_unlink_cbk, xl, xl, xl->fops->unlink, + pathloc, 0, NULL); + ret = 0; +err: + if (ret < 0) { + if (frame) + nfs_stack_destroy(nfl, frame); + } + + return ret; +} + +int32_t +nfs_fop_link_cbk(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, inode_t *inode, + struct iatt *buf, struct iatt *preparent, + struct iatt *postparent, dict_t *xdata) +{ + struct nfs_fop_local *nfl = NULL; + fop_link_cbk_t progcbk = NULL; + + if (op_ret == 0) { + nfs_fix_generation(this, inode); + } + + nfl_to_prog_data(nfl, progcbk, frame); + nfs_fop_restore_root_ino(nfl, op_ret, buf, NULL, preparent, postparent); + if (progcbk) + progcbk(frame, cookie, this, op_ret, op_errno, inode, buf, preparent, + postparent, xdata); + + nfs_stack_destroy(nfl, frame); + return 0; +} + +int +nfs_fop_link(xlator_t *nfsx, xlator_t *xl, nfs_user_t *nfu, loc_t *oldloc, + loc_t *newloc, fop_link_cbk_t cbk, void *local) +{ + call_frame_t *frame = NULL; + int ret = -EFAULT; + struct nfs_fop_local *nfl = NULL; + + if ((!nfsx) || (!xl) || (!oldloc) || (!newloc) || (!nfu)) + return ret; + + gf_msg_trace(GF_NFS, 0, "Link: %s -> %s", newloc->path, oldloc->path); + nfs_fop_handle_frame_create(frame, nfsx, nfu, ret, err); + nfs_fop_handle_local_init(frame, nfsx, nfl, cbk, local, ret, err); + nfs_fop_save_root_ino(nfl, newloc); + + STACK_WIND_COOKIE(frame, nfs_fop_link_cbk, xl, xl, xl->fops->link, oldloc, + newloc, NULL); + ret = 0; +err: + if (ret < 0) { + if (frame) + nfs_stack_destroy(nfl, frame); + } + + return ret; +} + +int32_t +nfs_fop_rename_cbk(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, struct iatt *buf, + struct iatt *preoldparent, struct iatt *postoldparent, + struct iatt *prenewparent, struct iatt *postnewparent, + dict_t *xdata) +{ + struct nfs_fop_local *nfl = NULL; + fop_rename_cbk_t progcbk = NULL; + + nfl_to_prog_data(nfl, progcbk, frame); + /* The preattr arg needs to be NULL instead of @buf because it is + * possible that the new parent is not root whereas the source dir + * could have been. That is handled in the next macro. + */ + nfs_fop_restore_root_ino(nfl, op_ret, NULL, NULL, preoldparent, + postoldparent); + nfs_fop_newloc_restore_root_ino(nfl, op_ret, buf, NULL, prenewparent, + postnewparent); + if (progcbk) + progcbk(frame, cookie, this, op_ret, op_errno, buf, preoldparent, + postoldparent, prenewparent, postnewparent, xdata); + nfs_stack_destroy(nfl, frame); + return 0; +} + +int +nfs_fop_rename(xlator_t *nfsx, xlator_t *xl, nfs_user_t *nfu, loc_t *oldloc, + loc_t *newloc, fop_rename_cbk_t cbk, void *local) +{ + call_frame_t *frame = NULL; + int ret = -EFAULT; + struct nfs_fop_local *nfl = NULL; + + if ((!nfsx) || (!xl) || (!oldloc) || (!newloc) || (!nfu)) + return ret; + + gf_msg_trace(GF_NFS, 0, "Rename: %s -> %s", oldloc->path, newloc->path); + nfs_fop_handle_frame_create(frame, nfsx, nfu, ret, err); + nfs_fop_handle_local_init(frame, nfsx, nfl, cbk, local, ret, err); + nfs_fop_save_root_ino(nfl, oldloc); + nfs_fop_newloc_save_root_ino(nfl, newloc); + + STACK_WIND_COOKIE(frame, nfs_fop_rename_cbk, xl, xl, xl->fops->rename, + oldloc, newloc, NULL); + ret = 0; +err: + if (ret < 0) { + if (frame) + nfs_stack_destroy(nfl, frame); + } + + return ret; +} + +int32_t +nfs_fop_open_cbk(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, fd_t *fd, dict_t *xdata) +{ + struct nfs_fop_local *nfl = NULL; + fop_open_cbk_t progcbk = NULL; + + nfl_to_prog_data(nfl, progcbk, frame); + if (progcbk) + progcbk(frame, cookie, this, op_ret, op_errno, fd, xdata); + nfs_stack_destroy(nfl, frame); + + return 0; +} + +int +nfs_fop_open(xlator_t *nfsx, xlator_t *xl, nfs_user_t *nfu, loc_t *loc, + int32_t flags, fd_t *fd, fop_open_cbk_t cbk, void *local) +{ + call_frame_t *frame = NULL; + int ret = -EFAULT; + struct nfs_fop_local *nfl = NULL; + + if ((!nfsx) || (!xl) || (!loc) || (!fd) || (!nfu)) + return ret; + + gf_msg_trace(GF_NFS, 0, "Open: %s", loc->path); + nfs_fop_handle_frame_create(frame, nfsx, nfu, ret, err); + nfs_fop_handle_local_init(frame, nfsx, nfl, cbk, local, ret, err); + + STACK_WIND_COOKIE(frame, nfs_fop_open_cbk, xl, xl, xl->fops->open, loc, + flags, fd, NULL); + ret = 0; +err: + if (ret < 0) { + if (frame) + nfs_stack_destroy(nfl, frame); + } + + return ret; +} + +int32_t +nfs_fop_writev_cbk(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, struct iatt *prebuf, + struct iatt *postbuf, dict_t *xdata) +{ + struct nfs_fop_local *nfl = NULL; + fop_writev_cbk_t progcbk = NULL; + + nfl_to_prog_data(nfl, progcbk, frame); + nfs_fop_restore_root_ino(nfl, op_ret, prebuf, postbuf, NULL, NULL); + if (progcbk) + progcbk(frame, cookie, this, op_ret, op_errno, prebuf, postbuf, xdata); + + nfs_stack_destroy(nfl, frame); + + return 0; +} + +int +nfs_fop_write(xlator_t *nfsx, xlator_t *xl, nfs_user_t *nfu, fd_t *fd, + struct iobref *srciobref, struct iovec *vector, int32_t count, + off_t offset, fop_writev_cbk_t cbk, void *local) +{ + call_frame_t *frame = NULL; + int ret = -EFAULT; + struct nfs_fop_local *nfl = NULL; + int flags = 0; + nfs3_call_state_t *cs = local; + + if ((!nfsx) || (!xl) || (!fd) || (!vector) || (!nfu) || (!srciobref)) + return ret; + + nfs_fop_handle_frame_create(frame, nfsx, nfu, ret, err); + nfs_fop_handle_local_init(frame, nfsx, nfl, cbk, local, ret, err); + nfs_fop_save_root_fd_ino(nfl, fd); + /* + nfl->iobref = iobref_new (); + if (!nfl->iobref) { + gf_log (GF_NFS, GF_LOG_ERROR, "iobref creation failed"); + ret = -ENOMEM; + goto err; + } + + iobref_add (nfl->iobref, srciob); + */ + + switch (cs->writetype) { + case UNSTABLE: + break; + case DATA_SYNC: + flags |= O_DSYNC; + break; + case FILE_SYNC: + flags |= O_SYNC; + break; + } + + STACK_WIND_COOKIE(frame, nfs_fop_writev_cbk, xl, xl, xl->fops->writev, fd, + vector, count, offset, flags, srciobref, NULL); + ret = 0; +err: + if (ret < 0) { + if (frame) + nfs_stack_destroy(nfl, frame); + } + + return ret; +} + +int32_t +nfs_fop_fsync_cbk(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, struct iatt *prebuf, + struct iatt *postbuf, dict_t *xdata) +{ + struct nfs_fop_local *nfl = NULL; + fop_fsync_cbk_t progcbk = NULL; + + nfl_to_prog_data(nfl, progcbk, frame); + nfs_fop_restore_root_ino(nfl, op_ret, prebuf, postbuf, NULL, NULL); + if (progcbk) + progcbk(frame, cookie, this, op_ret, op_errno, prebuf, postbuf, xdata); + + nfs_stack_destroy(nfl, frame); + return 0; +} + +int +nfs_fop_fsync(xlator_t *nfsx, xlator_t *xl, nfs_user_t *nfu, fd_t *fd, + int32_t datasync, fop_fsync_cbk_t cbk, void *local) +{ + call_frame_t *frame = NULL; + int ret = -EFAULT; + struct nfs_fop_local *nfl = NULL; + + if ((!nfsx) || (!xl) || (!fd)) + return ret; + + nfs_fop_handle_frame_create(frame, nfsx, nfu, ret, err); + nfs_fop_handle_local_init(frame, nfsx, nfl, cbk, local, ret, err); + nfs_fop_save_root_fd_ino(nfl, fd); + + STACK_WIND_COOKIE(frame, nfs_fop_fsync_cbk, xl, xl, xl->fops->fsync, fd, + datasync, NULL); + ret = 0; +err: + if (ret < 0) { + if (frame) + nfs_stack_destroy(nfl, frame); + } + + return ret; +} + +int32_t +nfs_fop_readv_cbk(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, struct iovec *vector, + int32_t count, struct iatt *stbuf, struct iobref *iobref, + dict_t *xdata) +{ + struct nfs_fop_local *nfl = NULL; + fop_readv_cbk_t progcbk = NULL; + + nfl_to_prog_data(nfl, progcbk, frame); + nfs_fop_restore_root_ino(nfl, op_ret, stbuf, NULL, NULL, NULL); + if (progcbk) + progcbk(frame, cookie, this, op_ret, op_errno, vector, count, stbuf, + iobref, xdata); + + nfs_stack_destroy(nfl, frame); + return 0; +} + +int +nfs_fop_read(xlator_t *nfsx, xlator_t *xl, nfs_user_t *nfu, fd_t *fd, + size_t size, off_t offset, fop_readv_cbk_t cbk, void *local) +{ + call_frame_t *frame = NULL; + int ret = -EFAULT; + struct nfs_fop_local *nfl = NULL; + + if ((!xl) || (!fd) || (!nfu)) + return ret; + + nfs_fop_handle_frame_create(frame, nfsx, nfu, ret, err); + nfs_fop_handle_local_init(frame, nfsx, nfl, cbk, local, ret, err); + nfs_fop_save_root_fd_ino(nfl, fd); + + STACK_WIND_COOKIE(frame, nfs_fop_readv_cbk, xl, xl, xl->fops->readv, fd, + size, offset, 0, NULL); + ret = 0; +err: + if (ret < 0) { + if (frame) + nfs_stack_destroy(nfl, frame); + } + + return ret; +} + +int32_t +nfs_fop_lk_cbk(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, struct gf_flock *flock, + dict_t *xdata) +{ + struct nfs_fop_local *nfl = NULL; + fop_lk_cbk_t progcbk = NULL; + + nfl_to_prog_data(nfl, progcbk, frame); + + if (!op_ret) + fd_lk_insert_and_merge(nfl->fd, nfl->cmd, &nfl->flock); + + fd_unref(nfl->fd); + + if (progcbk) + progcbk(frame, cookie, this, op_ret, op_errno, flock, xdata); + + nfs_stack_destroy(nfl, frame); + return 0; +} + +int +nfs_fop_lk(xlator_t *nfsx, xlator_t *xl, nfs_user_t *nfu, fd_t *fd, int cmd, + struct gf_flock *flock, fop_lk_cbk_t cbk, void *local) +{ + call_frame_t *frame = NULL; + int ret = -EFAULT; + struct nfs_fop_local *nfl = NULL; + + if ((!xl) || (!fd) || (!nfu)) + return ret; + + nfs_fop_handle_frame_create(frame, nfsx, nfu, ret, err); + nfs_fop_handle_local_init(frame, nfsx, nfl, cbk, local, ret, err); + + nfl->cmd = cmd; + nfl->fd = fd_ref(fd); + nfl->flock = *flock; + + STACK_WIND_COOKIE(frame, nfs_fop_lk_cbk, xl, xl, xl->fops->lk, fd, cmd, + flock, NULL); + ret = 0; +err: + if (ret < 0) { + if (frame) + nfs_stack_destroy(nfl, frame); + } + + return ret; +} + +int32_t +nfs_fop_getxattr_cbk(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, dict_t *dict, + dict_t *xdata) +{ + struct nfs_fop_local *nfl = NULL; + fop_getxattr_cbk_t progcbk = NULL; + + nfl_to_prog_data(nfl, progcbk, frame); + + if (progcbk) + progcbk(frame, cookie, this, op_ret, op_errno, dict, xdata); + + nfs_stack_destroy(nfl, frame); + return 0; +} + +int +nfs_fop_getxattr(xlator_t *nfsx, xlator_t *xl, nfs_user_t *nfu, loc_t *loc, + char *name, dict_t *xdata, fop_getxattr_cbk_t cbk, void *local) +{ + call_frame_t *frame = NULL; + int ret = -EFAULT; + struct nfs_fop_local *nfl = NULL; + + if ((!xl) || (!loc) || (!nfu)) + return ret; + + nfs_fop_handle_frame_create(frame, nfsx, nfu, ret, err); + nfs_fop_handle_local_init(frame, nfsx, nfl, cbk, local, ret, err); + + STACK_WIND_COOKIE(frame, nfs_fop_getxattr_cbk, xl, xl, xl->fops->getxattr, + loc, name, NULL); + ret = 0; +err: + if (ret < 0) { + if (frame) + nfs_stack_destroy(nfl, frame); + } + + return ret; +} + +int32_t +nfs_fop_setxattr_cbk(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, dict_t *xdata) +{ + struct nfs_fop_local *nfl = NULL; + fop_setxattr_cbk_t progcbk = NULL; + + nfl_to_prog_data(nfl, progcbk, frame); + + if (progcbk) + progcbk(frame, cookie, this, op_ret, op_errno, xdata); + + nfs_stack_destroy(nfl, frame); + return 0; +} + +int +nfs_fop_setxattr(xlator_t *nfsx, xlator_t *xl, nfs_user_t *nfu, loc_t *loc, + dict_t *dict, int32_t flags, dict_t *xdata, + fop_setxattr_cbk_t cbk, void *local) +{ + call_frame_t *frame = NULL; + int ret = -EFAULT; + struct nfs_fop_local *nfl = NULL; + + if ((!xl) || (!loc) || (!nfu)) + return ret; + + nfs_fop_handle_frame_create(frame, nfsx, nfu, ret, err); + nfs_fop_handle_local_init(frame, nfsx, nfl, cbk, local, ret, err); + + STACK_WIND_COOKIE(frame, nfs_fop_setxattr_cbk, xl, xl, xl->fops->setxattr, + loc, dict, flags, xdata); + ret = 0; +err: + if (ret < 0) { + if (frame) + nfs_stack_destroy(nfl, frame); + } + + return ret; +} + +int32_t +nfs_fop_truncate_cbk(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, struct iatt *prebuf, + struct iatt *postbuf, dict_t *xdata) +{ + struct nfs_fop_local *nfl = NULL; + fop_truncate_cbk_t progcbk = NULL; + + nfl_to_prog_data(nfl, progcbk, frame); + nfs_fop_restore_root_ino(nfl, op_ret, prebuf, postbuf, NULL, NULL); + if (progcbk) + progcbk(frame, cookie, this, op_ret, op_errno, prebuf, postbuf, xdata); + + nfs_stack_destroy(nfl, frame); + return 0; +} + +int +nfs_fop_truncate(xlator_t *nfsx, xlator_t *xl, nfs_user_t *nfu, loc_t *loc, + off_t offset, fop_truncate_cbk_t cbk, void *local) +{ + call_frame_t *frame = NULL; + int ret = -EFAULT; + struct nfs_fop_local *nfl = NULL; + + if ((!nfsx) || (!xl) || (!loc) || (!nfu)) + return ret; + + nfs_fop_handle_frame_create(frame, nfsx, nfu, ret, err); + nfs_fop_handle_local_init(frame, nfsx, nfl, cbk, local, ret, err); + nfs_fop_save_root_ino(nfl, loc); + + STACK_WIND_COOKIE(frame, nfs_fop_truncate_cbk, xl, xl, xl->fops->truncate, + loc, offset, NULL); + + ret = 0; +err: + if (ret < 0) { + if (frame) + nfs_stack_destroy(nfl, frame); + } + + return ret; +} |
