On 26/04/24 12:02AM, Suren Baghdasaryan wrote:
> Add MAPS_FILE environment variable to select whether the tests to be run
> for /proc/pid/maps or /proc/pid/smaps. Add support for testing smaps file
> by reusing the same logic as with maps file but skipping all the data
> except for the VMA addresses, which are the only part relevant for the
> tearing tests. Skip PROCMAP_QUERY parts of the tests because smaps does
> not implement that ioctl.
> 
> Signed-off-by: Suren Baghdasaryan <[email protected]>

One comment question, otherwise..

Reviewed-by: Liam R. Howlett <[email protected]>

> ---
>  tools/testing/selftests/proc/proc-maps-race.c | 176 +++++++++++++-----
>  1 file changed, 132 insertions(+), 44 deletions(-)
> 
> diff --git a/tools/testing/selftests/proc/proc-maps-race.c 
> b/tools/testing/selftests/proc/proc-maps-race.c
> index c5031b0593b7..b677bc23cab9 100644
> --- a/tools/testing/selftests/proc/proc-maps-race.c
> +++ b/tools/testing/selftests/proc/proc-maps-race.c
> @@ -17,8 +17,8 @@
>   */
>  /*
>   * Fork a child that concurrently modifies address space while the main
> - * process is reading /proc/$PID/maps and verifying the results. Address
> - * space modifications include:
> + * process is reading /proc/$PID/maps and /proc/$PID/smaps, verifying the
                                         ^^^ and? Should this be or?  It
                                         doesn't match your commit
                                         message.


> + * results. Address space modifications include:
>   *     VMA splitting and merging
>   *
>   */
> @@ -73,6 +73,11 @@ enum test_state {
>       TEST_DONE,
>  };
>  
> +enum maps_file {
> +     MAPS,
> +     SMAPS,
> +};
> +
>  struct vma_modifier_info;
>  
>  FIXTURE(proc_maps_race)
> @@ -83,6 +88,7 @@ FIXTURE(proc_maps_race)
>       struct line_content last_line;
>       struct line_content first_line;
>       unsigned long duration_sec;
> +     enum maps_file maps_file;
>       int shared_mem_size;
>       int skip_pages;
>       int page_size;
> @@ -199,6 +205,57 @@ static void copy_last_line(struct page_content *page, 
> char *last_line)
>       last_line[end - pos] = '\0';
>  }
>  
> +static bool copy_first_entry(struct page_content *page, char *first_line)
> +{
> +     const char *start_pos = page->data;
> +
> +     while (start_pos < page->data + page->size) {
> +             unsigned long start_addr;
> +             unsigned long end_addr;
> +             char *end_pos;
> +
> +             end_pos = strchr(start_pos, '\n');
> +             if (!end_pos)
> +                     break;
> +
> +             if (sscanf(start_pos, "%lx-%lx", &start_addr, &end_addr) == 2) {
> +                     strncpy(first_line, start_pos, end_pos - start_pos);
> +                     first_line[end_pos - start_pos] = '\0';
> +                     return true;
> +             }
> +
> +             start_pos = end_pos + 1;
> +     }
> +
> +     return false;
> +}
> +
> +static bool copy_last_entry(struct page_content *page, char *last_line)
> +{
> +     const char *end_pos = page->data + page->size - 1;
> +     const char *start_pos;
> +
> +     while (end_pos > page->data) {
> +             unsigned long start_addr;
> +             unsigned long end_addr;
> +
> +             /* skip last newline */
> +             start_pos = end_pos - 1;
> +             /* search previous newline */
> +             while (start_pos > page->data && start_pos[-1] != '\n')
> +                     start_pos--;
> +             if (sscanf(start_pos, "%lx-%lx", &start_addr, &end_addr) == 2) {
> +                     strncpy(last_line, start_pos, end_pos - start_pos);
> +                     last_line[end_pos - start_pos] = '\0';
> +                     return true;
> +             }
> +
> +             end_pos = start_pos - 1;
> +     }
> +
> +     return false;
> +}
> +
>  /* Read the last line of the first page and the first line of the second 
> page */
>  static bool read_boundary_lines(FIXTURE_DATA(proc_maps_race) *self,
>                               struct line_content *last_line,
> @@ -207,8 +264,16 @@ static bool 
> read_boundary_lines(FIXTURE_DATA(proc_maps_race) *self,
>       if (!read_two_pages(self))
>               return false;
>  
> -     copy_last_line(&self->page1, last_line->text);
> -     copy_first_line(&self->page2, first_line->text);
> +     if (self->maps_file == MAPS) {
> +             copy_last_line(&self->page1, last_line->text);
> +             copy_first_line(&self->page2, first_line->text);
> +     } else if (self->maps_file == SMAPS) {
> +             if (!copy_last_entry(&self->page1, last_line->text) ||
> +                 !copy_first_entry(&self->page2, first_line->text))
> +                     return false;
> +     } else {
> +             return false;
> +     }
>  
>       return sscanf(last_line->text, "%lx-%lx", &last_line->start_addr,
>                     &last_line->end_addr) == 2 &&
> @@ -464,6 +529,7 @@ FIXTURE_SETUP(proc_maps_race)
>  {
>       const char *verbose = getenv("VERBOSE");
>       const char *duration = getenv("DURATION");
> +     const char *maps_file = getenv("MAPS_FILE");
>       struct vma_modifier_info *mod_info;
>       pthread_mutexattr_t mutex_attr;
>       pthread_condattr_t cond_attr;
> @@ -474,6 +540,18 @@ FIXTURE_SETUP(proc_maps_race)
>  
>       self->page_size = (unsigned long)sysconf(_SC_PAGESIZE);
>       self->verbose = verbose && !strncmp(verbose, "1", 1);
> +     if (maps_file) {
> +             if (!strcmp(maps_file, "maps")) {
> +                     self->maps_file = MAPS;
> +             } else if (!strcmp(maps_file, "smaps")) {
> +                     self->maps_file = SMAPS;
> +             } else {
> +                     ksft_print_msg("Unknown maps file %s\n", maps_file);
> +                     ksft_exit_fail();
> +             }
> +     } else {
> +             self->maps_file = MAPS;
> +     }
>       duration_sec = duration ? atol(duration) : 0;
>       self->duration_sec = duration_sec ? duration_sec : 5UL;
>  
> @@ -540,7 +618,16 @@ FIXTURE_SETUP(proc_maps_race)
>               exit(0);
>       }
>  
> -     sprintf(fname, "/proc/%d/maps", self->pid);
> +     switch (self->maps_file) {
> +     case MAPS:
> +             sprintf(fname, "/proc/%d/maps", self->pid);
> +             break;
> +     case SMAPS:
> +             sprintf(fname, "/proc/%d/smaps", self->pid);
> +             break;
> +     default:
> +             ksft_exit_fail();
> +     }
>       self->maps_fd = open(fname, O_RDONLY);
>       ASSERT_NE(self->maps_fd, -1);
>  
> @@ -675,20 +762,20 @@ TEST_F(proc_maps_race, test_maps_tearing_from_split)
>               last_line_changed = strcmp(new_last_line.text, 
> self->last_line.text) != 0;
>               first_line_changed = strcmp(new_first_line.text, 
> self->first_line.text) != 0;
>               ASSERT_EQ(last_line_changed, first_line_changed);
> -
> -             /* Check if PROCMAP_QUERY ioclt() finds the right VMA */
> -             ASSERT_TRUE(query_addr_at(self->maps_fd, mod_info->addr + 
> self->page_size,
> -                                       &vma_start, &vma_end));
> -             /*
> -              * The vma at the split address can be either the same as
> -              * original one (if read before the split) or the same as the
> -              * first line in the second page (if read after the split).
> -              */
> -             ASSERT_TRUE((vma_start == self->last_line.start_addr &&
> -                          vma_end == self->last_line.end_addr) ||
> -                         (vma_start == split_first_line.start_addr &&
> -                          vma_end == split_first_line.end_addr));
> -
> +             if (self->maps_file == MAPS) {
> +                     /* Check if PROCMAP_QUERY ioclt() finds the right VMA */
> +                     ASSERT_TRUE(query_addr_at(self->maps_fd, mod_info->addr 
> + self->page_size,
> +                                               &vma_start, &vma_end));
> +                     /*
> +                      * The vma at the split address can be either the same 
> as
> +                      * original one (if read before the split) or the same 
> as the
> +                      * first line in the second page (if read after the 
> split).
> +                      */
> +                     ASSERT_TRUE((vma_start == self->last_line.start_addr &&
> +                                  vma_end == self->last_line.end_addr) ||
> +                                 (vma_start == split_first_line.start_addr &&
> +                                  vma_end == split_first_line.end_addr));
> +             }
>               clock_gettime(CLOCK_MONOTONIC_COARSE, &end_ts);
>               end_test_iteration(&end_ts, self->verbose);
>       } while (end_ts.tv_sec - start_ts.tv_sec < self->duration_sec);
> @@ -758,17 +845,18 @@ TEST_F(proc_maps_race, test_maps_tearing_from_resize)
>                                       strcmp(new_first_line.text, 
> restored_first_line.text),
>                                       "Expand result invalid", self));
>               }
> -
> -             /* Check if PROCMAP_QUERY ioclt() finds the right VMA */
> -             ASSERT_TRUE(query_addr_at(self->maps_fd, mod_info->addr, 
> &vma_start, &vma_end));
> -             /*
> -              * The vma should stay at the same address and have either the
> -              * original size of 3 pages or 1 page if read after shrinking.
> -              */
> -             ASSERT_TRUE(vma_start == self->last_line.start_addr &&
> -                         (vma_end - vma_start == self->page_size * 3 ||
> -                          vma_end - vma_start == self->page_size));
> -
> +             if (self->maps_file == MAPS) {
> +                     /* Check if PROCMAP_QUERY ioclt() finds the right VMA */
> +                     ASSERT_TRUE(query_addr_at(self->maps_fd, mod_info->addr,
> +                                               &vma_start, &vma_end));
> +                     /*
> +                      * The vma should stay at the same address and have 
> either the
> +                      * original size of 3 pages or 1 page if read after 
> shrinking.
> +                      */
> +                     ASSERT_TRUE(vma_start == self->last_line.start_addr &&
> +                                 (vma_end - vma_start == self->page_size * 3 
> ||
> +                                  vma_end - vma_start == self->page_size));
> +             }
>               clock_gettime(CLOCK_MONOTONIC_COARSE, &end_ts);
>               end_test_iteration(&end_ts, self->verbose);
>       } while (end_ts.tv_sec - start_ts.tv_sec < self->duration_sec);
> @@ -838,20 +926,20 @@ TEST_F(proc_maps_race, test_maps_tearing_from_remap)
>                                       strcmp(new_first_line.text, 
> restored_first_line.text),
>                                       "Remap restore result invalid", self));
>               }
> -
> -             /* Check if PROCMAP_QUERY ioclt() finds the right VMA */
> -             ASSERT_TRUE(query_addr_at(self->maps_fd, mod_info->addr + 
> self->page_size,
> -                                       &vma_start, &vma_end));
> -             /*
> -              * The vma should either stay at the same address and have the
> -              * original size of 3 pages or we should find the remapped vma
> -              * at the remap destination address with size of 1 page.
> -              */
> -             ASSERT_TRUE((vma_start == self->last_line.start_addr &&
> -                          vma_end - vma_start == self->page_size * 3) ||
> -                         (vma_start == self->last_line.start_addr + 
> self->page_size &&
> -                          vma_end - vma_start == self->page_size));
> -
> +             if (self->maps_file == MAPS) {
> +                     /* Check if PROCMAP_QUERY ioclt() finds the right VMA */
> +                     ASSERT_TRUE(query_addr_at(self->maps_fd, mod_info->addr 
> + self->page_size,
> +                                               &vma_start, &vma_end));
> +                     /*
> +                      * The vma should either stay at the same address and 
> have the
> +                      * original size of 3 pages or we should find the 
> remapped vma
> +                      * at the remap destination address with size of 1 page.
> +                      */
> +                     ASSERT_TRUE((vma_start == self->last_line.start_addr &&
> +                                  vma_end - vma_start == self->page_size * 
> 3) ||
> +                                 (vma_start == self->last_line.start_addr + 
> self->page_size &&
> +                                  vma_end - vma_start == self->page_size));
> +             }
>               clock_gettime(CLOCK_MONOTONIC_COARSE, &end_ts);
>               end_test_iteration(&end_ts, self->verbose);
>       } while (end_ts.tv_sec - start_ts.tv_sec < self->duration_sec);
> -- 
> 2.54.0.545.g6539524ca2-goog
> 

Reply via email to