diff options
Diffstat (limited to 'xlators/protocol/client/src/client-lk.c')
| -rw-r--r-- | xlators/protocol/client/src/client-lk.c | 439 |
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; } |
