aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/um/drivers/ubd.h1
-rw-r--r--arch/um/drivers/ubd_kern.c72
-rw-r--r--arch/um/drivers/ubd_user.c5
-rw-r--r--arch/um/include/shared/os.h3
-rw-r--r--arch/um/kernel/Makefile2
-rw-r--r--arch/um/kernel/irq.c4
-rw-r--r--arch/um/kernel/maccess.c24
-rw-r--r--arch/um/os-Linux/aio.c5
-rw-r--r--arch/um/os-Linux/file.c9
-rw-r--r--arch/um/os-Linux/main.c2
-rw-r--r--arch/um/os-Linux/process.c53
-rw-r--r--arch/um/os-Linux/sigio.c2
-rw-r--r--arch/um/os-Linux/util.c10
-rw-r--r--arch/x86/um/os-Linux/prctl.c2
-rw-r--r--fs/hostfs/hostfs_kern.c9
15 files changed, 176 insertions, 27 deletions
diff --git a/arch/um/drivers/ubd.h b/arch/um/drivers/ubd.h
index 3845051f1b10..3b48cd2081ee 100644
--- a/arch/um/drivers/ubd.h
+++ b/arch/um/drivers/ubd.h
@@ -7,7 +7,6 @@
7#ifndef __UM_UBD_USER_H 7#ifndef __UM_UBD_USER_H
8#define __UM_UBD_USER_H 8#define __UM_UBD_USER_H
9 9
10extern void ignore_sigwinch_sig(void);
11extern int start_io_thread(unsigned long sp, int *fds_out); 10extern int start_io_thread(unsigned long sp, int *fds_out);
12extern int io_thread(void *arg); 11extern int io_thread(void *arg);
13extern int kernel_fd; 12extern int kernel_fd;
diff --git a/arch/um/drivers/ubd_kern.c b/arch/um/drivers/ubd_kern.c
index 879990cb66c6..3716e6952554 100644
--- a/arch/um/drivers/ubd_kern.c
+++ b/arch/um/drivers/ubd_kern.c
@@ -41,7 +41,7 @@
41#include <os.h> 41#include <os.h>
42#include "cow.h" 42#include "cow.h"
43 43
44enum ubd_req { UBD_READ, UBD_WRITE }; 44enum ubd_req { UBD_READ, UBD_WRITE, UBD_FLUSH };
45 45
46struct io_thread_req { 46struct io_thread_req {
47 struct request *req; 47 struct request *req;
@@ -866,6 +866,7 @@ static int ubd_add(int n, char **error_out)
866 goto out; 866 goto out;
867 } 867 }
868 ubd_dev->queue->queuedata = ubd_dev; 868 ubd_dev->queue->queuedata = ubd_dev;
869 blk_queue_flush(ubd_dev->queue, REQ_FLUSH);
869 870
870 blk_queue_max_segments(ubd_dev->queue, MAX_SG); 871 blk_queue_max_segments(ubd_dev->queue, MAX_SG);
871 err = ubd_disk_register(UBD_MAJOR, ubd_dev->size, n, &ubd_gendisk[n]); 872 err = ubd_disk_register(UBD_MAJOR, ubd_dev->size, n, &ubd_gendisk[n]);
@@ -1239,11 +1240,40 @@ static void prepare_request(struct request *req, struct io_thread_req *io_req,
1239} 1240}
1240 1241
1241/* Called with dev->lock held */ 1242/* Called with dev->lock held */
1243static void prepare_flush_request(struct request *req,
1244 struct io_thread_req *io_req)
1245{
1246 struct gendisk *disk = req->rq_disk;
1247 struct ubd *ubd_dev = disk->private_data;
1248
1249 io_req->req = req;
1250 io_req->fds[0] = (ubd_dev->cow.file != NULL) ? ubd_dev->cow.fd :
1251 ubd_dev->fd;
1252 io_req->op = UBD_FLUSH;
1253}
1254
1255static bool submit_request(struct io_thread_req *io_req, struct ubd *dev)
1256{
1257 int n = os_write_file(thread_fd, &io_req,
1258 sizeof(io_req));
1259 if (n != sizeof(io_req)) {
1260 if (n != -EAGAIN)
1261 printk("write to io thread failed, "
1262 "errno = %d\n", -n);
1263 else if (list_empty(&dev->restart))
1264 list_add(&dev->restart, &restart);
1265
1266 kfree(io_req);
1267 return false;
1268 }
1269 return true;
1270}
1271
1272/* Called with dev->lock held */
1242static void do_ubd_request(struct request_queue *q) 1273static void do_ubd_request(struct request_queue *q)
1243{ 1274{
1244 struct io_thread_req *io_req; 1275 struct io_thread_req *io_req;
1245 struct request *req; 1276 struct request *req;
1246 int n;
1247 1277
1248 while(1){ 1278 while(1){
1249 struct ubd *dev = q->queuedata; 1279 struct ubd *dev = q->queuedata;
@@ -1259,6 +1289,19 @@ static void do_ubd_request(struct request_queue *q)
1259 } 1289 }
1260 1290
1261 req = dev->request; 1291 req = dev->request;
1292
1293 if (req->cmd_flags & REQ_FLUSH) {
1294 io_req = kmalloc(sizeof(struct io_thread_req),
1295 GFP_ATOMIC);
1296 if (io_req == NULL) {
1297 if (list_empty(&dev->restart))
1298 list_add(&dev->restart, &restart);
1299 return;
1300 }
1301 prepare_flush_request(req, io_req);
1302 submit_request(io_req, dev);
1303 }
1304
1262 while(dev->start_sg < dev->end_sg){ 1305 while(dev->start_sg < dev->end_sg){
1263 struct scatterlist *sg = &dev->sg[dev->start_sg]; 1306 struct scatterlist *sg = &dev->sg[dev->start_sg];
1264 1307
@@ -1273,17 +1316,8 @@ static void do_ubd_request(struct request_queue *q)
1273 (unsigned long long)dev->rq_pos << 9, 1316 (unsigned long long)dev->rq_pos << 9,
1274 sg->offset, sg->length, sg_page(sg)); 1317 sg->offset, sg->length, sg_page(sg));
1275 1318
1276 n = os_write_file(thread_fd, &io_req, 1319 if (submit_request(io_req, dev) == false)
1277 sizeof(struct io_thread_req *));
1278 if(n != sizeof(struct io_thread_req *)){
1279 if(n != -EAGAIN)
1280 printk("write to io thread failed, "
1281 "errno = %d\n", -n);
1282 else if(list_empty(&dev->restart))
1283 list_add(&dev->restart, &restart);
1284 kfree(io_req);
1285 return; 1320 return;
1286 }
1287 1321
1288 dev->rq_pos += sg->length >> 9; 1322 dev->rq_pos += sg->length >> 9;
1289 dev->start_sg++; 1323 dev->start_sg++;
@@ -1367,6 +1401,17 @@ static void do_io(struct io_thread_req *req)
1367 int err; 1401 int err;
1368 __u64 off; 1402 __u64 off;
1369 1403
1404 if (req->op == UBD_FLUSH) {
1405 /* fds[0] is always either the rw image or our cow file */
1406 n = os_sync_file(req->fds[0]);
1407 if (n != 0) {
1408 printk("do_io - sync failed err = %d "
1409 "fd = %d\n", -n, req->fds[0]);
1410 req->error = 1;
1411 }
1412 return;
1413 }
1414
1370 nsectors = req->length / req->sectorsize; 1415 nsectors = req->length / req->sectorsize;
1371 start = 0; 1416 start = 0;
1372 do { 1417 do {
@@ -1431,7 +1476,8 @@ int io_thread(void *arg)
1431 struct io_thread_req *req; 1476 struct io_thread_req *req;
1432 int n; 1477 int n;
1433 1478
1434 ignore_sigwinch_sig(); 1479 os_fix_helper_signals();
1480
1435 while(1){ 1481 while(1){
1436 n = os_read_file(kernel_fd, &req, 1482 n = os_read_file(kernel_fd, &req,
1437 sizeof(struct io_thread_req *)); 1483 sizeof(struct io_thread_req *));
diff --git a/arch/um/drivers/ubd_user.c b/arch/um/drivers/ubd_user.c
index a703e45d8aac..e376f9b9c68d 100644
--- a/arch/um/drivers/ubd_user.c
+++ b/arch/um/drivers/ubd_user.c
@@ -21,11 +21,6 @@
21#include "ubd.h" 21#include "ubd.h"
22#include <os.h> 22#include <os.h>
23 23
24void ignore_sigwinch_sig(void)
25{
26 signal(SIGWINCH, SIG_IGN);
27}
28
29int start_io_thread(unsigned long sp, int *fd_out) 24int start_io_thread(unsigned long sp, int *fd_out)
30{ 25{
31 int pid, fds[2], err; 26 int pid, fds[2], err;
diff --git a/arch/um/include/shared/os.h b/arch/um/include/shared/os.h
index 95feaa47a2fb..021104d98cb3 100644
--- a/arch/um/include/shared/os.h
+++ b/arch/um/include/shared/os.h
@@ -141,6 +141,7 @@ extern int os_seek_file(int fd, unsigned long long offset);
141extern int os_open_file(const char *file, struct openflags flags, int mode); 141extern int os_open_file(const char *file, struct openflags flags, int mode);
142extern int os_read_file(int fd, void *buf, int len); 142extern int os_read_file(int fd, void *buf, int len);
143extern int os_write_file(int fd, const void *buf, int count); 143extern int os_write_file(int fd, const void *buf, int count);
144extern int os_sync_file(int fd);
144extern int os_file_size(const char *file, unsigned long long *size_out); 145extern int os_file_size(const char *file, unsigned long long *size_out);
145extern int os_file_modtime(const char *file, unsigned long *modtime); 146extern int os_file_modtime(const char *file, unsigned long *modtime);
146extern int os_pipe(int *fd, int stream, int close_on_exec); 147extern int os_pipe(int *fd, int stream, int close_on_exec);
@@ -200,6 +201,7 @@ extern int os_unmap_memory(void *addr, int len);
200extern int os_drop_memory(void *addr, int length); 201extern int os_drop_memory(void *addr, int length);
201extern int can_drop_memory(void); 202extern int can_drop_memory(void);
202extern void os_flush_stdout(void); 203extern void os_flush_stdout(void);
204extern int os_mincore(void *addr, unsigned long len);
203 205
204/* execvp.c */ 206/* execvp.c */
205extern int execvp_noalloc(char *buf, const char *file, char *const argv[]); 207extern int execvp_noalloc(char *buf, const char *file, char *const argv[]);
@@ -233,6 +235,7 @@ extern void setup_machinename(char *machine_out);
233extern void setup_hostinfo(char *buf, int len); 235extern void setup_hostinfo(char *buf, int len);
234extern void os_dump_core(void) __attribute__ ((noreturn)); 236extern void os_dump_core(void) __attribute__ ((noreturn));
235extern void um_early_printk(const char *s, unsigned int n); 237extern void um_early_printk(const char *s, unsigned int n);
238extern void os_fix_helper_signals(void);
236 239
237/* time.c */ 240/* time.c */
238extern void idle_sleep(unsigned long long nsecs); 241extern void idle_sleep(unsigned long long nsecs);
diff --git a/arch/um/kernel/Makefile b/arch/um/kernel/Makefile
index babe21826e3e..d8b78a03855c 100644
--- a/arch/um/kernel/Makefile
+++ b/arch/um/kernel/Makefile
@@ -13,7 +13,7 @@ clean-files :=
13obj-y = config.o exec.o exitcode.o irq.o ksyms.o mem.o \ 13obj-y = config.o exec.o exitcode.o irq.o ksyms.o mem.o \
14 physmem.o process.o ptrace.o reboot.o sigio.o \ 14 physmem.o process.o ptrace.o reboot.o sigio.o \
15 signal.o smp.o syscall.o sysrq.o time.o tlb.o trap.o \ 15 signal.o smp.o syscall.o sysrq.o time.o tlb.o trap.o \
16 um_arch.o umid.o skas/ 16 um_arch.o umid.o maccess.o skas/
17 17
18obj-$(CONFIG_BLK_DEV_INITRD) += initrd.o 18obj-$(CONFIG_BLK_DEV_INITRD) += initrd.o
19obj-$(CONFIG_GPROF) += gprof_syms.o 19obj-$(CONFIG_GPROF) += gprof_syms.o
diff --git a/arch/um/kernel/irq.c b/arch/um/kernel/irq.c
index 36e12f0cefd5..1d8505b1e290 100644
--- a/arch/um/kernel/irq.c
+++ b/arch/um/kernel/irq.c
@@ -337,6 +337,8 @@ static struct irq_chip normal_irq_type = {
337 .irq_disable = dummy, 337 .irq_disable = dummy,
338 .irq_enable = dummy, 338 .irq_enable = dummy,
339 .irq_ack = dummy, 339 .irq_ack = dummy,
340 .irq_mask = dummy,
341 .irq_unmask = dummy,
340}; 342};
341 343
342static struct irq_chip SIGVTALRM_irq_type = { 344static struct irq_chip SIGVTALRM_irq_type = {
@@ -344,6 +346,8 @@ static struct irq_chip SIGVTALRM_irq_type = {
344 .irq_disable = dummy, 346 .irq_disable = dummy,
345 .irq_enable = dummy, 347 .irq_enable = dummy,
346 .irq_ack = dummy, 348 .irq_ack = dummy,
349 .irq_mask = dummy,
350 .irq_unmask = dummy,
347}; 351};
348 352
349void __init init_IRQ(void) 353void __init init_IRQ(void)
diff --git a/arch/um/kernel/maccess.c b/arch/um/kernel/maccess.c
new file mode 100644
index 000000000000..1f3d5c4910d1
--- /dev/null
+++ b/arch/um/kernel/maccess.c
@@ -0,0 +1,24 @@
1/*
2 * Copyright (C) 2013 Richard Weinberger <richrd@nod.at>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 */
8
9#include <linux/uaccess.h>
10#include <linux/kernel.h>
11#include <os.h>
12
13long probe_kernel_read(void *dst, const void *src, size_t size)
14{
15 void *psrc = (void *)rounddown((unsigned long)src, PAGE_SIZE);
16
17 if ((unsigned long)src < PAGE_SIZE || size <= 0)
18 return -EFAULT;
19
20 if (os_mincore(psrc, size + src - psrc) <= 0)
21 return -EFAULT;
22
23 return __probe_kernel_read(dst, src, size);
24}
diff --git a/arch/um/os-Linux/aio.c b/arch/um/os-Linux/aio.c
index 3a6bc2af0961..014eb35fd13b 100644
--- a/arch/um/os-Linux/aio.c
+++ b/arch/um/os-Linux/aio.c
@@ -104,8 +104,7 @@ static int aio_thread(void *arg)
104 struct io_event event; 104 struct io_event event;
105 int err, n, reply_fd; 105 int err, n, reply_fd;
106 106
107 signal(SIGWINCH, SIG_IGN); 107 os_fix_helper_signals();
108
109 while (1) { 108 while (1) {
110 n = io_getevents(ctx, 1, 1, &event, NULL); 109 n = io_getevents(ctx, 1, 1, &event, NULL);
111 if (n < 0) { 110 if (n < 0) {
@@ -173,7 +172,7 @@ static int not_aio_thread(void *arg)
173 struct aio_thread_reply reply; 172 struct aio_thread_reply reply;
174 int err; 173 int err;
175 174
176 signal(SIGWINCH, SIG_IGN); 175 os_fix_helper_signals();
177 while (1) { 176 while (1) {
178 err = read(aio_req_fd_r, &req, sizeof(req)); 177 err = read(aio_req_fd_r, &req, sizeof(req));
179 if (err != sizeof(req)) { 178 if (err != sizeof(req)) {
diff --git a/arch/um/os-Linux/file.c b/arch/um/os-Linux/file.c
index c17bd6f7d674..07a750197bb0 100644
--- a/arch/um/os-Linux/file.c
+++ b/arch/um/os-Linux/file.c
@@ -266,6 +266,15 @@ int os_write_file(int fd, const void *buf, int len)
266 return n; 266 return n;
267} 267}
268 268
269int os_sync_file(int fd)
270{
271 int n = fsync(fd);
272
273 if (n < 0)
274 return -errno;
275 return n;
276}
277
269int os_file_size(const char *file, unsigned long long *size_out) 278int os_file_size(const char *file, unsigned long long *size_out)
270{ 279{
271 struct uml_stat buf; 280 struct uml_stat buf;
diff --git a/arch/um/os-Linux/main.c b/arch/um/os-Linux/main.c
index 749c96da7b99..e1704ff600ff 100644
--- a/arch/um/os-Linux/main.c
+++ b/arch/um/os-Linux/main.c
@@ -123,6 +123,8 @@ int __init main(int argc, char **argv, char **envp)
123 123
124 setup_env_path(); 124 setup_env_path();
125 125
126 setsid();
127
126 new_argv = malloc((argc + 1) * sizeof(char *)); 128 new_argv = malloc((argc + 1) * sizeof(char *));
127 if (new_argv == NULL) { 129 if (new_argv == NULL) {
128 perror("Mallocing argv"); 130 perror("Mallocing argv");
diff --git a/arch/um/os-Linux/process.c b/arch/um/os-Linux/process.c
index b8f34c9e53ae..33496fe2bb52 100644
--- a/arch/um/os-Linux/process.c
+++ b/arch/um/os-Linux/process.c
@@ -4,6 +4,7 @@
4 */ 4 */
5 5
6#include <stdio.h> 6#include <stdio.h>
7#include <stdlib.h>
7#include <unistd.h> 8#include <unistd.h>
8#include <errno.h> 9#include <errno.h>
9#include <signal.h> 10#include <signal.h>
@@ -232,6 +233,57 @@ out:
232 return ok; 233 return ok;
233} 234}
234 235
236static int os_page_mincore(void *addr)
237{
238 char vec[2];
239 int ret;
240
241 ret = mincore(addr, UM_KERN_PAGE_SIZE, vec);
242 if (ret < 0) {
243 if (errno == ENOMEM || errno == EINVAL)
244 return 0;
245 else
246 return -errno;
247 }
248
249 return vec[0] & 1;
250}
251
252int os_mincore(void *addr, unsigned long len)
253{
254 char *vec;
255 int ret, i;
256
257 if (len <= UM_KERN_PAGE_SIZE)
258 return os_page_mincore(addr);
259
260 vec = calloc(1, (len + UM_KERN_PAGE_SIZE - 1) / UM_KERN_PAGE_SIZE);
261 if (!vec)
262 return -ENOMEM;
263
264 ret = mincore(addr, UM_KERN_PAGE_SIZE, vec);
265 if (ret < 0) {
266 if (errno == ENOMEM || errno == EINVAL)
267 ret = 0;
268 else
269 ret = -errno;
270
271 goto out;
272 }
273
274 for (i = 0; i < ((len + UM_KERN_PAGE_SIZE - 1) / UM_KERN_PAGE_SIZE); i++) {
275 if (!(vec[i] & 1)) {
276 ret = 0;
277 goto out;
278 }
279 }
280
281 ret = 1;
282out:
283 free(vec);
284 return ret;
285}
286
235void init_new_thread_signals(void) 287void init_new_thread_signals(void)
236{ 288{
237 set_handler(SIGSEGV); 289 set_handler(SIGSEGV);
@@ -242,5 +294,4 @@ void init_new_thread_signals(void)
242 signal(SIGHUP, SIG_IGN); 294 signal(SIGHUP, SIG_IGN);
243 set_handler(SIGIO); 295 set_handler(SIGIO);
244 signal(SIGWINCH, SIG_IGN); 296 signal(SIGWINCH, SIG_IGN);
245 signal(SIGTERM, SIG_DFL);
246} 297}
diff --git a/arch/um/os-Linux/sigio.c b/arch/um/os-Linux/sigio.c
index 8b61cc0e82c8..46e762f926eb 100644
--- a/arch/um/os-Linux/sigio.c
+++ b/arch/um/os-Linux/sigio.c
@@ -55,7 +55,7 @@ static int write_sigio_thread(void *unused)
55 int i, n, respond_fd; 55 int i, n, respond_fd;
56 char c; 56 char c;
57 57
58 signal(SIGWINCH, SIG_IGN); 58 os_fix_helper_signals();
59 fds = &current_poll; 59 fds = &current_poll;
60 while (1) { 60 while (1) {
61 n = poll(fds->poll, fds->used, -1); 61 n = poll(fds->poll, fds->used, -1);
diff --git a/arch/um/os-Linux/util.c b/arch/um/os-Linux/util.c
index 492ef5e6e166..faee55ef6d2f 100644
--- a/arch/um/os-Linux/util.c
+++ b/arch/um/os-Linux/util.c
@@ -94,6 +94,16 @@ static inline void __attribute__ ((noreturn)) uml_abort(void)
94 exit(127); 94 exit(127);
95} 95}
96 96
97/*
98 * UML helper threads must not handle SIGWINCH/INT/TERM
99 */
100void os_fix_helper_signals(void)
101{
102 signal(SIGWINCH, SIG_IGN);
103 signal(SIGINT, SIG_DFL);
104 signal(SIGTERM, SIG_DFL);
105}
106
97void os_dump_core(void) 107void os_dump_core(void)
98{ 108{
99 int pid; 109 int pid;
diff --git a/arch/x86/um/os-Linux/prctl.c b/arch/x86/um/os-Linux/prctl.c
index 9d34eddb517f..96eb2bd28832 100644
--- a/arch/x86/um/os-Linux/prctl.c
+++ b/arch/x86/um/os-Linux/prctl.c
@@ -4,7 +4,7 @@
4 */ 4 */
5 5
6#include <sys/ptrace.h> 6#include <sys/ptrace.h>
7#include <linux/ptrace.h> 7#include <asm/ptrace.h>
8 8
9int os_arch_prctl(int pid, int code, unsigned long *addr) 9int os_arch_prctl(int pid, int code, unsigned long *addr)
10{ 10{
diff --git a/fs/hostfs/hostfs_kern.c b/fs/hostfs/hostfs_kern.c
index cddb05217512..25437280a207 100644
--- a/fs/hostfs/hostfs_kern.c
+++ b/fs/hostfs/hostfs_kern.c
@@ -361,6 +361,13 @@ retry:
361 return 0; 361 return 0;
362} 362}
363 363
364static int hostfs_file_release(struct inode *inode, struct file *file)
365{
366 filemap_write_and_wait(inode->i_mapping);
367
368 return 0;
369}
370
364int hostfs_fsync(struct file *file, loff_t start, loff_t end, int datasync) 371int hostfs_fsync(struct file *file, loff_t start, loff_t end, int datasync)
365{ 372{
366 struct inode *inode = file->f_mapping->host; 373 struct inode *inode = file->f_mapping->host;
@@ -386,7 +393,7 @@ static const struct file_operations hostfs_file_fops = {
386 .write = do_sync_write, 393 .write = do_sync_write,
387 .mmap = generic_file_mmap, 394 .mmap = generic_file_mmap,
388 .open = hostfs_file_open, 395 .open = hostfs_file_open,
389 .release = NULL, 396 .release = hostfs_file_release,
390 .fsync = hostfs_fsync, 397 .fsync = hostfs_fsync,
391}; 398};
392 399