File: /usr/src/linux/fs/iobuf.c
1 /*
2 * iobuf.c
3 *
4 * Keep track of the general-purpose IO-buffer structures used to track
5 * abstract kernel-space io buffers.
6 *
7 */
8
9 #include <linux/iobuf.h>
10 #include <linux/slab.h>
11 #include <linux/vmalloc.h>
12
13 void end_kio_request(struct kiobuf *kiobuf, int uptodate)
14 {
15 if ((!uptodate) && !kiobuf->errno)
16 kiobuf->errno = -EIO;
17
18 if (atomic_dec_and_test(&kiobuf->io_count)) {
19 if (kiobuf->end_io)
20 kiobuf->end_io(kiobuf);
21 wake_up(&kiobuf->wait_queue);
22 }
23 }
24
25 static void kiobuf_init(struct kiobuf *iobuf)
26 {
27 memset(iobuf, 0, sizeof(*iobuf));
28 init_waitqueue_head(&iobuf->wait_queue);
29 iobuf->array_len = KIO_STATIC_PAGES;
30 iobuf->maplist = iobuf->map_array;
31 }
32
33 int alloc_kiobuf_bhs(struct kiobuf * kiobuf)
34 {
35 int i;
36
37 for (i = 0; i < KIO_MAX_SECTORS; i++)
38 if (!(kiobuf->bh[i] = kmem_cache_alloc(bh_cachep, SLAB_KERNEL))) {
39 while (i--) {
40 kmem_cache_free(bh_cachep, kiobuf->bh[i]);
41 kiobuf->bh[i] = NULL;
42 }
43 return -ENOMEM;
44 }
45 return 0;
46 }
47
48 void free_kiobuf_bhs(struct kiobuf * kiobuf)
49 {
50 int i;
51
52 for (i = 0; i < KIO_MAX_SECTORS; i++) {
53 kmem_cache_free(bh_cachep, kiobuf->bh[i]);
54 kiobuf->bh[i] = NULL;
55 }
56 }
57
58 int alloc_kiovec(int nr, struct kiobuf **bufp)
59 {
60 int i;
61 struct kiobuf *iobuf;
62
63 for (i = 0; i < nr; i++) {
64 iobuf = vmalloc(sizeof(struct kiobuf));
65 if (!iobuf) {
66 free_kiovec(i, bufp);
67 return -ENOMEM;
68 }
69 kiobuf_init(iobuf);
70 if (alloc_kiobuf_bhs(iobuf)) {
71 vfree(iobuf);
72 free_kiovec(i, bufp);
73 return -ENOMEM;
74 }
75 bufp[i] = iobuf;
76 }
77
78 return 0;
79 }
80
81 void free_kiovec(int nr, struct kiobuf **bufp)
82 {
83 int i;
84 struct kiobuf *iobuf;
85
86 for (i = 0; i < nr; i++) {
87 iobuf = bufp[i];
88 if (iobuf->locked)
89 unlock_kiovec(1, &iobuf);
90 if (iobuf->array_len > KIO_STATIC_PAGES)
91 kfree (iobuf->maplist);
92 free_kiobuf_bhs(iobuf);
93 vfree(bufp[i]);
94 }
95 }
96
97 int expand_kiobuf(struct kiobuf *iobuf, int wanted)
98 {
99 struct page ** maplist;
100
101 if (iobuf->array_len >= wanted)
102 return 0;
103
104 maplist = (struct page **)
105 kmalloc(wanted * sizeof(struct page **), GFP_KERNEL);
106 if (!maplist)
107 return -ENOMEM;
108
109 /* Did it grow while we waited? */
110 if (iobuf->array_len >= wanted) {
111 kfree(maplist);
112 return 0;
113 }
114
115 memcpy (maplist, iobuf->maplist, iobuf->array_len * sizeof(struct page **));
116
117 if (iobuf->array_len > KIO_STATIC_PAGES)
118 kfree (iobuf->maplist);
119
120 iobuf->maplist = maplist;
121 iobuf->array_len = wanted;
122 return 0;
123 }
124
125
126 void kiobuf_wait_for_io(struct kiobuf *kiobuf)
127 {
128 struct task_struct *tsk = current;
129 DECLARE_WAITQUEUE(wait, tsk);
130
131 if (atomic_read(&kiobuf->io_count) == 0)
132 return;
133
134 add_wait_queue(&kiobuf->wait_queue, &wait);
135 repeat:
136 set_task_state(tsk, TASK_UNINTERRUPTIBLE);
137 if (atomic_read(&kiobuf->io_count) != 0) {
138 run_task_queue(&tq_disk);
139 schedule();
140 if (atomic_read(&kiobuf->io_count) != 0)
141 goto repeat;
142 }
143 tsk->state = TASK_RUNNING;
144 remove_wait_queue(&kiobuf->wait_queue, &wait);
145 }
146
147
148
149