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

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

unix.superglobalmegacorp.com

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