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

📄 posix.c

📁 samba-3.0.22.tar.gz 编译smb服务器的源码
💻 C
📖 第 1 页 / 共 3 页
字号:
				DEBUG(10,("truncate low case: start=%.0f,size=%.0f\n",								(double)l_curr->start, (double)l_curr->size ));				l_curr = l_curr->next;					} else if ( (l_curr->start < lock->start) &&						(l_curr->start + l_curr->size > lock->start + lock->size) ) {				/*				 * Worst case scenario. Unlock request completely overlaps an existing				 * lock range. Split the request into two, push the new (upper) request				 * into the dlink list, and continue with the entry after ul_new (as we				 * know that ul_new will not overlap with this lock).				 *//*********************************************        +---------------------------+        |        l_curr             |        +---------------------------+                +---------+                | lock    |                +---------+BECOMES.....        +-------+         +---------+        | l_curr|         | l_new   |        +-------+         +---------+**********************************************/				struct lock_list *l_new = TALLOC_P(ctx, struct lock_list);				if(l_new == NULL) {					DEBUG(0,("posix_lock_list: talloc fail.\n"));					return NULL; /* The talloc_destroy takes care of cleanup. */				}				ZERO_STRUCTP(l_new);				l_new->start = lock->start + lock->size;				l_new->size = l_curr->start + l_curr->size - l_new->start;				/* Truncate the l_curr. */				l_curr->size = lock->start - l_curr->start;				DEBUG(10,("split case: curr: start=%.0f,size=%.0f \new: start=%.0f,size=%.0f\n", (double)l_curr->start, (double)l_curr->size,								(double)l_new->start, (double)l_new->size ));				/*				 * Add into the dlink list after the l_curr point - NOT at lhead. 				 * Note we can't use DLINK_ADD here as this inserts at the head of the given list.				 */				l_new->prev = l_curr;				l_new->next = l_curr->next;				l_curr->next = l_new;				/* And move after the link we added. */				l_curr = l_new->next;			} else {				/*				 * This logic case should never happen. Ensure this is the				 * case by forcing an abort.... Remove in production.				 */				pstring msg;				slprintf(msg, sizeof(msg)-1, "logic flaw in cases: l_curr: start = %.0f, size = %.0f : \lock: start = %.0f, size = %.0f\n", (double)l_curr->start, (double)l_curr->size, (double)lock->start, (double)lock->size );				smb_panic(msg);			}		} /* end for ( l_curr = lhead; l_curr;) */	} /* end for (i=0; i<num_locks && ul_head; i++) */	SAFE_FREE(dbuf.dptr);		return lhead;}/**************************************************************************** POSIX function to acquire a lock. Returns True if the lock could be granted, False if not.****************************************************************************/BOOL set_posix_lock(files_struct *fsp, SMB_BIG_UINT u_offset, SMB_BIG_UINT u_count, enum brl_type lock_type){	SMB_OFF_T offset;	SMB_OFF_T count;	BOOL ret = True;	size_t entry_num = 0;	size_t lock_count;	TALLOC_CTX *l_ctx = NULL;	struct lock_list *llist = NULL;	struct lock_list *ll = NULL;	int posix_lock_type = map_posix_lock_type(fsp,lock_type);	DEBUG(5,("set_posix_lock: File %s, offset = %.0f, count = %.0f, type = %s\n",			fsp->fsp_name, (double)u_offset, (double)u_count, posix_lock_type_name(lock_type) ));	/*	 * If the requested lock won't fit in the POSIX range, we will	 * pretend it was successful.	 */	if(!posix_lock_in_range(&offset, &count, u_offset, u_count))		return True;	/*	 * Windows is very strange. It allows read locks to be overlayed	 * (even over a write lock), but leaves the write lock in force until the first	 * unlock. It also reference counts the locks. This means the following sequence :	 *	 * process1                                      process2	 * ------------------------------------------------------------------------	 * WRITE LOCK : start = 2, len = 10	 *                                            READ LOCK: start =0, len = 10 - FAIL	 * READ LOCK : start = 0, len = 14 	 *                                            READ LOCK: start =0, len = 10 - FAIL	 * UNLOCK : start = 2, len = 10	 *                                            READ LOCK: start =0, len = 10 - OK	 *	 * Under POSIX, the same sequence in steps 1 and 2 would not be reference counted, but	 * would leave a single read lock over the 0-14 region. In order to	 * re-create Windows semantics mapped to POSIX locks, we create multiple TDB	 * entries, one for each overlayed lock request. We are guarenteed by the brlock	 * semantics that if a write lock is added, then it will be first in the array.	 */		if ((l_ctx = talloc_init("set_posix_lock")) == NULL) {		DEBUG(0,("set_posix_lock: unable to init talloc context.\n"));		return True; /* Not a fatal error. */	}	if ((ll = TALLOC_P(l_ctx, struct lock_list)) == NULL) {		DEBUG(0,("set_posix_lock: unable to talloc unlock list.\n"));		talloc_destroy(l_ctx);		return True; /* Not a fatal error. */	}	/*	 * Create the initial list entry containing the	 * lock we want to add.	 */	ZERO_STRUCTP(ll);	ll->start = offset;	ll->size = count;	DLIST_ADD(llist, ll);	/*	 * The following call calculates if there are any	 * overlapping locks held by this process on	 * fd's open on the same file and splits this list	 * into a list of lock ranges that do not overlap with existing	 * POSIX locks.	 */	llist = posix_lock_list(l_ctx, llist, fsp);	/*	 * Now we have the list of ranges to lock it is safe to add the	 * entry into the POSIX lock tdb. We take note of the entry we	 * added here in case we have to remove it on POSIX lock fail.	 */	if (!add_posix_lock_entry(fsp,offset,count,posix_lock_type,&entry_num)) {		DEBUG(0,("set_posix_lock: Unable to create posix lock entry !\n"));		talloc_destroy(l_ctx);		return False;	}	/*	 * Add the POSIX locks on the list of ranges returned.	 * As the lock is supposed to be added atomically, we need to	 * back out all the locks if any one of these calls fail.	 */	for (lock_count = 0, ll = llist; ll; ll = ll->next, lock_count++) {		offset = ll->start;		count = ll->size;		DEBUG(5,("set_posix_lock: Real lock: Type = %s: offset = %.0f, count = %.0f\n",			posix_lock_type_name(posix_lock_type), (double)offset, (double)count ));		if (!posix_fcntl_lock(fsp,SMB_F_SETLK,offset,count,posix_lock_type)) {			DEBUG(5,("set_posix_lock: Lock fail !: Type = %s: offset = %.0f, count = %.0f. Errno = %s\n",				posix_lock_type_name(posix_lock_type), (double)offset, (double)count, strerror(errno) ));			ret = False;			break;		}	}	if (!ret) {		/*		 * Back out all the POSIX locks we have on fail.		 */		for (ll = llist; lock_count; ll = ll->next, lock_count--) {			offset = ll->start;			count = ll->size;			DEBUG(5,("set_posix_lock: Backing out locks: Type = %s: offset = %.0f, count = %.0f\n",				posix_lock_type_name(posix_lock_type), (double)offset, (double)count ));			posix_fcntl_lock(fsp,SMB_F_SETLK,offset,count,F_UNLCK);		}		/*		 * Remove the tdb entry for this lock.		 */		delete_posix_lock_entry_by_index(fsp,entry_num);	}	talloc_destroy(l_ctx);	return ret;}/**************************************************************************** POSIX function to release a lock. Returns True if the lock could be released, False if not.****************************************************************************/BOOL release_posix_lock(files_struct *fsp, SMB_BIG_UINT u_offset, SMB_BIG_UINT u_count){	SMB_OFF_T offset;	SMB_OFF_T count;	BOOL ret = True;	TALLOC_CTX *ul_ctx = NULL;	struct lock_list *ulist = NULL;	struct lock_list *ul = NULL;	struct posix_lock deleted_lock;	int num_overlapped_entries;	DEBUG(5,("release_posix_lock: File %s, offset = %.0f, count = %.0f\n",		fsp->fsp_name, (double)u_offset, (double)u_count ));	/*	 * If the requested lock won't fit in the POSIX range, we will	 * pretend it was successful.	 */	if(!posix_lock_in_range(&offset, &count, u_offset, u_count))		return True;	/*	 * We treat this as one unlock request for POSIX accounting purposes even	 * if it may later be split into multiple smaller POSIX unlock ranges.	 * num_overlapped_entries is the number of existing locks that have any	 * overlap with this unlock request.	 */ 	num_overlapped_entries = delete_posix_lock_entry(fsp, offset, count, &deleted_lock);	if (num_overlapped_entries == -1) {		smb_panic("release_posix_lock: unable find entry to delete !\n");	}	/*	 * If num_overlapped_entries is > 0, and the lock_type we just deleted from the tdb was	 * a POSIX write lock, then before doing the unlock we need to downgrade	 * the POSIX lock to a read lock. This allows any overlapping read locks	 * to be atomically maintained.	 */	if (num_overlapped_entries > 0 && deleted_lock.lock_type == F_WRLCK) {		if (!posix_fcntl_lock(fsp,SMB_F_SETLK,offset,count,F_RDLCK)) {			DEBUG(0,("release_posix_lock: downgrade of lock failed with error %s !\n", strerror(errno) ));			return False;		}	}	if ((ul_ctx = talloc_init("release_posix_lock")) == NULL) {		DEBUG(0,("release_posix_lock: unable to init talloc context.\n"));		return True; /* Not a fatal error. */	}	if ((ul = TALLOC_P(ul_ctx, struct lock_list)) == NULL) {		DEBUG(0,("release_posix_lock: unable to talloc unlock list.\n"));		talloc_destroy(ul_ctx);		return True; /* Not a fatal error. */	}	/*	 * Create the initial list entry containing the	 * lock we want to remove.	 */	ZERO_STRUCTP(ul);	ul->start = offset;	ul->size = count;	DLIST_ADD(ulist, ul);	/*	 * The following call calculates if there are any	 * overlapping locks held by this process on	 * fd's open on the same file and creates a	 * list of unlock ranges that will allow	 * POSIX lock ranges to remain on the file whilst the	 * unlocks are performed.	 */	ulist = posix_lock_list(ul_ctx, ulist, fsp);	/*	 * Release the POSIX locks on the list of ranges returned.	 */	for(; ulist; ulist = ulist->next) {		offset = ulist->start;		count = ulist->size;		DEBUG(5,("release_posix_lock: Real unlock: offset = %.0f, count = %.0f\n",			(double)offset, (double)count ));		if (!posix_fcntl_lock(fsp,SMB_F_SETLK,offset,count,F_UNLCK))			ret = False;	}	talloc_destroy(ul_ctx);	return ret;}/**************************************************************************** Remove all lock entries for a specific dev/inode pair from the tdb.****************************************************************************/static void delete_posix_lock_entries(files_struct *fsp){	TDB_DATA kbuf = locking_key_fsp(fsp);	if (tdb_delete(posix_lock_tdb, kbuf) == -1)		DEBUG(0,("delete_close_entries: tdb_delete fail !\n"));}/**************************************************************************** Debug function.****************************************************************************/static void dump_entry(struct posix_lock *pl){	DEBUG(10,("entry: start=%.0f, size=%.0f, type=%d, fd=%i\n",		(double)pl->start, (double)pl->size, (int)pl->lock_type, pl->fd ));}/**************************************************************************** Remove any locks on this fd. Called from file_close().****************************************************************************/void posix_locking_close_file(files_struct *fsp){	struct posix_lock *entries = NULL;	size_t count, i;	/*	 * Optimization for the common case where we are the only	 * opener of a file. If all fd entries are our own, we don't	 * need to explicitly release all the locks via the POSIX functions,	 * we can just remove all the entries in the tdb and allow the	 * close to remove the real locks.	 */	count = get_posix_lock_entries(fsp, &entries);	if (count == 0) {		DEBUG(10,("posix_locking_close_file: file %s has no outstanding locks.\n", fsp->fsp_name ));		return;	}	for (i = 0; i < count; i++) {		if (entries[i].fd != fsp->fh->fd )			break;		dump_entry(&entries[i]);	}	if (i == count) {		/* All locks are ours. */		DEBUG(10,("posix_locking_close_file: file %s has %u outstanding locks, but all on one fd.\n", 			fsp->fsp_name, (unsigned int)count ));		SAFE_FREE(entries);		delete_posix_lock_entries(fsp);		return;	}	/*	 * Difficult case. We need to delete all our locks, whilst leaving	 * all other POSIX locks in place.	 */	for (i = 0; i < count; i++) {		struct posix_lock *pl = &entries[i];		if (pl->fd == fsp->fh->fd)			release_posix_lock(fsp, (SMB_BIG_UINT)pl->start, (SMB_BIG_UINT)pl->size );	}	SAFE_FREE(entries);}/******************************************************************* Create the in-memory POSIX lock databases.********************************************************************/BOOL posix_locking_init(int read_only){	if (posix_lock_tdb && posix_pending_close_tdb)		return True;		if (!posix_lock_tdb)		posix_lock_tdb = tdb_open_log(NULL, 0, TDB_INTERNAL,					  read_only?O_RDONLY:(O_RDWR|O_CREAT), 0644);	if (!posix_lock_tdb) {		DEBUG(0,("Failed to open POSIX byte range locking database.\n"));		return False;	}	if (!posix_pending_close_tdb)		posix_pending_close_tdb = tdb_open_log(NULL, 0, TDB_INTERNAL,						   read_only?O_RDONLY:(O_RDWR|O_CREAT), 0644);	if (!posix_pending_close_tdb) {		DEBUG(0,("Failed to open POSIX pending close database.\n"));		return False;	}	return True;}/******************************************************************* Delete the in-memory POSIX lock databases.********************************************************************/BOOL posix_locking_end(void){    if (posix_lock_tdb && tdb_close(posix_lock_tdb) != 0)		return False;    if (posix_pending_close_tdb && tdb_close(posix_pending_close_tdb) != 0)		return False;	return True;}

⌨️ 快捷键说明

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