]> git.proxmox.com Git - ceph.git/blame - ceph/src/test/libcephfs/lazyio.cc
update ceph source to reef 18.1.2
[ceph.git] / ceph / src / test / libcephfs / lazyio.cc
CommitLineData
92f5a8d4
TL
1// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2// vim: ts=8 sw=2 smarttab
3/*
4 * Ceph - scalable distributed file system
5 *
6 * Copyright (C) 2019 Red Hat Ltd
7 *
8 * This is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License version 2.1, as published by the Free Software
11 * Foundation. See file COPYING.
12 *
13 */
14
15#include "gtest/gtest.h"
1e59de90 16#include "include/compat.h"
92f5a8d4
TL
17#include "include/cephfs/libcephfs.h"
18#include "include/rados/librados.h"
19#include <errno.h>
20#include <fcntl.h>
21#include <unistd.h>
22#include <sys/types.h>
23#include <sys/stat.h>
24#include <dirent.h>
9f95a23c 25#if defined(__linux__)
92f5a8d4 26#include <sys/xattr.h>
9f95a23c 27#endif
92f5a8d4
TL
28
29rados_t cluster;
30
31TEST(LibCephFS, LazyIOOneWriterMulipleReaders) {
32 struct ceph_mount_info *ca, *cb;
33 ASSERT_EQ(ceph_create(&ca, NULL), 0);
34 ASSERT_EQ(ceph_conf_read_file(ca, NULL), 0);
35 ASSERT_EQ(0, ceph_conf_parse_env(ca, NULL));
36 ASSERT_EQ(ceph_mount(ca, NULL), 0);
37
38 ASSERT_EQ(ceph_create(&cb, NULL), 0);
39 ASSERT_EQ(ceph_conf_read_file(cb, NULL), 0);
40 ASSERT_EQ(0, ceph_conf_parse_env(cb, NULL));
41 ASSERT_EQ(ceph_mount(cb, NULL), 0);
42
43 char name[20];
44 snprintf(name, sizeof(name), "foo.%d", getpid());
45
46 int fda = ceph_open(ca, name, O_CREAT|O_RDWR, 0644);
47 ASSERT_LE(0, fda);
48
49 int fdb = ceph_open(cb, name, O_RDONLY, 0644);
50 ASSERT_LE(0, fdb);
51
52 ASSERT_EQ(0, ceph_lazyio(ca, fda, 1));
53 ASSERT_EQ(0, ceph_lazyio(cb, fdb, 1));
54
55 char out_buf[] = "fooooooooo";
56
57 /* Client a issues a write and propagates/flushes the buffer */
58 ASSERT_EQ((int)sizeof(out_buf), ceph_write(ca, fda, out_buf, sizeof(out_buf), 0));
59 ASSERT_EQ(0, ceph_lazyio_propagate(ca, fda, 0, 0));
60
61 /* Client a issues a write and propagates/flushes the buffer */
62 ASSERT_EQ((int)sizeof(out_buf), ceph_write(ca, fda, out_buf, sizeof(out_buf), 10));
63 ASSERT_EQ(0, ceph_lazyio_propagate(ca, fda, 0, 0));
64
65 char in_buf[40];
66 /* Calling ceph_lazyio_synchronize here will invalidate client b's cache and hence enable client a to fetch the propagated write of client a in the subsequent read */
67 ASSERT_EQ(0, ceph_lazyio_synchronize(cb, fdb, 0, 0));
68 ASSERT_EQ(ceph_read(cb, fdb, in_buf, sizeof(in_buf), 0), 2*strlen(out_buf)+1);
69 ASSERT_STREQ(in_buf, "fooooooooofooooooooo");
70
71 /* Client a does not need to call ceph_lazyio_synchronize here because it is the latest writer and fda holds the updated inode*/
72 ASSERT_EQ(ceph_read(ca, fda, in_buf, sizeof(in_buf), 0), 2*strlen(out_buf)+1);
73 ASSERT_STREQ(in_buf, "fooooooooofooooooooo");
74
75 ceph_close(ca, fda);
76 ceph_close(cb, fdb);
77
78 ceph_shutdown(ca);
79 ceph_shutdown(cb);
80}
81
82TEST(LibCephFS, LazyIOMultipleWritersMulipleReaders) {
83 struct ceph_mount_info *ca, *cb;
84 ASSERT_EQ(ceph_create(&ca, NULL), 0);
85 ASSERT_EQ(ceph_conf_read_file(ca, NULL), 0);
86 ASSERT_EQ(0, ceph_conf_parse_env(ca, NULL));
87 ASSERT_EQ(ceph_mount(ca, NULL), 0);
88
89 ASSERT_EQ(ceph_create(&cb, NULL), 0);
90 ASSERT_EQ(ceph_conf_read_file(cb, NULL), 0);
91 ASSERT_EQ(0, ceph_conf_parse_env(cb, NULL));
92 ASSERT_EQ(ceph_mount(cb, NULL), 0);
93
94 char name[20];
95 snprintf(name, sizeof(name), "foo2.%d", getpid());
96
97 int fda = ceph_open(ca, name, O_CREAT|O_RDWR, 0644);
98 ASSERT_LE(0, fda);
99
100 int fdb = ceph_open(cb, name, O_RDWR, 0644);
101 ASSERT_LE(0, fdb);
102
103 ASSERT_EQ(0, ceph_lazyio(ca, fda, 1));
104 ASSERT_EQ(0, ceph_lazyio(cb, fdb, 1));
105
106 char out_buf[] = "fooooooooo";
107 /* Client a issues a write and propagates/flushes the buffer */
108 ASSERT_EQ((int)sizeof(out_buf), ceph_write(ca, fda, out_buf, sizeof(out_buf), 0));
109 ASSERT_EQ(0, ceph_lazyio_propagate(ca, fda, 0, 0));
110
111 /* Client b issues a write and propagates/flushes the buffer*/
112 ASSERT_EQ((int)sizeof(out_buf), ceph_write(cb, fdb, out_buf, sizeof(out_buf), 10));
113 ASSERT_EQ(0, ceph_lazyio_propagate(cb, fdb, 0, 0));
114
115 char in_buf[40];
116 /* Calling ceph_lazyio_synchronize here will invalidate client a's cache and hence enable client a to fetch the propagated writes of client b in the subsequent read */
117 ASSERT_EQ(0, ceph_lazyio_synchronize(ca, fda, 0, 0));
118 ASSERT_EQ(ceph_read(ca, fda, in_buf, sizeof(in_buf), 0), 2*strlen(out_buf)+1);
119 ASSERT_STREQ(in_buf, "fooooooooofooooooooo");
120
121 /* Client b does not need to call ceph_lazyio_synchronize here because it is the latest writer and the writes before it have already been propagated*/
122 ASSERT_EQ(ceph_read(cb, fdb, in_buf, sizeof(in_buf), 0), 2*strlen(out_buf)+1);
123 ASSERT_STREQ(in_buf, "fooooooooofooooooooo");
124
125 /* Client a issues a write */
126 char wait_out_buf[] = "foobarbars";
127 ASSERT_EQ((int)sizeof(wait_out_buf), ceph_write(ca, fda, wait_out_buf, sizeof(wait_out_buf), 20));
128 ASSERT_EQ(0, ceph_lazyio_propagate(ca, fda, 0, 0));
129
130 /* Client a does not need to call ceph_lazyio_synchronize here because it is the latest writer and the writes before it have already been propagated*/
131 ASSERT_EQ(ceph_read(ca, fda, in_buf, sizeof(in_buf), 0), (2*(strlen(out_buf)))+strlen(wait_out_buf)+1);
132 ASSERT_STREQ(in_buf, "fooooooooofooooooooofoobarbars");
133
134 /* Calling ceph_lazyio_synchronize here will invalidate client b's cache and hence enable client a to fetch the propagated write of client a in the subsequent read */
135 ASSERT_EQ(0, ceph_lazyio_synchronize(cb, fdb, 0, 0));
136 ASSERT_EQ(ceph_read(cb, fdb, in_buf, sizeof(in_buf), 0), (2*(strlen(out_buf)))+strlen(wait_out_buf)+1);
137 ASSERT_STREQ(in_buf, "fooooooooofooooooooofoobarbars");
138
139 ceph_close(ca, fda);
140 ceph_close(cb, fdb);
141
142 ceph_shutdown(ca);
143 ceph_shutdown(cb);
144}
145
146TEST(LibCephFS, LazyIOMultipleWritersOneReader) {
147 struct ceph_mount_info *ca, *cb;
148 ASSERT_EQ(ceph_create(&ca, NULL), 0);
149 ASSERT_EQ(ceph_conf_read_file(ca, NULL), 0);
150 ASSERT_EQ(0, ceph_conf_parse_env(ca, NULL));
151 ASSERT_EQ(ceph_mount(ca, NULL), 0);
152
153 ASSERT_EQ(ceph_create(&cb, NULL), 0);
154 ASSERT_EQ(ceph_conf_read_file(cb, NULL), 0);
155 ASSERT_EQ(0, ceph_conf_parse_env(cb, NULL));
156 ASSERT_EQ(ceph_mount(cb, NULL), 0);
157
158 char name[20];
159 snprintf(name, sizeof(name), "foo3.%d", getpid());
160
161 int fda = ceph_open(ca, name, O_CREAT|O_RDWR, 0644);
162 ASSERT_LE(0, fda);
163
164 int fdb = ceph_open(cb, name, O_RDWR, 0644);
165 ASSERT_LE(0, fdb);
166
167 ASSERT_EQ(0, ceph_lazyio(ca, fda, 1));
168 ASSERT_EQ(0, ceph_lazyio(cb, fdb, 1));
169
170 char out_buf[] = "fooooooooo";
171 /* Client a issues a write and propagates/flushes the buffer */
172 ASSERT_EQ((int)sizeof(out_buf), ceph_write(ca, fda, out_buf, sizeof(out_buf), 0));
173 ASSERT_EQ(0, ceph_lazyio_propagate(ca, fda, 0, 0));
174
175 /* Client b issues a write and propagates/flushes the buffer*/
176 ASSERT_EQ((int)sizeof(out_buf), ceph_write(cb, fdb, out_buf, sizeof(out_buf), 10));
177 ASSERT_EQ(0, ceph_lazyio_propagate(cb, fdb, 0, 0));
178
179 char in_buf[40];
180 /* Client a reads the file and verifies that it only reads it's propagated writes and not Client b's*/
181 ASSERT_EQ(ceph_read(ca, fda, in_buf, sizeof(in_buf), 0), strlen(out_buf)+1);
182 ASSERT_STREQ(in_buf, "fooooooooo");
183
184 /* Client a reads the file again, this time with a lazyio_synchronize to check if the cache gets invalidated and data is refetched i.e all the propagated writes are being read*/
185 ASSERT_EQ(0, ceph_lazyio_synchronize(ca, fda, 0, 0));
186 ASSERT_EQ(ceph_read(ca, fda, in_buf, sizeof(in_buf), 0), 2*strlen(out_buf)+1);
187 ASSERT_STREQ(in_buf, "fooooooooofooooooooo");
188
189 ceph_close(ca, fda);
190 ceph_close(cb, fdb);
191
192 ceph_shutdown(ca);
193 ceph_shutdown(cb);
194}
195
196TEST(LibCephFS, LazyIOSynchronizeFlush) {
197 /* Test to make sure lazyio_synchronize flushes dirty buffers */
198 struct ceph_mount_info *ca, *cb;
199 ASSERT_EQ(ceph_create(&ca, NULL), 0);
200 ASSERT_EQ(ceph_conf_read_file(ca, NULL), 0);
201 ASSERT_EQ(0, ceph_conf_parse_env(ca, NULL));
202 ASSERT_EQ(ceph_mount(ca, NULL), 0);
203
204 ASSERT_EQ(ceph_create(&cb, NULL), 0);
205 ASSERT_EQ(ceph_conf_read_file(cb, NULL), 0);
206 ASSERT_EQ(0, ceph_conf_parse_env(cb, NULL));
207 ASSERT_EQ(ceph_mount(cb, NULL), 0);
208
209 char name[20];
210 snprintf(name, sizeof(name), "foo4.%d", getpid());
211
212 int fda = ceph_open(ca, name, O_CREAT|O_RDWR, 0644);
213 ASSERT_LE(0, fda);
214
215 int fdb = ceph_open(cb, name, O_RDWR, 0644);
216 ASSERT_LE(0, fdb);
217
218 ASSERT_EQ(0, ceph_lazyio(ca, fda, 1));
219 ASSERT_EQ(0, ceph_lazyio(cb, fdb, 1));
220
221 char out_buf[] = "fooooooooo";
222
223 /* Client a issues a write and propagates it*/
224 ASSERT_EQ((int)sizeof(out_buf), ceph_write(ca, fda, out_buf, sizeof(out_buf), 0));
225 ASSERT_EQ(0, ceph_lazyio_propagate(ca, fda, 0, 0));
226
227 /* Client b issues writes and without lazyio_propagate*/
228 ASSERT_EQ((int)sizeof(out_buf), ceph_write(cb, fdb, out_buf, sizeof(out_buf), 10));
229 ASSERT_EQ((int)sizeof(out_buf), ceph_write(cb, fdb, out_buf, sizeof(out_buf), 20));
230
231 char in_buf[40];
232 /* Calling ceph_lazyio_synchronize here will first flush the possibly pending buffered write of client b and invalidate client b's cache and hence enable client b to fetch all the propagated writes */
233 ASSERT_EQ(0, ceph_lazyio_synchronize(cb, fdb, 0, 0));
234 ASSERT_EQ(ceph_read(cb, fdb, in_buf, sizeof(in_buf), 0), 3*strlen(out_buf)+1);
235 ASSERT_STREQ(in_buf, "fooooooooofooooooooofooooooooo");
236
237 /* Required to call ceph_lazyio_synchronize here since client b is the latest writer and client a is out of sync with updated file*/
238 ASSERT_EQ(0, ceph_lazyio_synchronize(ca, fda, 0, 0));
239 ASSERT_EQ(ceph_read(ca, fda, in_buf, sizeof(in_buf), 0), 3*strlen(out_buf)+1);
240 ASSERT_STREQ(in_buf, "fooooooooofooooooooofooooooooo");
241
242 ceph_close(ca, fda);
243 ceph_close(cb, fdb);
244
245 ceph_shutdown(ca);
246 ceph_shutdown(cb);
247}
248
249TEST(LibCephFS, WithoutandWithLazyIO) {
250 struct ceph_mount_info *ca, *cb;
251 ASSERT_EQ(ceph_create(&ca, NULL), 0);
252 ASSERT_EQ(ceph_conf_read_file(ca, NULL), 0);
253 ASSERT_EQ(0, ceph_conf_parse_env(ca, NULL));
254 ASSERT_EQ(ceph_mount(ca, NULL), 0);
255
256 ASSERT_EQ(ceph_create(&cb, NULL), 0);
257 ASSERT_EQ(ceph_conf_read_file(cb, NULL), 0);
258 ASSERT_EQ(0, ceph_conf_parse_env(cb, NULL));
259 ASSERT_EQ(ceph_mount(cb, NULL), 0);
260
261 char name[20];
262 snprintf(name, sizeof(name), "foo5.%d", getpid());
263
264 int fda = ceph_open(ca, name, O_CREAT|O_RDWR, 0644);
265 ASSERT_LE(0, fda);
266
267 int fdb = ceph_open(cb, name, O_RDWR, 0644);
268 ASSERT_LE(0, fdb);
269
270 char out_buf_w[] = "1234567890";
271 /* Doing some non lazyio writes and read*/
272 ASSERT_EQ((int)sizeof(out_buf_w), ceph_write(ca, fda, out_buf_w, sizeof(out_buf_w), 0));
273
274 ASSERT_EQ((int)sizeof(out_buf_w), ceph_write(cb, fdb, out_buf_w, sizeof(out_buf_w), 10));
275
276 char in_buf_w[30];
277 ASSERT_EQ(ceph_read(ca, fda, in_buf_w, sizeof(in_buf_w), 0), 2*strlen(out_buf_w)+1);
278
279 /* Enable lazyio*/
280 ASSERT_EQ(0, ceph_lazyio(ca, fda, 1));
281 ASSERT_EQ(0, ceph_lazyio(cb, fdb, 1));
282
283 char out_buf[] = "fooooooooo";
284
285 /* Client a issues a write and propagates/flushes the buffer*/
286 ASSERT_EQ((int)sizeof(out_buf), ceph_write(ca, fda, out_buf, sizeof(out_buf), 20));
287 ASSERT_EQ(0, ceph_lazyio_propagate(ca, fda, 0, 0));
288
289 /* Client b issues a write and propagates/flushes the buffer*/
290 ASSERT_EQ((int)sizeof(out_buf), ceph_write(cb, fdb, out_buf, sizeof(out_buf), 30));
291 ASSERT_EQ(0, ceph_lazyio_propagate(cb, fdb, 0, 0));
292
293 char in_buf[50];
294 /* Calling ceph_lazyio_synchronize here will invalidate client a's cache and hence enable client a to fetch the propagated writes of client b in the subsequent read */
295 ASSERT_EQ(0, ceph_lazyio_synchronize(ca, fda, 0, 0));
296 ASSERT_EQ(ceph_read(ca, fda, in_buf, sizeof(in_buf), 0), (2*(strlen(out_buf)))+(2*(strlen(out_buf_w)))+1);
297 ASSERT_STREQ(in_buf, "12345678901234567890fooooooooofooooooooo");
298
299 /* Client b does not need to call ceph_lazyio_synchronize here because it is the latest writer and the writes before it have already been propagated*/
300 ASSERT_EQ(ceph_read(cb, fdb, in_buf, sizeof(in_buf), 0), (2*(strlen(out_buf)))+(2*(strlen(out_buf_w)))+1);
301 ASSERT_STREQ(in_buf, "12345678901234567890fooooooooofooooooooo");
302
303 ceph_close(ca, fda);
304 ceph_close(cb, fdb);
305
306 ceph_shutdown(ca);
307 ceph_shutdown(cb);
308}
309
310static int update_root_mode()
311{
312 struct ceph_mount_info *admin;
313 int r = ceph_create(&admin, NULL);
314 if (r < 0)
315 return r;
316 ceph_conf_read_file(admin, NULL);
317 ceph_conf_parse_env(admin, NULL);
318 ceph_conf_set(admin, "client_permissions", "false");
319 r = ceph_mount(admin, "/");
320 if (r < 0)
321 goto out;
322 r = ceph_chmod(admin, "/", 0777);
323out:
324 ceph_shutdown(admin);
325 return r;
326}
327
328int main(int argc, char **argv)
329{
330 int r = update_root_mode();
331 if (r < 0)
332 exit(1);
333
334 ::testing::InitGoogleTest(&argc, argv);
335
336 srand(getpid());
337
338 r = rados_create(&cluster, NULL);
339 if (r < 0)
340 exit(1);
341
342 r = rados_conf_read_file(cluster, NULL);
343 if (r < 0)
344 exit(1);
345
346 rados_conf_parse_env(cluster, NULL);
347 r = rados_connect(cluster);
348 if (r < 0)
349 exit(1);
350
351 r = RUN_ALL_TESTS();
352
353 rados_shutdown(cluster);
354
355 return r;
356}