~ubuntu-branches/ubuntu/trusty/nginx/trusty-proposed

« back to all changes in this revision

Viewing changes to src/os/unix/ngx_freebsd_sendfile_chain.c

  • Committer: Package Import Robot
  • Author(s): Kartik Mistry
  • Date: 2013-04-25 12:51:45 UTC
  • mfrom: (1.3.28)
  • mto: (1.3.29) (15.1.2 experimental)
  • mto: This revision was merged to the branch mainline in revision 64.
  • Revision ID: package-import@ubuntu.com-20130425125145-ugl0wor6bq0u5eae
Tags: upstream-1.4.0
ImportĀ upstreamĀ versionĀ 1.4.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
 
2
2
/*
3
3
 * Copyright (C) Igor Sysoev
 
4
 * Copyright (C) Nginx, Inc.
4
5
 */
5
6
 
6
7
 
11
12
 
12
13
/*
13
14
 * Although FreeBSD sendfile() allows to pass a header and a trailer,
14
 
 * it can not send a header with a part of the file in one packet until
 
15
 * it cannot send a header with a part of the file in one packet until
15
16
 * FreeBSD 5.3.  Besides, over the fast ethernet connection sendfile()
16
17
 * may send the partially filled packets, i.e. the 8 file pages may be sent
17
18
 * as the 11 full 1460-bytes packets, then one incomplete 324-bytes packet,
18
19
 * and then again the 11 full 1460-bytes packets.
19
20
 *
20
 
 * Threfore we use the TCP_NOPUSH option (similar to Linux's TCP_CORK)
 
21
 * Therefore we use the TCP_NOPUSH option (similar to Linux's TCP_CORK)
21
22
 * to postpone the sending - it not only sends a header and the first part of
22
23
 * the file in one packet, but also sends the file pages in the full packets.
23
24
 *
40
41
ngx_chain_t *
41
42
ngx_freebsd_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit)
42
43
{
43
 
    int              rc;
 
44
    int              rc, flags;
44
45
    u_char          *prev;
45
46
    off_t            size, send, prev_send, aligned, sent, fprev;
46
47
    size_t           header_size, file_size;
78
79
 
79
80
    send = 0;
80
81
    eagain = 0;
 
82
    flags = 0;
81
83
 
82
84
    header.elts = headers;
83
85
    header.size = sizeof(struct iovec);
105
107
        prev = NULL;
106
108
        iov = NULL;
107
109
 
108
 
        for (cl = in;
109
 
             cl && header.nelts < IOV_MAX && send < limit;
110
 
             cl = cl->next)
111
 
        {
 
110
        for (cl = in; cl && send < limit; cl = cl->next) {
 
111
 
112
112
            if (ngx_buf_special(cl->buf)) {
113
113
                continue;
114
114
            }
127
127
                iov->iov_len += (size_t) size;
128
128
 
129
129
            } else {
 
130
                if (header.nelts >= IOV_MAX){
 
131
                    break;
 
132
                }
 
133
 
130
134
                iov = ngx_array_push(&header);
131
135
                if (iov == NULL) {
132
136
                    return NGX_CHAIN_ERROR;
176
180
 
177
181
        if (file) {
178
182
 
179
 
            /* create the tailer iovec and coalesce the neighbouring bufs */
 
183
            /* create the trailer iovec and coalesce the neighbouring bufs */
180
184
 
181
185
            prev = NULL;
182
186
            iov = NULL;
183
187
 
