Hi,

--- On Thu, 12/25/08, Andrew Vagin <ava...@gmail.com> wrote:

> From: Andrew Vagin <ava...@gmail.com>
> Subject: [PATCH] add new testcase for check inotify subsytem.
> To: caiq...@cclom.cn
> Cc: subr...@linux.vnet.ibm.com, ltp-list@lists.sourceforge.net, "Andrew 
> Vagin" <ava...@gmail.com>
> Date: Thursday, December 25, 2008, 12:49 AM
> this testcase checked event IN_UNMOUNT
> IN_UNMOUNT File system containing watched object was
> unmounted and
> check filesystem that it can't be unmounted if exist
> opened inotify
> descriptor.
> 
> example of execution:
> 
> Running tests.......
> inotify03    0  INFO  :  mount /dev/loop0 to mnt_694
> fstype=ext3
> inotify03    0  INFO  :  umount /dev/loop0
> <<<test_start>>>
> tag=inotify03 stime=1229332020
> cmdline="inotify03 -D /dev/loop0 -T ext3"
> contacts=""
> analysis=exit
> initiation_status="ok"
> <<<test_output>>>
> incrementing stop
> inotify03    1  PASS  :  get event: wd=1 mask=2000 cookie=0
> len=0
> inotify03    2  PASS  :  get event: wd=1 mask=8000 cookie=0
> len=0
> inotify03    3  PASS  :  inotify_rm_watch (5, 1) return -1
> errno=22 : Invalid argument
> <<<execution_status>>>
> duration=0 termination_type=exited termination_id=0
> corefile=no
> cutime=0 cstime=0
> <<<test_end>>>
> 
> kernel: Linux avagin 2.6.25-rc6 #1 SMP Tue Jul 8 13:42:51
> MSD 2008 i686 Intel(R) Celeron(R) CPU 2.53GHz GenuineIntel
> GNU/Linux
> ---
>  runtest/syscalls                              |    1 +
>  testcases/kernel/syscalls/inotify/inotify03.c |  378
> +++++++++++++++++++++++++
>  2 files changed, 379 insertions(+), 0 deletions(-)
>  create mode 100644
> testcases/kernel/syscalls/inotify/inotify03.c
> 
> diff --git a/runtest/syscalls b/runtest/syscalls
> index 67c79c3..2b35f9a 100644
> --- a/runtest/syscalls
> +++ b/runtest/syscalls
> @@ -411,6 +411,7 @@ ioctl03      ioctl03
>  
>  inotify01 inotify01
>  inotify02 inotify02
> +inotify03 inotify03 -D DEVICE -T DEVICE_FS_TYPE
>  
>  ioperm01 ioperm01
>  ioperm02 ioperm02
> diff --git a/testcases/kernel/syscalls/inotify/inotify03.c
> b/testcases/kernel/syscalls/inotify/inotify03.c
> new file mode 100644
> index 0000000..2761b88
> --- /dev/null
> +++ b/testcases/kernel/syscalls/inotify/inotify03.c
> @@ -0,0 +1,378 @@
> +/*
> + * Copyright (c) 2008 Parallels.  All Rights Reserved.
> + *
> + * This program is free software; you can redistribute it
> and/or modify it
> + * under the terms of version 2 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.
> + *
> + * Further, this software is distributed without any
> warranty that it is
> + * free of the rightful claim of any third person
> regarding infringement
> + * or the like.  Any license provided herein, whether
> implied or
> + * otherwise, applies only to this software file.  Patent
> licenses, if
> + * any, provided herein do not apply to combinations of
> this program with
> + * other software, or any other product whatsoever.
> + *
> + * You should have received a copy of the GNU General
> Public License along
> + * with this program; if not, write the Free Software
> Foundation, Inc., 59
> + * Temple Place - Suite 330, Boston MA 02111-1307, USA.
> + *
> + * Started by Andrew Vagin <ava...@gmail.com>
> + *
> + */
> +/*
> + * NAME
> + *   inotify03
> + *
> + * DESCRIPTION
> + *   Check that inotify get IN_UNMOUNT event and
> + *   don't block the umount command.
> + *
> + * ALGORITHM
> + *   Execute sequence file's operation and check return
> events
> + *
> + */
> +
> +#include <stdio.h>
> +#include <sys/mount.h>
> +#include <sys/stat.h>
> +#include <sys/types.h>
> +#include <sys/fcntl.h>
> +#include <errno.h>
> +#include <string.h>
> +#include <sys/syscall.h>
> +#include <signal.h>
> +#include "test.h"
> +#include "usctest.h"
> +
> +#if defined(HAS_SYS_INOTIFY) &&
> defined(__NR_inotify_init)
> +#include <sys/inotify.h>
> +
> +#define EVENT_MAX 1024
> +/* size of the event structure, not counting name */
> +#define EVENT_SIZE (sizeof (struct inotify_event))
> +/* reasonable guess as to size of 1024 events */
> +#define EVENT_BUF_LEN                (EVENT_MAX * (EVENT_SIZE + 16))
> +
> +void help(void);
> +void setup();
> +void cleanup();
> +
> +char *TCID="inotify03";              /* Test program
> identifier.   */
> +int TST_TOTAL = 3;           /* Total number of test cases. */
> +extern int Tst_count;                /* Test Case counter for tst_*
> routines */
> +
> +#define BUF_SIZE 1024
> +char fname[BUF_SIZE];
> +char buf[BUF_SIZE];
> +int fd, fd_notify;
> +int wd;
> +
> +int event_set[EVENT_MAX];
> +
> +char event_buf[EVENT_BUF_LEN];
> +
> +static long myinotify_init()
> +{
> +     return syscall(__NR_inotify_init);
> +}
> +
> +static long myinotify_add_watch(int fd, const char
> *pathname, int mask)
> +{
> +     return syscall(__NR_inotify_add_watch, fd, pathname,
> mask);
> +}
> +
> +static long myinotify_rm_watch(int fd, int wd)
> +{
> +     return syscall(__NR_inotify_rm_watch, fd, wd);
> +}
> +
> +#define DEFAULT_FSTYPE       "ext2"
> +#define DIR_MODE     S_IRWXU | S_IRUSR | S_IXUSR | S_IRGRP |
> S_IXGRP
> +
> +static char *Fstype;
> +static char mntpoint[20];
> +static int mount_flag = 0;
> +static char *fstype;
> +static char *device;
> +static int Tflag = 0;
> +static int Dflag = 0;
> +
> +static option_t options[] = {                /* options supported by
> mount01 test */
> +     { "T:", &Tflag, &fstype },      /* -T type
> of filesystem */
> +     { "D:", &Dflag, &device },      /* -D device
> used for mounting     */
> +     { NULL, NULL, NULL }
> +};
> +
> +int main(int ac, char **av){
> +     char *msg;              /* message returned from parse_opts */
> +     int ret;
> +     int len, i, test_num;
> +
> +     /* parse standard options */
> +     msg = parse_opts(ac, av, (option_t *) options,
> &help);
> +     if ( msg != (char *) NULL )
> +             tst_brkm(TBROK, cleanup, "OPTION PARSING ERROR -
> %s", msg);
> +
> +     /* Check for mandatory option of the testcase */
> +     if (!Dflag) {
> +             tst_brkm(TBROK, NULL, "You must specifiy the device
> used for "
> +                     " mounting with -D option, Run '%s  -h'
> for option "
> +                     " information.", TCID);
> +             tst_exit();
> +     }
> +
> +     if (Tflag) {
> +             Fstype = (char *) malloc(strlen(fstype)+1);
> +             if(Fstype == NULL) {
> +                     tst_brkm(TBROK, NULL, "malloc - failed to alloc
> %d"
> +                             "errno %d", strlen(fstype), errno);
> +             }
> +             strncpy(Fstype, fstype, strlen(fstype)+1);
> +     } else {
> +             Fstype = (char *) malloc(strlen(DEFAULT_FSTYPE)+1);
> +             if(Fstype == NULL) {
> +                     tst_brkm(TBROK, NULL, "malloc - failed to alloc
> %d"
> +                             "errno %d", strlen(DEFAULT_FSTYPE), errno);
> +             }
> +             strncpy(Fstype, DEFAULT_FSTYPE,
> strlen(DEFAULT_FSTYPE)+1);
> +     }
> +
> +     /* perform global setup for test */
> +     setup();
> +
> +     Tst_count = 0;
> +
> +     event_set[Tst_count] = IN_UNMOUNT;
> +     Tst_count++;
> +     event_set[Tst_count] = IN_IGNORED;
> +     Tst_count++;
> +
> +     /*check exit code from inotify_rm_watch*/
> +     Tst_count++;
> +
> +     if (TST_TOTAL != Tst_count) {
> +            tst_brkm(TBROK, cleanup,
> +                    "TST_TOTAL and Tst_count are not
> equal");
> +        }
> +        Tst_count = 0;
> +
> +     tst_resm(TINFO, "umount %s", device);
> +     TEST(umount(mntpoint));
> +     if (TEST_RETURN != 0) {
> +             TEST_ERROR_LOG(TEST_ERRNO);
> +             tst_brkm(TBROK, cleanup, "umount(2) Failed "
> +                     "while unmounting errno = %d : %s",
> +                     TEST_ERRNO, strerror(TEST_ERRNO));
> +     }
> +     mount_flag = 0;
> +
> +     len = read(fd_notify, event_buf, EVENT_BUF_LEN);
> +     if (len < 0) {
> +             tst_brkm(TBROK, cleanup,
> +                     "read(%d, buf, %d) Failed, errno=%d : %s",
> +                     fd_notify, EVENT_BUF_LEN, errno,
> +                     strerror(errno));
> +     }
> +
> +     /* check events */
> +     test_num = 0;
> +     i = 0;
> +     while (i < len) {
> +             struct inotify_event *event;
> +             event = (struct inotify_event *) &event_buf[i];
> +             if (test_num >= (TST_TOTAL - 1)) {
> +                     tst_resm(TINFO,

Is not it better to use TWARN here if it is really unnecessary? It at 
least give us a sign of potential problems? If so, probably inotify01
and inotify02 test cases need to modify as well. Inotify02 test case
was used to use TFAIL instead, and it helped to find a bug in RHEL,

[RHEL5.3] LTP test failure in inotify02 testcase
https://bugzilla.redhat.com/show_bug.cgi?id=453990

> +                             "get unnecessary event: wd=%d mask=%x "
> +                             "cookie=%u len=%u",
> +                             event->wd, event->mask,
> +                             event->cookie, event->len);
> +             } else if (event_set[test_num] == event->mask){
> +                     tst_resm(TPASS, "get event: wd=%d mask=%x"
> +                             " cookie=%u len=%u",
> +                             event->wd, event->mask,
> +                             event->cookie, event->len);
> +
> +             } else {
> +                     tst_resm( TFAIL, "get event: wd=%d mask=%x "
> +                             "(expected %x) cookie=%u len=%u",
> +                             event->wd, event->mask,
> +                             event_set[test_num],
> +                             event->cookie, event->len);
> +             }
> +             test_num++;
> +             i += EVENT_SIZE + event->len;
> +     }
> +     for (; test_num<TST_TOTAL - 1; test_num++){
> +             tst_resm(TFAIL, "don't get event: mask=%x
> ",
> +                             event_set[test_num]);
> +
> +     }
> +     ret = myinotify_rm_watch(fd_notify, wd);
> +     if (ret != -1 || errno != EINVAL)
> +             tst_resm(TFAIL, "inotify_rm_watch (%d, %d) return
> %d "
> +                     "errno=%d : %s (instead of %d)",
> +                     fd_notify, wd, ret, errno, EINVAL, strerror(errno));
> +     else
> +             tst_resm(TPASS, "inotify_rm_watch (%d, %d) return
> %d "
> +                     "errno=%d : %s",
> +                     fd_notify, wd, ret, errno, strerror(errno));
> +
> +     /* cleanup and exit */
> +     cleanup();
> +
> +     return 0;
> +}    /* End main */
> +
> +/*
> + * setup() - performs all ONE TIME setup for this test.
> + */
> +void setup()
> +{
> +     int ret;
> +     /* capture signals */
> +     tst_sig(NOFORK, DEF_HANDLER, cleanup);
> +
> +     /* Pause if that option was specified */
> +     TEST_PAUSE;
> +
> +     /* make a temp directory and cd to it */
> +     tst_tmpdir();
> +
> +     (void)sprintf(mntpoint, "mnt_%d", getpid());
> +
> +     if (mkdir(mntpoint, DIR_MODE) < 0) {
> +             tst_brkm(TBROK, cleanup, "mkdir(%s, %#o) failed;
> "
> +                     "errno = %d: %s", mntpoint, DIR_MODE, errno,
> +                     strerror(errno));
> +     }
> +
> +     /* Call mount(2) */
> +     tst_resm(TINFO, "mount %s to %s fstype=%s",
> device, mntpoint, Fstype);
> +     TEST(mount(device, mntpoint, Fstype, 0, NULL));
> +
> +     /* check return code */
> +     if (TEST_RETURN != 0) {
> +             TEST_ERROR_LOG(TEST_ERRNO);
> +             tst_brkm(TBROK, cleanup, "mount(2) Failed errno =
> %d : %s",
> +                     TEST_ERRNO, strerror(TEST_ERRNO));
> +     }
> +     mount_flag = 1;
> +
> +     sprintf(fname,"%s/tfile_%d", mntpoint,
> getpid());
> +     fd = open(fname,O_RDWR|O_CREAT,0700);
> +     if (fd == -1) {
> +             tst_brkm(TBROK, cleanup,
> +                     "open(%s, O_RDWR|O_CREAT,0700) Failed, errno=%d :
> %s",
> +                     fname, errno, strerror(errno));
> +     }
> +
> +     ret = write(fd, fname, 1);
> +     if (ret == -1) {
> +             tst_brkm(TBROK, cleanup,
> +                             "write(%d, %s, 1) Failed, errno=%d : %s",
> +                             fd, fname, errno, strerror(errno));
> +     }
> +
> +     /* close the file we have open */
> +     if (close(fd) == -1) {
> +             tst_brkm(TBROK, cleanup,
> +                             "close(%s) Failed, errno=%d : %s",
> +                             fname, errno, strerror(errno));
> +     }
> +
> +     fd_notify = myinotify_init();
> +
> +     if (fd_notify < 0) {
> +             if( errno == ENOSYS ){
> +                     tst_resm(TCONF, "inotify is not configured in this
> kernel.");
> +                     tst_resm(TCONF, "Test will not run.");
> +                     cleanup();
> +                     tst_exit();
> +             }else{
> +                     tst_brkm(TBROK, cleanup,
> +                             "inotify_init () Failed, errno=%d : %s",
> +                             errno, strerror(errno));
> +             }
> +     }
> +
> +     wd = myinotify_add_watch (fd_notify, fname,
> IN_ALL_EVENTS);
> +     if (wd < 0) {
> +             tst_brkm(TBROK, cleanup,
> +                             "inotify_add_watch (%d, %s, IN_ALL_EVENTS)"
> +                             "Failed, errno=%d : %s",
> +                             fd_notify, fname, errno, strerror(errno));
> +     };
> +
> +}    /* End setup() */
> +
> +
> +/*
> + * cleanup() - performs all ONE TIME cleanup for this test
> at
> + *           completion or premature exit.
> + */
> +void cleanup()
> +{
> +     free(Fstype);
> +     if (close(fd_notify) == -1) {
> +             tst_resm(TWARN, "close(%d) Failed, errno=%d :
> %s",
> +                             fd_notify, errno, strerror(errno));
> +     }
> +
> +     if (mount_flag) {
> +             TEST(umount(mntpoint));
> +             if (TEST_RETURN != 0) {
> +                     TEST_ERROR_LOG(TEST_ERRNO);
> +                     tst_resm(TWARN, "umount(2) Failed "
> +                             "while unmounting errno = %d : %s",
> +                             TEST_ERRNO, strerror(TEST_ERRNO));
> +             }
> +     }
> +
> +     /*
> +      * print timing stats if that option was specified.
> +      * print errno log if that option was specified.
> +      */
> +     TEST_CLEANUP;
> +
> +     /* Remove tmp dir and all files in it */
> +     tst_rmdir();
> +
> +     /* exit with return code appropriate for results */
> +     tst_exit();
> +}    /* End cleanup() */
> +
> +/*
> + * issue a help message
> + */
> +void help()
> +{
> +     printf("-T type : specifies the type of filesystem
> to be mounted."
> +             " Default ext2. \n");
> +     printf("-D device : device used for mounting
> \n");
> +}
> +
> +#else
> +
> +char *TCID="inotify03";      /* Test program
> identifier.   */
> +int TST_TOTAL = 0;           /* Total number of test cases. */
> +
> +int
> +main()
> +{
> +#ifndef __NR_inotify_init
> +     tst_resm(TWARN, "This test needs a kernel that has
> inotify syscall.");
> +     tst_resm(TWARN, "Inotify syscall can be found at
> kernel 2.6.13 or higher.");

It would be better to use TCONF which will not generate false failure.

CAI Qian

> +     return 0;
> +#endif
> +#ifndef HAS_SYS_INOTIFY
> +     tst_resm(TBROK, "can't find header
> sys/inotify.h");
> +     return 1;
> +#endif
> +     return 0;
> +}
> +
> +#endif
> -- 
> 1.5.6.4

------------------------------------------------------------------------------
_______________________________________________
Ltp-list mailing list
Ltp-list@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/ltp-list

Reply via email to