Home | History | Annotate | Line # | Download | only in sys
t_msync.c revision 1.1
      1 /* $NetBSD: t_msync.c,v 1.1 2011/07/07 06:57:54 jruoho Exp $ */
      2 
      3 /*-
      4  * Copyright (c) 2011 The NetBSD Foundation, Inc.
      5  * All rights reserved.
      6  *
      7  * This code is derived from software contributed to The NetBSD Foundation
      8  * by Jukka Ruohonen.
      9  *
     10  * Redistribution and use in source and binary forms, with or without
     11  * modification, are permitted provided that the following conditions
     12  * are met:
     13  * 1. Redistributions of source code must retain the above copyright
     14  *    notice, this list of conditions and the following disclaimer.
     15  * 2. Redistributions in binary form must reproduce the above copyright
     16  *    notice, this list of conditions and the following disclaimer in the
     17  *    documentation and/or other materials provided with the distribution.
     18  *
     19  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     20  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     21  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     22  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     23  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     29  * POSSIBILITY OF SUCH DAMAGE.
     30  */
     31 #include <sys/cdefs.h>
     32 __RCSID("$NetBSD: t_msync.c,v 1.1 2011/07/07 06:57:54 jruoho Exp $");
     33 
     34 #include <sys/mman.h>
     35 
     36 #include <atf-c.h>
     37 #include <errno.h>
     38 #include <fcntl.h>
     39 #include <limits.h>
     40 #include <stdlib.h>
     41 #include <string.h>
     42 #include <unistd.h>
     43 
     44 static long		page = 0;
     45 static const off_t	off = 512;
     46 static const char	path[] = "msync";
     47 
     48 static const char	*msync_sync(const char *, int);
     49 
     50 static const char *
     51 msync_sync(const char *garbage, int flags)
     52 {
     53 	char *buf, *map = MAP_FAILED;
     54 	const char *str = NULL;
     55 	size_t i, len;
     56 	ssize_t tot;
     57 	int fd, rv;
     58 
     59 	/*
     60 	 * Create a temporary file, write
     61 	 * one page to it, and map the file.
     62 	 */
     63 	buf = malloc(page);
     64 
     65 	if (buf == NULL)
     66 		return NULL;
     67 
     68 	for (i = 0; i < (size_t)page; i++)
     69 		buf[i] = 'x';
     70 
     71 	fd = open(path, O_RDWR | O_CREAT, 0700);
     72 
     73 	if (fd < 0) {
     74 		str = "failed to open";
     75 		goto out;
     76 	}
     77 
     78 	tot = 0;
     79 
     80 	while (tot < page) {
     81 
     82 		rv = write(fd, buf, sizeof(buf));
     83 
     84 		if (rv < 0) {
     85 			str = "failed to write";
     86 			goto out;
     87 		}
     88 
     89 		tot += rv;
     90 	}
     91 
     92 	map = mmap(NULL, page, PROT_READ | PROT_WRITE, MAP_FILE|MAP_PRIVATE,
     93 	     fd, 0);
     94 
     95 	if (map == MAP_FAILED) {
     96 		str = "failed to map";
     97 		goto out;
     98 	}
     99 
    100 	/*
    101 	 * Seek to an arbitrary offset and
    102 	 * write garbage to this position.
    103 	 */
    104 	if (lseek(fd, off, SEEK_SET) != off) {
    105 		str = "failed to seek";
    106 		goto out;
    107 	}
    108 
    109 	len = strlen(garbage);
    110 	rv = write(fd, garbage, len);
    111 
    112 	if (rv != (ssize_t)len) {
    113 		str = "failed to write garbage";
    114 		goto out;
    115 	}
    116 
    117 	/*
    118 	 * Synchronize the mapping and verify
    119 	 * that garbage is at the given offset.
    120 	 */
    121 	if (msync(map, page, flags) != 0) {
    122 		str = "failed to msync";
    123 		goto out;
    124 	}
    125 
    126 	if (memcmp(map + off, garbage, len) != 0) {
    127 		str = "msync did not synchronize";
    128 		goto out;
    129 	}
    130 
    131 out:
    132 	free(buf);
    133 
    134 	(void)close(fd);
    135 	(void)unlink(path);
    136 
    137 	if (map != MAP_FAILED)
    138 		(void)munmap(map, page);
    139 
    140 	return str;
    141 }
    142 
    143 ATF_TC(msync_async);
    144 ATF_TC_HEAD(msync_async, tc)
    145 {
    146 	atf_tc_set_md_var(tc, "descr", "Test of msync(2), MS_ASYNC");
    147 }
    148 
    149 ATF_TC_BODY(msync_async, tc)
    150 {
    151 	const char *str;
    152 
    153 	str = msync_sync("garbage", MS_ASYNC);
    154 
    155 	if (str != NULL)
    156 		atf_tc_fail("%s", str);
    157 }
    158 
    159 ATF_TC(msync_err);
    160 ATF_TC_HEAD(msync_err, tc)
    161 {
    162 	atf_tc_set_md_var(tc, "descr", "Test error conditions in msync(2)");
    163 }
    164 
    165 ATF_TC_BODY(msync_err, tc)
    166 {
    167 
    168 	/*
    169 	 * Test that invalid flags error out.
    170 	 */
    171 	ATF_REQUIRE(msync_sync("error", -1) != NULL);
    172 	ATF_REQUIRE(msync_sync("error", INT_MAX) != NULL);
    173 
    174 	errno = 0;
    175 
    176 	ATF_REQUIRE(msync((void *)INT_MAX, page, MS_SYNC) != 0);
    177 	ATF_REQUIRE(errno == EFAULT);
    178 }
    179 
    180 ATF_TC(msync_invalidate);
    181 ATF_TC_HEAD(msync_invalidate, tc)
    182 {
    183 	atf_tc_set_md_var(tc, "descr", "Test of msync(2), MS_INVALIDATE");
    184 }
    185 
    186 ATF_TC_BODY(msync_invalidate, tc)
    187 {
    188 	const char *str;
    189 
    190 	str = msync_sync("garbage", MS_INVALIDATE);
    191 
    192 	if (str != NULL)
    193 		atf_tc_fail("%s", str);
    194 }
    195 
    196 ATF_TC(msync_sync);
    197 ATF_TC_HEAD(msync_sync, tc)
    198 {
    199 	atf_tc_set_md_var(tc, "descr", "Test of msync(2), MS_SYNC");
    200 }
    201 
    202 ATF_TC_BODY(msync_sync, tc)
    203 {
    204 	const char *str;
    205 
    206 	str = msync_sync("garbage", MS_SYNC);
    207 
    208 	if (str != NULL)
    209 		atf_tc_fail("%s", str);
    210 }
    211 
    212 ATF_TP_ADD_TCS(tp)
    213 {
    214 
    215 	page = sysconf(_SC_PAGESIZE);
    216 
    217 	ATF_REQUIRE(page >= 0);
    218 	ATF_REQUIRE(page > off);
    219 
    220 	ATF_TP_ADD_TC(tp, msync_async);
    221 	ATF_TP_ADD_TC(tp, msync_err);
    222 	ATF_TP_ADD_TC(tp, msync_invalidate);
    223 	ATF_TP_ADD_TC(tp, msync_sync);
    224 
    225 	return atf_no_error();
    226 }
    227