summaryrefslogtreecommitdiff
path: root/nscd/connections.c
diff options
context:
space:
mode:
authorUlrich Drepper <drepper@redhat.com>2004-09-08 15:46:42 +0000
committerUlrich Drepper <drepper@redhat.com>2004-09-08 15:46:42 +0000
commitc207f23b0b6b2d215be65e670d453768ad304247 (patch)
tree5d10943ec51bbda849db9ca2fdcc7b43feb2011c /nscd/connections.c
parent0a3ad40da92c0036bd3bd87949f7d7d9864c31c7 (diff)
Update.
* nscd/connections.c: Implement r/o sharing of nscd's cache with client processes via shared memory. * nscd/nscd-client.h: Likewise. * nscd/nscd.h: Likewise. * nscd/nscd_conf.c: Likewise. * nscd/nscd_getgr_r.c: Likewise. * nscd/nscd_getpw_r.c: Likewise. * nscd/nscd_gethst_r.c: Likewise. * nscd/nscd.conf: Add new config parameters. * nscd/Makefile (aux): Add nscd_helper. * nscd/nscd_helper.c: New file. * nscd/mem.c (gc): Indicate beginning and end of the gc cycle. * nscd/hstcache.c: Simplify a lot. We cache only the request itself, no derived information. * connections.c (nscd_init): Fix bug in testing size of the persistent. * nis/Makefile (aux): Add nis_hash. * nis/nis_hash.c: New file. Split out from nis_util.c. * nis/nis_util.c: Move __nis_hash code in separate file. * csu/tst-atomic.c: Improve atomic_increment_val test which would not have found a ppc bug.
Diffstat (limited to 'nscd/connections.c')
-rw-r--r--nscd/connections.c78
1 files changed, 67 insertions, 11 deletions
diff --git a/nscd/connections.c b/nscd/connections.c
index 53e258b498..552d554295 100644
--- a/nscd/connections.c
+++ b/nscd/connections.c
@@ -80,7 +80,10 @@ const char *serv2str[LASTREQ] =
[GETHOSTBYADDRv6] = "GETHOSTBYADDRv6",
[SHUTDOWN] = "SHUTDOWN",
[GETSTAT] = "GETSTAT",
- [INVALIDATE] = "INVALIDATE"
+ [INVALIDATE] = "INVALIDATE",
+ [GETFDPW] = "GETFDPW",
+ [GETFDGR] = "GETFDGR",
+ [GETFDHST] = "GETFDHST"
};
/* The control data structures for the services. */
@@ -91,6 +94,7 @@ struct database_dyn dbs[lastdb] =
.enabled = 0,
.check_file = 1,
.persistent = 0,
+ .shared = 0,
.filename = "/etc/passwd",
.db_filename = _PATH_NSCD_PASSWD_DB,
.disabled_iov = &pwd_iov_disabled,
@@ -105,6 +109,7 @@ struct database_dyn dbs[lastdb] =
.enabled = 0,
.check_file = 1,
.persistent = 0,
+ .shared = 0,
.filename = "/etc/group",
.db_filename = _PATH_NSCD_GROUP_DB,
.disabled_iov = &grp_iov_disabled,
@@ -119,6 +124,7 @@ struct database_dyn dbs[lastdb] =
.enabled = 0,
.check_file = 1,
.persistent = 0,
+ .shared = 0,
.filename = "/etc/hosts",
.db_filename = _PATH_NSCD_HOSTS_DB,
.disabled_iov = &hst_iov_disabled,
@@ -132,7 +138,7 @@ struct database_dyn dbs[lastdb] =
/* Mapping of request type to database. */
-static struct database_dyn *const serv2db[LASTDBREQ + 1] =
+static struct database_dyn *const serv2db[LASTREQ] =
{
[GETPWBYNAME] = &dbs[pwddb],
[GETPWBYUID] = &dbs[pwddb],
@@ -141,7 +147,10 @@ static struct database_dyn *const serv2db[LASTDBREQ + 1] =
[GETHOSTBYNAME] = &dbs[hstdb],
[GETHOSTBYNAMEv6] = &dbs[hstdb],
[GETHOSTBYADDR] = &dbs[hstdb],
- [GETHOSTBYADDRv6] = &dbs[hstdb]
+ [GETHOSTBYADDRv6] = &dbs[hstdb],
+ [GETFDPW] = &dbs[pwddb],
+ [GETFDGR] = &dbs[grpdb],
+ [GETFDHST] = &dbs[hstdb],
};
@@ -158,9 +167,6 @@ static int sock;
/* Number of times clients had to wait. */
unsigned long int client_queued;
-/* Alignment requirement of the beginning of the data region. */
-#define ALIGN 16
-
/* Initialize database information structures. */
void
@@ -224,11 +230,10 @@ nscd_init (void)
dbs[cnt].persistent = 0;
}
else if ((total = (sizeof (head)
- + roundup (head.module
- * sizeof (struct hashentry),
+ + roundup (head.module * sizeof (ref_t),
ALIGN)
+ head.data_size))
- < st.st_size)
+ > st.st_size)
{
dbg_log (_("invalid persistent database file \"%s\": %s"),
dbs[cnt].db_filename,
@@ -253,6 +258,7 @@ nscd_init (void)
dbnames[cnt]);
dbs[cnt].wr_fd = fd;
+ dbs[cnt].ro_fd = open (dbs[cnt].db_filename, O_RDONLY);
fd = -1;
/* We also need a read-only descriptor. */
dbs[cnt].ro_fd = open (dbs[cnt].db_filename, O_RDONLY);
@@ -439,6 +445,9 @@ cannot create read-only descriptor for \"%s\"; no mmap"),
* dbs[cnt].head->module);
dbs[cnt].data = xmalloc (dbs[cnt].head->data_size);
dbs[cnt].head->first_free = 0;
+
+ dbs[cnt].shared = 0;
+ assert (dbs[cnt].ro_fd == -1);
}
if (dbs[cnt].check_file)
@@ -529,6 +538,43 @@ invalidate_cache (char *key)
}
+#ifdef SCM_RIGHTS
+static void
+send_ro_fd (struct database_dyn *db, char *key, int fd)
+{
+ /* If we do not have an read-only file descriptor do nothing. */
+ if (db->ro_fd == -1)
+ return;
+
+ /* We need to send some data along with the descriptor. */
+ struct iovec iov[1];
+ iov[0].iov_base = key;
+ iov[0].iov_len = strlen (key) + 1;
+
+ /* Prepare the control message to transfer the descriptor. */
+ char buf[CMSG_SPACE (sizeof (int))];
+ struct msghdr msg = { .msg_iov = iov, .msg_iovlen = 1,
+ .msg_control = buf, .msg_controllen = sizeof (buf) };
+ struct cmsghdr *cmsg = CMSG_FIRSTHDR (&msg);
+
+ cmsg->cmsg_level = SOL_SOCKET;
+ cmsg->cmsg_type = SCM_RIGHTS;
+ cmsg->cmsg_len = CMSG_LEN (sizeof (int));
+
+ *(int *) CMSG_DATA (cmsg) = db->ro_fd;
+
+ msg.msg_controllen = cmsg->cmsg_len;
+
+ /* Send the control message. We repeat when we are interrupted but
+ everything else is ignored. */
+ (void) TEMP_FAILURE_RETRY (sendmsg (fd, &msg, 0));
+
+ if (__builtin_expect (debug_level > 0, 0))
+ dbg_log (_("provide access to FD %d, for %s"), db->ro_fd, key);
+}
+#endif /* SCM_RIGHTS */
+
+
/* Handle new request. */
static void
handle_request (int fd, request_header *req, void *key, uid_t uid)
@@ -614,7 +660,7 @@ cannot handle old request version %d; current version is %d"),
else if (__builtin_expect (debug_level, 0) > 0)
{
if (req->type == INVALIDATE)
- dbg_log ("\t%s (%s)", serv2str[req->type], (char *)key);
+ dbg_log ("\t%s (%s)", serv2str[req->type], (char *) key);
else
dbg_log ("\t%s", serv2str[req->type]);
}
@@ -697,6 +743,14 @@ cannot handle old request version %d; current version is %d"),
}
break;
+ case GETFDPW:
+ case GETFDGR:
+ case GETFDHST:
+#ifdef SCM_RIGHTS
+ send_ro_fd (serv2db[req->type], key, fd);
+#endif
+ break;
+
default:
/* Ignore the command, it's nothing we know. */
break;
@@ -733,7 +787,9 @@ nscd_run (void *p)
int timeout = -1;
if (run_prune)
{
- now = time (NULL);
+ /* NB: we do not flush the timestamp update using msync since
+ this value doesnot matter on disk. */
+ dbs[my_number].head->timestamp = now = time (NULL);
timeout = now < next_prune ? 1000 * (next_prune - now) : 0;
}