OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [net/] [khttpd/] [datasending.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/*
2
 
3
kHTTPd -- the next generation
4
 
5
Send actual file-data to the connections
6
 
7
*/
8
/****************************************************************
9
 *      This program is free software; you can redistribute it and/or modify
10
 *      it under the terms of the GNU General Public License as published by
11
 *      the Free Software Foundation; either version 2, or (at your option)
12
 *      any later version.
13
 *
14
 *      This program is distributed in the hope that it will be useful,
15
 *      but WITHOUT ANY WARRANTY; without even the implied warranty of
16
 *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17
 *      GNU General Public License for more details.
18
 *
19
 *      You should have received a copy of the GNU General Public License
20
 *      along with this program; if not, write to the Free Software
21
 *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22
 *
23
 ****************************************************************/
24
 
25
/*
26
 
27
Purpose:
28
 
29
DataSending does the actual sending of file-data to the socket.
30
 
31
Note: Since asynchronous reads do not -yet- exists, this might block!
32
 
33
Return value:
34
        The number of requests that changed status (ie: made some progress)
35
*/
36
 
37
#include <linux/config.h>
38
#include <linux/kernel.h>
39
#include <linux/locks.h>
40
#include <linux/skbuff.h>
41
 
42
#include <net/tcp.h>
43
 
44
#include <asm/uaccess.h>
45
#include <linux/smp_lock.h>
46
 
47
#include "structure.h"
48
#include "prototypes.h"
49
 
50
static  char    *Block[CONFIG_KHTTPD_NUMCPU];
51
 
52
/*
53
 
54
This send_actor is for use with do_generic_file_read (ie sendfile())
55
It sends the data to the socket indicated by desc->buf.
56
 
57
*/
58
static int sock_send_actor(read_descriptor_t * desc, struct page *page, unsigned long offset, unsigned long size)
59
{
60
        int written;
61
        char *kaddr;
62
        unsigned long count = desc->count;
63
        struct socket *sock = (struct socket *) desc->buf;
64
        mm_segment_t old_fs;
65
 
66
        if (size > count)
67
                size = count;
68
        old_fs = get_fs();
69
        set_fs(KERNEL_DS);
70
 
71
        kaddr = kmap(page);
72
        written = SendBuffer_async(sock, kaddr + offset, size);
73
        kunmap(page);
74
        set_fs(old_fs);
75
        if (written < 0) {
76
                desc->error = written;
77
                written = 0;
78
        }
79
        desc->count = count - written;
80
        desc->written += written;
81
        return written;
82
}
83
 
84
 
85
 
86
 
87
int DataSending(const int CPUNR)
88
{
89
        struct http_request *CurrentRequest,**Prev;
90
        int count = 0;
91
 
92
        EnterFunction("DataSending");
93
 
94
        Prev = &(threadinfo[CPUNR].DataSendingQueue);
95
        CurrentRequest = threadinfo[CPUNR].DataSendingQueue;
96
        while (CurrentRequest!=NULL)
97
        {
98
                int ReadSize,Space;
99
                int retval;
100
 
101
 
102
                /* First, test if the socket has any buffer-space left.
103
                   If not, no need to actually try to send something.  */
104
 
105
 
106
                Space = sock_wspace(CurrentRequest->sock->sk);
107
 
108
                ReadSize = min_t(int, 4 * 4096, CurrentRequest->FileLength - CurrentRequest->BytesSent);
109
                ReadSize = min_t(int, ReadSize, Space);
110
 
111
                if (ReadSize>0)
112
                {
113
                        struct inode *inode;
114
 
115
                        inode = CurrentRequest->filp->f_dentry->d_inode;
116
 
117
                        if (inode->i_mapping->a_ops->readpage) {
118
                                /* This does the actual transfer using sendfile */
119
                                read_descriptor_t desc;
120
                                loff_t *ppos;
121
 
122
                                CurrentRequest->filp->f_pos = CurrentRequest->BytesSent;
123
 
124
                                ppos = &CurrentRequest->filp->f_pos;
125
 
126
                                desc.written = 0;
127
                                desc.count = ReadSize;
128
                                desc.buf = (char *) CurrentRequest->sock;
129
                                desc.error = 0;
130
                                do_generic_file_read(CurrentRequest->filp, ppos, &desc, sock_send_actor);
131
                                if (desc.written>0)
132
                                {
133
                                        CurrentRequest->BytesSent += desc.written;
134
                                        count++;
135
                                }
136
                        }
137
                        else  /* FS doesn't support sendfile() */
138
                        {
139
                                mm_segment_t oldfs;
140
                                CurrentRequest->filp->f_pos = CurrentRequest->BytesSent;
141
 
142
                                oldfs = get_fs(); set_fs(KERNEL_DS);
143
                                retval = CurrentRequest->filp->f_op->read(CurrentRequest->filp, Block[CPUNR], ReadSize, &CurrentRequest->filp->f_pos);
144
                                set_fs(oldfs);
145
 
146
                                if (retval>0)
147
                                {
148
                                        retval = SendBuffer_async(CurrentRequest->sock,Block[CPUNR],(size_t)retval);
149
                                        if (retval>0)
150
                                        {
151
                                                CurrentRequest->BytesSent += retval;
152
                                                count++;
153
                                        }
154
                                }
155
                        }
156
 
157
                }
158
 
159
                /*
160
                   If end-of-file or closed connection: Finish this request
161
                   by moving it to the "logging" queue.
162
                */
163
                if ((CurrentRequest->BytesSent>=CurrentRequest->FileLength)||
164
                    (CurrentRequest->sock->sk->state!=TCP_ESTABLISHED
165
                     && CurrentRequest->sock->sk->state!=TCP_CLOSE_WAIT))
166
                {
167
                        struct http_request *Next;
168
                        Next = CurrentRequest->Next;
169
 
170
                        lock_sock(CurrentRequest->sock->sk);
171
                        if  (CurrentRequest->sock->sk->state == TCP_ESTABLISHED ||
172
                             CurrentRequest->sock->sk->state == TCP_CLOSE_WAIT)
173
                        {
174
                                CurrentRequest->sock->sk->tp_pinfo.af_tcp.nonagle = 0;
175
                                tcp_push_pending_frames(CurrentRequest->sock->sk,&(CurrentRequest->sock->sk->tp_pinfo.af_tcp));
176
                        }
177
                        release_sock(CurrentRequest->sock->sk);
178
 
179
                        (*Prev) = CurrentRequest->Next;
180
 
181
                        CurrentRequest->Next = threadinfo[CPUNR].LoggingQueue;
182
                        threadinfo[CPUNR].LoggingQueue = CurrentRequest;
183
 
184
                        CurrentRequest = Next;
185
                        continue;
186
 
187
                }
188
 
189
 
190
                Prev = &(CurrentRequest->Next);
191
                CurrentRequest = CurrentRequest->Next;
192
        }
193
 
194
        LeaveFunction("DataSending");
195
        return count;
196
}
197
 
198
int InitDataSending(int ThreadCount)
199
{
200
        int I,I2;
201
 
202
        EnterFunction("InitDataSending");
203
        I=0;
204
        while (I<ThreadCount)
205
        {
206
                Block[I] = (char*)get_free_page((int)GFP_KERNEL);
207
                if (Block[I] == NULL)
208
                {
209
                        I2=0;
210
                        while (I2<I-1)
211
                        {
212
                                free_page((unsigned long)Block[I2++]);
213
                        }
214
                        LeaveFunction("InitDataSending - abort");
215
                        return -1;
216
                }
217
                I++;
218
        }
219
        LeaveFunction("InitDataSending");
220
        return 0;
221
}
222
 
223
void StopDataSending(const int CPUNR)
224
{
225
        struct http_request *CurrentRequest,*Next;
226
 
227
        EnterFunction("StopDataSending");
228
        CurrentRequest = threadinfo[CPUNR].DataSendingQueue;
229
 
230
        while (CurrentRequest!=NULL)
231
        {
232
                Next = CurrentRequest->Next;
233
                CleanUpRequest(CurrentRequest);
234
                CurrentRequest=Next;
235
        }
236
 
237
        threadinfo[CPUNR].DataSendingQueue = NULL;
238
 
239
        free_page( (unsigned long)Block[CPUNR]);
240
        LeaveFunction("StopDataSending");
241
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.