Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/dev/pud Handle DIOCGPART in-kernel because a userspace s...
details: https://anonhg.NetBSD.org/src/rev/faf297580f0a
branches: trunk
changeset: 750268:faf297580f0a
user: pooka <pooka%NetBSD.org@localhost>
date: Tue Dec 22 17:32:03 2009 +0000
description:
Handle DIOCGPART in-kernel because a userspace server doesn't have
a chance in phobos of handling it. This makes it possible to do a
kernel mount of most file systems with the block device backed by
a pud userspace server.
- i'm too young to compile
- hey, no tty rough
- hurd me plenty
=> abstraction-violence
- nightmare!
diffstat:
sys/dev/pud/pud_dev.c | 61 +++++++++++++++++++++++++++++++++++++++++++++++++-
1 files changed, 59 insertions(+), 2 deletions(-)
diffs (96 lines):
diff -r b12e2d3f923e -r faf297580f0a sys/dev/pud/pud_dev.c
--- a/sys/dev/pud/pud_dev.c Tue Dec 22 16:32:41 2009 +0000
+++ b/sys/dev/pud/pud_dev.c Tue Dec 22 17:32:03 2009 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: pud_dev.c,v 1.5 2009/12/22 14:12:40 pooka Exp $ */
+/* $NetBSD: pud_dev.c,v 1.6 2009/12/22 17:32:03 pooka Exp $ */
/*
* Copyright (c) 2007 Antti Kantee. All Rights Reserved.
@@ -29,7 +29,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: pud_dev.c,v 1.5 2009/12/22 14:12:40 pooka Exp $");
+__KERNEL_RCSID(0, "$NetBSD: pud_dev.c,v 1.6 2009/12/22 17:32:03 pooka Exp $");
#include <sys/param.h>
#include <sys/buf.h>
@@ -57,13 +57,37 @@
return pud_request(dev, &pc_oc, sizeof(pc_oc), class, type);
}
+#include <sys/disklabel.h>
+/*
+ * XXX: this is not "reentrant". But then again, partinfo isn't
+ * exactly safe in any case.
+ */
+static struct disklabel dl_partinfo;
+
static int
doioctl(dev_t dev, u_long cmd, void *data, int flag, int class, int type)
{
struct pud_req_ioctl *pc_ioctl;
size_t dlen, allocsize;
+ u_long origcmd = cmd;
+ void *origdata = NULL; /* XXXgcc */
int error;
+ /*
+ * XXX: kludge. This is a horrible abstraction violation, but
+ * then again DIOCGPART is a horrible ioctl (even more horrible
+ * than the generic ioctl). We handle it specially here since
+ * the server in userspace has no chance to handle it. And it's
+ * a common operation used by most file systems. But really, it
+ * should be replaced by something a bit more ... transactional.
+ */
+ if (cmd == DIOCGPART) {
+ cmd = DIOCGDINFO;
+ origdata = data;
+ flag = 0;
+ data = &dl_partinfo;
+ }
+
dlen = IOCPARM_LEN(cmd);
allocsize = sizeof(struct pud_req_ioctl) + dlen;
pc_ioctl = kmem_zalloc(allocsize, KM_SLEEP);
@@ -79,6 +103,39 @@
if (cmd & IOC_OUT)
memcpy(data, pc_ioctl->pm_data, dlen);
+ /*
+ * In case doing the infamous DIOCGPART, issue the real
+ * ioctl and do pointer arithmetic to figure out the right
+ * partition. We could use DISKPART() too, but this seems
+ * "better".
+ */
+ if (origcmd == DIOCGPART) {
+ struct partinfo *pi, *pi_user;
+ int labidx;
+
+ CTASSERT(sizeof(struct partinfo) <= sizeof(struct disklabel));
+
+ pc_ioctl->pm_iocmd = DIOCGPART;
+ pc_ioctl->pm_flag = 0;
+
+ error = pud_request(dev, pc_ioctl, allocsize, class, type);
+ if (error)
+ goto out;
+
+ pi_user = (struct partinfo *)pc_ioctl->pm_data;
+ labidx = pi_user->part - &pi_user->disklab->d_partitions[0];
+ /* userspace error, but punish caller, since we have no infra */
+ if (labidx >= MAXPARTITIONS) {
+ error = E2BIG;
+ goto out;
+ }
+
+ pi = origdata;
+ pi->disklab = &dl_partinfo;
+ pi->part = &dl_partinfo.d_partitions[labidx];
+
+ }
+
out:
kmem_free(pc_ioctl, allocsize);
return error;
Home |
Main Index |
Thread Index |
Old Index