sysvinit/startpar-preload.diff

123 lines
3.0 KiB
Diff

--- startpar.c
+++ startpar.c 2009-03-27 11:48:00.080002479 +0100
@@ -29,6 +29,8 @@
#include <sys/select.h>
#include <sys/time.h>
#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <sys/un.h>
#include <sys/sysinfo.h>
#include <sys/stat.h>
#include <time.h>
@@ -64,6 +66,8 @@ static struct timeval lastlim;
static char *run_mode = NULL;
static struct makenode **nodevec;
+static enum { Unknown, Preload, NoPreload } ispreload = Unknown;
+
#define PBUF_SIZE 8192
struct prg {
char *name;
@@ -81,6 +85,19 @@ static int inpar, par;
static int pidpipe[2];
static double iorate = 800.0;
+void sighandler_nopreload(int x)
+{
+ (void)x;
+ ispreload = NoPreload;
+}
+
+
+void sighandler_preload(int x)
+{
+ (void)x;
+ ispreload = Preload;
+}
+
void *xcalloc(size_t nmemb, size_t size)
{
void *r;
@@ -248,11 +265,15 @@ static int checksystem(const int par, co
if (read_proc(&prcs_run, &prcs_blked))
return par;
+ /* if we have preload running, we expect I/O not to be a problem */
+ if (ispreload != NoPreload)
+ prcs_blked = 0;
+
newpar = (par*numcpu) - prcs_run + 1; /* +1 for startpar its self */
newpar -= (int)(((double)prcs_blked)*iorate); /* I/O load reduction */
#if DEBUG
- fprintf(stderr, "checksystem par=%d newpar=%d (prcs_run=%u) %ld\n", par, newpar, prcs_run, time(0));
+ fprintf(stderr, "checksystem par=%d newpar=%d (prcs_run=%lu) %ld\n", par, newpar, prcs_run, time(0));
dump_status();
#endif
if (newpar <= 0)
@@ -271,9 +292,12 @@ static inline int checkpar(const int par
return checksystem(par, start, false);
}
+#define SOCK_PATH "/dev/shm/preload_sock"
+
void run(struct prg *p)
{
char *m = 0;
+ pid_t parent = getpid();
p->len = 0;
p->pid = (pid_t)0;
@@ -341,6 +365,41 @@ void run(struct prg *p)
closeall();
+ if (!strcmp(arg, "start"))
+ {
+ int s, t, len;
+ struct sockaddr_un remote;
+ char str[100];
+
+ s = socket(AF_UNIX, SOCK_STREAM, 0);
+ if (s != -1)
+ {
+ memset(&remote, 0, sizeof(struct sockaddr_un));
+ remote.sun_family = AF_UNIX;
+ strcpy(remote.sun_path, SOCK_PATH);
+ len = strlen(remote.sun_path) + sizeof(remote.sun_family);
+
+ t = connect(s, (struct sockaddr *)&remote, len);
+ if (t != -1)
+ {
+ if (ispreload != Preload)
+ kill(parent, SIGUSR1);
+ send(s, p->name, strlen(p->name), 0);
+ recv(s, str, 100, 0);
+ }
+ else if ( ispreload == Unknown)
+ {
+ /*
+ * if we connected to preload once, we know it ran.
+ * In case we can't connect to it later, it means it did
+ * its job and we can guess I/O is no longer a problem.
+ */
+ kill(parent, SIGUSR2);
+ }
+ close(s);
+ }
+ }
+
if (run_mode)
{
char path[128];
@@ -557,6 +616,9 @@ int main(int argc, char **argv)
char *run_level = getenv("RUNLEVEL");
char *splashopt = 0;
+ (void)signal(SIGUSR1, sighandler_preload);
+ (void)signal(SIGUSR2, sighandler_nopreload);
+
(void)signal(SIGCHLD, SIG_DFL);
numcpu = sysconf(_SC_NPROCESSORS_ONLN);
myname = argv[0];