bos-mrafs-support-20010212
authorHartmut Reuter <reuter@rzg.mpg.de>
Mon, 12 Feb 2001 20:30:50 +0000 (20:30 +0000)
committerDerrick Brashear <shadow@dementia.org>
Mon, 12 Feb 2001 20:30:50 +0000 (20:30 +0000)
Necessary additions to bos for MR-AFS support

====================
This delta was composed from multiple commits as part of the CVS->Git migration.
The checkin message with each commit was inconsistent.
The following are the additional commit messages.
====================
FS bnode changes for MR-AFS

====================
allow hex numbers for residencies, used by bos

src/bozo/bos.c
src/bozo/fsbnodeops.c
src/util/volparse.c

index 1d3c1ed..f6c1085 100644 (file)
@@ -55,6 +55,30 @@ static DoStat();
 #include "bosint.h"
 #include "../permit_xprt.h"
 
+#define MRAFS_OFFSET  9
+#define ADDPARMOFFSET 26
+
+static struct SalvageParms {
+    afs_int32 Optdebug;
+    afs_int32 Optnowrite;
+    afs_int32 Optforce;
+    afs_int32 Optoktozap;
+    afs_int32 Optrootfiles;
+    afs_int32 Optsalvagedirs;
+    afs_int32 Optblockreads;
+    afs_int32 OptListResidencies;
+    afs_int32 OptSalvageRemote;
+    afs_int32 OptSalvageArchival;
+    afs_int32 OptIgnoreCheck;
+    afs_int32 OptForceOnLine;
+    afs_int32 OptUseRootDirACL;
+    afs_int32 OptTraceBadLinkCounts;
+    afs_int32 OptDontAskFS;
+    afs_int32 OptLogLevel;
+    afs_int32 OptRxDebug;
+    afs_uint32 OptResidencies;
+} mrafsParm;
+
 /* dummy routine for the audit work.  It should do nothing since audits */
 /* occur at the server level and bos is not a server. */
 osi_audit() {return 0;}
