X-Git-Url: https://git.whamcloud.com/?a=blobdiff_plain;f=lustre%2Fldlm%2Fldlm_flock.c;h=a8a4e417e03135c19faec2a4b63ec370c7670158;hb=4527751bec98cb25190d0fe7d242964b5fe32aa7;hp=c2da61acf06bebbe687a2f10473334e3d9b089c1;hpb=94a4663db95656ade6b6e695b849cd7763f0bd49;p=fs%2Flustre-release.git diff --git a/lustre/ldlm/ldlm_flock.c b/lustre/ldlm/ldlm_flock.c index c2da61a..a8a4e41 100644 --- a/lustre/ldlm/ldlm_flock.c +++ b/lustre/ldlm/ldlm_flock.c @@ -116,6 +116,24 @@ static inline void ldlm_flock_blocking_unlink(struct ldlm_lock *req) &req->l_exp_flock_hash); } +/** Remove cancelled lock from resource interval tree. */ +void ldlm_flock_unlink_lock(struct ldlm_lock *lock) +{ + struct ldlm_resource *res = lock->l_resource; + struct ldlm_interval *node = lock->l_tree_node; + + if (!node || !interval_is_intree(&node->li_node)) /* duplicate unlink */ + return; + + node = ldlm_interval_detach(lock); + if (node) { + struct interval_node **root = &res->lr_flock_node.lfn_root; + + interval_erase(&node->li_node, root); + ldlm_interval_free(node); + } +} + static inline void ldlm_flock_destroy(struct ldlm_lock *lock, enum ldlm_mode mode, __u64 flags) { @@ -137,6 +155,7 @@ ldlm_flock_destroy(struct ldlm_lock *lock, enum ldlm_mode mode, __u64 flags) */ ldlm_lock_decref_internal_nolock(lock, mode); } + ldlm_flock_unlink_lock(lock); ldlm_lock_destroy_nolock(lock); EXIT; @@ -264,6 +283,64 @@ static void ldlm_flock_cancel_on_deadlock(struct ldlm_lock *lock, } #endif /* HAVE_SERVER_SUPPORT */ +/** Add newly granted lock into interval tree for the resource. */ +static void ldlm_flock_add_lock(struct ldlm_resource *res, + struct list_head *head, + struct ldlm_lock *lock) +{ + struct interval_node *found, **root; + struct ldlm_interval *node = lock->l_tree_node; + struct ldlm_extent *extent = &lock->l_policy_data.l_extent; + int rc; + + LASSERT(ldlm_is_granted(lock)); + + LASSERT(node != NULL); + LASSERT(!interval_is_intree(&node->li_node)); + + rc = interval_set(&node->li_node, extent->start, extent->end); + LASSERT(!rc); + + root = &res->lr_flock_node.lfn_root; + found = interval_insert(&node->li_node, root); + if (found) { /* The same extent found. */ + struct ldlm_interval *tmp = ldlm_interval_detach(lock); + + LASSERT(tmp != NULL); + ldlm_interval_free(tmp); + ldlm_interval_attach(to_ldlm_interval(found), lock); + } + + /* Add the locks into list */ + ldlm_resource_add_lock(res, head, lock); +} + +static void +ldlm_flock_range_update(struct ldlm_lock *lock, struct ldlm_lock *req) +{ + struct ldlm_resource *res = lock->l_resource; + struct interval_node *found, **root = &res->lr_flock_node.lfn_root; + struct ldlm_interval *node; + struct ldlm_extent *extent = &lock->l_policy_data.l_extent; + + node = ldlm_interval_detach(lock); + if (!node) { + node = ldlm_interval_detach(req); + LASSERT(node); + } else { + interval_erase(&node->li_node, root); + } + interval_set(&node->li_node, extent->start, extent->end); + + found = interval_insert(&node->li_node, root); + if (found) { /* The policy group found. */ + ldlm_interval_free(node); + node = to_ldlm_interval(found); + } + ldlm_interval_attach(node, lock); + EXIT; +} + /** * Process a granting attempt for flock lock. * Must be called under ns lock held. @@ -501,6 +578,7 @@ reprocess: lock->l_policy_data.l_flock.end) { lock->l_policy_data.l_flock.end = new->l_policy_data.l_flock.start - 1; + ldlm_flock_range_update(lock, req); continue; } @@ -561,7 +639,7 @@ reprocess: lock->l_granted_mode); /* insert new2 at lock */ - ldlm_resource_add_lock(res, &lock->l_res_link, new2); + ldlm_flock_add_lock(res, &lock->l_res_link, new2); LDLM_LOCK_RELEASE(new2); break; } @@ -581,7 +659,7 @@ reprocess: * lock for the next owner, or might not be a lock at * all, but instead points at the head of the list */ - ldlm_resource_add_lock(res, &lock->l_res_link, req); + ldlm_flock_add_lock(res, &lock->l_res_link, req); } if (*flags != LDLM_FL_WAIT_NOREPROC) {