vfs.cpp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624
  1. #include <kernel/errno.h>
  2. #include <kernel/mem.h>
  3. #include <kernel/tty.hpp>
  4. #include <kernel/vfs.hpp>
  5. #include <stdint.h>
  6. #include <stdio.h>
  7. #include <types/allocator.hpp>
  8. #include <types/assert.h>
  9. #include <types/list.hpp>
  10. #include <types/map.hpp>
  11. #include <types/pair.hpp>
  12. #include <types/status.h>
  13. #include <types/string.hpp>
  14. #include <types/vector.hpp>
  15. using types::allocator_traits;
  16. using types::kernel_allocator;
  17. using types::string;
  18. using types::vector;
  19. struct tmpfs_file_entry {
  20. size_t ino;
  21. char filename[128];
  22. };
  23. fs::vfs::dentry::dentry(dentry* _parent, inode* _ind, const name_type& _name)
  24. : parent(_parent)
  25. , ind(_ind)
  26. , flags { 0 }
  27. , name(_name)
  28. {
  29. if (!_ind || _ind->flags.in.directory) {
  30. children = types::pnew<allocator_type>(children);
  31. idx_children = types::pnew<allocator_type>(idx_children);
  32. }
  33. }
  34. fs::vfs::dentry::dentry(dentry* _parent, inode* _ind, name_type&& _name)
  35. : parent(_parent)
  36. , ind(_ind)
  37. , flags { 0 }
  38. , name(types::move(_name))
  39. {
  40. if (!_ind || _ind->flags.in.directory) {
  41. children = types::pnew<allocator_type>(children);
  42. idx_children = types::pnew<allocator_type>(idx_children);
  43. }
  44. }
  45. fs::vfs::dentry::dentry(dentry&& val)
  46. : children(val.children)
  47. , idx_children(val.idx_children)
  48. , parent(val.parent)
  49. , ind(val.ind)
  50. , flags { val.flags }
  51. , name(types::move(val.name))
  52. {
  53. for (auto& item : *children)
  54. item.parent = this;
  55. memset(&val, 0x00, sizeof(dentry));
  56. }
  57. fs::vfs::dentry::~dentry()
  58. {
  59. if (children) {
  60. types::pdelete<allocator_type>(children);
  61. types::pdelete<allocator_type>(idx_children);
  62. }
  63. }
  64. fs::vfs::dentry* fs::vfs::dentry::append(inode* ind, const name_type& name, bool set_dirty)
  65. {
  66. auto iter = children->emplace_back(this, ind, name);
  67. idx_children->emplace(iter->name, &iter);
  68. if (set_dirty)
  69. this->flags.in.dirty = 1;
  70. return &iter;
  71. }
  72. fs::vfs::dentry* fs::vfs::dentry::append(inode* ind, name_type&& name, bool set_dirty)
  73. {
  74. auto iter = children->emplace_back(this, ind, types::move(name));
  75. idx_children->emplace(iter->name, &iter);
  76. if (set_dirty)
  77. this->flags.in.dirty = 1;
  78. return &iter;
  79. }
  80. fs::vfs::dentry* fs::vfs::dentry::find(const name_type& name)
  81. {
  82. if (ind->flags.in.directory && !flags.in.present)
  83. ind->fs->load_dentry(this);
  84. auto iter = idx_children->find(name);
  85. if (!iter) {
  86. errno = ENOTFOUND;
  87. return nullptr;
  88. }
  89. return iter->value;
  90. }
  91. fs::vfs::dentry* fs::vfs::dentry::replace(dentry* val)
  92. {
  93. // TODO: prevent the dirent to be swapped out of memory
  94. parent->idx_children->find(this->name)->value = val;
  95. return this;
  96. }
  97. void fs::vfs::dentry::invalidate(void)
  98. {
  99. // TODO: write back
  100. flags.in.dirty = 0;
  101. children->clear();
  102. idx_children->clear();
  103. flags.in.present = 0;
  104. }
  105. fs::vfs::vfs(void)
  106. : _root(nullptr, nullptr, "/")
  107. {
  108. }
  109. fs::inode* fs::vfs::cache_inode(inode_flags flags, uint32_t perm, size_t size, ino_t ino)
  110. {
  111. auto iter = _inodes.insert(types::make_pair(ino, inode { flags, perm, ino, this, size }));
  112. return &iter->value;
  113. }
  114. fs::inode* fs::vfs::get_inode(ino_t ino)
  115. {
  116. auto iter = _inodes.find(ino);
  117. // TODO: load inode from disk if not found
  118. if (iter)
  119. return &iter->value;
  120. else
  121. return nullptr;
  122. }
  123. void fs::vfs::register_root_node(inode* root)
  124. {
  125. if (!_root.ind)
  126. _root.ind = root;
  127. }
  128. int fs::vfs::load_dentry(dentry* ent)
  129. {
  130. auto* ind = ent->ind;
  131. if (!ind->flags.in.directory) {
  132. errno = ENOTDIR;
  133. return GB_FAILED;
  134. }
  135. size_t offset = 0;
  136. for (int ret = 1; ret > 0; offset += ret) {
  137. ret = this->inode_readdir(ind, offset,
  138. [&, this](const char* name, size_t len, ino_t ino, uint8_t) -> int {
  139. if (!len)
  140. ent->append(get_inode(ino), name, false);
  141. else
  142. ent->append(get_inode(ino), dentry::name_type(name, len), false);
  143. return GB_OK;
  144. });
  145. }
  146. ent->flags.in.present = 1;
  147. return GB_OK;
  148. }
  149. int fs::vfs::mount(dentry* mnt, vfs* new_fs)
  150. {
  151. if (!mnt->ind->flags.in.directory) {
  152. errno = ENOTDIR;
  153. return GB_FAILED;
  154. }
  155. auto* new_ent = new_fs->root();
  156. new_ent->parent = mnt->parent;
  157. new_ent->name = mnt->name;
  158. auto* orig_ent = mnt->replace(new_ent);
  159. _mount_recover_list.emplace(new_ent, orig_ent);
  160. new_ent->ind->flags.in.mount_point = 1;
  161. return GB_OK;
  162. }
  163. size_t fs::vfs::inode_read(inode*, char*, size_t, size_t, size_t)
  164. {
  165. assert(false);
  166. return 0xffffffff;
  167. }
  168. size_t fs::vfs::inode_write(inode*, const char*, size_t, size_t)
  169. {
  170. assert(false);
  171. return 0xffffffff;
  172. }
  173. int fs::vfs::inode_mkfile(dentry*, const char*)
  174. {
  175. assert(false);
  176. return GB_FAILED;
  177. }
  178. int fs::vfs::inode_mknode(dentry*, const char*, node_t)
  179. {
  180. assert(false);
  181. return GB_FAILED;
  182. }
  183. int fs::vfs::inode_rmfile(dentry*, const char*)
  184. {
  185. assert(false);
  186. return GB_FAILED;
  187. }
  188. int fs::vfs::inode_mkdir(dentry*, const char*)
  189. {
  190. assert(false);
  191. return GB_FAILED;
  192. }
  193. int fs::vfs::inode_stat(dentry*, stat*)
  194. {
  195. assert(false);
  196. return GB_FAILED;
  197. }
  198. uint32_t fs::vfs::inode_getnode(fs::inode*)
  199. {
  200. assert(false);
  201. return 0xffffffff;
  202. }
  203. class tmpfs : public virtual fs::vfs {
  204. private:
  205. using fe_t = tmpfs_file_entry;
  206. using vfe_t = vector<fe_t>;
  207. using fdata_t = vector<char>;
  208. private:
  209. fs::ino_t _next_ino;
  210. types::map<fs::ino_t, void*> inode_data;
  211. private:
  212. fs::ino_t _assign_ino(void)
  213. {
  214. return _next_ino++;
  215. }
  216. static constexpr vfe_t* as_vfe(void* data)
  217. {
  218. return static_cast<vfe_t*>(data);
  219. }
  220. static constexpr fdata_t* as_fdata(void* data)
  221. {
  222. return static_cast<fdata_t*>(data);
  223. }
  224. static inline ptr_t as_val(void* data)
  225. {
  226. return reinterpret_cast<ptr_t>(data);
  227. }
  228. inline void* _getdata(fs::ino_t ino) const
  229. {
  230. return inode_data.find(ino)->value;
  231. }
  232. inline fs::ino_t _savedata(void* data)
  233. {
  234. fs::ino_t ino = _assign_ino();
  235. inode_data.insert(types::make_pair(ino, data));
  236. return ino;
  237. }
  238. inline fs::ino_t _savedata(ptr_t data)
  239. {
  240. return _savedata((void*)data);
  241. }
  242. protected:
  243. inline vfe_t* mk_fe_vector(void)
  244. {
  245. return allocator_traits<kernel_allocator<vfe_t>>::allocate_and_construct();
  246. }
  247. inline fdata_t* mk_data_vector(void)
  248. {
  249. return allocator_traits<kernel_allocator<fdata_t>>::allocate_and_construct();
  250. }
  251. void mklink(fs::inode* dir, fs::inode* inode, const char* filename)
  252. {
  253. auto* fes = as_vfe(_getdata(dir->ino));
  254. auto iter = fes->emplace_back(fe_t {
  255. .ino = inode->ino,
  256. .filename = {} });
  257. strncpy(iter->filename, filename, sizeof(iter->filename));
  258. iter->filename[sizeof(iter->filename) - 1] = 0;
  259. dir->size += sizeof(fe_t);
  260. }
  261. virtual int inode_readdir(fs::inode* dir, size_t offset, fs::vfs::filldir_func filldir) override
  262. {
  263. if (!dir->flags.in.directory) {
  264. return -1;
  265. }
  266. auto& entries = *as_vfe(_getdata(dir->ino));
  267. size_t off = offset / sizeof(fe_t);
  268. size_t nread = 0;
  269. for (; (off + 1) <= entries.size(); ++off, nread += sizeof(fe_t)) {
  270. const auto& entry = entries[off];
  271. auto* ind = get_inode(entry.ino);
  272. auto type = DT_REG;
  273. if (ind->flags.in.directory)
  274. type = DT_DIR;
  275. if (ind->flags.in.special_node)
  276. type = DT_BLK;
  277. auto ret = filldir(entry.filename, 0, entry.ino, type);
  278. if (ret != GB_OK)
  279. break;
  280. }
  281. return nread;
  282. }
  283. public:
  284. explicit tmpfs(void)
  285. : _next_ino(1)
  286. {
  287. auto& in = *cache_inode({ INODE_DIR | INODE_MNT }, 0777, 0, _savedata(mk_fe_vector()));
  288. mklink(&in, &in, ".");
  289. mklink(&in, &in, "..");
  290. register_root_node(&in);
  291. }
  292. virtual int inode_mkfile(dentry* dir, const char* filename) override
  293. {
  294. auto& file = *cache_inode({ .v = INODE_FILE }, 0777, 0, _savedata(mk_data_vector()));
  295. mklink(dir->ind, &file, filename);
  296. dir->append(get_inode(file.ino), filename, true);
  297. return GB_OK;
  298. }
  299. virtual int inode_mknode(dentry* dir, const char* filename, fs::node_t sn) override
  300. {
  301. auto& node = *cache_inode({ .v = INODE_NODE }, 0777, 0, _savedata(sn.v));
  302. mklink(dir->ind, &node, filename);
  303. dir->append(get_inode(node.ino), filename, true);
  304. return GB_OK;
  305. }
  306. virtual int inode_mkdir(dentry* dir, const char* dirname) override
  307. {
  308. auto new_dir = cache_inode({ .v = INODE_DIR }, 0777, 0, _savedata(mk_fe_vector()));
  309. mklink(new_dir, new_dir, ".");
  310. mklink(dir->ind, new_dir, dirname);
  311. mklink(new_dir, dir->ind, "..");
  312. dir->append(new_dir, dirname, true);
  313. return GB_OK;
  314. }
  315. virtual size_t inode_read(fs::inode* file, char* buf, size_t buf_size, size_t offset, size_t n) override
  316. {
  317. if (file->flags.in.file != 1)
  318. return 0;
  319. auto* data = as_fdata(_getdata(file->ino));
  320. size_t fsize = data->size();
  321. if (offset + n > fsize)
  322. n = fsize - offset;
  323. if (buf_size < n) {
  324. n = buf_size;
  325. }
  326. memcpy(buf, data->data() + offset, n);
  327. return n;
  328. }
  329. virtual size_t inode_write(fs::inode* file, const char* buf, size_t offset, size_t n) override
  330. {
  331. if (file->flags.in.file != 1)
  332. return 0;
  333. auto* data = as_fdata(_getdata(file->ino));
  334. for (size_t i = data->size(); i < offset + n; ++i) {
  335. data->push_back(0);
  336. }
  337. memcpy(data->data() + offset, buf, n);
  338. return n;
  339. }
  340. virtual int inode_stat(dentry* dir, fs::stat* stat) override
  341. {
  342. auto* file_inode = dir->ind;
  343. stat->st_ino = file_inode->ino;
  344. stat->st_size = file_inode->size;
  345. if (file_inode->flags.in.file) {
  346. stat->st_rdev.v = 0;
  347. stat->st_blksize = 1;
  348. stat->st_blocks = file_inode->size;
  349. }
  350. if (file_inode->flags.in.directory) {
  351. stat->st_rdev.v = 0;
  352. stat->st_blksize = sizeof(fe_t);
  353. stat->st_blocks = file_inode->size;
  354. }
  355. if (file_inode->flags.in.special_node) {
  356. stat->st_rdev.v = as_val(_getdata(file_inode->ino));
  357. stat->st_blksize = 0;
  358. stat->st_blocks = 0;
  359. }
  360. return GB_OK;
  361. }
  362. virtual uint32_t inode_getnode(fs::inode* file) override
  363. {
  364. return as_val(_getdata(file->ino));
  365. }
  366. };
  367. // 8 * 8 for now
  368. static fs::special_node sns[8][8];
  369. size_t fs::vfs_read(fs::inode* file, char* buf, size_t buf_size, size_t offset, size_t n)
  370. {
  371. if (file->flags.in.special_node) {
  372. uint32_t ret = file->fs->inode_getnode(file);
  373. if (ret == SN_INVALID) {
  374. errno = EINVAL;
  375. return 0xffffffff;
  376. }
  377. fs::node_t sn {
  378. .v = ret
  379. };
  380. auto* ptr = &sns[sn.in.major][sn.in.minor];
  381. auto* ops = &ptr->ops;
  382. if (ops && ops->read)
  383. return ops->read(ptr, buf, buf_size, offset, n);
  384. else {
  385. errno = EINVAL;
  386. return 0xffffffff;
  387. }
  388. } else {
  389. return file->fs->inode_read(file, buf, buf_size, offset, n);
  390. }
  391. }
  392. size_t fs::vfs_write(fs::inode* file, const char* buf, size_t offset, size_t n)
  393. {
  394. if (file->flags.in.special_node) {
  395. uint32_t ret = file->fs->inode_getnode(file);
  396. if (ret == SN_INVALID) {
  397. errno = EINVAL;
  398. return 0xffffffff;
  399. }
  400. fs::node_t sn {
  401. .v = ret
  402. };
  403. auto* ptr = &sns[sn.in.major][sn.in.minor];
  404. auto* ops = &ptr->ops;
  405. if (ops && ops->write)
  406. return ops->write(ptr, buf, offset, n);
  407. else {
  408. errno = EINVAL;
  409. return 0xffffffff;
  410. }
  411. } else {
  412. return file->fs->inode_write(file, buf, offset, n);
  413. }
  414. }
  415. int fs::vfs_mkfile(fs::vfs::dentry* dir, const char* filename)
  416. {
  417. return dir->ind->fs->inode_mkfile(dir, filename);
  418. }
  419. int fs::vfs_mknode(fs::vfs::dentry* dir, const char* filename, fs::node_t sn)
  420. {
  421. return dir->ind->fs->inode_mknode(dir, filename, sn);
  422. }
  423. int fs::vfs_rmfile(fs::vfs::dentry* dir, const char* filename)
  424. {
  425. return dir->ind->fs->inode_rmfile(dir, filename);
  426. }
  427. int fs::vfs_mkdir(fs::vfs::dentry* dir, const char* dirname)
  428. {
  429. return dir->ind->fs->inode_mkdir(dir, dirname);
  430. }
  431. fs::vfs::dentry* fs::vfs_open(const char* path)
  432. {
  433. if (path[0] == '/' && path[1] == 0x00) {
  434. return fs::fs_root;
  435. }
  436. auto* cur = fs::fs_root;
  437. size_t n = 0;
  438. switch (*(path++)) {
  439. // absolute path
  440. case '/':
  441. while (true) {
  442. if (path[n] == 0x00) {
  443. cur = cur->find(string(path, n));
  444. return cur;
  445. }
  446. if (path[n] == '/') {
  447. cur = cur->find(string(path, n));
  448. if (!cur)
  449. return cur;
  450. if (path[n + 1] == 0x00) {
  451. return cur;
  452. } else {
  453. path += (n + 1);
  454. n = 0;
  455. continue;
  456. }
  457. }
  458. ++n;
  459. }
  460. break;
  461. // empty string
  462. case 0x00:
  463. return nullptr;
  464. break;
  465. // relative path
  466. default:
  467. return nullptr;
  468. break;
  469. }
  470. return nullptr;
  471. }
  472. int fs::vfs_stat(const char* filename, stat* stat)
  473. {
  474. auto ent = vfs_open(filename);
  475. return vfs_stat(ent, stat);
  476. }
  477. int fs::vfs_stat(fs::vfs::dentry* ent, stat* stat)
  478. {
  479. return ent->ind->fs->inode_stat(ent, stat);
  480. }
  481. static types::list<fs::vfs*>* fs_es;
  482. void fs::register_special_block(
  483. uint16_t major,
  484. uint16_t minor,
  485. fs::special_node_read read,
  486. fs::special_node_write write,
  487. uint32_t data1,
  488. uint32_t data2)
  489. {
  490. fs::special_node& sn = sns[major][minor];
  491. sn.ops.read = read;
  492. sn.ops.write = write;
  493. sn.data1 = data1;
  494. sn.data2 = data2;
  495. }
  496. fs::vfs* fs::register_fs(vfs* fs)
  497. {
  498. fs_es->push_back(fs);
  499. return fs;
  500. }
  501. size_t b_null_read(fs::special_node*, char* buf, size_t buf_size, size_t, size_t n)
  502. {
  503. if (n >= buf_size)
  504. n = buf_size;
  505. memset(buf, 0x00, n);
  506. return n;
  507. }
  508. size_t b_null_write(fs::special_node*, const char*, size_t, size_t n)
  509. {
  510. return n;
  511. }
  512. static size_t console_read(fs::special_node*, char* buf, size_t buf_size, size_t, size_t n)
  513. {
  514. return console->read(buf, buf_size, n);
  515. }
  516. static size_t console_write(fs::special_node*, const char* buf, size_t, size_t n)
  517. {
  518. size_t orig_n = n;
  519. while (n--)
  520. console->putchar(*(buf++));
  521. return orig_n;
  522. }
  523. void init_vfs(void)
  524. {
  525. using namespace fs;
  526. // null
  527. register_special_block(0, 0, b_null_read, b_null_write, 0, 0);
  528. // console (supports serial console only for now)
  529. // TODO: add interface to bind console device to other devices
  530. register_special_block(1, 0, console_read, console_write, 0, 0);
  531. fs_es = types::pnew<types::kernel_ident_allocator>(fs_es);
  532. auto* rootfs = types::_new<types::kernel_allocator, tmpfs>();
  533. fs_es->push_back(rootfs);
  534. fs_root = rootfs->root();
  535. vfs_mkdir(fs_root, "dev");
  536. vfs_mkdir(fs_root, "root");
  537. vfs_mkdir(fs_root, "mnt");
  538. vfs_mkfile(fs_root, "init");
  539. auto* init = vfs_open("/init");
  540. const char* str = "#/bin/sh\nexec /bin/sh\n";
  541. vfs_write(init->ind, str, 0, strlen(str));
  542. auto* dev = vfs_open("/dev");
  543. vfs_mknode(dev, "null", { .in { .major = 0, .minor = 0 } });
  544. vfs_mknode(dev, "console", { .in { .major = 1, .minor = 0 } });
  545. vfs_mknode(dev, "hda", { .in { .major = 2, .minor = 0 } });
  546. stat _stat {};
  547. vfs_stat("/init", &_stat);
  548. vfs_stat("/", &_stat);
  549. vfs_stat("/dev", &_stat);
  550. vfs_stat("/dev/null", &_stat);
  551. vfs_stat("/dev/console", &_stat);
  552. vfs_stat("/dev/hda", &_stat);
  553. }