xref: /freebsd/tools/test/stress2/misc/f_offset.sh (revision c1d255d3)
1#!/bin/sh
2
3#
4# Copyright (c) 2012 Peter Holm <pho@FreeBSD.org>
5# All rights reserved.
6#
7# Redistribution and use in source and binary forms, with or without
8# modification, are permitted provided that the following conditions
9# are met:
10# 1. Redistributions of source code must retain the above copyright
11#    notice, this list of conditions and the following disclaimer.
12# 2. Redistributions in binary form must reproduce the above copyright
13#    notice, this list of conditions and the following disclaimer in the
14#    documentation and/or other materials provided with the distribution.
15#
16# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19# ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26# SUCH DAMAGE.
27#
28
29# Problem seen with atomic assignment of f_offset. Fixed in r238029.
30
31# Test scenario by kib@
32
33. ../default.cfg
34
35here=`pwd`
36cd /tmp
37sed '1,/^EOF/d' < $here/$0 > f_offset.c
38mycc -o f_offset -Wall -Wextra -O2 f_offset.c -lpthread
39rm -f f_offset.c
40
41/tmp/f_offset
42
43rm -f /tmp/f_offset
44exit 0
45EOF
46/*
47   Description by kib:
48To really exercise the race conditions, all the following items must
49be fulfilled simultaneously:
501. you use 32bit host, i.e. i386
512. you operate on the file offsets larger than 4GB (but see below)
523. there are several threads or processes that operate on the same
53   file descriptor simultaneously.
54
55Please note that the normal fork(2) causes file descriptor table
56copy, so only rfork(2) call with RFFDG flag unset causes sharing. Or,
57multi-threading can be used.
58 */
59
60#include <err.h>
61#include <fcntl.h>
62#include <pthread.h>
63#include <stdio.h>
64#include <stdlib.h>
65#include <string.h>
66#include <sys/types.h>
67#include <unistd.h>
68
69int errors, fd;
70char file[128];
71
72#define START 0x100000000ULL
73#define N 1000000
74
75void *
76t1(void *arg __unused)
77{
78	int i;
79	off_t offset;
80
81	offset = START + 2;
82
83	for (i = 0; i < N; i++) {
84		if (lseek(fd, offset, SEEK_SET) == -1)
85			err(1, "lseek error");
86	}
87
88	return (0);
89}
90
91void *
92t2(void *arg __unused)
93{
94	int i;
95	off_t offset;
96
97	offset = 1;
98
99	for (i = 0; i < N; i++) {
100		if (lseek(fd, offset, SEEK_SET) == -1)
101			err(1, "lseek error");
102	}
103	return (0);
104}
105void *
106t3(void *arg __unused)
107{
108	int i;
109	off_t offset;
110
111	offset = 1;
112
113	for (i = 0; i < N; i++) {
114		if ((offset = lseek(fd, 0, SEEK_CUR)) == -1)
115			err(1, "lseek error");
116		if (offset != 1 && offset != START + 2)
117			fprintf(stderr, "FAIL #%d offset = %10jd (0x%09jx)\n",
118					errors++, offset, offset);
119	}
120
121	return (0);
122}
123
124int
125main(void)
126{
127	pthread_t threads[3];
128	int r;
129	int i;
130	off_t offset;
131
132	snprintf(file, sizeof(file), "file.%06d", getpid());
133	if ((fd = open(file, O_RDWR | O_CREAT | O_TRUNC, 0600)) < 0)
134		err(1, "%s", file);
135
136	offset = 1;
137	if (lseek(fd, offset, SEEK_SET) == -1)
138		err(1, "lseek error");
139
140	for (i = 0; i < 20 && errors < 10; i++) {
141		if ((r = pthread_create(&threads[0], NULL, t1, 0)) != 0)
142			errc(1, r, "pthread_create()");
143		if ((r = pthread_create(&threads[1], NULL, t2, 0)) != 0)
144			errc(1, r, "pthread_create()");
145		if ((r = pthread_create(&threads[2], NULL, t3, 0)) != 0)
146			errc(1, r, "pthread_create()");
147
148		if ((r = pthread_join(threads[0], NULL)) != 0)
149			errc(1, r, "pthread_join(%d)", 0);
150		if ((r = pthread_join(threads[1], NULL)) != 0)
151			errc(1, r, "pthread_join(%d)", 1);
152		if ((r = pthread_join(threads[2], NULL)) != 0)
153			errc(1, r, "pthread_join(%d)", 2);
154	}
155	close(fd);
156	if (unlink(file) == -1)
157		err(3, "unlink(%s)", file);
158
159	return (0);
160}
161