diff options
Diffstat (limited to 'source3')
-rw-r--r-- | source3/locking/locking.c | 41 | ||||
-rw-r--r-- | source3/smbd/open.c | 16 |
2 files changed, 43 insertions, 14 deletions
diff --git a/source3/locking/locking.c b/source3/locking/locking.c index fea821baa1..80537c8bc1 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -299,7 +299,7 @@ BOOL locking_init(int read_only) return True; tdb = tdb_open_log(lock_path("locking.tdb"), - 0, TDB_CLEAR_IF_FIRST|USE_TDB_MMAP_FLAG, + 0, USE_TDB_MMAP_FLAG|(read_only?0x0:TDB_CLEAR_IF_FIRST), read_only?O_RDONLY:O_RDWR|O_CREAT, 0644); @@ -365,18 +365,35 @@ static TDB_DATA locking_key_fsp(files_struct *fsp) return locking_key(fsp->dev, fsp->inode); } +#ifndef LOCK_SHARE_ENTRY_SPIN_COUNT +#define LOCK_SHARE_ENTRY_SPIN_COUNT 100 +#endif + /******************************************************************* Lock a hash bucket entry. ******************************************************************/ + BOOL lock_share_entry(connection_struct *conn, SMB_DEV_T dev, SMB_INO_T inode) { +#if 1 /* JRATEST */ + int count = 0; + for (count = 0; count < LOCK_SHARE_ENTRY_SPIN_COUNT; count++) + if (tdb_chainlock(tdb, locking_key(dev, inode)) == 0) + return True; + else + DEBUG(0,("lock_share_entry: locking (%d) for dev = %x, inode = %.0f failed with error %s\n", + count, (unsigned int)dev, (double)inode, strerror(errno) )); + return False; +#else return tdb_chainlock(tdb, locking_key(dev, inode)) == 0; +#endif } /******************************************************************* Unlock a hash bucket entry. ******************************************************************/ + void unlock_share_entry(connection_struct *conn, SMB_DEV_T dev, SMB_INO_T inode) { @@ -389,7 +406,18 @@ void unlock_share_entry(connection_struct *conn, BOOL lock_share_entry_fsp(files_struct *fsp) { +#if 1 /* JRATEST */ + int count = 0; + for (count = 0; count < LOCK_SHARE_ENTRY_SPIN_COUNT; count++) + if (tdb_chainlock(tdb, locking_key(fsp->dev, fsp->inode)) == 0) + return True; + else + DEBUG(0,("lock_share_entry_fsp: locking (%d) for dev = %x, inode = %.0f failed with error %s\n", + count, (unsigned int)fsp->dev, (double)fsp->inode, strerror(errno) )); + return False; +#else return tdb_chainlock(tdb, locking_key(fsp->dev, fsp->inode)) == 0; +#endif } /******************************************************************* @@ -465,7 +493,7 @@ BOOL share_modes_identical( share_mode_entry *e1, share_mode_entry *e2) Ignore if no entry deleted. ********************************************************************/ -static ssize_t del_share_entry( SMB_DEV_T dev, SMB_INO_T inode, +ssize_t del_share_entry( SMB_DEV_T dev, SMB_INO_T inode, share_mode_entry *entry, share_mode_entry **ppse) { TDB_DATA dbuf; @@ -706,15 +734,6 @@ BOOL downgrade_share_oplock(files_struct *fsp) } /******************************************************************* - Delete an exclusive share oplock owned by a defunct smbd.. -********************************************************************/ - -BOOL clear_share_entry(SMB_DEV_T dev, SMB_INO_T inode, share_mode_entry *entry) -{ - return mod_share_mode(dev, inode, entry, remove_share_oplock_fn, NULL); -} - -/******************************************************************* Get/Set the delete on close flag in a set of share modes. Return False on fail, True on success. ********************************************************************/ diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 633cf71817..a8cf9aba89 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -3,6 +3,7 @@ Version 1.9. file opening and share modes Copyright (C) Andrew Tridgell 1992-1998 + Copyright (C) Jeremy Allison 2001 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -542,8 +543,8 @@ dev = %x, inode = %.0f\n", old_shares[i].op_type, fname, (unsigned int)dev, (dou * as exlusive.... The process *must* be dead.... */ - DEBUG(0,("open_mode_check: exlusive oplock left after break ! For file %s, -dev = %x, inode = %.0f\n", fname, (unsigned int)dev, (double)inode)); + DEBUG(0,("open_mode_check: exlusive oplock left by process %d after break ! For file %s, +dev = %x, inode = %.0f. Deleting it to continue...\n", (int)broken_entry.pid, fname, (unsigned int)dev, (double)inode)); if (process_exists(broken_entry.pid)) { pstring errmsg; @@ -553,12 +554,21 @@ dev = %x, inode = %.0f\n", fname, (unsigned int)dev, (double)inode)); smb_panic(errmsg); } - if (!clear_share_entry(dev, inode, &broken_entry)) { + if (del_share_entry(dev, inode, &broken_entry, NULL) == -1) { errno = EACCES; unix_ERR_class = ERRDOS; unix_ERR_code = ERRbadshare; return -1; } + + /* + * We must reload the share modes after deleting the + * other process's entry. + */ + + free((char *)old_shares); + num_share_modes = get_share_modes(conn, dev, inode, &old_shares); + break; } } /* end for paranoia... */ } /* end if broke_oplock */ |