Parcourir la source

Also cope with glibc's copy_file_range emulation returning EINVAL because we are suddenly using O_DIRECT and it doesn't align its buffer.

Samuel Thibault il y a 7 ans
Parent
commit
45d2ee14f0
1 fichiers modifiés avec 24 ajouts et 46 suppressions
  1. 24 46
      src/core/disk_ops/unistd/disk_unistd_global.c

+ 24 - 46
src/core/disk_ops/unistd/disk_unistd_global.c

@@ -92,12 +92,9 @@ struct starpu_unistd_copy_thread
 
 struct starpu_unistd_copy_thread copy_thread[STARPU_MAXNODES][STARPU_MAXNODES];
 static unsigned starpu_unistd_nb_disk_opened = 0;
-#if !defined(HAVE_COPY_FILE_RANGE) && defined( __NR_copy_file_range)
 /* copy_file_range syscall can return ENOSYS. Use global var to catch
  * and prevent StarPU using direct disk to disk copy */
-enum starpu_unistd_failed_copy { INIT, CHECKED, FAILED };
-static enum starpu_unistd_failed_copy starpu_unistd_copy_failed = INIT;
-#endif
+static int starpu_unistd_copy_works = 1;
 #endif
 
 struct starpu_unistd_base
@@ -159,6 +156,7 @@ struct starpu_unistd_wait
 static void _starpu_unistd_init(struct starpu_unistd_global_obj *obj, int descriptor, char *path, size_t size)
 {
 	STARPU_HG_DISABLE_CHECKING(starpu_unistd_opened_files);
+	STARPU_HG_DISABLE_CHECKING(starpu_unistd_copy_works);
 	if (starpu_unistd_opened_files >= MAX_OPEN_FILES)
 	{
 		/* Too many opened files, avoid keeping this one opened */
@@ -604,24 +602,32 @@ static void * starpu_unistd_internal_thread(void * arg)
 			STARPU_PTHREAD_MUTEX_UNLOCK(&internal_copy_thread->mutex);
 
 			starpu_ssize_t ret = copy_file_range(work->fd_src, &work->off_src, work->fd_dst, &work->off_dst, work->len, work->flags);
-			fprintf(stderr,"copy file range %d %d %lu %lu %zd\n", work->fd_src, work->fd_dst, (unsigned long) work->off_src, (unsigned long) work->off_dst, work->len);
 
-#if !defined(HAVE_COPY_FILE_RANGE) && defined( __NR_copy_file_range)
-			STARPU_PTHREAD_MUTEX_LOCK(&internal_copy_thread->mutex);
-			if (starpu_unistd_copy_failed == INIT && ret == -1 && errno == ENOSYS)
+			if (ret == -1 && (errno == ENOSYS || errno == EINVAL))
 			{
-				starpu_unistd_copy_failed = FAILED;
+				void *buf;
+				/* System call not supported, or glibc
+				 * compatibility layer does not work (e.g.
+				 * because we use O_DIRECT and glibc doesn't
+				 * align the buffer), avoid submitting more
+				 * copies.  */
+				starpu_unistd_copy_works = 0;
+
+				/* And do the copy by hand for this time */
+				starpu_malloc(&buf, work->len);
+				ret = pread(work->fd_src, buf, work->len, work->off_src);
+				STARPU_ASSERT_MSG(ret >= 0, "Reading failed (errno %d)", errno);
+				STARPU_ASSERT_MSG(ret == work->len, "Reading failed (value %ld instead of %ld)", (long)ret, (long)work->len);
+				ret = pwrite(work->fd_dst, buf, work->len, work->off_dst);
+				STARPU_ASSERT_MSG(ret >= 0, "Writing failed (errno %d)", errno);
+				STARPU_ASSERT_MSG(ret == work->len, "Writing failed (value %ld instead of %ld)", (long)ret, (long)work->len);
+				starpu_free(buf);
 			}
 			else
 			{
-#endif
 				STARPU_ASSERT_MSG(ret >= 0, "Copy_file_range failed (errno %d)", errno);
 				STARPU_ASSERT_MSG((size_t) ret == work->len, "Copy_file_range failed (value %ld instead of %ld)", (long)ret, (long)work->len);
-#if !defined(HAVE_COPY_FILE_RANGE) && defined( __NR_copy_file_range)
-				starpu_unistd_copy_failed = CHECKED;
 			}
-			STARPU_PTHREAD_MUTEX_UNLOCK(&internal_copy_thread->mutex);
-#endif
 
 			starpu_sem_post(&work->finished);
 
@@ -723,10 +729,6 @@ void starpu_unistd_global_unplug(void *base)
 	}
 	starpu_unistd_nb_disk_opened--;
 
-#if !defined(HAVE_COPY_FILE_RANGE) && defined( __NR_copy_file_range)
-	if (starpu_unistd_nb_disk_opened == 0)
-		starpu_unistd_copy_failed = INIT;
-#endif
 #endif
 
 	free(fileBase->path);
@@ -1021,6 +1023,10 @@ void *  starpu_unistd_global_copy(void *base_src, void* obj_src, off_t offset_sr
 	struct starpu_unistd_base * unistd_base_src = base_src;
 	struct starpu_unistd_base * unistd_base_dst = base_dst;
 
+	if (starpu_unistd_copy_works == 0)
+		/* It didn't work previously, don't bother submitting more.  */
+		return NULL;
+
 	struct starpu_unistd_wait * event;
 	_STARPU_CALLOC(event, 1,sizeof(*event));
 	event->type = STARPU_UNISTD_COPY;
@@ -1048,39 +1054,11 @@ void *  starpu_unistd_global_copy(void *base_src, void* obj_src, off_t offset_sr
 
 	struct starpu_unistd_copy_thread * thread = &copy_thread[unistd_base_src->disk_index][unistd_base_dst->disk_index];
 
-#if !defined(HAVE_COPY_FILE_RANGE) && defined( __NR_copy_file_range)
-	unsigned check = 0;
-	STARPU_PTHREAD_MUTEX_LOCK(&thread->mutex);
-	if (starpu_unistd_copy_failed == INIT)
-		check = 1;
-	STARPU_PTHREAD_MUTEX_UNLOCK(&thread->mutex);
-#endif
-
-
 	STARPU_PTHREAD_MUTEX_LOCK(&thread->mutex);
 	starpu_unistd_work_copy_list_push_front(&thread->list, work);
         STARPU_PTHREAD_COND_BROADCAST(&thread->cond);
 	STARPU_PTHREAD_MUTEX_UNLOCK(&thread->mutex);
 
-#if !defined(HAVE_COPY_FILE_RANGE) && defined( __NR_copy_file_range)
-	if (check)
-	{
-		starpu_unistd_global_wait_request((void *) event);
-		/* add token when StarPU will test/wait the request */
-		starpu_sem_post(&work->finished);
-
-		STARPU_PTHREAD_MUTEX_LOCK(&thread->mutex);
-		/* here copy_file_range does not work */
-		if (starpu_unistd_copy_failed == FAILED)
-		{
-			STARPU_PTHREAD_MUTEX_UNLOCK(&thread->mutex);
-			starpu_unistd_global_free_request((void *) event);
-			return NULL;
-		}
-		STARPU_PTHREAD_MUTEX_UNLOCK(&thread->mutex);
-	}
-#endif
-
 	return event;
 }
 #endif