Hi! On 2015/08/06 22:43, Cyril Hrubis wrote: > Hi! >> +/* >> + * MIN_TIME_LIMIT is defined to 5 senconds as a minimal acceptable >> + * amount of time for the lease breaker waitting for unblock, if the >> + * lease breaker is unblocked within MIN_TIME_LIMIT we may consider >> + * that the feature of the lease mechanism works well. >> + */ >> +#define MIN_TIME_LIMIT 5 >> + >> +#define OP_OPEN_RDONLY 0 >> +#define OP_OPEN_WRONLY 1 >> +#define OP_OPEN_RDWR 2 >> +#define OP_TRUNCATE 3 >> + >> +#define FILE_MODE (S_IRWXU | S_IRWXG | S_IRWXO | S_ISUID | S_ISGID) >> +#define PATH_LS_BRK_T "/proc/sys/fs/lease-break-time" >> + >> +static void setup(void); >> +static void do_test(int); >> +static int do_child(int); >> +static void sighandler(int); >> +static void cleanup(void); >> + >> +static int fd; >> +static int ls_brk_t; >> +static volatile int lease; >> + >> +static struct test_case_t { >> + int lease_type; >> + int op_type; >> + char *string; > ^ > This is nice example how we shouldn't name variables. > > What about 'desc' or something that actually says more about > what is the string used for? >
I see, I will name variables reasonably, thanks! >> +} test_cases[] = { >> + {F_WRLCK, OP_OPEN_RDONLY, "open() O_RDONLY conflicts with F_WRLCK"}, >> + {F_WRLCK, OP_OPEN_WRONLY, "open() O_WRONLY conflicts with F_WRLCK"}, >> + {F_WRLCK, OP_OPEN_RDWR, "open() O_RDWR conflicts with F_WRLCK"}, >> + {F_WRLCK, OP_TRUNCATE, "truncate() conflicts with F_WRLCK"}, >> + {F_RDLCK, OP_OPEN_WRONLY, "open() O_WRONLY conflicts with O_RDLCK"}, >> + {F_RDLCK, OP_OPEN_RDWR, "open() O_RDWR conflicts with O_RDLCK"}, >> + {F_RDLCK, OP_TRUNCATE, "truncate() conflicts with F_RDLCK"}, >> +}; >> + >> +char *TCID = "fcntl33"; >> +int TST_TOTAL = ARRAY_SIZE(test_cases); >> + >> +int main(int ac, char **av) >> +{ >> + int lc; >> + int tc; >> + long type; >> + >> + tst_parse_opts(ac, av, NULL, NULL); >> + >> + setup(); >> + >> + switch ((type = tst_fs_type(cleanup, "."))) { >> + case TST_NFS_MAGIC: >> + case TST_RAMFS_MAGIC: >> + case TST_TMPFS_MAGIC: >> + tst_brkm(TCONF, cleanup, >> + "Cannot do fcntl on a file on %s filesystem", > > Here as well, please include what kind of fcntl these do not support. > OK, got it. >> + tst_fs_type_name(type)); >> + break; > > No need for the break here as tst_brkm() does not return (calls exit()). > OK, I will remove the break here as well as the one in fcntl32.c, thanks. >> + default: >> + break; >> + } >> + >> + for (lc = 0; TEST_LOOPING(lc); lc++) { >> + tst_count = 0; >> + >> + for (tc = 0; tc < TST_TOTAL; tc++) >> + do_test(tc); >> + } >> + >> + cleanup(); >> + tst_exit(); >> +} >> + >> +static void setup(void) >> +{ >> + tst_sig(FORK, DEF_HANDLER, cleanup); >> + >> + /* Backup the lease-break-time. */ >> + SAFE_FILE_SCANF(NULL, PATH_LS_BRK_T, "%d", &ls_brk_t); >> + SAFE_FILE_PRINTF(NULL, PATH_LS_BRK_T, "%d", 45); >> + >> + tst_tmpdir(); >> + >> + TST_CHECKPOINT_INIT(tst_rmdir); >> + >> + SAFE_TOUCH(cleanup, "file", FILE_MODE, NULL); >> + >> + TEST_PAUSE; >> +} >> + >> +static void do_test(int i) >> +{ >> + pid_t cpid; >> + >> + cpid = FORK_OR_VFORK(); > > Never use FORK_OR_VFORK() in testcases that are not ported to uclinux. > You should use tst_fork() instead. > OK, got it, thanks. >> + if (cpid < 0) >> + tst_brkm(TBROK | TERRNO, cleanup, "fork(2) failed"); >> + >> + if (cpid == 0) >> + do_child(i); >> + >> + fd = SAFE_OPEN(cleanup, "file", O_RDONLY); >> + >> + lease = test_cases[i].lease_type; >> + >> + TEST(fcntl(fd, F_SETLEASE, lease)); >> + if (TEST_RETURN == -1) { >> + tst_resm(TFAIL | TTERRNO, "fcntl(2) failed to set lease"); >> + SAFE_WAITPID(cleanup, cpid, NULL, 0); >> + SAFE_CLOSE(cleanup, fd); >> + fd = 0; >> + return; >> + } >> + >> + if (signal(SIGIO, sighandler) == SIG_ERR) >> + tst_brkm(TBROK | TERRNO, cleanup, "signal(2) failed"); > > Why don't we set up the signal handler once in the setup? > Yes, that is better. I will set up the signal handler there, thanks. >> + TST_SAFE_CHECKPOINT_WAKE(cleanup, 0); >> + >> + tst_record_childstatus(cleanup, cpid); >> + >> + SAFE_CLOSE(cleanup, fd); >> + fd = 0; >> +} >> + >> +static int do_child(int i) >> +{ >> + time_t time_start, time_end; >> + >> + TST_SAFE_CHECKPOINT_WAIT(NULL, 0); >> + >> + if (time(&time_start) == -1) { >> + tst_brkm(TBROK | TERRNO, NULL, >> + "getting start time failed"); >> + } > > Using time() for measuring elapsed time is wrong for several reasons. > > We have timer functions in LTP library (which are documented in > test-writing-guidelines.txt). Use them. > OK, I will check and use them instead, thanks. >> + switch (test_cases[i].op_type) { >> + case OP_OPEN_RDONLY: >> + SAFE_OPEN(NULL, "file", O_RDONLY); >> + break; >> + case OP_OPEN_WRONLY: >> + SAFE_OPEN(NULL, "file", O_WRONLY); >> + break; >> + case OP_OPEN_RDWR: >> + SAFE_OPEN(NULL, "file", O_RDWR); >> + break; >> + case OP_TRUNCATE: >> + SAFE_TRUNCATE(NULL, "file", 0); >> + break; >> + default: >> + break; >> + } >> + >> + if (time(&time_end) == -1) { >> + tst_brkm(TBROK | TERRNO, NULL, >> + "getting end time failed"); >> + } >> + >> + if (difftime(time_end, time_start) < MIN_TIME_LIMIT) { >> + tst_resm(TPASS, "fcntl(2) lease passed, " >> + "test type: %s", test_cases[i].string); >> + } else { >> + tst_resm(TFAIL, "unblocking took too long time, " >> + "test type: %s", test_cases[i].string); >> + } >> + >> + tst_exit(); >> +} >> + >> +static void sighandler(int sig) >> +{ >> + int ret; >> + >> + if (sig != SIGIO) { >> + ret = write(STDOUT_FILENO, "get wrong signal\n", >> + sizeof("get wrong signal\n")); >> + } else { >> + switch (lease) { >> + case F_WRLCK: >> + TEST(fcntl(fd, F_SETLEASE, F_RDLCK)); >> + if (TEST_RETURN == 0) >> + break; >> + case F_RDLCK: >> + TEST(fcntl(fd, F_SETLEASE, F_UNLCK)); >> + if (TEST_RETURN == -1) { >> + ret = write(STDOUT_FILENO, >> + "fcntl(2) failed\n", >> + sizeof("fcntl(2) failed\n")); >> + } >> + break; >> + default: >> + break; >> + } > > I do not like that we do the unlocking here in signal handler. It should > be done in parent process and we should fail the test properly if this > fails. > > What about doing sigtimedwait() in parent with suitable timeout instead? > OK,I will use sigtimedwait() instead, thanks. >> + } >> + >> + (void)ret; > > Why do we set the variable if it's not used at all? > Without the variable, compilation reports warning below, warning: ignoring return value of 'write', declared with attribute warn_unused_result Actually I would like to remove the variable if it's OK to the warning. >> +} >> + >> +static void cleanup(void) >> +{ >> + if (fd > 0 && close(fd)) >> + tst_resm(TWARN | TTERRNO, "failed to close file"); >> + >> + tst_rmdir(); >> + >> + /* Restore the lease-break-time. */ >> + FILE_PRINTF(PATH_LS_BRK_T, "%d", ls_brk_t); >> +} >> -- >> 1.8.4.2 >> >> >> ------------------------------------------------------------------------------ >> _______________________________________________ >> Ltp-list mailing list >> Ltp-list@lists.sourceforge.net >> https://lists.sourceforge.net/lists/listinfo/ltp-list > ------------------------------------------------------------------------------ _______________________________________________ Ltp-list mailing list Ltp-list@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/ltp-list