00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041 #include <types.h>
00042 #include <kern/errno.h>
00043 #include <kern/fcntl.h>
00044 #include <lib.h>
00045 #include <uio.h>
00046 #include <thread.h>
00047 #include <synch.h>
00048 #include <vfs.h>
00049 #include <fs.h>
00050 #include <vnode.h>
00051 #include <test.h>
00052
00053 #define SLOGAN "HODIE MIHI - CRAS TIBI\n"
00054 #define FILENAME "fstest.tmp"
00055 #define NCHUNKS 720
00056 #define NTHREADS 12
00057 #define NCREATES 32
00058
00059 static struct semaphore *threadsem = NULL;
00060
00061 static
00062 void
00063 init_threadsem(void)
00064 {
00065 if (threadsem==NULL) {
00066 threadsem = sem_create("fstestsem", 0);
00067 if (threadsem == NULL) {
00068 panic("fstest: sem_create failed\n");
00069 }
00070 }
00071 }
00072
00073
00074
00075
00076
00077 static
00078 void
00079 rotate(char *str, int amt)
00080 {
00081 int i, ch;
00082
00083 amt = (amt+2600)%26;
00084 KASSERT(amt>=0);
00085
00086 for (i=0; str[i]; i++) {
00087 ch = str[i];
00088 if (ch>='A' && ch<='Z') {
00089 ch = ch - 'A';
00090 ch += amt;
00091 ch %= 26;
00092 ch = ch + 'A';
00093 KASSERT(ch>='A' && ch<='Z');
00094 }
00095 str[i] = ch;
00096 }
00097 }
00098
00099
00100
00101 static
00102 void
00103 fstest_makename(char *buf, size_t buflen,
00104 const char *fs, const char *namesuffix)
00105 {
00106 snprintf(buf, buflen, "%s:%s%s", fs, FILENAME, namesuffix);
00107 KASSERT(strlen(buf) < buflen);
00108 }
00109
00110 #define MAKENAME() fstest_makename(name, sizeof(name), fs, namesuffix)
00111
00112 static
00113 int
00114 fstest_remove(const char *fs, const char *namesuffix)
00115 {
00116 char name[32];
00117 char buf[32];
00118 int err;
00119
00120 MAKENAME();
00121
00122 strcpy(buf, name);
00123 err = vfs_remove(buf);
00124 if (err) {
00125 kprintf("Could not remove %s: %s\n", name, strerror(err));
00126 return -1;
00127 }
00128
00129 return 0;
00130 }
00131
00132 static
00133 int
00134 fstest_write(const char *fs, const char *namesuffix,
00135 int stridesize, int stridepos)
00136 {
00137 struct vnode *vn;
00138 int err;
00139 int i;
00140 size_t shouldbytes=0;
00141 size_t bytes=0;
00142 off_t pos=0;
00143 char name[32];
00144 char buf[32];
00145 struct iovec iov;
00146 struct uio ku;
00147 int flags;
00148
00149 KASSERT(sizeof(buf) > strlen(SLOGAN));
00150
00151 MAKENAME();
00152
00153 flags = O_WRONLY|O_CREAT;
00154 if (stridesize == 1) {
00155 flags |= O_TRUNC;
00156 }
00157
00158
00159 strcpy(buf, name);
00160 err = vfs_open(buf, flags, 0664, &vn);
00161 if (err) {
00162 kprintf("Could not open %s for write: %s\n",
00163 name, strerror(err));
00164 return -1;
00165 }
00166
00167 for (i=0; i<NCHUNKS; i++) {
00168 if (i % stridesize != stridepos) {
00169 pos += strlen(SLOGAN);
00170 continue;
00171 }
00172 strcpy(buf, SLOGAN);
00173 rotate(buf, i);
00174 uio_kinit(&iov, &ku, buf, strlen(SLOGAN), pos, UIO_WRITE);
00175 err = VOP_WRITE(vn, &ku);
00176 if (err) {
00177 kprintf("%s: Write error: %s\n", name, strerror(err));
00178 vfs_close(vn);
00179 vfs_remove(name);
00180 return -1;
00181 }
00182
00183 if (ku.uio_resid > 0) {
00184 kprintf("%s: Short write: %lu bytes left over\n",
00185 name, (unsigned long) ku.uio_resid);
00186 vfs_close(vn);
00187 vfs_remove(name);
00188 return -1;
00189 }
00190
00191 bytes += (ku.uio_offset - pos);
00192 shouldbytes += strlen(SLOGAN);
00193 pos = ku.uio_offset;
00194 }
00195
00196 vfs_close(vn);
00197
00198 if (bytes != shouldbytes) {
00199 kprintf("%s: %lu bytes written, should have been %lu!\n",
00200 name, (unsigned long) bytes,
00201 (unsigned long) (NCHUNKS*strlen(SLOGAN)));
00202 vfs_remove(name);
00203 return -1;
00204 }
00205 kprintf("%s: %lu bytes written\n", name, (unsigned long) bytes);
00206
00207 return 0;
00208 }
00209
00210 static
00211 int
00212 fstest_read(const char *fs, const char *namesuffix)
00213 {
00214 struct vnode *vn;
00215 int err;
00216 int i;
00217 size_t bytes=0;
00218 char name[32];
00219 char buf[32];
00220 struct iovec iov;
00221 struct uio ku;
00222
00223 MAKENAME();
00224
00225
00226 strcpy(buf, name);
00227 err = vfs_open(buf, O_RDONLY, 0664, &vn);
00228 if (err) {
00229 kprintf("Could not open test file for read: %s\n",
00230 strerror(err));
00231 return -1;
00232 }
00233
00234 for (i=0; i<NCHUNKS; i++) {
00235 uio_kinit(&iov, &ku, buf, strlen(SLOGAN), bytes, UIO_READ);
00236 err = VOP_READ(vn, &ku);
00237 if (err) {
00238 kprintf("%s: Read error: %s\n", name, strerror(err));
00239 vfs_close(vn);
00240 return -1;
00241 }
00242
00243 if (ku.uio_resid > 0) {
00244 kprintf("%s: Short read: %lu bytes left over\n", name,
00245 (unsigned long) ku.uio_resid);
00246 vfs_close(vn);
00247 return -1;
00248 }
00249 buf[strlen(SLOGAN)] = 0;
00250 rotate(buf, -i);
00251 if (strcmp(buf, SLOGAN)) {
00252 kprintf("%s: Test failed: line %d mismatched: %s\n",
00253 name, i+1, buf);
00254 vfs_close(vn);
00255 return -1;
00256 }
00257
00258 bytes = ku.uio_offset;
00259 }
00260
00261 vfs_close(vn);
00262
00263 if (bytes != NCHUNKS*strlen(SLOGAN)) {
00264 kprintf("%s: %lu bytes read, should have been %lu!\n",
00265 name, (unsigned long) bytes,
00266 (unsigned long) (NCHUNKS*strlen(SLOGAN)));
00267 return -1;
00268 }
00269 kprintf("%s: %lu bytes read\n", name, (unsigned long) bytes);
00270 return 0;
00271 }
00272
00273
00274
00275 static
00276 void
00277 dofstest(const char *filesys)
00278 {
00279 kprintf("*** Starting filesystem test on %s:\n", filesys);
00280
00281 if (fstest_write(filesys, "", 1, 0)) {
00282 kprintf("*** Test failed\n");
00283 return;
00284 }
00285
00286 if (fstest_read(filesys, "")) {
00287 kprintf("*** Test failed\n");
00288 return;
00289 }
00290
00291 if (fstest_remove(filesys, "")) {
00292 kprintf("*** Test failed\n");
00293 return;
00294 }
00295
00296 kprintf("*** Filesystem test done\n");
00297 }
00298
00299
00300
00301 static
00302 void
00303 readstress_thread(void *fs, unsigned long num)
00304 {
00305 const char *filesys = fs;
00306 if (fstest_read(filesys, "")) {
00307 kprintf("*** Thread %lu: failed\n", num);
00308 }
00309 V(threadsem);
00310 }
00311
00312 static
00313 void
00314 doreadstress(const char *filesys)
00315 {
00316 int i, err;
00317
00318 init_threadsem();
00319
00320 kprintf("*** Starting fs read stress test on %s:\n", filesys);
00321
00322 if (fstest_write(filesys, "", 1, 0)) {
00323 kprintf("*** Test failed\n");
00324 return;
00325 }
00326
00327 for (i=0; i<NTHREADS; i++) {
00328 err = thread_fork("readstress", NULL,
00329 readstress_thread, (char *)filesys, i);
00330 if (err) {
00331 panic("readstress: thread_fork failed: %s\n",
00332 strerror(err));
00333 }
00334 }
00335
00336 for (i=0; i<NTHREADS; i++) {
00337 P(threadsem);
00338 }
00339
00340 if (fstest_remove(filesys, "")) {
00341 kprintf("*** Test failed\n");
00342 return;
00343 }
00344
00345 kprintf("*** fs read stress test done\n");
00346 }
00347
00348
00349
00350 static
00351 void
00352 writestress_thread(void *fs, unsigned long num)
00353 {
00354 const char *filesys = fs;
00355 char numstr[8];
00356 snprintf(numstr, sizeof(numstr), "%lu", num);
00357
00358 if (fstest_write(filesys, numstr, 1, 0)) {
00359 kprintf("*** Thread %lu: failed\n", num);
00360 V(threadsem);
00361 return;
00362 }
00363
00364 if (fstest_read(filesys, numstr)) {
00365 kprintf("*** Thread %lu: failed\n", num);
00366 V(threadsem);
00367 return;
00368 }
00369
00370 if (fstest_remove(filesys, numstr)) {
00371 kprintf("*** Thread %lu: failed\n", num);
00372 }
00373
00374 kprintf("*** Thread %lu: done\n", num);
00375
00376 V(threadsem);
00377 }
00378
00379 static
00380 void
00381 dowritestress(const char *filesys)
00382 {
00383 int i, err;
00384
00385 init_threadsem();
00386
00387 kprintf("*** Starting fs write stress test on %s:\n", filesys);
00388
00389 for (i=0; i<NTHREADS; i++) {
00390 err = thread_fork("writestress", NULL,
00391 writestress_thread, (char *)filesys, i);
00392 if (err) {
00393 panic("thread_fork failed %s\n", strerror(err));
00394 }
00395 }
00396
00397 for (i=0; i<NTHREADS; i++) {
00398 P(threadsem);
00399 }
00400
00401 kprintf("*** fs write stress test done\n");
00402 }
00403
00404
00405
00406 static
00407 void
00408 writestress2_thread(void *fs, unsigned long num)
00409 {
00410 const char *filesys = fs;
00411
00412 if (fstest_write(filesys, "", NTHREADS, num)) {
00413 kprintf("*** Thread %lu: failed\n", num);
00414 V(threadsem);
00415 return;
00416 }
00417
00418 V(threadsem);
00419 }
00420
00421 static
00422 void
00423 dowritestress2(const char *filesys)
00424 {
00425 int i, err;
00426 char name[32];
00427 struct vnode *vn;
00428
00429 init_threadsem();
00430
00431 kprintf("*** Starting fs write stress test 2 on %s:\n", filesys);
00432
00433
00434 fstest_makename(name, sizeof(name), filesys, "");
00435 err = vfs_open(name, O_WRONLY|O_CREAT|O_TRUNC, 0664, &vn);
00436 if (err) {
00437 kprintf("Could not create test file: %s\n", strerror(err));
00438 kprintf("*** Test failed\n");
00439 return;
00440 }
00441 vfs_close(vn);
00442
00443 for (i=0; i<NTHREADS; i++) {
00444 err = thread_fork("writestress2", NULL,
00445 writestress2_thread, (char *)filesys, i);
00446 if (err) {
00447 panic("writestress2: thread_fork failed: %s\n",
00448 strerror(err));
00449 }
00450 }
00451
00452 for (i=0; i<NTHREADS; i++) {
00453 P(threadsem);
00454 }
00455
00456 if (fstest_read(filesys, "")) {
00457 kprintf("*** Test failed\n");
00458 return;
00459 }
00460
00461 if (fstest_remove(filesys, "")) {
00462 kprintf("*** Test failed\n");
00463 }
00464
00465
00466 kprintf("*** fs write stress test 2 done\n");
00467 }
00468
00469
00470
00471 static
00472 void
00473 createstress_thread(void *fs, unsigned long num)
00474 {
00475 const char *filesys = fs;
00476 int i;
00477 char numstr[16];
00478
00479 for (i=0; i<NCREATES; i++) {
00480
00481 snprintf(numstr, sizeof(numstr), "%lu-%d", num, i);
00482
00483 if (fstest_write(filesys, numstr, 1, 0)) {
00484 kprintf("*** Thread %lu: file %d: failed\n", num, i);
00485 V(threadsem);
00486 return;
00487 }
00488
00489 if (fstest_read(filesys, numstr)) {
00490 kprintf("*** Thread %lu: file %d: failed\n", num, i);
00491 V(threadsem);
00492 return;
00493 }
00494
00495 if (fstest_remove(filesys, numstr)) {
00496 kprintf("*** Thread %lu: file %d: failed\n", num, i);
00497 V(threadsem);
00498 return;
00499 }
00500
00501 }
00502
00503 V(threadsem);
00504 }
00505
00506 static
00507 void
00508 docreatestress(const char *filesys)
00509 {
00510 int i, err;
00511
00512 init_threadsem();
00513
00514 kprintf("*** Starting fs create stress test on %s:\n", filesys);
00515
00516 for (i=0; i<NTHREADS; i++) {
00517 #ifdef UW
00518 err = thread_fork("createstress", NULL,
00519 createstress_thread, (char *)filesys, i);
00520 #else
00521 err = thread_fork("createstress",
00522 createstress_thread, (char *)filesys, i,
00523 NULL);
00524 #endif
00525 if (err) {
00526 panic("createstress: thread_fork failed %s\n",
00527 strerror(err));
00528 }
00529 }
00530
00531 for (i=0; i<NTHREADS; i++) {
00532 P(threadsem);
00533 }
00534
00535 kprintf("*** fs create stress test done\n");
00536 }
00537
00538
00539
00540 static
00541 int
00542 checkfilesystem(int nargs, char **args)
00543 {
00544 char *device;
00545
00546 if (nargs != 2) {
00547 kprintf("Usage: fs[12345] filesystem:\n");
00548 return EINVAL;
00549 }
00550
00551 device = args[1];
00552
00553
00554 if (device[strlen(device)-1]==':') {
00555 device[strlen(device)-1] = 0;
00556 }
00557
00558 return 0;
00559 }
00560
00561 #define DEFTEST(testname) \
00562 int \
00563 testname(int nargs, char **args) \
00564 { \
00565 int result; \
00566 result = checkfilesystem(nargs, args); \
00567 if (result) { \
00568 return result; \
00569 } \
00570 do##testname(args[1]); \
00571 return 0; \
00572 }
00573
00574 DEFTEST(fstest);
00575 DEFTEST(readstress);
00576 DEFTEST(writestress);
00577 DEFTEST(writestress2);
00578 DEFTEST(createstress);
00579
00580
00581
00582 int
00583 printfile(int nargs, char **args)
00584 {
00585 struct vnode *rv, *wv;
00586 struct iovec iov;
00587 struct uio ku;
00588 off_t rpos=0, wpos=0;
00589 char buf[128];
00590 char outfile[16];
00591 int result;
00592 int done=0;
00593
00594 if (nargs != 2) {
00595 kprintf("Usage: pf filename\n");
00596 return EINVAL;
00597 }
00598
00599
00600 strcpy(outfile, "con:");
00601
00602 result = vfs_open(args[1], O_RDONLY, 0664, &rv);
00603 if (result) {
00604 kprintf("printfile: %s\n", strerror(result));
00605 return result;
00606 }
00607
00608 result = vfs_open(outfile, O_WRONLY, 0664, &wv);
00609 if (result) {
00610 kprintf("printfile: output: %s\n", strerror(result));
00611 vfs_close(rv);
00612 return result;
00613 }
00614
00615 while (!done) {
00616 uio_kinit(&iov, &ku, buf, sizeof(buf), rpos, UIO_READ);
00617 result = VOP_READ(rv, &ku);
00618 if (result) {
00619 kprintf("Read error: %s\n", strerror(result));
00620 break;
00621 }
00622 rpos = ku.uio_offset;
00623
00624 if (ku.uio_resid > 0) {
00625 done = 1;
00626 }
00627
00628 uio_kinit(&iov, &ku, buf, sizeof(buf)-ku.uio_resid, wpos,
00629 UIO_WRITE);
00630 result = VOP_WRITE(wv, &ku);
00631 if (result) {
00632 kprintf("Write error: %s\n", strerror(result));
00633 break;
00634 }
00635 wpos = ku.uio_offset;
00636
00637 if (ku.uio_resid > 0) {
00638 kprintf("Warning: short write\n");
00639 }
00640 }
00641
00642 vfs_close(wv);
00643 vfs_close(rv);
00644
00645 return 0;
00646 }