Skip to content

Commit

Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
block: Allocate bio_reqs on the heap, not on the stack
Browse files Browse the repository at this point in the history
Signed-off-by: Pedro Falcato <pedro.falcato@gmail.com>
heatd committed Jan 5, 2024
1 parent c00abf8 commit d445e5c
Showing 7 changed files with 162 additions and 55 deletions.
27 changes: 16 additions & 11 deletions kernel/drivers/ahci/ahci.cpp
Original file line number Diff line number Diff line change
@@ -372,16 +372,19 @@ long ahci_setup_prdt_bio(prdt_t *prdt, struct bio_req *r, size_t *size)

bool ahci_do_command(struct ahci_port *ahci_port, struct ahci_command_ata *buf)
{
struct bio_req r;
r.bdev = ahci_port->bdev.get();
r.curr_vec_index = 0;
r.flags = BIO_REQ_DEVICE_SPECIFIC;
r.device_specific[0] = buf->cmd;
r.sector_number = 0;
r.nr_vecs = buf->nr_iov;
r.vec = buf->iovec;

if (ahci_port->io_queue->submit_request(&r) < 0)
struct bio_req *r = bio_alloc_and_init(GFP_KERNEL);
if (!r)
return false;

r->bdev = ahci_port->bdev.get();
r->curr_vec_index = 0;
r->flags = BIO_REQ_DEVICE_SPECIFIC;
r->device_specific[0] = buf->cmd;
r->sector_number = 0;
r->nr_vecs = buf->nr_iov;
r->vec = buf->iovec;

if (ahci_port->io_queue->submit_request(r) < 0)
return false;

int st = wait_for(
@@ -392,7 +395,9 @@ bool ahci_do_command(struct ahci_port *ahci_port, struct ahci_command_ata *buf)
},
WAIT_FOR_FOREVER, 0);

return st == 0 && !(r.flags & BIO_REQ_EIO);
bool ret = st == 0 && !(r->flags & BIO_REQ_EIO);
bio_free(r);
return ret;
}

unsigned int ahci_check_drive_type(ahci_port_t *port)
34 changes: 34 additions & 0 deletions kernel/include/onyx/block.h
Original file line number Diff line number Diff line change
@@ -55,6 +55,40 @@ struct bio_req
unsigned long device_specific[4];
};

/**
* @brief Allocate a bio_req
*
* @param gfp_flags GFP flags
* @return The allocated, uninitialized bio_req
*/
struct bio_req *bio_alloc(unsigned int gfp_flags);

/**
* @brief Free a bio_req
*
* @param req Request to free
*/
void bio_free(struct bio_req *req);

static inline void bio_init(struct bio_req *req)
{
*req = {};
}

/**
* @brief Allocate a bio_req and initialize it
*
* @param gfp_flags GFP flags
* @return The allocated, initialized bio_req
*/
static inline struct bio_req *bio_alloc_and_init(unsigned int gfp_flags)
{
struct bio_req *bio = bio_alloc(gfp_flags);
if (likely(bio))
bio_init(bio);
return bio;
}

using __blkflush = int (*)(struct blockdev *);
using __blkpowermanagement = int (*)(int, struct blockdev *);

6 changes: 5 additions & 1 deletion kernel/include/onyx/page.h
Original file line number Diff line number Diff line change
@@ -153,9 +153,13 @@ struct page *page_add_page_late(void *paddr);
#define __GFP_DIRECT_RECLAIM (1 << 8)
#define __GFP_WAKE_PAGEDAEMON (1 << 9)
#define __GFP_ATOMIC (1 << 10)
#define __GFP_IO (1 << 11)
#define __GFP_FS (1 << 12)
#define __GFP_MAY_RECLAIM (__GFP_DIRECT_RECLAIM | __GFP_WAKE_PAGEDAEMON)
#define GFP_KERNEL __GFP_MAY_RECLAIM
#define GFP_KERNEL (__GFP_MAY_RECLAIM | __GFP_IO)
#define GFP_ATOMIC (__GFP_ATOMIC | __GFP_WAKE_PAGEDAEMON)
#define GFP_NOIO (__GFP_MAY_RECLAIM)
#define GFP_NOFS (__GFP_MAY_RECLAIM | __GFP_IO)

