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

📄 brlock_tdb.c

📁 samba最新软件
💻 C
📖 第 1 页 / 共 2 页
字号:
	} else {		dbuf.dptr = (uint8_t *)locks;	}	locks[count] = lock;	dbuf.dsize += sizeof(lock);	status = rec->store(rec, dbuf, TDB_REPLACE);	if (!NT_STATUS_IS_OK(status)) {		goto fail;	}	talloc_free(rec);	/* the caller needs to know if the real lock was granted. If	   we have reached here then it must be a pending lock that	   was granted, so tell them the lock failed */	if (lock_type >= PENDING_READ_LOCK) {		return NT_STATUS_LOCK_NOT_GRANTED;	}	return NT_STATUS_OK; fail:	talloc_free(rec);	return status;}/*  we are removing a lock that might be holding up a pending lock. Scan for pending  locks that cover this range and if we find any then notify the server that it should  retry the lock*/static void brl_tdb_notify_unlock(struct brl_context *brl,			      struct lock_struct *locks, int count, 			      struct lock_struct *removed_lock){	int i, last_notice;	/* the last_notice logic is to prevent stampeding on a lock	   range. It prevents us sending hundreds of notifies on the	   same range of bytes. It doesn't prevent all possible	   stampedes, but it does prevent the most common problem */	last_notice = -1;	for (i=0;i<count;i++) {		if (locks[i].lock_type >= PENDING_READ_LOCK &&		    brl_tdb_overlap(&locks[i], removed_lock)) {			if (last_notice != -1 && brl_tdb_overlap(&locks[i], &locks[last_notice])) {				continue;			}			if (locks[i].lock_type == PENDING_WRITE_LOCK) {				last_notice = i;			}			messaging_send_ptr(brl->messaging_ctx, locks[i].context.server, 					   MSG_BRL_RETRY, locks[i].notify_ptr);		}	}}/*  send notifications for all pending locks - the file is being closed by this  user*/static void brl_tdb_notify_all(struct brl_context *brl,			   struct lock_struct *locks, int count){	int i;	for (i=0;i<count;i++) {		if (locks->lock_type >= PENDING_READ_LOCK) {			brl_tdb_notify_unlock(brl, locks, count, &locks[i]);		}	}}/* Unlock a range of bytes.*/static NTSTATUS brl_tdb_unlock(struct brl_context *brl,			   struct brl_handle *brlh, 			   uint16_t smbpid,			   uint64_t start, uint64_t size){	TDB_DATA kbuf, dbuf;	int count, i;	struct lock_struct *locks, *lock;	struct lock_context context;	NTSTATUS status;	struct db_record *rec = NULL;	kbuf.dptr = brlh->key.data;	kbuf.dsize = brlh->key.length;	rec = brl->db->fetch_locked(brl->db, brl, kbuf);	if (rec == NULL) {		return NT_STATUS_INTERNAL_DB_CORRUPTION;	}	if (!rec->value.dptr) {		talloc_free(rec);		return NT_STATUS_RANGE_NOT_LOCKED;	}	dbuf = rec->value;	context.smbpid = smbpid;	context.server = brl->server;	context.ctx = brl;	/* there are existing locks - find a match */	locks = (struct lock_struct *)dbuf.dptr;	count = dbuf.dsize / sizeof(*locks);	for (i=0; i<count; i++) {		lock = &locks[i];		if (brl_tdb_same_context(&lock->context, &context) &&		    lock->ntvfs == brlh->ntvfs &&		    lock->start == start &&		    lock->size == size &&		    lock->lock_type == WRITE_LOCK) {			break;		}	}	if (i < count) goto found;	for (i=0; i<count; i++) {		lock = &locks[i];		if (brl_tdb_same_context(&lock->context, &context) &&		    lock->ntvfs == brlh->ntvfs &&		    lock->start == start &&		    lock->size == size &&		    lock->lock_type < PENDING_READ_LOCK) {			break;		}	}found:	if (i == count) {		status = NT_STATUS_RANGE_NOT_LOCKED;	} else if (count == 1) {		status = rec->delete_rec(rec);	} else {		struct lock_struct removed_lock = *lock;		if (i < count-1) {			memmove(&locks[i], &locks[i+1], 				sizeof(*locks)*((count-1) - i));		}		count--;				/* send notifications for any relevant pending locks */		brl_tdb_notify_unlock(brl, locks, count, &removed_lock);				dbuf.dsize = count * sizeof(*locks);				status = rec->store(rec, dbuf, TDB_REPLACE);	} 	talloc_free(rec);	return status;}/*  remove a pending lock. This is called when the caller has either  given up trying to establish a lock or when they have succeeded in  getting it. In either case they no longer need to be notified.*/static NTSTATUS brl_tdb_remove_pending(struct brl_context *brl,				   struct brl_handle *brlh, 				   void *notify_ptr){	TDB_DATA kbuf, dbuf;	int count, i;	struct lock_struct *locks;	NTSTATUS status;	struct db_record *rec = NULL;	kbuf.dptr = brlh->key.data;	kbuf.dsize = brlh->key.length;	rec = brl->db->fetch_locked(brl->db, brl, kbuf);	if (rec == NULL) {		return NT_STATUS_INTERNAL_DB_CORRUPTION;	}	dbuf = rec->value;	/* there are existing locks - find a match */	locks = (struct lock_struct *)dbuf.dptr;	count = dbuf.dsize / sizeof(*locks);	status = NT_STATUS_RANGE_NOT_LOCKED;	for (i=0; i<count; i++) {		struct lock_struct *lock = &locks[i];				if (lock->lock_type >= PENDING_READ_LOCK &&		    lock->notify_ptr == notify_ptr &&		    cluster_id_equal(&lock->context.server, &brl->server)) {			/* found it - delete it */			if (count == 1) {				status = rec->delete_rec(rec);			} else {				if (i < count-1) {					memmove(&locks[i], &locks[i+1], 						sizeof(*locks)*((count-1) - i));				}				count--;				dbuf.dsize = count * sizeof(*locks);				status = rec->store(rec, dbuf, TDB_REPLACE);			}						break;		}	}	talloc_free(rec);	return status;}/*  Test if we are allowed to perform IO on a region of an open file*/static NTSTATUS brl_tdb_locktest(struct brl_context *brl,			     struct brl_handle *brlh,			     uint16_t smbpid, 			     uint64_t start, uint64_t size, 			     enum brl_type lock_type){	TDB_DATA kbuf, dbuf;	int count, i;	struct lock_struct lock, *locks;	NTSTATUS status;	kbuf.dptr = brlh->key.data;	kbuf.dsize = brlh->key.length;	if (brl->db->fetch(brl->db, brl, kbuf, &dbuf) != 0) {		return NT_STATUS_OK;	}	lock.context.smbpid = smbpid;	lock.context.server = brl->server;	lock.context.ctx = brl;	lock.ntvfs = brlh->ntvfs;	lock.start = start;	lock.size = size;	lock.lock_type = lock_type;	/* there are existing locks - make sure they don't conflict */	locks = (struct lock_struct *)dbuf.dptr;	count = dbuf.dsize / sizeof(*locks);	status = NT_STATUS_OK;	for (i=0; i<count; i++) {		if (brl_tdb_conflict_other(&locks[i], &lock)) {			status = NT_STATUS_FILE_LOCK_CONFLICT;			break;		}	}	talloc_free(dbuf.dptr);	return status;}/* Remove any locks associated with a open file.*/static NTSTATUS brl_tdb_close(struct brl_context *brl,			  struct brl_handle *brlh){	TDB_DATA kbuf, dbuf;	int count, i, dcount=0;	struct lock_struct *locks;	NTSTATUS status;	struct db_record *rec = NULL;	kbuf.dptr = brlh->key.data;	kbuf.dsize = brlh->key.length;	rec = brl->db->fetch_locked(brl->db, brl, kbuf);	if (rec == NULL) {		return NT_STATUS_INTERNAL_DB_CORRUPTION;	}	dbuf = rec->value;	if (!dbuf.dptr) {		talloc_free(rec);		return NT_STATUS_OK;	}	/* there are existing locks - remove any for this fnum */	locks = (struct lock_struct *)dbuf.dptr;	count = dbuf.dsize / sizeof(*locks);	for (i=0; i<count; i++) {		struct lock_struct *lock = &locks[i];		if (lock->context.ctx == brl &&		    cluster_id_equal(&lock->context.server, &brl->server) &&		    lock->ntvfs == brlh->ntvfs) {			/* found it - delete it */			if (count > 1 && i < count-1) {				memmove(&locks[i], &locks[i+1], 					sizeof(*locks)*((count-1) - i));			}			count--;			i--;			dcount++;		}	}	status = NT_STATUS_OK;	if (count == 0) {		status = rec->delete_rec(rec);	} else if (dcount != 0) {		/* tell all pending lock holders for this file that		   they have a chance now. This is a bit indiscriminant,		   but works OK */		brl_tdb_notify_all(brl, locks, count);		dbuf.dsize = count * sizeof(*locks);		status = rec->store(rec, dbuf, TDB_REPLACE);	}	talloc_free(rec);	return status;}static const struct brlock_ops brlock_tdb_ops = {	.brl_init           = brl_tdb_init,	.brl_create_handle  = brl_tdb_create_handle,	.brl_lock           = brl_tdb_lock,	.brl_unlock         = brl_tdb_unlock,	.brl_remove_pending = brl_tdb_remove_pending,	.brl_locktest       = brl_tdb_locktest,	.brl_close          = brl_tdb_close};void brl_tdb_init_ops(void){	brl_set_ops(&brlock_tdb_ops);}

⌨️ 快捷键说明

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