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
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053 #include "w_defines.h"
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072 #define IO_C
00073
00074 #include <w.h>
00075 #include <w_debug.h>
00076 #include <w_stream.h>
00077 #include <cstdlib>
00078 #include <cstring>
00079 #include <sys/time.h>
00080 #include <sys/wait.h>
00081 #include <new>
00082 #include <sys/stat.h>
00083 #include <sys/mman.h>
00084 #include <w_rusage.h>
00085 #if defined(HAVE_HUGETLBFS)
00086 #include <fcntl.h>
00087 #endif
00088 #include "sthread.h"
00089 #include "sthread_stats.h"
00090 #include <sdisk.h>
00091 #include <sdisk_unix.h>
00092
00093 #if defined(HUGEPAGESIZE) && (HUGEPAGESIZE == 0)
00094 #undef HUGEPAGESIZE
00095 #endif
00096
00097 extern class sthread_stats SthreadStats;
00098
00099 sdisk_t **sthread_t::_disks = 0;
00100 unsigned sthread_t::open_max = 0;
00101 unsigned sthread_t::open_count = 0;
00102
00103 static queue_based_lock_t protectFDs;
00104
00105 int sthread_t:: _disk_buffer_disalignment(0);
00106 size_t sthread_t:: _disk_buffer_size(0);
00107 char * sthread_t:: _disk_buffer (NULL);
00108
00109 int sthread_t::do_unmap()
00110 {
00111
00112
00113
00114
00115 #ifdef WITHOUT_MMAP
00116 ::free( _disk_buffer - _disk_buffer_disalignment );
00117 _disk_buffer = NULL;
00118 _disk_buffer_disalignment = 0;
00119 return 0;
00120 #endif
00121
00122 #if 0
00123 fprintf(stderr, "%d: munmap disalignment %d addr %p, size %lu\n",
00124 __LINE__,
00125 _disk_buffer_disalignment,
00126 ( _disk_buffer - _disk_buffer_disalignment),
00127 _disk_buffer_size);
00128 #endif
00129
00130 int err =
00131 munmap( _disk_buffer - _disk_buffer_disalignment, _disk_buffer_size);
00132
00133 if(err) {
00134 cerr << "munmap returns " << err
00135 << " errno is " << errno << " " << strerror(errno)
00136 << endl;
00137 w_assert1(!err);
00138 }
00139
00140 _disk_buffer = NULL;
00141 _disk_buffer_size = 0;
00142 _disk_buffer_disalignment = 0;
00143
00144 return err;
00145 }
00146
00147 void sthread_t::align_for_sm(size_t W_IFDEBUG1(requested_size))
00148 {
00149 char * _disk_buffer2 = (char *)alignon( _disk_buffer, SM_PAGESIZE);
00150 if( _disk_buffer2 != _disk_buffer)
00151 {
00152
00153 _disk_buffer_disalignment = ( _disk_buffer2 - _disk_buffer);
00154 w_assert1( _disk_buffer_disalignment < SM_PAGESIZE);
00155 w_assert1( _disk_buffer_size - _disk_buffer_disalignment
00156 >= requested_size);
00157
00158 _disk_buffer = _disk_buffer2;
00159
00160 }
00161 }
00162
00163 long sthread_t::get_max_page_size(long system_page_size)
00164 {
00165 long max_page_size = 0;
00166 #ifdef HAVE_GETPAGESIZES
00167 {
00168 int nelem = getpagesizes(NULL, 0);
00169 if(nelem >= 0) {
00170 size_t *pagesize = new size_t[nelem];
00171 int err = getpagesizes (pagesize, nelem);
00172 if(err >= 0) {
00173 for(int i=0; i < nelem; i++) {
00174 if ( pagesize[i] > max_page_size) {
00175 max_page_size = pagesize[i];
00176 }
00177 }
00178 } else {
00179 cerr << "getpagesizes(pagesize, " << nelem << ") failed. "
00180 << " errno is " << errno << " " << strerror(errno)
00181 << endl;
00182 }
00183 delete[] pagesize;
00184 } else {
00185 cerr << "getpagesizes(NULL,0) failed. "
00186 << " errno is " << errno << " " << strerror(errno)
00187 << endl;
00188 }
00189 }
00190 #else
00191 max_page_size = system_page_size;
00192 #endif
00193
00194
00195
00196
00197
00198
00199 return max_page_size;
00200 }
00201
00202 void sthread_t::align_bufsize(size_t size, long system_page_size,
00203 long max_page_size)
00204 {
00205
00206
00207
00208
00209
00210
00211
00212 w_assert0(alignon(max_page_size, system_page_size) == max_page_size);
00213
00214
00215
00216
00217
00218
00219
00220 _disk_buffer_size = alignon(size, max_page_size);
00221 w_assert1(_disk_buffer_size >= size);
00222
00223
00224 w_assert1(size_t(alignon(_disk_buffer_size, max_page_size))
00225 == _disk_buffer_size);
00226 w_assert1(size_t(alignon(_disk_buffer_size, system_page_size))
00227 == _disk_buffer_size);
00228 }
00229
00230 #if defined(HAVE_HUGETLBFS) && defined(HUGEPAGESIZE) && (HUGEPAGESIZE > 0)
00231 void clear(char *buf_start, size_t requested_size)
00232 {
00233
00234 size_t requested_huge_pages = requested_size / (HUGEPAGESIZE*1024);
00235 size_t requested_pages = requested_size / SM_PAGESIZE;
00236 for(size_t j=0; j < requested_pages; j++) {
00237 for(size_t i=0; i < SM_PAGESIZE; i++) {
00238 size_t offset = j*SM_PAGESIZE + i;
00239 size_t hugepagenum = offset / (HUGEPAGESIZE*1024);
00240 size_t hugepageoffset = offset - (hugepagenum *
00241 (HUGEPAGESIZE*1024));
00242 char x = buf_start[offset];
00243
00244
00245 if(int(i) < 0) fprintf(stderr, "0x%d 0x%x, 0x%x, 0x%x", x,
00246 int(hugepagenum), int(hugepageoffset), int(requested_huge_pages));
00247 }
00248 }
00249
00250 #if W_DEBUG_LEVEL > 4
00251 fprintf(stderr, "clearing %ld bytes starting at %p\n",
00252 requested_size, buf_start);
00253 #endif
00254 memset(buf_start, 0, requested_size);
00255 }
00256 #else
00257 void clear(char *buf_start, size_t requested_size )
00258 {
00259 memset(buf_start, 0, requested_size);
00260 }
00261 #endif
00262
00263
00264 w_rc_t sthread_t::set_bufsize_normal(
00265 size_t size, char *&buf_start , long system_page_size)
00266 {
00267 size_t requested_size = size;
00268
00269
00270
00271
00272
00273
00274 long max_page_size = get_max_page_size(system_page_size);
00275 w_assert1(system_page_size <= max_page_size);
00276
00277
00278
00279
00280
00281
00282 int fd(-1);
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299 int flags1 = MAP_PRIVATE;
00300 int flags2 = MAP_PRIVATE;
00301
00302 #if HAVE_DECL_MAP_ANONYMOUS==1
00303 flags1 |= MAP_ANONYMOUS;
00304 flags2 |= MAP_ANONYMOUS;
00305 #elif HAVE_DECL_MAP_ANON==1
00306 flags1 |= MAP_ANON;
00307 flags2 |= MAP_ANON;
00308 #else
00309 #endif
00310
00311 #if HAVE_DECL_MAP_NORESERVE==1
00312 flags1 |= MAP_NORESERVE;
00313 #endif
00314 #if HAVE_DECL_MAP_FIXED==1
00315 flags2 |= MAP_FIXED;
00316 #endif
00317
00318 #if HAVE_DECL_MAP_ALIGN==1
00319 flags1 |= MAP_ALIGN;
00320 #endif
00321
00322
00323
00324
00325
00326 size += SM_PAGESIZE;
00327 align_bufsize(size, system_page_size, max_page_size);
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339 errno = 0;
00340 _disk_buffer = (char*) mmap(0, _disk_buffer_size,
00341 PROT_NONE,
00342 flags1,
00343 fd,
00344 0
00345 );
00346
00347 if (_disk_buffer == MAP_FAILED) {
00348 cerr
00349 << __LINE__ << " "
00350 << "mmap (size=" << _disk_buffer_size
00351 << " = " << int(_disk_buffer_size/1024)
00352 << " KB ) returns " << long(_disk_buffer)
00353 << " errno is " << errno << " " << strerror(errno)
00354 << " flags " << flags1
00355 << " fd " << fd
00356 << endl;
00357 return RC(fcMMAPFAILED);
00358 }
00359 #if W_DEBUG_LEVEL > 4
00360 else
00361 {
00362 cerr
00363 << __LINE__ << " "
00364 << "mmap SUCCESS! (size=" << _disk_buffer_size
00365 << " = " << int(_disk_buffer_size/1024)
00366 << " KB ) returns " << long(_disk_buffer)
00367 << " errno is " << errno << " " << strerror(errno)
00368 << " flags " << flags1
00369 << " fd " << fd
00370 << endl;
00371 }
00372 #endif
00373
00374
00375
00376
00377
00378
00379
00380
00381 int nchunks = _disk_buffer_size / max_page_size;
00382 w_assert1(size_t(nchunks * max_page_size) == _disk_buffer_size);
00383
00384
00385 for(int i=0; i < nchunks; i++)
00386 {
00387 char *addr = _disk_buffer + (i * max_page_size);
00388 char *sub_buffer = (char*) mmap(addr,
00389 max_page_size,
00390 PROT_READ | PROT_WRITE,
00391 flags2,
00392 fd,
00393 0
00394 );
00395
00396 if (sub_buffer == MAP_FAILED) {
00397 cerr
00398 << __LINE__ << " "
00399 << "mmap (addr=" << long(addr )
00400 << ", size=" << max_page_size << ") returns -1;"
00401 << " errno is " << errno << " " << strerror(errno)
00402 << " flags " << flags2
00403 << " fd " << fd
00404 << endl;
00405 do_unmap();
00406 return RC(fcMMAPFAILED);
00407 }
00408 w_assert1(sub_buffer == addr);
00409 #ifdef HAVE_MEMCNTL
00410 struct memcntl_mha info;
00411 info.mha_cmd = MHA_MAPSIZE_VA;
00412 info.mha_flags = 0;
00413 info.mha_pagesize = max_page_size;
00414
00415 if(memcntl(sub_buffer, max_page_size, MC_HAT_ADVISE, (char *)&info, 0, 0) < 0)
00416
00417 {
00418 cerr << "memcntl (chunk " << i << ") returns -1;"
00419 << " errno is " << errno << " " << strerror(errno)
00420 << " requested size " << max_page_size << endl;
00421 do_unmap();
00422 return RC(fcMMAPFAILED);
00423 }
00424 #endif
00425 }
00426
00427 align_for_sm(requested_size);
00428 buf_start = _disk_buffer;
00429 clear(buf_start, requested_size);
00430 return RCOK;
00431 }
00432
00433 #ifdef WITHOUT_MMAP
00434 w_rc_t
00435 sthread_t::set_bufsize_memalign(size_t size, char *&buf_start ,
00436 long system_page_size)
00437 {
00438 size_t requested_size = size;
00439
00440
00441
00442
00443
00444
00445
00446 long max_page_size = system_page_size;
00447
00448 align_bufsize(size, system_page_size, max_page_size);
00449
00450 w_assert1(_disk_buffer == NULL);
00451
00452 #ifdef HAVE_POSIX_MEMALIGN
00453 void *addr;
00454 int e = posix_memalign(&addr, SM_PAGESIZE, size);
00455 if (e == 0) {
00456 _disk_buffer = (char *)addr;
00457 } else {
00458 _disk_buffer = 0;
00459 }
00460 #elif HAVE_MEMALIGN
00461 _disk_buffer = (char *)memalign(SM_PAGESIZE, size);
00462 #elif HAVE_VALLOC
00463 size += SM_PAGESIZE;
00464 _disk_buffer = valloc(size);
00465 #else
00466 size += SM_PAGESIZE;
00467 _disk_buffer = malloc(size);
00468 #endif
00469 if (_disk_buffer == 0) {
00470 cerr
00471 << __LINE__ << " "
00472 << "could not allocate memory (alignment=" << SM_PAGESIZE
00473 << "," << size << ") returns -error;"
00474 << " errno is " << strerror(errno)
00475 << endl;
00476 return RC(fcINTERNAL);
00477 }
00478 align_for_sm(requested_size);
00479 buf_start = _disk_buffer;
00480 clear(buf_start, requested_size);
00481 return RCOK;
00482 }
00483 #endif
00484
00485 #if defined(HAVE_HUGETLBFS)
00486
00487 #if HUGEPAGESIZE>0
00488 #else
00489 # error You have configured to use hugetlbfs but you have no hugepagesize
00490 # error Look for Hugepagesize in /proc/meminfo
00491 #endif
00492
00493 static const char *hugefs_path(NULL);
00494 w_rc_t
00495 sthread_t::set_hugetlbfs_path(const char *what)
00496 {
00497 if(strcmp(what, "NULL")==0) {
00498
00499 hugefs_path = NULL;
00500 return RCOK;
00501 }
00502
00503
00504
00505 struct stat statbuf;
00506 int e=stat(what, &statbuf);
00507 if(e) {
00508 fprintf(stderr, "Could not stat \"%s\"\n", what);
00509 int fd = ::open(what, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
00510 if (fd < 0) {
00511 fprintf(stderr, "Could not create \"%s\"\n", what);
00512 return RC(stBADPATH);
00513 } else {
00514 cerr << " created " << what << endl;
00515 }
00516 }
00517 hugefs_path = what;
00518
00519 return RCOK;
00520 }
00521
00522 w_rc_t
00523 sthread_t::set_bufsize_huge(
00524 size_t size,
00525 char *&buf_start ,
00526 long system_page_size)
00527 {
00528 size_t requested_size = size;
00529
00530
00531
00532
00533
00534
00535
00536 long max_page_size = 1024 * HUGEPAGESIZE;
00537
00538
00539 w_assert1(system_page_size <= max_page_size);
00540
00541
00542
00543
00544
00545
00546
00547
00548
00549
00550 if(hugefs_path == NULL)
00551 {
00552 fprintf(stderr, "path is %s\n", hugefs_path);
00553 fprintf(stderr,
00554 "Need path to huge fs. Use ::set_hugetlbfs_path(path)\n");
00555 return RC(fcMMAPFAILED);
00556 }
00557 int fd = ::open(hugefs_path, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
00558 if (fd < 0) {
00559 cerr << " could not open " << hugefs_path << endl;
00560 return RC(fcMMAPFAILED);
00561 }
00562
00563
00564
00565
00566
00567
00568
00569
00570
00571
00572
00573
00574
00575
00576
00577
00578 int flags =
00579 MAP_PRIVATE;
00580
00581
00582
00583 #if HAVE_DECL_MAP_ALIGN==1
00584 flags |= MAP_ALIGN;
00585 fprintf(stderr, "%d: adding flag 0x%x %s\n", __LINE__,
00586 MAP_ALIGN, "MAP_ALIGN");
00587 #endif
00588
00589
00590
00591
00592
00593 size += SM_PAGESIZE;
00594
00595 align_bufsize(size, system_page_size, max_page_size);
00596
00597
00598
00599
00600
00601
00602
00603 w_assert1(_disk_buffer == NULL);
00604
00605 errno = 0;
00606
00607 _disk_buffer = (char*) mmap(0, _disk_buffer_size,
00608 (PROT_READ | PROT_WRITE),
00609 flags,
00610 fd,
00611 0
00612 );
00613
00614 if (_disk_buffer == MAP_FAILED) {
00615 cerr
00616 << __LINE__ << " "
00617 << "mmap (size=" << _disk_buffer_size << ") returns "
00618 << long(_disk_buffer)
00619 << " errno is " << errno << " " << strerror(errno)
00620 << " prot " << (PROT_READ | PROT_WRITE)
00621 << " flags " << flags
00622 << " fd " << fd
00623 << endl;
00624 close(fd);
00625 return RC(fcMMAPFAILED);
00626 }
00627 #if W_DEBUG_LEVEL > 4
00628 else
00629 {
00630 fprintf(stderr,
00631 "%d mmap SUCCESS! (size= %lu, %lu KB) returns %p errno %d/%s prot 0x%x flags 0x%x fd %d\n",
00632 __LINE__,
00633 _disk_buffer_size,
00634 _disk_buffer_size/1024,
00635 _disk_buffer, errno, strerror(errno),
00636 (PROT_READ | PROT_WRITE),
00637 flags, fd);
00638 fprintf(stderr,
00639 "%d mmap (size= %lu, %lu KB) (requested_size %d, %d KB) buf-requested is %d\n",
00640 __LINE__,
00641 _disk_buffer_size,
00642 _disk_buffer_size/1024,
00643 int(requested_size),
00644 int(requested_size/1024),
00645 int(_disk_buffer_size-requested_size) );
00646
00647
00648 }
00649 #endif
00650
00651 align_for_sm(requested_size);
00652 buf_start = _disk_buffer;
00653 clear(buf_start, requested_size);
00654 return RCOK;
00655 }
00656 #endif
00657
00658
00659
00660
00661
00662
00663
00664
00665
00666
00667
00668
00669
00670
00671
00672
00673
00674
00675
00676
00677
00678
00679
00680
00681
00682
00683
00684
00685
00686
00687
00688
00689
00690
00691
00692
00693
00694
00695
00696
00697
00698
00699
00700
00701
00702
00703
00704
00705 w_rc_t
00706 sthread_t::set_bufsize(size_t size, char *&buf_start ,
00707 bool
00708 #if defined(HAVE_HUGETLBFS)
00709
00710 use_normal_if_huge_fails
00711 #endif
00712 )
00713 {
00714 if (_disk_buffer && size == 0) {
00715 do_unmap();
00716 return RCOK;
00717 }
00718
00719 if (_disk_buffer) {
00720 cerr << "Can't re-allocate disk buffer without disabling"
00721 << endl;
00722 return RC(fcINTERNAL);
00723 }
00724
00725 buf_start = 0;
00726
00727 long system_page_size = sysconf(_SC_PAGESIZE);
00728
00729 #ifdef WITHOUT_MMAP
00730
00731
00732 return set_bufsize_memalign(size, buf_start, system_page_size);
00733 #endif
00734
00735 #if defined(HAVE_HUGETLBFS)
00736
00737
00738
00739
00740
00741
00742 if(hugefs_path != NULL) {
00743 w_rc_t rc = set_bufsize_huge(size, buf_start, system_page_size);
00744 if( !rc.is_error() ) {
00745 #if W_DEBUG_LEVEL > 10
00746 cout << "Using hugetlbfs size " << size
00747 << " system_page_size " << system_page_size
00748 << " path " << hugefs_path << ". " << endl;
00749 #endif
00750 return rc;
00751 }
00752 if(!use_normal_if_huge_fails)
00753 {
00754 return rc;
00755 }
00756
00757 cerr << "Skipping hugetlbfs sue to mmap failure: " << rc << endl;
00758 } else {
00759 cout << "Skipping hugetlbfs based on user option. " << endl;
00760 }
00761 #endif
00762 return set_bufsize_normal(size, buf_start, system_page_size);
00763 }
00764
00765
00766 char *
00767 sthread_t::set_bufsize(size_t size)
00768 {
00769 w_rc_t e;
00770 char *start;
00771
00772 if(size==0) { do_unmap(); return NULL; }
00773
00774 e = set_bufsize(size, start);
00775
00776 if (e.is_error()) {
00777 cerr << "Hidden Failure: set_bufsize(" << size << "):"
00778 << endl << e << endl;
00779 return 0;
00780 }
00781
00782
00783 if (size == 0)
00784 start = 0;
00785
00786 return start;
00787 }
00788
00789
00790 w_rc_t
00791 sthread_t::open(const char* path, int flags, int mode, int &ret_fd)
00792 {
00793 w_rc_t e;
00794 sdisk_t *dp;
00795
00796
00797 ret_fd = -1;
00798
00799 bool open_local = true;
00800
00801 CRITICAL_SECTION(cs, protectFDs);
00802
00803 if (open_count >= open_max) {
00804
00805
00806
00807
00808
00809
00810
00811
00812
00813
00814 unsigned new_max = open_max + 64;
00815 sdisk_t **new_disks = new sdisk_t *[new_max];
00816
00817 if (!new_disks) {
00818 return RC(fcOUTOFMEMORY);
00819 }
00820 unsigned disk;
00821 for (disk = 0; disk < open_count; disk++)
00822 new_disks[disk] = _disks[disk];
00823 for (; disk < new_max; disk++)
00824 new_disks[disk] = 0;
00825 sdisk_t **tmp = _disks;
00826 _disks = new_disks;
00827 open_max = new_max;
00828 delete [] tmp;
00829 }
00830
00831
00832 unsigned disk;
00833 for (disk = 0; disk < open_max; disk++)
00834 if (!_disks[disk])
00835 break;
00836 if (disk == open_max) {
00837 return RC(stINTERNAL);
00838 }
00839
00840
00841
00842
00843 if (open_local) {
00844 e = sdisk_unix_t::make(path, flags, mode, dp);
00845 }
00846
00847
00848 if (e.is_error()) {
00849 return e;
00850 }
00851
00852 _disks[disk] = dp;
00853 open_count++;
00854
00855 ret_fd = fd_base + disk;
00856
00857 return RCOK;
00858 }
00859
00860
00861
00862
00863
00864
00865
00866
00867
00868 w_rc_t sthread_t::close(int fd)
00869 {
00870 fd -= fd_base;
00871 if (fd < 0 || fd >= (int)open_max || !_disks[fd])
00872 return RC(stBADFD);
00873
00874 w_rc_t e;
00875
00876
00877 e = _disks[fd]->sync();
00878 if (e.is_error())
00879 return e;
00880
00881 e = _disks[fd]->close();
00882 if (e.is_error())
00883 return e;
00884
00885 sdisk_t *togo;
00886 {
00887 CRITICAL_SECTION(cs, protectFDs);
00888 togo = _disks[fd];
00889 _disks[fd] = 0;
00890 open_count--;
00891 }
00892 delete togo;
00893
00894 return e;
00895 }
00896
00897
00898
00899
00900
00901
00902
00903
00904
00905
00906
00907
00908
00909
00910
00911
00912
00913
00914
00915
00916
00917
00918
00919
00920
00921 w_rc_t sthread_t::read(int fd, void* buf, int n)
00922 {
00923 fd -= fd_base;
00924 if (fd < 0 || fd >= (int)open_max || !_disks[fd])
00925 return RC(stBADFD);
00926
00927 int done = 0;
00928 w_rc_t e;
00929
00930 e = _disks[fd]->read(buf, n, done);
00931 if (!e.is_error() && done != n)
00932 e = RC(stSHORTIO);
00933
00934 return e;
00935 }
00936
00937
00938 w_rc_t sthread_t::write(int fd, const void* buf, int n)
00939 {
00940 fd -= fd_base;
00941 if (fd < 0 || fd >= (int)open_max || !_disks[fd])
00942 return RC(stBADFD);
00943
00944 int done = 0;
00945 w_rc_t e;
00946
00947 e = _disks[fd]->write(buf, n, done);
00948 if (!e.is_error() && done != n)
00949 e = RC(stSHORTIO);
00950
00951 return e;
00952 }
00953
00954
00955 w_rc_t sthread_t::readv(int fd, const iovec_t *iov, size_t iovcnt)
00956 {
00957 fd -= fd_base;
00958 if (fd < 0 || fd >= (int)open_max || !_disks[fd])
00959 return RC(stBADFD);
00960
00961 int done = 0;
00962 int total = 0;
00963 w_rc_t e;
00964
00965 total = sdisk_t::vsize(iov, iovcnt);
00966
00967 e = _disks[fd]->readv(iov, iovcnt, done);
00968 if (!e.is_error() && done != total)
00969 e = RC(stSHORTIO);
00970
00971 return e;
00972 }
00973
00974
00975 w_rc_t sthread_t::writev(int fd, const iovec_t *iov, size_t iovcnt)
00976 {
00977 fd -= fd_base;
00978 if (fd < 0 || fd >= (int)open_max || !_disks[fd])
00979 return RC(stBADFD);
00980
00981 int done = 0;
00982 int total = 0;
00983 w_rc_t e;
00984
00985 total = sdisk_t::vsize(iov, iovcnt);
00986
00987 e = _disks[fd]->writev(iov, iovcnt, done);
00988 if (!e.is_error() && done != total)
00989 e = RC(stSHORTIO);
00990
00991 return e;
00992 }
00993
00994
00995 w_rc_t sthread_t::pread(int fd, void *buf, int n, fileoff_t pos)
00996 {
00997 fd -= fd_base;
00998 if (fd < 0 || fd >= (int)open_max || !_disks[fd])
00999 return RC(stBADFD);
01000
01001 int done = 0;
01002 w_rc_t e;
01003
01004 errno = 0;
01005 e = _disks[fd]->pread(buf, n, pos, done);
01006 if (!e.is_error() && done != n) {
01007 e = RC2(stSHORTIO, done);
01008 }
01009
01010 return e;
01011 }
01012
01013
01014 w_rc_t sthread_t::pwrite(int fd, const void *buf, int n, fileoff_t pos)
01015 {
01016 fd -= fd_base;
01017 if (fd < 0 || fd >= (int)open_max || !_disks[fd])
01018 return RC(stBADFD);
01019
01020 int done = 0;
01021 w_rc_t e;
01022
01023 e = _disks[fd]->pwrite(buf, n, pos, done);
01024 if (!e.is_error() && done != n)
01025 e = RC(stSHORTIO);
01026
01027 return e;
01028 }
01029
01030
01031 w_rc_t sthread_t::fsync(int fd)
01032 {
01033 fd -= fd_base;
01034 if (fd < 0 || fd >= (int)open_max || !_disks[fd])
01035 return RC(stBADFD);
01036
01037 w_rc_t e;
01038 e = _disks[fd]->sync();
01039
01040 return e;
01041 }
01042
01043 w_rc_t sthread_t::ftruncate(int fd, fileoff_t n)
01044 {
01045 fd -= fd_base;
01046 if (fd < 0 || fd >= (int)open_max || !_disks[fd])
01047 return RC(stBADFD);
01048
01049 w_rc_t e;
01050 e = _disks[fd]->truncate(n);
01051
01052 return e;
01053 }
01054
01055
01056 w_rc_t sthread_t::lseek(int fd, fileoff_t pos, int whence, fileoff_t& ret)
01057 {
01058 fd -= fd_base;
01059 if (fd < 0 || fd >= (int)open_max || !_disks[fd])
01060 return RC(stBADFD);
01061
01062 w_rc_t e;
01063
01064 e = _disks[fd]->seek(pos, whence, ret);
01065
01066 return e;
01067 }
01068
01069
01070 w_rc_t sthread_t::lseek(int fd, fileoff_t offset, int whence)
01071 {
01072 fileoff_t dest;
01073 w_rc_t e;
01074
01075 e = sthread_t::lseek(fd, offset, whence, dest);
01076 if (!e.is_error() && whence == SEEK_AT_SET && dest != offset)
01077 e = RC(stSHORTSEEK);
01078
01079 return e;
01080 }
01081
01082
01083 w_rc_t sthread_t::fstat(int fd, filestat_t &st)
01084 {
01085 fd -= fd_base;
01086 if (fd < 0 || fd >= (int)open_max || !_disks[fd])
01087 return RC(stBADFD);
01088
01089 w_rc_t e;
01090
01091 e = _disks[fd]->stat(st);
01092
01093 return e;
01094 }
01095
01096 w_rc_t sthread_t::fisraw(int fd, bool &isRaw)
01097 {
01098 filestat_t st;
01099
01100 isRaw = false;
01101
01102 W_DO(fstat(fd, st));
01103
01104 isRaw = st.is_device ;
01105 return RCOK;
01106 }
01107
01108
01109 void sthread_t::dump_io(ostream &s)
01110 {
01111 s << "I/O:";
01112 s << " open_max=" << int(open_max);
01113 s << " open_count=" << open_count;
01114 s << endl;
01115 }
01116
01117 extern "C" void dump_io()
01118 {
01119 sthread_t::dump_io(cout);
01120 cout << flush;
01121 }
01122