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