1 #include <lunaix/foptions.h>
3 #include <lunaix/mm/valloc.h>
4 #include <lunaix/process.h>
5 #include <lunaix/spike.h>
6 #include <lunaix/syslog.h>
7 #include <lunaix/types.h>
11 struct llist_header all_mnts = { .next = &all_mnts, .prev = &all_mnts };
14 vfs_create_mount(struct v_mount* parent, struct v_dnode* mnt_point)
16 struct v_mount* mnt = vzalloc(sizeof(struct v_mount));
21 llist_init_head(&mnt->submnts);
22 llist_append(&all_mnts, &mnt->list);
23 mutex_init(&mnt->lock);
26 mnt->mnt_point = mnt_point;
27 mnt->super_block = mnt_point->super_block;
31 mutex_lock(&mnt->parent->lock);
32 llist_append(&parent->submnts, &mnt->sibmnts);
33 mutex_unlock(&mnt->parent->lock);
36 atomic_fetch_add(&mnt_point->ref_count, 1);
42 __vfs_do_unmount(struct v_mount* mnt)
45 struct v_superblock* sb = mnt->super_block;
47 if ((errno = sb->fs->unmount(sb))) {
51 llist_delete(&mnt->list);
52 llist_delete(&mnt->sibmnts);
54 // detached the inodes from cache, and let lru policy to recycle them
55 for (size_t i = 0; i < VFS_HASHTABLE_SIZE; i++) {
56 struct hbucket* bucket = &sb->i_cache[i];
60 bucket->head->pprev = 0;
63 mnt_chillax(mnt->parent);
66 vfs_d_free(mnt->mnt_point);
73 mnt_mkbusy(struct v_mount* mnt)
75 mutex_lock(&mnt->lock);
77 mutex_unlock(&mnt->lock);
81 mnt_chillax(struct v_mount* mnt)
83 mutex_lock(&mnt->lock);
85 mutex_unlock(&mnt->lock);
89 vfs_mount_root(const char* fs_name, struct device* device)
91 extern struct v_dnode* vfs_sysroot;
93 if (vfs_sysroot->mnt && (errno = vfs_unmount_at(vfs_sysroot))) {
96 return vfs_mount_at(fs_name, device, vfs_sysroot, 0);
100 vfs_mount(const char* target,
102 struct device* device,
109 vfs_walk(__current->cwd, target, &mnt, NULL, VFS_WALK_MKPARENT))) {
110 errno = vfs_mount_at(fs_name, device, mnt, options);
117 vfs_unmount(const char* target)
122 if (!(errno = vfs_walk(__current->cwd, target, &mnt, NULL, 0))) {
123 errno = vfs_unmount_at(mnt);
130 vfs_mount_at(const char* fs_name,
131 struct device* device,
132 struct v_dnode* mnt_point,
135 if (device && device->dev_type != DEV_IFVOL) {
139 if (mnt_point->inode && !(mnt_point->inode->itype & VFS_IFDIR)) {
143 struct filesystem* fs = fsm_get(fs_name);
148 if (fs->types == FSTYPE_ROFS) {
152 char* dev_name = "sys";
153 struct v_mount* parent_mnt = mnt_point->mnt;
154 struct v_superblock *sb = vfs_sb_alloc(), *old_sb = mnt_point->super_block;
156 mnt_point->super_block = sb;
159 dev_name = device->name_val;
163 if (!(errno = fs->mount(sb, mnt_point))) {
165 sb->root = mnt_point;
167 if (!(mnt_point->mnt = vfs_create_mount(parent_mnt, mnt_point))) {
172 kprintf("mount: dev=%s, fs=%s, mode=%d\n", dev_name, fs_name, options);
174 mnt_point->mnt->flags = options;
182 kprintf(KERROR "mount: dev=%s, fs=%s, mode=%d, err=%d\n",
187 mnt_point->super_block = old_sb;
193 vfs_unmount_at(struct v_dnode* mnt_point)
196 struct v_superblock* sb = mnt_point->super_block;
201 if (sb->root != mnt_point) {
205 if (mnt_point->mnt->busy_counter) {
209 if (!(errno = __vfs_do_unmount(mnt_point->mnt))) {
210 atomic_fetch_sub(&mnt_point->ref_count, 1);
217 vfs_check_writable(struct v_dnode* dnode)
219 if ((dnode->mnt->flags & MNT_RO)) {
225 __DEFINE_LXSYSCALL4(int,
236 struct v_dnode *dev, *mnt;
239 if ((errno = vfs_walk(__current->cwd, source, &dev, NULL, 0))) {
243 if ((errno = vfs_walk(__current->cwd, target, &mnt, NULL, 0))) {
247 if (mnt->ref_count > 1) {
252 // By our convention.
253 // XXX could we do better?
254 struct device* device = (struct device*)dev->inode->data;
256 if (!(dev->inode->itype & VFS_IFVOLDEV) || !device) {
261 errno = vfs_mount_at(fstype, device, mnt, options);
264 return DO_STATUS(errno);
267 __DEFINE_LXSYSCALL1(int, unmount, const char*, target)
269 return vfs_unmount(target);