Beispiel #1
0
BOOL brl_locktest(SMB_DEV_T dev, SMB_INO_T ino, int fnum,
		  uint16 smbpid, pid_t pid, uint16 tid,
		  br_off start, br_off size, 
		  enum brl_type lock_type, int check_self)
{
	TDB_DATA kbuf, dbuf;
	int count, i;
	struct lock_struct lock, *locks;

	kbuf = locking_key(dev,ino);

	dbuf.dptr = NULL;

	tdb_chainlock(tdb, kbuf);
	dbuf = tdb_fetch(tdb, kbuf);

	lock.context.smbpid = smbpid;
	lock.context.pid = pid;
	lock.context.tid = tid;
	lock.start = start;
	lock.size = size;
	lock.fnum = fnum;
	lock.lock_type = lock_type;

	if (dbuf.dptr) {
		/* there are existing locks - make sure they don't conflict */
		locks = (struct lock_struct *)dbuf.dptr;
		count = dbuf.dsize / sizeof(*locks);
		for (i=0; i<count; i++) {
			if (check_self) {
				if (brl_conflict(&locks[i], &lock))
					goto fail;
			} else {
				/*
				 * Our own locks don't conflict.
				 */
				if (brl_conflict_other(&locks[i], &lock))
					goto fail;
			}
		}
	}

	/* no conflicts - we could have added it */
	SAFE_FREE(dbuf.dptr);
	tdb_chainunlock(tdb, kbuf);
	return True;

 fail:
	SAFE_FREE(dbuf.dptr);
	tdb_chainunlock(tdb, kbuf);
	return False;
}
Beispiel #2
0
static BOOL message_recv(int *msg_type, pid_t *src, void **buf, size_t *len)
{
	TDB_DATA kbuf;
	TDB_DATA dbuf;
	struct message_rec rec;

	kbuf = message_key_pid(sys_getpid());

	tdb_chainlock(tdb, kbuf);
	
	dbuf = tdb_fetch(tdb, kbuf);
	if (dbuf.dptr == NULL || dbuf.dsize == 0) goto failed;

	memcpy(&rec, dbuf.dptr, sizeof(rec));

	if (rec.msg_version != MESSAGE_VERSION) {
		DEBUG(0,("message version %d received (expected %d)\n", rec.msg_version, MESSAGE_VERSION));
		goto failed;
	}

	if (rec.len > 0) {
		(*buf) = (void *)malloc(rec.len);
		if (!(*buf)) goto failed;

		memcpy(*buf, dbuf.dptr+sizeof(rec), rec.len);
	} else {
		*buf = NULL;
	}

	*len = rec.len;
	*msg_type = rec.msg_type;
	*src = rec.src;

	if (dbuf.dsize - (sizeof(rec)+rec.len) > 0)
		memmove(dbuf.dptr, dbuf.dptr+sizeof(rec)+rec.len, dbuf.dsize - (sizeof(rec)+rec.len));
	dbuf.dsize -= sizeof(rec)+rec.len;

	if (dbuf.dsize == 0)
		tdb_delete(tdb, kbuf);
	else
		tdb_store(tdb, kbuf, dbuf, TDB_REPLACE);

	SAFE_FREE(dbuf.dptr);
	tdb_chainunlock(tdb, kbuf);
	return True;

 failed:
	tdb_chainunlock(tdb, kbuf);
	return False;
}
Beispiel #3
0
static BOOL retrieve_all_messages(char **msgs_buf, size_t *total_len)
{
	TDB_DATA kbuf;
	TDB_DATA dbuf;
	TDB_DATA null_dbuf;

	ZERO_STRUCT(null_dbuf);

	*msgs_buf = NULL;
	*total_len = 0;

	kbuf = message_key_pid(pid_to_procid(sys_getpid()));

	if (tdb_chainlock(tdb, kbuf) == -1)
		return False;

	dbuf = tdb_fetch(tdb, kbuf);
	/*
	 * Replace with an empty record to keep the allocated
	 * space in the tdb.
	 */
	tdb_store(tdb, kbuf, null_dbuf, TDB_REPLACE);
	tdb_chainunlock(tdb, kbuf);

	if (dbuf.dptr == NULL || dbuf.dsize == 0) {
		SAFE_FREE(dbuf.dptr);
		return False;
	}

	*msgs_buf = dbuf.dptr;
	*total_len = dbuf.dsize;

	return True;
}
Beispiel #4
0
static int share_mode_lock_destructor(void *p)
{
	struct share_mode_lock *lck =
		talloc_get_type_abort(p, struct share_mode_lock);
	TDB_DATA key = locking_key(lck->dev, lck->ino);
	TDB_DATA data;

	if (!lck->modified) {
		goto done;
	}

	data = unparse_share_modes(lck);

	if (data.dptr == NULL) {
		if (!lck->fresh) {
			/* There has been an entry before, delete it */
			if (tdb_delete(tdb, key) == -1) {
				smb_panic("Could not delete share entry\n");
			}
		}
		goto done;
	}

	if (tdb_store(tdb, key, data, TDB_REPLACE) == -1) {
		smb_panic("Could not store share mode entry\n");
	}

 done:
	tdb_chainunlock(tdb, key);

	return 0;
}
Beispiel #5
0
/*
  unlock a record in the ltdb, given a key
 */
