Blame xlators/features/changetimerecorder/src/ctr-helper.h

Packit Service a90fdc
/*
Packit Service a90fdc
   Copyright (c) 2015 Red Hat, Inc. <http://www.redhat.com>
Packit Service a90fdc
   This file is part of GlusterFS.
Packit Service a90fdc
Packit Service a90fdc
   This file is licensed to you under your choice of the GNU Lesser
Packit Service a90fdc
   General Public License, version 3 or any later version (LGPLv3 or
Packit Service a90fdc
   later), or the GNU General Public License, version 2 (GPLv2), in all
Packit Service a90fdc
   cases as published by the Free Software Foundation.
Packit Service a90fdc
*/
Packit Service a90fdc
Packit Service a90fdc
#ifndef __CTR_HELPER_H
Packit Service a90fdc
#define __CTR_HELPER_H
Packit Service a90fdc
Packit Service a90fdc
#include <glusterfs/xlator.h>
Packit Service a90fdc
#include "ctr_mem_types.h"
Packit Service a90fdc
#include <glusterfs/iatt.h>
Packit Service a90fdc
#include <glusterfs/glusterfs.h>
Packit Service a90fdc
#include <glusterfs/xlator.h>
Packit Service a90fdc
#include <glusterfs/defaults.h>
Packit Service a90fdc
#include <glusterfs/logging.h>
Packit Service a90fdc
#include <glusterfs/common-utils.h>
Packit Service a90fdc
#include <time.h>
Packit Service a90fdc
#include <sys/time.h>
Packit Service a90fdc
#include <pthread.h>
Packit Service a90fdc
Packit Service a90fdc
#include "gfdb_data_store.h"
Packit Service a90fdc
#include "ctr-xlator-ctx.h"
Packit Service a90fdc
#include "ctr-messages.h"
Packit Service a90fdc
Packit Service a90fdc
#define CTR_DEFAULT_HARDLINK_EXP_PERIOD 300 /* Five mins */
Packit Service a90fdc
#define CTR_DEFAULT_INODE_EXP_PERIOD 300    /* Five mins */
Packit Service a90fdc
Packit Service a90fdc
typedef struct ctr_query_cbk_args {
Packit Service a90fdc
    int query_fd;
Packit Service a90fdc
    int count;
Packit Service a90fdc
} ctr_query_cbk_args_t;
Packit Service a90fdc
Packit Service a90fdc
/*CTR Xlator Private structure*/
Packit Service a90fdc
typedef struct gf_ctr_private {
Packit Service a90fdc
    gf_boolean_t enabled;
Packit Service a90fdc
    char *ctr_db_path;
Packit Service a90fdc
    gf_boolean_t ctr_hot_brick;
Packit Service a90fdc
    gf_boolean_t ctr_record_wind;
Packit Service a90fdc
    gf_boolean_t ctr_record_unwind;
Packit Service a90fdc
    gf_boolean_t ctr_record_counter;
Packit Service a90fdc
    gf_boolean_t ctr_record_metadata_heat;
Packit Service a90fdc
    gf_boolean_t ctr_link_consistency;
Packit Service a90fdc
    gfdb_db_type_t gfdb_db_type;
Packit Service a90fdc
    gfdb_sync_type_t gfdb_sync_type;
Packit Service a90fdc
    gfdb_conn_node_t *_db_conn;
Packit Service a90fdc
    uint64_t ctr_lookupheal_link_timeout;
Packit Service a90fdc
    uint64_t ctr_lookupheal_inode_timeout;
Packit Service a90fdc
    gf_boolean_t compact_active;
Packit Service a90fdc
    gf_boolean_t compact_mode_switched;
Packit Service a90fdc
    pthread_mutex_t compact_lock;
Packit Service a90fdc
} gf_ctr_private_t;
Packit Service a90fdc
Packit Service a90fdc
/*
Packit Service a90fdc
 * gf_ctr_local_t is the ctr xlator local data structure that is stored in
Packit Service a90fdc
 * the call_frame of each FOP.
Packit Service a90fdc
 *
Packit Service a90fdc
 * gfdb_db_record: The gf_ctr_local contains a gfdb_db_record object, which is
Packit Service a90fdc
 * used by the insert_record() api from the libgfdb. The gfdb_db_record object
Packit Service a90fdc
 * will contain all the inode and hardlink(only for dentry fops: create,
Packit Service a90fdc
 * mknod,link, unlink, rename).The ctr_local is keep alive till the unwind
Packit Service a90fdc
 * call and will be release during the unwind. The same gfdb_db_record will
Packit Service a90fdc
 * used for the unwind insert_record() api, to record unwind in the database.
Packit Service a90fdc
 *
Packit Service a90fdc
 * ia_inode_type in gf_ctr_local will tell the type of the inode. This is
Packit Service a90fdc
 * important for during the unwind path. As we will not have the inode during
Packit Service a90fdc
 * the unwind path. We would have include this in the gfdb_db_record itself
Packit Service a90fdc
 * but currently we record only file inode information.
Packit Service a90fdc
 *
Packit Service a90fdc
 * is_internal_fop in gf_ctr_local will tell us if this is a internal fop and
Packit Service a90fdc
 * take special/no action. We don't record change/access times or increement
Packit Service a90fdc
 * heat counter for internal fops from rebalancer.
Packit Service a90fdc
 * */
Packit Service a90fdc
typedef struct gf_ctr_local {
Packit Service a90fdc
    gfdb_db_record_t gfdb_db_record;
Packit Service a90fdc
    ia_type_t ia_inode_type;
Packit Service a90fdc
    gf_boolean_t is_internal_fop;
Packit Service a90fdc
    gf_special_pid_t client_pid;
Packit Service a90fdc
} gf_ctr_local_t;
Packit Service a90fdc
/*
Packit Service a90fdc
 * Easy access of gfdb_db_record of ctr_local
Packit Service a90fdc
 * */
Packit Service a90fdc
#define CTR_DB_REC(ctr_local) (ctr_local->gfdb_db_record)
Packit Service a90fdc
Packit Service a90fdc
/*Clear db record*/
Packit Service a90fdc
#define CLEAR_CTR_DB_RECORD(ctr_local)                                         \
Packit Service a90fdc
    do {                                                                       \
Packit Service a90fdc
        ctr_local->gfdb_db_record.gfdb_fop_path = GFDB_FOP_INVALID;            \
Packit Service a90fdc
        memset(&(ctr_local->gfdb_db_record.gfdb_wind_change_time), 0,          \
Packit Service a90fdc
               sizeof(gfdb_time_t));                                           \
Packit Service a90fdc
        memset(&(ctr_local->gfdb_db_record.gfdb_unwind_change_time), 0,        \
Packit Service a90fdc
               sizeof(gfdb_time_t));                                           \
Packit Service a90fdc
        gf_uuid_clear(ctr_local->gfdb_db_record.gfid);                         \
Packit Service a90fdc
        gf_uuid_clear(ctr_local->gfdb_db_record.pargfid);                      \
Packit Service a90fdc
        memset(ctr_local->gfdb_db_record.file_name, 0, GF_NAME_MAX + 1);       \
Packit Service a90fdc
        memset(ctr_local->gfdb_db_record.old_file_name, 0, GF_NAME_MAX + 1);   \
Packit Service a90fdc
        ctr_local->gfdb_db_record.gfdb_fop_type = GFDB_FOP_INVALID_OP;         \
Packit Service a90fdc
        ctr_local->ia_inode_type = IA_INVAL;                                   \
Packit Service a90fdc
    } while (0)
