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>
Thu, 17 Jan 2013 23:06:52 +0000 (00:06 +0100)
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>
source3/modules/vfs_default.c

index d937c4a8623a329b50207cf20a82db2a0c7e362a..8a03ea372a244e5d1ddb7e6c0a6773474170b9d0 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);
                }