1
0
mirror of https://github.com/samba-team/samba.git synced 2024-12-24 21:34:56 +03:00

r17140: Get rid of the lock release/reacquire code ! Turns out

that create dispositions that cause O_TRUNC break
oplocks. This simplifies the code - although we have
to keep separate the client requested access mask and
the access mask we actually use to open the file.
Jeremy.
(This used to be commit 3bcd52a475)
This commit is contained in:
Jeremy Allison 2006-07-19 18:34:19 +00:00 committed by Gerald (Jerry) Carter
parent 0e2f7c0ea4
commit dada5b4853

View File

@ -1117,6 +1117,7 @@ NTSTATUS open_file_ntcreate(connection_struct *conn,
uint16 mid = get_current_mid();
struct timeval request_time = timeval_zero();
struct share_mode_lock *lck = NULL;
uint32 open_access_mask = access_mask;
NTSTATUS status;
if (conn->printer) {
@ -1208,12 +1209,14 @@ NTSTATUS open_file_ntcreate(connection_struct *conn,
/* If file exists replace/overwrite. If file doesn't
* exist create. */
flags2 |= (O_CREAT | O_TRUNC);
open_access_mask |= FILE_WRITE_DATA; /* This will cause oplock breaks. */
break;
case FILE_OVERWRITE_IF:
/* If file exists replace/overwrite. If file doesn't
* exist create. */
flags2 |= (O_CREAT | O_TRUNC);
open_access_mask |= FILE_WRITE_DATA; /* This will cause oplock breaks. */
break;
case FILE_OPEN:
@ -1238,6 +1241,7 @@ NTSTATUS open_file_ntcreate(connection_struct *conn,
return NT_STATUS_OBJECT_NAME_NOT_FOUND;
}
flags2 |= O_TRUNC;
open_access_mask |= FILE_WRITE_DATA; /* This will cause oplock breaks. */
break;
case FILE_CREATE:
@ -1289,7 +1293,10 @@ NTSTATUS open_file_ntcreate(connection_struct *conn,
/* This is a nasty hack - must fix... JRA. */
if (access_mask == MAXIMUM_ALLOWED_ACCESS) {
access_mask = FILE_GENERIC_ALL;
open_access_mask = access_mask = FILE_GENERIC_ALL;
if (flags2 & O_TRUNC) {
open_access_mask |= FILE_WRITE_DATA; /* This will cause oplock breaks. */
}
}
/*
@ -1353,7 +1360,7 @@ NTSTATUS open_file_ntcreate(connection_struct *conn,
fsp->inode = psbuf->st_ino;
fsp->share_access = share_access;
fsp->fh->private_options = create_options;
fsp->access_mask = access_mask;
fsp->access_mask = open_access_mask; /* We change this to the requested access_mask after the open is done. */
/* Ensure no SAMBA_PRIVATE bits can be set. */
fsp->oplock_type = (oplock_request & ~SAMBA_PRIVATE_OPLOCK_MASK);
@ -1383,6 +1390,7 @@ NTSTATUS open_file_ntcreate(connection_struct *conn,
return NT_STATUS_SHARING_VIOLATION;
}
/* Use the client requested access mask here, not the one we open with. */
status = open_mode_check(conn, fname, lck,
access_mask, share_access,
create_options, &file_existed);
@ -1417,6 +1425,8 @@ NTSTATUS open_file_ntcreate(connection_struct *conn,
(NTCREATEX_OPTIONS_PRIVATE_DENY_DOS|
NTCREATEX_OPTIONS_PRIVATE_DENY_FCB)) {
files_struct *fsp_dup;
/* Use the client requested access mask here, not the one we open with. */
fsp_dup = fcb_or_dos_open(conn, fname, dev,
inode, access_mask,
share_access,
@ -1533,114 +1543,92 @@ NTSTATUS open_file_ntcreate(connection_struct *conn,
(unsigned int)flags, (unsigned int)flags2,
(unsigned int)unx_mode));
/* Drop the lock before doing any real file access. Allows kernel
oplock breaks to be processed. Handle any races after the open
call when we re-acquire the lock. */
if (lck) {
TALLOC_FREE(lck);
}
/*
* open_file strips any O_TRUNC flags itself.
*/
fsp_open = open_file(fsp,conn,fname,psbuf,flags|flags2,unx_mode,
access_mask);
fsp_open = open_file(fsp,conn,fname,psbuf,flags|flags2,unx_mode, open_access_mask);
if (!NT_STATUS_IS_OK(fsp_open)) {
if (lck != NULL) {
TALLOC_FREE(lck);
}
file_free(fsp);
return fsp_open;
}
/*
* Deal with the race condition where two smbd's detect the
* file doesn't exist and do the create at the same time. One
* of them will win and set a share mode, the other (ie. this
* one) should check if the requested share mode for this
* create is allowed.
*/
if (!file_existed) {
/*
* Now the file exists and fsp is successfully opened,
* fsp->dev and fsp->inode are valid and should replace the
* dev=0,inode=0 from a non existent file. Spotted by
* Nadav Danieli <nadavd@exanet.com>. JRA.
*/
/*
* Deal with the race condition where two smbd's detect the
* file doesn't exist and do the create at the same time. One
* of them will win and set a share mode, the other (ie. this
* one) should check if the requested share mode for this
* create is allowed.
*/
dev = fsp->dev;
inode = fsp->inode;
/*
* Now the file exists and fsp is successfully opened,
* fsp->dev and fsp->inode are valid and should replace the
* dev=0,inode=0 from a non existent file. Spotted by
* Nadav Danieli <nadavd@exanet.com>. JRA.
*/
lck = get_share_mode_lock(NULL, dev, inode,
conn->connectpath,
fname);
dev = fsp->dev;
inode = fsp->inode;
if (lck == NULL) {
DEBUG(0, ("open_file_ntcreate: Could not get share mode lock for %s\n", fname));
fd_close(conn, fsp);
file_free(fsp);
return NT_STATUS_SHARING_VIOLATION;
}
lck = get_share_mode_lock(NULL, dev, inode,
conn->connectpath,
fname);
/*
* The share entry is again *locked*.....
*/
/* First pass - send break only on batch oplocks. */
if (delay_for_oplocks(lck, fsp, 1, oplock_request)) {
schedule_defer_open(lck, request_time);
fd_close(conn, fsp);
file_free(fsp);
TALLOC_FREE(lck);
return NT_STATUS_SHARING_VIOLATION;
}
status = open_mode_check(conn, fname, lck,
access_mask, share_access,
create_options, &file_existed);
if (NT_STATUS_IS_OK(status)) {
/* We might be going to allow this open. Check oplock status again. */
/* Second pass - send break for both batch or exclusive oplocks. */
if (delay_for_oplocks(lck, fsp, 2, oplock_request)) {
schedule_defer_open(lck, request_time);
if (lck == NULL) {
DEBUG(0, ("open_file_ntcreate: Could not get share mode lock for %s\n", fname));
fd_close(conn, fsp);
file_free(fsp);
TALLOC_FREE(lck);
return NT_STATUS_SHARING_VIOLATION;
}
status = open_mode_check(conn, fname, lck,
access_mask, share_access,
create_options, &file_existed);
if (NT_STATUS_EQUAL(status, NT_STATUS_DELETE_PENDING)) {
/* DELETE_PENDING is not deferred for a second */
TALLOC_FREE(lck);
file_free(fsp);
return status;
}
if (!NT_STATUS_IS_OK(status)) {
struct deferred_open_record state;
fd_close(conn, fsp);
file_free(fsp);
state.delayed_for_oplocks = False;
state.dev = dev;
state.inode = inode;
/* Do it all over again immediately. In the second
* round we will find that the file existed and handle
* the DELETE_PENDING and FCB cases correctly. No need
* to duplicate the code here. Essentially this is a
* "goto top of this function", but don't tell
* anybody... */
defer_open(lck, request_time, timeval_zero(),
&state);
TALLOC_FREE(lck);
return status;
}
/*
* We exit this block with the share entry *locked*.....
*/
}
if (NT_STATUS_EQUAL(status, NT_STATUS_DELETE_PENDING)) {
/* DELETE_PENDING is not deferred for a second */
fd_close(conn, fsp);
file_free(fsp);
TALLOC_FREE(lck);
return status;
}
if (!NT_STATUS_IS_OK(status)) {
struct deferred_open_record state;
fd_close(conn, fsp);
file_free(fsp);
state.delayed_for_oplocks = False;
state.dev = dev;
state.inode = inode;
/* Do it all over again immediately. In the second
* round we will find that the file existed and handle
* the DELETE_PENDING and FCB cases correctly. No need
* to duplicate the code here. Essentially this is a
* "goto top of this function", but don't tell
* anybody... */
defer_open(lck, request_time, timeval_zero(),
&state);
TALLOC_FREE(lck);
return status;
}
SMB_ASSERT(lck != NULL);
/* note that we ignore failure for the following. It is
basically a hack for NFS, and NFS will never set one of
@ -1683,7 +1671,7 @@ NTSTATUS open_file_ntcreate(connection_struct *conn,
if (file_existed) {
/* stat opens on existing files don't get oplocks. */
if (is_stat_open(fsp->access_mask)) {
if (is_stat_open(open_access_mask)) {
fsp->oplock_type = NO_OPLOCK;
}