1
2
3
4
5
6
7
8
9#include <linux/iobuf.h>
10#include <linux/slab.h>
11
12int end_kio_request(struct kiobuf *kiobuf, int uptodate)
13{
14 int ret = 1;
15
16 if ((!uptodate) && !kiobuf->errno)
17 kiobuf->errno = -EIO;
18
19 if (atomic_dec_and_test(&kiobuf->io_count)) {
20 ret = 0;
21 if (kiobuf->end_io)
22 kiobuf->end_io(kiobuf);
23 wake_up(&kiobuf->wait_queue);
24 }
25
26 return ret;
27}
28
29static void kiobuf_init(struct kiobuf *iobuf)
30{
31 init_waitqueue_head(&iobuf->wait_queue);
32 atomic_set(&iobuf->io_count, 0);
33 iobuf->array_len = KIO_STATIC_PAGES;
34 iobuf->maplist = iobuf->map_array;
35 iobuf->nr_pages = 0;
36 iobuf->locked = 0;
37 iobuf->io_count.counter = 0;
38 iobuf->end_io = NULL;
39}
40
41int alloc_kiovec(int nr, struct kiobuf **bufp)
42{
43 int i;
44 struct kiobuf *iobuf;
45
46 for (i = 0; i < nr; i++) {
47 iobuf = kmalloc(sizeof(struct kiobuf), GFP_KERNEL);
48 if (!iobuf) {
49 free_kiovec(i, bufp);
50 return -ENOMEM;
51 }
52 kiobuf_init(iobuf);
53 bufp[i] = iobuf;
54 }
55
56 return 0;
57}
58
59void free_kiovec(int nr, struct kiobuf **bufp)
60{
61 int i;
62 struct kiobuf *iobuf;
63
64 for (i = 0; i < nr; i++) {
65 iobuf = bufp[i];
66 if (iobuf->locked)
67 unlock_kiovec(1, &iobuf);
68 if (iobuf->array_len > KIO_STATIC_PAGES)
69 kfree (iobuf->maplist);
70 kfree(bufp[i]);
71 }
72}
73
74int expand_kiobuf(struct kiobuf *iobuf, int wanted)
75{
76 struct page ** maplist;
77
78 if (iobuf->array_len >= wanted)
79 return 0;
80
81 maplist = (struct page **)
82 kmalloc(wanted * sizeof(struct page **), GFP_KERNEL);
83 if (!maplist)
84 return -ENOMEM;
85
86
87 if (iobuf->array_len >= wanted) {
88 kfree(maplist);
89 return 0;
90 }
91
92 memcpy (maplist, iobuf->maplist, iobuf->array_len * sizeof(struct page **));
93
94 if (iobuf->array_len > KIO_STATIC_PAGES)
95 kfree (iobuf->maplist);
96
97 iobuf->maplist = maplist;
98 iobuf->array_len = wanted;
99 return 0;
100}
101
102
103void kiobuf_wait_for_io(struct kiobuf *kiobuf)
104{
105 struct task_struct *tsk = current;
106 DECLARE_WAITQUEUE(wait, tsk);
107
108 if (atomic_read(&kiobuf->io_count) == 0)
109 return;
110
111 add_wait_queue(&kiobuf->wait_queue, &wait);
112repeat:
113 set_task_state(tsk, TASK_UNINTERRUPTIBLE);
114 if (atomic_read(&kiobuf->io_count) != 0) {
115 blk_run_queues();
116 schedule();
117 if (atomic_read(&kiobuf->io_count) != 0)
118 goto repeat;
119 }
120 tsk->state = TASK_RUNNING;
121 remove_wait_queue(&kiobuf->wait_queue, &wait);
122}
123
124
125
126