This commit was manufactured by cvs2svn to create tag
[linux-2.6.git] / arch / um / drivers / cow_kern.c
1 #define COW_MAJOR 60
2 #define MAJOR_NR COW_MAJOR
3
4 #include <linux/stddef.h>
5 #include <linux/kernel.h>
6 #include <linux/ctype.h>
7 #include <linux/stat.h>
8 #include <linux/vmalloc.h>
9 #include <linux/blkdev.h>
10 #include <linux/blk.h>
11 #include <linux/fs.h>
12 #include <linux/genhd.h>
13 #include <linux/devfs_fs.h>
14 #include <asm/uaccess.h>
15 #include "2_5compat.h"
16 #include "cow.h"
17 #include "ubd_user.h"
18
19 #define COW_SHIFT 4
20
21 struct cow {
22         int count;
23         char *cow_path;
24         dev_t cow_dev;
25         struct block_device *cow_bdev;
26         char *backing_path;
27         dev_t backing_dev;
28         struct block_device *backing_bdev;
29         int sectorsize;
30         unsigned long *bitmap;
31         unsigned long bitmap_len;
32         int bitmap_offset;
33         int data_offset;
34         devfs_handle_t devfs;
35         struct semaphore sem;
36         struct semaphore io_sem;
37         atomic_t working;
38         spinlock_t io_lock;
39         struct buffer_head *bh;
40         struct buffer_head *bhtail;
41         void *end_io;
42 };
43
44 #define DEFAULT_COW { \
45         .count                  = 0, \
46         .cow_path               = NULL, \
47         .cow_dev                = 0, \
48         .backing_path           = NULL, \
49         .backing_dev            = 0, \
50         .bitmap                 = NULL, \
51         .bitmap_len             = 0, \
52         .bitmap_offset          = 0, \
53         .data_offset            = 0, \
54         .devfs                  = NULL, \
55         .working                = ATOMIC_INIT(0), \
56         .io_lock                = SPIN_LOCK_UNLOCKED, \
57 }
58
59 #define MAX_DEV (8)
60 #define MAX_MINOR (MAX_DEV << COW_SHIFT)
61
62 struct cow cow_dev[MAX_DEV] = { [ 0 ... MAX_DEV - 1 ] = DEFAULT_COW };
63
64 /* Not modified by this driver */
65 static int blk_sizes[MAX_MINOR] = { [ 0 ... MAX_MINOR - 1 ] = BLOCK_SIZE };
66 static int hardsect_sizes[MAX_MINOR] = { [ 0 ... MAX_MINOR - 1 ] = 512 };
67
68 /* Protected by cow_lock */
69 static int sizes[MAX_MINOR] = { [ 0 ... MAX_MINOR - 1 ] = 0 };
70
71 static struct hd_struct cow_part[MAX_MINOR] =
72         { [ 0 ... MAX_MINOR - 1 ] = { 0, 0, 0 } };
73
74 /* Protected by io_request_lock */
75 static request_queue_t *cow_queue;
76
77 static int cow_open(struct inode *inode, struct file *filp);
78 static int cow_release(struct inode * inode, struct file * file);
79 static int cow_ioctl(struct inode * inode, struct file * file,
80                      unsigned int cmd, unsigned long arg);
81 static int cow_revalidate(kdev_t rdev);
82
83 static struct block_device_operations cow_blops = {
84         .open           = cow_open,
85         .release        = cow_release,
86         .ioctl          = cow_ioctl,
87         .revalidate     = cow_revalidate,
88 };
89
90 /* Initialized in an initcall, and unchanged thereafter */
91 devfs_handle_t cow_dir_handle;
92
93 #define INIT_GENDISK(maj, name, parts, shift, bsizes, max, blops) \
94 { \
95         .major          = maj, \
96         .major_name     = name, \
97         .minor_shift    = shift, \
98         .max_p          = 1 << shift, \
99         .part           = parts, \
100         .sizes          = bsizes, \
101         .nr_real        = max, \
102         .real_devices   = NULL, \
103         .next           = NULL, \
104         .fops           = blops, \
105         .de_arr         = NULL, \
106         .flags          = 0 \
107 }
108
109 static spinlock_t cow_lock = SPIN_LOCK_UNLOCKED;
110
111 static struct gendisk cow_gendisk = INIT_GENDISK(MAJOR_NR, "cow", cow_part,
112                                                  COW_SHIFT, sizes, MAX_DEV, 
113                                                  &cow_blops);
114
115 static int cow_add(int n)
116 {
117         struct cow *dev = &cow_dev[n];
118         char name[sizeof("nnnnnn\0")];
119         int err = -ENODEV;
120
121         if(dev->cow_path == NULL)
122                 goto out;
123
124         sprintf(name, "%d", n);
125         dev->devfs = devfs_register(cow_dir_handle, name, DEVFS_FL_REMOVABLE,
126                                     MAJOR_NR, n << COW_SHIFT, S_IFBLK | 
127                                     S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP,
128                                     &cow_blops, NULL);
129
130         init_MUTEX_LOCKED(&dev->sem);
131         init_MUTEX(&dev->io_sem);
132
133         return(0);
134
135  out:
136         return(err);
137 }
138
139 /*
140  * Add buffer_head to back of pending list
141  */
142 static void cow_add_bh(struct cow *cow, struct buffer_head *bh)
143 {
144         unsigned long flags;
145
146         spin_lock_irqsave(&cow->io_lock, flags);
147         if(cow->bhtail != NULL){
148                 cow->bhtail->b_reqnext = bh;
149                 cow->bhtail = bh;
150         }
151         else {
152                 cow->bh = bh;
153                 cow->bhtail = bh;
154         }
155         spin_unlock_irqrestore(&cow->io_lock, flags);
156 }
157
158 /*
159 * Grab first pending buffer
160 */
161 static struct buffer_head *cow_get_bh(struct cow *cow)
162 {
163         struct buffer_head *bh;
164
165         spin_lock_irq(&cow->io_lock);
166         bh = cow->bh;
167         if(bh != NULL){
168                 if(bh == cow->bhtail)
169                         cow->bhtail = NULL;
170                 cow->bh = bh->b_reqnext;
171                 bh->b_reqnext = NULL;
172         }
173         spin_unlock_irq(&cow->io_lock);
174
175         return(bh);
176 }
177
178 static void cow_handle_bh(struct cow *cow, struct buffer_head *bh, 
179                           struct buffer_head **cow_bh, int ncow_bh)
180 {
181         int i;
182
183         if(ncow_bh > 0)
184                 ll_rw_block(WRITE, ncow_bh, cow_bh);
185
186         for(i = 0; i < ncow_bh ; i++){
187                 wait_on_buffer(cow_bh[i]);
188                 brelse(cow_bh[i]);
189         }
190
191         ll_rw_block(WRITE, 1, &bh);
192         brelse(bh);
193 }
194
195 static struct buffer_head *cow_new_bh(struct cow *dev, int sector)
196 {
197         struct buffer_head *bh;
198
199         sector = (dev->bitmap_offset + sector / 8) / dev->sectorsize;
200         bh = getblk(dev->cow_dev, sector, dev->sectorsize);
201         memcpy(bh->b_data, dev->bitmap + sector / (8 * sizeof(dev->bitmap[0])),
202                dev->sectorsize);
203         return(bh);
204 }
205
206 /* Copied from loop.c, needed to avoid deadlocking in make_request. */
207
208 static int cow_thread(void *data)
209 {
210         struct cow *dev = data;
211         struct buffer_head *bh;
212
213         daemonize();
214         exit_files(current);
215
216         sprintf(current->comm, "cow%d", dev - cow_dev);
217
218         spin_lock_irq(&current->sigmask_lock);
219         sigfillset(&current->blocked);
220         flush_signals(current);
221         spin_unlock_irq(&current->sigmask_lock);
222
223         atomic_inc(&dev->working);
224
225         current->policy = SCHED_OTHER;
226         current->nice = -20;
227
228         current->flags |= PF_NOIO;
229
230         /*
231          * up sem, we are running
232          */
233         up(&dev->sem);
234
235         for(;;){
236                 int start, len, nbh, i, update_bitmap = 0;
237                 struct buffer_head *cow_bh[2];
238
239                 down_interruptible(&dev->io_sem);
240                 /*
241                  * could be upped because of tear-down, not because of
242                  * pending work
243                  */
244                 if(!atomic_read(&dev->working))
245                         break;
246
247                 bh = cow_get_bh(dev);
248                 if(bh == NULL){
249                         printk(KERN_ERR "cow: missing bh\n");
250                         continue;
251                 }
252
253                 start = bh->b_blocknr * bh->b_size / dev->sectorsize;
254                 len = bh->b_size / dev->sectorsize;
255                 for(i = 0; i < len ; i++){
256                         if(ubd_test_bit(start + i, 
257                                         (unsigned char *) dev->bitmap))
258                                 continue;
259
260                         update_bitmap = 1;
261                         ubd_set_bit(start + i, (unsigned char *) dev->bitmap);
262                 }
263
264                 cow_bh[0] = NULL;
265                 cow_bh[1] = NULL;
266                 nbh = 0;
267                 if(update_bitmap){
268                         cow_bh[0] = cow_new_bh(dev, start);
269                         nbh++;
270                         if(start / dev->sectorsize != 
271                            (start + len) / dev->sectorsize){
272                                 cow_bh[1] = cow_new_bh(dev, start + len);
273                                 nbh++;
274                         }
275                 }
276                 
277                 bh->b_dev = dev->cow_dev;
278                 bh->b_blocknr += dev->data_offset / dev->sectorsize;
279
280                 cow_handle_bh(dev, bh, cow_bh, nbh);
281
282                 /*
283                  * upped both for pending work and tear-down, lo_pending
284                  * will hit zero then
285                  */
286                 if(atomic_dec_and_test(&dev->working))
287                         break;
288         }
289
290         up(&dev->sem);
291         return(0);
292 }
293
294 static int cow_make_request(request_queue_t *q, int rw, struct buffer_head *bh)
295 {
296         struct cow *dev;
297         int n, minor;
298
299         minor = MINOR(bh->b_rdev);
300         n = minor >> COW_SHIFT;
301         dev = &cow_dev[n];
302
303         dev->end_io = NULL;
304         if(ubd_test_bit(bh->b_rsector, (unsigned char *) dev->bitmap)){
305                 bh->b_rdev = dev->cow_dev;
306                 bh->b_rsector += dev->data_offset / dev->sectorsize;
307         }
308         else if(rw == WRITE){
309                 bh->b_dev = dev->cow_dev;
310                 bh->b_blocknr += dev->data_offset / dev->sectorsize;
311
312                 cow_add_bh(dev, bh);
313                 up(&dev->io_sem);
314                 return(0);
315         }
316         else {
317                 bh->b_rdev = dev->backing_dev;
318         }
319
320         return(1);
321 }
322
323 int cow_init(void)
324 {
325         int i;
326
327         cow_dir_handle = devfs_mk_dir (NULL, "cow", NULL);
328         if (devfs_register_blkdev(MAJOR_NR, "cow", &cow_blops)) {
329                 printk(KERN_ERR "cow: unable to get major %d\n", MAJOR_NR);
330                 return -1;
331         }
332         read_ahead[MAJOR_NR] = 8;               /* 8 sector (4kB) read-ahead */
333         blksize_size[MAJOR_NR] = blk_sizes;
334         blk_size[MAJOR_NR] = sizes;
335         INIT_HARDSECT(hardsect_size, MAJOR_NR, hardsect_sizes);
336
337         cow_queue = BLK_DEFAULT_QUEUE(MAJOR_NR);
338         blk_init_queue(cow_queue, NULL);
339         INIT_ELV(cow_queue, &cow_queue->elevator);
340         blk_queue_make_request(cow_queue, cow_make_request);
341
342         add_gendisk(&cow_gendisk);
343
344         for(i=0;i<MAX_DEV;i++) 
345                 cow_add(i);
346
347         return(0);
348 }
349
350 __initcall(cow_init);
351
352 static int reader(__u64 start, char *buf, int count, void *arg)
353 {
354         dev_t dev = *((dev_t *) arg);
355         struct buffer_head *bh;
356         __u64 block;
357         int cur, offset, left, n, blocksize = get_hardsect_size(dev);
358
359         if(blocksize == 0)
360                 panic("Zero blocksize");
361
362         block = start / blocksize;
363         offset = start % blocksize;
364         left = count;
365         cur = 0;
366         while(left > 0){
367                 n = (left > blocksize) ? blocksize : left;
368
369                 bh = bread(dev, block, (n < 512) ? 512 : n);
370                 if(bh == NULL)
371                         return(-EIO);
372
373                 n -= offset;
374                 memcpy(&buf[cur], bh->b_data + offset, n);
375                 block++;
376                 left -= n;
377                 cur += n;
378                 offset = 0;
379                 brelse(bh);
380         }
381
382         return(count);
383 }
384
385 static int cow_open(struct inode *inode, struct file *filp)
386 {
387         int (*dev_ioctl)(struct inode *, struct file *, unsigned int, 
388                          unsigned long);
389         mm_segment_t fs;
390         struct cow *dev;
391         __u64 size;
392         __u32 version, align;
393         time_t mtime;
394         char *backing_file;
395         int n, offset, err = 0;
396
397         n = DEVICE_NR(inode->i_rdev);
398         if(n >= MAX_DEV)
399                 return(-ENODEV);
400         dev = &cow_dev[n];
401         offset = n << COW_SHIFT;
402
403         spin_lock(&cow_lock);
404
405         if(dev->count == 0){
406                 dev->cow_dev = name_to_kdev_t(dev->cow_path);
407                 if(dev->cow_dev == 0){
408                         printk(KERN_ERR "cow_open - name_to_kdev_t(\"%s\") "
409                                "failed\n", dev->cow_path);
410                         err = -ENODEV;
411                 }
412
413                 dev->backing_dev = name_to_kdev_t(dev->backing_path);
414                 if(dev->backing_dev == 0){
415                         printk(KERN_ERR "cow_open - name_to_kdev_t(\"%s\") "
416                                "failed\n", dev->backing_path);
417                         err = -ENODEV;
418                 }
419
420                 if(err) 
421                         goto out;
422
423                 dev->cow_bdev = bdget(dev->cow_dev);
424                 if(dev->cow_bdev == NULL){
425                         printk(KERN_ERR "cow_open - bdget(\"%s\") failed\n", 
426                                dev->cow_path);
427                         err = -ENOMEM;
428                 }
429                 dev->backing_bdev = bdget(dev->backing_dev);
430                 if(dev->backing_bdev == NULL){
431                         printk(KERN_ERR "cow_open - bdget(\"%s\") failed\n", 
432                                dev->backing_path);
433                         err = -ENOMEM;
434                 }
435
436                 if(err) 
437                         goto out;
438
439                 err = blkdev_get(dev->cow_bdev, FMODE_READ|FMODE_WRITE, 0, 
440                                  BDEV_RAW);
441                 if(err){
442                         printk("cow_open - blkdev_get of COW device failed, "
443                                "error = %d\n", err);
444                         goto out;
445                 }
446                 
447                 err = blkdev_get(dev->backing_bdev, FMODE_READ, 0, BDEV_RAW);
448                 if(err){
449                         printk("cow_open - blkdev_get of backing device "
450                                "failed, error = %d\n", err);
451                         goto out;
452                 }
453                 
454                 err = read_cow_header(reader, &dev->cow_dev, &version, 
455                                       &backing_file, &mtime, &size,
456                                       &dev->sectorsize, &align, 
457                                       &dev->bitmap_offset);
458                 if(err){
459                         printk(KERN_ERR "cow_open - read_cow_header failed, "
460                                "err = %d\n", err);
461                         goto out;
462                 }
463
464                 cow_sizes(version, size, dev->sectorsize, align, 
465                           dev->bitmap_offset, &dev->bitmap_len, 
466                           &dev->data_offset);
467                 dev->bitmap = (void *) vmalloc(dev->bitmap_len);
468                 if(dev->bitmap == NULL){
469                         err = -ENOMEM;
470                         printk(KERN_ERR "Failed to vmalloc COW bitmap\n");
471                         goto out;
472                 }
473                 flush_tlb_kernel_vm();
474                 
475                 err = reader(dev->bitmap_offset, (char *) dev->bitmap, 
476                              dev->bitmap_len, &dev->cow_dev);
477                 if(err < 0){
478                         printk(KERN_ERR "Failed to read COW bitmap\n");
479                         vfree(dev->bitmap);
480                         goto out;
481                 }
482
483                 dev_ioctl = dev->backing_bdev->bd_op->ioctl;
484                 fs = get_fs();
485                 set_fs(KERNEL_DS);
486                 err = (*dev_ioctl)(inode, filp, BLKGETSIZE, 
487                                    (unsigned long) &sizes[offset]);
488                 set_fs(fs);
489                 if(err){
490                         printk(KERN_ERR "cow_open - BLKGETSIZE failed, "
491                                "error = %d\n", err);
492                         goto out;
493                 }
494
495                 kernel_thread(cow_thread, dev, 
496                               CLONE_FS | CLONE_FILES | CLONE_SIGHAND);
497                 down(&dev->sem);
498         }
499         dev->count++;
500  out:
501         spin_unlock(&cow_lock);
502         return(err);
503 }
504
505 static int cow_release(struct inode * inode, struct file * file)
506 {
507         struct cow *dev;
508         int n, err;
509
510         n = DEVICE_NR(inode->i_rdev);
511         if(n >= MAX_DEV)
512                 return(-ENODEV);
513         dev = &cow_dev[n];
514
515         spin_lock(&cow_lock);
516
517         if(--dev->count > 0)
518                 goto out;
519
520         err = blkdev_put(dev->cow_bdev, BDEV_RAW);
521         if(err)
522                 printk("cow_release - blkdev_put of cow device failed, "
523                        "error = %d\n", err);
524         bdput(dev->cow_bdev);
525         dev->cow_bdev = 0;
526
527         err = blkdev_put(dev->backing_bdev, BDEV_RAW);
528         if(err)
529                 printk("cow_release - blkdev_put of backing device failed, "
530                        "error = %d\n", err);
531         bdput(dev->backing_bdev);
532         dev->backing_bdev = 0;
533
534  out:
535         spin_unlock(&cow_lock);
536         return(0);
537 }
538
539 static int cow_ioctl(struct inode * inode, struct file * file,
540                      unsigned int cmd, unsigned long arg)
541 {
542         struct cow *dev;
543         int (*dev_ioctl)(struct inode *, struct file *, unsigned int, 
544                          unsigned long);
545         int n;
546
547         n = DEVICE_NR(inode->i_rdev);
548         if(n >= MAX_DEV)
549                 return(-ENODEV);
550         dev = &cow_dev[n];
551
552         dev_ioctl = dev->backing_bdev->bd_op->ioctl;
553         return((*dev_ioctl)(inode, file, cmd, arg));
554 }
555
556 static int cow_revalidate(kdev_t rdev)
557 {
558         printk(KERN_ERR "Need to implement cow_revalidate\n");
559         return(0);
560 }
561
562 static int parse_unit(char **ptr)
563 {
564         char *str = *ptr, *end;
565         int n = -1;
566
567         if(isdigit(*str)) {
568                 n = simple_strtoul(str, &end, 0);
569                 if(end == str)
570                         return(-1);
571                 *ptr = end;
572         }
573         else if (('a' <= *str) && (*str <= 'h')) {
574                 n = *str - 'a';
575                 str++;
576                 *ptr = str;
577         }
578         return(n);
579 }
580
581 static int cow_setup(char *str)
582 {
583         struct cow *dev;
584         char *cow_name, *backing_name;
585         int unit;
586
587         unit = parse_unit(&str);
588         if(unit < 0){
589                 printk(KERN_ERR "cow_setup - Couldn't parse unit number\n");
590                 return(1);
591         }
592
593         if(*str != '='){
594                 printk(KERN_ERR "cow_setup - Missing '=' after unit "
595                        "number\n");
596                 return(1);
597         }
598         str++;
599
600         cow_name = str;
601         backing_name = strchr(str, ',');
602         if(backing_name == NULL){
603                 printk(KERN_ERR "cow_setup - missing backing device name\n");
604                 return(0);
605         }
606         *backing_name = '\0';
607         backing_name++;
608
609         spin_lock(&cow_lock);
610
611         dev = &cow_dev[unit];
612         dev->cow_path = cow_name;
613         dev->backing_path = backing_name;
614         
615         spin_unlock(&cow_lock);
616         return(0);
617 }
618
619 __setup("cow", cow_setup);
620
621 /*
622  * Overrides for Emacs so that we follow Linus's tabbing style.
623  * Emacs will notice this stuff at the end of the file and automatically
624  * adjust the settings for this buffer only.  This must remain at the end
625  * of the file.
626  * ---------------------------------------------------------------------------
627  * Local variables:
628  * c-file-style: "linux"
629  * End:
630  */