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

« back to all changes in this revision

Viewing changes to .pc/Version-dependent-compilation.patch/request.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/mempool.h>
 
24
#include <linux/spinlock.h>
 
25
#include <linux/mutex.h>
 
26
#include <linux/sched.h>
 
27
#include <linux/device.h>
 
28
#include <linux/slab.h>
 
29
 
 
30
#include "blktap.h"
 
31
 
 
32
/* max pages per shared pool. just to prevent accidental dos. */
 
33
#define POOL_MAX_PAGES           (256*BLKTAP_SEGMENT_MAX)
 
34
 
 
35
/* default page pool size. when considering to shrink a shared pool,
 
36
 * note that paused tapdisks may grab a whole lot of pages for a long
 
37
 * time. */
 
38
#define POOL_DEFAULT_PAGES       (2 * BLKTAP_RING_SIZE * BLKTAP_SEGMENT_MAX)
 
39
 
 
40
/* max number of pages allocatable per request. */
 
41
#define POOL_MAX_REQUEST_PAGES   BLKTAP_SEGMENT_MAX
 
42
 
 
43
/* min request structs per pool. These grow dynamically. */
 
44
#define POOL_MIN_REQS            BLKTAP_RING_SIZE
 
45
 
 
46
static struct kset *pool_set;
 
47
 
 
48
#define kobj_to_pool(_kobj) \
 
49
        container_of(_kobj, struct blktap_page_pool, kobj)
 
50
 
 
51
static struct kmem_cache *request_cache;
 
52
static mempool_t *request_pool;
 
53
 
 
54
static void
 
55
__page_pool_wake(struct blktap_page_pool *pool)
 
56
{
 
57
        mempool_t *mem = pool->bufs;
 
58
 
 
59
        /*
 
60
          NB. slightly wasteful to always wait for a full segment
 
61
          set. but this ensures the next disk makes
 
62
          progress. presently, the repeated request struct
 
63
          alloc/release cycles would otherwise keep everyone spinning.
 
64
        */
 
65
 
 
66
        if (mem->curr_nr >= POOL_MAX_REQUEST_PAGES)
 
67
                wake_up(&pool->wait);
 
68
}
 
69
 
 
70
int
 
71
blktap_request_get_pages(struct blktap *tap,
 
72
                         struct blktap_request *request, int nr_pages)
 
73
{
 
74
        struct blktap_page_pool *pool = tap->pool;
 
75
        mempool_t *mem = pool->bufs;
 
76
        struct page *page;
 
77
 
 
78
        BUG_ON(request->nr_pages != 0);
 
79
        BUG_ON(nr_pages > POOL_MAX_REQUEST_PAGES);
 
80
 
 
81
        if (mem->curr_nr < nr_pages)
 
82
                return -ENOMEM;
 
83
 
 
84
        /* NB. avoid thundering herds of tapdisks colliding. */
 
85
        spin_lock(&pool->lock);
 
86
 
 
87
        if (mem->curr_nr < nr_pages) {
 
88
                spin_unlock(&pool->lock);
 
89
                return -ENOMEM;
 
90
        }
 
91
 
 
92
        while (request->nr_pages < nr_pages) {
 
93
                page = mempool_alloc(mem, GFP_NOWAIT);
 
94
                BUG_ON(!page);
 
95
                request->pages[request->nr_pages++] = page;
 
96
        }
 
97
 
 
98
        spin_unlock(&pool->lock);
 
99
 
 
100
        return 0;
 
101
}
 
102
 
 
103
static void
 
104
blktap_request_put_pages(struct blktap *tap,
 
105
                         struct blktap_request *request)
 
106
{
 
107
        struct blktap_page_pool *pool = tap->pool;
 
108
        struct page *page;
 
109
 
 
110
        while (request->nr_pages) {
 
111
                page = request->pages[--request->nr_pages];
 
112
                mempool_free(page, pool->bufs);
 
113
        }
 
114
}
 
115
 
 
116
size_t
 
117
blktap_request_debug(struct blktap *tap, char *buf, size_t size)
 
