CS350 COS
COS
Loading...
Searching...
No Matches
o2fs.c File Reference
#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"
Include dependency graph for o2fs.c:

Go to the source code of this file.

Functions

VFSO2FS_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)
 
VNodeO2FSLoadVNode (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)
 

Variables

static VFSOp O2FSOperations
 

Function Documentation

◆ O2FS_Close()

int O2FS_Close ( VNode fn)

Definition at line 465 of file o2fs.c.

466{
467 return 0;
468}

◆ O2FS_GetRoot()

int O2FS_GetRoot ( VFS fs,
VNode **  dn 
)

O2FS_GetRoot –

Read the root directory Inode.

Parameters
[in]fsVFS Instance.
[out]dnVNode of the root directory.
Returns
0 on success, otherwise error.

Definition at line 353 of file o2fs.c.

354{
355 int status;
356 VNode *vn;
357 BufCacheEntry *entry;
358 BNode *bn;
359
360 if (fs->root) {
361 fs->root->refCount++;
362 *dn = fs->root;
363 return 0;
364 }
365
366 status = BufCache_Read(fs->disk, fs->fsval, &entry);
367 if (status < 0) {
368 Alert(o2fs, "disk read error\n");
369 return status;
370 }
371
372 bn = entry->buffer;
373 if (memcmp(&bn->magic, BNODE_MAGIC, 8) != 0) {
374 Alert(o2fs, "bad BNode magic\n");
375 BufCache_Release(entry);
376 return -1;
377 }
378 if (bn->versionMajor != O2FS_VERSION_MAJOR ||
380 Alert(o2fs, "unsupported BNode version\n");
381 BufCache_Release(entry);
382 return -1;
383 }
384
385 vn = VNode_Alloc();
386 vn->op = &O2FSOperations;
387 vn->disk = fs->disk;
388 Spinlock_Init(&vn->lock, "VNode Lock", SPINLOCK_TYPE_NORMAL);
389 vn->refCount = 1;
390 vn->fsptr = entry;
391 vn->vfs = fs;
392
393 *dn = vn;
394
395 return 0;
396}
int BufCache_Read(Disk *disk, uint64_t diskOffset, BufCacheEntry **entry)
Definition: bufcache.c:229
void BufCache_Release(BufCacheEntry *entry)
Definition: bufcache.c:205
#define Alert(_module, _format,...)
Definition: kassert.h:28
static VFSOp O2FSOperations
Definition: o2fs.c:29
uint8_t magic[8]
Definition: o2fs.h:84
uint16_t versionMinor
Definition: o2fs.h:86
#define BNODE_MAGIC
Definition: o2fs.h:93
#define O2FS_VERSION_MINOR
Definition: o2fs.h:31
uint16_t versionMajor
Definition: o2fs.h:85
#define O2FS_VERSION_MAJOR
Definition: o2fs.h:30
Definition: o2fs.h:83
#define SPINLOCK_TYPE_NORMAL
Definition: spinlock.h:12
void Spinlock_Init(Spinlock *lock, const char *name, uint64_t type)
Definition: spinlock.c:43
int memcmp(const void *b1, const void *b2, size_t len)
Definition: string.c:192
void * buffer
Definition: bufcache.h:11
Spinlock lock
Definition: vfs.h:27
VFSOp * op
Definition: vfs.h:25
uint64_t refCount
Definition: vfs.h:28
Disk * disk
Definition: vfs.h:13
Disk * disk
Definition: vfs.h:26
VFS * vfs
Definition: vfs.h:32
void * fsptr
Definition: vfs.h:30
uint64_t fsval
Definition: vfs.h:18
VNode * root
Definition: vfs.h:20
Definition: vfs.h:24
Here is the call graph for this function:
Here is the caller graph for this function:

◆ O2FS_Lookup()

int O2FS_Lookup ( VNode dn,
VNode **  fn,
const char *  name 
)

O2FS_Lookup –

Lookup a directory entry within a given directory.

Parameters
[in]vnVNode of the directory to look through.
[out]fnVNode of the entry if found.
[in]nameName of the file.
Returns
0 on success, otherwise error.

Definition at line 416 of file o2fs.c.

