Back to home page

Nginx displayed by LXR

Source navigation ]
Diff markup ]
Identifier search ]
general search ]
 
 
Version: nginx-1.13.12 ]​[ nginx-1.12.2 ]​

0001 
0002 /*
0003  * Copyright (C) Igor Sysoev
0004  * Copyright (C) Nginx, Inc.
0005  */
0006 
0007 
0008 #include <ngx_config.h>
0009 #include <ngx_core.h>
0010 #include <ngx_event.h>
0011 
0012 
0013 #if (NGX_TEST_BUILD_SOLARIS_SENDFILEV)
0014 
0015 /* Solaris declarations */
0016 
0017 typedef struct sendfilevec {
0018     int     sfv_fd;
0019     u_int   sfv_flag;
0020     off_t   sfv_off;
0021     size_t  sfv_len;
0022 } sendfilevec_t;
0023 
0024 #define SFV_FD_SELF  -2
0025 
0026 static ssize_t sendfilev(int fd, const struct sendfilevec *vec,
0027     int sfvcnt, size_t *xferred)
0028 {
0029     return -1;
0030 }
0031 
0032 ngx_chain_t *ngx_solaris_sendfilev_chain(ngx_connection_t *c, ngx_chain_t *in,
0033     off_t limit);
0034 
0035 #endif
0036 
0037 
0038 #define NGX_SENDFILEVECS  NGX_IOVS_PREALLOCATE
0039 
0040 
0041 ngx_chain_t *
0042 ngx_solaris_sendfilev_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit)
0043 {
0044     int             fd;
0045     u_char         *prev;
0046     off_t           size, send, prev_send, aligned, fprev;
0047     size_t          sent;
0048     ssize_t         n;
0049     ngx_int_t       eintr;
0050     ngx_err_t       err;
0051     ngx_buf_t      *file;
0052     ngx_uint_t      nsfv;
0053     sendfilevec_t  *sfv, sfvs[NGX_SENDFILEVECS];
0054     ngx_event_t    *wev;
0055     ngx_chain_t    *cl;
0056 
0057     wev = c->write;
0058 
0059     if (!wev->ready) {
0060         return in;
0061     }
0062 
0063     if (!c->sendfile) {
0064         return ngx_writev_chain(c, in, limit);
0065     }
0066 
0067 
0068     /* the maximum limit size is the maximum size_t value - the page size */
0069 
0070     if (limit == 0 || limit > (off_t) (NGX_MAX_SIZE_T_VALUE - ngx_pagesize)) {
0071         limit = NGX_MAX_SIZE_T_VALUE - ngx_pagesize;
0072     }
0073 
0074 
0075     send = 0;
0076 
0077     for ( ;; ) {
0078         fd = SFV_FD_SELF;
0079         prev = NULL;
0080         fprev = 0;
0081         file = NULL;
0082         sfv = NULL;
0083         eintr = 0;
0084         sent = 0;
0085         prev_send = send;
0086 
0087         nsfv = 0;
0088 
0089         /* create the sendfilevec and coalesce the neighbouring bufs */
0090 
0091         for (cl = in; cl && send < limit; cl = cl->next) {
0092 
0093             if (ngx_buf_special(cl->buf)) {
0094                 continue;
0095             }
0096 
0097             if (ngx_buf_in_memory_only(cl->buf)) {
0098                 fd = SFV_FD_SELF;
0099 
0100                 size = cl->buf->last - cl->buf->pos;
0101 
0102                 if (send + size > limit) {
0103                     size = limit - send;
0104                 }
0105 
0106                 if (prev == cl->buf->pos) {
0107                     sfv->sfv_len += (size_t) size;
0108 
0109                 } else {
0110                     if (nsfv == NGX_SENDFILEVECS) {
0111                         break;
0112                     }
0113 
0114                     sfv = &sfvs[nsfv++];
0115 
0116                     sfv->sfv_fd = SFV_FD_SELF;
0117                     sfv->sfv_flag = 0;
0118                     sfv->sfv_off = (off_t) (uintptr_t) cl->buf->pos;
0119                     sfv->sfv_len = (size_t) size;
0120                 }
0121 
0122                 prev = cl->buf->pos + (size_t) size;
0123                 send += size;
0124 
0125             } else {
0126                 prev = NULL;
0127 
0128                 size = cl->buf->file_last - cl->buf->file_pos;
0129 
0130                 if (send + size > limit) {
0131                     size = limit - send;
0132 
0133                     aligned = (cl->buf->file_pos + size + ngx_pagesize - 1)
0134                                & ~((off_t) ngx_pagesize - 1);
0135 
0136                     if (aligned <= cl->buf->file_last) {
0137                         size = aligned - cl->buf->file_pos;
0138                     }
0139                 }
0140 
0141                 if (fd == cl->buf->file->fd && fprev == cl->buf->file_pos) {
0142                     sfv->sfv_len += (size_t) size;
0143 
0144                 } else {
0145                     if (nsfv == NGX_SENDFILEVECS) {
0146                         break;
0147                     }
0148 
0149                     sfv = &sfvs[nsfv++];
0150 
0151                     fd = cl->buf->file->fd;
0152                     sfv->sfv_fd = fd;
0153                     sfv->sfv_flag = 0;
0154                     sfv->sfv_off = cl->buf->file_pos;
0155                     sfv->sfv_len = (size_t) size;
0156                 }
0157 
0158                 file = cl->buf;
0159                 fprev = cl->buf->file_pos + size;
0160                 send += size;
0161             }
0162         }
0163 
0164         n = sendfilev(c->fd, sfvs, nsfv, &sent);
0165 
0166         if (n == -1) {
0167             err = ngx_errno;
0168 
0169             switch (err) {
0170             case NGX_EAGAIN:
0171                 break;
0172 
0173             case NGX_EINTR:
0174                 eintr = 1;
0175                 break;
0176 
0177             default:
0178                 wev->error = 1;
0179                 ngx_connection_error(c, err, "sendfilev() failed");
0180                 return NGX_CHAIN_ERROR;
0181             }
0182 
0183             ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, err,
0184                           "sendfilev() sent only %uz bytes", sent);
0185 
0186         } else if (n == 0 && sent == 0) {
0187 
0188             /*
0189              * sendfilev() is documented to return -1 with errno
0190              * set to EINVAL if svf_len is greater than the file size,
0191              * but at least Solaris 11 returns 0 instead
0192              */
0193 
0194             if (file) {
0195                 ngx_log_error(NGX_LOG_ALERT, c->log, 0,
0196                         "sendfilev() reported that \"%s\" was truncated at %O",
0197                         file->file->name.data, file->file_pos);
0198 
0199             } else {
0200                 ngx_log_error(NGX_LOG_ALERT, c->log, 0,
0201                               "sendfilev() returned 0 with memory buffers");
0202             }
0203 
0204             return NGX_CHAIN_ERROR;
0205         }
0206 
0207         ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
0208                        "sendfilev: %z %z", n, sent);
0209 
0210         c->sent += sent;
0211 
0212         in = ngx_chain_update_sent(in, sent);
0213 
0214         if (eintr) {
0215             send = prev_send + sent;
0216             continue;
0217         }
0218 
0219         if (send - prev_send != (off_t) sent) {
0220             wev->ready = 0;
0221             return in;
0222         }
0223 
0224         if (send >= limit || in == NULL) {
0225             return in;
0226         }
0227     }
0228 }