diff options
-rw-r--r-- | libglusterfs/src/gfdb/gfdb_sqlite3_helper.c | 6 | ||||
-rwxr-xr-x | tests/basic/tier/tier_lookup_heal.t | 72 | ||||
-rw-r--r-- | xlators/features/changetimerecorder/src/Makefile.am | 4 | ||||
-rw-r--r-- | xlators/features/changetimerecorder/src/changetimerecorder.c | 344 | ||||
-rw-r--r-- | xlators/features/changetimerecorder/src/ctr-helper.h | 143 | ||||
-rw-r--r-- | xlators/features/changetimerecorder/src/ctr-xlator-ctx.c | 370 | ||||
-rw-r--r-- | xlators/features/changetimerecorder/src/ctr-xlator-ctx.h | 86 | ||||
-rw-r--r-- | xlators/features/changetimerecorder/src/ctr_mem_types.h | 2 |
8 files changed, 1021 insertions, 6 deletions
diff --git a/libglusterfs/src/gfdb/gfdb_sqlite3_helper.c b/libglusterfs/src/gfdb/gfdb_sqlite3_helper.c index 4b70b49419d..03ebb1f1c8a 100644 --- a/libglusterfs/src/gfdb/gfdb_sqlite3_helper.c +++ b/libglusterfs/src/gfdb/gfdb_sqlite3_helper.c @@ -373,7 +373,8 @@ gf_sql_insert_link (gf_sql_connection_t *sql_conn, /*Execute the prepare statement*/ if (sqlite3_step (insert_stmt) != SQLITE_DONE) { gf_log (GFDB_STR_SQLITE3, GF_LOG_ERROR, - "Failed executing the prepared stmt %s : %s", + "Failed executing the prepared stmt %s %s %s %s %s : %s", + gfid, pargfid, basename, basepath, insert_str, sqlite3_errmsg (sql_conn->sqlite3_db_conn)); ret = -1; @@ -568,7 +569,8 @@ gf_sql_insert_write_wind_time (gf_sql_connection_t *sql_conn, /*Execute the prepare statement*/ if (sqlite3_step (insert_stmt) != SQLITE_DONE) { gf_log (GFDB_STR_SQLITE3, GF_LOG_ERROR, - "Failed executing the prepared stmt %s : %s", + "Failed executing the prepared stmt GFID:%s %s : %s", + gfid, insert_str, sqlite3_errmsg (sql_conn->sqlite3_db_conn)); ret = -1; diff --git a/tests/basic/tier/tier_lookup_heal.t b/tests/basic/tier/tier_lookup_heal.t new file mode 100755 index 00000000000..2b778f749f9 --- /dev/null +++ b/tests/basic/tier/tier_lookup_heal.t @@ -0,0 +1,72 @@ +#!/bin/bash + +. $(dirname $0)/../../include.rc +. $(dirname $0)/../../volume.rc + +LAST_BRICK=1 +CACHE_BRICK_FIRST=2 +CACHE_BRICK_LAST=3 +PROMOTE_TIMEOUT=5 + +function file_on_fast_tier { + local ret="1" + + s1=$(md5sum $1) + s2=$(md5sum $B0/${V0}${CACHE_BRICK_FIRST}/$1) + + if [ -e $B0/${V0}${CACHE_BRICK_FIRST}/$1 ] && ! [ "$s1" == "$s2" ]; then + echo "0" + else + echo "1" + fi +} + +cleanup + + +TEST glusterd +TEST pidof glusterd + +TEST $CLI volume create $V0 replica 2 $H0:$B0/${V0}{0..$LAST_BRICK} +TEST $CLI volume start $V0 +TEST $GFS --volfile-id=/$V0 --volfile-server=$H0 $M0; + +# Create files before CTR xlator is on. +cd $M0 +TEST stat . +TEST touch file1 +TEST stat file1 + +# gf_file_tb and gf_flink_tb should be empty +ENTRY_COUNT=$(echo "select * from gf_file_tb; select * from gf_flink_tb;" | \ + sqlite3 $B0/${V0}$LAST_BRICK/.glusterfs/${V0}$LAST_BRICK.db | wc -l ) +TEST [ $ENTRY_COUNT -eq 0 ] + + +#Attach tier and switch ON CTR Xlator. +TEST $CLI volume attach-tier $V0 replica 2 $H0:$B0/${V0}$CACHE_BRICK_FIRST $H0:$B0/${V0}$CACHE_BRICK_LAST +TEST $CLI volume set $V0 features.ctr-enabled on +TEST $CLI volume set $V0 cluster.tier-demote-frequency 4 +TEST $CLI volume set $V0 cluster.tier-promote-frequency 4 +TEST $CLI volume set $V0 cluster.read-freq-threshold 0 +TEST $CLI volume set $V0 cluster.write-freq-threshold 0 +TEST $CLI volume set $V0 performance.quick-read off +TEST $CLI volume set $V0 performance.io-cache off + +#The lookup should heal the database. +TEST ls file1 + +# gf_file_tb and gf_flink_tb should NOT be empty +ENTRY_COUNT=$(echo "select * from gf_file_tb; select * from gf_flink_tb;" | \ + sqlite3 $B0/${V0}$LAST_BRICK/.glusterfs/${V0}$LAST_BRICK.db | wc -l ) +TEST [ $ENTRY_COUNT -eq 2 ] + +# Heat-up the file +uuidgen > file1 +TEST $CLI volume rebalance $V0 tier start +sleep 5 + +#Check if the file is promoted +EXPECT_WITHIN $PROMOTE_TIMEOUT "0" file_on_fast_tier file1 + +cleanup diff --git a/xlators/features/changetimerecorder/src/Makefile.am b/xlators/features/changetimerecorder/src/Makefile.am index e79be53c063..630dd8e6e15 100644 --- a/xlators/features/changetimerecorder/src/Makefile.am +++ b/xlators/features/changetimerecorder/src/Makefile.am @@ -7,12 +7,12 @@ endif changetimerecorder_la_LDFLAGS = -module -avoid-version -changetimerecorder_la_SOURCES = changetimerecorder.c ctr-helper.c +changetimerecorder_la_SOURCES = changetimerecorder.c ctr-helper.c ctr-xlator-ctx.c changetimerecorder_la_LIBADD = $(top_builddir)/libglusterfs/src/libglusterfs.la\ $(top_builddir)/libglusterfs/src/gfdb/libgfdb.la -noinst_HEADERS = changetimerecorder.h ctr_mem_types.h ctr-helper.h +noinst_HEADERS = changetimerecorder.h ctr_mem_types.h ctr-helper.h ctr-xlator-ctx.h AM_CPPFLAGS = $(GF_CPPFLAGS) -I$(top_srcdir)/libglusterfs/src \ -I$(top_srcdir)/libglusterfs/src/gfdb \ diff --git a/xlators/features/changetimerecorder/src/changetimerecorder.c b/xlators/features/changetimerecorder/src/changetimerecorder.c index fd57a445e08..dc23132b7f3 100644 --- a/xlators/features/changetimerecorder/src/changetimerecorder.c +++ b/xlators/features/changetimerecorder/src/changetimerecorder.c @@ -13,6 +13,308 @@ #include "gfdb_sqlite3.h" #include "ctr-helper.h" +/*******************************inode forget***********************************/ + +int +ctr_forget (xlator_t *this, inode_t *inode) +{ + fini_ctr_xlator_ctx (this, inode); + return 0; +} + +/************************** Look up heal **************************************/ +/* +Problem: The CTR xlator records file meta (heat/hardlinks) +into the data. This works fine for files which are created +after ctr xlator is switched ON. But for files which were +created before CTR xlator is ON, CTR xlator is not able to +record either of the meta i.e heat or hardlinks. Thus making +those files immune to promotions/demotions. + +Solution: The solution that is implemented in this patch is +do ctr-db heal of all those pre-existent files, using named lookup. +For this purpose we use the inode-xlator context variable option +in gluster. +The inode-xlator context variable for ctr xlator will have the +following, + a. A Lock for the context variable + b. A hardlink list: This list represents the successful looked + up hardlinks. +These are the scenarios when the hardlink list is updated: +1) Named-Lookup: Whenever a named lookup happens on a file, in the + wind path we copy all required hardlink and inode information to + ctr_db_record structure, which resides in the frame->local variable. + We dont update the database in wind. During the unwind, we read the + information from the ctr_db_record and , + Check if the inode context variable is created, if not we create it. + Check if the hard link is there in the hardlink list. + If its not there we add it to the list and send a update to the + database using libgfdb. + Please note: The database transaction can fail(and we ignore) as there + already might be a record in the db. This update to the db is to heal + if its not there. + If its there in the list we ignore it. +2) Inode Forget: Whenever an inode forget hits we clear the hardlink list in + the inode context variable and delete the inode context variable. + Please note: An inode forget may happen for two reason, + a. when the inode is delete. + b. the in-memory inode is evicted from the inode table due to cache limits. +3) create: whenever a create happens we create the inode context variable and + add the hardlink. The database updation is done as usual by ctr. +4) link: whenever a hardlink is created for the inode, we create the inode + context variable, if not present, and add the hardlink to the list. +5) unlink: whenever a unlink happens we delete the hardlink from the list. +6) mknod: same as create. +7) rename: whenever a rename happens we update the hardlink in list. if the + hardlink was not present for updation, we add the hardlink to the list. + +What is pending: +1) This solution will only work for named lookups. +2) We dont track afr-self-heal/dht-rebalancer traffic for healing. + +*/ + + +/* This function doesnot write anything to the db, + * just created the local variable + * for the frame and sets values for the ctr_db_record */ +static inline int +ctr_lookup_wind(call_frame_t *frame, + xlator_t *this, + gf_ctr_inode_context_t *ctr_inode_cx) +{ + int ret = -1; + gf_ctr_private_t *_priv = NULL; + gf_ctr_local_t *ctr_local = NULL; + + GF_ASSERT(frame); + GF_ASSERT(frame->root); + GF_ASSERT(this); + IS_CTR_INODE_CX_SANE(ctr_inode_cx); + + _priv = this->private; + GF_ASSERT (_priv); + + if (_priv->ctr_record_wind && ctr_inode_cx->ia_type != IA_IFDIR) { + + frame->local = init_ctr_local_t (this); + if (!frame->local) { + gf_log (this->name, GF_LOG_ERROR, + "WIND: Error while creating ctr local"); + goto out; + }; + ctr_local = frame->local; + ctr_local->client_pid = frame->root->pid; + /*Definately no internal fops will reach here*/ + ctr_local->is_internal_fop = _gf_false; + /*Dont record counters*/ + CTR_DB_REC(ctr_local).do_record_counters = _gf_false; + /*Don't record time at all*/ + CTR_DB_REC(ctr_local).do_record_times = _gf_false; + + /*Copy gfid into db record*/ + gf_uuid_copy (CTR_DB_REC(ctr_local).gfid, + *(ctr_inode_cx->gfid)); + + /* Set fop_path and fop_type, required by libgfdb to make + * decision while inserting the record */ + CTR_DB_REC(ctr_local).gfdb_fop_path = ctr_inode_cx->fop_path; + CTR_DB_REC(ctr_local).gfdb_fop_type = ctr_inode_cx->fop_type; + + /* Copy hard link info*/ + gf_uuid_copy (CTR_DB_REC(ctr_local).pargfid, + *((NEW_LINK_CX(ctr_inode_cx))->pargfid)); + strcpy (CTR_DB_REC(ctr_local).file_name, + NEW_LINK_CX(ctr_inode_cx)->basename); + strcpy (CTR_DB_REC(ctr_local).file_path, + NEW_LINK_CX(ctr_inode_cx)->basepath); + + } + + ret = 0; + +out: + + if (ret) { + free_ctr_local (ctr_local); + frame->local = NULL; + } + + return ret; +} + + +/* This function inserts the ctr_db_record populated by ctr_lookup_wind + * in to the db. It also destroys the frame->local created by ctr_lookup_wind */ +static inline int +ctr_lookup_unwind (call_frame_t *frame, + xlator_t *this) +{ + int ret = -1; + gf_ctr_private_t *_priv = NULL; + gf_ctr_local_t *ctr_local = NULL; + + GF_ASSERT(frame); + GF_ASSERT(this); + + _priv = this->private; + GF_ASSERT (_priv); + + GF_ASSERT(_priv->_db_conn); + + ctr_local = frame->local; + + if (ctr_local && (ctr_local->ia_inode_type != IA_IFDIR)) { + + ret = insert_record(_priv->_db_conn, + &ctr_local->gfdb_db_record); + if (ret == -1) { + gf_log(this->name, GF_LOG_ERROR, "UNWIND: Error" + "filling ctr local"); + goto out; + } + } + ret = 0; +out: + free_ctr_local (ctr_local); + frame->local = NULL; + return ret; +} + +/****************************************************************************** + * + * FOPS HANDLING BELOW + * + * ***************************************************************************/ + +/****************************LOOKUP********************************************/ + + +int32_t +ctr_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) +{ + int ret = -1; + ctr_xlator_ctx_t *ctr_xlator_ctx; + gf_ctr_local_t *ctr_local = NULL; + + CTR_IS_DISABLED_THEN_GOTO(this, out); + CTR_IF_INTERNAL_FOP_THEN_GOTO (frame, dict, out); + + /* if the lookup failed lookup dont do anything*/ + if (op_ret == -1) { + gf_log (this->name, GF_LOG_TRACE, "lookup failed with %s", + strerror (op_errno)); + goto out; + } + + /* Ignore directory lookups */ + if (inode->ia_type == IA_IFDIR) { + goto out; + } + + /* if frame local was not set by the ctr_lookup() + * so dont so anything*/ + if (!frame->local) { + goto out; + } + + ctr_local = frame->local; + /*Assign the proper inode type*/ + ctr_local->ia_inode_type = inode->ia_type; + + /* if its a first entry + * then mark the ctr_record for create + * A create will attempt a file and a hard link created in the db*/ + ctr_xlator_ctx = get_ctr_xlator_ctx (this, inode); + if (!ctr_xlator_ctx) { + CTR_DB_REC(ctr_local).gfdb_fop_type = GFDB_FOP_CREATE_WRITE; + } + + /* Copy the correct gfid from resolved inode */ + gf_uuid_copy (CTR_DB_REC(ctr_local).gfid, inode->gfid); + + /* Add hard link to the list */ + ret = add_hard_link_ctx (frame, this, inode); + if (ret < 0) { + gf_log (this->name, GF_LOG_TRACE, "Failed adding hard link"); + goto out; + } + + /* Inserts the ctr_db_record populated by ctr_lookup_wind + * in to the db. It also destroys the frame->local + * created by ctr_lookup_wind */ + ret = ctr_lookup_unwind(frame, this); + if (ret) { + gf_log (this->name, GF_LOG_TRACE, + "Failed inserting link wind"); + } + + +out: + free_ctr_local ((gf_ctr_local_t *)frame->local); + frame->local = NULL; + + STACK_UNWIND_STRICT (lookup, frame, op_ret, op_errno, inode, buf, + dict, postparent); + + return 0; +} + + + +int32_t +ctr_lookup (call_frame_t *frame, xlator_t *this, + loc_t *loc, dict_t *xdata) +{ + gf_ctr_inode_context_t ctr_inode_cx; + gf_ctr_inode_context_t *_inode_cx = &ctr_inode_cx; + gf_ctr_link_context_t ctr_link_cx; + gf_ctr_link_context_t *_link_cx = &ctr_link_cx; + int ret = -1; + + CTR_IS_DISABLED_THEN_GOTO(this, out); + CTR_IF_INTERNAL_FOP_THEN_GOTO (frame, xdata, out); + + GF_ASSERT(frame); + GF_ASSERT(frame->root); + + /* Dont handle nameless lookups*/ + if (!loc->parent) + goto out; + + /*fill ctr link context*/ + FILL_CTR_LINK_CX(_link_cx, loc->pargfid, loc->name, + loc->path); + + /* Fill ctr inode context*/ + /* IA_IFREG : We assume its a file in the wind + * but in the unwind we are sure what the inode is a file + * or directory + * gfid: we are just filling loc->gfid which is not correct. + * In unwind we fill the correct gfid for successful lookup*/ + FILL_CTR_INODE_CONTEXT(_inode_cx, IA_IFREG, + loc->gfid, _link_cx, NULL, + GFDB_FOP_DENTRY_WRITE, GFDB_FOP_WIND); + + /* Create the frame->local and populate ctr_db_record + * No writing to the db yet */ + ret = ctr_lookup_wind(frame, this, _inode_cx); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, + "Failed inserting link wind"); + } + +out: + STACK_WIND (frame, ctr_lookup_cbk, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->lookup, loc, xdata); + return 0; +} + + + + /****************************WRITEV********************************************/ int32_t ctr_writev_cbk (call_frame_t *frame, void *cookie, xlator_t *this, @@ -415,6 +717,15 @@ ctr_rename (call_frame_t *frame, xlator_t *this, loc_t *oldloc, if (ret) { gf_log (this->name, GF_LOG_ERROR, "Failed inserting rename wind"); + } else { + /* We are doing updation of hard link in inode context in wind + * As we dont get the "inode" in the call back for rename */ + ret = update_hard_link_ctx (frame, this, oldloc->inode); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, + "Failed updating hard link in" + "ctr inode context"); + } } out: @@ -509,6 +820,15 @@ ctr_unlink (call_frame_t *frame, xlator_t *this, if (ret) { gf_log (this->name, GF_LOG_ERROR, "Failed inserting unlink wind"); + } else { + /* We are doing delete of hard link in inode context in wind + * As we dont get the "inode" in the call back for rename */ + ret = delete_hard_link_ctx (frame, this, loc->inode); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, + "Failed deleting hard link from ctr " + "inode context"); + } } /* @@ -672,6 +992,12 @@ ctr_mknod_cbk (call_frame_t *frame, void *cookie, xlator_t *this, CTR_IS_DISABLED_THEN_GOTO(this, out); + /* Add hard link to the list */ + ret = add_hard_link_ctx (frame, this, inode); + if (ret) { + gf_log (this->name, GF_LOG_TRACE, "Failed adding hard link"); + } + ret = ctr_insert_unwind(frame, this, GFDB_FOP_CREATE_WRITE, GFDB_FOP_UNWIND); if (ret) { @@ -751,6 +1077,12 @@ ctr_create_cbk (call_frame_t *frame, void *cookie, xlator_t *this, CTR_IS_DISABLED_THEN_GOTO(this, out); + + ret = add_hard_link_ctx (frame, this, inode); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, "Failed adding hard link"); + } + ret = ctr_insert_unwind(frame, this, GFDB_FOP_CREATE_WRITE, GFDB_FOP_UNWIND); if (ret) { @@ -830,6 +1162,12 @@ ctr_link_cbk (call_frame_t *frame, void *cookie, xlator_t *this, CTR_IS_DISABLED_THEN_GOTO(this, out); + /* Add hard link to the list */ + ret = add_hard_link_ctx (frame, this, inode); + if (ret) { + gf_log (this->name, GF_LOG_TRACE, "Failed adding hard link"); + } + ret = ctr_insert_unwind(frame, this, GFDB_FOP_DENTRY_WRITE, GFDB_FOP_UNWIND); if (ret) { @@ -1117,6 +1455,8 @@ fini (xlator_t *this) } struct xlator_fops fops = { + /*lookup*/ + .lookup = ctr_lookup, /*write fops */ .mknod = ctr_mknod, .create = ctr_create, @@ -1133,7 +1473,9 @@ struct xlator_fops fops = { .readv = ctr_readv }; -struct xlator_cbks cbks; +struct xlator_cbks cbks = { + .forget = ctr_forget +}; struct volume_options options[] = { { .key = {"ctr-enabled",}, diff --git a/xlators/features/changetimerecorder/src/ctr-helper.h b/xlators/features/changetimerecorder/src/ctr-helper.h index 85ee872fa33..87b80e60354 100644 --- a/xlators/features/changetimerecorder/src/ctr-helper.h +++ b/xlators/features/changetimerecorder/src/ctr-helper.h @@ -28,6 +28,7 @@ #include <sys/time.h> #include "gfdb_data_store.h" +#include "ctr-xlator-ctx.h" /*CTR Xlator Private structure*/ typedef struct gf_ctr_private { @@ -384,7 +385,7 @@ ctr_insert_wind (call_frame_t *frame, /*Insert the db record*/ ret = insert_record (_priv->_db_conn, - &ctr_local->gfdb_db_record); + &ctr_local->gfdb_db_record); if (ret) { gf_log (this->name, GF_LOG_ERROR, "WIND: Inserting of record failed!"); @@ -462,6 +463,146 @@ out: return ret; } +/******************************* Hard link function ***************************/ + +static inline int +add_hard_link_ctx (call_frame_t *frame, + xlator_t *this, + inode_t *inode) +{ + int ret = -1; + gf_ctr_local_t *ctr_local = NULL; + ctr_xlator_ctx_t *ctr_xlator_ctx = NULL; + ctr_hard_link_t *ctr_hard_link = NULL; + + GF_ASSERT (frame); + GF_ASSERT (this); + GF_ASSERT (inode); + + ctr_local = frame->local; + if (!ctr_local) { + goto out; + } + + ctr_xlator_ctx = init_ctr_xlator_ctx (this, inode); + if (!ctr_xlator_ctx) { + gf_log (this->name, GF_LOG_ERROR, + "Failed accessing ctr inode context"); + goto out; + } + + LOCK (&ctr_xlator_ctx->lock); + + /* Check if the hard link already exists + * in the ctr inode context*/ + ctr_hard_link = ctr_search_hard_link_ctx (this, + ctr_xlator_ctx, + CTR_DB_REC(ctr_local).pargfid, + CTR_DB_REC(ctr_local).file_name); + /* if there then ignore */ + if (ctr_hard_link) { + ret = 1; + goto unlock; + } + + /* Add the hard link to the list*/ + ret = ctr_add_hard_link (this, ctr_xlator_ctx, + CTR_DB_REC(ctr_local).pargfid, + CTR_DB_REC(ctr_local).file_name); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, + "Failed to add hardlink to the ctr inode context"); + goto unlock; + } + + ret = 0; +unlock: + UNLOCK (&ctr_xlator_ctx->lock); +out: + return ret; +} + +static inline int +delete_hard_link_ctx (call_frame_t *frame, + xlator_t *this, + inode_t *inode) +{ + int ret = -1; + ctr_xlator_ctx_t *ctr_xlator_ctx = NULL; + gf_ctr_local_t *ctr_local = NULL; + + GF_ASSERT (frame); + GF_ASSERT (this); + GF_ASSERT (inode); + + ctr_local = frame->local; + if (!ctr_local) { + goto out; + } + + ctr_xlator_ctx = get_ctr_xlator_ctx (this, inode); + if (!ctr_xlator_ctx) { + /* Since there is no ctr inode context so nothing more to do */ + ret = 0; + goto out; + } + + ret = ctr_delete_hard_link (this, ctr_xlator_ctx, + CTR_DB_REC(ctr_local).pargfid, + CTR_DB_REC(ctr_local).file_name); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, "Failed to delete hard link"); + goto out; + } + + ret = 0; + +out: + return ret; +} + +static inline int +update_hard_link_ctx (call_frame_t *frame, + xlator_t *this, + inode_t *inode) +{ + int ret = -1; + ctr_xlator_ctx_t *ctr_xlator_ctx = NULL; + gf_ctr_local_t *ctr_local = NULL; + + GF_ASSERT (frame); + GF_ASSERT (this); + GF_ASSERT (inode); + + ctr_local = frame->local; + if (!ctr_local) { + goto out; + } + + ctr_xlator_ctx = init_ctr_xlator_ctx (this, inode); + if (!ctr_xlator_ctx) { + gf_log (this->name, GF_LOG_ERROR, + "Failed accessing ctr inode context"); + goto out; + } + + ret = ctr_update_hard_link (this, ctr_xlator_ctx, + CTR_DB_REC(ctr_local).pargfid, + CTR_DB_REC(ctr_local).file_name, + CTR_DB_REC(ctr_local).old_pargfid, + CTR_DB_REC(ctr_local).old_file_name); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, "Failed to delete hard link"); + goto out; + } + + ret = 0; + +out: + return ret; +} + + /****************************************************************************** * * CTR xlator init related functions diff --git a/xlators/features/changetimerecorder/src/ctr-xlator-ctx.c b/xlators/features/changetimerecorder/src/ctr-xlator-ctx.c new file mode 100644 index 00000000000..927c8542c4e --- /dev/null +++ b/xlators/features/changetimerecorder/src/ctr-xlator-ctx.c @@ -0,0 +1,370 @@ +/* + Copyright (c) 2015 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. +*/ + +#include "ctr-xlator-ctx.h" + +#define IS_THE_ONLY_HARDLINK(ctr_hard_link)\ + (ctr_hard_link->list.next == ctr_hard_link->list.prev) + + +static inline void +fini_ctr_hard_link (ctr_hard_link_t **ctr_hard_link) { + + GF_ASSERT (ctr_hard_link); + + if (*ctr_hard_link) + return; + GF_FREE ((*ctr_hard_link)->base_name); + GF_FREE (*ctr_hard_link); + *ctr_hard_link = NULL; +} + + +/* Please lock the ctr_xlator_ctx before using this function */ +ctr_hard_link_t * +ctr_search_hard_link_ctx (xlator_t *this, + ctr_xlator_ctx_t *ctr_xlator_ctx, + uuid_t pgfid, + const char *base_name) +{ + ctr_hard_link_t *_hard_link = NULL; + ctr_hard_link_t *searched_hardlink = NULL; + + GF_ASSERT (this); + GF_ASSERT (ctr_xlator_ctx); + + if (pgfid == NULL || base_name == NULL) + goto out; + + /*linear search*/ + list_for_each_entry (_hard_link, &ctr_xlator_ctx->hardlink_list, list) { + if (gf_uuid_compare (_hard_link->pgfid, pgfid) == 0 + && _hard_link->base_name + && strcmp(_hard_link->base_name, base_name) == 0) { + searched_hardlink = _hard_link; + break; + } + } + +out: + return searched_hardlink; +} + + + + +/* Please lock the ctr_xlator_ctx before using this function */ +int +ctr_add_hard_link (xlator_t *this, + ctr_xlator_ctx_t *ctr_xlator_ctx, + uuid_t pgfid, + const char *base_name) +{ + int ret = -1; + ctr_hard_link_t *ctr_hard_link = NULL; + + GF_ASSERT (this); + GF_ASSERT (ctr_xlator_ctx); + + if (pgfid == NULL || base_name == NULL) + goto out; + + ctr_hard_link = GF_CALLOC (1, sizeof (*ctr_hard_link), + gf_ctr_mt_hard_link_t); + if (!ctr_hard_link) { + gf_log (this->name, GF_LOG_ERROR, "Failed allocating " + "ctr_hard_link"); + goto out; + } + + /*Initialize the ctr_hard_link object and + * Assign the values : parent GFID and basename*/ + INIT_LIST_HEAD (&ctr_hard_link->list); + gf_uuid_copy (ctr_hard_link->pgfid, pgfid); + ret = gf_asprintf(&ctr_hard_link->base_name, "%s", base_name); + if (ret < 0) { + gf_log (this->name, GF_LOG_ERROR, "Failed copying basename" + "to ctr_hard_link"); + goto error; + } + + /*Add the hard link to the list*/ + list_add_tail (&ctr_hard_link->list, + &ctr_xlator_ctx->hardlink_list); + + /*aal izz well!*/ + ret = 0; + goto out; +error: + GF_FREE (ctr_hard_link); +out: + return ret; +} + +static void +__delete_hard_link_from_list (ctr_hard_link_t **ctr_hard_link) +{ + GF_ASSERT (ctr_hard_link); + GF_ASSERT (*ctr_hard_link); + + /*Remove hard link from list*/ + list_del(&(*ctr_hard_link)->list); + fini_ctr_hard_link (ctr_hard_link); +} + + +int +ctr_delete_hard_link (xlator_t *this, + ctr_xlator_ctx_t *ctr_xlator_ctx, + uuid_t pgfid, + const char *base_name) +{ + int ret = -1; + ctr_hard_link_t *ctr_hard_link = NULL; + + GF_ASSERT (this); + GF_ASSERT (ctr_xlator_ctx); + + + LOCK (&ctr_xlator_ctx->lock); + + /*Check if the hard link is present */ + ctr_hard_link = ctr_search_hard_link_ctx (this, ctr_xlator_ctx, + pgfid, base_name); + if (!ctr_hard_link) { + gf_log (this->name, GF_LOG_ERROR, "Hard link doesnt exist" + " in the list"); + goto out; + } + + __delete_hard_link_from_list (&ctr_hard_link); + ctr_hard_link = NULL; + + ret = 0; +out: + UNLOCK (&ctr_xlator_ctx->lock); + + return ret; +} + + + + +int +ctr_update_hard_link (xlator_t *this, + ctr_xlator_ctx_t *ctr_xlator_ctx, + uuid_t pgfid, + const char *base_name, + uuid_t old_pgfid, + const char *old_base_name) +{ + int ret = -1; + ctr_hard_link_t *ctr_hard_link = NULL; + + GF_ASSERT (this); + GF_ASSERT (ctr_xlator_ctx); + + + LOCK (&ctr_xlator_ctx->lock); + + /*Check if the hard link is present */ + ctr_hard_link = ctr_search_hard_link_ctx (this, ctr_xlator_ctx, + old_pgfid, old_base_name); + if (!ctr_hard_link) { + gf_log (this->name, GF_LOG_TRACE, "Hard link doesnt exist" + " in the list"); + /* Since the hard link is not present in the list + * we add it to the list */ + ret = ctr_add_hard_link (this, ctr_xlator_ctx, + pgfid, base_name); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, "Failed adding" + "hard link to the list"); + goto out; + } + ret = 0; + goto out; + } + + /* update the hard link */ + gf_uuid_copy (ctr_hard_link->pgfid, pgfid); + GF_FREE (&ctr_hard_link->base_name); + ret = gf_asprintf(&ctr_hard_link->base_name, "%s", base_name); + if (ret < 0) { + gf_log (this->name, GF_LOG_ERROR, "Failed copying basename" + "to ctr_hard_link"); + /* delete the corrupted entry */ + __delete_hard_link_from_list (&ctr_hard_link); + ctr_hard_link = NULL; + goto out; + } + + ret = 0; + +out: + UNLOCK (&ctr_xlator_ctx->lock); + + return ret; +} + + + + +/* Delete all hardlinks */ +static inline int +ctr_delete_all_hard_link (xlator_t *this, + ctr_xlator_ctx_t *ctr_xlator_ctx) +{ + int ret = -1; + ctr_hard_link_t *ctr_hard_link = NULL; + ctr_hard_link_t *tmp = NULL; + + GF_ASSERT (ctr_xlator_ctx); + + LOCK (&ctr_xlator_ctx->lock); + + list_for_each_entry_safe(ctr_hard_link, tmp, + &ctr_xlator_ctx->hardlink_list, list) + { + /*Remove hard link from list*/ + __delete_hard_link_from_list (&ctr_hard_link); + ctr_hard_link = NULL; + + } + + + UNLOCK (&ctr_xlator_ctx->lock); + + ret = 0; + + return ret; +} + + +/* Please lock the inode before using this function */ +static inline ctr_xlator_ctx_t * +__get_ctr_xlator_ctx (xlator_t *this, + inode_t *inode) +{ + int ret = 0; + uint64_t _addr = 0; + ctr_xlator_ctx_t *ctr_xlator_ctx = NULL; + + GF_ASSERT (this); + GF_ASSERT (inode); + + ret = __inode_ctx_get (inode, this, &_addr); + if (ret < 0) + _addr = 0; + if (_addr != 0) { + ctr_xlator_ctx = (ctr_xlator_ctx_t *) (long)_addr; + } + + return ctr_xlator_ctx; +} + + +ctr_xlator_ctx_t * +init_ctr_xlator_ctx (xlator_t *this, + inode_t *inode) +{ + int ret = -1; + uint64_t _addr = 0; + ctr_xlator_ctx_t *ctr_xlator_ctx = NULL; + + GF_ASSERT (this); + GF_ASSERT (inode); + + LOCK (&inode->lock); + { + ctr_xlator_ctx = __get_ctr_xlator_ctx (this, inode); + if (ctr_xlator_ctx) { + ret = 0; + goto out; + } + ctr_xlator_ctx = GF_CALLOC (1, sizeof (*ctr_xlator_ctx), + gf_ctr_mt_xlator_ctx); + if (!ctr_xlator_ctx) + goto out; + + ret = LOCK_INIT (&ctr_xlator_ctx->lock); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, + "Failed init lock %s", strerror(ret)); + goto out; + } + _addr = (uint64_t) ctr_xlator_ctx; + + ret = __inode_ctx_set (inode, this, &_addr); + if (ret) { + goto out; + } + + INIT_LIST_HEAD (&ctr_xlator_ctx->hardlink_list); + + } + ret = 0; +out: + if (ret) { + GF_FREE (ctr_xlator_ctx); + ctr_xlator_ctx = NULL; + } + + UNLOCK (&inode->lock); + + return ctr_xlator_ctx; +} + + + + +void +fini_ctr_xlator_ctx (xlator_t *this, + inode_t *inode) +{ + int ret = 0; + uint64_t _addr = 0; + ctr_xlator_ctx_t *ctr_xlator_ctx = NULL; + + + inode_ctx_del (inode, this, &_addr); + if (!_addr) + return; + + ctr_xlator_ctx = (ctr_xlator_ctx_t *) (long) _addr; + + ret = ctr_delete_all_hard_link (this, ctr_xlator_ctx); + if (ret) { + gf_log (this->name, GF_LOG_WARNING , "Failed deleting all hard" + " links from inode context"); + } + + LOCK_DESTROY (&ctr_xlator_ctx->lock); + + GF_FREE (ctr_xlator_ctx); + +} + + + + +ctr_xlator_ctx_t * +get_ctr_xlator_ctx (xlator_t *this, + inode_t *inode) +{ + ctr_xlator_ctx_t *ctr_xlator_ctx = NULL; + + LOCK (&inode->lock); + ctr_xlator_ctx = __get_ctr_xlator_ctx (this, inode); + UNLOCK (&inode->lock); + + return ctr_xlator_ctx; +} + diff --git a/xlators/features/changetimerecorder/src/ctr-xlator-ctx.h b/xlators/features/changetimerecorder/src/ctr-xlator-ctx.h new file mode 100644 index 00000000000..bc935014fc6 --- /dev/null +++ b/xlators/features/changetimerecorder/src/ctr-xlator-ctx.h @@ -0,0 +1,86 @@ +/* + Copyright (c) 2015 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 __CTR_XLATOR_CTX_H +#define __CTR_XLATOR_CTX_H + +#include "xlator.h" +#include "ctr_mem_types.h" +#include "iatt.h" +#include "glusterfs.h" +#include "xlator.h" +#include "logging.h" +#include "locking.h" +#include "common-utils.h" +#include <time.h> +#include <sys/time.h> + +typedef struct ctr_hard_link { + uuid_t pgfid; + char *base_name; + struct list_head list; +} ctr_hard_link_t; + +typedef struct ctr_xlator_ctx { + /* This represents the looked up hardlinks + * NOTE: This doesn't represent all physical hardlinks of the inode*/ + struct list_head hardlink_list; + gf_lock_t lock; +} ctr_xlator_ctx_t; + + +ctr_hard_link_t * +ctr_search_hard_link_ctx (xlator_t *this, + ctr_xlator_ctx_t *ctr_xlator_ctx, + uuid_t pgfid, + const char *base_name); + + +int +ctr_add_hard_link (xlator_t *this, + ctr_xlator_ctx_t *ctr_xlator_ctx, + uuid_t pgfid, + const char *base_name); + + + +int +ctr_delete_hard_link (xlator_t *this, + ctr_xlator_ctx_t *ctr_xlator_ctx, + uuid_t pgfid, + const char *base_name); + + +int +ctr_update_hard_link (xlator_t *this, + ctr_xlator_ctx_t *ctr_xlator_ctx, + uuid_t pgfid, + const char *base_name, + uuid_t old_pgfid, + const char *old_base_name); + + +ctr_xlator_ctx_t * +get_ctr_xlator_ctx (xlator_t *this, + inode_t *inode); + + + + +ctr_xlator_ctx_t * +init_ctr_xlator_ctx (xlator_t *this, + inode_t *inode); + + +void +fini_ctr_xlator_ctx (xlator_t *this, + inode_t *inode); + +#endif diff --git a/xlators/features/changetimerecorder/src/ctr_mem_types.h b/xlators/features/changetimerecorder/src/ctr_mem_types.h index 48387597814..f408c028e24 100644 --- a/xlators/features/changetimerecorder/src/ctr_mem_types.h +++ b/xlators/features/changetimerecorder/src/ctr_mem_types.h @@ -16,6 +16,8 @@ enum gf_ctr_mem_types_ { gf_ctr_mt_private_t = gfdb_mt_end + 1, + gf_ctr_mt_xlator_ctx, + gf_ctr_mt_hard_link_t, gf_ctr_mt_end }; #endif |