All of lore.kernel.org
 help / color / mirror / Atom feed
From: Peter Osterlund <petero2@telia.com>
To: linux-kernel@vger.kernel.org
Cc: Christoph Hellwig <hch@infradead.org>,
	Arnd Bergmann <arnd@arndb.de>, Jens Axboe <axboe@suse.de>,
	Andrew Morton <akpm@osdl.org>
Subject: Re: [RFC][PATCH] Control pktcdvd with an auxiliary character device
Date: 14 Jul 2004 02:17:27 +0200	[thread overview]
Message-ID: <m2oemjo31k.fsf@telia.com> (raw)
In-Reply-To: <m2vfgro3k6.fsf_-_@telia.com>

Peter Osterlund <petero2@telia.com> writes:

> Peter Osterlund <petero2@telia.com> writes:
> 
> > Christoph Hellwig <hch@infradead.org> writes:
> > 
> > > On Sun, Jul 11, 2004 at 01:20:45AM +0200, Arnd Bergmann wrote:
> > > > These are actually incorrect definitions since the ioctl argument is
> > > > not a pointer to unsigned int but instead just an int. However, that's
> > > > too late to fix without breaking the existing tools.
> > > 
> > > The tools need to change anyway to get away from the broken behaviour to
> > > issue in ioctl on the actual block device to bind it..
> > 
> > OK, I'll create a patch that gets rid of the ioctl interface and uses
> > an auxiliary character device instead to control device bindings.
> 
> Here is a patch for 2.6.7-mm7 that does that. The driver creates a
> misc character device and bind/unbind of the block devices are
> controlled by ioctl commands on the char device.
> 
> This patch needs corresponding changes in the pktsetup user space
> program. I'll post a patch for pktsetup as a separate message.

And here is a patch for udftools-1.0.0b3 that updates the pktsetup
program to make it able to use the character device for block device
setup/teardown.

---

 udftools-1.0.0b3-petero/pktsetup/pktsetup.c |  245 +++++++++++++++++++++++++++-
 1 files changed, 238 insertions(+), 7 deletions(-)

diff -puN pktsetup/pktsetup.c~pktsetup-char-dev pktsetup/pktsetup.c
--- udftools-1.0.0b3/pktsetup/pktsetup.c~pktsetup-char-dev	2004-07-12 19:57:51.000000000 +0200
+++ udftools-1.0.0b3-petero/pktsetup/pktsetup.c	2004-07-14 00:34:02.471317888 +0200
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 1999,2000	Jens Axboe <axboe@suse.de>
+ * Copyright (c) 2004		Peter Osterlund <petero2@telia.com>
  *
  *   This program is free software; you can redistribute it and/or modify
  *   it under the terms of the GNU General Public License as published by
@@ -19,6 +20,7 @@
 #include <stdio.h>
 #include <fcntl.h>
 #include <sys/ioctl.h>
+#include <sys/stat.h>
 #include <unistd.h>
 #include <getopt.h>
 #include <bits/types.h>
@@ -33,8 +35,33 @@
 #define PACKET_SETUP_DEV	_IOW('X', 1, unsigned int)
 #define PACKET_TEARDOWN_DEV	_IOW('X', 2, unsigned int)
 #endif
+#ifndef PACKET_CTRL_CMD
+#define PACKET_CTRL_CMD		_IOWR('X', 1, struct pkt_ctrl_command)
+#endif
+
+#define MAJOR(dev)      ((dev & 0xfff00) >> 8)
+#define MINOR(dev)      ((dev & 0xff) | ((dev >> 12) & 0xfff00))
+#define MKDEV(ma,mi)    ((mi & 0xff) | (ma << 8) | ((mi & ~0xff) << 12))
+
+#define MISC_MAJOR		10
+#define CTL_DIR "/dev/pktcdvd"
+#define CTL_DEV "control"
+
+#define PKT_CTRL_CMD_SETUP	0
+#define PKT_CTRL_CMD_TEARDOWN	1
+#define PKT_CTRL_CMD_STATUS	2
+
+struct pkt_ctrl_command {
+	__u32 command;				/* in: Setup, teardown, status */
+	__u32 dev_index;			/* in/out: Device index */
+	__u32 dev;				/* in/out: Device nr for cdrw device */
+	__u32 pkt_dev;				/* out: Device nr for packet device */
+	__u32 num_devices;			/* out: Largest device index + 1 */
+	__u32 padding;
+};
+
 
