summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeremy Allison <jra@samba.org>2013-01-16 16:29:11 -0800
committerDavid Disseldorp <ddiss@samba.org>2013-01-18 00:06:52 +0100
commitf2d028ef552adf13eed10b7db47e35bfa89a9c02 (patch)
tree3dcc5a313648d086421f5c38d42425f57ec8e785
parentd562e9006a341ade6f38ee129598dd2e1dc3a493 (diff)
downloadsamba-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.c42
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);
}