VirtualBox

source: vbox/trunk/src/VBox/Runtime/r3/linux/RTFileCopyPartEx-linux.cpp@ 77910

Last change on this file since 77910 was 77836, checked in by vboxsync, 6 years ago

IPRT: Spealiced RTFileCopyPartEx and associated prep/cleanup functions for linux copy_file_range(). [docs] bugref:9172

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 5.8 KB
Line 
1/* $Id: RTFileCopyPartEx-linux.cpp 77836 2019-03-21 20:52:08Z vboxsync $ */
2/** @file
3 * IPRT - RTFileCopyPartEx, linux specific implementation.
4 */
5
6/*
7 * Copyright (C) 2006-2019 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 *
17 * The contents of this file may alternatively be used under the terms
18 * of the Common Development and Distribution License Version 1.0
19 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
20 * VirtualBox OSE distribution, in which case the provisions of the
21 * CDDL are applicable instead of those of the GPL.
22 *
23 * You may elect to license modified versions of this file under the
24 * terms and conditions of either the GPL or the CDDL or both.
25 */
26
27
28/*********************************************************************************************************************************
29* Header Files *
30*********************************************************************************************************************************/
31#include <iprt/file.h>
32#include "internal/iprt.h"
33
34#include <iprt/asm.h>
35#include <iprt/assert.h>
36#include <iprt/err.h>
37
38#include <errno.h>
39#include <unistd.h>
40#include <sys/syscall.h>
41
42#ifndef __NR_copy_file_range
43# if defined(RT_ARCH_X86) || defined(RT_ARCH_AMD64)
44# define __NR_copy_file_range 285
45# endif
46#endif
47
48
49#ifndef __NR_copy_file_range
50# include "../../generic/RTFileCopyPartEx-generic.cpp"
51#else /* __NR_copy_file_range - whole file */
52/* Include the generic code as a fallback since copy_file_range is rather new . */
53# define IPRT_FALLBACK_VERSION
54# include "../../generic/RTFileCopyPartEx-generic.cpp"
55# undef IPRT_FALLBACK_VERSION
56
57
58/*********************************************************************************************************************************
59* Global Variables *
60*********************************************************************************************************************************/
61static int32_t volatile g_fCopyFileRangeSupported = -1;
62
63
64DECLINLINE(loff_t)
65MyCopyFileRangeSysCall(int fdIn, loff_t *poffIn, int fdOut, loff_t *poffOut, size_t cbChunk, unsigned int fFlags)
66{
67 return syscall(__NR_copy_file_range, fdIn, poffIn, fdOut, poffOut, cbChunk, fFlags);
68}
69
70
71DECL_NO_INLINE(static, bool) HasCopyFileRangeSyscallSlow(void)
72{
73 errno = 0;
74 MyCopyFileRangeSysCall(-1, NULL, -1, NULL, 4096, 0);
75 if (errno != ENOSYS)
76 {
77 ASMAtomicWriteS32(&g_fCopyFileRangeSupported, 1);
78 return true;
79 }
80 ASMAtomicWriteS32(&g_fCopyFileRangeSupported, 0);
81 return false;
82}
83
84DECLINLINE(bool) HasCopyFileRangeSyscall(void)
85{
86 int32_t i = ASMAtomicUoReadS32(&g_fCopyFileRangeSupported);
87 if (i != -1)
88 return i == 1;
89 return HasCopyFileRangeSyscallSlow();
90}
91
92
93
94RTDECL(int) RTFileCopyPartPrep(PRTFILECOPYPARTBUFSTATE pBufState, uint64_t cbToCopy)
95{
96 if (HasCopyFileRangeSyscall())
97 {
98 pBufState->iAllocType = -42;
99 pBufState->pbBuf = NULL;
100 pBufState->cbBuf = 0;
101 pBufState->uMagic = RTFILECOPYPARTBUFSTATE_MAGIC;
102 return VINF_SUCCESS;
103 }
104 return rtFileCopyPartPrepFallback(pBufState, cbToCopy);
105}
106
107
108RTDECL(void) RTFileCopyPartCleanup(PRTFILECOPYPARTBUFSTATE pBufState)
109{
110 return rtFileCopyPartCleanupFallback(pBufState);
111}
112
113
114RTDECL(int) RTFileCopyPartEx(RTFILE hFileSrc, RTFOFF offSrc, RTFILE hFileDst, RTFOFF offDst, uint64_t cbToCopy,
115 uint32_t fFlags, PRTFILECOPYPARTBUFSTATE pBufState, uint64_t *pcbCopied)
116{
117 /*
118 * Validate input.
119 */
120 if (pcbCopied)
121 *pcbCopied = 0;
122 AssertReturn(pBufState->uMagic == RTFILECOPYPARTBUFSTATE_MAGIC, VERR_INVALID_FLAGS);
123 if (pBufState->iAllocType == -42)
124 { /* more and more likley as time goes */ }
125 else
126 return rtFileCopyPartExFallback(hFileSrc, offSrc, hFileDst, offDst, cbToCopy, fFlags, pBufState, pcbCopied);
127 AssertReturn(offSrc >= 0, VERR_NEGATIVE_SEEK);
128 AssertReturn(offDst >= 0, VERR_NEGATIVE_SEEK);
129 AssertReturn(!fFlags, VERR_INVALID_FLAGS);
130
131 /*
132 * If nothing to copy, return right away.
133 */
134 if (!cbToCopy)
135 return VINF_SUCCESS;
136
137 /*
138 * Do the copying.
139 */
140 uint64_t cbCopied = 0;
141 int rc = VINF_SUCCESS;
142 do
143 {
144 size_t cbThisCopy = (size_t)RT_MIN(cbToCopy - cbCopied, _1G);
145 loff_t offThisDst = offSrc + cbCopied;
146 loff_t offThisSrc = offDst + cbCopied;
147 ssize_t cbActual = MyCopyFileRangeSysCall((int)RTFileToNative(hFileSrc), &offThisSrc,
148 (int)RTFileToNative(hFileDst), &offThisDst,
149 cbThisCopy, 0);
150 if (cbActual < 0)
151 {
152 rc = errno;
153 Assert(rc != 0);
154 rc = rc != 0 ? RTErrConvertFromErrno(rc) : VERR_READ_ERROR;
155 break;
156 }
157 Assert(offThisSrc == offSrc + (int64_t)cbCopied + cbActual);
158 Assert(offThisDst == offDst + (int64_t)cbCopied + cbActual);
159
160 if (cbActual == 0)
161 {
162 if (!pcbCopied)
163 rc = VERR_EOF;
164 break;
165 }
166
167 cbCopied += cbActual;
168 } while (cbCopied < cbToCopy);
169
170 if (pcbCopied)
171 *pcbCopied = cbCopied;
172
173 return rc;
174}
175
176#endif /* __NR_copy_file_range */
177
Note: See TracBrowser for help on using the repository browser.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette