diff options
Diffstat (limited to 'xlators/features/locks/src/common.c')
| -rw-r--r-- | xlators/features/locks/src/common.c | 348 |
1 files changed, 256 insertions, 92 deletions
diff --git a/xlators/features/locks/src/common.c b/xlators/features/locks/src/common.c index 4e089a0ee..b3309580d 100644 --- a/xlators/features/locks/src/common.c +++ b/xlators/features/locks/src/common.c @@ -1,22 +1,12 @@ /* - Copyright (c) 2006-2011 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 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/>. -*/ + Copyright (c) 2006-2012 Red Hat, Inc. <http://www.redhat.com> + This file is part of GlusterFS. + 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 <unistd.h> #include <fcntl.h> #include <limits.h> @@ -45,8 +35,9 @@ __insert_and_merge (pl_inode_t *pl_inode, posix_lock_t *lock); static int pl_send_prelock_unlock (xlator_t *this, pl_inode_t *pl_inode, posix_lock_t *old_lock); + static pl_dom_list_t * -allocate_domain (const char *volume) +__allocate_domain (const char *volume) { pl_dom_list_t *dom = NULL; @@ -85,24 +76,26 @@ get_domain (pl_inode_t *pl_inode, const char *volume) { pl_dom_list_t *dom = NULL; - GF_VALIDATE_OR_GOTO (POSIX_LOCKS, pl_inode, out); - GF_VALIDATE_OR_GOTO (POSIX_LOCKS, volume, out); - - list_for_each_entry (dom, &pl_inode->dom_list, inode_list) { - if (strcmp (dom->domain, volume) == 0) - goto found; + GF_VALIDATE_OR_GOTO ("posix-locks", pl_inode, out); + GF_VALIDATE_OR_GOTO ("posix-locks", volume, out); + pthread_mutex_lock (&pl_inode->mutex); + { + list_for_each_entry (dom, &pl_inode->dom_list, inode_list) { + if (strcmp (dom->domain, volume) == 0) + goto unlock; + } + dom = __allocate_domain (volume); + if (dom) + list_add (&dom->inode_list, &pl_inode->dom_list); } - - dom = allocate_domain (volume); - if (dom) - list_add (&dom->inode_list, &pl_inode->dom_list); -found: +unlock: + pthread_mutex_unlock (&pl_inode->mutex); if (dom) { - gf_log (POSIX_LOCKS, GF_LOG_TRACE, "Domain %s found", volume); + gf_log ("posix-locks", GF_LOG_TRACE, "Domain %s found", volume); } else { - gf_log (POSIX_LOCKS, GF_LOG_TRACE, "Domain %s not found", volume); + gf_log ("posix-locks", GF_LOG_TRACE, "Domain %s not found", volume); } out: return dom; @@ -143,10 +136,10 @@ __pl_inode_is_empty (pl_inode_t *pl_inode) void pl_print_locker (char *str, int size, xlator_t *this, call_frame_t *frame) { - snprintf (str, size, "Pid=%llu, lk-owner=%llu, Transport=%p, Frame=%llu", + snprintf (str, size, "Pid=%llu, lk-owner=%s, Client=%p, Frame=%llu", (unsigned long long) frame->root->pid, - (unsigned long long) frame->root->lk_owner, - (void *)frame->root->trans, + lkowner_utoa (&frame->root->lk_owner), + frame->root->client, (unsigned long long) frame->root->unique); } @@ -176,18 +169,17 @@ pl_print_lockee (char *str, int size, fd_t *fd, loc_t *loc) ipath = NULL; } - snprintf (str, size, "ino=%llu, fd=%p, path=%s", - (unsigned long long) inode->ino, fd, + snprintf (str, size, "gfid=%s, fd=%p, path=%s", + uuid_utoa (inode->gfid), fd, ipath ? ipath : "<nul>"); - if (ipath) - GF_FREE (ipath); + GF_FREE (ipath); } void pl_print_lock (char *str, int size, int cmd, - struct gf_flock *flock, uint64_t owner) + struct gf_flock *flock, gf_lkowner_t *owner) { char *cmd_str = NULL; char *type_str = NULL; @@ -235,11 +227,11 @@ pl_print_lock (char *str, int size, int cmd, } snprintf (str, size, "lock=FCNTL, cmd=%s, type=%s, " - "start=%llu, len=%llu, pid=%llu, lk-owner=%llu", + "start=%llu, len=%llu, pid=%llu, lk-owner=%s", 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); + lkowner_utoa (owner)); } @@ -262,7 +254,7 @@ pl_trace_in (xlator_t *this, call_frame_t *frame, fd_t *fd, loc_t *loc, if (domain) pl_print_inodelk (pl_lock, 256, cmd, flock, domain); else - pl_print_lock (pl_lock, 256, cmd, flock, frame->root->lk_owner); + pl_print_lock (pl_lock, 256, cmd, flock, &frame->root->lk_owner); gf_log (this->name, GF_LOG_INFO, "[REQUEST] Locker = {%s} Lockee = {%s} Lock = {%s}", @@ -312,7 +304,7 @@ pl_trace_out (xlator_t *this, call_frame_t *frame, fd_t *fd, loc_t *loc, if (domain) pl_print_inodelk (pl_lock, 256, cmd, flock, domain); else - pl_print_lock (pl_lock, 256, cmd, flock, frame->root->lk_owner); + pl_print_lock (pl_lock, 256, cmd, flock, &frame->root->lk_owner); pl_print_verdict (verdict, 32, op_ret, op_errno); @@ -342,7 +334,7 @@ pl_trace_block (xlator_t *this, call_frame_t *frame, fd_t *fd, loc_t *loc, if (domain) pl_print_inodelk (pl_lock, 256, cmd, flock, domain); else - pl_print_lock (pl_lock, 256, cmd, flock, frame->root->lk_owner); + pl_print_lock (pl_lock, 256, cmd, flock, &frame->root->lk_owner); gf_log (this->name, GF_LOG_INFO, "[BLOCKED] Locker = {%s} Lockee = {%s} Lock = {%s}", @@ -400,6 +392,7 @@ pl_update_refkeeper (xlator_t *this, inode_t *inode) pl_inode_t *pl_inode = NULL; int is_empty = 0; int need_unref = 0; + int need_ref = 0; pl_inode = pl_inode_get (this, inode); @@ -413,13 +406,17 @@ pl_update_refkeeper (xlator_t *this, inode_t *inode) } if (!is_empty && !pl_inode->refkeeper) { - pl_inode->refkeeper = inode_ref (inode); + need_ref = 1; + pl_inode->refkeeper = inode; } } pthread_mutex_unlock (&pl_inode->mutex); if (need_unref) inode_unref (inode); + + if (need_ref) + inode_ref (inode); } @@ -430,46 +427,50 @@ pl_inode_get (xlator_t *this, inode_t *inode) pl_inode_t *pl_inode = NULL; int ret = 0; - ret = inode_ctx_get (inode, this,&tmp_pl_inode); - if (ret == 0) { - pl_inode = (pl_inode_t *)(long)tmp_pl_inode; - goto out; - } - pl_inode = GF_CALLOC (1, sizeof (*pl_inode), - gf_locks_mt_pl_inode_t); - if (!pl_inode) { - goto out; - } + LOCK (&inode->lock); + { + ret = __inode_ctx_get (inode, this, &tmp_pl_inode); + if (ret == 0) { + pl_inode = (pl_inode_t *)(long)tmp_pl_inode; + goto unlock; + } + pl_inode = GF_CALLOC (1, sizeof (*pl_inode), + gf_locks_mt_pl_inode_t); + if (!pl_inode) { + goto unlock; + } - gf_log (this->name, GF_LOG_TRACE, - "Allocating new pl inode"); + gf_log (this->name, GF_LOG_TRACE, + "Allocating new pl inode"); - pthread_mutex_init (&pl_inode->mutex, NULL); + pthread_mutex_init (&pl_inode->mutex, NULL); - INIT_LIST_HEAD (&pl_inode->dom_list); - INIT_LIST_HEAD (&pl_inode->ext_list); - INIT_LIST_HEAD (&pl_inode->rw_list); - INIT_LIST_HEAD (&pl_inode->reservelk_list); - INIT_LIST_HEAD (&pl_inode->blocked_reservelks); - INIT_LIST_HEAD (&pl_inode->blocked_calls); + INIT_LIST_HEAD (&pl_inode->dom_list); + INIT_LIST_HEAD (&pl_inode->ext_list); + INIT_LIST_HEAD (&pl_inode->rw_list); + INIT_LIST_HEAD (&pl_inode->reservelk_list); + INIT_LIST_HEAD (&pl_inode->blocked_reservelks); + INIT_LIST_HEAD (&pl_inode->blocked_calls); - inode_ctx_put (inode, this, (uint64_t)(long)(pl_inode)); + __inode_ctx_put (inode, this, (uint64_t)(long)(pl_inode)); + } +unlock: + UNLOCK (&inode->lock); -out: return pl_inode; } /* Create a new posix_lock_t */ posix_lock_t * -new_posix_lock (struct gf_flock *flock, void *transport, pid_t client_pid, - uint64_t owner, fd_t *fd) +new_posix_lock (struct gf_flock *flock, client_t *client, pid_t client_pid, + gf_lkowner_t *owner, fd_t *fd) { posix_lock_t *lock = NULL; - GF_VALIDATE_OR_GOTO (POSIX_LOCKS, flock, out); - GF_VALIDATE_OR_GOTO (POSIX_LOCKS, transport, out); - GF_VALIDATE_OR_GOTO (POSIX_LOCKS, fd, out); + GF_VALIDATE_OR_GOTO ("posix-locks", flock, out); + GF_VALIDATE_OR_GOTO ("posix-locks", client, out); + GF_VALIDATE_OR_GOTO ("posix-locks", fd, out); lock = GF_CALLOC (1, sizeof (posix_lock_t), gf_locks_mt_posix_lock_t); @@ -485,11 +486,11 @@ new_posix_lock (struct gf_flock *flock, void *transport, pid_t client_pid, else lock->fl_end = flock->l_start + flock->l_len - 1; - lock->transport = transport; + lock->client = client; lock->fd_num = fd_to_fdnum (fd); lock->fd = fd; lock->client_pid = client_pid; - lock->owner = owner; + lock->owner = *owner; INIT_LIST_HEAD (&lock->list); @@ -533,6 +534,11 @@ posix_lock_to_flock (posix_lock_t *lock, struct gf_flock *flock) static void __insert_lock (pl_inode_t *pl_inode, posix_lock_t *lock) { + if (lock->blocked) + gettimeofday (&lock->blkd_time, NULL); + else + gettimeofday (&lock->granted_time, NULL); + list_add_tail (&lock->list, &pl_inode->ext_list); return; @@ -559,8 +565,8 @@ int same_owner (posix_lock_t *l1, posix_lock_t *l2) { - return ((l1->owner == l2->owner) && - (l1->transport == l2->transport)); + return (is_same_lkowner (&l1->owner, &l2->owner) && + (l1->client == l2->client)); } @@ -689,7 +695,7 @@ subtract_locks (posix_lock_t *big, posix_lock_t *small) } GF_ASSERT (0); - gf_log (POSIX_LOCKS, GF_LOG_ERROR, "Unexpected case in subtract_locks"); + gf_log ("posix-locks", GF_LOG_ERROR, "Unexpected case in subtract_locks"); out: if (v.locks[0]) { @@ -709,6 +715,36 @@ done: return v; } +static posix_lock_t * +first_conflicting_overlap (pl_inode_t *pl_inode, posix_lock_t *lock) +{ + posix_lock_t *l = NULL; + posix_lock_t *conf = NULL; + + pthread_mutex_lock (&pl_inode->mutex); + { + list_for_each_entry (l, &pl_inode->ext_list, list) { + if (l->blocked) + continue; + + if (locks_overlap (l, lock)) { + if (same_owner (l, lock)) + continue; + + if ((l->fl_type == F_WRLCK) || + (lock->fl_type == F_WRLCK)) { + conf = l; + goto unlock; + } + } + } + } +unlock: + pthread_mutex_unlock (&pl_inode->mutex); + + return conf; +} + /* Start searching from {begin}, and return the first lock that conflicts, NULL if no conflict @@ -767,6 +803,8 @@ __insert_and_merge (pl_inode_t *pl_inode, posix_lock_t *lock) struct _values v = { .locks = {0, 0, 0} }; list_for_each_entry_safe (conf, t, &pl_inode->ext_list, list) { + if (conf->blocked) + continue; if (!locks_overlap (conf, lock)) continue; @@ -775,7 +813,7 @@ __insert_and_merge (pl_inode_t *pl_inode, posix_lock_t *lock) sum = add_locks (lock, conf); sum->fl_type = lock->fl_type; - sum->transport = lock->transport; + sum->client = lock->client; sum->fd_num = lock->fd_num; sum->client_pid = lock->client_pid; sum->owner = lock->owner; @@ -784,6 +822,8 @@ __insert_and_merge (pl_inode_t *pl_inode, posix_lock_t *lock) __destroy_lock (conf); __destroy_lock (lock); + INIT_LIST_HEAD (&sum->list); + posix_lock_to_flock (sum, &sum->user_flock); __insert_and_merge (pl_inode, sum); return; @@ -791,7 +831,7 @@ __insert_and_merge (pl_inode_t *pl_inode, posix_lock_t *lock) sum = add_locks (lock, conf); sum->fl_type = conf->fl_type; - sum->transport = conf->transport; + sum->client = conf->client; sum->fd_num = conf->fd_num; sum->client_pid = conf->client_pid; sum->owner = conf->owner; @@ -811,6 +851,8 @@ __insert_and_merge (pl_inode_t *pl_inode, posix_lock_t *lock) continue; INIT_LIST_HEAD (&v.locks[i]->list); + posix_lock_to_flock (v.locks[i], + &v.locks[i]->user_flock); __insert_and_merge (pl_inode, v.locks[i]); } @@ -879,10 +921,9 @@ __grant_blocked_locks (xlator_t *this, pl_inode_t *pl_inode, struct list_head *g posix_lock_to_flock (l, &conf->user_flock); gf_log (this->name, GF_LOG_TRACE, - "%s (pid=%d) lk-owner:%"PRIu64" %"PRId64" - %"PRId64" => Granted", + "%s (pid=%d) lk-owner:%s %"PRId64" - %"PRId64" => Granted", l->fl_type == F_UNLCK ? "Unlock" : "Lock", - l->client_pid, - l->owner, + l->client_pid, lkowner_utoa (&l->owner), l->user_flock.l_start, l->user_flock.l_len); @@ -918,7 +959,8 @@ grant_blocked_locks (xlator_t *this, pl_inode_t *pl_inode) pl_trace_out (this, lock->frame, NULL, NULL, F_SETLKW, &lock->user_flock, 0, 0, NULL); - STACK_UNWIND (lock->frame, 0, 0, &lock->user_flock); + STACK_UNWIND_STRICT (lk, lock->frame, 0, 0, + &lock->user_flock, NULL); GF_FREE (lock); } @@ -947,8 +989,8 @@ pl_send_prelock_unlock (xlator_t *this, pl_inode_t *pl_inode, flock.l_len = old_lock->user_flock.l_len; - unlock_lock = new_posix_lock (&flock, old_lock->transport, - old_lock->client_pid, old_lock->owner, + unlock_lock = new_posix_lock (&flock, old_lock->client, + old_lock->client_pid, &old_lock->owner, old_lock->fd); GF_VALIDATE_OR_GOTO (this->name, unlock_lock, out); ret = 0; @@ -963,7 +1005,8 @@ pl_send_prelock_unlock (xlator_t *this, pl_inode_t *pl_inode, pl_trace_out (this, lock->frame, NULL, NULL, F_SETLKW, &lock->user_flock, 0, 0, NULL); - STACK_UNWIND (lock->frame, 0, 0, &lock->user_flock); + STACK_UNWIND_STRICT (lk, lock->frame, 0, 0, + &lock->user_flock, NULL); GF_FREE (lock); } @@ -1001,19 +1044,19 @@ pl_setlk (xlator_t *this, pl_inode_t *pl_inode, posix_lock_t *lock, if (__is_lock_grantable (pl_inode, lock)) { gf_log (this->name, GF_LOG_TRACE, - "%s (pid=%d) lk-owner:%"PRIu64" %"PRId64" - %"PRId64" => OK", + "%s (pid=%d) lk-owner:%s %"PRId64" - %"PRId64" => OK", lock->fl_type == F_UNLCK ? "Unlock" : "Lock", lock->client_pid, - lock->owner, + lkowner_utoa (&lock->owner), lock->user_flock.l_start, lock->user_flock.l_len); __insert_and_merge (pl_inode, lock); } else if (can_block) { gf_log (this->name, GF_LOG_TRACE, - "%s (pid=%d) lk-owner:%"PRIu64" %"PRId64" - %"PRId64" => Blocked", + "%s (pid=%d) lk-owner:%s %"PRId64" - %"PRId64" => Blocked", lock->fl_type == F_UNLCK ? "Unlock" : "Lock", lock->client_pid, - lock->owner, + lkowner_utoa (&lock->owner), lock->user_flock.l_start, lock->user_flock.l_len); lock->blocked = 1; @@ -1021,10 +1064,10 @@ pl_setlk (xlator_t *this, pl_inode_t *pl_inode, posix_lock_t *lock, ret = -1; } else { gf_log (this->name, GF_LOG_TRACE, - "%s (pid=%d) lk-owner:%"PRIu64" %"PRId64" - %"PRId64" => NOK", + "%s (pid=%d) lk-owner:%s %"PRId64" - %"PRId64" => NOK", lock->fl_type == F_UNLCK ? "Unlock" : "Lock", lock->client_pid, - lock->owner, + lkowner_utoa (&lock->owner), lock->user_flock.l_start, lock->user_flock.l_len); errno = EAGAIN; @@ -1046,7 +1089,7 @@ pl_getlk (pl_inode_t *pl_inode, posix_lock_t *lock) { posix_lock_t *conf = NULL; - conf = first_overlap (pl_inode, lock); + conf = first_conflicting_overlap (pl_inode, lock); if (conf == NULL) { lock->fl_type = F_UNLCK; @@ -1055,3 +1098,124 @@ pl_getlk (pl_inode_t *pl_inode, posix_lock_t *lock) return conf; } + + +struct _lock_table * +pl_lock_table_new (void) +{ + struct _lock_table *new = NULL; + + new = GF_CALLOC (1, sizeof (struct _lock_table), gf_common_mt_lock_table); + if (new == NULL) { + goto out; + } + INIT_LIST_HEAD (&new->entrylk_lockers); + INIT_LIST_HEAD (&new->inodelk_lockers); + LOCK_INIT (&new->lock); +out: + return new; +} + + +int +pl_add_locker (struct _lock_table *table, const char *volume, + loc_t *loc, fd_t *fd, pid_t pid, gf_lkowner_t *owner, + glusterfs_fop_t type) +{ + int32_t ret = -1; + struct _locker *new = NULL; + + GF_VALIDATE_OR_GOTO ("lock-table", table, out); + GF_VALIDATE_OR_GOTO ("lock-table", volume, out); + + new = GF_CALLOC (1, sizeof (struct _locker), gf_common_mt_locker); + if (new == NULL) { + goto out; + } + INIT_LIST_HEAD (&new->lockers); + + new->volume = gf_strdup (volume); + + if (fd == NULL) { + loc_copy (&new->loc, loc); + } else { + new->fd = fd_ref (fd); + } + + new->pid = pid; + new->owner = *owner; + + LOCK (&table->lock); + { + if (type == GF_FOP_ENTRYLK) + list_add_tail (&new->lockers, &table->entrylk_lockers); + else + list_add_tail (&new->lockers, &table->inodelk_lockers); + } + UNLOCK (&table->lock); +out: + return ret; +} + +int +pl_del_locker (struct _lock_table *table, const char *volume, + loc_t *loc, fd_t *fd, gf_lkowner_t *owner, glusterfs_fop_t type) +{ + struct _locker *locker = NULL; + struct _locker *tmp = NULL; + int32_t ret = -1; + struct list_head *head = NULL; + struct list_head del; + + GF_VALIDATE_OR_GOTO ("lock-table", table, out); + GF_VALIDATE_OR_GOTO ("lock-table", volume, out); + + INIT_LIST_HEAD (&del); + + LOCK (&table->lock); + { + if (type == GF_FOP_ENTRYLK) { + head = &table->entrylk_lockers; + } else { + head = &table->inodelk_lockers; + } + + list_for_each_entry_safe (locker, tmp, head, lockers) { + if (!is_same_lkowner (&locker->owner, owner) || + strcmp (locker->volume, volume)) + continue; + + /* + * It is possible for inodelk lock to come on anon-fd + * and inodelk unlock to come on normal fd in case of + * client re-opens. So don't check for fds to be equal. + */ + if (locker->fd && fd) + list_move_tail (&locker->lockers, &del); + else if (locker->loc.inode && loc && + (locker->loc.inode == loc->inode)) + list_move_tail (&locker->lockers, &del); + } + } + UNLOCK (&table->lock); + + tmp = NULL; + locker = NULL; + + list_for_each_entry_safe (locker, tmp, &del, lockers) { + list_del_init (&locker->lockers); + if (locker->fd) + fd_unref (locker->fd); + else + loc_wipe (&locker->loc); + + GF_FREE (locker->volume); + GF_FREE (locker); + } + + ret = 0; +out: + return ret; + +} + |
