diff options
Diffstat (limited to 'arch/um/drivers')
-rw-r--r-- | arch/um/drivers/cow.h | 2 | ||||
-rw-r--r-- | arch/um/drivers/cow_sys.h | 2 | ||||
-rw-r--r-- | arch/um/drivers/cow_user.c | 96 | ||||
-rw-r--r-- | arch/um/drivers/mconsole_kern.c | 8 | ||||
-rw-r--r-- | arch/um/drivers/net_user.c | 4 | ||||
-rw-r--r-- | arch/um/drivers/slirp_user.c | 2 |
6 files changed, 88 insertions, 26 deletions
diff --git a/arch/um/drivers/cow.h b/arch/um/drivers/cow.h index 04e3958266e0..dc36b222100b 100644 --- a/arch/um/drivers/cow.h +++ b/arch/um/drivers/cow.h | |||
@@ -46,7 +46,7 @@ extern int file_reader(__u64 offset, char *buf, int len, void *arg); | |||
46 | extern int read_cow_header(int (*reader)(__u64, char *, int, void *), | 46 | extern int read_cow_header(int (*reader)(__u64, char *, int, void *), |
47 | void *arg, __u32 *version_out, | 47 | void *arg, __u32 *version_out, |
48 | char **backing_file_out, time_t *mtime_out, | 48 | char **backing_file_out, time_t *mtime_out, |
49 | __u64 *size_out, int *sectorsize_out, | 49 | unsigned long long *size_out, int *sectorsize_out, |
50 | __u32 *align_out, int *bitmap_offset_out); | 50 | __u32 *align_out, int *bitmap_offset_out); |
51 | 51 | ||
52 | extern int write_cow_header(char *cow_file, int fd, char *backing_file, | 52 | extern int write_cow_header(char *cow_file, int fd, char *backing_file, |
diff --git a/arch/um/drivers/cow_sys.h b/arch/um/drivers/cow_sys.h index 94de4ead4f7a..7a5b4afde692 100644 --- a/arch/um/drivers/cow_sys.h +++ b/arch/um/drivers/cow_sys.h | |||
@@ -28,7 +28,7 @@ static inline int cow_seek_file(int fd, __u64 offset) | |||
28 | return(os_seek_file(fd, offset)); | 28 | return(os_seek_file(fd, offset)); |
29 | } | 29 | } |
30 | 30 | ||
31 | static inline int cow_file_size(char *file, __u64 *size_out) | 31 | static inline int cow_file_size(char *file, unsigned long long *size_out) |
32 | { | 32 | { |
33 | return(os_file_size(file, size_out)); | 33 | return(os_file_size(file, size_out)); |
34 | } | 34 | } |
diff --git a/arch/um/drivers/cow_user.c b/arch/um/drivers/cow_user.c index 61951b721268..6ab852bfcd3a 100644 --- a/arch/um/drivers/cow_user.c +++ b/arch/um/drivers/cow_user.c | |||
@@ -17,30 +17,34 @@ | |||
17 | 17 | ||
18 | #define PATH_LEN_V1 256 | 18 | #define PATH_LEN_V1 256 |
19 | 19 | ||
20 | typedef __u32 time32_t; | ||
21 | |||
20 | struct cow_header_v1 { | 22 | struct cow_header_v1 { |
21 | int magic; | 23 | __s32 magic; |
22 | int version; | 24 | __s32 version; |
23 | char backing_file[PATH_LEN_V1]; | 25 | char backing_file[PATH_LEN_V1]; |
24 | time_t mtime; | 26 | time32_t mtime; |
25 | __u64 size; | 27 | __u64 size; |
26 | int sectorsize; | 28 | __s32 sectorsize; |
27 | }; | 29 | } __attribute__((packed)); |
28 | 30 | ||
29 | #define PATH_LEN_V2 MAXPATHLEN | 31 | /* Define PATH_LEN_V3 as the usual value of MAXPATHLEN, just hard-code it in |
32 | * case other systems have different values for MAXPATHLEN. | ||
33 | * | ||
34 | * The same must hold for V2 - we want file format compatibility, not anything | ||
35 | * else. | ||
36 | */ | ||
37 | #define PATH_LEN_V3 4096 | ||
38 | #define PATH_LEN_V2 PATH_LEN_V3 | ||
30 | 39 | ||
31 | struct cow_header_v2 { | 40 | struct cow_header_v2 { |
32 | __u32 magic; | 41 | __u32 magic; |
33 | __u32 version; | 42 | __u32 version; |
34 | char backing_file[PATH_LEN_V2]; | 43 | char backing_file[PATH_LEN_V2]; |
35 | time_t mtime; | 44 | time32_t mtime; |
36 | __u64 size; | 45 | __u64 size; |
37 | int sectorsize; | 46 | __s32 sectorsize; |
38 | }; | 47 | } __attribute__((packed)); |
39 | |||
40 | /* Define PATH_LEN_V3 as the usual value of MAXPATHLEN, just hard-code it in | ||
41 | * case other systems have different values for MAXPATHLEN | ||
42 | */ | ||
43 | #define PATH_LEN_V3 4096 | ||
44 | 48 | ||
45 | /* Changes from V2 - | 49 | /* Changes from V2 - |
46 | * PATH_LEN_V3 as described above | 50 | * PATH_LEN_V3 as described above |
@@ -66,6 +70,15 @@ struct cow_header_v2 { | |||
66 | * Fixed (finally!) the rounding bug | 70 | * Fixed (finally!) the rounding bug |
67 | */ | 71 | */ |
68 | 72 | ||
73 | /* Until Dec2005, __attribute__((packed)) was left out from the below | ||
74 | * definition, leading on 64-bit systems to 4 bytes of padding after mtime, to | ||
75 | * align size to 8-byte alignment. This shifted all fields above (no padding | ||
76 | * was present on 32-bit, no other padding was added). | ||
77 | * | ||
78 | * However, this _can be detected_: it means that cow_format (always 0 until | ||
79 | * now) is shifted onto the first 4 bytes of backing_file, where it is otherwise | ||
80 | * impossible to find 4 zeros. -bb */ | ||
81 | |||
69 | struct cow_header_v3 { | 82 | struct cow_header_v3 { |
70 | __u32 magic; | 83 | __u32 magic; |
71 | __u32 version; | 84 | __u32 version; |
@@ -75,7 +88,19 @@ struct cow_header_v3 { | |||
75 | __u32 alignment; | 88 | __u32 alignment; |
76 | __u32 cow_format; | 89 | __u32 cow_format; |
77 | char backing_file[PATH_LEN_V3]; | 90 | char backing_file[PATH_LEN_V3]; |
78 | }; | 91 | } __attribute__((packed)); |
92 | |||
93 | /* This is the broken layout used by some 64-bit binaries. */ | ||
94 | struct cow_header_v3_broken { | ||
95 | __u32 magic; | ||
96 | __u32 version; | ||
97 | __s64 mtime; | ||
98 | __u64 size; | ||
99 | __u32 sectorsize; | ||
100 | __u32 alignment; | ||
101 | __u32 cow_format; | ||
102 | char backing_file[PATH_LEN_V3]; | ||
103 | } __attribute__((packed)); | ||
79 | 104 | ||
80 | /* COW format definitions - for now, we have only the usual COW bitmap */ | 105 | /* COW format definitions - for now, we have only the usual COW bitmap */ |
81 | #define COW_BITMAP 0 | 106 | #define COW_BITMAP 0 |
@@ -84,6 +109,7 @@ union cow_header { | |||
84 | struct cow_header_v1 v1; | 109 | struct cow_header_v1 v1; |
85 | struct cow_header_v2 v2; | 110 | struct cow_header_v2 v2; |
86 | struct cow_header_v3 v3; | 111 | struct cow_header_v3 v3; |
112 | struct cow_header_v3_broken v3_b; | ||
87 | }; | 113 | }; |
88 | 114 | ||
89 | #define COW_MAGIC 0x4f4f4f4d /* MOOO */ | 115 | #define COW_MAGIC 0x4f4f4f4d /* MOOO */ |
@@ -184,8 +210,9 @@ int write_cow_header(char *cow_file, int fd, char *backing_file, | |||
184 | 210 | ||
185 | err = -EINVAL; | 211 | err = -EINVAL; |
186 | if(strlen(backing_file) > sizeof(header->backing_file) - 1){ | 212 | if(strlen(backing_file) > sizeof(header->backing_file) - 1){ |
213 | /* Below, %zd is for a size_t value */ | ||
187 | cow_printf("Backing file name \"%s\" is too long - names are " | 214 | cow_printf("Backing file name \"%s\" is too long - names are " |
188 | "limited to %d characters\n", backing_file, | 215 | "limited to %zd characters\n", backing_file, |
189 | sizeof(header->backing_file) - 1); | 216 | sizeof(header->backing_file) - 1); |
190 | goto out_free; | 217 | goto out_free; |
191 | } | 218 | } |
@@ -300,7 +327,8 @@ int read_cow_header(int (*reader)(__u64, char *, int, void *), void *arg, | |||
300 | *align_out = *sectorsize_out; | 327 | *align_out = *sectorsize_out; |
301 | file = header->v2.backing_file; | 328 | file = header->v2.backing_file; |
302 | } | 329 | } |
303 | else if(version == 3){ | 330 | /* This is very subtle - see above at union cow_header definition */ |
331 | else if(version == 3 && (*((int*)header->v3.backing_file) != 0)){ | ||
304 | if(n < sizeof(header->v3)){ | 332 | if(n < sizeof(header->v3)){ |
305 | cow_printf("read_cow_header - failed to read V3 " | 333 | cow_printf("read_cow_header - failed to read V3 " |
306 | "header\n"); | 334 | "header\n"); |
@@ -310,9 +338,43 @@ int read_cow_header(int (*reader)(__u64, char *, int, void *), void *arg, | |||
310 | *size_out = ntohll(header->v3.size); | 338 | *size_out = ntohll(header->v3.size); |
311 | *sectorsize_out = ntohl(header->v3.sectorsize); | 339 | *sectorsize_out = ntohl(header->v3.sectorsize); |
312 | *align_out = ntohl(header->v3.alignment); | 340 | *align_out = ntohl(header->v3.alignment); |
341 | if (*align_out == 0) { | ||
342 | cow_printf("read_cow_header - invalid COW header, " | ||
343 | "align == 0\n"); | ||
344 | } | ||
313 | *bitmap_offset_out = ROUND_UP(sizeof(header->v3), *align_out); | 345 | *bitmap_offset_out = ROUND_UP(sizeof(header->v3), *align_out); |
314 | file = header->v3.backing_file; | 346 | file = header->v3.backing_file; |
315 | } | 347 | } |
348 | else if(version == 3){ | ||
349 | cow_printf("read_cow_header - broken V3 file with" | ||
350 | " 64-bit layout - recovering content.\n"); | ||
351 | |||
352 | if(n < sizeof(header->v3_b)){ | ||
353 | cow_printf("read_cow_header - failed to read V3 " | ||
354 | "header\n"); | ||
355 | goto out; | ||
356 | } | ||
357 | |||
358 | /* this was used until Dec2005 - 64bits are needed to represent | ||
359 | * 2038+. I.e. we can safely do this truncating cast. | ||
360 | * | ||
361 | * Additionally, we must use ntohl() instead of ntohll(), since | ||
362 | * the program used to use the former (tested - I got mtime | ||
363 | * mismatch "0 vs whatever"). | ||
364 | * | ||
365 | * Ever heard about bug-to-bug-compatibility ? ;-) */ | ||
366 | *mtime_out = (time32_t) ntohl(header->v3_b.mtime); | ||
367 | |||
368 | *size_out = ntohll(header->v3_b.size); | ||
369 | *sectorsize_out = ntohl(header->v3_b.sectorsize); | ||
370 | *align_out = ntohl(header->v3_b.alignment); | ||
371 | if (*align_out == 0) { | ||
372 | cow_printf("read_cow_header - invalid COW header, " | ||
373 | "align == 0\n"); | ||
374 | } | ||
375 | *bitmap_offset_out = ROUND_UP(sizeof(header->v3_b), *align_out); | ||
376 | file = header->v3_b.backing_file; | ||
377 | } | ||
316 | else { | 378 | else { |
317 | cow_printf("read_cow_header - invalid COW version\n"); | 379 | cow_printf("read_cow_header - invalid COW version\n"); |
318 | goto out; | 380 | goto out; |
diff --git a/arch/um/drivers/mconsole_kern.c b/arch/um/drivers/mconsole_kern.c index 28e3760e8b98..6d7173fc55a3 100644 --- a/arch/um/drivers/mconsole_kern.c +++ b/arch/um/drivers/mconsole_kern.c | |||
@@ -62,7 +62,7 @@ static void mc_work_proc(void *unused) | |||
62 | unsigned long flags; | 62 | unsigned long flags; |
63 | 63 | ||
64 | while(!list_empty(&mc_requests)){ | 64 | while(!list_empty(&mc_requests)){ |
65 | local_save_flags(flags); | 65 | local_irq_save(flags); |
66 | req = list_entry(mc_requests.next, struct mconsole_entry, | 66 | req = list_entry(mc_requests.next, struct mconsole_entry, |
67 | list); | 67 | list); |
68 | list_del(&req->list); | 68 | list_del(&req->list); |
@@ -87,7 +87,7 @@ static irqreturn_t mconsole_interrupt(int irq, void *dev_id, | |||
87 | if(req.cmd->context == MCONSOLE_INTR) | 87 | if(req.cmd->context == MCONSOLE_INTR) |
88 | (*req.cmd->handler)(&req); | 88 | (*req.cmd->handler)(&req); |
89 | else { | 89 | else { |
90 | new = kmalloc(sizeof(*new), GFP_ATOMIC); | 90 | new = kmalloc(sizeof(*new), GFP_NOWAIT); |
91 | if(new == NULL) | 91 | if(new == NULL) |
92 | mconsole_reply(&req, "Out of memory", 1, 0); | 92 | mconsole_reply(&req, "Out of memory", 1, 0); |
93 | else { | 93 | else { |
@@ -415,7 +415,6 @@ static int mem_config(char *str) | |||
415 | 415 | ||
416 | unplugged = page_address(page); | 416 | unplugged = page_address(page); |
417 | if(unplug_index == UNPLUGGED_PER_PAGE){ | 417 | if(unplug_index == UNPLUGGED_PER_PAGE){ |
418 | INIT_LIST_HEAD(&unplugged->list); | ||
419 | list_add(&unplugged->list, &unplugged_pages); | 418 | list_add(&unplugged->list, &unplugged_pages); |
420 | unplug_index = 0; | 419 | unplug_index = 0; |
421 | } | 420 | } |
@@ -616,7 +615,7 @@ static void console_write(struct console *console, const char *string, | |||
616 | return; | 615 | return; |
617 | 616 | ||
618 | while(1){ | 617 | while(1){ |
619 | n = min((size_t)len, ARRAY_SIZE(console_buf) - console_index); | 618 | n = min((size_t) len, ARRAY_SIZE(console_buf) - console_index); |
620 | strncpy(&console_buf[console_index], string, n); | 619 | strncpy(&console_buf[console_index], string, n); |
621 | console_index += n; | 620 | console_index += n; |
622 | string += n; | 621 | string += n; |
@@ -655,7 +654,6 @@ static void with_console(struct mc_request *req, void (*proc)(void *), | |||
655 | struct mconsole_entry entry; | 654 | struct mconsole_entry entry; |
656 | unsigned long flags; | 655 | unsigned long flags; |
657 | 656 | ||
658 | INIT_LIST_HEAD(&entry.list); | ||
659 | entry.request = *req; | 657 | entry.request = *req; |
660 | list_add(&entry.list, &clients); | 658 | list_add(&entry.list, &clients); |
661 | spin_lock_irqsave(&console_lock, flags); | 659 | spin_lock_irqsave(&console_lock, flags); |
diff --git a/arch/um/drivers/net_user.c b/arch/um/drivers/net_user.c index 0e2f06187ea7..0a7786e00cfb 100644 --- a/arch/um/drivers/net_user.c +++ b/arch/um/drivers/net_user.c | |||
@@ -182,7 +182,9 @@ static int change_tramp(char **argv, char *output, int output_len) | |||
182 | pe_data.stdout = fds[1]; | 182 | pe_data.stdout = fds[1]; |
183 | pid = run_helper(change_pre_exec, &pe_data, argv, NULL); | 183 | pid = run_helper(change_pre_exec, &pe_data, argv, NULL); |
184 | 184 | ||
185 | read_output(fds[0], output, output_len); | 185 | if (pid > 0) /* Avoid hang as we won't get data in failure case. */ |
186 | read_output(fds[0], output, output_len); | ||
187 | |||
186 | os_close_file(fds[0]); | 188 | os_close_file(fds[0]); |
187 | os_close_file(fds[1]); | 189 | os_close_file(fds[1]); |
188 | 190 | ||
diff --git a/arch/um/drivers/slirp_user.c b/arch/um/drivers/slirp_user.c index b94c66114bc8..33c5f6e625e8 100644 --- a/arch/um/drivers/slirp_user.c +++ b/arch/um/drivers/slirp_user.c | |||
@@ -104,7 +104,7 @@ static void slirp_close(int fd, void *data) | |||
104 | } | 104 | } |
105 | 105 | ||
106 | if(err == 0) { | 106 | if(err == 0) { |
107 | printk("slirp_close: process %d has not exited\n"); | 107 | printk("slirp_close: process %d has not exited\n", pri->pid); |
108 | return; | 108 | return; |
109 | } | 109 | } |
110 | 110 | ||