s3: Fix reading beyond the end of a named stream in xattr_streams
[ira/wip.git] / source3 / modules / vfs_aio_fork.c
index 8568ec39165d6e250e06d3ab5d279afb42f68240..c725fa6b9061ea74ec882e67b208a3e6d81df362 100644 (file)
@@ -343,6 +343,9 @@ static void aio_child_loop(int sockfd, struct mmap_area *map)
                        ret_struct.size = sys_pread(
                                fd, (void *)map->ptr, cmd_struct.n,
                                cmd_struct.offset);
+#ifdef ENABLE_BUILD_FARM_HACKS
+                       ret_struct.size = MAX(1, ret_struct.size * 0.9);
+#endif
                }
                else {
                        ret_struct.size = sys_pwrite(
@@ -357,6 +360,14 @@ static void aio_child_loop(int sockfd, struct mmap_area *map)
                        ret_struct.ret_errno = errno;
                }
 
+               /*
+                * Close the fd before telling our parent we're done. The
+                * parent might close and re-open the file very quickly, and
+                * with system-level share modes (GPFS) we would get an
+                * unjustified SHARING_VIOLATION.
+                */
+               close(fd);
+
                ret = write_data(sockfd, (char *)&ret_struct,
                                 sizeof(ret_struct));
                if (ret != sizeof(ret_struct)) {
@@ -364,8 +375,6 @@ static void aio_child_loop(int sockfd, struct mmap_area *map)
                                   strerror(errno)));
                        exit(2);
                }
-
-               close(fd);
        }
 }
 
@@ -417,6 +426,21 @@ static int aio_child_destructor(struct aio_child *child)
        return 0;
 }
 
+/*
+ * We have to close all fd's in open files, we might incorrectly hold a system
+ * level share mode on a file.
+ */
+
+static struct files_struct *close_fsp_fd(struct files_struct *fsp,
+                                        void *private_data)
+{
+       if ((fsp->fh != NULL) && (fsp->fh->fd != -1)) {
+               close(fsp->fh->fd);
+               fsp->fh->fd = -1;
+       }
+       return NULL;
+}
+
 static NTSTATUS create_aio_child(struct aio_child_list *children,
                                 size_t map_size,
                                 struct aio_child **presult)
@@ -455,6 +479,7 @@ static NTSTATUS create_aio_child(struct aio_child_list *children,
        if (result->pid == 0) {
                close(fdpair[0]);
                result->sockfd = fdpair[1];
+               file_walk_table(close_fsp_fd, NULL);
                aio_child_loop(result->sockfd, result->map);
        }
 
@@ -701,26 +726,17 @@ static int aio_fork_error_fn(struct vfs_handle_struct *handle,
        return child->retval.ret_errno;
 }
 
-/* VFS operations structure */
-
-static vfs_op_tuple aio_fork_ops[] = {
-       {SMB_VFS_OP(aio_fork_read),     SMB_VFS_OP_AIO_READ,
-        SMB_VFS_LAYER_TRANSPARENT},
-       {SMB_VFS_OP(aio_fork_write),    SMB_VFS_OP_AIO_WRITE,
-        SMB_VFS_LAYER_TRANSPARENT},
-       {SMB_VFS_OP(aio_fork_return_fn), SMB_VFS_OP_AIO_RETURN,
-        SMB_VFS_LAYER_TRANSPARENT},
-       {SMB_VFS_OP(aio_fork_cancel),   SMB_VFS_OP_AIO_CANCEL,
-        SMB_VFS_LAYER_TRANSPARENT},
-       {SMB_VFS_OP(aio_fork_error_fn), SMB_VFS_OP_AIO_ERROR,
-        SMB_VFS_LAYER_TRANSPARENT},
-       {SMB_VFS_OP(NULL),              SMB_VFS_OP_NOOP,
-        SMB_VFS_LAYER_NOOP}
+static struct vfs_fn_pointers vfs_aio_fork_fns = {
+       .aio_read = aio_fork_read,
+       .aio_write = aio_fork_write,
+       .aio_return_fn = aio_fork_return_fn,
+       .aio_cancel = aio_fork_cancel,
+       .aio_error_fn = aio_fork_error_fn,
 };
 
 NTSTATUS vfs_aio_fork_init(void);
 NTSTATUS vfs_aio_fork_init(void)
 {
        return smb_register_vfs(SMB_VFS_INTERFACE_VERSION,
-                               "aio_fork", aio_fork_ops);
+                               "aio_fork", &vfs_aio_fork_fns);
 }