blob: e618379a73b836c30827ae451b48072394297c18 [file] [log] [blame]
Igor Sysoev0e499db2003-11-27 07:45:22 +00001
Igor Sysoevd94049b2004-02-29 21:03:02 +00002/*
Igor Sysoevff8da912004-09-29 16:00:49 +00003 * Copyright (C) Igor Sysoev
Maxim Konovalovf8d59e32012-01-18 15:07:43 +00004 * Copyright (C) Nginx, Inc.
Igor Sysoevd94049b2004-02-29 21:03:02 +00005 */
6
7
Igor Sysoev0e499db2003-11-27 07:45:22 +00008#include <ngx_config.h>
9#include <ngx_core.h>
10#include <ngx_event.h>
11
12
Igor Sysoev42b12b32004-12-02 18:40:46 +000013#if (NGX_TEST_BUILD_SOLARIS_SENDFILEV)
14
15/* Solaris declarations */
16
17typedef struct sendfilevec {
18 int sfv_fd;
19 u_int sfv_flag;
20 off_t sfv_off;
21 size_t sfv_len;
22} sendfilevec_t;
23
24#define SFV_FD_SELF -2
25
26static ssize_t sendfilev(int fd, const struct sendfilevec *vec,
Igor Sysoev23340602005-12-05 16:59:05 +000027 int sfvcnt, size_t *xferred)
Igor Sysoev42b12b32004-12-02 18:40:46 +000028{
29 return -1;
30}
31
Ruslan Ermilov1efcca32012-07-24 15:09:54 +000032ngx_chain_t *ngx_solaris_sendfilev_chain(ngx_connection_t *c, ngx_chain_t *in,
33 off_t limit);
34
Igor Sysoev42b12b32004-12-02 18:40:46 +000035#endif
36
37
Valentin Bartenev651be602014-08-13 15:11:45 +040038#define NGX_SENDFILEVECS NGX_IOVS_PREALLOCATE
Igor Sysoev95d00c42004-09-16 16:10:13 +000039
40
Igor Sysoev23340602005-12-05 16:59:05 +000041ngx_chain_t *
42ngx_solaris_sendfilev_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit)
Igor Sysoev0e499db2003-11-27 07:45:22 +000043{
44 int fd;
Igor Sysoev10a543a2004-03-16 07:10:12 +000045 u_char *prev;
Igor Sysoev42b12b32004-12-02 18:40:46 +000046 off_t size, send, prev_send, aligned, fprev;
47 size_t sent;
48 ssize_t n;
Valentin Bartenev77d61352014-08-13 15:11:45 +040049 ngx_int_t eintr;
Igor Sysoev764543e2003-11-27 19:01:37 +000050 ngx_err_t err;
Igor Sysoev95d00c42004-09-16 16:10:13 +000051 sendfilevec_t *sfv, sfvs[NGX_SENDFILEVECS];
Igor Sysoev0e499db2003-11-27 07:45:22 +000052 ngx_array_t vec;
53 ngx_event_t *wev;
Igor Sysoevc1571722005-03-19 12:38:37 +000054 ngx_chain_t *cl;
Igor Sysoev0e499db2003-11-27 07:45:22 +000055
56 wev = c->write;
57
58 if (!wev->ready) {
59 return in;
60 }
61
Igor Sysoev924bd792004-10-11 15:07:03 +000062 if (!c->sendfile) {
63 return ngx_writev_chain(c, in, limit);
64 }
65
Igor Sysoev42b12b32004-12-02 18:40:46 +000066
67 /* the maximum limit size is the maximum size_t value - the page size */
68
Igor Sysoev83a68512007-07-29 18:24:53 +000069 if (limit == 0 || limit > (off_t) (NGX_MAX_SIZE_T_VALUE - ngx_pagesize)) {
Igor Sysoevb1dfe472004-12-21 12:30:30 +000070 limit = NGX_MAX_SIZE_T_VALUE - ngx_pagesize;
Igor Sysoev42b12b32004-12-02 18:40:46 +000071 }
72
73
Igor Sysoevef066482004-06-21 15:59:32 +000074 send = 0;
Igor Sysoevef066482004-06-21 15:59:32 +000075
Igor Sysoev95d00c42004-09-16 16:10:13 +000076 vec.elts = sfvs;
77 vec.size = sizeof(sendfilevec_t);
78 vec.nalloc = NGX_SENDFILEVECS;
79 vec.pool = c->pool;
80
Igor Sysoevef066482004-06-21 15:59:32 +000081 for ( ;; ) {
Igor Sysoev0e499db2003-11-27 07:45:22 +000082 fd = SFV_FD_SELF;
83 prev = NULL;
Igor Sysoev764543e2003-11-27 19:01:37 +000084 fprev = 0;
Igor Sysoev0e499db2003-11-27 07:45:22 +000085 sfv = NULL;
86 eintr = 0;
87 sent = 0;
Igor Sysoev42b12b32004-12-02 18:40:46 +000088 prev_send = send;
Igor Sysoev0e499db2003-11-27 07:45:22 +000089
Igor Sysoev95d00c42004-09-16 16:10:13 +000090 vec.nelts = 0;
Igor Sysoev764543e2003-11-27 19:01:37 +000091
Igor Sysoev369145c2004-05-28 15:49:23 +000092 /* create the sendfilevec and coalesce the neighbouring bufs */
Igor Sysoev0e499db2003-11-27 07:45:22 +000093
Maxim Dounin578c02f2012-04-17 09:13:15 +000094 for (cl = in; cl && send < limit; cl = cl->next) {
95
Igor Sysoev67f450d2004-06-01 06:04:46 +000096 if (ngx_buf_special(cl->buf)) {
Igor Sysoev0e499db2003-11-27 07:45:22 +000097 continue;
98 }
99
Igor Sysoev67f450d2004-06-01 06:04:46 +0000100 if (ngx_buf_in_memory_only(cl->buf)) {
Igor Sysoev0e499db2003-11-27 07:45:22 +0000101 fd = SFV_FD_SELF;
102
Igor Sysoevef066482004-06-21 15:59:32 +0000103 size = cl->buf->last - cl->buf->pos;
104
105 if (send + size > limit) {
106 size = limit - send;
107 }
108
Igor Sysoev67f450d2004-06-01 06:04:46 +0000109 if (prev == cl->buf->pos) {
Igor Sysoev42b12b32004-12-02 18:40:46 +0000110 sfv->sfv_len += (size_t) size;
Igor Sysoev0e499db2003-11-27 07:45:22 +0000111
112 } else {
Maxim Dounin578c02f2012-04-17 09:13:15 +0000113 if (vec.nelts >= IOV_MAX) {
114 break;
115 }
116
Igor Sysoevc1571722005-03-19 12:38:37 +0000117 sfv = ngx_array_push(&vec);
118 if (sfv == NULL) {
Igor Sysoev95d00c42004-09-16 16:10:13 +0000119 return NGX_CHAIN_ERROR;
120 }
121
Igor Sysoev0e499db2003-11-27 07:45:22 +0000122 sfv->sfv_fd = SFV_FD_SELF;
123 sfv->sfv_flag = 0;
Igor Sysoev67f450d2004-06-01 06:04:46 +0000124 sfv->sfv_off = (off_t) (uintptr_t) cl->buf->pos;
Igor Sysoev42b12b32004-12-02 18:40:46 +0000125 sfv->sfv_len = (size_t) size;
Igor Sysoev0e499db2003-11-27 07:45:22 +0000126 }
127
Igor Sysoev42b12b32004-12-02 18:40:46 +0000128 prev = cl->buf->pos + (size_t) size;
Igor Sysoevef066482004-06-21 15:59:32 +0000129 send += size;
Igor Sysoev0e499db2003-11-27 07:45:22 +0000130
131 } else {
132 prev = NULL;
133
Igor Sysoev42b12b32004-12-02 18:40:46 +0000134 size = cl->buf->file_last - cl->buf->file_pos;
Igor Sysoevef066482004-06-21 15:59:32 +0000135
136 if (send + size > limit) {
137 size = limit - send;
138
139 aligned = (cl->buf->file_pos + size + ngx_pagesize - 1)
Igor Sysoev57a713c2007-04-23 21:32:13 +0000140 & ~((off_t) ngx_pagesize - 1);
Igor Sysoevef066482004-06-21 15:59:32 +0000141
142 if (aligned <= cl->buf->file_last) {
143 size = aligned - cl->buf->file_pos;
144 }
145 }
146
Igor Sysoev67f450d2004-06-01 06:04:46 +0000147 if (fd == cl->buf->file->fd && fprev == cl->buf->file_pos) {
Igor Sysoev42b12b32004-12-02 18:40:46 +0000148 sfv->sfv_len += (size_t) size;
Igor Sysoev0e499db2003-11-27 07:45:22 +0000149
150 } else {
Maxim Dounin578c02f2012-04-17 09:13:15 +0000151 if (vec.nelts >= IOV_MAX) {
152 break;
153 }
154
Igor Sysoevc1571722005-03-19 12:38:37 +0000155 sfv = ngx_array_push(&vec);
156 if (sfv == NULL) {
Igor Sysoev95d00c42004-09-16 16:10:13 +0000157 return NGX_CHAIN_ERROR;
158 }
159
Igor Sysoev67f450d2004-06-01 06:04:46 +0000160 fd = cl->buf->file->fd;
Igor Sysoev0e499db2003-11-27 07:45:22 +0000161 sfv->sfv_fd = fd;
162 sfv->sfv_flag = 0;
Igor Sysoev67f450d2004-06-01 06:04:46 +0000163 sfv->sfv_off = cl->buf->file_pos;
Igor Sysoev42b12b32004-12-02 18:40:46 +0000164 sfv->sfv_len = (size_t) size;
Igor Sysoev0e499db2003-11-27 07:45:22 +0000165 }
166
Igor Sysoevef066482004-06-21 15:59:32 +0000167 fprev = cl->buf->file_pos + size;
168 send += size;
Igor Sysoev0e499db2003-11-27 07:45:22 +0000169 }
170 }
171
Igor Sysoev764543e2003-11-27 19:01:37 +0000172 n = sendfilev(c->fd, vec.elts, vec.nelts, &sent);
Igor Sysoev0e499db2003-11-27 07:45:22 +0000173
174 if (n == -1) {
175 err = ngx_errno;
176
Igor Sysoev8c491a72009-08-30 09:42:29 +0000177 switch (err) {
178 case NGX_EAGAIN:
179 break;
Igor Sysoev54498db2004-02-11 17:08:49 +0000180
Igor Sysoev8c491a72009-08-30 09:42:29 +0000181 case NGX_EINTR:
182 eintr = 1;
183 break;
Igor Sysoev54498db2004-02-11 17:08:49 +0000184
Igor Sysoev8c491a72009-08-30 09:42:29 +0000185 default:
Igor Sysoev0e499db2003-11-27 07:45:22 +0000186 wev->error = 1;
Igor Sysoev54498db2004-02-11 17:08:49 +0000187 ngx_connection_error(c, err, "sendfilev() failed");
Igor Sysoev0e499db2003-11-27 07:45:22 +0000188 return NGX_CHAIN_ERROR;
189 }
Igor Sysoev8c491a72009-08-30 09:42:29 +0000190
191 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, err,
192 "sendfilev() sent only %uz bytes", sent);
Igor Sysoev0e499db2003-11-27 07:45:22 +0000193 }
194
Igor Sysoev54498db2004-02-11 17:08:49 +0000195 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
Igor Sysoev1b735832004-11-11 14:07:14 +0000196 "sendfilev: %z %z", n, sent);
Igor Sysoev0e499db2003-11-27 07:45:22 +0000197
198 c->sent += sent;
199
Valentin Bartenev41ed9732014-11-19 21:16:19 +0300200 in = ngx_chain_update_sent(in, sent);
Igor Sysoev0e499db2003-11-27 07:45:22 +0000201
Igor Sysoevef066482004-06-21 15:59:32 +0000202 if (eintr) {
Valentin Bartenev840b3472014-08-27 20:51:01 +0400203 send = prev_send + sent;
Igor Sysoevef066482004-06-21 15:59:32 +0000204 continue;
205 }
206
Valentin Bartenev77d61352014-08-13 15:11:45 +0400207 if (send - prev_send != (off_t) sent) {
Igor Sysoevef066482004-06-21 15:59:32 +0000208 wev->ready = 0;
Gleb Smirnoff65e37b42013-08-08 15:06:39 +0400209 return in;
Igor Sysoevef066482004-06-21 15:59:32 +0000210 }
211
Gleb Smirnoff65e37b42013-08-08 15:06:39 +0400212 if (send >= limit || in == NULL) {
213 return in;
Igor Sysoevef066482004-06-21 15:59:32 +0000214 }
Igor Sysoev0e499db2003-11-27 07:45:22 +0000215 }
Igor Sysoev0e499db2003-11-27 07:45:22 +0000216}