AquilaOS documentation
How it works, and its code
Loading...
Searching...
No Matches
minix.c
Go to the documentation of this file.
1
6#include <core/system.h>
7#include <core/module.h>
8
9#include <fs/vfs.h>
10#include <fs/posix.h>
11#include <fs/vcache.h>
12#include <fs/bcache.h>
13#include <aquila/errno.h>
14#include <ds/bitmap.h>
15
16#include <minix.h>
17
18MALLOC_DEFINE(M_MINIX, "minix", "minix filesystem structure");
19MALLOC_DEFINE(M_MINIX_SB, "minix-sb", "minix filesystem superblock structure");
20
30int minix_inode_build(struct minix *desc, ino_t ino, struct vnode **ref)
31{
32 int err = 0;
33 struct vnode *inode = NULL;
34
35 /* is it in use already? */
36 if ((inode = vcache_find(desc->vcache, ino)))
37 goto found;
38
39 inode = kmalloc(sizeof(struct vnode), &M_VNODE, M_ZERO);
40 if (!inode) return -ENOMEM;
41
43
44 if ((err = minix_inode_read(desc, ino, &minix_inode)))
45 goto error;
46
47 inode->ino = ino;
48 inode->size = minix_inode.size;
49 inode->mode = minix_inode.mode;
50 inode->uid = minix_inode.uid;
51 inode->gid = minix_inode.gid;
52 inode->nlink = minix_inode.nlinks;
53
54 /* a device node's number is in its first zone, as Linux keeps it
55 * (major << 8 | minor, AquilaOS's dev_t) */
56 if (S_ISCHR(minix_inode.mode) || S_ISBLK(minix_inode.mode))
57 inode->rdev = (dev_t) minix_inode.zones[0];
58
59 /* version 1 inodes have one time, the modification time */
61 inode->mtime.tv_nsec = 0;
62
63 inode->fs = &minixfs;
64 inode->p = desc;
65
66 vcache_insert(desc->vcache, inode);
67
68found:
69 if (ref)
70 *ref = inode;
71
72 return 0;
73
74error:
75 if (inode)
76 kfree(inode);
77
78 return err;
79}
80
87int minix_inode_sync(struct vnode *inode)
88{
89 int err = 0;
90
91 struct minix *desc = inode->p;
93
94 if ((err = minix_inode_read(desc, inode->ino, &minix_inode)))
95 return err;
96
97 minix_inode.size = inode->size;
98 minix_inode.mode = inode->mode;
99 minix_inode.uid = inode->uid;
100 minix_inode.gid = inode->gid;
101 minix_inode.nlinks = inode->nlink;
102 minix_inode.mtime = inode->mtime.tv_sec;
103
104 return minix_inode_write(desc, inode->ino, &minix_inode);
105}
106
107/* The filesystem's operations */
108
110static int minix_init()
111{
112 return vfs_install(&minixfs);
113}
114
119static int minix_load(struct vnode *dev, struct vnode **super)
120{
121 int err = 0;
122
123 struct minix_superblock *sb = NULL;
124 struct minix *desc = NULL;
125
126 sb = kmalloc(sizeof(struct minix_superblock), &M_MINIX_SB, 0);
127 if (sb == NULL) return -ENOMEM;
128
129 if ((err = vfs_read(dev, 1024, sizeof(*sb), sb)) < 0)
130 goto error;
131
132 int version = 0;
133 size_t name_len = 0;
134
135 switch (sb->magic) {
136 case MINIX_MAGIC:
137 version = 1;
138 name_len = 14;
139 break;
140 case MINIX_MAGIC2:
141 version = 1;
142 name_len = 30;
143 break;
144 }
145
146 /* only zones of one 1 KiB block, which version 1 has (the code keeps
147 * blocks in buffers on the stack) */
148 if (!version || sb->block_size) {
149 err = -EINVAL;
150 goto error;
151 }
152
153 /* the mounted filesystem's structure */
154 desc = kmalloc(sizeof(struct minix), &M_MINIX, M_ZERO);
155 if (!desc) goto e_nomem;
156
157 desc->supernode = dev;
158 desc->superblock = sb;
159
160 if (version == 1) {
161 desc->bs = 1024UL << sb->block_size;
162
163 desc->imap_off = 1024UL + desc->bs;
164 desc->zmap_off = 1024UL + (1 + sb->imap_blocks) * desc->bs;
165
166 desc->inode_table = 1024UL + (1 + sb->imap_blocks + sb->zmap_blocks) * desc->bs;
167
168 desc->inode_size = 32;
169 desc->name_len = name_len;
170 desc->dentry_size = name_len + 2;
171 } else {
172 err = -ENOTSUP;
173 goto error;
174 }
175
176 /* the bitmaps are kept in memory: unless all of them can be read,
177 * there's no filesystem */
178 size_t imap_size = sb->imap_blocks * desc->bs, zmap_size = sb->zmap_blocks * desc->bs;
179
180 desc->imap.map = kmalloc(imap_size, &M_BUFFER, 0);
181 desc->zmap.map = kmalloc(zmap_size, &M_BUFFER, 0);
182 if (!desc->imap.map || !desc->zmap.map) goto e_nomem;
183
184 /* the bitmaps' last bits: bit i of the inode bitmap is inode i (1 to
185 * ninodes), bit i of the zone bitmap is zone firstdatazone + i - 1
186 * (zones run to nzones - 1); bit 0 of each is reserved */
187 desc->imap.max_idx = sb->ninodes;
188 desc->zmap.max_idx = sb->nzones > sb->firstdatazone ? sb->nzones - sb->firstdatazone : 0;
189
190 ssize_t r;
191
192 if ((r = vfs_read(desc->supernode, desc->imap_off, imap_size, desc->imap.map)) != (ssize_t) imap_size ||
193 (r = vfs_read(desc->supernode, desc->zmap_off, zmap_size, desc->zmap.map)) != (ssize_t) zmap_size) {
194 err = r < 0 ? (int) r : -EIO;
195 goto error;
196 }
197
198 desc->vcache = kmalloc(sizeof(struct vcache), &M_VCACHE, M_ZERO);
199 desc->bcache = kmalloc(sizeof(struct bcache), &M_BCACHE, M_ZERO);
200 if (!desc->vcache || !desc->bcache) goto e_nomem;
201
202 vcache_init(desc->vcache);
203 bcache_init(desc->bcache);
204 if (!desc->vcache->hashmap || !desc->bcache->hashmap) goto e_nomem;
205
206 /* the root directory (if its inode can't be read, there's no
207 * filesystem) */
208 if (super && (err = minix_inode_build(desc, 1, super)))
209 goto error;
210
211 return 0;
212
213e_nomem:
214 err = -ENOMEM;
215error:
216 /* nothing of it is in use yet, since the root comes last */
217 if (desc) {
218 if (desc->vcache && desc->vcache->hashmap)
219 hashmap_free(desc->vcache->hashmap);
220 if (desc->bcache && desc->bcache->hashmap)
221 hashmap_free(desc->bcache->hashmap);
222
223 kfree(desc->vcache);
224 kfree(desc->bcache);
225 kfree(desc->imap.map);
226 kfree(desc->zmap.map);
227 kfree(desc);
228 }
229
230 kfree(sb);
231 return err;
232}
233
236static int minix_mount(struct vnode *dir, int flags, void *_args)
237{
238 struct {
239 char *dev;
240 char *opt;
241 } *args = _args;
242
243 struct vnode *dev = NULL;
244 int err;
245
246 struct uio uio = {0}; /* the device is looked up as root */
247
248 if (!args || !args->dev)
249 return -EINVAL;
250
251 if ((err= vfs_lookup(args->dev, &uio, &dev)))
252 goto error;
253
254 struct vnode *fs;
255
256 if ((err = minixfs.load(dev, &fs)))
257 goto error;
258
259 return vfs_bind(dir, fs);
260
261error:
262 return err;
263}
264
265struct fs minixfs = {
266 .name = "minix",
267 .init = minix_init,
268 .load = minix_load,
269 .mount = minix_mount,
270
271 .vops = {
272 .read = minix_read,
273 .write = minix_write,
274 .readdir = minix_readdir,
275 .finddir = minix_finddir,
276 .trunc = minix_trunc,
277
278 .vmknod = minix_vmknod,
279 .vget = minix_vget,
280 },
281
282 .fops = {
283 .open = posix_file_open,
284 .read = posix_file_read,
285 .write = posix_file_write,
286 .readdir = posix_file_readdir,
287 .lseek = posix_file_lseek,
288 .trunc = posix_file_trunc,
289
290 .eof = posix_file_eof,
291 }
292};
293
void bcache_init(struct bcache *bcache)
Sets up an empty block cache.
Definition bcache.c:35
int posix_file_eof(struct file *file)
Says whether a file's offset is at or past its end, so that a read returns nothing.
Definition helpers.c:17
#define MALLOC_DEFINE(type, _name, _desc)
Definition kvmem.h:30
void * kmalloc(size_t size, struct malloc_type *type, int flags)
Allocates memory for one of the kernel's structures.
Definition kvmem.c:123
#define M_ZERO
Definition kvmem.h:26
void kfree(void *)
Frees an object that kmalloc() gave.
Definition kvmem.c:146
int vfs_lookup(const char *path, struct uio *uio, struct vnode **ref)
Finds the vnode a path names.
Definition lookup.c:349
off_t posix_file_lseek(struct file *file, off_t offset, int whence)
Moves an open file's offset: to offset (SEEK_SET), by offset from where it is (SEEK_CUR),...
Definition lseek.c:22
int minix_inode_read(struct minix *desc, ino_t ino, struct minix_inode *ref)
Reads an inode from the disk.
Definition inode.c:31
int minix_inode_write(struct minix *desc, ino_t ino, struct minix_inode *ref)
Writes an inode to the disk.
Definition inode.c:63
static int minix_mount(struct vnode *dir, int flags, void *_args)
Mounts the minix filesystem of a device (the dev argument) on a directory.
Definition minix.c:236
struct fs minixfs
Definition minix.c:265
int minix_inode_build(struct minix *desc, ino_t ino, struct vnode **ref)
Gets the vnode of an inode: the cached one if it's in use, or a new one made from the inode on the di...
Definition minix.c:30
int minix_inode_sync(struct vnode *inode)
Writes a vnode's attributes back to its inode on the disk.
Definition minix.c:87
static int minix_load(struct vnode *dev, struct vnode **super)
Loads a minix filesystem from a device: its superblock, its bitmaps, and its root directory's vnode i...
Definition minix.c:119
static int minix_init()
Installs the minix filesystem at boot.
Definition minix.c:110
ssize_t minix_read(struct vnode *inode, off_t offset, struct iobuf *io)
Reads from a file.
Definition vops.c:21
int minix_vget(struct vnode *super, ino_t ino, struct vnode **ref)
Gets the vnode of an inode, by its number.
Definition vops.c:363
int minix_finddir(struct vnode *dir, const char *fn, struct dirent *dirent)
Finds the entry of a directory that has a name.
Definition vops.c:324
#define MINIX_MAGIC
Definition minix.h:21
#define MINIX_MAGIC2
Definition minix.h:22
int minix_trunc(struct vnode *inode, off_t len)
Changes a file's length.
Definition vops.c:380
ssize_t minix_readdir(struct vnode *dir, off_t offset, struct dirent *dirent)
Reads a directory's entry at an offset; unused entries don't count.
Definition vops.c:151
int minix_vmknod(struct vnode *dir, const char *fn, mode_t mode, dev_t dev, struct uio *uio, struct vnode **ref)
Makes a node in a directory: a new inode, and an entry for it.
Definition vops.c:216
ssize_t minix_write(struct vnode *inode, off_t offset, struct iobuf *io)
Writes to a file, which grows if the write goes past its end.
Definition vops.c:75
#define MODULE_INIT(name, i, f)
Definition module.h:10
int posix_file_open(struct file *file)
Finishes opening a file: with O_TRUNC, a regular file is truncated to 0 bytes.
Definition open.c:17
ssize_t posix_file_read(struct file *file, struct iobuf *io)
Reads from an open file at its offset, and moves the offset past what was read.
Definition read.c:29
ssize_t posix_file_readdir(struct file *file, struct dirent *dirent)
Reads the directory entry at an open directory's offset, and moves the offset past it.
Definition readdir.c:22
int posix_file_trunc(struct file *file, off_t len)
Truncates (or extends) an open file to a new length.
Definition trunc.c:16
ssize_t posix_file_write(struct file *file, struct iobuf *io)
Writes to an open file at its offset, and moves the offset past what was written.
Definition write.c:25
ssize_t vfs_read(struct vnode *vnode, off_t off, size_t size, void *buf)
Reads from a vnode into a kernel buffer.
Definition read.c:52
#define NULL
Definition stddef.h:27
A filesystem's block cache (fs/bcache.c): its blocks that were read, by their offset.
Definition bcache.h:9
struct hashmap * hashmap
Definition bcache.h:10
size_t max_idx
Definition bitmap.h:19
bitmap_t * map
Definition bitmap.h:18
A device driver: its operations, any of which may be NULL.
Definition dev.h:28
A filesystem type.
Definition vfs.h:98
int(*) load(struct vnode *dev, struct vnode **super)
Definition vfs.h:101
A minix v1 inode, as it is on the disk.
Definition minix.h:64
uint32_t mtime
Definition minix.h:68
uint8_t gid
Definition minix.h:69
uint32_t size
Definition minix.h:67
uint16_t uid
Definition minix.h:66
uint16_t mode
Definition minix.h:65
uint16_t zones[9]
Definition minix.h:71
uint8_t nlinks
Definition minix.h:70
The superblock of minix v1 and v2, as it is on the disk.
Definition minix.h:32
uint16_t magic
Definition minix.h:42
uint16_t block_size
Definition minix.h:39
uint16_t imap_blocks
Definition minix.h:35
uint16_t ninodes
Definition minix.h:33
uint16_t firstdatazone
Definition minix.h:38
uint16_t zmap_blocks
Definition minix.h:36
uint16_t nzones
Definition minix.h:34
A mounted minix filesystem.
Definition minix.h:82
uint32_t zmap_off
Definition minix.h:91
size_t bs
Definition minix.h:101
struct minix_superblock * superblock
Definition minix.h:84
struct vcache * vcache
Definition minix.h:103
size_t name_len
Definition minix.h:88
size_t dentry_size
Definition minix.h:87
struct vnode * supernode
Definition minix.h:83
uint32_t inode_table
Definition minix.h:99
size_t inode_size
Definition minix.h:86
struct bcache * bcache
Definition minix.h:104
struct bitmap imap
Definition minix.h:93
struct bitmap zmap
Definition minix.h:94
uint32_t imap_off
Definition minix.h:90
uint32_t tv_nsec
Definition types.h:32
time_t tv_sec
Definition types.h:31
Who does a filesystem operation: where its paths start, and its credentials and umask.
Definition vfs.h:60
A filesystem's vnode cache (fs/vcache.c): its vnodes in memory, by their inode number,...
Definition vcache.h:10
struct hashmap * hashmap
Definition vcache.h:11
A file in memory (a vnode): what its inode says, and the kernel's own state.
Definition vfs.h:113
ino_t ino
Definition vfs.h:114
nlink_t nlink
Definition vfs.h:121
struct fs * fs
Definition vfs.h:127
_time_t mtime
Definition vfs.h:124
gid_t gid
Definition vfs.h:120
size_t size
Definition vfs.h:115
void * p
the filesystem's own data
Definition vfs.h:130
mode_t mode
Definition vfs.h:118
uid_t uid
Definition vfs.h:119
dev_t rdev
Definition vfs.h:117
uint16_t dev_t
Definition types.h:18
uintptr_t ino_t
Definition types.h:23
long int ssize_t
Definition types.h:12
void vcache_init(struct vcache *vcache)
Sets up an empty vnode cache.
Definition vcache.c:25
struct vnode * vcache_find(struct vcache *vcache, ino_t ino)
Finds the cached vnode of an inode.
Definition vcache.c:80
int vcache_insert(struct vcache *vcache, struct vnode *vnode)
Adds a vnode to a cache.
Definition vcache.c:37
int vfs_bind(struct vnode *dir, struct vnode *root)
Mounts a filesystem on a directory: a lookup that reaches dir goes on in root instead.
Definition vfs.c:53
int vfs_install(struct fs *fs)
Installs a filesystem, so that it can be mounted by name.
Definition vfs.c:85