|
7 | 7 | * Portions Copyright (c) 1994, Regents of the University of California
|
8 | 8 | *
|
9 | 9 | * IDENTIFICATION
|
10 |
| - * $PostgreSQL: pgsql/src/backend/storage/file/fd.c,v 1.106 2004/01/26 22:35:32 tgl Exp $ |
| 10 | + * $PostgreSQL: pgsql/src/backend/storage/file/fd.c,v 1.107 2004/02/23 20:45:59 tgl Exp $ |
11 | 11 | *
|
12 | 12 | * NOTES:
|
13 | 13 | *
|
|
54 | 54 |
|
55 | 55 |
|
56 | 56 | /*
|
57 |
| - * Problem: Postgres does a system(ld...) to do dynamic loading. |
58 |
| - * This will open several extra files in addition to those used by |
59 |
| - * Postgres. We need to guarantee that there are file descriptors free |
60 |
| - * for ld to use. |
| 57 | + * We must leave some file descriptors free for system(), the dynamic loader, |
| 58 | + * and other code that tries to open files without consulting fd.c. This |
| 59 | + * is the number left free. (While we can be pretty sure we won't get |
| 60 | + * EMFILE, there's never any guarantee that we won't get ENFILE due to |
| 61 | + * other processes chewing up FDs. So it's a bad idea to try to open files |
| 62 | + * without consulting fd.c. Nonetheless we cannot control all code.) |
61 | 63 | *
|
62 |
| - *The current solutionisto limit the number of file descriptors |
63 |
| - *that this code willallocate at one time: it leaves RESERVE_FOR_LD free. |
64 |
| - * |
65 |
| - *(Even though most dynamic loaders now use dlopen(3) or the |
66 |
| - *equivalent,theOS must stillopenseveralfilestoperform the |
67 |
| - *dynamic loading. And stdin/stdout/stderr count too. Keep this here.) |
| 64 | + *Because thisisjust a fixed setting, we are effectively assuming that |
| 65 | + *no such code willleave FDs open over the long term; otherwise the slop |
| 66 | + * is likely to be insufficient. Note in particular that we expect that |
| 67 | + *loading a shared library does not result in any permanent increase in |
| 68 | + * thenumber ofopen files. (This appearstobe true on most if not |
| 69 | + *all platforms as of Feb 2004.) |
68 | 70 | */
|
69 |
| -#ifndefRESERVE_FOR_LD |
70 |
| -#defineRESERVE_FOR_LD10 |
71 |
| -#endif |
| 71 | +#defineNUM_RESERVED_FDS10 |
72 | 72 |
|
73 | 73 | /*
|
74 |
| - * We need to ensure that we have at least some file descriptors |
75 |
| - * available to postgreSQL after we've reserved the ones for LD, |
76 |
| - * so we set that value here. |
77 |
| - * |
78 |
| - * I think 10 is an appropriate value so that's what it'll be |
79 |
| - * for now. |
| 74 | + * If we have fewer than this many usable FDs after allowing for the reserved |
| 75 | + * ones, choke. |
80 | 76 | */
|
81 |
| -#ifndefFD_MINFREE |
82 |
| -#defineFD_MINFREE 10 |
83 |
| -#endif |
| 77 | +#defineFD_MINFREE10 |
| 78 | + |
84 | 79 |
|
85 | 80 | /*
|
86 |
| - * A number of platforms return values for sysconf(_SC_OPEN_MAX) that are |
87 |
| - * far beyond what they can really support. This GUC parameter limits what |
88 |
| - * we will believe. |
| 81 | + * A number of platforms allow individual processes to open many more files |
| 82 | + * than they can really support when *many* processes do the same thing. |
| 83 | + * This GUC parameter lets the DBA limit max_safe_fds to something less than |
| 84 | + * what the postmaster's initial probe suggests will work. |
89 | 85 | */
|
90 | 86 | intmax_files_per_process=1000;
|
91 | 87 |
|
| 88 | +/* |
| 89 | + * Maximum number of file descriptors to open for either VFD entries or |
| 90 | + * AllocateFile files. This is initialized to a conservative value, and |
| 91 | + * remains that way indefinitely in bootstrap or standalone-backend cases. |
| 92 | + * In normal postmaster operation, the postmaster calls set_max_safe_fds() |
| 93 | + * late in initialization to update the value, and that value is then |
| 94 | + * inherited by forked subprocesses. |
| 95 | + * |
| 96 | + * Note: the value of max_files_per_process is taken into account while |
| 97 | + * setting this variable, and so need not be tested separately. |
| 98 | + */ |
| 99 | +staticintmax_safe_fds=32;/* default if not changed */ |
| 100 | + |
92 | 101 |
|
93 | 102 | /* Debugging.... */
|
94 | 103 |
|
@@ -199,7 +208,6 @@ static void FreeVfd(File file);
|
199 | 208 | staticintFileAccess(Filefile);
|
200 | 209 | staticFilefileNameOpenFile(FileNamefileName,intfileFlags,intfileMode);
|
201 | 210 | staticchar*filepath(constchar*filename);
|
202 |
| -staticlongpg_nofile(void); |
203 | 211 | staticvoidAtProcExit_Files(intcode,Datumarg);
|
204 | 212 | staticvoidCleanupTempFiles(boolisProcExit);
|
205 | 213 |
|
@@ -236,6 +244,105 @@ pg_fdatasync(int fd)
|
236 | 244 | return0;
|
237 | 245 | }
|
238 | 246 |
|
| 247 | +/* |
| 248 | + * count_usable_fds --- count how many FDs the system will let us open, |
| 249 | + *and estimate how many are already open. |
| 250 | + * |
| 251 | + * We assume stdin (FD 0) is available for dup'ing |
| 252 | + */ |
| 253 | +staticvoid |
| 254 | +count_usable_fds(int*usable_fds,int*already_open) |
| 255 | +{ |
| 256 | +int*fd; |
| 257 | +intsize; |
| 258 | +intused=0; |
| 259 | +inthighestfd=0; |
| 260 | +intj; |
| 261 | + |
| 262 | +size=1024; |
| 263 | +fd= (int*)palloc(size*sizeof(int)); |
| 264 | + |
| 265 | +/* dup until failure ... */ |
| 266 | +for (;;) |
| 267 | +{ |
| 268 | +intthisfd; |
| 269 | + |
| 270 | +thisfd=dup(0); |
| 271 | +if (thisfd<0) |
| 272 | +{ |
| 273 | +/* Expect EMFILE or ENFILE, else it's fishy */ |
| 274 | +if (errno!=EMFILE&&errno!=ENFILE) |
| 275 | +elog(WARNING,"dup(0) failed after %d successes: %m",used); |
| 276 | +break; |
| 277 | +} |
| 278 | + |
| 279 | +if (used >=size) |
| 280 | +{ |
| 281 | +size *=2; |
| 282 | +fd= (int*)repalloc(fd,size*sizeof(int)); |
| 283 | +} |
| 284 | +fd[used++]=thisfd; |
| 285 | + |
| 286 | +if (highestfd<thisfd) |
| 287 | +highestfd=thisfd; |
| 288 | +} |
| 289 | + |
| 290 | +/* release the files we opened */ |
| 291 | +for (j=0;j<used;j++) |
| 292 | +close(fd[j]); |
| 293 | + |
| 294 | +pfree(fd); |
| 295 | + |
| 296 | +/* |
| 297 | + * Return results. usable_fds is just the number of successful dups. |
| 298 | + * We assume that the system limit is highestfd+1 (remember 0 is a legal |
| 299 | + * FD number) and so already_open is highestfd+1 - usable_fds. |
| 300 | + */ |
| 301 | +*usable_fds=used; |
| 302 | +*already_open=highestfd+1-used; |
| 303 | +} |
| 304 | + |
| 305 | +/* |
| 306 | + * set_max_safe_fds |
| 307 | + *Determine number of filedescriptors that fd.c is allowed to use |
| 308 | + */ |
| 309 | +void |
| 310 | +set_max_safe_fds(void) |
| 311 | +{ |
| 312 | +intusable_fds; |
| 313 | +intalready_open; |
| 314 | + |
| 315 | +/* |
| 316 | + * We want to set max_safe_fds to |
| 317 | + *MIN(usable_fds, max_files_per_process - already_open) |
| 318 | + * less the slop factor for files that are opened without consulting |
| 319 | + * fd.c. This ensures that we won't exceed either max_files_per_process |
| 320 | + * or the experimentally-determined EMFILE limit. |
| 321 | + */ |
| 322 | +count_usable_fds(&usable_fds,&already_open); |
| 323 | + |
| 324 | +max_safe_fds=Min(usable_fds,max_files_per_process-already_open); |
| 325 | + |
| 326 | +/* |
| 327 | + * Take off the FDs reserved for system() etc. |
| 328 | + */ |
| 329 | +max_safe_fds-=NUM_RESERVED_FDS; |
| 330 | + |
| 331 | +/* |
| 332 | + * Make sure we still have enough to get by. |
| 333 | + */ |
| 334 | +if (max_safe_fds<FD_MINFREE) |
| 335 | +ereport(FATAL, |
| 336 | +(errcode(ERRCODE_INSUFFICIENT_RESOURCES), |
| 337 | +errmsg("insufficient file descriptors available to start server process"), |
| 338 | +errdetail("System allows %d, we need at least %d.", |
| 339 | +max_safe_fds+NUM_RESERVED_FDS, |
| 340 | +FD_MINFREE+NUM_RESERVED_FDS))); |
| 341 | + |
| 342 | +elog(DEBUG2,"max_safe_fds = %d, usable_fds = %d, already_open = %d", |
| 343 | +max_safe_fds,usable_fds,already_open); |
| 344 | +} |
| 345 | + |
239 | 346 | /*
|
240 | 347 | * BasicOpenFile --- same as open(2) except can free other FDs if needed
|
241 | 348 | *
|
@@ -279,63 +386,6 @@ BasicOpenFile(FileName fileName, int fileFlags, int fileMode)
|
279 | 386 | return-1;/* failure */
|
280 | 387 | }
|
281 | 388 |
|
282 |
| -/* |
283 |
| - * pg_nofile: determine number of filedescriptors that fd.c is allowed to use |
284 |
| - */ |
285 |
| -staticlong |
286 |
| -pg_nofile(void) |
287 |
| -{ |
288 |
| -staticlongno_files=0; |
289 |
| - |
290 |
| -/* need do this calculation only once */ |
291 |
| -if (no_files==0) |
292 |
| -{ |
293 |
| -/* |
294 |
| - * Ask the system what its files-per-process limit is. |
295 |
| - */ |
296 |
| -#ifdefHAVE_SYSCONF |
297 |
| -no_files=sysconf(_SC_OPEN_MAX); |
298 |
| -if (no_files <=0) |
299 |
| -{ |
300 |
| -#ifdefNOFILE |
301 |
| -no_files= (long)NOFILE; |
302 |
| -#else |
303 |
| -no_files= (long)max_files_per_process; |
304 |
| -#endif |
305 |
| -elog(LOG,"sysconf(_SC_OPEN_MAX) failed; using %ld", |
306 |
| -no_files); |
307 |
| -} |
308 |
| -#else/* !HAVE_SYSCONF */ |
309 |
| -#ifdefNOFILE |
310 |
| -no_files= (long)NOFILE; |
311 |
| -#else |
312 |
| -no_files= (long)max_files_per_process; |
313 |
| -#endif |
314 |
| -#endif/* HAVE_SYSCONF */ |
315 |
| - |
316 |
| -/* |
317 |
| - * Some platforms return hopelessly optimistic values.Apply a |
318 |
| - * configurable upper limit. |
319 |
| - */ |
320 |
| -if (no_files> (long)max_files_per_process) |
321 |
| -no_files= (long)max_files_per_process; |
322 |
| - |
323 |
| -/* |
324 |
| - * Make sure we have enough to get by after reserving some for LD. |
325 |
| - */ |
326 |
| -if ((no_files-RESERVE_FOR_LD)<FD_MINFREE) |
327 |
| -ereport(FATAL, |
328 |
| -(errcode(ERRCODE_INSUFFICIENT_RESOURCES), |
329 |
| -errmsg("insufficient file descriptors available to start server process"), |
330 |
| -errdetail("System allows %ld, we need at least %d.", |
331 |
| -no_files,RESERVE_FOR_LD+FD_MINFREE))); |
332 |
| - |
333 |
| -no_files-=RESERVE_FOR_LD; |
334 |
| -} |
335 |
| - |
336 |
| -returnno_files; |
337 |
| -} |
338 |
| - |
339 | 389 | #if defined(FDDEBUG)
|
340 | 390 |
|
341 | 391 | staticvoid
|
@@ -439,7 +489,7 @@ LruInsert(File file)
|
439 | 489 |
|
440 | 490 | if (FileIsNotOpen(file))
|
441 | 491 | {
|
442 |
| -while (nfile+numAllocatedFiles >=pg_nofile()) |
| 492 | +while (nfile+numAllocatedFiles >=max_safe_fds) |
443 | 493 | {
|
444 | 494 | if (!ReleaseLruFile())
|
445 | 495 | break;
|
@@ -698,7 +748,7 @@ fileNameOpenFile(FileName fileName,
|
698 | 748 | file=AllocateVfd();
|
699 | 749 | vfdP=&VfdCache[file];
|
700 | 750 |
|
701 |
| -while (nfile+numAllocatedFiles >=pg_nofile()) |
| 751 | +while (nfile+numAllocatedFiles >=max_safe_fds) |
702 | 752 | {
|
703 | 753 | if (!ReleaseLruFile())
|
704 | 754 | break;
|
@@ -1042,7 +1092,14 @@ AllocateFile(char *name, char *mode)
|
1042 | 1092 |
|
1043 | 1093 | DO_DB(elog(LOG,"AllocateFile: Allocated %d",numAllocatedFiles));
|
1044 | 1094 |
|
1045 |
| -if (numAllocatedFiles >=MAX_ALLOCATED_FILES) |
| 1095 | +/* |
| 1096 | + * The test against MAX_ALLOCATED_FILES prevents us from overflowing |
| 1097 | + * allocatedFiles[]; the test against max_safe_fds prevents AllocateFile |
| 1098 | + * from hogging every one of the available FDs, which'd lead to infinite |
| 1099 | + * looping. |
| 1100 | + */ |
| 1101 | +if (numAllocatedFiles >=MAX_ALLOCATED_FILES|| |
| 1102 | +numAllocatedFiles >=max_safe_fds-1) |
1046 | 1103 | elog(ERROR,"too many private FDs demanded");
|
1047 | 1104 |
|
1048 | 1105 | TryAgain:
|
|