#include <stdbool.h>
#include <stdint.h>
#include <string.h>
#include <errno.h>
#include <sys/kassert.h>
#include <sys/kmem.h>
#include <sys/spinlock.h>
#include <sys/disk.h>
#include <sys/bufcache.h>
#include <sys/vfs.h>
#include <sys/dirent.h>
#include <sys/thread.h>
#include "o2fs.h"
Go to the source code of this file.
|
VFS * | O2FS_Mount (Disk *disk) |
|
int | O2FS_Unmount (VFS *fs) |
|
int | O2FS_GetRoot (VFS *fs, VNode **dn) |
|
int | O2FS_Lookup (VNode *dn, VNode **fn, const char *name) |
|
int | O2FS_Open (VNode *fn) |
|
int | O2FS_Close (VNode *fn) |
|
int | O2FS_Stat (VNode *fn, struct stat *statinfo) |
|
int | O2FS_Read (VNode *fn, void *buf, uint64_t off, uint64_t len) |
|
int | O2FS_Write (VNode *fn, void *buf, uint64_t off, uint64_t len) |
|
int | O2FS_ReadDir (VNode *fn, void *buf, uint64_t len, uint64_t *off) |
|
uint64_t | O2FSBAlloc (VFS *fs) |
|
void | O2FSBFree (VFS *fs, uint64_t block) |
|
VNode * | O2FSLoadVNode (VFS *fs, ObjID *objid) |
|
int | O2FSGrowVNode (VNode *vn, uint64_t filesz) |
|
void | O2FSRetainVNode (VNode *vn) |
|
void | O2FSReleaseVNode (VNode *vn) |
|
int | O2FSResolveBuf (VNode *vn, uint64_t b, BufCacheEntry **dentp) |
|
void | O2FSDumpDirEntry (BDirEntry *entry) |
|
◆ O2FS_Close()
int O2FS_Close |
( |
VNode * |
fn | ) |
|
◆ O2FS_GetRoot()
int O2FS_GetRoot |
( |
VFS * |
fs, |
|
|
VNode ** |
dn |
|
) |
| |
O2FS_GetRoot –
Read the root directory Inode.
- Parameters
-
[in] | fs | VFS Instance. |
[out] | dn | VNode of the root directory. |
- Returns
- 0 on success, otherwise error.
Definition at line 353 of file o2fs.c.
354{
355 int status;
359
363 return 0;
364 }
365
367 if (status < 0) {
368 Alert(o2fs,
"disk read error\n");
369 return status;
370 }
371
374 Alert(o2fs,
"bad BNode magic\n");
376 return -1;
377 }
380 Alert(o2fs,
"unsupported BNode version\n");
382 return -1;
383 }
384
385 vn = VNode_Alloc();
392
393 *dn = vn;
394
395 return 0;
396}
int BufCache_Read(Disk *disk, uint64_t diskOffset, BufCacheEntry **entry)
void BufCache_Release(BufCacheEntry *entry)
#define Alert(_module, _format,...)
static VFSOp O2FSOperations
#define O2FS_VERSION_MINOR
#define O2FS_VERSION_MAJOR
#define SPINLOCK_TYPE_NORMAL
void Spinlock_Init(Spinlock *lock, const char *name, uint64_t type)
int memcmp(const void *b1, const void *b2, size_t len)
◆ O2FS_Lookup()
int O2FS_Lookup |
( |
VNode * |
dn, |
|
|
VNode ** |
fn, |
|
|
const char * |
name |
|
) |
| |
O2FS_Lookup –
Lookup a directory entry within a given directory.
- Parameters
-
[in] | vn | VNode of the directory to look through. |
[out] | fn | VNode of the entry if found. |
[in] | name | Name of the file. |
- Returns
- 0 on success, otherwise error.
Definition at line 416 of file o2fs.c.
417{
418 int status;
423 BNode *dirBN = dirEntry->buffer;
424 uint64_t blocks = (dirBN->
size + sb->blockSize - 1) / sb->blockSize;
426
427 DLOG(o2fs,
"Lookup %lld %d\n", dirBN->
size, blocks);
428
429 for (b = 0; b < blocks; b++) {
430
431 int e;
432 int entryPerBlock = sb->blockSize /
sizeof(
BDirEntry);
435
437 if (status != 0)
438 return status;
439
441 for (e = 0; e < entryPerBlock; e++) {
444
445 if (
strcmp((
char *)dir[e].name, name) == 0) {
447 return 0;
448 }
449 }
450 }
451
453 }
454
455 return -1;
456}
#define DLOG(_module, _format,...)
void O2FSDumpDirEntry(BDirEntry *entry)
int O2FSResolveBuf(VNode *vn, uint64_t b, BufCacheEntry **dentp)
VNode * O2FSLoadVNode(VFS *fs, ObjID *objid)
int strcmp(const char *s1, const char *s2)
◆ O2FS_Mount()
Definition at line 42 of file o2fs.c.
43{
44 int status;
45 VFS *fs = VFS_Alloc();
48
50
51 if (!fs)
53
55 if (status < 0) {
56 Alert(o2fs,
"Disk cache read failed\n");
58 }
59
60
63 Alert(o2fs,
"Invalid file system\n");
66 }
69 Alert(o2fs,
"Unsupported file system version\n");
72 }
73
74
77
80
82 Alert(o2fs,
"Bitmap read failed\n");
83 for (i = 0; i < 16; i++)
87 }
88
90 }
91
92 DLOG(o2fs,
"File system mounted\n");
94
98
99
105
107 if (status < 0) {
108 Alert(o2fs,
"Mount failed");
111 }
112
113 return fs;
114}
int O2FS_GetRoot(VFS *fs, VNode **dn)
◆ O2FS_Open()
int O2FS_Open |
( |
VNode * |
fn | ) |
|
◆ O2FS_Read()
O2FS_Read –
Read from a VNode.
- Parameters
-
[in] | fn | VNode of the file. |
[out] | buf | Buffer to read into. |
[in] | off | Offset within the file. |
[in] | len | Length of the buffer to read. |
- Returns
- number of bytes on success, otherwise negative error code.
Definition at line 512 of file o2fs.c.
513{
514 int status;
519 BNode *fileBN = fileEntry->buffer;
520 uint64_t blocks = (fileBN->
size + sb->blockSize - 1) / sb->blockSize;
522
523 DLOG(o2fs,
"Read %lld %d\n", fileBN->
size, blocks);
524
525 if (off > fileBN->
size) {
526 return 0;
527 }
528
529 if (off +
len > fileBN->
size) {
531 }
532
533 while (1) {
535 uint64_t bOff = off % sb->blockSize;
538
539 if (bOff +
len > sb->blockSize) {
540 bLen = sb->blockSize - bOff;
541 } else {
543 }
544
546 if (status != 0)
547 return status;
548
552
553 readBytes += bLen;
555 off += bLen;
557
559 break;
560 }
561
562 return readBytes;
563}
void * memcpy(void *dst, const void *src, size_t len)
◆ O2FS_ReadDir()
O2FS_ReadDir –
Read a directory entry.
- Parameters
-
[in] | fn | VNode of the directory. |
[out] | buf | Buffer to read the directory entry into. |
[in] | len | Length of the buffer. |
[in,out] | off | Offset to start from and return the next offset. |
- Returns
- 0 on success, otherwise error.
Definition at line 646 of file o2fs.c.
647{
648 int count = 0;
649 int status;
654
655 while (
len >=
sizeof(de)) {
656 if (*off == fileBN->size)
657 return count;
658 if (*off > fileBN->size)
660
661
662
663 status =
O2FS_Read(fn, &dirEntry, *off,
sizeof(dirEntry));
664 if (status != sizeof(dirEntry)) {
665 kprintf(
"Unexpected error reading directory: %d\n", status);
667 }
668 if (
strncmp((
char *)&dirEntry.magic[0],
BDIR_MAGIC,
sizeof(dirEntry.magic)) != 0) {
670 }
671
672
673 strcpy(de.d_name, (
char *)dirEntry.name);
674
676 if (status != 0)
677 return status;
678
679 *off += sizeof(dirEntry);
682
683 count++;
684 }
685
686 return count;
687}
int Copy_Out(void *fromkernel, uintptr_t touser, uintptr_t len)
int kprintf(const char *fmt,...)
int O2FS_Read(VNode *fn, void *buf, uint64_t off, uint64_t len)
char * strcpy(char *to, const char *from)
int strncmp(const char *s1, const char *s2, size_t len)
◆ O2FS_Stat()
int O2FS_Stat |
( |
VNode * |
fn, |
|
|
struct stat * |
statinfo |
|
) |
| |
O2FS_Stat –
Stat a VNode.
- Parameters
-
[in] | fn | VNode of the file to stat. |
[out] | statinfo | Stat structure. |
- Returns
- 0 on success.
Definition at line 481 of file o2fs.c.
482{
487 BNode *fileBN = fileEntry->buffer;
488
489 DLOG(o2fs,
"O2FS %p %d\n", fileBN, fileBN->
size);
490
491 statinfo->
st_ino = fileEntry->diskOffset;
493 statinfo->
st_blocks = (fileBN->
size + sb->blockSize - 1) / sb->blockSize;
495
496 return 0;
497}
◆ O2FS_Unmount()
int O2FS_Unmount |
( |
VFS * |
fs | ) |
|
Definition at line 117 of file o2fs.c.
118{
120 return -1;
121}
#define NOT_IMPLEMENTED()
◆ O2FS_Write()
O2FS_Write –
Write to a VNode.
- Parameters
-
[in] | fn | VNode of the file. |
[in] | buf | Buffer to write out. |
[in] | off | Offset within the file. |
[in] | len | Length of the buffer to write. |
- Returns
- number of bytes on success, otherwise negative error code.
Definition at line 578 of file o2fs.c.
579{
580 int status;
585 BNode *fileBN = fileEntry->buffer;
586 uint64_t blocks = (fileBN->
size + sb->blockSize - 1) / sb->blockSize;
588
589 DLOG(o2fs,
"Write %lld %d\n", fileBN->
size, blocks);
590
591
592
593 if (fileBN->
size < (off+
len)) {
595 if (status < 0)
596 return status;
597 }
598
599 while (1) {
601 uint64_t bOff = off % sb->blockSize;
604
605 if (bOff +
len > sb->blockSize) {
606 bLen = sb->blockSize - bOff;
607 } else {
609 }
610
612 if (status != 0)
613 return status;
614
615 DLOG(o2fs,
"WRITE %lx %lx %lld\n",
buf, entry->
buffer, bLen);
617
620
621 readBytes += bLen;
623 off += bLen;
625
627 break;
628 }
629
630 return readBytes;
631}
int BufCache_Write(BufCacheEntry *entry)
int O2FSGrowVNode(VNode *vn, uint64_t filesz)
◆ O2FSBAlloc()
O2FSBAlloc –
Allocate a block.
- Parameters
-
- Returns
- Block number.
Definition at line 133 of file o2fs.c.
134{
135 for (int i = 0; i < 16; i++) {
136 char *bitmap;
138
140 break;
141
143
144
145 for (
int b = 0; b < fs->
blksize; b++) {
146 for (int bi = 0; bi < 8; bi++) {
147 if (((bitmap[b] >> bi) & 0x1) == 0) {
148
149 bitmap[b] |= (1 << bi);
150
151
153
154
155
156
157
158
159
161 DLOG(o2fs,
"BAlloc %lu\n", blk);
162 return blk;
163 }
164 }
165 }
166 }
167
168 Alert(o2fs,
"Out of space!\n");
169 return 0;
170}
◆ O2FSBFree()
O2FSBFree –
Free a block.
- Parameters
-
[in] | vfs | VFS Instance. |
[in] | block | Block number. |
Definition at line 181 of file o2fs.c.
182{
186
187 DLOG(o2fs,
"BFree %lu\n", block);
188
191
192 char *bitmap = bentry->
buffer;
193
194
195 bitmap[bytoff] &= ~(1 << bitoff);
196
197
199}
◆ O2FSDumpDirEntry()
Definition at line 399 of file o2fs.c.
400{
402}
#define VLOG(_module, _format,...)
uint8_t name[MAXNAMELEN+1]
◆ O2FSGrowVNode()
O2FSGrowVNode –
Grow a VNode.
- Parameters
-
[in] | vfs | VFS Instance. |
[in] | bn | BNode for the object. |
[in] | filesz | New file size. |
- Returns
- 0 on success, otherwise error code.
Definition at line 263 of file o2fs.c.
264{
269
272
273 for (
int i = blkstart; i < ((filesz + vfs->
blksize - 1) / vfs->
blksize); i++) {
274 if (bn->direct[i].offset != 0)
275 continue;
276
278 if (blkno == 0) {
280 }
281
282 bn->direct[i].offset = blkno * vfs->
blksize;
283
284 }
285
286 DLOG(o2fs,
"Growing: %d\n", filesz);
287 bn->size = filesz;
288
290
291 return 0;
292}
uint64_t O2FSBAlloc(VFS *fs)
◆ O2FSLoadVNode()
O2FSLoadVNode –
Load a VNode from the disk given an ObjID.
- Parameters
-
[in] | vfs | VFS Instance. |
[in] | oobjid | Object ID. |
Definition at line 210 of file o2fs.c.
211{
212 int status;
216
218 if (status < 0) {
219 Alert(o2fs,
"disk read error\n");
221 }
222
225 Alert(o2fs,
"bad BNode magic\n");
228 }
231 Alert(o2fs,
"unsupported BNode version\n");
234 }
235
236 vn = VNode_Alloc();
237 if (!vn) {
239 }
240
247
248 return vn;
249}
◆ O2FSReleaseVNode()
void O2FSReleaseVNode |
( |
VNode * |
vn | ) |
|
O2FSReleaseVNode –
Decrement VNode reference count and release it if reaches zero.
- Parameters
-
Definition at line 315 of file o2fs.c.
316{
321 VNode_Free(vn);
322 }
323}
void Spinlock_Destroy(Spinlock *lock)
◆ O2FSResolveBuf()
Definition at line 326 of file o2fs.c.
327{
331 int status;
332
334 if (status < 0)
335 return status;
336
337 *dentp = dent;
338
339 return status;
340}
◆ O2FSRetainVNode()
void O2FSRetainVNode |
( |
VNode * |
vn | ) |
|
O2FSRetainVNode –
Increment VNode reference count.
- Parameters
-
Definition at line 302 of file o2fs.c.
◆ O2FSOperations
Initial value:= {
}
int O2FS_Write(VNode *fn, void *buf, uint64_t off, uint64_t len)
int O2FS_Unmount(VFS *fs)
int O2FS_Stat(VNode *fn, struct stat *statinfo)
int O2FS_Lookup(VNode *dn, VNode **fn, const char *name)
int O2FS_ReadDir(VNode *fn, void *buf, uint64_t len, uint64_t *off)
int O2FS_Close(VNode *fn)
Definition at line 29 of file o2fs.c.