vfs_lockf.c

来自「基于组件方式开发操作系统的OSKIT源代码」· C语言 代码 · 共 799 行 · 第 1/2 页

C
799
字号
lf_clearlock(unlock)	register struct lockf *unlock;{	struct lockf **head = unlock->lf_head;	register struct lockf *lf = *head;	struct lockf *overlap, **prev;	int ovcase;	if (lf == NOLOCKF)		return (0);#ifdef LOCKF_DEBUG	if (unlock->lf_type != F_UNLCK)		panic("lf_clearlock: bad type");	if (lockf_debug & 1)		lf_print("lf_clearlock", unlock);#endif /* LOCKF_DEBUG */	prev = head;	while ((ovcase = lf_findoverlap(lf, unlock, SELF,					&prev, &overlap)) != 0) {		/*		 * Wakeup the list of locks to be retried.		 */		lf_wakelock(overlap);		switch (ovcase) {		case 1: /* overlap == lock */			*prev = overlap->lf_next;			FREE(overlap, M_LOCKF);			break;		case 2: /* overlap contains lock: split it */			if (overlap->lf_start == unlock->lf_start) {				overlap->lf_start = unlock->lf_end + 1;				break;			}			lf_split(overlap, unlock);			overlap->lf_next = unlock->lf_next;			break;		case 3: /* lock contains overlap */			*prev = overlap->lf_next;			lf = overlap->lf_next;			free(overlap, M_LOCKF);			continue;		case 4: /* overlap starts before lock */			overlap->lf_end = unlock->lf_start - 1;			prev = &overlap->lf_next;			lf = overlap->lf_next;			continue;		case 5: /* overlap ends after lock */			overlap->lf_start = unlock->lf_end + 1;			break;		}		break;	}#ifdef LOCKF_DEBUG	if (lockf_debug & 1)		lf_printlist("lf_clearlock", unlock);#endif /* LOCKF_DEBUG */	return (0);}/* * Check whether there is a blocking lock, * and if so return its process identifier. */intlf_getlock(lock, fl)	register struct lockf *lock;	register struct flock *fl;{	register struct lockf *block;#ifdef LOCKF_DEBUG	if (lockf_debug & 1)		lf_print("lf_getlock", lock);#endif /* LOCKF_DEBUG */	if ((block = lf_getblock(lock)) != NULL) {		fl->l_type = block->lf_type;		fl->l_whence = SEEK_SET;		fl->l_start = block->lf_start;		if (block->lf_end == -1)			fl->l_len = 0;		else			fl->l_len = block->lf_end - block->lf_start + 1;		if (block->lf_flags & F_POSIX)			fl->l_pid = ((struct proc *)(block->lf_id))->p_pid;		else			fl->l_pid = -1;	} else {		fl->l_type = F_UNLCK;	}	return (0);}/* * Walk the list of locks for an inode and * return the first blocking lock. */struct lockf *lf_getblock(lock)	register struct lockf *lock;{	struct lockf **prev, *overlap, *lf = *(lock->lf_head);	int ovcase;	prev = lock->lf_head;	while ((ovcase = lf_findoverlap(lf, lock, OTHERS,					&prev, &overlap)) != 0) {		/*		 * We've found an overlap, see if it blocks us		 */		if ((lock->lf_type == F_WRLCK || overlap->lf_type == F_WRLCK))			return (overlap);		/*		 * Nope, point to the next one on the list and		 * see if it blocks us		 */		lf = overlap->lf_next;	}	return (NOLOCKF);}/* * Walk the list of locks for an inode to * find an overlapping lock (if any). * * NOTE: this returns only the FIRST overlapping lock.  There *	 may be more than one. */intlf_findoverlap(lf, lock, type, prev, overlap)	register struct lockf *lf;	struct lockf *lock;	int type;	struct lockf ***prev;	struct lockf **overlap;{	off_t start, end;	*overlap = lf;	if (lf == NOLOCKF)		return (0);#ifdef LOCKF_DEBUG	if (lockf_debug & 2)		lf_print("lf_findoverlap: looking for overlap in", lock);#endif /* LOCKF_DEBUG */	start = lock->lf_start;	end = lock->lf_end;	while (lf != NOLOCKF) {		if (((type & SELF) && lf->lf_id != lock->lf_id) ||		    ((type & OTHERS) && lf->lf_id == lock->lf_id)) {			*prev = &lf->lf_next;			*overlap = lf = lf->lf_next;			continue;		}#ifdef LOCKF_DEBUG		if (lockf_debug & 2)			lf_print("\tchecking", lf);#endif /* LOCKF_DEBUG */		/*		 * OK, check for overlap		 *		 * Six cases:		 *	0) no overlap		 *	1) overlap == lock		 *	2) overlap contains lock		 *	3) lock contains overlap		 *	4) overlap starts before lock		 *	5) overlap ends after lock		 */		if ((lf->lf_end != -1 && start > lf->lf_end) ||		    (end != -1 && lf->lf_start > end)) {			/* Case 0 */#ifdef LOCKF_DEBUG			if (lockf_debug & 2)				printf("no overlap\n");#endif /* LOCKF_DEBUG */			if ((type & SELF) && end != -1 && lf->lf_start > end)				return (0);			*prev = &lf->lf_next;			*overlap = lf = lf->lf_next;			continue;		}		if ((lf->lf_start == start) && (lf->lf_end == end)) {			/* Case 1 */#ifdef LOCKF_DEBUG			if (lockf_debug & 2)				printf("overlap == lock\n");#endif /* LOCKF_DEBUG */			return (1);		}		if ((lf->lf_start <= start) &&		    (end != -1) &&		    ((lf->lf_end >= end) || (lf->lf_end == -1))) {			/* Case 2 */#ifdef LOCKF_DEBUG			if (lockf_debug & 2)				printf("overlap contains lock\n");#endif /* LOCKF_DEBUG */			return (2);		}		if (start <= lf->lf_start &&		           (end == -1 ||			   (lf->lf_end != -1 && end >= lf->lf_end))) {			/* Case 3 */#ifdef LOCKF_DEBUG			if (lockf_debug & 2)				printf("lock contains overlap\n");#endif /* LOCKF_DEBUG */			return (3);		}		if ((lf->lf_start < start) &&			((lf->lf_end >= start) || (lf->lf_end == -1))) {			/* Case 4 */#ifdef LOCKF_DEBUG			if (lockf_debug & 2)				printf("overlap starts before lock\n");#endif /* LOCKF_DEBUG */			return (4);		}		if ((lf->lf_start > start) &&			(end != -1) &&			((lf->lf_end > end) || (lf->lf_end == -1))) {			/* Case 5 */#ifdef LOCKF_DEBUG			if (lockf_debug & 2)				printf("overlap ends after lock\n");#endif /* LOCKF_DEBUG */			return (5);		}		panic("lf_findoverlap: default");	}	return (0);}/* * Add a lock to the end of the blocked list. */voidlf_addblock(lock, blocked)	struct lockf *lock;	struct lockf *blocked;{	register struct lockf *lf;	if (blocked == NOLOCKF)		return;#ifdef LOCKF_DEBUG	if (lockf_debug & 2) {		lf_print("addblock: adding", blocked);		lf_print("to blocked list of", lock);	}#endif /* LOCKF_DEBUG */	if ((lf = lock->lf_block) == NOLOCKF) {		lock->lf_block = blocked;		return;	}	while (lf->lf_block != NOLOCKF)		lf = lf->lf_block;	lf->lf_block = blocked;	return;}/* * Split a lock and a contained region into * two or three locks as necessary. */voidlf_split(lock1, lock2)	register struct lockf *lock1;	register struct lockf *lock2;{	register struct lockf *splitlock;#ifdef LOCKF_DEBUG	if (lockf_debug & 2) {		lf_print("lf_split", lock1);		lf_print("splitting from", lock2);	}#endif /* LOCKF_DEBUG */	/*	 * Check to see if spliting into only two pieces.	 */	if (lock1->lf_start == lock2->lf_start) {		lock1->lf_start = lock2->lf_end + 1;		lock2->lf_next = lock1;		return;	}	if (lock1->lf_end == lock2->lf_end) {		lock1->lf_end = lock2->lf_start - 1;		lock2->lf_next = lock1->lf_next;		lock1->lf_next = lock2;		return;	}	/*	 * Make a new lock consisting of the last part of	 * the encompassing lock	 */	MALLOC(splitlock, struct lockf *, sizeof *splitlock, M_LOCKF, M_WAITOK);	bcopy((caddr_t)lock1, (caddr_t)splitlock, sizeof *splitlock);	splitlock->lf_start = lock2->lf_end + 1;	splitlock->lf_block = NOLOCKF;	lock1->lf_end = lock2->lf_start - 1;	/*	 * OK, now link it in	 */	splitlock->lf_next = lock1->lf_next;	lock2->lf_next = splitlock;	lock1->lf_next = lock2;}/* * Wakeup a blocklist */voidlf_wakelock(listhead)	struct lockf *listhead;{	register struct lockf *blocklist, *wakelock;	blocklist = listhead->lf_block;	listhead->lf_block = NOLOCKF;	while (blocklist != NOLOCKF) {		wakelock = blocklist;		blocklist = blocklist->lf_block;		wakelock->lf_block = NOLOCKF;		wakelock->lf_next = NOLOCKF;#ifdef LOCKF_DEBUG		if (lockf_debug & 2)			lf_print("lf_wakelock: awakening", wakelock);#endif /* LOCKF_DEBUG */		wakeup((caddr_t)wakelock);	}}#ifdef LOCKF_DEBUG/* * Print out a lock. */voidlf_print(tag, lock)	char *tag;	register struct lockf *lock;{		printf("%s: lock %p for ", tag, lock);	if (lock->lf_flags & F_POSIX)		printf("proc %d", ((struct proc *)(lock->lf_id))->p_pid);	else		printf("id 0x%x", lock->lf_id);	printf(" in ino %d on dev <%d, %d>, %s, start %d, end %d",		lock->lf_inode->i_number,		major(lock->lf_inode->i_dev),		minor(lock->lf_inode->i_dev),		lock->lf_type == F_RDLCK ? "shared" :		lock->lf_type == F_WRLCK ? "exclusive" :		lock->lf_type == F_UNLCK ? "unlock" :		"unknown", lock->lf_start, lock->lf_end);	if (lock->lf_block)		printf(" block %p\n", lock->lf_block);	else		printf("\n");}voidlf_printlist(tag, lock)	char *tag;	struct lockf *lock;{	register struct lockf *lf;	printf("%s: Lock list for ino %d on dev <%d, %d>:\n",		tag, lock->lf_inode->i_number,		major(lock->lf_inode->i_dev),		minor(lock->lf_inode->i_dev));	for (lf = lock->lf_inode->i_lockf; lf; lf = lf->lf_next) {		printf("\tlock %p for ", lf);		if (lf->lf_flags & F_POSIX)			printf("proc %d", ((struct proc *)(lf->lf_id))->p_pid);		else			printf("id 0x%x", lf->lf_id);		printf(", %s, start %d, end %d",			lf->lf_type == F_RDLCK ? "shared" :			lf->lf_type == F_WRLCK ? "exclusive" :			lf->lf_type == F_UNLCK ? "unlock" :			"unknown", lf->lf_start, lf->lf_end);		if (lf->lf_block)			printf(" block %p\n", lf->lf_block);		else			printf("\n");	}}#endif /* LOCKF_DEBUG */

⌨️ 快捷键说明

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