~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Linux Cross Reference
Linux/net/khttpd/datasending.c

Version: ~ [ 2.4.0 ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /*
  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(4*4096,CurrentRequest->FileLength - CurrentRequest->BytesSent);
109                 ReadSize = min(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 }
242 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.