]> git.proxmox.com Git - ceph.git/blob - ceph/src/seastar/src/core/fsqual.cc
update source to Ceph Pacific 16.2.2
[ceph.git] / ceph / src / seastar / src / core / fsqual.cc
1 /*
2 * Copyright 2016 ScyllaDB
3 */
4 /*
5 * This file is open source software, licensed to you under the terms
6 * of the Apache License, Version 2.0 (the "License"). See the NOTICE file
7 * distributed with this work for additional information regarding copyright
8 * ownership. You may not use this file except in compliance with the License.
9 *
10 * You may obtain a copy of the License at
11 *
12 * http://www.apache.org/licenses/LICENSE-2.0
13 *
14 * Unless required by applicable law or agreed to in writing,
15 * software distributed under the License is distributed on an
16 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17 * KIND, either express or implied. See the License for the
18 * specific language governing permissions and limitations
19 * under the License.
20 */
21
22 #include <seastar/core/posix.hh>
23 #include <seastar/util/defer.hh>
24 #include <seastar/core/linux-aio.hh>
25 #include <sys/time.h>
26 #include <sys/resource.h>
27 #include <fcntl.h>
28 #include <iostream>
29 #include <unistd.h>
30 #include <cstdlib>
31 #include <type_traits>
32 #include <seastar/core/fsqual.hh>
33
34 namespace seastar {
35
36 using namespace seastar::internal;
37 using namespace seastar::internal::linux_abi;
38
39 // Runs func(), and also adds the number of context switches
40 // that happened during func() to counter.
41 template <typename Counter, typename Func>
42 typename std::result_of<Func()>::type
43 with_ctxsw_counting(Counter& counter, Func&& func) {
44 struct count_guard {
45 Counter& counter;
46 count_guard(Counter& counter) : counter(counter) {
47 counter -= nvcsw();
48 }
49 ~count_guard() {
50 counter += nvcsw();
51 }
52 static Counter nvcsw() {
53 struct rusage usage;
54 getrusage(RUSAGE_THREAD, &usage);
55 return usage.ru_nvcsw;
56 }
57 };
58 count_guard g(counter);
59 return func();
60 }
61
62 bool filesystem_has_good_aio_support(sstring directory, bool verbose) {
63 aio_context_t ioctx = {};
64 auto r = io_setup(1, &ioctx);
65 throw_system_error_on(r == -1, "io_setup");
66 auto cleanup = defer([&] { io_destroy(ioctx); });
67 auto fname = directory + "/fsqual.tmp";
68 auto fd = file_desc::open(fname, O_CREAT|O_EXCL|O_RDWR|O_DIRECT, 0600);
69 unlink(fname.c_str());
70 auto nr = 1000;
71 fd.truncate(nr * 4096);
72 auto bufsize = 4096;
73 auto ctxsw = 0;
74 auto buf = aligned_alloc(4096, 4096);
75 for (int i = 0; i < nr; ++i) {
76 struct iocb cmd;
77 cmd = make_write_iocb(fd.get(), bufsize*i, buf, bufsize);
78 struct iocb* cmds[1] = { &cmd };
79 with_ctxsw_counting(ctxsw, [&] {
80 auto r = io_submit(ioctx, 1, cmds);
81 throw_system_error_on(r == -1, "io_submit");
82 assert(r == 1);
83 });
84 struct io_event ioev;
85 int n = -1;
86 do {
87 n = io_getevents(ioctx, 1, 1, &ioev, nullptr);
88 throw_system_error_on((n == -1) && (errno != EINTR) , "io_getevents");
89 } while (n == -1);
90 assert(n == 1);
91 throw_kernel_error(long(ioev.res));
92 assert(long(ioev.res) == bufsize);
93 }
94 auto rate = float(ctxsw) / nr;
95 bool ok = rate < 0.1;
96 if (verbose) {
97 auto verdict = ok ? "GOOD" : "BAD";
98 std::cout << "context switch per appending io: " << rate
99 << " (" << verdict << ")\n";
100 }
101 return ok;
102 }
103
104 }