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