Packit Service a90fdc
Packit Service a90fdc
static gf_ctr_local_t *
Packit Service a90fdc
init_ctr_local_t(xlator_t *this)
Packit Service a90fdc
{
Packit Service a90fdc
    gf_ctr_local_t *ctr_local = NULL;
Packit Service a90fdc
Packit Service a90fdc
    GF_ASSERT(this);
Packit Service a90fdc
Packit Service a90fdc
    ctr_local = mem_get0(this->local_pool);
Packit Service a90fdc
    if (!ctr_local) {
Packit Service a90fdc
        gf_msg(GFDB_DATA_STORE, GF_LOG_ERROR, 0,
Packit Service a90fdc
               CTR_MSG_CREATE_CTR_LOCAL_ERROR_WIND,
Packit Service a90fdc
               "Error while creating ctr local");
Packit Service a90fdc
        goto out;
Packit Service a90fdc
    }
Packit Service a90fdc
Packit Service a90fdc
    CLEAR_CTR_DB_RECORD(ctr_local);
Packit Service a90fdc
out:
Packit Service a90fdc
    return ctr_local;
Packit Service a90fdc
}
Packit Service a90fdc
Packit Service a90fdc
static void
Packit Service a90fdc
free_ctr_local(gf_ctr_local_t *ctr_local)
Packit Service a90fdc
{
Packit Service a90fdc
    if (ctr_local)
Packit Service a90fdc
        mem_put(ctr_local);
Packit Service a90fdc
}
Packit Service a90fdc
Packit Service a90fdc
/******************************************************************************
Packit Service a90fdc
 *
Packit Service a90fdc
 *
Packit Service a90fdc
 *                      Context Carrier Structures
Packit Service a90fdc
 *
Packit Service a90fdc
 *
Packit Service a90fdc
 * ****************************************************************************/
Packit Service a90fdc
Packit Service a90fdc
/*
Packit Service a90fdc
 * Context Carrier structures are used to carry relevant information about
Packit Service a90fdc
 * inodes and links from the fops calls to the ctr_insert_wind.
Packit Service a90fdc
 * These structure just have pointers to the original data and donot
Packit Service a90fdc
 * do a deep copy of any data. This info is deep copied to
Packit Service a90fdc
 * ctr_local->gfdb_db_record and passed to insert_record() api of libgfdb. This
Packit Service a90fdc
 * info remains persistent for the unwind in  ctr_local->gfdb_db_record
Packit Service a90fdc
 * and once used will be destroyed.
Packit Service a90fdc
 *
Packit Service a90fdc
 * gf_ctr_link_context_t : Context structure for hard links
Packit Service a90fdc
 * gf_ctr_inode_context_t : Context structure for inodes
Packit Service a90fdc
 *
Packit Service a90fdc
 * */
Packit Service a90fdc
Packit Service a90fdc
/*Context Carrier Structure for hard links*/
Packit Service a90fdc
typedef struct gf_ctr_link_context {
Packit Service a90fdc
    uuid_t *pargfid;
Packit Service a90fdc
    const char *basename;
Packit Service a90fdc
} gf_ctr_link_context_t;
Packit Service a90fdc
Packit Service a90fdc
/*Context Carrier Structure for inodes*/
Packit Service a90fdc
typedef struct gf_ctr_inode_context {
Packit Service a90fdc
    ia_type_t ia_type;
Packit Service a90fdc
    uuid_t *gfid;
Packit Service a90fdc
    uuid_t *old_gfid;
Packit Service a90fdc
    gf_ctr_link_context_t *new_link_cx;
Packit Service a90fdc
    gf_ctr_link_context_t *old_link_cx;
Packit Service a90fdc
    gfdb_fop_type_t fop_type;
Packit Service a90fdc
    gfdb_fop_path_t fop_path;
Packit Service a90fdc
    gf_boolean_t is_internal_fop;
Packit Service a90fdc
    /* Indicating metadata fops */
Packit Service a90fdc
    gf_boolean_t is_metadata_fop;
Packit Service a90fdc
} gf_ctr_inode_context_t;
Packit Service a90fdc
Packit Service a90fdc
/*******************Util Macros for Context Carrier Structures*****************/
Packit Service a90fdc
Packit Service a90fdc
/*Checks if ctr_link_cx is sane!*/
Packit Service a90fdc
#define IS_CTR_LINK_CX_SANE(ctr_link_cx)                                       \
Packit Service a90fdc
    do {                                                                       \
Packit Service a90fdc
        if (ctr_link_cx) {                                                     \
Packit Service a90fdc
            if (ctr_link_cx->pargfid)                                          \
Packit Service a90fdc
                GF_ASSERT(*(ctr_link_cx->pargfid));                            \
Packit Service a90fdc
            GF_ASSERT(ctr_link_cx->basename);                                  \
Packit Service a90fdc
        };                                                                     \
Packit Service a90fdc
    } while (0)
Packit Service a90fdc
Packit Service a90fdc
/*Clear and fill the ctr_link_context with values*/
Packit Service a90fdc
#define FILL_CTR_LINK_CX(ctr_link_cx, _pargfid, _basename, label)              \
Packit Service a90fdc
    do {                                                                       \
Packit Service a90fdc
        GF_VALIDATE_OR_GOTO("ctr", ctr_link_cx, label);                        \
Packit Service a90fdc
        GF_VALIDATE_OR_GOTO("ctr", _pargfid, label);                           \
Packit Service a90fdc
        GF_VALIDATE_OR_GOTO("ctr", _basename, label);                          \
Packit Service a90fdc
        memset(ctr_link_cx, 0, sizeof(*ctr_link_cx));                          \
Packit Service a90fdc
        ctr_link_cx->pargfid = &_pargfid;                                      \
Packit Service a90fdc
        ctr_link_cx->basename = _basename;                                     \
Packit Service a90fdc
    } while (0)
