Skip to content

Commit

Permalink
swap: Building blocks for swap support
Browse files Browse the repository at this point in the history
Includes swap parsing, mkswap, swapon(1) and swapon(2).
Does _not_ include actual swapping yet.

Signed-off-by: Pedro Falcato <[email protected]>
  • Loading branch information
heatd committed Aug 10, 2024
1 parent 8904519 commit 364ca7e
Show file tree
Hide file tree
Showing 13 changed files with 726 additions and 98 deletions.
31 changes: 30 additions & 1 deletion kernel/arch/x86_64/syscall_table.json
Original file line number Diff line number Diff line change
Expand Up @@ -2797,6 +2797,35 @@
],
"return_type": "int",
"abi": "c"
},
{
"name": "swapon",
"nr": 157,
"nr_args": 2,
"args": [
[
"const char *",
"path"
],
[
"int",
"flags"
]
],
"return_type": "int",
"abi": "c"
},
{
"name": "swapoff",
"nr": 158,
"nr_args": 1,
"args": [
[
"const char *",
"path"
]
],
"return_type": "int",
"abi": "c"
}

]
2 changes: 1 addition & 1 deletion kernel/include/onyx/block.h
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,7 @@ void block_queue_pending_io_queue(io_queue *queue);
*/
void bio_queue_pending_req(struct request *req);

__BEGIN_CDECLS
/**
* @brief Set the block device's block size
*
Expand All @@ -208,7 +209,6 @@ void bio_queue_pending_req(struct request *req);
*/
int block_set_bsize(struct blockdev *bdev, unsigned int block_size);

__BEGIN_CDECLS
int bdev_do_open(struct blockdev *bdev, bool exclusive);
void bdev_release(struct blockdev *bdev);
__END_CDECLS
Expand Down
2 changes: 2 additions & 0 deletions kernel/include/onyx/buffer.h
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,8 @@ void page_remove_block_buf(struct page *page, size_t offset, size_t end);

void buffer_free_page(struct vm_object *vmo, struct page *page);

struct block_buf *bdev_read_block(struct blockdev *bdev, unsigned long block);

__END_CDECLS

#ifdef __cplusplus
Expand Down
89 changes: 5 additions & 84 deletions kernel/include/onyx/namei.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,6 @@

#include <uapi/fcntl.h>

#include <onyx/string_view.hpp>

enum class fs_token_type : uint8_t
{
REGULAR_TOKEN = 0,
LAST_NAME_IN_PATH
};

#define LOOKUP_NOFOLLOW (1 << 0)
#define LOOKUP_FAIL_IF_LINK (1 << 1)
#define LOOKUP_MUST_BE_DIR (1 << 2)
Expand All @@ -31,83 +23,12 @@ enum class fs_token_type : uint8_t
#define LOOKUP_DONT_DO_LAST_NAME (1 << 5)
#define LOOKUP_INTERNAL_SAW_LAST_NAME (1U << 31)

/**
* @brief Represents a path during a lookup
*
*/
struct lookup_path
{
std::string_view view;
void *ownbuf{nullptr};
fs_token_type token_type{fs_token_type::REGULAR_TOKEN};
size_t pos{0};

lookup_path() = default;

lookup_path(std::string_view view) : view{view}
{
}

constexpr bool trailing_slash() const
{
return view[view.length() - 1] == '/';
}
};

struct nameidata
{
/* Data needed to resolve filesystem names:
* view - Contains the pathname;
* pos - Contains the offset in the parsing of the pathname;
* root - Contains the lookup's filesystem root;
* cur - Contains the current relative location and
* starts at whatever was passed as the relative dir (controlled with
* chdir or *at, or purely through kernel-side use).
*/
/* Note: root and location always hold a reference to the underlying object */
struct path root;
struct path cur;
/* Keeps the parent of cur, *if* we walked once */
struct path parent;

static constexpr const size_t max_loops = SYMLOOP_MAX;
/* Number of symbolic links found while looking up -
* if it reaches max_symlinks, the lookup fails with -ELOOP.
*/
int nloops{0};
int pdepth{0};
struct lookup_path paths[SYMLOOP_MAX];

unsigned int lookup_flags{};
int dirfd{AT_FDCWD};

nameidata(std::string_view view)
{
paths[0] = lookup_path{view};
path_init(&root);
path_init(&cur);
path_init(&parent);
}

~nameidata();

void setcur(struct path newcur)
{
DCHECK(!path_is_null(&newcur));
path_put(&parent);
parent = cur;
cur = newcur;
}

path getcur()
{
DCHECK(!path_is_null(&cur));
auto ret = cur;
path_init(&cur);
return ret;
}
};
__BEGIN_CDECLS
struct file *c_vfs_open(int dirfd, const char *name, unsigned int open_flags, mode_t mode);
__END_CDECLS

#ifdef __cplusplus
expected<file *, int> vfs_open(int dirfd, const char *name, unsigned int open_flags, mode_t mode);
#endif

#endif
37 changes: 37 additions & 0 deletions kernel/include/uapi/swap.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/*
* Copyright (c) 2024 Pedro Falcato
* This file is part of Onyx, and is released under the terms of the MIT License
* check LICENSE at the root directory for more information
*
* SPDX-License-Identifier: MIT
*/
#ifndef _UAPI_SWAP_H
#define _UAPI_SWAP_H

#include <onyx/types.h>

#define SWAP_VERSION_CURRENT 0
/* MAGIC = "ONYXSWAP", backwards on big endian */
#define SWAP_MAGIC 0x5041575358594E4F

