diff options
Diffstat (limited to 'arch/um')
-rw-r--r-- | arch/um/Makefile | 21 | ||||
-rw-r--r-- | arch/um/Makefile-i386 | 4 | ||||
-rw-r--r-- | arch/um/Makefile-x86_64 | 4 | ||||
-rw-r--r-- | arch/um/drivers/mconsole_kern.c | 23 | ||||
-rw-r--r-- | arch/um/drivers/mconsole_user.c | 1 | ||||
-rw-r--r-- | arch/um/drivers/ubd_kern.c | 319 | ||||
-rw-r--r-- | arch/um/include/mconsole.h | 1 | ||||
-rw-r--r-- | arch/um/include/mconsole_kern.h | 1 | ||||
-rw-r--r-- | arch/um/include/os.h | 2 | ||||
-rw-r--r-- | arch/um/include/sysdep-i386/barrier.h | 9 | ||||
-rw-r--r-- | arch/um/include/sysdep-x86_64/barrier.h | 7 | ||||
-rw-r--r-- | arch/um/kernel/dyn.lds.S | 1 | ||||
-rw-r--r-- | arch/um/kernel/tt/tracer.c | 1 | ||||
-rw-r--r-- | arch/um/kernel/uml.lds.S | 1 | ||||
-rw-r--r-- | arch/um/os-Linux/Makefile | 10 | ||||
-rw-r--r-- | arch/um/os-Linux/execvp.c | 149 | ||||
-rw-r--r-- | arch/um/os-Linux/helper.c | 14 | ||||
-rw-r--r-- | arch/um/os-Linux/process.c | 1 | ||||
-rw-r--r-- | arch/um/os-Linux/signal.c | 31 | ||||
-rw-r--r-- | arch/um/os-Linux/skas/process.c | 2 | ||||
-rw-r--r-- | arch/um/os-Linux/sys-i386/tls.c | 3 | ||||
-rw-r--r-- | arch/um/os-Linux/tls.c | 1 | ||||
-rw-r--r-- | arch/um/sys-i386/unmap.c | 11 | ||||
-rw-r--r-- | arch/um/sys-x86_64/unmap.c | 11 |
24 files changed, 440 insertions, 188 deletions
diff --git a/arch/um/Makefile b/arch/um/Makefile index c8016a98483b..5d5ed726faa0 100644 --- a/arch/um/Makefile +++ b/arch/um/Makefile | |||
@@ -64,9 +64,14 @@ CFLAGS += $(CFLAGS-y) -D__arch_um__ -DSUBARCH=\"$(SUBARCH)\" \ | |||
64 | 64 | ||
65 | AFLAGS += $(ARCH_INCLUDE) | 65 | AFLAGS += $(ARCH_INCLUDE) |
66 | 66 | ||
67 | USER_CFLAGS := $(patsubst -I%,,$(CFLAGS)) | 67 | USER_CFLAGS = $(patsubst $(KERNEL_DEFINES),,$(patsubst -D__KERNEL__,,\ |
68 | USER_CFLAGS := $(patsubst -D__KERNEL__,,$(USER_CFLAGS)) $(ARCH_INCLUDE) \ | 68 | $(patsubst -I%,,$(CFLAGS)))) $(ARCH_INCLUDE) $(MODE_INCLUDE) \ |
69 | $(MODE_INCLUDE) -D_FILE_OFFSET_BITS=64 | 69 | -D_FILE_OFFSET_BITS=64 |
70 | |||
71 | include $(srctree)/$(ARCH_DIR)/Makefile-$(SUBARCH) | ||
72 | |||
73 | #This will adjust *FLAGS accordingly to the platform. | ||
74 | include $(srctree)/$(ARCH_DIR)/Makefile-os-$(OS) | ||
70 | 75 | ||
71 | # -Derrno=kernel_errno - This turns all kernel references to errno into | 76 | # -Derrno=kernel_errno - This turns all kernel references to errno into |
72 | # kernel_errno to separate them from the libc errno. This allows -fno-common | 77 | # kernel_errno to separate them from the libc errno. This allows -fno-common |
@@ -74,15 +79,11 @@ USER_CFLAGS := $(patsubst -D__KERNEL__,,$(USER_CFLAGS)) $(ARCH_INCLUDE) \ | |||
74 | # errnos. | 79 | # errnos. |
75 | # These apply to kernelspace only. | 80 | # These apply to kernelspace only. |
76 | 81 | ||
77 | CFLAGS += -Derrno=kernel_errno -Dsigprocmask=kernel_sigprocmask \ | 82 | KERNEL_DEFINES = -Derrno=kernel_errno -Dsigprocmask=kernel_sigprocmask \ |
78 | -Dmktime=kernel_mktime | 83 | -Dmktime=kernel_mktime $(ARCH_KERNEL_DEFINES) |
84 | CFLAGS += $(KERNEL_DEFINES) | ||
79 | CFLAGS += $(call cc-option,-fno-unit-at-a-time,) | 85 | CFLAGS += $(call cc-option,-fno-unit-at-a-time,) |
80 | 86 | ||
81 | include $(srctree)/$(ARCH_DIR)/Makefile-$(SUBARCH) | ||
82 | |||
83 | #This will adjust *FLAGS accordingly to the platform. | ||
84 | include $(srctree)/$(ARCH_DIR)/Makefile-os-$(OS) | ||
85 | |||
86 | # These are needed for clean and mrproper, since in that case .config is not | 87 | # These are needed for clean and mrproper, since in that case .config is not |
87 | # included; the values here are meaningless | 88 | # included; the values here are meaningless |
88 | 89 | ||
diff --git a/arch/um/Makefile-i386 b/arch/um/Makefile-i386 index b65ca115ef77..c9f1c5b24c9a 100644 --- a/arch/um/Makefile-i386 +++ b/arch/um/Makefile-i386 | |||
@@ -16,7 +16,6 @@ OBJCOPYFLAGS := -O binary -R .note -R .comment -S | |||
16 | ifeq ("$(origin SUBARCH)", "command line") | 16 | ifeq ("$(origin SUBARCH)", "command line") |
17 | ifneq ("$(shell uname -m | sed -e s/i.86/i386/)", "$(SUBARCH)") | 17 | ifneq ("$(shell uname -m | sed -e s/i.86/i386/)", "$(SUBARCH)") |
18 | CFLAGS += $(call cc-option,-m32) | 18 | CFLAGS += $(call cc-option,-m32) |
19 | USER_CFLAGS += $(call cc-option,-m32) | ||
20 | AFLAGS += $(call cc-option,-m32) | 19 | AFLAGS += $(call cc-option,-m32) |
21 | LINK-y += $(call cc-option,-m32) | 20 | LINK-y += $(call cc-option,-m32) |
22 | UML_OBJCOPYFLAGS += -F $(ELF_FORMAT) | 21 | UML_OBJCOPYFLAGS += -F $(ELF_FORMAT) |
@@ -25,7 +24,7 @@ export LDFLAGS HOSTCFLAGS HOSTLDFLAGS UML_OBJCOPYFLAGS | |||
25 | endif | 24 | endif |
26 | endif | 25 | endif |
27 | 26 | ||
28 | CFLAGS += -U__$(SUBARCH)__ -U$(SUBARCH) | 27 | ARCH_KERNEL_DEFINES += -U__$(SUBARCH)__ -U$(SUBARCH) |
29 | 28 | ||
30 | # First of all, tune CFLAGS for the specific CPU. This actually sets cflags-y. | 29 | # First of all, tune CFLAGS for the specific CPU. This actually sets cflags-y. |
31 | include $(srctree)/arch/i386/Makefile.cpu | 30 | include $(srctree)/arch/i386/Makefile.cpu |
@@ -38,4 +37,3 @@ cflags-y += $(call cc-option,-mpreferred-stack-boundary=2) | |||
38 | cflags-y += -ffreestanding | 37 | cflags-y += -ffreestanding |
39 | 38 | ||
40 | CFLAGS += $(cflags-y) | 39 | CFLAGS += $(cflags-y) |
41 | USER_CFLAGS += $(cflags-y) | ||
diff --git a/arch/um/Makefile-x86_64 b/arch/um/Makefile-x86_64 index d278682dd799..69ecea63fdae 100644 --- a/arch/um/Makefile-x86_64 +++ b/arch/um/Makefile-x86_64 | |||
@@ -8,8 +8,8 @@ _extra_flags_ = -fno-builtin -m64 | |||
8 | 8 | ||
9 | #We #undef __x86_64__ for kernelspace, not for userspace where | 9 | #We #undef __x86_64__ for kernelspace, not for userspace where |
10 | #it's needed for headers to work! | 10 | #it's needed for headers to work! |
11 | CFLAGS += -U__$(SUBARCH)__ $(_extra_flags_) | 11 | ARCH_KERNEL_DEFINES = -U__$(SUBARCH)__ |
12 | USER_CFLAGS += $(_extra_flags_) | 12 | CFLAGS += $(_extra_flags_) |
13 | 13 | ||
14 | CHECKFLAGS += -m64 | 14 | CHECKFLAGS += -m64 |
15 | AFLAGS += -m64 | 15 | AFLAGS += -m64 |
diff --git a/arch/um/drivers/mconsole_kern.c b/arch/um/drivers/mconsole_kern.c index d08bd036ccb8..7b172160fe04 100644 --- a/arch/um/drivers/mconsole_kern.c +++ b/arch/um/drivers/mconsole_kern.c | |||
@@ -79,7 +79,7 @@ static irqreturn_t mconsole_interrupt(int irq, void *dev_id) | |||
79 | /* long to avoid size mismatch warnings from gcc */ | 79 | /* long to avoid size mismatch warnings from gcc */ |
80 | long fd; | 80 | long fd; |
81 | struct mconsole_entry *new; | 81 | struct mconsole_entry *new; |
82 | struct mc_request req; | 82 | static struct mc_request req; /* that's OK */ |
83 | 83 | ||
84 | fd = (long) dev_id; | 84 | fd = (long) dev_id; |
85 | while (mconsole_get_request(fd, &req)){ | 85 | while (mconsole_get_request(fd, &req)){ |
@@ -91,6 +91,7 @@ static irqreturn_t mconsole_interrupt(int irq, void *dev_id) | |||
91 | mconsole_reply(&req, "Out of memory", 1, 0); | 91 | mconsole_reply(&req, "Out of memory", 1, 0); |
92 | else { | 92 | else { |
93 | new->request = req; | 93 | new->request = req; |
94 | new->request.regs = get_irq_regs()->regs; | ||
94 | list_add(&new->list, &mc_requests); | 95 | list_add(&new->list, &mc_requests); |
95 | } | 96 | } |
96 | } | 97 | } |
@@ -314,9 +315,21 @@ void mconsole_stop(struct mc_request *req) | |||
314 | { | 315 | { |
315 | deactivate_fd(req->originating_fd, MCONSOLE_IRQ); | 316 | deactivate_fd(req->originating_fd, MCONSOLE_IRQ); |
316 | os_set_fd_block(req->originating_fd, 1); | 317 | os_set_fd_block(req->originating_fd, 1); |
317 | mconsole_reply(req, "", 0, 0); | 318 | mconsole_reply(req, "stopped", 0, 0); |
318 | while(mconsole_get_request(req->originating_fd, req)){ | 319 | while (mconsole_get_request(req->originating_fd, req)) { |
319 | if(req->cmd->handler == mconsole_go) break; | 320 | if (req->cmd->handler == mconsole_go) |
321 | break; | ||
322 | if (req->cmd->handler == mconsole_stop) { | ||
323 | mconsole_reply(req, "Already stopped", 1, 0); | ||
324 | continue; | ||
325 | } | ||
326 | if (req->cmd->handler == mconsole_sysrq) { | ||
327 | struct pt_regs *old_regs; | ||
328 | old_regs = set_irq_regs((struct pt_regs *)&req->regs); | ||
329 | mconsole_sysrq(req); | ||
330 | set_irq_regs(old_regs); | ||
331 | continue; | ||
332 | } | ||
320 | (*req->cmd->handler)(req); | 333 | (*req->cmd->handler)(req); |
321 | } | 334 | } |
322 | os_set_fd_block(req->originating_fd, 0); | 335 | os_set_fd_block(req->originating_fd, 0); |
@@ -673,9 +686,7 @@ static void with_console(struct mc_request *req, void (*proc)(void *), | |||
673 | static void sysrq_proc(void *arg) | 686 | static void sysrq_proc(void *arg) |
674 | { | 687 | { |
675 | char *op = arg; | 688 | char *op = arg; |
676 | struct pt_regs *old_regs = set_irq_regs(¤t->thread.regs); | ||
677 | handle_sysrq(*op, NULL); | 689 | handle_sysrq(*op, NULL); |
678 | set_irq_regs(old_regs); | ||
679 | } | 690 | } |
680 | 691 | ||
681 | void mconsole_sysrq(struct mc_request *req) | 692 | void mconsole_sysrq(struct mc_request *req) |
diff --git a/arch/um/drivers/mconsole_user.c b/arch/um/drivers/mconsole_user.c index 17068eb746c0..75aef6f7ef6e 100644 --- a/arch/um/drivers/mconsole_user.c +++ b/arch/um/drivers/mconsole_user.c | |||
@@ -14,6 +14,7 @@ | |||
14 | #include <sys/un.h> | 14 | #include <sys/un.h> |
15 | #include <unistd.h> | 15 | #include <unistd.h> |
16 | #include "user.h" | 16 | #include "user.h" |
17 | #include "sysdep/ptrace.h" | ||
17 | #include "mconsole.h" | 18 | #include "mconsole.h" |
18 | #include "umid.h" | 19 | #include "umid.h" |
19 | #include "user_util.h" | 20 | #include "user_util.h" |
diff --git a/arch/um/drivers/ubd_kern.c b/arch/um/drivers/ubd_kern.c index bc458f57921b..49c047b75cc5 100644 --- a/arch/um/drivers/ubd_kern.c +++ b/arch/um/drivers/ubd_kern.c | |||
@@ -106,10 +106,15 @@ static inline void ubd_set_bit(__u64 bit, unsigned char *data) | |||
106 | 106 | ||
107 | #define DRIVER_NAME "uml-blkdev" | 107 | #define DRIVER_NAME "uml-blkdev" |
108 | 108 | ||
109 | /* Can be taken in interrupt context, and is passed to the block layer to lock | ||
110 | * the request queue. Kernel side code knows that. */ | ||
109 | static DEFINE_SPINLOCK(ubd_io_lock); | 111 | static DEFINE_SPINLOCK(ubd_io_lock); |
110 | static DEFINE_SPINLOCK(ubd_lock); | ||
111 | 112 | ||
112 | static void (*do_ubd)(void); | 113 | static DEFINE_MUTEX(ubd_lock); |
114 | |||
115 | /* XXX - this made sense in 2.4 days, now it's only used as a boolean, and | ||
116 | * probably it doesn't make sense even for that. */ | ||
117 | static int do_ubd; | ||
113 | 118 | ||
114 | static int ubd_open(struct inode * inode, struct file * filp); | 119 | static int ubd_open(struct inode * inode, struct file * filp); |
115 | static int ubd_release(struct inode * inode, struct file * file); | 120 | static int ubd_release(struct inode * inode, struct file * file); |
@@ -117,7 +122,7 @@ static int ubd_ioctl(struct inode * inode, struct file * file, | |||
117 | unsigned int cmd, unsigned long arg); | 122 | unsigned int cmd, unsigned long arg); |
118 | static int ubd_getgeo(struct block_device *bdev, struct hd_geometry *geo); | 123 | static int ubd_getgeo(struct block_device *bdev, struct hd_geometry *geo); |
119 | 124 | ||
120 | #define MAX_DEV (8) | 125 | #define MAX_DEV (16) |
121 | 126 | ||
122 | static struct block_device_operations ubd_blops = { | 127 | static struct block_device_operations ubd_blops = { |
123 | .owner = THIS_MODULE, | 128 | .owner = THIS_MODULE, |
@@ -150,8 +155,9 @@ static struct gendisk *fake_gendisk[MAX_DEV]; | |||
150 | static struct openflags global_openflags = OPEN_FLAGS; | 155 | static struct openflags global_openflags = OPEN_FLAGS; |
151 | 156 | ||
152 | struct cow { | 157 | struct cow { |
153 | /* This is the backing file, actually */ | 158 | /* backing file name */ |
154 | char *file; | 159 | char *file; |
160 | /* backing file fd */ | ||
155 | int fd; | 161 | int fd; |
156 | unsigned long *bitmap; | 162 | unsigned long *bitmap; |
157 | unsigned long bitmap_len; | 163 | unsigned long bitmap_len; |
@@ -160,14 +166,16 @@ struct cow { | |||
160 | }; | 166 | }; |
161 | 167 | ||
162 | struct ubd { | 168 | struct ubd { |
169 | /* name (and fd, below) of the file opened for writing, either the | ||
170 | * backing or the cow file. */ | ||
163 | char *file; | 171 | char *file; |
164 | int count; | 172 | int count; |
165 | int fd; | 173 | int fd; |
166 | __u64 size; | 174 | __u64 size; |
167 | struct openflags boot_openflags; | 175 | struct openflags boot_openflags; |
168 | struct openflags openflags; | 176 | struct openflags openflags; |
169 | int shared; | 177 | unsigned shared:1; |
170 | int no_cow; | 178 | unsigned no_cow:1; |
171 | struct cow cow; | 179 | struct cow cow; |
172 | struct platform_device pdev; | 180 | struct platform_device pdev; |
173 | }; | 181 | }; |
@@ -192,18 +200,7 @@ struct ubd { | |||
192 | .cow = DEFAULT_COW, \ | 200 | .cow = DEFAULT_COW, \ |
193 | } | 201 | } |
194 | 202 | ||
195 | struct ubd ubd_dev[MAX_DEV] = { [ 0 ... MAX_DEV - 1 ] = DEFAULT_UBD }; | 203 | struct ubd ubd_devs[MAX_DEV] = { [ 0 ... MAX_DEV - 1 ] = DEFAULT_UBD }; |
196 | |||
197 | static int ubd0_init(void) | ||
198 | { | ||
199 | struct ubd *dev = &ubd_dev[0]; | ||
200 | |||
201 | if(dev->file == NULL) | ||
202 | dev->file = "root_fs"; | ||
203 | return(0); | ||
204 | } | ||
205 | |||
206 | __initcall(ubd0_init); | ||
207 | 204 | ||
208 | /* Only changed by fake_ide_setup which is a setup */ | 205 | /* Only changed by fake_ide_setup which is a setup */ |
209 | static int fake_ide = 0; | 206 | static int fake_ide = 0; |
@@ -277,7 +274,7 @@ static int parse_unit(char **ptr) | |||
277 | return(-1); | 274 | return(-1); |
278 | *ptr = end; | 275 | *ptr = end; |
279 | } | 276 | } |
280 | else if (('a' <= *str) && (*str <= 'h')) { | 277 | else if (('a' <= *str) && (*str <= 'z')) { |
281 | n = *str - 'a'; | 278 | n = *str - 'a'; |
282 | str++; | 279 | str++; |
283 | *ptr = str; | 280 | *ptr = str; |
@@ -285,9 +282,13 @@ static int parse_unit(char **ptr) | |||
285 | return(n); | 282 | return(n); |
286 | } | 283 | } |
287 | 284 | ||
285 | /* If *index_out == -1 at exit, the passed option was a general one; | ||
286 | * otherwise, the str pointer is used (and owned) inside ubd_devs array, so it | ||
287 | * should not be freed on exit. | ||
288 | */ | ||
288 | static int ubd_setup_common(char *str, int *index_out) | 289 | static int ubd_setup_common(char *str, int *index_out) |
289 | { | 290 | { |
290 | struct ubd *dev; | 291 | struct ubd *ubd_dev; |
291 | struct openflags flags = global_openflags; | 292 | struct openflags flags = global_openflags; |
292 | char *backing_file; | 293 | char *backing_file; |
293 | int n, err, i; | 294 | int n, err, i; |
@@ -311,7 +312,7 @@ static int ubd_setup_common(char *str, int *index_out) | |||
311 | } | 312 | } |
312 | 313 | ||
313 | err = 1; | 314 | err = 1; |
314 | spin_lock(&ubd_lock); | 315 | mutex_lock(&ubd_lock); |
315 | if(fake_major != MAJOR_NR){ | 316 | if(fake_major != MAJOR_NR){ |
316 | printk(KERN_ERR "Can't assign a fake major twice\n"); | 317 | printk(KERN_ERR "Can't assign a fake major twice\n"); |
317 | goto out1; | 318 | goto out1; |
@@ -323,7 +324,7 @@ static int ubd_setup_common(char *str, int *index_out) | |||
323 | major); | 324 | major); |
324 | err = 0; | 325 | err = 0; |
325 | out1: | 326 | out1: |
326 | spin_unlock(&ubd_lock); | 327 | mutex_unlock(&ubd_lock); |
327 | return(err); | 328 | return(err); |
328 | } | 329 | } |
329 | 330 | ||
@@ -340,10 +341,10 @@ static int ubd_setup_common(char *str, int *index_out) | |||
340 | } | 341 | } |
341 | 342 | ||
342 | err = 1; | 343 | err = 1; |
343 | spin_lock(&ubd_lock); | 344 | mutex_lock(&ubd_lock); |
344 | 345 | ||
345 | dev = &ubd_dev[n]; | 346 | ubd_dev = &ubd_devs[n]; |
346 | if(dev->file != NULL){ | 347 | if(ubd_dev->file != NULL){ |
347 | printk(KERN_ERR "ubd_setup : device already configured\n"); | 348 | printk(KERN_ERR "ubd_setup : device already configured\n"); |
348 | goto out; | 349 | goto out; |
349 | } | 350 | } |
@@ -360,10 +361,10 @@ static int ubd_setup_common(char *str, int *index_out) | |||
360 | flags.s = 1; | 361 | flags.s = 1; |
361 | break; | 362 | break; |
362 | case 'd': | 363 | case 'd': |
363 | dev->no_cow = 1; | 364 | ubd_dev->no_cow = 1; |
364 | break; | 365 | break; |
365 | case 'c': | 366 | case 'c': |
366 | dev->shared = 1; | 367 | ubd_dev->shared = 1; |
367 | break; | 368 | break; |
368 | case '=': | 369 | case '=': |
369 | str++; | 370 | str++; |
@@ -390,7 +391,7 @@ break_loop: | |||
390 | } | 391 | } |
391 | 392 | ||
392 | if(backing_file){ | 393 | if(backing_file){ |
393 | if(dev->no_cow) | 394 | if(ubd_dev->no_cow) |
394 | printk(KERN_ERR "Can't specify both 'd' and a " | 395 | printk(KERN_ERR "Can't specify both 'd' and a " |
395 | "cow file\n"); | 396 | "cow file\n"); |
396 | else { | 397 | else { |
@@ -398,11 +399,11 @@ break_loop: | |||
398 | backing_file++; | 399 | backing_file++; |
399 | } | 400 | } |
400 | } | 401 | } |
401 | dev->file = str; | 402 | ubd_dev->file = str; |
402 | dev->cow.file = backing_file; | 403 | ubd_dev->cow.file = backing_file; |
403 | dev->boot_openflags = flags; | 404 | ubd_dev->boot_openflags = flags; |
404 | out: | 405 | out: |
405 | spin_unlock(&ubd_lock); | 406 | mutex_unlock(&ubd_lock); |
406 | return(err); | 407 | return(err); |
407 | } | 408 | } |
408 | 409 | ||
@@ -472,8 +473,9 @@ int thread_fd = -1; | |||
472 | 473 | ||
473 | /* Changed by ubd_handler, which is serialized because interrupts only | 474 | /* Changed by ubd_handler, which is serialized because interrupts only |
474 | * happen on CPU 0. | 475 | * happen on CPU 0. |
476 | * XXX: currently unused. | ||
475 | */ | 477 | */ |
476 | int intr_count = 0; | 478 | static int intr_count = 0; |
477 | 479 | ||
478 | /* call ubd_finish if you need to serialize */ | 480 | /* call ubd_finish if you need to serialize */ |
479 | static void __ubd_finish(struct request *req, int error) | 481 | static void __ubd_finish(struct request *req, int error) |
@@ -493,6 +495,8 @@ static void __ubd_finish(struct request *req, int error) | |||
493 | end_request(req, 1); | 495 | end_request(req, 1); |
494 | } | 496 | } |
495 | 497 | ||
498 | /* Callable only from interrupt context - otherwise you need to do | ||
499 | * spin_lock_irq()/spin_lock_irqsave() */ | ||
496 | static inline void ubd_finish(struct request *req, int error) | 500 | static inline void ubd_finish(struct request *req, int error) |
497 | { | 501 | { |
498 | spin_lock(&ubd_io_lock); | 502 | spin_lock(&ubd_io_lock); |
@@ -500,14 +504,15 @@ static inline void ubd_finish(struct request *req, int error) | |||
500 | spin_unlock(&ubd_io_lock); | 504 | spin_unlock(&ubd_io_lock); |
501 | } | 505 | } |
502 | 506 | ||
503 | /* Called without ubd_io_lock held */ | 507 | /* XXX - move this inside ubd_intr. */ |
508 | /* Called without ubd_io_lock held, and only in interrupt context. */ | ||
504 | static void ubd_handler(void) | 509 | static void ubd_handler(void) |
505 | { | 510 | { |
506 | struct io_thread_req req; | 511 | struct io_thread_req req; |
507 | struct request *rq = elv_next_request(ubd_queue); | 512 | struct request *rq = elv_next_request(ubd_queue); |
508 | int n; | 513 | int n; |
509 | 514 | ||
510 | do_ubd = NULL; | 515 | do_ubd = 0; |
511 | intr_count++; | 516 | intr_count++; |
512 | n = os_read_file(thread_fd, &req, sizeof(req)); | 517 | n = os_read_file(thread_fd, &req, sizeof(req)); |
513 | if(n != sizeof(req)){ | 518 | if(n != sizeof(req)){ |
@@ -521,7 +526,9 @@ static void ubd_handler(void) | |||
521 | 526 | ||
522 | ubd_finish(rq, req.error); | 527 | ubd_finish(rq, req.error); |
523 | reactivate_fd(thread_fd, UBD_IRQ); | 528 | reactivate_fd(thread_fd, UBD_IRQ); |
529 | spin_lock(&ubd_io_lock); | ||
524 | do_ubd_request(ubd_queue); | 530 | do_ubd_request(ubd_queue); |
531 | spin_unlock(&ubd_io_lock); | ||
525 | } | 532 | } |
526 | 533 | ||
527 | static irqreturn_t ubd_intr(int irq, void *dev) | 534 | static irqreturn_t ubd_intr(int irq, void *dev) |
@@ -541,87 +548,90 @@ void kill_io_thread(void) | |||
541 | 548 | ||
542 | __uml_exitcall(kill_io_thread); | 549 | __uml_exitcall(kill_io_thread); |
543 | 550 | ||
544 | static int ubd_file_size(struct ubd *dev, __u64 *size_out) | 551 | static inline int ubd_file_size(struct ubd *ubd_dev, __u64 *size_out) |
545 | { | 552 | { |
546 | char *file; | 553 | char *file; |
547 | 554 | ||
548 | file = dev->cow.file ? dev->cow.file : dev->file; | 555 | file = ubd_dev->cow.file ? ubd_dev->cow.file : ubd_dev->file; |
549 | return(os_file_size(file, size_out)); | 556 | return(os_file_size(file, size_out)); |
550 | } | 557 | } |
551 | 558 | ||
552 | static void ubd_close(struct ubd *dev) | 559 | static void ubd_close_dev(struct ubd *ubd_dev) |
553 | { | 560 | { |
554 | os_close_file(dev->fd); | 561 | os_close_file(ubd_dev->fd); |
555 | if(dev->cow.file == NULL) | 562 | if(ubd_dev->cow.file == NULL) |
556 | return; | 563 | return; |
557 | 564 | ||
558 | os_close_file(dev->cow.fd); | 565 | os_close_file(ubd_dev->cow.fd); |
559 | vfree(dev->cow.bitmap); | 566 | vfree(ubd_dev->cow.bitmap); |
560 | dev->cow.bitmap = NULL; | 567 | ubd_dev->cow.bitmap = NULL; |
561 | } | 568 | } |
562 | 569 | ||
563 | static int ubd_open_dev(struct ubd *dev) | 570 | static int ubd_open_dev(struct ubd *ubd_dev) |
564 | { | 571 | { |
565 | struct openflags flags; | 572 | struct openflags flags; |
566 | char **back_ptr; | 573 | char **back_ptr; |
567 | int err, create_cow, *create_ptr; | 574 | int err, create_cow, *create_ptr; |
575 | int fd; | ||
568 | 576 | ||
569 | dev->openflags = dev->boot_openflags; | 577 | ubd_dev->openflags = ubd_dev->boot_openflags; |
570 | create_cow = 0; | 578 | create_cow = 0; |
571 | create_ptr = (dev->cow.file != NULL) ? &create_cow : NULL; | 579 | create_ptr = (ubd_dev->cow.file != NULL) ? &create_cow : NULL; |
572 | back_ptr = dev->no_cow ? NULL : &dev->cow.file; | 580 | back_ptr = ubd_dev->no_cow ? NULL : &ubd_dev->cow.file; |
573 | dev->fd = open_ubd_file(dev->file, &dev->openflags, dev->shared, | 581 | |
574 | back_ptr, &dev->cow.bitmap_offset, | 582 | fd = open_ubd_file(ubd_dev->file, &ubd_dev->openflags, ubd_dev->shared, |
575 | &dev->cow.bitmap_len, &dev->cow.data_offset, | 583 | back_ptr, &ubd_dev->cow.bitmap_offset, |
584 | &ubd_dev->cow.bitmap_len, &ubd_dev->cow.data_offset, | ||
576 | create_ptr); | 585 | create_ptr); |
577 | 586 | ||
578 | if((dev->fd == -ENOENT) && create_cow){ | 587 | if((fd == -ENOENT) && create_cow){ |
579 | dev->fd = create_cow_file(dev->file, dev->cow.file, | 588 | fd = create_cow_file(ubd_dev->file, ubd_dev->cow.file, |
580 | dev->openflags, 1 << 9, PAGE_SIZE, | 589 | ubd_dev->openflags, 1 << 9, PAGE_SIZE, |
581 | &dev->cow.bitmap_offset, | 590 | &ubd_dev->cow.bitmap_offset, |
582 | &dev->cow.bitmap_len, | 591 | &ubd_dev->cow.bitmap_len, |
583 | &dev->cow.data_offset); | 592 | &ubd_dev->cow.data_offset); |
584 | if(dev->fd >= 0){ | 593 | if(fd >= 0){ |
585 | printk(KERN_INFO "Creating \"%s\" as COW file for " | 594 | printk(KERN_INFO "Creating \"%s\" as COW file for " |
586 | "\"%s\"\n", dev->file, dev->cow.file); | 595 | "\"%s\"\n", ubd_dev->file, ubd_dev->cow.file); |
587 | } | 596 | } |
588 | } | 597 | } |
589 | 598 | ||
590 | if(dev->fd < 0){ | 599 | if(fd < 0){ |
591 | printk("Failed to open '%s', errno = %d\n", dev->file, | 600 | printk("Failed to open '%s', errno = %d\n", ubd_dev->file, |
592 | -dev->fd); | 601 | -fd); |
593 | return(dev->fd); | 602 | return fd; |
594 | } | 603 | } |
604 | ubd_dev->fd = fd; | ||
595 | 605 | ||
596 | if(dev->cow.file != NULL){ | 606 | if(ubd_dev->cow.file != NULL){ |
597 | err = -ENOMEM; | 607 | err = -ENOMEM; |
598 | dev->cow.bitmap = (void *) vmalloc(dev->cow.bitmap_len); | 608 | ubd_dev->cow.bitmap = (void *) vmalloc(ubd_dev->cow.bitmap_len); |
599 | if(dev->cow.bitmap == NULL){ | 609 | if(ubd_dev->cow.bitmap == NULL){ |
600 | printk(KERN_ERR "Failed to vmalloc COW bitmap\n"); | 610 | printk(KERN_ERR "Failed to vmalloc COW bitmap\n"); |
601 | goto error; | 611 | goto error; |
602 | } | 612 | } |
603 | flush_tlb_kernel_vm(); | 613 | flush_tlb_kernel_vm(); |
604 | 614 | ||
605 | err = read_cow_bitmap(dev->fd, dev->cow.bitmap, | 615 | err = read_cow_bitmap(ubd_dev->fd, ubd_dev->cow.bitmap, |
606 | dev->cow.bitmap_offset, | 616 | ubd_dev->cow.bitmap_offset, |
607 | dev->cow.bitmap_len); | 617 | ubd_dev->cow.bitmap_len); |
608 | if(err < 0) | 618 | if(err < 0) |
609 | goto error; | 619 | goto error; |
610 | 620 | ||
611 | flags = dev->openflags; | 621 | flags = ubd_dev->openflags; |
612 | flags.w = 0; | 622 | flags.w = 0; |
613 | err = open_ubd_file(dev->cow.file, &flags, dev->shared, NULL, | 623 | err = open_ubd_file(ubd_dev->cow.file, &flags, ubd_dev->shared, NULL, |
614 | NULL, NULL, NULL, NULL); | 624 | NULL, NULL, NULL, NULL); |
615 | if(err < 0) goto error; | 625 | if(err < 0) goto error; |
616 | dev->cow.fd = err; | 626 | ubd_dev->cow.fd = err; |
617 | } | 627 | } |
618 | return(0); | 628 | return(0); |
619 | error: | 629 | error: |
620 | os_close_file(dev->fd); | 630 | os_close_file(ubd_dev->fd); |
621 | return(err); | 631 | return(err); |
622 | } | 632 | } |
623 | 633 | ||
624 | static int ubd_new_disk(int major, u64 size, int unit, | 634 | static int ubd_disk_register(int major, u64 size, int unit, |
625 | struct gendisk **disk_out) | 635 | struct gendisk **disk_out) |
626 | 636 | ||
627 | { | 637 | { |
@@ -642,13 +652,13 @@ static int ubd_new_disk(int major, u64 size, int unit, | |||
642 | 652 | ||
643 | /* sysfs register (not for ide fake devices) */ | 653 | /* sysfs register (not for ide fake devices) */ |
644 | if (major == MAJOR_NR) { | 654 | if (major == MAJOR_NR) { |
645 | ubd_dev[unit].pdev.id = unit; | 655 | ubd_devs[unit].pdev.id = unit; |
646 | ubd_dev[unit].pdev.name = DRIVER_NAME; | 656 | ubd_devs[unit].pdev.name = DRIVER_NAME; |
647 | platform_device_register(&ubd_dev[unit].pdev); | 657 | platform_device_register(&ubd_devs[unit].pdev); |
648 | disk->driverfs_dev = &ubd_dev[unit].pdev.dev; | 658 | disk->driverfs_dev = &ubd_devs[unit].pdev.dev; |
649 | } | 659 | } |
650 | 660 | ||
651 | disk->private_data = &ubd_dev[unit]; | 661 | disk->private_data = &ubd_devs[unit]; |
652 | disk->queue = ubd_queue; | 662 | disk->queue = ubd_queue; |
653 | add_disk(disk); | 663 | add_disk(disk); |
654 | 664 | ||
@@ -660,25 +670,25 @@ static int ubd_new_disk(int major, u64 size, int unit, | |||
660 | 670 | ||
661 | static int ubd_add(int n) | 671 | static int ubd_add(int n) |
662 | { | 672 | { |
663 | struct ubd *dev = &ubd_dev[n]; | 673 | struct ubd *ubd_dev = &ubd_devs[n]; |
664 | int err; | 674 | int err; |
665 | 675 | ||
666 | err = -ENODEV; | 676 | err = -ENODEV; |
667 | if(dev->file == NULL) | 677 | if(ubd_dev->file == NULL) |
668 | goto out; | 678 | goto out; |
669 | 679 | ||
670 | err = ubd_file_size(dev, &dev->size); | 680 | err = ubd_file_size(ubd_dev, &ubd_dev->size); |
671 | if(err < 0) | 681 | if(err < 0) |
672 | goto out; | 682 | goto out; |
673 | 683 | ||
674 | dev->size = ROUND_BLOCK(dev->size); | 684 | ubd_dev->size = ROUND_BLOCK(ubd_dev->size); |
675 | 685 | ||
676 | err = ubd_new_disk(MAJOR_NR, dev->size, n, &ubd_gendisk[n]); | 686 | err = ubd_disk_register(MAJOR_NR, ubd_dev->size, n, &ubd_gendisk[n]); |
677 | if(err) | 687 | if(err) |
678 | goto out; | 688 | goto out; |
679 | 689 | ||
680 | if(fake_major != MAJOR_NR) | 690 | if(fake_major != MAJOR_NR) |
681 | ubd_new_disk(fake_major, dev->size, n, | 691 | ubd_disk_register(fake_major, ubd_dev->size, n, |
682 | &fake_gendisk[n]); | 692 | &fake_gendisk[n]); |
683 | 693 | ||
684 | /* perhaps this should also be under the "if (fake_major)" above */ | 694 | /* perhaps this should also be under the "if (fake_major)" above */ |
@@ -693,32 +703,41 @@ out: | |||
693 | 703 | ||
694 | static int ubd_config(char *str) | 704 | static int ubd_config(char *str) |
695 | { | 705 | { |
696 | int n, err; | 706 | int n, ret; |
697 | 707 | ||
698 | str = kstrdup(str, GFP_KERNEL); | 708 | str = kstrdup(str, GFP_KERNEL); |
699 | if(str == NULL){ | 709 | if (str == NULL) { |
700 | printk(KERN_ERR "ubd_config failed to strdup string\n"); | 710 | printk(KERN_ERR "ubd_config failed to strdup string\n"); |
701 | return(1); | 711 | ret = 1; |
712 | goto out; | ||
702 | } | 713 | } |
703 | err = ubd_setup_common(str, &n); | 714 | ret = ubd_setup_common(str, &n); |
704 | if(err){ | 715 | if (ret) { |
705 | kfree(str); | 716 | ret = -1; |
706 | return(-1); | 717 | goto err_free; |
718 | } | ||
719 | if (n == -1) { | ||
720 | ret = 0; | ||
721 | goto err_free; | ||
707 | } | 722 | } |
708 | if(n == -1) return(0); | ||
709 | 723 | ||
710 | spin_lock(&ubd_lock); | 724 | mutex_lock(&ubd_lock); |
711 | err = ubd_add(n); | 725 | ret = ubd_add(n); |
712 | if(err) | 726 | if (ret) |
713 | ubd_dev[n].file = NULL; | 727 | ubd_devs[n].file = NULL; |
714 | spin_unlock(&ubd_lock); | 728 | mutex_unlock(&ubd_lock); |
715 | 729 | ||
716 | return(err); | 730 | out: |
731 | return ret; | ||
732 | |||
733 | err_free: | ||
734 | kfree(str); | ||
735 | goto out; | ||
717 | } | 736 | } |
718 | 737 | ||
719 | static int ubd_get_config(char *name, char *str, int size, char **error_out) | 738 | static int ubd_get_config(char *name, char *str, int size, char **error_out) |
720 | { | 739 | { |
721 | struct ubd *dev; | 740 | struct ubd *ubd_dev; |
722 | int n, len = 0; | 741 | int n, len = 0; |
723 | 742 | ||
724 | n = parse_unit(&name); | 743 | n = parse_unit(&name); |
@@ -727,24 +746,24 @@ static int ubd_get_config(char *name, char *str, int size, char **error_out) | |||
727 | return(-1); | 746 | return(-1); |
728 | } | 747 | } |
729 | 748 | ||
730 | dev = &ubd_dev[n]; | 749 | ubd_dev = &ubd_devs[n]; |
731 | spin_lock(&ubd_lock); | 750 | mutex_lock(&ubd_lock); |
732 | 751 | ||
733 | if(dev->file == NULL){ | 752 | if(ubd_dev->file == NULL){ |
734 | CONFIG_CHUNK(str, size, len, "", 1); | 753 | CONFIG_CHUNK(str, size, len, "", 1); |
735 | goto out; | 754 | goto out; |
736 | } | 755 | } |
737 | 756 | ||
738 | CONFIG_CHUNK(str, size, len, dev->file, 0); | 757 | CONFIG_CHUNK(str, size, len, ubd_dev->file, 0); |
739 | 758 | ||
740 | if(dev->cow.file != NULL){ | 759 | if(ubd_dev->cow.file != NULL){ |
741 | CONFIG_CHUNK(str, size, len, ",", 0); | 760 | CONFIG_CHUNK(str, size, len, ",", 0); |
742 | CONFIG_CHUNK(str, size, len, dev->cow.file, 1); | 761 | CONFIG_CHUNK(str, size, len, ubd_dev->cow.file, 1); |
743 | } | 762 | } |
744 | else CONFIG_CHUNK(str, size, len, "", 1); | 763 | else CONFIG_CHUNK(str, size, len, "", 1); |
745 | 764 | ||
746 | out: | 765 | out: |
747 | spin_unlock(&ubd_lock); | 766 | mutex_unlock(&ubd_lock); |
748 | return(len); | 767 | return(len); |
749 | } | 768 | } |
750 | 769 | ||
@@ -760,22 +779,22 @@ static int ubd_id(char **str, int *start_out, int *end_out) | |||
760 | 779 | ||
761 | static int ubd_remove(int n) | 780 | static int ubd_remove(int n) |
762 | { | 781 | { |
763 | struct ubd *dev; | 782 | struct ubd *ubd_dev; |
764 | int err = -ENODEV; | 783 | int err = -ENODEV; |
765 | 784 | ||
766 | spin_lock(&ubd_lock); | 785 | mutex_lock(&ubd_lock); |
767 | 786 | ||
768 | if(ubd_gendisk[n] == NULL) | 787 | if(ubd_gendisk[n] == NULL) |
769 | goto out; | 788 | goto out; |
770 | 789 | ||
771 | dev = &ubd_dev[n]; | 790 | ubd_dev = &ubd_devs[n]; |
772 | 791 | ||
773 | if(dev->file == NULL) | 792 | if(ubd_dev->file == NULL) |
774 | goto out; | 793 | goto out; |
775 | 794 | ||
776 | /* you cannot remove a open disk */ | 795 | /* you cannot remove a open disk */ |
777 | err = -EBUSY; | 796 | err = -EBUSY; |
778 | if(dev->count > 0) | 797 | if(ubd_dev->count > 0) |
779 | goto out; | 798 | goto out; |
780 | 799 | ||
781 | del_gendisk(ubd_gendisk[n]); | 800 | del_gendisk(ubd_gendisk[n]); |
@@ -788,14 +807,15 @@ static int ubd_remove(int n) | |||
788 | fake_gendisk[n] = NULL; | 807 | fake_gendisk[n] = NULL; |
789 | } | 808 | } |
790 | 809 | ||
791 | platform_device_unregister(&dev->pdev); | 810 | platform_device_unregister(&ubd_dev->pdev); |
792 | *dev = ((struct ubd) DEFAULT_UBD); | 811 | *ubd_dev = ((struct ubd) DEFAULT_UBD); |
793 | err = 0; | 812 | err = 0; |
794 | out: | 813 | out: |
795 | spin_unlock(&ubd_lock); | 814 | mutex_unlock(&ubd_lock); |
796 | return err; | 815 | return err; |
797 | } | 816 | } |
798 | 817 | ||
818 | /* All these are called by mconsole in process context and without ubd-specific locks. */ | ||
799 | static struct mc_device ubd_mc = { | 819 | static struct mc_device ubd_mc = { |
800 | .name = "ubd", | 820 | .name = "ubd", |
801 | .config = ubd_config, | 821 | .config = ubd_config, |
@@ -804,7 +824,7 @@ static struct mc_device ubd_mc = { | |||
804 | .remove = ubd_remove, | 824 | .remove = ubd_remove, |
805 | }; | 825 | }; |
806 | 826 | ||
807 | static int ubd_mc_init(void) | 827 | static int __init ubd_mc_init(void) |
808 | { | 828 | { |
809 | mconsole_register_dev(&ubd_mc); | 829 | mconsole_register_dev(&ubd_mc); |
810 | return 0; | 830 | return 0; |
@@ -812,13 +832,24 @@ static int ubd_mc_init(void) | |||
812 | 832 | ||
813 | __initcall(ubd_mc_init); | 833 | __initcall(ubd_mc_init); |
814 | 834 | ||
835 | static int __init ubd0_init(void) | ||
836 | { | ||
837 | struct ubd *ubd_dev = &ubd_devs[0]; | ||
838 | |||
839 | if(ubd_dev->file == NULL) | ||
840 | ubd_dev->file = "root_fs"; | ||
841 | return(0); | ||
842 | } | ||
843 | |||
844 | __initcall(ubd0_init); | ||
845 | |||
815 | static struct platform_driver ubd_driver = { | 846 | static struct platform_driver ubd_driver = { |
816 | .driver = { | 847 | .driver = { |
817 | .name = DRIVER_NAME, | 848 | .name = DRIVER_NAME, |
818 | }, | 849 | }, |
819 | }; | 850 | }; |
820 | 851 | ||
821 | int ubd_init(void) | 852 | static int __init ubd_init(void) |
822 | { | 853 | { |
823 | int i; | 854 | int i; |
824 | 855 | ||
@@ -846,7 +877,7 @@ int ubd_init(void) | |||
846 | 877 | ||
847 | late_initcall(ubd_init); | 878 | late_initcall(ubd_init); |
848 | 879 | ||
849 | int ubd_driver_init(void){ | 880 | static int __init ubd_driver_init(void){ |
850 | unsigned long stack; | 881 | unsigned long stack; |
851 | int err; | 882 | int err; |
852 | 883 | ||
@@ -867,7 +898,7 @@ int ubd_driver_init(void){ | |||
867 | return(0); | 898 | return(0); |
868 | } | 899 | } |
869 | err = um_request_irq(UBD_IRQ, thread_fd, IRQ_READ, ubd_intr, | 900 | err = um_request_irq(UBD_IRQ, thread_fd, IRQ_READ, ubd_intr, |
870 | IRQF_DISABLED, "ubd", ubd_dev); | 901 | IRQF_DISABLED, "ubd", ubd_devs); |
871 | if(err != 0) | 902 | if(err != 0) |
872 | printk(KERN_ERR "um_request_irq failed - errno = %d\n", -err); | 903 | printk(KERN_ERR "um_request_irq failed - errno = %d\n", -err); |
873 | return 0; | 904 | return 0; |
@@ -878,24 +909,24 @@ device_initcall(ubd_driver_init); | |||
878 | static int ubd_open(struct inode *inode, struct file *filp) | 909 | static int ubd_open(struct inode *inode, struct file *filp) |
879 | { | 910 | { |
880 | struct gendisk *disk = inode->i_bdev->bd_disk; | 911 | struct gendisk *disk = inode->i_bdev->bd_disk; |
881 | struct ubd *dev = disk->private_data; | 912 | struct ubd *ubd_dev = disk->private_data; |
882 | int err = 0; | 913 | int err = 0; |
883 | 914 | ||
884 | if(dev->count == 0){ | 915 | if(ubd_dev->count == 0){ |
885 | err = ubd_open_dev(dev); | 916 | err = ubd_open_dev(ubd_dev); |
886 | if(err){ | 917 | if(err){ |
887 | printk(KERN_ERR "%s: Can't open \"%s\": errno = %d\n", | 918 | printk(KERN_ERR "%s: Can't open \"%s\": errno = %d\n", |
888 | disk->disk_name, dev->file, -err); | 919 | disk->disk_name, ubd_dev->file, -err); |
889 | goto out; | 920 | goto out; |
890 | } | 921 | } |
891 | } | 922 | } |
892 | dev->count++; | 923 | ubd_dev->count++; |
893 | set_disk_ro(disk, !dev->openflags.w); | 924 | set_disk_ro(disk, !ubd_dev->openflags.w); |
894 | 925 | ||
895 | /* This should no more be needed. And it didn't work anyway to exclude | 926 | /* This should no more be needed. And it didn't work anyway to exclude |
896 | * read-write remounting of filesystems.*/ | 927 | * read-write remounting of filesystems.*/ |
897 | /*if((filp->f_mode & FMODE_WRITE) && !dev->openflags.w){ | 928 | /*if((filp->f_mode & FMODE_WRITE) && !ubd_dev->openflags.w){ |
898 | if(--dev->count == 0) ubd_close(dev); | 929 | if(--ubd_dev->count == 0) ubd_close_dev(ubd_dev); |
899 | err = -EROFS; | 930 | err = -EROFS; |
900 | }*/ | 931 | }*/ |
901 | out: | 932 | out: |
@@ -905,10 +936,10 @@ static int ubd_open(struct inode *inode, struct file *filp) | |||
905 | static int ubd_release(struct inode * inode, struct file * file) | 936 | static int ubd_release(struct inode * inode, struct file * file) |
906 | { | 937 | { |
907 | struct gendisk *disk = inode->i_bdev->bd_disk; | 938 | struct gendisk *disk = inode->i_bdev->bd_disk; |
908 | struct ubd *dev = disk->private_data; | 939 | struct ubd *ubd_dev = disk->private_data; |
909 | 940 | ||
910 | if(--dev->count == 0) | 941 | if(--ubd_dev->count == 0) |
911 | ubd_close(dev); | 942 | ubd_close_dev(ubd_dev); |
912 | return(0); | 943 | return(0); |
913 | } | 944 | } |
914 | 945 | ||
@@ -976,12 +1007,12 @@ static void cowify_req(struct io_thread_req *req, unsigned long *bitmap, | |||
976 | static int prepare_request(struct request *req, struct io_thread_req *io_req) | 1007 | static int prepare_request(struct request *req, struct io_thread_req *io_req) |
977 | { | 1008 | { |
978 | struct gendisk *disk = req->rq_disk; | 1009 | struct gendisk *disk = req->rq_disk; |
979 | struct ubd *dev = disk->private_data; | 1010 | struct ubd *ubd_dev = disk->private_data; |
980 | __u64 offset; | 1011 | __u64 offset; |
981 | int len; | 1012 | int len; |
982 | 1013 | ||
983 | /* This should be impossible now */ | 1014 | /* This should be impossible now */ |
984 | if((rq_data_dir(req) == WRITE) && !dev->openflags.w){ | 1015 | if((rq_data_dir(req) == WRITE) && !ubd_dev->openflags.w){ |
985 | printk("Write attempted on readonly ubd device %s\n", | 1016 | printk("Write attempted on readonly ubd device %s\n", |
986 | disk->disk_name); | 1017 | disk->disk_name); |
987 | end_request(req, 0); | 1018 | end_request(req, 0); |
@@ -991,8 +1022,8 @@ static int prepare_request(struct request *req, struct io_thread_req *io_req) | |||
991 | offset = ((__u64) req->sector) << 9; | 1022 | offset = ((__u64) req->sector) << 9; |
992 | len = req->current_nr_sectors << 9; | 1023 | len = req->current_nr_sectors << 9; |
993 | 1024 | ||
994 | io_req->fds[0] = (dev->cow.file != NULL) ? dev->cow.fd : dev->fd; | 1025 | io_req->fds[0] = (ubd_dev->cow.file != NULL) ? ubd_dev->cow.fd : ubd_dev->fd; |
995 | io_req->fds[1] = dev->fd; | 1026 | io_req->fds[1] = ubd_dev->fd; |
996 | io_req->cow_offset = -1; | 1027 | io_req->cow_offset = -1; |
997 | io_req->offset = offset; | 1028 | io_req->offset = offset; |
998 | io_req->length = len; | 1029 | io_req->length = len; |
@@ -1001,13 +1032,13 @@ static int prepare_request(struct request *req, struct io_thread_req *io_req) | |||
1001 | 1032 | ||
1002 | io_req->op = (rq_data_dir(req) == READ) ? UBD_READ : UBD_WRITE; | 1033 | io_req->op = (rq_data_dir(req) == READ) ? UBD_READ : UBD_WRITE; |
1003 | io_req->offsets[0] = 0; | 1034 | io_req->offsets[0] = 0; |
1004 | io_req->offsets[1] = dev->cow.data_offset; | 1035 | io_req->offsets[1] = ubd_dev->cow.data_offset; |
1005 | io_req->buffer = req->buffer; | 1036 | io_req->buffer = req->buffer; |
1006 | io_req->sectorsize = 1 << 9; | 1037 | io_req->sectorsize = 1 << 9; |
1007 | 1038 | ||
1008 | if(dev->cow.file != NULL) | 1039 | if(ubd_dev->cow.file != NULL) |
1009 | cowify_req(io_req, dev->cow.bitmap, dev->cow.bitmap_offset, | 1040 | cowify_req(io_req, ubd_dev->cow.bitmap, ubd_dev->cow.bitmap_offset, |
1010 | dev->cow.bitmap_len); | 1041 | ubd_dev->cow.bitmap_len); |
1011 | 1042 | ||
1012 | return(0); | 1043 | return(0); |
1013 | } | 1044 | } |
@@ -1033,7 +1064,7 @@ static void do_ubd_request(request_queue_t *q) | |||
1033 | return; | 1064 | return; |
1034 | err = prepare_request(req, &io_req); | 1065 | err = prepare_request(req, &io_req); |
1035 | if(!err){ | 1066 | if(!err){ |
1036 | do_ubd = ubd_handler; | 1067 | do_ubd = 1; |
1037 | n = os_write_file(thread_fd, (char *) &io_req, | 1068 | n = os_write_file(thread_fd, (char *) &io_req, |
1038 | sizeof(io_req)); | 1069 | sizeof(io_req)); |
1039 | if(n != sizeof(io_req)) | 1070 | if(n != sizeof(io_req)) |
@@ -1045,18 +1076,18 @@ static void do_ubd_request(request_queue_t *q) | |||
1045 | 1076 | ||
1046 | static int ubd_getgeo(struct block_device *bdev, struct hd_geometry *geo) | 1077 | static int ubd_getgeo(struct block_device *bdev, struct hd_geometry *geo) |
1047 | { | 1078 | { |
1048 | struct ubd *dev = bdev->bd_disk->private_data; | 1079 | struct ubd *ubd_dev = bdev->bd_disk->private_data; |
1049 | 1080 | ||
1050 | geo->heads = 128; | 1081 | geo->heads = 128; |
1051 | geo->sectors = 32; | 1082 | geo->sectors = 32; |
1052 | geo->cylinders = dev->size / (128 * 32 * 512); | 1083 | geo->cylinders = ubd_dev->size / (128 * 32 * 512); |
1053 | return 0; | 1084 | return 0; |
1054 | } | 1085 | } |
1055 | 1086 | ||
1056 | static int ubd_ioctl(struct inode * inode, struct file * file, | 1087 | static int ubd_ioctl(struct inode * inode, struct file * file, |
1057 | unsigned int cmd, unsigned long arg) | 1088 | unsigned int cmd, unsigned long arg) |
1058 | { | 1089 | { |
1059 | struct ubd *dev = inode->i_bdev->bd_disk->private_data; | 1090 | struct ubd *ubd_dev = inode->i_bdev->bd_disk->private_data; |
1060 | struct hd_driveid ubd_id = { | 1091 | struct hd_driveid ubd_id = { |
1061 | .cyls = 0, | 1092 | .cyls = 0, |
1062 | .heads = 128, | 1093 | .heads = 128, |
@@ -1066,7 +1097,7 @@ static int ubd_ioctl(struct inode * inode, struct file * file, | |||
1066 | switch (cmd) { | 1097 | switch (cmd) { |
1067 | struct cdrom_volctrl volume; | 1098 | struct cdrom_volctrl volume; |
1068 | case HDIO_GET_IDENTITY: | 1099 | case HDIO_GET_IDENTITY: |
1069 | ubd_id.cyls = dev->size / (128 * 32 * 512); | 1100 | ubd_id.cyls = ubd_dev->size / (128 * 32 * 512); |
1070 | if(copy_to_user((char __user *) arg, (char *) &ubd_id, | 1101 | if(copy_to_user((char __user *) arg, (char *) &ubd_id, |
1071 | sizeof(ubd_id))) | 1102 | sizeof(ubd_id))) |
1072 | return(-EFAULT); | 1103 | return(-EFAULT); |
@@ -1353,8 +1384,8 @@ void do_io(struct io_thread_req *req) | |||
1353 | */ | 1384 | */ |
1354 | int kernel_fd = -1; | 1385 | int kernel_fd = -1; |
1355 | 1386 | ||
1356 | /* Only changed by the io thread */ | 1387 | /* Only changed by the io thread. XXX: currently unused. */ |
1357 | int io_count = 0; | 1388 | static int io_count = 0; |
1358 | 1389 | ||
1359 | int io_thread(void *arg) | 1390 | int io_thread(void *arg) |
1360 | { | 1391 | { |
diff --git a/arch/um/include/mconsole.h b/arch/um/include/mconsole.h index 58f67d391105..2666815b6af5 100644 --- a/arch/um/include/mconsole.h +++ b/arch/um/include/mconsole.h | |||
@@ -61,6 +61,7 @@ struct mc_request | |||
61 | 61 | ||
62 | struct mconsole_request request; | 62 | struct mconsole_request request; |
63 | struct mconsole_command *cmd; | 63 | struct mconsole_command *cmd; |
64 | union uml_pt_regs regs; | ||
64 | }; | 65 | }; |
65 | 66 | ||
66 | extern char mconsole_socket_name[]; | 67 | extern char mconsole_socket_name[]; |
diff --git a/arch/um/include/mconsole_kern.h b/arch/um/include/mconsole_kern.h index d0b690197fd7..1ea6d928e1cd 100644 --- a/arch/um/include/mconsole_kern.h +++ b/arch/um/include/mconsole_kern.h | |||
@@ -14,6 +14,7 @@ struct mconsole_entry { | |||
14 | struct mc_request request; | 14 | struct mc_request request; |
15 | }; | 15 | }; |
16 | 16 | ||
17 | /* All these methods are called in process context. */ | ||
17 | struct mc_device { | 18 | struct mc_device { |
18 | struct list_head list; | 19 | struct list_head list; |
19 | char *name; | 20 | char *name; |
diff --git a/arch/um/include/os.h b/arch/um/include/os.h index 6516f6dca96d..13a86bd383d3 100644 --- a/arch/um/include/os.h +++ b/arch/um/include/os.h | |||
@@ -233,6 +233,8 @@ extern unsigned long __do_user_copy(void *to, const void *from, int n, | |||
233 | void (*op)(void *to, const void *from, | 233 | void (*op)(void *to, const void *from, |
234 | int n), int *faulted_out); | 234 | int n), int *faulted_out); |
235 | 235 | ||
236 | /* execvp.c */ | ||
237 | extern int execvp_noalloc(char *buf, const char *file, char *const argv[]); | ||
236 | /* helper.c */ | 238 | /* helper.c */ |
237 | extern int run_helper(void (*pre_exec)(void *), void *pre_data, char **argv, | 239 | extern int run_helper(void (*pre_exec)(void *), void *pre_data, char **argv, |
238 | unsigned long *stack_out); | 240 | unsigned long *stack_out); |
diff --git a/arch/um/include/sysdep-i386/barrier.h b/arch/um/include/sysdep-i386/barrier.h new file mode 100644 index 000000000000..b58d52c5b2f4 --- /dev/null +++ b/arch/um/include/sysdep-i386/barrier.h | |||
@@ -0,0 +1,9 @@ | |||
1 | #ifndef __SYSDEP_I386_BARRIER_H | ||
2 | #define __SYSDEP_I386_BARRIER_H | ||
3 | |||
4 | /* Copied from include/asm-i386 for use by userspace. i386 has the option | ||
5 | * of using mfence, but I'm just using this, which works everywhere, for now. | ||
6 | */ | ||
7 | #define mb() asm volatile("lock; addl $0,0(%esp)") | ||
8 | |||
9 | #endif | ||
diff --git a/arch/um/include/sysdep-x86_64/barrier.h b/arch/um/include/sysdep-x86_64/barrier.h new file mode 100644 index 000000000000..7b610befdc8f --- /dev/null +++ b/arch/um/include/sysdep-x86_64/barrier.h | |||
@@ -0,0 +1,7 @@ | |||
1 | #ifndef __SYSDEP_X86_64_BARRIER_H | ||
2 | #define __SYSDEP_X86_64_BARRIER_H | ||
3 | |||
4 | /* Copied from include/asm-x86_64 for use by userspace. */ | ||
5 | #define mb() asm volatile("mfence":::"memory") | ||
6 | |||
7 | #endif | ||
diff --git a/arch/um/kernel/dyn.lds.S b/arch/um/kernel/dyn.lds.S index 68ed24df5c8f..e36f92b463ce 100644 --- a/arch/um/kernel/dyn.lds.S +++ b/arch/um/kernel/dyn.lds.S | |||
@@ -14,6 +14,7 @@ SECTIONS | |||
14 | * is remapped.*/ | 14 | * is remapped.*/ |
15 | __binary_start = .; | 15 | __binary_start = .; |
16 | . = ALIGN(4096); /* Init code and data */ | 16 | . = ALIGN(4096); /* Init code and data */ |
17 | _text = .; | ||
17 | _stext = .; | 18 | _stext = .; |
18 | __init_begin = .; | 19 | __init_begin = .; |
19 | .init.text : { | 20 | .init.text : { |
diff --git a/arch/um/kernel/tt/tracer.c b/arch/um/kernel/tt/tracer.c index 9882342206ec..b9195355075a 100644 --- a/arch/um/kernel/tt/tracer.c +++ b/arch/um/kernel/tt/tracer.c | |||
@@ -176,7 +176,6 @@ struct { | |||
176 | int signal_index[32]; | 176 | int signal_index[32]; |
177 | int nsignals = 0; | 177 | int nsignals = 0; |
178 | int debug_trace = 0; | 178 | int debug_trace = 0; |
179 | extern int io_nsignals, io_count, intr_count; | ||
180 | 179 | ||
181 | extern void signal_usr1(int sig); | 180 | extern void signal_usr1(int sig); |
182 | 181 | ||
diff --git a/arch/um/kernel/uml.lds.S b/arch/um/kernel/uml.lds.S index 8eca47a6ff08..f6301274cf3c 100644 --- a/arch/um/kernel/uml.lds.S +++ b/arch/um/kernel/uml.lds.S | |||
@@ -25,6 +25,7 @@ SECTIONS | |||
25 | . = ALIGN(4096); /* Init code and data */ | 25 | . = ALIGN(4096); /* Init code and data */ |
26 | #endif | 26 | #endif |
27 | 27 | ||
28 | _text = .; | ||
28 | _stext = .; | 29 | _stext = .; |
29 | __init_begin = .; | 30 | __init_begin = .; |
30 | .init.text : { | 31 | .init.text : { |
diff --git a/arch/um/os-Linux/Makefile b/arch/um/os-Linux/Makefile index b4183929b32c..2f8c79464015 100644 --- a/arch/um/os-Linux/Makefile +++ b/arch/um/os-Linux/Makefile | |||
@@ -3,8 +3,8 @@ | |||
3 | # Licensed under the GPL | 3 | # Licensed under the GPL |
4 | # | 4 | # |
5 | 5 | ||
6 | obj-y = aio.o elf_aux.o file.o helper.o irq.o main.o mem.o process.o sigio.o \ | 6 | obj-y = aio.o elf_aux.o execvp.o file.o helper.o irq.o main.o mem.o process.o \ |
7 | signal.o start_up.o time.o trap.o tty.o uaccess.o umid.o tls.o \ | 7 | sigio.o signal.o start_up.o time.o trap.o tty.o uaccess.o umid.o tls.o \ |
8 | user_syms.o util.o drivers/ sys-$(SUBARCH)/ | 8 | user_syms.o util.o drivers/ sys-$(SUBARCH)/ |
9 | 9 | ||
10 | obj-$(CONFIG_MODE_SKAS) += skas/ | 10 | obj-$(CONFIG_MODE_SKAS) += skas/ |
@@ -15,9 +15,9 @@ user-objs-$(CONFIG_MODE_TT) += tt.o | |||
15 | obj-$(CONFIG_TTY_LOG) += tty_log.o | 15 | obj-$(CONFIG_TTY_LOG) += tty_log.o |
16 | user-objs-$(CONFIG_TTY_LOG) += tty_log.o | 16 | user-objs-$(CONFIG_TTY_LOG) += tty_log.o |
17 | 17 | ||
18 | USER_OBJS := $(user-objs-y) aio.o elf_aux.o file.o helper.o irq.o main.o mem.o \ | 18 | USER_OBJS := $(user-objs-y) aio.o elf_aux.o execvp.o file.o helper.o irq.o \ |
19 | process.o sigio.o signal.o start_up.o time.o trap.o tty.o tls.o \ | 19 | main.o mem.o process.o sigio.o signal.o start_up.o time.o trap.o tty.o \ |
20 | uaccess.o umid.o util.o | 20 | tls.o uaccess.o umid.o util.o |
21 | 21 | ||
22 | CFLAGS_user_syms.o += -DSUBARCH_$(SUBARCH) | 22 | CFLAGS_user_syms.o += -DSUBARCH_$(SUBARCH) |
23 | 23 | ||
diff --git a/arch/um/os-Linux/execvp.c b/arch/um/os-Linux/execvp.c new file mode 100644 index 000000000000..66e583a4031b --- /dev/null +++ b/arch/um/os-Linux/execvp.c | |||
@@ -0,0 +1,149 @@ | |||
1 | /* Copyright (C) 2006 by Paolo Giarrusso - modified from glibc' execvp.c. | ||
2 | Original copyright notice follows: | ||
3 | |||
4 | Copyright (C) 1991,92,1995-99,2002,2004 Free Software Foundation, Inc. | ||
5 | This file is part of the GNU C Library. | ||
6 | |||
7 | The GNU C Library is free software; you can redistribute it and/or | ||
8 | modify it under the terms of the GNU Lesser General Public | ||
9 | License as published by the Free Software Foundation; either | ||
10 | version 2.1 of the License, or (at your option) any later version. | ||
11 | |||
12 | The GNU C Library is distributed in the hope that it will be useful, | ||
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
15 | Lesser General Public License for more details. | ||
16 | |||
17 | You should have received a copy of the GNU Lesser General Public | ||
18 | License along with the GNU C Library; if not, write to the Free | ||
19 | Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA | ||
20 | 02111-1307 USA. */ | ||
21 | #include <unistd.h> | ||
22 | |||
23 | #include <stdbool.h> | ||
24 | #include <stdlib.h> | ||
25 | #include <string.h> | ||
26 | #include <errno.h> | ||
27 | #include <limits.h> | ||
28 | |||
29 | #ifndef TEST | ||
30 | #include "um_malloc.h" | ||
31 | #else | ||
32 | #include <stdio.h> | ||
33 | #define um_kmalloc malloc | ||
34 | #endif | ||
35 | #include "os.h" | ||
36 | |||
37 | /* Execute FILE, searching in the `PATH' environment variable if it contains | ||
38 | no slashes, with arguments ARGV and environment from `environ'. */ | ||
39 | int execvp_noalloc(char *buf, const char *file, char *const argv[]) | ||
40 | { | ||
41 | if (*file == '\0') { | ||
42 | return -ENOENT; | ||
43 | } | ||
44 | |||
45 | if (strchr (file, '/') != NULL) { | ||
46 | /* Don't search when it contains a slash. */ | ||
47 | execv(file, argv); | ||
48 | } else { | ||
49 | int got_eacces; | ||
50 | size_t len, pathlen; | ||
51 | char *name, *p; | ||
52 | char *path = getenv("PATH"); | ||
53 | if (path == NULL) | ||
54 | path = ":/bin:/usr/bin"; | ||
55 | |||
56 | len = strlen(file) + 1; | ||
57 | pathlen = strlen(path); | ||
58 | /* Copy the file name at the top. */ | ||
59 | name = memcpy(buf + pathlen + 1, file, len); | ||
60 | /* And add the slash. */ | ||
61 | *--name = '/'; | ||
62 | |||
63 | got_eacces = 0; | ||
64 | p = path; | ||
65 | do { | ||
66 | char *startp; | ||
67 | |||
68 | path = p; | ||
69 | //Let's avoid this GNU extension. | ||
70 | //p = strchrnul (path, ':'); | ||
71 | p = strchr(path, ':'); | ||
72 | if (!p) | ||
73 | p = strchr(path, '\0'); | ||
74 | |||
75 | if (p == path) | ||
76 | /* Two adjacent colons, or a colon at the beginning or the end | ||
77 | of `PATH' means to search the current directory. */ | ||
78 | startp = name + 1; | ||
79 | else | ||
80 | startp = memcpy(name - (p - path), path, p - path); | ||
81 | |||
82 | /* Try to execute this name. If it works, execv will not return. */ | ||
83 | execv(startp, argv); | ||
84 | |||
85 | /* | ||
86 | if (errno == ENOEXEC) { | ||
87 | } | ||
88 | */ | ||
89 | |||
90 | switch (errno) { | ||
91 | case EACCES: | ||
92 | /* Record the we got a `Permission denied' error. If we end | ||
93 | up finding no executable we can use, we want to diagnose | ||
94 | that we did find one but were denied access. */ | ||
95 | got_eacces = 1; | ||
96 | case ENOENT: | ||
97 | case ESTALE: | ||
98 | case ENOTDIR: | ||
99 | /* Those errors indicate the file is missing or not executable | ||
100 | by us, in which case we want to just try the next path | ||
101 | directory. */ | ||
102 | case ENODEV: | ||
103 | case ETIMEDOUT: | ||
104 | /* Some strange filesystems like AFS return even | ||
105 | stranger error numbers. They cannot reasonably mean | ||
106 | anything else so ignore those, too. */ | ||
107 | case ENOEXEC: | ||
108 | /* We won't go searching for the shell | ||
109 | * if it is not executable - the Linux | ||
110 | * kernel already handles this enough, | ||
111 | * for us. */ | ||
112 | break; | ||
113 | |||
114 | default: | ||
115 | /* Some other error means we found an executable file, but | ||
116 | something went wrong executing it; return the error to our | ||
117 | caller. */ | ||
118 | return -errno; | ||
119 | } | ||
120 | } while (*p++ != '\0'); | ||
121 | |||
122 | /* We tried every element and none of them worked. */ | ||
123 | if (got_eacces) | ||
124 | /* At least one failure was due to permissions, so report that | ||
125 | error. */ | ||
126 | return -EACCES; | ||
127 | } | ||
128 | |||
129 | /* Return the error from the last attempt (probably ENOENT). */ | ||
130 | return -errno; | ||
131 | } | ||
132 | #ifdef TEST | ||
133 | int main(int argc, char**argv) | ||
134 | { | ||
135 | char buf[PATH_MAX]; | ||
136 | int ret; | ||
137 | argc--; | ||
138 | if (!argc) { | ||
139 | fprintf(stderr, "Not enough arguments\n"); | ||
140 | return 1; | ||
141 | } | ||
142 | argv++; | ||
143 | if (ret = execvp_noalloc(buf, argv[0], argv)) { | ||
144 | errno = -ret; | ||
145 | perror("execvp_noalloc"); | ||
146 | } | ||
147 | return 0; | ||
148 | } | ||
149 | #endif | ||
diff --git a/arch/um/os-Linux/helper.c b/arch/um/os-Linux/helper.c index d13299cfa318..c7ad6306e22f 100644 --- a/arch/um/os-Linux/helper.c +++ b/arch/um/os-Linux/helper.c | |||
@@ -8,18 +8,21 @@ | |||
8 | #include <unistd.h> | 8 | #include <unistd.h> |
9 | #include <errno.h> | 9 | #include <errno.h> |
10 | #include <sched.h> | 10 | #include <sched.h> |
11 | #include <limits.h> | ||
11 | #include <sys/signal.h> | 12 | #include <sys/signal.h> |
12 | #include <sys/wait.h> | 13 | #include <sys/wait.h> |
13 | #include "user.h" | 14 | #include "user.h" |
14 | #include "kern_util.h" | 15 | #include "kern_util.h" |
15 | #include "user_util.h" | 16 | #include "user_util.h" |
16 | #include "os.h" | 17 | #include "os.h" |
18 | #include "um_malloc.h" | ||
17 | 19 | ||
18 | struct helper_data { | 20 | struct helper_data { |
19 | void (*pre_exec)(void*); | 21 | void (*pre_exec)(void*); |
20 | void *pre_data; | 22 | void *pre_data; |
21 | char **argv; | 23 | char **argv; |
22 | int fd; | 24 | int fd; |
25 | char *buf; | ||
23 | }; | 26 | }; |
24 | 27 | ||
25 | /* Debugging aid, changed only from gdb */ | 28 | /* Debugging aid, changed only from gdb */ |
@@ -41,9 +44,8 @@ static int helper_child(void *arg) | |||
41 | } | 44 | } |
42 | if (data->pre_exec != NULL) | 45 | if (data->pre_exec != NULL) |
43 | (*data->pre_exec)(data->pre_data); | 46 | (*data->pre_exec)(data->pre_data); |
44 | execvp(argv[0], argv); | 47 | errval = execvp_noalloc(data->buf, argv[0], argv); |
45 | errval = -errno; | 48 | printk("helper_child - execvp of '%s' failed - errno = %d\n", argv[0], -errval); |
46 | printk("helper_child - execve of '%s' failed - errno = %d\n", argv[0], errno); | ||
47 | os_write_file(data->fd, &errval, sizeof(errval)); | 49 | os_write_file(data->fd, &errval, sizeof(errval)); |
48 | kill(os_getpid(), SIGKILL); | 50 | kill(os_getpid(), SIGKILL); |
49 | return 0; | 51 | return 0; |
@@ -84,11 +86,13 @@ int run_helper(void (*pre_exec)(void *), void *pre_data, char **argv, | |||
84 | data.pre_data = pre_data; | 86 | data.pre_data = pre_data; |
85 | data.argv = argv; | 87 | data.argv = argv; |
86 | data.fd = fds[1]; | 88 | data.fd = fds[1]; |
89 | data.buf = __cant_sleep() ? um_kmalloc_atomic(PATH_MAX) : | ||
90 | um_kmalloc(PATH_MAX); | ||
87 | pid = clone(helper_child, (void *) sp, CLONE_VM | SIGCHLD, &data); | 91 | pid = clone(helper_child, (void *) sp, CLONE_VM | SIGCHLD, &data); |
88 | if (pid < 0) { | 92 | if (pid < 0) { |
89 | ret = -errno; | 93 | ret = -errno; |
90 | printk("run_helper : clone failed, errno = %d\n", errno); | 94 | printk("run_helper : clone failed, errno = %d\n", errno); |
91 | goto out_close; | 95 | goto out_free2; |
92 | } | 96 | } |
93 | 97 | ||
94 | close(fds[1]); | 98 | close(fds[1]); |
@@ -109,6 +113,8 @@ int run_helper(void (*pre_exec)(void *), void *pre_data, char **argv, | |||
109 | CATCH_EINTR(waitpid(pid, NULL, 0)); | 113 | CATCH_EINTR(waitpid(pid, NULL, 0)); |
110 | } | 114 | } |
111 | 115 | ||
116 | out_free2: | ||
117 | kfree(data.buf); | ||
112 | out_close: | 118 | out_close: |
113 | if (fds[1] != -1) | 119 | if (fds[1] != -1) |
114 | close(fds[1]); | 120 | close(fds[1]); |
diff --git a/arch/um/os-Linux/process.c b/arch/um/os-Linux/process.c index 51f0893640a6..c692a192957a 100644 --- a/arch/um/os-Linux/process.c +++ b/arch/um/os-Linux/process.c | |||
@@ -7,7 +7,6 @@ | |||
7 | #include <stdio.h> | 7 | #include <stdio.h> |
8 | #include <errno.h> | 8 | #include <errno.h> |
9 | #include <signal.h> | 9 | #include <signal.h> |
10 | #include <linux/unistd.h> | ||
11 | #include <sys/mman.h> | 10 | #include <sys/mman.h> |
12 | #include <sys/wait.h> | 11 | #include <sys/wait.h> |
13 | #include <sys/mman.h> | 12 | #include <sys/mman.h> |
diff --git a/arch/um/os-Linux/signal.c b/arch/um/os-Linux/signal.c index 6b81739279d1..b897e8592d77 100644 --- a/arch/um/os-Linux/signal.c +++ b/arch/um/os-Linux/signal.c | |||
@@ -15,6 +15,7 @@ | |||
15 | #include "user.h" | 15 | #include "user.h" |
16 | #include "signal_kern.h" | 16 | #include "signal_kern.h" |
17 | #include "sysdep/sigcontext.h" | 17 | #include "sysdep/sigcontext.h" |
18 | #include "sysdep/barrier.h" | ||
18 | #include "sigcontext.h" | 19 | #include "sigcontext.h" |
19 | #include "mode.h" | 20 | #include "mode.h" |
20 | #include "os.h" | 21 | #include "os.h" |
@@ -34,8 +35,12 @@ | |||
34 | #define SIGALRM_BIT 2 | 35 | #define SIGALRM_BIT 2 |
35 | #define SIGALRM_MASK (1 << SIGALRM_BIT) | 36 | #define SIGALRM_MASK (1 << SIGALRM_BIT) |
36 | 37 | ||
37 | static int signals_enabled = 1; | 38 | /* These are used by both the signal handlers and |
38 | static int pending = 0; | 39 | * block/unblock_signals. I don't want modifications cached in a |
40 | * register - they must go straight to memory. | ||
41 | */ | ||
42 | static volatile int signals_enabled = 1; | ||
43 | static volatile int pending = 0; | ||
39 | 44 | ||
40 | void sig_handler(int sig, struct sigcontext *sc) | 45 | void sig_handler(int sig, struct sigcontext *sc) |
41 | { | 46 | { |
@@ -152,6 +157,12 @@ int change_sig(int signal, int on) | |||
152 | void block_signals(void) | 157 | void block_signals(void) |
153 | { | 158 | { |
154 | signals_enabled = 0; | 159 | signals_enabled = 0; |
160 | /* This must return with signals disabled, so this barrier | ||
161 | * ensures that writes are flushed out before the return. | ||
162 | * This might matter if gcc figures out how to inline this and | ||
163 | * decides to shuffle this code into the caller. | ||
164 | */ | ||
165 | mb(); | ||
155 | } | 166 | } |
156 | 167 | ||
157 | void unblock_signals(void) | 168 | void unblock_signals(void) |
@@ -171,9 +182,23 @@ void unblock_signals(void) | |||
171 | */ | 182 | */ |
172 | signals_enabled = 1; | 183 | signals_enabled = 1; |
173 | 184 | ||
185 | /* Setting signals_enabled and reading pending must | ||
186 | * happen in this order. | ||
187 | */ | ||
188 | mb(); | ||
189 | |||
174 | save_pending = pending; | 190 | save_pending = pending; |
175 | if(save_pending == 0) | 191 | if(save_pending == 0){ |
192 | /* This must return with signals enabled, so | ||
193 | * this barrier ensures that writes are | ||
194 | * flushed out before the return. This might | ||
195 | * matter if gcc figures out how to inline | ||
196 | * this (unlikely, given its size) and decides | ||
197 | * to shuffle this code into the caller. | ||
198 | */ | ||
199 | mb(); | ||
176 | return; | 200 | return; |
201 | } | ||
177 | 202 | ||
178 | pending = 0; | 203 | pending = 0; |
179 | 204 | ||
diff --git a/arch/um/os-Linux/skas/process.c b/arch/um/os-Linux/skas/process.c index cb9ab54146cc..9b34fe65949a 100644 --- a/arch/um/os-Linux/skas/process.c +++ b/arch/um/os-Linux/skas/process.c | |||
@@ -14,7 +14,7 @@ | |||
14 | #include <sys/mman.h> | 14 | #include <sys/mman.h> |
15 | #include <sys/user.h> | 15 | #include <sys/user.h> |
16 | #include <sys/time.h> | 16 | #include <sys/time.h> |
17 | #include <asm/unistd.h> | 17 | #include <sys/syscall.h> |
18 | #include <asm/types.h> | 18 | #include <asm/types.h> |
19 | #include "user.h" | 19 | #include "user.h" |
20 | #include "sysdep/ptrace.h" | 20 | #include "sysdep/ptrace.h" |
diff --git a/arch/um/os-Linux/sys-i386/tls.c b/arch/um/os-Linux/sys-i386/tls.c index 6e945ab45843..256532034c62 100644 --- a/arch/um/os-Linux/sys-i386/tls.c +++ b/arch/um/os-Linux/sys-i386/tls.c | |||
@@ -1,6 +1,9 @@ | |||
1 | #include <errno.h> | 1 | #include <errno.h> |
2 | #include <linux/unistd.h> | 2 | #include <linux/unistd.h> |
3 | |||
3 | #include <sys/syscall.h> | 4 | #include <sys/syscall.h> |
5 | #include <unistd.h> | ||
6 | |||
4 | #include "sysdep/tls.h" | 7 | #include "sysdep/tls.h" |
5 | #include "user_util.h" | 8 | #include "user_util.h" |
6 | 9 | ||
diff --git a/arch/um/os-Linux/tls.c b/arch/um/os-Linux/tls.c index a2de2580b8af..16215b990804 100644 --- a/arch/um/os-Linux/tls.c +++ b/arch/um/os-Linux/tls.c | |||
@@ -1,4 +1,5 @@ | |||
1 | #include <errno.h> | 1 | #include <errno.h> |
2 | #include <unistd.h> | ||
2 | #include <sys/ptrace.h> | 3 | #include <sys/ptrace.h> |
3 | #include <sys/syscall.h> | 4 | #include <sys/syscall.h> |
4 | #include <asm/ldt.h> | 5 | #include <asm/ldt.h> |
diff --git a/arch/um/sys-i386/unmap.c b/arch/um/sys-i386/unmap.c index 8e55cd5d3d07..1b0ad0e4adcd 100644 --- a/arch/um/sys-i386/unmap.c +++ b/arch/um/sys-i386/unmap.c | |||
@@ -5,17 +5,20 @@ | |||
5 | 5 | ||
6 | #include <linux/mman.h> | 6 | #include <linux/mman.h> |
7 | #include <asm/unistd.h> | 7 | #include <asm/unistd.h> |
8 | #include <sys/syscall.h> | ||
9 | 8 | ||
9 | static int errno; | ||
10 | |||
11 | static inline _syscall2(int,munmap,void *,start,size_t,len) | ||
12 | static inline _syscall6(void *,mmap2,void *,addr,size_t,len,int,prot,int,flags,int,fd,off_t,offset) | ||
10 | int switcheroo(int fd, int prot, void *from, void *to, int size) | 13 | int switcheroo(int fd, int prot, void *from, void *to, int size) |
11 | { | 14 | { |
12 | if (syscall(__NR_munmap, to, size) < 0){ | 15 | if(munmap(to, size) < 0){ |
13 | return(-1); | 16 | return(-1); |
14 | } | 17 | } |
15 | if (syscall(__NR_mmap2, to, size, prot, MAP_SHARED | MAP_FIXED, fd, 0) == (void*) -1 ){ | 18 | if(mmap2(to, size, prot, MAP_SHARED | MAP_FIXED, fd, 0) == (void*) -1 ){ |
16 | return(-1); | 19 | return(-1); |
17 | } | 20 | } |
18 | if (syscall(__NR_munmap, from, size) < 0){ | 21 | if(munmap(from, size) < 0){ |
19 | return(-1); | 22 | return(-1); |
20 | } | 23 | } |
21 | return(0); | 24 | return(0); |
diff --git a/arch/um/sys-x86_64/unmap.c b/arch/um/sys-x86_64/unmap.c index 57c9286a701b..f4a4bffd8a18 100644 --- a/arch/um/sys-x86_64/unmap.c +++ b/arch/um/sys-x86_64/unmap.c | |||
@@ -5,17 +5,20 @@ | |||
5 | 5 | ||
6 | #include <linux/mman.h> | 6 | #include <linux/mman.h> |
7 | #include <asm/unistd.h> | 7 | #include <asm/unistd.h> |
8 | #include <sys/syscall.h> | ||
9 | 8 | ||
9 | static int errno; | ||
10 | |||
11 | static inline _syscall2(int,munmap,void *,start,size_t,len) | ||
12 | static inline _syscall6(void *,mmap,void *,addr,size_t,len,int,prot,int,flags,int,fd,off_t,offset) | ||
10 | int switcheroo(int fd, int prot, void *from, void *to, int size) | 13 | int switcheroo(int fd, int prot, void *from, void *to, int size) |
11 | { | 14 | { |
12 | if (syscall(__NR_munmap, to, size) < 0){ | 15 | if(munmap(to, size) < 0){ |
13 | return(-1); | 16 | return(-1); |
14 | } | 17 | } |
15 | if (syscall(__NR_mmap, to, size, prot, MAP_SHARED | MAP_FIXED, fd, 0) == (void*) -1){ | 18 | if(mmap(to, size, prot, MAP_SHARED | MAP_FIXED, fd, 0) == (void*) -1){ |
16 | return(-1); | 19 | return(-1); |
17 | } | 20 | } |
18 | if (syscall(__NR_munmap, from, size) < 0){ | 21 | if(munmap(from, size) < 0){ |
19 | return(-1); | 22 | return(-1); |
20 | } | 23 | } |
21 | return(0); | 24 | return(0); |