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

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

unix.superglobalmegacorp.com

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