fs/dlm/lock.c

Source file repositories/reference/linux-study-clean/fs/dlm/lock.c

File Facts

System
Linux kernel
Corpus path
fs/dlm/lock.c
Extension
.c
Size
167187 bytes
Lines
6339
Domain
Core OS
Bucket
VFS And Filesystem Core
Inferred role
Core OS: implementation source
Status
source implementation candidate

Why This File Exists

Core operating-system implementation surface: boot, tasks, memory, VFS, syscall-facing interfaces, synchronization, credentials, and isolation.

Dependency Surface

Detected Declarations

Annotated Snippet

if (!rv) {
			/* rearm again try timer */
			enable_scan_timer(ls, DLM_TOSS_TIMER_RETRY);
			break;
		}

		r = list_first_entry_or_null(&ls->ls_scan_list, struct dlm_rsb,
					     res_scan_list);
		if (!r) {
			/* the next add_scan will enable the timer again */
			spin_unlock(&ls->ls_scan_lock);
			break;
		}

		/*
		 * If the first rsb is not yet expired, then stop because the
		 * list is sorted with nearest expiration first.
		 */
		if (time_before(jiffies, r->res_toss_time)) {
			/* rearm with the next rsb to expire in the future */
			enable_scan_timer(ls, r->res_toss_time);
			spin_unlock(&ls->ls_scan_lock);
			break;
		}

		/* in find_rsb_dir/nodir there is a reverse order of this
		 * lock, however this is only a trylock if we hit some
		 * possible contention we try it again.
		 */
		rv = write_trylock(&ls->ls_rsbtbl_lock);
		if (!rv) {
			spin_unlock(&ls->ls_scan_lock);
			/* rearm again try timer */
			enable_scan_timer(ls, DLM_TOSS_TIMER_RETRY);
			break;
		}

		list_del(&r->res_slow_list);
		rhashtable_remove_fast(&ls->ls_rsbtbl, &r->res_node,
				       dlm_rhash_rsb_params);
		rsb_clear_flag(r, RSB_HASHED);

		/* ls_rsbtbl_lock is not needed when calling send_remove() */
		write_unlock(&ls->ls_rsbtbl_lock);

		list_del_init(&r->res_scan_list);
		spin_unlock(&ls->ls_scan_lock);

		/* An rsb that is a dir record for a remote master rsb
		 * cannot be removed, and should not have a timer enabled.
		 */
		WARN_ON(!dlm_no_directory(ls) &&
			(r->res_master_nodeid != our_nodeid) &&
			(dlm_dir_nodeid(r) == our_nodeid));

		/* We're the master of this rsb but we're not
		 * the directory record, so we need to tell the
		 * dir node to remove the dir record
		 */
		if (!dlm_no_directory(ls) &&
		    (r->res_master_nodeid == our_nodeid) &&
		    (dlm_dir_nodeid(r) != our_nodeid))
			send_remove(r);

		free_inactive_rsb(r);
	}
}

/* If ls->ls_new_rsb is empty, return -EAGAIN, so the caller can
   unlock any spinlocks, go back and call pre_rsb_struct again.
   Otherwise, take an rsb off the list and return it. */

static int get_rsb_struct(struct dlm_ls *ls, const void *name, int len,
			  struct dlm_rsb **r_ret)
{
	struct dlm_rsb *r;

	r = dlm_allocate_rsb();
	if (!r)
		return -ENOMEM;

	r->res_ls = ls;
	r->res_length = len;
	memcpy(r->res_name, name, len);
	spin_lock_init(&r->res_lock);

	INIT_LIST_HEAD(&r->res_lookup);
	INIT_LIST_HEAD(&r->res_grantqueue);
	INIT_LIST_HEAD(&r->res_convertqueue);
	INIT_LIST_HEAD(&r->res_waitqueue);

Annotation

Implementation Notes