diff options
author | Jeremy Allison <jra@samba.org> | 2001-05-22 20:35:48 +0000 |
---|---|---|
committer | Jeremy Allison <jra@samba.org> | 2001-05-22 20:35:48 +0000 |
commit | faa0bef196b732b45c4614acd655af4881504808 (patch) | |
tree | ea629d40dcd14be6fcdf1ced898971a2dd54a173 /source3/locking | |
parent | 58339ac6ccf6e6d264dfbfd6bf9bcf336e90256d (diff) | |
download | samba-faa0bef196b732b45c4614acd655af4881504808.tar.gz samba-faa0bef196b732b45c4614acd655af4881504808.tar.bz2 samba-faa0bef196b732b45c4614acd655af4881504808.zip |
Defensive brlock and locking database cleaning code.
Jeremy.
(This used to be commit d7aa42e4593b02ee6e487f7a4633bd7e7620ef2f)
Diffstat (limited to 'source3/locking')
-rw-r--r-- | source3/locking/brlock.c | 49 | ||||
-rw-r--r-- | source3/locking/locking.c | 83 |
2 files changed, 124 insertions, 8 deletions
diff --git a/source3/locking/brlock.c b/source3/locking/brlock.c index 175ab5c9b0..089818c9aa 100644 --- a/source3/locking/brlock.c +++ b/source3/locking/brlock.c @@ -113,12 +113,16 @@ static BOOL brl_conflict(struct lock_struct *lck1, /**************************************************************************** -delete a record if it is for a dead process + 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); @@ -128,7 +132,20 @@ static int delete_fn(TDB_CONTEXT *ttdb, TDB_DATA kbuf, TDB_DATA dbuf, void *stat for (i=0; i<count; i++) { struct lock_struct *lock = &locks[i]; - if (process_exists(lock->context.pid)) continue; + /* 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], @@ -152,9 +169,13 @@ static int delete_fn(TDB_CONTEXT *ttdb, TDB_DATA kbuf, TDB_DATA dbuf, void *stat /**************************************************************************** Open up the brlock.tdb database. ****************************************************************************/ + void brl_init(int read_only) { - if (tdb) return; + BOOL check_self = False; + + if (tdb) + return; tdb = tdb_open(lock_path("brlock.tdb"), 0, TDB_CLEAR_IF_FIRST, read_only?O_RDONLY:(O_RDWR|O_CREAT), 0644); if (!tdb) { @@ -163,11 +184,27 @@ void brl_init(int read_only) } /* delete any dead locks */ - if (!read_only) { - tdb_traverse(tdb, delete_fn, NULL); - } + if (!read_only) + tdb_traverse(tdb, delete_fn, &check_self); } +/**************************************************************************** + Close down the brlock.tdb database. +****************************************************************************/ + +void brl_shutdown(int read_only) +{ + BOOL check_self = True; + + if (tdb) + return; + + /* delete any dead locks */ + if (!read_only) + tdb_traverse(tdb, delete_fn, &check_self); + + tdb_close(tdb); +} /**************************************************************************** Lock a range of bytes. diff --git a/source3/locking/locking.c b/source3/locking/locking.c index 5824287e91..c2d3106a67 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -215,13 +215,72 @@ void locking_close_file(files_struct *fsp) } /**************************************************************************** + 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). + This function is only called on locking startup and shutdown. +****************************************************************************/ + +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; + + tdb_chainlock(tdb, kbuf); + + data = (struct locking_data *)dbuf.dptr; + shares = (share_mode_entry *)(dbuf.dptr + sizeof(*data)); + + for (i=0;i<data->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->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->num_share_mode_entries == 0) + tdb_delete(ttdb, kbuf); + else + tdb_store(ttdb, kbuf, dbuf, TDB_REPLACE); + + tdb_chainunlock(tdb, kbuf); + return 0; +} + +/**************************************************************************** Initialise the locking functions. ****************************************************************************/ + +static int open_read_only; + BOOL locking_init(int read_only) { + BOOL check_self = False; + brl_init(read_only); - if (tdb) return True; + if (tdb) + return True; tdb = tdb_open(lock_path("locking.tdb"), 0, TDB_CLEAR_IF_FIRST, @@ -236,15 +295,35 @@ BOOL locking_init(int read_only) if (!posix_locking_init(read_only)) return False; + /* delete any dead locks */ + if (!read_only) + tdb_traverse(tdb, delete_fn, &check_self); + + open_read_only = read_only; + return True; } /******************************************************************* Deinitialize the share_mode management. ******************************************************************/ + BOOL locking_end(void) { - if (tdb && tdb_close(tdb) != 0) return False; + BOOL check_self = True; + + brl_shutdown(open_read_only); + if (tdb) { + + /* delete any dead locks */ + + if (!open_read_only) + tdb_traverse(tdb, delete_fn, &check_self); + + if (tdb_close(tdb) != 0) + return False; + } + return True; } |