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

📄 brlock.c

📁 samba-3.0.22.tar.gz 编译smb服务器的源码
💻 C
📖 第 1 页 / 共 2 页
字号:
/*    Unix SMB/CIFS implementation.   byte range locking code   Updated to handle range splits/merges.   Copyright (C) Andrew Tridgell 1992-2000   Copyright (C) Jeremy Allison 1992-2000      This program is free software; you can redistribute it and/or modify   it under the terms of the GNU General Public License as published by   the Free Software Foundation; either version 2 of the License, or   (at your option) any later version.      This program is distributed in the hope that it will be useful,   but WITHOUT ANY WARRANTY; without even the implied warranty of   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the   GNU General Public License for more details.      You should have received a copy of the GNU General Public License   along with this program; if not, write to the Free Software   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.*//* This module implements a tdb based byte range locking service,   replacing the fcntl() based byte range locking previously   used. This allows us to provide the same semantics as NT */#include "includes.h"#undef DBGC_CLASS#define DBGC_CLASS DBGC_LOCKING#define ZERO_ZERO 0/* This contains elements that differentiate locks. The smbpid is a   client supplied pid, and is essentially the locking context for   this client */struct lock_context {	uint16 smbpid;	uint16 tid;	struct process_id pid;};/* The data in brlock records is an unsorted linear array of these   records.  It is unnecessary to store the count as tdb provides the   size of the record */struct lock_struct {	struct lock_context context;	br_off start;	br_off size;	int fnum;	enum brl_type lock_type;};/* The key used in the brlock database. */struct lock_key {	SMB_DEV_T device;	SMB_INO_T inode;};/* The open brlock.tdb database. */static TDB_CONTEXT *tdb;/**************************************************************************** Create a locking key - ensuring zero filled for pad purposes.****************************************************************************/static TDB_DATA locking_key(SMB_DEV_T dev, SMB_INO_T inode){        static struct lock_key key;        TDB_DATA kbuf;        memset(&key, '\0', sizeof(key));        key.device = dev;        key.inode = inode;        kbuf.dptr = (char *)&key;        kbuf.dsize = sizeof(key);        return kbuf;}/**************************************************************************** See if two locking contexts are equal.****************************************************************************/static BOOL brl_same_context(struct lock_context *ctx1, 			     struct lock_context *ctx2){	return (procid_equal(&ctx1->pid, &ctx2->pid) &&		(ctx1->smbpid == ctx2->smbpid) &&		(ctx1->tid == ctx2->tid));}/**************************************************************************** See if lck1 and lck2 overlap.****************************************************************************/static BOOL brl_overlap(struct lock_struct *lck1,                        struct lock_struct *lck2){	/* this extra check is not redundent - it copes with locks	   that go beyond the end of 64 bit file space */	if (lck1->size != 0 &&	    lck1->start == lck2->start &&	    lck1->size == lck2->size) {		return True;	}	if (lck1->start >= (lck2->start+lck2->size) ||	    lck2->start >= (lck1->start+lck1->size)) {		return False;	}	return True;}/**************************************************************************** See if lock2 can be added when lock1 is in place.****************************************************************************/static BOOL brl_conflict(struct lock_struct *lck1, 			 struct lock_struct *lck2){	if (lck1->lock_type == PENDING_LOCK || lck2->lock_type == PENDING_LOCK )		return False;	if (lck1->lock_type == READ_LOCK && lck2->lock_type == READ_LOCK) {		return False;	}	if (brl_same_context(&lck1->context, &lck2->context) &&	    lck2->lock_type == READ_LOCK && lck1->fnum == lck2->fnum) {		return False;	}	return brl_overlap(lck1, lck2);} #if ZERO_ZEROstatic BOOL brl_conflict1(struct lock_struct *lck1, 			 struct lock_struct *lck2){	if (lck1->lock_type == PENDING_LOCK || lck2->lock_type == PENDING_LOCK )		return False;	if (lck1->lock_type == READ_LOCK && lck2->lock_type == READ_LOCK) {		return False;	}	if (brl_same_context(&lck1->context, &lck2->context) &&	    lck2->lock_type == READ_LOCK && lck1->fnum == lck2->fnum) {		return False;	}	if (lck2->start == 0 && lck2->size == 0 && lck1->size != 0) {		return True;	}	if (lck1->start >= (lck2->start + lck2->size) ||	    lck2->start >= (lck1->start + lck1->size)) {		return False;	}	    	return True;} #endif/**************************************************************************** Check to see if this lock conflicts, but ignore our own locks on the same fnum only.****************************************************************************/static BOOL brl_conflict_other(struct lock_struct *lck1, struct lock_struct *lck2){	if (lck1->lock_type == PENDING_LOCK || lck2->lock_type == PENDING_LOCK )		return False;	if (lck1->lock_type == READ_LOCK && lck2->lock_type == READ_LOCK) 		return False;	/*	 * Incoming WRITE locks conflict with existing READ locks even	 * if the context is the same. JRA. See LOCKTEST7 in smbtorture.	 */	if (!(lck2->lock_type == WRITE_LOCK && lck1->lock_type == READ_LOCK)) {		if (brl_same_context(&lck1->context, &lck2->context) &&					lck1->fnum == lck2->fnum)			return False;	}	return brl_overlap(lck1, lck2);} /**************************************************************************** Amazingly enough, w2k3 "remembers" whether the last lock failure is the same as this one and changes its error code. I wonder if any app depends on this ?****************************************************************************/static NTSTATUS brl_lock_failed(struct lock_struct *lock){	static struct lock_struct last_lock_failure;	if (brl_same_context(&lock->context, &last_lock_failure.context) &&			lock->fnum == last_lock_failure.fnum &&			lock->start == last_lock_failure.start &&			lock->size == last_lock_failure.size) {		return NT_STATUS_FILE_LOCK_CONFLICT;	}	last_lock_failure = *lock;	if (lock->start >= 0xEF000000 &&			(lock->start >> 63) == 0) {		/* amazing the little things you learn with a test		   suite. Locks beyond this offset (as a 64 bit		   number!) always generate the conflict error code,		   unless the top bit is set */		return NT_STATUS_FILE_LOCK_CONFLICT;	}	return NT_STATUS_LOCK_NOT_GRANTED;}#if DONT_DO_THIS	/* doing this traversal could kill solaris machines under high load (tridge) */	/* delete any dead locks *//**************************************************************************** Delete a record if it is for a dead process, if check_self is true, then delete any records belonging to this pid also (there shouldn't be any).****************************************************************************/static int delete_fn(TDB_CONTEXT *ttdb, TDB_DATA kbuf, TDB_DATA dbuf, void *state){	struct lock_struct *locks;	int count, i;	BOOL check_self = *(BOOL *)state;	pid_t mypid = sys_getpid();	tdb_chainlock(tdb, kbuf);	locks = (struct lock_struct *)dbuf.dptr;	count = dbuf.dsize / sizeof(*locks);	for (i=0; i<count; i++) {		struct lock_struct *lock = &locks[i];		/* If check_self is true we want to remove our own records. */		if (check_self && (mypid == lock->context.pid)) {			DEBUG(0,("brlock : delete_fn. LOGIC ERROR ! Shutting down and a record for my pid (%u) exists !\n",					(unsigned int)lock->context.pid ));		} else if (process_exists(&lock->context.pid)) {			DEBUG(10,("brlock : delete_fn. pid %u exists.\n", (unsigned int)lock->context.pid ));			continue;		}		DEBUG(10,("brlock : delete_fn. Deleting record for process %u\n",				(unsigned int)lock->context.pid ));		if (count > 1 && i < count-1) {			memmove(&locks[i], &locks[i+1], 				sizeof(*locks)*((count-1) - i));		}		count--;		i--;	}	if (count == 0) {		tdb_delete(tdb, kbuf);	} else if (count < (dbuf.dsize / sizeof(*locks))) {		dbuf.dsize = count * sizeof(*locks);		tdb_store(tdb, kbuf, dbuf, TDB_REPLACE);	}	tdb_chainunlock(tdb, kbuf);	return 0;}#endif/**************************************************************************** Open up the brlock.tdb database.****************************************************************************/void brl_init(int read_only){	if (tdb)		return;	tdb = tdb_open_log(lock_path("brlock.tdb"), 0,  TDB_DEFAULT|(read_only?0x0:TDB_CLEAR_IF_FIRST),		       read_only?O_RDONLY:(O_RDWR|O_CREAT), 0644 );	if (!tdb) {		DEBUG(0,("Failed to open byte range locking database\n"));		return;	}#if DONT_DO_THIS	/* doing this traversal could kill solaris machines under high load (tridge) */	/* delete any dead locks */	if (!read_only) {		BOOL check_self = False;		tdb_traverse(tdb, delete_fn, &check_self);	}#endif}/**************************************************************************** Close down the brlock.tdb database.****************************************************************************/void brl_shutdown(int read_only){	if (!tdb)		return;#if DONT_DO_THIS	/* doing this traversal could kill solaris machines under high load (tridge) */	/* delete any dead locks */	if (!read_only) {		BOOL check_self = True;		tdb_traverse(tdb, delete_fn, &check_self);	}#endif	tdb_close(tdb);}#if ZERO_ZERO/****************************************************************************compare two locks for sorting****************************************************************************/static int lock_compare(struct lock_struct *lck1, 			 struct lock_struct *lck2){	if (lck1->start != lck2->start) return (lck1->start - lck2->start);	if (lck2->size != lck1->size) {		return ((int)lck1->size - (int)lck2->size);	}	return 0;}#endif/**************************************************************************** Lock a range of bytes.****************************************************************************/NTSTATUS brl_lock(SMB_DEV_T dev, SMB_INO_T ino, int fnum,		  uint16 smbpid, struct process_id pid, uint16 tid,		  br_off start, br_off size, 		  enum brl_type lock_type, BOOL *my_lock_ctx){	TDB_DATA kbuf, dbuf;	int count, i;	struct lock_struct lock, *locks;	char *tp;	NTSTATUS status = NT_STATUS_OK;	*my_lock_ctx = False;	kbuf = locking_key(dev,ino);	dbuf.dptr = NULL;#if !ZERO_ZERO	if (start == 0 && size == 0) {		DEBUG(0,("client sent 0/0 lock - please report this\n"));	}#endif

⌨️ 快捷键说明

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