From b27512e006ae55777f481937d321f60fa195c48d Mon Sep 17 00:00:00 2001 From: Krishnan Parthasarathi Date: Wed, 16 Nov 2011 16:23:48 +0530 Subject: locks: Added a getxattr interface to clear locks on a given inode. getxattr returns a summary of no. of inodelks/entrylks cleared. cmd_structure: trusted.glusterfs.clrlk.t.k[.{range|basename}] where, type = "inode"| "entry"| "posix" kind = "granted"| "blocked" | "all" range = off,a-b, where a, b = 'start', 'len' from offset 'off' Change-Id: I8a771530531030a9d4268643bc6823786ccb51f2 BUG: 789858 Signed-off-by: Krishnan Parthasarathi Reviewed-on: http://review.gluster.com/2551 Tested-by: Gluster Build System Reviewed-by: Vijay Bellur --- xlators/cluster/afr/src/afr-common.c | 24 +- xlators/cluster/afr/src/afr-inode-read.c | 178 ++++++++++++-- xlators/features/locks/src/Makefile.am | 12 +- xlators/features/locks/src/clear.c | 409 +++++++++++++++++++++++++++++++ xlators/features/locks/src/clear.h | 86 +++++++ xlators/features/locks/src/posix.c | 111 ++++++++- 6 files changed, 784 insertions(+), 36 deletions(-) create mode 100644 xlators/features/locks/src/clear.c create mode 100644 xlators/features/locks/src/clear.h (limited to 'xlators') diff --git a/xlators/cluster/afr/src/afr-common.c b/xlators/cluster/afr/src/afr-common.c index b0f7b38f3fd..a5dee65f621 100644 --- a/xlators/cluster/afr/src/afr-common.c +++ b/xlators/cluster/afr/src/afr-common.c @@ -808,7 +808,6 @@ afr_local_transaction_cleanup (afr_local_t *local, xlator_t *this) GF_FREE (local->transaction.pre_op); GF_FREE (local->transaction.child_errno); - GF_FREE (local->child_errno); GF_FREE (local->transaction.eager_lock); GF_FREE (local->transaction.basename); @@ -845,6 +844,9 @@ afr_local_cleanup (afr_local_t *local, xlator_t *this) if (local->child_up) GF_FREE (local->child_up); + if (local->child_errno) + GF_FREE (local->child_errno); + if (local->fresh_children) GF_FREE (local->fresh_children); @@ -3592,8 +3594,8 @@ afr_local_init (afr_local_t *local, afr_private_t *priv, int32_t *op_errno) local->op_ret = -1; local->op_errno = EUCLEAN; - local->child_up = GF_CALLOC (sizeof (*local->child_up), - priv->child_count, + local->child_up = GF_CALLOC (priv->child_count, + sizeof (*local->child_up), gf_afr_mt_char); if (!local->child_up) { if (op_errno) @@ -3611,6 +3613,16 @@ afr_local_init (afr_local_t *local, afr_private_t *priv, int32_t *op_errno) *op_errno = ENOTCONN; goto out; } + + local->child_errno = GF_CALLOC (priv->child_count, + sizeof (*local->child_errno), + gf_afr_mt_int32_t); + if (!local->child_errno) { + if (op_errno) + *op_errno = ENOMEM; + goto out; + } + ret = 0; out: return ret; @@ -3711,12 +3723,6 @@ afr_transaction_local_init (afr_local_t *local, xlator_t *this) local->first_up_child = afr_first_up_child (local->child_up, priv->child_count); - local->child_errno = GF_CALLOC (sizeof (*local->child_errno), - priv->child_count, - gf_afr_mt_int32_t); - if (!local->child_errno) - goto out; - local->transaction.eager_lock = GF_CALLOC (sizeof (*local->transaction.eager_lock), priv->child_count, diff --git a/xlators/cluster/afr/src/afr-inode-read.c b/xlators/cluster/afr/src/afr-inode-read.c index 0ef0f4f8642..ec0acbd3b0b 100644 --- a/xlators/cluster/afr/src/afr-inode-read.c +++ b/xlators/cluster/afr/src/afr-inode-read.c @@ -631,6 +631,101 @@ afr_getxattr_unwind (call_frame_t *frame, return 0; } +int32_t +afr_getxattr_clrlk_cbk (call_frame_t *frame, void *cookie, + xlator_t *this, int32_t op_ret, int32_t op_errno, + dict_t *dict) +{ + afr_local_t *local = NULL; + afr_private_t *priv = NULL; + xlator_t **children = NULL; + dict_t *xattr = NULL; + char *tmp_report = NULL; + char lk_summary[1024] = {0,}; + int serz_len = 0; + int32_t callcnt = 0; + long int cky = 0; + int ret = 0; + + priv = this->private; + children = priv->children; + + local = frame->local; + cky = (long) cookie; + + LOCK (&frame->lock); + { + callcnt = --local->call_count; + + if (!local->dict) + local->dict = dict_new (); + if (local->dict) { + ret = dict_get_str (dict, local->cont.getxattr.name, + &tmp_report); + if (ret) + goto unlock; + ret = dict_set_str (local->dict, + children[cky]->name, + tmp_report); + if (ret) + goto unlock; + } + if (op_ret == -1) + local->child_errno[cky] = op_errno; + } +unlock: + UNLOCK (&frame->lock); + + if (!callcnt) { + xattr = dict_new (); + if (!xattr) { + op_ret = -1; + op_errno = ENOMEM; + goto unwind; + } + ret = dict_serialize_value_with_delim (local->dict, + lk_summary, + &serz_len, '\n'); + if (ret) { + op_ret = -1; + op_errno = ENOMEM; + gf_log (this->name, GF_LOG_ERROR, + "Error serializing dictionary"); + goto unwind; + } + if (serz_len == -1) + snprintf (lk_summary, sizeof (lk_summary), + "No locks cleared."); + ret = dict_set_dynstr (xattr, local->cont.getxattr.name, + gf_strdup (lk_summary)); + if (ret) { + op_ret = -1; + op_errno = ENOMEM; + gf_log (this->name, GF_LOG_ERROR, + "Error setting dictionary"); + goto unwind; + } + + unwind: + // Updating child_errno with more recent 'events' + local->child_errno[cky] = op_errno; + op_errno = afr_resultant_errno_get (NULL, local->child_errno, + priv->child_count); + AFR_STACK_UNWIND (getxattr, frame, op_ret, op_errno, xattr); + + if (local->dict) + dict_unref (local->dict); + + if (local->child_errno) + GF_FREE (local->child_errno); + + if (xattr) + dict_unref (xattr); + } + + return ret; +} + int32_t afr_getxattr_pathinfo_cbk (call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret, int32_t op_errno, @@ -735,20 +830,69 @@ afr_getxattr_pathinfo_cbk (call_frame_t *frame, void *cookie, return ret; } +static gf_boolean_t +afr_is_special_xattr (const char *name, fop_getxattr_cbk_t *cbk) +{ + gf_boolean_t is_spl = _gf_true; + + GF_ASSERT (cbk); + if (!cbk) { + is_spl = _gf_false; + goto out; + } + + if (!strcmp (name, GF_XATTR_PATHINFO_KEY)) + *cbk = afr_getxattr_pathinfo_cbk; + + else if (!strcmp (name, GF_XATTR_CLRLK_CMD)) + *cbk = afr_getxattr_clrlk_cbk; + else + is_spl = _gf_false; + +out: + return is_spl; +} + +static void +afr_getxattr_frm_all_children (xlator_t *this, call_frame_t *frame, + const char *name, loc_t *loc, + fop_getxattr_cbk_t cbk) +{ + afr_private_t *priv = NULL; + afr_local_t *local = NULL; + xlator_t **children = NULL; + int i = 0; + + priv = this->private; + children = priv->children; + + local = frame->local; + local->call_count = priv->child_count; + + for (i = 0; i < priv->child_count; i++) { + STACK_WIND_COOKIE (frame, cbk, + (void *) (long) i, + children[i], children[i]->fops->getxattr, + loc, name); + } + return; +} + int32_t afr_getxattr (call_frame_t *frame, xlator_t *this, loc_t *loc, const char *name) { - afr_private_t *priv = NULL; - xlator_t **children = NULL; - int call_child = 0; - afr_local_t *local = NULL; - xlator_list_t *trav = NULL; - xlator_t **sub_volumes = NULL; - int i = 0; - int32_t op_errno = 0; - int32_t read_child = -1; - int ret = -1; + afr_private_t *priv = NULL; + xlator_t **children = NULL; + int call_child = 0; + afr_local_t *local = NULL; + xlator_list_t *trav = NULL; + xlator_t **sub_volumes = NULL; + int i = 0; + int32_t op_errno = 0; + int32_t read_child = -1; + int ret = -1; + fop_getxattr_cbk_t cbk = NULL; VALIDATE_OR_GOTO (frame, out); @@ -814,17 +958,9 @@ afr_getxattr (call_frame_t *frame, xlator_t *this, * if we are doing getxattr with pathinfo as the key then we * collect information from all childs */ - if (strncmp (name, GF_XATTR_PATHINFO_KEY, - strlen (GF_XATTR_PATHINFO_KEY)) == 0) { - - local->call_count = priv->child_count; - for (i = 0; i < priv->child_count; i++) { - STACK_WIND_COOKIE (frame, afr_getxattr_pathinfo_cbk, - (void *) (long) i, - children[i], children[i]->fops->getxattr, - loc, name); - } - + if (afr_is_special_xattr (name, &cbk)) { + afr_getxattr_frm_all_children (this, frame, name, + loc, cbk); return 0; } diff --git a/xlators/features/locks/src/Makefile.am b/xlators/features/locks/src/Makefile.am index 53dd3aa5da5..e39676826b4 100644 --- a/xlators/features/locks/src/Makefile.am +++ b/xlators/features/locks/src/Makefile.am @@ -3,12 +3,14 @@ xlatordir = $(libdir)/glusterfs/$(PACKAGE_VERSION)/xlator/features locks_la_LDFLAGS = -module -avoidversion -locks_la_SOURCES = common.c posix.c entrylk.c inodelk.c reservelk.c -locks_la_LIBADD = $(top_builddir)/libglusterfs/src/libglusterfs.la +locks_la_SOURCES = common.c posix.c entrylk.c inodelk.c reservelk.c \ + clear.c +locks_la_LIBADD = $(top_builddir)/libglusterfs/src/libglusterfs.la -noinst_HEADERS = locks.h common.h locks-mem-types.h +noinst_HEADERS = locks.h common.h locks-mem-types.h clear.h -AM_CFLAGS = -fPIC -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE -Wall -fno-strict-aliasing -D$(GF_HOST_OS) \ +AM_CFLAGS = -fPIC -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE -Wall \ + -fno-strict-aliasing -D$(GF_HOST_OS) \ -I$(top_srcdir)/libglusterfs/src $(GF_CFLAGS) -shared -nostartfiles CLEANFILES = @@ -17,4 +19,4 @@ uninstall-local: rm -f $(DESTDIR)$(xlatordir)/posix-locks.so install-data-hook: - ln -sf locks.so $(DESTDIR)$(xlatordir)/posix-locks.so \ No newline at end of file + ln -sf locks.so $(DESTDIR)$(xlatordir)/posix-locks.so diff --git a/xlators/features/locks/src/clear.c b/xlators/features/locks/src/clear.c new file mode 100644 index 00000000000..a7b2455e33c --- /dev/null +++ b/xlators/features/locks/src/clear.c @@ -0,0 +1,409 @@ +/* + Copyright (c) 2006-2011 Gluster, Inc. + This file is part of GlusterFS. + + GlusterFS is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3 of the License, + or (at your option) any later version. + + GlusterFS is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see + . +*/ + +#include +#include +#include +#include + +#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 "locks.h" +#include "common.h" +#include "statedump.h" +#include "clear.h" + +int +clrlk_get_kind (char *kind) +{ + char *clrlk_kinds[CLRLK_KIND_MAX] = {"dummy", "blocked", "granted", + "all"}; + int ret_kind = CLRLK_KIND_MAX; + int i = 0; + + for (i = CLRLK_BLOCKED; i < CLRLK_KIND_MAX; i++) { + if (!strcmp (clrlk_kinds[i], kind)) { + ret_kind = i; + break; + } + } + + return ret_kind; +} + +int +clrlk_get_type (char *type) +{ + char *clrlk_types[CLRLK_TYPE_MAX] = {"inode", "entry", "posix"}; + int ret_type = CLRLK_TYPE_MAX; + int i = 0; + + for (i = CLRLK_INODE; i < CLRLK_TYPE_MAX; i++) { + if (!strcmp (clrlk_types[i], type)) { + ret_type = i; + break; + } + } + + return ret_type; +} + +int +clrlk_get_lock_range (char *range_str, struct gf_flock *ulock, + gf_boolean_t *chk_range) +{ + int ret = -1; + + if (!chk_range) + goto out; + + if (!range_str) { + ret = 0; + *chk_range = _gf_false; + goto out; + } + + if (sscanf (range_str, "%hd,%"PRId64"-""%"PRId64, &ulock->l_whence, + &ulock->l_start, &ulock->l_len) != 3) { + goto out; + } + + ret = 0; + *chk_range = _gf_true; +out: + return ret; +} + +int +clrlk_parse_args (const char* cmd, clrlk_args *args) +{ + char *opts = NULL; + char *cur = NULL; + char *tok = NULL; + char *sptr = NULL; + char *free_ptr = NULL; + char kw[KW_MAX] = {[KW_TYPE] = 't', + [KW_KIND] = 'k', + }; + int ret = -1; + int i = 0; + + GF_ASSERT (cmd); + free_ptr = opts = GF_CALLOC (1, strlen (cmd), gf_common_mt_char); + if (!opts) + goto out; + + if (sscanf (cmd, GF_XATTR_CLRLK_CMD".%s", opts) < 1) { + ret = -1; + goto out; + } + + /*clr_lk_prefix.ttype.kkind.args, args - type specific*/ + cur = opts; + for (i = 0; i < KW_MAX && (tok = strtok_r (cur, ".", &sptr)); + cur = NULL, i++) { + if (tok[0] != kw[i]) { + ret = -1; + goto out; + } + if (i == KW_TYPE) + args->type = clrlk_get_type (tok+1); + if (i == KW_KIND) + args->kind = clrlk_get_kind (tok+1); + } + + if ((args->type == CLRLK_TYPE_MAX) || (args->kind == CLRLK_KIND_MAX)) + goto out; + + /*optional args*/ + tok = strtok_r (NULL, ".", &sptr); + if (tok) + args->opts = gf_strdup (tok); + + ret = 0; +out: + if (free_ptr) + GF_FREE (free_ptr); + return ret; +} + +int +clrlk_clear_posixlk (xlator_t *this, pl_inode_t *pl_inode, clrlk_args *args, + int *blkd, int *granted, int *op_errno) +{ + posix_lock_t *plock = NULL; + posix_lock_t *tmp = NULL; + struct gf_flock ulock = {0, }; + int ret = -1; + int bcount = 0; + int gcount = 0; + gf_boolean_t chk_range = _gf_false; + + if (clrlk_get_lock_range (args->opts, &ulock, &chk_range)) { + *op_errno = EINVAL; + goto out; + } + + pthread_mutex_lock (&pl_inode->mutex); + { + list_for_each_entry_safe (plock, tmp, &pl_inode->ext_list, + list) { + if ((plock->blocked && + !(args->kind & CLRLK_BLOCKED)) || + (!plock->blocked && + !(args->kind & CLRLK_GRANTED))) + continue; + + if (chk_range && + (plock->user_flock.l_whence != ulock.l_whence + || plock->user_flock.l_start != ulock.l_start + || plock->user_flock.l_len != ulock.l_len)) + continue; + + list_del_init (&plock->list); + if (plock->blocked) { + bcount++; + pl_trace_out (this, plock->frame, NULL, NULL, + F_SETLKW, &plock->user_flock, + -1, EAGAIN, NULL); + + STACK_UNWIND (plock->frame, -1, EAGAIN, + &plock->user_flock); + + } else { + gcount++; + } + GF_FREE (plock); + } + } + pthread_mutex_unlock (&pl_inode->mutex); + grant_blocked_locks (this, pl_inode); +out: + *blkd = bcount; + *granted = gcount; + return ret; +} + +/* Returns 0 on success and -1 on failure */ +int +clrlk_clear_inodelk (xlator_t *this, pl_inode_t *pl_inode, pl_dom_list_t *dom, + clrlk_args *args, int *blkd, int *granted, int *op_errno) +{ + pl_inode_lock_t *ilock = NULL; + pl_inode_lock_t *tmp = NULL; + struct gf_flock ulock = {0, }; + int ret = -1; + int bcount = 0; + int gcount = 0; + gf_boolean_t chk_range = _gf_false; + + if (clrlk_get_lock_range (args->opts, &ulock, &chk_range)) { + *op_errno = EINVAL; + goto out; + } + + if (args->kind & CLRLK_BLOCKED) + goto blkd; + + if (args->kind & CLRLK_GRANTED) + goto granted; + +blkd: + pthread_mutex_lock (&pl_inode->mutex); + { + list_for_each_entry_safe (ilock, tmp, &dom->blocked_inodelks, + blocked_locks) { + if (chk_range && + (ilock->user_flock.l_whence != ulock.l_whence + || ilock->user_flock.l_start != ulock.l_start + || ilock->user_flock.l_len != ulock.l_len)) + continue; + + bcount++; + list_del_init (&ilock->list); + pl_trace_out (this, ilock->frame, NULL, NULL, F_SETLKW, + &ilock->user_flock, -1, EAGAIN, + ilock->volume); + STACK_UNWIND_STRICT (inodelk, ilock->frame, -1, + EAGAIN); + GF_FREE (ilock); + } + } + pthread_mutex_unlock (&pl_inode->mutex); + + if (!(args->kind & CLRLK_GRANTED)) { + ret = 0; + goto out; + } + +granted: + pthread_mutex_lock (&pl_inode->mutex); + { + list_for_each_entry_safe (ilock, tmp, &dom->inodelk_list, + list) { + if (chk_range && + (ilock->user_flock.l_whence != ulock.l_whence + || ilock->user_flock.l_start != ulock.l_start + || ilock->user_flock.l_len != ulock.l_len)) + continue; + + gcount++; + list_del_init (&ilock->list); + GF_FREE (ilock); + } + } + pthread_mutex_unlock (&pl_inode->mutex); + + grant_blocked_inode_locks (this, pl_inode, dom); + ret = 0; +out: + *blkd = bcount; + *granted = gcount; + return ret; +} + +/* Returns 0 on success and -1 on failure */ +int +clrlk_clear_entrylk (xlator_t *this, pl_inode_t *pl_inode, pl_dom_list_t *dom, + clrlk_args *args, int *blkd, int *granted, int *op_errno) +{ + pl_entry_lock_t *elock = NULL; + pl_entry_lock_t *tmp = NULL; + struct list_head removed = {0}; + int bcount = 0; + int gcount = 0; + int ret = -1; + + if (args->kind & CLRLK_BLOCKED) + goto blkd; + + if (args->kind & CLRLK_GRANTED) + goto granted; + +blkd: + pthread_mutex_lock (&pl_inode->mutex); + { + list_for_each_entry_safe (elock, tmp, &dom->blocked_entrylks, + blocked_locks) { + if (args->opts && + strncmp (elock->basename, args->opts, + strlen (elock->basename))) + continue; + + bcount++; + list_del_init (&elock->domain_list); + STACK_UNWIND_STRICT (entrylk, elock->frame, -1, + EAGAIN); + GF_FREE ((char *) elock->basename); + GF_FREE (elock); + } + } + pthread_mutex_unlock (&pl_inode->mutex); + + if (!(args->kind & CLRLK_GRANTED)) { + ret = 0; + goto out; + } + +granted: + INIT_LIST_HEAD (&removed); + pthread_mutex_lock (&pl_inode->mutex); + { + list_for_each_entry_safe (elock, tmp, &dom->entrylk_list, + domain_list) { + if (!elock->basename) + continue; + + if (args->opts && + strncmp (elock->basename, args->opts, + strlen (elock->basename))) + continue; + + gcount++; + list_del_init (&elock->domain_list); + list_add_tail (&elock->domain_list, &removed); + } + } + pthread_mutex_unlock (&pl_inode->mutex); + + list_for_each_entry_safe (elock, tmp, &removed, domain_list) { + grant_blocked_entry_locks (this, pl_inode, elock, dom); + } + + ret = 0; +out: + *blkd = bcount; + *granted = gcount; + return ret; +} + +int +clrlk_clear_lks_in_all_domains (xlator_t *this, pl_inode_t *pl_inode, + clrlk_args *args, int *blkd, int *granted, + int *op_errno) +{ + pl_dom_list_t *dom = NULL; + int ret = -1; + int tmp_bcount = 0; + int tmp_gcount = 0; + + if (list_empty (&pl_inode->dom_list)) { + ret = 0; + goto out; + } + + list_for_each_entry (dom, &pl_inode->dom_list, inode_list) { + tmp_bcount = tmp_gcount = 0; + + switch (args->type) + { + case CLRLK_INODE: + ret = clrlk_clear_inodelk (this, pl_inode, dom, args, + &tmp_bcount, &tmp_gcount, + op_errno); + if (ret) + goto out; + break; + case CLRLK_ENTRY: + ret = clrlk_clear_entrylk (this, pl_inode, dom, args, + &tmp_bcount, &tmp_gcount, + op_errno); + if (ret) + goto out; + break; + } + + *blkd += tmp_bcount; + *granted += tmp_gcount; + } + + ret = 0; +out: + return ret; +} diff --git a/xlators/features/locks/src/clear.h b/xlators/features/locks/src/clear.h new file mode 100644 index 00000000000..95572a9710e --- /dev/null +++ b/xlators/features/locks/src/clear.h @@ -0,0 +1,86 @@ +/* + Copyright (c) 2006-2011 Gluster, Inc. + This file is part of GlusterFS. + + GlusterFS is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3 of the License, + or (at your option) any later version. + + GlusterFS is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see + . +*/ + +#ifndef __CLEAR_H__ +#define __CLEAR_H__ + +#ifndef _CONFIG_H +#define _CONFIG_H +#include "config.h" +#endif + +#include "compat-errno.h" +#include "stack.h" +#include "call-stub.h" +#include "locks.h" + +typedef enum { + CLRLK_INODE, + CLRLK_ENTRY, + CLRLK_POSIX, + CLRLK_TYPE_MAX +} clrlk_type; + +typedef enum { + CLRLK_BLOCKED = 1, + CLRLK_GRANTED, + CLRLK_ALL, + CLRLK_KIND_MAX +} clrlk_kind; + +typedef enum { + KW_TYPE, + KW_KIND, + /*add new keywords here*/ + KW_MAX +} clrlk_opts; + +struct _clrlk_args; +typedef struct _clrlk_args clrlk_args; + +struct _clrlk_args { + int type; + int kind; + char *opts; +}; + +int +clrlk_get__kind (char *kind); +int +clrlk_get_type (char *type); +int +clrlk_get_lock_range (char *range_str, struct gf_flock *ulock, + gf_boolean_t *chk_range); +int +clrlk_parse_args (const char* cmd, clrlk_args *args); + +int +clrlk_clear_posixlk (xlator_t *this, pl_inode_t *pl_inode, clrlk_args *args, + int *blkd, int *granted, int *op_errno); +int +clrlk_clear_inodelk (xlator_t *this, pl_inode_t *pl_inode, pl_dom_list_t *dom, + clrlk_args *args, int *blkd, int *granted, int *op_errno); +int +clrlk_clear_entrylk (xlator_t *this, pl_inode_t *pl_inode, pl_dom_list_t *dom, + clrlk_args *args, int *blkd, int *granted, int *op_errno); +int +clrlk_clear_lks_in_all_domains (xlator_t *this, pl_inode_t *pl_inode, + clrlk_args *args, int *blkd, int *granted, + int *op_errno); +#endif /* __CLEAR_H__ */ diff --git a/xlators/features/locks/src/posix.c b/xlators/features/locks/src/posix.c index 7ce4ec942be..bd30ca4937d 100644 --- a/xlators/features/locks/src/posix.c +++ b/xlators/features/locks/src/posix.c @@ -37,6 +37,7 @@ #include "locks.h" #include "common.h" #include "statedump.h" +#include "clear.h" #ifndef LLONG_MAX #define LLONG_MAX LONG_LONG_MAX /* compat with old gcc */ @@ -352,6 +353,114 @@ __delete_locks_of_owner (pl_inode_t *pl_inode, return; } + +int32_t +pl_getxattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, dict_t *dict) +{ + STACK_UNWIND_STRICT (getxattr, frame, op_ret, op_errno, dict); + return 0; + +} + +int32_t +pl_getxattr (call_frame_t *frame, xlator_t *this, loc_t *loc, + const char *name) +{ + int op_errno = EINVAL; + int op_ret = -1; + int32_t bcount = 0; + int32_t gcount = 0; + char key[PATH_MAX] = {0, }; + char *lk_summary = NULL; + pl_inode_t *pl_inode = NULL; + dict_t *dict = NULL; + clrlk_args args = {0,}; + + if (!name) + goto usual; + + if (strncmp (name, GF_XATTR_CLRLK_CMD, strlen (GF_XATTR_CLRLK_CMD))) + goto usual; + + if (clrlk_parse_args (name, &args)) { + op_errno = EINVAL; + goto out; + } + + dict = dict_new (); + if (!dict) { + op_errno = ENOMEM; + goto out; + } + + pl_inode = pl_inode_get (this, loc->inode); + if (!pl_inode) { + op_errno = ENOMEM; + goto out; + } + + switch (args.type) { + case CLRLK_INODE: + case CLRLK_ENTRY: + op_ret = clrlk_clear_lks_in_all_domains (this, pl_inode, + &args, &bcount, + &gcount, + &op_errno); + if (op_ret) + goto out; + break; + case CLRLK_POSIX: + op_ret = clrlk_clear_posixlk (this, pl_inode, &args, + &bcount, &gcount, + &op_errno); + if (op_ret) + goto out; + break; + case CLRLK_TYPE_MAX: + op_errno = EINVAL; + goto out; + } + + if (!gcount && !bcount) { + if (gf_asprintf (&lk_summary, "No locks cleared.") == -1) { + op_errno = ENOMEM; + goto out; + } + } else if (gf_asprintf (&lk_summary, "%s: %s blocked locks=%d " + "granted locks=%d", this->name, + (args.type == CLRLK_INODE)? "inode": + (args.type == CLRLK_ENTRY)? "entry": + (args.type == CLRLK_POSIX)? "posix": " ", + bcount, gcount) == -1) { + op_errno = ENOMEM; + goto out; + } + + strncpy (key, name, strlen (name)); + if (dict_set_dynstr (dict, key, lk_summary)) { + op_errno = ENOMEM; + goto out; + } + + op_ret = 0; +out: + STACK_UNWIND_STRICT (getxattr, frame, op_ret, op_errno, dict); + + if (args.opts) + GF_FREE (args.opts); + if (op_ret && lk_summary) + GF_FREE (lk_summary); + if (dict) + dict_unref (dict); + return 0; + +usual: + STACK_WIND (frame, pl_getxattr_cbk, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->getxattr, loc, name); + return 0; +} + int32_t pl_opendir_cbk (call_frame_t *frame, void *cookie, @@ -1980,8 +2089,8 @@ struct xlator_fops fops = { .fentrylk = pl_fentrylk, .flush = pl_flush, .opendir = pl_opendir, - .readdirp = pl_readdirp, + .getxattr = pl_getxattr, }; struct xlator_dumpops dumpops = { -- cgit