Move copychunk locking to be local to the read/write calls.
authorJeremy Allison <jra@samba.org>
Thu, 17 Jan 2013 00:29:11 +0000 (16:29 -0800)
committerDavid Disseldorp <ddiss@samba.org>
Mon, 15 Apr 2013 16:15:15 +0000 (18:15 +0200)
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>
(cherry picked from commit f2d028ef552adf13eed10b7db47e35bfa89a9c02)

source3/modules/vfs_default.c

index a44f99fe19df7ac10bec00fa4cb75dcd167c5c5c..bc7e6ec3c8ae305c8f994400ce3568c8235bd501 100644 (file)
@@ -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);
                }