diff options
Diffstat (limited to 'xlators/features/leases/src/leases.c')
-rw-r--r-- | xlators/features/leases/src/leases.c | 1134 |
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} }, +}; |