diff options
-rw-r--r-- | xlators/features/locks/src/common.c | 6 | ||||
-rw-r--r-- | xlators/features/locks/src/common.h | 3 | ||||
-rw-r--r-- | xlators/features/locks/src/posix.c | 61 | ||||
-rw-r--r-- | xlators/protocol/server/src/server-helpers.c | 1 |
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); |