summaryrefslogtreecommitdiffstats
path: root/xlators/features/leases/src
diff options
context:
space:
mode:
Diffstat (limited to 'xlators/features/leases/src')
-rw-r--r--xlators/features/leases/src/leases-internal.c39
-rw-r--r--xlators/features/leases/src/leases.h1
2 files changed, 37 insertions, 3 deletions
diff --git a/xlators/features/leases/src/leases-internal.c b/xlators/features/leases/src/leases-internal.c
index 296799b8dff..00fb670ff2a 100644
--- a/xlators/features/leases/src/leases-internal.c
+++ b/xlators/features/leases/src/leases-internal.c
@@ -658,6 +658,7 @@ __remove_lease(xlator_t *this, inode_t *inode, lease_inode_ctx_t *lease_ctx,
remove_from_clnt_list(this, client_uid, lease_ctx->inode);
}
__destroy_lease_id_entry(lease_entry);
+ lease_ctx->blocked_fops_resuming = _gf_true;
}
if (lease_ctx->lease_cnt == 0 && lease_ctx->timer) {
@@ -692,6 +693,14 @@ __is_lease_grantable(xlator_t *this, lease_inode_ctx_t *lease_ctx,
goto out;
}
+ if (lease_ctx->blocked_fops_resuming) {
+ gf_msg_debug(this->name, 0,
+ "Previously blocked fops resuming, hence "
+ "failing the lease request");
+ grant = _gf_false;
+ goto out;
+ }
+
LOCK(&inode->lock);
{
list_for_each_entry(iter_fd, &inode->fd_list, inode_list)
@@ -776,6 +785,17 @@ do_blocked_fops(xlator_t *this, lease_inode_ctx_t *lease_ctx)
pthread_mutex_lock(&lease_ctx->lock);
{
+ if (!lease_ctx->blocked_fops_resuming) {
+ /* lease_ctx->blocked_fops_resuming will be set
+ * only when the last lease is released. That
+ * is when we need to resume blocked fops and unref
+ * the inode taken in __add_lease (when lease_cnt == 1).
+ * Return otherwise.
+ */
+ pthread_mutex_unlock(&lease_ctx->lock);
+ return;
+ }
+
list_for_each_entry_safe(blk_fop, tmp, &lease_ctx->blocked_list, list)
{
list_del_init(&blk_fop->list);
@@ -797,6 +817,9 @@ do_blocked_fops(xlator_t *this, lease_inode_ctx_t *lease_ctx)
pthread_mutex_lock(&lease_ctx->lock);
{
lease_ctx->lease_type = NONE;
+ /* unref the inode taken in __add_lease
+ * (when lease_cnt == 1) */
+ lease_ctx->blocked_fops_resuming = _gf_false;
inode_unref(lease_ctx->inode);
lease_ctx->inode = NULL;
}
@@ -829,6 +852,8 @@ recall_lease_timer_handler(struct gf_tw_timer_list *timer, void *data,
pthread_cond_broadcast(&priv->cond);
}
out:
+ /* unref the inode_ref taken by timer_data in __recall_lease */
+ inode_unref(timer_data->inode);
pthread_mutex_unlock(&priv->mutex);
GF_FREE(timer);
@@ -1166,6 +1191,7 @@ remove_clnt_leases(const char *client_uid, inode_t *inode, xlator_t *this)
lease_ctx->lease_cnt -= lease_entry->lease_cnt;
__destroy_lease_id_entry(lease_entry);
if (lease_ctx->lease_cnt == 0) {
+ lease_ctx->blocked_fops_resuming = _gf_true;
pthread_mutex_unlock(&lease_ctx->lock);
goto unblock;
}
@@ -1212,9 +1238,9 @@ cleanup_client_leases(xlator_t *this, const char *client_uid)
list_del_init(&l_inode->list);
list_add_tail(&l_inode->list, &cleanup_list);
}
+ __destroy_lease_client(clnt);
break;
}
- __destroy_lease_client(clnt);
}
}
pthread_mutex_unlock(&priv->mutex);
@@ -1223,6 +1249,7 @@ cleanup_client_leases(xlator_t *this, const char *client_uid)
list_for_each_entry_safe(l_inode, tmp1, &cleanup_list, list)
{
remove_clnt_leases(client_uid, l_inode->inode, this);
+ __destroy_lease_inode(l_inode);
}
out:
return ret;
@@ -1235,6 +1262,10 @@ __remove_all_leases(xlator_t *this, lease_inode_ctx_t *lease_ctx)
lease_id_entry_t *lease_entry = NULL;
lease_id_entry_t *tmp = NULL;
+ if (lease_ctx->lease_cnt == 0) {
+ /* No leases to remove. Return */
+ return;
+ }
__dump_leases_info(this, lease_ctx);
list_for_each_entry_safe(lease_entry, tmp, &lease_ctx->lease_id_list,
@@ -1250,8 +1281,8 @@ __remove_all_leases(xlator_t *this, lease_inode_ctx_t *lease_ctx)
lease_ctx->lease_type = 0;
lease_ctx->lease_cnt = 0;
lease_ctx->recall_in_progress = _gf_false;
- inode_unref(lease_ctx->inode);
lease_ctx->timer = NULL;
+ lease_ctx->blocked_fops_resuming = _gf_true;
/* TODO:
* - Mark the corresponding fd bad. Could be done on client side
@@ -1342,7 +1373,9 @@ expired_recall_cleanup(void *data)
" hence cleaning up leases on the inode",
recall_entry->inode);
remove_all_leases(this, recall_entry->inode);
- list_del_init(&recall_entry->list);
+ /* no need to take priv->mutex lock as this entry
+ * reference is removed from global recall list. */
+ __destroy_lease_inode(recall_entry);
}
}
diff --git a/xlators/features/leases/src/leases.h b/xlators/features/leases/src/leases.h
index d5fc451289d..6ac712b0bb0 100644
--- a/xlators/features/leases/src/leases.h
+++ b/xlators/features/leases/src/leases.h
@@ -185,6 +185,7 @@ struct _lease_inode_ctx {
uint64_t lease_cnt; /* Total number of leases on this inode */
uint64_t openfd_cnt; /* number of fds open */
gf_boolean_t recall_in_progress; /* if lease recall is sent on this inode */
+ gf_boolean_t blocked_fops_resuming; /* if blocked fops are being resumed */
struct list_head blocked_list; /* List of fops blocked until the
lease recall is complete */
inode_t *inode; /* this represents the inode on which the