#include <lunaix/mm/valloc.h>
#include <lunaix/syslog.h>
+#include <lunaix/blkpart_gpt.h>
+
#include <lunaix/spike.h>
#define BLOCK_EREAD 1
void
block_init()
{
+ blkio_init();
lbd_pile = cake_new_pile("block_dev", sizeof(struct block_dev), 1, 0);
dev_registry = vcalloc(sizeof(struct block_dev*), MAX_DEV);
free_slot = 0;
{
int errno;
struct block_dev* bdev = (struct block_dev*)dev->underlay;
- size_t bsize = bdev->blk_size, rd_block = offset / bsize,
+ size_t bsize = bdev->blk_size, rd_block = offset / bsize + bdev->start_lba,
r = offset % bsize, rd_size = 0;
+ if (!(len = MIN(len, ((size_t)bdev->end_lba - rd_block + 1) * bsize))) {
+ return 0;
+ }
+
struct vecbuf* vbuf = vbuf_alloc(NULL, buf, len);
struct blkio_req* req;
void* tmp_buf = NULL;
if (r) {
tmp_buf = vzalloc(bsize);
rd_size = MIN(len, bsize - r);
- vbuf->buf.size = rd_size;
+ vbuf->buf.size = bsize;
vbuf->buf.buffer = tmp_buf;
- vbuf_alloc(vbuf, buf + rd_size, len - rd_size);
+ if ((len - rd_size)) {
+ vbuf_alloc(vbuf, buf + rd_size, len - rd_size);
+ }
}
req = blkio_vrd(vbuf, rd_block, NULL, NULL, 0);
blkio_commit(bdev->blkio, req);
- wait_if(req->flags & BLKIO_PENDING);
+
+ pwait(&req->wait);
if (!(errno = req->errcode)) {
memcpy(buf, tmp_buf + r, rd_size);
+ errno = len;
+ } else {
+ errno = -errno;
}
if (tmp_buf) {
__block_write(struct device* dev, void* buf, size_t offset, size_t len)
{
struct block_dev* bdev = (struct block_dev*)dev->underlay;
- size_t bsize = bdev->blk_size, rd_block = offset / bsize,
+ size_t bsize = bdev->blk_size, rd_block = offset / bsize + bdev->start_lba,
r = offset % bsize;
+ if (!(len = MIN(len, ((size_t)bdev->end_lba - rd_block + 1) * bsize))) {
+ return 0;
+ }
+
struct vecbuf* vbuf = vbuf_alloc(NULL, buf, len);
struct blkio_req* req;
void* tmp_buf = NULL;
req = blkio_vwr(vbuf, rd_block, NULL, NULL, 0);
blkio_commit(bdev->blkio, req);
- wait_if(req->flags & BLKIO_PENDING);
+
+ pwait(&req->wait);
int errno = req->errcode;
+ if (!errno) {
+ errno = len;
+ } else {
+ errno = -errno;
+ }
if (tmp_buf) {
vfree(tmp_buf);
block_alloc_dev(const char* blk_id, void* driver, req_handler ioreq_handler)
{
struct block_dev* bdev = cake_grab(lbd_pile);
- *bdev = (struct block_dev){ .driver = driver };
-
+ memset(bdev, 0, sizeof(struct block_dev));
+ llist_init_head(&bdev->parts);
strncpy(bdev->name, blk_id, PARTITION_NAME_SIZE);
bdev->blkio = blkio_newctx(ioreq_handler);
+ bdev->driver = driver;
+ bdev->blkio->driver = driver;
return bdev;
}
goto error;
}
+ errno = blkpart_probegpt(bdev->dev);
+ if (errno < 0) {
+ kprintf(KERROR "Fail to parse partition table (%d)\n", errno);
+ } else if (!errno) {
+ // TODO try other PT parser...
+ }
+
struct twifs_node* dev_root = twifs_dir_node(blk_sysroot, bdev->bdev_id);
blk_set_blkmapping(bdev, dev_root);
fs_export(bdev, dev_root);
strcpy(bdev->bdev_id, dev->name_val);
dev_registry[free_slot++] = bdev;
return 1;
+}
+
+struct block_dev*
+blk_mount_part(struct block_dev* bdev,
+ const char* name,
+ size_t index,
+ u64_t start_lba,
+ u64_t end_lba)
+{
+ struct block_dev* pbdev = cake_grab(lbd_pile);
+ memcpy(pbdev, bdev, sizeof(*bdev));
+
+ struct device* dev =
+ device_addvol(NULL, pbdev, "%sp%d", bdev->bdev_id, index + 1);
+ dev->write = __block_write;
+ dev->read = __block_read;
+
+ pbdev->start_lba = start_lba;
+ pbdev->end_lba = end_lba;
+ pbdev->dev = dev;
+
+ strcpy(pbdev->bdev_id, dev->name_val);
+ if (name) {
+ strncpy(pbdev->name, name, PARTITION_NAME_SIZE);
+ }
+
+ llist_append(&bdev->parts, &pbdev->parts);
+
+ return pbdev;
}
\ No newline at end of file