|
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(¤t_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, ¤t_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, ¤t_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
|