~mitya57/ubuntu/precise/blktap-dkms/lp1157421

« back to all changes in this revision

Viewing changes to .pc/support_kernel_3.4.patch/ring.c

  • Committer: Dmitry Shachnev
  • Date: 2013-03-21 15:42:41 UTC
  • Revision ID: mitya57@ubuntu.com-20130321154241-1d0aygllqpuupavq
debian/patches/support_kernel_3.4.patch: support kernels >= 3.4,
including 12.04.2 kernel (LP: #1157421)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 *
 
3
 * Copyright (C) 2011 Citrix Systems Inc.
 
4
 *
 
5
 * This file is part of Blktap2.
 
6
 *
 
7
 * Blktap2 is free software: you can redistribute it and/or modify
 
8
 * it under the terms of the GNU General Public License version 2
 
9
 * as published by the Free Software Foundation.
 
10
 *
 
11
 * Blktap2 is distributed in the hope that it will be useful,
 
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
14
 * GNU General Public License version 2 for more details.
 
15
 *
 
16
 * You should have received a copy of the GNU General Public License
 
17
 * version 2 along with Blktap2.  If not, see 
 
18
 * <http://www.gnu.org/licenses/>.
 
19
 *
 
20
 *
 
21
 */
 
22
 
 
23
#include <linux/device.h>
 
24
#include <linux/signal.h>
 
25
#include <linux/sched.h>
 
26
#include <linux/poll.h>
 
27
#include <linux/blkdev.h>
 
28
#include <linux/mman.h>
 
29
 
 
30
#include "blktap.h"
 
31
 
 
32
int blktap_ring_major;
 
33
static struct cdev blktap_ring_cdev;
 
34
 
 
35
 /* 
 
36
  * BLKTAP - immediately before the mmap area,
 
37
  * we have a bunch of pages reserved for shared memory rings.
 
38
  */
 
39
#define RING_PAGES 1
 
40
 
 
41
#define BLKTAP_INFO_SIZE_AT(_memb)                      \
 
42
        offsetof(struct blktap_device_info, _memb) +    \
 
43
        sizeof(((struct blktap_device_info*)0)->_memb)
 
44
 
 
45
static void
 
46
blktap_ring_read_response(struct blktap *tap,
 
47
                          const struct blktap_ring_response *rsp)
 
48
{
 
49
        struct blktap_ring *ring = &tap->ring;
 
50
        struct blktap_request *request;
 
51
        int usr_idx, err;
 
52
 
 
53
        request = NULL;
 
54
 
 
55
        usr_idx = rsp->id;
 
56
        if (usr_idx < 0 || usr_idx >= BLKTAP_RING_SIZE) {
 
57
                err = -ERANGE;
 
58
                goto invalid;
 
59
        }
 
60
 
 
61
        request = ring->pending[usr_idx];
 
62
 
 
63
        if (!request) {
 
64
                err = -ESRCH;
 
65
                goto invalid;
 
66
        }
 
67
 
 
68
        if (rsp->operation != request->operation) {
 
69
                err = -EINVAL;
 
70
                goto invalid;
 
71
        }
 
72
 
 
73
        dev_dbg(ring->dev,
 
74
                "request %d [%p] response: %d\n",
 
75
                request->usr_idx, request, rsp->status);
 
76
 
 
77
        err = rsp->status == BLKTAP_RSP_OKAY ? 0 : -EIO;
 
78
end_request:
 
79
        blktap_device_end_request(tap, request, err);
 
80
        return;
 
81
 
 
82
invalid:
 
83
        dev_warn(ring->dev,
 
84
                 "invalid response, idx:%d status:%d op:%d/%d: err %d\n",
 
85
                 usr_idx, rsp->status,
 
86
                 rsp->operation, request->operation,
 
87
                 err);
 
88
        if (request)
 
89
                goto end_request;
 
90
}
 
91
 
 
92
static void
 
93
blktap_read_ring(struct blktap *tap)
 
94
{
 
95
        struct blktap_ring *ring = &tap->ring;
 
96
        struct blktap_ring_response rsp;
 
97
        RING_IDX rc, rp;
 
98
 
 
99
        down_read(&current->mm->mmap_sem);
 
100
        if (!ring->vma) {
 
101
                up_read(&current->mm->mmap_sem);
 
102
                return;
 
103
        }
 
104
 
 
105
        /* for each outstanding message on the ring  */
 
106
        rp = ring->ring.sring->rsp_prod;
 
107
        rmb();
 
108
 
 
109
        for (rc = ring->ring.rsp_cons; rc != rp; rc++) {
 
110
                memcpy(&rsp, RING_GET_RESPONSE(&ring->ring, rc), sizeof(rsp));
 
111
                blktap_ring_read_response(tap, &rsp);
 
112
        }
 
113
 
 
114
        ring->ring.rsp_cons = rc;
 
115
 
 
116
        up_read(&current->mm->mmap_sem);
 
117
}
 
118
 
 
119
#define MMAP_VADDR(_start, _req, _seg)                          \
 
120
        ((_start) +                                             \
 
121
         ((_req) * BLKTAP_SEGMENT_MAX * BLKTAP_PAGE_SIZE) +     \
 
122
         ((_seg) * BLKTAP_PAGE_SIZE))
 
123
 
 
124
static int blktap_ring_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
 
125
{
 
126
        return VM_FAULT_SIGBUS;
 
127
}
 
128
 
 
129
static void
 
130
blktap_ring_fail_pending(struct blktap *tap)
 
131
{
 
132
        struct blktap_ring *ring = &tap->ring;
 
133
        struct blktap_request *request;
 
134
        int usr_idx;
 
135
 
 
136
        for (usr_idx = 0; usr_idx < BLKTAP_RING_SIZE; usr_idx++) {
 
137
                request = ring->pending[usr_idx];
 
138
                if (!request)
 
139
                        continue;
 
140
 
 
141
                blktap_device_end_request(tap, request, -EIO);
 
142
        }
 
143
}
 
144
 
 
145
static void
 
146
blktap_ring_vm_close_sring(struct blktap *tap,
 
147
                           struct vm_area_struct *vma)
 
148
{
 
149
        struct blktap_ring *ring = &tap->ring;
 
150
        struct page *page = virt_to_page(ring->ring.sring);
 
151
 
 
152
        blktap_ring_fail_pending(tap);
 
153
 
 
154
        ClearPageReserved(page);
 
155
        __free_page(page);
 
156
 
 
157
        ring->vma = NULL;
 
158
 
 
159
        if (test_bit(BLKTAP_SHUTDOWN_REQUESTED, &tap->dev_inuse))
 
160
                blktap_control_destroy_tap(tap);
 
161
}
 
162
 
 
163
static void
 
164
blktap_ring_vm_close(struct vm_area_struct *vma)
 
165
{
 
166
        struct blktap *tap = vma->vm_private_data;
 
167
 
 
168
        dev_dbg(tap->ring.dev,
 
169
                "vm_close %lx-%lx (%lu) pgoff %lu\n",
 
170
                vma->vm_start, vma->vm_end, vma_pages(vma),
 
171
                vma->vm_pgoff);
 
172
 
 
173
        if (!vma->vm_pgoff)
 
174
                blktap_ring_vm_close_sring(tap, vma);
 
175
}
 
176
 
 
177
static struct vm_operations_struct blktap_ring_vm_operations = {
 
178
        .close    = blktap_ring_vm_close,
 
179
        .fault    = blktap_ring_fault,
 
180
};
 
181
 
 
182
int
 
183
blktap_ring_map_request(struct blktap *tap, struct file *filp,
 
184
                        struct blktap_request *request)
 
185
{
 
186
        struct blktap_ring *ring = &tap->ring;
 
187
        unsigned long addr, len, pgoff;
 
188
        int read, write, prot, flags;
 
189
 
 
190
        write = request->operation == BLKTAP_OP_WRITE;
 
191
        read  = request->operation == BLKTAP_OP_READ;
 
192
 
 
193
        if (write)
 
194
                blktap_request_bounce(tap, request, write);
 
195
 
 
196
        prot  = PROT_READ;
 
197
        prot |= read ? PROT_WRITE : 0;
 
198
 
 
199
        flags = MAP_FIXED|MAP_SHARED;
 
200
 
 
201
        addr  = MMAP_VADDR(ring->user_vstart, request->usr_idx, 0);
 
202
        len   = request->nr_pages << PAGE_SHIFT;
 
203
 
 
204
        pgoff = 1 + request->usr_idx * BLKTAP_SEGMENT_MAX;
 
205
 
 
206
        addr = do_mmap_pgoff(filp, addr, len, prot, flags, pgoff);
 
207
 
 
208
        return IS_ERR_VALUE(addr) ? addr : 0;
 
209
}
 
210
 
 
211
void
 
212
blktap_ring_unmap_request(struct blktap *tap,
 
213
                          struct blktap_request *request)
 
214
{
 
215
        struct blktap_ring *ring = &tap->ring;
 
216
        unsigned long addr, len;
 
217
        int read, err;
 
218
 
 
219
        read  = request->operation == BLKTAP_OP_READ;
 
220
        if (read)
 
221
                blktap_request_bounce(tap, request, !read);
 
222
 
 
223
        addr  = MMAP_VADDR(ring->user_vstart, request->usr_idx, 0);
 
224
        len   = request->nr_pages << PAGE_SHIFT;
 
225
 
 
226
        err = do_munmap(current->mm, addr, len);
 
227
        WARN_ON_ONCE(err);
 
228
}
 
229
 
 
230
void
 
231
blktap_ring_free_request(struct blktap *tap,
 
232
                         struct blktap_request *request)
 
233
{
 
234
        struct blktap_ring *ring = &tap->ring;
 
235
 
 
236
        ring->pending[request->usr_idx] = NULL;
 
237
        ring->n_pending--;
 
238
 
 
239
        blktap_request_free(tap, request);
 
240
}
 
241
 
 
242
struct blktap_request*
 
243
blktap_ring_make_request(struct blktap *tap)
 
244
{
 
245
        struct blktap_ring *ring = &tap->ring;
 
246
        struct blktap_request *request;
 
247
        int usr_idx;
 
248
 
 
249
        if (RING_FULL(&ring->ring))
 
250
                return ERR_PTR(-ENOSPC);
 
251
 
 
252
        request = blktap_request_alloc(tap);
 
253
        if (!request)
 
254
                return ERR_PTR(-ENOMEM);
 
255
 
 
256
        for (usr_idx = 0; usr_idx < BLKTAP_RING_SIZE; usr_idx++)
 
257
                if (!ring->pending[usr_idx])
 
258
                        break;
 
259
 
 
260
        BUG_ON(usr_idx >= BLKTAP_RING_SIZE);
 
261
 
 
262
        request->tap     = tap;
 
263
        request->usr_idx = usr_idx;
 
264
 
 
265
        ring->pending[usr_idx] = request;
 
266
        ring->n_pending++;
 
267
 
 
268
        return request;
 
269
}
 
270
 
 
271
static int
 
272
blktap_ring_make_rw_request(struct blktap *tap,
 
273
                            struct blktap_request *request,
 
274
                            struct blktap_ring_request *breq)
 
275
{
 
276
        struct scatterlist *sg;
 
277
        unsigned int i, nsecs = 0;
 
278
 
 
279
        blktap_for_each_sg(sg, request, i) {
 
280
                struct blktap_segment *seg = &breq->u.rw.seg[i];
 
281
                int first, count;
 
282
 
 
283
                count = sg->length >> 9;
 
284
                first = sg->offset >> 9;
 
285
 
 
286
                seg->first_sect = first;
 
287
                seg->last_sect  = first + count - 1;
 
288
 
 
289
                nsecs += count;
 
290
        }
 
291
 
 
292
        breq->u.rw.sector_number = blk_rq_pos(request->rq);
 
293
 
 
294
        return nsecs;
 
295
}
 
296
 
 
297
static int
 
298
blktap_ring_make_tr_request(struct blktap *tap,
 
299
                            struct blktap_request *request,
 
300
                            struct blktap_ring_request *breq)
 
301
{
 
302
        struct bio *bio = request->rq->bio;
 
303
        unsigned int nsecs;
 
304
 
 
305
        breq->u.tr.nr_sectors    = nsecs = bio_sectors(bio);
 
306
        breq->u.tr.sector_number = bio->bi_sector;
 
307
 
 
308
        return nsecs;
 
309
}
 
310
 
 
311
void
 
312
blktap_ring_submit_request(struct blktap *tap,
 
313
                           struct blktap_request *request)
 
314
{
 
315
        struct blktap_ring *ring = &tap->ring;
 
316
        struct blktap_ring_request *breq;
 
317
        int nsecs;
 
318
 
 
319
        dev_dbg(ring->dev,
 
320
                "request %d [%p] submit\n", request->usr_idx, request);
 
321
 
 
322
        breq = RING_GET_REQUEST(&ring->ring, ring->ring.req_prod_pvt);
 
323
 
 
324
        breq->id            = request->usr_idx;
 
325
        breq->__pad         = 0;
 
326
        breq->operation     = request->operation;
 
327
        breq->nr_segments   = request->nr_pages;
 
328
 
 
329
        switch (breq->operation) {
 
330
        case BLKTAP_OP_READ:
 
331
                nsecs = blktap_ring_make_rw_request(tap, request, breq);
 
332
 
 
333
                tap->stats.st_rd_sect += nsecs;
 
334
                tap->stats.st_rd_req++;
 
335
                break;
 
336
 
 
337
        case BLKTAP_OP_WRITE:
 
338
                nsecs = blktap_ring_make_rw_request(tap, request, breq);
 
339
 
 
340
                tap->stats.st_wr_sect += nsecs;
 
341
                tap->stats.st_wr_req++;
 
342
                break;
 
343
 
 
344
        case BLKTAP_OP_FLUSH:
 
345
                breq->u.rw.sector_number = 0;
 
346
                tap->stats.st_fl_req++;
 
347
                break;
 
348
 
 
349
        case BLKTAP_OP_TRIM:
 
350
                nsecs = blktap_ring_make_tr_request(tap, request, breq);
 
351
 
 
352
                tap->stats.st_tr_sect += nsecs;
 
353
                tap->stats.st_tr_req++;
 
354
                break;
 
355
        default:
 
356
                BUG();
 
357
        }
 
358
 
 
359
        ring->ring.req_prod_pvt++;
 
360
}
 
361
 
 
362
static int
 
363
blktap_ring_open(struct inode *inode, struct file *filp)
 
364
{
 
365
        struct blktap *tap = NULL;
 
366
        int minor;
 
367
 
 
368
        minor = iminor(inode);
 
369
 
 
370
        if (minor < blktap_max_minor)
 
371
                tap = blktaps[minor];
 
372
 
 
373
        if (!tap)
 
374
                return -ENXIO;
 
375
 
 
376
        if (test_bit(BLKTAP_SHUTDOWN_REQUESTED, &tap->dev_inuse))
 
377
                return -ENXIO;
 
378
 
 
379
        if (tap->ring.task)
 
380
                return -EBUSY;
 
381
 
 
382
        filp->private_data = tap;
 
383
        tap->ring.task = current;
 
384
 
 
385
        return 0;
 
386
}
 
387
 
 
388
static int
 
389
blktap_ring_release(struct inode *inode, struct file *filp)
 
390
{
 
391
        struct blktap *tap = filp->private_data;
 
392
 
 
393
        blktap_device_destroy_sync(tap);
 
394
 
 
395
        tap->ring.task = NULL;
 
396
 
 
397
        if (test_bit(BLKTAP_SHUTDOWN_REQUESTED, &tap->dev_inuse))
 
398
                blktap_control_destroy_tap(tap);
 
399
 
 
400
        return 0;
 
401
}
 
402
 
 
403
static int
 
404
blktap_ring_mmap_request(struct blktap *tap,
 
405
                         struct vm_area_struct *vma)
 
406
{
 
407
        struct blktap_ring *ring = &tap->ring;
 
408
        struct blktap_request *request;
 
409
        int usr_idx, seg, err;
 
410
        unsigned long addr, n_segs;
 
411
 
 
412
        usr_idx  = vma->vm_pgoff - 1;
 
413
        seg      = usr_idx % BLKTAP_SEGMENT_MAX;
 
414
        usr_idx /= BLKTAP_SEGMENT_MAX;
 
415
 
 
416
        request = ring->pending[usr_idx];
 
417
        if (!request)
 
418
                return -EINVAL;
 
419
 
 
420
        n_segs = request->nr_pages - seg;
 
421
        n_segs = min(n_segs, vma_pages(vma));
 
422
 
 
423
        for (addr = vma->vm_start;
 
424
             seg < n_segs;
 
425
             seg++, addr += PAGE_SIZE) {
 
426
                struct page *page = request->pages[seg];
 
427
 
 
428
                dev_dbg(tap->ring.dev,
 
429
                        "mmap request %d seg %d addr %lx\n",
 
430
                        usr_idx, seg, addr);
 
431
 
 
432
                err = vm_insert_page(vma, addr, page);
 
433
                if (err)
 
434
                        return err;
 
435
        }
 
436
 
 
437
        vma->vm_flags |= VM_DONTCOPY;
 
438
        vma->vm_flags |= VM_RESERVED;
 
439
 
 
440
        return 0;
 
441
}
 
442
 
 
443
static int
 
444
blktap_ring_mmap_sring(struct blktap *tap, struct vm_area_struct *vma)
 
445
{
 
446
        struct blktap_ring *ring = &tap->ring;
 
447
        struct blktap_sring *sring;
 
448
        struct page *page = NULL;
 
449
        int err;
 
450
 
 
451
        if (ring->vma)
 
452
                return -EBUSY;
 
453
 
 
454
        page = alloc_page(GFP_KERNEL|__GFP_ZERO);
 
455
        if (!page)
 
456
                return -ENOMEM;
 
457
 
 
458
        SetPageReserved(page);
 
459
 
 
460
        err = vm_insert_page(vma, vma->vm_start, page);
 
461
        if (err)
 
462
                goto fail;
 
463
 
 
464
        sring = page_address(page);
 
465
        SHARED_RING_INIT(sring);
 
466
        FRONT_RING_INIT(&ring->ring, sring, PAGE_SIZE);
 
467
 
 
468
        ring->ring_vstart = vma->vm_start;
 
469
        ring->user_vstart = ring->ring_vstart + PAGE_SIZE;
 
470
 
 
471
        vma->vm_private_data = tap;
 
472
 
 
473
        vma->vm_flags |= VM_DONTCOPY;
 
474
        vma->vm_flags |= VM_RESERVED;
 
475
 
 
476
        vma->vm_ops = &blktap_ring_vm_operations;
 
477
 
 
478
        ring->vma = vma;
 
479
        return 0;
 
480
 
 
481
fail:
 
482
        if (page) {
 
483
                ClearPageReserved(page);
 
484
                __free_page(page);
 
485
        }
 
486
 
 
487
        return err;
 
488
}
 
489
 
 
490
static int
 
491
blktap_ring_mmap(struct file *filp, struct vm_area_struct *vma)
 
492
{
 
493
        struct blktap *tap = filp->private_data;
 
494
 
 
495
        dev_dbg(tap->ring.dev,
 
496
                "mmap %lx-%lx (%lu) pgoff %lu\n",
 
497
                vma->vm_start, vma->vm_end, vma_pages(vma),
 
498
                vma->vm_pgoff);
 
499
 
 
500
        if (!vma->vm_pgoff)
 
501
                return blktap_ring_mmap_sring(tap, vma);
 
502
 
 
503
        return blktap_ring_mmap_request(tap, vma);
 
504
}
 
505
 
 
506
static long
 
507
blktap_ring_ioctl(struct file *filp,
 
508
                  unsigned int cmd, unsigned long arg)
 
509
{
 
510
        struct blktap *tap = filp->private_data;
 
511
        struct blktap_ring *ring = &tap->ring;
 
512
        void __user *ptr = (void *)arg;
 
513
        int err;
 
514
 
 
515
        BTDBG("%d: cmd: %u, arg: %lu\n", tap->minor, cmd, arg);
 
516
 
 
517
        if (!ring->vma || ring->vma->vm_mm != current->mm)
 
518
                return -EACCES;
 
519
 
 
520
        switch(cmd) {
 
521
        case BLKTAP_IOCTL_RESPOND:
 
522
 
 
523
                blktap_read_ring(tap);
 
524
                return 0;
 
525
 
 
526
        case BLKTAP_IOCTL_CREATE_DEVICE_COMPAT: {
 
527
                struct blktap_device_info info;
 
528
                struct blktap2_params params;
 
529
 
 
530
                if (copy_from_user(&params, ptr, sizeof(params)))
 
531
                        return -EFAULT;
 
532
 
 
533
                info.capacity             = params.capacity;
 
534
                info.sector_size          = params.sector_size;
 
535
                info.flags                = 0;
 
536
 
 
537
                err = blktap_device_create(tap, &info);
 
538
                if (err)
 
539
                        return err;
 
540
 
 
541
                if (params.name[0]) {
 
542
                        strncpy(tap->name, params.name, sizeof(params.name));
 
543
                        tap->name[sizeof(tap->name)-1] = 0;
 
544
                }
 
545
 
 
546
                return 0;
 
547
        }
 
548
 
 
549
        case BLKTAP_IOCTL_CREATE_DEVICE: {
 
550
                struct blktap_device_info __user *ptr = (void *)arg;
 
551
                struct blktap_device_info info;
 
552
                unsigned long mask;
 
553
                size_t base_sz, sz;
 
554
 
 
555
                mask  = BLKTAP_DEVICE_FLAG_RO;
 
556
                mask |= BLKTAP_DEVICE_FLAG_PSZ;
 
557
                mask |= BLKTAP_DEVICE_FLAG_FLUSH;
 
558
                mask |= BLKTAP_DEVICE_FLAG_TRIM;
 
559
                mask |= BLKTAP_DEVICE_FLAG_TRIM_RZ;
 
560
 
 
561
                memset(&info, 0, sizeof(info));
 
562
                sz = base_sz = BLKTAP_INFO_SIZE_AT(flags);
 
563
 
 
564
                if (copy_from_user(&info, ptr, sz))
 
565
                        return -EFAULT;
 
566
 
 
567
                if ((info.flags & BLKTAP_DEVICE_FLAG_PSZ) != 0)
 
568
                        sz = BLKTAP_INFO_SIZE_AT(phys_block_offset);
 
569
 
 
570
                if (info.flags & BLKTAP_DEVICE_FLAG_TRIM)
 
571
                        sz = BLKTAP_INFO_SIZE_AT(trim_block_offset);
 
572
 
 
573
                if (sz > base_sz)
 
574
                        if (copy_from_user(&info, ptr, sz))
 
575
                                return -EFAULT;
 
576
 
 
577
                if (put_user(info.flags & mask, &ptr->flags))
 
578
                        return -EFAULT;
 
579
 
 
580
                return blktap_device_create(tap, &info);
 
581
        }
 
582
 
 
583
        case BLKTAP_IOCTL_REMOVE_DEVICE:
 
584
 
 
585
                return blktap_device_destroy(tap);
 
586
        }
 
587
 
 
588
        return -ENOTTY;
 
589
}
 
590
 
 
591
static unsigned int blktap_ring_poll(struct file *filp, poll_table *wait)
 
592
{
 
593
        struct blktap *tap = filp->private_data;
 
594
        struct blktap_ring *ring = &tap->ring;
 
595
        int work;
 
596
 
 
597
        poll_wait(filp, &tap->pool->wait, wait);
 
598
        poll_wait(filp, &ring->poll_wait, wait);
 
599
 
 
600
        down_read(&current->mm->mmap_sem);
 
601
        if (ring->vma && tap->device.gd)
 
602
                blktap_device_run_queue(tap, filp);
 
603
        up_read(&current->mm->mmap_sem);
 
604
 
 
605
        work = ring->ring.req_prod_pvt - ring->ring.sring->req_prod;
 
606
        RING_PUSH_REQUESTS(&ring->ring);
 
607
 
 
608
        if (work ||
 
609
            *BLKTAP_RING_MESSAGE(ring->ring.sring) ||
 
610
            test_and_clear_bit(BLKTAP_DEVICE_CLOSED, &tap->dev_inuse))
 
611
                return POLLIN | POLLRDNORM;
 
612
 
 
613
        return 0;
 
614
}
 
615
 
 
616
static struct file_operations blktap_ring_file_operations = {
 
617
        .owner          = THIS_MODULE,
 
618
        .open           = blktap_ring_open,
 
619
        .release        = blktap_ring_release,
 
620
        .unlocked_ioctl = blktap_ring_ioctl,
 
621
        .mmap           = blktap_ring_mmap,
 
622
        .poll           = blktap_ring_poll,
 
623
};
 
624
 
 
625
void
 
626
blktap_ring_kick_user(struct blktap *tap)
 
627
{
 
628
        wake_up(&tap->ring.poll_wait);
 
629
}
 
630
 
 
631
int
 
632
blktap_ring_destroy(struct blktap *tap)
 
633
{
 
634
        struct blktap_ring *ring = &tap->ring;
 
635
 
 
636
        if (ring->task || ring->vma)
 
637
                return -EBUSY;
 
638
 
 
639
        return 0;
 
640
}
 
641
 
 
642
int
 
643
blktap_ring_create(struct blktap *tap)
 
644
{
 
645
        struct blktap_ring *ring = &tap->ring;
 
646
 
 
647
        init_waitqueue_head(&ring->poll_wait);
 
648
        ring->devno = MKDEV(blktap_ring_major, tap->minor);
 
649
 
 
650
        return 0;
 
651
}
 
652
 
 
653
size_t
 
654
blktap_ring_debug(struct blktap *tap, char *buf, size_t size)
 
655
{
 
656
        struct blktap_ring *ring = &tap->ring;
 
657
        char *s = buf, *end = buf + size;
 
658
        int usr_idx;
 
659
 
 
660
        s += snprintf(s, end - s,
 
661
                      "begin pending:%d\n", ring->n_pending);
 
662
 
 
663
        for (usr_idx = 0; usr_idx < BLKTAP_RING_SIZE; usr_idx++) {
 
664
                struct blktap_request *request;
 
665
                struct timeval t;
 
666
 
 
667
                request = ring->pending[usr_idx];
 
668
                if (!request)
 
669
                        continue;
 
670
 
 
671
                jiffies_to_timeval(jiffies - request->rq->start_time, &t);
 
672
 
 
673
                s += snprintf(s, end - s,
 
674
                              "%02d: usr_idx:%02d "
 
675
                              "op:%x nr_pages:%02d time:%lu.%09lu\n",
 
676
                              usr_idx, request->usr_idx,
 
677
                              request->operation, request->nr_pages,
 
678
                              t.tv_sec, t.tv_usec);
 
679
        }
 
680
 
 
681
        s += snprintf(s, end - s, "end pending\n");
 
682
 
 
683
        return s - buf;
 
684
}
 
685
 
 
686
 
 
687
int __init
 
688
blktap_ring_init(void)
 
689
{
 
690
        dev_t dev = 0;
 
691
        int err;
 
692
 
 
693
        cdev_init(&blktap_ring_cdev, &blktap_ring_file_operations);
 
694
        blktap_ring_cdev.owner = THIS_MODULE;
 
695
 
 
696
        err = alloc_chrdev_region(&dev, 0, MAX_BLKTAP_DEVICE, "blktap2");
 
697
        if (err < 0) {
 
698
                BTERR("error registering ring devices: %d\n", err);
 
699
                return err;
 
700
        }
 
701
 
 
702
        err = cdev_add(&blktap_ring_cdev, dev, MAX_BLKTAP_DEVICE);
 
703
        if (err) {
 
704
                BTERR("error adding ring device: %d\n", err);
 
705
                unregister_chrdev_region(dev, MAX_BLKTAP_DEVICE);
 
706
                return err;
 
707
        }
 
708
 
 
709
        blktap_ring_major = MAJOR(dev);
 
710
        BTINFO("blktap ring major: %d\n", blktap_ring_major);
 
711
 
 
712
        return 0;
 
713
}
 
714
 
 
715
void
 
716
blktap_ring_exit(void)
 
717
{
 
718
        if (!blktap_ring_major)
 
719
                return;
 
720
 
 
721
        cdev_del(&blktap_ring_cdev);
 
722
        unregister_chrdev_region(MKDEV(blktap_ring_major, 0),
 
723
                                 MAX_BLKTAP_DEVICE);
 
724
 
 
725
        blktap_ring_major = 0;
 
726
}