diff options
author | Ian Moffett <ian@osmora.org> | 2025-10-14 20:23:19 -0400 |
---|---|---|
committer | Ian Moffett <ian@osmora.org> | 2025-10-14 20:23:19 -0400 |
commit | aaa076ff1d68545085fb85ee24d5410b60a123bd (patch) | |
tree | 98b1642cd6aae676b15318e376661e7b343196f9 /src/sys/dms/dms_subr.c | |
parent | 6a0c08f51e59328d9a158bb521b1f1cf57663962 (diff) |
kern: dms: Make DMS block size aware
In order to safely copy between disk and host memory through a
programming interface, DMS must be aware of the hardware disk block size
Signed-off-by: Ian Moffett <ian@osmora.org>
Diffstat (limited to 'src/sys/dms/dms_subr.c')
-rw-r--r-- | src/sys/dms/dms_subr.c | 35 |
1 files changed, 33 insertions, 2 deletions
diff --git a/src/sys/dms/dms_subr.c b/src/sys/dms/dms_subr.c index 240449a..085633b 100644 --- a/src/sys/dms/dms_subr.c +++ b/src/sys/dms/dms_subr.c @@ -30,6 +30,7 @@ #include <sys/types.h> #include <sys/errno.h> #include <sys/queue.h> +#include <sys/param.h> #include <os/kalloc.h> #include <dms/dms.h> #include <string.h> @@ -100,6 +101,9 @@ dms_get(disk_id_t disk_id) ssize_t dms_write(struct dms_disk *dp, void *p, off_t off, size_t len) { + void *buf; + size_t real_len; + int error; struct dms_ops *ops; if (dp == NULL || p == NULL) { @@ -114,13 +118,25 @@ dms_write(struct dms_disk *dp, void *p, off_t off, size_t len) return -ENOTSUP; } - return ops->write(dp, p, off, len); + real_len = ALIGN_UP(len, dp->bsize); + if ((buf = kalloc(real_len)) == NULL) { + return -ENOMEM; + } + + memset(buf, 0, real_len); + memcpy(buf, p, len); + error = ops->write(dp, buf, off, real_len); + kfree(buf); + return error; } ssize_t dms_read(struct dms_disk *dp, void *p, off_t off, size_t len) { + void *buf; struct dms_ops *ops; + size_t real_len; + int error; if (dp == NULL || p == NULL) { return -EINVAL; @@ -134,5 +150,20 @@ dms_read(struct dms_disk *dp, void *p, off_t off, size_t len) return -ENOTSUP; } - return ops->read(dp, p, off, len); + /* Allocate a real sized buffer */ + real_len = ALIGN_UP(len, dp->bsize); + if ((buf = kalloc(real_len)) == NULL) { + return -ENOMEM; + } + + memset(buf, 0, real_len); + error = ops->read(dp, buf, off, real_len); + if (error < 0) { + kfree(buf); + return error; + } + + memcpy(p, buf, len); + kfree(buf); + return 0; } |