filetest.c 71 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743
  1. /*++
  2. Copyright (c) 2013 Minoca Corp.
  3. This file is licensed under the terms of the GNU General Public License
  4. version 3. Alternative licensing terms are available. Contact
  5. info@minocacorp.com for details. See the LICENSE file at the root of this
  6. project for complete licensing information.
  7. Module Name:
  8. filetest.c
  9. Abstract:
  10. This module implements the tests used to verify that basic file operations
  11. are working.
  12. Author:
  13. Evan Green 27-Sep-2013
  14. Environment:
  15. User Mode
  16. --*/
  17. //
  18. // ------------------------------------------------------------------- Includes
  19. //
  20. #include <minoca/lib/types.h>
  21. #include <assert.h>
  22. #include <errno.h>
  23. #include <fcntl.h>
  24. #include <getopt.h>
  25. #include <stdio.h>
  26. #include <stdlib.h>
  27. #include <string.h>
  28. #include <sys/stat.h>
  29. #include <sys/wait.h>
  30. #include <sys/time.h>
  31. #include <time.h>
  32. #include <unistd.h>
  33. //
  34. // --------------------------------------------------------------------- Macros
  35. //
  36. #define DEBUG_PRINT(...) \
  37. if (FileTestVerbosity >= TestVerbosityDebug) { \
  38. printf(__VA_ARGS__); \
  39. }
  40. #define PRINT(...) \
  41. if (FileTestVerbosity >= TestVerbosityNormal) { \
  42. printf(__VA_ARGS__); \
  43. }
  44. #define PRINT_ERROR(...) fprintf(stderr, "\nfiletest: " __VA_ARGS__)
  45. //
  46. // ---------------------------------------------------------------- Definitions
  47. //
  48. #define FILE_TEST_VERSION_MAJOR 1
  49. #define FILE_TEST_VERSION_MINOR 0
  50. #define FILE_TEST_USAGE \
  51. "Usage: filetest [options] \n" \
  52. "This utility hammers on the file system. Options are:\n" \
  53. " -c, --file-count <count> -- Set the number of files to create.\n" \
  54. " -s, --file-size <size> -- Set the size of each file in bytes.\n" \
  55. " -i, --iterations <count> -- Set the number of operations to perform.\n" \
  56. " -p, --threads <count> -- Set the number of threads to spin up.\n" \
  57. " -r, --seed=int -- Set the random seed for deterministic results.\n" \
  58. " -t, --test -- Set the test to perform. Valid values are all, \n" \
  59. " consistency, concurrency, seek, streamseek, append, and \n" \
  60. " uninitialized.\n" \
  61. " --debug -- Print lots of information about what's happening.\n" \
  62. " --quiet -- Print only errors.\n" \
  63. " --no-cleanup -- Leave test files around for debugging.\n" \
  64. " --help -- Print this help text and exit.\n" \
  65. " --version -- Print the test version and exit.\n" \
  66. #define FILE_TEST_OPTIONS_STRING "c:s:i:t:p:r:ndqhV"
  67. #define FILE_TEST_CREATE_PERMISSIONS (S_IRUSR | S_IWUSR)
  68. #define DEFAULT_FILE_COUNT 20
  69. #define DEFAULT_FILE_SIZE (1024 * 17)
  70. #define DEFAULT_OPERATION_COUNT (DEFAULT_FILE_COUNT * 50)
  71. #define DEFAULT_THREAD_COUNT 1
  72. #define UNINITIALIZED_DATA_PATTERN 0xAB
  73. #define UNINITIALIZED_DATA_SEEK_MAX 0x200
  74. //
  75. // ------------------------------------------------------ Data Type Definitions
  76. //
  77. typedef enum _FILE_TEST_ACTION {
  78. FileTestActionWrite,
  79. FileTestActionRead,
  80. FileTestActionDelete,
  81. FileTestActionRename,
  82. FileTestActionCount
  83. } FILE_TEST_ACTION, *PFILE_TEST_ACTION;
  84. typedef enum _TEST_VERBOSITY {
  85. TestVerbosityQuiet,
  86. TestVerbosityNormal,
  87. TestVerbosityDebug
  88. } TEST_VERBOSITY, *PTEST_VERBOSITY;
  89. typedef enum _FILE_TEST_TYPE {
  90. FileTestAll,
  91. FileTestConsistency,
  92. FileTestSeek,
  93. FileTestStreamSeek,
  94. FileTestConcurrency,
  95. FileTestAppend,
  96. FileTestUninitializedData
  97. } FILE_TEST_TYPE, *PFILE_TEST_TYPE;
  98. //
  99. // ----------------------------------------------- Internal Function Prototypes
  100. //
  101. ULONG
  102. RunFileConsistencyTest (
  103. INT FileCount,
  104. INT FileSize,
  105. INT Iterations
  106. );
  107. ULONG
  108. RunFileConcurrencyTest (
  109. INT FileCount,
  110. INT FileSize,
  111. INT Iterations
  112. );
  113. ULONG
  114. RunFileAppendTest (
  115. INT FileCount,
  116. INT FileSize,
  117. INT Iterations
  118. );
  119. ULONG
  120. RunFileSeekTest (
  121. INT BlockCount,
  122. INT BlockSize,
  123. INT Iterations
  124. );
  125. ULONG
  126. RunStreamSeekTest (
  127. INT BlockCount,
  128. INT BlockSize,
  129. INT Iterations
  130. );
  131. ULONG
  132. RunFileUninitializedDataTest (
  133. INT FileCount,
  134. INT FileSize,
  135. INT Iterations
  136. );
  137. ULONG
  138. PrintTestTime (
  139. struct timeval *StartTime
  140. );
  141. //
  142. // -------------------------------------------------------------------- Globals
  143. //
  144. //
  145. // Higher levels here print out more stuff.
  146. //
  147. TEST_VERBOSITY FileTestVerbosity = TestVerbosityNormal;
  148. //
  149. // Set this boolean to skip cleaning up files.
  150. //
  151. BOOL FileTestNoCleanup = FALSE;
  152. struct option FileTestLongOptions[] = {
  153. {"file-count", required_argument, 0, 'c'},
  154. {"file-size", required_argument, 0, 's'},
  155. {"iterations", required_argument, 0, 'i'},
  156. {"seed", required_argument, 0, 'r'},
  157. {"threads", required_argument, 0, 'p'},
  158. {"test", required_argument, 0, 't'},
  159. {"no-cleanup", no_argument, 0, 'n'},
  160. {"debug", no_argument, 0, 'd'},
  161. {"quiet", no_argument, 0, 'q'},
  162. {"help", no_argument, 0, 'h'},
  163. {"version", no_argument, 0, 'V'},
  164. {NULL, 0, 0, 0},
  165. };
  166. //
  167. // ------------------------------------------------------------------ Functions
  168. //
  169. int
  170. main (
  171. int ArgumentCount,
  172. char **Arguments
  173. )
  174. /*++
  175. Routine Description:
  176. This routine implements the file test program.
  177. Arguments:
  178. ArgumentCount - Supplies the number of elements in the arguments array.
  179. Arguments - Supplies an array of strings. The array count is bounded by the
  180. previous parameter, and the strings are null-terminated.
  181. Return Value:
  182. 0 on success.
  183. Non-zero on failure.
  184. --*/
  185. {
  186. PSTR AfterScan;
  187. pid_t Child;
  188. INT ChildIndex;
  189. pid_t *Children;
  190. INT Failures;
  191. INT FileCount;
  192. INT FileSize;
  193. BOOL IsParent;
  194. INT Iterations;
  195. INT Option;
  196. INT Seed;
  197. INT Status;
  198. FILE_TEST_TYPE Test;
  199. INT Threads;
  200. Children = NULL;
  201. Failures = 0;
  202. FileCount = DEFAULT_FILE_COUNT;
  203. FileSize = DEFAULT_FILE_SIZE;
  204. Iterations = DEFAULT_OPERATION_COUNT;
  205. Seed = time(NULL) ^ getpid();
  206. Test = FileTestAll;
  207. Threads = DEFAULT_THREAD_COUNT;
  208. Status = 0;
  209. setvbuf(stdout, NULL, _IONBF, 0);
  210. setvbuf(stderr, NULL, _IONBF, 0);
  211. //
  212. // Process the control arguments.
  213. //
  214. while (TRUE) {
  215. Option = getopt_long(ArgumentCount,
  216. Arguments,
  217. FILE_TEST_OPTIONS_STRING,
  218. FileTestLongOptions,
  219. NULL);
  220. if (Option == -1) {
  221. break;
  222. }
  223. if ((Option == '?') || (Option == ':')) {
  224. Status = 1;
  225. goto MainEnd;
  226. }
  227. switch (Option) {
  228. case 'c':
  229. FileCount = strtol(optarg, &AfterScan, 0);
  230. if ((FileCount <= 0) || (AfterScan == optarg)) {
  231. PRINT_ERROR("Invalid file count %s.\n", optarg);
  232. Status = 1;
  233. goto MainEnd;
  234. }
  235. break;
  236. case 's':
  237. FileSize = strtol(optarg, &AfterScan, 0);
  238. if ((FileSize < 0) || (AfterScan == optarg)) {
  239. PRINT_ERROR("Invalid file size %s.\n", optarg);
  240. Status = 1;
  241. goto MainEnd;
  242. }
  243. break;
  244. case 'i':
  245. Iterations = strtol(optarg, &AfterScan, 0);
  246. if ((Iterations < 0) || (AfterScan == optarg)) {
  247. PRINT_ERROR("Invalid iteration count %s.\n", optarg);
  248. Status = 1;
  249. goto MainEnd;
  250. }
  251. break;
  252. case 'n':
  253. FileTestNoCleanup = TRUE;
  254. break;
  255. case 'p':
  256. Threads = strtol(optarg, &AfterScan, 0);
  257. if ((Threads <= 0) || (AfterScan == optarg)) {
  258. PRINT_ERROR("Invalid thread count %s.\n", optarg);
  259. Status = 1;
  260. goto MainEnd;
  261. }
  262. break;
  263. case 'r':
  264. Seed = strtol(optarg, &AfterScan, 0);
  265. if (AfterScan == optarg) {
  266. PRINT_ERROR("Invalid seed %s.\n", optarg);
  267. Status = 1;
  268. goto MainEnd;
  269. }
  270. break;
  271. case 't':
  272. if (strcasecmp(optarg, "all") == 0) {
  273. Test = FileTestAll;
  274. } else if (strcasecmp(optarg, "consistency") == 0) {
  275. Test = FileTestConsistency;
  276. } else if (strcasecmp(optarg, "seek") == 0) {
  277. Test = FileTestSeek;
  278. } else if (strcasecmp(optarg, "streamseek") == 0) {
  279. Test = FileTestStreamSeek;
  280. } else if (strcasecmp(optarg, "concurrency") == 0) {
  281. Test = FileTestConcurrency;
  282. } else if (strcasecmp(optarg, "append") == 0) {
  283. Test = FileTestAppend;
  284. } else if (strcasecmp(optarg, "uninitialized") == 0) {
  285. Test = FileTestUninitializedData;
  286. } else {
  287. PRINT_ERROR("Invalid test: %s.\n", optarg);
  288. Status = 1;
  289. goto MainEnd;
  290. }
  291. break;
  292. case 'd':
  293. FileTestVerbosity = TestVerbosityDebug;
  294. break;
  295. case 'q':
  296. FileTestVerbosity = TestVerbosityQuiet;
  297. break;
  298. case 'V':
  299. printf("Minoca filetest version %d.%d\n",
  300. FILE_TEST_VERSION_MAJOR,
  301. FILE_TEST_VERSION_MINOR);
  302. return 1;
  303. case 'h':
  304. printf(FILE_TEST_USAGE);
  305. return 1;
  306. default:
  307. assert(FALSE);
  308. Status = 1;
  309. goto MainEnd;
  310. }
  311. }
  312. srand(Seed);
  313. DEBUG_PRINT("Seed: %d.\n", Seed);
  314. IsParent = TRUE;
  315. if (Threads > 1) {
  316. Children = malloc(sizeof(pid_t) * (Threads - 1));
  317. if (Children == NULL) {
  318. Status = ENOMEM;
  319. goto MainEnd;
  320. }
  321. memset(Children, 0, sizeof(pid_t) * (Threads - 1));
  322. for (ChildIndex = 0; ChildIndex < Threads - 1; ChildIndex += 1) {
  323. Child = fork();
  324. //
  325. // If this is the child, break out and run the tests.
  326. //
  327. if (Child == 0) {
  328. srand(time(NULL) + ChildIndex);
  329. IsParent = FALSE;
  330. break;
  331. }
  332. Children[ChildIndex] = Child;
  333. }
  334. }
  335. //
  336. // Run the tests.
  337. //
  338. if ((Test == FileTestAll) || (Test == FileTestConsistency)) {
  339. Failures += RunFileConsistencyTest(FileCount, FileSize, Iterations);
  340. }
  341. if ((Test == FileTestAll) || (Test == FileTestSeek)) {
  342. Failures += RunFileSeekTest(FileCount, FileSize, Iterations);
  343. }
  344. if ((Test == FileTestAll) || (Test == FileTestStreamSeek)) {
  345. Failures += RunStreamSeekTest(FileCount, FileSize, Iterations);
  346. }
  347. if ((Test == FileTestAll) || (Test == FileTestConcurrency)) {
  348. Failures += RunFileConcurrencyTest(FileCount, FileSize, Iterations);
  349. }
  350. if ((Test == FileTestAll) || (Test == FileTestAppend)) {
  351. Failures += RunFileAppendTest(FileCount, FileSize, Iterations);
  352. }
  353. if ((Test == FileTestAll) || (Test == FileTestUninitializedData)) {
  354. Failures += RunFileUninitializedDataTest(FileCount,
  355. FileSize,
  356. Iterations);
  357. }
  358. //
  359. // Wait for any children.
  360. //
  361. if (IsParent != FALSE) {
  362. if (Threads > 1) {
  363. for (ChildIndex = 0; ChildIndex < Threads - 1; ChildIndex += 1) {
  364. Child = waitpid(Children[ChildIndex], &Status, 0);
  365. if (Child == -1) {
  366. PRINT_ERROR("Failed to wait for child %d: %s.\n",
  367. Children[ChildIndex],
  368. strerror(errno));
  369. Status = errno;
  370. } else {
  371. assert(Child == Children[ChildIndex]);
  372. if (!WIFEXITED(Status)) {
  373. PRINT_ERROR("Child %d returned with status %x\n",
  374. Status);
  375. Failures += 1;
  376. }
  377. Failures += WEXITSTATUS(Status);
  378. Status = 0;
  379. }
  380. }
  381. }
  382. //
  383. // If this is a child, just report back the number of failures to the
  384. // parent.
  385. //
  386. } else {
  387. if (Failures > 100) {
  388. exit(100);
  389. } else {
  390. exit(Failures);
  391. }
  392. }
  393. MainEnd:
  394. if (Children != NULL) {
  395. free(Children);
  396. }
  397. if (Status != 0) {
  398. PRINT_ERROR("Error: %d.\n", Status);
  399. }
  400. if (Failures != 0) {
  401. PRINT_ERROR("\n *** %d failures in filetest ***\n", Failures);
  402. return Failures;
  403. }
  404. return 0;
  405. }
  406. //
  407. // --------------------------------------------------------- Internal Functions
  408. //
  409. ULONG
  410. RunFileConsistencyTest (
  411. INT FileCount,
  412. INT FileSize,
  413. INT Iterations
  414. )
  415. /*++
  416. Routine Description:
  417. This routine executes the file consistency test.
  418. Arguments:
  419. FileCount - Supplies the number of files to work with.
  420. FileSize - Supplies the size of each file.
  421. Iterations - Supplies the number of iterations to perform.
  422. Return Value:
  423. Returns the number of failures in the test suite.
  424. --*/
  425. {
  426. FILE_TEST_ACTION Action;
  427. ssize_t BytesComplete;
  428. ULONG Failures;
  429. INT File;
  430. PINT FileBuffer;
  431. INT FileIndex;
  432. CHAR FileName[16];
  433. PINT FileOffset;
  434. INT FillIndex;
  435. INT Iteration;
  436. INT MaxSimultaneousFiles;
  437. INT OpenFlags;
  438. INT Percent;
  439. pid_t Process;
  440. INT Result;
  441. INT SimultaneousFiles;
  442. struct timeval StartTime;
  443. INT TotalBytesComplete;
  444. Failures = 0;
  445. FileBuffer = NULL;
  446. FileOffset = NULL;
  447. //
  448. // Record the test start time.
  449. //
  450. Result = gettimeofday(&StartTime, NULL);
  451. if (Result != 0) {
  452. PRINT_ERROR("Failed to get time of day: %s.\n", strerror(errno));
  453. Failures += 1;
  454. goto RunFileConsistencyTestEnd;
  455. }
  456. //
  457. // Announce the test.
  458. //
  459. Process = getpid();
  460. PRINT("Process %d Running file consistency with %d files of %d bytes each. "
  461. "%d iterations.\n",
  462. Process,
  463. FileCount,
  464. FileSize,
  465. Iterations);
  466. Percent = Iterations / 100;
  467. if (Percent == 0) {
  468. Percent = 1;
  469. }
  470. MaxSimultaneousFiles = 0;
  471. SimultaneousFiles = 0;
  472. FileOffset = malloc(FileCount * sizeof(INT));
  473. if (FileOffset == NULL) {
  474. Failures += 1;
  475. goto RunFileConsistencyTestEnd;
  476. }
  477. for (FileIndex = 0; FileIndex < FileCount; FileIndex += 1) {
  478. FileOffset[FileIndex] = -1;
  479. }
  480. FileSize = ALIGN_RANGE_UP(FileSize, sizeof(INT));
  481. FileBuffer = malloc(FileSize);
  482. if (FileBuffer == NULL) {
  483. Failures += 1;
  484. goto RunFileConsistencyTestEnd;
  485. }
  486. //
  487. // Perform the file operations. This test writes an entire file with
  488. // incremental values and then tests that any file reads return the same
  489. // values.
  490. //
  491. for (Iteration = 0; Iteration < Iterations; Iteration += 1) {
  492. //
  493. // Pick a random file and a random action.
  494. //
  495. FileIndex = rand() % FileCount;
  496. snprintf(FileName,
  497. sizeof(FileName),
  498. "fot%x-%06x",
  499. Process & 0xFFFF,
  500. FileIndex);
  501. Action = rand() % FileTestActionRename;
  502. //
  503. // If the file has yet to be created, then the action must be write.
  504. //
  505. if (FileOffset[FileIndex] == -1) {
  506. Action = FileTestActionWrite;
  507. }
  508. switch (Action) {
  509. case FileTestActionWrite:
  510. if (FileOffset[FileIndex] == -1) {
  511. SimultaneousFiles += 1;
  512. if (SimultaneousFiles > MaxSimultaneousFiles) {
  513. MaxSimultaneousFiles = SimultaneousFiles;
  514. }
  515. }
  516. OpenFlags = O_WRONLY | O_CREAT;
  517. if ((rand() & 0x1) != 0) {
  518. OpenFlags |= O_TRUNC;
  519. }
  520. File = open(FileName, OpenFlags, FILE_TEST_CREATE_PERMISSIONS);
  521. if (File < 0) {
  522. PRINT_ERROR("Failed to open file %s (flags %x): %s.\n",
  523. FileName,
  524. OpenFlags,
  525. strerror(errno));
  526. Failures += 1;
  527. continue;
  528. }
  529. FileOffset[FileIndex] = rand();
  530. DEBUG_PRINT("Writing file %s, Value %x\n",
  531. FileName,
  532. FileOffset[FileIndex]);
  533. for (FillIndex = 0;
  534. FillIndex < FileSize / sizeof(INT);
  535. FillIndex += 1) {
  536. FileBuffer[FillIndex] = FileOffset[FileIndex] + FillIndex;
  537. }
  538. do {
  539. BytesComplete = write(File, FileBuffer, FileSize);
  540. } while ((BytesComplete < 0) && (errno == EINTR));
  541. if (BytesComplete != FileSize) {
  542. PRINT_ERROR("Write failed. Wrote %d of %d bytes: %s.\n",
  543. BytesComplete,
  544. FileSize,
  545. strerror(errno));
  546. Failures += 1;
  547. }
  548. if (close(File) != 0) {
  549. PRINT_ERROR("Failed to close: %s.\n", strerror(errno));
  550. Failures += 1;
  551. }
  552. break;
  553. case FileTestActionRead:
  554. DEBUG_PRINT("Reading file %s, Value should be %x\n",
  555. FileName,
  556. FileOffset[FileIndex]);
  557. OpenFlags = O_RDONLY;
  558. if ((rand() & 0x1) != 0) {
  559. OpenFlags = O_RDWR;
  560. }
  561. File = open(FileName, OpenFlags);
  562. if (File < 0) {
  563. PRINT_ERROR("Failed to open file %s (flags %x): %s.\n",
  564. FileName,
  565. OpenFlags,
  566. strerror(errno));
  567. Failures += 1;
  568. continue;
  569. }
  570. for (FillIndex = 0;
  571. FillIndex < FileSize / sizeof(INT);
  572. FillIndex += 1) {
  573. FileBuffer[FillIndex] = 0xFEEEF00D;
  574. }
  575. TotalBytesComplete = 0;
  576. while (TotalBytesComplete < FileSize) {
  577. do {
  578. BytesComplete = read(File,
  579. FileBuffer + TotalBytesComplete,
  580. FileSize - TotalBytesComplete);
  581. } while ((BytesComplete < 0) && (errno == EINTR));
  582. if (BytesComplete <= 0) {
  583. PRINT_ERROR("Read failed. Read %d (%d total) of "
  584. "%d bytes: %s.\n",
  585. BytesComplete,
  586. TotalBytesComplete,
  587. FileSize,
  588. strerror(errno));
  589. Failures += 1;
  590. break;
  591. }
  592. TotalBytesComplete += BytesComplete;
  593. }
  594. for (FillIndex = 0;
  595. FillIndex < FileSize / sizeof(INT);
  596. FillIndex += 1) {
  597. if (FileBuffer[FillIndex] !=
  598. FileOffset[FileIndex] + FillIndex) {
  599. PRINT_ERROR("Read data file %s index %x came back %x, "
  600. "should have been %x.\n",
  601. FileName,
  602. FillIndex,
  603. FileBuffer[FillIndex],
  604. FileOffset[FileIndex] + FillIndex);
  605. Failures += 1;
  606. }
  607. }
  608. if (close(File) != 0) {
  609. PRINT_ERROR("Failed to close: %s.\n", strerror(errno));
  610. Failures += 1;
  611. }
  612. break;
  613. case FileTestActionDelete:
  614. DEBUG_PRINT("Deleting file %s\n", FileName);
  615. if (unlink(FileName) != 0) {
  616. PRINT_ERROR("Failed to unlink %s: %s.\n",
  617. FileName,
  618. strerror(errno));
  619. Failures += 1;
  620. }
  621. FileOffset[FileIndex] = -1;
  622. SimultaneousFiles -= 1;
  623. break;
  624. default:
  625. assert(FALSE);
  626. break;
  627. }
  628. if ((Iteration % Percent) == 0) {
  629. PRINT("o");
  630. }
  631. }
  632. //
  633. // Clean up all files.
  634. //
  635. if (FileTestNoCleanup == FALSE) {
  636. for (FileIndex = 0; FileIndex < FileCount; FileIndex += 1) {
  637. if (FileOffset[FileIndex] != -1) {
  638. snprintf(FileName,
  639. sizeof(FileName),
  640. "fot%x-%06x",
  641. Process & 0xFFFF,
  642. FileIndex);
  643. if (unlink(FileName) != 0) {
  644. PRINT_ERROR("Failed to unlink %s: %s.\n",
  645. FileName,
  646. strerror(errno));
  647. Failures += 1;
  648. }
  649. }
  650. }
  651. }
  652. PRINT("\nMax usage: %d files, %I64d bytes.\n",
  653. MaxSimultaneousFiles,
  654. (ULONGLONG)MaxSimultaneousFiles * (ULONGLONG)FileSize);
  655. Failures += PrintTestTime(&StartTime);
  656. RunFileConsistencyTestEnd:
  657. if (FileOffset != NULL) {
  658. free(FileOffset);
  659. }
  660. if (FileBuffer != NULL) {
  661. free(FileBuffer);
  662. }
  663. return Failures;
  664. }
  665. ULONG
  666. RunFileConcurrencyTest (
  667. INT FileCount,
  668. INT FileSize,
  669. INT Iterations
  670. )
  671. /*++
  672. Routine Description:
  673. This routine executes the file concurrency test.
  674. Arguments:
  675. FileCount - Supplies the number of files to work with.
  676. FileSize - Supplies the size of each file.
  677. Iterations - Supplies the number of iterations to perform.
  678. Return Value:
  679. Returns the number of failures in the test suite.
  680. --*/
  681. {
  682. FILE_TEST_ACTION Action;
  683. unsigned ActionSeed;
  684. ssize_t BytesComplete;
  685. INT DestinationFileIndex;
  686. CHAR DestinationFileName[16];
  687. ULONG Failures;
  688. INT File;
  689. INT FileIndex;
  690. CHAR FileName[16];
  691. INT Iteration;
  692. INT Offset;
  693. INT OpenFlags;
  694. INT Percent;
  695. pid_t Process;
  696. INT Result;
  697. struct timeval StartTime;
  698. INT Value;
  699. Failures = 0;
  700. //
  701. // Record the test start time.
  702. //
  703. Result = gettimeofday(&StartTime, NULL);
  704. if (Result != 0) {
  705. PRINT_ERROR("Failed to get time of day: %s.\n", strerror(errno));
  706. Failures += 1;
  707. goto RunFileConcurrencyTestEnd;
  708. }
  709. //
  710. // Announce the test.
  711. //
  712. Process = getpid();
  713. PRINT("Process %d Running file concurrency test with %d files of %d bytes "
  714. "each. %d iterations.\n",
  715. Process,
  716. FileCount,
  717. FileSize,
  718. Iterations);
  719. Percent = Iterations / 100;
  720. if (Percent == 0) {
  721. Percent = 1;
  722. }
  723. FileSize = ALIGN_RANGE_UP(FileSize, sizeof(INT));
  724. //
  725. // Get a separate seed for the random actions.
  726. //
  727. ActionSeed = time(NULL);
  728. //
  729. // Perform the file operations.
  730. //
  731. for (Iteration = 0; Iteration < Iterations; Iteration += 1) {
  732. //
  733. // Pick a random file and a random action.
  734. //
  735. FileIndex = rand() % FileCount;
  736. snprintf(FileName,
  737. sizeof(FileName),
  738. "fct-%06x",
  739. FileIndex);
  740. Action = rand_r(&ActionSeed) % FileTestActionCount;
  741. switch (Action) {
  742. case FileTestActionWrite:
  743. Offset = rand() % FileSize;
  744. DEBUG_PRINT("Writing file %s, Offset %x\n", FileName, Offset);
  745. OpenFlags = O_WRONLY | O_CREAT;
  746. File = open(FileName, OpenFlags, FILE_TEST_CREATE_PERMISSIONS);
  747. if (File < 0) {
  748. PRINT_ERROR("Failed to open file %s (flags %x): %s.\n",
  749. FileName,
  750. OpenFlags,
  751. strerror(errno));
  752. Failures += 1;
  753. continue;
  754. }
  755. Result = lseek(File, Offset, SEEK_SET);
  756. if (Result < 0) {
  757. PRINT_ERROR("Seek on file %s offset %d failed.\n",
  758. FileName,
  759. Offset);
  760. Failures += 1;
  761. }
  762. do {
  763. BytesComplete = write(File, &Offset, 1);
  764. } while ((BytesComplete < 0) && (errno == EINTR));
  765. if (BytesComplete != 1) {
  766. PRINT_ERROR("Write failed. Wrote %d of %d bytes: %s.\n",
  767. BytesComplete,
  768. FileSize,
  769. strerror(errno));
  770. Failures += 1;
  771. }
  772. if (close(File) != 0) {
  773. PRINT_ERROR("Failed to close: %s.\n", strerror(errno));
  774. Failures += 1;
  775. }
  776. break;
  777. case FileTestActionRead:
  778. Offset = rand() % FileSize;
  779. DEBUG_PRINT("Reading file %s, Offset %x\n", FileName, Offset);
  780. OpenFlags = O_RDWR | O_CREAT;
  781. File = open(FileName, OpenFlags, FILE_TEST_CREATE_PERMISSIONS);
  782. if (File < 0) {
  783. PRINT_ERROR("Failed to open file %s (flags %x): %s.\n",
  784. FileName,
  785. OpenFlags,
  786. strerror(errno));
  787. Failures += 1;
  788. continue;
  789. }
  790. Result = lseek(File, Offset, SEEK_SET);
  791. if (Result < 0) {
  792. PRINT_ERROR("Seek on file %s offset %d failed.\n",
  793. FileName,
  794. Offset);
  795. Failures += 1;
  796. }
  797. //
  798. // Reads are tricky as the file can be deleted and recreated by
  799. // other threads. At least validate that if the read succeeded the
  800. // byte should be zero or the low byte of the offset.
  801. //
  802. Value = 0;
  803. do {
  804. BytesComplete = read(File, &Value, 1);
  805. } while ((BytesComplete < 0) && (errno == EINTR));
  806. if (BytesComplete < 0) {
  807. PRINT_ERROR("Read failed. Read %d of 1 bytes: %s.\n",
  808. BytesComplete,
  809. strerror(errno));
  810. Failures += 1;
  811. break;
  812. }
  813. if ((BytesComplete == 1) &&
  814. (Value != 0) && (Value != (Offset & 0xFF))) {
  815. PRINT_ERROR("Error: read of file %s at offset %x turned up "
  816. "%x (should have been %x or 0).\n",
  817. FileName,
  818. Offset,
  819. Value,
  820. Offset & 0xFF);
  821. }
  822. if (close(File) != 0) {
  823. PRINT_ERROR("Failed to close: %s.\n", strerror(errno));
  824. Failures += 1;
  825. }
  826. break;
  827. case FileTestActionDelete:
  828. DEBUG_PRINT("Deleting file %s\n", FileName);
  829. if (unlink(FileName) != 0) {
  830. if (errno != ENOENT) {
  831. PRINT_ERROR("Failed to unlink %s: %s.\n",
  832. FileName,
  833. strerror(errno));
  834. Failures += 1;
  835. }
  836. }
  837. break;
  838. case FileTestActionRename:
  839. //
  840. // Pick a random destination file.
  841. //
  842. DestinationFileIndex = rand() % FileCount;
  843. snprintf(DestinationFileName,
  844. sizeof(DestinationFileName),
  845. "fct-%06x",
  846. DestinationFileIndex);
  847. //
  848. // Rename the current file to the destination file.
  849. //
  850. DEBUG_PRINT("Renaming file %s to %s.\n",
  851. FileName,
  852. DestinationFileName);
  853. if (rename(FileName, DestinationFileName) != 0) {
  854. if (errno != ENOENT) {
  855. PRINT_ERROR("Failed to rename %s to %s: %s.\n",
  856. FileName,
  857. DestinationFileName,
  858. strerror(errno));
  859. Failures += 1;
  860. }
  861. }
  862. break;
  863. default:
  864. assert(FALSE);
  865. break;
  866. }
  867. if ((Iteration % Percent) == 0) {
  868. PRINT("c");
  869. }
  870. }
  871. //
  872. // Clean up. Sure, other threads could still be running the test, but they
  873. // should all clean up too.
  874. //
  875. if (FileTestNoCleanup == FALSE) {
  876. for (FileIndex = 0; FileIndex < FileCount; FileIndex += 1) {
  877. snprintf(FileName,
  878. sizeof(FileName),
  879. "fct-%06x",
  880. FileIndex);
  881. Result = unlink(FileName);
  882. if ((Result != 0) && (errno != ENOENT)) {
  883. PRINT_ERROR("Failed to unlink %s: %s.\n",
  884. FileName,
  885. strerror(errno));
  886. Failures += 1;
  887. }
  888. }
  889. }
  890. PRINT("\n");
  891. Failures += PrintTestTime(&StartTime);
  892. RunFileConcurrencyTestEnd:
  893. return Failures;
  894. }
  895. ULONG
  896. RunFileAppendTest (
  897. INT FileCount,
  898. INT FileSize,
  899. INT Iterations
  900. )
  901. /*++
  902. Routine Description:
  903. This routine executes the file append test.
  904. Arguments:
  905. FileCount - Supplies the number of files to work with.
  906. FileSize - Supplies the size of each file.
  907. Iterations - Supplies the number of iterations to perform.
  908. Return Value:
  909. Returns the number of failures in the test suite.
  910. --*/
  911. {
  912. FILE_TEST_ACTION Action;
  913. ssize_t BytesComplete;
  914. ULONG Failures;
  915. INT File;
  916. INT FileIndex;
  917. CHAR FileName[16];
  918. PINT FileOffset;
  919. INT Iteration;
  920. INT MaxSimultaneousFiles;
  921. LONG Offset;
  922. INT OpenFlags;
  923. INT Percent;
  924. pid_t Process;
  925. INT Result;
  926. INT SimultaneousFiles;
  927. struct timeval StartTime;
  928. INT TotalBytesComplete;
  929. INT Value;
  930. Failures = 0;
  931. FileOffset = NULL;
  932. //
  933. // Record the test start time.
  934. //
  935. Result = gettimeofday(&StartTime, NULL);
  936. if (Result != 0) {
  937. PRINT_ERROR("Failed to get time of day: %s.\n", strerror(errno));
  938. Failures += 1;
  939. goto RunFileAppendTestEnd;
  940. }
  941. //
  942. // Announce the test.
  943. //
  944. Process = getpid();
  945. PRINT("Process %d Running file append test with %d files of %d bytes each. "
  946. "%d iterations.\n",
  947. Process,
  948. FileCount,
  949. FileSize,
  950. Iterations);
  951. Percent = Iterations / 100;
  952. if (Percent == 0) {
  953. Percent = 1;
  954. }
  955. MaxSimultaneousFiles = 0;
  956. SimultaneousFiles = 0;
  957. FileOffset = malloc(FileCount * sizeof(INT));
  958. if (FileOffset == NULL) {
  959. Failures += 1;
  960. goto RunFileAppendTestEnd;
  961. }
  962. for (FileIndex = 0; FileIndex < FileCount; FileIndex += 1) {
  963. FileOffset[FileIndex] = 0;
  964. }
  965. FileSize = ALIGN_RANGE_UP(FileSize, sizeof(INT));
  966. //
  967. // Perform the file operations.
  968. //
  969. for (Iteration = 0; Iteration < Iterations; Iteration += 1) {
  970. //
  971. // Pick a random file and a random action.
  972. //
  973. FileIndex = rand() % FileCount;
  974. snprintf(FileName,
  975. sizeof(FileName),
  976. "fat%x-%06x",
  977. Process & 0xFFFF,
  978. FileIndex);
  979. Action = rand() % FileTestActionRename;
  980. //
  981. // If the file has yet to be created, then the action must be write.
  982. //
  983. if (FileOffset[FileIndex] == 0) {
  984. Action = FileTestActionWrite;
  985. }
  986. //
  987. // If the file shouldn't grow anymore, change writes into reads.
  988. //
  989. if ((FileOffset[FileIndex] > FileSize) &&
  990. (Action == FileTestActionWrite)) {
  991. Action = FileTestActionRead;
  992. }
  993. switch (Action) {
  994. case FileTestActionWrite:
  995. OpenFlags = O_WRONLY | O_APPEND;
  996. if (FileOffset[FileIndex] == 0) {
  997. OpenFlags |= O_CREAT | O_EXCL;
  998. SimultaneousFiles += 1;
  999. if (SimultaneousFiles > MaxSimultaneousFiles) {
  1000. MaxSimultaneousFiles = SimultaneousFiles;
  1001. }
  1002. }
  1003. DEBUG_PRINT("Writing file %s, Value %x\n",
  1004. FileName,
  1005. FileOffset[FileIndex]);
  1006. File = open(FileName, OpenFlags, FILE_TEST_CREATE_PERMISSIONS);
  1007. if (File < 0) {
  1008. PRINT_ERROR("Failed to open file %s (flags %x): %s.\n",
  1009. FileName,
  1010. OpenFlags,
  1011. strerror(errno));
  1012. Failures += 1;
  1013. continue;
  1014. }
  1015. //
  1016. // Seek somewhere to try and throw it off.
  1017. //
  1018. Result = lseek(File, rand(), SEEK_SET);
  1019. if (Result < 0) {
  1020. PRINT_ERROR("Seek failed. Result %d: %s.\n",
  1021. Result,
  1022. strerror(errno));
  1023. Failures += 1;
  1024. }
  1025. Value = FileOffset[FileIndex];
  1026. FileOffset[FileIndex] += 1;
  1027. do {
  1028. BytesComplete = write(File, &Value, sizeof(INT));
  1029. } while ((BytesComplete < 0) && (errno == EINTR));
  1030. if (BytesComplete != sizeof(INT)) {
  1031. PRINT_ERROR("Write failed. Wrote %d of %d bytes: %s.\n",
  1032. BytesComplete,
  1033. sizeof(INT),
  1034. strerror(errno));
  1035. Failures += 1;
  1036. }
  1037. if (close(File) != 0) {
  1038. PRINT_ERROR("Failed to close: %s.\n", strerror(errno));
  1039. Failures += 1;
  1040. }
  1041. break;
  1042. case FileTestActionRead:
  1043. if (FileOffset[FileIndex] == 0) {
  1044. DEBUG_PRINT("Skipping read from empty file %s.\n", FileName);
  1045. continue;
  1046. }
  1047. Offset = (rand() % FileOffset[FileIndex]) * sizeof(INT);
  1048. DEBUG_PRINT("Reading file %s offset %x, Value should be %x\n",
  1049. FileName,
  1050. Offset,
  1051. Offset / sizeof(INT));
  1052. OpenFlags = O_RDONLY;
  1053. if ((rand() & 0x1) != 0) {
  1054. OpenFlags = O_RDWR;
  1055. }
  1056. File = open(FileName, OpenFlags);
  1057. if (File < 0) {
  1058. PRINT_ERROR("Failed to open file %s (flags %x): %s.\n",
  1059. FileName,
  1060. OpenFlags,
  1061. strerror(errno));
  1062. Failures += 1;
  1063. continue;
  1064. }
  1065. Result = lseek(File, Offset, SEEK_SET);
  1066. if (Result < 0) {
  1067. PRINT_ERROR("Seek failed. Result %d: %s.\n",
  1068. Result,
  1069. strerror(errno));
  1070. Failures += 1;
  1071. }
  1072. Value = 0;
  1073. TotalBytesComplete = 0;
  1074. while (TotalBytesComplete < sizeof(INT)) {
  1075. do {
  1076. BytesComplete = read(File,
  1077. (PVOID)(&Value) + TotalBytesComplete,
  1078. sizeof(INT) - TotalBytesComplete);
  1079. } while ((BytesComplete < 0) && (errno == EINTR));
  1080. if (BytesComplete <= 0) {
  1081. PRINT_ERROR("Read failed. Read %d (%d total) of "
  1082. "%d bytes: %s.\n",
  1083. BytesComplete,
  1084. TotalBytesComplete,
  1085. sizeof(INT),
  1086. strerror(errno));
  1087. Failures += 1;
  1088. break;
  1089. }
  1090. TotalBytesComplete += BytesComplete;
  1091. }
  1092. if (Value != (Offset / sizeof(INT))) {
  1093. PRINT_ERROR("Read append data file %s offset %x came back %x, "
  1094. "should have been %x.\n",
  1095. FileName,
  1096. Offset,
  1097. Value,
  1098. Offset / sizeof(INT));
  1099. Failures += 1;
  1100. }
  1101. if (close(File) != 0) {
  1102. PRINT_ERROR("Failed to close: %s.\n", strerror(errno));
  1103. Failures += 1;
  1104. }
  1105. break;
  1106. case FileTestActionDelete:
  1107. DEBUG_PRINT("Deleting file %s\n", FileName);
  1108. if (unlink(FileName) != 0) {
  1109. PRINT_ERROR("Failed to unlink %s: %s.\n",
  1110. FileName,
  1111. strerror(errno));
  1112. Failures += 1;
  1113. }
  1114. FileOffset[FileIndex] = 0;
  1115. SimultaneousFiles -= 1;
  1116. break;
  1117. default:
  1118. assert(FALSE);
  1119. break;
  1120. }
  1121. if ((Iteration % Percent) == 0) {
  1122. PRINT("a");
  1123. }
  1124. }
  1125. //
  1126. // Clean up all files.
  1127. //
  1128. if (FileTestNoCleanup == FALSE) {
  1129. for (FileIndex = 0; FileIndex < FileCount; FileIndex += 1) {
  1130. if (FileOffset[FileIndex] != 0) {
  1131. snprintf(FileName,
  1132. sizeof(FileName),
  1133. "fat%x-%06x",
  1134. Process & 0xFFFF,
  1135. FileIndex);
  1136. if (unlink(FileName) != 0) {
  1137. PRINT_ERROR("Failed to unlink %s: %s.\n",
  1138. FileName,
  1139. strerror(errno));
  1140. Failures += 1;
  1141. }
  1142. }
  1143. }
  1144. }
  1145. PRINT("\nMax usage: %d files, %I64d bytes.\n",
  1146. MaxSimultaneousFiles,
  1147. (ULONGLONG)MaxSimultaneousFiles * (ULONGLONG)FileSize);
  1148. Failures += PrintTestTime(&StartTime);
  1149. RunFileAppendTestEnd:
  1150. if (FileOffset != NULL) {
  1151. free(FileOffset);
  1152. }
  1153. return Failures;
  1154. }
  1155. ULONG
  1156. RunFileSeekTest (
  1157. INT BlockCount,
  1158. INT BlockSize,
  1159. INT Iterations
  1160. )
  1161. /*++
  1162. Routine Description:
  1163. This routine executes the file seek test.
  1164. Arguments:
  1165. BlockCount - Supplies the number of blocks to play with in the file.
  1166. BlockSize - Supplies the size of each block.
  1167. Iterations - Supplies the number of iterations to perform.
  1168. Return Value:
  1169. Returns the number of failures in the test suite.
  1170. --*/
  1171. {
  1172. FILE_TEST_ACTION Action;
  1173. INT BlockErrorCount;
  1174. INT BlockIndex;
  1175. ssize_t BytesComplete;
  1176. ULONG Failures;
  1177. INT File;
  1178. PINT FileBuffer;
  1179. CHAR FileName[10];
  1180. PINT FileOffset;
  1181. INT FillIndex;
  1182. INT Iteration;
  1183. INT MaxBlock;
  1184. INT OpenFlags;
  1185. INT Percent;
  1186. pid_t Process;
  1187. INT Result;
  1188. struct timeval StartTime;
  1189. INT TotalBytesComplete;
  1190. Failures = 0;
  1191. FileBuffer = NULL;
  1192. FileOffset = NULL;
  1193. //
  1194. // Record the test start time.
  1195. //
  1196. Result = gettimeofday(&StartTime, NULL);
  1197. if (Result != 0) {
  1198. PRINT_ERROR("Failed to get time of day: %s.\n", strerror(errno));
  1199. Failures += 1;
  1200. goto RunFileSeekTestEnd;
  1201. }
  1202. //
  1203. // Announce the test.
  1204. //
  1205. Process = getpid();
  1206. PRINT("Process %d Running file seek test with %d blocks of %d bytes each. "
  1207. "%d iterations.\n",
  1208. Process,
  1209. BlockCount,
  1210. BlockSize,
  1211. Iterations);
  1212. Percent = Iterations / 100;
  1213. if (Percent == 0) {
  1214. Percent = 1;
  1215. }
  1216. MaxBlock = -1;
  1217. FileOffset = malloc(BlockCount * sizeof(INT));
  1218. if (FileOffset == NULL) {
  1219. Failures += 1;
  1220. goto RunFileSeekTestEnd;
  1221. }
  1222. for (BlockIndex = 0; BlockIndex < BlockCount; BlockIndex += 1) {
  1223. FileOffset[BlockIndex] = -1;
  1224. }
  1225. BlockSize = ALIGN_RANGE_UP(BlockSize, sizeof(INT));
  1226. FileBuffer = malloc(BlockSize);
  1227. if (FileBuffer == NULL) {
  1228. Failures += 1;
  1229. goto RunFileSeekTestEnd;
  1230. }
  1231. //
  1232. // Open up the file.
  1233. //
  1234. snprintf(FileName, sizeof(FileName), "ft%x", Process & 0xFFFF);
  1235. OpenFlags = O_RDWR | O_CREAT | O_TRUNC;
  1236. File = open(FileName, OpenFlags, FILE_TEST_CREATE_PERMISSIONS);
  1237. if (File < 0) {
  1238. PRINT_ERROR("Failed to open file %s (flags %x): %s.\n",
  1239. FileName,
  1240. OpenFlags,
  1241. strerror(errno));
  1242. Failures += 1;
  1243. goto RunFileSeekTestEnd;
  1244. }
  1245. //
  1246. // Perform the file operations.
  1247. //
  1248. for (Iteration = 0; Iteration < Iterations; Iteration += 1) {
  1249. //
  1250. // Pick a random block and a random action.
  1251. //
  1252. BlockIndex = rand() % BlockCount;
  1253. Action = rand() % FileTestActionDelete;
  1254. //
  1255. // A read beyond the end of the file so far won't work, so change it
  1256. // into a write.
  1257. //
  1258. if ((Action == FileTestActionRead) && (BlockIndex > MaxBlock)) {
  1259. Action = FileTestActionWrite;
  1260. }
  1261. //
  1262. // Seek to the right spot.
  1263. //
  1264. Result = lseek(File,
  1265. (ULONGLONG)BlockIndex * (ULONGLONG)BlockSize,
  1266. SEEK_SET);
  1267. if (Result < 0) {
  1268. PRINT_ERROR("Failed to seek to offset %I64x: %s.\n",
  1269. (ULONGLONG)BlockIndex * (ULONGLONG)BlockSize,
  1270. strerror(errno));
  1271. Failures += 1;
  1272. FileOffset[BlockIndex] = -1;
  1273. continue;
  1274. }
  1275. switch (Action) {
  1276. case FileTestActionWrite:
  1277. if (FileOffset[BlockIndex] == -1) {
  1278. if (MaxBlock < BlockIndex) {
  1279. MaxBlock = BlockIndex;
  1280. }
  1281. }
  1282. FileOffset[BlockIndex] = rand();
  1283. DEBUG_PRINT("Writing block %d, Value %x\n",
  1284. BlockIndex,
  1285. FileOffset[BlockIndex]);
  1286. for (FillIndex = 0;
  1287. FillIndex < BlockSize / sizeof(INT);
  1288. FillIndex += 1) {
  1289. FileBuffer[FillIndex] = FileOffset[BlockIndex] + FillIndex;
  1290. }
  1291. do {
  1292. BytesComplete = write(File, FileBuffer, BlockSize);
  1293. } while ((BytesComplete < 0) && (errno == EINTR));
  1294. if (BytesComplete != BlockSize) {
  1295. PRINT_ERROR("Write failed. Wrote %d of %d bytes: %s.\n",
  1296. BytesComplete,
  1297. BlockSize,
  1298. strerror(errno));
  1299. Failures += 1;
  1300. }
  1301. break;
  1302. case FileTestActionRead:
  1303. DEBUG_PRINT("Reading block %d, Value should be %x\n",
  1304. BlockIndex,
  1305. FileOffset[BlockIndex]);
  1306. for (FillIndex = 0;
  1307. FillIndex < BlockSize / sizeof(INT);
  1308. FillIndex += 1) {
  1309. FileBuffer[FillIndex] = 0xFEEEF00D;
  1310. }
  1311. TotalBytesComplete = 0;
  1312. while (TotalBytesComplete < BlockSize) {
  1313. do {
  1314. BytesComplete = read(File,
  1315. FileBuffer + TotalBytesComplete,
  1316. BlockSize - TotalBytesComplete);
  1317. } while ((BytesComplete < 0) && (errno == EINTR));
  1318. if (BytesComplete <= 0) {
  1319. PRINT_ERROR("Read failed. Read %d (%d total) of "
  1320. "%d bytes: %s.\n",
  1321. BytesComplete,
  1322. TotalBytesComplete,
  1323. BlockSize,
  1324. strerror(errno));
  1325. Failures += 1;
  1326. break;
  1327. }
  1328. TotalBytesComplete += BytesComplete;
  1329. }
  1330. BlockErrorCount = 0;
  1331. for (FillIndex = 0;
  1332. FillIndex < BlockSize / sizeof(INT);
  1333. FillIndex += 1) {
  1334. //
  1335. // If the file was never written before, it should be all
  1336. // zeroes.
  1337. //
  1338. if (FileOffset[BlockIndex] == -1) {
  1339. if (FileBuffer[FillIndex] != 0) {
  1340. PRINT_ERROR("Read data block %d index %x came back %x, "
  1341. "should have been zero.\n",
  1342. BlockIndex,
  1343. FillIndex,
  1344. FileBuffer[FillIndex]);
  1345. Failures += 1;
  1346. BlockErrorCount += 1;
  1347. }
  1348. //
  1349. // If the file was written before, validate that the data is
  1350. // still there and correct.
  1351. //
  1352. } else if (FileBuffer[FillIndex] !=
  1353. FileOffset[BlockIndex] + FillIndex) {
  1354. PRINT_ERROR("Read data block %d index %x came back %x, "
  1355. "should have been %x.\n",
  1356. BlockIndex,
  1357. FillIndex,
  1358. FileBuffer[FillIndex],
  1359. FileOffset[BlockIndex] + FillIndex);
  1360. Failures += 1;
  1361. BlockErrorCount += 1;
  1362. }
  1363. if (BlockErrorCount > 15) {
  1364. PRINT_ERROR("...you get the idea...\n");
  1365. break;
  1366. }
  1367. }
  1368. break;
  1369. default:
  1370. assert(FALSE);
  1371. break;
  1372. }
  1373. if ((Iteration % Percent) == 0) {
  1374. PRINT("s");
  1375. }
  1376. }
  1377. if (FileTestNoCleanup == FALSE) {
  1378. DEBUG_PRINT("Deleting file %s\n", FileName);
  1379. if (unlink(FileName) != 0) {
  1380. PRINT_ERROR("Failed to unlink %s: %s.\n",
  1381. FileName,
  1382. strerror(errno));
  1383. Failures += 1;
  1384. }
  1385. }
  1386. if (close(File) != 0) {
  1387. PRINT_ERROR("Failed to close: %s.\n", strerror(errno));
  1388. Failures += 1;
  1389. }
  1390. PRINT("\nMax block: %d, %I64d bytes.\n",
  1391. MaxBlock,
  1392. (ULONGLONG)MaxBlock * (ULONGLONG)BlockSize);
  1393. Failures += PrintTestTime(&StartTime);
  1394. RunFileSeekTestEnd:
  1395. if (FileOffset != NULL) {
  1396. free(FileOffset);
  1397. }
  1398. if (FileBuffer != NULL) {
  1399. free(FileBuffer);
  1400. }
  1401. return Failures;
  1402. }
  1403. ULONG
  1404. RunStreamSeekTest (
  1405. INT BlockCount,
  1406. INT BlockSize,
  1407. INT Iterations
  1408. )
  1409. /*++
  1410. Routine Description:
  1411. This routine executes the stream seek test, which is the same as the file
  1412. seek test except it uses streams instead of raw file descriptors..
  1413. Arguments:
  1414. BlockCount - Supplies the number of blocks to play with in the file.
  1415. BlockSize - Supplies the size of each block.
  1416. Iterations - Supplies the number of iterations to perform.
  1417. Return Value:
  1418. Returns the number of failures in the test suite.
  1419. --*/
  1420. {
  1421. FILE_TEST_ACTION Action;
  1422. INT BlockErrorCount;
  1423. INT BlockIndex;
  1424. ssize_t BytesComplete;
  1425. ULONG Failures;
  1426. FILE *File;
  1427. PINT FileBuffer;
  1428. CHAR FileName[10];
  1429. PINT FileOffset;
  1430. INT FillIndex;
  1431. INT Iteration;
  1432. INT MaxBlock;
  1433. INT Percent;
  1434. pid_t Process;
  1435. INT Result;
  1436. struct timeval StartTime;
  1437. INT TotalBytesComplete;
  1438. Failures = 0;
  1439. FileBuffer = NULL;
  1440. FileOffset = NULL;
  1441. //
  1442. // Record the test start time.
  1443. //
  1444. Result = gettimeofday(&StartTime, NULL);
  1445. if (Result != 0) {
  1446. PRINT_ERROR("Failed to get time of day: %s.\n", strerror(errno));
  1447. Failures += 1;
  1448. goto RunStreamSeekTestEnd;
  1449. }
  1450. //
  1451. // Announce the test.
  1452. //
  1453. Process = getpid();
  1454. PRINT("Process %d Running stream seek test with %d blocks of %d bytes "
  1455. "each. %d iterations.\n",
  1456. Process,
  1457. BlockCount,
  1458. BlockSize,
  1459. Iterations);
  1460. Percent = Iterations / 100;
  1461. if (Percent == 0) {
  1462. Percent = 1;
  1463. }
  1464. MaxBlock = -1;
  1465. FileOffset = malloc(BlockCount * sizeof(INT));
  1466. if (FileOffset == NULL) {
  1467. Failures += 1;
  1468. goto RunStreamSeekTestEnd;
  1469. }
  1470. for (BlockIndex = 0; BlockIndex < BlockCount; BlockIndex += 1) {
  1471. FileOffset[BlockIndex] = -1;
  1472. }
  1473. BlockSize = ALIGN_RANGE_UP(BlockSize, sizeof(INT));
  1474. FileBuffer = malloc(BlockSize);
  1475. if (FileBuffer == NULL) {
  1476. Failures += 1;
  1477. goto RunStreamSeekTestEnd;
  1478. }
  1479. //
  1480. // Open up the file.
  1481. //
  1482. snprintf(FileName, sizeof(FileName), "st%x", Process & 0xFFFF);
  1483. File = fopen(FileName, "w+");
  1484. if (File == NULL) {
  1485. PRINT_ERROR("Failed to open file %s (mode %s): %s.\n",
  1486. FileName,
  1487. "w+",
  1488. strerror(errno));
  1489. Failures += 1;
  1490. goto RunStreamSeekTestEnd;
  1491. }
  1492. //
  1493. // Perform the file operations.
  1494. //
  1495. for (Iteration = 0; Iteration < Iterations; Iteration += 1) {
  1496. //
  1497. // Pick a random block and a random action.
  1498. //
  1499. BlockIndex = rand() % BlockCount;
  1500. Action = rand() % FileTestActionDelete;
  1501. //
  1502. // A read beyond the end of the file so far won't work, so change it
  1503. // into a write.
  1504. //
  1505. if ((Action == FileTestActionRead) && (BlockIndex > MaxBlock)) {
  1506. Action = FileTestActionWrite;
  1507. }
  1508. //
  1509. // Seek to the right spot.
  1510. //
  1511. Result = fseeko64(File,
  1512. (ULONGLONG)BlockIndex * (ULONGLONG)BlockSize,
  1513. SEEK_SET);
  1514. if (Result < 0) {
  1515. PRINT_ERROR("Failed to seek to offset %I64x: %s.\n",
  1516. (ULONGLONG)BlockIndex * (ULONGLONG)BlockSize,
  1517. strerror(errno));
  1518. Failures += 1;
  1519. FileOffset[BlockIndex] = -1;
  1520. continue;
  1521. }
  1522. switch (Action) {
  1523. case FileTestActionWrite:
  1524. if (FileOffset[BlockIndex] == -1) {
  1525. if (MaxBlock < BlockIndex) {
  1526. MaxBlock = BlockIndex;
  1527. }
  1528. }
  1529. FileOffset[BlockIndex] = rand();
  1530. DEBUG_PRINT("Writing block %d, Value %x\n",
  1531. BlockIndex,
  1532. FileOffset[BlockIndex]);
  1533. for (FillIndex = 0;
  1534. FillIndex < BlockSize / sizeof(INT);
  1535. FillIndex += 1) {
  1536. FileBuffer[FillIndex] = FileOffset[BlockIndex] + FillIndex;
  1537. }
  1538. BytesComplete = fwrite(FileBuffer, 1, BlockSize, File);
  1539. if (BytesComplete != BlockSize) {
  1540. PRINT_ERROR("Write failed. Wrote %d of %d bytes: %s.\n",
  1541. BytesComplete,
  1542. BlockSize,
  1543. strerror(errno));
  1544. Failures += 1;
  1545. }
  1546. break;
  1547. case FileTestActionRead:
  1548. DEBUG_PRINT("Reading block %d, Value should be %x\n",
  1549. BlockIndex,
  1550. FileOffset[BlockIndex]);
  1551. for (FillIndex = 0;
  1552. FillIndex < BlockSize / sizeof(INT);
  1553. FillIndex += 1) {
  1554. FileBuffer[FillIndex] = 0xFEEEF00D;
  1555. }
  1556. TotalBytesComplete = 0;
  1557. while (TotalBytesComplete < BlockSize) {
  1558. BytesComplete = fread(FileBuffer + TotalBytesComplete,
  1559. 1,
  1560. BlockSize - TotalBytesComplete,
  1561. File);
  1562. if (BytesComplete <= 0) {
  1563. PRINT_ERROR("Read failed. Read %d (%d total) of "
  1564. "%d bytes: %s.\n",
  1565. BytesComplete,
  1566. TotalBytesComplete,
  1567. BlockSize,
  1568. strerror(errno));
  1569. Failures += 1;
  1570. break;
  1571. }
  1572. TotalBytesComplete += BytesComplete;
  1573. }
  1574. BlockErrorCount = 0;
  1575. for (FillIndex = 0;
  1576. FillIndex < BlockSize / sizeof(INT);
  1577. FillIndex += 1) {
  1578. //
  1579. // If the file was never written before, it should be all
  1580. // zeroes.
  1581. //
  1582. if (FileOffset[BlockIndex] == -1) {
  1583. if (FileBuffer[FillIndex] != 0) {
  1584. PRINT_ERROR("Read data block %d index %x came back %x, "
  1585. "should have been zero.\n",
  1586. BlockIndex,
  1587. FillIndex,
  1588. FileBuffer[FillIndex]);
  1589. Failures += 1;
  1590. BlockErrorCount += 1;
  1591. }
  1592. //
  1593. // If the file was written before, validate that the data is
  1594. // still there and correct.
  1595. //
  1596. } else if (FileBuffer[FillIndex] !=
  1597. FileOffset[BlockIndex] + FillIndex) {
  1598. PRINT_ERROR("Read data block %d index %x came back %x, "
  1599. "should have been %x.\n",
  1600. BlockIndex,
  1601. FillIndex,
  1602. FileBuffer[FillIndex],
  1603. FileOffset[BlockIndex] + FillIndex);
  1604. Failures += 1;
  1605. BlockErrorCount += 1;
  1606. }
  1607. if (BlockErrorCount > 15) {
  1608. PRINT_ERROR("...you get the idea...\n");
  1609. break;
  1610. }
  1611. }
  1612. break;
  1613. default:
  1614. assert(FALSE);
  1615. break;
  1616. }
  1617. if ((Iteration % Percent) == 0) {
  1618. PRINT("S");
  1619. }
  1620. }
  1621. if (FileTestNoCleanup == FALSE) {
  1622. DEBUG_PRINT("Deleting file %s\n", FileName);
  1623. if (unlink(FileName) != 0) {
  1624. PRINT_ERROR("Failed to unlink %s: %s.\n",
  1625. FileName,
  1626. strerror(errno));
  1627. Failures += 1;
  1628. }
  1629. }
  1630. if (fclose(File) != 0) {
  1631. PRINT_ERROR("Failed to close: %s.\n", strerror(errno));
  1632. Failures += 1;
  1633. }
  1634. PRINT("\nMax block: %d, %I64d bytes.\n",
  1635. MaxBlock,
  1636. (ULONGLONG)MaxBlock * (ULONGLONG)BlockSize);
  1637. Failures += PrintTestTime(&StartTime);
  1638. RunStreamSeekTestEnd:
  1639. if (FileOffset != NULL) {
  1640. free(FileOffset);
  1641. }
  1642. if (FileBuffer != NULL) {
  1643. free(FileBuffer);
  1644. }
  1645. return Failures;
  1646. }
  1647. ULONG
  1648. RunFileUninitializedDataTest (
  1649. INT FileCount,
  1650. INT FileSize,
  1651. INT Iterations
  1652. )
  1653. /*++
  1654. Routine Description:
  1655. This routine executes the file uninitialized data test.
  1656. Arguments:
  1657. FileCount - Supplies the number of files to work with.
  1658. FileSize - Supplies the size of each file.
  1659. Iterations - Supplies the number of iterations to perform.
  1660. Return Value:
  1661. Returns the number of failures in the test suite.
  1662. --*/
  1663. {
  1664. size_t ArraySize;
  1665. ssize_t BytesComplete;
  1666. INT Expected;
  1667. ULONG Failures;
  1668. INT File;
  1669. INT FileIndex;
  1670. CHAR FileName[16];
  1671. PBYTE *FileState;
  1672. INT Iteration;
  1673. ULONGLONG Offset;
  1674. INT OpenFlags;
  1675. INT Percent;
  1676. pid_t Process;
  1677. INT Result;
  1678. off_t ResultOffset;
  1679. INT Seek;
  1680. struct timeval StartTime;
  1681. PCHAR UninitializedDataBuffer;
  1682. INT UninitializedDataSize;
  1683. INT Value;
  1684. Failures = 0;
  1685. FileState = NULL;
  1686. UninitializedDataBuffer = NULL;
  1687. //
  1688. // Record the test start time.
  1689. //
  1690. Result = gettimeofday(&StartTime, NULL);
  1691. if (Result != 0) {
  1692. PRINT_ERROR("Failed to get time of day: %s.\n", strerror(errno));
  1693. Failures += 1;
  1694. goto RunFileUninitializedDataTestEnd;
  1695. }
  1696. //
  1697. // Announce the test.
  1698. //
  1699. Process = getpid();
  1700. PRINT("Process %d Running file uninitialized data test with %d files of "
  1701. "%d bytes each. %d iterations.\n",
  1702. Process,
  1703. FileCount,
  1704. FileSize,
  1705. Iterations);
  1706. Percent = Iterations / 100;
  1707. if (Percent == 0) {
  1708. Percent = 1;
  1709. }
  1710. FileSize = ALIGN_RANGE_UP(FileSize, sizeof(INT));
  1711. //
  1712. // Before starting this test, create a big file with distinct byte pattern
  1713. // and flush it to disk and then delete it. After this any clusters
  1714. // allocated by the test will have the pattern in the unmodified portions.
  1715. // If the system is working correctly, this pattern should never be read.
  1716. //
  1717. PRINT("Scribbling the pattern 0x%x over the disk.\n",
  1718. UNINITIALIZED_DATA_PATTERN);
  1719. UninitializedDataSize = FileSize * FileCount;
  1720. UninitializedDataBuffer = malloc(UninitializedDataSize);
  1721. if (UninitializedDataBuffer == NULL) {
  1722. Failures += 1;
  1723. goto RunFileUninitializedDataTestEnd;
  1724. }
  1725. for (FileIndex = 0; FileIndex < UninitializedDataSize; FileIndex += 1) {
  1726. UninitializedDataBuffer[FileIndex] = (CHAR)UNINITIALIZED_DATA_PATTERN;
  1727. }
  1728. snprintf(FileName, sizeof(FileName), "fudt-init%x", Process & 0xFFFF);
  1729. OpenFlags = O_WRONLY | O_CREAT;
  1730. File = open(FileName, OpenFlags, FILE_TEST_CREATE_PERMISSIONS);
  1731. if (File < 0) {
  1732. PRINT_ERROR("Filed to open file %s (flags %x): %s.\n",
  1733. FileName,
  1734. OpenFlags,
  1735. strerror(errno));
  1736. Failures += 1;
  1737. goto RunFileUninitializedDataTestEnd;
  1738. }
  1739. DEBUG_PRINT("Writing file %s\n", FileName);
  1740. do {
  1741. BytesComplete = write(File,
  1742. UninitializedDataBuffer,
  1743. UninitializedDataSize);
  1744. } while ((BytesComplete < 0) && (errno == EINTR));
  1745. if (BytesComplete != UninitializedDataSize) {
  1746. PRINT_ERROR("Write to %s failed. Wrote %d of %d bytes: %s.\n",
  1747. FileName,
  1748. BytesComplete,
  1749. UninitializedDataSize,
  1750. strerror(errno));
  1751. Failures += 1;
  1752. goto RunFileUninitializedDataTestEnd;
  1753. }
  1754. //
  1755. // Now flush the file to make sure the bytes make it to disk.
  1756. //
  1757. DEBUG_PRINT("Flushing file %s\n", FileName);
  1758. Result = fsync(File);
  1759. if (Result < 0) {
  1760. PRINT_ERROR("Flush of %s failed: %s.\n", FileName, strerror(errno));
  1761. Failures += 1;
  1762. goto RunFileUninitializedDataTestEnd;
  1763. }
  1764. //
  1765. // Close, truncate and unlink the file to free up the clusters.
  1766. //
  1767. DEBUG_PRINT("Closing file %s\n", FileName);
  1768. if (close(File) != 0) {
  1769. PRINT_ERROR("Failed to close: %s.\n", strerror(errno));
  1770. Failures += 1;
  1771. goto RunFileUninitializedDataTestEnd;
  1772. }
  1773. DEBUG_PRINT("Opening file for truncate %s\n", FileName);
  1774. OpenFlags = O_TRUNC;
  1775. File = open(FileName, OpenFlags, FILE_TEST_CREATE_PERMISSIONS);
  1776. if (File < 0) {
  1777. PRINT_ERROR("Failed to open file %s for truncate: %s.\n",
  1778. FileName,
  1779. strerror(errno));
  1780. Failures += 1;
  1781. goto RunFileUninitializedDataTestEnd;
  1782. }
  1783. DEBUG_PRINT("Closing file %s\n", FileName);
  1784. if (close(File) != 0) {
  1785. PRINT_ERROR("Failed to close: %s.\n", strerror(errno));
  1786. Failures += 1;
  1787. goto RunFileUninitializedDataTestEnd;
  1788. }
  1789. DEBUG_PRINT("Deleting file %s\n", FileName);
  1790. Result = unlink(FileName);
  1791. if (Result != 0) {
  1792. PRINT_ERROR("Failed to unlink %s: %s.\n",
  1793. FileName,
  1794. strerror(errno));
  1795. Failures += 1;
  1796. goto RunFileUninitializedDataTestEnd;
  1797. }
  1798. //
  1799. // Create an array to hold the expected state for each file.
  1800. //
  1801. FileState = malloc(FileCount * sizeof(PBYTE));
  1802. if (FileState == NULL) {
  1803. Failures += 1;
  1804. goto RunFileUninitializedDataTestEnd;
  1805. }
  1806. memset(FileState, 0, FileCount * sizeof(PBYTE));
  1807. //
  1808. // Perform the file operations.
  1809. //
  1810. PRINT("Starting tests.\n");
  1811. for (Iteration = 0; Iteration < Iterations; Iteration += 1) {
  1812. //
  1813. // Pick a random file and a random action.
  1814. //
  1815. FileIndex = rand() % FileCount;
  1816. snprintf(FileName,
  1817. sizeof(FileName),
  1818. "fudt%x-%06x",
  1819. Process & 0xFFFF,
  1820. FileIndex);
  1821. //
  1822. // If the file is yet to be created, then write to the first byte and
  1823. // the last byte and do some flushes to make sure partial pages are
  1824. // handled correctly.
  1825. //
  1826. if (FileState[FileIndex] == 0) {
  1827. ArraySize = FileSize + UNINITIALIZED_DATA_SEEK_MAX + 1;
  1828. FileState[FileIndex] = malloc(ArraySize);
  1829. memset(FileState[FileIndex], 0, ArraySize);
  1830. OpenFlags = O_RDWR | O_CREAT;
  1831. File = open(FileName, OpenFlags, FILE_TEST_CREATE_PERMISSIONS);
  1832. if (File < 0) {
  1833. PRINT_ERROR("Failed to open file %s (flags %x): %s.\n",
  1834. FileName,
  1835. OpenFlags,
  1836. strerror(errno));
  1837. Failures += 1;
  1838. continue;
  1839. }
  1840. //
  1841. // Write the first byte of the file and flush it.
  1842. //
  1843. Offset = 0;
  1844. Result = lseek(File, Offset, SEEK_SET);
  1845. if (Result < 0) {
  1846. PRINT_ERROR("Seek on file %s offset 0x%I64x failed.\n",
  1847. FileName,
  1848. Offset);
  1849. Failures += 1;
  1850. }
  1851. DEBUG_PRINT("Writing file %s, Offset 0x%I64x\n", FileName, Offset);
  1852. do {
  1853. BytesComplete = write(File, &Offset, 1);
  1854. } while ((BytesComplete < 0) && (errno == EINTR));
  1855. if (BytesComplete != 1) {
  1856. PRINT_ERROR("Write failed. Wrote %d of %d bytes: %s.\n",
  1857. BytesComplete,
  1858. FileSize,
  1859. strerror(errno));
  1860. Failures += 1;
  1861. }
  1862. FileState[FileIndex][Offset] = 1;
  1863. DEBUG_PRINT("Flushing file %s\n", FileName);
  1864. Result = fsync(File);
  1865. if (Result < 0) {
  1866. PRINT_ERROR("Flush of %s failed: %s.\n", FileName,
  1867. strerror(errno));
  1868. Failures += 1;
  1869. goto RunFileUninitializedDataTestEnd;
  1870. }
  1871. //
  1872. // Write the second byte of the file and the last byte and then
  1873. // flush it.
  1874. //
  1875. Offset = 2;
  1876. Result = lseek(File, Offset, SEEK_SET);
  1877. if (Result < 0) {
  1878. PRINT_ERROR("Seek on file %s offset 0x%I64x failed.\n",
  1879. FileName,
  1880. Offset);
  1881. Failures += 1;
  1882. }
  1883. DEBUG_PRINT("Writing file %s, Offset 0x%I64x\n", FileName, Offset);
  1884. do {
  1885. BytesComplete = write(File, &Offset, 1);
  1886. } while ((BytesComplete < 0) && (errno == EINTR));
  1887. if (BytesComplete != 1) {
  1888. PRINT_ERROR("Write failed. Wrote %d of %d bytes: %s.\n",
  1889. BytesComplete,
  1890. FileSize,
  1891. strerror(errno));
  1892. Failures += 1;
  1893. }
  1894. FileState[FileIndex][Offset] = 1;
  1895. Offset = FileSize - 1;
  1896. Result = lseek(File, Offset, SEEK_SET);
  1897. if (Result < 0) {
  1898. PRINT_ERROR("Seek on file %s offset 0x%I64x failed.\n",
  1899. FileName,
  1900. Offset);
  1901. Failures += 1;
  1902. }
  1903. DEBUG_PRINT("Writing file %s, Offset 0x%I64x\n", FileName, Offset);
  1904. do {
  1905. BytesComplete = write(File, &Offset, 1);
  1906. } while ((BytesComplete < 0) && (errno == EINTR));
  1907. if (BytesComplete != 1) {
  1908. PRINT_ERROR("Write failed. Wrote %d of %d bytes: %s.\n",
  1909. BytesComplete,
  1910. FileSize,
  1911. strerror(errno));
  1912. Failures += 1;
  1913. }
  1914. FileState[FileIndex][Offset] = 1;
  1915. DEBUG_PRINT("Flushing file %s\n", FileName);
  1916. Result = fsync(File);
  1917. if (Result < 0) {
  1918. PRINT_ERROR("Flush of %s failed: %s.\n", FileName,
  1919. strerror(errno));
  1920. Failures += 1;
  1921. goto RunFileUninitializedDataTestEnd;
  1922. }
  1923. //
  1924. // Now read the second byte again. Flushing out the last byte of
  1925. // the file should not have zero'd out the remainder of the first
  1926. // page. This read is here to make sure things are correct.
  1927. //
  1928. Offset = 2;
  1929. Result = lseek(File, Offset, SEEK_SET);
  1930. if (Result < 0) {
  1931. PRINT_ERROR("Seek on file %s offset 0x%I64x failed.\n",
  1932. FileName,
  1933. Offset);
  1934. Failures += 1;
  1935. }
  1936. Value = 0;
  1937. DEBUG_PRINT("Reading file %s, Offset 0x%I64x\n", FileName, Offset);
  1938. do {
  1939. BytesComplete = read(File, &Value, 1);
  1940. } while ((BytesComplete < 0) && (errno == EINTR));
  1941. if (BytesComplete < 0) {
  1942. PRINT_ERROR("Read failed. Read %d of 1 bytes: %s.\n",
  1943. BytesComplete,
  1944. strerror(errno));
  1945. Failures += 1;
  1946. break;
  1947. }
  1948. if ((BytesComplete == 1) &&
  1949. (((FileState[FileIndex][Offset] == 0) && (Value != 0)) ||
  1950. ((FileState[FileIndex][Offset] == 1) &&
  1951. (Value != (Offset & 0xFF))))) {
  1952. PRINT_ERROR("Error: initial read of file %s at offset 0x%I64x "
  1953. "turned up %x (should have been %x or 0).\n",
  1954. FileName,
  1955. Offset,
  1956. Value,
  1957. Offset & 0xFF);
  1958. }
  1959. FileState[FileIndex][Offset] = 1;
  1960. if (close(File) != 0) {
  1961. PRINT_ERROR("Failed to close: %s.\n", strerror(errno));
  1962. Failures += 1;
  1963. }
  1964. }
  1965. //
  1966. // Picks a random spot and writes a byte. Then read a few bytes after
  1967. // that to make sure the expected value is there.
  1968. //
  1969. Offset = rand() % FileSize;
  1970. if ((Offset & 0xFF) == UNINITIALIZED_DATA_PATTERN) {
  1971. Offset += 1;
  1972. }
  1973. DEBUG_PRINT("Writing file %s, Offset 0x%I64x\n", FileName, Offset);
  1974. OpenFlags = O_RDWR | O_CREAT;
  1975. File = open(FileName, OpenFlags, FILE_TEST_CREATE_PERMISSIONS);
  1976. if (File < 0) {
  1977. PRINT_ERROR("Failed to open file %s (flags %x): %s.\n",
  1978. FileName,
  1979. OpenFlags,
  1980. strerror(errno));
  1981. Failures += 1;
  1982. continue;
  1983. }
  1984. ResultOffset = lseek(File, Offset, SEEK_SET);
  1985. if (ResultOffset != Offset) {
  1986. PRINT_ERROR("Seek on file %s offset 0x%I64x failed: got 0x%I64x\n",
  1987. FileName,
  1988. Offset,
  1989. ResultOffset);
  1990. Failures += 1;
  1991. }
  1992. do {
  1993. BytesComplete = write(File, &Offset, 1);
  1994. } while ((BytesComplete < 0) && (errno == EINTR));
  1995. if (BytesComplete != 1) {
  1996. PRINT_ERROR("Write failed. Wrote %d of %d bytes: %s.\n",
  1997. BytesComplete,
  1998. FileSize,
  1999. strerror(errno));
  2000. Failures += 1;
  2001. }
  2002. FileState[FileIndex][Offset] = 1;
  2003. //
  2004. // Now seek forward a bit and read.
  2005. //
  2006. Seek = rand() % UNINITIALIZED_DATA_SEEK_MAX;
  2007. Offset = lseek(File, Seek, SEEK_CUR);
  2008. if (Offset == (ULONGLONG)-1) {
  2009. PRINT_ERROR("Seek on file %s failed to seek %d from current.\n",
  2010. FileName,
  2011. Seek);
  2012. Failures += 1;
  2013. }
  2014. //
  2015. // Reads are tricky as the file can be deleted and recreated by
  2016. // other threads. At least validate that if the read succeeded the
  2017. // byte should be zero or the low byte of the offset.
  2018. //
  2019. Value = 0;
  2020. DEBUG_PRINT("Reading file %s, Offset 0x%I64x\n", FileName, Offset);
  2021. do {
  2022. BytesComplete = read(File, &Value, 1);
  2023. } while ((BytesComplete < 0) && (errno == EINTR));
  2024. if (BytesComplete < 0) {
  2025. PRINT_ERROR("Read failed. Read %d of 1 bytes: %s.\n",
  2026. BytesComplete,
  2027. strerror(errno));
  2028. Failures += 1;
  2029. break;
  2030. }
  2031. Expected = 0;
  2032. if (FileState[FileIndex][Offset] != 0) {
  2033. Expected = (Offset & 0xFF);
  2034. }
  2035. if ((BytesComplete == 1) && (Value != Expected)) {
  2036. PRINT_ERROR("Error: Read of file %s at offset 0x%I64x turned up "
  2037. "%x (should have been %x).\n",
  2038. FileName,
  2039. Offset,
  2040. Value,
  2041. Expected);
  2042. }
  2043. if (close(File) != 0) {
  2044. PRINT_ERROR("Failed to close: %s.\n", strerror(errno));
  2045. Failures += 1;
  2046. }
  2047. if ((Iteration % Percent) == 0) {
  2048. PRINT("u");
  2049. }
  2050. }
  2051. //
  2052. // Clean up. Sure, other threads could still be running the test, but they
  2053. // should all clean up too.
  2054. //
  2055. if (FileTestNoCleanup == FALSE) {
  2056. for (FileIndex = 0; FileIndex < FileCount; FileIndex += 1) {
  2057. snprintf(FileName,
  2058. sizeof(FileName),
  2059. "fudt%x-%06x",
  2060. Process & 0xFFFF,
  2061. FileIndex);
  2062. Result = unlink(FileName);
  2063. if ((Result != 0) && (errno != ENOENT)) {
  2064. PRINT_ERROR("Failed to unlink %s: %s.\n",
  2065. FileName,
  2066. strerror(errno));
  2067. Failures += 1;
  2068. }
  2069. }
  2070. }
  2071. PRINT("\n");
  2072. Failures += PrintTestTime(&StartTime);
  2073. RunFileUninitializedDataTestEnd:
  2074. if (FileState != NULL) {
  2075. for (FileIndex = 0; FileIndex < FileCount; FileIndex += 1) {
  2076. if (FileState[FileIndex] != NULL) {
  2077. free(FileState[FileIndex]);
  2078. }
  2079. }
  2080. free(FileState);
  2081. }
  2082. if (UninitializedDataBuffer != NULL) {
  2083. free(UninitializedDataBuffer);
  2084. }
  2085. return Failures;
  2086. }
  2087. ULONG
  2088. PrintTestTime (
  2089. struct timeval *StartTime
  2090. )
  2091. /*++
  2092. Routine Description:
  2093. This routine prints the total time it took to run the test, given the
  2094. starting time of the test.
  2095. Arguments:
  2096. StartTime - Supplies a pointer to the test's start time.
  2097. Return Value:
  2098. Returns the number of failures.
  2099. --*/
  2100. {
  2101. struct timeval EndTime;
  2102. ULONG Failures;
  2103. INT Result;
  2104. struct timeval TotalTime;
  2105. Failures = 0;
  2106. //
  2107. // Record the end time and display the total time, in seconds.
  2108. //
  2109. Result = gettimeofday(&EndTime, NULL);
  2110. if (Result != 0) {
  2111. PRINT_ERROR("Failed to get time of day: %s.\n", strerror(errno));
  2112. Failures += 1;
  2113. goto PrintTestTimeEnd;
  2114. }
  2115. TotalTime.tv_sec = EndTime.tv_sec - StartTime->tv_sec;
  2116. TotalTime.tv_usec = EndTime.tv_usec - StartTime->tv_usec;
  2117. if (TotalTime.tv_usec < 0) {
  2118. TotalTime.tv_sec -= 1;
  2119. TotalTime.tv_usec += 1000000;
  2120. }
  2121. PRINT("Time: %lld.%06d seconds.\n",
  2122. (long long)TotalTime.tv_sec,
  2123. TotalTime.tv_usec);
  2124. PrintTestTimeEnd:
  2125. return Failures;
  2126. }