* nscd/connection.c (DEFAULT_DATASIZE_PER_BUCKET): Move to nscd.h.
authorUlrich Drepper <drepper@redhat.com>
Tue, 23 Aug 2005 23:21:53 +0000 (23:21 +0000)
committerUlrich Drepper <drepper@redhat.com>
Tue, 23 Aug 2005 23:21:53 +0000 (23:21 +0000)
(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.

13 files changed:
ChangeLog
nscd/aicache.c
nscd/connections.c
nscd/grpcache.c
nscd/hstcache.c
nscd/initgrcache.c
nscd/mem.c
nscd/nscd.c
nscd/nscd.conf
nscd/nscd.h
nscd/nscd_conf.c
nscd/nscd_stat.c
nscd/pwdcache.c

index e4848509d849b0f94d8b41f319a564c8aecbee31..08036d852824e9e056029b335c499735f79fd8c2 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -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>
index fb75dc199db1cfbed0939b3698147436b0dccbc2..992c6ef0236b3cba7b7fccf4e4218b489a4b8210 100644 (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.  */
index 0a0654d6b81cdc40c6d467bbcfbd78e4ca9d43f0..ce1348b0693d9798664b0602a7fa77916818cdda 100644 (file)
 #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)
            {
index c938554b2546a77da7e6d6ba6fe90c167e9beed3..6543ef354d0dcedd6f7121e9a95ea3bec93bfb7c 100644 (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.  */
index 377f02387d297acb188d84912907eca98cf744b1..29bce99819e34e0b8f29fe8bd2def8638219d129 100644 (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.  */
index db01f1bc28c5eaeb21a7353f04fe1e8cb2252c5e..bb6dee2b4ea4a4cb3623f6484c3e0703a11eaf80 100644 (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.  */
index 823eda101989894e94fe524dc51ddb044d396ae7..96f0170c6ca36605ca7b15cb2c099199c73312b2 100644 (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;
index a7aa96480445aada644eac7ef855b0c8cc7d9c2a..c16152c1b0429d80deb84d6d2dd29e702c528a78 100644 (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);
       }
index 87e7a84487d1f8bc20a927c7a3b318c15f7694c1..9491e1647232ac9b2346504c4ac5129267ecb83a 100644 (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
index 25a4b38eb4d5b4fea3272c92b092268bc5706673..3859d95d0195dae45290fa5e05990f3a9e3ca19b 100644 (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 */
index d21f2fc501135dbe305c9ec879935aaf0779b7fb..c5c06ae2d98fc06686df69077be5bd05abdf5673 100644 (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.  */
index 43f6266c6e2e3bba8ea7d58c187e09991c238eb0..c1d0bffe20e2ee3b0f6b65bc126e5bfe93814a34 100644 (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;
index 34265c3f39a12ffb8e6b0359217f222fedda09c2..6b25968f71dc0648121e03dbfc9b5724bdc91f83 100644 (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.  */