1*49cdfc7eSAndroid Build Coastguard Worker // SPDX-License-Identifier: GPL-2.0-or-later
2*49cdfc7eSAndroid Build Coastguard Worker /*
3*49cdfc7eSAndroid Build Coastguard Worker * Copyright (c) International Business Machines Corp., 2002
4*49cdfc7eSAndroid Build Coastguard Worker * Copyright (c) 2015 Cyril Hrubis <[email protected]>
5*49cdfc7eSAndroid Build Coastguard Worker * Copyright (c) 2019 FUJITSU LIMITED. All rights reserved.
6*49cdfc7eSAndroid Build Coastguard Worker *
7*49cdfc7eSAndroid Build Coastguard Worker * Robbie Williamson <[email protected]>
8*49cdfc7eSAndroid Build Coastguard Worker * Roy Lee <[email protected]>
9*49cdfc7eSAndroid Build Coastguard Worker */
10*49cdfc7eSAndroid Build Coastguard Worker /*
11*49cdfc7eSAndroid Build Coastguard Worker * Test Description:
12*49cdfc7eSAndroid Build Coastguard Worker *
13*49cdfc7eSAndroid Build Coastguard Worker * Tests truncate and mandatory record locking.
14*49cdfc7eSAndroid Build Coastguard Worker *
15*49cdfc7eSAndroid Build Coastguard Worker * Parent creates a file, child locks a region and sleeps.
16*49cdfc7eSAndroid Build Coastguard Worker *
17*49cdfc7eSAndroid Build Coastguard Worker * Parent checks that ftruncate before the locked region and inside the region
18*49cdfc7eSAndroid Build Coastguard Worker * fails while ftruncate after the region succeds.
19*49cdfc7eSAndroid Build Coastguard Worker *
20*49cdfc7eSAndroid Build Coastguard Worker * Parent wakes up child, child exits, lock is unlocked.
21*49cdfc7eSAndroid Build Coastguard Worker *
22*49cdfc7eSAndroid Build Coastguard Worker * Parent checks that ftruncate now works in all cases.
23*49cdfc7eSAndroid Build Coastguard Worker *
24*49cdfc7eSAndroid Build Coastguard Worker */
25*49cdfc7eSAndroid Build Coastguard Worker
26*49cdfc7eSAndroid Build Coastguard Worker #include <stdio.h>
27*49cdfc7eSAndroid Build Coastguard Worker #include <errno.h>
28*49cdfc7eSAndroid Build Coastguard Worker #include <sys/types.h>
29*49cdfc7eSAndroid Build Coastguard Worker #include <sys/stat.h>
30*49cdfc7eSAndroid Build Coastguard Worker #include <sys/mount.h>
31*49cdfc7eSAndroid Build Coastguard Worker #include <unistd.h>
32*49cdfc7eSAndroid Build Coastguard Worker #include <stdlib.h>
33*49cdfc7eSAndroid Build Coastguard Worker #include <sys/statvfs.h>
34*49cdfc7eSAndroid Build Coastguard Worker
35*49cdfc7eSAndroid Build Coastguard Worker #include "tst_test.h"
36*49cdfc7eSAndroid Build Coastguard Worker
37*49cdfc7eSAndroid Build Coastguard Worker #define RECLEN 100
38*49cdfc7eSAndroid Build Coastguard Worker #define MNTPOINT "mntpoint"
39*49cdfc7eSAndroid Build Coastguard Worker #define TESTFILE MNTPOINT"/testfile"
40*49cdfc7eSAndroid Build Coastguard Worker
41*49cdfc7eSAndroid Build Coastguard Worker static int len = 8 * 1024;
42*49cdfc7eSAndroid Build Coastguard Worker static int recstart, reclen;
43*49cdfc7eSAndroid Build Coastguard Worker
ftruncate_expect_fail(int fd,off_t offset,const char * msg)44*49cdfc7eSAndroid Build Coastguard Worker static void ftruncate_expect_fail(int fd, off_t offset, const char *msg)
45*49cdfc7eSAndroid Build Coastguard Worker {
46*49cdfc7eSAndroid Build Coastguard Worker TEST(ftruncate(fd, offset));
47*49cdfc7eSAndroid Build Coastguard Worker
48*49cdfc7eSAndroid Build Coastguard Worker if (TST_RET == 0) {
49*49cdfc7eSAndroid Build Coastguard Worker tst_res(TFAIL, "ftruncate() %s succeeded unexpectedly", msg);
50*49cdfc7eSAndroid Build Coastguard Worker return;
51*49cdfc7eSAndroid Build Coastguard Worker }
52*49cdfc7eSAndroid Build Coastguard Worker
53*49cdfc7eSAndroid Build Coastguard Worker if (TST_ERR != EAGAIN) {
54*49cdfc7eSAndroid Build Coastguard Worker tst_res(TFAIL | TTERRNO,
55*49cdfc7eSAndroid Build Coastguard Worker "ftruncate() %s failed unexpectedly, expected EAGAIN",
56*49cdfc7eSAndroid Build Coastguard Worker msg);
57*49cdfc7eSAndroid Build Coastguard Worker return;
58*49cdfc7eSAndroid Build Coastguard Worker }
59*49cdfc7eSAndroid Build Coastguard Worker
60*49cdfc7eSAndroid Build Coastguard Worker tst_res(TPASS, "ftruncate() %s failed with EAGAIN", msg);
61*49cdfc7eSAndroid Build Coastguard Worker }
62*49cdfc7eSAndroid Build Coastguard Worker
ftruncate_expect_success(int fd,off_t offset,const char * msg)63*49cdfc7eSAndroid Build Coastguard Worker static void ftruncate_expect_success(int fd, off_t offset, const char *msg)
64*49cdfc7eSAndroid Build Coastguard Worker {
65*49cdfc7eSAndroid Build Coastguard Worker struct stat sb;
66*49cdfc7eSAndroid Build Coastguard Worker
67*49cdfc7eSAndroid Build Coastguard Worker TEST(ftruncate(fd, offset));
68*49cdfc7eSAndroid Build Coastguard Worker
69*49cdfc7eSAndroid Build Coastguard Worker if (TST_RET != 0) {
70*49cdfc7eSAndroid Build Coastguard Worker tst_res(TFAIL | TTERRNO,
71*49cdfc7eSAndroid Build Coastguard Worker "ftruncate() %s failed unexpectedly", msg);
72*49cdfc7eSAndroid Build Coastguard Worker return;
73*49cdfc7eSAndroid Build Coastguard Worker }
74*49cdfc7eSAndroid Build Coastguard Worker
75*49cdfc7eSAndroid Build Coastguard Worker SAFE_FSTAT(fd, &sb);
76*49cdfc7eSAndroid Build Coastguard Worker
77*49cdfc7eSAndroid Build Coastguard Worker if (sb.st_size != offset) {
78*49cdfc7eSAndroid Build Coastguard Worker tst_res(TFAIL,
79*49cdfc7eSAndroid Build Coastguard Worker "ftruncate() to %li bytes succeded but fstat() reports size %li",
80*49cdfc7eSAndroid Build Coastguard Worker (long)offset, (long)sb.st_size);
81*49cdfc7eSAndroid Build Coastguard Worker return;
82*49cdfc7eSAndroid Build Coastguard Worker }
83*49cdfc7eSAndroid Build Coastguard Worker
84*49cdfc7eSAndroid Build Coastguard Worker tst_res(TPASS, "ftruncate() %s succeded", msg);
85*49cdfc7eSAndroid Build Coastguard Worker }
86*49cdfc7eSAndroid Build Coastguard Worker
doparent(void)87*49cdfc7eSAndroid Build Coastguard Worker static void doparent(void)
88*49cdfc7eSAndroid Build Coastguard Worker {
89*49cdfc7eSAndroid Build Coastguard Worker int fd;
90*49cdfc7eSAndroid Build Coastguard Worker
91*49cdfc7eSAndroid Build Coastguard Worker TST_CHECKPOINT_WAIT(0);
92*49cdfc7eSAndroid Build Coastguard Worker
93*49cdfc7eSAndroid Build Coastguard Worker fd = SAFE_OPEN(TESTFILE, O_RDWR | O_NONBLOCK);
94*49cdfc7eSAndroid Build Coastguard Worker
95*49cdfc7eSAndroid Build Coastguard Worker ftruncate_expect_fail(fd, RECLEN, "offset before lock");
96*49cdfc7eSAndroid Build Coastguard Worker ftruncate_expect_fail(fd, recstart + RECLEN/2, "offset in lock");
97*49cdfc7eSAndroid Build Coastguard Worker ftruncate_expect_success(fd, recstart + RECLEN, "offset after lock");
98*49cdfc7eSAndroid Build Coastguard Worker
99*49cdfc7eSAndroid Build Coastguard Worker TST_CHECKPOINT_WAKE(0);
100*49cdfc7eSAndroid Build Coastguard Worker SAFE_WAIT(NULL);
101*49cdfc7eSAndroid Build Coastguard Worker
102*49cdfc7eSAndroid Build Coastguard Worker ftruncate_expect_success(fd, recstart + RECLEN/2, "offset in lock");
103*49cdfc7eSAndroid Build Coastguard Worker ftruncate_expect_success(fd, recstart, "offset before lock");
104*49cdfc7eSAndroid Build Coastguard Worker ftruncate_expect_success(fd, recstart + RECLEN, "offset after lock");
105*49cdfc7eSAndroid Build Coastguard Worker
106*49cdfc7eSAndroid Build Coastguard Worker SAFE_CLOSE(fd);
107*49cdfc7eSAndroid Build Coastguard Worker }
108*49cdfc7eSAndroid Build Coastguard Worker
dochild(void)109*49cdfc7eSAndroid Build Coastguard Worker void dochild(void)
110*49cdfc7eSAndroid Build Coastguard Worker {
111*49cdfc7eSAndroid Build Coastguard Worker int fd;
112*49cdfc7eSAndroid Build Coastguard Worker struct flock flocks;
113*49cdfc7eSAndroid Build Coastguard Worker
114*49cdfc7eSAndroid Build Coastguard Worker fd = SAFE_OPEN(TESTFILE, O_RDWR);
115*49cdfc7eSAndroid Build Coastguard Worker
116*49cdfc7eSAndroid Build Coastguard Worker tst_res(TINFO, "Child locks file");
117*49cdfc7eSAndroid Build Coastguard Worker
118*49cdfc7eSAndroid Build Coastguard Worker flocks.l_type = F_WRLCK;
119*49cdfc7eSAndroid Build Coastguard Worker flocks.l_whence = SEEK_CUR;
120*49cdfc7eSAndroid Build Coastguard Worker flocks.l_start = recstart;
121*49cdfc7eSAndroid Build Coastguard Worker flocks.l_len = reclen;
122*49cdfc7eSAndroid Build Coastguard Worker
123*49cdfc7eSAndroid Build Coastguard Worker SAFE_FCNTL(fd, F_SETLKW, &flocks);
124*49cdfc7eSAndroid Build Coastguard Worker
125*49cdfc7eSAndroid Build Coastguard Worker TST_CHECKPOINT_WAKE_AND_WAIT(0);
126*49cdfc7eSAndroid Build Coastguard Worker
127*49cdfc7eSAndroid Build Coastguard Worker tst_res(TINFO, "Child unlocks file");
128*49cdfc7eSAndroid Build Coastguard Worker
129*49cdfc7eSAndroid Build Coastguard Worker exit(0);
130*49cdfc7eSAndroid Build Coastguard Worker }
131*49cdfc7eSAndroid Build Coastguard Worker
verify_ftruncate(void)132*49cdfc7eSAndroid Build Coastguard Worker static void verify_ftruncate(void)
133*49cdfc7eSAndroid Build Coastguard Worker {
134*49cdfc7eSAndroid Build Coastguard Worker int pid;
135*49cdfc7eSAndroid Build Coastguard Worker
136*49cdfc7eSAndroid Build Coastguard Worker if (tst_fill_file(TESTFILE, 0, 1024, 8))
137*49cdfc7eSAndroid Build Coastguard Worker tst_brk(TBROK, "Failed to create test file");
138*49cdfc7eSAndroid Build Coastguard Worker
139*49cdfc7eSAndroid Build Coastguard Worker SAFE_CHMOD(TESTFILE, 02666);
140*49cdfc7eSAndroid Build Coastguard Worker
141*49cdfc7eSAndroid Build Coastguard Worker reclen = RECLEN;
142*49cdfc7eSAndroid Build Coastguard Worker recstart = RECLEN + rand() % (len - 3 * RECLEN);
143*49cdfc7eSAndroid Build Coastguard Worker
144*49cdfc7eSAndroid Build Coastguard Worker pid = SAFE_FORK();
145*49cdfc7eSAndroid Build Coastguard Worker
146*49cdfc7eSAndroid Build Coastguard Worker if (pid == 0)
147*49cdfc7eSAndroid Build Coastguard Worker dochild();
148*49cdfc7eSAndroid Build Coastguard Worker
149*49cdfc7eSAndroid Build Coastguard Worker doparent();
150*49cdfc7eSAndroid Build Coastguard Worker }
151*49cdfc7eSAndroid Build Coastguard Worker
setup(void)152*49cdfc7eSAndroid Build Coastguard Worker static void setup(void)
153*49cdfc7eSAndroid Build Coastguard Worker {
154*49cdfc7eSAndroid Build Coastguard Worker /*
155*49cdfc7eSAndroid Build Coastguard Worker * Kernel returns EPERM when CONFIG_MANDATORY_FILE_LOCKING is not
156*49cdfc7eSAndroid Build Coastguard Worker * supported - to avoid false negatives, mount the fs first without
157*49cdfc7eSAndroid Build Coastguard Worker * flags and then remount it as MS_MANDLOCK
158*49cdfc7eSAndroid Build Coastguard Worker */
159*49cdfc7eSAndroid Build Coastguard Worker if (mount(NULL, MNTPOINT, NULL, MS_REMOUNT|MS_MANDLOCK, NULL) == -1) {
160*49cdfc7eSAndroid Build Coastguard Worker if (errno == EPERM) {
161*49cdfc7eSAndroid Build Coastguard Worker tst_brk(TCONF,
162*49cdfc7eSAndroid Build Coastguard Worker "Mandatory lock not supported by this system");
163*49cdfc7eSAndroid Build Coastguard Worker } else {
164*49cdfc7eSAndroid Build Coastguard Worker tst_brk(TBROK | TTERRNO,
165*49cdfc7eSAndroid Build Coastguard Worker "Remount with MS_MANDLOCK failed");
166*49cdfc7eSAndroid Build Coastguard Worker }
167*49cdfc7eSAndroid Build Coastguard Worker }
168*49cdfc7eSAndroid Build Coastguard Worker }
169*49cdfc7eSAndroid Build Coastguard Worker
170*49cdfc7eSAndroid Build Coastguard Worker static struct tst_test test = {
171*49cdfc7eSAndroid Build Coastguard Worker .needs_kconfigs = (const char *[]) {
172*49cdfc7eSAndroid Build Coastguard Worker "CONFIG_MANDATORY_FILE_LOCKING=y",
173*49cdfc7eSAndroid Build Coastguard Worker NULL
174*49cdfc7eSAndroid Build Coastguard Worker },
175*49cdfc7eSAndroid Build Coastguard Worker .test_all = verify_ftruncate,
176*49cdfc7eSAndroid Build Coastguard Worker .setup = setup,
177*49cdfc7eSAndroid Build Coastguard Worker .needs_checkpoints = 1,
178*49cdfc7eSAndroid Build Coastguard Worker .forks_child = 1,
179*49cdfc7eSAndroid Build Coastguard Worker .mount_device = 1,
180*49cdfc7eSAndroid Build Coastguard Worker .needs_root = 1,
181*49cdfc7eSAndroid Build Coastguard Worker .mntpoint = MNTPOINT,
182*49cdfc7eSAndroid Build Coastguard Worker };
183