118
{
 
119
        struct blktap_page_pool *pool = tap->pool;
 
120
        mempool_t *mem = pool->bufs;
 
121
        char *s = buf, *end = buf + size;
 
122
 
 
123
        s += snprintf(buf, end - s,
 
124
                      "pool:%s pages:%d free:%d\n",
 
125
                      kobject_name(&pool->kobj),
 
126
                      mem->min_nr, mem->curr_nr);
 
127
 
 
128
        return s - buf;
 
129
}
 
130
 
 
131
struct blktap_request*
 
132
blktap_request_alloc(struct blktap *tap)
 
133
{
 
134
        struct blktap_request *request;
 
135
 
 
136
        request = mempool_alloc(request_pool, GFP_NOWAIT);
 
137
        if (request)
 
138
                request->tap = tap;
 
139
 
 
140
        return request;
 
141
}
 
142
 
 
143
void
 
144
blktap_request_free(struct blktap *tap,
 
145
                    struct blktap_request *request)
 
146
{
 
147
        blktap_request_put_pages(tap, request);
 
148
 
 
149
        mempool_free(request, request_pool);
 
150
 
 
151
        __page_pool_wake(tap->pool);
 
152
}
 
153
 
 
154
static void
 
155
blktap_request_bounce_seg(struct blktap *tap,
 
156
                          struct blktap_request *request,
 
157
                          int seg, int write)
 
158
{
 
159
        struct scatterlist *sg = &request->sg_table[seg];
 
160
        void *s, *p;
 
161
 
 
162
        BUG_ON(seg >= request->nr_pages);
 
163
 
 
164
        s = sg_virt(sg);
 
165
        p = page_address(request->pages[seg]) + sg->offset;
 
166
 
 
167
        if (write)
 
168
                memcpy(p, s, sg->length);
 
169
        else
 
170
                memcpy(s, p, sg->length);
 
171
}
 
172
 
 
173
void
 
174
blktap_request_bounce(struct blktap *tap,
 
175
                      struct blktap_request *request,
 
176
                      int write)
 
177
{
 
178
        int seg;
 
179
 
 
180
        for (seg = 0; seg < request->nr_pages; seg++)
 
181
                blktap_request_bounce_seg(tap, request, seg, write);
 
182
}
 
183
 
 
184
static void
 
185
blktap_request_ctor(void *obj)
 
186
{
 
187
        struct blktap_request *request = obj;
 
188
 
 
189
        memset(request, 0, sizeof(*request));
 
190
        sg_init_table(request->sg_table, ARRAY_SIZE(request->sg_table));
 
191
}
 
192
 
 
193
static int
 
194
blktap_page_pool_resize(struct blktap_page_pool *pool, int target)
 
195
{
 
196
        mempool_t *bufs = pool->bufs;
 
197
        int err;
 
198
 
 
199
        /* NB. mempool asserts min_nr >= 1 */
 
200
        target = max(1, target);
 
201
 
 
202
        err = mempool_resize(bufs, target, GFP_KERNEL);
 
203
        if (err)
 
204
                return err;
 
205
 
 
206
        __page_pool_wake(pool);
 
207
 
 
208
        return 0;
 
209
}
 
210
 
 
211
struct pool_attribute {
 
212
        struct attribute attr;
 
213
 
 
214
        ssize_t (*show)(struct blktap_page_pool *pool,
 
215
                        char *buf);
 
216
 
 
217
        ssize_t (*store)(struct blktap_page_pool *pool,
 
218
                         const char *buf, size_t count);
 
219
};
 
220
 
 
221
#define kattr_to_pool_attr(_kattr) \
 
222
        container_of(_kattr, struct pool_attribute, attr)
 
223
 
 
224
static ssize_t
 
225
blktap_page_pool_show_size(struct blktap_page_pool *pool,
 
226
                           char *buf)
 
227
{
 
228
        mempool_t *mem = pool->bufs;
 
229
        return sprintf(buf, "%d", mem->min_nr);
 
230
}
 
231
 
 
232
static ssize_t
 
233
blktap_page_pool_store_size(struct blktap_page_pool *pool,
 
234
                            const char *buf, size_t size)
 
