ftp://ftp.kernel.org/pub/linux/kernel/v2.6/linux-2.6.6.tar.bz2
[linux-2.6.git] / arch / um / drivers / ubd_user.c
1 /* 
2  * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
3  * Copyright (C) 2001 Ridgerun,Inc (glonnon@ridgerun.com)
4  * Licensed under the GPL
5  */
6
7 #include <stddef.h>
8 #include <unistd.h>
9 #include <errno.h>
10 #include <sched.h>
11 #include <signal.h>
12 #include <string.h>
13 #include <netinet/in.h>
14 #include <sys/stat.h>
15 #include <sys/time.h>
16 #include <sys/fcntl.h>
17 #include <sys/socket.h>
18 #include <string.h>
19 #include <sys/mman.h>
20 #include <sys/param.h>
21 #include "asm/types.h"
22 #include "user_util.h"
23 #include "kern_util.h"
24 #include "user.h"
25 #include "ubd_user.h"
26 #include "os.h"
27
28 #include <endian.h>
29 #include <byteswap.h>
30 #if __BYTE_ORDER == __BIG_ENDIAN
31 # define ntohll(x) (x)
32 # define htonll(x) (x)
33 #elif __BYTE_ORDER == __LITTLE_ENDIAN
34 # define ntohll(x)  bswap_64(x)
35 # define htonll(x)  bswap_64(x)
36 #else
37 #error "__BYTE_ORDER not defined"
38 #endif
39
40 #define PATH_LEN_V1 256
41
42 struct cow_header_v1 {
43         int magic;
44         int version;
45         char backing_file[PATH_LEN_V1];
46         time_t mtime;
47         __u64 size;
48         int sectorsize;
49 };
50
51 #define PATH_LEN_V2 MAXPATHLEN
52
53 struct cow_header_v2 {
54         unsigned long magic;
55         unsigned long version;
56         char backing_file[PATH_LEN_V2];
57         time_t mtime;
58         __u64 size;
59         int sectorsize;
60 };
61
62 union cow_header {
63         struct cow_header_v1 v1;
64         struct cow_header_v2 v2;
65 };
66
67 #define COW_MAGIC 0x4f4f4f4d  /* MOOO */
68 #define COW_VERSION 2
69
70 static void sizes(__u64 size, int sectorsize, int bitmap_offset, 
71                   unsigned long *bitmap_len_out, int *data_offset_out)
72 {
73         *bitmap_len_out = (size + sectorsize - 1) / (8 * sectorsize);
74
75         *data_offset_out = bitmap_offset + *bitmap_len_out;
76         *data_offset_out = (*data_offset_out + sectorsize - 1) / sectorsize;
77         *data_offset_out *= sectorsize;
78 }
79
80 static int read_cow_header(int fd, int *magic_out, char **backing_file_out, 
81                            time_t *mtime_out, __u64 *size_out, 
82                            int *sectorsize_out, int *bitmap_offset_out)
83 {
84         union cow_header *header;
85         char *file;
86         int err, n;
87         unsigned long version, magic;
88
89         header = um_kmalloc(sizeof(*header));
90         if(header == NULL){
91                 printk("read_cow_header - Failed to allocate header\n");
92                 return(-ENOMEM);
93         }
94         err = -EINVAL;
95         n = read(fd, header, sizeof(*header));
96         if(n < offsetof(typeof(header->v1), backing_file)){
97                 printk("read_cow_header - short header\n");
98                 goto out;
99         }
100
101         magic = header->v1.magic;
102         if(magic == COW_MAGIC) {
103                 version = header->v1.version;
104         }
105         else if(magic == ntohl(COW_MAGIC)){
106                 version = ntohl(header->v1.version);
107         }
108         else goto out;
109
110         *magic_out = COW_MAGIC;
111
112         if(version == 1){
113                 if(n < sizeof(header->v1)){
114                         printk("read_cow_header - failed to read V1 header\n");
115                         goto out;
116                 }
117                 *mtime_out = header->v1.mtime;
118                 *size_out = header->v1.size;
119                 *sectorsize_out = header->v1.sectorsize;
120                 *bitmap_offset_out = sizeof(header->v1);
121                 file = header->v1.backing_file;
122         }
123         else if(version == 2){
124                 if(n < sizeof(header->v2)){
125                         printk("read_cow_header - failed to read V2 header\n");
126                         goto out;
127                 }
128                 *mtime_out = ntohl(header->v2.mtime);
129                 *size_out = ntohll(header->v2.size);
130                 *sectorsize_out = ntohl(header->v2.sectorsize);
131                 *bitmap_offset_out = sizeof(header->v2);
132                 file = header->v2.backing_file;
133         }
134         else {
135                 printk("read_cow_header - invalid COW version\n");
136                 goto out;
137         }
138         err = -ENOMEM;
139         *backing_file_out = uml_strdup(file);
140         if(*backing_file_out == NULL){
141                 printk("read_cow_header - failed to allocate backing file\n");
142                 goto out;
143         }
144         err = 0;
145  out:
146         kfree(header);
147         return(err);
148 }
149
150 static int same_backing_files(char *from_cmdline, char *from_cow, char *cow)
151 {
152         struct stat buf1, buf2;
153
154         if(from_cmdline == NULL) return(1);
155         if(!strcmp(from_cmdline, from_cow)) return(1);
156
157         if(stat(from_cmdline, &buf1) < 0){
158                 printk("Couldn't stat '%s', errno = %d\n", from_cmdline, 
159                        errno);
160                 return(1);
161         }
162         if(stat(from_cow, &buf2) < 0){
163                 printk("Couldn't stat '%s', errno = %d\n", from_cow, errno);
164                 return(1);
165         }
166         if((buf1.st_dev == buf2.st_dev) && (buf1.st_ino == buf2.st_ino))
167                 return(1);
168
169         printk("Backing file mismatch - \"%s\" requested,\n"
170                "\"%s\" specified in COW header of \"%s\"\n",
171                from_cmdline, from_cow, cow);
172         return(0);
173 }
174
175 static int backing_file_mismatch(char *file, __u64 size, time_t mtime)
176 {
177         struct stat64 buf;
178         long long actual;
179         int err;
180
181         if(stat64(file, &buf) < 0){
182                 printk("Failed to stat backing file \"%s\", errno = %d\n",
183                        file, errno);
184                 return(-errno);
185         }
186
187         err = os_file_size(file, &actual);
188         if(err){
189                 printk("Failed to get size of backing file \"%s\", "
190                        "errno = %d\n", file, -err);
191                 return(err);
192         }
193
194         if(actual != size){
195                 printk("Size mismatch (%ld vs %ld) of COW header vs backing "
196                        "file\n", size, actual);
197                 return(-EINVAL);
198         }
199         if(buf.st_mtime != mtime){
200                 printk("mtime mismatch (%ld vs %ld) of COW header vs backing "
201                        "file\n", mtime, buf.st_mtime);
202                 return(-EINVAL);
203         }
204         return(0);
205 }
206
207 int read_cow_bitmap(int fd, void *buf, int offset, int len)
208 {
209         int err;
210
211         err = os_seek_file(fd, offset);
212         if(err != 0) return(-errno);
213         err = read(fd, buf, len);
214         if(err < 0) return(-errno);
215         return(0);
216 }
217
218 static int absolutize(char *to, int size, char *from)
219 {
220         char save_cwd[256], *slash;
221         int remaining;
222
223         if(getcwd(save_cwd, sizeof(save_cwd)) == NULL) {
224                 printk("absolutize : unable to get cwd - errno = %d\n", errno);
225                 return(-1);
226         }
227         slash = strrchr(from, '/');
228         if(slash != NULL){
229                 *slash = '\0';
230                 if(chdir(from)){
231                         *slash = '/';
232                         printk("absolutize : Can't cd to '%s' - errno = %d\n",
233                                from, errno);
234                         return(-1);
235                 }
236                 *slash = '/';
237                 if(getcwd(to, size) == NULL){
238                         printk("absolutize : unable to get cwd of '%s' - "
239                                "errno = %d\n", from, errno);
240                         return(-1);
241                 }
242                 remaining = size - strlen(to);
243                 if(strlen(slash) + 1 > remaining){
244                         printk("absolutize : unable to fit '%s' into %d "
245                                "chars\n", from, size);
246                         return(-1);
247                 }
248                 strcat(to, slash);
249         }
250         else {
251                 if(strlen(save_cwd) + 1 + strlen(from) + 1 > size){
252                         printk("absolutize : unable to fit '%s' into %d "
253                                "chars\n", from, size);
254                         return(-1);
255                 }
256                 strcpy(to, save_cwd);
257                 strcat(to, "/");
258                 strcat(to, from);
259         }
260         chdir(save_cwd);
261         return(0);
262 }
263
264 static int write_cow_header(char *cow_file, int fd, char *backing_file, 
265                             int sectorsize, long long *size)
266 {
267         struct cow_header_v2 *header;
268         struct stat64 buf;
269         int err;
270
271         err = os_seek_file(fd, 0);
272         if(err != 0){
273                 printk("write_cow_header - lseek failed, errno = %d\n", errno);
274                 return(-errno);
275         }
276
277         err = -ENOMEM;
278         header = um_kmalloc(sizeof(*header));
279         if(header == NULL){
280                 printk("Failed to allocate COW V2 header\n");
281                 goto out;
282         }
283         header->magic = htonl(COW_MAGIC);
284         header->version = htonl(COW_VERSION);
285
286         err = -EINVAL;
287         if(strlen(backing_file) > sizeof(header->backing_file) - 1){
288                 printk("Backing file name \"%s\" is too long - names are "
289                        "limited to %d characters\n", backing_file, 
290                        sizeof(header->backing_file) - 1);
291                 goto out_free;
292         }
293
294         if(absolutize(header->backing_file, sizeof(header->backing_file), 
295                       backing_file))
296                 goto out_free;
297
298         err = stat64(header->backing_file, &buf);
299         if(err < 0){
300                 printk("Stat of backing file '%s' failed, errno = %d\n",
301                        header->backing_file, errno);
302                 err = -errno;
303                 goto out_free;
304         }
305
306         err = os_file_size(header->backing_file, size);
307         if(err){
308                 printk("Couldn't get size of backing file '%s', errno = %d\n",
309                        header->backing_file, -*size);
310                 goto out_free;
311         }
312
313         header->mtime = htonl(buf.st_mtime);
314         header->size = htonll(*size);
315         header->sectorsize = htonl(sectorsize);
316
317         err = write(fd, header, sizeof(*header));
318         if(err != sizeof(*header)){
319                 printk("Write of header to new COW file '%s' failed, "
320                        "errno = %d\n", cow_file, errno);
321                 goto out_free;
322         }
323         err = 0;
324  out_free:
325         kfree(header);
326  out:
327         return(err);
328 }
329
330 int open_ubd_file(char *file, struct openflags *openflags, 
331                   char **backing_file_out, int *bitmap_offset_out, 
332                   unsigned long *bitmap_len_out, int *data_offset_out, 
333                   int *create_cow_out)
334 {
335         time_t mtime;
336         __u64 size;
337         char *backing_file;
338         int fd, err, sectorsize, magic, same, mode = 0644;
339
340         if((fd = os_open_file(file, *openflags, mode)) < 0){
341                 if((fd == -ENOENT) && (create_cow_out != NULL))
342                         *create_cow_out = 1;
343                 if(!openflags->w ||
344                    ((errno != EROFS) && (errno != EACCES))) return(-errno);
345                 openflags->w = 0;
346                 if((fd = os_open_file(file, *openflags, mode)) < 0) 
347                         return(fd);
348         }
349         if(backing_file_out == NULL) return(fd);
350
351         err = read_cow_header(fd, &magic, &backing_file, &mtime, &size, 
352                               &sectorsize, bitmap_offset_out);
353         if(err && (*backing_file_out != NULL)){
354                 printk("Failed to read COW header from COW file \"%s\", "
355                        "errno = %d\n", file, err);
356                 goto error;
357         }
358         if(err) return(fd);
359
360         if(backing_file_out == NULL) return(fd);
361         
362         same = same_backing_files(*backing_file_out, backing_file, file);
363
364         if(!same && !backing_file_mismatch(*backing_file_out, size, mtime)){
365                 printk("Switching backing file to '%s'\n", *backing_file_out);
366                 err = write_cow_header(file, fd, *backing_file_out, 
367                                        sectorsize, &size);
368                 if(err){
369                         printk("Switch failed, errno = %d\n", err);
370                         return(err);
371                 }
372         }
373         else {
374                 *backing_file_out = backing_file;
375                 err = backing_file_mismatch(*backing_file_out, size, mtime);
376                 if(err) goto error;
377         }
378
379         sizes(size, sectorsize, *bitmap_offset_out, bitmap_len_out, 
380               data_offset_out);
381
382         return(fd);
383  error:
384         close(fd);
385         return(err);
386 }
387
388 int create_cow_file(char *cow_file, char *backing_file, struct openflags flags,
389                     int sectorsize, int *bitmap_offset_out, 
390                     unsigned long *bitmap_len_out, int *data_offset_out)
391 {
392         __u64 blocks;
393         long zero;
394         int err, fd, i;
395         long long size;
396
397         flags.c = 1;
398         fd = open_ubd_file(cow_file, &flags, NULL, NULL, NULL, NULL, NULL);
399         if(fd < 0){
400                 err = fd;
401                 printk("Open of COW file '%s' failed, errno = %d\n", cow_file,
402                        -err);
403                 goto out;
404         }
405
406         err = write_cow_header(cow_file, fd, backing_file, sectorsize, &size);
407         if(err) goto out_close;
408
409         blocks = (size + sectorsize - 1) / sectorsize;
410         blocks = (blocks + sizeof(long) * 8 - 1) / (sizeof(long) * 8);
411         zero = 0;
412         for(i = 0; i < blocks; i++){
413                 err = write(fd, &zero, sizeof(zero));
414                 if(err != sizeof(zero)){
415                         printk("Write of bitmap to new COW file '%s' failed, "
416                                "errno = %d\n", cow_file, errno);
417                         goto out_close;
418                 }
419         }
420
421         sizes(size, sectorsize, sizeof(struct cow_header_v2), 
422               bitmap_len_out, data_offset_out);
423         *bitmap_offset_out = sizeof(struct cow_header_v2);
424
425         return(fd);
426
427  out_close:
428         close(fd);
429  out:
430         return(err);
431 }
432
433 int read_ubd_fs(int fd, void *buffer, int len)
434 {
435         int n;
436
437         n = read(fd, buffer, len);
438         if(n < 0) return(-errno);
439         else return(n);
440 }
441
442 int write_ubd_fs(int fd, char *buffer, int len)
443 {
444         int n;
445
446         n = write(fd, buffer, len);
447         if(n < 0) return(-errno);
448         else return(n);
449 }
450
451 int ubd_is_dir(char *file)
452 {
453         struct stat64 buf;
454
455         if(stat64(file, &buf) < 0) return(0);
456         return(S_ISDIR(buf.st_mode));
457 }
458
459 void do_io(struct io_thread_req *req)
460 {
461         char *buf;
462         unsigned long len;
463         int n, nsectors, start, end, bit;
464         __u64 off;
465
466         nsectors = req->length / req->sectorsize;
467         start = 0;
468         do {
469                 bit = ubd_test_bit(start, (unsigned char *) &req->sector_mask);
470                 end = start;
471                 while((end < nsectors) && 
472                       (ubd_test_bit(end, (unsigned char *) 
473                                     &req->sector_mask) == bit))
474                         end++;
475
476                 if(end != nsectors)
477                         printk("end != nsectors\n");
478                 off = req->offset + req->offsets[bit] + 
479                         start * req->sectorsize;
480                 len = (end - start) * req->sectorsize;
481                 buf = &req->buffer[start * req->sectorsize];
482
483                 if(os_seek_file(req->fds[bit], off) != 0){
484                         printk("do_io - lseek failed : errno = %d\n", errno);
485                         req->error = 1;
486                         return;
487                 }
488                 if(req->op == UBD_READ){
489                         n = 0;
490                         do {
491                                 buf = &buf[n];
492                                 len -= n;
493                                 n = read(req->fds[bit], buf, len);
494                                 if (n < 0) {
495                                         printk("do_io - read returned %d : "
496                                                "errno = %d fd = %d\n", n,
497                                                errno, req->fds[bit]);
498                                         req->error = 1;
499                                         return;
500                                 }
501                         } while((n < len) && (n != 0));
502                         if (n < len) memset(&buf[n], 0, len - n);
503                 }
504                 else {
505                         n = write(req->fds[bit], buf, len);
506                         if(n != len){
507                                 printk("do_io - write returned %d : "
508                                        "errno = %d fd = %d\n", n, 
509                                        errno, req->fds[bit]);
510                                 req->error = 1;
511                                 return;
512                         }
513                 }
514
515                 start = end;
516         } while(start < nsectors);
517
518         if(req->cow_offset != -1){
519                 if(os_seek_file(req->fds[1], req->cow_offset) != 0){
520                         printk("do_io - bitmap lseek failed : errno = %d\n",
521                                errno);
522                         req->error = 1;
523                         return;
524                 }
525                 n = write(req->fds[1], &req->bitmap_words, 
526                           sizeof(req->bitmap_words));
527                 if(n != sizeof(req->bitmap_words)){
528                         printk("do_io - bitmap update returned %d : "
529                                "errno = %d fd = %d\n", n, errno, req->fds[1]);
530                         req->error = 1;
531                         return;
532                 }
533         }
534         req->error = 0;
535         return;
536 }
537
538 /* Changed in start_io_thread, which is serialized by being called only
539  * from ubd_init, which is an initcall.
540  */
541 int kernel_fd = -1;
542
543 /* Only changed by the io thread */
544 int io_count = 0;
545
546 int io_thread(void *arg)
547 {
548         struct io_thread_req req;
549         int n;
550
551         signal(SIGWINCH, SIG_IGN);
552         while(1){
553                 n = read(kernel_fd, &req, sizeof(req));
554                 if(n < 0) printk("io_thread - read returned %d, errno = %d\n",
555                                  n, errno);
556                 else if(n < sizeof(req)){
557                         printk("io_thread - short read : length = %d\n", n);
558                         continue;
559                 }
560                 io_count++;
561                 do_io(&req);
562                 n = write(kernel_fd, &req, sizeof(req));
563                 if(n != sizeof(req))
564                         printk("io_thread - write failed, errno = %d\n",
565                                errno);
566         }
567 }
568
569 int start_io_thread(unsigned long sp, int *fd_out)
570 {
571         int pid, fds[2], err;
572
573         err = os_pipe(fds, 1, 1);
574         if(err){
575                 printk("start_io_thread - os_pipe failed, errno = %d\n", -err);
576                 return(-1);
577         }
578         kernel_fd = fds[0];
579         *fd_out = fds[1];
580
581         pid = clone(io_thread, (void *) sp, CLONE_FILES | CLONE_VM | SIGCHLD,
582                     NULL);
583         if(pid < 0){
584                 printk("start_io_thread - clone failed : errno = %d\n", errno);
585                 return(-errno);
586         }
587         return(pid);
588 }
589
590 #ifdef notdef
591 int start_io_thread(unsigned long sp, int *fd_out)
592 {
593         int pid;
594
595         if((kernel_fd = get_pty()) < 0) return(-1);
596         raw(kernel_fd, 0);
597         if((*fd_out = open(ptsname(kernel_fd), O_RDWR)) < 0){
598                 printk("Couldn't open tty for IO\n");
599                 return(-1);
600         }
601
602         pid = clone(io_thread, (void *) sp, CLONE_FILES | CLONE_VM | SIGCHLD,
603                     NULL);
604         if(pid < 0){
605                 printk("start_io_thread - clone failed : errno = %d\n", errno);
606                 return(-errno);
607         }
608         return(pid);
609 }
610 #endif
611
612 /*
613  * Overrides for Emacs so that we follow Linus's tabbing style.
614  * Emacs will notice this stuff at the end of the file and automatically
615  * adjust the settings for this buffer only.  This must remain at the end
616  * of the file.
617  * ---------------------------------------------------------------------------
618  * Local variables:
619  * c-file-style: "linux"
620  * End:
621  */