mirror of
https://github.com/samba-team/samba.git
synced 2025-08-05 12:22:11 +03:00
Fixed the (incorrect) paranioa fix I put in for the fcntl lock spin.
Don't delete a share mode that failed to remove the oplock (doh!), just set the oplock entry to zero.... Jeremy.
This commit is contained in:
@ -451,7 +451,7 @@ static void fill_share_mode(char *p, files_struct *fsp, uint16 port, uint16 op_t
|
|||||||
and port info.
|
and port info.
|
||||||
********************************************************************/
|
********************************************************************/
|
||||||
|
|
||||||
static BOOL share_modes_identical( share_mode_entry *e1, share_mode_entry *e2)
|
BOOL share_modes_identical( share_mode_entry *e1, share_mode_entry *e2)
|
||||||
{
|
{
|
||||||
return (e1->pid == e2->pid &&
|
return (e1->pid == e2->pid &&
|
||||||
e1->share_mode == e2->share_mode &&
|
e1->share_mode == e2->share_mode &&
|
||||||
@ -465,7 +465,7 @@ static BOOL share_modes_identical( share_mode_entry *e1, share_mode_entry *e2)
|
|||||||
Ignore if no entry deleted.
|
Ignore if no entry deleted.
|
||||||
********************************************************************/
|
********************************************************************/
|
||||||
|
|
||||||
ssize_t del_share_entry( SMB_DEV_T dev, SMB_INO_T inode,
|
static ssize_t del_share_entry( SMB_DEV_T dev, SMB_INO_T inode,
|
||||||
share_mode_entry *entry, share_mode_entry **ppse)
|
share_mode_entry *entry, share_mode_entry **ppse)
|
||||||
{
|
{
|
||||||
TDB_DATA dbuf;
|
TDB_DATA dbuf;
|
||||||
@ -491,6 +491,8 @@ ssize_t del_share_entry( SMB_DEV_T dev, SMB_INO_T inode,
|
|||||||
* from the record.
|
* from the record.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
DEBUG(10,("del_share_mode: num_share_modes = %d\n", data->num_share_mode_entries ));
|
||||||
|
|
||||||
for (i=0;i<data->num_share_mode_entries;) {
|
for (i=0;i<data->num_share_mode_entries;) {
|
||||||
if (share_modes_identical(&shares[i], entry)) {
|
if (share_modes_identical(&shares[i], entry)) {
|
||||||
if (ppse)
|
if (ppse)
|
||||||
@ -499,6 +501,9 @@ ssize_t del_share_entry( SMB_DEV_T dev, SMB_INO_T inode,
|
|||||||
memmove(&shares[i], &shares[i+1],
|
memmove(&shares[i], &shares[i+1],
|
||||||
dbuf.dsize - (sizeof(*data) + (i+1)*sizeof(*shares)));
|
dbuf.dsize - (sizeof(*data) + (i+1)*sizeof(*shares)));
|
||||||
del_count++;
|
del_count++;
|
||||||
|
|
||||||
|
DEBUG(10,("del_share_mode: deleting entry %d\n", i ));
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
@ -603,34 +608,28 @@ BOOL set_share_mode(files_struct *fsp, uint16 port, uint16 op_type)
|
|||||||
A generic in-place modification call for share mode entries.
|
A generic in-place modification call for share mode entries.
|
||||||
********************************************************************/
|
********************************************************************/
|
||||||
|
|
||||||
static BOOL mod_share_mode(files_struct *fsp,
|
static BOOL mod_share_mode( SMB_DEV_T dev, SMB_INO_T inode, share_mode_entry *entry,
|
||||||
void (*mod_fn)(share_mode_entry *, SMB_DEV_T, SMB_INO_T, void *),
|
void (*mod_fn)(share_mode_entry *, SMB_DEV_T, SMB_INO_T, void *),
|
||||||
void *param)
|
void *param)
|
||||||
{
|
{
|
||||||
TDB_DATA dbuf;
|
TDB_DATA dbuf;
|
||||||
struct locking_data *data;
|
struct locking_data *data;
|
||||||
int i;
|
int i;
|
||||||
share_mode_entry *shares, entry;
|
share_mode_entry *shares;
|
||||||
BOOL need_store=False;
|
BOOL need_store=False;
|
||||||
|
|
||||||
/* read in the existing share modes */
|
/* read in the existing share modes */
|
||||||
dbuf = tdb_fetch(tdb, locking_key_fsp(fsp));
|
dbuf = tdb_fetch(tdb, locking_key(dev, inode));
|
||||||
if (!dbuf.dptr)
|
if (!dbuf.dptr)
|
||||||
return False;
|
return False;
|
||||||
|
|
||||||
data = (struct locking_data *)dbuf.dptr;
|
data = (struct locking_data *)dbuf.dptr;
|
||||||
shares = (share_mode_entry *)(dbuf.dptr + sizeof(*data));
|
shares = (share_mode_entry *)(dbuf.dptr + sizeof(*data));
|
||||||
|
|
||||||
/*
|
|
||||||
* Fake up a share_mode_entry for comparisons.
|
|
||||||
*/
|
|
||||||
|
|
||||||
fill_share_mode((char *)&entry, fsp, 0, 0);
|
|
||||||
|
|
||||||
/* find any with our pid and call the supplied function */
|
/* find any with our pid and call the supplied function */
|
||||||
for (i=0;i<data->num_share_mode_entries;i++) {
|
for (i=0;i<data->num_share_mode_entries;i++) {
|
||||||
if (share_modes_identical(&entry, &shares[i])) {
|
if (share_modes_identical(entry, &shares[i])) {
|
||||||
mod_fn(&shares[i], fsp->dev, fsp->inode, param);
|
mod_fn(&shares[i], dev, inode, param);
|
||||||
need_store=True;
|
need_store=True;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -638,10 +637,10 @@ static BOOL mod_share_mode(files_struct *fsp,
|
|||||||
/* if the mod fn was called then store it back */
|
/* if the mod fn was called then store it back */
|
||||||
if (need_store) {
|
if (need_store) {
|
||||||
if (data->num_share_mode_entries == 0) {
|
if (data->num_share_mode_entries == 0) {
|
||||||
if (tdb_delete(tdb, locking_key_fsp(fsp)) == -1)
|
if (tdb_delete(tdb, locking_key(dev, inode)) == -1)
|
||||||
need_store = False;
|
need_store = False;
|
||||||
} else {
|
} else {
|
||||||
if (tdb_store(tdb, locking_key_fsp(fsp), dbuf, TDB_REPLACE) == -1)
|
if (tdb_store(tdb, locking_key(dev, inode), dbuf, TDB_REPLACE) == -1)
|
||||||
need_store = False;
|
need_store = False;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -671,7 +670,12 @@ static void remove_share_oplock_fn(share_mode_entry *entry, SMB_DEV_T dev, SMB_I
|
|||||||
|
|
||||||
BOOL remove_share_oplock(files_struct *fsp)
|
BOOL remove_share_oplock(files_struct *fsp)
|
||||||
{
|
{
|
||||||
return mod_share_mode(fsp, remove_share_oplock_fn, NULL);
|
share_mode_entry entry;
|
||||||
|
/*
|
||||||
|
* Fake up an entry for comparisons...
|
||||||
|
*/
|
||||||
|
fill_share_mode((char *)&entry, fsp, 0, 0);
|
||||||
|
return mod_share_mode(fsp->dev, fsp->inode, &entry, remove_share_oplock_fn, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*******************************************************************
|
/*******************************************************************
|
||||||
@ -693,7 +697,21 @@ static void downgrade_share_oplock_fn(share_mode_entry *entry, SMB_DEV_T dev, SM
|
|||||||
|
|
||||||
BOOL downgrade_share_oplock(files_struct *fsp)
|
BOOL downgrade_share_oplock(files_struct *fsp)
|
||||||
{
|
{
|
||||||
return mod_share_mode(fsp, downgrade_share_oplock_fn, NULL);
|
share_mode_entry entry;
|
||||||
|
/*
|
||||||
|
* Fake up an entry for comparisons...
|
||||||
|
*/
|
||||||
|
fill_share_mode((char *)&entry, fsp, 0, 0);
|
||||||
|
return mod_share_mode(fsp->dev, fsp->inode, &entry, downgrade_share_oplock_fn, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*******************************************************************
|
||||||
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*******************************************************************
|
/*******************************************************************
|
||||||
|
@ -153,6 +153,9 @@ static int close_normal_file(files_struct *fsp, BOOL normal_close)
|
|||||||
lock_share_entry_fsp(fsp);
|
lock_share_entry_fsp(fsp);
|
||||||
share_entry_count = del_share_mode(fsp, &share_entry);
|
share_entry_count = del_share_mode(fsp, &share_entry);
|
||||||
|
|
||||||
|
DEBUG(10,("close_normal_file: share_entry_count = %d for file %s\n",
|
||||||
|
share_entry_count, fsp->fsp_name ));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We delete on close if it's the last open, and the
|
* We delete on close if it's the last open, and the
|
||||||
* delete on close flag was set in the entry we just deleted.
|
* delete on close flag was set in the entry we just deleted.
|
||||||
|
@ -527,17 +527,42 @@ dev = %x, inode = %.0f\n", old_shares[i].op_type, fname, (unsigned int)dev, (dou
|
|||||||
|
|
||||||
if(broke_oplock) {
|
if(broke_oplock) {
|
||||||
free((char *)old_shares);
|
free((char *)old_shares);
|
||||||
if (del_share_entry(dev, inode, &broken_entry, NULL) == -1) {
|
|
||||||
DEBUG(0,("open_mode_check: cannot delete entry when breaking oplock (%x) on file %s, \
|
|
||||||
dev = %x, inode = %.0f\n", broken_entry.op_type, fname, (unsigned int)dev, (double)inode));
|
|
||||||
errno = EACCES;
|
|
||||||
unix_ERR_class = ERRDOS;
|
|
||||||
unix_ERR_code = ERRbadshare;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
num_share_modes = get_share_modes(conn, dev, inode, &old_shares);
|
num_share_modes = get_share_modes(conn, dev, inode, &old_shares);
|
||||||
oplock_contention_count++;
|
oplock_contention_count++;
|
||||||
}
|
|
||||||
|
/* Paranoia check that this is no longer an exlusive entry. */
|
||||||
|
for(i = 0; i < num_share_modes; i++) {
|
||||||
|
share_mode_entry *share_entry = &old_shares[i];
|
||||||
|
|
||||||
|
if (share_modes_identical(&broken_entry, share_entry) &&
|
||||||
|
EXCLUSIVE_OPLOCK_TYPE(share_entry->op_type) ) {
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This should not happen. The target left this oplock
|
||||||
|
* 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));
|
||||||
|
|
||||||
|
if (process_exists(broken_entry.pid)) {
|
||||||
|
pstring errmsg;
|
||||||
|
slprintf(errmsg, sizeof(errmsg)-1,
|
||||||
|
"open_mode_check: Existant process %d left active oplock.\n",
|
||||||
|
broken_entry.pid );
|
||||||
|
smb_panic(errmsg);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!clear_share_entry(dev, inode, &broken_entry)) {
|
||||||
|
errno = EACCES;
|
||||||
|
unix_ERR_class = ERRDOS;
|
||||||
|
unix_ERR_code = ERRbadshare;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} /* end for paranoia... */
|
||||||
|
} /* end if broke_oplock */
|
||||||
|
|
||||||
} while(broke_oplock);
|
} while(broke_oplock);
|
||||||
|
|
||||||
if(old_shares != 0)
|
if(old_shares != 0)
|
||||||
@ -570,6 +595,7 @@ static void kernel_flock(files_struct *fsp, int deny_mode)
|
|||||||
else if (deny_mode == DENY_ALL) kernel_mode = LOCK_MAND;
|
else if (deny_mode == DENY_ALL) kernel_mode = LOCK_MAND;
|
||||||
if (kernel_mode) flock(fsp->fd, kernel_mode);
|
if (kernel_mode) flock(fsp->fd, kernel_mode);
|
||||||
#endif
|
#endif
|
||||||
|
;;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1141,6 +1141,9 @@ void release_level_2_oplocks_on_change(files_struct *fsp)
|
|||||||
|
|
||||||
num_share_modes = get_share_modes(fsp->conn, fsp->dev, fsp->inode, &share_list);
|
num_share_modes = get_share_modes(fsp->conn, fsp->dev, fsp->inode, &share_list);
|
||||||
|
|
||||||
|
DEBUG(10,("release_level_2_oplocks_on_change: num_share_modes = %d\n",
|
||||||
|
num_share_modes ));
|
||||||
|
|
||||||
for(i = 0; i < num_share_modes; i++) {
|
for(i = 0; i < num_share_modes; i++) {
|
||||||
share_mode_entry *share_entry = &share_list[i];
|
share_mode_entry *share_entry = &share_list[i];
|
||||||
|
|
||||||
@ -1153,6 +1156,9 @@ void release_level_2_oplocks_on_change(files_struct *fsp)
|
|||||||
* also no harm to ignore existing NO_OPLOCK states. JRA.
|
* also no harm to ignore existing NO_OPLOCK states. JRA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
DEBUG(10,("release_level_2_oplocks_on_change: share_entry[%i]->op_type == %d\n",
|
||||||
|
i, share_entry->op_type ));
|
||||||
|
|
||||||
if (share_entry->op_type == NO_OPLOCK)
|
if (share_entry->op_type == NO_OPLOCK)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@ -1179,6 +1185,8 @@ void release_level_2_oplocks_on_change(files_struct *fsp)
|
|||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DEBUG(10,("release_level_2_oplocks_on_change: breaking our own oplock.\n"));
|
||||||
|
|
||||||
oplock_break_level2(new_fsp, True, token);
|
oplock_break_level2(new_fsp, True, token);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
@ -1188,17 +1196,19 @@ void release_level_2_oplocks_on_change(files_struct *fsp)
|
|||||||
* message.
|
* message.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
DEBUG(10,("release_level_2_oplocks_on_change: breaking remote oplock.\n"));
|
||||||
request_oplock_break(share_entry, fsp->dev, fsp->inode);
|
request_oplock_break(share_entry, fsp->dev, fsp->inode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
free((char *)share_list);
|
if (share_list)
|
||||||
|
free((char *)share_list);
|
||||||
unlock_share_entry_fsp(fsp);
|
unlock_share_entry_fsp(fsp);
|
||||||
|
|
||||||
/* Paranoia check... */
|
/* Paranoia check... */
|
||||||
if (LEVEL_II_OPLOCK_TYPE(fsp->oplock_type)) {
|
if (LEVEL_II_OPLOCK_TYPE(fsp->oplock_type)) {
|
||||||
DEBUG(0,("release_level_2_oplocks_on_change: PANIC. File %s still has a level II oplock.\n", fsp->fsp_name));
|
DEBUG(0,("release_level_2_oplocks_on_change: PANIC. File %s still has a level II oplock.\n", fsp->fsp_name));
|
||||||
abort();
|
smb_panic("release_level_2_oplocks_on_change");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user