summaryrefslogtreecommitdiffstats
path: root/xlators/protocol/client/src/client-lk.c
diff options
context:
space:
mode:
Diffstat (limited to 'xlators/protocol/client/src/client-lk.c')
-rw-r--r--xlators/protocol/client/src/client-lk.c439
1 files changed, 31 insertions, 408 deletions
diff --git a/xlators/protocol/client/src/client-lk.c b/xlators/protocol/client/src/client-lk.c
index c018d5375..1fd8f0d50 100644
--- a/xlators/protocol/client/src/client-lk.c
+++ b/xlators/protocol/client/src/client-lk.c
@@ -1,32 +1,21 @@
/*
- Copyright (c) 2008-2010 Gluster, Inc. <http://www.gluster.com>
+ Copyright (c) 2008-2012 Red Hat, Inc. <http://www.redhat.com>
This file is part of GlusterFS.
- GlusterFS is free software; you can redistribute it and/or modify
- it under the terms of the GNU Affero General Public License as published
- by the Free Software Foundation; either version 3 of the License,
- or (at your option) any later version.
-
- GlusterFS is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Affero General Public License for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this program. If not, see
- <http://www.gnu.org/licenses/>.
+ This file is licensed to you under your choice of the GNU Lesser
+ General Public License, version 3 or any later version (LGPLv3 or
+ later), or the GNU General Public License, version 2 (GPLv2), in all
+ cases as published by the Free Software Foundation.
*/
#include "common-utils.h"
#include "xlator.h"
#include "client.h"
+#include "lkowner.h"
static void
__insert_and_merge (clnt_fd_ctx_t *fdctx, client_posix_lock_t *lock);
-static int
-client_send_recovery_lock (call_frame_t *frame, xlator_t *this,
- client_posix_lock_t *lock);
static void
__dump_client_lock (client_posix_lock_t *lock)
{
@@ -34,13 +23,13 @@ __dump_client_lock (client_posix_lock_t *lock)
this = THIS;
- gf_log (this->name, GF_LOG_TRACE,
+ gf_log (this->name, GF_LOG_INFO,
"{fd=%p}"
- "{%s lk-owner:%"PRIu64" %"PRId64" - %"PRId64"}"
+ "{%s lk-owner:%s %"PRId64" - %"PRId64"}"
"{start=%"PRId64" end=%"PRId64"}",
lock->fd,
lock->fl_type == F_WRLCK ? "Write-Lock" : "Read-Lock",
- lock->owner,
+ lkowner_utoa (&lock->owner),
lock->user_flock.l_start,
lock->user_flock.l_len,
lock->fl_start,
@@ -133,12 +122,6 @@ add_locks (client_posix_lock_t *l1, client_posix_lock_t *l2)
return sum;
}
-/* Return true if the locks have the same owner */
-static int
-same_owner (client_posix_lock_t *l1, client_posix_lock_t *l2)
-{
- return ((l1->owner == l2->owner));
-}
/* Return true if the locks overlap, false otherwise */
static int
@@ -241,7 +224,8 @@ subtract_locks (client_posix_lock_t *big, client_posix_lock_t *small)
memcpy (v.locks[1], small, sizeof (client_posix_lock_t));
}
else {
- gf_log ("client-protocol", GF_LOG_ERROR,
+ /* LOG-TODO : decide what more info is required here*/
+ gf_log ("client-protocol", GF_LOG_CRITICAL,
"Unexpected case in subtract_locks. Please send "
"a bug report to gluster-devel@nongnu.org");
}
@@ -284,11 +268,11 @@ __insert_and_merge (clnt_fd_ctx_t *fdctx, client_posix_lock_t *lock)
if (!locks_overlap (conf, lock))
continue;
- if (same_owner (conf, lock)) {
+ if (is_same_lkowner (&conf->owner, &lock->owner)) {
if (conf->fl_type == lock->fl_type) {
sum = add_locks (lock, conf);
- sum->fd = lock->fd;
+ sum->fd = lock->fd;
__delete_client_lock (conf);
__destroy_client_lock (conf);
@@ -300,8 +284,8 @@ __insert_and_merge (clnt_fd_ctx_t *fdctx, client_posix_lock_t *lock)
} else {
sum = add_locks (lock, conf);
- sum->fd = conf->fd;
- sum->owner = conf->owner;
+ sum->fd = conf->fd;
+ sum->owner = conf->owner;
v = subtract_locks (sum, lock);
@@ -364,9 +348,9 @@ destroy_client_lock (client_posix_lock_t *lock)
}
int32_t
-delete_granted_locks_owner (fd_t *fd, uint64_t owner)
+delete_granted_locks_owner (fd_t *fd, gf_lkowner_t *owner)
{
- clnt_fd_ctx_t *fdctx = NULL;
+ clnt_fd_ctx_t *fdctx = NULL;
client_posix_lock_t *lock = NULL;
client_posix_lock_t *tmp = NULL;
xlator_t *this = NULL;
@@ -379,7 +363,7 @@ delete_granted_locks_owner (fd_t *fd, uint64_t owner)
this = THIS;
fdctx = this_fd_get_ctx (fd, this);
if (!fdctx) {
- gf_log (this->name, GF_LOG_DEBUG,
+ gf_log (this->name, GF_LOG_WARNING,
"fdctx not valid");
ret = -1;
goto out;
@@ -388,7 +372,7 @@ delete_granted_locks_owner (fd_t *fd, uint64_t owner)
pthread_mutex_lock (&fdctx->mutex);
{
list_for_each_entry_safe (lock, tmp, &fdctx->lock_list, list) {
- if (lock->owner == owner) {
+ if (!is_same_lkowner (&lock->owner, owner)) {
list_del_init (&lock->list);
list_add_tail (&lock->list, &delete_list);
count++;
@@ -402,8 +386,8 @@ delete_granted_locks_owner (fd_t *fd, uint64_t owner)
destroy_client_lock (lock);
}
-/* FIXME: Need to actually print the locks instead of count */
- gf_log (this->name, GF_LOG_DEBUG,
+ /* FIXME: Need to actually print the locks instead of count */
+ gf_log (this->name, GF_LOG_TRACE,
"Number of locks cleared=%d", count);
out:
@@ -437,23 +421,12 @@ delete_granted_locks_fd (clnt_fd_ctx_t *fdctx)
}
/* FIXME: Need to actually print the locks instead of count */
- gf_log (this->name, GF_LOG_DEBUG,
+ gf_log (this->name, GF_LOG_TRACE,
"Number of locks cleared=%d", count);
return ret;
}
-static void
-client_mark_bad_fd (fd_t *fd, clnt_fd_ctx_t *fdctx)
-{
- xlator_t *this = NULL;
-
- this = THIS;
- if (fdctx)
- fdctx->remote_fd = -1;
- this_fd_set_ctx (fd, this, NULL, fdctx);
-}
-
int32_t
client_cmd_to_gf_cmd (int32_t cmd, int32_t *gf_cmd)
{
@@ -481,19 +454,14 @@ client_cmd_to_gf_cmd (int32_t cmd, int32_t *gf_cmd)
}
static client_posix_lock_t *
-new_client_lock (struct gf_flock *flock, uint64_t owner,
+new_client_lock (struct gf_flock *flock, gf_lkowner_t *owner,
int32_t cmd, fd_t *fd)
{
client_posix_lock_t *new_lock = NULL;
- xlator_t *this = NULL;
-
- this = THIS;
new_lock = GF_CALLOC (1, sizeof (*new_lock),
gf_client_mt_clnt_lock_t);
if (!new_lock) {
- gf_log (this->name, GF_LOG_ERROR,
- "Out of memory");
goto out;
}
@@ -509,9 +477,9 @@ new_client_lock (struct gf_flock *flock, uint64_t owner,
else
new_lock->fl_end = flock->l_start + flock->l_len - 1;
- new_lock->owner = owner;
- new_lock->cmd = cmd; /* Not really useful */
+ new_lock->owner = *owner;
+ new_lock->cmd = cmd; /* Not really useful */
out:
return new_lock;
@@ -528,8 +496,8 @@ client_save_number_fds (clnt_conf_t *conf, int count)
}
int
-client_add_lock_for_recovery (fd_t *fd, struct gf_flock *flock, uint64_t owner,
- int32_t cmd)
+client_add_lock_for_recovery (fd_t *fd, struct gf_flock *flock,
+ gf_lkowner_t *owner, int32_t cmd)
{
clnt_fd_ctx_t *fdctx = NULL;
xlator_t *this = NULL;
@@ -548,16 +516,14 @@ client_add_lock_for_recovery (fd_t *fd, struct gf_flock *flock, uint64_t owner,
pthread_mutex_unlock (&conf->lock);
if (!fdctx) {
- gf_log (this->name, GF_LOG_DEBUG,
- "failed to get fd context. Marking as bad fd.");
+ gf_log (this->name, GF_LOG_WARNING,
+ "failed to get fd context. sending EBADFD");
ret = -EBADFD;
goto out;
}
lock = new_client_lock (flock, owner, cmd, fd);
if (!lock) {
- gf_log (this->name, GF_LOG_ERROR,
- "Out of memory");
ret = -ENOMEM;
goto out;
}
@@ -569,349 +535,6 @@ out:
}
-static int
-construct_reserve_unlock (struct gf_flock *lock, call_frame_t *frame,
- client_posix_lock_t *client_lock)
-{
- GF_ASSERT (lock);
- GF_ASSERT (frame);
- GF_ASSERT (frame->root->lk_owner);
-
- lock->l_type = F_UNLCK;
- lock->l_start = 0;
- lock->l_whence = SEEK_SET;
- lock->l_len = 0; /* Whole file */
- lock->l_pid = (uint64_t)(unsigned long)frame->root;
-
- frame->root->lk_owner = client_lock->owner;
-
- return 0;
-}
-
-static int
-construct_reserve_lock (client_posix_lock_t *client_lock, call_frame_t *frame,
- struct gf_flock *lock)
-{
- GF_ASSERT (client_lock);
-
- memcpy (lock, &(client_lock->user_flock), sizeof (struct gf_flock));
-
- frame->root->lk_owner = client_lock->owner;
-
- return 0;
-}
-
-uint64_t
-decrement_reopen_fd_count (xlator_t *this, clnt_conf_t *conf)
-{
- uint64_t fd_count = 0;
-
- LOCK (&conf->rec_lock);
- {
- fd_count = --(conf->reopen_fd_count);
- }
- UNLOCK (&conf->rec_lock);
-
- if (fd_count == 0) {
- gf_log (this->name, GF_LOG_DEBUG,
- "last fd open'd/lock-self-heal'd - notifying CHILD-UP");
- client_notify_parents_child_up (this);
- }
-
- return fd_count;
-}
-
-int32_t
-client_remove_reserve_lock_cbk (call_frame_t *frame,
- void *cookie,
- xlator_t *this,
- int32_t op_ret,
- int32_t op_errno,
- struct gf_flock *lock)
-{
- clnt_local_t *local = NULL;
- clnt_conf_t *conf = NULL;
-
- uint64_t fd_count = 0;
-
- local = frame->local;
- conf = this->private;
-
- if (op_ret < 0) {
- /* TODO: critical error describing recovery command
- and blanket on ops on fd */
- gf_log (this->name, GF_LOG_CRITICAL,
- "Lock recovery failed with error msg=%s",
- strerror(op_errno));
- goto cleanup;
- }
-
- gf_log (this->name, GF_LOG_DEBUG,
- "Removing reserve lock was successful.");
-
-cleanup:
- frame->local = NULL;
- client_mark_bad_fd (local->client_lock->fd,
- local->fdctx);
- destroy_client_lock (local->client_lock);
- client_local_wipe (local);
- STACK_DESTROY (frame->root);
- fd_count = decrement_reopen_fd_count (this, conf);
- gf_log (this->name, GF_LOG_DEBUG,
- "Need to attempt lock recovery on %lld open fds",
- (unsigned long long) fd_count);
- return 0;
-}
-
-static void
-client_remove_reserve_lock (xlator_t *this, call_frame_t *frame,
- client_posix_lock_t *lock)
-{
- struct gf_flock unlock;
- clnt_local_t *local = NULL;
-
- local = frame->local;
- construct_reserve_unlock (&unlock, frame, lock);
-
- STACK_WIND (frame, client_remove_reserve_lock_cbk,
- this, this->fops->lk,
- lock->fd, F_RESLK_UNLCK, &unlock);
-}
-
-static client_posix_lock_t *
-get_next_recovery_lock (xlator_t *this, clnt_local_t *local)
-{
- client_posix_lock_t *lock = NULL;
-
- pthread_mutex_lock (&local->mutex);
- {
- if (list_empty (&local->lock_list)) {
- gf_log (this->name, GF_LOG_DEBUG,
- "lock-list empty");
- goto unlock;
- }
-
- lock = list_entry ((local->lock_list).next, typeof (*lock), list);
- list_del_init (&lock->list);
- }
-unlock:
- pthread_mutex_unlock (&local->mutex);
-
- return lock;
-
-}
-
-int32_t
-client_reserve_lock_cbk (call_frame_t *frame,
- void *cookie,
- xlator_t *this,
- int32_t op_ret,
- int32_t op_errno,
- struct gf_flock *lock)
-{
-
- clnt_local_t *local = NULL;
- clnt_conf_t *conf = NULL;
-
- uint64_t fd_count = 0;
-
- local = frame->local;
- conf = this->private;
-
- /* Got the reserve lock. Check if lock is grantable and proceed
- with the real lk call */
-
- if (op_ret >= 0) {
- /* Lock is grantable if flock reflects a successful getlk() call*/
- if (lock->l_type == F_UNLCK && lock->l_pid) {
- gf_log (this->name, GF_LOG_DEBUG,
- "Got the reservelk, but the lock is not grantable. ");
- client_remove_reserve_lock (this, frame, local->client_lock);
- goto out;
- }
-
- gf_log (this->name, GF_LOG_DEBUG,
- "Reserve Lock succeeded");
- client_send_recovery_lock (frame, this, local->client_lock);
- goto out;
- }
-
- /* Somebody else has a reserve lk. Lock conflict detected.
- Mark fd as bad */
-
- gf_log (this->name, GF_LOG_DEBUG,
- "Reservelk OP failed. Aborting lock recovery and marking bad fd");
-
- client_mark_bad_fd (local->client_lock->fd,
- local->fdctx);
- destroy_client_lock (local->client_lock);
- frame->local = NULL;
- client_local_wipe (local);
- STACK_DESTROY (frame->root);
- fd_count = decrement_reopen_fd_count (this, conf);
- gf_log (this->name, GF_LOG_DEBUG,
- "Need to attempt lock recovery on %lld open fds",
- (unsigned long long) fd_count);
-
-out:
- return 0;
-}
-
-int32_t
-client_recovery_lock_cbk (call_frame_t *frame,
- void *cookie,
- xlator_t *this,
- int32_t op_ret,
- int32_t op_errno,
- struct gf_flock *lock)
-{
- clnt_local_t *local = NULL;
- clnt_fd_ctx_t *fdctx = NULL;
- clnt_conf_t *conf = NULL;
- client_posix_lock_t *next_lock = NULL;
-
- struct gf_flock reserve_flock;
- uint64_t fd_count = 0;
-
- local = frame->local;
- conf = this->private;
-
- if (op_ret < 0) {
- /* TODO: critical error describing recovery command
- and blanket on ops on fd */
- gf_log (this->name, GF_LOG_CRITICAL,
- "Lock recovery failed with error msg=%s",
- strerror(op_errno));
-
- client_mark_bad_fd (local->client_lock->fd,
- local->fdctx);
- goto cleanup;
-
- /* Lock recovered. Continue with reserve lock for next lock */
- } else {
- gf_log (this->name, GF_LOG_DEBUG,
- "lock recovered successfully - Continuing with next lock.");
-
- next_lock = get_next_recovery_lock (this, local);
- if (!next_lock) {
- gf_log (this->name, GF_LOG_DEBUG,
- "All locks recovered on fd");
- goto cleanup;
- }
-
- construct_reserve_lock (next_lock, frame, &reserve_flock);
- local->fdctx = fdctx;
- local->client_lock = next_lock;
-
- STACK_WIND (frame, client_reserve_lock_cbk,
- this, this->fops->lk,
- next_lock->fd, F_RESLK_LCK, &reserve_flock);
- goto out;
-
- }
-
-cleanup:
- frame->local = NULL;
- client_local_wipe (local);
- if (local->client_lock)
- destroy_client_lock (local->client_lock);
- STACK_DESTROY (frame->root);
- fd_count = decrement_reopen_fd_count (this, conf);
- gf_log (this->name, GF_LOG_DEBUG,
- "Need to attempt lock recovery on %lld open fds",
- (unsigned long long) fd_count);
-
-out:
- return 0;
-}
-
-static int
-client_send_recovery_lock (call_frame_t *frame, xlator_t *this,
- client_posix_lock_t *lock)
-{
-
- frame->root->lk_owner = lock->owner;
-
- /* Send all locks as F_SETLK to prevent the frame
- from blocking if there is a conflict */
-
- STACK_WIND (frame, client_recovery_lock_cbk,
- this, this->fops->lk,
- lock->fd, F_SETLK,
- &(lock->user_flock));
-
- return 0;
-}
-
-static int
-client_lockrec_init (clnt_fd_ctx_t *fdctx, clnt_local_t *local)
-{
-
- INIT_LIST_HEAD (&local->lock_list);
- pthread_mutex_init (&local->mutex, NULL);
-
- pthread_mutex_lock (&fdctx->mutex);
- {
- list_splice_init (&fdctx->lock_list, &local->lock_list);
- }
- pthread_mutex_unlock (&fdctx->mutex);
-
- return 0;
-}
-
-
-int
-client_attempt_lock_recovery (xlator_t *this, clnt_fd_ctx_t *fdctx)
-{
- call_frame_t *frame = NULL;
- clnt_local_t *local = NULL;
- client_posix_lock_t *lock = NULL;
-
- struct gf_flock reserve_flock;
- int ret = 0;
-
- local = GF_CALLOC (1, sizeof (*local), gf_client_mt_clnt_local_t);
- if (!local) {
- gf_log (this->name, GF_LOG_ERROR,
- "Out of memory");
- ret = -ENOMEM;
- goto out;
- }
-
- client_lockrec_init (fdctx, local);
-
- lock = get_next_recovery_lock (this, local);
- if (!lock) {
- gf_log (this->name, GF_LOG_DEBUG,
- "No locks on fd");
- ret = -1;
- goto out;
- }
-
- frame = create_frame (this, this->ctx->pool);
- if (!frame) {
- gf_log (this->name, GF_LOG_ERROR,
- "Out of memory");
- ret = -1;
- goto out;
- }
-
- construct_reserve_lock (lock, frame, &reserve_flock);
-
- frame->local = local;
- local->fdctx = fdctx;
- local->client_lock = lock;
-
- STACK_WIND (frame, client_reserve_lock_cbk,
- this, this->fops->lk,
- lock->fd, F_RESLK_LCK, &reserve_flock);
-
-out:
- return ret;
-
-
-}
-
int32_t
client_dump_locks (char *name, inode_t *inode,
dict_t *dict)
@@ -928,8 +551,8 @@ client_dump_locks (char *name, inode_t *inode,
ret = dict_set_dynstr(new_dict, CLIENT_DUMP_LOCKS, dict_string);
if (ret) {
- gf_log (THIS->name, GF_LOG_DEBUG,
- "Could not set dict with %s", CLIENT_DUMP_LOCKS);
+ gf_log (THIS->name, GF_LOG_WARNING,
+ "could not set dict with %s", CLIENT_DUMP_LOCKS);
goto out;
}