aboutsummaryrefslogtreecommitdiffstats
path: root/arch/um/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'arch/um/drivers')
-rw-r--r--arch/um/drivers/ubd_kern.c385
1 files changed, 190 insertions, 195 deletions
diff --git a/arch/um/drivers/ubd_kern.c b/arch/um/drivers/ubd_kern.c
index be3a2797dac4..5e45e39a8a8d 100644
--- a/arch/um/drivers/ubd_kern.c
+++ b/arch/um/drivers/ubd_kern.c
@@ -72,18 +72,6 @@ struct io_thread_req {
72 int error; 72 int error;
73}; 73};
74 74
75extern int open_ubd_file(char *file, struct openflags *openflags, int shared,
76 char **backing_file_out, int *bitmap_offset_out,
77 unsigned long *bitmap_len_out, int *data_offset_out,
78 int *create_cow_out);
79extern int create_cow_file(char *cow_file, char *backing_file,
80 struct openflags flags, int sectorsize,
81 int alignment, int *bitmap_offset_out,
82 unsigned long *bitmap_len_out,
83 int *data_offset_out);
84extern int read_cow_bitmap(int fd, void *buf, int offset, int len);
85extern void do_io(struct io_thread_req *req);
86
87static inline int ubd_test_bit(__u64 bit, unsigned char *data) 75static inline int ubd_test_bit(__u64 bit, unsigned char *data)
88{ 76{
89 __u64 n; 77 __u64 n;
@@ -200,7 +188,7 @@ struct ubd {
200} 188}
201 189
202/* Protected by ubd_lock */ 190/* Protected by ubd_lock */
203struct ubd ubd_devs[MAX_DEV] = { [ 0 ... MAX_DEV - 1 ] = DEFAULT_UBD }; 191static struct ubd ubd_devs[MAX_DEV] = { [0 ... MAX_DEV - 1] = DEFAULT_UBD };
204 192
205/* Only changed by fake_ide_setup which is a setup */ 193/* Only changed by fake_ide_setup which is a setup */
206static int fake_ide = 0; 194static int fake_ide = 0;
@@ -463,7 +451,7 @@ __uml_help(udb_setup,
463static void do_ubd_request(struct request_queue * q); 451static void do_ubd_request(struct request_queue * q);
464 452
465/* Only changed by ubd_init, which is an initcall. */ 453/* Only changed by ubd_init, which is an initcall. */
466int thread_fd = -1; 454static int thread_fd = -1;
467 455
468static void ubd_end_request(struct request *req, int bytes, int error) 456static void ubd_end_request(struct request *req, int bytes, int error)
469{ 457{
@@ -531,7 +519,7 @@ static irqreturn_t ubd_intr(int irq, void *dev)
531/* Only changed by ubd_init, which is an initcall. */ 519/* Only changed by ubd_init, which is an initcall. */
532static int io_pid = -1; 520static int io_pid = -1;
533 521
534void kill_io_thread(void) 522static void kill_io_thread(void)
535{ 523{
536 if(io_pid != -1) 524 if(io_pid != -1)
537 os_kill_process(io_pid, 1); 525 os_kill_process(io_pid, 1);
@@ -547,6 +535,192 @@ static inline int ubd_file_size(struct ubd *ubd_dev, __u64 *size_out)
547 return os_file_size(file, size_out); 535 return os_file_size(file, size_out);
548} 536}
549 537
538static int read_cow_bitmap(int fd, void *buf, int offset, int len)
539{
540 int err;
541
542 err = os_seek_file(fd, offset);
543 if (err < 0)
544 return err;
545
546 err = os_read_file(fd, buf, len);
547 if (err < 0)
548 return err;
549
550 return 0;
551}
552
553static int backing_file_mismatch(char *file, __u64 size, time_t mtime)
554{
555 unsigned long modtime;
556 unsigned long long actual;
557 int err;
558
559 err = os_file_modtime(file, &modtime);
560 if (err < 0) {
561 printk(KERN_ERR "Failed to get modification time of backing "
562 "file \"%s\", err = %d\n", file, -err);
563 return err;
564 }
565
566 err = os_file_size(file, &actual);
567 if (err < 0) {
568 printk(KERN_ERR "Failed to get size of backing file \"%s\", "
569 "err = %d\n", file, -err);
570 return err;
571 }
572
573 if (actual != size) {
574 /*__u64 can be a long on AMD64 and with %lu GCC complains; so
575 * the typecast.*/
576 printk(KERN_ERR "Size mismatch (%llu vs %llu) of COW header "
577 "vs backing file\n", (unsigned long long) size, actual);
578 return -EINVAL;
579 }
580 if (modtime != mtime) {
581 printk(KERN_ERR "mtime mismatch (%ld vs %ld) of COW header vs "
582 "backing file\n", mtime, modtime);
583 return -EINVAL;
584 }
585 return 0;
586}
587
588static int path_requires_switch(char *from_cmdline, char *from_cow, char *cow)
589{
590 struct uml_stat buf1, buf2;
591 int err;
592
593 if (from_cmdline == NULL)
594 return 0;
595 if (!strcmp(from_cmdline, from_cow))
596 return 0;
597
598 err = os_stat_file(from_cmdline, &buf1);
599 if (err < 0) {
600 printk(KERN_ERR "Couldn't stat '%s', err = %d\n", from_cmdline,
601 -err);
602 return 0;
603 }
604 err = os_stat_file(from_cow, &buf2);
605 if (err < 0) {
606 printk(KERN_ERR "Couldn't stat '%s', err = %d\n", from_cow,
607 -err);
608 return 1;
609 }
610 if ((buf1.ust_dev == buf2.ust_dev) && (buf1.ust_ino == buf2.ust_ino))
611 return 0;
612
613 printk(KERN_ERR "Backing file mismatch - \"%s\" requested, "
614 "\"%s\" specified in COW header of \"%s\"\n",
615 from_cmdline, from_cow, cow);
616 return 1;
617}
618
619static int open_ubd_file(char *file, struct openflags *openflags, int shared,
620 char **backing_file_out, int *bitmap_offset_out,
621 unsigned long *bitmap_len_out, int *data_offset_out,
622 int *create_cow_out)
623{
624 time_t mtime;
625 unsigned long long size;
626 __u32 version, align;
627 char *backing_file;
628 int fd, err, sectorsize, asked_switch, mode = 0644;
629
630 fd = os_open_file(file, *openflags, mode);
631 if (fd < 0) {
632 if ((fd == -ENOENT) && (create_cow_out != NULL))
633 *create_cow_out = 1;
634 if (!openflags->w ||
635 ((fd != -EROFS) && (fd != -EACCES)))
636 return fd;
637 openflags->w = 0;
638 fd = os_open_file(file, *openflags, mode);
639 if (fd < 0)
640 return fd;
641 }
642
643 if (shared)
644 printk(KERN_INFO "Not locking \"%s\" on the host\n", file);
645 else {
646 err = os_lock_file(fd, openflags->w);
647 if (err < 0) {
648 printk(KERN_ERR "Failed to lock '%s', err = %d\n",
649 file, -err);
650 goto out_close;
651 }
652 }
653
654 /* Successful return case! */
655 if (backing_file_out == NULL)
656 return fd;
657
658 err = read_cow_header(file_reader, &fd, &version, &backing_file, &mtime,
659 &size, &sectorsize, &align, bitmap_offset_out);
660 if (err && (*backing_file_out != NULL)) {
661 printk(KERN_ERR "Failed to read COW header from COW file "
662 "\"%s\", errno = %d\n", file, -err);
663 goto out_close;
664 }
665 if (err)
666 return fd;
667
668 asked_switch = path_requires_switch(*backing_file_out, backing_file,
669 file);
670
671 /* Allow switching only if no mismatch. */
672 if (asked_switch && !backing_file_mismatch(*backing_file_out, size,
673 mtime)) {
674 printk(KERN_ERR "Switching backing file to '%s'\n",
675 *backing_file_out);
676 err = write_cow_header(file, fd, *backing_file_out,
677 sectorsize, align, &size);
678 if (err) {
679 printk(KERN_ERR "Switch failed, errno = %d\n", -err);
680 goto out_close;
681 }
682 } else {
683 *backing_file_out = backing_file;
684 err = backing_file_mismatch(*backing_file_out, size, mtime);
685 if (err)
686 goto out_close;
687 }
688
689 cow_sizes(version, size, sectorsize, align, *bitmap_offset_out,
690 bitmap_len_out, data_offset_out);
691
692 return fd;
693 out_close:
694 os_close_file(fd);
695 return err;
696}
697
698static int create_cow_file(char *cow_file, char *backing_file,
699 struct openflags flags,
700 int sectorsize, int alignment, int *bitmap_offset_out,
701 unsigned long *bitmap_len_out, int *data_offset_out)
702{
703 int err, fd;
704
705 flags.c = 1;
706 fd = open_ubd_file(cow_file, &flags, 0, NULL, NULL, NULL, NULL, NULL);
707 if (fd < 0) {
708 err = fd;
709 printk(KERN_ERR "Open of COW file '%s' failed, errno = %d\n",
710 cow_file, -err);
711 goto out;
712 }
713
714 err = init_cow_file(fd, cow_file, backing_file, sectorsize, alignment,
715 bitmap_offset_out, bitmap_len_out,
716 data_offset_out);
717 if (!err)
718 return fd;
719 os_close_file(fd);
720 out:
721 return err;
722}
723
550static void ubd_close_dev(struct ubd *ubd_dev) 724static void ubd_close_dev(struct ubd *ubd_dev)
551{ 725{
552 os_close_file(ubd_dev->fd); 726 os_close_file(ubd_dev->fd);
@@ -1166,185 +1340,6 @@ static int ubd_ioctl(struct inode * inode, struct file * file,
1166 return -EINVAL; 1340 return -EINVAL;
1167} 1341}
1168 1342
1169static int path_requires_switch(char *from_cmdline, char *from_cow, char *cow)
1170{
1171 struct uml_stat buf1, buf2;
1172 int err;
1173
1174 if(from_cmdline == NULL)
1175 return 0;
1176 if(!strcmp(from_cmdline, from_cow))
1177 return 0;
1178
1179 err = os_stat_file(from_cmdline, &buf1);
1180 if(err < 0){
1181 printk("Couldn't stat '%s', err = %d\n", from_cmdline, -err);
1182 return 0;
1183 }
1184 err = os_stat_file(from_cow, &buf2);
1185 if(err < 0){
1186 printk("Couldn't stat '%s', err = %d\n", from_cow, -err);
1187 return 1;
1188 }
1189 if((buf1.ust_dev == buf2.ust_dev) && (buf1.ust_ino == buf2.ust_ino))
1190 return 0;
1191
1192 printk("Backing file mismatch - \"%s\" requested,\n"
1193 "\"%s\" specified in COW header of \"%s\"\n",
1194 from_cmdline, from_cow, cow);
1195 return 1;
1196}
1197
1198static int backing_file_mismatch(char *file, __u64 size, time_t mtime)
1199{
1200 unsigned long modtime;
1201 unsigned long long actual;
1202 int err;
1203
1204 err = os_file_modtime(file, &modtime);
1205 if(err < 0){
1206 printk("Failed to get modification time of backing file "
1207 "\"%s\", err = %d\n", file, -err);
1208 return err;
1209 }
1210
1211 err = os_file_size(file, &actual);
1212 if(err < 0){
1213 printk("Failed to get size of backing file \"%s\", "
1214 "err = %d\n", file, -err);
1215 return err;
1216 }
1217
1218 if(actual != size){
1219 /*__u64 can be a long on AMD64 and with %lu GCC complains; so
1220 * the typecast.*/
1221 printk("Size mismatch (%llu vs %llu) of COW header vs backing "
1222 "file\n", (unsigned long long) size, actual);
1223 return -EINVAL;
1224 }
1225 if(modtime != mtime){
1226 printk("mtime mismatch (%ld vs %ld) of COW header vs backing "
1227 "file\n", mtime, modtime);
1228 return -EINVAL;
1229 }
1230 return 0;
1231}
1232
1233int read_cow_bitmap(int fd, void *buf, int offset, int len)
1234{
1235 int err;
1236
1237 err = os_seek_file(fd, offset);
1238 if(err < 0)
1239 return err;
1240
1241 err = os_read_file(fd, buf, len);
1242 if(err < 0)
1243 return err;
1244
1245 return 0;
1246}
1247
1248int open_ubd_file(char *file, struct openflags *openflags, int shared,
1249 char **backing_file_out, int *bitmap_offset_out,
1250 unsigned long *bitmap_len_out, int *data_offset_out,
1251 int *create_cow_out)
1252{
1253 time_t mtime;
1254 unsigned long long size;
1255 __u32 version, align;
1256 char *backing_file;
1257 int fd, err, sectorsize, asked_switch, mode = 0644;
1258
1259 fd = os_open_file(file, *openflags, mode);
1260 if (fd < 0) {
1261 if ((fd == -ENOENT) && (create_cow_out != NULL))
1262 *create_cow_out = 1;
1263 if (!openflags->w ||
1264 ((fd != -EROFS) && (fd != -EACCES)))
1265 return fd;
1266 openflags->w = 0;
1267 fd = os_open_file(file, *openflags, mode);
1268 if (fd < 0)
1269 return fd;
1270 }
1271
1272 if(shared)
1273 printk("Not locking \"%s\" on the host\n", file);
1274 else {
1275 err = os_lock_file(fd, openflags->w);
1276 if(err < 0){
1277 printk("Failed to lock '%s', err = %d\n", file, -err);
1278 goto out_close;
1279 }
1280 }
1281
1282 /* Successful return case! */
1283 if(backing_file_out == NULL)
1284 return fd;
1285
1286 err = read_cow_header(file_reader, &fd, &version, &backing_file, &mtime,
1287 &size, &sectorsize, &align, bitmap_offset_out);
1288 if(err && (*backing_file_out != NULL)){
1289 printk("Failed to read COW header from COW file \"%s\", "
1290 "errno = %d\n", file, -err);
1291 goto out_close;
1292 }
1293 if(err)
1294 return fd;
1295
1296 asked_switch = path_requires_switch(*backing_file_out, backing_file, file);
1297
1298 /* Allow switching only if no mismatch. */
1299 if (asked_switch && !backing_file_mismatch(*backing_file_out, size, mtime)) {
1300 printk("Switching backing file to '%s'\n", *backing_file_out);
1301 err = write_cow_header(file, fd, *backing_file_out,
1302 sectorsize, align, &size);
1303 if (err) {
1304 printk("Switch failed, errno = %d\n", -err);
1305 goto out_close;
1306 }
1307 } else {
1308 *backing_file_out = backing_file;
1309 err = backing_file_mismatch(*backing_file_out, size, mtime);
1310 if (err)
1311 goto out_close;
1312 }
1313
1314 cow_sizes(version, size, sectorsize, align, *bitmap_offset_out,
1315 bitmap_len_out, data_offset_out);
1316
1317 return fd;
1318 out_close:
1319 os_close_file(fd);
1320 return err;
1321}
1322
1323int create_cow_file(char *cow_file, char *backing_file, struct openflags flags,
1324 int sectorsize, int alignment, int *bitmap_offset_out,
1325 unsigned long *bitmap_len_out, int *data_offset_out)
1326{
1327 int err, fd;
1328
1329 flags.c = 1;
1330 fd = open_ubd_file(cow_file, &flags, 0, NULL, NULL, NULL, NULL, NULL);
1331 if(fd < 0){
1332 err = fd;
1333 printk("Open of COW file '%s' failed, errno = %d\n", cow_file,
1334 -err);
1335 goto out;
1336 }
1337
1338 err = init_cow_file(fd, cow_file, backing_file, sectorsize, alignment,
1339 bitmap_offset_out, bitmap_len_out,
1340 data_offset_out);
1341 if(!err)
1342 return fd;
1343 os_close_file(fd);
1344 out:
1345 return err;
1346}
1347
1348static int update_bitmap(struct io_thread_req *req) 1343static int update_bitmap(struct io_thread_req *req)
1349{ 1344{
1350 int n; 1345 int n;
@@ -1369,7 +1364,7 @@ static int update_bitmap(struct io_thread_req *req)
1369 return 0; 1364 return 0;
1370} 1365}
1371 1366
1372void do_io(struct io_thread_req *req) 1367static void do_io(struct io_thread_req *req)
1373{ 1368{
1374 char *buf; 1369 char *buf;
1375 unsigned long len; 1370 unsigned long len;