generic: new case to test getcwd(2)

The following kernel commit introduced a race condition that causes
getcwd(2) to return "/" instead of correct path

232d2d6 dcache: Translating dentry into pathname without taking rename_lock

Jan Stancek hit it once when building ltp and Mikulas Patocka could
hit it by running lvm2 test suite. Please refer to this thread

https://www.mail-archive.com/ltp-list@lists.sourceforge.net/msg17896.html

These commits fixed the bug
ede4ceb prepend_path() needs to reinitialize dentry/vfsmount/mnt on restarts
f650080 __dentry_path() fixes

Cc: Artem Savkov <asavkov@redhat.com>
Cc: Jan Stancek <jstancek@redhat.com>
Signed-off-by: Eryu Guan <eguan@redhat.com>
Reviewed-by: Dave Chinner <dchinner@redhat.com>
Signed-off-by: Dave Chinner <david@fromorbit.com>
This commit is contained in:
Eryu Guan
2014-06-18 09:31:38 +10:00
committed by Dave Chinner
parent c8dc487de7
commit 76d0cfb488
6 changed files with 165 additions and 1 deletions
+1
View File
@@ -83,6 +83,7 @@
/src/t_dir_offset /src/t_dir_offset
/src/t_dir_offset2 /src/t_dir_offset2
/src/t_futimens /src/t_futimens
/src/t_getcwd
/src/t_holes /src/t_holes
/src/t_immutable /src/t_immutable
/src/t_mmap_writev /src/t_mmap_writev
+1 -1
View File
@@ -19,7 +19,7 @@ LINUX_TARGETS = xfsctl bstat t_mtab getdevicesize preallo_rw_pattern_reader \
bulkstat_unlink_test_modified t_dir_offset t_futimens t_immutable \ bulkstat_unlink_test_modified t_dir_offset t_futimens t_immutable \
stale_handle pwrite_mmap_blocked t_dir_offset2 seek_sanity_test \ stale_handle pwrite_mmap_blocked t_dir_offset2 seek_sanity_test \
seek_copy_test t_readdir_1 t_readdir_2 fsync-tester nsexec cloner \ seek_copy_test t_readdir_1 t_readdir_2 fsync-tester nsexec cloner \
renameat2 renameat2 t_getcwd
SUBDIRS = SUBDIRS =
+102
View File
@@ -0,0 +1,102 @@
#include <sys/types.h>
#include <sys/wait.h>
#include <errno.h>
#include <fcntl.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#define TIMEOUT 5
#define BUF_SIZE 256
static sig_atomic_t end;
int test_getcwd(char *init_cwd)
{
int i = 0;
char cur_cwd[BUF_SIZE];
while (1) {
getcwd(cur_cwd, BUF_SIZE);
if (strncmp(init_cwd, cur_cwd, BUF_SIZE)) {
printf("[%u] %s != %s\n", i, init_cwd, cur_cwd);
return 1;
}
if (end)
break;
i++;
}
return 0;
}
void do_rename(char *prefix)
{
int i = 0;
int fd;
char c_name[BUF_SIZE];
char n_name[BUF_SIZE];
strncpy(c_name, prefix, BUF_SIZE);
fd = open(c_name, O_CREAT | O_RDWR, 0644);
if (fd < 0) {
fprintf(stderr, "failed to create file %s: %s\n",
c_name, strerror(errno));
exit(1);
}
close(fd);
while (1) {
i++;
snprintf(n_name, BUF_SIZE, "%s%u", prefix, i);
rename(c_name, n_name);
strncpy(c_name, n_name, BUF_SIZE);
}
}
void sigproc(int sig)
{
end = 1;
}
int main(int argc, char *argv[])
{
char *init_cwd;
pid_t pid;
int status;
int ret = 1;
if (argc != 2) {
printf("Usage: %s <dir>\n", argv[0]);
exit(1);
}
init_cwd = argv[1];
ret = chdir(init_cwd);
if (ret < 0) {
perror("chdir failed");
exit(1);
}
if (signal(SIGALRM, sigproc) == SIG_ERR) {
perror("signal failed");
exit(1);
}
alarm(TIMEOUT);
pid = fork();
if (pid < 0) {
perror("fork failed");
exit(1);
} else if (pid == 0) {
do_rename("t_getcwd_testfile");
} else {
ret = test_getcwd(init_cwd);
kill(pid, SIGTERM);
waitpid(pid, &status, 0);
}
exit(ret);
}
+58
View File
@@ -0,0 +1,58 @@
#! /bin/bash
# FS QA Test No. generic/028
#
# The following commit introduced a race condition that causes getcwd(2)
# to return "/" instead of correct path
#
# 232d2d6 dcache: Translating dentry into pathname without taking rename_lock
#
# These commits fixed the bug
# ede4ceb prepend_path() needs to reinitialize dentry/vfsmount/mnt on restarts
# f650080 __dentry_path() fixes
#
#-----------------------------------------------------------------------
# Copyright (c) 2014 Red Hat Inc. All Rights Reserved.
#
# 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.
#
# This program is distributed in the hope that it would 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, write the Free Software Foundation,
# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#-----------------------------------------------------------------------
#
seq=`basename $0`
seqres=$RESULT_DIR/$seq
echo "QA output created by $seq"
here=`pwd`
tmp=/tmp/$$
status=1 # failure is the default!
trap "_cleanup; exit \$status" 0 1 2 3 15
_cleanup()
{
cd /
rm -f $tmp.*
}
# get standard environment, filters and checks
. ./common/rc
. ./common/filter
# real QA test starts here
_supported_fs generic
_supported_os Linux
echo "Silence is golden"
$here/src/t_getcwd $TEST_DIR
status=$?
exit
+2
View File
@@ -0,0 +1,2 @@
QA output created by 028
Silence is golden
+1
View File
@@ -30,6 +30,7 @@
025 auto quick 025 auto quick
026 acl quick auto 026 acl quick auto
027 auto enospc 027 auto enospc
028 auto quick
053 acl repair auto quick 053 acl repair auto quick
062 attr udf auto quick 062 attr udf auto quick
068 other auto freeze dangerous stress 068 other auto freeze dangerous stress