Commit 29d56cfe authored by Jeff Dike's avatar Jeff Dike Committed by Linus Torvalds

[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: default avatarJeff Dike <jdike@addtoit.com>
Cc: Paolo Giarrusso <blaisorblade@yahoo.it>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent fc47a0d1
...@@ -602,11 +602,26 @@ int line_get_config(char *name, struct line *lines, unsigned int num, char *str, ...@@ -602,11 +602,26 @@ int line_get_config(char *name, struct line *lines, unsigned int num, char *str,
return n; 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")]; char config[sizeof("conxxxx=none\0")];
sprintf(config, "%s=none", str); sprintf(config, "%d=none", n);
return !line_setup(lines, num, config, 0); return !line_setup(lines, num, config, 0);
} }
......
...@@ -419,8 +419,9 @@ void mconsole_config(struct mc_request *req) ...@@ -419,8 +419,9 @@ void mconsole_config(struct mc_request *req)
void mconsole_remove(struct mc_request *req) void mconsole_remove(struct mc_request *req)
{ {
struct mc_device *dev; struct mc_device *dev;
char *ptr = req->request.data; char *ptr = req->request.data, *err_msg = "";
int err; char error[256];
int err, start, end, n;
ptr += strlen("remove"); ptr += strlen("remove");
while(isspace(*ptr)) ptr++; while(isspace(*ptr)) ptr++;
...@@ -429,8 +430,35 @@ void mconsole_remove(struct mc_request *req) ...@@ -429,8 +430,35 @@ void mconsole_remove(struct mc_request *req)
mconsole_reply(req, "Bad remove option", 1, 0); mconsole_reply(req, "Bad remove option", 1, 0);
return; 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 #ifdef CONFIG_MAGIC_SYSRQ
......
...@@ -612,25 +612,35 @@ static int net_config(char *str) ...@@ -612,25 +612,35 @@ static int net_config(char *str)
return(err); return(err);
} }
static int net_remove(char *str) static int net_id(char **str, int *start_out, int *end_out)
{ {
struct uml_net *device;
struct net_device *dev;
struct uml_net_private *lp;
char *end; char *end;
int n; int n;
n = simple_strtoul(str, &end, 0); n = simple_strtoul(*str, &end, 0);
if((*end != '\0') || (end == str)) if((*end != '\0') || (end == *str))
return(-1); 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;
device = find_device(n); device = find_device(n);
if(device == NULL) if(device == NULL)
return(0); return -ENODEV;
dev = device->dev; dev = device->dev;
lp = dev->priv; lp = dev->priv;
if(lp->fd > 0) return(-1); if(lp->fd > 0)
return -EBUSY;
if(lp->remove != NULL) (*lp->remove)(&lp->user); if(lp->remove != NULL) (*lp->remove)(&lp->user);
unregister_netdev(dev); unregister_netdev(dev);
platform_device_unregister(&device->pdev); platform_device_unregister(&device->pdev);
...@@ -638,13 +648,14 @@ static int net_remove(char *str) ...@@ -638,13 +648,14 @@ static int net_remove(char *str)
list_del(&device->list); list_del(&device->list);
kfree(device); kfree(device);
free_netdev(dev); free_netdev(dev);
return(0); return 0;
} }
static struct mc_device net_mc = { static struct mc_device net_mc = {
.name = "eth", .name = "eth",
.config = net_config, .config = net_config,
.get_config = NULL, .get_config = NULL,
.id = net_id,
.remove = net_remove, .remove = net_remove,
}; };
......
...@@ -49,7 +49,7 @@ static struct chan_opts opts = { ...@@ -49,7 +49,7 @@ static struct chan_opts opts = {
static int ssl_config(char *str); static int ssl_config(char *str);
static int ssl_get_config(char *dev, char *str, int size, char **error_out); 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 = { static struct line_driver driver = {
.name = "UML serial line", .name = "UML serial line",
...@@ -69,6 +69,7 @@ static struct line_driver driver = { ...@@ -69,6 +69,7 @@ static struct line_driver driver = {
.name = "ssl", .name = "ssl",
.config = ssl_config, .config = ssl_config,
.get_config = ssl_get_config, .get_config = ssl_get_config,
.id = line_id,
.remove = ssl_remove, .remove = ssl_remove,
}, },
}; };
...@@ -94,10 +95,10 @@ static int ssl_get_config(char *dev, char *str, int size, char **error_out) ...@@ -94,10 +95,10 @@ static int ssl_get_config(char *dev, char *str, int size, char **error_out)
str, size, error_out)); str, size, error_out));
} }
static int ssl_remove(char *str) static int ssl_remove(int n)
{ {
return(line_remove(serial_lines, return line_remove(serial_lines,
sizeof(serial_lines)/sizeof(serial_lines[0]), str)); sizeof(serial_lines)/sizeof(serial_lines[0]), n);
} }
int ssl_open(struct tty_struct *tty, struct file *filp) int ssl_open(struct tty_struct *tty, struct file *filp)
......
...@@ -55,7 +55,7 @@ static struct chan_opts opts = { ...@@ -55,7 +55,7 @@ static struct chan_opts opts = {
static int con_config(char *str); static int con_config(char *str);
static int con_get_config(char *dev, char *str, int size, char **error_out); 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 = { static struct line_driver driver = {
.name = "UML console", .name = "UML console",
...@@ -75,6 +75,7 @@ static struct line_driver driver = { ...@@ -75,6 +75,7 @@ static struct line_driver driver = {
.name = "con", .name = "con",
.config = con_config, .config = con_config,
.get_config = con_get_config, .get_config = con_get_config,
.id = line_id,
.remove = con_remove, .remove = con_remove,
}, },
}; };
...@@ -99,9 +100,9 @@ static int con_get_config(char *dev, char *str, int size, char **error_out) ...@@ -99,9 +100,9 @@ static int con_get_config(char *dev, char *str, int size, char **error_out)
size, 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) static int con_open(struct tty_struct *tty, struct file *filp)
......
...@@ -754,24 +754,34 @@ static int ubd_get_config(char *name, char *str, int size, char **error_out) ...@@ -754,24 +754,34 @@ static int ubd_get_config(char *name, char *str, int size, char **error_out)
return(len); 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; struct ubd *dev;
int n, err = -ENODEV; int err = -ENODEV;
n = parse_unit(&str); spin_lock(&ubd_lock);
if((n < 0) || (n >= MAX_DEV)) if(ubd_gendisk[n] == NULL)
return(err); goto out;
dev = &ubd_dev[n]; dev = &ubd_dev[n];
if(dev->count > 0)
return(-EBUSY); /* you cannot remove a open disk */
err = 0; if(dev->file == NULL)
spin_lock(&ubd_lock); goto out;
if(ubd_gendisk[n] == NULL) /* you cannot remove a open disk */
err = -EBUSY;
if(dev->count > 0)
goto out; goto out;
del_gendisk(ubd_gendisk[n]); del_gendisk(ubd_gendisk[n]);
...@@ -787,15 +797,16 @@ static int ubd_remove(char *str) ...@@ -787,15 +797,16 @@ static int ubd_remove(char *str)
platform_device_unregister(&dev->pdev); platform_device_unregister(&dev->pdev);
*dev = ((struct ubd) DEFAULT_UBD); *dev = ((struct ubd) DEFAULT_UBD);
err = 0; err = 0;
out: out:
spin_unlock(&ubd_lock); spin_unlock(&ubd_lock);
return(err); return err;
} }
static struct mc_device ubd_mc = { static struct mc_device ubd_mc = {
.name = "ubd", .name = "ubd",
.config = ubd_config, .config = ubd_config,
.get_config = ubd_get_config, .get_config = ubd_get_config,
.id = ubd_id,
.remove = ubd_remove, .remove = ubd_remove,
}; };
......
...@@ -101,7 +101,8 @@ extern void lines_init(struct line *lines, int nlines); ...@@ -101,7 +101,8 @@ extern void lines_init(struct line *lines, int nlines);
extern void close_lines(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_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, extern int line_get_config(char *dev, struct line *lines, unsigned int sizeof_lines, char *str,
int size, char **error_out); int size, char **error_out);
......
...@@ -20,7 +20,8 @@ struct mc_device { ...@@ -20,7 +20,8 @@ struct mc_device {
char *name; char *name;
int (*config)(char *); int (*config)(char *);
int (*get_config)(char *, char *, int, 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) \ #define CONFIG_CHUNK(str, size, current, chunk, end) \
......
...@@ -153,10 +153,10 @@ void remove_gdb_cb(void *unused) ...@@ -153,10 +153,10 @@ void remove_gdb_cb(void *unused)
exit_debugger_cb(NULL); exit_debugger_cb(NULL);
} }
int gdb_remove(char *unused) int gdb_remove(int unused)
{ {
initial_thread_cb(remove_gdb_cb, NULL); initial_thread_cb(remove_gdb_cb, NULL);
return(0); return 0;
} }
void signal_usr1(int sig) void signal_usr1(int sig)
......
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
#ifdef CONFIG_MCONSOLE #ifdef CONFIG_MCONSOLE
extern int gdb_config(char *str); extern int gdb_config(char *str);
extern int gdb_remove(char *unused); extern int gdb_remove(int n);
static struct mc_device gdb_mc = { static struct mc_device gdb_mc = {
.name = "gdb", .name = "gdb",
......
...@@ -4,8 +4,8 @@ ...@@ -4,8 +4,8 @@
* Licensed under the GPL * Licensed under the GPL
*/ */
#ifndef __DEBUG_H #ifndef __UML_TT_DEBUG_H
#define __DEBUG_H #define __UML_TT_DEBUG_H
extern int debugger_proxy(int status, pid_t pid); extern int debugger_proxy(int status, pid_t pid);
extern void child_proxy(pid_t pid, int status); extern void child_proxy(pid_t pid, int status);
...@@ -13,17 +13,6 @@ extern void init_proxy (pid_t pid, int waiting, 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 int start_debugger(char *prog, int startup, int stop, int *debugger_fd);
extern void fake_child_exit(void); extern void fake_child_exit(void);
extern int gdb_config(char *str); extern int gdb_config(char *str);
extern int gdb_remove(char *unused); extern int gdb_remove(int unused);
#endif #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:
*/
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment