| 873 | } |
| 874 | |
| 875 | Errata |
| 876 | StripeSM::loadMeta() |
| 877 | { |
| 878 | // Read from disk in chunks of this size. This needs to be a multiple of both the |
| 879 | // store block size and the directory entry size so neither goes across read boundaries. |
| 880 | // Beyond that the value should be in the ~10MB range for what I guess is best performance |
| 881 | // vs. blocking production disk I/O on a live system. |
| 882 | constexpr static int64_t N = (1 << 8) * CacheStoreBlocks::SCALE * sizeof(CacheDirEntry); |
| 883 | |
| 884 | Errata zret; |
| 885 | |
| 886 | int fd = _span->_fd; |
| 887 | Bytes n; |
| 888 | bool found; |
| 889 | MemSpan<void> data; // The current view of the read buffer. |
| 890 | Bytes delta; |
| 891 | Bytes pos = _start; |
| 892 | // Avoid searching the entire span, because some of it must be content. Assume that AOS is more than 160 |
| 893 | // which means at most 10/160 (1/16) of the span can be directory/header. |
| 894 | Bytes limit = pos + _len / 16; |
| 895 | size_t io_align = _span->_geometry.blocksz; |
| 896 | StripeMeta const *meta; |
| 897 | |
| 898 | std::unique_ptr<char> bulk_buff; // Buffer for bulk reads. |
| 899 | static const size_t SBSIZE = CacheStoreBlocks::SCALE; // save some typing. |
| 900 | alignas(SBSIZE) char stripe_buff[SBSIZE]; // Use when reading a single stripe block. |
| 901 | alignas(SBSIZE) char stripe_buff2[SBSIZE]; // use to save the stripe freelist |
| 902 | if (io_align > SBSIZE) { |
| 903 | return Errata("Cannot load stripe {} on span [} because the I/O block alignment {} is larger than the buffer alignment {}", |
| 904 | _idx, _span->_path.string(), io_align, SBSIZE); |
| 905 | } |
| 906 | |
| 907 | _directory._start = pos; |
| 908 | // Header A must be at the start of the stripe block. |
| 909 | // Todo: really need to check pread() for failure. |
| 910 | ssize_t headerbyteCount = pread(fd, stripe_buff2, SBSIZE, pos); |
| 911 | n.assign(headerbyteCount); |
| 912 | data.assign(stripe_buff2, n); |
| 913 | meta = static_cast<StripeMeta *>(data.data()); |
| 914 | // TODO:: We need to read more data at this point to populate dir |
| 915 | if (this->validateMeta(meta)) { |
| 916 | delta = Bytes(data.rebind<char>().data() - stripe_buff2); |
| 917 | _meta[A][HEAD] = *meta; |
| 918 | _meta_pos[A][HEAD] = round_down(pos + Bytes(delta)); |
| 919 | pos += round_up(SBSIZE); |
| 920 | _directory._skip = Bytes(SBSIZE); // first guess, updated in @c updateLiveData when the header length is computed. |
| 921 | // Search for Footer A. Nothing for it except to grub through the disk. |
| 922 | // The searched data is cached so it's available for directory parsing later if needed. |
| 923 | while (pos < limit) { |
| 924 | char *buff = static_cast<char *>(ats_memalign(io_align, N)); |
| 925 | bulk_buff.reset(buff); |
| 926 | n.assign(pread(fd, buff, N, pos)); |
| 927 | data.assign(buff, n); |
| 928 | found = this->probeMeta(data, &_meta[A][HEAD]); |
| 929 | if (found) { |
| 930 | ptrdiff_t diff = data.rebind<char>().data() - buff; |
| 931 | _meta[A][FOOT] = static_cast<StripeMeta *>(data.data())[0]; |
| 932 | _meta_pos[A][FOOT] = round_down(pos + Bytes(diff)); |
no test coverage detected