~ubuntu-branches/ubuntu/vivid/blktap-dkms/vivid-proposed

« back to all changes in this revision

Viewing changes to .pc/Version-dependent-compilation.patch/ring.c

  • Committer: Package Import Robot
  • Author(s): Adam Conrad
  • Date: 2015-07-28 23:25:07 UTC
  • mfrom: (9.1.1 wily-proposed)
  • Revision ID: package-import@ubuntu.com-20150728232507-rulha87ttvrvotbw
Tags: 2.0.93-0.3ubuntu6~15.04.1
debian/rules: Stop recommending kernel headers, our DKMS packages
shouldn't do this, as we have no way of matching installed kernel.

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