diff options
Diffstat (limited to 'xlators/features/marker')
25 files changed, 1655 insertions, 2904 deletions
diff --git a/xlators/features/marker/Makefile.am b/xlators/features/marker/Makefile.am index a6ba2de16..a985f42a8 100644 --- a/xlators/features/marker/Makefile.am +++ b/xlators/features/marker/Makefile.am @@ -1,3 +1,3 @@ -SUBDIRS = src @SYNCDAEMON_SUBDIR@ +SUBDIRS = src CLEANFILES = diff --git a/xlators/features/marker/src/Makefile.am b/xlators/features/marker/src/Makefile.am index 501586a76..a7c676472 100644 --- a/xlators/features/marker/src/Makefile.am +++ b/xlators/features/marker/src/Makefile.am @@ -1,15 +1,17 @@ xlator_LTLIBRARIES = marker.la xlatordir = $(libdir)/glusterfs/$(PACKAGE_VERSION)/xlator/features -marker_la_LDFLAGS = -module -avoidversion +marker_la_LDFLAGS = -module -avoid-version marker_la_SOURCES = marker.c marker-quota.c marker-quota-helper.c marker-common.c marker_la_LIBADD = $(top_builddir)/libglusterfs/src/libglusterfs.la noinst_HEADERS = marker-mem-types.h marker.h marker-quota.h marker-quota-helper.h marker-common.h $(top_builddir)/xlators/lib/src/libxlator.h -AM_CFLAGS = -fPIC -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE -Wall -fno-strict-aliasing -D$(GF_HOST_OS) \ - -I$(top_srcdir)/libglusterfs/src -I$(top_srcdir)/xlators/lib/src $(GF_CFLAGS) -shared -nostartfiles +AM_CPPFLAGS = $(GF_CPPFLAGS) -I$(top_srcdir)/libglusterfs/src \ + -I$(top_srcdir)/xlators/lib/src + +AM_CFLAGS = -Wall -fno-strict-aliasing $(GF_CFLAGS) CLEANFILES = diff --git a/xlators/features/marker/src/marker-common.c b/xlators/features/marker/src/marker-common.c index dac08ec55..84a718add 100644 --- a/xlators/features/marker/src/marker-common.c +++ b/xlators/features/marker/src/marker-common.c @@ -1,21 +1,12 @@ -/*Copyright (c) 2008-2010 Gluster, Inc. <http://www.gluster.com> - This file is part of GlusterFS. +/* + Copyright (c) 2008-2012 Red Hat, Inc. <http://www.redhat.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/>. + 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" @@ -69,18 +60,10 @@ unlock: UNLOCK (&inode->lock); return ret; } -void +int marker_filter_quota_xattr (dict_t *dict, char *key, data_t *value, void *data) { - int ret = -1; - - GF_VALIDATE_OR_GOTO ("marker", dict, out); - GF_VALIDATE_OR_GOTO ("marker", key, out); - - ret = fnmatch ("trusted.glusterfs.quota*", key, 0); - if (ret == 0) - dict_del (dict, key); -out: - return; + dict_del (dict, key); + return 0; } diff --git a/xlators/features/marker/src/marker-common.h b/xlators/features/marker/src/marker-common.h index 2533571c1..23dd846cb 100644 --- a/xlators/features/marker/src/marker-common.h +++ b/xlators/features/marker/src/marker-common.h @@ -1,21 +1,12 @@ -/*Copyright (c) 2008-2010 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/>. +/* + Copyright (c) 2008-2012 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 _MARKER_COMMON_H #define _MARKER_COMMON_H @@ -31,6 +22,6 @@ int32_t marker_force_inode_ctx_get (inode_t *, xlator_t *, marker_inode_ctx_t **); -void +int marker_filter_quota_xattr (dict_t *, char *, data_t *, void *); #endif diff --git a/xlators/features/marker/src/marker-mem-types.h b/xlators/features/marker/src/marker-mem-types.h index 847bfa67c..1f74d5048 100644 --- a/xlators/features/marker/src/marker-mem-types.h +++ b/xlators/features/marker/src/marker-mem-types.h @@ -1,36 +1,24 @@ /* - Copyright (c) 2008-2010 Gluster, Inc. <http://www.gluster.com> + Copyright (c) 2008-2012 Red Hat, Inc. <http://www.redhat.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 Affero 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 - Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see - <http://www.gnu.org/licenses/>. + 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 __MARKER_MEM_TYPES_H__ #define __MARKER_MEM_TYPES_H__ #include "mem-types.h" enum gf_marker_mem_types_ { - gf_marker_mt_marker_local_t = gf_common_mt_end + 1, - gf_marker_mt_marker_conf_t, + gf_marker_mt_marker_conf_t = gf_common_mt_end + 1, gf_marker_mt_loc_t, gf_marker_mt_volume_mark, gf_marker_mt_int64_t, gf_marker_mt_quota_inode_ctx_t, gf_marker_mt_marker_inode_ctx_t, - gf_marker_mt_quota_local_t, gf_marker_mt_inode_contribution_t, gf_marker_mt_end }; diff --git a/xlators/features/marker/src/marker-quota-helper.c b/xlators/features/marker/src/marker-quota-helper.c index a559da808..af5fed132 100644 --- a/xlators/features/marker/src/marker-quota-helper.c +++ b/xlators/features/marker/src/marker-quota-helper.c @@ -1,21 +1,12 @@ -/*Copyright (c) 2008-2010 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/>. +/* + Copyright (c) 2008-2012 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" @@ -28,16 +19,19 @@ #include "marker-mem-types.h" int -quota_loc_fill (loc_t *loc, inode_t *inode, inode_t *parent, char *path) +mq_loc_fill (loc_t *loc, inode_t *inode, inode_t *parent, char *path) { int ret = -1; - if (!loc) - return ret; + GF_VALIDATE_OR_GOTO ("marker", loc, out); + GF_VALIDATE_OR_GOTO ("marker", inode, out); + GF_VALIDATE_OR_GOTO ("marker", path, out); + /* Not checking for parent because while filling + * loc of root, parent will be NULL + */ if (inode) { loc->inode = inode_ref (inode); - loc->ino = inode->ino; } if (parent) @@ -59,13 +53,13 @@ quota_loc_fill (loc_t *loc, inode_t *inode, inode_t *parent, char *path) loc_wipe: if (ret < 0) loc_wipe (loc); - +out: return ret; } int32_t -quota_inode_loc_fill (const char *parent_gfid, inode_t *inode, loc_t *loc) +mq_inode_loc_fill (const char *parent_gfid, inode_t *inode, loc_t *loc) { char *resolvedpath = NULL; inode_t *parent = NULL; @@ -74,7 +68,7 @@ quota_inode_loc_fill (const char *parent_gfid, inode_t *inode, loc_t *loc) if ((!inode) || (!loc)) return ret; - if ((inode) && (inode->ino == 1)) { + if ((inode) && __is_root_gfid (inode->gfid)) { loc->parent = NULL; goto ignore_parent; } @@ -93,7 +87,7 @@ ignore_parent: if (ret < 0) goto err; - ret = quota_loc_fill (loc, inode, parent, resolvedpath); + ret = mq_loc_fill (loc, inode, parent, resolvedpath); if (ret < 0) goto err; @@ -108,7 +102,7 @@ err: quota_inode_ctx_t * -quota_alloc_inode_ctx () +mq_alloc_inode_ctx () { int32_t ret = -1; quota_inode_ctx_t *ctx = NULL; @@ -119,6 +113,7 @@ quota_alloc_inode_ctx () ctx->size = 0; ctx->dirty = 0; + ctx->updation_status = _gf_false; LOCK_INIT (&ctx->lock); INIT_LIST_HEAD (&ctx->contribution_head); out: @@ -126,13 +121,13 @@ out: } inode_contribution_t * -get_contribution_node (inode_t *inode, quota_inode_ctx_t *ctx) +mq_get_contribution_node (inode_t *inode, quota_inode_ctx_t *ctx) { inode_contribution_t *contri = NULL; inode_contribution_t *temp = NULL; - GF_VALIDATE_OR_GOTO ("marker", inode, out); - GF_VALIDATE_OR_GOTO ("marker", ctx, out); + if (!inode || !ctx) + goto out; list_for_each_entry (temp, &ctx->contribution_head, contri_list) { if (uuid_compare (temp->gfid, inode->gfid) == 0) { @@ -146,8 +141,8 @@ out: int32_t -delete_contribution_node (dict_t *dict, char *key, - inode_contribution_t *contribution) +mq_delete_contribution_node (dict_t *dict, char *key, + inode_contribution_t *contribution) { if (dict_get (dict, key) != NULL) goto out; @@ -159,13 +154,25 @@ out: inode_contribution_t * -__add_new_contribution_node (xlator_t *this, quota_inode_ctx_t *ctx, loc_t *loc) +__mq_add_new_contribution_node (xlator_t *this, quota_inode_ctx_t *ctx, loc_t *loc) { int32_t ret = 0; inode_contribution_t *contribution = NULL; + if (!loc->parent) { + if (!uuid_is_null (loc->pargfid)) + loc->parent = inode_find (loc->inode->table, + loc->pargfid); + if (!loc->parent) + loc->parent = inode_parent (loc->inode, loc->pargfid, + loc->name); + if (!loc->parent) + goto out; + } + list_for_each_entry (contribution, &ctx->contribution_head, contri_list) { - if (uuid_compare (contribution->gfid, loc->parent->gfid) == 0) { + if (loc->parent && + uuid_compare (contribution->gfid, loc->parent->gfid) == 0) { goto out; } } @@ -179,6 +186,7 @@ __add_new_contribution_node (xlator_t *this, quota_inode_ctx_t *ctx, loc_t *loc) uuid_copy (contribution->gfid, loc->parent->gfid); LOCK_INIT (&contribution->lock); + INIT_LIST_HEAD (&contribution->contri_list); list_add_tail (&contribution->contri_list, &ctx->contribution_head); @@ -188,7 +196,7 @@ out: inode_contribution_t * -add_new_contribution_node (xlator_t *this, quota_inode_ctx_t *ctx, loc_t *loc) +mq_add_new_contribution_node (xlator_t *this, quota_inode_ctx_t *ctx, loc_t *loc) { inode_contribution_t *contribution = NULL; @@ -200,7 +208,7 @@ add_new_contribution_node (xlator_t *this, quota_inode_ctx_t *ctx, loc_t *loc) LOCK (&ctx->lock); { - contribution = __add_new_contribution_node (this, ctx, loc); + contribution = __mq_add_new_contribution_node (this, ctx, loc); } UNLOCK (&ctx->lock); @@ -209,8 +217,8 @@ add_new_contribution_node (xlator_t *this, quota_inode_ctx_t *ctx, loc_t *loc) int32_t -dict_set_contribution (xlator_t *this, dict_t *dict, - loc_t *loc) +mq_dict_set_contribution (xlator_t *this, dict_t *dict, + loc_t *loc) { int32_t ret = -1; char contri_key [512] = {0, }; @@ -218,6 +226,7 @@ dict_set_contribution (xlator_t *this, dict_t *dict, GF_VALIDATE_OR_GOTO ("marker", this, out); GF_VALIDATE_OR_GOTO ("marker", dict, out); GF_VALIDATE_OR_GOTO ("marker", loc, out); + GF_VALIDATE_OR_GOTO ("marker", loc->parent, out); GET_CONTRI_KEY (contri_key, loc->parent->gfid, ret); if (ret < 0) { @@ -240,8 +249,8 @@ out: int32_t -quota_inode_ctx_get (inode_t *inode, xlator_t *this, - quota_inode_ctx_t **ctx) +mq_inode_ctx_get (inode_t *inode, xlator_t *this, + quota_inode_ctx_t **ctx) { int32_t ret = -1; uint64_t ctx_int = 0; @@ -274,7 +283,7 @@ out: quota_inode_ctx_t * -__quota_inode_ctx_new (inode_t *inode, xlator_t *this) +__mq_inode_ctx_new (inode_t *inode, xlator_t *this) { int32_t ret = -1; quota_inode_ctx_t *quota_ctx = NULL; @@ -290,7 +299,7 @@ __quota_inode_ctx_new (inode_t *inode, xlator_t *this) LOCK (&inode->lock); { if (mark_ctx->quota_ctx == NULL) { - quota_ctx = quota_alloc_inode_ctx (); + quota_ctx = mq_alloc_inode_ctx (); if (quota_ctx == NULL) { ret = -1; goto unlock; @@ -310,29 +319,23 @@ out: quota_inode_ctx_t * -quota_inode_ctx_new (inode_t * inode, xlator_t *this) +mq_inode_ctx_new (inode_t * inode, xlator_t *this) { - return __quota_inode_ctx_new (inode, this); + return __mq_inode_ctx_new (inode, this); } quota_local_t * -quota_local_new () +mq_local_new () { - int32_t ret = -1; quota_local_t *local = NULL; - QUOTA_ALLOC (local, quota_local_t, ret); - if (ret < 0) + local = mem_get0 (THIS->local_pool); + if (!local) goto out; local->ref = 1; - local->delta = 0; - local->err = 0; LOCK_INIT (&local->lock); - memset (&local->loc, 0, sizeof (loc_t)); - memset (&local->parent_loc, 0, sizeof (loc_t)); - local->ctx = NULL; local->contri = NULL; @@ -341,7 +344,7 @@ out: } quota_local_t * -quota_local_ref (quota_local_t *local) +mq_local_ref (quota_local_t *local) { LOCK (&local->lock); { @@ -354,7 +357,7 @@ quota_local_ref (quota_local_t *local) int32_t -quota_local_unref (xlator_t *this, quota_local_t *local) +mq_local_unref (xlator_t *this, quota_local_t *local) { int32_t ref = 0; if (local == NULL) @@ -362,7 +365,7 @@ quota_local_unref (xlator_t *this, quota_local_t *local) QUOTA_SAFE_DECREMENT (&local->lock, local->ref, ref); - if (ref > 0) + if (ref != 0) goto out; if (local->fd != NULL) @@ -373,38 +376,36 @@ quota_local_unref (xlator_t *this, quota_local_t *local) loc_wipe (&local->parent_loc); LOCK_DESTROY (&local->lock); + + mem_put (local); out: return 0; } inode_contribution_t * -get_contribution_from_loc (xlator_t *this, loc_t *loc) +mq_get_contribution_from_loc (xlator_t *this, loc_t *loc) { int32_t ret = 0; quota_inode_ctx_t *ctx = NULL; inode_contribution_t *contribution = NULL; - ret = quota_inode_ctx_get (loc->inode, this, &ctx); + ret = mq_inode_ctx_get (loc->inode, this, &ctx); if (ret < 0) { gf_log_callingfn (this->name, GF_LOG_WARNING, "cannot get marker-quota context from inode " - "(ino: %"PRId64", gfid:%s, path:%s)", - loc->inode->ino, - uuid_utoa (loc->inode->gfid), - loc->path); + "(gfid:%s, path:%s)", + uuid_utoa (loc->inode->gfid), loc->path); goto err; } - contribution = get_contribution_node (loc->parent, ctx); + contribution = mq_get_contribution_node (loc->parent, ctx); if (contribution == NULL) { gf_log_callingfn (this->name, GF_LOG_WARNING, - "inode (ino:%"PRId64", gfid:%s, path:%s ) has" - " no contribution towards parent (ino:%"PRId64 - ", gfid:%s)", loc->inode->ino, + "inode (gfid:%s, path:%s) has " + "no contribution towards parent (gfid:%s)", uuid_utoa (loc->inode->gfid), - loc->path, loc->parent->ino, - uuid_utoa (loc->parent->gfid)); + loc->path, uuid_utoa (loc->parent->gfid)); goto err; } diff --git a/xlators/features/marker/src/marker-quota-helper.h b/xlators/features/marker/src/marker-quota-helper.h index 1c925ec7c..6cdd14881 100644 --- a/xlators/features/marker/src/marker-quota-helper.h +++ b/xlators/features/marker/src/marker-quota-helper.h @@ -1,20 +1,13 @@ -/*Copyright (c) 2008-2010 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/>. +/* + Copyright (c) 2008-2012 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 _MARKER_QUOTA_HELPER_H #define _MARKER_QUOTA_HELPER @@ -23,7 +16,7 @@ #include "config.h" #endif -#include "marker-quota.h" +#include "marker.h" #define QUOTA_FREE_CONTRIBUTION_NODE(_contribution) \ do { \ @@ -48,36 +41,36 @@ } while (0) inode_contribution_t * -add_new_contribution_node (xlator_t *, quota_inode_ctx_t *, loc_t *); +mq_add_new_contribution_node (xlator_t *, quota_inode_ctx_t *, loc_t *); int32_t -dict_set_contribution (xlator_t *, dict_t *, loc_t *); +mq_dict_set_contribution (xlator_t *, dict_t *, loc_t *); quota_inode_ctx_t * -quota_inode_ctx_new (inode_t *, xlator_t *); +mq_inode_ctx_new (inode_t *, xlator_t *); int32_t -quota_inode_ctx_get (inode_t *, xlator_t *, quota_inode_ctx_t **); +mq_inode_ctx_get (inode_t *, xlator_t *, quota_inode_ctx_t **); int32_t -delete_contribution_node (dict_t *, char *, inode_contribution_t *); +mq_delete_contribution_node (dict_t *, char *, inode_contribution_t *); int32_t -quota_inode_loc_fill (const char *, inode_t *, loc_t *); +mq_inode_loc_fill (const char *, inode_t *, loc_t *); quota_local_t * -quota_local_new (); +mq_local_new (); quota_local_t * -quota_local_ref (quota_local_t *); +mq_local_ref (quota_local_t *); int32_t -quota_local_unref (xlator_t *, quota_local_t *); +mq_local_unref (xlator_t *, quota_local_t *); inode_contribution_t * -get_contribution_node (inode_t *, quota_inode_ctx_t *); +mq_get_contribution_node (inode_t *, quota_inode_ctx_t *); inode_contribution_t * -get_contribution_from_loc (xlator_t *this, loc_t *loc); +mq_get_contribution_from_loc (xlator_t *this, loc_t *loc); #endif diff --git a/xlators/features/marker/src/marker-quota.c b/xlators/features/marker/src/marker-quota.c index 8caf5b0c0..6f9af6e13 100644 --- a/xlators/features/marker/src/marker-quota.c +++ b/xlators/features/marker/src/marker-quota.c @@ -1,21 +1,12 @@ -/*Copyright (c) 2008-2010 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/>. +/* + Copyright (c) 2008-2012 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" @@ -30,6 +21,110 @@ #include "marker-quota.h" #include "marker-quota-helper.h" +int +mq_loc_copy (loc_t *dst, loc_t *src) +{ + int ret = -1; + + GF_VALIDATE_OR_GOTO ("marker", dst, out); + GF_VALIDATE_OR_GOTO ("marker", src, out); + + if (src->inode == NULL || + src->path == NULL) { + gf_log ("marker", GF_LOG_WARNING, + "src loc is not valid"); + goto out; + } + + ret = loc_copy (dst, src); +out: + return ret; +} + +int32_t +mq_get_local_err (quota_local_t *local, + int32_t *val) +{ + int32_t ret = -1; + + GF_VALIDATE_OR_GOTO ("marker", local, out); + GF_VALIDATE_OR_GOTO ("marker", val, out); + + LOCK (&local->lock); + { + *val = local->err; + } + UNLOCK (&local->lock); + + ret = 0; +out: + return ret; +} + +int32_t +mq_get_ctx_updation_status (quota_inode_ctx_t *ctx, + gf_boolean_t *status) +{ + int32_t ret = -1; + + GF_VALIDATE_OR_GOTO ("marker", ctx, out); + GF_VALIDATE_OR_GOTO ("marker", status, out); + + LOCK (&ctx->lock); + { + *status = ctx->updation_status; + } + UNLOCK (&ctx->lock); + + ret = 0; +out: + return ret; +} + + +int32_t +mq_set_ctx_updation_status (quota_inode_ctx_t *ctx, + gf_boolean_t status) +{ + int32_t ret = -1; + + if (ctx == NULL) + goto out; + + LOCK (&ctx->lock); + { + ctx->updation_status = status; + } + UNLOCK (&ctx->lock); + + ret = 0; +out: + return ret; +} + +int32_t +mq_test_and_set_ctx_updation_status (quota_inode_ctx_t *ctx, + gf_boolean_t *status) +{ + int32_t ret = -1; + gf_boolean_t temp = _gf_false; + + GF_VALIDATE_OR_GOTO ("marker", ctx, out); + GF_VALIDATE_OR_GOTO ("marker", status, out); + + LOCK (&ctx->lock); + { + temp = *status; + *status = ctx->updation_status; + ctx->updation_status = temp; + } + UNLOCK (&ctx->lock); + + ret = 0; +out: + return ret; +} + void mq_assign_lk_owner (xlator_t *this, call_frame_t *frame) { @@ -48,15 +143,15 @@ mq_assign_lk_owner (xlator_t *this, call_frame_t *frame) } UNLOCK (&conf->lock); - frame->root->lk_owner = lk_owner; + set_lk_owner_from_uint64 (&frame->root->lk_owner, lk_owner); return; } int32_t -loc_fill_from_name (xlator_t *this, loc_t *newloc, loc_t *oldloc, - uint64_t ino, char *name) +mq_loc_fill_from_name (xlator_t *this, loc_t *newloc, loc_t *oldloc, + uint64_t ino, char *name) { int32_t ret = -1; int32_t len = 0; @@ -67,8 +162,6 @@ loc_fill_from_name (xlator_t *this, loc_t *newloc, loc_t *oldloc, GF_VALIDATE_OR_GOTO ("marker", oldloc, out); GF_VALIDATE_OR_GOTO ("marker", name, out); - newloc->ino = ino; - newloc->inode = inode_new (oldloc->inode->table); if (!newloc->inode) { @@ -77,6 +170,7 @@ loc_fill_from_name (xlator_t *this, loc_t *newloc, loc_t *oldloc, } newloc->parent = inode_ref (oldloc->inode); + uuid_copy (newloc->pargfid, oldloc->inode->gfid); len = strlen (oldloc->path); @@ -104,37 +198,29 @@ out: } int32_t -dirty_inode_updation_done (call_frame_t *frame, void *cookie, xlator_t *this, - int32_t op_ret, int32_t op_errno) +mq_dirty_inode_updation_done (call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, dict_t *xdata) { - quota_local_t *local = NULL; - int32_t value = 0; - - local = frame->local; - - if (!local->err) - QUOTA_SAFE_DECREMENT (&local->lock, local->ref, value); - else - frame->local = NULL; - QUOTA_STACK_DESTROY (frame, this); return 0; } int32_t -release_lock_on_dirty_inode (call_frame_t *frame, void *cookie, xlator_t *this, - int32_t op_ret, int32_t op_errno) +mq_release_lock_on_dirty_inode (call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, dict_t *xdata) { struct gf_flock lock = {0, }; quota_local_t *local = NULL; + loc_t loc = {0, }; + int ret = -1; local = frame->local; if (op_ret == -1) { local->err = -1; - dirty_inode_updation_done (frame, NULL, this, 0, 0); + mq_dirty_inode_updation_done (frame, NULL, this, 0, 0, NULL); return 0; } @@ -148,32 +234,50 @@ release_lock_on_dirty_inode (call_frame_t *frame, void *cookie, xlator_t *this, lock.l_len = 0; lock.l_pid = 0; + ret = loc_copy (&loc, &local->loc); + if (ret == -1) { + local->err = -1; + frame->local = NULL; + mq_dirty_inode_updation_done (frame, NULL, this, 0, 0, NULL); + return 0; + } + + if (local->loc.inode == NULL) { + gf_log (this->name, GF_LOG_WARNING, + "Inode is NULL, so can't stackwind."); + goto out; + } + STACK_WIND (frame, - dirty_inode_updation_done, + mq_dirty_inode_updation_done, FIRST_CHILD(this), FIRST_CHILD(this)->fops->inodelk, - this->name, &local->loc, F_SETLKW, &lock); + this->name, &loc, F_SETLKW, &lock, NULL); + + loc_wipe (&loc); + + return 0; +out: + mq_dirty_inode_updation_done (frame, NULL, this, -1, 0, NULL); return 0; } int32_t -mark_inode_undirty (call_frame_t *frame, void *cookie, xlator_t *this, - int32_t op_ret, int32_t op_errno, dict_t *dict) +mq_mark_inode_undirty (call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, dict_t *dict, + dict_t *xdata) { int32_t ret = -1; int64_t *size = NULL; dict_t *newdict = NULL; quota_local_t *local = NULL; - marker_conf_t *priv = NULL; local = (quota_local_t *) frame->local; if (op_ret == -1) goto err; - priv = (marker_conf_t *) this->private; - if (!dict) goto wind; @@ -196,17 +300,21 @@ wind: if (ret) goto err; - STACK_WIND (frame, release_lock_on_dirty_inode, + if (uuid_is_null (local->loc.gfid)) + uuid_copy (local->loc.gfid, local->loc.inode->gfid); + + GF_UUID_ASSERT (local->loc.gfid); + STACK_WIND (frame, mq_release_lock_on_dirty_inode, FIRST_CHILD(this), FIRST_CHILD(this)->fops->setxattr, - &local->loc, newdict, 0); + &local->loc, newdict, 0, NULL); ret = 0; err: if (op_ret == -1 || ret == -1) { local->err = -1; - release_lock_on_dirty_inode (frame, NULL, this, 0, 0); + mq_release_lock_on_dirty_inode (frame, NULL, this, 0, 0, NULL); } if (newdict) @@ -216,24 +324,21 @@ err: } int32_t -update_size_xattr (call_frame_t *frame, void *cookie, xlator_t *this, - int32_t op_ret, int32_t op_errno, inode_t *inode, - struct iatt *buf, dict_t *dict, struct iatt *postparent) +mq_update_size_xattr (call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, inode_t *inode, + struct iatt *buf, dict_t *dict, struct iatt *postparent) { int32_t ret = -1; dict_t *new_dict = NULL; int64_t *size = NULL; int64_t *delta = NULL; quota_local_t *local = NULL; - marker_conf_t *priv = NULL; local = frame->local; if (op_ret == -1) goto err; - priv = this->private; - if (dict == NULL) { gf_log (this->name, GF_LOG_WARNING, "Dict is null while updating the size xattr %s", @@ -265,9 +370,14 @@ update_size_xattr (call_frame_t *frame, void *cookie, xlator_t *this, if (ret) goto err; - STACK_WIND (frame, mark_inode_undirty, FIRST_CHILD(this), + if (uuid_is_null (local->loc.gfid)) + uuid_copy (local->loc.gfid, buf->ia_gfid); + + GF_UUID_ASSERT (local->loc.gfid); + + STACK_WIND (frame, mq_mark_inode_undirty, FIRST_CHILD(this), FIRST_CHILD(this)->fops->xattrop, &local->loc, - GF_XATTROP_ADD_ARRAY64, new_dict); + GF_XATTROP_ADD_ARRAY64, new_dict, NULL); ret = 0; @@ -275,7 +385,7 @@ err: if (op_ret == -1 || ret == -1) { local->err = -1; - release_lock_on_dirty_inode (frame, NULL, this, 0, 0); + mq_release_lock_on_dirty_inode (frame, NULL, this, 0, 0, NULL); } if (new_dict) @@ -285,17 +395,37 @@ err: } int32_t -get_dirty_inode_size (call_frame_t *frame, xlator_t *this) +mq_test_and_set_local_err(quota_local_t *local, + int32_t *val) +{ + int tmp = 0; + int32_t ret = -1; + + GF_VALIDATE_OR_GOTO ("marker", local, out); + GF_VALIDATE_OR_GOTO ("marker", val, out); + + LOCK (&local->lock); + { + tmp = local->err; + local->err = *val; + *val = tmp; + } + UNLOCK (&local->lock); + + ret = 0; +out: + return ret; +} + +int32_t +mq_get_dirty_inode_size (call_frame_t *frame, xlator_t *this) { int32_t ret = -1; dict_t *dict = NULL; quota_local_t *local = NULL; - marker_conf_t *priv = NULL; local = (quota_local_t *) frame->local; - priv = (marker_conf_t *) this->private; - dict = dict_new (); if (!dict) { ret = -1; @@ -306,7 +436,12 @@ get_dirty_inode_size (call_frame_t *frame, xlator_t *this) if (ret) goto err; - STACK_WIND (frame, update_size_xattr, FIRST_CHILD(this), + if (uuid_is_null (local->loc.gfid)) + uuid_copy (local->loc.gfid, local->loc.inode->gfid); + + GF_UUID_ASSERT (local->loc.gfid); + + STACK_WIND (frame, mq_update_size_xattr, FIRST_CHILD(this), FIRST_CHILD(this)->fops->lookup, &local->loc, dict); ret =0; @@ -314,22 +449,25 @@ err: if (ret) { local->err = -1; - release_lock_on_dirty_inode (frame, NULL, this, 0, 0); + mq_release_lock_on_dirty_inode (frame, NULL, this, 0, 0, NULL); } + if (dict) + dict_unref (dict); + return 0; } int32_t -get_child_contribution (call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno, - inode_t *inode, - struct iatt *buf, - dict_t *dict, - struct iatt *postparent) +mq_get_child_contribution (call_frame_t *frame, + void *cookie, + xlator_t *this, + int32_t op_ret, + int32_t op_errno, + inode_t *inode, + struct iatt *buf, + dict_t *dict, + struct iatt *postparent) { int32_t ret = -1; int32_t val = 0; @@ -344,17 +482,20 @@ get_child_contribution (call_frame_t *frame, QUOTA_STACK_DESTROY (frame, this); if (op_ret == -1) { - gf_log (this->name, GF_LOG_ERROR, "%s", strerror (op_errno)); - - local->err = -2; - - release_lock_on_dirty_inode (local->frame, NULL, this, 0, 0); + gf_log (this->name, GF_LOG_ERROR, "%s", + strerror (op_errno)); + val = -2; + if (!mq_test_and_set_local_err (local, &val) && + val != -2) + mq_release_lock_on_dirty_inode (local->frame, NULL, + this, 0, 0, NULL); - goto out; + goto exit; } - if (local->err) - goto out; + ret = mq_get_local_err (local, &val); + if (!ret && val == -2) + goto exit; GET_CONTRI_KEY (contri_key, local->loc.inode->gfid, ret); if (ret < 0) @@ -373,29 +514,29 @@ out: } UNLOCK (&local->lock); - if (val== 0) { - if (local->err) { - QUOTA_SAFE_DECREMENT (&local->lock, local->ref, val); - - quota_local_unref (this, local); - } else - quota_dirty_inode_readdir (local->frame, NULL, this, - 0, 0, NULL); + if (val == 0) { + mq_dirty_inode_readdir (local->frame, NULL, this, + 0, 0, NULL, NULL); } + mq_local_unref (this, local); return 0; +exit: + mq_local_unref (this, local); + return 0; } int32_t -quota_readdir_cbk (call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno, - gf_dirent_t *entries) +mq_readdir_cbk (call_frame_t *frame, + void *cookie, + xlator_t *this, + int32_t op_ret, + int32_t op_errno, + gf_dirent_t *entries, dict_t *xdata) { char contri_key [512] = {0, }; int32_t ret = 0; + int32_t val = 0; off_t offset = 0; int32_t count = 0; dict_t *dict = NULL; @@ -404,20 +545,20 @@ quota_readdir_cbk (call_frame_t *frame, call_frame_t *newframe = NULL; loc_t loc = {0, }; - local = frame->local; + local = mq_local_ref (frame->local); if (op_ret == -1) { gf_log (this->name, GF_LOG_DEBUG, "readdir failed %s", strerror (op_errno)); local->err = -1; - release_lock_on_dirty_inode (frame, NULL, this, 0, 0); + mq_release_lock_on_dirty_inode (frame, NULL, this, 0, 0, NULL); - return 0; + goto end; } else if (op_ret == 0) { - get_dirty_inode_size (frame, this); + mq_get_dirty_inode_size (frame, this); - return 0; + goto end; } local->dentry_child_count = 0; @@ -436,16 +577,20 @@ quota_readdir_cbk (call_frame_t *frame, count++; } + if (count == 0) { + mq_get_dirty_inode_size (frame, this); + goto end; + + } + local->frame = frame; - if (count > 0) { - LOCK (&local->lock); - { - local->dentry_child_count = count; - local->d_off = offset; - } - UNLOCK (&local->lock); + LOCK (&local->lock); + { + local->dentry_child_count = count; + local->d_off = offset; } + UNLOCK (&local->lock); list_for_each_entry (entry, (&entries->list), list) { @@ -458,18 +603,29 @@ quota_readdir_cbk (call_frame_t *frame, continue; } - ret = loc_fill_from_name (this, &loc, &local->loc, - entry->d_ino, entry->d_name); + ret = mq_loc_fill_from_name (this, &loc, &local->loc, + entry->d_ino, entry->d_name); if (ret < 0) goto out; - newframe = copy_frame (frame); - if (!newframe) { - ret = -1; - goto out; + ret = 0; + + LOCK (&local->lock); + { + if (local->err != -2) { + newframe = copy_frame (frame); + if (!newframe) { + ret = -1; + } + } else + ret = -1; } + UNLOCK (&local->lock); + + if (ret == -1) + goto out; - newframe->local = local; + newframe->local = mq_local_ref (local); dict = dict_new (); if (!dict) { @@ -486,7 +642,7 @@ quota_readdir_cbk (call_frame_t *frame, goto out; STACK_WIND (newframe, - get_child_contribution, + mq_get_child_contribution, FIRST_CHILD(this), FIRST_CHILD(this)->fops->lookup, &loc, dict); @@ -495,6 +651,8 @@ quota_readdir_cbk (call_frame_t *frame, loc_wipe (&loc); + newframe = NULL; + out: if (dict) { dict_unref (dict); @@ -502,18 +660,12 @@ quota_readdir_cbk (call_frame_t *frame, } if (ret) { - LOCK (&local->lock); - { - if (local->dentry_child_count == 0) - local->err = -1; - else - local->err = -2; - } - UNLOCK (&local->lock); + val = -2; + mq_test_and_set_local_err (local, &val); if (newframe) { newframe->local = NULL; - + mq_local_unref(this, local); QUOTA_STACK_DESTROY (newframe, this); } @@ -521,22 +673,22 @@ quota_readdir_cbk (call_frame_t *frame, } } - if (ret) { - release_lock_on_dirty_inode (frame, NULL, this, 0, 0); - } else if (count == 0 ) { - get_dirty_inode_size (frame, this); + if (ret && val != -2) { + mq_release_lock_on_dirty_inode (frame, NULL, this, 0, 0, NULL); } +end: + mq_local_unref (this, local); return 0; } int32_t -quota_dirty_inode_readdir (call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno, - fd_t *fd) +mq_dirty_inode_readdir (call_frame_t *frame, + void *cookie, + xlator_t *this, + int32_t op_ret, + int32_t op_errno, + fd_t *fd, dict_t *xdata) { quota_local_t *local = NULL; @@ -544,7 +696,7 @@ quota_dirty_inode_readdir (call_frame_t *frame, if (op_ret == -1) { local->err = -1; - release_lock_on_dirty_inode (frame, NULL, this, 0, 0); + mq_release_lock_on_dirty_inode (frame, NULL, this, 0, 0, NULL); return 0; } @@ -552,30 +704,29 @@ quota_dirty_inode_readdir (call_frame_t *frame, local->fd = fd_ref (fd); STACK_WIND (frame, - quota_readdir_cbk, + mq_readdir_cbk, FIRST_CHILD(this), FIRST_CHILD(this)->fops->readdir, - local->fd, READDIR_BUF, local->d_off); + local->fd, READDIR_BUF, local->d_off, xdata); return 0; } int32_t -check_if_still_dirty (call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno, - inode_t *inode, - struct iatt *buf, - dict_t *dict, - struct iatt *postparent) +mq_check_if_still_dirty (call_frame_t *frame, + void *cookie, + xlator_t *this, + int32_t op_ret, + int32_t op_errno, + inode_t *inode, + struct iatt *buf, + dict_t *dict, + struct iatt *postparent) { int8_t dirty = -1; int32_t ret = -1; fd_t *fd = NULL; quota_local_t *local = NULL; - marker_conf_t *priv = NULL; local = frame->local; @@ -585,8 +736,6 @@ check_if_still_dirty (call_frame_t *frame, goto err; } - priv = this->private; - if (!dict) { ret = -1; goto err; @@ -598,7 +747,7 @@ check_if_still_dirty (call_frame_t *frame, //the inode is not dirty anymore if (dirty == 0) { - release_lock_on_dirty_inode (frame, NULL, this, 0, 0); + mq_release_lock_on_dirty_inode (frame, NULL, this, 0, 0, NULL); return 0; } @@ -607,18 +756,22 @@ check_if_still_dirty (call_frame_t *frame, local->d_off = 0; + if (uuid_is_null (local->loc.gfid)) + uuid_copy (local->loc.gfid, buf->ia_gfid); + + GF_UUID_ASSERT (local->loc.gfid); STACK_WIND(frame, - quota_dirty_inode_readdir, + mq_dirty_inode_readdir, FIRST_CHILD(this), FIRST_CHILD(this)->fops->opendir, - &local->loc, fd); + &local->loc, fd, NULL); ret = 0; err: if (op_ret == -1 || ret == -1) { local->err = -1; - release_lock_on_dirty_inode (frame, NULL, this, 0, 0); + mq_release_lock_on_dirty_inode (frame, NULL, this, 0, 0, NULL); } if (fd != NULL) { @@ -629,21 +782,18 @@ err: } int32_t -get_dirty_xattr (call_frame_t *frame, void *cookie, - xlator_t *this, int32_t op_ret, int32_t op_errno) +mq_get_dirty_xattr (call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, dict_t *xdata) { int32_t ret = -1; dict_t *xattr_req = NULL; quota_local_t *local = NULL; - marker_conf_t *priv = NULL; if (op_ret == -1) { - dirty_inode_updation_done (frame, NULL, this, 0, 0); + mq_dirty_inode_updation_done (frame, NULL, this, 0, 0, NULL); return 0; } - priv = (marker_conf_t *) this->private; - local = frame->local; xattr_req = dict_new (); @@ -656,8 +806,13 @@ get_dirty_xattr (call_frame_t *frame, void *cookie, if (ret) goto err; + if (uuid_is_null (local->loc.gfid)) + uuid_copy (local->loc.gfid, local->loc.inode->gfid); + + GF_UUID_ASSERT (local->loc.gfid); + STACK_WIND (frame, - check_if_still_dirty, + mq_check_if_still_dirty, FIRST_CHILD(this), FIRST_CHILD(this)->fops->lookup, &local->loc, @@ -667,7 +822,7 @@ get_dirty_xattr (call_frame_t *frame, void *cookie, err: if (ret) { local->err = -1; - release_lock_on_dirty_inode(frame, NULL, this, 0, 0); + mq_release_lock_on_dirty_inode(frame, NULL, this, 0, 0, NULL); } if (xattr_req) @@ -676,17 +831,27 @@ err: return 0; } +/* return 1 when dirty updation started + * 0 other wise + */ int32_t -update_dirty_inode (xlator_t *this, - loc_t *loc, - quota_inode_ctx_t *ctx, - inode_contribution_t *contribution) +mq_update_dirty_inode (xlator_t *this, + loc_t *loc, + quota_inode_ctx_t *ctx, + inode_contribution_t *contribution) { int32_t ret = -1; quota_local_t *local = NULL; + gf_boolean_t status = _gf_false; struct gf_flock lock = {0, }; call_frame_t *frame = NULL; + ret = mq_get_ctx_updation_status (ctx, &status); + if (ret == -1 || status == _gf_true) { + ret = 0; + goto out; + } + frame = create_frame (this, this->ctx->pool); if (frame == NULL) { ret = -1; @@ -695,13 +860,12 @@ update_dirty_inode (xlator_t *this, mq_assign_lk_owner (this, frame); - local = quota_local_new (); + local = mq_local_new (); if (local == NULL) goto fr_destroy; frame->local = local; - - ret = loc_copy (&local->loc, loc); + ret = mq_loc_copy (&local->loc, loc); if (ret < 0) goto fr_destroy; @@ -714,12 +878,19 @@ update_dirty_inode (xlator_t *this, lock.l_start = 0; lock.l_len = 0; + if (local->loc.inode == NULL) { + ret = -1; + gf_log (this->name, GF_LOG_WARNING, + "Inode is NULL, so can't stackwind."); + goto fr_destroy; + } + STACK_WIND (frame, - get_dirty_xattr, + mq_get_dirty_xattr, FIRST_CHILD(this), FIRST_CHILD(this)->fops->inodelk, - this->name, &local->loc, F_SETLKW, &lock); - return 0; + this->name, &local->loc, F_SETLKW, &lock, NULL); + return 1; fr_destroy: QUOTA_STACK_DESTROY (frame, this); @@ -730,12 +901,20 @@ out: int32_t -quota_inode_creation_done (call_frame_t *frame, void *cookie, xlator_t *this, - int32_t op_ret, int32_t op_errno) +mq_inode_creation_done (call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, dict_t *xdata) { + quota_local_t *local = NULL; + if (frame == NULL) return 0; + local = frame->local; + + if (local != NULL) { + mq_initiate_quota_txn (this, &local->loc); + } + QUOTA_STACK_DESTROY (frame, this); return 0; @@ -743,9 +922,9 @@ quota_inode_creation_done (call_frame_t *frame, void *cookie, xlator_t *this, int32_t -quota_xattr_creation_release_lock (call_frame_t *frame, void *cookie, - xlator_t *this, int32_t op_ret, - int32_t op_errno) +mq_xattr_creation_release_lock (call_frame_t *frame, void *cookie, + xlator_t *this, int32_t op_ret, + int32_t op_errno, dict_t *xdata) { struct gf_flock lock = {0, }; quota_local_t *local = NULL; @@ -759,24 +938,24 @@ quota_xattr_creation_release_lock (call_frame_t *frame, void *cookie, lock.l_pid = 0; STACK_WIND (frame, - quota_inode_creation_done, + mq_inode_creation_done, FIRST_CHILD(this), FIRST_CHILD(this)->fops->inodelk, this->name, &local->loc, - F_SETLKW, &lock); + F_SETLKW, &lock, NULL); return 0; } int32_t -create_dirty_xattr (call_frame_t *frame, void *cookie, xlator_t *this, - int32_t op_ret, int32_t op_errno, dict_t *dict) +mq_create_dirty_xattr (call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, dict_t *dict, + dict_t *xdata) { int32_t ret = -1; dict_t *newdict = NULL; quota_local_t *local = NULL; - marker_conf_t *priv = NULL; if (op_ret < 0) { goto err; @@ -784,8 +963,6 @@ create_dirty_xattr (call_frame_t *frame, void *cookie, xlator_t *this, local = frame->local; - priv = (marker_conf_t *) this->private; - if (local->loc.inode->ia_type == IA_IFDIR) { newdict = dict_new (); if (!newdict) { @@ -797,19 +974,22 @@ create_dirty_xattr (call_frame_t *frame, void *cookie, xlator_t *this, goto err; } - STACK_WIND (frame, quota_xattr_creation_release_lock, + uuid_copy (local->loc.gfid, local->loc.inode->gfid); + GF_UUID_ASSERT (local->loc.gfid); + + STACK_WIND (frame, mq_xattr_creation_release_lock, FIRST_CHILD(this), FIRST_CHILD(this)->fops->setxattr, - &local->loc, newdict, 0); + &local->loc, newdict, 0, NULL); } else { - quota_xattr_creation_release_lock (frame, NULL, this, 0, 0); + mq_xattr_creation_release_lock (frame, NULL, this, 0, 0, NULL); } ret = 0; err: if (ret < 0) { - quota_xattr_creation_release_lock (frame, NULL, this, 0, 0); + mq_xattr_creation_release_lock (frame, NULL, this, 0, 0, NULL); } if (newdict != NULL) @@ -820,7 +1000,7 @@ err: int32_t -quota_create_xattr (xlator_t *this, call_frame_t *frame) +mq_create_xattr (xlator_t *this, call_frame_t *frame) { int32_t ret = 0; int64_t *value = NULL; @@ -828,7 +1008,6 @@ quota_create_xattr (xlator_t *this, call_frame_t *frame) dict_t *dict = NULL; char key[512] = {0, }; quota_local_t *local = NULL; - marker_conf_t *priv = NULL; quota_inode_ctx_t *ctx = NULL; inode_contribution_t *contri = NULL; @@ -837,14 +1016,12 @@ quota_create_xattr (xlator_t *this, call_frame_t *frame) local = frame->local; - priv = (marker_conf_t *) this->private; - - ret = quota_inode_ctx_get (local->loc.inode, this, &ctx); + ret = mq_inode_ctx_get (local->loc.inode, this, &ctx); if (ret < 0) { - ctx = quota_inode_ctx_new (local->loc.inode, this); + ctx = mq_inode_ctx_new (local->loc.inode, this); if (ctx == NULL) { gf_log (this->name, GF_LOG_WARNING, - "quota_inode_ctx_new failed"); + "mq_inode_ctx_new failed"); ret = -1; goto out; } @@ -862,7 +1039,7 @@ quota_create_xattr (xlator_t *this, call_frame_t *frame) } if (strcmp (local->loc.path, "/") != 0) { - contri = add_new_contribution_node (this, ctx, &local->loc); + contri = mq_add_new_contribution_node (this, ctx, &local->loc); if (contri == NULL) goto err; @@ -874,9 +1051,11 @@ quota_create_xattr (xlator_t *this, call_frame_t *frame) goto free_value; } - STACK_WIND (frame, create_dirty_xattr, FIRST_CHILD(this), + GF_UUID_ASSERT (local->loc.gfid); + + STACK_WIND (frame, mq_create_dirty_xattr, FIRST_CHILD(this), FIRST_CHILD(this)->fops->xattrop, &local->loc, - GF_XATTROP_ADD_ARRAY64, dict); + GF_XATTROP_ADD_ARRAY64, dict, NULL); ret = 0; free_size: @@ -894,7 +1073,7 @@ err: out: if (ret < 0) { - quota_xattr_creation_release_lock (frame, NULL, this, 0, 0); + mq_xattr_creation_release_lock (frame, NULL, this, 0, 0, NULL); } return 0; @@ -902,15 +1081,14 @@ out: int32_t -quota_check_n_set_inode_xattr (call_frame_t *frame, void *cookie, - xlator_t *this, int32_t op_ret, int32_t op_errno, - inode_t *inode, struct iatt *buf, dict_t *dict, - struct iatt *postparent) +mq_check_n_set_inode_xattr (call_frame_t *frame, void *cookie, + xlator_t *this, int32_t op_ret, int32_t op_errno, + inode_t *inode, struct iatt *buf, dict_t *dict, + struct iatt *postparent) { quota_local_t *local = NULL; int64_t *size = NULL, *contri = NULL; int8_t dirty = 0; - marker_conf_t *priv = NULL; int32_t ret = 0; char contri_key[512] = {0, }; @@ -919,7 +1097,6 @@ quota_check_n_set_inode_xattr (call_frame_t *frame, void *cookie, } local = frame->local; - priv = this->private; ret = dict_get_bin (dict, QUOTA_SIZE_KEY, (void **) &size); if (ret < 0) @@ -941,18 +1118,22 @@ quota_check_n_set_inode_xattr (call_frame_t *frame, void *cookie, } out: - quota_xattr_creation_release_lock (frame, NULL, this, 0, 0); + mq_xattr_creation_release_lock (frame, NULL, this, 0, 0, NULL); return 0; create_xattr: - quota_create_xattr (this, frame); + if (uuid_is_null (local->loc.gfid)) { + uuid_copy (local->loc.gfid, buf->ia_gfid); + } + + mq_create_xattr (this, frame); return 0; } int32_t -quota_get_xattr (call_frame_t *frame, void *cookie, xlator_t *this, - int32_t op_ret, int32_t op_errno) +mq_get_xattr (call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, dict_t *xdata) { dict_t *xattr_req = NULL; quota_local_t *local = NULL; @@ -969,29 +1150,39 @@ quota_get_xattr (call_frame_t *frame, void *cookie, xlator_t *this, goto err; } - ret = quota_req_xattr (this, &local->loc, xattr_req); + ret = mq_req_xattr (this, &local->loc, xattr_req); if (ret < 0) { gf_log (this->name, GF_LOG_WARNING, "cannot request xattr"); goto err; } - STACK_WIND (frame, quota_check_n_set_inode_xattr, FIRST_CHILD(this), + if (uuid_is_null (local->loc.gfid)) + uuid_copy (local->loc.gfid, local->loc.inode->gfid); + + GF_UUID_ASSERT (local->loc.gfid); + + STACK_WIND (frame, mq_check_n_set_inode_xattr, FIRST_CHILD(this), FIRST_CHILD(this)->fops->lookup, &local->loc, xattr_req); + dict_unref (xattr_req); + return 0; err: - quota_xattr_creation_release_lock (frame, NULL, this, 0, 0); + mq_xattr_creation_release_lock (frame, NULL, this, 0, 0, NULL); + + if (xattr_req) + dict_unref (xattr_req); return 0; lock_err: - quota_inode_creation_done (frame, NULL, this, 0, 0); + mq_inode_creation_done (frame, NULL, this, 0, 0, NULL); return 0; } int32_t -quota_set_inode_xattr (xlator_t *this, loc_t *loc) +mq_set_inode_xattr (xlator_t *this, loc_t *loc) { struct gf_flock lock = {0, }; quota_local_t *local = NULL; @@ -1004,7 +1195,7 @@ quota_set_inode_xattr (xlator_t *this, loc_t *loc) goto err; } - local = quota_local_new (); + local = mq_local_new (); if (local == NULL) { goto err; } @@ -1024,10 +1215,10 @@ quota_set_inode_xattr (xlator_t *this, loc_t *loc) lock.l_whence = SEEK_SET; STACK_WIND (frame, - quota_get_xattr, + mq_get_xattr, FIRST_CHILD(this), FIRST_CHILD(this)->fops->inodelk, - this->name, &local->loc, F_SETLKW, &lock); + this->name, &local->loc, F_SETLKW, &lock, NULL); return 0; @@ -1039,38 +1230,68 @@ err: int32_t -get_parent_inode_local (xlator_t *this, quota_local_t *local) +mq_get_parent_inode_local (xlator_t *this, quota_local_t *local) { - int32_t ret; + int32_t ret = -1; quota_inode_ctx_t *ctx = NULL; + GF_VALIDATE_OR_GOTO ("marker", this, out); + GF_VALIDATE_OR_GOTO ("marker", local, out); + + local->contri = NULL; + loc_wipe (&local->loc); - loc_copy (&local->loc, &local->parent_loc); + ret = mq_loc_copy (&local->loc, &local->parent_loc); + if (ret < 0) { + gf_log_callingfn (this->name, GF_LOG_WARNING, + "loc copy failed"); + goto out; + } loc_wipe (&local->parent_loc); - quota_inode_loc_fill (NULL, local->loc.parent, &local->parent_loc); + ret = mq_inode_loc_fill (NULL, local->loc.parent, + &local->parent_loc); + if (ret < 0) { + gf_log_callingfn (this->name, GF_LOG_WARNING, + "failed to build parent loc of %s", + local->loc.path); + goto out; + } - ret = quota_inode_ctx_get (local->loc.inode, this, &ctx); - if (ret < 0) - return -1; + ret = mq_inode_ctx_get (local->loc.inode, this, &ctx); + if (ret < 0) { + gf_log_callingfn (this->name, GF_LOG_WARNING, + "inode ctx get failed"); + goto out; + } local->ctx = ctx; + if (list_empty (&ctx->contribution_head)) { + gf_log_callingfn (this->name, GF_LOG_WARNING, + "contribution node list is empty which " + "is an error"); + ret = -1; + goto out; + } + local->contri = (inode_contribution_t *) ctx->contribution_head.next; - return 0; + ret = 0; +out: + return ret; } int32_t -xattr_updation_done (call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno, - dict_t *dict) +mq_xattr_updation_done (call_frame_t *frame, + void *cookie, + xlator_t *this, + int32_t op_ret, + int32_t op_errno, + dict_t *dict, dict_t *xdata) { QUOTA_STACK_DESTROY (frame, this); return 0; @@ -1078,18 +1299,22 @@ xattr_updation_done (call_frame_t *frame, int32_t -quota_inodelk_cbk (call_frame_t *frame, void *cookie, - xlator_t *this, int32_t op_ret, int32_t op_errno) +mq_inodelk_cbk (call_frame_t *frame, void *cookie, + xlator_t *this, int32_t op_ret, int32_t op_errno, dict_t *xdata) { - int32_t ret = 0; - quota_local_t *local = NULL; + int32_t ret = 0; + gf_boolean_t status = _gf_false; + quota_local_t *local = NULL; local = frame->local; if (op_ret == -1 || local->err) { - gf_log (this->name, GF_LOG_DEBUG, - "lock setting failed (%s)", strerror (op_errno)); - xattr_updation_done (frame, NULL, this, 0, 0, NULL); + if (op_ret == -1) { + gf_log (this->name, GF_LOG_DEBUG, + "unlocking failed on path (%s)(%s)", + local->parent_loc.path, strerror (op_errno)); + } + mq_xattr_updation_done (frame, NULL, this, 0, 0, NULL, NULL); return 0; } @@ -1099,15 +1324,23 @@ quota_inodelk_cbk (call_frame_t *frame, void *cookie, if ((strcmp (local->parent_loc.path, "/") == 0) || (local->delta == 0)) { - xattr_updation_done (frame, NULL, this, 0, 0, NULL); + mq_xattr_updation_done (frame, NULL, this, 0, 0, NULL, NULL); } else { - ret = get_parent_inode_local (this, local); + ret = mq_get_parent_inode_local (this, local); if (ret < 0) { - xattr_updation_done (frame, NULL, this, 0, 0, NULL); + mq_xattr_updation_done (frame, NULL, this, 0, 0, NULL, + NULL); goto out; } - - get_lock_on_parent (frame, this); + status = _gf_true; + + ret = mq_test_and_set_ctx_updation_status (local->ctx, &status); + if (ret == 0 && status == _gf_false) { + mq_get_lock_on_parent (frame, this); + } else { + mq_xattr_updation_done (frame, NULL, this, 0, 0, NULL, + NULL); + } } out: return 0; @@ -1116,9 +1349,9 @@ out: //now release lock on the parent inode int32_t -quota_release_parent_lock (call_frame_t *frame, void *cookie, - xlator_t *this, int32_t op_ret, - int32_t op_errno) +mq_release_parent_lock (call_frame_t *frame, void *cookie, + xlator_t *this, int32_t op_ret, + int32_t op_errno, dict_t *xdata) { int32_t ret = 0; quota_local_t *local = NULL; @@ -1127,7 +1360,16 @@ quota_release_parent_lock (call_frame_t *frame, void *cookie, local = frame->local; - ret = quota_inode_ctx_get (local->parent_loc.inode, this, &ctx); + if (local->err != 0) { + gf_log_callingfn (this->name, + (local->err == ENOENT) ? GF_LOG_DEBUG + : GF_LOG_WARNING, + "An operation during quota updation " + "of path (%s) failed (%s)", local->loc.path, + strerror (local->err)); + } + + ret = mq_inode_ctx_get (local->parent_loc.inode, this, &ctx); if (ret < 0) goto wind; @@ -1137,6 +1379,12 @@ quota_release_parent_lock (call_frame_t *frame, void *cookie, } UNLOCK (&ctx->lock); + if (local->parent_loc.inode == NULL) { + gf_log (this->name, GF_LOG_DEBUG, + "Invalid parent inode."); + goto err; + } + wind: lock.l_type = F_UNLCK; lock.l_whence = SEEK_SET; @@ -1145,30 +1393,33 @@ wind: lock.l_pid = 0; STACK_WIND (frame, - quota_inodelk_cbk, + mq_inodelk_cbk, FIRST_CHILD(this), FIRST_CHILD(this)->fops->inodelk, this->name, &local->parent_loc, - F_SETLKW, &lock); + F_SETLKW, &lock, NULL); return 0; +err: + mq_xattr_updation_done (frame, NULL, this, + 0, 0 , NULL, NULL); + return 0; } int32_t -quota_mark_undirty (call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno, - dict_t *dict) +mq_mark_undirty (call_frame_t *frame, + void *cookie, + xlator_t *this, + int32_t op_ret, + int32_t op_errno, + dict_t *dict, dict_t *xdata) { int32_t ret = -1; int64_t *size = NULL; dict_t *newdict = NULL; quota_local_t *local = NULL; quota_inode_ctx_t *ctx = NULL; - marker_conf_t *priv = NULL; local = frame->local; @@ -1180,17 +1431,19 @@ quota_mark_undirty (call_frame_t *frame, goto err; } - priv = this->private; - //update the size of the parent inode if (dict != NULL) { - ret = quota_inode_ctx_get (local->parent_loc.inode, this, &ctx); - if (ret < 0) + ret = mq_inode_ctx_get (local->parent_loc.inode, this, &ctx); + if (ret < 0) { + op_errno = EINVAL; goto err; + } ret = dict_get_bin (dict, QUOTA_SIZE_KEY, (void **) &size); - if (ret < 0) + if (ret < 0) { + op_errno = EINVAL; goto err; + } LOCK (&ctx->lock); { @@ -1203,26 +1456,32 @@ quota_mark_undirty (call_frame_t *frame, } newdict = dict_new (); - - if (!newdict) + if (!newdict) { + op_errno = ENOMEM; goto err; + } ret = dict_set_int8 (newdict, QUOTA_DIRTY_KEY, 0); - if (ret == -1) + if (ret == -1) { + op_errno = -ret; goto err; + } + + uuid_copy (local->parent_loc.gfid, local->parent_loc.inode->gfid); + GF_UUID_ASSERT (local->parent_loc.gfid); - STACK_WIND (frame, quota_release_parent_lock, + STACK_WIND (frame, mq_release_parent_lock, FIRST_CHILD(this), FIRST_CHILD(this)->fops->setxattr, - &local->parent_loc, newdict, 0); + &local->parent_loc, newdict, 0, NULL); ret = 0; err: if (op_ret == -1 || ret == -1) { - local->err = 1; + local->err = op_errno; - quota_release_parent_lock (frame, NULL, this, 0, 0); + mq_release_parent_lock (frame, NULL, this, 0, 0, NULL); } if (newdict) @@ -1233,17 +1492,16 @@ err: int32_t -quota_update_parent_size (call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno, - dict_t *dict) +mq_update_parent_size (call_frame_t *frame, + void *cookie, + xlator_t *this, + int32_t op_ret, + int32_t op_errno, + dict_t *dict, dict_t *xdata) { int64_t *size = NULL; int32_t ret = -1; dict_t *newdict = NULL; - marker_conf_t *priv = NULL; quota_local_t *local = NULL; quota_inode_ctx_t *ctx = NULL; @@ -1251,7 +1509,7 @@ quota_update_parent_size (call_frame_t *frame, if (op_ret == -1) { gf_log (this->name, ((op_errno == ENOENT) ? GF_LOG_DEBUG : - GF_LOG_ERROR), + GF_LOG_WARNING), "xattrop call failed: %s", strerror (op_errno)); goto err; @@ -1267,17 +1525,20 @@ quota_update_parent_size (call_frame_t *frame, local->loc.path, local->ctx->size, local->contri->contribution); - priv = this->private; - - if (dict == NULL) + if (dict == NULL) { + op_errno = EINVAL; goto err; + } - ret = quota_inode_ctx_get (local->parent_loc.inode, this, &ctx); - if (ret < 0) + ret = mq_inode_ctx_get (local->parent_loc.inode, this, &ctx); + if (ret < 0) { + op_errno = EINVAL; goto err; + } newdict = dict_new (); if (!newdict) { + op_errno = ENOMEM; ret = -1; goto err; } @@ -1287,21 +1548,28 @@ quota_update_parent_size (call_frame_t *frame, *size = hton64 (local->delta); ret = dict_set_bin (newdict, QUOTA_SIZE_KEY, size, 8); - if (ret < 0) + if (ret < 0) { + op_errno = -ret; goto err; + } + + if (uuid_is_null (local->parent_loc.gfid)) + uuid_copy (local->parent_loc.gfid, + local->parent_loc.inode->gfid); + GF_UUID_ASSERT (local->parent_loc.gfid); STACK_WIND (frame, - quota_mark_undirty, + mq_mark_undirty, FIRST_CHILD(this), FIRST_CHILD(this)->fops->xattrop, &local->parent_loc, GF_XATTROP_ADD_ARRAY64, - newdict); + newdict, NULL); ret = 0; err: if (op_ret == -1 || ret < 0) { - local->err = 1; - quota_release_parent_lock (frame, NULL, this, 0, 0); + local->err = op_errno; + mq_release_parent_lock (frame, NULL, this, 0, 0, NULL); } if (newdict) @@ -1311,11 +1579,11 @@ err: } int32_t -quota_update_inode_contribution (call_frame_t *frame, void *cookie, - xlator_t *this, int32_t op_ret, - int32_t op_errno, inode_t *inode, - struct iatt *buf, dict_t *dict, - struct iatt *postparent) +mq_update_inode_contribution (call_frame_t *frame, void *cookie, + xlator_t *this, int32_t op_ret, + int32_t op_errno, inode_t *inode, + struct iatt *buf, dict_t *dict, + struct iatt *postparent) { int32_t ret = -1; int64_t *size = NULL, size_int = 0, contri_int = 0; @@ -1325,7 +1593,6 @@ quota_update_inode_contribution (call_frame_t *frame, void *cookie, dict_t *newdict = NULL; quota_local_t *local = NULL; quota_inode_ctx_t *ctx = NULL; - marker_conf_t *priv = NULL; inode_contribution_t *contribution = NULL; local = frame->local; @@ -1333,28 +1600,30 @@ quota_update_inode_contribution (call_frame_t *frame, void *cookie, if (op_ret == -1) { gf_log (this->name, ((op_errno == ENOENT) ? GF_LOG_DEBUG : GF_LOG_WARNING), - "failed to get size and contribution with %s error", - strerror (op_errno)); + "failed to get size and contribution of path (%s)(%s)", + local->loc.path, strerror (op_errno)); goto err; } - priv = this->private; - ctx = local->ctx; contribution = local->contri; //prepare to update size & contribution of the inode GET_CONTRI_KEY (contri_key, contribution->gfid, ret); - if (ret == -1) + if (ret == -1) { + op_errno = ENOMEM; goto err; + } LOCK (&ctx->lock); { if (local->loc.inode->ia_type == IA_IFDIR ) { ret = dict_get_bin (dict, QUOTA_SIZE_KEY, (void **) &size); - if (ret < 0) + if (ret < 0) { + op_errno = EINVAL; goto unlock; + } ctx->size = ntoh64 (*size); } else @@ -1388,12 +1657,13 @@ unlock: local->delta = size_int - contri_int; if (local->delta == 0) { - quota_mark_undirty (frame, NULL, this, 0, 0, NULL); + mq_mark_undirty (frame, NULL, this, 0, 0, NULL, NULL); return 0; } newdict = dict_new (); if (newdict == NULL) { + op_errno = ENOMEM; ret = -1; goto err; } @@ -1404,24 +1674,30 @@ unlock: ret = dict_set_bin (newdict, contri_key, delta, 8); if (ret < 0) { + op_errno = -ret; ret = -1; goto err; } + if (uuid_is_null (local->loc.gfid)) + uuid_copy (local->loc.gfid, buf->ia_gfid); + + GF_UUID_ASSERT (local->loc.gfid); + STACK_WIND (frame, - quota_update_parent_size, + mq_update_parent_size, FIRST_CHILD(this), FIRST_CHILD(this)->fops->xattrop, &local->loc, GF_XATTROP_ADD_ARRAY64, - newdict); + newdict, NULL); ret = 0; err: if (op_ret == -1 || ret < 0) { - local->err = 1; + local->err = op_errno; - quota_release_parent_lock (frame, NULL, this, 0, 0); + mq_release_parent_lock (frame, NULL, this, 0, 0, NULL); } if (newdict) @@ -1431,22 +1707,23 @@ err: } int32_t -quota_fetch_child_size_and_contri (call_frame_t *frame, void *cookie, - xlator_t *this, int32_t op_ret, - int32_t op_errno) +mq_fetch_child_size_and_contri (call_frame_t *frame, void *cookie, + xlator_t *this, int32_t op_ret, + int32_t op_errno, dict_t *xdata) { int32_t ret = -1; char contri_key [512] = {0, }; dict_t *newdict = NULL; quota_local_t *local = NULL; - marker_conf_t *priv = NULL; quota_inode_ctx_t *ctx = NULL; local = frame->local; if (op_ret == -1) { - gf_log (this->name, GF_LOG_ERROR, - "%s couldnt mark dirty", local->parent_loc.path); + gf_log (this->name, (op_errno == ENOENT) ? GF_LOG_DEBUG + : GF_LOG_WARNING, + "couldnt mark inode corresponding to path (%s) dirty " + "(%s)", local->parent_loc.path, strerror (op_errno)); goto err; } @@ -1455,12 +1732,12 @@ quota_fetch_child_size_and_contri (call_frame_t *frame, void *cookie, gf_log (this->name, GF_LOG_DEBUG, "%s marked dirty", local->parent_loc.path); - priv = this->private; - //update parent ctx - ret = quota_inode_ctx_get (local->parent_loc.inode, this, &ctx); - if (ret == -1) + ret = mq_inode_ctx_get (local->parent_loc.inode, this, &ctx); + if (ret == -1) { + op_errno = EINVAL; goto err; + } LOCK (&ctx->lock); { @@ -1469,29 +1746,52 @@ quota_fetch_child_size_and_contri (call_frame_t *frame, void *cookie, UNLOCK (&ctx->lock); newdict = dict_new (); - if (newdict == NULL) + if (newdict == NULL) { + op_errno = ENOMEM; goto err; + } if (local->loc.inode->ia_type == IA_IFDIR) { ret = dict_set_int64 (newdict, QUOTA_SIZE_KEY, 0); + if (ret < 0) { + gf_log (this->name, GF_LOG_WARNING, + "dict_set failed."); + goto err; + } } GET_CONTRI_KEY (contri_key, local->contri->gfid, ret); - if (ret < 0) + if (ret < 0) { + op_errno = ENOMEM; goto err; + } ret = dict_set_int64 (newdict, contri_key, 0); + if (ret < 0) { + gf_log (this->name, GF_LOG_WARNING, + "dict_set failed."); + goto err; + } - STACK_WIND (frame, quota_update_inode_contribution, FIRST_CHILD(this), + mq_set_ctx_updation_status (local->ctx, _gf_false); + + if (uuid_is_null (local->loc.gfid)) + uuid_copy (local->loc.gfid, local->loc.inode->gfid); + + GF_UUID_ASSERT (local->loc.gfid); + + STACK_WIND (frame, mq_update_inode_contribution, FIRST_CHILD(this), FIRST_CHILD(this)->fops->lookup, &local->loc, newdict); ret = 0; err: - if (op_ret == -1 || ret == -1) { - local->err = 1; + if ((op_ret == -1) || (ret < 0)) { + local->err = op_errno; + + mq_set_ctx_updation_status (local->ctx, _gf_false); - quota_release_parent_lock (frame, NULL, this, 0, 0); + mq_release_parent_lock (frame, NULL, this, 0, 0, NULL); } if (newdict) @@ -1501,24 +1801,25 @@ err: } int32_t -quota_markdirty (call_frame_t *frame, void *cookie, - xlator_t *this, int32_t op_ret, int32_t op_errno) +mq_markdirty (call_frame_t *frame, void *cookie, + xlator_t *this, int32_t op_ret, int32_t op_errno, dict_t *xdata) { int32_t ret = -1; dict_t *dict = NULL; quota_local_t *local = NULL; - marker_conf_t *priv = NULL; local = frame->local; if (op_ret == -1){ - gf_log (this->name, GF_LOG_ERROR, - "lock setting failed on %s (%s)", + gf_log (this->name, (op_errno == ENOENT) ? GF_LOG_DEBUG + : GF_LOG_WARNING, "acquiring locks failed on %s (%s)", local->parent_loc.path, strerror (op_errno)); - local->err = 1; + local->err = op_errno; + + mq_set_ctx_updation_status (local->ctx, _gf_false); - quota_inodelk_cbk (frame, NULL, this, 0, 0); + mq_inodelk_cbk (frame, NULL, this, 0, 0, NULL); return 0; } @@ -1526,8 +1827,6 @@ quota_markdirty (call_frame_t *frame, void *cookie, gf_log (this->name, GF_LOG_TRACE, "inodelk succeeded on %s", local->parent_loc.path); - priv = this->private; - dict = dict_new (); if (!dict) { ret = -1; @@ -1538,17 +1837,23 @@ quota_markdirty (call_frame_t *frame, void *cookie, if (ret == -1) goto err; - STACK_WIND (frame, quota_fetch_child_size_and_contri, + uuid_copy (local->parent_loc.gfid, + local->parent_loc.inode->gfid); + GF_UUID_ASSERT (local->parent_loc.gfid); + + STACK_WIND (frame, mq_fetch_child_size_and_contri, FIRST_CHILD(this), FIRST_CHILD(this)->fops->setxattr, - &local->parent_loc, dict, 0); + &local->parent_loc, dict, 0, NULL); ret = 0; err: if (ret == -1) { local->err = 1; - quota_release_parent_lock (frame, NULL, this, 0, 0); + mq_set_ctx_updation_status (local->ctx, _gf_false); + + mq_release_parent_lock (frame, NULL, this, 0, 0, NULL); } if (dict) @@ -1559,7 +1864,7 @@ err: int32_t -get_lock_on_parent (call_frame_t *frame, xlator_t *this) +mq_get_lock_on_parent (call_frame_t *frame, xlator_t *this) { struct gf_flock lock = {0, }; quota_local_t *local = NULL; @@ -1570,30 +1875,37 @@ get_lock_on_parent (call_frame_t *frame, xlator_t *this) gf_log (this->name, GF_LOG_DEBUG, "taking lock on %s", local->parent_loc.path); + if (local->parent_loc.inode == NULL) { + gf_log (this->name, GF_LOG_DEBUG, + "parent inode is not valid, aborting " + "transaction."); + goto fr_destroy; + } + lock.l_len = 0; lock.l_start = 0; lock.l_type = F_WRLCK; lock.l_whence = SEEK_SET; STACK_WIND (frame, - quota_markdirty, + mq_markdirty, FIRST_CHILD(this), FIRST_CHILD(this)->fops->inodelk, - this->name, &local->parent_loc, F_SETLKW, &lock); + this->name, &local->parent_loc, F_SETLKW, &lock, NULL); return 0; fr_destroy: QUOTA_STACK_DESTROY (frame, this); - return 0; + return -1; } int -start_quota_txn (xlator_t *this, loc_t *loc, - quota_inode_ctx_t *ctx, - inode_contribution_t *contri) +mq_start_quota_txn (xlator_t *this, loc_t *loc, + quota_inode_ctx_t *ctx, + inode_contribution_t *contri) { int32_t ret = -1; call_frame_t *frame = NULL; @@ -1605,46 +1917,52 @@ start_quota_txn (xlator_t *this, loc_t *loc, mq_assign_lk_owner (this, frame); - local = quota_local_new (); + local = mq_local_new (); if (local == NULL) goto fr_destroy; frame->local = local; - ret = loc_copy (&local->loc, loc); + ret = mq_loc_copy (&local->loc, loc); if (ret < 0) goto fr_destroy; - ret = quota_inode_loc_fill (NULL, local->loc.parent, - &local->parent_loc); + ret = mq_inode_loc_fill (NULL, local->loc.parent, + &local->parent_loc); if (ret < 0) goto fr_destroy; local->ctx = ctx; local->contri = contri; - get_lock_on_parent (frame, this); + ret = mq_get_lock_on_parent (frame, this); + if (ret == -1) + goto err; return 0; fr_destroy: QUOTA_STACK_DESTROY (frame, this); - err: + mq_set_ctx_updation_status (ctx, _gf_false); + return -1; } int -initiate_quota_txn (xlator_t *this, loc_t *loc) +mq_initiate_quota_txn (xlator_t *this, loc_t *loc) { int32_t ret = -1; + gf_boolean_t status = _gf_false; quota_inode_ctx_t *ctx = NULL; inode_contribution_t *contribution = NULL; - VALIDATE_OR_GOTO (loc, out); + GF_VALIDATE_OR_GOTO ("marker", this, out); + GF_VALIDATE_OR_GOTO ("marker", loc, out); + GF_VALIDATE_OR_GOTO ("marker", loc->inode, out); - ret = quota_inode_ctx_get (loc->inode, this, &ctx); + ret = mq_inode_ctx_get (loc->inode, this, &ctx); if (ret == -1) { gf_log (this->name, GF_LOG_WARNING, "inode ctx get failed, aborting quota txn"); @@ -1652,13 +1970,26 @@ initiate_quota_txn (xlator_t *this, loc_t *loc) goto out; } - contribution = get_contribution_node (loc->parent, ctx); + contribution = mq_get_contribution_node (loc->parent, ctx); if (contribution == NULL) goto out; - start_quota_txn (this, loc, ctx, contribution); + /* To improve performance, donot start another transaction + * if one is already in progress for same inode + */ + status = _gf_true; + + ret = mq_test_and_set_ctx_updation_status (ctx, &status); + if (ret < 0) + goto out; + + if (status == _gf_false) { + mq_start_quota_txn (this, loc, ctx, contribution); + } + + ret = 0; out: - return 0; + return ret; } @@ -1667,7 +1998,7 @@ out: /* int64_t contribution) */ /* { */ /* if (size != contribution) { */ -/* initiate_quota_txn (this, loc); */ +/* mq_initiate_quota_txn (this, loc); */ /* } */ /* return 0; */ @@ -1675,31 +2006,39 @@ out: int32_t -inspect_directory_xattr (xlator_t *this, - loc_t *loc, - dict_t *dict, - struct iatt buf) +mq_inspect_directory_xattr (xlator_t *this, + loc_t *loc, + dict_t *dict, + struct iatt buf) { int32_t ret = 0; int8_t dirty = -1; int64_t *size = NULL, size_int = 0; int64_t *contri = NULL, contri_int = 0; char contri_key [512] = {0, }; - marker_conf_t *priv = NULL; gf_boolean_t not_root = _gf_false; quota_inode_ctx_t *ctx = NULL; inode_contribution_t *contribution = NULL; - priv = this->private; - - ret = quota_inode_ctx_get (loc->inode, this, &ctx); + ret = mq_inode_ctx_get (loc->inode, this, &ctx); if (ret < 0) { - ctx = quota_inode_ctx_new (loc->inode, this); + ctx = mq_inode_ctx_new (loc->inode, this); if (ctx == NULL) { gf_log (this->name, GF_LOG_WARNING, - "quota_inode_ctx_new failed"); + "mq_inode_ctx_new failed"); ret = -1; - goto out; + goto err; + } + } + + if (strcmp (loc->path, "/") != 0) { + contribution = mq_add_new_contribution_node (this, ctx, loc); + if (contribution == NULL) { + if (!uuid_is_null (loc->inode->gfid)) + gf_log (this->name, GF_LOG_WARNING, + "cannot add a new contribution node"); + ret = -1; + goto err; } } @@ -1714,13 +2053,6 @@ inspect_directory_xattr (xlator_t *this, if (strcmp (loc->path, "/") != 0) { not_root = _gf_true; - contribution = add_new_contribution_node (this, ctx, loc); - if (contribution == NULL) { - gf_log (this->name, GF_LOG_DEBUG, - "cannot add a new contributio node"); - goto out; - } - GET_CONTRI_KEY (contri_key, contribution->gfid, ret); if (ret < 0) goto out; @@ -1749,47 +2081,47 @@ inspect_directory_xattr (xlator_t *this, " contri=%"PRId64, size_int, contri_int); if (dirty) { - update_dirty_inode (this, loc, ctx, contribution); - } else if ((not_root == _gf_true) && (size_int != contri_int)) { - initiate_quota_txn (this, loc); + ret = mq_update_dirty_inode (this, loc, ctx, contribution); + } + + if ((!dirty || ret == 0) && (not_root == _gf_true) && + (size_int != contri_int)) { + mq_initiate_quota_txn (this, loc); } ret = 0; out: if (ret) - quota_set_inode_xattr (this, loc); - - return 0; + mq_set_inode_xattr (this, loc); +err: + return ret; } int32_t -inspect_file_xattr (xlator_t *this, - loc_t *loc, - dict_t *dict, - struct iatt buf) +mq_inspect_file_xattr (xlator_t *this, + loc_t *loc, + dict_t *dict, + struct iatt buf) { int32_t ret = -1; uint64_t contri_int = 0, size = 0; int64_t *contri_ptr = NULL; char contri_key [512] = {0, }; - marker_conf_t *priv = NULL; quota_inode_ctx_t *ctx = NULL; inode_contribution_t *contribution = NULL; - priv = this->private; - - ret = quota_inode_ctx_get (loc->inode, this, &ctx); + ret = mq_inode_ctx_get (loc->inode, this, &ctx); if (ret < 0) { - ctx = quota_inode_ctx_new (loc->inode, this); + ctx = mq_inode_ctx_new (loc->inode, this); if (ctx == NULL) { gf_log (this->name, GF_LOG_WARNING, - "quota_inode_ctx_new failed"); + "mq_inode_ctx_new failed"); ret = -1; goto out; } } - contribution = add_new_contribution_node (this, ctx, loc); + contribution = mq_add_new_contribution_node (this, ctx, loc); if (contribution == NULL) goto out; @@ -1821,10 +2153,10 @@ inspect_file_xattr (xlator_t *this, "size=%"PRId64 " contri=%"PRId64, size, contri_int); if (size != contri_int) { - initiate_quota_txn (this, loc); + mq_initiate_quota_txn (this, loc); } } else - initiate_quota_txn (this, loc); + mq_initiate_quota_txn (this, loc); } out: @@ -1832,39 +2164,38 @@ out: } int32_t -quota_xattr_state (xlator_t *this, - loc_t *loc, - dict_t *dict, - struct iatt buf) +mq_xattr_state (xlator_t *this, + loc_t *loc, + dict_t *dict, + struct iatt buf) { if (buf.ia_type == IA_IFREG || buf.ia_type == IA_IFLNK) { - inspect_file_xattr (this, loc, dict, buf); + mq_inspect_file_xattr (this, loc, dict, buf); } else if (buf.ia_type == IA_IFDIR) - inspect_directory_xattr (this, loc, dict, buf); + mq_inspect_directory_xattr (this, loc, dict, buf); return 0; } int32_t -quota_req_xattr (xlator_t *this, - loc_t *loc, - dict_t *dict) +mq_req_xattr (xlator_t *this, + loc_t *loc, + dict_t *dict) { int32_t ret = -1; - marker_conf_t *priv = NULL; GF_VALIDATE_OR_GOTO ("marker", this, out); - GF_VALIDATE_OR_GOTO ("marker", loc, out); GF_VALIDATE_OR_GOTO ("marker", dict, out); - priv = this->private; + if (!loc) + goto set_size; //if not "/" then request contribution if (strcmp (loc->path, "/") == 0) goto set_size; - ret = dict_set_contribution (this, dict, loc); + ret = mq_dict_set_contribution (this, dict, loc); if (ret == -1) goto out; @@ -1889,8 +2220,8 @@ out: int32_t -quota_removexattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this, - int32_t op_ret, int32_t op_errno) +mq_removexattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, dict_t *xdata) { QUOTA_STACK_DESTROY (frame, this); @@ -1898,8 +2229,8 @@ quota_removexattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this, } int32_t -quota_inode_remove_done (call_frame_t *frame, void *cookie, xlator_t *this, - int32_t op_ret, int32_t op_errno) +_mq_inode_remove_done (call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, dict_t *xdata) { int32_t ret = 0; char contri_key [512] = {0, }; @@ -1908,7 +2239,7 @@ quota_inode_remove_done (call_frame_t *frame, void *cookie, xlator_t *this, local = (quota_local_t *) frame->local; if (op_ret == -1 || local->err == -1) { - quota_removexattr_cbk (frame, NULL, this, -1, 0); + mq_removexattr_cbk (frame, NULL, this, -1, 0, NULL); return 0; } @@ -1917,30 +2248,31 @@ quota_inode_remove_done (call_frame_t *frame, void *cookie, xlator_t *this, if (local->hl_count > 1) { GET_CONTRI_KEY (contri_key, local->contri->gfid, ret); - STACK_WIND (frame, quota_removexattr_cbk, FIRST_CHILD(this), + STACK_WIND (frame, mq_removexattr_cbk, FIRST_CHILD(this), FIRST_CHILD(this)->fops->removexattr, - &local->loc, contri_key); + &local->loc, contri_key, NULL); ret = 0; } else { - quota_removexattr_cbk (frame, NULL, this, 0, 0); + mq_removexattr_cbk (frame, NULL, this, 0, 0, NULL); } if (strcmp (local->parent_loc.path, "/") != 0) { - get_parent_inode_local (this, local); + ret = mq_get_parent_inode_local (this, local); + if (ret < 0) + goto out; - start_quota_txn (this, &local->loc, local->ctx, local->contri); + mq_start_quota_txn (this, &local->loc, local->ctx, local->contri); } - - /* TODO: free local in quota_local_unref only*/ - quota_local_unref (this, local); - GF_FREE (local); +out: + mq_local_unref (this, local); return 0; } int32_t mq_inode_remove_done (call_frame_t *frame, void *cookie, xlator_t *this, - int32_t op_ret, int32_t op_errno, dict_t *dict) + int32_t op_ret, int32_t op_errno, dict_t *dict, + dict_t *xdata) { int32_t ret = -1; struct gf_flock lock = {0, }; @@ -1952,7 +2284,7 @@ mq_inode_remove_done (call_frame_t *frame, void *cookie, xlator_t *this, if (op_ret == -1) local->err = -1; - ret = quota_inode_ctx_get (local->parent_loc.inode, this, &ctx); + ret = mq_inode_ctx_get (local->parent_loc.inode, this, &ctx); LOCK (&local->contri->lock); { @@ -1983,24 +2315,22 @@ mq_inode_remove_done (call_frame_t *frame, void *cookie, xlator_t *this, lock.l_pid = 0; STACK_WIND (frame, - quota_inode_remove_done, + _mq_inode_remove_done, FIRST_CHILD(this), FIRST_CHILD(this)->fops->inodelk, this->name, &local->parent_loc, - F_SETLKW, &lock); + F_SETLKW, &lock, NULL); return 0; } int32_t -mq_reduce_parent_size_xattr (call_frame_t *frame, void *cookie, - xlator_t *this, int32_t op_ret, int32_t op_errno) +mq_reduce_parent_size_xattr (call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, dict_t *xdata) { int32_t ret = -1; int64_t *size = NULL; dict_t *dict = NULL; - marker_conf_t *priv = NULL; quota_local_t *local = NULL; - inode_contribution_t *contribution = NULL; local = frame->local; if (op_ret == -1) { @@ -2012,10 +2342,6 @@ mq_reduce_parent_size_xattr (call_frame_t *frame, void *cookie, VALIDATE_OR_GOTO (local->contri, err); - priv = this->private; - - contribution = local->contri; - dict = dict_new (); if (dict == NULL) { ret = -1; @@ -2030,28 +2356,30 @@ mq_reduce_parent_size_xattr (call_frame_t *frame, void *cookie, if (ret < 0) goto err; + uuid_copy (local->parent_loc.gfid, + local->parent_loc.inode->gfid); + GF_UUID_ASSERT (local->parent_loc.gfid); STACK_WIND (frame, mq_inode_remove_done, FIRST_CHILD(this), FIRST_CHILD(this)->fops->xattrop, &local->parent_loc, - GF_XATTROP_ADD_ARRAY64, dict); + GF_XATTROP_ADD_ARRAY64, dict, NULL); dict_unref (dict); return 0; err: local->err = 1; - mq_inode_remove_done (frame, NULL, this, -1, 0, NULL); + mq_inode_remove_done (frame, NULL, this, -1, 0, NULL, NULL); if (dict) dict_unref (dict); return 0; } int32_t -reduce_parent_size (xlator_t *this, loc_t *loc, int64_t contri) +mq_reduce_parent_size (xlator_t *this, loc_t *loc, int64_t contri) { int32_t ret = -1; struct gf_flock lock = {0,}; call_frame_t *frame = NULL; - marker_conf_t *priv = NULL; quota_local_t *local = NULL; quota_inode_ctx_t *ctx = NULL; inode_contribution_t *contribution = NULL; @@ -2059,17 +2387,15 @@ reduce_parent_size (xlator_t *this, loc_t *loc, int64_t contri) GF_VALIDATE_OR_GOTO ("marker", this, out); GF_VALIDATE_OR_GOTO ("marker", loc, out); - priv = this->private; - - ret = quota_inode_ctx_get (loc->inode, this, &ctx); + ret = mq_inode_ctx_get (loc->inode, this, &ctx); if (ret < 0) goto out; - contribution = get_contribution_node (loc->parent, ctx); + contribution = mq_get_contribution_node (loc->parent, ctx); if (contribution == NULL) goto out; - local = quota_local_new (); + local = mq_local_new (); if (local == NULL) { ret = -1; goto out; @@ -2090,14 +2416,14 @@ reduce_parent_size (xlator_t *this, loc_t *loc, int64_t contri) goto out; } - ret = loc_copy (&local->loc, loc); + ret = mq_loc_copy (&local->loc, loc); if (ret < 0) goto out; local->ctx = ctx; local->contri = contribution; - ret = quota_inode_loc_fill (NULL, loc->parent, &local->parent_loc); + ret = mq_inode_loc_fill (NULL, loc->parent, &local->parent_loc); if (ret < 0) goto out; @@ -2116,19 +2442,24 @@ reduce_parent_size (xlator_t *this, loc_t *loc, int64_t contri) lock.l_type = F_WRLCK; lock.l_whence = SEEK_SET; + if (local->parent_loc.inode == NULL) { + ret = -1; + gf_log (this->name, GF_LOG_DEBUG, + "Inode is NULL, so can't stackwind."); + goto out; + } + STACK_WIND (frame, mq_reduce_parent_size_xattr, FIRST_CHILD(this), FIRST_CHILD(this)->fops->inodelk, - this->name, &local->parent_loc, F_SETLKW, &lock); + this->name, &local->parent_loc, F_SETLKW, &lock, NULL); local = NULL; ret = 0; out: - if (local != NULL) { - quota_local_unref (this, local); - GF_FREE (local); - } + if (local != NULL) + mq_local_unref (this, local); return ret; } @@ -2142,7 +2473,7 @@ init_quota_priv (xlator_t *this) int32_t -quota_rename_update_newpath (xlator_t *this, loc_t *loc) +mq_rename_update_newpath (xlator_t *this, loc_t *loc) { int32_t ret = -1; quota_inode_ctx_t *ctx = NULL; @@ -2152,23 +2483,23 @@ quota_rename_update_newpath (xlator_t *this, loc_t *loc) GF_VALIDATE_OR_GOTO ("marker", loc, out); GF_VALIDATE_OR_GOTO ("marker", loc->inode, out); - ret = quota_inode_ctx_get (loc->inode, this, &ctx); + ret = mq_inode_ctx_get (loc->inode, this, &ctx); if (ret < 0) goto out; - contribution = add_new_contribution_node (this, ctx, loc); + contribution = mq_add_new_contribution_node (this, ctx, loc); if (contribution == NULL) { ret = -1; goto out; } - initiate_quota_txn (this, loc); + mq_initiate_quota_txn (this, loc); out: return ret; } int32_t -quota_forget (xlator_t *this, quota_inode_ctx_t *ctx) +mq_forget (xlator_t *this, quota_inode_ctx_t *ctx) { inode_contribution_t *contri = NULL; inode_contribution_t *next = NULL; diff --git a/xlators/features/marker/src/marker-quota.h b/xlators/features/marker/src/marker-quota.h index 384a96ccc..385760ac4 100644 --- a/xlators/features/marker/src/marker-quota.h +++ b/xlators/features/marker/src/marker-quota.h @@ -1,21 +1,12 @@ -/*Copyright (c) 2008-2010 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/>. +/* + Copyright (c) 2008-2012 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 _MARKER_QUOTA_H #define _MARKER_QUOTA_H @@ -24,7 +15,6 @@ #include "config.h" #endif -#include "marker.h" #include "xlator.h" #include "marker-mem-types.h" @@ -42,8 +32,7 @@ _local = _frame->local; \ _frame->local = NULL; \ STACK_DESTROY (_frame->root); \ - quota_local_unref (_this, _local); \ - GF_FREE (_local); \ + mq_local_unref (_this, _local); \ } while (0) @@ -91,6 +80,7 @@ struct quota_inode_ctx { int64_t size; int8_t dirty; + gf_boolean_t updation_status; gf_lock_t lock; struct list_head contribution_head; }; @@ -104,59 +94,37 @@ struct inode_contribution { }; typedef struct inode_contribution inode_contribution_t; -struct quota_local { - int64_t delta; - int64_t d_off; - int32_t err; - int32_t ref; - int64_t sum; - int64_t size; - int32_t hl_count; - int32_t dentry_child_count; - - fd_t *fd; - call_frame_t *frame; - gf_lock_t lock; - - loc_t loc; - loc_t parent_loc; - - quota_inode_ctx_t *ctx; - inode_contribution_t *contri; -}; -typedef struct quota_local quota_local_t; - int32_t -get_lock_on_parent (call_frame_t *, xlator_t *); +mq_get_lock_on_parent (call_frame_t *, xlator_t *); int32_t -quota_req_xattr (xlator_t *, loc_t *, dict_t *); +mq_req_xattr (xlator_t *, loc_t *, dict_t *); int32_t init_quota_priv (xlator_t *); int32_t -quota_xattr_state (xlator_t *, loc_t *, dict_t *, struct iatt); +mq_xattr_state (xlator_t *, loc_t *, dict_t *, struct iatt); int32_t -quota_set_inode_xattr (xlator_t *, loc_t *); +mq_set_inode_xattr (xlator_t *, loc_t *); int -initiate_quota_txn (xlator_t *, loc_t *); +mq_initiate_quota_txn (xlator_t *, loc_t *); int32_t -quota_dirty_inode_readdir (call_frame_t *, void *, xlator_t *, - int32_t, int32_t, fd_t *); +mq_dirty_inode_readdir (call_frame_t *, void *, xlator_t *, + int32_t, int32_t, fd_t *, dict_t *); int32_t -reduce_parent_size (xlator_t *, loc_t *, int64_t); +mq_reduce_parent_size (xlator_t *, loc_t *, int64_t); int32_t -quota_rename_update_newpath (xlator_t *, loc_t *); +mq_rename_update_newpath (xlator_t *, loc_t *); int32_t -inspect_file_xattr (xlator_t *this, loc_t *loc, dict_t *dict, struct iatt buf); +mq_inspect_file_xattr (xlator_t *this, loc_t *loc, dict_t *dict, struct iatt buf); int32_t -quota_forget (xlator_t *, quota_inode_ctx_t *); +mq_forget (xlator_t *, quota_inode_ctx_t *); #endif diff --git a/xlators/features/marker/src/marker.c b/xlators/features/marker/src/marker.c index 84c13435f..6a2c85691 100644 --- a/xlators/features/marker/src/marker.c +++ b/xlators/features/marker/src/marker.c @@ -1,21 +1,12 @@ -/*Copyright (c) 2008-2010 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/>. +/* + Copyright (c) 2008-2012 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" @@ -31,6 +22,8 @@ #include "marker-common.h" #include "byte-order.h" +#define _GF_UID_GID_CHANGED 1 + void fini (xlator_t *this); @@ -63,23 +56,25 @@ marker_loc_fill (loc_t *loc, inode_t *inode, inode_t *parent, char *path) if (inode) { loc->inode = inode_ref (inode); - loc->ino = inode->ino; + if (uuid_is_null (loc->gfid)) { + uuid_copy (loc->gfid, loc->inode->gfid); + } } if (parent) loc->parent = inode_ref (parent); - loc->path = gf_strdup (path); - if (!loc->path) { - gf_log ("loc fill", GF_LOG_ERROR, "strdup failed"); - goto loc_wipe; - } + if (path) { + loc->path = gf_strdup (path); + if (!loc->path) { + gf_log ("loc fill", GF_LOG_ERROR, "strdup failed"); + goto loc_wipe; + } - loc->name = strrchr (loc->path, '/'); - if (loc->name) - loc->name++; - else - goto loc_wipe; + loc->name = strrchr (loc->path, '/'); + if (loc->name) + loc->name++; + } ret = 0; loc_wipe: @@ -93,23 +88,14 @@ int marker_inode_loc_fill (inode_t *inode, loc_t *loc) { char *resolvedpath = NULL; - inode_t *parent = NULL; int ret = -1; + inode_t *parent = NULL; if ((!inode) || (!loc)) return ret; - if ((inode) && (inode->ino == 1)) { - loc->parent = NULL; - goto ignore_parent; - } - - parent = inode_parent (inode, 0, NULL); - if (!parent) { - goto err; - } + parent = inode_parent (inode, NULL, NULL); -ignore_parent: ret = inode_path (inode, NULL, &resolvedpath); if (ret < 0) goto err; @@ -119,11 +105,10 @@ ignore_parent: goto err; err: - if (parent) - inode_unref (parent); + if (parent) + inode_unref (parent); - if (resolvedpath) - GF_FREE (resolvedpath); + GF_FREE (resolvedpath); return ret; } @@ -133,8 +118,17 @@ marker_trav_parent (marker_local_t *local) { int32_t ret = 0; loc_t loc = {0, }; + inode_t *parent = NULL; + int8_t need_unref = 0; + + if (!local->loc.parent) { + parent = inode_parent (local->loc.inode, NULL, NULL); + if (parent) + need_unref = 1; + } else + parent = local->loc.parent; - ret = marker_inode_loc_fill (local->loc.parent, &loc); + ret = marker_inode_loc_fill (parent, &loc); if (ret < 0) { ret = -1; @@ -145,16 +139,28 @@ marker_trav_parent (marker_local_t *local) local->loc = loc; out: + if (need_unref) + inode_unref (parent); + return ret; } int32_t -marker_error_handler (xlator_t *this) +marker_error_handler (xlator_t *this, marker_local_t *local, int32_t op_errno) { - marker_conf_t *priv = NULL; + marker_conf_t *priv = NULL; + const char *path = NULL; - priv = (marker_conf_t *) this->private; + priv = (marker_conf_t *) this->private; + path = local + ? (local->loc.path + ? local->loc.path : uuid_utoa(local->loc.gfid)) + : "<nul>"; + gf_log (this->name, GF_LOG_CRITICAL, + "Indexing gone corrupt at %s (reason: %s)." + " Geo-replication slave content needs to be revalidated", + path, strerror (op_errno)); unlink (priv->timestamp_file); return 0; @@ -179,12 +185,14 @@ marker_local_unref (marker_local_t *local) loc_wipe (&local->loc); loc_wipe (&local->parent_loc); + if (local->xdata) + dict_unref (local->xdata); if (local->oplocal) { marker_local_unref (local->oplocal); local->oplocal = NULL; } - GF_FREE (local); + mem_put (local); out: return 0; } @@ -219,13 +227,14 @@ stat_stampfile (xlator_t *this, marker_conf_t *priv, int32_t marker_getxattr_stampfile_cbk (call_frame_t *frame, xlator_t *this, - const char *name, struct volume_mark *vol_mark) + const char *name, struct volume_mark *vol_mark, + dict_t *xdata) { int32_t ret = -1; dict_t *dict = NULL; if (vol_mark == NULL){ - STACK_UNWIND_STRICT (getxattr, frame, -1, ENOMEM, NULL); + STACK_UNWIND_STRICT (getxattr, frame, -1, ENOMEM, NULL, NULL); goto out; } @@ -234,8 +243,11 @@ marker_getxattr_stampfile_cbk (call_frame_t *frame, xlator_t *this, ret = dict_set_bin (dict, (char *)name, vol_mark, sizeof (struct volume_mark)); + if (ret) + gf_log (this->name, GF_LOG_WARNING, "failed to set key %s", + name); - STACK_UNWIND_STRICT (getxattr, frame, 0, 0, dict); + STACK_UNWIND_STRICT (getxattr, frame, 0, 0, dict, xdata); dict_unref (dict); out: @@ -251,7 +263,7 @@ call_from_special_client (call_frame_t *frame, xlator_t *this, const char *name) priv = (marker_conf_t *)this->private; - if (frame->root->pid != -1 || name == NULL || + if (frame->root->pid != GF_CLIENT_PID_GSYNCD || name == NULL || strcmp (name, MARKER_XATTR_PREFIX "." VOLUME_MARK) != 0) { ret = _gf_false; goto out; @@ -259,28 +271,31 @@ call_from_special_client (call_frame_t *frame, xlator_t *this, const char *name) stat_stampfile (this, priv, &vol_mark); - marker_getxattr_stampfile_cbk (frame, this, name, vol_mark); + marker_getxattr_stampfile_cbk (frame, this, name, vol_mark, NULL); out: return ret; } int32_t marker_getxattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this, - int32_t op_ret, int32_t op_errno, dict_t *dict) + int32_t op_ret, int32_t op_errno, dict_t *dict, + dict_t *xdata) { if (cookie) { gf_log (this->name, GF_LOG_DEBUG, "Filtering the quota extended attributes"); - dict_foreach (dict, marker_filter_quota_xattr, NULL); + dict_foreach_fnmatch (dict, "trusted.glusterfs.quota*", + marker_filter_quota_xattr, NULL); } - STACK_UNWIND_STRICT (getxattr, frame, op_ret, op_errno, dict); + + STACK_UNWIND_STRICT (getxattr, frame, op_ret, op_errno, dict, xdata); return 0; } int32_t marker_getxattr (call_frame_t *frame, xlator_t *this, loc_t *loc, - const char *name) + const char *name, dict_t *xdata) { gf_boolean_t ret = _gf_false; marker_conf_t *priv = NULL; @@ -307,7 +322,7 @@ wind: STACK_WIND_COOKIE (frame, marker_getxattr_cbk, (void *)cookie, FIRST_CHILD(this), FIRST_CHILD(this)->fops->getxattr, loc, - name); + name, xdata); } return 0; @@ -332,7 +347,7 @@ marker_setxattr_done (call_frame_t *frame) int marker_specific_setxattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this, - int32_t op_ret, int32_t op_errno) + int32_t op_ret, int32_t op_errno, dict_t *xdata) { int32_t ret = 0; int32_t done = 0; @@ -341,20 +356,26 @@ marker_specific_setxattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this, local = (marker_local_t*) frame->local; if (op_ret == -1 && op_errno == ENOSPC) { - marker_error_handler (this); + marker_error_handler (this, local, op_errno); done = 1; goto out; } - if (strcmp (local->loc.path, "/") == 0) { - done = 1; - goto out; + if (local) { + if (local->loc.path && strcmp (local->loc.path, "/") == 0) { + done = 1; + goto out; + } + if (__is_root_gfid (local->loc.gfid)) { + done = 1; + goto out; + } } ret = marker_trav_parent (local); if (ret == -1) { - gf_log (this->name, GF_LOG_DEBUG, "Error occured " + gf_log (this->name, GF_LOG_DEBUG, "Error occurred " "while traversing to the parent, stopping marker"); done = 1; @@ -375,7 +396,7 @@ out: int32_t marker_start_setxattr (call_frame_t *frame, xlator_t *this) { - int32_t ret = 0; + int32_t ret = -1; dict_t *dict = NULL; marker_local_t *local = NULL; marker_conf_t *priv = NULL; @@ -384,19 +405,37 @@ marker_start_setxattr (call_frame_t *frame, xlator_t *this) local = (marker_local_t*) frame->local; + if (!local) + goto out; + dict = dict_new (); + if (!dict) + goto out; + + if (local->loc.inode && uuid_is_null (local->loc.gfid)) + uuid_copy (local->loc.gfid, local->loc.inode->gfid); + + GF_UUID_ASSERT (local->loc.gfid); + ret = dict_set_static_bin (dict, priv->marker_xattr, (void *)local->timebuf, 8); - - gf_log (this->name, GF_LOG_DEBUG, "path = %s", local->loc.path); + if (ret) { + gf_log (this->name, GF_LOG_WARNING, + "failed to set marker xattr (%s)", local->loc.path); + goto out; + } STACK_WIND (frame, marker_specific_setxattr_cbk, FIRST_CHILD(this), - FIRST_CHILD(this)->fops->setxattr, &local->loc, dict, 0); + FIRST_CHILD(this)->fops->setxattr, &local->loc, dict, 0, + NULL); - dict_unref (dict); + ret = 0; +out: + if (dict) + dict_unref (dict); - return 0; + return ret; } void @@ -429,12 +468,24 @@ marker_create_frame (xlator_t *this, marker_local_t *local) int32_t marker_xtime_update_marks (xlator_t *this, marker_local_t *local) { + marker_conf_t *priv = NULL; + + GF_VALIDATE_OR_GOTO ("marker", this, out); + GF_VALIDATE_OR_GOTO (this->name, local, out); + + priv = this->private; + + if ((local->pid == GF_CLIENT_PID_GSYNCD + && !(priv->feature_enabled & GF_XTIME_GSYNC_FORCE)) + || (local->pid == GF_CLIENT_PID_DEFRAG)) + goto out; + marker_gettimeofday (local); marker_local_ref (local); marker_create_frame (this, local); - +out: return 0; } @@ -443,7 +494,7 @@ int32_t marker_mkdir_cbk (call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret, int32_t op_errno, inode_t *inode, struct iatt *buf, struct iatt *preparent, - struct iatt *postparent) + struct iatt *postparent, dict_t *xdata) { marker_conf_t *priv = NULL; marker_local_t *local = NULL; @@ -458,15 +509,18 @@ marker_mkdir_cbk (call_frame_t *frame, void *cookie, xlator_t *this, frame->local = NULL; STACK_UNWIND_STRICT (mkdir, frame, op_ret, op_errno, inode, - buf, preparent, postparent); + buf, preparent, postparent, xdata); if (op_ret == -1 || local == NULL) goto out; + if (uuid_is_null (local->loc.gfid)) + uuid_copy (local->loc.gfid, buf->ia_gfid); + priv = this->private; if (priv->feature_enabled & GF_QUOTA) - quota_set_inode_xattr (this, &local->loc); + mq_set_inode_xattr (this, &local->loc); if (priv->feature_enabled & GF_XTIME) marker_xtime_update_marks (this, local); @@ -479,7 +533,7 @@ out: int marker_mkdir (call_frame_t *frame, xlator_t *this, loc_t *loc, mode_t mode, - dict_t *params) + mode_t umask, dict_t *xdata) { int32_t ret = 0; marker_local_t *local = NULL; @@ -490,7 +544,7 @@ marker_mkdir (call_frame_t *frame, xlator_t *this, loc_t *loc, mode_t mode, if (priv->feature_enabled == 0) goto wind; - ALLOCATE_OR_GOTO (local, marker_local_t, err); + local = mem_get0 (this->local_pool); MARKER_INIT_LOCAL (frame, local); @@ -500,12 +554,12 @@ marker_mkdir (call_frame_t *frame, xlator_t *this, loc_t *loc, mode_t mode, goto err; wind: STACK_WIND (frame, marker_mkdir_cbk, FIRST_CHILD(this), - FIRST_CHILD(this)->fops->mkdir, loc, mode, params); + FIRST_CHILD(this)->fops->mkdir, loc, mode, umask, xdata); return 0; err: STACK_UNWIND_STRICT (mkdir, frame, -1, ENOMEM, NULL, - NULL, NULL, NULL); + NULL, NULL, NULL, NULL); return 0; } @@ -514,7 +568,7 @@ int32_t marker_create_cbk (call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret, int32_t op_errno, fd_t *fd, inode_t *inode, struct iatt *buf, struct iatt *preparent, - struct iatt *postparent) + struct iatt *postparent, dict_t *xdata) { marker_local_t *local = NULL; marker_conf_t *priv = NULL; @@ -529,15 +583,18 @@ marker_create_cbk (call_frame_t *frame, void *cookie, xlator_t *this, frame->local = NULL; STACK_UNWIND_STRICT (create, frame, op_ret, op_errno, fd, inode, buf, - preparent, postparent); + preparent, postparent, xdata); if (op_ret == -1 || local == NULL) goto out; + if (uuid_is_null (local->loc.gfid)) + uuid_copy (local->loc.gfid, buf->ia_gfid); + priv = this->private; if (priv->feature_enabled & GF_QUOTA) - inspect_file_xattr (this, &local->loc, NULL, *buf); + mq_set_inode_xattr (this, &local->loc); if (priv->feature_enabled & GF_XTIME) marker_xtime_update_marks (this, local); @@ -550,7 +607,7 @@ out: int32_t marker_create (call_frame_t *frame, xlator_t *this, loc_t *loc, int32_t flags, - mode_t mode, fd_t *fd, dict_t *params) + mode_t mode, mode_t umask, fd_t *fd, dict_t *xdata) { int32_t ret = 0; marker_local_t *local = NULL; @@ -561,7 +618,7 @@ marker_create (call_frame_t *frame, xlator_t *this, loc_t *loc, int32_t flags, if (priv->feature_enabled == 0) goto wind; - ALLOCATE_OR_GOTO (local, marker_local_t, err); + local = mem_get0 (this->local_pool); MARKER_INIT_LOCAL (frame, local); @@ -571,12 +628,12 @@ marker_create (call_frame_t *frame, xlator_t *this, loc_t *loc, int32_t flags, goto err; wind: STACK_WIND (frame, marker_create_cbk, FIRST_CHILD(this), - FIRST_CHILD(this)->fops->create, loc, flags, mode, fd, - params); + FIRST_CHILD(this)->fops->create, loc, flags, mode, umask, + fd, xdata); return 0; err: STACK_UNWIND_STRICT (create, frame, -1, ENOMEM, NULL, NULL, NULL, NULL, - NULL); + NULL, NULL); return 0; } @@ -585,7 +642,7 @@ err: int32_t marker_writev_cbk (call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret, int32_t op_errno, struct iatt *prebuf, - struct iatt *postbuf) + struct iatt *postbuf, dict_t *xdata) { marker_conf_t *priv = NULL; marker_local_t *local = NULL; @@ -599,7 +656,8 @@ marker_writev_cbk (call_frame_t *frame, void *cookie, xlator_t *this, frame->local = NULL; - STACK_UNWIND_STRICT (writev, frame, op_ret, op_errno, prebuf, postbuf); + STACK_UNWIND_STRICT (writev, frame, op_ret, op_errno, prebuf, postbuf, + xdata); if (op_ret == -1 || local == NULL) goto out; @@ -607,7 +665,7 @@ marker_writev_cbk (call_frame_t *frame, void *cookie, xlator_t *this, priv = this->private; if (priv->feature_enabled & GF_QUOTA) - initiate_quota_txn (this, &local->loc); + mq_initiate_quota_txn (this, &local->loc); if (priv->feature_enabled & GF_XTIME) marker_xtime_update_marks (this, local); @@ -624,8 +682,8 @@ marker_writev (call_frame_t *frame, fd_t *fd, struct iovec *vector, int32_t count, - off_t offset, - struct iobref *iobref) + off_t offset, uint32_t flags, + struct iobref *iobref, dict_t *xdata) { int32_t ret = 0; marker_local_t *local = NULL; @@ -636,7 +694,7 @@ marker_writev (call_frame_t *frame, if (priv->feature_enabled == 0) goto wind; - ALLOCATE_OR_GOTO (local, marker_local_t, err); + local = mem_get0 (this->local_pool); MARKER_INIT_LOCAL (frame, local); @@ -647,10 +705,10 @@ marker_writev (call_frame_t *frame, wind: STACK_WIND (frame, marker_writev_cbk, FIRST_CHILD(this), FIRST_CHILD(this)->fops->writev, fd, vector, count, offset, - iobref); + flags, iobref, xdata); return 0; err: - STACK_UNWIND_STRICT (writev, frame, -1, ENOMEM, NULL, NULL); + STACK_UNWIND_STRICT (writev, frame, -1, ENOMEM, NULL, NULL, NULL); return 0; } @@ -659,7 +717,7 @@ err: int32_t marker_rmdir_cbk (call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret, int32_t op_errno, struct iatt *preparent, - struct iatt *postparent) + struct iatt *postparent, dict_t *xdata) { marker_conf_t *priv = NULL; marker_local_t *local = NULL; @@ -674,7 +732,7 @@ marker_rmdir_cbk (call_frame_t *frame, void *cookie, xlator_t *this, frame->local = NULL; STACK_UNWIND_STRICT (rmdir, frame, op_ret, op_errno, preparent, - postparent); + postparent, xdata); if (op_ret == -1 || local == NULL) goto out; @@ -682,7 +740,7 @@ marker_rmdir_cbk (call_frame_t *frame, void *cookie, xlator_t *this, priv = this->private; if (priv->feature_enabled & GF_QUOTA) - reduce_parent_size (this, &local->loc, -1); + mq_reduce_parent_size (this, &local->loc, -1); if (priv->feature_enabled & GF_XTIME) marker_xtime_update_marks (this, local); @@ -693,7 +751,8 @@ out: } int32_t -marker_rmdir (call_frame_t *frame, xlator_t *this, loc_t *loc, int flags) +marker_rmdir (call_frame_t *frame, xlator_t *this, loc_t *loc, int flags, + dict_t *xdata) { int32_t ret = 0; marker_local_t *local = NULL; @@ -704,7 +763,7 @@ marker_rmdir (call_frame_t *frame, xlator_t *this, loc_t *loc, int flags) if (priv->feature_enabled == 0) goto wind; - ALLOCATE_OR_GOTO (local, marker_local_t, err); + local = mem_get0 (this->local_pool); MARKER_INIT_LOCAL (frame, local); @@ -714,10 +773,10 @@ marker_rmdir (call_frame_t *frame, xlator_t *this, loc_t *loc, int flags) goto err; wind: STACK_WIND (frame, marker_rmdir_cbk, FIRST_CHILD(this), - FIRST_CHILD(this)->fops->rmdir, loc, flags); + FIRST_CHILD(this)->fops->rmdir, loc, flags, xdata); return 0; err: - STACK_UNWIND_STRICT (rmdir, frame, -1, ENOMEM, NULL, NULL); + STACK_UNWIND_STRICT (rmdir, frame, -1, ENOMEM, NULL, NULL, NULL); return 0; } @@ -726,7 +785,7 @@ err: int32_t marker_unlink_cbk (call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret, int32_t op_errno, struct iatt *preparent, - struct iatt *postparent) + struct iatt *postparent, dict_t *xdata) { marker_conf_t *priv = NULL; marker_local_t *local = NULL; @@ -741,7 +800,7 @@ marker_unlink_cbk (call_frame_t *frame, void *cookie, xlator_t *this, frame->local = NULL; STACK_UNWIND_STRICT (unlink, frame, op_ret, op_errno, preparent, - postparent); + postparent, xdata); if (op_ret == -1 || local == NULL) goto out; @@ -749,7 +808,7 @@ marker_unlink_cbk (call_frame_t *frame, void *cookie, xlator_t *this, priv = this->private; if ((priv->feature_enabled & GF_QUOTA) && (local->ia_nlink == 1)) - reduce_parent_size (this, &local->loc, -1); + mq_reduce_parent_size (this, &local->loc, -1); if (priv->feature_enabled & GF_XTIME) marker_xtime_update_marks (this, local); @@ -762,33 +821,38 @@ out: int32_t marker_unlink_stat_cbk (call_frame_t *frame, void *cookie, xlator_t *this, - int32_t op_ret, int32_t op_errno, struct iatt *buf) + int32_t op_ret, int32_t op_errno, struct iatt *buf, + dict_t *xdata) { marker_local_t *local = NULL; + local = frame->local; if (op_ret < 0) { goto err; } - local = frame->local; if (local == NULL) { + op_errno = EINVAL; goto err; } local->ia_nlink = buf->ia_nlink; STACK_WIND (frame, marker_unlink_cbk, FIRST_CHILD(this), - FIRST_CHILD(this)->fops->unlink, &local->loc); + FIRST_CHILD(this)->fops->unlink, &local->loc, local->xflag, + local->xdata); return 0; err: - STACK_UNWIND_STRICT (unlink, frame, -1, ENOMEM, NULL, NULL); - + frame->local = NULL; + STACK_UNWIND_STRICT (unlink, frame, -1, op_errno, NULL, NULL, NULL); + marker_local_unref (local); return 0; } int32_t -marker_unlink (call_frame_t *frame, xlator_t *this, loc_t *loc) +marker_unlink (call_frame_t *frame, xlator_t *this, loc_t *loc, int xflag, + dict_t *xdata) { int32_t ret = 0; marker_local_t *local = NULL; @@ -799,8 +863,10 @@ marker_unlink (call_frame_t *frame, xlator_t *this, loc_t *loc) if (priv->feature_enabled == 0) goto unlink_wind; - ALLOCATE_OR_GOTO (local, marker_local_t, err); - + local = mem_get0 (this->local_pool); + local->xflag = xflag; + if (xdata) + local->xdata = dict_ref (xdata); MARKER_INIT_LOCAL (frame, local); ret = loc_copy (&local->loc, loc); @@ -808,17 +874,21 @@ marker_unlink (call_frame_t *frame, xlator_t *this, loc_t *loc) if (ret == -1) goto err; + if (uuid_is_null (loc->gfid) && loc->inode) + uuid_copy (loc->gfid, loc->inode->gfid); + STACK_WIND (frame, marker_unlink_stat_cbk, FIRST_CHILD(this), - FIRST_CHILD(this)->fops->stat, loc); + FIRST_CHILD(this)->fops->stat, loc, xdata); return 0; unlink_wind: STACK_WIND (frame, marker_unlink_cbk, FIRST_CHILD(this), - FIRST_CHILD(this)->fops->unlink, loc); + FIRST_CHILD(this)->fops->unlink, loc, xflag, xdata); return 0; err: - STACK_UNWIND_STRICT (unlink, frame, -1, ENOMEM, NULL, NULL); - + frame->local = NULL; + STACK_UNWIND_STRICT (unlink, frame, -1, ENOMEM, NULL, NULL, NULL); + marker_local_unref (local); return 0; } @@ -827,13 +897,13 @@ int32_t marker_link_cbk (call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret, int32_t op_errno, inode_t *inode, struct iatt *buf, struct iatt *preparent, - struct iatt *postparent) + struct iatt *postparent, dict_t *xdata) { marker_local_t *local = NULL; marker_conf_t *priv = NULL; if (op_ret == -1) { - gf_log (this->name, GF_LOG_TRACE, "%s occured while " + gf_log (this->name, GF_LOG_TRACE, "%s occurred while " "linking a file ", strerror (op_errno)); } @@ -842,7 +912,7 @@ marker_link_cbk (call_frame_t *frame, void *cookie, xlator_t *this, frame->local = NULL; STACK_UNWIND_STRICT (link, frame, op_ret, op_errno, inode, buf, - preparent, postparent); + preparent, postparent, xdata); if (op_ret == -1 || local == NULL) goto out; @@ -850,7 +920,7 @@ marker_link_cbk (call_frame_t *frame, void *cookie, xlator_t *this, priv = this->private; if (priv->feature_enabled & GF_QUOTA) - initiate_quota_txn (this, &local->loc); + mq_initiate_quota_txn (this, &local->loc); if (priv->feature_enabled & GF_XTIME) marker_xtime_update_marks (this, local); @@ -861,7 +931,8 @@ out: } int32_t -marker_link (call_frame_t *frame, xlator_t *this, loc_t *oldloc, loc_t *newloc) +marker_link (call_frame_t *frame, xlator_t *this, loc_t *oldloc, loc_t *newloc, + dict_t *xdata) { int32_t ret = 0; marker_local_t *local = NULL; @@ -872,7 +943,7 @@ marker_link (call_frame_t *frame, xlator_t *this, loc_t *oldloc, loc_t *newloc) if (priv->feature_enabled == 0) goto wind; - ALLOCATE_OR_GOTO (local, marker_local_t, err); + local = mem_get0 (this->local_pool); MARKER_INIT_LOCAL (frame, local); @@ -882,10 +953,11 @@ marker_link (call_frame_t *frame, xlator_t *this, loc_t *oldloc, loc_t *newloc) goto err; wind: STACK_WIND (frame, marker_link_cbk, FIRST_CHILD(this), - FIRST_CHILD(this)->fops->link, oldloc, newloc); + FIRST_CHILD(this)->fops->link, oldloc, newloc, xdata); return 0; err: - STACK_UNWIND_STRICT (link, frame, -1, ENOMEM, NULL, NULL, NULL, NULL); + STACK_UNWIND_STRICT (link, frame, -1, ENOMEM, NULL, NULL, NULL, NULL, + NULL); return 0; } @@ -893,7 +965,7 @@ err: int32_t marker_rename_done (call_frame_t *frame, void *cookie, xlator_t *this, - int32_t op_ret, int32_t op_errno) + int32_t op_ret, int32_t op_errno, dict_t *xdata) { marker_local_t *local = NULL, *oplocal = NULL; loc_t newloc = {0, }; @@ -912,9 +984,8 @@ marker_rename_done (call_frame_t *frame, void *cookie, xlator_t *this, } gf_log (this->name, GF_LOG_WARNING, - "inodelk (UNLOCK) failed on path:%s, inode (ino:%"PRId64 - ", gfid:%s)(%s)", local->parent_loc.path, - local->parent_loc.inode->ino, + "inodelk (UNLOCK) failed on path:%s (gfid:%s) (%s)", + local->parent_loc.path, uuid_utoa (local->parent_loc.inode->gfid), strerror (op_errno)); } @@ -924,27 +995,29 @@ marker_rename_done (call_frame_t *frame, void *cookie, xlator_t *this, local->stub = NULL; } else if (local->err != 0) { STACK_UNWIND_STRICT (rename, frame, -1, local->err, NULL, NULL, - NULL, NULL, NULL); + NULL, NULL, NULL, NULL); } - reduce_parent_size (this, &oplocal->loc, oplocal->contribution); + mq_reduce_parent_size (this, &oplocal->loc, oplocal->contribution); if (local->loc.inode != NULL) { - reduce_parent_size (this, &local->loc, local->contribution); + mq_reduce_parent_size (this, &local->loc, local->contribution); } newloc.inode = inode_ref (oplocal->loc.inode); newloc.path = gf_strdup (local->loc.path); - newloc.name = gf_strdup (local->loc.name); + newloc.name = strrchr (newloc.path, '/'); + if (newloc.name) + newloc.name++; newloc.parent = inode_ref (local->loc.parent); - newloc.ino = oplocal->loc.inode->ino; - quota_rename_update_newpath (this, &newloc); + mq_rename_update_newpath (this, &newloc); loc_wipe (&newloc); if (priv->feature_enabled & GF_XTIME) { //update marks on oldpath + uuid_copy (local->loc.gfid, oplocal->loc.inode->gfid); marker_xtime_update_marks (this, oplocal); marker_xtime_update_marks (this, local); } @@ -958,7 +1031,7 @@ marker_rename_done (call_frame_t *frame, void *cookie, xlator_t *this, int32_t marker_rename_release_newp_lock (call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret, - int32_t op_errno) + int32_t op_errno, dict_t *xdata) { marker_local_t *local = NULL, *oplocal = NULL; struct gf_flock lock = {0, }; @@ -972,15 +1045,14 @@ marker_rename_release_newp_lock (call_frame_t *frame, void *cookie, } gf_log (this->name, GF_LOG_WARNING, - "inodelk (UNLOCK) failed on path:%s, inode (ino:%"PRId64 - ", gfid:%s)(%s)", oplocal->parent_loc.path, - oplocal->parent_loc.inode->ino, + "inodelk (UNLOCK) failed on %s (gfid:%s) (%s)", + oplocal->parent_loc.path, uuid_utoa (oplocal->parent_loc.inode->gfid), strerror (op_errno)); } if (local->next_lock_on == NULL) { - marker_rename_done (frame, NULL, this, 0, 0); + marker_rename_done (frame, NULL, this, 0, 0, NULL); goto out; } @@ -994,7 +1066,7 @@ marker_rename_release_newp_lock (call_frame_t *frame, void *cookie, marker_rename_done, FIRST_CHILD(this), FIRST_CHILD(this)->fops->inodelk, - this->name, &local->parent_loc, F_SETLKW, &lock); + this->name, &local->parent_loc, F_SETLKW, &lock, NULL); out: return 0; @@ -1004,7 +1076,7 @@ out: int32_t marker_rename_release_oldp_lock (call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret, - int32_t op_errno) + int32_t op_errno, dict_t *xdata) { marker_local_t *local = NULL, *oplocal = NULL; struct gf_flock lock = {0, }; @@ -1016,6 +1088,10 @@ marker_rename_release_oldp_lock (call_frame_t *frame, void *cookie, local->err = op_errno; } + //Reset frame uid and gid if set. + if (cookie == (void *) _GF_UID_GID_CHANGED) + MARKER_RESET_UID_GID (frame, frame->root, local); + lock.l_type = F_UNLCK; lock.l_whence = SEEK_SET; lock.l_start = 0; @@ -1026,7 +1102,7 @@ marker_rename_release_oldp_lock (call_frame_t *frame, void *cookie, marker_rename_release_newp_lock, FIRST_CHILD(this), FIRST_CHILD(this)->fops->inodelk, - this->name, &oplocal->parent_loc, F_SETLKW, &lock); + this->name, &oplocal->parent_loc, F_SETLKW, &lock, NULL); return 0; } @@ -1035,7 +1111,8 @@ int32_t marker_rename_cbk (call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret, int32_t op_errno, struct iatt *buf, struct iatt *preoldparent, struct iatt *postoldparent, - struct iatt *prenewparent, struct iatt *postnewparent) + struct iatt *prenewparent, struct iatt *postnewparent, + dict_t *xdata) { marker_conf_t *priv = NULL; marker_local_t *local = NULL; @@ -1043,6 +1120,7 @@ marker_rename_cbk (call_frame_t *frame, void *cookie, xlator_t *this, call_stub_t *stub = NULL; int32_t ret = 0; char contri_key [512] = {0, }; + loc_t newloc = {0, }; local = (marker_local_t *) frame->local; @@ -1057,7 +1135,7 @@ marker_rename_cbk (call_frame_t *frame, void *cookie, xlator_t *this, local->err = op_errno; } - gf_log (this->name, GF_LOG_TRACE, "%s occured while " + gf_log (this->name, GF_LOG_TRACE, "%s occurred while " "renaming a file ", strerror (op_errno)); } @@ -1069,7 +1147,7 @@ marker_rename_cbk (call_frame_t *frame, void *cookie, xlator_t *this, stub = fop_rename_cbk_stub (frame, default_rename_cbk, op_ret, op_errno, buf, preoldparent, postoldparent, prenewparent, - postnewparent); + postnewparent, xdata); if (stub == NULL) { local->err = ENOMEM; goto quota_err; @@ -1083,16 +1161,31 @@ marker_rename_cbk (call_frame_t *frame, void *cookie, xlator_t *this, goto quota_err; } - STACK_WIND (frame, marker_rename_release_oldp_lock, - FIRST_CHILD(this), - FIRST_CHILD(this)->fops->removexattr, &local->loc, - contri_key); + /* Removexattr requires uid and gid to be 0, + * reset them in the callback. + */ + MARKER_SET_UID_GID (frame, local, frame->root); + + newloc.inode = inode_ref (oplocal->loc.inode); + newloc.path = gf_strdup (local->loc.path); + newloc.name = strrchr (newloc.path, '/'); + if (newloc.name) + newloc.name++; + newloc.parent = inode_ref (local->loc.parent); + uuid_copy (newloc.gfid, oplocal->loc.inode->gfid); + + STACK_WIND_COOKIE (frame, marker_rename_release_oldp_lock, + frame->cookie, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->removexattr, + &newloc, contri_key, NULL); + + loc_wipe (&newloc); } else { frame->local = NULL; STACK_UNWIND_STRICT (rename, frame, op_ret, op_errno, buf, preoldparent, postoldparent, prenewparent, - postnewparent); + postnewparent, xdata); if ((op_ret < 0) || (local == NULL)) { goto out; @@ -1100,6 +1193,7 @@ marker_rename_cbk (call_frame_t *frame, void *cookie, xlator_t *this, if (priv->feature_enabled & GF_XTIME) { //update marks on oldpath + uuid_copy (local->loc.gfid, oplocal->loc.inode->gfid); marker_xtime_update_marks (this, oplocal); marker_xtime_update_marks (this, local); } @@ -1114,15 +1208,14 @@ out: return 0; quota_err: - marker_rename_release_oldp_lock (frame, NULL, this, 0, 0); + marker_rename_release_oldp_lock (frame, NULL, this, 0, 0, NULL); return 0; } int32_t marker_do_rename (call_frame_t *frame, void *cookie, xlator_t *this, - int32_t op_ret, int32_t op_errno, dict_t *dict) - + int32_t op_ret, int32_t op_errno, dict_t *dict, dict_t *xdata) { marker_local_t *local = NULL, *oplocal = NULL; char contri_key[512] = {0, }; @@ -1132,12 +1225,15 @@ marker_do_rename (call_frame_t *frame, void *cookie, xlator_t *this, local = frame->local; oplocal = local->oplocal; + //Reset frame uid and gid if set. + if (cookie == (void *) _GF_UID_GID_CHANGED) + MARKER_RESET_UID_GID (frame, frame->root, local); + if ((op_ret < 0) && (op_errno != ENOATTR)) { local->err = op_errno; gf_log (this->name, GF_LOG_WARNING, - "fetching contribution values from %s (ino:%"PRId64", " - "gfid:%s) failed (%s)", local->loc.path, - local->loc.inode->ino, + "fetching contribution values from %s (gfid:%s) " + "failed (%s)", local->loc.path, uuid_utoa (local->loc.inode->gfid), strerror (op_errno)); goto err; @@ -1158,12 +1254,12 @@ marker_do_rename (call_frame_t *frame, void *cookie, xlator_t *this, STACK_WIND (frame, marker_rename_cbk, FIRST_CHILD(this), FIRST_CHILD(this)->fops->rename, &oplocal->loc, - &local->loc); + &local->loc, NULL); return 0; err: - marker_rename_release_oldp_lock (frame, NULL, this, 0, 0); + marker_rename_release_oldp_lock (frame, NULL, this, 0, 0, NULL); return 0; } @@ -1171,7 +1267,7 @@ err: int32_t marker_get_newpath_contribution (call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret, - int32_t op_errno, dict_t *dict) + int32_t op_errno, dict_t *dict, dict_t *xdata) { marker_local_t *local = NULL, *oplocal = NULL; char contri_key[512] = {0, }; @@ -1181,12 +1277,15 @@ marker_get_newpath_contribution (call_frame_t *frame, void *cookie, local = frame->local; oplocal = local->oplocal; + //Reset frame uid and gid if set. + if (cookie == (void *) _GF_UID_GID_CHANGED) + MARKER_RESET_UID_GID (frame, frame->root, local); + if ((op_ret < 0) && (op_errno != ENOATTR)) { local->err = op_errno; gf_log (this->name, GF_LOG_WARNING, - "fetching contribution values from %s (ino:%"PRId64", " - "gfid:%s) failed (%s)", oplocal->loc.path, - oplocal->loc.inode->ino, + "fetching contribution values from %s (gfid:%s) " + "failed (%s)", oplocal->loc.path, uuid_utoa (oplocal->loc.inode->gfid), strerror (op_errno)); goto err; @@ -1208,17 +1307,26 @@ marker_get_newpath_contribution (call_frame_t *frame, void *cookie, goto err; } - STACK_WIND (frame, marker_do_rename, - FIRST_CHILD(this), - FIRST_CHILD(this)->fops->getxattr, &local->loc, - contri_key); + /* getxattr requires uid and gid to be 0, + * reset them in the callback. + */ + MARKER_SET_UID_GID (frame, local, frame->root); + if (uuid_is_null (local->loc.gfid)) + uuid_copy (local->loc.gfid, local->loc.inode->gfid); + + GF_UUID_ASSERT (local->loc.gfid); + + STACK_WIND_COOKIE (frame, marker_do_rename, + frame->cookie, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->getxattr, + &local->loc, contri_key, NULL); } else { - marker_do_rename (frame, NULL, this, 0, 0, NULL); + marker_do_rename (frame, NULL, this, 0, 0, NULL, NULL); } return 0; err: - marker_rename_release_oldp_lock (frame, NULL, this, 0, 0); + marker_rename_release_oldp_lock (frame, NULL, this, 0, 0, NULL); return 0; } @@ -1226,7 +1334,7 @@ err: int32_t marker_get_oldpath_contribution (call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret, - int32_t op_errno) + int32_t op_errno, dict_t *xdata) { marker_local_t *local = NULL, *oplocal = NULL; char contri_key[512] = {0, }; @@ -1238,10 +1346,8 @@ marker_get_oldpath_contribution (call_frame_t *frame, void *cookie, if (op_ret < 0) { local->err = op_errno; gf_log (this->name, GF_LOG_WARNING, - "cannot hold inodelk on %s (ino:%"PRId64", gfid:%s)" - "(%s)", + "cannot hold inodelk on %s (gfid:%s) (%s)", local->next_lock_on->path, - local->next_lock_on->inode->ino, uuid_utoa (local->next_lock_on->inode->gfid), strerror (op_errno)); goto lock_err; @@ -1253,22 +1359,34 @@ marker_get_oldpath_contribution (call_frame_t *frame, void *cookie, goto quota_err; } - STACK_WIND (frame, marker_get_newpath_contribution, FIRST_CHILD(this), - FIRST_CHILD(this)->fops->getxattr, &oplocal->loc, - contri_key); + /* getxattr requires uid and gid to be 0, + * reset them in the callback. + */ + MARKER_SET_UID_GID (frame, local, frame->root); + + if (uuid_is_null (oplocal->loc.gfid)) + uuid_copy (oplocal->loc.gfid, + oplocal->loc.inode->gfid); + + GF_UUID_ASSERT (oplocal->loc.gfid); + + STACK_WIND_COOKIE (frame, marker_get_newpath_contribution, + frame->cookie, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->getxattr, + &oplocal->loc, contri_key, NULL); return 0; quota_err: - marker_rename_release_oldp_lock (frame, NULL, this, 0, 0); + marker_rename_release_oldp_lock (frame, NULL, this, 0, 0, NULL); return 0; lock_err: if ((local->next_lock_on == NULL) || (local->next_lock_on == &local->parent_loc)) { local->next_lock_on = NULL; - marker_rename_release_oldp_lock (frame, NULL, this, 0, 0); + marker_rename_release_oldp_lock (frame, NULL, this, 0, 0, NULL); } else { - marker_rename_release_newp_lock (frame, NULL, this, 0, 0); + marker_rename_release_newp_lock (frame, NULL, this, 0, 0, NULL); } return 0; @@ -1277,7 +1395,7 @@ lock_err: int32_t marker_rename_inodelk_cbk (call_frame_t *frame, void *cookie, xlator_t *this, - int32_t op_ret, int32_t op_errno) + int32_t op_ret, int32_t op_errno, dict_t *xdata) { marker_local_t *local = NULL, *oplocal = NULL; loc_t *loc = NULL; @@ -1295,9 +1413,8 @@ marker_rename_inodelk_cbk (call_frame_t *frame, void *cookie, xlator_t *this, local->err = op_errno; gf_log (this->name, GF_LOG_WARNING, - "cannot hold inodelk on %s (ino:%"PRId64", gfid:%s)" - "(%s)", loc->path, loc->inode->ino, - uuid_utoa (loc->inode->gfid), + "cannot hold inodelk on %s (gfid:%s) (%s)", + loc->path, uuid_utoa (loc->inode->gfid), strerror (op_errno)); goto err; } @@ -1313,22 +1430,22 @@ marker_rename_inodelk_cbk (call_frame_t *frame, void *cookie, xlator_t *this, FIRST_CHILD(this), FIRST_CHILD(this)->fops->inodelk, this->name, local->next_lock_on, - F_SETLKW, &lock); + F_SETLKW, &lock, NULL); } else { - marker_get_oldpath_contribution (frame, 0, this, 0, 0); + marker_get_oldpath_contribution (frame, 0, this, 0, 0, NULL); } return 0; err: - marker_rename_done (frame, NULL, this, 0, 0); + marker_rename_done (frame, NULL, this, 0, 0, NULL); return 0; } int32_t marker_rename (call_frame_t *frame, xlator_t *this, loc_t *oldloc, - loc_t *newloc) + loc_t *newloc, dict_t *xdata) { int32_t ret = 0; marker_local_t *local = NULL; @@ -1342,11 +1459,11 @@ marker_rename (call_frame_t *frame, xlator_t *this, loc_t *oldloc, if (priv->feature_enabled == 0) goto rename_wind; - ALLOCATE_OR_GOTO (local, marker_local_t, err); + local = mem_get0 (this->local_pool); MARKER_INIT_LOCAL (frame, local); - ALLOCATE_OR_GOTO (oplocal, marker_local_t, err); + oplocal = mem_get0 (this->local_pool); MARKER_INIT_LOCAL (frame, oplocal); @@ -1366,11 +1483,11 @@ marker_rename (call_frame_t *frame, xlator_t *this, loc_t *oldloc, goto rename_wind; } - ret = quota_inode_loc_fill (NULL, newloc->parent, &local->parent_loc); + ret = mq_inode_loc_fill (NULL, newloc->parent, &local->parent_loc); if (ret < 0) goto err; - ret = quota_inode_loc_fill (NULL, oldloc->parent, &oplocal->parent_loc); + ret = mq_inode_loc_fill (NULL, oldloc->parent, &oplocal->parent_loc); if (ret < 0) goto err; @@ -1397,18 +1514,18 @@ marker_rename (call_frame_t *frame, xlator_t *this, loc_t *oldloc, FIRST_CHILD(this), FIRST_CHILD(this)->fops->inodelk, this->name, lock_on, - F_SETLKW, &lock); + F_SETLKW, &lock, NULL); return 0; rename_wind: STACK_WIND (frame, marker_rename_cbk, FIRST_CHILD(this), - FIRST_CHILD(this)->fops->rename, oldloc, newloc); + FIRST_CHILD(this)->fops->rename, oldloc, newloc, xdata); return 0; err: STACK_UNWIND_STRICT (rename, frame, -1, ENOMEM, NULL, - NULL, NULL, NULL, NULL); + NULL, NULL, NULL, NULL, NULL); return 0; } @@ -1417,13 +1534,13 @@ err: int32_t marker_truncate_cbk (call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret, int32_t op_errno, struct iatt *prebuf, - struct iatt *postbuf) + struct iatt *postbuf, dict_t *xdata) { marker_local_t *local = NULL; marker_conf_t *priv = NULL; if (op_ret == -1) { - gf_log (this->name, GF_LOG_TRACE, "%s occured while " + gf_log (this->name, GF_LOG_TRACE, "%s occurred while " "truncating a file ", strerror (op_errno)); } @@ -1432,7 +1549,7 @@ marker_truncate_cbk (call_frame_t *frame, void *cookie, xlator_t *this, frame->local = NULL; STACK_UNWIND_STRICT (truncate, frame, op_ret, op_errno, prebuf, - postbuf); + postbuf, xdata); if (op_ret == -1 || local == NULL) goto out; @@ -1440,7 +1557,7 @@ marker_truncate_cbk (call_frame_t *frame, void *cookie, xlator_t *this, priv = this->private; if (priv->feature_enabled & GF_QUOTA) - initiate_quota_txn (this, &local->loc); + mq_initiate_quota_txn (this, &local->loc); if (priv->feature_enabled & GF_XTIME) marker_xtime_update_marks (this, local); @@ -1452,7 +1569,8 @@ out: } int32_t -marker_truncate (call_frame_t *frame, xlator_t *this, loc_t *loc, off_t offset) +marker_truncate (call_frame_t *frame, xlator_t *this, loc_t *loc, off_t offset, + dict_t *xdata) { int32_t ret = 0; marker_local_t *local = NULL; @@ -1463,7 +1581,7 @@ marker_truncate (call_frame_t *frame, xlator_t *this, loc_t *loc, off_t offset) if (priv->feature_enabled == 0) goto wind; - ALLOCATE_OR_GOTO (local, marker_local_t, err); + local = mem_get0 (this->local_pool); MARKER_INIT_LOCAL (frame, local); @@ -1473,10 +1591,10 @@ marker_truncate (call_frame_t *frame, xlator_t *this, loc_t *loc, off_t offset) goto err; wind: STACK_WIND (frame, marker_truncate_cbk, FIRST_CHILD(this), - FIRST_CHILD(this)->fops->truncate, loc, offset); + FIRST_CHILD(this)->fops->truncate, loc, offset, xdata); return 0; err: - STACK_UNWIND_STRICT (truncate, frame, -1, ENOMEM, NULL, NULL); + STACK_UNWIND_STRICT (truncate, frame, -1, ENOMEM, NULL, NULL, NULL); return 0; } @@ -1485,13 +1603,13 @@ err: int32_t marker_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) + struct iatt *postbuf, dict_t *xdata) { marker_local_t *local = NULL; marker_conf_t *priv = NULL; if (op_ret == -1) { - gf_log (this->name, GF_LOG_TRACE, "%s occured while " + gf_log (this->name, GF_LOG_TRACE, "%s occurred while " "truncating a file ", strerror (op_errno)); } @@ -1500,7 +1618,7 @@ marker_ftruncate_cbk (call_frame_t *frame, void *cookie, xlator_t *this, frame->local = NULL; STACK_UNWIND_STRICT (ftruncate, frame, op_ret, op_errno, prebuf, - postbuf); + postbuf, xdata); if (op_ret == -1 || local == NULL) goto out; @@ -1508,7 +1626,7 @@ marker_ftruncate_cbk (call_frame_t *frame, void *cookie, xlator_t *this, priv = this->private; if (priv->feature_enabled & GF_QUOTA) - initiate_quota_txn (this, &local->loc); + mq_initiate_quota_txn (this, &local->loc); if (priv->feature_enabled & GF_XTIME) marker_xtime_update_marks (this, local); @@ -1519,7 +1637,8 @@ out: } int32_t -marker_ftruncate (call_frame_t *frame, xlator_t *this, fd_t *fd, off_t offset) +marker_ftruncate (call_frame_t *frame, xlator_t *this, fd_t *fd, off_t offset, + dict_t *xdata) { int32_t ret = 0; marker_local_t *local = NULL; @@ -1530,7 +1649,7 @@ marker_ftruncate (call_frame_t *frame, xlator_t *this, fd_t *fd, off_t offset) if (priv->feature_enabled == 0) goto wind; - ALLOCATE_OR_GOTO (local, marker_local_t, err); + local = mem_get0 (this->local_pool); MARKER_INIT_LOCAL (frame, local); @@ -1540,10 +1659,10 @@ marker_ftruncate (call_frame_t *frame, xlator_t *this, fd_t *fd, off_t offset) goto err; wind: STACK_WIND (frame, marker_ftruncate_cbk, FIRST_CHILD(this), - FIRST_CHILD(this)->fops->ftruncate, fd, offset); + FIRST_CHILD(this)->fops->ftruncate, fd, offset, xdata); return 0; err: - STACK_UNWIND_STRICT (ftruncate, frame, -1, ENOMEM, NULL, NULL); + STACK_UNWIND_STRICT (ftruncate, frame, -1, ENOMEM, NULL, NULL, NULL); return 0; } @@ -1553,13 +1672,13 @@ int32_t marker_symlink_cbk (call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret, int32_t op_errno, inode_t *inode, struct iatt *buf, struct iatt *preparent, - struct iatt *postparent) + struct iatt *postparent, dict_t *xdata) { marker_conf_t *priv = NULL; marker_local_t *local = NULL; if (op_ret == -1) { - gf_log (this->name, GF_LOG_TRACE, "%s occured while " + gf_log (this->name, GF_LOG_TRACE, "%s occurred while " "creating symlinks ", strerror (op_errno)); } @@ -1568,15 +1687,18 @@ marker_symlink_cbk (call_frame_t *frame, void *cookie, xlator_t *this, frame->local = NULL; STACK_UNWIND_STRICT (symlink, frame, op_ret, op_errno, inode, buf, - preparent, postparent); + preparent, postparent, xdata); if (op_ret == -1 || local == NULL) goto out; + if (uuid_is_null (local->loc.gfid)) + uuid_copy (local->loc.gfid, buf->ia_gfid); + priv = this->private; if (priv->feature_enabled & GF_QUOTA) - inspect_file_xattr (this, &local->loc, NULL, *buf); + mq_set_inode_xattr (this, &local->loc); if (priv->feature_enabled & GF_XTIME) marker_xtime_update_marks (this, local); @@ -1588,7 +1710,7 @@ out: int marker_symlink (call_frame_t *frame, xlator_t *this, const char *linkpath, - loc_t *loc, dict_t *params) + loc_t *loc, mode_t umask, dict_t *xdata) { int32_t ret = 0; marker_local_t *local = NULL; @@ -1599,7 +1721,7 @@ marker_symlink (call_frame_t *frame, xlator_t *this, const char *linkpath, if (priv->feature_enabled == 0) goto wind; - ALLOCATE_OR_GOTO (local, marker_local_t, err); + local = mem_get0 (this->local_pool); MARKER_INIT_LOCAL (frame, local); @@ -1609,11 +1731,12 @@ marker_symlink (call_frame_t *frame, xlator_t *this, const char *linkpath, goto err; wind: STACK_WIND (frame, marker_symlink_cbk, FIRST_CHILD(this), - FIRST_CHILD(this)->fops->symlink, linkpath, loc, params); + FIRST_CHILD(this)->fops->symlink, linkpath, loc, umask, + xdata); return 0; err: STACK_UNWIND_STRICT (symlink, frame, -1, ENOMEM, NULL, - NULL, NULL, NULL); + NULL, NULL, NULL, NULL); return 0; } @@ -1622,13 +1745,13 @@ int32_t marker_mknod_cbk (call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret, int32_t op_errno, inode_t *inode, struct iatt *buf, struct iatt *preparent, - struct iatt *postparent) + struct iatt *postparent, dict_t *xdata) { marker_local_t *local = NULL; marker_conf_t *priv = NULL; if (op_ret == -1) { - gf_log (this->name, GF_LOG_TRACE, "%s occured while " + gf_log (this->name, GF_LOG_TRACE, "%s occurred while " "creating symlinks ", strerror (op_errno)); } @@ -1637,15 +1760,18 @@ marker_mknod_cbk (call_frame_t *frame, void *cookie, xlator_t *this, frame->local = NULL; STACK_UNWIND_STRICT (mknod, frame, op_ret, op_errno, inode, - buf, preparent, postparent); + buf, preparent, postparent, xdata); if (op_ret == -1 || local == NULL) goto out; + if (uuid_is_null (local->loc.gfid)) + uuid_copy (local->loc.gfid, buf->ia_gfid); + priv = this->private; if ((priv->feature_enabled & GF_QUOTA) && (S_ISREG (local->mode))) { - inspect_file_xattr (this, &local->loc, NULL, *buf); + mq_set_inode_xattr (this, &local->loc); } if (priv->feature_enabled & GF_XTIME) @@ -1658,7 +1784,7 @@ out: int marker_mknod (call_frame_t *frame, xlator_t *this, loc_t *loc, mode_t mode, - dev_t rdev, dict_t *parms) + dev_t rdev, mode_t umask, dict_t *xdata) { int32_t ret = 0; marker_local_t *local = NULL; @@ -1669,7 +1795,7 @@ marker_mknod (call_frame_t *frame, xlator_t *this, loc_t *loc, mode_t mode, if (priv->feature_enabled == 0) goto wind; - ALLOCATE_OR_GOTO (local, marker_local_t, err); + local = mem_get0 (this->local_pool); MARKER_INIT_LOCAL (frame, local); @@ -1681,11 +1807,216 @@ marker_mknod (call_frame_t *frame, xlator_t *this, loc_t *loc, mode_t mode, goto err; wind: STACK_WIND (frame, marker_mknod_cbk, FIRST_CHILD(this), - FIRST_CHILD(this)->fops->mknod, loc, mode, rdev, parms); + FIRST_CHILD(this)->fops->mknod, loc, mode, rdev, umask, + xdata); return 0; err: STACK_UNWIND_STRICT (mknod, frame, -1, ENOMEM, NULL, - NULL, NULL, NULL); + NULL, NULL, NULL, NULL); + return 0; +} + + +int32_t +marker_fallocate_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) +{ + marker_local_t *local = NULL; + marker_conf_t *priv = NULL; + + if (op_ret == -1) { + gf_log (this->name, GF_LOG_TRACE, "%s occurred while " + "fallocating a file ", strerror (op_errno)); + } + + local = (marker_local_t *) frame->local; + + frame->local = NULL; + + STACK_UNWIND_STRICT (fallocate, frame, op_ret, op_errno, prebuf, + postbuf, xdata); + + if (op_ret == -1 || local == NULL) + goto out; + + priv = this->private; + + if (priv->feature_enabled & GF_QUOTA) + mq_initiate_quota_txn (this, &local->loc); + + if (priv->feature_enabled & GF_XTIME) + marker_xtime_update_marks (this, local); +out: + marker_local_unref (local); + + return 0; +} + +int32_t +marker_fallocate(call_frame_t *frame, xlator_t *this, fd_t *fd, int32_t mode, + off_t offset, size_t len, dict_t *xdata) +{ + int32_t ret = 0; + marker_local_t *local = NULL; + marker_conf_t *priv = NULL; + + priv = this->private; + + if (priv->feature_enabled == 0) + goto wind; + + local = mem_get0 (this->local_pool); + + MARKER_INIT_LOCAL (frame, local); + + ret = marker_inode_loc_fill (fd->inode, &local->loc); + + if (ret == -1) + goto err; +wind: + STACK_WIND (frame, marker_fallocate_cbk, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->fallocate, fd, mode, offset, len, + xdata); + return 0; +err: + STACK_UNWIND_STRICT (fallocate, frame, -1, ENOMEM, NULL, NULL, NULL); + + return 0; +} + + +int32_t +marker_discard_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) +{ + marker_local_t *local = NULL; + marker_conf_t *priv = NULL; + + if (op_ret == -1) { + gf_log (this->name, GF_LOG_TRACE, "%s occurred during discard", + strerror (op_errno)); + } + + local = (marker_local_t *) frame->local; + + frame->local = NULL; + + STACK_UNWIND_STRICT (discard, frame, op_ret, op_errno, prebuf, + postbuf, xdata); + + if (op_ret == -1 || local == NULL) + goto out; + + priv = this->private; + + if (priv->feature_enabled & GF_QUOTA) + mq_initiate_quota_txn (this, &local->loc); + + if (priv->feature_enabled & GF_XTIME) + marker_xtime_update_marks (this, local); +out: + marker_local_unref (local); + + return 0; +} + +int32_t +marker_discard(call_frame_t *frame, xlator_t *this, fd_t *fd, off_t offset, + size_t len, dict_t *xdata) +{ + int32_t ret = 0; + marker_local_t *local = NULL; + marker_conf_t *priv = NULL; + + priv = this->private; + + if (priv->feature_enabled == 0) + goto wind; + + local = mem_get0 (this->local_pool); + + MARKER_INIT_LOCAL (frame, local); + + ret = marker_inode_loc_fill (fd->inode, &local->loc); + + if (ret == -1) + goto err; +wind: + STACK_WIND (frame, marker_discard_cbk, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->discard, fd, offset, len, xdata); + return 0; +err: + STACK_UNWIND_STRICT (discard, frame, -1, ENOMEM, NULL, NULL, NULL); + + return 0; +} + +int32_t +marker_zerofill_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) +{ + marker_local_t *local = NULL; + marker_conf_t *priv = NULL; + + if (op_ret == -1) { + gf_log (this->name, GF_LOG_TRACE, "%s occurred during zerofill", + strerror (op_errno)); + } + + local = (marker_local_t *) frame->local; + + frame->local = NULL; + + STACK_UNWIND_STRICT (zerofill, frame, op_ret, op_errno, prebuf, + postbuf, xdata); + + if (op_ret == -1 || local == NULL) + goto out; + + priv = this->private; + + if (priv->feature_enabled & GF_QUOTA) + mq_initiate_quota_txn (this, &local->loc); + + if (priv->feature_enabled & GF_XTIME) + marker_xtime_update_marks (this, local); +out: + marker_local_unref (local); + + return 0; +} + +int32_t +marker_zerofill(call_frame_t *frame, xlator_t *this, fd_t *fd, off_t offset, + size_t len, dict_t *xdata) +{ + int32_t ret = 0; + marker_local_t *local = NULL; + marker_conf_t *priv = NULL; + + priv = this->private; + + if (priv->feature_enabled == 0) + goto wind; + + local = mem_get0 (this->local_pool); + + MARKER_INIT_LOCAL (frame, local); + + ret = marker_inode_loc_fill (fd->inode, &local->loc); + + if (ret == -1) + goto err; +wind: + STACK_WIND (frame, marker_zerofill_cbk, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->zerofill, fd, offset, len, xdata); + return 0; +err: + STACK_UNWIND_STRICT (zerofill, frame, -1, ENOMEM, NULL, NULL, NULL); + return 0; } @@ -1716,7 +2047,7 @@ call_from_sp_client_to_reset_tmfile (call_frame_t *frame, if (data == NULL) return -1; - if (frame->root->pid != -1) { + if (frame->root->pid != GF_CLIENT_PID_GSYNCD) { op_ret = -1; op_errno = EPERM; @@ -1745,7 +2076,7 @@ call_from_sp_client_to_reset_tmfile (call_frame_t *frame, op_errno = EINVAL; } out: - STACK_UNWIND_STRICT (setxattr, frame, op_ret, op_errno); + STACK_UNWIND_STRICT (setxattr, frame, op_ret, op_errno, NULL); return 0; } @@ -1753,21 +2084,21 @@ out: int32_t marker_setxattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this, - int32_t op_ret, int32_t op_errno) + int32_t op_ret, int32_t op_errno, dict_t *xdata) { marker_local_t *local = NULL; marker_conf_t *priv = NULL; if (op_ret == -1) { - gf_log (this->name, GF_LOG_TRACE, "%s occured while " - "creating symlinks ", strerror (op_errno)); + gf_log (this->name, GF_LOG_TRACE, "%s occurred in " + "setxattr ", strerror (op_errno)); } local = (marker_local_t *) frame->local; frame->local = NULL; - STACK_UNWIND_STRICT (setxattr, frame, op_ret, op_errno); + STACK_UNWIND_STRICT (setxattr, frame, op_ret, op_errno, xdata); if (op_ret == -1 || local == NULL) goto out; @@ -1784,7 +2115,7 @@ out: int32_t marker_setxattr (call_frame_t *frame, xlator_t *this, loc_t *loc, dict_t *dict, - int32_t flags) + int32_t flags, dict_t *xdata) { int32_t ret = 0; marker_local_t *local = NULL; @@ -1799,7 +2130,7 @@ marker_setxattr (call_frame_t *frame, xlator_t *this, loc_t *loc, dict_t *dict, if (ret == 0) return 0; - ALLOCATE_OR_GOTO (local, marker_local_t, err); + local = mem_get0 (this->local_pool); MARKER_INIT_LOCAL (frame, local); @@ -1809,10 +2140,10 @@ marker_setxattr (call_frame_t *frame, xlator_t *this, loc_t *loc, dict_t *dict, goto err; wind: STACK_WIND (frame, marker_setxattr_cbk, FIRST_CHILD(this), - FIRST_CHILD(this)->fops->setxattr, loc, dict, flags); + FIRST_CHILD(this)->fops->setxattr, loc, dict, flags, xdata); return 0; err: - STACK_UNWIND_STRICT (setxattr, frame, -1, ENOMEM); + STACK_UNWIND_STRICT (setxattr, frame, -1, ENOMEM, NULL); return 0; } @@ -1820,13 +2151,13 @@ err: int32_t marker_fsetxattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this, - int32_t op_ret, int32_t op_errno) + int32_t op_ret, int32_t op_errno, dict_t *xdata) { marker_local_t *local = NULL; marker_conf_t *priv = NULL; if (op_ret == -1) { - gf_log (this->name, GF_LOG_TRACE, "%s occured while " + gf_log (this->name, GF_LOG_TRACE, "%s occurred while " "creating symlinks ", strerror (op_errno)); } @@ -1834,7 +2165,7 @@ marker_fsetxattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this, frame->local = NULL; - STACK_UNWIND_STRICT (fsetxattr, frame, op_ret, op_errno); + STACK_UNWIND_STRICT (fsetxattr, frame, op_ret, op_errno, xdata); if (op_ret == -1 || local == NULL) goto out; @@ -1851,7 +2182,7 @@ out: int32_t marker_fsetxattr (call_frame_t *frame, xlator_t *this, fd_t *fd, dict_t *dict, - int32_t flags) + int32_t flags, dict_t *xdata) { int32_t ret = 0; marker_local_t *local = NULL; @@ -1866,7 +2197,7 @@ marker_fsetxattr (call_frame_t *frame, xlator_t *this, fd_t *fd, dict_t *dict, if (ret == 0) return 0; - ALLOCATE_OR_GOTO (local, marker_local_t, err); + local = mem_get0 (this->local_pool); MARKER_INIT_LOCAL (frame, local); @@ -1876,10 +2207,10 @@ marker_fsetxattr (call_frame_t *frame, xlator_t *this, fd_t *fd, dict_t *dict, goto err; wind: STACK_WIND (frame, marker_fsetxattr_cbk, FIRST_CHILD(this), - FIRST_CHILD(this)->fops->fsetxattr, fd, dict, flags); + FIRST_CHILD(this)->fops->fsetxattr, fd, dict, flags, xdata); return 0; err: - STACK_UNWIND_STRICT (fsetxattr, frame, -1, ENOMEM); + STACK_UNWIND_STRICT (fsetxattr, frame, -1, ENOMEM, NULL); return 0; } @@ -1888,13 +2219,13 @@ err: int32_t marker_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) + struct iatt *statpost, dict_t *xdata) { marker_local_t *local = NULL; marker_conf_t *priv = NULL; if (op_ret == -1) { - gf_log (this->name, GF_LOG_ERROR, "%s occured while " + gf_log (this->name, GF_LOG_ERROR, "%s occurred while " "creating symlinks ", strerror (op_errno)); } @@ -1903,7 +2234,7 @@ marker_fsetattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this, frame->local = NULL; STACK_UNWIND_STRICT (fsetattr, frame, op_ret, op_errno, statpre, - statpost); + statpost, xdata); if (op_ret == -1 || local == NULL) goto out; @@ -1921,7 +2252,7 @@ out: int32_t marker_fsetattr (call_frame_t *frame, xlator_t *this, fd_t *fd, - struct iatt *stbuf, int32_t valid) + struct iatt *stbuf, int32_t valid, dict_t *xdata) { int32_t ret = 0; marker_local_t *local = NULL; @@ -1932,7 +2263,7 @@ marker_fsetattr (call_frame_t *frame, xlator_t *this, fd_t *fd, if (priv->feature_enabled == 0) goto wind; - ALLOCATE_OR_GOTO (local, marker_local_t, err); + local = mem_get0 (this->local_pool); MARKER_INIT_LOCAL (frame, local); @@ -1942,10 +2273,10 @@ marker_fsetattr (call_frame_t *frame, xlator_t *this, fd_t *fd, goto err; wind: STACK_WIND (frame, marker_fsetattr_cbk, FIRST_CHILD (this), - FIRST_CHILD (this)->fops->fsetattr, fd, stbuf, valid); + FIRST_CHILD (this)->fops->fsetattr, fd, stbuf, valid, xdata); return 0; err: - STACK_UNWIND_STRICT (fsetattr, frame, -1, ENOMEM, NULL, NULL); + STACK_UNWIND_STRICT (fsetattr, frame, -1, ENOMEM, NULL, NULL, NULL); return 0; } @@ -1954,7 +2285,7 @@ err: int32_t marker_setattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret, int32_t op_errno, struct iatt *statpre, - struct iatt *statpost) + struct iatt *statpost, dict_t *xdata) { marker_local_t *local = NULL; marker_conf_t *priv = NULL; @@ -1966,13 +2297,13 @@ marker_setattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this, if (op_ret == -1) { gf_log (this->name, ((op_errno == ENOENT) ? GF_LOG_DEBUG : GF_LOG_ERROR), - "%s occured during setattr of %s", + "%s occurred during setattr of %s", strerror (op_errno), (local ? local->loc.path : "<nul>")); } STACK_UNWIND_STRICT (setattr, frame, op_ret, op_errno, statpre, - statpost); + statpost, xdata); if (op_ret == -1 || local == NULL) goto out; @@ -1989,7 +2320,7 @@ out: int32_t marker_setattr (call_frame_t *frame, xlator_t *this, loc_t *loc, - struct iatt *stbuf, int32_t valid) + struct iatt *stbuf, int32_t valid, dict_t *xdata) { int32_t ret = 0; marker_local_t *local = NULL; @@ -2000,7 +2331,7 @@ marker_setattr (call_frame_t *frame, xlator_t *this, loc_t *loc, if (priv->feature_enabled == 0) goto wind; - ALLOCATE_OR_GOTO (local, marker_local_t, err); + local = mem_get0 (this->local_pool); MARKER_INIT_LOCAL (frame, local); @@ -2010,10 +2341,10 @@ marker_setattr (call_frame_t *frame, xlator_t *this, loc_t *loc, goto err; wind: STACK_WIND (frame, marker_setattr_cbk, FIRST_CHILD (this), - FIRST_CHILD (this)->fops->setattr, loc, stbuf, valid); + FIRST_CHILD (this)->fops->setattr, loc, stbuf, valid, xdata); return 0; err: - STACK_UNWIND_STRICT (setattr, frame, -1, ENOMEM, NULL, NULL); + STACK_UNWIND_STRICT (setattr, frame, -1, ENOMEM, NULL, NULL, NULL); return 0; } @@ -2021,13 +2352,13 @@ err: int32_t marker_removexattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this, - int32_t op_ret, int32_t op_errno) + int32_t op_ret, int32_t op_errno, dict_t *xdata) { marker_local_t *local = NULL; marker_conf_t *priv = NULL; if (op_ret == -1) { - gf_log (this->name, GF_LOG_ERROR, "%s occured while " + gf_log (this->name, GF_LOG_ERROR, "%s occurred while " "creating symlinks ", strerror (op_errno)); } @@ -2035,7 +2366,7 @@ marker_removexattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this, frame->local = NULL; - STACK_UNWIND_STRICT (removexattr, frame, op_ret, op_errno); + STACK_UNWIND_STRICT (removexattr, frame, op_ret, op_errno, xdata); if (op_ret == -1 || local == NULL) goto out; @@ -2052,7 +2383,7 @@ out: int32_t marker_removexattr (call_frame_t *frame, xlator_t *this, loc_t *loc, - const char *name) + const char *name, dict_t *xdata) { int32_t ret = 0; marker_local_t *local = NULL; @@ -2063,7 +2394,7 @@ marker_removexattr (call_frame_t *frame, xlator_t *this, loc_t *loc, if (priv->feature_enabled == 0) goto wind; - ALLOCATE_OR_GOTO (local, marker_local_t, err); + local = mem_get0 (this->local_pool); MARKER_INIT_LOCAL (frame, local); @@ -2073,10 +2404,10 @@ marker_removexattr (call_frame_t *frame, xlator_t *this, loc_t *loc, goto err; wind: STACK_WIND (frame, marker_removexattr_cbk, FIRST_CHILD(this), - FIRST_CHILD(this)->fops->removexattr, loc, name); + FIRST_CHILD(this)->fops->removexattr, loc, name, xdata); return 0; err: - STACK_UNWIND_STRICT (removexattr, frame, -1, ENOMEM); + STACK_UNWIND_STRICT (removexattr, frame, -1, ENOMEM, NULL); return 0; } @@ -2105,10 +2436,19 @@ marker_lookup_cbk (call_frame_t *frame, void *cookie, xlator_t *this, if (op_ret == -1 || local == NULL) goto out; + /* copy the gfid from the stat structure instead of inode, + * since if the lookup is fresh lookup, then the inode + * would have not yet linked to the inode table which happens + * in protocol/server. + */ + if (uuid_is_null (local->loc.gfid)) + uuid_copy (local->loc.gfid, buf->ia_gfid); + + priv = this->private; if (priv->feature_enabled & GF_QUOTA) { - quota_xattr_state (this, &local->loc, dict, *buf); + mq_xattr_state (this, &local->loc, dict, *buf); } out: @@ -2130,7 +2470,7 @@ marker_lookup (call_frame_t *frame, xlator_t *this, if (priv->feature_enabled == 0) goto wind; - ALLOCATE_OR_GOTO (local, marker_local_t, err); + local = mem_get0 (this->local_pool); MARKER_INIT_LOCAL (frame, local); @@ -2139,7 +2479,7 @@ marker_lookup (call_frame_t *frame, xlator_t *this, goto err; if ((priv->feature_enabled & GF_QUOTA) && xattr_req) - quota_req_xattr (this, loc, xattr_req); + mq_req_xattr (this, loc, xattr_req); wind: STACK_WIND (frame, marker_lookup_cbk, FIRST_CHILD(this), FIRST_CHILD(this)->fops->lookup, loc, xattr_req); @@ -2150,6 +2490,49 @@ err: return 0; } +int +marker_readdirp_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + int op_ret, int op_errno, gf_dirent_t *entries, + dict_t *xdata) +{ + gf_dirent_t *entry = NULL; + + if (op_ret <= 0) + goto unwind; + + list_for_each_entry (entry, &entries->list, list) { + /* TODO: fill things */ + } + +unwind: + STACK_UNWIND_STRICT (readdirp, frame, op_ret, op_errno, entries, xdata); + + return 0; +} + +int +marker_readdirp (call_frame_t *frame, xlator_t *this, fd_t *fd, size_t size, + off_t offset, dict_t *dict) +{ + marker_conf_t *priv = NULL; + + priv = this->private; + + if (priv->feature_enabled == 0) + goto wind; + + if ((priv->feature_enabled & GF_QUOTA) && dict) + mq_req_xattr (this, NULL, dict); + +wind: + STACK_WIND (frame, marker_readdirp_cbk, + FIRST_CHILD(this), FIRST_CHILD(this)->fops->readdirp, + fd, size, offset, dict); + + return 0; +} + + int32_t mem_acct_init (xlator_t *this) { @@ -2250,14 +2633,11 @@ marker_xtime_priv_cleanup (xlator_t *this) GF_VALIDATE_OR_GOTO (this->name, priv, out); - if (priv->volume_uuid != NULL) - GF_FREE (priv->volume_uuid); + GF_FREE (priv->volume_uuid); - if (priv->timestamp_file != NULL) - GF_FREE (priv->timestamp_file); + GF_FREE (priv->timestamp_file); - if (priv->marker_xattr != NULL) - GF_FREE (priv->marker_xattr); + GF_FREE (priv->marker_xattr); out: return; } @@ -2285,7 +2665,7 @@ out: int32_t reconfigure (xlator_t *this, dict_t *options) { - int32_t ret = -1; + int32_t ret = 0; data_t *data = NULL; gf_boolean_t flag = _gf_false; marker_conf_t *priv = NULL; @@ -2326,11 +2706,17 @@ reconfigure (xlator_t *this, dict_t *options) "xtime updation will fail"); } else { priv->feature_enabled |= GF_XTIME; + data = dict_get (options, "gsync-force-xtime"); + if (!data) + goto out; + ret = gf_string2boolean (data->data, &flag); + if (ret == 0 && flag) + priv->feature_enabled |= GF_XTIME_GSYNC_FORCE; } } } out: - return 0; + return ret; } @@ -2386,9 +2772,23 @@ init (xlator_t *this) goto err; priv->feature_enabled |= GF_XTIME; + data = dict_get (options, "gsync-force-xtime"); + if (!data) + goto cont; + ret = gf_string2boolean (data->data, &flag); + if (ret == 0 && flag) + priv->feature_enabled |= GF_XTIME_GSYNC_FORCE; } } + cont: + this->local_pool = mem_pool_new (marker_local_t, 128); + if (!this->local_pool) { + gf_log (this->name, GF_LOG_ERROR, + "failed to create local_t's memory pool"); + goto err; + } + return 0; err: marker_priv_cleanup (this); @@ -2410,7 +2810,7 @@ marker_forget (xlator_t *this, inode_t *inode) goto out; } - quota_forget (this, ctx->quota_ctx); + mq_forget (this, ctx->quota_ctx); GF_FREE (ctx); out: @@ -2441,7 +2841,11 @@ struct xlator_fops fops = { .setattr = marker_setattr, .fsetattr = marker_fsetattr, .removexattr = marker_removexattr, - .getxattr = marker_getxattr + .getxattr = marker_getxattr, + .readdirp = marker_readdirp, + .fallocate = marker_fallocate, + .discard = marker_discard, + .zerofill = marker_zerofill, }; struct xlator_cbks cbks = { @@ -2453,5 +2857,6 @@ struct volume_options options[] = { {.key = {"timestamp-file"}}, {.key = {"quota"}}, {.key = {"xtime"}}, + {.key = {"gsync-force-xtime"}}, {.key = {NULL}} }; diff --git a/xlators/features/marker/src/marker.h b/xlators/features/marker/src/marker.h index a5a435e3b..1a58f8cfc 100644 --- a/xlators/features/marker/src/marker.h +++ b/xlators/features/marker/src/marker.h @@ -1,21 +1,12 @@ -/*Copyright (c) 2008-2010 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/>. -*/ +/* + Copyright (c) 2008-2012 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 _MARKER_H #define _MARKER_H @@ -37,8 +28,9 @@ #define TIMESTAMP_FILE "timestamp-file" enum { - GF_QUOTA=1, - GF_XTIME=2 + GF_QUOTA = 1, + GF_XTIME = 2, + GF_XTIME_GSYNC_FORCE = 4, }; /*initialize the local variable*/ @@ -47,6 +39,8 @@ enum { _local->pid = _frame->root->pid; \ memset (&_local->loc, 0, sizeof (loc_t)); \ _local->ref = 1; \ + _local->uid = -1; \ + _local->gid = -1; \ LOCK_INIT (&_local->lock); \ _local->oplocal = NULL; \ } while (0) @@ -62,12 +56,37 @@ enum { } \ } while (0) +#define _MARKER_SET_UID_GID(dest, src) \ + do { \ + if (src->uid != -1 && \ + src->gid != -1) { \ + dest->uid = src->uid; \ + dest->gid = src->gid; \ + } \ + } while (0) + +#define MARKER_SET_UID_GID(frame, dest, src) \ + do { \ + _MARKER_SET_UID_GID (dest, src); \ + frame->root->uid = 0; \ + frame->root->gid = 0; \ + frame->cookie = (void *) _GF_UID_GID_CHANGED; \ + } while (0) + +#define MARKER_RESET_UID_GID(frame, dest, src) \ + do { \ + _MARKER_SET_UID_GID (dest, src); \ + frame->cookie = NULL; \ + } while (0) + struct marker_local{ uint32_t timebuf[2]; pid_t pid; loc_t loc; loc_t parent_loc; loc_t *next_lock_on; + uid_t uid; + gid_t gid; int32_t ref; int32_t ia_nlink; gf_lock_t lock; @@ -76,9 +95,28 @@ struct marker_local{ call_stub_t *stub; int64_t contribution; struct marker_local *oplocal; + + /* marker quota specific */ + int64_t delta; + int64_t d_off; + int64_t sum; + int64_t size; + int32_t hl_count; + int32_t dentry_child_count; + + fd_t *fd; + call_frame_t *frame; + + quota_inode_ctx_t *ctx; + inode_contribution_t *contri; + + int xflag; + dict_t *xdata; }; typedef struct marker_local marker_local_t; +#define quota_local_t marker_local_t + struct marker_inode_ctx { struct quota_inode_ctx *quota_ctx; }; diff --git a/xlators/features/marker/utils/Makefile.am b/xlators/features/marker/utils/Makefile.am deleted file mode 100644 index 84e926c00..000000000 --- a/xlators/features/marker/utils/Makefile.am +++ /dev/null @@ -1,7 +0,0 @@ -SUBDIRS = syncdaemon - -gsyncddir = $(libexecdir)/glusterfs - -gsyncd_SCRIPTS = gsyncd - -CLEANFILES = diff --git a/xlators/features/marker/utils/gsyncd.in b/xlators/features/marker/utils/gsyncd.in deleted file mode 100755 index a7af8c0b0..000000000 --- a/xlators/features/marker/utils/gsyncd.in +++ /dev/null @@ -1,55 +0,0 @@ -#!/bin/sh - -prefix="@prefix@" -exec_prefix="@exec_prefix@" -libexecdir=`eval echo "@libexecdir@"` -sbindir=`eval echo "@sbindir@"` - -gluster="$sbindir"/gluster - -# glusterd service autodetection - -config_wanted=1 -if [ "$_GLUSTERD_CALLED_" = 1 ]; then - # OK, we know glusterd called us, no need to look for further config - config_wanted=0 - # ... altough this conclusion should not inherit to our children - unset _GLUSTERD_CALLED_ -else - # look for a -c option -- if present, we are already configured. - - for a in "$@"; do - # -c found, see if it has an argument - if [ "$one_more_arg" = 1 ]; then - if echo "$a" | grep -qv ^-; then - config_wanted=0 - break - fi - one_more_arg=0 - fi - - if [ "$a" = -c ] || [ "$a" = --config-file ]; then - one_more_arg=1 - continue - fi - - if echo $a | grep -qE '^(-c.|--config-file=)'; then - config_wanted=0; - break - fi - done - -fi - -if [ $config_wanted = 1 ]; then - wd="`${gluster} system:: getwd`" - if [ $? -eq 0 ]; then - config_file="$wd/geo-replication/gsyncd.conf" - fi -fi - -if [ -z "$config_file" ]; then - exec @PYTHON@ "$libexecdir"/glusterfs/python/syncdaemon/gsyncd.py "$@" -else - exec @PYTHON@ "$libexecdir"/glusterfs/python/syncdaemon/gsyncd.py -c "$config_file" "$@" -fi diff --git a/xlators/features/marker/utils/syncdaemon/Makefile.am b/xlators/features/marker/utils/syncdaemon/Makefile.am deleted file mode 100644 index ef2dc9aea..000000000 --- a/xlators/features/marker/utils/syncdaemon/Makefile.am +++ /dev/null @@ -1,5 +0,0 @@ -syncdaemondir = $(libexecdir)/glusterfs/python/syncdaemon - -syncdaemon_PYTHON = gconf.py gsyncd.py __init__.py master.py README.md repce.py resource.py configinterface.py syncdutils.py monitor.py libcxattr.py - -CLEANFILES = diff --git a/xlators/features/marker/utils/syncdaemon/README.md b/xlators/features/marker/utils/syncdaemon/README.md deleted file mode 100644 index d45006932..000000000 --- a/xlators/features/marker/utils/syncdaemon/README.md +++ /dev/null @@ -1,81 +0,0 @@ -gsycnd, the Gluster Syncdaemon -============================== - -REQUIREMENTS ------------- - -_gsyncd_ is a program which can operate either in _master_ or in _slave_ mode. -Requirements are categorized according to this. - -* supported OS is GNU/Linux -* Python >= 2.5, or 2.4 with Ctypes (see below) (both) -* OpenSSH >= 4.0 (master) / SSH2 compliant sshd (eg. openssh) (slave) -* rsync (both) -* glusterfs with marker support (master); glusterfs (optional on slave) -* FUSE; for supported versions consult glusterfs - -INSTALLATION ------------- - -As of now, the supported way of operation is running from the source directory. - -If you use Python 2.4.x, you need to install the [Ctypes module](http://python.net/crew/theller/ctypes/). - -CONFIGURATION -------------- - -gsyncd tunables are a subset of the long command-line options; for listing them, -type - - gsyncd.py --help - -and see the long options up to "--config-file". (The leading double dash should be omitted; -interim underscores and dashes are interchangeable.) The set of options bear some resemblance -to those of glusterfs and rsync. - -The config file format matches the following syntax: - - <option1>: <value1> - <option2>: <value2> - # comment - -By default (unless specified by the option `-c`), gsyncd looks for config file at _conf/gsyncd.conf_ -in the source tree. - -USAGE ------ - -gsyncd is a utilitly for continous mirroring, ie. it mirrors master to slave incrementally. -Assume we have a gluster volume _pop_ at localhost. We try to set up the following mirrors -for it with gysncd: - -1. _/data/mirror_ -2. local gluster volume _yow_ -3. _/data/far_mirror_ at example.com -4. gluster volume _moz_ at example.com - -The respective gsyncd invocations are (demoing some syntax sugaring): - -1. - - gsyncd.py gluster://localhost:pop file:///data/mirror - - or short form - - gsyncd.py :pop /data/mirror - -2. `gsyncd :pop :yow` -3. - - gsyncd.py :pop ssh://example.com:/data/far_mirror - - or short form - - gsyncd.py :pop example.com:/data/far_mirror - -4. `gsyncd.py :pop example.com::moz` - -gsyncd has to be available on both sides; it's location on the remote side has to be specified -via the "--remote-gsyncd" option (or "remote-gsyncd" config file parameter). (This option can also be -used for setting options on the remote side, although the suggested mode of operation is to -set parameters like log file / pid file in the configuration file.) diff --git a/xlators/features/marker/utils/syncdaemon/__init__.py b/xlators/features/marker/utils/syncdaemon/__init__.py deleted file mode 100644 index e69de29bb..000000000 --- a/xlators/features/marker/utils/syncdaemon/__init__.py +++ /dev/null diff --git a/xlators/features/marker/utils/syncdaemon/configinterface.py b/xlators/features/marker/utils/syncdaemon/configinterface.py deleted file mode 100644 index a170b2236..000000000 --- a/xlators/features/marker/utils/syncdaemon/configinterface.py +++ /dev/null @@ -1,185 +0,0 @@ -try: - import ConfigParser -except ImportError: - # py 3 - import configparser as ConfigParser -import re -from string import Template - -from syncdutils import escape, unescape, norm, update_file - -SECT_ORD = '__section_order__' -SECT_META = '__meta__' -config_version = 2.0 - -re_type = type(re.compile('')) - - -class MultiDict(object): - - def __init__(self, *dd): - self.dicts = dd - - def __getitem__(self, key): - val = None - for d in self.dicts: - if d.get(key): - val = d[key] - if not val: - raise KeyError(key) - return val - - -class GConffile(object): - - def _normconfig(self): - for n, s in self.config._sections.items(): - if n.find('__') == 0: - continue - s2 = type(s)() - for k, v in s.items(): - if k.find('__') != 0: - k = norm(k) - s2[k] = v - self.config._sections[n] = s2 - - def __init__(self, path, peers, *dd): - self.peers = peers - self.path = path - self.auxdicts = dd - self.config = ConfigParser.RawConfigParser() - self.config.read(path) - self._normconfig() - - def section(self, rx=False): - peers = self.peers - if not peers: - peers = ['.', '.'] - rx = True - if rx: - st = 'peersrx' - else: - st = 'peers' - return ' '.join([st] + [escape(u) for u in peers]) - - @staticmethod - def parse_section(section): - sl = section.split() - st = sl.pop(0) - sl = [unescape(u) for u in sl] - if st == 'peersrx': - sl = [re.compile(u) for u in sl] - return sl - - def ord_sections(self): - """Return an ordered list of sections. - - Ordering happens based on the auxiliary - SECT_ORD section storing indices for each - section added through the config API. - - To not to go corrupt in case of manually - written config files, we take care to append - also those sections which are not registered - in SECT_ORD. - - Needed for python 2.{4,5} where ConfigParser - cannot yet order sections/options internally. - """ - so = {} - if self.config.has_section(SECT_ORD): - so = self.config._sections[SECT_ORD] - so2 = {} - for k, v in so.items(): - if k != '__name__': - so2[k] = int(v) - tv = 0 - if so2: - tv = max(so2.values()) + 1 - ss = [s for s in self.config.sections() if s.find('__') != 0] - for s in ss: - if s in so.keys(): - continue - so2[s] = tv - tv += 1 - def scmp(x, y): - return cmp(*(so2[s] for s in (x, y))) - ss.sort(scmp) - return ss - - def update_to(self, dct, allow_unresolved=False): - if not self.peers: - raise RuntimeError('no peers given, cannot select matching options') - def update_from_sect(sect, mud): - for k, v in self.config._sections[sect].items(): - if k == '__name__': - continue - if allow_unresolved: - dct[k] = Template(v).safe_substitute(mud) - else: - dct[k] = Template(v).substitute(mud) - for sect in self.ord_sections(): - sp = self.parse_section(sect) - if isinstance(sp[0], re_type) and len(sp) == len(self.peers): - match = True - mad = {} - for i in range(len(sp)): - m = sp[i].search(self.peers[i]) - if not m: - match = False - break - for j in range(len(m.groups())): - mad['match%d_%d' % (i+1, j+1)] = m.groups()[j] - if match: - update_from_sect(sect, MultiDict(dct, mad, *self.auxdicts)) - if self.config.has_section(self.section()): - update_from_sect(self.section(), MultiDict(dct, mad, *self.auxdicts)) - - def get(self, opt=None): - d = {} - self.update_to(d, allow_unresolved = True) - if opt: - opt = norm(opt) - v = d.get(opt) - if v: - print v - else: - for k, v in d.iteritems(): - if k == '__name__': - continue - print("%s: %s" % (k, v)) - - def write(self, trfn, opt, *a, **kw): - def mergeconf(f): - self.config = ConfigParser.RawConfigParser() - self.config.readfp(f) - self._normconfig() - if not self.config.has_section(SECT_META): - self.config.add_section(SECT_META) - self.config.set(SECT_META, 'version', config_version) - return trfn(norm(opt), *a, **kw) - def updateconf(f): - self.config.write(f) - update_file(self.path, updateconf, mergeconf) - - def _set(self, opt, val, rx=False): - sect = self.section(rx) - if not self.config.has_section(sect): - self.config.add_section(sect) - # regarding SECT_ORD, cf. ord_sections - if not self.config.has_section(SECT_ORD): - self.config.add_section(SECT_ORD) - self.config.set(SECT_ORD, sect, len(self.config._sections[SECT_ORD])) - self.config.set(sect, opt, val) - return True - - def set(self, opt, *a, **kw): - self.write(self._set, opt, *a, **kw) - - def _delete(self, opt, rx=False): - sect = self.section(rx) - if self.config.has_section(sect): - return self.config.remove_option(sect, opt) - - def delete(self, opt, *a, **kw): - self.write(self._delete, opt, *a, **kw) diff --git a/xlators/features/marker/utils/syncdaemon/gconf.py b/xlators/features/marker/utils/syncdaemon/gconf.py deleted file mode 100644 index 24165b619..000000000 --- a/xlators/features/marker/utils/syncdaemon/gconf.py +++ /dev/null @@ -1,15 +0,0 @@ -import os - -class GConf(object): - ssh_ctl_dir = None - ssh_ctl_args = None - cpid = None - pid_file_owned = False - permanent_handles = [] - - @classmethod - def setup_ssh_ctl(cls, ctld): - cls.ssh_ctl_dir = ctld - cls.ssh_ctl_args = ["-oControlMaster=auto", "-S", os.path.join(ctld, "gsycnd-ssh-%r@%h:%p")] - -gconf = GConf() diff --git a/xlators/features/marker/utils/syncdaemon/gsyncd.py b/xlators/features/marker/utils/syncdaemon/gsyncd.py deleted file mode 100644 index a502c2009..000000000 --- a/xlators/features/marker/utils/syncdaemon/gsyncd.py +++ /dev/null @@ -1,305 +0,0 @@ -#!/usr/bin/env python - -import os -import os.path -import sys -import time -import logging -import signal -import select -import optparse -import fcntl -from optparse import OptionParser, SUPPRESS_HELP -from logging import Logger -from errno import EEXIST, ENOENT - -from gconf import gconf -from syncdutils import FreeObject, norm, grabpidfile, finalize, log_raise_exception -from configinterface import GConffile -import resource -from monitor import monitor - -class GLogger(Logger): - - def makeRecord(self, name, level, *a): - rv = Logger.makeRecord(self, name, level, *a) - rv.nsecs = (rv.created - int(rv.created)) * 1000000 - fr = sys._getframe(4) - callee = fr.f_locals.get('self') - if callee: - ctx = str(type(callee)).split("'")[1].split('.')[-1] - else: - ctx = '<top>' - if not hasattr(rv, 'funcName'): - rv.funcName = fr.f_code.co_name - rv.lvlnam = logging.getLevelName(level)[0] - rv.ctx = ctx - return rv - - @classmethod - def setup(cls, **kw): - lbl = kw.get('label', "") - if lbl: - lbl = '(' + lbl + ')' - lprm = {'datefmt': "%Y-%m-%d %H:%M:%S", - 'format': "[%(asctime)s.%(nsecs)d] %(lvlnam)s [%(module)s" + lbl + ":%(lineno)s:%(funcName)s] %(ctx)s: %(message)s"} - lprm.update(kw) - lvl = kw.get('level', logging.INFO) - lprm['level'] = lvl - logging.root = cls("root", lvl) - logging.setLoggerClass(cls) - logging.getLogger().handlers = [] - logging.basicConfig(**lprm) - - -def startup(**kw): - if getattr(gconf, 'pid_file', None) and kw.get('go_daemon') != 'postconn': - if not grabpidfile(): - sys.stderr.write("pidfile is taken, exiting.\n") - sys.exit(2) - gconf.pid_file_owned = True - - if kw.get('go_daemon') == 'should': - x, y = os.pipe() - gconf.cpid = os.fork() - if gconf.cpid: - os.close(x) - sys.exit() - os.close(y) - os.setsid() - dn = os.open(os.devnull, os.O_RDWR) - for f in (sys.stdin, sys.stdout, sys.stderr): - os.dup2(dn, f.fileno()) - if getattr(gconf, 'pid_file', None): - if not grabpidfile(gconf.pid_file + '.tmp'): - raise RuntimeError("cannot grap temporary pidfile") - os.rename(gconf.pid_file + '.tmp', gconf.pid_file) - # wait for parent to terminate - # so we can start up with - # no messing from the dirty - # ol' bustard - select.select((x,), (), ()) - os.close(x) - - lkw = {} - if gconf.log_level: - lkw['level'] = gconf.log_level - if kw.get('log_file'): - if kw['log_file'] in ('-', '/dev/stderr'): - lkw['stream'] = sys.stderr - elif kw['log_file'] == '/dev/stdout': - lkw['stream'] = sys.stdout - else: - lkw['filename'] = kw['log_file'] - GLogger.setup(label=kw.get('label'), **lkw) - -def main(): - signal.signal(signal.SIGTERM, lambda *a: finalize(*a, **{'exval': 1})) - GLogger.setup() - excont = FreeObject(exval = 0) - try: - try: - main_i() - except: - log_raise_exception(excont) - finally: - finalize(exval = excont.exval) - -def main_i(): - rconf = {'go_daemon': 'should'} - - def store_abs(opt, optstr, val, parser): - if val and val != '-': - val = os.path.abspath(val) - setattr(parser.values, opt.dest, val) - def store_local(opt, optstr, val, parser): - rconf[opt.dest] = val - def store_local_curry(val): - return lambda o, oo, vx, p: store_local(o, oo, val, p) - def store_local_obj(op, dmake): - return lambda o, oo, vx, p: store_local(o, oo, FreeObject(op=op, **dmake(vx)), p) - - op = OptionParser(usage="%prog [options...] <master> <slave>", version="%prog 0.0.1") - op.add_option('--gluster-command', metavar='CMD', default='glusterfs') - op.add_option('--gluster-log-file', metavar='LOGF', default=os.devnull, type=str, action='callback', callback=store_abs) - op.add_option('--gluster-log-level', metavar='LVL') - op.add_option('-p', '--pid-file', metavar='PIDF', type=str, action='callback', callback=store_abs) - op.add_option('-l', '--log-file', metavar='LOGF', type=str, action='callback', callback=store_abs) - op.add_option('--state-file', metavar='STATF', type=str, action='callback', callback=store_abs) - op.add_option('-L', '--log-level', metavar='LVL') - op.add_option('-r', '--remote-gsyncd', metavar='CMD', default=os.path.abspath(sys.argv[0])) - op.add_option('--volume-id', metavar='UUID') - op.add_option('--session-owner', metavar='ID') - op.add_option('-s', '--ssh-command', metavar='CMD', default='ssh') - op.add_option('--rsync-command', metavar='CMD', default='rsync') - op.add_option('--rsync-extra', metavar='ARGS', default='-sS', help=SUPPRESS_HELP) - op.add_option('--timeout', metavar='SEC', type=int, default=120) - op.add_option('--sync-jobs', metavar='N', type=int, default=3) - op.add_option('--turns', metavar='N', type=int, default=0, help=SUPPRESS_HELP) - - op.add_option('-c', '--config-file', metavar='CONF', type=str, action='callback', callback=store_local) - # duh. need to specify dest or value will be mapped to None :S - op.add_option('--monitor', dest='monitor', action='callback', callback=store_local_curry(True)) - op.add_option('--feedback-fd', dest='feedback_fd', type=int, help=SUPPRESS_HELP, action='callback', callback=store_local) - op.add_option('--listen', dest='listen', help=SUPPRESS_HELP, action='callback', callback=store_local_curry(True)) - op.add_option('-N', '--no-daemon', dest="go_daemon", action='callback', callback=store_local_curry('dont')) - op.add_option('--debug', dest="go_daemon", action='callback', callback=lambda *a: (store_local_curry('dont')(*a), - setattr(a[-1].values, 'log_file', '-'), - setattr(a[-1].values, 'log_level', 'DEBUG'))), - - for a in ('check', 'get'): - op.add_option('--config-' + a, metavar='OPT', type=str, dest='config', action='callback', - callback=store_local_obj(a, lambda vx: {'opt': vx})) - op.add_option('--config-get-all', dest='config', action='callback', callback=store_local_obj('get', lambda vx: {'opt': None})) - for m in ('', '-rx'): - # call this code 'Pythonic' eh? - # have to define a one-shot local function to be able to inject (a value depending on the) - # iteration variable into the inner lambda - def conf_mod_opt_regex_variant(rx): - op.add_option('--config-set' + m, metavar='OPT VAL', type=str, nargs=2, dest='config', action='callback', - callback=store_local_obj('set', lambda vx: {'opt': vx[0], 'val': vx[1], 'rx': rx})) - op.add_option('--config-del' + m, metavar='OPT', type=str, dest='config', action='callback', - callback=store_local_obj('del', lambda vx: {'opt': vx, 'rx': rx})) - conf_mod_opt_regex_variant(not not m) - - op.add_option('--normalize-url', dest='url_print', action='callback', callback=store_local_curry('normal')) - op.add_option('--canonicalize-url', dest='url_print', action='callback', callback=store_local_curry('canon')) - op.add_option('--canonicalize-escape-url', dest='url_print', action='callback', callback=store_local_curry('canon_esc')) - - tunables = [ norm(o.get_opt_string()[2:]) for o in op.option_list if o.callback in (store_abs, None) and o.get_opt_string() not in ('--version', '--help') ] - - # precedence for sources of values: 1) commandline, 2) cfg file, 3) defaults - # -- for this to work out we need to tell apart defaults from explicitly set - # options... so churn out the defaults here and call the parser with virgin - # values container. - defaults = op.get_default_values() - opts, args = op.parse_args(values=optparse.Values()) - confdata = rconf.get('config') - if not (len(args) == 2 or \ - (len(args) == 1 and rconf.get('listen')) or \ - (len(args) <= 2 and confdata) or \ - rconf.get('url_print')): - sys.stderr.write("error: incorrect number of arguments\n\n") - sys.stderr.write(op.get_usage() + "\n") - sys.exit(1) - - if getattr(confdata, 'rx', None): - # peers are regexen, don't try to parse them - canon_peers = args - namedict = {} - else: - rscs = [resource.parse_url(u) for u in args] - dc = rconf.get('url_print') - if dc: - for r in rscs: - print(r.get_url(**{'normal': {}, - 'canon': {'canonical': True}, - 'canon_esc': {'canonical': True, 'escaped': True}}[dc])) - return - local = remote = None - if rscs: - local = rscs[0] - if len(rscs) > 1: - remote = rscs[1] - if not local.can_connect_to(remote): - raise RuntimeError("%s cannot work with %s" % (local.path, remote and remote.path)) - pa = ([], [], []) - urlprms = ({}, {'canonical': True}, {'canonical': True, 'escaped': True}) - for x in rscs: - for i in range(len(pa)): - pa[i].append(x.get_url(**urlprms[i])) - peers, canon_peers, canon_esc_peers = pa - # creating the namedict, a dict representing various ways of referring to / repreenting - # peers to be fillable in config templates - mods = (lambda x: x, lambda x: x[0].upper() + x[1:], lambda x: 'e' + x[0].upper() + x[1:]) - if remote: - rmap = { local: ('local', 'master'), remote: ('remote', 'slave') } - else: - rmap = { local: ('local', 'slave') } - namedict = {} - for i in range(len(rscs)): - x = rscs[i] - for name in rmap[x]: - for j in range(3): - namedict[mods[j](name)] = pa[j][i] - if x.scheme == 'gluster': - namedict[name + 'vol'] = x.volume - if not 'config_file' in rconf: - rconf['config_file'] = os.path.join(os.path.dirname(sys.argv[0]), "conf/gsyncd.conf") - gcnf = GConffile(rconf['config_file'], canon_peers, defaults.__dict__, opts.__dict__, namedict) - - if confdata: - opt_ok = norm(confdata.opt) in tunables + [None] - if confdata.op == 'check': - if opt_ok: - sys.exit(0) - else: - sys.exit(1) - elif not opt_ok: - raise RuntimeError("not a valid option: " + confdata.opt) - if confdata.op == 'get': - gcnf.get(confdata.opt) - elif confdata.op == 'set': - gcnf.set(confdata.opt, confdata.val, confdata.rx) - elif confdata.op == 'del': - gcnf.delete(confdata.opt, confdata.rx) - return - - gconf.__dict__.update(defaults.__dict__) - gcnf.update_to(gconf.__dict__) - gconf.__dict__.update(opts.__dict__) - gconf.configinterface = gcnf - - ffd = rconf.get('feedback_fd') - if ffd: - fcntl.fcntl(ffd, fcntl.F_SETFD, fcntl.FD_CLOEXEC) - - #normalize loglevel - lvl0 = gconf.log_level - if isinstance(lvl0, str): - lvl1 = lvl0.upper() - lvl2 = logging.getLevelName(lvl1) - # I have _never_ _ever_ seen such an utterly braindead - # error condition - if lvl2 == "Level " + lvl1: - raise RuntimeError('cannot recognize log level "%s"' % lvl0) - gconf.log_level = lvl2 - - go_daemon = rconf['go_daemon'] - be_monitor = rconf.get('monitor') - - if not be_monitor and isinstance(remote, resource.SSH) and \ - go_daemon == 'should': - go_daemon = 'postconn' - log_file = None - else: - log_file = gconf.log_file - if be_monitor: - label = 'monitor' - elif remote: - #master - label = '' - else: - label = 'slave' - startup(go_daemon=go_daemon, log_file=log_file, label=label) - - if be_monitor: - return monitor() - - logging.info("syncing: %s" % " -> ".join(peers)) - if remote: - go_daemon = remote.connect_remote(go_daemon=go_daemon) - if go_daemon: - startup(go_daemon=go_daemon, log_file=gconf.log_file) - # complete remote connection in child - remote.connect_remote(go_daemon='done') - local.connect() - if ffd: - os.close(ffd) - local.service_loop(*[r for r in [remote] if r]) - - logging.info("exiting.") - - -if __name__ == "__main__": - main() diff --git a/xlators/features/marker/utils/syncdaemon/libcxattr.py b/xlators/features/marker/utils/syncdaemon/libcxattr.py deleted file mode 100644 index fdc016c47..000000000 --- a/xlators/features/marker/utils/syncdaemon/libcxattr.py +++ /dev/null @@ -1,62 +0,0 @@ -import os -from ctypes import * -from ctypes.util import find_library - -class Xattr(object): - - libc = CDLL(find_library("libc")) - - @classmethod - def geterrno(cls): - return c_int.in_dll(cls.libc, 'errno').value - - @classmethod - def raise_oserr(cls): - errn = cls.geterrno() - raise OSError(errn, os.strerror(errn)) - - @classmethod - def _query_xattr(cls, path, siz, syscall, *a): - if siz: - buf = create_string_buffer('\0' * siz) - else: - buf = None - ret = getattr(cls.libc, syscall)(*((path,) + a + (buf, siz))) - if ret == -1: - cls.raise_oserr() - if siz: - return buf.raw[:ret] - else: - return ret - - @classmethod - def lgetxattr(cls, path, attr, siz=0): - return cls._query_xattr( path, siz, 'lgetxattr', attr) - - @classmethod - def llistxattr(cls, path, siz=0): - ret = cls._query_xattr(path, siz, 'llistxattr') - if isinstance(ret, str): - ret = ret.split('\0') - return ret - - @classmethod - def lsetxattr(cls, path, attr, val): - ret = cls.libc.lsetxattr(path, attr, val, len(val), 0) - if ret == -1: - cls.raise_oserr() - - @classmethod - def lremovexattr(cls, path, attr): - ret = cls.libc.lremovexattr(path, attr) - if ret == -1: - cls.raise_oserr() - - @classmethod - def llistxattr_buf(cls, path): - size = cls.llistxattr(path) - if size == -1: - cls.raise_oserr() - if size == 0: - return [] - return cls.llistxattr(path, size) diff --git a/xlators/features/marker/utils/syncdaemon/master.py b/xlators/features/marker/utils/syncdaemon/master.py deleted file mode 100644 index 35dc4ee06..000000000 --- a/xlators/features/marker/utils/syncdaemon/master.py +++ /dev/null @@ -1,366 +0,0 @@ -import os -import sys -import time -import stat -import signal -import logging -import errno -from errno import ENOENT, ENODATA -from threading import currentThread, Condition, Lock - -from gconf import gconf -from syncdutils import FreeObject, Thread - -URXTIME = (-1, 0) - -class GMaster(object): - - KFGN = 0 - KNAT = 1 - - def get_sys_volinfo(self): - fgn_vis, nat_vi = self.master.server.foreign_volume_infos(), \ - self.master.server.native_volume_info() - fgn_vi = None - if fgn_vis: - if len(fgn_vis) > 1: - raise RuntimeError("cannot work with multiple foreign masters") - fgn_vi = fgn_vis[0] - return fgn_vi, nat_vi - - @property - def uuid(self): - if self.volinfo: - return self.volinfo['uuid'] - - @property - def volmark(self): - if self.volinfo: - return self.volinfo['volume_mark'] - - @property - def inter_master(self): - return self.volinfo_state[self.KFGN] and True or False - - def xtime(self, path, *a, **opts): - if a: - rsc = a[0] - else: - rsc = self.master - if not 'create' in opts: - opts['create'] = (rsc == self.master and not self.inter_master) - if not 'default_xtime' in opts: - if rsc == self.master and self.inter_master: - opts['default_xtime'] = ENODATA - else: - opts['default_xtime'] = URXTIME - xt = rsc.server.xtime(path, self.uuid) - if isinstance(xt, int) and xt != ENODATA: - return xt - invalid_xtime = (xt == ENODATA or xt < self.volmark) - if invalid_xtime and opts['create']: - t = time.time() - sec = int(t) - nsec = int((t - sec) * 1000000) - xt = (sec, nsec) - rsc.server.set_xtime(path, self.uuid, xt) - if invalid_xtime: - xt = opts['default_xtime'] - return xt - - def __init__(self, master, slave): - self.master = master - self.slave = slave - self.jobtab = {} - self.syncer = Syncer(slave) - self.total_turns = int(gconf.turns) - self.turns = 0 - self.start = None - self.change_seen = None - # the authorative (foreign, native) volinfo pair - # which lets us deduce what to do when we refetch - # the volinfos from system - uuid_preset = getattr(gconf, 'volume_id', None) - self.volinfo_state = (uuid_preset and {'uuid': uuid_preset}, None) - # the actual volinfo we make use of - self.volinfo = None - self.terminate = False - - def crawl_loop(self): - timo = int(gconf.timeout or 0) - if timo > 0: - def keep_alive(): - while True: - gap = timo * 0.5 - # first grab a reference as self.volinfo - # can be changed in main thread - vi = self.volinfo - if vi: - # then have a private copy which we can mod - vi = vi.copy() - vi['timeout'] = int(time.time()) + timo - else: - # send keep-alives more frequently to - # avoid a delay in announcing our volume info - # to slave if it becomes established in the - # meantime - gap = min(10, gap) - self.slave.server.keep_alive(vi) - time.sleep(gap) - t = Thread(target=keep_alive) - t.start() - while not self.terminate: - self.crawl() - - def add_job(self, path, label, job, *a, **kw): - if self.jobtab.get(path) == None: - self.jobtab[path] = [] - self.jobtab[path].append((label, a, lambda : job(*a, **kw))) - - def add_failjob(self, path, label): - logging.debug('salvaged: ' + label) - self.add_job(path, label, lambda: False) - - def wait(self, path, *args): - jobs = self.jobtab.pop(path, []) - succeed = True - for j in jobs: - ret = j[-1]() - if not ret: - succeed = False - if succeed: - self.sendmark(path, *args) - return succeed - - def sendmark(self, path, mark, adct=None): - if adct: - self.slave.server.setattr(path, adct) - self.slave.server.set_xtime(path, self.uuid, mark) - - @staticmethod - def volinfo_state_machine(volinfo_state, volinfo_sys): - # store the value below "boxed" to emulate proper closures - # (variables of the enclosing scope are available inner functions - # provided they are no reassigned; mutation is OK). - param = FreeObject(relax_mismatch = False, state_change = None, index=-1) - def select_vi(vi0, vi): - param.index += 1 - if vi and (not vi0 or vi0['uuid'] == vi['uuid']): - if not vi0 and not param.relax_mismatch: - param.state_change = param.index - # valid new value found; for the rest, we are graceful about - # uuid mismatch - param.relax_mismatch = True - return vi - if vi0 and vi and vi0['uuid'] != vi['uuid'] and not param.relax_mismatch: - # uuid mismatch for master candidate, bail out - raise RuntimeError("aborting on uuid change from %s to %s" % \ - (vi0['uuid'], vi['uuid'])) - # fall back to old - return vi0 - newstate = tuple(select_vi(*vip) for vip in zip(volinfo_state, volinfo_sys)) - srep = lambda vi: vi and vi['uuid'][0:8] - logging.debug('(%s, %s) << (%s, %s) -> (%s, %s)' % \ - tuple(srep(vi) for vi in volinfo_state + volinfo_sys + newstate)) - return newstate, param.state_change - - def crawl(self, path='.', xtl=None): - if path == '.': - if self.start: - logging.info("... done, took %.6f seconds" % (time.time() - self.start)) - time.sleep(1) - self.start = time.time() - volinfo_sys = self.get_sys_volinfo() - self.volinfo_state, state_change = self.volinfo_state_machine(self.volinfo_state, - volinfo_sys) - if self.inter_master: - self.volinfo = volinfo_sys[self.KFGN] - else: - self.volinfo = volinfo_sys[self.KNAT] - if state_change == self.KFGN or (state_change == self.KNAT and not self.inter_master): - logging.info('new master is %s', self.uuid) - if state_change == self.KFGN: - gconf.configinterface.set('volume_id', self.uuid) - if self.volinfo: - if self.volinfo['retval']: - raise RuntimeError ("master is corrupt") - logging.info("%s master with volume id %s ..." % \ - (self.inter_master and "intermediate" or "primary", self.uuid)) - else: - if self.inter_master: - logging.info("waiting for being synced from %s ..." % \ - self.volinfo_state[self.KFGN]['uuid']) - else: - logging.info("waiting for volume info ...") - return - logging.debug("entering " + path) - if not xtl: - xtl = self.xtime(path) - if isinstance(xtl, int): - self.add_failjob(path, 'no-local-node') - return - xtr0 = self.xtime(path, self.slave) - if isinstance(xtr0, int): - if xtr0 != ENOENT: - self.slave.server.purge(path) - try: - self.slave.server.mkdir(path) - except OSError: - self.add_failjob(path, 'no-remote-node') - return - xtr = URXTIME - else: - xtr = xtr0 - if xtr > xtl: - raise RuntimeError("timestamp corruption for " + path) - if xtl == xtr: - if path == '.' and self.total_turns and self.change_seen: - self.turns += 1 - self.change_seen = False - logging.info("finished turn #%s/%s" % (self.turns, self.total_turns)) - if self.turns == self.total_turns: - logging.info("reached turn limit") - self.terminate = True - return - if path == '.': - self.change_seen = True - try: - dem = self.master.server.entries(path) - except OSError: - self.add_failjob(path, 'local-entries-fail') - return - try: - des = self.slave.server.entries(path) - except OSError: - self.slave.server.purge(path) - try: - self.slave.server.mkdir(path) - des = self.slave.server.entries(path) - except OSError: - self.add_failjob(path, 'remote-entries-fail') - return - dd = set(des) - set(dem) - if dd: - self.slave.server.purge(path, dd) - chld = [] - for e in dem: - e = os.path.join(path, e) - xte = self.xtime(e) - if isinstance(xte, int): - logging.warn("irregular xtime for %s: %s" % (e, errno.errorcode[xte])) - elif xte > xtr: - chld.append((e, xte)) - def indulgently(e, fnc, blame=None): - if not blame: - blame = path - try: - return fnc(e) - except (IOError, OSError): - ex = sys.exc_info()[1] - if ex.errno == ENOENT: - logging.warn("salvaged ENOENT for" + e) - self.add_failjob(blame, 'by-indulgently') - return False - else: - raise - for e, xte in chld: - st = indulgently(e, lambda e: os.lstat(e)) - if st == False: - continue - mo = st.st_mode - adct = {'own': (st.st_uid, st.st_gid)} - if stat.S_ISLNK(mo): - if indulgently(e, lambda e: self.slave.server.symlink(os.readlink(e), e)) == False: - continue - self.sendmark(e, xte, adct) - elif stat.S_ISREG(mo): - logging.debug("syncing %s ..." % e) - pb = self.syncer.add(e) - def regjob(e, xte, pb): - if pb.wait(): - logging.debug("synced " + e) - self.sendmark(e, xte) - return True - else: - logging.error("failed to sync " + e) - self.add_job(path, 'reg', regjob, e, xte, pb) - elif stat.S_ISDIR(mo): - adct['mode'] = mo - if indulgently(e, lambda e: (self.add_job(path, 'cwait', self.wait, e, xte, adct), - self.crawl(e, xte), - True)[-1], blame=e) == False: - continue - else: - # ignore fifos, sockets and special files - pass - if path == '.': - self.wait(path, xtl) - -class BoxClosedErr(Exception): - pass - -class PostBox(list): - - def __init__(self, *a): - list.__init__(self, *a) - self.lever = Condition() - self.open = True - self.done = False - - def wait(self): - self.lever.acquire() - if not self.done: - self.lever.wait() - self.lever.release() - return self.result - - def wakeup(self, data): - self.result = data - self.lever.acquire() - self.done = True - self.lever.notifyAll() - self.lever.release() - - def append(self, e): - self.lever.acquire() - if not self.open: - raise BoxClosedErr - list.append(self, e) - self.lever.release() - - def close(self): - self.lever.acquire() - self.open = False - self.lever.release() - -class Syncer(object): - - def __init__(self, slave): - self.slave = slave - self.lock = Lock() - self.pb = PostBox() - for i in range(int(gconf.sync_jobs)): - t = Thread(target=self.syncjob) - t.start() - - def syncjob(self): - while True: - pb = None - while True: - self.lock.acquire() - if self.pb: - pb, self.pb = self.pb, PostBox() - self.lock.release() - if pb: - break - time.sleep(0.5) - pb.close() - pb.wakeup(self.slave.rsync(pb)) - - def add(self, e): - while True: - try: - self.pb.append(e) - return self.pb - except BoxClosedErr: - pass diff --git a/xlators/features/marker/utils/syncdaemon/monitor.py b/xlators/features/marker/utils/syncdaemon/monitor.py deleted file mode 100644 index 365e91435..000000000 --- a/xlators/features/marker/utils/syncdaemon/monitor.py +++ /dev/null @@ -1,80 +0,0 @@ -import os -import sys -import time -import logging -import select -from signal import SIGKILL -from gconf import gconf -from syncdutils import update_file - -class Monitor(object): - - def __init__(self): - self.state = None - - def set_state(self, state): - if state == self.state: - return - self.state = state - logging.info('new state: %s' % state) - if getattr(gconf, 'state_file', None): - update_file(gconf.state_file, lambda f: f.write(state + '\n')) - - def monitor(self): - argv = sys.argv[:] - for o in ('-N', '--no-daemon', '--monitor'): - while o in argv: - argv.remove(o) - argv.extend(('-N', '-p', '')) - argv.insert(0, os.path.basename(sys.executable)) - - self.set_state('starting...') - ret = 0 - def nwait(p, o=0): - p2, r = os.waitpid(p, o) - if not p2: - return - if os.WIFEXITED(r): - return os.WEXITSTATUS(r) - return 1 - conn_timeout = 60 - while ret in (0, 1): - logging.info('-' * conn_timeout) - logging.info('starting gsyncd worker') - pr, pw = os.pipe() - cpid = os.fork() - if cpid == 0: - os.close(pr) - os.execv(sys.executable, argv + ['--feedback-fd', str(pw)]) - os.close(pw) - t0 = time.time() - so = select.select((pr,), (), (), conn_timeout)[0] - os.close(pr) - if so: - ret = nwait(cpid, os.WNOHANG) - if ret != None: - logging.debug("worker died before establishing connection") - else: - logging.debug("worker seems to be connected (?? racy check)") - while time.time() < t0 + conn_timeout: - ret = nwait(cpid, os.WNOHANG) - if ret != None: - logging.debug("worker died in startup phase") - break - time.sleep(1) - else: - logging.debug("worker not confirmed in %d sec, aborting it" % \ - conn_timeout) - os.kill(cpid, SIGKILL) - ret = nwait(cpid) - if ret == None: - self.set_state('OK') - ret = nwait(cpid) - elif ret in (0, 1): - self.set_state('faulty') - time.sleep(10) - self.set_state('inconsistent') - return ret - -def monitor(): - return Monitor().monitor() diff --git a/xlators/features/marker/utils/syncdaemon/repce.py b/xlators/features/marker/utils/syncdaemon/repce.py deleted file mode 100644 index 47691301e..000000000 --- a/xlators/features/marker/utils/syncdaemon/repce.py +++ /dev/null @@ -1,162 +0,0 @@ -import os -import sys -import select -import time -import logging -from threading import Condition -try: - import thread -except ImportError: - # py 3 - import _thread as thread -try: - from Queue import Queue -except ImportError: - # py 3 - from queue import Queue -try: - import cPickle as pickle -except ImportError: - # py 3 - import pickle - -from syncdutils import Thread - -pickle_proto = -1 -repce_version = 1.0 - -def ioparse(i, o): - if isinstance(i, int): - i = os.fdopen(i) - # rely on duck typing for recognizing - # streams as that works uniformly - # in py2 and py3 - if hasattr(o, 'fileno'): - o = o.fileno() - return (i, o) - -def send(out, *args): - os.write(out, pickle.dumps(args, pickle_proto)) - -def recv(inf): - return pickle.load(inf) - - -class RepceServer(object): - - def __init__(self, obj, i, o, wnum=6): - self.obj = obj - self.inf, self.out = ioparse(i, o) - self.wnum = wnum - self.q = Queue() - - def service_loop(self): - for i in range(self.wnum): - t = Thread(target=self.worker) - t.start() - try: - while True: - self.q.put(recv(self.inf)) - except EOFError: - logging.info("terminating on reaching EOF.") - - def worker(self): - while True: - in_data = self.q.get(True) - rid = in_data[0] - rmeth = in_data[1] - exc = False - if rmeth == '__repce_version__': - res = repce_version - else: - try: - res = getattr(self.obj, rmeth)(*in_data[2:]) - except: - res = sys.exc_info()[1] - exc = True - logging.exception("call failed: ") - send(self.out, rid, exc, res) - - -class RepceJob(object): - - def __init__(self, cbk): - self.rid = (os.getpid(), thread.get_ident(), time.time()) - self.cbk = cbk - self.lever = Condition() - self.done = False - - def __repr__(self): - return ':'.join([str(x) for x in self.rid]) - - def wait(self): - self.lever.acquire() - if not self.done: - self.lever.wait() - self.lever.release() - return self.result - - def wakeup(self, data): - self.result = data - self.lever.acquire() - self.done = True - self.lever.notify() - self.lever.release() - - -class RepceClient(object): - - def __init__(self, i, o): - self.inf, self.out = ioparse(i, o) - self.jtab = {} - t = Thread(target = self.listen) - t.start() - - def listen(self): - while True: - select.select((self.inf,), (), ()) - rid, exc, res = recv(self.inf) - rjob = self.jtab.pop(rid) - if rjob.cbk: - rjob.cbk(rjob, [exc, res]) - - def push(self, meth, *args, **kw): - cbk = kw.get('cbk') - if not cbk: - def cbk(rj, res): - if res[0]: - raise res[1] - rjob = RepceJob(cbk) - self.jtab[rjob.rid] = rjob - logging.debug("call %s %s%s ..." % (repr(rjob), meth, repr(args))) - send(self.out, rjob.rid, meth, *args) - return rjob - - def __call__(self, meth, *args): - rjob = self.push(meth, *args, **{'cbk': lambda rj, res: rj.wakeup(res)}) - exc, res = rjob.wait() - if exc: - logging.error('call %s (%s) failed on peer with %s' % (repr(rjob), meth, str(type(res).__name__))) - raise res - logging.debug("call %s %s -> %s" % (repr(rjob), meth, repr(res))) - return res - - class mprx(object): - - def __init__(self, ins, meth): - self.ins = ins - self.meth = meth - - def __call__(self, *a): - return self.ins(self.meth, *a) - - def __getattr__(self, meth): - return self.mprx(self, meth) - - def __version__(self): - d = {'proto': self('__repce_version__')} - try: - d['object'] = self('version') - except AttributeError: - pass - return d diff --git a/xlators/features/marker/utils/syncdaemon/resource.py b/xlators/features/marker/utils/syncdaemon/resource.py deleted file mode 100644 index 1e1364c26..000000000 --- a/xlators/features/marker/utils/syncdaemon/resource.py +++ /dev/null @@ -1,466 +0,0 @@ -import re -import os -import sys -import pwd -import stat -import time -import errno -import struct -import select -import socket -import logging -import tempfile -from errno import EEXIST, ENOENT, ENODATA, ENOTDIR, ELOOP, EISDIR - -from gconf import gconf -import repce -from repce import RepceServer, RepceClient -from master import GMaster -import syncdutils - -UrlRX = re.compile('\A(\w+)://(.*)') -HostRX = re.compile('[a-z\d](?:[a-z\d.-]*[a-z\d])?', re.I) -UserRX = re.compile("[\w!\#$%&'*+-\/=?^_`{|}~]+") - -def sup(x, *a, **kw): - return getattr(super(type(x), x), sys._getframe(1).f_code.co_name)(*a, **kw) - -def desugar(ustr): - m = re.match('([^:]*):(.*)', ustr) - if m: - if not m.groups()[0]: - return "gluster://localhost" + ustr - elif '@' in m.groups()[0] or re.search('[:/]', m.groups()[1]): - return "ssh://" + ustr - else: - return "gluster://" + ustr - else: - if ustr[0] != '/': - raise RuntimeError("cannot resolve sugared url '%s'" % ustr) - ap = os.path.normpath(ustr) - if ap.startswith('//'): - ap = ap[1:] - return "file://" + ap - -def parse_url(ustr): - m = UrlRX.match(ustr) - if not m: - ustr = desugar(ustr) - m = UrlRX.match(ustr) - if not m: - raise RuntimeError("malformed url") - sch, path = m.groups() - this = sys.modules[__name__] - if not hasattr(this, sch.upper()): - raise RuntimeError("unknown url scheme " + sch) - return getattr(this, sch.upper())(path) - - -class _MetaXattr(object): - - # load Xattr stuff on-demand - - def __getattr__(self, meth): - from libcxattr import Xattr as LXattr - xmeth = [ m for m in dir(LXattr) if m[0] != '_' ] - if not meth in xmeth: - return - for m in xmeth: - setattr(self, m, getattr(LXattr, m)) - return getattr(self, meth) - -Xattr = _MetaXattr() - - -class Server(object): - - GX_NSPACE = "trusted.glusterfs" - NTV_FMTSTR = "!" + "B"*19 + "II" - FRGN_XTRA_FMT = "I" - FRGN_FMTSTR = NTV_FMTSTR + FRGN_XTRA_FMT - - @staticmethod - def entries(path): - # prevent symlinks being followed - if not stat.S_ISDIR(os.lstat(path).st_mode): - raise OSError(ENOTDIR, os.strerror(ENOTDIR)) - return os.listdir(path) - - @classmethod - def purge(cls, path, entries=None): - me_also = entries == None - if not entries: - try: - # if it's a symlink, prevent - # following it - try: - os.unlink(path) - return - except OSError: - ex = sys.exc_info()[1] - if ex.errno == EISDIR: - entries = os.listdir(path) - else: - raise - except OSError: - ex = sys.exc_info()[1] - if ex.errno in (ENOTDIR, ENOENT, ELOOP): - try: - os.unlink(path) - return - except OSError: - ex = sys.exc_info()[1] - if ex.errno == ENOENT: - return - raise - else: - raise - for e in entries: - cls.purge(os.path.join(path, e)) - if me_also: - os.rmdir(path) - - @classmethod - def _create(cls, path, ctor): - try: - ctor(path) - except OSError: - ex = sys.exc_info()[1] - if ex.errno == EEXIST: - cls.purge(path) - return ctor(path) - raise - - @classmethod - def mkdir(cls, path): - cls._create(path, os.mkdir) - - @classmethod - def symlink(cls, lnk, path): - cls._create(path, lambda p: os.symlink(lnk, p)) - - @classmethod - def xtime(cls, path, uuid): - try: - return struct.unpack('!II', Xattr.lgetxattr(path, '.'.join([cls.GX_NSPACE, uuid, 'xtime']), 8)) - except OSError: - ex = sys.exc_info()[1] - if ex.errno in (ENOENT, ENODATA, ENOTDIR): - return ex.errno - else: - raise - - @classmethod - def set_xtime(cls, path, uuid, mark): - Xattr.lsetxattr(path, '.'.join([cls.GX_NSPACE, uuid, 'xtime']), struct.pack('!II', *mark)) - - @staticmethod - def setattr(path, adct): - own = adct.get('own') - if own: - os.lchown(path, *own) - mode = adct.get('mode') - if mode: - os.chmod(path, stat.S_IMODE(mode)) - times = adct.get('times') - if times: - os.utime(path, times) - - @staticmethod - def pid(): - return os.getpid() - - last_keep_alive = 0 - @classmethod - def keep_alive(cls, dct): - if dct: - key = '.'.join([cls.GX_NSPACE, 'volume-mark', dct['uuid']]) - val = struct.pack(cls.FRGN_FMTSTR, - *(dct['version'] + - tuple(int(x,16) for x in re.findall('(?:[\da-f]){2}', dct['uuid'])) + - (dct['retval'],) + dct['volume_mark'][0:2] + (dct['timeout'],))) - Xattr.lsetxattr('.', key, val) - cls.last_keep_alive += 1 - return cls.last_keep_alive - - @staticmethod - def version(): - return 1.0 - - -class SlaveLocal(object): - - def can_connect_to(self, remote): - return not remote - - def service_loop(self): - repce = RepceServer(self.server, sys.stdin, sys.stdout, int(gconf.sync_jobs)) - t = syncdutils.Thread(target=repce.service_loop) - t.start() - logging.info("slave listening") - if gconf.timeout and int(gconf.timeout) > 0: - while True: - lp = self.server.last_keep_alive - time.sleep(int(gconf.timeout)) - if lp == self.server.last_keep_alive: - logging.info("connection inactive for %d seconds, stopping" % int(gconf.timeout)) - break - else: - select.select((), (), ()) - -class SlaveRemote(object): - - def connect_remote(self, rargs=[], **opts): - slave = opts.get('slave', self.url) - ix, ox = os.pipe() - iy, oy = os.pipe() - pid = os.fork() - if not pid: - os.close(ox) - os.dup2(ix, sys.stdin.fileno()) - os.close(iy) - os.dup2(oy, sys.stdout.fileno()) - so = getattr(gconf, 'session_owner', None) - if so: - so_args = ['--session-owner', so] - else: - so_args = [] - argv = rargs + gconf.remote_gsyncd.split() + so_args + \ - ['-N', '--listen', '--timeout', str(gconf.timeout), slave] - os.execvp(argv[0], argv) - os.close(ix) - os.close(oy) - return self.start_fd_client(iy, ox, **opts) - - def start_fd_client(self, i, o, **opts): - self.server = RepceClient(i, o) - rv = self.server.__version__() - exrv = {'proto': repce.repce_version, 'object': Server.version()} - da0 = (rv, exrv) - da1 = ({}, {}) - for i in range(2): - for k, v in da0[i].iteritems(): - da1[i][k] = int(v) - if da1[0] != da1[1]: - raise RuntimeError("RePCe major version mismatch: local %s, remote %s" % (exrv, rv)) - - def rsync(self, files, *args): - if not files: - raise RuntimeError("no files to sync") - logging.debug("files: " + ", ".join(files)) - argv = gconf.rsync_command.split() + gconf.rsync_extra.split() + ['-aR'] + files + list(args) - return os.spawnvp(os.P_WAIT, argv[0], argv) == 0 - - -class AbstractUrl(object): - - def __init__(self, path, pattern): - m = re.search(pattern, path) - if not m: - raise RuntimeError("malformed path") - self.path = path - return m.groups() - - @property - def scheme(self): - return type(self).__name__.lower() - - def canonical_path(self): - return self.path - - def get_url(self, canonical=False, escaped=False): - if canonical: - pa = self.canonical_path() - else: - pa = self.path - u = "://".join((self.scheme, pa)) - if escaped: - u = syncdutils.escape(u) - return u - - @property - def url(self): - return self.get_url() - - - ### Concrete resource classes ### - - -class FILE(AbstractUrl, SlaveLocal, SlaveRemote): - - class FILEServer(Server): - pass - - server = FILEServer - - def __init__(self, path): - sup(self, path, '^/') - - def connect(self): - os.chdir(self.path) - - def rsync(self, files): - return sup(self, files, self.path) - - -class GLUSTER(AbstractUrl, SlaveLocal, SlaveRemote): - - class GLUSTERServer(Server): - - @classmethod - def _attr_unpack_dict(cls, xattr, extra_fields = ''): - fmt_string = cls.NTV_FMTSTR + extra_fields - buf = Xattr.lgetxattr('.', xattr, struct.calcsize(fmt_string)) - vm = struct.unpack(fmt_string, buf) - m = re.match('(.{8})(.{4})(.{4})(.{4})(.{12})', "".join(['%02x' % x for x in vm[2:18]])) - uuid = '-'.join(m.groups()) - volinfo = { 'version': vm[0:2], - 'uuid' : uuid, - 'retval' : vm[18], - 'volume_mark': vm[19:21], - } - if extra_fields: - return volinfo, vm[-len(extra_fields):] - else: - return volinfo - - @classmethod - def foreign_volume_infos(cls): - dict_list = [] - xattr_list = Xattr.llistxattr_buf('.') - for ele in xattr_list: - if ele.find('.'.join([cls.GX_NSPACE, 'volume-mark', ''])) == 0: - d, x = cls._attr_unpack_dict(ele, cls.FRGN_XTRA_FMT) - now = int(time.time()) - if x[0] > now: - logging.debug("volinfo[%s] expires: %d (%d sec later)" % \ - (d['uuid'], x[0], x[0] - now)) - dict_list.append(d) - else: - try: - Xattr.lremovexattr('.', ele) - except OSError: - pass - return dict_list - - @classmethod - def native_volume_info(cls): - try: - return cls._attr_unpack_dict('.'.join([cls.GX_NSPACE, 'volume-mark'])) - except OSError: - ex = sys.exc_info()[1] - if ex.errno != ENODATA: - raise - - server = GLUSTERServer - - def __init__(self, path): - self.host, self.volume = sup(self, path, '^(%s):(.+)' % HostRX.pattern) - - def canonical_path(self): - return ':'.join([socket.gethostbyname(self.host), self.volume]) - - def can_connect_to(self, remote): - return True - - def connect(self): - def umount_l(d): - argv = ['umount', '-l', d] - return os.spawnvp(os.P_WAIT, argv[0], argv) - d = tempfile.mkdtemp(prefix='gsyncd-aux-mount-') - mounted = False - try: - argv = gconf.gluster_command.split() + \ - (gconf.gluster_log_level and ['-L', gconf.gluster_log_level] or []) + \ - ['-l', gconf.gluster_log_file, '-s', self.host, - '--volfile-id', self.volume, '--client-pid=-1', d] - if os.spawnvp(os.P_WAIT, argv[0], argv): - raise RuntimeError("command failed: " + " ".join(argv)) - mounted = True - logging.debug('auxiliary glusterfs mount in place') - os.chdir(d) - if umount_l(d) != 0: - raise RuntimeError("umounting %s failed" % d) - mounted = False - finally: - try: - if mounted: - umount_l(d) - os.rmdir(d) - except: - logging.warn('stale mount possibly left behind on ' + d) - logging.debug('auxiliary glusterfs mount prepared') - - def connect_remote(self, *a, **kw): - sup(self, *a, **kw) - self.slavedir = "/proc/%d/cwd" % self.server.pid() - - def service_loop(self, *args): - if args: - GMaster(self, args[0]).crawl_loop() - else: - sup(self, *args) - - def rsync(self, files): - return sup(self, files, self.slavedir) - - -class SSH(AbstractUrl, SlaveRemote): - - def __init__(self, path): - self.remote_addr, inner_url = sup(self, path, - '^((?:%s@)?%s):(.+)' % tuple([ r.pattern for r in (UserRX, HostRX) ])) - self.inner_rsc = parse_url(inner_url) - - def canonical_path(self): - m = re.match('([^@]+)@(.+)', self.remote_addr) - if m: - u, h = m.groups() - else: - u, h = pwd.getpwuid(os.geteuid()).pw_name, self.remote_addr - remote_addr = '@'.join([u, socket.gethostbyname(h)]) - return ':'.join([remote_addr, self.inner_rsc.get_url(canonical=True)]) - - def can_connect_to(self, remote): - return False - - def start_fd_client(self, *a, **opts): - if opts.get('deferred'): - return a - sup(self, *a) - ityp = type(self.inner_rsc) - if ityp == FILE: - slavepath = self.inner_rsc.path - elif ityp == GLUSTER: - slavepath = "/proc/%d/cwd" % self.server.pid() - else: - raise NotImplementedError - self.slaveurl = ':'.join([self.remote_addr, slavepath]) - - def connect_remote(self, go_daemon=None): - if go_daemon == 'done': - return self.start_fd_client(*self.fd_pair) - gconf.setup_ssh_ctl(tempfile.mkdtemp(prefix='gsyncd-aux-ssh-')) - deferred = go_daemon == 'postconn' - ret = sup(self, gconf.ssh_command.split() + gconf.ssh_ctl_args + [self.remote_addr], slave=self.inner_rsc.url, deferred=deferred) - if deferred: - # send a message to peer so that we can wait for - # the answer from which we know connection is - # established and we can proceed with daemonization - # (doing that too early robs the ssh passwd prompt...) - # However, we'd better not start the RepceClient - # before daemonization (that's not preserved properly - # in daemon), we just do a an ad-hoc linear put/get. - i, o = ret - inf = os.fdopen(i) - repce.send(o, None, '__repce_version__') - select.select((inf,), (), ()) - repce.recv(inf) - # hack hack hack: store a global reference to the file - # to save it from getting GC'd which implies closing it - gconf.permanent_handles.append(inf) - self.fd_pair = (i, o) - return 'should' - - def rsync(self, files): - return sup(self, files, '-ze', " ".join(gconf.ssh_command.split() + gconf.ssh_ctl_args), self.slaveurl) diff --git a/xlators/features/marker/utils/syncdaemon/syncdutils.py b/xlators/features/marker/utils/syncdaemon/syncdutils.py deleted file mode 100644 index 4bf51da74..000000000 --- a/xlators/features/marker/utils/syncdaemon/syncdutils.py +++ /dev/null @@ -1,160 +0,0 @@ -import os -import sys -import time -import fcntl -import shutil -import logging -from threading import Lock, Thread as baseThread -from errno import EACCES, EAGAIN -from signal import SIGTERM, SIGKILL -from time import sleep - -from gconf import gconf - -try: - # py 3 - from urllib import parse as urllib -except ImportError: - import urllib - -def escape(s): - return urllib.quote_plus(s) - -def unescape(s): - return urllib.unquote_plus(s) - -def norm(s): - if s: - return s.replace('-', '_') - -def update_file(path, updater, merger = lambda f: True): - """update a file in a transaction-like manner""" - - fr = fw = None - try: - fd = os.open(path, os.O_CREAT|os.O_RDWR) - try: - fr = os.fdopen(fd, 'r+b') - except: - os.close(fd) - raise - fcntl.lockf(fr, fcntl.LOCK_EX) - if not merger(fr): - return - - tmpp = path + '.tmp.' + str(os.getpid()) - fd = os.open(tmpp, os.O_CREAT|os.O_EXCL|os.O_WRONLY) - try: - fw = os.fdopen(fd, 'wb', 0) - except: - os.close(fd) - raise - updater(fw) - os.fsync(fd) - os.rename(tmpp, path) - finally: - for fx in (fr, fw): - if fx: - fx.close() - -def grabfile(fname, content=None): - # damn those messy open() mode codes - fd = os.open(fname, os.O_CREAT|os.O_RDWR) - f = os.fdopen(fd, 'r+b', 0) - try: - fcntl.lockf(f, fcntl.LOCK_EX|fcntl.LOCK_NB) - except: - ex = sys.exc_info()[1] - f.close() - if isinstance(ex, IOError) and ex.errno in (EACCES, EAGAIN): - # cannot grab, it's taken - return - raise - if content: - try: - f.truncate() - f.write(content) - except: - f.close() - raise - gconf.permanent_handles.append(f) - return f - -def grabpidfile(fname=None, setpid=True): - if not fname: - fname = gconf.pid_file - content = None - if setpid: - content = str(os.getpid()) + '\n' - return grabfile(fname, content=content) - -final_lock = Lock() - -def finalize(*a, **kw): - final_lock.acquire() - if getattr(gconf, 'pid_file', None): - rm_pidf = gconf.pid_file_owned - if gconf.cpid: - # exit path from parent branch of daemonization - rm_pidf = False - while True: - f = grabpidfile(setpid=False) - if not f: - # child has already taken over pidfile - break - if os.waitpid(gconf.cpid, os.WNOHANG)[0] == gconf.cpid: - # child has terminated - rm_pidf = True - break; - time.sleep(0.1) - if rm_pidf: - try: - os.unlink(gconf.pid_file) - except: - ex = sys.exc_info()[1] - if ex.errno == ENOENT: - pass - else: - raise - if gconf.ssh_ctl_dir and not gconf.cpid: - shutil.rmtree(gconf.ssh_ctl_dir) - sys.stdout.flush() - sys.stderr.flush() - os._exit(kw.get('exval', 0)) - -def log_raise_exception(excont): - exc = sys.exc_info()[1] - if isinstance(exc, SystemExit): - excont.exval = exc.code or 0 - raise - else: - logging.exception("FAIL: ") - sys.stderr.write("failed with %s.\n" % type(exc).__name__) - excont.exval = 1 - sys.exit(excont.exval) - - -class FreeObject(object): - """wildcard class for which any attribute can be set""" - - def __init__(self, **kw): - for k,v in kw.iteritems(): - setattr(self, k, v) - -class Thread(baseThread): - - def __init__(self, *a, **kw): - tf = kw.get('target') - if tf: - def twrap(*aa): - excont = FreeObject(exval = 0) - try: - tf(*aa) - except: - try: - log_raise_exception(excont) - finally: - finalize(exval = excont.exval) - kw['target'] = twrap - baseThread.__init__(self, *a, **kw) - self.setDaemon(True) |