417{
418 int status;
419 VFS *vfs = dn->vfs;
420 BufCacheEntry *sbEntry = (BufCacheEntry *)vfs->fsptr;
421 SuperBlock *sb = sbEntry->buffer;
422 BufCacheEntry *dirEntry = (BufCacheEntry *)dn->fsptr;
423 BNode *dirBN = dirEntry->buffer;
424 uint64_t blocks = (dirBN->size + sb->blockSize - 1) / sb->blockSize;
425 uint64_t b;
426
427 DLOG(o2fs, "Lookup %lld %d\n", dirBN->size, blocks);
428
429 for (b = 0; b < blocks; b++) {
430 // Read block
431 int e;
432 int entryPerBlock = sb->blockSize / sizeof(BDirEntry);
433 BufCacheEntry *entry;
434 BDirEntry *dir;
435
436 status = O2FSResolveBuf(dn, b, &entry);
437 if (status != 0)
438 return status;
439
440 dir = (BDirEntry *)entry->buffer;
441 for (e = 0; e < entryPerBlock; e++) {
442 if (strcmp((char *)dir[e].magic, BDIR_MAGIC) == 0) {
443 O2FSDumpDirEntry(&dir[e]);
444
445 if (strcmp((char *)dir[e].name, name) == 0) {
446 *fn = O2FSLoadVNode(vfs, &dir[e].objId);
447 return 0;
448 }
449 }
450 }
451
452 BufCache_Release(entry);
453 }
454
455 return -1;
456}
#define DLOG(_module, _format,...)
Definition: kassert.h:37
void O2FSDumpDirEntry(BDirEntry *entry)
Definition: o2fs.c:399
int O2FSResolveBuf(VNode *vn, uint64_t b, BufCacheEntry **dentp)
Definition: o2fs.c:326
VNode * O2FSLoadVNode(VFS *fs, ObjID *objid)
Definition: o2fs.c:210
#define BDIR_MAGIC
Definition: o2fs.h:112
uint64_t size
Definition: o2fs.h:88
Definition: o2fs.h:99
int strcmp(const char *s1, const char *s2)
Definition: string.c:81
unsigned long uint64_t
Definition: types.h:13
void * fsptr
Definition: vfs.h:17
Definition: vfs.h:11
Here is the call graph for this function:

◆ O2FS_Mount()

VFS * O2FS_Mount ( Disk disk)

Definition at line 42 of file o2fs.c.

43{
44 int status;
45 VFS *fs = VFS_Alloc();
46 BufCacheEntry *entry;
47 SuperBlock *sb;
48
49 ASSERT(sizeof(BDirEntry) == 512);
50
51 if (!fs)
52 return NULL;
53
54 status = BufCache_Read(disk, 0, &entry);
55 if (status < 0) {
56 Alert(o2fs, "Disk cache read failed\n");
57 return NULL;
58 }
59
60 // Read superblock
61 sb = entry->buffer;
62 if (memcmp(sb->magic, SUPERBLOCK_MAGIC, 8) != 0) {
63 Alert(o2fs, "Invalid file system\n");
64 BufCache_Release(entry);
65 return NULL;
66 }
69 Alert(o2fs, "Unsupported file system version\n");
70 BufCache_Release(entry);
71 return NULL;
72 }
73
74 // Read bitmap
75 for (int i = 0; i < sb->bitmapSize; i++) {
76 ASSERT(i < 16);
77
78 BufCacheEntry *bentry;
79 uint64_t offset = sb->bitmapOffset + i * sb->blockSize;
80
81 if (BufCache_Read(disk, offset, &bentry) < 0) {
82 Alert(o2fs, "Bitmap read failed\n");
83 for (i = 0; i < 16; i++)
85 BufCache_Release(entry);
86 return NULL;
87 }
88
89 fs->bitmap[i] = bentry;
90 }
91
92 DLOG(o2fs, "File system mounted\n");
93 DLOG(o2fs, "Root @ 0x%llx\n", sb->root.offset);
94
95 fs->fsptr = entry;
96 fs->fsval = sb->root.offset;
97 fs->blksize = sb->blockSize;
98
99 // Setup VFS structure
100 fs->op = &O2FSOperations;
101 fs->disk = disk;
102 Spinlock_Init(&fs->lock, "O2FS Lock", SPINLOCK_TYPE_NORMAL);
103 fs->refCount = 1;
104 fs->root = NULL;
105
106 status = O2FS_GetRoot(fs, &fs->root);
107 if (status < 0) {
108 Alert(o2fs, "Mount failed");
109 BufCache_Release(entry);
110 return NULL;
111 }
112
113 return fs;
114}
#define ASSERT(_x)
Definition: kassert.h:8
int O2FS_GetRoot(VFS *fs, VNode **dn)
Definition: o2fs.c:353
#define SUPERBLOCK_MAGIC
Definition: o2fs.h:63
uint8_t magic[8]
Definition: o2fs.h:47
ObjID root
Definition: o2fs.h:58
uint16_t versionMinor
Definition: o2fs.h:49
uint16_t versionMajor
Definition: o2fs.h:48
uint64_t offset
Definition: o2fs.h:39
uint64_t bitmapSize
Definition: o2fs.h:54
uint64_t blockSize
Definition: o2fs.h:53
uint64_t bitmapOffset
Definition: o2fs.h:55
#define NULL
Definition: stddef.h:6
void * bitmap[16]
Definition: vfs.h:21
uint64_t blksize
Definition: vfs.h:19
Spinlock lock
Definition: vfs.h:14
VFSOp * op
Definition: vfs.h:12
uint64_t refCount
Definition: vfs.h:15
Here is the call graph for this function:
Here is the caller graph for this function:

