Project

General

Profile

Bug #2655 » lighttpd-use-single-fd-per-connection.patch

Switch from stat() to fstat() using a cached file descriptor. - tfischer, 2015-08-03 22:47

View differences:

lighttpd-1.4.36/src/base.h 2015-08-03 09:09:37.139818979 -0600
448 448
	etag_flags_t etag_flags;
449 449

  
450 450
	int conditional_is_valid[COMP_LAST_ELEMENT]; 
451
	int src_fd; /* Any logic can cache the file descriptor to the source being fetched
452
		     * and connection state machine will close it when the connection is
453
		     * shutdown.
454
		     */
451 455
} connection;
452 456

  
453 457
typedef struct {
lighttpd-1.4.36/src/connections.c 2015-08-03 13:29:35.816608136 -0600
70 70
#endif
71 71

  
72 72
	conns->ptr[conns->used]->ndx = conns->used;
73
	conns->ptr[conns->used]->src_fd = -1;
73 74
	return conns->ptr[conns->used++];
74 75
}
75 76

  
......
144 145
	log_error_write(srv, __FILE__, __LINE__, "sd",
145 146
			"closed()", con->fd);
146 147
#endif
147

  
148
	if (con->src_fd != -1) {
149
		close(con->src_fd);
150
		con->src_fd = -1;
151
	}
148 152
	connection_del(srv, con);
149 153
	connection_set_state(srv, con, CON_STATE_CONNECT);
150 154

  
......
1123 1127
		/* ok, we have the connection, register it */
1124 1128
#if 0
1125 1129
		log_error_write(srv, __FILE__, __LINE__, "sd",
1126
				"appected()", cnt);
1130
				"accepted()", cnt);
1127 1131
#endif
1128 1132
		srv->con_opened++;
1129 1133

  
......
1343 1347

  
1344 1348
			srv->con_written++;
1345 1349

  
1350
			if (-1 != con->src_fd) {
1351
				close(con->src_fd);
1352
				con->src_fd = -1;
1353
			}
1354

  
1346 1355
			if (con->keep_alive) {
1347 1356
				connection_set_state(srv, con, CON_STATE_REQUEST_START);
1348 1357

  
lighttpd-1.4.36/src/stat_cache.c 2015-08-03 13:41:17.104146897 -0600
424 424
				if (sce->stat_ts == srv->cur_ts) {
425 425
					*ret_sce = sce;
426 426
					return HANDLER_GO_ON;
427
				} else {
428
				  log_error_write(srv, __FILE__, __LINE__, "sxss",
429
						  "stale stat cache entry[", con, "]:", name->ptr);
427 430
				}
428 431
			}