/* Used if we go over BADBLOCKS, or if BADBLOCKS themselves are bad */
#define SWP_FLAG_BAD (1 << 0)

#define SWP_RESERVED_BADBLOCKS_PAGES 8

typedef __u64 __swap_block_t;

struct swap_super
{
__u64 swp_magic;
__u32 swp_version;
__u32 swp_pagesize;
__swap_block_t swp_nr_pages;
__u32 swp_flags;
__u32 swp_nr_badblocks;
__u8 swp_uuid[16];
};

#define MIN_SWAP_SIZE_PAGES (SWP_RESERVED_BADBLOCKS_PAGES + 1)

#endif
41 changes: 41 additions & 0 deletions kernel/kernel/fs/buffer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -487,6 +487,47 @@ struct block_buf *sb_read_block(const struct superblock *sb, unsigned long block
return buf;
}

struct block_buf *bdev_read_block(struct blockdev *bdev, unsigned long block)
{
size_t real_off = bdev->block_size * block;
size_t aligned_off = real_off & -PAGE_SIZE;

struct page *page;

int st = filemap_find_page(bdev->b_ino, real_off >> PAGE_SHIFT, 0, &page, nullptr);

if (st < 0)
return nullptr;

auto buf = reinterpret_cast<block_buf *>(page->priv);

while (buf && buf->block_nr != block)
buf = buf->next;

if (unlikely(!buf))
{
size_t page_off = real_off - aligned_off;
sector_t aligned_block = aligned_off / bdev->block_size;
sector_t block_nr = aligned_block + ((real_off - aligned_off) / bdev->block_size);

if (!(buf = page_add_blockbuf(page, page_off)))
{
page_unref(page);
return nullptr;
}

buf->block_nr = block_nr;
buf->block_size = bdev->block_size;
buf->dev = bdev;
}

block_buf_get(buf);

page_unref(page);

return buf;
}

void block_buf_dirty(block_buf *buf)
{
if (!bb_test_and_set(buf, BLOCKBUF_FLAG_DIRTY))
Expand Down
91 changes: 90 additions & 1 deletion kernel/kernel/fs/namei.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
*/
#include <onyx/cred.h>
#include <onyx/dentry.h>
#include <onyx/err.h>
#include <onyx/file.h>
#include <onyx/mount.h>
#include <onyx/namei.h>
Expand All @@ -17,7 +18,88 @@

#include <onyx/memory.hpp>

// XXX(heat): lookup root seems to leak
enum class fs_token_type : uint8_t
{
REGULAR_TOKEN = 0,
LAST_NAME_IN_PATH
};

/**
* @brief Represents a path during a lookup
*
*/
struct lookup_path
{
std::string_view view;
void *ownbuf{nullptr};
fs_token_type token_type{fs_token_type::REGULAR_TOKEN};
size_t pos{0};

lookup_path() = default;

lookup_path(std::string_view view) : view{view}
{
}

constexpr bool trailing_slash() const
{
return view[view.length() - 1] == '/';
}
};

struct nameidata
{
/* Data needed to resolve filesystem names:
* view - Contains the pathname;
* pos - Contains the offset in the parsing of the pathname;
* root - Contains the lookup's filesystem root;
* cur - Contains the current relative location and
* starts at whatever was passed as the relative dir (controlled with
* chdir or *at, or purely through kernel-side use).
*/
/* Note: root and location always hold a reference to the underlying object */
struct path root;
struct path cur;
/* Keeps the parent of cur, *if* we walked once */
struct path parent;

static constexpr const size_t max_loops = SYMLOOP_MAX;
/* Number of symbolic links found while looking up -
* if it reaches max_symlinks, the lookup fails with -ELOOP.
*/
int nloops{0};
int pdepth{0};
struct lookup_path paths[SYMLOOP_MAX];

unsigned int lookup_flags{};
int dirfd{AT_FDCWD};

nameidata(std::string_view view)
{
paths[0] = lookup_path{view};
path_init(&root);
path_init(&cur);
path_init(&parent);
}

~nameidata();

void setcur(struct path newcur)
{
DCHECK(!path_is_null(&newcur));
path_put(&parent);
parent = cur;
cur = newcur;
}

path getcur()
{
DCHECK(!path_is_null(&cur));
auto ret = cur;
path_init(&cur);
return ret;
}
};

std::string_view get_token_from_path(lookup_path &path, bool no_consume_if_last)
{
Expand Down Expand Up @@ -1366,3 +1448,10 @@ int path_openat(int dirfd, const char *name, unsigned int flags, struct path *pa
*path = namedata.getcur();
return 0;
}

extern "C" struct file *c_vfs_open(int dirfd, const char *name, unsigned int open_flags,
mode_t mode)
{
auto ex = vfs_open(dirfd, name, open_flags, mode);
return ex.has_value() ? ex.value() : (struct file *) ERR_PTR(ex.error());
}
2 changes: 1 addition & 1 deletion kernel/kernel/mm/Makefile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
mm-y:= bootmem.o page.o pagealloc.o vm_object.o vm.o vmalloc.o reclaim.o anon.o mincore.o page_lru.o rmap.o
mm-y:= bootmem.o page.o pagealloc.o vm_object.o vm.o vmalloc.o reclaim.o anon.o mincore.o page_lru.o swap.o rmap.o
mm-$(CONFIG_KUNIT)+= vm_tests.o
mm-$(CONFIG_X86)+= memory.o
mm-$(CONFIG_RISCV)+= memory.o
Expand Down
Loading

0 comments on commit 364ca7e

Please sign in to comment.