Packit Service a90fdc
Packit Service a90fdc
#define NEW_LINK_CX(ctr_inode_cx) ctr_inode_cx->new_link_cx
Packit Service a90fdc
Packit Service a90fdc
#define OLD_LINK_CX(ctr_inode_cx) ctr_inode_cx->old_link_cx
Packit Service a90fdc
Packit Service a90fdc
/*Checks if ctr_inode_cx is sane!*/
Packit Service a90fdc
#define IS_CTR_INODE_CX_SANE(ctr_inode_cx)                                     \
Packit Service a90fdc
    do {                                                                       \
Packit Service a90fdc
        GF_ASSERT(ctr_inode_cx);                                               \
Packit Service a90fdc
        GF_ASSERT(ctr_inode_cx->gfid);                                         \
Packit Service a90fdc
        GF_ASSERT(*(ctr_inode_cx->gfid));                                      \
Packit Service a90fdc
        GF_ASSERT(ctr_inode_cx->fop_type != GFDB_FOP_INVALID_OP);              \
Packit Service a90fdc
        GF_ASSERT(ctr_inode_cx->fop_path != GFDB_FOP_INVALID);                 \
Packit Service a90fdc
        IS_CTR_LINK_CX_SANE(NEW_LINK_CX(ctr_inode_cx));                        \
Packit Service a90fdc
        IS_CTR_LINK_CX_SANE(OLD_LINK_CX(ctr_inode_cx));                        \
Packit Service a90fdc
    } while (0)
Packit Service a90fdc
Packit Service a90fdc
/*Clear and fill the ctr_inode_context with values*/
Packit Service a90fdc
#define FILL_CTR_INODE_CONTEXT(ctr_inode_cx, _ia_type, _gfid, _new_link_cx,    \
Packit Service a90fdc
                               _old_link_cx, _fop_type, _fop_path)             \
Packit Service a90fdc
    do {                                                                       \
Packit Service a90fdc
        GF_ASSERT(ctr_inode_cx);                                               \
Packit Service a90fdc
        GF_ASSERT(_gfid);                                                      \
Packit Service a90fdc
        GF_ASSERT(_fop_type != GFDB_FOP_INVALID_OP);                           \
Packit Service a90fdc
        GF_ASSERT(_fop_path != GFDB_FOP_INVALID);                              \
Packit Service a90fdc
        memset(ctr_inode_cx, 0, sizeof(*ctr_inode_cx));                        \
Packit Service a90fdc
        ctr_inode_cx->ia_type = _ia_type;                                      \
Packit Service a90fdc
        ctr_inode_cx->gfid = &_gfid;                                           \
Packit Service a90fdc
        IS_CTR_LINK_CX_SANE(NEW_LINK_CX(ctr_inode_cx));                        \
Packit Service a90fdc
        if (_new_link_cx)                                                      \
Packit Service a90fdc
            NEW_LINK_CX(ctr_inode_cx) = _new_link_cx;                          \
Packit Service a90fdc
        IS_CTR_LINK_CX_SANE(OLD_LINK_CX(ctr_inode_cx));                        \
Packit Service a90fdc
        if (_old_link_cx)                                                      \
Packit Service a90fdc
            OLD_LINK_CX(ctr_inode_cx) = _old_link_cx;                          \
Packit Service a90fdc
        ctr_inode_cx->fop_type = _fop_type;                                    \
Packit Service a90fdc
        ctr_inode_cx->fop_path = _fop_path;                                    \
Packit Service a90fdc
    } while (0)
Packit Service a90fdc
Packit Service a90fdc
/******************************************************************************
Packit Service a90fdc
 *
Packit Service a90fdc
 *                      Util functions or macros used by
Packit Service a90fdc
 *                      insert wind and insert unwind
Packit Service a90fdc
 *
Packit Service a90fdc
 * ****************************************************************************/
Packit Service a90fdc
/* Free ctr frame local */
Packit Service a90fdc
static inline void
Packit Service a90fdc
ctr_free_frame_local(call_frame_t *frame)
Packit Service a90fdc
{
Packit Service a90fdc
    if (frame) {
Packit Service a90fdc
        free_ctr_local((gf_ctr_local_t *)frame->local);
Packit Service a90fdc
        frame->local = NULL;
Packit Service a90fdc
    }
Packit Service a90fdc
}
Packit Service a90fdc
Packit Service a90fdc
/* Setting GF_REQUEST_LINK_COUNT_XDATA in dict
Packit Service a90fdc
 * that has to be sent to POSIX Xlator to send
Packit Service a90fdc
 * link count in unwind path.
Packit Service a90fdc
 * return 0 for success with not creation of dict
Packit Service a90fdc
 * return 1 for success with creation of dict
Packit Service a90fdc
 * return -1 for failure.
Packit Service a90fdc
 * */
Packit Service a90fdc
static inline int
Packit Service a90fdc
set_posix_link_request(xlator_t *this, dict_t **xdata)
Packit Service a90fdc
{
Packit Service a90fdc
    int ret = -1;
Packit Service a90fdc
    gf_boolean_t is_created = _gf_false;
Packit Service a90fdc
Packit Service a90fdc
    GF_VALIDATE_OR_GOTO("ctr", this, out);
Packit Service a90fdc
    GF_VALIDATE_OR_GOTO(this->name, xdata, out);
Packit Service a90fdc
Packit Service a90fdc
    /*create xdata if NULL*/
Packit Service a90fdc
    if (!*xdata) {
Packit Service a90fdc
        *xdata = dict_new();
Packit Service a90fdc
        is_created = _gf_true;
Packit Service a90fdc
        ret = 1;
Packit Service a90fdc
    } else {
Packit Service a90fdc
        ret = 0;
Packit Service a90fdc
    }
Packit Service a90fdc
Packit Service a90fdc
    if (!*xdata) {
Packit Service a90fdc
        gf_msg(this->name, GF_LOG_ERROR, 0, CTR_MSG_XDATA_NULL,
Packit Service a90fdc
               "xdata is NULL :Cannot send "
Packit Service a90fdc
               "GF_REQUEST_LINK_COUNT_XDATA to posix");
Packit Service a90fdc
        ret = -1;
Packit Service a90fdc
        goto out;
Packit Service a90fdc
    }
Packit Service a90fdc
Packit Service a90fdc
    ret = dict_set_int32(*xdata, GF_REQUEST_LINK_COUNT_XDATA, 1);
Packit Service a90fdc
    if (ret) {
Packit Service a90fdc
        gf_msg(this->name, GF_LOG_ERROR, 0,
Packit Service a90fdc
               CTR_MSG_SET_CTR_RESPONSE_LINK_COUNT_XDATA_FAILED,
Packit Service a90fdc
               "Failed setting GF_REQUEST_LINK_COUNT_XDATA");
Packit Service a90fdc
        ret = -1;
Packit Service a90fdc
        goto out;
Packit Service a90fdc
    }
Packit Service a90fdc
    ret = 0;
Packit Service a90fdc
out:
Packit Service a90fdc
    if (ret == -1) {
Packit Service a90fdc
        if (*xdata && is_created) {
Packit Service a90fdc
            dict_unref(*xdata);
Packit Service a90fdc
        }
Packit Service a90fdc
    }
Packit Service a90fdc
    return ret;
Packit Service a90fdc
}
Packit Service a90fdc
Packit Service a90fdc
/*
Packit Service a90fdc
 * If a bitrot fop
Packit Service a90fdc
 * */