235
{
 
236
        int target;
 
237
 
 
238
        /*
 
239
         * NB. target fixup to avoid undesired results. less than a
 
240
         * full segment set can wedge the disk. much more than a
 
241
         * couple times the physical queue depth is rarely useful.
 
242
         */
 
243
 
 
244
        target = simple_strtoul(buf, NULL, 0);
 
245
        target = max(POOL_MAX_REQUEST_PAGES, target);
 
246
        target = min(target, POOL_MAX_PAGES);
 
247
 
 
248
        return blktap_page_pool_resize(pool, target) ? : size;
 
249
}
 
250
 
 
251
static struct pool_attribute blktap_page_pool_attr_size =
 
252
        __ATTR(size, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH,
 
253
               blktap_page_pool_show_size,
 
254
               blktap_page_pool_store_size);
 
255
 
 
256
static ssize_t
 
257
blktap_page_pool_show_free(struct blktap_page_pool *pool,
 
258
                           char *buf)
 
259
{
 
260
        mempool_t *mem = pool->bufs;
 
261
        return sprintf(buf, "%d", mem->curr_nr);
 
262
}
 
263
 
 
264
static struct pool_attribute blktap_page_pool_attr_free =
 
265
        __ATTR(free, S_IRUSR|S_IRGRP|S_IROTH,
 
266
               blktap_page_pool_show_free,
 
267
               NULL);
 
268
 
 
269
static struct attribute *blktap_page_pool_attrs[] = {
 
270
        &blktap_page_pool_attr_size.attr,
 
271
        &blktap_page_pool_attr_free.attr,
 
272
        NULL,
 
273
};
 
274
 
 
275
static inline struct kobject*
 
276
__blktap_kset_find_obj(struct kset *kset, const char *name)
 
277
{
 
278
        struct kobject *k;
 
279
        struct kobject *ret = NULL;
 
280
 
 
281
        spin_lock(&kset->list_lock);
 
282
        list_for_each_entry(k, &kset->list, entry) {
 
283
                if (kobject_name(k) && !strcmp(kobject_name(k), name)) {
 
284
                        ret = kobject_get(k);
 
285
                        break;
 
286
                }
 
287
        }
 
288
        spin_unlock(&kset->list_lock);
 
289
        return ret;
 
290
}
 
291
 
 
292
static ssize_t
 
293
blktap_page_pool_show_attr(struct kobject *kobj, struct attribute *kattr,
 
294
                           char *buf)
 
295
{
 
296
        struct blktap_page_pool *pool = kobj_to_pool(kobj);
 
297
        struct pool_attribute *attr = kattr_to_pool_attr(kattr);
 
298
 
 
299
        if (attr->show)
 
300
                return attr->show(pool, buf);
 
301
 
 
302
        return -EIO;
 
303
}
 
304
 
 
305
static ssize_t
 
306
blktap_page_pool_store_attr(struct kobject *kobj, struct attribute *kattr,
 
307
                            const char *buf, size_t size)
 
308
{
 
309
        struct blktap_page_pool *pool = kobj_to_pool(kobj);
 
310
        struct pool_attribute *attr = kattr_to_pool_attr(kattr);
 
311
 
 
312
        if (attr->show)
 
313
                return attr->store(pool, buf, size);
 
314
 
 
315
        return -EIO;
 
316
}
 
317
 
 
318
static struct sysfs_ops blktap_page_pool_sysfs_ops = {
 
319
        .show           = blktap_page_pool_show_attr,
 
320
        .store          = blktap_page_pool_store_attr,
 
321
};
 
322
 
 
323
static void
 
324
blktap_page_pool_release(struct kobject *kobj)
 
325
{
 
326
        struct blktap_page_pool *pool = kobj_to_pool(kobj);
 
327
        mempool_destroy(pool->bufs);
 
328
        kfree(pool);
 
329
}
 
330
 
 
331
struct kobj_type blktap_page_pool_ktype = {
 
332
        .release       = blktap_page_pool_release,
 
333
        .sysfs_ops     = &blktap_page_pool_sysfs_ops,
 
334
        .default_attrs = blktap_page_pool_attrs,
 
335
};
 
