diff options
| author | Krishnan Parthasarathi <kp@gluster.com> | 2011-11-16 16:23:48 +0530 | 
|---|---|---|
| committer | Vijay Bellur <vijay@gluster.com> | 2012-02-14 02:48:59 -0800 | 
| commit | b27512e006ae55777f481937d321f60fa195c48d (patch) | |
| tree | d84c8cf1e5d34849da39ef9f936553d05fae1a2c | |
| parent | 58a538e99806ae84ec4d4bf03aa726302e16d07b (diff) | |
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<type>.k<kind>[.{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 <kp@gluster.com>
Reviewed-on: http://review.gluster.com/2551
Tested-by: Gluster Build System <jenkins@build.gluster.com>
Reviewed-by: Vijay Bellur <vijay@gluster.com>
| -rw-r--r-- | libglusterfs/src/glusterfs.h | 1 | ||||
| -rw-r--r-- | xlators/cluster/afr/src/afr-common.c | 24 | ||||
| -rw-r--r-- | xlators/cluster/afr/src/afr-inode-read.c | 178 | ||||
| -rw-r--r-- | xlators/features/locks/src/Makefile.am | 12 | ||||
| -rw-r--r-- | xlators/features/locks/src/clear.c | 409 | ||||
| -rw-r--r-- | xlators/features/locks/src/clear.h | 86 | ||||
| -rw-r--r-- | xlators/features/locks/src/posix.c | 111 | 
7 files changed, 785 insertions, 36 deletions
diff --git a/libglusterfs/src/glusterfs.h b/libglusterfs/src/glusterfs.h index 680f0de98f2..8360077ecf7 100644 --- a/libglusterfs/src/glusterfs.h +++ b/libglusterfs/src/glusterfs.h @@ -79,6 +79,7 @@  #define ZR_STRICT_VOLFILE_CHECK "strict-volfile-check"  #define ZR_DUMP_FUSE            "dump-fuse" +#define GF_XATTR_CLRLK_CMD      "glusterfs.clrlk"  #define GF_XATTR_PATHINFO_KEY   "trusted.glusterfs.pathinfo"  #define GF_XATTR_LINKINFO_KEY   "trusted.distribute.linkinfo"  #define GFID_XATTR_KEY "trusted.gfid" 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 @@ -632,6 +632,101 @@ afr_getxattr_unwind (call_frame_t *frame,  }  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,                             dict_t *dict) @@ -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. <http://www.gluster.com> +  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 +  <http://www.gnu.org/licenses/>. +*/ + +#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 "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. <http://www.gluster.com> +  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 +  <http://www.gnu.org/licenses/>. +*/ + +#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 = {  | 