int ctdb_ltdb_unlock(struct ctdb_db_context *ctdb_db, TDB_DATA key)
{
	int ret = tdb_chainunlock(ctdb_db->ltdb->tdb, key);
	if (ret != 0) {
		DEBUG(DEBUG_ERR,("tdb_chainunlock failed\n"));
	}
	return ret;
}
Beispiel #6
0
/*
  unlock a record in the ltdb, given a key
 */
int ctdb_ltdb_unlock(struct ctdb_db_context *ctdb_db, TDB_DATA key)
{
	int ret = tdb_chainunlock(ctdb_db->ltdb->tdb, key);
	if (ret != 0) {
 		DEBUG(DEBUG_ERR,("tdb_chainunlock failed on db %s [%s]\n", ctdb_db->db_name, tdb_errorstr(ctdb_db->ltdb->tdb)));
	}
	return ret;
}
Beispiel #7
0
static int db_tdb_record_destr(struct db_record* data)
{
	struct db_tdb_ctx *ctx =
		talloc_get_type_abort(data->private_data, struct db_tdb_ctx);

	db_tdb_log_key("Unlocking", data->key);
	tdb_chainunlock(ctx->wtdb->tdb, data->key);
	return 0;
}
Beispiel #8
0
/* ----------------------- */
static cnid_t get_cnid(struct _cnid_tdb_private *db)
{
    TDB_DATA rootinfo_key, data;
    cnid_t hint,id;
    
    memset(&rootinfo_key, 0, sizeof(rootinfo_key));
    memset(&data, 0, sizeof(data));
    rootinfo_key.dptr = ROOTINFO_KEY;
    rootinfo_key.dsize = ROOTINFO_KEYLEN;
    
    tdb_chainlock(db->tdb_didname, rootinfo_key);  
    data = tdb_fetch(db->tdb_didname, rootinfo_key);
    if (data.dptr)
    {
        memcpy(&hint, data.dptr, sizeof(cnid_t));
        free(data.dptr);
        id = ntohl(hint);
        /* If we've hit the max CNID allowed, we return a fatal error.  CNID
         * needs to be recycled before proceding. */
        if (++id == CNID_INVALID) {
            LOG(log_error, logtype_default, "cnid_add: FATAL: CNID database has reached its limit.");
            errno = CNID_ERR_MAX;
            goto cleanup;
        }
        hint = htonl(id);
    }
    else {
        hint = htonl(CNID_START);
    }
    
    memset(&data, 0, sizeof(data));
    data.dptr = (char *)&hint;
    data.dsize = sizeof(hint);
    if (tdb_store(db->tdb_didname, rootinfo_key, data, TDB_REPLACE)) {
        goto cleanup;
    }

    tdb_chainunlock(db->tdb_didname, rootinfo_key );  
    return hint;
cleanup:
    tdb_chainunlock(db->tdb_didname, rootinfo_key);  
    return CNID_INVALID;
}
Beispiel #9
0
int smb_unlock_share_mode_entry(struct smbdb_ctx *db_ctx,
                                uint64_t dev,
                                uint64_t ino,
                                uint64_t extid)
{
	struct locking_key lk;
	tdb_chainunlock(db_ctx->smb_tdb,
			get_locking_key(&lk, dev, ino, extid));
	return 0;
}
Beispiel #10
0
static int delete_fn(TDB_CONTEXT *ttdb, TDB_DATA kbuf, TDB_DATA dbuf, void *state)
{
	struct locking_data *data;
	share_mode_entry *shares;
	int i, del_count=0;
	pid_t mypid = sys_getpid();
	BOOL check_self = *(BOOL *)state;
	int ret = 0;

	tdb_chainlock(tdb, kbuf);

	data = (struct locking_data *)dbuf.dptr;
	shares = (share_mode_entry *)(dbuf.dptr + sizeof(*data));

	for (i=0;i<data->u.num_share_mode_entries;) {

		if (check_self && (shares[i].pid == mypid)) {
			DEBUG(0,("locking : delete_fn. LOGIC ERROR ! Shutting down and a record for my pid (%u) exists !\n",
					(unsigned int)shares[i].pid ));
		} else if (!process_exists(shares[i].pid)) {
			DEBUG(0,("locking : delete_fn. LOGIC ERROR ! Entry for pid %u and it no longer exists !\n",
					(unsigned int)shares[i].pid ));
		} else {
			/* Process exists, leave this record alone. */
			i++;
			continue;
		}

		data->u.num_share_mode_entries--;
		memmove(&shares[i], &shares[i+1],
		dbuf.dsize - (sizeof(*data) + (i+1)*sizeof(*shares)));
		del_count++;

	}

	/* the record has shrunk a bit */
	dbuf.dsize -= del_count * sizeof(*shares);

	/* store it back in the database */
	if (data->u.num_share_mode_entries == 0) {
		if (tdb_delete(ttdb, kbuf) == -1)
			ret = -1;
	} else {
		if (tdb_store(ttdb, kbuf, dbuf, TDB_REPLACE) == -1)
			ret = -1;
	}

	tdb_chainunlock(tdb, kbuf);
	return ret;
}
Beispiel #11
0
static struct db_record *db_tdb_fetch_locked_internal(
	struct db_context *db, TALLOC_CTX *mem_ctx, TDB_DATA key)
{
	struct db_tdb_ctx *ctx = talloc_get_type_abort(db->private_data,
						       struct db_tdb_ctx);
	struct tdb_fetch_locked_state state;