Packit Service a90fdc
#define BITROT_FOP(frame)                                                      \
Packit Service a90fdc
    (frame->root->pid == GF_CLIENT_PID_BITD ||                                 \
Packit Service a90fdc
     frame->root->pid == GF_CLIENT_PID_SCRUB)
Packit Service a90fdc
Packit Service a90fdc
/*
Packit Service a90fdc
 * If a rebalancer fop
Packit Service a90fdc
 * */
Packit Service a90fdc
#define REBALANCE_FOP(frame) (frame->root->pid == GF_CLIENT_PID_DEFRAG)
Packit Service a90fdc
Packit Service a90fdc
/*
Packit Service a90fdc
 * If its a tiering rebalancer fop
Packit Service a90fdc
 * */
Packit Service a90fdc
#define TIER_REBALANCE_FOP(frame)                                              \
Packit Service a90fdc
    (frame->root->pid == GF_CLIENT_PID_TIER_DEFRAG)
Packit Service a90fdc
Packit Service a90fdc
/*
Packit Service a90fdc
 * If its a AFR SELF HEAL
Packit Service a90fdc
 * */
Packit Service a90fdc
#define AFR_SELF_HEAL_FOP(frame) (frame->root->pid == GF_CLIENT_PID_SELF_HEALD)
Packit Service a90fdc
Packit Service a90fdc
/*
Packit Service a90fdc
 * if a rebalancer fop goto
Packit Service a90fdc
 * */
Packit Service a90fdc
#define CTR_IF_REBALANCE_FOP_THEN_GOTO(frame, label)                           \
Packit Service a90fdc
    do {                                                                       \
Packit Service a90fdc
        if (REBALANCE_FOP(frame))                                              \
Packit Service a90fdc
            goto label;                                                        \
Packit Service a90fdc
    } while (0)
Packit Service a90fdc
Packit Service a90fdc
/*
Packit Service a90fdc
 * Internal fop
Packit Service a90fdc
 *
Packit Service a90fdc
 * */
Packit Service a90fdc
static inline gf_boolean_t
Packit Service a90fdc
is_internal_fop(call_frame_t *frame, dict_t *xdata)
Packit Service a90fdc
{
Packit Service a90fdc
    gf_boolean_t ret = _gf_false;
Packit Service a90fdc
Packit Service a90fdc
    GF_ASSERT(frame);
Packit Service a90fdc
    GF_ASSERT(frame->root);
Packit Service a90fdc
Packit Service a90fdc
    if (AFR_SELF_HEAL_FOP(frame)) {
Packit Service a90fdc
        ret = _gf_true;
Packit Service a90fdc
    }
Packit Service a90fdc
    if (BITROT_FOP(frame)) {
Packit Service a90fdc
        ret = _gf_true;
Packit Service a90fdc
    }
Packit Service a90fdc
    if (REBALANCE_FOP(frame) || TIER_REBALANCE_FOP(frame)) {
Packit Service a90fdc
        ret = _gf_true;
Packit Service a90fdc
        if (xdata && dict_get(xdata, CTR_ATTACH_TIER_LOOKUP)) {
Packit Service a90fdc
            ret = _gf_false;
Packit Service a90fdc
        }
Packit Service a90fdc
    }
Packit Service a90fdc
    if (xdata && dict_get(xdata, GLUSTERFS_INTERNAL_FOP_KEY)) {
Packit Service a90fdc
        ret = _gf_true;
Packit Service a90fdc
    }
Packit Service a90fdc
Packit Service a90fdc
    return ret;
Packit Service a90fdc
}
Packit Service a90fdc
Packit Service a90fdc
#define CTR_IF_INTERNAL_FOP_THEN_GOTO(frame, dict, label)                      \
Packit Service a90fdc
    do {                                                                       \
Packit Service a90fdc
        if (is_internal_fop(frame, dict))                                      \
Packit Service a90fdc
            goto label;                                                        \
Packit Service a90fdc
    } while (0)
Packit Service a90fdc
Packit Service a90fdc
/* if fop has failed exit */
Packit Service a90fdc
#define CTR_IF_FOP_FAILED_THEN_GOTO(this, op_ret, op_errno, label)             \
Packit Service a90fdc
    do {                                                                       \
Packit Service a90fdc
        if (op_ret == -1) {                                                    \
Packit Service a90fdc
            gf_msg_trace(this->name, 0, "Failed fop with %s",                  \
Packit Service a90fdc
                         strerror(op_errno));                                  \
Packit Service a90fdc
            goto label;                                                        \
Packit Service a90fdc
        };                                                                     \
Packit Service a90fdc
    } while (0)
Packit Service a90fdc
Packit Service a90fdc
/*
Packit Service a90fdc
 * IS CTR Xlator is disabled then goto to label
Packit Service a90fdc
 * */
Packit Service a90fdc
#define CTR_IS_DISABLED_THEN_GOTO(this, label)                                 \
Packit Service a90fdc
    do {                                                                       \
Packit Service a90fdc
        gf_ctr_private_t *_priv = NULL;                                        \
Packit Service a90fdc
        GF_ASSERT(this);                                                       \
Packit Service a90fdc
        GF_ASSERT(this->private);                                              \
Packit Service a90fdc
        _priv = this->private;                                                 \
Packit Service a90fdc
        if (!_priv->_db_conn)                                                  \
Packit Service a90fdc
            goto label;                                                        \
Packit Service a90fdc
    } while (0)
Packit Service a90fdc
Packit Service a90fdc
/*
Packit Service a90fdc
 * IS CTR record metadata heat is disabled then goto to label
Packit Service a90fdc
 * */
Packit Service a90fdc
#define CTR_RECORD_METADATA_HEAT_IS_DISABLED_THEN_GOTO(this, label)            \
Packit Service a90fdc
    do {                                                                       \
Packit Service a90fdc
        gf_ctr_private_t *_priv = NULL;                                        \
Packit Service a90fdc
        GF_ASSERT(this);                                                       \
Packit Service a90fdc
        GF_ASSERT(this->private);                                              \
Packit Service a90fdc
        _priv = this->private;                                                 \
Packit Service a90fdc
        if (!_priv->ctr_record_metadata_heat)                                  \
Packit Service a90fdc
            goto label;                                                        \
Packit Service a90fdc
    } while (0)
Packit Service a90fdc
Packit Service a90fdc
int
Packit Service a90fdc
fill_db_record_for_unwind(xlator_t *this, gf_ctr_local_t *ctr_local,
Packit Service a90fdc
                          gfdb_fop_type_t fop_type, gfdb_fop_path_t fop_path);
Packit Service a90fdc
Packit Service a90fdc
int
Packit Service a90fdc
fill_db_record_for_wind(xlator_t *this, gf_ctr_local_t *ctr_local,
Packit Service a90fdc
                        gf_ctr_inode_context_t *ctr_inode_cx);
