aboutsummaryrefslogtreecommitdiff
path: root/nscd
diff options
context:
space:
mode:
Diffstat (limited to 'nscd')
-rw-r--r--nscd/aicache.c2
-rw-r--r--nscd/connections.c32
-rw-r--r--nscd/grpcache.c3
-rw-r--r--nscd/hstcache.c3
-rw-r--r--nscd/initgrcache.c3
-rw-r--r--nscd/mem.c18
-rw-r--r--nscd/nscd.c5
-rw-r--r--nscd/nscd.conf4
-rw-r--r--nscd/nscd.h17
-rw-r--r--nscd/nscd_conf.c29
-rw-r--r--nscd/nscd_stat.c6
-rw-r--r--nscd/pwdcache.c3
12 files changed, 99 insertions, 26 deletions
diff --git a/nscd/aicache.c b/nscd/aicache.c
index fb75dc1..992c6ef 100644
--- a/nscd/aicache.c
+++ b/nscd/aicache.c
@@ -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. */
diff --git a/nscd/connections.c b/nscd/connections.c
index 0a0654d..ce1348b 100644
--- a/nscd/connections.c
+++ b/nscd/connections.c
@@ -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)
{
diff --git a/nscd/grpcache.c b/nscd/grpcache.c
index c938554..6543ef3 100644
--- a/nscd/grpcache.c
+++ b/nscd/grpcache.c
@@ -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. */
diff --git a/nscd/hstcache.c b/nscd/hstcache.c
index 377f023..29bce99 100644
--- a/nscd/hstcache.c
+++ b/nscd/hstcache.c
@@ -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. */
diff --git a/nscd/initgrcache.c b/nscd/initgrcache.c
index db01f1b..bb6dee2 100644
--- a/nscd/initgrcache.c
+++ b/nscd/initgrcache.c
@@ -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. */
diff --git a/nscd/mem.c b/nscd/mem.c
index 823eda1..96f0170 100644
--- a/nscd/mem.c
+++ b/nscd/mem.c
@@ -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;
diff --git a/nscd/nscd.c b/nscd/nscd.c
index a7aa964..c16152c 100644
--- a/nscd/nscd.c
+++ b/nscd/nscd.c
@@ -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);
}
diff --git a/nscd/nscd.conf b/nscd/nscd.conf
index 87e7a84..9491e16 100644
--- a/nscd/nscd.conf
+++ b/nscd/nscd.conf
@@ -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
diff --git a/nscd/nscd.h b/nscd/nscd.h
index 25a4b38..3859d95 100644
--- a/nscd/nscd.h
+++ b/nscd/nscd.h
@@ -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 */
diff --git a/nscd/nscd_conf.c b/nscd/nscd_conf.c
index d21f2fc..c5c06ae 100644
--- a/nscd/nscd_conf.c
+++ b/nscd/nscd_conf.c
@@ -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. */
diff --git a/nscd/nscd_stat.c b/nscd/nscd_stat.c
index 43f6266..c1d0bff 100644
--- a/nscd/nscd_stat.c
+++ b/nscd/nscd_stat.c
@@ -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;
diff --git a/nscd/pwdcache.c b/nscd/pwdcache.c
index 34265c3..6b25968 100644
--- a/nscd/pwdcache.c
+++ b/nscd/pwdcache.c
@@ -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. */