* [PATCH v9 1/2] fsstress: add mwrite/mread into test operation list
@ 2017-03-28 8:46 Zorro Lang
2017-03-28 8:46 ` [PATCH v9 2/2] xfs/068: update golden output due to new operations in fsstress Zorro Lang
2017-03-28 9:08 ` [PATCH v9 1/2] fsstress: add mwrite/mread into test operation list Zorro Lang
0 siblings, 2 replies; 3+ messages in thread
From: Zorro Lang @ 2017-03-28 8:46 UTC (permalink / raw)
To: fstests; +Cc: linux-xfs
mmap as a popular and basic operation, most of softwares use it to
access files. More and more customers report bugs related with
mmap/munmap and other stress conditions.
So add mmap read/write test into fsstress to increase mmap related
stress to reproduce or find more bugs easily.
Signed-off-by: Zorro Lang <zlang@redhat.com>
---
configure.ac | 1 +
ltp/fsstress.c | 159 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
src/global.h | 4 ++
3 files changed, 162 insertions(+), 2 deletions(-)
diff --git a/configure.ac b/configure.ac
index fa48d2f..246f92e 100644
--- a/configure.ac
+++ b/configure.ac
@@ -32,6 +32,7 @@ AC_HEADER_STDC
xfs/platform_defs.h \
btrfs/ioctl.h \
cifs/ioctl.h \
+ sys/mman.h \
])
AC_CHECK_HEADERS([xfs/xfs_log_format.h],,,[
diff --git a/ltp/fsstress.c b/ltp/fsstress.c
index 7e7cf60..6d8f117 100644
--- a/ltp/fsstress.c
+++ b/ltp/fsstress.c
@@ -17,6 +17,7 @@
*/
#include <linux/fs.h>
+#include <setjmp.h>
#include "global.h"
#ifdef HAVE_ATTR_XATTR_H
@@ -69,6 +70,8 @@ typedef enum {
OP_LINK,
OP_MKDIR,
OP_MKNOD,
+ OP_MREAD,
+ OP_MWRITE,
OP_PUNCH,
OP_ZERO,
OP_COLLAPSE,
@@ -168,6 +171,8 @@ void getdents_f(int, long);
void link_f(int, long);
void mkdir_f(int, long);
void mknod_f(int, long);
+void mread_f(int, long);
+void mwrite_f(int, long);
void punch_f(int, long);
void zero_f(int, long);
void collapse_f(int, long);
@@ -208,6 +213,8 @@ opdesc_t ops[] = {
{ OP_LINK, "link", link_f, 1, 1 },
{ OP_MKDIR, "mkdir", mkdir_f, 2, 1 },
{ OP_MKNOD, "mknod", mknod_f, 2, 1 },
+ { OP_MREAD, "mread", mread_f, 2, 0 },
+ { OP_MWRITE, "mwrite", mwrite_f, 2, 1 },
{ OP_PUNCH, "punch", punch_f, 1, 1 },
{ OP_ZERO, "zero", zero_f, 1, 1 },
{ OP_COLLAPSE, "collapse", collapse_f, 1, 1 },
@@ -262,6 +269,7 @@ int cleanup = 0;
int verbose = 0;
int verifiable_log = 0;
sig_atomic_t should_stop = 0;
+sigjmp_buf *sigbus_jmp = NULL;
char *execute_cmd = NULL;
int execute_freq = 1;
struct print_string flag_str = {0};
@@ -311,7 +319,26 @@ void zero_freq(void);
void sg_handler(int signum)
{
- should_stop = 1;
+ switch (signum) {
+ case SIGTERM:
+ should_stop = 1;
+ break;
+ case SIGBUS:
+ /*
+ * Only handle SIGBUS when mmap write to a hole and no
+ * block can be allocated due to ENOSPC, abort otherwise.
+ */
+ if (sigbus_jmp) {
+ siglongjmp(*sigbus_jmp, -1);
+ } else {
+ printf("Unknown SIGBUS is caught, Abort!\n");
+ abort();
+ }
+ /* should not reach here */
+ break;
+ default:
+ break;
+ }
}
int main(int argc, char **argv)
@@ -527,10 +554,13 @@ int main(int argc, char **argv)
for (i = 0; i < nproc; i++) {
if (fork() == 0) {
- action.sa_handler = SIG_DFL;
sigemptyset(&action.sa_mask);
+ action.sa_handler = SIG_DFL;
if (sigaction(SIGTERM, &action, 0))
return 1;
+ action.sa_handler = sg_handler;
+ if (sigaction(SIGBUS, &action, 0))
+ return 1;
#ifdef HAVE_SYS_PRCTL_H
prctl(PR_SET_PDEATHSIG, SIGKILL);
if (getppid() == 1) /* parent died already? */
@@ -2655,6 +2685,131 @@ mknod_f(int opno, long r)
free_pathname(&f);
}
+#ifdef HAVE_SYS_MMAN_H
+struct print_flags mmap_flags[] = {
+ { MAP_SHARED, "SHARED"},
+ { MAP_PRIVATE, "PRIVATE"},
+ { -1, NULL}
+};
+
+#define translate_mmap_flags(flags) \
+ ({translate_flags(flags, "|", mmap_flags);})
+#endif
+
+void
+do_mmap(int opno, long r, int prot)
+{
+#ifdef HAVE_SYS_MMAN_H
+ char *addr;
+ int e;
+ pathname_t f;
+ int fd;
+ size_t len;
+ __int64_t lr;
+ off64_t off;
+ int flags;
+ struct stat64 stb;
+ int v;
+ char st[1024];
+ sigjmp_buf sigbus_jmpbuf;
+
+ init_pathname(&f);
+ if (!get_fname(FT_REGFILE, r, &f, NULL, NULL, &v)) {
+ if (v)
+ printf("%d/%d: do_mmap - no filename\n", procid, opno);
+ free_pathname(&f);
+ return;
+ }
+ fd = open_path(&f, O_RDWR);
+ e = fd < 0 ? errno : 0;
+ check_cwd();
+ if (fd < 0) {
+ if (v)
+ printf("%d/%d: do_mmap - open %s failed %d\n",
+ procid, opno, f.path, e);
+ free_pathname(&f);
+ return;
+ }
+ if (fstat64(fd, &stb) < 0) {
+ if (v)
+ printf("%d/%d: do_mmap - fstat64 %s failed %d\n",
+ procid, opno, f.path, errno);
+ free_pathname(&f);
+ close(fd);
+ return;
+ }
+ inode_info(st, sizeof(st), &stb, v);
+ if (stb.st_size == 0) {
+ if (v)
+ printf("%d/%d: do_mmap - %s%s zero size\n", procid, opno,
+ f.path, st);
+ free_pathname(&f);
+ close(fd);
+ return;
+ }
+
+ lr = ((__int64_t)random() << 32) + random();
+ off = (off64_t)(lr % stb.st_size);
+ off &= (off64_t)(~(sysconf(_SC_PAGE_SIZE) - 1));
+ len = (size_t)(random() % MIN(stb.st_size - off, FILELEN_MAX)) + 1;
+
+ flags = (random() % 2) ? MAP_SHARED : MAP_PRIVATE;
+ addr = mmap(NULL, len, prot, flags, fd, off);
+ e = (addr == MAP_FAILED) ? errno : 0;
+ if (e) {
+ if (v)
+ printf("%d/%d: do_mmap - mmap failed %s%s [%lld,%d,%s] %d\n",
+ procid, opno, f.path, st, (long long)off,
+ (int)len, translate_mmap_flags(flags), e);
+ free_pathname(&f);
+ close(fd);
+ return;
+ }
+
+ if (prot & PROT_WRITE) {
+ if ((e = sigsetjmp(sigbus_jmpbuf, 1)) == 0) {
+ sigbus_jmp = &sigbus_jmpbuf;
+ memset(addr, nameseq & 0xff, len);
+ }
+ } else {
+ char *buf;
+ if ((buf = malloc(len)) != NULL) {
+ memcpy(buf, addr, len);
+ free(buf);
+ }
+ }
+ munmap(addr, len);
+ /* set NULL to stop other functions from doing siglongjmp */
+ sigbus_jmp = NULL;
+
+ if (v)
+ printf("%d/%d: %s %s%s [%lld,%d,%s] %s\n",
+ procid, opno, (prot & PROT_WRITE) ? "mwrite" : "mread",
+ f.path, st, (long long)off, (int)len,
+ translate_mmap_flags(flags),
+ (e == 0) ? "0" : "Bus error");
+
+ free_pathname(&f);
+ close(fd);
+#endif
+}
+
+void
+mread_f(int opno, long r)
+{
+#ifdef HAVE_SYS_MMAN_H
+ do_mmap(opno, r, PROT_READ);
+#endif
+}
+
+void
+mwrite_f(int opno, long r)
+{
+#ifdef HAVE_SYS_MMAN_H
+ do_mmap(opno, r, PROT_WRITE);
+#endif
+}
+
void
punch_f(int opno, long r)
{
diff --git a/src/global.h b/src/global.h
index f63246b..3920c0d 100644
--- a/src/global.h
+++ b/src/global.h
@@ -178,4 +178,8 @@
#endif /* HAVE_LINUX_FALLOC_H */
+#ifdef HAVE_SYS_MMAN_H
+#include <sys/mman.h>
+#endif
+
#endif /* GLOBAL_H */
--
2.7.4
^ permalink raw reply related [flat|nested] 3+ messages in thread
* [PATCH v9 2/2] xfs/068: update golden output due to new operations in fsstress
2017-03-28 8:46 [PATCH v9 1/2] fsstress: add mwrite/mread into test operation list Zorro Lang
@ 2017-03-28 8:46 ` Zorro Lang
2017-03-28 9:08 ` [PATCH v9 1/2] fsstress: add mwrite/mread into test operation list Zorro Lang
1 sibling, 0 replies; 3+ messages in thread
From: Zorro Lang @ 2017-03-28 8:46 UTC (permalink / raw)
To: fstests; +Cc: linux-xfs
xfs/068 use a fixed seed (-s) and number of operations (-n) to run
fsstress, to get fixed number of files and directories. But new
operations of fsstress will break this "fixed number". So update
it, after fsstress get new operations.
Signed-off-by: Zorro Lang <zlang@redhat.com>
---
tests/xfs/068 | 2 --
tests/xfs/068.out | 2 +-
2 files changed, 1 insertion(+), 3 deletions(-)
diff --git a/tests/xfs/068 b/tests/xfs/068
index 4dac95e..7151e28 100755
--- a/tests/xfs/068
+++ b/tests/xfs/068
@@ -43,8 +43,6 @@ trap "rm -rf $tmp.*; exit \$status" 0 1 2 3 15
_supported_fs xfs
_supported_os Linux
-# need to ensure new fsstress operations don't perturb expected output
-FSSTRESS_AVOID="-f insert=0 $FSSTRESS_AVOID"
_create_dumpdir_stress_num 4096
_do_dump_restore
diff --git a/tests/xfs/068.out b/tests/xfs/068.out
index 2196eee..b20604f 100644
--- a/tests/xfs/068.out
+++ b/tests/xfs/068.out
@@ -22,7 +22,7 @@ xfsrestore: session id: ID
xfsrestore: media ID: ID
xfsrestore: searching media for directory dump
xfsrestore: reading directories
-xfsrestore: 495 directories and 1593 entries processed
+xfsrestore: 474 directories and 1592 entries processed
xfsrestore: directory post-processing
xfsrestore: restoring non-directory files
xfsrestore: restore complete: SECS seconds elapsed
--
2.7.4
^ permalink raw reply related [flat|nested] 3+ messages in thread
* Re: [PATCH v9 1/2] fsstress: add mwrite/mread into test operation list
2017-03-28 8:46 [PATCH v9 1/2] fsstress: add mwrite/mread into test operation list Zorro Lang
2017-03-28 8:46 ` [PATCH v9 2/2] xfs/068: update golden output due to new operations in fsstress Zorro Lang
@ 2017-03-28 9:08 ` Zorro Lang
1 sibling, 0 replies; 3+ messages in thread
From: Zorro Lang @ 2017-03-28 9:08 UTC (permalink / raw)
To: fstests; +Cc: linux-xfs
On Tue, Mar 28, 2017 at 04:46:34PM +0800, Zorro Lang wrote:
> mmap as a popular and basic operation, most of softwares use it to
> access files. More and more customers report bugs related with
> mmap/munmap and other stress conditions.
>
> So add mmap read/write test into fsstress to increase mmap related
> stress to reproduce or find more bugs easily.
>
> Signed-off-by: Zorro Lang <zlang@redhat.com>
> ---
Hi,
Sorry I forgot to write changelog.
Thanks Eryu found a problem by run g/270 and give me more suggestions.
When filesystem is filled, mwrite a hole of sparse file will hit
ENOSPC, and will trigger SIGBUS which will kill running process and
core dump.
So V9 add SIGBUS handler. Use sigsetjmp() before mwrite a mapped
memory, and siglongjmp() back to sigsetjmp() place from signal
handler. If siglongjmp() from a non-zero, print "Bus error".
To stop SIGBUS from other functions cause a endless loop (trigger
SIGBUS over and over ...), abort() the process if an unknown
SIGBUS is triggered.
generic/270 and xfs/068 test passed by merge this V9 patchset.
Thanks,
Zorro
> configure.ac | 1 +
> ltp/fsstress.c | 159 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
> src/global.h | 4 ++
> 3 files changed, 162 insertions(+), 2 deletions(-)
>
> diff --git a/configure.ac b/configure.ac
> index fa48d2f..246f92e 100644
> --- a/configure.ac
> +++ b/configure.ac
> @@ -32,6 +32,7 @@ AC_HEADER_STDC
> xfs/platform_defs.h \
> btrfs/ioctl.h \
> cifs/ioctl.h \
> + sys/mman.h \
> ])
>
> AC_CHECK_HEADERS([xfs/xfs_log_format.h],,,[
> diff --git a/ltp/fsstress.c b/ltp/fsstress.c
> index 7e7cf60..6d8f117 100644
> --- a/ltp/fsstress.c
> +++ b/ltp/fsstress.c
> @@ -17,6 +17,7 @@
> */
>
> #include <linux/fs.h>
> +#include <setjmp.h>
> #include "global.h"
>
> #ifdef HAVE_ATTR_XATTR_H
> @@ -69,6 +70,8 @@ typedef enum {
> OP_LINK,
> OP_MKDIR,
> OP_MKNOD,
> + OP_MREAD,
> + OP_MWRITE,
> OP_PUNCH,
> OP_ZERO,
> OP_COLLAPSE,
> @@ -168,6 +171,8 @@ void getdents_f(int, long);
> void link_f(int, long);
> void mkdir_f(int, long);
> void mknod_f(int, long);
> +void mread_f(int, long);
> +void mwrite_f(int, long);
> void punch_f(int, long);
> void zero_f(int, long);
> void collapse_f(int, long);
> @@ -208,6 +213,8 @@ opdesc_t ops[] = {
> { OP_LINK, "link", link_f, 1, 1 },
> { OP_MKDIR, "mkdir", mkdir_f, 2, 1 },
> { OP_MKNOD, "mknod", mknod_f, 2, 1 },
> + { OP_MREAD, "mread", mread_f, 2, 0 },
> + { OP_MWRITE, "mwrite", mwrite_f, 2, 1 },
> { OP_PUNCH, "punch", punch_f, 1, 1 },
> { OP_ZERO, "zero", zero_f, 1, 1 },
> { OP_COLLAPSE, "collapse", collapse_f, 1, 1 },
> @@ -262,6 +269,7 @@ int cleanup = 0;
> int verbose = 0;
> int verifiable_log = 0;
> sig_atomic_t should_stop = 0;
> +sigjmp_buf *sigbus_jmp = NULL;
> char *execute_cmd = NULL;
> int execute_freq = 1;
> struct print_string flag_str = {0};
> @@ -311,7 +319,26 @@ void zero_freq(void);
>
> void sg_handler(int signum)
> {
> - should_stop = 1;
> + switch (signum) {
> + case SIGTERM:
> + should_stop = 1;
> + break;
> + case SIGBUS:
> + /*
> + * Only handle SIGBUS when mmap write to a hole and no
> + * block can be allocated due to ENOSPC, abort otherwise.
> + */
> + if (sigbus_jmp) {
> + siglongjmp(*sigbus_jmp, -1);
> + } else {
> + printf("Unknown SIGBUS is caught, Abort!\n");
> + abort();
> + }
> + /* should not reach here */
> + break;
> + default:
> + break;
> + }
> }
>
> int main(int argc, char **argv)
> @@ -527,10 +554,13 @@ int main(int argc, char **argv)
>
> for (i = 0; i < nproc; i++) {
> if (fork() == 0) {
> - action.sa_handler = SIG_DFL;
> sigemptyset(&action.sa_mask);
> + action.sa_handler = SIG_DFL;
> if (sigaction(SIGTERM, &action, 0))
> return 1;
> + action.sa_handler = sg_handler;
> + if (sigaction(SIGBUS, &action, 0))
> + return 1;
> #ifdef HAVE_SYS_PRCTL_H
> prctl(PR_SET_PDEATHSIG, SIGKILL);
> if (getppid() == 1) /* parent died already? */
> @@ -2655,6 +2685,131 @@ mknod_f(int opno, long r)
> free_pathname(&f);
> }
>
> +#ifdef HAVE_SYS_MMAN_H
> +struct print_flags mmap_flags[] = {
> + { MAP_SHARED, "SHARED"},
> + { MAP_PRIVATE, "PRIVATE"},
> + { -1, NULL}
> +};
> +
> +#define translate_mmap_flags(flags) \
> + ({translate_flags(flags, "|", mmap_flags);})
> +#endif
> +
> +void
> +do_mmap(int opno, long r, int prot)
> +{
> +#ifdef HAVE_SYS_MMAN_H
> + char *addr;
> + int e;
> + pathname_t f;
> + int fd;
> + size_t len;
> + __int64_t lr;
> + off64_t off;
> + int flags;
> + struct stat64 stb;
> + int v;
> + char st[1024];
> + sigjmp_buf sigbus_jmpbuf;
> +
> + init_pathname(&f);
> + if (!get_fname(FT_REGFILE, r, &f, NULL, NULL, &v)) {
> + if (v)
> + printf("%d/%d: do_mmap - no filename\n", procid, opno);
> + free_pathname(&f);
> + return;
> + }
> + fd = open_path(&f, O_RDWR);
> + e = fd < 0 ? errno : 0;
> + check_cwd();
> + if (fd < 0) {
> + if (v)
> + printf("%d/%d: do_mmap - open %s failed %d\n",
> + procid, opno, f.path, e);
> + free_pathname(&f);
> + return;
> + }
> + if (fstat64(fd, &stb) < 0) {
> + if (v)
> + printf("%d/%d: do_mmap - fstat64 %s failed %d\n",
> + procid, opno, f.path, errno);
> + free_pathname(&f);
> + close(fd);
> + return;
> + }
> + inode_info(st, sizeof(st), &stb, v);
> + if (stb.st_size == 0) {
> + if (v)
> + printf("%d/%d: do_mmap - %s%s zero size\n", procid, opno,
> + f.path, st);
> + free_pathname(&f);
> + close(fd);
> + return;
> + }
> +
> + lr = ((__int64_t)random() << 32) + random();
> + off = (off64_t)(lr % stb.st_size);
> + off &= (off64_t)(~(sysconf(_SC_PAGE_SIZE) - 1));
> + len = (size_t)(random() % MIN(stb.st_size - off, FILELEN_MAX)) + 1;
> +
> + flags = (random() % 2) ? MAP_SHARED : MAP_PRIVATE;
> + addr = mmap(NULL, len, prot, flags, fd, off);
> + e = (addr == MAP_FAILED) ? errno : 0;
> + if (e) {
> + if (v)
> + printf("%d/%d: do_mmap - mmap failed %s%s [%lld,%d,%s] %d\n",
> + procid, opno, f.path, st, (long long)off,
> + (int)len, translate_mmap_flags(flags), e);
> + free_pathname(&f);
> + close(fd);
> + return;
> + }
> +
> + if (prot & PROT_WRITE) {
> + if ((e = sigsetjmp(sigbus_jmpbuf, 1)) == 0) {
> + sigbus_jmp = &sigbus_jmpbuf;
> + memset(addr, nameseq & 0xff, len);
> + }
> + } else {
> + char *buf;
> + if ((buf = malloc(len)) != NULL) {
> + memcpy(buf, addr, len);
> + free(buf);
> + }
> + }
> + munmap(addr, len);
> + /* set NULL to stop other functions from doing siglongjmp */
> + sigbus_jmp = NULL;
> +
> + if (v)
> + printf("%d/%d: %s %s%s [%lld,%d,%s] %s\n",
> + procid, opno, (prot & PROT_WRITE) ? "mwrite" : "mread",
> + f.path, st, (long long)off, (int)len,
> + translate_mmap_flags(flags),
> + (e == 0) ? "0" : "Bus error");
> +
> + free_pathname(&f);
> + close(fd);
> +#endif
> +}
> +
> +void
> +mread_f(int opno, long r)
> +{
> +#ifdef HAVE_SYS_MMAN_H
> + do_mmap(opno, r, PROT_READ);
> +#endif
> +}
> +
> +void
> +mwrite_f(int opno, long r)
> +{
> +#ifdef HAVE_SYS_MMAN_H
> + do_mmap(opno, r, PROT_WRITE);
> +#endif
> +}
> +
> void
> punch_f(int opno, long r)
> {
> diff --git a/src/global.h b/src/global.h
> index f63246b..3920c0d 100644
> --- a/src/global.h
> +++ b/src/global.h
> @@ -178,4 +178,8 @@
>
> #endif /* HAVE_LINUX_FALLOC_H */
>
> +#ifdef HAVE_SYS_MMAN_H
> +#include <sys/mman.h>
> +#endif
> +
> #endif /* GLOBAL_H */
> --
> 2.7.4
>
> --
> To unsubscribe from this list: send the line "unsubscribe fstests" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2017-03-28 9:09 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2017-03-28 8:46 [PATCH v9 1/2] fsstress: add mwrite/mread into test operation list Zorro Lang
2017-03-28 8:46 ` [PATCH v9 2/2] xfs/068: update golden output due to new operations in fsstress Zorro Lang
2017-03-28 9:08 ` [PATCH v9 1/2] fsstress: add mwrite/mread into test operation list Zorro Lang
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).