summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPavan Sondur <pavan@gluster.com>2010-10-18 03:16:05 +0000
committerVijay Bellur <vijay@dev.gluster.com>2010-10-18 03:25:54 -0700
commitef4005be3ac7f0f266f139c5b3d66538e35b924c (patch)
tree51b8639acc090d982541660249eaae27a1bb5252
parent5ade1467e0cad9687134f25be2b37a667be8ae1a (diff)
features/locks: Handle upgrade/downgrade of locks properly.v3.0.6rc1
Signed-off-by: root <pavan@gluster.com> Signed-off-by: Vijay Bellur <vijay@dev.gluster.com> BUG: 1017 (Locking deadlock when upgrading lock) URL: http://bugs.gluster.com/cgi-bin/bugzilla3/show_bug.cgi?id=1017
-rw-r--r--xlators/features/locks/src/common.c70
-rw-r--r--xlators/features/locks/src/locks.h1
2 files changed, 68 insertions, 3 deletions
diff --git a/xlators/features/locks/src/common.c b/xlators/features/locks/src/common.c
index 3df1312..483d7bf 100644
--- a/xlators/features/locks/src/common.c
+++ b/xlators/features/locks/src/common.c
@@ -42,7 +42,9 @@ static int
__is_lock_grantable (pl_inode_t *pl_inode, posix_lock_t *lock);
static void
__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)
{
@@ -468,6 +470,7 @@ new_posix_lock (struct flock *flock, transport_t *transport, pid_t client_pid,
lock->transport = transport;
lock->fd_num = fd_to_fdnum (fd);
+ lock->fd = fd;
lock->client_pid = client_pid;
lock->owner = owner;
@@ -507,12 +510,11 @@ posix_lock_to_flock (posix_lock_t *lock, struct flock *flock)
flock->l_len = lock->fl_end - lock->fl_start + 1;
}
-
/* Insert the lock into the inode's lock list */
static void
__insert_lock (pl_inode_t *pl_inode, posix_lock_t *lock)
{
- list_add_tail (&lock->list, &pl_inode->ext_list);
+ list_add_tail (&lock->list, &pl_inode->ext_list);
return;
}
@@ -860,6 +862,56 @@ grant_blocked_locks (xlator_t *this, pl_inode_t *pl_inode)
return;
}
+static int
+pl_send_prelock_unlock (xlator_t *this, pl_inode_t *pl_inode,
+ posix_lock_t *old_lock)
+{
+ struct flock flock = {0,};
+ posix_lock_t *unlock_lock = NULL;
+
+ struct list_head granted_list;
+ posix_lock_t *tmp = NULL;
+ posix_lock_t *lock = NULL;
+
+ int ret = 0;
+
+ INIT_LIST_HEAD (&granted_list);
+
+ flock.l_type = F_UNLCK;
+ flock.l_whence = old_lock->user_flock.l_whence;
+ flock.l_start = old_lock->user_flock.l_start;
+ 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,
+ old_lock->fd);
+ if (!unlock_lock) {
+ gf_log (this->name, GF_LOG_ERROR,
+ "Out of memory");
+ ret = -1;
+ goto out;
+ }
+
+ __insert_and_merge (pl_inode, unlock_lock);
+
+ __grant_blocked_locks (this, pl_inode, &granted_list);
+
+ list_for_each_entry_safe (lock, tmp, &granted_list, list) {
+ list_del_init (&lock->list);
+
+ 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);
+
+ FREE (lock);
+ }
+
+out:
+
+ return ret;
+}
int
pl_setlk (xlator_t *this, pl_inode_t *pl_inode, posix_lock_t *lock,
@@ -871,6 +923,18 @@ pl_setlk (xlator_t *this, pl_inode_t *pl_inode, posix_lock_t *lock,
pthread_mutex_lock (&pl_inode->mutex);
{
+ /* Send unlock before the actual lock to
+ prevent lock upgrade / downgrade
+ problems
+ */
+
+ ret = pl_send_prelock_unlock (this, pl_inode,
+ lock);
+ if (ret)
+ gf_log (this->name, GF_LOG_DEBUG,
+ "Could not send pre-lock "
+ "unlock");
+
if (__is_lock_grantable (pl_inode, lock)) {
gf_log (this->name, GF_LOG_TRACE,
"%s (pid=%d) lk-owner:%"PRIu64" %"PRId64" - %"PRId64" => OK",
diff --git a/xlators/features/locks/src/locks.h b/xlators/features/locks/src/locks.h
index e890928..1bbbee1 100644
--- a/xlators/features/locks/src/locks.h
+++ b/xlators/features/locks/src/locks.h
@@ -44,6 +44,7 @@ struct __posix_lock {
xlator_t *this; /* required for blocked locks */
unsigned long fd_num;
+ fd_t *fd;
call_frame_t *frame;
/* These two together serve to uniquely identify each process