Example #1
0
/**
 * Determine if the lock is compatible with all locks on the queue.
 *
 * If \a work_list is provided, conflicting locks are linked there.
 * If \a work_list is not provided, we exit this function on first conflict.
 *
 * \retval 0 if there are conflicting locks in the \a queue
 * \retval 1 if the lock is compatible to all locks in \a queue
 */
static inline int
ldlm_plain_compat_queue(struct list_head *queue, struct ldlm_lock *req,
			struct list_head *work_list)
{
	enum ldlm_mode req_mode = req->l_req_mode;
	struct ldlm_lock *lock, *next_lock;
	int compat = 1;
	ENTRY;

	lockmode_verify(req_mode);

	list_for_each_entry_safe(lock, next_lock, queue, l_res_link) {

		/* We stop walking the queue if we hit ourselves so we don't
		 * take conflicting locks enqueued after us into account,
		 * or we'd wait forever. */
		if (req == lock)
			RETURN(compat);

		/* Advance loop cursor to last lock of mode group. */
		next_lock = list_entry(list_entry(lock->l_sl_mode.prev,
						  struct ldlm_lock,
						  l_sl_mode)->l_res_link.next,
				       struct ldlm_lock, l_res_link);

		if (lockmode_compat(lock->l_req_mode, req_mode))
                        continue;

                if (!work_list)
                        RETURN(0);

                compat = 0;

		/* Add locks of the mode group to \a work_list as
		 * blocking locks for \a req. */
                if (lock->l_blocking_ast)
                        ldlm_add_ast_work_item(lock, req, work_list);

                {
			struct list_head *head;

                        head = &lock->l_sl_mode;
			list_for_each_entry(lock, head, l_sl_mode)
                                if (lock->l_blocking_ast)
                                        ldlm_add_ast_work_item(lock, req,
                                                               work_list);
                }
        }

        RETURN(compat);
}
Example #2
0
static inline int
ldlm_plain_compat_queue(cfs_list_t *queue, struct ldlm_lock *req,
                        cfs_list_t *work_list)
{
        cfs_list_t *tmp;
        struct ldlm_lock *lock;
        ldlm_mode_t req_mode = req->l_req_mode;
        int compat = 1;
        ENTRY;

        lockmode_verify(req_mode);

        cfs_list_for_each(tmp, queue) {
                lock = cfs_list_entry(tmp, struct ldlm_lock, l_res_link);

                if (req == lock)
                        RETURN(compat);

                 /* last lock in mode group */
                 tmp = &cfs_list_entry(lock->l_sl_mode.prev,
                                       struct ldlm_lock,
                                       l_sl_mode)->l_res_link;

                 if (lockmode_compat(lock->l_req_mode, req_mode))
                        continue;

                if (!work_list)
                        RETURN(0);

                compat = 0;

                /* add locks of the mode group to @work_list as
                 * blocking locks for @req */
                if (lock->l_blocking_ast)
                        ldlm_add_ast_work_item(lock, req, work_list);

                {
                        cfs_list_t *head;

                        head = &lock->l_sl_mode;
                        cfs_list_for_each_entry(lock, head, l_sl_mode)
                                if (lock->l_blocking_ast)
                                        ldlm_add_ast_work_item(lock, req,
                                                               work_list);
                }
        }
Example #3
0
/* Determine if the lock is compatible with all locks on the queue. */
static int
ldlm_inodebits_compat_queue(cfs_list_t *queue, struct ldlm_lock *req,
                            cfs_list_t *work_list)
{
        cfs_list_t *tmp;
        struct ldlm_lock *lock;
        ldlm_mode_t req_mode = req->l_req_mode;
        __u64 req_bits = req->l_policy_data.l_inodebits.bits;
        int compat = 1;
        ENTRY;

        LASSERT(req_bits); /* There is no sense in lock with no bits set,
                              I think. Also such a lock would be compatible
                               with any other bit lock */

        cfs_list_for_each(tmp, queue) {
                cfs_list_t *mode_tail;

                lock = cfs_list_entry(tmp, struct ldlm_lock, l_res_link);

                if (req == lock)
                        RETURN(compat);

                /* last lock in mode group */
                LASSERT(lock->l_sl_mode.prev != NULL);
                mode_tail = &cfs_list_entry(lock->l_sl_mode.prev,
                                            struct ldlm_lock,
                                            l_sl_mode)->l_res_link;

                /* locks are compatible, bits don't matter */
                if (lockmode_compat(lock->l_req_mode, req_mode)) {
                        /* jump to last lock in mode group */
                        tmp = mode_tail;
                        continue;
                }

                for (;;) {
                        cfs_list_t *head;

                        /* last lock in policy group */
                        tmp = &cfs_list_entry(lock->l_sl_policy.prev,
                                              struct ldlm_lock,
                                              l_sl_policy)->l_res_link;

                        /* locks with bits overlapped are conflicting locks */
                        if (lock->l_policy_data.l_inodebits.bits & req_bits) {
                                /* COS lock from the same client is
                                   not conflicting */
                                if (lock->l_req_mode == LCK_COS &&
                                    lock->l_client_cookie == req->l_client_cookie)
                                        goto not_conflicting;
                                /* conflicting policy */
                                if (!work_list)
                                        RETURN(0);

                                compat = 0;

                                /* add locks of the policy group to
                                 * @work_list as blocking locks for
                                 * @req */
                                if (lock->l_blocking_ast)
                                        ldlm_add_ast_work_item(lock, req,
                                                               work_list);
                                head = &lock->l_sl_policy;
                                cfs_list_for_each_entry(lock, head, l_sl_policy)
                                        if (lock->l_blocking_ast)
                                                ldlm_add_ast_work_item(lock, req,
                                                                       work_list);
                        }
                not_conflicting:
                        if (tmp == mode_tail)
                                break;

                        tmp = tmp->next;
                        lock = cfs_list_entry(tmp, struct ldlm_lock,
                                              l_res_link);
                } /* loop over policy groups within one mode group */
        } /* loop over mode groups within @queue */