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

📄 locks.c

📁 elinux jffs初始版本 具体了解JFFS的文件系统!
💻 C
📖 第 1 页 / 共 3 页
字号:
	error = -EBUSY;	if ((fl = filp->f_inode->i_flock) && (fl->fl_flags & FL_POSIX))		goto out;	while (fl != NULL) {		if (!flock_locks_conflict(new_fl, fl)) {			fl = fl->fl_next;			continue;		}		error = -EAGAIN;		if (!wait)			goto out;		locks_insert_block(fl, new_fl);		interruptible_sleep_on(&new_fl->fl_wait);		locks_delete_block(fl, new_fl);		goto repeat;	}	locks_insert_lock(&filp->f_inode->i_flock, new_fl);	new_fl = NULL;	error = 0;out:	if (new_fl)		locks_free_lock(new_fl);	return (error);}/* Add a POSIX style lock to a file. * We merge adjacent locks whenever possible. POSIX locks are sorted by owner * task, then by starting address * * Kai Petzke writes: * To make freeing a lock much faster, we keep a pointer to the lock before the * actual one. But the real gain of the new coding was, that lock_it() and * unlock_it() became one function. * * To all purists: Yes, I use a few goto's. Just pass on to the next function. */static int posix_lock_file(struct file *filp, struct file_lock *caller,			   unsigned int wait){	struct file_lock *fl;	struct file_lock *new_fl, *new_fl2;	struct file_lock *left = NULL;	struct file_lock *right = NULL;	struct file_lock **before;	int error;	int added = 0;	/*	 * We may need two file_lock structures for this operation,	 * so we get them in advance to avoid races.	 */	new_fl  = locks_empty_lock();	new_fl2 = locks_empty_lock();	error = -ENOLCK; /* "no luck" */	if (!(new_fl && new_fl2))		goto out; 	if (caller->fl_type != F_UNLCK) {  repeat:		error = -EBUSY;		if ((fl = filp->f_inode->i_flock) && (fl->fl_flags & FL_FLOCK))			goto out;		while (fl != NULL) {			if (!posix_locks_conflict(caller, fl)) {				fl = fl->fl_next;				continue;			}			error = -EAGAIN;			if (!wait)				goto out;			error = -EDEADLK;			if (posix_locks_deadlock(caller->fl_owner, fl->fl_owner))				goto out;			error = -ERESTARTSYS;			if (current->signal & ~current->blocked)				goto out;			locks_insert_block(fl, caller);			interruptible_sleep_on(&caller->fl_wait);			locks_delete_block(fl, caller);			goto repeat;  		}  	}	/*	 * We've allocated the new locks in advance, so there are no	 * errors possible (and no blocking operations) from here on.	 * 	 * Find the first old lock with the same owner as the new lock.	 */		before = &filp->f_inode->i_flock;	error = -EBUSY;	if ((*before != NULL) && ((*before)->fl_flags & FL_FLOCK))		goto out;	/* First skip locks owned by other processes.	 */	while ((fl = *before) && (caller->fl_owner != fl->fl_owner)) {		before = &fl->fl_next;	}	/* Process locks with this owner.	 */	while ((fl = *before) && (caller->fl_owner == fl->fl_owner)) {		/* Detect adjacent or overlapping regions (if same lock type)		 */		if (caller->fl_type == fl->fl_type) {			if (fl->fl_end < caller->fl_start - 1)				goto next_lock;			/* If the next lock in the list has entirely bigger			 * addresses than the new one, insert the lock here.			 */			if (fl->fl_start > caller->fl_end + 1)				break;			/* If we come here, the new and old lock are of the			 * same type and adjacent or overlapping. Make one			 * lock yielding from the lower start address of both			 * locks to the higher end address.			 */			if (fl->fl_start > caller->fl_start)				fl->fl_start = caller->fl_start;			else				caller->fl_start = fl->fl_start;			if (fl->fl_end < caller->fl_end)				fl->fl_end = caller->fl_end;			else				caller->fl_end = fl->fl_end;			if (added) {				locks_delete_lock(before, 0);				continue;			}			caller = fl;			added = 1;		}		else {			/* Processing for different lock types is a bit			 * more complex.			 */			if (fl->fl_end < caller->fl_start)				goto next_lock;			if (fl->fl_start > caller->fl_end)				break;			if (caller->fl_type == F_UNLCK)				added = 1;			if (fl->fl_start < caller->fl_start)				left = fl;			/* If the next lock in the list has a higher end			 * address than the new one, insert the new one here.			 */			if (fl->fl_end > caller->fl_end) {				right = fl;				break;			}			if (fl->fl_start >= caller->fl_start) {				/* The new lock completely replaces an old				 * one (This may happen several times).				 */				if (added) {					locks_delete_lock(before, 0);					continue;				}				/* Replace the old lock with the new one.				 * Wake up anybody waiting for the old one,				 * as the change in lock type might satisfy				 * their needs.				 */				locks_wake_up_blocks(fl, 0);				fl->fl_start = caller->fl_start;				fl->fl_end = caller->fl_end;				fl->fl_type = caller->fl_type;				caller = fl;				added = 1;			}		}		/* Go on to next lock.		 */	next_lock:		before = &fl->fl_next;	}	error = 0;	if (!added) {		if (caller->fl_type == F_UNLCK)			goto out;		locks_init_lock(new_fl, caller);		locks_insert_lock(before, new_fl);		new_fl = NULL;	}	if (right) {		if (left == right) {			/* The new lock breaks the old one in two pieces,			 * so we have to use the second new lock (in this			 * case, even F_UNLCK may fail!).			 */			left = locks_init_lock(new_fl2, right);			locks_insert_lock(before, left);			new_fl2 = NULL;		}		right->fl_start = caller->fl_end + 1;		locks_wake_up_blocks(right, 0);	}	if (left) {		left->fl_end = caller->fl_start - 1;		locks_wake_up_blocks(left, 0);	}out:	/*	 * Free any unused locks.  (They haven't	 * ever been used, so we use kfree().)	 */	if (new_fl)		kfree(new_fl);	if (new_fl2)		kfree(new_fl2);	return error;}/* * Allocate an empty lock structure. We can use GFP_KERNEL now that * all allocations are done in advance. */static struct file_lock *locks_empty_lock(void){	return ((struct file_lock *) kmalloc(sizeof(struct file_lock),						GFP_KERNEL));}/* * Initialize a new lock from an existing file_lock structure. */static struct file_lock *locks_init_lock(struct file_lock *new,					 struct file_lock *fl){	if (new) {		memset(new, 0, sizeof(*new));		new->fl_owner = fl->fl_owner;		new->fl_file = fl->fl_file;		new->fl_flags = fl->fl_flags;		new->fl_type = fl->fl_type;		new->fl_start = fl->fl_start;		new->fl_end = fl->fl_end;	}	return new;}/* Insert file lock fl into an inode's lock list at the position indicated * by pos. At the same time add the lock to the global file lock list. */static void locks_insert_lock(struct file_lock **pos, struct file_lock *fl){	fl->fl_nextlink = file_lock_table;	fl->fl_prevlink = NULL;	if (file_lock_table != NULL)		file_lock_table->fl_prevlink = fl;	file_lock_table = fl;	fl->fl_next = *pos;	/* insert into file's list */	*pos = fl;	return;}/* Delete a lock and free it. * First remove our lock from the active lock lists. Then call * locks_wake_up_blocks() to wake up processes that are blocked * waiting for this lock. Finally free the lock structure. */static void locks_delete_lock(struct file_lock **thisfl_p, unsigned int wait){	struct file_lock *thisfl;	struct file_lock *prevfl;	struct file_lock *nextfl;		thisfl = *thisfl_p;	*thisfl_p = thisfl->fl_next;	prevfl = thisfl->fl_prevlink;	nextfl = thisfl->fl_nextlink;	if (nextfl != NULL)		nextfl->fl_prevlink = prevfl;	if (prevfl != NULL)		prevfl->fl_nextlink = nextfl;	else		file_lock_table = nextfl;		locks_wake_up_blocks(thisfl, wait);	locks_free_lock(thisfl);	return;}static char *lock_get_status(struct file_lock *fl, int id, char *pfx){	static char temp[129];	char *p = temp;	struct inode *inode;	inode = fl->fl_file->f_inode;	p += sprintf(p, "%d:%s ", id, pfx);	if (fl->fl_flags & FL_POSIX) {		p += sprintf(p, "%6s %s ",			     (fl->fl_flags & FL_BROKEN) ? "BROKEN" :			     (fl->fl_flags & FL_ACCESS) ? "ACCESS" : "POSIX ",			     (IS_MANDLOCK(inode) &&			      (inode->i_mode & (S_IXGRP | S_ISGID)) == S_ISGID) ?			     "MANDATORY" : "ADVISORY ");	}	else {		p += sprintf(p, "FLOCK  ADVISORY  ");	}	p += sprintf(p, "%s ", (fl->fl_type == F_RDLCK) ? "READ " : "WRITE");	p += sprintf(p, "%d %s:%ld %ld %ld ",		     fl->fl_owner ? fl->fl_owner->pid : 0,		     kdevname(inode->i_dev), inode->i_ino, fl->fl_start,		     fl->fl_end);	sprintf(p, "%08lx %08lx %08lx %08lx %08lx\n",		(long)fl, (long)fl->fl_prevlink, (long)fl->fl_nextlink,		(long)fl->fl_next, (long)fl->fl_nextblock);	return (temp);}static inline int copy_lock_status(char *p, char **q, off_t pos, int len,				   off_t offset, int length){	int i;	i = pos - offset;	if (i > 0) {		if (i >= length) {			i = len + length - i;			memcpy(*q, p, i);			*q += i;			return (0);		}		if (i < len) {			p += len - i;		}		else			i = len;		memcpy(*q, p, i);		*q += i;	}		return (1);}int get_locks_status(char *buffer, char **start, off_t offset, int length){	struct file_lock *fl;	struct file_lock *bfl;	char *p;	char *q = buffer;	int i;	int len;	off_t pos = 0;	for (fl = file_lock_table, i = 1; fl != NULL; fl = fl->fl_nextlink, i++) {		p = lock_get_status(fl, i, "");		len = strlen(p);		pos += len;		if (!copy_lock_status(p, &q, pos, len, offset, length))			goto done;		if ((bfl = fl->fl_nextblock) == NULL)			continue;		do {			p = lock_get_status(bfl, i, " ->");			len = strlen(p);			pos += len;			if (!copy_lock_status(p, &q, pos, len, offset, length))				goto done;		} while ((bfl = bfl->fl_nextblock) != fl);	}done:	if (q != buffer)		*start = buffer;	return (q - buffer);}

⌨️ 快捷键说明

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