summaryrefslogtreecommitdiffstats
path: root/xlators/features/upcall/src/upcall.c
diff options
context:
space:
mode:
authorSoumya Koduri <skoduri@redhat.com>2015-02-15 23:35:56 +0530
committerKaleb KEITHLEY <kkeithle@redhat.com>2015-03-17 05:08:07 -0700
commit2b97b57cd8c71cb07b7002cf3483e9cfc9403c58 (patch)
tree9fc96451b469e213348f3065ca07e7a7c5a96ec0 /xlators/features/upcall/src/upcall.c
parent79009691c01f2b32b523d91a159aadd0e414f31b (diff)
Upcall: New xlator to store various states and send cbk events
Framework on the server-side, to handle certain state of the files accessed and send notifications to the clients connected. A generic and extensible framework, used to maintain states in the glusterfsd process for each of the files accessed (including the clients info doing the fops) and send notifications to the respective glusterfs clients incase of any change in that state. This patch handles "Inode Update/Invalidation" upcall event. Feature page: URL: http://www.gluster.org/community/documentation/index.php/Features/Upcall-infrastructure Below link has a writeup which explains the code changes done - URL: https://soumyakoduri.wordpress.com/2015/02/25/glusterfs-understanding-upcall-infrastructure-and-cache-invalidation-support/ Change-Id: Ie3d724be9a3419fcf18901a753e8ec2df2ac802f BUG: 1200262 Signed-off-by: Soumya Koduri <skoduri@redhat.com> Reviewed-on: http://review.gluster.org/9535 Reviewed-by: Kaleb KEITHLEY <kkeithle@redhat.com> Tested-by: Gluster Build System <jenkins@build.gluster.com>
Diffstat (limited to 'xlators/features/upcall/src/upcall.c')
-rw-r--r--xlators/features/upcall/src/upcall.c956
1 files changed, 956 insertions, 0 deletions
diff --git a/xlators/features/upcall/src/upcall.c b/xlators/features/upcall/src/upcall.c
new file mode 100644
index 00000000000..b7f2e975bba
--- /dev/null
+++ b/xlators/features/upcall/src/upcall.c
@@ -0,0 +1,956 @@
+/*
+ Copyright (c) 2015 Red Hat, Inc. <http://www.redhat.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 <unistd.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <pthread.h>
+
+#ifndef _CONFIG_H
+#define _CONFIG_H
+#include "config.h"
+#endif
+
+#include "glusterfs.h"
+#include "compat.h"
+#include "xlator.h"
+#include "inode.h"
+#include "logging.h"
+#include "common-utils.h"
+
+#include "statedump.h"
+#include "syncop.h"
+
+#include "upcall.h"
+#include "upcall-mem-types.h"
+#include "glusterfs3-xdr.h"
+#include "protocol-common.h"
+#include "defaults.h"
+
+int
+up_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)
+{
+ client_t *client = NULL;
+ uint32_t flags = 0;
+ upcall_local_t *local = NULL;
+
+ EXIT_IF_UPCALL_OFF (out);
+
+ client = frame->root->client;
+ local = frame->local;
+
+ if ((op_ret < 0) || !local) {
+ goto out;
+ }
+ flags = UP_IDEMPOTENT_FLAGS;
+ CACHE_INVALIDATE (frame, this, client, local->inode, flags);
+
+out:
+ UPCALL_STACK_UNWIND (open, frame, op_ret, op_errno, fd, xdata);
+
+ return 0;
+}
+
+
+int
+up_open (call_frame_t *frame, xlator_t *this, loc_t *loc, int32_t flags,
+ fd_t *fd, dict_t *xdata)
+{
+ int32_t op_errno = -1;
+ upcall_local_t *local = NULL;
+
+ EXIT_IF_UPCALL_OFF (out);
+
+ local = upcall_local_init (frame, this, fd->inode);
+ if (!local) {
+ op_errno = ENOMEM;
+ goto err;
+ }
+
+out:
+ STACK_WIND (frame, up_open_cbk,
+ FIRST_CHILD(this), FIRST_CHILD(this)->fops->open,
+ loc, flags, fd, xdata);
+
+ return 0;
+
+err:
+ op_errno = (op_errno == -1) ? errno : op_errno;
+ UPCALL_STACK_UNWIND (open, frame, -1, op_errno, NULL, NULL);
+
+ return 0;
+}
+
+int
+up_writev_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
+ int op_ret, int op_errno, struct iatt *prebuf,
+ struct iatt *postbuf, dict_t *xdata)
+{
+ client_t *client = NULL;
+ uint32_t flags = 0;
+ upcall_local_t *local = NULL;
+
+ client = frame->root->client;
+ local = frame->local;
+
+ if ((op_ret < 0) || !local) {
+ goto out;
+ }
+ flags = UP_WRITE_FLAGS;
+ CACHE_INVALIDATE (frame, this, client, local->inode, flags);
+
+out:
+ UPCALL_STACK_UNWIND (writev, frame, op_ret, op_errno,
+ prebuf, postbuf, xdata);
+
+ return 0;
+}
+
+
+int
+up_writev (call_frame_t *frame, xlator_t *this, fd_t *fd,
+ struct iovec *vector, int count, off_t off, uint32_t flags,
+ struct iobref *iobref, dict_t *xdata)
+{
+ int32_t op_errno = -1;
+ upcall_local_t *local = NULL;
+
+ EXIT_IF_UPCALL_OFF (out);
+
+ local = upcall_local_init (frame, this, fd->inode);
+ if (!local) {
+ op_errno = ENOMEM;
+ goto err;
+ }
+
+out:
+ STACK_WIND (frame, up_writev_cbk,
+ FIRST_CHILD(this), FIRST_CHILD(this)->fops->writev,
+ fd, vector, count, off, flags, iobref, xdata);
+
+ return 0;
+
+err:
+ op_errno = (op_errno == -1) ? errno : op_errno;
+ op_errno = (op_errno == -1) ? errno : op_errno;
+ UPCALL_STACK_UNWIND (writev, frame, -1, op_errno, NULL, NULL, NULL);
+
+ return 0;
+}
+
+
+int
+up_readv_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
+ int op_ret, int op_errno,
+ struct iovec *vector, int count, struct iatt *stbuf,
+ struct iobref *iobref, dict_t *xdata)
+{
+ client_t *client = NULL;
+ uint32_t flags = 0;
+ upcall_local_t *local = NULL;
+
+ EXIT_IF_UPCALL_OFF (out);
+
+ client = frame->root->client;
+ local = frame->local;
+
+ if ((op_ret < 0) || !local) {
+ goto out;
+ }
+ flags = UP_IDEMPOTENT_FLAGS;
+ CACHE_INVALIDATE (frame, this, client, local->inode, flags);
+
+out:
+ UPCALL_STACK_UNWIND (readv, frame, op_ret, op_errno, vector,
+ count, stbuf, iobref, xdata);
+
+ return 0;
+}
+
+int
+up_readv (call_frame_t *frame, xlator_t *this,
+ fd_t *fd, size_t size, off_t offset,
+ uint32_t flags, dict_t *xdata)
+{
+ int32_t op_errno = -1;
+ upcall_local_t *local = NULL;
+
+ EXIT_IF_UPCALL_OFF (out);
+
+ local = upcall_local_init (frame, this, fd->inode);
+ if (!local) {
+ op_errno = ENOMEM;
+ goto err;
+ }
+
+out:
+ STACK_WIND (frame, up_readv_cbk,
+ FIRST_CHILD(this), FIRST_CHILD(this)->fops->readv,
+ fd, size, offset, flags, xdata);
+
+ return 0;
+
+err:
+ op_errno = (op_errno == -1) ? errno : op_errno;
+ UPCALL_STACK_UNWIND (readv, frame, -1, op_errno, NULL, 0,
+ NULL, NULL, NULL);
+
+ return 0;
+}
+
+int32_t
+up_lk_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
+ int32_t op_ret, int32_t op_errno, struct gf_flock *lock,
+ dict_t *xdata)
+{
+ client_t *client = NULL;
+ uint32_t flags = 0;
+ upcall_local_t *local = NULL;
+
+ EXIT_IF_UPCALL_OFF (out);
+
+ client = frame->root->client;
+ local = frame->local;
+
+ if ((op_ret < 0) || !local) {
+ goto out;
+ }
+ flags = UP_IDEMPOTENT_FLAGS;
+ CACHE_INVALIDATE (frame, this, client, local->inode, flags);
+
+out:
+ UPCALL_STACK_UNWIND (lk, frame, op_ret, op_errno, lock, xdata);
+
+ return 0;
+}
+
+int
+up_lk (call_frame_t *frame, xlator_t *this,
+ fd_t *fd, int32_t cmd, struct gf_flock *flock, dict_t *xdata)
+{
+ int32_t op_errno = -1;
+ upcall_local_t *local = NULL;
+
+ EXIT_IF_UPCALL_OFF (out);
+
+ local = upcall_local_init (frame, this, fd->inode);
+ if (!local) {
+ op_errno = ENOMEM;
+ goto err;
+ }
+
+out:
+ STACK_WIND (frame, up_lk_cbk, FIRST_CHILD(this),
+ FIRST_CHILD(this)->fops->lk,
+ fd, cmd, flock, xdata);
+ return 0;
+
+err:
+ op_errno = (op_errno == -1) ? errno : op_errno;
+ UPCALL_STACK_UNWIND (lk, frame, -1, op_errno, NULL, NULL);
+
+ return 0;
+}
+
+int
+up_truncate_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
+ int op_ret, int op_errno, struct iatt *prebuf,
+ struct iatt *postbuf, dict_t *xdata)
+{
+ client_t *client = NULL;
+ uint32_t flags = 0;
+ upcall_local_t *local = NULL;
+
+ EXIT_IF_UPCALL_OFF (out);
+
+ client = frame->root->client;
+ local = frame->local;
+
+ if ((op_ret < 0) || !local) {
+ goto out;
+ }
+ flags = UP_WRITE_FLAGS;
+ CACHE_INVALIDATE (frame, this, client, local->inode, flags);
+
+out:
+ UPCALL_STACK_UNWIND (truncate, frame, op_ret, op_errno,
+ prebuf, postbuf, xdata);
+
+ return 0;
+}
+
+int
+up_truncate (call_frame_t *frame, xlator_t *this, loc_t *loc, off_t offset,
+ dict_t *xdata)
+{
+ int32_t op_errno = -1;
+ upcall_local_t *local = NULL;
+
+ EXIT_IF_UPCALL_OFF (out);
+
+ local = upcall_local_init (frame, this, loc->inode);
+ if (!local) {
+ op_errno = ENOMEM;
+ goto err;
+ }
+
+out:
+ STACK_WIND (frame, up_truncate_cbk,
+ FIRST_CHILD(this), FIRST_CHILD(this)->fops->truncate,
+ loc, offset, xdata);
+
+ return 0;
+
+err:
+ op_errno = (op_errno == -1) ? errno : op_errno;
+ UPCALL_STACK_UNWIND (truncate, frame, -1, op_errno, NULL, NULL, NULL);
+
+ return 0;
+}
+
+int
+up_setattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
+ int op_ret, int op_errno, struct iatt *statpre,
+ struct iatt *statpost, dict_t *xdata)
+{
+ client_t *client = NULL;
+ uint32_t flags = 0;
+ upcall_local_t *local = NULL;
+
+ EXIT_IF_UPCALL_OFF (out);
+
+ client = frame->root->client;
+ local = frame->local;
+
+ if ((op_ret < 0) || !local) {
+ goto out;
+ }
+ /* XXX: setattr -> UP_SIZE or UP_OWN or UP_MODE or UP_TIMES
+ * or INODE_UPDATE (or UP_PERM esp incase of ACLs -> INODE_INVALIDATE)
+ * Need to check what attr is changed and accordingly pass UP_FLAGS.
+ * Bug1200271.
+ */
+ flags = UP_ATTR_FLAGS;
+ CACHE_INVALIDATE (frame, this, client, local->inode, flags);
+
+out:
+ UPCALL_STACK_UNWIND (setattr, frame, op_ret, op_errno,
+ statpre, statpost, xdata);
+
+ return 0;
+}
+
+int
+up_setattr (call_frame_t *frame, xlator_t *this, loc_t *loc,
+ struct iatt *stbuf, int32_t valid, dict_t *xdata)
+{
+ int32_t op_errno = -1;
+ upcall_local_t *local = NULL;
+
+ EXIT_IF_UPCALL_OFF (out);
+
+ local = upcall_local_init (frame, this, loc->inode);
+ if (!local) {
+ op_errno = ENOMEM;
+ goto err;
+ }
+
+out:
+ STACK_WIND (frame, up_setattr_cbk,
+ FIRST_CHILD(this),
+ FIRST_CHILD(this)->fops->setattr,
+ loc, stbuf, valid, xdata);
+
+ return 0;
+
+err:
+ op_errno = (op_errno == -1) ? errno : op_errno;
+ UPCALL_STACK_UNWIND (setattr, frame, -1, op_errno, NULL, NULL, NULL);
+
+ return 0;
+}
+
+int
+up_rename_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
+ int32_t op_ret, int32_t op_errno, struct iatt *stbuf,
+ struct iatt *preoldparent, struct iatt *postoldparent,
+ struct iatt *prenewparent, struct iatt *postnewparent,
+ dict_t *xdata)
+{
+ client_t *client = NULL;
+ uint32_t flags = 0;
+ upcall_local_t *local = NULL;
+
+ EXIT_IF_UPCALL_OFF (out);
+
+ client = frame->root->client;
+ local = frame->local;
+
+ if ((op_ret < 0) || !local) {
+ goto out;
+ }
+ flags = UP_RENAME_FLAGS;
+ CACHE_INVALIDATE (frame, this, client, local->inode, flags);
+
+ /* Need to invalidate old and new parent entries as well */
+ flags = UP_PARENT_DENTRY_FLAGS;
+ CACHE_INVALIDATE_DIR (frame, this, client, local->inode, flags);
+
+ /* XXX: notify oldparent as well */
+/* if (uuid_compare (preoldparent->ia_gfid, prenewparent->ia_gfid))
+ CACHE_INVALIDATE (frame, this, client, prenewparent->ia_gfid, flags);*/
+
+out:
+ UPCALL_STACK_UNWIND (rename, frame, op_ret, op_errno,
+ stbuf, preoldparent, postoldparent,
+ prenewparent, postnewparent, xdata);
+
+ return 0;
+}
+
+int
+up_rename (call_frame_t *frame, xlator_t *this,
+ loc_t *oldloc, loc_t *newloc, dict_t *xdata)
+{
+ int32_t op_errno = -1;
+ upcall_local_t *local = NULL;
+
+ EXIT_IF_UPCALL_OFF (out);
+
+ local = upcall_local_init (frame, this, oldloc->inode);
+ if (!local) {
+ op_errno = ENOMEM;
+ goto err;
+ }
+
+out:
+ STACK_WIND (frame, up_rename_cbk,
+ FIRST_CHILD(this), FIRST_CHILD(this)->fops->rename,
+ oldloc, newloc, xdata);
+
+ return 0;
+
+err:
+ op_errno = (op_errno == -1) ? errno : op_errno;
+ UPCALL_STACK_UNWIND (rename, frame, -1, op_errno, NULL,
+ NULL, NULL, NULL, NULL, NULL);
+
+ return 0;
+}
+
+int
+up_unlink_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
+ int op_ret, int op_errno, struct iatt *preparent,
+ struct iatt *postparent, dict_t *xdata)
+{
+ client_t *client = NULL;
+ uint32_t flags = 0;
+ upcall_local_t *local = NULL;
+
+ EXIT_IF_UPCALL_OFF (out);
+
+ client = frame->root->client;
+ local = frame->local;
+
+ if ((op_ret < 0) || !local) {
+ goto out;
+ }
+ flags = UP_NLINK_FLAGS;
+ CACHE_INVALIDATE (frame, this, client, local->inode, flags);
+
+ flags = UP_PARENT_DENTRY_FLAGS;
+ /* invalidate parent's entry too */
+ CACHE_INVALIDATE_DIR (frame, this, client, local->inode, flags);
+
+out:
+ UPCALL_STACK_UNWIND (unlink, frame, op_ret, op_errno,
+ preparent, postparent, xdata);
+
+ return 0;
+}
+
+int
+up_unlink (call_frame_t *frame, xlator_t *this, loc_t *loc, int xflag,
+ dict_t *xdata)
+{
+ int32_t op_errno = -1;
+ upcall_local_t *local = NULL;
+
+ EXIT_IF_UPCALL_OFF (out);
+
+ local = upcall_local_init (frame, this, loc->inode);
+ if (!local) {
+ op_errno = ENOMEM;
+ goto err;
+ }
+
+out:
+ STACK_WIND (frame, up_unlink_cbk,
+ FIRST_CHILD(this), FIRST_CHILD(this)->fops->unlink,
+ loc, xflag, xdata);
+
+ return 0;
+
+err:
+ op_errno = (op_errno == -1) ? errno : op_errno;
+ UPCALL_STACK_UNWIND (unlink, frame, -1, op_errno, NULL, NULL, NULL);
+
+ return 0;
+}
+
+int
+up_link_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
+ int op_ret, int op_errno, inode_t *inode, struct iatt *stbuf,
+ struct iatt *preparent, struct iatt *postparent, dict_t *xdata)
+{
+ client_t *client = NULL;
+ uint32_t flags = 0;
+ upcall_local_t *local = NULL;
+
+ EXIT_IF_UPCALL_OFF (out);
+
+ client = frame->root->client;
+ local = frame->local;
+
+ if ((op_ret < 0) || !local) {
+ goto out;
+ }
+ flags = UP_NLINK_FLAGS;
+ CACHE_INVALIDATE (frame, this, client, local->inode, flags);
+
+ /* do we need to update parent as well?? */
+out:
+ UPCALL_STACK_UNWIND (link, frame, op_ret, op_errno,
+ inode, stbuf, preparent, postparent, xdata);
+
+ return 0;
+}
+
+int
+up_link (call_frame_t *frame, xlator_t *this, loc_t *oldloc,
+ loc_t *newloc, dict_t *xdata)
+{
+ int32_t op_errno = -1;
+ upcall_local_t *local = NULL;
+
+ EXIT_IF_UPCALL_OFF (out);
+
+ local = upcall_local_init (frame, this, oldloc->inode);
+ if (!local) {
+ op_errno = ENOMEM;
+ goto err;
+ }
+
+out:
+ STACK_WIND (frame, up_link_cbk,
+ FIRST_CHILD(this), FIRST_CHILD(this)->fops->link,
+ oldloc, newloc, xdata);
+
+ return 0;
+
+err:
+ op_errno = (op_errno == -1) ? errno : op_errno;
+ UPCALL_STACK_UNWIND (link, frame, -1, op_errno, NULL,
+ NULL, NULL, NULL, NULL);
+
+ return 0;
+}
+
+int
+up_rmdir_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
+ int op_ret, int op_errno, struct iatt *preparent,
+ struct iatt *postparent, dict_t *xdata)
+{
+ client_t *client = NULL;
+ uint32_t flags = 0;
+ upcall_local_t *local = NULL;
+
+ EXIT_IF_UPCALL_OFF (out);
+
+ client = frame->root->client;
+ local = frame->local;
+
+ if ((op_ret < 0) || !local) {
+ goto out;
+ }
+ flags = UP_NLINK_FLAGS;
+ CACHE_INVALIDATE (frame, this, client, local->inode, flags);
+
+ /* invalidate parent's entry too */
+ flags = UP_PARENT_DENTRY_FLAGS;
+ CACHE_INVALIDATE_DIR (frame, this, client, local->inode, flags);
+
+out:
+ UPCALL_STACK_UNWIND (rmdir, frame, op_ret, op_errno,
+ preparent, postparent, xdata);
+
+ return 0;
+}
+
+int
+up_rmdir (call_frame_t *frame, xlator_t *this, loc_t *loc, int flags,
+ dict_t *xdata)
+{
+ int32_t op_errno = -1;
+ upcall_local_t *local = NULL;
+
+ EXIT_IF_UPCALL_OFF (out);
+
+ local = upcall_local_init (frame, this, loc->inode);
+ if (!local) {
+ op_errno = ENOMEM;
+ goto err;
+ }
+
+out:
+ STACK_WIND (frame, up_rmdir_cbk,
+ FIRST_CHILD(this), FIRST_CHILD(this)->fops->rmdir,
+ loc, flags, xdata);
+
+ return 0;
+
+err:
+ op_errno = (op_errno == -1) ? errno : op_errno;
+ UPCALL_STACK_UNWIND (rmdir, frame, -1, op_errno, NULL, NULL, NULL);
+
+ return 0;
+}
+
+int
+up_mkdir_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
+ int op_ret, int op_errno, inode_t *inode,
+ struct iatt *stbuf, struct iatt *preparent,
+ struct iatt *postparent, dict_t *xdata)
+{
+ client_t *client = NULL;
+ uint32_t flags = 0;
+ upcall_local_t *local = NULL;
+
+ EXIT_IF_UPCALL_OFF (out);
+
+ client = frame->root->client;
+ local = frame->local;
+
+ if ((op_ret < 0) || !local) {
+ goto out;
+ }
+ flags = UP_NLINK_FLAGS;
+ CACHE_INVALIDATE (frame, this, client, local->inode, flags);
+
+ /* invalidate parent's entry too */
+ flags = UP_PARENT_DENTRY_FLAGS;
+ CACHE_INVALIDATE_DIR (frame, this, client, local->inode, flags);
+
+out:
+ UPCALL_STACK_UNWIND (mkdir, frame, op_ret, op_errno,
+ inode, stbuf, preparent, postparent, xdata);
+
+ return 0;
+}
+
+int
+up_mkdir (call_frame_t *frame, xlator_t *this,
+ loc_t *loc, mode_t mode, mode_t umask, dict_t *params)
+{
+ int32_t op_errno = -1;
+ upcall_local_t *local = NULL;
+
+ EXIT_IF_UPCALL_OFF (out);
+
+ local = upcall_local_init (frame, this, loc->inode);
+ if (!local) {
+ op_errno = ENOMEM;
+ goto err;
+ }
+
+out:
+ STACK_WIND (frame, up_mkdir_cbk,
+ FIRST_CHILD(this), FIRST_CHILD(this)->fops->mkdir,
+ loc, mode, umask, params);
+
+ return 0;
+
+err:
+ op_errno = (op_errno == -1) ? errno : op_errno;
+ UPCALL_STACK_UNWIND (mkdir, frame, -1, op_errno, NULL,
+ NULL, NULL, NULL, NULL);
+
+ return 0;
+}
+
+int
+up_create_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
+ int op_ret, int op_errno, fd_t *fd, inode_t *inode,
+ struct iatt *stbuf, struct iatt *preparent,
+ struct iatt *postparent, dict_t *xdata)
+{
+ client_t *client = NULL;
+ uint32_t flags = 0;
+ upcall_local_t *local = NULL;
+
+ EXIT_IF_UPCALL_OFF (out);
+
+ client = frame->root->client;
+ local = frame->local;
+
+ if ((op_ret < 0) || !local) {
+ goto out;
+ }
+
+ /* As its a new file create, no need of sending notification */
+ /* However invalidate parent's entry */
+ flags = UP_PARENT_DENTRY_FLAGS;
+ CACHE_INVALIDATE_DIR (frame, this, client, local->inode, flags);
+
+out:
+ UPCALL_STACK_UNWIND (create, frame, op_ret, op_errno, fd,
+ inode, stbuf, preparent, postparent, xdata);
+
+ return 0;
+}
+
+int
+up_create (call_frame_t *frame, xlator_t *this,
+ loc_t *loc, int32_t flags, mode_t mode,
+ mode_t umask, fd_t *fd, dict_t *params)
+{
+ int32_t op_errno = -1;
+ upcall_local_t *local = NULL;
+
+ EXIT_IF_UPCALL_OFF (out);
+
+ local = upcall_local_init (frame, this, loc->inode);
+
+ if (!local) {
+ op_errno = ENOMEM;
+ goto err;
+ }
+
+out:
+ STACK_WIND (frame, up_create_cbk,
+ FIRST_CHILD(this), FIRST_CHILD(this)->fops->create,
+ loc, flags, mode, umask, fd, params);
+
+ return 0;
+
+err:
+ op_errno = (op_errno == -1) ? errno : op_errno;
+ UPCALL_STACK_UNWIND (create, frame, -1, op_errno, NULL,
+ NULL, NULL, NULL, NULL, NULL);
+
+ return 0;
+}
+
+int32_t
+mem_acct_init (xlator_t *this)
+{
+ int ret = -1;
+
+ if (!this)
+ return ret;
+
+ ret = xlator_mem_acct_init (this, gf_upcall_mt_end + 1);
+
+ if (ret != 0) {
+ gf_msg ("upcall", GF_LOG_WARNING, 0,
+ UPCALL_MSG_NO_MEMORY,
+ "Memory allocation failed");
+ return ret;
+ }
+
+ return ret;
+}
+
+void
+upcall_local_wipe (xlator_t *this, upcall_local_t *local)
+{
+ if (local) {
+ inode_unref (local->inode);
+ mem_put (local);
+ }
+}
+
+upcall_local_t *
+upcall_local_init (call_frame_t *frame, xlator_t *this, inode_t *inode)
+{
+ upcall_local_t *local = NULL;
+
+ local = mem_get0 (THIS->local_pool);
+
+ if (!local)
+ goto out;
+
+ local->inode = inode_ref (inode);
+
+ /* Shall we get inode_ctx and store it here itself? */
+ local->upcall_inode_ctx = upcall_inode_ctx_get (inode, this);
+
+ frame->local = local;
+
+out:
+ return local;
+}
+
+int
+init (xlator_t *this)
+{
+ int ret = -1;
+ upcalls_private_t *priv = NULL;
+
+ priv = GF_CALLOC (1, sizeof (*priv),
+ gf_upcall_mt_private_t);
+ if (!priv) {
+ gf_msg ("upcall", GF_LOG_WARNING, 0,
+ UPCALL_MSG_NO_MEMORY,
+ "Memory allocation failed");
+ goto out;
+ }
+
+ this->private = priv;
+ this->local_pool = mem_pool_new (upcall_local_t, 512);
+ ret = 0;
+
+out:
+ if (ret) {
+ GF_FREE (priv);
+ }
+
+ return ret;
+}
+
+int
+fini (xlator_t *this)
+{
+ upcalls_private_t *priv = NULL;
+
+ priv = this->private;
+ if (!priv) {
+ return 0;
+ }
+ this->private = NULL;
+ GF_FREE (priv);
+
+ return 0;
+}
+
+int
+upcall_forget (xlator_t *this, inode_t *inode)
+{
+ upcall_cleanup_inode_ctx (this, inode);
+ return 0;
+}
+
+int
+upcall_release (xlator_t *this, fd_t *fd)
+{
+ return 0;
+}
+
+int
+notify (xlator_t *this, int32_t event, void *data, ...)
+{
+ int ret = -1;
+ int32_t val = 0;
+ notify_event_data_t *notify_event = NULL;
+ struct gf_upcall up_req = {0,};
+ upcall_client_t *up_client_entry = NULL;
+
+ switch (event) {
+ case GF_EVENT_UPCALL:
+ {
+ gf_log (this->name, GF_LOG_DEBUG, "Upcall Notify event = %d",
+ event);
+
+ notify_event = (notify_event_data_t *) data;
+ up_client_entry = notify_event->client_entry;
+
+ if (!up_client_entry) {
+ goto out;
+ }
+
+ up_req.client_uid = up_client_entry->client_uid;
+
+ memcpy (up_req.gfid, notify_event->gfid, 16);
+ gf_log (this->name, GF_LOG_DEBUG,
+ "Sending notify to the client- %s, gfid - %s",
+ up_client_entry->client_uid, up_req.gfid);
+
+ switch (notify_event->event_type) {
+ case CACHE_INVALIDATION:
+ GF_ASSERT (notify_event->extra);
+ up_req.flags = notify_event->invalidate_flags;
+ up_req.expire_time_attr = up_client_entry->expire_time_attr;
+ break;
+ default:
+ goto out;
+ }
+
+ up_req.event_type = notify_event->event_type;
+
+ ret = default_notify (this, event, &up_req);
+
+ /*
+ * notify may fail as the client could have been
+ * dis(re)connected. Cleanup the client entry.
+ */
+ if (ret < 0)
+ __upcall_cleanup_client_entry (up_client_entry);
+ }
+ break;
+ default:
+ default_notify (this, event, data);
+ break;
+ }
+ ret = 0;
+
+out:
+ return ret;
+}
+
+struct xlator_fops fops = {
+ .open = up_open,
+ .readv = up_readv,
+ .writev = up_writev,
+ .truncate = up_truncate,
+ .lk = up_lk,
+ .setattr = up_setattr,
+ .rename = up_rename,
+ .unlink = up_unlink, /* invalidate both file and parent dir */
+ .rmdir = up_rmdir, /* same as above */
+ .link = up_link, /* invalidate both file and parent dir */
+ .create = up_create, /* update only direntry */
+ .mkdir = up_mkdir, /* update only dirent */
+#ifdef WIP
+ .ftruncate = up_ftruncate, /* reqd? */
+ .getattr = up_getattr, /* ?? */
+ .getxattr = up_getxattr, /* ?? */
+ .access = up_access,
+ .lookup = up_lookup,
+ .symlink = up_symlink, /* invalidate both file and parent dir maybe */
+ .readlink = up_readlink, /* Needed? readlink same as read? */
+ .readdirp = up_readdirp,
+ .readdir = up_readdir,
+/* other fops to be considered - Bug1200271
+ * lookup, stat, opendir, readdir, readdirp, readlink, mknod, statfs, flush,
+ * fsync, mknod, fsyncdir, setxattr, removexattr, rchecksum, fallocate, discard,
+ * zerofill, (also variants of above similar to fsetattr)
+ */
+#endif
+};
+
+struct xlator_cbks cbks = {
+ .forget = upcall_forget,
+ .release = upcall_release,
+};
+
+struct volume_options options[] = {
+ { .key = {NULL} },
+};