static inline bool __page_should_zero(unsigned long flags)
{
30 changes: 30 additions & 0 deletions kernel/kernel/fs/block.cpp
Original file line number Diff line number Diff line change
@@ -15,6 +15,7 @@
#include <onyx/block.h>
#include <onyx/buffer.h>
#include <onyx/filemap.h>
#include <onyx/mm/slab.h>
#include <onyx/page.h>
#include <onyx/page_iov.h>
#include <onyx/rwlock.h>
@@ -258,3 +259,32 @@ flush::writeback_dev *bdev_get_wbdev(struct inode *ino)
DCHECK(dev != nullptr);
return dev;
}

static struct slab_cache *bio_cache;

__init static void bio_cache_init()
{
bio_cache = kmem_cache_create("bio_req", sizeof(bio_req), 0, 0, nullptr);
CHECK(bio_cache != nullptr);
}

/**
* @brief Allocate a bio_req
*
* @param gfp_flags GFP flags
* @return The allocated, uninitialized bio_req
*/
struct bio_req *bio_alloc(unsigned int gfp_flags)
{
return (struct bio_req *) kmem_cache_alloc(bio_cache, gfp_flags);
}

/**
* @brief Free a bio_req
*
* @param req Request to free
*/
void bio_free(struct bio_req *req)
{
kmem_cache_free(bio_cache, req);
}
36 changes: 23 additions & 13 deletions kernel/kernel/fs/buffer.cpp
Original file line number Diff line number Diff line change
@@ -64,18 +64,24 @@ ssize_t buffer_writepage(struct page *page, size_t offset, struct inode *ino) RE
vec.page_off = first_dirty->page_off;
vec.page = first_dirty->this_page;

struct bio_req r = {};
r.nr_vecs = 1;
r.sector_number = disk_sect;
r.flags = BIO_REQ_WRITE_OP;

r.vec = &vec;
struct bio_req *r = bio_alloc_and_init(GFP_NOIO);
if (!r)
return -EIO;
r->nr_vecs = 1;
r->sector_number = disk_sect;
r->flags = BIO_REQ_WRITE_OP;
r->vec = &vec;

page_start_writeback(page, ino);
__atomic_fetch_or(&vec.page->flags, PAGE_FLAG_WRITEBACK, __ATOMIC_RELAXED);

if (bio_submit_request(blkdev, &r) < 0)
if (bio_submit_request(blkdev, r) < 0)
{
bio_free(r);
return -EIO;
}

bio_free(r);
page_end_writeback(page, ino);

#if 0
@@ -240,18 +246,22 @@ ssize_t bbuffer_readpage(struct page *p, size_t off, struct inode *ino)
vec.page = p;
vec.page_off = 0;

struct bio_req r = {};
r.nr_vecs = 1;
r.vec = &vec;
r.sector_number = sec_nr;
r.flags = BIO_REQ_READ_OP;
struct bio_req *r = bio_alloc_and_init(GFP_NOIO);
if (!r)
return -EIO;

r->nr_vecs = 1;
r->vec = &vec;
r->sector_number = sec_nr;
r->flags = BIO_REQ_READ_OP;

auto nr_blocks = PAGE_SIZE / block_size;
size_t starting_block_nr = off / block_size;

size_t curr_off = 0;

int iost = bio_submit_request(blkdev, &r);
int iost = bio_submit_request(blkdev, r);
bio_free(r);
if (iost < 0)
return iost;

