X-Git-Url: https://scm.lunaixsky.com/lunaix-os.git/blobdiff_plain/a7384053efe345d199440720b437a28e91058ff3..0765e7c133eb393d8cd0292af444543c2edf8ccc:/lunaix-os/kernel/fs/mount.c diff --git a/lunaix-os/kernel/fs/mount.c b/lunaix-os/kernel/fs/mount.c index aa4acef..2b996d4 100644 --- a/lunaix-os/kernel/fs/mount.c +++ b/lunaix-os/kernel/fs/mount.c @@ -1,9 +1,15 @@ +#include #include #include #include +#include +#include +#include #include -static struct llist_header all_mnts = { .next = &all_mnts, .prev = &all_mnts }; +LOG_MODULE("fs") + +struct llist_header all_mnts = { .next = &all_mnts, .prev = &all_mnts }; struct v_mount* vfs_create_mount(struct v_mount* parent, struct v_dnode* mnt_point) @@ -17,17 +23,17 @@ vfs_create_mount(struct v_mount* parent, struct v_dnode* mnt_point) llist_append(&all_mnts, &mnt->list); mutex_init(&mnt->lock); - mnt_mkbusy(parent); mnt->parent = parent; mnt->mnt_point = mnt_point; mnt->super_block = mnt_point->super_block; if (parent) { + mnt_mkbusy(parent); mutex_lock(&mnt->parent->lock); llist_append(&parent->submnts, &mnt->sibmnts); mutex_unlock(&mnt->parent->lock); } - + atomic_fetch_add(&mnt_point->ref_count, 1); return mnt; @@ -57,8 +63,10 @@ __vfs_do_unmount(struct v_mount* mnt) mnt_chillax(mnt->parent); + mnt->mnt_point->mnt = mnt->parent; + vfs_sb_free(sb); - vfs_d_free(mnt->mnt_point); + atomic_fetch_sub(&mnt->mnt_point->ref_count, 1); vfree(mnt); return errno; @@ -67,46 +75,42 @@ __vfs_do_unmount(struct v_mount* mnt) void mnt_mkbusy(struct v_mount* mnt) { - while (mnt) { - mutex_lock(&mnt->lock); - mnt->busy_counter++; - mutex_unlock(&mnt->lock); - - mnt = mnt->parent; - } + mutex_lock(&mnt->lock); + mnt->busy_counter++; + mutex_unlock(&mnt->lock); } void mnt_chillax(struct v_mount* mnt) { - while (mnt) { - mutex_lock(&mnt->lock); - mnt->busy_counter--; - mutex_unlock(&mnt->lock); - - mnt = mnt->parent; - } + mutex_lock(&mnt->lock); + mnt->busy_counter--; + mutex_unlock(&mnt->lock); } int vfs_mount_root(const char* fs_name, struct device* device) { + extern struct v_dnode* vfs_sysroot; int errno = 0; if (vfs_sysroot->mnt && (errno = vfs_unmount_at(vfs_sysroot))) { return errno; } - return vfs_mount_at(fs_name, device, vfs_sysroot); + return vfs_mount_at(fs_name, device, vfs_sysroot, 0); } int -vfs_mount(const char* target, const char* fs_name, struct device* device) +vfs_mount(const char* target, + const char* fs_name, + struct device* device, + int options) { int errno; struct v_dnode* mnt; if (!(errno = vfs_walk(__current->cwd, target, &mnt, NULL, VFS_WALK_MKPARENT))) { - errno = vfs_mount_at(fs_name, device, mnt); + errno = vfs_mount_at(fs_name, device, mnt, options); } return errno; @@ -128,9 +132,14 @@ vfs_unmount(const char* target) int vfs_mount_at(const char* fs_name, struct device* device, - struct v_dnode* mnt_point) + struct v_dnode* mnt_point, + int options) { - if (mnt_point->inode && !(mnt_point->inode->itype & VFS_IFDIR)) { + if (device && device->dev_type != DEV_IFVOL) { + return ENOTBLK; + } + + if (mnt_point->inode && (mnt_point->inode->itype & F_MFILE)) { return ENOTDIR; } @@ -139,13 +148,22 @@ vfs_mount_at(const char* fs_name, return ENODEV; } + if (fs->types == FSTYPE_ROFS) { + options |= MNT_RO; + } + + char* dev_name = "sys"; struct v_mount* parent_mnt = mnt_point->mnt; - struct v_superblock* sb = vfs_sb_alloc(); + struct v_superblock *sb = vfs_sb_alloc(), *old_sb = mnt_point->super_block; sb->dev = device; + mnt_point->super_block = sb; + + if (device) { + dev_name = device->name_val; + } int errno = 0; if (!(errno = fs->mount(sb, mnt_point))) { - mnt_point->super_block = sb; sb->fs = fs; sb->root = mnt_point; @@ -153,6 +171,10 @@ vfs_mount_at(const char* fs_name, errno = ENOMEM; goto cleanup; } + + kprintf("mount: dev=%s, fs=%s, mode=%d", dev_name, fs_name, options); + + mnt_point->mnt->flags = options; } else { goto cleanup; } @@ -160,6 +182,12 @@ vfs_mount_at(const char* fs_name, return errno; cleanup: + ERROR("mount: dev=%s, fs=%s, mode=%d, err=%d", + dev_name, + fs_name, + options, + errno); + mnt_point->super_block = old_sb; vfs_sb_free(sb); return errno; } @@ -188,21 +216,31 @@ vfs_unmount_at(struct v_dnode* mnt_point) return errno; } -__DEFINE_LXSYSCALL3(int, +int +vfs_check_writable(struct v_dnode* dnode) +{ + if ((dnode->mnt->flags & MNT_RO)) { + return EROFS; + } + return 0; +} + +__DEFINE_LXSYSCALL4(int, mount, const char*, source, const char*, target, const char*, - fstype) + fstype, + int, + options) { - struct v_dnode *dev, *mnt; + struct v_dnode *dev = NULL, *mnt = NULL; int errno = 0; - if ((errno = vfs_walk(__current->cwd, source, &dev, NULL, 0))) { - goto done; - } + // It is fine if source is not exist, as some mounting don't require it + vfs_walk(__current->cwd, source, &dev, NULL, 0); if ((errno = vfs_walk(__current->cwd, target, &mnt, NULL, 0))) { goto done; @@ -213,16 +251,24 @@ __DEFINE_LXSYSCALL3(int, goto done; } + if (mnt->mnt->mnt_point == mnt) { + errno = EBUSY; + goto done; + } + // By our convention. // XXX could we do better? - struct device* device = (struct device*)dev->data; + struct device* device = NULL; - if (!(dev->inode->itype & VFS_IFVOLDEV) || !device) { - errno = ENOTDEV; - goto done; + if (dev) { + if (!(dev->inode->itype & VFS_IFVOLDEV)) { + errno = ENOTDEV; + goto done; + } + device = (struct device*)dev->inode->data; } - errno = vfs_mount_at(fstype, device, mnt); + errno = vfs_mount_at(fstype, device, mnt, options); done: return DO_STATUS(errno);