	state.mem_ctx = mem_ctx;
	state.result = NULL;

	if ((tdb_parse_record(ctx->wtdb->tdb, key, db_tdb_fetchlock_parse,
			      &state) < 0) &&
	    (tdb_error(ctx->wtdb->tdb) != TDB_ERR_NOEXIST)) {
		tdb_chainunlock(ctx->wtdb->tdb, key);
		return NULL;
	}

	if (state.result == NULL) {
		db_tdb_fetchlock_parse(key, tdb_null, &state);
	}

	if (state.result == NULL) {
		tdb_chainunlock(ctx->wtdb->tdb, key);
		return NULL;
	}

	talloc_set_destructor(state.result, db_tdb_record_destr);

	state.result->private_data = talloc_reference(state.result, ctx);
	state.result->store = db_tdb_store;
	state.result->delete_rec = db_tdb_delete;

	DEBUG(10, ("Allocated locked data 0x%p\n", state.result));

	return state.result;
}
Beispiel #12
0
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;
}
Beispiel #13
0
PyObject *py_tdb_hnd_chainunlock(PyObject *self, PyObject *args)
{
	tdb_hnd_object *obj = (tdb_hnd_object *)self;
	TDB_DATA key;
	int result;

        if (!obj->tdb) {
		PyErr_SetString(py_tdb_error, "tdb object has been closed"); 
		return NULL;
        }	

	if (!PyArg_ParseTuple(args, "s#", &key.dptr, &key.dsize))
		return NULL;

	result = tdb_chainunlock(obj->tdb, key);

	return PyInt_FromLong(result != -1);
}
Beispiel #14
0
static struct db_record *db_tdb_fetch_locked(struct db_context *db,
				     TALLOC_CTX *mem_ctx, TDB_DATA key)
{
	struct db_tdb_ctx *ctx = talloc_get_type_abort(db->private_data,
						       struct db_tdb_ctx);
	struct tdb_fetch_locked_state state;

	db_tdb_log_key("Locking", key);

	if (tdb_chainlock(ctx->wtdb->tdb, key) != 0) {
		DEBUG(3, ("tdb_chainlock failed\n"));
		return NULL;
	}

	state.mem_ctx = mem_ctx;
	state.result = NULL;

	tdb_parse_record(ctx->wtdb->tdb, key, db_tdb_fetchlock_parse, &state);

	if (state.result == NULL) {
		db_tdb_fetchlock_parse(key, tdb_null, &state);
	}

	if (state.result == NULL) {
		tdb_chainunlock(ctx->wtdb->tdb, key);
		return NULL;
	}

	talloc_set_destructor(state.result, db_tdb_record_destr);

	state.result->private_data = talloc_reference(state.result, ctx);
	state.result->store = db_tdb_store;
	state.result->delete_rec = db_tdb_delete;

	DEBUG(10, ("Allocated locked data 0x%p\n", state.result));

	return state.result;
}
static int do_child(int tdb_flags, int to, int from)
{
	struct tdb_context *tdb;
	unsigned int log_count;
	struct tdb_logging_context log_ctx = { log_fn, &log_count };
	int ret;
	char c = 0;

	tdb = tdb_open_ex("mutex-allrecord-trylock.tdb", 3, tdb_flags,
			  O_RDWR|O_CREAT, 0755, &log_ctx, NULL);
	ok(tdb, "tdb_open_ex should succeed");

	ret = tdb_chainlock(tdb, key);
	ok(ret == 0, "tdb_chainlock should succeed");

	write(to, &c, sizeof(c));

	read(from, &c, sizeof(c));

	ret = tdb_chainunlock(tdb, key);
	ok(ret == 0, "tdb_chainunlock should succeed");

	return 0;
}
Beispiel #16
0
int smb_unlock_share_mode_entry(struct smbdb_ctx *db_ctx,
                                uint64_t dev,
                                uint64_t ino)
{
	return tdb_chainunlock(db_ctx->smb_tdb, get_locking_key(dev, ino));
}
Beispiel #17
0
BOOL message_send_pid(pid_t pid, int msg_type, const void *buf, size_t len,
		      BOOL duplicates_allowed)
{
	TDB_DATA kbuf;
	TDB_DATA dbuf;
	struct message_rec rec;
	void *p;

	rec.msg_version = MESSAGE_VERSION;
	rec.msg_type = msg_type;
	rec.dest = pid;
	rec.src = sys_getpid();
	rec.len = len;

	kbuf = message_key_pid(pid);

	/* lock the record for the destination */
	tdb_chainlock(tdb, kbuf);

	dbuf = tdb_fetch(tdb, kbuf);

	if (!dbuf.dptr) {
		/* its a new record */
		p = (void *)malloc(len + sizeof(rec));
		if (!p) goto failed;

		memcpy(p, &rec, sizeof(rec));
		if (len > 0) memcpy((void *)((char*)p+sizeof(rec)), buf, len);

		dbuf.dptr = p;
		dbuf.dsize = len + sizeof(rec);
		tdb_store(tdb, kbuf, dbuf, TDB_REPLACE);
		SAFE_FREE(p);
		goto ok;
	}

	if (!duplicates_allowed) {
		char *ptr;
		struct message_rec prec;
		
		for(ptr = (char *)dbuf.dptr; ptr < dbuf.dptr + dbuf.dsize; ) {
			/*
			 * First check if the message header matches, then, if it's a non-zero
			 * sized message, check if the data matches. If so it's a duplicate and
			 * we can discard it. JRA.
			 */

			if (!memcmp(ptr, &rec, sizeof(rec))) {
				if (!len || (len && !memcmp( ptr + sizeof(rec), buf, len))) {
					DEBUG(10,("message_send_pid: discarding duplicate message.\n"));
					SAFE_FREE(dbuf.dptr);
					tdb_chainunlock(tdb, kbuf);
					return True;
				}
			}
			memcpy(&prec, ptr, sizeof(prec));
			ptr += sizeof(rec) + prec.len;
		}
	}

	/* we're adding to an existing entry */
	p = (void *)malloc(dbuf.dsize + len + sizeof(rec));
	if (!p) goto failed;

	memcpy(p, dbuf.dptr, dbuf.dsize);
	memcpy((void *)((char*)p+dbuf.dsize), &rec, sizeof(rec));
	if (len > 0) memcpy((void *)((char*)p+dbuf.dsize+sizeof(rec)), buf, len);

	SAFE_FREE(dbuf.dptr);
	dbuf.dptr = p;
	dbuf.dsize += len + sizeof(rec);
	tdb_store(tdb, kbuf, dbuf, TDB_REPLACE);
	SAFE_FREE(dbuf.dptr);

 ok:
	tdb_chainunlock(tdb, kbuf);
	errno = 0;                    /* paranoia */
	return message_notify(pid);

 failed:
	tdb_chainunlock(tdb, kbuf);
	errno = 0;                    /* paranoia */
	return False;
}
Beispiel #18
0
void unlock_share_entry(connection_struct *conn,
			SMB_DEV_T dev, SMB_INO_T inode)
{
	tdb_chainunlock(tdb, locking_key(dev, inode));
}
Beispiel #19
0
void unlock_share_entry_fsp(files_struct *fsp)
{
	tdb_chainunlock(tdb, locking_key(fsp->dev, fsp->inode));
}
Beispiel #20
0
static BOOL message_send_pid_internal(struct process_id pid, int msg_type,
				      const void *buf, size_t len,
				      BOOL duplicates_allowed,
				      unsigned int timeout)
{
	TDB_DATA kbuf;
	TDB_DATA dbuf;
	TDB_DATA old_dbuf;
	struct message_rec rec;
	char *ptr;
	struct message_rec prec;

	/* NULL pointer means implicit length zero. */
	if (!buf) {
		SMB_ASSERT(len == 0);
	}

	/*
	 * Doing kill with a non-positive pid causes messages to be
	 * sent to places we don't want.
	 */

	SMB_ASSERT(procid_to_pid(&pid) > 0);

	rec.msg_version = MESSAGE_VERSION;
	rec.msg_type = msg_type;
	rec.dest = pid;
	rec.src = procid_self();
	rec.len = buf ? len : 0;

	kbuf = message_key_pid(pid);

	dbuf.dptr = (void *)SMB_MALLOC(len + sizeof(rec));
	if (!dbuf.dptr)
		return False;

	memcpy(dbuf.dptr, &rec, sizeof(rec));
	if (len > 0 && buf)
		memcpy((void *)((char*)dbuf.dptr+sizeof(rec)), buf, len);

	dbuf.dsize = len + sizeof(rec);

	if (duplicates_allowed) {

		/* If duplicates are allowed we can just append the message and return. */

		/* lock the record for the destination */
		if (timeout) {
			if (tdb_chainlock_with_timeout(tdb, kbuf, timeout) == -1) {
				DEBUG(0,("message_send_pid_internal: failed to get chainlock with timeout %ul.\n", timeout));
				return False;
			}
		} else {
			if (tdb_chainlock(tdb, kbuf) == -1) {
				DEBUG(0,("message_send_pid_internal: failed to get chainlock.\n"));
				return False;
			}
		}	
		tdb_append(tdb, kbuf, dbuf);
		tdb_chainunlock(tdb, kbuf);

		SAFE_FREE(dbuf.dptr);
		errno = 0;                    /* paranoia */
		return message_notify(pid);
	}

	/* lock the record for the destination */
	if (timeout) {
		if (tdb_chainlock_with_timeout(tdb, kbuf, timeout) == -1) {
			DEBUG(0,("message_send_pid_internal: failed to get chainlock with timeout %ul.\n", timeout));
			return False;
		}
	} else {
		if (tdb_chainlock(tdb, kbuf) == -1) {
			DEBUG(0,("message_send_pid_internal: failed to get chainlock.\n"));
			return False;
		}
	}	

	old_dbuf = tdb_fetch(tdb, kbuf);

	if (!old_dbuf.dptr) {
		/* its a new record */

		tdb_store(tdb, kbuf, dbuf, TDB_REPLACE);
		tdb_chainunlock(tdb, kbuf);

		SAFE_FREE(dbuf.dptr);
		errno = 0;                    /* paranoia */
		return message_notify(pid);
	}

	/* Not a new record. Check for duplicates. */

	for(ptr = (char *)old_dbuf.dptr; ptr < old_dbuf.dptr + old_dbuf.dsize; ) {
		/*
		 * First check if the message header matches, then, if it's a non-zero
		 * sized message, check if the data matches. If so it's a duplicate and
		 * we can discard it. JRA.
		 */

		if (!memcmp(ptr, &rec, sizeof(rec))) {
			if (!len || (len && !memcmp( ptr + sizeof(rec), buf, len))) {
				tdb_chainunlock(tdb, kbuf);
				DEBUG(10,("message_send_pid_internal: discarding duplicate message.\n"));
				SAFE_FREE(dbuf.dptr);
				SAFE_FREE(old_dbuf.dptr);
				return True;
			}
		}
		memcpy(&prec, ptr, sizeof(prec));
		ptr += sizeof(rec) + prec.len;
	}

	/* we're adding to an existing entry */

	tdb_append(tdb, kbuf, dbuf);
	tdb_chainunlock(tdb, kbuf);

	SAFE_FREE(old_dbuf.dptr);
	SAFE_FREE(dbuf.dptr);

	errno = 0;                    /* paranoia */
	return message_notify(pid);
}
Beispiel #21
0
void brl_close(SMB_DEV_T dev, SMB_INO_T ino, pid_t pid, int tid, int fnum)
{
	TDB_DATA kbuf, dbuf;
	int count, i, j, dcount=0;
	struct lock_struct *locks;

	kbuf = locking_key(dev,ino);

	dbuf.dptr = NULL;

	tdb_chainlock(tdb, kbuf);
	dbuf = tdb_fetch(tdb, kbuf);

	if (!dbuf.dptr) goto fail;

	/* 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.tid == tid &&
		    lock->context.pid == pid &&
		    lock->fnum == fnum) {

			/* Send unlock messages to any pending waiters that overlap. */
			for (j=0; j<count; j++) {
				struct lock_struct *pend_lock = &locks[j];

				/* Ignore our own or non-pending locks. */
				if (pend_lock->lock_type != PENDING_LOCK)
					continue;

				if (pend_lock->context.tid == tid &&
				    pend_lock->context.pid == pid &&
				    pend_lock->fnum == fnum)
					continue;

				/* We could send specific lock info here... */
				if (brl_pending_overlap(lock, pend_lock))
					message_send_pid(pend_lock->context.pid,
							MSG_SMB_UNLOCK,
							NULL, 0, True);
			}

			/* found it - delete it */
			if (count > 1 && i < count-1) {
				memmove(&locks[i], &locks[i+1], 
					sizeof(*locks)*((count-1) - i));
			}
			count--;
			i--;
			dcount++;
		}
	}

	if (count == 0) {
		tdb_delete(tdb, kbuf);
	} else if (count < (dbuf.dsize / sizeof(*locks))) {
		dbuf.dsize -= dcount * sizeof(*locks);
		tdb_store(tdb, kbuf, dbuf, TDB_REPLACE);
	}

	/* we didn't find it */
 fail:
	SAFE_FREE(dbuf.dptr);
	tdb_chainunlock(tdb, kbuf);
}
Beispiel #22
0
int main(int argc, char *argv[])
{
	unsigned int i, extra_msgs;
	struct tdb_context *tdb;
	struct tdb_data key = tdb_mkdata("key", 3);
	struct tdb_data data = tdb_mkdata("data", 4);
	int flags[] = { TDB_DEFAULT, TDB_NOMMAP,
			TDB_CONVERT, TDB_NOMMAP|TDB_CONVERT,
			TDB_VERSION1, TDB_NOMMAP|TDB_VERSION1,
			TDB_CONVERT|TDB_VERSION1,
			TDB_NOMMAP|TDB_CONVERT|TDB_VERSION1 };

	plan_tests(sizeof(flags) / sizeof(flags[0]) * 48);

	for (i = 0; i < sizeof(flags) / sizeof(flags[0]); i++) {
		/* RW -> R0 */
		tdb = tdb_open("run-92-get-set-readonly.tdb", flags[i],
			       O_RDWR|O_CREAT|O_TRUNC, 0600, &tap_log_attr);
		ok1(tdb);
		ok1(!(tdb_get_flags(tdb) & TDB_RDONLY));

		/* TDB1 complains multiple times. */
		if (flags[i] & TDB_VERSION1) {
			extra_msgs = 1;
		} else {
			extra_msgs = 0;
		}

		ok1(tdb_store(tdb, key, data, TDB_INSERT) == TDB_SUCCESS);

		tdb_add_flag(tdb, TDB_RDONLY);
		ok1(tdb_get_flags(tdb) & TDB_RDONLY);

		/* Can't store, append, delete. */
		ok1(tdb_store(tdb, key, data, TDB_MODIFY) == TDB_ERR_RDONLY);
		ok1(tap_log_messages == 1);
		ok1(tdb_append(tdb, key, data) == TDB_ERR_RDONLY);
		tap_log_messages -= extra_msgs;
		ok1(tap_log_messages == 2);
		ok1(tdb_delete(tdb, key) == TDB_ERR_RDONLY);
		tap_log_messages -= extra_msgs;
		ok1(tap_log_messages == 3);

		/* Can't start a transaction, or any write lock. */
		ok1(tdb_transaction_start(tdb) == TDB_ERR_RDONLY);
		ok1(tap_log_messages == 4);
		ok1(tdb_chainlock(tdb, key) == TDB_ERR_RDONLY);
		tap_log_messages -= extra_msgs;
		ok1(tap_log_messages == 5);
		ok1(tdb_lockall(tdb) == TDB_ERR_RDONLY);
		ok1(tap_log_messages == 6);
		ok1(tdb_wipe_all(tdb) == TDB_ERR_RDONLY);
		ok1(tap_log_messages == 7);

		/* Back to RW. */
		tdb_remove_flag(tdb, TDB_RDONLY);
		ok1(!(tdb_get_flags(tdb) & TDB_RDONLY));

		ok1(tdb_store(tdb, key, data, TDB_MODIFY) == TDB_SUCCESS);
		ok1(tdb_append(tdb, key, data) == TDB_SUCCESS);
		ok1(tdb_delete(tdb, key) == TDB_SUCCESS);

		ok1(tdb_transaction_start(tdb) == TDB_SUCCESS);
		ok1(tdb_store(tdb, key, data, TDB_INSERT) == TDB_SUCCESS);
		ok1(tdb_transaction_commit(tdb) == TDB_SUCCESS);

		ok1(tdb_chainlock(tdb, key) == TDB_SUCCESS);
		tdb_chainunlock(tdb, key);
		ok1(tdb_lockall(tdb) == TDB_SUCCESS);
		tdb_unlockall(tdb);
		ok1(tdb_wipe_all(tdb) == TDB_SUCCESS);
		ok1(tap_log_messages == 7);

		tdb_close(tdb);

		/* R0 -> RW */
		tdb = tdb_open("run-92-get-set-readonly.tdb", flags[i],
			       O_RDONLY, 0600, &tap_log_attr);
		ok1(tdb);
		ok1(tdb_get_flags(tdb) & TDB_RDONLY);

		/* Can't store, append, delete. */
		ok1(tdb_store(tdb, key, data, TDB_INSERT) == TDB_ERR_RDONLY);
		ok1(tap_log_messages == 8);
		ok1(tdb_append(tdb, key, data) == TDB_ERR_RDONLY);
		tap_log_messages -= extra_msgs;
		ok1(tap_log_messages == 9);
		ok1(tdb_delete(tdb, key) == TDB_ERR_RDONLY);
		tap_log_messages -= extra_msgs;
		ok1(tap_log_messages == 10);

		/* Can't start a transaction, or any write lock. */
		ok1(tdb_transaction_start(tdb) == TDB_ERR_RDONLY);
		ok1(tap_log_messages == 11);
		ok1(tdb_chainlock(tdb, key) == TDB_ERR_RDONLY);
		tap_log_messages -= extra_msgs;
		ok1(tap_log_messages == 12);
		ok1(tdb_lockall(tdb) == TDB_ERR_RDONLY);
		ok1(tap_log_messages == 13);
		ok1(tdb_wipe_all(tdb) == TDB_ERR_RDONLY);
		ok1(tap_log_messages == 14);

		/* Can't remove TDB_RDONLY since we opened with O_RDONLY */
		tdb_remove_flag(tdb, TDB_RDONLY);
		ok1(tap_log_messages == 15);
		ok1(tdb_get_flags(tdb) & TDB_RDONLY);
		tdb_close(tdb);

		ok1(tap_log_messages == 15);
		tap_log_messages = 0;
	}
	return exit_status();
}
Beispiel #23
0
BOOL brl_unlock(SMB_DEV_T dev, SMB_INO_T ino, int fnum,
		uint16 smbpid, pid_t pid, uint16 tid,
		br_off start, br_off size,
		BOOL remove_pending_locks_only)
{
	TDB_DATA kbuf, dbuf;
	int count, i, j;
	struct lock_struct *locks;
	struct lock_context context;

	kbuf = locking_key(dev,ino);

	dbuf.dptr = NULL;

	tdb_chainlock(tdb, kbuf);
	dbuf = tdb_fetch(tdb, kbuf);

	if (!dbuf.dptr) {
		DEBUG(10,("brl_unlock: tdb_fetch failed !\n"));
		goto fail;
	}

	context.smbpid = smbpid;
	context.pid = pid;
	context.tid = tid;

	/* there are existing locks - find a match */
	locks = (struct lock_struct *)dbuf.dptr;
	count = dbuf.dsize / sizeof(*locks);

#if ZERO_ZERO
	for (i=0; i<count; i++) {
		struct lock_struct *lock = &locks[i];

		if (lock->lock_type == WRITE_LOCK &&
		    brl_same_context(&lock->context, &context) &&
		    lock->fnum == fnum &&
		    lock->start == start &&
		    lock->size == size) {
			/* found it - delete it */
			if (count == 1) {
				tdb_delete(tdb, kbuf);
			} else {
				if (i < count-1) {
					memmove(&locks[i], &locks[i+1], 
						sizeof(*locks)*((count-1) - i));
				}
				dbuf.dsize -= sizeof(*locks);
				tdb_store(tdb, kbuf, dbuf, TDB_REPLACE);
			}

			SAFE_FREE(dbuf.dptr);
			tdb_chainunlock(tdb, kbuf);
			return True;
		}
	}
#endif

	locks = (struct lock_struct *)dbuf.dptr;
	count = dbuf.dsize / sizeof(*locks);
	for (i=0; i<count; i++) {
		struct lock_struct *lock = &locks[i];

		if (brl_same_context(&lock->context, &context) &&
				lock->fnum == fnum &&
				lock->start == start &&
				lock->size == size) {

			if (remove_pending_locks_only && lock->lock_type != PENDING_LOCK)
				continue;

			if (lock->lock_type != PENDING_LOCK) {
				/* Send unlock messages to any pending waiters that overlap. */
				for (j=0; j<count; j++) {
					struct lock_struct *pend_lock = &locks[j];

					/* Ignore non-pending locks. */
					if (pend_lock->lock_type != PENDING_LOCK)
						continue;

					/* We could send specific lock info here... */
					if (brl_pending_overlap(lock, pend_lock)) {
						DEBUG(10,("brl_unlock: sending unlock message to pid %u\n",
									(unsigned int)pend_lock->context.pid ));

						message_send_pid(pend_lock->context.pid,
								MSG_SMB_UNLOCK,
								NULL, 0, True);
					}
				}
			}

			/* found it - delete it */
			if (count == 1) {
				tdb_delete(tdb, kbuf);
			} else {
				if (i < count-1) {
					memmove(&locks[i], &locks[i+1], 
						sizeof(*locks)*((count-1) - i));
				}
				dbuf.dsize -= sizeof(*locks);
				tdb_store(tdb, kbuf, dbuf, TDB_REPLACE);
			}

			SAFE_FREE(dbuf.dptr);
			tdb_chainunlock(tdb, kbuf);
			return True;
		}
	}

	/* we didn't find it */

 fail:
	SAFE_FREE(dbuf.dptr);
	tdb_chainunlock(tdb, kbuf);
	return False;
}
Beispiel #24
0
NTSTATUS brl_lock(SMB_DEV_T dev, SMB_INO_T ino, int fnum,
		  uint16 smbpid, pid_t pid, uint16 tid,
		  br_off start, br_off size, 
		  enum brl_type lock_type)
{
	TDB_DATA kbuf, dbuf;
	int count, i;
	struct lock_struct lock, *locks;
	char *tp;
	NTSTATUS status = NT_STATUS_OK;
	static int last_failed = -1;
	static br_off last_failed_start;

	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

