📄 brlock.c
字号:
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 = brl_lock_failed(&lock);; /* Did we block ourselves ? */ if (brl_same_context(&locks[i].context, &lock.context)) *my_lock_ctx = True; 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 = SMB_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 if (tdb_store(tdb, kbuf, dbuf, TDB_REPLACE) != 0) { status = NT_STATUS_INTERNAL_DB_CORRUPTION; goto fail; } SAFE_FREE(dbuf.dptr); tdb_chainunlock(tdb, kbuf); return NT_STATUS_OK; fail: SAFE_FREE(dbuf.dptr); tdb_chainunlock(tdb, kbuf); return status;}/**************************************************************************** Check if an unlock overlaps a pending lock.****************************************************************************/static BOOL brl_pending_overlap(struct lock_struct *lock, struct lock_struct *pend_lock){ if ((lock->start <= pend_lock->start) && (lock->start + lock->size > pend_lock->start)) return True; if ((lock->start >= pend_lock->start) && (lock->start <= pend_lock->start + pend_lock->size)) return True; return False;}/**************************************************************************** Unlock a range of bytes.****************************************************************************/BOOL brl_unlock(SMB_DEV_T dev, SMB_INO_T ino, int fnum, uint16 smbpid, struct process_id pid, uint16 tid, br_off start, br_off size, BOOL remove_pending_locks_only, void (*pre_unlock_fn)(void *), void *pre_unlock_data){ 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) { if (pre_unlock_fn) (*pre_unlock_fn)(pre_unlock_data); /* 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) { /* Do any POSIX unlocks needed. */ if (pre_unlock_fn) (*pre_unlock_fn)(pre_unlock_data); /* 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 %s\n", procid_str_static(&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;}/**************************************************************************** Test if we could add a lock if we wanted to.****************************************************************************/BOOL brl_locktest(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){ TDB_DATA kbuf, dbuf; int count, i; struct lock_struct lock, *locks; kbuf = locking_key(dev,ino); dbuf.dptr = NULL; 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++) { /* * 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); return True; fail: SAFE_FREE(dbuf.dptr); return False;}/**************************************************************************** Remove any locks associated with a open file.****************************************************************************/void brl_close(SMB_DEV_T dev, SMB_INO_T ino, struct process_id 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 && procid_equal(&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 && procid_equal(&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);}/**************************************************************************** Traverse the whole database with this function, calling traverse_callback on each lock.****************************************************************************/static int traverse_fn(TDB_CONTEXT *ttdb, TDB_DATA kbuf, TDB_DATA dbuf, void *state){ struct lock_struct *locks; struct lock_key *key; int i; BRLOCK_FN(traverse_callback) = (BRLOCK_FN_CAST())state; locks = (struct lock_struct *)dbuf.dptr; key = (struct lock_key *)kbuf.dptr; for (i=0;i<dbuf.dsize/sizeof(*locks);i++) { traverse_callback(key->device, key->inode, locks[i].context.pid, locks[i].lock_type, locks[i].start, locks[i].size); } return 0;}/******************************************************************* Call the specified function on each lock in the database.********************************************************************/int brl_forall(BRLOCK_FN(fn)){ if (!tdb) return 0; return tdb_traverse(tdb, traverse_fn, (void *)fn);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -