16
#include <glusterfs/upcall-utils.h>
56
is_leases_enabled(xlator_t *this)
58
leases_private_t *priv = NULL;
59
gf_boolean_t is_enabled = _gf_false;
61
GF_VALIDATE_OR_GOTO("leases", this, out);
64
priv = (leases_private_t *)this->private;
65
is_enabled = priv->leases_enabled;
78
get_recall_lease_timeout(xlator_t *this)
80
leases_private_t *priv = NULL;
81
time_t timeout = (time_t)-1;
83
GF_VALIDATE_OR_GOTO("leases", this, out);
86
priv = (leases_private_t *)this->private;
87
timeout = priv->recall_lease_timeout;
94
__dump_leases_info(xlator_t *this, lease_inode_ctx_t *lease_ctx)
96
lease_id_entry_t *lease_entry = NULL;
97
lease_id_entry_t *tmp = NULL;
99
GF_VALIDATE_OR_GOTO("leases", this, out);
100
GF_VALIDATE_OR_GOTO("leases", lease_ctx, out);
102
gf_msg_debug(this->name, 0,
103
"Lease held on this inode, lease_type: %d,"
104
" lease_cnt:%" PRIu64
105
", RD lease:%d, RW lease:%d, "
106
"openfd cnt:%" PRIu64,
107
lease_ctx->lease_type, lease_ctx->lease_cnt,
108
lease_ctx->lease_type_cnt[GF_RD_LEASE],
109
lease_ctx->lease_type_cnt[GF_RW_LEASE], lease_ctx->openfd_cnt);
111
list_for_each_entry_safe(lease_entry, tmp, &lease_ctx->lease_id_list,
114
gf_msg_debug(this->name, 0,
115
"Leases held by client: %s, lease "
116
"ID:%s, RD lease:%d, RW lease:%d, lease_type: %d, "
117
"lease_cnt:%" PRIu64,
118
lease_entry->client_uid, lease_entry->lease_id,
119
lease_entry->lease_type_cnt[GF_RD_LEASE],
120
lease_entry->lease_type_cnt[GF_RW_LEASE],
121
lease_entry->lease_type, lease_entry->lease_cnt);
128
__lease_ctx_set(inode_t *inode, xlator_t *this)
130
lease_inode_ctx_t *inode_ctx = NULL;
133
inode_ctx = GF_CALLOC(1, sizeof(*inode_ctx),
134
gf_leases_mt_lease_inode_ctx_t);
135
GF_CHECK_ALLOC(inode_ctx, ret, out);
137
pthread_mutex_init(&inode_ctx->lock, NULL);
138
INIT_LIST_HEAD(&inode_ctx->lease_id_list);
139
INIT_LIST_HEAD(&inode_ctx->blocked_list);
141
inode_ctx->lease_cnt = 0;
143
ret = __inode_ctx_set(inode, this, (uint64_t *)inode_ctx);
146
gf_msg(this->name, GF_LOG_INFO, 0, LEASE_MSG_INVAL_INODE_CTX,
147
"failed to set inode ctx (%p)", inode);
153
static lease_inode_ctx_t *
154
__lease_ctx_get(inode_t *inode, xlator_t *this)
156
lease_inode_ctx_t *inode_ctx = NULL;
160
ret = __inode_ctx_get(inode, this, &ctx);
162
ret = __lease_ctx_set(inode, this);
166
ret = __inode_ctx_get(inode, this, &ctx);
168
gf_msg(this->name, GF_LOG_WARNING, 0, LEASE_MSG_INVAL_INODE_CTX,
169
"failed to get inode ctx (%p)", inode);
174
inode_ctx = (lease_inode_ctx_t *)(long)ctx;
180
lease_ctx_get(inode_t *inode, xlator_t *this)
182
lease_inode_ctx_t *inode_ctx = NULL;
184
GF_VALIDATE_OR_GOTO("leases", inode, out);
185
GF_VALIDATE_OR_GOTO("leases", this, out);
189
inode_ctx = __lease_ctx_get(inode, this);
191
UNLOCK(&inode->lock);
196
static lease_id_entry_t *
197
new_lease_id_entry(call_frame_t *frame, const char *lease_id)
199
lease_id_entry_t *lease_entry = NULL;
201
GF_VALIDATE_OR_GOTO("leases", frame, out);
202
GF_VALIDATE_OR_GOTO("leases", lease_id, out);
204
lease_entry = GF_CALLOC(1, sizeof(*lease_entry),
205
gf_leases_mt_lease_id_entry_t);
207
gf_msg(frame->this->name, GF_LOG_ERROR, ENOMEM, LEASE_MSG_NO_MEM,
208
"Memory allocation for lease_entry failed");
212
INIT_LIST_HEAD(&lease_entry->lease_id_list);
213
lease_entry->lease_type = NONE;
214
lease_entry->lease_cnt = 0;
215
lease_entry->recall_time = get_recall_lease_timeout(frame->this);
216
lease_entry->client_uid = gf_strdup(frame->root->client->client_uid);
217
if (!lease_entry->client_uid) {
218
gf_msg(frame->this->name, GF_LOG_ERROR, ENOMEM, LEASE_MSG_NO_MEM,
219
"Memory allocation for client_uid failed");
220
GF_FREE(lease_entry);
225
memcpy(lease_entry->lease_id, lease_id, LEASE_ID_SIZE);
231
__destroy_lease_id_entry(lease_id_entry_t *lease_entry)
233
GF_VALIDATE_OR_GOTO("leases", lease_entry, out);
235
list_del_init(&lease_entry->lease_id_list);
236
GF_FREE(lease_entry->client_uid);
237
GF_FREE(lease_entry);
242
static inline gf_boolean_t
243
__is_same_lease_id(const char *k1, const char *k2)
245
if (memcmp(k1, k2, strlen(k1)) == 0)
255
__another_lease_found(lease_inode_ctx_t *lease_ctx, const char *lease_id)
257
lease_id_entry_t *lease_entry = NULL;
258
lease_id_entry_t *tmp = NULL;
259
gf_boolean_t found_lease = _gf_false;
261
GF_VALIDATE_OR_GOTO("leases", lease_id, out);
262
GF_VALIDATE_OR_GOTO("leases", lease_ctx, out);
264
list_for_each_entry_safe(lease_entry, tmp, &lease_ctx->lease_id_list,
267
if (!__is_same_lease_id(lease_id, lease_entry->lease_id)) {
268
if (lease_entry->lease_cnt > 0) {
269
found_lease = _gf_true;
283
static lease_id_entry_t *
284
__get_lease_id_entry(lease_inode_ctx_t *lease_ctx, const char *lease_id)
286
lease_id_entry_t *lease_entry = NULL;
287
lease_id_entry_t *tmp = NULL;
288
lease_id_entry_t *found = NULL;
290
GF_VALIDATE_OR_GOTO("leases", lease_id, out);
291
GF_VALIDATE_OR_GOTO("leases", lease_ctx, out);
293
list_for_each_entry_safe(lease_entry, tmp, &lease_ctx->lease_id_list,
296
if (__is_same_lease_id(lease_id, lease_entry->lease_id)) {
298
gf_msg_debug("leases", 0,
299
"lease ID entry found "
300
"Client UID:%s, lease id:%s",
301
lease_entry->client_uid,
302
leaseid_utoa(lease_entry->lease_id));
315
static lease_id_entry_t *
316
__get_or_new_lease_entry(call_frame_t *frame, const char *lease_id,
317
lease_inode_ctx_t *lease_ctx)
319
lease_id_entry_t *lease_entry = NULL;
321
GF_VALIDATE_OR_GOTO("leases", frame, out);
322
GF_VALIDATE_OR_GOTO("leases", lease_id, out);
323
GF_VALIDATE_OR_GOTO("leases", lease_ctx, out);
325
lease_entry = __get_lease_id_entry(lease_ctx, lease_id);
327
lease_entry = new_lease_id_entry(frame, lease_id);
331
list_add_tail(&lease_entry->lease_id_list, &lease_ctx->lease_id_list);
333
gf_msg_debug(frame->this->name, 0,
334
"lease ID entry added,"
335
" Client UID:%s, lease id:%s",
336
lease_entry->client_uid,
337
leaseid_utoa(lease_entry->lease_id));
343
static lease_inode_t *
344
new_lease_inode(inode_t *inode)
346
lease_inode_t *l_inode = GF_MALLOC(sizeof(*l_inode),
347
gf_leases_mt_lease_inode_t);
351
INIT_LIST_HEAD(&l_inode->list);
352
l_inode->inode = inode_ref(inode);
358
__destroy_lease_inode(lease_inode_t *l_inode)
360
list_del_init(&l_inode->list);
361
inode_unref(l_inode->inode);
365
static lease_client_t *
366
new_lease_client(const char *client_uid)
368
lease_client_t *clnt = GF_MALLOC(sizeof(*clnt),
369
gf_leases_mt_lease_client_t);
373
INIT_LIST_HEAD(&clnt->client_list);
374
INIT_LIST_HEAD(&clnt->inode_list);
375
clnt->client_uid = gf_strdup(client_uid);
381
__destroy_lease_client(lease_client_t *clnt)
383
list_del_init(&clnt->inode_list);
384
list_del_init(&clnt->client_list);
390
static lease_client_t *
391
__get_lease_client(xlator_t *this, leases_private_t *priv,
392
const char *client_uid)
394
lease_client_t *clnt = NULL;
395
lease_client_t *tmp = NULL;
396
lease_client_t *found = NULL;
398
list_for_each_entry_safe(clnt, tmp, &priv->client_list, client_list)
400
if ((strcmp(clnt->client_uid, client_uid) == 0)) {
402
gf_msg_debug(this->name, 0,
403
"Client:%s already found "
404
"in the cleanup list",
412
static lease_client_t *
413
__get_or_new_lease_client(xlator_t *this, leases_private_t *priv,
414
const char *client_uid)
416
lease_client_t *found = NULL;
418
found = __get_lease_client(this, priv, client_uid);
420
found = new_lease_client(client_uid);
423
list_add_tail(&found->client_list, &priv->client_list);
424
gf_msg_debug(this->name, 0,
425
"Adding a new client:%s entry "
426
"to the cleanup list",
434
add_inode_to_client_list(xlator_t *this, inode_t *inode, const char *client_uid)
436
leases_private_t *priv = this->private;
437
lease_client_t *clnt = NULL;
439
lease_inode_t *lease_inode = new_lease_inode(inode);
443
pthread_mutex_lock(&priv->mutex);
445
clnt = __get_or_new_lease_client(this, priv, client_uid);
447
pthread_mutex_unlock(&priv->mutex);
448
__destroy_lease_inode(lease_inode);
451
list_add_tail(&clnt->inode_list, &lease_inode->list);
453
pthread_mutex_unlock(&priv->mutex);
454
gf_msg_debug(this->name, 0,
455
"Added a new inode:%p to the client(%s) "
456
"cleanup list, gfid(%s)",
457
inode, client_uid, uuid_utoa(inode->gfid));
467
__add_lease(call_frame_t *frame, inode_t *inode, lease_inode_ctx_t *lease_ctx,
468
const char *client_uid, struct gf_lease *lease)
470
lease_id_entry_t *lease_entry = NULL;
473
GF_VALIDATE_OR_GOTO("leases", frame, out);
474
GF_VALIDATE_OR_GOTO("leases", client_uid, out);
475
GF_VALIDATE_OR_GOTO("leases", lease_ctx, out);
476
GF_VALIDATE_OR_GOTO("leases", inode, out);
477
GF_VALIDATE_OR_GOTO("leases", lease, out);
479
gf_msg_trace(frame->this->name, 0,
480
"Granting lease lock to client %s with lease id %s"
482
client_uid, leaseid_utoa(lease->lease_id),
483
uuid_utoa(inode->gfid));
485
lease_entry = __get_or_new_lease_entry(frame, lease->lease_id, lease_ctx);
491
lease_entry->lease_type_cnt[lease->lease_type]++;
492
lease_entry->lease_cnt++;
493
lease_entry->lease_type |= lease->lease_type;
497
if (lease_entry->lease_cnt == 1) {
498
add_inode_to_client_list(frame->this, inode, client_uid);
501
lease_ctx->lease_cnt++;
502
lease_ctx->lease_type_cnt[lease->lease_type]++;
503
lease_ctx->lease_type |= lease->lease_type;
509
if (lease_ctx->lease_cnt == 1) {
510
lease_ctx->inode = inode_ref(inode);
519
__is_clnt_lease_none(const char *client_uid, lease_inode_ctx_t *lease_ctx)
521
gf_boolean_t lease_none = _gf_true;
522
lease_id_entry_t *lease_entry = NULL;
523
lease_id_entry_t *tmp = NULL;
525
list_for_each_entry_safe(lease_entry, tmp, &lease_ctx->lease_id_list,
528
if ((strcmp(client_uid, lease_entry->client_uid) == 0) &&
529
(lease_entry->lease_cnt != 0)) {
530
lease_none = _gf_false;
539
__remove_inode_from_clnt_list(xlator_t *this, lease_client_t *clnt,
543
lease_inode_t *l_inode = NULL;
544
lease_inode_t *tmp1 = NULL;
546
list_for_each_entry_safe(l_inode, tmp1, &clnt->inode_list, list)
548
if (l_inode->inode == inode) {
549
__destroy_lease_inode(l_inode);
550
gf_msg_debug(this->name, 0,
551
"Removed the inode from the client cleanup list");
561
remove_from_clnt_list(xlator_t *this, const char *client_uid, inode_t *inode)
563
leases_private_t *priv = NULL;
565
lease_client_t *clnt = NULL;
567
priv = this->private;
571
pthread_mutex_lock(&priv->mutex);
573
clnt = __get_lease_client(this, priv, client_uid);
575
pthread_mutex_unlock(&priv->mutex);
576
gf_msg(this->name, GF_LOG_ERROR, 0, LEASE_MSG_CLNT_NOTFOUND,
577
"There is no client entry found in the cleanup list");
580
ret = __remove_inode_from_clnt_list(this, clnt, inode);
582
pthread_mutex_unlock(&priv->mutex);
583
gf_msg(this->name, GF_LOG_ERROR, 0, LEASE_MSG_INODE_NOTFOUND,
584
"There is no inode entry found in the cleanup list");
588
pthread_mutex_unlock(&priv->mutex);
596
__remove_lease(xlator_t *this, inode_t *inode, lease_inode_ctx_t *lease_ctx,
597
const char *client_uid, struct gf_lease *lease)
599
lease_id_entry_t *lease_entry = NULL;
601
int32_t lease_type = 0;
602
leases_private_t *priv = NULL;
604
GF_VALIDATE_OR_GOTO("leases", lease_ctx, out);
605
GF_VALIDATE_OR_GOTO("leases", lease, out);
607
priv = this->private;
609
gf_msg_trace(this->name, 0,
610
"Removing lease entry for client: %s, "
611
"lease type:%d, lease id:%s",
612
client_uid, lease->lease_type, leaseid_utoa(lease->lease_id));
618
lease_entry = __get_lease_id_entry(lease_ctx, lease->lease_id);
620
gf_msg(this->name, GF_LOG_INFO, 0, LEASE_MSG_INVAL_UNLK_LEASE,
621
"Got unlock lease request from client:%s, but has no "
622
"corresponding lock",
628
if (!(lease_entry->lease_type & lease->lease_type)) {
629
gf_msg(this->name, GF_LOG_INFO, 0, LEASE_MSG_INVAL_UNLK_LEASE,
630
"Got unlock lease request from client:%s for an invalid "
637
lease_type = lease->lease_type;
638
lease_entry->lease_type_cnt[lease_type]--;
639
lease_entry->lease_cnt--;
641
lease_ctx->lease_type_cnt[lease_type]--;
642
lease_ctx->lease_cnt--;
644
if (lease_entry->lease_type_cnt[lease_type] == 0)
645
lease_entry->lease_type = lease_entry->lease_type & (~lease_type);
647
if (lease_ctx->lease_type_cnt[lease_type] == 0)
648
lease_ctx->lease_type = lease_ctx->lease_type & (~lease_type);
650
if (lease_entry->lease_cnt == 0) {
651
if (__is_clnt_lease_none(client_uid, lease_ctx)) {
652
gf_msg_trace(this->name, 0,
653
"Client(%s) has no leases"
654
" on gfid (%s), hence removing the inode"
655
" from the client cleanup list",
656
client_uid, uuid_utoa(inode->gfid));
657
remove_from_clnt_list(this, client_uid, lease_ctx->inode);
659
__destroy_lease_id_entry(lease_entry);
660
lease_ctx->blocked_fops_resuming = _gf_true;
663
if (lease_ctx->lease_cnt == 0 && lease_ctx->timer) {
664
ret = gf_tw_del_timer(priv->timer_wheel, lease_ctx->timer);
665
lease_ctx->recall_in_progress = _gf_false;
666
lease_ctx->timer = NULL;
673
__is_lease_grantable(xlator_t *this, lease_inode_ctx_t *lease_ctx,
674
struct gf_lease *lease, inode_t *inode)
676
uint32_t fd_count = 0;
678
fd_t *iter_fd = NULL;
679
gf_boolean_t grant = _gf_false;
680
lease_fd_ctx_t *fd_ctx = NULL;
682
GF_VALIDATE_OR_GOTO("leases", lease_ctx, out);
683
GF_VALIDATE_OR_GOTO("leases", lease, out);
684
GF_VALIDATE_OR_GOTO("leases", inode, out);
686
if (lease_ctx->recall_in_progress) {
687
gf_msg_debug(this->name, 0,
688
"Recall in progress, hence "
689
"failing the lease request");
694
if (lease_ctx->blocked_fops_resuming) {
695
gf_msg_debug(this->name, 0,
696
"Previously blocked fops resuming, hence "
697
"failing the lease request");
704
list_for_each_entry(iter_fd, &inode->fd_list, inode_list)
706
fd_ctx = fd_ctx_get_ptr(iter_fd, this);
709
UNLOCK(&inode->lock);
710
gf_msg(this->name, GF_LOG_ERROR, 0, LEASE_MSG_INVAL_FD_CTX,
711
"Unable to get fd ctx");
719
if (fd_ctx->client_uid != NULL &&
720
!__is_same_lease_id(fd_ctx->lease_id, lease->lease_id)) {
722
flags |= iter_fd->flags;
726
UNLOCK(&inode->lock);
728
gf_msg_debug(this->name, 0, "open fd count:%d flags:%d", fd_count, flags);
730
__dump_leases_info(this, lease_ctx);
732
switch (lease->lease_type) {
735
if ((fd_count > 0) && ((flags & O_WRONLY) || (flags & O_RDWR))) {
741
if (lease_ctx->lease_type == NONE ||
742
lease_ctx->lease_type == GF_RD_LEASE ||
743
!(__another_lease_found(lease_ctx, lease->lease_id)))
758
if (lease_ctx->lease_type == NONE ||
759
!(__another_lease_found(lease_ctx, lease->lease_id)))
766
gf_msg(this->name, GF_LOG_ERROR, EINVAL, LEASE_MSG_INVAL_LEASE_TYPE,
767
"Invalid lease type specified");
775
do_blocked_fops(xlator_t *this, lease_inode_ctx_t *lease_ctx)
777
struct list_head wind_list;
778
fop_stub_t *blk_fop = NULL;
779
fop_stub_t *tmp = NULL;
781
INIT_LIST_HEAD(&wind_list);
783
pthread_mutex_lock(&lease_ctx->lock);
785
if (!lease_ctx->blocked_fops_resuming) {
792
pthread_mutex_unlock(&lease_ctx->lock);
796
list_for_each_entry_safe(blk_fop, tmp, &lease_ctx->blocked_list, list)
798
list_del_init(&blk_fop->list);
799
list_add_tail(&blk_fop->list, &wind_list);
802
pthread_mutex_unlock(&lease_ctx->lock);
804
gf_msg_trace(this->name, 0, "Executing the blocked stubs on gfid(%s)",
805
uuid_utoa(lease_ctx->inode->gfid));
806
list_for_each_entry_safe(blk_fop, tmp, &wind_list, list)
808
list_del_init(&blk_fop->list);
809
gf_msg_trace(this->name, 0, "Executing fop:%d", blk_fop->stub->fop);
810
call_resume(blk_fop->stub);
814
pthread_mutex_lock(&lease_ctx->lock);
816
lease_ctx->lease_type = NONE;
819
lease_ctx->blocked_fops_resuming = _gf_false;
820
inode_unref(lease_ctx->inode);
821
lease_ctx->inode = NULL;
823
pthread_mutex_unlock(&lease_ctx->lock);
829
recall_lease_timer_handler(struct gf_tw_timer_list *timer, void *data,
830
unsigned long calltime)
832
inode_t *inode = NULL;
833
lease_inode_t *lease_inode = NULL;
834
leases_private_t *priv = NULL;
835
lease_timer_data_t *timer_data = NULL;
839
priv = timer_data->this->private;
840
inode = timer_data->inode;
841
lease_inode = new_lease_inode(inode);
846
pthread_mutex_lock(&priv->mutex);
848
list_add_tail(&lease_inode->list, &priv->recall_list);
849
pthread_cond_broadcast(&priv->cond);
851
pthread_mutex_unlock(&priv->mutex);
854
inode_unref(timer_data->inode);
860
__recall_lease(xlator_t *this, lease_inode_ctx_t *lease_ctx)
862
lease_id_entry_t *lease_entry = NULL;
863
lease_id_entry_t *tmp = NULL;
864
struct gf_upcall up_req = {
867
struct gf_upcall_recall_lease recall_req = {
871
struct gf_tw_timer_list *timer = NULL;
872
leases_private_t *priv = NULL;
873
lease_timer_data_t *timer_data = NULL;
876
if (lease_ctx->recall_in_progress) {
877
gf_msg_debug(this->name, 0,
878
"Lease recall is already in "
879
"progress, hence not sending another recall");
883
priv = this->private;
884
recall_time = gf_time();
885
list_for_each_entry_safe(lease_entry, tmp, &lease_ctx->lease_id_list,
888
gf_uuid_copy(up_req.gfid, lease_ctx->inode->gfid);
889
up_req.client_uid = lease_entry->client_uid;
890
up_req.event_type = GF_UPCALL_RECALL_LEASE;
891
up_req.data = &recall_req;
893
notify_ret = this->notify(this, GF_EVENT_UPCALL, &up_req);
894
if (notify_ret < 0) {
895
gf_msg(this->name, GF_LOG_ERROR, 0, LEASE_MSG_RECALL_FAIL,
896
"Recall notification to client: %s failed",
897
lease_entry->client_uid);
901
gf_msg_debug(this->name, 0,
903
"notification sent to client %s",
904
lease_entry->client_uid);
907
lease_ctx->recall_in_progress = _gf_true;
908
lease_entry->recall_time = recall_time;
910
timer = GF_MALLOC(sizeof(*timer), gf_common_mt_tw_timer_list);
914
timer_data = GF_MALLOC(sizeof(lease_timer_data_t),
915
gf_leases_mt_timer_data_t);
921
timer_data->inode = inode_ref(lease_ctx->inode);
922
timer_data->this = this;
923
timer->data = timer_data;
925
INIT_LIST_HEAD(&timer->entry);
926
timer->expires = get_recall_lease_timeout(this);
927
timer->function = recall_lease_timer_handler;
928
lease_ctx->timer = timer;
929
gf_tw_add_timer(priv->timer_wheel, timer);
930
gf_msg_trace(this->name, 0,
943
process_lease_req(call_frame_t *frame, xlator_t *this, inode_t *inode,
944
struct gf_lease *lease)
947
char *client_uid = NULL;
948
lease_inode_ctx_t *lease_ctx = NULL;
950
GF_VALIDATE_OR_GOTO("leases", frame, out);
951
GF_VALIDATE_OR_GOTO("leases", this, out);
952
GF_VALIDATE_OR_GOTO("leases", inode, out);
953
GF_VALIDATE_OR_GOTO("leases", lease, out);
955
client_uid = frame->root->client->client_uid;
957
if (!is_valid_lease_id(lease->lease_id)) {
958
gf_msg(this->name, GF_LOG_ERROR, EINVAL, LEASE_MSG_INVAL_LEASE_ID,
959
"Invalid lease id, from"
967
lease_ctx = lease_ctx_get(inode, this);
969
gf_msg(this->name, GF_LOG_WARNING, ENOMEM, LEASE_MSG_NO_MEM,
970
"Unable to create/get inode ctx, "
978
gf_msg_debug(this->name, 0,
979
"Lease request from client: %s, "
980
"lease type:%d, lease cmd:%d, lease ID:%s, gfid:%s",
981
client_uid, lease->lease_type, lease->cmd,
982
leaseid_utoa(lease->lease_id), uuid_utoa(inode->gfid));
984
pthread_mutex_lock(&lease_ctx->lock);
986
switch (lease->cmd) {
988
lease->lease_type = lease_ctx->lease_type;
989
gf_msg_debug(this->name, 0,
990
"Get lease, existing lease"
992
lease_ctx->lease_type);
997
if (__is_lease_grantable(this, lease_ctx, lease, inode)) {
998
__add_lease(frame, inode, lease_ctx, client_uid, lease);
1001
gf_msg_debug(this->name, GF_LOG_DEBUG,
1002
"Not granting the conflicting lease"
1003
" request from %s on gfid(%s)",
1004
client_uid, uuid_utoa(inode->gfid));
1005
__recall_lease(this, lease_ctx);
1010
ret = __remove_lease(this, inode, lease_ctx, client_uid, lease);
1011
if ((ret >= 0) && (lease_ctx->lease_cnt == 0)) {
1012
pthread_mutex_unlock(&lease_ctx->lock);
1021
pthread_mutex_unlock(&lease_ctx->lock);
1026
do_blocked_fops(this, lease_ctx);
1035
__check_lease_conflict(call_frame_t *frame, lease_inode_ctx_t *lease_ctx,
1036
const char *lease_id, gf_boolean_t is_write)
1038
gf_lease_types_t lease_type = {
1041
gf_boolean_t conflicts = _gf_false;
1042
lease_id_entry_t *lease_entry = NULL;
1044
GF_VALIDATE_OR_GOTO("leases", frame, out);
1045
GF_VALIDATE_OR_GOTO("leases", lease_ctx, out);
1047
lease_type = lease_ctx->lease_type;
1052
if ((frame->root->op == GF_FOP_RENAME) ||
1053
(frame->root->op == GF_FOP_UNLINK)) {
1054
conflicts = _gf_true;
1064
if (frame->root->pid < 0) {
1065
conflicts = _gf_false;
1071
if (!lease_id && (lease_ctx->lease_cnt > 0)) {
1072
conflicts = _gf_true;
1076
switch (lease_type) {
1077
case (GF_RW_LEASE | GF_RD_LEASE):
1079
lease_entry = __get_lease_id_entry(lease_ctx, lease_id);
1080
if (lease_entry && (lease_entry->lease_type & GF_RW_LEASE))
1081
conflicts = _gf_false;
1083
conflicts = _gf_true;
1086
if (is_write && __another_lease_found(lease_ctx, lease_id))
1087
conflicts = _gf_true;
1089
conflicts = _gf_false;
1100
__recall_lease(frame->this, lease_ctx);
1111
check_lease_conflict(call_frame_t *frame, inode_t *inode, const char *lease_id,
1114
lease_inode_ctx_t *lease_ctx = NULL;
1115
gf_boolean_t is_blocking_fop = _gf_false;
1116
gf_boolean_t is_write_fop = _gf_false;
1117
gf_boolean_t conflicts = _gf_false;
1120
lease_ctx = lease_ctx_get(inode, frame->this);
1122
gf_msg(frame->this->name, GF_LOG_WARNING, ENOMEM, LEASE_MSG_NO_MEM,
1123
"Unable to create/get inode ctx");
1129
is_blocking_fop = ((fop_flags & BLOCKING_FOP) != 0);
1130
is_write_fop = ((fop_flags & DATA_MODIFY_FOP) != 0);
1132
pthread_mutex_lock(&lease_ctx->lock);
1134
if (lease_ctx->lease_type == NONE) {
1135
pthread_mutex_unlock(&lease_ctx->lock);
1136
gf_msg_debug(frame->this->name, 0,
1137
"No leases found continuing with the"
1139
gf_fop_list[frame->root->op]);
1143
conflicts = __check_lease_conflict(frame, lease_ctx, lease_id,
1146
if (is_blocking_fop) {
1147
gf_msg_debug(frame->this->name, 0,
1149
"conflicting existing "
1150
"lease: %d, blocking the"
1152
gf_fop_list[frame->root->op],
1153
lease_ctx->lease_type);
1156
gf_msg_debug(frame->this->name, 0,
1158
"conflicting existing "
1159
"lease: %d, sending "
1161
gf_fop_list[frame->root->op],
1162
lease_ctx->lease_type);
1168
pthread_mutex_unlock(&lease_ctx->lock);
1174
remove_clnt_leases(const char *client_uid, inode_t *inode, xlator_t *this)
1176
lease_inode_ctx_t *lease_ctx = NULL;
1177
lease_id_entry_t *lease_entry = NULL;
1178
lease_id_entry_t *tmp = NULL;
1182
lease_ctx = lease_ctx_get(inode, this);
1184
gf_msg(this->name, GF_LOG_WARNING, ENOMEM, LEASE_MSG_INVAL_INODE_CTX,
1185
"Unable to create/get inode ctx");
1191
pthread_mutex_lock(&lease_ctx->lock);
1193
list_for_each_entry_safe(lease_entry, tmp, &lease_ctx->lease_id_list,
1196
if (strcmp(client_uid, lease_entry->client_uid) == 0) {
1197
for (i = 0; i < GF_LEASE_MAX_TYPE; i++) {
1198
lease_ctx->lease_type_cnt[i] -= lease_entry
1199
->lease_type_cnt[i];
1201
lease_ctx->lease_cnt -= lease_entry->lease_cnt;
1202
__destroy_lease_id_entry(lease_entry);
1203
if (lease_ctx->lease_cnt == 0) {
1204
lease_ctx->blocked_fops_resuming = _gf_true;
1205
pthread_mutex_unlock(&lease_ctx->lock);
1211
pthread_mutex_unlock(&lease_ctx->lock);
1216
do_blocked_fops(this, lease_ctx);
1221
cleanup_client_leases(xlator_t *this, const char *client_uid)
1223
lease_client_t *clnt = NULL;
1224
lease_client_t *tmp = NULL;
1225
struct list_head cleanup_list = {
1228
lease_inode_t *l_inode = NULL;
1229
lease_inode_t *tmp1 = NULL;
1230
leases_private_t *priv = NULL;
1233
priv = this->private;
1240
INIT_LIST_HEAD(&cleanup_list);
1241
pthread_mutex_lock(&priv->mutex);
1243
list_for_each_entry_safe(clnt, tmp, &priv->client_list, client_list)
1245
if ((strcmp(clnt->client_uid, client_uid) == 0)) {
1246
list_for_each_entry_safe(l_inode, tmp1, &clnt->inode_list, list)
1248
list_del_init(&l_inode->list);
1249
list_add_tail(&l_inode->list, &cleanup_list);
1251
__destroy_lease_client(clnt);
1256
pthread_mutex_unlock(&priv->mutex);
1258
l_inode = tmp1 = NULL;
1259
list_for_each_entry_safe(l_inode, tmp1, &cleanup_list, list)
1261
remove_clnt_leases(client_uid, l_inode->inode, this);
1262
__destroy_lease_inode(l_inode);
1269
__remove_all_leases(xlator_t *this, lease_inode_ctx_t *lease_ctx)
1272
lease_id_entry_t *lease_entry = NULL;
1273
lease_id_entry_t *tmp = NULL;
1275
if (lease_ctx->lease_cnt == 0) {
1279
__dump_leases_info(this, lease_ctx);
1281
list_for_each_entry_safe(lease_entry, tmp, &lease_ctx->lease_id_list,
1284
lease_entry->lease_cnt = 0;
1285
remove_from_clnt_list(this, lease_entry->client_uid, lease_ctx->inode);
1286
__destroy_lease_id_entry(lease_entry);
1288
INIT_LIST_HEAD(&lease_ctx->lease_id_list);
1289
for (i = 0; i <= GF_LEASE_MAX_TYPE; i++)
1290
lease_ctx->lease_type_cnt[i] = 0;
1291
lease_ctx->lease_type = 0;
1292
lease_ctx->lease_cnt = 0;
1293
lease_ctx->recall_in_progress = _gf_false;
1294
lease_ctx->timer = NULL;
1295
lease_ctx->blocked_fops_resuming = _gf_true;
1306
remove_all_leases(xlator_t *this, inode_t *inode)
1308
lease_inode_ctx_t *lease_ctx = NULL;
1311
GF_VALIDATE_OR_GOTO("leases", inode, out);
1313
lease_ctx = lease_ctx_get(inode, this);
1315
gf_msg(this->name, GF_LOG_WARNING, ENOMEM, LEASE_MSG_INVAL_INODE_CTX,
1316
"Unable to create/get inode ctx");
1322
pthread_mutex_lock(&lease_ctx->lock);
1324
__remove_all_leases(this, lease_ctx);
1326
pthread_mutex_unlock(&lease_ctx->lock);
1328
do_blocked_fops(this, lease_ctx);
1334
expired_recall_cleanup(void *data)
1336
struct timespec sleep_till = {
1339
struct list_head recall_cleanup_list;
1340
lease_inode_t *recall_entry = NULL;
1341
lease_inode_t *tmp = NULL;
1342
leases_private_t *priv = NULL;
1343
xlator_t *this = NULL;
1346
GF_VALIDATE_OR_GOTO("leases", data, out);
1349
priv = this->private;
1351
gf_msg_debug(this->name, 0, "Started the expired_recall_cleanup thread");
1354
time_now = gf_time();
1355
pthread_mutex_lock(&priv->mutex);
1358
pthread_mutex_unlock(&priv->mutex);
1361
INIT_LIST_HEAD(&recall_cleanup_list);
1362
if (list_empty(&priv->recall_list)) {
1363
sleep_till.tv_sec = time_now + 600;
1364
pthread_cond_timedwait(&priv->cond, &priv->mutex, &sleep_till);
1366
if (!list_empty(&priv->recall_list)) {
1367
gf_msg_debug(this->name, 0, "Found expired recalls");
1368
list_for_each_entry_safe(recall_entry, tmp, &priv->recall_list,
1371
list_del_init(&recall_entry->list);
1372
list_add_tail(&recall_entry->list, &recall_cleanup_list);
1376
pthread_mutex_unlock(&priv->mutex);
1378
recall_entry = tmp = NULL;
1379
list_for_each_entry_safe(recall_entry, tmp, &recall_cleanup_list, list)
1381
gf_msg_debug(this->name, 0,
1382
"Recall lease was sent on"
1383
" inode:%p, recall timer has expired"
1384
" and clients haven't unlocked the lease"
1385
" hence cleaning up leases on the inode",
1386
recall_entry->inode);
1387
remove_all_leases(this, recall_entry->inode);
1390
__destroy_lease_inode(recall_entry);