home *** CD-ROM | disk | FTP | other *** search
- /* do: "sh -x bdupdate.c" to make the executable */
-
- /*
- * v1.0 - released to Eric Youngdale 17 jan 1994
- * v1.1 - added exit() statements after two loops, DEBUG, argv0 diags
- * v1.2 - added getopt and a buch of flags to set params
- * v1.3 - Call setsid after each fork, print version number.
- * v1.4 - Minor bugfix - sync_delay and flush_delay were not being used.
- */
-
- #undef DEBUG
-
- #include <stdio.h>
- #include <sys/types.h>
- #include <unistd.h>
- #include <limits.h>
- #include <signal.h>
- #include <linux/unistd.h>
-
- /*
- * bdupdate: an attempt to unify the update and bdflush programs; this
- * should be a drop-in replacement for "update", but calls bdflush (if
- * it works) every 5 seconds, too.
- *
- * If invoked with an argument, it prints stats as-per bdflush.
- *
- * - alec <Alec.Muffett@UK.Sun.COM>
- */
-
- _syscall2(int, bdflush, int, func, int, data);
-
- static char * version_string = "1.4";
-
- char *bdparam[] =
- {
- "Max fraction of LRU list to examine for dirty blocks",
- "Max number of dirty blocks to write each time bdflush activated",
- "Num of clean buffers to be loaded onto free list by refill_freelist",
- "Dirty block threshold for activating bdflush in refill_freelist",
- "Percentage of cache to scan for free clusters",
- "Time for data buffers to age before flushing",
- "Time for non-data (dir, bitmap, etc) buffers to age before flushing",
- "Time buffer cache load average constant",
- "LAV ratio (used to determine threshold for buffer fratricide).",
- (char *) 0
- };
-
- void
- inststr(char *dst[], int argc, char *src)
- {
- if (strlen(src) <= strlen(dst[0]))
- {
- char *ptr;
-
- for (ptr = dst[0]; *ptr; *(ptr++) = '\0');
-
- strcpy(dst[0], src);
- } else
- {
- /* stolen from the source to perl 4.036 (assigning to $0) */
- char *ptr, *ptr2;
- int count;
- ptr = dst[0] + strlen(dst[0]);
- for (count = 1; count < argc; count++) {
- if (dst[count] == ptr + 1)
- ptr += strlen(++ptr);
- }
- if (environ[0] == ptr + 1) {
- for (count = 0; environ[count]; count++)
- if (environ[count] == ptr + 1)
- ptr += strlen(++ptr);
- }
- count = 0;
- for (ptr2 = dst[0]; ptr2 <= ptr; ptr2++) {
- *ptr2 = '\0';
- count++;
- }
- strncpy(dst[0], src, count);
- }
- }
-
- void
- usage(argv)
- char ** argv;
- {
- fprintf(stderr,"Usage:%s [-d][-s sync-delay][-f flush-delay]\n",argv[0]);
- fprintf(stderr," [-0 Max fraction of LRU list to examine for dirty blocks] \n");
- fprintf(stderr," [-1 Max number of dirty blocks to write each time bdflush activated] \n");
- fprintf(stderr," [-2 Num of clean buffers to be loaded onto free list by refill_freelist] \n");
- fprintf(stderr," [-3 Dirty block threshold for activating bdflush in refill_freelist] \n");
- fprintf(stderr," [-4 Percentage of cache to scan for free clusters] \n");
- fprintf(stderr," [-5 Time for data buffers to age before flushing] \n");
- fprintf(stderr," [-6 Time for non-data (dir, bitmap, etc) buffers to age before flushing] \n");
- fprintf(stderr," [-7 Time buffer cache load average constant] \n");
- fprintf(stderr," [-8 LAV ratio (used to determine threshold for buffer fratricide)] \n");
- exit(1);
- }
-
-
- int
- main(int argc, char *argv[])
- {
- int sync_delay = 30 , flush_delay = 5;
- int i;
- int go = 0;
- int ch;
-
- /* shame on whomever wrote getopt - global variables */
- extern char * optarg;
- extern int optind, optopt;
-
- /* Start by parseing command line options */
- while((ch = getopt(argc, argv, "ds:f:1:2:3:4:5:6:7:8:0:")) != EOF)
- switch(ch) {
- case 'd':
- /* print out the current parameters */
- printf("bdflush version %s\n", version_string);
- for (i = 0; bdparam[i]; i++)
- {
- int j;
- int data;
- int bdflag;
-
- bdflag = 2 + (i << 1);
-
- j = bdflush(bdflag, (int) &data);
-
- printf("%d: %5d %s\n", i, data, bdparam[i]);
-
- if (j)
- {
- fprintf(stderr, "bdupdate:(%d) bdflush(%08x,&d)=%d %d\n",
- i, bdflag, j, errno);
- break;
- }
- }
-
- go = 1;
-
- break;
- case 's':
- sync_delay = atoi(optarg);
- break;
- case 'f':
- flush_delay = atoi(optarg);
- break;
- case '1': case '2': case '3': case '4':
- case '5': case '6': case '7': case '8':
- case '0':
-
- if (i = bdflush(1+((ch - '0' + 1) <<1 ), atoi(optarg)))
- {
- fprintf(stderr, "bdupdate: bdflush(%d,%d)=%d %d\n",1+((ch - '0') <<1 ), atoi(optarg), i, errno);
- exit(1);
- }
-
- break;
- case ':':
- fprintf(stderr, "Option -%c requires an argument!\n",
- optopt);
- usage(argv);
- break;
- default:
- usage(argv);
- break;
- }
-
- if(go) exit(0);
-
- #ifndef DEBUG
- for (i = 0; i < OPEN_MAX; i++)
- {
- close(i);
- }
- #endif
-
- chdir("/");
-
- signal(SIGTERM, SIG_IGN);
- signal(SIGINT, SIG_IGN);
- signal(SIGCLD, SIG_IGN);
-
- if (!fork()) /* fork off a daemon */
- {
- inststr(argv, argc, "bdflush (daemon)");
- setsid(); /* Release terminal */
-
- if (i = bdflush(0, 0)) /* should never return */
- {
- #ifdef DEBUG /* this should not happen */
- fprintf(stderr, "bdupdate: bdflush(0,0)=%d %d\n", i, errno);
- #endif
- }
- exit(1);
- }
-
- if (!fork()) /* fork off a daemon */
- {
- int has_bdflush;
-
- inststr(argv, argc, "update (bdflush)");
- setsid(); /* Release terminal */
-
- has_bdflush = 1;
-
- for (;;) /* flush expired buffers */
- {
- if (has_bdflush)
- {
- sleep(flush_delay);
-
- if (i = bdflush(1, 0))
- {
- has_bdflush = 0; /* oopsie! */
-
- inststr(argv, argc, "update (sync)");
- #ifdef DEBUG
- fprintf(stderr, "bdupdate: bdflush(1,0)=%d %d\n", i, errno);
- #endif
- }
- } else
- {
- sleep(sync_delay);
-
- sync();
- }
- }
-
- exit(1);
- }
- /* parent exits */
- return (0);
- }
-