* 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>
* 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.
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);
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);
/* If we cannot permanently store the result, so be it. */

View file

@ -48,10 +48,6 @@
#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. */
extern void *xmalloc (size_t n);
extern void *xcalloc (size_t n, size_t s);
@ -104,6 +100,7 @@ struct database_dyn dbs[lastdb] =
.check_file = 1,
.persistent = 0,
.shared = 0,
.max_db_size = DEFAULT_MAX_DB_SIZE,
.filename = "/etc/passwd",
.db_filename = _PATH_NSCD_PASSWD_DB,
.disabled_iov = &pwd_iov_disabled,
@ -119,6 +116,7 @@ struct database_dyn dbs[lastdb] =
.check_file = 1,
.persistent = 0,
.shared = 0,
.max_db_size = DEFAULT_MAX_DB_SIZE,
.filename = "/etc/group",
.db_filename = _PATH_NSCD_GROUP_DB,
.disabled_iov = &grp_iov_disabled,
@ -134,6 +132,7 @@ struct database_dyn dbs[lastdb] =
.check_file = 1,
.persistent = 0,
.shared = 0,
.max_db_size = DEFAULT_MAX_DB_SIZE,
.filename = "/etc/hosts",
.db_filename = _PATH_NSCD_HOSTS_DB,
.disabled_iov = &hst_iov_disabled,
@ -188,7 +187,7 @@ writeall (int fd, const void *buf, size_t len)
ssize_t ret;
do
{
ret = TEMP_FAILURE_RETRY (write (fd, buf, n));
ret = TEMP_FAILURE_RETRY (send (fd, buf, n, MSG_NOSIGNAL));
if (ret <= 0)
break;
buf = (const char *) buf + ret;
@ -473,8 +472,16 @@ nscd_init (void)
_("file size does not match"));
unlink (dbs[cnt].db_filename);
}
else if ((mem = mmap (NULL, total, PROT_READ | PROT_WRITE,
MAP_SHARED, fd, 0)) == MAP_FAILED)
/* Note we map with the maximum size allowed for the
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;
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)))
!= sizeof (head))
|| posix_fallocate (fd, 0, total) != 0
|| (mem = mmap (NULL, total, PROT_READ | PROT_WRITE,
|| (TEMP_FAILURE_RETRY_VAL (posix_fallocate (fd, 0, total))
!= 0)
|| (mem = mmap (NULL, dbs[cnt].max_db_size,
PROT_READ | PROT_WRITE,
MAP_SHARED, fd, 0)) == MAP_FAILED)
{
write_fail:
@ -901,8 +910,9 @@ cannot handle old request version %d; current version is %d"),
if (!db->enabled)
{
/* No, sent the prepared record. */
if (TEMP_FAILURE_RETRY (write (fd, db->disabled_iov->iov_base,
db->disabled_iov->iov_len))
if (TEMP_FAILURE_RETRY (send (fd, db->disabled_iov->iov_base,
db->disabled_iov->iov_len,
MSG_NOSIGNAL))
!= (ssize_t) db->disabled_iov->iov_len
&& __builtin_expect (debug_level, 0) > 0)
{

View file

@ -107,7 +107,8 @@ cache_addgr (struct database_dyn *db, int fd, request_header *req,
case. */
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);
/* 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);
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);
/* 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
case. */
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);
/* 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)
{
/* 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)
+ db->head->module * sizeof (ref_t)
+ 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)
+ db->head->module * sizeof (ref_t)
+ 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
|| posix_fallocate (db->wr_fd, oldtotal, newtotal) != 0)
/* Try to resize the mapping. Note: no MREMAP_MAYMOVE. */
&& mremap (db->head, oldtotal, newtotal, 0) == 0)
if (db->mmap_used && newtotal > oldtotal
/* We only have to adjust the file size. The new pages
become magically available. */
&& TEMP_FAILURE_RETRY_VAL (posix_fallocate (db->wr_fd, oldtotal,
newtotal
- oldtotal)) == 0)
{
db->head->data_size = new_data_size;
tried_resize = true;

View file

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

View file

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

View file

@ -63,6 +63,7 @@ struct database_dyn
int check_file;
int persistent;
int shared;
size_t max_db_size;
const char *filename;
const char *db_filename;
time_t file_mtime;
@ -99,6 +100,12 @@ struct database_dyn
#define BLOCK_ALIGN (1 << BLOCK_ALIGN_LOG)
#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. */
extern struct database_dyn dbs[lastdb];
@ -241,4 +248,14 @@ extern void gc (struct database_dyn *db);
/* nscd_setup_thread.c */
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 */

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.
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)
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)
set_logfile (arg1);
else if (strcmp (entry, "debug-level") == 0)
@ -290,6 +301,22 @@ cannot get current working directory: %s; disabling paranoia mode"),
if (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 (line);
/* Close configuration file. */

View file

@ -133,7 +133,8 @@ send_stats (int fd, struct database_dyn dbs[lastdb])
if (selinux_enabled)
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];
dbg_log (_("cannot write statistics: %s"),
@ -180,7 +181,8 @@ receive_print_stats (void)
req.version = NSCD_VERSION;
req.type = GETSTAT;
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))
{
int err = errno;

View file

@ -114,7 +114,8 @@ cache_addpw (struct database_dyn *db, int fd, request_header *req,
written = total = sizeof (notfound);
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);
/* If we cannot permanently store the result, so be it. */