Packit Service a90fdc
Packit Service a90fdc
/*******************************************************************************
Packit Service a90fdc
 *                              CTR INSERT WIND
Packit Service a90fdc
 * *****************************************************************************
Packit Service a90fdc
 * Function used to insert/update record into the database during a wind fop
Packit Service a90fdc
 * This function creates ctr_local structure into the frame of the fop
Packit Service a90fdc
 * call.
Packit Service a90fdc
 * ****************************************************************************/
Packit Service a90fdc
Packit Service a90fdc
static inline int
Packit Service a90fdc
ctr_insert_wind(call_frame_t *frame, xlator_t *this,
Packit Service a90fdc
                gf_ctr_inode_context_t *ctr_inode_cx)
Packit Service a90fdc
{
Packit Service a90fdc
    int ret = -1;
Packit Service a90fdc
    gf_ctr_private_t *_priv = NULL;
Packit Service a90fdc
    gf_ctr_local_t *ctr_local = NULL;
Packit Service a90fdc
Packit Service a90fdc
    GF_ASSERT(frame);
Packit Service a90fdc
    GF_ASSERT(frame->root);
Packit Service a90fdc
    GF_ASSERT(this);
Packit Service a90fdc
    IS_CTR_INODE_CX_SANE(ctr_inode_cx);
Packit Service a90fdc
Packit Service a90fdc
    _priv = this->private;
Packit Service a90fdc
    GF_ASSERT(_priv);
Packit Service a90fdc
Packit Service a90fdc
    GF_ASSERT(_priv->_db_conn);
Packit Service a90fdc
Packit Service a90fdc
    /*If record_wind option of CTR is on record wind for
Packit Service a90fdc
     * regular files only*/
Packit Service a90fdc
    if (_priv->ctr_record_wind && ctr_inode_cx->ia_type != IA_IFDIR) {
Packit Service a90fdc
        frame->local = init_ctr_local_t(this);
Packit Service a90fdc
        if (!frame->local) {
Packit Service a90fdc
            gf_msg(this->name, GF_LOG_ERROR, 0,
Packit Service a90fdc
                   CTR_MSG_CREATE_CTR_LOCAL_ERROR_WIND,
Packit Service a90fdc
                   "WIND: Error while creating ctr local");
Packit Service a90fdc
            goto out;
Packit Service a90fdc
        };
Packit Service a90fdc
        ctr_local = frame->local;
Packit Service a90fdc
        ctr_local->client_pid = frame->root->pid;
Packit Service a90fdc
        ctr_local->is_internal_fop = ctr_inode_cx->is_internal_fop;
Packit Service a90fdc
Packit Service a90fdc
        /* Decide whether to record counters or not */
Packit Service a90fdc
        CTR_DB_REC(ctr_local).do_record_counters = _gf_false;
Packit Service a90fdc
        /* If record counter is enabled */
Packit Service a90fdc
        if (_priv->ctr_record_counter) {
Packit Service a90fdc
            /* If not a internal fop */
Packit Service a90fdc
            if (!(ctr_local->is_internal_fop)) {
Packit Service a90fdc
                /* If its a metadata fop AND
Packit Service a90fdc
                 * record metadata heat
Packit Service a90fdc
                 * OR
Packit Service a90fdc
                 * its NOT a metadata fop */
Packit Service a90fdc
                if ((ctr_inode_cx->is_metadata_fop &&
Packit Service a90fdc
                     _priv->ctr_record_metadata_heat) ||
Packit Service a90fdc
                    (!ctr_inode_cx->is_metadata_fop)) {
Packit Service a90fdc
                    CTR_DB_REC(ctr_local).do_record_counters = _gf_true;
Packit Service a90fdc
                }
Packit Service a90fdc
            }
Packit Service a90fdc
        }
Packit Service a90fdc
Packit Service a90fdc
        /* Decide whether to record times or not
Packit Service a90fdc
         * For non internal FOPS record times as usual*/
Packit Service a90fdc
        CTR_DB_REC(ctr_local).do_record_times = _gf_false;
Packit Service a90fdc
        if (!ctr_local->is_internal_fop) {
Packit Service a90fdc
            /* If its a metadata fop AND
Packit Service a90fdc
             * record metadata heat
Packit Service a90fdc
             * OR
Packit Service a90fdc
             * its NOT a metadata fop */
Packit Service a90fdc
            if ((ctr_inode_cx->is_metadata_fop &&
Packit Service a90fdc
                 _priv->ctr_record_metadata_heat) ||
Packit Service a90fdc
                (!ctr_inode_cx->is_metadata_fop)) {
Packit Service a90fdc
                CTR_DB_REC(ctr_local).do_record_times =
Packit Service a90fdc
                    (_priv->ctr_record_wind || _priv->ctr_record_unwind);
Packit Service a90fdc
            }
Packit Service a90fdc
        }
Packit Service a90fdc
        /* when its a internal FOPS*/
Packit Service a90fdc
        else {
Packit Service a90fdc
            /* Record times only for create
Packit Service a90fdc
             * i.e when the inode is created */
Packit Service a90fdc
            CTR_DB_REC(ctr_local).do_record_times = (isdentrycreatefop(
Packit Service a90fdc
                                                        ctr_inode_cx->fop_type))
Packit Service a90fdc
                                                        ? _gf_true
Packit Service a90fdc
                                                        : _gf_false;
Packit Service a90fdc
        }
Packit Service a90fdc
Packit Service a90fdc
        /*Fill the db record for insertion*/
Packit Service a90fdc
        ret = fill_db_record_for_wind(this, ctr_local, ctr_inode_cx);
Packit Service a90fdc
        if (ret) {
Packit Service a90fdc
            gf_msg(this->name, GF_LOG_ERROR, 0,
Packit Service a90fdc
                   CTR_MSG_FILL_CTR_LOCAL_ERROR_WIND,
Packit Service a90fdc
                   "WIND: Error filling  ctr local");
Packit Service a90fdc
            goto out;
Packit Service a90fdc
        }
Packit Service a90fdc
Packit Service a90fdc
        /*Insert the db record*/
Packit Service a90fdc
        ret = insert_record(_priv->_db_conn, &ctr_local->gfdb_db_record);
Packit Service a90fdc
        if (ret) {
Packit Service a90fdc
            gf_msg(this->name, GF_LOG_ERROR, 0,
Packit Service a90fdc
                   CTR_MSG_INSERT_RECORD_WIND_FAILED,
Packit Service a90fdc
                   "WIND: Inserting of record failed!");
Packit Service a90fdc
            goto out;
Packit Service a90fdc
        }
Packit Service a90fdc
    }
Packit Service a90fdc
    ret = 0;
Packit Service a90fdc
out:
Packit Service a90fdc
Packit Service a90fdc
    if (ret) {
Packit Service a90fdc
        free_ctr_local(ctr_local);
Packit Service a90fdc
        frame->local = NULL;
Packit Service a90fdc
    }
Packit Service a90fdc
Packit Service a90fdc
    return ret;
Packit Service a90fdc
}
Packit Service a90fdc
Packit Service a90fdc
/*******************************************************************************
Packit Service a90fdc
 *                             CTR INSERT UNWIND
Packit Service a90fdc
 * *****************************************************************************
Packit Service a90fdc
 * Function used to insert/update record into the database during a unwind fop
Packit Service a90fdc
 * This function destroys ctr_local structure into the frame of the fop
Packit Service a90fdc
 * call at the end.
Packit Service a90fdc
 * ****************************************************************************/
