- more 2.6.17 port work (still does not build)
[linux-flexiantxendom0-3.2.10.git] / drivers / scsi / iscsitarget / tio.c
1 /*
2  * Target I/O.
3  * (C) 2005 FUJITA Tomonori <tomof@acm.org>
4  * This code is licenced under the GPL.
5  */
6
7 #include "iscsi.h"
8 #include "iscsi_dbg.h"
9 #include "iotype.h"
10
11 static int tio_add_pages(struct tio *tio, int count)
12 {
13         int i;
14         struct page *page;
15
16         dprintk(D_GENERIC, "%p %d (%d)\n", tio, count, tio->pg_cnt);
17
18         tio->pg_cnt = count;
19
20         count *= sizeof(struct page *);
21
22         do {
23                 if (!(tio->pvec = kmalloc(count, GFP_KERNEL)))
24                         yield();
25         } while (!tio->pvec);
26
27         memset(tio->pvec, 0, count);
28
29         for (i = 0; i < tio->pg_cnt; i++) {
30                 do {
31                         if (!(page = alloc_page(GFP_KERNEL)))
32                                 yield();
33                 } while (!page);
34                 tio->pvec[i] = page;
35         }
36         return 0;
37 }
38
39 static kmem_cache_t *tio_cache;
40
41 struct tio *tio_alloc(int count)
42 {
43         struct tio *tio;
44
45         tio = kmem_cache_alloc(tio_cache, GFP_KERNEL | __GFP_NOFAIL);
46
47         tio->pg_cnt = 0;
48         tio->idx = 0;
49         tio->offset = 0;
50         tio->size = 0;
51         tio->pvec = NULL;
52
53         atomic_set(&tio->count, 1);
54
55         if (count)
56                 tio_add_pages(tio, count);
57
58         return tio;
59 }
60
61 static void tio_free(struct tio *tio)
62 {
63         int i;
64         for (i = 0; i < tio->pg_cnt; i++) {
65                 assert(tio->pvec[i]);
66                 __free_page(tio->pvec[i]);
67         }
68         kfree(tio->pvec);
69         kmem_cache_free(tio_cache, tio);
70 }
71
72 void tio_put(struct tio *tio)
73 {
74         assert(atomic_read(&tio->count));
75         if (atomic_dec_and_test(&tio->count))
76                 tio_free(tio);
77 }
78
79 void tio_get(struct tio *tio)
80 {
81         atomic_inc(&tio->count);
82 }
83
84 void tio_set(struct tio *tio, u32 size, loff_t offset)
85 {
86         tio->idx = offset >> PAGE_CACHE_SHIFT;
87         tio->offset = offset & ~PAGE_CACHE_MASK;
88         tio->size = size;
89 }
90
91 int tio_read(struct iet_volume *lu, struct tio *tio)
92 {
93         struct iotype *iot = lu->iotype;
94         assert(iot);
95         return iot->make_request ? iot->make_request(lu, tio, READ) : 0;
96 }
97
98 int tio_write(struct iet_volume *lu, struct tio *tio)
99 {
100         struct iotype *iot = lu->iotype;
101         assert(iot);
102         return iot->make_request ? iot->make_request(lu, tio, WRITE) : 0;
103 }
104
105 int tio_sync(struct iet_volume *lu, struct tio *tio)
106 {
107         struct iotype *iot = lu->iotype;
108         assert(iot);
109         return iot->sync ? iot->sync(lu, tio) : 0;
110 }
111
112 int tio_init(void)
113 {
114         tio_cache = kmem_cache_create("tio",
115                                               sizeof(struct tio), 0, 0, NULL, NULL);
116         return  tio_cache ? 0 : -ENOMEM;
117 }
118
119 void tio_exit(void)
120 {
121         if (tio_cache)
122                 kmem_cache_destroy(tio_cache);
123 }