1 #include <lunaix/foptions.h>
2 #include <lunaix/fs/api.h>
3 #include <lunaix/mm/valloc.h>
4 #include <lunaix/process.h>
5 #include <lunaix/spike.h>
6 #include <lunaix/syscall_utils.h>
7 #include <lunaix/syslog.h>
8 #include <lunaix/types.h>
12 struct llist_header all_mnts = { .next = &all_mnts, .prev = &all_mnts };
15 __vfs_attach_vmnt(struct v_dnode* mnt_point, struct v_mount* vmnt)
17 vmnt->mnt_point = mnt_point;
18 vfs_d_assign_vmnt(mnt_point, vmnt);
19 vfs_ref_dnode(mnt_point);
22 static struct v_mount*
23 __vfs_create_mount(struct v_mount* parent, struct v_superblock* mnt_sb)
25 struct v_mount* mnt = vzalloc(sizeof(struct v_mount));
30 llist_init_head(&mnt->submnts);
31 llist_init_head(&mnt->sibmnts);
32 llist_append(&all_mnts, &mnt->list);
33 mutex_init(&mnt->lock);
36 vfs_vmnt_assign_sb(mnt, mnt_sb);
40 mutex_lock(&mnt->parent->lock);
41 llist_append(&parent->submnts, &mnt->sibmnts);
42 mutex_unlock(&mnt->parent->lock);
49 __vfs_detach_vmnt(struct v_mount* mnt)
51 assert(llist_empty(&mnt->submnts));
53 vfs_unref_dnode(mnt->mnt_point);
54 assert(!mnt->busy_counter);
57 mnt_chillax(mnt->parent);
60 mnt->mnt_point->mnt = NULL;
62 llist_delete(&mnt->sibmnts);
63 llist_delete(&mnt->list);
68 __detach_node_cache_ref(struct hbucket* bucket)
74 bucket->head->pprev = 0;
78 __vfs_do_unmount(struct v_mount* mnt)
81 struct v_superblock* sb = mnt->super_block;
83 if ((errno = sb->fs->unmount(sb))) {
87 // detached the inodes from cache, and let lru policy to recycle them
88 for (size_t i = 0; i < VFS_HASHTABLE_SIZE; i++) {
89 __detach_node_cache_ref(&sb->i_cache[i]);
90 __detach_node_cache_ref(&sb->d_cache[i]);
93 struct v_dnode *pos, *next;
94 llist_for_each(pos, next, &mnt->mnt_point->children, siblings)
99 __vfs_detach_vmnt(mnt);
100 vfs_d_assign_vmnt(mnt->mnt_point, mnt->parent);
106 mnt_mkbusy(struct v_mount* mnt)
108 mutex_lock(&mnt->lock);
110 mutex_unlock(&mnt->lock);
114 mnt_chillax(struct v_mount* mnt)
116 mutex_lock(&mnt->lock);
118 mutex_unlock(&mnt->lock);
122 vfs_mount_root(const char* fs_name, struct device* device)
124 extern struct v_dnode* vfs_sysroot;
126 if (vfs_sysroot->mnt && (errno = vfs_unmount_at(vfs_sysroot))) {
129 return vfs_mount_at(fs_name, device, vfs_sysroot, 0);
133 vfs_mount(const char* target,
135 struct device* device,
142 vfs_walk(__current->cwd, target, &mnt, NULL, VFS_WALK_MKPARENT))) {
143 errno = vfs_mount_at(fs_name, device, mnt, options);
150 vfs_unmount(const char* target)
155 if (!(errno = vfs_walk(__current->cwd, target, &mnt, NULL, 0))) {
156 errno = vfs_unmount_at(mnt);
163 vfs_mount_fsat(struct filesystem* fs,
164 struct device* device,
165 struct v_dnode* mnt_point,
169 if (device && device->dev_type != DEV_IFVOL) {
173 if (mnt_point->inode && !check_directory_node(mnt_point->inode)) {
177 if ((fs->types & FSTYPE_ROFS)) {
181 if (!(fs->types & FSTYPE_PSEUDO) && !device) {
188 struct v_mount *parent_mnt, *vmnt;
189 struct v_superblock *sb;
191 fsname = HSTR_VAL(fs->fs_name);
192 parent_mnt = mnt_point->mnt;
195 dev_name = device ? device->name_val : "sys";
197 // prepare v_superblock for fs::mount invoke
200 sb->root = mnt_point;
202 vmnt = __vfs_create_mount(parent_mnt, sb);
209 __vfs_attach_vmnt(mnt_point, vmnt);
211 mnt_point->mnt->flags = options;
212 if (!(errno = fs->mount(sb, mnt_point))) {
213 kprintf("mount: dev=%s, fs=%s, mode=%d",
214 dev_name, fsname, options);
222 ERROR("failed mount: dev=%s, fs=%s, mode=%d, err=%d",
223 dev_name, fsname, options, errno);
225 __vfs_detach_vmnt(mnt_point->mnt);
226 vfs_d_assign_vmnt(mnt_point, parent_mnt);
228 mnt_point->mnt = parent_mnt;
234 vfs_mount_at(const char* fs_name,
235 struct device* device,
236 struct v_dnode* mnt_point,
240 struct filesystem* fs = fsm_get(fs_name);
245 return vfs_mount_fsat(fs, device, mnt_point, options);
252 while (fsm_itnext(&fsi))
254 if ((fsi.fs->types & FSTYPE_PSEUDO)) {
258 INFO("mount attempt: %s", HSTR_VAL(fsi.fs->fs_name));
259 errno = vfs_mount_fsat(fsi.fs, device, mnt_point, options);
269 vfs_unmount_at(struct v_dnode* mnt_point)
272 struct v_superblock* sb;
274 sb = mnt_point->super_block;
279 if (sb->root != mnt_point) {
283 if (mnt_check_busy(mnt_point->mnt)) {
287 return __vfs_do_unmount(mnt_point->mnt);
291 vfs_check_writable(struct v_dnode* dnode)
293 if ((dnode->mnt->flags & MNT_RO)) {
297 if (!check_allow_write(dnode->inode)) {
304 __DEFINE_LXSYSCALL4(int,
315 struct device* device = NULL;
316 struct v_dnode *dev = NULL, *mnt = NULL;
319 // It is fine if source is not exist, as some mounting don't require it
320 vfs_walk(__current->cwd, source, &dev, NULL, 0);
322 if ((errno = vfs_walk(__current->cwd, target, &mnt, NULL, 0))) {
326 if (mnt->ref_count > 1) {
331 if (mnt->mnt->mnt_point == mnt) {
337 if (!check_voldev_node(dev->inode)) {
342 device = resolve_device(dev->inode->data);
346 errno = vfs_mount_at(fstype, device, mnt, options);
349 return DO_STATUS(errno);
352 __DEFINE_LXSYSCALL1(int, unmount, const char*, target)
354 return vfs_unmount(target);