Packit Service a90fdc
static inline int
Packit Service a90fdc
ctr_insert_unwind(call_frame_t *frame, xlator_t *this, gfdb_fop_type_t fop_type,
Packit Service a90fdc
                  gfdb_fop_path_t fop_path)
Packit Service a90fdc
{
Packit Service a90fdc
    int ret = -1;
Packit Service a90fdc
    gf_ctr_private_t *_priv = NULL;
Packit Service a90fdc
    gf_ctr_local_t *ctr_local = NULL;
Packit Service a90fdc
Packit Service a90fdc
    GF_ASSERT(frame);
Packit Service a90fdc
    GF_ASSERT(this);
Packit Service a90fdc
Packit Service a90fdc
    _priv = this->private;
Packit Service a90fdc
    GF_ASSERT(_priv);
Packit Service a90fdc
Packit Service a90fdc
    GF_ASSERT(_priv->_db_conn);
Packit Service a90fdc
Packit Service a90fdc
    ctr_local = frame->local;
Packit Service a90fdc
Packit Service a90fdc
    if (ctr_local && (_priv->ctr_record_unwind || isdentryfop(fop_type)) &&
Packit Service a90fdc
        (ctr_local->ia_inode_type != IA_IFDIR)) {
Packit Service a90fdc
        CTR_DB_REC(ctr_local).do_record_uwind_time = _priv->ctr_record_unwind;
Packit Service a90fdc
Packit Service a90fdc
        ret = fill_db_record_for_unwind(this, ctr_local, fop_type, fop_path);
Packit Service a90fdc
        if (ret == -1) {
Packit Service a90fdc
            gf_msg(this->name, GF_LOG_ERROR, 0,
Packit Service a90fdc
                   CTR_MSG_FILL_CTR_LOCAL_ERROR_UNWIND,
Packit Service a90fdc
                   "UNWIND: Error filling ctr local");
Packit Service a90fdc
            goto out;
Packit Service a90fdc
        }
Packit Service a90fdc
Packit Service a90fdc
        ret = insert_record(_priv->_db_conn, &ctr_local->gfdb_db_record);
Packit Service a90fdc
        if (ret == -1) {
Packit Service a90fdc
            gf_msg(this->name, GF_LOG_ERROR, 0,
Packit Service a90fdc
                   CTR_MSG_FILL_CTR_LOCAL_ERROR_UNWIND,
Packit Service a90fdc
                   "UNWIND: Error filling ctr local");
Packit Service a90fdc
            goto out;
Packit Service a90fdc
        }
Packit Service a90fdc
    }
Packit Service a90fdc
    ret = 0;
Packit Service a90fdc
out:
Packit Service a90fdc
    return ret;
Packit Service a90fdc
}
Packit Service a90fdc
Packit Service a90fdc
/******************************************************************************
Packit Service a90fdc
 *                          Delete file/flink record/s from db
Packit Service a90fdc
 * ****************************************************************************/
Packit Service a90fdc
static inline int
Packit Service a90fdc
ctr_delete_hard_link_from_db(xlator_t *this, uuid_t gfid, uuid_t pargfid,
Packit Service a90fdc
                             char *basename, gfdb_fop_type_t fop_type,
Packit Service a90fdc
                             gfdb_fop_path_t fop_path)
Packit Service a90fdc
{
Packit Service a90fdc
    int ret = -1;
Packit Service a90fdc
    gfdb_db_record_t gfdb_db_record;
Packit Service a90fdc
    gf_ctr_private_t *_priv = NULL;
Packit Service a90fdc
Packit Service a90fdc
    _priv = this->private;
Packit Service a90fdc
    GF_VALIDATE_OR_GOTO(this->name, _priv, out);
Packit Service a90fdc
    GF_VALIDATE_OR_GOTO(this->name, (!gf_uuid_is_null(gfid)), out);
Packit Service a90fdc
    GF_VALIDATE_OR_GOTO(this->name, (!gf_uuid_is_null(pargfid)), out);
Packit Service a90fdc
    GF_VALIDATE_OR_GOTO(this->name, (fop_type == GFDB_FOP_DENTRY_WRITE), out);
Packit Service a90fdc
    GF_VALIDATE_OR_GOTO(
Packit Service a90fdc
        this->name, (fop_path == GFDB_FOP_UNDEL || GFDB_FOP_UNDEL_ALL), out);
Packit Service a90fdc
Packit Service a90fdc
    /* Set gfdb_db_record to 0 */
Packit Service a90fdc
    memset(&gfdb_db_record, 0, sizeof(gfdb_db_record));
Packit Service a90fdc
Packit Service a90fdc
    /* Copy basename */
Packit Service a90fdc
    if (snprintf(gfdb_db_record.file_name, GF_NAME_MAX, "%s", basename) >=
Packit Service a90fdc
        GF_NAME_MAX)
Packit Service a90fdc
        goto out;
Packit Service a90fdc
Packit Service a90fdc
    /* Copy gfid into db record */
Packit Service a90fdc
    gf_uuid_copy(gfdb_db_record.gfid, gfid);
Packit Service a90fdc
Packit Service a90fdc
    /* Copy pargid into db record */
Packit Service a90fdc
    gf_uuid_copy(gfdb_db_record.pargfid, pargfid);
Packit Service a90fdc
Packit Service a90fdc
    gfdb_db_record.gfdb_fop_path = fop_path;
Packit Service a90fdc
    gfdb_db_record.gfdb_fop_type = fop_type;
Packit Service a90fdc
Packit Service a90fdc
    /*send delete request to db*/
Packit Service a90fdc
    ret = insert_record(_priv->_db_conn, &gfdb_db_record);
Packit Service a90fdc
    if (ret) {
Packit Service a90fdc
        gf_msg(this->name, GF_LOG_ERROR, 0, CTR_MSG_INSERT_RECORD_WIND_FAILED,
Packit Service a90fdc
               "Failed to delete record. %s", basename);
Packit Service a90fdc
        goto out;
Packit Service a90fdc
    }
Packit Service a90fdc
Packit Service a90fdc
    ret = 0;
Packit Service a90fdc
out:
Packit Service a90fdc
    return ret;
Packit Service a90fdc
}
Packit Service a90fdc
Packit Service a90fdc
/******************************* Hard link function ***************************/
Packit Service a90fdc
Packit Service a90fdc
static inline gf_boolean_t
Packit Service a90fdc
__is_inode_expired(ctr_xlator_ctx_t *ctr_xlator_ctx, gf_ctr_private_t *_priv,
Packit Service a90fdc
                   gfdb_time_t *current_time)
