1272343Sngie/* $NetBSD: snapshot.c,v 1.7 2013/02/06 09:05:01 hannken Exp $ */ 2272343Sngie 3272343Sngie#include <sys/types.h> 4272343Sngie#include <sys/ioctl.h> 5272343Sngie#include <sys/mount.h> 6272343Sngie 7272343Sngie#include <dev/fssvar.h> 8272343Sngie 9272343Sngie#include <atf-c.h> 10272343Sngie#include <fcntl.h> 11272343Sngie#include <pthread.h> 12272343Sngie#include <stdio.h> 13272343Sngie#include <stdlib.h> 14272343Sngie#include <string.h> 15272343Sngie#include <unistd.h> 16272343Sngie 17272343SngieATF_TC_WITH_CLEANUP(snapshot); 18272343SngieATF_TC_HEAD(snapshot, tc) 19272343Sngie{ 20272343Sngie 21272343Sngie atf_tc_set_md_var(tc, "descr", "basic snapshot features"); 22272343Sngie} 23272343Sngie 24272343Sngiestatic void 25272343Sngiemakefile(const char *path) 26272343Sngie{ 27272343Sngie int fd; 28272343Sngie 29272343Sngie fd = rump_sys_open(path, O_CREAT | O_RDWR, 0777); 30272343Sngie if (fd == -1) 31272343Sngie atf_tc_fail_errno("create %s", path); 32272343Sngie rump_sys_close(fd); 33272343Sngie} 34272343Sngie 35272343SngieATF_TC_BODY(snapshot, tc) 36272343Sngie{ 37272343Sngie char buf[1024]; 38272343Sngie struct fss_set fss; 39272343Sngie int fssfd; 40272343Sngie int fd, fd2, i; 41272343Sngie 42272343Sngie if (system(NEWFS) == -1) 43272343Sngie atf_tc_fail_errno("cannot create file system"); 44272343Sngie 45272343Sngie rump_init(); 46272343Sngie begin(); 47272343Sngie 48272343Sngie if (rump_sys_mkdir("/mnt", 0777) == -1) 49272343Sngie atf_tc_fail_errno("mount point create"); 50272343Sngie if (rump_sys_mkdir("/snap", 0777) == -1) 51272343Sngie atf_tc_fail_errno("mount point 2 create"); 52272343Sngie 53272343Sngie rump_pub_etfs_register("/diskdev", IMGNAME, RUMP_ETFS_BLK); 54272343Sngie 55272343Sngie mount_diskfs("/diskdev", "/mnt"); 56272343Sngie 57272343Sngie#define TESTSTR1 "huihai\n" 58272343Sngie#define TESTSZ1 (sizeof(TESTSTR1)-1) 59272343Sngie#define TESTSTR2 "baana liten\n" 60272343Sngie#define TESTSZ2 (sizeof(TESTSTR2)-1) 61272343Sngie 62272343Sngie fd = rump_sys_open("/mnt/myfile", O_RDWR | O_CREAT, 0777); 63272343Sngie if (fd == -1) 64272343Sngie atf_tc_fail_errno("create file"); 65272343Sngie if (rump_sys_write(fd, TESTSTR1, TESTSZ1) != TESTSZ1) 66272343Sngie atf_tc_fail_errno("write fail"); 67272343Sngie 68272343Sngie fssfd = rump_sys_open("/dev/rfss0", O_RDWR); 69272343Sngie if (fssfd == -1) 70272343Sngie atf_tc_fail_errno("cannot open fss"); 71272343Sngie makefile(BAKNAME); 72272343Sngie memset(&fss, 0, sizeof(fss)); 73272343Sngie fss.fss_mount = __UNCONST("/mnt"); 74272343Sngie fss.fss_bstore = __UNCONST(BAKNAME); 75272343Sngie fss.fss_csize = 0; 76272343Sngie if (rump_sys_ioctl(fssfd, FSSIOCSET, &fss) == -1) 77272343Sngie atf_tc_fail_errno("create snapshot"); 78272343Sngie 79272343Sngie for (i = 0; i < 10000; i++) { 80272343Sngie if (rump_sys_write(fd, TESTSTR2, TESTSZ2) != TESTSZ2) 81272343Sngie atf_tc_fail_errno("write fail"); 82272343Sngie } 83272343Sngie rump_sys_sync(); 84272343Sngie 85272343Sngie /* technically we should fsck it first? */ 86272343Sngie mount_diskfs("/dev/fss0", "/snap"); 87272343Sngie 88272343Sngie /* check for old contents */ 89272343Sngie fd2 = rump_sys_open("/snap/myfile", O_RDONLY); 90272343Sngie if (fd2 == -1) 91272343Sngie atf_tc_fail_errno("fail"); 92272343Sngie memset(buf, 0, sizeof(buf)); 93272343Sngie if (rump_sys_read(fd2, buf, sizeof(buf)) == -1) 94272343Sngie atf_tc_fail_errno("read snap"); 95272343Sngie ATF_CHECK(strcmp(buf, TESTSTR1) == 0); 96272343Sngie 97272343Sngie /* check that new files are invisible in the snapshot */ 98272343Sngie makefile("/mnt/newfile"); 99272343Sngie if (rump_sys_open("/snap/newfile", O_RDONLY) != -1) 100272343Sngie atf_tc_fail("newfile exists in snapshot"); 101272343Sngie if (errno != ENOENT) 102272343Sngie atf_tc_fail_errno("newfile open should fail with ENOENT"); 103272343Sngie 104272343Sngie /* check that removed files are still visible in the snapshot */ 105272343Sngie rump_sys_unlink("/mnt/myfile"); 106272343Sngie if (rump_sys_open("/snap/myfile", O_RDONLY) == -1) 107272343Sngie atf_tc_fail_errno("unlinked file no longer in snapshot"); 108272343Sngie 109272343Sngie /* done for now */ 110272343Sngie} 111272343Sngie 112272343SngieATF_TC_CLEANUP(snapshot, tc) 113272343Sngie{ 114272343Sngie 115272343Sngie unlink(IMGNAME); 116272343Sngie} 117272343Sngie 118272343SngieATF_TC_WITH_CLEANUP(snapshotstress); 119272343SngieATF_TC_HEAD(snapshotstress, tc) 120272343Sngie{ 121272343Sngie 122272343Sngie atf_tc_set_md_var(tc, "descr", "snapshot on active file system"); 123272343Sngie} 124272343Sngie 125272343Sngie#define NACTIVITY 4 126272343Sngie 127272343Sngiestatic bool activity_stop = false; 128272343Sngiestatic pid_t wrkpid; 129272343Sngie 130272343Sngiestatic void * 131272343Sngiefs_activity(void *arg) 132272343Sngie{ 133272343Sngie int di, fi; 134272343Sngie char *prefix = arg, path[128]; 135272343Sngie 136272343Sngie rump_pub_lwproc_newlwp(wrkpid); 137272343Sngie 138272343Sngie RL(rump_sys_mkdir(prefix, 0777)); 139272343Sngie while (! activity_stop) { 140272343Sngie for (di = 0; di < 5; di++) { 141272343Sngie snprintf(path, sizeof(path), "%s/d%d", prefix, di); 142272343Sngie RL(rump_sys_mkdir(path, 0777)); 143272343Sngie for (fi = 0; fi < 5; fi++) { 144272343Sngie snprintf(path, sizeof(path), "%s/d%d/f%d", 145272343Sngie prefix, di, fi); 146272343Sngie makefile(path); 147272343Sngie } 148272343Sngie } 149272343Sngie for (di = 0; di < 5; di++) { 150272343Sngie for (fi = 0; fi < 5; fi++) { 151272343Sngie snprintf(path, sizeof(path), "%s/d%d/f%d", 152272343Sngie prefix, di, fi); 153272343Sngie RL(rump_sys_unlink(path)); 154272343Sngie } 155272343Sngie snprintf(path, sizeof(path), "%s/d%d", prefix, di); 156272343Sngie RL(rump_sys_rmdir(path)); 157272343Sngie } 158272343Sngie } 159272343Sngie RL(rump_sys_rmdir(prefix)); 160272343Sngie 161272343Sngie rump_pub_lwproc_releaselwp(); 162272343Sngie 163272343Sngie return NULL; 164272343Sngie} 165272343Sngie 166272343SngieATF_TC_BODY(snapshotstress, tc) 167272343Sngie{ 168272343Sngie pthread_t at[NACTIVITY]; 169272343Sngie struct fss_set fss; 170272343Sngie char prefix[NACTIVITY][128]; 171272343Sngie int i, fssfd; 172272343Sngie 173272343Sngie if (system(NEWFS) == -1) 174272343Sngie atf_tc_fail_errno("cannot create file system"); 175272343Sngie /* Force SMP so the stress makes sense. */ 176272343Sngie RL(setenv("RUMP_NCPU", "4", 1)); 177272343Sngie RZ(rump_init()); 178272343Sngie /* Prepare for fsck to use the RUMP /dev/fss0. */ 179272343Sngie RL(rump_init_server("unix://commsock")); 180272343Sngie RL(setenv("LD_PRELOAD", "/usr/lib/librumphijack.so", 1)); 181272343Sngie RL(setenv("RUMP_SERVER", "unix://commsock", 1)); 182272343Sngie RL(setenv("RUMPHIJACK", "blanket=/dev/rfss0", 1)); 183272343Sngie begin(); 184272343Sngie 185272343Sngie RL(rump_sys_mkdir("/mnt", 0777)); 186272343Sngie 187272343Sngie rump_pub_etfs_register("/diskdev", IMGNAME, RUMP_ETFS_BLK); 188272343Sngie 189272343Sngie mount_diskfs("/diskdev", "/mnt"); 190272343Sngie 191272343Sngie /* Start file system activity. */ 192272343Sngie RL(wrkpid = rump_sys_getpid()); 193272343Sngie for (i = 0; i < NACTIVITY; i++) { 194272343Sngie snprintf(prefix[i], sizeof(prefix[i]), "/mnt/a%d", i); 195272343Sngie RL(pthread_create(&at[i], NULL, fs_activity, prefix[i])); 196272343Sngie sleep(1); 197272343Sngie } 198272343Sngie 199272343Sngie fssfd = rump_sys_open("/dev/rfss0", O_RDWR); 200272343Sngie if (fssfd == -1) 201272343Sngie atf_tc_fail_errno("cannot open fss"); 202272343Sngie makefile(BAKNAME); 203272343Sngie memset(&fss, 0, sizeof(fss)); 204272343Sngie fss.fss_mount = __UNCONST("/mnt"); 205272343Sngie fss.fss_bstore = __UNCONST(BAKNAME); 206272343Sngie fss.fss_csize = 0; 207272343Sngie if (rump_sys_ioctl(fssfd, FSSIOCSET, &fss) == -1) 208272343Sngie atf_tc_fail_errno("create snapshot"); 209272343Sngie 210272343Sngie activity_stop = true; 211272343Sngie for (i = 0; i < NACTIVITY; i++) 212272343Sngie RL(pthread_join(at[i], NULL)); 213272343Sngie 214272343Sngie RL(system(FSCK " /dev/rfss0")); 215272343Sngie} 216272343Sngie 217272343SngieATF_TC_CLEANUP(snapshotstress, tc) 218272343Sngie{ 219272343Sngie 220272343Sngie unlink(IMGNAME); 221272343Sngie} 222272343Sngie 223272343SngieATF_TP_ADD_TCS(tp) 224272343Sngie{ 225272343Sngie ATF_TP_ADD_TC(tp, snapshot); 226272343Sngie ATF_TP_ADD_TC(tp, snapshotstress); 227272343Sngie return 0; 228272343Sngie} 229