Skip to content

Commit

Permalink
dentry: Add proper shrinking, LRU
Browse files Browse the repository at this point in the history
Add proper shrinking, LRU, with some dentry fixes sprinkled around.
Shrinkers aren't great atm, but they Work(tm) ish.

Signed-off-by: Pedro Falcato <[email protected]>
  • Loading branch information
heatd committed Aug 4, 2024
1 parent 7cefbb0 commit 6a40762
Show file tree
Hide file tree
Showing 21 changed files with 564 additions and 61 deletions.
26 changes: 25 additions & 1 deletion kernel/include/onyx/dentry.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#include <onyx/inode.h>
#include <onyx/limits.h>
#include <onyx/list.h>
#include <onyx/lru.h>
#include <onyx/rcupdate.h>
#include <onyx/rwlock.h>

Expand All @@ -32,6 +33,9 @@ __BEGIN_CDECLS
#define DENTRY_FLAG_FAILED (1 << 3)
#define DENTRY_FLAG_NEGATIVE (1 << 4)
#define DENTRY_FLAG_HASHED (1 << 5)
#define DENTRY_FLAG_SHRINK (1 << 6)
#define DENTRY_FLAG_LRU (1 << 7)
#define DENTRY_FLAG_REFERENCED (1 << 8)

struct dentry_operations
{
Expand All @@ -56,7 +60,11 @@ struct dentry
struct list_head d_cache_node;
struct list_head d_children_head;
const struct dentry_operations *d_ops;
struct rcu_head d_rcu;
union {
struct rcu_head d_rcu;
struct list_head d_lru;
};

unsigned long d_private;
#ifdef __cplusplus
atomic<uint16_t> d_flags;
Expand Down Expand Up @@ -106,6 +114,22 @@ __always_inline bool dentry_is_symlink(const struct dentry *d)
return S_ISLNK(d->d_inode->i_mode);
}

struct dcache_scan_result
{
unsigned long scanned_bytes;
unsigned long scanned_objs;
};

struct dcache_shrink_result
{
unsigned long to_shrink_bytes;
unsigned long to_shrink_objs;
struct list_head reclaim_list;
};

enum lru_walk_ret scan_dcache_lru_one(struct lru_list *lru, struct list_head *object, void *data);
enum lru_walk_ret shrink_dcache_lru_one(struct lru_list *lru, struct list_head *object, void *data);

__END_CDECLS

#ifdef __cplusplus
Expand Down
14 changes: 14 additions & 0 deletions kernel/include/onyx/list.h
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,20 @@ static inline void list_splice_tail(struct list_head *src, struct list_head *dst
list_splice_internal(src, dst->prev, dst);
}

static inline int list_is_head(const struct list_head *list, const struct list_head *head)
{
return list == head;
}

#define list_entry(ptr, type, member) container_of(ptr, type, member)
#define list_next_entry(pos, member) list_entry((pos)->member.next, __typeof__(*(pos)), member)
#define list_prepare_entry(pos, head, member) ((pos) ?: list_entry(head, __typeof__(*pos), member))
#define list_entry_is_head(pos, head, member) list_is_head(&pos->member, (head))

#define list_for_each_entry_continue(pos, head, member) \
for (pos = list_next_entry(pos, member); !list_entry_is_head(pos, head, member); \
pos = list_next_entry(pos, member))

/*
* TODO: This code is weird, inconsistent, and needs to be rewritten
* and re-thought.
Expand Down
51 changes: 51 additions & 0 deletions kernel/include/onyx/lru.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/*
* Copyright (c) 2024 Pedro Falcato
* This file is part of Onyx, and is released under the terms of the GPLv2 License
* check LICENSE at the root directory for more information
*
* SPDX-License-Identifier: GPL-2.0-only
*/

#ifndef _ONYX_LRU_H
#define _ONYX_LRU_H

#include <onyx/list.h>
#include <onyx/spinlock.h>

/**
* @brief Simple LRU list implementation
*
*/
struct lru_list
{
struct list_head obj_list;
struct spinlock lock;
};

__BEGIN_CDECLS

static inline void lru_list_init(struct lru_list *lru)
{
INIT_LIST_HEAD(&lru->obj_list);
spinlock_init(&lru->lock);
}

