Annotation of nono/host/diskimage.cpp, revision 1.1.1.5

1.1       root        1: //
                      2: // nono
                      3: // Copyright (C) 2021 nono project
                      4: // Licensed under nono-license.txt
                      5: //
                      6: 
                      7: //
1.1.1.2   root        8: // ディスクイメージ
1.1       root        9: //
                     10: 
                     11: #include "diskimage.h"
                     12: #include "diskimage_raw.h"
1.1.1.2   root       13: #include "mainapp.h"
                     14: #include <fcntl.h>
                     15: 
                     16: //
                     17: // ディスクイメージクラス (外部向け)
                     18: //
1.1       root       19: 
                     20: // コンストラクタ
1.1.1.2   root       21: DiskImage::DiskImage()
1.1       root       22: {
                     23: }
                     24: 
                     25: // デストラクタ
                     26: DiskImage::~DiskImage()
                     27: {
1.1.1.2   root       28:        Close();
1.1       root       29: }
                     30: 
1.1.1.2   root       31: // パス名を指定して、下位ドライバをオープン
                     32: bool
                     33: DiskImage::CreateHandler(const std::string& pathname_)
1.1       root       34: {
1.1.1.2   root       35:        pathname = pathname_;
                     36:        cow_enable = false;
                     37: 
1.1       root       38:        // 今の所 Raw しかない
1.1.1.4   root       39:        driver.reset(new DiskImageRaw(pathname));
                     40:        if ((bool)driver) {
1.1.1.2   root       41:                return true;
                     42:        }
                     43:        return false;
                     44: }
                     45: 
                     46: 
                     47: // このディスクイメージのサイズと書き込み可能かどうかを返す。
                     48: // Open() 前でも動作する。
                     49: bool
                     50: DiskImage::GetInfo(off_t *sizep, bool *w_ok)
                     51: {
                     52:        assert((bool)driver);
                     53:        return driver->GetInfo(sizep, w_ok);
                     54: }
                     55: 
                     56: // オープン
                     57: //
                     58: // ro          cow
                     59: // false       false   : RW オープン、書き込み可
                     60: // true                false   : RO オープン、読み込み専用
                     61: // *           true    : RO オープン、CoW
                     62: bool
                     63: DiskImage::Open(bool read_only, bool cow_enable_)
                     64: {
                     65:        assert((bool)driver);
                     66:        cow_enable = cow_enable_;
                     67: 
                     68:        // ベースファイルをオープン
                     69:        if (cow_enable) {
                     70:                read_only = true;
                     71:        }
                     72:        if (driver->Open(read_only) == false) {
                     73:                return false;
                     74:        }
                     75: 
                     76:        if (cow_enable) {
                     77:                // CoW なら一時ファイルもオープン
                     78: 
                     79:                // VM ディレクトリに適当な名前の隠しファイルで作成
                     80:                auto pos = pathname.rfind('/');
                     81:                if (pos != std::string::npos) {
                     82:                        // パス区切りがあればファイル名部分
                     83:                        cowname = pathname.substr(pos + 1);
                     84:                } else {
                     85:                        // なければ全部
                     86:                        cowname = pathname;
                     87:                }
                     88:                // 空になることはないはず
                     89:                assert(cowname.empty() == false);
                     90: 
                     91:                cowname = gMainApp.GetVMDir() + "/." + cowname + ".cow";
1.1.1.5 ! root       92:                cowfd = open(cowname.c_str(), O_RDWR | O_CREAT | O_TRUNC, 0600);
1.1.1.2   root       93:                if (cowfd < 0) {
                     94:                        return false;
                     95:                }
                     96:        }
                     97: 
                     98:        return true;
                     99: }
                    100: 
                    101: // クローズ
                    102: void
                    103: DiskImage::Close()
                    104: {
                    105:        if (cow_enable) {
                    106:                if (cowfd.Valid()) {
                    107:                        cowfd.Close();
                    108:                        unlink(cowname.c_str());
                    109:                }
                    110:                cow_enable = false;
                    111:        }
                    112: 
                    113:        if ((bool)driver) {
                    114:                driver.reset();
                    115:        }
                    116: }
                    117: 
                    118: // このディスクイメージのサイズ(バイト数)を返す。
                    119: // オープン後のみ使用可能。
                    120: off_t
                    121: DiskImage::GetSize() const
                    122: {
                    123:        assert((bool)driver);
                    124:        return driver->GetSize();
                    125: }
                    126: 
                    127: // 読み出し
                    128: bool
                    129: DiskImage::Read(void *buf, off_t offset, size_t size) const
                    130: {
                    131:        assert((bool)driver);
                    132: 
1.1.1.3   root      133:        if (__predict_false(offset + size > GetSize())) {
1.1.1.2   root      134:                return false;
                    135:        }
                    136: 
                    137:        if (__predict_true(cow_enable == false)) {
                    138:                // 通常モード
                    139:                return driver->Read(buf, offset, size);
                    140: 
                    141:        } else {
                    142:                // Copy-on-Write モード
                    143:                while (size > 0) {
                    144:                        off_t  blk_addr = offset / BLKSIZE;
                    145:                        size_t blk_off  = offset % BLKSIZE;
                    146:                        size_t blk_size = std::min(size, BLKSIZE - blk_off);
                    147: 
                    148:                        if (map_contains(blk_addr)) {
                    149:                                // キャッシュにあればそこから読み出す。
                    150:                                auto cow_offset = map.at(blk_addr);
                    151:                                if (lseek(cowfd, cow_offset + blk_off, SEEK_SET) < 0) {
                    152:                                        return false;
                    153:                                }
                    154:                                if (read(cowfd, buf, blk_size) < 0) {
                    155:                                        return false;
                    156:                                }
                    157:                        } else {
                    158:                                // キャッシュになければファイルから直接読む
                    159:                                if (driver->Read(buf, offset, blk_size) == false) {
                    160:                                        return false;
                    161:                                }
                    162:                        }
                    163: 
                    164:                        buf = (uint8 *)buf + blk_size;
                    165:                        offset += blk_size;
                    166:                        size -= blk_size;
                    167:                }
                    168:        }
                    169: 
                    170:        return true;
                    171: }
                    172: 
                    173: // 書き込み
                    174: bool
                    175: DiskImage::Write(const void *buf, off_t offset, size_t size)
                    176: {
                    177:        assert((bool)driver);
                    178: 
1.1.1.3   root      179:        if (__predict_false(offset + size > GetSize())) {
1.1.1.2   root      180:                return false;
                    181:        }
                    182: 
                    183:        if (__predict_true(cow_enable == false)) {
                    184:                // 通常モード
                    185:                return driver->Write(buf, offset, size);
                    186: 
                    187:        } else {
                    188:                // Copy-on-Write モード
                    189: 
                    190:                off_t cow_offset;
                    191:                while (size > 0) {
                    192:                        off_t  blk_addr = offset / BLKSIZE;
                    193:                        size_t blk_off  = offset % BLKSIZE;
                    194:                        size_t blk_size = std::min(size, BLKSIZE - blk_off);
                    195: 
                    196:                        if (map_contains(blk_addr) == false) {
                    197:                                // キャッシュになければファイルから読んで..
                    198:                                SectBuf newbuf;
                    199:                                off_t read_off = blk_addr * BLKSIZE;
                    200:                                if (driver->Read(&newbuf[0], read_off, BLKSIZE) == false) {
                    201:                                        return false;
                    202:                                }
                    203: 
                    204:                                // それをキャッシュの末尾に追加
                    205:                                cow_offset = lseek(cowfd, 0, SEEK_END);
                    206:                                if (cow_offset == (off_t)-1) {
                    207:                                        return false;
                    208:                                }
                    209:                                if (write(cowfd, &newbuf[0], BLKSIZE) < BLKSIZE) {
                    210:                                        return false;
                    211:                                }
                    212:                                map.emplace(blk_addr, cow_offset);
                    213:                        }
                    214: 
                    215:                        // キャッシュに書き込む
                    216:                        cow_offset = map.at(blk_addr);
                    217:                        if (lseek(cowfd, cow_offset + blk_off, SEEK_SET) < 0) {
                    218:                                return false;
                    219:                        }
                    220:                        if (write(cowfd, buf, blk_size) < 0) {
                    221:                                return false;
                    222:                        }
                    223: 
                    224:                        buf = (const uint8 *)buf + blk_size;
                    225:                        offset += blk_size;
                    226:                        size -= blk_size;
                    227:                }
                    228:        }
                    229: 
                    230:        return true;
                    231: }
                    232: 
                    233: 
                    234: //
                    235: // ディスクイメージドライバの基本クラス
                    236: //
                    237: 
                    238: // コンストラクタ
                    239: DiskImageDriver::DiskImageDriver(const std::string& pathname_)
                    240:        : pathname(pathname_)
                    241: {
                    242: }
                    243: 
                    244: // デストラクタ
                    245: DiskImageDriver::~DiskImageDriver()
                    246: {
1.1       root      247: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.