summary |
shortlog |
log |
commit | commitdiff |
tree
raw |
patch |
inline | side by side (from parent 1:
eb1d71e)
chore: minor fixes and refactoring
#define __LUNAIX_LRU_H
#include <lunaix/ds/llist.h>
#define __LUNAIX_LRU_H
#include <lunaix/ds/llist.h>
+#include <lunaix/types.h>
- struct llist_header lead_node;
- struct llist_header zones;
+ struct llist_header lru_nodes;
+typedef int (*evict_cb)(struct lru_node* lru_obj);
+
+struct lru_zone
- struct llist_header lru_nodes;
+ struct llist_header lead_node;
+ struct llist_header zones;
+ uint32_t objects;
+ evict_cb try_evict;
+lru_new_zone(evict_cb try_evict_cb);
void
lru_use_one(struct lru_zone* zone, struct lru_node* node);
void
lru_use_one(struct lru_zone* zone, struct lru_node* node);
lru_evict_one(struct lru_zone* zone);
void
lru_evict_one(struct lru_zone* zone);
void
-lru_remove(struct lru_node* node);
+lru_remove(struct lru_zone* zone, struct lru_node* node);
+
+void
+lru_evict_half(struct lru_zone* zone);
#endif /* __LUNAIX_LRU_H */
#endif /* __LUNAIX_LRU_H */
uint32_t lb_usage;
uint32_t fsize;
struct hlist_node hash_list;
uint32_t lb_usage;
uint32_t fsize;
struct hlist_node hash_list;
struct pcache* pg_cache;
void* data; // 允许底层FS绑定他的一些专有数据
struct
struct pcache* pg_cache;
void* data; // 允许底层FS绑定他的一些专有数据
struct
int (*open)(struct v_inode* this, struct v_file* file);
int (*sync)(struct v_inode* this);
int (*mkdir)(struct v_inode* this, struct v_dnode* dnode);
int (*open)(struct v_inode* this, struct v_file* file);
int (*sync)(struct v_inode* this);
int (*mkdir)(struct v_inode* this, struct v_dnode* dnode);
- int (*rmdir)(struct v_inode* this);
+ int (*rmdir)(struct v_inode* this, struct v_dnode* dir);
int (*unlink)(struct v_inode* this);
int (*link)(struct v_inode* this, struct v_dnode* new_name);
int (*read_symlink)(struct v_inode* this, const char** path_out);
int (*unlink)(struct v_inode* this);
int (*link)(struct v_inode* this, struct v_dnode* new_name);
int (*read_symlink)(struct v_inode* this, const char** path_out);
- int (*symlink)(struct v_inode* this, const char* target);
+ int (*set_symlink)(struct v_inode* this, const char* target);
int (*dir_lookup)(struct v_inode* this, struct v_dnode* dnode);
int (*rename)(struct v_inode* from_inode,
struct v_dnode* from_dnode,
int (*dir_lookup)(struct v_inode* this, struct v_dnode* dnode);
int (*rename)(struct v_inode* from_inode,
struct v_dnode* from_dnode,
struct v_dnode
{
mutex_t lock; // sync the path walking
struct v_dnode
{
mutex_t lock; // sync the path walking
struct hstr name;
struct v_inode* inode;
struct v_dnode* parent;
struct hstr name;
struct v_inode* inode;
struct v_dnode* parent;
struct v_fd* fds[VFS_MAX_FD];
};
struct v_fd* fds[VFS_MAX_FD];
};
-struct pcache_pg
-{
- struct llist_header pg_list;
- struct llist_header dirty_list;
- struct lru_node lru;
- void* pg;
- uint32_t flags;
- uint32_t fpos;
-};
-
struct pcache
{
struct v_inode* master;
struct pcache
{
struct v_inode* master;
+struct pcache_pg
+{
+ struct llist_header pg_list;
+ struct llist_header dirty_list;
+ struct lru_node lru;
+ struct pcache* holder;
+ void* pg;
+ uint32_t flags;
+ uint32_t fpos;
+};
/* --- file system manager --- */
void
fsm_init();
/* --- file system manager --- */
void
fsm_init();
int
vfs_fsync(struct v_file* file);
int
vfs_fsync(struct v_file* file);
+void
+vfs_assign_inode(struct v_dnode* assign_to, struct v_inode* inode);
+
struct v_superblock*
vfs_sb_alloc();
struct v_superblock*
vfs_sb_alloc();
struct llist_header zone_lead = { .next = &zone_lead, .prev = &zone_lead };
struct lru_zone*
struct llist_header zone_lead = { .next = &zone_lead, .prev = &zone_lead };
struct lru_zone*
+lru_new_zone(evict_cb try_evict_cb)
- struct lru_zone* zone = valloc(sizeof(struct lru_zone));
+ struct lru_zone* zone = vzalloc(sizeof(struct lru_zone));
if (!zone) {
return NULL;
}
if (!zone) {
return NULL;
}
+ zone->try_evict = try_evict_cb;
+
llist_init_head(&zone->lead_node);
llist_append(&zone_lead, &zone->zones);
llist_init_head(&zone->lead_node);
llist_append(&zone_lead, &zone->zones);
}
llist_prepend(&zone->lead_node, &node->lru_nodes);
}
llist_prepend(&zone->lead_node, &node->lru_nodes);
+ zone->objects++;
+}
+
+static void
+__do_evict(struct lru_zone* zone, struct llist_header* elem)
+{
+ llist_delete(elem);
+ if (!zone->try_evict(container_of(elem, struct lru_node, lru_nodes))) {
+ llist_append(&zone->lead_node, elem);
+ } else {
+ zone->objects--;
+ }
lru_evict_one(struct lru_zone* zone)
{
struct llist_header* tail = zone->lead_node.prev;
lru_evict_one(struct lru_zone* zone)
{
struct llist_header* tail = zone->lead_node.prev;
+ __do_evict(zone, tail);
+}
- return container_of(tail, struct lru_node, lru_nodes);
+void
+lru_evict_half(struct lru_zone* zone)
+{
+ int target = (int)(zone->objects / 2);
+ struct llist_header* tail = zone->lead_node.prev;
+ while (tail != &zone->lead_node && target > 0) {
+ __do_evict(zone, tail);
+ tail = tail->prev;
+ target--;
+ }
-lru_remove(struct lru_node* node)
+lru_remove(struct lru_zone* zone, struct lru_node* node)
{
if (node->lru_nodes.next && node->lru_nodes.prev) {
llist_delete(&node->lru_nodes);
}
{
if (node->lru_nodes.next && node->lru_nodes.prev) {
llist_delete(&node->lru_nodes);
}
}
\ No newline at end of file
}
\ No newline at end of file
static struct lru_zone* pcache_zone;
static struct lru_zone* pcache_zone;
+static int
+__pcache_try_evict(struct lru_node* obj)
+{
+ struct pcache_pg* page = container_of(obj, struct pcache_pg, lru);
+ pcache_invalidate(page->holder, page);
+ return 1;
+}
+
void
pcache_init(struct pcache* pcache)
{
btrie_init(&pcache->tree, PG_SIZE_BITS);
llist_init_head(&pcache->dirty);
llist_init_head(&pcache->pages);
void
pcache_init(struct pcache* pcache)
{
btrie_init(&pcache->tree, PG_SIZE_BITS);
llist_init_head(&pcache->dirty);
llist_init_head(&pcache->pages);
- pcache_zone = lru_new_zone();
+ pcache_zone = lru_new_zone(__pcache_try_evict);
-void
-pcache_evict(struct pcache* pcache)
-{
- struct pcache_pg* page =
- container_of(lru_evict_one(pcache_zone), struct pcache_pg, lru);
-
- if (!page)
- return;
-
- pcache_invalidate(pcache, page);
-}
-
struct pcache_pg*
pcache_new_page(struct pcache* pcache, uint32_t index)
{
struct pcache_pg*
pcache_new_page(struct pcache* pcache, uint32_t index)
{
void* pg = valloc(PG_SIZE);
if (!ppg || !pg) {
void* pg = valloc(PG_SIZE);
if (!ppg || !pg) {
+ lru_evict_one(pcache_zone);
if (!ppg && !(ppg = vzalloc(sizeof(struct pcache_pg)))) {
return NULL;
}
if (!ppg && !(ppg = vzalloc(sizeof(struct pcache_pg)))) {
return NULL;
}
llist_append(&pcache->pages, &ppg->pg_list);
btrie_set(&pcache->tree, index, ppg);
llist_append(&pcache->pages, &ppg->pg_list);
btrie_set(&pcache->tree, index, ppg);
struct pcache_pg *pos, *n;
llist_for_each(pos, n, &pcache->pages, pg_list)
{
struct pcache_pg *pos, *n;
llist_for_each(pos, n, &pcache->pages, pg_list)
{
+ lru_remove(pcache_zone, &pos->lru);
__twifs_mkdir(struct v_inode* inode, struct v_dnode* dnode);
int
__twifs_mkdir(struct v_inode* inode, struct v_dnode* dnode);
int
-__twifs_rmstuff(struct v_inode* inode);
+__twifs_rmstuff(struct v_inode* inode, struct v_dnode* dir);
int
__twifs_fwrite(struct v_inode* inode, void* buffer, size_t len, size_t fpos);
int
__twifs_fwrite(struct v_inode* inode, void* buffer, size_t len, size_t fpos);
return ENOTEMPTY;
}
llist_delete(&node->siblings);
return ENOTEMPTY;
}
llist_delete(&node->siblings);
- vfs_i_free(node->inode);
cake_release(twi_pile, node);
return 0;
}
cake_release(twi_pile, node);
return 0;
}
int
__twifs_mkdir(struct v_inode* inode, struct v_dnode* dnode)
{
int
__twifs_mkdir(struct v_inode* inode, struct v_dnode* dnode)
{
- struct twifs_node* parent_node = (struct twifs_node*)inode->data;
- if (!(parent_node->itype & VFS_IFDIR)) {
- return ENOTDIR;
- }
- struct twifs_node* new_node =
- twifs_dir_node(parent_node, dnode->name.value, dnode->name.len, 0);
- dnode->inode = new_node->inode;
-
- return 0;
}
int
__twifs_mount(struct v_superblock* vsb, struct v_dnode* mount_point)
{
}
int
__twifs_mount(struct v_superblock* vsb, struct v_dnode* mount_point)
{
- mount_point->inode = fs_root->inode;
+ vfs_assign_inode(mount_point, fs_root->inode);
inode->ops.dir_lookup = __twifs_dirlookup;
inode->ops.mkdir = __twifs_mkdir;
inode->ops.dir_lookup = __twifs_dirlookup;
inode->ops.mkdir = __twifs_mkdir;
- inode->ops.unlink = __twifs_rmstuff;
inode->ops.rmdir = __twifs_rmstuff;
inode->ops.open = __twifs_openfile;
inode->ops.rmdir = __twifs_rmstuff;
inode->ops.open = __twifs_openfile;
-__twifs_rmstuff(struct v_inode* inode)
+__twifs_rmstuff(struct v_inode* inode, struct v_dnode* dir)
- struct twifs_node* twi_node = (struct twifs_node*)inode->data;
- return twifs_rm_node(twi_node);
struct twifs_node* child_node = __twifs_get_node(twi_node, &dnode->name);
if (child_node) {
struct twifs_node* child_node = __twifs_get_node(twi_node, &dnode->name);
if (child_node) {
- dnode->inode = child_node->inode;
+ vfs_assign_inode(dnode, child_node->inode);
return 0;
}
return ENOENT;
return 0;
}
return ENOENT;
It is overseen by Twilight Sparkle ;)
It is overseen by Twilight Sparkle ;)
- 1. Get inodes hooked into lru
- 2. Get dnodes hooked into lru
+ 1. Get inodes hooked into lru (CHECKED)
+ 2. Get dnodes hooked into lru (CHECKED)
3. Get inodes properly hashed so they can be reused by underling fs (CHECKED)
3. Get inodes properly hashed so they can be reused by underling fs (CHECKED)
- 4. (lru) Add a callback function (or destructor) for eviction.
+ 4. (lru) Add a callback function (or destructor) for eviction. (CHECKED)
[good idea] or a constructor/destructor pattern in cake allocator ?
5. (mount) Figure out a way to identify a busy mount point before unmount
maybe a unified mount_point structure that maintain a referencing
[good idea] or a constructor/destructor pattern in cake allocator ?
5. (mount) Figure out a way to identify a busy mount point before unmount
maybe a unified mount_point structure that maintain a referencing
#define HASH_MASK (HASHTABLE_SIZE - 1)
#define HASHBITS (32 - HASHTABLE_BITS)
#define HASH_MASK (HASHTABLE_SIZE - 1)
#define HASHBITS (32 - HASHTABLE_BITS)
-#define lock_inode(inode) mutex_lock(&inode->lock)
#define unlock_inode(inode) mutex_unlock(&inode->lock)
#define unlock_inode(inode) mutex_unlock(&inode->lock)
+#define lock_inode(inode) \
+ ({ \
+ mutex_lock(&inode->lock); \
+ lru_use_one(inode_lru, &inode->lru); \
+ })
-#define lock_dnode(dnode) mutex_lock(&dnode->lock)
#define unlock_dnode(dnode) mutex_unlock(&dnode->lock)
#define unlock_dnode(dnode) mutex_unlock(&dnode->lock)
+#define lock_dnode(dnode) \
+ ({ \
+ mutex_lock(&dnode->lock); \
+ lru_use_one(dnode_lru, &dnode->lru); \
+ })
static struct cake_pile* dnode_pile;
static struct cake_pile* inode_pile;
static struct cake_pile* dnode_pile;
static struct cake_pile* inode_pile;
static struct v_superblock* root_sb;
static struct hbucket *dnode_cache, *inode_cache;
static struct v_superblock* root_sb;
static struct hbucket *dnode_cache, *inode_cache;
+static struct lru_zone *dnode_lru, *inode_lru;
+
struct hstr vfs_ddot = HSTR("..", 2);
struct hstr vfs_dot = HSTR(".", 1);
struct hstr vfs_empty = HSTR("", 0);
struct hstr vfs_ddot = HSTR("..", 2);
struct hstr vfs_dot = HSTR(".", 1);
struct hstr vfs_empty = HSTR("", 0);
void
vfs_sb_free(struct v_superblock* sb);
void
vfs_sb_free(struct v_superblock* sb);
+static int
+__vfs_try_evict_dnode(struct lru_node* obj);
+
+static int
+__vfs_try_evict_inode(struct lru_node* obj);
+
dnode_cache = vzalloc(HASHTABLE_SIZE * sizeof(struct hbucket));
inode_cache = vzalloc(HASHTABLE_SIZE * sizeof(struct hbucket));
dnode_cache = vzalloc(HASHTABLE_SIZE * sizeof(struct hbucket));
inode_cache = vzalloc(HASHTABLE_SIZE * sizeof(struct hbucket));
+ dnode_lru = lru_new_zone(__vfs_try_evict_dnode);
+ inode_lru = lru_new_zone(__vfs_try_evict_inode);
+
hstr_rehash(&vfs_ddot, HSTR_FULL_HASH);
hstr_rehash(&vfs_dot, HSTR_FULL_HASH);
// 创建一个根superblock,用来蕴含我们的根目录。
root_sb = vfs_sb_alloc();
root_sb->root = vfs_d_alloc();
hstr_rehash(&vfs_ddot, HSTR_FULL_HASH);
hstr_rehash(&vfs_dot, HSTR_FULL_HASH);
// 创建一个根superblock,用来蕴含我们的根目录。
root_sb = vfs_sb_alloc();
root_sb->root = vfs_d_alloc();
- root_sb->root->inode = vfs_i_alloc(root_sb, 0);
if (!dnode) {
dnode = vfs_d_alloc();
if (!dnode) {
dnode = vfs_d_alloc();
+ if (!dnode) {
+ errno = ENOMEM;
+ goto error;
+ }
+
hstrcpy(&dnode->name, &name);
lock_inode(current_level->inode);
hstrcpy(&dnode->name, &name);
lock_inode(current_level->inode);
if (errno) {
unlock_dnode(current_level);
vfree(dnode->name.value);
if (errno) {
unlock_dnode(current_level);
vfree(dnode->name.value);
}
vfs_dcache_add(current_level, dnode);
}
vfs_dcache_add(current_level, dnode);
*dentry = current_level;
return 0;
*dentry = current_level;
return 0;
*dentry = NULL;
return errno;
}
*dentry = NULL;
return errno;
}
int errno = __vfs_walk(start, path, &interim, component, options);
int counter = 0;
int errno = __vfs_walk(start, path, &interim, component, options);
int counter = 0;
+ while (!errno && interim->inode && (options & VFS_WALK_NOFOLLOW)) {
if (counter >= VFS_MAX_SYMLINK) {
errno = ELOOP;
continue;
}
if ((interim->inode->itype & VFS_IFSYMLINK) &&
if (counter >= VFS_MAX_SYMLINK) {
errno = ELOOP;
continue;
}
if ((interim->inode->itype & VFS_IFSYMLINK) &&
- !(options & VFS_WALK_NOFOLLOW) &&
interim->inode->ops.read_symlink) {
interim->inode->ops.read_symlink) {
+
+ lock_inode(interim->inode);
errno = interim->inode->ops.read_symlink(interim->inode, &pathname);
errno = interim->inode->ops.read_symlink(interim->inode, &pathname);
+ unlock_inode(interim->inode);
+
struct device* device,
struct v_dnode* mnt_point)
{
struct device* device,
struct v_dnode* mnt_point)
{
- if (!(mnt_point->inode->itype & VFS_IFDIR)) {
+ if (mnt_point->inode && !(mnt_point->inode->itype & VFS_IFDIR)) {
+void
+vfs_assign_inode(struct v_dnode* assign_to, struct v_inode* inode)
+{
+ if (assign_to->inode) {
+ assign_to->inode->link_count--;
+ }
+ assign_to->inode = inode;
+ inode->link_count++;
+}
+
int
vfs_link(struct v_dnode* to_link, struct v_dnode* name)
{
int
vfs_link(struct v_dnode* to_link, struct v_dnode* name)
{
} else if (!to_link->inode->ops.link) {
errno = ENOTSUP;
} else if (!(errno = to_link->inode->ops.link(to_link->inode, name))) {
} else if (!to_link->inode->ops.link) {
errno = ENOTSUP;
} else if (!(errno = to_link->inode->ops.link(to_link->inode, name))) {
- name->inode = to_link->inode;
- to_link->inode->link_count++;
+ vfs_assign_inode(name, to_link->inode);
}
unlock_inode(to_link->inode);
}
unlock_inode(to_link->inode);
cake_release(superblock_pile, sb);
}
cake_release(superblock_pile, sb);
}
+static int
+__vfs_try_evict_dnode(struct lru_node* obj)
+{
+ struct v_dnode* dnode = container_of(obj, struct v_dnode, lru);
+
+ if (!dnode->ref_count) {
+ vfs_d_free(dnode);
+ return 1;
+ }
+ return 0;
+}
+
+static int
+__vfs_try_evict_inode(struct lru_node* obj)
+{
+ struct v_inode* inode = container_of(obj, struct v_inode, lru);
+
+ if (!inode->link_count && !inode->open_count) {
+ vfs_i_free(inode);
+ return 1;
+ }
+ return 0;
+}
+
struct v_dnode*
vfs_d_alloc()
{
struct v_dnode* dnode = cake_grab(dnode_pile);
struct v_dnode*
vfs_d_alloc()
{
struct v_dnode* dnode = cake_grab(dnode_pile);
+ if (!dnode) {
+ lru_evict_half(dnode_lru);
+
+ if (!(dnode = cake_grab(dnode_pile))) {
+ return NULL;
+ }
+ }
+
memset(dnode, 0, sizeof(*dnode));
llist_init_head(&dnode->children);
llist_init_head(&dnode->siblings);
memset(dnode, 0, sizeof(*dnode));
llist_init_head(&dnode->children);
llist_init_head(&dnode->siblings);
dnode->ref_count = ATOMIC_VAR_INIT(0);
dnode->name = HHSTR(vzalloc(VFS_NAME_MAXLEN), 0, 0);
dnode->ref_count = ATOMIC_VAR_INIT(0);
dnode->name = HHSTR(vzalloc(VFS_NAME_MAXLEN), 0, 0);
+ lru_use_one(dnode_lru, &dnode->lru);
+
return dnode;
}
void
vfs_d_free(struct v_dnode* dnode)
{
return dnode;
}
void
vfs_d_free(struct v_dnode* dnode)
{
- if (dnode->ref_count) {
- // it can be only freed if no one is refering
- return;
- }
- if (dnode->inode && dnode->inode->link_count) {
+ assert(dnode->ref_count == 0);
+
+ if (dnode->inode) {
+ assert(dnode->inode->link_count > 0);
dnode->inode->link_count--;
}
dnode->inode->link_count--;
}
// 这也就是说,每个 v_inode 的 id
// 必须要由设备ID,和该虚拟inode缓存所对应的物理inode
// 相对于其所在的文件系统的id,进行组成!
// 这也就是说,每个 v_inode 的 id
// 必须要由设备ID,和该虚拟inode缓存所对应的物理inode
// 相对于其所在的文件系统的id,进行组成!
- inode_id = hash_32(inode_id ^ device_id, HASH_SIZE_BITS);
+ inode_id = hash_32(inode_id ^ (-device_id), HASH_SIZE_BITS);
inode_id = (inode_id >> HASHBITS) ^ inode_id;
struct hbucket* slot = &inode_cache[inode_id & HASH_MASK];
inode_id = (inode_id >> HASHBITS) ^ inode_id;
struct hbucket* slot = &inode_cache[inode_id & HASH_MASK];
hashtable_bucket_foreach(slot, pos, n, hash_list)
{
if (pos->id == inode_id) {
hashtable_bucket_foreach(slot, pos, n, hash_list)
{
if (pos->id == inode_id) {
+ goto done;
+ }
+ }
+
+ if (!(pos = cake_grab(inode_pile))) {
+ lru_evict_half(inode_lru);
+ if (!(pos = cake_grab(inode_pile))) {
+ return NULL;
- pos = cake_grab(inode_pile);
memset(pos, 0, sizeof(*pos));
pos->id = inode_id;
memset(pos, 0, sizeof(*pos));
pos->id = inode_id;
mutex_init(&pos->lock);
hlist_add(&slot->head, &pos->hash_list);
mutex_init(&pos->lock);
hlist_add(&slot->head, &pos->hash_list);
+done:
+ lru_use_one(inode_lru, &pos->lru);
struct v_dnode* parent = *fdir;
struct v_dnode* file_new = vfs_d_alloc();
struct v_dnode* parent = *fdir;
struct v_dnode* file_new = vfs_d_alloc();
+
+ if (!file_new) {
+ return ENOMEM;
+ }
+
hstrcpy(&file_new->name, &name);
hstrcpy(&file_new->name, &name);
if (!(errno = parent->inode->ops.create(parent->inode, file_new))) {
*file = file_new;
if (!(errno = parent->inode->ops.create(parent->inode, file_new))) {
*file = file_new;
+ unlock_dnode(parent);
+
__SYSCALL_INTERRUPTIBLE(
{ errno = file->ops.read(file->inode, buf, count, file->f_pos); })
__SYSCALL_INTERRUPTIBLE(
{ errno = file->ops.read(file->inode, buf, count, file->f_pos); })
- unlock_inode(file->inode);
-
if (errno > 0) {
file->f_pos += errno;
if (errno > 0) {
file->f_pos += errno;
+ unlock_inode(file->inode);
+ unlock_inode(file->inode);
+
done:
return DO_STATUS(errno);
}
done:
return DO_STATUS(errno);
}
__SYSCALL_INTERRUPTIBLE(
{ errno = file->ops.write(file->inode, buf, count, file->f_pos); })
__SYSCALL_INTERRUPTIBLE(
{ errno = file->ops.write(file->inode, buf, count, file->f_pos); })
- unlock_inode(file->inode);
-
if (errno > 0) {
file->f_pos += errno;
if (errno > 0) {
file->f_pos += errno;
+ unlock_inode(file->inode);
+ unlock_inode(file->inode);
+
done:
return DO_STATUS(errno);
}
done:
return DO_STATUS(errno);
}
- if (dnode->parent)
- lock_dnode(dnode->parent);
-
if ((dnode->super_block->fs->types & FSTYPE_ROFS)) {
errno = EROFS;
goto done;
}
if ((dnode->super_block->fs->types & FSTYPE_ROFS)) {
errno = EROFS;
goto done;
}
- if (dnode->ref_count || dnode->inode->open_count) {
+ if (dnode->ref_count > 1 || dnode->inode->open_count) {
errno = EBUSY;
goto done;
}
errno = EBUSY;
goto done;
}
- lock_inode(dnode->inode);
+ struct v_dnode* parent = dnode->parent;
+
+ if (!parent) {
+ errno = EINVAL;
+ goto done;
+ }
+
+ lock_dnode(parent);
+ lock_inode(parent->inode);
if ((dnode->inode->itype & VFS_IFDIR)) {
if ((dnode->inode->itype & VFS_IFDIR)) {
- errno = dnode->inode->ops.rmdir(dnode->inode);
+ errno = parent->inode->ops.rmdir(parent->inode, dnode);
if (!errno) {
vfs_dcache_remove(dnode);
if (!errno) {
vfs_dcache_remove(dnode);
- unlock_inode(dnode->inode);
- vfs_d_free(dnode);
-
- goto done;
}
} else {
errno = ENOTDIR;
}
}
} else {
errno = ENOTDIR;
}
- unlock_inode(dnode->inode);
+ unlock_inode(parent->inode);
+ unlock_dnode(parent);
done:
unlock_dnode(dnode);
done:
unlock_dnode(dnode);
- if (dnode->parent)
- unlock_dnode(dnode->parent);
return DO_STATUS(errno);
}
__DEFINE_LXSYSCALL1(int, mkdir, const char*, path)
{
return DO_STATUS(errno);
}
__DEFINE_LXSYSCALL1(int, mkdir, const char*, path)
{
struct v_dnode *parent, *dir = vfs_d_alloc();
struct v_dnode *parent, *dir = vfs_d_alloc();
- int errno =
- vfs_walk(__current->cwd, path, &parent, &dir->name, VFS_WALK_PARENT);
- if (errno) {
+
+ if (!dir) {
+ errno = ENOMEM;
+ goto done;
+ }
+
+ if ((errno = vfs_walk(
+ __current->cwd, path, &parent, &dir->name, VFS_WALK_PARENT))) {
// symlink case
errno = inode->ops.unlink(inode);
if (!errno) {
// symlink case
errno = inode->ops.unlink(inode);
if (!errno) {
vfs_dcache_remove(dnode);
vfs_d_free(dnode);
}
vfs_dcache_remove(dnode);
vfs_d_free(dnode);
}
errno = EROFS;
goto done;
}
errno = EROFS;
goto done;
}
- if (!dnode->inode->ops.symlink) {
+ if (!dnode->inode->ops.set_symlink) {
errno = ENOTSUP;
goto done;
}
lock_inode(dnode->inode);
errno = ENOTSUP;
goto done;
}
lock_inode(dnode->inode);
- errno = dnode->inode->ops.symlink(dnode->inode, link_target);
+ errno = dnode->inode->ops.set_symlink(dnode->inode, link_target);
unlock_inode(dnode->inode);
unlock_inode(dnode->inode);
errno = vfs_walk(target_parent, name.value, &target, NULL, 0);
if (errno == ENOENT) {
target = vfs_d_alloc();
errno = vfs_walk(target_parent, name.value, &target, NULL, 0);
if (errno == ENOENT) {
target = vfs_d_alloc();
- hstrcpy(&target->name, &name);
} else if (errno) {
goto done;
}
} else if (errno) {
goto done;
}
+ if (!target) {
+ errno = ENOMEM;
+ goto done;
+ }
+
+ hstrcpy(&target->name, &name);
+
if (!(errno = vfs_do_rename(cur, target))) {
vfs_d_free(target);
}
if (!(errno = vfs_do_rename(cur, target))) {
vfs_d_free(target);
}
current_addr = VMAP_START;
}
}
current_addr = VMAP_START;
}
}
- panick("vmm: out of memory");
done:
uintptr_t alloc_begin = current_addr - examed_size;
done:
uintptr_t alloc_begin = current_addr - examed_size;