summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--xlators/features/locks/src/common.c6
-rw-r--r--xlators/features/locks/src/common.h3
-rw-r--r--xlators/features/locks/src/posix.c61
-rw-r--r--xlators/protocol/server/src/server-helpers.c1
4 files changed, 66 insertions, 5 deletions
diff --git a/xlators/features/locks/src/common.c b/xlators/features/locks/src/common.c
index 58b95d20781..5c83f366ee8 100644
--- a/xlators/features/locks/src/common.c
+++ b/xlators/features/locks/src/common.c
@@ -425,7 +425,8 @@ out:
/* Create a new posix_lock_t */
posix_lock_t *
-new_posix_lock (struct flock *flock, transport_t *transport, pid_t client_pid, uint64_t owner)
+new_posix_lock (struct flock *flock, transport_t *transport, pid_t client_pid,
+ uint64_t owner, fd_t *fd)
{
posix_lock_t *lock = NULL;
@@ -443,6 +444,7 @@ new_posix_lock (struct flock *flock, transport_t *transport, pid_t client_pid, u
lock->fl_end = flock->l_start + flock->l_len - 1;
lock->transport = transport;
+ lock->fd = fd;
lock->client_pid = client_pid;
lock->owner = owner;
@@ -686,6 +688,7 @@ __insert_and_merge (pl_inode_t *pl_inode, posix_lock_t *lock)
sum->fl_type = lock->fl_type;
sum->transport = lock->transport;
+ sum->fd = lock->fd;
sum->client_pid = lock->client_pid;
sum->owner = lock->owner;
@@ -701,6 +704,7 @@ __insert_and_merge (pl_inode_t *pl_inode, posix_lock_t *lock)
sum->fl_type = conf->fl_type;
sum->transport = conf->transport;
+ sum->fd = conf->fd;
sum->client_pid = conf->client_pid;
sum->owner = conf->owner;
diff --git a/xlators/features/locks/src/common.h b/xlators/features/locks/src/common.h
index 0d847f77029..32c27c7d198 100644
--- a/xlators/features/locks/src/common.h
+++ b/xlators/features/locks/src/common.h
@@ -21,7 +21,8 @@
#define __COMMON_H__
posix_lock_t *
-new_posix_lock (struct flock *flock, transport_t *transport, pid_t client_pid, uint64_t owner);
+new_posix_lock (struct flock *flock, transport_t *transport, pid_t client_pid,
+ uint64_t owner, fd_t *fd);
pl_inode_t *
pl_inode_get (xlator_t *this, inode_t *inode);
diff --git a/xlators/features/locks/src/posix.c b/xlators/features/locks/src/posix.c
index f3b95e059d8..f0188b402b9 100644
--- a/xlators/features/locks/src/posix.c
+++ b/xlators/features/locks/src/posix.c
@@ -234,6 +234,44 @@ unwind:
return 0;
}
+static void
+delete_locks_of_fd (xlator_t *this, pl_inode_t *pl_inode, fd_t *fd)
+{
+ posix_lock_t *tmp = NULL;
+ posix_lock_t *l = NULL;
+
+ struct list_head blocked_list;
+
+ INIT_LIST_HEAD (&blocked_list);
+
+ pthread_mutex_lock (&pl_inode->mutex);
+ {
+
+ list_for_each_entry_safe (l, tmp, &pl_inode->ext_list, list) {
+ if ((l->fd == fd)) {
+ if (l->blocked) {
+ list_move_tail (&l->list, &blocked_list);
+ continue;
+ }
+ __delete_lock (pl_inode, l);
+ __destroy_lock (l);
+ }
+ }
+
+ }
+ pthread_mutex_unlock (&pl_inode->mutex);
+
+ list_for_each_entry_safe (l, tmp, &blocked_list, list) {
+ list_del_init(&l->list);
+ STACK_UNWIND_STRICT (lk, l->frame, -1, EAGAIN, &l->user_flock);
+ __destroy_lock (l);
+ }
+
+ grant_blocked_locks (this, pl_inode);
+
+ do_blocked_rw (pl_inode);
+
+}
static void
__delete_locks_of_owner (pl_inode_t *pl_inode,
@@ -270,10 +308,12 @@ int
pl_flush (call_frame_t *frame, xlator_t *this,
fd_t *fd)
{
- posix_locks_private_t *priv = NULL;
+ posix_locks_private_t *priv = NULL;
pl_inode_t *pl_inode = NULL;
+ uint64_t owner = -1;
priv = this->private;
+ owner = frame->root->lk_owner;
pl_inode = pl_inode_get (this, fd->inode);
@@ -285,10 +325,21 @@ pl_flush (call_frame_t *frame, xlator_t *this,
pl_trace_flush (this, frame, fd);
+ if (owner == 0) {
+ /* Handle special case when protocol/server sets lk-owner to zero.
+ * This usually happens due to a client disconnection. Hence, free
+ * all locks opened with this fd.
+ */
+ gf_log (this->name, GF_LOG_TRACE,
+ "Releasing all locks with fd %p", fd);
+ delete_locks_of_fd (this, pl_inode, fd);
+ goto wind;
+
+ }
pthread_mutex_lock (&pl_inode->mutex);
{
__delete_locks_of_owner (pl_inode, frame->root->trans,
- frame->root->lk_owner);
+ owner);
}
pthread_mutex_unlock (&pl_inode->mutex);
@@ -296,6 +347,7 @@ pl_flush (call_frame_t *frame, xlator_t *this,
do_blocked_rw (pl_inode);
+wind:
STACK_WIND (frame, pl_flush_cbk, FIRST_CHILD(this),
FIRST_CHILD(this)->fops->flush, fd);
return 0;
@@ -455,6 +507,7 @@ pl_readv (call_frame_t *frame, xlator_t *this,
region.fl_start = offset;
region.fl_end = offset + size - 1;
region.transport = frame->root->trans;
+ region.fd = fd;
region.client_pid = frame->root->pid;
region.owner = frame->root->lk_owner;
@@ -551,6 +604,7 @@ pl_writev (call_frame_t *frame, xlator_t *this, fd_t *fd,
region.fl_start = offset;
region.fl_end = offset + iov_length (vector, count) - 1;
region.transport = frame->root->trans;
+ region.fd = fd;
region.client_pid = frame->root->pid;
region.owner = frame->root->lk_owner;
@@ -642,7 +696,8 @@ pl_lk (call_frame_t *frame, xlator_t *this,
goto unwind;
}
- reqlock = new_posix_lock (flock, transport, client_pid, owner);
+ reqlock = new_posix_lock (flock, transport, client_pid,
+ owner, fd);
if (!reqlock) {
gf_log (this->name, GF_LOG_ERROR,
diff --git a/xlators/protocol/server/src/server-helpers.c b/xlators/protocol/server/src/server-helpers.c
index ae33d6848d9..5e681c507f3 100644
--- a/xlators/protocol/server/src/server-helpers.c
+++ b/xlators/protocol/server/src/server-helpers.c
@@ -594,6 +594,7 @@ do_fd_cleanup (xlator_t *this, server_connection_t *conn, call_frame_t *frame,
tmp_frame->root->pid = 0;
tmp_frame->root->trans = conn;
+ tmp_frame->root->lk_owner = 0;
STACK_WIND (tmp_frame,
server_connection_cleanup_flush_cbk,
bound_xl, bound_xl->fops->flush, fd);