VirtualBox

source: vbox/trunk/src/VBox/Storage/testcase/tstVDFill.cpp

Last change on this file was 106061, checked in by vboxsync, 2 months ago

Copyright year updates by scm.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 7.1 KB
Line 
1/** @file
2 *
3 * Test utility to fill a given image with random data up to a certain size (sequentially).
4 */
5
6/*
7 * Copyright (C) 2016-2024 Oracle and/or its affiliates.
8 *
9 * This file is part of VirtualBox base platform packages, as
10 * available from https://www.virtualbox.org.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation, in version 3 of the
15 * License.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, see <https://www.gnu.org/licenses>.
24 *
25 * SPDX-License-Identifier: GPL-3.0-only
26 */
27
28#include <VBox/vd.h>
29#include <iprt/errcore.h>
30#include <VBox/log.h>
31#include <iprt/asm.h>
32#include <iprt/dir.h>
33#include <iprt/string.h>
34#include <iprt/stream.h>
35#include <iprt/file.h>
36#include <iprt/mem.h>
37#include <iprt/initterm.h>
38#include <iprt/getopt.h>
39#include <iprt/rand.h>
40
41
42/*********************************************************************************************************************************
43* Global Variables *
44*********************************************************************************************************************************/
45/** The error count. */
46unsigned g_cErrors = 0;
47/** Global RNG state. */
48RTRAND g_hRand;
49
50#define TSTVDFILL_TEST_PATTERN_SIZE _1M
51
52static DECLCALLBACK(void) tstVDError(void *pvUser, int rc, RT_SRC_POS_DECL, const char *pszFormat, va_list va)
53{
54 RT_NOREF1(pvUser);
55 g_cErrors++;
56 RTPrintf("tstVDFill: Error %Rrc at %s:%u (%s): ", rc, RT_SRC_POS_ARGS);
57 RTPrintfV(pszFormat, va);
58 RTPrintf("\n");
59}
60
61static DECLCALLBACK(int) tstVDMessage(void *pvUser, const char *pszFormat, va_list va)
62{
63 RT_NOREF1(pvUser);
64 RTPrintf("tstVDFill: ");
65 RTPrintfV(pszFormat, va);
66 return VINF_SUCCESS;
67}
68
69static int tstFill(const char *pszFilename, const char *pszFormat, bool fStreamOptimized, uint64_t cbDisk, uint64_t cbFill)
70{
71 int rc;
72 PVDISK pVD = NULL;
73 VDGEOMETRY PCHS = { 0, 0, 0 };
74 VDGEOMETRY LCHS = { 0, 0, 0 };
75 PVDINTERFACE pVDIfs = NULL;
76 VDINTERFACEERROR VDIfError;
77
78 /** Buffer storing the random test pattern. */
79 uint8_t *pbTestPattern = NULL;
80
81 /* Create the virtual disk test data */
82 pbTestPattern = (uint8_t *)RTMemAlloc(TSTVDFILL_TEST_PATTERN_SIZE);
83
84 RTRandAdvBytes(g_hRand, pbTestPattern, TSTVDFILL_TEST_PATTERN_SIZE);
85
86 RTPrintf("Disk size is %llu bytes\n", cbDisk);
87
88 /* Create error interface. */
89 /* Create error interface. */
90 VDIfError.pfnError = tstVDError;
91 VDIfError.pfnMessage = tstVDMessage;
92
93 rc = VDInterfaceAdd(&VDIfError.Core, "tstVD_Error", VDINTERFACETYPE_ERROR,
94 NULL, sizeof(VDINTERFACEERROR), &pVDIfs);
95 AssertRC(rc);
96
97#define CHECK(str) \
98 do \
99 { \
100 RTPrintf("%s rc=%Rrc\n", str, rc); \
101 if (RT_FAILURE(rc)) \
102 { \
103 if (pbTestPattern) \
104 RTMemFree(pbTestPattern); \
105 VDDestroy(pVD); \
106 g_cErrors++; \
107 return rc; \
108 } \
109 } while (0)
110
111 rc = VDCreate(pVDIfs, VDTYPE_HDD, &pVD);
112 CHECK("VDCreate()");
113
114 rc = VDCreateBase(pVD, pszFormat, pszFilename, cbDisk,
115 fStreamOptimized ? VD_VMDK_IMAGE_FLAGS_STREAM_OPTIMIZED : VD_IMAGE_FLAGS_NONE,
116 "Test image", &PCHS, &LCHS, NULL, VD_OPEN_FLAGS_NORMAL,
117 NULL, NULL);
118 CHECK("VDCreateBase()");
119
120 uint64_t uOff = 0;
121 uint64_t cbGb = 0;
122 while ( uOff < cbFill
123 && RT_SUCCESS(rc))
124 {
125 size_t cbThisWrite = RT_MIN(TSTVDFILL_TEST_PATTERN_SIZE, cbFill - uOff);
126 rc = VDWrite(pVD, uOff, pbTestPattern, cbThisWrite);
127 if (RT_SUCCESS(rc))
128 {
129 uOff += cbThisWrite;
130 cbGb += cbThisWrite;
131 /* Print a message for every GB we wrote. */
132 if (cbGb >= _1G)
133 {
134 RTStrmPrintf(g_pStdErr, "Wrote %llu bytes\n", uOff);
135 cbGb = 0;
136 }
137 }
138 }
139
140 VDDestroy(pVD);
141 if (pbTestPattern)
142 RTMemFree(pbTestPattern);
143
144#undef CHECK
145 return rc;
146}
147
148/**
149 * Shows help message.
150 */
151static void printUsage(void)
152{
153 RTPrintf("Usage:\n"
154 "--disk-size <size in MB> Size of the disk\n"
155 "--fill-size <size in MB> How much to fill\n"
156 "--filename <filename> Filename of the image\n"
157 "--format <VDI|VMDK|...> Format to use\n"
158 "--streamoptimized Use the stream optimized format\n"
159 "--help Show this text\n");
160}
161
162static const RTGETOPTDEF g_aOptions[] =
163{
164 { "--disk-size", 's', RTGETOPT_REQ_UINT64 },
165 { "--fill-size", 'f', RTGETOPT_REQ_UINT64 },
166 { "--filename", 'p', RTGETOPT_REQ_STRING },
167 { "--format", 't', RTGETOPT_REQ_STRING },
168 { "--streamoptimized", 'r', RTGETOPT_REQ_NOTHING },
169 { "--help", 'h', RTGETOPT_REQ_NOTHING }
170};
171
172int main(int argc, char *argv[])
173{
174 RTR3InitExe(argc, &argv, 0);
175 int rc;
176 RTGETOPTUNION ValueUnion;
177 RTGETOPTSTATE GetState;
178 char c;
179 uint64_t cbDisk = 0;
180 uint64_t cbFill = 0;
181 const char *pszFilename = NULL;
182 const char *pszFormat = NULL;
183 bool fStreamOptimized = false;
184
185 rc = VDInit();
186 if (RT_FAILURE(rc))
187 return RTEXITCODE_FAILURE;
188
189 RTGetOptInit(&GetState, argc, argv, g_aOptions,
190 RT_ELEMENTS(g_aOptions), 1, RTGETOPTINIT_FLAGS_NO_STD_OPTS);
191
192 while ( RT_SUCCESS(rc)
193 && (c = RTGetOpt(&GetState, &ValueUnion)))
194 {
195 switch (c)
196 {
197 case 's':
198 cbDisk = ValueUnion.u64 * _1M;
199 break;
200 case 'f':
201 cbFill = ValueUnion.u64 * _1M;
202 break;
203 case 'p':
204 pszFilename = ValueUnion.psz;
205 break;
206 case 't':
207 pszFormat = ValueUnion.psz;
208 break;
209 case 'r':
210 fStreamOptimized = true;
211 break;
212 case 'h':
213 default:
214 printUsage();
215 break;
216 }
217 }
218
219 if (!cbDisk || !cbFill || !pszFilename || !pszFormat)
220 {
221 RTPrintf("tstVDFill: Arguments missing!\n");
222 return 1;
223 }
224
225 rc = RTRandAdvCreateParkMiller(&g_hRand);
226 if (RT_FAILURE(rc))
227 {
228 RTPrintf("tstVDFill: Creating RNG failed rc=%Rrc\n", rc);
229 return 1;
230 }
231
232 RTRandAdvSeed(g_hRand, 0x12345678);
233
234 rc = tstFill(pszFilename, pszFormat, fStreamOptimized, cbDisk, cbFill);
235 if (RT_FAILURE(rc))
236 RTPrintf("tstVDFill: Filling disk failed! rc=%Rrc\n", rc);
237
238 rc = VDShutdown();
239 if (RT_FAILURE(rc))
240 RTPrintf("tstVDFill: unloading backends failed! rc=%Rrc\n", rc);
241
242 return RTEXITCODE_SUCCESS;
243}
244
Note: See TracBrowser for help on using the repository browser.

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