Packit Service a90fdc
{
Packit Service a90fdc
    gf_boolean_t ret = _gf_false;
Packit Service a90fdc
    uint64_t time_diff = 0;
Packit Service a90fdc
Packit Service a90fdc
    GF_ASSERT(ctr_xlator_ctx);
Packit Service a90fdc
    GF_ASSERT(_priv);
Packit Service a90fdc
    GF_ASSERT(current_time);
Packit Service a90fdc
Packit Service a90fdc
    time_diff = current_time->tv_sec - ctr_xlator_ctx->inode_heal_period;
Packit Service a90fdc
Packit Service a90fdc
    ret = (time_diff >= _priv->ctr_lookupheal_inode_timeout) ? _gf_true
Packit Service a90fdc
                                                             : _gf_false;
Packit Service a90fdc
    return ret;
Packit Service a90fdc
}
Packit Service a90fdc
Packit Service a90fdc
static inline gf_boolean_t
Packit Service a90fdc
__is_hardlink_expired(ctr_hard_link_t *ctr_hard_link, gf_ctr_private_t *_priv,
Packit Service a90fdc
                      gfdb_time_t *current_time)
Packit Service a90fdc
{
Packit Service a90fdc
    gf_boolean_t ret = _gf_false;
Packit Service a90fdc
    uint64_t time_diff = 0;
Packit Service a90fdc
Packit Service a90fdc
    GF_ASSERT(ctr_hard_link);
Packit Service a90fdc
    GF_ASSERT(_priv);
Packit Service a90fdc
    GF_ASSERT(current_time);
Packit Service a90fdc
Packit Service a90fdc
    time_diff = current_time->tv_sec - ctr_hard_link->hardlink_heal_period;
Packit Service a90fdc
Packit Service a90fdc
    ret = ret || (time_diff >= _priv->ctr_lookupheal_link_timeout) ? _gf_true
Packit Service a90fdc
                                                                   : _gf_false;
Packit Service a90fdc
Packit Service a90fdc
    return ret;
Packit Service a90fdc
}
Packit Service a90fdc
Packit Service a90fdc
/* Return values of heal*/
Packit Service a90fdc
typedef enum ctr_heal_ret_val {
Packit Service a90fdc
    CTR_CTX_ERROR = -1,
Packit Service a90fdc
    /* No healing required */
Packit Service a90fdc
    CTR_TRY_NO_HEAL = 0,
Packit Service a90fdc
    /* Try healing hard link */
Packit Service a90fdc
    CTR_TRY_HARDLINK_HEAL = 1,
Packit Service a90fdc
    /* Try healing inode */
Packit Service a90fdc
    CTR_TRY_INODE_HEAL = 2,
Packit Service a90fdc
} ctr_heal_ret_val_t;
Packit Service a90fdc
Packit Service a90fdc
/**
Packit Service a90fdc
 * @brief Function to add hard link to the inode context variable.
Packit Service a90fdc
 *        The inode context maintainences a in-memory list. This is used
Packit Service a90fdc
 *        smart healing of database.
Packit Service a90fdc
 * @param frame of the FOP
Packit Service a90fdc
 * @param this is the Xlator instant
Packit Service a90fdc
 * @param inode
Packit Service a90fdc
 * @return Return ctr_heal_ret_val_t
Packit Service a90fdc
 */