◆ O2FS_Open()

int O2FS_Open ( VNode fn)

Definition at line 459 of file o2fs.c.

460{
461 return 0;
462}

◆ O2FS_Read()

int O2FS_Read ( VNode fn,
void *  buf,
uint64_t  off,
uint64_t  len 
)

O2FS_Read –

Read from a VNode.

Parameters
[in]fnVNode of the file.
[out]bufBuffer to read into.
[in]offOffset within the file.
[in]lenLength 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;
515 VFS *vfs = fn->vfs;
516 BufCacheEntry *sbEntry = (BufCacheEntry *)vfs->fsptr;
517 SuperBlock *sb = sbEntry->buffer;
518 BufCacheEntry *fileEntry = (BufCacheEntry *)fn->fsptr;
519 BNode *fileBN = fileEntry->buffer;
520 uint64_t blocks = (fileBN->size + sb->blockSize - 1) / sb->blockSize;
521 uint64_t readBytes = 0;
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) {
530 len = fileBN->size - off;
531 }
532
533 while (1) {
534 uint64_t b = off / sb->blockSize;
535 uint64_t bOff = off % sb->blockSize;
536 uint64_t bLen;
537 BufCacheEntry *entry;
538
539 if (bOff + len > sb->blockSize) {
540 bLen = sb->blockSize - bOff;
541 } else {
542 bLen = len;
543 }
544
545 status = O2FSResolveBuf(fn, b, &entry);
546 if (status != 0)
547 return status;
548
549 DLOG(o2fs, "READ %lx %lx %lld\n", buf, entry->buffer, bLen);
550 memcpy(buf, entry->buffer + bOff, bLen);
551 BufCache_Release(entry);
552
553 readBytes += bLen;
554 buf += bLen;
555 off += bLen;
556 len -= bLen;
557
558 if (len == 0)
559 break;
560 }
561
562 return readBytes;
563}
static char buf[4096]
Definition: ethdump.c:10
uint64_t len
Definition: multiboot.h:2
void * memcpy(void *dst, const void *src, size_t len)
Definition: string.c:177
Here is the call graph for this function:
Here is the caller graph for this function:

◆ O2FS_ReadDir()

int O2FS_ReadDir ( VNode fn,
void *  buf,
uint64_t  len,
uint64_t off 
)

O2FS_ReadDir –

Read a directory entry.