	tdb_chainlock(tdb, kbuf);
	dbuf = tdb_fetch(tdb, kbuf);

	lock.context.smbpid = smbpid;
	lock.context.pid = pid;
	lock.context.tid = tid;
	lock.start = start;
	lock.size = size;
	lock.fnum = fnum;
	lock.lock_type = lock_type;

	if (dbuf.dptr) {
		/* there are existing locks - make sure they don't conflict */
		locks = (struct lock_struct *)dbuf.dptr;
		count = dbuf.dsize / sizeof(*locks);
		for (i=0; i<count; i++) {
			if (brl_conflict(&locks[i], &lock)) {
				status = NT_STATUS_LOCK_NOT_GRANTED;
				goto fail;
			}
#if ZERO_ZERO
			if (lock.start == 0 && lock.size == 0 && 
			    locks[i].size == 0) {
				break;
			}
#endif
		}
	}

	/* no conflicts - add it to the list of locks */
	tp = Realloc(dbuf.dptr, dbuf.dsize + sizeof(*locks));
	if (!tp) {
		status = NT_STATUS_NO_MEMORY;
		goto fail;
	} else {
		dbuf.dptr = tp;
	}
	memcpy(dbuf.dptr + dbuf.dsize, &lock, sizeof(lock));
	dbuf.dsize += sizeof(lock);

#if ZERO_ZERO
	/* sort the lock list */
	qsort(dbuf.dptr, dbuf.dsize/sizeof(lock), sizeof(lock), lock_compare);
#endif