184
 
            while (cl && header.nelts < IOV_MAX && send < limit) {
 
188
            while (cl && send < limit) {
185
189
 
186
190
                if (ngx_buf_special(cl->buf)) {
187
191
                    cl = cl->next;
202
206
                    iov->iov_len += (size_t) size;
203
207
 
204
208
                } else {
 
209
                    if (trailer.nelts >= IOV_MAX){
 
210
                        break;
 
211
                    }
 
212
 
205
213
                    iov = ngx_array_push(&trailer);
206
214
                    if (iov == NULL) {
207
215
                        return NGX_CHAIN_ERROR;
245
253
                }
246
254
            }
247
255
 
248
 
            hdtr.headers = (struct iovec *) header.elts;
 
256
            /*
 
257
             * sendfile() does unneeded work if sf_hdtr's count is 0,
 
258
             * but corresponding pointer is not NULL
 
259
             */
 
260
 
 
261
            hdtr.headers = header.nelts ? (struct iovec *) header.elts: NULL;
249
262
            hdtr.hdr_cnt = header.nelts;
250
 
            hdtr.trailers = (struct iovec *) trailer.elts;
 
263
            hdtr.trailers = trailer.nelts ? (struct iovec *) trailer.elts: NULL;
251
264
            hdtr.trl_cnt = trailer.nelts;
252
265
 
253
266
            /*
261
274
 
262
275
            sent = 0;
263
276
 
 
277
#if (NGX_HAVE_AIO_SENDFILE)
 
278
            flags = c->aio_sendfile ? SF_NODISKIO : 0;
 
279
#endif
 
280
 
264
281
            rc = sendfile(file->file->fd, c->fd, file->file_pos,
265
 
                          file_size + header_size, &hdtr, &sent, 0);
 
282
                          file_size + header_size, &hdtr, &sent, flags);
266
283
 
267
284
            if (rc == -1) {
268
285
                err = ngx_errno;
269
286
 
270
 
                if (err == NGX_EAGAIN || err == NGX_EINTR) {
271
 
                    if (err == NGX_EINTR) {
272
 
                        eintr = 1;
273
 
 
274
 
                    } else {
275
 
                        eagain = 1;
276
 
                    }
277
 
 
278
 
                    ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, err,
279
 
                                   "sendfile() sent only %O bytes", sent);
280
 
 
281
 
                } else {
 
287
                switch (err) {
 
288
                case NGX_EAGAIN:
 
289
                    eagain = 1;
 
290
                    break;
 
291
 
 
292
                case NGX_EINTR:
 
293
                    eintr = 1;
 
294
                    break;
 
295
 
 
296
#if (NGX_HAVE_AIO_SENDFILE)
 
297
                case NGX_EBUSY:
 
298
                    c->busy_sendfile = file;
 
299
                    break;
 
300
#endif
 
301
 
 
302
                default:
282
303
                    wev->error = 1;
283
304
                    (void) ngx_connection_error(c, err, "sendfile() failed");
284
305
                    return NGX_CHAIN_ERROR;
285
306
                }
286
 
            }
 
307
 
 
308
                ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, err,
 
309
                               "sendfile() sent only %O bytes", sent);
287
310
 
288
311
            /*
289
312
             * sendfile() in FreeBSD 3.x-4.x may return value >= 0
290
313
             * on success, although only 0 is documented
291
314
             */
292
315
 
293
 
            if (rc >= 0 && sent == 0) {
 
316
            } else if (rc >= 0 && sent == 0) {
294
317
 
295
318
                /*
296
319
                 * if rc is OK and sent equal to zero, then someone
299
322
                 */
300
323
 
301
324
                ngx_log_error(NGX_LOG_ALERT, c->log, 0,
302
 
                              "sendfile() reported that \"%s\" was truncated",
303
 
                              file->file->name.data);
 
325
                         "sendfile() reported that \"%s\" was truncated at %O",
 
326
                         file->file->name.data, file->file_pos);
304
327
 
305
328
                return NGX_CHAIN_ERROR;
306
329
            }
318
341
            if (rc == -1) {
319
342
                err = ngx_errno;
320
343
 
321
 
                if (err == NGX_EAGAIN || err == NGX_EINTR) {
322
 
                    if (err == NGX_EINTR) {
323
 
                        eintr = 1;
324
 
                    }
325
 
 
326
 
                    ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, err,
327
 
                                   "writev() not ready");
328
 
 
329
 
                } else {
 
344
                switch (err) {
 
345
                case NGX_EAGAIN:
 
346
                    break;
 
347
 
 
348
                case NGX_EINTR:
 
349
                    eintr = 1;
 
350
                    break;
 
351
 
 
352
                default:
330
353
                    wev->error = 1;
331
354
                    ngx_connection_error(c, err, "writev() failed");
332
355
                    return NGX_CHAIN_ERROR;
333
356
                }
 
357
 
 
358
                ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, err,
 
359
                               "writev() not ready");
334
360
            }
335
361
 
336
362
            sent = rc > 0 ? rc : 0;
379
405
            break;
380
406
        }
381
407
 
 
408
#if (NGX_HAVE_AIO_SENDFILE)
 
409
        if (c->busy_sendfile) {
 
410
            return cl;
 
411
        }
 
412
#endif
 
413
 
382
414
        if (eagain) {
383
415
 
384
416
            /*