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; }
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; }
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; }
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; }
/* 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; }
/* 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; }
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; }
/* ----------------------- */ 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; }
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; }
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; }
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; }
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; }
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); }
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; }
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)); }
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; }
void unlock_share_entry(connection_struct *conn, SMB_DEV_T dev, SMB_INO_T inode) { tdb_chainunlock(tdb, locking_key(dev, inode)); }
void unlock_share_entry_fsp(files_struct *fsp) { tdb_chainunlock(tdb, locking_key(fsp->dev, fsp->inode)); }
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); }
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); }
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(); }
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; }
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); }
void tdb_unlock_bystring(struct tdb_context *tdb, const char *keyval) { TDB_DATA key = string_term_tdb_data(keyval); tdb_chainunlock(tdb, key); }