/*
Copyright (c) 2007-2010 Gluster, Inc. <http://www.gluster.com>
This file is part of GlusterFS.
GlusterFS is free software; you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published
by the Free Software Foundation; either version 3 of the License,
or (at your option) any later version.
GlusterFS is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see
<http://www.gnu.org/licenses/>.
*/
#include "dict.h"
#include "byte-order.h"
#include "common-utils.h"
#include "afr.h"
#include "afr-transaction.h"
#include <signal.h>
#define LOCKED_NO 0x0 /* no lock held */
#define LOCKED_YES 0x1 /* for DATA, METADATA, ENTRY and higher_path */
#define LOCKED_LOWER 0x2 /* for lower path */
int
afr_lock_blocking (call_frame_t *frame, xlator_t *this, int child_index);
static uint64_t afr_lock_number = 1;
static uint64_t
get_afr_lock_number ()
{
return (++afr_lock_number);
}
int
afr_set_lock_number (call_frame_t *frame, xlator_t *this)
{
afr_local_t *local = NULL;
afr_internal_lock_t *int_lock = NULL;
local = frame->local;
int_lock = &local->internal_lock;
int_lock->lock_number = get_afr_lock_number ();
return 0;
}
void
afr_set_lk_owner (call_frame_t *frame, xlator_t *this)
{
if (!frame->root->lk_owner) {
gf_log (this->name, GF_LOG_TRACE,
"Setting lk-owner=%llu",
(unsigned long long) (unsigned long)frame->root);
frame->root->lk_owner = (uint64_t) (unsigned long)frame->root;
}
}
static int
is_afr_lock_selfheal (afr_local_t *local)
{
afr_internal_lock_t *int_lock = NULL;
int ret = -1;
int_lock = &local->internal_lock;
switch (int_lock->selfheal_lk_type) {
case AFR_DATA_SELF_HEAL_LK:
case AFR_METADATA_SELF_HEAL_LK:
ret = 1;
break;
case AFR_ENTRY_SELF_HEAL_LK:
ret = 0;
break;
}
return ret;
}
int32_t
internal_lock_count (call_frame_t *frame, xlator_t *this,
afr_fd_ctx_t *fd_ctx)
{
afr_local_t *local = NULL;
afr_private_t *priv = NULL;
int32_t call_count = 0;
int i = 0;
local = frame->local;
priv = this->private;
if (fd_ctx) {
GF_ASSERT (local->fd);
for (i = 0; i < priv->child_count; i++) {
if (local->child_up[i] && fd_ctx->opened_on[i])
++call_count;
}
} else {
for (i = 0; i < priv->child_count; i++) {
if (local->child_up[i])
++call_count;
}
}
return call_count;
}
static void
afr_print_inodelk (char *str, int size, int cmd,
struct gf_flock *flock, uint64_t owner)
{
char *cmd_str = NULL;
char *type_str = NULL;
switch (cmd) {
#if F_GETLK != F_GETLK64
case F_GETLK64:
#endif
case F_GETLK:
cmd_str = "GETLK";
break;
#if F_SETLK != F_SETLK64
case F_SETLK64:
#endif
case F_SETLK:
cmd_str = "SETLK";
break;
#if F_SETLKW != F_SETLKW64
case F_SETLKW64:
#endif
case F_SETLKW:
cmd_str = "SETLKW";
break;
default:
cmd_str = "<null>";
break;
}
switch (flock->l_type) {
case F_RDLCK:
type_str = "READ";
break;
case F_WRLCK:
type_str = "WRITE";
break;
case F_UNLCK:
type_str = "UNLOCK";
break;
default:
type_str = "UNKNOWN";
break;
}
snprintf (str, size, "lock=INODELK, cmd=%s, type=%s, "
"start=%llu, len=%llu, pid=%llu, lk-owner=%llu",
cmd_str, type_str, (unsigned long long) flock->l_start,
(unsigned long long) flock->l_len,
(unsigned long long) flock->l_pid,
(unsigned long long) owner);
}
static void
afr_print_lockee (char *str, int size, loc_t *loc, fd_t *fd,
int child_index)
{
snprintf (str, size, "path=%s, fd=%p, child=%d",
loc->path ? loc->path : "<nul>",
fd ? fd : NULL,
child_index);
}
void
afr_print_entrylk (char *str, int size, const char *basename,
uint64_t owner)
{
snprintf (str, size, "Basename=%s, lk-owner=%llu",
basename ? basename : "<nul>",
(unsigned long long)owner);
}
static void
afr_print_verdict (int op_ret, int op_errno, char *str)
{
if (op_ret < 0) {
if (op_errno == EAGAIN)
strcpy (str, "EAGAIN");
else
strcpy (str, "FAILED");
}
else
strcpy (str, "GRANTED");
}
static void
afr_set_lock_call_type (afr_lock_call_type_t lock_call_type,
char *lock_call_type_str,
afr_internal_lock_t *int_lock)
{
switch (lock_call_type) {
case AFR_INODELK_TRANSACTION:
if (int_lock->transaction_lk_type == AFR_TRANSACTION_LK)
strcpy (lock_call_type_str, "AFR_INODELK_TRANSACTION");
else
strcpy (lock_call_type_str, "AFR_INODELK_SELFHEAL");
break;
case AFR_INODELK_NB_TRANSACTION:
if (int_lock->transaction_lk_type == AFR_TRANSACTION_LK)
strcpy (lock_call_type_str, "AFR_INODELK_NB_TRANSACTION");
else
strcpy (lock_call_type_str, "AFR_INODELK_NB_SELFHEAL");
break;
case AFR_ENTRYLK_TRANSACTION:
if (int_lock->transaction_lk_type == AFR_TRANSACTION_LK)
strcpy (lock_call_type_str, "AFR_ENTRYLK_TRANSACTION");
else
strcpy (lock_call_type_str, "AFR_ENTRYLK_SELFHEAL");
break;
case AFR_ENTRYLK_NB_TRANSACTION:
if (int_lock->transaction_lk_type == AFR_TRANSACTION_LK)
strcpy (lock_call_type_str, "AFR_ENTRYLK_NB_TRANSACTION");
else
strcpy (lock_call_type_str, "AFR_ENTRYLK_NB_SELFHEAL");
break;
default:
strcpy (lock_call_type_str, "UNKNOWN");
break;
}
}
static void
afr_trace_inodelk_out (call_frame_t *frame, afr_lock_call_type_t lock_call_type,
afr_lock_op_type_t lk_op_type, struct gf_flock *flock,
int op_ret, int op_errno, int32_t child_index)
{
xlator_t *this = NULL;
afr_internal_lock_t *int_lock = NULL;
afr_local_t *local = NULL;
afr_private_t *priv = NULL;
char lockee[256];
char lock_call_type_str[256];
char verdict[16];
this = THIS;
local = frame->local;
int_lock = &local->internal_lock;
priv = this->private;
if (!priv->inodelk_trace) {
return;
}
afr_print_lockee (lockee, 256, &local->loc, local->fd, child_index);
afr_set_lock_call_type (lock_call_type, lock_call_type_str, int_lock);
afr_print_verdict (op_ret, op_errno, verdict);
gf_log (this->name, GF_LOG_INFO,
"[%s %s] [%s] Lockee={%s} Number={%llu}",
lock_call_type_str,
lk_op_type == AFR_LOCK_OP ? "LOCK REPLY" : "UNLOCK REPLY",
verdict,
lockee,
(unsigned long long) int_lock->lock_number);
}
static void
afr_trace_inodelk_in (call_frame_t *frame, afr_lock_call_type_t lock_call_type,
afr_lock_op_type_t lk_op_type, struct gf_flock *flock,
int32_t cmd, int32_t child_index)
{
xlator_t *this = NULL;
afr_local_t *local = NULL;
afr_internal_lock_t *int_lock = NULL;
afr_private_t *priv = NULL;
char lock[256];
char lockee[256];
char lock_call_type_str[256];
this = THIS;
local = frame->local;
int_lock = &local->internal_lock;
priv = this->private;
if (!priv->inodelk_trace) {
return;
}
afr_print_inodelk (lock, 256, cmd, flock, frame->root->lk_owner);
afr_print_lockee (lockee, 256, &local->loc, local->fd, child_index);
afr_set_lock_call_type (lock_call_type, lock_call_type_str, int_lock);
gf_log (this->name, GF_LOG_INFO,
"[%s %s] Lock={%s} Lockee={%s} Number={%llu}",
lock_call_type_str,
lk_op_type == AFR_LOCK_OP ? "LOCK REQUEST" : "UNLOCK REQUEST",
lock, lockee,
(unsigned long long) int_lock->lock_number);
}
static void
afr_trace_entrylk_in (call_frame_t *frame, afr_lock_call_type_t lock_call_type,
afr_lock_op_type_t lk_op_type, const char *basename,
int32_t child_index)
{
xlator_t *this = NULL;
afr_local_t *local = NULL;
afr_internal_lock_t *int_lock = NULL;
afr_private_t *priv = NULL;
char lock[256];
char lockee[256];
char lock_call_type_str[256];
this = THIS;
local = frame->local;
int_lock = &local->internal_lock;
priv = this->private;
if (!priv->entrylk_trace) {
return;
}
afr_print_entrylk (lock, 256, basename, frame->root->lk_owner);
afr_print_lockee (lockee, 256, &local->loc, local->fd, child_index);
afr_set_lock_call_type (lock_call_type, lock_call_type_str, int_lock);
gf_log (this->name, GF_LOG_INFO,
"[%s %s] Lock={%s} Lockee={%s} Number={%llu}",
lock_call_type_str,
lk_op_type == AFR_LOCK_OP ? "LOCK REQUEST" : "UNLOCK REQUEST",
lock, lockee,
(unsigned long long) int_lock->lock_number);
}
static void
afr_trace_entrylk_out (call_frame_t *frame, afr_lock_call_type_t lock_call_type,
afr_lock_op_type_t lk_op_type, const char *basename, int op_ret,
int op_errno, int32_t child_index)
{
xlator_t *this = NULL;
afr_internal_lock_t *int_lock = NULL;
afr_local_t *local = NULL;
afr_private_t *priv = NULL;
char lock[256];
char lockee[256];
char lock_call_type_str[256];
char verdict[16];
this = THIS;
local = frame->local;
int_lock = &local->internal_lock;
priv = this->private;
if (!priv->entrylk_trace) {
return;
}
afr_print_lockee (lockee, 256, &local->loc, local->fd, child_index);
afr_set_lock_call_type (lock_call_type, lock_call_type_str, int_lock);
afr_print_verdict (op_ret, op_errno, verdict);
gf_log (this->name, GF_LOG_INFO,
"[%s %s] [%s] Lock={%s} Lockee={%s} Number={%llu}",
lock_call_type_str,
lk_op_type == AFR_LOCK_OP ? "LOCK REPLY" : "UNLOCK REPLY",
verdict,
|