Packit Service a90fdc
Packit Service a90fdc
static inline ctr_heal_ret_val_t
Packit Service a90fdc
add_hard_link_ctx(call_frame_t *frame, xlator_t *this, inode_t *inode)
Packit Service a90fdc
{
Packit Service a90fdc
    ctr_heal_ret_val_t ret_val = CTR_TRY_NO_HEAL;
Packit Service a90fdc
    int ret = -1;
Packit Service a90fdc
    gf_ctr_local_t *ctr_local = NULL;
Packit Service a90fdc
    ctr_xlator_ctx_t *ctr_xlator_ctx = NULL;
Packit Service a90fdc
    ctr_hard_link_t *ctr_hard_link = NULL;
Packit Service a90fdc
    gf_ctr_private_t *_priv = NULL;
Packit Service a90fdc
    gfdb_time_t current_time = {0};
Packit Service a90fdc
Packit Service a90fdc
    GF_ASSERT(frame);
Packit Service a90fdc
    GF_ASSERT(this);
Packit Service a90fdc
    GF_ASSERT(inode);
Packit Service a90fdc
    GF_ASSERT(this->private);
Packit Service a90fdc
Packit Service a90fdc
    _priv = this->private;
Packit Service a90fdc
Packit Service a90fdc
    ctr_local = frame->local;
Packit Service a90fdc
    if (!ctr_local) {
Packit Service a90fdc
        goto out;
Packit Service a90fdc
    }
Packit Service a90fdc
Packit Service a90fdc
    ctr_xlator_ctx = init_ctr_xlator_ctx(this, inode);
Packit Service a90fdc
    if (!ctr_xlator_ctx) {
Packit Service a90fdc
        gf_msg(this->name, GF_LOG_ERROR, 0,
Packit Service a90fdc
               CTR_MSG_ACCESS_CTR_INODE_CONTEXT_FAILED,
Packit Service a90fdc
               "Failed accessing ctr inode context");
Packit Service a90fdc
        goto out;
Packit Service a90fdc
    }
Packit Service a90fdc
Packit Service a90fdc
    LOCK(&ctr_xlator_ctx->lock);
Packit Service a90fdc
Packit Service a90fdc
    /* Check if the hard link already exists
Packit Service a90fdc
     * in the ctr inode context*/
Packit Service a90fdc
    ctr_hard_link = ctr_search_hard_link_ctx(this, ctr_xlator_ctx,
Packit Service a90fdc
                                             CTR_DB_REC(ctr_local).pargfid,
Packit Service a90fdc
                                             CTR_DB_REC(ctr_local).file_name);
Packit Service a90fdc
    /* if there then ignore */
Packit Service a90fdc
    if (ctr_hard_link) {
Packit Service a90fdc
        ret = gettimeofday(&current_time, NULL);
Packit Service a90fdc
        if (ret == -1) {
Packit Service a90fdc
            gf_log(this->name, GF_LOG_ERROR, "Failed to get current time");
Packit Service a90fdc
            ret_val = CTR_CTX_ERROR;
Packit Service a90fdc
            goto unlock;
Packit Service a90fdc
        }
Packit Service a90fdc
Packit Service a90fdc
        if (__is_hardlink_expired(ctr_hard_link, _priv, &current_time)) {
Packit Service a90fdc
            ctr_hard_link->hardlink_heal_period = current_time.tv_sec;
Packit Service a90fdc
            ret_val = ret_val | CTR_TRY_HARDLINK_HEAL;
Packit Service a90fdc
        }
Packit Service a90fdc
Packit Service a90fdc
        if (__is_inode_expired(ctr_xlator_ctx, _priv, &current_time)) {
Packit Service a90fdc
            ctr_xlator_ctx->inode_heal_period = current_time.tv_sec;
Packit Service a90fdc
            ret_val = ret_val | CTR_TRY_INODE_HEAL;
Packit Service a90fdc
        }
Packit Service a90fdc
Packit Service a90fdc
        goto unlock;
Packit Service a90fdc
    }
Packit Service a90fdc
Packit Service a90fdc
    /* Add the hard link to the list*/
Packit Service a90fdc
    ret = ctr_add_hard_link(this, ctr_xlator_ctx, CTR_DB_REC(ctr_local).pargfid,
Packit Service a90fdc
                            CTR_DB_REC(ctr_local).file_name);
Packit Service a90fdc
    if (ret) {
Packit Service a90fdc
        gf_msg(this->name, GF_LOG_ERROR, 0,
Packit Service a90fdc
               CTR_MSG_ADD_HARDLINK_TO_CTR_INODE_CONTEXT_FAILED,
Packit Service a90fdc
               "Failed to add hardlink to the ctr inode context");
Packit Service a90fdc
        ret_val = CTR_CTX_ERROR;
Packit Service a90fdc
        goto unlock;
Packit Service a90fdc
    }
Packit Service a90fdc
Packit Service a90fdc
    ret_val = CTR_TRY_NO_HEAL;
Packit Service a90fdc
unlock:
Packit Service a90fdc
    UNLOCK(&ctr_xlator_ctx->lock);
Packit Service a90fdc
out:
Packit Service a90fdc
    return ret_val;
Packit Service a90fdc
}
Packit Service a90fdc
Packit Service a90fdc
static inline int
Packit Service a90fdc
delete_hard_link_ctx(call_frame_t *frame, xlator_t *this, inode_t *inode)
Packit Service a90fdc
{
Packit Service a90fdc
    int ret = -1;
Packit Service a90fdc
    ctr_xlator_ctx_t *ctr_xlator_ctx = NULL;
Packit Service a90fdc
    gf_ctr_local_t *ctr_local = NULL;
Packit Service a90fdc
Packit Service a90fdc
    GF_ASSERT(frame);
Packit Service a90fdc
    GF_ASSERT(this);
Packit Service a90fdc
    GF_ASSERT(inode);
Packit Service a90fdc
Packit Service a90fdc
    ctr_local = frame->local;
Packit Service a90fdc
    if (!ctr_local) {
Packit Service a90fdc
        goto out;
Packit Service a90fdc
    }
Packit Service a90fdc
Packit Service a90fdc
    ctr_xlator_ctx = get_ctr_xlator_ctx(this, inode);
Packit Service a90fdc
    if (!ctr_xlator_ctx) {
Packit Service a90fdc
        /* Since there is no ctr inode context so nothing more to do */
Packit Service a90fdc
        ret = 0;
Packit Service a90fdc
        goto out;
Packit Service a90fdc
    }
Packit Service a90fdc
Packit Service a90fdc
    ret = ctr_delete_hard_link(this, ctr_xlator_ctx,
Packit Service a90fdc
                               CTR_DB_REC(ctr_local).pargfid,
Packit Service a90fdc
                               CTR_DB_REC(ctr_local).file_name);
Packit Service a90fdc
    if (ret) {
Packit Service a90fdc
        gf_msg(this->name, GF_LOG_ERROR, 0, CTR_MSG_DELETE_HARDLINK_FAILED,
Packit Service a90fdc
               "Failed to delete hard link");
Packit Service a90fdc
        goto out;
Packit Service a90fdc
    }
Packit Service a90fdc
Packit Service a90fdc
    ret = 0;
Packit Service a90fdc
Packit Service a90fdc
out:
Packit Service a90fdc
    return ret;
Packit Service a90fdc
}
Packit Service a90fdc
Packit Service a90fdc
static inline int
Packit Service a90fdc
update_hard_link_ctx(call_frame_t *frame, xlator_t *this, inode_t *inode)
Packit Service a90fdc
{
Packit Service a90fdc
    int ret = -1;
Packit Service a90fdc
    ctr_xlator_ctx_t *ctr_xlator_ctx = NULL;
Packit Service a90fdc
    gf_ctr_local_t *ctr_local = NULL;
Packit Service a90fdc
Packit Service a90fdc
    GF_ASSERT(frame);
Packit Service a90fdc
    GF_ASSERT(this);
Packit Service a90fdc
    GF_ASSERT(inode);
Packit Service a90fdc
Packit Service a90fdc
    ctr_local = frame->local;
Packit Service a90fdc
    if (!ctr_local) {
Packit Service a90fdc
        goto out;
Packit Service a90fdc
    }
Packit Service a90fdc
Packit Service a90fdc
    ctr_xlator_ctx = init_ctr_xlator_ctx(this, inode);
Packit Service a90fdc
    if (!ctr_xlator_ctx) {
Packit Service a90fdc
        gf_msg(this->name, GF_LOG_ERROR, 0,
Packit Service a90fdc
               CTR_MSG_ACCESS_CTR_INODE_CONTEXT_FAILED,
Packit Service a90fdc
               "Failed accessing ctr inode context");
Packit Service a90fdc
        goto out;
Packit Service a90fdc
    }
Packit Service a90fdc
Packit Service a90fdc
    ret = ctr_update_hard_link(
Packit Service a90fdc
        this, ctr_xlator_ctx, CTR_DB_REC(ctr_local).pargfid,
Packit Service a90fdc
        CTR_DB_REC(ctr_local).file_name, CTR_DB_REC(ctr_local).old_pargfid,
Packit Service a90fdc
        CTR_DB_REC(ctr_local).old_file_name);
Packit Service a90fdc
    if (ret) {
Packit Service a90fdc
        gf_msg(this->name, GF_LOG_ERROR, 0, CTR_MSG_DELETE_HARDLINK_FAILED,
Packit Service a90fdc
               "Failed to delete hard link");
Packit Service a90fdc
        goto out;
Packit Service a90fdc
    }
Packit Service a90fdc
Packit Service a90fdc
    ret = 0;
Packit Service a90fdc
Packit Service a90fdc
out:
Packit Service a90fdc
    return ret;
Packit Service a90fdc
}
Packit Service a90fdc
Packit Service a90fdc
/******************************************************************************
Packit Service a90fdc
 *
Packit Service a90fdc
 *                      CTR xlator init related functions
Packit Service a90fdc
 *
Packit Service a90fdc
 *
Packit Service a90fdc
 * ****************************************************************************/
Packit Service a90fdc
int
Packit Service a90fdc
extract_db_params(xlator_t *this, dict_t *params_dict, gfdb_db_type_t db_type);
Packit Service a90fdc
Packit Service a90fdc
int
Packit Service a90fdc
extract_ctr_options(xlator_t *this, gf_ctr_private_t *_priv);
Packit Service a90fdc
Packit Service a90fdc
#endif