336
 
 
337
static void*
 
338
__mempool_page_alloc(gfp_t gfp_mask, void *pool_data)
 
339
{
 
340
        struct page *page;
 
341
 
 
342
        if (!(gfp_mask & __GFP_WAIT))
 
343
                return NULL;
 
344
 
 
345
        page = alloc_page(gfp_mask);
 
346
        if (page)
 
347
                SetPageReserved(page);
 
348
 
 
349
        return page;
 
350
}
 
351
 
 
352
static void
 
353
__mempool_page_free(void *element, void *pool_data)
 
354
{
 
355
        struct page *page = element;
 
356
 
 
357
        ClearPageReserved(page);
 
358
        put_page(page);
 
359
}
 
360
 
 
361
static struct kobject*
 
362
blktap_page_pool_create(const char *name, int nr_pages)
 
363
{
 
364
        struct blktap_page_pool *pool;
 
365
        int err;
 
366
 
 
367
        pool = kzalloc(sizeof(*pool), GFP_KERNEL);
 
368
        if (!pool)
 
369
                goto fail;
 
370
 
 
371
        spin_lock_init(&pool->lock);
 
372
        init_waitqueue_head(&pool->wait);
 
373
 
 
374
        pool->bufs = mempool_create(nr_pages,
 
375
                                    __mempool_page_alloc, __mempool_page_free,
 
376
                                    pool);
 
377
        if (!pool->bufs)
 
378
                goto fail_pool;
 
379
 
 
380
        kobject_init(&pool->kobj, &blktap_page_pool_ktype);
 
381
        pool->kobj.kset = pool_set;
 
382
        err = kobject_add(&pool->kobj, &pool_set->kobj, "%s", name);
 
383
        if (err)
 
384
                goto fail_bufs;
 
385
 
 
386
        return &pool->kobj;
 
387
 
 
388
        kobject_del(&pool->kobj);
 
389
fail_bufs:
 
390
        mempool_destroy(pool->bufs);
 
391
fail_pool:
 
392
        kfree(pool);
 
393
fail:
 
394
        return NULL;
 
395
}
 
396
 
 
397
struct blktap_page_pool*
 
398
blktap_page_pool_get(const char *name)
 
399
{
 
400
        struct kobject *kobj;
 
401
 
 
402
        kobj = __blktap_kset_find_obj(pool_set, name);
 
403
        if (!kobj)
 
404
                kobj = blktap_page_pool_create(name,
 
405
                                               POOL_DEFAULT_PAGES);
 
406
        if (!kobj)
 
407
                return ERR_PTR(-ENOMEM);
 
408
 
 
409
        return kobj_to_pool(kobj);
 
410
}
 
411
 
 
412
int __init
 
413
blktap_page_pool_init(struct kobject *parent)
 
414
{
 
415
        request_cache =
 
416
                kmem_cache_create("blktap-request",
 
417
                                  sizeof(struct blktap_request), 0,
 
418
                                  0, blktap_request_ctor);
 
419
        if (!request_cache)
 
420
                return -ENOMEM;
 
421
 
 
422
        request_pool =
 
423
                mempool_create_slab_pool(POOL_MIN_REQS, request_cache);
 
424
        if (!request_pool)
 
425
                return -ENOMEM;
 
426
 
 
427
        pool_set = kset_create_and_add("pools", NULL, parent);
 
428
        if (!pool_set)
 
429
                return -ENOMEM;
 
430
 
 
431
        return 0;
 
432
}
 
433
 
 
434
void
 
435
blktap_page_pool_exit(void)
 
436
{
 
437
        if (pool_set) {
 
438
                BUG_ON(!list_empty(&pool_set->list));
 
439
                kset_unregister(pool_set);
 
440
                pool_set = NULL;
 
441
        }
 
442
 
 
443
        if (request_pool) {
 
444
                mempool_destroy(request_pool);
 
445
                request_pool = NULL;
 
446
        }
 
447
 
 
448
        if (request_cache) {
 
449
                kmem_cache_destroy(request_cache);
 
450
                request_cache = NULL;
 
451
        }
 
452
}