void lru_list_add(struct lru_list *lru, struct list_head *object);
void lru_list_remove(struct lru_list *lru, struct list_head *object);

enum lru_walk_ret
{
LRU_WALK_ROTATE = 0,
LRU_WALK_SKIP,
LRU_WALK_STOP,
LRU_WALK_REMOVED,
};

void lru_list_walk(struct lru_list *lru,
enum lru_walk_ret (*walk)(struct lru_list *lru, struct list_head *obj,
void *data),
void *data);

__END_CDECLS

#endif
4 changes: 4 additions & 0 deletions kernel/include/onyx/mm/shrinker.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@

#include <onyx/list.h>

__BEGIN_CDECLS

struct shrink_control
{
/**
Expand Down Expand Up @@ -41,4 +43,6 @@ struct shrinker
void shrinker_register(struct shrinker *shr);
void shrinker_unregister(struct shrinker *shr);

__END_CDECLS

#endif
4 changes: 4 additions & 0 deletions kernel/include/onyx/rcupdate.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,10 @@ void call_rcu(struct rcu_head *head, void (*callback)(struct rcu_head *head));
void synchronize_rcu();
void __kfree_rcu(struct rcu_head *head, unsigned long off);

#ifdef __cplusplus
#define _Static_assert(x) static_assert(x)
#endif

#define is_kfree_rcu_off(off) ((off) < 4096)
#define kfree_rcu(ptr, head) \
({ \
Expand Down
16 changes: 15 additions & 1 deletion kernel/include/onyx/seqlock.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,21 @@ static inline unsigned int read_seqbegin(seqlock_t *sl)

static inline bool read_seqretry(seqlock_t *sl, unsigned int old)
{
return read_seqcount_retry(&sl->seqcount, old);
return !(old & 1) && read_seqcount_retry(&sl->seqcount, old);
}

static inline void read_seqbegin_or_lock(seqlock_t *sl, unsigned int *seq)
{
if (unlikely(*seq & 1))
spin_lock(&sl->lock);
else
*seq = read_seqbegin(sl);
}

static inline void done_seqretry(seqlock_t *sl, unsigned int seq)
{
if (unlikely(seq & 1))
spin_unlock(&sl->lock);
}

#endif
4 changes: 4 additions & 0 deletions kernel/include/onyx/superblock.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
#include <sys/statfs.h>

#include <onyx/list.h>
#include <onyx/lru.h>
#include <onyx/mm/shrinker.h>
#include <onyx/mutex.h>
#include <onyx/spinlock.h>
#include <onyx/types.h>
Expand All @@ -37,6 +39,8 @@ struct superblock
dev_t s_devnr;
unsigned long s_flags;
struct mutex s_rename_lock;
struct lru_list s_dcache_lru;
struct shrinker s_shrinker;
};

__BEGIN_CDECLS
Expand Down
2 changes: 1 addition & 1 deletion kernel/kernel/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ kern-y+= arc4random.o binfmt.o compression.o copy.o cppnew.o cpprt.o crc32.o dev
smp.o spinlock.o symbol.o tasklet.o time.o timer.o utils.o wait_queue.o \
worker.o cred.o list.o softirq.o cputime.o rlimit.o handle.o ctor.o internal_abi.o ssp.o \
cmdline.o syscall_thunk.o vdso.o sysinfo.o memstream.o perf.o radix.o rcupdate.o iovec_iter.o \
maple_tree.o bug.o
maple_tree.o bug.o lru.o

kern-$(CONFIG_UBSAN)+= ubsan.o

Expand Down
3 changes: 2 additions & 1 deletion kernel/kernel/fs/anon_inode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ struct file *anon_inode_open(mode_t file_type, struct file_ops *ops, const char
dentry = dentry_create(name, ino, nullptr);
if (!dentry)
goto err;
dget(dentry);

f = inode_to_file(ino);
if (!f)
Expand All @@ -73,7 +74,7 @@ struct file *anon_inode_open(mode_t file_type, struct file_ops *ops, const char
return f;
err:
if (dentry)
dentry_put(dentry);
dput(dentry);
if (ino)
inode_unref(ino);
return nullptr;
Expand Down
Loading

0 comments on commit 6a40762

Please sign in to comment.