From: Zeng L. <zen...@cn...> - 2014-01-10 11:29:55
|
Add new error number tests for linkat(2): * ENAMETOOLONG * EEXIST * ELOOP * EACCES * EMLINK * EROFS Signed-off-by: Zeng Linggang <zen...@cn...> --- runtest/syscalls | 1 + testcases/kernel/syscalls/.gitignore | 1 + testcases/kernel/syscalls/linkat/linkat02.c | 311 ++++++++++++++++++++++++++++ 3 files changed, 313 insertions(+) create mode 100644 testcases/kernel/syscalls/linkat/linkat02.c diff --git a/runtest/syscalls b/runtest/syscalls index afa7976..02fb9ad 100644 --- a/runtest/syscalls +++ b/runtest/syscalls @@ -487,6 +487,7 @@ link07 link07 #linkat test cases linkat01 linkat01 +linkat01 linkat01 -D DEVICE -T DEVICE_FS_TYPE listen01 listen01 diff --git a/testcases/kernel/syscalls/.gitignore b/testcases/kernel/syscalls/.gitignore index 91cf0f1..d1a8547 100644 --- a/testcases/kernel/syscalls/.gitignore +++ b/testcases/kernel/syscalls/.gitignore @@ -445,6 +445,7 @@ /link/link06 /link/link07 /linkat/linkat01 +/linkat/linkat02 /listen/listen01 /llseek/llseek01 /llseek/llseek02 diff --git a/testcases/kernel/syscalls/linkat/linkat02.c b/testcases/kernel/syscalls/linkat/linkat02.c new file mode 100644 index 0000000..7f9da3d --- /dev/null +++ b/testcases/kernel/syscalls/linkat/linkat02.c @@ -0,0 +1,311 @@ +/* + * Copyright (c) 2014 Fujitsu Ltd. + * Author: Zeng Linggang <zen...@cn...> + * + * 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. + * + * You should have received a copy of the GNU General Public License along + * with this program. + */ +/* + * Test that linkat() fails and sets the proper errno values. + */ + +#define _GNU_SOURCE + +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <unistd.h> +#include <error.h> +#include <stdlib.h> +#include <errno.h> +#include <string.h> +#include <signal.h> +#include <pwd.h> +#include <sys/mount.h> + +#include "test.h" +#include "usctest.h" +#include "linux_syscall_numbers.h" +#include "safe_macros.h" + +#ifndef AT_FDCWD +# define AT_FDCWD -100 +#endif +#ifndef AT_SYMLINK_FOLLOW +# define AT_SYMLINK_FOLLOW 0x400 +#endif + +#define DIR_MODE (S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP| \ + S_IXGRP|S_IROTH|S_IXOTH) +#define TEST_FILE "testfile" +#define TEST_EXIST "testexist" +#define TEST_ELOOP "testeloop" +#define TEST_EACCES "./tmp/testeeacces" +#define TEST_EACCES2 "./tmp/testeeacces2" +#define TEST_EROFS "mntpoint" +#define TEST_EROFS2 "mntpoint/testerofs2" +#define TEST_EMLINK "mntpoint/testemlink" +#define BASENAME "mntpoint/basename" + +static long link_max; +static char lname[PATH_MAX]; +static char nametoolong[PATH_MAX+2]; +static char *fstype = "ext2"; +static char *device; +static int dflag; +static int mount_flag; + +static void setup(void); +static void cleanup(void); + +static int setup_eacces(void); +static int setup_erofs(void); +static void cleanup_erofs(void); +static void cleanup_eacces(void); +static int setup_emlink(void); +static void cleanup_emlink(void); +static void help(void); + +static option_t options[] = { + {"T:", NULL, &fstype}, + {"D:", &dflag, &device}, + {NULL, NULL, NULL} +}; + +static struct test_struct { + const char *oldfn; + const char *newfn; + int flags; + int expected_errno; + int (*setupfunc) (); + void (*cleanfunc) (); +} test_cases[] = { + {TEST_FILE, nametoolong, 0, ENAMETOOLONG, NULL, NULL}, + {nametoolong, TEST_FILE, 0, ENAMETOOLONG, NULL, NULL}, + {TEST_EXIST, TEST_EXIST, 0, EEXIST, NULL, NULL}, + {TEST_ELOOP, TEST_FILE, AT_SYMLINK_FOLLOW, ELOOP, NULL, NULL}, + {TEST_EACCES, TEST_EACCES2, 0, EACCES, setup_eacces, cleanup_eacces}, + {TEST_EROFS, TEST_EROFS2, 0, EROFS, setup_erofs, cleanup_erofs}, + {TEST_EMLINK, lname, 0, EMLINK, setup_emlink, cleanup_emlink}, +}; + +char *TCID = "linkat02"; +int TST_TOTAL = ARRAY_SIZE(test_cases); + +static struct passwd *ltpuser; +static void verify_linkat(struct test_struct *); + +static int exp_enos[] = { ENAMETOOLONG, EEXIST, ELOOP, + EACCES, EROFS, EMLINK, 0 }; + +int main(int ac, char **av) +{ + int lc; + char *msg; + int i; + + msg = parse_opts(ac, av, options, help); + if (msg != NULL) + tst_brkm(TBROK, NULL, "OPTION PARSING ERROR - %s", msg); + + if (!dflag) { + tst_brkm(TBROK, NULL, + "you must specify the device used for mounting with " + "-D option"); + } + + setup(); + + TEST_EXP_ENOS(exp_enos); + + for (lc = 0; TEST_LOOPING(lc); lc++) { + + tst_count = 0; + + for (i = 0; i < TST_TOTAL; i++) + verify_linkat(&test_cases[i]); + + } + + cleanup(); + tst_exit(); +} + +static void verify_linkat(struct test_struct *desc) +{ + if (desc->setupfunc != NULL) { + if (desc->setupfunc() != 0) { + if (desc->cleanfunc() != NULL) + desc->cleanfunc(); + return; + } + } + + TEST(ltp_syscall(__NR_linkat, AT_FDCWD, desc->oldfn, + AT_FDCWD, desc->newfn, desc->flags)); + + if (desc->cleanfunc != NULL) + desc->cleanfunc(); + + if (TEST_RETURN != -1) { + tst_resm(TFAIL, + "linkat(%s, %s, %s, %s, %d) succeeded unexpectedly", + "AT_FDCWD", desc->oldfn, + "AT_FDCWD", desc->newfn, desc->flags); + return; + } + + if (TEST_ERRNO == desc->expected_errno) { + tst_resm(TPASS | TTERRNO, "linkat failed as expected"); + } else { + tst_resm(TFAIL | TTERRNO, + "linkat failed unexpectedly; expected: " + "%d - %s", desc->expected_errno, + strerror(desc->expected_errno)); + } +} + +static void setup(void) +{ + if ((tst_kvercmp(2, 6, 16)) < 0) + tst_brkm(TCONF, NULL, "This test needs kernel 2.6.16 or newer"); + + tst_sig(NOFORK, DEF_HANDLER, cleanup); + + tst_tmpdir(); + + TEST_PAUSE; + + ltpuser = SAFE_GETPWNAM(cleanup, "nobody"); + + SAFE_TOUCH(cleanup, TEST_FILE, 0644, NULL); + + memset(nametoolong, 'a', PATH_MAX+1); + + SAFE_TOUCH(cleanup, TEST_EXIST, 0644, NULL); + + SAFE_SYMLINK(cleanup, TEST_ELOOP, "test_file_eloop2"); + SAFE_SYMLINK(cleanup, "test_file_eloop2", TEST_ELOOP); + + SAFE_MKDIR(cleanup, "./tmp", DIR_MODE); + SAFE_TOUCH(cleanup, TEST_EACCES, 0666, NULL); + + tst_mkfs(NULL, device, fstype, NULL); + SAFE_MKDIR(cleanup, "mntpoint", DIR_MODE); +} + +static int setup_emlink(void) +{ + if (mount(device, "mntpoint", fstype, 0, NULL) < 0) { + tst_brkm(TBROK | TERRNO, cleanup, + "mount device:%s failed", device); + } + mount_flag = 1; + + SAFE_TOUCH(cleanup_emlink, TEST_EMLINK, 0666, NULL); + + link_max = 0; + + while (1) { + sprintf(lname, "%s%ld", BASENAME, ++link_max); + TEST(link(TEST_EMLINK, lname)); + if (TEST_RETURN == -1) { + link_max--; + switch (TEST_ERRNO) { + case ENOSPC: + tst_resm(TCONF, + "the device has no space for the new " + "directory entry. link(%s, %s) failed", + TEST_EMLINK, lname); + return 1; + case EMLINK: + tst_resm(TINFO, "for %s the max links is %ld", + fstype, link_max+1); + return 0; + default: + tst_resm(TFAIL | TERRNO, + "link(%s, %s[0-%ld]) ret %ld, ", + TEST_EMLINK, BASENAME, link_max, + TEST_RETURN); + return 1; + } + } + } +} + +static void cleanup_emlink(void) +{ + long i; + + for (i = 1; i <= link_max; i++) { + sprintf(lname, "%s%ld", BASENAME, i); + SAFE_UNLINK(cleanup, lname); + } + + SAFE_UNLINK(cleanup, TEST_EMLINK); + + if (mount_flag && umount("mntpoint") < 0) { + mount_flag = 0; + tst_brkm(TBROK | TERRNO, cleanup, + "umount device:%s failed", device); + } + mount_flag = 0; +} + +static int setup_eacces(void) +{ + SAFE_SETEUID(cleanup, ltpuser->pw_uid); + return 0; +} + +static void cleanup_eacces(void) +{ + SAFE_SETEUID(cleanup, 0); +} + +static int setup_erofs(void) +{ + if (mount(device, "mntpoint", fstype, MS_RDONLY, NULL) < 0) { + tst_brkm(TBROK | TERRNO, cleanup_erofs, + "mount device:%s failed", device); + } + mount_flag = 1; + return 0; +} + +static void cleanup_erofs(void) +{ + if (mount_flag && umount("mntpoint") < 0) { + mount_flag = 0; + tst_brkm(TBROK | TERRNO, cleanup, + "umount device:%s failed", device); + } + mount_flag = 0; +} + +static void cleanup(void) +{ + TEST_CLEANUP; + + if (mount_flag && umount("mntpoint") < 0) { + tst_brkm(TBROK | TERRNO, NULL, + "umount device:%s failed", device); + } + + tst_rmdir(); +} + +static void help(void) +{ + printf("-T type : specifies the type of filesystem to be mounted. " + "Default ext2.\n"); + printf("-D device : device used for mounting.\n"); +} -- 1.8.4.2 |
From: Zeng L. <zen...@cn...> - 2014-01-11 03:13:27
|
Add new error number tests for linkat(2): * ENAMETOOLONG * EEXIST * ELOOP * EACCES * EMLINK * EROFS Signed-off-by: Zeng Linggang <zen...@cn...> --- runtest/syscalls | 1 + testcases/kernel/syscalls/.gitignore | 1 + testcases/kernel/syscalls/linkat/linkat02.c | 296 ++++++++++++++++++++++++++++ 3 files changed, 298 insertions(+) create mode 100644 testcases/kernel/syscalls/linkat/linkat02.c diff --git a/runtest/syscalls b/runtest/syscalls index afa7976..4a6b891 100644 --- a/runtest/syscalls +++ b/runtest/syscalls @@ -487,6 +487,7 @@ link07 link07 #linkat test cases linkat01 linkat01 +linkat02 linkat02 -D DEVICE -T DEVICE_FS_TYPE listen01 listen01 diff --git a/testcases/kernel/syscalls/.gitignore b/testcases/kernel/syscalls/.gitignore index 91cf0f1..d1a8547 100644 --- a/testcases/kernel/syscalls/.gitignore +++ b/testcases/kernel/syscalls/.gitignore @@ -445,6 +445,7 @@ /link/link06 /link/link07 /linkat/linkat01 +/linkat/linkat02 /listen/listen01 /llseek/llseek01 /llseek/llseek02 diff --git a/testcases/kernel/syscalls/linkat/linkat02.c b/testcases/kernel/syscalls/linkat/linkat02.c new file mode 100644 index 0000000..af5162a --- /dev/null +++ b/testcases/kernel/syscalls/linkat/linkat02.c @@ -0,0 +1,296 @@ +/* + * Copyright (c) 2014 Fujitsu Ltd. + * Author: Zeng Linggang <zen...@cn...> + * + * 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. + * + * You should have received a copy of the GNU General Public License along + * with this program. + */ +/* + * Test that linkat() fails and sets the proper errno values. + */ + +#define _GNU_SOURCE + +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <unistd.h> +#include <error.h> +#include <stdlib.h> +#include <errno.h> +#include <string.h> +#include <signal.h> +#include <pwd.h> +#include <sys/mount.h> + +#include "test.h" +#include "usctest.h" +#include "linux_syscall_numbers.h" +#include "safe_macros.h" + +#ifndef AT_FDCWD +# define AT_FDCWD -100 +#endif +#ifndef AT_SYMLINK_FOLLOW +# define AT_SYMLINK_FOLLOW 0x400 +#endif + +#define DIR_MODE (S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP| \ + S_IXGRP|S_IROTH|S_IXOTH) +#define TEST_FILE "testfile" +#define TEST_EXIST "testexist" +#define TEST_ELOOP "testeloop" +#define TEST_EACCES "./tmp/testeeacces" +#define TEST_EACCES2 "./tmp/testeeacces2" +#define TEST_EROFS "mntpoint" +#define TEST_EROFS2 "mntpoint/testerofs2" +#define TEST_EMLINK "mntpoint/testemlink" +#define BASENAME "mntpoint/basename" + +static long link_max; +static char lname[PATH_MAX]; +static char nametoolong[PATH_MAX+2]; +static char *fstype = "ext2"; +static char *device; +static int dflag; +static int mount_flag; + +static void setup(void); +static void cleanup(void); + +static void setup_eacces(void); +static void setup_erofs(void); +static void cleanup_erofs(void); +static void cleanup_eacces(void); +static void setup_emlink(void); +static void cleanup_emlink(void); +static void help(void); + +static option_t options[] = { + {"T:", NULL, &fstype}, + {"D:", &dflag, &device}, + {NULL, NULL, NULL} +}; + +static struct test_struct { + const char *oldfn; + const char *newfn; + int flags; + int expected_errno; + void (*setupfunc) (); + void (*cleanfunc) (); +} test_cases[] = { + {TEST_FILE, nametoolong, 0, ENAMETOOLONG, NULL, NULL}, + {nametoolong, TEST_FILE, 0, ENAMETOOLONG, NULL, NULL}, + {TEST_EXIST, TEST_EXIST, 0, EEXIST, NULL, NULL}, + {TEST_ELOOP, TEST_FILE, AT_SYMLINK_FOLLOW, ELOOP, NULL, NULL}, + {TEST_EACCES, TEST_EACCES2, 0, EACCES, setup_eacces, cleanup_eacces}, + {TEST_EROFS, TEST_EROFS2, 0, EROFS, setup_erofs, cleanup_erofs}, + {TEST_EMLINK, lname, 0, EMLINK, setup_emlink, cleanup_emlink}, +}; + +char *TCID = "linkat02"; +int TST_TOTAL = ARRAY_SIZE(test_cases); + +static struct passwd *ltpuser; +static void verify_linkat(struct test_struct *); + +static int exp_enos[] = { ENAMETOOLONG, EEXIST, ELOOP, + EACCES, EROFS, EMLINK, 0 }; + +int main(int ac, char **av) +{ + int lc; + char *msg; + int i; + + msg = parse_opts(ac, av, options, help); + if (msg != NULL) + tst_brkm(TBROK, NULL, "OPTION PARSING ERROR - %s", msg); + + if (!dflag) { + tst_brkm(TBROK, NULL, + "you must specify the device used for mounting with " + "-D option"); + } + + setup(); + + TEST_EXP_ENOS(exp_enos); + + for (lc = 0; TEST_LOOPING(lc); lc++) { + + tst_count = 0; + + for (i = 0; i < TST_TOTAL; i++) + verify_linkat(&test_cases[i]); + + } + + cleanup(); + tst_exit(); +} + +static void verify_linkat(struct test_struct *desc) +{ + if (desc->setupfunc != NULL) + desc->setupfunc(); + + TEST(ltp_syscall(__NR_linkat, AT_FDCWD, desc->oldfn, + AT_FDCWD, desc->newfn, desc->flags)); + + if (desc->cleanfunc != NULL) + desc->cleanfunc(); + + if (TEST_RETURN != -1) { + tst_resm(TFAIL, + "linkat(%s, %s, %s, %s, %d) succeeded unexpectedly", + "AT_FDCWD", desc->oldfn, + "AT_FDCWD", desc->newfn, desc->flags); + return; + } + + if (TEST_ERRNO == desc->expected_errno) { + tst_resm(TPASS | TTERRNO, "linkat failed as expected"); + } else { + tst_resm(TFAIL | TTERRNO, + "linkat failed unexpectedly; expected: " + "%d - %s", desc->expected_errno, + strerror(desc->expected_errno)); + } +} + +static void setup(void) +{ + if ((tst_kvercmp(2, 6, 16)) < 0) + tst_brkm(TCONF, NULL, "This test needs kernel 2.6.16 or newer"); + + tst_sig(NOFORK, DEF_HANDLER, cleanup); + + tst_tmpdir(); + + TEST_PAUSE; + + ltpuser = SAFE_GETPWNAM(cleanup, "nobody"); + + SAFE_TOUCH(cleanup, TEST_FILE, 0644, NULL); + + memset(nametoolong, 'a', PATH_MAX+1); + + SAFE_TOUCH(cleanup, TEST_EXIST, 0644, NULL); + + SAFE_SYMLINK(cleanup, TEST_ELOOP, "test_file_eloop2"); + SAFE_SYMLINK(cleanup, "test_file_eloop2", TEST_ELOOP); + + SAFE_MKDIR(cleanup, "./tmp", DIR_MODE); + SAFE_TOUCH(cleanup, TEST_EACCES, 0666, NULL); + + tst_mkfs(NULL, device, fstype, NULL); + SAFE_MKDIR(cleanup, "mntpoint", DIR_MODE); +} + +static void setup_emlink(void) +{ + if (mount(device, "mntpoint", fstype, 0, NULL) < 0) { + tst_brkm(TBROK | TERRNO, cleanup, + "mount device:%s failed", device); + } + mount_flag = 1; + + SAFE_TOUCH(cleanup, TEST_EMLINK, 0666, NULL); + + link_max = 0; + + while (1) { + sprintf(lname, "%s%ld", BASENAME, ++link_max); + TEST(link(TEST_EMLINK, lname)); + if (TEST_RETURN == -1) { + switch (TEST_ERRNO) { + case EMLINK: + tst_resm(TINFO, "for %s the max links is %ld", + fstype, link_max); + break; + default: + tst_brkm(TBROK | TERRNO, cleanup_emlink, + "Unexpected error: "); + break; + } + break; + } + } +} + +static void cleanup_emlink(void) +{ + long i; + + for (i = 1; i < link_max; i++) { + sprintf(lname, "%s%ld", BASENAME, i); + SAFE_UNLINK(cleanup, lname); + } + + SAFE_UNLINK(cleanup, TEST_EMLINK); + + if (mount_flag && umount("mntpoint") < 0) { + mount_flag = 0; + tst_brkm(TBROK | TERRNO, cleanup, + "umount device:%s failed", device); + } + mount_flag = 0; +} + +static void setup_eacces(void) +{ + SAFE_SETEUID(cleanup, ltpuser->pw_uid); +} + +static void cleanup_eacces(void) +{ + SAFE_SETEUID(cleanup, 0); +} + +static void setup_erofs(void) +{ + if (mount(device, "mntpoint", fstype, MS_RDONLY, NULL) < 0) { + tst_brkm(TBROK | TERRNO, cleanup, + "mount device:%s failed", device); + } + mount_flag = 1; +} + +static void cleanup_erofs(void) +{ + if (mount_flag && umount("mntpoint") < 0) { + mount_flag = 0; + tst_brkm(TBROK | TERRNO, cleanup, + "umount device:%s failed", device); + } + mount_flag = 0; +} + +static void cleanup(void) +{ + TEST_CLEANUP; + + if (mount_flag && umount("mntpoint") < 0) { + tst_brkm(TBROK | TERRNO, NULL, + "umount device:%s failed", device); + } + + tst_rmdir(); +} + +static void help(void) +{ + printf("-T type : specifies the type of filesystem to be mounted. " + "Default ext2.\n"); + printf("-D device : device used for mounting.\n"); +} -- 1.8.4.2 |
From: Zeng L. <zen...@cn...> - 2014-05-14 06:20:36
|
As Shuang Qiu <shu...@or...> reports: * The 32 bit link count in the inode theoretically maxes out at UINT_MAX. * Since the pathconf interface is signed, we use 2^31 - 1 instead. * The old inode format had a 16 bit link count, so its maximum is USHRT_MAX. #define XFS_MAXLINK ((1U << 31) - 1U) #define XFS_MAXLINK_1 65535U We are not able to reach such limitation. If the mntpoint is xfs, we skip the setup for EMLINK and return TCONF in the EMLINK test. Signed-off-by: Zeng Linggang <zen...@cn...> --- testcases/kernel/syscalls/linkat/linkat02.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/testcases/kernel/syscalls/linkat/linkat02.c b/testcases/kernel/syscalls/linkat/linkat02.c index 26a244c..29bc44b 100644 --- a/testcases/kernel/syscalls/linkat/linkat02.c +++ b/testcases/kernel/syscalls/linkat/linkat02.c @@ -36,6 +36,7 @@ #include "linux_syscall_numbers.h" #include "safe_macros.h" #include "lapi/fcntl.h" +#include "tst_fs_type.h" #define DIR_MODE (S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP| \ S_IXGRP|S_IROTH|S_IXOTH) @@ -127,8 +128,15 @@ int main(int ac, char **av) static void linkat_verify(const struct test_struct *desc) { - if (desc->setupfunc != NULL) - desc->setupfunc(); + if (desc->setupfunc != NULL) { + if (desc->setupfunc == setup_emlink && + tst_fs_type(cleanup, "mntpoint") == TST_XFS_MAGIC) { + tst_resm(TCONF, "Test skip XFS filesystem."); + return; + } else { + desc->setupfunc(); + } + } TEST(ltp_syscall(__NR_linkat, AT_FDCWD, desc->oldfname, AT_FDCWD, desc->newfname, desc->flags)); @@ -194,6 +202,9 @@ static void setup(void) SAFE_TOUCH(cleanup, TEST_EMLINK, 0666, NULL); + if (tst_fs_type(cleanup, "mntpoint") == TST_XFS_MAGIC) + return; + while (1) { sprintf(lname, "%s%ld", BASENAME, ++link_max); TEST(link(TEST_EMLINK, lname)); -- 1.8.4.2 |
From: <ch...@su...> - 2014-05-14 16:02:29
|
Hi! I've changed the code to store the fs_type into an variable in setup() rather than calling the function on each iteration and pushed, thanks. -- Cyril Hrubis ch...@su... |
From: Zeng L. <zen...@cn...> - 2014-05-15 01:25:05
|
On Wed, 2014-05-14 at 18:02 +0200, ch...@su... wrote: > Hi! > I've changed the code to store the fs_type into an variable in setup() > rather than calling the function on each iteration and pushed, thanks. > OK. And thank you. :) Best regards, Zeng |
From: <ch...@su...> - 2014-02-24 19:33:20
|
Hi! > Add new error number tests for linkat(2): > * ENAMETOOLONG > * EEXIST > * ELOOP > * EACCES > * EMLINK > * EROFS > > Signed-off-by: Zeng Linggang <zen...@cn...> > --- > runtest/syscalls | 1 + > testcases/kernel/syscalls/.gitignore | 1 + > testcases/kernel/syscalls/linkat/linkat02.c | 296 ++++++++++++++++++++++++++++ > 3 files changed, 298 insertions(+) > create mode 100644 testcases/kernel/syscalls/linkat/linkat02.c > > diff --git a/runtest/syscalls b/runtest/syscalls > index afa7976..4a6b891 100644 > --- a/runtest/syscalls > +++ b/runtest/syscalls > @@ -487,6 +487,7 @@ link07 link07 > > #linkat test cases > linkat01 linkat01 > +linkat02 linkat02 -D DEVICE -T DEVICE_FS_TYPE Please update the entry to the new format. > listen01 listen01 > > diff --git a/testcases/kernel/syscalls/.gitignore b/testcases/kernel/syscalls/.gitignore > index 91cf0f1..d1a8547 100644 > --- a/testcases/kernel/syscalls/.gitignore > +++ b/testcases/kernel/syscalls/.gitignore > @@ -445,6 +445,7 @@ > /link/link06 > /link/link07 > /linkat/linkat01 > +/linkat/linkat02 > /listen/listen01 > /llseek/llseek01 > /llseek/llseek02 > diff --git a/testcases/kernel/syscalls/linkat/linkat02.c b/testcases/kernel/syscalls/linkat/linkat02.c > new file mode 100644 > index 0000000..af5162a > --- /dev/null > +++ b/testcases/kernel/syscalls/linkat/linkat02.c > @@ -0,0 +1,296 @@ > +/* > + * Copyright (c) 2014 Fujitsu Ltd. > + * Author: Zeng Linggang <zen...@cn...> > + * > + * 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. > + * > + * You should have received a copy of the GNU General Public License along > + * with this program. > + */ > +/* > + * Test that linkat() fails and sets the proper errno values. > + */ > + > +#define _GNU_SOURCE > + > +#include <sys/types.h> > +#include <sys/stat.h> > +#include <fcntl.h> > +#include <unistd.h> > +#include <error.h> > +#include <stdlib.h> > +#include <errno.h> > +#include <string.h> > +#include <signal.h> > +#include <pwd.h> > +#include <sys/mount.h> > + > +#include "test.h" > +#include "usctest.h" > +#include "linux_syscall_numbers.h" > +#include "safe_macros.h" > + > +#ifndef AT_FDCWD > +# define AT_FDCWD -100 > +#endif > +#ifndef AT_SYMLINK_FOLLOW > +# define AT_SYMLINK_FOLLOW 0x400 > +#endif Please put these two defines into include/lapi/fcntl.h > +#define DIR_MODE (S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP| \ > + S_IXGRP|S_IROTH|S_IXOTH) > +#define TEST_FILE "testfile" > +#define TEST_EXIST "testexist" > +#define TEST_ELOOP "testeloop" > +#define TEST_EACCES "./tmp/testeeacces" > +#define TEST_EACCES2 "./tmp/testeeacces2" > +#define TEST_EROFS "mntpoint" > +#define TEST_EROFS2 "mntpoint/testerofs2" > +#define TEST_EMLINK "mntpoint/testemlink" > +#define BASENAME "mntpoint/basename" > + > +static long link_max; > +static char lname[PATH_MAX]; > +static char nametoolong[PATH_MAX+2]; > +static char *fstype = "ext2"; > +static char *device; > +static int dflag; > +static int mount_flag; > + > +static void setup(void); > +static void cleanup(void); > + > +static void setup_eacces(void); > +static void setup_erofs(void); > +static void cleanup_erofs(void); > +static void cleanup_eacces(void); > +static void setup_emlink(void); > +static void cleanup_emlink(void); > +static void help(void); > + > +static option_t options[] = { > + {"T:", NULL, &fstype}, > + {"D:", &dflag, &device}, > + {NULL, NULL, NULL} > +}; > + > +static struct test_struct { > + const char *oldfn; > + const char *newfn; This isn't wrong but fn is usually short for function. Perhaps oldfname and newfname would be a bit clearer. > + int flags; > + int expected_errno; > + void (*setupfunc) (); > + void (*cleanfunc) (); > +} test_cases[] = { > + {TEST_FILE, nametoolong, 0, ENAMETOOLONG, NULL, NULL}, > + {nametoolong, TEST_FILE, 0, ENAMETOOLONG, NULL, NULL}, > + {TEST_EXIST, TEST_EXIST, 0, EEXIST, NULL, NULL}, > + {TEST_ELOOP, TEST_FILE, AT_SYMLINK_FOLLOW, ELOOP, NULL, NULL}, > + {TEST_EACCES, TEST_EACCES2, 0, EACCES, setup_eacces, cleanup_eacces}, > + {TEST_EROFS, TEST_EROFS2, 0, EROFS, setup_erofs, cleanup_erofs}, > + {TEST_EMLINK, lname, 0, EMLINK, setup_emlink, cleanup_emlink}, > +}; > + > +char *TCID = "linkat02"; > +int TST_TOTAL = ARRAY_SIZE(test_cases); > + > +static struct passwd *ltpuser; > +static void verify_linkat(struct test_struct *); > + > +static int exp_enos[] = { ENAMETOOLONG, EEXIST, ELOOP, > + EACCES, EROFS, EMLINK, 0 }; > + > +int main(int ac, char **av) > +{ > + int lc; > + char *msg; > + int i; > + > + msg = parse_opts(ac, av, options, help); > + if (msg != NULL) > + tst_brkm(TBROK, NULL, "OPTION PARSING ERROR - %s", msg); > + > + if (!dflag) { You can remove the dflag and use !device instead. > + tst_brkm(TBROK, NULL, > + "you must specify the device used for mounting with " > + "-D option"); > + } > + > + setup(); > + > + TEST_EXP_ENOS(exp_enos); > + > + for (lc = 0; TEST_LOOPING(lc); lc++) { > + > + tst_count = 0; > + > + for (i = 0; i < TST_TOTAL; i++) > + verify_linkat(&test_cases[i]); > + > + } > + > + cleanup(); > + tst_exit(); > +} > + > +static void verify_linkat(struct test_struct *desc) > +{ > + if (desc->setupfunc != NULL) > + desc->setupfunc(); > + > + TEST(ltp_syscall(__NR_linkat, AT_FDCWD, desc->oldfn, > + AT_FDCWD, desc->newfn, desc->flags)); > + > + if (desc->cleanfunc != NULL) > + desc->cleanfunc(); > + > + if (TEST_RETURN != -1) { > + tst_resm(TFAIL, > + "linkat(%s, %s, %s, %s, %d) succeeded unexpectedly", > + "AT_FDCWD", desc->oldfn, > + "AT_FDCWD", desc->newfn, desc->flags); > + return; > + } > + > + if (TEST_ERRNO == desc->expected_errno) { > + tst_resm(TPASS | TTERRNO, "linkat failed as expected"); > + } else { > + tst_resm(TFAIL | TTERRNO, > + "linkat failed unexpectedly; expected: " > + "%d - %s", desc->expected_errno, > + strerror(desc->expected_errno)); > + } > +} > + > +static void setup(void) > +{ > + if ((tst_kvercmp(2, 6, 16)) < 0) > + tst_brkm(TCONF, NULL, "This test needs kernel 2.6.16 or newer"); > + > + tst_sig(NOFORK, DEF_HANDLER, cleanup); > + > + tst_tmpdir(); > + > + TEST_PAUSE; > + > + ltpuser = SAFE_GETPWNAM(cleanup, "nobody"); > + > + SAFE_TOUCH(cleanup, TEST_FILE, 0644, NULL); > + > + memset(nametoolong, 'a', PATH_MAX+1); > + > + SAFE_TOUCH(cleanup, TEST_EXIST, 0644, NULL); > + > + SAFE_SYMLINK(cleanup, TEST_ELOOP, "test_file_eloop2"); > + SAFE_SYMLINK(cleanup, "test_file_eloop2", TEST_ELOOP); > + > + SAFE_MKDIR(cleanup, "./tmp", DIR_MODE); > + SAFE_TOUCH(cleanup, TEST_EACCES, 0666, NULL); > + > + tst_mkfs(NULL, device, fstype, NULL); > + SAFE_MKDIR(cleanup, "mntpoint", DIR_MODE); > +} > + > +static void setup_emlink(void) > +{ > + if (mount(device, "mntpoint", fstype, 0, NULL) < 0) { > + tst_brkm(TBROK | TERRNO, cleanup, > + "mount device:%s failed", device); > + } > + mount_flag = 1; > + > + SAFE_TOUCH(cleanup, TEST_EMLINK, 0666, NULL); > + > + link_max = 0; > + > + while (1) { > + sprintf(lname, "%s%ld", BASENAME, ++link_max); > + TEST(link(TEST_EMLINK, lname)); > + if (TEST_RETURN == -1) { > + switch (TEST_ERRNO) { > + case EMLINK: > + tst_resm(TINFO, "for %s the max links is %ld", > + fstype, link_max); > + break; > + default: > + tst_brkm(TBROK | TERRNO, cleanup_emlink, > + "Unexpected error: "); If we fail here the cleanup that does tst_rmdir() will not be called. What is needed here is another cleanup function that calls the cleanup_emlink() and then the test overall cleanup() > + break; > + } > + break; > + } > + } Do we need to recreate the links in each emlink setup? Can't we just remount the device RW here and RO in the EROFS case? > +} > + > +static void cleanup_emlink(void) > +{ > + long i; > + > + for (i = 1; i < link_max; i++) { > + sprintf(lname, "%s%ld", BASENAME, i); > + SAFE_UNLINK(cleanup, lname); > + } > + > + SAFE_UNLINK(cleanup, TEST_EMLINK); > + > + if (mount_flag && umount("mntpoint") < 0) { > + mount_flag = 0; > + tst_brkm(TBROK | TERRNO, cleanup, > + "umount device:%s failed", device); > + } > + mount_flag = 0; > +} > + > +static void setup_eacces(void) > +{ > + SAFE_SETEUID(cleanup, ltpuser->pw_uid); > +} > + > +static void cleanup_eacces(void) > +{ > + SAFE_SETEUID(cleanup, 0); This would not work unless the test was executed by root. Is tst_require_root(NULL) missing from setup? > +} > + > +static void setup_erofs(void) > +{ > + if (mount(device, "mntpoint", fstype, MS_RDONLY, NULL) < 0) { > + tst_brkm(TBROK | TERRNO, cleanup, > + "mount device:%s failed", device); > + } > + mount_flag = 1; > +} > + > +static void cleanup_erofs(void) > +{ > + if (mount_flag && umount("mntpoint") < 0) { > + mount_flag = 0; > + tst_brkm(TBROK | TERRNO, cleanup, > + "umount device:%s failed", device); > + } > + mount_flag = 0; > +} > + > +static void cleanup(void) > +{ > + TEST_CLEANUP; > + > + if (mount_flag && umount("mntpoint") < 0) { > + tst_brkm(TBROK | TERRNO, NULL, > + "umount device:%s failed", device); Hmm, I would rather use tst_resm(TWARN, ...) here so that the cleanup() will continue to the tst_rmdir() here. Even if the tst_rmdir() is not able to remove all files, it will remove at least some. > + } > + > + tst_rmdir(); > +} > + > +static void help(void) > +{ > + printf("-T type : specifies the type of filesystem to be mounted. " > + "Default ext2.\n"); > + printf("-D device : device used for mounting.\n"); > +} -- Cyril Hrubis ch...@su... |
From: Zeng L. <zen...@cn...> - 2014-02-25 06:32:58
|
Add new error number tests for linkat(2): * ENAMETOOLONG * EEXIST * ELOOP * EACCES * EMLINK * EROFS Signed-off-by: Zeng Linggang <zen...@cn...> --- include/lapi/fcntl.h | 7 + runtest/syscalls | 1 + testcases/kernel/syscalls/.gitignore | 1 + testcases/kernel/syscalls/linkat/linkat02.c | 260 ++++++++++++++++++++++++++++ 4 files changed, 269 insertions(+) create mode 100644 testcases/kernel/syscalls/linkat/linkat02.c diff --git a/include/lapi/fcntl.h b/include/lapi/fcntl.h index f77871f..385bbae 100644 --- a/include/lapi/fcntl.h +++ b/include/lapi/fcntl.h @@ -35,4 +35,11 @@ #define F_GETPIPE_SZ 1032 #endif +#ifndef AT_FDCWD +# define AT_FDCWD -100 +#endif +#ifndef AT_SYMLINK_FOLLOW +# define AT_SYMLINK_FOLLOW 0x400 +#endif + #endif /* __LAPI_FCNTL_H__ */ diff --git a/runtest/syscalls b/runtest/syscalls index 46d63a5..49e3e79 100644 --- a/runtest/syscalls +++ b/runtest/syscalls @@ -492,6 +492,7 @@ link08 link08 -D $LTP_DEV -T $LTP_DEV_FS_TYPE #linkat test cases linkat01 linkat01 +linkat02 linkat02 -D $LTP_DEV -T $LTP_DEV_FS_TYPE listen01 listen01 diff --git a/testcases/kernel/syscalls/.gitignore b/testcases/kernel/syscalls/.gitignore index a5d0a34..75a12ba 100644 --- a/testcases/kernel/syscalls/.gitignore +++ b/testcases/kernel/syscalls/.gitignore @@ -451,6 +451,7 @@ /link/link07 /link/link08 /linkat/linkat01 +/linkat/linkat02 /listen/listen01 /llseek/llseek01 /llseek/llseek02 diff --git a/testcases/kernel/syscalls/linkat/linkat02.c b/testcases/kernel/syscalls/linkat/linkat02.c new file mode 100644 index 0000000..088b9e0 --- /dev/null +++ b/testcases/kernel/syscalls/linkat/linkat02.c @@ -0,0 +1,260 @@ +/* + * Copyright (c) 2014 Fujitsu Ltd. + * Author: Zeng Linggang <zen...@cn...> + * + * 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. + * + * You should have received a copy of the GNU General Public License along + * with this program. + */ +/* + * Test that linkat() fails and sets the proper errno values. + */ + +#define _GNU_SOURCE + +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <unistd.h> +#include <error.h> +#include <stdlib.h> +#include <errno.h> +#include <string.h> +#include <signal.h> +#include <pwd.h> +#include <sys/mount.h> + +#include "test.h" +#include "usctest.h" +#include "linux_syscall_numbers.h" +#include "safe_macros.h" +#include "fcntl.h" + +#define DIR_MODE (S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP| \ + S_IXGRP|S_IROTH|S_IXOTH) +#define TEST_FILE "testfile" +#define TEST_EXIST "testexist" +#define TEST_ELOOP "testeloop" +#define TEST_EACCES "./tmp/testeeacces" +#define TEST_EACCES2 "./tmp/testeeacces2" +#define TEST_EROFS "mntpoint" +#define TEST_EROFS2 "mntpoint/testerofs2" +#define TEST_EMLINK "mntpoint/testemlink" +#define BASENAME "mntpoint/basename" + +static char lname[PATH_MAX]; +static char nametoolong[PATH_MAX+2]; +static char *fstype = "ext2"; +static char *device; +static int mount_flag; + +static void setup(void); +static void cleanup(void); +static void setup_eacces(void); +static void cleanup_eacces(void); +static void setup_erofs(void); +static void setup_emlink(void); +static void help(void); + +static option_t options[] = { + {"T:", NULL, &fstype}, + {"D:", NULL, &device}, + {NULL, NULL, NULL} +}; + +static struct test_struct { + const char *oldfname; + const char *newfname; + int flags; + int expected_errno; + void (*setupfunc) (void); + void (*cleanfunc) (void); +} test_cases[] = { + {TEST_FILE, nametoolong, 0, ENAMETOOLONG, NULL, NULL}, + {nametoolong, TEST_FILE, 0, ENAMETOOLONG, NULL, NULL}, + {TEST_EXIST, TEST_EXIST, 0, EEXIST, NULL, NULL}, + {TEST_ELOOP, TEST_FILE, AT_SYMLINK_FOLLOW, ELOOP, NULL, NULL}, + {TEST_EACCES, TEST_EACCES2, 0, EACCES, setup_eacces, cleanup_eacces}, + {TEST_EROFS, TEST_EROFS2, 0, EROFS, setup_erofs, NULL}, + {TEST_EMLINK, lname, 0, EMLINK, setup_emlink, NULL}, +}; + +char *TCID = "linkat02"; +int TST_TOTAL = ARRAY_SIZE(test_cases); + +static struct passwd *ltpuser; +static void linkat_verify(const struct test_struct *); + +static int exp_enos[] = { ENAMETOOLONG, EEXIST, ELOOP, + EACCES, EROFS, EMLINK, 0 }; + +int main(int ac, char **av) +{ + int lc; + char *msg; + int i; + + msg = parse_opts(ac, av, options, help); + if (msg != NULL) + tst_brkm(TBROK, NULL, "OPTION PARSING ERROR - %s", msg); + + if (!device) { + tst_brkm(TBROK, NULL, + "you must specify the device used for mounting with " + "-D option"); + } + + setup(); + + TEST_EXP_ENOS(exp_enos); + + for (lc = 0; TEST_LOOPING(lc); lc++) { + tst_count = 0; + for (i = 0; i < TST_TOTAL; i++) + linkat_verify(&test_cases[i]); + } + + cleanup(); + tst_exit(); +} + +static void linkat_verify(const struct test_struct *desc) +{ + if (desc->setupfunc != NULL) + desc->setupfunc(); + + TEST(ltp_syscall(__NR_linkat, AT_FDCWD, desc->oldfname, + AT_FDCWD, desc->newfname, desc->flags)); + + if (desc->cleanfunc != NULL) + desc->cleanfunc(); + + if (TEST_RETURN != -1) { + tst_resm(TFAIL, + "linkat(""AT_FDCWD"", %s, ""AT_FDCWD"", %s, %d)" + "succeeded unexpectedly", desc->oldfname, + desc->newfname, desc->flags); + return; + } + + if (TEST_ERRNO == desc->expected_errno) { + tst_resm(TPASS | TTERRNO, "linkat failed as expected"); + } else { + tst_resm(TFAIL | TTERRNO, + "linkat failed unexpectedly; expected: " + "%d - %s", desc->expected_errno, + strerror(desc->expected_errno)); + } +} + +static void setup(void) +{ + long link_max = 0; + + if ((tst_kvercmp(2, 6, 16)) < 0) + tst_brkm(TCONF, NULL, "This test needs kernel 2.6.16 or newer"); + + tst_require_root(NULL); + + tst_sig(NOFORK, DEF_HANDLER, cleanup); + + tst_tmpdir(); + + TEST_PAUSE; + + ltpuser = SAFE_GETPWNAM(cleanup, "nobody"); + + SAFE_TOUCH(cleanup, TEST_FILE, 0644, NULL); + + memset(nametoolong, 'a', PATH_MAX+1); + + SAFE_TOUCH(cleanup, TEST_EXIST, 0644, NULL); + + SAFE_SYMLINK(cleanup, TEST_ELOOP, "test_file_eloop2"); + SAFE_SYMLINK(cleanup, "test_file_eloop2", TEST_ELOOP); + + SAFE_MKDIR(cleanup, "./tmp", DIR_MODE); + SAFE_TOUCH(cleanup, TEST_EACCES, 0666, NULL); + + tst_mkfs(NULL, device, fstype, NULL); + SAFE_MKDIR(cleanup, "mntpoint", DIR_MODE); + + if (mount(device, "mntpoint", fstype, 0, NULL) < 0) { + tst_brkm(TBROK | TERRNO, cleanup, + "mount device:%s failed", device); + } + mount_flag = 1; + + SAFE_TOUCH(cleanup, TEST_EMLINK, 0666, NULL); + + while (1) { + sprintf(lname, "%s%ld", BASENAME, ++link_max); + TEST(link(TEST_EMLINK, lname)); + if (TEST_RETURN == -1) { + switch (TEST_ERRNO) { + case EMLINK: + tst_resm(TINFO, "for %s the max links is %ld", + fstype, link_max); + break; + default: + tst_brkm(TBROK | TTERRNO, cleanup, + "Unexpected error: "); + break; + } + break; + } + } +} + +static void setup_emlink(void) +{ + if (mount(device, "mntpoint", fstype, MS_REMOUNT, NULL) < 0) { + tst_brkm(TBROK | TERRNO, cleanup, + "remount device:%s failed", device); + } + mount_flag = 1; +} + +static void setup_eacces(void) +{ + SAFE_SETEUID(cleanup, ltpuser->pw_uid); +} + +static void cleanup_eacces(void) +{ + SAFE_SETEUID(cleanup, 0); +} + +static void setup_erofs(void) +{ + if (mount(device, "mntpoint", fstype, + MS_REMOUNT | MS_RDONLY, NULL) < 0) { + tst_brkm(TBROK | TERRNO, cleanup, "remount device:%s failed", + device); + } + mount_flag = 1; +} + +static void cleanup(void) +{ + TEST_CLEANUP; + + if (mount_flag && umount("mntpoint") < 0) + tst_resm(TWARN | TERRNO, "umount device:%s failed", device); + + tst_rmdir(); +} + +static void help(void) +{ + printf("-T type : specifies the type of filesystem to be mounted. " + "Default ext2.\n"); + printf("-D device : device used for mounting.\n"); +} -- 1.8.4.2 |
From: <ch...@su...> - 2014-02-25 12:53:18
|
Hi! > +#include "test.h" > +#include "usctest.h" > +#include "linux_syscall_numbers.h" > +#include "safe_macros.h" > +#include "fcntl.h" I've changed this to "lapi/fcntl.h". Note that ../../../../include/lapi/ is not passed to the compiler as -I so the lapi/fcntl.h is not found and this include defaults to /usr/include/fcntl.h (because /usr/include/ is is in the default search path). Pushed, thanks. -- Cyril Hrubis ch...@su... |
From: Zeng L. <zen...@cn...> - 2014-02-26 01:32:07
|
On Tue, 2014-02-25 at 13:53 +0100, ch...@su... wrote: > Hi! > > +#include "test.h" > > +#include "usctest.h" > > +#include "linux_syscall_numbers.h" > > +#include "safe_macros.h" > > +#include "fcntl.h" > > I've changed this to "lapi/fcntl.h". Note that ../../../../include/lapi/ > is not passed to the compiler as -I so the lapi/fcntl.h is not found and > this include defaults to /usr/include/fcntl.h (because /usr/include/ is > is in the default search path). > OK, and thank you very much. Best regards, Zeng > > Pushed, thanks. > |
From: Shuang Q. <shu...@or...> - 2014-05-06 08:54:26
|
Hello, On 02/25/2014 02:26 PM, Zeng Linggang wrote: > + > + SAFE_TOUCH(cleanup, TEST_EMLINK, 0666, NULL); > + > + while (1) { > + sprintf(lname, "%s%ld", BASENAME, ++link_max); > + TEST(link(TEST_EMLINK, lname)); > + if (TEST_RETURN == -1) { > + switch (TEST_ERRNO) { > + case EMLINK: > + tst_resm(TINFO, "for %s the max links is %ld", > + fstype, link_max); > + break; > + default: > + tst_brkm(TBROK | TTERRNO, cleanup, > + "Unexpected error: "); > + break; > + } > + break; > + } > + } > +} > Should it give a limit max number here when test EMLINK to handler the filesystems which unlimited link count. AFAIK,it use 2^31 - 1 with xfs: /* * The 32 bit link count in the inode theoretically maxes out at UINT_MAX. * Since the pathconf interface is signed, we use 2^31 - 1 instead. * The old inode format had a 16 bit link count, so its maximum is USHRT_MAX. */ #define XFS_MAXLINK ((1U << 31) - 1U) #define XFS_MAXLINK_1 65535U We are not able to reach such limitation. Thanks Shuang |
From: Xiaoguang W. <wan...@cn...> - 2014-05-06 10:04:12
|
Hi, On 05/06/2014 04:54 PM, Shuang Qiu wrote: > Hello, > On 02/25/2014 02:26 PM, Zeng Linggang wrote: >> + >> + SAFE_TOUCH(cleanup, TEST_EMLINK, 0666, NULL); >> + >> + while (1) { >> + sprintf(lname, "%s%ld", BASENAME, ++link_max); >> + TEST(link(TEST_EMLINK, lname)); >> + if (TEST_RETURN == -1) { >> + switch (TEST_ERRNO) { >> + case EMLINK: >> + tst_resm(TINFO, "for %s the max links is %ld", >> + fstype, link_max); >> + break; >> + default: >> + tst_brkm(TBROK | TTERRNO, cleanup, >> + "Unexpected error: "); >> + break; >> + } >> + break; >> + } >> + } >> +} >> > Should it give a limit max number here when test EMLINK to handler the > filesystems which unlimited link count. > AFAIK,it use 2^31 - 1 with xfs: > /* > * The 32 bit link count in the inode theoretically maxes out at UINT_MAX. > * Since the pathconf interface is signed, we use 2^31 - 1 instead. > * The old inode format had a 16 bit link count, so its maximum is > USHRT_MAX. > */ > #define XFS_MAXLINK ((1U << 31) - 1U) > #define XFS_MAXLINK_1 65535U > > We are not able to reach such limitation. Yeah, I think so. Or we should make the file system hard coded to ext2/3/4. Regards, Xiaoguang Wang > > Thanks > Shuang > > ------------------------------------------------------------------------------ > Is your legacy SCM system holding you back? Join Perforce May 7 to find out: > • 3 signs your SCM is hindering your productivity > • Requirements for releasing software faster > • Expert tips and advice for migrating your SCM now > http://p.sf.net/sfu/perforce > _______________________________________________ > Ltp-list mailing list > Ltp...@li... > https://lists.sourceforge.net/lists/listinfo/ltp-list > |
From: <ch...@su...> - 2014-05-06 14:48:39
|
Hi! > > + > > + SAFE_TOUCH(cleanup, TEST_EMLINK, 0666, NULL); > > + > > + while (1) { > > + sprintf(lname, "%s%ld", BASENAME, ++link_max); > > + TEST(link(TEST_EMLINK, lname)); > > + if (TEST_RETURN == -1) { > > + switch (TEST_ERRNO) { > > + case EMLINK: > > + tst_resm(TINFO, "for %s the max links is %ld", > > + fstype, link_max); > > + break; > > + default: > > + tst_brkm(TBROK | TTERRNO, cleanup, > > + "Unexpected error: "); > > + break; > > + } > > + break; > > + } > > + } > > +} > > > Should it give a limit max number here when test EMLINK to handler the > filesystems which unlimited link count. > AFAIK,it use 2^31 - 1 with xfs: > /* > * The 32 bit link count in the inode theoretically maxes out at UINT_MAX. > * Since the pathconf interface is signed, we use 2^31 - 1 instead. > * The old inode format had a 16 bit link count, so its maximum is > USHRT_MAX. > */ > #define XFS_MAXLINK ((1U << 31) - 1U) > #define XFS_MAXLINK_1 65535U > > We are not able to reach such limitation. If xfs has no limit or not reachable limit on number of links we should skip the setup for EMLINK and return TCONF in the EMLINK test if xfs filesystem is used. -- Cyril Hrubis ch...@su... |
From: Zeng L. <zen...@cn...> - 2014-05-07 08:11:51
|
Signed-off-by: Zeng Linggang <zen...@cn...> --- include/tst_fs_type.h | 1 + lib/tst_fs_type.c | 2 ++ 2 files changed, 3 insertions(+) diff --git a/include/tst_fs_type.h b/include/tst_fs_type.h index 92b7120..44367b0 100644 --- a/include/tst_fs_type.h +++ b/include/tst_fs_type.h @@ -32,6 +32,7 @@ #define TST_RAMFS_MAGIC 0x858458f6 #define TST_TMPFS_MAGIC 0x01021994 #define TST_V9FS_MAGIC 0x01021997 +#define TST_XFS_MAGIC 0x58465342 /* * Returns filesystem magick for a given path. diff --git a/lib/tst_fs_type.c b/lib/tst_fs_type.c index 4805bac..b1a3675 100644 --- a/lib/tst_fs_type.c +++ b/lib/tst_fs_type.c @@ -55,6 +55,8 @@ const char *tst_fs_type_name(long f_type) return "RAMFS"; case TST_BTRFS_MAGIC: return "BTRFS"; + case TST_XFS_MAGIC: + return "XFS"; default: return "Unknown"; } -- 1.8.4.2 |
From: Zeng L. <zen...@cn...> - 2014-05-07 08:13:14
|
As Shuang Qiu <shu...@or...> reports: * The 32 bit link count in the inode theoretically maxes out at UINT_MAX. * Since the pathconf interface is signed, we use 2^31 - 1 instead. * The old inode format had a 16 bit link count, so its maximum is USHRT_MAX. #define XFS_MAXLINK ((1U << 31) - 1U) #define XFS_MAXLINK_1 65535U We are not able to reach such limitation. If it cant't reach the max links, return TCONF in the EMLINK test. Signed-off-by: Zeng Linggang <zen...@cn...> --- testcases/kernel/syscalls/linkat/linkat02.c | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/testcases/kernel/syscalls/linkat/linkat02.c b/testcases/kernel/syscalls/linkat/linkat02.c index 26a244c..21119a5 100644 --- a/testcases/kernel/syscalls/linkat/linkat02.c +++ b/testcases/kernel/syscalls/linkat/linkat02.c @@ -54,6 +54,7 @@ static char nametoolong[PATH_MAX+2]; static char *fstype = "ext2"; static char *device; static int mount_flag; +static int emlink_flag; static void setup(void); static void cleanup(void); @@ -127,8 +128,15 @@ int main(int ac, char **av) static void linkat_verify(const struct test_struct *desc) { - if (desc->setupfunc != NULL) - desc->setupfunc(); + if (desc->setupfunc != NULL) { + if (desc->setupfunc == setup_emlink && emlink_flag == 1) { + tst_resm(TCONF, "We can't reach the max links for %s", + fstype); + return; + } else { + desc->setupfunc(); + } + } TEST(ltp_syscall(__NR_linkat, AT_FDCWD, desc->oldfname, AT_FDCWD, desc->newfname, desc->flags)); @@ -204,8 +212,10 @@ static void setup(void) fstype, link_max); break; default: - tst_brkm(TBROK | TTERRNO, cleanup, - "Unexpected error: "); + emlink_flag = 1; + tst_resm(TINFO | TTERRNO, + "for %s we can't reach the max links", + fstype); break; } break; -- 1.8.4.2 |
From: <ch...@su...> - 2014-05-07 12:28:14
|
Hi! > static void setup(void); > static void cleanup(void); > @@ -127,8 +128,15 @@ int main(int ac, char **av) > > static void linkat_verify(const struct test_struct *desc) > { > - if (desc->setupfunc != NULL) > - desc->setupfunc(); > + if (desc->setupfunc != NULL) { > + if (desc->setupfunc == setup_emlink && emlink_flag == 1) { > + tst_resm(TCONF, "We can't reach the max links for %s", > + fstype); > + return; > + } else { > + desc->setupfunc(); > + } > + } > > TEST(ltp_syscall(__NR_linkat, AT_FDCWD, desc->oldfname, > AT_FDCWD, desc->newfname, desc->flags)); > @@ -204,8 +212,10 @@ static void setup(void) > fstype, link_max); > break; > default: > - tst_brkm(TBROK | TTERRNO, cleanup, > - "Unexpected error: "); > + emlink_flag = 1; > + tst_resm(TINFO | TTERRNO, > + "for %s we can't reach the max links", What errno do we get here instead of the EMLINK? -- Cyril Hrubis ch...@su... |
From: Zeng L. <zen...@cn...> - 2014-05-08 02:48:51
|
On Wed, 2014-05-07 at 14:27 +0200, ch...@su... wrote: > > @@ -204,8 +212,10 @@ static void setup(void) > > fstype, link_max); > > break; > > default: > > - tst_brkm(TBROK | TTERRNO, cleanup, > > - "Unexpected error: "); > > + emlink_flag = 1; > > + tst_resm(TINFO | TTERRNO, > > + "for %s we can't reach the max links", > > What errno do we get here instead of the EMLINK? > When I test for xfs, it is ENOSPC. Best regards, Zeng |
From: <ch...@su...> - 2014-05-13 11:47:32
|
Hi! > > > fstype, link_max); > > > break; > > > default: > > > - tst_brkm(TBROK | TTERRNO, cleanup, > > > - "Unexpected error: "); > > > + emlink_flag = 1; > > > + tst_resm(TINFO | TTERRNO, > > > + "for %s we can't reach the max links", > > > > What errno do we get here instead of the EMLINK? > > > > When I test for xfs, it is ENOSPC. Hmm, looking at the test, what likely happens is that the loopback device is filled full with links. What will happen if you create much bigger device? If there is no limit on number of links the link_max will likely will overflow and the link() will fail with EEXIST instead. I still think that it would be much more straightforward to set the emlink_flag if you are on XFS. Or is there any problem with this? -- Cyril Hrubis ch...@su... |
From: Zeng L. <zen...@cn...> - 2014-05-14 06:26:21
|
On Tue, 2014-05-13 at 13:46 +0200, ch...@su... wrote: > Hi! > > > > fstype, link_max); > > > > break; > > > > default: > > > > - tst_brkm(TBROK | TTERRNO, cleanup, > > > > - "Unexpected error: "); > > > > + emlink_flag = 1; > > > > + tst_resm(TINFO | TTERRNO, > > > > + "for %s we can't reach the max links", > > > > > > What errno do we get here instead of the EMLINK? > > > > > > > When I test for xfs, it is ENOSPC. > > Hmm, looking at the test, what likely happens is that the loopback > device is filled full with links. What will happen if you create much > bigger device? If there is no limit on number of links the link_max will > likely will overflow and the link() will fail with EEXIST instead. > Yes, link_max will overflow and the it fail with EEXIST. > I still think that it would be much more straightforward to set the > emlink_flag if you are on XFS. Or is there any problem with this? > I have write a new PATCH to you. It will skip EMLINK test if it is XFS. And thank you for your prompt. Best regards, Zeng |