diff options
Diffstat (limited to 'xlators/protocol/client/src/client-lk.c')
| -rw-r--r-- | xlators/protocol/client/src/client-lk.c | 1129 |
1 files changed, 349 insertions, 780 deletions
diff --git a/xlators/protocol/client/src/client-lk.c b/xlators/protocol/client/src/client-lk.c index 5334500a96c..795839734c5 100644 --- a/xlators/protocol/client/src/client-lk.c +++ b/xlators/protocol/client/src/client-lk.c @@ -1,946 +1,515 @@ /* - Copyright (c) 2008-2011 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 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 - General Public License for more details. - - You should have received a copy of the GNU 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 <glusterfs/common-utils.h> +#include <glusterfs/xlator.h> #include "client.h" +#include <glusterfs/lkowner.h> +#include "client-messages.h" static void -__insert_and_merge (clnt_fd_ctx_t *fdctx, client_posix_lock_t *lock); +__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) +__dump_client_lock(client_posix_lock_t *lock) { - xlator_t *this = NULL; - - this = THIS; - - gf_log (this->name, GF_LOG_INFO, - "{fd=%p}" - "{%s lk-owner:%"PRIu64" %"PRId64" - %"PRId64"}" - "{start=%"PRId64" end=%"PRId64"}", - lock->fd, - lock->fl_type == F_WRLCK ? "Write-Lock" : "Read-Lock", - lock->owner, - lock->user_flock.l_start, - lock->user_flock.l_len, - lock->fl_start, - lock->fl_end); + xlator_t *this = NULL; + + this = THIS; + + gf_smsg( + this->name, GF_LOG_INFO, 0, PC_MSG_CLIENT_LOCK_INFO, "fd=%p", lock->fd, + "fl_type=%s", lock->fl_type == F_WRLCK ? "Write-Lock" : "Read-Lock", + "lk-owner=%s", lkowner_utoa(&lock->owner), "l_start=%" PRId64, + lock->user_flock.l_start, "l_len=%" PRId64, lock->user_flock.l_len, + "start=%" PRId64, lock->fl_start, "end=%" PRId64, lock->fl_end, NULL); } static int -dump_client_locks_fd (clnt_fd_ctx_t *fdctx) +dump_client_locks_fd(clnt_fd_ctx_t *fdctx) { - client_posix_lock_t *lock = NULL; - int count = 0; + client_posix_lock_t *lock = NULL; + int count = 0; - pthread_mutex_lock (&fdctx->mutex); - { - list_for_each_entry (lock, &fdctx->lock_list, list) { - __dump_client_lock (lock); - count++; - } - } - pthread_mutex_unlock (&fdctx->mutex); - - return count; + list_for_each_entry(lock, &fdctx->lock_list, list) + { + __dump_client_lock(lock); + count++; + } + return count; } int -dump_client_locks (inode_t *inode) +dump_client_locks(inode_t *inode) { - fd_t *fd = NULL; - clnt_conf_t *conf = NULL; - xlator_t *this = NULL; - clnt_fd_ctx_t *fdctx = NULL; + fd_t *fd = NULL; + xlator_t *this = NULL; + clnt_fd_ctx_t *fdctx = NULL; + clnt_conf_t *conf = NULL; - int total_count = 0; - int locks_fd_count = 0; + int total_count = 0; + int locks_fd_count = 0; - this = THIS; - conf = this->private; + this = THIS; + conf = this->private; - LOCK (&inode->lock); + LOCK(&inode->lock); + { + list_for_each_entry(fd, &inode->fd_list, inode_list) { - list_for_each_entry (fd, &inode->fd_list, inode_list) { - locks_fd_count = 0; - - pthread_mutex_lock (&conf->lock); - { - fdctx = this_fd_get_ctx (fd, this); - } - pthread_mutex_unlock (&conf->lock); + locks_fd_count = 0; - if (fdctx) - locks_fd_count = dump_client_locks_fd (fdctx); - - total_count += locks_fd_count; - } + pthread_spin_lock(&conf->fd_lock); + fdctx = this_fd_get_ctx(fd, this); + if (fdctx) + locks_fd_count = dump_client_locks_fd(fdctx); + pthread_spin_unlock(&conf->fd_lock); + total_count += locks_fd_count; } - UNLOCK (&inode->lock); - - return total_count; + } + UNLOCK(&inode->lock); + return total_count; } static off_t -__get_lock_length (off_t start, off_t end) +__get_lock_length(off_t start, off_t end) { - if (end == LLONG_MAX) - return 0; - else - return (end - start + 1); + if (end == LLONG_MAX) + return 0; + else + return (end - start + 1); } /* Add two locks */ static client_posix_lock_t * -add_locks (client_posix_lock_t *l1, client_posix_lock_t *l2) +add_locks(client_posix_lock_t *l1, client_posix_lock_t *l2) { - client_posix_lock_t *sum = NULL; - - sum = GF_CALLOC (1, sizeof (*sum), gf_client_mt_clnt_lock_t); - if (!sum) - return NULL; + client_posix_lock_t *sum = NULL; - sum->fl_start = min (l1->fl_start, l2->fl_start); - sum->fl_end = max (l1->fl_end, l2->fl_end); + sum = GF_CALLOC(1, sizeof(*sum), gf_client_mt_clnt_lock_t); + if (!sum) + return NULL; - sum->user_flock.l_start = sum->fl_start; - sum->user_flock.l_len = __get_lock_length (sum->fl_start, - sum->fl_end); + sum->fl_start = min(l1->fl_start, l2->fl_start); + sum->fl_end = max(l1->fl_end, l2->fl_end); - return sum; -} + sum->user_flock.l_start = sum->fl_start; + sum->user_flock.l_len = __get_lock_length(sum->fl_start, sum->fl_end); -/* 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 sum; } /* Return true if the locks overlap, false otherwise */ static int -locks_overlap (client_posix_lock_t *l1, client_posix_lock_t *l2) +locks_overlap(client_posix_lock_t *l1, client_posix_lock_t *l2) { - /* - Note: - FUSE always gives us absolute offsets, so no need to worry - about SEEK_CUR or SEEK_END - */ - - return ((l1->fl_end >= l2->fl_start) && - (l2->fl_end >= l1->fl_start)); + /* + Note: + FUSE always gives us absolute offsets, so no need to worry + about SEEK_CUR or SEEK_END + */ + + return ((l1->fl_end >= l2->fl_start) && (l2->fl_end >= l1->fl_start)); } static void -__delete_client_lock (client_posix_lock_t *lock) +__delete_client_lock(client_posix_lock_t *lock) { - list_del_init (&lock->list); + list_del_init(&lock->list); } /* Destroy a posix_lock */ static void -__destroy_client_lock (client_posix_lock_t *lock) +__destroy_client_lock(client_posix_lock_t *lock) { - GF_FREE (lock); + GF_FREE(lock); } /* Subtract two locks */ struct _values { - client_posix_lock_t *locks[3]; + client_posix_lock_t *locks[3]; }; /* {big} must always be contained inside {small} */ static struct _values -subtract_locks (client_posix_lock_t *big, client_posix_lock_t *small) -{ - struct _values v = { .locks = {0, 0, 0} }; - - if ((big->fl_start == small->fl_start) && - (big->fl_end == small->fl_end)) { - /* both edges coincide with big */ - v.locks[0] = GF_CALLOC (1, sizeof (client_posix_lock_t), - gf_client_mt_clnt_lock_t ); - GF_ASSERT (v.locks[0]); - memcpy (v.locks[0], big, sizeof (client_posix_lock_t)); - v.locks[0]->fl_type = small->fl_type; - } - else if ((small->fl_start > big->fl_start) && - (small->fl_end < big->fl_end)) { - /* both edges lie inside big */ - v.locks[0] = GF_CALLOC (1, sizeof (client_posix_lock_t), - gf_client_mt_clnt_lock_t); - GF_ASSERT (v.locks[0]); - v.locks[1] = GF_CALLOC (1, sizeof (client_posix_lock_t), - gf_client_mt_clnt_lock_t); - GF_ASSERT (v.locks[1]); - v.locks[2] = GF_CALLOC (1, sizeof (client_posix_lock_t), - gf_client_mt_clnt_lock_t); - GF_ASSERT (v.locks[2]); - - memcpy (v.locks[0], big, sizeof (client_posix_lock_t)); - v.locks[0]->fl_end = small->fl_start - 1; - v.locks[0]->user_flock.l_len = __get_lock_length (v.locks[0]->fl_start, - v.locks[0]->fl_end); - - memcpy (v.locks[1], small, sizeof (client_posix_lock_t)); - memcpy (v.locks[2], big, sizeof (client_posix_lock_t)); - v.locks[2]->fl_start = small->fl_end + 1; - v.locks[2]->user_flock.l_start = small->fl_end + 1; - } - /* one edge coincides with big */ - else if (small->fl_start == big->fl_start) { - v.locks[0] = GF_CALLOC (1, sizeof (client_posix_lock_t), - gf_client_mt_clnt_lock_t); - GF_ASSERT (v.locks[0]); - v.locks[1] = GF_CALLOC (1, sizeof (client_posix_lock_t), - gf_client_mt_clnt_lock_t); - GF_ASSERT (v.locks[1]); - - memcpy (v.locks[0], big, sizeof (client_posix_lock_t)); - v.locks[0]->fl_start = small->fl_end + 1; - v.locks[0]->user_flock.l_start = small->fl_end + 1; - - memcpy (v.locks[1], small, sizeof (client_posix_lock_t)); - } - else if (small->fl_end == big->fl_end) { - v.locks[0] = GF_CALLOC (1, sizeof (client_posix_lock_t), - gf_client_mt_clnt_lock_t); - GF_ASSERT (v.locks[0]); - v.locks[1] = GF_CALLOC (1, sizeof (client_posix_lock_t), - gf_client_mt_clnt_lock_t); - GF_ASSERT (v.locks[1]); - - memcpy (v.locks[0], big, sizeof (client_posix_lock_t)); - v.locks[0]->fl_end = small->fl_start - 1; - v.locks[0]->user_flock.l_len = __get_lock_length (v.locks[0]->fl_start, - v.locks[0]->fl_end); - - memcpy (v.locks[1], small, sizeof (client_posix_lock_t)); - } - else { - /* 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"); - } - - return v; +subtract_locks(client_posix_lock_t *big, client_posix_lock_t *small) +{ + struct _values v = {.locks = {0, 0, 0}}; + + if ((big->fl_start == small->fl_start) && (big->fl_end == small->fl_end)) { + /* both edges coincide with big */ + v.locks[0] = GF_MALLOC(sizeof(client_posix_lock_t), + gf_client_mt_clnt_lock_t); + GF_ASSERT(v.locks[0]); + memcpy(v.locks[0], big, sizeof(client_posix_lock_t)); + v.locks[0]->fl_type = small->fl_type; + } else if ((small->fl_start > big->fl_start) && + (small->fl_end < big->fl_end)) { + /* both edges lie inside big */ + v.locks[0] = GF_MALLOC(sizeof(client_posix_lock_t), + gf_client_mt_clnt_lock_t); + GF_ASSERT(v.locks[0]); + memcpy(v.locks[0], big, sizeof(client_posix_lock_t)); + v.locks[0]->fl_end = small->fl_start - 1; + v.locks[0]->user_flock.l_len = __get_lock_length(v.locks[0]->fl_start, + v.locks[0]->fl_end); + v.locks[1] = GF_MALLOC(sizeof(client_posix_lock_t), + gf_client_mt_clnt_lock_t); + GF_ASSERT(v.locks[1]); + memcpy(v.locks[1], small, sizeof(client_posix_lock_t)); + v.locks[2] = GF_MALLOC(sizeof(client_posix_lock_t), + gf_client_mt_clnt_lock_t); + GF_ASSERT(v.locks[2]); + memcpy(v.locks[2], big, sizeof(client_posix_lock_t)); + v.locks[2]->fl_start = small->fl_end + 1; + v.locks[2]->user_flock.l_start = small->fl_end + 1; + } + /* one edge coincides with big */ + else if (small->fl_start == big->fl_start) { + v.locks[0] = GF_MALLOC(sizeof(client_posix_lock_t), + gf_client_mt_clnt_lock_t); + GF_ASSERT(v.locks[0]); + memcpy(v.locks[0], big, sizeof(client_posix_lock_t)); + v.locks[0]->fl_start = small->fl_end + 1; + v.locks[0]->user_flock.l_start = small->fl_end + 1; + v.locks[1] = GF_MALLOC(sizeof(client_posix_lock_t), + gf_client_mt_clnt_lock_t); + GF_ASSERT(v.locks[1]); + memcpy(v.locks[1], small, sizeof(client_posix_lock_t)); + } else if (small->fl_end == big->fl_end) { + v.locks[0] = GF_MALLOC(sizeof(client_posix_lock_t), + gf_client_mt_clnt_lock_t); + GF_ASSERT(v.locks[0]); + memcpy(v.locks[0], big, sizeof(client_posix_lock_t)); + v.locks[0]->fl_end = small->fl_start - 1; + v.locks[0]->user_flock.l_len = __get_lock_length(v.locks[0]->fl_start, + v.locks[0]->fl_end); + + v.locks[1] = GF_MALLOC(sizeof(client_posix_lock_t), + gf_client_mt_clnt_lock_t); + GF_ASSERT(v.locks[1]); + memcpy(v.locks[1], small, sizeof(client_posix_lock_t)); + } else { + /* LOG-TODO : decide what more info is required here*/ + gf_smsg("client-protocol", GF_LOG_CRITICAL, 0, PC_MSG_LOCK_ERROR, NULL); + } + + return v; } static void -__delete_unlck_locks (clnt_fd_ctx_t *fdctx) +__delete_unlck_locks(clnt_fd_ctx_t *fdctx) { - client_posix_lock_t *l = NULL; - client_posix_lock_t *tmp = NULL; - - list_for_each_entry_safe (l, tmp, &fdctx->lock_list, list) { - if (l->fl_type == F_UNLCK) { - __delete_client_lock (l); - __destroy_client_lock (l); - } - } + client_posix_lock_t *l = NULL; + client_posix_lock_t *tmp = NULL; + + list_for_each_entry_safe(l, tmp, &fdctx->lock_list, list) + { + if (l->fl_type == F_UNLCK) { + __delete_client_lock(l); + __destroy_client_lock(l); + } + } } static void -__insert_lock (clnt_fd_ctx_t *fdctx, client_posix_lock_t *lock) +__insert_lock(clnt_fd_ctx_t *fdctx, client_posix_lock_t *lock) { - list_add_tail (&lock->list, &fdctx->lock_list); + list_add_tail(&lock->list, &fdctx->lock_list); - return; + return; } static void -__insert_and_merge (clnt_fd_ctx_t *fdctx, client_posix_lock_t *lock) +__insert_and_merge(clnt_fd_ctx_t *fdctx, client_posix_lock_t *lock) { - client_posix_lock_t *conf = NULL; - client_posix_lock_t *t = NULL; - client_posix_lock_t *sum = NULL; - int i = 0; - struct _values v = { .locks = {0, 0, 0} }; - - list_for_each_entry_safe (conf, t, &fdctx->lock_list, list) { - if (!locks_overlap (conf, lock)) - continue; + client_posix_lock_t *conf = NULL; + client_posix_lock_t *t = NULL; + client_posix_lock_t *sum = NULL; + int i = 0; + struct _values v = {.locks = {0, 0, 0}}; - if (same_owner (conf, lock)) { - if (conf->fl_type == lock->fl_type) { - sum = add_locks (lock, conf); + list_for_each_entry_safe(conf, t, &fdctx->lock_list, list) + { + if (!locks_overlap(conf, lock)) + continue; - sum->fd = lock->fd; + if (is_same_lkowner(&conf->owner, &lock->owner)) { + if (conf->fl_type == lock->fl_type) { + sum = add_locks(lock, conf); - __delete_client_lock (conf); - __destroy_client_lock (conf); + sum->fd = lock->fd; - __destroy_client_lock (lock); - __insert_and_merge (fdctx, sum); + __delete_client_lock(conf); + __destroy_client_lock(conf); - return; - } else { - sum = add_locks (lock, conf); + __destroy_client_lock(lock); + __insert_and_merge(fdctx, sum); - sum->fd = conf->fd; - sum->owner = conf->owner; + return; + } else { + sum = add_locks(lock, conf); - v = subtract_locks (sum, lock); + sum->fd = conf->fd; + sum->owner = conf->owner; - __delete_client_lock (conf); - __destroy_client_lock (conf); + v = subtract_locks(sum, lock); - __delete_client_lock (lock); - __destroy_client_lock (lock); + __delete_client_lock(conf); + __destroy_client_lock(conf); - __destroy_client_lock (sum); + __delete_client_lock(lock); + __destroy_client_lock(lock); - for (i = 0; i < 3; i++) { - if (!v.locks[i]) - continue; + __destroy_client_lock(sum); - INIT_LIST_HEAD (&v.locks[i]->list); - __insert_and_merge (fdctx, - v.locks[i]); - } - - __delete_unlck_locks (fdctx); - return; - } - } - - if (lock->fl_type == F_UNLCK) { + for (i = 0; i < 3; i++) { + if (!v.locks[i]) continue; - } - if ((conf->fl_type == F_RDLCK) && (lock->fl_type == F_RDLCK)) { - __insert_lock (fdctx, lock); - return; + INIT_LIST_HEAD(&v.locks[i]->list); + __insert_and_merge(fdctx, v.locks[i]); } - } - - /* no conflicts, so just insert */ - if (lock->fl_type != F_UNLCK) { - __insert_lock (fdctx, lock); - } else { - __destroy_client_lock (lock); - } -} - -static void -client_setlk (clnt_fd_ctx_t *fdctx, client_posix_lock_t *lock) -{ - pthread_mutex_lock (&fdctx->mutex); - { - __insert_and_merge (fdctx, lock); - } - pthread_mutex_unlock (&fdctx->mutex); - - return; -} - -static void -destroy_client_lock (client_posix_lock_t *lock) -{ - GF_FREE (lock); -} -int32_t -delete_granted_locks_owner (fd_t *fd, uint64_t owner) -{ - clnt_fd_ctx_t *fdctx = NULL; - client_posix_lock_t *lock = NULL; - client_posix_lock_t *tmp = NULL; - xlator_t *this = NULL; - - struct list_head delete_list; - int ret = 0; - int count = 0; - - INIT_LIST_HEAD (&delete_list); - this = THIS; - fdctx = this_fd_get_ctx (fd, this); - if (!fdctx) { - gf_log (this->name, GF_LOG_WARNING, - "fdctx not valid"); - ret = -1; - goto out; + __delete_unlck_locks(fdctx); + return; + } } - pthread_mutex_lock (&fdctx->mutex); - { - list_for_each_entry_safe (lock, tmp, &fdctx->lock_list, list) { - if (lock->owner == owner) { - list_del_init (&lock->list); - list_add_tail (&lock->list, &delete_list); - count++; - } - } + if (lock->fl_type == F_UNLCK) { + continue; } - pthread_mutex_unlock (&fdctx->mutex); - list_for_each_entry_safe (lock, tmp, &delete_list, list) { - list_del_init (&lock->list); - destroy_client_lock (lock); + if ((conf->fl_type == F_RDLCK) && (lock->fl_type == F_RDLCK)) { + __insert_lock(fdctx, lock); + return; } + } - /* FIXME: Need to actually print the locks instead of count */ - gf_log (this->name, GF_LOG_TRACE, - "Number of locks cleared=%d", count); - -out: - return ret; + /* no conflicts, so just insert */ + if (lock->fl_type != F_UNLCK) { + __insert_lock(fdctx, lock); + } else { + __destroy_client_lock(lock); + } } -int32_t -delete_granted_locks_fd (clnt_fd_ctx_t *fdctx) +static void +client_setlk(clnt_fd_ctx_t *fdctx, client_posix_lock_t *lock) { - client_posix_lock_t *lock = NULL; - client_posix_lock_t *tmp = NULL; - xlator_t *this = NULL; - - struct list_head delete_list; - int ret = 0; - int count = 0; - - INIT_LIST_HEAD (&delete_list); - this = THIS; - - pthread_mutex_lock (&fdctx->mutex); - { - list_splice_init (&fdctx->lock_list, &delete_list); - } - pthread_mutex_unlock (&fdctx->mutex); - - list_for_each_entry_safe (lock, tmp, &delete_list, list) { - list_del_init (&lock->list); - count++; - destroy_client_lock (lock); - } - - /* FIXME: Need to actually print the locks instead of count */ - gf_log (this->name, GF_LOG_TRACE, - "Number of locks cleared=%d", count); - - return ret; + __insert_and_merge(fdctx, lock); } static void -client_mark_bad_fd (fd_t *fd, clnt_fd_ctx_t *fdctx) +destroy_client_lock(client_posix_lock_t *lock) { - xlator_t *this = NULL; - - this = THIS; - if (fdctx) - fdctx->remote_fd = -1; - - gf_log (this->name, GF_LOG_WARNING, - "marking the file descriptor (%p) bad", fd); - - this_fd_set_ctx (fd, this, NULL, fdctx); + GF_FREE(lock); } int32_t -client_cmd_to_gf_cmd (int32_t cmd, int32_t *gf_cmd) -{ - int ret = 0; - - if (cmd == F_GETLK || cmd == F_GETLK64) - *gf_cmd = GF_LK_GETLK; - else if (cmd == F_SETLK || cmd == F_SETLK64) - *gf_cmd = GF_LK_SETLK; - else if (cmd == F_SETLKW || cmd == F_SETLKW64) - *gf_cmd = GF_LK_SETLKW; - else if (cmd == F_RESLK_LCK) - *gf_cmd = GF_LK_RESLK_LCK; - else if (cmd == F_RESLK_LCKW) - *gf_cmd = GF_LK_RESLK_LCKW; - else if (cmd == F_RESLK_UNLCK) - *gf_cmd = GF_LK_RESLK_UNLCK; - else if (cmd == F_GETLK_FD) - *gf_cmd = GF_LK_GETLK_FD; - else - ret = -1; - - return ret; - -} - -static client_posix_lock_t * -new_client_lock (struct gf_flock *flock, uint64_t owner, - int32_t cmd, fd_t *fd) -{ - client_posix_lock_t *new_lock = NULL; - - new_lock = GF_CALLOC (1, sizeof (*new_lock), - gf_client_mt_clnt_lock_t); - if (!new_lock) { - goto out; - } - - INIT_LIST_HEAD (&new_lock->list); - new_lock->fd = fd; - memcpy (&new_lock->user_flock, flock, sizeof (struct gf_flock)); - - new_lock->fl_type = flock->l_type; - new_lock->fl_start = flock->l_start; - - if (flock->l_len == 0) - new_lock->fl_end = LLONG_MAX; - else - new_lock->fl_end = flock->l_start + flock->l_len - 1; - - new_lock->owner = owner; - new_lock->cmd = cmd; /* Not really useful */ - -out: - return new_lock; -} - -void -client_save_number_fds (clnt_conf_t *conf, int count) -{ - LOCK (&conf->rec_lock); - { - conf->reopen_fd_count = count; +delete_granted_locks_owner(fd_t *fd, gf_lkowner_t *owner) +{ + clnt_fd_ctx_t *fdctx = NULL; + client_posix_lock_t *lock = NULL; + client_posix_lock_t *tmp = NULL; + xlator_t *this = NULL; + clnt_conf_t *conf = NULL; + + struct list_head delete_list; + int ret = 0; + int count = 0; + + INIT_LIST_HEAD(&delete_list); + this = THIS; + conf = this->private; + + pthread_spin_lock(&conf->fd_lock); + + fdctx = this_fd_get_ctx(fd, this); + if (!fdctx) { + pthread_spin_unlock(&conf->fd_lock); + + gf_smsg(this->name, GF_LOG_WARNING, EINVAL, PC_MSG_FD_CTX_INVALID, + NULL); + ret = -1; + goto out; + } + + list_for_each_entry_safe(lock, tmp, &fdctx->lock_list, list) + { + if (is_same_lkowner(&lock->owner, owner)) { + list_del_init(&lock->list); + list_add_tail(&lock->list, &delete_list); + count++; } - UNLOCK (&conf->rec_lock); -} - -int -client_add_lock_for_recovery (fd_t *fd, struct gf_flock *flock, uint64_t owner, - int32_t cmd) -{ - clnt_fd_ctx_t *fdctx = NULL; - xlator_t *this = NULL; - client_posix_lock_t *lock = NULL; - clnt_conf_t *conf = NULL; - - int ret = 0; + } - this = THIS; - conf = this->private; + pthread_spin_unlock(&conf->fd_lock); - pthread_mutex_lock (&conf->lock); + if (!list_empty(&delete_list)) { + list_for_each_entry_safe(lock, tmp, &delete_list, list) { - fdctx = this_fd_get_ctx (fd, this); - } - pthread_mutex_unlock (&conf->lock); - - if (!fdctx) { - 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) { - ret = -ENOMEM; - goto out; + list_del_init(&lock->list); + destroy_client_lock(lock); } + } - client_setlk (fdctx, lock); + /* FIXME: Need to actually print the locks instead of count */ + gf_msg_trace(this->name, 0, "Number of locks cleared=%d", count); out: - return ret; - -} - -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_INFO, - "last fd open'd/lock-self-heal'd - notifying CHILD-UP"); - client_notify_parents_child_up (this); - } - - return fd_count; + return ret; } 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) { - gf_log (this->name, GF_LOG_WARNING, - "removing reserver lock on fd failed: %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_TRACE, - "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; - - construct_reserve_unlock (&unlock, frame, lock); - - STACK_WIND (frame, client_remove_reserve_lock_cbk, - this, this->fops->lk, - lock->fd, F_RESLK_UNLCK, &unlock); +client_cmd_to_gf_cmd(int32_t cmd, int32_t *gf_cmd) +{ + int ret = 0; + + if (cmd == F_GETLK || cmd == F_GETLK64) + *gf_cmd = GF_LK_GETLK; + else if (cmd == F_SETLK || cmd == F_SETLK64) + *gf_cmd = GF_LK_SETLK; + else if (cmd == F_SETLKW || cmd == F_SETLKW64) + *gf_cmd = GF_LK_SETLKW; + else if (cmd == F_RESLK_LCK) + *gf_cmd = GF_LK_RESLK_LCK; + else if (cmd == F_RESLK_LCKW) + *gf_cmd = GF_LK_RESLK_LCKW; + else if (cmd == F_RESLK_UNLCK) + *gf_cmd = GF_LK_RESLK_UNLCK; + else if (cmd == F_GETLK_FD) + *gf_cmd = GF_LK_GETLK_FD; + else + ret = -1; + + return ret; } 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) +new_client_lock(struct gf_flock *flock, gf_lkowner_t *owner, int32_t cmd, + fd_t *fd) { + client_posix_lock_t *new_lock = NULL; - clnt_local_t *local = NULL; - clnt_conf_t *conf = NULL; + new_lock = GF_CALLOC(1, sizeof(*new_lock), gf_client_mt_clnt_lock_t); + if (!new_lock) { + goto out; + } - uint64_t fd_count = 0; + INIT_LIST_HEAD(&new_lock->list); + new_lock->fd = fd; + memcpy(&new_lock->user_flock, flock, sizeof(struct gf_flock)); - local = frame->local; - conf = this->private; + new_lock->fl_type = flock->l_type; + new_lock->fl_start = flock->l_start; - /* Got the reserve lock. Check if lock is grantable and proceed - with the real lk call */ + if (flock->l_len == 0) + new_lock->fl_end = LLONG_MAX; + else + new_lock->fl_end = flock->l_start + flock->l_len - 1; - 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_INFO, - "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_WARNING, - "reservelk OP failed. aborting lock recovery"); - - 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 %"PRIu64" open fds", - 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) { - gf_log (this->name, GF_LOG_ERROR, - "lock recovery failed: %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; - - } + new_lock->owner = *owner; -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 %"PRIu64" open fds", - fd_count); + new_lock->cmd = cmd; /* Not really useful */ 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; + return new_lock; } -static int -client_lockrec_init (clnt_fd_ctx_t *fdctx, clnt_local_t *local) +void +client_save_number_fds(clnt_conf_t *conf, int count) { - - 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; + LOCK(&conf->rec_lock); + { + conf->reopen_fd_count = count; + } + UNLOCK(&conf->rec_lock); } - int -client_attempt_lock_recovery (xlator_t *this, clnt_fd_ctx_t *fdctx) +client_add_lock_for_recovery(fd_t *fd, struct gf_flock *flock, + gf_lkowner_t *owner, int32_t cmd) { - call_frame_t *frame = NULL; - clnt_local_t *local = NULL; - client_posix_lock_t *lock = NULL; - - struct gf_flock reserve_flock; - int ret = 0; + clnt_fd_ctx_t *fdctx = NULL; + xlator_t *this = NULL; + client_posix_lock_t *lock = NULL; + clnt_conf_t *conf = NULL; - local = GF_CALLOC (1, sizeof (*local), gf_client_mt_clnt_local_t); - if (!local) { - ret = -ENOMEM; - goto out; - } + int ret = 0; - client_lockrec_init (fdctx, local); + this = THIS; + conf = this->private; - lock = get_next_recovery_lock (this, local); - if (!lock) { - gf_log (this->name, GF_LOG_DEBUG, - "no locks found on fd"); - ret = -1; - goto out; - } + pthread_spin_lock(&conf->fd_lock); - frame = create_frame (this, this->ctx->pool); - if (!frame) { - gf_log (this->name, GF_LOG_ERROR, - "creating of frame failed, lock recovery failed"); - ret = -1; - goto out; - } + fdctx = this_fd_get_ctx(fd, this); + if (!fdctx) { + pthread_spin_unlock(&conf->fd_lock); - construct_reserve_lock (lock, frame, &reserve_flock); + gf_smsg(this->name, GF_LOG_WARNING, 0, PC_MSG_FD_GET_FAIL, NULL); + ret = -EBADFD; + goto out; + } - frame->local = local; - local->fdctx = fdctx; - local->client_lock = lock; + lock = new_client_lock(flock, owner, cmd, fd); + if (!lock) { + pthread_spin_unlock(&conf->fd_lock); - STACK_WIND (frame, client_reserve_lock_cbk, - this, this->fops->lk, - lock->fd, F_RESLK_LCK, &reserve_flock); + ret = -ENOMEM; + goto out; + } -out: - return ret; + client_setlk(fdctx, lock); + pthread_spin_unlock(&conf->fd_lock); +out: + return ret; } int32_t -client_dump_locks (char *name, inode_t *inode, - dict_t *dict) +client_dump_locks(char *name, inode_t *inode, dict_t *dict) { - int ret = 0; - dict_t *new_dict = NULL; - char dict_string[256]; + int ret = 0; + dict_t *new_dict = NULL; + char dict_string[256]; - GF_ASSERT (dict); - new_dict = dict; + GF_ASSERT(dict); + new_dict = dict; - ret = dump_client_locks (inode); - snprintf (dict_string, 256, "%d locks dumped in log file", ret); + ret = dump_client_locks(inode); + snprintf(dict_string, 256, "%d locks dumped in log file", ret); - ret = dict_set_dynstr(new_dict, CLIENT_DUMP_LOCKS, dict_string); - if (ret) { - gf_log (THIS->name, GF_LOG_WARNING, - "could not set dict with %s", CLIENT_DUMP_LOCKS); - goto out; - } + ret = dict_set_dynstr(new_dict, CLIENT_DUMP_LOCKS, dict_string); + if (ret) { + gf_smsg(THIS->name, GF_LOG_WARNING, 0, PC_MSG_DICT_SET_FAIL, "lock=%s", + CLIENT_DUMP_LOCKS, NULL); + goto out; + } out: - return ret; + return ret; } int32_t -is_client_dump_locks_cmd (char *name) +is_client_dump_locks_cmd(char *name) { - int ret = 0; + int ret = 0; - if (strcmp (name, CLIENT_DUMP_LOCKS) == 0) - ret = 1; + if (strcmp(name, CLIENT_DUMP_LOCKS) == 0) + ret = 1; - return ret; + return ret; } |