-int init_cdrom(int fd)
+static int init_cdrom(int fd)
 {
 	if (ioctl(fd, CDROM_DRIVE_STATUS, CDSL_CURRENT) < 0) {
 		perror("drive not ready\n");
@@ -54,7 +81,7 @@ int init_cdrom(int fd)
 	return 0;
 }
 
-void setup_dev(char *pkt_device, char *device, int rem)
+static void setup_dev(char *pkt_device, char *device, int rem)
 {
 	int pkt_fd, dev_fd, cmd;
 
@@ -88,29 +115,233 @@ void setup_dev(char *pkt_device, char *d
 	close(pkt_fd);
 }
 
-int usage(void)
+static int usage(void)
 {
-	printf("pktsetup /dev/pktcdvd0 /dev/cdrom\tsetup device\n");
-	printf("pktsetup -d /dev/pktcdvd0\t\ttear down device\n");
+	printf("For pktcdvd < 0.2.0:\n");
+	printf("  pktsetup /dev/pktcdvd0 /dev/cdrom  setup device\n");
+	printf("  pktsetup -d /dev/pktcdvd0          tear down device\n");
+	printf("For pktcdvd >= 0.2.0:\n");
+	printf("  pktsetup dev_name /dev/cdrom       setup device\n");
+	printf("  pktsetup -d dev_name               tear down device\n");
+	printf("  pktsetup -d major:minor            tear down device\n");
+	printf("  pktsetup -s                        show device mappings\n");
 	return 1;
 }
 
+/*
+ * Find the minor device number for the pktcdvd control device.
+ */
+static int get_misc_minor(void)
+{
+	int minor;
+	char name[64];
+	FILE *f;
+
+	if ((f = fopen("/proc/misc", "r")) == NULL)
+		return -1;
+	while (fscanf(f, " %d %64s", &minor, name) == 2) {
+		if (strcmp(name, "pktcdvd") == 0) {
+			fclose(f);
+			return minor;
+		}
+	}
+	fclose(f);
+	return -1;
+}
+
+static const char *pkt_dev_name(const char *dev)
+{
+	static char buf[128];
+	snprintf(buf, sizeof(buf), "%s/%s", CTL_DIR, dev);
+	return buf;
+}
+
+static void create_ctl_dev(void)
+{
+	int misc_minor;
+	struct stat stat_buf;
+	int dev;
+
+	if ((misc_minor = get_misc_minor()) < 0) {
+		system("/sbin/modprobe pktcdvd");
+		misc_minor = get_misc_minor();
+	}
+	if (misc_minor < 0) {
+		fprintf(stderr, "Can't find pktcdvd character device\n");
+		return;
+	}
+	dev = MKDEV(MISC_MAJOR, misc_minor);
+
+	if ((stat(pkt_dev_name(CTL_DEV), &stat_buf) >= 0) &&
+	    S_ISCHR(stat_buf.st_mode) && (stat_buf.st_rdev == dev))
+		return;			    /* Already set up */
+
+	mkdir(CTL_DIR, 0755);
+	unlink(pkt_dev_name(CTL_DEV));
+	mknod(pkt_dev_name(CTL_DEV), S_IFCHR | 0644, dev);
+}
+
+static int remove_stale_dev_node(int ctl_fd, char *devname)
+{
+	struct stat stat_buf;
+	int i, dev;
+	struct pkt_ctrl_command c;
+
+	if (stat(pkt_dev_name(devname), &stat_buf) < 0)
+		return 0;
+	if (!S_ISBLK(stat_buf.st_mode))
+		return 1;
+	dev = stat_buf.st_rdev;
+	memset(&c, 0, sizeof(struct pkt_ctrl_command));
+	for (i = 0; ; i++) {
+		c.command = PKT_CTRL_CMD_STATUS;
+		c.dev_index = i;
+		if (ioctl(ctl_fd, PACKET_CTRL_CMD, &c) < 0) {
+			perror("ioctl");
+			return 1;
+		}
+		if (i >= c.num_devices)
+			break;
+		if (c.pkt_dev == dev)
+			return 1;	    /* busy */
+	}
+	unlink(pkt_dev_name(devname));
+	return 0;
+}
+
+static void setup_dev_chardev(char *pkt_device, char *device, int rem)
+{
+	struct pkt_ctrl_command c;
+	struct stat stat_buf;
+	int ctl_fd, dev_fd;
+
+	memset(&c, 0, sizeof(struct pkt_ctrl_command));
+
+	create_ctl_dev();
+	if ((ctl_fd = open(pkt_dev_name(CTL_DEV), O_RDONLY)) < 0) {
+		perror("ctl open");
+		return;
+	}
+
+	if (!rem) {
+		if ((dev_fd = open(device, O_RDONLY | O_NONBLOCK)) == -1) {
+			perror("open cd-rom");
+			goto out_close;
+		}
+		if (init_cdrom(dev_fd)) {
+			close(dev_fd);
+			goto out_close;
+		}
+		close(dev_fd);
+
+		if (stat(device, &stat_buf) < 0) {
+			perror("stat cd-rom");
+			goto out_close;
+		}
+		if (!S_ISBLK(stat_buf.st_mode)) {
+			fprintf(stderr, "Not a block device\n");
+			goto out_close;
+		}
+		c.command = PKT_CTRL_CMD_SETUP;
+		c.dev = stat_buf.st_rdev;
+
+		if (remove_stale_dev_node(ctl_fd, pkt_device) != 0) {
+			fprintf(stderr, "Device node '%s' already in use\n", pkt_device);
+			goto out_close;
+		}
+		if (ioctl(ctl_fd, PACKET_CTRL_CMD, &c) < 0) {
+			perror("ioctl");
+			goto out_close;
+		}
+		mknod(pkt_dev_name(pkt_device), S_IFBLK | 0640, c.pkt_dev);
+	} else {
+		int major, minor, remove_node;
+
+		if ((stat(pkt_dev_name(pkt_device), &stat_buf) >= 0) &&
+		    S_ISBLK(stat_buf.st_mode)) {
+			major = MAJOR(stat_buf.st_rdev);
+			minor = MINOR(stat_buf.st_rdev);
+			remove_node = 1;
+		} else if (sscanf(pkt_device, "%d:%d", &major, &minor) == 2) {
+			remove_node = 0;
+		} else {
+			fprintf(stderr, "Can't find major/minor numbers\n");
+			goto out_close;
+		}
+
+		c.command = PKT_CTRL_CMD_TEARDOWN;
+		c.pkt_dev = MKDEV(major, minor);
+		if (ioctl(ctl_fd, PACKET_CTRL_CMD, &c) < 0) {
+			perror("ioctl");
+			goto out_close;
+		}
+		if (remove_node)
+			unlink(pkt_dev_name(pkt_device));
+	}
+
+out_close:
+	close(ctl_fd);
+}
+
+static void show_mappings(void)
+{
+	struct pkt_ctrl_command c;
+	int ctl_fd, i;
+
+	memset(&c, 0, sizeof(struct pkt_ctrl_command));
+
+	create_ctl_dev();
+	if ((ctl_fd = open(pkt_dev_name(CTL_DEV), O_RDONLY)) < 0) {
+		perror("ctl open");
+		return;
+	}
+
+	for (i = 0; ; i++) {
+		c.command = PKT_CTRL_CMD_STATUS;
+		c.dev_index = i;
+		if (ioctl(ctl_fd, PACKET_CTRL_CMD, &c) < 0) {
+			perror("ioctl");
+			goto out_close;
+		}
+		if (i >= c.num_devices)
+			break;
+		if (c.dev) {
+			printf("%2d : %d:%d -> %d:%d\n",
+			       i, MAJOR(c.pkt_dev), MINOR(c.pkt_dev),
+			       MAJOR(c.dev), MINOR(c.dev));
+		}
+	}
+
+out_close:
+	close(ctl_fd);
+}
+
 int main(int argc, char **argv)
 {
 	int rem = 0, c;
+	char *pkt_device;
+	char *device;
 
 	if (argc == 1)
 		return usage();
 
-	while ((c = getopt(argc, argv, "d")) != EOF) {
+	while ((c = getopt(argc, argv, "ds?")) != EOF) {
 		switch (c) {
 			case 'd':
 				rem = 1;
 				break;
+			case 's':
+				show_mappings();
+				return 0;
 			default:
 				return usage();
 		}
 	}
-	setup_dev(argv[optind], argv[optind + 1], rem);
+	pkt_device = argv[optind];
+	device = argv[optind + 1];
+	if (strchr(pkt_device, '/'))
+		setup_dev(pkt_device, device, rem);
+	else
+		setup_dev_chardev(pkt_device, device, rem);
 	return 0;
 }
_

-- 
Peter Osterlund - petero2@telia.com
http://w1.894.telia.com/~u89404340

  reply	other threads:[~2004-07-14  0:17 UTC|newest]

Thread overview: 27+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2004-07-01 13:34 [PATCH] CDRW packet writing support for 2.6.7-bk13 Peter Osterlund
2004-07-02 21:52 ` Peter Osterlund
2004-07-02 22:08   ` Andrew Morton
2004-07-02 22:47     ` Greg KH
2004-07-02 22:59       ` Andrew Morton
2004-07-02 23:24         ` Peter Osterlund
2004-07-02 23:51           ` Andrew Morton
2004-07-04 11:57             ` Peter Osterlund
2004-07-04 20:58               ` Andrew Morton
2004-07-04 21:06                 ` Christoph Hellwig
2004-07-04 12:30 ` [PATCH] Fix race in pktcdvd kernel thread handling Peter Osterlund
2004-07-04 12:37 ` [PATCH] Fix open/close races in pktcdvd Peter Osterlund
2004-07-04 13:05 ` [PATCH] CDRW packet writing support for 2.6.7-bk13 Christoph Hellwig
2004-07-04 23:49   ` Peter Osterlund
2004-07-05  0:01     ` Peter Osterlund
2004-07-10 23:20       ` Arnd Bergmann
2004-07-10 23:27         ` Christoph Hellwig
2004-07-11  1:06           ` Peter Osterlund
2004-07-12 16:25             ` Arnd Bergmann
2004-07-12 16:34               ` Christoph Hellwig
2004-07-13  6:04                 ` Jens Axboe
2004-07-14  0:06             ` [RFC][PATCH] Control pktcdvd with an auxiliary character device Peter Osterlund
2004-07-14  0:17               ` Peter Osterlund [this message]
2004-07-05  8:17     ` [PATCH] CDRW packet writing support for 2.6.7-bk13 Jens Axboe
2004-07-05 10:26     ` Christoph Hellwig
2004-07-06  8:45     ` Peter Osterlund
2004-07-07 10:06   ` Peter Osterlund

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=m2oemjo31k.fsf@telia.com \
    --to=petero2@telia.com \
    --cc=akpm@osdl.org \
    --cc=arnd@arndb.de \
    --cc=axboe@suse.de \
    --cc=hch@infradead.org \
    --cc=linux-kernel@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.