1488570ebSJim Harris /* SPDX-License-Identifier: BSD-3-Clause
2a6dbe372Spaul luse * Copyright (C) 2017 Intel Corporation.
312e840b9SSeth Howell * All rights reserved.
412e840b9SSeth Howell */
512e840b9SSeth Howell
612e840b9SSeth Howell #include "spdk/stdinc.h"
712e840b9SSeth Howell
812e840b9SSeth Howell #include "spdk/blobfs.h"
912e840b9SSeth Howell #include "spdk/env.h"
1012e840b9SSeth Howell #include "spdk/log.h"
1112e840b9SSeth Howell #include "spdk/barrier.h"
125fc0475cSJiewei Ke #include "thread/thread_internal.h"
1312e840b9SSeth Howell
14ae431e31SKonrad Sztyber #include "spdk_internal/cunit.h"
1512e840b9SSeth Howell #include "unit/lib/blob/bs_dev_common.c"
16c9fb57a2SSeth Howell #include "common/lib/test_env.c"
1712e840b9SSeth Howell #include "blobfs/blobfs.c"
1812e840b9SSeth Howell #include "blobfs/tree.c"
1912e840b9SSeth Howell
2012e840b9SSeth Howell struct spdk_filesystem *g_fs;
2112e840b9SSeth Howell struct spdk_file *g_file;
2212e840b9SSeth Howell int g_fserrno;
23088c5e04SBen Walker struct spdk_thread *g_dispatch_thread = NULL;
2412e840b9SSeth Howell
2512e840b9SSeth Howell struct ut_request {
2612e840b9SSeth Howell fs_request_fn fn;
2712e840b9SSeth Howell void *arg;
2812e840b9SSeth Howell volatile int done;
2912e840b9SSeth Howell };
3012e840b9SSeth Howell
31ba8f1a9eSAlexey Marchuk DEFINE_STUB(spdk_memory_domain_memzero, int, (struct spdk_memory_domain *src_domain,
32ba8f1a9eSAlexey Marchuk void *src_domain_ctx, struct iovec *iov, uint32_t iovcnt, void (*cpl_cb)(void *, int),
33ba8f1a9eSAlexey Marchuk void *cpl_cb_arg), 0);
34475b86aaSKonrad Sztyber DEFINE_STUB(spdk_mempool_lookup, struct spdk_mempool *, (const char *name), NULL);
35ba8f1a9eSAlexey Marchuk
3612e840b9SSeth Howell static void
send_request(fs_request_fn fn,void * arg)3712e840b9SSeth Howell send_request(fs_request_fn fn, void *arg)
3812e840b9SSeth Howell {
39088c5e04SBen Walker spdk_thread_send_msg(g_dispatch_thread, (spdk_msg_fn)fn, arg);
40088c5e04SBen Walker }
4112e840b9SSeth Howell
42088c5e04SBen Walker static void
ut_call_fn(void * arg)43088c5e04SBen Walker ut_call_fn(void *arg)
44088c5e04SBen Walker {
45088c5e04SBen Walker struct ut_request *req = arg;
4612e840b9SSeth Howell
47088c5e04SBen Walker req->fn(req->arg);
48088c5e04SBen Walker req->done = 1;
4912e840b9SSeth Howell }
5012e840b9SSeth Howell
5112e840b9SSeth Howell static void
ut_send_request(fs_request_fn fn,void * arg)5212e840b9SSeth Howell ut_send_request(fs_request_fn fn, void *arg)
5312e840b9SSeth Howell {
5412e840b9SSeth Howell struct ut_request req;
5512e840b9SSeth Howell
5612e840b9SSeth Howell req.fn = fn;
5712e840b9SSeth Howell req.arg = arg;
5812e840b9SSeth Howell req.done = 0;
5912e840b9SSeth Howell
60088c5e04SBen Walker spdk_thread_send_msg(g_dispatch_thread, ut_call_fn, &req);
6112e840b9SSeth Howell
62088c5e04SBen Walker /* Wait for this to finish */
63088c5e04SBen Walker while (req.done == 0) { }
6412e840b9SSeth Howell }
6512e840b9SSeth Howell
6612e840b9SSeth Howell static void
fs_op_complete(void * ctx,int fserrno)6712e840b9SSeth Howell fs_op_complete(void *ctx, int fserrno)
6812e840b9SSeth Howell {
6912e840b9SSeth Howell g_fserrno = fserrno;
7012e840b9SSeth Howell }
7112e840b9SSeth Howell
7212e840b9SSeth Howell static void
fs_op_with_handle_complete(void * ctx,struct spdk_filesystem * fs,int fserrno)7312e840b9SSeth Howell fs_op_with_handle_complete(void *ctx, struct spdk_filesystem *fs, int fserrno)
7412e840b9SSeth Howell {
7512e840b9SSeth Howell g_fs = fs;
7612e840b9SSeth Howell g_fserrno = fserrno;
7712e840b9SSeth Howell }
7812e840b9SSeth Howell
7912e840b9SSeth Howell static void
fs_thread_poll(void)80c41c4c2bSChangpeng Liu fs_thread_poll(void)
8112e840b9SSeth Howell {
8211654a60SBen Walker struct spdk_thread *thread;
83c41c4c2bSChangpeng Liu
84c41c4c2bSChangpeng Liu thread = spdk_get_thread();
85c41c4c2bSChangpeng Liu while (spdk_thread_poll(thread, 0, 0) > 0) {}
86c41c4c2bSChangpeng Liu while (spdk_thread_poll(g_cache_pool_thread, 0, 0) > 0) {}
87c41c4c2bSChangpeng Liu }
88c41c4c2bSChangpeng Liu
89c41c4c2bSChangpeng Liu static void
_fs_init(void * arg)90c41c4c2bSChangpeng Liu _fs_init(void *arg)
91c41c4c2bSChangpeng Liu {
9212e840b9SSeth Howell struct spdk_bs_dev *dev;
9312e840b9SSeth Howell
9412e840b9SSeth Howell g_fs = NULL;
9512e840b9SSeth Howell g_fserrno = -1;
9612e840b9SSeth Howell dev = init_dev();
9712e840b9SSeth Howell spdk_fs_init(dev, NULL, send_request, fs_op_with_handle_complete, NULL);
98c41c4c2bSChangpeng Liu
99c41c4c2bSChangpeng Liu fs_thread_poll();
10011654a60SBen Walker
10112e840b9SSeth Howell SPDK_CU_ASSERT_FATAL(g_fs != NULL);
10211654a60SBen Walker SPDK_CU_ASSERT_FATAL(g_fs->bdev == dev);
10312e840b9SSeth Howell CU_ASSERT(g_fserrno == 0);
10412e840b9SSeth Howell }
10512e840b9SSeth Howell
10612e840b9SSeth Howell static void
_fs_load(void * arg)107e967dcd2SJim Harris _fs_load(void *arg)
108e967dcd2SJim Harris {
109e967dcd2SJim Harris struct spdk_bs_dev *dev;
110e967dcd2SJim Harris
111e967dcd2SJim Harris g_fs = NULL;
112e967dcd2SJim Harris g_fserrno = -1;
113e967dcd2SJim Harris dev = init_dev();
114e967dcd2SJim Harris spdk_fs_load(dev, send_request, fs_op_with_handle_complete, NULL);
115c41c4c2bSChangpeng Liu
116c41c4c2bSChangpeng Liu fs_thread_poll();
117e967dcd2SJim Harris
118e967dcd2SJim Harris SPDK_CU_ASSERT_FATAL(g_fs != NULL);
119e967dcd2SJim Harris SPDK_CU_ASSERT_FATAL(g_fs->bdev == dev);
120e967dcd2SJim Harris CU_ASSERT(g_fserrno == 0);
121e967dcd2SJim Harris }
122e967dcd2SJim Harris
123e967dcd2SJim Harris static void
_fs_unload(void * arg)12412e840b9SSeth Howell _fs_unload(void *arg)
12512e840b9SSeth Howell {
12612e840b9SSeth Howell g_fserrno = -1;
12712e840b9SSeth Howell spdk_fs_unload(g_fs, fs_op_complete, NULL);
128c41c4c2bSChangpeng Liu
129c41c4c2bSChangpeng Liu fs_thread_poll();
130c41c4c2bSChangpeng Liu
13112e840b9SSeth Howell CU_ASSERT(g_fserrno == 0);
13212e840b9SSeth Howell g_fs = NULL;
13312e840b9SSeth Howell }
13412e840b9SSeth Howell
13512e840b9SSeth Howell static void
_nop(void * arg)136cdd089a8SJim Harris _nop(void *arg)
137cdd089a8SJim Harris {
138cdd089a8SJim Harris }
139cdd089a8SJim Harris
140cdd089a8SJim Harris static void
cache_read_after_write(void)1416ff6a270SChangpeng Liu cache_read_after_write(void)
14212e840b9SSeth Howell {
14312e840b9SSeth Howell uint64_t length;
14412e840b9SSeth Howell int rc;
1456ff6a270SChangpeng Liu char w_buf[100], r_buf[100];
146e9d400d5SBen Walker struct spdk_fs_thread_ctx *channel;
1476ff6a270SChangpeng Liu struct spdk_file_stat stat = {0};
14812e840b9SSeth Howell
14912e840b9SSeth Howell ut_send_request(_fs_init, NULL);
15012e840b9SSeth Howell
151e9d400d5SBen Walker channel = spdk_fs_alloc_thread_ctx(g_fs);
15212e840b9SSeth Howell
15312e840b9SSeth Howell rc = spdk_fs_open_file(g_fs, channel, "testfile", SPDK_BLOBFS_OPEN_CREATE, &g_file);
15412e840b9SSeth Howell CU_ASSERT(rc == 0);
15512e840b9SSeth Howell SPDK_CU_ASSERT_FATAL(g_file != NULL);
15612e840b9SSeth Howell
15712e840b9SSeth Howell length = (4 * 1024 * 1024);
158703d1f80SZiye Yang rc = spdk_file_truncate(g_file, channel, length);
159703d1f80SZiye Yang CU_ASSERT(rc == 0);
16012e840b9SSeth Howell
1616ff6a270SChangpeng Liu memset(w_buf, 0x5a, sizeof(w_buf));
1626ff6a270SChangpeng Liu spdk_file_write(g_file, channel, w_buf, 0, sizeof(w_buf));
16312e840b9SSeth Howell
16412e840b9SSeth Howell CU_ASSERT(spdk_file_get_length(g_file) == length);
16512e840b9SSeth Howell
1666ff6a270SChangpeng Liu rc = spdk_file_truncate(g_file, channel, sizeof(w_buf));
167703d1f80SZiye Yang CU_ASSERT(rc == 0);
16812e840b9SSeth Howell
16912e840b9SSeth Howell spdk_file_close(g_file, channel);
1706ff6a270SChangpeng Liu
171c41c4c2bSChangpeng Liu fs_thread_poll();
172c41c4c2bSChangpeng Liu
1736ff6a270SChangpeng Liu rc = spdk_fs_file_stat(g_fs, channel, "testfile", &stat);
1746ff6a270SChangpeng Liu CU_ASSERT(rc == 0);
1756ff6a270SChangpeng Liu CU_ASSERT(sizeof(w_buf) == stat.size);
1766ff6a270SChangpeng Liu
1776ff6a270SChangpeng Liu rc = spdk_fs_open_file(g_fs, channel, "testfile", 0, &g_file);
1786ff6a270SChangpeng Liu CU_ASSERT(rc == 0);
1796ff6a270SChangpeng Liu SPDK_CU_ASSERT_FATAL(g_file != NULL);
1806ff6a270SChangpeng Liu
1816ff6a270SChangpeng Liu memset(r_buf, 0, sizeof(r_buf));
1826ff6a270SChangpeng Liu spdk_file_read(g_file, channel, r_buf, 0, sizeof(r_buf));
1836ff6a270SChangpeng Liu CU_ASSERT(memcmp(w_buf, r_buf, sizeof(r_buf)) == 0);
1846ff6a270SChangpeng Liu
1856ff6a270SChangpeng Liu spdk_file_close(g_file, channel);
186c41c4c2bSChangpeng Liu
187c41c4c2bSChangpeng Liu fs_thread_poll();
188c41c4c2bSChangpeng Liu
18912e840b9SSeth Howell rc = spdk_fs_delete_file(g_fs, channel, "testfile");
19012e840b9SSeth Howell CU_ASSERT(rc == 0);
19112e840b9SSeth Howell
19212e840b9SSeth Howell rc = spdk_fs_delete_file(g_fs, channel, "testfile");
19312e840b9SSeth Howell CU_ASSERT(rc == -ENOENT);
19412e840b9SSeth Howell
195e9d400d5SBen Walker spdk_fs_free_thread_ctx(channel);
19612e840b9SSeth Howell
19712e840b9SSeth Howell ut_send_request(_fs_unload, NULL);
19812e840b9SSeth Howell }
19912e840b9SSeth Howell
20012e840b9SSeth Howell static void
file_length(void)201e967dcd2SJim Harris file_length(void)
202e967dcd2SJim Harris {
203e967dcd2SJim Harris int rc;
204e967dcd2SJim Harris char *buf;
205e967dcd2SJim Harris uint64_t buf_length;
2069c48768aSZiye Yang volatile uint64_t *length_flushed;
207e967dcd2SJim Harris struct spdk_fs_thread_ctx *channel;
208e967dcd2SJim Harris struct spdk_file_stat stat = {0};
209e967dcd2SJim Harris
210e967dcd2SJim Harris ut_send_request(_fs_init, NULL);
211e967dcd2SJim Harris
212e967dcd2SJim Harris channel = spdk_fs_alloc_thread_ctx(g_fs);
213e967dcd2SJim Harris
214e967dcd2SJim Harris g_file = NULL;
215e967dcd2SJim Harris rc = spdk_fs_open_file(g_fs, channel, "testfile", SPDK_BLOBFS_OPEN_CREATE, &g_file);
216e967dcd2SJim Harris CU_ASSERT(rc == 0);
217e967dcd2SJim Harris SPDK_CU_ASSERT_FATAL(g_file != NULL);
218e967dcd2SJim Harris
219cdd089a8SJim Harris /* Write one CACHE_BUFFER. Filling at least one cache buffer triggers
220cdd089a8SJim Harris * a flush to disk.
221e967dcd2SJim Harris */
222cdd089a8SJim Harris buf_length = CACHE_BUFFER_SIZE;
223e967dcd2SJim Harris buf = calloc(1, buf_length);
224e967dcd2SJim Harris spdk_file_write(g_file, channel, buf, 0, buf_length);
225e967dcd2SJim Harris free(buf);
226e967dcd2SJim Harris
227e967dcd2SJim Harris /* Spin until all of the data has been flushed to the SSD. There's been no
228e967dcd2SJim Harris * sync operation yet, so the xattr on the file is still 0.
2299c48768aSZiye Yang *
2309c48768aSZiye Yang * length_flushed: This variable is modified by a different thread in this unit
2319c48768aSZiye Yang * test. So we need to dereference it as a volatile to ensure the value is always
2329c48768aSZiye Yang * re-read.
233e967dcd2SJim Harris */
2349c48768aSZiye Yang length_flushed = &g_file->length_flushed;
2359c48768aSZiye Yang while (*length_flushed != buf_length) {}
236e967dcd2SJim Harris
237e967dcd2SJim Harris /* Close the file. This causes an implicit sync which should write the
238e967dcd2SJim Harris * length_flushed value as the "length" xattr on the file.
239e967dcd2SJim Harris */
240e967dcd2SJim Harris spdk_file_close(g_file, channel);
241e967dcd2SJim Harris
242c41c4c2bSChangpeng Liu fs_thread_poll();
243c41c4c2bSChangpeng Liu
244e967dcd2SJim Harris rc = spdk_fs_file_stat(g_fs, channel, "testfile", &stat);
245e967dcd2SJim Harris CU_ASSERT(rc == 0);
246e967dcd2SJim Harris CU_ASSERT(buf_length == stat.size);
247e967dcd2SJim Harris
248e967dcd2SJim Harris spdk_fs_free_thread_ctx(channel);
249e967dcd2SJim Harris
250e967dcd2SJim Harris /* Unload and reload the filesystem. The file length will be
251e967dcd2SJim Harris * read during load from the length xattr. We want to make sure
252e967dcd2SJim Harris * it matches what was written when the file was originally
253e967dcd2SJim Harris * written and closed.
254e967dcd2SJim Harris */
255e967dcd2SJim Harris ut_send_request(_fs_unload, NULL);
256e967dcd2SJim Harris
257e967dcd2SJim Harris ut_send_request(_fs_load, NULL);
258e967dcd2SJim Harris
259e967dcd2SJim Harris channel = spdk_fs_alloc_thread_ctx(g_fs);
260e967dcd2SJim Harris
261e967dcd2SJim Harris rc = spdk_fs_file_stat(g_fs, channel, "testfile", &stat);
262e967dcd2SJim Harris CU_ASSERT(rc == 0);
263e967dcd2SJim Harris CU_ASSERT(buf_length == stat.size);
264e967dcd2SJim Harris
265e967dcd2SJim Harris g_file = NULL;
266e967dcd2SJim Harris rc = spdk_fs_open_file(g_fs, channel, "testfile", 0, &g_file);
267e967dcd2SJim Harris CU_ASSERT(rc == 0);
268e967dcd2SJim Harris SPDK_CU_ASSERT_FATAL(g_file != NULL);
269e967dcd2SJim Harris
270e967dcd2SJim Harris spdk_file_close(g_file, channel);
271e967dcd2SJim Harris
272c41c4c2bSChangpeng Liu fs_thread_poll();
273c41c4c2bSChangpeng Liu
274e967dcd2SJim Harris rc = spdk_fs_delete_file(g_fs, channel, "testfile");
275e967dcd2SJim Harris CU_ASSERT(rc == 0);
276e967dcd2SJim Harris
277e967dcd2SJim Harris spdk_fs_free_thread_ctx(channel);
278e967dcd2SJim Harris
279e967dcd2SJim Harris ut_send_request(_fs_unload, NULL);
280e967dcd2SJim Harris }
281e967dcd2SJim Harris
282e967dcd2SJim Harris static void
append_write_to_extend_blob(void)283678c0261SChangpeng Liu append_write_to_extend_blob(void)
284678c0261SChangpeng Liu {
285678c0261SChangpeng Liu uint64_t blob_size, buf_length;
286678c0261SChangpeng Liu char *buf, append_buf[64];
287678c0261SChangpeng Liu int rc;
288678c0261SChangpeng Liu struct spdk_fs_thread_ctx *channel;
289678c0261SChangpeng Liu
290678c0261SChangpeng Liu ut_send_request(_fs_init, NULL);
291678c0261SChangpeng Liu
292678c0261SChangpeng Liu channel = spdk_fs_alloc_thread_ctx(g_fs);
293678c0261SChangpeng Liu
294678c0261SChangpeng Liu /* create a file and write the file with blob_size - 1 data length */
295678c0261SChangpeng Liu rc = spdk_fs_open_file(g_fs, channel, "testfile", SPDK_BLOBFS_OPEN_CREATE, &g_file);
296678c0261SChangpeng Liu CU_ASSERT(rc == 0);
297678c0261SChangpeng Liu SPDK_CU_ASSERT_FATAL(g_file != NULL);
298678c0261SChangpeng Liu
299678c0261SChangpeng Liu blob_size = __file_get_blob_size(g_file);
300678c0261SChangpeng Liu
301678c0261SChangpeng Liu buf_length = blob_size - 1;
302678c0261SChangpeng Liu buf = calloc(1, buf_length);
303678c0261SChangpeng Liu rc = spdk_file_write(g_file, channel, buf, 0, buf_length);
304678c0261SChangpeng Liu CU_ASSERT(rc == 0);
305678c0261SChangpeng Liu free(buf);
306678c0261SChangpeng Liu
307678c0261SChangpeng Liu spdk_file_close(g_file, channel);
308c41c4c2bSChangpeng Liu fs_thread_poll();
309678c0261SChangpeng Liu spdk_fs_free_thread_ctx(channel);
310678c0261SChangpeng Liu ut_send_request(_fs_unload, NULL);
311678c0261SChangpeng Liu
312678c0261SChangpeng Liu /* load existing file and write extra 2 bytes to cross blob boundary */
313678c0261SChangpeng Liu ut_send_request(_fs_load, NULL);
314678c0261SChangpeng Liu
315678c0261SChangpeng Liu channel = spdk_fs_alloc_thread_ctx(g_fs);
316678c0261SChangpeng Liu g_file = NULL;
317678c0261SChangpeng Liu rc = spdk_fs_open_file(g_fs, channel, "testfile", 0, &g_file);
318678c0261SChangpeng Liu CU_ASSERT(rc == 0);
319678c0261SChangpeng Liu SPDK_CU_ASSERT_FATAL(g_file != NULL);
320678c0261SChangpeng Liu
321678c0261SChangpeng Liu CU_ASSERT(g_file->length == buf_length);
322678c0261SChangpeng Liu CU_ASSERT(g_file->last == NULL);
323678c0261SChangpeng Liu CU_ASSERT(g_file->append_pos == buf_length);
324678c0261SChangpeng Liu
325678c0261SChangpeng Liu rc = spdk_file_write(g_file, channel, append_buf, buf_length, 2);
326678c0261SChangpeng Liu CU_ASSERT(rc == 0);
327678c0261SChangpeng Liu CU_ASSERT(2 * blob_size == __file_get_blob_size(g_file));
328678c0261SChangpeng Liu spdk_file_close(g_file, channel);
329c41c4c2bSChangpeng Liu fs_thread_poll();
330678c0261SChangpeng Liu CU_ASSERT(g_file->length == buf_length + 2);
331678c0261SChangpeng Liu
332678c0261SChangpeng Liu spdk_fs_free_thread_ctx(channel);
333678c0261SChangpeng Liu ut_send_request(_fs_unload, NULL);
334678c0261SChangpeng Liu }
335678c0261SChangpeng Liu
336678c0261SChangpeng Liu static void
partial_buffer(void)337cdd089a8SJim Harris partial_buffer(void)
338cdd089a8SJim Harris {
339cdd089a8SJim Harris int rc;
340cdd089a8SJim Harris char *buf;
341cdd089a8SJim Harris uint64_t buf_length;
342cdd089a8SJim Harris struct spdk_fs_thread_ctx *channel;
343cdd089a8SJim Harris struct spdk_file_stat stat = {0};
344cdd089a8SJim Harris
345cdd089a8SJim Harris ut_send_request(_fs_init, NULL);
346cdd089a8SJim Harris
347cdd089a8SJim Harris channel = spdk_fs_alloc_thread_ctx(g_fs);
348cdd089a8SJim Harris
349cdd089a8SJim Harris g_file = NULL;
350cdd089a8SJim Harris rc = spdk_fs_open_file(g_fs, channel, "testfile", SPDK_BLOBFS_OPEN_CREATE, &g_file);
351cdd089a8SJim Harris CU_ASSERT(rc == 0);
352cdd089a8SJim Harris SPDK_CU_ASSERT_FATAL(g_file != NULL);
353cdd089a8SJim Harris
354cdd089a8SJim Harris /* Write one CACHE_BUFFER plus one byte. Filling at least one cache buffer triggers
355cdd089a8SJim Harris * a flush to disk. We want to make sure the extra byte is not implicitly flushed.
356cdd089a8SJim Harris * It should only get flushed once we sync or close the file.
357cdd089a8SJim Harris */
358cdd089a8SJim Harris buf_length = CACHE_BUFFER_SIZE + 1;
359cdd089a8SJim Harris buf = calloc(1, buf_length);
360cdd089a8SJim Harris spdk_file_write(g_file, channel, buf, 0, buf_length);
361cdd089a8SJim Harris free(buf);
362cdd089a8SJim Harris
363cdd089a8SJim Harris /* Send some nop messages to the dispatch thread. This will ensure any of the
364cdd089a8SJim Harris * pending write operations are completed. A well-functioning blobfs should only
365cdd089a8SJim Harris * issue one write for the filled CACHE_BUFFER - a buggy one might try to write
366cdd089a8SJim Harris * the extra byte. So do a bunch of _nops to make sure all of them (even the buggy
367cdd089a8SJim Harris * ones) get a chance to run. Note that we can't just send a message to the
368cdd089a8SJim Harris * dispatch thread to call spdk_thread_poll() because the messages are themselves
369cdd089a8SJim Harris * run in the context of spdk_thread_poll().
370cdd089a8SJim Harris */
371cdd089a8SJim Harris ut_send_request(_nop, NULL);
372cdd089a8SJim Harris ut_send_request(_nop, NULL);
373cdd089a8SJim Harris ut_send_request(_nop, NULL);
374cdd089a8SJim Harris ut_send_request(_nop, NULL);
375cdd089a8SJim Harris ut_send_request(_nop, NULL);
376cdd089a8SJim Harris ut_send_request(_nop, NULL);
377cdd089a8SJim Harris
378cdd089a8SJim Harris CU_ASSERT(g_file->length_flushed == CACHE_BUFFER_SIZE);
379cdd089a8SJim Harris
380cdd089a8SJim Harris /* Close the file. This causes an implicit sync which should write the
381cdd089a8SJim Harris * length_flushed value as the "length" xattr on the file.
382cdd089a8SJim Harris */
383cdd089a8SJim Harris spdk_file_close(g_file, channel);
384cdd089a8SJim Harris
385c41c4c2bSChangpeng Liu fs_thread_poll();
386c41c4c2bSChangpeng Liu
387cdd089a8SJim Harris rc = spdk_fs_file_stat(g_fs, channel, "testfile", &stat);
388cdd089a8SJim Harris CU_ASSERT(rc == 0);
389cdd089a8SJim Harris CU_ASSERT(buf_length == stat.size);
390cdd089a8SJim Harris
391cdd089a8SJim Harris rc = spdk_fs_delete_file(g_fs, channel, "testfile");
392cdd089a8SJim Harris CU_ASSERT(rc == 0);
393cdd089a8SJim Harris
394cdd089a8SJim Harris spdk_fs_free_thread_ctx(channel);
395cdd089a8SJim Harris
396cdd089a8SJim Harris ut_send_request(_fs_unload, NULL);
397cdd089a8SJim Harris }
398cdd089a8SJim Harris
399cdd089a8SJim Harris static void
cache_write_null_buffer(void)40012e840b9SSeth Howell cache_write_null_buffer(void)
40112e840b9SSeth Howell {
40212e840b9SSeth Howell uint64_t length;
40312e840b9SSeth Howell int rc;
404e9d400d5SBen Walker struct spdk_fs_thread_ctx *channel;
40511654a60SBen Walker struct spdk_thread *thread;
40612e840b9SSeth Howell
40712e840b9SSeth Howell ut_send_request(_fs_init, NULL);
40812e840b9SSeth Howell
409e9d400d5SBen Walker channel = spdk_fs_alloc_thread_ctx(g_fs);
41012e840b9SSeth Howell
41112e840b9SSeth Howell rc = spdk_fs_open_file(g_fs, channel, "testfile", SPDK_BLOBFS_OPEN_CREATE, &g_file);
41212e840b9SSeth Howell CU_ASSERT(rc == 0);
41312e840b9SSeth Howell SPDK_CU_ASSERT_FATAL(g_file != NULL);
41412e840b9SSeth Howell
41512e840b9SSeth Howell length = 0;
416703d1f80SZiye Yang rc = spdk_file_truncate(g_file, channel, length);
417703d1f80SZiye Yang CU_ASSERT(rc == 0);
41812e840b9SSeth Howell
41912e840b9SSeth Howell rc = spdk_file_write(g_file, channel, NULL, 0, 0);
42012e840b9SSeth Howell CU_ASSERT(rc == 0);
42112e840b9SSeth Howell
42212e840b9SSeth Howell spdk_file_close(g_file, channel);
423c41c4c2bSChangpeng Liu
424c41c4c2bSChangpeng Liu fs_thread_poll();
425c41c4c2bSChangpeng Liu
42612e840b9SSeth Howell rc = spdk_fs_delete_file(g_fs, channel, "testfile");
42712e840b9SSeth Howell CU_ASSERT(rc == 0);
42812e840b9SSeth Howell
429e9d400d5SBen Walker spdk_fs_free_thread_ctx(channel);
43012e840b9SSeth Howell
43111654a60SBen Walker thread = spdk_get_thread();
4328abfb06eSBen Walker while (spdk_thread_poll(thread, 0, 0) > 0) {}
43311654a60SBen Walker
43412e840b9SSeth Howell ut_send_request(_fs_unload, NULL);
43512e840b9SSeth Howell }
43612e840b9SSeth Howell
43712e840b9SSeth Howell static void
fs_create_sync(void)43812e840b9SSeth Howell fs_create_sync(void)
43912e840b9SSeth Howell {
44012e840b9SSeth Howell int rc;
441e9d400d5SBen Walker struct spdk_fs_thread_ctx *channel;
44212e840b9SSeth Howell
44312e840b9SSeth Howell ut_send_request(_fs_init, NULL);
44412e840b9SSeth Howell
445e9d400d5SBen Walker channel = spdk_fs_alloc_thread_ctx(g_fs);
44612e840b9SSeth Howell CU_ASSERT(channel != NULL);
44712e840b9SSeth Howell
44812e840b9SSeth Howell rc = spdk_fs_create_file(g_fs, channel, "testfile");
44912e840b9SSeth Howell CU_ASSERT(rc == 0);
45012e840b9SSeth Howell
45112e840b9SSeth Howell /* Create should fail, because the file already exists. */
45212e840b9SSeth Howell rc = spdk_fs_create_file(g_fs, channel, "testfile");
45312e840b9SSeth Howell CU_ASSERT(rc != 0);
45412e840b9SSeth Howell
45512e840b9SSeth Howell rc = spdk_fs_delete_file(g_fs, channel, "testfile");
45612e840b9SSeth Howell CU_ASSERT(rc == 0);
45712e840b9SSeth Howell
458e9d400d5SBen Walker spdk_fs_free_thread_ctx(channel);
45912e840b9SSeth Howell
460c41c4c2bSChangpeng Liu fs_thread_poll();
46111654a60SBen Walker
46212e840b9SSeth Howell ut_send_request(_fs_unload, NULL);
46312e840b9SSeth Howell }
46412e840b9SSeth Howell
46512e840b9SSeth Howell static void
fs_rename_sync(void)46698ef63aaSChangpeng Liu fs_rename_sync(void)
46798ef63aaSChangpeng Liu {
46898ef63aaSChangpeng Liu int rc;
46998ef63aaSChangpeng Liu struct spdk_fs_thread_ctx *channel;
47098ef63aaSChangpeng Liu
47198ef63aaSChangpeng Liu ut_send_request(_fs_init, NULL);
47298ef63aaSChangpeng Liu
47398ef63aaSChangpeng Liu channel = spdk_fs_alloc_thread_ctx(g_fs);
47498ef63aaSChangpeng Liu CU_ASSERT(channel != NULL);
47598ef63aaSChangpeng Liu
47698ef63aaSChangpeng Liu rc = spdk_fs_open_file(g_fs, channel, "testfile", SPDK_BLOBFS_OPEN_CREATE, &g_file);
47798ef63aaSChangpeng Liu CU_ASSERT(rc == 0);
47898ef63aaSChangpeng Liu SPDK_CU_ASSERT_FATAL(g_file != NULL);
47998ef63aaSChangpeng Liu
48098ef63aaSChangpeng Liu CU_ASSERT(strcmp(spdk_file_get_name(g_file), "testfile") == 0);
48198ef63aaSChangpeng Liu
48298ef63aaSChangpeng Liu rc = spdk_fs_rename_file(g_fs, channel, "testfile", "newtestfile");
48398ef63aaSChangpeng Liu CU_ASSERT(rc == 0);
48498ef63aaSChangpeng Liu CU_ASSERT(strcmp(spdk_file_get_name(g_file), "newtestfile") == 0);
48598ef63aaSChangpeng Liu
48698ef63aaSChangpeng Liu spdk_file_close(g_file, channel);
48798ef63aaSChangpeng Liu
488c41c4c2bSChangpeng Liu fs_thread_poll();
489c41c4c2bSChangpeng Liu
490c41c4c2bSChangpeng Liu spdk_fs_free_thread_ctx(channel);
49198ef63aaSChangpeng Liu
49298ef63aaSChangpeng Liu ut_send_request(_fs_unload, NULL);
49398ef63aaSChangpeng Liu }
49498ef63aaSChangpeng Liu
49598ef63aaSChangpeng Liu static void
cache_append_no_cache(void)49612e840b9SSeth Howell cache_append_no_cache(void)
49712e840b9SSeth Howell {
49812e840b9SSeth Howell int rc;
49912e840b9SSeth Howell char buf[100];
500e9d400d5SBen Walker struct spdk_fs_thread_ctx *channel;
50112e840b9SSeth Howell
50212e840b9SSeth Howell ut_send_request(_fs_init, NULL);
50312e840b9SSeth Howell
504e9d400d5SBen Walker channel = spdk_fs_alloc_thread_ctx(g_fs);
50512e840b9SSeth Howell
50612e840b9SSeth Howell rc = spdk_fs_open_file(g_fs, channel, "testfile", SPDK_BLOBFS_OPEN_CREATE, &g_file);
50712e840b9SSeth Howell CU_ASSERT(rc == 0);
50812e840b9SSeth Howell SPDK_CU_ASSERT_FATAL(g_file != NULL);
50912e840b9SSeth Howell
51012e840b9SSeth Howell spdk_file_write(g_file, channel, buf, 0 * sizeof(buf), sizeof(buf));
51112e840b9SSeth Howell CU_ASSERT(spdk_file_get_length(g_file) == 1 * sizeof(buf));
51212e840b9SSeth Howell spdk_file_write(g_file, channel, buf, 1 * sizeof(buf), sizeof(buf));
51312e840b9SSeth Howell CU_ASSERT(spdk_file_get_length(g_file) == 2 * sizeof(buf));
51412e840b9SSeth Howell spdk_file_sync(g_file, channel);
515c41c4c2bSChangpeng Liu
516c41c4c2bSChangpeng Liu fs_thread_poll();
517c41c4c2bSChangpeng Liu
51812e840b9SSeth Howell spdk_file_write(g_file, channel, buf, 2 * sizeof(buf), sizeof(buf));
51912e840b9SSeth Howell CU_ASSERT(spdk_file_get_length(g_file) == 3 * sizeof(buf));
52012e840b9SSeth Howell spdk_file_write(g_file, channel, buf, 3 * sizeof(buf), sizeof(buf));
52112e840b9SSeth Howell CU_ASSERT(spdk_file_get_length(g_file) == 4 * sizeof(buf));
52212e840b9SSeth Howell spdk_file_write(g_file, channel, buf, 4 * sizeof(buf), sizeof(buf));
52312e840b9SSeth Howell CU_ASSERT(spdk_file_get_length(g_file) == 5 * sizeof(buf));
52412e840b9SSeth Howell
52512e840b9SSeth Howell spdk_file_close(g_file, channel);
526c41c4c2bSChangpeng Liu
527c41c4c2bSChangpeng Liu fs_thread_poll();
528c41c4c2bSChangpeng Liu
52912e840b9SSeth Howell rc = spdk_fs_delete_file(g_fs, channel, "testfile");
53012e840b9SSeth Howell CU_ASSERT(rc == 0);
53112e840b9SSeth Howell
532e9d400d5SBen Walker spdk_fs_free_thread_ctx(channel);
53312e840b9SSeth Howell
53412e840b9SSeth Howell ut_send_request(_fs_unload, NULL);
53512e840b9SSeth Howell }
53612e840b9SSeth Howell
53712e840b9SSeth Howell static void
fs_delete_file_without_close(void)53812e840b9SSeth Howell fs_delete_file_without_close(void)
53912e840b9SSeth Howell {
54012e840b9SSeth Howell int rc;
541e9d400d5SBen Walker struct spdk_fs_thread_ctx *channel;
54212e840b9SSeth Howell struct spdk_file *file;
54312e840b9SSeth Howell
54412e840b9SSeth Howell ut_send_request(_fs_init, NULL);
545e9d400d5SBen Walker channel = spdk_fs_alloc_thread_ctx(g_fs);
54612e840b9SSeth Howell CU_ASSERT(channel != NULL);
54712e840b9SSeth Howell
54812e840b9SSeth Howell rc = spdk_fs_open_file(g_fs, channel, "testfile", SPDK_BLOBFS_OPEN_CREATE, &g_file);
54912e840b9SSeth Howell CU_ASSERT(rc == 0);
550438b71d1SSeth Howell SPDK_CU_ASSERT_FATAL(g_file != NULL);
55112e840b9SSeth Howell
55212e840b9SSeth Howell rc = spdk_fs_delete_file(g_fs, channel, "testfile");
55312e840b9SSeth Howell CU_ASSERT(rc == 0);
55412e840b9SSeth Howell CU_ASSERT(g_file->ref_count != 0);
55512e840b9SSeth Howell CU_ASSERT(g_file->is_deleted == true);
55612e840b9SSeth Howell
55712e840b9SSeth Howell rc = spdk_fs_open_file(g_fs, channel, "testfile", 0, &file);
55812e840b9SSeth Howell CU_ASSERT(rc != 0);
55912e840b9SSeth Howell
56012e840b9SSeth Howell spdk_file_close(g_file, channel);
56112e840b9SSeth Howell
562c41c4c2bSChangpeng Liu fs_thread_poll();
563c41c4c2bSChangpeng Liu
56412e840b9SSeth Howell rc = spdk_fs_open_file(g_fs, channel, "testfile", 0, &file);
56512e840b9SSeth Howell CU_ASSERT(rc != 0);
56612e840b9SSeth Howell
567e9d400d5SBen Walker spdk_fs_free_thread_ctx(channel);
56812e840b9SSeth Howell
56912e840b9SSeth Howell ut_send_request(_fs_unload, NULL);
57012e840b9SSeth Howell
57112e840b9SSeth Howell }
57212e840b9SSeth Howell
573088c5e04SBen Walker static bool g_thread_exit = false;
574088c5e04SBen Walker
57512e840b9SSeth Howell static void
terminate_spdk_thread(void * arg)57612e840b9SSeth Howell terminate_spdk_thread(void *arg)
57712e840b9SSeth Howell {
578088c5e04SBen Walker g_thread_exit = true;
57912e840b9SSeth Howell }
58012e840b9SSeth Howell
58112e840b9SSeth Howell static void *
spdk_thread(void * arg)58212e840b9SSeth Howell spdk_thread(void *arg)
58312e840b9SSeth Howell {
584088c5e04SBen Walker struct spdk_thread *thread = arg;
58512e840b9SSeth Howell
586605e530aSBen Walker spdk_set_thread(thread);
58712e840b9SSeth Howell
588088c5e04SBen Walker while (!g_thread_exit) {
5898abfb06eSBen Walker spdk_thread_poll(thread, 0, 0);
59012e840b9SSeth Howell }
59112e840b9SSeth Howell
59212e840b9SSeth Howell return NULL;
59312e840b9SSeth Howell }
59412e840b9SSeth Howell
5958dd1cd21SBen Walker int
main(int argc,char ** argv)5968dd1cd21SBen Walker main(int argc, char **argv)
59712e840b9SSeth Howell {
598605e530aSBen Walker struct spdk_thread *thread;
59912e840b9SSeth Howell CU_pSuite suite = NULL;
60012e840b9SSeth Howell pthread_t spdk_tid;
60112e840b9SSeth Howell unsigned int num_failures;
60212e840b9SSeth Howell
60378b696bcSVitaliy Mysak CU_initialize_registry();
60412e840b9SSeth Howell
60512e840b9SSeth Howell suite = CU_add_suite("blobfs_sync_ut", NULL, NULL);
60612e840b9SSeth Howell
607dcf0ca15SVitaliy Mysak CU_ADD_TEST(suite, cache_read_after_write);
608dcf0ca15SVitaliy Mysak CU_ADD_TEST(suite, file_length);
609dcf0ca15SVitaliy Mysak CU_ADD_TEST(suite, append_write_to_extend_blob);
610dcf0ca15SVitaliy Mysak CU_ADD_TEST(suite, partial_buffer);
611dcf0ca15SVitaliy Mysak CU_ADD_TEST(suite, cache_write_null_buffer);
612dcf0ca15SVitaliy Mysak CU_ADD_TEST(suite, fs_create_sync);
613dcf0ca15SVitaliy Mysak CU_ADD_TEST(suite, fs_rename_sync);
614dcf0ca15SVitaliy Mysak CU_ADD_TEST(suite, cache_append_no_cache);
615dcf0ca15SVitaliy Mysak CU_ADD_TEST(suite, fs_delete_file_without_close);
61612e840b9SSeth Howell
617088c5e04SBen Walker spdk_thread_lib_init(NULL, 0);
618088c5e04SBen Walker
6195d0b5e2cSBen Walker thread = spdk_thread_create("test_thread", NULL);
620605e530aSBen Walker spdk_set_thread(thread);
6217f6068f0SBen Walker
6225d0b5e2cSBen Walker g_dispatch_thread = spdk_thread_create("dispatch_thread", NULL);
623088c5e04SBen Walker pthread_create(&spdk_tid, NULL, spdk_thread, g_dispatch_thread);
624088c5e04SBen Walker
62512e840b9SSeth Howell g_dev_buffer = calloc(1, DEV_BUFFER_SIZE);
626088c5e04SBen Walker
627*ea941caeSKonrad Sztyber num_failures = spdk_ut_run_tests(argc, argv, NULL);
62812e840b9SSeth Howell CU_cleanup_registry();
629088c5e04SBen Walker
63012e840b9SSeth Howell free(g_dev_buffer);
631088c5e04SBen Walker
632088c5e04SBen Walker ut_send_request(terminate_spdk_thread, NULL);
63312e840b9SSeth Howell pthread_join(spdk_tid, NULL);
634088c5e04SBen Walker
635088c5e04SBen Walker while (spdk_thread_poll(g_dispatch_thread, 0, 0) > 0) {}
636088c5e04SBen Walker while (spdk_thread_poll(thread, 0, 0) > 0) {}
637088c5e04SBen Walker
638e036215fSBen Walker spdk_set_thread(thread);
6399cba82b9SBen Walker spdk_thread_exit(thread);
640e7ead00bSShuhei Matsumoto while (!spdk_thread_is_exited(thread)) {
641e7ead00bSShuhei Matsumoto spdk_thread_poll(thread, 0, 0);
642e7ead00bSShuhei Matsumoto }
643e036215fSBen Walker spdk_thread_destroy(thread);
644e036215fSBen Walker
645e036215fSBen Walker spdk_set_thread(g_dispatch_thread);
646088c5e04SBen Walker spdk_thread_exit(g_dispatch_thread);
647e7ead00bSShuhei Matsumoto while (!spdk_thread_is_exited(g_dispatch_thread)) {
648e7ead00bSShuhei Matsumoto spdk_thread_poll(g_dispatch_thread, 0, 0);
649e7ead00bSShuhei Matsumoto }
650e036215fSBen Walker spdk_thread_destroy(g_dispatch_thread);
651088c5e04SBen Walker
652088c5e04SBen Walker spdk_thread_lib_fini();
653088c5e04SBen Walker
65412e840b9SSeth Howell return num_failures;
65512e840b9SSeth Howell }
656