⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 recover.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
	int error = 0, count = 0;	log_debug(ls, "dlm_recover_masters");	down_read(&ls->ls_root_sem);	list_for_each_entry(r, &ls->ls_root_list, res_root_list) {		if (dlm_recovery_stopped(ls)) {			up_read(&ls->ls_root_sem);			error = -EINTR;			goto out;		}		if (dlm_no_directory(ls))			count += recover_master_static(r);		else if (!is_master(r) &&			 (dlm_is_removed(ls, r->res_nodeid) ||			  rsb_flag(r, RSB_NEW_MASTER))) {			recover_master(r);			count++;		}		schedule();	}	up_read(&ls->ls_root_sem);	log_debug(ls, "dlm_recover_masters %d resources", count);	error = dlm_wait_function(ls, &recover_list_empty); out:	if (error)		recover_list_clear(ls);	return error;}int dlm_recover_master_reply(struct dlm_ls *ls, struct dlm_rcom *rc){	struct dlm_rsb *r;	int nodeid;	r = recover_list_find(ls, rc->rc_id);	if (!r) {		log_error(ls, "dlm_recover_master_reply no id %llx",			  (unsigned long long)rc->rc_id);		goto out;	}	nodeid = rc->rc_result;	if (nodeid == dlm_our_nodeid())		nodeid = 0;	set_new_master(r, nodeid);	recover_list_del(r);	if (recover_list_empty(ls))		wake_up(&ls->ls_wait_general); out:	return 0;}/* Lock recovery: rebuild the process-copy locks we hold on a   remastered rsb on the new rsb master.   dlm_recover_locks   recover_locks   recover_locks_queue   dlm_send_rcom_lock              ->  receive_rcom_lock                                       dlm_recover_master_copy   receive_rcom_lock_reply         <-   dlm_recover_process_copy*//* * keep a count of the number of lkb's we send to the new master; when we get * an equal number of replies then recovery for the rsb is done */static int recover_locks_queue(struct dlm_rsb *r, struct list_head *head){	struct dlm_lkb *lkb;	int error = 0;	list_for_each_entry(lkb, head, lkb_statequeue) {	   	error = dlm_send_rcom_lock(r, lkb);		if (error)			break;		r->res_recover_locks_count++;	}	return error;}static int recover_locks(struct dlm_rsb *r){	int error = 0;	lock_rsb(r);	DLM_ASSERT(!r->res_recover_locks_count, dlm_dump_rsb(r););	error = recover_locks_queue(r, &r->res_grantqueue);	if (error)		goto out;	error = recover_locks_queue(r, &r->res_convertqueue);	if (error)		goto out;	error = recover_locks_queue(r, &r->res_waitqueue);	if (error)		goto out;	if (r->res_recover_locks_count)		recover_list_add(r);	else		rsb_clear_flag(r, RSB_NEW_MASTER); out:	unlock_rsb(r);	return error;}int dlm_recover_locks(struct dlm_ls *ls){	struct dlm_rsb *r;	int error, count = 0;	log_debug(ls, "dlm_recover_locks");	down_read(&ls->ls_root_sem);	list_for_each_entry(r, &ls->ls_root_list, res_root_list) {		if (is_master(r)) {			rsb_clear_flag(r, RSB_NEW_MASTER);			continue;		}		if (!rsb_flag(r, RSB_NEW_MASTER))			continue;		if (dlm_recovery_stopped(ls)) {			error = -EINTR;			up_read(&ls->ls_root_sem);			goto out;		}		error = recover_locks(r);		if (error) {			up_read(&ls->ls_root_sem);			goto out;		}		count += r->res_recover_locks_count;	}	up_read(&ls->ls_root_sem);	log_debug(ls, "dlm_recover_locks %d locks", count);	error = dlm_wait_function(ls, &recover_list_empty); out:	if (error)		recover_list_clear(ls);	else		dlm_set_recover_status(ls, DLM_RS_LOCKS);	return error;}void dlm_recovered_lock(struct dlm_rsb *r){	DLM_ASSERT(rsb_flag(r, RSB_NEW_MASTER), dlm_dump_rsb(r););	r->res_recover_locks_count--;	if (!r->res_recover_locks_count) {		rsb_clear_flag(r, RSB_NEW_MASTER);		recover_list_del(r);	}	if (recover_list_empty(r->res_ls))		wake_up(&r->res_ls->ls_wait_general);}/* * The lvb needs to be recovered on all master rsb's.  This includes setting * the VALNOTVALID flag if necessary, and determining the correct lvb contents * based on the lvb's of the locks held on the rsb. * * RSB_VALNOTVALID is set if there are only NL/CR locks on the rsb.  If it * was already set prior to recovery, it's not cleared, regardless of locks. * * The LVB contents are only considered for changing when this is a new master * of the rsb (NEW_MASTER2).  Then, the rsb's lvb is taken from any lkb with * mode > CR.  If no lkb's exist with mode above CR, the lvb contents are taken * from the lkb with the largest lvb sequence number. */static void recover_lvb(struct dlm_rsb *r){	struct dlm_lkb *lkb, *high_lkb = NULL;	uint32_t high_seq = 0;	int lock_lvb_exists = 0;	int big_lock_exists = 0;	int lvblen = r->res_ls->ls_lvblen;	list_for_each_entry(lkb, &r->res_grantqueue, lkb_statequeue) {		if (!(lkb->lkb_exflags & DLM_LKF_VALBLK))			continue;		lock_lvb_exists = 1;		if (lkb->lkb_grmode > DLM_LOCK_CR) {			big_lock_exists = 1;			goto setflag;		}		if (((int)lkb->lkb_lvbseq - (int)high_seq) >= 0) {			high_lkb = lkb;			high_seq = lkb->lkb_lvbseq;		}	}	list_for_each_entry(lkb, &r->res_convertqueue, lkb_statequeue) {		if (!(lkb->lkb_exflags & DLM_LKF_VALBLK))			continue;		lock_lvb_exists = 1;		if (lkb->lkb_grmode > DLM_LOCK_CR) {			big_lock_exists = 1;			goto setflag;		}		if (((int)lkb->lkb_lvbseq - (int)high_seq) >= 0) {			high_lkb = lkb;			high_seq = lkb->lkb_lvbseq;		}	} setflag:	if (!lock_lvb_exists)		goto out;	if (!big_lock_exists)		rsb_set_flag(r, RSB_VALNOTVALID);	/* don't mess with the lvb unless we're the new master */	if (!rsb_flag(r, RSB_NEW_MASTER2))		goto out;	if (!r->res_lvbptr) {		r->res_lvbptr = allocate_lvb(r->res_ls);		if (!r->res_lvbptr)			goto out;	}	if (big_lock_exists) {		r->res_lvbseq = lkb->lkb_lvbseq;		memcpy(r->res_lvbptr, lkb->lkb_lvbptr, lvblen);	} else if (high_lkb) {		r->res_lvbseq = high_lkb->lkb_lvbseq;		memcpy(r->res_lvbptr, high_lkb->lkb_lvbptr, lvblen);	} else {		r->res_lvbseq = 0;		memset(r->res_lvbptr, 0, lvblen);	} out:	return;}/* All master rsb's flagged RECOVER_CONVERT need to be looked at.  The locks   converting PR->CW or CW->PR need to have their lkb_grmode set. */static void recover_conversion(struct dlm_rsb *r){	struct dlm_lkb *lkb;	int grmode = -1;	list_for_each_entry(lkb, &r->res_grantqueue, lkb_statequeue) {		if (lkb->lkb_grmode == DLM_LOCK_PR ||		    lkb->lkb_grmode == DLM_LOCK_CW) {			grmode = lkb->lkb_grmode;			break;		}	}	list_for_each_entry(lkb, &r->res_convertqueue, lkb_statequeue) {		if (lkb->lkb_grmode != DLM_LOCK_IV)			continue;		if (grmode == -1)			lkb->lkb_grmode = lkb->lkb_rqmode;		else			lkb->lkb_grmode = grmode;	}}/* We've become the new master for this rsb and waiting/converting locks may   need to be granted in dlm_grant_after_purge() due to locks that may have   existed from a removed node. */static void set_locks_purged(struct dlm_rsb *r){	if (!list_empty(&r->res_waitqueue) || !list_empty(&r->res_convertqueue))		rsb_set_flag(r, RSB_LOCKS_PURGED);}void dlm_recover_rsbs(struct dlm_ls *ls){	struct dlm_rsb *r;	int count = 0;	log_debug(ls, "dlm_recover_rsbs");	down_read(&ls->ls_root_sem);	list_for_each_entry(r, &ls->ls_root_list, res_root_list) {		lock_rsb(r);		if (is_master(r)) {			if (rsb_flag(r, RSB_RECOVER_CONVERT))				recover_conversion(r);			if (rsb_flag(r, RSB_NEW_MASTER2))				set_locks_purged(r);			recover_lvb(r);			count++;		}		rsb_clear_flag(r, RSB_RECOVER_CONVERT);		rsb_clear_flag(r, RSB_NEW_MASTER2);		unlock_rsb(r);	}	up_read(&ls->ls_root_sem);	log_debug(ls, "dlm_recover_rsbs %d rsbs", count);}/* Create a single list of all root rsb's to be used during recovery */int dlm_create_root_list(struct dlm_ls *ls){	struct dlm_rsb *r;	int i, error = 0;	down_write(&ls->ls_root_sem);	if (!list_empty(&ls->ls_root_list)) {		log_error(ls, "root list not empty");		error = -EINVAL;		goto out;	}	for (i = 0; i < ls->ls_rsbtbl_size; i++) {		read_lock(&ls->ls_rsbtbl[i].lock);		list_for_each_entry(r, &ls->ls_rsbtbl[i].list, res_hashchain) {			list_add(&r->res_root_list, &ls->ls_root_list);			dlm_hold_rsb(r);		}		read_unlock(&ls->ls_rsbtbl[i].lock);	} out:	up_write(&ls->ls_root_sem);	return error;}void dlm_release_root_list(struct dlm_ls *ls){	struct dlm_rsb *r, *safe;	down_write(&ls->ls_root_sem);	list_for_each_entry_safe(r, safe, &ls->ls_root_list, res_root_list) {		list_del_init(&r->res_root_list);		dlm_put_rsb(r);	}	up_write(&ls->ls_root_sem);}void dlm_clear_toss_list(struct dlm_ls *ls){	struct dlm_rsb *r, *safe;	int i;	for (i = 0; i < ls->ls_rsbtbl_size; i++) {		write_lock(&ls->ls_rsbtbl[i].lock);		list_for_each_entry_safe(r, safe, &ls->ls_rsbtbl[i].toss,					 res_hashchain) {			list_del(&r->res_hashchain);			free_rsb(r);		}		write_unlock(&ls->ls_rsbtbl[i].lock);	}}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -