* nscd/connection.c (DEFAULT_DATASIZE_PER_BUCKET): Move to nscd.h.

(dbs): Initialize max_db_size fields.
	(nscd_init): When mapping the database, use max_db_size as the
	mapping size even if it is bigger than the file size.
	* nscd/mem.c (mempool_alloc): When resizing the file make sure the
	limit in max_db_size is not exceeded.  Don't use mremap, just
	posix_fallocate is enough (according to Linus).  Use posix_fallocate
	correctly.
	* nscd/nscd.conf: Add max-db-size parameters.
	* nscd/nscd.h (struct database_dyn): Add max_db_size field.
	Define DEFAULT_MAX_DB_SIZE and DEFAULT_DATASIZE_PER_BUCKET.
	Temporarily define TEMP_FAILURE_RETRY_VAL here.
	* nscd/nscd_conf.c (nscd_parse_file): Parse max-db-size parameter
	and add sanity checks for it.

	* nscd/aicache.c (addhstaiX): Use send with MSG_NOSIGNAL not write to
	send reply.
	* nscd/connection.c (writeall): Likewise.
	(handle_request): Likewise.
	* nscd/grpcache.c (cache_addgr): Likewise.
	* nscd/hstcache.c (cache_addhst): Likewise.
	* nscd/initgrcache.c (addinitgroupsX): Likewise.
	* nscd/nscd.c (parse_opt): Likewise.
	* nscd/nscd_stat.c (send_stats): Likewise.
	(receive_print_stats): Likewise.
	* nscd/pwdcache.c (cache_addpw): Likewise.
This commit is contained in:
Ulrich Drepper 2005-08-23 23:21:53 +00:00
parent fd4af66481
commit 2c210d1eb8
13 changed files with 126 additions and 26 deletions

View File

@ -1,5 +1,32 @@
2005-08-23 Ulrich Drepper <drepper@redhat.com> 2005-08-23 Ulrich Drepper <drepper@redhat.com>
* nscd/connection.c (DEFAULT_DATASIZE_PER_BUCKET): Move to nscd.h.
(dbs): Initialize max_db_size fields.
(nscd_init): When mapping the database, use max_db_size as the
mapping size even if it is bigger than the file size.
* nscd/mem.c (mempool_alloc): When resizing the file make sure the
limit in max_db_size is not exceeded. Don't use mremap, just
posix_fallocate is enough (according to Linus). Use posix_fallocate
correctly.
* nscd/nscd.conf: Add max-db-size parameters.
* nscd/nscd.h (struct database_dyn): Add max_db_size field.
Define DEFAULT_MAX_DB_SIZE and DEFAULT_DATASIZE_PER_BUCKET.
Temporarily define TEMP_FAILURE_RETRY_VAL here.
* nscd/nscd_conf.c (nscd_parse_file): Parse max-db-size parameter
and add sanity checks for it.
* nscd/aicache.c (addhstaiX): Use send with MSG_NOSIGNAL not write to
send reply.
* nscd/connection.c (writeall): Likewise.
(handle_request): Likewise.
* nscd/grpcache.c (cache_addgr): Likewise.
* nscd/hstcache.c (cache_addhst): Likewise.
* nscd/initgrcache.c (addinitgroupsX): Likewise.
* nscd/nscd.c (parse_opt): Likewise.
* nscd/nscd_stat.c (send_stats): Likewise.
(receive_print_stats): Likewise.
* nscd/pwdcache.c (cache_addpw): Likewise.
* sysdeps/unix/sysv/linux/Versions: Export Inotify_* syscalls. * sysdeps/unix/sysv/linux/Versions: Export Inotify_* syscalls.
2005-08-22 Jakub Jelinek <jakub@redhat.com> 2005-08-22 Jakub Jelinek <jakub@redhat.com>

View File

@ -399,7 +399,7 @@ addhstaiX (struct database_dyn *db, int fd, request_header *req,
total = sizeof (notfound); total = sizeof (notfound);
if (fd != -1) if (fd != -1)
TEMP_FAILURE_RETRY (write (fd, &notfound, total)); TEMP_FAILURE_RETRY (send (fd, &notfound, total, MSG_NOSIGNAL));
dataset = mempool_alloc (db, sizeof (struct dataset) + req->key_len); dataset = mempool_alloc (db, sizeof (struct dataset) + req->key_len);
/* If we cannot permanently store the result, so be it. */ /* If we cannot permanently store the result, so be it. */

View File

@ -48,10 +48,6 @@
#include "selinux.h" #include "selinux.h"
/* Number of bytes of data we initially reserve for each hash table bucket. */
#define DEFAULT_DATASIZE_PER_BUCKET 1024
/* Wrapper functions with error checking for standard functions. */ /* Wrapper functions with error checking for standard functions. */
extern void *xmalloc (size_t n); extern void *xmalloc (size_t n);
extern void *xcalloc (size_t n, size_t s); extern void *xcalloc (size_t n, size_t s);
@ -104,6 +100,7 @@ struct database_dyn dbs[lastdb] =
.check_file = 1, .check_file = 1,
.persistent = 0, .persistent = 0,
.shared = 0, .shared = 0,
.max_db_size = DEFAULT_MAX_DB_SIZE,
.filename = "/etc/passwd", .filename = "/etc/passwd",
.db_filename = _PATH_NSCD_PASSWD_DB, .db_filename = _PATH_NSCD_PASSWD_DB,
.disabled_iov = &pwd_iov_disabled, .disabled_iov = &pwd_iov_disabled,
@ -119,6 +116,7 @@ struct database_dyn dbs[lastdb] =
.check_file = 1, .check_file = 1,
.persistent = 0, .persistent = 0,
.shared = 0, .shared = 0,
.max_db_size = DEFAULT_MAX_DB_SIZE,
.filename = "/etc/group", .filename = "/etc/group",
.db_filename = _PATH_NSCD_GROUP_DB, .db_filename = _PATH_NSCD_GROUP_DB,
.disabled_iov = &grp_iov_disabled, .disabled_iov = &grp_iov_disabled,
@ -134,6 +132,7 @@ struct database_dyn dbs[lastdb] =
.check_file = 1, .check_file = 1,
.persistent = 0, .persistent = 0,
.shared = 0, .shared = 0,
.max_db_size = DEFAULT_MAX_DB_SIZE,
.filename = "/etc/hosts", .filename = "/etc/hosts",
.db_filename = _PATH_NSCD_HOSTS_DB, .db_filename = _PATH_NSCD_HOSTS_DB,
.disabled_iov = &hst_iov_disabled, .disabled_iov = &hst_iov_disabled,
@ -188,7 +187,7 @@ writeall (int fd, const void *buf, size_t len)
ssize_t ret; ssize_t ret;
do do
{ {
ret = TEMP_FAILURE_RETRY (write (fd, buf, n)); ret = TEMP_FAILURE_RETRY (send (fd, buf, n, MSG_NOSIGNAL));
if (ret <= 0) if (ret <= 0)
break; break;
buf = (const char *) buf + ret; buf = (const char *) buf + ret;
@ -473,8 +472,16 @@ nscd_init (void)
_("file size does not match")); _("file size does not match"));
unlink (dbs[cnt].db_filename); unlink (dbs[cnt].db_filename);
} }
else if ((mem = mmap (NULL, total, PROT_READ | PROT_WRITE, /* Note we map with the maximum size allowed for the
MAP_SHARED, fd, 0)) == MAP_FAILED) database. This is likely much larger than the
actual file size. This is OK on most OSes since
extensions of the underlying file will
automatically translate more pages available for
memory access. */
else if ((mem = mmap (NULL, dbs[cnt].max_db_size,
PROT_READ | PROT_WRITE,
MAP_SHARED, fd, 0))
== MAP_FAILED)
goto fail_db; goto fail_db;
else if (!verify_persistent_db (mem, &head, cnt)) else if (!verify_persistent_db (mem, &head, cnt))
{ {
@ -638,8 +645,10 @@ cannot create read-only descriptor for \"%s\"; no mmap"),
if ((TEMP_FAILURE_RETRY (write (fd, &head, sizeof (head))) if ((TEMP_FAILURE_RETRY (write (fd, &head, sizeof (head)))
!= sizeof (head)) != sizeof (head))
|| posix_fallocate (fd, 0, total) != 0 || (TEMP_FAILURE_RETRY_VAL (posix_fallocate (fd, 0, total))
|| (mem = mmap (NULL, total, PROT_READ | PROT_WRITE, != 0)
|| (mem = mmap (NULL, dbs[cnt].max_db_size,
PROT_READ | PROT_WRITE,
MAP_SHARED, fd, 0)) == MAP_FAILED) MAP_SHARED, fd, 0)) == MAP_FAILED)
{ {
write_fail: write_fail:
@ -901,8 +910,9 @@ cannot handle old request version %d; current version is %d"),
if (!db->enabled) if (!db->enabled)
{ {
/* No, sent the prepared record. */ /* No, sent the prepared record. */
if (TEMP_FAILURE_RETRY (write (fd, db->disabled_iov->iov_base, if (TEMP_FAILURE_RETRY (send (fd, db->disabled_iov->iov_base,
db->disabled_iov->iov_len)) db->disabled_iov->iov_len,
MSG_NOSIGNAL))
!= (ssize_t) db->disabled_iov->iov_len != (ssize_t) db->disabled_iov->iov_len
&& __builtin_expect (debug_level, 0) > 0) && __builtin_expect (debug_level, 0) > 0)
{ {

View File

@ -107,7 +107,8 @@ cache_addgr (struct database_dyn *db, int fd, request_header *req,
case. */ case. */
total = sizeof (notfound); total = sizeof (notfound);
written = TEMP_FAILURE_RETRY (write (fd, &notfound, total)); written = TEMP_FAILURE_RETRY (send (fd, &notfound, total,
MSG_NOSIGNAL));
dataset = mempool_alloc (db, sizeof (struct dataset) + req->key_len); dataset = mempool_alloc (db, sizeof (struct dataset) + req->key_len);
/* If we cannot permanently store the result, so be it. */ /* If we cannot permanently store the result, so be it. */

View File

@ -115,7 +115,8 @@ cache_addhst (struct database_dyn *db, int fd, request_header *req,
written = total = sizeof (notfound); written = total = sizeof (notfound);
if (fd != -1) if (fd != -1)
written = TEMP_FAILURE_RETRY (write (fd, &notfound, total)); written = TEMP_FAILURE_RETRY (send (fd, &notfound, total,
MSG_NOSIGNAL));
dataset = mempool_alloc (db, sizeof (struct dataset) + req->key_len); dataset = mempool_alloc (db, sizeof (struct dataset) + req->key_len);
/* If we cannot permanently store the result, so be it. */ /* If we cannot permanently store the result, so be it. */

View File

@ -188,7 +188,8 @@ addinitgroupsX (struct database_dyn *db, int fd, request_header *req,
/* We have no data. This means we send the standard reply for this /* We have no data. This means we send the standard reply for this
case. */ case. */
if (fd != -1) if (fd != -1)
written = TEMP_FAILURE_RETRY (write (fd, &notfound, total)); written = TEMP_FAILURE_RETRY (send (fd, &notfound, total,
MSG_NOSIGNAL));
dataset = mempool_alloc (db, sizeof (struct dataset) + req->key_len); dataset = mempool_alloc (db, sizeof (struct dataset) + req->key_len);
/* If we cannot permanently store the result, so be it. */ /* If we cannot permanently store the result, so be it. */

View File

@ -481,18 +481,26 @@ mempool_alloc (struct database_dyn *db, size_t len)
if (! tried_resize) if (! tried_resize)
{ {
/* Try to resize the database. Grow size of 1/8th. */ /* Try to resize the database. Grow size of 1/8th. */
size_t new_data_size = db->head->data_size + db->head->data_size / 8;
size_t oldtotal = (sizeof (struct database_pers_head) size_t oldtotal = (sizeof (struct database_pers_head)
+ db->head->module * sizeof (ref_t) + db->head->module * sizeof (ref_t)
+ db->head->data_size); + db->head->data_size);
size_t new_data_size = (db->head->data_size
+ MAX (2 * len, db->head->data_size / 8));
size_t newtotal = (sizeof (struct database_pers_head) size_t newtotal = (sizeof (struct database_pers_head)
+ db->head->module * sizeof (ref_t) + db->head->module * sizeof (ref_t)
+ new_data_size); + new_data_size);
if (newtotal > db->max_db_size)
{
new_data_size -= newtotal - db->max_db_size;
newtotal = db->max_db_size;
}
if ((!db->mmap_used if (db->mmap_used && newtotal > oldtotal
|| posix_fallocate (db->wr_fd, oldtotal, newtotal) != 0) /* We only have to adjust the file size. The new pages
/* Try to resize the mapping. Note: no MREMAP_MAYMOVE. */ become magically available. */
&& mremap (db->head, oldtotal, newtotal, 0) == 0) && TEMP_FAILURE_RETRY_VAL (posix_fallocate (db->wr_fd, oldtotal,
newtotal
- oldtotal)) == 0)
{ {
db->head->data_size = new_data_size; db->head->data_size = new_data_size;
tried_resize = true; tried_resize = true;

View File

@ -315,8 +315,9 @@ parse_opt (int key, char *arg, struct argp_state *state)
req.version = NSCD_VERSION; req.version = NSCD_VERSION;
req.type = SHUTDOWN; req.type = SHUTDOWN;
req.key_len = 0; req.key_len = 0;
nbytes = TEMP_FAILURE_RETRY (write (sock, &req, nbytes = TEMP_FAILURE_RETRY (send (sock, &req,
sizeof (request_header))); sizeof (request_header),
MSG_NOSIGNAL));
close (sock); close (sock);
exit (nbytes != sizeof (request_header) ? EXIT_FAILURE : EXIT_SUCCESS); exit (nbytes != sizeof (request_header) ? EXIT_FAILURE : EXIT_SUCCESS);
} }

View File

@ -23,6 +23,7 @@
# check-files <service> <yes|no> # check-files <service> <yes|no>
# persistent <service> <yes|no> # persistent <service> <yes|no>
# shared <service> <yes|no> # shared <service> <yes|no>
# max-db-szie <service> <number bytes>
# #
# Currently supported cache names (services): passwd, group, hosts # Currently supported cache names (services): passwd, group, hosts
# #
@ -45,6 +46,7 @@
check-files passwd yes check-files passwd yes
persistent passwd yes persistent passwd yes
shared passwd yes shared passwd yes
max-db-size passwd 33554432
enable-cache group yes enable-cache group yes
positive-time-to-live group 3600 positive-time-to-live group 3600
@ -53,6 +55,7 @@
check-files group yes check-files group yes
persistent group yes persistent group yes
shared group yes shared group yes
max-db-size group 33554432
enable-cache hosts yes enable-cache hosts yes
positive-time-to-live hosts 3600 positive-time-to-live hosts 3600
@ -61,3 +64,4 @@
check-files hosts yes check-files hosts yes
persistent hosts yes persistent hosts yes
shared hosts yes shared hosts yes
max-db-size hosts 33554432

View File

@ -63,6 +63,7 @@ struct database_dyn
int check_file; int check_file;
int persistent; int persistent;
int shared; int shared;
size_t max_db_size;
const char *filename; const char *filename;
const char *db_filename; const char *db_filename;
time_t file_mtime; time_t file_mtime;
@ -99,6 +100,12 @@ struct database_dyn
#define BLOCK_ALIGN (1 << BLOCK_ALIGN_LOG) #define BLOCK_ALIGN (1 << BLOCK_ALIGN_LOG)
#define BLOCK_ALIGN_M1 (BLOCK_ALIGN - 1) #define BLOCK_ALIGN_M1 (BLOCK_ALIGN - 1)
/* Default value for the maximum size of the database files. */
#define DEFAULT_MAX_DB_SIZE (32 * 1024 * 1024)
/* Number of bytes of data we initially reserve for each hash table bucket. */
#define DEFAULT_DATASIZE_PER_BUCKET 1024
/* Global variables. */ /* Global variables. */
extern struct database_dyn dbs[lastdb]; extern struct database_dyn dbs[lastdb];
@ -241,4 +248,14 @@ extern void gc (struct database_dyn *db);
/* nscd_setup_thread.c */ /* nscd_setup_thread.c */
extern void setup_thread (struct database_dyn *db); extern void setup_thread (struct database_dyn *db);
/* Special version of TEMP_FAILURE_RETRY for functions returning error
values. */
#define TEMP_FAILURE_RETRY_VAL(expression) \
(__extension__ \
({ long int __result; \
do __result = (long int) (expression); \
while (__result == EINTR); \
__result; }))
#endif /* nscd.h */ #endif /* nscd.h */

View File

@ -1,4 +1,4 @@
/* Copyright (c) 1998, 2000, 2003, 2004 Free Software Foundation, Inc. /* Copyright (c) 1998, 2000, 2003, 2004, 2005 Free Software Foundation, Inc.
This file is part of the GNU C Library. This file is part of the GNU C Library.
Contributed by Thorsten Kukuk <kukuk@suse.de>, 1998. Contributed by Thorsten Kukuk <kukuk@suse.de>, 1998.
@ -171,6 +171,17 @@ nscd_parse_file (const char *fname, struct database_dyn dbs[lastdb])
if (cnt == lastdb) if (cnt == lastdb)
dbg_log ("database %s is not supported\n", arg1); dbg_log ("database %s is not supported\n", arg1);
} }
else if (strcmp (entry, "max-db-size") == 0)
{
for (cnt = 0; cnt < lastdb; ++cnt)
if (strcmp (arg1, dbnames[cnt]) == 0)
{
dbs[cnt].max_db_size = atol (arg2);
break;
}
if (cnt == lastdb)
dbg_log ("database %s is not supported\n", arg1);
}
else if (strcmp (entry, "logfile") == 0) else if (strcmp (entry, "logfile") == 0)
set_logfile (arg1); set_logfile (arg1);
else if (strcmp (entry, "debug-level") == 0) else if (strcmp (entry, "debug-level") == 0)
@ -290,6 +301,22 @@ cannot get current working directory: %s; disabling paranoia mode"),
if (max_nthreads < nthreads) if (max_nthreads < nthreads)
max_nthreads = nthreads; max_nthreads = nthreads;
for (cnt = 0; cnt < lastdb; ++cnt)
{
size_t datasize = (sizeof (struct database_pers_head)
+ roundup (dbs[cnt].suggested_module
* sizeof (ref_t), ALIGN)
+ (dbs[cnt].suggested_module
* DEFAULT_DATASIZE_PER_BUCKET));
if (datasize > dbs[cnt].max_db_size)
{
dbg_log (_("maximum file size for %s database too small"),
dbnames[cnt]);
dbs[cnt].max_db_size = datasize;
}
}
/* Free the buffer. */ /* Free the buffer. */
free (line); free (line);
/* Close configuration file. */ /* Close configuration file. */

View File

@ -133,7 +133,8 @@ send_stats (int fd, struct database_dyn dbs[lastdb])
if (selinux_enabled) if (selinux_enabled)
nscd_avc_cache_stats (&data.cstats); nscd_avc_cache_stats (&data.cstats);
if (TEMP_FAILURE_RETRY (write (fd, &data, sizeof (data))) != sizeof (data)) if (TEMP_FAILURE_RETRY (send (fd, &data, sizeof (data), MSG_NOSIGNAL))
!= sizeof (data))
{ {
char buf[256]; char buf[256];
dbg_log (_("cannot write statistics: %s"), dbg_log (_("cannot write statistics: %s"),
@ -180,7 +181,8 @@ receive_print_stats (void)
req.version = NSCD_VERSION; req.version = NSCD_VERSION;
req.type = GETSTAT; req.type = GETSTAT;
req.key_len = 0; req.key_len = 0;
nbytes = TEMP_FAILURE_RETRY (write (fd, &req, sizeof (request_header))); nbytes = TEMP_FAILURE_RETRY (send (fd, &req, sizeof (request_header),
MSG_NOSIGNAL));
if (nbytes != sizeof (request_header)) if (nbytes != sizeof (request_header))
{ {
int err = errno; int err = errno;

View File

@ -114,7 +114,8 @@ cache_addpw (struct database_dyn *db, int fd, request_header *req,
written = total = sizeof (notfound); written = total = sizeof (notfound);
if (fd != -1) if (fd != -1)
written = TEMP_FAILURE_RETRY (write (fd, &notfound, total)); written = TEMP_FAILURE_RETRY (send (fd, &notfound, total,
MSG_NOSIGNAL));
dataset = mempool_alloc (db, sizeof (struct dataset) + req->key_len); dataset = mempool_alloc (db, sizeof (struct dataset) + req->key_len);
/* If we cannot permanently store the result, so be it. */ /* If we cannot permanently store the result, so be it. */