diff options
author | Tim Prouty <tprouty@samba.org> | 2009-05-12 16:32:32 -0700 |
---|---|---|
committer | Tim Prouty <tprouty@samba.org> | 2009-05-12 17:13:40 -0700 |
commit | c60bb39df355c2ef36e4cfdff69cc348adc6dae1 (patch) | |
tree | e6ee42a51c44a54798345a516bc0c97c890fd622 /source3/smbd | |
parent | 5aefb44bf04becc6b80e7c3bf038d79851c5b0f9 (diff) | |
download | samba-c60bb39df355c2ef36e4cfdff69cc348adc6dae1.tar.gz samba-c60bb39df355c2ef36e4cfdff69cc348adc6dae1.tar.bz2 samba-c60bb39df355c2ef36e4cfdff69cc348adc6dae1.zip |
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.
Diffstat (limited to 'source3/smbd')
-rw-r--r-- | source3/smbd/reply.c | 46 |
1 files changed, 24 insertions, 22 deletions
diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index f1275b1088..05de4d4c26 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -3352,12 +3352,22 @@ static void send_file_readX(connection_struct *conn, struct smb_request *req, { SMB_STRUCT_STAT sbuf; ssize_t nread = -1; + struct lock_struct lock; if(SMB_VFS_FSTAT(fsp, &sbuf) == -1) { reply_unixerror(req, ERRDOS, ERRnoaccess); 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) || (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", fsp->fnum, (int)smb_maxcnt, (int)nread ) ); /* No outbuf here means successful sendfile. */ - TALLOC_FREE(req->outbuf); - return; + goto strict_unlock; } 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)) { sendfile_short_send(fsp, nread, sizeof(headerbuf), smb_maxcnt); } - /* No outbuf here means successful sendfile. */ - TALLOC_FREE(req->outbuf); SMB_PERFCOUNT_SET_MSGLEN_OUT(&req->pcd, nread); SMB_PERFCOUNT_END(&req->pcd); - return; + goto strict_unlock; } normal_read: @@ -3478,8 +3485,7 @@ normal_read: fsp->fsp_name, strerror(errno) )); exit_server_cleanly("send_file_readX: fake_sendfile failed"); } - TALLOC_FREE(req->outbuf); - return; + goto strict_unlock; } nosendfile_read: @@ -3487,6 +3493,9 @@ nosendfile_read: reply_outbuf(req, 12, smb_maxcnt); nread = read_file(fsp, smb_buf(req->outbuf), startpos, smb_maxcnt); + + SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock); + if (nread < 0) { reply_unixerror(req, ERRDOS, ERRnoaccess); return; @@ -3498,6 +3507,12 @@ nosendfile_read: fsp->fnum, (int)smb_maxcnt, (int)nread ) ); 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; SMB_OFF_T startpos; size_t smb_maxcnt; - struct lock_struct lock; bool big_readX = False; #if 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 && 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); -strict_unlock: - SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock); - + out: END_PROFILE(SMBreadX); return; } |