blob: 9c4e9112b30095a0f18a0c717160bcf0af1ba7fe [file] [log] [blame]
/*
* Copyright (c) 2017 Fujitsu Ltd.
* Ported: Guangwen Feng <fenggw-fnst@cn.fujitsu.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
/*
* This is a regression test about the race in autogroup, this test
* can crash the buggy kernel, and the bug has been fixed in:
*
* commit 18f649ef344127ef6de23a5a4272dbe2fdb73dde
* Author: Oleg Nesterov <oleg@redhat.com>
* Date: Mon Nov 14 19:46:09 2016 +0100
*
* sched/autogroup: Fix autogroup_move_group() to never skip sched_move_task()
*/
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include "tst_test.h"
#define LOOPS 1000
#define PATH_AUTOGROUP "/proc/sys/kernel/sched_autogroup_enabled"
static int orig_autogroup = -1;
static void do_test(void)
{
int i;
if (!SAFE_FORK()) {
SAFE_FILE_PRINTF(PATH_AUTOGROUP, "%d", 1);
SAFE_SETSID();
if (SAFE_FORK())
pause();
SAFE_KILL(getppid(), SIGKILL);
usleep(1000);
// The child has gone, the grandchild runs with kref == 1
SAFE_FILE_PRINTF(PATH_AUTOGROUP, "%d", 0);
SAFE_SETSID();
// runs with the freed ag/tg
for (i = 0; i < LOOPS; i++)
usleep(10);
TST_CHECKPOINT_WAKE(0);
exit(0);
}
SAFE_WAIT(NULL); // destroy the child's ag/tg
TST_CHECKPOINT_WAIT(0);
tst_res(TPASS, "Bug not reproduced");
}
static void setup(void)
{
if (access(PATH_AUTOGROUP, F_OK))
tst_brk(TCONF, "autogroup not supported");
SAFE_FILE_SCANF(PATH_AUTOGROUP, "%d", &orig_autogroup);
}
static void cleanup(void)
{
if (orig_autogroup != -1)
SAFE_FILE_PRINTF(PATH_AUTOGROUP, "%d", orig_autogroup);
}
static struct tst_test test = {
.forks_child = 1,
.needs_root = 1,
.needs_checkpoints = 1,
.setup = setup,
.cleanup = cleanup,
.test_all = do_test,
};