@@ -154,14 +178,15 @@ struct cmd_syndesc *as; {
     bcopy(th->h_addr, &addr, sizeof(afs_int32));
 
     /* get tokens for making authenticated connections */
-    localauth = (as->parms[14].items != 0);
+    localauth = (as->parms[ADDPARMOFFSET + 2].items != 0);
     confdir = (localauth ? AFSDIR_SERVER_ETC_DIRPATH : AFSDIR_CLIENT_ETC_DIRPATH);
     tdir = afsconf_Open (confdir);
     if (tdir) {
        struct afsconf_cell info;
        char *tname;
 
-       if (as->parms[12].items) tname = as->parms[12].items->data;
+       if (as->parms[ADDPARMOFFSET].items) 
+           tname = as->parms[ADDPARMOFFSET].items->data;
        else tname = (char *) 0;
        /* next call expands cell name abbrevs for us and handles looking up
          * local cell */
@@ -184,8 +209,8 @@ struct cmd_syndesc *as; {
     sc[2] = 0;
     scIndex = 0;
 
-    if (!as->parms[13].items) {        /* not -noauth */
-       if (as->parms[14].items) { /* -localauth */
+    if (!as->parms[ADDPARMOFFSET + 1].items) { /* not -noauth */
+       if (as->parms[ADDPARMOFFSET + 2].items) { /* -localauth */
            code = afsconf_GetLatestKey (tdir, 0,0);
            if (code) com_err ("bos", code, "(getting key from local KeyFile)");
            else {
@@ -496,6 +521,36 @@ struct cmd_syndesc *as; {
     return 0;
 }
 
+static BlockScannerCmd(as, arock)
+struct cmd_syndesc *as;
+char *arock; {
+    register afs_int32 code;
+    struct rx_connection *tconn;
+    char BlockCommand[] = "/usr/afs/bin/scanner -block";
+
+    tconn = GetConn(as, 0);
+    code = BOZO_Exec(tconn, BlockCommand);
+    if (code)
+        printf("bos: failed to block scanner from making migration requests (%s)\n",
+               em(code));
+    return 0;
+}
+
+static UnBlockScannerCmd(as, arock)
+struct cmd_syndesc *as;
+char *arock; {
+    register afs_int32 code;
+    struct rx_connection *tconn;
+    char UnBlockCommand[] = "/usr/afs/bin/scanner -unblock";
+
+    tconn = GetConn(as, 0);
+    code = BOZO_Exec(tconn, UnBlockCommand);
+    if (code)
+        printf("bos: failed to allow scanner daemon to make migration requests again (%s)\n",
+               em(code));
+    return 0;
+}                      
+
 static GetRestartCmd(as, arock)
 struct cmd_syndesc *as;
 char *arock; {
@@ -751,8 +806,8 @@ register struct cmd_syndesc *as; {
        strcpy((char *)&tkey, buf);
     }
     else {    /* kerberos key */
-       if (as->parms[12].items) {
-           strcpy(cellBuffer, as->parms[12].items->data);
+       if (as->parms[ADDPARMOFFSET].items) {
+           strcpy(cellBuffer, as->parms[ADDPARMOFFSET].items->data);
 
            /* string to key needs upper-case cell names */
 
@@ -1034,6 +1089,8 @@ register struct cmd_syndesc *as; {
     return code;
 }
 
+#define PARMBUFFERSSIZE 32
+
 static DoSalvage(aconn, aparm1, aparm2, aoutName, showlog,parallel,atmpDir,orphans)
 struct rx_connection *aconn;
 char *aoutName;
@@ -1054,6 +1111,7 @@ char *orphans;
     FILE *outFile;
     int closeIt;
     char partName[20]; /* canonical name for partition */
+    char pbuffer[PARMBUFFERSSIZE];
     afs_int32 partNumber;
     char *notifier = NONOTIFIER;
 
@@ -1141,6 +1199,47 @@ char *orphans;
        strcat(tbuffer, orphans);
     }
 
+    if (mrafsParm.Optdebug)
+        strcat(tbuffer," -debug");
+    if (mrafsParm.Optnowrite)
+        strcat(tbuffer," -nowrite");
+    if (mrafsParm.Optforce)
+        strcat(tbuffer," -force");
+    if (mrafsParm.Optoktozap)
+        strcat(tbuffer," -oktozap");
+    if (mrafsParm.Optrootfiles)
+        strcat(tbuffer," -rootfiles");
+    if (mrafsParm.Optsalvagedirs)
+        strcat(tbuffer," -salvagedirs");
+    if (mrafsParm.Optblockreads)
+        strcat(tbuffer," -blockreads");
+    if (mrafsParm.OptListResidencies)
+        strcat(tbuffer," -ListResidencies");
+    if (mrafsParm.OptSalvageRemote)
+        strcat(tbuffer," -SalvageRemote");
+    if (mrafsParm.OptSalvageArchival)
+        strcat(tbuffer," -SalvageArchival");
+    if (mrafsParm.OptIgnoreCheck)
+        strcat(tbuffer," -IgnoreCheck");
+    if (mrafsParm.OptForceOnLine)
+        strcat(tbuffer," -ForceOnLine");
+    if (mrafsParm.OptUseRootDirACL)
+        strcat(tbuffer," -UseRootDirACL");
+    if (mrafsParm.OptTraceBadLinkCounts)
+        strcat(tbuffer," -TraceBadLinkCounts");
+    if (mrafsParm.OptDontAskFS)
+        strcat(tbuffer," -DontAskFS");
+    if (mrafsParm.OptLogLevel) {
+        sprintf(pbuffer, " -LogLevel %ld", mrafsParm.OptLogLevel);
+        strcat(tbuffer, pbuffer);
+    }
+    if (mrafsParm.OptRxDebug)
+        strcat(tbuffer," -rxdebug");
+    if (mrafsParm.OptResidencies) {
+        sprintf(pbuffer, " -Residencies %lu", mrafsParm.OptResidencies);
+        strcat(tbuffer, pbuffer);
+    } 
+
     parms[0] = tbuffer;
     parms[1] = "now";      /* when to do it */
     code = BOZO_CreateBnode(aconn, "cron", "salvage-tmp", parms[0], parms[1],
@@ -1158,6 +1257,7 @@ char *orphans;
        printf("bos: salvage failed (%s)\n", em(code));
        goto done;
     }
+    code = 0;
 
     /* now print the log file to the output file */
     printf("bos: salvage completed\n");
@@ -1225,19 +1325,28 @@ register struct cmd_syndesc *as; {
 static SalvageCmd(as)
 struct cmd_syndesc *as; {
     register struct rx_connection *tconn;
-    register afs_int32 code, rc;
+    register afs_int32 code, rc, i;
     char *outName;
-    char tname[65];
+    char tname[BOZO_BSSIZE];
     afs_int32 newID;
     extern struct ubik_client *cstruct;
-    afs_int32 curGoal, showlog = 0;
+    afs_int32 curGoal, showlog = 0, mrafs = 0;
     char *parallel;
     char *tmpDir;
     char *orphans;
+    char *tp;
+
+    bzero(&mrafsParm, sizeof(mrafsParm));
     
     /* parm 0 is machine name, 1 is partition, 2 is volume, 3 is -all flag */
     tconn = GetConn(as, 0);
 
+    /* Find out whether fileserver is running MR-AFS (has a scanner instance) */
+    /* XXX this should really be done some other way, potentially by RPC */
+    tp = &tname;
+    if (code = BOZO_GetInstanceParm(tconn, "fs", 3, &tp) == 0)
+       mrafs = 1;
+
     /* we can do a volume, a partition or the whole thing, but not mixtures
      * thereof */
     if (!as->parms[1].items && as->parms[2].items) {
@@ -1274,8 +1383,75 @@ struct cmd_syndesc *as; {
 
     /* -orphans option */
     orphans = (char *)0;
-    if (as->parms[8].items)
-       orphans = as->parms[8].items->data;
+    if (as->parms[8].items) {
+       if (mrafs) {
+           printf("Can't specify -orphans for MR-AFS fileserver\n");
+           return EINVAL;
+       }
+        orphans = as->parms[8].items->data;
+    }
+    
+    if (mrafs) {
+        if (as->parms[MRAFS_OFFSET].items)
+            mrafsParm.Optdebug = 1;
+        if (as->parms[MRAFS_OFFSET + 1].items)
+            mrafsParm.Optnowrite = 1;
+        if (as->parms[MRAFS_OFFSET + 2].items)
+            mrafsParm.Optforce = 1;
+        if (as->parms[MRAFS_OFFSET + 3].items)
+            mrafsParm.Optoktozap = 1;
+        if (as->parms[MRAFS_OFFSET + 4].items)
+            mrafsParm.Optrootfiles = 1;
+        if (as->parms[MRAFS_OFFSET + 5].items)
+            mrafsParm.Optsalvagedirs = 1;
+        if (as->parms[MRAFS_OFFSET + 6].items)
+            mrafsParm.Optblockreads = 1;
+        if (as->parms[MRAFS_OFFSET + 7].items)
+            mrafsParm.OptListResidencies = 1;
+        if (as->parms[MRAFS_OFFSET + 8].items)
+            mrafsParm.OptSalvageRemote = 1;
+        if (as->parms[MRAFS_OFFSET + 9].items)
+            mrafsParm.OptSalvageArchival = 1;
+        if (as->parms[MRAFS_OFFSET + 10].items)
+            mrafsParm.OptIgnoreCheck = 1;
+        if (as->parms[MRAFS_OFFSET + 11].items)
+            mrafsParm.OptForceOnLine = 1;
+        if (as->parms[MRAFS_OFFSET + 12].items)
+            mrafsParm.OptUseRootDirACL = 1;
+        if (as->parms[MRAFS_OFFSET + 13].items)
+            mrafsParm.OptTraceBadLinkCounts = 1;
+        if (as->parms[MRAFS_OFFSET + 14].items)
+            mrafsParm.OptDontAskFS = 1;
+        if (as->parms[MRAFS_OFFSET + 15].items)
+            mrafsParm.OptLogLevel = atoi(as->parms[MRAFS_OFFSET + 15].items->dta);
+        if (as->parms[MRAFS_OFFSET + 16].items)
+            mrafsParm.OptRxDebug = 1;
+        if (as->parms[MRAFS_OFFSET + 17].items) {                             
+           if (as->parms[MRAFS_OFFSET + 8].items || 
+               as->parms[MRAFS_OFFSET + 9].items) {
+                printf("Can't specify -Residencies with -SalvageRemote or -SalvageArchival\n");
+                return EINVAL;
+            }
+            code = GetUInt32(as->parms[MRAFS_OFFSET + 17].items->data, 
+                                       &mrafsParm.OptResidencies);
+            if (code) {
+                printf("bos: '%s' is not a valid residency mask.\n",
+                       as->parms[MRAFS_OFFSET + 13].items->data);
+                return code;
+            }
+        }
+    } else {
+       int stop = 0;
+
+       for (i = 9; i < ADDPARMOFFSET; i++) {
+           if (as->parms[i].items) {
+               printf(" %s only possible for MR-AFS fileserver.\n",
+                       as->parms[i].name);
+               stop = 1;
+           }
+       }
+       if (stop) exit(1);
+    }
 
     if (as->parms[4].items) {
        /* salvage whole enchilada */
@@ -1355,10 +1531,11 @@ struct cmd_syndesc *as; {
        const char *confdir;
        int localauth;
 
-       if (as->parms[12].items) tmpname = as->parms[12].items->data;
+       if (as->parms[ADDPARMOFFSET].items) 
+           tmpname = as->parms[ADDPARMOFFSET].items->data;
        else tmpname = (char *) 0;
 
-       localauth = (as->parms[14].items != 0);
+       localauth = (as->parms[ADDPARMOFFSET + 2].items != 0);
        confdir = (localauth ? AFSDIR_SERVER_ETC_DIRPATH : AFSDIR_CLIENT_ETC_DIRPATH);
        code = vsu_ClientInit(/* noauth */ 1, confdir, tmpname,
                              /* server auth */ 0, &cstruct, (int (*)()) 0);
@@ -1548,12 +1725,12 @@ struct cmd_syndesc *as; {
 static void add_std_args (ts)
   register struct cmd_syndesc *ts;
 {
-    cmd_Seek(ts, 12);
-    /* 12 */ cmd_AddParm(ts, "-cell", CMD_SINGLE, CMD_OPTIONAL, "cell name");
-    /* 13 */cmd_AddParm(ts, "-noauth", CMD_FLAG, CMD_OPTIONAL,
-                       "don't authenticate");
-    /* 14 */ cmd_AddParm (ts, "-localauth", CMD_FLAG, CMD_OPTIONAL,
-                         "create tickets from KeyFile");
+    cmd_Seek(ts, ADDPARMOFFSET);
+    /* + 0 */ cmd_AddParm(ts, "-cell", CMD_SINGLE, CMD_OPTIONAL, "cell name");
+    /* + 1 */ cmd_AddParm(ts, "-noauth", CMD_FLAG, CMD_OPTIONAL,
+                        "don't authenticate");
+    /* + 2 */ cmd_AddParm (ts, "-localauth", CMD_FLAG, CMD_OPTIONAL,
+                          "create tickets from KeyFile");
 }
   
 #include "AFS_component_version_number.c"
@@ -1790,8 +1967,36 @@ main(argc, argv)
                "directory to place tmp files");
     cmd_AddParm(ts, "-orphans", CMD_SINGLE, CMD_OPTIONAL, 
                "ignore | remove | attach");
+    cmd_AddParm(ts, "-debug", CMD_FLAG,CMD_OPTIONAL, "(MR-AFS) Run in Debugging mode");
+    cmd_AddParm(ts, "-nowrite", CMD_FLAG,CMD_OPTIONAL, "(MR-AFS) Run readonly/test mode");
+    cmd_AddParm(ts, "-force", CMD_FLAG,CMD_OPTIONAL, "(MR-AFS) Force full salvaging");
+    cmd_AddParm(ts, "-oktozap", CMD_FLAG,CMD_OPTIONAL, "(MR-AFS) Give permission to destroy bogus file residencies/volumes - debugging flag");
+    cmd_AddParm(ts, "-rootfiles", CMD_FLAG,CMD_OPTIONAL, "(MR-AFS) Show files owned by root - debugging flag");
+    cmd_AddParm(ts, "-salvagedirs", CMD_FLAG,CMD_OPTIONAL, "(MR-AFS) Force rebuild/salvage of all directories");
+    cmd_AddParm(ts, "-blockreads", CMD_FLAG,CMD_OPTIONAL, "(MR-AFS) Read smaller blocks to handle IO/bad blocks");
+    cmd_AddParm(ts, "-ListResidencies", CMD_FLAG,CMD_OPTIONAL, "(MR-AFS) Just list affected file residencies - debugging flag");
+    cmd_AddParm(ts, "-SalvageRemote", CMD_FLAG,CMD_OPTIONAL, "(MR-AFS) Salvage storage systems that are not directly attached");
+    cmd_AddParm(ts, "-SalvageArchival", CMD_FLAG,CMD_OPTIONAL, "(MR-AFS) Salvage HSM storage systems");
+    cmd_AddParm(ts, "-IgnoreCheck", CMD_FLAG,CMD_OPTIONAL, "(MR-AFS) Don't perform VLDB safety check when deleting unreferenced files.  Only a good idea in single server cell.");
+    cmd_AddParm(ts, "-ForceOnLine", CMD_FLAG,CMD_OPTIONAL, "(MR-AFS) Force the volume to come online, even if it hasn't salvaged cleanly.");
+    cmd_AddParm(ts, "-UseRootDirACL", CMD_FLAG,CMD_OPTIONAL, "(MR-AFS) Use the root directory ACL for lost+found directory if it is created.");
+    cmd_AddParm(ts, "-TraceBadLinkCounts", CMD_FLAG,CMD_OPTIONAL, "(MR-AFS) Print out lines about volume reference count changes.");
+    cmd_AddParm(ts, "-DontAskFS", CMD_FLAG,CMD_OPTIONAL, "(MR-AFS) Don't ask fileserver to take volume offline.  THIS IS VERY DANGEROUS.");
+    cmd_AddParm(ts, "-LogLevel", CMD_SINGLE, CMD_OPTIONAL, "(MR-AFS) log level");
+    cmd_AddParm(ts, "-rxdebug", CMD_FLAG, CMD_OPTIONAL, "(MR-AFS) Write out rx debug information.");
+    cmd_AddParm(ts, "-Residencies", CMD_SINGLE, CMD_OPTIONAL, "(MR-AFS) Numeric mask of residencies to be included in the salvage.  Do not use with -SalvageRemote or -SalvageArchival");
     add_std_args (ts);
 
+    ts = cmd_CreateSyntax("blockscanner", BlockScannerCmd, 0,
+                          "block scanner daemon from making migration requests");
+    cmd_AddParm(ts, "-server", CMD_SINGLE, CMD_REQUIRED, "machine name");
+    add_std_args (ts);
+
+    ts = cmd_CreateSyntax("unblockscanner", UnBlockScannerCmd, 0,
+                          "allow scanner daemon to make migration requests again");
+    cmd_AddParm(ts, "-server", CMD_SINGLE, CMD_REQUIRED, "machine name");
+    add_std_args (ts); 
+
 #ifdef BOS_RESTRICTED_MODE
     ts = cmd_CreateSyntax("getrestricted", GetRestrict, 0, "get restrict mode");
     cmd_AddParm(ts, "-server", CMD_SINGLE, 0, "machine name");
index ec4d62d..6b63285 100644 (file)
@@ -30,6 +30,7 @@ static int fs_timeout(), fs_getstat(), fs_setstat(), fs_delete();
 static int fs_procexit(), fs_getstring(), fs_getparm(), fs_restartp();
 static int fs_hascore();
 struct bnode *fs_create();
+struct bnode *fsmr_create();
 
 static SetNeedsClock();
 static NudgeProcs();
@@ -80,20 +81,26 @@ struct fsbnode {
     char *filecmd;                 /* command to start primary file server */
     char *volcmd;                  /* command to start secondary vol server */
     char *salcmd;                  /* command to start salvager */
+    char *scancmd;                  /* command to start scanner (MR-AFS) */
     struct bnode_proc *fileProc;    /* process for file server */
     struct bnode_proc *volProc;            /* process for vol server */
     struct bnode_proc *salProc;            /* process for salvager */
-    afs_int32 lastFileStart;               /* last start for file */
-    afs_int32 lastVolStart;                /* last start for vol */
+    struct bnode_proc *scanProc;    /* process for scanner (MR-AFS) */
+    afs_int32 lastFileStart;        /* last start for file */
+    afs_int32 lastVolStart;         /* last start for vol */
+    afs_int32 lastScanStart;        /* last start for scanner (MR-AFS) */
     char fileRunning;              /* file process is running */
     char volRunning;               /* volser is running */
     char salRunning;               /* salvager is running */
+    char scanRunning;               /* scanner is running (MR_AFS) */
     char fileSDW;                  /* file shutdown wait */
     char volSDW;                   /* vol shutdown wait */
     char salSDW;                   /* waiting for the salvager to shutdown */
+    char scanSDW;                   /* scanner shutdown wait (MR_AFS) */
     char fileKillSent;             /* kill signal has been sent */
     char volKillSent;
     char salKillSent;
+    char scanKillSent;              /* kill signal has been sent (MR_AFS) */
     char needsSalvage;             /* salvage before running */
     char needsClock;               /* do we need clock ticks */
 };
@@ -120,6 +127,10 @@ register struct ezbnode *abnode; {
     bnode_CoreName(abnode, "salv", tbuffer);
     if (access(tbuffer, 0) == 0) return 1;
 
+    /* see if scanner left a core file (MR-AFS) */
+    bnode_CoreName(abnode, "scan", tbuffer);
+    if (access(tbuffer, 0) == 0) return 1;
+
     /* no one left a core file */
     return 0;
 }
@@ -155,6 +166,22 @@ register struct fsbnode *abnode; {
     if (tstat.st_ctime > abnode->lastVolStart) code = 1;
     else code = 0;
     bnode_FreeTokens(tt);
+    if (code) return code;
+
+    if (abnode->scancmd) {                     /* Only in MR-AFS */
+        /* now do same for scancmd (MR-AFS) */
+        code = bnode_ParseLine(abnode->scancmd, &tt);
+        if (code) return 0;
+        if (!tt) return 0;
+        code = stat(tt->key, &tstat);
+        if (code) {
+            bnode_FreeTokens(tt);
+            return 0;
+       }
+        if (tstat.st_ctime > abnode->lastScanStart) code = 1;
+        else code = 0;
+        bnode_FreeTokens(tt); 
+    }
 
     return code;
 }
@@ -210,6 +237,7 @@ struct fsbnode *abnode; {
     free(abnode->filecmd);
     free(abnode->volcmd);
     free(abnode->salcmd);
+    if (abnode->scancmd) free(abnode->scancmd);
     free(abnode);
     return 0;
 }
@@ -229,15 +257,16 @@ static void AppendExecutableExtension(char *cmd)
 #endif /* AFS_NT40_ENV */
 
 
-struct bnode *fs_create(ainstance, afilecmd, avolcmd, asalcmd)
+struct bnode *fs_create(ainstance, afilecmd, avolcmd, asalcmd, ascancmd)
 char *ainstance;
 char *afilecmd;
 char *avolcmd;
-char *asalcmd; {
+char *asalcmd; 
+char *ascancmd; {
     struct stat tstat;
     register struct fsbnode *te;
     char cmdname[AFSDIR_PATH_MAX];
-    char *fileCmdpath, *volCmdpath, *salCmdpath;
+    char *fileCmdpath, *volCmdpath, *salCmdpath, *scanCmdpath;
     int bailout = 0;
 
     fileCmdpath = volCmdpath = salCmdpath = NULL;
@@ -256,6 +285,13 @@ char *asalcmd; {
        bailout = 1;
     }
 
+    if (strlen(ascancmd)) {
+       if (ConstructLocalBinPath(ascancmd, &scanCmdpath)) {
+            bozo_Log("BNODE: command path invalid '%s'\n", ascancmd);
+            bailout = 1;
+       }
+    }
+
     if (!bailout) {
        sscanf(fileCmdpath, "%s", cmdname);
 #ifdef AFS_NT40_ENV
@@ -283,6 +319,17 @@ char *asalcmd; {
            bozo_Log("BNODE: salvager binary '%s' not found\n", cmdname);
            bailout = 1;
        }
+
+        if (strlen(ascancmd)) {
+           sscanf(scanCmdpath, "%s", cmdname);
+#ifdef AFS_NT40_ENV
+           AppendExecutableExtension(cmdname);
+#endif
+           if (stat(cmdname, &tstat)) {
+               bozo_Log("BNODE: scanner binary '%s' not found\n", cmdname);
+               bailout = 1;
+           }
+       }
     }
 
     if (bailout) {
@@ -295,6 +342,10 @@ char *asalcmd; {
     te->filecmd = fileCmdpath;
     te->volcmd = volCmdpath;
     te->salcmd = salCmdpath;
+    if (strlen(ascancmd))
+       te->scancmd = scanCmdpath;
+    else 
+       te->scancmd = (char *)0;
     bnode_InitBnode(te, &fsbnode_ops, ainstance);
     bnode_SetTimeout(te, POLLTIME);    /* ask for timeout activations every 10 seconds */
     RestoreSalFlag(te);                /* restore needsSalvage flag based on file's existence */
@@ -333,6 +384,14 @@ struct fsbnode *abnode; {
                     FSSDTIME);
        }
     }
+    if (abnode->scanSDW) {
+        if (!abnode->scanKillSent && now - abnode->timeSDStarted > SDTIME) {
+            bnode_StopProc(abnode->scanProc, SIGKILL);
+            abnode->scanKillSent = 1;
+            bozo_Log("bos shutdown: scanner failed to shutdown within %d seconds\n",
+                     SDTIME);
+        }
+    }
     SetNeedsClock(abnode);
 }
 
@@ -340,11 +399,13 @@ static int fs_getstat(abnode, astatus)
 struct fsbnode *abnode;
 afs_int32 *astatus; {
     register afs_int32 temp;
-    if (abnode->volSDW || abnode->fileSDW || abnode->salSDW) temp = BSTAT_SHUTTINGDOWN;
+    if (abnode->volSDW || abnode->fileSDW || abnode->salSDW || abnode->scanSDW)
+       temp = BSTAT_SHUTTINGDOWN;
     else if (abnode->salRunning) temp = BSTAT_NORMAL;
-    else if (abnode->volRunning && abnode->fileRunning) temp = BSTAT_NORMAL;
-    else if (!abnode->salRunning && !abnode->volRunning && !abnode->fileRunning)
-       temp = BSTAT_SHUTDOWN;
+    else if (abnode->volRunning && abnode->fileRunning && (!abnode->scancmd || 
+       abnode->scanRunning)) temp = BSTAT_NORMAL;
+    else if (!abnode->salRunning && !abnode->volRunning && !abnode->fileRunning
+        && !abnode->scanRunning) temp = BSTAT_SHUTDOWN;
     else temp = BSTAT_STARTINGUP;
     *astatus = temp;
     return 0;
@@ -390,6 +451,12 @@ struct bnode_proc *aproc; {
        abnode->salSDW = 0;
        abnode->salKillSent = 0;
     }
+    else if (aproc == abnode->scanProc) {
+        abnode->scanProc = 0;
+        abnode->scanRunning = 0;
+        abnode->scanSDW = 0;
+        abnode->scanKillSent = 0;
+    }
 
     /* now restart anyone who needs to restart */
     return NudgeProcs(abnode);
@@ -397,10 +464,13 @@ struct bnode_proc *aproc; {
 
 /* make sure we're periodically checking the state if we need to */
 static SetNeedsClock(ab)
-register struct fsbnode *ab; {
-    if (ab->b.goal == 1 && ab->fileRunning && ab->volRunning)
+    register struct fsbnode *ab; 
+{
+    if (ab->b.goal == 1 && ab->fileRunning && ab->volRunning
+       && (!ab->scancmd || ab->scanRunning))
        ab->needsClock = 0; /* running normally */
-    else if (ab->b.goal == 0 && !ab->fileRunning && !ab->volRunning && !ab->salRunning)
+    else if (ab->b.goal == 0 && !ab->fileRunning && !ab->volRunning 
+            && !ab->salRunning && !ab->scanRunning)
        ab->needsClock = 0; /* halted normally */
     else ab->needsClock        = 1;    /* other */
     if (ab->needsClock && !bnode_PendingTimeout(ab))
@@ -437,6 +507,16 @@ register struct fsbnode *abnode; {
                    abnode->volRunning = 1;
                }
            }
+           if (abnode->scancmd) {
+               if (!abnode->scanRunning) {
+                   abnode->lastScanStart = FT_ApproxTime();
+                   code = bnode_NewProc(abnode, abnode->scancmd, "scanner", &tp);
+                   if (code == 0) {
+                       abnode->scanProc = tp;
+                       abnode->scanRunning = 1;
+                   }
+               }
+           }    
        }
        else {  /* file is not running */
            /* see how to start */
@@ -459,6 +539,15 @@ register struct fsbnode *abnode; {
                        abnode->volRunning = 1;
                    }
                }
+               if (abnode->scancmd && !abnode->scanRunning) {
+                    abnode->lastScanStart = FT_ApproxTime();
+                    code = bnode_NewProc(abnode, abnode->scancmd, "scanner",
+                                         &tp);
+                    if (code == 0) {
+                        abnode->scanProc = tp;
+                        abnode->scanRunning = 1;
+                    }
+                }
            }
            else {  /* needs to be salvaged */
                /* make sure file server and volser are gone */
@@ -472,7 +561,13 @@ register struct fsbnode *abnode; {
                    if (!abnode->fileSDW) abnode->timeSDStarted = now;
                    abnode->fileSDW = 1;
                }
-               if (abnode->volRunning || abnode->fileRunning) return 0;
+                if (abnode->scanRunning) {
+                    bnode_StopProc(abnode->scanProc, SIGTERM);
+                    if (!abnode->scanSDW) abnode->timeSDStarted = now;
+                    abnode->scanSDW = 1;
+                }
+               if (abnode->volRunning || abnode->fileRunning 
+                   || abnode->scanRunning) return 0;
                /* otherwise, it is safe to start salvager */
                if (!abnode->salRunning) {
                    code = bnode_NewProc(abnode, abnode->salcmd, "salv", &tp);
@@ -501,6 +596,11 @@ register struct fsbnode *abnode; {
            abnode->volSDW = 1;
            abnode->timeSDStarted = now;
        }
+        if (abnode->scanRunning && !abnode->scanSDW) {
+            bnode_StopProc(abnode->scanProc, SIGTERM);
+            abnode->scanSDW = 1;
+            abnode->timeSDStarted = now;
+        }
     }
     SetNeedsClock(abnode);
     return 0;
@@ -514,7 +614,18 @@ afs_int32 alen;{
     if (abnode->b.goal == 1) {
        if (abnode->fileRunning) {
            if (abnode->fileSDW) strcpy(abuffer, "file server shutting down");
-           else if (!abnode->volRunning) strcpy(abuffer, "file server up; volser down");
+           else if (abnode->scancmd) {
+                if (!abnode->volRunning && !abnode->scanRunning)
+                    strcpy(abuffer, "file server up; volser and scanner down");
+               else if (abnode->volRunning && !abnode->scanRunning)
+                    strcpy(abuffer, "file server up; volser up; scanner down");
+               else if (!abnode->volRunning && abnode->scanRunning)
+                    strcpy(abuffer, "file server up; volser down; scanner up");
+
+               else strcpy(abuffer, "file server running");
+           } 
+           else if (!abnode->volRunning) 
+               strcpy(abuffer, "file server up; volser down");
            else strcpy(abuffer, "file server running");
        }
        else if (abnode->salRunning) {
@@ -524,7 +635,7 @@ afs_int32 alen;{
     }
     else {
        /* shutting down */
-       if (abnode->fileRunning || abnode->volRunning) {
+       if (abnode->fileRunning || abnode->volRunning || abnode->scanRunning) {
            strcpy(abuffer, "file server shutting down");
        }
        else if (abnode->salRunning)
@@ -545,6 +656,8 @@ afs_int32  alen; {
        strcpy(abuffer, abnode->volcmd);
     else if (aindex == 2)
        strcpy(abuffer, abnode->salcmd);
+    else if (aindex == 3 && abnode->scancmd)
+       strcpy(abuffer, abnode->scancmd);
     else
        return BZDOM;
     return 0;
index 1efbcd1..33cbb69 100644 (file)
@@ -179,3 +179,43 @@ afs_int32 *aval;
     else *aval = total;
     return 0;
 }
+
+afs_uint32
+GetUInt32 (as, aval)
+register char *as;
+afs_uint32 *aval;
+{
+    register afs_uint32 total;
+    register int tc;
+    int base;
+
+    total = 0;  /* initialize things */
+
+    /* skip over leading spaces */
+    while (tc = *as) {
+        if (tc != ' ' && tc != '\t') break;
+    }
+
+    /* compute the base */
+    if (*as == '0') {
+        as++;
+        if (*as == 'x' || *as == 'X') {
+            base = 16;
+            as++;
+       }
+        else base = 8;
+    }
+    else base = 10;
+
+    /* compute the # itself */
+    while(tc = *as) {
+        if (!ismeta(tc, base)) return -1;
+        total *= base;
+        total += getmeta(tc);
+        as++;
+    }
+    
+    *aval = total;
+    return 0;
+}
+