Parameters
[in]fnVNode of the directory.
[out]bufBuffer to read the directory entry into.
[in]lenLength of the buffer.
[in,out]offOffset 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;
650 BufCacheEntry *fileEntry = (BufCacheEntry *)fn->fsptr;
651 BNode *fileBN = fileEntry->buffer;
652 BDirEntry dirEntry;
653 struct dirent de;
654
655 while (len >= sizeof(de)) {
656 if (*off == fileBN->size)
657 return count;
658 if (*off > fileBN->size)
659 return -EINVAL;
660
661 // XXX: Check offset
662
663 status = O2FS_Read(fn, &dirEntry, *off, sizeof(dirEntry));
664 if (status != sizeof(dirEntry)) {
665 kprintf("Unexpected error reading directory: %d\n", status);
666 return -ENOTDIR;
667 }
668 if (strncmp((char *)&dirEntry.magic[0], BDIR_MAGIC, sizeof(dirEntry.magic)) != 0) {
669 return -ENOTDIR;
670 }
671
672 // XXX: Validation and fill in all fields
673 strcpy(de.d_name, (char *)dirEntry.name);
674
675 status = Copy_Out(&de, (uintptr_t)buf, sizeof(de));
676 if (status != 0)
677 return status;
678
679 *off += sizeof(dirEntry);
680 buf += sizeof(de);
681 len -= sizeof(de);
682
683 count++;
684 }
685
686 return count;
687}
#define EINVAL
Definition: errno.h:12
#define ENOTDIR
Definition: errno.h:16
int Copy_Out(void *fromkernel, uintptr_t touser, uintptr_t len)
Definition: copy.c:70
int kprintf(const char *fmt,...)
Definition: printf.c:210
int O2FS_Read(VNode *fn, void *buf, uint64_t off, uint64_t len)
Definition: o2fs.c:512
char * strcpy(char *to, const char *from)
Definition: string.c:24
int strncmp(const char *s1, const char *s2, size_t len)
Definition: string.c:91
Definition: dirent.h:9
uint64_t uintptr_t
Definition: types.h:16
Here is the call graph for this function:

◆ O2FS_Stat()

int O2FS_Stat ( VNode fn,
struct stat statinfo 
)

O2FS_Stat –

Stat a VNode.

Parameters
[in]fnVNode of the file to stat.
[out]statinfoStat structure.
Returns
0 on success.

Definition at line 481 of file o2fs.c.

482{
483 VFS *vfs = fn->vfs;
484 BufCacheEntry *sbEntry = (BufCacheEntry *)vfs->fsptr;
485 SuperBlock *sb = sbEntry->buffer;
486 BufCacheEntry *fileEntry = (BufCacheEntry *)fn->fsptr;
487 BNode *fileBN = fileEntry->buffer;
488
489 DLOG(o2fs, "O2FS %p %d\n", fileBN, fileBN->size);
490
491 statinfo->st_ino = fileEntry->diskOffset;
492 statinfo->st_size = fileBN->size;
493 statinfo->st_blocks = (fileBN->size + sb->blockSize - 1) / sb->blockSize;
494 statinfo->st_blksize = sb->blockSize;
495
496 return 0;
497}
off_t st_size
Definition: stat.h:11
ino_t st_ino
Definition: stat.h:6
size_t st_blocks
Definition: stat.h:12
size_t st_blksize
Definition: stat.h:13

◆ O2FS_Unmount()

int O2FS_Unmount ( VFS fs)

Definition at line 117 of file o2fs.c.

118{
120 return -1;
121}
#define NOT_IMPLEMENTED()
Definition: kassert.h:13

◆ O2FS_Write()

int O2FS_Write ( VNode fn,
void *  buf,
uint64_t  off,
uint64_t  len 
)

O2FS_Write –

Write to a VNode.

Parameters
[in]fnVNode of the file.
[in]bufBuffer to write out.
[in]offOffset within the file.
[in]lenLength 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;
581 VFS *vfs = fn->vfs;
582 BufCacheEntry *sbEntry = (BufCacheEntry *)vfs->fsptr;
583 SuperBlock *sb = sbEntry->buffer;
584 BufCacheEntry *fileEntry = (BufCacheEntry *)fn->fsptr;
585 BNode *fileBN = fileEntry->buffer;
586 uint64_t blocks = (fileBN->size + sb->blockSize - 1) / sb->blockSize;
587 uint64_t readBytes = 0;
588
589 DLOG(o2fs, "Write %lld %d\n", fileBN->size, blocks);
590
591 // XXX: Check permissions
592
593 if (fileBN->size < (off+len)) {
594 status = O2FSGrowVNode(fn, off+len);
595 if (status < 0)
596 return status;
597 }
598
599 while (1) {
600 uint64_t b = off / sb->blockSize;
601 uint64_t bOff = off % sb->blockSize;
602 uint64_t bLen;
603 BufCacheEntry *entry;
604
605 if (bOff + len > sb->blockSize) {
606 bLen = sb->blockSize - bOff;
607 } else {
608 bLen = len;
609 }
610
611 status = O2FSResolveBuf(fn, b, &entry);
612 if (status != 0)
613 return status;
614
615 DLOG(o2fs, "WRITE %lx %lx %lld\n", buf, entry->buffer, bLen);
616 memcpy(entry->buffer + bOff, buf, bLen);
617
618 BufCache_Write(entry);
619 BufCache_Release(entry);
620
621 readBytes += bLen;
622 buf += bLen;
623 off += bLen;
624 len -= bLen;
625
626 if (len == 0)
627 break;
628 }
629
630 return readBytes;
631}
int BufCache_Write(BufCacheEntry *entry)
Definition: bufcache.c:273
int O2FSGrowVNode(VNode *vn, uint64_t filesz)
Definition: o2fs.c:263
Here is the call graph for this function:

◆ O2FSBAlloc()

uint64_t O2FSBAlloc ( VFS fs)

O2FSBAlloc –

Allocate a block.

Parameters
[in]vfsVFS Instance.
Returns
Block number.

Definition at line 133 of file o2fs.c.

134{
135 for (int i = 0; i < 16; i++) {
136 char *bitmap;
137 BufCacheEntry *bentry = fs->bitmap[i];
138
139 if (fs->bitmap[i] == NULL)
140 break;
141
142 bitmap = bentry->buffer;
143
144 // XXX: Check for end of disk
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 /* Set bit */
149 bitmap[b] |= (1 << bi);
150
151 /* Write bitmap */
152 BufCache_Write(bentry);
153
154 /*
155 * Block index is the sum of:
156 * blksize*8 blocks per bitmap entry
157 * 8 blocks per bitmap byte
158 * bit #
159 */
160 uint64_t blk = fs->blksize*8*i + 8*b + bi;
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}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ O2FSBFree()

void O2FSBFree ( VFS fs,
uint64_t  block 
)

O2FSBFree –

Free a block.

Parameters
[in]vfsVFS Instance.
[in]blockBlock number.

Definition at line 181 of file o2fs.c.

182{
183 uint64_t bitoff = block & 0x7;
184 uint64_t bytoff = (block >> 8) % fs->blksize;
185 uint64_t bufoff = block / (fs->blksize*8);
186
187 DLOG(o2fs, "BFree %lu\n", block);
188
189 BufCacheEntry *bentry = fs->bitmap[bufoff];
190 ASSERT(bentry != NULL);
191
192 char *bitmap = bentry->buffer;
193
194 /* Mask out the bit */
195 bitmap[bytoff] &= ~(1 << bitoff);
196
197 /* Write the bitmap */
198 BufCache_Write(bentry);
199}
Here is the call graph for this function:

◆ O2FSDumpDirEntry()

void O2FSDumpDirEntry ( BDirEntry entry)

Definition at line 399 of file o2fs.c.

400{
401 VLOG(o2fs, "%16s %08llx %08llx\n", entry->name, entry->objId.offset, entry->size);
402}
#define VLOG(_module, _format,...)
Definition: kassert.h:42
uint8_t name[MAXNAMELEN+1]
Definition: o2fs.h:109
uint64_t size
Definition: o2fs.h:102
ObjID objId
Definition: o2fs.h:101
Here is the caller graph for this function:

◆ O2FSGrowVNode()

int O2FSGrowVNode ( VNode vn,
uint64_t  filesz 
)

O2FSGrowVNode –

Grow a VNode.

Parameters
[in]vfsVFS Instance.
[in]bnBNode for the object.
[in]fileszNew file size.
Returns
0 on success, otherwise error code.

Definition at line 263 of file o2fs.c.

264{
265 VFS *vfs = vn->vfs;
266 BufCacheEntry *vnEntry = (BufCacheEntry *)vn->fsptr;
267 BNode *bn = vnEntry->buffer;
268 uint64_t blkstart = (bn->size + vfs->blksize - 1) / vfs->blksize;
269
270 if (filesz > (vfs->blksize * O2FS_DIRECT_PTR))
271 return -EINVAL;
272
273 for (int i = blkstart; i < ((filesz + vfs->blksize - 1) / vfs->blksize); i++) {
274 if (bn->direct[i].offset != 0)
275 continue;
276
277 uint64_t blkno = O2FSBAlloc(vfs);
278 if (blkno == 0) {
279 return -ENOSPC;
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
289 BufCache_Write(vnEntry);
290
291 return 0;
292}
#define ENOSPC
Definition: errno.h:28
uint64_t O2FSBAlloc(VFS *fs)
Definition: o2fs.c:133
#define O2FS_DIRECT_PTR
Definition: o2fs.h:77
Here is the call graph for this function:
Here is the caller graph for this function:

◆ O2FSLoadVNode()

VNode * O2FSLoadVNode ( VFS fs,
ObjID objid 
)

O2FSLoadVNode –

Load a VNode from the disk given an ObjID.

Parameters
[in]vfsVFS Instance.
[in]oobjidObject ID.

Definition at line 210 of file o2fs.c.

211{
212 int status;
213 VNode *vn;
214 BNode *bn;
215 BufCacheEntry *entry;
216
217 status = BufCache_Read(fs->disk, objid->offset, &entry);
218 if (status < 0) {
219 Alert(o2fs, "disk read error\n");
220 return NULL;
221 }
222
223 bn = entry->buffer;
224 if (memcmp(&bn->magic, BNODE_MAGIC, 8) != 0) {
225 Alert(o2fs, "bad BNode magic\n");
226 BufCache_Release(entry);
227 return NULL;
228 }
229 if (bn->versionMajor != O2FS_VERSION_MAJOR ||
231 Alert(o2fs, "unsupported BNode version\n");
232 BufCache_Release(entry);
233 return NULL;
234 }
235
236 vn = VNode_Alloc();
237 if (!vn) {
238 return NULL;
239 }
240
241 vn->op = &O2FSOperations;
242 vn->disk = fs->disk;
243 Spinlock_Init(&vn->lock, "VNode Lock", SPINLOCK_TYPE_NORMAL);
244 vn->refCount = 1;
245 vn->fsptr = entry;
246 vn->vfs = fs;
247
248 return vn;
249}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ O2FSReleaseVNode()

void O2FSReleaseVNode ( VNode vn)

O2FSReleaseVNode –

Decrement VNode reference count and release it if reaches zero.

Parameters
[in]vnVNode.

Definition at line 315 of file o2fs.c.

316{
317 vn->refCount--;
318 if (vn->refCount == 0) {
321 VNode_Free(vn);
322 }
323}
void Spinlock_Destroy(Spinlock *lock)
Definition: spinlock.c:61
Here is the call graph for this function:

◆ O2FSResolveBuf()

int O2FSResolveBuf ( VNode vn,
uint64_t  b,
BufCacheEntry **  dentp 
)

Definition at line 326 of file o2fs.c.

327{
328 BufCacheEntry *vnent = (BufCacheEntry *)vn->fsptr;
329 BufCacheEntry *dent;
330 BNode *bn = vnent->buffer;
331 int status;
332
333 status = BufCache_Read(vn->disk, bn->direct[b].offset, &dent);
334 if (status < 0)
335 return status;
336
337 *dentp = dent;
338
339 return status;
340}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ O2FSRetainVNode()

void O2FSRetainVNode ( VNode vn)

O2FSRetainVNode –

Increment VNode reference count.

Parameters
[in]vnVNode.

Definition at line 302 of file o2fs.c.

303{
304 vn->refCount++;
305}

Variable Documentation

◆ O2FSOperations

VFSOp O2FSOperations
static
Initial value:
= {
.unmount = O2FS_Unmount,
.getroot = O2FS_GetRoot,
.lookup = O2FS_Lookup,
.open = O2FS_Open,
.close = O2FS_Close,
.stat = O2FS_Stat,
.read = O2FS_Read,
.write = O2FS_Write,
.readdir = O2FS_ReadDir,
}
int O2FS_Write(VNode *fn, void *buf, uint64_t off, uint64_t len)
Definition: o2fs.c:578
int O2FS_Open(VNode *fn)
Definition: o2fs.c:459
int O2FS_Unmount(VFS *fs)
Definition: o2fs.c:117
int O2FS_Stat(VNode *fn, struct stat *statinfo)
Definition: o2fs.c:481
int O2FS_Lookup(VNode *dn, VNode **fn, const char *name)
Definition: o2fs.c:416
int O2FS_ReadDir(VNode *fn, void *buf, uint64_t len, uint64_t *off)
Definition: o2fs.c:646
int O2FS_Close(VNode *fn)
Definition: o2fs.c:465

Definition at line 29 of file o2fs.c.