summaryrefslogtreecommitdiffstats
path: root/xlators/features/leases/src/leases.c
diff options
context:
space:
mode:
Diffstat (limited to 'xlators/features/leases/src/leases.c')
-rw-r--r--xlators/features/leases/src/leases.c1134
1 files changed, 1134 insertions, 0 deletions
diff --git a/xlators/features/leases/src/leases.c b/xlators/features/leases/src/leases.c
new file mode 100644
index 00000000000..8783a5ce9c2
--- /dev/null
+++ b/xlators/features/leases/src/leases.c
@@ -0,0 +1,1134 @@
+/*
+ Copyright (c) 2015-2016 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.
+*/
+
+#ifndef _CONFIG_H
+#define _CONFIG_H
+#include "config.h"
+#endif
+
+#include "leases.h"
+
+int32_t
+leases_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)
+{
+ STACK_UNWIND_STRICT (open, frame, op_ret, op_errno, fd, xdata);
+
+ return 0;
+}
+
+
+int32_t
+leases_open (call_frame_t *frame, xlator_t *this, loc_t *loc, int32_t flags,
+ fd_t *fd, dict_t *xdata)
+{
+ uint32_t fop_flags = 0;
+ int32_t op_errno = 0;
+ int ret = 0;
+ lease_fd_ctx_t *fd_ctx = NULL;
+ char *lease_id = NULL;
+
+ EXIT_IF_LEASES_OFF (this, out);
+
+ fd_ctx = GF_CALLOC (1, sizeof (*fd_ctx), gf_leases_mt_fd_ctx_t);
+
+ fd_ctx->client_uid = gf_strdup (frame->root->client->client_uid);
+ if (!fd_ctx->client_uid) {
+ op_errno = ENOMEM;
+ goto err;
+ }
+
+ GET_FLAGS (frame->op, flags);
+ GET_LEASE_ID (xdata, lease_id, frame->root->client->client_uid);
+ if (lease_id != NULL)
+ memcpy (fd_ctx->lease_id, lease_id, LEASE_ID_SIZE);
+ else
+ memset (fd_ctx->lease_id, 0, LEASE_ID_SIZE);
+
+ ret = fd_ctx_set (fd, this, (uint64_t)fd_ctx);
+ if (ret) {
+ op_errno = ENOMEM;
+ goto err;
+ }
+
+ ret = check_lease_conflict (frame, fd->inode, lease_id, fop_flags);
+ if (ret < 0)
+ goto err;
+ else if (ret == BLOCK_FOP)
+ goto block;
+ else if (ret == WIND_FOP)
+ goto out;
+
+block:
+ LEASE_BLOCK_FOP (fd->inode, open, frame, this,
+ loc, flags, fd, xdata);
+ return 0;
+
+out:
+ STACK_WIND (frame, leases_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;
+ STACK_UNWIND_STRICT (open, frame, -1, op_errno, NULL, NULL);
+ return 0;
+}
+
+int32_t
+leases_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)
+{
+ STACK_UNWIND_STRICT (writev, frame, op_ret, op_errno,
+ prebuf, postbuf, xdata);
+
+ return 0;
+}
+
+
+int32_t
+leases_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)
+{
+ uint32_t fop_flags = 0;
+ int32_t op_errno = -1;
+ char *lease_id = NULL;
+ int ret = 0;
+
+ EXIT_IF_LEASES_OFF (this, out);
+
+ GET_LEASE_ID (xdata, lease_id, frame->root->client->client_uid);
+ GET_FLAGS (frame->op, fd->flags);
+
+ ret = check_lease_conflict (frame, fd->inode, lease_id, fop_flags);
+ if (ret < 0)
+ goto err;
+ else if (ret == BLOCK_FOP)
+ goto block;
+ else if (ret == WIND_FOP)
+ goto out;
+
+block:
+ LEASE_BLOCK_FOP (fd->inode, writev, frame, this, fd, vector, count,
+ off, flags, iobref, xdata);
+ return 0;
+
+out:
+ STACK_WIND (frame, leases_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;
+ STACK_UNWIND_STRICT (writev, frame, -1, op_errno, NULL, NULL, NULL);
+ return 0;
+}
+
+
+int32_t
+leases_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)
+{
+ STACK_UNWIND_STRICT (readv, frame, op_ret, op_errno, vector,
+ count, stbuf, iobref, xdata);
+
+ return 0;
+}
+
+int32_t
+leases_readv (call_frame_t *frame, xlator_t *this,
+ fd_t *fd, size_t size, off_t offset,
+ uint32_t flags, dict_t *xdata)
+{
+ uint32_t fop_flags = 0;
+ int32_t op_errno = -1;
+ char *lease_id = NULL;
+ int ret = 0;
+
+ EXIT_IF_LEASES_OFF (this, out);
+
+ GET_LEASE_ID (xdata, lease_id, frame->root->client->client_uid);
+ GET_FLAGS (frame->op, fd->flags);
+
+ ret = check_lease_conflict (frame, fd->inode, lease_id, fop_flags);
+ if (ret < 0)
+ goto err;
+ else if (ret == BLOCK_FOP)
+ goto block;
+ else if (ret == WIND_FOP)
+ goto out;
+
+block:
+ LEASE_BLOCK_FOP (fd->inode, readv, frame, this,
+ fd, size, offset, flags, xdata);
+ return 0;
+
+out:
+ STACK_WIND (frame, leases_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;
+ STACK_UNWIND_STRICT (readv, frame, -1, op_errno, NULL, 0,
+ NULL, NULL, NULL);
+ return 0;
+}
+
+int32_t
+leases_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)
+{
+ STACK_UNWIND_STRICT (lk, frame, op_ret, op_errno, lock, xdata);
+
+ return 0;
+}
+
+int32_t
+leases_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 = 0;
+ uint32_t fop_flags = 0;
+ char *lease_id = NULL;
+ int ret = 0;
+
+ EXIT_IF_LEASES_OFF (this, out);
+
+ GET_LEASE_ID (xdata, lease_id, frame->root->client->client_uid);
+ GET_FLAGS_LK (cmd, flock->l_type, fd->flags);
+
+ ret = check_lease_conflict (frame, fd->inode, lease_id, fop_flags);
+ if (ret < 0)
+ goto err;
+ else if (ret == BLOCK_FOP)
+ goto block;
+ else if (ret == WIND_FOP)
+ goto out;
+
+block:
+ LEASE_BLOCK_FOP (fd->inode, lk, frame, this,
+ fd, cmd, flock, xdata);
+ return 0;
+
+out:
+ STACK_WIND (frame, leases_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;
+ STACK_UNWIND_STRICT (lk, frame, -1, op_errno, NULL, NULL);
+ return 0;
+}
+
+int32_t
+leases_lease (call_frame_t *frame, xlator_t *this,
+ loc_t *loc, struct gf_lease *lease, dict_t *xdata)
+{
+ int32_t op_errno = 0;
+ int ret = 0;
+ struct gf_lease nullease = {0, };
+ int32_t op_ret = 0;
+
+ EXIT_IF_LEASES_OFF (this, out);
+
+ ret = process_lease_req (frame, this, loc->inode, lease);
+ if (ret < 0) {
+ op_errno = -ret;
+ op_ret = -1;
+ }
+ goto unwind;
+
+out:
+ gf_msg (this->name, GF_LOG_ERROR, EINVAL, LEASE_MSG_NOT_ENABLED,
+ "\"features/leases\" translator is not enabled. "
+ "You need to enable it for proper functioning of your "
+ "application");
+ op_errno = ENOSYS;
+ op_ret = -1;
+
+unwind:
+ STACK_UNWIND_STRICT (lease, frame, op_ret, op_errno,
+ (op_errno == ENOSYS) ? &nullease : lease, xdata);
+ return 0;
+}
+
+int32_t
+leases_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)
+{
+ STACK_UNWIND_STRICT (truncate, frame, op_ret, op_errno,
+ prebuf, postbuf, xdata);
+
+ return 0;
+}
+
+int32_t
+leases_truncate (call_frame_t *frame, xlator_t *this, loc_t *loc, off_t offset,
+ dict_t *xdata)
+{
+ uint32_t fop_flags = 0;
+ int32_t op_errno = -1;
+ char *lease_id = NULL;
+ int ret = 0;
+
+ EXIT_IF_LEASES_OFF (this, out);
+
+ GET_LEASE_ID (xdata, lease_id, frame->root->client->client_uid);
+ GET_FLAGS (frame->op, 0);
+
+ ret = check_lease_conflict (frame, loc->inode, lease_id, fop_flags);
+ if (ret < 0)
+ goto err;
+ else if (ret == BLOCK_FOP)
+ goto block;
+ else if (ret == WIND_FOP)
+ goto out;
+
+block:
+ LEASE_BLOCK_FOP (loc->inode, truncate, frame, this,
+ loc, offset, xdata);
+ return 0;
+
+out:
+ STACK_WIND (frame, leases_truncate_cbk,
+ FIRST_CHILD(this), FIRST_CHILD(this)->fops->truncate,
+ loc, offset, xdata);
+ return 0;
+
+err:
+ op_errno = (op_errno == -1) ? errno : op_errno;
+ STACK_UNWIND_STRICT (truncate, frame, -1, op_errno, NULL, NULL, NULL);
+ return 0;
+}
+
+int32_t
+leases_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)
+{
+ STACK_UNWIND_STRICT (setattr, frame, op_ret, op_errno,
+ statpre, statpost, xdata);
+
+ return 0;
+}
+
+int32_t
+leases_setattr (call_frame_t *frame, xlator_t *this, loc_t *loc,
+ struct iatt *stbuf, int32_t valid, dict_t *xdata)
+{
+ uint32_t fop_flags = 0;
+ int32_t op_errno = -1;
+ char *lease_id = NULL;
+ int ret = 0;
+
+ EXIT_IF_LEASES_OFF (this, out);
+
+ GET_LEASE_ID (xdata, lease_id, frame->root->client->client_uid);
+ GET_FLAGS (frame->op, 0);
+
+ ret = check_lease_conflict (frame, loc->inode, lease_id, fop_flags);
+ if (ret < 0)
+ goto err;
+ else if (ret == BLOCK_FOP)
+ goto block;
+ else if (ret == WIND_FOP)
+ goto out;
+
+block:
+ LEASE_BLOCK_FOP (loc->inode, setattr, frame, this,
+ loc, stbuf, valid, xdata);
+ return 0;
+
+out:
+ STACK_WIND (frame, leases_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;
+ STACK_UNWIND_STRICT (setattr, frame, -1, op_errno, NULL, NULL, NULL);
+ return 0;
+}
+
+int32_t
+leases_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)
+{
+ STACK_UNWIND_STRICT (rename, frame, op_ret, op_errno,
+ stbuf, preoldparent, postoldparent,
+ prenewparent, postnewparent, xdata);
+
+ return 0;
+}
+
+int32_t
+leases_rename (call_frame_t *frame, xlator_t *this,
+ loc_t *oldloc, loc_t *newloc, dict_t *xdata)
+{
+ uint32_t fop_flags = 0;
+ int32_t op_errno = -1;
+ char *lease_id = NULL;
+ int ret = 0;
+
+ EXIT_IF_LEASES_OFF (this, out);
+
+ /* should the lease be also checked for newloc */
+ GET_LEASE_ID (xdata, lease_id, frame->root->client->client_uid);
+ GET_FLAGS (frame->op, 0);
+
+ ret = check_lease_conflict (frame, oldloc->inode, lease_id, fop_flags);
+ if (ret < 0)
+ goto err;
+ else if (ret == BLOCK_FOP)
+ goto block;
+ else if (ret == WIND_FOP)
+ goto out;
+
+block:
+ LEASE_BLOCK_FOP (oldloc->inode, rename, frame, this,
+ oldloc, newloc, xdata);
+ return 0;
+
+out:
+ STACK_WIND (frame, leases_rename_cbk,
+ FIRST_CHILD(this), FIRST_CHILD(this)->fops->rename,
+ oldloc, newloc, xdata);
+ return 0;
+
+err:
+ op_errno = (op_errno == -1) ? errno : op_errno;
+ STACK_UNWIND_STRICT (rename, frame, -1, op_errno, NULL,
+ NULL, NULL, NULL, NULL, NULL);
+ return 0;
+}
+
+int32_t
+leases_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)
+{
+ STACK_UNWIND_STRICT (unlink, frame, op_ret, op_errno,
+ preparent, postparent, xdata);
+
+ return 0;
+}
+
+int32_t
+leases_unlink (call_frame_t *frame, xlator_t *this, loc_t *loc, int xflag,
+ dict_t *xdata)
+{
+ uint32_t fop_flags = 0;
+ int32_t op_errno = -1;
+ char *lease_id = NULL;
+ int ret = 0;
+
+ EXIT_IF_LEASES_OFF (this, out);
+
+ GET_LEASE_ID (xdata, lease_id, frame->root->client->client_uid);
+ GET_FLAGS (frame->op, 0);
+
+ ret = check_lease_conflict (frame, loc->inode, lease_id, fop_flags);
+ if (ret < 0)
+ goto err;
+ else if (ret == BLOCK_FOP)
+ goto block;
+ else if (ret == WIND_FOP)
+ goto out;
+
+block:
+ LEASE_BLOCK_FOP (loc->inode, unlink, frame, this,
+ loc, xflag, xdata);
+ return 0;
+
+out:
+ STACK_WIND (frame, leases_unlink_cbk,
+ FIRST_CHILD(this), FIRST_CHILD(this)->fops->unlink,
+ loc, xflag, xdata);
+ return 0;
+
+err:
+ op_errno = (op_errno == -1) ? errno : op_errno;
+ STACK_UNWIND_STRICT (unlink, frame, -1, op_errno, NULL, NULL, NULL);
+ return 0;
+}
+
+int32_t
+leases_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)
+{
+ STACK_UNWIND_STRICT (link, frame, op_ret, op_errno,
+ inode, stbuf, preparent, postparent, xdata);
+
+ return 0;
+}
+
+int32_t
+leases_link (call_frame_t *frame, xlator_t *this, loc_t *oldloc,
+ loc_t *newloc, dict_t *xdata)
+{
+ uint32_t fop_flags = 0;
+ int32_t op_errno = -1;
+ char *lease_id = NULL;
+ int ret = 0;
+
+ EXIT_IF_LEASES_OFF (this, out);
+
+ GET_LEASE_ID (xdata, lease_id, frame->root->client->client_uid);
+ GET_FLAGS (frame->op, 0);
+
+ ret = check_lease_conflict (frame, oldloc->inode, lease_id, fop_flags);
+ if (ret < 0)
+ goto err;
+ else if (ret == BLOCK_FOP)
+ goto block;
+ else if (ret == WIND_FOP)
+ goto out;
+
+block:
+ LEASE_BLOCK_FOP (oldloc->inode, link, frame, this,
+ oldloc, newloc, xdata);
+ return 0;
+out:
+ STACK_WIND (frame, leases_link_cbk,
+ FIRST_CHILD(this), FIRST_CHILD(this)->fops->link,
+ oldloc, newloc, xdata);
+ return 0;
+
+err:
+ op_errno = (op_errno == -1) ? errno : op_errno;
+ STACK_UNWIND_STRICT (link, frame, -1, op_errno, NULL,
+ NULL, NULL, NULL, NULL);
+ return 0;
+}
+
+int32_t
+leases_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)
+{
+ STACK_UNWIND_STRICT (create, frame, op_ret, op_errno, fd,
+ inode, stbuf, preparent, postparent, xdata);
+
+ return 0;
+}
+
+int32_t
+leases_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 *xdata)
+{
+ uint32_t fop_flags = 0;
+ int32_t op_errno = -1;
+ char *lease_id = NULL;
+ int ret = 0;
+
+ EXIT_IF_LEASES_OFF (this, out);
+
+ GET_LEASE_ID (xdata, lease_id, frame->root->client->client_uid);
+ GET_FLAGS (frame->op, flags);
+
+ ret = check_lease_conflict (frame, fd->inode, lease_id, fop_flags);
+ if (ret < 0)
+ goto err;
+ else if (ret == BLOCK_FOP)
+ goto block;
+ else if (ret == WIND_FOP)
+ goto out;
+
+block:
+ LEASE_BLOCK_FOP (fd->inode, create, frame, this,
+ loc, flags, mode, umask, fd, xdata);
+ return 0;
+
+out:
+ STACK_WIND (frame, leases_create_cbk,
+ FIRST_CHILD(this), FIRST_CHILD(this)->fops->create,
+ loc, flags, mode, umask, fd, xdata);
+ return 0;
+
+err:
+ op_errno = (op_errno == -1) ? errno : op_errno;
+ STACK_UNWIND_STRICT (create, frame, -1, op_errno, NULL, NULL, NULL,
+ NULL, NULL, NULL);
+ return 0;
+}
+
+int32_t
+leases_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)
+{
+ STACK_UNWIND_STRICT (fsync, frame, op_ret, op_errno, prebuf, postbuf,
+ xdata);
+ return 0;
+}
+
+int32_t
+leases_fsync (call_frame_t *frame, xlator_t *this, fd_t *fd,
+ int32_t flags, dict_t *xdata)
+{
+ uint32_t fop_flags = 0;
+ int32_t op_errno = -1;
+ char *lease_id = NULL;
+ int ret = 0;
+
+ EXIT_IF_LEASES_OFF (this, out);
+
+ GET_LEASE_ID (xdata, lease_id, frame->root->client->client_uid);
+ GET_FLAGS (frame->op, fd->flags);
+
+ ret = check_lease_conflict (frame, fd->inode, lease_id, fop_flags);
+ if (ret < 0)
+ goto err;
+ else if (ret == BLOCK_FOP)
+ goto block;
+ else if (ret == WIND_FOP)
+ goto out;
+
+block:
+ LEASE_BLOCK_FOP (fd->inode, fsync, frame, this,
+ fd, flags, xdata);
+ return 0;
+
+out:
+ STACK_WIND (frame, leases_fsync_cbk, FIRST_CHILD(this),
+ FIRST_CHILD(this)->fops->fsync, fd, flags, xdata);
+ return 0;
+err:
+ op_errno = (op_errno == -1) ? errno : op_errno;
+ STACK_UNWIND_STRICT (fsync, frame, -1, op_errno, NULL, NULL, NULL);
+ return 0;
+}
+
+int32_t
+leases_ftruncate_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)
+{
+ STACK_UNWIND_STRICT (ftruncate, frame, op_ret, op_errno, prebuf,
+ postbuf, xdata);
+ return 0;
+}
+
+int32_t
+leases_ftruncate (call_frame_t *frame, xlator_t *this,
+ fd_t *fd, off_t offset, dict_t *xdata)
+{
+ uint32_t fop_flags = 0;
+ int32_t op_errno = -1;
+ char *lease_id = NULL;
+ int ret = 0;
+
+ EXIT_IF_LEASES_OFF (this, out);
+
+ GET_LEASE_ID (xdata, lease_id, frame->root->client->client_uid);
+ GET_FLAGS (frame->op, 0); /* TODO:fd->flags?*/
+
+ ret = check_lease_conflict (frame, fd->inode, lease_id, fop_flags);
+ if (ret < 0)
+ goto err;
+ else if (ret == BLOCK_FOP)
+ goto block;
+ else if (ret == WIND_FOP)
+ goto out;
+
+block:
+ LEASE_BLOCK_FOP (fd->inode, ftruncate, frame, this,
+ fd, offset, xdata);
+ return 0;
+
+out:
+ STACK_WIND (frame, leases_ftruncate_cbk,
+ FIRST_CHILD(this), FIRST_CHILD(this)->fops->ftruncate,
+ fd, offset, xdata);
+ return 0;
+
+err:
+ op_errno = (op_errno == -1) ? errno : op_errno;
+ STACK_UNWIND_STRICT (ftruncate, frame, -1, op_errno, NULL,
+ NULL, NULL);
+ return 0;
+}
+
+int32_t
+leases_fsetattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
+ int32_t op_ret, int32_t op_errno, struct iatt *statpre,
+ struct iatt *statpost, dict_t *xdata)
+{
+ STACK_UNWIND_STRICT (fsetattr, frame, op_ret, op_errno,
+ statpre, statpost, xdata);
+ return 0;
+}
+
+int32_t
+leases_fsetattr (call_frame_t *frame, xlator_t *this, fd_t *fd,
+ struct iatt *stbuf, int32_t valid, dict_t *xdata)
+{
+ uint32_t fop_flags = 0;
+ int32_t op_errno = -1;
+ char *lease_id = NULL;
+ int ret = 0;
+
+ EXIT_IF_LEASES_OFF (this, out);
+
+ GET_LEASE_ID (xdata, lease_id, frame->root->client->client_uid);
+ GET_FLAGS (frame->op, fd->flags);
+
+ ret = check_lease_conflict (frame, fd->inode, lease_id, fop_flags);
+ if (ret < 0)
+ goto err;
+ else if (ret == BLOCK_FOP)
+ goto block;
+ else if (ret == WIND_FOP)
+ goto out;
+
+block:
+ LEASE_BLOCK_FOP (fd->inode, fsetattr, frame, this,
+ fd, stbuf, valid, xdata);
+ return 0;
+
+out:
+ STACK_WIND (frame, leases_fsetattr_cbk,
+ FIRST_CHILD(this), FIRST_CHILD(this)->fops->fsetattr,
+ fd, stbuf, valid, xdata);
+ return 0;
+
+err:
+ op_errno = (op_errno == -1) ? errno : op_errno;
+ STACK_UNWIND_STRICT (fsetattr, frame, -1, op_errno, NULL,
+ NULL, NULL);
+ return 0;
+}
+
+int32_t
+leases_fallocate_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)
+{
+ STACK_UNWIND_STRICT (fallocate, frame, op_ret, op_errno, pre,
+ post, xdata);
+
+ return 0;
+}
+
+int32_t
+leases_fallocate (call_frame_t *frame, xlator_t *this, fd_t *fd,
+ int32_t mode, off_t offset, size_t len, dict_t *xdata)
+{
+ uint32_t fop_flags = 0;
+ int32_t op_errno = -1;
+ char *lease_id = NULL;
+ int ret = 0;
+
+ EXIT_IF_LEASES_OFF (this, out);
+
+ GET_LEASE_ID (xdata, lease_id, frame->root->client->client_uid);
+ GET_FLAGS (frame->op, fd->flags);
+
+ ret = check_lease_conflict (frame, fd->inode, lease_id, fop_flags);
+ if (ret < 0)
+ goto err;
+ else if (ret == BLOCK_FOP)
+ goto block;
+ else if (ret == WIND_FOP)
+ goto out;
+
+block:
+ LEASE_BLOCK_FOP (fd->inode, fallocate, frame, this,
+ fd, mode, offset, len, xdata);
+ return 0;
+
+out:
+ STACK_WIND (frame, leases_fallocate_cbk,
+ FIRST_CHILD(this), FIRST_CHILD(this)->fops->fallocate,
+ fd, mode, offset, len, xdata);
+ return 0;
+
+err:
+ op_errno = (op_errno == -1) ? errno : op_errno;
+ STACK_UNWIND_STRICT (fallocate, frame, -1, op_errno, NULL,
+ NULL, NULL);
+ return 0;
+}
+
+int32_t
+leases_discard_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)
+{
+ STACK_UNWIND_STRICT (discard, frame, op_ret, op_errno, pre,
+ post, xdata);
+
+ return 0;
+}
+
+int32_t
+leases_discard (call_frame_t *frame, xlator_t *this, fd_t *fd,
+ off_t offset, size_t len, dict_t *xdata)
+{
+ uint32_t fop_flags = 0;
+ int32_t op_errno = -1;
+ char *lease_id = NULL;
+ int ret = 0;
+
+ EXIT_IF_LEASES_OFF (this, out);
+
+ GET_LEASE_ID (xdata, lease_id, frame->root->client->client_uid);
+ GET_FLAGS (frame->op, fd->flags);
+
+ ret = check_lease_conflict (frame, fd->inode, lease_id, fop_flags);
+ if (ret < 0)
+ goto err;
+ else if (ret == BLOCK_FOP)
+ goto block;
+ else if (ret == WIND_FOP)
+ goto out;
+
+block:
+ LEASE_BLOCK_FOP (fd->inode, discard, frame, this,
+ fd, offset, len, xdata);
+ return 0;
+
+out:
+ STACK_WIND (frame, leases_discard_cbk,
+ FIRST_CHILD(this), FIRST_CHILD(this)->fops->discard,
+ fd, offset, len, xdata);
+ return 0;
+
+err:
+ op_errno = (op_errno == -1) ? errno : op_errno;
+ STACK_UNWIND_STRICT (discard, frame, -1, op_errno, NULL,
+ NULL, NULL);
+ return 0;
+}
+
+int32_t
+leases_zerofill_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)
+{
+ STACK_UNWIND_STRICT (zerofill, frame, op_ret, op_errno, pre,
+ post, xdata);
+
+ return 0;
+}
+
+int
+leases_zerofill (call_frame_t *frame, xlator_t *this, fd_t *fd,
+ off_t offset, off_t len, dict_t *xdata)
+{
+ uint32_t fop_flags = 0;
+ int32_t op_errno = -1;
+ char *lease_id = NULL;
+ int ret = 0;
+
+ EXIT_IF_LEASES_OFF (this, out);
+
+ GET_LEASE_ID (xdata, lease_id, frame->root->client->client_uid);
+ GET_FLAGS (frame->op, fd->flags);
+
+ ret = check_lease_conflict (frame, fd->inode, lease_id, fop_flags);
+ if (ret < 0)
+ goto err;
+ else if (ret == BLOCK_FOP)
+ goto block;
+ else if (ret == WIND_FOP)
+ goto out;
+
+block:
+ LEASE_BLOCK_FOP (fd->inode, zerofill, frame, this,
+ fd, offset, len, xdata);
+ return 0;
+
+out:
+ STACK_WIND (frame, leases_zerofill_cbk,
+ FIRST_CHILD(this), FIRST_CHILD(this)->fops->zerofill,
+ fd, offset, len, xdata);
+ return 0;
+
+err:
+ op_errno = (op_errno == -1) ? errno : op_errno;
+ STACK_UNWIND_STRICT (zerofill, frame, -1, op_errno, NULL,
+ NULL, NULL);
+ return 0;
+}
+
+int
+leases_flush_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
+ int32_t op_ret, int32_t op_errno, dict_t *xdata)
+{
+ STACK_UNWIND_STRICT (flush, frame, op_ret, op_errno, xdata);
+
+ return 0;
+}
+
+int
+leases_flush (call_frame_t *frame, xlator_t *this,
+ fd_t *fd, dict_t *xdata)
+{
+ int32_t op_errno = -1;
+ uint32_t fop_flags = 0;
+ char *lease_id = NULL;
+ int ret = 0;
+
+ EXIT_IF_LEASES_OFF (this, out);
+
+ GET_LEASE_ID (xdata, lease_id, frame->root->client->client_uid);
+ GET_FLAGS (frame->op, fd->flags);
+
+ ret = check_lease_conflict (frame, fd->inode, lease_id, fop_flags);
+ if (ret < 0)
+ goto err;
+ else if (ret == BLOCK_FOP)
+ goto block;
+ else if (ret == WIND_FOP)
+ goto out;
+
+block:
+ LEASE_BLOCK_FOP (fd->inode, flush, frame, this,
+ fd, xdata);
+ return 0;
+
+out:
+ STACK_WIND (frame, leases_flush_cbk, FIRST_CHILD(this),
+ FIRST_CHILD(this)->fops->flush, fd, xdata);
+ return 0;
+
+err:
+ op_errno = (op_errno == -1) ? errno : op_errno;
+ STACK_UNWIND_STRICT (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_leases_mt_end + 1);
+
+ if (ret != 0) {
+ gf_msg (this->name, GF_LOG_WARNING, ENOMEM, LEASE_MSG_NO_MEM,
+ "mem account init failed");
+ return ret;
+ }
+
+ return ret;
+}
+
+int
+reconfigure (xlator_t *this, dict_t *options)
+{
+ leases_private_t *priv = NULL;
+ int ret = -1;
+
+ priv = this->private;
+ GF_ASSERT (priv);
+
+ GF_OPTION_RECONF ("leases", priv->leases_enabled,
+ options, bool, out);
+ GF_OPTION_RECONF ("lease-lock-recall-timeout",
+ priv->recall_lease_timeout,
+ options, int32, out);
+
+ ret = 0;
+out:
+ return ret;
+}
+
+int
+init (xlator_t *this)
+{
+ int ret = -1;
+ leases_private_t *priv = NULL;
+
+ priv = GF_CALLOC (1, sizeof (*priv),
+ gf_leases_mt_private_t);
+ if (!priv) {
+ gf_msg (this->name, GF_LOG_WARNING, ENOMEM, LEASE_MSG_NO_MEM,
+ "Leases init failed");
+ goto out;
+ }
+
+ GF_OPTION_INIT ("leases", priv->leases_enabled,
+ bool, out);
+ GF_OPTION_INIT ("lease-lock-recall-timeout",
+ priv->recall_lease_timeout, int32, out);
+ pthread_mutex_init (&priv->mutex, NULL);
+ INIT_LIST_HEAD (&priv->client_list);
+ INIT_LIST_HEAD (&priv->recall_list);
+
+ priv->timer_wheel = glusterfs_global_timer_wheel (this);
+ if (!priv->timer_wheel) {
+ gf_msg (this->name, GF_LOG_ERROR, 0, LEASE_MSG_NO_TIMER_WHEEL,
+ "Initing the global timer wheel");
+ ret = glusterfs_global_timer_wheel_init (this->ctx);
+ if (ret) {
+ gf_msg (this->name, GF_LOG_INFO, 0, LEASE_MSG_NO_TIMER_WHEEL,
+ "Initing the global timer wheel failed");
+ goto out;
+ }
+ }
+
+ pthread_create (&priv->recall_thr, NULL, expired_recall_cleanup, this);
+
+ this->private = priv;
+ ret = 0;
+
+out:
+ if (ret) {
+ GF_FREE (priv);
+ }
+
+ return ret;
+}
+
+int
+fini (xlator_t *this)
+{
+ leases_private_t *priv = NULL;
+
+ priv = this->private;
+ if (!priv) {
+ return 0;
+ }
+ this->private = NULL;
+
+ priv->fini = _gf_false;
+ pthread_join (priv->recall_thr, NULL);
+
+ GF_FREE (priv);
+
+ return 0;
+}
+
+static int
+leases_forget (xlator_t *this, inode_t *inode)
+{
+ /* TODO:leases_cleanup_inode_ctx (this, inode); */
+ return 0;
+}
+
+static int
+leases_release (xlator_t *this, fd_t *fd)
+{
+ /* TODO:cleanup fd_ctx */
+ return 0;
+}
+
+static int
+leases_clnt_disconnect_cbk (xlator_t *this, client_t *client)
+{
+ int ret = 0;
+
+ EXIT_IF_LEASES_OFF (this, out);
+
+ ret = cleanup_client_leases (this, client->client_uid);
+out:
+ return ret;
+}
+
+int
+notify (xlator_t *this, int32_t event, void *data, ...)
+{
+ int ret = 0;
+
+ EXIT_IF_LEASES_OFF (this, out);
+
+ ret = default_notify (this, event, data);
+out:
+ return ret;
+}
+
+struct xlator_fops fops = {
+ /* Metadata modifying fops */
+ .fsetattr = leases_fsetattr,
+ .setattr = leases_setattr,
+
+ /* File Data reading fops */
+ .open = leases_open,
+ .readv = leases_readv,
+
+ /* File Data modifying fops */
+ .truncate = leases_truncate,
+ .ftruncate = leases_ftruncate,
+ .writev = leases_writev,
+ .zerofill = leases_zerofill,
+ .fallocate = leases_fallocate,
+ .discard = leases_discard,
+ .lk = leases_lk,
+ .fsync = leases_fsync,
+ .flush = leases_flush,
+ .lease = leases_lease,
+
+ /* Directory Data modifying fops */
+ .create = leases_create,
+ .rename = leases_rename,
+ .unlink = leases_unlink,
+ .link = leases_link,
+
+#ifdef NOT_SUPPORTED
+ /* internal lk fops */
+ .inodelk = leases_inodelk,
+ .finodelk = leases_finodelk,
+ .entrylk = leases_entrylk,
+ .fentrylk = leases_fentrylk,
+
+ /* Internal special fops*/
+ .xattrop = leases_xattrop,
+ .fxattrop = leases_fxattrop,
+#endif
+};
+
+struct xlator_cbks cbks = {
+ .forget = leases_forget,
+ .release = leases_release,
+ .client_disconnect = leases_clnt_disconnect_cbk,
+};
+
+struct volume_options options[] = {
+ { .key = {"leases"},
+ .type = GF_OPTION_TYPE_BOOL,
+ .default_value = "off",
+ .description = "When \"on\", enables leases support"
+ },
+ { .key = {"lease-lock-recall-timeout"},
+ .type = GF_OPTION_TYPE_INT,
+ .default_value = RECALL_LEASE_LK_TIMEOUT,
+ .description = "After 'timeout' seconds since the recall_lease"
+ " request has been sent to the client, the lease lock"
+ " will be forcefully purged by the server."
+ },
+ { .key = {NULL} },
+};