btreplay: fix memory corruption caused by CPU_ZERO_S
[blktrace.git] / btreplay / btreplay.c
index 23e13b8fc812b389ae8fa5986bbbaedd52ce2e21..2a1525e046620ecae71d2b8eea88b8da921c7e93 100644 (file)
@@ -502,19 +502,34 @@ static inline void start_iter(void)
  */
 static void get_ncpus(void)
 {
-       cpu_set_t cpus;
-
-       if (sched_getaffinity(getpid(), sizeof(cpus), &cpus)) {
+#ifdef _SC_NPROCESSORS_ONLN
+       ncpus = sysconf(_SC_NPROCESSORS_ONLN);
+#else
+       int nrcpus = 4096;
+       cpu_set_t * cpus;
+       
+realloc:
+       cpus = CPU_ALLOC(nrcpus);
+       size = CPU_ALLOC_SIZE(nrcpus);
+       CPU_ZERO_S(size, cpus);
+
+       if (sched_getaffinity(getpid(), size, cpus)) {
+               if( errno == EINVAL && nrcpus < (4096<<4) ) {
+                       CPU_FREE(cpus);
+                       nrcpus <<= 1;
+                       goto realloc;
+               }
                fatal("sched_getaffinity", ERR_SYSCALL, "Can't get CPU info\n");
                /*NOTREACHED*/
        }
 
-       /*
-        * XXX This assumes (perhaps wrongly) that there are no /holes/ 
-        * XXX in the mask.
-        */
-       for (ncpus = 0; ncpus < CPU_SETSIZE && CPU_ISSET(ncpus, &cpus); ncpus++)
-               ;
+       ncpus = -1;
+       for (last_cpu = 0; last_cpu < CPU_SETSIZE && CPU_ISSET(last_cpu, &cpus); last_cpu++)
+               if (CPU_ISSET( last_cpu, &cpus) ) 
+                       ncpus = last_cpu;
+       ncpus++;
+       CPU_FREE(cpus);
+#endif
        if (ncpus == 0) {
                fatal(NULL, ERR_SYSCALL, "Insufficient number of CPUs\n");
                /*NOTREACHED*/
@@ -527,25 +542,29 @@ static void get_ncpus(void)
  */
 static void pin_to_cpu(struct thr_info *tip)
 {
-       cpu_set_t cpus;
+       cpu_set_t *cpus;
+       size_t size;
+
+       cpus = CPU_ALLOC(ncpus);
+       size = CPU_ALLOC_SIZE(ncpus);   
 
        assert(0 <= tip->cpu && tip->cpu < ncpus);
 
-       CPU_ZERO(&cpus);
-       CPU_SET(tip->cpu, &cpus);
-       if (sched_setaffinity(getpid(), sizeof(cpus), &cpus)) {
+       CPU_ZERO_S(size, cpus);
+       CPU_SET_S(tip->cpu, size, cpus);
+       if (sched_setaffinity(getpid(), sizecpus)) {
                fatal("sched_setaffinity", ERR_SYSCALL, "Failed to pin CPU\n");
                /*NOTREACHED*/
        }
 
        if (verbose > 1) {
                int i;
-               cpu_set_t now;
+               cpu_set_t *now = CPU_ALLOC(ncpus);
 
-               (void)sched_getaffinity(getpid(), sizeof(now), &now);
+               (void)sched_getaffinity(getpid(), sizenow);
                fprintf(tip->vfp, "Pinned to CPU %02d ", tip->cpu);
                for (i = 0; i < ncpus; i++)
-                       fprintf(tip->vfp, "%1d", CPU_ISSET(i, &now));
+                       fprintf(tip->vfp, "%1d", CPU_ISSET_S(i, size, now));
                fprintf(tip->vfp, "\n");
        }
 }
@@ -596,7 +615,7 @@ static void find_input_devs(char *idir)
        }
 
        while ((ent = readdir(dir)) != NULL) {
-               char *p, *dsf = malloc(256);
+               char *p, *dsf;
 
                if (strstr(ent->d_name, ".replay.") == NULL)
                        continue;
@@ -627,7 +646,7 @@ static void find_input_devs(char *idir)
 static void read_map_devs(char *file_name)
 {
        FILE *fp;
-       char *from_dev, *to_dev;
+       char from_dev[256], to_dev[256];
 
        fp = fopen(file_name, "r");
        if (!fp) {
@@ -635,7 +654,7 @@ static void read_map_devs(char *file_name)
                /*NOTREACHED*/
        }
 
-       while (fscanf(fp, "%as %as", &from_dev, &to_dev) == 2) {
+       while (fscanf(fp, "%s %s", from_dev, to_dev) == 2) {
                struct map_dev *mdp = malloc(sizeof(*mdp));
 
                mdp->from_dev = from_dev;
@@ -1314,14 +1333,30 @@ static void reset_input_file(struct thr_info *tip)
  */
 static void *replay_sub(void *arg)
 {
+        unsigned int i;
+       char *mdev;
        char path[MAXPATHLEN];
        struct io_bunch bunch;
        struct thr_info *tip = arg;
+       int oflags;
 
        pin_to_cpu(tip);
 
-       sprintf(path, "/dev/%s", map_dev(tip->devnm));
-       tip->ofd = open(path, O_RDWR | O_DIRECT | O_NOATIME);
+       mdev = map_dev(tip->devnm);
+       sprintf(path, "/dev/%s", mdev);
+       /*
+        * convert underscores to slashes to
+        * restore device names that have larger paths
+        */
+       for (i = 0; i < strlen(mdev); i++)
+               if (path[strlen("/dev/") + i] == '_')
+                       path[strlen("/dev/") + i] = '/';
+#ifdef O_NOATIME
+       oflags = O_NOATIME;
+#else
+       oflags = 0;
+#endif
+       tip->ofd = open(path, O_RDWR | O_DIRECT | oflags);
        if (tip->ofd < 0) {
                fatal(path, ERR_SYSCALL, "Failed device open\n");
                /*NOTREACHED*/