generic: add OFD lock tests

Test OFD locks. Use fcntl F_OFD_SETLK/F_OFD_GETLK, to verify we are
being given correct advices through getlk by kernel.

The basic idea is one setlk routine setting locks via fcntl *_SETLK,
followed by operations like clone, dup then close fd; another
routine getlk getting locks via fcntl *_GETLK.

Firstly in setlk routine process P0, place a lock L0 on an opened
testfile, then do clone or dup and close relative fd.

In getlk process P2, do fcntl *_GETLK with lock L1 after get
notified by setlk routine.

In the end, getlk routine check the returned struct flock.l_type to
see if the lock mechanism works fine.

Test combainations of:
- shared or exclusive lock
- these locks are conflicting or not
- one OFD lock and one POSIX lock
- that open testfile RDONLY or RDWR
- clone with CLONE_FILES or not
- dup and close newfd

[eguan: made some minor non-functional changes]

Signed-off-by: Xiong Zhou <xzhou@redhat.com>
Reviewed-by: Eryu Guan <eguan@redhat.com>
Signed-off-by: Eryu Guan <eguan@redhat.com>
This commit is contained in:
Xiong Zhou
2018-02-13 22:10:26 +08:00
committed by Eryu Guan
parent 03cc97346b
commit 4a6d40ad68
7 changed files with 800 additions and 1 deletions
+1
View File
@@ -128,6 +128,7 @@
/src/t_mmap_write_ro
/src/t_mmap_writev
/src/t_mtab
/src/t_ofd_locks
/src/t_readdir_1
/src/t_readdir_2
/src/t_rename_overwrite
+11
View File
@@ -3308,6 +3308,17 @@ _require_test_fcntl_advisory_locks()
_notrun "Require fcntl advisory locks support"
}
_require_ofd_locks()
{
# Give a test run by getlk wrlck on testfile.
# If the running kernel does not support OFD locks,
# EINVAL will be returned.
_require_test_program "t_ofd_locks"
touch $TEST_DIR/ofd_testfile
src/t_ofd_locks -t $TEST_DIR/ofd_testfile > /dev/null 2>&1
[ $? -eq 22 ] && _notrun "Require OFD locks support"
}
_require_test_lsattr()
{
testio=$(lsattr -d $TEST_DIR 2>&1)
+2 -1
View File
@@ -14,7 +14,8 @@ TARGETS = dirstress fill fill2 getpagesize holes lstat64 \
t_mmap_writev t_truncate_cmtime dirhash_collide t_rename_overwrite \
holetest t_truncate_self t_mmap_dio af_unix t_mmap_stale_pmd \
t_mmap_cow_race t_mmap_fallocate fsync-err t_mmap_write_ro \
t_ext4_dax_journal_corruption t_ext4_dax_inline_corruption
t_ext4_dax_journal_corruption t_ext4_dax_inline_corruption \
t_ofd_locks
LINUX_TARGETS = xfsctl bstat t_mtab getdevicesize preallo_rw_pattern_reader \
preallo_rw_pattern_writer ftrunc trunc fs_perms testx looptest \
+444
View File
@@ -0,0 +1,444 @@
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <sched.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/ipc.h>
#include <sys/sem.h>
/*
* In distributions that do not have these macros ready in glibc-headers,
* compilation fails. Adding them here to avoid build errors, relevant tests
* would fail at the helper which requires OFD locks support and notrun if the
* kernel does not support OFD locks. If the kernel does support OFD locks, we
* are good to go.
*/
#ifndef F_OFD_GETLK
#define F_OFD_GETLK 36
#endif
#ifndef F_OFD_SETLK
#define F_OFD_SETLK 37
#endif
#ifndef F_OFD_SETLKW
#define F_OFD_SETLKW 38
#endif
/*
* Usually we run getlk routine after running setlk routine
* in background. However, getlk could be executed before setlk
* sometimes, which is invalid for our tests. So we use semaphore
* to synchronize between getlk and setlk.
*
* setlk routine: * getlk routine:
* *
* start * start
* | * |
* open file * open file
* | * |
* init sem * |
* | * |
* wait init sem done * wait init sem done
* | * |
* setlk * |
* | * |
* |------------clone()--------| * |
* | | * |
* |(parent) (child)| * |
* | | * |
* | close fd * |
* | | * |
* | set sem0=0 * wait sem0==0
* | | * |
* | | * getlk
* | | * |
* wait sem1==0 | * set sem1=0
* | | * |
* wait child | * |
* | | * check result
* | | * |
* exit exit * exit
*/
static int fd;
static int semid;
/* This is required by semctl to set semaphore value */
union semun {
int val; /* Value for SETVAL */
struct semid_ds *buf; /* Buffer for IPC_STAT, IPC_SET */
unsigned short *array; /* Array for GETALL, SETALL */
struct seminfo *__buf; /* Buffer for IPC_INFO
(Linux-specific) */
};
static void err_exit(char *op, int errn)
{
fprintf(stderr, "%s: %s\n", op, strerror(errn));
if (fd > 0)
close(fd);
if (semid > 0 && semctl(semid, 2, IPC_RMID) == -1)
perror("exit rmid");
exit(errn);
}
/*
* Flags that used to specify operation details.
* They can be specified via command line options.
*
* option: -P
* posix : 1 <--> test posix lock
* 0 <--> test OFD lock (default)
*
* option: -s/-g
* lock_cmd : 1 <--> setlk (default)
* 0 <--> getlk
*
* option: -r/-w
* lock_rw : 1 <--> set/get wrlck (default)
* 0 <--> set/get rdlck
*
* option: -o num
* lock_start : l_start to getlk
*
* option: -F
* clone_fs : clone with CLONE_FILES
*
* option: -d
* use_dup : dup and close to setup condition in setlk
*
* option: -R/-W
* open_rw : 1 <--> open file RDWR (default)
* 0 <--> open file RDONLY
*
* This option is for _require_ofd_locks helper, just do
* fcntl setlk then return errno.
* option: -t
* testrun : 1 <--> this is a testrun, return after setlk
* 0 <--> this is not a testrun, run as usual
*/
static void usage(char *arg0)
{
printf("Usage: %s [-sgrwo:l:RWPtFd] filename\n", arg0);
printf("\t-s/-g : to setlk or to getlk\n");
printf("\t-P : POSIX locks\n");
printf("\t-F : clone with CLONE_FILES in setlk to setup test condition\n");
printf("\t-d : dup and close in setlk\n");
printf("\twithout both -F/d, use clone without CLONE_FILES\n");
printf("\t-r/-w : set/get rdlck/wrlck\n");
printf("\t-o num : offset start to lock, default 0\n");
printf("\t-l num : lock length, default 10\n");
printf("\t-R/-W : open file RDONLY/RDWR\n\n");
printf("\tUsually we run a setlk routine in background and then\n");
printf("\trun a getlk routine to check. They must be paired, or\n");
printf("\ttest will hang.\n\n");
exit(0);
}
#define STACK_SIZE (1024 * 1024)
static char child_stack[STACK_SIZE] __attribute__((aligned));
static int child_fn(void* p)
{
union semun semu;
int cfd = *(int *)p;
/* close relative fd */
if (cfd > 0 && close(cfd) == -1)
perror("close in child");
/* set sem0 = 0 (setlk and close fd done) */
semu.val = 0;
if (semctl(semid, 0, SETVAL, semu) == -1)
err_exit("set sem0 0", errno);
return 0;
}
int main(int argc, char **argv)
{
int posix = 0;
int lock_cmd = 1;
int lock_rw = 1;
int lock_start = 0;
int lock_l = 10;
int open_rw = 1;
int clone_fs = 0;
int use_dup = 0;
int testrun = 0;
int setlk_macro = F_OFD_SETLKW;
int getlk_macro = F_OFD_GETLK;
struct timespec ts;
key_t semkey;
unsigned short vals[2];
union semun semu;
struct semid_ds sem_ds;
struct sembuf sop;
int opt, ret, retry;
while((opt = getopt(argc, argv, "sgrwo:l:PRWtFd")) != -1) {
switch(opt) {
case 's':
lock_cmd = 1;
break;
case 'g':
lock_cmd = 0;
break;
case 'r':
lock_rw = 0;
break;
case 'w':
lock_rw = 1;
break;
case 'o':
lock_start = atoi(optarg);
break;
case 'l':
lock_l = atoi(optarg);
break;
case 'P':
posix = 1;
break;
case 'R':
open_rw = 0;
break;
case 'W':
open_rw = 1;
break;
case 't':
testrun = 1;
break;
case 'F':
clone_fs = 1;
break;
case 'd':
use_dup = 1;
break;
default:
usage(argv[0]);
return -1;
}
}
if (optind >= argc) {
usage(argv[0]);
return -1;
}
struct flock flk = {
.l_whence = SEEK_SET,
.l_start = lock_start,
.l_len = lock_l,
.l_type = F_RDLCK,
};
if (posix == 0) {
/* OFD lock requires l_pid to be zero */
flk.l_pid = 0;
setlk_macro = F_OFD_SETLKW;
getlk_macro = F_OFD_GETLK;
} else {
setlk_macro = F_SETLKW;
getlk_macro = F_GETLK;
}
if (lock_rw == 1)
flk.l_type = F_WRLCK;
else
flk.l_type = F_RDLCK;
if (open_rw == 0)
fd = open(argv[optind], O_RDONLY);
else
fd = open(argv[optind], O_RDWR);
if (fd == -1)
err_exit("open", errno);
/*
* In a testun, we do a fcntl getlk call and exit
* immediately no matter it succeeds or not.
*/
if (testrun == 1) {
fcntl(fd, F_OFD_GETLK, &flk);
err_exit("test_ofd_getlk", errno);
}
if((semkey = ftok(argv[optind], 255)) == -1)
err_exit("ftok", errno);
/* setlk, and always init the semaphore at setlk time */
if (lock_cmd == 1) {
/*
* Init the semaphore, with a key related to the testfile.
* getlk routine will wait untill this sem has been created and
* iniialized.
*
* We must make sure the semaphore set is newly created, rather
* then the one left from last run. In which case getlk will
* exit immediately and left setlk routine waiting forever.
* Also because newly created semaphore has zero sem_otime,
* which is used here to sync with getlk routine.
*/
retry = 0;
do {
semid = semget(semkey, 2, IPC_CREAT|IPC_EXCL);
if (semid < 0 && errno == EEXIST) {
/* remove sem set after one round of test */
if (semctl(semid, 2, IPC_RMID, semu) == -1)
err_exit("rmid 0", errno);
retry++;
} else if (semid < 0)
err_exit("semget", errno);
else
retry = 10;
} while (retry < 5);
/* We can't create a new semaphore set in 5 tries */
if (retry == 5)
err_exit("semget", errno);
/* Init both new sem to 1 */
vals[0] = 1;
vals[1] = 1;
semu.array = vals;
if (semctl(semid, 2, SETALL, semu) == -1)
err_exit("init sem", errno);
/* Inc both new sem to 2 */
sop.sem_num = 0;
sop.sem_op = 1;
sop.sem_flg = 0;
ts.tv_sec = 15;
ts.tv_nsec = 0;
if (semtimedop(semid, &sop, 1, &ts) == -1)
err_exit("inc sem0 2", errno);
sop.sem_num = 1;
sop.sem_op = 1;
sop.sem_flg = 0;
ts.tv_sec = 15;
ts.tv_nsec = 0;
if (semtimedop(semid, &sop, 1, &ts) == -1)
err_exit("inc sem1 2", errno);
/*
* Wait initialization complete. semctl(2) only update
* sem_ctime, semop(2) will update sem_otime.
*/
ret = -1;
do {
memset(&sem_ds, 0, sizeof(sem_ds));
semu.buf = &sem_ds;
ret = semctl(semid, 0, IPC_STAT, semu);
} while (!(ret == 0 && sem_ds.sem_otime != 0));
/* place the lock */
if (fcntl(fd, setlk_macro, &flk) < 0)
err_exit("setlkw", errno);
if (use_dup == 1) {
/* dup fd and close the newfd */
int dfd = dup(fd);
if (dfd == -1)
err_exit("dup", errno);
close(dfd);
/* set sem0 = 0 (setlk and close fd done) */
semu.val = 0;
if (semctl(semid, 0, SETVAL, semu) == -1)
err_exit("set sem0 0", errno);
} else {
/*
* clone a child to close the fd then tell getlk to go;
* in parent we keep holding the lock till getlk done.
*/
pid_t child_pid = 0;
if (clone_fs)
child_pid = clone(child_fn, child_stack+STACK_SIZE,
CLONE_FILES|CLONE_SYSVSEM|SIGCHLD, &fd);
else
child_pid = clone(child_fn, child_stack+STACK_SIZE,
CLONE_SYSVSEM|SIGCHLD, &fd);
if (child_pid == -1)
err_exit("clone", errno);
/* wait child done */
waitpid(child_pid, NULL, 0);
}
/* "hold" lock and wait sem1 == 0 (getlk done) */
sop.sem_num = 1;
sop.sem_op = 0;
sop.sem_flg = 0;
ts.tv_sec = 15;
ts.tv_nsec = 0;
if (semtimedop(semid, &sop, 1, &ts) == -1)
err_exit("wait sem1 0", errno);
/* remove sem set after one round of test */
if (semctl(semid, 2, IPC_RMID, semu) == -1)
err_exit("rmid", errno);
close(fd);
exit(0);
}
/* getlck */
if (lock_cmd == 0) {
/* wait sem created and initialized */
do {
semid = semget(semkey, 2, 0);
if (semid != -1)
break;
if (errno == ENOENT)
continue;
else
err_exit("getlk_semget", errno);
} while (1);
do {
memset(&sem_ds, 0, sizeof(sem_ds));
semu.buf = &sem_ds;
ret = semctl(semid, 0, IPC_STAT, semu);
} while (!(ret == 0 && sem_ds.sem_otime != 0));
/* wait sem0 == 0 (setlk and close fd done) */
sop.sem_num = 0;
sop.sem_op = 0;
sop.sem_flg = 0;
ts.tv_sec = 15;
ts.tv_nsec = 0;
if (semtimedop(semid, &sop, 1, &ts) == -1)
err_exit("wait sem0 0", errno);
if (fcntl(fd, getlk_macro, &flk) < 0)
err_exit("getlk", errno);
/* set sem1 = 0 (getlk done) */
semu.val = 0;
if (semctl(semid, 1, SETVAL, semu) == -1)
err_exit("set sem1 0", errno);
/* check result */
switch (flk.l_type) {
case F_UNLCK:
printf("lock could be placed\n");
break;
case F_RDLCK:
printf("get rdlck\n");
break;
case F_WRLCK:
printf("get wrlck\n");
break;
default:
printf("unknown lock type\n");
break;
}
close(fd);
}
return 0;
}
+250
View File
@@ -0,0 +1,250 @@
#! /bin/bash
# FS QA Test 478
#
# Test OFD lock. fcntl F_OFD_SETLK to set lock, then F_OFD_GETLK
# to verify we are being given correct advice by kernel.
#
# OFD lock combines POSIX lock and BSD flock:
# + does not share between threads
# + byte granularity
# (both tested by LTP/fcntl3{4,6})
# + only release automatically after all open fd closed
#
# This test target the third one and expand a little bit.
#
# The basic idea is one setlk routine setting locks via fcntl
# *_SETLK, followed by operations like clone, dup then close fd;
# another routine getlk getting locks via fcntl *_GETLK.
#
# Firstly in setlk routine process P0, place a lock L0 on an
# opened testfile, then
#
# + clone() a child P1 to close the fd then tell getlk to go,
# parent P0 wait getlk done then close fd.
# or
# + dup() fd to a newfd then close newfd then tell getlk to go,
# then wait getlk done then close fd.
#
# In getlk process P2, do fcntl *_GETLK with lock L1 after get
# notified by setlk routine.
#
# In the end, getlk routine check the returned struct flock.l_type
# to see if the lock mechanism works fine.
#
# When testing with clone,
# + CLONE_FILES set, close releases all locks;
# + CLONE_FILES not set, locks remain in P0;
#
# If L0 is a POSIX lock,
# + it is not inherited into P1
# + it is released after dup & close
#
# If L0 is a OFD lock,
# + it is inherited into P1
# + it is not released after dup & close
#
# setlk routine: * getlk routine:
# start * start
# | * |
# open file * open file
# | * |
# init sem * |
# | * |
# wait init sem done * wait init sem done
# | * |
# setlk L0 * |
# | * |
# |---------clone()--------| * |
# | | * |
# |(child P1) (parent P0)| * | (P2)
# | | * |
# | close fd * |
# | | * |
# | set sem0=0 * wait sem0==0
# | | * |
# | | * getlk L1
# | | * |
# wait sem1==0 | * set sem1=0
# | | * |
# exit wait child * |
# | * check result
# cleanup * |
# | * |
# exit * exit
#
# We can test combainations of:
# + shared or exclusive lock
# + these locks are conflicting or not
# + one OFD lock and one POSIX lock
# + that open testfile RDONLY or RDWR
# + clone with CLONE_FILES or not
# + dup and close newfd
#
#-----------------------------------------------------------------------
# Copyright (c) 2018 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
# remove previous $seqres.full before test
rm -f $seqres.full
# Modify as appropriate.
_supported_fs generic
_supported_os Linux
_require_test
_require_ofd_locks
# real QA test starts here
# prepare a 4k testfile in TEST_DIR
$XFS_IO_PROG -f -c "pwrite -S 0xFF 0 4096" \
$TEST_DIR/testfile >> $seqres.full 2>&1
do_test()
{
local soptions="$1"
local goptions="$2"
# print options and getlk output for debug
echo $* >> $seqres.full 2>&1
# -s : do setlk
$here/src/t_ofd_locks $soptions $TEST_DIR/testfile &
# -g : do getlk
$here/src/t_ofd_locks $goptions $TEST_DIR/testfile | \
tee -a $seqres.full
wait $!
# add -F to clone with CLONE_FILES
soptions="$1 -F"
# with -F, new locks are always file to place
$here/src/t_ofd_locks $soptions $TEST_DIR/testfile &
$here/src/t_ofd_locks $goptions $TEST_DIR/testfile | \
tee -a $seqres.full
wait $!
# add -d to dup and close
soptions="$1 -d"
$here/src/t_ofd_locks $soptions $TEST_DIR/testfile &
$here/src/t_ofd_locks $goptions $TEST_DIR/testfile | \
tee -a $seqres.full
wait $!
}
# Always setlk at range [0,9], getlk at range [0,9] [5,24] or [20,29].
# To open file RDONLY or RDWR should not break the locks.
# POSIX locks should be released after closed fd, so it wont conflict
# with other locks in tests
# -P : operate posix lock
# -w : operate on F_WRLCK
# -r : operate on F_RDLCK
# -R : open file RDONLY
# -W : open file RDWR
# -o : file offset where the lock starts
# -l : lock length
# -F : clone with CLONE_FILES in setlk
# -d : dup and close in setlk
# setlk wrlck [0,9], getlk wrlck [0,9], expect
# + wrlck when CLONE_FILES not set
# + unlck when CLONE_FILES set
# + wrlck when dup & close
do_test "-s -w -o 0 -l 10 -W" "-g -w -o 0 -l 10 -W" "wrlck" "unlck" "wrlck"
# setlk wrlck [0,9], getlk posix wrlck [5,24]
do_test "-s -w -o 0 -l 10 -W" "-g -w -o 5 -l 20 -W -P" "wrlck" "unlck" "wrlck"
# setlk wrlck [0,9], getlk wrlck [20,29]
do_test "-s -w -o 0 -l 10 -W" "-g -w -o 20 -l 10 -W" "unlck" "unlck" "unlck"
# setlk posix wrlck [0,9], getlk wrlck [5,24]
do_test "-s -w -o 0 -l 10 -W -P" "-g -w -o 5 -l 20 -W" "wrlck" "unlck" "unlck"
# setlk posix wrlck [0,9], getlk wrlck [20,29]
do_test "-s -w -o 0 -l 10 -W -P" "-g -w -o 20 -l 10 -W" "unlck" "unlck" "unlck"
# setlk wrlck [0,9], getlk rdlck [0,9]
do_test "-s -w -o 0 -l 10 -W" "-g -r -o 0 -l 10 -W" "wrlck" "unlck" "wrlck"
# setlk wrlck [0,9], getlk posix rdlck [5,24]
do_test "-s -w -o 0 -l 10" "-g -r -o 5 -l 20 -P" "wrlck" "unlck" "wrlck"
# setlk wrlck [0,9], getlk rdlck [20,29]
do_test "-s -w -o 0 -l 10" "-g -r -o 20 -l 10" "unlck" "unlck" "unlck"
# setlk posix wrlck [0,9], getlk rdlck [5,24]
do_test "-s -w -o 0 -l 10 -P" "-g -r -o 5 -l 20" "wrlck" "unlck" "unlck"
# setlk posix wrlck [0,9], getlk rdlck [20,29]
do_test "-s -w -o 0 -l 10 -P" "-g -r -o 20 -l 10" "unlck" "unlck" "unlck"
# setlk rdlck [0,9], getlk wrlck [0,9], open RDONLY
do_test "-s -r -o 0 -l 10 -R" "-g -w -o 0 -l 10 -R" "rdlck" "unlck" "rdlck"
# setlk rdlck [0,9], getlk wrlck [5,24], open RDONLY
do_test "-s -r -o 0 -l 10 -R" "-g -w -o 5 -l 20 -R -P" "rdlck" "unlck" "rdlck"
# setlk posix rdlck [0,9], getlk wrlck [5,24], open RDONLY
do_test "-s -r -o 0 -l 10 -R -P" "-g -w -o 5 -l 20 -R" "rdlck" "unlck" "unlck"
# setlk rdlck [0,9], getlk wrlck [0,9]
do_test "-s -r -o 0 -l 10" "-g -w -o 0 -l 10" "rdlck" "unlck" "rdlck"
# setlk rdlck [0,9], getlk posix wrlck [5,24]
do_test "-s -r -o 0 -l 10" "-g -w -o 5 -l 20 -P" "rdlck" "unlck" "rdlck"
# setlk posix rdlck [0,9], getlk wrlck [5,24]
do_test "-s -r -o 0 -l 10 -P" "-g -w -o 5 -l 20" "rdlck" "unlck" "unlck"
# setlk rdlck [0,9], getlk wrlck [20,29], open RDONLY
do_test "-s -r -o 0 -l 10 -R" "-g -w -o 20 -l 10 -R" "unlck" "unlck" "unlck"
# setlk posix rdlck [0,9], getlk wrlck [20,29], open RDONLY
do_test "-s -r -o 0 -l 10 -R -P" "-g -w -o 20 -l 10 -R" "unlck" "unlck" "unlck"
# setlk rdlck [0,9], getlk wrlck [20,29]
do_test "-s -r -o 0 -l 10" "-g -w -o 20 -l 10" "unlck" "unlck" "unlck"
# setlk posix rdlck [0,9], getlk wrlck [20,29]
do_test "-s -r -o 0 -l 10 -P" "-g -w -o 20 -l 10" "unlck" "unlck" "unlck"
# setlk rdlck [0,9], getlk rdlck [0,9], open RDONLY
do_test "-s -r -o 0 -l 10 -R" "-g -r -o 0 -l 10 -R" "unlck" "unlck" "unlck"
# setlk rdlck [0,9], getlk posix rdlck [0,9], open RDONLY
do_test "-s -r -o 0 -l 10 -R" "-g -r -o 0 -l 10 -R -P" "unlck" "unlck" "unlck"
# setlk posix rdlck [0,9], getlk rdlck [0,9], open RDONLY
do_test "-s -r -o 0 -l 10 -R -P" "-g -r -o 0 -l 10 -R" "unlck" "unlck" "unlck"
# setlk rdlck [0,9], getlk rdlck [0,9]
do_test "-s -r -o 0 -l 10" "-g -r -o 0 -l 10" "unlck" "unlck" "unlck"
# setlk posix rdlck [0,9], getlk rdlck [0,9]
do_test "-s -r -o 0 -l 10 -P" "-g -r -o 0 -l 10" "unlck" "unlck" "unlck"
# setlk rdlck [0,9], getlk rdlck [20,29], open RDONLY
do_test "-s -r -o 0 -l 10 -R" "-g -r -o 20 -l 10 -R" "unlck" "unlck" "unlck"
# setlk rdlck [0,9], getlk posix rdlck [20,29], open RDONLY
do_test "-s -r -o 0 -l 10 -R" "-g -r -o 20 -l 10 -R -P" "unlck" "unlck" "unlck"
# setlk posix rdlck [0,9], getlk rdlck [20,29], open RDONLY
do_test "-s -r -o 0 -l 10 -R -P" "-g -r -o 20 -l 10 -R" "unlck" "unlck" "unlck"
# setlk rdlck [0,9], getlk rdlck [20,29]
do_test "-s -r -o 0 -l 10" "-g -r -o 20 -l 10" "unlck" "unlck" "unlck"
# setlk posix rdlck [0,9], getlk rdlck [20,29]
do_test "-s -r -o 0 -l 10 -P" "-g -r -o 20 -l 10" "unlck" "unlck" "unlck"
# success, all done
status=0
exit
+91
View File
@@ -0,0 +1,91 @@
QA output created by 478
get wrlck
lock could be placed
get wrlck
get wrlck
lock could be placed
get wrlck
lock could be placed
lock could be placed
lock could be placed
get wrlck
lock could be placed
lock could be placed
lock could be placed
lock could be placed
lock could be placed
get wrlck
lock could be placed
get wrlck
get wrlck
lock could be placed
get wrlck
lock could be placed
lock could be placed
lock could be placed
get wrlck
lock could be placed
lock could be placed
lock could be placed
lock could be placed
lock could be placed
get rdlck
lock could be placed
get rdlck
get rdlck
lock could be placed
get rdlck
get rdlck
lock could be placed
lock could be placed
get rdlck
lock could be placed
get rdlck
get rdlck
lock could be placed
get rdlck
get rdlck
lock could be placed
lock could be placed
lock could be placed
lock could be placed
lock could be placed
lock could be placed
lock could be placed
lock could be placed
lock could be placed
lock could be placed
lock could be placed
lock could be placed
lock could be placed
lock could be placed
lock could be placed
lock could be placed
lock could be placed
lock could be placed
lock could be placed
lock could be placed
lock could be placed
lock could be placed
lock could be placed
lock could be placed
lock could be placed
lock could be placed
lock could be placed
lock could be placed
lock could be placed
lock could be placed
lock could be placed
lock could be placed
lock could be placed
lock could be placed
lock could be placed
lock could be placed
lock could be placed
lock could be placed
lock could be placed
lock could be placed
lock could be placed
lock could be placed
lock could be placed
lock could be placed
+1
View File
@@ -480,3 +480,4 @@
475 shutdown auto log metadata
476 auto rw
477 auto quick exportfs
478 auto quick