[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>
This commit is contained in:
parent
fc47a0d18a
commit
29d56cfe3c
@ -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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
return(err);
|
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 uml_net *device;
|
||||||
struct net_device *dev;
|
struct net_device *dev;
|
||||||
struct uml_net_private *lp;
|
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);
|
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)
|
|||||||
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 = {
|
|||||||
|
|
||||||
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 = {
|
|||||||
.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)
|
|||||||
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 = {
|
|||||||
|
|
||||||
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 = {
|
|||||||
.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)
|
|||||||
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,26 +754,36 @@ 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))
|
|
||||||
return(err);
|
|
||||||
|
|
||||||
dev = &ubd_dev[n];
|
|
||||||
if(dev->count > 0)
|
|
||||||
return(-EBUSY); /* you cannot remove a open disk */
|
|
||||||
|
|
||||||
err = 0;
|
|
||||||
spin_lock(&ubd_lock);
|
|
||||||
|
|
||||||
if(ubd_gendisk[n] == NULL)
|
if(ubd_gendisk[n] == NULL)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
|
dev = &ubd_dev[n];
|
||||||
|
|
||||||
|
if(dev->file == NULL)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
/* you cannot remove a open disk */
|
||||||
|
err = -EBUSY;
|
||||||
|
if(dev->count > 0)
|
||||||
|
goto out;
|
||||||
|
|
||||||
del_gendisk(ubd_gendisk[n]);
|
del_gendisk(ubd_gendisk[n]);
|
||||||
put_disk(ubd_gendisk[n]);
|
put_disk(ubd_gendisk[n]);
|
||||||
ubd_gendisk[n] = NULL;
|
ubd_gendisk[n] = NULL;
|
||||||
@ -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);
|
|||||||
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 {
|
|||||||
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)
|
|||||||
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 @@
|
|||||||
#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 @@
|
|||||||
* 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);
|
|||||||
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:
|
|
||||||
*/
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user