From f2d028ef552adf13eed10b7db47e35bfa89a9c02 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 16 Jan 2013 16:29:11 -0800 Subject: 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 Reviewed-by: David Disseldorp --- source3/modules/vfs_default.c | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) (limited to 'source3/modules') 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); } -- cgit