aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeff Dike <jdike@addtoit.com>2005-06-25 14:55:25 -0700
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-06-25 16:24:36 -0700
commit29d56cfe3ca599ddc3ae9156e7e469c044d97b96 (patch)
tree7790477f5b138c249725fe8ecf9dc07794e9d1eb
parentfc47a0d18a1994b4a18d2235fcde1b75dfa72552 (diff)
[PATCH] uml: hot-unplug code cleanup
Clean up the hot-unplugging code. There is now an id procedure which is called to figure out what device we're talking to. The error messages from that are now done from mconsole_remove instead of the driver. remove is now called with the device number, after it has been checked, so doesn't need to do sanity checking on it. Signed-off-by: Jeff Dike <jdike@addtoit.com> Cc: Paolo Giarrusso <blaisorblade@yahoo.it> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r--arch/um/drivers/line.c19
-rw-r--r--arch/um/drivers/mconsole_kern.c36
-rw-r--r--arch/um/drivers/net_kern.c31
-rw-r--r--arch/um/drivers/ssl.c9
-rw-r--r--arch/um/drivers/stdio_console.c7
-rw-r--r--arch/um/drivers/ubd_kern.c37
-rw-r--r--arch/um/include/line.h3
-rw-r--r--arch/um/include/mconsole_kern.h3
-rw-r--r--arch/um/kernel/tt/gdb.c4
-rw-r--r--arch/um/kernel/tt/gdb_kern.c2
-rw-r--r--arch/um/kernel/tt/include/debug.h17
11 files changed, 113 insertions, 55 deletions
diff --git a/arch/um/drivers/line.c b/arch/um/drivers/line.c
index 0f59736db32..2bb4c4f5dec 100644
--- a/arch/um/drivers/line.c
+++ b/arch/um/drivers/line.c
@@ -602,11 +602,26 @@ int line_get_config(char *name, struct line *lines, unsigned int num, char *str,
return n;
}
-int line_remove(struct line *lines, unsigned int num, char *str)
+int line_id(char **str, int *start_out, int *end_out)
+{
+ char *end;
+ int n;
+
+ n = simple_strtoul(*str, &end, 0);
+ if((*end != '\0') || (end == *str))
+ return -1;
+
+ *str = end;
+ *start_out = n;
+ *end_out = n;
+ return n;
+}
+
+int line_remove(struct line *lines, unsigned int num, int n)
{
char config[sizeof("conxxxx=none\0")];
- sprintf(config, "%s=none", str);
+ sprintf(config, "%d=none", n);
return !line_setup(lines, num, config, 0);
}
diff --git a/arch/um/drivers/mconsole_kern.c b/arch/um/drivers/mconsole_kern.c
index d7c7adcc0a6..404de41a4f6 100644
--- a/arch/um/drivers/mconsole_kern.c
+++ b/arch/um/drivers/mconsole_kern.c
@@ -419,8 +419,9 @@ void mconsole_config(struct mc_request *req)
void mconsole_remove(struct mc_request *req)
{
struct mc_device *dev;
- char *ptr = req->request.data;
- int err;
+ char *ptr = req->request.data, *err_msg = "";
+ char error[256];
+ int err, start, end, n;
ptr += strlen("remove");
while(isspace(*ptr)) ptr++;
@@ -429,8 +430,35 @@ void mconsole_remove(struct mc_request *req)
mconsole_reply(req, "Bad remove option", 1, 0);
return;
}
- err = (*dev->remove)(&ptr[strlen(dev->name)]);
- mconsole_reply(req, "", err, 0);
+
+ ptr = &ptr[strlen(dev->name)];
+
+ err = 1;
+ n = (*dev->id)(&ptr, &start, &end);
+ if(n < 0){
+ err_msg = "Couldn't parse device number";
+ goto out;
+ }
+ else if((n < start) || (n > end)){
+ sprintf(error, "Invalid device number - must be between "
+ "%d and %d", start, end);
+ err_msg = error;
+ goto out;
+ }
+
+ err = (*dev->remove)(n);
+ switch(err){
+ case -ENODEV:
+ err_msg = "Device doesn't exist";
+ break;
+ case -EBUSY:
+ err_msg = "Device is currently open";
+ break;
+ default:
+ break;
+ }
+ out:
+ mconsole_reply(req, err_msg, err, 0);
}
#ifdef CONFIG_MAGIC_SYSRQ
diff --git a/arch/um/drivers/net_kern.c b/arch/um/drivers/net_kern.c
index 5388a742869..1495007bf6c 100644
--- a/arch/um/drivers/net_kern.c
+++ b/arch/um/drivers/net_kern.c
@@ -612,25 +612,35 @@ static int net_config(char *str)
return(err);
}
-static int net_remove(char *str)
+static int net_id(char **str, int *start_out, int *end_out)
+{
+ char *end;
+ int n;
+
+ n = simple_strtoul(*str, &end, 0);
+ if((*end != '\0') || (end == *str))
+ return -1;
+
+ *start_out = n;
+ *end_out = n;
+ *str = end;
+ return n;
+}
+
+static int net_remove(int n)
{
struct uml_net *device;
struct net_device *dev;
struct uml_net_private *lp;
- char *end;
- int n;
-
- n = simple_strtoul(str, &end, 0);
- if((*end != '\0') || (end == str))
- return(-1);
device = find_device(n);
if(device == NULL)
- return(0);
+ return -ENODEV;
dev = device->dev;
lp = dev->priv;
- if(lp->fd > 0) return(-1);
+ if(lp->fd > 0)
+ return -EBUSY;
if(lp->remove != NULL) (*lp->remove)(&lp->user);
unregister_netdev(dev);
platform_device_unregister(&device->pdev);
@@ -638,13 +648,14 @@ static int net_remove(char *str)
list_del(&device->list);
kfree(device);
free_netdev(dev);
- return(0);
+ return 0;
}
static struct mc_device net_mc = {
.name = "eth",
.config = net_config,
.get_config = NULL,
+ .id = net_id,
.remove = net_remove,
};
diff --git a/arch/um/drivers/ssl.c b/arch/um/drivers/ssl.c
index b32a77010fb..62e04ecfada 100644
--- a/arch/um/drivers/ssl.c
+++ b/arch/um/drivers/ssl.c
@@ -49,7 +49,7 @@ static struct chan_opts opts = {
static int ssl_config(char *str);
static int ssl_get_config(char *dev, char *str, int size, char **error_out);
-static int ssl_remove(char *str);
+static int ssl_remove(int n);
static struct line_driver driver = {
.name = "UML serial line",
@@ -69,6 +69,7 @@ static struct line_driver driver = {
.name = "ssl",
.config = ssl_config,
.get_config = ssl_get_config,
+ .id = line_id,
.remove = ssl_remove,
},
};
@@ -94,10 +95,10 @@ static int ssl_get_config(char *dev, char *str, int size, char **error_out)
str, size, error_out));
}
-static int ssl_remove(char *str)
+static int ssl_remove(int n)
{
- return(line_remove(serial_lines,
- sizeof(serial_lines)/sizeof(serial_lines[0]), str));
+ return line_remove(serial_lines,
+ sizeof(serial_lines)/sizeof(serial_lines[0]), n);
}
int ssl_open(struct tty_struct *tty, struct file *filp)
diff --git a/arch/um/drivers/stdio_console.c b/arch/um/drivers/stdio_console.c
index afbe1e71ed8..005aa6333b6 100644
--- a/arch/um/drivers/stdio_console.c
+++ b/arch/um/drivers/stdio_console.c
@@ -55,7 +55,7 @@ static struct chan_opts opts = {
static int con_config(char *str);
static int con_get_config(char *dev, char *str, int size, char **error_out);
-static int con_remove(char *str);
+static int con_remove(int n);
static struct line_driver driver = {
.name = "UML console",
@@ -75,6 +75,7 @@ static struct line_driver driver = {
.name = "con",
.config = con_config,
.get_config = con_get_config,
+ .id = line_id,
.remove = con_remove,
},
};
@@ -99,9 +100,9 @@ static int con_get_config(char *dev, char *str, int size, char **error_out)
size, error_out));
}
-static int con_remove(char *str)
+static int con_remove(int n)
{
- return(line_remove(vts, sizeof(vts)/sizeof(vts[0]), str));
+ return line_remove(vts, sizeof(vts)/sizeof(vts[0]), n);
}
static int con_open(struct tty_struct *tty, struct file *filp)
diff --git a/arch/um/drivers/ubd_kern.c b/arch/um/drivers/ubd_kern.c
index 2a7f6892c55..344b24d09a7 100644
--- a/arch/um/drivers/ubd_kern.c
+++ b/arch/um/drivers/ubd_kern.c
@@ -754,24 +754,34 @@ static int ubd_get_config(char *name, char *str, int size, char **error_out)
return(len);
}
-static int ubd_remove(char *str)
+static int ubd_id(char **str, int *start_out, int *end_out)
+{
+ int n;
+
+ n = parse_unit(str);
+ *start_out = 0;
+ *end_out = MAX_DEV - 1;
+ return n;
+}
+
+static int ubd_remove(int n)
{
struct ubd *dev;
- int n, err = -ENODEV;
+ int err = -ENODEV;
- n = parse_unit(&str);
+ spin_lock(&ubd_lock);
- if((n < 0) || (n >= MAX_DEV))
- return(err);
+ if(ubd_gendisk[n] == NULL)
+ goto out;
dev = &ubd_dev[n];
- if(dev->count > 0)
- return(-EBUSY); /* you cannot remove a open disk */
- err = 0;
- spin_lock(&ubd_lock);
+ if(dev->file == NULL)
+ goto out;
- if(ubd_gendisk[n] == NULL)
+ /* you cannot remove a open disk */
+ err = -EBUSY;
+ if(dev->count > 0)
goto out;
del_gendisk(ubd_gendisk[n]);
@@ -787,15 +797,16 @@ static int ubd_remove(char *str)
platform_device_unregister(&dev->pdev);
*dev = ((struct ubd) DEFAULT_UBD);
err = 0;
- out:
- spin_unlock(&ubd_lock);
- return(err);
+out:
+ spin_unlock(&ubd_lock);
+ return err;
}
static struct mc_device ubd_mc = {
.name = "ubd",
.config = ubd_config,
.get_config = ubd_get_config,
+ .id = ubd_id,
.remove = ubd_remove,
};
diff --git a/arch/um/include/line.h b/arch/um/include/line.h
index 4c5e92c04cc..5323d22a6ca 100644
--- a/arch/um/include/line.h
+++ b/arch/um/include/line.h
@@ -101,7 +101,8 @@ extern void lines_init(struct line *lines, int nlines);
extern void close_lines(struct line *lines, int nlines);
extern int line_config(struct line *lines, unsigned int sizeof_lines, char *str);
-extern int line_remove(struct line *lines, unsigned int sizeof_lines, char *str);
+extern int line_id(char **str, int *start_out, int *end_out);
+extern int line_remove(struct line *lines, unsigned int sizeof_lines, int n);
extern int line_get_config(char *dev, struct line *lines, unsigned int sizeof_lines, char *str,
int size, char **error_out);
diff --git a/arch/um/include/mconsole_kern.h b/arch/um/include/mconsole_kern.h
index 61c274fcee5..d86ee14260c 100644
--- a/arch/um/include/mconsole_kern.h
+++ b/arch/um/include/mconsole_kern.h
@@ -20,7 +20,8 @@ struct mc_device {
char *name;
int (*config)(char *);
int (*get_config)(char *, char *, int, char **);
- int (*remove)(char *);
+ int (*id)(char **, int *, int *);
+ int (*remove)(int);
};
#define CONFIG_CHUNK(str, size, current, chunk, end) \
diff --git a/arch/um/kernel/tt/gdb.c b/arch/um/kernel/tt/gdb.c
index 19a0ad7b35b..37e22d71a0d 100644
--- a/arch/um/kernel/tt/gdb.c
+++ b/arch/um/kernel/tt/gdb.c
@@ -153,10 +153,10 @@ void remove_gdb_cb(void *unused)
exit_debugger_cb(NULL);
}
-int gdb_remove(char *unused)
+int gdb_remove(int unused)
{
initial_thread_cb(remove_gdb_cb, NULL);
- return(0);
+ return 0;
}
void signal_usr1(int sig)
diff --git a/arch/um/kernel/tt/gdb_kern.c b/arch/um/kernel/tt/gdb_kern.c
index 93fb121f86a..26506388a6a 100644
--- a/arch/um/kernel/tt/gdb_kern.c
+++ b/arch/um/kernel/tt/gdb_kern.c
@@ -10,7 +10,7 @@
#ifdef CONFIG_MCONSOLE
extern int gdb_config(char *str);
-extern int gdb_remove(char *unused);
+extern int gdb_remove(int n);
static struct mc_device gdb_mc = {
.name = "gdb",
diff --git a/arch/um/kernel/tt/include/debug.h b/arch/um/kernel/tt/include/debug.h
index 8eff674107c..738435461e1 100644
--- a/arch/um/kernel/tt/include/debug.h
+++ b/arch/um/kernel/tt/include/debug.h
@@ -4,8 +4,8 @@
* Licensed under the GPL
*/
-#ifndef __DEBUG_H
-#define __DEBUG_H
+#ifndef __UML_TT_DEBUG_H
+#define __UML_TT_DEBUG_H
extern int debugger_proxy(int status, pid_t pid);
extern void child_proxy(pid_t pid, int status);
@@ -13,17 +13,6 @@ extern void init_proxy (pid_t pid, int waiting, int status);
extern int start_debugger(char *prog, int startup, int stop, int *debugger_fd);
extern void fake_child_exit(void);
extern int gdb_config(char *str);
-extern int gdb_remove(char *unused);
+extern int gdb_remove(int unused);
#endif
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only. This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */