diff options
author | Jeremy Allison <jra@samba.org> | 2013-01-16 16:29:11 -0800 |
---|---|---|
committer | David Disseldorp <ddiss@samba.org> | 2013-01-18 00:06:52 +0100 |
commit | f2d028ef552adf13eed10b7db47e35bfa89a9c02 (patch) | |
tree | 3dcc5a313648d086421f5c38d42425f57ec8e785 | |
parent | d562e9006a341ade6f38ee129598dd2e1dc3a493 (diff) | |
download | samba-f2d028ef552adf13eed10b7db47e35bfa89a9c02.tar.gz samba-f2d028ef552adf13eed10b7db47e35bfa89a9c02.tar.bz2 samba-f2d028ef552adf13eed10b7db47e35bfa89a9c02.zip |
Move copychunk locking to be local to the read/write calls.
Eliminates the need to hold locks across the
entire lifetime of the call.
Next commit will remove these.
Signed-off-by: Jeremy Allison <jra@samba.org>
Reviewed-by: David Disseldorp <ddiss@samba.org>
-rw-r--r-- | source3/modules/vfs_default.c | 42 |
1 files changed, 42 insertions, 0 deletions
diff --git a/source3/modules/vfs_default.c b/source3/modules/vfs_default.c index d937c4a862..8a03ea372a 100644 --- a/source3/modules/vfs_default.c +++ b/source3/modules/vfs_default.c @@ -1372,12 +1372,34 @@ static struct tevent_req *vfswrap_copy_chunk_send(struct vfs_handle_struct *hand /* could use 2.6.33+ sendfile here to do this in kernel */ while (vfs_cc_state->copied < num) { ssize_t ret; + struct lock_struct lck; + int saved_errno; + off_t this_num = MIN(sizeof(vfs_cc_state->buf), num - vfs_cc_state->copied); + init_strict_lock_struct(src_fsp, + src_fsp->op->global->open_persistent_id, + src_off, + this_num, + READ_LOCK, + &lck); + + if (!SMB_VFS_STRICT_LOCK(src_fsp->conn, src_fsp, &lck)) { + tevent_req_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT); + return tevent_req_post(req, ev); + } + ret = SMB_VFS_PREAD(src_fsp, vfs_cc_state->buf, this_num, src_off); if (ret == -1) { + saved_errno = errno; + } + + SMB_VFS_STRICT_UNLOCK(src_fsp->conn, src_fsp, &lck); + + if (ret == -1) { + errno = saved_errno; tevent_req_nterror(req, map_nt_error_from_unix(errno)); return tevent_req_post(req, ev); } @@ -1386,11 +1408,31 @@ static struct tevent_req *vfswrap_copy_chunk_send(struct vfs_handle_struct *hand tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR); return tevent_req_post(req, ev); } + src_off += ret; + init_strict_lock_struct(dest_fsp, + dest_fsp->op->global->open_persistent_id, + dest_off, + this_num, + WRITE_LOCK, + &lck); + + if (!SMB_VFS_STRICT_LOCK(dest_fsp->conn, dest_fsp, &lck)) { + tevent_req_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT); + return tevent_req_post(req, ev); + } + ret = SMB_VFS_PWRITE(dest_fsp, vfs_cc_state->buf, this_num, dest_off); if (ret == -1) { + saved_errno = errno; + } + + SMB_VFS_STRICT_UNLOCK(src_fsp->conn, src_fsp, &lck); + + if (ret == -1) { + errno = saved_errno; tevent_req_nterror(req, map_nt_error_from_unix(errno)); return tevent_req_post(req, ev); } |