429 432
		} else {
......
491 494
	 * - stat() if regular file + open() to see if we can read from it is better
492 495
	 *
493 496
	 * */
494
	if (-1 == stat(name->ptr, &st)) {
495
		return HANDLER_ERROR;
497

  
498
	/* Open the file once and cache the file descriptor.
499
	 * The changes the logic flow as before we only opened the
500
	 * file if it was a regular file.  The above comment says
501
	 * this is trouble for a named pipe.
502
	 */
503
	fd = con->src_fd;
504
	if (-1 == fd) {
505
		if (-1 == (fd = open(name->ptr, O_RDONLY))) {
506
			return HANDLER_ERROR;
507
		}
496 508
	}
497 509

  
510
	if (-1 == fstat(fd, &st)) {
511
		close(fd);
512
		con->src_fd = -1;
513
		return HANDLER_ERROR;
514
	}
498 515

  
499 516
	if (S_ISREG(st.st_mode)) {
500 517
		/* fix broken stat/open for symlinks to reg files with appended slash on freebsd,osx */
501 518
		if (name->ptr[buffer_string_length(name) - 1] == '/') {
502 519
			errno = ENOTDIR;
520
			close(fd);
521
			con->src_fd = -1;
503 522
			return HANDLER_ERROR;
504 523
		}
505

  
506
		/* try to open the file to check if we can read it */
507
		if (-1 == (fd = open(name->ptr, O_RDONLY))) {
508
			return HANDLER_ERROR;
509
		}
510
		close(fd);
511 524
	}
512 525

  
526
	con->src_fd = fd;
527

  
513 528
	if (NULL == sce) {
514 529
#ifdef DEBUG_STAT_CACHE
515 530
		int osize = splaytree_size(sc->files);
lighttpd-1.4.36/src/network_linux_sendfile.c 2015-08-03 13:28:34.455793134 -0600
129 129
			off_t offset;
130 130
			off_t toSend;
131 131
			stat_cache_entry *sce = NULL;
132
			int src_fd;
132 133

  
133 134
			offset = c->file.start + c->offset;
134 135
			toSend = c->file.length - c->offset;
135 136
			if (toSend > max_bytes) toSend = max_bytes;
136 137

  
137 138
			/* open file if not already opened */
138
			if (-1 == c->file.fd) {
139
				if (-1 == (c->file.fd = open(c->file.name->ptr, O_RDONLY))) {
139
			if (-1 != con->src_fd) {
140
				src_fd = con->src_fd;
141
			} else {
142
				if (-1 == (src_fd = open(c->file.name->ptr, O_RDONLY))) {
140 143
					log_error_write(srv, __FILE__, __LINE__, "ss", "open failed: ", strerror(errno));
141

  
142 144
					return -1;
143 145
				}
144
				fd_close_on_exec(c->file.fd);
146
				con->src_fd = src_fd;
147
			}
148
			fd_close_on_exec(src_fd);
145 149
#ifdef HAVE_POSIX_FADVISE
146
				/* tell the kernel that we want to stream the file */
147
				if (-1 == posix_fadvise(c->file.fd, 0, 0, POSIX_FADV_SEQUENTIAL)) {
148
					if (ENOSYS != errno) {
149
						log_error_write(srv, __FILE__, __LINE__, "ssd",
150
							"posix_fadvise failed:", strerror(errno), c->file.fd);
151
					}
150
			/* tell the kernel that we want to stream the file */
151
			if (-1 == posix_fadvise(src_, 0, 0, POSIX_FADV_SEQUENTIAL)) {
152
				if (ENOSYS != errno) {
153
					log_error_write(srv, __FILE__, __LINE__, "ssd",
154
							"posix_fadvise failed:", strerror(errno), src_fd);
152 155
				}
153
#endif
154 156
			}
157
#endif
155 158

  
156
			if (-1 == (r = sendfile(fd, c->file.fd, &offset, toSend))) {
159
			if (-1 == (r = sendfile(fd, src_fd, &offset, toSend))) {
157 160
				switch (errno) {
158 161
				case EAGAIN:
159 162
				case EINTR:
......
199 202
			/* check if we need a new chunk */
200 203
			if ((c->offset & ~(READ_AHEAD - 1)) != ((c->offset + r) & ~(READ_AHEAD - 1))) {
201 204
				/* tell the kernel that we want to stream the file */
202
				if (-1 == posix_fadvise(c->file.fd, (c->offset + r) & ~(READ_AHEAD - 1), READ_AHEAD, POSIX_FADV_NOREUSE)) {
205
				if (-1 == posix_fadvise(src_.fd, (c->offset + r) & ~(READ_AHEAD - 1), READ_AHEAD, POSIX_FADV_NOREUSE)) {
203 206
					log_error_write(srv, __FILE__, __LINE__, "ssd",
204
						"posix_fadvise failed:", strerror(errno), c->file.fd);
207
						"posix_fadvise failed:", strerror(errno), src_fd);
205 208
				}
206 209
			}
207 210
#endif
......
213 216

  
214 217
			if (c->offset == c->file.length) {
215 218
				chunk_finished = 1;
216

  
217
				/* chunk_free() / chunk_reset() will cleanup for us but it is a ok to be faster :) */
218

  
219
				if (c->file.fd != -1) {
220
					close(c->file.fd);
221
					c->file.fd = -1;
222
				}
223 219
			}
224 220

  
225 221
			break;
lighttpd-1.4.36/src/chunk.c 2015-08-03 09:09:37.159817933 -0600
65 65

  
66 66
	buffer_reset(c->file.name);
67 67

  
68
	if (c->file.fd != -1) {
69
		close(c->file.fd);
70
		c->file.fd = -1;
71
	}
72 68
	if (MAP_FAILED != c->file.mmap.start) {
73 69
		munmap(c->file.mmap.start, c->file.mmap.length);
74 70
		c->file.mmap.start = MAP_FAILED;
(1-1/2)