diff options
Diffstat (limited to 'xlators/features/marker/src')
| -rw-r--r-- | xlators/features/marker/src/Makefile.am | 8 | ||||
| -rw-r--r-- | xlators/features/marker/src/marker-common.c | 41 | ||||
| -rw-r--r-- | xlators/features/marker/src/marker-common.h | 26 | ||||
| -rw-r--r-- | xlators/features/marker/src/marker-mem-types.h | 24 | ||||
| -rw-r--r-- | xlators/features/marker/src/marker-quota-helper.c | 172 | ||||
| -rw-r--r-- | xlators/features/marker/src/marker-quota-helper.h | 64 | ||||
| -rw-r--r-- | xlators/features/marker/src/marker-quota.c | 1983 | ||||
| -rw-r--r-- | xlators/features/marker/src/marker-quota.h | 129 | ||||
| -rw-r--r-- | xlators/features/marker/src/marker.c | 1885 | ||||
| -rw-r--r-- | xlators/features/marker/src/marker.h | 88 |
10 files changed, 3121 insertions, 1299 deletions
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 3e2d7f000..84a718add 100644 --- a/xlators/features/marker/src/marker-common.c +++ b/xlators/features/marker/src/marker-common.c @@ -1,26 +1,17 @@ -/*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" #endif - +#include <fnmatch.h> #include "marker-common.h" marker_inode_ctx_t * @@ -42,20 +33,21 @@ int32_t marker_force_inode_ctx_get (inode_t *inode, xlator_t *this, marker_inode_ctx_t **ctx) { - int32_t ret = -1; - uint64_t ctx_int; + int32_t ret = -1; + uint64_t ctx_int = 0; LOCK (&inode->lock); { ret = __inode_ctx_get (inode, this, &ctx_int); if (ret == 0) - *ctx = (marker_inode_ctx_t *) ctx_int; + *ctx = (marker_inode_ctx_t *) (unsigned long)ctx_int; else { *ctx = marker_inode_ctx_new (); if (*ctx == NULL) goto unlock; - ret = __inode_ctx_put (inode, this, (uint64_t ) *ctx); + ret = __inode_ctx_put (inode, this, + (uint64_t )(unsigned long) *ctx); if (ret == -1) { GF_FREE (*ctx); goto unlock; @@ -68,3 +60,10 @@ unlock: UNLOCK (&inode->lock); return ret; } +int +marker_filter_quota_xattr (dict_t *dict, char *key, + data_t *value, void *data) +{ + 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 311e4e238..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. +/* + 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 _MARKER_COMMON_H #define _MARKER_COMMON_H @@ -30,4 +21,7 @@ int32_t marker_force_inode_ctx_get (inode_t *, xlator_t *, marker_inode_ctx_t **); + +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 b6a87698e..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; } } @@ -178,6 +185,9 @@ __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); out: @@ -186,11 +196,11 @@ 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; - if (ctx == NULL || loc == NULL) + if ((ctx == NULL) || (loc == NULL)) return NULL; if (strcmp (loc->path, "/") == 0) @@ -198,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); @@ -207,12 +217,17 @@ 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, }; + 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) { ret = -1; @@ -222,7 +237,8 @@ dict_set_contribution (xlator_t *this, dict_t *dict, ret = dict_set_int64 (dict, contri_key, 0); if (ret < 0) { gf_log (this->name, GF_LOG_WARNING, - "unable to set dict value."); + "unable to set dict value on %s.", + loc->path); goto out; } @@ -233,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; @@ -251,7 +267,7 @@ quota_inode_ctx_get (inode_t *inode, xlator_t *this, goto out; } - mark_ctx = (marker_inode_ctx_t *) ctx_int; + mark_ctx = (marker_inode_ctx_t *) (unsigned long)ctx_int; if (mark_ctx->quota_ctx == NULL) { ret = -1; goto out; @@ -267,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; @@ -283,48 +299,43 @@ __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; } mark_ctx->quota_ctx = quota_ctx; - } else + } else { quota_ctx = mark_ctx->quota_ctx; + } ret = 0; } -unlock: UNLOCK (&inode->lock); - +unlock: + UNLOCK (&inode->lock); out: return quota_ctx; } 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; @@ -333,7 +344,7 @@ out: } quota_local_t * -quota_local_ref (quota_local_t *local) +mq_local_ref (quota_local_t *local) { LOCK (&local->lock); { @@ -346,21 +357,58 @@ 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) goto out; - QUOTA_SAFE_DECREMENT (&local->lock, local->ref); + QUOTA_SAFE_DECREMENT (&local->lock, local->ref, ref); - if (local->ref > 0) + if (ref != 0) goto out; + if (local->fd != NULL) + fd_unref (local->fd); + loc_wipe (&local->loc); loc_wipe (&local->parent_loc); LOCK_DESTROY (&local->lock); + + mem_put (local); out: return 0; } + + +inode_contribution_t * +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 = 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 " + "(gfid:%s, path:%s)", + uuid_utoa (loc->inode->gfid), loc->path); + goto err; + } + + contribution = mq_get_contribution_node (loc->parent, ctx); + if (contribution == NULL) { + gf_log_callingfn (this->name, GF_LOG_WARNING, + "inode (gfid:%s, path:%s) has " + "no contribution towards parent (gfid:%s)", + uuid_utoa (loc->inode->gfid), + loc->path, uuid_utoa (loc->parent->gfid)); + goto err; + } + +err: + return contribution; +} diff --git a/xlators/features/marker/src/marker-quota-helper.h b/xlators/features/marker/src/marker-quota-helper.h index 9a24c8c3d..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 @@ -22,7 +15,8 @@ #define _CONFIG_H #include "config.h" #endif -#include "marker-quota.h" + +#include "marker.h" #define QUOTA_FREE_CONTRIBUTION_NODE(_contribution) \ do { \ @@ -37,40 +31,46 @@ UNLOCK (lock); \ } while (0) -#define QUOTA_SAFE_DECREMENT(lock, var) \ - do { \ - LOCK (lock); \ - var --; \ - UNLOCK (lock); \ +#define QUOTA_SAFE_DECREMENT(lock, var, value) \ + do { \ + LOCK (lock); \ + { \ + value = --var; \ + } \ + UNLOCK (lock); \ } 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 * +mq_get_contribution_node (inode_t *, quota_inode_ctx_t *); inode_contribution_t * -get_contribution_node (inode_t *, quota_inode_ctx_t *); +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 f7b397a5a..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,15 +21,146 @@ #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 -loc_fill_from_name (xlator_t *this, loc_t *newloc, loc_t *oldloc, uint64_t ino, char *name) +mq_get_local_err (quota_local_t *local, + int32_t *val) { - int32_t ret = 0; + 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) +{ + marker_conf_t *conf = NULL; + uint64_t lk_owner = 0; + + conf = this->private; + + LOCK (&conf->lock); + { + if (++conf->quota_lk_owner == 0) { + ++conf->quota_lk_owner; + } + + lk_owner = conf->quota_lk_owner; + } + UNLOCK (&conf->lock); + + set_lk_owner_from_uint64 (&frame->root->lk_owner, lk_owner); + + return; +} + + +int32_t +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; char *path = NULL; - - newloc->ino = ino; + GF_VALIDATE_OR_GOTO ("marker", this, out); + GF_VALIDATE_OR_GOTO ("marker", newloc, out); + GF_VALIDATE_OR_GOTO ("marker", oldloc, out); + GF_VALIDATE_OR_GOTO ("marker", name, out); newloc->inode = inode_new (oldloc->inode->table); @@ -48,6 +170,7 @@ loc_fill_from_name (xlator_t *this, loc_t *newloc, loc_t *oldloc, uint64_t ino, } newloc->parent = inode_ref (oldloc->inode); + uuid_copy (newloc->pargfid, oldloc->inode->gfid); len = strlen (oldloc->path); @@ -68,46 +191,40 @@ loc_fill_from_name (xlator_t *this, loc_t *newloc, loc_t *oldloc, uint64_t ino, if (newloc->name) newloc->name++; - gf_log (this->name, GF_LOG_INFO, "path = %s name =%s",newloc->path, newloc->name); + gf_log (this->name, GF_LOG_DEBUG, "path = %s name =%s", + newloc->path, newloc->name); out: return ret; } 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; - - local = frame->local; - - if (!local->err) - QUOTA_SAFE_DECREMENT (&local->lock, local->ref); - 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; + 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; } - local = frame->local; - if (op_ret == 0) local->ctx->dirty = 0; @@ -117,61 +234,87 @@ 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; + int32_t ret = -1; + int64_t *size = NULL; + dict_t *newdict = NULL; + quota_local_t *local = NULL; + + local = (quota_local_t *) frame->local; if (op_ret == -1) goto err; - priv = (marker_conf_t *) this->private; - - local = (quota_local_t *) frame->local; - if (!dict) goto wind; - ret = dict_get_bin (dict, priv->size_key, (void **) &size); + ret = dict_get_bin (dict, QUOTA_SIZE_KEY, (void **) &size); if (ret) goto wind; - local->ctx->size = ntoh64 (*size); + LOCK (&local->ctx->lock); + { + local->ctx->size = ntoh64 (*size); + } + UNLOCK (&local->ctx->lock); wind: newdict = dict_new (); if (!newdict) goto err; - ret = dict_set_int8 (newdict, priv->dirty_key, 0); + ret = dict_set_int8 (newdict, QUOTA_DIRTY_KEY, 0); 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) @@ -181,49 +324,60 @@ 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) + if (dict == NULL) { + gf_log (this->name, GF_LOG_WARNING, + "Dict is null while updating the size xattr %s", + local->loc.path?local->loc.path:""); goto err; + } - local = frame->local; - - ret = dict_get_bin (dict, priv->size_key, (void **) &size); - if (!size) + ret = dict_get_bin (dict, QUOTA_SIZE_KEY, (void **) &size); + if (!size) { + gf_log (this->name, GF_LOG_WARNING, + "failed to get the size, %s", + local->loc.path?local->loc.path:""); goto err; + } QUOTA_ALLOC_OR_GOTO (delta, int64_t, ret, err); - *delta = ntoh64 (ntoh64 (*size) - local->sum); + *delta = hton64 (local->sum - ntoh64 (*size)); - gf_log (this->name, GF_LOG_DEBUG, "calculated size = %ld, original size = %ld" - "path = %s diff = %ld", local->sum, ntoh64 (*size), - local->loc.path, ntoh64 (*delta)); + gf_log (this->name, GF_LOG_DEBUG, "calculated size = %"PRId64", " + "original size = %"PRIu64 + " path = %s diff = %"PRIu64, local->sum, ntoh64 (*size), + local->loc.path, ntoh64 (*delta)); new_dict = dict_new (); if (!new_dict); - ret = dict_set_bin (new_dict, priv->size_key, delta, 8); + ret = dict_set_bin (new_dict, QUOTA_SIZE_KEY, delta, 8); 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; @@ -231,26 +385,46 @@ 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) - dict_unref (dict); + dict_unref (new_dict); return 0; } 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) { - int32_t ret = -1; - dict_t *dict = NULL; - quota_local_t *local = NULL; - marker_conf_t *priv = NULL; + int tmp = 0; + int32_t ret = -1; - local = (quota_local_t *) frame->local; + GF_VALIDATE_OR_GOTO ("marker", local, out); + GF_VALIDATE_OR_GOTO ("marker", val, out); - priv = (marker_conf_t *) this->private; + 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; + + local = (quota_local_t *) frame->local; dict = dict_new (); if (!dict) { @@ -258,11 +432,16 @@ get_dirty_inode_size (call_frame_t *frame, xlator_t *this) goto err; } - ret = dict_set_int64 (dict, priv->size_key, 0); + ret = dict_set_int64 (dict, QUOTA_SIZE_KEY, 0); 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; @@ -270,27 +449,31 @@ 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; - char contri_key [512] = {0, }; - int64_t *contri = NULL; - quota_local_t *local = NULL; + int32_t ret = -1; + int32_t val = 0; + char contri_key [512] = {0, }; + int64_t *contri = NULL; + quota_local_t *local = NULL; local = frame->local; @@ -299,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); - - goto out; + 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 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) @@ -324,92 +510,122 @@ get_child_contribution (call_frame_t *frame, out: LOCK (&local->lock); { - local->dentry_child_count--; + val = --local->dentry_child_count; } UNLOCK (&local->lock); - if (local->dentry_child_count == 0) { - if (local->err) { - QUOTA_SAFE_DECREMENT (&local->lock, local->ref); - - 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, }; - loc_t loc; - int32_t ret = 0; - off_t offset = 0; - int32_t count = 0; - dict_t *dict = NULL; - quota_local_t *local = NULL; - gf_dirent_t *entry = NULL; - call_frame_t *newframe = NULL; - - local = frame->local; + 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; + quota_local_t *local = NULL; + gf_dirent_t *entry = NULL; + call_frame_t *newframe = NULL; + loc_t loc = {0, }; + + 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; list_for_each_entry (entry, (&entries->list), list) { - gf_log (this->name, GF_LOG_INFO, "entry = %s", entry->d_name); + gf_log (this->name, GF_LOG_DEBUG, "entry = %s", entry->d_name); + + if ((!strcmp (entry->d_name, ".")) || (!strcmp (entry->d_name, + ".."))) { + gf_log (this->name, GF_LOG_DEBUG, "entry = %s", + entry->d_name); + continue; + } + + offset = entry->d_off; + count++; + } + + if (count == 0) { + mq_get_dirty_inode_size (frame, this); + goto end; - if ((!strcmp (entry->d_name, ".")) || (!strcmp (entry->d_name, ".."))) { - gf_log (this->name, GF_LOG_INFO, "entry = %s", entry->d_name); - continue; - } - count++; } local->frame = frame; + LOCK (&local->lock); + { + local->dentry_child_count = count; + local->d_off = offset; + } + UNLOCK (&local->lock); + + list_for_each_entry (entry, (&entries->list), list) { - gf_log (this->name, GF_LOG_INFO, "entry = %s", entry->d_name); + gf_log (this->name, GF_LOG_DEBUG, "entry = %s", entry->d_name); - if ((!strcmp (entry->d_name, ".")) || (!strcmp (entry->d_name, ".."))) { - gf_log (this->name, GF_LOG_INFO, "entry = %s", entry->d_name); - offset = entry->d_off; + if ((!strcmp (entry->d_name, ".")) || (!strcmp (entry->d_name, + ".."))) { + gf_log (this->name, GF_LOG_DEBUG, "entry = %s", + entry->d_name); 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); - newframe->local = local; + if (ret == -1) + goto out; + + newframe->local = mq_local_ref (local); dict = dict_new (); if (!dict) { @@ -425,10 +641,8 @@ quota_readdir_cbk (call_frame_t *frame, if (ret) goto out; - QUOTA_SAFE_INCREMENT (&local->lock, local->dentry_child_count); - STACK_WIND (newframe, - get_child_contribution, + mq_get_child_contribution, FIRST_CHILD(this), FIRST_CHILD(this)->fops->lookup, &loc, dict); @@ -437,6 +651,8 @@ quota_readdir_cbk (call_frame_t *frame, loc_wipe (&loc); + newframe = NULL; + out: if (dict) { dict_unref (dict); @@ -444,83 +660,73 @@ 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); } break; } } - gf_log (this->name, GF_LOG_INFO, "offset before =%lu",local->d_off); - local->d_off +=offset; - gf_log (this->name, GF_LOG_INFO, "offset after = %lu",local->d_off); - - 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; + local = frame->local; + 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; } - local = frame->local; - if (local->fd == NULL) 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; @@ -530,20 +736,18 @@ check_if_still_dirty (call_frame_t *frame, goto err; } - priv = this->private; - if (!dict) { - ret = -1; - goto err; + ret = -1; + goto err; } - ret = dict_get_int8 (dict, priv->dirty_key, &dirty); + ret = dict_get_int8 (dict, QUOTA_DIRTY_KEY, &dirty); if (ret) goto err; //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; } @@ -552,39 +756,44 @@ 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) { + fd_unref (fd); } return 0; } 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; + int32_t ret = -1; + dict_t *xattr_req = NULL; + quota_local_t *local = 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 (); @@ -593,12 +802,17 @@ get_dirty_xattr (call_frame_t *frame, void *cookie, goto err; } - ret = dict_set_int8 (xattr_req, priv->dirty_key, 0); + ret = dict_set_int8 (xattr_req, QUOTA_DIRTY_KEY, 0); 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, @@ -608,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) @@ -617,16 +831,26 @@ 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; - struct gf_flock lock; - call_frame_t *frame = NULL; + 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) { @@ -634,13 +858,14 @@ update_dirty_inode (xlator_t *this, goto out; } - local = quota_local_new (); + mq_assign_lk_owner (this, frame); + + 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; @@ -648,21 +873,27 @@ update_dirty_inode (xlator_t *this, local->contri = contribution; - frame->root->lk_owner = cn++; - lock.l_type = F_WRLCK; lock.l_whence = SEEK_SET; lock.l_start = 0; lock.l_len = 0; - STACK_WIND (frame, - get_dirty_xattr, - FIRST_CHILD(this), - FIRST_CHILD(this)->fops->inodelk, - this->name, &local->loc, F_SETLKW, &lock); + 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, + mq_get_dirty_xattr, + FIRST_CHILD(this), + FIRST_CHILD(this)->fops->inodelk, + this->name, &local->loc, F_SETLKW, &lock, NULL); + return 1; fr_destroy: - QUOTA_STACK_DESTROY (frame, this); + QUOTA_STACK_DESTROY (frame, this); out: return 0; @@ -670,8 +901,8 @@ 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; @@ -680,50 +911,88 @@ quota_inode_creation_done (call_frame_t *frame, void *cookie, xlator_t *this, local = frame->local; + if (local != NULL) { + mq_initiate_quota_txn (this, &local->loc); + } + QUOTA_STACK_DESTROY (frame, this); return 0; } + +int32_t +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; + + local = frame->local; + + lock.l_type = F_UNLCK; + lock.l_whence = SEEK_SET; + lock.l_start = 0; + lock.l_len = 0; + lock.l_pid = 0; + + STACK_WIND (frame, + mq_inode_creation_done, + FIRST_CHILD(this), + FIRST_CHILD(this)->fops->inodelk, + this->name, &local->loc, + 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 == -1 && op_errno == ENOTCONN) + if (op_ret < 0) { goto err; + } local = frame->local; - priv = (marker_conf_t *) this->private; - if (local->loc.inode->ia_type == IA_IFDIR) { newdict = dict_new (); - if (!newdict) + if (!newdict) { goto err; + } - ret = dict_set_int8 (newdict, priv->dirty_key, 0); - if (ret == -1) + ret = dict_set_int8 (newdict, QUOTA_DIRTY_KEY, 0); + if (ret == -1) { goto err; + } + + uuid_copy (local->loc.gfid, local->loc.inode->gfid); + GF_UUID_ASSERT (local->loc.gfid); - STACK_WIND (frame, quota_inode_creation_done, + STACK_WIND (frame, mq_xattr_creation_release_lock, FIRST_CHILD(this), FIRST_CHILD(this)->fops->setxattr, - &local->loc, newdict, 0); - } else - quota_inode_creation_done (frame, NULL, this, 0, 0); + &local->loc, newdict, 0, NULL); + } else { + mq_xattr_creation_release_lock (frame, NULL, this, 0, 0, NULL); + } ret = 0; err: - if (ret == -1) - quota_inode_creation_done (frame, NULL, this, -1, 0); + if (ret < 0) { + mq_xattr_creation_release_lock (frame, NULL, this, 0, 0, NULL); + } - if (newdict) + if (newdict != NULL) dict_unref (newdict); return 0; @@ -731,30 +1000,28 @@ err: int32_t -quota_set_inode_xattr (xlator_t *this, loc_t *loc) +mq_create_xattr (xlator_t *this, call_frame_t *frame) { int32_t ret = 0; int64_t *value = NULL; int64_t *size = NULL; dict_t *dict = NULL; char key[512] = {0, }; - call_frame_t *frame = NULL; quota_local_t *local = NULL; - marker_conf_t *priv = NULL; quota_inode_ctx_t *ctx = NULL; inode_contribution_t *contri = NULL; - if (loc == NULL || this == NULL) + if (frame == NULL || this == NULL) return 0; - priv = (marker_conf_t *) this->private; + local = frame->local; - ret = quota_inode_ctx_get (loc->inode, this, &ctx); + ret = mq_inode_ctx_get (local->loc.inode, this, &ctx); if (ret < 0) { - ctx = quota_inode_ctx_new (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; } @@ -764,106 +1031,267 @@ quota_set_inode_xattr (xlator_t *this, loc_t *loc) if (!dict) goto out; - if (loc->inode->ia_type == IA_IFDIR) { + if (local->loc.inode->ia_type == IA_IFDIR) { QUOTA_ALLOC_OR_GOTO (size, int64_t, ret, err); - ret = dict_set_bin (dict, priv->size_key, size, 8); + ret = dict_set_bin (dict, QUOTA_SIZE_KEY, size, 8); if (ret < 0) goto free_size; } - //if '/' then dont set contribution xattr - if (strcmp (loc->path, "/") == 0) - goto wind; + if (strcmp (local->loc.path, "/") != 0) { + contri = mq_add_new_contribution_node (this, ctx, &local->loc); + if (contri == NULL) + goto err; - contri = add_new_contribution_node (this, ctx, loc); - if (contri == NULL) - goto err; + QUOTA_ALLOC_OR_GOTO (value, int64_t, ret, err); + GET_CONTRI_KEY (key, local->loc.parent->gfid, ret); + + ret = dict_set_bin (dict, key, value, 8); + if (ret < 0) + goto free_value; + } + + 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, NULL); + ret = 0; + +free_size: + if (ret < 0) { + GF_FREE (size); + } + +free_value: + if (ret < 0) { + GF_FREE (value); + } + +err: + dict_unref (dict); + +out: + if (ret < 0) { + mq_xattr_creation_release_lock (frame, NULL, this, 0, 0, NULL); + } + + return 0; +} + + +int32_t +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; + int32_t ret = 0; + char contri_key[512] = {0, }; - QUOTA_ALLOC_OR_GOTO (value, int64_t, ret, err); - GET_CONTRI_KEY (key, loc->parent->gfid, ret); + if (op_ret < 0) { + goto out; + } + + local = frame->local; - ret = dict_set_bin (dict, key, value, 8); + ret = dict_get_bin (dict, QUOTA_SIZE_KEY, (void **) &size); if (ret < 0) - goto free_value; + goto create_xattr; + + ret = dict_get_int8 (dict, QUOTA_DIRTY_KEY, &dirty); + if (ret < 0) + goto create_xattr; + + //check contribution xattr if not root + if (strcmp (local->loc.path, "/") != 0) { + GET_CONTRI_KEY (contri_key, local->loc.parent->gfid, ret); + if (ret < 0) + goto out; + + ret = dict_get_bin (dict, contri_key, (void **) &contri); + if (ret < 0) + goto create_xattr; + } + +out: + mq_xattr_creation_release_lock (frame, NULL, this, 0, 0, NULL); + return 0; + +create_xattr: + if (uuid_is_null (local->loc.gfid)) { + uuid_copy (local->loc.gfid, buf->ia_gfid); + } + + mq_create_xattr (this, frame); + return 0; +} + + +int32_t +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; + int32_t ret = 0; + + if (op_ret < 0) { + goto lock_err; + } + + local = frame->local; + + xattr_req = dict_new (); + if (xattr_req == NULL) { + goto err; + } + + ret = mq_req_xattr (this, &local->loc, xattr_req); + if (ret < 0) { + gf_log (this->name, GF_LOG_WARNING, "cannot request xattr"); + 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, 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: + mq_xattr_creation_release_lock (frame, NULL, this, 0, 0, NULL); + + if (xattr_req) + dict_unref (xattr_req); + return 0; + +lock_err: + mq_inode_creation_done (frame, NULL, this, 0, 0, NULL); + return 0; +} + + +int32_t +mq_set_inode_xattr (xlator_t *this, loc_t *loc) +{ + struct gf_flock lock = {0, }; + quota_local_t *local = NULL; + int32_t ret = 0; + call_frame_t *frame = NULL; -wind: frame = create_frame (this, this->ctx->pool); if (!frame) { ret = -1; goto err; } - local = quota_local_new (); - if (local == NULL) - goto free_size; - - local->ctx = ctx; + local = mq_local_new (); + if (local == NULL) { + goto err; + } - local->contri = contri; + frame->local = local; ret = loc_copy (&local->loc, loc); - if (ret < 0) - quota_local_unref (this, local); + if (ret < 0) { + goto err; + } frame->local = local; - STACK_WIND (frame, create_dirty_xattr, FIRST_CHILD(this), - FIRST_CHILD(this)->fops->xattrop, &local->loc, - GF_XATTROP_ADD_ARRAY64, dict); - ret = 0; + lock.l_len = 0; + lock.l_start = 0; + lock.l_type = F_WRLCK; + lock.l_whence = SEEK_SET; -free_size: - if (ret < 0) - GF_FREE (size); + STACK_WIND (frame, + mq_get_xattr, + FIRST_CHILD(this), + FIRST_CHILD(this)->fops->inodelk, + this->name, &local->loc, F_SETLKW, &lock, NULL); -free_value: - if (ret < 0) - GF_FREE (value); + return 0; err: - dict_unref (dict); - -out: - if (ret < 0) - quota_inode_creation_done (NULL, NULL, this, -1, 0); + QUOTA_STACK_DESTROY (frame, this); return 0; } 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) { - uint32_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; @@ -871,19 +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; - - trap (); + 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_INFO, "lock setting failed"); - 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; } @@ -891,16 +1322,25 @@ quota_inodelk_cbk (call_frame_t *frame, void *cookie, gf_log (this->name, GF_LOG_DEBUG, "inodelk released on %s", local->parent_loc.path); - if (strcmp (local->parent_loc.path, "/") == 0) { - xattr_updation_done (frame, NULL, this, 0, 0, NULL); + if ((strcmp (local->parent_loc.path, "/") == 0) + || (local->delta == 0)) { + 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; @@ -909,20 +1349,27 @@ 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; - struct gf_flock lock; quota_local_t *local = NULL; quota_inode_ctx_t *ctx = NULL; - - trap (); + struct gf_flock lock = {0, }; 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; @@ -932,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; @@ -940,32 +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; - - trap (); local = frame->local; @@ -977,47 +1431,57 @@ quota_mark_undirty (call_frame_t *frame, goto err; } - priv = this->private; - - //update the size of the parent inode + //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, priv->size_key, (void **) &size); - if (ret < 0) + ret = dict_get_bin (dict, QUOTA_SIZE_KEY, (void **) &size); + if (ret < 0) { + op_errno = EINVAL; goto err; + } LOCK (&ctx->lock); { if (size) ctx->size = ntoh64 (*size); + gf_log (this->name, GF_LOG_DEBUG, "%s %"PRId64, + local->parent_loc.path, ctx->size); } UNLOCK (&ctx->lock); } newdict = dict_new (); - - if (!newdict) + if (!newdict) { + op_errno = ENOMEM; goto err; + } - ret = dict_set_int8 (newdict, priv->dirty_key, 0); + 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) @@ -1028,169 +1492,212 @@ 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; - trap (); - local = frame->local; if (op_ret == -1) { - gf_log (this->name, GF_LOG_ERROR, "%s", strerror (op_errno)); + gf_log (this->name, ((op_errno == ENOENT) ? GF_LOG_DEBUG : + GF_LOG_WARNING), + "xattrop call failed: %s", strerror (op_errno)); goto err; } - priv = this->private; + LOCK (&local->contri->lock); + { + local->contri->contribution += local->delta; + } + UNLOCK (&local->contri->lock); + + gf_log (this->name, GF_LOG_DEBUG, "%s %"PRId64 "%"PRId64, + local->loc.path, local->ctx->size, + local->contri->contribution); - 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; } QUOTA_ALLOC_OR_GOTO (size, int64_t, ret, err); - *size = ntoh64 (local->delta); + *size = hton64 (local->delta); - ret = dict_set_bin (newdict, priv->size_key, size, 8); - if (ret < 0) + ret = dict_set_bin (newdict, QUOTA_SIZE_KEY, size, 8); + 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 (dict) + if (newdict) dict_unref (newdict); return 0; } 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; - int64_t *contri = NULL; - int64_t *delta = NULL; + int32_t ret = -1; + int64_t *size = NULL, size_int = 0, contri_int = 0; + int64_t *contri = NULL; + int64_t *delta = NULL; char contri_key [512] = {0, }; - 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; - - trap (); + dict_t *newdict = NULL; + quota_local_t *local = NULL; + quota_inode_ctx_t *ctx = NULL; + inode_contribution_t *contribution = NULL; local = frame->local; if (op_ret == -1) { - gf_log (this->name, GF_LOG_ERROR, "failed to get size and " - "contribution with %s error", strerror (op_errno)); + gf_log (this->name, ((op_errno == ENOENT) ? GF_LOG_DEBUG : + GF_LOG_WARNING), + "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, priv->size_key, + 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 - ctx->size = buf->ia_size; + ctx->size = buf->ia_blocks * 512; - ret = dict_get_bin (dict, contri_key, (void **) &contri); + size_int = ctx->size; + } +unlock: + UNLOCK (&ctx->lock); + + if (ret < 0) { + goto err; + } + + ret = dict_get_bin (dict, contri_key, (void **) &contri); + + LOCK (&contribution->lock); + { if (ret < 0) contribution->contribution = 0; else contribution->contribution = ntoh64 (*contri); - ret = 0; + contri_int = contribution->contribution; } -unlock: - UNLOCK (&ctx->lock); + UNLOCK (&contribution->lock); - if (ret < 0) - goto err; + gf_log (this->name, GF_LOG_DEBUG, "%s %"PRId64 "%"PRId64, + local->loc.path, size_int, contri_int); + + local->delta = size_int - contri_int; + + if (local->delta == 0) { + 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; } - local->delta = ctx->size - contribution->contribution; - QUOTA_ALLOC_OR_GOTO (delta, int64_t, ret, err); *delta = hton64 (local->delta); 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) @@ -1200,35 +1707,37 @@ 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; + 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; - - trap (); + dict_t *newdict = NULL; + quota_local_t *local = 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; } - gf_log (this->name, GF_LOG_DEBUG, "%s marked dirty", local->parent_loc.path); + VALIDATE_OR_GOTO (local->ctx, err); + VALIDATE_OR_GOTO (local->contri, err); - priv = this->private; + gf_log (this->name, GF_LOG_DEBUG, "%s marked dirty", local->parent_loc.path); //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); { @@ -1237,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, priv->size_key, 0); + 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; + } + + mq_set_ctx_updation_status (local->ctx, _gf_false); - STACK_WIND (frame, quota_update_inode_contribution, 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_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) @@ -1269,23 +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 %s", strerror (op_errno)); + 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; - quota_inodelk_cbk (frame, NULL, this, 0, 0); + mq_set_ctx_updation_status (local->ctx, _gf_false); + + mq_inodelk_cbk (frame, NULL, this, 0, 0, NULL); return 0; } @@ -1293,29 +1827,33 @@ 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; goto err; } - ret = dict_set_int8 (dict, priv->dirty_key, 1); + ret = dict_set_int8 (dict, QUOTA_DIRTY_KEY, 1); 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) @@ -1326,14 +1864,23 @@ 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; + struct gf_flock lock = {0, }; quota_local_t *local = NULL; GF_VALIDATE_OR_GOTO ("marker", frame, fr_destroy); local = frame->local; + 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; @@ -1341,80 +1888,81 @@ get_lock_on_parent (call_frame_t *frame, xlator_t *this) 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; - quota_local_t *local = NULL; + int32_t ret = -1; + call_frame_t *frame = NULL; + quota_local_t *local = NULL; frame = create_frame (this, this->ctx->pool); if (frame == NULL) goto err; - frame->root->lk_owner = cn++; + 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 local_unref; + 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 local_unref; + 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; -local_unref: - quota_local_unref (this, local); - 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; - quota_inode_ctx_t *ctx = NULL; + int32_t ret = -1; + gf_boolean_t status = _gf_false; + quota_inode_ctx_t *ctx = NULL; inode_contribution_t *contribution = NULL; - trap (); - - 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"); @@ -1422,72 +1970,88 @@ 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; } -int32_t -validate_inode_size_contribution (xlator_t *this, - loc_t *loc, - quota_inode_ctx_t *ctx, - inode_contribution_t *contribution) -{ - if (ctx->size != contribution->contribution) - initiate_quota_txn (this, loc); +/* int32_t */ +/* validate_inode_size_contribution (xlator_t *this, loc_t *loc, int64_t size, */ +/* int64_t contribution) */ +/* { */ +/* if (size != contribution) { */ +/* mq_initiate_quota_txn (this, loc); */ +/* } */ - return 0; -} +/* return 0; */ +/* } */ 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; - int64_t *contri = 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); + 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, }; + gf_boolean_t not_root = _gf_false; + quota_inode_ctx_t *ctx = NULL; + inode_contribution_t *contribution = NULL; + + 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; } } - ret = dict_get_bin (dict, priv->size_key, (void **) &size); + 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; + } + } + + ret = dict_get_bin (dict, QUOTA_SIZE_KEY, (void **) &size); if (ret < 0) goto out; - ret = dict_get_int8 (dict, priv->dirty_key, &dirty); + ret = dict_get_int8 (dict, QUOTA_DIRTY_KEY, &dirty); if (ret < 0) goto out; if (strcmp (loc->path, "/") != 0) { - 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; - } + not_root = _gf_true; GET_CONTRI_KEY (contri_key, contribution->gfid, ret); if (ret < 0) @@ -1497,75 +2061,102 @@ inspect_directory_xattr (xlator_t *this, if (ret < 0) goto out; - contribution->contribution = ntoh64 (*contri); + LOCK (&contribution->lock); + { + contribution->contribution = ntoh64 (*contri); + contri_int = contribution->contribution; + } + UNLOCK (&contribution->lock); } - ctx->size = ntoh64 (*size); + LOCK (&ctx->lock); + { + ctx->size = ntoh64 (*size); + ctx->dirty = dirty; + size_int = ctx->size; + } + UNLOCK (&ctx->lock); + + gf_log (this->name, GF_LOG_DEBUG, "size=%"PRId64 + " contri=%"PRId64, size_int, contri_int); + + if (dirty) { + ret = mq_update_dirty_inode (this, loc, ctx, contribution); + } - ctx->dirty = dirty; - if (ctx->dirty == 1) - 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; - int64_t *contri_ptr = NULL; + 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; + 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; LOCK (&ctx->lock); { - ctx->size = buf.ia_size; + ctx->size = 512 * buf.ia_blocks; + size = ctx->size; } UNLOCK (&ctx->lock); - list_for_each_entry (contribution, &ctx->contribution_head, contri_list) { + list_for_each_entry (contribution, &ctx->contribution_head, + contri_list) { GET_CONTRI_KEY (contri_key, contribution->gfid, ret); if (ret < 0) continue; ret = dict_get_bin (dict, contri_key, (void **) &contri_int); if (ret == 0) { - contri_ptr = (int64_t *) contri_int; + contri_ptr = (int64_t *)(unsigned long)contri_int; + + LOCK (&contribution->lock); + { + contribution->contribution = ntoh64 (*contri_ptr); + contri_int = contribution->contribution; + } + UNLOCK (&contribution->lock); - contribution->contribution = ntoh64 (*contri_ptr); + gf_log (this->name, GF_LOG_DEBUG, + "size=%"PRId64 " contri=%"PRId64, size, contri_int); - ret = validate_inode_size_contribution - (this, loc, ctx, contribution); + if (size != contri_int) { + mq_initiate_quota_txn (this, loc); + } } else - initiate_quota_txn (this, loc); + mq_initiate_quota_txn (this, loc); } out: @@ -1573,51 +2164,49 @@ 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) { - k ++; - 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; set_size: - ret = dict_set_uint64 (dict, priv->size_key, 0); + ret = dict_set_uint64 (dict, QUOTA_SIZE_KEY, 0); if (ret < 0) { ret = -1; goto out; } - ret = dict_set_int8 (dict, priv->dirty_key, 0); + ret = dict_set_int8 (dict, QUOTA_DIRTY_KEY, 0); if (ret < 0) { ret = -1; goto out; @@ -1631,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); @@ -1640,106 +2229,237 @@ 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, dict_t *dict) +_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, }; - quota_local_t *local = NULL; + int32_t ret = 0; + char contri_key [512] = {0, }; + quota_local_t *local = NULL; local = (quota_local_t *) frame->local; + if (op_ret == -1 || local->err == -1) { + mq_removexattr_cbk (frame, NULL, this, -1, 0, NULL); + return 0; + } + + frame->local = NULL; + if (local->hl_count > 1) { GET_CONTRI_KEY (contri_key, local->contri->gfid, ret); - STACK_WIND (frame, quota_removexattr_cbk, FIRST_CHILD(this), - FIRST_CHILD(this)->fops->removexattr, - &local->loc, contri_key); + STACK_WIND (frame, mq_removexattr_cbk, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->removexattr, + &local->loc, contri_key, NULL); ret = 0; + } else { + 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); } +out: + mq_local_unref (this, local); + + return 0; +} - quota_local_unref (this, local); +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, + dict_t *xdata) +{ + int32_t ret = -1; + struct gf_flock lock = {0, }; + quota_inode_ctx_t *ctx = NULL; + quota_local_t *local = NULL; + int64_t contribution = 0; + local = frame->local; + if (op_ret == -1) + local->err = -1; + + ret = mq_inode_ctx_get (local->parent_loc.inode, this, &ctx); + + LOCK (&local->contri->lock); + { + contribution = local->contri->contribution; + } + UNLOCK (&local->contri->lock); + + if (contribution == local->size) { + if (ret == 0) { + LOCK (&ctx->lock); + { + ctx->size -= contribution; + } + UNLOCK (&ctx->lock); + + LOCK (&local->contri->lock); + { + local->contri->contribution = 0; + } + UNLOCK (&local->contri->lock); + } + } + + lock.l_type = F_UNLCK; + lock.l_whence = SEEK_SET; + lock.l_start = 0; + lock.l_len = 0; + lock.l_pid = 0; + + STACK_WIND (frame, + _mq_inode_remove_done, + FIRST_CHILD(this), + FIRST_CHILD(this)->fops->inodelk, + this->name, &local->parent_loc, + F_SETLKW, &lock, NULL); return 0; } int32_t -reduce_parent_size (xlator_t *this, loc_t *loc) +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; - 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; + + local = frame->local; + if (op_ret == -1) { + gf_log (this->name, GF_LOG_WARNING, + "inodelk set failed on %s", local->parent_loc.path); + QUOTA_STACK_DESTROY (frame, this); + return 0; + } + + VALIDATE_OR_GOTO (local->contri, err); + + dict = dict_new (); + if (dict == NULL) { + ret = -1; + goto err; + } + + QUOTA_ALLOC_OR_GOTO (size, int64_t, ret, err); + + *size = hton64 (-local->size); + + ret = dict_set_bin (dict, QUOTA_SIZE_KEY, size, 8); + 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, NULL); + dict_unref (dict); + return 0; + +err: + local->err = 1; + mq_inode_remove_done (frame, NULL, this, -1, 0, NULL, NULL); + if (dict) + dict_unref (dict); + return 0; +} + +int32_t +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; + quota_local_t *local = NULL; + quota_inode_ctx_t *ctx = NULL; + inode_contribution_t *contribution = NULL; 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; } - ret = quota_inode_loc_fill ((const char *) loc->parent->gfid, - loc->parent, &local->parent_loc); - if (ret < 0) - goto free_local; + if (contri >= 0) { + local->size = contri; + } else { + LOCK (&contribution->lock); + { + local->size = contribution->contribution; + } + UNLOCK (&contribution->lock); + } - dict = dict_new (); - if (dict == NULL) { - ret = -1; - goto free_local; + if (local->size == 0) { + ret = 0; + goto out; } - QUOTA_ALLOC_OR_GOTO (size, int64_t, ret, free_local); + ret = mq_loc_copy (&local->loc, loc); + if (ret < 0) + goto out; - *size = hton64 (-contribution->contribution); + local->ctx = ctx; + local->contri = contribution; - ret = dict_set_bin (dict, priv->size_key, size, 8); + ret = mq_inode_loc_fill (NULL, loc->parent, &local->parent_loc); if (ret < 0) - goto free_size; + goto out; frame = create_frame (this, this->ctx->pool); if (!frame) { ret = -1; - goto free_size; + goto out; } + mq_assign_lk_owner (this, frame); + frame->local = local; - STACK_WIND (frame, quota_inode_remove_done, FIRST_CHILD(this), - FIRST_CHILD(this)->fops->xattrop, &local->parent_loc, - GF_XATTROP_ADD_ARRAY64, dict); + lock.l_len = 0; + lock.l_start = 0; + 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, NULL); + local = NULL; ret = 0; -free_size: - if (ret < 0) - GF_FREE (size); -free_local: - if (ret < 0) - quota_local_unref (this, local); out: - dict_unref (dict); + if (local != NULL) + mq_local_unref (this, local); return ret; } @@ -1748,24 +2468,12 @@ out: int32_t init_quota_priv (xlator_t *this) { - marker_conf_t *priv = NULL; - - priv = this->private; - - strcpy (volname, "quota"); - - gf_asprintf (&priv->size_key, QUOTA_XATTR_PREFIX - ".%s.size", volname); - - gf_asprintf (&priv->dirty_key, QUOTA_XATTR_PREFIX - ".%s.dirty", volname); - return 0; } int32_t -quota_rename_update_newpath (xlator_t *this, loc_t *loc, inode_t *inode) +mq_rename_update_newpath (xlator_t *this, loc_t *loc) { int32_t ret = -1; quota_inode_ctx_t *ctx = NULL; @@ -1773,28 +2481,25 @@ quota_rename_update_newpath (xlator_t *this, loc_t *loc, inode_t *inode) GF_VALIDATE_OR_GOTO ("marker", this, out); GF_VALIDATE_OR_GOTO ("marker", loc, out); - GF_VALIDATE_OR_GOTO ("marker", inode, out); - - if (loc->inode == NULL) - loc->inode = inode_ref (inode); + 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 fdec1230f..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,17 +15,16 @@ #include "config.h" #endif -#include "marker.h" #include "xlator.h" #include "marker-mem-types.h" #define QUOTA_XATTR_PREFIX "trusted.glusterfs" +#define QUOTA_DIRTY_KEY "trusted.glusterfs.quota.dirty" + #define CONTRIBUTION "contri" -#define VOL_NAME volname #define CONTRI_KEY_MAX 512 #define READDIR_BUF 4096 -char volname [40]; #define QUOTA_STACK_DESTROY(_frame, _this) \ do { \ @@ -42,27 +32,26 @@ char volname [40]; _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) #define QUOTA_ALLOC(var, type, ret) \ do { \ + ret = 0; \ var = GF_CALLOC (sizeof (type), 1, \ - gf_marker_mt_##type); \ + gf_marker_mt_##type); \ if (!var) { \ gf_log ("", GF_LOG_ERROR, \ "out of memory"); \ ret = -1; \ } \ - ret = 0; \ } while (0); #define QUOTA_ALLOC_OR_GOTO(var, type, ret, label) \ do { \ var = GF_CALLOC (sizeof (type), 1, \ - gf_marker_mt_##type); \ + gf_marker_mt_##type); \ if (!var) { \ gf_log ("", GF_LOG_ERROR, \ "out of memory"); \ @@ -72,96 +61,70 @@ char volname [40]; ret = 0; \ } while (0); -#define GET_CONTRI_KEY(var, _gfid, _ret) \ - do { \ - char _gfid_unparsed[40]; \ - uuid_unparse (_gfid, _gfid_unparsed); \ +#define GET_CONTRI_KEY(var, _gfid, _ret) \ + do { \ + char _gfid_unparsed[40]; \ + uuid_unparse (_gfid, _gfid_unparsed); \ _ret = snprintf (var, CONTRI_KEY_MAX, QUOTA_XATTR_PREFIX \ - ".%s.%s." CONTRIBUTION, VOL_NAME, \ - _gfid_unparsed); \ + ".%s.%s." CONTRIBUTION, "quota", \ + _gfid_unparsed); \ } while (0); -#define QUOTA_SAFE_INCREMENT(lock, var) \ - do { \ - LOCK (lock); \ - var ++; \ - UNLOCK (lock); \ +#define QUOTA_SAFE_INCREMENT(lock, var) \ + do { \ + LOCK (lock); \ + var ++; \ + UNLOCK (lock); \ } while (0) -#define QUOTA_SAFE_DECREMENT(lock, var) \ - do { \ - LOCK (lock); \ - var --; \ - UNLOCK (lock); \ - } while (0) - - struct quota_inode_ctx { - int64_t size; - int8_t dirty; - gf_lock_t lock; - struct list_head contribution_head; + int64_t size; + int8_t dirty; + gf_boolean_t updation_status; + gf_lock_t lock; + struct list_head contribution_head; }; typedef struct quota_inode_ctx quota_inode_ctx_t; struct inode_contribution { struct list_head contri_list; - int64_t contribution; - uuid_t gfid; + int64_t contribution; + uuid_t gfid; + gf_lock_t lock; }; 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; - 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 cn; - 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 +mq_dirty_inode_readdir (call_frame_t *, void *, xlator_t *, + int32_t, int32_t, fd_t *, dict_t *); int32_t -quota_dirty_inode_readdir (call_frame_t *, void *, xlator_t *, - int32_t, int32_t, fd_t *); +mq_reduce_parent_size (xlator_t *, loc_t *, int64_t); int32_t -reduce_parent_size (xlator_t *, loc_t *); +mq_rename_update_newpath (xlator_t *, loc_t *); int32_t -quota_rename_update_newpath (xlator_t *, loc_t *, inode_t *); +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 b629a7eb6..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" @@ -27,6 +18,11 @@ #include "marker.h" #include "marker-mem-types.h" #include "marker-quota.h" +#include "marker-quota-helper.h" +#include "marker-common.h" +#include "byte-order.h" + +#define _GF_UID_GID_CHANGED 1 void fini (xlator_t *this); @@ -60,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: @@ -90,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, NULL, NULL); - parent = inode_parent (inode, 0, NULL); - if (!parent) { - goto err; - } - -ignore_parent: ret = inode_path (inode, NULL, &resolvedpath); if (ret < 0) goto err; @@ -116,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; } @@ -130,26 +118,49 @@ marker_trav_parent (marker_local_t *local) { int32_t ret = 0; loc_t loc = {0, }; + inode_t *parent = NULL; + int8_t need_unref = 0; - ret = marker_inode_loc_fill (local->loc.parent, &loc); + if (!local->loc.parent) { + parent = inode_parent (local->loc.inode, NULL, NULL); + if (parent) + need_unref = 1; + } else + parent = local->loc.parent; - if (ret == -1) + ret = marker_inode_loc_fill (parent, &loc); + + if (ret < 0) { + ret = -1; goto out; + } loc_wipe (&local->loc); 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; - - priv = (marker_conf_t *) this->private; - + marker_conf_t *priv = NULL; + const char *path = NULL; + + 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; @@ -158,37 +169,43 @@ marker_error_handler (xlator_t *this) int32_t marker_local_unref (marker_local_t *local) { + int32_t var = 0; + if (local == NULL) return -1; LOCK (&local->lock); { - local->ref--; + var = --local->ref; } UNLOCK (&local->lock); - if (local->ref != 0) + if (var != 0) goto out; loc_wipe (&local->loc); + loc_wipe (&local->parent_loc); + if (local->xdata) + dict_unref (local->xdata); if (local->oplocal) { - loc_wipe (&local->oplocal->loc); - GF_FREE (local->oplocal); + marker_local_unref (local->oplocal); + local->oplocal = NULL; } - GF_FREE (local); + mem_put (local); out: return 0; } int32_t -stat_stampfile (xlator_t *this, marker_conf_t *priv, struct volume_mark **status) +stat_stampfile (xlator_t *this, marker_conf_t *priv, + struct volume_mark **status) { - struct stat buf; - struct volume_mark *vol_mark; + struct stat buf = {0, }; + struct volume_mark *vol_mark = NULL; vol_mark = GF_CALLOC (sizeof (struct volume_mark), 1, - gf_marker_mt_volume_mark); + gf_marker_mt_volume_mark); vol_mark->major = 1; vol_mark->minor = 0; @@ -201,7 +218,7 @@ stat_stampfile (xlator_t *this, marker_conf_t *priv, struct volume_mark **status vol_mark->sec = htonl (buf.st_ctime); vol_mark->usec = htonl (ST_CTIM_NSEC (&buf)/1000); } else - vol_mark->retval = 0; + vol_mark->retval = 1; *status = vol_mark; @@ -210,13 +227,14 @@ stat_stampfile (xlator_t *this, marker_conf_t *priv, struct volume_mark **status 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; + 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; } @@ -224,9 +242,12 @@ marker_getxattr_stampfile_cbk (call_frame_t *frame, xlator_t *this, dict = dict_new (); ret = dict_set_bin (dict, (char *)name, vol_mark, - sizeof (struct volume_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: @@ -242,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; @@ -250,32 +271,59 @@ 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) { - STACK_UNWIND_STRICT (getxattr, frame, op_ret, op_errno, dict); + if (cookie) { + gf_log (this->name, GF_LOG_DEBUG, + "Filtering the quota extended attributes"); + + dict_foreach_fnmatch (dict, "trusted.glusterfs.quota*", + marker_filter_quota_xattr, NULL); + } + + 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_boolean_t ret = _gf_false; + marker_conf_t *priv = NULL; + unsigned long cookie = 0; + + priv = this->private; + + if (priv == NULL || (priv->feature_enabled & GF_XTIME) == 0) + goto wind; gf_log (this->name, GF_LOG_DEBUG, "USER:PID = %d", frame->root->pid); ret = call_from_special_client (frame, this, name); - - if (ret == _gf_false) - STACK_WIND (frame, marker_getxattr_cbk, FIRST_CHILD(this), - FIRST_CHILD(this)->fops->getxattr, loc, name); +wind: + if (ret == _gf_false) { + if (name == NULL) { + /* Signifies that marker translator + * has to filter the quota's xattr's, + * this is to prevent afr from performing + * self healing on marker-quota xattrs' + */ + cookie = 1; + } + STACK_WIND_COOKIE (frame, marker_getxattr_cbk, (void *)cookie, + FIRST_CHILD(this), + FIRST_CHILD(this)->fops->getxattr, loc, + name, xdata); + } return 0; } @@ -299,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; @@ -308,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; @@ -342,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; @@ -351,25 +405,43 @@ 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 marker_gettimeofday (marker_local_t *local) { - struct timeval tv; + struct timeval tv = {0, }; gettimeofday (&tv, NULL); @@ -394,29 +466,41 @@ marker_create_frame (xlator_t *this, marker_local_t *local) } int32_t -update_marks (xlator_t *this, marker_local_t *local) +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; } 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) + int32_t op_ret, int32_t op_errno, inode_t *inode, + struct iatt *buf, struct iatt *preparent, + 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_ERROR, "error occurred " + gf_log (this->name, GF_LOG_TRACE, "error occurred " "while Creating a file %s", strerror (op_errno)); } @@ -425,18 +509,21 @@ 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) + 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_GSYNC) - update_marks (this, local); + if (priv->feature_enabled & GF_XTIME) + marker_xtime_update_marks (this, local); out: marker_local_unref (local); @@ -446,12 +533,18 @@ 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; + marker_conf_t *priv = NULL; + + priv = this->private; - ALLOCATE_OR_GOTO (local, marker_local_t, err); + if (priv->feature_enabled == 0) + goto wind; + + local = mem_get0 (this->local_pool); MARKER_INIT_LOCAL (frame, local); @@ -459,29 +552,29 @@ marker_mkdir (call_frame_t *frame, xlator_t *this, loc_t *loc, mode_t mode, if (ret == -1) 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; } 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) + int32_t op_ret, int32_t op_errno, fd_t *fd, inode_t *inode, + struct iatt *buf, struct iatt *preparent, + 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_ERROR, "error occurred " + gf_log (this->name, GF_LOG_TRACE, "error occurred " "while Creating a file %s", strerror (op_errno)); } @@ -490,18 +583,21 @@ 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) + 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_GSYNC) - update_marks (this, local); + if (priv->feature_enabled & GF_XTIME) + marker_xtime_update_marks (this, local); out: marker_local_unref (local); @@ -511,12 +607,18 @@ 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; + marker_conf_t *priv = NULL; + + priv = this->private; + + 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); @@ -524,13 +626,14 @@ marker_create (call_frame_t *frame, xlator_t *this, loc_t *loc, int32_t flags, if (ret == -1) 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); + STACK_UNWIND_STRICT (create, frame, -1, ENOMEM, NULL, NULL, NULL, NULL, + NULL, NULL); return 0; } @@ -539,13 +642,13 @@ 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; if (op_ret == -1) { - gf_log (this->name, GF_LOG_ERROR, "error occurred " + gf_log (this->name, GF_LOG_TRACE, "error occurred " "while write, %s", strerror (op_errno)); } @@ -553,18 +656,19 @@ 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) + if (op_ret == -1 || local == NULL) goto out; 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_GSYNC) - update_marks (this, local); + if (priv->feature_enabled & GF_XTIME) + marker_xtime_update_marks (this, local); out: marker_local_unref (local); @@ -574,17 +678,23 @@ out: int32_t marker_writev (call_frame_t *frame, - xlator_t *this, - fd_t *fd, - struct iovec *vector, - int32_t count, - off_t offset, - struct iobref *iobref) + xlator_t *this, + fd_t *fd, + struct iovec *vector, + int32_t count, + off_t offset, uint32_t flags, + struct iobref *iobref, 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; - ALLOCATE_OR_GOTO (local, marker_local_t, err); + local = mem_get0 (this->local_pool); MARKER_INIT_LOCAL (frame, local); @@ -592,13 +702,13 @@ marker_writev (call_frame_t *frame, if (ret == -1) goto err; - +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; } @@ -606,14 +716,14 @@ 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) + int32_t op_ret, int32_t op_errno, struct iatt *preparent, + 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_ERROR, "error occurred " + gf_log (this->name, GF_LOG_TRACE, "error occurred " "rmdir %s", strerror (op_errno)); } @@ -622,18 +732,18 @@ 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) + if (op_ret == -1 || local == NULL) goto out; priv = this->private; if (priv->feature_enabled & GF_QUOTA) - reduce_parent_size (this, &local->loc); + mq_reduce_parent_size (this, &local->loc, -1); - if (priv->feature_enabled & GF_GSYNC) - update_marks (this, local); + if (priv->feature_enabled & GF_XTIME) + marker_xtime_update_marks (this, local); out: marker_local_unref (local); @@ -641,12 +751,19 @@ 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; + marker_conf_t *priv = NULL; - ALLOCATE_OR_GOTO (local, marker_local_t, err); + priv = this->private; + + if (priv->feature_enabled == 0) + goto wind; + + local = mem_get0 (this->local_pool); MARKER_INIT_LOCAL (frame, local); @@ -654,12 +771,12 @@ marker_rmdir (call_frame_t *frame, xlator_t *this, loc_t *loc, int flags) if (ret == -1) 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; } @@ -667,14 +784,14 @@ 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) + int32_t op_ret, int32_t op_errno, struct iatt *preparent, + 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_ERROR, + gf_log (this->name, GF_LOG_TRACE, "%s occurred in unlink", strerror (op_errno)); } @@ -683,32 +800,73 @@ 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) + if (op_ret == -1 || local == NULL) goto out; priv = this->private; - if (priv->feature_enabled & GF_QUOTA) - reduce_parent_size (this, &local->loc); + if ((priv->feature_enabled & GF_QUOTA) && (local->ia_nlink == 1)) + mq_reduce_parent_size (this, &local->loc, -1); - if (priv->feature_enabled & GF_GSYNC) - update_marks (this, local); + if (priv->feature_enabled & GF_XTIME) + marker_xtime_update_marks (this, local); out: marker_local_unref (local); return 0; } + +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, + dict_t *xdata) +{ + marker_local_t *local = NULL; + + local = frame->local; + if (op_ret < 0) { + goto err; + } + + 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, local->xflag, + local->xdata); + return 0; +err: + 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; + marker_conf_t *priv = NULL; + + priv = this->private; - ALLOCATE_OR_GOTO (local, marker_local_t, err); + if (priv->feature_enabled == 0) + goto unlink_wind; + 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); @@ -716,27 +874,36 @@ 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, 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; } 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) + int32_t op_ret, int32_t op_errno, inode_t *inode, + struct iatt *buf, struct iatt *preparent, + 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_ERROR, "%s occured while " + gf_log (this->name, GF_LOG_TRACE, "%s occurred while " "linking a file ", strerror (op_errno)); } @@ -745,18 +912,18 @@ 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) + if (op_ret == -1 || local == NULL) goto out; 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_GSYNC) - update_marks (this, local); + if (priv->feature_enabled & GF_XTIME) + marker_xtime_update_marks (this, local); out: marker_local_unref (local); @@ -764,12 +931,19 @@ 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; + marker_conf_t *priv = NULL; + + priv = this->private; + + 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); @@ -777,98 +951,581 @@ marker_link (call_frame_t *frame, xlator_t *this, loc_t *oldloc, loc_t *newloc) if (ret == -1) 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; } 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) +marker_rename_done (call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, dict_t *xdata) { - marker_conf_t *priv = NULL; - marker_local_t *local = NULL; - marker_local_t *oplocal = NULL; + marker_local_t *local = NULL, *oplocal = NULL; + loc_t newloc = {0, }; + marker_conf_t *priv = NULL; - if (op_ret == -1) { - gf_log (this->name, GF_LOG_ERROR, "%s occured while " - "renaming a file ", strerror (op_errno)); - } + local = frame->local; + oplocal = local->oplocal; - local = (marker_local_t *) frame->local; + priv = this->private; frame->local = NULL; - STACK_UNWIND_STRICT (rename, frame, op_ret, op_errno, buf, preoldparent, - postoldparent, prenewparent, postnewparent); + if (op_ret < 0) { + if (local->err == 0) { + local->err = op_errno; + } + + gf_log (this->name, GF_LOG_WARNING, + "inodelk (UNLOCK) failed on path:%s (gfid:%s) (%s)", + local->parent_loc.path, + uuid_utoa (local->parent_loc.inode->gfid), + strerror (op_errno)); + } + + if (local->stub != NULL) { + call_resume (local->stub); + local->stub = NULL; + } else if (local->err != 0) { + STACK_UNWIND_STRICT (rename, frame, -1, local->err, NULL, NULL, + NULL, NULL, NULL, NULL); + } + mq_reduce_parent_size (this, &oplocal->loc, oplocal->contribution); + + if (local->loc.inode != NULL) { + 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 = strrchr (newloc.path, '/'); + if (newloc.name) + newloc.name++; + newloc.parent = inode_ref (local->loc.parent); + + 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); + } + + marker_local_unref (local); + marker_local_unref (oplocal); + return 0; +} + + +int32_t +marker_rename_release_newp_lock (call_frame_t *frame, void *cookie, + xlator_t *this, int32_t op_ret, + int32_t op_errno, dict_t *xdata) +{ + marker_local_t *local = NULL, *oplocal = NULL; + struct gf_flock lock = {0, }; + + local = frame->local; oplocal = local->oplocal; - local->oplocal = NULL; - if (op_ret == -1) + if (op_ret < 0) { + if (local->err == 0) { + local->err = op_errno; + } + + gf_log (this->name, GF_LOG_WARNING, + "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, NULL); goto out; + } + + lock.l_type = F_UNLCK; + lock.l_whence = SEEK_SET; + lock.l_start = 0; + lock.l_len = 0; + lock.l_pid = 0; + + STACK_WIND (frame, + marker_rename_done, + FIRST_CHILD(this), + FIRST_CHILD(this)->fops->inodelk, + this->name, &local->parent_loc, F_SETLKW, &lock, NULL); + +out: + return 0; +} + + +int32_t +marker_rename_release_oldp_lock (call_frame_t *frame, void *cookie, + xlator_t *this, int32_t op_ret, + int32_t op_errno, dict_t *xdata) +{ + marker_local_t *local = NULL, *oplocal = NULL; + struct gf_flock lock = {0, }; + + local = frame->local; + oplocal = local->oplocal; + + if ((op_ret < 0) && (op_errno != ENOATTR)) { + 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; + lock.l_len = 0; + lock.l_pid = 0; + + STACK_WIND (frame, + marker_rename_release_newp_lock, + FIRST_CHILD(this), + FIRST_CHILD(this)->fops->inodelk, + this->name, &oplocal->parent_loc, F_SETLKW, &lock, NULL); + return 0; +} + + +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, + dict_t *xdata) +{ + marker_conf_t *priv = NULL; + marker_local_t *local = NULL; + marker_local_t *oplocal = NULL; + call_stub_t *stub = NULL; + int32_t ret = 0; + char contri_key [512] = {0, }; + loc_t newloc = {0, }; + + local = (marker_local_t *) frame->local; + + if (local != NULL) { + oplocal = local->oplocal; + } priv = this->private; - if (priv->feature_enabled & GF_QUOTA) { - reduce_parent_size (this, &oplocal->loc); - quota_rename_update_newpath (this, &local->loc, - oplocal->loc.inode); + if (op_ret < 0) { + if (local != NULL) { + local->err = op_errno; + } + + gf_log (this->name, GF_LOG_TRACE, "%s occurred while " + "renaming a file ", strerror (op_errno)); } - if (priv->feature_enabled & GF_GSYNC) { - //update marks on oldpath - update_marks (this, oplocal); - update_marks (this, local); + if (priv->feature_enabled & GF_QUOTA) { + if ((op_ret < 0) || (local == NULL)) { + goto quota_err; + } + + stub = fop_rename_cbk_stub (frame, default_rename_cbk, op_ret, + op_errno, buf, preoldparent, + postoldparent, prenewparent, + postnewparent, xdata); + if (stub == NULL) { + local->err = ENOMEM; + goto quota_err; + } + + local->stub = stub; + + GET_CONTRI_KEY (contri_key, oplocal->loc.parent->gfid, ret); + if (ret < 0) { + local->err = ENOMEM; + goto quota_err; + } + + /* 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, xdata); + + if ((op_ret < 0) || (local == NULL)) { + goto out; + } + + 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); + } } + out: - marker_local_unref (local); - marker_local_unref (oplocal); + if (!(priv->feature_enabled & GF_QUOTA)) { + marker_local_unref (local); + marker_local_unref (oplocal); + } + + return 0; + +quota_err: + 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, dict_t *xdata) +{ + marker_local_t *local = NULL, *oplocal = NULL; + char contri_key[512] = {0, }; + int32_t ret = 0; + int64_t *contribution = 0; + + 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 (gfid:%s) " + "failed (%s)", local->loc.path, + uuid_utoa (local->loc.inode->gfid), + strerror (op_errno)); + goto err; + } + + if (local->loc.inode != NULL) { + GET_CONTRI_KEY (contri_key, local->loc.parent->gfid, ret); + if (ret < 0) { + local->err = errno; + goto err; + } + + if (dict_get_bin (dict, contri_key, + (void **) &contribution) == 0) { + local->contribution = ntoh64 (*contribution); + } + } + + STACK_WIND (frame, marker_rename_cbk, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->rename, &oplocal->loc, + &local->loc, NULL); + + return 0; + +err: + marker_rename_release_oldp_lock (frame, NULL, this, 0, 0, NULL); + return 0; +} + + +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, dict_t *xdata) +{ + marker_local_t *local = NULL, *oplocal = NULL; + char contri_key[512] = {0, }; + int32_t ret = 0; + int64_t *contribution = 0; + + 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 (gfid:%s) " + "failed (%s)", oplocal->loc.path, + uuid_utoa (oplocal->loc.inode->gfid), + strerror (op_errno)); + goto err; + } + + GET_CONTRI_KEY (contri_key, oplocal->loc.parent->gfid, ret); + if (ret < 0) { + local->err = errno; + goto err; + } + + if (dict_get_bin (dict, contri_key, (void **) &contribution) == 0) + oplocal->contribution = ntoh64 (*contribution); + + if (local->loc.inode != NULL) { + GET_CONTRI_KEY (contri_key, local->loc.parent->gfid, ret); + if (ret < 0) { + local->err = errno; + goto err; + } + + /* 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, NULL); + } + + return 0; +err: + marker_rename_release_oldp_lock (frame, NULL, this, 0, 0, NULL); return 0; } + +int32_t +marker_get_oldpath_contribution (call_frame_t *frame, void *cookie, + xlator_t *this, int32_t op_ret, + int32_t op_errno, dict_t *xdata) +{ + marker_local_t *local = NULL, *oplocal = NULL; + char contri_key[512] = {0, }; + int32_t ret = 0; + + local = frame->local; + oplocal = local->oplocal; + + if (op_ret < 0) { + local->err = op_errno; + gf_log (this->name, GF_LOG_WARNING, + "cannot hold inodelk on %s (gfid:%s) (%s)", + local->next_lock_on->path, + uuid_utoa (local->next_lock_on->inode->gfid), + strerror (op_errno)); + goto lock_err; + } + + GET_CONTRI_KEY (contri_key, oplocal->loc.parent->gfid, ret); + if (ret < 0) { + local->err = errno; + goto quota_err; + } + + /* 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, 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, NULL); + } else { + marker_rename_release_newp_lock (frame, NULL, this, 0, 0, NULL); + } + + return 0; +} + + +int32_t +marker_rename_inodelk_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, dict_t *xdata) +{ + marker_local_t *local = NULL, *oplocal = NULL; + loc_t *loc = NULL; + struct gf_flock lock = {0, }; + + local = frame->local; + oplocal = local->oplocal; + + if (op_ret < 0) { + if (local->next_lock_on != &oplocal->parent_loc) { + loc = &oplocal->parent_loc; + } else { + loc = &local->parent_loc; + } + + local->err = op_errno; + gf_log (this->name, GF_LOG_WARNING, + "cannot hold inodelk on %s (gfid:%s) (%s)", + loc->path, uuid_utoa (loc->inode->gfid), + strerror (op_errno)); + goto err; + } + + if (local->next_lock_on != NULL) { + lock.l_len = 0; + lock.l_start = 0; + lock.l_type = F_WRLCK; + lock.l_whence = SEEK_SET; + + STACK_WIND (frame, + marker_get_oldpath_contribution, + FIRST_CHILD(this), + FIRST_CHILD(this)->fops->inodelk, + this->name, local->next_lock_on, + F_SETLKW, &lock, NULL); + } else { + marker_get_oldpath_contribution (frame, 0, this, 0, 0, NULL); + } + + return 0; + +err: + 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; - marker_local_t *oplocal = NULL; + int32_t ret = 0; + marker_local_t *local = NULL; + marker_local_t *oplocal = NULL; + marker_conf_t *priv = NULL; + struct gf_flock lock = {0, }; + loc_t *lock_on = NULL; + + priv = this->private; + + 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); frame->local = local; - local->oplocal = oplocal; + local->oplocal = marker_local_ref (oplocal); ret = loc_copy (&local->loc, newloc); - if (ret == -1) + if (ret < 0) goto err; ret = loc_copy (&oplocal->loc, oldloc); - if (ret == -1) + if (ret < 0) + goto err; + + if (!(priv->feature_enabled & GF_QUOTA)) { + goto rename_wind; + } + + ret = mq_inode_loc_fill (NULL, newloc->parent, &local->parent_loc); + if (ret < 0) + goto err; + + ret = mq_inode_loc_fill (NULL, oldloc->parent, &oplocal->parent_loc); + if (ret < 0) goto err; + if ((newloc->inode != NULL) && (newloc->parent != oldloc->parent) + && (uuid_compare (newloc->parent->gfid, + oldloc->parent->gfid) < 0)) { + lock_on = &local->parent_loc; + local->next_lock_on = &oplocal->parent_loc; + } else { + lock_on = &oplocal->parent_loc; + if ((newloc->inode != NULL) && (newloc->parent + != oldloc->parent)) { + local->next_lock_on = &local->parent_loc; + } + } + + lock.l_len = 0; + lock.l_start = 0; + lock.l_type = F_WRLCK; + lock.l_whence = SEEK_SET; + + STACK_WIND (frame, + marker_rename_inodelk_cbk, + FIRST_CHILD(this), + FIRST_CHILD(this)->fops->inodelk, + this->name, lock_on, + 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; } @@ -876,14 +1533,14 @@ 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) + 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_ERROR, "%s occured while " + gf_log (this->name, GF_LOG_TRACE, "%s occurred while " "truncating a file ", strerror (op_errno)); } @@ -892,18 +1549,18 @@ 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) + if (op_ret == -1 || local == NULL) goto out; 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_GSYNC) - update_marks (this, local); + if (priv->feature_enabled & GF_XTIME) + marker_xtime_update_marks (this, local); out: marker_local_unref (local); @@ -912,12 +1569,19 @@ 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; + marker_conf_t *priv = NULL; + + priv = this->private; + + 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); @@ -925,12 +1589,12 @@ marker_truncate (call_frame_t *frame, xlator_t *this, loc_t *loc, off_t offset) if (ret == -1) 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; } @@ -938,14 +1602,14 @@ 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) + 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_ERROR, "%s occured while " + gf_log (this->name, GF_LOG_TRACE, "%s occurred while " "truncating a file ", strerror (op_errno)); } @@ -954,18 +1618,18 @@ 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) + if (op_ret == -1 || local == NULL) goto out; 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_GSYNC) - update_marks (this, local); + if (priv->feature_enabled & GF_XTIME) + marker_xtime_update_marks (this, local); out: marker_local_unref (local); @@ -973,12 +1637,19 @@ 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; + marker_conf_t *priv = NULL; + + priv = this->private; + + 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); @@ -986,12 +1657,12 @@ marker_ftruncate (call_frame_t *frame, xlator_t *this, fd_t *fd, off_t offset) if (ret == -1) 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; } @@ -999,15 +1670,15 @@ err: 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) + int32_t op_ret, int32_t op_errno, inode_t *inode, + struct iatt *buf, struct iatt *preparent, + 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_ERROR, "%s occured while " + gf_log (this->name, GF_LOG_TRACE, "%s occurred while " "creating symlinks ", strerror (op_errno)); } @@ -1016,18 +1687,21 @@ 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) + 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) - initiate_quota_txn (this, &local->loc); + mq_set_inode_xattr (this, &local->loc); - if (priv->feature_enabled & GF_GSYNC) - update_marks (this, local); + if (priv->feature_enabled & GF_XTIME) + marker_xtime_update_marks (this, local); out: marker_local_unref (local); @@ -1036,12 +1710,18 @@ 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; + marker_conf_t *priv = NULL; + + priv = this->private; - ALLOCATE_OR_GOTO (local, marker_local_t, err); + if (priv->feature_enabled == 0) + goto wind; + + local = mem_get0 (this->local_pool); MARKER_INIT_LOCAL (frame, local); @@ -1049,28 +1729,29 @@ marker_symlink (call_frame_t *frame, xlator_t *this, const char *linkpath, if (ret == -1) 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; } 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) + int32_t op_ret, int32_t op_errno, inode_t *inode, + struct iatt *buf, struct iatt *preparent, + 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_ERROR, "%s occured while " + gf_log (this->name, GF_LOG_TRACE, "%s occurred while " "creating symlinks ", strerror (op_errno)); } @@ -1079,15 +1760,22 @@ 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) + 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_GSYNC) - update_marks (this, local); + if ((priv->feature_enabled & GF_QUOTA) && (S_ISREG (local->mode))) { + mq_set_inode_xattr (this, &local->loc); + } + + if (priv->feature_enabled & GF_XTIME) + marker_xtime_update_marks (this, local); out: marker_local_unref (local); @@ -1096,26 +1784,239 @@ 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; + marker_conf_t *priv = NULL; - ALLOCATE_OR_GOTO (local, marker_local_t, err); + priv = this->private; + + if (priv->feature_enabled == 0) + goto wind; + + local = mem_get0 (this->local_pool); MARKER_INIT_LOCAL (frame, local); ret = loc_copy (&local->loc, loc); + local->mode = mode; + if (ret == -1) 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; } @@ -1146,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; @@ -1154,7 +2055,7 @@ call_from_sp_client_to_reset_tmfile (call_frame_t *frame, } if (data->len == 0 || (data->len == 5 && - memcmp (data->data, "RESET", 5) == 0)) { + memcmp (data->data, "RESET", 5) == 0)) { fd = open (priv->timestamp_file, O_WRONLY|O_TRUNC); if (fd != -1) { /* TODO check whether the O_TRUNC would update the @@ -1175,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; } @@ -1183,29 +2084,29 @@ 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_ERROR, "%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) + if (op_ret == -1 || local == NULL) goto out; priv = this->private; - if (priv->feature_enabled == GF_GSYNC) - update_marks (this, local); + if (priv->feature_enabled & GF_XTIME) + marker_xtime_update_marks (this, local); out: marker_local_unref (local); @@ -1214,16 +2115,22 @@ 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; + marker_conf_t *priv = NULL; + + priv = this->private; + + if (priv->feature_enabled == 0) + goto wind; ret = call_from_sp_client_to_reset_tmfile (frame, this, 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); @@ -1231,12 +2138,12 @@ marker_setxattr (call_frame_t *frame, xlator_t *this, loc_t *loc, dict_t *dict, if (ret == -1) 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; } @@ -1244,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_ERROR, "%s occured while " + gf_log (this->name, GF_LOG_TRACE, "%s occurred while " "creating symlinks ", strerror (op_errno)); } @@ -1258,15 +2165,15 @@ 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) + if (op_ret == -1 || local == NULL) goto out; priv = this->private; - if (priv->feature_enabled == GF_GSYNC) - update_marks (this, local); + if (priv->feature_enabled & GF_XTIME) + marker_xtime_update_marks (this, local); out: marker_local_unref (local); @@ -1275,16 +2182,22 @@ 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; + marker_conf_t *priv = NULL; + + priv = this->private; + + if (priv->feature_enabled == 0) + goto wind; ret = call_from_sp_client_to_reset_tmfile (frame, this, 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); @@ -1292,12 +2205,12 @@ marker_fsetxattr (call_frame_t *frame, xlator_t *this, fd_t *fd, dict_t *dict, if (ret == -1) 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; } @@ -1305,14 +2218,14 @@ 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) + int32_t op_ret, int32_t op_errno, struct iatt *statpre, + 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)); } @@ -1321,15 +2234,15 @@ 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) + if (op_ret == -1 || local == NULL) goto out; priv = this->private; - if (priv->feature_enabled == GF_GSYNC) - update_marks (this, local); + if (priv->feature_enabled & GF_XTIME) + marker_xtime_update_marks (this, local); out: marker_local_unref (local); @@ -1339,12 +2252,18 @@ 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; + marker_conf_t *priv = NULL; + + priv = this->private; + + 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); @@ -1352,12 +2271,12 @@ marker_fsetattr (call_frame_t *frame, xlator_t *this, fd_t *fd, if (ret == -1) 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; } @@ -1365,31 +2284,34 @@ 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) + int32_t op_ret, int32_t op_errno, struct iatt *statpre, + 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 " - "creating symlinks ", strerror (op_errno)); - } - local = (marker_local_t *) frame->local; frame->local = NULL; + if (op_ret == -1) { + gf_log (this->name, ((op_errno == ENOENT) ? GF_LOG_DEBUG : + GF_LOG_ERROR), + "%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) + if (op_ret == -1 || local == NULL) goto out; priv = this->private; - if (priv->feature_enabled == GF_GSYNC) - update_marks (this, local); + if (priv->feature_enabled & GF_XTIME) + marker_xtime_update_marks (this, local); out: marker_local_unref (local); @@ -1398,12 +2320,18 @@ 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; + marker_conf_t *priv = NULL; - ALLOCATE_OR_GOTO (local, marker_local_t, err); + priv = this->private; + + if (priv->feature_enabled == 0) + goto wind; + + local = mem_get0 (this->local_pool); MARKER_INIT_LOCAL (frame, local); @@ -1411,12 +2339,12 @@ marker_setattr (call_frame_t *frame, xlator_t *this, loc_t *loc, if (ret == -1) 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; } @@ -1424,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)); } @@ -1438,15 +2366,15 @@ 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) + if (op_ret == -1 || local == NULL) goto out; priv = this->private; - if (priv->feature_enabled == GF_GSYNC) - update_marks (this, local); + if (priv->feature_enabled & GF_XTIME) + marker_xtime_update_marks (this, local); out: marker_local_unref (local); @@ -1455,12 +2383,18 @@ 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; + marker_conf_t *priv = NULL; + + priv = this->private; - ALLOCATE_OR_GOTO (local, marker_local_t, err); + if (priv->feature_enabled == 0) + goto wind; + + local = mem_get0 (this->local_pool); MARKER_INIT_LOCAL (frame, local); @@ -1468,12 +2402,12 @@ marker_removexattr (call_frame_t *frame, xlator_t *this, loc_t *loc, if (ret == -1) 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; } @@ -1484,7 +2418,6 @@ marker_lookup_cbk (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) { - struct iatt stat_buf; marker_conf_t *priv = NULL; marker_local_t *local = NULL; @@ -1493,12 +2426,6 @@ marker_lookup_cbk (call_frame_t *frame, void *cookie, xlator_t *this, strerror (op_errno)); } - priv = this->private; - - dict_ref (dict); - - memmove (&stat_buf, buf, sizeof (struct iatt)); - local = (marker_local_t *) frame->local; frame->local = NULL; @@ -1506,18 +2433,27 @@ marker_lookup_cbk (call_frame_t *frame, void *cookie, xlator_t *this, STACK_UNWIND_STRICT (lookup, frame, op_ret, op_errno, inode, buf, dict, postparent); - if (op_ret == -1) + 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, stat_buf); + mq_xattr_state (this, &local->loc, dict, *buf); } out: marker_local_unref (local); - dict_unref (dict); - return 0; } @@ -1526,12 +2462,15 @@ marker_lookup (call_frame_t *frame, xlator_t *this, loc_t *loc, dict_t *xattr_req) { int32_t ret = 0; - marker_conf_t *priv = NULL; marker_local_t *local = NULL; + marker_conf_t *priv = NULL; priv = this->private; - ALLOCATE_OR_GOTO (local, marker_local_t, err); + if (priv->feature_enabled == 0) + goto wind; + + local = mem_get0 (this->local_pool); MARKER_INIT_LOCAL (frame, local); @@ -1539,9 +2478,9 @@ marker_lookup (call_frame_t *frame, xlator_t *this, if (ret == -1) goto err; - if (priv->feature_enabled & GF_QUOTA) - quota_req_xattr (this, loc, xattr_req); - + if ((priv->feature_enabled & GF_QUOTA) && 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); return 0; @@ -1551,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) { @@ -1563,7 +2545,7 @@ mem_acct_init (xlator_t *this) if (ret != 0) { gf_log(this->name, GF_LOG_ERROR, "Memory accounting init" - "failed"); + "failed"); return ret; } @@ -1572,19 +2554,15 @@ mem_acct_init (xlator_t *this) int32_t -init_gsync_priv (xlator_t *this) +init_xtime_priv (xlator_t *this, dict_t *options) { - dict_t *options = NULL; data_t *data = NULL; - int32_t ret = 0; + int32_t ret = -1; marker_conf_t *priv = NULL; - if (!this) { - ret = -1; - goto out; - } - - options = this->options; + GF_VALIDATE_OR_GOTO ("marker", this, out); + GF_VALIDATE_OR_GOTO (this->name, options, out); + GF_VALIDATE_OR_GOTO (this->name, this->private, out); priv = this->private; @@ -1593,12 +2571,14 @@ init_gsync_priv (xlator_t *this) ret = uuid_parse (priv->volume_uuid, priv->volume_uuid_bin); if (ret == -1) { - gf_log (this->name, GF_LOG_ERROR, "invalid volume uuid %s", priv->volume_uuid); + gf_log (this->name, GF_LOG_ERROR, + "invalid volume uuid %s", priv->volume_uuid); goto out; } ret = gf_asprintf (& (priv->marker_xattr), "%s.%s.%s", - MARKER_XATTR_PREFIX, priv->volume_uuid, XTIME); + MARKER_XATTR_PREFIX, priv->volume_uuid, + XTIME); if (ret == -1){ priv->marker_xattr = NULL; @@ -1642,12 +2622,111 @@ out: return ret; } +void +marker_xtime_priv_cleanup (xlator_t *this) +{ + marker_conf_t *priv = NULL; + + GF_VALIDATE_OR_GOTO ("marker", this, out); + + priv = (marker_conf_t *) this->private; + + GF_VALIDATE_OR_GOTO (this->name, priv, out); + + GF_FREE (priv->volume_uuid); + + GF_FREE (priv->timestamp_file); + + GF_FREE (priv->marker_xattr); +out: + return; +} + +void +marker_priv_cleanup (xlator_t *this) +{ + marker_conf_t *priv = NULL; + + GF_VALIDATE_OR_GOTO ("marker", this, out); + + priv = (marker_conf_t *) this->private; + + GF_VALIDATE_OR_GOTO (this->name, priv, out); + + marker_xtime_priv_cleanup (this); + + LOCK_DESTROY (&priv->lock); + + GF_FREE (priv); +out: + return; +} + +int32_t +reconfigure (xlator_t *this, dict_t *options) +{ + int32_t ret = 0; + data_t *data = NULL; + gf_boolean_t flag = _gf_false; + marker_conf_t *priv = NULL; + + GF_ASSERT (this); + GF_ASSERT (this->private); + + priv = this->private; + + priv->feature_enabled = 0; + + GF_VALIDATE_OR_GOTO (this->name, options, out); + + data = dict_get (options, "quota"); + if (data) { + ret = gf_string2boolean (data->data, &flag); + if (ret == 0 && flag == _gf_true) { + ret = init_quota_priv (this); + if (ret < 0) { + gf_log (this->name, GF_LOG_WARNING, + "failed to initialize quota private"); + } else { + priv->feature_enabled |= GF_QUOTA; + } + } + } + + data = dict_get (options, "xtime"); + if (data) { + ret = gf_string2boolean (data->data, &flag); + if (ret == 0 && flag == _gf_true) { + marker_xtime_priv_cleanup (this); + + ret = init_xtime_priv (this, options); + if (ret < 0) { + gf_log (this->name, GF_LOG_WARNING, + "failed to initialize xtime private, " + "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 ret; +} + + int32_t init (xlator_t *this) { dict_t *options = NULL; data_t *data = NULL; int32_t ret = 0; + gf_boolean_t flag = _gf_false; marker_conf_t *priv = NULL; if (!this->children) { @@ -1670,38 +2749,49 @@ init (xlator_t *this) priv->feature_enabled = 0; + LOCK_INIT (&priv->lock); + data = dict_get (options, "quota"); if (data) { - if (strcmp (data->data, "on") == 0) { - priv->feature_enabled |= GF_QUOTA; + ret = gf_string2boolean (data->data, &flag); + if (ret == 0 && flag == _gf_true) { ret = init_quota_priv (this); if (ret < 0) goto err; + + priv->feature_enabled |= GF_QUOTA; } } - data = dict_get (options, "gsync"); + data = dict_get (options, "xtime"); if (data) { - if (strcmp (data->data, "on") == 0) { - priv->feature_enabled |= GF_GSYNC; - ret = init_gsync_priv (this); + ret = gf_string2boolean (data->data, &flag); + if (ret == 0 && flag == _gf_true) { + ret = init_xtime_priv (this, options); if (ret < 0) 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; } } - if (priv->feature_enabled == 0) { - gf_log (this->name, GF_LOG_WARNING, - "Marker translator in the volfile " - "but no functionality is enabled " - "failing marker init()"); - + 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: - fini (this); + marker_priv_cleanup (this); return -1; } @@ -1709,12 +2799,18 @@ err: int32_t marker_forget (xlator_t *this, inode_t *inode) { - marker_inode_ctx_t *ctx = NULL; + marker_inode_ctx_t *ctx = NULL; + uint64_t value = 0; - if (inode_ctx_get (inode, this, (uint64_t *) &ctx) != 0) + if (inode_ctx_del (inode, this, &value) != 0) goto out; - quota_forget (this, ctx->quota_ctx); + ctx = (marker_inode_ctx_t *)(unsigned long)value; + if (ctx == NULL) { + goto out; + } + + mq_forget (this, ctx->quota_ctx); GF_FREE (ctx); out: @@ -1724,31 +2820,7 @@ out: void fini (xlator_t *this) { - marker_conf_t *priv = NULL; - - priv = (marker_conf_t *) this->private; - - if (priv == NULL) - goto out; - - if (priv->volume_uuid != NULL) - GF_FREE (priv->volume_uuid); - - if (priv->timestamp_file != NULL) - GF_FREE (priv->timestamp_file); - - if (priv->marker_xattr != NULL) - GF_FREE (priv->marker_xattr); - - if (priv->size_key != NULL) - GF_FREE (priv->size_key); - - if (priv->dirty_key != NULL) - GF_FREE (priv->dirty_key); - - GF_FREE (priv); -out: - return ; + marker_priv_cleanup (this); } struct xlator_fops fops = { @@ -1769,17 +2841,22 @@ 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 = { - .forget = marker_forget + .forget = marker_forget }; struct volume_options options[] = { {.key = {"volume-uuid"}}, {.key = {"timestamp-file"}}, {.key = {"quota"}}, - {.key = {"gsync"}}, + {.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 5602456ff..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 @@ -28,6 +19,7 @@ #include "xlator.h" #include "defaults.h" #include "uuid.h" +#include "call-stub.h" #define MARKER_XATTR_PREFIX "trusted.glusterfs" #define XTIME "xtime" @@ -36,8 +28,9 @@ #define TIMESTAMP_FILE "timestamp-file" enum { - GF_QUOTA=1, - GF_GSYNC=2 + GF_QUOTA = 1, + GF_XTIME = 2, + GF_XTIME_GSYNC_FORCE = 4, }; /*initialize the local variable*/ @@ -46,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) @@ -61,17 +56,67 @@ 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; + mode_t mode; + int32_t err; + 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; }; @@ -85,8 +130,9 @@ struct marker_conf{ uuid_t volume_uuid_bin; char *timestamp_file; char *marker_xattr; + uint64_t quota_lk_owner; + gf_lock_t lock; }; typedef struct marker_conf marker_conf_t; -int32_t k; #endif |