46 changes: 32 additions & 14 deletions kernel/kernel/fs/partition.cpp
Original file line number Diff line number Diff line change
@@ -103,6 +103,7 @@ static uuid_t unused_type = {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0
static struct page *read_disk(struct blockdev *dev, sector_t sector, size_t count)
{
size_t nr_pages = vm_size_to_pages(count);
struct bio_req *r = nullptr;
struct page *p = nullptr;
int st = 0;
struct page *pages =
@@ -127,14 +128,21 @@ static struct page *read_disk(struct blockdev *dev, sector_t sector, size_t coun
p = p->next_un.next_allocation;
}

struct bio_req r;
r.curr_vec_index = 0;
r.flags = BIO_REQ_READ_OP;
r.nr_vecs = nr_pages;
r.sector_number = sector;
r.vec = vec;
r = bio_alloc_and_init(GFP_KERNEL);
if (!r)
{
st = -ENOMEM;
goto out;
}

r->curr_vec_index = 0;
r->flags = BIO_REQ_READ_OP;
r->nr_vecs = nr_pages;
r->sector_number = sector;
r->vec = vec;

st = bio_submit_request(dev, &r);
st = bio_submit_request(dev, r);
bio_free(r);
out:
if (st < 0)
free_pages(pages);
@@ -192,6 +200,7 @@ int partition_setup_disk_gpt(struct blockdev *dev)
struct page *p = nullptr;
unsigned int nr_parts = 1;
struct page *part_tab_pages = nullptr;
struct bio_req *r = nullptr;

struct page *gpt_header_pages = read_disk(dev, 1, dev->sector_size);
if (!gpt_header_pages)
@@ -252,20 +261,29 @@ int partition_setup_disk_gpt(struct blockdev *dev)
p = p->next_un.next_allocation;
}

struct bio_req r;
r.curr_vec_index = 0;
r.flags = BIO_REQ_READ_OP;
r.nr_vecs = vm_size_to_pages(count);
r.sector_number = 2;
r.vec = vec;
r = bio_alloc_and_init(GFP_KERNEL);
if (!r)
{
st = -ENOMEM;
goto out;
}

if (bio_submit_request(dev, &r) < 0)
r->curr_vec_index = 0;
r->flags = BIO_REQ_READ_OP;
r->nr_vecs = vm_size_to_pages(count);
r->sector_number = 2;
r->vec = vec;

if (bio_submit_request(dev, r) < 0)
{
bio_free(r);
printk("Error reading partition table\n");
st = -EIO;
goto out;
}

bio_free(r);

csum = gpt_header->partition_array_crc32;

actual_csum = crc32_calculate((uint8_t *) part_table, count);
38 changes: 22 additions & 16 deletions kernel/kernel/fs/superblock.cpp
Original file line number Diff line number Diff line change
@@ -18,26 +18,32 @@ void superblock_init(struct superblock *sb)

int sb_read_bio(struct superblock *sb, struct page_iov *vec, size_t nr_vecs, size_t block_number)
{
struct bio_req r
{
};
r.nr_vecs = nr_vecs;
r.vec = vec;
r.sector_number = block_number * (sb->s_block_size / sb->s_bdev->sector_size);
r.flags = BIO_REQ_READ_OP;
struct bio_req *r = bio_alloc_and_init(GFP_NOFS);
if (!r)
return -ENOMEM;

return bio_submit_request(sb->s_bdev, &r);
r->nr_vecs = nr_vecs;
r->vec = vec;
r->sector_number = block_number * (sb->s_block_size / sb->s_bdev->sector_size);
r->flags = BIO_REQ_READ_OP;

int st = bio_submit_request(sb->s_bdev, r);
bio_free(r);
return st;
}

int sb_write_bio(struct superblock *sb, struct page_iov *vec, size_t nr_vecs, size_t block_number)
{
struct bio_req r
{
};
r.nr_vecs = nr_vecs;
r.vec = vec;
r.sector_number = block_number * (sb->s_block_size / sb->s_bdev->sector_size);
r.flags = BIO_REQ_WRITE_OP;
struct bio_req *r = bio_alloc_and_init(GFP_NOFS);
if (!r)
return -ENOMEM;

r->nr_vecs = nr_vecs;
r->vec = vec;
r->sector_number = block_number * (sb->s_block_size / sb->s_bdev->sector_size);
r->flags = BIO_REQ_WRITE_OP;

return bio_submit_request(sb->s_bdev, &r);
int st = bio_submit_request(sb->s_bdev, r);
bio_free(r);
return st;
}

0 comments on commit d445e5c

Please sign in to comment.