1
0
mirror of https://github.com/samba-team/samba.git synced 2025-03-03 12:58:35 +03:00

s3: Fix strict locking with chained reads

Move the strict lock/unlock code down a level for reads to avoid
calling chain_reply before the unlock.
This commit is contained in:
Tim Prouty 2009-05-12 16:32:32 -07:00
parent 5aefb44bf0
commit c60bb39df3

View File

@ -3352,12 +3352,22 @@ static void send_file_readX(connection_struct *conn, struct smb_request *req,
{ {
SMB_STRUCT_STAT sbuf; SMB_STRUCT_STAT sbuf;
ssize_t nread = -1; ssize_t nread = -1;
struct lock_struct lock;
if(SMB_VFS_FSTAT(fsp, &sbuf) == -1) { if(SMB_VFS_FSTAT(fsp, &sbuf) == -1) {
reply_unixerror(req, ERRDOS, ERRnoaccess); reply_unixerror(req, ERRDOS, ERRnoaccess);
return; return;
} }
init_strict_lock_struct(fsp, (uint32)req->smbpid,
(uint64_t)startpos, (uint64_t)smb_maxcnt, READ_LOCK,
&lock);
if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
reply_doserror(req, ERRDOS, ERRlock);
return;
}
if (!S_ISREG(sbuf.st_mode) || (startpos > sbuf.st_size) if (!S_ISREG(sbuf.st_mode) || (startpos > sbuf.st_size)
|| (smb_maxcnt > (sbuf.st_size - startpos))) { || (smb_maxcnt > (sbuf.st_size - startpos))) {
/* /*
@ -3419,8 +3429,7 @@ static void send_file_readX(connection_struct *conn, struct smb_request *req,
DEBUG( 3, ( "send_file_readX: fake_sendfile fnum=%d max=%d nread=%d\n", DEBUG( 3, ( "send_file_readX: fake_sendfile fnum=%d max=%d nread=%d\n",
fsp->fnum, (int)smb_maxcnt, (int)nread ) ); fsp->fnum, (int)smb_maxcnt, (int)nread ) );
/* No outbuf here means successful sendfile. */ /* No outbuf here means successful sendfile. */
TALLOC_FREE(req->outbuf); goto strict_unlock;
return;
} }
DEBUG(0,("send_file_readX: sendfile failed for file %s (%s). Terminating\n", DEBUG(0,("send_file_readX: sendfile failed for file %s (%s). Terminating\n",
@ -3447,12 +3456,10 @@ static void send_file_readX(connection_struct *conn, struct smb_request *req,
if (nread != smb_maxcnt + sizeof(headerbuf)) { if (nread != smb_maxcnt + sizeof(headerbuf)) {
sendfile_short_send(fsp, nread, sizeof(headerbuf), smb_maxcnt); sendfile_short_send(fsp, nread, sizeof(headerbuf), smb_maxcnt);
} }
/* No outbuf here means successful sendfile. */ /* No outbuf here means successful sendfile. */
TALLOC_FREE(req->outbuf);
SMB_PERFCOUNT_SET_MSGLEN_OUT(&req->pcd, nread); SMB_PERFCOUNT_SET_MSGLEN_OUT(&req->pcd, nread);
SMB_PERFCOUNT_END(&req->pcd); SMB_PERFCOUNT_END(&req->pcd);
return; goto strict_unlock;
} }
normal_read: normal_read:
@ -3478,8 +3485,7 @@ normal_read:
fsp->fsp_name, strerror(errno) )); fsp->fsp_name, strerror(errno) ));
exit_server_cleanly("send_file_readX: fake_sendfile failed"); exit_server_cleanly("send_file_readX: fake_sendfile failed");
} }
TALLOC_FREE(req->outbuf); goto strict_unlock;
return;
} }
nosendfile_read: nosendfile_read:
@ -3487,6 +3493,9 @@ nosendfile_read:
reply_outbuf(req, 12, smb_maxcnt); reply_outbuf(req, 12, smb_maxcnt);
nread = read_file(fsp, smb_buf(req->outbuf), startpos, smb_maxcnt); nread = read_file(fsp, smb_buf(req->outbuf), startpos, smb_maxcnt);
SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
if (nread < 0) { if (nread < 0) {
reply_unixerror(req, ERRDOS, ERRnoaccess); reply_unixerror(req, ERRDOS, ERRnoaccess);
return; return;
@ -3498,6 +3507,12 @@ nosendfile_read:
fsp->fnum, (int)smb_maxcnt, (int)nread ) ); fsp->fnum, (int)smb_maxcnt, (int)nread ) );
chain_reply(req); chain_reply(req);
return;
strict_unlock:
SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
TALLOC_FREE(req->outbuf);
return;
} }
/**************************************************************************** /****************************************************************************
@ -3510,7 +3525,6 @@ void reply_read_and_X(struct smb_request *req)
files_struct *fsp; files_struct *fsp;
SMB_OFF_T startpos; SMB_OFF_T startpos;
size_t smb_maxcnt; size_t smb_maxcnt;
struct lock_struct lock;
bool big_readX = False; bool big_readX = False;
#if 0 #if 0
size_t smb_mincnt = SVAL(req->vwv+6, 0); size_t smb_mincnt = SVAL(req->vwv+6, 0);
@ -3599,26 +3613,14 @@ void reply_read_and_X(struct smb_request *req)
} }
init_strict_lock_struct(fsp, (uint32)req->smbpid,
(uint64_t)startpos, (uint64_t)smb_maxcnt, READ_LOCK,
&lock);
if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
END_PROFILE(SMBreadX);
reply_doserror(req, ERRDOS, ERRlock);
return;
}
if (!big_readX && if (!big_readX &&
schedule_aio_read_and_X(conn, req, fsp, startpos, smb_maxcnt)) { schedule_aio_read_and_X(conn, req, fsp, startpos, smb_maxcnt)) {
goto strict_unlock; goto out;
} }
send_file_readX(conn, req, fsp, startpos, smb_maxcnt); send_file_readX(conn, req, fsp, startpos, smb_maxcnt);
strict_unlock: out:
SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
END_PROFILE(SMBreadX); END_PROFILE(SMBreadX);
return; return;
} }