	tdb_store(tdb, kbuf, dbuf, TDB_REPLACE);

	SAFE_FREE(dbuf.dptr);
	tdb_chainunlock(tdb, kbuf);
	return NT_STATUS_OK;

 fail:
	/* this is a nasty hack to try to simulate the lock result cache code in w2k.
	   It isn't completely accurate as I haven't yet worked out the correct
	   semantics (tridge)
	*/
	if (last_failed == fnum &&
	    last_failed_start == start &&
	    NT_STATUS_EQUAL(status, NT_STATUS_LOCK_NOT_GRANTED)) {
		status = NT_STATUS_FILE_LOCK_CONFLICT;
	}
	last_failed = fnum;
	last_failed_start = start;

	SAFE_FREE(dbuf.dptr);
	tdb_chainunlock(tdb, kbuf);
	return status;
}
static void addrec_db(void)
{
	int klen, dlen;
	char *k, *d;
	TDB_DATA key, data;

	klen = 1 + (rand() % KEYLEN);
	dlen = 1 + (rand() % DATALEN);

	k = randbuf(klen);
	d = randbuf(dlen);

	key.dptr = (unsigned char *)k;
	key.dsize = klen+1;

	data.dptr = (unsigned char *)d;
	data.dsize = dlen+1;

#if REOPEN_PROB
	if (in_transaction == 0 && random() % REOPEN_PROB == 0) {
		tdb_reopen_all(0);
		goto next;
	}
#endif

#if TRANSACTION_PROB
	if (in_transaction == 0 &&
	    (always_transaction || random() % TRANSACTION_PROB == 0)) {
		if (tdb_transaction_start(db) != 0) {
			fatal("tdb_transaction_start failed");
		}
		in_transaction++;
		goto next;
	}
	if (in_transaction && random() % TRANSACTION_PROB == 0) {
		if (random() % TRANSACTION_PREPARE_PROB == 0) {
			if (tdb_transaction_prepare_commit(db) != 0) {
				fatal("tdb_transaction_prepare_commit failed");
			}
		}
		if (tdb_transaction_commit(db) != 0) {
			fatal("tdb_transaction_commit failed");
		}
		in_transaction--;
		goto next;
	}
	if (in_transaction && random() % TRANSACTION_PROB == 0) {
		if (tdb_transaction_cancel(db) != 0) {
			fatal("tdb_transaction_cancel failed");
		}
		in_transaction--;
		goto next;
	}
#endif

#if DELETE_PROB
	if (random() % DELETE_PROB == 0) {
		tdb_delete(db, key);
		goto next;
	}
#endif

#if STORE_PROB
	if (random() % STORE_PROB == 0) {
		if (tdb_store(db, key, data, TDB_REPLACE) != 0) {
			fatal("tdb_store failed");
		}
		goto next;
	}
#endif

#if APPEND_PROB
	if (random() % APPEND_PROB == 0) {
		if (tdb_append(db, key, data) != 0) {
			fatal("tdb_append failed");
		}
		goto next;
	}
#endif

#if LOCKSTORE_PROB
	if (random() % LOCKSTORE_PROB == 0) {
		tdb_chainlock(db, key);
		data = tdb_fetch(db, key);
		if (tdb_store(db, key, data, TDB_REPLACE) != 0) {
			fatal("tdb_store failed");
		}
		if (data.dptr) free(data.dptr);
		tdb_chainunlock(db, key);
		goto next;
	} 
#endif

#if TRAVERSE_PROB
	if (random() % TRAVERSE_PROB == 0) {
		tdb_traverse(db, cull_traverse, NULL);
		goto next;
	}
#endif

#if TRAVERSE_READ_PROB
	if (random() % TRAVERSE_READ_PROB == 0) {
		tdb_traverse_read(db, NULL, NULL);
		goto next;
	}
#endif

	data = tdb_fetch(db, key);
	if (data.dptr) free(data.dptr);

next:
	free(k);
	free(d);
}
Beispiel #26
0
void tdb_unlock_bystring(struct tdb_context *tdb, const char *keyval)
{
	TDB_DATA key = string_term_tdb_data(keyval);

	tdb_chainunlock(tdb, key);
}