dev: implement reading from block devices

reading from block devices is done using the block cache (bcache).
This cache stores sectors from a block device in pages of memory
marked as 'cached', which will allow them to be reclaimed when
memory pressure is high (TODO).

while block device drivers implement callbacks allowing reading/writing
at block-granularity, the device subsystem uses the block cache to
implement reading/writing at byte-granularity in a driver-agnostic way.

block drivers can disable the block cache for their devices, but this
will require that any clients communicate with the devices at
block-granularity.

also added an offset parameter to device and object read/write functions/callbacks.
This commit is contained in:
2023-07-09 21:58:40 +01:00
parent 53440653f2
commit 3233169f25
14 changed files with 435 additions and 52 deletions

View File

@@ -11,8 +11,8 @@ static struct object *dev_folder = NULL;
static struct device *__root_device = NULL;
static struct device *__misc_device = NULL;
static kern_status_t device_object_destroy(struct object *);
static kern_status_t device_object_read(struct object *obj, void *, size_t *, socks_flags_t);
static kern_status_t device_object_write(struct object *obj, const void *, size_t *, socks_flags_t);
static kern_status_t device_object_read(struct object *obj, void *, size_t, size_t *, socks_flags_t);
static kern_status_t device_object_write(struct object *obj, const void *, size_t, size_t *, socks_flags_t);
static kern_status_t device_object_query_name(struct object *, char out[OBJECT_NAME_MAX]);
static kern_status_t device_object_get_child_at(struct object *, size_t, struct object **);
static kern_status_t device_object_get_child_named(struct object *, const char *, struct object **);
@@ -123,23 +123,23 @@ struct device *generic_device_create(void)
return dev;
}
kern_status_t device_read(struct device *dev, void *buf, size_t size, size_t *bytes_read, socks_flags_t flags)
kern_status_t device_read(struct device *dev, void *buf, size_t offset, size_t size, size_t *bytes_read, socks_flags_t flags)
{
kern_status_t status = KERN_UNSUPPORTED;
if (type_ops[dev->dev_type] && type_ops[dev->dev_type]->read) {
status = type_ops[dev->dev_type]->read(dev, buf, size, bytes_read, flags);
status = type_ops[dev->dev_type]->read(dev, buf, offset, size, bytes_read, flags);
}
return status;
}
kern_status_t device_write(struct device *dev, const void *buf, size_t size, size_t *bytes_written, socks_flags_t flags)
kern_status_t device_write(struct device *dev, const void *buf, size_t offset, size_t size, size_t *bytes_written, socks_flags_t flags)
{
kern_status_t status = KERN_UNSUPPORTED;
if (type_ops[dev->dev_type] && type_ops[dev->dev_type]->write) {
status = type_ops[dev->dev_type]->write(dev, buf, size, bytes_written, flags);
status = type_ops[dev->dev_type]->write(dev, buf, offset, size, bytes_written, flags);
}
return status;
@@ -150,16 +150,16 @@ struct device *cast_to_device(struct object *obj)
return DEVICE_CAST(obj);
}
static kern_status_t device_object_read(struct object *obj, void *p, size_t *count, socks_flags_t flags)
static kern_status_t device_object_read(struct object *obj, void *p, size_t offset, size_t *count, socks_flags_t flags)
{
struct device *dev = DEVICE_CAST(obj);
return device_read(dev, p, *count, count, flags);
return device_read(dev, p, *count, offset, count, flags);
}
static kern_status_t device_object_write(struct object *obj, const void *p, size_t *count, socks_flags_t flags)
static kern_status_t device_object_write(struct object *obj, const void *p, size_t offset, size_t *count, socks_flags_t flags)
{
struct device *dev = DEVICE_CAST(obj);
return device_write(dev, p, *count, count, flags);
return device_write(dev, p, *count, offset, count, flags);
}
static kern_status_t device_object_destroy(struct object *obj)