Allocate pathname buffers dynamically
[openafs.git] / src / bozo / fsbnodeops.c
index ed4f02d..7893599 100644 (file)
 
 #include <afs/procmgmt.h>
 #include <roken.h>
+#include <afs/opr.h>
 
 #include <lwp.h>
 #include <rx/rx.h>
 #include <afs/afsutil.h>
+#include <opr/queue.h>
 
 #include "bnode.h"
+#include "bnode_internal.h"
 #include "bosprototypes.h"
 
+extern char *DoPidFiles;
 static int emergency = 0;
 
 /* if this file exists, then we have to salvage the file system */
@@ -94,6 +98,7 @@ static int fs_delete(struct bnode *abnode);
 static int fs_timeout(struct bnode *abnode);
 static int fs_getstat(struct bnode *abnode, afs_int32 * astatus);
 static int fs_setstat(struct bnode *abnode, afs_int32 astatus);
+static int fs_procstarted(struct bnode *abnode, struct bnode_proc *aproc);
 static int fs_procexit(struct bnode *abnode, struct bnode_proc *aproc);
 static int fs_getstring(struct bnode *abnode, char *abuffer, afs_int32 alen);
 static int fs_getparm(struct bnode *abnode, afs_int32 aindex,
@@ -107,9 +112,9 @@ static void SetNeedsClock(struct fsbnode *);
 static int NudgeProcs(struct fsbnode *);
 
 #ifdef AFS_NT40_ENV
-static void AppendExecutableExtension(char *cmd);
+static char *AppendExecutableExtension(char *cmd);
 #else
-#define AppendExecutableExtension(x)
+#define AppendExecutableExtension(x) strdup(x)
 #endif
 
 struct bnode_ops fsbnode_ops = {
@@ -123,6 +128,7 @@ struct bnode_ops fsbnode_ops = {
     fs_getparm,
     fs_restartp,
     fs_hascore,
+    fs_procstarted,
 };
 
 /* demand attach fs bnode ops */
@@ -137,6 +143,7 @@ struct bnode_ops dafsbnode_ops = {
     dafs_getparm,
     fs_restartp,
     fs_hascore,
+    fs_procstarted,
 };
 
 /* Quick inline function to safely convert a fsbnode to a bnode without
@@ -279,20 +286,22 @@ fs_restartp(struct bnode *bn)
 static int
 SetSalFlag(struct fsbnode *abnode, int aflag)
 {
-    char tbuffer[AFSDIR_PATH_MAX];
+    char *filepath;
     int fd;
 
     /* don't use the salvage flag for demand attach fs */
     if (abnode->salsrvcmd == NULL) {
        abnode->needsSalvage = aflag;
-       strcompose(tbuffer, AFSDIR_PATH_MAX, AFSDIR_SERVER_LOCAL_DIRPATH, "/",
-                  SALFILE, abnode->b.name, NULL);
+       if (asprintf(&filepath, "%s/%s%s", AFSDIR_SERVER_LOCAL_DIRPATH,
+                  SALFILE, abnode->b.name) < 0)
+           return ENOMEM;
        if (aflag) {
-           fd = open(tbuffer, O_CREAT | O_TRUNC | O_RDWR, 0666);
+           fd = open(filepath, O_CREAT | O_TRUNC | O_RDWR, 0666);
            close(fd);
        } else {
-           unlink(tbuffer);
+           unlink(filepath);
        }
+       free(filepath);
     }
     return 0;
 }
@@ -301,33 +310,26 @@ SetSalFlag(struct fsbnode *abnode, int aflag)
 static int
 RestoreSalFlag(struct fsbnode *abnode)
 {
-    char tbuffer[AFSDIR_PATH_MAX];
+    char *filepath;
 
     /* never set needs salvage flag for demand attach fs */
     if (abnode->salsrvcmd != NULL) {
        abnode->needsSalvage = 0;
     } else {
-       strcompose(tbuffer, AFSDIR_PATH_MAX, AFSDIR_SERVER_LOCAL_DIRPATH, "/",
-                  SALFILE, abnode->b.name, NULL);
-       if (access(tbuffer, 0) == 0) {
+       if (asprintf(&filepath, "%s/%s%s", AFSDIR_SERVER_LOCAL_DIRPATH,
+                    SALFILE, abnode->b.name) < 0)
+           return ENOMEM;
+       if (access(filepath, 0) == 0) {
            /* file exists, so need to salvage */
            abnode->needsSalvage = 1;
        } else {
            abnode->needsSalvage = 0;
        }
+       free(filepath);
     }
     return 0;
 }
 
-char *
-copystr(char *a)
-{
-    char *b;
-    b = (char *)malloc(strlen(a) + 1);
-    strcpy(b, a);
-    return b;
-}
-
 static int
 fs_delete(struct bnode *bn)
 {
@@ -346,16 +348,19 @@ fs_delete(struct bnode *bn)
 
 
 #ifdef AFS_NT40_ENV
-static void
+static char *
 AppendExecutableExtension(char *cmd)
 {
     char cmdext[_MAX_EXT];
+    char *cmdexe;
 
     _splitpath(cmd, NULL, NULL, NULL, cmdext);
     if (*cmdext == '\0') {
-       /* no filename extension supplied for cmd; append .exe */
-       strcat(cmd, ".exe");
+       if (asprintf(&cmdexe, "%s.exe", cmd) < 0)
+           return NULL;
+       return cmdexe;
     }
+    return strdup(cmd);
 }
 #endif /* AFS_NT40_ENV */
 
@@ -366,7 +371,7 @@ fs_create(char *ainstance, char *afilecmd, char *avolcmd, char *asalcmd,
 {
     struct stat tstat;
     struct fsbnode *te;
-    char cmdname[AFSDIR_PATH_MAX];
+    char *cmdname = NULL;
     char *fileCmdpath, *volCmdpath, *salCmdpath, *scanCmdpath;
     int bailout = 0;
 
@@ -399,24 +404,38 @@ fs_create(char *ainstance, char *afilecmd, char *avolcmd, char *asalcmd,
     }
 
     if (!bailout) {
-       sscanf(fileCmdpath, "%s", cmdname);
-       AppendExecutableExtension(cmdname);
+       cmdname = AppendExecutableExtension(fileCmdpath);
+       if (cmdname == NULL) {
+           bozo_Log("Out of memory constructing binary filename\n");
+           bailout = 1;
+           goto done;
+       }
        if (stat(cmdname, &tstat)) {
            bozo_Log("BNODE: file server binary '%s' not found\n", cmdname);
            bailout = 1;
            goto done;
        }
+       free(cmdname);
 
-       sscanf(volCmdpath, "%s", cmdname);
-       AppendExecutableExtension(cmdname);
+       cmdname = AppendExecutableExtension(volCmdpath);
+       if (cmdname == NULL) {
+           bozo_Log("Out of memory constructing binary filename\n");
+           bailout = 1;
+           goto done;
+       }
        if (stat(cmdname, &tstat)) {
            bozo_Log("BNODE: volume server binary '%s' not found\n", cmdname);
            bailout = 1;
            goto done;
        }
+       free(cmdname);
 
-       sscanf(salCmdpath, "%s", cmdname);
-       AppendExecutableExtension(cmdname);
+       cmdname = AppendExecutableExtension(salCmdpath);
+       if (cmdname == NULL) {
+           bozo_Log("Out of memory constructing binary filename\n");
+           bailout = 1;
+           goto done;
+       }
        if (stat(cmdname, &tstat)) {
            bozo_Log("BNODE: salvager binary '%s' not found\n", cmdname);
            bailout = 1;
@@ -424,8 +443,13 @@ fs_create(char *ainstance, char *afilecmd, char *avolcmd, char *asalcmd,
        }
 
        if (ascancmd && strlen(ascancmd)) {
-           sscanf(scanCmdpath, "%s", cmdname);
-           AppendExecutableExtension(cmdname);
+           free(cmdname);
+           cmdname = AppendExecutableExtension(scanCmdpath);
+           if (cmdname == NULL) {
+               bozo_Log("Out of memory constructing binary filename\n");
+               bailout = 1;
+               goto done;
+           }
            if (stat(cmdname, &tstat)) {
                bozo_Log("BNODE: scanner binary '%s' not found\n", cmdname);
                bailout = 1;
@@ -434,12 +458,11 @@ fs_create(char *ainstance, char *afilecmd, char *avolcmd, char *asalcmd,
        }
     }
 
-    te = (struct fsbnode *)malloc(sizeof(struct fsbnode));
+    te = calloc(1, sizeof(struct fsbnode));
     if (te == NULL) {
        bailout = 1;
        goto done;
     }
-    memset(te, 0, sizeof(struct fsbnode));
     te->filecmd = fileCmdpath;
     te->volcmd = volCmdpath;
     te->salsrvcmd = NULL;
@@ -453,11 +476,12 @@ fs_create(char *ainstance, char *afilecmd, char *avolcmd, char *asalcmd,
        goto done;
     }
     bnode_SetTimeout(fsbnode2bnode(te), POLLTIME);
-               /* ask for timeout activations every 10 seconds */
+               /* ask for timeout activations every 20 seconds */
     RestoreSalFlag(te);                /* restore needsSalvage flag based on file's existence */
     SetNeedsClock(te);         /* compute needsClock field */
 
  done:
+    free(cmdname);
     if (bailout) {
        if (te)
            free(te);
@@ -482,7 +506,7 @@ dafs_create(char *ainstance, char *afilecmd, char *avolcmd,
 {
     struct stat tstat;
     struct fsbnode *te;
-    char cmdname[AFSDIR_PATH_MAX];
+    char *cmdname = NULL;
     char *fileCmdpath, *volCmdpath, *salsrvCmdpath, *salCmdpath, *scanCmdpath;
     int bailout = 0;
 
@@ -520,32 +544,51 @@ dafs_create(char *ainstance, char *afilecmd, char *avolcmd,
     }
 
     if (!bailout) {
-       sscanf(fileCmdpath, "%s", cmdname);
-       AppendExecutableExtension(cmdname);
+       cmdname = AppendExecutableExtension(fileCmdpath);
+       if (cmdname == NULL) {
+           bozo_Log("Out of memory constructing binary filename\n");
+           bailout = 1;
+           goto done;
+       }
        if (stat(cmdname, &tstat)) {
            bozo_Log("BNODE: file server binary '%s' not found\n", cmdname);
            bailout = 1;
            goto done;
        }
+       free(cmdname);
 
-       sscanf(volCmdpath, "%s", cmdname);
-       AppendExecutableExtension(cmdname);
+       cmdname = AppendExecutableExtension(volCmdpath);
+       if (cmdname == NULL) {
+           bozo_Log("Out of memory constructing binary filename\n");
+           bailout = 1;
+           goto done;
+       }
        if (stat(cmdname, &tstat)) {
            bozo_Log("BNODE: volume server binary '%s' not found\n", cmdname);
            bailout = 1;
            goto done;
        }
+       free(cmdname);
 
-       sscanf(salsrvCmdpath, "%s", cmdname);
-       AppendExecutableExtension(cmdname);
+       cmdname = AppendExecutableExtension(salsrvCmdpath);
+       if (cmdname == NULL) {
+           bozo_Log("Out of memory constructing binary filename\n");
+           bailout = 1;
+           goto done;
+       }
        if (stat(cmdname, &tstat)) {
            bozo_Log("BNODE: salvageserver binary '%s' not found\n", cmdname);
            bailout = 1;
            goto done;
        }
+       free(cmdname);
 
-       sscanf(salCmdpath, "%s", cmdname);
-       AppendExecutableExtension(cmdname);
+       cmdname = AppendExecutableExtension(salCmdpath);
+       if (cmdname == NULL) {
+           bozo_Log("Out of memory constructing binary filename\n");
+           bailout = 1;
+           goto done;
+       }
        if (stat(cmdname, &tstat)) {
            bozo_Log("BNODE: salvager binary '%s' not found\n", cmdname);
            bailout = 1;
@@ -553,8 +596,13 @@ dafs_create(char *ainstance, char *afilecmd, char *avolcmd,
        }
 
        if (ascancmd && strlen(ascancmd)) {
-           sscanf(scanCmdpath, "%s", cmdname);
-           AppendExecutableExtension(cmdname);
+           free(cmdname);
+           cmdname = AppendExecutableExtension(scanCmdpath);
+           if (cmdname == NULL) {
+               bozo_Log("Out of memory constructing binary filename\n");
+               bailout = 1;
+               goto done;
+           }
            if (stat(cmdname, &tstat)) {
                bozo_Log("BNODE: scanner binary '%s' not found\n", cmdname);
                bailout = 1;
@@ -563,12 +611,11 @@ dafs_create(char *ainstance, char *afilecmd, char *avolcmd,
        }
     }
 
-    te = (struct fsbnode *)malloc(sizeof(struct fsbnode));
+    te = calloc(1, sizeof(struct fsbnode));
     if (te == NULL) {
        bailout = 1;
        goto done;
     }
-    memset(te, 0, sizeof(struct fsbnode));
     te->filecmd = fileCmdpath;
     te->volcmd = volCmdpath;
     te->salsrvcmd = salsrvCmdpath;
@@ -582,11 +629,12 @@ dafs_create(char *ainstance, char *afilecmd, char *avolcmd,
        goto done;
     }
     bnode_SetTimeout(fsbnode2bnode(te), POLLTIME);
-               /* ask for timeout activations every 10 seconds */
+               /* ask for timeout activations every 20 seconds */
     RestoreSalFlag(te);                /* restore needsSalvage flag based on file's existence */
     SetNeedsClock(te);         /* compute needsClock field */
 
  done:
+    free(cmdname);
     if (bailout) {
        if (te)
            free(te);
@@ -661,6 +709,16 @@ fs_timeout(struct bnode *bn)
                 SDTIME);
        }
     }
+
+    if ((abnode->b.flags & BNODE_ERRORSTOP) && !abnode->salRunning
+       && !abnode->volRunning && !abnode->fileRunning && !abnode->scanRunning
+       && !abnode->salsrvRunning) {
+       bnode_SetStat(bn, BSTAT_NORMAL);
+    }
+    else {
+       bnode_ResetErrorCount(bn);
+    }
+
     SetNeedsClock(abnode);
     return 0;
 }
@@ -697,12 +755,27 @@ fs_setstat(struct bnode *abnode, afs_int32 astatus)
 }
 
 static int
+fs_procstarted(struct bnode *bn, struct bnode_proc *aproc)
+{
+    int code = 0;
+
+    if (DoPidFiles) {
+       code = bozo_CreatePidFile(bn->name, aproc->coreName, aproc->pid);
+    }
+    return code;
+}
+
+static int
 fs_procexit(struct bnode *bn, struct bnode_proc *aproc)
 {
    struct fsbnode *abnode = (struct fsbnode *)bn;
 
     /* process has exited */
 
+    if (DoPidFiles) {
+       bozo_DeletePidFile(bn->name, aproc->coreName);
+    }
+
     if (aproc == abnode->volProc) {
        abnode->volProc = 0;
        abnode->volRunning = 0;
@@ -750,17 +823,38 @@ fs_procexit(struct bnode *bn, struct bnode_proc *aproc)
 static void
 SetNeedsClock(struct fsbnode *ab)
 {
-    if (ab->b.goal == 1 && ab->fileRunning && ab->volRunning
+    afs_int32 timeout = POLLTIME;
+
+    if ((ab->fileSDW && !ab->fileKillSent) || (ab->volSDW && !ab->volKillSent)
+       || (ab->scanSDW && !ab->scanKillSent) || (ab->salSDW && !ab->salKillSent)
+       || (ab->salsrvSDW && !ab->salsrvKillSent)) {
+       /* SIGQUIT sent, will send SIGKILL if process does not exit */
+       ab->needsClock = 1;
+    } else if (ab->b.goal == 1 && ab->fileRunning && ab->volRunning
        && (!ab->scancmd || ab->scanRunning)
-       && (!ab->salsrvcmd || ab->salsrvRunning))
-       ab->needsClock = 0;     /* running normally */
-    else if (ab->b.goal == 0 && !ab->fileRunning && !ab->volRunning
-            && !ab->salRunning && !ab->scanRunning && !ab->salsrvRunning)
-       ab->needsClock = 0;     /* halted normally */
-    else
+       && (!ab->salsrvcmd || ab->salsrvRunning)) {
+       if (ab->b.errorStopCount) {
+           /* reset error count after running for a bit */
+           ab->needsClock = 1;
+       } else {
+           ab->needsClock = 0; /* running normally */
+       }
+    } else if ((ab->b.goal == 0) && !ab->fileRunning && !ab->volRunning
+              && !ab->salRunning && !ab->scanRunning && !ab->salsrvRunning) {
+       if (ab->b.flags & BNODE_ERRORSTOP && ab->b.errorStopDelay) {
+           bozo_Log("%s will retry start in %d seconds\n", ab->b.name,
+                    ab->b.errorStopDelay);
+           ab->needsClock = 1; /* halted for errors, retry later */
+           timeout = ab->b.errorStopDelay;
+       } else {
+           ab->needsClock = 0; /* halted normally */
+       }
+    } else
        ab->needsClock = 1;     /* other */
-    if (ab->needsClock && !bnode_PendingTimeout(fsbnode2bnode(ab)))
-       bnode_SetTimeout(fsbnode2bnode(ab), POLLTIME);
+
+    if (ab->needsClock && (!bnode_PendingTimeout(fsbnode2bnode(ab))
+                          || ab->b.period != timeout))
+       bnode_SetTimeout(fsbnode2bnode(ab), timeout);
     if (!ab->needsClock)
        bnode_SetTimeout(fsbnode2bnode(ab), 0);
 }