1 module during.tests.fsync; 2 3 import during; 4 import during.tests.base; 5 6 import core.stdc.stdlib; 7 import core.sys.linux.errno; 8 import core.sys.linux.fcntl; 9 import core.sys.posix.sys.uio : iovec; 10 import core.sys.posix.unistd; 11 12 @("single") 13 unittest 14 { 15 Uring io; 16 auto res = io.setup(); 17 assert(res >= 0, "Error initializing IO"); 18 19 auto fname = getTestFileName!"fsync_single"; 20 auto fd = openFile(fname, O_CREAT | O_WRONLY); 21 scope (exit) unlink(&fname[0]); 22 23 auto ret = io 24 .putWith!((ref SubmissionEntry e, int fd) => e.prepFsync(fd))(fd) 25 .submit(1); 26 assert(ret == 1); 27 assert(io.length == 1); 28 assert(io.front.res == 0); 29 io.popFront(); 30 31 close(fd); 32 } 33 34 @("barrier") 35 unittest 36 { 37 if (!checkKernelVersion(5, 3)) return; 38 39 enum NUM_WRITES = 4; 40 Uring io; 41 auto res = io.setup(); 42 assert(res >= 0, "Error initializing IO"); 43 44 auto fname = getTestFileName!"fsync_barier"; 45 auto fd = openFile(fname, O_CREAT | O_WRONLY); 46 scope (exit) unlink(&fname[0]); 47 48 iovec[NUM_WRITES] iovecs; 49 foreach (i; 0..NUM_WRITES) 50 { 51 iovecs[i].iov_base = malloc(4096); 52 iovecs[i].iov_len = 4096; 53 } 54 55 int off; 56 foreach (i; 0..NUM_WRITES) 57 { 58 io.putWith!((ref SubmissionEntry e, int fd, ref iovec v, int off) 59 { 60 e.prepWritev(fd, v, off); 61 e.user_data = 1; 62 })(fd, iovecs[i], off); 63 off += 4096; 64 } 65 66 io.putWith!((ref SubmissionEntry e, int fd) 67 { 68 e.prepFsync(fd, FsyncFlags.DATASYNC); 69 e.user_data = 2; 70 // TODO: Works with IO_LINK but not without it: See: https://github.com/axboe/liburing/issues/33 71 e.flags = cast(SubmissionEntryFlags)(SubmissionEntryFlags.IO_DRAIN | SubmissionEntryFlags.IO_LINK); 72 // e.flags = SubmissionEntryFlags.IO_DRAIN; 73 })(fd); 74 75 auto ret = io.submit(NUM_WRITES + 1); 76 if (ret < 0) 77 { 78 if (ret == -EINVAL) 79 { 80 version (D_BetterC) 81 { 82 errmsg = "Expected kernel to support barrier fsync"; 83 return; 84 } 85 else throw new Exception("Expected kernel to support barrier fsync"); 86 } 87 assert(0, "submit failed"); 88 } 89 else assert(ret == NUM_WRITES + 1); 90 91 assert(io.length == NUM_WRITES + 1); 92 foreach (i; 0..NUM_WRITES + 1) 93 { 94 if (io.front.res == -EINVAL) 95 { 96 version (D_BetterC) 97 { 98 errmsg = "Expected kernel to support IOSQE_IO_DRAIN"; 99 break; 100 } 101 else throw new Exception("Expected kernel to support IOSQE_IO_DRAIN"); 102 } 103 assert(io.front.res >= 0); 104 if (i < NUM_WRITES) assert(io.front.user_data == 1, "unexpected op completion"); 105 else assert(io.front.user_data == 2, "unexpected op completion"); 106 107 io.popFront(); 108 } 109 110 close(fd); 111 } 112 113 @("range") 114 unittest 115 { 116 if (!checkKernelVersion(5, 2)) return; 117 118 enum NUM_WRITES = 4; 119 Uring io; 120 auto res = io.setup(); 121 assert(res >= 0, "Error initializing IO"); 122 123 auto fname = getTestFileName!"fsync_range"; 124 auto fd = openFile(fname, O_CREAT | O_WRONLY); 125 scope (exit) unlink(&fname[0]); 126 127 iovec[NUM_WRITES] iovecs; 128 foreach (i; 0..NUM_WRITES) 129 { 130 iovecs[i].iov_base = malloc(4096); 131 iovecs[i].iov_len = 4096; 132 } 133 134 int off; 135 foreach (i; 0..NUM_WRITES) 136 { 137 io.putWith!((ref SubmissionEntry e, int fd, ref iovec v, int off) 138 { 139 e.prepWritev(fd, v, off); 140 e.user_data = 1; 141 e.flags = SubmissionEntryFlags.IO_LINK; 142 })(fd, iovecs[i], off); 143 off += 4096; 144 } 145 146 io.putWith!((ref SubmissionEntry e, int fd) 147 { 148 e.prepSyncFileRange(fd, (NUM_WRITES - 1) * 4096, 4096); 149 e.user_data = 2; 150 e.flags = SubmissionEntryFlags.IO_LINK; 151 })(fd); 152 153 auto ret = io.submit(NUM_WRITES + 1); 154 if (ret < 0) 155 { 156 if (ret == -EINVAL) 157 { 158 version (D_BetterC) 159 { 160 errmsg = "Expected kernel to support range file sync"; 161 return; 162 } 163 else throw new Exception("Expected kernel to support range file sync"); 164 } 165 assert(0, "submit failed"); 166 } 167 else assert(ret == NUM_WRITES + 1); 168 169 assert(io.length == NUM_WRITES + 1); 170 foreach (i; 0..NUM_WRITES + 1) 171 { 172 assert(io.front.res >= 0); 173 if (i < NUM_WRITES) assert(io.front.user_data == 1, "unexpected op completion"); 174 else assert(io.front.user_data == 2, "unexpected op completion"); 175 io.popFront(); 176 } 177 178 close(fd); 179 }